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

Implementation of PIM-DM protocol (RFC 3973). More...

#include <PIMDM.h>

Inheritance diagram for inet::PIMDM:
inet::PIMBase inet::OperationalBase inet::ILifecycle

Classes

struct  DownstreamInterface
 
class  PIMDMOutInterface
 
struct  Route
 
struct  UpstreamInterface
 

Public Member Functions

 PIMDM ()
 
virtual ~PIMDM ()
 
- Public Member Functions inherited from inet::PIMBase
 PIMBase (PIMInterface::PIMMode mode)
 
virtual ~PIMBase ()
 
- Public Member Functions inherited from inet::OperationalBase
 OperationalBase ()
 
- Public Member Functions inherited from inet::ILifecycle
virtual ~ILifecycle ()
 

Protected Member Functions

virtual int numInitStages () const override
 
virtual void handleMessageWhenUp (cMessage *msg) override
 
virtual void initialize (int stage) override
 
virtual bool handleNodeStart (IDoneCallback *doneCallback) override
 
virtual bool handleNodeShutdown (IDoneCallback *doneCallback) override
 
virtual void handleNodeCrash () override
 
virtual void stopPIMRouting ()
 
- Protected Member Functions inherited from inet::PIMBase
void sendHelloPackets ()
 
void sendHelloPacket (PIMInterface *pimInterface)
 
void processHelloTimer (cMessage *timer)
 
void processHelloPacket (PIMHello *pkt)
 
virtual bool isInitializeStage (int stage) override
 
virtual bool isNodeStartStage (int stage) override
 
virtual bool isNodeShutdownStage (int stage) override
 
- Protected Member Functions inherited from inet::OperationalBase
virtual void handleMessage (cMessage *msg) override
 
virtual void handleMessageWhenDown (cMessage *msg)
 
virtual bool handleOperationStage (LifecycleOperation *operation, int stage, IDoneCallback *doneCallback) override
 Perform one stage of a lifecycle operation. More...
 
virtual void setOperational (bool isOperational)
 

Private Types

typedef std::map< SourceAndGroup, Route * > RoutingTable
 

Private Member Functions

void receiveSignal (cComponent *source, simsignal_t signalID, cObject *obj, cObject *details) override
 
void unroutableMulticastPacketArrived (IPv4Address srcAddress, IPv4Address destAddress, unsigned short ttl)
 The method process notification about new multicast data stream. More...
 
void multicastPacketArrivedOnNonRpfInterface (IPv4Address group, IPv4Address source, int interfaceId)
 The method has to solve the problem when multicast data appears on non-RPF interface. More...
 
void multicastPacketArrivedOnRpfInterface (int interfaceId, IPv4Address group, IPv4Address source, unsigned short ttl)
 
void multicastReceiverAdded (InterfaceEntry *ie, IPv4Address newAddr)
 
void multicastReceiverRemoved (InterfaceEntry *ie, IPv4Address oldAddr)
 The method process notification about multicast groups removed from interface. More...
 
void rpfInterfaceHasChanged (IPv4MulticastRoute *route, IPv4Route *routeToSource)
 The method process notification about interface change. More...
 
void processPruneTimer (cMessage *timer)
 
void processPrunePendingTimer (cMessage *timer)
 
void processGraftRetryTimer (cMessage *timer)
 
void processOverrideTimer (cMessage *timer)
 
void processSourceActiveTimer (cMessage *timer)
 
void processStateRefreshTimer (cMessage *timer)
 
void processAssertTimer (cMessage *timer)
 
void processJoinPrunePacket (PIMJoinPrune *pkt)
 
void processGraftPacket (PIMGraft *pkt)
 
void processGraftAckPacket (PIMGraftAck *pkt)
 
void processStateRefreshPacket (PIMStateRefresh *pkt)
 The method is used to process PIMStateRefresh packet. More...
 
void processAssertPacket (PIMAssert *pkt)
 
void processPrune (Route *route, int intId, int holdTime, int numRpfNeighbors, IPv4Address upstreamNeighborField)
 The method process PIM Prune packet. More...
 
void processJoin (Route *route, int intId, int numRpfNeighbors, IPv4Address upstreamNeighborField)
 
void processGraft (IPv4Address source, IPv4Address group, IPv4Address sender, int intId)
 The method is used to process PIMGraft packet. More...
 
void processAssert (Interface *downstream, AssertMetric receivedMetric, int stateRefreshInterval)
 
void processOlistEmptyEvent (Route *route)
 
void processOlistNonEmptyEvent (Route *route)
 
void sendPrunePacket (IPv4Address nextHop, IPv4Address src, IPv4Address grp, int holdTime, int intId)
 
void sendJoinPacket (IPv4Address nextHop, IPv4Address source, IPv4Address group, int interfaceId)
 
void sendGraftPacket (IPv4Address nextHop, IPv4Address src, IPv4Address grp, int intId)
 
void sendGraftAckPacket (PIMGraft *msg)
 
void sendStateRefreshPacket (IPv4Address originator, Route *route, DownstreamInterface *downstream, unsigned short ttl)
 
void sendAssertPacket (IPv4Address source, IPv4Address group, AssertMetric metric, InterfaceEntry *ie)
 
void sendToIP (PIMPacket *packet, IPv4Address source, IPv4Address dest, int outInterfaceId)
 
void restartTimer (cMessage *timer, double interval)
 
void cancelAndDeleteTimer (cMessage *&timer)
 
PIMInterfacegetIncomingInterface (IPv4Datagram *datagram)
 
IPv4MulticastRoutefindIPv4MulticastRoute (IPv4Address group, IPv4Address source)
 
RoutefindRoute (IPv4Address source, IPv4Address group)
 
void deleteRoute (IPv4Address source, IPv4Address group)
 
void clearRoutes ()
 

Private Attributes

double pruneInterval = 0
 
double pruneLimitInterval = 0
 
double overrideInterval = 0
 
double propagationDelay = 0
 
double graftRetryInterval = 0
 
double sourceActiveInterval = 0
 
double stateRefreshInterval = 0
 
double assertTime = 0
 
RoutingTable routes
 

Static Private Attributes

static simsignal_t sentGraftPkSignal = registerSignal("sentGraftPk")
 
static simsignal_t rcvdGraftPkSignal = registerSignal("rcvdGraftPk")
 
static simsignal_t sentGraftAckPkSignal = registerSignal("sentGraftAckPk")
 
static simsignal_t rcvdGraftAckPkSignal = registerSignal("rcvdGraftAckPk")
 
static simsignal_t sentJoinPrunePkSignal = registerSignal("sentJoinPrunePk")
 
static simsignal_t rcvdJoinPrunePkSignal = registerSignal("rcvdJoinPrunePk")
 
static simsignal_t sentAssertPkSignal = registerSignal("sentAssertPk")
 
static simsignal_t rcvdAssertPkSignal = registerSignal("rcvdAssertPk")
 
static simsignal_t sentStateRefreshPkSignal = registerSignal("sentStateRefreshPk")
 
static simsignal_t rcvdStateRefreshPkSignal = registerSignal("rcvdStateRefreshPk")
 

Friends

std::ostream & operator<< (std::ostream &out, const Route *route)
 

Additional Inherited Members

- Protected Types inherited from inet::PIMBase
enum  PIMTimerKind {
  HelloTimer = 1, TriggeredHelloDelay, AssertTimer, PruneTimer,
  PrunePendingTimer, GraftRetryTimer, UpstreamOverrideTimer, PruneLimitTimer,
  SourceActiveTimer, StateRefreshTimer, KeepAliveTimer, RegisterStopTimer,
  ExpiryTimer, JoinTimer
}
 
- Protected Attributes inherited from inet::PIMBase
IIPv4RoutingTablert = nullptr
 
IInterfaceTableift = nullptr
 
PIMInterfaceTablepimIft = nullptr
 
PIMNeighborTablepimNbt = nullptr
 
bool isUp = false
 
bool isEnabled = false
 
const char * hostname = nullptr
 
double helloPeriod = 0
 
double holdTime = 0
 
int designatedRouterPriority = 0
 
PIMInterface::PIMMode mode = (PIMInterface::PIMMode)0
 
uint32_t generationID = 0
 
cMessage * helloTimer = nullptr
 
- Protected Attributes inherited from inet::OperationalBase
bool isOperational
 
simtime_t lastChange
 
- Static Protected Attributes inherited from inet::PIMBase
static const IPv4Address ALL_PIM_ROUTERS_MCAST
 
static simsignal_t sentHelloPkSignal = registerSignal("sentHelloPk")
 
static simsignal_t rcvdHelloPkSignal = registerSignal("rcvdHelloPk")
 

Detailed Description

Implementation of PIM-DM protocol (RFC 3973).

Member Typedef Documentation

typedef std::map<SourceAndGroup, Route *> inet::PIMDM::RoutingTable
private

Constructor & Destructor Documentation

inet::PIMDM::PIMDM ( )
inline
Definition: PIMInterfaceTable.h:36
PIMBase(PIMInterface::PIMMode mode)
Definition: PIMBase.h:181
inet::PIMDM::~PIMDM ( )
virtual
48 {
49  for (auto & elem : routes)
50  delete elem.second;
51  routes.clear();
52 }
RoutingTable routes
Definition: PIMDM.h:182

Member Function Documentation

void inet::PIMDM::cancelAndDeleteTimer ( cMessage *&  timer)
private
1668 {
1669  cancelAndDelete(timer);
1670  timer = nullptr;
1671 }
void inet::PIMDM::clearRoutes ( )
private
1711 {
1712  // delete IPv4 routes
1713  bool changed = true;
1714  while (changed) {
1715  changed = false;
1716  for (int i = 0; i < rt->getNumMulticastRoutes(); i++) {
1717  IPv4MulticastRoute *ipv4Route = rt->getMulticastRoute(i);
1718  if (ipv4Route->getSource() == this) {
1719  rt->deleteMulticastRoute(ipv4Route);
1720  changed = true;
1721  break;
1722  }
1723  }
1724  }
1725 
1726  // clear local table
1727  for (auto & elem : routes)
1728  delete elem.second;
1729  routes.clear();
1730 }
virtual int getNumMulticastRoutes() const =0
Returns the total number of multicast routes.
virtual IPv4MulticastRoute * getMulticastRoute(int k) const override=0
Returns the kth multicast route.
virtual bool deleteMulticastRoute(IPv4MulticastRoute *entry)=0
Deletes the given multicast route from the routing table.
IIPv4RoutingTable * rt
Definition: PIMBase.h:158
RoutingTable routes
Definition: PIMDM.h:182
void inet::PIMDM::deleteRoute ( IPv4Address  source,
IPv4Address  group 
)
private
1702 {
1703  auto it = routes.find(SourceAndGroup(source, group));
1704  if (it != routes.end()) {
1705  delete it->second;
1706  routes.erase(it);
1707  }
1708 }
RoutingTable routes
Definition: PIMDM.h:182
IPv4MulticastRoute * inet::PIMDM::findIPv4MulticastRoute ( IPv4Address  group,
IPv4Address  source 
)
private
1685 {
1686  int numRoutes = rt->getNumMulticastRoutes();
1687  for (int i = 0; i < numRoutes; i++) {
1688  IPv4MulticastRoute *route = rt->getMulticastRoute(i);
1689  if (route->getSource() == this && route->getMulticastGroup() == group && route->getOrigin() == source)
1690  return route;
1691  }
1692  return nullptr;
1693 }
virtual int getNumMulticastRoutes() const =0
Returns the total number of multicast routes.
virtual IPv4MulticastRoute * getMulticastRoute(int k) const override=0
Returns the kth multicast route.
IIPv4RoutingTable * rt
Definition: PIMBase.h:158
PIMDM::Route * inet::PIMDM::findRoute ( IPv4Address  source,
IPv4Address  group 
)
private
1696 {
1697  auto it = routes.find(SourceAndGroup(source, group));
1698  return it != routes.end() ? it->second : nullptr;
1699 }
RoutingTable routes
Definition: PIMDM.h:182
PIMInterface * inet::PIMDM::getIncomingInterface ( IPv4Datagram datagram)
private
1674 {
1675  cGate *g = datagram->getArrivalGate();
1676  if (g) {
1677  InterfaceEntry *ie = ift->getInterfaceByNetworkLayerGateIndex(g->getIndex());
1678  if (ie)
1679  return pimIft->getInterfaceById(ie->getInterfaceId());
1680  }
1681  return nullptr;
1682 }
PIMInterfaceTable * pimIft
Definition: PIMBase.h:160
virtual InterfaceEntry * getInterfaceByNetworkLayerGateIndex(int index)=0
Returns an interface given by its getNetworkLayerGateIndex().
IInterfaceTable * ift
Definition: PIMBase.h:159
virtual PIMInterface * getInterfaceById(int interfaceId)
Definition: PIMInterfaceTable.cc:116
milli< kg >::type g
Definition: Units.h:900
void inet::PIMDM::handleMessageWhenUp ( cMessage *  msg)
overrideprotectedvirtual

Implements inet::OperationalBase.

