INET Framework for OMNeT++/OMNEST
inet::RIPRouting Class Reference

Implementation of the Routing Information Protocol. More...

#include <RIPRouting.h>

Inheritance diagram for inet::RIPRouting:
inet::ILifecycle

Public Member Functions

 RIPRouting ()
 
 ~RIPRouting ()
 
- Public Member Functions inherited from inet::ILifecycle
virtual ~ILifecycle ()
 

Protected Member Functions

virtual int numInitStages () const override
 
virtual void initialize (int stage) override
 
virtual void handleMessage (cMessage *msg) override
 
virtual void receiveSignal (cComponent *source, simsignal_t signalID, cObject *obj, cObject *details) override
 Listen on interface/route changes and update private data structures. More...
 
virtual bool handleOperationStage (LifecycleOperation *operation, int stage, IDoneCallback *doneCallback) override
 Perform one stage of a lifecycle operation. More...
 
virtual void startRIPRouting ()
 
virtual void stopRIPRouting ()
 
virtual void configureInterfaces (cXMLElement *config)
 Creates a RIPInterfaceEntry for each interface found in the interface table. More...
 
virtual void configureInitialRoutes ()
 Import interface/static/default routes from the routing table. More...
 
virtual RIPRouteimportRoute (IRoute *route, RIPRoute::RouteType type, int metric=1, uint16 routeTag=0)
 Adds a new route the RIP routing table for an existing IRoute. More...
 
virtual void sendRIPRequest (const RIPInterfaceEntry &ripInterface)
 Sends a RIP request to routers on the specified link. More...
 
virtual void processRequest (RIPPacket *packet)
 Processes a request received from a RIP router or a monitoring process. More...
 
virtual void processUpdate (bool triggered)
 This method called when a triggered or regular update timer expired. More...
 
virtual void sendRoutes (const L3Address &address, int port, const RIPInterfaceEntry &ripInterface, bool changedOnly)
 Send all or changed part of the routing table to address/port on the specified interface. More...
 
virtual void processResponse (RIPPacket *packet)
 Processes the RIP response and updates the routing table. More...
 
virtual bool isValidResponse (RIPPacket *packet)
 
virtual void addRoute (const L3Address &dest, int prefixLength, const InterfaceEntry *ie, const L3Address &nextHop, int metric, uint16 routeTag, const L3Address &from)
 RFC 2453 3.9.2: More...
 
virtual void updateRoute (RIPRoute *route, const InterfaceEntry *ie, const L3Address &nextHop, int metric, uint16 routeTag, const L3Address &from)
 Updates an existing route with the information learned from a RIP packet. More...
 
virtual void triggerUpdate ()
 Sets the update timer to trigger an update in the [1s,5s] interval. More...
 
virtual RIPRoutecheckRouteIsExpired (RIPRoute *route)
 Should be called regularly to handle expiry and purge of routes. More...
 
virtual void invalidateRoute (RIPRoute *route)
 
virtual void purgeRoute (RIPRoute *route)
 Removes the route from the routing table. More...
 
virtual void sendPacket (RIPPacket *packet, const L3Address &destAddr, int destPort, const InterfaceEntry *destInterface)
 Sends the packet to the specified destination. More...
 

Private Types

enum  Mode { RIPv2, RIPng }
 
typedef std::vector< RIPInterfaceEntryInterfaceVector
 
typedef std::vector< RIPRoute * > RouteVector
 

Private Member Functions

RIPInterfaceEntryfindInterfaceById (int interfaceId)
 
RIPRoutefindRoute (const L3Address &destAddress, int prefixLength)
 
RIPRoutefindRoute (const L3Address &destination, int prefixLength, RIPRoute::RouteType type)
 
RIPRoutefindRoute (const IRoute *route)
 
RIPRoutefindRoute (const InterfaceEntry *ie, RIPRoute::RouteType type)
 
void addInterface (const InterfaceEntry *ie, cXMLElement *config)
 
void deleteInterface (const InterfaceEntry *ie)
 
void invalidateRoutes (const InterfaceEntry *ie)
 
IRouteaddRoute (const L3Address &dest, int prefixLength, const InterfaceEntry *ie, const L3Address &nextHop, int metric)
 
void deleteRoute (IRoute *route)
 
bool isLoopbackInterfaceRoute (const IRoute *route)
 
bool isLocalInterfaceRoute (const IRoute *route)
 
bool isDefaultRoute (const IRoute *route)
 
std::string getHostName ()
 
int getInterfaceMetric (InterfaceEntry *ie)
 

Private Attributes

cModule * host = nullptr
 
IInterfaceTableift = nullptr
 
IRoutingTablert = nullptr
 
IL3AddressTypeaddressType = nullptr
 
InterfaceVector ripInterfaces
 
RouteVector ripRoutes
 
UDPSocket socket
 
cMessage * updateTimer = nullptr
 
cMessage * triggeredUpdateTimer = nullptr
 
cMessage * startupTimer = nullptr
 
cMessage * shutdownTimer = nullptr
 
Mode mode = (Mode)-1
 
int ripUdpPort = -1
 
simtime_t updateInterval
 
simtime_t routeExpiryTime
 
simtime_t routePurgeTime
 
simtime_t shutdownTime
 
bool isOperational = false
 

Static Private Attributes

static simsignal_t sentRequestSignal = registerSignal("sentRequest")
 
static simsignal_t sentUpdateSignal = registerSignal("sentUpdate")
 
static simsignal_t rcvdResponseSignal = registerSignal("rcvdResponse")
 
static simsignal_t badResponseSignal = registerSignal("badResponse")
 
static simsignal_t numRoutesSignal = registerSignal("numRoutes")
 

Detailed Description

Implementation of the Routing Information Protocol.

This module supports RIPv2 (RFC 2453) and RIPng (RFC 2080).

RIP is a distance vector routing protocol. Each RIP router periodically sends its whole routing table to neighbor routers, and updates its own routing table according to the received information. If a route changed the router might send a notification to its neighbors immediately (or rather with a small delay) which contains only the changed routes (triggered updates).

TODO

  1. Initially the router knows only the routes to the directly connected networks, and the routes that were manually configured. As it receives route updates from the neighbors it learns routes to remote networks. It should be possible to cooperate with other routing protocols that work in the same AS (e.g. OSPF) or with exterior protocols that connects this AS to other ASs (e.g. BGP). This requires some configurable criteria which routes of the routing table should be advertise by the RIP router, e.g. 'advertise the default route added by BGP with RIP metric 1'.
  2. There is no merging of subnet routes. RFC 2453 3.7 suggests that subnetted network routes should not be advertised outside the subnetted network.

Member Typedef Documentation

typedef std::vector<RIPRoute *> inet::RIPRouting::RouteVector
private

Member Enumeration Documentation

enum inet::RIPRouting::Mode
private
Enumerator
RIPv2 
RIPng 
137 { RIPv2, RIPng };
Definition: RIPRouting.h:137
Definition: RIPRouting.h:137

Constructor & Destructor Documentation

inet::RIPRouting::RIPRouting ( )
167 {
168 }
inet::RIPRouting::~RIPRouting ( )
171 {
172  for (auto & elem : ripRoutes)
173  delete elem;
174  ripRoutes.clear();
175  cancelAndDelete(updateTimer);
176  cancelAndDelete(triggeredUpdateTimer);
177  cancelAndDelete(startupTimer);
178  cancelAndDelete(shutdownTimer);
179 }
RouteVector ripRoutes
Definition: RIPRouting.h:147
cMessage * startupTimer
Definition: RIPRouting.h:151
cMessage * shutdownTimer
Definition: RIPRouting.h:152
cMessage * updateTimer
Definition: RIPRouting.h:149
cMessage * triggeredUpdateTimer
Definition: RIPRouting.h:150

Member Function Documentation

void inet::RIPRouting::addInterface ( const InterfaceEntry ie,
cXMLElement *  config 
)
private
1107 {
1108  RIPInterfaceEntry ripInterface(ie);
1109  if (config)
1110  ripInterface.configure(config);
1111  ripInterfaces.push_back(ripInterface);
1112 }
InterfaceVector ripInterfaces
Definition: RIPRouting.h:146
IRoute * inet::RIPRouting::addRoute ( const L3Address dest,
int  prefixLength,
const InterfaceEntry ie,
const L3Address nextHop,
int  metric 
)
private
1152 {
1153  IRoute *route = rt->createRoute();
1154  route->setSourceType(IRoute::RIP);
1155  route->setSource(this);
1156  route->setDestination(dest);
1157  route->setPrefixLength(prefixLength);
1158  route->setInterface(const_cast<InterfaceEntry *>(ie));
1159  route->setNextHop(nextHop);
1160  route->setMetric(metric);
1161  rt->addRoute(route);
1162  return route;
1163 }
virtual void setSourceType(SourceType type)=0
IRoutingTable * rt
Definition: RIPRouting.h:143
virtual void addRoute(IRoute *entry)=0
Adds a route to the routing table.
virtual IRoute * createRoute()=0
managed by the given routing protocol
Definition: IRoute.h:45
void inet::RIPRouting::addRoute ( const L3Address dest,
int  prefixLength,
const InterfaceEntry ie,
const L3Address nextHop,
int  metric,
uint16  routeTag,
const L3Address from 
)
protectedvirtual

