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.

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 }

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  ) 
 

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 }

void RoutingTable::configureLoopbackForIPv4  )  [protected]
 

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 }

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.

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 }

RoutingEntry * RoutingTable::findBestMatchingRoute const IPAddress dest  ) 
 

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 }

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.

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 }

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

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 }

std::vector< IPAddress > RoutingTable::gatherAddresses  ) 
 

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 }

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.

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 }

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.

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 }

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.

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 }

bool RoutingTable::multicastLocalDeliver const IPAddress dest  ) 
 

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 }

MulticastRoutes RoutingTable::multicastRoutesFor const IPAddress dest  ) 
 

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 }

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

00187 {return 4;}

int RoutingTable::numRoutingEntries  ) 
 

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

00361 {
00362     return routes.size()+multicastRoutes.size();
00363 }

void RoutingTable::printIfconfig  ) 
 

void RoutingTable::printRoutingTable  ) 
 

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 }

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

IPAddress RoutingTable::routerId  )  [inline]
 

Returns routerId.

00226 {return _routerId;}

RoutingEntry * RoutingTable::routingEntry int  k  ) 
 

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 }

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

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 }

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]
 

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 }


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 Sat Apr 1 20:52:23 2006 for INET Framework for OMNeT++/OMNEST by  doxygen 1.4.1