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

Implementation of the Routing Information Protocol. More...

#include <Rip.h>

Inheritance diagram for inet::Rip:
inet::RoutingProtocolBase inet::OperationalBase inet::OperationalMixin< cSimpleModule > inet::ILifecycle

Public Member Functions

 Rip ()
 
 ~Rip ()
 
- Public Member Functions inherited from inet::RoutingProtocolBase
 RoutingProtocolBase ()
 
- Public Member Functions inherited from inet::OperationalMixin< cSimpleModule >
virtual ~OperationalMixin ()
 }@ More...
 
- 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 handleMessageWhenUp (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 void handleStartOperation (LifecycleOperation *operation) override
 
virtual void handleStopOperation (LifecycleOperation *operation) override
 
virtual void handleCrashOperation (LifecycleOperation *operation) override
 
virtual void startRIPRouting ()
 
virtual void stopRIPRouting ()
 
virtual RipRouteimportRoute (IRoute *route, RipRoute::RouteType type, int metric=1, uint16_t routeTag=0)
 Adds a new route the RIP routing table for an existing IRoute. More...
 
virtual void sendRIPRequest (const RipNetworkInterface &ripInterface)
 Sends a RIP request to routers on the specified link. More...
 
virtual void processRequest (Packet *pk)
 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 RipNetworkInterface &ripInterface, bool changedOnly)
 Send all or changed part of the routing table to address/port on the specified interface. More...
 
virtual void processResponse (Packet *pk)
 Processes the RIP response and updates the routing table. More...
 
virtual bool isValidResponse (Packet *packet)
 
virtual void updateRoute (RipRoute *route, const NetworkInterface *ie, const L3Address &nextHop, int metric, uint16_t routeTag, const L3Address &from)
 Updates an existing route with the information learned from a RIP packet. More...
 
virtual void addRoute (const L3Address &dest, int prefixLength, const NetworkInterface *ie, const L3Address &nextHop, int metric, uint16_t routeTag, const L3Address &from)
 RFC 2453 3.9.2: More...
 
virtual void checkExpiredRoutes ()
 Should be called regularly to handle expiry and purge of routes. More...
 
virtual void invalidateRoute (RipRoute *route)
 
virtual RouteVector::iterator purgeRoute (RipRoute *route)
 Removes the route from the routing table. More...
 
virtual void triggerUpdate ()
 Sets the update timer to trigger an update in the [1s,5s] interval. More...
 
virtual void sendPacket (Packet *packet, const L3Address &destAddr, int destPort, const NetworkInterface *destInterface)
 Sends the packet to the specified destination. More...
 
- Protected Member Functions inherited from inet::RoutingProtocolBase
virtual bool isInitializeStage (int stage) const override
 
virtual bool isModuleStartStage (int stage) const override
 
virtual bool isModuleStopStage (int stage) const override
 
- Protected Member Functions inherited from inet::OperationalMixin< cSimpleModule >
virtual int numInitStages () const override
 
virtual void refreshDisplay () const override
 
virtual void handleMessage (cMessage *msg) override
 
virtual void handleMessageWhenDown (cMessage *msg)
 
virtual bool handleOperationStage (LifecycleOperation *operation, IDoneCallback *doneCallback) override
 Perform one stage of a lifecycle operation. More...
 
virtual State getInitialOperationalState () const
 Returns initial operational state: OPERATING or NOT_OPERATING. More...
 
virtual void handleActiveOperationTimeout (cMessage *message)
 
virtual bool isUp () const
 utility functions More...
 
virtual bool isDown () const
 
virtual void setOperationalState (State newState)
 
virtual void scheduleOperationTimeout (simtime_t timeout)
 
virtual void setupActiveOperation (LifecycleOperation *operation, IDoneCallback *doneCallback, State)
 
virtual void delayActiveOperationFinish (simtime_t timeout)
 
virtual void startActiveOperationExtraTime (simtime_t delay=SIMTIME_ZERO)
 
virtual void startActiveOperationExtraTimeOrFinish (simtime_t extraTime)
 
virtual void finishActiveOperation ()
 

Private Types

enum  Mode { RIPv2, RIPng }
 
typedef std::vector< RipNetworkInterfaceInterfaceVector
 
typedef std::vector< RipRoute * > RouteVector
 

Private Member Functions

RipNetworkInterfacefindRipInterfaceById (int interfaceId)
 
RipRoutefindRipRoute (const L3Address &destAddress, int prefixLength)
 
RipRoutefindRipRoute (const L3Address &destination, int prefixLength, RipRoute::RouteType type)
 
RipRoutefindRipRoute (const IRoute *route)
 
RipRoutefindRipRoute (const NetworkInterface *ie, RipRoute::RouteType type)
 
void addRipInterface (const NetworkInterface *ie, cXMLElement *config)
 
void deleteRipInterface (const NetworkInterface *ie)
 
int getInterfaceMetric (NetworkInterface *ie)
 
IRoutecreateRoute (const L3Address &dest, int prefixLength, const NetworkInterface *ie, const L3Address &nextHop, int metric)
 
bool isLoopbackInterfaceRoute (const IRoute *route)
 
bool isLocalInterfaceRoute (const IRoute *route)
 
bool isDefaultRoute (const IRoute *route)
 

Private Attributes

cModule * host = nullptr
 
ModuleRefByPar< IInterfaceTableift
 
ModuleRefByPar< IRoutingTablert
 
IL3AddressTypeaddressType = nullptr
 
InterfaceVector ripInterfaces
 
RouteVector ripRoutingTable
 
UdpSocket socket
 
cMessage * updateTimer = nullptr
 
cMessage * triggeredUpdateTimer = nullptr
 
cMessage * startupTimer = nullptr
 
cMessage * shutdownTimer = nullptr
 
Mode mode = static_cast<Mode>(-1)
 
int ripUdpPort = -1
 
simtime_t updateInterval
 
simtime_t routeExpiryTime
 
simtime_t routePurgeTime
 
simtime_t holdDownTime
 
simtime_t shutdownTime
 
bool triggeredUpdate = 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")
 

Additional Inherited Members

- Protected Types inherited from inet::OperationalMixin< cSimpleModule >
enum  State
 
- Protected Attributes inherited from inet::OperationalMixin< cSimpleModule >
State operationalState
 
simtime_t lastChange
 
Operation activeOperation
 
cMessage * activeOperationTimeout
 
cMessage * activeOperationExtraTimer
 

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

◆ InterfaceVector

typedef std::vector<RipNetworkInterface> inet::Rip::InterfaceVector
private

◆ RouteVector

typedef std::vector<RipRoute *> inet::Rip::RouteVector
private

Member Enumeration Documentation

◆ Mode

enum inet::Rip::Mode
private
Enumerator
RIPv2 
RIPng 
82 { RIPv2, RIPng };

Constructor & Destructor Documentation

◆ Rip()

inet::Rip::Rip ( )
70 {
71 }

◆ ~Rip()

inet::Rip::~Rip ( )
74 {
75  for (auto& elem : ripRoutingTable)
76  delete elem;
77  ripRoutingTable.clear();
78  cancelAndDelete(updateTimer);
79  cancelAndDelete(triggeredUpdateTimer);
80  cancelAndDelete(startupTimer);
81  cancelAndDelete(shutdownTimer);
82 }

Member Function Documentation

◆ addRipInterface()

