INET Framework for OMNeT++/OMNEST
|
#include <RoutingTable.h>
Public Member Functions | |
RoutingTable () | |
virtual | ~RoutingTable () |
virtual void | printRoutingTable () const |
virtual bool | isIPForwardingEnabled () |
virtual IPAddress | getRouterId () |
virtual void | setRouterId (IPAddress a) |
Interfaces | |
virtual void | configureInterfaceForIPv4 (InterfaceEntry *ie) |
virtual InterfaceEntry * | getInterfaceByAddress (const IPAddress &address) const |
Routing functions (query the route table) | |
virtual bool | isLocalAddress (const IPAddress &dest) const |
virtual const IPRoute * | findBestMatchingRoute (const IPAddress &dest) const |
virtual InterfaceEntry * | getInterfaceForDestAddr (const IPAddress &dest) const |
virtual IPAddress | getGatewayForDestAddr (const IPAddress &dest) const |
Multicast routing functions | |
virtual bool | isLocalMulticastAddress (const IPAddress &dest) const |
virtual MulticastRoutes | getMulticastRoutesFor (const IPAddress &dest) const |
Route table manipulation | |
virtual int | getNumRoutes () const |
virtual const IPRoute * | getRoute (int k) const |
virtual const IPRoute * | findRoute (const IPAddress &target, const IPAddress &netmask, const IPAddress &gw, int metric=0, const char *dev=NULL) const |
virtual const IPRoute * | getDefaultRoute () const |
virtual void | addRoute (const IPRoute *entry) |
virtual bool | deleteRoute (const IPRoute *entry) |
virtual std::vector< IPAddress > | gatherAddresses () const |
Protected Types | |
typedef std::vector< IPRoute * > | RouteVector |
typedef std::map< IPAddress, const IPRoute * > | RoutingCache |
typedef std::set< IPAddress > | AddressSet |
Protected Member Functions | |
virtual void | configureLoopbackForIPv4 () |
virtual bool | routeMatches (const IPRoute *entry, const IPAddress &target, const IPAddress &nmask, const IPAddress &gw, int metric, const char *dev) const |
virtual void | configureRouterId () |
virtual void | updateNetmaskRoutes () |
virtual void | updateDisplayString () |
virtual void | deleteInterfaceRoutes (InterfaceEntry *entry) |
virtual void | invalidateCache () |
virtual int | numInitStages () const |
virtual void | initialize (int stage) |
virtual void | handleMessage (cMessage *) |
virtual void | receiveChangeNotification (int category, const cPolymorphic *details) |
Protected Attributes | |
IInterfaceTable * | ift |
NotificationBoard * | nb |
IPAddress | routerId |
bool | IPForward |
RouteVector | routes |
RouteVector | multicastRoutes |
RoutingCache | routingCache |
AddressSet | localAddresses |
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 IPRoute objects. IPRoute objects can be polymorphic: if a routing protocol needs to store additional data, it can simply subclass from IPRoute, and add the derived object to the table.
Uses RoutingTableParser to read routing files (.irt, .mrt).
typedef std::set<IPAddress> RoutingTable::AddressSet [protected] |
typedef std::vector<IPRoute *> RoutingTable::RouteVector [protected] |
typedef std::map<IPAddress, const IPRoute *> RoutingTable::RoutingCache [protected] |
RoutingTable::RoutingTable | ( | ) |
{ }
RoutingTable::~RoutingTable | ( | ) | [virtual] |
{ for (unsigned int i=0; i<routes.size(); i++) delete routes[i]; for (unsigned int i=0; i<multicastRoutes.size(); i++) delete multicastRoutes[i]; }
void RoutingTable::addRoute | ( | const IPRoute * | entry | ) | [virtual] |
Adds a route to the routing table. Note that once added, routes cannot be modified; you must delete and re-add them instead.
Implements IRoutingTable.
{ Enter_Method("addRoute(...)"); // check for null address and default route if (entry->getHost().isUnspecified() != entry->getNetmask().isUnspecified()) error("addRoute(): to add a default route, set both host and netmask to zero"); if (entry->getHost().doAnd(entry->getNetmask().isUnspecified()).getInt() != 0) error("addRoute(): suspicious route: host %s has 1-bits outside netmask %s", entry->getHost().str().c_str(), entry->getNetmask().str().c_str()); // check that the interface exists if (!entry->getInterface()) error("addRoute(): interface cannot be NULL"); // if this is a default route, remove old default route (we're replacing it) if (entry->getNetmask().isUnspecified() && getDefaultRoute()!=NULL) deleteRoute(getDefaultRoute()); // add to tables if (!entry->getHost().isMulticast()) routes.push_back(const_cast<IPRoute*>(entry)); else multicastRoutes.push_back(const_cast<IPRoute*>(entry)); invalidateCache(); updateDisplayString(); nb->fireChangeNotification(NF_IPv4_ROUTE_ADDED, entry); }
void RoutingTable::configureInterfaceForIPv4 | ( | InterfaceEntry * | ie | ) | [virtual] |
Implements IRoutingTable.
Referenced by initialize().
{ IPv4InterfaceData *d = new IPv4InterfaceData(); ie->setIPv4Data(d); // metric: some hints: OSPF cost (2e9/bps value), MS KB article Q299540, ... d->setMetric((int)ceil(2e9/ie->getDatarate())); // use OSPF cost as default }
void RoutingTable::configureLoopbackForIPv4 | ( | ) | [protected, virtual] |
Referenced by initialize().
{ InterfaceEntry *ie = ift->getFirstLoopbackInterface(); // add IPv4 info. Set 127.0.0.1/8 as address by default -- // we may reconfigure later it to be the routerId IPv4InterfaceData *d = new IPv4InterfaceData(); d->setIPAddress(IPAddress::LOOPBACK_ADDRESS); d->setNetmask(IPAddress::LOOPBACK_NETMASK); d->setMetric(1); ie->setIPv4Data(d); }
void RoutingTable::configureRouterId | ( | ) | [protected, virtual] |
Referenced by initialize().
{ if (routerId.isUnspecified()) // not yet configured { const char *routerIdStr = par("routerId").stringValue(); if (!strcmp(routerIdStr, "auto")) // non-"auto" cases already handled in stage 1 { // choose highest interface address as routerId for (int i=0; i<ift->getNumInterfaces(); ++i) { InterfaceEntry *ie = ift->getInterface(i); if (!ie->isLoopback() && ie->ipv4Data()->getIPAddress().getInt() > routerId.getInt()) routerId = ie->ipv4Data()->getIPAddress(); } } } else // already configured { // if there is no interface with routerId yet, assign it to the loopback address; // TODO find out if this is a good practice, in which situations it is useful etc. if (getInterfaceByAddress(routerId)==NULL) { InterfaceEntry *lo0 = ift->getFirstLoopbackInterface(); lo0->ipv4Data()->setIPAddress(routerId); lo0->ipv4Data()->setNetmask(IPAddress::ALLONES_ADDRESS); } } }
void RoutingTable::deleteInterfaceRoutes | ( | InterfaceEntry * | entry | ) | [protected, virtual] |
Referenced by receiveChangeNotification().
{ RouteVector::iterator it = routes.begin(); while (it != routes.end()) { IPRoute *route = *it; if (route->getInterface() == entry) { deleteRoute(route); it = routes.begin(); // iterator became invalid -- start over } else { ++it; } } }
bool RoutingTable::deleteRoute | ( | const IPRoute * | entry | ) | [virtual] |
Deletes the given route from the routing table. Returns true if the route was deleted correctly, false if it was not in the routing table.
Implements IRoutingTable.
Referenced by addRoute(), and deleteInterfaceRoutes().
{ Enter_Method("deleteRoute(...)"); RouteVector::iterator i = std::find(routes.begin(), routes.end(), entry); if (i!=routes.end()) { nb->fireChangeNotification(NF_IPv4_ROUTE_DELETED, entry); // rather: going to be deleted routes.erase(i); delete entry; invalidateCache(); updateDisplayString(); return true; } i = std::find(multicastRoutes.begin(), multicastRoutes.end(), entry); if (i!=multicastRoutes.end()) { nb->fireChangeNotification(NF_IPv4_ROUTE_DELETED, entry); // rather: going to be deleted multicastRoutes.erase(i); delete entry; invalidateCache(); updateDisplayString(); return true; } return false; }
The routing function.
Implements IRoutingTable.
Referenced by getGatewayForDestAddr(), and getInterfaceForDestAddr().
{ Enter_Method("findBestMatchingRoute(%u.%u.%u.%u)", dest.getDByte(0), dest.getDByte(1), dest.getDByte(2), dest.getDByte(3)); // note: str().c_str() too slow here RoutingCache::iterator it = routingCache.find(dest); if (it != routingCache.end()) return it->second; // find best match (one with longest prefix) // default route has zero prefix length, so (if exists) it'll be selected as last resort const IPRoute *bestRoute = NULL; uint32 longestNetmask = 0; for (RouteVector::const_iterator i=routes.begin(); i!=routes.end(); ++i) { const IPRoute *e = *i; if (IPAddress::maskedAddrAreEqual(dest, e->getHost(), e->getNetmask()) && // match (!bestRoute || e->getNetmask().getInt() > longestNetmask)) // longest so far { bestRoute = e; longestNetmask = e->getNetmask().getInt(); } } routingCache[dest] = bestRoute; return bestRoute; }
const IPRoute * RoutingTable::findRoute | ( | const IPAddress & | target, |
const IPAddress & | netmask, | ||
const IPAddress & | gw, | ||
int | metric = 0 , |
||
const char * | dev = NULL |
||
) | const [virtual] |
Finds the first route with the given parameters.
Implements IRoutingTable.
{ int n = getNumRoutes(); for (int i=0; i<n; i++) if (routeMatches(getRoute(i), target, netmask, gw, metric, dev)) return getRoute(i); return NULL; }
std::vector< IPAddress > RoutingTable::gatherAddresses | ( | ) | const [virtual] |
Utility function: Returns a vector of all addresses of the node.
Implements IRoutingTable.
{ std::vector<IPAddress> addressvector; for (int i=0; i<ift->getNumInterfaces(); ++i) addressvector.push_back(ift->getInterface(i)->ipv4Data()->getIPAddress()); return addressvector; }
const IPRoute * RoutingTable::getDefaultRoute | ( | ) | const [virtual] |
Finds and returns the default route, or NULL if it doesn't exist
Implements IRoutingTable.
Referenced by addRoute().
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).
Implements IRoutingTable.
InterfaceEntry * RoutingTable::getInterfaceByAddress | ( | const IPAddress & | address | ) | const [virtual] |
Returns an interface given by its address. Returns NULL if not found.
Implements IRoutingTable.
Referenced by configureRouterId().
{ Enter_Method("getInterfaceByAddress(%u.%u.%u.%u)", addr.getDByte(0), addr.getDByte(1), addr.getDByte(2), addr.getDByte(3)); // note: str().c_str() too slow here if (addr.isUnspecified()) return NULL; for (int i=0; i<ift->getNumInterfaces(); ++i) { InterfaceEntry *ie = ift->getInterface(i); if (ie->ipv4Data()->getIPAddress()==addr) return ie; } return NULL; }
InterfaceEntry * RoutingTable::getInterfaceForDestAddr | ( | const IPAddress & | dest | ) | const [virtual] |
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.
Implements IRoutingTable.
MulticastRoutes RoutingTable::getMulticastRoutesFor | ( | const IPAddress & | dest | ) | const [virtual] |
Returns routes for a multicast address.
Implements IRoutingTable.
{ Enter_Method("getMulticastRoutesFor(%u.%u.%u.%u)", dest.getDByte(0), dest.getDByte(1), dest.getDByte(2), dest.getDByte(3)); // note: str().c_str() too slow here here MulticastRoutes res; res.reserve(16); for (RouteVector::const_iterator i=multicastRoutes.begin(); i!=multicastRoutes.end(); ++i) { const IPRoute *e = *i; if (IPAddress::maskedAddrAreEqual(dest, e->getHost(), e->getNetmask())) { MulticastRoute r; r.interf = e->getInterface(); r.gateway = e->getGateway(); res.push_back(r); } } return res; }
int RoutingTable::getNumRoutes | ( | ) | const [virtual] |
Returns the total number of routes (unicast, multicast, plus the default route).
Implements IRoutingTable.
Referenced by findRoute(), and printRoutingTable().
{ return routes.size()+multicastRoutes.size(); }
const IPRoute * RoutingTable::getRoute | ( | int | k | ) | const [virtual] |
Returns the kth route. The returned route cannot be modified; you must delete and re-add it instead. This rule is emphasized by returning a const pointer.
Implements IRoutingTable.
Referenced by findRoute(), and printRoutingTable().
{ if (k < (int)routes.size()) return routes[k]; k -= routes.size(); if (k < (int)multicastRoutes.size()) return multicastRoutes[k]; return NULL; }
virtual IPAddress RoutingTable::getRouterId | ( | ) | [inline, virtual] |
void RoutingTable::handleMessage | ( | cMessage * | msg | ) | [protected, virtual] |
Raises an error.
{
opp_error("This module doesn't process messages");
}
void RoutingTable::initialize | ( | int | stage | ) | [protected, virtual] |
{ if (stage==0) { // get a pointer to the NotificationBoard module and IInterfaceTable nb = NotificationBoardAccess().get(); ift = InterfaceTableAccess().get(); IPForward = par("IPForward").boolValue(); nb->subscribe(this, NF_INTERFACE_CREATED); nb->subscribe(this, NF_INTERFACE_DELETED); nb->subscribe(this, NF_INTERFACE_STATE_CHANGED); nb->subscribe(this, NF_INTERFACE_CONFIG_CHANGED); nb->subscribe(this, NF_INTERFACE_IPv4CONFIG_CHANGED); WATCH_PTRVECTOR(routes); WATCH_PTRVECTOR(multicastRoutes); WATCH(IPForward); WATCH(routerId); } else if (stage==1) { // L2 modules register themselves in stage 0, so we can only configure // the interfaces in stage 1. const char *filename = par("routingFile"); // At this point, all L2 modules have registered themselves (added their // interface entries). Create the per-interface IPv4 data structures. IInterfaceTable *interfaceTable = InterfaceTableAccess().get(); for (int i=0; i<interfaceTable->getNumInterfaces(); ++i) configureInterfaceForIPv4(interfaceTable->getInterface(i)); configureLoopbackForIPv4(); // read routing table file (and interface configuration) RoutingTableParser parser(ift, this); if (*filename && parser.readRoutingTableFromFile(filename)==-1) error("Error reading routing table file %s", filename); // set routerId if param is not "" (==no routerId) or "auto" (in which case we'll // do it later in stage 3, after network configurators configured the interfaces) const char *routerIdStr = par("routerId").stringValue(); if (strcmp(routerIdStr, "") && strcmp(routerIdStr, "auto")) routerId = IPAddress(routerIdStr); } else if (stage==3) { // routerID selection must be after stage==2 when network autoconfiguration // assigns interface addresses configureRouterId(); // we don't use notifications during initialize(), so we do it manually. // Should be in stage=3 because autoconfigurator runs in stage=2. updateNetmaskRoutes(); //printRoutingTable(); } }
void RoutingTable::invalidateCache | ( | ) | [protected, virtual] |
Referenced by addRoute(), deleteRoute(), receiveChangeNotification(), and updateNetmaskRoutes().
{ routingCache.clear(); localAddresses.clear(); }
virtual bool RoutingTable::isIPForwardingEnabled | ( | ) | [inline, virtual] |
bool RoutingTable::isLocalAddress | ( | const IPAddress & | dest | ) | const [virtual] |
Checks if the address is a local one, i.e. one of the host's.
Implements IRoutingTable.
{ Enter_Method("isLocalAddress(%u.%u.%u.%u)", dest.getDByte(0), dest.getDByte(1), dest.getDByte(2), dest.getDByte(3)); // note: str().c_str() too slow here if (localAddresses.empty()) { // collect interface addresses if not yet done for (int i=0; i<ift->getNumInterfaces(); i++) { IPAddress interfaceAddr = ift->getInterface(i)->ipv4Data()->getIPAddress(); localAddresses.insert(interfaceAddr); } } AddressSet::iterator it = localAddresses.find(dest); return it!=localAddresses.end(); }
bool RoutingTable::isLocalMulticastAddress | ( | const IPAddress & | dest | ) | const [virtual] |
Checks if the address is in one of the local multicast group address list.
Implements IRoutingTable.
{ Enter_Method("isLocalMulticastAddress(%u.%u.%u.%u)", dest.getDByte(0), dest.getDByte(1), dest.getDByte(2), dest.getDByte(3)); // note: str().c_str() too slow here for (int i=0; i<ift->getNumInterfaces(); i++) { InterfaceEntry *ie = ift->getInterface(i); if (ie->ipv4Data()->isMemberOfMulticastGroup(dest)) return true; } return false; }
virtual int RoutingTable::numInitStages | ( | ) | const [inline, protected, virtual] |
{return 4;}
void RoutingTable::printRoutingTable | ( | ) | const [virtual] |
For debugging
Implements IRoutingTable.
{ EV << "-- Routing table --\n"; ev.printf("%-16s %-16s %-16s %-3s %s\n", "Destination", "Gateway", "Netmask", "Iface"); for (int i=0; i<getNumRoutes(); i++) EV << getRoute(i)->detailedInfo() << "\n"; EV << "\n"; }
void RoutingTable::receiveChangeNotification | ( | int | category, |
const cPolymorphic * | details | ||
) | [protected, virtual] |
Called by the NotificationBoard whenever a change of a category occurs to which this client has subscribed.
Implements INotifiable.
{ if (simulation.getContextType()==CTX_INITIALIZE) return; // ignore notifications during initialize Enter_Method_Silent(); printNotificationBanner(category, details); if (category==NF_INTERFACE_CREATED) { // add netmask route for the new interface updateNetmaskRoutes(); } else if (category==NF_INTERFACE_DELETED) { // remove all routes that point to that interface InterfaceEntry *entry = check_and_cast<InterfaceEntry*>(details); deleteInterfaceRoutes(entry); } else if (category==NF_INTERFACE_STATE_CHANGED) { invalidateCache(); } else if (category==NF_INTERFACE_CONFIG_CHANGED) { invalidateCache(); } else if (category==NF_INTERFACE_IPv4CONFIG_CHANGED) { // if anything IPv4-related changes in the interfaces, interface netmask // based routes have to be re-built. updateNetmaskRoutes(); } }
bool RoutingTable::routeMatches | ( | const IPRoute * | entry, |
const IPAddress & | target, | ||
const IPAddress & | nmask, | ||
const IPAddress & | gw, | ||
int | metric, | ||
const char * | dev | ||
) | const [protected, virtual] |
Referenced by findRoute().
{ if (!target.isUnspecified() && !target.equals(entry->getHost())) return false; if (!nmask.isUnspecified() && !nmask.equals(entry->getNetmask())) return false; if (!gw.isUnspecified() && !gw.equals(entry->getGateway())) return false; if (metric && metric!=entry->getMetric()) return false; if (dev && strcmp(dev, entry->getInterfaceName())) return false; return true; }
virtual void RoutingTable::setRouterId | ( | IPAddress | a | ) | [inline, virtual] |
void RoutingTable::updateDisplayString | ( | ) | [protected, virtual] |
Referenced by addRoute(), deleteRoute(), and updateNetmaskRoutes().
{ if (!ev.isGUI()) return; std::stringstream os; if (!routerId.isUnspecified()) os << "routerId: " << routerId <<"\n"; os << "" << routes.size() << "+" << multicastRoutes.size() << " routes"; getDisplayString().setTagArg("t", 0, os.str().c_str()); }
void RoutingTable::updateNetmaskRoutes | ( | ) | [protected, virtual] |
Referenced by initialize(), and receiveChangeNotification().
{ // first, delete all routes with src=IFACENETMASK for (unsigned int k=0; k<routes.size(); k++) if (routes[k]->getSource()==IPRoute::IFACENETMASK) routes.erase(routes.begin()+(k--)); // '--' is necessary because indices shift down // then re-add them, according to actual interface configuration for (int i=0; i<ift->getNumInterfaces(); i++) { InterfaceEntry *ie = ift->getInterface(i); if (ie->ipv4Data()->getNetmask()!=IPAddress::ALLONES_ADDRESS) { IPRoute *route = new IPRoute(); route->setType(IPRoute::DIRECT); route->setSource(IPRoute::IFACENETMASK); route->setHost(ie->ipv4Data()->getIPAddress()); route->setNetmask(ie->ipv4Data()->getNetmask()); route->setGateway(IPAddress()); route->setMetric(ie->ipv4Data()->getMetric()); route->setInterface(ie); routes.push_back(route); } } invalidateCache(); updateDisplayString(); }
IInterfaceTable* RoutingTable::ift [protected] |
bool RoutingTable::IPForward [protected] |
Referenced by initialize().
AddressSet RoutingTable::localAddresses [mutable, protected] |
Referenced by invalidateCache(), and isLocalAddress().
RouteVector RoutingTable::multicastRoutes [protected] |
Referenced by addRoute(), deleteRoute(), getMulticastRoutesFor(), getNumRoutes(), getRoute(), initialize(), updateDisplayString(), and ~RoutingTable().
NotificationBoard* RoutingTable::nb [protected] |
Referenced by addRoute(), deleteRoute(), and initialize().
IPAddress RoutingTable::routerId [protected] |
Referenced by configureRouterId(), initialize(), and updateDisplayString().
RouteVector RoutingTable::routes [protected] |
RoutingCache RoutingTable::routingCache [mutable, protected] |
Referenced by findBestMatchingRoute(), and invalidateCache().