diff --git a/src/inet/networklayer/icmpv6/Ipv6NeighbourDiscovery.cc b/src/inet/networklayer/icmpv6/Ipv6NeighbourDiscovery.cc index 9785d3f5522..3fe03ee0449 100644 --- a/src/inet/networklayer/icmpv6/Ipv6NeighbourDiscovery.cc +++ b/src/inet/networklayer/icmpv6/Ipv6NeighbourDiscovery.cc @@ -1010,10 +1010,17 @@ void Ipv6NeighbourDiscovery::createAndSendRsPacket(NetworkInterface *ie) // or the unspecified address. Ipv6Address myIPv6Address = ie->getProtocolData()->getPreferredAddress(); - if (myIPv6Address.isUnspecified()) - myIPv6Address = ie->getProtocolData()->getLinkLocalAddress(); // so we use the link local address instead - - if (ie->getProtocolData()->isTentativeAddress(myIPv6Address)) + // getPreferredAddress() returns the default source address for off-link destinations, + // and deliberately prefers a global address even while Duplicate Address Detection (DAD) + // is still running for it. A solicitation only has to reach the link-local all-routers + // multicast address, so fall back to the link-local address rather than straight to the + // unspecified address: a tentative address is not assigned to the interface yet + // (RFC 4862 Section 5.4), and Ipv6 would substitute it on transmission, releasing the + // solicitation with a source address that contradicts the option chosen below. + if (myIPv6Address.isUnspecified() || ie->getProtocolData()->isTentativeAddress(myIPv6Address)) + myIPv6Address = ie->getProtocolData()->getLinkLocalAddress(); + + if (myIPv6Address.isUnspecified() || ie->getProtocolData()->isTentativeAddress(myIPv6Address)) myIPv6Address = Ipv6Address::UNSPECIFIED_ADDRESS; Ipv6Address destAddr = Ipv6Address::ALL_ROUTERS_2; // all_routers multicast diff --git a/tests/fingerprint/examples.csv b/tests/fingerprint/examples.csv index 283915ab865..0e7a11c157b 100644 --- a/tests/fingerprint/examples.csv +++ b/tests/fingerprint/examples.csv @@ -380,9 +380,9 @@ /examples/manetrouting/multiradio/, -f omnetpp.ini -c MultiRadio -r 0, 20s, ec17-5cc2/tplx;55f5-0894/~tNl, PASS, wireless adhoc Ipv4 /examples/manetrouting/multiradio/, -f omnetpp.ini -c SingleRadio -r 0, 20s, 85a0-51b8/tplx;c07a-44e1/~tNl;3aa0-49ed/tyf, PASS, wireless adhoc Ipv4 -/examples/ipv6/mipv6/, -f omnetpp.ini -c Handover -r 0, 70s, 19b8-20a4/tplx;b378-071d/~tNl;d358-e3bb/~tND;44ef-1a45/tyf, PASS, wireless EthernetMac -/examples/ipv6/mipv6/, -f omnetpp.ini -c RouteOptimizationTwoCNs -r 0, 60s, 3f0c-078d/tplx;04e1-1f03/~tNl;4199-2b15/~tND;ed3e-17fa/tyf, PASS, wireless EthernetMac -/examples/ipv6/mipv6roaming/, -f omnetpp.ini -c Roaming -r 0, 70s, 0798-40c2/tplx;a682-8d0e/~tNl;cdb7-1b34/~tND;afae-2b3c/tyf, PASS, wireless EthernetMac +/examples/ipv6/mipv6/, -f omnetpp.ini -c Handover -r 0, 70s, 43f0-699e/tplx;ff9a-8dbc/~tNl;9304-d5d5/~tND;44ef-1a45/tyf, PASS, wireless EthernetMac +/examples/ipv6/mipv6/, -f omnetpp.ini -c RouteOptimizationTwoCNs -r 0, 60s, b457-5c37/tplx;4038-4ba8/~tNl;d2a0-90db/~tND;ed3e-17fa/tyf, PASS, wireless EthernetMac +/examples/ipv6/mipv6roaming/, -f omnetpp.ini -c Roaming -r 0, 70s, 5272-c850/tplx;1d99-c152/~tNl;9ca1-b5ff/~tND;afae-2b3c/tyf, PASS, wireless EthernetMac /examples/ipv6/pmipv6/, -f omnetpp.ini -c General -r 0, 60s, f614-da0d/tplx;8b55-7191/~tNl;b490-dc09/~tND;0277-d784/tyf, PASS, wireless EthernetMac /examples/mobility/, -f omnetpp.ini -c AnsimMobility -r 0, 10000s, 72f8-5c0b/tplx;0000-0000/~tNl;0000-0000/~tND;7dd1-18eb/tyf, PASS, diff --git a/tests/fingerprint/mipv6-refactoring.csv b/tests/fingerprint/mipv6-refactoring.csv index 4c2175bce5a..361ba8afe04 100644 --- a/tests/fingerprint/mipv6-refactoring.csv +++ b/tests/fingerprint/mipv6-refactoring.csv @@ -8,9 +8,9 @@ # empty-shim step, which kept these fingerprints bit-for-bit identical. # MIPv6 example — the primary test -/examples/ipv6/mipv6/, -f omnetpp.ini -c Handover -r 0, 70s, aa29-a8c5/~tNlb, PASS, wireless EthernetMac -/examples/ipv6/mipv6/, -f omnetpp.ini -c RouteOptimizationTwoCNs -r 0, 60s, 068b-23aa/~tNlb, PASS, wireless EthernetMac -/examples/ipv6/mipv6roaming/, -f omnetpp.ini -c Roaming -r 0, 70s, 7ed8-bee3/~tNlb, PASS, wireless EthernetMac +/examples/ipv6/mipv6/, -f omnetpp.ini -c Handover -r 0, 70s, 9489-e81a/~tNlb, PASS, wireless EthernetMac +/examples/ipv6/mipv6/, -f omnetpp.ini -c RouteOptimizationTwoCNs -r 0, 60s, f670-714f/~tNlb, PASS, wireless EthernetMac +/examples/ipv6/mipv6roaming/, -f omnetpp.ini -c Roaming -r 0, 70s, 05e6-93d0/~tNlb, PASS, wireless EthernetMac # IPv6 examples # MLD example — new PASS row; ~tNl locks the MLD Report/Query/Done/MAS-Query packet exchange (traffic+lengths); diff --git a/tests/module/Ipv6RouterSolicitation_SourceLinkLayerAddressOption.test b/tests/module/Ipv6RouterSolicitation_SourceLinkLayerAddressOption.test new file mode 100644 index 00000000000..0841427daec --- /dev/null +++ b/tests/module/Ipv6RouterSolicitation_SourceLinkLayerAddressOption.test @@ -0,0 +1,75 @@ +%description: +Tests that a Router Solicitation whose IP source address is a real (not +unspecified) address carries the Source Link-Layer Address option, even when +Duplicate Address Detection (DAD) is still running for the host's global +address at the moment the solicitation is sent. + +RFC 4861 Section 6.3.7: "A host sends Router Solicitations to the all-routers +multicast address. The IP source address is set to either one of the +interface's unicast addresses or the unspecified address. The Source +Link-Layer Address option SHOULD be set to the host's link-layer address, if +the IP source address is not the unspecified address." + +The router logs the link-layer address it extracts from each solicitation, so +a missing option shows up as an all-zero MAC address. + +%#-------------------------------------------------------------------------------------------------------------- +%file: test.ned +import inet.networklayer.configurator.ipv6.Ipv6NetworkConfigurator; +import inet.node.ethernet.EthernetSwitch; +import inet.node.ipv6.Router6; +import inet.node.ipv6.StandardHost6; +import ned.DatarateChannel; + +network RsSourceLinkLayerOptionNetwork +{ + types: + channel ethline extends DatarateChannel + { + delay = 0.1us; + datarate = 100Mbps; + } + submodules: + configurator: Ipv6NetworkConfigurator; + router: Router6; + switch: EthernetSwitch; + host[2]: StandardHost6; + connections: + router.ethg++ <--> ethline <--> switch.ethg++; + for i=0..1 { + host[i].ethg++ <--> ethline <--> switch.ethg++; + } +} +%#-------------------------------------------------------------------------------------------------------------- +%inifile: omnetpp.ini +[General] +record-vector-results = false +ned-path = ../../../../src +network = RsSourceLinkLayerOptionNetwork +sim-time-limit = 10s +cmdenv-express-mode = false +cmdenv-log-prefix = "%C: " + +# Stateless address autoconfiguration: the configurator only hands out the prefix +**.ipv6.configurator.networkConfiguratorModule = "configurator" +*.configurator.assignAddressesToHosts = false +*.configurator.config = xml("") + +# Advertise often, so that a host holds a tentative global address by the time +# its own Router Solicitation is due +*.router.ipv6.neighbourDiscovery.minIntervalBetweenRAs = 0.1s +*.router.ipv6.neighbourDiscovery.maxIntervalBetweenRAs = 0.2s + +%#-------------------------------------------------------------------------------------------------------------- +%subst: /omnetpp::// +%#-------------------------------------------------------------------------------------------------------------- +%not-contains: stdout +MAC Address '00-00-00-00-00-00' extracted +%#-------------------------------------------------------------------------------------------------------------- +%contains: stdout +MAC Address '0A-AA- +%#-------------------------------------------------------------------------------------------------------------- +%postrun-command: grep "undisposed object:" test.out > test_undisposed.out || true +%not-contains: test_undisposed.out +undisposed object: ( +%#--------------------------------------------------------------------------------------------------------------