RFC 2453 3.9.2:

Adding a route to the routing table consists of:

  • Setting the destination address to the destination address in the RTE
  • Setting the metric to the newly calculated metric
  • Set the next hop address to be the address of the router from which the datagram came
  • Initialize the timeout for the route. If the garbage-collection timer is running for this route, stop it
  • Set the route change flag
  • Signal the output process to trigger an update
882 {
883  EV_DEBUG << "Add route to " << dest << "/" << prefixLength << ": "
884  << "nextHop=" << nextHop << " metric=" << metric << std::endl;
885 
886  IRoute *route = addRoute(dest, prefixLength, ie, nextHop, metric);
887 
888  RIPRoute *ripRoute = new RIPRoute(route, RIPRoute::RIP_ROUTE_RTE, metric, routeTag);
889  ripRoute->setFrom(from);
890  ripRoute->setLastUpdateTime(simTime());
891  ripRoute->setChanged(true);
892  ripRoutes.push_back(ripRoute);
893  emit(numRoutesSignal, (unsigned long)ripRoutes.size());
894  triggerUpdate();
895 }
static simsignal_t numRoutesSignal
Definition: RIPRouting.h:167
RouteVector ripRoutes
Definition: RIPRouting.h:147
virtual void triggerUpdate()
Sets the update timer to trigger an update in the [1s,5s] interval.
Definition: RIPRouting.cc:962
IRoute * addRoute(const L3Address &dest, int prefixLength, const InterfaceEntry *ie, const L3Address &nextHop, int metric)
Definition: RIPRouting.cc:1151
Definition: RIPRouting.h:36
RIPRoute * inet::RIPRouting::checkRouteIsExpired ( RIPRoute route)
protectedvirtual

Should be called regularly to handle expiry and purge of routes.

If the route is valid, then returns it, otherwise returns nullptr.

979 {
980  if (route->getType() == RIPRoute::RIP_ROUTE_RTE) {
981  simtime_t now = simTime();
982  if (now >= route->getLastUpdateTime() + routeExpiryTime + routePurgeTime) {
983  purgeRoute(route);
984  return nullptr;
985  }
986  if (now >= route->getLastUpdateTime() + routeExpiryTime) {
987  invalidateRoute(route);
988  return nullptr;
989  }
990  }
991  return route;
992 }
simtime_t routePurgeTime
Definition: RIPRouting.h:158
virtual void invalidateRoute(RIPRoute *route)
Definition: RIPRouting.cc:1005
virtual void purgeRoute(RIPRoute *route)
Removes the route from the routing table.
Definition: RIPRouting.cc:1020
simtime_t routeExpiryTime
Definition: RIPRouting.h:157
Definition: RIPRouting.h:36
void inet::RIPRouting::configureInitialRoutes ( )
protectedvirtual

Import interface/static/default routes from the routing table.

250 {
251  for (int i = 0; i < rt->getNumRoutes(); ++i) {
252  IRoute *route = rt->getRoute(i);
253  if (isLoopbackInterfaceRoute(route)) {
254  /*ignore*/
255  ;
256  }
257  else if (isLocalInterfaceRoute(route)) {
258  InterfaceEntry *ie = check_and_cast<InterfaceEntry *>(route->getSource());
260  }
261  else if (isDefaultRoute(route))
263  else {
264  const L3Address& destAddr = route->getDestinationAsGeneric();
265  if (!destAddr.isMulticast() && !destAddr.isLinkLocal())
267  }
268  }
269 }
virtual IRoute * getRoute(int k) const =0
Returns the kth route.
virtual int getNumRoutes() const =0
Returns the total number of unicast routes.
IRoutingTable * rt
Definition: RIPRouting.h:143
Definition: RIPRouting.h:37
bool isLoopbackInterfaceRoute(const IRoute *route)
Definition: RIPRouting.cc:1170
Definition: RIPRouting.h:40
int getInterfaceMetric(InterfaceEntry *ie)
Definition: RIPRouting.cc:1137
bool isLocalInterfaceRoute(const IRoute *route)
Definition: RIPRouting.cc:1176
Definition: RIPRouting.h:38
virtual RIPRoute * importRoute(IRoute *route, RIPRoute::RouteType type, int metric=1, uint16 routeTag=0)
Adds a new route the RIP routing table for an existing IRoute.
Definition: RIPRouting.cc:275
bool isDefaultRoute(const IRoute *route)
Definition: RIPRouting.h:186
void inet::RIPRouting::configureInterfaces ( cXMLElement *  config)
protectedvirtual

Creates a RIPInterfaceEntry for each interface found in the interface table.

