Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

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.

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 }

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]
 

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 }

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.

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 }

RoutingEntry * RoutingTable::findBestMatchingRoute const IPAddress dest  ) 
 

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 }

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.

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 }

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

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 }

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     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 }

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.

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 }

bool RoutingTable::ipForward  )  [inline]
 

IP forwarding on/off

00221 {return IPForward;}

bool RoutingTable::localDeliver const IPAddress dest  ) 
 

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 }

bool RoutingTable::multicastLocalDeliver const IPAddress dest  ) 
 

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 }

MulticastRoutes RoutingTable::multicastRoutesFor const IPAddress dest  ) 
 

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 }

int RoutingTable::numInitStages  )  const [inline, protected]
 

00187 {return 4;}

int RoutingTable::numRoutingEntries  ) 
 

Total number of routing entries (unicast, multicast entries and default route).

00364 {
00365     return routes.size()+multicastRoutes.size();
00366 }

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.

00226 {return _routerId;}

RoutingEntry * RoutingTable::routingEntry int  k  ) 
 

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 }

bool RoutingTable::routingEntryMatches RoutingEntry entry,
const IPAddress target,
const IPAddress nmask,
const IPAddress gw,
int  metric,
const char *  dev
[protected]
 

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 }

void RoutingTable::setRouterId IPAddress  a  )  [inline]
 

Sets routerId.

00231 {_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]
 

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 }


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 Thu Oct 19 18:22:28 2006 for INET Framework for OMNeT++/OMNEST by  doxygen 1.4.0