#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. 00389 { 00390 Enter_Method("addRoutingEntry(...)"); 00391 00392 // check for null address and default route 00393 if ((entry->host.isUnspecified() || entry->netmask.isUnspecified()) && 00394 (!entry->host.isUnspecified() || !entry->netmask.isUnspecified())) 00395 error("addRoutingEntry(): to add a default route, set both host and netmask to zero"); 00396 00397 // fill in interface ptr from interface name 00398 entry->interfacePtr = ift->interfaceByName(entry->interfaceName.c_str()); 00399 if (!entry->interfacePtr) 00400 error("addRoutingEntry(): interface `%s' doesn't exist", entry->interfaceName.c_str()); 00401 00402 // add to tables 00403 if (!entry->host.isMulticast()) 00404 { 00405 routes.push_back(entry); 00406 } 00407 else 00408 { 00409 multicastRoutes.push_back(entry); 00410 } 00411 00412 updateDisplayString(); 00413 }
|
|
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 }
|
|
00233 { 00234 IPv4InterfaceData *d = new IPv4InterfaceData(); 00235 ie->setIPv4Data(d); 00236 00237 // metric: some hints: OSPF cost (2e9/bps value), MS KB article Q299540, ... 00238 d->setMetric((int)ceil(2e9/ie->datarate())); // use OSPF cost as default 00239 }
|
|
00257 { 00258 InterfaceEntry *ie = ift->firstLoopbackInterface(); 00259 00260 // add IPv4 info. Set 127.0.0.1/8 as address by default -- 00261 // we may reconfigure later it to be the routerId 00262 IPv4InterfaceData *d = new IPv4InterfaceData(); 00263 d->setInetAddress(IPAddress::LOOPBACK_ADDRESS); 00264 d->setNetmask(IPAddress::LOOPBACK_NETMASK); 00265 d->setMetric(1); 00266 ie->setIPv4Data(d); 00267 }
|
|
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. 00417 { 00418 Enter_Method("deleteRoutingEntry(...)"); 00419 00420 RouteVector::iterator i = std::find(routes.begin(), routes.end(), entry); 00421 if (i!=routes.end()) 00422 { 00423 routes.erase(i); 00424 delete entry; 00425 updateDisplayString(); 00426 return true; 00427 } 00428 i = std::find(multicastRoutes.begin(), multicastRoutes.end(), entry); 00429 if (i!=multicastRoutes.end()) 00430 { 00431 multicastRoutes.erase(i); 00432 delete entry; 00433 updateDisplayString(); 00434 return true; 00435 } 00436 return false; 00437 }
|
|
The routing function. 00301 { 00302 // find best match (one with longest prefix) 00303 // default route has zero prefix length, so (if exists) it'll be selected as last resort 00304 RoutingEntry *bestRoute = NULL; 00305 uint32 longestNetmask = 0; 00306 for (RouteVector::iterator i=routes.begin(); i!=routes.end(); ++i) 00307 { 00308 RoutingEntry *e = *i; 00309 if (IPAddress::maskedAddrAreEqual(dest, e->host, e->netmask) && // match 00310 (!bestRoute || e->netmask.getInt()>longestNetmask)) // longest so far 00311 { 00312 bestRoute = e; 00313 longestNetmask = e->netmask.getInt(); 00314 } 00315 } 00316 return bestRoute; 00317 }
|
|
Find first routing entry with the given parameters. 00380 { 00381 int n = numRoutingEntries(); 00382 for (int i=0; i<n; i++) 00383 if (routingEntryMatches(routingEntry(i), target, netmask, gw, metric, dev)) 00384 return routingEntry(i); 00385 return NULL; 00386 }
|
|
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). 00329 { 00330 Enter_Method("gatewayForDestAddr(%s)=?", dest.str().c_str()); 00331 00332 RoutingEntry *e = findBestMatchingRoute(dest); 00333 if (!e) return IPAddress(); 00334 return e->gateway; 00335 }
|
|
Utility function: Returns a vector of all addresses of the node. 00222 { 00223 std::vector<IPAddress> addressvector; 00224 00225 for (int i=0; i<ift->numInterfaces(); ++i) 00226 addressvector.push_back(ift->interfaceAt(i)->ipv4()->inetAddress()); 00227 return addressvector; 00228 }
|
|
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. 00242 { 00243 Enter_Method("interfaceByAddress(%s)=?", addr.str().c_str()); 00244 if (addr.isUnspecified()) 00245 return NULL; 00246 for (int i=0; i<ift->numInterfaces(); ++i) 00247 { 00248 InterfaceEntry *ie = ift->interfaceAt(i); 00249 if (ie->ipv4()->inetAddress()==addr) 00250 return ie; 00251 } 00252 return NULL; 00253 }
|
|
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. 00320 { 00321 Enter_Method("interfaceForDestAddr(%s)=?", dest.str().c_str()); 00322 00323 RoutingEntry *e = findBestMatchingRoute(dest); 00324 if (!e) return NULL; 00325 return e->interfacePtr; 00326 }
|
|
IP forwarding on/off 00221 {return IPForward;}
|
|
Checks if the address is a local one, i.e. one of the host's. 00272 { 00273 Enter_Method("localDeliver(%s) y/n", dest.str().c_str()); 00274 00275 // check if we have an interface with this address 00276 for (int i=0; i<ift->numInterfaces(); i++) 00277 { 00278 InterfaceEntry *ie = ift->interfaceAt(i); 00279 if (dest==ie->ipv4()->inetAddress()) 00280 return true; 00281 } 00282 return false; 00283 }
|
|
Checks if the address is in one of the local multicast group address list. 00286 { 00287 Enter_Method("multicastLocalDeliver(%s) y/n", dest.str().c_str()); 00288 00289 for (int i=0; i<ift->numInterfaces(); i++) 00290 { 00291 InterfaceEntry *ie = ift->interfaceAt(i); 00292 for (unsigned int j=0; j < ie->ipv4()->multicastGroups().size(); j++) 00293 if (dest.equals(ie->ipv4()->multicastGroups()[j])) 00294 return true; 00295 } 00296 return false; 00297 }
|
|
Returns routes for a multicast address. 00339 { 00340 Enter_Method("multicastRoutesFor(%s)=?", dest.str().c_str()); 00341 00342 MulticastRoutes res; 00343 res.reserve(16); 00344 for (RouteVector::iterator i=multicastRoutes.begin(); i!=multicastRoutes.end(); ++i) 00345 { 00346 RoutingEntry *e = *i; 00347 if (IPAddress::maskedAddrAreEqual(dest, e->host, e->netmask)) 00348 { 00349 MulticastRoute r; 00350 r.interf = ift->interfaceByName(e->interfaceName.c_str()); // Ughhhh 00351 r.gateway = e->gateway; 00352 res.push_back(r); 00353 } 00354 } 00355 return res; 00356 00357 }
|
|
00187 {return 4;}
|
|
Total number of routing entries (unicast, multicast entries and default route). 00361 { 00362 return routes.size()+multicastRoutes.size(); 00363 }
|
|
|
|
00211 { 00212 EV << "-- Routing table --\n"; 00213 ev.printf("%-16s %-16s %-16s %-3s %s\n", 00214 "Destination", "Gateway", "Netmask", "Iface"); 00215 00216 for (int i=0; i<numRoutingEntries(); i++) 00217 EV << routingEntry(i)->detailedInfo() << "\n"; 00218 EV << "\n"; 00219 }
|
|
Called by the NotificationBoard whenever a change of a category occurs to which this client has subscribed. Implements INotifiable. 00201 { 00202 if (category==NF_IPv4_INTERFACECONFIG_CHANGED) 00203 { 00204 // if anything IPv4-related changes in the interfaces, interface netmask 00205 // based routes have to be re-built. 00206 updateNetmaskRoutes(); 00207 } 00208 }
|
|
Returns routerId. 00226 {return _routerId;}
|
|
Return kth routing entry. 00366 { 00367 if (k < (int)routes.size()) 00368 return routes[k]; 00369 k -= routes.size(); 00370 if (k < (int)multicastRoutes.size()) 00371 return multicastRoutes[k]; 00372 return NULL; 00373 }
|
|
00446 { 00447 if (!target.isUnspecified() && !target.equals(entry->host)) 00448 return false; 00449 if (!nmask.isUnspecified() && !nmask.equals(entry->netmask)) 00450 return false; 00451 if (!gw.isUnspecified() && !gw.equals(entry->gateway)) 00452 return false; 00453 if (metric && metric!=entry->metric) 00454 return false; 00455 if (dev && strcmp(dev, entry->interfaceName.c_str())) 00456 return false; 00457 00458 return true; 00459 }
|
|
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 }
|
|
00462 { 00463 // first, delete all routes with src=IFACENETMASK 00464 for (unsigned int k=0; k<routes.size(); k++) 00465 if (routes[k]->source==RoutingEntry::IFACENETMASK) 00466 routes.erase(routes.begin()+(k--)); // '--' is necessary because indices shift down 00467 00468 // then re-add them, according to actual interface configuration 00469 for (int i=0; i<ift->numInterfaces(); i++) 00470 { 00471 InterfaceEntry *ie = ift->interfaceAt(i); 00472 if (ie->ipv4()->netmask()!=IPAddress::ALLONES_ADDRESS) 00473 { 00474 RoutingEntry *route = new RoutingEntry(); 00475 route->type = RoutingEntry::DIRECT; 00476 route->source = RoutingEntry::IFACENETMASK; 00477 route->host = ie->ipv4()->inetAddress(); 00478 route->netmask = ie->ipv4()->netmask(); 00479 route->gateway = IPAddress(); 00480 route->metric = ie->ipv4()->metric(); 00481 route->interfaceName = ie->name(); 00482 route->interfacePtr = ie; 00483 routes.push_back(route); 00484 } 00485 } 00486 00487 updateDisplayString(); 00488 }
|
|
|
|
|
|
|
|
|
|
|
|
|