233 {
234  cXMLElementList interfaceElements = config->getChildrenByTagName("interface");
235  InterfaceMatcher matcher(interfaceElements);
236 
237  for (int k = 0; k < ift->getNumInterfaces(); ++k) {
238  InterfaceEntry *ie = ift->getInterface(k);
239  if (ie->isMulticast() && !ie->isLoopback()) {
240  int i = matcher.findMatchingSelector(ie);
241  addInterface(ie, i >= 0 ? interfaceElements[i] : nullptr);
242  }
243  }
244 }
IInterfaceTable * ift
Definition: RIPRouting.h:142
virtual int getNumInterfaces() const =0
Returns the number of interfaces.
virtual InterfaceEntry * getInterface(int pos) const =0
Returns the InterfaceEntry specified by an index 0..numInterfaces-1.
const double k
Definition: QAM16Modulation.cc:24
void addInterface(const InterfaceEntry *ie, cXMLElement *config)
Definition: RIPRouting.cc:1106
void inet::RIPRouting::deleteInterface ( const InterfaceEntry ie)
private
1115 {
1116  // delete interfaces and routes referencing ie
1117  for (auto it = ripInterfaces.begin(); it != ripInterfaces.end(); ) {
1118  if (it->ie == ie)
1119  it = ripInterfaces.erase(it);
1120  else
1121  it++;
1122  }
1123  bool emitNumRoutesSignal = false;
1124  for (auto it = ripRoutes.begin(); it != ripRoutes.end(); ) {
1125  if ((*it)->getInterface() == ie) {
1126  delete *it;
1127  it = ripRoutes.erase(it);
1128  emitNumRoutesSignal = true;
1129  }
1130  else
1131  it++;
1132  }
1133  if (emitNumRoutesSignal)
1134  emit(numRoutesSignal, (unsigned long)ripRoutes.size());
1135 }
static simsignal_t numRoutesSignal
Definition: RIPRouting.h:167
RouteVector ripRoutes
Definition: RIPRouting.h:147
InterfaceVector ripInterfaces
Definition: RIPRouting.h:146
void inet::RIPRouting::deleteRoute ( IRoute route)
private
1166 {
1167  rt->deleteRoute(route);
1168 }
virtual bool deleteRoute(IRoute *entry)=0
Deletes the given route from the routing table.
IRoutingTable * rt
Definition: RIPRouting.h:143
RIPInterfaceEntry * inet::RIPRouting::findInterfaceById ( int  interfaceId)
private
1062 {
1063  for (auto & elem : ripInterfaces)
1064  if (elem.ie->getInterfaceId() == interfaceId)
1065  return &(elem);
1066 
1067  return nullptr;
1068 }
InterfaceVector ripInterfaces
Definition: RIPRouting.h:146
RIPRoute * inet::RIPRouting::findRoute ( const L3Address destAddress,
int  prefixLength 
)
private
1071 {
1072  for (auto & elem : ripRoutes)
1073  if ((elem)->getDestination() == destination && (elem)->getPrefixLength() == prefixLength)
1074  return elem;
1075 
1076  return nullptr;
1077 }
RouteVector ripRoutes
Definition: RIPRouting.h:147
RIPRoute * inet::RIPRouting::findRoute ( const L3Address destination,
int  prefixLength,
RIPRoute::RouteType  type 
)
private
1080 {
1081  for (auto & elem : ripRoutes)
1082  if ((elem)->getType() == type && (elem)->getDestination() == destination && (elem)->getPrefixLength() == prefixLength)
1083  return elem;
1084 
1085  return nullptr;
1086 }
RouteVector ripRoutes
Definition: RIPRouting.h:147
RIPRoute * inet::RIPRouting::findRoute ( const IRoute route)
private
1089 {
1090  for (auto & elem : ripRoutes)
1091  if ((elem)->getRoute() == route)
1092  return elem;
1093 
1094  return nullptr;
1095 }
RouteVector ripRoutes
Definition: RIPRouting.h:147
RIPRoute * inet::RIPRouting::findRoute ( const InterfaceEntry ie,
RIPRoute::RouteType  type 
)
private
1098 {
1099  for (auto & elem : ripRoutes)
1100  if ((elem)->getType() == type && (elem)->getInterface() == ie)
1101  return elem;
1102 
1103  return nullptr;
1104 }
RouteVector ripRoutes
Definition: RIPRouting.h:147
std::string inet::RIPRouting::getHostName ( )
inlineprivate
187 { return host->getFullName(); }
cModule * host
Definition: RIPRouting.h:141
int inet::RIPRouting::getInterfaceMetric ( InterfaceEntry ie)
private
1138 {
1139  RIPInterfaceEntry *ripIe = findInterfaceById(ie->getInterfaceId());
1140  return ripIe ? ripIe->metric : 1;
1141 }
RIPInterfaceEntry * findInterfaceById(int interfaceId)
Definition: RIPRouting.cc:1061
int metric
Definition: RIPRouting.h:105
void inet::RIPRouting::handleMessage ( cMessage *  msg)
overrideprotectedvirtual
512 {
513  if (!isOperational) {
514  if (msg->isSelfMessage())
515  throw cRuntimeError("Model error: self msg '%s' received when isOperational is false", msg->getName());
516  EV_ERROR << "Application is turned off, dropping '" << msg->getName() << "' message\n";
517  delete msg;
518  return;
519  }
520 
521  if (msg->isSelfMessage()) {
522  if (msg == updateTimer) {
523  processUpdate(false);
524  scheduleAt(simTime() + updateInterval, msg);
525  }
526  else if (msg == triggeredUpdateTimer) {
527  processUpdate(true);
528  }
529  else if (msg == startupTimer) {
530  startRIPRouting();
531  }
532  else if (msg == shutdownTimer) {
533  isOperational = false;
534  IDoneCallback *doneCallback = (IDoneCallback *)msg->getContextPointer();
535  msg->setContextPointer(nullptr);
536  doneCallback->invoke();
537  }
538  }
539  else if (msg->getKind() == UDP_I_DATA) {
540  RIPPacket *packet = check_and_cast<RIPPacket *>(msg);
541  unsigned char command = packet->getCommand();
542  if (command == RIP_REQUEST)
543  processRequest(packet);
544  else if (command == RIP_RESPONSE)
545  processResponse(packet);
546  else
547  throw cRuntimeError("RIP: unknown command (%d)", (int)command);
548  }
549  else if (msg->getKind() == UDP_I_ERROR) {
550  EV_DETAIL << "Ignoring UDP error report\n";
551  delete msg;
552  }
553 }
simtime_t updateInterval
Definition: RIPRouting.h:156
Definition: UDPControlInfo_m.h:83
Definition: UDPControlInfo_m.h:84
cMessage * startupTimer
Definition: RIPRouting.h:151
bool isOperational
Definition: RIPRouting.h:160
Definition: RIPPacket_m.h:58
virtual void processResponse(RIPPacket *packet)
Processes the RIP response and updates the routing table.
Definition: RIPRouting.cc:745
virtual void processUpdate(bool triggered)
This method called when a triggered or regular update timer expired.
Definition: RIPRouting.cc:559
virtual void startRIPRouting()
Definition: RIPRouting.cc:448
cMessage * shutdownTimer
Definition: RIPRouting.h:152
Definition: RIPPacket_m.h:57
cMessage * updateTimer
Definition: RIPRouting.h:149
cMessage * triggeredUpdateTimer
Definition: RIPRouting.h:150
virtual void processRequest(RIPPacket *packet)
Processes a request received from a RIP router or a monitoring process.
Definition: RIPRouting.cc:595
bool inet::RIPRouting::handleOperationStage ( LifecycleOperation operation,
int  stage,
IDoneCallback doneCallback 
)
overrideprotectedvirtual

Perform one stage of a lifecycle operation.

Processing may be done entirely within this method, or may be a longer process that involves nonzero simulation time or several events, and is triggered by this method call.

Return value: true = "done"; false = "not yet done, will invoke doneCallback when done"

Implements inet::ILifecycle.

408 {
409  Enter_Method_Silent();
410 
411  if (dynamic_cast<NodeStartOperation *>(operation)) {
413  isOperational = true;
414  cancelEvent(startupTimer);
415  scheduleAt(simTime() + par("startupTime").doubleValue(), startupTimer);
416  return true;
417  }
418  }
419  else if (dynamic_cast<NodeShutdownOperation *>(operation)) {
421  // invalidate routes
422  for (auto & elem : ripRoutes)
423  invalidateRoute(elem);
424  // send updates to neighbors
425  for (auto & elem : ripInterfaces)
427 
428  stopRIPRouting();
429 
430  // wait a few seconds before calling doneCallback, so that UDP can send the messages
431  shutdownTimer->setContextPointer(doneCallback);
432  scheduleAt(simTime() + shutdownTime, shutdownTimer);
433 
434  return false;
435  }
436  }
437  else if (dynamic_cast<NodeCrashOperation *>(operation)) {
439  stopRIPRouting();
440  isOperational = false;
441  return true;
442  }
443  }
444 
445  return true;
446 }
int ripUdpPort
Definition: RIPRouting.h:155
RouteVector ripRoutes
Definition: RIPRouting.h:147
InterfaceVector ripInterfaces
Definition: RIPRouting.h:146
virtual L3Address getLinkLocalRIPRoutersMulticastAddress() const =0
IL3AddressType * addressType
Definition: RIPRouting.h:144
virtual void sendRoutes(const L3Address &address, int port, const RIPInterfaceEntry &ripInterface, bool changedOnly)
Send all or changed part of the routing table to address/port on the specified interface.
Definition: RIPRouting.cc:652
virtual void invalidateRoute(RIPRoute *route)
Definition: RIPRouting.cc:1005
cMessage * startupTimer
Definition: RIPRouting.h:151
bool isOperational
Definition: RIPRouting.h:160
Stage
Definition: NodeOperations.h:71
Stage
Definition: NodeOperations.h:126
cMessage * shutdownTimer
Definition: RIPRouting.h:152
simtime_t shutdownTime
Definition: RIPRouting.h:159
Stage
Definition: NodeOperations.h:46
virtual void stopRIPRouting()
Definition: RIPRouting.cc:484
Definition: NodeOperations.h:127
RIPRoute * inet::RIPRouting::importRoute ( IRoute route,
RIPRoute::RouteType  type,
int  metric = 1,
uint16  routeTag = 0 
)
protectedvirtual

Adds a new route the RIP routing table for an existing IRoute.

This route will be advertised with the specified metric and routeTag fields.