123 {
124  if (msg->isSelfMessage()) {
125  switch (msg->getKind()) {
126  case HelloTimer:
127  processHelloTimer(msg);
128  break;
129 
130  case AssertTimer:
131  processAssertTimer(msg);
132  break;
133 
134  case PruneTimer:
135  processPruneTimer(msg);
136  break;
137 
138  case PrunePendingTimer:
140  break;
141 
142  case GraftRetryTimer:
144  break;
145 
148  break;
149 
150  case PruneLimitTimer:
151  break;
152 
153  case SourceActiveTimer:
155  break;
156 
157  case StateRefreshTimer:
159  break;
160 
161  default:
162  throw cRuntimeError("PIMDM: unknown self message: %s (%s)", msg->getName(), msg->getClassName());
163  }
164  }
165  else if (dynamic_cast<PIMPacket *>(msg)) {
166  if (!isEnabled) {
167  EV_DETAIL << "PIM-DM is disabled, dropping packet.\n";
168  delete msg;
169  return;
170  }
171 
172  PIMPacket *pkt = static_cast<PIMPacket *>(msg);
173  switch (pkt->getType()) {
174  case Hello:
175  processHelloPacket(check_and_cast<PIMHello *>(pkt));
176  break;
177 
178  case JoinPrune:
179  processJoinPrunePacket(check_and_cast<PIMJoinPrune *>(pkt));
180  break;
181 
182  case Assert:
183  processAssertPacket(check_and_cast<PIMAssert *>(pkt));
184  break;
185 
186  case Graft:
187  processGraftPacket(check_and_cast<PIMGraft *>(pkt));
188  break;
189 
190  case GraftAck:
191  processGraftAckPacket(check_and_cast<PIMGraftAck *>(pkt));
192  break;
193 
194  case StateRefresh:
195  processStateRefreshPacket(check_and_cast<PIMStateRefresh *>(pkt));
196  break;
197 
198  default:
199  EV_WARN << "Dropping packet " << pkt->getName() << ".\n";
200  delete pkt;
201  break;
202  }
203  }
204  else
205  throw cRuntimeError("PIMDM: received unknown message: %s (%s).", msg->getName(), msg->getClassName());
206 }
bool isEnabled
Definition: PIMBase.h:164
Definition: PIMBase.h:137
void processStateRefreshPacket(PIMStateRefresh *pkt)
The method is used to process PIMStateRefresh packet.
Definition: PIMDM.cc:580
void processGraftRetryTimer(cMessage *timer)
Definition: PIMDM.cc:899
void processStateRefreshTimer(cMessage *timer)
Definition: PIMDM.cc:978
Definition: PIMBase.h:133
void processJoinPrunePacket(PIMJoinPrune *pkt)
Definition: PIMDM.cc:208
void processAssertPacket(PIMAssert *pkt)
Definition: PIMDM.cc:678
void processGraftAckPacket(PIMGraftAck *pkt)
Definition: PIMDM.cc:532
void processAssertTimer(cMessage *timer)
Definition: PIMDM.cc:1008
void processOverrideTimer(cMessage *timer)
Definition: PIMDM.cc:918
Definition: PIMBase.h:145
void processGraftPacket(PIMGraft *pkt)
Definition: PIMDM.cc:378
void processHelloPacket(PIMHello *pkt)
Definition: PIMBase.cc:190
Definition: PIMBase.h:138
Definition: PIMBase.h:143
Definition: PIMPacket_m.h:65
Definition: PIMBase.h:144
void processSourceActiveTimer(cMessage *timer)
Definition: PIMDM.cc:939
Definition: PIMPacket_m.h:69
void processHelloTimer(cMessage *timer)
Definition: PIMBase.cc:135
void processPrunePendingTimer(cMessage *timer)
Definition: PIMDM.cc:874
Definition: PIMPacket_m.h:67
Definition: PIMBase.h:139
Definition: PIMPacket_m.h:71
Definition: PIMPacket_m.h:68
void processPruneTimer(cMessage *timer)
Definition: PIMDM.cc:838
Definition: PIMBase.h:146
Definition: PIMPacket_m.h:62
Definition: PIMBase.h:142
void inet::PIMDM::handleNodeCrash ( )
overrideprotectedvirtual

Reimplemented from inet::PIMBase.

99 {
100  stopPIMRouting();
102 }
virtual void stopPIMRouting()
Definition: PIMDM.cc:104
virtual void handleNodeCrash() override
Definition: PIMBase.cc:128
bool inet::PIMDM::handleNodeShutdown ( IDoneCallback doneCallback)
overrideprotectedvirtual

Reimplemented from inet::PIMBase.

92 {
93  // TODO send PIM Hellos to neighbors with 0 HoldTime
95  return PIMBase::handleNodeShutdown(doneCallback);
96 }
virtual void stopPIMRouting()
Definition: PIMDM.cc:104
virtual bool handleNodeShutdown(IDoneCallback *doneCallback) override
Definition: PIMBase.cc:120
bool inet::PIMDM::handleNodeStart ( IDoneCallback doneCallback)
overrideprotectedvirtual

Reimplemented from inet::PIMBase.

71 {
72  bool done = PIMBase::handleNodeStart(doneCallback);
73 
74  // subscribe for notifications
75  if (isEnabled) {
76  cModule *host = findContainingNode(this);
77  if (!host)
78  throw cRuntimeError("PIMDM: containing node not found.");
79  host->subscribe(NF_IPv4_NEW_MULTICAST, this);
80  host->subscribe(NF_IPv4_MCAST_REGISTERED, this);
81  host->subscribe(NF_IPv4_MCAST_UNREGISTERED, this);
82  host->subscribe(NF_IPv4_DATA_ON_NONRPF, this);
83  host->subscribe(NF_IPv4_DATA_ON_RPF, this);
84  host->subscribe(NF_ROUTE_ADDED, this);
85  host->subscribe(NF_INTERFACE_STATE_CHANGED, this);
86  }
87 
88  return done;
89 }
bool isEnabled
Definition: PIMBase.h:164
simsignal_t NF_IPv4_DATA_ON_RPF
Definition: NotifierConsts.cc:74
simsignal_t NF_IPv4_MCAST_UNREGISTERED
Definition: NotifierConsts.cc:68
simsignal_t NF_IPv4_NEW_MULTICAST
Definition: NotifierConsts.cc:70
cModule * findContainingNode(const cModule *from)
Find the node containing the given module.
Definition: ModuleAccess.cc:56
simsignal_t NF_IPv4_MCAST_REGISTERED
Definition: NotifierConsts.cc:67
simsignal_t NF_INTERFACE_STATE_CHANGED
Definition: NotifierConsts.cc:50
virtual bool handleNodeStart(IDoneCallback *doneCallback) override
Definition: PIMBase.cc:94
simsignal_t NF_ROUTE_ADDED
Definition: NotifierConsts.cc:57
simsignal_t NF_IPv4_DATA_ON_NONRPF
Definition: NotifierConsts.cc:73
void inet::PIMDM::initialize ( int  stage)
overrideprotectedvirtual

Reimplemented from inet::PIMBase.

55 {
56  PIMBase::initialize(stage);
57 
58  if (stage == INITSTAGE_LOCAL) {
59  pruneInterval = par("pruneInterval");
60  pruneLimitInterval = par("pruneLimitInterval");
61  overrideInterval = par("overrideInterval");
62  propagationDelay = par("propagationDelay");
63  graftRetryInterval = par("graftRetryInterval");
64  sourceActiveInterval = par("sourceActiveInterval");
65  stateRefreshInterval = par("stateRefreshInterval");
66  assertTime = par("assertTime");
67  }
68 }
double overrideInterval
Definition: PIMDM.h:162
double sourceActiveInterval
Definition: PIMDM.h:165
virtual void initialize(int stage) override
Definition: PIMBase.cc:72
double propagationDelay
Definition: PIMDM.h:163
double pruneInterval
Definition: PIMDM.h:160
double assertTime
Definition: PIMDM.h:167
double stateRefreshInterval
Definition: PIMDM.h:166
Local initializations.
Definition: InitStages.h:35
double pruneLimitInterval
Definition: PIMDM.h:161
double graftRetryInterval
Definition: PIMDM.h:164
void inet::PIMDM::multicastPacketArrivedOnNonRpfInterface ( IPv4Address  group,
IPv4Address  source,
int  interfaceId 
)
private

The method has to solve the problem when multicast data appears on non-RPF interface.

It can happen when there is loop in the network. In this case, router has to prune from the neighbor, so it sends Prune message.

1271 {
1272  EV_DETAIL << "Received multicast datagram (source=" << source << ", group=" << group << ") on non-RPF interface: " << interfaceId << ".\n";
1273 
1274  Route *route = findRoute(source, group);
1275  ASSERT(route);
1276 
1277  UpstreamInterface *upstream = route->upstreamInterface;
1278  DownstreamInterface *downstream = route->findDownstreamInterfaceByInterfaceId(interfaceId);
1279  if (!downstream)
1280  return;
1281 
1282  // in case of p2p link, send prune
1283  // FIXME There should be better indicator of P2P link
1284  if (pimNbt->getNumNeighbors(interfaceId) == 1) {
1285  // send Prune msg to the neighbor who sent these multicast data
1286  IPv4Address nextHop = (pimNbt->getNeighbor(interfaceId, 0))->getAddress();
1287  sendPrunePacket(nextHop, source, group, pruneInterval, interfaceId);
1288 
1289  // the incoming interface has to change its state to Pruned
1290  if (downstream->pruneState == DownstreamInterface::NO_INFO) {
1291  downstream->pruneState = DownstreamInterface::PRUNED;
1292  downstream->startPruneTimer(pruneInterval);
1293 
1294  // if there is no outgoing interface, Prune msg has to be sent on upstream
1295  if (route->isOilistNull()) {
1296  EV << "Route is not forwarding any more, send Prune to upstream" << endl;
1297  upstream->graftPruneState = UpstreamInterface::PRUNED;
1298  if (!upstream->isSourceDirectlyConnected()) {
1299  sendPrunePacket(upstream->rpfNeighbor(), source, group, pruneInterval, upstream->getInterfaceId());
1300  }
1301  }
1302  }
1303  return;
1304  }
1305 
1306  //
1307  // Assert State Machine; event: An (S,G) data packet arrives on downstream interface I
1308  //
1309  if (downstream->assertState == DownstreamInterface::NO_ASSERT_INFO) {
1310  // An (S,G) data packet arrived on a downstream interface. It is
1311  // optimistically assumed that this router will be the Assert winner
1312  // for this (S,G). The Assert state machine MUST transition to the
1313  // "I am Assert Winner" state, send an Assert(S,G) to interface I,
1314  // store its own address and metric as the Assert Winner, and set
1315  // the Assert_Timer (AT(S,G,I) to Assert_Time, thereby initiating
1316  // the Assert negotiation for (S,G).
1317  downstream->assertState = DownstreamInterface::I_WON_ASSERT;
1318  downstream->winnerMetric = route->metric.setAddress(downstream->ie->ipv4Data()->getIPAddress());
1319  sendAssertPacket(source, group, route->metric, downstream->ie);
1320  downstream->startAssertTimer(assertTime);
1321  }
1322  else if (downstream->assertState == DownstreamInterface::I_WON_ASSERT) {
1323  // An (S,G) data packet arrived on a downstream interface. The
1324  // Assert state machine remains in the "I am Assert Winner" state.
1325  // The router MUST send an Assert(S,G) to interface I and set the
1326  // Assert Timer (AT(S,G,I) to Assert_Time.
1327  sendAssertPacket(source, group, route->metric, downstream->ie);
1328  restartTimer(downstream->assertTimer, assertTime);
1329  }
1330 }
PIMNeighborTable * pimNbt
Definition: PIMBase.h:161
double pruneInterval
Definition: PIMDM.h:160
double assertTime
Definition: PIMDM.h:167
virtual int getNumNeighbors(int interfaceId)
Returns the number of neighbors on the given interface.
Definition: PIMNeighborTable.cc:176
void restartTimer(cMessage *timer, double interval)
Definition: PIMDM.cc:1661
virtual PIMNeighbor * getNeighbor(int interfaceId, int index)
Returns the neighbor on the given interface at the specified position.
Definition: PIMNeighborTable.cc:182
Route * findRoute(IPv4Address source, IPv4Address group)
Definition: PIMDM.cc:1695
void sendAssertPacket(IPv4Address source, IPv4Address group, AssertMetric metric, InterfaceEntry *ie)
Definition: PIMDM.cc:1624
void sendPrunePacket(IPv4Address nextHop, IPv4Address src, IPv4Address grp, int holdTime, int intId)
Definition: PIMDM.cc:1493
void inet::PIMDM::multicastPacketArrivedOnRpfInterface ( int  interfaceId,
IPv4Address  group,
IPv4Address  source,
unsigned short  ttl 
)
private
1196 {
1197  EV_DETAIL << "Multicast datagram arrived: source=" << source << ", group=" << group << ".\n";
1198 
1199  Route *route = findRoute(source, group);
1200  ASSERT(route);
1201  UpstreamInterface *upstream = route->upstreamInterface;
1202 
1203  // RFC 3973 4.5.2.2
1204  //
1205  // Receive Data Packet from S addressed to G
1206  // The router remains in the Originator (O) state and MUST reset
1207  // SAT(S,G) to SourceLifetime. The router SHOULD increase its
1208  // recorded TTL to match the TTL of the packet, if the packet's TTL
1209  // is larger than the previously recorded TTL. A router MAY record
1210  // the TTL based on an implementation specific sampling policy to
1211  // avoid examining the TTL of every multicast packet it handles.
1212 
1213  // Is source directly connected?
1214  if (upstream->isSourceDirectlyConnected()) {
1215  // State Refresh Originator state machine event: Receive Data from S AND S directly connected
1216  if (upstream->originatorState == UpstreamInterface::NOT_ORIGINATOR) {
1217  upstream->originatorState = UpstreamInterface::ORIGINATOR;
1218  PIMInterface *pimInterface = pimIft->getInterfaceById(upstream->ie->getInterfaceId());
1219  if (pimInterface && pimInterface->getSR())
1220  upstream->startStateRefreshTimer();
1221  }
1222  restartTimer(upstream->sourceActiveTimer, sourceActiveInterval);
1223 
1224  // record max TTL seen, it is used in StateRefresh messages
1225  upstream->maxTtlSeen = max(upstream->maxTtlSeen, ttl);
1226  }
1227 
1228  // upstream state transition
1229 
1230  // Data Packet arrives on RPF_Interface(S) AND olist(S,G) == nullptr AND S is NOT directly connected ?
1231  if (upstream->ie->getInterfaceId() == interfaceId && route->isOilistNull() && !upstream->isSourceDirectlyConnected()) {
1232  EV_DETAIL << "Route does not have any outgoing interface and source is not directly connected.\n";
1233 
1234  switch (upstream->graftPruneState) {
1236  // The Upstream(S,G) state machine MUST transition to the Pruned (P)
1237  // state, send a Prune(S,G) to RPF'(S), and set PLT(S,G) to t_limit seconds.
1238  sendPrunePacket(upstream->rpfNeighbor(), source, group, pruneInterval, upstream->getInterfaceId());
1239  upstream->startPruneLimitTimer();
1240  upstream->graftPruneState = UpstreamInterface::PRUNED;
1241  break;
1242 
1244  // Either another router on the LAN desires traffic from S addressed
1245  // to G or a previous Prune was lost. To prevent generating a
1246  // Prune(S,G) in response to every data packet, the PruneLimit Timer
1247  // (PLT(S,G)) is used. Once the PLT(S,G) expires, the router needs
1248  // to send another prune in response to a data packet not received
1249  // directly from the source. A Prune(S,G) MUST be sent to RPF'(S),
1250  // and the PLT(S,G) MUST be set to t_limit.
1251  //
1252  // if GRT is running now, do not send Prune msg
1253  if (!upstream->isPruneLimitTimerRunning()) {
1254  sendPrunePacket(upstream->rpfNeighbor(), source, group, pruneInterval, upstream->getInterfaceId());
1255  upstream->startPruneLimitTimer();
1256  }
1257  break;
1258 
1260  break;
1261  }
1262  }
1263 }
double sourceActiveInterval
Definition: PIMDM.h:165
PIMInterfaceTable * pimIft
Definition: PIMBase.h:160
double max(double a, double b)
Returns the greater of the given parameters.
Definition: INETMath.h:161
double pruneInterval
Definition: PIMDM.h:160
void restartTimer(cMessage *timer, double interval)
Definition: PIMDM.cc:1661
virtual PIMInterface * getInterfaceById(int interfaceId)
Definition: PIMInterfaceTable.cc:116
Route * findRoute(IPv4Address source, IPv4Address group)
Definition: PIMDM.cc:1695
uint8_t ttl
Definition: TCP_NSC.cc:87
void sendPrunePacket(IPv4Address nextHop, IPv4Address src, IPv4Address grp, int holdTime, int intId)
Definition: PIMDM.cc:1493
void inet::PIMDM::multicastReceiverAdded ( InterfaceEntry ie,
IPv4Address  newAddr 
)
private
1339 {
1340  EV_DETAIL << "Multicast receiver added for group " << group << ".\n";
1341 
1342  int numRoutes = rt->getNumMulticastRoutes();
1343  for (int i = 0; i < numRoutes; i++) {
1344  IPv4MulticastRoute *ipv4Route = rt->getMulticastRoute(i);
1345 
1346  // check group
1347  if (ipv4Route->getSource() != this || ipv4Route->getMulticastGroup() != group)
1348  continue;
1349 
1350  Route *route = findRoute(ipv4Route->getOrigin(), group);
1351  ASSERT(route);
1352 
1353  // check on RPF interface
1354  UpstreamInterface *upstream = route->upstreamInterface;
1355  if (upstream->ie == ie)
1356  continue;
1357 
1358  // is interface in list of outgoing interfaces?
1359  DownstreamInterface *downstream = route->findDownstreamInterfaceByInterfaceId(ie->getInterfaceId());
1360  if (downstream) {
1361  EV << "Interface is already on list of outgoing interfaces" << endl;
1362  if (downstream->pruneState == DownstreamInterface::PRUNED)
1363  downstream->pruneState = DownstreamInterface::NO_INFO;
1364  }
1365  else {
1366  // create new downstream data
1367  EV << "Interface is not on list of outgoing interfaces yet, it will be added" << endl;
1368  downstream = route->createDownstreamInterface(ie);
1369  ipv4Route->addOutInterface(new PIMDMOutInterface(ie, downstream));
1370  }
1371 
1372  downstream->setHasConnectedReceivers(true);
1373 
1374  // fire upstream state machine event
1375  if (upstream->graftPruneState == UpstreamInterface::PRUNED && downstream->isInOlist())
1377  }
1378 }
virtual int getNumMulticastRoutes() const =0
Returns the total number of multicast routes.
void processOlistNonEmptyEvent(Route *route)
Definition: PIMDM.cc:503
virtual IPv4MulticastRoute * getMulticastRoute(int k) const override=0
Returns the kth multicast route.
IIPv4RoutingTable * rt
Definition: PIMBase.h:158
Route * findRoute(IPv4Address source, IPv4Address group)
Definition: PIMDM.cc:1695
void inet::PIMDM::multicastReceiverRemoved ( InterfaceEntry ie,
IPv4Address  group 
)
private

