INET Framework for OMNeT++/OMNEST
inet::Ipv6NeighbourDiscovery Class Reference

Implements RFC 2461 Neighbor Discovery for Ipv6. More...

#include <Ipv6NeighbourDiscovery.h>

Inheritance diagram for inet::Ipv6NeighbourDiscovery:
inet::LifecycleUnsupported inet::ILifecycle

Classes

struct  AdvIfEntry
 
struct  DadEntry
 
struct  RdEntry
 

Public Types

typedef std::vector< Packet * > MsgPtrVector
 
typedef Ipv6NeighbourCache::Key Key
 
typedef Ipv6NeighbourCache::Neighbour Neighbour
 
typedef Ipv6NeighbourCache::DefaultRouterList DefaultRouterList
 

Public Member Functions

 Ipv6NeighbourDiscovery ()
 
virtual ~Ipv6NeighbourDiscovery ()
 
const MacAddressresolveNeighbour (const Ipv6Address &nextHop, int interfaceId)
 Public method, to be invoked from the Ipv6 module to determine link-layer address and the output interface of the next hop. More...
 
virtual void reachabilityConfirmed (const Ipv6Address &neighbour, int interfaceId)
 Public method, it can be invoked from the Ipv6 module or any other module to let Neighbour Discovery know that the reachability of the given neighbor has just been confirmed (e.g. More...
 
- Public Member Functions inherited from inet::LifecycleUnsupported
virtual bool handleOperationStage (LifecycleOperation *operation, IDoneCallback *doneCallback) override
 Perform one stage of a lifecycle operation. More...
 
- Public Member Functions inherited from inet::ILifecycle
virtual ~ILifecycle ()
 

Protected Types

typedef std::set< cMessage * > RaTimerList
 
typedef std::set< DadEntry * > DadList
 
typedef std::set< RdEntry * > RdList
 
typedef std::set< AdvIfEntry * > AdvIfList
 

Protected Member Functions

virtual int numInitStages () const override
 
virtual void initialize (int stage) override
 
virtual void handleMessage (cMessage *msg) override
 
virtual void processNDMessage (Packet *packet, const Icmpv6Header *msg)
 
virtual void finish () override
 
virtual void processIpv6Datagram (Packet *packet)
 
virtual Ipv6NeighbourDiscovery::AdvIfEntryfetchAdvIfEntry (NetworkInterface *ie)
 
virtual Ipv6NeighbourDiscovery::RdEntryfetchRdEntry (NetworkInterface *ie)
 
virtual Ipv6Address determineNextHop (const Ipv6Address &destAddr, int &outIfID)
 This function accepts the datagram's destination address and attempts to determine the destination's next hop address and interface ID by: (1) looking up the destination cache, (2)looking up the routing table, or (3) selecting a default router. More...
 
virtual void initiateNeighbourUnreachabilityDetection (Neighbour *neighbour)
 
virtual void processNudTimeout (cMessage *timeoutMsg)
 
virtual Ipv6Address selectDefaultRouter (int &outIfID)
 
virtual void timeoutPrefixEntry (const Ipv6Address &destPrefix, int prefixLength)
 RFC 2461: Section 6.3.5 Whenever the invalidation timer expires for a Prefix List entry, that entry is discarded. More...
 
virtual void timeoutDefaultRouter (const Ipv6Address &addr, int interfaceID)
 RFC 2461: Section 6.3.5 Whenever the Lifetime of an entry in the Default Router List expires, that entry is discarded. More...
 
virtual void initiateAddressResolution (const Ipv6Address &dgSrcAddr, Neighbour *nce)
 This method attempts to resolve the given neighbour's link-layer address. More...
 
virtual void processArTimeout (cMessage *arTimeoutMsg)
 Resends a NS packet to the address intended for address resolution. More...
 
virtual void dropQueuedPacketsAwaitingAr (Neighbour *nce)
 Drops specific queued packets for a specific NCE AR-timeout. More...
 
virtual void sendPacketToIpv6Module (Packet *msg, const Ipv6Address &destAddr, const Ipv6Address &srcAddr, int interfaceId)
 Create control info and assigns it to a msg. More...
 
virtual void sendQueuedPacketsToIpv6Module (Neighbour *nce)
 Send off any queued packets within the Neighbour Discovery module awaiting address resolution. More...
 
virtual void initiateDad (const Ipv6Address &tentativeAddr, NetworkInterface *ie)
 Initiating DAD means to send off a Neighbour Solicitation with its target address set as this node's tentative link-local address. More...
 
virtual void processDadTimeout (cMessage *msg)
 Sends a scheduled DAD NS packet. More...
 
virtual void makeTentativeAddressPermanent (const Ipv6Address &tentativeAddr, NetworkInterface *ie)
 Permanently assign the given address for the given interface entry. More...
 
virtual void assignLinkLocalAddress (cMessage *timerMsg)
 as it is not possbile to explicitly define RFC 2462. More...
 
virtual void createAndSendRsPacket (NetworkInterface *ie)
 
virtual void initiateRouterDiscovery (cMessage *msg)
 
virtual void cancelRouterDiscovery (NetworkInterface *ie)
 RFC 2461: Section 6.3.7 4th paragraph Once the host sends a Router Solicitation, and receives a valid Router Advertisement with a non-zero Router Lifetime, the host MUST desist from sending additional solicitations on that interface,. More...
 
virtual void processRdTimeout (cMessage *msg)
 
virtual void processRsPacket (Packet *packet, const Ipv6RouterSolicitation *rs)
 
virtual bool validateRsPacket (Packet *packet, const Ipv6RouterSolicitation *rs)
 
virtual void createAndSendRaPacket (const Ipv6Address &destAddr, NetworkInterface *ie)
 
virtual void processRaPacket (Packet *packet, const Ipv6RouterAdvertisement *ra)
 
virtual void processRaForRouterUpdates (Packet *packet, const Ipv6RouterAdvertisement *ra)
 
virtual void processRaPrefixInfo (const Ipv6RouterAdvertisement *ra, NetworkInterface *ie)
 
virtual void processRaPrefixInfoForAddrAutoConf (const Ipv6NdPrefixInformation &prefixInfo, NetworkInterface *ie)
 
virtual void createRaTimer (NetworkInterface *ie)
 Create a timer for the given interface entry that sends periodic Router Advertisements. More...
 
virtual void resetRaTimer (NetworkInterface *ie)
 Reset the given interface entry's Router Advertisement timer. More...
 
virtual void sendPeriodicRa (cMessage *msg)
 
virtual void sendSolicitedRa (cMessage *msg)
 
virtual bool validateRaPacket (Packet *packet, const Ipv6RouterAdvertisement *ra)
 
virtual void createAndSendNsPacket (const Ipv6Address &nsTargetAddr, const Ipv6Address &dgDestAddr, const Ipv6Address &dgSrcAddr, NetworkInterface *ie)
 
virtual void processNsPacket (Packet *packet, const Ipv6NeighbourSolicitation *ns)
 
virtual bool validateNsPacket (Packet *packet, const Ipv6NeighbourSolicitation *ns)
 
virtual void processNsForTentativeAddress (Packet *packet, const Ipv6NeighbourSolicitation *ns)
 
virtual void processNsForNonTentativeAddress (Packet *packet, const Ipv6NeighbourSolicitation *ns, NetworkInterface *ie)
 
virtual void processNsWithSpecifiedSrcAddr (Packet *packet, const Ipv6NeighbourSolicitation *ns, NetworkInterface *ie)
 
virtual void sendSolicitedNa (Packet *packet, const Ipv6NeighbourSolicitation *ns, NetworkInterface *ie)
 
virtual void sendUnsolicitedNa (NetworkInterface *ie)
 
virtual void processNaPacket (Packet *packet, const Ipv6NeighbourAdvertisement *na)
 
virtual bool validateNaPacket (Packet *packet, const Ipv6NeighbourAdvertisement *na)
 
virtual void processNaForIncompleteNceState (const Ipv6NeighbourAdvertisement *na, Ipv6NeighbourCache::Neighbour *nce)
 
virtual void processNaForOtherNceStates (const Ipv6NeighbourAdvertisement *na, Ipv6NeighbourCache::Neighbour *nce)
 
virtual void createAndSendRedirectPacket (NetworkInterface *ie)
 
virtual void processRedirectPacket (const Ipv6Redirect *redirect)
 

Protected Attributes

cQueue pendingQueue
 
ModuleRefByPar< IInterfaceTableift
 
ModuleRefByPar< Ipv6RoutingTablert6
 
ModuleRefByPar< Icmpv6icmpv6
 
CrcMode crcMode = CRC_MODE_UNDEFINED
 
Ipv6NeighbourCache neighbourCache
 
RaTimerList raTimerList
 
DadList dadList
 
RdList rdList
 
AdvIfList advIfList
 

Static Private Attributes

static simsignal_t startDadSignal = registerSignal("startDad")
 

Detailed Description

Implements RFC 2461 Neighbor Discovery for Ipv6.

Member Typedef Documentation

◆ AdvIfList

typedef std::set<AdvIfEntry *> inet::Ipv6NeighbourDiscovery::AdvIfList
protected

◆ DadList

typedef std::set<DadEntry *> inet::Ipv6NeighbourDiscovery::DadList
protected

◆ DefaultRouterList

◆ Key

◆ MsgPtrVector

◆ Neighbour

◆ RaTimerList

typedef std::set<cMessage *> inet::Ipv6NeighbourDiscovery::RaTimerList
protected

◆ RdList

typedef std::set<RdEntry *> inet::Ipv6NeighbourDiscovery::RdList
protected

Constructor & Destructor Documentation

◆ Ipv6NeighbourDiscovery()

inet::Ipv6NeighbourDiscovery::Ipv6NeighbourDiscovery ( )
42  : neighbourCache(*this)
43 {
44 }

◆ ~Ipv6NeighbourDiscovery()

inet::Ipv6NeighbourDiscovery::~Ipv6NeighbourDiscovery ( )
virtual
47 {
48  // FIXME delete the following data structures, cancelAndDelete timers in them etc.
49  // Deleting the data structures my become unnecessary if the lists store the
50  // structs themselves and not pointers.
51 
52 // RaTimerList raTimerList;
53  for (const auto& elem : raTimerList) {
54  cancelAndDelete(elem);
55  delete elem;
56  }
57 
58 // DadList dadList;
59  for (const auto& elem : dadList) {
60  cancelAndDelete((elem)->timeoutMsg);
61  delete elem;
62  }
63 
64 // RdList rdList;
65  for (const auto& elem : rdList) {
66  cancelAndDelete((elem)->timeoutMsg);
67  delete elem;
68  }
69 
70 // AdvIfList advIfList;
71  for (const auto& elem : advIfList) {
72  cancelAndDelete((elem)->raTimeoutMsg);
73  delete elem;
74  }
75 }

Member Function Documentation

◆ assignLinkLocalAddress()

void inet::Ipv6NeighbourDiscovery::assignLinkLocalAddress ( cMessage *  timerMsg)
protectedvirtual

as it is not possbile to explicitly define RFC 2462.

ND is the next best place to do this.

RFC 2462-Ipv6 Stateless Address Autoconfiguration: Section 1 The autoconfiguration process specified in this document applies only to hosts and not routers. Since host autoconfiguration uses information advertised by routers, routers will need to be configured by some other means. However, it is expected that routers will generate link-local addresses using the mechanism described in this document. In addition, routers are expected to successfully pass the Duplicate Address Detection procedure described in this document on all addresses prior to assigning them to an interface.

768 {
769  // Node has booted up. Start assigning a link-local address for each
770  // interface in this node.
771  for (int i = 0; i < ift->getNumInterfaces(); i++) {
772  NetworkInterface *ie = ift->getInterface(i);
773 
774  // Skip the loopback interface.
775  if (ie->isLoopback())
776  continue;
777 
778  Ipv6Address linkLocalAddr = ie->getProtocolData<Ipv6InterfaceData>()->getLinkLocalAddress();
779  if (linkLocalAddr.isUnspecified()) {
780  // if no link local address exists for this interface, we assign one to it.
781  EV_INFO << "No link local address exists. Forming one" << endl;
782  linkLocalAddr = Ipv6Address().formLinkLocalAddress(ie->getInterfaceToken());
783  ie->getProtocolDataForUpdate<Ipv6InterfaceData>()->assignAddress(linkLocalAddr, true, SIMTIME_ZERO, SIMTIME_ZERO);
784  }
785 
786  // Before we can use this address, we MUST initiate DAD first.
787  if (ie->getProtocolData<Ipv6InterfaceData>()->isTentativeAddress(linkLocalAddr)) {
788  if (ie->getProtocolData<Ipv6InterfaceData>()->getDupAddrDetectTransmits() > 0)
789  initiateDad(linkLocalAddr, ie);
790  else
791  makeTentativeAddressPermanent(linkLocalAddr, ie);
792  }
793  }
794  delete timerMsg;
795 }

Referenced by handleMessage().

◆ cancelRouterDiscovery()

void inet::Ipv6NeighbourDiscovery::cancelRouterDiscovery ( NetworkInterface ie)
protectedvirtual

RFC 2461: Section 6.3.7 4th paragraph Once the host sends a Router Solicitation, and receives a valid Router Advertisement with a non-zero Router Lifetime, the host MUST desist from sending additional solicitations on that interface,.

Cancel Router Discovery on the Interface where a RA was received with the given Interface Entry.

1017 {
1018  // Next we retrieve the rdEntry with the Interface Entry.
1019  RdEntry *rdEntry = fetchRdEntry(ie);
1020  if (rdEntry != nullptr) {
1021  EV_DETAIL << "rdEntry is not nullptr, RD cancelled!" << endl;
1022  cancelAndDelete(rdEntry->timeoutMsg);
1023  rdList.erase(rdEntry);
1024  delete rdEntry;
1025  }
1026  else
1027  EV_DETAIL << "rdEntry is nullptr, not cancelling RD!" << endl;
1028 }

Referenced by processRaPacket().

◆ createAndSendNsPacket()

void inet::Ipv6NeighbourDiscovery::createAndSendNsPacket ( const Ipv6Address nsTargetAddr,
const Ipv6Address dgDestAddr,
const Ipv6Address dgSrcAddr,
NetworkInterface ie 
)
protectedvirtual
1811 {
1812 #ifdef INET_WITH_xMIPv6
1813  Enter_Method("createAndSendNsPacket");
1814 #endif /* INET_WITH_xMIPv6 */
1815 
1816  MacAddress myMacAddr = ie->getMacAddress();
1817 
1818  // Construct a Neighbour Solicitation message
1819  auto ns = makeShared<Ipv6NeighbourSolicitation>();
1820 
1821  // Neighbour Solicitation Specific Information
1822  ns->setTargetAddress(nsTargetAddr);
1823 
1824  /*If the solicitation is being sent to a solicited-node multicast
1825  address, the sender MUST include its link-layer address (if it has
1826  one) as a Source Link-Layer Address option.*/
1827  if (dgDestAddr.matches(Ipv6Address("FF02::1:FF00:0"), 104) && // FIXME what's this? make constant...
1828  !dgSrcAddr.isUnspecified())
1829  {
1830  auto sla = new Ipv6NdSourceLinkLayerAddress();
1831  sla->setLinkLayerAddress(myMacAddr);
1832  ns->getOptionsForUpdate().appendOption(sla);
1834  }
1835  auto packet = new Packet("NSpacket");
1836  Icmpv6::insertCrc(crcMode, ns, packet);
1837  packet->insertAtFront(ns);
1838  sendPacketToIpv6Module(packet, dgDestAddr, dgSrcAddr, ie->getInterfaceId());
1839 
1840 }

Referenced by initiateAddressResolution(), initiateDad(), processArTimeout(), processDadTimeout(), and processNudTimeout().

◆ createAndSendRaPacket()

void inet::Ipv6NeighbourDiscovery::createAndSendRaPacket ( const Ipv6Address destAddr,
NetworkInterface ie 
)
protectedvirtual
1176 {
1177  EV_INFO << "Create and send RA invoked!\n";
1178  // Must use link-local addr. See: RFC2461 Section 6.1.2
1179  Ipv6Address sourceAddr = ie->getProtocolData<Ipv6InterfaceData>()->getLinkLocalAddress();
1180 
1181  // This operation includes all options, regardless whether it is solicited or unsolicited.
1182  if (ie->getProtocolData<Ipv6InterfaceData>()->getAdvSendAdvertisements()) { // if this is an advertising interface
1183  // Construct a Router Advertisment message
1184  auto ra = makeShared<Ipv6RouterAdvertisement>();
1185 
1186  // RFC 2461: Section 6.2.3 Router Advertisment Message Content
1187  /*A router sends periodic as well as solicited Router Advertisements out
1188  its advertising interfaces. Outgoing Router Advertisements are filled
1189  with the following values consistent with the message format given in
1190  Section 4.2:*/
1191 
1192  // - In the Router Lifetime field: the interface's configured AdvDefaultLifetime.
1193  ra->setRouterLifetime(SIMTIME_DBL(ie->getProtocolData<Ipv6InterfaceData>()->getAdvDefaultLifetime()));
1194 
1195  // - In the M and O flags: the interface's configured AdvManagedFlag and
1196  // AdvOtherConfigFlag, respectively. See [ADDRCONF].
1197  ra->setManagedAddrConfFlag(ie->getProtocolData<Ipv6InterfaceData>()->getAdvManagedFlag());
1198  ra->setOtherStatefulConfFlag(ie->getProtocolData<Ipv6InterfaceData>()->getAdvOtherConfigFlag());
1199 
1200 #ifdef INET_WITH_xMIPv6
1201  // Configuring the HomeAgentFlag (H-bit) (RFC 3775): Zarrar 25.02.07
1202  if (rt6->isHomeAgent())
1203  ra->setHomeAgentFlag(true); // Set H-bit if the router is a HA
1204  else
1205  ra->setHomeAgentFlag(ie->getProtocolData<Ipv6InterfaceData>()->getAdvHomeAgentFlag()); // else unset it, which is default
1206 #endif /* INET_WITH_xMIPv6 */
1207 
1208  // - In the Cur Hop Limit field: the interface's configured CurHopLimit.
1209  ra->setCurHopLimit(ie->getProtocolData<Ipv6InterfaceData>()->getAdvCurHopLimit());
1210 
1211  // - In the Reachable Time field: the interface's configured AdvReachableTime.
1212  ra->setReachableTime(ie->getProtocolData<Ipv6InterfaceData>()->getAdvReachableTime());
1213 
1214  // - In the Retrans Timer field: the interface's configured AdvRetransTimer.
1215  ra->setRetransTimer(ie->getProtocolData<Ipv6InterfaceData>()->getAdvRetransTimer());
1216 
1217  // - In the options:
1218  /*o Source Link-Layer Address option: link-layer address of the sending
1219  interface. (Assumption: We always send this)*/
1220  auto sla = new Ipv6NdSourceLinkLayerAddress();
1221  sla->setLinkLayerAddress(ie->getMacAddress());
1222  ra->getOptionsForUpdate().appendOption(sla);
1223  ra->addChunkLength(IPv6ND_LINK_LAYER_ADDRESS_OPTION_LENGTH);
1224 
1225  // set MTU option
1226  auto mtu = new Ipv6NdMtu();
1227  mtu->setMtu(ie->getProtocolData<Ipv6InterfaceData>()->getAdvLinkMtu());
1228  ra->getOptionsForUpdate().appendOption(mtu);
1229  ra->addChunkLength(IPv6ND_MTU_OPTION_LENGTH);
1230 
1231  // Add all Advertising Prefixes to the RA
1232  int numAdvPrefixes = ie->getProtocolData<Ipv6InterfaceData>()->getNumAdvPrefixes();
1233  EV_DETAIL << "Number of Adv Prefixes: " << numAdvPrefixes << endl;
1234  for (int i = 0; i < numAdvPrefixes; i++) {
1235  Ipv6InterfaceData::AdvPrefix advPrefix = ie->getProtocolData<Ipv6InterfaceData>()->getAdvPrefix(i);
1236  auto prefixInfo = new Ipv6NdPrefixInformation();
1237 
1238 #ifndef INET_WITH_xMIPv6
1239  prefixInfo->setPrefix(advPrefix.prefix);
1240 #else /* INET_WITH_xMIPv6 */
1241  EV_DETAIL << "\n+=+=+=+= Appendign Prefix Info Option to RA +=+=+=+=\n";
1242  EV_DETAIL << "Prefix Value: " << advPrefix.prefix << endl;
1243  EV_DETAIL << "Prefix Length: " << advPrefix.prefixLength << endl;
1244  EV_DETAIL << "L-Flag: " << advPrefix.advOnLinkFlag << endl;
1245  EV_DETAIL << "A-Flag: " << advPrefix.advAutonomousFlag << endl;
1246  EV_DETAIL << "R-Flag: " << advPrefix.advRtrAddr << endl;
1247  EV_DETAIL << "Global Address from Prefix: " << advPrefix.rtrAddress << endl;
1248 
1249  if (rt6->isHomeAgent() && advPrefix.advRtrAddr == true)
1250  prefixInfo->setPrefix(advPrefix.rtrAddress); // add the global-scope address of the HA's interface in the prefix option list of the RA message.
1251  else
1252  prefixInfo->setPrefix(advPrefix.prefix); // adds the prefix only of the router's interface in the prefix option list of the RA message.
1253 #endif /* INET_WITH_xMIPv6 */
1254 
1255  prefixInfo->setPrefixLength(advPrefix.prefixLength);
1256 
1257  // - In the "on-link" flag: the entry's AdvOnLinkFlag.
1258  prefixInfo->setOnlinkFlag(advPrefix.advOnLinkFlag);
1259  // - In the Valid Lifetime field: the entry's AdvValidLifetime.
1260  prefixInfo->setValidLifetime(SIMTIME_DBL(advPrefix.advValidLifetime));
1261  // - In the "Autonomous address configuration" flag: the entry's
1262  // AdvAutonomousFlag.
1263  prefixInfo->setAutoAddressConfFlag(advPrefix.advAutonomousFlag);
1264 
1265 #ifdef INET_WITH_xMIPv6
1266  if (rt6->isHomeAgent())
1267  prefixInfo->setRouterAddressFlag(true); // set the R-bit if the node is a HA
1268 
1269  // - In the Valid Lifetime field: the entry's AdvValidLifetime.
1270  prefixInfo->setValidLifetime(SIMTIME_DBL(advPrefix.advValidLifetime));
1271 #endif /* INET_WITH_xMIPv6 */
1272 
1273  // - In the Preferred Lifetime field: the entry's AdvPreferredLifetime.
1274  prefixInfo->setPreferredLifetime(SIMTIME_DBL(advPrefix.advPreferredLifetime));
1275  // Now we pop the prefix info into the RA.
1276  ra->getOptionsForUpdate().appendOption(prefixInfo);
1277  ra->addChunkLength(IPv6ND_PREFIX_INFORMATION_OPTION_LENGTH);
1278  }
1279 
1280  auto packet = new Packet("RApacket");
1281  Icmpv6::insertCrc(crcMode, ra, packet);
1282  packet->insertAtFront(ra);
1283  sendPacketToIpv6Module(packet, destAddr, sourceAddr, ie->getInterfaceId());
1284  }
1285 }

Referenced by sendPeriodicRa(), and sendSolicitedRa().

◆ createAndSendRedirectPacket()

void inet::Ipv6NeighbourDiscovery::createAndSendRedirectPacket ( NetworkInterface ie)
protectedvirtual
2406 {
2407  // Construct a Redirect message
2408  auto redirect = makeShared<Ipv6Redirect>(); // TODO "redirectMsg");
2409 
2410  // FIXME incomplete code
2411 #if 0
2412  // Redirect Message Specific Information
2413  redirect->setTargetAddress();
2414  redirect->setDestinationAddress();
2415 
2416  // Possible Option
2417  redirect->setTargetLinkLayerAddress();
2418  redirect->addByteLength(IPv6ND_LINK_LAYER_ADDRESS_OPTION_LENGTH);
2419 #endif
2420 }

◆ createAndSendRsPacket()

void inet::Ipv6NeighbourDiscovery::createAndSendRsPacket ( NetworkInterface ie)
protectedvirtual
948 {
949  ASSERT(ie->getProtocolData<Ipv6InterfaceData>()->getAdvSendAdvertisements() == false);
950  // RFC 2461: Section 6.3.7 Sending Router Solicitations
951  // A host sends Router Solicitations to the All-Routers multicast address. The
952  // IP source address is set to either one of the interface's unicast addresses
953  // or the unspecified address.
954  Ipv6Address myIPv6Address = ie->getProtocolData<Ipv6InterfaceData>()->getPreferredAddress();
955 
956  if (myIPv6Address.isUnspecified())
957  myIPv6Address = ie->getProtocolData<Ipv6InterfaceData>()->getLinkLocalAddress(); // so we use the link local address instead
958 
959  if (ie->getProtocolData<Ipv6InterfaceData>()->isTentativeAddress(myIPv6Address))
960  myIPv6Address = Ipv6Address::UNSPECIFIED_ADDRESS; // set my Ipv6 address to unspecified.
961 
962  Ipv6Address destAddr = Ipv6Address::ALL_ROUTERS_2; // all_routers multicast
963  auto rs = makeShared<Ipv6RouterSolicitation>();
964 
965  // The Source Link-Layer Address option SHOULD be set to the host's link-layer
966  // address, if the IP source address is not the unspecified address.
967  if (!myIPv6Address.isUnspecified()) {
968  auto sla = new Ipv6NdSourceLinkLayerAddress();
969  sla->setLinkLayerAddress(ie->getMacAddress());
970  rs->getOptionsForUpdate().insertUniqueOption(sla);
972  }
973 
974  // Construct a Router Solicitation message
975  auto packet = new Packet("RSpacket");
976  Icmpv6::insertCrc(crcMode, rs, packet);
977  packet->insertAtFront(rs);
978  sendPacketToIpv6Module(packet, destAddr, myIPv6Address, ie->getInterfaceId());
979 }

Referenced by initiateRouterDiscovery(), and processRdTimeout().

◆ createRaTimer()

void inet::Ipv6NeighbourDiscovery::createRaTimer ( NetworkInterface ie)
protectedvirtual

Create a timer for the given interface entry that sends periodic Router Advertisements.

1637 {
1638  cMessage *msg = new cMessage("sendPeriodicRA", MK_SEND_PERIODIC_RTRADV);
1639  msg->setContextPointer(ie);
1640  AdvIfEntry *advIfEntry = new AdvIfEntry();
1641  advIfEntry->interfaceId = ie->getInterfaceId();
1642  advIfEntry->numRASent = 0;
1643 
1644 #ifdef INET_WITH_xMIPv6
1645  // 20.9.07 - CB
1646  /*if ( rt6->isRouter() )
1647  {
1648  ie->ipv6()->setMinRtrAdvInterval(Ipv6NeighbourDiscovery::getMinRAInterval()); //should be 0.07 for MIPv6 Support
1649  ie->ipv6()->setMaxRtrAdvInterval(Ipv6NeighbourDiscovery::getMaxRAInterval()); //should be 0.03 for MIPv6 Support
1650  }*/
1651  // update 23.10.07 - CB
1652 
1653  if (canServeWirelessNodes(ie)) {
1654  EV_INFO << "This Interface is connected to a WLAN AP, hence using MIPv6 Default Values" << endl;
1655  simtime_t minRAInterval = par("minIntervalBetweenRAs"); // reading from the omnetpp.ini (ZY 23.07.09)
1656  simtime_t maxRAInterval = par("maxIntervalBetweenRAs"); // reading from the omnetpp.ini (ZY 23.07.09
1657  ie->getProtocolDataForUpdate<Ipv6InterfaceData>()->setMinRtrAdvInterval(minRAInterval);
1658  ie->getProtocolDataForUpdate<Ipv6InterfaceData>()->setMaxRtrAdvInterval(maxRAInterval);
1659  }
1660  else {
1661  EV_INFO << "This Interface is not connected to a WLAN AP, hence using default values" << endl;
1662 // interval = uniform( ie->ipv6()->minRtrAdvInterval(), ie->ipv6()->maxRtrAdvInterval() );
1663 // EV<<"\nThe random calculated RA_ND interval is: "<< interval<<" seconds\n";
1664  }
1665  // end CB
1666 #endif /* INET_WITH_xMIPv6 */
1667 
1668  simtime_t interval = uniform(ie->getProtocolData<Ipv6InterfaceData>()->getMinRtrAdvInterval(), ie->getProtocolData<Ipv6InterfaceData>()->getMaxRtrAdvInterval());
1669  advIfEntry->raTimeoutMsg = msg;
1670 
1671  simtime_t nextScheduledTime = simTime() + interval;
1672  advIfEntry->nextScheduledRATime = nextScheduledTime;
1673  advIfList.insert(advIfEntry);
1674  EV_DETAIL << "Interval: " << interval << endl;
1675  EV_DETAIL << "Next scheduled time: " << nextScheduledTime << endl;
1676  // now we schedule the msg for whatever time that was derived
1677  scheduleAfter(interval, msg);
1678 }

Referenced by initialize().

◆ determineNextHop()

Ipv6Address inet::Ipv6NeighbourDiscovery::determineNextHop ( const Ipv6Address destAddr,
int &  outIfID 
)
protectedvirtual

This function accepts the datagram's destination address and attempts to determine the destination's next hop address and interface ID by: (1) looking up the destination cache, (2)looking up the routing table, or (3) selecting a default router.

It then updates the destination cache. If no default router can be selected than we assume the destination address to be onlink and simply return any available interface.

423 {
424  Ipv6Address nextHopAddr;
425  simtime_t expiryTime;
426 
427  // RFC 2461 Section 5.2
428  // Next-hop determination for a given unicast destination operates as follows.
429 
430  // The sender performs a longest prefix match against the Prefix List to
431  // determine whether the packet's destination is on- or off-link.
432  EV_INFO << "Find out if supplied dest addr is on-link or off-link.\n";
433  const Ipv6Route *route = rt6->doLongestPrefixMatch(destAddr);
434 
435  if (route != nullptr) {
436  expiryTime = route->getExpiryTime();
437  outIfID = route->getInterface() ? route->getInterface()->getInterfaceId() : -1;
438 
439  // If the destination is on-link, the next-hop address is the same as the
440  // packet's destination address.
441  if (route->getNextHop().isUnspecified()) {
442  EV_INFO << "Dest is on-link, next-hop addr is same as dest addr.\n";
443  nextHopAddr = destAddr;
444  }
445  else {
446  EV_INFO << "A next-hop address was found with the route, dest is off-link\n";
447  EV_INFO << "Assume next-hop address as the selected default router.\n";
448  nextHopAddr = route->getNextHop();
449  }
450  }
451  else {
452  // Otherwise, the sender selects a router from the Default Router List
453  // (following the rules described in Section 6.3.6).
454 
455  EV_INFO << "No routes were found, Dest addr is off-link.\n";
456  nextHopAddr = selectDefaultRouter(outIfID);
457  expiryTime = 0;
458 
459  if (outIfID == -1)
460  EV_INFO << "No Default Routers were found.";
461  else
462  EV_INFO << "Default router found.\n";
463  }
464 
465  /*the results of next-hop determination computations are saved in the Destination
466  Cache (which also contains updates learned from Redirect messages).*/
467  rt6->updateDestCache(destAddr, nextHopAddr, outIfID, expiryTime);
468  return nextHopAddr;
469 }

Referenced by processIpv6Datagram().

◆ dropQueuedPacketsAwaitingAr()

void inet::Ipv6NeighbourDiscovery::dropQueuedPacketsAwaitingAr ( Neighbour nce)
protectedvirtual

Drops specific queued packets for a specific NCE AR-timeout.

TODO Not implemented yet!

708 {
709  const Key *nceKey = nce->nceKey;
710  // RFC 2461: Section 7.2.2
711  /*If no Neighbor Advertisement is received after MAX_MULTICAST_SOLICIT
712  solicitations, address resolution has failed. The sender MUST return ICMP
713  destination unreachable indications with code 3 (Address Unreachable) for
714  each packet queued awaiting address resolution.*/
715  MsgPtrVector& pendingPackets = nce->pendingPackets;
716  EV_INFO << "Pending Packets empty:" << pendingPackets.empty() << endl;
717 
718  while (!pendingPackets.empty()) {
719  auto i = pendingPackets.begin();
720  Packet *msg = (*i);
721  // Assume msg is the packet itself. I need the datagram's source addr.
722  // The datagram's src addr will be the destination of the unreachable msg.
723  EV_INFO << "Sending ICMP unreachable destination." << endl;
724  pendingPackets.erase(i);
725  pendingQueue.remove(msg);
727  delete msg;
728  }
729 
730  // RFC 2461: Section 7.3.3
731  /*If address resolution fails, the entry SHOULD be deleted, so that subsequent
732  traffic to that neighbor invokes the next-hop determination procedure again.*/
733  EV_INFO << "Removing neighbour cache entry" << endl;
734  neighbourCache.remove(nceKey->address, nceKey->interfaceID);
735 }

Referenced by processArTimeout().

◆ fetchAdvIfEntry()

Ipv6NeighbourDiscovery::AdvIfEntry * inet::Ipv6NeighbourDiscovery::fetchAdvIfEntry ( NetworkInterface ie)
protectedvirtual
305 {
306  for (auto advIfEntry : advIfList) {
307  if (advIfEntry->interfaceId == ie->getInterfaceId()) {
308  return advIfEntry;
309  }
310  }
311  return nullptr;
312 }

Referenced by processRsPacket(), and sendPeriodicRa().

◆ fetchRdEntry()

Ipv6NeighbourDiscovery::RdEntry * inet::Ipv6NeighbourDiscovery::fetchRdEntry ( NetworkInterface ie)
protectedvirtual
315 {
316  for (auto rdEntry : rdList) {
317  if (rdEntry->interfaceId == ie->getInterfaceId()) {
318  return rdEntry;
319  }
320  }
321  return nullptr;
322 }

Referenced by cancelRouterDiscovery(), and processRdTimeout().

◆ finish()

void inet::Ipv6NeighbourDiscovery::finish ( )
overrideprotectedvirtual
212 {
213 }

◆ handleMessage()

void inet::Ipv6NeighbourDiscovery::handleMessage ( cMessage *  msg)
overrideprotectedvirtual
135 {
136  if (msg->isSelfMessage()) {
137  EV_TRACE << "Self message received!\n";
138 
139  if (msg->getKind() == MK_SEND_PERIODIC_RTRADV) {
140  EV_INFO << "Sending periodic RA\n";
141  sendPeriodicRa(msg);
142  }
143  else if (msg->getKind() == MK_SEND_SOL_RTRADV) {
144  EV_INFO << "Sending solicited RA\n";
145  sendSolicitedRa(msg);
146  }
147  else if (msg->getKind() == MK_ASSIGN_LINKLOCAL_ADDRESS) {
148  EV_INFO << "Assigning Link Local Address\n";
150  }
151  else if (msg->getKind() == MK_DAD_TIMEOUT) {
152  EV_INFO << "DAD Timeout message received\n";
153  processDadTimeout(msg);
154  }
155  else if (msg->getKind() == MK_RD_TIMEOUT) {
156  EV_INFO << "Router Discovery message received\n";
157  processRdTimeout(msg);
158  }
159  else if (msg->getKind() == MK_INITIATE_RTRDIS) {
160  EV_INFO << "initiate router discovery.\n";
162  }
163  else if (msg->getKind() == MK_NUD_TIMEOUT) {
164  EV_INFO << "NUD Timeout message received\n";
165  processNudTimeout(msg);
166  }
167  else if (msg->getKind() == MK_AR_TIMEOUT) {
168  EV_INFO << "Address Resolution Timeout message received\n";
169  processArTimeout(msg);
170  }
171  else
172  throw cRuntimeError("Unrecognized Timer"); // stops sim w/ error msg.
173  }
174  else if (auto packet = dynamic_cast<Packet *>(msg)) {
175  auto protocol = packet->getTag<PacketProtocolTag>()->getProtocol();
176  if (protocol == &Protocol::icmpv6) {
177  // This information will serve as input parameters to various processors.
178  const auto& ndMsg = packet->peekAtFront<Icmpv6Header>();
179  processNDMessage(packet, ndMsg.get()); // KLUDGE remove get()
180  }
181  else { // not ND message
182  processIpv6Datagram(packet);
183  }
184  }
185  else
186  throw cRuntimeError("Unknown message type received.\n");
187 }

◆ initialize()

void inet::Ipv6NeighbourDiscovery::initialize ( int  stage)
overrideprotectedvirtual
78 {
79  cSimpleModule::initialize(stage);
80 
81  if (stage == INITSTAGE_LOCAL) {
82  const char *crcModeString = par("crcMode");
83  crcMode = parseCrcMode(crcModeString, false);
84  }
85  else if (stage == INITSTAGE_NETWORK_LAYER_PROTOCOLS) {
86  cModule *node = findContainingNode(this);
87  NodeStatus *nodeStatus = node ? check_and_cast_nullable<NodeStatus *>(node->getSubmodule("status")) : nullptr;
88  bool isOperational = (!nodeStatus) || nodeStatus->getState() == NodeStatus::UP;
89  if (!isOperational)
90  throw cRuntimeError("This module doesn't support starting in node DOWN state");
91  ift.reference(this, "interfaceTableModule", true);
92  rt6.reference(this, "routingTableModule", true);
93  icmpv6.reference(this, "icmpv6Module", true);
94 
95 #ifdef INET_WITH_xMIPv6
96  if (rt6->isMobileNode())
97  mipv6.reference(this, "xmipv6Module", true);
98 #endif /* INET_WITH_xMIPv6 */
99 
100  pendingQueue.setName("pendingQueue");
101 
102 #ifdef INET_WITH_xMIPv6
103 // MIPv6Enabled = par("MIPv6Support"); // (Zarrar 14.07.07)
104  /*if(rt6->isRouter()) // 12.9.07 - CB
105  {
106  minRAInterval = par("minIntervalBetweenRAs"); // from the omnetpp.ini file (Zarrar 15.07.07)
107  maxRAInterval = par("maxIntervalBetweenRAs"); // from the omnetpp.ini file (Zarrar 15.07.07)
108  //WATCH (MIPv6Enabled); // (Zarrar 14.07.07)
109  WATCH(minRAInterval); // (Zarrar 15.07.07)
110  WATCH(maxRAInterval); // (Zarrar 15.07.07)
111  }*/
112 #endif /* INET_WITH_xMIPv6 */
113 
114  for (int i = 0; i < ift->getNumInterfaces(); i++) {
115  NetworkInterface *ie = ift->getInterface(i);
116 
117  if (ie->getProtocolData<Ipv6InterfaceData>()->getAdvSendAdvertisements() && !(ie->isLoopback())) {
118  createRaTimer(ie);
119  }
120  }
121 
122  // This simulates random node bootup time. Link local address assignment
123  // takes place during this time.
124  cMessage *msg = new cMessage("assignLinkLocalAddr", MK_ASSIGN_LINKLOCAL_ADDRESS);
125 
126  // We want routers to boot up faster!
127  if (rt6->isRouter())
128  scheduleAfter(uniform(0, 0.3), msg); // Random Router bootup time
129  else
130  scheduleAfter(uniform(0.4, 1), msg); // Random Host bootup time
131  }
132 }

◆ initiateAddressResolution()

void inet::Ipv6NeighbourDiscovery::initiateAddressResolution ( const Ipv6Address dgSrcAddr,
Neighbour nce 
)
protectedvirtual

This method attempts to resolve the given neighbour's link-layer address.

The source address of the packet prompting address resolution is also given in order to decide the source address of the NS to be sent. nceKey stores 2 pieces of information (Neighbour address and Interface ID) which is needed for addr resolution and access to the corresponding nce.

632 {
633  const Key *nceKey = nce->nceKey;
634  NetworkInterface *ie = ift->getInterfaceById(nceKey->interfaceID);
635  Ipv6Address neighbourAddr = nceKey->address;
636  int ifID = nceKey->interfaceID;
637 
638  // RFC2461: Section 7.2.2
639  // When a node has a unicast packet to send to a neighbor, but does not
640  // know the neighbor's link-layer address, it performs address
641  // resolution. For multicast-capable interfaces this entails creating a
642  // Neighbor Cache entry in the INCOMPLETE state(already created if not done yet)
643  // WEI-If entry already exists, we still have to ensure that its state is INCOMPLETE.
644  nce->reachabilityState = Ipv6NeighbourCache::INCOMPLETE;
645 
646  // and transmitting a Neighbor Solicitation message targeted at the
647  // neighbor. The solicitation is sent to the solicited-node multicast
648  // address "corresponding to"(or "derived from") the target address.
649  // (in this case, the target address is the address we are trying to resolve)
650  EV_INFO << "Preparing to send NS to solicited-node multicast group\n";
651  EV_INFO << "on the next hop interface\n";
652  Ipv6Address nsDestAddr = neighbourAddr.formSolicitedNodeMulticastAddress(); // for NS datagram
653  Ipv6Address nsTargetAddr = neighbourAddr; // for the field within the NS
654  Ipv6Address nsSrcAddr;
655 
656  /*If the source address of the packet prompting the solicitation is the
657  same as one of the addresses assigned to the outgoing interface,*/
658  if (ie->getProtocolData<Ipv6InterfaceData>()->hasAddress(dgSrcAddr))
659  /*that address SHOULD be placed in the IP Source Address of the outgoing
660  solicitation.*/
661  nsSrcAddr = dgSrcAddr;
662  else
663  /*Otherwise, any one of the addresses assigned to the interface
664  should be used.*/
665  nsSrcAddr = ie->getProtocolData<Ipv6InterfaceData>()->getPreferredAddress();
666  ASSERT(ifID != -1);
667  // Sending NS on specified interface.
668  createAndSendNsPacket(nsTargetAddr, nsDestAddr, nsSrcAddr, ie);
669  nce->numOfARNSSent = 1;
670  nce->nsSrcAddr = nsSrcAddr;
671 
672  /*While awaiting a response, the sender SHOULD retransmit Neighbor Solicitation
673  messages approximately every RetransTimer milliseconds, even in the absence
674  of additional traffic to the neighbor. Retransmissions MUST be rate-limited
675  to at most one solicitation per neighbor every RetransTimer milliseconds.*/
676  cMessage *msg = new cMessage("arTimeout", MK_AR_TIMEOUT); // AR msg timer
677  nce->arTimer = msg;
678  msg->setContextPointer(nce);
679  scheduleAfter(ie->getProtocolData<Ipv6InterfaceData>()->_getRetransTimer(), msg);
680 }

Referenced by processIpv6Datagram().

◆ initiateDad()

void inet::Ipv6NeighbourDiscovery::initiateDad ( const Ipv6Address tentativeAddr,
NetworkInterface ie 
)
protectedvirtual

Initiating DAD means to send off a Neighbour Solicitation with its target address set as this node's tentative link-local address.

798 {
799 #ifdef INET_WITH_xMIPv6
800  Enter_Method("initiateDad");
801  EV_INFO << "----------INITIATING DUPLICATE ADDRESS DISCOVERY----------" << endl;
802  ie->getProtocolDataForUpdate<Ipv6InterfaceData>()->setDadInProgress(true);
803 #endif /* INET_WITH_xMIPv6 */
804 
805  DadEntry *dadEntry = new DadEntry();
806  dadEntry->interfaceId = ie->getInterfaceId();
807  dadEntry->address = tentativeAddr;
808  dadEntry->numNSSent = 0;
809  dadList.insert(dadEntry);
810  /*
811  RFC2462: Section 5.4.2
812  To check an address, a node sends DupAddrDetectTransmits Neighbor
813  Solicitations, each separated by RetransTimer milliseconds. The
814  solicitation's Target Address is set to the address being checked,
815  the IP source is set to the unspecified address and the IP
816  destination is set to the solicited-node multicast address of the
817  target address.*/
818  Ipv6Address destAddr = tentativeAddr.formSolicitedNodeMulticastAddress();
819  // Send a NS
820  createAndSendNsPacket(tentativeAddr, destAddr,
822  dadEntry->numNSSent++;
823 
824  cMessage *msg = new cMessage("dadTimeout", MK_DAD_TIMEOUT);
825  msg->setContextPointer(dadEntry);
826 
827 #ifndef INET_WITH_xMIPv6
828  scheduleAfter(ie->getProtocolData<Ipv6InterfaceData>()->getRetransTimer(), msg);
829 #else /* INET_WITH_xMIPv6 */
830  // update: added uniform(0, IPv6_MAX_RTR_SOLICITATION_DELAY) to account for joining the solicited-node multicast
831  // group which is delay up to one 1 second (RFC 4862, 5.4.2) - 16.01.08, CB
832  scheduleAfter(ie->getProtocolData<Ipv6InterfaceData>()->getRetransTimer() + uniform(0, IPv6_MAX_RTR_SOLICITATION_DELAY), msg);
833 #endif /* INET_WITH_xMIPv6 */
834 
835  emit(startDadSignal, 1);
836 }

Referenced by assignLinkLocalAddress().

◆ initiateNeighbourUnreachabilityDetection()

void inet::Ipv6NeighbourDiscovery::initiateNeighbourUnreachabilityDetection ( Neighbour neighbour)
protectedvirtual
472 {
473  ASSERT(nce->reachabilityState == Ipv6NeighbourCache::STALE);
474  ASSERT(nce->nudTimeoutEvent == nullptr);
475  const Key *nceKey = nce->nceKey;
476  EV_INFO << "Initiating Neighbour Unreachability Detection";
477  NetworkInterface *ie = ift->getInterfaceById(nceKey->interfaceID);
478  EV_INFO << "Setting NCE state to DELAY.\n";
479  /*The first time a node sends a packet to a neighbor whose entry is
480  STALE, the sender changes the state to DELAY*/
481  nce->reachabilityState = Ipv6NeighbourCache::DELAY;
482 
483  /*and sets a timer to expire in DELAY_FIRST_PROBE_TIME seconds.*/
484  cMessage *msg = new cMessage("NUDTimeout", MK_NUD_TIMEOUT);
485  msg->setContextPointer(nce);
486  nce->nudTimeoutEvent = msg;
487  scheduleAfter(ie->getProtocolData<Ipv6InterfaceData>()->_getDelayFirstProbeTime(), msg);
488 }

Referenced by processIpv6Datagram(), and resolveNeighbour().

◆ initiateRouterDiscovery()

void inet::Ipv6NeighbourDiscovery::initiateRouterDiscovery ( cMessage *  msg)
protectedvirtual
982 {
983  EV_INFO << "Initiating Router Discovery" << endl;
984  NetworkInterface *ie = (NetworkInterface *)msg->getContextPointer();
985  delete msg;
986  // RFC2461: Section 6.3.7
987  /*When an interface becomes enabled, a host may be unwilling to wait for the
988  next unsolicited Router Advertisement to locate default routers or learn
989  prefixes. To obtain Router Advertisements quickly, a host SHOULD transmit up
990  to MAX_RTR_SOLICITATIONS Router Solicitation messages each separated by at
991  least RTR_SOLICITATION_INTERVAL seconds.(FIXMETherefore this should be invoked
992  at the beginning of the simulation-WEI)*/
993  RdEntry *rdEntry = new RdEntry();
994  rdEntry->interfaceId = ie->getInterfaceId();
995  rdEntry->numRSSent = 0;
997  rdEntry->numRSSent++;
998 
999  // Create and schedule a message for retransmission to this module
1000  cMessage *rdTimeoutMsg = new cMessage("processRDTimeout", MK_RD_TIMEOUT);
1001  rdTimeoutMsg->setContextPointer(ie);
1002  rdEntry->timeoutMsg = rdTimeoutMsg;
1003  rdList.insert(rdEntry);
1004  /*Before a host sends an initial solicitation, it SHOULD delay the
1005  transmission for a random amount of time between 0 and
1006  MAX_RTR_SOLICITATION_DELAY. This serves to alleviate congestion when
1007  many hosts start up on a link at the same time, such as might happen
1008  after recovery from a power failure. If a host has already performed
1009  a random delay since the interface became (re)enabled (e.g., as part
1010  of Duplicate Address Detection [ADDRCONF]) there is no need to delay
1011  again before sending the first Router Solicitation message.*/
1012 // simtime_t rndInterval = uniform(0, ie->getProtocolData<Ipv6InterfaceData>()->_getMaxRtrSolicitationDelay());
1013  scheduleAfter(ie->getProtocolData<Ipv6InterfaceData>()->_getRtrSolicitationInterval(), rdTimeoutMsg);
1014 }

Referenced by handleMessage().

◆ makeTentativeAddressPermanent()

void inet::Ipv6NeighbourDiscovery::makeTentativeAddressPermanent ( const Ipv6Address tentativeAddr,
NetworkInterface ie 
)
protectedvirtual

Permanently assign the given address for the given interface entry.

To be called after successful DAD.

868 {
869  ie->getProtocolDataForUpdate<Ipv6InterfaceData>()->permanentlyAssign(tentativeAddr);
870 
871 #ifdef INET_WITH_xMIPv6
872  ie->getProtocolDataForUpdate<Ipv6InterfaceData>()->setDadInProgress(false);
873 
874  // update 28.09.07 - CB
875  // after the link-local address was verified to be unique
876  // we can assign the address and initiate the MIPv6 protocol
877  // in case there are any pending entries in the list
878  auto it = dadGlobalList.find(ie);
879  if (it != dadGlobalList.end()) {
880  DadGlobalEntry& entry = it->second;
881 
882  ie->getProtocolDataForUpdate<Ipv6InterfaceData>()->assignAddress(entry.addr, false, simTime() + entry.validLifetime,
883  simTime() + entry.preferredLifetime, entry.hFlag);
884 
885  // moved from processRAPrefixInfoForAddrAutoConf()
886  // we can remove the old CoA now
887  if (!entry.CoA.isUnspecified())
888  ie->getProtocolDataForUpdate<Ipv6InterfaceData>()->removeAddress(entry.CoA);
889 
890  // set addresses on this interface to tentative=false
891  for (int i = 0; i < ie->getProtocolData<Ipv6InterfaceData>()->getNumAddresses(); i++) {
892  // TODO improve this code so that only addresses are permanently assigned
893  // which are formed based on the new prefix from the RA
894  Ipv6Address addr = ie->getProtocolData<Ipv6InterfaceData>()->getAddress(i);
895  ie->getProtocolDataForUpdate<Ipv6InterfaceData>()->permanentlyAssign(addr);
896  }
897 
898  // if we have MIPv6 protocols on this node we will eventually have to
899  // call some appropriate methods
900  if (rt6->isMobileNode()) {
901  if (entry.hFlag == false) // if we are not in the home network, send BUs
902  mipv6->initiateMipv6Protocol(ie, tentativeAddr);
903  /*
904  else if ( entry.returnedHome ) // if we are again in the home network
905  {
906  ASSERT(entry.CoA.isUnspecified() == false);
907  mipv6->returningHome(entry.CoA, ie); // initiate the returning home procedure
908  }*/
909  }
910 
911  dadGlobalList.erase(it->first);
912  }
913 
914  // an optimization to make sure that the access router on the link gets our L2 address
915 // sendUnsolicitedNA(ie);
916 
917  // =================================Start: Zarrar Yousaf 08.07.07 ===============================================
918  /* == Calling the routine to assign global scope adddresses to the the routers only. At present during the simulation initialization, the Ipv6FlatNetworkConfigurator assigns a 64 bit prefix to the routers but for xMIPv6 operation, we need full 128bit global scope address, only for routers. The call to autoConfRouterGlobalScopeAddress() will autoconfigure the full 128 bit global scope address, which will be used by the MN in its BU message destination address, especially for home registeration.
919  */
920  if (rt6->isRouter() && !(ie->isLoopback())) {
921  for (int i = 0; i < ie->getProtocolData<Ipv6InterfaceData>()->getNumAdvPrefixes(); i++) {
922  Ipv6Address globalAddress = ie->getProtocolDataForUpdate<Ipv6InterfaceData>()->autoConfRouterGlobalScopeAddress(i);
923  ie->getProtocolDataForUpdate<Ipv6InterfaceData>()->assignAddress(globalAddress, false, 0, 0);
924 // ie->getProtocolData<Ipv6InterfaceData>()->deduceAdvPrefix(); //commented out but the above two statements can be replaced with this single statement. But i am using the above two statements for clarity reasons.
925  }
926  }
927  // ==================================End: Zarrar Yousaf 08.07.07===========================================
928 #endif /* INET_WITH_xMIPv6 */
929 
930  /*RFC 2461: Section 6.3.7 2nd Paragraph
931  Before a host sends an initial solicitation, it SHOULD delay the
932  transmission for a random amount of time between 0 and
933  MAX_RTR_SOLICITATION_DELAY. This serves to alleviate congestion when
934  many hosts start up on a link at the same time, such as might happen
935  after recovery from a power failure.*/
936  // TODO Placing these operations here means fast router solicitation is
937  // not adopted. Will relocate.
938  if (ie->getProtocolData<Ipv6InterfaceData>()->getAdvSendAdvertisements() == false) {
939  EV_INFO << "creating router discovery message timer\n";
940  cMessage *rtrDisMsg = new cMessage("initiateRTRDIS", MK_INITIATE_RTRDIS);
941  rtrDisMsg->setContextPointer(ie);
942  simtime_t interval = uniform(0, ie->getProtocolData<Ipv6InterfaceData>()->_getMaxRtrSolicitationDelay()); // random delay
943  scheduleAfter(interval, rtrDisMsg);
944  }
945 }

Referenced by assignLinkLocalAddress(), and processDadTimeout().

◆ numInitStages()

virtual int inet::Ipv6NeighbourDiscovery::numInitStages ( ) const
inlineoverrideprotectedvirtual
158 { return NUM_INIT_STAGES; }

◆ processArTimeout()

void inet::Ipv6NeighbourDiscovery::processArTimeout ( cMessage *  arTimeoutMsg)
protectedvirtual

Resends a NS packet to the address intended for address resolution.

TODO Not implemented yet!

683 {
684  // AR timeouts are cancelled when a valid solicited NA is received.
685  Neighbour *nce = (Neighbour *)arTimeoutMsg->getContextPointer();
686  const Key *nceKey = nce->nceKey;
687  Ipv6Address nsTargetAddr = nceKey->address;
688  NetworkInterface *ie = ift->getInterfaceById(nceKey->interfaceID);
689  EV_INFO << "Num Of NS Sent:" << nce->numOfARNSSent << endl;
690  EV_INFO << "Max Multicast Solicitation:" << ie->getProtocolData<Ipv6InterfaceData>()->_getMaxMulticastSolicit() << endl;
691 
692  if (nce->numOfARNSSent < ie->getProtocolData<Ipv6InterfaceData>()->_getMaxMulticastSolicit()) {
693  EV_INFO << "Sending another Address Resolution NS message" << endl;
694  Ipv6Address nsDestAddr = nsTargetAddr.formSolicitedNodeMulticastAddress();
695  createAndSendNsPacket(nsTargetAddr, nsDestAddr, nce->nsSrcAddr, ie);
696  nce->numOfARNSSent++;
697  scheduleAfter(ie->getProtocolData<Ipv6InterfaceData>()->_getRetransTimer(), arTimeoutMsg);
698  return;
699  }
700 
701  EV_WARN << "Address Resolution has failed." << endl;
703  EV_INFO << "Deleting AR timeout msg\n";
704  delete arTimeoutMsg;
705 }

Referenced by handleMessage().

◆ processDadTimeout()

void inet::Ipv6NeighbourDiscovery::processDadTimeout ( cMessage *  msg)
protectedvirtual

Sends a scheduled DAD NS packet.

If number of sends is equals or more than dupAddrDetectTransmits, then permantly assign target link local address as permanent address for given interface entry.

839 {
840  DadEntry *dadEntry = (DadEntry *)msg->getContextPointer();
841  NetworkInterface *ie = ift->getInterfaceById(dadEntry->interfaceId);
842  Ipv6Address tentativeAddr = dadEntry->address;
843  // Here, we need to check how many DAD messages for the interface entry were
844  // sent vs. DupAddrDetectTransmits
845  EV_DETAIL << "numOfDADMessagesSent is: " << dadEntry->numNSSent << endl;
846  EV_DETAIL << "dupAddrDetectTrans is: " << ie->getProtocolData<Ipv6InterfaceData>()->getDupAddrDetectTransmits() << endl;
847 
848  if (dadEntry->numNSSent < ie->getProtocolData<Ipv6InterfaceData>()->getDupAddrDetectTransmits()) {
849  bubble("Sending another DAD NS message.");
850  Ipv6Address destAddr = tentativeAddr.formSolicitedNodeMulticastAddress();
851  createAndSendNsPacket(dadEntry->address, destAddr, Ipv6Address::UNSPECIFIED_ADDRESS, ie);
852  dadEntry->numNSSent++;
853  // Reuse the received msg
854  scheduleAfter(ie->getProtocolData<Ipv6InterfaceData>()->getRetransTimer(), msg);
855  }
856  else {
857  bubble("Max number of DAD messages for interface sent. Address is unique.");
858  dadList.erase(dadEntry);
859  EV_DETAIL << "delete dadEntry and msg\n";
860  delete dadEntry;
861  delete msg;
862 
863  makeTentativeAddressPermanent(tentativeAddr, ie);
864  }
865 }

Referenced by handleMessage().

◆ processIpv6Datagram()

void inet::Ipv6NeighbourDiscovery::processIpv6Datagram ( Packet packet)
protectedvirtual
216 {
217  const auto& msg = packet->peekAtFront<Ipv6Header>();
218  EV_INFO << "Packet " << packet << " arrived from Ipv6 module.\n";
219 
220  Ipv6NdControlInfo *ctrl = check_and_cast<Ipv6NdControlInfo *>(packet->getControlInfo());
221  int nextHopIfID = ctrl->getInterfaceId();
222  Ipv6Address nextHopAddr = ctrl->getNextHop();
223 // bool fromHL = ctrl->getFromHL();
224 
225  if (nextHopIfID == -1 || nextHopAddr.isUnspecified()) {
226  EV_INFO << "Determining Next Hop" << endl;
227  nextHopAddr = determineNextHop(msg->getDestAddress(), nextHopIfID);
228  ctrl->setInterfaceId(nextHopIfID);
229  ctrl->setNextHop(nextHopAddr);
230  }
231 
232  if (nextHopIfID == -1) {
233  // draft-ietf-ipv6-2461bis-04 has omitted on-link assumption.
234  // draft-ietf-v6ops-onlinkassumption-03 explains why.
235  delete packet->removeControlInfo();
236  icmpv6->sendErrorMessage(packet, ICMPv6_DESTINATION_UNREACHABLE, NO_ROUTE_TO_DEST);
237  delete packet;
238  return;
239  }
240 
241  EV_INFO << "Next Hop Address is: " << nextHopAddr << " on interface: " << nextHopIfID << endl;
242 
243  // RFC2461: Section 5.2 Conceptual Sending Algorithm
244  // Once the IP address of the next-hop node is known, the sender examines the
245  // Neighbor Cache for link-layer information about that neighbor.
246  Neighbour *nce = neighbourCache.lookup(nextHopAddr, nextHopIfID);
247 
248  if (nce == nullptr) {
249  EV_INFO << "No Entry exists in the Neighbour Cache.\n";
250  NetworkInterface *ie = ift->getInterfaceById(nextHopIfID);
251  if (ie->isPointToPoint()) {
252  // the sender creates one, sets its state to STALE,
253  EV_DETAIL << "Creating an STALE entry in the neighbour cache.\n";
254  nce = neighbourCache.addNeighbour(nextHopAddr, nextHopIfID, MacAddress::UNSPECIFIED_ADDRESS);
255  }
256  else {
257  // the sender creates one, sets its state to INCOMPLETE,
258  EV_DETAIL << "Creating an INCOMPLETE entry in the neighbour cache.\n";
259  nce = neighbourCache.addNeighbour(nextHopAddr, nextHopIfID);
260 
261  // initiates Address Resolution,
262  EV_DETAIL << "Initiating Address Resolution for:" << nextHopAddr
263  << " on Interface:" << nextHopIfID << endl;
264  initiateAddressResolution(msg->getSrcAddress(), nce);
265  }
266  }
267 
268  /*
269  * A host is capable of sending packets to a destination in all states except INCOMPLETE
270  * or when there is no corresponding NC entry. In INCOMPLETE state the data packets are
271  * queued pending completion of address resolution.
272  */
273  switch (nce->reachabilityState) {
275  EV_INFO << "Reachability State is INCOMPLETE. Address Resolution already initiated.\n";
276  EV_INFO << "Add packet to entry's queue until Address Resolution is complete.\n";
277  bubble("Packet added to queue until Address Resolution is complete.");
278  nce->pendingPackets.push_back(packet);
279  pendingQueue.insert(packet);
280  break;
282  EV_INFO << "Reachability State is STALE.\n";
283  send(packet, "ipv6Out");
285  break;
287  EV_INFO << "Next hop is REACHABLE, sending packet to next-hop address.";
288  send(packet, "ipv6Out");
289  break;
291  EV_INFO << "Next hop is in DELAY state, sending packet to next-hop address.";
292  send(packet, "ipv6Out");
293  break;
295  EV_INFO << "Next hop is in PROBE state, sending packet to next-hop address.";
296  send(packet, "ipv6Out");
297  break;
298  default:
299  throw cRuntimeError("Unknown Neighbour cache entry state.");
300  break;
301  }
302 }

Referenced by handleMessage().

◆ processNaForIncompleteNceState()

void inet::Ipv6NeighbourDiscovery::processNaForIncompleteNceState ( const Ipv6NeighbourAdvertisement na,
Ipv6NeighbourCache::Neighbour nce 
)
protectedvirtual
2254 {
2255  MacAddress naMacAddr;
2256  if (auto tla = check_and_cast_nullable<const Ipv6NdTargetLinkLayerAddress *>(na->getOptions().findOption(IPv6ND_TARGET_LINK_LAYER_ADDR_OPTION)))
2257  naMacAddr = tla->getLinkLayerAddress();
2258  bool naRouterFlag = na->getRouterFlag();
2259  bool naSolicitedFlag = na->getSolicitedFlag();
2260  const Key *nceKey = nce->nceKey;
2261  NetworkInterface *ie = ift->getInterfaceById(nceKey->interfaceID);
2262 
2263  /*If the target's neighbour Cache entry is in the INCOMPLETE state when the
2264  advertisement is received, one of two things happens.*/
2265  if (naMacAddr.isUnspecified()) {
2266  /*If the link layer has addresses and no Target Link-Layer address option
2267  is included, the receiving node SHOULD silently discard the received
2268  advertisement.*/
2269  EV_INFO << "No MAC Address specified in NA. Ignoring NA\n";
2270  return;
2271  }
2272  else {
2273  // Otherwise, the receiving node performs the following steps:
2274  // - It records the link-layer address in the neighbour Cache entry.
2275  EV_INFO << "ND is updating Neighbour Cache Entry.\n";
2276  nce->macAddress = naMacAddr;
2277 
2278  // - If the advertisement's Solicited flag is set, the state of the
2279  // entry is set to REACHABLE, otherwise it is set to STALE.
2280  if (naSolicitedFlag == true) {
2281  nce->reachabilityState = Ipv6NeighbourCache::REACHABLE;
2282  EV_INFO << "Reachability confirmed through successful Addr Resolution.\n";
2283  nce->reachabilityExpires = simTime() + ie->getProtocolData<Ipv6InterfaceData>()->_getReachableTime();
2284  }
2285  else
2286  nce->reachabilityState = Ipv6NeighbourCache::STALE;
2287 
2288  // - It sets the IsRouter flag in the cache entry based on the Router
2289  // flag in the received advertisement.
2290  nce->isRouter = naRouterFlag;
2291  if (nce->isDefaultRouter() && !nce->isRouter)
2293 
2294  // - It sends any packets queued for the neighbour awaiting address
2295  // resolution.
2297  cancelAndDelete(nce->arTimer);
2298  nce->arTimer = nullptr;
2299  }
2300 }

Referenced by processNaPacket().

◆ processNaForOtherNceStates()

void inet::Ipv6NeighbourDiscovery::processNaForOtherNceStates ( const Ipv6NeighbourAdvertisement na,
Ipv6NeighbourCache::Neighbour nce 
)
protectedvirtual
2303 {
2304  bool naRouterFlag = na->getRouterFlag();
2305  bool naSolicitedFlag = na->getSolicitedFlag();
2306  bool naOverrideFlag = na->getOverrideFlag();
2307  MacAddress naMacAddr;
2308  if (auto tla = check_and_cast_nullable<const Ipv6NdTargetLinkLayerAddress *>(na->getOptions().findOption(IPv6ND_TARGET_LINK_LAYER_ADDR_OPTION)))
2309  naMacAddr = tla->getLinkLayerAddress();
2310  const Key *nceKey = nce->nceKey;
2311  NetworkInterface *ie = ift->getInterfaceById(nceKey->interfaceID);
2312 
2313  /*draft-ietf-ipv6-2461bis-04
2314  Section 7.2.5: Receipt of Neighbour Advertisements
2315  If the target's Neighbor Cache entry is in any state other than INCOMPLETE
2316  when the advertisement is received, the following actions take place:*/
2317 
2318  if (naOverrideFlag == false && !(naMacAddr.equals(nce->macAddress))
2319  && !(naMacAddr.isUnspecified()))
2320  {
2321  EV_INFO << "NA override is FALSE and NA MAC addr is different.\n";
2322 
2323  // I. If the Override flag is clear and the supplied link-layer address
2324  // differs from that in the cache, then one of two actions takes place:
2325  // (Note: An unspecified MAC should not be compared with the NCE's mac!)
2326  // a. If the state of the entry is REACHABLE,
2327  if (nce->reachabilityState == Ipv6NeighbourCache::REACHABLE) {
2328  EV_INFO << "NA mac is different. Change NCE state from REACHABLE to STALE\n";
2329  // set it to STALE, but do not update the entry in any other way.
2330  nce->reachabilityState = Ipv6NeighbourCache::STALE;
2331  }
2332  else
2333  // b. Otherwise, the received advertisement should be ignored and
2334  // MUST NOT update the cache.
2335  EV_INFO << "NCE is not in REACHABLE state. Ignore NA.\n";
2336  }
2337  else if (naOverrideFlag == true || naMacAddr.equals(nce->macAddress)
2338  || naMacAddr.isUnspecified())
2339  {
2340  EV_INFO << "NA override flag is TRUE. or Advertised MAC is same as NCE's. or"
2341  << " NA MAC is not specified.\n";
2342  /*II. If the Override flag is set, or the supplied link-layer address
2343  is the same as that in the cache, or no Target Link-layer address
2344  option was supplied, the received advertisement MUST update the
2345  Neighbor Cache entry as follows:*/
2346 
2347  /*- The link-layer address in the Target Link-Layer Address option
2348  MUST be inserted in the cache (if one is supplied and is
2349  Different than the already recorded address).*/
2350  if (!(naMacAddr.isUnspecified()) && !(naMacAddr.equals(nce->macAddress))) {
2351  EV_INFO << "Updating NCE's MAC addr with NA's.\n";
2352  nce->macAddress = naMacAddr;
2353  }
2354 
2355  // - If the Solicited flag is set,
2356  if (naSolicitedFlag == true) {
2357  EV_INFO << "Solicited Flag is TRUE. Set NCE state to REACHABLE.\n";
2358  // the state of the entry MUST be set to REACHABLE.
2359  nce->reachabilityState = Ipv6NeighbourCache::REACHABLE;
2360  // We have to cancel the NUD self timer message if there is one.
2361 
2362  cMessage *msg = nce->nudTimeoutEvent;
2363  if (msg != nullptr) {
2364  EV_INFO << "NUD in progress. Cancelling NUD Timer\n";
2365  bubble("Reachability Confirmed via NUD.");
2366  nce->reachabilityExpires = simTime() + ie->getProtocolData<Ipv6InterfaceData>()->_getReachableTime();
2367  cancelAndDelete(msg);
2368  nce->nudTimeoutEvent = nullptr;
2369  }
2370  }
2371  else {
2372  // If the Solicited flag is zero
2373  EV_INFO << "Solicited Flag is FALSE.\n";
2374  // and the link layer address was updated with a different address
2375 
2376  if (!(naMacAddr.equals(nce->macAddress))) {
2377  EV_INFO << "NA's MAC is different from NCE's.Set NCE state to STALE\n";
2378  // the state MUST be set to STALE.
2379  nce->reachabilityState = Ipv6NeighbourCache::STALE;
2380  }
2381  else
2382  // Otherwise, the entry's state remains unchanged.
2383  EV_INFO << "NA's MAC is the same as NCE's. State remains unchanged.\n";
2384  }
2385  // (Next paragraph with explanation is omitted.-WEI)
2386 
2387  /*- The IsRouter flag in the cache entry MUST be set based on the
2388  Router flag in the received advertisement.*/
2389  EV_INFO << "Updating NCE's router flag to " << naRouterFlag << endl;
2390  nce->isRouter = naRouterFlag;
2391 
2392  /*In those cases where the IsRouter flag changes from TRUE to FALSE as a
2393  result of this update, the node MUST remove that router from the Default
2394  Router List and update the Destination Cache entries for all destinations
2395  using that neighbor as a router as specified in Section 7.3.3. This is
2396  needed to detect when a node that is used as a router stops forwarding
2397  packets due to being configured as a host.*/
2398  if (nce->isDefaultRouter() && !nce->isRouter)
2400 
2401  // TODO remove destination cache entries
2402  }
2403 }

Referenced by processNaPacket().

◆ processNaPacket()

void inet::Ipv6NeighbourDiscovery::processNaPacket ( Packet packet,
const Ipv6NeighbourAdvertisement na 
)
protectedvirtual
2180 {
2181  if (validateNaPacket(packet, na) == false) {
2182  delete packet;
2183  return;
2184  }
2185 
2186  // Neighbour Advertisement Information
2187  Ipv6Address naTargetAddr = na->getTargetAddress();
2188 
2189  // First, we check if the target address in NA is found in the interface it
2190  // was received on is tentative.
2191  NetworkInterface *ie = ift->getInterfaceById(packet->getTag<InterfaceInd>()->getInterfaceId());
2192  if (ie->getProtocolData<Ipv6InterfaceData>()->isTentativeAddress(naTargetAddr)) {
2193  throw cRuntimeError("Duplicate Address Detected! Manual attention needed!");
2194  }
2195  // Logic as defined in Section 7.2.5
2196  Neighbour *neighbourEntry = neighbourCache.lookup(naTargetAddr, ie->getInterfaceId());
2197 
2198  if (neighbourEntry == nullptr) {
2199  EV_INFO << "NA received. Target Address not found in Neighbour Cache\n";
2200  EV_INFO << "Dropping NA packet.\n";
2201  delete packet;
2202  return;
2203  }
2204 
2205  // Target Address has entry in Neighbour Cache
2206  EV_INFO << "NA received. Target Address found in Neighbour Cache\n";
2207 
2208  if (neighbourEntry->reachabilityState == Ipv6NeighbourCache::INCOMPLETE)
2209  processNaForIncompleteNceState(na, neighbourEntry);
2210  else
2211  processNaForOtherNceStates(na, neighbourEntry);
2212  delete packet;
2213 }

Referenced by processNDMessage().

◆ processNDMessage()

void inet::Ipv6NeighbourDiscovery::processNDMessage ( Packet packet,
const Icmpv6Header msg 
)
protectedvirtual
190 {
191  if (auto rs = dynamic_cast<const Ipv6RouterSolicitation *>(icmpv6Header)) {
192  processRsPacket(packet, rs);
193  }
194  else if (auto ra = dynamic_cast<const Ipv6RouterAdvertisement *>(icmpv6Header)) {
195  processRaPacket(packet, ra);
196  }
197  else if (auto ns = dynamic_cast<const Ipv6NeighbourSolicitation *>(icmpv6Header)) {
198  processNsPacket(packet, ns);
199  }
200  else if (auto na = dynamic_cast<const Ipv6NeighbourAdvertisement *>(icmpv6Header)) {
201  processNaPacket(packet, na);
202  }
203  else if (auto redirect = dynamic_cast<const Ipv6Redirect *>(icmpv6Header)) {
204  processRedirectPacket(redirect);
205  }
206  else {
207  throw cRuntimeError("Unrecognized ND message!");
208  }
209 }

Referenced by handleMessage().

◆ processNsForNonTentativeAddress()

void inet::Ipv6NeighbourDiscovery::processNsForNonTentativeAddress ( Packet packet,
const Ipv6NeighbourSolicitation ns,
NetworkInterface ie 
)
protectedvirtual
1948 {
1949  // Neighbour Solicitation Information
1950 // MacAddress nsMacAddr = ns->getSourceLinkLayerAddress();
1951 
1952  // target addr is not tentative addr
1953  // solicitation processed as described in RFC2461:section 7.2.3
1954  if (packet->getTag<L3AddressInd>()->getSrcAddress().toIpv6().isUnspecified()) {
1955  EV_INFO << "Address is duplicate! Inform Sender of duplicate address!\n";
1956  sendSolicitedNa(packet, ns, ie);
1957  }
1958  else {
1959  processNsWithSpecifiedSrcAddr(packet, ns, ie);
1960  }
1961 }

Referenced by processNsPacket().

◆ processNsForTentativeAddress()

void inet::Ipv6NeighbourDiscovery::processNsForTentativeAddress ( Packet packet,
const Ipv6NeighbourSolicitation ns 
)
protectedvirtual
1921 {
1922  // Control Information
1923  Ipv6Address nsSrcAddr = packet->getTag<L3AddressInd>()->getSrcAddress().toIpv6();
1924 // Ipv6Address nsDestAddr = nsCtrlInfo->getDestAddr();
1925 
1926  ASSERT(nsSrcAddr.isUnicast() || nsSrcAddr.isUnspecified());
1927  // solicitation is processed as described in RFC2462:section 5.4.3
1928 
1929  if (nsSrcAddr.isUnspecified()) {
1930  EV_INFO << "Source Address is UNSPECIFIED. Sender is performing DAD\n";
1931 
1932  // Sender performing Duplicate Address Detection
1933  if (rt6->isLocalAddress(nsSrcAddr)) // FIXME isLocalAddress(UNSPECIFIED) is always false!!! Must write another check for detecting source is myself/foreign node!!!
1934  EV_INFO << "NS comes from myself. Ignoring NS\n";
1935  else {
1936  EV_INFO << "NS comes from another node. Address is duplicate!\n";
1937  throw cRuntimeError("Duplicate Address Detected! Manual Attention Required!");
1938  }
1939  }
1940  else if (nsSrcAddr.isUnicast()) {
1941  // Sender performing address resolution
1942  EV_INFO << "Sender is performing Address Resolution\n";
1943  EV_INFO << "Target Address is tentative. Ignoring NS.\n";
1944  }
1945 }

Referenced by processNsPacket().

◆ processNsPacket()

void inet::Ipv6NeighbourDiscovery::processNsPacket ( Packet packet,
const Ipv6NeighbourSolicitation ns 
)
protectedvirtual
1843 {
1844  // Control Information
1845  NetworkInterface *ie = ift->getInterfaceById(packet->getTag<InterfaceInd>()->getInterfaceId());
1846 
1847  Ipv6Address nsTargetAddr = ns->getTargetAddress();
1848 
1849  // RFC 2461:Section 7.2.3
1850  // If target address is not a valid "unicast" or anycast address assigned to the
1851  // receiving interface, we should silently discard the packet.
1852  if (validateNsPacket(packet, ns) == false
1853  || ie->getProtocolData<Ipv6InterfaceData>()->hasAddress(nsTargetAddr) == false)
1854  {
1855  bubble("NS validation failed\n");
1856  delete packet;
1857  return;
1858  }
1859 
1860  bubble("NS validation passed.\n");
1861 
1862  if (ie->getProtocolData<Ipv6InterfaceData>()->isTentativeAddress(nsTargetAddr)) {
1863  // If the Target Address is tentative, the Neighbor Solicitation should
1864  // be processed as described in [ADDRCONF].
1865  EV_INFO << "Process NS for Tentative target address.\n";
1867  }
1868  else {
1869  // Otherwise, the following description applies.
1870  EV_INFO << "Process NS for Non-Tentative target address.\n";
1871  processNsForNonTentativeAddress(packet, ns, ie);
1872  }
1873  delete packet;
1874 }

Referenced by processNDMessage().

◆ processNsWithSpecifiedSrcAddr()

void inet::Ipv6NeighbourDiscovery::processNsWithSpecifiedSrcAddr ( Packet packet,
const Ipv6NeighbourSolicitation ns,
NetworkInterface ie 
)
protectedvirtual
1964 {
1965  // RFC 2461, Section 7.2.3
1966  /*If the Source Address is not the unspecified address and, on link layers
1967  that have addresses, the solicitation includes a Source Link-Layer Address
1968  option, then the recipient SHOULD create or update the Neighbor Cache entry
1969  for the IP Source Address of the solicitation.*/
1970 
1971  // Neighbour Solicitation Information
1972  MacAddress nsMacAddr;
1973  if (auto sla = check_and_cast_nullable<const Ipv6NdSourceLinkLayerAddress *>(ns->getOptions().findOption(IPv6ND_SOURCE_LINK_LAYER_ADDR_OPTION)))
1974  nsMacAddr = sla->getLinkLayerAddress();
1975  Ipv6Address nsL3SrcAddr = packet->getTag<L3AddressInd>()->getSrcAddress().toIpv6();
1976 
1977  int ifID = ie->getInterfaceId();
1978 
1979  // Look for the Neighbour Cache Entry
1980  Neighbour *entry = neighbourCache.lookup(nsL3SrcAddr, ifID);
1981 
1982  if (entry == nullptr) {
1983  /*If an entry does not already exist, the node SHOULD create a new one
1984  and set its reachability state to STALE as specified in Section 7.3.3.*/
1985  EV_INFO << "Neighbour Entry not found. Create a Neighbour Cache Entry.\n";
1986  neighbourCache.addNeighbour(nsL3SrcAddr, ifID, nsMacAddr);
1987  }
1988  else {
1989  /*If an entry already exists, and the cached link-layer address differs from
1990  the one in the received Source Link-Layer option,*/
1991  if (!(entry->macAddress.equals(nsMacAddr)) && !nsMacAddr.isUnspecified()) {
1992  // the cached address should be replaced by the received address
1993  entry->macAddress = nsMacAddr;
1994  // and the entry's reachability state MUST be set to STALE.
1995  entry->reachabilityState = Ipv6NeighbourCache::STALE;
1996  }
1997  }
1998 
1999  /*After any updates to the Neighbor Cache, the node sends a Neighbor
2000  Advertisement response as described in the next section.*/
2001  sendSolicitedNa(packet, ns, ie);
2002 }

Referenced by processNsForNonTentativeAddress().

◆ processNudTimeout()

void inet::Ipv6NeighbourDiscovery::processNudTimeout ( cMessage *  timeoutMsg)
protectedvirtual
491 {
492  EV_INFO << "NUD has timed out\n";
493  Neighbour *nce = (Neighbour *)timeoutMsg->getContextPointer();
494 
495  const Key *nceKey = nce->nceKey;
496  if (nceKey == nullptr)
497  throw cRuntimeError("The nceKey is nullptr at nce->MAC=%s, isRouter=%d",
498  nce->macAddress.str().c_str(), nce->isRouter);
499 
500  NetworkInterface *ie = ift->getInterfaceById(nceKey->interfaceID);
501 
502  if (nce->reachabilityState == Ipv6NeighbourCache::DELAY) {
503  /*If the entry is still in the DELAY state when the timer expires, the
504  entry's state changes to PROBE. If reachability confirmation is received,
505  the entry's state changes to REACHABLE.*/
506  EV_DETAIL << "Neighbour Entry is still in DELAY state.\n";
507  EV_DETAIL << "Entering PROBE state. Sending NS probe.\n";
508  nce->reachabilityState = Ipv6NeighbourCache::PROBE;
509  nce->numProbesSent = 0;
510  }
511 
512  /*If no response is received after waiting RetransTimer milliseconds
513  after sending the MAX_UNICAST_SOLICIT solicitations, retransmissions cease
514  and the entry SHOULD be deleted. Subsequent traffic to that neighbor will
515  recreate the entry and performs address resolution again.*/
516  if (nce->numProbesSent == (int)ie->getProtocolData<Ipv6InterfaceData>()->_getMaxUnicastSolicit()) {
517  EV_DETAIL << "Max number of probes have been sent." << endl;
518  EV_DETAIL << "Neighbour is Unreachable, removing NCE." << endl;
519  neighbourCache.remove(nceKey->address, nceKey->interfaceID); // remove nce from cache, cancel and delete timeoutMsg;
520  return;
521  }
522 
523  /*Upon entering the PROBE state, a node sends a unicast Neighbor Solicitation
524  message to the neighbor using the cached link-layer address.*/
525  createAndSendNsPacket(nceKey->address, nceKey->address,
526  ie->getProtocolData<Ipv6InterfaceData>()->getPreferredAddress(), ie);
527  nce->numProbesSent++;
528  /*While in the PROBE state, a node retransmits Neighbor Solicitation messages
529  every RetransTimer milliseconds until reachability confirmation is obtained.
530  Probes are retransmitted even if no additional packets are sent to the
531  neighbor.*/
532  scheduleAfter(ie->getProtocolData<Ipv6InterfaceData>()->_getRetransTimer(), timeoutMsg);
533 }

Referenced by handleMessage().

◆ processRaForRouterUpdates()

void inet::Ipv6NeighbourDiscovery::processRaForRouterUpdates ( Packet packet,
const Ipv6RouterAdvertisement ra 
)
protectedvirtual
1350 {
1351  EV_INFO << "Processing RA for Router Updates\n";
1352  // RFC2461: Section 6.3.4
1353  // Paragraphs 1 and 2 omitted.
1354 
1355  // On receipt of a valid Router Advertisement, a host extracts the source
1356  // address of the packet and does the following:
1357  Ipv6Address raSrcAddr = packet->getTag<L3AddressInd>()->getSrcAddress().toIpv6();
1358  NetworkInterface *ie = ift->getInterfaceById(packet->getTag<InterfaceInd>()->getInterfaceId());
1359  int ifID = ie->getInterfaceId();
1360 
1361  MacAddress sourceLinkLayerAddress;
1362  if (auto sla = check_and_cast_nullable<const Ipv6NdSourceLinkLayerAddress *>(ra->getOptions().findOption(IPv6ND_SOURCE_LINK_LAYER_ADDR_OPTION)))
1363  sourceLinkLayerAddress = sla->getLinkLayerAddress();
1364 
1365  /*- If the address is not already present in the host's Default Router List,
1366  and the advertisement's Router Lifetime is non-zero, create a new entry in
1367  the list, and initialize its invalidation timer value from the advertisement's
1368  Router Lifetime field.*/
1369  Neighbour *neighbour = neighbourCache.lookup(raSrcAddr, ifID);
1370 
1371 #ifdef INET_WITH_xMIPv6
1372  // update 3.9.07 - CB // if (neighbour == nullptr && (ra->homeAgentFlag() == true)) //the RA is from a Router acting as a Home Agent as well
1373 #endif /* INET_WITH_xMIPv6 */
1374 
1375  if (neighbour == nullptr) {
1376  EV_INFO << "Neighbour Cache Entry does not contain RA's source address\n";
1377  if (ra->getRouterLifetime() != 0) {
1378  EV_INFO << "RA's router lifetime is non-zero, creating an entry in the "
1379  << "Host's default router list with lifetime=" << ra->getRouterLifetime() << "\n";
1380 
1381 #ifdef INET_WITH_xMIPv6
1382  // initiate neighbour unreachability detection for existing routers and remove default route(r), 3.9.07 - CB
1383  // TODO improve this code
1384  routersUnreachabilityDetection(ie);
1385 #endif /* INET_WITH_xMIPv6 */
1386 
1387  // If a Neighbor Cache entry is created for the router its reachability
1388  // state MUST be set to STALE as specified in Section 7.3.3.
1389  neighbour = neighbourCache.addRouter(raSrcAddr, ifID,
1390  sourceLinkLayerAddress, simTime() + ra->getRouterLifetime()
1391 #ifdef INET_WITH_xMIPv6
1392  , ra->getHomeAgentFlag()
1393 #endif /* INET_WITH_xMIPv6 */
1394  );
1395  // According to Greg, we should add a default route for hosts as well!
1396  rt6->addDefaultRoute(raSrcAddr, ifID, simTime() + ra->getRouterLifetime());
1397  }
1398  else {
1399  EV_INFO << "Router Lifetime is 0, adding NON-default router.\n";
1400  // WEI-The router is advertising itself, BUT not as a default router.
1401  if (sourceLinkLayerAddress.isUnspecified())
1402  neighbour = neighbourCache.addNeighbour(raSrcAddr, ifID);
1403  else
1404  neighbour = neighbourCache.addNeighbour(raSrcAddr, ifID,
1405  sourceLinkLayerAddress);
1406  neighbour->isRouter = true;
1407  }
1408  }
1409  else {
1410  // If no Source Link-Layer Address is included, but a corresponding Neighbor
1411  // Cache entry exists, its IsRouter flag MUST be set to TRUE.
1412  neighbour->isRouter = true;
1413 
1414  // If a cache entry already exists and is updated with a different link-
1415  // layer address the reachability state MUST also be set to STALE.
1416  if (sourceLinkLayerAddress.isUnspecified() == false &&
1417  neighbour->macAddress.equals(sourceLinkLayerAddress) == false)
1418  neighbour->macAddress = sourceLinkLayerAddress;
1419 
1420  /*- If the address is already present in the host's Default Router List
1421  as a result of a previously-received advertisement, reset its invalidation
1422  timer to the Router Lifetime value in the newly-received advertisement.*/
1423  neighbour->routerExpiryTime = simTime() + ra->getRouterLifetime();
1424 
1425  /*- If the address is already present in the host's Default Router List
1426  and the received Router Lifetime value is zero, immediately time-out the
1427  entry as specified in Section 6.3.5.*/
1428  if (ra->getRouterLifetime() == 0) {
1429  EV_INFO << "RA's router lifetime is ZERO. Timing-out entry.\n";
1430  timeoutDefaultRouter(raSrcAddr, ifID);
1431  }
1432  }
1433 
1434  // Paragraph Omitted.
1435 
1436  // If the received Cur Hop Limit value is non-zero the host SHOULD set
1437  // its CurHopLimit variable to the received value.
1438  if (ra->getCurHopLimit() != 0) {
1439  EV_INFO << "RA's Cur Hop Limit is non-zero. Setting host's Cur Hop Limit to "
1440  << "received value.\n";
1441  ie->getProtocolDataForUpdate<Ipv6InterfaceData>()->setCurHopLimit(ra->getCurHopLimit());
1442  }
1443 
1444  // If the received Reachable Time value is non-zero the host SHOULD set its
1445  // BaseReachableTime variable to the received value.
1446  if (ra->getReachableTime() != 0) {
1447  EV_INFO << "RA's reachable time is non-zero ";
1448 
1449  if (ra->getReachableTime() != SIMTIME_DBL(ie->getProtocolData<Ipv6InterfaceData>()->getReachableTime())) {
1450  EV_INFO << " and RA's and Host's reachable time differ, \nsetting host's base"
1451  << " reachable time to received value.\n";
1452  ie->getProtocolDataForUpdate<Ipv6InterfaceData>()->setBaseReachableTime(ra->getReachableTime());
1453  // If the new value differs from the previous value, the host SHOULD
1454  // recompute a new random ReachableTime value.
1455  ie->getProtocolDataForUpdate<Ipv6InterfaceData>()->setReachableTime(ie->getProtocolDataForUpdate<Ipv6InterfaceData>()->generateReachableTime());
1456  }
1457 
1458  EV_INFO << endl;
1459  }
1460 
1461  // The RetransTimer variable SHOULD be copied from the Retrans Timer field,
1462  // if the received value is non-zero.
1463  if (ra->getRetransTimer() != 0) {
1464  EV_INFO << "RA's retrans timer is non-zero, copying retrans timer variable.\n";
1465  ie->getProtocolDataForUpdate<Ipv6InterfaceData>()->setRetransTimer(ra->getRetransTimer());
1466  }
1467 
1468  /*If the MTU option is present, hosts SHOULD copy the option's value into
1469  LinkMTU so long as the value is greater than or equal to the minimum link MTU
1470  [Ipv6] and does not exceed the default LinkMTU value specified in the link
1471  type specific document (e.g., [Ipv6-ETHER]).*/
1472  // TODO not done yet
1473 
1474  processRaPrefixInfo(ra, ie);
1475 }

Referenced by processRaPacket().

◆ processRaPacket()

void inet::Ipv6NeighbourDiscovery::processRaPacket ( Packet packet,
const Ipv6RouterAdvertisement ra 
)
protectedvirtual
1288 {
1289  NetworkInterface *ie = ift->getInterfaceById(packet->getTag<InterfaceInd>()->getInterfaceId());
1290  if (ie->getProtocolData<Ipv6InterfaceData>()->getAdvSendAdvertisements()) {
1291  EV_INFO << "Interface is an advertising interface, dropping RA message.\n";
1292  delete packet;
1293  return;
1294  }
1295  else {
1296  if (validateRaPacket(packet, ra) == false) {
1297  delete packet;
1298  return;
1299  }
1300 
1301 #ifdef INET_WITH_xMIPv6
1302  if (ie->getProtocolDataForUpdate<Ipv6InterfaceData>()->isDadInProgress()) {
1303  // in case we are currently performing DAD we ignore this RA
1304  // TODO improve this procedure in order to allow reinitiating DAD
1305  // (which means cancel current DAD, start new DAD)
1306  delete packet;
1307  return;
1308  }
1309 #endif /* INET_WITH_xMIPv6 */
1310 
1311  cancelRouterDiscovery(ie); // Cancel router discovery if it is in progress.
1312  EV_INFO << "Interface is a host, processing RA.\n";
1313 
1314  processRaForRouterUpdates(packet, ra); // See RFC2461: Section 6.3.4
1315 
1316  // Possible options
1317 // MacAddress macAddress = ra->getSourceLinkLayerAddress();
1318 // uint mtu = ra->getMTU();
1319  for (int i = 0; i < (int)ra->getOptions().getOptionArraySize(); i++) {
1320  auto option = ra->getOptions().getOption(i);
1321  if (option->getType() != IPv6ND_PREFIX_INFORMATION)
1322  continue;
1323  const Ipv6NdPrefixInformation& prefixInfo = *check_and_cast<const Ipv6NdPrefixInformation *>(option);
1324  if (prefixInfo.getAutoAddressConfFlag() == true) { // If auto addr conf is set
1325 #ifndef INET_WITH_xMIPv6
1326  processRaPrefixInfoForAddrAutoConf(prefixInfo, ie); // We process prefix Info and form an addr
1327 #else /* INET_WITH_xMIPv6 */
1328  processRaPrefixInfoForAddrAutoConf(prefixInfo, ie, ra->getHomeAgentFlag()); // then calling the overloaded function for address configuration. The address conf for MN is different from other nodes as it needs to classify the newly formed address as HoA or CoA, depending on the status of the H-Flag. (Zarrar Yousaf 20.07.07)
1329 #endif /* INET_WITH_xMIPv6 */
1330  }
1331 
1332 #ifdef INET_WITH_xMIPv6
1333  // When in foreign network(s), the MN needs info about its HA address and its own Home Address (HoA), when sending BU to HA and CN(s). Therefore while in the home network I intialise struct HomeNetworkInfo{} with HoA and HA address, which will eventually be used by the MN while sending BUs from within visit networks. (Zarrar Yousaf 12.07.07)
1334  if (ra->getHomeAgentFlag() && (prefixInfo.getRouterAddressFlag() == true)) { // If R-Flag is set and RA is from HA
1335  // homeNetworkInfo now carries HoA, global unicast HA address and the home network prefix
1336  // update 4.9.07 - CB
1337  Ipv6Address HoA = ie->getProtocolData<Ipv6InterfaceData>()->getGlobalAddress(); // MN's home address
1338  Ipv6Address HA = packet->getTag<L3AddressInd>()->getSrcAddress().toIpv6().setPrefix(prefixInfo.getPrefix(), prefixInfo.getPrefixLength());
1339  EV_DETAIL << "The HoA of MN is: " << HoA << ", MN's HA Address is: " << HA
1340  << " and the home prefix is " << prefixInfo.getPrefix() << endl;
1341  ie->getProtocolDataForUpdate<Ipv6InterfaceData>()->updateHomeNetworkInfo(HoA, HA, prefixInfo.getPrefix(), prefixInfo.getPrefixLength()); // populate the HoA of MN, the HA global scope address and the home network prefix
1342  }
1343 #endif /* INET_WITH_xMIPv6 */
1344  }
1345  }
1346  delete packet;
1347 }

Referenced by processNDMessage().

◆ processRaPrefixInfo()

void inet::Ipv6NeighbourDiscovery::processRaPrefixInfo ( const Ipv6RouterAdvertisement ra,
NetworkInterface ie 
)
protectedvirtual
1478 {
1479  // Continued from section 6.3.4
1480  /*Prefix Information options that have the "on-link" (L) flag set indicate a
1481  prefix identifying a range of addresses that should be considered on-link.
1482  Note, however, that a Prefix Information option with the on-link flag set to
1483  zero conveys no information concerning on-link determination and MUST NOT be
1484  interpreted to mean that addresses covered by the prefix are off-link. The
1485  only way to cancel a previous on-link indication is to advertise that prefix
1486  with the L-bit set and the Lifetime set to zero. The default behavior (see
1487  Section 5.2) when sending a packet to an address for which no information is
1488  known about the on-link status of the address is to forward the packet to a
1489  default router; the reception of a Prefix Information option with the "on-link "
1490  (L) flag set to zero does not change this behavior. The reasons for an address
1491  being treated as on-link is specified in the definition of "on-link" in
1492  Section 2.1. Prefixes with the on-link flag set to zero would normally have
1493  the autonomous flag set and be used by [ADDRCONF].*/
1494  Ipv6NdPrefixInformation prefixInfo;
1495  // For each Prefix Information option
1496  for (int i = 0; i < (int)ra->getOptions().getOptionArraySize(); i++) {
1497  auto option = ra->getOptions().getOption(i);
1498  if (option->getType() != IPv6ND_PREFIX_INFORMATION)
1499  continue;
1500  const Ipv6NdPrefixInformation& prefixInfo = *check_and_cast<const Ipv6NdPrefixInformation *>(option);
1501  if (!prefixInfo.getOnlinkFlag())
1502  break; // skip to next prefix option
1503 
1504  // with the on-link flag set, a host does the following:
1505  EV_INFO << "Fetching Prefix Information: option " << i + 1 << " of "
1506  << ra->getOptions().getOptionArraySize() << endl;
1507  uint prefixLength = prefixInfo.getPrefixLength();
1508  simtime_t validLifetime = prefixInfo.getValidLifetime();
1509 // uint preferredLifetime = prefixInfo.getPreferredLifetime();
1510  Ipv6Address prefix = prefixInfo.getPrefix();
1511 
1512  // - If the prefix is the link-local prefix, silently ignore the Prefix
1513  // Information option.
1514  if (prefix.isLinkLocal()) {
1515  EV_INFO << "Prefix is link-local, ignoring prefix.\n";
1516  return;
1517  }
1518 
1519  // - If the prefix is not already present in the Prefix List,
1520  if (!rt6->isPrefixPresent(prefix)) {
1521  // and the Prefix Information option's Valid Lifetime field is non-zero,
1522  if (validLifetime != 0) {
1523  /*create a new entry for the prefix and initialize its invalidation
1524  timer to the Valid Lifetime value in the Prefix Information option.*/
1525  rt6->addOrUpdateOnLinkPrefix(prefix, prefixLength, ie->getInterfaceId(),
1526  simTime() + validLifetime);
1527  }
1528  /*- If the Prefix Information option's Valid Lifetime field is zero,
1529  and the prefix is not present in the host's Prefix List,
1530  silently ignore the option.*/
1531  }
1532  else {
1533  /* If the new Lifetime value is zero, time-out the prefix immediately
1534  (see Section 6.3.5).*/
1535  if (validLifetime == 0) {
1536  EV_INFO << "Prefix Info's valid lifetime is 0, time-out prefix\n";
1537  rt6->deleteOnLinkPrefix(prefix, prefixLength);
1538  return;
1539  }
1540 
1541  /*- If the prefix is already present in the host's Prefix List as
1542  the result of a previously-received advertisement, reset its
1543  invalidation timer to the Valid Lifetime value in the Prefix
1544  Information option.*/
1545  rt6->addOrUpdateOnLinkPrefix(prefix, prefixLength, ie->getInterfaceId(),
1546  simTime() + validLifetime);
1547  }
1548 
1549  /*Stateless address autoconfiguration [ADDRCONF] may in some
1550  circumstances increase the Valid Lifetime of a prefix or ignore it
1551  completely in order to prevent a particular denial of service attack.
1552  However, since the effect of the same denial of service targeted at
1553  the on-link prefix list is not catastrophic (hosts would send packets
1554  to a default router and receive a redirect rather than sending
1555  packets directly to a neighbor) the Neighbor Discovery protocol does
1556  not impose such a check on the prefix lifetime values.*/
1557  }
1558 }

Referenced by processRaForRouterUpdates().

◆ processRaPrefixInfoForAddrAutoConf()

void inet::Ipv6NeighbourDiscovery::processRaPrefixInfoForAddrAutoConf ( const Ipv6NdPrefixInformation prefixInfo,
NetworkInterface ie 
)
protectedvirtual
1562 {
1563  EV_INFO << "Processing Prefix Info for address auto-configuration.\n";
1564  Ipv6Address prefix = prefixInfo.getPrefix();
1565  uint prefixLength = prefixInfo.getPrefixLength();
1566  simtime_t preferredLifetime = prefixInfo.getPreferredLifetime();
1567  simtime_t validLifetime = prefixInfo.getValidLifetime();
1568 
1569  // RFC 2461: Section 5.5.3
1570  // First condition tested, the autonomous flag is already set
1571 
1572  // b) If the prefix is the link-local prefix, silently ignore the Prefix
1573  // Information option.
1574  if (prefixInfo.getPrefix().isLinkLocal() == true) {
1575  EV_INFO << "Prefix is link-local, ignore Prefix Information Option\n";
1576  return;
1577  }
1578 
1579  // c) If the preferred lifetime is greater than the valid lifetime, silently
1580  // ignore the Prefix Information option. A node MAY wish to log a system
1581  // management error in this case.
1582  if (preferredLifetime > validLifetime) {
1583  EV_INFO << "Preferred lifetime is greater than valid lifetime, ignore Prefix Information\n";
1584  return;
1585  }
1586 
1587  bool isPrefixAssignedToInterface = false;
1588  for (int i = 0; i < ie->getProtocolData<Ipv6InterfaceData>()->getNumAddresses(); i++) {
1589  if (ie->getProtocolData<Ipv6InterfaceData>()->getAddress(i).matches(prefix, prefixLength) == true)
1590  isPrefixAssignedToInterface = true;
1591  }
1592 
1593  /*d) If the prefix advertised does not match the prefix of an address already
1594  in the list, and the Valid Lifetime is not 0, form an address (and add
1595  it to the list) by combining the advertised prefix with the link�s
1596  interface identifier as follows:*/
1597  if (isPrefixAssignedToInterface == false && validLifetime != 0) {
1598  Ipv6Address linkLocalAddress = ie->getProtocolData<Ipv6InterfaceData>()->getLinkLocalAddress();
1599  ASSERT(linkLocalAddress.isUnspecified() == false);
1600  Ipv6Address newAddr = linkLocalAddress.setPrefix(prefix, prefixLength);
1601  // TODO for now we leave the newly formed address as not tentative,
1602  // according to Greg, we have to always perform DAD for a newly formed address.
1603  EV_INFO << "Assigning new address to: " << ie->getInterfaceName() << endl;
1604  ie->getProtocolDataForUpdate<Ipv6InterfaceData>()->assignAddress(newAddr, false, simTime() + validLifetime,
1605  simTime() + preferredLifetime);
1606  }
1607 
1608  // TODO this is the simplified version.
1609  /*e) If the advertised prefix matches the prefix of an autoconfigured
1610  address (i.e., one obtained via stateless or stateful address
1611  autoconfiguration) in the list of addresses associated with the
1612  interface, the specific action to perform depends on the Valid
1613  Lifetime in the received advertisement and the Lifetime
1614  associated with the previously autoconfigured address (which we
1615  call StoredLifetime in the discussion that follows):
1616 
1617  1) If the received Lifetime is greater than 2 hours or greater
1618  than StoredLifetime, update the stored Lifetime of the
1619  corresponding address.
1620 
1621  2) If the StoredLifetime is less than or equal to 2 hours and the
1622  received Lifetime is less than or equal to StoredLifetime,
1623  ignore the prefix, unless the Router Advertisement from which
1624 
1625  this Prefix Information option was obtained has been
1626  authenticated (e.g., via IPSec [RFC2402]). If the Router
1627  Advertisment was authenticated, the StoredLifetime should be
1628  set to the Lifetime in the received option.
1629 
1630  3) Otherwise, reset the stored Lifetime in the corresponding
1631  address to two hours.*/
1632 }

Referenced by processRaPacket().

◆ processRdTimeout()

void inet::Ipv6NeighbourDiscovery::processRdTimeout ( cMessage *  msg)
protectedvirtual
1031 {
1032  NetworkInterface *ie = (NetworkInterface *)msg->getContextPointer();
1033  RdEntry *rdEntry = fetchRdEntry(ie);
1034 
1035  if (rdEntry->numRSSent < ie->getProtocolData<Ipv6InterfaceData>()->_getMaxRtrSolicitations()) {
1036  bubble("Sending another RS message.");
1038  rdEntry->numRSSent++;
1039 
1040  // Need to find out if this is the last RS we are sending out.
1041  if (rdEntry->numRSSent == ie->getProtocolData<Ipv6InterfaceData>()->_getMaxRtrSolicitations())
1042  scheduleAfter(ie->getProtocolData<Ipv6InterfaceData>()->_getMaxRtrSolicitationDelay(), msg);
1043  else
1044  scheduleAfter(ie->getProtocolData<Ipv6InterfaceData>()->_getRtrSolicitationInterval(), msg);
1045  }
1046  else {
1047  // RFC 2461, Section 6.3.7
1048  /*If a host sends MAX_RTR_SOLICITATIONS solicitations, and receives no Router
1049  Advertisements after having waited MAX_RTR_SOLICITATION_DELAY seconds after
1050  sending the last solicitation, the host concludes that there are no routers
1051  on the link for the purpose of [ADDRCONF]. However, the host continues to
1052  receive and process Router Advertisements messages in the event that routers
1053  appear on the link.*/
1054  bubble("Max number of RS messages sent");
1055  EV_INFO << "No RA messages were received. Assume no routers are on-link";
1056  rdList.erase(rdEntry);
1057  delete rdEntry;
1058  delete msg;
1059  }
1060 }

Referenced by handleMessage().

◆ processRedirectPacket()

void inet::Ipv6NeighbourDiscovery::processRedirectPacket ( const Ipv6Redirect redirect)
protectedvirtual
2423 {
2424  // FIXME incomplete code
2425 #if 0
2426  // First we need to extract information from the redirect message
2427  Ipv6Address targetAddr = redirect->getTargetAddress(); // Addressed to me
2428  Ipv6Address destAddr = redirect->getDestinationAddress(); // new dest addr
2429 
2430  // Optional
2431  MacAddress macAddr = redirect->getTargetLinkLayerAddress();
2432 #endif
2433 }

Referenced by processNDMessage().

◆ processRsPacket()

void inet::Ipv6NeighbourDiscovery::processRsPacket ( Packet packet,
const Ipv6RouterSolicitation rs 
)
protectedvirtual
1063 {
1064  if (validateRsPacket(packet, rs) == false) {
1065  delete packet;
1066  return;
1067  }
1068 
1069  // Find out which interface the RS message arrived on.
1070  NetworkInterface *ie = ift->getInterfaceById(packet->getTag<InterfaceInd>()->getInterfaceId());
1071  AdvIfEntry *advIfEntry = fetchAdvIfEntry(ie); // fetch advertising interface entry.
1072 
1073  // RFC 2461: Section 6.2.6
1074  // A host MUST silently discard any received Router Solicitation messages.
1075  if (ie->getProtocolData<Ipv6InterfaceData>()->getAdvSendAdvertisements()) {
1076  EV_INFO << "This is an advertising interface, processing RS\n";
1077 
1078  if (validateRsPacket(packet, rs) == false) {
1079  delete packet;
1080  return;
1081  }
1082 
1083  EV_INFO << "RS message validated\n";
1084 
1085  // First we extract RS specific information from the received message
1086  MacAddress macAddr;
1087  if (auto sla = check_and_cast_nullable<const Ipv6NdSourceLinkLayerAddress *>(rs->getOptions().findOption(IPv6ND_SOURCE_LINK_LAYER_ADDR_OPTION)))
1088  macAddr = sla->getLinkLayerAddress();
1089  EV_INFO << "MAC Address '" << macAddr << "' extracted\n";
1090 
1091  /*A router MAY choose to unicast the response directly to the soliciting
1092  host's address (if the solicitation's source address is not the unspecified
1093  address), but the usual case is to multicast the response to the
1094  all-nodes group. In the latter case, the interface's interval timer is
1095  reset to a new random value, as if an unsolicited advertisement had just
1096  been sent(see Section 6.2.4).*/
1097 
1098  /*In all cases, Router Advertisements sent in response to a Router
1099  Solicitation MUST be delayed by a random time between 0 and
1100  MAX_RA_DELAY_TIME seconds. (If a single advertisement is sent in
1101  response to multiple solicitations, the delay is relative to the
1102  first solicitation.) In addition, consecutive Router Advertisements
1103  sent to the all-nodes multicast address MUST be rate limited to no
1104  more than one advertisement every MIN_DELAY_BETWEEN_RAS seconds.*/
1105 
1106  /*A router might process Router Solicitations as follows:
1107  - Upon receipt of a Router Solicitation, compute a random delay
1108  within the range 0 through MAX_RA_DELAY_TIME. If the computed
1109  value corresponds to a time later than the time the next multicast
1110  Router Advertisement is scheduled to be sent, ignore the random
1111  delay and send the advertisement at the already-scheduled time.*/
1112  cMessage *msg = new cMessage("sendSolicitedRA", MK_SEND_SOL_RTRADV);
1113  msg->setContextPointer(ie);
1114  simtime_t interval = uniform(0, ie->getProtocolData<Ipv6InterfaceData>()->_getMaxRaDelayTime());
1115  if (interval < advIfEntry->nextScheduledRATime) {
1116  scheduleAfter(interval, msg);
1117  advIfEntry->nextScheduledRATime = simTime() + interval;
1118  }
1119  // else we ignore the generate interval and send it at the next scheduled time.
1120 
1121  // We need to keep a log here each time an RA is sent. Not implemented yet.
1122  // Assume the first course of action.
1123  /*- If the router sent a multicast Router Advertisement (solicited or
1124  unsolicited) within the last MIN_DELAY_BETWEEN_RAS seconds,
1125  schedule the advertisement to be sent at a time corresponding to
1126  MIN_DELAY_BETWEEN_RAS plus the random value after the previous
1127  advertisement was sent. This ensures that the multicast Router
1128  Advertisements are rate limited.
1129 
1130  - Otherwise, schedule the sending of a Router Advertisement at the
1131  time given by the random value.*/
1132  }
1133  else {
1134  EV_INFO << "This interface is a host, discarding RA message\n";
1135  }
1136  delete packet;
1137 }

Referenced by processNDMessage().

◆ reachabilityConfirmed()

void inet::Ipv6NeighbourDiscovery::reachabilityConfirmed ( const Ipv6Address neighbour,
int  interfaceId 
)
virtual

Public method, it can be invoked from the Ipv6 module or any other module to let Neighbour Discovery know that the reachability of the given neighbor has just been confirmed (e.g.

TCP received ACK of new data from it). Neighbour Discovery can then update the neighbour cache with this information, and cancel the Neighbour Unreachability Detection procedure if it is currently running.

355 {
356  Enter_Method("reachabilityConfirmed(%s,if=%d)", neighbour.str().c_str(), interfaceId);
357  // hmmm... this should only be invoked if a TCP ACK was received and NUD is
358  // currently being performed on the neighbour where the TCP ACK was received from.
359 
360  Neighbour *nce = neighbourCache.lookup(neighbour, interfaceId);
361  if (!nce)
362  throw cRuntimeError("Model error: not found in cache");
363 
364  cMessage *msg = nce->nudTimeoutEvent;
365  if (msg != nullptr) {
366  EV_INFO << "NUD in progress. Cancelling NUD Timer\n";
367  bubble("Reachability Confirmed via NUD.");
368  cancelAndDelete(msg);
369  nce->nudTimeoutEvent = nullptr;
370  }
371 
372  // TODO (see header file for description)
373  /*A neighbor is considered reachable if the node has recently received
374  a confirmation that packets sent recently to the neighbor were
375  received by its IP layer. Positive confirmation can be gathered in
376  two ways: hints from upper layer protocols that indicate a connection
377  is making "forward progress", or receipt of a Neighbor Advertisement
378  message that is a response to a Neighbor Solicitation message.
379 
380  A connection makes "forward progress" if the packets received from a
381  remote peer can only be arriving if recent packets sent to that peer
382  are actually reaching it. In TCP, for example, receipt of a (new)
383  acknowledgement indicates that previously sent data reached the peer.
384  Likewise, the arrival of new (non-duplicate) data indicates that
385 
386  earlier acknowledgements are being delivered to the remote peer. If
387  packets are reaching the peer, they must also be reaching the
388  sender's next-hop neighbor; thus "forward progress" is a confirmation
389  that the next-hop neighbor is reachable. For off-link destinations,
390  forward progress implies that the first-hop router is reachable.
391  When available, this upper-layer information SHOULD be used.
392 
393  In some cases (e.g., UDP-based protocols and routers forwarding
394  packets to hosts) such reachability information may not be readily
395  available from upper-layer protocols. When no hints are available
396  and a node is sending packets to a neighbor, the node actively probes
397  the neighbor using unicast Neighbor Solicitation messages to verify
398  that the forward path is still working.
399 
400  The receipt of a solicited Neighbor Advertisement serves as
401  reachability confirmation, since advertisements with the Solicited
402  flag set to one are sent only in response to a Neighbor Solicitation.
403  Receipt of other Neighbor Discovery messages such as Router
404  Advertisements and Neighbor Advertisement with the Solicited flag set
405  to zero MUST NOT be treated as a reachability confirmation. Receipt
406  of unsolicited messages only confirm the one-way path from the sender
407  to the recipient node. In contrast, Neighbor Unreachability
408  Detection requires that a node keep track of the reachability of the
409  forward path to a neighbor from the its perspective, not the
410  neighbor's perspective. Note that receipt of a solicited
411  advertisement indicates that a path is working in both directions.
412  The solicitation must have reached the neighbor, prompting it to
413  generate an advertisement. Likewise, receipt of an advertisement
414  indicates that the path from the sender to the recipient is working.
415  However, the latter fact is known only to the recipient; the
416  advertisement's sender has no direct way of knowing that the
417  advertisement it sent actually reached a neighbor. From the
418  perspective of Neighbor Unreachability Detection, only the
419  reachability of the forward path is of interest.*/
420 }

◆ resetRaTimer()

void inet::Ipv6NeighbourDiscovery::resetRaTimer ( NetworkInterface ie)
protectedvirtual

Reset the given interface entry's Router Advertisement timer.

This is usually done when a router interface responds (by replying with a Router Advertisement sent to the All-Node multicast group)to a router solicitation Also see: RFC 2461, Section 6.2.6

1681 { // Not used yet but could be useful later on.-WEI
1682  // Iterate through all RA timers within the Neighbour Discovery module.
1683 /*
1684  for (auto it =raTimerList.begin(); it != raTimerList.end(); it++)
1685  {
1686  cMessage *msg = (*it);
1687  NetworkInterface *msgIE = (NetworkInterface *)msg->getContextPointer();
1688  //Find the timer that matches the given Interface Entry.
1689  if (msgIE->outputPort() == ie->outputPort())
1690  {
1691  EV << "Resetting RA timer for port: " << ie->outputPort();
1692  cancelEvent(msg); //Cancel the next scheduled msg.
1693  simtime_t interval
1694  = uniform(ie->getProtocolData<Ipv6InterfaceData>()->getMinRtrAdvInterval(),ie->getProtocolData<Ipv6InterfaceData>()->getMaxRtrAdvInterval());
1695  scheduleAfter(interval, msg);
1696  }
1697  }
1698  */
1699 }

◆ resolveNeighbour()

const MacAddress & inet::Ipv6NeighbourDiscovery::resolveNeighbour ( const Ipv6Address nextHop,
int  interfaceId 
)

Public method, to be invoked from the Ipv6 module to determine link-layer address and the output interface of the next hop.

If the neighbor cache does not contain this address or it's in the state INCOMPLETE, this method will return the nullptr address, and the Ipv6 module should then send the datagram here to Ipv6NeighbourDiscovery where it will be stored until neighbour resolution completes.

If the neighbour cache entry is STALE (or REACHABLE but more than reachableTime elapsed since reachability was last confirmed), the link-layer address is still returned and Ipv6 can send the datagram, but simultaneously, this call should trigger the Neighbour Unreachability Detection procedure to start in the Ipv6NeighbourDiscovery module.

325 {
326  Enter_Method("resolveNeighbor(%s,if=%d)", nextHop.str().c_str(), interfaceId);
327 
328  Neighbour *nce = neighbourCache.lookup(nextHop, interfaceId);
329 // NetworkInterface *ie = ift->getInterfaceById(interfaceId);
330 
331  if (!nce || nce->reachabilityState == Ipv6NeighbourCache::INCOMPLETE)
333 
334  if (nce->reachabilityState == Ipv6NeighbourCache::STALE) {
336  }
337  else if (nce->reachabilityState == Ipv6NeighbourCache::REACHABLE &&
338  simTime() > nce->reachabilityExpires)
339  {
340  nce->reachabilityState = Ipv6NeighbourCache::STALE;
342  }
343  else if (nce->reachabilityState != Ipv6NeighbourCache::REACHABLE) {
344  // reachability state must be either in DELAY or PROBE
345  ASSERT(nce->reachabilityState == Ipv6NeighbourCache::DELAY ||
346  nce->reachabilityState == Ipv6NeighbourCache::PROBE);
347  EV_INFO << "NUD in progress.\n";
348  }
349 
350  // else the entry is REACHABLE and no further action is required here.
351  return nce->macAddress;
352 }

◆ selectDefaultRouter()

Ipv6Address inet::Ipv6NeighbourDiscovery::selectDefaultRouter ( int &  outIfID)
protectedvirtual
536 {
537  EV_INFO << "Selecting default router...\n";
538  // draft-ietf-ipv6-2461bis-04.txt Section 6.3.6
539  /*The algorithm for selecting a router depends in part on whether or not a
540  router is known to be reachable. The exact details of how a node keeps track
541  of a neighbor's reachability state are covered in Section 7.3. The algorithm
542  for selecting a default router is invoked during next-hop determination when
543  no Destination Cache entry exists for an off-link destination or when
544  communication through an existing router appears to be failing. Under normal
545  conditions, a router would be selected the first time traffic is sent to a
546  destination, with subsequent traffic for that destination using the same router
547  as indicated in the Destination Cache modulo any changes to the Destination
548  Cache caused by Redirect messages.
549 
550  The policy for selecting routers from the Default Router List is as
551  follows:*/
552 
553  /*1) Routers that are reachable or probably reachable (i.e., in any state
554  other than INCOMPLETE) SHOULD be preferred over routers whose reachability
555  is unknown or suspect (i.e., in the INCOMPLETE state, or for which no Neighbor
556  Cache entry exists). An implementation may choose to always return the same
557  router or cycle through the router list in a round-robin fashion as long as
558  it always returns a reachable or a probably reachable router when one is
559  available.*/
561  for (auto it = defaultRouters.begin(); it != defaultRouters.end();) {
562  Neighbour& nce = *it;
563  if (simTime() > nce.routerExpiryTime) {
564  EV_INFO << "Found an expired default router. Deleting entry...\n";
565  ++it;
566  neighbourCache.remove(nce.nceKey->address, nce.nceKey->interfaceID);
567  continue;
568  }
569  if (nce.reachabilityState != Ipv6NeighbourCache::INCOMPLETE) {
570  EV_INFO << "Found a probably reachable router in the default router list.\n";
571  defaultRouters.setHead(*nce.nextDefaultRouter);
572  outIfID = nce.nceKey->interfaceID;
573  return nce.nceKey->address;
574  }
575  ++it;
576  }
577 
578  /*2) When no routers on the list are known to be reachable or probably
579  reachable, routers SHOULD be selected in a round-robin fashion, so that
580  subsequent requests for a default router do not return the same router until
581  all other routers have been selected.
582 
583  Cycling through the router list in this case ensures that all available
584  routers are actively probed by the Neighbor Unreachability Detection algorithm.
585  A request for a default router is made in conjunction with the sending of a
586  packet to a router, and the selected router will be probed for reachability
587  as a side effect.*/
588  Neighbour *defaultRouter = defaultRouters.getHead();
589  if (defaultRouter != nullptr) {
590  EV_INFO << "Found a router in the neighbour cache (default router list).\n";
591  defaultRouters.setHead(*defaultRouter->nextDefaultRouter);
592  outIfID = defaultRouter->nceKey->interfaceID;
593  return defaultRouter->nceKey->address;
594  }
595 
596  EV_INFO << "No suitable routers found.\n";
597  outIfID = -1;
599 }

Referenced by determineNextHop().

◆ sendPacketToIpv6Module()

void inet::Ipv6NeighbourDiscovery::sendPacketToIpv6Module ( Packet msg,
const Ipv6Address destAddr,
const Ipv6Address srcAddr,
int  interfaceId 
)
protectedvirtual

Create control info and assigns it to a msg.

Returns a copy of the msg with the control info.

739 {
740  msg->removeTagIfPresent<DispatchProtocolReq>();
741  msg->addTagIfAbsent<InterfaceReq>()->setInterfaceId(interfaceId);
742  msg->addTagIfAbsent<PacketProtocolTag>()->setProtocol(&Protocol::icmpv6);
743  auto addressReq = msg->addTagIfAbsent<L3AddressReq>();
744  addressReq->setSrcAddress(srcAddr);
745  addressReq->setDestAddress(destAddr);
746  msg->addTagIfAbsent<HopLimitReq>()->setHopLimit(255);
747 
748  send(msg, "ipv6Out");
749 }

Referenced by createAndSendNsPacket(), createAndSendRaPacket(), createAndSendRsPacket(), sendSolicitedNa(), and sendUnsolicitedNa().

◆ sendPeriodicRa()

void inet::Ipv6NeighbourDiscovery::sendPeriodicRa ( cMessage *  msg)
protectedvirtual
1702 {
1703  NetworkInterface *ie = (NetworkInterface *)msg->getContextPointer();
1704  AdvIfEntry *advIfEntry = fetchAdvIfEntry(ie);
1705  Ipv6Address destAddr = Ipv6Address("FF02::1");
1706  createAndSendRaPacket(destAddr, ie);
1707  advIfEntry->numRASent++;
1708 
1709  // RFC 2461, Section 6.2.4
1710  /*Whenever a multicast advertisement is sent from an interface, the timer is
1711  reset to a uniformly-distributed random value between the interface's
1712  configured MinRtrAdvInterval and MaxRtrAdvInterval; expiration of the timer
1713  causes the next advertisement to be sent and a new random value to be chosen.*/
1714 
1715 #ifdef INET_WITH_xMIPv6
1716  EV_DEBUG << "\n+=+=+= MIPv6 Feature: " << rt6->hasMipv6Support() << " +=+=+=\n";
1717 #endif /* INET_WITH_xMIPv6 */
1718 
1719  simtime_t interval = uniform(ie->getProtocolData<Ipv6InterfaceData>()->getMinRtrAdvInterval(), ie->getProtocolData<Ipv6InterfaceData>()->getMaxRtrAdvInterval());
1720 
1721 #ifdef INET_WITH_xMIPv6
1722  EV_DETAIL << "\n +=+=+= The random calculated interval is: " << interval << " +=+=+=\n";
1723 #endif /* INET_WITH_xMIPv6 */
1724 
1725  /*For the first few advertisements (up to MAX_INITIAL_RTR_ADVERTISEMENTS)
1726  sent from an interface when it becomes an advertising interface,*/
1727  EV_DETAIL << "Num RA sent is: " << advIfEntry->numRASent << endl;
1728  EV_DETAIL << "maxInitialRtrAdvertisements is: " << ie->getProtocolData<Ipv6InterfaceData>()->_getMaxInitialRtrAdvertisements() << endl;
1729 
1730  if (advIfEntry->numRASent <= ie->getProtocolData<Ipv6InterfaceData>()->_getMaxInitialRtrAdvertisements()) {
1731  if (interval > ie->getProtocolData<Ipv6InterfaceData>()->_getMaxInitialRtrAdvertInterval()) {
1732  // if the randomly chosen interval is greater than MAX_INITIAL_RTR_ADVERT_INTERVAL,
1733  // the timer SHOULD be set to MAX_INITIAL_RTR_ADVERT_INTERVAL instead.
1734  interval = ie->getProtocolData<Ipv6InterfaceData>()->_getMaxInitialRtrAdvertInterval();
1735  EV_INFO << "Sending initial RA but interval is too long. Using default value." << endl;
1736  }
1737  else
1738  EV_INFO << "Sending initial RA. Using randomly generated interval." << endl;
1739  }
1740 
1741  simtime_t nextScheduledTime = simTime() + interval;
1742  EV_DETAIL << "Next scheduled time: " << nextScheduledTime << endl;
1743  advIfEntry->nextScheduledRATime = nextScheduledTime;
1744  ASSERT(nextScheduledTime > simTime());
1745  scheduleAfter(interval, msg);
1746 }

Referenced by handleMessage().

◆ sendQueuedPacketsToIpv6Module()

void inet::Ipv6NeighbourDiscovery::sendQueuedPacketsToIpv6Module ( Neighbour nce)
protectedvirtual

Send off any queued packets within the Neighbour Discovery module awaiting address resolution.

Not used yet-unsure if we really need it.

–DELETED, Andras

754 {
755  MsgPtrVector& pendingPackets = nce->pendingPackets;
756 
757  while (!pendingPackets.empty()) {
758  auto i = pendingPackets.begin();
759  cMessage *msg = (*i);
760  pendingPackets.erase(i);
761  pendingQueue.remove(msg);
762  EV_INFO << "Sending queued packet " << msg << endl;
763  send(msg, "ipv6Out");
764  }
765 }

Referenced by processNaForIncompleteNceState().

◆ sendSolicitedNa()

void inet::Ipv6NeighbourDiscovery::sendSolicitedNa ( Packet packet,
const Ipv6NeighbourSolicitation ns,
NetworkInterface ie 
)
protectedvirtual
2005 {
2006  auto na = makeShared<Ipv6NeighbourAdvertisement>();
2007 
2008  // RFC 2461: Section 7.2.4
2009  /*A node sends a Neighbor Advertisement in response to a valid Neighbor
2010  Solicitation targeting one of the node's assigned addresses. The
2011  Target Address of the advertisement is copied from the Target Address
2012  of the solicitation.*/
2013  na->setTargetAddress(ns->getTargetAddress());
2014 
2015  /*If the solicitation's IP Destination Address is not a multicast address,
2016  the Target Link-Layer Address option MAY be omitted; the neighboring node's
2017  cached value must already be current in order for the solicitation to have
2018  been received. If the solicitation's IP Destination Address is a multicast
2019  address, the Target Link-Layer option MUST be included in the advertisement.*/
2020  auto tla = new Ipv6NdTargetLinkLayerAddress();
2021  tla->setLinkLayerAddress(ie->getMacAddress());
2022  na->getOptionsForUpdate().appendOption(tla);
2023  na->addChunkLength(IPv6ND_LINK_LAYER_ADDRESS_OPTION_LENGTH);
2024 
2025  /*Furthermore, if the node is a router, it MUST set the Router flag to one;
2026  otherwise it MUST set the flag to zero.*/
2027  na->setRouterFlag(rt6->isRouter());
2028 
2029  /*If the (NS)Target Address is either an anycast address or a unicast
2030  address for which the node is providing proxy service, or the Target
2031  Link-Layer Address option is not included,*/
2032  // TODOANYCAST will not be implemented here!
2033 
2034  MacAddress sourceLinkLayerAddress;
2035  if (auto sla = check_and_cast_nullable<const Ipv6NdSourceLinkLayerAddress *>(ns->getOptions().findOption(IPv6ND_SOURCE_LINK_LAYER_ADDR_OPTION)))
2036  sourceLinkLayerAddress = sla->getLinkLayerAddress();
2037 
2038  if (sourceLinkLayerAddress.isUnspecified())
2039  // the Override flag SHOULD be set to zero.
2040  na->setOverrideFlag(false);
2041  else
2042  // Otherwise, the Override flag SHOULD be set to one.
2043  na->setOverrideFlag(true);
2044 
2045  /*Proper setting of the Override flag ensures that nodes give preference to
2046  non-proxy advertisements, even when received after proxy advertisements, and
2047  also ensures that the first advertisement for an anycast address "wins".*/
2048 
2049  Ipv6Address naDestAddr;
2050  // If the source of the solicitation is the unspecified address,
2051  if (packet->getTag<L3AddressInd>()->getSrcAddress().toIpv6().isUnspecified()) {
2052  /*the node MUST set the Solicited flag to zero and multicast the advertisement
2053  to the all-nodes address.*/
2054  na->setSolicitedFlag(false);
2055  naDestAddr = Ipv6Address::ALL_NODES_2;
2056  }
2057  else {
2058  /*Otherwise, the node MUST set the Solicited flag to one and unicast
2059  the advertisement to the Source Address of the solicitation.*/
2060  na->setSolicitedFlag(true);
2061  naDestAddr = packet->getTag<L3AddressInd>()->getSrcAddress().toIpv6();
2062  }
2063 
2064  /*If the Target Address is an anycast address the sender SHOULD delay sending
2065  a response for a random time between 0 and MAX_ANYCAST_DELAY_TIME seconds.*/
2066  /*TODO More associated complexity for this one. We will have to delay
2067  sending off the solicitation. Perhaps the self message could have a context
2068  pointer pointing to a struct with enough info to create and send a NA packet.*/
2069 
2070  /*Because unicast Neighbor Solicitations are not required to include a
2071  Source Link-Layer Address, it is possible that a node sending a
2072  solicited Neighbor Advertisement does not have a corresponding link-
2073  layer address for its neighbor in its Neighbor Cache. In such
2074  situations, a node will first have to use Neighbor Discovery to
2075  determine the link-layer address of its neighbor (i.e, send out a
2076  multicast Neighbor Solicitation).*/
2077  // TODO if above mentioned happens, can addr resolution be performed for ND messages?
2078  // if no link-layer addr exists for unicast addr when sending solicited NA, we should
2079  // add the NA to the list of queued packets. What if we have a list of queued
2080  // packets for different unicast solicitations? each time addr resolution is
2081  // done we should check the destinations of the list of queued packets and send
2082  // off the respective ones.
2083  Ipv6Address myIPv6Addr = ie->getProtocolData<Ipv6InterfaceData>()->getPreferredAddress();
2084 
2085  auto naPacket = new Packet("NApacket");
2086  Icmpv6::insertCrc(crcMode, na, packet);
2087  naPacket->insertAtFront(na);
2088  sendPacketToIpv6Module(naPacket, naDestAddr, myIPv6Addr, ie->getInterfaceId());
2089 }

Referenced by processNsForNonTentativeAddress(), and processNsWithSpecifiedSrcAddr().

◆ sendSolicitedRa()

void inet::Ipv6NeighbourDiscovery::sendSolicitedRa ( cMessage *  msg)
protectedvirtual
1749 {
1750  EV_INFO << "Send Solicited RA invoked!\n";
1751  NetworkInterface *ie = (NetworkInterface *)msg->getContextPointer();
1752  Ipv6Address destAddr = Ipv6Address("FF02::1");
1753  EV_DETAIL << "Testing condition!\n";
1754  createAndSendRaPacket(destAddr, ie);
1755  delete msg;
1756 }

Referenced by handleMessage().

◆ sendUnsolicitedNa()

void inet::Ipv6NeighbourDiscovery::sendUnsolicitedNa ( NetworkInterface ie)
protectedvirtual
2092 {
2093  // RFC 2461
2094  // Section 7.2.6: Sending Unsolicited Neighbor Advertisements
2095 #ifdef INET_WITH_xMIPv6
2096  Enter_Method("sendUnsolicitedNa");
2097 #endif /* INET_WITH_xMIPv6 */
2098 
2099 #ifndef INET_WITH_xMIPv6
2100  // In some cases a node may be able to determine that its link-layer
2101  // address has changed (e.g., hot-swap of an interface card) and may
2102  // wish to inform its neighbors of the new link-layer address quickly.
2103  // In such cases a node MAY send up to MAX_NEIGHBOR_ADVERTISEMENT
2104  // unsolicited Neighbor Advertisement messages to the all-nodes
2105  // multicast address. These advertisements MUST be separated by at
2106  // least RetransTimer seconds.
2107 #else /* INET_WITH_xMIPv6 */
2108  auto na = makeShared<Ipv6NeighbourAdvertisement>();
2109  Ipv6Address myIPv6Addr = ie->getProtocolData<Ipv6InterfaceData>()->getPreferredAddress();
2110 #endif /* INET_WITH_xMIPv6 */
2111 
2112  // The Target Address field in the unsolicited advertisement is set to
2113  // an IP address of the interface, and the Target Link-Layer Address
2114  // option is filled with the new link-layer address.
2115 #ifdef INET_WITH_xMIPv6
2116  na->setTargetAddress(myIPv6Addr);
2117  auto sla = new Ipv6NdTargetLinkLayerAddress();
2118  sla->setLinkLayerAddress(ie->getMacAddress());
2119  na->getOptionsForUpdate().appendOption(sla);
2120  na->addChunkLength(IPv6ND_LINK_LAYER_ADDRESS_OPTION_LENGTH);
2121 #endif /* INET_WITH_xMIPv6 */
2122 
2123  // The Solicited flag MUST be set to zero, in order to avoid confusing
2124  // the Neighbor Unreachability Detection algorithm.
2125 #ifdef INET_WITH_xMIPv6
2126  na->setSolicitedFlag(false);
2127 #endif /* INET_WITH_xMIPv6 */
2128 
2129  // If the node is a router, it MUST set the Router flag to one;
2130  // otherwise it MUST set it to zero.
2131 #ifdef INET_WITH_xMIPv6
2132  na->setRouterFlag(rt6->isRouter());
2133 #endif /* INET_WITH_xMIPv6 */
2134 
2135  // The Override flag MAY be set to either zero or one. In either case,
2136  // neighboring nodes will immediately change the state of their Neighbor
2137  // Cache entries for the Target Address to STALE, prompting them to
2138  // verify the path for reachability. If the Override flag is set to
2139  // one, neighboring nodes will install the new link-layer address in
2140  // their caches. Otherwise, they will ignore the new link-layer
2141  // address, choosing instead to probe the cached address.
2142 #ifdef INET_WITH_xMIPv6
2143  na->setOverrideFlag(true);
2144 #endif /* INET_WITH_xMIPv6 */
2145 
2146  // A node that has multiple IP addresses assigned to an interface MAY
2147  // multicast a separate Neighbor Advertisement for each address. In
2148  // such a case the node SHOULD introduce a small delay between the
2149  // sending of each advertisement to reduce the probability of the
2150  // advertisements being lost due to congestion.
2151 
2152  // A proxy MAY multicast Neighbor Advertisements when its link-layer
2153  // address changes or when it is configured (by system management or
2154  // other mechanisms) to proxy for an address. If there are multiple
2155  // nodes that are providing proxy services for the same set of addresses
2156  // the proxies SHOULD provide a mechanism that prevents multiple proxies
2157  // from multicasting advertisements for any one address, in order to
2158  // reduce the risk of excessive multicast traffic.
2159 
2160  // Also, a node belonging to an anycast address MAY multicast
2161  // unsolicited Neighbor Advertisements for the anycast address when the
2162  // node's link-layer address changes.
2163 
2164  // Note that because unsolicited Neighbor Advertisements do not reliably
2165  // update caches in all nodes (the advertisements might not be received
2166  // by all nodes), they should only be viewed as a performance
2167  // optimization to quickly update the caches in most neighbors. The
2168  // Neighbor Unreachability Detection algorithm ensures that all nodes
2169  // obtain a reachable link-layer address, though the delay may be
2170  // slightly longer.
2171 #ifdef INET_WITH_xMIPv6
2172  auto packet = new Packet("NApacket");
2173  Icmpv6::insertCrc(crcMode, na, packet);
2174  packet->insertAtFront(na);
2175  sendPacketToIpv6Module(packet, Ipv6Address::ALL_NODES_2, myIPv6Addr, ie->getInterfaceId());
2176 #endif /* INET_WITH_xMIPv6 */
2177 }

◆ timeoutDefaultRouter()

void inet::Ipv6NeighbourDiscovery::timeoutDefaultRouter ( const Ipv6Address addr,
int  interfaceID 
)
protectedvirtual

RFC 2461: Section 6.3.5 Whenever the Lifetime of an entry in the Default Router List expires, that entry is discarded.

When removing a router from the Default Router list, the node MUST update the Destination Cache in such a way that all entries using the router perform next-hop determination again rather than continue sending traffic to the (deleted) router.

617 {
618  // RFC 2461: Section 6.3.5
619  /*Whenever the Lifetime of an entry in the Default Router List expires,
620  that entry is discarded.*/
621  neighbourCache.remove(addr, interfaceID);
622 
623  /*When removing a router from the Default Router list, the node MUST update
624  the Destination Cache in such a way that all entries using the router perform
625  next-hop determination again rather than continue sending traffic to the
626  (deleted) router.*/
627  rt6->purgeDestCacheEntriesToNeighbour(addr, interfaceID);
628 }

Referenced by processRaForRouterUpdates().

◆ timeoutPrefixEntry()

void inet::Ipv6NeighbourDiscovery::timeoutPrefixEntry ( const Ipv6Address destPrefix,
int  prefixLength 
)
protectedvirtual

RFC 2461: Section 6.3.5 Whenever the invalidation timer expires for a Prefix List entry, that entry is discarded.

No existing Destination Cache entries need be updated, however. Should a reachability problem arise with an existing Neighbor Cache entry, Neighbor Unreachability Detection will perform any needed recovery.

602 {
603  // RFC 2461: Section 6.3.5
604  /*Whenever the invalidation timer expires for a Prefix List entry, that
605  entry is discarded.*/
606  rt6->deleteOnLinkPrefix(destPrefix, prefixLength);
607  // hmmm... should the unicast address associated with this prefix be deleted
608  // as well?-TODO The address should be timeout/deleted as well!!
609 
610  /*No existing Destination Cache entries need be updated, however. Should a
611  reachability problem arise with an existing Neighbor Cache entry, Neighbor
612  Unreachability Detection will perform any needed recovery.*/
613 }

◆ validateNaPacket()

bool inet::Ipv6NeighbourDiscovery::validateNaPacket ( Packet packet,
const Ipv6NeighbourAdvertisement na 
)
protectedvirtual
2216 {
2217  bool result = true; // adopt optimistic approach
2218 
2219  // RFC 2461:7.1.2 Validation of Neighbor Advertisments(some checks are omitted)
2220  // A node MUST silently discard any received Neighbor Advertisment messages
2221  // that do not satisfy all of the following validity checks:
2222 
2223  // - The IP Hop Limit field has a value of 255, i.e., the packet
2224  // could not possibly have been forwarded by a router.
2225  if (packet->getTag<HopLimitInd>()->getHopLimit() != 255) {
2226  EV_WARN << "Hop Limit is not 255! NA validation failed!\n";
2227  result = false;
2228  }
2229 
2230  // - Target Address is not a multicast address.
2231  if (na->getTargetAddress().isMulticast() == true) {
2232  EV_WARN << "Target Address is a multicast address! NA validation failed!\n";
2233  result = false;
2234  }
2235 
2236  // - If the IP Destination Address is a multicast address the Solicited flag
2237  // is zero.
2238  if (packet->getTag<L3AddressInd>()->getDestAddress().toIpv6().isMulticast()) {
2239  if (na->getSolicitedFlag() == true) {
2240  EV_WARN << "Dest Address is multicast address but solicited flag is 0!\n";
2241  result = false;
2242  }
2243  }
2244 
2245  if (result == true)
2246  bubble("NA validation passed.");
2247  else
2248  bubble("NA validation failed.");
2249 
2250  return result;
2251 }

Referenced by processNaPacket().

◆ validateNsPacket()

bool inet::Ipv6NeighbourDiscovery::validateNsPacket ( Packet packet,
const Ipv6NeighbourSolicitation ns 
)
protectedvirtual
1877 {
1878  bool result = true;
1879 
1880  /*RFC 2461:7.1.1. Validation of Neighbor Solicitations(some checks are omitted)
1881  A node MUST silently discard any received Neighbor Solicitation
1882  messages that do not satisfy all of the following validity checks:*/
1883  // - The IP Hop Limit field has a value of 255, i.e., the packet
1884  // could not possibly have been forwarded by a router.
1885  if (packet->getTag<HopLimitInd>()->getHopLimit() != 255) {
1886  EV_WARN << "Hop limit is not 255! NS validation failed!\n";
1887  result = false;
1888  }
1889 
1890  // - Target Address is not a multicast address.
1891  if (ns->getTargetAddress().isMulticast() == true) {
1892  EV_WARN << "Target address is a multicast address! NS validation failed!\n";
1893  result = false;
1894  }
1895 
1896  // - If the IP source address is the unspecified address,
1897  if (packet->getTag<L3AddressInd>()->getSrcAddress().toIpv6().isUnspecified()) {
1898  EV_WARN << "Source Address is unspecified\n";
1899 
1900  // the IP destination address is a solicited-node multicast address.
1901  if (packet->getTag<L3AddressInd>()->getDestAddress().toIpv6().matches(Ipv6Address::SOLICITED_NODE_PREFIX, 104) == false) {
1902  EV_WARN << " but IP dest address is not a solicited-node multicast address! NS validation failed!\n";
1903  result = false;
1904  }
1905  // there is no source link-layer address option in the message.
1906  else {
1907  MacAddress sourceLinkLayerAddress;
1908  if (auto sla = check_and_cast_nullable<const Ipv6NdSourceLinkLayerAddress *>(ns->getOptions().findOption(IPv6ND_SOURCE_LINK_LAYER_ADDR_OPTION)))
1909  sourceLinkLayerAddress = sla->getLinkLayerAddress();
1910  if (sourceLinkLayerAddress.isUnspecified() == false) {
1911  EV_WARN << " but Source link-layer address is not empty! NS validation failed!\n";
1912  result = false;
1913  }
1914  }
1915  }
1916 
1917  return result;
1918 }

Referenced by processNsPacket().

◆ validateRaPacket()

bool inet::Ipv6NeighbourDiscovery::validateRaPacket ( Packet packet,
const Ipv6RouterAdvertisement ra 
)
protectedvirtual
1759 {
1760  bool result = true;
1761 
1762  // RFC 2461: Section 6.1.2 Validation of Router Advertisement Messages
1763  /*A node MUST silently discard any received Router Advertisement
1764  messages that do not satisfy all of the following validity checks:*/
1765  Ipv6Address srcAddr = packet->getTag<L3AddressInd>()->getSrcAddress().toIpv6();
1766 
1767  // - IP Source Address is a link-local address. Routers must use
1768  // their link-local address as the source for Router Advertisement
1769  // and Redirect messages so that hosts can uniquely identify
1770  // routers.
1771  if (srcAddr.isLinkLocal() == false) {
1772  EV_WARN << "RA source address is not link-local. RA validation failed!\n";
1773  result = false;
1774  }
1775 
1776  // - The IP Hop Limit field has a value of 255, i.e., the packet
1777  // could not possibly have been forwarded by a router.
1778  if (packet->getTag<HopLimitInd>()->getHopLimit() != 255) {
1779  EV_WARN << "Hop limit is not 255! RA validation failed!\n";
1780  result = false;
1781  }
1782 
1783  // - ICMP Code is 0.
1784  if (packet->getTag<PacketProtocolTag>()->getProtocol() != &Protocol::icmpv6) {
1785  EV_WARN << "ICMP Code is not 0! RA validation failed!\n";
1786  result = false;
1787  }
1788 
1789 #ifdef INET_WITH_xMIPv6
1790  // - All included options have a length that is greater than zero.
1791  // CB
1792  bool prefixInfoFound = false;
1793  for (int i = 0; i < (int)ra->getOptions().getOptionArraySize(); i++) {
1794  auto option = ra->getOptions().getOption(i);
1795  if (option->getType() == IPv6ND_PREFIX_INFORMATION) {
1796  prefixInfoFound = true;
1797  break;
1798  }
1799  }
1800  if (!prefixInfoFound) {
1801  EV_WARN << "No prefix information available! RA validation failed\n";
1802  result = false;
1803  }
1804 #endif /* INET_WITH_xMIPv6 */
1805 
1806  return result;
1807 }

Referenced by processRaPacket().

◆ validateRsPacket()

bool inet::Ipv6NeighbourDiscovery::validateRsPacket ( Packet packet,
const Ipv6RouterSolicitation rs 
)
protectedvirtual
1140 {
1141  bool result = true;
1142  /*6.1.1. Validation of Router Solicitation Messages
1143  A router MUST silently discard any received Router Solicitation
1144  messages that do not satisfy all of the following validity checks:
1145 
1146  - The IP Hop Limit field has a value of 255, i.e., the packet
1147  could not possibly have been forwarded by a router.*/
1148  if (packet->getTag<HopLimitInd>()->getHopLimit() != 255) {
1149  EV_WARN << "Hop limit is not 255! RS validation failed!\n";
1150  result = false;
1151  }
1152 
1153  // - ICMP Code is 0.
1154  if (packet->getTag<PacketProtocolTag>()->getProtocol() != &Protocol::icmpv6) {
1155  EV_WARN << "ICMP Code is not 0! RS validation failed!\n";
1156  result = false;
1157  }
1158 
1159  // - If the IP source address is the unspecified address, there is no
1160  // source link-layer address option in the message.
1161  if (packet->getTag<L3AddressInd>()->getSrcAddress().toIpv6().isUnspecified()) {
1162  EV_WARN << "IP source address is unspecified\n";
1163 
1164  MacAddress macAddr;
1165  if (auto sla = check_and_cast_nullable<const Ipv6NdSourceLinkLayerAddress *>(rs->getOptions().findOption(IPv6ND_SOURCE_LINK_LAYER_ADDR_OPTION)))
1166  macAddr = sla->getLinkLayerAddress();
1167  if (macAddr.isUnspecified() == false) {
1168  EV_WARN << " but source link layer address is provided. RS validation failed!\n";
1169  }
1170  }
1171 
1172  return result;
1173 }

Referenced by processRsPacket().

Member Data Documentation

◆ advIfList

AdvIfList inet::Ipv6NeighbourDiscovery::advIfList
protected

◆ crcMode

◆ dadList

DadList inet::Ipv6NeighbourDiscovery::dadList
protected

◆ icmpv6

ModuleRefByPar<Icmpv6> inet::Ipv6NeighbourDiscovery::icmpv6
protected

◆ ift

◆ neighbourCache

◆ pendingQueue

cQueue inet::Ipv6NeighbourDiscovery::pendingQueue
protected

◆ raTimerList

RaTimerList inet::Ipv6NeighbourDiscovery::raTimerList
protected

Referenced by ~Ipv6NeighbourDiscovery().

◆ rdList

RdList inet::Ipv6NeighbourDiscovery::rdList
protected

◆ rt6

◆ startDadSignal

simsignal_t inet::Ipv6NeighbourDiscovery::startDadSignal = registerSignal("startDad")
staticprivate

Referenced by initiateDad().


The documentation for this class was generated from the following files:
inet::Ipv6NeighbourCache::Key::interfaceID
int interfaceID
Definition: Ipv6NeighbourCache.h:50
inet::Ipv6NeighbourDiscovery::startDadSignal
static simsignal_t startDadSignal
Definition: Ipv6NeighbourDiscovery.h:52
inet::findContainingNode
cModule * findContainingNode(const cModule *from)
Find the node containing the given module.
Definition: ModuleAccess.cc:31
inet::Ipv6NeighbourDiscovery::initiateAddressResolution
virtual void initiateAddressResolution(const Ipv6Address &dgSrcAddr, Neighbour *nce)
This method attempts to resolve the given neighbour's link-layer address.
Definition: Ipv6NeighbourDiscovery.cc:630
inet::Ipv6Address::ALL_ROUTERS_2
static const Ipv6Address ALL_ROUTERS_2
All-routers multicast address, scope 2 (link-local)
Definition: Ipv6Address.h:69
inet::Ipv6NeighbourDiscovery::advIfList
AdvIfList advIfList
Definition: Ipv6NeighbourDiscovery.h:138
inet::Ipv6NeighbourDiscovery::Key
Ipv6NeighbourCache::Key Key
Definition: Ipv6NeighbourDiscovery.h:43
inet::Ipv6NeighbourDiscovery::processNsPacket
virtual void processNsPacket(Packet *packet, const Ipv6NeighbourSolicitation *ns)
Definition: Ipv6NeighbourDiscovery.cc:1842
inet::Ipv6NeighbourDiscovery::processRaPacket
virtual void processRaPacket(Packet *packet, const Ipv6RouterAdvertisement *ra)
Definition: Ipv6NeighbourDiscovery.cc:1287
inet::Ipv6NeighbourDiscovery::DefaultRouterList
Ipv6NeighbourCache::DefaultRouterList DefaultRouterList
Definition: Ipv6NeighbourDiscovery.h:45
inet::Icmpv6::insertCrc
static void insertCrc(CrcMode crcMode, const Ptr< Icmpv6Header > &icmpHeader, Packet *packet)
Definition: Icmpv6.cc:333
inet::Ipv6NeighbourDiscovery::sendPacketToIpv6Module
virtual void sendPacketToIpv6Module(Packet *msg, const Ipv6Address &destAddr, const Ipv6Address &srcAddr, int interfaceId)
Create control info and assigns it to a msg.
Definition: Ipv6NeighbourDiscovery.cc:737
protocol
removed DscpReq Ipv4ControlInfo Ipv6ControlInfo up L3AddressInd DispatchProtocolReq L4PortInd Ipv4ControlInfo Ipv6ControlInfo down protocol
Definition: IUdp-gates.txt:25
MK_DAD_TIMEOUT
#define MK_DAD_TIMEOUT
Definition: Ipv6NeighbourDiscovery.cc:32
inet::Ipv6NeighbourCache::addRouter
virtual Neighbour * addRouter(const Ipv6Address &addr, int interfaceID, MacAddress macAddress, simtime_t expiryTime, bool isHomeAgent=false)
Creates and initializes a router entry (isRouter=isDefaultRouter=true), MAC address and state=STALE.
Definition: Ipv6NeighbourCache.cc:121
inet::Ipv6NeighbourDiscovery::timeoutDefaultRouter
virtual void timeoutDefaultRouter(const Ipv6Address &addr, int interfaceID)
RFC 2461: Section 6.3.5 Whenever the Lifetime of an entry in the Default Router List expires,...
Definition: Ipv6NeighbourDiscovery.cc:615
inet::Ipv6NeighbourDiscovery::initiateNeighbourUnreachabilityDetection
virtual void initiateNeighbourUnreachabilityDetection(Neighbour *neighbour)
Definition: Ipv6NeighbourDiscovery.cc:471
inet::Ipv6NeighbourDiscovery::icmpv6
ModuleRefByPar< Icmpv6 > icmpv6
Definition: Ipv6NeighbourDiscovery.h:91
inet::ICMPv6_HEADER_BYTES
const B ICMPv6_HEADER_BYTES
Definition: Icmpv6Header_m.h:55
inet::Ipv6NeighbourCache::Neighbour::nceKey
const Key * nceKey
Definition: Ipv6NeighbourCache.h:61
inet::Ipv6NeighbourDiscovery::processRdTimeout
virtual void processRdTimeout(cMessage *msg)
Definition: Ipv6NeighbourDiscovery.cc:1030
inet::Ipv6NeighbourDiscovery::determineNextHop
virtual Ipv6Address determineNextHop(const Ipv6Address &destAddr, int &outIfID)
This function accepts the datagram's destination address and attempts to determine the destination's ...
Definition: Ipv6NeighbourDiscovery.cc:422
INET_WITH_xMIPv6
#define INET_WITH_xMIPv6
Definition: features.h:221
inet::IPv6ND_LINK_LAYER_ADDRESS_OPTION_LENGTH
const B IPv6ND_LINK_LAYER_ADDRESS_OPTION_LENGTH
Definition: Ipv6NdMessage_m.h:64
inet::Ipv6NeighbourDiscovery::processRaPrefixInfo
virtual void processRaPrefixInfo(const Ipv6RouterAdvertisement *ra, NetworkInterface *ie)
Definition: Ipv6NeighbourDiscovery.cc:1477
inet::Ipv6NeighbourDiscovery::assignLinkLocalAddress
virtual void assignLinkLocalAddress(cMessage *timerMsg)
as it is not possbile to explicitly define RFC 2462.
Definition: Ipv6NeighbourDiscovery.cc:767
inet::Ipv6NeighbourDiscovery::processArTimeout
virtual void processArTimeout(cMessage *arTimeoutMsg)
Resends a NS packet to the address intended for address resolution.
Definition: Ipv6NeighbourDiscovery.cc:682
inet::Ipv6NeighbourDiscovery::validateRaPacket
virtual bool validateRaPacket(Packet *packet, const Ipv6RouterAdvertisement *ra)
Definition: Ipv6NeighbourDiscovery.cc:1758
inet::Ipv6NeighbourDiscovery::selectDefaultRouter
virtual Ipv6Address selectDefaultRouter(int &outIfID)
Definition: Ipv6NeighbourDiscovery.cc:535
inet::Ipv6NeighbourDiscovery::processNudTimeout
virtual void processNudTimeout(cMessage *timeoutMsg)
Definition: Ipv6NeighbourDiscovery.cc:490
inet::Ipv6Address::ALL_NODES_2
static const Ipv6Address ALL_NODES_2
All-nodes multicast address, scope 2 (link-local)
Definition: Ipv6Address.h:63
MK_NUD_TIMEOUT
#define MK_NUD_TIMEOUT
Definition: Ipv6NeighbourDiscovery.cc:34
inet::Ipv6NeighbourDiscovery::sendSolicitedNa
virtual void sendSolicitedNa(Packet *packet, const Ipv6NeighbourSolicitation *ns, NetworkInterface *ie)
Definition: Ipv6NeighbourDiscovery.cc:2004
inet::Ipv6NeighbourCache::INCOMPLETE
@ INCOMPLETE
Definition: Ipv6NeighbourCache.h:41
inet::Ipv6NeighbourDiscovery::rt6
ModuleRefByPar< Ipv6RoutingTable > rt6
Definition: Ipv6NeighbourDiscovery.h:90
inet::Ipv6NeighbourCache::Key::address
Ipv6Address address
Definition: Ipv6NeighbourCache.h:49
inet::Ipv6NeighbourCache::PROBE
@ PROBE
Definition: Ipv6NeighbourCache.h:41
inet::Ipv6NeighbourDiscovery::sendPeriodicRa
virtual void sendPeriodicRa(cMessage *msg)
Definition: Ipv6NeighbourDiscovery.cc:1701
InterfaceReq
removed InterfaceReq
Definition: IUdp-gates.txt:11
DispatchProtocolReq
removed DscpReq Ipv4ControlInfo Ipv6ControlInfo up L3AddressInd DispatchProtocolReq L4PortInd Ipv4ControlInfo Ipv6ControlInfo down DispatchProtocolReq
Definition: IUdp-gates.txt:25
L3AddressInd
removed DscpReq Ipv4ControlInfo Ipv6ControlInfo up L3AddressInd L3AddressInd
Definition: IUdp-gates.txt:20
inet::Ipv6NeighbourDiscovery::createAndSendRsPacket
virtual void createAndSendRsPacket(NetworkInterface *ie)
Definition: Ipv6NeighbourDiscovery.cc:947
inet::parseCrcMode
CrcMode parseCrcMode(const char *crcModeString, bool allowDisable)
Definition: CrcMode.cc:14
inet::Ipv6NeighbourDiscovery::processNaForOtherNceStates
virtual void processNaForOtherNceStates(const Ipv6NeighbourAdvertisement *na, Ipv6NeighbourCache::Neighbour *nce)
Definition: Ipv6NeighbourDiscovery.cc:2302
inet::Ipv6NeighbourDiscovery::dadList
DadList dadList
Definition: Ipv6NeighbourDiscovery.h:132
inet::IPv6ND_PREFIX_INFORMATION
@ IPv6ND_PREFIX_INFORMATION
Definition: Ipv6NdMessage_m.h:91
inet::Ipv6NeighbourDiscovery::Neighbour
Ipv6NeighbourCache::Neighbour Neighbour
Definition: Ipv6NeighbourDiscovery.h:44
inet::IPv6ND_PREFIX_INFORMATION_OPTION_LENGTH
const B IPv6ND_PREFIX_INFORMATION_OPTION_LENGTH
Definition: Ipv6NdMessage_m.h:65
inet::Ipv6NeighbourDiscovery::initiateRouterDiscovery
virtual void initiateRouterDiscovery(cMessage *msg)
Definition: Ipv6NeighbourDiscovery.cc:981
MK_AR_TIMEOUT
#define MK_AR_TIMEOUT
Definition: Ipv6NeighbourDiscovery.cc:35
PacketProtocolTag
removed DscpReq Ipv4ControlInfo Ipv6ControlInfo up L3AddressInd DispatchProtocolReq L4PortInd Ipv4ControlInfo Ipv6ControlInfo down PacketProtocolTag
Definition: IUdp-gates.txt:25
inet::Ipv6NeighbourCache::remove
virtual void remove(const Ipv6Address &addr, int interfaceID)
Deletes the given neighbour from the cache.
Definition: Ipv6NeighbourCache.cc:140
inet::Ipv6NeighbourDiscovery::processRedirectPacket
virtual void processRedirectPacket(const Ipv6Redirect *redirect)
Definition: Ipv6NeighbourDiscovery.cc:2422
inet::Ipv6NeighbourDiscovery::MsgPtrVector
std::vector< Packet * > MsgPtrVector
Definition: Ipv6NeighbourDiscovery.h:42
inet::Ipv6NeighbourDiscovery::processRaPrefixInfoForAddrAutoConf
virtual void processRaPrefixInfoForAddrAutoConf(const Ipv6NdPrefixInformation &prefixInfo, NetworkInterface *ie)
Definition: Ipv6NeighbourDiscovery.cc:1561
ctrl
removed ctrl
Definition: IUdp-gates.txt:7
MK_RD_TIMEOUT
#define MK_RD_TIMEOUT
Definition: Ipv6NeighbourDiscovery.cc:33
inet::Ipv6NeighbourDiscovery::initiateDad
virtual void initiateDad(const Ipv6Address &tentativeAddr, NetworkInterface *ie)
Initiating DAD means to send off a Neighbour Solicitation with its target address set as this node's ...
Definition: Ipv6NeighbourDiscovery.cc:797
inet::Ipv6NeighbourDiscovery::processDadTimeout
virtual void processDadTimeout(cMessage *msg)
Sends a scheduled DAD NS packet.
Definition: Ipv6NeighbourDiscovery.cc:838
inet::Ipv6Address::UNSPECIFIED_ADDRESS
static const Ipv6Address UNSPECIFIED_ADDRESS
The unspecified address.
Definition: Ipv6Address.h:54
inet::Ipv6NeighbourDiscovery::sendQueuedPacketsToIpv6Module
virtual void sendQueuedPacketsToIpv6Module(Neighbour *nce)
Send off any queued packets within the Neighbour Discovery module awaiting address resolution.
Definition: Ipv6NeighbourDiscovery.cc:753
inet::Ipv6NeighbourCache::STALE
@ STALE
Definition: Ipv6NeighbourCache.h:41
inet::Ipv6NeighbourDiscovery::createRaTimer
virtual void createRaTimer(NetworkInterface *ie)
Create a timer for the given interface entry that sends periodic Router Advertisements.
Definition: Ipv6NeighbourDiscovery.cc:1636
HopLimitReq
removed HopLimitReq
Definition: IUdp-gates.txt:11
inet::Ipv6NeighbourDiscovery::dropQueuedPacketsAwaitingAr
virtual void dropQueuedPacketsAwaitingAr(Neighbour *nce)
Drops specific queued packets for a specific NCE AR-timeout.
Definition: Ipv6NeighbourDiscovery.cc:707
inet::ADDRESS_UNREACHABLE
@ ADDRESS_UNREACHABLE
Definition: Icmpv6Header_m.h:125
inet::Ipv6NeighbourDiscovery::rdList
RdList rdList
Definition: Ipv6NeighbourDiscovery.h:135
inet::Ipv6NeighbourCache::REACHABLE
@ REACHABLE
Definition: Ipv6NeighbourCache.h:41
inet::Ipv6NeighbourDiscovery::validateNsPacket
virtual bool validateNsPacket(Packet *packet, const Ipv6NeighbourSolicitation *ns)
Definition: Ipv6NeighbourDiscovery.cc:1876
inet::INITSTAGE_LOCAL
INET_API InitStage INITSTAGE_LOCAL
Initialization of local state that don't use or affect other modules includes:
inet::Ipv6NeighbourDiscovery::createAndSendNsPacket
virtual void createAndSendNsPacket(const Ipv6Address &nsTargetAddr, const Ipv6Address &dgDestAddr, const Ipv6Address &dgSrcAddr, NetworkInterface *ie)
Definition: Ipv6NeighbourDiscovery.cc:1809
inet::Ipv6NeighbourCache::getDefaultRouterList
DefaultRouterList & getDefaultRouterList()
Definition: Ipv6NeighbourCache.h:159
inet::Ipv6NeighbourDiscovery::processNsWithSpecifiedSrcAddr
virtual void processNsWithSpecifiedSrcAddr(Packet *packet, const Ipv6NeighbourSolicitation *ns, NetworkInterface *ie)
Definition: Ipv6NeighbourDiscovery.cc:1963
inet::NO_ROUTE_TO_DEST
@ NO_ROUTE_TO_DEST
Definition: Icmpv6Header_m.h:123
NUM_INIT_STAGES
#define NUM_INIT_STAGES
Definition: InitStageRegistry.h:73
inet::Ipv6NeighbourCache::Neighbour::isRouter
bool isRouter
Definition: Ipv6NeighbourCache.h:63
MK_ASSIGN_LINKLOCAL_ADDRESS
#define MK_ASSIGN_LINKLOCAL_ADDRESS
Definition: Ipv6NeighbourDiscovery.cc:28
inet::Ipv6NeighbourCache::lookup
virtual Neighbour * lookup(const Ipv6Address &addr, int interfaceID)
Returns a neighbour entry, or nullptr.
Definition: Ipv6NeighbourCache.cc:76
inet::Ipv6NeighbourCache::DELAY
@ DELAY
Definition: Ipv6NeighbourCache.h:41
inet::Ipv6NeighbourDiscovery::validateNaPacket
virtual bool validateNaPacket(Packet *packet, const Ipv6NeighbourAdvertisement *na)
Definition: Ipv6NeighbourDiscovery.cc:2215
inet::Ipv6NeighbourCache::DefaultRouterList::remove
void remove(Neighbour &router)
Definition: Ipv6NeighbourCache.cc:32
inet::Ipv6NeighbourDiscovery::processRaForRouterUpdates
virtual void processRaForRouterUpdates(Packet *packet, const Ipv6RouterAdvertisement *ra)
Definition: Ipv6NeighbourDiscovery.cc:1349
inet::Protocol::icmpv6
static const Protocol icmpv6
Definition: Protocol.h:72
inet::Ipv6NeighbourDiscovery::pendingQueue
cQueue pendingQueue
Definition: Ipv6NeighbourDiscovery.h:87
inet::Ipv6NeighbourDiscovery::createAndSendRaPacket
virtual void createAndSendRaPacket(const Ipv6Address &destAddr, NetworkInterface *ie)
Definition: Ipv6NeighbourDiscovery.cc:1175
inet::NodeStatus::UP
@ UP
Definition: NodeStatus.h:28
inet::Ipv6NeighbourDiscovery::processNaPacket
virtual void processNaPacket(Packet *packet, const Ipv6NeighbourAdvertisement *na)
Definition: Ipv6NeighbourDiscovery.cc:2179
inet::Ipv6NeighbourDiscovery::crcMode
CrcMode crcMode
Definition: Ipv6NeighbourDiscovery.h:92
inet::Ipv6NeighbourDiscovery::fetchRdEntry
virtual Ipv6NeighbourDiscovery::RdEntry * fetchRdEntry(NetworkInterface *ie)
Definition: Ipv6NeighbourDiscovery.cc:314
Enter_Method
#define Enter_Method(...)
Definition: SelfDoc.h:71
inet::Ipv6NeighbourDiscovery::fetchAdvIfEntry
virtual Ipv6NeighbourDiscovery::AdvIfEntry * fetchAdvIfEntry(NetworkInterface *ie)
Definition: Ipv6NeighbourDiscovery.cc:304
inet::Ipv6NeighbourCache::addNeighbour
virtual Neighbour * addNeighbour(const Ipv6Address &addr, int interfaceID)
Creates and initializes a neighbour entry with isRouter=false, state=INCOMPLETE.
Definition: Ipv6NeighbourCache.cc:89
inet::IPv6ND_TARGET_LINK_LAYER_ADDR_OPTION
@ IPv6ND_TARGET_LINK_LAYER_ADDR_OPTION
Definition: Ipv6NdMessage_m.h:90
MK_SEND_PERIODIC_RTRADV
#define MK_SEND_PERIODIC_RTRADV
Definition: Ipv6NeighbourDiscovery.cc:29
inet::Ipv6NeighbourDiscovery::processNsForTentativeAddress
virtual void processNsForTentativeAddress(Packet *packet, const Ipv6NeighbourSolicitation *ns)
Definition: Ipv6NeighbourDiscovery.cc:1920
inet::Ipv6NeighbourDiscovery::cancelRouterDiscovery
virtual void cancelRouterDiscovery(NetworkInterface *ie)
RFC 2461: Section 6.3.7 4th paragraph Once the host sends a Router Solicitation, and receives a valid...
Definition: Ipv6NeighbourDiscovery.cc:1016
inet::MacAddress::UNSPECIFIED_ADDRESS
static const MacAddress UNSPECIFIED_ADDRESS
The unspecified MAC address, 00:00:00:00:00:00.
Definition: MacAddress.h:31
IPv6_MAX_RTR_SOLICITATION_DELAY
#define IPv6_MAX_RTR_SOLICITATION_DELAY
Definition: Ipv6InterfaceData.h:48
inet::Ipv6NeighbourDiscovery::sendSolicitedRa
virtual void sendSolicitedRa(cMessage *msg)
Definition: Ipv6NeighbourDiscovery.cc:1748
inet::Ipv6NeighbourDiscovery::makeTentativeAddressPermanent
virtual void makeTentativeAddressPermanent(const Ipv6Address &tentativeAddr, NetworkInterface *ie)
Permanently assign the given address for the given interface entry.
Definition: Ipv6NeighbourDiscovery.cc:867
MK_INITIATE_RTRDIS
#define MK_INITIATE_RTRDIS
Definition: Ipv6NeighbourDiscovery.cc:31
inet::Ipv6NeighbourDiscovery::processIpv6Datagram
virtual void processIpv6Datagram(Packet *packet)
Definition: Ipv6NeighbourDiscovery.cc:215
inet::uint
unsigned int uint
Definition: INETDefs.h:55
inet::Ipv6NeighbourDiscovery::processNDMessage
virtual void processNDMessage(Packet *packet, const Icmpv6Header *msg)
Definition: Ipv6NeighbourDiscovery.cc:189
MK_SEND_SOL_RTRADV
#define MK_SEND_SOL_RTRADV
Definition: Ipv6NeighbourDiscovery.cc:30
inet::Ipv6NeighbourDiscovery::validateRsPacket
virtual bool validateRsPacket(Packet *packet, const Ipv6RouterSolicitation *rs)
Definition: Ipv6NeighbourDiscovery.cc:1139
inet::Ipv6NeighbourDiscovery::raTimerList
RaTimerList raTimerList
Definition: Ipv6NeighbourDiscovery.h:129
inet::Ipv6Address::SOLICITED_NODE_PREFIX
static const Ipv6Address SOLICITED_NODE_PREFIX
The solicited-node multicast address prefix (prefix length = 104)
Definition: Ipv6Address.h:75
inet::Ipv6NeighbourDiscovery::processNsForNonTentativeAddress
virtual void processNsForNonTentativeAddress(Packet *packet, const Ipv6NeighbourSolicitation *ns, NetworkInterface *ie)
Definition: Ipv6NeighbourDiscovery.cc:1947
inet::ICMPv6_DESTINATION_UNREACHABLE
@ ICMPv6_DESTINATION_UNREACHABLE
Definition: Icmpv6Header_m.h:85
inet::INITSTAGE_NETWORK_LAYER_PROTOCOLS
INET_API InitStage INITSTAGE_NETWORK_LAYER_PROTOCOLS
Initialization of network layer protocols over IP.
inet::Ipv6NeighbourDiscovery::processRsPacket
virtual void processRsPacket(Packet *packet, const Ipv6RouterSolicitation *rs)
Definition: Ipv6NeighbourDiscovery.cc:1062
inet::Ipv6NeighbourCache::Neighbour::macAddress
MacAddress macAddress
Definition: Ipv6NeighbourCache.h:62
inet::units::units::ns
nano< s >::type ns
Definition: Units.h:1074
inet::Ipv6NeighbourDiscovery::processNaForIncompleteNceState
virtual void processNaForIncompleteNceState(const Ipv6NeighbourAdvertisement *na, Ipv6NeighbourCache::Neighbour *nce)
Definition: Ipv6NeighbourDiscovery.cc:2253
inet::IPv6ND_SOURCE_LINK_LAYER_ADDR_OPTION
@ IPv6ND_SOURCE_LINK_LAYER_ADDR_OPTION
Definition: Ipv6NdMessage_m.h:89
inet::Ipv6NeighbourDiscovery::ift
ModuleRefByPar< IInterfaceTable > ift
Definition: Ipv6NeighbourDiscovery.h:89
inet::Ipv6NeighbourDiscovery::neighbourCache
Ipv6NeighbourCache neighbourCache
Definition: Ipv6NeighbourDiscovery.h:98
inet::IPv6ND_MTU_OPTION_LENGTH
const B IPv6ND_MTU_OPTION_LENGTH
Definition: Ipv6NdMessage_m.h:68