276 {
277  ASSERT(metric < RIP_INFINITE_METRIC);
278 
279  RIPRoute *ripRoute = new RIPRoute(route, type, metric, routeTag);
280  if (type == RIPRoute::RIP_ROUTE_INTERFACE) {
281  InterfaceEntry *ie = check_and_cast<InterfaceEntry *>(route->getSource());
282  ripRoute->setInterface(ie);
283  }
284 
285  ripRoutes.push_back(ripRoute);
286  emit(numRoutesSignal, (unsigned long)ripRoutes.size());
287  return ripRoute;
288 }
static simsignal_t numRoutesSignal
Definition: RIPRouting.h:167
RouteVector ripRoutes
Definition: RIPRouting.h:147
#define RIP_INFINITE_METRIC
Definition: RIPRouting.h:31
Definition: RIPRouting.h:40
void inet::RIPRouting::initialize ( int  stage)
overrideprotectedvirtual
188 {
189  cSimpleModule::initialize(stage);
190 
191  if (stage == INITSTAGE_LOCAL) {
192  host = getContainingNode(this);
193  ift = getModuleFromPar<IInterfaceTable>(par("interfaceTableModule"), this);
194  rt = getModuleFromPar<IRoutingTable>(par("routingTableModule"), this);
195  socket.setOutputGate(gate("udpOut"));
196 
197  const char *m = par("mode");
198  if (!m)
199  throw cRuntimeError("Missing 'mode' parameter.");
200  else if (!strcmp(m, "RIPv2"))
201  mode = RIPv2;
202  else if (!strcmp(m, "RIPng"))
203  mode = RIPng;
204  else
205  throw cRuntimeError("Unrecognized 'mode' parameter: %s", m);
206 
207  ripUdpPort = par("udpPort");
208  updateInterval = par("updateInterval").doubleValue();
209  routeExpiryTime = par("routeExpiryTime").doubleValue();
210  routePurgeTime = par("routePurgeTime").doubleValue();
211  shutdownTime = par("shutdownTime").doubleValue();
212 
213  updateTimer = new cMessage("RIP-timer");
214  triggeredUpdateTimer = new cMessage("RIP-trigger");
215  startupTimer = new cMessage("RIP-startup");
216  shutdownTimer = new cMessage("RIP-shutdown");
217 
218  WATCH_VECTOR(ripInterfaces);
219  WATCH_PTRVECTOR(ripRoutes);
220  }
221  else if (stage == INITSTAGE_ROUTING_PROTOCOLS) { // interfaces and static routes are already initialized
222  NodeStatus *nodeStatus = dynamic_cast<NodeStatus *>(findContainingNode(this)->getSubmodule("status"));
223  isOperational = !nodeStatus || nodeStatus->getState() == NodeStatus::UP;
224  if (isOperational)
225  scheduleAt(simTime() + par("startupTime").doubleValue(), startupTimer);
226  }
227 }
Mode mode
Definition: RIPRouting.h:154
cModule * host
Definition: RIPRouting.h:141
IInterfaceTable * ift
Definition: RIPRouting.h:142
int ripUdpPort
Definition: RIPRouting.h:155
simtime_t routePurgeTime
Definition: RIPRouting.h:158
simtime_t updateInterval
Definition: RIPRouting.h:156
RouteVector ripRoutes
Definition: RIPRouting.h:147
Definition: RIPRouting.h:137
IRoutingTable * rt
Definition: RIPRouting.h:143
UDPSocket socket
Definition: RIPRouting.h:148
InterfaceVector ripInterfaces
Definition: RIPRouting.h:146
Definition: RIPRouting.h:137
Initialization of routing protocols.
Definition: InitStages.h:101
void setOutputGate(cGate *toUdp)
Sets the gate on which to send to UDP.
Definition: UDPSocket.h:110
cMessage * startupTimer
Definition: RIPRouting.h:151
bool isOperational
Definition: RIPRouting.h:160
cModule * findContainingNode(const cModule *from)
Find the node containing the given module.
Definition: ModuleAccess.cc:56
Local initializations.
Definition: InitStages.h:35
cModule * getContainingNode(const cModule *from)
Find the node containing the given module.
Definition: ModuleAccess.cc:65
cMessage * shutdownTimer
Definition: RIPRouting.h:152
simtime_t shutdownTime
Definition: RIPRouting.h:159
cMessage * updateTimer
Definition: RIPRouting.h:149
cMessage * triggeredUpdateTimer
Definition: RIPRouting.h:150
simtime_t routeExpiryTime
Definition: RIPRouting.h:157
value< double, units::m > m
Definition: Units.h:1047
Definition: NodeStatus.h:40
void inet::RIPRouting::invalidateRoute ( RIPRoute route)
protectedvirtual
1006 {
1007  IRoute *route = ripRoute->getRoute();
1008  if (route) {
1009  ripRoute->setRoute(nullptr);
1010  deleteRoute(route);
1011  }
1012  ripRoute->setMetric(RIP_INFINITE_METRIC);
1013  ripRoute->setChanged(true);
1014  triggerUpdate();
1015 }
void deleteRoute(IRoute *route)
Definition: RIPRouting.cc:1165
#define RIP_INFINITE_METRIC
Definition: RIPRouting.h:31
virtual void triggerUpdate()
Sets the update timer to trigger an update in the [1s,5s] interval.
Definition: RIPRouting.cc:962
void inet::RIPRouting::invalidateRoutes ( const InterfaceEntry ie)
private
1144 {
1145  for (auto & elem : ripRoutes)
1146  if ((elem)->getInterface() == ie)
1147  invalidateRoute(elem);
1148 
1149 }
RouteVector ripRoutes
Definition: RIPRouting.h:147
virtual void invalidateRoute(RIPRoute *route)
Definition: RIPRouting.cc:1005
bool inet::RIPRouting::isDefaultRoute ( const IRoute route)
inlineprivate
186 { return route->getPrefixLength() == 0; }
bool inet::RIPRouting::isLocalInterfaceRoute ( const IRoute route)
private
1177 {
1178  InterfaceEntry *ie = dynamic_cast<InterfaceEntry *>(route->getSource());
1179  return ie && !ie->isLoopback();
1180 }
bool inet::RIPRouting::isLoopbackInterfaceRoute ( const IRoute route)
private
1171 {
1172  InterfaceEntry *ie = dynamic_cast<InterfaceEntry *>(route->getSource());
1173  return ie && ie->isLoopback();
1174 }
bool inet::RIPRouting::isValidResponse ( RIPPacket packet)
protectedvirtual
800 {
801  UDPDataIndication *ctrlInfo = check_and_cast<UDPDataIndication *>(packet->getControlInfo());
802 
803  // check that received from ripUdpPort
804  if (ctrlInfo->getSrcPort() != ripUdpPort) {
805  EV_WARN << "source port is not " << ripUdpPort << "\n";
806  return false;
807  }
808 
809  // check that it is not our response (received own multicast message)
810  if (rt->isLocalAddress(ctrlInfo->getSrcAddr())) {
811  EV_WARN << "received own response\n";
812  return false;
813  }
814 
815  if (mode == RIPng) {
816  if (!ctrlInfo->getSrcAddr().isLinkLocal()) {
817  EV_WARN << "source address is not link-local: " << ctrlInfo->getSrcAddr() << "\n";
818  return false;
819  }
820  if (ctrlInfo->getTtl() != 255) {
821  EV_WARN << "ttl is not 255";
822  return false;
823  }
824  }
825  else {
826  // check that source is on a directly connected network
827  if (!ift->isNeighborAddress(ctrlInfo->getSrcAddr())) {
828  EV_WARN << "source is not directly connected " << ctrlInfo->getSrcAddr() << "\n";
829  return false;
830  }
831  }
832 
833  // validate entries
834  int numEntries = packet->getEntryArraySize();
835  for (int i = 0; i < numEntries; ++i) {
836  RIPEntry& entry = packet->getEntry(i);
837 
838  // check that metric is in range [1,16]
839  if (entry.metric < 1 || entry.metric > RIP_INFINITE_METRIC) {
840  EV_WARN << "received metric is not in the [1," << RIP_INFINITE_METRIC << "] range.\n";
841  return false;
842  }
843 
844  // check that destination address is a unicast address
845  // TODO exclude 0.x.x.x, 127.x.x.x too
846  if (!entry.address.isUnicast()) {
847  EV_WARN << "destination address of an entry is not unicast: " << entry.address << "\n";
848  return false;
849  }
850 
851  if (mode == RIPng) {
852  if (entry.address.isLinkLocal()) {
853  EV_WARN << "destination address of an entry is link-local: " << entry.address << "\n";
854  return false;
855  }
856  if (entry.prefixLength < 0 || entry.prefixLength > addressType->getMaxPrefixLength()) {
857  EV_WARN << "prefixLength is outside of the [0," << addressType->getMaxPrefixLength() << "] interval\n";
858  return false;
859  }
860  }
861  }
862 
863  return true;
864 }
Mode mode
Definition: RIPRouting.h:154
IInterfaceTable * ift
Definition: RIPRouting.h:142
int ripUdpPort
Definition: RIPRouting.h:155
IRoutingTable * rt
Definition: RIPRouting.h:143
#define RIP_INFINITE_METRIC
Definition: RIPRouting.h:31
virtual bool isLocalAddress(const L3Address &dest) const =0
Checks if the address is a local one, i.e.
IL3AddressType * addressType
Definition: RIPRouting.h:144
Definition: RIPRouting.h:137
virtual bool isNeighborAddress(const L3Address &address) const =0
Checks if the address is on the network of one of the interfaces, but not local.
virtual int getMaxPrefixLength() const =0
virtual int inet::RIPRouting::numInitStages ( ) const
inlineoverrideprotectedvirtual
191 { return NUM_INIT_STAGES; }
The number of initialization stages.
Definition: InitStages.h:116
void inet::RIPRouting::processRequest ( RIPPacket packet)
protectedvirtual

Processes a request received from a RIP router or a monitoring process.

The request processing follows the guidelines described in RFC 2453 3.9.1.

There are two cases:

  • the request enumerates the requested prefixes There is an RIPEntry for each requested route in the packet. The RIP module simply looks up the prefix in its table, and if it sets the metric field of the entry to the metric of the found route, or to infinity (16) if not found. Once all entries are have been filled in, change the command from Request to Response, and sent the packet back to the requestor. If there are no entries in the request, then no response is sent; the request is silently discarded.
  • the whole routing table is requested In this case the RIPPacket contains only one entry, with addressFamilyId 0, and metric 16 (infinity). In this case the whole routing table is sent, using the normal output process (sendRoutes() method).
