#include <IPv6NeighbourDiscovery.h>
This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along with this program; if not, see <http://www.gnu.org/licenses/>. Implements RFC 2461 Neighbor Discovery for IPv6.
Public Types | |
typedef std::vector< cMessage * > | MsgPtrVector |
typedef IPv6NeighbourCache::Key | Key |
typedef IPv6NeighbourCache::Neighbour | Neighbour |
Public Member Functions | |
IPv6NeighbourDiscovery () | |
virtual | ~IPv6NeighbourDiscovery () |
const MACAddress & | resolveNeighbour (const IPv6Address &nextHop, int interfaceId) |
virtual void | reachabilityConfirmed (const IPv6Address &neighbour, int interfaceId) |
Protected Types | |
typedef std::set< cMessage * > | RATimerList |
typedef std::set< DADEntry * > | DADList |
typedef std::set< RDEntry * > | RDList |
typedef std::set< AdvIfEntry * > | AdvIfList |
Protected Member Functions | |
virtual int | numInitStages () const |
virtual void | initialize (int stage) |
virtual void | handleMessage (cMessage *msg) |
virtual void | processNDMessage (ICMPv6Message *msg, IPv6ControlInfo *ctrlInfo) |
virtual void | finish () |
virtual void | processIPv6Datagram (IPv6Datagram *datagram) |
virtual IPv6NeighbourDiscovery::AdvIfEntry * | fetchAdvIfEntry (InterfaceEntry *ie) |
virtual IPv6NeighbourDiscovery::RDEntry * | fetchRDEntry (InterfaceEntry *ie) |
virtual IPv6Address | determineNextHop (const IPv6Address &destAddr, int &outIfID) |
virtual void | initiateNeighbourUnreachabilityDetection (Neighbour *neighbour) |
virtual void | processNUDTimeout (cMessage *timeoutMsg) |
virtual IPv6Address | selectDefaultRouter (int &outIfID) |
virtual void | timeoutPrefixEntry (const IPv6Address &destPrefix, int prefixLength) |
virtual void | timeoutDefaultRouter (const IPv6Address &addr, int interfaceID) |
virtual void | initiateAddressResolution (const IPv6Address &dgSrcAddr, Neighbour *nce) |
virtual void | processARTimeout (cMessage *arTimeoutMsg) |
virtual void | dropQueuedPacketsAwaitingAR (Neighbour *nce) |
virtual void | sendPacketToIPv6Module (cMessage *msg, const IPv6Address &destAddr, const IPv6Address &srcAddr, int interfaceId) |
virtual void | sendQueuedPacketsToIPv6Module (Neighbour *nce) |
virtual void | initiateDAD (const IPv6Address &tentativeAddr, InterfaceEntry *ie) |
virtual void | processDADTimeout (cMessage *msg) |
virtual void | assignLinkLocalAddress (cMessage *timerMsg) |
virtual IPv6RouterSolicitation * | createAndSendRSPacket (InterfaceEntry *ie) |
virtual void | initiateRouterDiscovery (cMessage *msg) |
virtual void | cancelRouterDiscovery (InterfaceEntry *ie) |
virtual void | processRDTimeout (cMessage *msg) |
virtual void | processRSPacket (IPv6RouterSolicitation *rs, IPv6ControlInfo *rsCtrlInfo) |
virtual bool | validateRSPacket (IPv6RouterSolicitation *rs, IPv6ControlInfo *rsCtrlInfo) |
virtual IPv6RouterAdvertisement * | createAndSendRAPacket (const IPv6Address &destAddr, InterfaceEntry *ie) |
virtual void | processRAPacket (IPv6RouterAdvertisement *ra, IPv6ControlInfo *raCtrlInfo) |
virtual void | processRAForRouterUpdates (IPv6RouterAdvertisement *ra, IPv6ControlInfo *raCtrlInfo) |
virtual void | processRAPrefixInfo (IPv6RouterAdvertisement *ra, InterfaceEntry *ie) |
virtual void | processRAPrefixInfoForAddrAutoConf (IPv6NDPrefixInformation &prefixInfo, InterfaceEntry *ie) |
virtual void | createRATimer (InterfaceEntry *ie) |
virtual void | resetRATimer (InterfaceEntry *ie) |
virtual void | sendPeriodicRA (cMessage *msg) |
virtual void | sendSolicitedRA (cMessage *msg) |
virtual bool | validateRAPacket (IPv6RouterAdvertisement *ra, IPv6ControlInfo *raCtrlInfo) |
virtual IPv6NeighbourSolicitation * | createAndSendNSPacket (const IPv6Address &nsTargetAddr, const IPv6Address &dgDestAddr, const IPv6Address &dgSrcAddr, InterfaceEntry *ie) |
virtual void | processNSPacket (IPv6NeighbourSolicitation *ns, IPv6ControlInfo *naCtrlInfo) |
virtual bool | validateNSPacket (IPv6NeighbourSolicitation *ns, IPv6ControlInfo *nsCtrlInfo) |
virtual void | processNSForTentativeAddress (IPv6NeighbourSolicitation *ns, IPv6ControlInfo *ctrlInfo) |
virtual void | processNSForNonTentativeAddress (IPv6NeighbourSolicitation *ns, IPv6ControlInfo *ctrlInfo, InterfaceEntry *ie) |
virtual void | processNSWithSpecifiedSrcAddr (IPv6NeighbourSolicitation *ns, IPv6ControlInfo *ctrlInfo, InterfaceEntry *ie) |
virtual void | sendSolicitedNA (IPv6NeighbourSolicitation *ns, IPv6ControlInfo *nsCtrlInfo, InterfaceEntry *ie) |
virtual void | sendUnsolicitedNA (InterfaceEntry *ie) |
virtual void | processNAPacket (IPv6NeighbourAdvertisement *na, IPv6ControlInfo *naCtrlInfo) |
virtual bool | validateNAPacket (IPv6NeighbourAdvertisement *na, IPv6ControlInfo *naCtrlInfo) |
virtual void | processNAForIncompleteNCEState (IPv6NeighbourAdvertisement *na, IPv6NeighbourCache::Neighbour *nce) |
virtual void | processNAForOtherNCEStates (IPv6NeighbourAdvertisement *na, IPv6NeighbourCache::Neighbour *nce) |
virtual IPv6Redirect * | createAndSendRedirectPacket (InterfaceEntry *ie) |
virtual void | processRedirectPacket (IPv6Redirect *redirect, IPv6ControlInfo *ctrlInfo) |
Protected Attributes | |
cQueue | pendingQueue |
IInterfaceTable * | ift |
RoutingTable6 * | rt6 |
ICMPv6 * | icmpv6 |
IPv6NeighbourCache | neighbourCache |
RATimerList | raTimerList |
DADList | dadList |
RDList | rdList |
AdvIfList | advIfList |
Classes | |
struct | AdvIfEntry |
struct | DADEntry |
struct | RDEntry |
typedef std::vector<cMessage*> IPv6NeighbourDiscovery::MsgPtrVector |
typedef std::set<cMessage*> IPv6NeighbourDiscovery::RATimerList [protected] |
typedef std::set<DADEntry*> IPv6NeighbourDiscovery::DADList [protected] |
typedef std::set<RDEntry*> IPv6NeighbourDiscovery::RDList [protected] |
typedef std::set<AdvIfEntry*> IPv6NeighbourDiscovery::AdvIfList [protected] |
IPv6NeighbourDiscovery::~IPv6NeighbourDiscovery | ( | ) | [virtual] |
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 }
const MACAddress & IPv6NeighbourDiscovery::resolveNeighbour | ( | const IPv6Address & | nextHop, | |
int | interfaceId | |||
) |
Public method, to be invoked from the IPv6 module to determine link-layer address and the output interface of the next hop.
If the neighbor cache does not contain this address or it's in the state INCOMPLETE, this method will return the NULL address, and the IPv6 module should then send the datagram here to IPv6NeighbourDiscovery where it will be stored until neighbour resolution completes.
If the neighbour cache entry is STALE (or REACHABLE but more than reachableTime elapsed since reachability was last confirmed), the link-layer address is still returned and IPv6 can send the datagram, but simultaneously, this call should trigger the Neighbour Unreachability Detection procedure to start in the IPv6NeighbourDiscovery module.
Referenced by IPv6::routePacket().
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 }
void IPv6NeighbourDiscovery::reachabilityConfirmed | ( | const IPv6Address & | neighbour, | |
int | interfaceId | |||
) | [virtual] |
Public method, it can be invoked from the IPv6 module or any other module to let Neighbour Discovery know that the reachability of the given neighbor has just been confirmed (e.g. TCP received ACK of new data from it). Neighbour Discovery can then update the neighbour cache with this information, and cancel the Neighbour Unreachability Detection procedure if it is currently running.
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 }
virtual int IPv6NeighbourDiscovery::numInitStages | ( | ) | const [inline, protected, virtual] |
void IPv6NeighbourDiscovery::initialize | ( | int | stage | ) | [protected, virtual] |
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 }
void IPv6NeighbourDiscovery::handleMessage | ( | cMessage * | msg | ) | [protected, virtual] |
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 }
void IPv6NeighbourDiscovery::processNDMessage | ( | ICMPv6Message * | msg, | |
IPv6ControlInfo * | ctrlInfo | |||
) | [protected, virtual] |
Referenced by handleMessage().
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 }
void IPv6NeighbourDiscovery::processIPv6Datagram | ( | IPv6Datagram * | datagram | ) | [protected, virtual] |
Referenced by handleMessage().
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 }
IPv6NeighbourDiscovery::AdvIfEntry * IPv6NeighbourDiscovery::fetchAdvIfEntry | ( | InterfaceEntry * | ie | ) | [protected, virtual] |
Referenced by processRSPacket(), and sendPeriodicRA().
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 }
IPv6NeighbourDiscovery::RDEntry * IPv6NeighbourDiscovery::fetchRDEntry | ( | InterfaceEntry * | ie | ) | [protected, virtual] |
Referenced by cancelRouterDiscovery(), and processRDTimeout().
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 }
IPv6Address IPv6NeighbourDiscovery::determineNextHop | ( | const IPv6Address & | destAddr, | |
int & | outIfID | |||
) | [protected, virtual] |
This function accepts the datagram's destination address and attempts to determine the destination's next hop address and interface ID by: (1) looking up the destination cache, (2)looking up the routing table, or (3) selecting a default router. It then updates the destination cache. If no default router can be selected than we assume the destination address to be onlink and simply return any available interface.
Referenced by processIPv6Datagram().
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 }
void IPv6NeighbourDiscovery::initiateNeighbourUnreachabilityDetection | ( | Neighbour * | neighbour | ) | [protected, virtual] |
Referenced by processIPv6Datagram(), and resolveNeighbour().
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 }
void IPv6NeighbourDiscovery::processNUDTimeout | ( | cMessage * | timeoutMsg | ) | [protected, virtual] |
Referenced by handleMessage().
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 }
IPv6Address IPv6NeighbourDiscovery::selectDefaultRouter | ( | int & | outIfID | ) | [protected, virtual] |
Referenced by determineNextHop().
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 }
void IPv6NeighbourDiscovery::timeoutPrefixEntry | ( | const IPv6Address & | destPrefix, | |
int | prefixLength | |||
) | [protected, virtual] |
RFC 2461: Section 6.3.5 Whenever the invalidation timer expires for a Prefix List entry, that entry is discarded. No existing Destination Cache entries need be updated, however. Should a reachability problem arise with an existing Neighbor Cache entry, Neighbor Unreachability Detection will perform any needed recovery.
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 }
void IPv6NeighbourDiscovery::timeoutDefaultRouter | ( | const IPv6Address & | addr, | |
int | interfaceID | |||
) | [protected, virtual] |
RFC 2461: Section 6.3.5 Whenever the Lifetime of an entry in the Default Router List expires, that entry is discarded. When removing a router from the Default Router list, the node MUST update the Destination Cache in such a way that all entries using the router perform next-hop determination again rather than continue sending traffic to the (deleted) router.
Referenced by processRAForRouterUpdates().
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 }
void IPv6NeighbourDiscovery::initiateAddressResolution | ( | const IPv6Address & | dgSrcAddr, | |
Neighbour * | nce | |||
) | [protected, virtual] |
This method attempts to resolve the given neighbour's link-layer address. The source address of the packet prompting address resolution is also given in order to decide the source address of the NS to be sent. nceKey stores 2 pieces of information (Neighbour address and Interface ID) which is needed for addr resolution and access to the corresponding nce.
Referenced by processIPv6Datagram().
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 }
void IPv6NeighbourDiscovery::processARTimeout | ( | cMessage * | arTimeoutMsg | ) | [protected, virtual] |
Resends a NS packet to the address intended for address resolution. TODO: Not implemented yet!
Referenced by handleMessage().
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 }
void IPv6NeighbourDiscovery::dropQueuedPacketsAwaitingAR | ( | Neighbour * | nce | ) | [protected, virtual] |
Drops specific queued packets for a specific NCE AR-timeout. TODO: Not implemented yet!
Referenced by processARTimeout().
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 }
void IPv6NeighbourDiscovery::sendPacketToIPv6Module | ( | cMessage * | msg, | |
const IPv6Address & | destAddr, | |||
const IPv6Address & | srcAddr, | |||
int | interfaceId | |||
) | [protected, virtual] |
Create control info and assigns it to a msg. Returns a copy of the msg with the control info.
Referenced by createAndSendNSPacket(), createAndSendRAPacket(), createAndSendRSPacket(), processIPv6Datagram(), and sendSolicitedNA().
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 }
void IPv6NeighbourDiscovery::sendQueuedPacketsToIPv6Module | ( | Neighbour * | nce | ) | [protected, virtual] |
Send off any queued packets within the Neighbour Discovery module awaiting address resolution.
Not used yet-unsure if we really need it. --DELETED, Andras
Referenced by processNAForIncompleteNCEState().
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 }
void IPv6NeighbourDiscovery::initiateDAD | ( | const IPv6Address & | tentativeAddr, | |
InterfaceEntry * | ie | |||
) | [protected, virtual] |
Initiating DAD means to send off a Neighbour Solicitation with its target address set as this node's tentative link-local address.
Referenced by assignLinkLocalAddress().
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 }
void IPv6NeighbourDiscovery::processDADTimeout | ( | cMessage * | msg | ) | [protected, virtual] |
Sends a scheduled DAD NS packet. If number of sends is equals or more than dupAddrDetectTransmits, then permantly assign target link local address as permanent address for given interface entry.
Referenced by handleMessage().
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 }
void IPv6NeighbourDiscovery::assignLinkLocalAddress | ( | cMessage * | timerMsg | ) | [protected, virtual] |
as it is not possbile to explicitly define RFC 2462. ND is the next best place to do this.
RFC 2462-IPv6 Stateless Address Autoconfiguration: Section 1 The autoconfiguration process specified in this document applies only to hosts and not routers. Since host autoconfiguration uses information advertised by routers, routers will need to be configured by some other means. However, it is expected that routers will generate link-local addresses using the mechanism described in this document. In addition, routers are expected to successfully pass the Duplicate Address Detection procedure described in this document on all addresses prior to assigning them to an interface.
Referenced by handleMessage().
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 }
IPv6RouterSolicitation * IPv6NeighbourDiscovery::createAndSendRSPacket | ( | InterfaceEntry * | ie | ) | [protected, virtual] |
Referenced by initiateRouterDiscovery(), and processRDTimeout().
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 }
void IPv6NeighbourDiscovery::initiateRouterDiscovery | ( | cMessage * | msg | ) | [protected, virtual] |
Referenced by handleMessage().
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 }
void IPv6NeighbourDiscovery::cancelRouterDiscovery | ( | InterfaceEntry * | ie | ) | [protected, virtual] |
RFC 2461: Section 6.3.7 4th paragraph Once the host sends a Router Solicitation, and receives a valid Router Advertisement with a non-zero Router Lifetime, the host MUST desist from sending additional solicitations on that interface,
Cancel Router Discovery on the Interface where a RA was received with the given Interface Entry.
Referenced by processRAPacket().
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 }
void IPv6NeighbourDiscovery::processRDTimeout | ( | cMessage * | msg | ) | [protected, virtual] |
Referenced by handleMessage().
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 }
void IPv6NeighbourDiscovery::processRSPacket | ( | IPv6RouterSolicitation * | rs, | |
IPv6ControlInfo * | rsCtrlInfo | |||
) | [protected, virtual] |
Referenced by processNDMessage().
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 }
bool IPv6NeighbourDiscovery::validateRSPacket | ( | IPv6RouterSolicitation * | rs, | |
IPv6ControlInfo * | rsCtrlInfo | |||
) | [protected, virtual] |
Referenced by processRSPacket().
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 }
IPv6RouterAdvertisement * IPv6NeighbourDiscovery::createAndSendRAPacket | ( | const IPv6Address & | destAddr, | |
InterfaceEntry * | ie | |||
) | [protected, virtual] |
Referenced by sendPeriodicRA(), and sendSolicitedRA().
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 }
void IPv6NeighbourDiscovery::processRAPacket | ( | IPv6RouterAdvertisement * | ra, | |
IPv6ControlInfo * | raCtrlInfo | |||
) | [protected, virtual] |
Referenced by processNDMessage().
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 }
void IPv6NeighbourDiscovery::processRAForRouterUpdates | ( | IPv6RouterAdvertisement * | ra, | |
IPv6ControlInfo * | raCtrlInfo | |||
) | [protected, virtual] |
Referenced by processRAPacket().
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 }
void IPv6NeighbourDiscovery::processRAPrefixInfo | ( | IPv6RouterAdvertisement * | ra, | |
InterfaceEntry * | ie | |||
) | [protected, virtual] |
Referenced by processRAForRouterUpdates().
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 }
void IPv6NeighbourDiscovery::processRAPrefixInfoForAddrAutoConf | ( | IPv6NDPrefixInformation & | prefixInfo, | |
InterfaceEntry * | ie | |||
) | [protected, virtual] |
Referenced by processRAPacket().
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 }
void IPv6NeighbourDiscovery::createRATimer | ( | InterfaceEntry * | ie | ) | [protected, virtual] |
Create a timer for the given interface entry that sends periodic Router Advertisements
Referenced by initialize().
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 }
void IPv6NeighbourDiscovery::resetRATimer | ( | InterfaceEntry * | ie | ) | [protected, virtual] |
Reset the given interface entry's Router Advertisement timer. This is usually done when a router interface responds (by replying with a Router Advertisement sent to the All-Node multicast group)to a router solicitation Also see: RFC 2461, Section 6.2.6
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 }
void IPv6NeighbourDiscovery::sendPeriodicRA | ( | cMessage * | msg | ) | [protected, virtual] |
Referenced by handleMessage().
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 }
void IPv6NeighbourDiscovery::sendSolicitedRA | ( | cMessage * | msg | ) | [protected, virtual] |
Referenced by handleMessage().
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 }
bool IPv6NeighbourDiscovery::validateRAPacket | ( | IPv6RouterAdvertisement * | ra, | |
IPv6ControlInfo * | raCtrlInfo | |||
) | [protected, virtual] |
Referenced by processRAPacket().
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 }
IPv6NeighbourSolicitation * IPv6NeighbourDiscovery::createAndSendNSPacket | ( | const IPv6Address & | nsTargetAddr, | |
const IPv6Address & | dgDestAddr, | |||
const IPv6Address & | dgSrcAddr, | |||
InterfaceEntry * | ie | |||
) | [protected, virtual] |
Referenced by initiateAddressResolution(), initiateDAD(), processARTimeout(), processDADTimeout(), and processNUDTimeout().
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 }
void IPv6NeighbourDiscovery::processNSPacket | ( | IPv6NeighbourSolicitation * | ns, | |
IPv6ControlInfo * | naCtrlInfo | |||
) | [protected, virtual] |
Referenced by processNDMessage().
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 }
bool IPv6NeighbourDiscovery::validateNSPacket | ( | IPv6NeighbourSolicitation * | ns, | |
IPv6ControlInfo * | nsCtrlInfo | |||
) | [protected, virtual] |
Referenced by processNSPacket().
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 }
void IPv6NeighbourDiscovery::processNSForTentativeAddress | ( | IPv6NeighbourSolicitation * | ns, | |
IPv6ControlInfo * | ctrlInfo | |||
) | [protected, virtual] |
Referenced by processNSPacket().
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 }
void IPv6NeighbourDiscovery::processNSForNonTentativeAddress | ( | IPv6NeighbourSolicitation * | ns, | |
IPv6ControlInfo * | ctrlInfo, | |||
InterfaceEntry * | ie | |||
) | [protected, virtual] |
Referenced by processNSPacket().
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 }
void IPv6NeighbourDiscovery::processNSWithSpecifiedSrcAddr | ( | IPv6NeighbourSolicitation * | ns, | |
IPv6ControlInfo * | ctrlInfo, | |||
InterfaceEntry * | ie | |||
) | [protected, virtual] |
Referenced by processNSForNonTentativeAddress().
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 }
void IPv6NeighbourDiscovery::sendSolicitedNA | ( | IPv6NeighbourSolicitation * | ns, | |
IPv6ControlInfo * | nsCtrlInfo, | |||
InterfaceEntry * | ie | |||
) | [protected, virtual] |
Referenced by processNSForNonTentativeAddress(), and processNSWithSpecifiedSrcAddr().
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 }
void IPv6NeighbourDiscovery::sendUnsolicitedNA | ( | InterfaceEntry * | ie | ) | [protected, virtual] |
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 }
void IPv6NeighbourDiscovery::processNAPacket | ( | IPv6NeighbourAdvertisement * | na, | |
IPv6ControlInfo * | naCtrlInfo | |||
) | [protected, virtual] |
Referenced by processNDMessage().
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 }
bool IPv6NeighbourDiscovery::validateNAPacket | ( | IPv6NeighbourAdvertisement * | na, | |
IPv6ControlInfo * | naCtrlInfo | |||
) | [protected, virtual] |
Referenced by processNAPacket().
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 }
void IPv6NeighbourDiscovery::processNAForIncompleteNCEState | ( | IPv6NeighbourAdvertisement * | na, | |
IPv6NeighbourCache::Neighbour * | nce | |||
) | [protected, virtual] |
Referenced by processNAPacket().
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 }
void IPv6NeighbourDiscovery::processNAForOtherNCEStates | ( | IPv6NeighbourAdvertisement * | na, | |
IPv6NeighbourCache::Neighbour * | nce | |||
) | [protected, virtual] |
Referenced by processNAPacket().
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 }
IPv6Redirect * IPv6NeighbourDiscovery::createAndSendRedirectPacket | ( | InterfaceEntry * | ie | ) | [protected, virtual] |
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 }
void IPv6NeighbourDiscovery::processRedirectPacket | ( | IPv6Redirect * | redirect, | |
IPv6ControlInfo * | ctrlInfo | |||
) | [protected, virtual] |
Referenced by processNDMessage().
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 }
cQueue IPv6NeighbourDiscovery::pendingQueue [protected] |
Referenced by dropQueuedPacketsAwaitingAR(), initialize(), processIPv6Datagram(), and sendQueuedPacketsToIPv6Module().
IInterfaceTable* IPv6NeighbourDiscovery::ift [protected] |
Referenced by assignLinkLocalAddress(), initialize(), initiateAddressResolution(), initiateNeighbourUnreachabilityDetection(), processARTimeout(), processDADTimeout(), processNAForIncompleteNCEState(), processNAForOtherNCEStates(), processNAPacket(), processNSPacket(), processNUDTimeout(), processRAForRouterUpdates(), processRAPacket(), and processRSPacket().
RoutingTable6* IPv6NeighbourDiscovery::rt6 [protected] |
ICMPv6* IPv6NeighbourDiscovery::icmpv6 [protected] |
Referenced by dropQueuedPacketsAwaitingAR(), initialize(), and processIPv6Datagram().
RATimerList IPv6NeighbourDiscovery::raTimerList [protected] |
DADList IPv6NeighbourDiscovery::dadList [protected] |
Referenced by initiateDAD(), and processDADTimeout().
RDList IPv6NeighbourDiscovery::rdList [protected] |
Referenced by cancelRouterDiscovery(), fetchRDEntry(), and initiateRouterDiscovery().
AdvIfList IPv6NeighbourDiscovery::advIfList [protected] |
Referenced by createRATimer(), and fetchAdvIfEntry().