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

Implementation of PIM-SM protocol (RFC 4601). More...

#include <PimSm.h>

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

Classes

struct  DownstreamInterface
 
struct  PimsmInterface
 
class  PimSmOutInterface
 
struct  Route
 
struct  UpstreamInterface
 

Public Member Functions

 PimSm ()
 
virtual ~PimSm ()
 
- Public Member Functions inherited from inet::PimBase
 PimBase (PimInterface::PimMode mode)
 
virtual ~PimBase ()
 
- Public Member Functions inherited from inet::RoutingProtocolBase
 RoutingProtocolBase ()
 
- Public Member Functions inherited from inet::OperationalMixin< cSimpleModule >
virtual ~OperationalMixin ()
 }@ More...
 
- Public Member Functions inherited from inet::ILifecycle
virtual ~ILifecycle ()
 

Protected Member Functions

virtual int numInitStages () const override
 
virtual void initialize (int stage) override
 
virtual void handleStartOperation (LifecycleOperation *operation) override
 
virtual void handleStopOperation (LifecycleOperation *operation) override
 
virtual void handleCrashOperation (LifecycleOperation *operation) override
 
virtual void stopPIMRouting ()
 
virtual void handleMessageWhenUp (cMessage *msg) override
 
virtual void receiveSignal (cComponent *source, simsignal_t signalID, cObject *obj, cObject *details) override
 
- Protected Member Functions inherited from inet::PimBase
void sendHelloPackets ()
 
void sendHelloPacket (PimInterface *pimInterface)
 
void processHelloTimer (cMessage *timer)
 
void processHelloPacket (Packet *pk)
 
- Protected Member Functions inherited from inet::RoutingProtocolBase
virtual bool isInitializeStage (int stage) const override
 
virtual bool isModuleStartStage (int stage) const override
 
virtual bool isModuleStopStage (int stage) const override
 
- Protected Member Functions inherited from inet::OperationalMixin< cSimpleModule >
virtual int numInitStages () const override
 
virtual void refreshDisplay () const override
 
virtual void handleMessage (cMessage *msg) override
 
virtual void handleMessageWhenDown (cMessage *msg)
 
virtual bool handleOperationStage (LifecycleOperation *operation, IDoneCallback *doneCallback) override
 Perform one stage of a lifecycle operation. More...
 
virtual State getInitialOperationalState () const
 Returns initial operational state: OPERATING or NOT_OPERATING. More...
 
virtual void handleActiveOperationTimeout (cMessage *message)
 
virtual bool isUp () const
 utility functions More...
 
virtual bool isDown () const
 
virtual void setOperationalState (State newState)
 
virtual void scheduleOperationTimeout (simtime_t timeout)
 
virtual void setupActiveOperation (LifecycleOperation *operation, IDoneCallback *doneCallback, State)
 
virtual void delayActiveOperationFinish (simtime_t timeout)
 
virtual void startActiveOperationExtraTime (simtime_t delay=SIMTIME_ZERO)
 
virtual void startActiveOperationExtraTimeOrFinish (simtime_t extraTime)
 
virtual void finishActiveOperation ()
 

Private Types

enum  RouteType { RP, G, SG, SGrpt }
 
typedef std::vector< DownstreamInterface * > DownstreamInterfaceVector
 
typedef std::map< SourceAndGroup, Route * > RoutingTable
 

Private Member Functions

void processJoinPrunePacket (Packet *pk)
 
void processRegisterPacket (Packet *pk)
 The method is used for processing PIM Register message sent from source DR. More...
 
void processRegisterStopPacket (Packet *pk)
 The method is used for processing PIM Register-Stop message sent from RP. More...
 
void processAssertPacket (Packet *pk)
 
void processJoinG (Ipv4Address group, Ipv4Address rp, Ipv4Address upstreamNeighborField, int holdTime, NetworkInterface *inInterface)
 
void processJoinSG (Ipv4Address origin, Ipv4Address group, Ipv4Address upstreamNeighborField, int holdTime, NetworkInterface *inInterface)
 
void processJoinSGrpt (Ipv4Address origin, Ipv4Address group, Ipv4Address upstreamNeighborField, int holdTime, NetworkInterface *inInterface)
 
void processPruneG (Ipv4Address multGroup, Ipv4Address upstreamNeighborField, NetworkInterface *inInterface)
 
void processPruneSG (Ipv4Address source, Ipv4Address group, Ipv4Address upstreamNeighborField, NetworkInterface *inInterface)
 
void processPruneSGrpt (Ipv4Address source, Ipv4Address group, Ipv4Address upstreamNeighborField, NetworkInterface *inInterface)
 
void processAssertSG (PimsmInterface *interface, const AssertMetric &receivedMetric)
 
void processAssertG (PimsmInterface *interface, const AssertMetric &receivedMetric)
 
void processKeepAliveTimer (cMessage *timer)
 
void processRegisterStopTimer (cMessage *timer)
 
void processExpiryTimer (cMessage *timer)
 The method is used to process PIM Expiry Timer. More...
 
void processJoinTimer (cMessage *timer)
 
void processPrunePendingTimer (cMessage *timer)
 Prune Pending Timer is used for delaying of Prune message sending (for possible overriding Join from another PIM neighbor) More...
 
void processAssertTimer (cMessage *timer)
 
void unroutableMulticastPacketArrived (Ipv4Address srcAddr, Ipv4Address destAddr)
 
void multicastPacketArrivedOnRpfInterface (Route *route)
 The method process notification about data which appears on RPF interface. More...
 
void multicastPacketArrivedOnNonRpfInterface (Route *route, int interfaceId)
 
void multicastPacketForwarded (Packet *pk)
 
void multicastReceiverAdded (NetworkInterface *ie, Ipv4Address group)
 
void multicastReceiverRemoved (NetworkInterface *ie, Ipv4Address group)
 
void joinDesiredChanged (Route *route)
 
void designatedRouterAddressHasChanged (NetworkInterface *ie)
 
void iAmDRHasChanged (NetworkInterface *ie, bool iAmDR)
 
void sendPIMRegister (Packet *pk, Ipv4Address dest, int outInterfaceId)
 
void sendPIMRegisterStop (Ipv4Address source, Ipv4Address dest, Ipv4Address multGroup, Ipv4Address multSource)
 
void sendPIMRegisterNull (Ipv4Address multSource, Ipv4Address multDest)
 
void sendPIMJoin (Ipv4Address group, Ipv4Address source, Ipv4Address upstreamNeighbor, RouteType JPtype)
 
void sendPIMPrune (Ipv4Address group, Ipv4Address source, Ipv4Address upstreamNeighbor, RouteType JPtype)
 
void sendPIMAssert (Ipv4Address source, Ipv4Address group, AssertMetric metric, NetworkInterface *ie, bool rptBit)
 
void sendToIP (Packet *packet, Ipv4Address source, Ipv4Address dest, int outInterfaceId, short ttl)
 
void forwardMulticastData (Packet *pk, int outInterfaceId)
 The method is used as abstraction for encapsulation multicast data to Register packet. More...
 
double joinPruneHoldTime ()
 
double effectivePropagationDelay ()
 
double effectiveOverrideInterval ()
 
double joinPruneOverrideInterval ()
 
void updateJoinDesired (Route *route)
 
void updateDesignatedRouterAddress (NetworkInterface *ie)
 
void updateCouldAssert (DownstreamInterface *interface)
 
void updateAssertTrackingDesired (PimsmInterface *interface)
 
bool IamRP (Ipv4Address rpAddr)
 
bool IamDR (NetworkInterface *ie)
 
PimInterfacegetIncomingInterface (NetworkInterface *fromIE)
 
bool deleteMulticastRoute (Route *route)
 
void clearRoutes ()
 
void cancelAndDeleteTimer (cMessage *&timer)
 
void restartTimer (cMessage *timer, double interval)
 
void restartExpiryTimer (Route *route, NetworkInterface *originIntf, int holdTime)
 The method is used to restart ET. More...
 
bool removeRoute (Route *route)
 
RoutefindRouteG (Ipv4Address group)
 
RoutefindRouteSG (Ipv4Address source, Ipv4Address group)
 
RouteaddNewRouteG (Ipv4Address group, int flags)
 
RouteaddNewRouteSG (Ipv4Address source, Ipv4Address group, int flags)
 
Ipv4MulticastRoutecreateIpv4Route (Route *route)
 
Ipv4MulticastRoutefindIpv4Route (Ipv4Address source, Ipv4Address group)
 

Private Attributes

Ipv4Address rpAddr
 
double joinPrunePeriod = 0
 
double defaultOverrideInterval = 0
 
double defaultPropagationDelay = 0
 
double keepAlivePeriod = 0
 
double rpKeepAlivePeriod = 0
 
double registerSuppressionTime = 0
 
double registerProbeTime = 0
 
double assertTime = 0
 
double assertOverrideInterval = 0
 
RoutingTable gRoutes
 
RoutingTable sgRoutes
 

Static Private Attributes

static simsignal_t sentRegisterPkSignal = registerSignal("sentRegisterPk")
 
static simsignal_t rcvdRegisterPkSignal = registerSignal("rcvdRegisterPk")
 
static simsignal_t sentRegisterStopPkSignal = registerSignal("sentRegisterStopPk")
 
static simsignal_t rcvdRegisterStopPkSignal = registerSignal("rcvdRegisterStopPk")
 
static simsignal_t sentJoinPrunePkSignal = registerSignal("sentJoinPrunePk")
 
static simsignal_t rcvdJoinPrunePkSignal = registerSignal("rcvdJoinPrunePk")
 
static simsignal_t sentAssertPkSignal = registerSignal("sentAssertPk")
 
static simsignal_t rcvdAssertPkSignal = registerSignal("rcvdAssertPk")
 

Friends

std::ostream & operator<< (std::ostream &out, const PimSm::Route &sourceGroup)
 

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 Types inherited from inet::OperationalMixin< cSimpleModule >
enum  State
 
- Protected Attributes inherited from inet::PimBase
ModuleRefByPar< IIpv4RoutingTablert
 
ModuleRefByPar< IInterfaceTableift
 
ModuleRefByPar< PimInterfaceTablepimIft
 
ModuleRefByPar< PimNeighborTablepimNbt
 
opp_component_ptr< PimpimModule
 
bool isUp = false
 
bool isEnabled = false
 
const char * hostname = nullptr
 
double helloPeriod = 0
 
double holdTime = 0
 
int designatedRouterPriority = 0
 
PimInterface::PimMode mode = static_cast<PimInterface::PimMode>(0)
 
uint32_t generationID = 0
 
cMessage * helloTimer = nullptr
 
- Protected Attributes inherited from inet::OperationalMixin< cSimpleModule >
State operationalState
 
simtime_t lastChange
 
Operation activeOperation
 
cMessage * activeOperationTimeout
 
cMessage * activeOperationExtraTimer
 
- 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-SM protocol (RFC 4601).

Protocol state is stored in two tables:

  • gRoutes table contains (*,G) state
  • sgRoutes table contains (S,G) state Note that (*,*,RP) and (S,G,rpt) state is currently missing.

The routes stored in the tables are not the same as the routes of the Ipv4RoutingTable. The RFC defines the terms "Tree Information Base" (TIB) and "Multicast Forwaring Information Base" (MFIB). According to this division, TIB is the state of this module, while MFIB is stored by Ipv4RoutingTable.

Incoming packets, notifications, and timer events may cause a change of the TIB, and of the MFIB (if the forwarding rules change).

Member Typedef Documentation

◆ DownstreamInterfaceVector

◆ RoutingTable

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

Member Enumeration Documentation

◆ RouteType

enum inet::PimSm::RouteType
private
Enumerator
RP 
SG 
SGrpt 
121  {
122  RP, // (*,*,RP)
123  G, // (*,G)
124  SG, // (S,G)
125  SGrpt // (S,G,rpt)
126  };

Constructor & Destructor Documentation

◆ PimSm()

inet::PimSm::PimSm ( )
inline

◆ ~PimSm()

inet::PimSm::~PimSm ( )
virtual
37 {
38  for (auto& elem : gRoutes)
39  delete elem.second;
40  for (auto& elem : sgRoutes)
41  delete elem.second;
42  // TODO rt contains references to the deleted route entries
43 }

Member Function Documentation

◆ addNewRouteG()

PimSm::Route * inet::PimSm::addNewRouteG ( Ipv4Address  group,
int  flags 
)
private
1740 {
1741  Route *newRouteG = new Route(this, G, Ipv4Address::UNSPECIFIED_ADDRESS, group);
1742  newRouteG->setFlags(flags);
1743  newRouteG->rpAddr = rpAddr;
1744 
1745  // set upstream interface toward RP and set metric
1746  if (!IamRP(rpAddr)) {
1747  Ipv4Route *routeToRP = rt->findBestMatchingRoute(rpAddr);
1748  if (routeToRP) {
1749  NetworkInterface *ieTowardRP = routeToRP->getInterface();
1750  Ipv4Address rpfNeighbor = routeToRP->getGateway();
1751  if (!pimNbt->findNeighbor(ieTowardRP->getInterfaceId(), rpfNeighbor) &&
1752  pimNbt->getNumNeighbors(ieTowardRP->getInterfaceId()) > 0)
1753  {
1754  PimNeighbor *neighbor = pimNbt->getNeighbor(ieTowardRP->getInterfaceId(), 0);
1755  if (neighbor)
1756  rpfNeighbor = neighbor->getAddress();
1757  }
1758  newRouteG->upstreamInterface = new UpstreamInterface(newRouteG, ieTowardRP, rpfNeighbor);
1759  newRouteG->metric = AssertMetric(true, routeToRP->getAdminDist(), routeToRP->getMetric());
1760  }
1761  }
1762 
1763  // add downstream interfaces
1764  for (int i = 0; i < pimIft->getNumInterfaces(); i++) {
1765  PimInterface *pimInterface = pimIft->getInterface(i);
1766  if (pimInterface->getMode() == PimInterface::SparseMode &&
1767  (!newRouteG->upstreamInterface || pimInterface->getInterfacePtr() != newRouteG->upstreamInterface->ie))
1768  {
1769  DownstreamInterface *downstream = new DownstreamInterface(newRouteG, pimInterface->getInterfacePtr(), DownstreamInterface::NO_INFO);
1770  newRouteG->addDownstreamInterface(downstream);
1771  }
1772  }
1773 
1774  SourceAndGroup sg(Ipv4Address::UNSPECIFIED_ADDRESS, group);
1775  gRoutes[sg] = newRouteG;
1776  rt->addMulticastRoute(createIpv4Route(newRouteG));
1777 
1778  // set (*,G) route in (S,G) and (S,G,rpt) routes
1779  for (auto& elem : sgRoutes) {
1780  if (elem.first.group == group) {
1781  Route *sgRoute = elem.second;
1782  sgRoute->gRoute = newRouteG;
1783  }
1784  }
1785 
1786  return newRouteG;
1787 }

Referenced by multicastReceiverAdded(), processJoinG(), processRegisterPacket(), and unroutableMulticastPacketArrived().

◆ addNewRouteSG()

