Skip to content

mipv6: verify the home address before acknowledging a home registration - #1195

Open
adamgeorge309 wants to merge 2 commits into
masterfrom
topic/gy/mipv6-ha-dad
Open

mipv6: verify the home address before acknowledging a home registration#1195
adamgeorge309 wants to merge 2 commits into
masterfrom
topic/gy/mipv6-ha-dad

Conversation

@adamgeorge309

Copy link
Copy Markdown
Contributor

Fixes #1194.

A home agent now runs real Duplicate Address Detection for the mobile node's home address on the
home link before it acknowledges a first home registration, as RFC 6275 Section 10.3.1 requires,
instead of standing a hardcoded one-second delay in for the check. It also rejects the
registration with status 134 when the address turns out to be in use, which was a bare // TODO.

The two commits

ipv6: add an address probe to Neighbour Discovery adds the capability and nothing else.
Ipv6NeighbourDiscovery could previously run Duplicate Address Detection only for an address it
was about to assign: initiateDad() puts the address on the interface, and
makeTentativeAddressPermanent() keeps it there on success. A home agent needs the opposite --
it must check an address it must not take, because Ipv6InterfaceData::hasAddress() answers
true for a tentative address too, so assigning the home address would make the home agent start
accepting the mobile node's packets and destroy the interception the tunnel depends on.

startAddressProbe() sends the RFC 4862 Section 5.4.2 solicitations without touching the
interface and reports the outcome through the new IAddressProbeHandler.

The random Section 5.4.2 term delays the first solicitation here, rather than being added to
the timeout as initiateDad() does. The join must precede the solicitation, so delaying the join
delays the solicitation with it; adding it to the timeout is #1179, which #1183 repairs for
initiateDad(). The total wait is the same either way, so this only decides when the
solicitation leaves -- but a new probe should not be written with the defect in it. If #1183
lands first there is nothing to reconcile; if this lands first, #1183 brings initiateDad() to
the same shape.

mipv6: verify the home address before acknowledging a home registration uses it, and
carries the baseline it moves.

Architecture

IAddressProbeHandler is a new contract, in its own header so that mipv6 can implement it
without icmpv6 gaining any dependency on mipv6. Nothing else in the surface changes: no NED
file, no .msg file, no packet content, no configuration parameter, no signal. DAD_FAILED = 134
already existed in MobilityHeader.msg. No sealed path is touched, and check-architecture.sh
flags nothing in icmpv6/ or mipv6/.

One deliberate deletion: with no caller left passing a delay, the sendTime parameter of
createAndSendBAMessage() and sendMobilityMessageToIPv6Module() and the sendDelayed() branch
it fed are removed, along with the // TODO solve the HA DAD problem in a different way that sat
on them. That TODO was a claim, and this makes good on it; leaving it would describe a mechanism
the change had just deleted.

What changes in behaviour

before after
acknowledgement delay, first home registration 1.0015 s on every seed 1.036 / 1.451 / 1.911 s for seed sets 1-3
acknowledgement delay, re-registration 0.0017 s 0.0017 s (unchanged)
acknowledgement delay, correspondent binding (H=0) at a home agent 1 s immediate
Neighbor Solicitations for the home address none, ever one probe per first home registration
Binding Acknowledgements per first home registration 2 1
status 134 unreachable sent, binding withdrawn

The delay varies now because Duplicate Address Detection genuinely costs retransTimer plus the
uniform 0-1 s group-join term of RFC 4862 Section 5.4.2.

The double acknowledgement is gone because a registration still waiting for its probe is no longer
treated as a binding the home agent already has. Previously the mobile node's retransmission
arrived after the Binding Cache entry existed, was read as a re-registration, and was acknowledged
immediately on top of the delayed acknowledgement owed to the original.

The third row is a change master made by accident: it delayed every first-time Binding Update a
home agent received, including one with the home registration flag clear. RFC 6275 Section 9.5.4
asks for no Duplicate Address Detection on a correspondent binding, so the guard is now on
homeRegistration as well.