The method process notification about multicast groups removed from interface.

For each old address it tries to find route. If there is route, it finds interface in list of outgoing interfaces. If the interface is in the list it will be removed. If the router was not pruned and there is no outgoing interface, the router will prune from the multicast tree.

1387 {
1388  EV_DETAIL << "No more receiver for group " << group << " on interface '" << ie->getName() << "'.\n";
1389 
1390  // delete pimInt from outgoing interfaces of multicast routes for group
1391  int numRoutes = rt->getNumMulticastRoutes();
1392  for (int i = 0; i < numRoutes; i++) {
1393  IPv4MulticastRoute *ipv4Route = rt->getMulticastRoute(i);
1394  if (ipv4Route->getSource() == this && ipv4Route->getMulticastGroup() == group) {
1395  Route *route = findRoute(ipv4Route->getOrigin(), group);
1396 
1397  // remove pimInt from the list of outgoing interfaces
1398  DownstreamInterface *downstream = route->findDownstreamInterfaceByInterfaceId(ie->getInterfaceId());
1399  if (downstream) {
1400  bool wasInOlist = downstream->isInOlist();
1401  downstream->setHasConnectedReceivers(false);
1402  if (wasInOlist && !downstream->isInOlist()) {
1403  EV_DEBUG << "Removed interface '" << ie->getName() << "' from the outgoing interface list of route " << route << ".\n";
1404 
1405  // fire upstream state machine event
1406  if (route->isOilistNull())
1407  processOlistEmptyEvent(route);
1408  }
1409  }
1410  }
1411  }
1412 }
virtual int getNumMulticastRoutes() const =0
Returns the total number of multicast routes.
virtual IPv4MulticastRoute * getMulticastRoute(int k) const override=0
Returns the kth multicast route.
DownstreamInterface * findDownstreamInterfaceByInterfaceId(int interfaceId) const
Definition: PIMDM.cc:1740
IIPv4RoutingTable * rt
Definition: PIMBase.h:158
Route * findRoute(IPv4Address source, IPv4Address group)
Definition: PIMDM.cc:1695
bool isInOlist() const
Definition: PIMDM.cc:1902
void processOlistEmptyEvent(Route *route)
Definition: PIMDM.cc:477
virtual int inet::PIMDM::numInitStages ( ) const
inlineoverrideprotectedvirtual

Reimplemented from inet::PIMBase.

242 { return NUM_INIT_STAGES; }
The number of initialization stages.
Definition: InitStages.h:116
void inet::PIMDM::processAssert ( Interface downstream,
AssertMetric  receivedMetric,
int  stateRefreshInterval 
)
private
706 {
707  Route *route = check_and_cast<Route *>(incomingInterface->owner);
708  UpstreamInterface *upstream = route->upstreamInterface;
709 
710  //
711  // Assert State Machine
712  //
713  AssertMetric currentMetric = incomingInterface->assertState == Interface::NO_ASSERT_INFO ?
714  route->metric.setAddress(incomingInterface->ie->ipv4Data()->getIPAddress()) :
715  incomingInterface->winnerMetric;
716  bool isEqual = receivedMetric == currentMetric;
717  bool isBetter = receivedMetric < currentMetric;
718  bool couldAssert = incomingInterface != upstream;
719 
720  // event: Received Preferred Assert
721  if (isBetter || isEqual) {
722  if (incomingInterface->assertState == Interface::NO_ASSERT_INFO) {
723  // The received Assert or State Refresh has a better metric than
724  // this router's, and therefore the Assert state machine MUST
725  // transition to the "I am Assert Loser" state and store the Assert
726  // Winner's address and metric. If the metric was received in an
727  // Assert, the router MUST set the Assert Timer (AT(S,G,I)) to
728  // Assert_Time. If the metric was received in a State Refresh, the
729  // router MUST set the Assert Timer (AT(S,G,I)) to three times the
730  // received State Refresh Interval. If CouldAssert(S,G,I) == TRUE,
731  // the router MUST also multicast a Prune(S,G) to the Assert winner
732  // with a Prune Hold Time equal to the Assert Timer and evaluate any
733  // changes in its Upstream(S,G) state machine.
734  ASSERT(isBetter);
735  EV_DEBUG << "Received better metrics, going to I_LOST_ASSERT state.\n";
736  incomingInterface->assertState = Interface::I_LOST_ASSERT;
737  incomingInterface->winnerMetric = receivedMetric;
739  incomingInterface->startAssertTimer(assertTime);
740  if (couldAssert)
741  sendPrunePacket(incomingInterface->winnerMetric.address, route->source, route->group, assertTime, incomingInterface->ie->getInterfaceId());
742 
743  // upstream state machine
744  if (upstream->graftPruneState != UpstreamInterface::PRUNED && route->isOilistNull())
745  processOlistEmptyEvent(route);
746  }
747  else if (incomingInterface->assertState == Interface::I_WON_ASSERT) {
748  // An (S,G) Assert is received that has a better
749  // metric than this router's metric for S on interface I. The
750  // Assert state machine MUST transition to "I am Assert Loser" state
751  // and store the new Assert Winner's address and metric. The router MUST set the Assert
752  // Timer (AT(S,G,I)) to Assert_Time. The router MUST also
753  // multicast a Prune(S,G) to the Assert winner, with a Prune Hold
754  // Time equal to the Assert Timer, and evaluate any changes in its
755  // Upstream(S,G) state machine.
756  ASSERT(isBetter);
757  EV_DEBUG << "Received better metrics, going to I_LOST_ASSERT state.\n";
758  incomingInterface->assertState = DownstreamInterface::I_LOST_ASSERT;
759  incomingInterface->winnerMetric = receivedMetric;
760  restartTimer(incomingInterface->assertTimer, assertTime);
761  sendPrunePacket(incomingInterface->winnerMetric.address, route->source, route->group, assertTime, incomingInterface->ie->getInterfaceId());
762 
763  // upstream state machine
764  if (upstream->graftPruneState != UpstreamInterface::PRUNED && route->isOilistNull())
765  processOlistEmptyEvent(route);
766  }
767  else if (incomingInterface->assertState == Interface::I_LOST_ASSERT) {
768  // An Assert is received that has a metric better
769  // than or equal to that of the current Assert winner. The Assert
770  // state machine remains in Loser (L) state. If the metric was
771  // received in an Assert, the router MUST set the Assert Timer
772  // (AT(S,G,I)) to Assert_Time. The router MUST set the Assert Timer (AT(S,G,I))
773  // to three times the received State Refresh Interval. If the
774  // metric is better than the current Assert Winner, the router MUST
775  // store the address and metric of the new Assert Winner, and if
776  // CouldAssert(S,G,I) == TRUE, the router MUST multicast a
777  // Prune(S,G) to the new Assert winner.
778  EV_DEBUG << "Received better metrics, stay in I_LOST_ASSERT state.\n";
779  restartTimer(incomingInterface->assertTimer, stateRefreshInterval > 0 ? 3 * stateRefreshInterval : assertTime);
780  if (isBetter) {
781  incomingInterface->winnerMetric = receivedMetric;
782  if (couldAssert)
783  sendPrunePacket(incomingInterface->winnerMetric.address, route->source, route->group, assertTime, incomingInterface->ie->getInterfaceId());
784  }
785  }
786  }
787  // event: Receive Inferior Assert from Assert Winner
788  else if (receivedMetric.address == incomingInterface->winnerMetric.address) {
789  if (incomingInterface->assertState == Interface::I_LOST_ASSERT) {
790  // An Assert is received from the current Assert
791  // winner that is worse than this router's metric for S (typically,
792  // the winner's metric became worse). The Assert state machine MUST
793  // transition to NoInfo (NI) state and cancel AT(S,G,I). The router
794  // MUST delete the previous Assert Winner's address and metric and
795  // evaluate any possible transitions to its Upstream(S,G) state
796  // machine. Usually this router will eventually re-assert and win
797  // when data packets from S have started flowing again.
798  EV_DEBUG << "Assert winner lost best route, going to NO_ASSERT_INFO state.\n";
799  incomingInterface->deleteAssertInfo();
800  // upstream state machine
801  if (upstream->graftPruneState == UpstreamInterface::PRUNED && !route->isOilistNull())
803  }
804  }
805  // event: Receive Inferior Assert from non-Assert Winner AND CouldAssert==TRUE
806  else if (couldAssert) {
807  if (incomingInterface->assertState == Interface::NO_ASSERT_INFO) {
808  // An Assert or State Refresh is received for (S,G) that is inferior
809  // to our own assert metric on interface I. The Assert state machine
810  // MUST transition to the "I am Assert Winner" state, send an
811  // Assert(S,G) to interface I, store its own address and metric as
812  // the Assert Winner, and set the Assert Timer (AT(S,G,I)) to
813  // Assert_Time.
814  EV_DEBUG << "Received inferior assert metrics, going to I_WON_ASSERT state.\n";
815  incomingInterface->assertState = DownstreamInterface::I_WON_ASSERT;
816  sendAssertPacket(route->source, route->group, route->metric, incomingInterface->ie);
817  incomingInterface->startAssertTimer(assertTime);
818  }
819  else if (incomingInterface->assertState == DownstreamInterface::I_WON_ASSERT) {
820  // An (S,G) Assert is received containing a metric for S that is
821  // worse than this router's metric for S. Whoever sent the Assert
822  // is in error. The router MUST send an Assert(S,G) to interface I
823  // and reset the Assert Timer (AT(S,G,I)) to Assert_Time.
824  EV_DEBUG << "Received inferior assert metrics, stay in I_WON_ASSERT state.\n";
825  sendAssertPacket(route->source, route->group, route->metric, incomingInterface->ie);
826  restartTimer(incomingInterface->assertTimer, assertTime);
827  }
828  }
829 }
void processOlistNonEmptyEvent(Route *route)
Definition: PIMDM.cc:503
double assertTime
Definition: PIMDM.h:167
double stateRefreshInterval
Definition: PIMDM.h:166
void restartTimer(cMessage *timer, double interval)
Definition: PIMDM.cc:1661
void sendAssertPacket(IPv4Address source, IPv4Address group, AssertMetric metric, InterfaceEntry *ie)
Definition: PIMDM.cc:1624
void processOlistEmptyEvent(Route *route)
Definition: PIMDM.cc:477
if(!(yy_init))
Definition: lexer.cc:1644
void sendPrunePacket(IPv4Address nextHop, IPv4Address src, IPv4Address grp, int holdTime, int intId)
Definition: PIMDM.cc:1493
void inet::PIMDM::processAssertPacket ( PIMAssert pkt)
private
679 {
680  IPv4ControlInfo *ctrlInfo = check_and_cast<IPv4ControlInfo *>(pkt->getControlInfo());
681  int incomingInterfaceId = ctrlInfo->getInterfaceId();
682  IPv4Address source = pkt->getSourceAddress();
683  IPv4Address group = pkt->getGroupAddress();
684  AssertMetric receivedMetric = AssertMetric(pkt->getMetricPreference(), pkt->getMetric(), ctrlInfo->getSrcAddr());
685  Route *route = findRoute(source, group);
686  ASSERT(route); // XXX create S,G state?
687  Interface *incomingInterface = route->upstreamInterface->getInterfaceId() == incomingInterfaceId ?
688  static_cast<Interface *>(route->upstreamInterface) :
689  static_cast<Interface *>(route->findDownstreamInterfaceByInterfaceId(incomingInterfaceId));
690  ASSERT(incomingInterface);
691 
692  EV_INFO << "Received Assert(S=" << source << ", G=" << group
693  << ") packet on interface '" << incomingInterface->ie->getName() << "'.\n";
694 
695  emit(rcvdAssertPkSignal, pkt);
696 
697  processAssert(incomingInterface, receivedMetric, 0);
698 
699  delete pkt;
700 }
void processAssert(Interface *downstream, AssertMetric receivedMetric, int stateRefreshInterval)
Definition: PIMDM.cc:705
static simsignal_t rcvdAssertPkSignal
Definition: PIMDM.h:177
Route * findRoute(IPv4Address source, IPv4Address group)
Definition: PIMDM.cc:1695
void inet::PIMDM::processAssertTimer ( cMessage *  timer)
private
1009 {
1010  Interface *interfaceData = static_cast<Interface *>(timer->getContextPointer());
1011  ASSERT(timer == interfaceData->assertTimer);
1012  ASSERT(interfaceData->assertState != DownstreamInterface::NO_ASSERT_INFO);
1013 
1014  Route *route = check_and_cast<Route *>(interfaceData->owner);
1015  UpstreamInterface *upstream = route->upstreamInterface;
1016  EV_DETAIL << "AssertTimer" << route << " interface=" << interfaceData->ie->getName() << " has expired.\n";
1017 
1018  //
1019  // Assert State Machine; event: AT(S,G,I) expires
1020  //
1021 
1022  // The Assert state machine MUST transition to NoInfo (NI) state.
1023  // The router MUST delete the Assert Winner's address and metric.
1024  // If CouldAssert == TRUE, the router MUST evaluate any possible
1025  // transitions to its Upstream(S,G) state machine.
1026  EV_DEBUG << "Going into NO_ASSERT_INFO state.\n";
1027  interfaceData->deleteAssertInfo(); // deletes timer
1028 
1029  // upstream state machine transition
1030  if (interfaceData != upstream) {
1031  bool isOlistNull = route->isOilistNull();
1032  if (upstream->graftPruneState == UpstreamInterface::PRUNED && !isOlistNull)
1034  else if (upstream->graftPruneState != UpstreamInterface::PRUNED && isOlistNull)
1035  processOlistEmptyEvent(route);
1036  }
1037 }
void processOlistNonEmptyEvent(Route *route)
Definition: PIMDM.cc:503
void processOlistEmptyEvent(Route *route)
Definition: PIMDM.cc:477
void inet::PIMDM::processGraft ( IPv4Address  source,
IPv4Address  group,
IPv4Address  sender,
int  incomingInterfaceId 
)
private