PimSm::Route * inet::PimSm::addNewRouteSG ( Ipv4Address  source,
Ipv4Address  group,
int  flags 
)
private
1790 {
1791  ASSERT(!source.isUnspecified());
1792  ASSERT(group.isMulticast() && !group.isLinkLocalMulticast());
1793 
1794  Route *newRouteSG = new Route(this, SG, source, group);
1795  newRouteSG->setFlags(flags);
1796  newRouteSG->rpAddr = rpAddr;
1797 
1798  // set upstream interface toward source and set metric
1799  Ipv4Route *routeToSource = rt->findBestMatchingRoute(source);
1800  if (routeToSource) {
1801  NetworkInterface *ieTowardSource = routeToSource->getInterface();
1802  Ipv4Address rpfNeighbor = routeToSource->getGateway();
1803 
1804  if (rpfNeighbor.isUnspecified())
1805  newRouteSG->setFlag(Route::SOURCE_DIRECTLY_CONNECTED, true);
1806  else {
1807  if (!pimNbt->findNeighbor(ieTowardSource->getInterfaceId(), rpfNeighbor) &&
1808  pimNbt->getNumNeighbors(ieTowardSource->getInterfaceId()) > 0)
1809  {
1810  PimNeighbor *neighbor = pimNbt->getNeighbor(ieTowardSource->getInterfaceId(), 0);
1811  if (neighbor)
1812  rpfNeighbor = neighbor->getAddress();
1813  }
1814  }
1815  newRouteSG->upstreamInterface = new UpstreamInterface(newRouteSG, ieTowardSource, rpfNeighbor);
1816  newRouteSG->metric = AssertMetric(false, routeToSource->getAdminDist(), routeToSource->getMetric());
1817  }
1818 
1819  // add downstream interfaces
1820  for (int i = 0; i < pimIft->getNumInterfaces(); i++) {
1821  PimInterface *pimInterface = pimIft->getInterface(i);
1822  if (pimInterface->getMode() == PimInterface::SparseMode && pimInterface->getInterfacePtr() != newRouteSG->upstreamInterface->ie) {
1823  DownstreamInterface *downstream = new DownstreamInterface(newRouteSG, pimInterface->getInterfacePtr(), DownstreamInterface::NO_INFO);
1824  newRouteSG->addDownstreamInterface(downstream);
1825  }
1826  }
1827 
1828  SourceAndGroup sg(source, group);
1829  sgRoutes[sg] = newRouteSG;
1830  rt->addMulticastRoute(createIpv4Route(newRouteSG));
1831 
1832  // set (*,G) route if exists
1833  newRouteSG->gRoute = findRouteG(group);
1834 
1835  // set (S,G,rpt) route if exists
1836  Route *sgrptRoute = nullptr; // TODO
1837  newRouteSG->sgrptRoute = sgrptRoute;
1838 
1839  // set (S,G) route in (S,G,rpt) route
1840  if (sgrptRoute) {
1841 // sgrptRoute->sgRoute = newRouteSG;
1842  }
1843 
1844  return newRouteSG;
1845 }

Referenced by processJoinSG(), processRegisterPacket(), and unroutableMulticastPacketArrived().

◆ cancelAndDeleteTimer()

void inet::PimSm::cancelAndDeleteTimer ( cMessage *&  timer)
private
1901 {
1902  cancelAndDelete(timer);
1903  timer = nullptr;
1904 }

Referenced by joinDesiredChanged(), processExpiryTimer(), processJoinG(), processJoinSG(), processPrunePendingTimer(), and processRegisterStopPacket().

◆ clearRoutes()

void inet::PimSm::clearRoutes ( )
private
1714 {
1715  // delete Ipv4 routes
1716  bool changed = true;
1717  while (changed) {
1718  changed = false;
1719  for (int i = 0; i < rt->getNumMulticastRoutes(); i++) {
1720  Ipv4MulticastRoute *ipv4Route = rt->getMulticastRoute(i);
1721  if (ipv4Route->getSource() == this) {
1722  rt->deleteMulticastRoute(ipv4Route);
1723  changed = true;
1724  break;
1725  }
1726  }
1727  }
1728 
1729  // clear local tables
1730  for (auto& elem : gRoutes)
1731  delete elem.second;
1732  gRoutes.clear();
1733 
1734  for (auto& elem : sgRoutes)
1735  delete elem.second;
1736  sgRoutes.clear();
1737 }

Referenced by stopPIMRouting().

◆ createIpv4Route()

Ipv4MulticastRoute * inet::PimSm::createIpv4Route ( Route route)
private
1848 {
1849  Ipv4MulticastRoute *newRoute = new Ipv4MulticastRoute();
1850  newRoute->setOrigin(route->source);
1851  newRoute->setOriginNetmask(route->source.isUnspecified() ? Ipv4Address::UNSPECIFIED_ADDRESS : Ipv4Address::ALLONES_ADDRESS);
1852  newRoute->setMulticastGroup(route->group);
1853  newRoute->setSourceType(IMulticastRoute::PIM_SM);
1854  newRoute->setSource(this);
1855  if (route->upstreamInterface)
1856  newRoute->setInInterface(new IMulticastRoute::InInterface(route->upstreamInterface->ie));
1857  unsigned int numOutInterfaces = route->downstreamInterfaces.size();
1858  for (unsigned int i = 0; i < numOutInterfaces; ++i) {
1859  DownstreamInterface *downstream = route->downstreamInterfaces[i];
1860  newRoute->addOutInterface(new PimSmOutInterface(downstream));
1861  }
1862  return newRoute;
1863 }

Referenced by addNewRouteG(), and addNewRouteSG().

◆ deleteMulticastRoute()

bool inet::PimSm::deleteMulticastRoute ( Route route)
private
1692 {
1693  if (removeRoute(route)) {
1694  // remove route from Ipv4 routing table
1695  Ipv4MulticastRoute *ipv4Route = findIpv4Route(route->source, route->group);
1696  if (ipv4Route)
1697  rt->deleteMulticastRoute(ipv4Route);
1698 
1699  // unlink
1700  if (route->type == G) {
1701  for (auto& elem : sgRoutes)
1702  if (elem.second->gRoute == route)
1703  elem.second->gRoute = nullptr;
1704 
1705  }
1706 
1707  delete route;
1708  return true;
1709  }
1710  return false;
1711 }

Referenced by processExpiryTimer(), and processKeepAliveTimer().

◆ designatedRouterAddressHasChanged()

void inet::PimSm::designatedRouterAddressHasChanged ( NetworkInterface ie)
private
1321 {
1322  // TODO
1323 }

Referenced by updateDesignatedRouterAddress().

◆ effectiveOverrideInterval()

double inet::PimSm::effectiveOverrideInterval ( )
inlineprivate
279 { return defaultOverrideInterval; }

◆ effectivePropagationDelay()

double inet::PimSm::effectivePropagationDelay ( )
inlineprivate
278 { return defaultPropagationDelay; }

◆ findIpv4Route()

Ipv4MulticastRoute * inet::PimSm::findIpv4Route ( Ipv4Address  source,
Ipv4Address  group 
)
private
1890 {
1891  unsigned int numMulticastRoutes = rt->getNumMulticastRoutes();
1892  for (unsigned int i = 0; i < numMulticastRoutes; ++i) {
1893  Ipv4MulticastRoute *ipv4Route = rt->getMulticastRoute(i);
1894  if (ipv4Route->getSource() == this && ipv4Route->getOrigin() == source && ipv4Route->getMulticastGroup() == group)
1895  return ipv4Route;
1896  }
1897  return nullptr;
1898 }

Referenced by deleteMulticastRoute().

◆ findRouteG()

PimSm::Route * inet::PimSm::findRouteG ( Ipv4Address  group)
private

◆ findRouteSG()

PimSm::Route * inet::PimSm::findRouteSG ( Ipv4Address  source,
Ipv4Address  group 
)
private
1882 {
1883  ASSERT(!source.isUnspecified());
1884  SourceAndGroup sg(source, group);
1885  auto it = sgRoutes.find(sg);
1886  return it != sgRoutes.end() ? it->second : nullptr;
1887 }

Referenced by multicastPacketForwarded(), processAssertPacket(), processJoinSG(), processPruneSG(), processRegisterPacket(), processRegisterStopPacket(), and receiveSignal().

◆ forwardMulticastData()

void inet::PimSm::forwardMulticastData ( Packet data,
int  outInterfaceId 
)
private

The method is used as abstraction for encapsulation multicast data to Register packet.

The method create message MultData with multicast source address and multicast group address and send the message from RP to RPT.

1538 {
1539  EV << "pimSM::forwardMulticastData" << endl;
1540 
1541  //
1542  // Note: we should inject the datagram somehow into the normal Ipv4 forwarding path.
1543  //
1544  const auto& ipv4Header = data->popAtFront<Ipv4Header>();
1545 
1546  // set control info
1547  data->addTagIfAbsent<PacketProtocolTag>()->setProtocol(ipv4Header->getProtocol());
1548  data->addTagIfAbsent<InterfaceReq>()->setInterfaceId(outInterfaceId);
1549  auto addrTag = data->addTagIfAbsent<L3AddressReq>();
1550  addrTag->setSrcAddress(ipv4Header->getSrcAddress());
1551  addrTag->setNonLocalSrcAddress(true);
1552  addrTag->setDestAddress(ipv4Header->getDestAddress());
1553  data->addTagIfAbsent<HopLimitReq>()->setHopLimit(MAX_TTL - 2); // one minus for source DR router and one for RP router // TODO specification???
1554  data->trim();
1555  send(data, "ipOut");
1556 }

Referenced by processRegisterPacket().

◆ getIncomingInterface()

PimInterface * inet::PimSm::getIncomingInterface ( NetworkInterface fromIE)
private
1685 {
1686  if (fromIE)
1687  return pimIft->getInterfaceById(fromIE->getInterfaceId());
1688  return nullptr;
1689 }

Referenced by receiveSignal().

◆ handleCrashOperation()

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

Reimplemented from inet::PimBase.

101 {
102  stopPIMRouting();
104 }

◆ handleMessageWhenUp()

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

Implements inet::OperationalMixin< cSimpleModule >.

127 {
128  if (msg->isSelfMessage()) {
129  switch (msg->getKind()) {
130  case HelloTimer:
131  processHelloTimer(msg);
132  break;
133 
134  case JoinTimer:
135  processJoinTimer(msg);
136  break;
137 
138  case PrunePendingTimer:
140  break;
141 
142  case ExpiryTimer:
143  processExpiryTimer(msg);
144  break;
145 
146  case KeepAliveTimer:
148  break;
149 
150  case RegisterStopTimer:
152  break;
153 
154  case AssertTimer:
155  processAssertTimer(msg);
156  break;
157 
158  default:
159  throw cRuntimeError("PimSm: unknown self message: %s (%s)", msg->getName(), msg->getClassName());
160  }
161  }
162  else {
163  Packet *pk = check_and_cast<Packet *>(msg);
164  const auto& pkt = pk->peekAtFront<PimPacket>();
165  if (pkt == nullptr)
166  throw cRuntimeError("PIM-SM: received unknown message: %s (%s).", msg->getName(), msg->getClassName());
167  if (!isEnabled) {
168  EV_DETAIL << "PIM-SM is disabled, dropping packet.\n";
169  delete msg;
170  return;
171  }
172 
173  switch (pkt->getType()) {
174  case Hello:
175  processHelloPacket(pk);
176  break;
177 
178  case JoinPrune:
180  break;
181 
182  case Register:
184  break;
185 
186  case RegisterStop:
188  break;
189 
190  case Assert:
192  break;
193 
194  case Graft:
195  EV_WARN << "Ignoring PIM-DM Graft packet.\n";
196  delete pk;
197  break;
198 
199  case GraftAck:
200  EV_WARN << "Ignoring PIM-DM GraftAck packet.\n";
201  delete pk;
202  break;
203 
204  case StateRefresh:
205  EV_WARN << "Ignoring PIM-DM StateRefresh packet.\n";
206  delete pk;
207  break;
208 
209  case Bootstrap:
210  delete pk;
211  break;
212 
214  delete pk;
215  break;
216 
217  default:
218  throw cRuntimeError("PimSm: received unknown PIM packet: %s (%s)", pk->getName(), pk->getClassName());
219  }
220  }
221 }

◆ handleStartOperation()

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

Reimplemented from inet::PimBase.

67 {
69 
70  if (isEnabled) {
71  if (rpAddr.isUnspecified())
72  throw cRuntimeError("PimSm: missing RP address parameter.");
73 
74  // subscribe for notifications
75  cModule *host = findContainingNode(this);
76  if (!host)
77  throw cRuntimeError("PimDm: containing node not found.");
78  host->subscribe(ipv4NewMulticastSignal, this);
79  host->subscribe(ipv4MdataRegisterSignal, this);
80  host->subscribe(ipv4DataOnRpfSignal, this);
81  host->subscribe(ipv4DataOnNonrpfSignal, this);
82  host->subscribe(ipv4MulticastGroupRegisteredSignal, this);
83  host->subscribe(ipv4MulticastGroupUnregisteredSignal, this);
84  host->subscribe(pimNeighborAddedSignal, this);
85  host->subscribe(pimNeighborDeletedSignal, this);
86  host->subscribe(pimNeighborChangedSignal, this);
87 
88  WATCH_PTRMAP(gRoutes);
89  WATCH_PTRMAP(sgRoutes);
90  }
91 }

◆ handleStopOperation()

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

Reimplemented from inet::PimBase.

94 {
95  // TODO send PIM Hellos to neighbors with 0 HoldTime
98 }

◆ IamDR()

bool inet::PimSm::IamDR ( NetworkInterface ie)
private
1677 {
1678  PimInterface *pimInterface = pimIft->getInterfaceById(ie->getInterfaceId());
1679  ASSERT(pimInterface);
1680  Ipv4Address drAddress = pimInterface->getDRAddress();
1681  return drAddress.isUnspecified() || drAddress == ie->getProtocolData<Ipv4InterfaceData>()->getIPAddress();
1682 }

◆ iAmDRHasChanged()

void inet::PimSm::iAmDRHasChanged ( NetworkInterface ie,
bool  iAmDR 
)
private
1326 {
1327  // TODO
1328 }

Referenced by updateDesignatedRouterAddress().

◆ IamRP()

bool inet::PimSm::IamRP ( Ipv4Address  rpAddr)
inlineprivate
289 { return rt->isLocalAddress(rpAddr); }

Referenced by addNewRouteG(), and processExpiryTimer().

◆ initialize()

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

Reimplemented from inet::PimBase.

46 {
47  PimBase::initialize(stage);
48 
49  if (stage == INITSTAGE_LOCAL) {
50  const char *rp = par("RP");
51  if (rp && *rp)
52  rpAddr = Ipv4Address(rp);
53 
54  joinPrunePeriod = par("joinPrunePeriod");
55  defaultOverrideInterval = par("defaultOverrideInterval");
56  defaultPropagationDelay = par("defaultPropagationDelay");
57  keepAlivePeriod = par("keepAlivePeriod");
58  rpKeepAlivePeriod = par("rpKeepAlivePeriod");
59  registerSuppressionTime = par("registerSuppressionTime");
60  registerProbeTime = par("registerProbeTime");
61  assertTime = par("assertTime");
62  assertOverrideInterval = par("assertOverrideInterval");
63  }
64 }

◆ joinDesiredChanged()

void inet::PimSm::joinDesiredChanged ( Route route)
private
1265 {
1266  if (route->type == G) {
1267  Route *routeG = route;
1268 
1269  if (routeG->isFlagSet(Route::PRUNED) && routeG->joinDesired()) {
1270  //
1271  // Upstream (*,G) State Machine; event: JoinDesired(S,G) -> TRUE
1272  //
1273  routeG->clearFlag(Route::PRUNED);
1274  if (routeG->upstreamInterface) {
1275  sendPIMJoin(routeG->group, routeG->rpAddr, routeG->upstreamInterface->rpfNeighbor(), G);
1276  routeG->startJoinTimer(joinPrunePeriod);
1277  }
1278  }
1279  else if (!routeG->isFlagSet(Route::PRUNED) && !routeG->joinDesired()) {
1280  //
1281  // Upstream (*,G) State Machine; event: JoinDesired(S,G) -> FALSE
1282  //
1283  routeG->setFlags(Route::PRUNED);
1284  cancelAndDeleteTimer(routeG->joinTimer);
1285  if (routeG->upstreamInterface)
1286  sendPIMPrune(routeG->group, routeG->rpAddr, routeG->upstreamInterface->rpfNeighbor(), G);
1287  }
1288  }
1289  else if (route->type == SG) {
1290  Route *routeSG = route;
1291 
1292  if (routeSG->isFlagSet(Route::PRUNED) && routeSG->joinDesired()) {
1293  //
1294  // Upstream (S,G) State Machine; event: JoinDesired(S,G) -> TRUE
1295  //
1296  routeSG->clearFlag(Route::PRUNED);
1297  if (!routeSG->isSourceDirectlyConnected()) {
1298  sendPIMJoin(routeSG->group, routeSG->source, routeSG->upstreamInterface->rpfNeighbor(), SG);
1299  routeSG->startJoinTimer(joinPrunePeriod);
1300  }
1301  }
1302  else if (!routeSG->isFlagSet(Route::PRUNED) && !route->joinDesired()) {
1303  //
1304  // Upstream (S,G) State Machine; event: JoinDesired(S,G) -> FALSE
1305  //
1306 
1307  // The upstream (S,G) state machine transitions to NotJoined
1308  // state. Send Prune(S,G) to the appropriate upstream neighbor,
1309  // which is RPF'(S,G). Cancel the Join Timer (JT), and set
1310  // SPTbit(S,G) to FALSE.
1311  routeSG->setFlags(Route::PRUNED);
1312  routeSG->clearFlag(Route::SPT_BIT);
1313  cancelAndDeleteTimer(routeSG->joinTimer);
1314  if (!routeSG->isSourceDirectlyConnected())
1315  sendPIMPrune(routeSG->group, routeSG->source, routeSG->upstreamInterface->rpfNeighbor(), SG);
1316  }
1317  }
1318 }