596 {
597  int numEntries = packet->getEntryArraySize();
598  if (numEntries == 0) {
599  EV_INFO << "received empty request, ignoring.\n";
600  delete packet;
601  return;
602  }
603 
604  UDPDataIndication *ctrlInfo = check_and_cast<UDPDataIndication *>(packet->removeControlInfo());
605  L3Address srcAddr = ctrlInfo->getSrcAddr();
606  int srcPort = ctrlInfo->getSrcPort();
607  int interfaceId = ctrlInfo->getInterfaceId();
608  delete ctrlInfo;
609 
610  EV_INFO << "received request from " << srcAddr << "\n";
611 
612  RIPRoute *ripRoute;
613  for (int i = 0; i < numEntries; ++i) {
614  RIPEntry& entry = packet->getEntry(i);
615  switch (entry.addressFamilyId) {
616  case RIP_AF_NONE:
617  if (numEntries == 1 && entry.metric == RIP_INFINITE_METRIC) {
618  RIPInterfaceEntry *ripInterface = findInterfaceById(interfaceId);
619  if (ripInterface)
620  sendRoutes(srcAddr, srcPort, *ripInterface, false);
621  delete packet;
622  return;
623  }
624  else {
625  delete packet;
626  throw cRuntimeError("RIP: invalid request.");
627  }
628  break;
629 
630  case RIP_AF_INET:
631  ripRoute = findRoute(entry.address, entry.prefixLength);
632  entry.metric = ripRoute ? ripRoute->getMetric() : RIP_INFINITE_METRIC;
633  // entry.nextHop, entry.routeTag?
634  break;
635 
636  default:
637  delete packet;
638  throw cRuntimeError("RIP: request has invalid addressFamilyId: %d.", (int)entry.addressFamilyId);
639  }
640  }
641 
642  packet->setCommand(RIP_RESPONSE);
643  packet->setName("RIP response");
644  socket.sendTo(packet, srcAddr, srcPort);
645 }
RIPInterfaceEntry * findInterfaceById(int interfaceId)
Definition: RIPRouting.cc:1061
void sendTo(cPacket *msg, L3Address destAddr, int destPort, const SendOptions *options=nullptr)
Sends a data packet to the given address and port.
Definition: UDPSocket.cc:88
UDPSocket socket
Definition: RIPRouting.h:148
#define RIP_INFINITE_METRIC
Definition: RIPRouting.h:31
Definition: RIPPacket_m.h:77
virtual void sendRoutes(const L3Address &address, int port, const RIPInterfaceEntry &ripInterface, bool changedOnly)
Send all or changed part of the routing table to address/port on the specified interface.
Definition: RIPRouting.cc:652
Definition: RIPPacket_m.h:78
Definition: RIPPacket_m.h:58
RIPRoute * findRoute(const L3Address &destAddress, int prefixLength)
Definition: RIPRouting.cc:1070
void inet::RIPRouting::processResponse ( RIPPacket packet)
protectedvirtual

Processes the RIP response and updates the routing table.

First it validates the packet to avoid corrupting the routing table with a wrong packet. Valid responses must come from a neighboring RIP router.

Next each RIPEntry is processed one by one. Check that destination address and metric are valid. Then compute the new metric by adding the metric of the interface to the metric found in the entry.

If there is no route to the destination, and the new metric is not infinity, then add a new route to the routing table.

If there is an existing route to the destination,

  1. validate packet
  2. for each entry: metric = MIN(p.metric + cost of if it arrived at, infinity) if there is no route for the dest address: add new route to the routing table unless the metric is infinity else: if received from the route.gateway reinitialize timeout if (received from route.gateway AND route.metric != metric) OR metric < route.metric updateRoute(route)
746 {
747  emit(rcvdResponseSignal, packet);
748 
749  bool isValid = isValidResponse(packet);
750  if (!isValid) {
751  EV_INFO << "dropping invalid response.\n";
752  emit(badResponseSignal, packet);
753  delete packet;
754  return;
755  }
756 
757  UDPDataIndication *ctrlInfo = check_and_cast<UDPDataIndication *>(packet->removeControlInfo());
758  L3Address srcAddr = ctrlInfo->getSrcAddr();
759  int interfaceId = ctrlInfo->getInterfaceId();
760  delete ctrlInfo;
761 
762  RIPInterfaceEntry *incomingIe = findInterfaceById(interfaceId);
763  if (!incomingIe) {
764  EV_INFO << "dropping unexpected RIP response.\n";
765  emit(badResponseSignal, packet);
766  delete packet;
767  return;
768  }
769 
770  EV_INFO << "response received from " << srcAddr << "\n";
771  int numEntries = packet->getEntryArraySize();
772  for (int i = 0; i < numEntries; ++i) {
773  RIPEntry& entry = packet->getEntry(i);
774  int metric = std::min((int)entry.metric + incomingIe->metric, RIP_INFINITE_METRIC);
775  L3Address nextHop = entry.nextHop.isUnspecified() ? srcAddr : entry.nextHop;
776 
777  RIPRoute *ripRoute = findRoute(entry.address, entry.prefixLength);
778  if (ripRoute) {
779  RIPRoute::RouteType routeType = ripRoute->getType();
780  int routeMetric = ripRoute->getMetric();
781  if ((routeType == RIPRoute::RIP_ROUTE_STATIC || routeType == RIPRoute::RIP_ROUTE_DEFAULT) && routeMetric != RIP_INFINITE_METRIC)
782  continue;
783  if (ripRoute->getFrom() == srcAddr)
784  ripRoute->setLastUpdateTime(simTime());
785  if ((ripRoute->getFrom() == srcAddr && ripRoute->getMetric() != metric) || metric < ripRoute->getMetric())
786  updateRoute(ripRoute, incomingIe->ie, nextHop, metric, entry.routeTag, srcAddr);
787  // TODO RIPng: if the metric is the same as the old one, and the old route is aboute to expire (i.e. at least halfway to the expiration point)
788  // then update the old route with the new RTE
789  }
790  else {
791  if (metric != RIP_INFINITE_METRIC)
792  addRoute(entry.address, entry.prefixLength, incomingIe->ie, nextHop, metric, entry.routeTag, srcAddr);
793  }
794  }
795 
796  delete packet;
797 }
RIPInterfaceEntry * findInterfaceById(int interfaceId)
Definition: RIPRouting.cc:1061
double min(const double a, const double b)
Returns the minimum of a and b.
Definition: SCTPAssociation.h:270
#define RIP_INFINITE_METRIC
Definition: RIPRouting.h:31
Definition: RIPRouting.h:37
virtual void updateRoute(RIPRoute *route, const InterfaceEntry *ie, const L3Address &nextHop, int metric, uint16 routeTag, const L3Address &from)
Updates an existing route with the information learned from a RIP packet.
Definition: RIPRouting.cc:913
RouteType
Definition: RIPRouting.h:35
IRoute * addRoute(const L3Address &dest, int prefixLength, const InterfaceEntry *ie, const L3Address &nextHop, int metric)
Definition: RIPRouting.cc:1151
Definition: RIPRouting.h:38
static simsignal_t rcvdResponseSignal
Definition: RIPRouting.h:165
static simsignal_t badResponseSignal
Definition: RIPRouting.h:166
RIPRoute * findRoute(const L3Address &destAddress, int prefixLength)
Definition: RIPRouting.cc:1070
virtual bool isValidResponse(RIPPacket *packet)
Definition: RIPRouting.cc:799
void inet::RIPRouting::processUpdate ( bool  triggered)
protectedvirtual

This method called when a triggered or regular update timer expired.

It either sends the changed/all routes to neighbors.

560 {
561  if (triggered)
562  EV_INFO << "sending triggered updates on all interfaces.\n";
563  else
564  EV_INFO << "sending regular updates on all interfaces\n";
565 
566  for (auto & elem : ripInterfaces)
567  if (elem.mode != NO_RIP)
569 
570 
571  // clear changed flags
572  for (auto & elem : ripRoutes)
573  (elem)->setChanged(false);
574 }
int ripUdpPort
Definition: RIPRouting.h:155
RouteVector ripRoutes
Definition: RIPRouting.h:147
InterfaceVector ripInterfaces
Definition: RIPRouting.h:146
virtual L3Address getLinkLocalRIPRoutersMulticastAddress() const =0
IL3AddressType * addressType
Definition: RIPRouting.h:144
virtual void sendRoutes(const L3Address &address, int port, const RIPInterfaceEntry &ripInterface, bool changedOnly)
Send all or changed part of the routing table to address/port on the specified interface.
Definition: RIPRouting.cc:652
Definition: RIPRouting.h:89
void inet::RIPRouting::purgeRoute ( RIPRoute route)
protectedvirtual

Removes the route from the routing table.