The method is used to process PIMGraft packet.

Packet means that downstream router wants to join to multicast tree, so the packet cannot come to RPF interface. Router finds correct outgoig interface towards downstream router. Change its state to forward if it was not before and cancel Prune Timer. If route was in pruned state, router will send also Graft message to join multicast tree.

417 {
418  EV_DEBUG << "Processing Graft(S=" << source << ", G=" << group << "), sender=" << sender << "incoming if=" << incomingInterfaceId << endl;
419 
420  Route *route = findRoute(source, group);
421 
422  UpstreamInterface *upstream = route->upstreamInterface;
423 
424  // check if message come to non-RPF interface
425  if (upstream->ie->getInterfaceId() == incomingInterfaceId) {
426  EV << "ERROR: Graft message came to RPF interface." << endl;
427  return;
428  }
429 
430  DownstreamInterface *downstream = route->findDownstreamInterfaceByInterfaceId(incomingInterfaceId);
431  if (!downstream)
432  return;
433 
434  //
435  // Downstream Interface State Machine
436  //
437  // Note: GraftAck is sent in processGraftPacket()
438  bool olistChanged = false;
439  switch (downstream->pruneState) {
441  // do nothing
442  break;
443 
445  downstream->stopPrunePendingTimer();
446  downstream->pruneState = DownstreamInterface::NO_INFO;
447  break;
448 
450  EV << "Interface " << downstream->ie->getInterfaceId() << " transit to forwarding state (Graft)." << endl;
451  downstream->stopPruneTimer();
452  downstream->pruneState = DownstreamInterface::NO_INFO;
453  olistChanged = downstream->isInOlist();
454  break;
455  }
456 
457  if (olistChanged)
459 
460  //
461  // Assert State Machine; event: Receive Graft(S,G)
462  //
463  if (downstream->assertState == DownstreamInterface::I_LOST_ASSERT) {
464  // A Graft(S,G) message was received on
465  // interface I with its upstream neighbor address set to the
466  // router's address on I. The router MUST send an Assert(S,G) on
467  // the receiving interface I to initiate an Assert negotiation. The
468  // Assert state machine remains in the Assert Loser(L) state.
469  // The router MUST respond with a GraftAck(S,G).
470  sendAssertPacket(route->source, route->group, route->metric, downstream->ie);
471  }
472 }
void processOlistNonEmptyEvent(Route *route)
Definition: PIMDM.cc:503
Route * findRoute(IPv4Address source, IPv4Address group)
Definition: PIMDM.cc:1695
void sendAssertPacket(IPv4Address source, IPv4Address group, AssertMetric metric, InterfaceEntry *ie)
Definition: PIMDM.cc:1624
void inet::PIMDM::processGraftAckPacket ( PIMGraftAck pkt)
private
533 {
534  EV_INFO << "Received GraftAck packet.\n";
535 
536  emit(rcvdGraftAckPkSignal, pkt);
537 
538  IPv4ControlInfo *ctrlInfo = check_and_cast<IPv4ControlInfo *>(pkt->getControlInfo());
539  IPv4Address destAddress = ctrlInfo->getDestAddr();
540 
541  for (unsigned int i = 0; i < pkt->getJoinPruneGroupsArraySize(); i++) {
542  JoinPruneGroup& group = pkt->getJoinPruneGroups(i);
543  IPv4Address groupAddr = group.getGroupAddress();
544 
545  for (unsigned int j = 0; j < group.getJoinedSourceAddressArraySize(); j++) {
546  EncodedAddress& source = group.getJoinedSourceAddress(j);
547  Route *route = findRoute(source.IPaddress, groupAddr);
548  UpstreamInterface *upstream = route->upstreamInterface;
549 
550  // If the destination address of the GraftAck packet is not
551  // the address of the upstream interface, then no state transition occur.
552  if (destAddress != upstream->ie->ipv4Data()->getIPAddress())
553  continue;
554 
555  // upstream state transition
556  // event: Receive GraftAck(S,G) from RPF'(S)
557  if (upstream->graftPruneState == UpstreamInterface::ACK_PENDING) {
558  // A GraftAck is received from RPF'(S). The GraftRetry Timer MUST
559  // be cancelled, and the Upstream(S,G) state machine MUST transition
560  // to the Forwarding(F) state.
561  ASSERT(upstream->graftRetryTimer);
562  cancelAndDelete(upstream->graftRetryTimer);
563  upstream->graftRetryTimer = nullptr;
564  upstream->graftPruneState = UpstreamInterface::FORWARDING;
565  }
566  }
567  }
568 
569  delete pkt;
570 }
static simsignal_t rcvdGraftAckPkSignal
Definition: PIMDM.h:173
Route * findRoute(IPv4Address source, IPv4Address group)
Definition: PIMDM.cc:1695
void inet::PIMDM::processGraftPacket ( PIMGraft pkt)
private
379 {
380  EV_INFO << "Received Graft packet.\n";
381 
382  emit(rcvdGraftPkSignal, pkt);
383 
384  IPv4ControlInfo *ctrlInfo = check_and_cast<IPv4ControlInfo *>(pkt->getControlInfo());
385  IPv4Address sender = ctrlInfo->getSrcAddr();
386  InterfaceEntry *incomingInterface = ift->getInterfaceById(ctrlInfo->getInterfaceId());
387 
388  // does packet belong to this router?
389  if (pkt->getUpstreamNeighborAddress() != incomingInterface->ipv4Data()->getIPAddress()) {
390  delete pkt;
391  return;
392  }
393 
394  for (unsigned int i = 0; i < pkt->getJoinPruneGroupsArraySize(); i++) {
395  JoinPruneGroup& group = pkt->getJoinPruneGroups(i);
396  IPv4Address groupAddr = group.getGroupAddress();
397 
398  for (unsigned int j = 0; j < group.getJoinedSourceAddressArraySize(); j++) {
399  EncodedAddress& source = group.getJoinedSourceAddress(j);
400  processGraft(source.IPaddress, groupAddr, sender, incomingInterface->getInterfaceId());
401  }
402  }
403 
404  // Send GraftAck for this Graft message
405  sendGraftAckPacket(pkt);
406 
407  delete pkt;
408 }
virtual InterfaceEntry * getInterfaceById(int id) const =0
Returns an interface by its Id.
IInterfaceTable * ift
Definition: PIMBase.h:159
static simsignal_t rcvdGraftPkSignal
Definition: PIMDM.h:171
void processGraft(IPv4Address source, IPv4Address group, IPv4Address sender, int intId)
The method is used to process PIMGraft packet.
Definition: PIMDM.cc:416
void sendGraftAckPacket(PIMGraft *msg)
Definition: PIMDM.cc:1579
void inet::PIMDM::processGraftRetryTimer ( cMessage *  timer)
private
900 {
901  EV_INFO << "GraftRetryTimer expired.\n";
902  UpstreamInterface *upstream = static_cast<UpstreamInterface *>(timer->getContextPointer());
903  ASSERT(upstream->graftPruneState == UpstreamInterface::ACK_PENDING);
904  ASSERT(timer == upstream->graftRetryTimer);
905 
906  Route *route = upstream->route();
907  EV_INFO << "GraftRetryTimer" << route << " expired.\n";
908 
909  // The Upstream(S,G) state machine stays in the AckPending (AP)
910  // state. Another Graft message for (S,G) SHOULD be unicast to
911  // RPF'(S) and the GraftRetry Timer (GRT(S,G)) reset to
912  // Graft_Retry_Period. It is RECOMMENDED that the router retry a
913  // configured number of times before ceasing retries.
914  sendGraftPacket(upstream->rpfNeighbor(), route->source, route->group, upstream->getInterfaceId());
915  scheduleAt(simTime() + graftRetryInterval, timer);
916 }
void sendGraftPacket(IPv4Address nextHop, IPv4Address src, IPv4Address grp, int intId)
Definition: PIMDM.cc:1551
double graftRetryInterval
Definition: PIMDM.h:164
void inet::PIMDM::processJoin ( Route route,
int  intId,
int  numRpfNeighbors,
IPv4Address  upstreamNeighborField 
)
private
327 {
328  UpstreamInterface *upstream = route->upstreamInterface;
329 
330  // See join to RPF'(S,G) ?
331  if (upstream->ie->getInterfaceId() == intId && numRpfNeighbors > 1) {
332  // TODO check that destAddress == upstream->nextHop
333  if (upstream->graftPruneState == UpstreamInterface::FORWARDING || upstream->graftPruneState == UpstreamInterface::ACK_PENDING) {
334  // If the OT(S,G) is running, then it
335  // means that the router had scheduled a Join to override a
336  // previously received Prune. Another router has responded more
337  // quickly with a Join, so the local router SHOULD cancel its
338  // OT(S,G), if it is running.
339  cancelAndDelete(upstream->overrideTimer);
340  upstream->overrideTimer = nullptr;
341  }
342  }
343 
344  //
345  // Downstream Interface State Machine
346  //
347  DownstreamInterface *downstream = route->findDownstreamInterfaceByInterfaceId(intId);
348  if (!downstream)
349  return;
350 
351  // does packet belong to this router?
352  if (upstreamNeighborField != downstream->ie->ipv4Data()->getIPAddress())
353  return;
354 
355  if (downstream->pruneState == DownstreamInterface::PRUNE_PENDING)
356  downstream->stopPrunePendingTimer();
357  else if (downstream->pruneState == DownstreamInterface::PRUNED)
358  downstream->stopPruneTimer();
359 
360  downstream->pruneState = DownstreamInterface::NO_INFO;
361 
362  if (upstream->graftPruneState == UpstreamInterface::PRUNED && !route->isOilistNull())
363  processOlistNonEmptyEvent(route); // will send Graft upstream
364 
365  //
366  // Assert State Machine; event: Receive Join(S,G)
367  //
368  if (downstream->assertState == DownstreamInterface::I_LOST_ASSERT) {
369  // A Join(S,G) message was received on
370  // interface I with its upstream neighbor address set to the
371  // router's address on I. The router MUST send an Assert(S,G) on
372  // the receiving interface I to initiate an Assert negotiation. The
373  // Assert state machine remains in the Assert Loser(L) state.
374  sendAssertPacket(route->source, route->group, route->metric, downstream->ie);
375  }
376 }
void processOlistNonEmptyEvent(Route *route)
Definition: PIMDM.cc:503
void sendAssertPacket(IPv4Address source, IPv4Address group, AssertMetric metric, InterfaceEntry *ie)
Definition: PIMDM.cc:1624
void inet::PIMDM::processJoinPrunePacket ( PIMJoinPrune pkt)
private
209 {
210  EV_INFO << "Received JoinPrune packet.\n";
211 
212  emit(rcvdJoinPrunePkSignal, pkt);
213 
214  IPv4ControlInfo *ctrlInfo = check_and_cast<IPv4ControlInfo *>(pkt->getControlInfo());
215  InterfaceEntry *incomingInterface = ift->getInterfaceById(ctrlInfo->getInterfaceId());
216 
217  if (!incomingInterface) {
218  delete pkt;
219  return;
220  }
221 
222  IPv4Address upstreamNeighborAddress = pkt->getUpstreamNeighborAddress();
223  int numRpfNeighbors = pimNbt->getNumNeighbors(incomingInterface->getInterfaceId());
224 
225  for (unsigned int i = 0; i < pkt->getJoinPruneGroupsArraySize(); i++) {
226  JoinPruneGroup group = pkt->getJoinPruneGroups(i);
227  IPv4Address groupAddr = group.getGroupAddress();
228 
229  // go through list of joined sources
230  for (unsigned int j = 0; j < group.getJoinedSourceAddressArraySize(); j++) {
231  EncodedAddress& source = group.getJoinedSourceAddress(j);
232  Route *route = findRoute(source.IPaddress, groupAddr);
233  processJoin(route, incomingInterface->getInterfaceId(), numRpfNeighbors, upstreamNeighborAddress);
234  }
235 
236  // go through list of pruned sources
237  for (unsigned int j = 0; j < group.getPrunedSourceAddressArraySize(); j++) {
238  EncodedAddress& source = group.getPrunedSourceAddress(j);
239  Route *route = findRoute(source.IPaddress, groupAddr);
240  processPrune(route, incomingInterface->getInterfaceId(), pkt->getHoldTime(), numRpfNeighbors, upstreamNeighborAddress);
241  }
242  }
243 
244  delete pkt;
245 }
virtual InterfaceEntry * getInterfaceById(int id) const =0
Returns an interface by its Id.
PIMNeighborTable * pimNbt
Definition: PIMBase.h:161
IInterfaceTable * ift
Definition: PIMBase.h:159
virtual int getNumNeighbors(int interfaceId)
Returns the number of neighbors on the given interface.
Definition: PIMNeighborTable.cc:176
void processPrune(Route *route, int intId, int holdTime, int numRpfNeighbors, IPv4Address upstreamNeighborField)
The method process PIM Prune packet.
Definition: PIMDM.cc:253
static simsignal_t rcvdJoinPrunePkSignal
Definition: PIMDM.h:175
Route * findRoute(IPv4Address source, IPv4Address group)
Definition: PIMDM.cc:1695
void processJoin(Route *route, int intId, int numRpfNeighbors, IPv4Address upstreamNeighborField)
Definition: PIMDM.cc:326
void inet::PIMDM::processOlistEmptyEvent ( Route route)
private
478 {
479  UpstreamInterface *upstream = route->upstreamInterface;
480 
481  // upstream state transitions
482 
483  // olist(S,G) -> nullptr AND S NOT directly connected?
484  if (!upstream->isSourceDirectlyConnected()) {
485  if (upstream->graftPruneState == UpstreamInterface::FORWARDING || upstream->graftPruneState == UpstreamInterface::ACK_PENDING) {
486  // The Upstream(S,G) state machine MUST
487  // transition to the Pruned (P) state. A Prune(S,G) MUST be
488  // multicast to the RPF_interface(S), with RPF'(S) named in the
489  // upstream neighbor field. The GraftRetry Timer (GRT(S,G)) MUST be
490  // cancelled, and PLT(S,G) MUST be set to t_limit seconds.
491  sendPrunePacket(upstream->rpfNeighbor(), route->source, route->group, pruneInterval, upstream->getInterfaceId());
492  upstream->startPruneLimitTimer();
493  if (upstream->graftPruneState == UpstreamInterface::ACK_PENDING) {
494  cancelAndDelete(upstream->graftRetryTimer);
495  upstream->graftRetryTimer = nullptr;
496  }
497  }
498  }
499 
500  upstream->graftPruneState = UpstreamInterface::PRUNED;
501 }
double pruneInterval
Definition: PIMDM.h:160
void sendPrunePacket(IPv4Address nextHop, IPv4Address src, IPv4Address grp, int holdTime, int intId)
Definition: PIMDM.cc:1493
void inet::PIMDM::processOlistNonEmptyEvent ( Route route)
private
504 {
505  // upstream state transition: Pruned->AckPending if olist is not empty
506  // if all route was pruned, remove prune flag
507  // if upstrem is not source, send Graft message
508  UpstreamInterface *upstream = route->upstreamInterface;
509  if (upstream->graftPruneState == UpstreamInterface::PRUNED) {
510  // olist(S,G)->non-nullptr AND S NOT directly connected
511  //
512  // The set of interfaces defined by the olist(S,G) macro becomes
513  // non-empty, indicating that traffic from S addressed to group G
514  // must be forwarded. The Upstream(S,G) state machine MUST cancel
515  // PLT(S,G), transition to the AckPending (AP) state and unicast a
516  // Graft message to RPF'(S). The Graft Retry Timer (GRT(S,G)) MUST
517  // be set to Graft_Retry_Period.
518 
519  if (!upstream->isSourceDirectlyConnected()) {
520  EV << "Route is not pruned any more, send Graft to upstream" << endl;
521  sendGraftPacket(upstream->rpfNeighbor(), route->source, route->group, upstream->getInterfaceId());
522  upstream->stopPruneLimitTimer();
523  upstream->startGraftRetryTimer();
524  upstream->graftPruneState = UpstreamInterface::ACK_PENDING;
525  }
526  else {
527  upstream->graftPruneState = UpstreamInterface::FORWARDING;
528  }
529  }
530 }
void sendGraftPacket(IPv4Address nextHop, IPv4Address src, IPv4Address grp, int intId)
Definition: PIMDM.cc:1551
void inet::PIMDM::processOverrideTimer ( cMessage *  timer)
private
919 {
920  UpstreamInterface *upstream = static_cast<UpstreamInterface *>(timer->getContextPointer());
921  ASSERT(timer == upstream->overrideTimer);
922  ASSERT(upstream->graftPruneState != UpstreamInterface::PRUNED);
923 
924  Route *route = upstream->route();
925  EV_INFO << "OverrideTimer" << route << " expired.\n";
926 
927  // send a Join(S,G) to RPF'(S)
928  sendJoinPacket(upstream->rpfNeighbor(), route->source, route->group, upstream->getInterfaceId());
929 
930  upstream->overrideTimer = nullptr;
931  delete timer;
932 }
void sendJoinPacket(IPv4Address nextHop, IPv4Address source, IPv4Address group, int interfaceId)
Definition: PIMDM.cc:1519
void inet::PIMDM::processPrune ( Route route,
int  intId,
int  holdTime,
int  numRpfNeighbors,
IPv4Address  upstreamNeighborField 
)
private