Referenced by updateJoinDesired().

◆ joinPruneHoldTime()

double inet::PimSm::joinPruneHoldTime ( )
inlineprivate
277 { return 3.5 * joinPrunePeriod; } // Holdtime in Join/Prune messages

Referenced by sendPIMJoin(), and sendPIMPrune().

◆ joinPruneOverrideInterval()

double inet::PimSm::joinPruneOverrideInterval ( )
inlineprivate

◆ multicastPacketArrivedOnNonRpfInterface()

void inet::PimSm::multicastPacketArrivedOnNonRpfInterface ( Route route,
int  interfaceId 
)
private
1201 {
1202  if (route->type == G || route->type == SG) {
1203  //
1204  // (S,G) Assert State Machine; event: An (S,G) data packet arrives on interface I
1205  // OR
1206  // (*,G) Assert State Machine; event: A data packet destined for G arrives on interface I
1207  //
1208  DownstreamInterface *downstream = route->findDownstreamInterfaceByInterfaceId(interfaceId);
1209  if (downstream && downstream->couldAssert() && downstream->assertState == Interface::NO_ASSERT_INFO) {
1210  // An (S,G) data packet arrived on an downstream interface that
1211  // is in our (S,G) or (*,G) outgoing interface list. We optimistically
1212  // assume that we will be the assert winner for this (S,G) or (*,G), and
1213  // so we transition to the "I am Assert Winner" state and perform
1214  // Actions A1 (below), which will initiate the assert negotiation
1215  // for (S,G) or (*,G).
1216  downstream->assertState = Interface::I_WON_ASSERT;
1217  downstream->winnerMetric = route->metric.setAddress(downstream->ie->getProtocolData<Ipv4InterfaceData>()->getIPAddress());
1218  sendPIMAssert(route->source, route->group, downstream->winnerMetric, downstream->ie, route->type == G);
1219  downstream->startAssertTimer(assertTime - assertOverrideInterval);
1220  }
1221  else if (route->type == SG && (!downstream || downstream->assertState == Interface::NO_ASSERT_INFO)) {
1222  // When in NO_ASSERT_INFO state before and after consideration of the received message,
1223  // then call (*,G) assert processing.
1224  Route *routeG = findRouteG(route->group);
1225  if (routeG)
1226  multicastPacketArrivedOnNonRpfInterface(routeG, interfaceId);
1227  }
1228  }
1229 }

Referenced by receiveSignal().

◆ multicastPacketArrivedOnRpfInterface()

void inet::PimSm::multicastPacketArrivedOnRpfInterface ( Route route)
private

The method process notification about data which appears on RPF interface.

It means that source is still active. The result is resetting of Keep Alive Timer. Also if first data packet arrive to last hop router in RPT, switchover to SPT has to be considered.

1150 {
1151  if (route->type == SG) { // (S,G) route
1152  // set KeepAlive timer
1153  if ( /*DirectlyConnected(route->source) ||*/
1154  (!route->isFlagSet(Route::PRUNED) && !route->isInheritedOlistNull()))
1155  {
1156  EV_DETAIL << "Data arrived on RPF interface, restarting KAT(" << route->source << ", " << route->group << ") timer.\n";
1157 
1158  if (!route->keepAliveTimer)
1159  route->startKeepAliveTimer(keepAlivePeriod);
1160  else
1161  restartTimer(route->keepAliveTimer, keepAlivePeriod);
1162  }
1163 
1164  // Update SPT bit
1165 
1166  /* TODO
1167  void
1168  Update_SPTbit(S,G,iif) {
1169  if ( iif == RPF_interface(S)
1170  AND JoinDesired(S,G) == TRUE
1171  AND ( DirectlyConnected(S) == TRUE
1172  OR RPF_interface(S) != RPF_interface(RP(G))
1173  OR inherited_olist(S,G,rpt) == nullptr
1174  OR ( ( RPF'(S,G) == RPF'(*,G) ) AND
1175  ( RPF'(S,G) != nullptr ) )
1176  OR ( I_Am_Assert_Loser(S,G,iif) ) {
1177  Set SPTbit(S,G) to TRUE
1178  }
1179  }
1180  */
1181  route->setFlags(Route::SPT_BIT);
1182  }
1183 
1184  // check switch from RP tree to the SPT
1185  if (route->isFlagSet(Route::SPT_BIT)) {
1186  /*
1187  void
1188  CheckSwitchToSpt(S,G) {
1189  if ( ( pim_include(*,G) (-) pim_exclude(S,G)
1190  (+) pim_include(S,G) != nullptr )
1191  AND SwitchToSptDesired(S,G) ) {
1192  # Note: Restarting the KAT will result in the SPT switch
1193  set KeepaliveTimer(S,G) to Keepalive_Period
1194  }
1195  }
1196  */
1197  }
1198 }

Referenced by receiveSignal().

◆ multicastPacketForwarded()

void inet::PimSm::multicastPacketForwarded ( Packet pk)
private
1232 {
1233  const auto& ipv4Header = pk->peekAtFront<Ipv4Header>();
1234  Ipv4Address source = ipv4Header->getSrcAddress();
1235  Ipv4Address group = ipv4Header->getDestAddress();
1236 
1237  Route *routeSG = findRouteSG(source, group);
1238  if (!routeSG || !routeSG->isFlagSet(Route::REGISTER) || !routeSG->isFlagSet(Route::PRUNED))
1239  return;
1240 
1241  // send Register message to RP
1242 
1243  if (routeSG->registerState == Route::RS_JOIN) {
1244  // refresh KAT timer
1245  if (routeSG->keepAliveTimer) {
1246  EV << " (S,G) KAT timer refresh" << endl;
1247  restartTimer(routeSG->keepAliveTimer, KAT);
1248  }
1249 
1250  NetworkInterface *interfaceTowardRP = rt->getInterfaceForDestAddr(routeSG->rpAddr);
1251  ASSERT(interfaceTowardRP != nullptr);
1252  sendPIMRegister(pk, routeSG->rpAddr, interfaceTowardRP->getInterfaceId());
1253  }
1254 }

Referenced by receiveSignal().

◆ multicastReceiverAdded()

void inet::PimSm::multicastReceiverAdded ( NetworkInterface ie,
Ipv4Address  group 
)
private
1131 {
1132  EV_DETAIL << "Multicast receiver added for group " << group << " on interface '" << ie->getInterfaceName() << "'.\n";
1133 
1134  Route *routeG = findRouteG(group);
1135  if (!routeG)
1136  routeG = addNewRouteG(group, Route::PRUNED);
1137 
1138  DownstreamInterface *downstream = routeG->getDownstreamInterfaceByInterfaceId(ie->getInterfaceId());
1139  downstream->setLocalReceiverInclude(true);
1140 
1141  updateJoinDesired(routeG);
1142 }

Referenced by receiveSignal().

◆ multicastReceiverRemoved()

void inet::PimSm::multicastReceiverRemoved ( NetworkInterface ie,
Ipv4Address  group 
)
private
1119 {
1120  EV_DETAIL << "No more receiver for group " << group << " on interface '" << ie->getInterfaceName() << "'.\n";
1121 
1122  Route *routeG = findRouteG(group);
1123  if (routeG) {
1124  DownstreamInterface *downstream = routeG->getDownstreamInterfaceByInterfaceId(ie->getInterfaceId());
1125  downstream->setLocalReceiverInclude(false);
1126  updateJoinDesired(routeG);
1127  }
1128 }

Referenced by receiveSignal().

◆ numInitStages()

virtual int inet::PimSm::numInitStages ( ) const
inlineoverrideprotectedvirtual

Reimplemented from inet::PimBase.

220 { return NUM_INIT_STAGES; }

◆ processAssertG()

void inet::PimSm::processAssertG ( PimsmInterface interface,
const AssertMetric receivedMetric 
)
private
783 {
784  Route *routeG = interface->route();
785  AssertMetric myMetric = interface->couldAssert() ?
786  routeG->metric.setAddress(interface->ie->getProtocolData<Ipv4InterfaceData>()->getIPAddress()) :
788 
789  // A "preferred assert" is one with a better metric than the current winner.
790  bool isPreferredAssert = receivedMetric < interface->winnerMetric;
791 
792  // An "acceptable assert" is one that has a better metric than my_assert_metric(S,G,I).
793  // An assert is never considered acceptable if its metric is infinite.
794  bool isAcceptableAssert = receivedMetric < myMetric;
795 
796  // An "inferior assert" is one with a worse metric than my_assert_metric(S,G,I).
797  // An assert is never considered inferior if my_assert_metric(S,G,I) is infinite.
798  bool isInferiorAssert = myMetric < receivedMetric;
799 
800  if (interface->assertState == Interface::NO_ASSERT_INFO) {
801  if (isInferiorAssert && receivedMetric.rptBit && interface->couldAssert()) {
802  // An Inferior (*,G) assert is received for G on Interface I. If
803  // CouldAssert(*,G,I) is TRUE, then I is our downstream
804  // interface, and we have (*,G) forwarding state on this
805  // interface, so we should be the assert winner. We transition
806  // to the "I am Assert Winner" state and perform Actions:
807  interface->assertState = Interface::I_WON_ASSERT;
808  sendPIMAssert(Ipv4Address::UNSPECIFIED_ADDRESS, routeG->group, myMetric, interface->ie, true);
809  interface->startAssertTimer(assertTime - assertOverrideInterval);
810  interface->winnerMetric = myMetric;
811  }
812  else if (isAcceptableAssert && receivedMetric.rptBit && interface->assertTrackingDesired()) {
813  // We're interested in (*,G) Asserts, either because I is a
814  // downstream interface for which we have (*,G) forwarding state,
815  // or because I is the upstream interface for RP(G) and we have
816  // (*,G) forwarding state. We get a (*,G) Assert that has a
817  // better metric than our own, so we do not win the Assert. We
818  // transition to "I am Assert Loser" and perform Actions:
819  interface->assertState = Interface::I_LOST_ASSERT;
820  interface->winnerMetric = receivedMetric;
821  interface->startAssertTimer(assertTime);
822  }
823  }
824  else if (interface->assertState == Interface::I_WON_ASSERT) {
825  if (isInferiorAssert) {
826  // We receive a (*,G) assert that has a worse metric than our
827  // own. Whoever sent the assert has lost, and so we resend a
828  // (*,G) Assert and restart the Assert Timer (Actions A3 below).
829  sendPIMAssert(Ipv4Address::UNSPECIFIED_ADDRESS, routeG->group, myMetric, interface->ie, true);
830  restartTimer(interface->assertTimer, assertTime - assertOverrideInterval);
831  }
832  else if (isPreferredAssert) {
833  // We receive a (*,G) assert that has a better metric than our
834  // own. We transition to "I am Assert Loser" state and perform
835  // Actions A2 (below).
836  interface->assertState = Interface::I_LOST_ASSERT;
837  interface->winnerMetric = receivedMetric;
838  restartTimer(interface->assertTimer, assertTime);
839  }
840  }
841  else if (interface->assertState == Interface::I_LOST_ASSERT) {
842  if (isPreferredAssert && receivedMetric.rptBit) {
843  // We receive a (*,G) assert that is better than that of the
844  // current assert winner. We stay in Loser state and perform
845  // Actions A2 below.
846  interface->winnerMetric = receivedMetric;
847  restartTimer(interface->assertTimer, assertTime);
848  }
849  else if (isAcceptableAssert && receivedMetric.address == interface->winnerMetric.address && receivedMetric.rptBit) {
850  // We receive a (*,G) assert from the current assert winner that
851  // is better than our own metric for this group (although the
852  // metric may be worse than the winner's previous metric). We
853  // stay in Loser state and perform Actions A2 below.
854  // interface->winnerAddress = ...;
855  interface->winnerMetric = receivedMetric;
856  restartTimer(interface->assertTimer, assertTime);
857  }
858  else if (isInferiorAssert /*or AssertCancel*/ && receivedMetric.address == interface->winnerMetric.address) {
859  // We receive an assert from the current assert winner that is
860  // worse than our own metric for this group (typically because
861  // the winner's metric became worse or is now an assert cancel).
862  // We transition to NoInfo state, delete this (*,G) assert state
863  // (Actions A5), and allow the normal PIM Join/Prune mechanisms
864  // to operate. Usually, we will eventually re-assert and win
865  // when data packets for G have started flowing again.
866  interface->deleteAssertInfo();
867  }
868  }
869 }

Referenced by processAssertPacket().

◆ processAssertPacket()

void inet::PimSm::processAssertPacket ( Packet pk)
private
630 {
631  const auto& pkt = pk->peekAtFront<PimAssert>();
632  int incomingInterfaceId = pk->getTag<InterfaceInd>()->getInterfaceId();
633  Ipv4Address source = pkt->getSourceAddress().unicastAddress.toIpv4();
634  Ipv4Address group = pkt->getGroupAddress().groupAddress.toIpv4();
635  AssertMetric receivedMetric = AssertMetric(pkt->getR(), pkt->getMetricPreference(), pkt->getMetric(), pk->getTag<L3AddressInd>()->getSrcAddress().toIpv4());
636 
637  EV_INFO << "Received Assert(" << (source.isUnspecified() ? "*" : source.str()) << ", " << group << ")"
638  << " packet on interface '" << ift->getInterfaceById(incomingInterfaceId)->getInterfaceName() << "'.\n";
639 
640  emit(rcvdAssertPkSignal, pk);
641 
642  if (!source.isUnspecified() && !receivedMetric.rptBit) {
643  Route *routeSG = findRouteSG(source, group);
644  if (routeSG) {
645  PimsmInterface *incomingInterface = routeSG->upstreamInterface->getInterfaceId() == incomingInterfaceId ?
646  static_cast<PimsmInterface *>(routeSG->upstreamInterface) :
647  static_cast<PimsmInterface *>(routeSG->getDownstreamInterfaceByInterfaceId(incomingInterfaceId));
648  ASSERT(incomingInterface);
649 
650  Interface::AssertState stateBefore = incomingInterface->assertState;
651  processAssertSG(incomingInterface, receivedMetric);
652 
653  if (stateBefore != Interface::NO_ASSERT_INFO || incomingInterface->assertState != Interface::NO_ASSERT_INFO) {
654  // processed by SG
655  delete pk;
656  return;
657  }
658  }
659  }
660 
661  // process (*,G) asserts and (S,G) asserts for which there is no assert state in (S,G) routes
662  Route *routeG = findRouteG(group);
663  if (routeG) {
664  PimsmInterface *incomingInterface = routeG->upstreamInterface->getInterfaceId() == incomingInterfaceId ?
665  static_cast<PimsmInterface *>(routeG->upstreamInterface) :
666  static_cast<PimsmInterface *>(routeG->getDownstreamInterfaceByInterfaceId(incomingInterfaceId));
667  ASSERT(incomingInterface);
668  processAssertG(incomingInterface, receivedMetric);
669  }
670 
671  delete pk;
672 }

Referenced by handleMessageWhenUp().

◆ processAssertSG()