1021 {
1022  ASSERT(ripRoute->getType() == RIPRoute::RIP_ROUTE_RTE);
1023 
1024  IRoute *route = ripRoute->getRoute();
1025  if (route) {
1026  ripRoute->setRoute(nullptr);
1027  deleteRoute(route);
1028  }
1029 
1030  remove(ripRoutes, ripRoute);
1031  delete ripRoute;
1032 
1033  emit(numRoutesSignal, (unsigned long)ripRoutes.size());
1034 }
static simsignal_t numRoutesSignal
Definition: RIPRouting.h:167
RouteVector ripRoutes
Definition: RIPRouting.h:147
void deleteRoute(IRoute *route)
Definition: RIPRouting.cc:1165
Definition: RIPRouting.h:36
void inet::RIPRouting::receiveSignal ( cComponent *  source,
simsignal_t  signalID,
cObject *  obj,
cObject *  details 
)
overrideprotectedvirtual

Listen on interface/route changes and update private data structures.

309 {
310  Enter_Method_Silent("RIPRouting::receiveChangeNotification(%s)", notificationCategoryName(signalID));
311 
312  IRoute *route;
313  const InterfaceEntry *ie;
314  const InterfaceEntryChangeDetails *change;
315 
316  if (signalID == NF_INTERFACE_CREATED) {
317  // configure interface for RIP
318  ie = check_and_cast<const InterfaceEntry *>(obj);
319  if (ie->isMulticast() && !ie->isLoopback()) {
320  cXMLElementList config = par("ripConfig").xmlValue()->getChildrenByTagName("interface");
321  int i = InterfaceMatcher(config).findMatchingSelector(ie);
322  if (i >= 0)
323  addInterface(ie, config[i]);
324  }
325  }
326  else if (signalID == NF_INTERFACE_DELETED) {
327  // delete interfaces and routes referencing the deleted interface
328  ie = check_and_cast<const InterfaceEntry *>(obj);
329  deleteInterface(ie);
330  }
331  else if (signalID == NF_INTERFACE_STATE_CHANGED) {
332  change = check_and_cast<const InterfaceEntryChangeDetails *>(obj);
333  if (change->getFieldId() == InterfaceEntry::F_CARRIER || change->getFieldId() == InterfaceEntry::F_STATE) {
334  ie = change->getInterfaceEntry();
335  if (!ie->isUp()) {
336  invalidateRoutes(ie);
337  }
338  else {
339  RIPInterfaceEntry *ripInterfacePtr = findInterfaceById(ie->getInterfaceId());
340  if (ripInterfacePtr && ripInterfacePtr->mode != NO_RIP)
341  sendRIPRequest(*ripInterfacePtr);
342  }
343  }
344  }
345  else if (signalID == NF_ROUTE_DELETED) {
346  // remove references to the deleted route and invalidate the RIP route
347  route = const_cast<IRoute *>(check_and_cast<const IRoute *>(obj));
348  if (route->getSource() != this) {
349  for (auto & elem : ripRoutes)
350  if ((elem)->getRoute() == route) {
351  (elem)->setRoute(nullptr);
352  invalidateRoute(elem);
353  }
354  }
355  }
356  else if (signalID == NF_ROUTE_ADDED) {
357  // add or update the RIP route
358  route = const_cast<IRoute *>(check_and_cast<const IRoute *>(obj));
359  if (route->getSource() != this) {
360  if (isLoopbackInterfaceRoute(route)) {
361  /*ignore*/
362  ;
363  }
364  else if (isLocalInterfaceRoute(route)) {
365  InterfaceEntry *ie = check_and_cast<InterfaceEntry *>(route->getSource());
366  RIPRoute *ripRoute = findRoute(ie, RIPRoute::RIP_ROUTE_INTERFACE);
367  if (ripRoute) { // readded
368  RIPInterfaceEntry *ripIe = findInterfaceById(ie->getInterfaceId());
369  ripRoute->setRoute(route);
370  ripRoute->setMetric(ripIe ? ripIe->metric : 1);
371  ripRoute->setChanged(true);
372  triggerUpdate();
373  }
374  else
376  }
377  else {
378  // TODO import external routes from other routing daemons
379  }
380  }
381  }
382  else if (signalID == NF_ROUTE_CHANGED) {
383  route = const_cast<IRoute *>(check_and_cast<const IRoute *>(obj));
384  if (route->getSource() != this) {
385  RIPRoute *ripRoute = findRoute(route);
386  if (ripRoute) {
387  // TODO check and update tag
388  bool changed = route->getDestinationAsGeneric() != ripRoute->getDestination() ||
389  route->getPrefixLength() != ripRoute->getPrefixLength() ||
390  route->getNextHopAsGeneric() != ripRoute->getNextHop() ||
391  route->getInterface() != ripRoute->getInterface();
392  ripRoute->setDestination(route->getDestinationAsGeneric());
393  ripRoute->setPrefixLength(route->getPrefixLength());
394  ripRoute->setNextHop(route->getNextHopAsGeneric());
395  ripRoute->setInterface(route->getInterface());
396  if (changed) {
397  ripRoute->setChanged(changed);
398  triggerUpdate();
399  }
400  }
401  }
402  }
403  else
404  throw cRuntimeError("Unexpected signal: %s", getSignalName(signalID));
405 }
RIPInterfaceEntry * findInterfaceById(int interfaceId)
Definition: RIPRouting.cc:1061
simsignal_t NF_ROUTE_DELETED
Definition: NotifierConsts.cc:58
RouteVector ripRoutes
Definition: RIPRouting.h:147
void deleteInterface(const InterfaceEntry *ie)
Definition: RIPRouting.cc:1114
void invalidateRoutes(const InterfaceEntry *ie)
Definition: RIPRouting.cc:1143
virtual void triggerUpdate()
Sets the update timer to trigger an update in the [1s,5s] interval.
Definition: RIPRouting.cc:962
Definition: InterfaceEntry.h:139
virtual void sendRIPRequest(const RIPInterfaceEntry &ripInterface)
Sends a RIP request to routers on the specified link.
Definition: RIPRouting.cc:293
virtual void invalidateRoute(RIPRoute *route)
Definition: RIPRouting.cc:1005
Definition: RIPRouting.h:89
bool isLoopbackInterfaceRoute(const IRoute *route)
Definition: RIPRouting.cc:1170
Definition: RIPRouting.h:40
simsignal_t NF_INTERFACE_STATE_CHANGED
Definition: NotifierConsts.cc:50
simsignal_t NF_INTERFACE_CREATED
Definition: NotifierConsts.cc:48
int getInterfaceMetric(InterfaceEntry *ie)
Definition: RIPRouting.cc:1137
simsignal_t NF_ROUTE_CHANGED
Definition: NotifierConsts.cc:59
simsignal_t NF_ROUTE_ADDED
Definition: NotifierConsts.cc:57
Definition: InterfaceEntry.h:139
bool isLocalInterfaceRoute(const IRoute *route)
Definition: RIPRouting.cc:1176
virtual RIPRoute * importRoute(IRoute *route, RIPRoute::RouteType type, int metric=1, uint16 routeTag=0)
Adds a new route the RIP routing table for an existing IRoute.
Definition: RIPRouting.cc:275
const char * notificationCategoryName(simsignal_t signalID)
Utility function.
Definition: NotifierConsts.cc:104
simsignal_t NF_INTERFACE_DELETED
Definition: NotifierConsts.cc:49
void addInterface(const InterfaceEntry *ie, cXMLElement *config)
Definition: RIPRouting.cc:1106
RIPRoute * findRoute(const L3Address &destAddress, int prefixLength)
Definition: RIPRouting.cc:1070
void inet::RIPRouting::sendPacket ( RIPPacket packet,
const L3Address destAddr,
int  destPort,
const InterfaceEntry destInterface 
)
protectedvirtual

Sends the packet to the specified destination.

If the destAddr is a multicast, then the destInterface must be specified.

1041 {
1042  packet->setByteLength(RIP_HEADER_SIZE + RIP_RTE_SIZE * packet->getEntryArraySize());
1043 
1044  if (destAddr.isMulticast()) {
1045  UDPSocket::SendOptions options;
1046  options.outInterfaceId = destInterface->getInterfaceId();
1047  if (mode == RIPng) {
1048  socket.setTimeToLive(255);
1049  options.srcAddr = addressType->getLinkLocalAddress(destInterface);
1050  }
1051  socket.sendTo(packet, destAddr, destPort, &options);
1052  }
1053  else
1054  socket.sendTo(packet, destAddr, destPort);
1055 }
Mode mode
Definition: RIPRouting.h:154
const int RIP_HEADER_SIZE
Definition: RIPPacket_m.h:38
const int RIP_RTE_SIZE
Definition: RIPPacket_m.h:39
void sendTo(cPacket *msg, L3Address destAddr, int destPort, const SendOptions *options=nullptr)
Sends a data packet to the given address and port.
Definition: UDPSocket.cc:88
void setTimeToLive(int ttl)
Set the TTL (IPv6: Hop Limit) field on sent packets.
Definition: UDPSocket.cc:131
UDPSocket socket
Definition: RIPRouting.h:148
IL3AddressType * addressType
Definition: RIPRouting.h:144
Definition: RIPRouting.h:137
virtual L3Address getLinkLocalAddress(const InterfaceEntry *ie) const =0
Returns the first valid link-local address of the interface, or UNSPECIFIED_ADDRESS if there&#39;s none...
void inet::RIPRouting::sendRIPRequest ( const RIPInterfaceEntry ripInterface)
protectedvirtual