The method process PIM Prune packet.

First the method has to find correct outgoing interface where PIM Prune packet came to. The method also checks if there is still any forwarding outgoing interface. Forwarding interfaces, where Prune packet come to, goes to prune state. If all outgoing interfaces are pruned, the router will prune from multicast tree.

254 {
255  EV_INFO << "Processing Prune" << route << ".\n";
256 
257  //
258  // Upstream Interface State Machine; event: See Prune(S,G)
259  //
260 
261  // See Prune(S,G) AND S is NOT directly connected ?
262  UpstreamInterface *upstream = route->upstreamInterface;
263  if (upstream->ie->getInterfaceId() == intId && !upstream->isSourceDirectlyConnected()) {
264  // This event is only relevant if RPF_interface(S) is a shared
265  // medium. This router sees another router on RPF_interface(S) send
266  // a Prune(S,G). When this router is in Forwarding/AckPending state, it must
267  // override the Prune after a short random interval. If OT(S,G) is
268  // not running, the router MUST set OT(S,G) to t_override seconds.
269  // The Upstream(S,G) state machine remains in Forwarding/AckPending state.
270  if (upstream->graftPruneState == UpstreamInterface::FORWARDING || upstream->graftPruneState == UpstreamInterface::ACK_PENDING) {
271  if (!upstream->overrideTimer)
272  upstream->startOverrideTimer();
273  }
274  }
275 
276  // we find correct outgoing interface
277  DownstreamInterface *downstream = route->findDownstreamInterfaceByInterfaceId(intId);
278  if (!downstream)
279  return;
280 
281  // does packet belong to this router?
282  if (upstreamNeighborField != downstream->ie->ipv4Data()->getIPAddress())
283  return;
284 
285  //
286  // Downstream Interface State Machine; event: Receive Prune(S,G)
287  //
288 
289  // A Prune(S,G) is received on interface I with the upstream
290  // neighbor field set to the router's address on I.
291  if (downstream->pruneState == DownstreamInterface::NO_INFO) {
292  // The Prune(S,G) Downstream state machine on interface I MUST transition to the
293  // PrunePending (PP) state. The PrunePending Timer (PPT(S,G,I))
294  // MUST be set to J/P_Override_Interval if the router has more than
295  // one neighbor on I. If the router has only one neighbor on
296  // interface I, then it SHOULD set the PPT(S,G,I) to zero,
297  // effectively transitioning immediately to the Pruned (P) state.
298  double prunePendingInterval = numRpfNeighbors > 1 ? overrideInterval + propagationDelay : 0;
299  downstream->startPrunePendingTimer(prunePendingInterval);
300  downstream->pruneState = DownstreamInterface::PRUNE_PENDING;
301  }
302  else if (downstream->pruneState == DownstreamInterface::PRUNED) {
303  // The Prune(S,G) Downstream state machine on interface I remains in the Pruned (P)
304  // state. The Prune Timer (PT(S,G,I)) SHOULD be reset to the
305  // holdtime contained in the Prune(S,G) message if it is greater
306  // than the current value.
307  EV << "Outgoing interface is already pruned, restart Prune Timer." << endl;
308  if (downstream->pruneTimer->getArrivalTime() < simTime() + holdTime)
309  restartTimer(downstream->pruneTimer, holdTime);
310  }
311 
312  //
313  // Assert state machine; event: Receive Prune(S,G)
314  //
315  if (downstream->assertState == DownstreamInterface::I_LOST_ASSERT) {
316  // Receive Prune(S,G)
317  // A Prune(S,G) message was received on
318  // interface I with its upstream neighbor address set to the
319  // router's address on I. The router MUST send an Assert(S,G) on
320  // the receiving interface I to initiate an Assert negotiation. The
321  // Assert state machine remains in the Assert Loser(L) state.
322  sendAssertPacket(route->source, route->group, route->metric, downstream->ie);
323  }
324 }
double overrideInterval
Definition: PIMDM.h:162
double propagationDelay
Definition: PIMDM.h:163
void restartTimer(cMessage *timer, double interval)
Definition: PIMDM.cc:1661
double holdTime
Definition: PIMBase.h:169
void sendAssertPacket(IPv4Address source, IPv4Address group, AssertMetric metric, InterfaceEntry *ie)
Definition: PIMDM.cc:1624
void inet::PIMDM::processPrunePendingTimer ( cMessage *  timer)
private
875 {
876  DownstreamInterface *downstream = static_cast<DownstreamInterface *>(timer->getContextPointer());
877  ASSERT(timer == downstream->prunePendingTimer);
878  ASSERT(downstream->pruneState == DownstreamInterface::PRUNE_PENDING);
879 
880  delete timer;
881  downstream->prunePendingTimer = nullptr;
882 
883  Route *route = downstream->route();
884  EV_INFO << "PrunePendingTimer" << route << " has expired.\n";
885 
886  //
887  // go to pruned state
888  downstream->pruneState = DownstreamInterface::PRUNED;
889  double holdTime = pruneInterval - overrideInterval - propagationDelay; // XXX should be received HoldTime - computed override interval;
890  downstream->startPruneTimer(holdTime);
891 
892  // TODO optionally send PruneEcho
893 
894  // upstream state change if olist become nullptr
895  if (route->isOilistNull())
896  processOlistEmptyEvent(route);
897 }
double overrideInterval
Definition: PIMDM.h:162
double propagationDelay
Definition: PIMDM.h:163
double pruneInterval
Definition: PIMDM.h:160
double holdTime
Definition: PIMBase.h:169
void processOlistEmptyEvent(Route *route)
Definition: PIMDM.cc:477
void inet::PIMDM::processPruneTimer ( cMessage *  timer)
private
839 {
840  DownstreamInterface *downstream = static_cast<DownstreamInterface *>(timer->getContextPointer());
841  ASSERT(timer == downstream->pruneTimer);
842  ASSERT(downstream->pruneState == DownstreamInterface::PRUNED);
843 
844  Route *route = downstream->route();
845  EV_INFO << "PruneTimer" << route << " expired.\n";
846 
847  // state of interface is changed to forwarding
848  downstream->stopPruneTimer();
849  downstream->pruneState = DownstreamInterface::NO_INFO;
850 
851  // upstream state change if olist become non nullptr
852  if (!route->isOilistNull())
854 }
void processOlistNonEmptyEvent(Route *route)
Definition: PIMDM.cc:503
void inet::PIMDM::processSourceActiveTimer ( cMessage *  timer)
private
940 {
941  UpstreamInterface *upstream = static_cast<UpstreamInterface *>(timer->getContextPointer());
942  ASSERT(timer == upstream->sourceActiveTimer);
943  ASSERT(upstream->originatorState == UpstreamInterface::ORIGINATOR);
944 
945  Route *route = upstream->route();
946  EV_INFO << "SourceActiveTimer" << route << " expired.\n";
947 
948  upstream->originatorState = UpstreamInterface::NOT_ORIGINATOR;
949  cancelAndDelete(upstream->stateRefreshTimer);
950  upstream->stateRefreshTimer = nullptr;
951 
952  // delete the route, because there are no more packets
953  IPv4Address routeSource = route->source;
954  IPv4Address routeGroup = route->group;
955  deleteRoute(routeSource, routeGroup);
956  IPv4MulticastRoute *ipv4Route = findIPv4MulticastRoute(routeGroup, routeSource);
957  if (ipv4Route)
958  rt->deleteMulticastRoute(ipv4Route);
959 }
void deleteRoute(IPv4Address source, IPv4Address group)
Definition: PIMDM.cc:1701
IPv4MulticastRoute * findIPv4MulticastRoute(IPv4Address group, IPv4Address source)
Definition: PIMDM.cc:1684
virtual bool deleteMulticastRoute(IPv4MulticastRoute *entry)=0
Deletes the given multicast route from the routing table.
IIPv4RoutingTable * rt
Definition: PIMBase.h:158
void inet::PIMDM::processStateRefreshPacket ( PIMStateRefresh pkt)
private