void inet::PimSm::processAssertSG ( PimsmInterface interface,
const AssertMetric receivedMetric 
)
private
675 {
676  Route *routeSG = interface->route();
677  AssertMetric myMetric = interface->couldAssert() ? // TODO check routeG metric too
678  routeSG->metric.setAddress(interface->ie->getProtocolData<Ipv4InterfaceData>()->getIPAddress()) :
680 
681  // A "preferred assert" is one with a better metric than the current winner.
682  bool isPreferredAssert = receivedMetric < interface->winnerMetric;
683 
684  // An "acceptable assert" is one that has a better metric than my_assert_metric(S,G,I).
685  // An assert is never considered acceptable if its metric is infinite.
686  bool isAcceptableAssert = receivedMetric < myMetric;
687 
688  // An "inferior assert" is one with a worse metric than my_assert_metric(S,G,I).
689  // An assert is never considered inferior if my_assert_metric(S,G,I) is infinite.
690  bool isInferiorAssert = myMetric < receivedMetric;
691 
692  if (interface->assertState == Interface::NO_ASSERT_INFO) {
693  if (isInferiorAssert && !receivedMetric.rptBit && interface->couldAssert()) {
694  // An assert is received for (S,G) with the RPT bit cleared that
695  // is inferior to our own assert metric. The RPT bit cleared
696  // indicates that the sender of the assert had (S,G) forwarding
697  // state on this interface. If the assert is inferior to our
698  // metric, then we must also have (S,G) forwarding state (i.e.,
699  // CouldAssert(S,G,I)==TRUE) as (S,G) asserts beat (*,G) asserts,
700  // and so we should be the assert winner. We transition to the
701  // "I am Assert Winner" state and perform Actions A1 (below).
702  interface->assertState = Interface::I_WON_ASSERT;
703  interface->winnerMetric = myMetric;
704  sendPIMAssert(routeSG->source, routeSG->group, myMetric, interface->ie, false);
705  interface->startAssertTimer(assertTime - assertOverrideInterval);
706  }
707  else if (receivedMetric.rptBit && interface->couldAssert()) {
708  // An assert is received for (S,G) on I with the RPT bit set
709  // (it's a (*,G) assert). CouldAssert(S,G,I) is TRUE only if we
710  // have (S,G) forwarding state on this interface, so we should be
711  // the assert winner. We transition to the "I am Assert Winner"
712  // state and perform Actions A1 (below).
713  interface->assertState = Interface::I_WON_ASSERT;
714  interface->winnerMetric = myMetric;
715  sendPIMAssert(routeSG->source, routeSG->group, myMetric, interface->ie, false);
716  interface->startAssertTimer(assertTime - assertOverrideInterval);
717  }
718  else if (isAcceptableAssert && !receivedMetric.rptBit && interface->assertTrackingDesired()) {
719  // We're interested in (S,G) Asserts, either because I is a
720  // downstream interface for which we have (S,G) or (*,G)
721  // forwarding state, or because I is the upstream interface for S
722  // and we have (S,G) forwarding state. The received assert has a
723  // better metric than our own, so we do not win the Assert. We
724  // transition to "I am Assert Loser" and perform Actions A6
725  // (below).
726  interface->assertState = Interface::I_LOST_ASSERT;
727  interface->winnerMetric = receivedMetric;
728  interface->startAssertTimer(assertTime);
729  // TODO If (I is RPF_interface(S)) AND (UpstreamJPState(S,G) == true)
730  // set SPTbit(S,G) to TRUE.
731  }
732  }
733  else if (interface->assertState == Interface::I_WON_ASSERT) {
734  if (isInferiorAssert) {
735  // We receive an (S,G) assert or (*,G) assert mentioning S that
736  // has a worse metric than our own. Whoever sent the assert is
737  // in error, and so we resend an (S,G) Assert and restart the
738  // Assert Timer (Actions A3 below).
739  sendPIMAssert(routeSG->source, routeSG->group, myMetric, interface->ie, false);
740  restartTimer(interface->assertTimer, assertTime - assertOverrideInterval);
741  }
742  else if (isPreferredAssert) {
743  // We receive an (S,G) assert that has a better metric than our
744  // own. We transition to "I am Assert Loser" state and perform
745  // Actions A2 (below). Note that this may affect the value of
746  // JoinDesired(S,G) and PruneDesired(S,G,rpt), which could cause
747  // transitions in the upstream (S,G) or (S,G,rpt) state machines.
748  interface->assertState = Interface::I_LOST_ASSERT;
749  interface->winnerMetric = receivedMetric;
750  restartTimer(interface->assertTimer, assertTime);
751  }
752  }
753  else if (interface->assertState == Interface::I_LOST_ASSERT) {
754  if (isPreferredAssert) {
755  // We receive an assert that is better than that of the current
756  // assert winner. We stay in Loser state and perform Actions A2
757  // below.
758  interface->winnerMetric = receivedMetric;
759  restartTimer(interface->assertTimer, assertTime);
760  }
761  else if (isAcceptableAssert && !receivedMetric.rptBit && receivedMetric.address == interface->winnerMetric.address) {
762  // We receive an assert from the current assert winner that is
763  // better than our own metric for this (S,G) (although the metric
764  // may be worse than the winner's previous metric). We stay in
765  // Loser state and perform Actions A2 below.
766  interface->winnerMetric = receivedMetric;
767  restartTimer(interface->assertTimer, assertTime);
768  }
769  else if (isInferiorAssert /* or AssertCancel */ && receivedMetric.address == interface->winnerMetric.address) {
770  // We receive an assert from the current assert winner that is
771  // worse than our own metric for this group (typically, because
772  // the winner's metric became worse or because it is an assert
773  // cancel). We transition to NoInfo state, deleting the (S,G)
774  // assert information and allowing the normal PIM Join/Prune
775  // mechanisms to operate. Usually, we will eventually re-assert
776  // and win when data packets from S have started flowing again.
777  interface->deleteAssertInfo();
778  }
779  }
780 }

Referenced by processAssertPacket().

◆ processAssertTimer()

void inet::PimSm::processAssertTimer ( cMessage *  timer)
private
1023 {
1024  PimsmInterface *interfaceData = static_cast<PimsmInterface *>(timer->getContextPointer());
1025  ASSERT(timer == interfaceData->assertTimer);
1026  ASSERT(interfaceData->assertState != Interface::NO_ASSERT_INFO);
1027 
1028  Route *route = interfaceData->route();
1029  if (route->type == SG || route->type == G) {
1030  //
1031  // (S,G) Assert State Machine; event: AT(S,G,I) expires OR
1032  // (*,G) Assert State Machine; event: AT(*,G,I) expires
1033  //
1034  EV_DETAIL << "AssertTimer(" << (route->type == G ? "*" : route->source.str()) << ", "
1035  << route->group << ", " << interfaceData->ie->getInterfaceName() << ") has expired.\n";
1036 
1037  if (interfaceData->assertState == Interface::I_WON_ASSERT) {
1038  // The (S,G) or (*,G) Assert Timer expires. As we're in the Winner state,
1039  // we must still have (S,G) or (*,G) forwarding state that is actively
1040  // being kept alive. We resend the (S,G) or (*,G) Assert and restart the
1041  // Assert Timer. Note that the assert
1042  // winner's Assert Timer is engineered to expire shortly before
1043  // timers on assert losers; this prevents unnecessary thrashing
1044  // of the forwarder and periodic flooding of duplicate packets.
1045  sendPIMAssert(route->source, route->group, route->metric, interfaceData->ie, route->type == G);
1046  restartTimer(interfaceData->assertTimer, assertTime - assertOverrideInterval);
1047  return;
1048  }
1049  else if (interfaceData->assertState == Interface::I_LOST_ASSERT) {
1050  // The (S,G) or (*,G) Assert Timer expires. We transition to NoInfo
1051  // state, deleting the (S,G) or (*,G) assert information.
1052  EV_DEBUG << "Going into NO_ASSERT_INFO state.\n";
1053  interfaceData->deleteAssertInfo(); // deleted timer
1054  return;
1055  }
1056  }
1057 
1058  delete timer;
1059 }

Referenced by handleMessageWhenUp().

◆ processExpiryTimer()

void inet::PimSm::processExpiryTimer ( cMessage *  timer)
private

The method is used to process PIM Expiry Timer.

It is timer for (S,G) and (*,G). When Expiry timer expires,route is removed from multicast routing table.

912 {
913  EV << "pimSM::processExpiryTimer: " << endl;
914 
915  PimsmInterface *interface = static_cast<PimsmInterface *>(timer->getContextPointer());
916  Route *route = interface->route();
917 
918  if (interface != route->upstreamInterface) {
919  //
920  // Downstream Join/Prune State Machine; event: ET expires
921  //
922  DownstreamInterface *downstream = check_and_cast<DownstreamInterface *>(interface);
923  downstream->joinPruneState = DownstreamInterface::NO_INFO;
924  cancelAndDeleteTimer(downstream->prunePendingTimer);
925  downstream->expiryTimer = nullptr;
926  delete timer;
927 
928  // upstream state machine
929  if (route->isInheritedOlistNull()) {
930  route->setFlags(Route::PRUNED);
931  if (route->type == G && !IamRP(route->rpAddr))
932  sendPIMPrune(route->group, route->rpAddr, route->upstreamInterface->rpfNeighbor(), G);
933  else if (route->type == SG)
934  sendPIMPrune(route->group, route->source, route->upstreamInterface->rpfNeighbor(), SG);
935 
936  cancelAndDeleteTimer(route->joinTimer);
937  }
938  }
939  if (route->upstreamInterface->expiryTimer && interface == route->upstreamInterface) {
940  for (unsigned i = 0; i < route->downstreamInterfaces.size();) {
941  if (route->downstreamInterfaces[i]->expiryTimer)
942  route->removeDownstreamInterface(i);
943  else
944  i++;
945  }
946  if (IamRP(rpAddr) && route->type == G) {
947  EV << "ET for (*,G) route on RP expires - go to stopped" << endl;
948  cancelAndDeleteTimer(route->upstreamInterface->expiryTimer);
949  }
950  else
951  deleteMulticastRoute(route);
952  }
953 }

Referenced by handleMessageWhenUp().

◆ processJoinG()

void inet::PimSm::processJoinG ( Ipv4Address  group,
Ipv4Address  rp,
Ipv4Address  upstreamNeighborField,
int  holdTime,
NetworkInterface inInterface 
)
private
339 {
340  EV_DETAIL << "Processing Join(*," << group << ") received on interface '" << inInterface->getInterfaceName() << "'.\n";
341 
342  // TODO RP check
343 
344  //
345  // Downstream per-interface (*,G) state machine; event = Receive Join(*,G)
346  //
347 
348  // check UpstreamNeighbor field
349  if (upstreamNeighborField != inInterface->getProtocolData<Ipv4InterfaceData>()->getIPAddress())
350  return;
351 
352  bool newRoute = false;
353  Route *routeG = findRouteG(group);
354  if (!routeG) {
355  routeG = addNewRouteG(group, Route::PRUNED);
356  newRoute = true;
357  }
358 
359  DownstreamInterface *downstream = routeG->findDownstreamInterfaceByInterfaceId(inInterface->getInterfaceId());
360 
361  if (downstream) {
362  // A Join(*,G) is received on interface I with its Upstream
363  // Neighbor Address set to the router's primary IP address on I.
364  if (downstream->joinPruneState == DownstreamInterface::NO_INFO) {
365  // The (*,G) downstream state machine on interface I transitions
366  // to the Join state. The Expiry Timer (ET) is started and set
367  // to the HoldTime from the triggering Join/Prune message.
368  downstream->joinPruneState = DownstreamInterface::JOIN;
369  downstream->startExpiryTimer(holdTime);
370  }
371  else if (downstream->joinPruneState == DownstreamInterface::JOIN) {
372  // The (*,G) downstream state machine on interface I remains in
373  // Join state, and the Expiry Timer (ET) is restarted, set to
374  // maximum of its current value and the HoldTime from the
375  // triggering Join/Prune message.
376  if (simTime() + holdTime > downstream->expiryTimer->getArrivalTime())
377  restartTimer(downstream->expiryTimer, holdTime);
378  }
379  else if (downstream->joinPruneState == DownstreamInterface::PRUNE_PENDING) {
380  // The (*,G) downstream state machine on interface I transitions
381  // to the Join state. The Prune-Pending Timer is canceled
382  // (without triggering an expiry event). The Expiry Timer is
383  // restarted, set to maximum of its current value and the
384  // HoldTime from the triggering Join/Prune message.
385  cancelAndDeleteTimer(downstream->prunePendingTimer);
386  if (simTime() + holdTime > downstream->expiryTimer->getArrivalTime())
387  restartTimer(downstream->expiryTimer, holdTime);
388  }
389  }
390 
391  // TODO Join(*,G) messages can affect (S,G,rpt) downstream state machines too
392 
393  // check upstream state transition
394  updateJoinDesired(routeG);
395 
396  if (!newRoute && !routeG->upstreamInterface) { // I am RP
397  routeG->clearFlag(Route::REGISTER);
398  }
399 }

Referenced by processJoinPrunePacket().

◆ processJoinPrunePacket()

void inet::PimSm::processJoinPrunePacket ( Packet pk)
private
293 {
294  const auto& pkt = pk->peekAtFront<PimJoinPrune>();
295  EV_INFO << "Received JoinPrune packet.\n";
296 
297  emit(rcvdJoinPrunePkSignal, pk);
298 
299  NetworkInterface *inInterface = ift->getInterfaceById(pk->getTag<InterfaceInd>()->getInterfaceId());
300 
301  int holdTime = pkt->getHoldTime();
302  Ipv4Address upstreamNeighbor = pkt->getUpstreamNeighborAddress().unicastAddress.toIpv4();
303 
304  for (unsigned int i = 0; i < pkt->getJoinPruneGroupsArraySize(); i++) {
305  JoinPruneGroup group = pkt->getJoinPruneGroups(i);
306  Ipv4Address groupAddr = group.getGroupAddress().groupAddress.toIpv4();
307 
308  // go through list of joined sources
309  for (unsigned int j = 0; j < group.getJoinedSourceAddressArraySize(); j++) {
310  const auto& source = group.getJoinedSourceAddress(j);
311  if (source.S) {
312  if (source.W) // (*,G) Join
313  processJoinG(groupAddr, source.sourceAddress.toIpv4(), upstreamNeighbor, holdTime, inInterface);
314  else if (source.R) // (S,G,rpt) Join
315  processJoinSGrpt(source.sourceAddress.toIpv4(), groupAddr, upstreamNeighbor, holdTime, inInterface);
316  else // (S,G) Join
317  processJoinSG(source.sourceAddress.toIpv4(), groupAddr, upstreamNeighbor, holdTime, inInterface);
318  }
319  }
320 
321  // go through list of pruned sources
322  for (unsigned int j = 0; j < group.getPrunedSourceAddressArraySize(); j++) {
323  const auto& source = group.getPrunedSourceAddress(j);
324  if (source.S) {
325  if (source.W) // (*,G) Prune
326  processPruneG(groupAddr, upstreamNeighbor, inInterface);
327  else if (source.R) // (S,G,rpt) Prune
328  processPruneSGrpt(source.sourceAddress.toIpv4(), groupAddr, upstreamNeighbor, inInterface);
329  else // (S,G) Prune
330  processPruneSG(source.sourceAddress.toIpv4(), groupAddr, upstreamNeighbor, inInterface);
331  }
332  }
333  }
334 
335  delete pk;
336 }

Referenced by handleMessageWhenUp().

◆ processJoinSG()

void inet::PimSm::processJoinSG ( Ipv4Address  origin,
Ipv4Address  group,
Ipv4Address  upstreamNeighborField,
int  holdTime,
NetworkInterface inInterface 
)
private
402 {
403  EV_DETAIL << "Processing Join(" << source << ", " << group << ") received on interface '" << inInterface->getInterfaceName() << "'.'n";
404 
405  //
406  // Downstream per-interface (S,G) state machine; event = Receive Join(S,G)
407  //
408 
409  // check UpstreamNeighbor field
410  if (upstreamNeighborField != inInterface->getProtocolData<Ipv4InterfaceData>()->getIPAddress())
411  return;
412 
413  Route *routeSG = findRouteSG(source, group);
414  if (!routeSG) { // create (S,G) route between RP and source DR
415  routeSG = addNewRouteSG(source, group, Route::PRUNED);
416  routeSG->startKeepAliveTimer(keepAlivePeriod);
417  }
418 
419  DownstreamInterface *downstream = routeSG->findDownstreamInterfaceByInterfaceId(inInterface->getInterfaceId());
420 
421  if (downstream) {
422  // A Join(S,G) is received on interface I with its Upstream
423  // Neighbor Address set to the router's primary IP address on I.
424  if (downstream->joinPruneState == DownstreamInterface::NO_INFO) {
425  // The (S,G) downstream state machine on interface I transitions
426  // to the Join state. The Expiry Timer (ET) is started and set
427  // to the HoldTime from the triggering Join/Prune message.
428  downstream->joinPruneState = DownstreamInterface::JOIN;
429  downstream->startExpiryTimer(holdTime);
430  }
431  else if (downstream->joinPruneState == DownstreamInterface::JOIN) {
432  // The (S,G) downstream state machine on interface I remains in
433  // Join state, and the Expiry Timer (ET) is restarted, set to
434  // maximum of its current value and the HoldTime from the
435  // triggering Join/Prune message.
436  if (simTime() + holdTime > downstream->expiryTimer->getArrivalTime())
437  restartTimer(downstream->expiryTimer, holdTime);
438  }
439  else if (downstream->joinPruneState == DownstreamInterface::PRUNE_PENDING) {
440  // The (S,G) downstream state machine on interface I transitions
441  // to the Join state. The Prune-Pending Timer is canceled
442  // (without triggering an expiry event). The Expiry Timer is
443  // restarted, set to maximum of its current value and the
444  // HoldTime from the triggering Join/Prune message.
445  cancelAndDeleteTimer(downstream->prunePendingTimer);
446  if (simTime() + holdTime > downstream->expiryTimer->getArrivalTime())
447  restartTimer(downstream->expiryTimer, holdTime);
448  }
449  }
450 
451  // check upstream state transition
452  updateJoinDesired(routeSG);
453 }

