icmpv6: stop Duplicate Address Detection of an address that is removed - #1254
Open
adamgeorge309 wants to merge 2 commits into
Open
adamgeorge309 wants to merge 2 commits into
adamgeorge309 wants to merge 2 commits into
Conversation
…elDad() cancelDad() takes over the loop with which dadHasFailed() cancelled the Duplicate Address Detection (DAD) timer of an address and deleted its dadList entry, so that every place that removes an address can stop its DAD the same way. Change: src.networklayer.icmpv6 | refactor | - | ipv6-dad-removed-address
…emoved When one IPv6 Router Advertisement (RA) carries two autonomous prefixes that are new to a host whose link-local Duplicate Address Detection (DAD) has completed, processRaPrefixInfoForAddrAutoConf() assigns the address of the first prefix tentative and starts its DAD. The second prefix takes the path written for a Mobile IPv6 handover: it records the first address as the old care-of address and restarts DAD on the link-local address. When the link-local DAD completes first, makeTentativeAddressPermanent() removes the first address, but its DAD entry stays in dadList with its timer running. When that timer fires, processDadTimeout() calls permanentlyAssign() for an address the interface no longer holds. findAddress() returns -1, so a debug build stops with "ASSERT: Condition 'k != -1' does not hold in function 'permanentlyAssign'", and a release build writes one byte to addresses[-1]. RFC 4862 (IPv6 Stateless Address Autoconfiguration) Section 5.4 requires DAD on an address before it is assigned to the interface; once the address is removed, its DAD has nothing to verify. Every place in Ipv6NeighbourDiscovery that removes an address now stops its DAD with cancelDad(), as dadHasFailed() already did: the old care-of address in makeTentativeAddressPermanent(), an address whose prefix is advertised with a Valid Lifetime of zero, and the care-of address removed on returning home. Only the first has a known trigger on master. The other two remove an address that can be tentative with its DAD running in the same way, and their timers would reach the same permanentlyAssign() call. tests/module/IPv6_DAD_removed_address.test reproduces it with the configurator's prefix aaaa:0:65::/64 and a second prefix aaaa:2::/64 in the router's RA, at seed-set 0. Before this commit the link-local DAD completed at 4.394825462416 s and removed aaaa:0:65:0:8aa:ff:fe00:2, whose DAD then completed at 4.534878067138 s; valgrind reported an invalid write of size 1 in permanentlyAssign(), 32 bytes before a block of size 192. After it the DAD of aaaa:0:65:0:8aa:ff:fe00:2 ends when the address is removed, and valgrind reports no error. Change: src.networklayer.icmpv6 | behavior.change.fix | test whatsnew | ipv6-dad-removed-address
There was a problem hiding this comment.
🔍 Devin Review: 2 flags
Not posted on this PR by your GitHub settings — view them in Devin Review. (Configure)
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.
An address removed from an interface while its Duplicate Address Detection (DAD) is running keeps its DAD timer, and DAD then completes for an address the interface no longer holds: a debug build stops on
ASSERT(k != -1)inIpv6InterfaceData::permanentlyAssign(), a release build writes one byte toaddresses[-1]. This pull request stops the DAD of an address whereverIpv6NeighbourDiscoveryremoves one.Closes #1253
The problem
An Internet Protocol version 6 (IPv6) Router Advertisement (RA) with two autonomous prefixes that are new to the host, arriving after its link-local DAD has completed:
aaaa:0:65::/64:aaaa:0:65:0:8aa:ff:fe00:2assigned tentative, its DAD startsaaaa:2::/64: every address set tentative, DAD restarts onfe80::8aa:ff:fe00:2,aaaa:0:65:0:8aa:ff:fe00:2recorded as the old care-of addressmakeTentativeAddressPermanent()removesaaaa:0:65:0:8aa:ff:fe00:2permanentlyAssign()withfindAddress()= -1This is master at
seed-set = 0with the network oftests/module/IPv6_DAD_removed_address.test.The commits
icmpv6: refactor: move the Duplicate Address Detection stop into cancelDad(): the loop thatdadHasFailed()ran inline becomes a method the other removal sites can call. No behavior change.icmpv6: fix: stop Duplicate Address Detection of an address that is removed: the three other places that remove an address call it. Only the old care-of address inmakeTentativeAddressPermanent()has a known trigger on master; an address whose prefix is advertised with a Valid Lifetime of zero, and the care-of address removed on returning home, can be tentative with a DAD running in the same way.Architectural surface
One new protected virtual method,
Ipv6NeighbourDiscovery::cancelDad(). No packet, parameter or signal declaration changes. In a run that takes this path, the removed address no longer completes DAD:dadCompletedhas one emission less, and withsendGratuitousNa = trueone unsolicited Neighbor Advertisement for that address is no longer sent.Verification
tests/module/IPv6_DAD_removed_address.testreproduces the table above. On master its%not-containsfor the "DAD completed" line of the removed address fails (the line is in the output, at 4.534878067138 s); with the fix it passes:The memory error, with the test's
test.nedandomnetpp.iniextracted into a directory (thened-pathline removed):In a debug build, with the test's network at
seed-set = 0, commit 1 (no fix yet) stops withASSERT: Condition 'k != -1' does not hold in function 'permanentlyAssign' at inet/networklayer/ipv6/Ipv6InterfaceData.cc:393 ... at t=4.534878067138s; with this pull request the run completes. The 39 module tests thatinet_run_module_tests -m debug --no-build -l ERROR -f 'IPv6|DAD|MIPv6|PMIPv6|NUD|ND_'selects all pass in debug, includingIPv6_packet_too_bigandMIPv6_tcp_handover, which fail on master in release only, and thendprotocol suite gives the same 22 PASS, 15 FAIL in debug as in release.Gates:
check-commits.sh origin/master..HEADandcheck-classification.sh origin/master..HEADpass (notes: subjects of 75 and 76 characters). Onsrc/inet/networklayer/icmpv6,check-architecture.sh,check-interfaces.shandcheck-source-seals.shpass;check-naming.shreports the two hits it reports on master, inIcmpv6Header.msgandMldv2Message.msg, which this pull request does not touch.Suites, release build, results diffed by test name against unmodified master. The fingerprint, module and
ipv6runs were made on master 49e1fa0 and on both commits. The branch was then rebased onto master 4eb3bb4, which changes nothing undersrc/,tests/module/ortests/fingerprint/; thendandmldprotocol suites, new in 4eb3bb4, were run on 4eb3bb4 and on commit 2 only.-F tyf)ipv6ndmldThe failing and erroring tests are the same by name in every column. The 63 fingerprint errors are configurations of optional features this build does not enable (VoIPStream, TcpLwip, the OpenSceneGraph (OSG) visualizer, the Z3 gate scheduler) and
ethernet-nonstandardspeed.iniat 5 Gbps half duplex. The 46 module failures are 34tcp_*tests, ConvolutionalCoder12/34, EtherHost_lifecycle, ExternalProcess_3, Ieee80211BitDomain/SymbolDomain, Ieee8021d-Rstp/Stp, IPv6_packet_too_big, MIPv6_tcp_handover, PacketGate_1 and UDPSocket_1. Theipv6protocol failure isRfc8200OverlappingFragments; thendandmldfailures are the gaps their suites record on master (onemldtest is marked as an expected failure). The one module test added isIPv6_DAD_removed_address. No fingerprint moves.Not addressed here
processRaPrefixInfoForAddrAutoConf()treats any second new prefix as a Mobile IPv6 handover and removes the first address as the old care-of address, which Request for Comments (RFC) 4862 (IPv6 Stateless Address Autoconfiguration) Section 5.5.3 does not ask for. Limiting that branch to a real handover is a separate change; ipv6: verify a care-of address before registering it with the home agent #1141 (DAD for the care-of address formed at a handover) edits the same branch.Ipv6InterfaceDataalso removes addresses whose valid lifetime has expired, outsideIpv6NeighbourDiscovery; that removal does not stop a running DAD either.aaaa:1::/64,seed-set = 1). That is a separate Router Discovery defect, not filed yet.