Sends a RIP request to routers on the specified link.

294 {
295  RIPPacket *packet = new RIPPacket("RIP request");
296  packet->setCommand(RIP_REQUEST);
297  packet->setEntryArraySize(1);
298  RIPEntry& entry = packet->getEntry(0);
299  entry.addressFamilyId = RIP_AF_NONE;
300  entry.metric = RIP_INFINITE_METRIC;
301  emit(sentRequestSignal, packet);
303 }
int ripUdpPort
Definition: RIPRouting.h:155
#define RIP_INFINITE_METRIC
Definition: RIPRouting.h:31
Definition: RIPPacket_m.h:77
virtual L3Address getLinkLocalRIPRoutersMulticastAddress() const =0
IL3AddressType * addressType
Definition: RIPRouting.h:144
Definition: RIPPacket_m.h:57
virtual void sendPacket(RIPPacket *packet, const L3Address &destAddr, int destPort, const InterfaceEntry *destInterface)
Sends the packet to the specified destination.
Definition: RIPRouting.cc:1040
static simsignal_t sentRequestSignal
Definition: RIPRouting.h:163
void inet::RIPRouting::sendRoutes ( const L3Address address,
int  port,
const RIPInterfaceEntry ripInterface,
bool  changedOnly 
)
protectedvirtual

Send all or changed part of the routing table to address/port on the specified interface.

This method is called by regular updates (every 30s), triggered updates (when some route changed), and when RIP requests are processed.

653 {
654  EV_DEBUG << "Sending " << (changedOnly ? "changed" : "all") << " routes on " << ripInterface.ie->getFullName() << std::endl;
655 
656  int maxEntries = mode == RIPv2 ? 25 : (ripInterface.ie->getMTU() - 40 /*IPv6_HEADER_BYTES*/ - 8 /*UDP_HEADER_BYTES*/ - RIP_HEADER_SIZE) / RIP_RTE_SIZE;
657 
658  RIPPacket *packet = new RIPPacket("RIP response");
659  packet->setCommand(RIP_RESPONSE);
660  packet->setEntryArraySize(maxEntries);
661  int k = 0; // index into RIP entries
662 
663  for (auto & elem : ripRoutes) {
664  RIPRoute *ripRoute = checkRouteIsExpired(elem);
665  if (!ripRoute)
666  continue;
667 
668  if (changedOnly && !ripRoute->isChanged())
669  continue;
670 
671  // Split Horizon check:
672  // Omit routes learned from one neighbor in updates sent to that neighbor.
673  // In the case of a broadcast network, all routes learned from any neighbor on
674  // that network are omitted from updates sent on that network.
675  // Split Horizon with Poisoned Reverse:
676  // Do include such routes in updates, but sets their metrics to infinity.
677  int metric = ripRoute->getMetric();
678  if (ripRoute->getInterface() == ripInterface.ie) {
679  if (ripInterface.mode == SPLIT_HORIZON)
680  continue;
681  else if (ripInterface.mode == SPLIT_HORIZON_POISONED_REVERSE)
682  metric = RIP_INFINITE_METRIC;
683  }
684 
685  EV_DEBUG << "Add entry for " << ripRoute->getDestination() << "/" << ripRoute->getPrefixLength() << ": "
686  << " metric=" << metric << std::endl;
687 
688  // fill next entry
689  RIPEntry& entry = packet->getEntry(k++);
690  entry.addressFamilyId = RIP_AF_INET;
691  entry.address = ripRoute->getDestination();
692  entry.prefixLength = ripRoute->getPrefixLength();
693  entry.nextHop = addressType->getUnspecifiedAddress(); //route->getNextHop() if local ?
694  entry.routeTag = ripRoute->getRouteTag();
695  entry.metric = metric;
696 
697  // if packet is full, then send it and allocate a new one
698  if (k >= maxEntries) {
699  emit(sentUpdateSignal, packet);
700  sendPacket(packet, address, port, ripInterface.ie);
701  packet = new RIPPacket("RIP response");
702  packet->setCommand(RIP_RESPONSE);
703  packet->setEntryArraySize(maxEntries);
704  k = 0;
705  }
706  }
707 
708  // send last packet if it has entries
709  if (k > 0) {
710  packet->setEntryArraySize(k);
711  emit(sentUpdateSignal, packet);
712  sendPacket(packet, address, port, ripInterface.ie);
713  }
714  else
715  delete packet;
716 }
Mode mode
Definition: RIPRouting.h:154
const int RIP_HEADER_SIZE
Definition: RIPPacket_m.h:38
RouteVector ripRoutes
Definition: RIPRouting.h:147
Definition: RIPRouting.h:137
const int RIP_RTE_SIZE
Definition: RIPPacket_m.h:39
#define RIP_INFINITE_METRIC
Definition: RIPRouting.h:31
IL3AddressType * addressType
Definition: RIPRouting.h:144
Definition: RIPRouting.h:92
Definition: RIPPacket_m.h:78
virtual L3Address getUnspecifiedAddress() const =0
Definition: RIPRouting.h:91
Definition: RIPPacket_m.h:58
static simsignal_t sentUpdateSignal
Definition: RIPRouting.h:164
virtual void sendPacket(RIPPacket *packet, const L3Address &destAddr, int destPort, const InterfaceEntry *destInterface)
Sends the packet to the specified destination.
Definition: RIPRouting.cc:1040
const double k
Definition: QAM16Modulation.cc:24
virtual RIPRoute * checkRouteIsExpired(RIPRoute *route)
Should be called regularly to handle expiry and purge of routes.
Definition: RIPRouting.cc:978
void inet::RIPRouting::startRIPRouting ( )
protectedvirtual
449 {
451 
452  // configure interfaces
453  configureInterfaces(par("ripConfig").xmlValue());
454 
455  // import interface routes
457 
458  // subscribe to notifications
459  host->subscribe(NF_INTERFACE_CREATED, this);
460  host->subscribe(NF_INTERFACE_DELETED, this);
461  host->subscribe(NF_INTERFACE_STATE_CHANGED, this);
462  host->subscribe(NF_ROUTE_DELETED, this);
463  host->subscribe(NF_ROUTE_ADDED, this);
464  host->subscribe(NF_ROUTE_CHANGED, this);
465 
466  // configure socket
467  socket.setMulticastLoop(false);
469 
470  for (auto & elem : ripInterfaces)
471  if (elem.mode != NO_RIP)
473 
474 
475  for (auto & elem : ripInterfaces)
476  if (elem.mode != NO_RIP)
477  sendRIPRequest(elem);
478 
479 
480  // set update timer
481  scheduleAt(simTime() + updateInterval, updateTimer);
482 }
cModule * host
Definition: RIPRouting.h:141
virtual void configureInterfaces(cXMLElement *config)
Creates a RIPInterfaceEntry for each interface found in the interface table.
Definition: RIPRouting.cc:232
int ripUdpPort
Definition: RIPRouting.h:155
simsignal_t NF_ROUTE_DELETED
Definition: NotifierConsts.cc:58
simtime_t updateInterval
Definition: RIPRouting.h:156
void setMulticastLoop(bool value)
The boolean value specifies whether sent multicast packets should be looped back to the local sockets...
Definition: UDPSocket.cc:161
IRoutingTable * rt
Definition: RIPRouting.h:143
UDPSocket socket
Definition: RIPRouting.h:148
InterfaceVector ripInterfaces
Definition: RIPRouting.h:146
virtual L3Address getLinkLocalRIPRoutersMulticastAddress() const =0
IL3AddressType * addressType
Definition: RIPRouting.h:144
virtual void sendRIPRequest(const RIPInterfaceEntry &ripInterface)
Sends a RIP request to routers on the specified link.
Definition: RIPRouting.cc:293
Definition: RIPRouting.h:89
virtual void configureInitialRoutes()
Import interface/static/default routes from the routing table.
Definition: RIPRouting.cc:249
simsignal_t NF_INTERFACE_STATE_CHANGED
Definition: NotifierConsts.cc:50
IL3AddressType * getAddressType() const
Definition: L3Address.cc:60
simsignal_t NF_INTERFACE_CREATED
Definition: NotifierConsts.cc:48
simsignal_t NF_ROUTE_CHANGED
Definition: NotifierConsts.cc:59
simsignal_t NF_ROUTE_ADDED
Definition: NotifierConsts.cc:57
void joinMulticastGroup(const L3Address &multicastAddr, int interfaceId=-1)
Adds the socket to the given multicast group, that is, UDP packets arriving to the given multicast ad...
Definition: UDPSocket.cc:181
cMessage * updateTimer
Definition: RIPRouting.h:149
simsignal_t NF_INTERFACE_DELETED
Definition: NotifierConsts.cc:49
void bind(int localPort)
Bind the socket to a local port number.
Definition: UDPSocket.cc:53
virtual L3Address getRouterIdAsGeneric() const =0
Returns routerId.
void inet::RIPRouting::stopRIPRouting ( )
protectedvirtual
485 {
486  if (startupTimer->isScheduled())
487  cancelEvent(startupTimer);
488  else {
489  socket.close();
490 
491  // unsubscribe to notifications
492  host->unsubscribe(NF_INTERFACE_CREATED, this);
493  host->unsubscribe(NF_INTERFACE_DELETED, this);
494  host->unsubscribe(NF_INTERFACE_STATE_CHANGED, this);
495  host->unsubscribe(NF_ROUTE_DELETED, this);
496  host->unsubscribe(NF_ROUTE_ADDED, this);
497  host->unsubscribe(NF_ROUTE_CHANGED, this);
498  }
499 
500  // cancel timers
501  cancelEvent(updateTimer);
502  cancelEvent(triggeredUpdateTimer);
503 
504  // clear data
505  for (auto& elem : ripRoutes)
506  delete elem;
507  ripRoutes.clear();
508  ripInterfaces.clear();
509 }
cModule * host
Definition: RIPRouting.h:141
simsignal_t NF_ROUTE_DELETED
Definition: NotifierConsts.cc:58
RouteVector ripRoutes
Definition: RIPRouting.h:147
UDPSocket socket
Definition: RIPRouting.h:148
InterfaceVector ripInterfaces
Definition: RIPRouting.h:146
cMessage * startupTimer
Definition: RIPRouting.h:151
void close()
Unbinds the socket.
Definition: UDPSocket.cc:112
simsignal_t NF_INTERFACE_STATE_CHANGED
Definition: NotifierConsts.cc:50
simsignal_t NF_INTERFACE_CREATED
Definition: NotifierConsts.cc:48
simsignal_t NF_ROUTE_CHANGED
Definition: NotifierConsts.cc:59
simsignal_t NF_ROUTE_ADDED
Definition: NotifierConsts.cc:57
cMessage * updateTimer
Definition: RIPRouting.h:149
cMessage * triggeredUpdateTimer
Definition: RIPRouting.h:150
simsignal_t NF_INTERFACE_DELETED
Definition: NotifierConsts.cc:49
void inet::RIPRouting::triggerUpdate ( )
protectedvirtual