Referenced by processJoinPrunePacket().

◆ processJoinSGrpt()

void inet::PimSm::processJoinSGrpt ( Ipv4Address  origin,
Ipv4Address  group,
Ipv4Address  upstreamNeighborField,
int  holdTime,
NetworkInterface inInterface 
)
private
456 {
457  // TODO
458 }

Referenced by processJoinPrunePacket().

◆ processJoinTimer()

void inet::PimSm::processJoinTimer ( cMessage *  timer)
private
956 {
957  EV << "pimSM::processJoinTimer:" << endl;
958 
959  Route *route = static_cast<Route *>(timer->getContextPointer());
960  ASSERT(timer == route->joinTimer);
961  Ipv4Address joinAddr = route->type == G ? route->rpAddr : route->source;
962 
963  if (!route->isInheritedOlistNull()) {
964  sendPIMJoin(route->group, joinAddr, route->upstreamInterface->nextHop, route->type);
965  restartTimer(route->joinTimer, joinPrunePeriod);
966  }
967  else {
968  delete timer;
969  route->joinTimer = nullptr;
970  }
971 }

Referenced by handleMessageWhenUp().

◆ processKeepAliveTimer()

void inet::PimSm::processKeepAliveTimer ( cMessage *  timer)
private
876 {
877  EV << "pimSM::processKeepAliveTimer: route will be deleted" << endl;
878  Route *route = static_cast<Route *>(timer->getContextPointer());
879  ASSERT(route->type == SG);
880  ASSERT(timer == route->keepAliveTimer);
881 
882  delete timer;
883  route->keepAliveTimer = nullptr;
884  deleteMulticastRoute(route);
885 }

Referenced by handleMessageWhenUp().

◆ processPruneG()

void inet::PimSm::processPruneG ( Ipv4Address  multGroup,
Ipv4Address  upstreamNeighborField,
NetworkInterface inInterface 
)
private
461 {
462  EV_DETAIL << "Processing Prune(*," << group << ") received on interface '" << inInterface->getInterfaceName() << "'.\n";
463 
464  //
465  // Downstream per-interface (*,G) state machine; event = Receive Prune(*,G)
466  //
467 
468  // check UpstreamNeighbor field
469  if (upstreamNeighborField != inInterface->getProtocolData<Ipv4InterfaceData>()->getIPAddress())
470  return;
471 
472  Route *routeG = findRouteG(group);
473  if (routeG) {
474  DownstreamInterface *downstream = routeG->findDownstreamInterfaceByInterfaceId(inInterface->getInterfaceId());
475  if (downstream && downstream->joinPruneState == DownstreamInterface::JOIN) {
476  // The (*,G) downstream state machine on interface I transitions
477  // to the Prune-Pending state. The Prune-Pending Timer is
478  // started. It is set to the J/P_Override_Interval(I) if the
479  // router has more than one neighbor on that interface;
480  // otherwise, it is set to zero, causing it to expire
481  // immediately.
482  downstream->joinPruneState = DownstreamInterface::PRUNE_PENDING;
483  double pruneOverrideInterval = pimNbt->getNumNeighbors(inInterface->getInterfaceId()) > 1 ?
485  downstream->startPrunePendingTimer(pruneOverrideInterval);
486  }
487  }
488 
489  // check upstream state transition
490  if (routeG)
491  updateJoinDesired(routeG);
492 }

Referenced by processJoinPrunePacket().

◆ processPrunePendingTimer()

void inet::PimSm::processPrunePendingTimer ( cMessage *  timer)
private

Prune Pending Timer is used for delaying of Prune message sending (for possible overriding Join from another PIM neighbor)

978 {
979  EV << "pimSM::processPrunePendingTimer:" << endl;
980  DownstreamInterface *downstream = static_cast<DownstreamInterface *>(timer->getContextPointer());
981  ASSERT(timer == downstream->prunePendingTimer);
982  ASSERT(downstream->joinPruneState == DownstreamInterface::PRUNE_PENDING);
983  Route *route = downstream->route();
984 
985  if (route->type == G || route->type == SG) {
986  //
987  // Downstream (*,G)/(S,G) Join/Prune State Machine; event: PPT expires
988  //
989 
990  // go to NO_INFO state
991  downstream->joinPruneState = DownstreamInterface::NO_INFO;
992  cancelAndDeleteTimer(downstream->expiryTimer);
993  downstream->prunePendingTimer = nullptr;
994  delete timer;
995 
996  // optionally send PruneEcho message
997  if (pimNbt->getNumNeighbors(downstream->ie->getInterfaceId()) > 1) {
998  // A PruneEcho is simply a Prune message sent by the
999  // upstream router on a LAN with its own address in the Upstream
1000  // Neighbor Address field. Its purpose is to add additional
1001  // reliability so that if a Prune that should have been
1002  // overridden by another router is lost locally on the LAN, then
1003  // the PruneEcho may be received and cause the override to happen.
1004  Ipv4Address pruneAddr = route->type == G ? route->rpAddr : route->source;
1005  Ipv4Address upstreamNeighborField = downstream->ie->getProtocolData<Ipv4InterfaceData>()->getIPAddress();
1006  sendPIMPrune(route->group, pruneAddr, upstreamNeighborField, route->type);
1007  }
1008  }
1009  else if (route->type == SGrpt) {
1010  //
1011  // Downstream (S,G,rpt) Join/Prune State Machine; event: PPT expires
1012  //
1013 
1014  // go to PRUNE state
1015  // TODO
1016  }
1017 
1018  // Now check upstream state transitions
1019  updateJoinDesired(route);
1020 }

Referenced by handleMessageWhenUp().

◆ processPruneSG()

void inet::PimSm::processPruneSG ( Ipv4Address  source,
Ipv4Address  group,
Ipv4Address  upstreamNeighborField,
NetworkInterface inInterface 
)
private
495 {
496  EV_DETAIL << "Processing Prune(" << source << ", " << group << ") received on interface '" << inInterface->getInterfaceName() << "'.'n";
497 
498  //
499  // Downstream per-interface (S,G) state machine; event = Receive Prune(S,G)
500  //
501 
502  // check UpstreamNeighbor field
503  if (upstreamNeighborField != inInterface->getProtocolData<Ipv4InterfaceData>()->getIPAddress())
504  return;
505 
506  Route *routeSG = findRouteSG(source, group);
507  if (routeSG) {
508  DownstreamInterface *downstream = routeSG->findDownstreamInterfaceByInterfaceId(inInterface->getInterfaceId());
509  if (downstream && downstream->joinPruneState == DownstreamInterface::JOIN) {
510  // The (S,G) downstream state machine on interface I transitions
511  // to the Prune-Pending state. The Prune-Pending Timer is
512  // started. It is set to the J/P_Override_Interval(I) if the
513  // router has more than one neighbor on that interface;
514  // otherwise, it is set to zero, causing it to expire
515  // immediately.
516  downstream->joinPruneState = DownstreamInterface::PRUNE_PENDING;
517  double pruneOverrideInterval = pimNbt->getNumNeighbors(inInterface->getInterfaceId()) > 1 ?
519  downstream->startPrunePendingTimer(pruneOverrideInterval);
520  }
521  }
522 
523  // check upstream state transition
524  if (routeSG)
525  updateJoinDesired(routeSG);
526 }

Referenced by processJoinPrunePacket().

◆ processPruneSGrpt()

void inet::PimSm::processPruneSGrpt ( Ipv4Address  source,
Ipv4Address  group,
Ipv4Address  upstreamNeighborField,
NetworkInterface inInterface 
)
private
529 {
530  // TODO
531 }

Referenced by processJoinPrunePacket().

◆ processRegisterPacket()

void inet::PimSm::processRegisterPacket ( Packet pk)
private

The method is used for processing PIM Register message sent from source DR.

If PIM Register isn't Null and route doesn't exist, it is created and PIM Register-Stop is sent. If PIM Register is Null, Register-Stop is sent.

539 {
540  const auto& pkt = pk->popAtFront<PimRegister>();
541  EV_INFO << "Received Register packet.\n";
542 
543  emit(rcvdRegisterPkSignal, pk);
544 
545  Ipv4Address srcAddr = pk->getTag<L3AddressInd>()->getSrcAddress().toIpv4();
546  Ipv4Address destAddr = pk->getTag<L3AddressInd>()->getDestAddress().toIpv4();
547  const auto& encapData = pk->peekAtFront<Ipv4Header>();
548  Ipv4Address source = encapData->getSrcAddress();
549  Ipv4Address group = encapData->getDestAddress();
550  Route *routeG = findRouteG(group);
551  Route *routeSG = findRouteSG(source, group);
552 
553  if (!pkt->getN()) { // It is Null Register ?
554  if (!routeG) {
555  routeG = addNewRouteG(group, Route::PRUNED);
556  }
557 
558  if (!routeSG) {
559  routeSG = addNewRouteSG(source, group, Route::PRUNED);
560  routeSG->startKeepAliveTimer(keepAlivePeriod);
561  }
562  else if (routeSG->keepAliveTimer) {
563  EV << " (S,G) KAT timer refresh" << endl;
564  restartTimer(routeSG->keepAliveTimer, KAT);
565  }
566 
567  if (!routeG->isInheritedOlistNull()) { // we have some active receivers
568  routeSG->clearFlag(Route::PRUNED);
569 
570  if (!routeSG->isFlagSet(Route::SPT_BIT)) { // only if isn't build SPT between RP and registering DR
571  // decapsulate and forward the inner packet to inherited_olist(S,G,rpt)
572  // TODO we are forwarding on inherited_olist(*,G)
573  for (auto& elem : routeG->downstreamInterfaces) {
574  DownstreamInterface *downstream = elem;
575  if (downstream->isInInheritedOlist())
576  forwardMulticastData(pk->dup(), downstream->getInterfaceId());
577  }
578 
579  // send Join(S,G) toward source to establish SPT between RP and registering DR
580  sendPIMJoin(group, source, routeSG->upstreamInterface->rpfNeighbor(), SG);
581 
582  // send register-stop packet
583  sendPIMRegisterStop(destAddr, srcAddr, group, source);
584  }
585  }
586  }
587 
588  if (routeG) {
589  if (routeG->isFlagSet(Route::PRUNED) || pkt->getN()) {
590  sendPIMRegisterStop(destAddr, srcAddr, group, source);
591  }
592  }
593 
594  delete pk;
595 }

Referenced by handleMessageWhenUp().

◆ processRegisterStopPacket()

void inet::PimSm::processRegisterStopPacket ( Packet pk)
private

The method is used for processing PIM Register-Stop message sent from RP.

If the message is received Register Tunnel between RP and source DR is set from Join status revert to Prune status. Also Register Stop Timer is created for periodic sending PIM Register Null messages.

604 {
605  const auto& pkt = pk->peekAtFront<PimRegisterStop>();
606  EV_INFO << "Received RegisterStop packet.\n";
607 
608  emit(rcvdRegisterStopPkSignal, pk);
609 
610  // TODO support wildcard source address
611  Route *routeSG = findRouteSG(pkt->getSourceAddress().unicastAddress.toIpv4(), pkt->getGroupAddress().groupAddress.toIpv4());
612  if (routeSG) {
613  if (routeSG->registerState == Route::RS_JOIN || routeSG->registerState == Route::RS_JOIN_PENDING) {
614  routeSG->registerState = Route::RS_PRUNE;
615  cancelAndDeleteTimer(routeSG->registerStopTimer);
616 
617  // The Register-Stop Timer is set to a random value chosen
618  // uniformly from the interval ( 0.5 * Register_Suppression_Time,
619  // 1.5 * Register_Suppression_Time) minus Register_Probe_Time.
620  // Subtracting off Register_Probe_Time is a bit unnecessary because
621  // it is really small compared to Register_Suppression_Time, but
622  // this was in the old spec and is kept for compatibility.
623  routeSG->startRegisterStopTimer(uniform(0.5 * registerSuppressionTime, 1.5 * registerSuppressionTime) - registerProbeTime);
624  }
625  }
626  delete pk;
627 }

Referenced by handleMessageWhenUp().

◆ processRegisterStopTimer()

void inet::PimSm::processRegisterStopTimer ( cMessage *  timer)
private
888 {
889  EV << "pimSM::processRegisterStopTimer: " << endl;
890  Route *routeSG = static_cast<Route *>(timer->getContextPointer());
891  ASSERT(timer == routeSG->registerStopTimer);
892  ASSERT(routeSG->type == SG);
893 
894  delete timer;
895  routeSG->registerStopTimer = nullptr;
896 
897  if (routeSG->registerState == Route::RS_PRUNE) {
898  routeSG->registerState = Route::RS_JOIN_PENDING;
899  sendPIMRegisterNull(routeSG->source, routeSG->group);
900  routeSG->startRegisterStopTimer(registerProbeTime);
901  }
902  else if (routeSG->registerState == Route::RS_JOIN_PENDING) {
903  routeSG->registerState = Route::RS_JOIN;
904  }
905 }

Referenced by handleMessageWhenUp().

◆ receiveSignal()

void inet::PimSm::receiveSignal ( cComponent *  source,
simsignal_t  signalID,
cObject *  obj,
cObject *  details 
)
overrideprotectedvirtual
224 {
225  Enter_Method("%s", cComponent::getSignalName(signalID));
226 
227  printSignalBanner(signalID, obj, details);
228 
229  if (signalID == ipv4MulticastGroupRegisteredSignal) {
230  EV << "pimSM::receiveChangeNotification - NEW IGMP ADDED" << endl;
231  const Ipv4MulticastGroupInfo *info = check_and_cast<const Ipv4MulticastGroupInfo *>(obj);
232  PimInterface *pimInterface = pimIft->getInterfaceById(info->ie->getInterfaceId());
233  if (pimInterface && pimInterface->getMode() == PimInterface::SparseMode)
234  multicastReceiverAdded(info->ie, info->groupAddress);
235  }
236  else if (signalID == ipv4MulticastGroupUnregisteredSignal) {
237  EV << "pimSM::receiveChangeNotification - IGMP REMOVED" << endl;
238  const Ipv4MulticastGroupInfo *info = check_and_cast<const Ipv4MulticastGroupInfo *>(obj);
239  PimInterface *pimInterface = pimIft->getInterfaceById(info->ie->getInterfaceId());
240  if (pimInterface && pimInterface->getMode() == PimInterface::SparseMode)
241  multicastReceiverRemoved(info->ie, info->groupAddress);
242  }
243  else if (signalID == ipv4NewMulticastSignal) {
244  EV << "PimSM::receiveChangeNotification - NEW MULTICAST" << endl;
245  const Ipv4Header *ipv4Header = check_and_cast<const Ipv4Header *>(obj);
246  Ipv4Address srcAddr = ipv4Header->getSrcAddress();
247  Ipv4Address destAddr = ipv4Header->getDestAddress();
248  unroutableMulticastPacketArrived(srcAddr, destAddr);
249  }
250  else if (signalID == ipv4DataOnRpfSignal) {
251  EV << "pimSM::receiveChangeNotification - DATA ON RPF" << endl;
252  const Ipv4Header *ipv4Header = check_and_cast<const Ipv4Header *>(obj);
253  PimInterface *incomingInterface = getIncomingInterface(check_and_cast<NetworkInterface *>(details));
254  if (incomingInterface && incomingInterface->getMode() == PimInterface::SparseMode) {
255  Route *route = findRouteG(ipv4Header->getDestAddress());
256  if (route)
258  route = findRouteSG(ipv4Header->getSrcAddress(), ipv4Header->getDestAddress());
259  if (route)
261  }
262  }
263  else if (signalID == ipv4DataOnNonrpfSignal) {
264  const Ipv4Header *ipv4Header = check_and_cast<const Ipv4Header *>(obj);
265  PimInterface *incomingInterface = getIncomingInterface(check_and_cast<NetworkInterface *>(details));
266  if (incomingInterface && incomingInterface->getMode() == PimInterface::SparseMode) {
267  Ipv4Address srcAddr = ipv4Header->getSrcAddress();
268  Ipv4Address destAddr = ipv4Header->getDestAddress();
269  Route *route;
270  if ((route = findRouteSG(srcAddr, destAddr)) != nullptr)
271  multicastPacketArrivedOnNonRpfInterface(route, incomingInterface->getInterfaceId());
272  else if ((route = findRouteG(destAddr)) != nullptr)
273  multicastPacketArrivedOnNonRpfInterface(route, incomingInterface->getInterfaceId());
274  }
275  }
276  else if (signalID == ipv4MdataRegisterSignal) {
277  EV << "pimSM::receiveChangeNotification - REGISTER DATA" << endl;
278  Packet *pk = check_and_cast<Packet *>(obj);
279  const auto& ipv4Header = pk->peekAtFront<Ipv4Header>();
280  PimInterface *incomingInterface = getIncomingInterface(check_and_cast<NetworkInterface *>(details));
281  Route *route = findRouteSG(ipv4Header->getSrcAddress(), ipv4Header->getDestAddress());
282  (void)route; // TODO unused variable
283  if (incomingInterface && incomingInterface->getMode() == PimInterface::SparseMode)
285  }
286  else if (signalID == pimNeighborAddedSignal || signalID == pimNeighborDeletedSignal || signalID == pimNeighborChangedSignal) {
287  PimNeighbor *neighbor = check_and_cast<PimNeighbor *>(obj);
288  updateDesignatedRouterAddress(neighbor->getInterfacePtr());
289  }
290 }

