#include <RoutingTable.h>
Inheritance diagram for RoutingTable:
See the NED documentation for general overview.
This is a simple module without gates, it requires function calls to it (message handling does nothing). Methods are provided for reading and updating the interface table and the route table, as well as for unicast and multicast routing.
Interfaces are dynamically registered: at the start of the simulation, every L2 module adds its own interface entry to the table.
The route table is read from a file (RoutingTableParser); the file can also fill in or overwrite interface settings. The route table can also be read and modified during simulation, typically by routing protocol implementations (e.g. OSPF).
Entries in the route table are represented by RoutingEntry objects. RoutingEntry objects can be polymorphic: if a routing protocol needs to store additional data, it can simply subclass from RoutingEntry, and add the derived object to the table.
Uses RoutingTableParser to read routing files (.irt, .mrt).
typedef std::vector<RoutingEntry *> RoutingTable::RouteVector [private] |
RoutingTable::~RoutingTable | ( | ) | [virtual] |
00092 { 00093 for (unsigned int i=0; i<routes.size(); i++) 00094 delete routes[i]; 00095 for (unsigned int i=0; i<multicastRoutes.size(); i++) 00096 delete multicastRoutes[i]; 00097 }
void RoutingTable::addRoutingEntry | ( | RoutingEntry * | entry | ) |
Adds a route to the routing table.
00437 { 00438 Enter_Method("addRoutingEntry(...)"); 00439 00440 // check for null address and default route 00441 if ((entry->host.isUnspecified() || entry->netmask.isUnspecified()) && 00442 (!entry->host.isUnspecified() || !entry->netmask.isUnspecified())) 00443 error("addRoutingEntry(): to add a default route, set both host and netmask to zero"); 00444 00445 // fill in interface ptr from interface name 00446 entry->interfacePtr = ift->interfaceByName(entry->interfaceName.c_str()); 00447 if (!entry->interfacePtr) 00448 error("addRoutingEntry(): interface `%s' doesn't exist", entry->interfaceName.c_str()); 00449 00450 // add to tables 00451 if (!entry->host.isMulticast()) 00452 { 00453 routes.push_back(entry); 00454 } 00455 else 00456 { 00457 multicastRoutes.push_back(entry); 00458 } 00459 00460 #ifdef _MAX_SPEED 00461 routeCache.erase(entry->host.getInt()); 00462 assert(routeCache.count(entry->host.getInt()) == 0); 00463 #endif //_MAX_SPEED 00464 00465 updateDisplayString(); 00466 }
void RoutingTable::autoconfigRouterId | ( | ) | [protected] |
00154 { 00155 if (_routerId.isUnspecified()) // not yet configured 00156 { 00157 const char *routerIdStr = par("routerId").stringValue(); 00158 if (!strcmp(routerIdStr, "auto")) // non-"auto" cases already handled in stage 1 00159 { 00160 // choose highest interface address as routerId 00161 for (int i=0; i<ift->numInterfaces(); ++i) 00162 { 00163 InterfaceEntry *ie = ift->interfaceAt(i); 00164 if (!ie->isLoopback() && ie->ipv4()->inetAddress().getInt() > _routerId.getInt()) 00165 _routerId = ie->ipv4()->inetAddress(); 00166 } 00167 } 00168 } 00169 else // already configured 00170 { 00171 // if there is no interface with routerId yet, assign it to the loopback address; 00172 // TODO find out if this is a good practice, in which situations it is useful etc. 00173 if (interfaceByAddress(_routerId)==NULL) 00174 { 00175 InterfaceEntry *lo0 = ift->firstLoopbackInterface(); 00176 lo0->ipv4()->setInetAddress(_routerId); 00177 lo0->ipv4()->setNetmask(IPAddress::ALLONES_ADDRESS); 00178 } 00179 } 00180 }
void RoutingTable::configureInterfaceForIPv4 | ( | InterfaceEntry * | ie | ) |
00236 { 00237 IPv4InterfaceData *d = new IPv4InterfaceData(); 00238 ie->setIPv4Data(d); 00239 00240 // metric: some hints: OSPF cost (2e9/bps value), MS KB article Q299540, ... 00241 d->setMetric((int)ceil(2e9/ie->datarate())); // use OSPF cost as default 00242 }
void RoutingTable::configureLoopbackForIPv4 | ( | ) | [protected] |
00265 { 00266 InterfaceEntry *ie = ift->firstLoopbackInterface(); 00267 00268 // add IPv4 info. Set 127.0.0.1/8 as address by default -- 00269 // we may reconfigure later it to be the routerId 00270 IPv4InterfaceData *d = new IPv4InterfaceData(); 00271 d->setInetAddress(IPAddress::LOOPBACK_ADDRESS); 00272 d->setNetmask(IPAddress::LOOPBACK_NETMASK); 00273 d->setMetric(1); 00274 ie->setIPv4Data(d); 00275 }
bool RoutingTable::deleteRoutingEntry | ( | RoutingEntry * | entry | ) |
Deletes the given routes from the routing table. Returns true if the route was deleted correctly, false if it was not in the routing table.
00470 { 00471 Enter_Method("deleteRoutingEntry(...)"); 00472 00473 routeCache.clear(); //bad fix, but erase doesn't work 00474 00475 RouteVector::iterator i = std::find(routes.begin(), routes.end(), entry); 00476 if (i!=routes.end()) 00477 { 00478 #ifdef _MAX_SPEED 00479 routeCache.erase(entry->host.getInt()); //buggy 00480 assert(routeCache.count(entry->host.getInt()) == 0); 00481 #endif //_MAX_SPEED 00482 00483 routes.erase(i); 00484 delete entry; 00485 updateDisplayString(); 00486 return true; 00487 } 00488 i = std::find(multicastRoutes.begin(), multicastRoutes.end(), entry); 00489 if (i!=multicastRoutes.end()) 00490 { 00491 #ifdef _MAX_SPEED 00492 routeCache.erase(entry->host.getInt()); 00493 assert(routeCache.count(entry->host.getInt()) == 0); 00494 #endif //_MAX_SPEED 00495 00496 multicastRoutes.erase(i); 00497 delete entry; 00498 updateDisplayString(); 00499 return true; 00500 } 00501 return false; 00502 }
RoutingEntry * RoutingTable::findBestMatchingRoute | ( | const IPAddress & | dest | ) |
The routing function.
00323 { 00324 // find best match (one with longest prefix) 00325 // default route has zero prefix length, so (if exists) it'll be selected as last resort 00326 RoutingEntry *bestRoute = NULL; 00327 uint32 longestNetmask = 0; 00328 00329 #ifdef _MAX_SPEED 00330 RouteHashMap::iterator r = routeCache.find(dest.getInt()); 00331 00332 if(r != routeCache.end()) 00333 return r->second; 00334 #endif //_MAX_SPEED 00335 00336 for (RouteVector::iterator i=routes.begin(); i!=routes.end(); ++i) 00337 { 00338 RoutingEntry *e = *i; 00339 if (IPAddress::maskedAddrAreEqual(dest, e->host, e->netmask) && // match 00340 (!bestRoute || e->netmask.getInt()>longestNetmask)) // longest so far 00341 { 00342 bestRoute = e; 00343 longestNetmask = e->netmask.getInt(); 00344 } 00345 } 00346 00347 #ifdef _MAX_SPEED 00348 routeCache.insert(RouteCacheEntry(dest.getInt(), bestRoute)); 00349 assert(routeCache.count(dest.getInt()) == 1); 00350 #endif //_MAX_SPEED 00351 00352 return bestRoute; 00353 }
RoutingEntry * RoutingTable::findRoutingEntry | ( | const IPAddress & | target, | |
const IPAddress & | netmask, | |||
const IPAddress & | gw, | |||
int | metric = 0 , |
|||
char * | dev = NULL | |||
) |
Find first routing entry with the given parameters.
00428 { 00429 int n = numRoutingEntries(); 00430 for (int i=0; i<n; i++) 00431 if (routingEntryMatches(routingEntry(i), target, netmask, gw, metric, dev)) 00432 return routingEntry(i); 00433 return NULL; 00434 }
Convenience function based on findBestMatchingRoute().
Returns the gateway to send the destination. Returns null address if the destination is not in routing table or there is no gateway (local delivery).
00369 { 00370 #ifndef _MAX_SPEED 00371 Enter_Method("gatewayForDestAddr(%s)=?", dest.str().c_str()); 00372 #else 00373 Enter_Method("gatewayForDestAddr()=?"); 00374 #endif 00375 00376 RoutingEntry *e = findBestMatchingRoute(dest); 00377 if (!e) return IPAddress(); 00378 return e->gateway; 00379 }
std::vector< IPAddress > RoutingTable::gatherAddresses | ( | ) |
Utility function: Returns a vector of all addresses of the node.
00225 { 00226 std::vector<IPAddress> addressvector; 00227 00228 for (int i=0; i<ift->numInterfaces(); ++i) 00229 addressvector.push_back(ift->interfaceAt(i)->ipv4()->inetAddress()); 00230 return addressvector; 00231 }
void RoutingTable::handleMessage | ( | cMessage * | ) | [protected] |
void RoutingTable::initialize | ( | int | stage | ) | [protected] |
00100 { 00101 if (stage==0) 00102 { 00103 // get a pointer to the NotificationBoard module and InterfaceTable 00104 nb = NotificationBoardAccess().get(); 00105 ift = InterfaceTableAccess().get(); 00106 00107 IPForward = par("IPForward").boolValue(); 00108 00109 WATCH_PTRVECTOR(routes); 00110 WATCH_PTRVECTOR(multicastRoutes); 00111 WATCH(IPForward); 00112 WATCH(_routerId); 00113 } 00114 else if (stage==1) 00115 { 00116 // L2 modules register themselves in stage 0, so we can only configure 00117 // the interfaces in stage 1. 00118 const char *filename = par("routingFile"); 00119 00120 // At this point, all L2 modules have registered themselves (added their 00121 // interface entries). Create the per-interface IPv4 data structures. 00122 InterfaceTable *interfaceTable = InterfaceTableAccess().get(); 00123 for (int i=0; i<interfaceTable->numInterfaces(); ++i) 00124 configureInterfaceForIPv4(interfaceTable->interfaceAt(i)); 00125 configureLoopbackForIPv4(); 00126 00127 // read routing table file (and interface configuration) 00128 RoutingTableParser parser(ift, this); 00129 if (*filename && parser.readRoutingTableFromFile(filename)==-1) 00130 error("Error reading routing table file %s", filename); 00131 00132 // set routerId if param is not "" (==no routerId) or "auto" (in which case we'll 00133 // do it later in stage 3, after network configurators configured the interfaces) 00134 const char *routerIdStr = par("routerId").stringValue(); 00135 if (strcmp(routerIdStr, "") && strcmp(routerIdStr, "auto")) 00136 _routerId = IPAddress(routerIdStr); 00137 } 00138 else if (stage==3) 00139 { 00140 // routerID selection must be after stage==2 when network autoconfiguration 00141 // assigns interface addresses 00142 autoconfigRouterId(); 00143 00144 // we don't use notifications during initialize(), so we do it manually. 00145 // Should be in stage=3 because autoconfigurator runs in stage=2. 00146 updateNetmaskRoutes(); 00147 00148 //printIfconfig(); 00149 //printRoutingTable(); 00150 } 00151 }
InterfaceEntry * RoutingTable::interfaceByAddress | ( | const IPAddress & | address | ) |
Returns an interface given by its address. Returns NULL if not found.
00245 { 00246 #ifndef _MAX_SPEED 00247 Enter_Method("interfaceByAddress(%s)=?", addr.str().c_str()); 00248 #else 00249 Enter_Method("interfaceByAddress()=?"); 00250 #endif 00251 00252 if (addr.isUnspecified()) 00253 return NULL; 00254 for (int i=0; i<ift->numInterfaces(); ++i) 00255 { 00256 InterfaceEntry *ie = ift->interfaceAt(i); 00257 if (ie->ipv4()->inetAddress()==addr) 00258 return ie; 00259 } 00260 return NULL; 00261 }
InterfaceEntry * RoutingTable::interfaceForDestAddr | ( | const IPAddress & | dest | ) |
Convenience function based on findBestMatchingRoute().
Returns the interface Id to send the packets with dest as destination address, or -1 if destination is not in routing table.
00356 { 00357 #ifndef _MAX_SPEED 00358 Enter_Method("interfaceForDestAddr(%s)=?", dest.str().c_str()); 00359 #else 00360 Enter_Method("interfaceForDestAddr()=?"); 00361 #endif 00362 00363 RoutingEntry *e = findBestMatchingRoute(dest); 00364 if (!e) return NULL; 00365 return e->interfacePtr; 00366 }
bool RoutingTable::localDeliver | ( | const IPAddress & | dest | ) |
Checks if the address is a local one, i.e. one of the host's.
00280 { 00281 #ifndef _MAX_SPEED 00282 Enter_Method("localDeliver(%s) y/n", dest.str().c_str()); 00283 #else 00284 Enter_Method("localDeliver() y/n"); 00285 #endif 00286 00287 // check if we have an interface with this address 00288 for (int i=0; i<ift->numInterfaces(); i++) 00289 { 00290 InterfaceEntry *ie = ift->interfaceAt(i); 00291 if (dest==ie->ipv4()->inetAddress()) 00292 return true; 00293 #ifdef _MAX_SPEED 00294 else if (i>0) { // ib: ugly speed hack: singlehomed, skip lo0 00295 return false; 00296 } 00297 #endif 00298 00299 } 00300 return false; 00301 }
bool RoutingTable::multicastLocalDeliver | ( | const IPAddress & | dest | ) |
Checks if the address is in one of the local multicast group address list.
00304 { 00305 #ifndef _MAX_SPEED 00306 Enter_Method("multicastLocalDeliver(%s) y/n", dest.str().c_str()); 00307 #else 00308 Enter_Method("multicastLocalDeliver() y/n"); 00309 #endif 00310 00311 for (int i=0; i<ift->numInterfaces(); i++) 00312 { 00313 InterfaceEntry *ie = ift->interfaceAt(i); 00314 for (unsigned int j=0; j < ie->ipv4()->multicastGroups().size(); j++) 00315 if (dest.equals(ie->ipv4()->multicastGroups()[j])) 00316 return true; 00317 } 00318 return false; 00319 }
MulticastRoutes RoutingTable::multicastRoutesFor | ( | const IPAddress & | dest | ) |
Returns routes for a multicast address.
00383 { 00384 #ifndef _MAX_SPEED 00385 Enter_Method("multicastRoutesFor(%s)=?", dest.str().c_str()); 00386 #else 00387 Enter_Method("multicastRoutesFor()=?"); 00388 #endif 00389 00390 MulticastRoutes res; 00391 res.reserve(16); 00392 for (RouteVector::iterator i=multicastRoutes.begin(); i!=multicastRoutes.end(); ++i) 00393 { 00394 RoutingEntry *e = *i; 00395 if (IPAddress::maskedAddrAreEqual(dest, e->host, e->netmask)) 00396 { 00397 MulticastRoute r; 00398 r.interf = ift->interfaceByName(e->interfaceName.c_str()); // Ughhhh 00399 r.gateway = e->gateway; 00400 res.push_back(r); 00401 } 00402 } 00403 return res; 00404 00405 }
int RoutingTable::numRoutingEntries | ( | ) |
Total number of routing entries (unicast, multicast entries and default route).
00409 { 00410 return routes.size()+multicastRoutes.size(); 00411 }
void RoutingTable::printIfconfig | ( | ) |
void RoutingTable::printRoutingTable | ( | ) |
00214 { 00215 EV << "-- Routing table --\n"; 00216 ev.printf("%-16s %-16s %-16s %-3s %s\n", 00217 "Destination", "Gateway", "Netmask", "Iface"); 00218 00219 for (int i=0; i<numRoutingEntries(); i++) 00220 EV << routingEntry(i)->detailedInfo() << "\n"; 00221 EV << "\n"; 00222 }
void RoutingTable::receiveChangeNotification | ( | int | category, | |
cPolymorphic * | details | |||
) | [virtual] |
Called by the NotificationBoard whenever a change of a category occurs to which this client has subscribed.
Implements INotifiable.
00201 { 00202 Enter_Method_Silent(); 00203 printNotificationBanner(category, details); 00204 00205 if (category==NF_IPv4_INTERFACECONFIG_CHANGED) 00206 { 00207 // if anything IPv4-related changes in the interfaces, interface netmask 00208 // based routes have to be re-built. 00209 updateNetmaskRoutes(); 00210 } 00211 }
RoutingEntry * RoutingTable::routingEntry | ( | int | k | ) |
Return kth routing entry.
00414 { 00415 if (k < (int)routes.size()) 00416 return routes[k]; 00417 k -= routes.size(); 00418 if (k < (int)multicastRoutes.size()) 00419 return multicastRoutes[k]; 00420 return NULL; 00421 }
bool RoutingTable::routingEntryMatches | ( | RoutingEntry * | entry, | |
const IPAddress & | target, | |||
const IPAddress & | nmask, | |||
const IPAddress & | gw, | |||
int | metric, | |||
const char * | dev | |||
) | [protected] |
00511 { 00512 if (!target.isUnspecified() && !target.equals(entry->host)) 00513 return false; 00514 if (!nmask.isUnspecified() && !nmask.equals(entry->netmask)) 00515 return false; 00516 if (!gw.isUnspecified() && !gw.equals(entry->gateway)) 00517 return false; 00518 if (metric && metric!=entry->metric) 00519 return false; 00520 if (dev && strcmp(dev, entry->interfaceName.c_str())) 00521 return false; 00522 00523 return true; 00524 }
void RoutingTable::updateDisplayString | ( | ) | [protected] |
00183 { 00184 if (!ev.isGUI()) 00185 return; 00186 00187 char buf[80]; 00188 if (_routerId.isUnspecified()) 00189 sprintf(buf, "%d+%d routes", routes.size(), multicastRoutes.size()); 00190 else 00191 sprintf(buf, "routerId: %s\n%d+%d routes", _routerId.str().c_str(), routes.size(), multicastRoutes.size()); 00192 displayString().setTagArg("t",0,buf); 00193 }
void RoutingTable::updateNetmaskRoutes | ( | ) | [protected] |
00527 { 00528 // first, delete all routes with src=IFACENETMASK 00529 for (unsigned int k=0; k<routes.size(); k++) 00530 if (routes[k]->source==RoutingEntry::IFACENETMASK) 00531 routes.erase(routes.begin()+(k--)); // '--' is necessary because indices shift down 00532 00533 // then re-add them, according to actual interface configuration 00534 for (int i=0; i<ift->numInterfaces(); i++) 00535 { 00536 InterfaceEntry *ie = ift->interfaceAt(i); 00537 if (ie->ipv4()->netmask()!=IPAddress::ALLONES_ADDRESS) 00538 { 00539 RoutingEntry *route = new RoutingEntry(); 00540 route->type = RoutingEntry::DIRECT; 00541 route->source = RoutingEntry::IFACENETMASK; 00542 route->host = ie->ipv4()->inetAddress(); 00543 route->netmask = ie->ipv4()->netmask(); 00544 route->gateway = IPAddress(); 00545 route->metric = ie->ipv4()->metric(); 00546 route->interfaceName = ie->name(); 00547 route->interfacePtr = ie; 00548 routes.push_back(route); 00549 } 00550 } 00551 00552 updateDisplayString(); 00553 }
IPAddress RoutingTable::_routerId [private] |
InterfaceTable* RoutingTable::ift [private] |
bool RoutingTable::IPForward [private] |
RouteVector RoutingTable::multicastRoutes [private] |
NotificationBoard* RoutingTable::nb [private] |
RouteVector RoutingTable::routes [private] |