The method is used to process PIMStateRefresh packet.

The method checks if there is route in mroute and that packet has came to RPF interface. Then it goes through all outgoing interfaces. If the interface is pruned, it resets Prune Timer. For each interface State Refresh message is copied and correct prune indicator is set according to state of outgoing interface (pruned/forwarding).

State Refresh message is used to stop flooding of network each 3 minutes.

581 {
582  EV << "pimDM::processStateRefreshPacket" << endl;
583 
584  emit(rcvdStateRefreshPkSignal, pkt);
585 
586  // first check if there is route for given group address and source
587  Route *route = findRoute(pkt->getSourceAddress(), pkt->getGroupAddress());
588  if (route == nullptr) {
589  delete pkt;
590  return;
591  }
592 
593  // check if State Refresh msg has came from RPF neighbor
594  IPv4ControlInfo *ctrlInfo = check_and_cast<IPv4ControlInfo *>(pkt->getControlInfo());
595  UpstreamInterface *upstream = route->upstreamInterface;
596  if (ctrlInfo->getInterfaceId() != upstream->getInterfaceId() || upstream->rpfNeighbor() != ctrlInfo->getSrcAddr()) {
597  delete pkt;
598  return;
599  }
600 
601  // upstream state transitions
602  bool pruneIndicator = pkt->getP();
603  switch (upstream->graftPruneState) {
605  if (pruneIndicator) {
606  upstream->startOverrideTimer();
607  }
608  break;
609 
611  if (!pruneIndicator) {
612  if (!upstream->isPruneLimitTimerRunning()) {
613  sendPrunePacket(upstream->rpfNeighbor(), route->source, route->group, pruneInterval, upstream->getInterfaceId());
614  upstream->startPruneLimitTimer();
615  }
616  }
617  else
618  upstream->startPruneLimitTimer();
619  break;
620 
622  if (pruneIndicator) {
623  if (!upstream->overrideTimer)
624  upstream->startOverrideTimer();
625  }
626  else {
627  cancelAndDelete(upstream->graftRetryTimer);
628  upstream->graftRetryTimer = nullptr;
629  upstream->graftPruneState = UpstreamInterface::FORWARDING;
630  }
631  break;
632  }
633 
634  //
635  // Forward StateRefresh message downstream
636  //
637 
638  // TODO check StateRefreshRateLimit(S,G)
639 
640  if (pkt->getTtl() == 0) {
641  delete pkt;
642  return;
643  }
644 
645  // go through all outgoing interfaces, reser Prune Timer and send out State Refresh msg
646  for (unsigned int i = 0; i < route->downstreamInterfaces.size(); i++) {
647  DownstreamInterface *downstream = route->downstreamInterfaces[i];
648  // TODO check ttl threshold and boundary
649  if (downstream->assertState == DownstreamInterface::I_LOST_ASSERT)
650  continue;
651 
652  if (downstream->pruneState == DownstreamInterface::PRUNED) {
653  // reset PT
654  restartTimer(downstream->pruneTimer, pruneInterval);
655  }
656  sendStateRefreshPacket(pkt->getOriginatorAddress(), route, downstream, pkt->getTtl() - 1);
657 
658  //
659  // Assert State Machine; event: Send State Refresh
660  //
661  if (downstream->assertState == DownstreamInterface::I_WON_ASSERT) {
662  // The router is sending a State Refresh(S,G) message on interface I.
663  // The router MUST set the Assert Timer (AT(S,G,I)) to three
664  // times the State Refresh Interval contained in the State Refresh(S,G) message.
665  restartTimer(downstream->assertTimer, 3 * stateRefreshInterval);
666  }
667  }
668 
669  //
670  // Assert State Machine; event: Receive State Refresh
671  //
672  AssertMetric receivedMetric(pkt->getMetricPreference(), pkt->getMetric(), ctrlInfo->getSrcAddr());
673  processAssert(upstream, receivedMetric, pkt->getInterval());
674 
675  delete pkt;
676 }
void processAssert(Interface *downstream, AssertMetric receivedMetric, int stateRefreshInterval)
Definition: PIMDM.cc:705
double pruneInterval
Definition: PIMDM.h:160
static simsignal_t rcvdStateRefreshPkSignal
Definition: PIMDM.h:179
double stateRefreshInterval
Definition: PIMDM.h:166
void restartTimer(cMessage *timer, double interval)
Definition: PIMDM.cc:1661
void sendStateRefreshPacket(IPv4Address originator, Route *route, DownstreamInterface *downstream, unsigned short ttl)
Definition: PIMDM.cc:1599
UpstreamInterface * upstreamInterface
Definition: PIMDM.h:131
Route * findRoute(IPv4Address source, IPv4Address group)
Definition: PIMDM.cc:1695
void sendPrunePacket(IPv4Address nextHop, IPv4Address src, IPv4Address grp, int holdTime, int intId)
Definition: PIMDM.cc:1493
void inet::PIMDM::processStateRefreshTimer ( cMessage *  timer)
private
979 {
980  UpstreamInterface *upstream = static_cast<UpstreamInterface *>(timer->getContextPointer());
981  ASSERT(timer == upstream->stateRefreshTimer);
982  ASSERT(upstream->originatorState == UpstreamInterface::ORIGINATOR);
983 
984  Route *route = upstream->route();
985 
986  EV_INFO << "StateRefreshTimer" << route << " expired.\n";
987 
988  EV_DETAIL << "Sending StateRefresh packets on downstream interfaces.\n";
989  for (unsigned int i = 0; i < route->downstreamInterfaces.size(); i++) {
990  DownstreamInterface *downstream = route->downstreamInterfaces[i];
991  // TODO check ttl threshold and boundary
992  if (downstream->assertState == DownstreamInterface::I_LOST_ASSERT)
993  continue;
994 
995  // when sending StateRefresh in Pruned state, then restart PruneTimer
996  bool isPruned = downstream->pruneState == DownstreamInterface::PRUNED;
997  if (isPruned)
998  restartTimer(downstream->pruneTimer, pruneInterval);
999 
1000  // Send StateRefresh message downstream
1001  IPv4Address originator = downstream->ie->ipv4Data()->getIPAddress();
1002  sendStateRefreshPacket(originator, route, downstream, upstream->maxTtlSeen);
1003  }
1004 
1005  scheduleAt(simTime() + stateRefreshInterval, timer);
1006 }
double pruneInterval
Definition: PIMDM.h:160
double stateRefreshInterval
Definition: PIMDM.h:166
void restartTimer(cMessage *timer, double interval)
Definition: PIMDM.cc:1661
void sendStateRefreshPacket(IPv4Address originator, Route *route, DownstreamInterface *downstream, unsigned short ttl)
Definition: PIMDM.cc:1599
void inet::PIMDM::receiveSignal ( cComponent *  source,
simsignal_t  signalID,
cObject *  obj,
cObject *  details 
)
overrideprivate
1040 {
1041  Enter_Method_Silent();
1042  printNotificationBanner(signalID, obj);
1043  IPv4Datagram *datagram;
1044  PIMInterface *pimInterface;
1045 
1046  // new multicast data appears in router
1047  if (signalID == NF_IPv4_NEW_MULTICAST) {
1048  datagram = check_and_cast<IPv4Datagram *>(obj);
1049  pimInterface = getIncomingInterface(datagram);
1050  if (pimInterface && pimInterface->getMode() == PIMInterface::DenseMode)
1051  unroutableMulticastPacketArrived(datagram->getSrcAddress(), datagram->getDestAddress(), datagram->getTimeToLive());
1052  }
1053  // configuration of interface changed, it means some change from IGMP, address were added.
1054  else if (signalID == NF_IPv4_MCAST_REGISTERED) {
1055  IPv4MulticastGroupInfo *info = check_and_cast<IPv4MulticastGroupInfo *>(obj);
1056  pimInterface = pimIft->getInterfaceById(info->ie->getInterfaceId());
1057  if (pimInterface && pimInterface->getMode() == PIMInterface::DenseMode)
1058  multicastReceiverAdded(pimInterface->getInterfacePtr(), info->groupAddress);
1059  }
1060  // configuration of interface changed, it means some change from IGMP, address were removed.
1061  else if (signalID == NF_IPv4_MCAST_UNREGISTERED) {
1062  IPv4MulticastGroupInfo *info = check_and_cast<IPv4MulticastGroupInfo *>(obj);
1063  pimInterface = pimIft->getInterfaceById(info->ie->getInterfaceId());
1064  if (pimInterface && pimInterface->getMode() == PIMInterface::DenseMode)
1065  multicastReceiverRemoved(pimInterface->getInterfacePtr(), info->groupAddress);
1066  }
1067  // data come to non-RPF interface
1068  else if (signalID == NF_IPv4_DATA_ON_NONRPF) {
1069  datagram = check_and_cast<IPv4Datagram *>(obj);
1070  pimInterface = getIncomingInterface(datagram);
1071  if (pimInterface && pimInterface->getMode() == PIMInterface::DenseMode)
1072  multicastPacketArrivedOnNonRpfInterface(datagram->getDestAddress(), datagram->getSrcAddress(), pimInterface->getInterfaceId());
1073  }
1074  // data come to RPF interface
1075  else if (signalID == NF_IPv4_DATA_ON_RPF) {
1076  datagram = check_and_cast<IPv4Datagram *>(obj);
1077  pimInterface = getIncomingInterface(datagram);
1078  if (pimInterface && pimInterface->getMode() == PIMInterface::DenseMode)
1079  multicastPacketArrivedOnRpfInterface(pimInterface->getInterfaceId(),
1080  datagram->getDestAddress(), datagram->getSrcAddress(), datagram->getTimeToLive());
1081  }
1082  // RPF interface has changed
1083  else if (signalID == NF_ROUTE_ADDED) {
1084  IPv4Route *entry = check_and_cast<IPv4Route *>(obj);
1085  IPv4Address routeSource = entry->getDestination();
1086  IPv4Address routeNetmask = entry->getNetmask();
1087 
1088  int numRoutes = rt->getNumMulticastRoutes();
1089  for (int i = 0; i < numRoutes; i++) {
1090  // find multicast routes whose source are on the destination of the new unicast route
1091  IPv4MulticastRoute *route = rt->getMulticastRoute(i);
1092  if (route->getSource() == this && IPv4Address::maskedAddrAreEqual(route->getOrigin(), routeSource, routeNetmask)) {
1093  IPv4Address source = route->getOrigin();
1094  IPv4Route *routeToSource = rt->findBestMatchingRoute(source);
1095  InterfaceEntry *newRpfInterface = routeToSource->getInterface();
1096  InterfaceEntry *oldRpfInterface = route->getInInterface()->getInterface();
1097 
1098  // is there any change?
1099  if (newRpfInterface != oldRpfInterface)
1100  rpfInterfaceHasChanged(route, routeToSource);
1101 
1102  // TODO update metric
1103  }
1104  }
1105  }
1106 }
simsignal_t NF_IPv4_DATA_ON_RPF
Definition: NotifierConsts.cc:74
static bool maskedAddrAreEqual(const IPv4Address &addr1, const IPv4Address &addr2, const IPv4Address &netmask)
Test if the masked addresses (ie the mask is applied to addr1 and addr2) are equal.
Definition: IPv4Address.cc:260
virtual int getNumMulticastRoutes() const =0
Returns the total number of multicast routes.
void unroutableMulticastPacketArrived(IPv4Address srcAddress, IPv4Address destAddress, unsigned short ttl)
The method process notification about new multicast data stream.
Definition: PIMDM.cc:1113
simsignal_t NF_IPv4_MCAST_UNREGISTERED
Definition: NotifierConsts.cc:68
PIMInterfaceTable * pimIft
Definition: PIMBase.h:160
void multicastPacketArrivedOnNonRpfInterface(IPv4Address group, IPv4Address source, int interfaceId)
The method has to solve the problem when multicast data appears on non-RPF interface.
Definition: PIMDM.cc:1270
void multicastPacketArrivedOnRpfInterface(int interfaceId, IPv4Address group, IPv4Address source, unsigned short ttl)
Definition: PIMDM.cc:1195
void multicastReceiverRemoved(InterfaceEntry *ie, IPv4Address oldAddr)
The method process notification about multicast groups removed from interface.
Definition: PIMDM.cc:1386
virtual IPv4MulticastRoute * getMulticastRoute(int k) const override=0
Returns the kth multicast route.
simsignal_t NF_IPv4_NEW_MULTICAST
Definition: NotifierConsts.cc:70
simsignal_t NF_IPv4_MCAST_REGISTERED
Definition: NotifierConsts.cc:67
PIMInterface * getIncomingInterface(IPv4Datagram *datagram)
Definition: PIMDM.cc:1673
virtual PIMInterface * getInterfaceById(int interfaceId)
Definition: PIMInterfaceTable.cc:116
simsignal_t NF_ROUTE_ADDED
Definition: NotifierConsts.cc:57
InterfaceEntry * getInterface() const override
Next hop interface.
Definition: IPv4Route.h:114
void printNotificationBanner(simsignal_t signalID, const cObject *obj)
Utility function.
Definition: NotifierConsts.cc:109
IIPv4RoutingTable * rt
Definition: PIMBase.h:158
virtual IPv4Route * findBestMatchingRoute(const IPv4Address &dest) const =0
The routing function.
void rpfInterfaceHasChanged(IPv4MulticastRoute *route, IPv4Route *routeToSource)
The method process notification about interface change.
Definition: PIMDM.cc:1422
simsignal_t NF_IPv4_DATA_ON_NONRPF
Definition: NotifierConsts.cc:73
IPv4Address getOrigin() const
Source address prefix to match.
Definition: IPv4Route.h:222
Definition: PIMInterfaceTable.h:36
void multicastReceiverAdded(InterfaceEntry *ie, IPv4Address newAddr)
Definition: PIMDM.cc:1338
void inet::PIMDM::restartTimer ( cMessage *  timer,
double  interval 
)
private
1662 {
1663  cancelEvent(timer);
1664  scheduleAt(simTime() + interval, timer);
1665 }
void inet::PIMDM::rpfInterfaceHasChanged ( IPv4MulticastRoute ipv4Route,
IPv4Route routeToSource 
)
private

The method process notification about interface change.

Multicast routing table will be changed if RPF interface has changed. New RPF interface is set to route and is removed from outgoing interfaces. On the other hand, old RPF interface is added to outgoing interfaces. If route was not pruned, the router has to join to the multicast tree again (by different path).

1423 {
1424  InterfaceEntry *newRpf = routeToSource->getInterface();
1425  IPv4Address source = ipv4Route->getOrigin();
1426  IPv4Address group = ipv4Route->getMulticastGroup();
1427  int rpfId = newRpf->getInterfaceId();
1428 
1429  EV_DETAIL << "New RPF interface for group=" << group << " source=" << source << " is " << newRpf->getName() << endl;
1430 
1431  Route *route = findRoute(source, group);
1432  ASSERT(route);
1433 
1434  // delete old upstream interface data
1435  UpstreamInterface *oldUpstreamInterface = route->upstreamInterface;
1436  InterfaceEntry *oldRpfInterface = oldUpstreamInterface ? oldUpstreamInterface->ie : nullptr;
1437  delete oldUpstreamInterface;
1438  delete ipv4Route->getInInterface();
1439  ipv4Route->setInInterface(nullptr);
1440 
1441  // set new upstream interface data
1442  bool isSourceDirectlyConnected = routeToSource->getSourceType() == IPv4Route::IFACENETMASK;
1443  IPv4Address newRpfNeighbor = pimNbt->getNeighbor(rpfId, 0)->getAddress(); // XXX what happens if no neighbors?
1444  UpstreamInterface *upstream = route->upstreamInterface = new UpstreamInterface(route, newRpf, newRpfNeighbor, isSourceDirectlyConnected);
1445  ipv4Route->setInInterface(new IMulticastRoute::InInterface(newRpf));
1446 
1447  // delete rpf interface from the downstream interfaces
1448  DownstreamInterface *oldDownstreamInterface = route->removeDownstreamInterface(newRpf->getInterfaceId());
1449  if (oldDownstreamInterface) {
1450  ipv4Route->removeOutInterface(newRpf); // will delete downstream data, XXX method should be called deleteOutInterface()
1451  delete oldDownstreamInterface;
1452  }
1453 
1454  // old RPF interface should be now a downstream interface if it is not down
1455  if (oldRpfInterface && oldRpfInterface->isUp()) {
1456  DownstreamInterface *downstream = route->createDownstreamInterface(oldRpfInterface);
1457  ipv4Route->addOutInterface(new PIMDMOutInterface(oldRpfInterface, downstream));
1458  }
1459 
1460  bool isOlistNull = route->isOilistNull();
1461 
1462  // upstream state transitions
1463 
1464  // RPF'(S) Changes AND olist(S,G) != nullptr AND S is NOT directly connected?
1465  if (!isOlistNull && !upstream->isSourceDirectlyConnected()) {
1466  // The Upstream(S,G) state
1467  // machine MUST transition to the AckPending (AP) state, unicast a
1468  // Graft to the new RPF'(S), and set the GraftRetry Timer (GRT(S,G))
1469  // to Graft_Retry_Period.
1470 
1471  if (upstream->graftPruneState == UpstreamInterface::PRUNED)
1472  upstream->stopPruneLimitTimer();
1473 
1474  // route was not pruned, join to the multicast tree again
1475  sendGraftPacket(upstream->rpfNeighbor(), source, group, rpfId);
1476  upstream->startGraftRetryTimer();
1477  upstream->graftPruneState = UpstreamInterface::ACK_PENDING;
1478  }
1479  // RPF'(S) Changes AND olist(S,G) == nullptr
1480  else if (isOlistNull) {
1481  if (upstream->graftPruneState == UpstreamInterface::PRUNED) {
1482  upstream->stopPruneLimitTimer();
1483  }
1484  else if (upstream->graftPruneState == UpstreamInterface::ACK_PENDING) {
1485  cancelAndDelete(upstream->graftRetryTimer);
1486  upstream->graftRetryTimer = nullptr;
1487  }
1488 
1489  upstream->graftPruneState = UpstreamInterface::PRUNED;
1490  }
1491 }
PIMNeighborTable * pimNbt
Definition: PIMBase.h:161
IPv4Address getAddress() const
Definition: PIMNeighborTable.h:58
void sendGraftPacket(IPv4Address nextHop, IPv4Address src, IPv4Address grp, int intId)
Definition: PIMDM.cc:1551
comes from an interface&#39;s netmask
Definition: IRoute.h:41
virtual PIMNeighbor * getNeighbor(int interfaceId, int index)
Returns the neighbor on the given interface at the specified position.
Definition: PIMNeighborTable.cc:182
Route * findRoute(IPv4Address source, IPv4Address group)
Definition: PIMDM.cc:1695
void inet::PIMDM::sendAssertPacket ( IPv4Address  source,
IPv4Address  group,
AssertMetric  metric,
InterfaceEntry ie 
)
private
1625 {
1626  EV_INFO << "Sending Assert(S= " << source << ", G= " << group << ") message on interface '" << ie->getName() << "'\n";
1627 
1628  PIMAssert *pkt = new PIMAssert("PIMAssert");
1629  pkt->setGroupAddress(group);
1630  pkt->setSourceAddress(source);
1631  pkt->setR(false);
1632  pkt->setMetricPreference(metric.preference);
1633  pkt->setMetric(metric.metric);
1634 
1635  pkt->setByteLength(PIM_HEADER_LENGTH
1638  + 8);
1639 
1640  emit(sentAssertPkSignal, pkt);
1641 
1643 }
void sendToIP(PIMPacket *packet, IPv4Address source, IPv4Address dest, int outInterfaceId)
Definition: PIMDM.cc:1645
#define ENCODED_UNICODE_ADDRESS_LENGTH
Definition: PIMPacket_m.h:34
static simsignal_t sentAssertPkSignal
Definition: PIMDM.h:176
#define ENCODED_GROUP_ADDRESS_LENGTH
Definition: PIMPacket_m.h:35
static const IPv4Address UNSPECIFIED_ADDRESS
0.0.0.0
Definition: IPv4Address.h:102
static const IPv4Address ALL_PIM_ROUTERS_MCAST
Definition: PIMBase.h:155
#define PIM_HEADER_LENGTH
Definition: PIMPacket_m.h:33
void inet::PIMDM::sendGraftAckPacket ( PIMGraft msg)
private
1580 {
1581  EV_INFO << "Sending GraftAck message.\n";
1582 
1583  IPv4ControlInfo *oldCtrl = check_and_cast<IPv4ControlInfo *>(graftPacket->removeControlInfo());
1584  IPv4Address destAddr = oldCtrl->getSrcAddr();
1585  IPv4Address srcAddr = oldCtrl->getDestAddr();
1586  int outInterfaceId = oldCtrl->getInterfaceId();
1587  delete oldCtrl;
1588 
1589  PIMGraftAck *msg = new PIMGraftAck();
1590  *((PIMGraft *)msg) = *graftPacket;
1591  msg->setName("PIMGraftAck");
1592  msg->setType(GraftAck);
1593 
1594  emit(sentGraftAckPkSignal, msg);
1595 
1596  sendToIP(msg, srcAddr, destAddr, outInterfaceId);
1597 }
static simsignal_t sentGraftAckPkSignal
Definition: PIMDM.h:172
void sendToIP(PIMPacket *packet, IPv4Address source, IPv4Address dest, int outInterfaceId)
Definition: PIMDM.cc:1645
Definition: PIMPacket_m.h:69
void inet::PIMDM::sendGraftPacket ( IPv4Address  nextHop,
IPv4Address  src,
IPv4Address  grp,
int  intId 
)
private
1552 {
1553  EV_INFO << "Sending Graft(S=" << src << ", G=" << grp << ") message to neighbor '" << nextHop << "' on interface '" << intId << "'\n";
1554 
1555  PIMGraft *msg = new PIMGraft("PIMGraft");
1556  msg->setHoldTime(0);
1557  msg->setUpstreamNeighborAddress(nextHop);
1558 
1559  msg->setJoinPruneGroupsArraySize(1);
1560  JoinPruneGroup& group = msg->getJoinPruneGroups(0);
1561  group.setGroupAddress(grp);
1562  group.setJoinedSourceAddressArraySize(1);
1563  EncodedAddress& address = group.getJoinedSourceAddress(0);
1564  address.IPaddress = src;
1565 
1567 
1568  emit(sentGraftPkSignal, msg);
1569 
1570  sendToIP(msg, IPv4Address::UNSPECIFIED_ADDRESS, nextHop, intId);
1571 }
static simsignal_t sentGraftPkSignal
Definition: PIMDM.h:170
void sendToIP(PIMPacket *packet, IPv4Address source, IPv4Address dest, int outInterfaceId)
Definition: PIMDM.cc:1645
#define ENCODED_SOURCE_ADDRESS_LENGTH
Definition: PIMPacket_m.h:36
#define ENCODED_GROUP_ADDRESS_LENGTH
Definition: PIMPacket_m.h:35
static const IPv4Address UNSPECIFIED_ADDRESS
0.0.0.0
Definition: IPv4Address.h:102
#define PIM_HEADER_LENGTH
Definition: PIMPacket_m.h:33
void inet::PIMDM::sendJoinPacket ( IPv4Address  nextHop,
IPv4Address  source,
IPv4Address  group,
int  interfaceId 
)
private
1520 {
1521  ASSERT(!src.isUnspecified());
1522  ASSERT(grp.isMulticast());
1523 
1524  EV_INFO << "Sending Join(S=" << src << ", G=" << grp << ") message to neighbor '" << nextHop << "' on interface '" << intId << "'\n";
1525 
1526  PIMJoinPrune *packet = new PIMJoinPrune("PIMJoin");
1527  packet->setUpstreamNeighborAddress(nextHop);
1528  packet->setHoldTime(0); // ignored by the receiver
1529 
1530  // set multicast groups
1531  packet->setJoinPruneGroupsArraySize(1);
1532  JoinPruneGroup& group = packet->getJoinPruneGroups(0);
1533  group.setGroupAddress(grp);
1534  group.setJoinedSourceAddressArraySize(1);
1535  EncodedAddress& address = group.getJoinedSourceAddress(0);
1536  address.IPaddress = src;
1537 
1539 
1540  emit(sentJoinPrunePkSignal, packet);
1541 
1543 }
void sendToIP(PIMPacket *packet, IPv4Address source, IPv4Address dest, int outInterfaceId)
Definition: PIMDM.cc:1645
static simsignal_t sentJoinPrunePkSignal
Definition: PIMDM.h:174
#define ENCODED_SOURCE_ADDRESS_LENGTH
Definition: PIMPacket_m.h:36
#define ENCODED_GROUP_ADDRESS_LENGTH
Definition: PIMPacket_m.h:35
static const IPv4Address UNSPECIFIED_ADDRESS
0.0.0.0
Definition: IPv4Address.h:102
static const IPv4Address ALL_PIM_ROUTERS_MCAST
Definition: PIMBase.h:155
#define PIM_HEADER_LENGTH
Definition: PIMPacket_m.h:33
void inet::PIMDM::sendPrunePacket ( IPv4Address  nextHop,
IPv4Address  src,
IPv4Address  grp,
int  holdTime,
int  intId 
)
private
1494 {
1495  ASSERT(!src.isUnspecified());
1496  ASSERT(grp.isMulticast());
1497 
1498  EV_INFO << "Sending Prune(S=" << src << ", G=" << grp << ") message to neighbor '" << nextHop << "' on interface '" << intId << "'\n";
1499 
1500  PIMJoinPrune *packet = new PIMJoinPrune("PIMPrune");
1501  packet->setUpstreamNeighborAddress(nextHop);
1502  packet->setHoldTime(holdTime);
1503 
1504  // set multicast groups
1505  packet->setJoinPruneGroupsArraySize(1);
1506  JoinPruneGroup& group = packet->getJoinPruneGroups(0);
1507  group.setGroupAddress(grp);
1508  group.setPrunedSourceAddressArraySize(1);
1509  EncodedAddress& address = group.getPrunedSourceAddress(0);
1510  address.IPaddress = src;
1511 
1513 
1514  emit(sentJoinPrunePkSignal, packet);
1515 
1517 }
void sendToIP(PIMPacket *packet, IPv4Address source, IPv4Address dest, int outInterfaceId)
Definition: PIMDM.cc:1645
static simsignal_t sentJoinPrunePkSignal
Definition: PIMDM.h:174
#define ENCODED_SOURCE_ADDRESS_LENGTH
Definition: PIMPacket_m.h:36
double holdTime
Definition: PIMBase.h:169
#define ENCODED_GROUP_ADDRESS_LENGTH
Definition: PIMPacket_m.h:35
static const IPv4Address UNSPECIFIED_ADDRESS
0.0.0.0
Definition: IPv4Address.h:102
static const IPv4Address ALL_PIM_ROUTERS_MCAST
Definition: PIMBase.h:155
#define PIM_HEADER_LENGTH
Definition: PIMPacket_m.h:33
void inet::PIMDM::sendStateRefreshPacket ( IPv4Address  originator,
Route route,
DownstreamInterface downstream,
unsigned short  ttl 
)
private
1600 {
1601  EV_INFO << "Sending StateRefresh(S=" << route->source << ", G=" << route->group
1602  << ") message on interface '" << downstream->ie->getName() << "'\n";
1603 
1604  PIMStateRefresh *msg = new PIMStateRefresh("PIMStateRefresh");
1605  msg->setGroupAddress(route->group);
1606  msg->setSourceAddress(route->source);
1607  msg->setOriginatorAddress(originator);
1608  msg->setInterval(stateRefreshInterval);
1609  msg->setTtl(ttl);
1610  msg->setP(downstream->pruneState == DownstreamInterface::PRUNED);
1611  // TODO set metric
1612 
1613  msg->setByteLength(PIM_HEADER_LENGTH
1617  + 12);
1618 
1619  emit(sentStateRefreshPkSignal, msg);
1620 
1621  sendToIP(msg, IPv4Address::UNSPECIFIED_ADDRESS, ALL_PIM_ROUTERS_MCAST, downstream->ie->getInterfaceId());
1622 }
static simsignal_t sentStateRefreshPkSignal
Definition: PIMDM.h:178
void sendToIP(PIMPacket *packet, IPv4Address source, IPv4Address dest, int outInterfaceId)
Definition: PIMDM.cc:1645
#define ENCODED_UNICODE_ADDRESS_LENGTH
Definition: PIMPacket_m.h:34
double stateRefreshInterval
Definition: PIMDM.h:166
#define ENCODED_GROUP_ADDRESS_LENGTH
Definition: PIMPacket_m.h:35
static const IPv4Address UNSPECIFIED_ADDRESS
0.0.0.0
Definition: IPv4Address.h:102
static const IPv4Address ALL_PIM_ROUTERS_MCAST
Definition: PIMBase.h:155
uint8_t ttl
Definition: TCP_NSC.cc:87
#define PIM_HEADER_LENGTH
Definition: PIMPacket_m.h:33
void inet::PIMDM::sendToIP ( PIMPacket packet,
IPv4Address  source,
IPv4Address  dest,
int  outInterfaceId 
)
private
1646 {
1647  IPv4ControlInfo *ctrl = new IPv4ControlInfo();
1648  ctrl->setSrcAddr(srcAddr);
1649  ctrl->setDestAddr(destAddr);
1650  ctrl->setProtocol(IP_PROT_PIM);
1651  ctrl->setTimeToLive(1);
1652  ctrl->setInterfaceId(outInterfaceId);
1653  packet->setControlInfo(ctrl);
1654  send(packet, "ipOut");
1655 }
Definition: IPProtocolId_m.h:90
void inet::PIMDM::stopPIMRouting ( )
protectedvirtual
105 {
106  if (isEnabled) {
107  cModule *host = findContainingNode(this);
108  if (!host)
109  throw cRuntimeError("PIMDM: containing node not found.");
110  host->unsubscribe(NF_IPv4_NEW_MULTICAST, this);
111  host->unsubscribe(NF_IPv4_MCAST_REGISTERED, this);
112  host->unsubscribe(NF_IPv4_MCAST_UNREGISTERED, this);
113  host->unsubscribe(NF_IPv4_DATA_ON_NONRPF, this);
114  host->unsubscribe(NF_IPv4_DATA_ON_RPF, this);
115  host->unsubscribe(NF_ROUTE_ADDED, this);
116  host->unsubscribe(NF_INTERFACE_STATE_CHANGED, this);
117  }
118 
119  clearRoutes();
120 }
bool isEnabled
Definition: PIMBase.h:164
simsignal_t NF_IPv4_DATA_ON_RPF
Definition: NotifierConsts.cc:74
simsignal_t NF_IPv4_MCAST_UNREGISTERED
Definition: NotifierConsts.cc:68
simsignal_t NF_IPv4_NEW_MULTICAST
Definition: NotifierConsts.cc:70
cModule * findContainingNode(const cModule *from)
Find the node containing the given module.
Definition: ModuleAccess.cc:56
simsignal_t NF_IPv4_MCAST_REGISTERED
Definition: NotifierConsts.cc:67
simsignal_t NF_INTERFACE_STATE_CHANGED
Definition: NotifierConsts.cc:50
simsignal_t NF_ROUTE_ADDED
Definition: NotifierConsts.cc:57
void clearRoutes()
Definition: PIMDM.cc:1710
simsignal_t NF_IPv4_DATA_ON_NONRPF
Definition: NotifierConsts.cc:73
void inet::PIMDM::unroutableMulticastPacketArrived ( IPv4Address  source,
IPv4Address  group,
unsigned short  ttl 
)
private