◆ removeRoute()

bool inet::PimSm::removeRoute ( Route route)
private
1866 {
1867  SourceAndGroup sg(route->source, route->group);
1868  if (route->type == G)
1869  return gRoutes.erase(sg);
1870  else
1871  return sgRoutes.erase(sg);
1872 }

Referenced by deleteMulticastRoute().

◆ restartExpiryTimer()

void inet::PimSm::restartExpiryTimer ( Route route,
NetworkInterface originIntf,
int  holdTime 
)
private

The method is used to restart ET.

ET is used for outgoing interfaces and whole route in router. After ET expires, outgoing interface is removed or if there aren't any outgoing interface, route is removed after ET expires.

1068 {
1069  EV << "pimSM::restartExpiryTimer: next ET @ " << simTime() + holdTime << " for type: ";
1070 
1071  if (route) {
1072  // ET for route
1073  if (route->upstreamInterface && route->upstreamInterface->expiryTimer)
1074  restartTimer(route->upstreamInterface->expiryTimer, holdTime);
1075 
1076  // ET for outgoing interfaces
1077  for (unsigned i = 0; i < route->downstreamInterfaces.size(); i++) { // if exist ET and for given interface
1078  DownstreamInterface *downstream = route->downstreamInterfaces[i];
1079  if (downstream->expiryTimer && (downstream->getInterfaceId() == originIntf->getInterfaceId())) {
1080  EV << /*timer->getStateType() << " , " <<*/ route->group << " , " << route->source << ", int: " << downstream->ie->getInterfaceName() << endl;
1081  restartTimer(downstream->expiryTimer, holdTime);
1082  break;
1083  }
1084  }
1085  }
1086 }

◆ restartTimer()

void inet::PimSm::restartTimer ( cMessage *  timer,
double  interval 
)
private

◆ sendPIMAssert()

void inet::PimSm::sendPIMAssert ( Ipv4Address  source,
Ipv4Address  group,
AssertMetric  metric,
NetworkInterface ie,
bool  rptBit 
)
private
1495 {
1496  EV_INFO << "Sending Assert(S= " << source << ", G= " << group << ") message on interface '" << ie->getInterfaceName() << "'\n";
1497 
1498  Packet *pk = new Packet("PimAssert");
1499  const auto& pkt = makeShared<PimAssert>();
1500  pkt->getGroupAddressForUpdate().groupAddress = group;
1501  // TODO set other fields of groupAddress
1502  pkt->getSourceAddressForUpdate().unicastAddress = source;
1503  pkt->setR(rptBit);
1504  pkt->setMetricPreference(metric.preference);
1505  pkt->setMetric(metric.metric);
1506 
1507  pkt->setChunkLength(PIM_HEADER_LENGTH
1510  + B(8));
1511  pkt->setCrcMode(pimModule->getCrcMode());
1512  Pim::insertCrc(pkt);
1513  pk->insertAtFront(pkt);
1514 
1515  emit(sentAssertPkSignal, pk);
1516 
1517  sendToIP(pk, Ipv4Address::UNSPECIFIED_ADDRESS, ALL_PIM_ROUTERS_MCAST, ie->getInterfaceId(), 1);
1518 }

Referenced by multicastPacketArrivedOnNonRpfInterface(), processAssertG(), processAssertSG(), and processAssertTimer().

◆ sendPIMJoin()

