Skip to content

ipv6: a home agent sends a spurious ICMPv6 Redirect for every reverse-tunneled datagram it forwards #1197

Description

@adamgeorge309

What happens

A home agent that decapsulates a reverse-tunneled datagram and forwards the inner one back out
of the interface the outer datagram arrived on sends an ICMPv6 Redirect for it. The Redirect is
addressed to the mobile node's home address -- a node that is not on that link at all, and that
the home agent itself then has to tunnel the Redirect to.

Ipv6.ned has sendRedirects = default(true), so this is the out-of-the-box behavior of every
Mobile IPv6 scenario using bidirectional tunneling; a modeller has to know to set
sendRedirects = false to suppress it.

How to reproduce

In the stock example, no branch or showcase needed:

cd examples/ipv6/mipv6roaming
opp_run -r 0 -m -u Cmdenv -c Roaming -n ../..:../../../src -l ../../../src/INET \
    --cmdenv-express-mode=false --cmdenv-log-prefix="%t %C: " omnetpp.ini | grep Redirect

Two Redirects are sent, at t = 25.502306 s and t = 25.508414 s -- one for each of the two
reverse-tunneled datagrams the home agent forwards in the run. The log around the first:

Home_Agent.ipv6.ipv6: local delivery
Home_Agent.ipv6.ipv6: Tunnelled IP datagram
Home_Agent.ipv6.ipv6: Routing datagram `' with dest=2001:db8:0:7:8aa:ff:fe00:c, ...
Home_Agent.ipv6.neighbourDiscovery: Sending ICMPv6 Redirect to 2001:db8:0:2:8aa:ff:fe00:b:
    use fe80::8aa:ff:fe00:7 as next hop for 2001:db8:0:7:8aa:ff:fe00:c

2001:db8:0:2:8aa:ff:fe00:b is the mobile node's home address; it is away from home.

Verified on 1869032b71. The code below is byte-identical at 021485b99c, so the defect is
present unchanged on current master.

What the standard says

RFC 4861 Section 8.2:

A router SHOULD send a redirect message, subject to rate limiting, whenever it forwards a
packet that is not explicitly addressed to itself [...] in which:

  • the Source Address field of the packet identifies a neighbor, and

  • the router determines [...] that a better first-hop node resides on the same link as the
    sending node for the Destination Address of the packet being forwarded, and

  • the Destination Address of the packet is not a multicast address.

The first condition fails here. The datagram did not arrive on a link: it arrived through a
tunnel, which RFC 2473 Section 3 models as a link of its own, and its source -- the mobile
node's home address -- is not a neighbor on the physical interface the outer datagram came in
on. There is no "better first hop on the same link as the sending node", because the sending
node is not on that link.

Cause

Ipv6::routePacket() (src/inet/networklayer/ipv6/Ipv6.cc:532) approximates the neighbor
condition by comparing the output interface with the arrival interface:

if (sendRedirects && rt->isRouter() && !fromHL && fromIE && interfaceId == fromIE->getInterfaceId()) {

That is sound for a datagram that really arrived on a link. But Ipv6::localDeliverFinish()
(src/inet/networklayer/ipv6/Ipv6.cc:846-854) passes the physical arrival interface of the
outer datagram on when it re-injects the decapsulated inner one:

packet->removeTagIfPresent<InterfaceReq>();
auto verdict = datagramPreRoutingHook(packet);
if (verdict == INetfilter::IHook::ACCEPT)
    preroutingFinish(packet, fromIE, nullptr, Ipv6Address::UNSPECIFIED_ADDRESS);

so the comparison matches and the Redirect goes out.

Suggested fix

Attribute the decapsulated datagram's routing decision to the tunnel interface rather than to
the physical arrival interface. The tunnel interface can be found from the outer header: its
entry point is the outer destination and its exit point the outer source.

Note two limits. Only the routing decision should be re-attributed: the InterfaceInd tag must
keep naming the physical interface, because upper layers read it to find the link the datagram
came in on -- Mipv6::processHoTMessage() looks up that interface's Mipv6InterfaceData, which
a tunnel interface does not carry, and re-tagging it throws "Tag 'inet::Mipv6InterfaceData' is
absent". And only unicast should be re-attributed: routeMulticastPacket() reads the arrival
interface's Ipv6InterfaceData for its group-membership test and matches the interface against
the multicast route's incoming interface, and a tunnel interface has neither -- while Redirects
are never sent for multicast anyway.

Related

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions