diff --git a/WHATSNEW b/WHATSNEW index 03828369a2a..4a3a262392b 100644 --- a/WHATSNEW +++ b/WHATSNEW @@ -293,6 +293,22 @@ Notable backward incompatible changes are the following: negotiation. The MacQosWithBlockAck example fingerprints are updated; the QoS and NonQos showcase fingerprint controls remain unchanged. +17. Mobile IPv6 signaling goes to the next hop, not to the whole link + + Mobile Internet Protocol version 6 (Mobile IPv6, MIPv6) sent the Binding + Update (BU), the Care-of Test Init (CoTI), the Binding Acknowledgement (BA) + and the Binding Refresh Request on a fixed output interface without naming a + next hop, so the Ipv6 module addressed each of them to the link-layer + broadcast address. On 802.11 the access point relayed every such frame back + into its cell, and the relayed frame was sent without an acknowledgement. + Mipv6 now names the next hop, and the frame goes to that neighbour's + link-layer address when the Neighbour Cache holds it. + + In MIPv6 simulations, the access point no longer relays the signaling into + the cell, and each signaling frame the access point forwards to a station + gets an 802.11 acknowledgement, so their trajectories and fingerprints may + change. + Notable backward compatible changes are the following: 1. IEEE 802.11 per-station rate statistics diff --git a/src/inet/networklayer/icmpv6/Ipv6NeighbourDiscovery.cc b/src/inet/networklayer/icmpv6/Ipv6NeighbourDiscovery.cc index 9785d3f5522..0e6af55b26c 100644 --- a/src/inet/networklayer/icmpv6/Ipv6NeighbourDiscovery.cc +++ b/src/inet/networklayer/icmpv6/Ipv6NeighbourDiscovery.cc @@ -16,6 +16,7 @@ #include "inet/linklayer/common/InterfaceTag_m.h" #include "inet/networklayer/common/HopLimitTag_m.h" #include "inet/networklayer/common/L3AddressTag_m.h" +#include "inet/networklayer/common/NextHopAddressTag_m.h" #include "inet/networklayer/contract/IInterfaceTable.h" #include "inet/networklayer/icmpv6/Icmpv6.h" #include "inet/networklayer/ipv6/Ipv6Header.h" @@ -755,6 +756,12 @@ void Ipv6NeighbourDiscovery::sendPacketToIpv6Module(Packet *msg, const Ipv6Addre { msg->removeTagIfPresent(); msg->addTagIfAbsent()->setInterfaceId(interfaceId); + /*RFC 4861 Section 5.2: a Neighbour Discovery message is always addressed to a + neighbour on the link it goes out on, so its next hop is its destination. Pinning + the output interface makes the Ipv6 module skip next-hop determination, so state + the next hop here; without it the Ipv6 module has no address to look up in the + Neighbour Cache and has to fall back to the broadcast address.*/ + msg->addTagIfAbsent()->setNextHopAddress(destAddr); msg->addTagIfAbsent()->setProtocol(&Protocol::icmpv6); auto addressReq = msg->addTagIfAbsent(); addressReq->setSrcAddress(srcAddr); diff --git a/src/inet/networklayer/ipv6/Ipv6.cc b/src/inet/networklayer/ipv6/Ipv6.cc index f3f518f1616..22f483591a6 100644 --- a/src/inet/networklayer/ipv6/Ipv6.cc +++ b/src/inet/networklayer/ipv6/Ipv6.cc @@ -433,10 +433,23 @@ void Ipv6::datagramLocalOut(Packet *packet, const NetworkInterface *destIE, Ipv6 const auto& ipv6Header = packet->peekAtFront(); // route packet if (destIE != nullptr) { - if (!ipv6Header->getDestAddress().isMulticast()) - fragmentPostRouting(packet, destIE, MacAddress::BROADCAST_ADDRESS, true); - else - fragmentPostRouting(packet, destIE, ipv6Header->getDestAddress().mapToMulticastMacAddress(), true); + Ipv6Address destAddress = ipv6Header->getDestAddress(); + if (destAddress.isMulticast()) + fragmentPostRouting(packet, destIE, destAddress.mapToMulticastMacAddress(), true); + else { + // RFC 4861 Section 5.2: the link-layer address of the next hop comes from the + // Neighbour Cache. A pinned output interface skips next-hop determination, so the + // cache can only be consulted when the sender states the next hop itself (as + // Neighbour Discovery and GPSR do, for an on-link neighbour they already know). + // Otherwise the destination need not be the next hop -- it may not even be on this + // link -- and the link layer cannot be addressed. + MacAddress macAddress; + if (!requestedNextHopAddress.isUnspecified()) + macAddress = nd->resolveNeighbour(requestedNextHopAddress, destIE->getInterfaceId()); + if (macAddress.isUnspecified()) + macAddress = MacAddress::BROADCAST_ADDRESS; + fragmentPostRouting(packet, destIE, macAddress, true); + } } else if (!ipv6Header->getDestAddress().isMulticast()) routePacket(packet, destIE, nullptr, requestedNextHopAddress, true); diff --git a/src/inet/networklayer/mipv6/Mipv6.cc b/src/inet/networklayer/mipv6/Mipv6.cc index c70d39b322b..c49462f6b9a 100644 --- a/src/inet/networklayer/mipv6/Mipv6.cc +++ b/src/inet/networklayer/mipv6/Mipv6.cc @@ -23,6 +23,7 @@ #include "inet/networklayer/common/L3AddressResolver.h" #include "inet/networklayer/common/L3AddressTag_m.h" #include "inet/networklayer/common/L3Tools.h" +#include "inet/networklayer/common/NextHopAddressTag_m.h" #include "inet/networklayer/contract/IInterfaceTable.h" #include "inet/networklayer/icmpv6/Ipv6NeighbourDiscovery.h" #include "inet/networklayer/ipv6/Ipv6.h" @@ -631,8 +632,15 @@ void Mipv6::sendMobilityMessageToIPv6Module(Packet *msg, const Ipv6Address& dest EV_INFO << "Appending ControlInfo to mobility message\n"; msg->addTagIfAbsent()->setProtocol(&Protocol::ipv6); msg->addTagIfAbsent()->setProtocol(&Protocol::mobileipv6); - if (interfaceId != -1) + if (interfaceId != -1) { msg->addTagIfAbsent()->setInterfaceId(interfaceId); + // A pinned output interface makes the Ipv6 module skip next-hop determination, and + // without a stated next hop it sends a unicast datagram to the link-layer broadcast + // address. RFC 4861 Section 5.2: the link-layer address is that of the next hop. + Ipv6Address nextHop = getNextHopOnInterface(destAddr, interfaceId); + if (!nextHop.isUnspecified()) + msg->addTagIfAbsent()->setNextHopAddress(nextHop); + } msg->addTagIfAbsent()->setSrcAddress(srcAddr); msg->addTagIfAbsent()->setDestAddress(destAddr); msg->addTagIfAbsent()->setHopLimit(255); @@ -650,6 +658,29 @@ void Mipv6::sendMobilityMessageToIPv6Module(Packet *msg, const Ipv6Address& dest send(msg, "toIPv6"); } +Ipv6Address Mipv6::getNextHopOnInterface(const Ipv6Address& destAddr, int interfaceId) const +{ + if (destAddr.isMulticast()) + return Ipv6Address::UNSPECIFIED_ADDRESS; + // RFC 4861 Section 5.1: the link-local prefix is always on-link + if (destAddr.isLinkLocal()) + return destAddr; + // longest prefix match among the routes through the given interface; the routing + // table keeps its routes sorted by prefix length, so the first match is the longest + for (int i = 0; i < rt6->getNumRoutes(); i++) { + const Ipv6Route *route = rt6->getRoute(i); + if (route->getInterface() == nullptr || route->getInterface()->getInterfaceId() != interfaceId) + continue; + if (!destAddr.matches(route->getDestPrefix(), route->getPrefixLength())) + continue; + if (route->getExpiryTime() != 0 && simTime() > route->getExpiryTime()) // 0 means infinity + continue; + // an on-link destination is its own next hop + return route->getNextHop().isUnspecified() ? destAddr : route->getNextHop(); + } + return Ipv6Address::UNSPECIFIED_ADDRESS; +} + void Mipv6::processBUMessage(Packet *inPacket, const Ptr& bu) { EV_INFO << "Entered BU processing method" << endl; diff --git a/src/inet/networklayer/mipv6/Mipv6.h b/src/inet/networklayer/mipv6/Mipv6.h index bb871ae9114..77ff7a8563b 100644 --- a/src/inet/networklayer/mipv6/Mipv6.h +++ b/src/inet/networklayer/mipv6/Mipv6.h @@ -309,6 +309,15 @@ class INET_API Mipv6 : public OperationalBase, public IIpv6ExtensionHeaderHandle simtime_t sendTime = 0); // overloaded for use at CN - CB // void sendMobilityMessageToIPv6Module(cMessage *msg, const Ipv6Address& destAddr, simtime_t sendTime = 0); // overloaded for use at CN - CB + /** + * Returns the next hop toward destAddr through the given interface: destAddr itself + * for a link-local destination or when the longest matching route through that + * interface is on-link, otherwise that route's next hop. Returns the unspecified + * address for a multicast destination and when no route through the interface + * matches. + */ + Ipv6Address getNextHopOnInterface(const Ipv6Address& destAddr, int interfaceId) const; + /** * Process a BU - only applicable to HAs and CNs. */ diff --git a/tests/fingerprint/examples.csv b/tests/fingerprint/examples.csv index 9fc76d91942..a62474f4967 100644 --- a/tests/fingerprint/examples.csv +++ b/tests/fingerprint/examples.csv @@ -31,14 +31,14 @@ /examples/bgpv4/BgpUpdate/, -f omnetpp.ini -c General -r 0, 30s, 9552-83f7/tplx;3a06-a4f0/~tNl;62be-5688/~tND;0573-e0b4/tyf, PASS, ospf EthernetMac Ipv4 /examples/bgpv4/BgpAndOspf/, -f omnetpp.ini -c General -r 0, 1000s, 1e22-36e3/tplx;2b66-00b2/~tNl;430e-7064/~tND;de89-afd7/tyf, PASS, ospf EthernetMac Ipv4 /examples/bgpv4/BgpAndOspfSimple/, -f omnetpp.ini -c General -r 0, 1000s, dc15-38aa/tplx;dacd-0cbd/~tNl;46d3-bcb3/~tND;8a59-2347/tyf, PASS, ospf EthernetMac Ipv4 -/examples/bgpv4/BgpIpv6Basic/, -f omnetpp.ini -c General -r 0, 30s, 4094-e79b/tplx;a631-2b6d/~tNl;7b45-6ce9/~tND;b856-841a/tyf, PASS, EthernetMac Ipv6 -/examples/bgpv4/BgpAndOspfv3/, -f omnetpp.ini -c General -r 0, 100s, 279e-7c39/tplx;c850-91d5/~tNl;4a67-0d99/~tND, PASS, ospf EthernetMac Ipv6 +/examples/bgpv4/BgpIpv6Basic/, -f omnetpp.ini -c General -r 0, 30s, a26e-8273/tplx;36ba-430c/~tNl;e9c4-a35f/~tND;b856-841a/tyf, PASS, EthernetMac Ipv6 +/examples/bgpv4/BgpAndOspfv3/, -f omnetpp.ini -c General -r 0, 100s, 67be-f00f/tplx;7d88-3330/~tNl;64a4-c663/~tND, PASS, ospf EthernetMac Ipv6 /examples/bgpv4/BgpDiamondFailover/, -f omnetpp.ini -c General -r 0, 160s, 819b-726f/tplx;759b-8711/~tNl;f690-850d/~tND;fc56-f343/tyf, PASS, ospf EthernetMac Ipv4 lifecycle -/examples/bgpv4/BgpDiamondFailover6/,-f omnetpp.ini -c General -r 0, 160s, a666-6758/tplx;d51e-c4d6/~tNl;2735-bd52/~tND;5c49-0569/tyf, PASS, ospf EthernetMac Ipv6 lifecycle +/examples/bgpv4/BgpDiamondFailover6/,-f omnetpp.ini -c General -r 0, 160s, 7ce1-a53b/tplx;ebe9-b795/~tNl;5b84-f820/~tND;5c49-0569/tyf, PASS, ospf EthernetMac Ipv6 lifecycle /examples/bgpv4/BgpWithdrawal/, -f omnetpp.ini -c General -r 0, 100s, 5c56-7cbf/tplx;8250-4312/~tNl;4fe4-ce94/~tND;4b70-109c/tyf, PASS, ospf EthernetMac Ipv4 lifecycle /examples/bgpv4/BgpWithdrawal/, -f omnetpp.ini -c Restart -r 0, 160s, ca6f-1994/tplx;93e2-ddd6/~tNl;e095-19d7/~tND;6886-9c54/tyf, PASS, ospf EthernetMac Ipv4 lifecycle -/examples/bgpv4/BgpWithdrawal6/, -f omnetpp.ini -c General -r 0, 100s, ab2e-3ef8/tplx;9719-7216/~tNl;3f7c-49a9/~tND;e5cd-25cd/tyf, PASS, ospf EthernetMac Ipv6 lifecycle -/examples/bgpv4/BgpWithdrawal6/, -f omnetpp.ini -c Restart -r 0, 160s, 1049-f3fa/tplx;9430-9652/~tNl;16c8-e8fa/~tND;92cc-81f6/tyf, PASS, ospf EthernetMac Ipv6 lifecycle +/examples/bgpv4/BgpWithdrawal6/, -f omnetpp.ini -c General -r 0, 100s, 70ed-0ae3/tplx;5b70-b964/~tNl;1866-187a/~tND;e5cd-25cd/tyf, PASS, ospf EthernetMac Ipv6 lifecycle +/examples/bgpv4/BgpWithdrawal6/, -f omnetpp.ini -c Restart -r 0, 160s, d5d0-192b/tplx;3c33-5b8e/~tNl;c72e-402c/~tND;92cc-81f6/tyf, PASS, ospf EthernetMac Ipv6 lifecycle /examples/clock/, -f omnetpp.ini -c General -r 0, 10ms, 35c3-8325/tplx;0000-0000/~tNl;0000-0000/~tND;a4b7-bff5/tyf, PASS, @@ -336,7 +336,7 @@ # /examples/ipv6/nclients/, -f omnetpp.ini -c TCP_APP -r 0 # abstract-config # /examples/ipv6/nclients/, -f omnetpp.ini -c SCTP_APP -r 0 # abstract-config -/examples/ipv6/nclients/, -f omnetpp.ini -c ETH -r 0, 1000s, 5ceb-d724/tplx;f68f-bd29/~tNl;dc62-23bc/tyf, PASS, EthernetMac +/examples/ipv6/nclients/, -f omnetpp.ini -c ETH -r 0, 1000s, 362d-6d53/tplx;bf89-7a8f/~tNl;dc62-23bc/tyf, PASS, EthernetMac /examples/ipv6/nclients/, -f omnetpp.ini -c PPP -r 0, 1000s, e456-89b4/tplx;495e-637d/~tNl;70e4-0b40/tyf, PASS, /examples/ipv6/nclients/, -f omnetpp.ini -c PPP_SCTP -r 0, 100s, 8e6b-b19c/tplx;72ba-2d33/~tNl;6414-b270/~tND;acbf-ec68/tyf, PASS, @@ -365,25 +365,25 @@ # /examples/manetrouting/gpsr/, -f omnetpp.ini -c _IPv6 -r 0, # abstract-config # /examples/manetrouting/gpsr/, -f omnetpp.ini -c _Generic -r 0, # abstract-config /examples/manetrouting/gpsr/, -f omnetpp.ini -c IPv4 -r 0, 20s, 1128-a3bc/tplx;9f6c-df77/~tNl;5d32-0ae4/tyf, PASS, wireless adhoc Ipv4 -/examples/manetrouting/gpsr/, -f omnetpp.ini -c IPv6 -r 0, 20s, e008-a90a/tplx;eead-fc34/~tNl;f19e-13d3/tyf, PASS, wireless adhoc +/examples/manetrouting/gpsr/, -f omnetpp.ini -c IPv6 -r 0, 20s, 7787-9c5d/tplx;ee66-a52a/~tNl;f19e-13d3/tyf, PASS, wireless adhoc /examples/manetrouting/gpsr/, -f omnetpp.ini -c Generic -r 0, 20s, 6b9d-8586/tplx;c58b-970e/~tNl;17f5-8ad3/tyf, PASS, wireless adhoc # /examples/manetrouting/gpsr/, -f omnetpp.ini -c _Multi -r 0, # abstract-config /examples/manetrouting/gpsr/, -f omnetpp.ini -c MultiIPv4 -r 0, 20s, d4a1-5cf9/tplx;c727-b58f/~tNl;bf7d-a45f/tyf, PASS, wireless adhoc Ipv4 -/examples/manetrouting/gpsr/, -f omnetpp.ini -c MultiIPv6 -r 0, 20s, e008-a90a/tplx;eead-fc34/~tNl;273d-a6b5/tyf, PASS, wireless adhoc +/examples/manetrouting/gpsr/, -f omnetpp.ini -c MultiIPv6 -r 0, 20s, 7787-9c5d/tplx;ee66-a52a/~tNl;273d-a6b5/tyf, PASS, wireless adhoc /examples/manetrouting/gpsr/, -f omnetpp.ini -c MultiGeneric -r 0, 20s, 5c6b-556c/tplx;e56d-c248/~tNl;c35c-205b/tyf, PASS, wireless adhoc /examples/manetrouting/gpsr/, -f omnetpp.ini -c Manual -r 0, 20s, 41d0-4325/tplx;b911-bca9/~tNl;8a0e-d569/tyf, PASS, wireless adhoc Ipv4 # /examples/manetrouting/gpsr/, -f omnetpp.ini -c _Dynamic -r 0, # abstract-config /examples/manetrouting/gpsr/, -f omnetpp.ini -c DynamicIPv4 -r 0, 20s, ce31-f8ed/tplx;8a3b-235d/~tNl;3ecd-bfef/tyf, PASS, wireless adhoc Ipv4 -/examples/manetrouting/gpsr/, -f omnetpp.ini -c DynamicIPv6 -r 0, 20s, e618-be99/tplx;edb3-6679/~tNl;2653-aa28/tyf, PASS, wireless adhoc +/examples/manetrouting/gpsr/, -f omnetpp.ini -c DynamicIPv6 -r 0, 20s, e378-1afe/tplx;b62a-cdf2/~tNl;2653-aa28/tyf, PASS, wireless adhoc /examples/manetrouting/gpsr/, -f omnetpp.ini -c DynamicGeneric -r 0, 20s, 732c-c576/tplx;03c2-f3ec/~tNl;fb81-3dac/tyf, PASS, wireless adhoc /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, dca6-3751/tplx;a44c-17bf/~tNl;96ff-ed7c/~tND;44ef-1a45/tyf, PASS, wireless EthernetMac -/examples/ipv6/mipv6/, -f omnetpp.ini -c RouteOptimizationTwoCNs -r 0, 60s, 1560-028f/tplx;e6db-28c0/~tNl;805b-8a25/~tND;ed3e-17fa/tyf, PASS, wireless EthernetMac -/examples/ipv6/mipv6roaming/, -f omnetpp.ini -c Roaming -r 0, 70s, 342e-5e65/tplx;28ce-974e/~tNl;dcec-ae59/~tND;afae-2b3c/tyf, PASS, wireless EthernetMac -/examples/ipv6/pmipv6/, -f omnetpp.ini -c General -r 0, 60s, 081b-769c/tplx;1064-9bd4/~tNl;bd46-d85c/~tND;0277-d784/tyf, PASS, wireless EthernetMac +/examples/ipv6/mipv6/, -f omnetpp.ini -c Handover -r 0, 70s, 0fef-37ec/tplx;0844-99eb/~tNl;2308-14bb/~tND;44ef-1a45/tyf, PASS, wireless EthernetMac +/examples/ipv6/mipv6/, -f omnetpp.ini -c RouteOptimizationTwoCNs -r 0, 60s, d3cb-de8b/tplx;907f-cb55/~tNl;ecf9-c130/~tND;ed3e-17fa/tyf, PASS, wireless EthernetMac +/examples/ipv6/mipv6roaming/, -f omnetpp.ini -c Roaming -r 0, 70s, 7035-050f/tplx;403e-7666/~tNl;97c7-529a/~tND;afae-2b3c/tyf, PASS, wireless EthernetMac +/examples/ipv6/pmipv6/, -f omnetpp.ini -c General -r 0, 60s, 2778-df83/tplx;c7f6-cd7f/~tNl;7cc7-064c/~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, /examples/mobility, -f omnetpp.ini -c AttachedMobility, 10s, 566c-6355/tplx;0000-0000/~tNl;0000-0000/~tND;fa92-f68c/tyf, PASS, @@ -528,7 +528,7 @@ /examples/rip/mixednetwork/, -f omnetpp.ini -c disconnect -r 0, 100s, cff2-9525/tplx;ba53-ebda/~tNl;fa7d-05a5/~tND;65b9-9e8c/tyf, PASS, EthernetMac Ipv4 /examples/rip/mixednetwork/, -f omnetpp.ini -c shutdown-restart -r 0, 100s, 3f15-0c9c/tplx;0916-8bd0/~tNl;d7b7-042f/~tND;3d73-91e0/tyf, PASS, EthernetMac Ipv4 /examples/rip/simpletest/, -f omnetpp.ini -c IPv4 -r 0, 100s, e4b8-5591/tplx;eede-9ed7/~tNl;a16a-0e30/~tND;bac1-99b5/tyf, PASS, EthernetMac Ipv4 -/examples/rip/simpletest/, -f omnetpp.ini -c IPv6 -r 0, 100s, 86c3-66f0/tplx;ce03-6f52/~tNl;883f-6d71/tyf, PASS, EthernetMac +/examples/rip/simpletest/, -f omnetpp.ini -c IPv6 -r 0, 100s, ca72-7399/tplx;1c05-e326/~tNl;883f-6d71/tyf, PASS, EthernetMac /examples/rip/simpletest/, -f omnetpp.ini -c MultiIPv4 -r 0, 100s, 640c-b305/tplx;2dde-f981/~tNl;d7cc-b710/~tND;3d31-178a/tyf, PASS, EthernetMac Ipv4 /examples/rtp/multicast1/, -f omnetpp.ini -c General -r 0, 500s, 3b10-2c5c/tplx;b015-6f81/~tNl;5260-d4c2/~tND;d294-df5c/tyf, PASS, igmp Ipv4 diff --git a/tests/fingerprint/mipv6-refactoring.csv b/tests/fingerprint/mipv6-refactoring.csv index 4e8ebad4ab4..00217e59021 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, 8a43-2e1a/~tNlb, PASS, wireless EthernetMac -/examples/ipv6/mipv6/, -f omnetpp.ini -c RouteOptimizationTwoCNs -r 0, 60s, 8a20-d2eb/~tNlb, PASS, wireless EthernetMac -/examples/ipv6/mipv6roaming/, -f omnetpp.ini -c Roaming -r 0, 70s, bc7d-f706/~tNlb, PASS, wireless EthernetMac +/examples/ipv6/mipv6/, -f omnetpp.ini -c Handover -r 0, 70s, 1a18-5b6e/~tNlb, PASS, wireless EthernetMac +/examples/ipv6/mipv6/, -f omnetpp.ini -c RouteOptimizationTwoCNs -r 0, 60s, e9ac-1767/~tNlb, PASS, wireless EthernetMac +/examples/ipv6/mipv6roaming/, -f omnetpp.ini -c Roaming -r 0, 70s, 6b12-cb8a/~tNlb, PASS, wireless EthernetMac # IPv6 examples # MLD example — new PASS row; ~tNl locks the MLD Report/Query/Done/MAS-Query packet exchange (traffic+lengths); @@ -18,7 +18,7 @@ # causes parsimPack() to abort — use ~tNl (no parsim serialization) instead; tyf excluded as unreliable /examples/ipv6/mld/, -f omnetpp.ini -c MldDemo -r 0, 30s, f1b1-b523/~tNl, PASS, EthernetMac MLD /examples/ipv6/mld/, -f omnetpp.ini -c MldV2Ssm -r 0, 30s, a22a-81c9/~tNl, PASS, EthernetMac MLD -/examples/ipv6/nclients/, -f omnetpp.ini -c ETH -r 0, 1000s, 50c9-9bb3/~tNlb, PASS, EthernetMac +/examples/ipv6/nclients/, -f omnetpp.ini -c ETH -r 0, 1000s, 01b2-59f7/~tNlb, PASS, EthernetMac /examples/ipv6/nclients/, -f omnetpp.ini -c PPP -r 0, 1000s, 0e0c-b800/~tNlb, PASS, /examples/ipv6/nclients/, -f omnetpp.ini -c PPP_SCTP -r 0, 100s, 3a7c-924c/~tNlb, PASS, diff --git a/tests/module/IPv6_nd_unicast_mac.test b/tests/module/IPv6_nd_unicast_mac.test new file mode 100644 index 00000000000..4c5c85a04c8 --- /dev/null +++ b/tests/module/IPv6_nd_unicast_mac.test @@ -0,0 +1,96 @@ +%description: +Tests that a locally-originated IPv6 unicast datagram sent out on a pinned +output interface takes the next hop's Ethernet address from the Neighbour +Cache, instead of the Ethernet broadcast address (FF:FF:FF:FF:FF:FF). + +Every Neighbour Discovery message pins its output interface, so the defect +was visible on both the solicited Neighbour Advertisement and the unicast +Neighbour Solicitation that Neighbour Unreachability Detection sends. + +RFC 4861 Section 5.2: Once the IP address of the next-hop node is known, +the sender examines the Neighbor Cache for link-layer information about +that neighbor. + +RFC 4861 Section 7.2.4: Otherwise, the node MUST set the Solicited flag to +one and unicast the advertisement to the Source Address of the solicitation. + +Topology: a router and three hosts on one switched Ethernet link. H1 sends +UDP to H2, so address resolution has to run and H2 has to answer with a +solicited Neighbour Advertisement. The run is long enough for Neighbour +Unreachability Detection to probe as well. + +An IPv6-only Ethernet link carries multicast and unicast frames only, so no +frame in this simulation may be addressed to the broadcast address. + +%#-------------------------------------------------------------------------------------------------------------- +%file: test.ned +import inet.networklayer.configurator.ipv6.Ipv6FlatNetworkConfigurator; +import inet.node.ethernet.EthernetSwitch; +import inet.node.ipv6.Router6; +import inet.node.ipv6.StandardHost6; +import ned.DatarateChannel; + +network NdUnicastMacTestNetwork +{ + types: + channel ethline extends DatarateChannel + { + delay = 0.1us; + datarate = 10Mbps; + } + submodules: + configurator: Ipv6FlatNetworkConfigurator; + switch1: EthernetSwitch; + R1: Router6; + H1: StandardHost6; + H2: StandardHost6; + H3: StandardHost6; + connections: + H1.ethg++ <--> ethline <--> switch1.ethg++; + H2.ethg++ <--> ethline <--> switch1.ethg++; + H3.ethg++ <--> ethline <--> switch1.ethg++; + R1.ethg++ <--> ethline <--> switch1.ethg++; +} +%#-------------------------------------------------------------------------------------------------------------- +%inifile: omnetpp.ini +[General] +record-vector-results = false +ned-path = ../../../../src +network = NdUnicastMacTestNetwork +sim-time-limit = 120s +cpu-time-limit = 60s +cmdenv-express-mode = false +cmdenv-log-prefix = "%C: " + +# Ethernet NIC configuration +**.eth[*].queue.typename = "EthernetQosQueue" +**.eth[*].queue.dataQueue.typename = "DropTailQueue" +**.eth[*].queue.dataQueue.packetCapacity = 10 + +# H1 sends UDP to H2 on the same link, so address resolution has to run +*.H1.numApps = 1 +*.H1.app[0].typename = "UdpBasicApp" +*.H1.app[0].destAddresses = "H2(ipv6)" +*.H1.app[0].destPort = 5000 +*.H1.app[0].messageLength = 100B +*.H1.app[0].sendInterval = 1s +*.H1.app[0].startTime = 5s + +*.H2.numApps = 1 +*.H2.app[0].typename = "UdpSink" +*.H2.app[0].localPort = 5000 + +%#-------------------------------------------------------------------------------------------------------------- +%subst: /omnetpp::// +%subst: /\x1B\[[0-9;]*m// +%#-------------------------------------------------------------------------------------------------------------- +%contains: stdout +received 115 packets +%#-------------------------------------------------------------------------------------------------------------- +%not-contains: stdout +dest = FF-FF-FF-FF-FF-FF +%#-------------------------------------------------------------------------------------------------------------- +%postrun-command: grep "undisposed object:" test.out > test_undisposed.out || true +%not-contains: test_undisposed.out +undisposed object: ( +%#-------------------------------------------------------------------------------------------------------------- diff --git a/tests/module/MIPv6_signaling_unicast_mac.test b/tests/module/MIPv6_signaling_unicast_mac.test new file mode 100644 index 00000000000..d9f0397a938 --- /dev/null +++ b/tests/module/MIPv6_signaling_unicast_mac.test @@ -0,0 +1,133 @@ +%description: +Tests that the mobility messages Mobile IPv6 sends with a pinned output interface +are addressed to the link-layer address of their next hop, not to the broadcast +address FF-FF-FF-FF-FF-FF. + +Mipv6 pins the output interface of the Binding Update, the Care-of Test Init and +the Binding Acknowledgement. A pinned interface makes the Ipv6 module skip +next-hop determination, so Mipv6 states the next hop itself: the next hop of the +longest matching route through the pinned interface. + +RFC 4861 Section 5.2: Once the IP address of the next-hop node is known, the +sender examines the Neighbor Cache for link-layer information about that +neighbor. + +The mobile node moves from its home link to the foreign link and back, so it +sends a home registration, return routability and a Binding Update to the +correspondent node from the foreign link, and the de-registrations from the home +link. On the foreign link the next hop of every message to a global address is +the access router; a broadcast frame would be relayed back into the cell by the +access point. + +%#-------------------------------------------------------------------------------------------------------------- +%inifile: omnetpp.ini +[General] +record-vector-results = false +# log the frames as they are queued for transmission, with their link-layer addresses +**.MN[0].wlan[0].mac.dcf.channelAccess.pendingQueue.cmdenv-log-level = trace +**.Home_Agent.eth[*].queue.dataQueue.cmdenv-log-level = trace +**.CN[0].eth[0].queue.dataQueue.cmdenv-log-level = trace +**.mipv6.cmdenv-log-level = trace +**.cmdenv-log-level = off +cmdenv-event-banners = false +ned-path = .;../../../../src;../../lib +network = inet.test.moduletest.lib.Mipv6Network +sim-time-limit = 60s +cmdenv-express-mode = false +cmdenv-log-prefix = "%C: " +num-rngs = 3 +seed-set = 1 +**.mobility.rng-0 = 2 + +*.total_mn = 1 +*.total_cn = 1 + +# realistic Router Advertisement intervals; movement is detected from a Router +# Solicitation sent on each L2 (re)association (default detectL2Movement) +**.neighbourDiscovery.minIntervalBetweenRAs = 3s +**.neighbourDiscovery.maxIntervalBetweenRAs = 7s + +*.radioMedium.mediumLimitCache.maxTransmissionPower = 2.0mW +*.radioMedium.mediumLimitCache.minReceptionPower = -82dBm +*.radioMedium.mediumLimitCache.minInterferencePower = -82dBm + +**.wlan*.mgmt.numAuthSteps = 4 +**.AP*.wlan*.mgmt.beaconInterval = 0.1s +**.AP_Home.wlan*.mgmt.ssid = "HOME" +**.AP_Home.wlan*.address = "10:AA:00:00:00:01" +**.AP_Home.eth[0].address = "10:AE:00:00:00:02" +**.AP_Home.eth[0].duplexMode = true +**.AP_1.wlan*.mgmt.ssid = "AP1" +**.AP_1.wlan*.address = "10:AA:00:00:A1:01" +**.AP_1.eth[0].address = "10:AE:00:00:A1:02" +**.AP_1.eth[0].duplexMode = true + +# the MN dwells at home, dashes to the foreign network, dwells there, then returns +# home and stays, so it also sends the de-registrations from the home link +**.mobility.constraintAreaMinZ = 0m +**.mobility.constraintAreaMaxZ = 0m +**.MN[0].mobility.typename = "TurtleMobility" +**.MN[0].mobility.turtleScript = xml("") +**.MN*.mobility.updateInterval = 0.1s + +# the correspondent node pings the MN's home address throughout +**.MN*.numApps = 0 +**.CN*.numApps = 1 +**.CN[0].app[0].typename = "PingApp" +**.CN[0].app[0].destAddr = "aaaa:0:66:0:8aa:ff:fe00:8" +**.CN[0].app[0].packetSize = 56B +**.CN[0].app[0].sendInterval = 0.5s +**.CN[0].app[0].startTime = 1s +**.CN[0].app[0].hopLimit = 32 +**.CN[0].app[0].printPing = true + +**.forwarding = false +**.eth[*].queue.typename = "EthernetQosQueue" +**.eth[*].queue.dataQueue.typename = "DropTailQueue" +**.eth[*].queue.dataQueue.packetCapacity = 10 +**.eth*.duplexMode = true +**.analogModel.ignorePartialInterference = true +**.AP_Home.wlan*.radio.channelNumber = 1 +**.AP_1.wlan*.radio.channelNumber = 2 +**.MN*.wlan*.radio.channelNumber = 0 +**.wlan*.agent.activeScan = true +**.wlan*.agent.defaultSsid = "" +**.wlan*.agent.channelsToScan = "1 2" +**.wlan*.agent.probeDelay = 0.1s +**.wlan*.agent.minChannelTime = 0.15s +**.wlan*.agent.maxChannelTime = 0.3s +**.wlan*.agent.authenticationTimeout = 5s +**.wlan*.agent.associationTimeout = 5s +**.wlan*.bitrate = 2Mbps +**.wlan*.mac.dcf.channelAccess.cwMin = 7 +**.radio.transmitter.power = 2.0mW +**.constraintAreaMinX = 0m +**.constraintAreaMinY = 0m +**.constraintAreaMaxX = 850m +**.constraintAreaMaxY = 850m + +%#-------------------------------------------------------------------------------------------------------------- +%subst: /omnetpp::// +%subst: /\x1B\[[0-9;]*m// +%#-------------------------------------------------------------------------------------------------------------- +%# the scenario covers registration, route optimization and de-registration +%contains: stdout +Mipv6Network.MN[0].ipv6.mipv6: Message recognised as CARE-OF TEST (CoT) +%#-------------------------------------------------------------------------------------------------------------- +%contains: stdout +Mipv6Network.CN[0].ipv6.mipv6: Deregistered binding +%#-------------------------------------------------------------------------------------------------------------- +%# the mobile node sends its Binding Update to the access router on the foreign link +%contains-regex: stdout +pendingQueue: Pushing packet, packet = \(Packet\)Binding Update [^\n]*receiverAddress = 10-AA-00-00-A1-01[^\n]*address3 = 0A-AA-00-00-00-04 +%#-------------------------------------------------------------------------------------------------------------- +%# no mobility message to a global address goes out as a link-layer broadcast (the mobile +%# node also sends a Care-of Test Init to the home agent's link-local address from the +%# foreign link, which has no neighbour to address) +%not-contains-regex: stdout +Pushing packet, packet = \(Packet\)(Binding Update|Binding Acknowledgement|CoTI|HoTI|CoT|HoT) [^\n]*(address3|dest) = FF-FF-FF-FF-FF-FF[^\n]*destinationAddress = (?!fe80:) +%#-------------------------------------------------------------------------------------------------------------- +%postrun-command: grep "undisposed object:" test.out > test_undisposed.out || true +%not-contains: test_undisposed.out +undisposed object: ( +%#--------------------------------------------------------------------------------------------------------------