00001
00019 #include "IPv6NeighbourDiscovery.h"
00020
00021
00022 #define MK_ASSIGN_LINKLOCAL_ADDRESS 0
00023 #define MK_SEND_PERIODIC_RTRADV 1
00024 #define MK_SEND_SOL_RTRADV 2
00025 #define MK_INITIATE_RTRDIS 3
00026 #define MK_DAD_TIMEOUT 4
00027 #define MK_RD_TIMEOUT 5
00028 #define MK_NUD_TIMEOUT 6
00029 #define MK_AR_TIMEOUT 7
00030
00031 Define_Module(IPv6NeighbourDiscovery);
00032
00033
00034 IPv6NeighbourDiscovery::IPv6NeighbourDiscovery()
00035 {
00036 }
00037
00038 IPv6NeighbourDiscovery::~IPv6NeighbourDiscovery()
00039 {
00040
00041
00042
00043
00044
00045
00046
00047 }
00048
00049 void IPv6NeighbourDiscovery::initialize(int stage)
00050 {
00051
00052
00053
00054 if (stage==3)
00055 {
00056 ift = InterfaceTableAccess().get();
00057 rt6 = RoutingTable6Access().get();
00058 icmpv6 = ICMPv6Access().get();
00059 pendingQueue.setName("pendingQueue");
00060
00061 for (int i=0; i < ift->getNumInterfaces(); i++)
00062 {
00063 InterfaceEntry *ie = ift->getInterface(i);
00064
00065 if (ie->ipv6Data()->getAdvSendAdvertisements() && !(ie->isLoopback()))
00066 {
00067 createRATimer(ie);
00068 }
00069 }
00070
00071
00072 cMessage *msg = new cMessage("assignLinkLocalAddr", MK_ASSIGN_LINKLOCAL_ADDRESS);
00073
00074 if (rt6->isRouter())
00075 scheduleAt(uniform(0,0.3), msg);
00076 else
00077 scheduleAt(uniform(0.4,1), msg);
00078 }
00079 }
00080
00081 void IPv6NeighbourDiscovery::handleMessage(cMessage *msg)
00082 {
00083 if (msg->isSelfMessage())
00084 {
00085 EV << "Self message received!\n";
00086 if (msg->getKind()==MK_SEND_PERIODIC_RTRADV)
00087 {
00088 EV << "Sending periodic RA\n";
00089 sendPeriodicRA(msg);
00090 }
00091 else if (msg->getKind()==MK_SEND_SOL_RTRADV)
00092 {
00093 EV << "Sending solicited RA\n";
00094 sendSolicitedRA(msg);
00095 }
00096 else if (msg->getKind()==MK_ASSIGN_LINKLOCAL_ADDRESS)
00097 {
00098 EV << "Assigning Link Local Address\n";
00099 assignLinkLocalAddress(msg);
00100 }
00101 else if (msg->getKind()==MK_DAD_TIMEOUT)
00102 {
00103 EV << "DAD Timeout message received\n";
00104 processDADTimeout(msg);
00105 }
00106 else if (msg->getKind()==MK_RD_TIMEOUT)
00107 {
00108 EV << "Router Discovery message received\n";
00109 processRDTimeout(msg);
00110 }
00111 else if (msg->getKind()==MK_INITIATE_RTRDIS)
00112 {
00113 EV << "initiate router discovery.\n";
00114 initiateRouterDiscovery(msg);
00115 }
00116 else if (msg->getKind()==MK_NUD_TIMEOUT)
00117 {
00118 EV << "NUD Timeout message received\n";
00119 processNUDTimeout(msg);
00120 }
00121 else if (msg->getKind()==MK_AR_TIMEOUT)
00122 {
00123 EV << "Address Resolution Timeout message received\n";
00124 processARTimeout(msg);
00125 }
00126 else
00127 error("Unrecognized Timer");
00128 }
00129 else if (dynamic_cast<ICMPv6Message *>(msg))
00130 {
00131
00132 IPv6ControlInfo *ctrlInfo
00133 = check_and_cast<IPv6ControlInfo*>(msg->removeControlInfo());
00134 ICMPv6Message *ndMsg = (ICMPv6Message *)msg;
00135 processNDMessage(ndMsg, ctrlInfo);
00136 }
00137 else if (dynamic_cast<IPv6Datagram *>(msg))
00138 {
00139 IPv6Datagram *datagram = (IPv6Datagram *)msg;
00140 processIPv6Datagram(datagram);
00141 }
00142 else
00143 error("Unknown message type received.\n");
00144 }
00145
00146 void IPv6NeighbourDiscovery::processNDMessage(ICMPv6Message *msg,
00147 IPv6ControlInfo *ctrlInfo)
00148 {
00149
00150 if (dynamic_cast<IPv6RouterSolicitation *>(msg))
00151 {
00152 IPv6RouterSolicitation *rs = (IPv6RouterSolicitation *)msg;
00153 processRSPacket(rs, ctrlInfo);
00154 }
00155 else if (dynamic_cast<IPv6RouterAdvertisement *>(msg))
00156 {
00157 IPv6RouterAdvertisement *ra = (IPv6RouterAdvertisement *)msg;
00158 processRAPacket(ra, ctrlInfo);
00159 }
00160 else if (dynamic_cast<IPv6NeighbourSolicitation *>(msg))
00161 {
00162 IPv6NeighbourSolicitation *ns = (IPv6NeighbourSolicitation *)msg;
00163 processNSPacket(ns, ctrlInfo);
00164 }
00165 else if (dynamic_cast<IPv6NeighbourAdvertisement *>(msg))
00166 {
00167 IPv6NeighbourAdvertisement *na = (IPv6NeighbourAdvertisement *)msg;
00168 processNAPacket(na, ctrlInfo);
00169 }
00170 else if (dynamic_cast<IPv6Redirect *>(msg))
00171 {
00172 IPv6Redirect *redirect = (IPv6Redirect *)msg;
00173 processRedirectPacket(redirect, ctrlInfo);
00174 }
00175 else
00176 {
00177 error("Unrecognized ND message!");
00178 }
00179 }
00180
00181 void IPv6NeighbourDiscovery::finish()
00182 {
00183 }
00184
00185 void IPv6NeighbourDiscovery::processIPv6Datagram(IPv6Datagram *msg)
00186 {
00187 EV << "Packet " << msg << " arrived from IPv6 module.\n";
00188
00189 int nextHopIfID;
00190 EV << "Determining Next Hop" << endl;
00191 IPv6Address nextHopAddr = determineNextHop(msg->getDestAddress(), nextHopIfID);
00192 if (nextHopIfID == -1)
00193 {
00194
00195
00196 icmpv6->sendErrorMessage(msg, ICMPv6_DESTINATION_UNREACHABLE, NO_ROUTE_TO_DEST);
00197 return;
00198 }
00199 EV << "Next Hop Address is: " << nextHopAddr << " on interface: " << nextHopIfID << endl;
00200
00201
00202
00203
00204 Neighbour *nce = neighbourCache.lookup(nextHopAddr, nextHopIfID);
00205
00206 if (nce==NULL)
00207 {
00208
00209 EV << "No Entry exists in the Neighbour Cache.\n";
00210
00211
00212 EV << "Creating an INCOMPLETE entry in the neighbour cache.\n";
00213 nce = neighbourCache.addNeighbour(nextHopAddr, nextHopIfID);
00214
00215
00216 EV << "Initiating Address Resolution for:" << nextHopAddr
00217 << " on Interface:" << nextHopIfID << endl;
00218 initiateAddressResolution(msg->getSrcAddress(), nce);
00219
00220
00221 EV << "Add packet to entry's queue until Address Resolution is complete.\n";
00222 nce->pendingPackets.push_back(msg);
00223 pendingQueue.insert(msg);
00224 }
00225 else if (nce->reachabilityState == IPv6NeighbourCache::INCOMPLETE)
00226 {
00227 EV << "Reachability State is INCOMPLETE.Address Resolution already initiated.\n";
00228 bubble("Packet added to queue until Address Resolution is complete.");
00229 nce->pendingPackets.push_back(msg);
00230 pendingQueue.insert(msg);
00231 }
00232 else if (nce->macAddress.isUnspecified())
00233 {
00234 EV << "NCE's MAC address is unspecified.\n";
00235 EV << "Initiate Address Resolution and add packet to queue.\n";
00236 initiateAddressResolution(msg->getSrcAddress(), nce);
00237 nce->pendingPackets.push_back(msg);
00238 pendingQueue.insert(msg);
00239 }
00240 else if (nce->reachabilityState == IPv6NeighbourCache::STALE)
00241 {
00242 EV << "Reachability State is STALE.\n";
00243 send(msg,"ipv6Out");
00244 initiateNeighbourUnreachabilityDetection(nce);
00245 }
00246 else if (nce->reachabilityState == IPv6NeighbourCache::REACHABLE)
00247 {
00248 EV << "Next hop is REACHABLE, sending packet to next-hop address.";
00249 sendPacketToIPv6Module(msg, nextHopAddr, msg->getSrcAddress(), nextHopIfID);
00250 }
00251 else if (nce->reachabilityState == IPv6NeighbourCache::DELAY)
00252 {
00253 EV << "Next hop is in DELAY state, sending packet to next-hop address.";
00254 sendPacketToIPv6Module(msg, nextHopAddr, msg->getSrcAddress(), nextHopIfID);
00255 }
00256 else
00257 error("Unknown Neighbour cache entry state.");
00258 }
00259
00260 IPv6NeighbourDiscovery::AdvIfEntry *IPv6NeighbourDiscovery::fetchAdvIfEntry(InterfaceEntry *ie)
00261 {
00262 for (AdvIfList::iterator it=advIfList.begin(); it!=advIfList.end(); it++)
00263 {
00264 AdvIfEntry *advIfEntry = (*it);
00265 if (advIfEntry->interfaceId == ie->getInterfaceId())
00266 {
00267 return advIfEntry;
00268 }
00269 }
00270 return NULL;
00271 }
00272
00273 IPv6NeighbourDiscovery::RDEntry *IPv6NeighbourDiscovery::fetchRDEntry(InterfaceEntry *ie)
00274 {
00275 for (RDList::iterator it=rdList.begin(); it!=rdList.end(); it++)
00276 {
00277 RDEntry *rdEntry = (*it);
00278 if (rdEntry->interfaceId == ie->getInterfaceId())
00279 {
00280 return rdEntry;
00281 }
00282 }
00283 return NULL;
00284 }
00285
00286 const MACAddress& IPv6NeighbourDiscovery::resolveNeighbour(const IPv6Address& nextHop, int interfaceId)
00287 {
00288 Enter_Method("resolveNeighbor(%s,if=%d)", nextHop.str().c_str(), interfaceId);
00289
00290 Neighbour *nce = neighbourCache.lookup(nextHop, interfaceId);
00291
00292
00293 if (!nce || nce->reachabilityState==IPv6NeighbourCache::INCOMPLETE)
00294 return MACAddress::UNSPECIFIED_ADDRESS;
00295 else if (nce->reachabilityState==IPv6NeighbourCache::STALE)
00296 initiateNeighbourUnreachabilityDetection(nce);
00297 else if (nce->reachabilityState==IPv6NeighbourCache::REACHABLE &&
00298 simTime() > nce->reachabilityExpires)
00299 {
00300 nce->reachabilityState = IPv6NeighbourCache::STALE;
00301 initiateNeighbourUnreachabilityDetection(nce);
00302 }
00303 else if (nce->reachabilityState!=IPv6NeighbourCache::REACHABLE)
00304 {
00305
00306 ASSERT(nce->reachabilityState==IPv6NeighbourCache::DELAY ||
00307 nce->reachabilityState==IPv6NeighbourCache::PROBE);
00308 EV << "NUD in progress.\n";
00309 }
00310
00311 return nce->macAddress;
00312 }
00313
00314 void IPv6NeighbourDiscovery::reachabilityConfirmed(const IPv6Address& neighbour, int interfaceId)
00315 {
00316 Enter_Method("reachabilityConfirmed(%s,if=%d)", neighbour.str().c_str(), interfaceId);
00317
00318
00319
00320 Neighbour *nce = neighbourCache.lookup(neighbour, interfaceId);
00321
00322 cMessage *msg = nce->nudTimeoutEvent;
00323 if (msg != NULL)
00324 {
00325 EV << "NUD in progress. Cancelling NUD Timer\n";
00326 bubble("Reachability Confirmed via NUD.");
00327 cancelEvent(msg);
00328 delete msg;
00329 }
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379 }
00380
00381 IPv6Address IPv6NeighbourDiscovery::determineNextHop(
00382 const IPv6Address& destAddr, int& outIfID)
00383 {
00384 IPv6Address nextHopAddr;
00385
00386
00387
00388
00389
00390
00391 EV << "Find out if supplied dest addr is on-link or off-link.\n";
00392 const IPv6Route *route = rt6->doLongestPrefixMatch(destAddr);
00393
00394 if (route != NULL)
00395 {
00396
00397
00398 if (route->getNextHop().isUnspecified())
00399 {
00400 EV << "Dest is on-link, next-hop addr is same as dest addr.\n";
00401 outIfID = route->getInterfaceId();
00402 nextHopAddr = destAddr;
00403 }
00404 else
00405 {
00406 EV << "A next-hop address was found with the route, dest is off-link\n";
00407 EV << "Assume next-hop address as the selected default router.\n";
00408 outIfID = route->getInterfaceId();
00409 nextHopAddr = route->getNextHop();
00410 }
00411 }
00412 else
00413 {
00414
00415
00416
00417 EV << "No routes were found, Dest addr is off-link.\n";
00418 nextHopAddr = selectDefaultRouter(outIfID);
00419
00420 if (outIfID == -1) EV << "No Default Routers were found.";
00421 else EV << "Default router found.\n";
00422 }
00423
00424
00425
00426 rt6->updateDestCache(destAddr, nextHopAddr, outIfID);
00427 return nextHopAddr;
00428 }
00429
00430 void IPv6NeighbourDiscovery::initiateNeighbourUnreachabilityDetection(
00431 Neighbour *nce)
00432 {
00433 ASSERT(nce->reachabilityState==IPv6NeighbourCache::STALE);
00434 const Key *nceKey = nce->nceKey;
00435 EV << "Initiating Neighbour Unreachability Detection";
00436 InterfaceEntry *ie = ift->getInterfaceById(nceKey->interfaceID);
00437 EV << "Setting NCE state to DELAY.\n";
00438
00439
00440 nce->reachabilityState = IPv6NeighbourCache::DELAY;
00441
00442
00443 cMessage *msg = new cMessage("NUDTimeout", MK_NUD_TIMEOUT);
00444 msg->setContextPointer(nce);
00445 nce->nudTimeoutEvent = msg;
00446 scheduleAt(simTime()+ie->ipv6Data()->_getDelayFirstProbeTime(), msg);
00447 }
00448
00449 void IPv6NeighbourDiscovery::processNUDTimeout(cMessage *timeoutMsg)
00450 {
00451 EV << "NUD has timed out\n";
00452 Neighbour *nce = (Neighbour *) timeoutMsg->getContextPointer();
00453 const Key *nceKey = nce->nceKey;
00454 InterfaceEntry *ie = ift->getInterfaceById(nceKey->interfaceID);
00455
00456 if (nce->reachabilityState == IPv6NeighbourCache::DELAY)
00457 {
00458
00459
00460
00461 EV << "Neighbour Entry is still in DELAY state.\n";
00462 EV << "Entering PROBE state. Sending NS probe.\n";
00463 nce->reachabilityState = IPv6NeighbourCache::PROBE;
00464 nce->numProbesSent = 0;
00465 }
00466
00467
00468
00469
00470
00471 if (nce->numProbesSent == (int)ie->ipv6Data()->_getMaxUnicastSolicit())
00472 {
00473 EV << "Max number of probes have been sent." << endl;
00474 EV << "Neighbour is Unreachable, removing NCE." << endl;
00475 neighbourCache.remove(nceKey->address, nceKey->interfaceID);
00476 return;
00477 }
00478
00479
00480
00481 createAndSendNSPacket(nceKey->address, nceKey->address,
00482 ie->ipv6Data()->getPreferredAddress(), ie);
00483 nce->numProbesSent++;
00484
00485
00486
00487
00488 scheduleAt(simTime()+ie->ipv6Data()->_getRetransTimer(), timeoutMsg);
00489 }
00490
00491 IPv6Address IPv6NeighbourDiscovery::selectDefaultRouter(int& outIfID)
00492 {
00493 EV << "Selecting default router...\n";
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509 IPv6Address routerAddr;
00510
00511 for(IPv6NeighbourCache::iterator it=neighbourCache.begin(); it != neighbourCache.end(); it++)
00512 {
00513 Key key = it->first;
00514 Neighbour nce = it->second;
00515 bool routerExpired = false;
00516 if (nce.isDefaultRouter)
00517 {
00518 if (simTime()>nce.routerExpiryTime)
00519 {
00520 EV << "Found an expired default router. Deleting entry...\n";
00521 neighbourCache.remove(key.address,key.interfaceID);
00522 routerExpired = true;
00523 }
00524 }
00525
00526 if (routerExpired == false)
00527 {
00528 if (nce.reachabilityState == IPv6NeighbourCache::REACHABLE ||
00529 nce.reachabilityState == IPv6NeighbourCache::STALE ||
00530 nce.reachabilityState == IPv6NeighbourCache::DELAY)
00531 {
00532 EV << "Found a router in the neighbour cache(default router list).\n";
00533 outIfID = key.interfaceID;
00534 if (routerExpired == false) return key.address;
00535 }
00536 }
00537 }
00538 EV << "No suitable routers found.\n";
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559 outIfID = -1;
00560 return IPv6Address();
00561 }
00562
00563 void IPv6NeighbourDiscovery::timeoutPrefixEntry(const IPv6Address& destPrefix,
00564 int prefixLength)
00565 {
00566
00567
00568
00569 rt6->removeOnLinkPrefix(destPrefix, prefixLength);
00570
00571
00572
00573
00574
00575
00576 }
00577
00578 void IPv6NeighbourDiscovery::timeoutDefaultRouter(const IPv6Address& addr,
00579 int interfaceID)
00580 {
00581
00582
00583
00584 neighbourCache.remove(addr, interfaceID);
00585
00586
00587
00588
00589
00590 rt6->purgeDestCacheEntriesToNeighbour(addr, interfaceID);
00591 }
00592
00593 void IPv6NeighbourDiscovery::initiateAddressResolution(const IPv6Address& dgSrcAddr,
00594 Neighbour *nce)
00595 {
00596 const Key *nceKey = nce->nceKey;
00597 InterfaceEntry *ie = ift->getInterfaceById(nceKey->interfaceID);
00598 IPv6Address neighbourAddr = nceKey->address;
00599 int ifID = nceKey->interfaceID;
00600
00601
00602
00603
00604
00605
00606
00607 nce->reachabilityState = IPv6NeighbourCache::INCOMPLETE;
00608
00609
00610
00611
00612
00613 EV << "Preparing to send NS to solicited-node multicast group\n";
00614 EV << "on the next hop interface\n";
00615 IPv6Address nsDestAddr = neighbourAddr.formSolicitedNodeMulticastAddress();
00616 IPv6Address nsTargetAddr = neighbourAddr;
00617 IPv6Address nsSrcAddr;
00618
00619
00620
00621 if (ie->ipv6Data()->hasAddress(dgSrcAddr))
00622
00623
00624 nsSrcAddr = dgSrcAddr;
00625 else
00626
00627
00628 nsSrcAddr = ie->ipv6Data()->getPreferredAddress();
00629 ASSERT(ifID != -1);
00630
00631 createAndSendNSPacket(nsTargetAddr, nsDestAddr, nsSrcAddr, ie);
00632 nce->numOfARNSSent = 1;
00633 nce->nsSrcAddr = nsSrcAddr;
00634
00635
00636
00637
00638
00639 cMessage *msg = new cMessage("arTimeout", MK_AR_TIMEOUT);
00640 nce->arTimer = msg;
00641 msg->setContextPointer(nce);
00642 scheduleAt(simTime()+ie->ipv6Data()->_getRetransTimer(), msg);
00643 }
00644
00645
00646 void IPv6NeighbourDiscovery::processARTimeout(cMessage *arTimeoutMsg)
00647 {
00648
00649 Neighbour *nce = (Neighbour *)arTimeoutMsg->getContextPointer();
00650 const Key *nceKey = nce->nceKey;
00651 IPv6Address nsTargetAddr = nceKey->address;
00652 InterfaceEntry *ie = ift->getInterfaceById(nceKey->interfaceID);
00653 EV << "Num Of NS Sent:" << nce->numOfARNSSent << endl;
00654 EV << "Max Multicast Solicitation:" << ie->ipv6Data()->_getMaxMulticastSolicit() << endl;
00655 if (nce->numOfARNSSent < ie->ipv6Data()->_getMaxMulticastSolicit())
00656 {
00657 EV << "Sending another Address Resolution NS message" << endl;
00658 IPv6Address nsDestAddr = nsTargetAddr.formSolicitedNodeMulticastAddress();
00659 createAndSendNSPacket(nsTargetAddr, nsDestAddr, nce->nsSrcAddr, ie);
00660 nce->numOfARNSSent++;
00661 scheduleAt(simTime()+ie->ipv6Data()->_getRetransTimer(), arTimeoutMsg);
00662 return;
00663 }
00664 EV << "Address Resolution has failed." << endl;
00665 dropQueuedPacketsAwaitingAR(nce);
00666 EV << "Deleting AR timeout msg\n";
00667 delete arTimeoutMsg;
00668 }
00669
00670 void IPv6NeighbourDiscovery::dropQueuedPacketsAwaitingAR(Neighbour *nce)
00671 {
00672 const Key *nceKey = nce->nceKey;
00673
00674
00675
00676
00677
00678 MsgPtrVector pendingPackets = nce->pendingPackets;
00679 EV << "Pending Packets empty:" << pendingPackets.empty() << endl;
00680 while (!pendingPackets.empty())
00681 {
00682 MsgPtrVector::iterator i = pendingPackets.begin();
00683 cMessage *msg = (*i);
00684 IPv6Datagram *ipv6Msg = (IPv6Datagram *)msg;
00685
00686
00687 EV << "Sending ICMP unreachable destination." << endl;
00688 pendingPackets.erase(i);
00689 pendingQueue.remove(msg);
00690 icmpv6->sendErrorMessage(ipv6Msg, ICMPv6_DESTINATION_UNREACHABLE, ADDRESS_UNREACHABLE);
00691 }
00692
00693
00694
00695
00696 EV << "Removing neighbour cache entry" << endl;
00697 neighbourCache.remove(nceKey->address, nceKey->interfaceID);
00698 }
00699
00700 void IPv6NeighbourDiscovery::sendPacketToIPv6Module(cMessage *msg, const IPv6Address& destAddr,
00701 const IPv6Address& srcAddr, int interfaceId)
00702 {
00703 IPv6ControlInfo *controlInfo = new IPv6ControlInfo();
00704 controlInfo->setProtocol(IP_PROT_IPv6_ICMP);
00705 controlInfo->setDestAddr(destAddr);
00706 controlInfo->setSrcAddr(srcAddr);
00707 controlInfo->setHopLimit(255);
00708 controlInfo->setInterfaceId(interfaceId);
00709 msg->setControlInfo(controlInfo);
00710
00711 send(msg,"ipv6Out");
00712 }
00713
00716 void IPv6NeighbourDiscovery::sendQueuedPacketsToIPv6Module(Neighbour *nce)
00717 {
00718 MsgPtrVector& pendingPackets = nce->pendingPackets;
00719 while(!pendingPackets.empty())
00720 {
00721 MsgPtrVector::iterator i = pendingPackets.begin();
00722 cMessage *msg = (*i);
00723 pendingPackets.erase(i);
00724 pendingQueue.remove(msg);
00725 EV << "Sending queued packet " << msg << endl;
00726 send(msg,"ipv6Out");
00727 }
00728 }
00729
00730 void IPv6NeighbourDiscovery::assignLinkLocalAddress(cMessage *timerMsg)
00731 {
00732
00733
00734 for (int i=0; i < ift->getNumInterfaces(); i++)
00735 {
00736 InterfaceEntry *ie = ift->getInterface(i);
00737
00738
00739 if (ie->isLoopback()) continue;
00740
00741 IPv6Address linkLocalAddr = ie->ipv6Data()->getLinkLocalAddress();
00742 if (linkLocalAddr.isUnspecified())
00743 {
00744
00745 EV << "No link local address exists. Forming one" << endl;
00746 linkLocalAddr = IPv6Address().formLinkLocalAddress(ie->getInterfaceToken());
00747 ie->ipv6Data()->assignAddress(linkLocalAddr, true, 0, 0);
00748 }
00749
00750
00751 initiateDAD(linkLocalAddr, ie);
00752 }
00753 delete timerMsg;
00754 }
00755
00756 void IPv6NeighbourDiscovery::initiateDAD(const IPv6Address& tentativeAddr,
00757 InterfaceEntry *ie)
00758 {
00759 DADEntry *dadEntry = new DADEntry();
00760 dadEntry->interfaceId = ie->getInterfaceId();
00761 dadEntry->address = tentativeAddr;
00762 dadEntry->numNSSent = 0;
00763 dadList.insert(dadEntry);
00764
00765
00766
00767
00768
00769
00770
00771
00772 IPv6Address destAddr = tentativeAddr.formSolicitedNodeMulticastAddress();
00773
00774 createAndSendNSPacket(tentativeAddr, destAddr,
00775 IPv6Address::UNSPECIFIED_ADDRESS, ie);
00776 dadEntry->numNSSent++;
00777
00778 cMessage *msg = new cMessage("dadTimeout", MK_DAD_TIMEOUT);
00779 msg->setContextPointer(dadEntry);
00780 scheduleAt(simTime()+ie->ipv6Data()->getRetransTimer(), msg);
00781 }
00782
00783 void IPv6NeighbourDiscovery::processDADTimeout(cMessage *msg)
00784 {
00785 DADEntry *dadEntry = (DADEntry *)msg->getContextPointer();
00786 InterfaceEntry *ie = (InterfaceEntry *)ift->getInterfaceById(dadEntry->interfaceId);
00787 IPv6Address tentativeAddr = dadEntry->address;
00788
00789
00790 EV << "numOfDADMessagesSent is: " << dadEntry->numNSSent << endl;
00791 EV << "dupAddrDetectTrans is: " << ie->ipv6Data()->dupAddrDetectTransmits() << endl;
00792 if (dadEntry->numNSSent < ie->ipv6Data()->dupAddrDetectTransmits())
00793 {
00794 bubble("Sending another DAD NS message.");
00795 IPv6Address destAddr = tentativeAddr.formSolicitedNodeMulticastAddress();
00796 createAndSendNSPacket(dadEntry->address, destAddr, IPv6Address::UNSPECIFIED_ADDRESS, ie);
00797 dadEntry->numNSSent++;
00798
00799 scheduleAt(simTime()+ie->ipv6Data()->getRetransTimer(), msg);
00800 }
00801 else
00802 {
00803 bubble("Max number of DAD messages for interface sent. Address is unique.");
00804 ie->ipv6Data()->permanentlyAssign(tentativeAddr);
00805 dadList.erase(dadEntry);
00806 EV << "delete dadEntry and msg\n";
00807 delete dadEntry;
00808 delete msg;
00809
00810
00811
00812
00813
00814
00815
00816
00817 if (ie->ipv6Data()->getAdvSendAdvertisements() == false)
00818 {
00819 EV << "creating router discovery message timer\n";
00820 cMessage *rtrDisMsg = new cMessage("initiateRTRDIS",MK_INITIATE_RTRDIS);
00821 rtrDisMsg->setContextPointer(ie);
00822 simtime_t interval = uniform(0, ie->ipv6Data()->_getMaxRtrSolicitationDelay());
00823 scheduleAt(simTime()+interval, rtrDisMsg);
00824 }
00825 }
00826 }
00827
00828 IPv6RouterSolicitation *IPv6NeighbourDiscovery::createAndSendRSPacket(InterfaceEntry *ie)
00829 {
00830 ASSERT(ie->ipv6Data()->getAdvSendAdvertisements() == false);
00831
00832
00833
00834
00835 IPv6Address myIPv6Address = ie->ipv6Data()->getPreferredAddress();
00836 if (myIPv6Address.isUnspecified())
00837 myIPv6Address = ie->ipv6Data()->getLinkLocalAddress();
00838 if (ie->ipv6Data()->isTentativeAddress(myIPv6Address))
00839 myIPv6Address = IPv6Address::UNSPECIFIED_ADDRESS;
00840 IPv6Address destAddr = IPv6Address::ALL_ROUTERS_2;
00841 IPv6RouterSolicitation *rs = new IPv6RouterSolicitation("RSpacket");
00842 rs->setType(ICMPv6_ROUTER_SOL);
00843
00844
00845
00846 if (!myIPv6Address.isUnspecified())
00847 rs->setSourceLinkLayerAddress(ie->getMacAddress());
00848
00849
00850 sendPacketToIPv6Module(rs, destAddr, myIPv6Address, ie->getInterfaceId());
00851 return rs;
00852 }
00853
00854 void IPv6NeighbourDiscovery::initiateRouterDiscovery(cMessage *msg)
00855 {
00856 EV << "Initiating Router Discovery" << endl;
00857 InterfaceEntry *ie = (InterfaceEntry *)msg->getContextPointer();
00858 delete msg;
00859
00860
00861
00862
00863
00864
00865
00866 RDEntry *rdEntry = new RDEntry();
00867 rdEntry->interfaceId = ie->getInterfaceId();
00868 rdEntry->numRSSent = 0;
00869 createAndSendRSPacket(ie);
00870 rdEntry->numRSSent++;
00871
00872
00873 cMessage *rdTimeoutMsg = new cMessage("processRDTimeout", MK_RD_TIMEOUT);
00874 rdTimeoutMsg->setContextPointer(ie);
00875 rdEntry->timeoutMsg = rdTimeoutMsg;
00876 rdList.insert(rdEntry);
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886 scheduleAt(simTime()+ie->ipv6Data()->_getRtrSolicitationInterval(), rdTimeoutMsg);
00887 }
00888
00889 void IPv6NeighbourDiscovery::cancelRouterDiscovery(InterfaceEntry *ie)
00890 {
00891
00892 RDEntry *rdEntry = fetchRDEntry(ie);
00893 if (rdEntry != NULL)
00894 {
00895 EV << "rdEntry is not NULL, RD cancelled!" << endl;
00896 cancelEvent(rdEntry->timeoutMsg);
00897 rdList.erase(rdEntry);
00898 delete rdEntry;
00899 }
00900 else
00901 EV << "rdEntry is NULL, not cancelling RD!" << endl;
00902 }
00903
00904 void IPv6NeighbourDiscovery::processRDTimeout(cMessage *msg)
00905 {
00906 InterfaceEntry *ie = (InterfaceEntry *)msg->getContextPointer();
00907 RDEntry *rdEntry = fetchRDEntry(ie);
00908 if (rdEntry->numRSSent < ie->ipv6Data()->_getMaxRtrSolicitations())
00909 {
00910 bubble("Sending another RS message.");
00911 createAndSendRSPacket(ie);
00912 rdEntry->numRSSent++;
00913
00914 if (rdEntry->numRSSent == ie->ipv6Data()->_getMaxRtrSolicitations())
00915 scheduleAt(simTime()+ie->ipv6Data()->_getMaxRtrSolicitationDelay(), msg);
00916 else
00917 scheduleAt(simTime()+ie->ipv6Data()->_getRtrSolicitationInterval(), msg);
00918 }
00919 else
00920 {
00921
00922
00923
00924
00925
00926
00927
00928 bubble("Max number of RS messages sent");
00929 EV << "No RA messages were received. Assume no routers are on-link";
00930 delete rdEntry;
00931 delete msg;
00932 }
00933 }
00934
00935 void IPv6NeighbourDiscovery::processRSPacket(IPv6RouterSolicitation *rs,
00936 IPv6ControlInfo *rsCtrlInfo)
00937 {
00938 if (validateRSPacket(rs, rsCtrlInfo) == false) return;
00939
00940 InterfaceEntry *ie = ift->getInterfaceById(rsCtrlInfo->getInterfaceId());
00941 AdvIfEntry *advIfEntry = fetchAdvIfEntry(ie);
00942
00943
00944
00945 if (ie->ipv6Data()->getAdvSendAdvertisements())
00946 {
00947 EV << "This is an advertising interface, processing RS\n";
00948
00949 if (validateRSPacket(rs, rsCtrlInfo) == false) return;
00950 EV << "RS message validated\n";
00951
00952
00953 MACAddress macAddr = rs->getSourceLinkLayerAddress();
00954 EV << "MAC Address extracted\n";
00955 delete rs;
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978 cMessage *msg = new cMessage("sendSolicitedRA", MK_SEND_SOL_RTRADV);
00979 msg->setContextPointer(ie);
00980 simtime_t interval = uniform(0, ie->ipv6Data()->_getMaxRADelayTime());
00981
00982 if (interval < advIfEntry->nextScheduledRATime)
00983 {
00984 simtime_t nextScheduledTime;
00985 nextScheduledTime = simTime()+interval;
00986 scheduleAt(nextScheduledTime, msg);
00987 advIfEntry->nextScheduledRATime = nextScheduledTime;
00988 }
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002 }
01003 else
01004 {
01005 EV << "This interface is a host, discarding RA message\n";
01006 delete rs;
01007 }
01008 }
01009
01010 bool IPv6NeighbourDiscovery::validateRSPacket(IPv6RouterSolicitation *rs,
01011 IPv6ControlInfo *rsCtrlInfo)
01012 {
01013 bool result = true;
01014
01015
01016
01017
01018
01019
01020 if (rsCtrlInfo->getHopLimit() != 255)
01021 {
01022 EV << "Hop limit is not 255! RS validation failed!\n";
01023 result = false;
01024 }
01025
01026 if (rsCtrlInfo->getProtocol() != IP_PROT_IPv6_ICMP)
01027 {
01028 EV << "ICMP Code is not 0! RS validation failed!\n";
01029 result = false;
01030 }
01031
01032
01033 if (rsCtrlInfo->getSrcAddr().isUnspecified())
01034 {
01035 EV << "IP source address is unspecified\n";
01036 if (rs->getSourceLinkLayerAddress().isUnspecified() == false)
01037 {
01038 EV << " but source link layer address is provided. RS validation failed!\n";
01039 }
01040 }
01041 return result;
01042 }
01043
01044 IPv6RouterAdvertisement *IPv6NeighbourDiscovery::createAndSendRAPacket(
01045 const IPv6Address& destAddr, InterfaceEntry *ie)
01046 {
01047 EV << "Create and send RA invoked!\n";
01048
01049 IPv6Address sourceAddr = ie->ipv6Data()->getLinkLocalAddress();
01050
01051
01052 if (ie->ipv6Data()->getAdvSendAdvertisements())
01053 {
01054
01055 IPv6RouterAdvertisement *ra = new IPv6RouterAdvertisement("RApacket");
01056 ra->setType(ICMPv6_ROUTER_AD);
01057
01058
01059
01060
01061
01062
01063
01064
01065 ra->setRouterLifetime(SIMTIME_DBL(ie->ipv6Data()->getAdvDefaultLifetime()));
01066
01067
01068
01069 ra->setManagedAddrConfFlag(ie->ipv6Data()->getAdvManagedFlag());
01070 ra->setOtherStatefulConfFlag(ie->ipv6Data()->getAdvOtherConfigFlag());
01071
01072
01073 ra->setCurHopLimit(ie->ipv6Data()->getAdvCurHopLimit());
01074
01075
01076 ra->setReachableTime(ie->ipv6Data()->getAdvReachableTime());
01077
01078
01079 ra->setRetransTimer(ie->ipv6Data()->getAdvRetransTimer());
01080
01081
01082
01083
01084 ra->setSourceLinkLayerAddress(ie->getMacAddress());
01085 ra->setMTU(ie->ipv6Data()->getAdvLinkMTU());
01086
01087
01088 int numAdvPrefixes = ie->ipv6Data()->getNumAdvPrefixes();
01089 EV << "Number of Adv Prefixes: " << numAdvPrefixes << endl;
01090 ra->setPrefixInformationArraySize(numAdvPrefixes);
01091 for (int i = 0; i < numAdvPrefixes; i++)
01092 {
01093 IPv6InterfaceData::AdvPrefix advPrefix = ie->ipv6Data()->getAdvPrefix(i);
01094 IPv6NDPrefixInformation prefixInfo;
01095 prefixInfo.setPrefix(advPrefix.prefix);
01096 prefixInfo.setPrefixLength(advPrefix.prefixLength);
01097
01098
01099 prefixInfo.setOnlinkFlag(advPrefix.advOnLinkFlag);
01100
01101 prefixInfo.setValidLifetime(SIMTIME_DBL(advPrefix.advValidLifetime));
01102
01103
01104 prefixInfo.setAutoAddressConfFlag(advPrefix.advAutonomousFlag);
01105
01106 prefixInfo.setPreferredLifetime(SIMTIME_DBL(advPrefix.advPreferredLifetime));
01107
01108 ra->setPrefixInformation(i, prefixInfo);
01109 }
01110 sendPacketToIPv6Module(ra, destAddr, sourceAddr, ie->getInterfaceId());
01111 return ra;
01112 }
01113 return NULL;
01114 }
01115
01116 void IPv6NeighbourDiscovery::processRAPacket(IPv6RouterAdvertisement *ra,
01117 IPv6ControlInfo *raCtrlInfo)
01118 {
01119 InterfaceEntry *ie = ift->getInterfaceById(raCtrlInfo->getInterfaceId());
01120
01121 if (ie->ipv6Data()->getAdvSendAdvertisements())
01122 {
01123 EV << "Interface is an advertising interface, dropping RA message.\n";
01124 delete ra;
01125 return;
01126 }
01127 else
01128 {
01129 if (validateRAPacket(ra, raCtrlInfo) == false)
01130 {
01131 delete ra;
01132 return;
01133 }
01134 cancelRouterDiscovery(ie);
01135 EV << "Interface is a host, processing RA.\n";
01136
01137 processRAForRouterUpdates(ra, raCtrlInfo);
01138
01139
01140 MACAddress macAddress = ra->getSourceLinkLayerAddress();
01141 uint mtu = ra->getMTU();
01142 for (int i = 0; i < (int)ra->getPrefixInformationArraySize(); i++)
01143 {
01144 IPv6NDPrefixInformation& prefixInfo = ra->getPrefixInformation(i);
01145 if (prefixInfo.getAutoAddressConfFlag() == true)
01146 processRAPrefixInfoForAddrAutoConf(prefixInfo, ie);
01147 }
01148 }
01149 delete raCtrlInfo;
01150 delete ra;
01151 }
01152
01153 void IPv6NeighbourDiscovery::processRAForRouterUpdates(IPv6RouterAdvertisement *ra,
01154 IPv6ControlInfo *raCtrlInfo)
01155 {
01156 EV << "Processing RA for Router Updates\n";
01157
01158
01159
01160
01161
01162 IPv6Address raSrcAddr = raCtrlInfo->getSrcAddr();
01163 InterfaceEntry *ie = ift->getInterfaceById(raCtrlInfo->getInterfaceId());
01164 int ifID = ie->getInterfaceId();
01165
01166
01167
01168
01169
01170 Neighbour *neighbour = neighbourCache.lookup(raSrcAddr, ifID);
01171 if (neighbour == NULL)
01172 {
01173 EV << "Neighbour Cache Entry does not contain RA's source address\n";
01174 if (ra->getRouterLifetime() != 0)
01175 {
01176 EV << "RA's router lifetime is non-zero, creating an entry in the "
01177 << "Host's default router list.\n" << ra->getRouterLifetime();
01178
01179
01180 if (ra->getSourceLinkLayerAddress().isUnspecified())
01181 {
01182 neighbour = neighbourCache.addRouter(raSrcAddr, ifID,
01183 simTime()+ra->getRouterLifetime());
01184
01185 }
01186 else
01187 {
01188 neighbour = neighbourCache.addRouter(raSrcAddr, ifID,
01189 ra->getSourceLinkLayerAddress(), simTime()+ra->getRouterLifetime());
01190
01191 rt6->addDefaultRoute(raSrcAddr, ifID, simTime()+ra->getRouterLifetime());
01192 }
01193 }
01194 else
01195 {
01196 EV << "Router Lifetime is 0, adding NON-default router.\n";
01197
01198 if (ra->getSourceLinkLayerAddress().isUnspecified())
01199 neighbour = neighbourCache.addNeighbour(raSrcAddr, ifID);
01200 else
01201 neighbour = neighbourCache.addNeighbour(raSrcAddr, ifID,
01202 ra->getSourceLinkLayerAddress());
01203 neighbour->isRouter = true;
01204 }
01205 }
01206 else
01207 {
01208
01209
01210 neighbour->isRouter = true;
01211
01212
01213
01214 if (ra->getSourceLinkLayerAddress().isUnspecified() == false &&
01215 neighbour->macAddress.equals(ra->getSourceLinkLayerAddress()) == false)
01216 neighbour->macAddress = ra->getSourceLinkLayerAddress();
01217
01218
01219
01220
01221 neighbour->routerExpiryTime = simTime()+ra->getRouterLifetime();
01222
01223
01224
01225
01226 if (ra->getRouterLifetime() == 0)
01227 {
01228 EV << "RA's router lifetime is ZERO. Timing-out entry.\n";
01229 timeoutDefaultRouter(raSrcAddr, ifID);
01230 }
01231 }
01232
01233
01234
01235
01236
01237 if (ra->getCurHopLimit() != 0)
01238 {
01239 EV << "RA's Cur Hop Limit is non-zero. Setting host's Cur Hop Limit to "
01240 << "received value.\n";
01241 ie->ipv6Data()->setCurHopLimit(ra->getCurHopLimit());
01242 }
01243
01244
01245
01246 if (ra->getReachableTime() != 0)
01247 {
01248 EV << "RA's reachable time is non-zero ";
01249 if (ra->getReachableTime() != SIMTIME_DBL(ie->ipv6Data()->getReachableTime()))
01250 {
01251 EV << " and RA's and Host's reachable time differ, \nsetting host's base"
01252 << " reachable time to received value.\n";
01253 ie->ipv6Data()->setBaseReachableTime(ra->getReachableTime());
01254
01255
01256 ie->ipv6Data()->setReachableTime(ie->ipv6Data()->generateReachableTime());
01257 }
01258 EV << endl;
01259 }
01260
01261
01262
01263 if (ra->getRetransTimer() != 0)
01264 {
01265 EV << "RA's retrans timer is non-zero, copying retrans timer variable.\n";
01266 ie->ipv6Data()->setRetransTimer(ra->getRetransTimer());
01267 }
01268
01269
01270
01271
01272
01273
01274
01275 processRAPrefixInfo(ra, ie);
01276 }
01277
01278 void IPv6NeighbourDiscovery::processRAPrefixInfo(IPv6RouterAdvertisement *ra,
01279 InterfaceEntry *ie)
01280 {
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296 IPv6NDPrefixInformation prefixInfo;
01297
01298 for (int i = 0; i < (int)ra->getPrefixInformationArraySize(); i++)
01299 {
01300 prefixInfo = ra->getPrefixInformation(i);
01301 if (!prefixInfo.getOnlinkFlag()) break;
01302
01303
01304 EV << "Fetching Prefix Information:" << i+1 << " of "
01305 << ra->getPrefixInformationArraySize() << endl;
01306 uint prefixLength = prefixInfo.getPrefixLength();
01307 simtime_t validLifetime = prefixInfo.getValidLifetime();
01308 uint preferredLifetime = prefixInfo.getPreferredLifetime();
01309 IPv6Address prefix = prefixInfo.getPrefix();
01310
01311
01312
01313 if (prefix.isLinkLocal())
01314 {
01315 EV << "Prefix is link-local, ignoring prefix.\n";
01316 return;
01317 }
01318
01319
01320 if (!rt6->isPrefixPresent(prefix)) {
01321
01322 if (validLifetime != 0)
01323 {
01324
01325
01326 rt6->addOrUpdateOnLinkPrefix(prefix, prefixLength, ie->getInterfaceId(),
01327 simTime()+validLifetime);
01328 }
01329
01330
01331
01332 }
01333 else
01334 {
01335
01336
01337 if (validLifetime == 0)
01338 {
01339 EV << "Prefix Info's valid lifetime is 0, time-out prefix\n";
01340 rt6->removeOnLinkPrefix(prefix, prefixLength);
01341 return;
01342 }
01343
01344
01345
01346
01347 rt6->addOrUpdateOnLinkPrefix(prefix, prefixLength, ie->getInterfaceId(),
01348 simTime()+validLifetime);
01349 }
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359 }
01360 }
01361
01362 void IPv6NeighbourDiscovery::processRAPrefixInfoForAddrAutoConf(
01363 IPv6NDPrefixInformation& prefixInfo, InterfaceEntry *ie)
01364 {
01365 EV << "Processing Prefix Info for address auto-configuration.\n";
01366 IPv6Address prefix = prefixInfo.getPrefix();
01367 uint prefixLength = prefixInfo.getPrefixLength();
01368 simtime_t preferredLifetime = prefixInfo.getPreferredLifetime();
01369 simtime_t validLifetime = prefixInfo.getValidLifetime();
01370
01371
01372
01373
01374
01375
01376 if (prefixInfo.getPrefix().isLinkLocal() == true)
01377 {
01378 EV << "Prefix is link-local, ignore Prefix Information Option\n";
01379 return;
01380 }
01381
01382
01383
01384
01385 if (preferredLifetime > validLifetime)
01386 {
01387 EV << "Preferred lifetime is greater than valid lifetime, ignore Prefix Information\n";
01388 return;
01389 }
01390
01391 bool isPrefixAssignedToInterface = false;
01392 for (int i = 0; i < ie->ipv6Data()->getNumAddresses(); i++)
01393 {
01394 if (ie->ipv6Data()->getAddress(i).matches(prefix, prefixLength) == true)
01395 isPrefixAssignedToInterface = true;
01396 }
01397
01398
01399
01400
01401 if (isPrefixAssignedToInterface == false && validLifetime != 0)
01402 {
01403 IPv6Address linkLocalAddress = ie->ipv6Data()->getLinkLocalAddress();
01404 ASSERT(linkLocalAddress.isUnspecified() == false);
01405 IPv6Address newAddr = linkLocalAddress.setPrefix(prefix, prefixLength);
01406
01407
01408 EV << "Assigning new address to: " << ie->getName() << endl;
01409 ie->ipv6Data()->assignAddress(newAddr, false, simTime()+validLifetime,
01410 simTime()+preferredLifetime);
01411 }
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438 }
01439
01440 void IPv6NeighbourDiscovery::createRATimer(InterfaceEntry *ie)
01441 {
01442 cMessage *msg = new cMessage("sendPeriodicRA", MK_SEND_PERIODIC_RTRADV);
01443 msg->setContextPointer(ie);
01444 AdvIfEntry *advIfEntry = new AdvIfEntry();
01445 advIfEntry->interfaceId = ie->getInterfaceId();
01446 advIfEntry->numRASent = 0;
01447 simtime_t interval = uniform(ie->ipv6Data()->getMinRtrAdvInterval(), ie->ipv6Data()->getMaxRtrAdvInterval());
01448 advIfEntry->raTimeoutMsg = msg;
01449
01450 simtime_t nextScheduledTime = simTime() + interval;
01451 advIfEntry->nextScheduledRATime = nextScheduledTime;
01452 advIfList.insert(advIfEntry);
01453 EV << "Interval: " << interval << endl;
01454 EV << "Next scheduled time: " << nextScheduledTime << endl;
01455
01456 scheduleAt(nextScheduledTime, msg);
01457 }
01458
01459 void IPv6NeighbourDiscovery::resetRATimer(InterfaceEntry *ie)
01460 {
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478 }
01479
01480 void IPv6NeighbourDiscovery::sendPeriodicRA(cMessage *msg)
01481 {
01482 InterfaceEntry *ie = (InterfaceEntry *)msg->getContextPointer();
01483 AdvIfEntry *advIfEntry = fetchAdvIfEntry(ie);
01484 IPv6Address destAddr = IPv6Address("FF02::1");
01485 createAndSendRAPacket(destAddr, ie);
01486 advIfEntry->numRASent++;
01487 simtime_t nextScheduledTime;
01488
01489
01490
01491
01492
01493
01494 simtime_t interval = uniform(ie->ipv6Data()->getMinRtrAdvInterval(), ie->ipv6Data()->getMaxRtrAdvInterval());
01495 nextScheduledTime = simTime() + interval;
01496
01497
01498
01499 EV << "Num RA sent is: " << advIfEntry->numRASent << endl;
01500 EV << "maxInitialRtrAdvertisements is: " << ie->ipv6Data()->_getMaxInitialRtrAdvertisements() << endl;
01501 if(advIfEntry->numRASent <= ie->ipv6Data()->_getMaxInitialRtrAdvertisements())
01502 {
01503 if (interval > ie->ipv6Data()->_getMaxInitialRtrAdvertInterval())
01504 {
01505
01506
01507 nextScheduledTime = simTime() + ie->ipv6Data()->_getMaxInitialRtrAdvertInterval();
01508 EV << "Sending initial RA but interval is too long. Using default value." << endl;
01509 }
01510 else
01511 EV << "Sending initial RA. Using randomly generated interval." << endl;
01512 }
01513 EV << "Next scheduled time: " << nextScheduledTime << endl;
01514 advIfEntry->nextScheduledRATime = nextScheduledTime;
01515 ASSERT(nextScheduledTime > simTime());
01516 scheduleAt(nextScheduledTime, msg);
01517 }
01518
01519 void IPv6NeighbourDiscovery::sendSolicitedRA(cMessage *msg)
01520 {
01521 EV << "Send Solicited RA invoked!\n";
01522 InterfaceEntry *ie = (InterfaceEntry *)msg->getContextPointer();
01523 IPv6Address destAddr = IPv6Address("FF02::1");
01524 EV << "Testing condition!\n";
01525 createAndSendRAPacket(destAddr, ie);
01526 delete msg;
01527 }
01528
01529 bool IPv6NeighbourDiscovery::validateRAPacket(IPv6RouterAdvertisement *ra,
01530 IPv6ControlInfo *raCtrlInfo)
01531 {
01532 bool result = true;
01533
01534
01535
01536
01537 raCtrlInfo->getSrcAddr();
01538
01539
01540
01541
01542 if (raCtrlInfo->getSrcAddr().isLinkLocal() == false)
01543 {
01544 EV << "RA source address is not link-local. RA validation failed!\n";
01545 result = false;
01546 }
01547
01548
01549
01550 if (raCtrlInfo->getHopLimit() != 255)
01551 {
01552 EV << "Hop limit is not 255! RA validation failed!\n";
01553 result = false;
01554 }
01555
01556
01557 if (raCtrlInfo->getProtocol() != IP_PROT_IPv6_ICMP)
01558 {
01559 EV << "ICMP Code is not 0! RA validation failed!\n";
01560 result = false;
01561 }
01562
01563 return result;
01564 }
01565
01566 IPv6NeighbourSolicitation *IPv6NeighbourDiscovery::createAndSendNSPacket(
01567 const IPv6Address& nsTargetAddr, const IPv6Address& dgDestAddr,
01568 const IPv6Address& dgSrcAddr, InterfaceEntry *ie)
01569 {
01570 MACAddress myMacAddr = ie->getMacAddress();
01571
01572
01573 IPv6NeighbourSolicitation *ns = new IPv6NeighbourSolicitation("NSpacket");
01574 ns->setType(ICMPv6_NEIGHBOUR_SOL);
01575
01576
01577 ns->setTargetAddress(nsTargetAddr);
01578
01579
01580
01581
01582 if (dgDestAddr.matches(IPv6Address("FF02::1:FF00:0"),104) &&
01583 !dgSrcAddr.isUnspecified())
01584 ns->setSourceLinkLayerAddress(myMacAddr);
01585
01586 sendPacketToIPv6Module(ns, dgDestAddr, dgSrcAddr, ie->getInterfaceId());
01587
01588 return ns;
01589 }
01590
01591 void IPv6NeighbourDiscovery::processNSPacket(IPv6NeighbourSolicitation *ns,
01592 IPv6ControlInfo *nsCtrlInfo)
01593 {
01594
01595 InterfaceEntry *ie = ift->getInterfaceById(nsCtrlInfo->getInterfaceId());
01596
01597 IPv6Address nsTargetAddr = ns->getTargetAddress();
01598
01599
01600
01601
01602 if (validateNSPacket(ns, nsCtrlInfo) == false
01603 || ie->ipv6Data()->hasAddress(nsTargetAddr) == false)
01604 {
01605 bubble("NS validation failed\n");
01606 delete nsCtrlInfo;
01607 delete ns;
01608 return;
01609 }
01610 bubble("NS validation passed.\n");
01611 if (ie->ipv6Data()->isTentativeAddress(nsTargetAddr))
01612 {
01613
01614
01615 EV << "Process NS for Tentative target address.\n";
01616 processNSForTentativeAddress(ns, nsCtrlInfo);
01617 }
01618 else
01619 {
01620
01621 EV << "Process NS for Non-Tentative target address.\n";
01622 processNSForNonTentativeAddress(ns, nsCtrlInfo, ie);
01623 }
01624 delete nsCtrlInfo;
01625 delete ns;
01626 }
01627
01628 bool IPv6NeighbourDiscovery::validateNSPacket(IPv6NeighbourSolicitation *ns,
01629 IPv6ControlInfo *nsCtrlInfo)
01630 {
01631 bool result = true;
01632
01633
01634
01635
01636
01637 if (nsCtrlInfo->getHopLimit() != 255)
01638 {
01639 EV << "Hop limit is not 255! NS validation failed!\n";
01640 result = false;
01641 }
01642
01643 if (ns->getTargetAddress().isMulticast() == true)
01644 {
01645 EV << "Target address is a multicast address! NS validation failed!\n";
01646 result = false;
01647 }
01648
01649 if (nsCtrlInfo->getSrcAddr().isUnspecified())
01650 {
01651 EV << "Source Address is unspecified\n";
01652
01653 if (nsCtrlInfo->getDestAddr().matches(IPv6Address::SOLICITED_NODE_PREFIX,104) == false)
01654 {
01655 EV << " but IP dest address is not a solicited-node multicast address! NS validation failed!\n";
01656 result = false;
01657 }
01658
01659 else if (ns->getSourceLinkLayerAddress().isUnspecified() == false)
01660 {
01661 EV << " but Source link-layer address is not empty! NS validation failed!\n";
01662 result = false;
01663 }
01664 else
01665 EV << "NS Validation Passed\n";
01666 }
01667
01668 return result;
01669 }
01670
01671 void IPv6NeighbourDiscovery::processNSForTentativeAddress(IPv6NeighbourSolicitation *ns,
01672 IPv6ControlInfo *nsCtrlInfo)
01673 {
01674
01675 IPv6Address nsSrcAddr = nsCtrlInfo->getSrcAddr();
01676 IPv6Address nsDestAddr = nsCtrlInfo->getDestAddr();
01677
01678 ASSERT(nsSrcAddr.isUnicast() || nsSrcAddr.isUnspecified());
01679
01680
01681 if (nsSrcAddr.isUnspecified())
01682 {
01683 EV << "Source Address is UNSPECIFIED. Sender is performing DAD\n";
01684
01685 if (rt6->isLocalAddress(nsSrcAddr))
01686 EV << "NS comes from myself. Ignoring NS\n";
01687 else
01688 EV << "NS comes from another node. Address is duplicate!\n";
01689 error("Duplicate Address Detected! Manual Attention Required!");
01690 }
01691 else if (nsSrcAddr.isUnicast())
01692 {
01693
01694 EV << "Sender is performing Address Resolution\n";
01695 EV << "Target Address is tentative. Ignoring NS.\n";
01696 }
01697 }
01698
01699 void IPv6NeighbourDiscovery::processNSForNonTentativeAddress(IPv6NeighbourSolicitation *ns,
01700 IPv6ControlInfo *nsCtrlInfo, InterfaceEntry *ie)
01701 {
01702
01703 MACAddress nsMacAddr = ns->getSourceLinkLayerAddress();
01704
01705 int ifID = ie->getInterfaceId();
01706
01707
01708
01709 if (nsCtrlInfo->getSrcAddr().isUnspecified())
01710 {
01711 EV << "Address is duplicate! Inform Sender of duplicate address!\n";
01712 sendSolicitedNA(ns, nsCtrlInfo, ie);
01713 }
01714 else
01715 {
01716 processNSWithSpecifiedSrcAddr(ns, nsCtrlInfo, ie);
01717 }
01718 }
01719
01720 void IPv6NeighbourDiscovery::processNSWithSpecifiedSrcAddr(IPv6NeighbourSolicitation *ns,
01721 IPv6ControlInfo *nsCtrlInfo, InterfaceEntry *ie)
01722 {
01723
01724
01725
01726
01727
01728
01729
01730 MACAddress nsMacAddr = ns->getSourceLinkLayerAddress();
01731
01732 int ifID = ie->getInterfaceId();
01733
01734
01735 Neighbour *entry = neighbourCache.lookup(nsCtrlInfo->getSrcAddr(), ifID);
01736
01737 if (entry == NULL)
01738 {
01739
01740
01741 EV << "Neighbour Entry not found. Create a Neighbour Cache Entry.\n";
01742 neighbourCache.addNeighbour(nsCtrlInfo->getSrcAddr(), ifID, nsMacAddr);
01743 }
01744 else
01745 {
01746
01747
01748 if (!(entry->macAddress.equals(nsMacAddr)) && !nsMacAddr.isUnspecified())
01749 {
01750
01751 entry->macAddress = nsMacAddr;
01752
01753 entry->reachabilityState = IPv6NeighbourCache::STALE;
01754 }
01755 }
01756
01757
01758 sendSolicitedNA(ns, nsCtrlInfo, ie);
01759 }
01760
01761 void IPv6NeighbourDiscovery::sendSolicitedNA(IPv6NeighbourSolicitation *ns,
01762 IPv6ControlInfo *nsCtrlInfo, InterfaceEntry *ie)
01763 {
01764 IPv6NeighbourAdvertisement *na = new IPv6NeighbourAdvertisement("NApacket");
01765
01766
01767
01768
01769
01770 na->setTargetAddress(ns->getTargetAddress());
01771
01772
01773
01774
01775
01776
01777 na->setTargetLinkLayerAddress(ie->getMacAddress());
01778
01779
01780
01781 na->setRouterFlag(rt6->isRouter());
01782
01783
01784
01785
01786
01787 if (ns->getSourceLinkLayerAddress().isUnspecified())
01788
01789 na->setOverrideFlag(false);
01790 else
01791
01792 na->setOverrideFlag(true);
01793
01794
01795
01796
01797 IPv6Address naDestAddr;
01798
01799 if(nsCtrlInfo->getSrcAddr().isUnspecified())
01800 {
01801
01802
01803 na->setSolicitedFlag(false);
01804 naDestAddr = IPv6Address::ALL_NODES_2;
01805 }
01806 else
01807 {
01808
01809
01810 na->setSolicitedFlag(true);
01811 naDestAddr = nsCtrlInfo->getSrcAddr();
01812 }
01813
01814
01815
01816
01817
01818
01819
01820
01821
01822
01823
01824
01825
01826
01827
01828
01829
01830
01831
01832
01833 IPv6Address myIPv6Addr = ie->ipv6Data()->getPreferredAddress();
01834 sendPacketToIPv6Module(na, naDestAddr, myIPv6Addr, ie->getInterfaceId());
01835 }
01836
01837 void IPv6NeighbourDiscovery::sendUnsolicitedNA(InterfaceEntry *ie)
01838 {
01839
01840
01841
01842
01843
01844
01845
01846
01847
01848
01849
01850
01851
01852
01853
01854
01855
01856
01857
01858
01859
01860
01861
01862
01863
01864
01865
01866
01867
01868
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884
01885
01886
01887
01888
01889 }
01890
01891 void IPv6NeighbourDiscovery::processNAPacket(IPv6NeighbourAdvertisement *na,
01892 IPv6ControlInfo *naCtrlInfo)
01893 {
01894 if (validateNAPacket(na, naCtrlInfo) == false)
01895 {
01896 delete naCtrlInfo;
01897 delete na;
01898 return;
01899 }
01900
01901
01902 IPv6Address naTargetAddr = na->getTargetAddress();
01903
01904
01905
01906 InterfaceEntry *ie = ift->getInterfaceById(naCtrlInfo->getInterfaceId());
01907 if (ie->ipv6Data()->isTentativeAddress(naTargetAddr))
01908 {
01909 error("Duplicate Address Detected! Manual attention needed!");
01910 }
01911
01912 Neighbour *neighbourEntry = neighbourCache.lookup(naTargetAddr, ie->getInterfaceId());
01913
01914 if (neighbourEntry == NULL)
01915 {
01916 EV << "NA received. Target Address not found in Neighbour Cache\n";
01917 EV << "Dropping NA packet.\n";
01918 delete naCtrlInfo;
01919 delete na;
01920 return;
01921 }
01922
01923
01924 EV << "NA received. Target Address found in Neighbour Cache\n";
01925
01926 if (neighbourEntry->reachabilityState == IPv6NeighbourCache::INCOMPLETE)
01927 processNAForIncompleteNCEState(na, neighbourEntry);
01928 else
01929 processNAForOtherNCEStates(na, neighbourEntry);
01930 delete naCtrlInfo;
01931 delete na;
01932 }
01933
01934 bool IPv6NeighbourDiscovery::validateNAPacket(IPv6NeighbourAdvertisement *na,
01935 IPv6ControlInfo *naCtrlInfo)
01936 {
01937 bool result = true;
01938
01939
01940
01941
01942
01943
01944
01945 if (naCtrlInfo->getHopLimit() != 255)
01946 {
01947 EV << "Hop Limit is not 255! NA validation failed!\n";
01948 result = false;
01949 }
01950
01951
01952 if (na->getTargetAddress().isMulticast() == true)
01953 {
01954 EV << "Target Address is a multicast address! NA validation failed!\n";
01955 result = false;
01956 }
01957
01958
01959
01960 if (naCtrlInfo->getDestAddr().isMulticast())
01961 {
01962 if (na->getSolicitedFlag() == true)
01963 {
01964 EV << "Dest Address is multicast address but solicted flag is 0!\n";
01965 result = false;
01966 }
01967 }
01968
01969 if (result == true) bubble("NA validation passed.");
01970 else bubble("NA validation failed.");
01971 return result;
01972 }
01973
01974 void IPv6NeighbourDiscovery::processNAForIncompleteNCEState(
01975 IPv6NeighbourAdvertisement *na, Neighbour *nce)
01976 {
01977 MACAddress naMacAddr = na->getTargetLinkLayerAddress();
01978 bool naRouterFlag = na->getRouterFlag();
01979 bool naSolicitedFlag = na->getSolicitedFlag();
01980 const Key *nceKey = nce->nceKey;
01981 InterfaceEntry *ie = ift->getInterfaceById(nceKey->interfaceID);
01982
01983
01984
01985 if (naMacAddr.isUnspecified())
01986 {
01987
01988
01989
01990 EV << "No MAC Address specified in NA. Ignoring NA\n";
01991 return;
01992 }
01993 else
01994 {
01995
01996
01997 EV << "ND is updating Neighbour Cache Entry.\n";
01998 nce->macAddress = naMacAddr;
01999
02000
02001
02002 if (naSolicitedFlag == true)
02003 {
02004 nce->reachabilityState = IPv6NeighbourCache::REACHABLE;
02005 EV << "Reachability confirmed through successful Addr Resolution.\n";
02006 nce->reachabilityExpires = simTime() + ie->ipv6Data()->_getReachableTime();
02007 }
02008 else
02009 nce->reachabilityState = IPv6NeighbourCache::STALE;
02010
02011
02012
02013 nce->isRouter = naRouterFlag;
02014
02015
02016
02017 sendQueuedPacketsToIPv6Module(nce);
02018 cancelEvent(nce->arTimer);
02019 }
02020 }
02021
02022 void IPv6NeighbourDiscovery:: processNAForOtherNCEStates(
02023 IPv6NeighbourAdvertisement *na, Neighbour *nce)
02024 {
02025 bool naRouterFlag = na->getRouterFlag();
02026 bool naSolicitedFlag = na->getSolicitedFlag();
02027 bool naOverrideFlag = na->getOverrideFlag();
02028 MACAddress naMacAddr = na->getTargetLinkLayerAddress();
02029 const Key *nceKey = nce->nceKey;
02030 InterfaceEntry *ie = ift->getInterfaceById(nceKey->interfaceID);
02031
02032
02033
02034
02035
02036
02037 if (naOverrideFlag == false && !(naMacAddr.equals(nce->macAddress))
02038 && !(naMacAddr.isUnspecified()))
02039 {
02040 EV << "NA override is FALSE and NA MAC addr is different.\n";
02041
02042
02043
02044
02045 if (nce->reachabilityState == IPv6NeighbourCache::REACHABLE)
02046 {
02047 EV << "NA mac is different. Change NCE state from REACHABLE to STALE\n";
02048
02049 nce->reachabilityState = IPv6NeighbourCache::STALE;
02050 }
02051 else
02052
02053
02054 EV << "NCE is not in REACHABLE state. Ignore NA.\n";
02055 }
02056 else if (naOverrideFlag == true || naMacAddr.equals(nce->macAddress)
02057 || naMacAddr.isUnspecified())
02058 {
02059 EV << "NA override flag is TRUE. or Advertised MAC is same as NCE's. or"
02060 << " NA MAC is not specified.\n";
02061
02062
02063
02064
02065
02066
02067
02068
02069 if (!(naMacAddr.isUnspecified()) &&
02070 !(naMacAddr.equals(nce->macAddress)))
02071 {
02072 EV << "Updating NCE's MAC addr with NA's.\n";
02073 nce->macAddress = naMacAddr;
02074 }
02075
02076
02077 if (naSolicitedFlag == true)
02078 {
02079 EV << "Solicited Flag is TRUE. Set NCE state to REACHABLE.\n";
02080
02081 nce->reachabilityState = IPv6NeighbourCache::REACHABLE;
02082
02083 cMessage *msg = nce->nudTimeoutEvent;
02084 if (msg != NULL)
02085 {
02086 EV << "NUD in progress. Cancelling NUD Timer\n";
02087 bubble("Reachability Confirmed via NUD.");
02088 nce->reachabilityExpires = simTime() + ie->ipv6Data()->_getReachableTime();
02089 cancelEvent(msg);
02090 delete msg;
02091 }
02092 }
02093 else
02094 {
02095
02096 EV << "Solicited Flag is FALSE.\n";
02097
02098 if (!(naMacAddr.equals(nce->macAddress)))
02099 {
02100 EV << "NA's MAC is different from NCE's.Set NCE state to STALE\n";
02101
02102 nce->reachabilityState = IPv6NeighbourCache::STALE;
02103 }
02104 else
02105
02106 EV << "NA's MAC is the same as NCE's. State remains unchanged.\n";
02107 }
02108
02109
02110
02111
02112 EV << "Updating NCE's router flag to " << naRouterFlag << endl;
02113 nce->isRouter = naRouterFlag;
02114
02115
02116
02117
02118
02119
02120
02121
02122 }
02123 }
02124
02125 IPv6Redirect *IPv6NeighbourDiscovery::createAndSendRedirectPacket(InterfaceEntry *ie)
02126 {
02127
02128 IPv6Redirect *redirect = new IPv6Redirect("redirectMsg");
02129 redirect->setType(ICMPv6_REDIRECT);
02130
02131
02132
02133
02134
02135
02136
02137
02138 return redirect;
02139 }
02140
02141 void IPv6NeighbourDiscovery::processRedirectPacket(IPv6Redirect *redirect,
02142 IPv6ControlInfo *ctrlInfo)
02143 {
02144
02145 IPv6Address targetAddr = redirect->getTargetAddress();
02146 IPv6Address destAddr = redirect->getDestinationAddress();
02147
02148
02149 MACAddress macAddr = redirect->getTargetLinkLayerAddress();
02150 }
02151