Skip to content

ipv6, mipv6: fix two defects on the Mobile IPv6 reverse-tunneled path - #1247

Open
adamgeorge309 wants to merge 3 commits into
masterfrom
topic/gy/mipv6-forwarding-path
Open

adamgeorge309 wants to merge 3 commits into
masterfrom
topic/gy/mipv6-forwarding-path

Conversation

@adamgeorge309

@adamgeorge309 adamgeorge309 commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Two defects on the reverse-tunneled path of Mobile IPv6 (MIPv6), the mobility support of Internet Protocol version 6 (IPv6), both visible in examples/ipv6/mipv6roaming on master at 49e1fa0 (the merge base). The home agent sent an Internet Control Message Protocol for IPv6 (ICMPv6) Redirect for each reverse-tunneled datagram it forwarded (#1197). The mobile node discarded the packets it sourced from its home address while its home registration was in flight (#1198). The two fixes belong together because the fix for #1198 alone makes #1197 worse. It releases the held datagrams through the reverse tunnel, and without the fix for #1197 the home agent redirects those too: 3 Redirects in examples/ipv6/mipv6roaming instead of 2 on master.

Closes #1197
Closes #1198

The problem

examples/ipv6/mipv6roaming -c Roaming, release build:

event t (s) node master at 49e1fa0 (the merge base) this branch
Home Test Init and echo reply sourced from the home address 22.503 mobile node 2 discarded ("Using HoA instead of CoA... dropping datagram"; HoA is the home address, CoA the care-of address) held, sent through the reverse tunnel once it exists
echo reply sourced from the home address 23.001 mobile node 1 discarded held, then sent
Redirect for a decapsulated reverse-tunneled datagram 23.502, 23.505 home agent 2 sent, addressed to the mobile node's home address none

The issues were measured on 1869032b71, where the same events happen about 2 s later.

The commits

  1. ipv6: add: find a tunnel interface by its endpoints. Ipv6RoutingTable::findTunnelNetworkInterface() returns the Ipv6TunnelInterface configured with a given entry and exit point, and Ipv6Tunnel exposes its two endpoints for it. The commit is generic tunnel plumbing with no caller yet, and no fingerprint moves.
  2. ipv6: fix: route a decapsulated datagram as arriving from the tunnel (ipv6: a home agent sends a spurious ICMPv6 Redirect for every reverse-tunneled datagram it forwards #1197). Request for Comments (RFC) 4861 Section 8.2 allows a Redirect only when "the Source Address field of the packet identifies a neighbor". Ipv6::routePacket() approximates that condition by comparing the output interface with the arrival interface. Ipv6::localDeliverFinish() passed a decapsulated datagram on with the physical arrival interface of the outer datagram. RFC 2473 Section 3 models the tunnel as a link of its own. The datagram is now routed as arriving on the tunnel interface, found from the outer addresses. This is limited to unicast and to the routing decision: the InterfaceInd tag still names the physical interface, which Mipv6 reads. For the same reason, a pre-routing hook that returns QUEUE for a decapsulated datagram loses the tunnel attribution, because reinjectQueuedDatagram() recovers the arrival interface from that tag.
  3. mipv6: fix: hold home-address traffic until the reverse tunnel exists (mipv6: a mobile node discards its home-address-sourced packets while its home registration is in flight #1198). RFC 6275 Section 11.3.1 requires reverse tunneling when there is no binding at the correspondent node. The mobile node creates its reverse tunnel when the Binding Acknowledgement arrives, but the home agent starts tunneling as soon as it accepts the Binding Update. Mipv6::datagramLocalOutHook() now returns QUEUE for a home-address-sourced datagram in that window. When the Binding Acknowledgement creates the tunnel, processBAMessage() calls releaseHeldDatagrams(), which reinjects the held datagrams onto it. The hold is bounded: it applies only while a Binding Update is unacknowledged, and it holds at most 100 datagrams per home agent, dropping the oldest beyond that. Held datagrams are dropped, with a packetDropped signal, when the binding update list entry expires or the registration is torn down. A held Home Test Init is not retransmitted: its timer would otherwise fire while it waits, and both copies would be released together and run return routability twice. releaseHeldDatagrams() restarts the timer from the initial interval when it sends the held message. RFC 6275 Section 11.8 calls for a retransmission "if the mobile node fails to receive a valid matching response within the selected initial retransmission interval", and a held message has not been sent.

Relationship to #1236

Pull request #1236 (topic/gy/ipv6-redirect) adds the Request for Comments (RFC) 4861 Section 8.2 check that the source is a neighbor. That check also stops the Internet Control Message Protocol for IPv6 (ICMPv6) Redirects of #1197, and #1236 does not close #1197. The two fixes are independent and touch different functions of Ipv6.cc (routePacket() there, localDeliverFinish() here), so the C++ source merges without conflict. WHATSNEW conflicts on the item numbers, and the two comma-separated values (CSV) baseline files conflict on the rows below. On master alone, commit 2 removes the Redirects and changes the arrival interface of the decapsulated datagram. MIPv6_no_redirect_for_tunneled_traffic.test checks the interface through the new log line Routing the decapsulated datagram as arriving on ip6tun1 at Home_Agent (the test matches the ip6tun prefix). For unicast, routePacket() reads the arrival interface only in the Redirect check. So with #1236 applied, both fixes remove the same Redirects in the shipped examples, and the log line is the only difference there. In the code the two fixes differ when a decapsulated datagram's inner source is on-link on the physical arrival interface. #1236 would still redirect such a datagram, and this pull request does not. No shipped example has that case.

Both pull requests re-record the same six MIPv6 fingerprint rows: examples/ipv6/mipv6 Handover and RouteOptimizationTwoCNs and examples/ipv6/mipv6roaming Roaming, each in examples.csv and mipv6-refactoring.csv. Whichever lands second re-records them.

Architectural surface

  • Public C++ interface: new Ipv6RoutingTable::findTunnelNetworkInterface() (virtual) and Ipv6Tunnel::getSource() / getDestination().
  • Behavior of Ipv6: the arrival interface used for the routing decision of a decapsulated unicast datagram. The InterfaceInd tag is unchanged.
  • Behavior of Mipv6: the local-out hook returns QUEUE in the case above, held datagrams dropped on overflow or registration end are reported with packetDropped, and a Home Test Init is not retransmitted while it is held.
  • Eight protected, non-virtual helpers and three members added to the INET_API class Mipv6 (commit 3); no new virtual function. Mipv6.h now includes Simsignals_m.h. The cap of 100 held datagrams per home agent is a compile-time constant, not a Network Description (NED) parameter.
  • New C++ dependency: networklayer/ipv6/Ipv6RoutingTable.cc includes networklayer/ipv6tunneling/Ipv6Tunnel.h (commit 1). Both directories belong to the Ipv6 feature in .oppfeatures.
  • INetfilter queue contract: Mipv6 keeps the datagrams it queued as borrowed pointers and hands them back through reinjectQueuedDatagram() or dropQueuedDatagram(). Ipv6::flush() frees the queue on stop and crash without notifying hooks, so Mipv6 clears its map in the same lifecycle operations (commit 3).
  • No NED parameter, packet format, configuration surface or feature descriptor changes. No sealed path is touched, and no architecture or naming exception is added; the names of the three new MIPv6_*.test files fall under the existing naming exception NV-16.

Verification

Reproduction (the table above):

cd examples/ipv6/mipv6roaming
inet -s -u Cmdenv -c Roaming -r 0 --cmdenv-express-mode=false --cmdenv-log-prefix="%t %C: " > roaming.log
grep -c "Sending ICMPv6 Redirect" roaming.log
grep "Using HoA instead of CoA" roaming.log

On master the first command prints 2 and the second prints three lines. On this branch the first prints 0 and the second prints nothing.

New module tests:

  • MIPv6_no_redirect_for_tunneled_traffic.test (commit 2) requires that the home agent decapsulates tunneled traffic, routes the inner datagram as arriving on its tunnel interface, and sends no Redirect.
  • MIPv6_reverse_tunnel_pending.test (commit 3) requires that the binding is accepted, that a datagram is held and then sent when the tunnel comes up, and that no datagram is discarded with "Using HoA instead of CoA".
  • MIPv6_held_home_test_init_not_retransmitted.test (commit 3) requires that a Home Test Init held longer than its 1 s retransmission interval reaches the correspondent node once, followed by one Binding Update. A channel defined in the test delays the Binding Acknowledgement by 0.4 s on the Home_Agent–R_2 link, on top of the home agent's 1 s acknowledgement delay for a first registration. With commit 3 as of f4add9b the test counts two of each.

Release build (make MODE=release), on master at 49e1fa0 (the merge base) before any change and on commits 2 and 3:

  • tests/fingerprint: ./fingerprinttest -s -F tyf runs every baseline file, all 1774 rows. -F tyf skips only the graphical fingerprint values, whose ingredients are t (simulation time), y (display strings) and f (canvas figures). Master gives 0 failures and 62 errors. The 62 errors are optional features that are not built (VoipStreamSender, TcpLwip, Z3GateScheduleConfigurator, the OpenSceneGraph (OSG) visualizer networks). With the re-recorded values, each of the two commits gives 0 failures and the same 62 errors.
  • tests/module: inet_run_module_tests -m release --no-build -l ERROR gives 46 failures on master (346 tests), on commit 2 (347) and on commit 3 (349), with the same names each time: 34 of the 41 tcp_* tests, ConvolutionalCoder12/34, EtherHost_lifecycle, ExternalProcess_3, Ieee80211BitDomain/SymbolDomain, Ieee8021d-Rstp/Stp, IPv6_packet_too_big, MIPv6_tcp_handover, PacketGate_1 and UDPSocket_1. The new tests pass.
  • tests/protocol/ipv6: inet_run_protocol_tests -m release passes 26 of 27 on master and on both commits. Rfc8200OverlappingFragments fails on all three.

Commit 1, release build: ./fingerprinttest -s -F tyf -m 'ipv6|IPv6|bgpv4|ospfv3|dsdv|rip/simpletest|udpclientserver' examples.csv mipv6-refactoring.csv passes unmodified. The 59 module tests matched by -f 'IPv6|Ipv6|MIPv6|ICMP|Icmp|MLD|Mld|PMIPv6|Ping|NetfilterHooks' give the same result as on master. MIPv6_tcp_handover and IPv6_packet_too_big fail on master too.

Debug build (make MODE=debug) of commit 3: the 62 module tests matched by the same filter pass, including all three new tests. All 27 tests/protocol/ipv6 tests pass, and so does ./fingerprinttest -d -F tyf -m mipv6 examples.csv mipv6-refactoring.csv. MIPv6_tcp_handover, IPv6_packet_too_big and Rfc8200OverlappingFragments fail only in release, on master too.

In doc/project/enforcement/, check-commits.sh and check-classification.sh pass. check-architecture.sh passes on src/inet/networklayer/ipv6, mipv6 and ipv6tunneling, and check-source-seals.sh --base origin/master passes. The tree-wide check-architecture.sh, check-naming.sh --base origin/master and check-interfaces.sh report output identical to that on master.

Fingerprints re-recorded:

  • Commit 2: Handover, RouteOptimizationTwoCNs and Roaming, with tplx, ~tNl and ~tND in examples.csv and ~tNlb in mipv6-refactoring.csv, because the Redirects leave the wire.
  • Commit 3: Handover and Roaming, with the same ingredients, because the held datagrams are now sent through the reverse tunnel. RouteOptimizationTwoCNs does not move.

Each commit message gives the reason for each ingredient. No other row of the full suite moves. The graphical tyf values of these rows are not re-recorded and were not checked.


Devin Review

Ipv6RoutingTable creates and deletes the Ipv6TunnelInterface modules that
perform Internet Protocol version 6 (IPv6) in IPv6 encapsulation (Request
for Comments (RFC) 2473), but nothing could ask it which of them a given
pair of tunnel endpoints belongs to.

A node that receives a tunneled datagram needs exactly that. The outer
header names the tunnel's exit point as its destination and the entry point
as its source, and the local interface configured with those endpoints is
the one the inner datagram arrived on: RFC 2473 Section 3 models a tunnel as
a link of its own, so the arrival interface of the inner datagram is the
tunnel, not the physical interface the outer datagram came in on.

Ipv6Tunnel now exposes the endpoints it was configured with, for
findTunnelNetworkInterface() only.

Endpoints do not identify a tunnel uniquely: several tunnels may share an
entry and exit pair and differ only in what is routed onto them. They all
denote the same pair of tunnel endpoints, so for naming the link a datagram
arrived on any of them will do, and the first match is returned.

The function has no caller yet, so behavior is unchanged: the fingerprint
rows of the IPv6 configurations in examples.csv and mipv6-refactoring.csv
pass unmodified at this commit. The commit "ipv6: fix: route a decapsulated
datagram as arriving from the tunnel" is the first caller, and its module
test covers the function.

Change: src.networklayer.ipv6.Ipv6RoutingTable | behavior.add | test whatsnew | mipv6-forwarding-path
A home agent that decapsulated a reverse-tunneled datagram and forwarded the
inner one back out of the interface the outer datagram had arrived on sent
an Internet Control Message Protocol for Internet Protocol version 6
(ICMPv6) Redirect for every one of them, addressed to the mobile node's home
address -- a node that is not on that link, and to which the home agent then
had to tunnel the Redirect.

To reproduce, count the Redirects in the Mobile IPv6 (MIPv6) roaming
example:

  cd examples/ipv6/mipv6roaming
  inet -s -u Cmdenv -c Roaming -r 0 --cmdenv-express-mode=false \
       --cmdenv-log-prefix="%t %C: " | grep "Sending ICMPv6 Redirect"

Before this commit (on 49e1fa0) the home agent sent 2, at t = 23.502 s
and t = 23.505 s, one for each reverse-tunneled datagram it forwarded. It
sends none now.

Request for Comments (RFC) 4861 Section 8.2 lets a router send a Redirect
only when, among other conditions, "the Source Address field of the packet
identifies a neighbor". routePacket() approximates that by comparing the
output interface with the arrival interface, which is sound for a datagram
that arrived on a link. A decapsulated datagram did not arrive on one: RFC
2473 Section 3 models the tunnel as a link of its own. localDeliverFinish()
passed the physical arrival interface on regardless, so the comparison
matched and the Redirect went out.

The inner datagram is now routed as arriving on the tunnel interface found
from the outer addresses. The arrival interface is the input that was wrong:
the comparison in routePacket() is right for a datagram that arrived on a
link, and a tunnel is a link of its own. Correcting the input also covers a
decapsulated datagram whose inner source is on-link on the physical
interface, which a neighbour test on the source address alone would still
redirect. The module test MIPv6_no_redirect_for_tunneled_traffic.test checks
the arrival interface through the new log line (ip6tun1 at the home agent in
this run; the test matches the ip6tun prefix) and the absence of Redirects.

Three limits are deliberate. Only the routing decision is re-attributed: the
InterfaceInd tag still names the physical interface, because upper layers
read it to find the link the datagram came in on -- Mipv6 looks up that
interface's Mipv6InterfaceData, which a tunnel interface does not carry --
and for the same reason a pre-routing hook that QUEUEs the datagram loses
the re-attribution, since reinjectQueuedDatagram() recovers the interface
from that tag. Only unicast is re-attributed: routeMulticastPacket() reads
the arrival interface's Ipv6InterfaceData for its group-membership test and
matches it against the multicast route's incoming interface, and a tunnel
interface has neither, while RFC 4861 Section 8.2 excludes multicast
destinations from Redirects. And a node that decapsulates without having a
tunnel interface for these endpoints, for instance the far end of a
unidirectional tunnel, keeps the physical interface as before.

Ipv6.ned defaults sendRedirects to true, so a MIPv6 home agent did this
without any configuration whenever it forwarded reverse-tunneled traffic
back out of its arrival interface.

Fingerprints: the Handover and RouteOptimizationTwoCNs rows of
examples/ipv6/mipv6 and the Roaming row of examples/ipv6/mipv6roaming move,
in examples.csv (tplx, ~tNl and ~tND) and in mipv6-refactoring.csv (~tNlb),
because the Redirects are no longer transmitted: '~' because the set of
inter-node packet events loses them; 't' because the events after them
shift; 'N' and 'p' because the removed events had their own node and module
paths; 'l', 'b' and 'D' because the Redirects' length, contents and bytes
leave the hash; and 'x' because it hashes per-event extra data for those
same events. No other row of the full suite moves. The graphical tyf values
of these rows (t simulation time, y display strings, f canvas figures) were
not checked, because every run used -F tyf, and are left as recorded.

Change: src.networklayer.ipv6.Ipv6 | behavior.change.fix | fingerprint test whatsnew | mipv6-forwarding-path

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 2 potential issues.

1 flag not posted on this PR by your GitHub settings — view it in Devin Review. (Configure)

Devin Review

Comment on lines +2097 to +2099
const auto& ipv6Header = datagram->peekAtFront<Ipv6Header>();
if (datagram->findTag<InterfaceReq>() != nullptr)
return false; // an output interface (the reverse tunnel, or another one) is already pinned

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Local packets diverted into reverse tunnel

During registration, holdUntilReverseTunnelExists queues home-address packets even when their destination is local. handleMessageFromHL selects loopback, but release pins the tunnel instead. Local packets leave for the home agent or remain queued without acknowledgement.

Learn more

IPv6 selects a loopback output for a packet addressed to the same node before calling the LOCAL_OUT hook in handleMessageFromHL. The new hold ignores this decision because it examines only the packet's InterfaceReq tag, which is absent when IPv6 chose loopback internally. After an acknowledgement, releaseHeldDatagrams pins a tunnel and reinjects the packet, replacing local delivery. An unacknowledged registration leaves the packet queued despite the local destination.

Example: An away mobile node sends from its home address to another local IPv6 address while its home-agent BU is pending. Instead of reaching a local application, the packet waits for a BA and then enters the tunnel.

Recommended fix: Exclude locally destined datagrams from the hold, using the same local-address decision as Ipv6 before enqueuing. Also consider multicast separately: IPv6's locally originated multicast path does not pass through the unicast HoA drop guard.

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +2097 to +2099
const auto& ipv6Header = datagram->peekAtFront<Ipv6Header>();
if (datagram->findTag<InterfaceReq>() != nullptr)
return false; // an output interface (the reverse tunnel, or another one) is already pinned

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Held extension-header packets still drop

When a home-address packet starts with an IPv6 extension header, holdUntilReverseTunnelExists queues it during registration. requestTunnelOutputInterface rejects extension headers both before holding and upon release. The released packet uses the foreign interface and hits IPv6's home-address drop guard.

Learn more

The LOCAL_OUT hook first tries to request a reverse-tunnel interface, then calls the new hold. The tunnel requester refuses IPv6 headers whose protocol ID is an extension header in requestTunnelOutputInterface. Holding still succeeds for these packets when the home-address and registration checks match. releaseHeldDatagrams invokes the same requester, so reinjection has no tunnel pin; resolveMACAddressAndSendPacket discards the packet if it leaves by a foreign interface.

Example: An away node emits a HoA-sourced datagram with a destination-options header while the HA BA is pending. The datagram is held, logged as released after the BA, then discarded instead of entering the tunnel.

Recommended fix: Make reverse-tunnel selection handle supported extension-header chains for both initial transmission and reinjection. Until then, avoid claiming an extension-header datagram is releasable through this hold.

Devin Review


Was this helpful? React with 👍 or 👎 to provide feedback.

A Mobile Internet Protocol version 6 (Mobile IPv6, MIPv6) mobile node that
had just moved to a foreign network discarded the packets it sourced from
its home address until its home registration completed, logging "Using HoA
instead of CoA... dropping datagram" (HoA is the home address, CoA the
care-of address).

To reproduce:

  cd examples/ipv6/mipv6roaming
  inet -s -u Cmdenv -c Roaming -r 0 --cmdenv-express-mode=false \
       --cmdenv-log-prefix="%t %C: " | grep "Using HoA instead of CoA"

Before this commit (on 49e1fa0) three datagrams were lost this way during
the first registration: the first Home Test Init and an Internet Control
Message Protocol for IPv6 (ICMPv6) echo reply to the correspondent node at t
= 22.503 s, and a second echo reply at t = 23.001 s. Losing the Home Test
Init also delayed return routability by a retransmission timeout. None is
lost now.

Request for Comments (RFC) 6275 Section 11.3.1 says: "If a binding exists,
the mobile node SHOULD send the packets directly to the correspondent node.
Otherwise, if a binding does not exist, the mobile node MUST use reverse
tunneling."

The reverse tunnel is created only when the home agent's Binding
Acknowledgement arrives, whereas the home agent creates its own tunnel and
starts forwarding as soon as it accepts the Binding Update. In that window
the mobile node receives tunneled traffic it cannot answer:
datagramLocalOutHook() finds no tunnel to pin as the output interface, the
datagram is routed onto the foreign link, and
Ipv6::resolveMACAddressAndSendPacket() discards it. That guard is right in
itself -- a home address is not a topologically valid source on a foreign
link -- but traffic that a binding is about to make deliverable should not
reach it.

The hook now returns QUEUE for such a datagram. When the Binding
Acknowledgement creates the reverse tunnel, processBAMessage() calls
releaseHeldDatagrams(), which reinjects the held datagrams onto the tunnel.

Without the commit "ipv6: fix: route a decapsulated datagram as arriving
from the tunnel" this fix makes the Redirect defect worse: the released
datagrams reach the home agent through the reverse tunnel, and in
mipv6roaming the home agent then sends 3 Redirects instead of 2.

The alternative is to create the reverse tunnel when the Binding Update is
sent rather than when it is acknowledged, which would send these datagrams
at once instead of after a registration round trip. It is rejected because
RFC 6275 Section 11.3.1 defines the reverse tunnel's outer source as "the
primary care-of address as registered with the home agent": before the
acknowledgement nothing is registered, and the datagrams would be tunneled
to a home agent that has no binding for them.

Holding is bounded from three directions, because the registration alone
does not bound it: Mipv6 retransmits a Binding Update that is never
acknowledged without a limit (RFC 6275 Section 11.8), and the binding update
list entry of such a registration does not expire. A datagram is held only
while a Binding Update to that home agent is unacknowledged and only when
the interface it is sourced from has a care-of address, the same condition
the drop guard tests; at most 100 datagrams are held per home agent, the
oldest being dropped beyond that; and the whole set is dropped when the
binding update list entry expires or the registration is torn down. A
dropped held datagram is reported with a packetDropped signal. The map holds
pointers borrowed from the IPv6 module's netfilter queue, which
Ipv6::flush() frees on stop and crash without notifying its hooks, so the
map is cleared in the same lifecycle operations.

A held Home Test Init is not retransmitted. Its retransmission timer runs
from the moment Mipv6 hands it to the IPv6 module, so a Binding
Acknowledgement that arrives more than INITIAL_BINDACK_TIMEOUT (1 s) later
would find a second Home Test Init held beside the first. Both would be
released together, and return routability would run twice: two Home Test
Init, two Home Test, two Binding Updates to the correspondent node and two
acknowledgements. RFC 6275 Section 11.8 calls for a retransmission "if the
mobile node fails to receive a valid matching response within the selected
initial retransmission interval"; a held message has not been sent, so no
response is missing yet. sendTestInit() therefore skips the retransmission
while a Home Test Init to that correspondent node is held, and
releaseHeldDatagrams() restarts the timer from the initial interval when the
held message is sent. The timer keeps running while the message is held
rather than stopping, because a held datagram can still be dropped
(overflow, binding update list expiry, registration teardown); the next
check then sends a fresh Home Test Init.

Mipv6::processBUMessage() delays the acknowledgement of a first registration
by 1 s (sendTime = existingBinding ? 0 : 1), a stand-in for Duplicate
Address Detection (RFC 6275 Section 10.3.1), and the home agent tunnels from
acceptance. Both intervals are 1 s, so the timer fires first whenever the
Binding Acknowledgement spends longer in transit from the home agent than
the tunneled packet that starts return routability.

The new module test MIPv6_reverse_tunnel_pending.test requires that a
datagram is held and later sent, and that none is discarded with the "Using
HoA instead of CoA" message.

MIPv6_held_home_test_init_not_retransmitted.test delays the Binding
Acknowledgement by 0.4 s on the link between Home_Agent and R_2, on top of
that 1 s: the Home Test Init is held at t = 34.004 s, its retransmission
timer fires at 35.004 s and the acknowledgement arrives at 35.231 s. The
test requires one Home Test Init and one Binding Update at the correspondent
node; without the retransmission check it sees two of each.

Fingerprints: the Handover row of examples/ipv6/mipv6 and the Roaming row of
examples/ipv6/mipv6roaming move, in examples.csv (tplx, ~tNl and ~tND) and
in mipv6-refactoring.csv (~tNlb), because datagrams that were discarded are
now transmitted through the reverse tunnel, and the recovered Home Test Init
advances the return-routability exchange that follows it: '~' because the
set of inter-node packet events gains the recovered datagrams; 't' because
the exchange after them shifts; 'N' and 'p' because the added events have
their own node and module paths; 'l', 'b' and 'D' because the datagrams now
carry an outer IPv6 header; and 'x' because it hashes per-event extra data
for those same events. RouteOptimizationTwoCNs does not move, and no other
row of the full suite moves. The graphical tyf values of these rows (t
simulation time, y display strings, f canvas figures) were not checked,
because every run used -F tyf, and are left as recorded.

Change: src.networklayer.mipv6.Mipv6 | behavior.change.fix | fingerprint test whatsnew | mipv6-forwarding-path
@adamgeorge309
adamgeorge309 force-pushed the topic/gy/mipv6-forwarding-path branch from f4add9b to 09822c1 Compare October 1, 2026 11:12
@adamgeorge309

Copy link
Copy Markdown
Contributor Author

Commit 3 is amended (now 09822c1): a Home Test Init held until the reverse tunnel exists is
no longer retransmitted while it waits; see body item 3. With the previous revision of commit
3 (f4add9b), a Binding Acknowledgement arriving more than 1 s after the Home Test Init was
held released a retransmitted second one with it, and return routability ran twice. In the
RouteOptimization configuration of an unpublished Mobile Internet Protocol version 6 (Mobile
IPv6) showcase that also carries #1195 (the home agent's Duplicate Address Detection fix), this
happened in seed sets 2, 3, 6, 7, 8, 9 and 10 of
1 to 10 with f4add9b and in none with 09822c1. The new module test reproduces it on this
branch alone: 2 Home Test Init and 2 Binding Updates at the correspondent node with
f4add9b, 1 of each now.

Every result in the Verification section holds on 09822c1; the counts now read 349 release
module tests and 62 filtered debug module tests, all three new tests passing. The amend changes
no fingerprint value: no row of the full suite moves.

adamgeorge309 added a commit that referenced this pull request Oct 5, 2026
Brings this branch to the current head of #1247 (09822c1): a Home Test Init held until the reverse tunnel exists is not retransmitted while it waits, so return routability runs once.

This branch has not been deployed

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

Labels

None yet

Projects

None yet

1 participant