Sets the update timer to trigger an update in the [1s,5s] interval.

If the update is already scheduled, it does nothing.

963 {
964  if (!triggeredUpdateTimer->isScheduled()) {
965  double delay = par("triggeredUpdateDelay");
966  simtime_t updateTime = simTime() + delay;
967  // Triggered updates may be suppressed if a regular
968  // update is due by the time the triggered update would be sent.
969  if (!updateTimer->isScheduled() || updateTimer->getArrivalTime() > updateTime)
970  scheduleAt(updateTime, triggeredUpdateTimer);
971  }
972 }
cMessage * updateTimer
Definition: RIPRouting.h:149
cMessage * triggeredUpdateTimer
Definition: RIPRouting.h:150
void inet::RIPRouting::updateRoute ( RIPRoute ripRoute,
const InterfaceEntry ie,
const L3Address nextHop,
int  metric,
uint16  routeTag,
const L3Address from 
)
protectedvirtual

Updates an existing route with the information learned from a RIP packet.

If the metric is infinite (16), then the route is invalidated. It triggers an update, so neighbor routers are notified about the change.

RFC 2453 3.9.2:

Do the following actions:

  • Adopt the route from the datagram (i.e., put the new metric in and adjust the next hop address, if necessary).
  • Set the route change flag and signal the output process to trigger an update
  • If the new metric is infinity, start the deletion process (described above); otherwise, re-initialize the timeout
914 {
915  //ASSERT(ripRoute && ripRoute->getType() == RIPRoute::RIP_ROUTE_RTE);
916  //ASSERT(!ripRoute->getRoute() || ripRoute->getRoute()->getSource() == this);
917 
918  EV_DEBUG << "Updating route to " << ripRoute->getDestination() << "/" << ripRoute->getPrefixLength() << ": "
919  << "nextHop=" << nextHop << " metric=" << metric << std::endl;
920 
921  int oldMetric = ripRoute->getMetric();
922  ripRoute->setInterface(const_cast<InterfaceEntry *>(ie));
923  ripRoute->setMetric(metric);
924  ripRoute->setFrom(from);
925  ripRoute->setRouteTag(routeTag);
926 
927  if (oldMetric == RIP_INFINITE_METRIC && metric < RIP_INFINITE_METRIC) {
928  ASSERT(!ripRoute->getRoute());
929  ripRoute->setType(RIPRoute::RIP_ROUTE_RTE);
930  ripRoute->setNextHop(nextHop);
931 
932  IRoute *route = addRoute(ripRoute->getDestination(), ripRoute->getPrefixLength(), ie, nextHop, metric);
933  ripRoute->setRoute(route);
934  }
935  if (oldMetric != RIP_INFINITE_METRIC) {
936  IRoute *route = ripRoute->getRoute();
937  ASSERT(route);
938 
939  ripRoute->setRoute(nullptr);
940  deleteRoute(route);
941 
942  ripRoute->setNextHop(nextHop);
943  if (metric < RIP_INFINITE_METRIC) {
944  route = addRoute(ripRoute->getDestination(), ripRoute->getPrefixLength(), ie, nextHop, metric);
945  ripRoute->setRoute(route);
946  }
947  }
948 
949  ripRoute->setChanged(true);
950  triggerUpdate();
951 
952  if (metric == RIP_INFINITE_METRIC && oldMetric != RIP_INFINITE_METRIC)
953  invalidateRoute(ripRoute);
954  else
955  ripRoute->setLastUpdateTime(simTime());
956 }
void deleteRoute(IRoute *route)
Definition: RIPRouting.cc:1165
#define RIP_INFINITE_METRIC
Definition: RIPRouting.h:31
virtual void triggerUpdate()
Sets the update timer to trigger an update in the [1s,5s] interval.
Definition: RIPRouting.cc:962
virtual void invalidateRoute(RIPRoute *route)
Definition: RIPRouting.cc:1005
IRoute * addRoute(const L3Address &dest, int prefixLength, const InterfaceEntry *ie, const L3Address &nextHop, int metric)
Definition: RIPRouting.cc:1151
Definition: RIPRouting.h:36

Member Data Documentation

IL3AddressType* inet::RIPRouting::addressType = nullptr
private
simsignal_t inet::RIPRouting::badResponseSignal = registerSignal("badResponse")
staticprivate

Referenced by ~RIPRouting().

cModule* inet::RIPRouting::host = nullptr
private
IInterfaceTable* inet::RIPRouting::ift = nullptr
private
bool inet::RIPRouting::isOperational = false
private
Mode inet::RIPRouting::mode = (Mode)-1
private
simsignal_t inet::RIPRouting::numRoutesSignal = registerSignal("numRoutes")
staticprivate

Referenced by ~RIPRouting().

simsignal_t inet::RIPRouting::rcvdResponseSignal = registerSignal("rcvdResponse")
staticprivate

Referenced by ~RIPRouting().

InterfaceVector inet::RIPRouting::ripInterfaces
private
RouteVector inet::RIPRouting::ripRoutes
private
int inet::RIPRouting::ripUdpPort = -1
private
simtime_t inet::RIPRouting::routeExpiryTime
private
simtime_t inet::RIPRouting::routePurgeTime
private
IRoutingTable* inet::RIPRouting::rt = nullptr
private
simsignal_t inet::RIPRouting::sentRequestSignal = registerSignal("sentRequest")
staticprivate

Referenced by ~RIPRouting().

simsignal_t inet::RIPRouting::sentUpdateSignal = registerSignal("sentUpdate")
staticprivate

Referenced by ~RIPRouting().

simtime_t inet::RIPRouting::shutdownTime
private
cMessage* inet::RIPRouting::shutdownTimer = nullptr
private
UDPSocket inet::RIPRouting::socket
private
cMessage* inet::RIPRouting::startupTimer = nullptr
private
cMessage* inet::RIPRouting::triggeredUpdateTimer = nullptr
private
simtime_t inet::RIPRouting::updateInterval
private
cMessage* inet::RIPRouting::updateTimer = nullptr
private

The documentation for this class was generated from the following files: