RoutingTable Class Reference

#include <RoutingTable.h>

Inheritance diagram for RoutingTable:

INotifiable List of all members.

Detailed Description

Represents the routing table. This object has one instance per host or router. It has methods to manage the route table and the interface table, so one can achieve functionality similar to the "route" and "ifconfig" commands.

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).

See also:
InterfaceEntry, IPv4InterfaceData, RoutingEntry


Public Member Functions

 RoutingTable ()
virtual ~RoutingTable ()
virtual void receiveChangeNotification (int category, cPolymorphic *details)
bool ipForward ()
IPAddress routerId ()
void setRouterId (IPAddress a)
Debug/utility
void printIfconfig ()
void printRoutingTable ()
Interfaces
void configureInterfaceForIPv4 (InterfaceEntry *ie)
InterfaceEntryinterfaceByAddress (const IPAddress &address)
Routing functions (query the route table)
bool localDeliver (const IPAddress &dest)
RoutingEntryfindBestMatchingRoute (const IPAddress &dest)
InterfaceEntryinterfaceForDestAddr (const IPAddress &dest)
IPAddress gatewayForDestAddr (const IPAddress &dest)
Multicast routing functions
bool multicastLocalDeliver (const IPAddress &dest)
MulticastRoutes multicastRoutesFor (const IPAddress &dest)
Route table manipulation
int numRoutingEntries ()
RoutingEntryroutingEntry (int k)
RoutingEntryfindRoutingEntry (const IPAddress &target, const IPAddress &netmask, const IPAddress &gw, int metric=0, char *dev=NULL)
void addRoutingEntry (RoutingEntry *entry)
bool deleteRoutingEntry (RoutingEntry *entry)
std::vector< IPAddressgatherAddresses ()

Protected Member Functions

void configureLoopbackForIPv4 ()
bool routingEntryMatches (RoutingEntry *entry, const IPAddress &target, const IPAddress &nmask, const IPAddress &gw, int metric, const char *dev)
void autoconfigRouterId ()
void updateNetmaskRoutes ()
void updateDisplayString ()
int numInitStages () const
void initialize (int stage)
void handleMessage (cMessage *)

Private Types

typedef std::vector< RoutingEntry * > RouteVector

Private Attributes

InterfaceTableift
NotificationBoardnb
IPAddress _routerId
bool IPForward
RouteVector routes
RouteVector multicastRoutes


Member Typedef Documentation

typedef std::vector<RoutingEntry *> RoutingTable::RouteVector [private]


Constructor & Destructor Documentation

RoutingTable::RoutingTable (  ) 

00088 {
00089 }

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 }


Member Function Documentation

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 }

IPAddress RoutingTable::gatewayForDestAddr ( const IPAddress dest  ) 

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]

Raises an error.

00196 {
00197     opp_error("This module doesn't process messages");
00198 }

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::ipForward (  )  [inline]

IP forwarding on/off

00230 {return IPForward;}

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::numInitStages (  )  const [inline, protected]

00196 {return 4;}

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 }

IPAddress RoutingTable::routerId (  )  [inline]

Returns routerId.

00235 {return _routerId;}

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::setRouterId ( IPAddress  a  )  [inline]

Sets routerId.

00240 {_routerId = a;}

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 }


Member Data Documentation

IPAddress RoutingTable::_routerId [private]

InterfaceTable* RoutingTable::ift [private]

bool RoutingTable::IPForward [private]

RouteVector RoutingTable::multicastRoutes [private]

NotificationBoard* RoutingTable::nb [private]

RouteVector RoutingTable::routes [private]


The documentation for this class was generated from the following files:
Generated on Wed Apr 4 13:20:23 2007 for INET Framework for OMNeT++/OMNEST by  doxygen 1.4.7