#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).
|
|
|
00088 { 00089 }
|
|
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 }
|
|
Adds a route to the routing table. 00392 { 00393 Enter_Method("addRoutingEntry(...)"); 00394 00395 // check for null address and default route 00396 if ((entry->host.isUnspecified() || entry->netmask.isUnspecified()) && 00397 (!entry->host.isUnspecified() || !entry->netmask.isUnspecified())) 00398 error("addRoutingEntry(): to add a default route, set both host and netmask to zero"); 00399 00400 // fill in interface ptr from interface name 00401 entry->interfacePtr = ift->interfaceByName(entry->interfaceName.c_str()); 00402 if (!entry->interfacePtr) 00403 error("addRoutingEntry(): interface `%s' doesn't exist", entry->interfaceName.c_str()); 00404 00405 // add to tables 00406 if (!entry->host.isMulticast()) 00407 { 00408 routes.push_back(entry); 00409 } 00410 else 00411 { 00412 multicastRoutes.push_back(entry); 00413 } 00414 00415 updateDisplayString(); 00416 }
|
|
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 }
|
|
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 }
|
|
00260 { 00261 InterfaceEntry *ie = ift->firstLoopbackInterface(); 00262 00263 // add IPv4 info. Set 127.0.0.1/8 as address by default -- 00264 // we may reconfigure later it to be the routerId 00265 IPv4InterfaceData *d = new IPv4InterfaceData(); 00266 d->setInetAddress(IPAddress::LOOPBACK_ADDRESS); 00267 d->setNetmask(IPAddress::LOOPBACK_NETMASK); 00268 d->setMetric(1); 00269 ie->setIPv4Data(d); 00270 }
|
|
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. 00420 { 00421 Enter_Method("deleteRoutingEntry(...)"); 00422 00423 RouteVector::iterator i = std::find(routes.begin(), routes.end(), entry); 00424 if (i!=routes.end()) 00425 { 00426 routes.erase(i); 00427 delete entry; 00428 updateDisplayString(); 00429 return true; 00430 } 00431 i = std::find(multicastRoutes.begin(), multicastRoutes.end(), entry); 00432 if (i!=multicastRoutes.end()) 00433 { 00434 multicastRoutes.erase(i); 00435 delete entry; 00436 updateDisplayString(); 00437 return true; 00438 } 00439 return false; 00440 }
|
|
The routing function. 00304 { 00305 // find best match (one with longest prefix) 00306 // default route has zero prefix length, so (if exists) it'll be selected as last resort 00307 RoutingEntry *bestRoute = NULL; 00308 uint32 longestNetmask = 0; 00309 for (RouteVector::iterator i=routes.begin(); i!=routes.end(); ++i) 00310 { 00311 RoutingEntry *e = *i; 00312 if (IPAddress::maskedAddrAreEqual(dest, e->host, e->netmask) && // match 00313 (!bestRoute || e->netmask.getInt()>longestNetmask)) // longest so far 00314 { 00315 bestRoute = e; 00316 longestNetmask = e->netmask.getInt(); 00317 } 00318 } 00319 return bestRoute; 00320 }
|
|
Find first routing entry with the given parameters. 00383 { 00384 int n = numRoutingEntries(); 00385 for (int i=0; i<n; i++) 00386 if (routingEntryMatches(routingEntry(i), target, netmask, gw, metric, dev)) 00387 return routingEntry(i); 00388 return NULL; 00389 }
|
|
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). 00332 { 00333 Enter_Method("gatewayForDestAddr(%s)=?", dest.str().c_str()); 00334 00335 RoutingEntry *e = findBestMatchingRoute(dest); 00336 if (!e) return IPAddress(); 00337 return e->gateway; 00338 }
|
|
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 }
|
|
Raises an error. 00196 {
00197 opp_error("This module doesn't process messages");
00198 }
|
|
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 }
|
|
Returns an interface given by its address. Returns NULL if not found. 00245 { 00246 Enter_Method("interfaceByAddress(%s)=?", addr.str().c_str()); 00247 if (addr.isUnspecified()) 00248 return NULL; 00249 for (int i=0; i<ift->numInterfaces(); ++i) 00250 { 00251 InterfaceEntry *ie = ift->interfaceAt(i); 00252 if (ie->ipv4()->inetAddress()==addr) 00253 return ie; 00254 } 00255 return NULL; 00256 }
|
|
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. 00323 { 00324 Enter_Method("interfaceForDestAddr(%s)=?", dest.str().c_str()); 00325 00326 RoutingEntry *e = findBestMatchingRoute(dest); 00327 if (!e) return NULL; 00328 return e->interfacePtr; 00329 }
|
|
IP forwarding on/off 00221 {return IPForward;}
|
|
Checks if the address is a local one, i.e. one of the host's. 00275 { 00276 Enter_Method("localDeliver(%s) y/n", dest.str().c_str()); 00277 00278 // check if we have an interface with this address 00279 for (int i=0; i<ift->numInterfaces(); i++) 00280 { 00281 InterfaceEntry *ie = ift->interfaceAt(i); 00282 if (dest==ie->ipv4()->inetAddress()) 00283 return true; 00284 } 00285 return false; 00286 }
|
|
Checks if the address is in one of the local multicast group address list. 00289 { 00290 Enter_Method("multicastLocalDeliver(%s) y/n", dest.str().c_str()); 00291 00292 for (int i=0; i<ift->numInterfaces(); i++) 00293 { 00294 InterfaceEntry *ie = ift->interfaceAt(i); 00295 for (unsigned int j=0; j < ie->ipv4()->multicastGroups().size(); j++) 00296 if (dest.equals(ie->ipv4()->multicastGroups()[j])) 00297 return true; 00298 } 00299 return false; 00300 }
|
|
Returns routes for a multicast address. 00342 { 00343 Enter_Method("multicastRoutesFor(%s)=?", dest.str().c_str()); 00344 00345 MulticastRoutes res; 00346 res.reserve(16); 00347 for (RouteVector::iterator i=multicastRoutes.begin(); i!=multicastRoutes.end(); ++i) 00348 { 00349 RoutingEntry *e = *i; 00350 if (IPAddress::maskedAddrAreEqual(dest, e->host, e->netmask)) 00351 { 00352 MulticastRoute r; 00353 r.interf = ift->interfaceByName(e->interfaceName.c_str()); // Ughhhh 00354 r.gateway = e->gateway; 00355 res.push_back(r); 00356 } 00357 } 00358 return res; 00359 00360 }
|
|
00187 {return 4;}
|
|
Total number of routing entries (unicast, multicast entries and default route). 00364 { 00365 return routes.size()+multicastRoutes.size(); 00366 }
|
|
|
|
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 }
|
|
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 }
|
|
Returns routerId. 00226 {return _routerId;}
|
|
Return kth routing entry. 00369 { 00370 if (k < (int)routes.size()) 00371 return routes[k]; 00372 k -= routes.size(); 00373 if (k < (int)multicastRoutes.size()) 00374 return multicastRoutes[k]; 00375 return NULL; 00376 }
|
|
00449 { 00450 if (!target.isUnspecified() && !target.equals(entry->host)) 00451 return false; 00452 if (!nmask.isUnspecified() && !nmask.equals(entry->netmask)) 00453 return false; 00454 if (!gw.isUnspecified() && !gw.equals(entry->gateway)) 00455 return false; 00456 if (metric && metric!=entry->metric) 00457 return false; 00458 if (dev && strcmp(dev, entry->interfaceName.c_str())) 00459 return false; 00460 00461 return true; 00462 }
|
|
Sets routerId. 00231 {_routerId = a;}
|
|
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 }
|
|
00465 { 00466 // first, delete all routes with src=IFACENETMASK 00467 for (unsigned int k=0; k<routes.size(); k++) 00468 if (routes[k]->source==RoutingEntry::IFACENETMASK) 00469 routes.erase(routes.begin()+(k--)); // '--' is necessary because indices shift down 00470 00471 // then re-add them, according to actual interface configuration 00472 for (int i=0; i<ift->numInterfaces(); i++) 00473 { 00474 InterfaceEntry *ie = ift->interfaceAt(i); 00475 if (ie->ipv4()->netmask()!=IPAddress::ALLONES_ADDRESS) 00476 { 00477 RoutingEntry *route = new RoutingEntry(); 00478 route->type = RoutingEntry::DIRECT; 00479 route->source = RoutingEntry::IFACENETMASK; 00480 route->host = ie->ipv4()->inetAddress(); 00481 route->netmask = ie->ipv4()->netmask(); 00482 route->gateway = IPAddress(); 00483 route->metric = ie->ipv4()->metric(); 00484 route->interfaceName = ie->name(); 00485 route->interfacePtr = ie; 00486 routes.push_back(route); 00487 } 00488 } 00489 00490 updateDisplayString(); 00491 }
|
|
|
|
|
|
|
|
|
|
|
|
|