The method process notification about new multicast data stream.

It goes through all PIM interfaces and tests them if they can be added to the list of outgoing interfaces. If there is no interface on the list at the end, the router will prune from the multicast tree.

1114 {
1115  ASSERT(!source.isUnspecified());
1116  ASSERT(group.isMulticast());
1117 
1118  EV_DETAIL << "New multicast source observed: source=" << source << ", group=" << group << ".\n";
1119 
1120  IPv4Route *routeToSrc = rt->findBestMatchingRoute(source);
1121  if (!routeToSrc || !routeToSrc->getInterface()) {
1122  EV << "ERROR: PIMDM::newMulticast(): cannot find RPF interface, routing information is missing.";
1123  return;
1124  }
1125 
1126  PIMInterface *rpfInterface = pimIft->getInterfaceById(routeToSrc->getInterface()->getInterfaceId());
1127  if (!rpfInterface || rpfInterface->getMode() != PIMInterface::DenseMode)
1128  return;
1129 
1130  // gateway is unspecified for directly connected destinations
1131  bool isSourceDirectlyConnected = routeToSrc->getSourceType() == IPv4Route::IFACENETMASK;
1132  IPv4Address rpfNeighbor = routeToSrc->getGateway().isUnspecified() ? source : routeToSrc->getGateway();
1133 
1134  Route *route = new Route(this, source, group);
1135  routes[SourceAndGroup(source, group)] = route;
1136  route->metric = AssertMetric(routeToSrc->getAdminDist(), routeToSrc->getMetric(), IPv4Address::UNSPECIFIED_ADDRESS);
1137  route->upstreamInterface = new UpstreamInterface(route, rpfInterface->getInterfacePtr(), rpfNeighbor, isSourceDirectlyConnected);
1138 
1139  // if the source is directly connected, then go to the Originator state
1140  if (isSourceDirectlyConnected) {
1141  route->upstreamInterface->originatorState = UpstreamInterface::ORIGINATOR;
1142  if (rpfInterface->getSR())
1143  route->upstreamInterface->startStateRefreshTimer();
1144  route->upstreamInterface->startSourceActiveTimer();
1145  route->upstreamInterface->maxTtlSeen = ttl;
1146  }
1147 
1148  bool allDownstreamInterfacesArePruned = true;
1149 
1150  // insert all PIM interfaces except rpf int
1151  for (int i = 0; i < pimIft->getNumInterfaces(); i++) {
1152  PIMInterface *pimInterface = pimIft->getInterface(i);
1153 
1154  //check if PIM-DM interface and it is not RPF interface
1155  if (pimInterface == rpfInterface || pimInterface->getMode() != PIMInterface::DenseMode) // XXX original code added downstream if data for PIM-SM interfaces too
1156  continue;
1157 
1158  bool hasPIMNeighbors = pimNbt->getNumNeighbors(pimInterface->getInterfaceId()) > 0;
1159  bool hasConnectedReceivers = pimInterface->getInterfacePtr()->ipv4Data()->hasMulticastListener(group);
1160 
1161  // if there are neighbors on interface, we will forward
1162  if (hasPIMNeighbors || hasConnectedReceivers) {
1163  // create new outgoing interface
1164  DownstreamInterface *downstream = route->createDownstreamInterface(pimInterface->getInterfacePtr());
1165  downstream->setHasConnectedReceivers(hasConnectedReceivers);
1166  allDownstreamInterfacesArePruned = false;
1167  }
1168  }
1169 
1170  // if there is no outgoing interface, prune from multicast tree
1171  if (allDownstreamInterfacesArePruned) {
1172  EV_DETAIL << "There is no outgoing interface for multicast, will send Prune message to upstream.\n";
1173  route->upstreamInterface->graftPruneState = UpstreamInterface::PRUNED;
1174 
1175  // Prune message is sent from the forwarding hook (NF_IPv4_DATA_ON_RPF), see multicastPacketArrivedOnRpfInterface()
1176  }
1177 
1178  // create new multicast route
1179  IPv4MulticastRoute *newRoute = new IPv4MulticastRoute();
1180  newRoute->setOrigin(source);
1181  newRoute->setOriginNetmask(IPv4Address::ALLONES_ADDRESS);
1182  newRoute->setMulticastGroup(group);
1183  newRoute->setSourceType(IMulticastRoute::PIM_DM);
1184  newRoute->setSource(this);
1185  newRoute->setInInterface(new IMulticastRoute::InInterface(route->upstreamInterface->ie));
1186  for (auto & elem : route->downstreamInterfaces) {
1187  DownstreamInterface *downstream = elem;
1188  newRoute->addOutInterface(new PIMDMOutInterface(downstream->ie, downstream));
1189  }
1190 
1191  rt->addMulticastRoute(newRoute);
1192  EV_DETAIL << "New route was added to the multicast routing table.\n";
1193 }
PIMNeighborTable * pimNbt
Definition: PIMBase.h:161
virtual void addMulticastRoute(IPv4MulticastRoute *entry)=0
Adds a multicast route to the routing table.
virtual PIMInterface * getInterface(int k)
Definition: PIMInterfaceTable.h:80
PIMInterfaceTable * pimIft
Definition: PIMBase.h:160
managed by PIM-DM router
Definition: IRoute.h:156
comes from an interface&#39;s netmask
Definition: IRoute.h:41
virtual int getNumNeighbors(int interfaceId)
Returns the number of neighbors on the given interface.
Definition: PIMNeighborTable.cc:176
virtual PIMInterface * getInterfaceById(int interfaceId)
Definition: PIMInterfaceTable.cc:116
IIPv4RoutingTable * rt
Definition: PIMBase.h:158
virtual IPv4Route * findBestMatchingRoute(const IPv4Address &dest) const =0
The routing function.
static const IPv4Address UNSPECIFIED_ADDRESS
0.0.0.0
Definition: IPv4Address.h:102
virtual int getNumInterfaces()
Definition: PIMInterfaceTable.h:79
RoutingTable routes
Definition: PIMDM.h:182
static const IPv4Address ALLONES_ADDRESS
255.255.255.255
Definition: IPv4Address.h:105
Definition: PIMInterfaceTable.h:36
uint8_t ttl
Definition: TCP_NSC.cc:87

Friends And Related Function Documentation

std::ostream& operator<< ( std::ostream &  out,
const Route route 
)
friend

Member Data Documentation

double inet::PIMDM::assertTime = 0
private
double inet::PIMDM::graftRetryInterval = 0
private
double inet::PIMDM::overrideInterval = 0
private
double inet::PIMDM::propagationDelay = 0
private
double inet::PIMDM::pruneInterval = 0
private
double inet::PIMDM::pruneLimitInterval = 0
private
simsignal_t inet::PIMDM::rcvdAssertPkSignal = registerSignal("rcvdAssertPk")
staticprivate
simsignal_t inet::PIMDM::rcvdGraftAckPkSignal = registerSignal("rcvdGraftAckPk")
staticprivate
simsignal_t inet::PIMDM::rcvdGraftPkSignal = registerSignal("rcvdGraftPk")
staticprivate
simsignal_t inet::PIMDM::rcvdJoinPrunePkSignal = registerSignal("rcvdJoinPrunePk")
staticprivate
simsignal_t inet::PIMDM::rcvdStateRefreshPkSignal = registerSignal("rcvdStateRefreshPk")
staticprivate
RoutingTable inet::PIMDM::routes
private
simsignal_t inet::PIMDM::sentAssertPkSignal = registerSignal("sentAssertPk")
staticprivate
simsignal_t inet::PIMDM::sentGraftAckPkSignal = registerSignal("sentGraftAckPk")
staticprivate
simsignal_t inet::PIMDM::sentGraftPkSignal = registerSignal("sentGraftPk")
staticprivate
simsignal_t inet::PIMDM::sentJoinPrunePkSignal = registerSignal("sentJoinPrunePk")
staticprivate
simsignal_t inet::PIMDM::sentStateRefreshPkSignal = registerSignal("sentStateRefreshPk")
staticprivate
double inet::PIMDM::sourceActiveInterval = 0
private
double inet::PIMDM::stateRefreshInterval = 0
private

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