void inet::Rip::addRipInterface ( const NetworkInterface ie,
cXMLElement *  config 
)
private
1040 {
1041  RipNetworkInterface ripInterface(ie);
1042 
1043  // Fills in the parameters of the interface from the matching <interface>
1044  // element of the configuration.
1045  if (config) {
1046  const char *metricAttr = config->getAttribute("metric");
1047 
1048  if (metricAttr) {
1049  int metric = atoi(metricAttr);
1050  if (metric < 0 || metric >= RIP_INFINITE_METRIC)
1051  throw cRuntimeError("RIP: invalid metric in <interface> element at %s: %s", config->getSourceLocation(), metricAttr);
1052  ripInterface.metric = metric;
1053  }
1054 
1055  const char *ripModeAttr = config->getAttribute("mode");
1056  RipMode mode = !ripModeAttr ? SPLIT_HORIZON_POISON_REVERSE :
1057  strcmp(ripModeAttr, "NoRIP") == 0 ? NO_RIP :
1058  strcmp(ripModeAttr, "PASSIVE") == 0 ? PASSIVE :
1059  strcmp(ripModeAttr, "NoSplitHorizon") == 0 ? NO_SPLIT_HORIZON :
1060  strcmp(ripModeAttr, "SplitHorizon") == 0 ? SPLIT_HORIZON :
1061  strcmp(ripModeAttr, "SplitHorizonPoisonReverse") == 0 ? SPLIT_HORIZON_POISON_REVERSE :
1062  strcmp(ripModeAttr, "SplitHorizonPoisonedReverse") == 0 ? SPLIT_HORIZON_POISON_REVERSE : // TODO left here for backward compatibility, delete this line eventually
1063  static_cast<RipMode>(-1);
1064 
1065  if (mode == static_cast<RipMode>(-1))
1066  throw cRuntimeError("RIP: invalid mode attribute in <interface> element at %s: %s",
1067  config->getSourceLocation(), ripModeAttr);
1068  ripInterface.mode = mode;
1069  }
1070 
1071  ripInterfaces.push_back(ripInterface);
1072 }

Referenced by receiveSignal(), and startRIPRouting().

◆ addRoute()

