Repository navigation
icmpv6: end address resolution when an NS sets the entry STALE - #1337
Open
adamgeorge309 wants to merge 1 commit into
Open
adamgeorge309 wants to merge 1 commit into
adamgeorge309 wants to merge 1 commit into
Conversation
A Neighbor Solicitation (NS) with a Source Link-Layer Address option that found an INCOMPLETE Neighbour Cache entry recorded the address and set the entry STALE, but left the address-resolution timer running and the packets queued for the entry waiting. The timer then went on with the retransmissions: processArTimeout() does not check the state, so it sent multicast NSs for a neighbour whose link-layer address was known and, after MAX_MULTICAST_SOLICIT NSs in all, declared address resolution failed and deleted the entry, which could be REACHABLE by then. RFC 4861 Appendix C gives this transition as "INCOMPLETE NS ... Record link-layer address. Send queued packets. STALE"; Section 7.2.2 retransmits only while awaiting a response. processNsWithSpecifiedSrcAddr() now sets an INCOMPLETE entry STALE even if a Router Advertisement already recorded the same address, and cancels the timer and sends the queued packets, as processNaForIncompleteNceState() does when a Neighbor Advertisement (NA) completes resolution. With two hosts on one link that start sending to each other at the same moment, each host's entry for the other is INCOMPLETE when the other's multicast NS arrives. Before this commit the two hosts sent 8 extra multicast NSs and deleted their entries 4 times in 6 s of traffic; after it, none. tests/module/IPv6_ND_solicitation_ends_address_resolution.test runs that case and checks that no host retransmits an NS for address resolution or declares it failed; it fails before this commit. The fingerprints of the GPSR (Greedy Perimeter Stateless Routing) rows IPv6, MultiIPv6 and DynamicIPv6 in examples.csv change, and this commit records the new ones: in IPv6, failed address resolutions go from 17 to 9. Their statistical baselines change as well; the statistics repository updates them after this merges. Change: src.networklayer.icmpv6.Ipv6NeighbourDiscovery | behavior.change.fix | test fingerprint statistical whatsnew
This was referenced Oct 15, 2026
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A Neighbor Solicitation (NS) with a Source Link-Layer Address option that found an INCOMPLETE Neighbour Cache entry set it STALE, but left the address-resolution timer running and the queued packets waiting. The timer went on sending multicast NSs for a neighbour whose link-layer address was known, and then declared address resolution failed and deleted the entry. RFC 4861 Appendix C gives this transition as "Record link-layer address. Send queued packets." The NS now cancels the timer and sends the queued packets, as a Neighbor Advertisement (NA) that completes resolution already does.
Risk: runs in which an INCOMPLETE entry receives an NS from its neighbour, typically two nodes that resolve each other at the same moment, send fewer multicast NSs, keep their entries, and send the queued datagrams earlier. The fingerprints of three IPv6 rows of
examples/manetrouting/gpsr(Greedy Perimeter Stateless Routing, GPSR) change and are recorded here; their statistical baselines need re-recording after the merge.Closes #1336
One commit:
icmpv6: fix: end address resolution when an NS sets the entry STALE.The problem
initiateAddressResolution()schedulesNeighbour::arTimer(src/inet/networklayer/icmpv6/Ipv6NeighbourDiscovery.cc:692-695on master), and Neighbour Discovery cancels it on a state change only inprocessNaForIncompleteNceState()(lines 2262-2264), together with sending the queued packets.processNsWithSpecifiedSrcAddr()(lines 1957-1966) records the link-layer address of an existing entry and sets it STALE when the cached address differs, which is the case for an INCOMPLETE entry unless a Router Advertisement already recorded the same address, but does neither. The NA that answers the entry's own NS then finds it STALE;processNaForOtherNceStates()sends the queued packets but leaves the timer.processArTimeout()(lines 698-721) does not check the state: it sends another multicast NS while fewer than MAX_MULTICAST_SOLICIT have been sent, and then callsdropQueuedPacketsAwaitingAr(), which returns any queued packets as Internet Control Message Protocol for IPv6 (ICMPv6) Destination Unreachable and deletes the entry.RFC 4861 Appendix C:
Section 7.2.2 retransmits "While awaiting a response", and Appendix C has a retransmit timeout only in INCOMPLETE and PROBE; it has none in STALE, DELAY or REACHABLE.
The fix
When the existing entry is INCOMPLETE,
processNsWithSpecifiedSrcAddr()now records the address and sets it STALE even if a Router Advertisement already recorded the same address, and it cancels and deletesarTimerand callssendQueuedPacketsToIpv6Module(), the two stepsprocessNaForIncompleteNceState()takes. For entries in the other states the Section 7.2.3 rule is unchanged: STALE only when the address differs. The packets go back toIpv6, whereresolveNeighbour()finds the STALE entry, returns its link-layer address and starts the DELAY state, as Section 7.3.3 requires for a packet sent to a STALE neighbour.Not changed: a Router Advertisement with a Source Link-Layer Address option records the address of an existing entry but leaves its state (lines 1474-1478), so an INCOMPLETE entry stays INCOMPLETE until an NA or an NS arrives; Redirect and Router Solicitation handling do not update the Neighbour Cache. No C++ interface, Network Description (NED) parameter, message field or feature descriptor changes.
Verification
Reproduction: two
StandardHost6on one 10 Mb/s link withIpv6FlatNetworkConfigurator, each running aUdpBasicAppto the other (64 B every 1 s, stopping at 12 s, run to 20 s). The committed test,tests/module/IPv6_ND_solicitation_ends_address_resolution.test, uses the simultaneous start without a stop time and runs to 10 s; it fails on master and passes with this change.Sending another Address Resolution NS messageAddress Resolution has failed.Initiating Address ResolutionWith this change host a sends the datagram queued at 6 s when b's NS arrives (6.0000785 s) instead of when b's NA does (6.0001665 s on master); the entry goes to DELAY, and the NA at 6.0002865 s sets it REACHABLE and cancels the DELAY timer. On master, a deletes its entry for b at 9 s and at 12 s; after 9 s it resolves b again.
examples/manetrouting/gpsr, run for 20 s as in the fingerprint test, with**.neighbourDiscovery.cmdenv-log-level = detail:host[0])IPv6, masterIPv6, this changeDynamicIPv6, masterDynamicIPv6, this changeRelease build (
make MODE=releasein the root andtests/module/lib), each suite run on master41eee1d619and with this change:tests/fingerprint: ./fingerprinttest -s -F tyfgpsrrowsIPv6,MultiIPv6andDynamicIPv6pass with the fingerprints this commit records, and master computes the previous ones (for examplee008-a90a/tplxforIPv6);./fingerprinttest -s -m gpsr, with every ingredient includingtyf, passes its 10 rowstests/module: inet_run_module_tests -m release --no-build -l ERRORIeee80211BlockAckVariant_1now pass;Ieee80211BlockAckVariant_1failed in the master run and in a run of an earlier version of this change, and passed in all 7 later runs, one of them with master'sIpv6NeighbourDiscovery.ccThe 5 fingerprint failures are rows of
mipv6-refactoring.csvwhose recorded~tNlbfingerprints are stale on master; the 62 errors are configurations whose optional features are not built. Of the 290 module failures on master, 274 aretcp_*tests, one is the new test, and 15 areConvolutionalCoder12,ConvolutionalCoder34,DimensionalMediumAnalogModel_PrintAttenuation_1,EtherHost_lifecycle,ExternalProcess_3,Ieee80211BitDomain,Ieee80211BlockAckVariant_1,Ieee80211SymbolDomain,Ieee8021d-Rstp,Ieee8021d-Stp,IPv6_packet_too_big,LogNormalShadowing_Correlated_4,MIPv6_tcp_handover,PacketGate_1,UDPSocket_1; all of them exceptIeee80211BlockAckVariant_1fail with this change as well.Debug build (
make MODE=debugin the root andtests/module/lib, exit 0, no compiler warning inIpv6NeighbourDiscovery.cc):inet_run_module_tests -m debug --no-build -l ERRORpasses the new test andIPv6_NUD_stale_to_probe.Statistical baselines (the separate
statisticsrepository at8fdf7f5): thegpsrIPv6andDynamicIPv6runs record 2376 scalars each, all equal on master to the scalar at the same position in the baseline, which records more; with this change 1139 (IPv6) and 825 (DynamicIPv6) of them differ, for examplehost[0].app[0]pingRxSeq:countfrom 7 to 9 and from 0 to 1.MultiIPv6has the sametplxand~tNlfingerprints asIPv6, before and after. The three baselines belong in a commit to the statistics repository after this merges, naming this one. Not verified by a test: the sending of the queued datagrams from the NS path (in the reproduction the NA would send them too), and an INCOMPLETE entry whose address a Router Advertisement already recorded.Gates:
check-pull-request.sh --base origin/master(commits, classification, includes, NED parameters, description),check-source-seals.sh --base origin/masterandcheck-architecture.sh src/inet/networklayer/icmpv6pass.Relationship to other pull requests
#1334 fixes a different defect on the same NA path (ReachableTime not restarted by a solicited NA); in the reproduction its defect accounts for the Neighbour Unreachability Detection starts on master.
Ipv6NeighbourCache::remove()does not cancelarTimer(not reported yet); on master the leftover timer of this defect can outlive an entry that Neighbour Unreachability Detection removes, and this change removes that case for the NS path. #1260 changes the RetransTimer thatinitiateAddressResolution()andprocessArTimeout()schedule with, and adds no cancellation. #1152 and #1262 also change the fingerprints of these threegpsrrows; whichever merges later re-records them. #1322, #1324, #1326, #1328 and #1334 also add an entry under "Notable bug fixes" inWHATSNEW; whichever merges later renumbers.