00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <algorithm>
00021 #include "opp_utils.h"
00022 #include "RoutingTable6.h"
00023 #include "IPv6InterfaceData.h"
00024 #include "InterfaceTableAccess.h"
00025
00026
00027
00028 Define_Module(RoutingTable6);
00029
00030
00031 std::string IPv6Route::info() const
00032 {
00033 std::stringstream out;
00034 out << getDestPrefix() << "/" << getPrefixLength() << " --> ";
00035 out << "if=" << getInterfaceId() << " next hop:" << getNextHop();
00036 out << " " << routeSrcName(getSrc());
00037 if (getExpiryTime()>0)
00038 out << " exp:" << getExpiryTime();
00039 return out.str();
00040 }
00041
00042 std::string IPv6Route::detailedInfo() const
00043 {
00044 return std::string();
00045 }
00046
00047 const char *IPv6Route::routeSrcName(RouteSrc src)
00048 {
00049 switch (src)
00050 {
00051 case FROM_RA: return "FROM_RA";
00052 case OWN_ADV_PREFIX: return "OWN_ADV_PREFIX";
00053 case STATIC: return "STATIC";
00054 case ROUTING_PROT: return "ROUTING_PROT";
00055 default: return "???";
00056 }
00057 }
00058
00059
00060
00061 std::ostream& operator<<(std::ostream& os, const IPv6Route& e)
00062 {
00063 os << e.info();
00064 return os;
00065 };
00066
00067 std::ostream& operator<<(std::ostream& os, const RoutingTable6::DestCacheEntry& e)
00068 {
00069 os << "if=" << e.interfaceId << " " << e.nextHopAddr;
00070 return os;
00071 };
00072
00073 RoutingTable6::RoutingTable6()
00074 {
00075 }
00076
00077 RoutingTable6::~RoutingTable6()
00078 {
00079 for (unsigned int i=0; i<routeList.size(); i++)
00080 delete routeList[i];
00081 }
00082
00083 void RoutingTable6::initialize(int stage)
00084 {
00085 if (stage==1)
00086 {
00087 ift = InterfaceTableAccess().get();
00088 nb = NotificationBoardAccess().get();
00089
00090 nb->subscribe(this, NF_INTERFACE_CREATED);
00091 nb->subscribe(this, NF_INTERFACE_DELETED);
00092 nb->subscribe(this, NF_INTERFACE_STATE_CHANGED);
00093 nb->subscribe(this, NF_INTERFACE_CONFIG_CHANGED);
00094 nb->subscribe(this, NF_INTERFACE_IPv6CONFIG_CHANGED);
00095
00096 WATCH_PTRVECTOR(routeList);
00097 WATCH_MAP(destCache);
00098 isrouter = par("isRouter");
00099 WATCH(isrouter);
00100
00101
00102 for (int i=0; i<ift->getNumInterfaces(); i++)
00103 {
00104 InterfaceEntry *ie = ift->getInterface(i);
00105 configureInterfaceForIPv6(ie);
00106 }
00107
00108 parseXMLConfigFile();
00109
00110
00111 if (isrouter)
00112 {
00113
00114 for (int x = 0; x < ift->getNumInterfaces(); x++)
00115 {
00116 InterfaceEntry *ie = ift->getInterface(x);
00117
00118 if (ie->isLoopback())
00119 continue;
00120
00121 for (int y = 0; y < ie->ipv6Data()->getNumAdvPrefixes(); y++)
00122 if (ie->ipv6Data()->getAdvPrefix(y).prefix.isGlobal())
00123 addOrUpdateOwnAdvPrefix(ie->ipv6Data()->getAdvPrefix(y).prefix,
00124 ie->ipv6Data()->getAdvPrefix(y).prefixLength,
00125 ie->getInterfaceId(), 0);
00126 }
00127 }
00128 }
00129 else if (stage==4)
00130 {
00131
00132 updateDisplayString();
00133 }
00134 }
00135
00136 void RoutingTable6::parseXMLConfigFile()
00137 {
00138
00139
00140 cXMLElement *config = par("routingTableFile");
00141 for (cXMLElement *child=config->getFirstChild(); child; child = child->getNextSibling())
00142 {
00143
00144
00145
00146 if (opp_strcmp(child->getTagName(),"local")!=0) continue;
00147
00148 if (opp_strcmp(child->getAttribute("node"),getParentModule()->getFullName())!=0)
00149 continue;
00150
00151
00152 for (cXMLElement *ifTag=child->getFirstChild(); ifTag; ifTag = ifTag->getNextSibling())
00153 {
00154
00155 if (opp_strcmp(ifTag->getTagName(),"interface")!=0)
00156 continue;
00157
00158 const char *ifname = ifTag->getAttribute("name");
00159 if (!ifname)
00160 error("<interface> without name attribute at %s", child->getSourceLocation());
00161 InterfaceEntry *ie = ift->getInterfaceByName(ifname);
00162 if (!ie)
00163 error("no interface named %s was registered, %s", ifname, child->getSourceLocation());
00164 configureInterfaceFromXML(ie, ifTag);
00165 }
00166 }
00167 }
00168
00169 void RoutingTable6::updateDisplayString()
00170 {
00171 if (!ev.isGUI())
00172 return;
00173
00174 std::stringstream os;
00175
00176 os << getNumRoutes() << " routes\n" << destCache.size() << " destcache entries";
00177 getDisplayString().setTagArg("t", 0, os.str().c_str());
00178 }
00179
00180 void RoutingTable6::handleMessage(cMessage *msg)
00181 {
00182 opp_error("This module doesn't process messages");
00183 }
00184
00185 void RoutingTable6::receiveChangeNotification(int category, const cPolymorphic *details)
00186 {
00187 if (simulation.getContextType()==CTX_INITIALIZE)
00188 return;
00189
00190 Enter_Method_Silent();
00191 printNotificationBanner(category, details);
00192
00193 if (category==NF_INTERFACE_CREATED)
00194 {
00195
00196
00197
00198 }
00199 else if (category==NF_INTERFACE_DELETED)
00200 {
00201
00202 }
00203 else if (category==NF_INTERFACE_STATE_CHANGED)
00204 {
00205
00206 }
00207 else if (category==NF_INTERFACE_CONFIG_CHANGED)
00208 {
00209
00210 }
00211 else if (category==NF_INTERFACE_IPv6CONFIG_CHANGED)
00212 {
00213
00214 }
00215 }
00216
00217 void RoutingTable6::configureInterfaceForIPv6(InterfaceEntry *ie)
00218 {
00219 IPv6InterfaceData *ipv6IfData = new IPv6InterfaceData();
00220 ie->setIPv6Data(ipv6IfData);
00221
00222
00223
00224
00225
00226 ipv6IfData->setAdvSendAdvertisements(isrouter);
00227
00228
00229
00230
00231
00232 assignRequiredNodeAddresses(ie);
00233 }
00234
00235 void RoutingTable6::assignRequiredNodeAddresses(InterfaceEntry *ie)
00236 {
00237
00238
00239
00240
00241
00242 if (ie->isLoopback())
00243 {
00244 ie->ipv6Data()->assignAddress(IPv6Address("::1"), false, 0, 0);
00245 return;
00246 }
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274 }
00275
00276 static const char *getRequiredAttr(cXMLElement *elem, const char *attrName)
00277 {
00278 const char *s = elem->getAttribute(attrName);
00279 if (!s)
00280 opp_error("element <%s> misses required attribute %s at %s",
00281 elem->getTagName(), attrName, elem->getSourceLocation());
00282 return s;
00283 }
00284 static bool toBool(const char *s, bool defaultValue=false)
00285 {
00286 if (!s)
00287 return defaultValue;
00288 return !strcmp(s,"on") || !strcmp(s,"true") || !strcmp(s,"yes");
00289 }
00290
00291 void RoutingTable6::configureInterfaceFromXML(InterfaceEntry *ie, cXMLElement *cfg)
00292 {
00293
00294
00295
00296
00297
00298 IPv6InterfaceData *d = ie->ipv6Data();
00299
00300
00301 d->setAdvSendAdvertisements(toBool(getRequiredAttr(cfg, "AdvSendAdvertisements")));
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322 cXMLElementList prefixList = cfg->getElementsByTagName("AdvPrefix");
00323 for (unsigned int i=0; i<prefixList.size(); i++)
00324 {
00325 cXMLElement *node = prefixList[i];
00326 IPv6InterfaceData::AdvPrefix prefix;
00327
00328
00329
00330
00331 int pfxLen;
00332 if (!prefix.prefix.tryParseAddrWithPrefix(node->getNodeValue(),pfxLen))
00333 opp_error("element <%s> at %s: wrong IPv6Address/prefix syntax %s",
00334 node->getTagName(), node->getSourceLocation(), node->getNodeValue());
00335 prefix.prefixLength = pfxLen;
00336 prefix.advValidLifetime = OPP_Global::atoul(getRequiredAttr(node, "AdvValidLifetime"));
00337 prefix.advOnLinkFlag = toBool(getRequiredAttr(node, "AdvOnLinkFlag"));
00338 prefix.advPreferredLifetime = OPP_Global::atoul(getRequiredAttr(node, "AdvPreferredLifetime"));
00339 prefix.advAutonomousFlag = toBool(getRequiredAttr(node, "AdvAutonomousFlag"));
00340 d->addAdvPrefix(prefix);
00341 }
00342
00343
00344 cXMLElementList addrList = cfg->getChildrenByTagName("inetAddr");
00345 for (unsigned int k=0; k<addrList.size(); k++)
00346 {
00347 cXMLElement *node = addrList[k];
00348 IPv6Address address = node->getNodeValue();
00349
00350 d->assignAddress(address, toBool(getRequiredAttr(node, "tentative")), 0, 0);
00351 }
00352 }
00353
00354 InterfaceEntry *RoutingTable6::getInterfaceByAddress(const IPv6Address& addr)
00355 {
00356 Enter_Method("getInterfaceByAddress(%s)=?", addr.str().c_str());
00357
00358 if (addr.isUnspecified())
00359 return NULL;
00360 for (int i=0; i<ift->getNumInterfaces(); ++i)
00361 {
00362 InterfaceEntry *ie = ift->getInterface(i);
00363 if (ie->ipv6Data()->hasAddress(addr))
00364 return ie;
00365 }
00366 return NULL;
00367 }
00368
00369 bool RoutingTable6::isLocalAddress(const IPv6Address& dest) const
00370 {
00371 Enter_Method("isLocalAddress(%s) y/n", dest.str().c_str());
00372
00373
00374 for (int i=0; i<ift->getNumInterfaces(); i++)
00375 {
00376 InterfaceEntry *ie = ift->getInterface(i);
00377 if (ie->ipv6Data()->hasAddress(dest))
00378 return true;
00379 }
00380
00381
00382
00383
00384
00385 if (dest==IPv6Address::ALL_NODES_1 || dest==IPv6Address::ALL_NODES_2)
00386 return true;
00387 if (isRouter() && (dest==IPv6Address::ALL_ROUTERS_1 || dest==IPv6Address::ALL_ROUTERS_2 || dest==IPv6Address::ALL_ROUTERS_5))
00388 return true;
00389
00390
00391 if (dest.matches(IPv6Address::SOLICITED_NODE_PREFIX, 104))
00392 {
00393 for (int i=0; i<ift->getNumInterfaces(); i++)
00394 {
00395 InterfaceEntry *ie = ift->getInterface(i);
00396 if (ie->ipv6Data()->matchesSolicitedNodeMulticastAddress(dest))
00397 return true;
00398 }
00399 }
00400 return false;
00401 }
00402
00403 const IPv6Address& RoutingTable6::lookupDestCache(const IPv6Address& dest, int& outInterfaceId) const
00404 {
00405 Enter_Method("lookupDestCache(%s)", dest.str().c_str());
00406
00407 DestCache::const_iterator it = destCache.find(dest);
00408 if (it == destCache.end())
00409 {
00410 outInterfaceId = -1;
00411 return IPv6Address::UNSPECIFIED_ADDRESS;
00412 }
00413 outInterfaceId = it->second.interfaceId;
00414 return it->second.nextHopAddr;
00415 }
00416
00417 const IPv6Route *RoutingTable6::doLongestPrefixMatch(const IPv6Address& dest)
00418 {
00419 Enter_Method("doLongestPrefixMatch(%s)", dest.str().c_str());
00420
00421
00422
00423 for (RouteList::const_iterator it=routeList.begin(); it!=routeList.end(); it++)
00424 {
00425 if (dest.matches((*it)->getDestPrefix(),(*it)->getPrefixLength()))
00426 {
00427
00428 bool entryExpired = false;
00429 if (simTime() > (*it)->getExpiryTime() && (*it)->getExpiryTime() != 0)
00430 {
00431 EV << "Expired prefix detected!!" << endl;
00432 removeOnLinkPrefix((*it)->getDestPrefix(), (*it)->getPrefixLength());
00433 entryExpired = true;
00434 }
00435 if (entryExpired == false) return *it;
00436 }
00437 }
00438
00439 return NULL;
00440 }
00441
00442 bool RoutingTable6::isPrefixPresent(const IPv6Address& prefix) const
00443 {
00444 for (RouteList::const_iterator it=routeList.begin(); it!=routeList.end(); it++)
00445 if (prefix.matches((*it)->getDestPrefix(),128))
00446 return true;
00447 return false;
00448 }
00449
00450 void RoutingTable6::updateDestCache(const IPv6Address& dest, const IPv6Address& nextHopAddr, int interfaceId)
00451 {
00452
00453 destCache[dest].nextHopAddr = nextHopAddr;
00454 destCache[dest].interfaceId = interfaceId;
00455
00456 updateDisplayString();
00457 }
00458
00459 void RoutingTable6::purgeDestCache()
00460 {
00461 destCache.clear();
00462 updateDisplayString();
00463 }
00464
00465 void RoutingTable6::purgeDestCacheEntriesToNeighbour(const IPv6Address& nextHopAddr, int interfaceId)
00466 {
00467 for (DestCache::iterator it=destCache.begin(); it!=destCache.end(); )
00468 {
00469 if (it->second.interfaceId==interfaceId && it->second.nextHopAddr==nextHopAddr)
00470 {
00471
00472 DestCache::iterator oldIt = it++;
00473 destCache.erase(oldIt);
00474 }
00475 else
00476 {
00477 it++;
00478 }
00479 }
00480
00481 updateDisplayString();
00482 }
00483
00484 void RoutingTable6::addOrUpdateOnLinkPrefix(const IPv6Address& destPrefix, int prefixLength,
00485 int interfaceId, simtime_t expiryTime)
00486 {
00487
00488 IPv6Route *route = NULL;
00489 for (RouteList::iterator it=routeList.begin(); it!=routeList.end(); it++)
00490 {
00491 if ((*it)->getSrc()==IPv6Route::FROM_RA && (*it)->getDestPrefix()==destPrefix && (*it)->getPrefixLength()==prefixLength)
00492 {
00493 route = *it;
00494 break;
00495 }
00496 }
00497
00498 if (route==NULL)
00499 {
00500
00501 IPv6Route *route = new IPv6Route(destPrefix, prefixLength, IPv6Route::FROM_RA);
00502 route->setInterfaceId(interfaceId);
00503 route->setExpiryTime(expiryTime);
00504 route->setMetric(0);
00505
00506
00507 addRoute(route);
00508 }
00509 else
00510 {
00511
00512 nb->fireChangeNotification(NF_IPv6_ROUTE_DELETED, route);
00513 route->setInterfaceId(interfaceId);
00514 route->setExpiryTime(expiryTime);
00515 nb->fireChangeNotification(NF_IPv6_ROUTE_ADDED, route);
00516 }
00517
00518 updateDisplayString();
00519 }
00520
00521 void RoutingTable6::addOrUpdateOwnAdvPrefix(const IPv6Address& destPrefix, int prefixLength,
00522 int interfaceId, simtime_t expiryTime)
00523 {
00524
00525
00526
00527 IPv6Route *route = NULL;
00528 for (RouteList::iterator it=routeList.begin(); it!=routeList.end(); it++)
00529 {
00530 if ((*it)->getSrc()==IPv6Route::OWN_ADV_PREFIX && (*it)->getDestPrefix()==destPrefix && (*it)->getPrefixLength()==prefixLength)
00531 {
00532 route = *it;
00533 break;
00534 }
00535 }
00536
00537 if (route==NULL)
00538 {
00539
00540 IPv6Route *route = new IPv6Route(destPrefix, prefixLength, IPv6Route::OWN_ADV_PREFIX);
00541 route->setInterfaceId(interfaceId);
00542 route->setExpiryTime(expiryTime);
00543 route->setMetric(0);
00544
00545
00546 addRoute(route);
00547 }
00548 else
00549 {
00550
00551 nb->fireChangeNotification(NF_IPv6_ROUTE_DELETED, route);
00552 route->setInterfaceId(interfaceId);
00553 route->setExpiryTime(expiryTime);
00554 nb->fireChangeNotification(NF_IPv6_ROUTE_ADDED, route);
00555 }
00556
00557 updateDisplayString();
00558 }
00559
00560 void RoutingTable6::removeOnLinkPrefix(const IPv6Address& destPrefix, int prefixLength)
00561 {
00562
00563 for (RouteList::iterator it=routeList.begin(); it!=routeList.end(); it++)
00564 {
00565 if ((*it)->getSrc()==IPv6Route::FROM_RA && (*it)->getDestPrefix()==destPrefix && (*it)->getPrefixLength()==prefixLength)
00566 {
00567 routeList.erase(it);
00568 return;
00569 }
00570 }
00571
00572 updateDisplayString();
00573 }
00574
00575 void RoutingTable6::addStaticRoute(const IPv6Address& destPrefix, int prefixLength,
00576 unsigned int interfaceId, const IPv6Address& nextHop,
00577 int metric)
00578 {
00579
00580 IPv6Route *route = new IPv6Route(destPrefix, prefixLength, IPv6Route::STATIC);
00581 route->setInterfaceId(interfaceId);
00582 route->setNextHop(nextHop);
00583 if (metric==0)
00584 metric = 10;
00585 route->setMetric(metric);
00586
00587
00588 addRoute(route);
00589 }
00590
00591 void RoutingTable6::addDefaultRoute(const IPv6Address& nextHop, unsigned int ifID,
00592 simtime_t routerLifetime)
00593 {
00594
00595 IPv6Route *route = new IPv6Route(IPv6Address(), 0, IPv6Route::FROM_RA);
00596 route->setInterfaceId(ifID);
00597 route->setNextHop(nextHop);
00598 route->setMetric(10);
00599
00600
00601 addRoute(route);
00602 }
00603
00604 void RoutingTable6::addRoutingProtocolRoute(IPv6Route *route)
00605 {
00606 ASSERT(route->getSrc()==IPv6Route::ROUTING_PROT);
00607 addRoute(route);
00608 }
00609
00610 bool RoutingTable6::routeLessThan(const IPv6Route *a, const IPv6Route *b)
00611 {
00612
00613
00614
00615 if (a->getPrefixLength()!=b->getPrefixLength())
00616 return a->getPrefixLength() > b->getPrefixLength();
00617 return a->getMetric() < b->getMetric();
00618 }
00619
00620 void RoutingTable6::addRoute(IPv6Route *route)
00621 {
00622 routeList.push_back(route);
00623
00624
00625
00626 std::sort(routeList.begin(), routeList.end(), routeLessThan);
00627
00628 updateDisplayString();
00629
00630 nb->fireChangeNotification(NF_IPv6_ROUTE_ADDED, route);
00631 }
00632
00633 void RoutingTable6::removeRoute(IPv6Route *route)
00634 {
00635 RouteList::iterator it = std::find(routeList.begin(), routeList.end(), route);
00636 ASSERT(it!=routeList.end());
00637
00638 nb->fireChangeNotification(NF_IPv6_ROUTE_DELETED, route);
00639
00640 routeList.erase(it);
00641 delete route;
00642
00643 updateDisplayString();
00644 }
00645
00646 int RoutingTable6::getNumRoutes() const
00647 {
00648 return routeList.size();
00649 }
00650
00651 IPv6Route *RoutingTable6::getRoute(int i)
00652 {
00653 ASSERT(i>=0 && i<(int)routeList.size());
00654 return routeList[i];
00655 }
00656