Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 30 additions & 20 deletions src/inet/networklayer/icmpv6/Ipv6NeighbourDiscovery.cc
Original file line number Diff line number Diff line change
Expand Up @@ -897,7 +897,18 @@ void Ipv6NeighbourDiscovery::makeTentativeAddressPermanent(const Ipv6Address& te
ie->getProtocolDataForUpdate<Ipv6InterfaceData>()->setDadInProgress(false);

if (!tentativeAddr.isLinkLocal()) {
// DAD completed for a global address -- nothing else to do
// DAD completed for a global address. When it is the care-of address formed at a
// handover, the mobile node may now register it with its home agent: until this
// point its uniqueness on the visited link was unverified (RFC 4862 Section 5.4).
auto git = dadGlobalList.find(ie->getInterfaceId());
if (git != dadGlobalList.end() && git->second.addr == tentativeAddr) {
[[maybe_unused]] bool homeNetwork = git->second.hFlag;
dadGlobalList.erase(git);
#ifdef INET_WITH_MIPV6
if (rt6->isMobileNode() && !homeNetwork) // if we are not in the home network, send BUs
mipv6->initiateMipv6Protocol(ie, tentativeAddr);
#endif
}
return;
}

Expand All @@ -908,32 +919,31 @@ void Ipv6NeighbourDiscovery::makeTentativeAddressPermanent(const Ipv6Address& te
if (it != dadGlobalList.end()) {
DadGlobalEntry& entry = it->second;

ie->getProtocolDataForUpdate<Ipv6InterfaceData>()->assignAddress(entry.addr, false, simTime() + entry.validLifetime,
// Clear the tentative flag on the addresses that were already on the interface when
// the Router Advertisement arrived: the link-local address whose DAD just completed,
// and the home address. This has to happen before the address formed from the new
// prefix is added below, because that address has not been verified yet.
for (int i = 0; i < ie->getProtocolData<Ipv6InterfaceData>()->getNumAddresses(); i++) {
Ipv6Address addr = ie->getProtocolData<Ipv6InterfaceData>()->getAddress(i);
ie->getProtocolDataForUpdate<Ipv6InterfaceData>()->permanentlyAssign(addr);
}

// RFC 4862 Section 5.4 requires DAD on every unicast address, so the care-of address
// formed from the new prefix is assigned as tentative; the loop at the end of this
// function starts DAD for it. The MIPv6 registration is not started here but when
// that DAD completes (see above), so no Binding Update can advertise an address
// whose uniqueness on the visited link is still unverified.
ie->getProtocolDataForUpdate<Ipv6InterfaceData>()->assignAddress(entry.addr, true, simTime() + entry.validLifetime,
simTime() + entry.preferredLifetime, entry.hFlag);

// moved from processRAPrefixInfoForAddrAutoConf()
// we can remove the old CoA now
if (!entry.CoA.isUnspecified())
ie->getProtocolDataForUpdate<Ipv6InterfaceData>()->removeAddress(entry.CoA);

// set addresses on this interface to tentative=false
for (int i = 0; i < ie->getProtocolData<Ipv6InterfaceData>()->getNumAddresses(); i++) {
// TODO improve this code so that only addresses are permanently assigned
// which are formed based on the new prefix from the RA
Ipv6Address addr = ie->getProtocolData<Ipv6InterfaceData>()->getAddress(i);
ie->getProtocolDataForUpdate<Ipv6InterfaceData>()->permanentlyAssign(addr);
}

#ifdef INET_WITH_MIPV6
// if we have MIPv6 protocols on this node we will eventually have to
// call some appropriate methods
if (rt6->isMobileNode()) {
if (entry.hFlag == false) // if we are not in the home network, send BUs
mipv6->initiateMipv6Protocol(ie, tentativeAddr);
}
#endif

dadGlobalList.erase(it->first);
// The MIPv6 protocol is initiated once the care-of address assigned above has
// passed DAD; the dadGlobalList entry is kept until then. dadHasFailed() drops
// it, so a care-of address that is already in use is never registered.
}

// Assign global scope addresses to routers. The Ipv6FlatNetworkConfigurator assigns
Expand Down
6 changes: 3 additions & 3 deletions tests/fingerprint/examples.csv
Original file line number Diff line number Diff line change
Expand Up @@ -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, 6204-6190/tplx;68f4-68c6/~tNl;76af-99d1/~tND;44ef-1a45/tyf, PASS, wireless EthernetMac
/examples/ipv6/mipv6/, -f omnetpp.ini -c RouteOptimizationTwoCNs -r 0, 60s, 9faf-b8a8/tplx;f076-4454/~tNl;582f-fb5e/~tND;ed3e-17fa/tyf, PASS, wireless EthernetMac
/examples/ipv6/mipv6roaming/, -f omnetpp.ini -c Roaming -r 0, 70s, 4ab1-dea8/tplx;9d55-36d4/~tNl;1f90-d7bf/~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,
Expand Down
6 changes: 3 additions & 3 deletions tests/fingerprint/mipv6-refactoring.csv
Original file line number Diff line number Diff line change
Expand Up @@ -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, c8dc-27c2/~tNlb, PASS, wireless EthernetMac
/examples/ipv6/mipv6/, -f omnetpp.ini -c Handover -r 0, 70s, dfed-b54a/~tNlb, PASS, wireless EthernetMac
/examples/ipv6/mipv6/, -f omnetpp.ini -c RouteOptimizationTwoCNs -r 0, 60s, ab29-ae3f/~tNlb, PASS, wireless EthernetMac
/examples/ipv6/mipv6roaming/, -f omnetpp.ini -c Roaming -r 0, 70s, 2b0b-fa1a/~tNlb, PASS, wireless EthernetMac

# IPv6 examples
# MLD example — new PASS row; ~tNl locks the MLD Report/Query/Done/MAS-Query packet exchange (traffic+lengths);
Expand Down
134 changes: 134 additions & 0 deletions tests/module/MIPv6_care_of_address_DAD.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
%description:
Tests that a care-of address formed at a handover undergoes Duplicate Address
Detection (DAD) before it is used, as required by RFC 4862 Section 5.4, and that
the Mobile Node does not register it with its Home Agent until that DAD passes.

The Mobile Node boots on its home link (where it has only a link-local address,
so the home address is verified through the single-address path), then moves to
the foreign network. On arrival its interface already holds a link-local address
and the home address, so address autoconfiguration takes the multi-address path.
Before this test was added, that path assigned the care-of address as permanent
and started no DAD for it, and the Binding Update advertised an address whose
uniqueness on the visited link had never been tested.

%#--------------------------------------------------------------------------------------------------------------
%inifile: omnetpp.ini
[General]
record-vector-results = false
**.neighbourDiscovery.cmdenv-log-level = trace
**.mipv6.cmdenv-log-level = trace
**.app[*].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

# number of MNs and CNs
*.total_mn = 1
*.total_cn = 1

**.neighbourDiscovery.minIntervalBetweenRAs = 0.03s
**.neighbourDiscovery.maxIntervalBetweenRAs = 0.07s
**.neighbourDiscovery.detectL2Movement = false # legacy: detect movement from periodic RAs only

# channel physical parameters
*.radioMedium.mediumLimitCache.maxTransmissionPower = 2.0mW
*.radioMedium.mediumLimitCache.minReceptionPower = -82dBm
*.radioMedium.mediumLimitCache.minInterferencePower = -82dBm

# access point
**.wlan*.mgmt.numAuthSteps = 4

# ALL APs common parameters
**.AP*.wlan*.mgmt.beaconInterval = 0.1s

# Access Point parameters
**.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

# mobility
**.mobility.constraintAreaMinZ = 0m
**.mobility.constraintAreaMaxZ = 0m

**.MN[0].mobility.typename = "RectangleMobility"
**.MN[0].mobility.constraintAreaMinX = 180m
**.MN[0].mobility.constraintAreaMinY = 170m
**.MN[0].mobility.constraintAreaMaxX = 630m
**.MN[0].mobility.constraintAreaMaxY = 180m
**.MN[0].mobility.startPos = 0
**.MN[0].mobility.speed = 10mps
**.MN*.mobility.updateInterval = 0.1s

# No apps needed - we just test the handover signaling
**.MN*.numApps = 0
**.CN*.numApps = 0

# ip settings
**.forwarding = false

# Ethernet NIC configuration
**.eth[*].queue.typename = "EthernetQosQueue"
**.eth[*].queue.dataQueue.typename = "DropTailQueue"
**.eth[*].queue.dataQueue.packetCapacity = 10
**.eth*.duplexMode = true

# analog model
**.analogModel.ignorePartialInterference = true

# wireless channels
**.AP_Home.wlan*.radio.channelNumber = 1
**.AP_1.wlan*.radio.channelNumber = 2
**.MN*.wlan*.radio.channelNumber = 0

# wireless configuration
**.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

# nic settings
**.wlan*.bitrate = 2Mbps
**.wlan*.mac.dcf.channelAccess.cwMin = 7
**.radio.transmitter.power = 2.0mW

**.constraintAreaMinX = 0m
**.constraintAreaMinY = 0m
**.constraintAreaMaxX = 850m
**.constraintAreaMaxY = 850m

%#--------------------------------------------------------------------------------------------------------------
%subst: /omnetpp:://
%#--------------------------------------------------------------------------------------------------------------
%contains: stdout
Mipv6Network.MN[0].ipv6.neighbourDiscovery: Starting DAD for tentative global address aaaa:1:66:0:8aa:ff:fe00:8
%#--------------------------------------------------------------------------------------------------------------
%contains: stdout
Mipv6Network.MN[0].ipv6.neighbourDiscovery: DAD completed for address aaaa:1:66:0:8aa:ff:fe00:8 on wlan0, address is unique
%#--------------------------------------------------------------------------------------------------------------
%contains: stdout
Mipv6Network.MN[0].ipv6.mipv6: Initiating Mobile Ipv6 protocol...
%#--------------------------------------------------------------------------------------------------------------
%contains: stdout
Mipv6Network.Home_Agent.ipv6.mipv6: BU validation passed
%#--------------------------------------------------------------------------------------------------------------
%postrun-command: grep "undisposed object:" test.out > test_undisposed.out || true
%not-contains: test_undisposed.out
undisposed object: (
%#--------------------------------------------------------------------------------------------------------------