void inet::PimSm::sendPIMJoin ( Ipv4Address  group,
Ipv4Address  source,
Ipv4Address  upstreamNeighbor,
RouteType  JPtype 
)
private
1335 {
1336  EV_INFO << "Sending Join(S=" << (routeType == G ? "*" : source.str()) << ", G=" << group << ") to neighbor " << upstreamNeighbor << ".\n";
1337 
1338  Packet *pk = new Packet("PIMJoin");
1339  const auto& msg = makeShared<PimJoinPrune>();
1340  msg->setType(JoinPrune);
1341  msg->getUpstreamNeighborAddressForUpdate().unicastAddress = upstreamNeighbor;
1342  msg->setHoldTime(joinPruneHoldTime());
1343 
1344  msg->setJoinPruneGroupsArraySize(1);
1345  JoinPruneGroup& multGroup = msg->getJoinPruneGroupsForUpdate(0);
1346  auto& groupAddr = multGroup.getGroupAddressForUpdate();
1347  groupAddr.groupAddress = group;
1348  // TODO other fields of groupAddr
1349  multGroup.setJoinedSourceAddressArraySize(1);
1350  auto& encodedAddr = multGroup.getJoinedSourceAddressForUpdate(0);
1351  encodedAddr.sourceAddress = source;
1352  encodedAddr.S = true;
1353  encodedAddr.W = (routeType == G);
1354  encodedAddr.R = (routeType == G);
1355 
1356  msg->setChunkLength(PIM_HEADER_LENGTH
1358  + B(4)
1360  + B(4)
1362  msg->setCrcMode(pimModule->getCrcMode());
1363  Pim::insertCrc(msg);
1364 
1365  pk->insertAtFront(msg);
1366 
1367  emit(sentJoinPrunePkSignal, pk);
1368 
1369  NetworkInterface *interfaceToRP = rt->getInterfaceForDestAddr(source);
1370  sendToIP(pk, Ipv4Address::UNSPECIFIED_ADDRESS, ALL_PIM_ROUTERS_MCAST, interfaceToRP->getInterfaceId(), 1);
1371 }

Referenced by joinDesiredChanged(), processJoinTimer(), and processRegisterPacket().

◆ sendPIMPrune()

void inet::PimSm::sendPIMPrune ( Ipv4Address  group,
Ipv4Address  source,
Ipv4Address  upstreamNeighbor,
RouteType  JPtype 
)
private
1374 {
1375  EV_INFO << "Sending Prune(S=" << (routeType == G ? "*" : source.str()) << ", G=" << group << ") to neighbor " << upstreamNeighbor << ".\n";
1376 
1377  Packet *pk = new Packet("PIMPrune");
1378  const auto& msg = makeShared<PimJoinPrune>();
1379  msg->setType(JoinPrune);
1380  msg->getUpstreamNeighborAddressForUpdate().unicastAddress = upstreamNeighbor;
1381  msg->setHoldTime(joinPruneHoldTime());
1382 
1383  msg->setJoinPruneGroupsArraySize(1);
1384  JoinPruneGroup& multGroup = msg->getJoinPruneGroupsForUpdate(0);
1385  multGroup.getGroupAddressForUpdate().groupAddress = group;
1386  multGroup.setPrunedSourceAddressArraySize(1);
1387  auto& encodedAddr = multGroup.getPrunedSourceAddressForUpdate(0);
1388  encodedAddr.sourceAddress = source;
1389  encodedAddr.S = true;
1390  encodedAddr.W = (routeType == G);
1391  encodedAddr.R = (routeType == G);
1392 
1393  msg->setChunkLength(PIM_HEADER_LENGTH
1395  + B(4)
1397  + B(4)
1399  msg->setCrcMode(pimModule->getCrcMode());
1400  Pim::insertCrc(msg);
1401 
1402  pk->insertAtFront(msg);
1403 
1404  emit(sentJoinPrunePkSignal, pk);
1405 
1406  NetworkInterface *interfaceToRP = rt->getInterfaceForDestAddr(source);
1407  sendToIP(pk, Ipv4Address::UNSPECIFIED_ADDRESS, ALL_PIM_ROUTERS_MCAST, interfaceToRP->getInterfaceId(), 1);
1408 }

Referenced by joinDesiredChanged(), processExpiryTimer(), and processPrunePendingTimer().

◆ sendPIMRegister()

void inet::PimSm::sendPIMRegister ( Packet pk,
Ipv4Address  dest,
int  outInterfaceId 
)
private
1446 {
1447  ASSERT(ipv4Packet->peekAtFront<Ipv4Header>() != nullptr);
1448 
1449  EV << "pimSM::sendPIMRegister - encapsulating data packet into Register packet and sending to RP" << endl;
1450 
1451  Packet *pk = new Packet("PimRegister");
1452  const auto& msg = makeShared<PimRegister>();
1453  msg->setType(Register);
1454  msg->setN(false);
1455  msg->setB(false);
1456 
1457  msg->setChunkLength(PIM_HEADER_LENGTH + B(4));
1458  msg->setCrcMode(pimModule->getCrcMode());
1459  Pim::insertCrc(msg);
1460 
1461  pk->insertAtBack(ipv4Packet->peekDataAt(b(0), ipv4Packet->getDataLength()));
1462  pk->insertAtFront(msg);
1463 
1464  emit(sentRegisterPkSignal, pk);
1465 
1466  sendToIP(pk, Ipv4Address::UNSPECIFIED_ADDRESS, dest, outInterfaceId, MAX_TTL);
1467 }

Referenced by multicastPacketForwarded().

◆ sendPIMRegisterNull()

void inet::PimSm::sendPIMRegisterNull ( Ipv4Address  multSource,
Ipv4Address  multDest 
)
private
1411 {
1412  EV << "pimSM::sendPIMRegisterNull" << endl;
1413 
1414  // only if (S,G exist)
1415 // if (getRouteFor(multDest,multSource))
1416  if (findRouteG(multGroup)) {
1417  Packet *pk = new Packet("PimRegister(Null)");
1418  const auto& msg = makeShared<PimRegister>();
1419  msg->setType(Register);
1420  msg->setN(true);
1421  msg->setB(false);
1422  msg->setChunkLength(PIM_HEADER_LENGTH + B(4));
1423  msg->setCrcMode(pimModule->getCrcMode());
1424  Pim::insertCrc(msg);
1425  pk->insertAtFront(msg);
1426 
1427  // set encapsulated packet (Ipv4 header only)
1428  const auto& ipv4Header = makeShared<Ipv4Header>();
1429  ipv4Header->setDestAddress(multGroup);
1430  ipv4Header->setSrcAddress(multOrigin);
1431  ipv4Header->setProtocolId(IP_PROT_PIM);
1432  ipv4Header->setHeaderLength(IPv4_MIN_HEADER_LENGTH);
1433  ipv4Header->setTotalLengthField(IPv4_MIN_HEADER_LENGTH);
1434  ipv4Header->setCrcMode(pimModule->getCrcMode());
1435  Ipv4::insertCrc(ipv4Header);
1436  pk->insertAtBack(ipv4Header);
1437 
1438  emit(sentRegisterPkSignal, pk);
1439 
1440  NetworkInterface *interfaceToRP = rt->getInterfaceForDestAddr(rpAddr);
1441  sendToIP(pk, Ipv4Address::UNSPECIFIED_ADDRESS, rpAddr, interfaceToRP->getInterfaceId(), MAX_TTL);
1442  }
1443 }

Referenced by processRegisterStopTimer().

◆ sendPIMRegisterStop()

void inet::PimSm::sendPIMRegisterStop ( Ipv4Address  source,
Ipv4Address  dest,
Ipv4Address  multGroup,
Ipv4Address  multSource 
)
private
1470 {
1471  EV << "pimSM::sendPIMRegisterStop" << endl;
1472 
1473  // create PIM Register datagram
1474  Packet *pk = new Packet("PimRegisterStop");
1475  const auto& msg = makeShared<PimRegisterStop>();
1476 
1477  // set PIM packet
1478  msg->setType(RegisterStop);
1479  msg->getSourceAddressForUpdate().unicastAddress = multSource;
1480  msg->getGroupAddressForUpdate().groupAddress = multGroup;
1481 
1483  msg->setCrcMode(pimModule->getCrcMode());
1484  Pim::insertCrc(msg);
1485  pk->insertAtFront(msg);
1486 
1487  emit(sentRegisterStopPkSignal, pk);
1488 
1489  // set IP packet
1490  NetworkInterface *interfaceToDR = rt->getInterfaceForDestAddr(dest);
1491  sendToIP(pk, source, dest, interfaceToDR->getInterfaceId(), MAX_TTL);
1492 }

Referenced by processRegisterPacket().

◆ sendToIP()

void inet::PimSm::sendToIP ( Packet packet,
Ipv4Address  source,
Ipv4Address  dest,
int  outInterfaceId,
short  ttl 
)
private
1521 {
1522  packet->addTagIfAbsent<PacketProtocolTag>()->setProtocol(&Protocol::pim);
1523  packet->addTagIfAbsent<DispatchProtocolInd>()->setProtocol(&Protocol::pim);
1524  packet->addTagIfAbsent<DispatchProtocolReq>()->setProtocol(&Protocol::ipv4);
1525  packet->addTagIfAbsent<InterfaceReq>()->setInterfaceId(outInterfaceId);
1526  packet->addTagIfAbsent<L3AddressReq>()->setSrcAddress(srcAddr);
1527  packet->addTagIfAbsent<L3AddressReq>()->setDestAddress(destAddr);
1528  packet->addTagIfAbsent<HopLimitReq>()->setHopLimit(ttl);
1529  send(packet, "ipOut");
1530 }

Referenced by sendPIMAssert(), sendPIMJoin(), sendPIMPrune(), sendPIMRegister(), sendPIMRegisterNull(), and sendPIMRegisterStop().

◆ stopPIMRouting()

void inet::PimSm::stopPIMRouting ( )
protectedvirtual
107 {
108  if (isEnabled) {
109  cModule *host = findContainingNode(this);
110  if (!host)
111  throw cRuntimeError("PimSm: containing node not found.");
112  host->unsubscribe(ipv4NewMulticastSignal, this);
113  host->unsubscribe(ipv4MdataRegisterSignal, this);
114  host->unsubscribe(ipv4DataOnRpfSignal, this);
115  host->unsubscribe(ipv4DataOnNonrpfSignal, this);
116  host->unsubscribe(ipv4MulticastGroupRegisteredSignal, this);
117  host->unsubscribe(ipv4MulticastGroupUnregisteredSignal, this);
118  host->unsubscribe(pimNeighborAddedSignal, this);
119  host->unsubscribe(pimNeighborDeletedSignal, this);
120  host->unsubscribe(pimNeighborChangedSignal, this);
121  }
122 
123  clearRoutes();
124 }

Referenced by handleCrashOperation(), and handleStopOperation().

◆ unroutableMulticastPacketArrived()

void inet::PimSm::unroutableMulticastPacketArrived ( Ipv4Address  srcAddr,
Ipv4Address  destAddr 
)
private
1093 {
1094  Ipv4Route *routeTowardSource = rt->findBestMatchingRoute(source); // rt->getInterfaceForDestAddr(source);
1095  if (!routeTowardSource)
1096  return;
1097 
1098  PimInterface *rpfInterface = pimIft->getInterfaceById(routeTowardSource->getInterface()->getInterfaceId());
1099  if (!rpfInterface || rpfInterface->getMode() != PimInterface::SparseMode)
1100  return;
1101 
1102  NetworkInterface *interfaceTowardRP = rt->getInterfaceForDestAddr(rpAddr);
1103 
1104  // RPF check and check if I am DR of the source
1105  if ((interfaceTowardRP != routeTowardSource->getInterface()) && routeTowardSource->getGateway().isUnspecified()) {
1106  EV_DETAIL << "New multicast source observed: source=" << source << ", group=" << group << ".\n";
1107 
1108  // create new (S,G) route
1109  Route *newRouteSG = addNewRouteSG(source, group, Route::PRUNED | Route::REGISTER | Route::SPT_BIT);
1110  newRouteSG->startKeepAliveTimer(keepAlivePeriod);
1111  newRouteSG->registerState = Route::RS_JOIN;
1112 
1113  // create new (*,G) route
1114  addNewRouteG(newRouteSG->group, Route::PRUNED | Route::REGISTER);
1115  }
1116 }

Referenced by receiveSignal().

◆ updateAssertTrackingDesired()

void inet::PimSm::updateAssertTrackingDesired ( PimsmInterface interface)
private
1651 {
1652  // TODO
1653 
1654  // AssertTrackingDesired(S,G,I) =
1655  // (I in ( ( joins(*,*,RP(G)) (+) joins(*,G) (-) prunes(S,G,rpt) )
1656  // (+) ( pim_include(*,G) (-) pim_exclude(S,G) )
1657  // (-) lost_assert(*,G)
1658  // (+) joins(S,G) ) )
1659  // OR (local_receiver_include(S,G,I) == TRUE
1660  // AND (I_am_DR(I) OR (AssertWinner(S,G,I) == me)))
1661  // OR ((RPF_interface(S) == I) AND (JoinDesired(S,G) == TRUE))
1662  // OR ((RPF_interface(RP(G)) == I) AND (JoinDesired(*,G) == TRUE)
1663  // AND (SPTbit(S,G) == FALSE))
1664 
1665  // AssertTrackingDesired(*,G,I) =
1666  // CouldAssert(*,G,I)
1667  // OR (local_receiver_include(*,G,I)==TRUE
1668  // AND (I_am_DR(I) OR AssertWinner(*,G,I) == me))
1669  // OR (RPF_interface(RP(G)) == I AND RPTJoinDesired(G))
1670 }

◆ updateCouldAssert()

void inet::PimSm::updateCouldAssert ( DownstreamInterface interface)
private
1633 {
1634  // TODO
1635 
1636  // CouldAssert(S,G,I) =
1637  // SPTbit(S,G)==TRUE
1638  // AND (RPF_interface(S) != I)
1639  // AND (I in ( ( joins(*,*,RP(G)) (+) joins(*,G) (-) prunes(S,G,rpt) )
1640  // (+) ( pim_include(*,G) (-) pim_exclude(S,G) )
1641  // (-) lost_assert(*,G)
1642  // (+) joins(S,G) (+) pim_include(S,G) ) )
1643 
1644  // CouldAssert(*,G,I) =
1645  // ( I in ( joins(*,*,RP(G)) (+) joins(*,G)
1646  // (+) pim_include(*,G)) )
1647  // AND (RPF_interface(RP(G)) != I)
1648 }

◆ updateDesignatedRouterAddress()

void inet::PimSm::updateDesignatedRouterAddress ( NetworkInterface ie)
private
1593 {
1594  int interfaceId = ie->getInterfaceId();
1595  int numNeighbors = pimNbt->getNumNeighbors(interfaceId);
1596 
1597  bool eachNeighborHasPriority = true;
1598  for (int i = 0; i < numNeighbors && eachNeighborHasPriority; i++)
1599  if (pimNbt->getNeighbor(interfaceId, i))
1600  eachNeighborHasPriority = false;
1601 
1602  Ipv4Address drAddress = ie->getProtocolData<Ipv4InterfaceData>()->getIPAddress();
1603  int drPriority = this->designatedRouterPriority;
1604  for (int i = 0; i < numNeighbors; i++) {
1605  PimNeighbor *neighbor = pimNbt->getNeighbor(interfaceId, i);
1606  bool isBetter = eachNeighborHasPriority ?
1607  (neighbor->getDRPriority() > drPriority ||
1608  (neighbor->getDRPriority() == drPriority &&
1609  neighbor->getAddress() > drAddress)) :
1610  (neighbor->getAddress() > drAddress);
1611  if (isBetter) {
1612  drPriority = neighbor->getDRPriority();
1613  drAddress = neighbor->getAddress();
1614  }
1615  }
1616 
1617  PimInterface *pimInterface = pimIft->getInterfaceById(interfaceId);
1618  ASSERT(pimInterface);
1619  Ipv4Address oldDRAddress = pimInterface->getDRAddress();
1620  if (drAddress != oldDRAddress) {
1621  pimInterface->setDRAddress(drAddress);
1623 
1624  Ipv4Address myAddress = ie->getProtocolData<Ipv4InterfaceData>()->getIPAddress();
1625  bool iWasDR = oldDRAddress.isUnspecified() || oldDRAddress == myAddress;
1626  bool iAmDR = drAddress == myAddress;
1627  if (iWasDR != iAmDR)
1628  iAmDRHasChanged(ie, iAmDR);
1629  }
1630 }

Referenced by receiveSignal().

◆ updateJoinDesired()

void inet::PimSm::updateJoinDesired ( Route route)
private
1562 {
1563  bool oldValue = route->joinDesired();
1564  bool newValue = false;
1565  if (route->type == RP)
1566  newValue = !route->isImmediateOlistNull();
1567  if (route->type == G)
1568  newValue = !route->isImmediateOlistNull() /* || JoinDesired(*,*,RP(G)) AND AssertWinner(*,G,RPF_interface(RP(G))) != nullptr */;
1569  else if (route->type == SG)
1570  newValue = !route->isImmediateOlistNull() || (route->keepAliveTimer && !route->isInheritedOlistNull());
1571 
1572  if (newValue != oldValue) {
1573  route->setFlag(Route::JOIN_DESIRED, newValue);
1574  joinDesiredChanged(route);
1575 
1576  if (route->type == RP) {
1577  // TODO
1578  }
1579  else if (route->type == G) {
1580  for (auto& elem : sgRoutes) {
1581  if (elem.second->gRoute == route)
1582  updateJoinDesired(elem.second);
1583  }
1584  }
1585  }
1586 }

Referenced by multicastReceiverAdded(), multicastReceiverRemoved(), processJoinG(), processJoinSG(), processPruneG(), processPrunePendingTimer(), and processPruneSG().

Friends And Related Function Documentation

◆ operator<<

std::ostream& operator<< ( std::ostream &  out,
const PimSm::Route sourceGroup 
)
friend
2157 {
2158  out << "(" << (route.source.isUnspecified() ? "*" : route.source.str()) << ", "
2159  << (route.group.isUnspecified() ? "*" : route.group.str()) << "), ";
2160  out << "RP is " << route.rpAddr << ", ";
2161 
2162  out << "Incoming interface: ";
2163  if (route.upstreamInterface) {
2164  out << route.upstreamInterface->ie->getInterfaceName() << ", ";
2165  out << "RPF neighbor: " << route.upstreamInterface->rpfNeighbor() << ", ";
2166  }
2167  else
2168  out << "nullptr, ";
2169 
2170  out << "Downstream interfaces: ";
2171  for (unsigned int i = 0; i < route.downstreamInterfaces.size(); ++i) {
2172  if (i > 0)
2173  out << ", ";
2174  out << route.downstreamInterfaces[i]->ie->getInterfaceName() << " ";
2175  switch (route.downstreamInterfaces[i]->joinPruneState) {
2177  out << "(NI)";
2178  break;
2179 
2181  out << "(J)";
2182  break;
2183 
2185  out << "(PP)";
2186  break;
2187  }
2188  }
2189 
2190  return out;
2191 }

Member Data Documentation

◆ assertOverrideInterval

double inet::PimSm::assertOverrideInterval = 0
private

◆ assertTime

double inet::PimSm::assertTime = 0
private

◆ defaultOverrideInterval

double inet::PimSm::defaultOverrideInterval = 0
private

Referenced by initialize().

◆ defaultPropagationDelay

double inet::PimSm::defaultPropagationDelay = 0
private

Referenced by initialize().

◆ gRoutes

◆ joinPrunePeriod

double inet::PimSm::joinPrunePeriod = 0
private

◆ keepAlivePeriod

◆ rcvdAssertPkSignal

simsignal_t inet::PimSm::rcvdAssertPkSignal = registerSignal("rcvdAssertPk")
staticprivate

Referenced by processAssertPacket().

◆ rcvdJoinPrunePkSignal

simsignal_t inet::PimSm::rcvdJoinPrunePkSignal = registerSignal("rcvdJoinPrunePk")
staticprivate

Referenced by processJoinPrunePacket().

◆ rcvdRegisterPkSignal

simsignal_t inet::PimSm::rcvdRegisterPkSignal = registerSignal("rcvdRegisterPk")
staticprivate

Referenced by processRegisterPacket().

◆ rcvdRegisterStopPkSignal

simsignal_t inet::PimSm::rcvdRegisterStopPkSignal = registerSignal("rcvdRegisterStopPk")
staticprivate

◆ registerProbeTime

double inet::PimSm::registerProbeTime = 0
private

◆ registerSuppressionTime

double inet::PimSm::registerSuppressionTime = 0
private

◆ rpAddr

◆ rpKeepAlivePeriod

double inet::PimSm::rpKeepAlivePeriod = 0
private

Referenced by initialize().

◆ sentAssertPkSignal

simsignal_t inet::PimSm::sentAssertPkSignal = registerSignal("sentAssertPk")
staticprivate

Referenced by sendPIMAssert().

◆ sentJoinPrunePkSignal

simsignal_t inet::PimSm::sentJoinPrunePkSignal = registerSignal("sentJoinPrunePk")
staticprivate

Referenced by sendPIMJoin(), and sendPIMPrune().

◆ sentRegisterPkSignal

simsignal_t inet::PimSm::sentRegisterPkSignal = registerSignal("sentRegisterPk")
staticprivate

◆ sentRegisterStopPkSignal

simsignal_t inet::PimSm::sentRegisterStopPkSignal = registerSignal("sentRegisterStopPk")
staticprivate

Referenced by sendPIMRegisterStop().

◆ sgRoutes


The documentation for this class was generated from the following files:
inet::findContainingNode
cModule * findContainingNode(const cModule *from)
Find the node containing the given module.
Definition: ModuleAccess.cc:31
inet::Register
@ Register
Definition: PimPacket_m.h:94
inet::ipv4DataOnRpfSignal
simsignal_t ipv4DataOnRpfSignal
Definition: Simsignals.cc:58
inet::PimBase::Interface::NO_ASSERT_INFO
@ NO_ASSERT_INFO
Definition: PimBase.h:74
inet::PimSm::cancelAndDeleteTimer
void cancelAndDeleteTimer(cMessage *&timer)
Definition: PimSm.cc:1900
inet::Hello
@ Hello
Definition: PimPacket_m.h:93
inet::PimSm::processAssertPacket
void processAssertPacket(Packet *pk)
Definition: PimSm.cc:629
inet::PimSm::rpAddr
Ipv4Address rpAddr
Definition: PimSm.h:190
inet::PimBase::JoinTimer
@ JoinTimer
Definition: PimBase.h:140
inet::PimSm::assertTime
double assertTime
Definition: PimSm.h:198
inet::PimBase::Interface::AssertState
AssertState
Definition: PimBase.h:74
inet::PimSm::sgRoutes
RoutingTable sgRoutes
Definition: PimSm.h:213
inet::PimSm::processRegisterStopPacket
void processRegisterStopPacket(Packet *pk)
The method is used for processing PIM Register-Stop message sent from RP.
Definition: PimSm.cc:603
inet::PimSm::Route::RS_JOIN
@ RS_JOIN
Definition: PimSm.h:155
inet::PimSm::DownstreamInterface::PRUNE_PENDING
@ PRUNE_PENDING
Definition: PimSm.h:95
inet::PIM_HEADER_LENGTH
const B PIM_HEADER_LENGTH
Definition: PimPacket_m.h:68
inet::PimSm::sendPIMRegisterNull
void sendPIMRegisterNull(Ipv4Address multSource, Ipv4Address multDest)
Definition: PimSm.cc:1410
inet::PimSm::restartTimer
void restartTimer(cMessage *timer, double interval)
Definition: PimSm.cc:1906
inet::PimBase::ift
ModuleRefByPar< IInterfaceTable > ift
Definition: PimBase.h:147
inet::PimBase::handleCrashOperation
virtual void handleCrashOperation(LifecycleOperation *operation) override
Definition: PimBase.cc:88
inet::pimNeighborDeletedSignal
simsignal_t pimNeighborDeletedSignal
Definition: Simsignals.cc:61
inet::PimSm::Route::REGISTER
@ REGISTER
Definition: PimSm.h:132
inet::PimBase::KeepAliveTimer
@ KeepAliveTimer
Definition: PimBase.h:137
inet::PimSm::getIncomingInterface
PimInterface * getIncomingInterface(NetworkInterface *fromIE)
Definition: PimSm.cc:1684
inet::Protocol::ipv4
static const Protocol ipv4
Definition: Protocol.h:93
inet::PimSm::joinPruneOverrideInterval
double joinPruneOverrideInterval()
Definition: PimSm.h:280
inet::PimSm::registerSuppressionTime
double registerSuppressionTime
Definition: PimSm.h:196
inet::PimSm::sendToIP
void sendToIP(Packet *packet, Ipv4Address source, Ipv4Address dest, int outInterfaceId, short ttl)
Definition: PimSm.cc:1520
inet::PimSm::Route::SOURCE_DIRECTLY_CONNECTED
@ SOURCE_DIRECTLY_CONNECTED
Definition: PimSm.h:135
inet::ENCODED_GROUP_ADDRESS_LENGTH
const B ENCODED_GROUP_ADDRESS_LENGTH
Definition: PimPacket_m.h:70
inet::pimNeighborChangedSignal
simsignal_t pimNeighborChangedSignal
Definition: Simsignals.cc:62
inet::PimSm::updateDesignatedRouterAddress
void updateDesignatedRouterAddress(NetworkInterface *ie)
Definition: PimSm.cc:1592
inet::PimBase::Interface::I_WON_ASSERT
@ I_WON_ASSERT
Definition: PimBase.h:74
MAX_TTL
#define MAX_TTL
Maximum TTL.
Definition: PimSm.h:20
inet::PimSm::processRegisterStopTimer
void processRegisterStopTimer(cMessage *timer)
Definition: PimSm.cc:887
inet::PimSm::clearRoutes
void clearRoutes()
Definition: PimSm.cc:1713
inet::PimSm::sendPIMAssert
void sendPIMAssert(Ipv4Address source, Ipv4Address group, AssertMetric metric, NetworkInterface *ie, bool rptBit)
Definition: PimSm.cc:1494
inet::PimSm::findRouteG
Route * findRouteG(Ipv4Address group)
Definition: PimSm.cc:1874
inet::PimBase::isEnabled
bool isEnabled
Definition: PimBase.h:153
InterfaceReq
removed InterfaceReq
Definition: IUdp-gates.txt:11
inet::PimSm::rcvdRegisterStopPkSignal
static simsignal_t rcvdRegisterStopPkSignal
Definition: PimSm.h:205
DispatchProtocolReq
removed DscpReq Ipv4ControlInfo Ipv6ControlInfo up L3AddressInd DispatchProtocolReq L4PortInd Ipv4ControlInfo Ipv6ControlInfo down DispatchProtocolReq
Definition: IUdp-gates.txt:25
inet::printSignalBanner
void printSignalBanner(simsignal_t signalID, const cObject *obj, const cObject *details)
Utility function.
Definition: Simsignals.cc:126
inet::PimSm::sentAssertPkSignal
static simsignal_t sentAssertPkSignal
Definition: PimSm.h:208
L3AddressInd
removed DscpReq Ipv4ControlInfo Ipv6ControlInfo up L3AddressInd L3AddressInd
Definition: IUdp-gates.txt:20
inet::PimSm::rpKeepAlivePeriod
double rpKeepAlivePeriod
Definition: PimSm.h:195
inet::PimSm::processPruneG
void processPruneG(Ipv4Address multGroup, Ipv4Address upstreamNeighborField, NetworkInterface *inInterface)
Definition: PimSm.cc:460
inet::PimBase::pimModule
opp_component_ptr< Pim > pimModule
Definition: PimBase.h:150
inet::PimSm::processAssertG
void processAssertG(PimsmInterface *interface, const AssertMetric &receivedMetric)
Definition: PimSm.cc:782
inet::PimSm::joinDesiredChanged
void joinDesiredChanged(Route *route)
Definition: PimSm.cc:1264
inet::PimSm::designatedRouterAddressHasChanged
void designatedRouterAddressHasChanged(NetworkInterface *ie)
Definition: PimSm.cc:1320
inet::PimSm::addNewRouteG
Route * addNewRouteG(Ipv4Address group, int flags)
Definition: PimSm.cc:1739
inet::PimSm::addNewRouteSG
Route * addNewRouteSG(Ipv4Address source, Ipv4Address group, int flags)
Definition: PimSm.cc:1789
inet::PimSm::multicastReceiverAdded
void multicastReceiverAdded(NetworkInterface *ie, Ipv4Address group)
Definition: PimSm.cc:1130
inet::PimSm::unroutableMulticastPacketArrived
void unroutableMulticastPacketArrived(Ipv4Address srcAddr, Ipv4Address destAddr)
Definition: PimSm.cc:1092
inet::PimSm::stopPIMRouting
virtual void stopPIMRouting()
Definition: PimSm.cc:106
inet::PimSm::sentJoinPrunePkSignal
static simsignal_t sentJoinPrunePkSignal
Definition: PimSm.h:206
inet::Pim::insertCrc
static void insertCrc(const Ptr< PimPacket > &pimPacket)
Definition: Pim.cc:103
inet::PimSm::joinPruneHoldTime
double joinPruneHoldTime()
Definition: PimSm.h:277
inet::PimBase::PrunePendingTimer
@ PrunePendingTimer
Definition: PimBase.h:127
inet::PimBase::ALL_PIM_ROUTERS_MCAST
static const Ipv4Address ALL_PIM_ROUTERS_MCAST
Definition: PimBase.h:143
inet::PimBase::ExpiryTimer
@ ExpiryTimer
Definition: PimBase.h:139
inet::PimSm::Route::SPT_BIT
@ SPT_BIT
Definition: PimSm.h:133
inet::PimSm::joinPrunePeriod
double joinPrunePeriod
Definition: PimSm.h:191
inet::PimSm::sendPIMRegister
void sendPIMRegister(Packet *pk, Ipv4Address dest, int outInterfaceId)
Definition: PimSm.cc:1445
inet::PimSm::RP
@ RP
Definition: PimSm.h:122
inet::PimBase::handleStartOperation
virtual void handleStartOperation(LifecycleOperation *operation) override
Definition: PimBase.cc:60
inet::PimSm::rcvdJoinPrunePkSignal
static simsignal_t rcvdJoinPrunePkSignal
Definition: PimSm.h:207
inet::PimSm::iAmDRHasChanged
void iAmDRHasChanged(NetworkInterface *ie, bool iAmDR)
Definition: PimSm.cc:1325
PacketProtocolTag
removed DscpReq Ipv4ControlInfo Ipv6ControlInfo up L3AddressInd DispatchProtocolReq L4PortInd Ipv4ControlInfo Ipv6ControlInfo down PacketProtocolTag
Definition: IUdp-gates.txt:25
inet::PimSm::updateJoinDesired
void updateJoinDesired(Route *route)
Definition: PimSm.cc:1561
inet::ipv4NewMulticastSignal
simsignal_t ipv4NewMulticastSignal
Definition: Simsignals.cc:56
inet::Ipv4Address::ALLONES_ADDRESS
static const Ipv4Address ALLONES_ADDRESS
255.255.255.255
Definition: Ipv4Address.h:94
inet::PimSm::forwardMulticastData
void forwardMulticastData(Packet *pk, int outInterfaceId)
The method is used as abstraction for encapsulation multicast data to Register packet.
Definition: PimSm.cc:1537
inet::PimSm::DownstreamInterface::JOIN
@ JOIN
Definition: PimSm.h:95
inet::ipv4MdataRegisterSignal
simsignal_t ipv4MdataRegisterSignal
Definition: Simsignals.cc:59
inet::StateRefresh
@ StateRefresh
Definition: PimPacket_m.h:102
inet::pimNeighborAddedSignal
simsignal_t pimNeighborAddedSignal
Definition: Simsignals.cc:60
inet::PimSm::sendPIMJoin
void sendPIMJoin(Ipv4Address group, Ipv4Address source, Ipv4Address upstreamNeighbor, RouteType JPtype)
Definition: PimSm.cc:1334
inet::RegisterStop
@ RegisterStop
Definition: PimPacket_m.h:95
inet::PimSm::defaultOverrideInterval
double defaultOverrideInterval
Definition: PimSm.h:192
inet::PimSm::Route::PRUNED
@ PRUNED
Definition: PimSm.h:131
inet::Protocol::pim
static const Protocol pim
Definition: Protocol.h:103
inet::PimSm::DownstreamInterface::NO_INFO
@ NO_INFO
Definition: PimSm.h:95
inet::PimBase::PimBase
PimBase(PimInterface::PimMode mode)
Definition: PimBase.h:170
inet::units::units::B
intscale< b, 1, 8 > B
Definition: Units.h:1168
inet::PimSm::createIpv4Route
Ipv4MulticastRoute * createIpv4Route(Route *route)
Definition: PimSm.cc:1847
inet::PimSm::processJoinTimer
void processJoinTimer(cMessage *timer)
Definition: PimSm.cc:955
inet::PimBase::Interface::I_LOST_ASSERT
@ I_LOST_ASSERT
Definition: PimBase.h:74
inet::PimSm::effectiveOverrideInterval
double effectiveOverrideInterval()
Definition: PimSm.h:279
inet::PimSm::processJoinSG
void processJoinSG(Ipv4Address origin, Ipv4Address group, Ipv4Address upstreamNeighborField, int holdTime, NetworkInterface *inInterface)
Definition: PimSm.cc:401
inet::PimSm::multicastPacketArrivedOnNonRpfInterface
void multicastPacketArrivedOnNonRpfInterface(Route *route, int interfaceId)
Definition: PimSm.cc:1200
inet::ipv4MulticastGroupRegisteredSignal
simsignal_t ipv4MulticastGroupRegisteredSignal
Definition: Simsignals.cc:52
HopLimitReq
removed HopLimitReq
Definition: IUdp-gates.txt:11
inet::PimBase::pimIft
ModuleRefByPar< PimInterfaceTable > pimIft
Definition: PimBase.h:148
inet::PimSm::rcvdRegisterPkSignal
static simsignal_t rcvdRegisterPkSignal
Definition: PimSm.h:203
inet::PimSm::SGrpt
@ SGrpt
Definition: PimSm.h:125
inet::PimSm::assertOverrideInterval
double assertOverrideInterval
Definition: PimSm.h:199
inet::PimSm::processJoinSGrpt
void processJoinSGrpt(Ipv4Address origin, Ipv4Address group, Ipv4Address upstreamNeighborField, int holdTime, NetworkInterface *inInterface)
Definition: PimSm.cc:455
inet::PimSm::findIpv4Route
Ipv4MulticastRoute * findIpv4Route(Ipv4Address source, Ipv4Address group)
Definition: PimSm.cc:1889
inet::PimSm::effectivePropagationDelay
double effectivePropagationDelay()
Definition: PimSm.h:278
inet::PimSm::rcvdAssertPkSignal
static simsignal_t rcvdAssertPkSignal
Definition: PimSm.h:209
inet::PimSm::sentRegisterPkSignal
static simsignal_t sentRegisterPkSignal
Definition: PimSm.h:202
inet::INITSTAGE_LOCAL
INET_API InitStage INITSTAGE_LOCAL
Initialization of local state that don't use or affect other modules includes:
inet::PimBase::AssertMetric::PIM_INFINITE
static const AssertMetric PIM_INFINITE
Definition: PimBase.h:37
inet::Graft
@ Graft
Definition: PimPacket_m.h:99
inet::units::values::b
value< int64_t, units::b > b
Definition: Units.h:1241
inet::ENCODED_SOURCE_ADDRESS_LENGTH
const B ENCODED_SOURCE_ADDRESS_LENGTH
Definition: PimPacket_m.h:71
NUM_INIT_STAGES
#define NUM_INIT_STAGES
Definition: InitStageRegistry.h:73
inet::ipv4DataOnNonrpfSignal
simsignal_t ipv4DataOnNonrpfSignal
Definition: Simsignals.cc:57
inet::PimBase::holdTime
double holdTime
Definition: PimBase.h:158
inet::PimSm::processPrunePendingTimer
void processPrunePendingTimer(cMessage *timer)
Prune Pending Timer is used for delaying of Prune message sending (for possible overriding Join from ...
Definition: PimSm.cc:977
inet::PimBase::processHelloTimer
void processHelloTimer(cMessage *timer)
Definition: PimBase.cc:95
inet::PimSm::sendPIMPrune
void sendPIMPrune(Ipv4Address group, Ipv4Address source, Ipv4Address upstreamNeighbor, RouteType JPtype)
Definition: PimSm.cc:1373
inet::PimBase::pimNbt
ModuleRefByPar< PimNeighborTable > pimNbt
Definition: PimBase.h:149
inet::PimSm::multicastPacketForwarded
void multicastPacketForwarded(Packet *pk)
Definition: PimSm.cc:1231
inet::Ipv4Address::UNSPECIFIED_ADDRESS
static const Ipv4Address UNSPECIFIED_ADDRESS
0.0.0.0
Definition: Ipv4Address.h:91
Enter_Method
#define Enter_Method(...)
Definition: SelfDoc.h:71
inet::PimSm::gRoutes
RoutingTable gRoutes
Definition: PimSm.h:212
inet::ipv4MulticastGroupUnregisteredSignal
simsignal_t ipv4MulticastGroupUnregisteredSignal
Definition: Simsignals.cc:53
inet::IP_PROT_PIM
@ IP_PROT_PIM
Definition: IpProtocolId_m.h:106
inet::PimBase::designatedRouterPriority
int designatedRouterPriority
Definition: PimBase.h:159
inet::PimSm::processPruneSGrpt
void processPruneSGrpt(Ipv4Address source, Ipv4Address group, Ipv4Address upstreamNeighborField, NetworkInterface *inInterface)
Definition: PimSm.cc:528
inet::PimInterface::SparseMode
@ SparseMode
Definition: PimInterfaceTable.h:26
inet::PimSm::Route::RS_JOIN_PENDING
@ RS_JOIN_PENDING
Definition: PimSm.h:155
inet::Ipv4::insertCrc
static void insertCrc(const Ptr< Ipv4Header > &ipv4Header)
Definition: Ipv4.cc:832
inet::PimBase::RegisterStopTimer
@ RegisterStopTimer
Definition: PimBase.h:138
inet::PimSm::multicastPacketArrivedOnRpfInterface
void multicastPacketArrivedOnRpfInterface(Route *route)
The method process notification about data which appears on RPF interface.
Definition: PimSm.cc:1149
inet::PimSm::processJoinG
void processJoinG(Ipv4Address group, Ipv4Address rp, Ipv4Address upstreamNeighborField, int holdTime, NetworkInterface *inInterface)
Definition: PimSm.cc:338
inet::PimSm::sendPIMRegisterStop
void sendPIMRegisterStop(Ipv4Address source, Ipv4Address dest, Ipv4Address multGroup, Ipv4Address multSource)
Definition: PimSm.cc:1469
inet::PimSm::SG
@ SG
Definition: PimSm.h:124
inet::PimBase::AssertTimer
@ AssertTimer
Definition: PimBase.h:125
inet::PimSm::processExpiryTimer
void processExpiryTimer(cMessage *timer)
The method is used to process PIM Expiry Timer.
Definition: PimSm.cc:911
inet::PimSm::processKeepAliveTimer
void processKeepAliveTimer(cMessage *timer)
Definition: PimSm.cc:875
inet::PimSm::processRegisterPacket
void processRegisterPacket(Packet *pk)
The method is used for processing PIM Register message sent from source DR.
Definition: PimSm.cc:538
inet::PimSm::IamRP
bool IamRP(Ipv4Address rpAddr)
Definition: PimSm.h:289
inet::Assert
@ Assert
Definition: PimPacket_m.h:98
inet::ENCODED_UNICODE_ADDRESS_LENGTH
const B ENCODED_UNICODE_ADDRESS_LENGTH
Definition: PimPacket_m.h:69
inet::PimSm::Route::RS_PRUNE
@ RS_PRUNE
Definition: PimSm.h:155
inet::PimSm::findRouteSG
Route * findRouteSG(Ipv4Address source, Ipv4Address group)
Definition: PimSm.cc:1881
inet::PimSm::deleteMulticastRoute
bool deleteMulticastRoute(Route *route)
Definition: PimSm.cc:1691
inet::PimBase::handleStopOperation
virtual void handleStopOperation(LifecycleOperation *operation) override
Definition: PimBase.cc:81
inet::PimSm::sentRegisterStopPkSignal
static simsignal_t sentRegisterStopPkSignal
Definition: PimSm.h:204
inet::IPv4_MIN_HEADER_LENGTH
const B IPv4_MIN_HEADER_LENGTH
Definition: Ipv4Header_m.h:68
KAT
#define KAT
Keep alive timer, if RPT is disconnect.
Definition: PimSm.h:19
inet::PimSm::processPruneSG
void processPruneSG(Ipv4Address source, Ipv4Address group, Ipv4Address upstreamNeighborField, NetworkInterface *inInterface)
Definition: PimSm.cc:494
inet::PimSm::processAssertSG
void processAssertSG(PimsmInterface *interface, const AssertMetric &receivedMetric)
Definition: PimSm.cc:674
inet::PimSm::processJoinPrunePacket
void processJoinPrunePacket(Packet *pk)
Definition: PimSm.cc:292
inet::CandidateRPAdvertisement
@ CandidateRPAdvertisement
Definition: PimPacket_m.h:101
inet::Ipv4Address::isUnspecified
bool isUnspecified() const
True if all four address bytes are zero.
Definition: Ipv4Address.h:165
inet::PimSm::registerProbeTime
double registerProbeTime
Definition: PimSm.h:197
inet::IMulticastRoute::PIM_SM
@ PIM_SM
managed by PIM-SM router
Definition: IRoute.h:169
inet::PimSm::G
@ G
Definition: PimSm.h:123
inet::Bootstrap
@ Bootstrap
Definition: PimPacket_m.h:97
inet::PimSm::defaultPropagationDelay
double defaultPropagationDelay
Definition: PimSm.h:193
inet::PimBase::initialize
virtual void initialize(int stage) override
Definition: PimBase.cc:37
inet::PimSm::removeRoute
bool removeRoute(Route *route)
Definition: PimSm.cc:1865
inet::PimSm::processAssertTimer
void processAssertTimer(cMessage *timer)
Definition: PimSm.cc:1022
inet::PimBase::processHelloPacket
void processHelloPacket(Packet *pk)
Definition: PimBase.cc:153
inet::PimSm::multicastReceiverRemoved
void multicastReceiverRemoved(NetworkInterface *ie, Ipv4Address group)
Definition: PimSm.cc:1118
inet::PimBase::HelloTimer
@ HelloTimer
Definition: PimBase.h:121
inet::PimSm::keepAlivePeriod
double keepAlivePeriod
Definition: PimSm.h:194
inet::PimSm::Route::JOIN_DESIRED
@ JOIN_DESIRED
Definition: PimSm.h:134
inet::GraftAck
@ GraftAck
Definition: PimPacket_m.h:100
inet::JoinPrune
@ JoinPrune
Definition: PimPacket_m.h:96
inet::PimBase::rt
ModuleRefByPar< IIpv4RoutingTable > rt
Definition: PimBase.h:146