The mobile node still retransmits its first Binding Update on every seed, because the probe
costs retransTimer (1 s) plus a non-negative term while its own first-registration timeout is
1 s (#1132, #1133). It is acknowledged once either way. Whether #1134's 1.5 s changes that has not
been measured here and is not claimed.

Baselines

Three rows move, all in examples.csv, and they share one explanation: mipv6 Handover,
mipv6 RouteOptimizationTwoCNs and mipv6roaming Roaming are the only scenarios in the suite
where a home agent accepts a first home registration. In each, the tplx, ~tNl and ~tND
values move because the acknowledgement now waits for a real probe instead of a constant, because
the home agent's probe solicitations are new packets on the home link, and because the duplicate
acknowledgement is gone.

Ingredient letters, verified against omnetpp/include/omnetpp/cfingerprint.h and
src/inet/common/FingerprintCalculator.h: ~ network-communication filter, t simulation time,
N network node path, l message bit length, D packet data, p module full path, x extra
data. r (random numbers drawn) appears in none of these specs, so the added uniform() draw is
not hashed directly; only its effect on packet timing is.

No other row moves. The 13 other IPv6 rows matched in examples.csv are unchanged:
ipv6/pmipv6 General, pim/sm_ipv6, pim/dm_ipv6, pim/ssm_ipv6, inet/ipsec
UDPTraffic6/TCPTraffic6/Multicast6, inet/udpclientserver
udp_OK_ipv6/udp_Port_Unav_ipv6/udp_Host_Unav_ipv6, and ipv6/nclients ETH/PPP/
PPP_SCTP. pmipv6 matters most of those: it shares the same Ipv6NeighbourDiscovery and is
untouched. The new code is inert unless a home agent accepts a first home registration.

mipv6-refactoring.csv is deliberately not touched. Its three MIPv6 rows already fail on
origin/master 021485b99c -- confirmed by building and running that commit unchanged, which
produces ad4c-9f8c, 2402-9a6f and 464c-536f against recorded values of aa29-a8c5,
068b-23aa and 7ed8-bee3. The recent IEEE 802.11 and serializer work moved them and re-recorded
examples.csv without them. Re-recording them here would fold that unrelated movement into this
commit, which is exactly what TR-BASELINE-PROVENANCE forbids. They want a separate refresh from
whoever landed that work.

The tyf fingerprints are not re-recorded. They were already stale at the merge base -- the
untouched pmipv6 row fails tyf too -- and the tool itself reports them as not regularly kept
up to date. Since t is one of their ingredients, this change does move them; they are simply not
tracked.

How this was verified

From the repository root, with source setenv, on origin/master 021485b99c:

cd tests/fingerprint
./fingerprinttest -s -F tyf -m 'ipv6|mipv6' examples.csv     # Ran 16 tests ... OK

cd ../module
inet_run_module_tests -m release -f '(IPv6|Ipv6|MIPv6).*'    # 44 TOTAL, 42 PASS, 2 FAIL
  • Before: 42 total, 40 pass, 2 fail.
  • After: 44 total, 42 pass, 2 fail.

The two failures are MIPv6_tcp_handover and IPv6_packet_too_big, both already failing on
origin/master before any change here, and neither file is touched by this branch. Every other
test keeps its verdict; the only difference in the verdict list is the two new tests.

The first commit was checked on its own, with the second stashed: at that commit
examples.csv passes 16/16 against the un-updated baseline and the module suite reproduces
42/40/2 exactly, which is what "adds the capability and nothing else" means.

Tests

MIPv6_home_agent_dad covers the success path: the home agent holds the acknowledgement,
Neighbour Discovery sends a real probe, nobody answers, the registration is acknowledged. It also
pins the acknowledgement count at exactly one, which is the assertion that would have caught the
double acknowledgement.

MIPv6_home_agent_dad_duplicate covers the rejection. Arranging a duplicate needs one trick worth
explaining: a node holding the home address from the start would defend it against the mobile
node's own autoconfiguration at boot, and the mobile node would never get a home address to
register. So a squatter on the home link carries the mobile node's MAC -- autoconfiguration then
derives the same address for both -- and Duplicate Address Detection is switched off on both so
that neither probes and neither defends while they boot. The home agent keeps it enabled, probes,
is answered, and rejects. The test asserts that no registration is ever accepted.

Both are separate files rather than assertions bolted onto MIPv6_handover, so that a failure
names which property broke.

A defect this makes reachable

MIPv6_home_agent_dad_duplicate exposes something that could not happen before, because status
134 could never be sent: the mobile node logs the rejection and then ignores it. processBAMessage
says so itself -- "retransmission is performed anyway as timers are not deleted", with a
// TODO store DO_NOT_SEND_BU in BUL. So it retries with the ordinary Binding Update backoff:
rejections at t=32.8, 33.8, 35.8, 39.8, 47.8 and 63.8 s, doubling to the 32 s cap and never giving
up. RFC 6275 Section 11.7.3 asks it to stop on a rejection status.

This is a separate defect on the mobile node's side and is not fixed here. It was previously
unreachable, and is worth its own issue.

What this does not do

The binding, its expiry timer and the home-agent tunnel are still installed when the Binding
Update is accepted, before the probe finishes, so for the 1-2 s the probe lasts the home agent is
already tunnelling for an address another node may own. RFC 6275 Section 10.3.1 places Duplicate
Address Detection before the acknowledgement, not before the cache entry, so this follows the
text; it is called out because it is a real window. On rejection all three are withdrawn.

A de-registration that overtakes a running probe cancels it and sends no acknowledgement for the
registration it withdrew. That is a choice, not something the RFC states.

The competing-probe case is deliberately not detected: another node running Duplicate Address
Detection for the same address sends its solicitation to the solicited-node multicast address of
that address, and two gates stop it -- Ipv6::routeMulticastPacket() delivers a multicast locally
only if the node holds the address or joined the group, and processNsPacket() then discards a
solicitation whose target the node does not hold. Writing that branch today would be unreachable
code. A proxying home agent passes both gates, so it belongs with the proxy Neighbor Discovery
work.

Mipv6::findHomeLinkInterface() duplicates the loop in Ipv6RoutingTable::isOnLinkAddress().
Companion work on proxy Neighbor Discovery extracts that loop as
Ipv6RoutingTable::findOnLinkInterface(); whichever lands second should fold one into the other.
Kept separate here so the two changes do not conflict.

Proxy Neighbor Discovery at the home agent (RFC 6275 Section 10.4.1) is out of scope and filed
separately. Section 10.3.1 governs what must happen before the acknowledgement goes out; Section
10.4.1 governs what must happen on the home link while the binding lives. Different triggers,
independently testable, independently revertible.

Ipv6NeighbourDiscovery could run Duplicate Address Detection only for an
address it was about to assign: initiateDad() puts the address on the
interface, and makeTentativeAddressPermanent() keeps it there when the probe
succeeds.

RFC 6275 Section 10.3.1 needs the other shape. Before a home agent accepts a
first home registration it must run Duplicate Address Detection for the mobile
node's home address on the home link -- an address it must not take for
itself, because Ipv6InterfaceData::hasAddress() answers true for a tentative
address as well, so assigning it would make the home agent start accepting
packets that belong to the mobile node.

Add startAddressProbe(), which sends the RFC 4862 Section 5.4.2 solicitations
without ever touching the interface and reports the outcome through the new
IAddressProbeHandler interface. cancelAddressProbe() abandons a probe, and
isAddressProbeRunning() lets a caller that holds state for the duration of one
notice a probe that ended without a callback -- stop() drops the probe list, so
the callback is promised at most once, not exactly once.

The random RFC 4862 Section 5.4.2 term delays the first solicitation, rather
than being added to the timeout as initiateDad() does. The join must precede
the solicitation, so delaying the join delays the solicitation with it; adding
it to the timeout instead is issue #1179, which pull request #1183 repairs for
initiateDad(). The total wait is the same either way, so this only decides when
the solicitation leaves, and a new probe should not be written with the defect
in it.

Probing an address this node already holds reports it in use rather than
asserting. That is the honest answer to the question the probe asks, and it is
the state a home agent will be in once it proxies the address.

A duplicate is reported when another node defends the address with a Neighbor
Advertisement, which arrives because a defending advertisement goes to the
all-nodes multicast address. The competing case -- another node running
Duplicate Address Detection for the same address at the same time -- is not
reported. That solicitation goes to the solicited-node multicast address of the
probed address, and two gates stop it: Ipv6::routeMulticastPacket() delivers a
multicast locally only if the node holds the address or joined the group, and
processNsPacket() then discards a solicitation whose target the node does not
hold. A proxying home agent passes both, so that case belongs with the proxy
Neighbor Discovery work.

There is no caller yet, so no behaviour changes and no baseline moves.
RFC 6275 Section 10.3.1:

  Unless this home agent already has a binding for the given home address, the
  home agent MUST perform Duplicate Address Detection on the mobile node's
  home link before returning the Binding Acknowledgement. ... If this
  Duplicate Address Detection fails for the given home address or an
  associated link local address, then the home agent MUST reject the complete
  Binding Update and MUST return a Binding Acknowledgement to the mobile node,
  in which the Status field is set to 134.

Neither half was implemented. The check was replaced by a hardcoded one second
delay on the acknowledgement, sendTime = existingBinding ? 0 : 1, carrying the
admission "TODO solve the HA DAD problem in a different way"; the rejection
path was a bare TODO, so status 134 could never be sent.

Reproduce the defect on the unfixed tree:

  cd examples/ipv6/mipv6
  inet -u Cmdenv -c Handover -r 0 --seed-set=1 --sim-time-limit=25s \
    --cmdenv-express-mode=false --cmdenv-log-level=off \
    '--*.Home_Agent.ipv6.neighbourDiscovery.cmdenv-log-level=trace' \
    '--*.Home_Agent.ipv6.mipv6.cmdenv-log-level=info'

The home agent logs Duplicate Address Detection exactly twice, both at
t=0.0436 s for its own two interfaces at boot, and never at t=21.712822 s when
the Binding Update arrives and is validated. No solicitation for the home
address is ever sent. The acknowledgement arrives 1.0015 s after the Binding
Update on every seed set: 1.001527, 1.001727 and 1.001587 s for sets 1 to 3,
one second of sendDelayed plus link latency.

Run the probe instead, and hold the acknowledgement until it ends: status 0
when nobody answers, status 134 with the binding, its tunnel and its expiry
timer withdrawn when another node defends the address. With no caller left
passing a delay, the sendTime parameter and the delayed-send branch it fed go
with it.

Three deltas in behaviour, all intended.

The acknowledgement delay now varies per seed, 1.036, 1.451 and 1.911 s for
seed sets 1 to 3, because real Duplicate Address Detection costs retransTimer
plus the RFC 4862 Section 5.4.2 group-join term. It was a constant standing in
for a quantity that genuinely has spread.

A first registration draws one Binding Acknowledgement instead of two. The
mobile node's retransmission -- its first-registration timeout is one second,
see issues #1132 and #1133 -- used to arrive after the Binding Cache entry
already existed, so it was read as a re-registration and acknowledged at once,
on top of the delayed acknowledgement owed to the original. A registration
still waiting for its probe is no longer a binding the home agent already has.

A home agent that receives a Binding Update with the home registration flag
clear now acknowledges it immediately rather than one second later. Master
delayed every first-time Binding Update a home agent saw; RFC 6275 Section
9.5.4 asks for no Duplicate Address Detection on a correspondent binding.

Three fingerprint rows move, all in examples.csv, and each for the same reason:
the mipv6 Handover, mipv6 RouteOptimizationTwoCNs and mipv6roaming Roaming
scenarios are the only ones in the suite where a home agent accepts a first
home registration. In each, the tplx, ~tNl and ~tND values move because the
acknowledgement now waits for a real probe instead of a constant, because the
home agent's probe solicitations are new packets on the home link, and because
the duplicate acknowledgement is gone. No other row moves: the remaining 13
IPv6 rows matched in examples.csv are unchanged, pmipv6 among them, which
shares the same Ipv6NeighbourDiscovery.

mipv6-refactoring.csv is deliberately not touched. Its three MIPv6 rows already
fail on origin/master 021485b, which was confirmed by building and running
that commit unchanged; the recent IEEE 802.11 and serializer work moved them
and re-recorded examples.csv without them. Re-recording them here would fold
that unrelated movement into this commit.

MIPv6_home_agent_dad covers the success path and pins the acknowledgement count
at one. MIPv6_home_agent_dad_duplicate covers the rejection: a squatter on the
home link carries the mobile node's MAC, so autoconfiguration gives them the
same home address, and Duplicate Address Detection is switched off on both so
that neither defends against the other while they boot. The home agent, which
keeps it on, then probes, is answered, and rejects.

That test also shows a limitation this change makes reachable: the mobile node
logs the rejection but does not act on it, so it retries with the ordinary
Binding Update backoff -- rejections at t=32.8, 33.8, 35.8, 39.8, 47.8, 63.8 s,
doubling to the 32 s cap and never giving up. RFC 6275 Section 11.7.3 asks it to
stop; the code says "retransmission is performed anyway as timers are not
deleted". That is a separate defect on the mobile node's side, previously
unreachable because status 134 could never be sent.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

mipv6: the home agent does not perform Duplicate Address Detection for the home address, a hardcoded 1 s delay stands in

1 participant