void inet::Rip::addRoute ( const L3Address dest,
int  prefixLength,
const NetworkInterface ie,
const L3Address nextHop,
int  metric,
uint16_t  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
804 {
805  EV_DEBUG << "Add route to " << dest << "/" << prefixLength << ": "
806  << "nextHop=" << nextHop << " metric=" << metric << std::endl;
807 
808  IRoute *route = createRoute(dest, prefixLength, ie, nextHop, metric);
809 
810  RipRoute *ripRoute = new RipRoute(route, RipRoute::RIP_ROUTE_RTE, metric, routeTag);
811  ripRoute->setFrom(from);
812  ripRoute->setLastUpdateTime(simTime());
813  ripRoute->setChanged(true);
814  ripRoutingTable.push_back(ripRoute);
815 
816  emit(numRoutesSignal, (unsigned long)ripRoutingTable.size());
817  triggerUpdate();
818 }

Referenced by processResponse().

◆ checkExpiredRoutes()

void inet::Rip::checkExpiredRoutes ( )
protectedvirtual

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

902 {
903  // iterate over each rip route and check if it has expired
904  // note that the iterator becomes invalid after calling purgeRoute
905  for (RouteVector::iterator iter = ripRoutingTable.begin(); iter != ripRoutingTable.end();) {
906  RipRoute *ripRoute = (*iter);
907  if (ripRoute->getType() == RipRoute::RIP_ROUTE_RTE) {
908  simtime_t now = simTime();
909  if (now >= ripRoute->getLastUpdateTime() + routeExpiryTime + routePurgeTime) {
910  iter = purgeRoute(ripRoute);
911  continue;
912  }
913  else if (now >= ripRoute->getLastUpdateTime() + routeExpiryTime)
914  invalidateRoute(ripRoute);
915  }
916 
917  iter++;
918  }
919 }

Referenced by sendRoutes().

◆ createRoute()

IRoute * inet::Rip::createRoute ( const L3Address dest,
int  prefixLength,
const NetworkInterface ie,
const L3Address nextHop,
int  metric 
)
private
1104 {
1105  // create a new route
1106  IRoute *route = rt->createRoute();
1107 
1108  // adding generic fields
1109  route->setDestination(dest);
1110  route->setNextHop(nextHop);
1111  route->setPrefixLength(prefixLength);
1112  route->setMetric(metric);
1113  route->setAdminDist(IRoute::dRIP);
1114  route->setInterface(const_cast<NetworkInterface *>(ie));
1115  route->setSourceType(IRoute::RIP);
1116  route->setSource(this);
1117 
1118  EV_DETAIL << "Adding new route " << route << endl;
1119  rt->addRoute(route);
1120 
1121  return route;
1122 }

Referenced by addRoute(), and updateRoute().

◆ deleteRipInterface()

void inet::Rip::deleteRipInterface ( const NetworkInterface ie)
private
1075 {
1076  // delete interfaces and routes referencing ie
1077  for (auto it = ripInterfaces.begin(); it != ripInterfaces.end();) {
1078  if (it->ie == ie)
1079  it = ripInterfaces.erase(it);
1080  else
1081  it++;
1082  }
1083  bool emitNumRoutesSignal = false;
1084  for (auto it = ripRoutingTable.begin(); it != ripRoutingTable.end();) {
1085  if ((*it)->getInterface() == ie) {
1086  delete *it;
1087  it = ripRoutingTable.erase(it);
1088  emitNumRoutesSignal = true;
1089  }
1090  else
1091  it++;
1092  }
1093  if (emitNumRoutesSignal)
1094  emit(numRoutesSignal, (unsigned long)ripRoutingTable.size());
1095 }

Referenced by receiveSignal().

◆ findRipInterfaceById()

RipNetworkInterface * inet::Rip::findRipInterfaceById ( int  interfaceId)
private
995 {
996  for (auto& elem : ripInterfaces)
997  if (elem.ie->getInterfaceId() == interfaceId)
998  return &(elem);
999 
1000  return nullptr;
1001 }

Referenced by getInterfaceMetric(), processRequest(), processResponse(), receiveSignal(), and startRIPRouting().

◆ findRipRoute() [1/4]

RipRoute * inet::Rip::findRipRoute ( const IRoute route)
private
1022 {
1023  for (auto& elem : ripRoutingTable)
1024  if ((elem)->getRoute() == route)
1025  return elem;
1026 
1027  return nullptr;
1028 }

◆ findRipRoute() [2/4]

RipRoute * inet::Rip::findRipRoute ( const L3Address destAddress,
int  prefixLength 
)
private
1004 {
1005  for (auto& elem : ripRoutingTable)
1006  if ((elem)->getDestination() == destination && (elem)->getPrefixLength() == prefixLength)
1007  return elem;
1008 
1009  return nullptr;
1010 }

Referenced by processRequest(), processResponse(), and receiveSignal().

◆ findRipRoute() [3/4]

RipRoute * inet::Rip::findRipRoute ( const L3Address destination,
int  prefixLength,
RipRoute::RouteType  type 
)
private
1013 {
1014  for (auto& elem : ripRoutingTable)
1015  if ((elem)->getType() == type && (elem)->getDestination() == destination && (elem)->getPrefixLength() == prefixLength)
1016  return elem;
1017 
1018  return nullptr;
1019 }

◆ findRipRoute() [4/4]

RipRoute * inet::Rip::findRipRoute ( const NetworkInterface ie,
RipRoute::RouteType  type 
)
private
1031 {
1032  for (auto& elem : ripRoutingTable)
1033  if ((elem)->getType() == type && (elem)->getInterface() == ie)
1034  return elem;
1035 
1036  return nullptr;
1037 }

◆ getInterfaceMetric()

int inet::Rip::getInterfaceMetric ( NetworkInterface ie)
private
1098 {
1099  RipNetworkInterface *ripIe = findRipInterfaceById(ie->getInterfaceId());
1100  return ripIe ? ripIe->metric : 1;
1101 }

Referenced by receiveSignal(), and startRIPRouting().

◆ handleCrashOperation()

void inet::Rip::handleCrashOperation ( LifecycleOperation operation)
overrideprotectedvirtual

Implements inet::OperationalMixin< cSimpleModule >.

428 {
429  stopRIPRouting();
430 }

◆ handleMessageWhenUp()

void inet::Rip::handleMessageWhenUp ( cMessage *  msg)
overrideprotectedvirtual

Implements inet::OperationalMixin< cSimpleModule >.

129 {
130  if (msg->isSelfMessage()) {
131  if (msg == updateTimer) {
132  processUpdate(false);
133  scheduleAfter(updateInterval, msg);
134  }
135  else if (msg == triggeredUpdateTimer) {
136  processUpdate(true);
137  }
138  else if (msg == startupTimer) {
139  startRIPRouting();
140  }
141  else if (msg == shutdownTimer) {
142  ASSERT(operationalState == State::STOPPING_OPERATION);
144  }
145  else
146  throw cRuntimeError("unknown self message");
147  }
148  else if (msg->getKind() == UDP_I_DATA) {
149  Packet *pk = check_and_cast<Packet *>(msg);
150  unsigned char command = pk->peekAtFront<RipPacket>()->getCommand();
151  if (command == RIP_REQUEST)
152  processRequest(pk);
153  else if (command == RIP_RESPONSE)
154  processResponse(pk);
155  else
156  throw cRuntimeError("RIP: unknown command (%d)", (int)command);
157  }
158  else if (msg->getKind() == UDP_I_ERROR) {
159  EV_DETAIL << "Ignoring UDP error report\n";
160  delete msg;
161  }
162  else if (msg->getKind() == UDP_I_SOCKET_CLOSED) {
163  EV_DETAIL << "Ignoring UDP socket closed indication\n";
164  delete msg;
165  }
166  else
167  throw cRuntimeError("RIP: unknown msg kind (%d)", (int)msg->getKind());
168 }

◆ handleStartOperation()

void inet::Rip::handleStartOperation ( LifecycleOperation operation)
overrideprotectedvirtual

Implements inet::OperationalMixin< cSimpleModule >.

407 {
408  rescheduleAfter(par("startupTime"), startupTimer);
409 }

◆ handleStopOperation()

void inet::Rip::handleStopOperation ( LifecycleOperation operation)
overrideprotectedvirtual

Implements inet::OperationalMixin< cSimpleModule >.

412 {
413  // invalidate routes
414  for (auto& elem : ripRoutingTable)
415  invalidateRoute(elem);
416  // send updates to neighbors
417  for (auto& elem : ripInterfaces)
419 
420  stopRIPRouting();
421 
422  // wait a few seconds before calling doneCallback, so that UDP can send the messages
423  scheduleAfter(shutdownTime, shutdownTimer);
424  delayActiveOperationFinish(par("stopOperationTimeout"));
425 }

◆ importRoute()

RipRoute * inet::Rip::importRoute ( IRoute route,
RipRoute::RouteType  type,
int  metric = 1,
uint16_t  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.

264 {
265  ASSERT(metric < RIP_INFINITE_METRIC);
266 
267  RipRoute *ripRoute = new RipRoute(route, type, metric, routeTag);
269  NetworkInterface *ie = check_and_cast<NetworkInterface *>(route->getSource());
270  ripRoute->setInterface(ie);
271  }
272 
273  ripRoutingTable.push_back(ripRoute);
274  emit(numRoutesSignal, (unsigned long)ripRoutingTable.size());
275  return ripRoute;
276 }

Referenced by receiveSignal(), and startRIPRouting().

◆ initialize()

void inet::Rip::initialize ( int  stage)
overrideprotectedvirtual

Reimplemented from inet::OperationalMixin< cSimpleModule >.

91 {
93 
94  if (stage == INITSTAGE_LOCAL) {
95  host = getContainingNode(this);
96  ift.reference(this, "interfaceTableModule", true);
97  rt.reference(this, "routingTableModule", true);
98  socket.setOutputGate(gate("socketOut"));
99 
100  const char *m = par("mode");
101  if (!m)
102  throw cRuntimeError("Missing 'mode' parameter.");
103  else if (!strcmp(m, "RIPv2"))
104  mode = RIPv2;
105  else if (!strcmp(m, "RIPng"))
106  mode = RIPng;
107  else
108  throw cRuntimeError("Unrecognized 'mode' parameter: %s", m);
109 
110  ripUdpPort = par("udpPort");
111  updateInterval = par("updateInterval");
112  routeExpiryTime = par("routeExpiryTime");
113  routePurgeTime = par("routePurgeTime");
114  holdDownTime = par("holdDownTime");
115  shutdownTime = par("shutdownTime");
116  triggeredUpdate = par("triggeredUpdate");
117 
118  updateTimer = new cMessage("RIP-timer");
119  triggeredUpdateTimer = new cMessage("RIP-trigger");
120  startupTimer = new cMessage("RIP-startup");
121  shutdownTimer = new cMessage("RIP-shutdown");
122 
123  WATCH_VECTOR(ripInterfaces);
124  WATCH_PTRVECTOR(ripRoutingTable);
125  }
126 }

◆ invalidateRoute()

void inet::Rip::invalidateRoute ( RipRoute route)
protectedvirtual
933 {
934  EV_INFO << "invalidating route dest:" << ripRoute->getDestination() << "\n";
935 
936  IRoute *route = ripRoute->getRoute();
937  if (route) {
938  ripRoute->setRoute(nullptr);
939  rt->deleteRoute(route);
940  }
941  ripRoute->setMetric(RIP_INFINITE_METRIC);
942  ripRoute->setChanged(true);
943  ripRoute->setLastInvalidationTime(simTime());
944  triggerUpdate();
945 }

Referenced by checkExpiredRoutes(), handleStopOperation(), receiveSignal(), and updateRoute().

◆ isDefaultRoute()

bool inet::Rip::isDefaultRoute ( const IRoute route)
inlineprivate
177 { return route->getPrefixLength() == 0; }

Referenced by startRIPRouting().

◆ isLocalInterfaceRoute()

bool inet::Rip::isLocalInterfaceRoute ( const IRoute route)
inlineprivate
172  {
173  NetworkInterface *ie = dynamic_cast<NetworkInterface *>(route->getSource());
174  return ie && !ie->isLoopback();
175  }

Referenced by receiveSignal(), and startRIPRouting().

◆ isLoopbackInterfaceRoute()

bool inet::Rip::isLoopbackInterfaceRoute ( const IRoute route)
inlineprivate
167  {
168  NetworkInterface *ie = dynamic_cast<NetworkInterface *>(route->getSource());
169  return ie && ie->isLoopback();
170  }

Referenced by receiveSignal(), and startRIPRouting().

◆ isValidResponse()

bool inet::Rip::isValidResponse ( Packet packet)
protectedvirtual
721 {
722  // check that received from ripUdpPort
723  if (packet->getTag<L4PortInd>()->getSrcPort() != ripUdpPort) {
724  EV_WARN << "source port is not " << ripUdpPort << "\n";
725  return false;
726  }
727 
728  L3Address srcAddr = packet->getTag<L3AddressInd>()->getSrcAddress();
729 
730  // check that it is not our response (received own multicast message)
731  if (rt->isLocalAddress(srcAddr)) {
732  EV_WARN << "received own response\n";
733  return false;
734  }
735 
736  if (mode == RIPng) {
737  if (!srcAddr.isLinkLocal()) {
738  EV_WARN << "source address is not link-local: " << srcAddr << "\n";
739  return false;
740  }
741  if (packet->getTag<HopLimitInd>()->getHopLimit() != 255) {
742  EV_WARN << "ttl is not 255";
743  return false;
744  }
745  }
746  else {
747  // check that source is on a directly connected network
748  if (!ift->isNeighborAddress(srcAddr)) {
749  EV_WARN << "source is not directly connected " << srcAddr << "\n";
750  return false;
751  }
752  }
753 
754  const auto& ripPacket = packet->peekAtFront<RipPacket>();
755  // validate entries
756  int numEntries = ripPacket->getEntryArraySize();
757  for (int i = 0; i < numEntries; ++i) {
758  const RipEntry& entry = ripPacket->getEntry(i);
759 
760  // check that metric is in range [0,16]
761  if (entry.metric < 0 || entry.metric > RIP_INFINITE_METRIC) {
762  EV_WARN << "received metric is not in the [0," << RIP_INFINITE_METRIC << "] range.\n";
763  return false;
764  }
765 
766  // check that destination address is a unicast address
767  // TODO exclude 0.x.x.x, 127.x.x.x too
768  if (!entry.address.isUnicast()) {
769  EV_WARN << "destination address of an entry is not unicast: " << entry.address << "\n";
770  return false;
771  }
772 
773  if (mode == RIPng) {
774  if (entry.address.isLinkLocal()) {
775  EV_WARN << "destination address of an entry is link-local: " << entry.address << "\n";
776  return false;
777  }
778  if (entry.prefixLength < 0 || entry.prefixLength > addressType->getMaxPrefixLength()) {
779  EV_WARN << "prefixLength is outside of the [0," << addressType->getMaxPrefixLength() << "] interval\n";
780  return false;
781  }
782  }
783  }
784 
785  return true;
786 }

Referenced by processResponse().

◆ numInitStages()

virtual int inet::Rip::numInitStages ( ) const
inlineoverrideprotectedvirtual
120 { return NUM_INIT_STAGES; }

◆ processRequest()

void inet::Rip::processRequest ( Packet 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 requester. 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).
472 {
473  const auto& ripPacket = dynamicPtrCast<RipPacket>(packet->peekAtFront<RipPacket>()->dupShared());
474 
475  int numEntries = ripPacket->getEntryArraySize();
476  if (numEntries == 0) {
477  EV_INFO << "received empty request, ignoring.\n";
478  delete packet;
479  return;
480  }
481 
482  L3Address srcAddr = packet->getTag<L3AddressInd>()->getSrcAddress();
483  int srcPort = packet->getTag<L4PortInd>()->getSrcPort();
484  int interfaceId = packet->getTag<InterfaceInd>()->getInterfaceId();
485 
486  EV_INFO << "received request from " << srcAddr << "\n";
487 
488  for (int i = 0; i < numEntries; ++i) {
489  RipEntry& entry = ripPacket->getEntryForUpdate(i);
490  switch (entry.addressFamilyId) {
491  case RIP_AF_NONE:
492  if (numEntries == 1 && entry.metric == RIP_INFINITE_METRIC) {
493  RipNetworkInterface *ripInterface = findRipInterfaceById(interfaceId);
494  if (ripInterface)
495  sendRoutes(srcAddr, srcPort, *ripInterface, false);
496  delete packet;
497  return;
498  }
499  else {
500  throw cRuntimeError("RIP: invalid request.");
501  }
502  break;
503 
504  case RIP_AF_INET: {
505  RipRoute *ripRoute = findRipRoute(entry.address, entry.prefixLength);
506  entry.metric = ripRoute ? ripRoute->getMetric() : RIP_INFINITE_METRIC;
507  // entry.nextHop, entry.routeTag?
508  break;
509  }
510 
511  default:
512  throw cRuntimeError("RIP: request has invalid addressFamilyId: %d.", (int)entry.addressFamilyId);
513  }
514  }
515 
516  ripPacket->setCommand(RIP_RESPONSE);
517  Packet *outPacket = new Packet("RIP response");
518  outPacket->insertAtBack(ripPacket);
519  socket.sendTo(outPacket, srcAddr, srcPort);
520 }

Referenced by handleMessageWhenUp().

◆ processResponse()

void inet::Rip::processResponse ( Packet 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)
643 {
644  emit(rcvdResponseSignal, packet);
645 
646  bool isValid = isValidResponse(packet);
647  if (!isValid) {
648  EV_INFO << "dropping invalid response.\n";
649  emit(badResponseSignal, packet);
650  delete packet;
651  return;
652  }
653 
654  L3Address srcAddr = packet->getTag<L3AddressInd>()->getSrcAddress();
655  int interfaceId = packet->getTag<InterfaceInd>()->getInterfaceId();
656  packet->clearTags();
657 
658  RipNetworkInterface *incomingIe = findRipInterfaceById(interfaceId);
659  if (!incomingIe) {
660  EV_INFO << "dropping unexpected RIP response.\n";
661  emit(badResponseSignal, packet);
662  delete packet;
663  return;
664  }
665 
666  const auto& ripPacket = packet->peekAtFront<RipPacket>();
667 
668  EV_INFO << "response received from " << srcAddr << "\n";
669  int numEntries = ripPacket->getEntryArraySize();
670  for (int i = 0; i < numEntries; ++i) {
671  const RipEntry& entry = ripPacket->getEntry(i);
672  int metric = std::min((int)entry.metric + std::max(incomingIe->metric, 1), RIP_INFINITE_METRIC);
673  L3Address nextHop = entry.nextHop.isUnspecified() ? srcAddr : entry.nextHop;
674 
675  RipRoute *ripRoute = findRipRoute(entry.address, entry.prefixLength);
676  if (ripRoute) {
677  RipRoute::RouteType routeType = ripRoute->getType();
678  int routeMetric = ripRoute->getMetric();
679  L3Address fromAddr = ripRoute->getFrom();
680 
681  if ((routeType == RipRoute::RIP_ROUTE_STATIC || routeType == RipRoute::RIP_ROUTE_DEFAULT) && routeMetric != RIP_INFINITE_METRIC)
682  continue;
683 
684  if (fromAddr == srcAddr)
685  ripRoute->setLastUpdateTime(simTime());
686 
687  if (metric < routeMetric || (fromAddr == srcAddr && routeMetric != metric)) {
688  bool preventRouteUpdate = false;
689  // we receive a route update that shows the unreachable route is now reachable
690  if (routeMetric == RIP_INFINITE_METRIC && metric < RIP_INFINITE_METRIC) {
691  if (holdDownTime > 0 && simTime() < ripRoute->getLastInvalidationTime() + holdDownTime) {
692  EV_DEBUG << "hold-down timer prevents update to route " << ripRoute->getDestination() << std::endl;
693  preventRouteUpdate = true;
694  }
695  else {
696  IRoute *route = ripRoute->getRoute();
697  if (route && route->getMetric() <= metric) {
698  EV_DEBUG << "existing route " << ripRoute->getDestination() << " has a better metric" << std::endl;
699  preventRouteUpdate = true;
700  }
701  }
702  }
703 
704  if (!preventRouteUpdate)
705  updateRoute(ripRoute, incomingIe->ie, nextHop, metric, entry.routeTag, srcAddr);
706  }
707 
708  // TODO RIPng: if the metric is the same as the old one, and the old route is about to expire (i.e. at least halfway to the expiration point)
709  // then update the old route with the new RTE
710  }
711  else {
712  if (metric != RIP_INFINITE_METRIC)
713  addRoute(entry.address, entry.prefixLength, incomingIe->ie, nextHop, metric, entry.routeTag, srcAddr);
714  }
715  }
716 
717  delete packet;
718 }

Referenced by handleMessageWhenUp().

◆ processUpdate()

void inet::Rip::processUpdate ( bool  triggered)
protectedvirtual

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

It either sends the changed/all routes to neighbors.

437 {
438  if (triggered)
439  EV_INFO << "sending triggered updates on all interfaces.\n";
440  else
441  EV_INFO << "sending regular updates on all interfaces\n";
442 
443  for (auto& ripInterface : ripInterfaces)
444  if (ripInterface.ie->isUp())
446 
447  // clear changed flags
448  for (auto& ripRoute : ripRoutingTable)
449  ripRoute->setChanged(false);
450 }

Referenced by handleMessageWhenUp().

◆ purgeRoute()

Rip::RouteVector::iterator inet::Rip::purgeRoute ( RipRoute route)
protectedvirtual

Removes the route from the routing table.

951 {
952  ASSERT(ripRoute->getType() == RipRoute::RIP_ROUTE_RTE);
953 
954  EV_INFO << "purging route dest:" << ripRoute->getDestination() << "\n";
955 
956  IRoute *route = ripRoute->getRoute();
957  if (route) {
958  ripRoute->setRoute(nullptr);
959  rt->deleteRoute(route);
960  }
961 
962  // erase the ripRoute from the vector
963  auto itt = ripRoutingTable.erase(find(ripRoutingTable, ripRoute));
964 
965  delete ripRoute;
966  ripRoute = nullptr;
967 
968  emit(numRoutesSignal, (unsigned long)ripRoutingTable.size());
969 
970  // return the iterator that points to the next element after the deleted one
971  return itt;
972 }

Referenced by checkExpiredRoutes().

◆ receiveSignal()

void inet::Rip::receiveSignal ( cComponent *  source,
simsignal_t  signalID,
cObject *  obj,
cObject *  details 
)
overrideprotectedvirtual

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

303 {
304  Enter_Method("%s", cComponent::getSignalName(signalID));
305 
306  const NetworkInterface *ie;
307  const NetworkInterfaceChangeDetails *change;
308 
309  if (signalID == interfaceCreatedSignal) {
310  // configure interface for RIP
311  ie = check_and_cast<const NetworkInterface *>(obj);
312  if (ie->isMulticast() && !ie->isLoopback()) {
313  cXMLElementList config = par("ripConfig").xmlValue()->getChildrenByTagName("interface");
314  int i = InterfaceMatcher(config).findMatchingSelector(ie);
315  if (i >= 0)
316  addRipInterface(ie, config[i]);
317  }
318  }
319  else if (signalID == interfaceDeletedSignal) {
320  // delete interfaces and routes referencing the deleted interface
321  ie = check_and_cast<const NetworkInterface *>(obj);
322  deleteRipInterface(ie);
323  }
324  else if (signalID == interfaceStateChangedSignal) {
325  change = check_and_cast<const NetworkInterfaceChangeDetails *>(obj);
326  auto fieldId = change->getFieldId();
327  if (fieldId == NetworkInterface::F_STATE || fieldId == NetworkInterface::F_CARRIER) {
328  ie = change->getNetworkInterface();
329  if (!ie->isUp()) {
330  for (auto& elem : ripRoutingTable)
331  if ((elem)->getInterface() == ie) {
332  invalidateRoute(elem);
333  }
334  }
335  else {
336  RipNetworkInterface *ripInterfacePtr = findRipInterfaceById(ie->getInterfaceId());
337  if (ripInterfacePtr && ripInterfacePtr->mode != NO_RIP && ripInterfacePtr->mode != PASSIVE)
338  sendRIPRequest(*ripInterfacePtr);
339  }
340  }
341  }
342  else if (signalID == routeDeletedSignal) {
343  // remove references to the deleted route and invalidate the RIP route
344  const IRoute *route = check_and_cast<const IRoute *>(obj);
345  for (auto& elem : ripRoutingTable) {
346  if ((elem)->getRoute() == route) {
347  (elem)->setRoute(nullptr);
348  if (route->getSource() != this) {
349  invalidateRoute(elem);
350  }
351  }
352  }
353  }
354  else if (signalID == routeAddedSignal) {
355  // add or update the RIP route
356  IRoute *route = const_cast<IRoute *>(check_and_cast<const IRoute *>(obj));
357  if (route->getSource() != this) {
358  if (isLoopbackInterfaceRoute(route))
359  ; // void
360  else if (isLocalInterfaceRoute(route)) {
361  NetworkInterface *ie = check_and_cast<NetworkInterface *>(route->getSource());
362  RipRoute *ripRoute = findRipRoute(ie, RipRoute::RIP_ROUTE_INTERFACE);
363  if (ripRoute) { // readded
364  RipNetworkInterface *ripIe = findRipInterfaceById(ie->getInterfaceId());
365  ripRoute->setRoute(route);
366  ripRoute->setMetric(ripIe ? ripIe->metric : 1);
367  ripRoute->setChanged(true);
368  triggerUpdate();
369  }
370  else {
371  RipNetworkInterface *ripIe = findRipInterfaceById(ie->getInterfaceId());
372  if (!ripIe || ripIe->mode != NO_RIP)
374  }
375  }
376  else {
377  // TODO import external routes from other routing daemons
378  }
379  }
380  }
381  else if (signalID == routeChangedSignal) {
382  const IRoute *route = check_and_cast<const IRoute *>(obj);
383  if (route->getSource() != this) {
384  RipRoute *ripRoute = findRipRoute(route);
385  if (ripRoute) {
386  // TODO check and update tag
387  bool changed = route->getDestinationAsGeneric() != ripRoute->getDestination() ||
388  route->getPrefixLength() != ripRoute->getPrefixLength() ||
389  route->getNextHopAsGeneric() != ripRoute->getNextHop() ||
390  route->getInterface() != ripRoute->getInterface();
391  ripRoute->setDestination(route->getDestinationAsGeneric());
392  ripRoute->setPrefixLength(route->getPrefixLength());
393  ripRoute->setNextHop(route->getNextHopAsGeneric());
394  ripRoute->setInterface(route->getInterface());
395  if (changed) {
396  ripRoute->setChanged(true);
397  triggerUpdate();
398  }
399  }
400  }
401  }
402  else
403  throw cRuntimeError("Unexpected signal: %s", getSignalName(signalID));
404 }

◆ sendPacket()

void inet::Rip::sendPacket ( Packet packet,
const L3Address destAddr,
int  destPort,
const NetworkInterface destInterface 
)
protectedvirtual

Sends the packet to the specified destination.

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

979 {
980  if (destAddr.isMulticast()) {
981  packet->addTagIfAbsent<InterfaceReq>()->setInterfaceId(destInterface->getInterfaceId());
982  if (mode == RIPng) {
983  socket.setTimeToLive(255);
984  packet->addTagIfAbsent<L3AddressReq>()->setSrcAddress(addressType->getLinkLocalAddress(destInterface));
985  }
986  }
987  socket.sendTo(packet, destAddr, destPort);
988 }

Referenced by sendRIPRequest(), and sendRoutes().

◆ sendRIPRequest()

void inet::Rip::sendRIPRequest ( const RipNetworkInterface ripInterface)
protectedvirtual

Sends a RIP request to routers on the specified link.

282 {
283  const auto& packet = makeShared<RipPacket>();
284  packet->setCommand(RIP_REQUEST);
285  packet->setEntryArraySize(1);
286  RipEntry& entry = packet->getEntryForUpdate(0);
287  entry.addressFamilyId = RIP_AF_NONE;
288  entry.metric = RIP_INFINITE_METRIC;
289  packet->setChunkLength(RIP_HEADER_SIZE + RIP_RTE_SIZE * packet->getEntryArraySize());
290 
291  EV_INFO << "sending RIP request from " << ripInterface.ie->getInterfaceName() << "\n";
292 
293  Packet *pk = new Packet("RIP request");
294  pk->insertAtBack(packet);
295  emit(sentRequestSignal, pk);
297 }

Referenced by receiveSignal(), and startRIPRouting().

◆ sendRoutes()

void inet::Rip::sendRoutes ( const L3Address address,
int  port,
const RipNetworkInterface 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.

528 {
529  if (ripInterface.mode == NO_RIP)
530  return;
531 
532  if (ripInterface.mode == PASSIVE) {
533  EV_DEBUG << "No update is sent from passive interface " << ripInterface.ie->getFullName() << std::endl;
535  return;
536  }
537 
538  EV_DEBUG << "Sending " << (changedOnly ? "changed" : "all") << " routes on " << ripInterface.ie->getFullName() << std::endl;
539 
540  int maxEntries = mode == RIPv2 ? 25 : B(B(ripInterface.ie->getMtu()) - IPv6_HEADER_BYTES - UDP_HEADER_LENGTH - RIP_HEADER_SIZE).get() / RIP_RTE_SIZE.get();
541 
542  Packet *pk = new Packet("RIP response");
543  auto packet = makeShared<RipPacket>();
544  packet->setCommand(RIP_RESPONSE);
545  packet->setEntryArraySize(maxEntries);
546  int k = 0; // index into RIP entries
547 
549 
550  for (auto& ripRoute : ripRoutingTable) {
551  // this is a triggered update
552  if (changedOnly) {
553 
554  // make sure triggered update is active
555  ASSERT(triggeredUpdate);
556 
557  if (!ripRoute->isChanged())
558  continue;
559  }
560 
561  // Split Horizon check:
562  // Omit routes learned from one neighbor in updates sent to that neighbor.
563  // In the case of a broadcast network, all routes learned from any neighbor on
564  // that network are omitted from updates sent on that network.
565  // Split Horizon with Poisoned Reverse:
566  // Do include such routes in updates, but sets their metrics to infinity.
567  int metric = ripRoute->getMetric();
568  if (ripRoute->getInterface() == ripInterface.ie) {
569  if (ripInterface.mode == SPLIT_HORIZON)
570  continue;
571  else if (ripInterface.mode == SPLIT_HORIZON_POISON_REVERSE)
572  metric = RIP_INFINITE_METRIC;
573  }
574 
575  EV_DEBUG << "Add entry for " << ripRoute->getDestination() << "/" << ripRoute->getPrefixLength() << ": "
576  << " metric=" << metric << std::endl;
577 
578  // fill next entry
579  RipEntry& entry = packet->getEntryForUpdate(k++);
580  entry.addressFamilyId = RIP_AF_INET;
581  entry.address = ripRoute->getDestination();
582  entry.prefixLength = ripRoute->getPrefixLength();
583  entry.nextHop = addressType->getUnspecifiedAddress(); // route->getNextHop() if local ?
584  entry.routeTag = ripRoute->getRouteTag();
585  entry.metric = metric;
586 
587  // if packet is full, then send it and allocate a new one
588  if (k >= maxEntries) {
589  packet->setChunkLength(RIP_HEADER_SIZE + RIP_RTE_SIZE * packet->getEntryArraySize());
590  pk->insertAtBack(packet);
591 
592  emit(sentUpdateSignal, pk);
593  sendPacket(pk, address, port, ripInterface.ie);
594  pk = new Packet("RIP response");
595  packet = makeShared<RipPacket>();
596  packet->setCommand(RIP_RESPONSE);
597  packet->setEntryArraySize(maxEntries);
598  k = 0;
599  }
600  }
601 
602  // send last packet if it has entries
603  if (k > 0) {
604  packet->setEntryArraySize(k);
605  packet->setChunkLength(RIP_HEADER_SIZE + RIP_RTE_SIZE * packet->getEntryArraySize());
606  pk->insertAtBack(packet);
607 
608  emit(sentUpdateSignal, pk);
609  sendPacket(pk, address, port, ripInterface.ie);
610  }
611  else
612  delete pk;
613 }

Referenced by handleStopOperation(), processRequest(), and processUpdate().

◆ startRIPRouting()

void inet::Rip::startRIPRouting ( )
protectedvirtual
171 {
172  addressType = rt->getRouterIdAsGeneric().getAddressType();
173 
174  cXMLElementList interfaceElements = par("ripConfig").xmlValue()->getChildrenByTagName("interface");
175  InterfaceMatcher matcher(interfaceElements);
176 
177  // Creates a RipNetworkInterface for each interface found in the 'interface table'.
178  for (int k = 0; k < ift->getNumInterfaces(); ++k) {
179  NetworkInterface *ie = ift->getInterface(k);
180  if (ie->isMulticast() && !ie->isLoopback()) {
181  int i = matcher.findMatchingSelector(ie);
182  addRipInterface(ie, i >= 0 ? interfaceElements[i] : nullptr);
183  }
184  }
185 
186  // Import interface/static/default routes from the 'routing table'.
187  for (int i = 0; i < rt->getNumRoutes(); ++i) {
188  IRoute *route = rt->getRoute(i);
189  if (isLoopbackInterfaceRoute(route))
190  ; // void
191  else if (isLocalInterfaceRoute(route)) {
192  NetworkInterface *ie = check_and_cast<NetworkInterface *>(route->getSource());
193  RipNetworkInterface *ripIe = findRipInterfaceById(ie->getInterfaceId());
194  if (!ripIe || ripIe->mode != NO_RIP)
196  }
197  else if (isDefaultRoute(route))
199  else {
200  const L3Address& destAddr = route->getDestinationAsGeneric();
201  if (!destAddr.isMulticast() && !destAddr.isLinkLocal())
203  }
204  }
205 
206  // subscribe to interface created/deleted/changed notifications
207  host->subscribe(interfaceCreatedSignal, this);
208  host->subscribe(interfaceDeletedSignal, this);
209  host->subscribe(interfaceStateChangedSignal, this);
210 
211  // subscribe to route added/deleted/changed notifications
212  host->subscribe(routeAddedSignal, this);
213  host->subscribe(routeDeletedSignal, this);
214  host->subscribe(routeChangedSignal, this);
215 
216  // configure socket
217  socket.setMulticastLoop(false);
219 
220  for (auto& elem : ripInterfaces)
221  if (elem.mode != NO_RIP && elem.mode != PASSIVE)
223 
224  for (auto& elem : ripInterfaces)
225  if (elem.mode != NO_RIP && elem.mode != PASSIVE)
226  sendRIPRequest(elem);
227 
228  // set update timer
229  scheduleAfter(updateInterval, updateTimer);
230 }

Referenced by handleMessageWhenUp().

◆ stopRIPRouting()

void inet::Rip::stopRIPRouting ( )
protectedvirtual
233 {
234  if (startupTimer->isScheduled())
235  cancelEvent(startupTimer);
236  else {
237  socket.close();
238 
239  // unsubscribe to notifications
240  host->unsubscribe(interfaceCreatedSignal, this);
241  host->unsubscribe(interfaceDeletedSignal, this);
242  host->unsubscribe(interfaceStateChangedSignal, this);
243  host->unsubscribe(routeDeletedSignal, this);
244  host->unsubscribe(routeAddedSignal, this);
245  host->unsubscribe(routeChangedSignal, this);
246  }
247 
248  // cancel timers
249  cancelEvent(updateTimer);
250  cancelEvent(triggeredUpdateTimer);
251 
252  // clear data
253  for (auto& elem : ripRoutingTable)
254  delete elem;
255  ripRoutingTable.clear();
256  ripInterfaces.clear();
257 }

Referenced by handleCrashOperation(), and handleStopOperation().

◆ triggerUpdate()

void inet::Rip::triggerUpdate ( )
protectedvirtual

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

If the update is already scheduled, it does nothing.

886 {
887  if (triggeredUpdate && !triggeredUpdateTimer->isScheduled()) {
888  double delay = par("triggeredUpdateDelay");
889  // Triggered updates may be suppressed if a regular
890  // update is due by the time the triggered update would be sent.
891  if (!updateTimer->isScheduled() || updateTimer->getArrivalTime() > simTime() + delay) {
892  EV_DETAIL << "scheduling triggered update \n";
893  scheduleAfter(delay, triggeredUpdateTimer);
894  }
895  }
896 }

Referenced by addRoute(), invalidateRoute(), receiveSignal(), and updateRoute().

◆ updateRoute()

void inet::Rip::updateRoute ( RipRoute ripRoute,
const NetworkInterface ie,
const L3Address nextHop,
int  metric,
uint16_t  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
837 {
838  EV_DEBUG << "Updating route to " << ripRoute->getDestination() << "/" << ripRoute->getPrefixLength() << ": "
839  << "nextHop=" << nextHop << " metric=" << metric << std::endl;
840 
841  int oldMetric = ripRoute->getMetric();
842 
843  ripRoute->setInterface(const_cast<NetworkInterface *>(ie));
844  ripRoute->setMetric(metric);
845  ripRoute->setFrom(from);
846  ripRoute->setRouteTag(routeTag);
847 
848  if (oldMetric == RIP_INFINITE_METRIC && metric < RIP_INFINITE_METRIC) {
849  IRoute *route = ripRoute->getRoute();
850  if (route)
851  rt->deleteRoute(route);
852  ripRoute->setType(RipRoute::RIP_ROUTE_RTE);
853  ripRoute->setNextHop(nextHop);
854  IRoute *newRoute = createRoute(ripRoute->getDestination(), ripRoute->getPrefixLength(), ie, nextHop, metric);
855  ripRoute->setRoute(newRoute);
856  }
857 
858  if (oldMetric != RIP_INFINITE_METRIC) {
859  IRoute *route = ripRoute->getRoute();
860  ASSERT(route);
861  rt->deleteRoute(route);
862 
863  ripRoute->setRoute(nullptr);
864  ripRoute->setNextHop(nextHop);
865 
866  if (metric < RIP_INFINITE_METRIC) {
867  IRoute *newRoute = createRoute(ripRoute->getDestination(), ripRoute->getPrefixLength(), ie, nextHop, metric);
868  ripRoute->setRoute(newRoute);
869  }
870  }
871 
872  ripRoute->setChanged(true);
873  triggerUpdate();
874 
875  if (oldMetric != RIP_INFINITE_METRIC && metric == RIP_INFINITE_METRIC)
876  invalidateRoute(ripRoute);
877  else
878  ripRoute->setLastUpdateTime(simTime());
879 }

Referenced by processResponse().

Member Data Documentation

◆ addressType

◆ badResponseSignal

simsignal_t inet::Rip::badResponseSignal = registerSignal("badResponse")
staticprivate

Referenced by processResponse().

◆ holdDownTime

simtime_t inet::Rip::holdDownTime
private

Referenced by initialize(), and processResponse().

◆ host

cModule* inet::Rip::host = nullptr
private

◆ ift

ModuleRefByPar<IInterfaceTable> inet::Rip::ift
private

◆ mode

Mode inet::Rip::mode = static_cast<Mode>(-1)
private

◆ numRoutesSignal

simsignal_t inet::Rip::numRoutesSignal = registerSignal("numRoutes")
staticprivate

◆ rcvdResponseSignal

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

Referenced by processResponse().

◆ ripInterfaces

◆ ripRoutingTable

◆ ripUdpPort

int inet::Rip::ripUdpPort = -1
private

◆ routeExpiryTime

simtime_t inet::Rip::routeExpiryTime
private

Referenced by checkExpiredRoutes(), and initialize().

◆ routePurgeTime

simtime_t inet::Rip::routePurgeTime
private

Referenced by checkExpiredRoutes(), and initialize().

◆ rt

◆ sentRequestSignal

simsignal_t inet::Rip::sentRequestSignal = registerSignal("sentRequest")
staticprivate

Referenced by sendRIPRequest().

◆ sentUpdateSignal

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

Referenced by sendRoutes().

◆ shutdownTime

simtime_t inet::Rip::shutdownTime
private

Referenced by handleStopOperation(), and initialize().

◆ shutdownTimer

cMessage* inet::Rip::shutdownTimer = nullptr
private

◆ socket

UdpSocket inet::Rip::socket
private

◆ startupTimer

cMessage* inet::Rip::startupTimer = nullptr
private

◆ triggeredUpdate

bool inet::Rip::triggeredUpdate = false
private

◆ triggeredUpdateTimer

cMessage* inet::Rip::triggeredUpdateTimer = nullptr
private

◆ updateInterval

simtime_t inet::Rip::updateInterval
private

◆ updateTimer

cMessage* inet::Rip::updateTimer = nullptr
private

The documentation for this class was generated from the following files:
inet::UdpSocket::setOutputGate
void setOutputGate(cGate *toUdp)
Sets the gate on which to send to UDP.
Definition: UdpSocket.h:117
inet::Rip::routePurgeTime
simtime_t routePurgeTime
Definition: Rip.h:103
inet::UdpSocket::setTimeToLive
void setTimeToLive(int ttl)
Set the TTL (Ipv6: Hop Limit) field on sent packets.
Definition: UdpSocket.cc:112
inet::NetworkInterface::F_STATE
@ F_STATE
Definition: NetworkInterface.h:146
inet::RIP_AF_NONE
@ RIP_AF_NONE
Definition: RipPacket_m.h:90
inet::Rip::startupTimer
cMessage * startupTimer
Definition: Rip.h:96
inet::RIP_REQUEST
@ RIP_REQUEST
Definition: RipPacket_m.h:68
inet::Rip::startRIPRouting
virtual void startRIPRouting()
Definition: Rip.cc:170
inet::Rip::findRipInterfaceById
RipNetworkInterface * findRipInterfaceById(int interfaceId)
Definition: Rip.cc:994
inet::OperationalMixin< cSimpleModule >::operationalState
State operationalState
Definition: OperationalMixin.h:23
inet::Rip::checkExpiredRoutes
virtual void checkExpiredRoutes()
Should be called regularly to handle expiry and purge of routes.
Definition: Rip.cc:901
inet::Rip::importRoute
virtual RipRoute * importRoute(IRoute *route, RipRoute::RouteType type, int metric=1, uint16_t routeTag=0)
Adds a new route the RIP routing table for an existing IRoute.
Definition: Rip.cc:263
inet::UdpSocket::bind
void bind(int localPort)
Bind the socket to a local port number.
Definition: UdpSocket.cc:34
inet::Rip::createRoute
IRoute * createRoute(const L3Address &dest, int prefixLength, const NetworkInterface *ie, const L3Address &nextHop, int metric)
Definition: Rip.cc:1103
inet::IL3AddressType::getMaxPrefixLength
virtual int getMaxPrefixLength() const =0
inet::Rip::triggerUpdate
virtual void triggerUpdate()
Sets the update timer to trigger an update in the [1s,5s] interval.
Definition: Rip.cc:885
inet::UdpSocket::sendTo
void sendTo(Packet *msg, L3Address destAddr, int destPort)
Sends a data packet to the given address and port.
Definition: UdpSocket.cc:69
inet::Rip::numRoutesSignal
static simsignal_t numRoutesSignal
Definition: Rip.h:113
inet::IRoute::RIP
@ RIP
managed by the given routing protocol
Definition: IRoute.h:34
inet::Rip::sentRequestSignal
static simsignal_t sentRequestSignal
Definition: Rip.h:109
inet::Rip::RIPv2
@ RIPv2
Definition: Rip.h:82
inet::RipMode
RipMode
Enumerated parameter to control how the Rip module advertises the routes to its neighbors.
Definition: Rip.h:28
inet::Rip::addRipInterface
void addRipInterface(const NetworkInterface *ie, cXMLElement *config)
Definition: Rip.cc:1039
inet::sctp::min
double min(const double a, const double b)
Returns the minimum of a and b.
Definition: SctpAssociation.h:261
inet::getContainingNode
cModule * getContainingNode(const cModule *from)
Find the node containing the given module.
Definition: ModuleAccess.cc:40
inet::OperationalMixin< cSimpleModule >::initialize
virtual void initialize(int stage) override
Definition: OperationalMixinImpl.h:26
inet::routeChangedSignal
simsignal_t routeChangedSignal
Definition: Simsignals.cc:43
InterfaceReq
removed InterfaceReq
Definition: IUdp-gates.txt:11
inet::Rip::holdDownTime
simtime_t holdDownTime
Definition: Rip.h:104
inet::Rip::addRoute
virtual void addRoute(const L3Address &dest, int prefixLength, const NetworkInterface *ie, const L3Address &nextHop, int metric, uint16_t routeTag, const L3Address &from)
RFC 2453 3.9.2:
Definition: Rip.cc:802
inet::Rip::mode
Mode mode
Definition: Rip.h:99
RIP_INFINITE_METRIC
#define RIP_INFINITE_METRIC
Definition: Rip.h:22
inet::RIP_RESPONSE
@ RIP_RESPONSE
Definition: RipPacket_m.h:69
L3AddressInd
removed DscpReq Ipv4ControlInfo Ipv6ControlInfo up L3AddressInd L3AddressInd
Definition: IUdp-gates.txt:20
inet::find
std::vector< T >::iterator find(std::vector< T > &v, const Tk &a)
Definition: stlutils.h:44
inet::Rip::deleteRipInterface
void deleteRipInterface(const NetworkInterface *ie)
Definition: Rip.cc:1074
inet::NO_SPLIT_HORIZON
@ NO_SPLIT_HORIZON
Definition: Rip.h:31
inet::Rip::updateInterval
simtime_t updateInterval
Definition: Rip.h:101
inet::Rip::triggeredUpdate
bool triggeredUpdate
Definition: Rip.h:106
inet::IL3AddressType::getLinkLocalAddress
virtual L3Address getLinkLocalAddress(const NetworkInterface *ie) const =0
Returns the first valid link-local address of the interface, or UNSPECIFIED_ADDRESS if there's none.
inet::Rip::triggeredUpdateTimer
cMessage * triggeredUpdateTimer
Definition: Rip.h:95
inet::Rip::purgeRoute
virtual RouteVector::iterator purgeRoute(RipRoute *route)
Removes the route from the routing table.
Definition: Rip.cc:950
inet::Rip::badResponseSignal
static simsignal_t badResponseSignal
Definition: Rip.h:112
inet::Rip::ripRoutingTable
RouteVector ripRoutingTable
Definition: Rip.h:92
inet::Rip::shutdownTimer
cMessage * shutdownTimer
Definition: Rip.h:97
inet::interfaceDeletedSignal
simsignal_t interfaceDeletedSignal
Definition: Simsignals.cc:31
inet::NetworkInterface::F_CARRIER
@ F_CARRIER
Definition: NetworkInterface.h:146
inet::Rip::socket
UdpSocket socket
Definition: Rip.h:93
inet::Rip::invalidateRoute
virtual void invalidateRoute(RipRoute *route)
Definition: Rip.cc:932
inet::Rip::isLocalInterfaceRoute
bool isLocalInterfaceRoute(const IRoute *route)
Definition: Rip.h:172
inet::units::units::B
intscale< b, 1, 8 > B
Definition: Units.h:1168
inet::SPLIT_HORIZON_POISON_REVERSE
@ SPLIT_HORIZON_POISON_REVERSE
Definition: Rip.h:33
inet::IL3AddressType::getUnspecifiedAddress
virtual L3Address getUnspecifiedAddress() const =0
inet::Rip::isDefaultRoute
bool isDefaultRoute(const IRoute *route)
Definition: Rip.h:177
inet::Rip::host
cModule * host
Definition: Rip.h:86
inet::UDP_I_SOCKET_CLOSED
@ UDP_I_SOCKET_CLOSED
Definition: UdpControlInfo_m.h:159
inet::Rip::isLoopbackInterfaceRoute
bool isLoopbackInterfaceRoute(const IRoute *route)
Definition: Rip.h:167
inet::Rip::shutdownTime
simtime_t shutdownTime
Definition: Rip.h:105
inet::SPLIT_HORIZON
@ SPLIT_HORIZON
Definition: Rip.h:32
inet::Rip::updateRoute
virtual void updateRoute(RipRoute *route, const NetworkInterface *ie, const L3Address &nextHop, int metric, uint16_t routeTag, const L3Address &from)
Updates an existing route with the information learned from a RIP packet.
Definition: Rip.cc:836
inet::Rip::getInterfaceMetric
int getInterfaceMetric(NetworkInterface *ie)
Definition: Rip.cc:1097
type
removed type
Definition: IUdp-gates.txt:7
inet::Rip::processRequest
virtual void processRequest(Packet *pk)
Processes a request received from a RIP router or a monitoring process.
Definition: Rip.cc:471
inet::UdpSocket::joinMulticastGroup
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:175
inet::interfaceStateChangedSignal
simsignal_t interfaceStateChangedSignal
Definition: Simsignals.cc:32
inet::INITSTAGE_LOCAL
INET_API InitStage INITSTAGE_LOCAL
Initialization of local state that don't use or affect other modules includes:
inet::NO_RIP
@ NO_RIP
Definition: Rip.h:29
inet::Rip::ripInterfaces
InterfaceVector ripInterfaces
Definition: Rip.h:91
inet::Rip::ripUdpPort
int ripUdpPort
Definition: Rip.h:100
inet::IRoute::dRIP
@ dRIP
Definition: IRoute.h:69
inet::Rip::RIPng
@ RIPng
Definition: Rip.h:82
inet::UdpSocket::close
virtual void close() override
Unbinds the socket.
Definition: UdpSocket.cc:87
inet::Rip::processResponse
virtual void processResponse(Packet *pk)
Processes the RIP response and updates the routing table.
Definition: Rip.cc:642
inet::RipRoute::RIP_ROUTE_DEFAULT
@ RIP_ROUTE_DEFAULT
Definition: RipRouteData.h:25
inet::IL3AddressType::getLinkLocalRIPRoutersMulticastAddress
virtual L3Address getLinkLocalRIPRoutersMulticastAddress() const =0
inet::routeAddedSignal
simsignal_t routeAddedSignal
Definition: Simsignals.cc:41
inet::Rip::sendRIPRequest
virtual void sendRIPRequest(const RipNetworkInterface &ripInterface)
Sends a RIP request to routers on the specified link.
Definition: Rip.cc:281
NUM_INIT_STAGES
#define NUM_INIT_STAGES
Definition: InitStageRegistry.h:73
inet::UDP_HEADER_LENGTH
const B UDP_HEADER_LENGTH
Definition: UdpHeader_m.h:51
inet::IPv6_HEADER_BYTES
const B IPv6_HEADER_BYTES
Definition: Ipv6Consts.h:15
inet::sctp::max
double max(const double a, const double b)
Returns the maximum of a and b.
Definition: SctpAssociation.h:266
inet::physicallayer::k
const double k
Definition: Qam1024Modulation.cc:14
inet::Rip::routeExpiryTime
simtime_t routeExpiryTime
Definition: Rip.h:102
inet::RIP_AF_INET
@ RIP_AF_INET
Definition: RipPacket_m.h:91
L4PortInd
removed DscpReq Ipv4ControlInfo Ipv6ControlInfo up L3AddressInd L4PortInd
Definition: IUdp-gates.txt:20
inet::Rip::updateTimer
cMessage * updateTimer
Definition: Rip.h:94
inet::Rip::rcvdResponseSignal
static simsignal_t rcvdResponseSignal
Definition: Rip.h:111
inet::UDP_I_DATA
@ UDP_I_DATA
Definition: UdpControlInfo_m.h:157
inet::Rip::findRipRoute
RipRoute * findRipRoute(const L3Address &destAddress, int prefixLength)
Definition: Rip.cc:1003
inet::OperationalMixin< cSimpleModule >::delayActiveOperationFinish
virtual void delayActiveOperationFinish(simtime_t timeout)
Definition: OperationalMixinImpl.h:161
inet::Rip::addressType
IL3AddressType * addressType
Definition: Rip.h:89
inet::Rip::ift
ModuleRefByPar< IInterfaceTable > ift
Definition: Rip.h:87
Enter_Method
#define Enter_Method(...)
Definition: SelfDoc.h:71
inet::RipRoute::RIP_ROUTE_RTE
@ RIP_ROUTE_RTE
Definition: RipRouteData.h:23
inet::routeDeletedSignal
simsignal_t routeDeletedSignal
Definition: Simsignals.cc:42
inet::units::value::get
const value_type & get() const
Definition: Units.h:108
inet::Rip::processUpdate
virtual void processUpdate(bool triggered)
This method called when a triggered or regular update timer expired.
Definition: Rip.cc:436
inet::Rip::sendPacket
virtual void sendPacket(Packet *packet, const L3Address &destAddr, int destPort, const NetworkInterface *destInterface)
Sends the packet to the specified destination.
Definition: Rip.cc:978
inet::Rip::stopRIPRouting
virtual void stopRIPRouting()
Definition: Rip.cc:232
inet::RipRoute::RouteType
RouteType
Definition: RipRouteData.h:22
inet::Rip::sentUpdateSignal
static simsignal_t sentUpdateSignal
Definition: Rip.h:110
inet::RIP_HEADER_SIZE
const B RIP_HEADER_SIZE
Definition: RipPacket_m.h:50
inet::units::values::m
value< double, units::m > m
Definition: Units.h:1233
inet::Rip::rt
ModuleRefByPar< IRoutingTable > rt
Definition: Rip.h:88
inet::OperationalMixin< cSimpleModule >::finishActiveOperation
virtual void finishActiveOperation()
Definition: OperationalMixinImpl.h:188
inet::RIP_RTE_SIZE
const B RIP_RTE_SIZE
Definition: RipPacket_m.h:51
inet::interfaceCreatedSignal
simsignal_t interfaceCreatedSignal
Definition: Simsignals.cc:30
inet::RipRoute::RIP_ROUTE_INTERFACE
@ RIP_ROUTE_INTERFACE
Definition: RipRouteData.h:27
inet::PASSIVE
@ PASSIVE
Definition: Rip.h:30
inet::UdpSocket::setMulticastLoop
void setMulticastLoop(bool value)
The boolean value specifies whether sent multicast packets should be looped back to the local sockets...
Definition: UdpSocket.cc:157
inet::UDP_I_ERROR
@ UDP_I_ERROR
Definition: UdpControlInfo_m.h:158
inet::Rip::sendRoutes
virtual void sendRoutes(const L3Address &address, int port, const RipNetworkInterface &ripInterface, bool changedOnly)
Send all or changed part of the routing table to address/port on the specified interface.
Definition: Rip.cc:527
inet::RipRoute::RIP_ROUTE_STATIC
@ RIP_ROUTE_STATIC
Definition: RipRouteData.h:24
inet::Rip::isValidResponse
virtual bool isValidResponse(Packet *packet)
Definition: Rip.cc:720