IPv6NeighbourDiscovery.cc

Go to the documentation of this file.
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     // FIXME delete the following data structures, cancelAndDelete timers in them etc.
00041     // Deleting the data structures my become unnecessary if the lists store the
00042     // structs themselves and not pointers.
00043     //   RATimerList raTimerList;
00044     //   DADList dadList;
00045     //   RDList rdList;
00046     //   AdvIfList advIfList;
00047 }
00048 
00049 void IPv6NeighbourDiscovery::initialize(int stage)
00050 {
00051     // We have to wait until the 3rd stage (stage 2) with scheduling messages,
00052     // because interface registration and IPv6 configuration takes places
00053     // in the first two stages.
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         //This simulates random node bootup time. Link local address assignment
00071         //takes place during this time.
00072         cMessage *msg = new cMessage("assignLinkLocalAddr", MK_ASSIGN_LINKLOCAL_ADDRESS);
00073         //We want routers to boot up faster!
00074         if (rt6->isRouter())
00075             scheduleAt(uniform(0,0.3), msg);//Random Router bootup time
00076         else
00077             scheduleAt(uniform(0.4,1), msg);//Random Host bootup time
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");//stops sim w/ error msg.
00128     }
00129     else if (dynamic_cast<ICMPv6Message *>(msg))
00130     {
00131         //This information will serve as input parameters to various processors.
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))// not ND message
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         //draft-ietf-ipv6-2461bis-04 has omitted on-link assumption.
00195         //draft-ietf-v6ops-onlinkassumption-03 explains why.
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     //RFC2461: Section 5.2 Conceptual Sending Algorithm
00202     //Once the IP address of the next-hop node is known, the sender examines the
00203     //Neighbor Cache for link-layer information about that neighbor.
00204     Neighbour *nce = neighbourCache.lookup(nextHopAddr, nextHopIfID);
00205 
00206     if (nce==NULL)
00207     {
00208         //If no entry exists,
00209         EV << "No Entry exists in the Neighbour Cache.\n";
00210 
00211         //the sender creates one, sets its state to INCOMPLETE,
00212         EV << "Creating an INCOMPLETE entry in the neighbour cache.\n";
00213         nce = neighbourCache.addNeighbour(nextHopAddr, nextHopIfID);
00214 
00215         //initiates Address Resolution,
00216         EV << "Initiating Address Resolution for:" << nextHopAddr
00217            << " on Interface:" << nextHopIfID << endl;
00218         initiateAddressResolution(msg->getSrcAddress(), nce);
00219 
00220         //and then queues the data packet pending completion of address resolution.
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)//TODO: What if NCE is in PROBE state?
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     //InterfaceEntry *ie = ift->getInterfaceById(interfaceId);
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         //reachability state must be either in DELAY or PROBE
00306         ASSERT(nce->reachabilityState==IPv6NeighbourCache::DELAY ||
00307                nce->reachabilityState==IPv6NeighbourCache::PROBE);
00308         EV << "NUD in progress.\n";
00309     }
00310     //else the entry is REACHABLE and no further action is required here.
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     //hmmm... this should only be invoked if a TCP ACK was received and NUD is
00318     //currently being performed on the neighbour where the TCP ACK was received from.
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     // TODO (see header file for description)
00332     /*A neighbor is considered reachable if the node has recently received
00333     a confirmation that packets sent recently to the neighbor were
00334     received by its IP layer.  Positive confirmation can be gathered in
00335     two ways: hints from upper layer protocols that indicate a connection
00336     is making "forward progress", or receipt of a Neighbor Advertisement
00337     message that is a response to a Neighbor Solicitation message.
00338 
00339     A connection makes "forward progress" if the packets received from a
00340     remote peer can only be arriving if recent packets sent to that peer
00341     are actually reaching it.  In TCP, for example, receipt of a (new)
00342     acknowledgement indicates that previously sent data reached the peer.
00343     Likewise, the arrival of new (non-duplicate) data indicates that
00344 
00345     earlier acknowledgements are being delivered to the remote peer.  If
00346     packets are reaching the peer, they must also be reaching the
00347     sender's next-hop neighbor; thus "forward progress" is a confirmation
00348     that the next-hop neighbor is reachable.  For off-link destinations,
00349     forward progress implies that the first-hop router is reachable.
00350     When available, this upper-layer information SHOULD be used.
00351 
00352     In some cases (e.g., UDP-based protocols and routers forwarding
00353     packets to hosts) such reachability information may not be readily
00354     available from upper-layer protocols.  When no hints are available
00355     and a node is sending packets to a neighbor, the node actively probes
00356     the neighbor using unicast Neighbor Solicitation messages to verify
00357     that the forward path is still working.
00358 
00359     The receipt of a solicited Neighbor Advertisement serves as
00360     reachability confirmation, since advertisements with the Solicited
00361     flag set to one are sent only in response to a Neighbor Solicitation.
00362     Receipt of other Neighbor Discovery messages such as Router
00363     Advertisements and Neighbor Advertisement with the Solicited flag set
00364     to zero MUST NOT be treated as a reachability confirmation.  Receipt
00365     of unsolicited messages only confirm the one-way path from the sender
00366     to the recipient node.  In contrast, Neighbor Unreachability
00367     Detection requires that a node keep track of the reachability of the
00368     forward path to a neighbor from the its perspective, not the
00369     neighbor's perspective.  Note that receipt of a solicited
00370     advertisement indicates that a path is working in both directions.
00371     The solicitation must have reached the neighbor, prompting it to
00372     generate an advertisement.  Likewise, receipt of an advertisement
00373     indicates that the path from the sender to the recipient is working.
00374     However, the latter fact is known only to the recipient; the
00375     advertisement's sender has no direct way of knowing that the
00376     advertisement it sent actually reached a neighbor.  From the
00377     perspective of Neighbor Unreachability Detection, only the
00378     reachability of the forward path is of interest.*/
00379 }
00380 
00381 IPv6Address IPv6NeighbourDiscovery::determineNextHop(
00382     const IPv6Address& destAddr, int& outIfID)
00383 {
00384     IPv6Address nextHopAddr;
00385 
00386     //RFC 2461 Section 5.2
00387     //Next-hop determination for a given unicast destination operates as follows.
00388 
00389     //The sender performs a longest prefix match against the Prefix List to
00390     //determine whether the packet's destination is on- or off-link.
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         //If the destination is on-link, the next-hop address is the same as the
00397         //packet's destination address.
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         //Otherwise, the sender selects a router from the Default Router List
00415         //(following the rules described in Section 6.3.6).
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     /*the results of next-hop determination computations are saved in the Destination
00425     Cache (which also contains updates learned from Redirect messages).*/
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     /*The first time a node sends a packet to a neighbor whose entry is
00439     STALE, the sender changes the state to DELAY*/
00440     nce->reachabilityState = IPv6NeighbourCache::DELAY;
00441 
00442     /*and sets a timer to expire in DELAY_FIRST_PROBE_TIME seconds.*/
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         /*If the entry is still in the DELAY state when the timer expires, the
00459         entry's state changes to PROBE. If reachability confirmation is received,
00460         the entry's state changes to REACHABLE.*/
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     /*If no response is received after waiting RetransTimer milliseconds
00468     after sending the MAX_UNICAST_SOLICIT solicitations, retransmissions cease
00469     and the entry SHOULD be deleted. Subsequent traffic to that neighbor will
00470     recreate the entry and performs address resolution again.*/
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     /*Upon entering the PROBE state, a node sends a unicast Neighbor Solicitation
00480     message to the neighbor using the cached link-layer address.*/
00481     createAndSendNSPacket(nceKey->address, nceKey->address,
00482         ie->ipv6Data()->getPreferredAddress(), ie);
00483     nce->numProbesSent++;
00484     /*While in the PROBE state, a node retransmits Neighbor Solicitation messages
00485     every RetransTimer milliseconds until reachability confirmation is obtained.
00486     Probes are retransmitted even if no additional packets are sent to the
00487     neighbor.*/
00488     scheduleAt(simTime()+ie->ipv6Data()->_getRetransTimer(), timeoutMsg);
00489 }
00490 
00491 IPv6Address IPv6NeighbourDiscovery::selectDefaultRouter(int& outIfID)
00492 {
00493     EV << "Selecting default router...\n";
00494     //draft-ietf-ipv6-2461bis-04.txt Section 6.3.6
00495     /*The algorithm for selecting a router depends in part on whether or not a
00496     router is known to be reachable. The exact details of how a node keeps track
00497     of a neighbor's reachability state are covered in Section 7.3.  The algorithm
00498     for selecting a default router is invoked during next-hop determination when
00499     no Destination Cache entry exists for an off-link destination or when
00500     communication through an existing router appears to be failing.  Under normal
00501     conditions, a router would be selected the first time traffic is sent to a
00502     destination, with subsequent traffic for that destination using the same router
00503     as indicated in the Destination Cache modulo any changes to the Destination
00504     Cache caused by Redirect messages.
00505 
00506     The policy for selecting routers from the Default Router List is as
00507     follows:*/
00508 
00509     IPv6Address routerAddr;
00510     //Cycle through all entries in the neighbour cache entry.
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)//TODO: Need to improve this algorithm!
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     /*1) Routers that are reachable or probably reachable (i.e., in any state
00541     other than INCOMPLETE) SHOULD be preferred over routers whose reachability
00542     is unknown or suspect (i.e., in the INCOMPLETE state, or for which no Neighbor
00543     Cache entry exists). An implementation may choose to always return the same
00544     router or cycle through the router list in a round-robin fashion as long as
00545     it always returns a reachable or a probably reachable router when one is
00546     available.*/
00547 
00548     /*2) When no routers on the list are known to be reachable or probably
00549     reachable, routers SHOULD be selected in a round-robin fashion, so that
00550     subsequent requests for a default router do not return the same router until
00551     all other routers have been selected.
00552 
00553     Cycling through the router list in this case ensures that all available
00554     routers are actively probed by the Neighbor Unreachability Detection algorithm.
00555     A request for a default router is made in conjunction with the sending of a
00556     packet to a router, and the selected router will be probed for reachability
00557     as a side effect.*/
00558 
00559     outIfID = -1;//nothing found yet
00560     return IPv6Address();
00561 }
00562 
00563 void IPv6NeighbourDiscovery::timeoutPrefixEntry(const IPv6Address& destPrefix,
00564     int prefixLength)//REDUNDANT
00565 {
00566     //RFC 2461: Section 6.3.5
00567     /*Whenever the invalidation timer expires for a Prefix List entry, that
00568     entry is discarded.*/
00569     rt6->removeOnLinkPrefix(destPrefix, prefixLength);
00570     //hmmm... should the unicast address associated with this prefix be deleted
00571     //as well?-TODO: The address should be timeout/deleted as well!!
00572 
00573     /*No existing Destination Cache entries need be updated, however. Should a
00574     reachability problem arise with an existing Neighbor Cache entry, Neighbor
00575     Unreachability Detection will perform any needed recovery.*/
00576 }
00577 
00578 void IPv6NeighbourDiscovery::timeoutDefaultRouter(const IPv6Address& addr,
00579     int interfaceID)
00580 {
00581     //RFC 2461: Section 6.3.5
00582     /*Whenever the Lifetime of an entry in the Default Router List expires,
00583     that entry is discarded.*/
00584     neighbourCache.remove(addr, interfaceID);
00585 
00586     /*When removing a router from the Default Router list, the node MUST update
00587     the Destination Cache in such a way that all entries using the router perform
00588     next-hop determination again rather than continue sending traffic to the
00589     (deleted) router.*/
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     //RFC2461: Section 7.2.2
00602     //When a node has a unicast packet to send to a neighbor, but does not
00603     //know the neighbor's link-layer address, it performs address
00604     //resolution.  For multicast-capable interfaces this entails creating a
00605     //Neighbor Cache entry in the INCOMPLETE state(already created if not done yet)
00606     //WEI-If entry already exists, we still have to ensure that its state is INCOMPLETE.
00607     nce->reachabilityState = IPv6NeighbourCache::INCOMPLETE;
00608 
00609     //and transmitting a Neighbor Solicitation message targeted at the
00610     //neighbor.  The solicitation is sent to the solicited-node multicast
00611     //address "corresponding to"(or "derived from") the target address.
00612     //(in this case, the target address is the address we are trying to resolve)
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();//for NS datagram
00616     IPv6Address nsTargetAddr = neighbourAddr;//for the field within the NS
00617     IPv6Address nsSrcAddr;
00618 
00619     /*If the source address of the packet prompting the solicitation is the
00620     same as one of the addresses assigned to the outgoing interface,*/
00621     if (ie->ipv6Data()->hasAddress(dgSrcAddr))
00622         /*that address SHOULD be placed in the IP Source Address of the outgoing
00623         solicitation.*/
00624         nsSrcAddr = dgSrcAddr;
00625     else
00626         /*Otherwise, any one of the addresses assigned to the interface
00627         should be used.*/
00628         nsSrcAddr = ie->ipv6Data()->getPreferredAddress();
00629     ASSERT(ifID != -1);
00630     //Sending NS on specified interface.
00631     createAndSendNSPacket(nsTargetAddr, nsDestAddr, nsSrcAddr, ie);
00632     nce->numOfARNSSent = 1;
00633     nce->nsSrcAddr = nsSrcAddr;
00634 
00635     /*While awaiting a response, the sender SHOULD retransmit Neighbor Solicitation
00636     messages approximately every RetransTimer milliseconds, even in the absence
00637     of additional traffic to the neighbor. Retransmissions MUST be rate-limited
00638     to at most one solicitation per neighbor every RetransTimer milliseconds.*/
00639     cMessage *msg = new cMessage("arTimeout", MK_AR_TIMEOUT);//AR msg timer
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     //AR timeouts are cancelled when a valid solicited NA is received.
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     //RFC 2461: Section 7.2.2
00674     /*If no Neighbor Advertisement is received after MAX_MULTICAST_SOLICIT
00675     solicitations, address resolution has failed. The sender MUST return ICMP
00676     destination unreachable indications with code 3 (Address Unreachable) for
00677     each packet queued awaiting address resolution.*/
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         //Assume msg is the packet itself. I need the datagram's source addr.
00686         //The datagram's src addr will be the destination of the unreachable msg.
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     //RFC 2461: Section 7.3.3
00694     /*If address resolution fails, the entry SHOULD be deleted, so that subsequent
00695     traffic to that neighbor invokes the next-hop determination procedure again.*/
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())//FIXME: pendingPackets are always 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     //Node has booted up. Start assigning a link-local address for each
00733     //interface in this node.
00734     for (int i=0; i < ift->getNumInterfaces(); i++)
00735     {
00736         InterfaceEntry *ie = ift->getInterface(i);
00737 
00738         //Skip the loopback interface.
00739         if (ie->isLoopback()) continue;
00740 
00741         IPv6Address linkLocalAddr = ie->ipv6Data()->getLinkLocalAddress();
00742         if (linkLocalAddr.isUnspecified())
00743         {
00744             //if no link local address exists for this interface, we assign one to it.
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         //Before we can use this address, we MUST initiate DAD first.
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     RFC2462: Section 5.4.2
00766     To check an address, a node sends DupAddrDetectTransmits Neighbor
00767     Solicitations, each separated by RetransTimer milliseconds. The
00768     solicitation's Target Address is set to the address being checked,
00769     the IP source is set to the unspecified address and the IP
00770     destination is set to the solicited-node multicast address of the
00771     target address.*/
00772     IPv6Address destAddr = tentativeAddr.formSolicitedNodeMulticastAddress();
00773     //Send a NS
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     //Here, we need to check how many DAD messages for the interface entry were
00789     //sent vs. DupAddrDetectTransmits
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         //Reuse the received msg
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         /*RFC 2461: Section 6.3.7 2nd Paragraph
00810         Before a host sends an initial solicitation, it SHOULD delay the
00811         transmission for a random amount of time between 0 and
00812         MAX_RTR_SOLICITATION_DELAY.  This serves to alleviate congestion when
00813         many hosts start up on a link at the same time, such as might happen
00814         after recovery from a power failure.*/
00815         //TODO: Placing these operations here means fast router solicitation is
00816         //not adopted. Will relocate.
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()); // random delay
00823             scheduleAt(simTime()+interval, rtrDisMsg);
00824         }
00825     }
00826 }
00827 
00828 IPv6RouterSolicitation *IPv6NeighbourDiscovery::createAndSendRSPacket(InterfaceEntry *ie)
00829 {
00830     ASSERT(ie->ipv6Data()->getAdvSendAdvertisements() == false);
00831     //RFC 2461: Section 6.3.7 Sending Router Solicitations
00832     //A host sends Router Solicitations to the All-Routers multicast address. The
00833     //IP source address is set to either one of the interface's unicast addresses
00834     //or the unspecified address.
00835     IPv6Address myIPv6Address = ie->ipv6Data()->getPreferredAddress();
00836     if (myIPv6Address.isUnspecified())
00837         myIPv6Address = ie->ipv6Data()->getLinkLocalAddress();//so we use the link local address instead
00838     if (ie->ipv6Data()->isTentativeAddress(myIPv6Address))
00839         myIPv6Address = IPv6Address::UNSPECIFIED_ADDRESS;//set my IPv6 address to unspecified.
00840     IPv6Address destAddr = IPv6Address::ALL_ROUTERS_2;//all_routers multicast
00841     IPv6RouterSolicitation *rs = new IPv6RouterSolicitation("RSpacket");
00842     rs->setType(ICMPv6_ROUTER_SOL);
00843 
00844     //The Source Link-Layer Address option SHOULD be set to the host's link-layer
00845     //address, if the IP source address is not the unspecified address.
00846     if (!myIPv6Address.isUnspecified())
00847         rs->setSourceLinkLayerAddress(ie->getMacAddress());
00848 
00849     //Construct a Router Solicitation message
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     //RFC2461: Section 6.3.7
00860     /*When an interface becomes enabled, a host may be unwilling to wait for the
00861     next unsolicited Router Advertisement to locate default routers or learn
00862     prefixes.  To obtain Router Advertisements quickly, a host SHOULD transmit up
00863     to MAX_RTR_SOLICITATIONS Router Solicitation messages each separated by at
00864     least RTR_SOLICITATION_INTERVAL seconds.(FIXME:Therefore this should be invoked
00865     at the beginning of the simulation-WEI)*/
00866     RDEntry *rdEntry = new RDEntry();
00867     rdEntry->interfaceId = ie->getInterfaceId();
00868     rdEntry->numRSSent = 0;
00869     createAndSendRSPacket(ie);
00870     rdEntry->numRSSent++;
00871 
00872     //Create and schedule a message for retransmission to this module
00873     cMessage *rdTimeoutMsg = new cMessage("processRDTimeout", MK_RD_TIMEOUT);
00874     rdTimeoutMsg->setContextPointer(ie);
00875     rdEntry->timeoutMsg = rdTimeoutMsg;
00876     rdList.insert(rdEntry);
00877     /*Before a host sends an initial solicitation, it SHOULD delay the
00878     transmission for a random amount of time between 0 and
00879     MAX_RTR_SOLICITATION_DELAY.  This serves to alleviate congestion when
00880     many hosts start up on a link at the same time, such as might happen
00881     after recovery from a power failure.  If a host has already performed
00882     a random delay since the interface became (re)enabled (e.g., as part
00883     of Duplicate Address Detection [ADDRCONF]) there is no need to delay
00884     again before sending the first Router Solicitation message.*/
00885     //simtime_t rndInterval = uniform(0, ie->ipv6Data()->_getMaxRtrSolicitationDelay());
00886     scheduleAt(simTime()+ie->ipv6Data()->_getRtrSolicitationInterval(), rdTimeoutMsg);
00887 }
00888 
00889 void IPv6NeighbourDiscovery::cancelRouterDiscovery(InterfaceEntry *ie)
00890 {
00891     //Next we retrieve the rdEntry with the Interface Entry.
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         //Need to find out if this is the last RS we are sending out.
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         //RFC 2461, Section 6.3.7
00922         /*If a host sends MAX_RTR_SOLICITATIONS solicitations, and receives no Router
00923         Advertisements after having waited MAX_RTR_SOLICITATION_DELAY seconds after
00924         sending the last solicitation, the host concludes that there are no routers
00925         on the link for the purpose of [ADDRCONF]. However, the host continues to
00926         receive and process Router Advertisements messages in the event that routers
00927         appear on the link.*/
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     //Find out which interface the RS message arrived on.
00940     InterfaceEntry *ie = ift->getInterfaceById(rsCtrlInfo->getInterfaceId());
00941     AdvIfEntry *advIfEntry = fetchAdvIfEntry(ie);//fetch advertising interface entry.
00942 
00943     //RFC 2461: Section 6.2.6
00944     //A host MUST silently discard any received Router Solicitation messages.
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         //First we extract RS specific information from the received message
00953         MACAddress macAddr = rs->getSourceLinkLayerAddress();
00954         EV << "MAC Address extracted\n";
00955         delete rs;
00956 
00957         /*A router MAY choose to unicast the response directly to the soliciting
00958         host's address (if the solicitation's source address is not the unspecified
00959         address), but the usual case is to multicast the response to the
00960         all-nodes group. In the latter case, the interface's interval timer is
00961         reset to a new random value, as if an unsolicited advertisement had just
00962         been sent(see Section 6.2.4).*/
00963 
00964         /*In all cases, Router Advertisements sent in response to a Router
00965         Solicitation MUST be delayed by a random time between 0 and
00966         MAX_RA_DELAY_TIME seconds. (If a single advertisement is sent in
00967         response to multiple solicitations, the delay is relative to the
00968         first solicitation.)  In addition, consecutive Router Advertisements
00969         sent to the all-nodes multicast address MUST be rate limited to no
00970         more than one advertisement every MIN_DELAY_BETWEEN_RAS seconds.*/
00971 
00972         /*A router might process Router Solicitations as follows:
00973         - Upon receipt of a Router Solicitation, compute a random delay
00974         within the range 0 through MAX_RA_DELAY_TIME. If the computed
00975         value corresponds to a time later than the time the next multicast
00976         Router Advertisement is scheduled to be sent, ignore the random
00977         delay and send the advertisement at the already-scheduled time.*/
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         //else we ignore the generate interval and send it at the next scheduled time.
00990 
00991         //We need to keep a log here each time an RA is sent. Not implemented yet.
00992         //Assume the first course of action.
00993         /*- If the router sent a multicast Router Advertisement (solicited or
00994         unsolicited) within the last MIN_DELAY_BETWEEN_RAS seconds,
00995         schedule the advertisement to be sent at a time corresponding to
00996         MIN_DELAY_BETWEEN_RAS plus the random value after the previous
00997         advertisement was sent. This ensures that the multicast Router
00998         Advertisements are rate limited.
00999 
01000         - Otherwise, schedule the sending of a Router Advertisement at the
01001         time given by the random value.*/
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     /*6.1.1.  Validation of Router Solicitation Messages
01015     A router MUST silently discard any received Router Solicitation
01016     messages that do not satisfy all of the following validity checks:
01017 
01018     - The IP Hop Limit field has a value of 255, i.e., the packet
01019     could not possibly have been forwarded by a router.*/
01020     if (rsCtrlInfo->getHopLimit() != 255)
01021     {
01022         EV << "Hop limit is not 255! RS validation failed!\n";
01023         result = false;
01024     }
01025     //- ICMP Code is 0.
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     //- If the IP source address is the unspecified address, there is no
01032     //source link-layer address option in the message.
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     //Must use link-local addr. See: RFC2461 Section 6.1.2
01049     IPv6Address sourceAddr = ie->ipv6Data()->getLinkLocalAddress();
01050 
01051     //This operation includes all options, regardless whether it is solicited or unsolicited.
01052     if (ie->ipv6Data()->getAdvSendAdvertisements()) //if this is an advertising interface
01053     {
01054         //Construct a Router Advertisment message
01055         IPv6RouterAdvertisement *ra = new IPv6RouterAdvertisement("RApacket");
01056         ra->setType(ICMPv6_ROUTER_AD);
01057 
01058         //RFC 2461: Section 6.2.3 Router Advertisment Message Content
01059         /*A router sends periodic as well as solicited Router Advertisements out
01060         its advertising interfaces.  Outgoing Router Advertisements are filled
01061         with the following values consistent with the message format given in
01062         Section 4.2:*/
01063 
01064         //- In the Router Lifetime field: the interface's configured AdvDefaultLifetime.
01065         ra->setRouterLifetime(SIMTIME_DBL(ie->ipv6Data()->getAdvDefaultLifetime()));
01066 
01067         //- In the M and O flags: the interface's configured AdvManagedFlag and
01068         //AdvOtherConfigFlag, respectively.  See [ADDRCONF].
01069         ra->setManagedAddrConfFlag(ie->ipv6Data()->getAdvManagedFlag());
01070         ra->setOtherStatefulConfFlag(ie->ipv6Data()->getAdvOtherConfigFlag());
01071 
01072         //- In the Cur Hop Limit field: the interface's configured CurHopLimit.
01073         ra->setCurHopLimit(ie->ipv6Data()->getAdvCurHopLimit());
01074 
01075         //- In the Reachable Time field: the interface's configured AdvReachableTime.
01076         ra->setReachableTime(ie->ipv6Data()->getAdvReachableTime());
01077 
01078         //- In the Retrans Timer field: the interface's configured AdvRetransTimer.
01079         ra->setRetransTimer(ie->ipv6Data()->getAdvRetransTimer());
01080 
01081         //- In the options:
01082         /*o Source Link-Layer Address option: link-layer address of the sending
01083             interface.  (Assumption: We always send this)*/
01084         ra->setSourceLinkLayerAddress(ie->getMacAddress());
01085         ra->setMTU(ie->ipv6Data()->getAdvLinkMTU());
01086 
01087         //Add all Advertising Prefixes to the RA
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             //- In the "on-link" flag: the entry's AdvOnLinkFlag.
01099             prefixInfo.setOnlinkFlag(advPrefix.advOnLinkFlag);
01100             //- In the Valid Lifetime field: the entry's AdvValidLifetime.
01101             prefixInfo.setValidLifetime(SIMTIME_DBL(advPrefix.advValidLifetime));
01102             //- In the "Autonomous address configuration" flag: the entry's
01103             //AdvAutonomousFlag.
01104             prefixInfo.setAutoAddressConfFlag(advPrefix.advAutonomousFlag);
01105             //- In the Preferred Lifetime field: the entry's AdvPreferredLifetime.
01106             prefixInfo.setPreferredLifetime(SIMTIME_DBL(advPrefix.advPreferredLifetime));
01107             //Now we pop the prefix info into the RA.
01108             ra->setPrefixInformation(i, prefixInfo);
01109         }
01110         sendPacketToIPv6Module(ra, destAddr, sourceAddr, ie->getInterfaceId());
01111         return ra;
01112     }
01113     return NULL; //XXX is this OK?
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);//Cancel router discovery if it is in progress.
01135         EV << "Interface is a host, processing RA.\n";
01136 
01137         processRAForRouterUpdates(ra, raCtrlInfo);//See RFC2461: Section 6.3.4
01138 
01139         //Possible options
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)//If auto addr conf is set
01146                 processRAPrefixInfoForAddrAutoConf(prefixInfo, ie);//We process prefix Info and form an addr
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     //RFC2461: Section 6.3.4
01158     //Paragraphs 1 and 2 omitted.
01159 
01160     //On receipt of a valid Router Advertisement, a host extracts the source
01161     //address of the packet and does the following:
01162     IPv6Address raSrcAddr = raCtrlInfo->getSrcAddr();
01163     InterfaceEntry *ie = ift->getInterfaceById(raCtrlInfo->getInterfaceId());
01164     int ifID = ie->getInterfaceId();
01165 
01166     /*- If the address is not already present in the host's Default Router List,
01167     and the advertisement's Router Lifetime is non-zero, create a new entry in
01168     the list, and initialize its invalidation timer value from the advertisement's
01169     Router Lifetime field.*/
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             //If a Neighbor Cache entry is created for the router its reachability
01179             //state MUST be set to STALE as specified in Section 7.3.3.
01180             if (ra->getSourceLinkLayerAddress().isUnspecified())
01181             {
01182                 neighbour = neighbourCache.addRouter(raSrcAddr, ifID,
01183                     simTime()+ra->getRouterLifetime());
01184                 //Note:invalidation timers are not explicitly defined.
01185             }
01186             else
01187             {
01188                 neighbour = neighbourCache.addRouter(raSrcAddr, ifID,
01189                     ra->getSourceLinkLayerAddress(), simTime()+ra->getRouterLifetime());
01190                 //According to Greg, we should add a default route for hosts as well!
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             //WEI-The router is advertising itself, BUT not as a default router.
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         //If no Source Link-Layer Address is included, but a corresponding Neighbor
01209         //Cache entry exists, its IsRouter flag MUST be set to TRUE.
01210         neighbour->isRouter = true;
01211 
01212         //If a cache entry already exists and is updated with a different link-
01213         //layer address the reachability state MUST also be set to STALE.
01214         if (ra->getSourceLinkLayerAddress().isUnspecified() == false &&
01215             neighbour->macAddress.equals(ra->getSourceLinkLayerAddress()) == false)
01216             neighbour->macAddress = ra->getSourceLinkLayerAddress();
01217 
01218         /*- If the address is already present in the host's Default Router List
01219         as a result of a previously-received advertisement, reset its invalidation
01220         timer to the Router Lifetime value in the newly-received advertisement.*/
01221         neighbour->routerExpiryTime = simTime()+ra->getRouterLifetime();
01222 
01223         /*- If the address is already present in the host's Default Router List
01224         and the received Router Lifetime value is zero, immediately time-out the
01225         entry as specified in Section 6.3.5.*/
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     //Paragraph Omitted.
01234 
01235     //If the received Cur Hop Limit value is non-zero the host SHOULD set
01236     //its CurHopLimit variable to the received value.
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     //If the received Reachable Time value is non-zero the host SHOULD set its
01245     //BaseReachableTime variable to the received value.
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             //If the new value differs from the previous value, the host SHOULD
01255             //recompute a new random ReachableTime value.
01256             ie->ipv6Data()->setReachableTime(ie->ipv6Data()->generateReachableTime());
01257         }
01258         EV << endl;
01259     }
01260 
01261     //The RetransTimer variable SHOULD be copied from the Retrans Timer field,
01262     //if the received value is non-zero.
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     /*If the MTU option is present, hosts SHOULD copy the option's value into
01270     LinkMTU so long as the value is greater than or equal to the minimum link MTU
01271     [IPv6] and does not exceed the default LinkMTU value specified in the link
01272     type specific document (e.g., [IPv6-ETHER]).*/
01273     //TODO: not done yet
01274 
01275     processRAPrefixInfo(ra, ie);
01276 }
01277 
01278 void IPv6NeighbourDiscovery::processRAPrefixInfo(IPv6RouterAdvertisement *ra,
01279     InterfaceEntry *ie)
01280 {
01281     //Continued from section 6.3.4
01282     /*Prefix Information options that have the "on-link" (L) flag set indicate a
01283     prefix identifying a range of addresses that should be considered on-link.
01284     Note, however, that a Prefix Information option with the on-link flag set to
01285     zero conveys no information concerning on-link determination and MUST NOT be
01286     interpreted to mean that addresses covered by the prefix are off-link. The
01287     only way to cancel a previous on-link indication is to advertise that prefix
01288     with the L-bit set and the Lifetime set to zero. The default behavior (see
01289     Section 5.2) when sending a packet to an address for which no information is
01290     known about the on-link status of the address is to forward the packet to a
01291     default router; the reception of a Prefix Information option with the "on-link "
01292     (L) flag set to zero does not change this behavior. The reasons for an address
01293     being treated as on-link is specified in the definition of "on-link" in
01294     Section 2.1. Prefixes with the on-link flag set to zero would normally have
01295     the autonomous flag set and be used by [ADDRCONF].*/
01296     IPv6NDPrefixInformation prefixInfo;
01297     //For each Prefix Information option
01298     for (int i = 0; i < (int)ra->getPrefixInformationArraySize(); i++)
01299     {
01300         prefixInfo = ra->getPrefixInformation(i);
01301         if (!prefixInfo.getOnlinkFlag()) break;//skip to next prefix option
01302 
01303         //with the on-link flag set, a host does the following:
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         //- If the prefix is the link-local prefix, silently ignore the Prefix
01312         //Information option.
01313         if (prefix.isLinkLocal())
01314         {
01315             EV << "Prefix is link-local, ignoring prefix.\n";
01316             return;
01317         }
01318 
01319         //- If the prefix is not already present in the Prefix List,
01320         if (!rt6->isPrefixPresent(prefix)) {
01321             //and the Prefix Information option's Valid Lifetime field is non-zero,
01322             if (validLifetime != 0)
01323             {
01324                 /*create a new entry for the prefix and initialize its invalidation
01325                 timer to the Valid Lifetime value in the Prefix Information option.*/
01326                 rt6->addOrUpdateOnLinkPrefix(prefix, prefixLength, ie->getInterfaceId(),
01327                     simTime()+validLifetime);
01328             }
01329             /*- If the Prefix Information option's Valid Lifetime field is zero,
01330             and the prefix is not present in the host's Prefix List,
01331             silently ignore the option.*/
01332         }
01333         else
01334         {
01335             /* If the new Lifetime value is zero, time-out the prefix immediately
01336             (see Section 6.3.5).*/
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             /*- If the prefix is already present in the host's Prefix List as
01344             the result of a previously-received advertisement, reset its
01345             invalidation timer to the Valid Lifetime value in the Prefix
01346             Information option.*/
01347             rt6->addOrUpdateOnLinkPrefix(prefix, prefixLength, ie->getInterfaceId(),
01348                 simTime()+validLifetime);
01349         }
01350 
01351         /*Stateless address autoconfiguration [ADDRCONF] may in some
01352         circumstances increase the Valid Lifetime of a prefix or ignore it
01353         completely in order to prevent a particular denial of service attack.
01354         However, since the effect of the same denial of service targeted at
01355         the on-link prefix list is not catastrophic (hosts would send packets
01356         to a default router and receive a redirect rather than sending
01357         packets directly to a neighbor) the Neighbor Discovery protocol does
01358         not impose such a check on the prefix lifetime values.*/
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     //RFC 2461: Section 5.5.3
01372     //First condition tested, the autonomous flag is already set
01373 
01374     //b) If the prefix is the link-local prefix, silently ignore the Prefix
01375     //Information option.
01376     if (prefixInfo.getPrefix().isLinkLocal() == true)
01377     {
01378         EV << "Prefix is link-local, ignore Prefix Information Option\n";
01379         return;
01380     }
01381 
01382     //c) If the preferred lifetime is greater than the valid lifetime, silently
01383     //ignore the Prefix Information option. A node MAY wish to log a system
01384     //management error in this case.
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     /*d) If the prefix advertised does not match the prefix of an address already
01398          in the list, and the Valid Lifetime is not 0, form an address (and add
01399          it to the list) by combining the advertised prefix with the link’s
01400          interface identifier as follows:*/
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         //TODO: for now we leave the newly formed address as not tentative,
01407         //according to Greg, we have to always perform DAD for a newly formed address.
01408         EV << "Assigning new address to: " << ie->getName() << endl;
01409         ie->ipv6Data()->assignAddress(newAddr, false, simTime()+validLifetime,
01410             simTime()+preferredLifetime);
01411     }
01412 
01413     //TODO: this is the simplified version.
01414     /*e) If the advertised prefix matches the prefix of an autoconfigured
01415        address (i.e., one obtained via stateless or stateful address
01416        autoconfiguration) in the list of addresses associated with the
01417        interface, the specific action to perform depends on the Valid
01418        Lifetime in the received advertisement and the Lifetime
01419        associated with the previously autoconfigured address (which we
01420        call StoredLifetime in the discussion that follows):
01421 
01422        1) If the received Lifetime is greater than 2 hours or greater
01423           than StoredLifetime, update the stored Lifetime of the
01424           corresponding address.
01425 
01426        2) If the StoredLifetime is less than or equal to 2 hours and the
01427           received Lifetime is less than or equal to StoredLifetime,
01428           ignore the prefix, unless the Router Advertisement from which
01429 
01430           this Prefix Information option was obtained has been
01431           authenticated (e.g., via IPSec [RFC2402]). If the Router
01432           Advertisment was authenticated, the StoredLifetime should be
01433           set to the Lifetime in the received option.
01434 
01435        3) Otherwise, reset the stored Lifetime in the corresponding
01436           address to two hours.*/
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     //now we schedule the msg for whatever time that was derived
01456     scheduleAt(nextScheduledTime, msg);
01457 }
01458 
01459 void IPv6NeighbourDiscovery::resetRATimer(InterfaceEntry *ie)
01460 {//Not used yet but could be useful later on.-WEI
01461     //Iterate through all RA timers within the Neighbour Discovery module.
01462 /*
01463     for (RATimerList::iterator it=raTimerList.begin(); it != raTimerList.end(); it++)
01464     {
01465         cMessage *msg = (*it);
01466         InterfaceEntry *msgIE = (InterfaceEntry *)msg->getContextPointer();
01467         //Find the timer that matches the given Interface Entry.
01468         if (msgIE->outputPort() == ie->outputPort())
01469         {
01470             EV << "Resetting RA timer for port: " << ie->outputPort();
01471             cancelEvent(msg);//Cancel the next scheduled msg.
01472             simtime_t interval
01473                 = uniform(ie->ipv6Data()->getMinRtrAdvInterval(),ie->ipv6Data()->getMaxRtrAdvInterval());
01474             scheduleAt(simTime()+interval, msg);
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     //RFC 2461, Section 6.2.4
01490     /*Whenever a multicast advertisement is sent from an interface, the timer is
01491     reset to a uniformly-distributed random value between the interface's
01492     configured MinRtrAdvInterval and MaxRtrAdvInterval; expiration of the timer
01493     causes the next advertisement to be sent and a new random value to be chosen.*/
01494     simtime_t interval = uniform(ie->ipv6Data()->getMinRtrAdvInterval(), ie->ipv6Data()->getMaxRtrAdvInterval());
01495     nextScheduledTime = simTime() + interval;
01496 
01497     /*For the first few advertisements (up to MAX_INITIAL_RTR_ADVERTISEMENTS)
01498     sent from an interface when it becomes an advertising interface,*/
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             //if the randomly chosen interval is greater than MAX_INITIAL_RTR_ADVERT_INTERVAL,
01506             //the timer SHOULD be set to MAX_INITIAL_RTR_ADVERT_INTERVAL instead.
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     //RFC 2461: Section 6.1.2 Validation of Router Advertisement Messages
01535     /*A node MUST silently discard any received Router Advertisement
01536     messages that do not satisfy all of the following validity checks:*/
01537     raCtrlInfo->getSrcAddr();
01538     //- IP Source Address is a link-local address.  Routers must use
01539     //  their link-local address as the source for Router Advertisement
01540     //  and Redirect messages so that hosts can uniquely identify
01541     //  routers.
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     //- The IP Hop Limit field has a value of 255, i.e., the packet
01549     //  could not possibly have been forwarded by a router.
01550     if (raCtrlInfo->getHopLimit() != 255)
01551     {
01552         EV << "Hop limit is not 255! RA validation failed!\n";
01553         result = false;
01554     }
01555 
01556     //- ICMP Code is 0.
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     //Construct a Neighbour Solicitation message
01573     IPv6NeighbourSolicitation *ns = new IPv6NeighbourSolicitation("NSpacket");
01574     ns->setType(ICMPv6_NEIGHBOUR_SOL);
01575 
01576     //Neighbour Solicitation Specific Information
01577     ns->setTargetAddress(nsTargetAddr);
01578 
01579     /*If the solicitation is being sent to a solicited-node multicast
01580     address, the sender MUST include its link-layer address (if it has
01581     one) as a Source Link-Layer Address option.*/
01582     if (dgDestAddr.matches(IPv6Address("FF02::1:FF00:0"),104) && // FIXME what's this? make constant...
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     //Control Information
01595     InterfaceEntry *ie = ift->getInterfaceById(nsCtrlInfo->getInterfaceId());
01596 
01597     IPv6Address nsTargetAddr = ns->getTargetAddress();
01598 
01599     //RFC 2461:Section 7.2.3
01600     //If target address is not a valid "unicast" or anycast address assigned to the
01601     //receiving interface, we should silently discard the packet.
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         //If the Target Address is tentative, the Neighbor Solicitation should
01614         //be processed as described in [ADDRCONF].
01615         EV << "Process NS for Tentative target address.\n";
01616         processNSForTentativeAddress(ns, nsCtrlInfo);
01617     }
01618     else
01619     {
01620         //Otherwise, the following description applies.
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     /*RFC 2461:7.1.1. Validation of Neighbor Solicitations(some checks are omitted)
01633     A node MUST silently discard any received Neighbor Solicitation
01634     messages that do not satisfy all of the following validity checks:*/
01635     //- The IP Hop Limit field has a value of 255, i.e., the packet
01636     //could not possibly have been forwarded by a router.
01637     if (nsCtrlInfo->getHopLimit() != 255)
01638     {
01639         EV << "Hop limit is not 255! NS validation failed!\n";
01640         result = false;
01641     }
01642     //- Target Address is not a multicast address.
01643     if (ns->getTargetAddress().isMulticast() == true)
01644     {
01645         EV << "Target address is a multicast address! NS validation failed!\n";
01646         result = false;
01647     }
01648     //- If the IP source address is the unspecified address,
01649     if (nsCtrlInfo->getSrcAddr().isUnspecified())
01650     {
01651         EV << "Source Address is unspecified\n";
01652         //the IP destination address is a solicited-node multicast address.
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         //there is no source link-layer address option in the message.
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     //Control Information
01675     IPv6Address nsSrcAddr = nsCtrlInfo->getSrcAddr();
01676     IPv6Address nsDestAddr = nsCtrlInfo->getDestAddr();
01677 
01678     ASSERT(nsSrcAddr.isUnicast() || nsSrcAddr.isUnspecified());
01679     //solicitation is processed as described in RFC2462:section 5.4.3
01680 
01681     if (nsSrcAddr.isUnspecified())
01682     {
01683         EV << "Source Address is UNSPECIFIED. Sender is performing DAD\n";
01684         //Sender performing Duplicate Address Detection
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         //Sender performing address resolution
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     //Neighbour Solicitation Information
01703     MACAddress nsMacAddr = ns->getSourceLinkLayerAddress();
01704 
01705     int ifID = ie->getInterfaceId();
01706 
01707     //target addr is not tentative addr
01708     //solicitation processed as described in RFC2461:section 7.2.3
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     //RFC 2461, Section 7.2.3
01724     /*If the Source Address is not the unspecified address and, on link layers
01725     that have addresses, the solicitation includes a Source Link-Layer Address
01726     option, then the recipient SHOULD create or update the Neighbor Cache entry
01727     for the IP Source Address of the solicitation.*/
01728 
01729     //Neighbour Solicitation Information
01730     MACAddress nsMacAddr = ns->getSourceLinkLayerAddress();
01731 
01732     int ifID = ie->getInterfaceId();
01733 
01734     //Look for the Neighbour Cache Entry
01735     Neighbour *entry = neighbourCache.lookup(nsCtrlInfo->getSrcAddr(), ifID);
01736 
01737     if (entry == NULL)
01738     {
01739         /*If an entry does not already exist, the node SHOULD create a new one
01740         and set its reachability state to STALE as specified in Section 7.3.3.*/
01741         EV << "Neighbour Entry not found. Create a Neighbour Cache Entry.\n";
01742         neighbourCache.addNeighbour(nsCtrlInfo->getSrcAddr(), ifID, nsMacAddr);
01743     }
01744     else
01745     {
01746         /*If an entry already exists, and the cached link-layer address differs from
01747         the one in the received Source Link-Layer option,*/
01748         if (!(entry->macAddress.equals(nsMacAddr)) && !nsMacAddr.isUnspecified())
01749         {
01750             //the cached address should be replaced by the received address
01751             entry->macAddress = nsMacAddr;
01752             //and the entry's reachability state MUST be set to STALE.
01753             entry->reachabilityState = IPv6NeighbourCache::STALE;
01754         }
01755     }
01756     /*After any updates to the Neighbor Cache, the node sends a Neighbor
01757     Advertisement response as described in the next section.*/
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     //RFC 2461: Section 7.2.4
01766     /*A node sends a Neighbor Advertisement in response to a valid Neighbor
01767     Solicitation targeting one of the node's assigned addresses.  The
01768     Target Address of the advertisement is copied from the Target Address
01769     of the solicitation.*/
01770     na->setTargetAddress(ns->getTargetAddress());
01771 
01772     /*If the solicitation's IP Destination Address is not a multicast address,
01773     the Target Link-Layer Address option MAY be omitted; the neighboring node's
01774     cached value must already be current in order for the solicitation to have
01775     been received. If the solicitation's IP Destination Address is a multicast
01776     address, the Target Link-Layer option MUST be included in the advertisement.*/
01777     na->setTargetLinkLayerAddress(ie->getMacAddress());//here, we always include the MAC addr.
01778 
01779     /*Furthermore, if the node is a router, it MUST set the Router flag to one;
01780     otherwise it MUST set the flag to zero.*/
01781     na->setRouterFlag(rt6->isRouter());
01782 
01783     /*If the (NS)Target Address is either an anycast address or a unicast
01784     address for which the node is providing proxy service, or the Target
01785     Link-Layer Address option is not included,*/
01786     //TODO:ANYCAST will not be implemented here!
01787     if (ns->getSourceLinkLayerAddress().isUnspecified())
01788         //the Override flag SHOULD be set to zero.
01789         na->setOverrideFlag(false);
01790     else
01791         //Otherwise, the Override flag SHOULD be set to one.
01792         na->setOverrideFlag(true);
01793     /*Proper setting of the Override flag ensures that nodes give preference to
01794     non-proxy advertisements, even when received after proxy advertisements, and
01795     also ensures that the first advertisement for an anycast address "wins".*/
01796 
01797     IPv6Address naDestAddr;
01798     //If the source of the solicitation is the unspecified address,
01799     if(nsCtrlInfo->getSrcAddr().isUnspecified())
01800     {
01801         /*the node MUST set the Solicited flag to zero and multicast the advertisement
01802         to the all-nodes address.*/
01803         na->setSolicitedFlag(false);
01804         naDestAddr = IPv6Address::ALL_NODES_2;
01805     }
01806     else
01807     {
01808         /*Otherwise, the node MUST set the Solicited flag to one and unicast
01809         the advertisement to the Source Address of the solicitation.*/
01810         na->setSolicitedFlag(true);
01811         naDestAddr = nsCtrlInfo->getSrcAddr();
01812     }
01813 
01814     /*If the Target Address is an anycast address the sender SHOULD delay sending
01815     a response for a random time between 0 and MAX_ANYCAST_DELAY_TIME seconds.*/
01816     /*TODO: More associated complexity for this one. We will have to delay
01817     sending off the solicitation. Perhaps the self message could have a context
01818     pointer pointing to a struct with enough info to create and send a NA packet.*/
01819 
01820     /*Because unicast Neighbor Solicitations are not required to include a
01821     Source Link-Layer Address, it is possible that a node sending a
01822     solicited Neighbor Advertisement does not have a corresponding link-
01823     layer address for its neighbor in its Neighbor Cache.  In such
01824     situations, a node will first have to use Neighbor Discovery to
01825     determine the link-layer address of its neighbor (i.e, send out a
01826     multicast Neighbor Solicitation).*/
01827     //TODO: if above mentioned happens, can addr resolution be performed for ND messages?
01828     //if no link-layer addr exists for unicast addr when sending solicited NA, we should
01829     //add the NA to the list of queued packets. What if we have a list of queued
01830     //packets for different unicast solicitations? each time addr resolution is
01831     //done we should check the destinations of the list of queued packets and send
01832     //off the respective ones.
01833     IPv6Address myIPv6Addr = ie->ipv6Data()->getPreferredAddress();
01834     sendPacketToIPv6Module(na, naDestAddr, myIPv6Addr, ie->getInterfaceId());
01835 }
01836 
01837 void IPv6NeighbourDiscovery::sendUnsolicitedNA(InterfaceEntry *ie)
01838 {
01839     //RFC 2461
01840     //Section 7.2.6: Sending Unsolicited Neighbor Advertisements
01841 
01842     /*In some cases a node may be able to determine that its link-layer
01843     address has changed (e.g., hot-swap of an interface card) and may
01844     wish to inform its neighbors of the new link-layer address quickly.
01845     In such cases a node MAY send up to MAX_NEIGHBOR_ADVERTISEMENT
01846     unsolicited Neighbor Advertisement messages to the all-nodes
01847     multicast address.  These advertisements MUST be separated by at
01848     least RetransTimer seconds.
01849 
01850     The Target Address field in the unsolicited advertisement is set to
01851     an IP address of the interface, and the Target Link-Layer Address
01852     option is filled with the new link-layer address.  The Solicited flag
01853     MUST be set to zero, in order to avoid confusing the Neighbor
01854     Unreachability Detection algorithm.  If the node is a router, it MUST
01855     set the Router flag to one; otherwise it MUST set it to zero.  The
01856     Override flag MAY be set to either zero or one.  In either case,
01857     neighboring nodes will immediately change the state of their Neighbor
01858     Cache entries for the Target Address to STALE, prompting them to
01859     verify the path for reachability.  If the Override flag is set to
01860     one, neighboring nodes will install the new link-layer address in
01861     their caches.  Otherwise, they will ignore the new link-layer
01862     address, choosing instead to probe the cached address.
01863 
01864     A node that has multiple IP addresses assigned to an interface MAY
01865     multicast a separate Neighbor Advertisement for each address.  In
01866     such a case the node SHOULD introduce a small delay between the
01867     sending of each advertisement to reduce the probability of the
01868     advertisements being lost due to congestion.
01869 
01870     A proxy MAY multicast Neighbor Advertisements when its link-layer
01871     address changes or when it is configured (by system management or
01872     other mechanisms) to proxy for an address.  If there are multiple
01873     nodes that are providing proxy services for the same set of addresses
01874     the proxies SHOULD provide a mechanism that prevents multiple proxies
01875     from multicasting advertisements for any one address, in order to
01876     reduce the risk of excessive multicast traffic.
01877 
01878     Also, a node belonging to an anycast address MAY multicast
01879     unsolicited Neighbor Advertisements for the anycast address when the
01880     node's link-layer address changes.
01881 
01882     Note that because unsolicited Neighbor Advertisements do not reliably
01883     update caches in all nodes (the advertisements might not be received
01884     by all nodes), they should only be viewed as a performance
01885     optimization to quickly update the caches in most neighbors.  The
01886     Neighbor Unreachability Detection algorithm ensures that all nodes
01887     obtain a reachable link-layer address, though the delay may be
01888     slightly longer.*/
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     //Neighbour Advertisement Information
01902     IPv6Address naTargetAddr = na->getTargetAddress();
01903 
01904     //First, we check if the target address in NA is found in the interface it
01905     //was received on is tentative.
01906     InterfaceEntry *ie = ift->getInterfaceById(naCtrlInfo->getInterfaceId());
01907     if (ie->ipv6Data()->isTentativeAddress(naTargetAddr))
01908     {
01909         error("Duplicate Address Detected! Manual attention needed!");
01910     }
01911     //Logic as defined in Section 7.2.5
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     //Target Address has entry in Neighbour Cache
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;//adopt optimistic approach
01938 
01939     //RFC 2461:7.1.2 Validation of Neighbor Advertisments(some checks are omitted)
01940     //A node MUST silently discard any received Neighbor Advertisment messages
01941     //that do not satisfy all of the following validity checks:
01942 
01943     //- The IP Hop Limit field has a value of 255, i.e., the packet
01944     //  could not possibly have been forwarded by a router.
01945     if (naCtrlInfo->getHopLimit() != 255)
01946     {
01947         EV << "Hop Limit is not 255! NA validation failed!\n";
01948         result = false;
01949     }
01950 
01951     //- Target Address is not a multicast address.
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     //- If the IP Destination Address is a multicast address the Solicited flag
01959     //  is zero.
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     /*If the target's neighbour Cache entry is in the INCOMPLETE state when the
01984     advertisement is received, one of two things happens.*/
01985     if (naMacAddr.isUnspecified())
01986     {
01987         /*If the link layer has addresses and no Target Link-Layer address option
01988         is included, the receiving node SHOULD silently discard the received
01989         advertisement.*/
01990         EV << "No MAC Address specified in NA. Ignoring NA\n";
01991         return;
01992     }
01993     else
01994     {
01995         //Otherwise, the receiving node performs the following steps:
01996         //- It records the link-layer address in the neighbour Cache entry.
01997         EV << "ND is updating Neighbour Cache Entry.\n";
01998         nce->macAddress = naMacAddr;
01999 
02000         //- If the advertisement's Solicited flag is set, the state of the
02001         //  entry is set to REACHABLE, otherwise it is set to STALE.
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         //- It sets the IsRouter flag in the cache entry based on the Router
02012         //  flag in the received advertisement.
02013         nce->isRouter = naRouterFlag;
02014 
02015         //- It sends any packets queued for the neighbour awaiting address
02016         //  resolution.
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     /*draft-ietf-ipv6-2461bis-04
02033     Section 7.2.5: Receipt of Neighbour Advertisements
02034     If the target's Neighbor Cache entry is in any state other than INCOMPLETE
02035     when the advertisement is received, the following actions take place:*/
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         //I. If the Override flag is clear and the supplied link-layer address
02042         //   differs from that in the cache, then one of two actions takes place:
02043         //(Note: An unspecified MAC should not be compared with the NCE's mac!)
02044         //a. If the state of the entry is REACHABLE,
02045         if (nce->reachabilityState == IPv6NeighbourCache::REACHABLE)
02046         {
02047             EV << "NA mac is different. Change NCE state from REACHABLE to STALE\n";
02048             //set it to STALE, but do not update the entry in any other way.
02049             nce->reachabilityState = IPv6NeighbourCache::STALE;
02050         }
02051         else
02052             //b. Otherwise, the received advertisement should be ignored and
02053             //MUST NOT update the cache.
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         /*II. If the Override flag is set, or the supplied link-layer address
02062         is the same as that in the cache, or no Target Link-layer address
02063         option was supplied, the received advertisement MUST update the
02064         Neighbor Cache entry as follows:*/
02065 
02066         /*- The link-layer address in the Target Link-Layer Address option
02067             MUST be inserted in the cache (if one is supplied and is
02068             Different than the already recorded address).*/
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         //- If the Solicited flag is set,
02077         if (naSolicitedFlag == true)
02078         {
02079             EV << "Solicited Flag is TRUE. Set NCE state to REACHABLE.\n";
02080             //the state of the entry MUST be set to REACHABLE.
02081             nce->reachabilityState = IPv6NeighbourCache::REACHABLE;
02082             //We have to cancel the NUD self timer message if there is one.
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             //If the Solicited flag is zero
02096             EV << "Solicited Flag is FALSE.\n";
02097             //and the link layer address was updated with a different address
02098             if (!(naMacAddr.equals(nce->macAddress)))
02099             {
02100                 EV << "NA's MAC is different from NCE's.Set NCE state to STALE\n";
02101                 //the state MUST be set to STALE.
02102                 nce->reachabilityState = IPv6NeighbourCache::STALE;
02103             }
02104             else
02105                 //Otherwise, the entry's state remains unchanged.
02106                 EV << "NA's MAC is the same as NCE's. State remains unchanged.\n";
02107         }
02108         //(Next paragraph with explanation is omitted.-WEI)
02109 
02110         /*- The IsRouter flag in the cache entry MUST be set based on the
02111         Router flag in the received advertisement.*/
02112         EV << "Updating NCE's router flag to " << naRouterFlag << endl;
02113         nce->isRouter = naRouterFlag;
02114 
02115         //TODO: To be implemented
02116         /*In those cases where the IsRouter flag changes from TRUE to FALSE as a
02117         result of this update, the node MUST remove that router from the Default
02118         Router List and update the Destination Cache entries for all destinations
02119         using that neighbor as a router as specified in Section 7.3.3. This is
02120         needed to detect when a node that is used as a router stops forwarding
02121         packets due to being configured as a host.*/
02122     }
02123 }
02124 
02125 IPv6Redirect *IPv6NeighbourDiscovery::createAndSendRedirectPacket(InterfaceEntry *ie)
02126 {
02127     //Construct a Redirect message
02128     IPv6Redirect *redirect = new IPv6Redirect("redirectMsg");
02129     redirect->setType(ICMPv6_REDIRECT);
02130 
02131     //Redirect Message Specific Information
02132     //redirect->setTargetAddress();
02133     //redirect->setDestinationAddress();
02134 
02135     //Possible Option
02136     //redirect->setTargetLinkLayerAddress();
02137 
02138     return redirect;
02139 }
02140 
02141 void IPv6NeighbourDiscovery::processRedirectPacket(IPv6Redirect *redirect,
02142     IPv6ControlInfo *ctrlInfo)
02143 {
02144     //First we need to extract information from the redirect message
02145     IPv6Address targetAddr = redirect->getTargetAddress();//Addressed to me
02146     IPv6Address destAddr = redirect->getDestinationAddress();//new dest addr
02147 
02148     //Optional
02149     MACAddress macAddr = redirect->getTargetLinkLayerAddress();
02150 }
02151