Summary
A router interface ends up holding two entries for the same global unicast address: one from
Ipv6NetworkConfigurator, one from Ipv6NeighbourDiscovery.
src/inet/networklayer/icmpv6/Ipv6NeighbourDiscovery.cc:940 forms a global address from every
advertised prefix of a router interface once the interface's link-local address has passed
Duplicate Address Detection (DAD), and assigns it unconditionally:
// Assign global scope addresses to routers. The Ipv6FlatNetworkConfigurator assigns
// a 64 bit prefix to the routers but for Mipv6 operation, we need full 128bit global
// scope address for routers.
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);
}
}
With Ipv6NetworkConfigurator the interface already holds that address: the configurator derives
it from the same prefix and the same interface identifier at
Ipv6NetworkConfigurator.cc:172. Ipv6InterfaceData::assignAddress()
(src/inet/networklayer/ipv6/Ipv6InterfaceData.cc:293) appends to the address vector without
checking whether the address is already there, so the second assignment adds a duplicate entry.
The comment names Ipv6FlatNetworkConfigurator, and that is still accurate: the flat configurator
assigns advertised prefixes and a link-local address but no global address, so the block is still
needed for it. The duplicate appears only with the newer Ipv6NetworkConfigurator.
What the module contract says
Ipv6InterfaceData models an interface's address list, and getNumAddresses(),
getAddress(int), findAddress(), hasAddress() and permanentlyAssign() all read it as a set
of distinct addresses. findAddress() returns the index of the first match:
int Ipv6InterfaceData::findAddress(const Ipv6Address& addr) const
{
for (AddressDataVector::const_iterator it = addresses.begin(); it != addresses.end(); it++)
if (it->address == addr)
return it - addresses.begin();
return -1;
}
so permanentlyAssign() and isTentativeAddress() operate on one of the two entries and leave the
other untouched. Ipv6NetworkConfigurator.cc:171 guards its own assignment with
if (!ipv6Data->hasAddress(...)), which shows the intended invariant; the Neighbour Discovery
site has no such guard.
Why it matters
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
router1's eth0 reports its global address twice:
interfaceIpv6ConfigChanged eth0 ID:101 ... Ipv6:{
Addrs:2001:db8:0:1:8aa:ff:fe00:3(global) expiryTime: inf prefExpiryTime: inf
, 2001:db8:0:1:8aa:ff:fe00:3(global) expiryTime: inf prefExpiryTime: inf
, fe80::8aa:ff:fe00:3(link) expiryTime: inf prefExpiryTime: inf
All six router interfaces in that network show it. Today the consequences are cosmetic and
statistical -- a duplicated line in every interface dump and an inflated getNumAddresses() --
because both entries carry the same flags. They stop being cosmetic as soon as the two entries can
differ, which is what #1171 does: it makes the configured address tentative, and then the
interface holds the same address once tentative and once permanent, with the address predicates
answering for whichever entry happens to come first.
Relationship to #1171
This one is the prerequisite. Fixing it alone is a complete, self-contained improvement and changes
no fingerprint. Fixing #1171 alone is not shippable, for the reason above.
Summary
A router interface ends up holding two entries for the same global unicast address: one from
Ipv6NetworkConfigurator, one fromIpv6NeighbourDiscovery.src/inet/networklayer/icmpv6/Ipv6NeighbourDiscovery.cc:940forms a global address from everyadvertised prefix of a router interface once the interface's link-local address has passed
Duplicate Address Detection (DAD), and assigns it unconditionally:
With
Ipv6NetworkConfiguratorthe interface already holds that address: the configurator derivesit from the same prefix and the same interface identifier at
Ipv6NetworkConfigurator.cc:172.Ipv6InterfaceData::assignAddress()(
src/inet/networklayer/ipv6/Ipv6InterfaceData.cc:293) appends to the address vector withoutchecking whether the address is already there, so the second assignment adds a duplicate entry.
The comment names
Ipv6FlatNetworkConfigurator, and that is still accurate: the flat configuratorassigns advertised prefixes and a link-local address but no global address, so the block is still
needed for it. The duplicate appears only with the newer
Ipv6NetworkConfigurator.What the module contract says
Ipv6InterfaceDatamodels an interface's address list, andgetNumAddresses(),getAddress(int),findAddress(),hasAddress()andpermanentlyAssign()all read it as a setof distinct addresses.
findAddress()returns the index of the first match:so
permanentlyAssign()andisTentativeAddress()operate on one of the two entries and leave theother untouched.
Ipv6NetworkConfigurator.cc:171guards its own assignment withif (!ipv6Data->hasAddress(...)), which shows the intended invariant; the Neighbour Discoverysite has no such guard.
Why it matters
examples/ipv6/ipv6configurator -c Defaultonorigin/master(7aef79d), release mode:router1'seth0reports its global address twice:All six router interfaces in that network show it. Today the consequences are cosmetic and
statistical -- a duplicated line in every interface dump and an inflated
getNumAddresses()--because both entries carry the same flags. They stop being cosmetic as soon as the two entries can
differ, which is what #1171 does: it makes the configured address tentative, and then the
interface holds the same address once tentative and once permanent, with the address predicates
answering for whichever entry happens to come first.
Relationship to #1171
This one is the prerequisite. Fixing it alone is a complete, self-contained improvement and changes
no fingerprint. Fixing #1171 alone is not shippable, for the reason above.