Skip to content

ipv6: a global address that was not autoconfigured is assigned without Duplicate Address Detection #1171

Description

@adamgeorge309

Summary

A statically configured global unicast IPv6 address is assigned to an interface permanently, in
one step, so Duplicate Address Detection (DAD) is never performed on it and a duplicate is never
found. Only link-local addresses and addresses formed by Stateless Address Autoconfiguration
(SLAAC) are checked.

Two sites assign a global unicast address with tentative = false:

src/inet/networklayer/configurator/ipv6/Ipv6NetworkConfigurator.cc:172 -- the configurator's
static assignment, applied to every router interface always and to every host interface as well
unless assignAddressesToHosts is turned off:

if (!ipv6Data->hasAddress(interfaceInfo->globalAddress)) {
    ipv6Data->assignAddress(interfaceInfo->globalAddress, false, SIMTIME_ZERO, SIMTIME_ZERO);
    EV_DETAIL << "  assigned global address " << ...;
}

src/inet/networklayer/icmpv6/Ipv6NeighbourDiscovery.cc:945 -- the router address formed from
each advertised prefix, assigned inside Neighbour Discovery after link-local Duplicate Address
Detection (DAD) completes:

if (rt6->isRouter() && !(ie->isLoopback())) {
    for (int i = 0; i < ie->getProtocolData<Ipv6InterfaceData>()->getNumAdvPrefixes(); i++) {
        Ipv6Address globalAddress = ie->getProtocolDataForUpdate<Ipv6InterfaceData>()->autoConfRouterGlobalScopeAddress(i);
        ie->getProtocolDataForUpdate<Ipv6InterfaceData>()->assignAddress(globalAddress, false, 0, 0);
    }
}

Ipv6NeighbourDiscovery::initiateDad() is reached only for an address that was assigned with
tentative = true, so neither address is probed.

For contrast, Ipv6RoutingTable.cc:265 assigns the link-local address with true, which is why
link-local Duplicate Address Detection (DAD) happens at all, and
Ipv6NeighbourDiscovery.cc:2568 assigns a SLAAC-derived global address with true and calls
initiateDad().

What the standard says

RFC 4862 Section 5.4:

Duplicate Address Detection MUST be performed on all unicast addresses prior to assigning them
to an interface, regardless of whether they are obtained through stateless autoconfiguration,
DHCPv6, or manual configuration, with the following exceptions:

  • An interface whose DupAddrDetectTransmits variable is set to zero does not perform Duplicate
    Address Detection.

  • Duplicate Address Detection MUST NOT be performed on anycast addresses [...]

  • Each individual unicast address SHOULD be tested for uniqueness. Note that there are
    implementations deployed that only perform Duplicate Address Detection for the link-local
    address and skip the test for the global address that uses the same interface identifier as
    that of the link-local address. Whereas this document does not invalidate such
    implementations, this kind of "optimization" is NOT RECOMMENDED, and new implementations MUST
    NOT do that optimization.

INET's behaviour is that "optimization", and it is not covered by the first exception: the
dupAddrDetectTransmits parameter of Ipv6NeighbourDiscovery defaults to 1, and the interfaces
in question do run Duplicate Address Detection (DAD) -- for their link-local address only.

The same section also states what "tentative" means, which is what an address assigned in one step
skips:

An address on which the Duplicate Address Detection procedure is applied is said to be tentative
until the procedure has completed successfully. A tentative address is not considered "assigned
to an interface" in the traditional sense.

Why it matters

Ipv6NetworkConfigurator.assignAddressesToHosts defaults to true, so this is the normal case,
not a corner case: in a default IPv6 network no node performs Duplicate Address Detection (DAD) on
a global address at all.

examples/ipv6/ipv6configurator -c Default on origin/master (7aef79d), release mode:

cd examples/ipv6/ipv6configurator
inet --release -u Cmdenv -c Default --sim-time-limit=15s \
     --cmdenv-express-mode=false --cmdenv-log-level=detail | grep "DAD completed"

Ten interfaces receive a configured global address. Ten DAD completed lines appear, all of them
for fe80:: link-local addresses, between t = 1.27 s and t = 2.65 s. Not one of the ten global
addresses appears.

Consequences:

  • A duplicate configured address goes undetected. A scenario that gives two nodes the same
    configured global address runs as if nothing were wrong, because no node ever sends a Neighbour
    Solicitation for that address.
  • The startDad and dadCompleted statistics under-count, in a default configuration by exactly
    the number of global addresses in the network.
  • A configured address is usable from t = 0 rather than after the check, so a node is reachable
    earlier than a conforming implementation would allow, and simulations that measure the cost of
    bringing an interface up are optimistic.

The behaviour is not a regression: it predates the current Neighbour Discovery work. Commit
adfe5ba71e ("IPv6 ND: implement DAD for autoconfigured global addresses (RFC 4862)") deliberately
covered only addresses formed by Stateless Address Autoconfiguration (SLAAC) and left configured
addresses as they were.

Relationship to #1170

They must be fixed together. Making the configured address tentative while
Ipv6NeighbourDiscovery.cc:945 still assigns the same address a second time would leave a router
interface holding one entry that is tentative and one that is permanent;
Ipv6InterfaceData::findAddress() returns the first match, so isTentativeAddress() and
permanentlyAssign() would then depend on the order of the address list. #1170 is the
load-bearing prerequisite and has to land first.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions