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::OperationalBase 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::OperationalBase
 OperationalBase ()
 
- Public Member Functions inherited from inet::ILifecycle
virtual ~ILifecycle ()
 

Protected Member Functions

virtual int numInitStages () const override
 
virtual void initialize (int stage) override
 
virtual bool handleNodeStart (IDoneCallback *doneCallback) override
 
virtual bool handleNodeShutdown (IDoneCallback *doneCallback) override
 
virtual void handleNodeCrash () override
 
virtual void stopPIMRouting ()
 
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 (PIMHello *pkt)
 
virtual bool isInitializeStage (int stage) override
 
virtual bool isNodeStartStage (int stage) override
 
virtual bool isNodeShutdownStage (int stage) override
 
- Protected Member Functions inherited from inet::OperationalBase
virtual void handleMessage (cMessage *msg) override
 
virtual void handleMessageWhenDown (cMessage *msg)
 
virtual bool handleOperationStage (LifecycleOperation *operation, int stage, IDoneCallback *doneCallback) override
 Perform one stage of a lifecycle operation. More...
 
virtual void setOperational (bool isOperational)
 

Private Types

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

Private Member Functions

void processJoinPrunePacket (PIMJoinPrune *pkt)
 
void processRegisterPacket (PIMRegister *pkt)
 The method is used for processing PIM Register message sent from source DR. More...
 
void processRegisterStopPacket (PIMRegisterStop *pkt)
 The method is used for processing PIM Register-Stop message sent from RP. More...
 
void processAssertPacket (PIMAssert *pkt)
 
void processJoinG (IPv4Address group, IPv4Address rp, IPv4Address upstreamNeighborField, int holdTime, InterfaceEntry *inInterface)
 
void processJoinSG (IPv4Address origin, IPv4Address group, IPv4Address upstreamNeighborField, int holdTime, InterfaceEntry *inInterface)
 
void processJoinSGrpt (IPv4Address origin, IPv4Address group, IPv4Address upstreamNeighborField, int holdTime, InterfaceEntry *inInterface)
 
void processPruneG (IPv4Address multGroup, IPv4Address upstreamNeighborField, InterfaceEntry *inInterface)
 
void processPruneSG (IPv4Address source, IPv4Address group, IPv4Address upstreamNeighborField, InterfaceEntry *inInterface)
 
void processPruneSGrpt (IPv4Address source, IPv4Address group, IPv4Address upstreamNeighborField, InterfaceEntry *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 (IPv4Datagram *datagram)
 
void multicastReceiverAdded (InterfaceEntry *ie, IPv4Address group)
 
void multicastReceiverRemoved (InterfaceEntry *ie, IPv4Address group)
 
void joinDesiredChanged (Route *route)
 
void designatedRouterAddressHasChanged (InterfaceEntry *ie)
 
void iAmDRHasChanged (InterfaceEntry *ie, bool iAmDR)
 
void sendPIMRegister (IPv4Datagram *datagram, 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, InterfaceEntry *ie, bool rptBit)
 
void sendToIP (PIMPacket *packet, IPv4Address source, IPv4Address dest, int outInterfaceId, short ttl)
 
void forwardMulticastData (IPv4Datagram *datagram, 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 (InterfaceEntry *ie)
 
void updateCouldAssert (DownstreamInterface *interface)
 
void updateAssertTrackingDesired (PimsmInterface *interface)
 
bool IamRP (IPv4Address rpAddr)
 
bool IamDR (InterfaceEntry *ie)
 
PIMInterfacegetIncomingInterface (IPv4Datagram *datagram)
 
bool deleteMulticastRoute (Route *route)
 
void clearRoutes ()
 
void cancelAndDeleteTimer (cMessage *&timer)
 
void restartTimer (cMessage *timer, double interval)
 
void restartExpiryTimer (Route *route, InterfaceEntry *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 SourceAndGroup &sourceGroup)
 
std::ostream & operator<< (std::ostream &out, const 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 Attributes inherited from inet::PIMBase
IIPv4RoutingTablert = nullptr
 
IInterfaceTableift = nullptr
 
PIMInterfaceTablepimIft = nullptr
 
PIMNeighborTablepimNbt = nullptr
 
bool isUp = false
 
bool isEnabled = false
 
const char * hostname = nullptr
 
double helloPeriod = 0
 
double holdTime = 0
 
int designatedRouterPriority = 0
 
PIMInterface::PIMMode mode = (PIMInterface::PIMMode)0
 
uint32_t generationID = 0
 
cMessage * helloTimer = nullptr
 
- Protected Attributes inherited from inet::OperationalBase
bool isOperational
 
simtime_t lastChange
 
- Static Protected Attributes inherited from inet::PIMBase
static const IPv4Address ALL_PIM_ROUTERS_MCAST
 
static simsignal_t sentHelloPkSignal = registerSignal("sentHelloPk")
 
static simsignal_t rcvdHelloPkSignal = registerSignal("rcvdHelloPk")
 

Detailed Description

Implementation of PIM-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

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

Member Enumeration Documentation

enum inet::PIMSM::RouteType
private
Enumerator
RP 
SG 
SGrpt 
138  {
139  RP, // (*,*,RP)
140  G, // (*,G)
141  SG, // (S,G)
142  SGrpt // (S,G,rpt)
143  };
Definition: PIMSM.h:141
Definition: PIMSM.h:142
Definition: PIMSM.h:140
Definition: PIMSM.h:139

Constructor & Destructor Documentation

inet::PIMSM::PIMSM ( )
inline
Definition: PIMInterfaceTable.h:37
PIMBase(PIMInterface::PIMMode mode)
Definition: PIMBase.h:181
inet::PIMSM::~PIMSM ( )
virtual
84 {
85  for (auto & elem : gRoutes)
86  delete elem.second;
87  for (auto & elem : sgRoutes)
88  delete elem.second;
89  // XXX rt contains references to the deleted route entries
90 }
RoutingTable gRoutes
Definition: PIMSM.h:228
RoutingTable sgRoutes
Definition: PIMSM.h:229

Member Function Documentation

PIMSM::Route * inet::PIMSM::addNewRouteG ( IPv4Address  group,
int  flags 
)
private

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

1762 {
1763  Route *newRouteG = new Route(this, G, IPv4Address::UNSPECIFIED_ADDRESS, group);
1764  newRouteG->setFlags(flags);
1765  newRouteG->rpAddr = rpAddr;
1766 
1767  // set upstream interface toward RP and set metric
1768  if (!IamRP(rpAddr)) {
1769  IPv4Route *routeToRP = rt->findBestMatchingRoute(rpAddr);
1770  if (routeToRP) {
1771  InterfaceEntry *ieTowardRP = routeToRP->getInterface();
1772  IPv4Address rpfNeighbor = routeToRP->getGateway();
1773  if (!pimNbt->findNeighbor(ieTowardRP->getInterfaceId(), rpfNeighbor) &&
1774  pimNbt->getNumNeighbors(ieTowardRP->getInterfaceId()) > 0)
1775  {
1776  PIMNeighbor *neighbor = pimNbt->getNeighbor(ieTowardRP->getInterfaceId(), 0);
1777  if (neighbor)
1778  rpfNeighbor = neighbor->getAddress();
1779  }
1780  newRouteG->upstreamInterface = new UpstreamInterface(newRouteG, ieTowardRP, rpfNeighbor);
1781  newRouteG->metric = AssertMetric(true, routeToRP->getAdminDist(), routeToRP->getMetric());
1782  }
1783  }
1784 
1785  // add downstream interfaces
1786  for (int i = 0; i < pimIft->getNumInterfaces(); i++) {
1787  PIMInterface *pimInterface = pimIft->getInterface(i);
1788  if (pimInterface->getMode() == PIMInterface::SparseMode &&
1789  (!newRouteG->upstreamInterface || pimInterface->getInterfacePtr() != newRouteG->upstreamInterface->ie))
1790  {
1791  DownstreamInterface *downstream = new DownstreamInterface(newRouteG, pimInterface->getInterfacePtr(), DownstreamInterface::NO_INFO);
1792  newRouteG->addDownstreamInterface(downstream);
1793  }
1794  }
1795 
1796  SourceAndGroup sg(IPv4Address::UNSPECIFIED_ADDRESS, group);
1797  gRoutes[sg] = newRouteG;
1798  rt->addMulticastRoute(createIPv4Route(newRouteG));
1799 
1800  // set (*,G) route in (S,G) and (S,G,rpt) routes
1801  for (auto & elem : sgRoutes) {
1802  if (elem.first.group == group) {
1803  Route *sgRoute = elem.second;
1804  sgRoute->gRoute = newRouteG;
1805  }
1806  }
1807 
1808  return newRouteG;
1809 }
PIMNeighborTable * pimNbt
Definition: PIMBase.h:161
virtual void addMulticastRoute(IPv4MulticastRoute *entry)=0
Adds a multicast route to the routing table.
IPv4Address getAddress() const
Definition: PIMNeighborTable.h:58
RoutingTable gRoutes
Definition: PIMSM.h:228
virtual PIMInterface * getInterface(int k)
Definition: PIMInterfaceTable.h:80
RoutingTable sgRoutes
Definition: PIMSM.h:229
PIMInterfaceTable * pimIft
Definition: PIMBase.h:160
virtual int getNumNeighbors(int interfaceId)
Returns the number of neighbors on the given interface.
Definition: PIMNeighborTable.cc:176
IPv4Address rpAddr
Definition: PIMSM.h:206
IPv4MulticastRoute * createIPv4Route(Route *route)
Definition: PIMSM.cc:1869
InterfaceEntry * getInterface() const override
Next hop interface.
Definition: IPv4Route.h:114
virtual PIMNeighbor * findNeighbor(int interfaceId, IPv4Address addr)
Returns the neighbor that is identified by the given (interfaceId,addr), or nullptr if no such neighb...
Definition: PIMNeighborTable.cc:164
IIPv4RoutingTable * rt
Definition: PIMBase.h:158
bool IamRP(IPv4Address rpAddr)
Definition: PIMSM.h:305
virtual IPv4Route * findBestMatchingRoute(const IPv4Address &dest) const =0
The routing function.
static const IPv4Address UNSPECIFIED_ADDRESS
0.0.0.0
Definition: IPv4Address.h:102
Definition: PIMInterfaceTable.h:37
virtual int getNumInterfaces()
Definition: PIMInterfaceTable.h:79
virtual PIMNeighbor * getNeighbor(int interfaceId, int index)
Returns the neighbor on the given interface at the specified position.
Definition: PIMNeighborTable.cc:182
Definition: PIMSM.h:140
PIMSM::Route * inet::PIMSM::addNewRouteSG ( IPv4Address  source,
IPv4Address  group,
int  flags 
)
private

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

1812 {
1813  ASSERT(!source.isUnspecified());
1814  ASSERT(group.isMulticast() && !group.isLinkLocalMulticast());
1815 
1816  Route *newRouteSG = new Route(this, SG, source, group);
1817  newRouteSG->setFlags(flags);
1818  newRouteSG->rpAddr = rpAddr;
1819 
1820  // set upstream interface toward source and set metric
1821  IPv4Route *routeToSource = rt->findBestMatchingRoute(source);
1822  if (routeToSource) {
1823  InterfaceEntry *ieTowardSource = routeToSource->getInterface();
1824  IPv4Address rpfNeighbor = routeToSource->getGateway();
1825 
1826  if (rpfNeighbor.isUnspecified())
1827  newRouteSG->setFlag(Route::SOURCE_DIRECTLY_CONNECTED, true);
1828  else {
1829  if (!pimNbt->findNeighbor(ieTowardSource->getInterfaceId(), rpfNeighbor) &&
1830  pimNbt->getNumNeighbors(ieTowardSource->getInterfaceId()) > 0)
1831  {
1832  PIMNeighbor *neighbor = pimNbt->getNeighbor(ieTowardSource->getInterfaceId(), 0);
1833  if (neighbor)
1834  rpfNeighbor = neighbor->getAddress();
1835  }
1836  }
1837  newRouteSG->upstreamInterface = new UpstreamInterface(newRouteSG, ieTowardSource, rpfNeighbor);
1838  newRouteSG->metric = AssertMetric(false, routeToSource->getAdminDist(), routeToSource->getMetric());
1839  }
1840 
1841  // add downstream interfaces
1842  for (int i = 0; i < pimIft->getNumInterfaces(); i++) {
1843  PIMInterface *pimInterface = pimIft->getInterface(i);
1844  if (pimInterface->getMode() == PIMInterface::SparseMode && pimInterface->getInterfacePtr() != newRouteSG->upstreamInterface->ie) {
1845  DownstreamInterface *downstream = new DownstreamInterface(newRouteSG, pimInterface->getInterfacePtr(), DownstreamInterface::NO_INFO);
1846  newRouteSG->addDownstreamInterface(downstream);
1847  }
1848  }
1849 
1850  SourceAndGroup sg(source, group);
1851  sgRoutes[sg] = newRouteSG;
1852  rt->addMulticastRoute(createIPv4Route(newRouteSG));
1853 
1854  // set (*,G) route if exists
1855  newRouteSG->gRoute = findRouteG(group);
1856 
1857  // set (S,G,rpt) route if exists
1858  Route *sgrptRoute = nullptr; // TODO
1859  newRouteSG->sgrptRoute = sgrptRoute;
1860 
1861  // set (S,G) route in (S,G,rpt) route
1862  if (sgrptRoute) {
1863 // sgrptRoute->sgRoute = newRouteSG;
1864  }
1865 
1866  return newRouteSG;
1867 }
PIMNeighborTable * pimNbt
Definition: PIMBase.h:161
virtual void addMulticastRoute(IPv4MulticastRoute *entry)=0
Adds a multicast route to the routing table.
IPv4Address getAddress() const
Definition: PIMNeighborTable.h:58
virtual PIMInterface * getInterface(int k)
Definition: PIMInterfaceTable.h:80
RoutingTable sgRoutes
Definition: PIMSM.h:229
Route * findRouteG(IPv4Address group)
Definition: PIMSM.cc:1896
Definition: PIMSM.h:141
PIMInterfaceTable * pimIft
Definition: PIMBase.h:160
virtual int getNumNeighbors(int interfaceId)
Returns the number of neighbors on the given interface.
Definition: PIMNeighborTable.cc:176
IPv4Address rpAddr
Definition: PIMSM.h:206
IPv4MulticastRoute * createIPv4Route(Route *route)
Definition: PIMSM.cc:1869
InterfaceEntry * getInterface() const override
Next hop interface.
Definition: IPv4Route.h:114
virtual PIMNeighbor * findNeighbor(int interfaceId, IPv4Address addr)
Returns the neighbor that is identified by the given (interfaceId,addr), or nullptr if no such neighb...
Definition: PIMNeighborTable.cc:164
IIPv4RoutingTable * rt
Definition: PIMBase.h:158
virtual IPv4Route * findBestMatchingRoute(const IPv4Address &dest) const =0
The routing function.
Definition: PIMInterfaceTable.h:37
virtual int getNumInterfaces()
Definition: PIMInterfaceTable.h:79
virtual PIMNeighbor * getNeighbor(int interfaceId, int index)
Returns the neighbor on the given interface at the specified position.
Definition: PIMNeighborTable.cc:182
void inet::PIMSM::cancelAndDeleteTimer ( cMessage *&  timer)
private

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

1923 {
1924  cancelAndDelete(timer);
1925  timer = nullptr;
1926 }
void inet::PIMSM::clearRoutes ( )
private

Referenced by stopPIMRouting().

1736 {
1737  // delete IPv4 routes
1738  bool changed = true;
1739  while (changed) {
1740  changed = false;
1741  for (int i = 0; i < rt->getNumMulticastRoutes(); i++) {
1742  IPv4MulticastRoute *ipv4Route = rt->getMulticastRoute(i);
1743  if (ipv4Route->getSource() == this) {
1744  rt->deleteMulticastRoute(ipv4Route);
1745  changed = true;
1746  break;
1747  }
1748  }
1749  }
1750 
1751  // clear local tables
1752  for (auto & elem : gRoutes)
1753  delete elem.second;
1754  gRoutes.clear();
1755 
1756  for (auto & elem : sgRoutes)
1757  delete elem.second;
1758  sgRoutes.clear();
1759 }
RoutingTable gRoutes
Definition: PIMSM.h:228
virtual int getNumMulticastRoutes() const =0
Returns the total number of multicast routes.
RoutingTable sgRoutes
Definition: PIMSM.h:229
virtual IPv4MulticastRoute * getMulticastRoute(int k) const override=0
Returns the kth multicast route.
virtual bool deleteMulticastRoute(IPv4MulticastRoute *entry)=0
Deletes the given multicast route from the routing table.
IIPv4RoutingTable * rt
Definition: PIMBase.h:158
IPv4MulticastRoute * inet::PIMSM::createIPv4Route ( Route route)
private

Referenced by addNewRouteG(), and addNewRouteSG().

1870 {
1871  IPv4MulticastRoute *newRoute = new IPv4MulticastRoute();
1872  newRoute->setOrigin(route->source);
1873  newRoute->setOriginNetmask(route->source.isUnspecified() ? IPv4Address::UNSPECIFIED_ADDRESS : IPv4Address::ALLONES_ADDRESS);
1874  newRoute->setMulticastGroup(route->group);
1875  newRoute->setSourceType(IMulticastRoute::PIM_SM);
1876  newRoute->setSource(this);
1877  if (route->upstreamInterface)
1878  newRoute->setInInterface(new IMulticastRoute::InInterface(route->upstreamInterface->ie));
1879  unsigned int numOutInterfaces = route->downstreamInterfaces.size();
1880  for (unsigned int i = 0; i < numOutInterfaces; ++i) {
1881  DownstreamInterface *downstream = route->downstreamInterfaces[i];
1882  newRoute->addOutInterface(new PIMSMOutInterface(downstream));
1883  }
1884  return newRoute;
1885 }
static const IPv4Address UNSPECIFIED_ADDRESS
0.0.0.0
Definition: IPv4Address.h:102
managed by PIM-SM router
Definition: IRoute.h:157
static const IPv4Address ALLONES_ADDRESS
255.255.255.255
Definition: IPv4Address.h:105
bool inet::PIMSM::deleteMulticastRoute ( Route route)
private

Referenced by processExpiryTimer(), and processKeepAliveTimer().

1714 {
1715  if (removeRoute(route)) {
1716  // remove route from IPv4 routing table
1717  IPv4MulticastRoute *ipv4Route = findIPv4Route(route->source, route->group);
1718  if (ipv4Route)
1719  rt->deleteMulticastRoute(ipv4Route);
1720 
1721  // unlink
1722  if (route->type == G) {
1723  for (auto & elem : sgRoutes)
1724  if (elem.second->gRoute == route)
1725  elem.second->gRoute = nullptr;
1726 
1727  }
1728 
1729  delete route;
1730  return true;
1731  }
1732  return false;
1733 }
RoutingTable sgRoutes
Definition: PIMSM.h:229
virtual bool deleteMulticastRoute(IPv4MulticastRoute *entry)=0
Deletes the given multicast route from the routing table.
IIPv4RoutingTable * rt
Definition: PIMBase.h:158
Definition: PIMSM.h:140
IPv4MulticastRoute * findIPv4Route(IPv4Address source, IPv4Address group)
Definition: PIMSM.cc:1911
bool removeRoute(Route *route)
Definition: PIMSM.cc:1887
void inet::PIMSM::designatedRouterAddressHasChanged ( InterfaceEntry ie)
private

Referenced by updateDesignatedRouterAddress().

1365 {
1366  // TODO
1367 }
double inet::PIMSM::effectiveOverrideInterval ( )
inlineprivate
295 { return defaultOverrideInterval; }
double defaultOverrideInterval
Definition: PIMSM.h:208
double inet::PIMSM::effectivePropagationDelay ( )
inlineprivate
294 { return defaultPropagationDelay; }
double defaultPropagationDelay
Definition: PIMSM.h:209
IPv4MulticastRoute * inet::PIMSM::findIPv4Route ( IPv4Address  source,
IPv4Address  group 
)
private

Referenced by deleteMulticastRoute(), and inet::PIMSM::Route::removeDownstreamInterface().

1912 {
1913  unsigned int numMulticastRoutes = rt->getNumMulticastRoutes();
1914  for (unsigned int i = 0; i < numMulticastRoutes; ++i) {
1915  IPv4MulticastRoute *ipv4Route = rt->getMulticastRoute(i);
1916  if (ipv4Route->getSource() == this && ipv4Route->getOrigin() == source && ipv4Route->getMulticastGroup() == group)
1917  return ipv4Route;
1918  }
1919  return nullptr;
1920 }
virtual int getNumMulticastRoutes() const =0
Returns the total number of multicast routes.
virtual IPv4MulticastRoute * getMulticastRoute(int k) const override=0
Returns the kth multicast route.
IIPv4RoutingTable * rt
Definition: PIMBase.h:158
PIMSM::Route * inet::PIMSM::findRouteG ( IPv4Address  group)
private

Referenced by addNewRouteSG(), multicastPacketArrivedOnNonRpfInterface(), multicastReceiverAdded(), multicastReceiverRemoved(), processAssertPacket(), processJoinG(), processPruneG(), processRegisterPacket(), receiveSignal(), and sendPIMRegisterNull().

1897 {
1898  SourceAndGroup sg(IPv4Address::UNSPECIFIED_ADDRESS, group);
1899  auto it = gRoutes.find(sg);
1900  return it != gRoutes.end() ? it->second : nullptr;
1901 }
RoutingTable gRoutes
Definition: PIMSM.h:228
static const IPv4Address UNSPECIFIED_ADDRESS
0.0.0.0
Definition: IPv4Address.h:102
PIMSM::Route * inet::PIMSM::findRouteSG ( IPv4Address  source,
IPv4Address  group 
)
private

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

1904 {
1905  ASSERT(!source.isUnspecified());
1906  SourceAndGroup sg(source, group);
1907  auto it = sgRoutes.find(sg);
1908  return it != sgRoutes.end() ? it->second : nullptr;
1909 }
RoutingTable sgRoutes
Definition: PIMSM.h:229
void inet::PIMSM::forwardMulticastData ( IPv4Datagram datagram,
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.

Referenced by processRegisterPacket().

1555 {
1556  EV << "pimSM::forwardMulticastData" << endl;
1557 
1558  //
1559  // Note: we should inject the datagram somehow into the normal IPv4 forwarding path.
1560  //
1561  cPacket *data = datagram->decapsulate();
1562 
1563  // set control info
1564  IPv4ControlInfo *ctrl = new IPv4ControlInfo();
1565  ctrl->setDestAddr(datagram->getDestAddress());
1566  // XXX ctrl->setSrcAddr(datagram->getSrcAddress()); // FIXME IP won't accept if the source is non-local
1567  ctrl->setInterfaceId(outInterfaceId);
1568  ctrl->setTimeToLive(MAX_TTL - 2); //one minus for source DR router and one for RP router // XXX specification???
1569  ctrl->setProtocol(datagram->getTransportProtocol());
1570  data->setControlInfo(ctrl);
1571  send(data, "ipOut");
1572  delete datagram;
1573 }
#define MAX_TTL
Maximum TTL.
Definition: PIMSM.h:31
PIMInterface * inet::PIMSM::getIncomingInterface ( IPv4Datagram datagram)
private

Referenced by receiveSignal().

1703 {
1704  cGate *g = datagram->getArrivalGate();
1705  if (g) {
1706  InterfaceEntry *ie = ift->getInterfaceByNetworkLayerGateIndex(g->getIndex());
1707  if (ie)
1708  return pimIft->getInterfaceById(ie->getInterfaceId());
1709  }
1710  return nullptr;
1711 }
PIMInterfaceTable * pimIft
Definition: PIMBase.h:160
virtual InterfaceEntry * getInterfaceByNetworkLayerGateIndex(int index)=0
Returns an interface given by its getNetworkLayerGateIndex().
IInterfaceTable * ift
Definition: PIMBase.h:159
virtual PIMInterface * getInterfaceById(int interfaceId)
Definition: PIMInterfaceTable.cc:116
milli< kg >::type g
Definition: Units.h:900
void inet::PIMSM::handleMessageWhenUp ( cMessage *  msg)
overrideprotectedvirtual

Implements inet::OperationalBase.

176 {
177  if (msg->isSelfMessage()) {
178  switch (msg->getKind()) {
179  case HelloTimer:
180  processHelloTimer(msg);
181  break;
182 
183  case JoinTimer:
184  processJoinTimer(msg);
185  break;
186 
187  case PrunePendingTimer:
189  break;
190 
191  case ExpiryTimer:
192  processExpiryTimer(msg);
193  break;
194 
195  case KeepAliveTimer:
197  break;
198 
199  case RegisterStopTimer:
201  break;
202 
203  case AssertTimer:
204  processAssertTimer(msg);
205  break;
206 
207  default:
208  throw cRuntimeError("PIMSM: unknown self message: %s (%s)", msg->getName(), msg->getClassName());
209  }
210  }
211  else if (dynamic_cast<PIMPacket *>(msg)) {
212  if (!isEnabled) {
213  EV_DETAIL << "PIM-SM is disabled, dropping packet.\n";
214  delete msg;
215  return;
216  }
217 
218  PIMPacket *pkt = check_and_cast<PIMPacket *>(msg);
219  switch (pkt->getType()) {
220  case Hello:
221  processHelloPacket(check_and_cast<PIMHello *>(pkt));
222  break;
223 
224  case JoinPrune:
225  processJoinPrunePacket(check_and_cast<PIMJoinPrune *>(pkt));
226  break;
227 
228  case Register:
229  processRegisterPacket(check_and_cast<PIMRegister *>(pkt));
230  break;
231 
232  case RegisterStop:
233  processRegisterStopPacket(check_and_cast<PIMRegisterStop *>(pkt));
234  break;
235 
236  case Assert:
237  processAssertPacket(check_and_cast<PIMAssert *>(pkt));
238  break;
239 
240  case Graft:
241  EV_WARN << "Ignoring PIM-DM Graft packet.\n";
242  delete pkt;
243  break;
244 
245  case GraftAck:
246  EV_WARN << "Ignoring PIM-DM GraftAck packet.\n";
247  delete pkt;
248  break;
249 
250  case StateRefresh:
251  EV_WARN << "Ignoring PIM-DM StateRefresh packet.\n";
252  delete pkt;
253  break;
254 
255  case Bootstrap:
256  delete pkt;
257  break;
258 
260  delete pkt;
261  break;
262 
263  default:
264  throw cRuntimeError("PIMSM: received unknown PIM packet: %s (%s)", pkt->getName(), pkt->getClassName());
265  }
266  }
267  else
268  EV << "PIMSM::handleMessage: Wrong message" << endl;
269 }
void processJoinTimer(cMessage *timer)
Definition: PIMSM.cc:1000
Definition: PIMPacket_m.h:64
bool isEnabled
Definition: PIMBase.h:164
void processRegisterStopPacket(PIMRegisterStop *pkt)
The method is used for processing PIM Register-Stop message sent from RP.
Definition: PIMSM.cc:649
Definition: PIMBase.h:137
void processAssertTimer(cMessage *timer)
Definition: PIMSM.cc:1067
Definition: PIMBase.h:133
void processAssertPacket(PIMAssert *pkt)
Definition: PIMSM.cc:674
Definition: PIMBase.h:151
void processJoinPrunePacket(PIMJoinPrune *pkt)
Definition: PIMSM.cc:339
Definition: PIMPacket_m.h:63
Definition: PIMPacket_m.h:70
void processHelloPacket(PIMHello *pkt)
Definition: PIMBase.cc:190
void processKeepAliveTimer(cMessage *timer)
Definition: PIMSM.cc:920
void processRegisterStopTimer(cMessage *timer)
Definition: PIMSM.cc:932
Definition: PIMPacket_m.h:65
Definition: PIMPacket_m.h:69
void processHelloTimer(cMessage *timer)
Definition: PIMBase.cc:135
void processPrunePendingTimer(cMessage *timer)
Prune Pending Timer is used for delaying of Prune message sending (for possible overriding Join from ...
Definition: PIMSM.cc:1022
Definition: PIMPacket_m.h:67
Definition: PIMBase.h:150
Definition: PIMBase.h:139
Definition: PIMBase.h:149
Definition: PIMPacket_m.h:66
Definition: PIMPacket_m.h:71
Definition: PIMBase.h:152
Definition: PIMPacket_m.h:68
void processRegisterPacket(PIMRegister *pkt)
The method is used for processing PIM Register message sent from source DR.
Definition: PIMSM.cc:584
Definition: PIMPacket_m.h:62
void processExpiryTimer(cMessage *timer)
The method is used to process PIM Expiry Timer.
Definition: PIMSM.cc:956
void inet::PIMSM::handleNodeCrash ( )
overrideprotectedvirtual

Reimplemented from inet::PIMBase.

150 {
151  stopPIMRouting();
153 }
virtual void stopPIMRouting()
Definition: PIMSM.cc:155
virtual void handleNodeCrash() override
Definition: PIMBase.cc:128
bool inet::PIMSM::handleNodeShutdown ( IDoneCallback doneCallback)
overrideprotectedvirtual

Reimplemented from inet::PIMBase.

143 {
144  // TODO send PIM Hellos to neighbors with 0 HoldTime
145  stopPIMRouting();
146  return PIMBase::handleNodeShutdown(doneCallback);
147 }
virtual void stopPIMRouting()
Definition: PIMSM.cc:155
virtual bool handleNodeShutdown(IDoneCallback *doneCallback) override
Definition: PIMBase.cc:120
bool inet::PIMSM::handleNodeStart ( IDoneCallback doneCallback)
overrideprotectedvirtual

Reimplemented from inet::PIMBase.

117 {
118  bool done = PIMBase::handleNodeStart(doneCallback);
119 
120  if (isEnabled) {
121  if (rpAddr.isUnspecified())
122  throw cRuntimeError("PIMSM: missing RP address parameter.");
123 
124  // subscribe for notifications
125  cModule *host = findContainingNode(this);
126  if (!host)
127  throw cRuntimeError("PIMDM: containing node not found.");
128  host->subscribe(NF_IPv4_NEW_MULTICAST, this);
129  host->subscribe(NF_IPv4_MDATA_REGISTER, this);
130  host->subscribe(NF_IPv4_DATA_ON_RPF, this);
131  host->subscribe(NF_IPv4_DATA_ON_NONRPF, this);
132  host->subscribe(NF_IPv4_MCAST_REGISTERED, this);
133  host->subscribe(NF_IPv4_MCAST_UNREGISTERED, this);
134  host->subscribe(NF_PIM_NEIGHBOR_ADDED, this);
135  host->subscribe(NF_PIM_NEIGHBOR_DELETED, this);
136  host->subscribe(NF_PIM_NEIGHBOR_CHANGED, this);
137  }
138 
139  return done;
140 }
bool isEnabled
Definition: PIMBase.h:164
bool isUnspecified() const
True if all four address bytes are zero.
Definition: IPv4Address.h:176
simsignal_t NF_IPv4_DATA_ON_RPF
Definition: NotifierConsts.cc:74
simsignal_t NF_IPv4_MCAST_UNREGISTERED
Definition: NotifierConsts.cc:68
simsignal_t NF_PIM_NEIGHBOR_ADDED
Definition: NotifierConsts.cc:81
simsignal_t NF_PIM_NEIGHBOR_CHANGED
Definition: NotifierConsts.cc:83
simsignal_t NF_IPv4_NEW_MULTICAST
Definition: NotifierConsts.cc:70
cModule * findContainingNode(const cModule *from)
Find the node containing the given module.
Definition: ModuleAccess.cc:56
simsignal_t NF_IPv4_MCAST_REGISTERED
Definition: NotifierConsts.cc:67
IPv4Address rpAddr
Definition: PIMSM.h:206
virtual bool handleNodeStart(IDoneCallback *doneCallback) override
Definition: PIMBase.cc:94
simsignal_t NF_IPv4_MDATA_REGISTER
Definition: NotifierConsts.cc:77
simsignal_t NF_IPv4_DATA_ON_NONRPF
Definition: NotifierConsts.cc:73
simsignal_t NF_PIM_NEIGHBOR_DELETED
Definition: NotifierConsts.cc:82
bool inet::PIMSM::IamDR ( InterfaceEntry ie)
private
1695 {
1696  PIMInterface *pimInterface = pimIft->getInterfaceById(ie->getInterfaceId());
1697  ASSERT(pimInterface);
1698  IPv4Address drAddress = pimInterface->getDRAddress();
1699  return drAddress.isUnspecified() || drAddress == ie->ipv4Data()->getIPAddress();
1700 }
PIMInterfaceTable * pimIft
Definition: PIMBase.h:160
virtual PIMInterface * getInterfaceById(int interfaceId)
Definition: PIMInterfaceTable.cc:116
void inet::PIMSM::iAmDRHasChanged ( InterfaceEntry ie,
bool  iAmDR 
)
private

Referenced by updateDesignatedRouterAddress().

1370 {
1371  // TODO
1372 }
bool inet::PIMSM::IamRP ( IPv4Address  rpAddr)
inlineprivate

Referenced by addNewRouteG(), and processExpiryTimer().

305 { return rt->isLocalAddress(rpAddr); }
virtual bool isLocalAddress(const IPv4Address &dest) const =0
Checks if the address is a local one, i.e.
IPv4Address rpAddr
Definition: PIMSM.h:206
IIPv4RoutingTable * rt
Definition: PIMBase.h:158
void inet::PIMSM::initialize ( int  stage)
overrideprotectedvirtual

Reimplemented from inet::PIMBase.

93 {
94  PIMBase::initialize(stage);
95 
96  if (stage == INITSTAGE_LOCAL) {
97  const char *rp = par("RP");
98  if (rp && *rp)
99  rpAddr = IPv4Address(rp);
100 
101  joinPrunePeriod = par("joinPrunePeriod");
102  defaultOverrideInterval = par("defaultOverrideInterval");
103  defaultPropagationDelay = par("defaultPropagationDelay");
104  keepAlivePeriod = par("keepAlivePeriod");
105  rpKeepAlivePeriod = par("rpKeepAlivePeriod");
106  registerSuppressionTime = par("registerSuppressionTime");
107  registerProbeTime = par("registerProbeTime");
108  assertTime = par("assertTime");
109  assertOverrideInterval = par("assertOverrideInterval");
110 
111  WATCH_PTRMAP(gRoutes);
112  WATCH_PTRMAP(sgRoutes);
113  }
114 }
RoutingTable gRoutes
Definition: PIMSM.h:228
double rpKeepAlivePeriod
Definition: PIMSM.h:211
RoutingTable sgRoutes
Definition: PIMSM.h:229
virtual void initialize(int stage) override
Definition: PIMBase.cc:72
double assertTime
Definition: PIMSM.h:214
double registerProbeTime
Definition: PIMSM.h:213
double joinPrunePeriod
Definition: PIMSM.h:207
Local initializations.
Definition: InitStages.h:35
IPv4Address rpAddr
Definition: PIMSM.h:206
double defaultPropagationDelay
Definition: PIMSM.h:209
double defaultOverrideInterval
Definition: PIMSM.h:208
double keepAlivePeriod
Definition: PIMSM.h:210
double assertOverrideInterval
Definition: PIMSM.h:215
double registerSuppressionTime
Definition: PIMSM.h:212
void inet::PIMSM::joinDesiredChanged ( Route route)
private

Referenced by updateJoinDesired().

1309 {
1310  if (route->type == G) {
1311  Route *routeG = route;
1312 
1313  if (routeG->isFlagSet(Route::PRUNED) && routeG->joinDesired()) {
1314  //
1315  // Upstream (*,G) State Machine; event: JoinDesired(S,G) -> TRUE
1316  //
1317  routeG->clearFlag(Route::PRUNED);
1318  if (routeG->upstreamInterface) {
1319  sendPIMJoin(routeG->group, routeG->rpAddr, routeG->upstreamInterface->rpfNeighbor(), G);
1320  routeG->startJoinTimer(joinPrunePeriod);
1321  }
1322  }
1323  else if (!routeG->isFlagSet(Route::PRUNED) && !routeG->joinDesired()) {
1324  //
1325  // Upstream (*,G) State Machine; event: JoinDesired(S,G) -> FALSE
1326  //
1327  routeG->setFlags(Route::PRUNED);
1328  cancelAndDeleteTimer(routeG->joinTimer);
1329  if (routeG->upstreamInterface)
1330  sendPIMPrune(routeG->group, routeG->rpAddr, routeG->upstreamInterface->rpfNeighbor(), G);
1331  }
1332  }
1333  else if (route->type == SG) {
1334  Route *routeSG = route;
1335 
1336  if (routeSG->isFlagSet(Route::PRUNED) && routeSG->joinDesired()) {
1337  //
1338  // Upstream (S,G) State Machine; event: JoinDesired(S,G) -> TRUE
1339  //
1340  routeSG->clearFlag(Route::PRUNED);
1341  if (!routeSG->isSourceDirectlyConnected()) {
1342  sendPIMJoin(routeSG->group, routeSG->source, routeSG->upstreamInterface->rpfNeighbor(), SG);
1343  routeSG->startJoinTimer(joinPrunePeriod);
1344  }
1345  }
1346  else if (!routeSG->isFlagSet(Route::PRUNED) && !route->joinDesired()) {
1347  //
1348  // Upstream (S,G) State Machine; event: JoinDesired(S,G) -> FALSE
1349  //
1350 
1351  // The upstream (S,G) state machine transitions to NotJoined
1352  // state. Send Prune(S,G) to the appropriate upstream neighbor,
1353  // which is RPF'(S,G). Cancel the Join Timer (JT), and set
1354  // SPTbit(S,G) to FALSE.
1355  routeSG->setFlags(Route::PRUNED);
1356  routeSG->clearFlag(Route::SPT_BIT);
1357  cancelAndDeleteTimer(routeSG->joinTimer);
1358  if (!routeSG->isSourceDirectlyConnected())
1359  sendPIMPrune(routeSG->group, routeSG->source, routeSG->upstreamInterface->rpfNeighbor(), SG);
1360  }
1361  }
1362 }
void sendPIMPrune(IPv4Address group, IPv4Address source, IPv4Address upstreamNeighbor, RouteType JPtype)
Definition: PIMSM.cc:1411
void sendPIMJoin(IPv4Address group, IPv4Address source, IPv4Address upstreamNeighbor, RouteType JPtype)
Definition: PIMSM.cc:1378
Definition: PIMSM.h:141
Definition: PIMSM.h:149
Definition: PIMSM.h:151
double joinPrunePeriod
Definition: PIMSM.h:207
void cancelAndDeleteTimer(cMessage *&timer)
Definition: PIMSM.cc:1922
Definition: PIMSM.h:140
double inet::PIMSM::joinPruneHoldTime ( )
inlineprivate

Referenced by sendPIMJoin(), and sendPIMPrune().

293 { return 3.5 * joinPrunePeriod; } // Holdtime in Join/Prune messages
double joinPrunePeriod
Definition: PIMSM.h:207
double inet::PIMSM::joinPruneOverrideInterval ( )
inlineprivate

Referenced by processPruneG(), and processPruneSG().

double effectivePropagationDelay()
Definition: PIMSM.h:294
double effectiveOverrideInterval()
Definition: PIMSM.h:295
void inet::PIMSM::multicastPacketArrivedOnNonRpfInterface ( Route route,
int  interfaceId 
)
private

Referenced by receiveSignal().

1246 {
1247  if (route->type == G || route->type == SG) {
1248  //
1249  // (S,G) Assert State Machine; event: An (S,G) data packet arrives on interface I
1250  // OR
1251  // (*,G) Assert State Machine; event: A data packet destined for G arrives on interface I
1252  //
1253  DownstreamInterface *downstream = route->findDownstreamInterfaceByInterfaceId(interfaceId);
1254  if (downstream && downstream->couldAssert() && downstream->assertState == Interface::NO_ASSERT_INFO) {
1255  // An (S,G) data packet arrived on an downstream interface that
1256  // is in our (S,G) or (*,G) outgoing interface list. We optimistically
1257  // assume that we will be the assert winner for this (S,G) or (*,G), and
1258  // so we transition to the "I am Assert Winner" state and perform
1259  // Actions A1 (below), which will initiate the assert negotiation
1260  // for (S,G) or (*,G).
1261  downstream->assertState = Interface::I_WON_ASSERT;
1262  downstream->winnerMetric = route->metric.setAddress(downstream->ie->ipv4Data()->getIPAddress());
1263  sendPIMAssert(route->source, route->group, downstream->winnerMetric, downstream->ie, route->type == G);
1264  downstream->startAssertTimer(assertTime - assertOverrideInterval);
1265  }
1266  else if (route->type == SG && (!downstream || downstream->assertState == Interface::NO_ASSERT_INFO)) {
1267  // When in NO_ASSERT_INFO state before and after consideration of the received message,
1268  // then call (*,G) assert processing.
1269  Route *routeG = findRouteG(route->group);
1270  if (routeG)
1271  multicastPacketArrivedOnNonRpfInterface(routeG, interfaceId);
1272  }
1273  }
1274 }
Route * findRouteG(IPv4Address group)
Definition: PIMSM.cc:1896
Definition: PIMSM.h:141
void multicastPacketArrivedOnNonRpfInterface(Route *route, int interfaceId)
Definition: PIMSM.cc:1245
double assertTime
Definition: PIMSM.h:214
void sendPIMAssert(IPv4Address source, IPv4Address group, AssertMetric metric, InterfaceEntry *ie, bool rptBit)
Definition: PIMSM.cc:1516
double assertOverrideInterval
Definition: PIMSM.h:215
Definition: PIMSM.h:140
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.

Referenced by receiveSignal().

1195 {
1196  if (route->type == SG) { // (S,G) route
1197  // set KeepAlive timer
1198  if ( /*DirectlyConnected(route->source) ||*/
1199  (!route->isFlagSet(Route::PRUNED) && !route->isInheritedOlistNull()))
1200  {
1201  EV_DETAIL << "Data arrived on RPF interface, restarting KAT(" << route->source << ", " << route->group << ") timer.\n";
1202 
1203  if (!route->keepAliveTimer)
1204  route->startKeepAliveTimer(keepAlivePeriod);
1205  else
1206  restartTimer(route->keepAliveTimer, keepAlivePeriod);
1207  }
1208 
1209  // Update SPT bit
1210 
1211  /* TODO
1212  void
1213  Update_SPTbit(S,G,iif) {
1214  if ( iif == RPF_interface(S)
1215  AND JoinDesired(S,G) == TRUE
1216  AND ( DirectlyConnected(S) == TRUE
1217  OR RPF_interface(S) != RPF_interface(RP(G))
1218  OR inherited_olist(S,G,rpt) == nullptr
1219  OR ( ( RPF'(S,G) == RPF'(*,G) ) AND
1220  ( RPF'(S,G) != nullptr ) )
1221  OR ( I_Am_Assert_Loser(S,G,iif) ) {
1222  Set SPTbit(S,G) to TRUE
1223  }
1224  }
1225  */
1226  route->setFlags(Route::SPT_BIT);
1227  }
1228 
1229  // check switch from RP tree to the SPT
1230  if (route->isFlagSet(Route::SPT_BIT)) {
1231  /*
1232  void
1233  CheckSwitchToSpt(S,G) {
1234  if ( ( pim_include(*,G) (-) pim_exclude(S,G)
1235  (+) pim_include(S,G) != nullptr )
1236  AND SwitchToSptDesired(S,G) ) {
1237  # Note: Restarting the KAT will result in the SPT switch
1238  set KeepaliveTimer(S,G) to Keepalive_Period
1239  }
1240  }
1241  */
1242  }
1243 }
Definition: PIMSM.h:141
Definition: PIMSM.h:149
Definition: PIMSM.h:151
void restartTimer(cMessage *timer, double interval)
Definition: PIMSM.cc:1928
double keepAlivePeriod
Definition: PIMSM.h:210
void inet::PIMSM::multicastPacketForwarded ( IPv4Datagram datagram)
private

Referenced by receiveSignal().

1277 {
1278  IPv4Address source = datagram->getSrcAddress();
1279  IPv4Address group = datagram->getDestAddress();
1280 
1281  Route *routeSG = findRouteSG(source, group);
1282  if (!routeSG || !routeSG->isFlagSet(Route::REGISTER) || !routeSG->isFlagSet(Route::PRUNED))
1283  return;
1284 
1285  // send Register message to RP
1286 
1287  InterfaceEntry *interfaceTowardRP = rt->getInterfaceForDestAddr(routeSG->rpAddr);
1288 
1289  if (routeSG->registerState == Route::RS_JOIN) {
1290  // refresh KAT timer
1291  if (routeSG->keepAliveTimer) {
1292  EV << " (S,G) KAT timer refresh" << endl;
1293  restartTimer(routeSG->keepAliveTimer, KAT);
1294  }
1295 
1296  sendPIMRegister(datagram, routeSG->rpAddr, interfaceTowardRP->getInterfaceId());
1297  }
1298 }
Definition: PIMSM.h:173
virtual InterfaceEntry * getInterfaceForDestAddr(const IPv4Address &dest) const =0
Convenience function based on findBestMatchingRoute().
Route * findRouteSG(IPv4Address source, IPv4Address group)
Definition: PIMSM.cc:1903
Definition: PIMSM.h:149
Definition: PIMSM.h:150
IIPv4RoutingTable * rt
Definition: PIMBase.h:158
void restartTimer(cMessage *timer, double interval)
Definition: PIMSM.cc:1928
void sendPIMRegister(IPv4Datagram *datagram, IPv4Address dest, int outInterfaceId)
Definition: PIMSM.cc:1474
#define KAT
Keep alive timer, if RPT is disconnect.
Definition: PIMSM.h:30
void inet::PIMSM::multicastReceiverAdded ( InterfaceEntry ie,
IPv4Address  group 
)
private

Referenced by receiveSignal().

1176 {
1177  EV_DETAIL << "Multicast receiver added for group " << group << " on interface '" << ie->getName() << "'.\n";
1178 
1179  Route *routeG = findRouteG(group);
1180  if (!routeG)
1181  routeG = addNewRouteG(group, Route::PRUNED);
1182 
1183  DownstreamInterface *downstream = routeG->getDownstreamInterfaceByInterfaceId(ie->getInterfaceId());
1184  downstream->setLocalReceiverInclude(true);
1185 
1186  updateJoinDesired(routeG);
1187 }
Route * findRouteG(IPv4Address group)
Definition: PIMSM.cc:1896
Definition: PIMSM.h:149
Route * addNewRouteG(IPv4Address group, int flags)
Definition: PIMSM.cc:1761
void updateJoinDesired(Route *route)
Definition: PIMSM.cc:1578
void inet::PIMSM::multicastReceiverRemoved ( InterfaceEntry ie,
IPv4Address  group 
)
private

Referenced by receiveSignal().

1164 {
1165  EV_DETAIL << "No more receiver for group " << group << " on interface '" << ie->getName() << "'.\n";
1166 
1167  Route *routeG = findRouteG(group);
1168  if (routeG) {
1169  DownstreamInterface *downstream = routeG->getDownstreamInterfaceByInterfaceId(ie->getInterfaceId());
1170  downstream->setLocalReceiverInclude(false);
1171  updateJoinDesired(routeG);
1172  }
1173 }
Route * findRouteG(IPv4Address group)
Definition: PIMSM.cc:1896
void updateJoinDesired(Route *route)
Definition: PIMSM.cc:1578
virtual int inet::PIMSM::numInitStages ( ) const
inlineoverrideprotectedvirtual

Reimplemented from inet::PIMBase.

236 { return NUM_INIT_STAGES; }
The number of initialization stages.
Definition: InitStages.h:116
void inet::PIMSM::processAssertG ( PimsmInterface interface,
const AssertMetric receivedMetric 
)
private

Referenced by processAssertPacket().

828 {
829  Route *routeG = interface->route();
830  AssertMetric myMetric = interface->couldAssert() ?
831  routeG->metric.setAddress(interface->ie->ipv4Data()->getIPAddress()) :
833 
834  // A "preferred assert" is one with a better metric than the current winner.
835  bool isPreferredAssert = receivedMetric < interface->winnerMetric;
836 
837  // An "acceptable assert" is one that has a better metric than my_assert_metric(S,G,I).
838  // An assert is never considered acceptable if its metric is infinite.
839  bool isAcceptableAssert = receivedMetric < myMetric;
840 
841  // An "inferior assert" is one with a worse metric than my_assert_metric(S,G,I).
842  // An assert is never considered inferior if my_assert_metric(S,G,I) is infinite.
843  bool isInferiorAssert = myMetric < receivedMetric;
844 
845  if (interface->assertState == Interface::NO_ASSERT_INFO) {
846  if (isInferiorAssert && receivedMetric.rptBit && interface->couldAssert()) {
847  // An Inferior (*,G) assert is received for G on Interface I. If
848  // CouldAssert(*,G,I) is TRUE, then I is our downstream
849  // interface, and we have (*,G) forwarding state on this
850  // interface, so we should be the assert winner. We transition
851  // to the "I am Assert Winner" state and perform Actions:
852  interface->assertState = Interface::I_WON_ASSERT;
853  sendPIMAssert(IPv4Address::UNSPECIFIED_ADDRESS, routeG->group, myMetric, interface->ie, true);
854  interface->startAssertTimer(assertTime - assertOverrideInterval);
855  interface->winnerMetric = myMetric;
856  }
857  else if (isAcceptableAssert && receivedMetric.rptBit && interface->assertTrackingDesired()) {
858  // We're interested in (*,G) Asserts, either because I is a
859  // downstream interface for which we have (*,G) forwarding state,
860  // or because I is the upstream interface for RP(G) and we have
861  // (*,G) forwarding state. We get a (*,G) Assert that has a
862  // better metric than our own, so we do not win the Assert. We
863  // transition to "I am Assert Loser" and perform Actions:
864  interface->assertState = Interface::I_LOST_ASSERT;
865  interface->winnerMetric = receivedMetric;
866  interface->startAssertTimer(assertTime);
867  }
868  }
869  else if (interface->assertState == Interface::I_WON_ASSERT) {
870  if (isInferiorAssert) {
871  // We receive a (*,G) assert that has a worse metric than our
872  // own. Whoever sent the assert has lost, and so we resend a
873  // (*,G) Assert and restart the Assert Timer (Actions A3 below).
874  sendPIMAssert(IPv4Address::UNSPECIFIED_ADDRESS, routeG->group, myMetric, interface->ie, true);
875  restartTimer(interface->assertTimer, assertTime - assertOverrideInterval);
876  }
877  else if (isPreferredAssert) {
878  // We receive a (*,G) assert that has a better metric than our
879  // own. We transition to "I am Assert Loser" state and perform
880  // Actions A2 (below).
881  interface->assertState = Interface::I_LOST_ASSERT;
882  interface->winnerMetric = receivedMetric;
883  restartTimer(interface->assertTimer, assertTime);
884  }
885  }
886  else if (interface->assertState == Interface::I_LOST_ASSERT) {
887  if (isPreferredAssert && receivedMetric.rptBit) {
888  // We receive a (*,G) assert that is better than that of the
889  // current assert winner. We stay in Loser state and perform
890  // Actions A2 below.
891  interface->winnerMetric = receivedMetric;
892  restartTimer(interface->assertTimer, assertTime);
893  }
894  else if (isAcceptableAssert && receivedMetric.address == interface->winnerMetric.address && receivedMetric.rptBit) {
895  // We receive a (*,G) assert from the current assert winner that
896  // is better than our own metric for this group (although the
897  // metric may be worse than the winner's previous metric). We
898  // stay in Loser state and perform Actions A2 below.
899  //interface->winnerAddress = ...;
900  interface->winnerMetric = receivedMetric;
901  restartTimer(interface->assertTimer, assertTime);
902  }
903  else if (isInferiorAssert /*or AssertCancel*/ && receivedMetric.address == interface->winnerMetric.address) {
904  // We receive an assert from the current assert winner that is
905  // worse than our own metric for this group (typically because
906  // the winner's metric became worse or is now an assert cancel).
907  // We transition to NoInfo state, delete this (*,G) assert state
908  // (Actions A5), and allow the normal PIM Join/Prune mechanisms
909  // to operate. Usually, we will eventually re-assert and win
910  // when data packets for G have started flowing again.
911  interface->deleteAssertInfo();
912  }
913  }
914 }
double assertTime
Definition: PIMSM.h:214
static const AssertMetric PIM_INFINITE
Definition: PIMBase.h:48
void sendPIMAssert(IPv4Address source, IPv4Address group, AssertMetric metric, InterfaceEntry *ie, bool rptBit)
Definition: PIMSM.cc:1516
static const IPv4Address UNSPECIFIED_ADDRESS
0.0.0.0
Definition: IPv4Address.h:102
void restartTimer(cMessage *timer, double interval)
Definition: PIMSM.cc:1928
double assertOverrideInterval
Definition: PIMSM.h:215
void inet::PIMSM::processAssertPacket ( PIMAssert pkt)
private

Referenced by handleMessageWhenUp().

675 {
676  IPv4ControlInfo *ctrlInfo = check_and_cast<IPv4ControlInfo *>(pkt->getControlInfo());
677  int incomingInterfaceId = ctrlInfo->getInterfaceId();
678  IPv4Address source = pkt->getSourceAddress();
679  IPv4Address group = pkt->getGroupAddress();
680  AssertMetric receivedMetric = AssertMetric(pkt->getR(), pkt->getMetricPreference(), pkt->getMetric(), ctrlInfo->getSrcAddr());
681 
682  EV_INFO << "Received Assert(" << (source.isUnspecified() ? "*" : source.str()) << ", " << group << ")"
683  << " packet on interface '" << ift->getInterfaceById(incomingInterfaceId)->getName() << "'.\n";
684 
685  emit(rcvdAssertPkSignal, pkt);
686 
687  if (!source.isUnspecified() && !receivedMetric.rptBit) {
688  Route *routeSG = findRouteSG(source, group);
689  if (routeSG) {
690  PimsmInterface *incomingInterface = routeSG->upstreamInterface->getInterfaceId() == incomingInterfaceId ?
691  static_cast<PimsmInterface *>(routeSG->upstreamInterface) :
692  static_cast<PimsmInterface *>(routeSG->getDownstreamInterfaceByInterfaceId(incomingInterfaceId));
693  ASSERT(incomingInterface);
694 
695  Interface::AssertState stateBefore = incomingInterface->assertState;
696  processAssertSG(incomingInterface, receivedMetric);
697 
698  if (stateBefore != Interface::NO_ASSERT_INFO || incomingInterface->assertState != Interface::NO_ASSERT_INFO) {
699  // processed by SG
700  delete pkt;
701  return;
702  }
703  }
704  }
705 
706  // process (*,G) asserts and (S,G) asserts for which there is no assert state in (S,G) routes
707  Route *routeG = findRouteG(group);
708  if (routeG) {
709  PimsmInterface *incomingInterface = routeG->upstreamInterface->getInterfaceId() == incomingInterfaceId ?
710  static_cast<PimsmInterface *>(routeG->upstreamInterface) :
711  static_cast<PimsmInterface *>(routeG->getDownstreamInterfaceByInterfaceId(incomingInterfaceId));
712  ASSERT(incomingInterface);
713  processAssertG(incomingInterface, receivedMetric);
714  }
715 
716  delete pkt;
717 }
virtual InterfaceEntry * getInterfaceById(int id) const =0
Returns an interface by its Id.
Route * findRouteG(IPv4Address group)
Definition: PIMSM.cc:1896
Route * findRouteSG(IPv4Address source, IPv4Address group)
Definition: PIMSM.cc:1903
void processAssertG(PimsmInterface *interface, const AssertMetric &receivedMetric)
Definition: PIMSM.cc:827
AssertState
Definition: PIMBase.h:87
IInterfaceTable * ift
Definition: PIMBase.h:159
static simsignal_t rcvdAssertPkSignal
Definition: PIMSM.h:225
void processAssertSG(PimsmInterface *interface, const AssertMetric &receivedMetric)
Definition: PIMSM.cc:719
void inet::PIMSM::processAssertSG ( PimsmInterface interface,
const AssertMetric receivedMetric 
)
private

Referenced by processAssertPacket().

720 {
721  Route *routeSG = interface->route();
722  AssertMetric myMetric = interface->couldAssert() ? // XXX check routeG metric too
723  routeSG->metric.setAddress(interface->ie->ipv4Data()->getIPAddress()) :
725 
726  // A "preferred assert" is one with a better metric than the current winner.
727  bool isPreferredAssert = receivedMetric < interface->winnerMetric;
728 
729  // An "acceptable assert" is one that has a better metric than my_assert_metric(S,G,I).
730  // An assert is never considered acceptable if its metric is infinite.
731  bool isAcceptableAssert = receivedMetric < myMetric;
732 
733  // An "inferior assert" is one with a worse metric than my_assert_metric(S,G,I).
734  // An assert is never considered inferior if my_assert_metric(S,G,I) is infinite.
735  bool isInferiorAssert = myMetric < receivedMetric;
736 
737  if (interface->assertState == Interface::NO_ASSERT_INFO) {
738  if (isInferiorAssert && !receivedMetric.rptBit && interface->couldAssert()) {
739  // An assert is received for (S,G) with the RPT bit cleared that
740  // is inferior to our own assert metric. The RPT bit cleared
741  // indicates that the sender of the assert had (S,G) forwarding
742  // state on this interface. If the assert is inferior to our
743  // metric, then we must also have (S,G) forwarding state (i.e.,
744  // CouldAssert(S,G,I)==TRUE) as (S,G) asserts beat (*,G) asserts,
745  // and so we should be the assert winner. We transition to the
746  // "I am Assert Winner" state and perform Actions A1 (below).
747  interface->assertState = Interface::I_WON_ASSERT;
748  interface->winnerMetric = myMetric;
749  sendPIMAssert(routeSG->source, routeSG->group, myMetric, interface->ie, false);
750  interface->startAssertTimer(assertTime - assertOverrideInterval);
751  }
752  else if (receivedMetric.rptBit && interface->couldAssert()) {
753  // An assert is received for (S,G) on I with the RPT bit set
754  // (it's a (*,G) assert). CouldAssert(S,G,I) is TRUE only if we
755  // have (S,G) forwarding state on this interface, so we should be
756  // the assert winner. We transition to the "I am Assert Winner"
757  // state and perform Actions A1 (below).
758  interface->assertState = Interface::I_WON_ASSERT;
759  interface->winnerMetric = myMetric;
760  sendPIMAssert(routeSG->source, routeSG->group, myMetric, interface->ie, false);
761  interface->startAssertTimer(assertTime - assertOverrideInterval);
762  }
763  else if (isAcceptableAssert && !receivedMetric.rptBit && interface->assertTrackingDesired()) {
764  // We're interested in (S,G) Asserts, either because I is a
765  // downstream interface for which we have (S,G) or (*,G)
766  // forwarding state, or because I is the upstream interface for S
767  // and we have (S,G) forwarding state. The received assert has a
768  // better metric than our own, so we do not win the Assert. We
769  // transition to "I am Assert Loser" and perform Actions A6
770  // (below).
771  interface->assertState = Interface::I_LOST_ASSERT;
772  interface->winnerMetric = receivedMetric;
773  interface->startAssertTimer(assertTime);
774  // TODO If (I is RPF_interface(S)) AND (UpstreamJPState(S,G) == true)
775  // set SPTbit(S,G) to TRUE.
776  }
777  }
778  else if (interface->assertState == Interface::I_WON_ASSERT) {
779  if (isInferiorAssert) {
780  // We receive an (S,G) assert or (*,G) assert mentioning S that
781  // has a worse metric than our own. Whoever sent the assert is
782  // in error, and so we resend an (S,G) Assert and restart the
783  // Assert Timer (Actions A3 below).
784  sendPIMAssert(routeSG->source, routeSG->group, myMetric, interface->ie, false);
785  restartTimer(interface->assertTimer, assertTime - assertOverrideInterval);
786  }
787  else if (isPreferredAssert) {
788  // We receive an (S,G) assert that has a better metric than our
789  // own. We transition to "I am Assert Loser" state and perform
790  // Actions A2 (below). Note that this may affect the value of
791  // JoinDesired(S,G) and PruneDesired(S,G,rpt), which could cause
792  // transitions in the upstream (S,G) or (S,G,rpt) state machines.
793  interface->assertState = Interface::I_LOST_ASSERT;
794  interface->winnerMetric = receivedMetric;
795  restartTimer(interface->assertTimer, assertTime);
796  }
797  }
798  else if (interface->assertState == Interface::I_LOST_ASSERT) {
799  if (isPreferredAssert) {
800  // We receive an assert that is better than that of the current
801  // assert winner. We stay in Loser state and perform Actions A2
802  // below.
803  interface->winnerMetric = receivedMetric;
804  restartTimer(interface->assertTimer, assertTime);
805  }
806  else if (isAcceptableAssert && !receivedMetric.rptBit && receivedMetric.address == interface->winnerMetric.address) {
807  // We receive an assert from the current assert winner that is
808  // better than our own metric for this (S,G) (although the metric
809  // may be worse than the winner's previous metric). We stay in
810  // Loser state and perform Actions A2 below.
811  interface->winnerMetric = receivedMetric;
812  restartTimer(interface->assertTimer, assertTime);
813  }
814  else if (isInferiorAssert /* or AssertCancel */ && receivedMetric.address == interface->winnerMetric.address) {
815  // We receive an assert from the current assert winner that is
816  // worse than our own metric for this group (typically, because
817  // the winner's metric became worse or because it is an assert
818  // cancel). We transition to NoInfo state, deleting the (S,G)
819  // assert information and allowing the normal PIM Join/Prune
820  // mechanisms to operate. Usually, we will eventually re-assert
821  // and win when data packets from S have started flowing again.
822  interface->deleteAssertInfo();
823  }
824  }
825 }
double assertTime
Definition: PIMSM.h:214
static const AssertMetric PIM_INFINITE
Definition: PIMBase.h:48
void sendPIMAssert(IPv4Address source, IPv4Address group, AssertMetric metric, InterfaceEntry *ie, bool rptBit)
Definition: PIMSM.cc:1516
void restartTimer(cMessage *timer, double interval)
Definition: PIMSM.cc:1928
double assertOverrideInterval
Definition: PIMSM.h:215
void inet::PIMSM::processAssertTimer ( cMessage *  timer)
private

Referenced by handleMessageWhenUp().

1068 {
1069  PimsmInterface *interfaceData = static_cast<PimsmInterface *>(timer->getContextPointer());
1070  ASSERT(timer == interfaceData->assertTimer);
1071  ASSERT(interfaceData->assertState != Interface::NO_ASSERT_INFO);
1072 
1073  Route *route = interfaceData->route();
1074  if (route->type == SG || route->type == G) {
1075  //
1076  // (S,G) Assert State Machine; event: AT(S,G,I) expires OR
1077  // (*,G) Assert State Machine; event: AT(*,G,I) expires
1078  //
1079  EV_DETAIL << "AssertTimer(" << (route->type == G ? "*" : route->source.str()) << ", "
1080  << route->group << ", " << interfaceData->ie->getName() << ") has expired.\n";
1081 
1082  if (interfaceData->assertState == Interface::I_WON_ASSERT) {
1083  // The (S,G) or (*,G) Assert Timer expires. As we're in the Winner state,
1084  // we must still have (S,G) or (*,G) forwarding state that is actively
1085  // being kept alive. We resend the (S,G) or (*,G) Assert and restart the
1086  // Assert Timer. Note that the assert
1087  // winner's Assert Timer is engineered to expire shortly before
1088  // timers on assert losers; this prevents unnecessary thrashing
1089  // of the forwarder and periodic flooding of duplicate packets.
1090  sendPIMAssert(route->source, route->group, route->metric, interfaceData->ie, route->type == G);
1091  restartTimer(interfaceData->assertTimer, assertTime - assertOverrideInterval);
1092  return;
1093  }
1094  else if (interfaceData->assertState == Interface::I_LOST_ASSERT) {
1095  // The (S,G) or (*,G) Assert Timer expires. We transition to NoInfo
1096  // state, deleting the (S,G) or (*,G) assert information.
1097  EV_DEBUG << "Going into NO_ASSERT_INFO state.\n";
1098  interfaceData->deleteAssertInfo(); // deleted timer
1099  return;
1100  }
1101  }
1102 
1103  delete timer;
1104 }
Definition: PIMSM.h:141
double assertTime
Definition: PIMSM.h:214
void sendPIMAssert(IPv4Address source, IPv4Address group, AssertMetric metric, InterfaceEntry *ie, bool rptBit)
Definition: PIMSM.cc:1516
void restartTimer(cMessage *timer, double interval)
Definition: PIMSM.cc:1928
double assertOverrideInterval
Definition: PIMSM.h:215
Definition: PIMSM.h:140
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.

Referenced by handleMessageWhenUp().

957 {
958  EV << "pimSM::processExpiryTimer: " << endl;
959 
960  PimsmInterface *interface = static_cast<PimsmInterface *>(timer->getContextPointer());
961  Route *route = interface->route();
962 
963  if (interface != route->upstreamInterface) {
964  //
965  // Downstream Join/Prune State Machine; event: ET expires
966  //
967  DownstreamInterface *downstream = check_and_cast<DownstreamInterface *>(interface);
968  downstream->joinPruneState = DownstreamInterface::NO_INFO;
969  cancelAndDeleteTimer(downstream->prunePendingTimer);
970  downstream->expiryTimer = nullptr;
971  delete timer;
972 
973  // upstream state machine
974  if (route->isInheritedOlistNull()) {
975  route->setFlags(Route::PRUNED);
976  if (route->type == G && !IamRP(route->rpAddr))
977  sendPIMPrune(route->group, route->rpAddr, route->upstreamInterface->rpfNeighbor(), G);
978  else if (route->type == SG)
979  sendPIMPrune(route->group, route->source, route->upstreamInterface->rpfNeighbor(), SG);
980 
981  cancelAndDeleteTimer(route->joinTimer);
982  }
983  }
984  if (route->upstreamInterface->expiryTimer && interface == route->upstreamInterface) {
985  for (unsigned i = 0; i < route->downstreamInterfaces.size(); ) {
986  if (route->downstreamInterfaces[i]->expiryTimer)
987  route->removeDownstreamInterface(i);
988  else
989  i++;
990  }
991  if (IamRP(rpAddr) && route->type == G) {
992  EV << "ET for (*,G) route on RP expires - go to stopped" << endl;
993  cancelAndDeleteTimer(route->upstreamInterface->expiryTimer);
994  }
995  else
996  deleteMulticastRoute(route);
997  }
998 }
void sendPIMPrune(IPv4Address group, IPv4Address source, IPv4Address upstreamNeighbor, RouteType JPtype)
Definition: PIMSM.cc:1411
Definition: PIMSM.h:141
Definition: PIMSM.h:149
IPv4Address rpAddr
Definition: PIMSM.h:206
void cancelAndDeleteTimer(cMessage *&timer)
Definition: PIMSM.cc:1922
bool IamRP(IPv4Address rpAddr)
Definition: PIMSM.h:305
Definition: PIMSM.h:140
bool deleteMulticastRoute(Route *route)
Definition: PIMSM.cc:1713
void inet::PIMSM::processJoinG ( IPv4Address  group,
IPv4Address  rp,
IPv4Address  upstreamNeighborField,
int  holdTime,
InterfaceEntry inInterface 
)
private

Referenced by processJoinPrunePacket().

385 {
386  EV_DETAIL << "Processing Join(*," << group << ") received on interface '" << inInterface->getName() << "'.\n";
387 
388  // TODO RP check
389 
390  //
391  // Downstream per-interface (*,G) state machine; event = Receive Join(*,G)
392  //
393 
394  // check UpstreamNeighbor field
395  if (upstreamNeighborField != inInterface->ipv4Data()->getIPAddress())
396  return;
397 
398  bool newRoute = false;
399  Route *routeG = findRouteG(group);
400  if (!routeG) {
401  routeG = addNewRouteG(group, Route::PRUNED);
402  newRoute = true;
403  }
404 
405  DownstreamInterface *downstream = routeG->findDownstreamInterfaceByInterfaceId(inInterface->getInterfaceId());
406 
407  if (downstream) {
408  // A Join(*,G) is received on interface I with its Upstream
409  // Neighbor Address set to the router's primary IP address on I.
410  if (downstream->joinPruneState == DownstreamInterface::NO_INFO) {
411  // The (*,G) downstream state machine on interface I transitions
412  // to the Join state. The Expiry Timer (ET) is started and set
413  // to the HoldTime from the triggering Join/Prune message.
414  downstream->joinPruneState = DownstreamInterface::JOIN;
415  downstream->startExpiryTimer(holdTime);
416  }
417  else if (downstream->joinPruneState == DownstreamInterface::JOIN) {
418  // The (*,G) downstream state machine on interface I remains in
419  // Join state, and the Expiry Timer (ET) is restarted, set to
420  // maximum of its current value and the HoldTime from the
421  // triggering Join/Prune message.
422  if (simTime() + holdTime > downstream->expiryTimer->getArrivalTime())
423  restartTimer(downstream->expiryTimer, holdTime);
424  }
425  else if (downstream->joinPruneState == DownstreamInterface::PRUNE_PENDING) {
426  // The (*,G) downstream state machine on interface I transitions
427  // to the Join state. The Prune-Pending Timer is canceled
428  // (without triggering an expiry event). The Expiry Timer is
429  // restarted, set to maximum of its current value and the
430  // HoldTime from the triggering Join/Prune message.
431  cancelAndDeleteTimer(downstream->prunePendingTimer);
432  if (simTime() + holdTime > downstream->expiryTimer->getArrivalTime())
433  restartTimer(downstream->expiryTimer, holdTime);
434  }
435  }
436 
437  // XXX Join(*,G) messages can affect (S,G,rpt) downstream state machines too
438 
439  // check upstream state transition
440  updateJoinDesired(routeG);
441 
442  if (!newRoute && !routeG->upstreamInterface) { // I am RP
443  routeG->clearFlag(Route::REGISTER);
444  }
445 }
Route * findRouteG(IPv4Address group)
Definition: PIMSM.cc:1896
Definition: PIMSM.h:149
double holdTime
Definition: PIMBase.h:169
void cancelAndDeleteTimer(cMessage *&timer)
Definition: PIMSM.cc:1922
Definition: PIMSM.h:150
Route * addNewRouteG(IPv4Address group, int flags)
Definition: PIMSM.cc:1761
void restartTimer(cMessage *timer, double interval)
Definition: PIMSM.cc:1928
void updateJoinDesired(Route *route)
Definition: PIMSM.cc:1578
void inet::PIMSM::processJoinPrunePacket ( PIMJoinPrune pkt)
private

Referenced by handleMessageWhenUp().

340 {
341  EV_INFO << "Received JoinPrune packet.\n";
342 
343  emit(rcvdJoinPrunePkSignal, pkt);
344 
345  IPv4ControlInfo *ctrl = check_and_cast<IPv4ControlInfo *>(pkt->getControlInfo());
346  InterfaceEntry *inInterface = ift->getInterfaceById(ctrl->getInterfaceId());
347  int holdTime = pkt->getHoldTime();
348  IPv4Address upstreamNeighbor = pkt->getUpstreamNeighborAddress();
349 
350  for (unsigned int i = 0; i < pkt->getJoinPruneGroupsArraySize(); i++) {
351  JoinPruneGroup group = pkt->getJoinPruneGroups(i);
352  IPv4Address groupAddr = group.getGroupAddress();
353 
354  // go through list of joined sources
355  for (unsigned int j = 0; j < group.getJoinedSourceAddressArraySize(); j++) {
356  EncodedAddress& source = group.getJoinedSourceAddress(j);
357  if (source.S) {
358  if (source.W) // (*,G) Join
359  processJoinG(groupAddr, source.IPaddress, upstreamNeighbor, holdTime, inInterface);
360  else if (source.R) // (S,G,rpt) Join
361  processJoinSGrpt(source.IPaddress, groupAddr, upstreamNeighbor, holdTime, inInterface);
362  else // (S,G) Join
363  processJoinSG(source.IPaddress, groupAddr, upstreamNeighbor, holdTime, inInterface);
364  }
365  }
366 
367  // go through list of pruned sources
368  for (unsigned int j = 0; j < group.getPrunedSourceAddressArraySize(); j++) {
369  EncodedAddress& source = group.getPrunedSourceAddress(j);
370  if (source.S) {
371  if (source.W) // (*,G) Prune
372  processPruneG(groupAddr, upstreamNeighbor, inInterface);
373  else if (source.R) // (S,G,rpt) Prune
374  processPruneSGrpt(source.IPaddress, groupAddr, upstreamNeighbor, inInterface);
375  else // (S,G) Prune
376  processPruneSG(source.IPaddress, groupAddr, upstreamNeighbor, inInterface);
377  }
378  }
379  }
380 
381  delete pkt;
382 }
virtual InterfaceEntry * getInterfaceById(int id) const =0
Returns an interface by its Id.
void processPruneSG(IPv4Address source, IPv4Address group, IPv4Address upstreamNeighborField, InterfaceEntry *inInterface)
Definition: PIMSM.cc:540
void processJoinSG(IPv4Address origin, IPv4Address group, IPv4Address upstreamNeighborField, int holdTime, InterfaceEntry *inInterface)
Definition: PIMSM.cc:447
static simsignal_t rcvdJoinPrunePkSignal
Definition: PIMSM.h:223
void processPruneG(IPv4Address multGroup, IPv4Address upstreamNeighborField, InterfaceEntry *inInterface)
Definition: PIMSM.cc:506
IInterfaceTable * ift
Definition: PIMBase.h:159
void processPruneSGrpt(IPv4Address source, IPv4Address group, IPv4Address upstreamNeighborField, InterfaceEntry *inInterface)
Definition: PIMSM.cc:574
double holdTime
Definition: PIMBase.h:169
void processJoinG(IPv4Address group, IPv4Address rp, IPv4Address upstreamNeighborField, int holdTime, InterfaceEntry *inInterface)
Definition: PIMSM.cc:384
void processJoinSGrpt(IPv4Address origin, IPv4Address group, IPv4Address upstreamNeighborField, int holdTime, InterfaceEntry *inInterface)
Definition: PIMSM.cc:501
void inet::PIMSM::processJoinSG ( IPv4Address  origin,
IPv4Address  group,
IPv4Address  upstreamNeighborField,
int  holdTime,
InterfaceEntry inInterface 
)
private

Referenced by processJoinPrunePacket().

448 {
449  EV_DETAIL << "Processing Join(" << source << ", " << group << ") received on interface '" << inInterface->getName() << "'.'n";
450 
451  //
452  // Downstream per-interface (S,G) state machine; event = Receive Join(S,G)
453  //
454 
455  // check UpstreamNeighbor field
456  if (upstreamNeighborField != inInterface->ipv4Data()->getIPAddress())
457  return;
458 
459  Route *routeSG = findRouteSG(source, group);
460  if (!routeSG) { // create (S,G) route between RP and source DR
461  routeSG = addNewRouteSG(source, group, Route::PRUNED);
462  routeSG->startKeepAliveTimer(keepAlivePeriod);
463  }
464 
465  DownstreamInterface *downstream = routeSG->findDownstreamInterfaceByInterfaceId(inInterface->getInterfaceId());
466 
467  if (downstream) {
468  // A Join(S,G) is received on interface I with its Upstream
469  // Neighbor Address set to the router's primary IP address on I.
470  if (downstream->joinPruneState == DownstreamInterface::NO_INFO) {
471  // The (S,G) downstream state machine on interface I transitions
472  // to the Join state. The Expiry Timer (ET) is started and set
473  // to the HoldTime from the triggering Join/Prune message.
474  downstream->joinPruneState = DownstreamInterface::JOIN;
475  downstream->startExpiryTimer(holdTime);
476  }
477  else if (downstream->joinPruneState == DownstreamInterface::JOIN) {
478  // The (S,G) downstream state machine on interface I remains in
479  // Join state, and the Expiry Timer (ET) is restarted, set to
480  // maximum of its current value and the HoldTime from the
481  // triggering Join/Prune message.
482  if (simTime() + holdTime > downstream->expiryTimer->getArrivalTime())
483  restartTimer(downstream->expiryTimer, holdTime);
484  }
485  else if (downstream->joinPruneState == DownstreamInterface::PRUNE_PENDING) {
486  // The (S,G) downstream state machine on interface I transitions
487  // to the Join state. The Prune-Pending Timer is canceled
488  // (without triggering an expiry event). The Expiry Timer is
489  // restarted, set to maximum of its current value and the
490  // HoldTime from the triggering Join/Prune message.
491  cancelAndDeleteTimer(downstream->prunePendingTimer);
492  if (simTime() + holdTime > downstream->expiryTimer->getArrivalTime())
493  restartTimer(downstream->expiryTimer, holdTime);
494  }
495  }
496 
497  // check upstream state transition
498  updateJoinDesired(routeSG);
499 }
Route * findRouteSG(IPv4Address source, IPv4Address group)
Definition: PIMSM.cc:1903
Definition: PIMSM.h:149
double holdTime
Definition: PIMBase.h:169
void cancelAndDeleteTimer(cMessage *&timer)
Definition: PIMSM.cc:1922
Route * addNewRouteSG(IPv4Address source, IPv4Address group, int flags)
Definition: PIMSM.cc:1811
void restartTimer(cMessage *timer, double interval)
Definition: PIMSM.cc:1928
double keepAlivePeriod
Definition: PIMSM.h:210
void updateJoinDesired(Route *route)
Definition: PIMSM.cc:1578
void inet::PIMSM::processJoinSGrpt ( IPv4Address  origin,
IPv4Address  group,
IPv4Address  upstreamNeighborField,
int  holdTime,
InterfaceEntry inInterface 
)
private

Referenced by processJoinPrunePacket().

502 {
503  // TODO
504 }
void inet::PIMSM::processJoinTimer ( cMessage *  timer)
private

Referenced by handleMessageWhenUp().

1001 {
1002  EV << "pimSM::processJoinTimer:" << endl;
1003 
1004  Route *route = static_cast<Route *>(timer->getContextPointer());
1005  ASSERT(timer == route->joinTimer);
1006  IPv4Address joinAddr = route->type == G ? route->rpAddr : route->source;
1007 
1008  if (!route->isInheritedOlistNull()) {
1009  sendPIMJoin(route->group, joinAddr, route->upstreamInterface->nextHop, route->type);
1010  restartTimer(route->joinTimer, joinPrunePeriod);
1011  }
1012  else {
1013  delete timer;
1014  route->joinTimer = nullptr;
1015  }
1016 }
void sendPIMJoin(IPv4Address group, IPv4Address source, IPv4Address upstreamNeighbor, RouteType JPtype)
Definition: PIMSM.cc:1378
double joinPrunePeriod
Definition: PIMSM.h:207
void restartTimer(cMessage *timer, double interval)
Definition: PIMSM.cc:1928
Definition: PIMSM.h:140
void inet::PIMSM::processKeepAliveTimer ( cMessage *  timer)
private

Referenced by handleMessageWhenUp().

921 {
922  EV << "pimSM::processKeepAliveTimer: route will be deleted" << endl;
923  Route *route = static_cast<Route *>(timer->getContextPointer());
924  ASSERT(route->type == SG);
925  ASSERT(timer == route->keepAliveTimer);
926 
927  delete timer;
928  route->keepAliveTimer = nullptr;
929  deleteMulticastRoute(route);
930 }
Definition: PIMSM.h:141
bool deleteMulticastRoute(Route *route)
Definition: PIMSM.cc:1713
void inet::PIMSM::processPruneG ( IPv4Address  multGroup,
IPv4Address  upstreamNeighborField,
InterfaceEntry inInterface 
)
private

Referenced by processJoinPrunePacket().

507 {
508  EV_DETAIL << "Processing Prune(*," << group << ") received on interface '" << inInterface->getName() << "'.\n";
509 
510  //
511  // Downstream per-interface (*,G) state machine; event = Receive Prune(*,G)
512  //
513 
514  // check UpstreamNeighbor field
515  if (upstreamNeighborField != inInterface->ipv4Data()->getIPAddress())
516  return;
517 
518  Route *routeG = findRouteG(group);
519  if (routeG) {
520  DownstreamInterface *downstream = routeG->findDownstreamInterfaceByInterfaceId(inInterface->getInterfaceId());
521  if (downstream && downstream->joinPruneState == DownstreamInterface::JOIN) {
522  // The (*,G) downstream state machine on interface I transitions
523  // to the Prune-Pending state. The Prune-Pending Timer is
524  // started. It is set to the J/P_Override_Interval(I) if the
525  // router has more than one neighbor on that interface;
526  // otherwise, it is set to zero, causing it to expire
527  // immediately.
528  downstream->joinPruneState = DownstreamInterface::PRUNE_PENDING;
529  double pruneOverrideInterval = pimNbt->getNumNeighbors(inInterface->getInterfaceId()) > 1 ?
531  downstream->startPrunePendingTimer(pruneOverrideInterval);
532  }
533  }
534 
535  // check upstream state transition
536  if (routeG)
537  updateJoinDesired(routeG);
538 }
PIMNeighborTable * pimNbt
Definition: PIMBase.h:161
Route * findRouteG(IPv4Address group)
Definition: PIMSM.cc:1896
double joinPruneOverrideInterval()
Definition: PIMSM.h:296
virtual int getNumNeighbors(int interfaceId)
Returns the number of neighbors on the given interface.
Definition: PIMNeighborTable.cc:176
void updateJoinDesired(Route *route)
Definition: PIMSM.cc:1578
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)

Referenced by handleMessageWhenUp().

1023 {
1024  EV << "pimSM::processPrunePendingTimer:" << endl;
1025  DownstreamInterface *downstream = static_cast<DownstreamInterface *>(timer->getContextPointer());
1026  ASSERT(timer == downstream->prunePendingTimer);
1027  ASSERT(downstream->joinPruneState == DownstreamInterface::PRUNE_PENDING);
1028  Route *route = downstream->route();
1029 
1030  if (route->type == G || route->type == SG) {
1031  //
1032  // Downstream (*,G)/(S,G) Join/Prune State Machine; event: PPT expires
1033  //
1034 
1035  // go to NO_INFO state
1036  downstream->joinPruneState = DownstreamInterface::NO_INFO;
1037  cancelAndDeleteTimer(downstream->expiryTimer);
1038  downstream->prunePendingTimer = nullptr;
1039  delete timer;
1040 
1041  // optionally send PruneEcho message
1042  if (pimNbt->getNumNeighbors(downstream->ie->getInterfaceId()) > 1) {
1043  // A PruneEcho is simply a Prune message sent by the
1044  // upstream router on a LAN with its own address in the Upstream
1045  // Neighbor Address field. Its purpose is to add additional
1046  // reliability so that if a Prune that should have been
1047  // overridden by another router is lost locally on the LAN, then
1048  // the PruneEcho may be received and cause the override to happen.
1049  IPv4Address pruneAddr = route->type == G ? route->rpAddr : route->source;
1050  IPv4Address upstreamNeighborField = downstream->ie->ipv4Data()->getIPAddress();
1051  sendPIMPrune(route->group, pruneAddr, upstreamNeighborField, route->type);
1052  }
1053  }
1054  else if (route->type == SGrpt) {
1055  //
1056  // Downstream (S,G,rpt) Join/Prune State Machine; event: PPT expires
1057  //
1058 
1059  // go to PRUNE state
1060  // TODO
1061  }
1062 
1063  // Now check upstream state transitions
1064  updateJoinDesired(route);
1065 }
PIMNeighborTable * pimNbt
Definition: PIMBase.h:161
void sendPIMPrune(IPv4Address group, IPv4Address source, IPv4Address upstreamNeighbor, RouteType JPtype)
Definition: PIMSM.cc:1411
Definition: PIMSM.h:141
Definition: PIMSM.h:142
virtual int getNumNeighbors(int interfaceId)
Returns the number of neighbors on the given interface.
Definition: PIMNeighborTable.cc:176
void cancelAndDeleteTimer(cMessage *&timer)
Definition: PIMSM.cc:1922
Definition: PIMSM.h:140
void updateJoinDesired(Route *route)
Definition: PIMSM.cc:1578
void inet::PIMSM::processPruneSG ( IPv4Address  source,
IPv4Address  group,
IPv4Address  upstreamNeighborField,
InterfaceEntry inInterface 
)
private

Referenced by processJoinPrunePacket().

541 {
542  EV_DETAIL << "Processing Prune(" << source << ", " << group << ") received on interface '" << inInterface->getName() << "'.'n";
543 
544  //
545  // Downstream per-interface (S,G) state machine; event = Receive Prune(S,G)
546  //
547 
548  // check UpstreamNeighbor field
549  if (upstreamNeighborField != inInterface->ipv4Data()->getIPAddress())
550  return;
551 
552  Route *routeSG = findRouteSG(source, group);
553  if (routeSG) {
554  DownstreamInterface *downstream = routeSG->findDownstreamInterfaceByInterfaceId(inInterface->getInterfaceId());
555  if (downstream && downstream->joinPruneState == DownstreamInterface::JOIN) {
556  // The (S,G) downstream state machine on interface I transitions
557  // to the Prune-Pending state. The Prune-Pending Timer is
558  // started. It is set to the J/P_Override_Interval(I) if the
559  // router has more than one neighbor on that interface;
560  // otherwise, it is set to zero, causing it to expire
561  // immediately.
562  downstream->joinPruneState = DownstreamInterface::PRUNE_PENDING;
563  double pruneOverrideInterval = pimNbt->getNumNeighbors(inInterface->getInterfaceId()) > 1 ?
565  downstream->startPrunePendingTimer(pruneOverrideInterval);
566  }
567  }
568 
569  // check upstream state transition
570  if (routeSG)
571  updateJoinDesired(routeSG);
572 }
PIMNeighborTable * pimNbt
Definition: PIMBase.h:161
Route * findRouteSG(IPv4Address source, IPv4Address group)
Definition: PIMSM.cc:1903
double joinPruneOverrideInterval()
Definition: PIMSM.h:296
virtual int getNumNeighbors(int interfaceId)
Returns the number of neighbors on the given interface.
Definition: PIMNeighborTable.cc:176
void updateJoinDesired(Route *route)
Definition: PIMSM.cc:1578
void inet::PIMSM::processPruneSGrpt ( IPv4Address  source,
IPv4Address  group,
IPv4Address  upstreamNeighborField,
InterfaceEntry inInterface 
)
private

Referenced by processJoinPrunePacket().

575 {
576  // TODO
577 }
void inet::PIMSM::processRegisterPacket ( PIMRegister pkt)
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.

Referenced by handleMessageWhenUp().

585 {
586  EV_INFO << "Received Register packet.\n";
587 
588  emit(rcvdRegisterPkSignal, pkt);
589 
590  IPv4Datagram *encapData = check_and_cast<IPv4Datagram *>(pkt->decapsulate());
591  IPv4Address source = encapData->getSrcAddress();
592  IPv4Address group = encapData->getDestAddress();
593  Route *routeG = findRouteG(group);
594  Route *routeSG = findRouteSG(source, group);
595 
596  if (!pkt->getN()) { // It is Null Register ?
597  if (!routeG) {
598  routeG = addNewRouteG(group, Route::PRUNED);
599  }
600 
601  if (!routeSG) {
602  routeSG = addNewRouteSG(source, group, Route::PRUNED);
603  routeSG->startKeepAliveTimer(keepAlivePeriod);
604  }
605  else if (routeSG->keepAliveTimer) {
606  EV << " (S,G) KAT timer refresh" << endl;
607  restartTimer(routeSG->keepAliveTimer, KAT);
608  }
609 
610  if (!routeG->isInheritedOlistNull()) { // we have some active receivers
611  routeSG->clearFlag(Route::PRUNED);
612 
613  if (!routeSG->isFlagSet(Route::SPT_BIT)) { // only if isn't build SPT between RP and registering DR
614  // decapsulate and forward the inner packet to inherited_olist(S,G,rpt)
615  // XXX we are forwarding on inherited_olist(*,G)
616  for (auto & elem : routeG->downstreamInterfaces) {
617  DownstreamInterface *downstream = elem;
618  if (downstream->isInInheritedOlist())
619  forwardMulticastData(encapData->dup(), downstream->getInterfaceId());
620  }
621 
622  // send Join(S,G) toward source to establish SPT between RP and registering DR
623  sendPIMJoin(group, source, routeSG->upstreamInterface->rpfNeighbor(), SG);
624 
625  // send register-stop packet
626  IPv4ControlInfo *ctrlInfo = check_and_cast<IPv4ControlInfo *>(pkt->getControlInfo());
627  sendPIMRegisterStop(ctrlInfo->getDestAddr(), ctrlInfo->getSrcAddr(), group, source);
628  }
629  }
630  }
631 
632  if (routeG) {
633  if (routeG->isFlagSet(Route::PRUNED) || pkt->getN()) {
634  IPv4ControlInfo *ctrlInfo = check_and_cast<IPv4ControlInfo *>(pkt->getControlInfo());
635  sendPIMRegisterStop(ctrlInfo->getDestAddr(), ctrlInfo->getSrcAddr(), group, source);
636  }
637  }
638 
639  delete encapData;
640  delete pkt;
641 }
Route * findRouteG(IPv4Address group)
Definition: PIMSM.cc:1896
Route * findRouteSG(IPv4Address source, IPv4Address group)
Definition: PIMSM.cc:1903
void sendPIMJoin(IPv4Address group, IPv4Address source, IPv4Address upstreamNeighbor, RouteType JPtype)
Definition: PIMSM.cc:1378
Definition: PIMSM.h:141
void sendPIMRegisterStop(IPv4Address source, IPv4Address dest, IPv4Address multGroup, IPv4Address multSource)
Definition: PIMSM.cc:1494
Definition: PIMSM.h:149
Definition: PIMSM.h:151
void forwardMulticastData(IPv4Datagram *datagram, int outInterfaceId)
The method is used as abstraction for encapsulation multicast data to Register packet.
Definition: PIMSM.cc:1554
static simsignal_t rcvdRegisterPkSignal
Definition: PIMSM.h:219
Route * addNewRouteSG(IPv4Address source, IPv4Address group, int flags)
Definition: PIMSM.cc:1811
Route * addNewRouteG(IPv4Address group, int flags)
Definition: PIMSM.cc:1761
void restartTimer(cMessage *timer, double interval)
Definition: PIMSM.cc:1928
double keepAlivePeriod
Definition: PIMSM.h:210
#define KAT
Keep alive timer, if RPT is disconnect.
Definition: PIMSM.h:30
void inet::PIMSM::processRegisterStopPacket ( PIMRegisterStop pkt)
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.

Referenced by handleMessageWhenUp().

650 {
651  EV_INFO << "Received RegisterStop packet.\n";
652 
653  emit(rcvdRegisterStopPkSignal, pkt);
654 
655  // TODO support wildcard source address
656  Route *routeSG = findRouteSG(pkt->getSourceAddress(), pkt->getGroupAddress());
657  if (routeSG) {
658  if (routeSG->registerState == Route::RS_JOIN || routeSG->registerState == Route::RS_JOIN_PENDING) {
659  routeSG->registerState = Route::RS_PRUNE;
660  cancelAndDeleteTimer(routeSG->registerStopTimer);
661 
662  // The Register-Stop Timer is set to a random value chosen
663  // uniformly from the interval ( 0.5 * Register_Suppression_Time,
664  // 1.5 * Register_Suppression_Time) minus Register_Probe_Time.
665  // Subtracting off Register_Probe_Time is a bit unnecessary because
666  // it is really small compared to Register_Suppression_Time, but
667  // this was in the old spec and is kept for compatibility.
668  routeSG->startRegisterStopTimer(uniform(0.5 * registerSuppressionTime, 1.5 * registerSuppressionTime) - registerProbeTime);
669  }
670  }
671  delete pkt;
672 }
Definition: PIMSM.h:173
Route * findRouteSG(IPv4Address source, IPv4Address group)
Definition: PIMSM.cc:1903
RegisterState registerState
Definition: PIMSM.h:174
Definition: PIMSM.h:173
double registerProbeTime
Definition: PIMSM.h:213
void cancelAndDeleteTimer(cMessage *&timer)
Definition: PIMSM.cc:1922
double registerSuppressionTime
Definition: PIMSM.h:212
static simsignal_t rcvdRegisterStopPkSignal
Definition: PIMSM.h:221
void inet::PIMSM::processRegisterStopTimer ( cMessage *  timer)
private

Referenced by handleMessageWhenUp().

933 {
934  EV << "pimSM::processRegisterStopTimer: " << endl;
935  Route *routeSG = static_cast<Route *>(timer->getContextPointer());
936  ASSERT(timer == routeSG->registerStopTimer);
937  ASSERT(routeSG->type == SG);
938 
939  delete timer;
940  routeSG->registerStopTimer = nullptr;
941 
942  if (routeSG->registerState == Route::RS_PRUNE) {
943  routeSG->registerState = Route::RS_JOIN_PENDING;
944  sendPIMRegisterNull(routeSG->source, routeSG->group);
945  routeSG->startRegisterStopTimer(registerProbeTime);
946  }
947  else if (routeSG->registerState == Route::RS_JOIN_PENDING) {
948  routeSG->registerState = Route::RS_JOIN;
949  }
950 }
Definition: PIMSM.h:173
Definition: PIMSM.h:141
Definition: PIMSM.h:173
double registerProbeTime
Definition: PIMSM.h:213
void sendPIMRegisterNull(IPv4Address multSource, IPv4Address multDest)
Definition: PIMSM.cc:1444
void inet::PIMSM::receiveSignal ( cComponent *  source,
simsignal_t  signalID,
cObject *  obj,
cObject *  details 
)
overrideprotectedvirtual
272 {
273  Enter_Method_Silent();
274  printNotificationBanner(signalID, obj);
275  Route *route;
276  IPv4Datagram *datagram;
277  PIMInterface *pimInterface;
278 
279  if (signalID == NF_IPv4_MCAST_REGISTERED) {
280  EV << "pimSM::receiveChangeNotification - NEW IGMP ADDED" << endl;
281  IPv4MulticastGroupInfo *info = check_and_cast<IPv4MulticastGroupInfo *>(obj);
282  pimInterface = pimIft->getInterfaceById(info->ie->getInterfaceId());
283  if (pimInterface && pimInterface->getMode() == PIMInterface::SparseMode)
284  multicastReceiverAdded(info->ie, info->groupAddress);
285  }
286  else if (signalID == NF_IPv4_MCAST_UNREGISTERED) {
287  EV << "pimSM::receiveChangeNotification - IGMP REMOVED" << endl;
288  IPv4MulticastGroupInfo *info = check_and_cast<IPv4MulticastGroupInfo *>(obj);
289  pimInterface = pimIft->getInterfaceById(info->ie->getInterfaceId());
290  if (pimInterface && pimInterface->getMode() == PIMInterface::SparseMode)
291  multicastReceiverRemoved(info->ie, info->groupAddress);
292  }
293  else if (signalID == NF_IPv4_NEW_MULTICAST) {
294  EV << "PimSM::receiveChangeNotification - NEW MULTICAST" << endl;
295  datagram = check_and_cast<IPv4Datagram *>(obj);
296  IPv4Address srcAddr = datagram->getSrcAddress();
297  IPv4Address destAddr = datagram->getDestAddress();
298  unroutableMulticastPacketArrived(srcAddr, destAddr);
299  }
300  else if (signalID == NF_IPv4_DATA_ON_RPF) {
301  EV << "pimSM::receiveChangeNotification - DATA ON RPF" << endl;
302  datagram = check_and_cast<IPv4Datagram *>(obj);
303  PIMInterface *incomingInterface = getIncomingInterface(datagram);
304  if (incomingInterface && incomingInterface->getMode() == PIMInterface::SparseMode) {
305  route = findRouteG(datagram->getDestAddress());
306  if (route)
308  route = findRouteSG(datagram->getSrcAddress(), datagram->getDestAddress());
309  if (route)
311  }
312  }
313  else if (signalID == NF_IPv4_DATA_ON_NONRPF) {
314  datagram = check_and_cast<IPv4Datagram *>(obj);
315  PIMInterface *incomingInterface = getIncomingInterface(datagram);
316  if (incomingInterface && incomingInterface->getMode() == PIMInterface::SparseMode) {
317  IPv4Address srcAddr = datagram->getSrcAddress();
318  IPv4Address destAddr = datagram->getDestAddress();
319  if ((route = findRouteSG(srcAddr, destAddr)) != nullptr)
320  multicastPacketArrivedOnNonRpfInterface(route, incomingInterface->getInterfaceId());
321  else if ((route = findRouteG(destAddr)) != nullptr)
322  multicastPacketArrivedOnNonRpfInterface(route, incomingInterface->getInterfaceId());
323  }
324  }
325  else if (signalID == NF_IPv4_MDATA_REGISTER) {
326  EV << "pimSM::receiveChangeNotification - REGISTER DATA" << endl;
327  datagram = check_and_cast<IPv4Datagram *>(obj);
328  PIMInterface *incomingInterface = getIncomingInterface(datagram);
329  route = findRouteSG(datagram->getSrcAddress(), datagram->getDestAddress());
330  if (incomingInterface && incomingInterface->getMode() == PIMInterface::SparseMode)
331  multicastPacketForwarded(datagram);
332  }
333  else if (signalID == NF_PIM_NEIGHBOR_ADDED || signalID == NF_PIM_NEIGHBOR_DELETED || signalID == NF_PIM_NEIGHBOR_CHANGED) {
334  PIMNeighbor *neighbor = check_and_cast<PIMNeighbor *>(obj);
335  updateDesignatedRouterAddress(neighbor->getInterfacePtr());
336  }
337 }
simsignal_t NF_IPv4_DATA_ON_RPF
Definition: NotifierConsts.cc:74
void multicastPacketArrivedOnRpfInterface(Route *route)
The method process notification about data which appears on RPF interface.
Definition: PIMSM.cc:1194
Route * findRouteG(IPv4Address group)
Definition: PIMSM.cc:1896
Route * findRouteSG(IPv4Address source, IPv4Address group)
Definition: PIMSM.cc:1903
simsignal_t NF_IPv4_MCAST_UNREGISTERED
Definition: NotifierConsts.cc:68
simsignal_t NF_PIM_NEIGHBOR_ADDED
Definition: NotifierConsts.cc:81
void multicastPacketArrivedOnNonRpfInterface(Route *route, int interfaceId)
Definition: PIMSM.cc:1245
PIMInterfaceTable * pimIft
Definition: PIMBase.h:160
void updateDesignatedRouterAddress(InterfaceEntry *ie)
Definition: PIMSM.cc:1609
void multicastReceiverAdded(InterfaceEntry *ie, IPv4Address group)
Definition: PIMSM.cc:1175
simsignal_t NF_PIM_NEIGHBOR_CHANGED
Definition: NotifierConsts.cc:83
PIMInterface * getIncomingInterface(IPv4Datagram *datagram)
Definition: PIMSM.cc:1702
simsignal_t NF_IPv4_NEW_MULTICAST
Definition: NotifierConsts.cc:70
simsignal_t NF_IPv4_MCAST_REGISTERED
Definition: NotifierConsts.cc:67
void multicastReceiverRemoved(InterfaceEntry *ie, IPv4Address group)
Definition: PIMSM.cc:1163
virtual PIMInterface * getInterfaceById(int interfaceId)
Definition: PIMInterfaceTable.cc:116
void multicastPacketForwarded(IPv4Datagram *datagram)
Definition: PIMSM.cc:1276
void printNotificationBanner(simsignal_t signalID, const cObject *obj)
Utility function.
Definition: NotifierConsts.cc:109
void unroutableMulticastPacketArrived(IPv4Address srcAddr, IPv4Address destAddr)
Definition: PIMSM.cc:1137
Definition: PIMInterfaceTable.h:37
simsignal_t NF_IPv4_MDATA_REGISTER
Definition: NotifierConsts.cc:77
simsignal_t NF_IPv4_DATA_ON_NONRPF
Definition: NotifierConsts.cc:73
simsignal_t NF_PIM_NEIGHBOR_DELETED
Definition: NotifierConsts.cc:82
bool inet::PIMSM::removeRoute ( Route route)
private

Referenced by deleteMulticastRoute().

1888 {
1889  SourceAndGroup sg(route->source, route->group);
1890  if (route->type == G)
1891  return gRoutes.erase(sg);
1892  else
1893  return sgRoutes.erase(sg);
1894 }
RoutingTable gRoutes
Definition: PIMSM.h:228
RoutingTable sgRoutes
Definition: PIMSM.h:229
Definition: PIMSM.h:140
void inet::PIMSM::restartExpiryTimer ( Route route,
InterfaceEntry 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.

1113 {
1114  EV << "pimSM::restartExpiryTimer: next ET @ " << simTime() + holdTime << " for type: ";
1115 
1116  if (route) {
1117  // ET for route
1118  if (route->upstreamInterface && route->upstreamInterface->expiryTimer)
1119  restartTimer(route->upstreamInterface->expiryTimer, holdTime);
1120 
1121  // ET for outgoing interfaces
1122  for (unsigned i = 0; i < route->downstreamInterfaces.size(); i++) { // if exist ET and for given interface
1123  DownstreamInterface *downstream = route->downstreamInterfaces[i];
1124  if (downstream->expiryTimer && (downstream->getInterfaceId() == originIntf->getInterfaceId())) {
1125  EV << /*timer->getStateType() << " , " <<*/ route->group << " , " << route->source << ", int: " << downstream->ie->getName() << endl;
1126  restartTimer(downstream->expiryTimer, holdTime);
1127  break;
1128  }
1129  }
1130  }
1131 }
double holdTime
Definition: PIMBase.h:169
void restartTimer(cMessage *timer, double interval)
Definition: PIMSM.cc:1928
void inet::PIMSM::restartTimer ( cMessage *  timer,
double  interval 
)
private
void inet::PIMSM::sendPIMAssert ( IPv4Address  source,
IPv4Address  group,
AssertMetric  metric,
InterfaceEntry ie,
bool  rptBit 
)
private

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

1517 {
1518  EV_INFO << "Sending Assert(S= " << source << ", G= " << group << ") message on interface '" << ie->getName() << "'\n";
1519 
1520  PIMAssert *pkt = new PIMAssert("PIMAssert");
1521  pkt->setGroupAddress(group);
1522  pkt->setSourceAddress(source);
1523  pkt->setR(rptBit);
1524  pkt->setMetricPreference(metric.preference);
1525  pkt->setMetric(metric.metric);
1526 
1527  pkt->setByteLength(PIM_HEADER_LENGTH
1530  + 8);
1531 
1532  emit(sentAssertPkSignal, pkt);
1533 
1534  sendToIP(pkt, IPv4Address::UNSPECIFIED_ADDRESS, ALL_PIM_ROUTERS_MCAST, ie->getInterfaceId(), 1);
1535 }
void sendToIP(PIMPacket *packet, IPv4Address source, IPv4Address dest, int outInterfaceId, short ttl)
Definition: PIMSM.cc:1537
#define ENCODED_UNICODE_ADDRESS_LENGTH
Definition: PIMPacket_m.h:34
#define ENCODED_GROUP_ADDRESS_LENGTH
Definition: PIMPacket_m.h:35
static const IPv4Address UNSPECIFIED_ADDRESS
0.0.0.0
Definition: IPv4Address.h:102
static const IPv4Address ALL_PIM_ROUTERS_MCAST
Definition: PIMBase.h:155
static simsignal_t sentAssertPkSignal
Definition: PIMSM.h:224
#define PIM_HEADER_LENGTH
Definition: PIMPacket_m.h:33
void inet::PIMSM::sendPIMJoin ( IPv4Address  group,
IPv4Address  source,
IPv4Address  upstreamNeighbor,
RouteType  JPtype 
)
private

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

1379 {
1380  EV_INFO << "Sending Join(S=" << (routeType == G ? "*" : source.str()) << ", G=" << group << ") to neighbor " << upstreamNeighbor << ".\n";
1381 
1382  PIMJoinPrune *msg = new PIMJoinPrune();
1383  msg->setType(JoinPrune);
1384  msg->setName("PIMJoin");
1385  msg->setUpstreamNeighborAddress(upstreamNeighbor);
1386  msg->setHoldTime(joinPruneHoldTime());
1387 
1388  msg->setJoinPruneGroupsArraySize(1);
1389  JoinPruneGroup& multGroup = msg->getJoinPruneGroups(0);
1390  multGroup.setGroupAddress(group);
1391  multGroup.setJoinedSourceAddressArraySize(1);
1392  EncodedAddress& encodedAddr = multGroup.getJoinedSourceAddress(0);
1393  encodedAddr.IPaddress = source;
1394  encodedAddr.S = true;
1395  encodedAddr.W = (routeType == G);
1396  encodedAddr.R = (routeType == G);
1397 
1398  msg->setByteLength(PIM_HEADER_LENGTH
1400  + 4
1402  + 4
1404 
1405  emit(sentJoinPrunePkSignal, msg);
1406 
1407  InterfaceEntry *interfaceToRP = rt->getInterfaceForDestAddr(source);
1408  sendToIP(msg, IPv4Address::UNSPECIFIED_ADDRESS, ALL_PIM_ROUTERS_MCAST, interfaceToRP->getInterfaceId(), 1);
1409 }
void sendToIP(PIMPacket *packet, IPv4Address source, IPv4Address dest, int outInterfaceId, short ttl)
Definition: PIMSM.cc:1537
virtual InterfaceEntry * getInterfaceForDestAddr(const IPv4Address &dest) const =0
Convenience function based on findBestMatchingRoute().
#define ENCODED_UNICODE_ADDRESS_LENGTH
Definition: PIMPacket_m.h:34
#define ENCODED_SOURCE_ADDRESS_LENGTH
Definition: PIMPacket_m.h:36
Definition: PIMPacket_m.h:65
double joinPruneHoldTime()
Definition: PIMSM.h:293
#define ENCODED_GROUP_ADDRESS_LENGTH
Definition: PIMPacket_m.h:35
IIPv4RoutingTable * rt
Definition: PIMBase.h:158
static const IPv4Address UNSPECIFIED_ADDRESS
0.0.0.0
Definition: IPv4Address.h:102
static const IPv4Address ALL_PIM_ROUTERS_MCAST
Definition: PIMBase.h:155
Definition: PIMSM.h:140
static simsignal_t sentJoinPrunePkSignal
Definition: PIMSM.h:222
#define PIM_HEADER_LENGTH
Definition: PIMPacket_m.h:33
void inet::PIMSM::sendPIMPrune ( IPv4Address  group,
IPv4Address  source,
IPv4Address  upstreamNeighbor,
RouteType  JPtype 
)
private

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

1412 {
1413  EV_INFO << "Sending Prune(S=" << (routeType == G ? "*" : source.str()) << ", G=" << group << ") to neighbor " << upstreamNeighbor << ".\n";
1414 
1415  PIMJoinPrune *msg = new PIMJoinPrune();
1416  msg->setType(JoinPrune);
1417  msg->setName("PIMPrune");
1418  msg->setUpstreamNeighborAddress(upstreamNeighbor);
1419  msg->setHoldTime(joinPruneHoldTime());
1420 
1421  msg->setJoinPruneGroupsArraySize(1);
1422  JoinPruneGroup& multGroup = msg->getJoinPruneGroups(0);
1423  multGroup.setGroupAddress(group);
1424  multGroup.setPrunedSourceAddressArraySize(1);
1425  EncodedAddress& encodedAddr = multGroup.getPrunedSourceAddress(0);
1426  encodedAddr.IPaddress = source;
1427  encodedAddr.S = true;
1428  encodedAddr.W = (routeType == G);
1429  encodedAddr.R = (routeType == G);
1430 
1431  msg->setByteLength(PIM_HEADER_LENGTH
1433  + 4
1435  + 4
1437 
1438  emit(sentJoinPrunePkSignal, msg);
1439 
1440  InterfaceEntry *interfaceToRP = rt->getInterfaceForDestAddr(source);
1441  sendToIP(msg, IPv4Address::UNSPECIFIED_ADDRESS, ALL_PIM_ROUTERS_MCAST, interfaceToRP->getInterfaceId(), 1);
1442 }
void sendToIP(PIMPacket *packet, IPv4Address source, IPv4Address dest, int outInterfaceId, short ttl)
Definition: PIMSM.cc:1537
virtual InterfaceEntry * getInterfaceForDestAddr(const IPv4Address &dest) const =0
Convenience function based on findBestMatchingRoute().
#define ENCODED_UNICODE_ADDRESS_LENGTH
Definition: PIMPacket_m.h:34
#define ENCODED_SOURCE_ADDRESS_LENGTH
Definition: PIMPacket_m.h:36
Definition: PIMPacket_m.h:65
double joinPruneHoldTime()
Definition: PIMSM.h:293
#define ENCODED_GROUP_ADDRESS_LENGTH
Definition: PIMPacket_m.h:35
IIPv4RoutingTable * rt
Definition: PIMBase.h:158
static const IPv4Address UNSPECIFIED_ADDRESS
0.0.0.0
Definition: IPv4Address.h:102
static const IPv4Address ALL_PIM_ROUTERS_MCAST
Definition: PIMBase.h:155
Definition: PIMSM.h:140
static simsignal_t sentJoinPrunePkSignal
Definition: PIMSM.h:222
#define PIM_HEADER_LENGTH
Definition: PIMPacket_m.h:33
void inet::PIMSM::sendPIMRegister ( IPv4Datagram datagram,
IPv4Address  dest,
int  outInterfaceId 
)
private

Referenced by multicastPacketForwarded().

1475 {
1476  EV << "pimSM::sendPIMRegister - encapsulating data packet into Register packet and sending to RP" << endl;
1477 
1478  PIMRegister *msg = new PIMRegister("PIMRegister");
1479  msg->setType(Register);
1480  msg->setN(false);
1481  msg->setB(false);
1482 
1483  msg->setByteLength(PIM_HEADER_LENGTH + 4);
1484 
1485  IPv4Datagram *datagramCopy = datagram->dup();
1486  delete datagramCopy->removeControlInfo();
1487  msg->encapsulate(datagramCopy);
1488 
1489  emit(sentRegisterPkSignal, msg);
1490 
1491  sendToIP(msg, IPv4Address::UNSPECIFIED_ADDRESS, dest, outInterfaceId, MAX_TTL);
1492 }
void sendToIP(PIMPacket *packet, IPv4Address source, IPv4Address dest, int outInterfaceId, short ttl)
Definition: PIMSM.cc:1537
static simsignal_t sentRegisterPkSignal
Definition: PIMSM.h:218
Definition: PIMPacket_m.h:63
static const IPv4Address UNSPECIFIED_ADDRESS
0.0.0.0
Definition: IPv4Address.h:102
#define MAX_TTL
Maximum TTL.
Definition: PIMSM.h:31
#define PIM_HEADER_LENGTH
Definition: PIMPacket_m.h:33
void inet::PIMSM::sendPIMRegisterNull ( IPv4Address  multSource,
IPv4Address  multDest 
)
private

Referenced by processRegisterStopTimer().

1445 {
1446  EV << "pimSM::sendPIMRegisterNull" << endl;
1447 
1448  // only if (S,G exist)
1449  //if (getRouteFor(multDest,multSource))
1450  if (findRouteG(multGroup)) {
1451  PIMRegister *msg = new PIMRegister();
1452  msg->setName("PIMRegister(Null)");
1453  msg->setType(Register);
1454  msg->setN(true);
1455  msg->setB(false);
1456 
1457  msg->setByteLength(PIM_HEADER_LENGTH + 4);
1458 
1459  // set encapsulated packet (IPv4 header only)
1460  IPv4Datagram *datagram = new IPv4Datagram();
1461  datagram->setDestAddress(multGroup);
1462  datagram->setSrcAddress(multOrigin);
1463  datagram->setTransportProtocol(IP_PROT_PIM);
1464  datagram->setByteLength(IP_HEADER_BYTES);
1465  msg->encapsulate(datagram);
1466 
1467  emit(sentRegisterPkSignal, msg);
1468 
1469  InterfaceEntry *interfaceToRP = rt->getInterfaceForDestAddr(rpAddr);
1470  sendToIP(msg, IPv4Address::UNSPECIFIED_ADDRESS, rpAddr, interfaceToRP->getInterfaceId(), MAX_TTL);
1471  }
1472 }
void sendToIP(PIMPacket *packet, IPv4Address source, IPv4Address dest, int outInterfaceId, short ttl)
Definition: PIMSM.cc:1537
Route * findRouteG(IPv4Address group)
Definition: PIMSM.cc:1896
virtual InterfaceEntry * getInterfaceForDestAddr(const IPv4Address &dest) const =0
Convenience function based on findBestMatchingRoute().
static simsignal_t sentRegisterPkSignal
Definition: PIMSM.h:218
const int IP_HEADER_BYTES
Definition: IPv4Datagram_m.h:41
Definition: PIMPacket_m.h:63
Definition: IPProtocolId_m.h:90
IPv4Address rpAddr
Definition: PIMSM.h:206
IIPv4RoutingTable * rt
Definition: PIMBase.h:158
static const IPv4Address UNSPECIFIED_ADDRESS
0.0.0.0
Definition: IPv4Address.h:102
#define MAX_TTL
Maximum TTL.
Definition: PIMSM.h:31
#define PIM_HEADER_LENGTH
Definition: PIMPacket_m.h:33
void inet::PIMSM::sendPIMRegisterStop ( IPv4Address  source,
IPv4Address  dest,
IPv4Address  multGroup,
IPv4Address  multSource 
)
private

Referenced by processRegisterPacket().

1495 {
1496  EV << "pimSM::sendPIMRegisterStop" << endl;
1497 
1498  // create PIM Register datagram
1499  PIMRegisterStop *msg = new PIMRegisterStop();
1500 
1501  // set PIM packet
1502  msg->setName("PIMRegisterStop");
1503  msg->setType(RegisterStop);
1504  msg->setSourceAddress(multSource);
1505  msg->setGroupAddress(multGroup);
1506 
1508 
1509  emit(sentRegisterStopPkSignal, msg);
1510 
1511  // set IP packet
1512  InterfaceEntry *interfaceToDR = rt->getInterfaceForDestAddr(dest);
1513  sendToIP(msg, source, dest, interfaceToDR->getInterfaceId(), MAX_TTL);
1514 }
Definition: PIMPacket_m.h:64
void sendToIP(PIMPacket *packet, IPv4Address source, IPv4Address dest, int outInterfaceId, short ttl)
Definition: PIMSM.cc:1537
virtual InterfaceEntry * getInterfaceForDestAddr(const IPv4Address &dest) const =0
Convenience function based on findBestMatchingRoute().
static simsignal_t sentRegisterStopPkSignal
Definition: PIMSM.h:220
#define ENCODED_UNICODE_ADDRESS_LENGTH
Definition: PIMPacket_m.h:34
#define ENCODED_GROUP_ADDRESS_LENGTH
Definition: PIMPacket_m.h:35
IIPv4RoutingTable * rt
Definition: PIMBase.h:158
#define MAX_TTL
Maximum TTL.
Definition: PIMSM.h:31
#define PIM_HEADER_LENGTH
Definition: PIMPacket_m.h:33
void inet::PIMSM::sendToIP ( PIMPacket packet,
IPv4Address  source,
IPv4Address  dest,
int  outInterfaceId,
short  ttl 
)
private

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

1538 {
1539  IPv4ControlInfo *ctrl = new IPv4ControlInfo();
1540  ctrl->setSrcAddr(srcAddr);
1541  ctrl->setDestAddr(destAddr);
1542  ctrl->setProtocol(IP_PROT_PIM);
1543  ctrl->setTimeToLive(ttl);
1544  ctrl->setInterfaceId(outInterfaceId);
1545  packet->setControlInfo(ctrl);
1546  send(packet, "ipOut");
1547 }
Definition: IPProtocolId_m.h:90
uint8_t ttl
Definition: TCP_NSC.cc:87
void inet::PIMSM::stopPIMRouting ( )
protectedvirtual

Referenced by handleNodeCrash(), and handleNodeShutdown().

156 {
157  if (isEnabled) {
158  cModule *host = findContainingNode(this);
159  if (!host)
160  throw cRuntimeError("PIMSM: containing node not found.");
161  host->unsubscribe(NF_IPv4_NEW_MULTICAST, this);
162  host->unsubscribe(NF_IPv4_MDATA_REGISTER, this);
163  host->unsubscribe(NF_IPv4_DATA_ON_RPF, this);
164  host->unsubscribe(NF_IPv4_DATA_ON_NONRPF, this);
165  host->unsubscribe(NF_IPv4_MCAST_REGISTERED, this);
166  host->unsubscribe(NF_IPv4_MCAST_UNREGISTERED, this);
167  host->unsubscribe(NF_PIM_NEIGHBOR_ADDED, this);
168  host->unsubscribe(NF_PIM_NEIGHBOR_DELETED, this);
169  host->unsubscribe(NF_PIM_NEIGHBOR_CHANGED, this);
170  }
171 
172  clearRoutes();
173 }
void clearRoutes()
Definition: PIMSM.cc:1735
bool isEnabled
Definition: PIMBase.h:164
simsignal_t NF_IPv4_DATA_ON_RPF
Definition: NotifierConsts.cc:74
simsignal_t NF_IPv4_MCAST_UNREGISTERED
Definition: NotifierConsts.cc:68
simsignal_t NF_PIM_NEIGHBOR_ADDED
Definition: NotifierConsts.cc:81
simsignal_t NF_PIM_NEIGHBOR_CHANGED
Definition: NotifierConsts.cc:83
simsignal_t NF_IPv4_NEW_MULTICAST
Definition: NotifierConsts.cc:70
cModule * findContainingNode(const cModule *from)
Find the node containing the given module.
Definition: ModuleAccess.cc:56
simsignal_t NF_IPv4_MCAST_REGISTERED
Definition: NotifierConsts.cc:67
simsignal_t NF_IPv4_MDATA_REGISTER
Definition: NotifierConsts.cc:77
simsignal_t NF_IPv4_DATA_ON_NONRPF
Definition: NotifierConsts.cc:73
simsignal_t NF_PIM_NEIGHBOR_DELETED
Definition: NotifierConsts.cc:82
void inet::PIMSM::unroutableMulticastPacketArrived ( IPv4Address  srcAddr,
IPv4Address  destAddr 
)
private

Referenced by receiveSignal().

1138 {
1139  IPv4Route *routeTowardSource = rt->findBestMatchingRoute(source); // rt->getInterfaceForDestAddr(source);
1140  if (!routeTowardSource)
1141  return;
1142 
1143  PIMInterface *rpfInterface = pimIft->getInterfaceById(routeTowardSource->getInterface()->getInterfaceId());
1144  if (!rpfInterface || rpfInterface->getMode() != PIMInterface::SparseMode)
1145  return;
1146 
1147  InterfaceEntry *interfaceTowardRP = rt->getInterfaceForDestAddr(rpAddr);
1148 
1149  // RPF check and check if I am DR of the source
1150  if ((interfaceTowardRP != routeTowardSource->getInterface()) && routeTowardSource->getGateway().isUnspecified()) {
1151  EV_DETAIL << "New multicast source observed: source=" << source << ", group=" << group << ".\n";
1152 
1153  // create new (S,G) route
1154  Route *newRouteSG = addNewRouteSG(source, group, Route::PRUNED | Route::REGISTER | Route::SPT_BIT);
1155  newRouteSG->startKeepAliveTimer(keepAlivePeriod);
1156  newRouteSG->registerState = Route::RS_JOIN;
1157 
1158  // create new (*,G) route
1159  addNewRouteG(newRouteSG->group, Route::PRUNED | Route::REGISTER);
1160  }
1161 }
Definition: PIMSM.h:173
virtual InterfaceEntry * getInterfaceForDestAddr(const IPv4Address &dest) const =0
Convenience function based on findBestMatchingRoute().
PIMInterfaceTable * pimIft
Definition: PIMBase.h:160
Definition: PIMSM.h:149
Definition: PIMSM.h:151
IPv4Address rpAddr
Definition: PIMSM.h:206
virtual PIMInterface * getInterfaceById(int interfaceId)
Definition: PIMInterfaceTable.cc:116
Definition: PIMSM.h:150
Route * addNewRouteSG(IPv4Address source, IPv4Address group, int flags)
Definition: PIMSM.cc:1811
IIPv4RoutingTable * rt
Definition: PIMBase.h:158
virtual IPv4Route * findBestMatchingRoute(const IPv4Address &dest) const =0
The routing function.
Route * addNewRouteG(IPv4Address group, int flags)
Definition: PIMSM.cc:1761
Definition: PIMInterfaceTable.h:37
double keepAlivePeriod
Definition: PIMSM.h:210
void inet::PIMSM::updateAssertTrackingDesired ( PimsmInterface interface)
private
1669 {
1670  // TODO
1671 
1672  // AssertTrackingDesired(S,G,I) =
1673  // (I in ( ( joins(*,*,RP(G)) (+) joins(*,G) (-) prunes(S,G,rpt) )
1674  // (+) ( pim_include(*,G) (-) pim_exclude(S,G) )
1675  // (-) lost_assert(*,G)
1676  // (+) joins(S,G) ) )
1677  // OR (local_receiver_include(S,G,I) == TRUE
1678  // AND (I_am_DR(I) OR (AssertWinner(S,G,I) == me)))
1679  // OR ((RPF_interface(S) == I) AND (JoinDesired(S,G) == TRUE))
1680  // OR ((RPF_interface(RP(G)) == I) AND (JoinDesired(*,G) == TRUE)
1681  // AND (SPTbit(S,G) == FALSE))
1682 
1683  // AssertTrackingDesired(*,G,I) =
1684  // CouldAssert(*,G,I)
1685  // OR (local_receiver_include(*,G,I)==TRUE
1686  // AND (I_am_DR(I) OR AssertWinner(*,G,I) == me))
1687  // OR (RPF_interface(RP(G)) == I AND RPTJoinDesired(G))
1688 }
void inet::PIMSM::updateCouldAssert ( DownstreamInterface interface)
private
1651 {
1652  // TODO
1653 
1654  // CouldAssert(S,G,I) =
1655  // SPTbit(S,G)==TRUE
1656  // AND (RPF_interface(S) != I)
1657  // AND (I in ( ( joins(*,*,RP(G)) (+) joins(*,G) (-) prunes(S,G,rpt) )
1658  // (+) ( pim_include(*,G) (-) pim_exclude(S,G) )
1659  // (-) lost_assert(*,G)
1660  // (+) joins(S,G) (+) pim_include(S,G) ) )
1661 
1662  // CouldAssert(*,G,I) =
1663  // ( I in ( joins(*,*,RP(G)) (+) joins(*,G)
1664  // (+) pim_include(*,G)) )
1665  // AND (RPF_interface(RP(G)) != I)
1666 }
void inet::PIMSM::updateDesignatedRouterAddress ( InterfaceEntry ie)
private

Referenced by receiveSignal().

1610 {
1611  int interfaceId = ie->getInterfaceId();
1612  int numNeighbors = pimNbt->getNumNeighbors(interfaceId);
1613 
1614  bool eachNeighborHasPriority = true;
1615  for (int i = 0; i < numNeighbors && eachNeighborHasPriority; i++)
1616  if (pimNbt->getNeighbor(interfaceId, i))
1617  eachNeighborHasPriority = false;
1618 
1619 
1620  IPv4Address drAddress = ie->ipv4Data()->getIPAddress();
1621  int drPriority = this->designatedRouterPriority;
1622  for (int i = 0; i < numNeighbors; i++) {
1623  PIMNeighbor *neighbor = pimNbt->getNeighbor(interfaceId, i);
1624  bool isBetter = eachNeighborHasPriority ?
1625  (neighbor->getDRPriority() > drPriority ||
1626  (neighbor->getDRPriority() == drPriority &&
1627  neighbor->getAddress() > drAddress)) :
1628  (neighbor->getAddress() > drAddress);
1629  if (isBetter) {
1630  drPriority = neighbor->getDRPriority();
1631  drAddress = neighbor->getAddress();
1632  }
1633  }
1634 
1635  PIMInterface *pimInterface = pimIft->getInterfaceById(interfaceId);
1636  ASSERT(pimInterface);
1637  IPv4Address oldDRAddress = pimInterface->getDRAddress();
1638  if (drAddress != oldDRAddress) {
1639  pimInterface->setDRAddress(drAddress);
1641 
1642  IPv4Address myAddress = ie->ipv4Data()->getIPAddress();
1643  bool iWasDR = oldDRAddress.isUnspecified() || oldDRAddress == myAddress;
1644  bool iAmDR = drAddress == myAddress;
1645  if (iWasDR != iAmDR)
1646  iAmDRHasChanged(ie, iAmDR);
1647  }
1648 }
PIMNeighborTable * pimNbt
Definition: PIMBase.h:161
int designatedRouterPriority
Definition: PIMBase.h:170
void iAmDRHasChanged(InterfaceEntry *ie, bool iAmDR)
Definition: PIMSM.cc:1369
PIMInterfaceTable * pimIft
Definition: PIMBase.h:160
void designatedRouterAddressHasChanged(InterfaceEntry *ie)
Definition: PIMSM.cc:1364
virtual int getNumNeighbors(int interfaceId)
Returns the number of neighbors on the given interface.
Definition: PIMNeighborTable.cc:176
virtual PIMInterface * getInterfaceById(int interfaceId)
Definition: PIMInterfaceTable.cc:116
virtual PIMNeighbor * getNeighbor(int interfaceId, int index)
Returns the neighbor on the given interface at the specified position.
Definition: PIMNeighborTable.cc:182
void inet::PIMSM::updateJoinDesired ( Route route)
private

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

1579 {
1580  bool oldValue = route->joinDesired();
1581  bool newValue = false;
1582  if (route->type == RP)
1583  newValue = !route->isImmediateOlistNull();
1584  if (route->type == G)
1585  newValue = !route->isImmediateOlistNull() /* || JoinDesired(*,*,RP(G)) AND AssertWinner(*,G,RPF_interface(RP(G))) != nullptr */;
1586  else if (route->type == SG)
1587  newValue = !route->isImmediateOlistNull() || (route->keepAliveTimer && !route->isInheritedOlistNull());
1588 
1589  if (newValue != oldValue) {
1590  route->setFlag(Route::JOIN_DESIRED, newValue);
1591  joinDesiredChanged(route);
1592 
1593  if (route->type == RP) {
1594  // TODO
1595  }
1596  else if (route->type == G) {
1597  for (auto & elem : sgRoutes) {
1598  if (elem.second->gRoute == route)
1599  updateJoinDesired(elem.second);
1600  }
1601  }
1602  }
1603 }
RoutingTable sgRoutes
Definition: PIMSM.h:229
Definition: PIMSM.h:141
void joinDesiredChanged(Route *route)
Definition: PIMSM.cc:1308
Definition: PIMSM.h:152
Definition: PIMSM.h:140
void updateJoinDesired(Route *route)
Definition: PIMSM.cc:1578
Definition: PIMSM.h:139

Friends And Related Function Documentation

std::ostream& operator<< ( std::ostream &  out,
const SourceAndGroup sourceGroup 
)
friend
std::ostream& operator<< ( std::ostream &  out,
const Route sourceGroup 
)
friend
47 {
48  out << "(" << (route.source.isUnspecified() ? "*" : route.source.str()) << ", "
49  << (route.group.isUnspecified() ? "*" : route.group.str()) << "), ";
50  out << "RP is " << route.rpAddr << ", ";
51 
52  out << "Incoming interface: ";
53  if (route.upstreamInterface) {
54  out << route.upstreamInterface->ie->getName() << ", ";
55  out << "RPF neighbor: " << route.upstreamInterface->rpfNeighbor() << ", ";
56  }
57  else
58  out << "nullptr, ";
59 
60  out << "Downstream interfaces: ";
61  for (unsigned int i = 0; i < route.downstreamInterfaces.size(); ++i) {
62  if (i > 0)
63  out << ", ";
64  out << route.downstreamInterfaces[i]->ie->getName() << " ";
65  switch (route.downstreamInterfaces[i]->joinPruneState) {
67  out << "(NI)";
68  break;
69 
71  out << "(J)";
72  break;
73 
75  out << "(PP)";
76  break;
77  }
78  }
79 
80  return out;
81 }

Member Data Documentation

double inet::PIMSM::assertOverrideInterval = 0
private
double inet::PIMSM::assertTime = 0
private
double inet::PIMSM::defaultOverrideInterval = 0
private

Referenced by initialize().

double inet::PIMSM::defaultPropagationDelay = 0
private

Referenced by initialize().

RoutingTable inet::PIMSM::gRoutes
private
double inet::PIMSM::joinPrunePeriod = 0
private
simsignal_t inet::PIMSM::rcvdAssertPkSignal = registerSignal("rcvdAssertPk")
staticprivate

Referenced by processAssertPacket().

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

Referenced by processJoinPrunePacket().

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

Referenced by processRegisterPacket().

simsignal_t inet::PIMSM::rcvdRegisterStopPkSignal = registerSignal("rcvdRegisterStopPk")
staticprivate
double inet::PIMSM::registerProbeTime = 0
private
double inet::PIMSM::registerSuppressionTime = 0
private
double inet::PIMSM::rpKeepAlivePeriod = 0
private

Referenced by initialize().

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

Referenced by sendPIMAssert().

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

Referenced by sendPIMJoin(), and sendPIMPrune().

simsignal_t inet::PIMSM::sentRegisterPkSignal = registerSignal("sentRegisterPk")
staticprivate
simsignal_t inet::PIMSM::sentRegisterStopPkSignal = registerSignal("sentRegisterStopPk")
staticprivate

Referenced by sendPIMRegisterStop().


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