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
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.nedhassendRedirects = default(true), so this is the out-of-the-box behavior of everyMobile IPv6 scenario using bidirectional tunneling; a modeller has to know to set
sendRedirects = falseto suppress it.How to reproduce
In the stock example, no branch or showcase needed:
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:
2001:db8:0:2:8aa:ff:fe00:bis the mobile node's home address; it is away from home.Verified on
1869032b71. The code below is byte-identical at021485b99c, so the defect ispresent unchanged on current master.
What the standard says
RFC 4861 Section 8.2:
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 neighborcondition by comparing the output interface with the arrival interface:
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 theouter datagram on when it re-injects the decapsulated inner one:
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
InterfaceIndtag mustkeep naming the physical interface, because upper layers read it to find the link the datagram
came in on --
Mipv6::processHoTMessage()looks up that interface'sMipv6InterfaceData, whicha 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 arrivalinterface's
Ipv6InterfaceDatafor its group-membership test and matches the interface againstthe multicast route's incoming interface, and a tunnel interface has neither -- while Redirects
are never sent for multicast anyway.
Related