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

#include <IGMPv3.h>

Inheritance diagram for inet::IGMPv3:

Classes

struct  HostGroupData
 
struct  HostInterfaceData
 
struct  RouterGroupData
 
struct  RouterInterfaceData
 
struct  SourceRecord
 

Protected Types

enum  RouterState { IGMPV3_RS_INITIAL, IGMPV3_RS_QUERIER, IGMPV3_RS_NON_QUERIER }
 
enum  RouterGroupState { IGMPV3_RGS_NO_MEMBERS_PRESENT, IGMPV3_RGS_MEMBERS_PRESENT, IGMPV3_RGS_CHECKING_MEMBERSHIP }
 
enum  HostGroupState { IGMPV3_HGS_NON_MEMBER, IGMPV3_HGS_DELAYING_MEMBER, IGMPV3_HGS_IDLE_MEMBER }
 
enum  FilterMode { IGMPV3_FM_INCLUDE, IGMPV3_FM_EXCLUDE }
 
enum  ReportType {
  IGMPV3_RT_IS_IN = 1, IGMPV3_RT_IS_EX = 2, IGMPV3_RT_TO_IN = 3, IGMPV3_RT_TO_EX = 4,
  IGMPV3_RT_ALLOW = 5, IGMPV3_RT_BLOCK = 6
}
 
enum  IGMPTimerKind {
  IGMPV3_R_GENERAL_QUERY_TIMER, IGMPV3_R_GROUP_TIMER, IGMPV3_R_SOURCE_TIMER, IGMPV3_H_GENERAL_QUERY_TIMER,
  IGMPV3_H_GROUP_TIMER
}
 
typedef std::vector< IPv4AddressIPv4AddressVector
 
typedef std::map< IPv4Address, HostGroupData * > GroupToHostDataMap
 
typedef std::map< IPv4Address, SourceRecord * > SourceToSourceRecordMap
 
typedef std::map< IPv4Address, RouterGroupData * > GroupToRouterDataMap
 
typedef std::map< int, HostInterfaceData * > InterfaceToHostDataMap
 
typedef std::map< int, RouterInterfaceData * > InterfaceToRouterDataMap
 

Protected Member Functions

virtual int numInitStages () const override
 
virtual void initialize (int stage) override
 
virtual void handleMessage (cMessage *msg) override
 
virtual void receiveSignal (cComponent *source, simsignal_t signalID, cObject *obj, cObject *details) override
 
virtual ~IGMPv3 ()
 
virtual HostInterfaceDatacreateHostInterfaceData (InterfaceEntry *ie)
 
virtual RouterInterfaceDatacreateRouterInterfaceData (InterfaceEntry *ie)
 
virtual HostInterfaceDatagetHostInterfaceData (InterfaceEntry *ie)
 
virtual RouterInterfaceDatagetRouterInterfaceData (InterfaceEntry *ie)
 
virtual void deleteHostInterfaceData (int interfaceId)
 
virtual void deleteRouterInterfaceData (int interfaceId)
 
virtual void configureInterface (InterfaceEntry *ie)
 
virtual void startTimer (cMessage *timer, double interval)
 
virtual void sendGeneralQuery (RouterInterfaceData *interface, double maxRespTime)
 
virtual void sendGroupSpecificQuery (RouterGroupData *group)
 
virtual void sendGroupAndSourceSpecificQuery (RouterGroupData *group, const IPv4AddressVector &sources)
 
virtual void sendGroupReport (InterfaceEntry *ie, const std::vector< GroupRecord > &records)
 
virtual void sendQueryToIP (IGMPv3Query *msg, InterfaceEntry *ie, IPv4Address dest)
 
virtual void sendReportToIP (IGMPv3Report *msg, InterfaceEntry *ie, IPv4Address dest)
 
virtual void processHostGeneralQueryTimer (cMessage *msg)
 
virtual void processHostGroupQueryTimer (cMessage *msg)
 
virtual void processRouterGeneralQueryTimer (cMessage *msg)
 
virtual void processRouterGroupTimer (cMessage *msg)
 Function for switching EXCLUDE filter mode back to INCLUDE If at least one source timer is still runing, it will switch to Include mode. More...
 
virtual void processRouterSourceTimer (cMessage *msg)
 Function for checking expired source timers if group is in INCLUDE filter mode. More...
 
virtual void processIgmpMessage (IGMPMessage *msg)
 
virtual void processQuery (IGMPv3Query *msg)
 
virtual void processReport (IGMPv3Report *msg)
 
virtual void multicastSourceListChanged (InterfaceEntry *ie, IPv4Address group, const IPv4MulticastSourceList &sourceList)
 This function is sending report message if interface state was changed. More...
 
virtual double decodeTime (unsigned char code)
 Function for computing the time value in seconds from an encoded value. More...
 

Protected Attributes

IRoutingTablert
 
IInterfaceTableift
 
bool enabled
 
int robustness
 
double queryInterval
 
double queryResponseInterval
 
double groupMembershipInterval
 
double otherQuerierPresentInterval
 
double startupQueryInterval
 
double startupQueryCount
 
double lastMemberQueryInterval
 
double lastMemberQueryCount
 
double lastMemberQueryTime
 
double unsolicitedReportInterval
 
InterfaceToHostDataMap hostData
 
InterfaceToRouterDataMap routerData
 
int numGroups
 
int numHostGroups
 
int numRouterGroups
 
int numQueriesSent
 
int numQueriesRecv
 
int numGeneralQueriesSent
 
int numGeneralQueriesRecv
 
int numGroupSpecificQueriesSent
 
int numGroupSpecificQueriesRecv
 
int numGroupAndSourceSpecificQueriesSent
 
int numGroupAndSourceSpecificQueriesRecv
 
int numReportsSent
 
int numReportsRecv
 

Member Typedef Documentation

typedef std::map<int, HostInterfaceData *> inet::IGMPv3::InterfaceToHostDataMap
protected
typedef std::map<int, RouterInterfaceData *> inet::IGMPv3::InterfaceToRouterDataMap
protected
typedef std::vector<IPv4Address> inet::IGMPv3::IPv4AddressVector
protected

Member Enumeration Documentation

enum inet::IGMPv3::FilterMode
protected
Enumerator
IGMPV3_FM_INCLUDE 
IGMPV3_FM_EXCLUDE 
62  {
65  };
Definition: IGMPv3.h:63
Definition: IGMPv3.h:64
Enumerator
IGMPV3_HGS_NON_MEMBER 
IGMPV3_HGS_DELAYING_MEMBER 
IGMPV3_HGS_IDLE_MEMBER 
Enumerator
IGMPV3_R_GENERAL_QUERY_TIMER 
IGMPV3_R_GROUP_TIMER 
IGMPV3_R_SOURCE_TIMER 
IGMPV3_H_GENERAL_QUERY_TIMER 
IGMPV3_H_GROUP_TIMER 
enum inet::IGMPv3::ReportType
protected
Enumerator
IGMPV3_RT_IS_IN 
IGMPV3_RT_IS_EX 
IGMPV3_RT_TO_IN 
IGMPV3_RT_TO_EX 
IGMPV3_RT_ALLOW 
IGMPV3_RT_BLOCK 
67  {
68  IGMPV3_RT_IS_IN = 1,
69  IGMPV3_RT_IS_EX = 2,
70  IGMPV3_RT_TO_IN = 3,
71  IGMPV3_RT_TO_EX = 4,
72  IGMPV3_RT_ALLOW = 5,
73  IGMPV3_RT_BLOCK = 6,
74  };
Definition: IGMPv3.h:73
Definition: IGMPv3.h:71
Definition: IGMPv3.h:69
Definition: IGMPv3.h:70
Definition: IGMPv3.h:72
Definition: IGMPv3.h:68
Enumerator
IGMPV3_RGS_NO_MEMBERS_PRESENT 
IGMPV3_RGS_MEMBERS_PRESENT 
IGMPV3_RGS_CHECKING_MEMBERSHIP 
enum inet::IGMPv3::RouterState
protected
Enumerator
IGMPV3_RS_INITIAL 
IGMPV3_RS_QUERIER 
IGMPV3_RS_NON_QUERIER 
44  {
48  };
Definition: IGMPv3.h:45
Definition: IGMPv3.h:46

Constructor & Destructor Documentation

inet::IGMPv3::~IGMPv3 ( )
protectedvirtual
459 {
460  while (!hostData.empty())
461  deleteHostInterfaceData(hostData.begin()->first);
462  while (!routerData.empty())
463  deleteRouterInterfaceData(routerData.begin()->first);
464 }
virtual void deleteHostInterfaceData(int interfaceId)
Definition: IGMPv3.cc:360
InterfaceToRouterDataMap routerData
Definition: IGMPv3.h:192
virtual void deleteRouterInterfaceData(int interfaceId)
Definition: IGMPv3.cc:370
InterfaceToHostDataMap hostData
Definition: IGMPv3.h:191

Member Function Documentation

void inet::IGMPv3::configureInterface ( InterfaceEntry ie)
protectedvirtual

Referenced by initialize(), and receiveSignal().

493 {
495  // start querier on this interface
496  EV_INFO << "Sending General Query on interface '" << ie->getName() << "', and scheduling next Query to '"
497  << (simTime() + startupQueryInterval) << "'.\n";
498  RouterInterfaceData *routerData = getRouterInterfaceData(ie);
499  routerData->state = IGMPV3_RS_QUERIER;
500 
502  startTimer(routerData->generalQueryTimer, startupQueryInterval);
503  }
504 }
InterfaceToRouterDataMap routerData
Definition: IGMPv3.h:192
virtual RouterInterfaceData * getRouterInterfaceData(InterfaceEntry *ie)
Definition: IGMPv3.cc:348
double startupQueryInterval
Definition: IGMPv3.h:182
double queryResponseInterval
Definition: IGMPv3.h:179
bool enabled
Definition: IGMPv3.h:176
virtual bool isMulticastForwardingEnabled() const =0
Multicast forwarding on/off.
IRoutingTable * rt
Definition: IGMPv3.h:173
Definition: IGMPv3.h:46
virtual void startTimer(cMessage *timer, double interval)
Definition: IGMPv3.cc:568
virtual void sendGeneralQuery(RouterInterfaceData *interface, double maxRespTime)
Definition: IGMPv3.cc:575
IGMPv3::HostInterfaceData * inet::IGMPv3::createHostInterfaceData ( InterfaceEntry ie)
protectedvirtual

Referenced by getHostInterfaceData().

327 {
328  return new HostInterfaceData(this, ie);
329 }
IGMPv3::RouterInterfaceData * inet::IGMPv3::createRouterInterfaceData ( InterfaceEntry ie)
protectedvirtual

Referenced by getRouterInterfaceData().

332 {
333  return new RouterInterfaceData(this, ie);
334 }
double inet::IGMPv3::decodeTime ( unsigned char  code)
protectedvirtual

Function for computing the time value in seconds from an encoded value.

Codes in the [1,127] interval are the number of 1/10 seconds, codes above 127 are contain a 3-bit exponent and a four bit mantissa and represents the (mantissa + 16) * 2^(3+exp) number of 1/10 seconds.

Referenced by processQuery().

961 {
962  unsigned time;
963  if (code < 128)
964  time = code;
965  else {
966  unsigned mantis = code & 0x15;
967  unsigned exp = (code >> 4) & 0x07;
968  time = (mantis | 0x10) << (exp + 3);
969  }
970 
971  return (double)time / 10.0;
972 }
void inet::IGMPv3::deleteHostInterfaceData ( int  interfaceId)
protectedvirtual

Referenced by receiveSignal(), and ~IGMPv3().

361 {
362  auto interfaceIt = hostData.find(interfaceId);
363  if (interfaceIt != hostData.end()) {
364  HostInterfaceData *interface = interfaceIt->second;
365  hostData.erase(interfaceIt);
366  delete interface;
367  }
368 }
InterfaceToHostDataMap hostData
Definition: IGMPv3.h:191
void inet::IGMPv3::deleteRouterInterfaceData ( int  interfaceId)
protectedvirtual

Referenced by receiveSignal(), and ~IGMPv3().

371 {
372  auto interfaceIt = routerData.find(interfaceId);
373  if (interfaceIt != routerData.end()) {
374  RouterInterfaceData *interface = interfaceIt->second;
375  routerData.erase(interfaceIt);
376  delete interface;
377  }
378 }
InterfaceToRouterDataMap routerData
Definition: IGMPv3.h:192
IGMPv3::HostInterfaceData * inet::IGMPv3::getHostInterfaceData ( InterfaceEntry ie)
protectedvirtual

Referenced by multicastSourceListChanged(), and processQuery().

337 {
338  int interfaceId = ie->getInterfaceId();
339  auto it = hostData.find(interfaceId);
340  if (it != hostData.end())
341  return it->second;
342 
343  HostInterfaceData *data = createHostInterfaceData(ie);
344  hostData[interfaceId] = data;
345  return data;
346 }
virtual HostInterfaceData * createHostInterfaceData(InterfaceEntry *ie)
Definition: IGMPv3.cc:326
InterfaceToHostDataMap hostData
Definition: IGMPv3.h:191
IGMPv3::RouterInterfaceData * inet::IGMPv3::getRouterInterfaceData ( InterfaceEntry ie)
protectedvirtual

Referenced by configureInterface(), processQuery(), and processReport().

349 {
350  int interfaceId = ie->getInterfaceId();
351  auto it = routerData.find(interfaceId);
352  if (it != routerData.end())
353  return it->second;
354 
355  RouterInterfaceData *data = createRouterInterfaceData(ie);
356  routerData[interfaceId] = data;
357  return data;
358 }
InterfaceToRouterDataMap routerData
Definition: IGMPv3.h:192
virtual RouterInterfaceData * createRouterInterfaceData(InterfaceEntry *ie)
Definition: IGMPv3.cc:331
void inet::IGMPv3::handleMessage ( cMessage *  msg)
overrideprotectedvirtual
507 {
508  if (!enabled) {
509  if (!msg->isSelfMessage()) {
510  EV << "IGMPv3 disabled, dropping packet.\n";
511  delete msg;
512  }
513  return;
514  }
515 
516  if (msg->isSelfMessage()) {
517  switch (msg->getKind()) {
520  break;
521 
524  break;
525 
528  break;
529 
532  break;
533 
536  break;
537 
538  default:
539  ASSERT(false);
540  break;
541  }
542  }
543  else
544  processIgmpMessage(check_and_cast<IGMPMessage *>(msg));
545 }
Definition: IGMPv3.h:169
bool enabled
Definition: IGMPv3.h:176
virtual void processIgmpMessage(IGMPMessage *msg)
Definition: IGMPv3.cc:547
Definition: IGMPv3.h:167
Definition: IGMPv3.h:166
virtual void processRouterGroupTimer(cMessage *msg)
Function for switching EXCLUDE filter mode back to INCLUDE If at least one source timer is still runi...
Definition: IGMPv3.cc:1266
virtual void processRouterSourceTimer(cMessage *msg)
Function for checking expired source timers if group is in INCLUDE filter mode.
Definition: IGMPv3.cc:1302
virtual void processHostGeneralQueryTimer(cMessage *msg)
Definition: IGMPv3.cc:685
virtual void processHostGroupQueryTimer(cMessage *msg)
Definition: IGMPv3.cc:733
virtual void processRouterGeneralQueryTimer(cMessage *msg)
Definition: IGMPv3.cc:639
void inet::IGMPv3::initialize ( int  stage)
overrideprotectedvirtual
381 {
382  if (stage == INITSTAGE_LOCAL) {
383  ift = getModuleFromPar<IInterfaceTable>(par("interfaceTableModule"), this);
384  rt = getModuleFromPar<IIPv4RoutingTable>(par("routingTableModule"), this);
385 
386  cModule *host = getContainingNode(this);
387  host->subscribe(NF_INTERFACE_DELETED, this);
388  host->subscribe(NF_IPv4_MCAST_CHANGE, this);
389 
390  enabled = par("enabled");
391  robustness = par("robustnessVariable");
392  queryInterval = par("queryInterval");
393  queryResponseInterval = par("queryResponseInterval");
394  groupMembershipInterval = par("groupMembershipInterval");
395  otherQuerierPresentInterval = par("otherQuerierPresentInterval");
396  startupQueryInterval = par("startupQueryInterval");
397  startupQueryCount = par("startupQueryCount");
398  lastMemberQueryInterval = par("lastMemberQueryInterval");
399  lastMemberQueryCount = par("lastMemberQueryCount");
400  lastMemberQueryTime = lastMemberQueryInterval * lastMemberQueryCount; //todo checknut ci je to takto..
401  unsolicitedReportInterval = par("unsolicitedReportInterval");
402 
403  numGroups = 0;
404  numHostGroups = 0;
405  numRouterGroups = 0;
406 
407  numQueriesSent = 0;
408  numQueriesRecv = 0;
415  numReportsSent = 0;
416  numReportsRecv = 0;
417 
418  WATCH(numGroups);
419  WATCH(numHostGroups);
420  WATCH(numRouterGroups);
421 
422  WATCH(numQueriesSent);
423  WATCH(numQueriesRecv);
424  WATCH(numGeneralQueriesSent);
425  WATCH(numGeneralQueriesRecv);
430  WATCH(numReportsSent);
431  WATCH(numReportsRecv);
432 
433  IPSocket ipSocket(gate("ipOut"));
434  ipSocket.registerProtocol(IP_PROT_IGMP);
435  }
436  else if (stage == INITSTAGE_NETWORK_LAYER) {
437  for (int i = 0; i < (int)ift->getNumInterfaces(); ++i) {
438  InterfaceEntry *ie = ift->getInterface(i);
439  if (ie->isMulticast())
440  configureInterface(ie);
441  }
442 
443  cModule *host = getContainingNode(this);
444  host->subscribe(NF_INTERFACE_CREATED, this);
445  }
446  else if (stage == INITSTAGE_NETWORK_LAYER_2) { // ipv4Data() created in INITSTAGE_NETWORK_LAYER
447  // in multicast routers: join to ALL_IGMPv3_ROUTERS_MCAST address on all interfaces
448  if (enabled && rt->isMulticastForwardingEnabled()) {
449  for (int i = 0; i < (int)ift->getNumInterfaces(); ++i) {
450  InterfaceEntry *ie = ift->getInterface(i);
451  if (ie->isMulticast())
453  }
454  }
455  }
456 }
IInterfaceTable * ift
Definition: IGMPv3.h:174
double lastMemberQueryInterval
Definition: IGMPv3.h:184
IPv4InterfaceData * ipv4Data() const
Definition: InterfaceEntry.h:221
int numGroupSpecificQueriesRecv
Definition: IGMPv3.h:203
int numHostGroups
Definition: IGMPv3.h:195
double startupQueryInterval
Definition: IGMPv3.h:182
int numQueriesSent
Definition: IGMPv3.h:198
int numGroupAndSourceSpecificQueriesRecv
Definition: IGMPv3.h:205
virtual void joinMulticastGroup(const IPv4Address &multicastAddress)
Definition: IPv4InterfaceData.cc:205
int numGroups
Definition: IGMPv3.h:194
double lastMemberQueryCount
Definition: IGMPv3.h:185
static const IPv4Address ALL_IGMPV3_ROUTERS_MCAST
224.0.0.22 All IGMPv3 routers
Definition: IPv4Address.h:112
double startupQueryCount
Definition: IGMPv3.h:183
double queryResponseInterval
Definition: IGMPv3.h:179
bool enabled
Definition: IGMPv3.h:176
int numReportsSent
Definition: IGMPv3.h:206
simsignal_t NF_IPv4_MCAST_CHANGE
Definition: NotifierConsts.cc:66
int numReportsRecv
Definition: IGMPv3.h:207
Initialization of network-layer protocols, stage 1.
Definition: InitStages.h:72
Local initializations.
Definition: InitStages.h:35
cModule * getContainingNode(const cModule *from)
Find the node containing the given module.
Definition: ModuleAccess.cc:65
virtual int getNumInterfaces() const =0
Returns the number of interfaces.
simsignal_t NF_INTERFACE_CREATED
Definition: NotifierConsts.cc:48
double otherQuerierPresentInterval
Definition: IGMPv3.h:181
int numQueriesRecv
Definition: IGMPv3.h:199
int numGeneralQueriesRecv
Definition: IGMPv3.h:201
int numRouterGroups
Definition: IGMPv3.h:196
double groupMembershipInterval
Definition: IGMPv3.h:180
IRoutingTable * rt
Definition: IGMPv3.h:173
Initialization of network-layer protocols, stage 2.
Definition: InitStages.h:78
double queryInterval
Definition: IGMPv3.h:178
int numGroupAndSourceSpecificQueriesSent
Definition: IGMPv3.h:204
virtual void configureInterface(InterfaceEntry *ie)
Definition: IGMPv3.cc:492
simsignal_t NF_INTERFACE_DELETED
Definition: NotifierConsts.cc:49
int numGeneralQueriesSent
Definition: IGMPv3.h:200
double lastMemberQueryTime
Definition: IGMPv3.h:186
virtual InterfaceEntry * getInterface(int pos) const =0
Returns the InterfaceEntry specified by an index 0..numInterfaces-1.
Definition: IPProtocolId_m.h:78
double unsolicitedReportInterval
Definition: IGMPv3.h:187
int numGroupSpecificQueriesSent
Definition: IGMPv3.h:202
int robustness
Definition: IGMPv3.h:177
void inet::IGMPv3::multicastSourceListChanged ( InterfaceEntry ie,
IPv4Address  group,
const IPv4MulticastSourceList sourceList 
)
protectedvirtual

This function is sending report message if interface state was changed.

See RFC 3376 5.1.

Referenced by receiveSignal().

774 {
775  ASSERT(ie);
776  ASSERT(isSorted(sourceList.sources));
777 
778  if (!enabled || group.isLinkLocalMulticast())
779  return;
780 
781  HostInterfaceData *interfaceData = getHostInterfaceData(ie);
782  HostGroupData *groupData = interfaceData->getOrCreateGroupData(group);
783 
784  FilterMode filter = sourceList.filterMode == MCAST_INCLUDE_SOURCES ? IGMPV3_FM_INCLUDE : IGMPV3_FM_EXCLUDE;
785 
786  EV_DETAIL_C("test") << "State of group '" << group << "' on interface '" << ie->getName() << "' has changed:\n";
787  EV_DETAIL_C("test") << " Old state: " << groupData->getStateInfo() << ".\n";
788  EV_DETAIL_C("test") << " New state: " << (filter == IGMPV3_FM_INCLUDE ? "INCLUDE" : "EXCLUDE") << sourceList.sources << ".\n";
789 
790  // Check if IF state is different
791  if (!(groupData->filter == filter) || !(groupData->sourceAddressList == sourceList.sources)) {
792  // INCLUDE(A) -> INCLUDE(B): Send ALLOW(B-A), BLOCK(A-B)
793  if (groupData->filter == IGMPV3_FM_INCLUDE && filter == IGMPV3_FM_INCLUDE && groupData->sourceAddressList != sourceList.sources) {
794  EV_DETAIL << "Sending ALLOW/BLOCK report.\n";
795  vector<GroupRecord> records(2);
796  records[0].groupAddress = group;
797  records[0].recordType = IGMPV3_RT_ALLOW;
798  records[0].sourceList = set_complement(sourceList.sources, groupData->sourceAddressList);
799  records[1].groupAddress = group;
800  records[1].recordType = IGMPV3_RT_BLOCK;
801  records[1].sourceList = set_complement(groupData->sourceAddressList, sourceList.sources);
802  records.erase(remove_if(records.begin(), records.end(), isEmptyRecord), records.end());
803  if (!records.empty())
804  sendGroupReport(ie, records);
805  }
806  // EXCLUDE(A) -> EXCLUDE(B): Send ALLOW(A-B), BLOCK(B-A)
807  else if (groupData->filter == IGMPV3_FM_EXCLUDE && filter == IGMPV3_FM_EXCLUDE && groupData->sourceAddressList != sourceList.sources) {
808  EV_DETAIL << "Sending ALLOW/BLOCK report.\n";
809  vector<GroupRecord> records(2);
810  records[0].groupAddress = group;
811  records[0].recordType = IGMPV3_RT_ALLOW;
812  records[0].sourceList = set_complement(groupData->sourceAddressList, sourceList.sources);
813  records[1].groupAddress = group;
814  records[1].recordType = IGMPV3_RT_BLOCK;
815  records[1].sourceList = set_complement(sourceList.sources, groupData->sourceAddressList);
816  records.erase(remove_if(records.begin(), records.end(), isEmptyRecord), records.end());
817  if (!records.empty())
818  sendGroupReport(ie, records);
819  }
820  // INCLUDE(A) -> EXCLUDE(B): Send TO_EX(B)
821  else if (groupData->filter == IGMPV3_FM_INCLUDE && filter == IGMPV3_FM_EXCLUDE) {
822  EV_DETAIL << "Sending TO_EX report.\n";
823  vector<GroupRecord> records(1);
824  records[0].groupAddress = group;
825  records[0].recordType = IGMPV3_RT_TO_EX;
826  records[0].sourceList = sourceList.sources;
827  sendGroupReport(ie, records);
828  }
829  // EXCLUDE(A) -> INCLUDE(B): Send TO_IN(B)
830  else if (groupData->filter == IGMPV3_FM_EXCLUDE && filter == IGMPV3_FM_INCLUDE) {
831  EV_DETAIL << "Sending TO_IN report.\n";
832  vector<GroupRecord> records(1);
833  records[0].groupAddress = group;
834  records[0].recordType = IGMPV3_RT_TO_IN;
835  records[0].sourceList = sourceList.sources;
836  sendGroupReport(ie, records);
837  }
838 
839  // Go to new state
840  groupData->filter = filter;
841  groupData->sourceAddressList = sourceList.sources;
842  sort(groupData->sourceAddressList.begin(), groupData->sourceAddressList.end());
843  }
844 
845  // FIXME missing: the report is retransmitted [Robustness Variable] - 1 more times,
846  // at intervals chosen at random from the range (0, [Unsolicited Report Interval])
847 
848  // FIXME if an interface change occured when there is a pending report, then
849  // the groups of the old report and the new report are to be merged.
850 }
Definition: IGMPv3.h:73
Definition: IGMPv3.h:71
virtual void sendGroupReport(InterfaceEntry *ie, const std::vector< GroupRecord > &records)
Definition: IGMPv3.cc:974
Definition: IGMPv3.h:70
bool enabled
Definition: IGMPv3.h:176
virtual HostInterfaceData * getHostInterfaceData(InterfaceEntry *ie)
Definition: IGMPv3.cc:336
Definition: IGMPv3.h:63
void sort(std::vector< T > &v)
Definition: stlutils.h:112
Definition: IGMPv3.h:64
FilterMode
Definition: IGMPv3.h:62
Definition: InterfaceEntry.h:44
Definition: IGMPv3.h:72
if(!(yy_init))
Definition: lexer.cc:1644
virtual int inet::IGMPv3::numInitStages ( ) const
inlineoverrideprotectedvirtual
210 { return NUM_INIT_STAGES; }
The number of initialization stages.
Definition: InitStages.h:116
void inet::IGMPv3::processHostGeneralQueryTimer ( cMessage *  msg)
protectedvirtual

Referenced by handleMessage().

686 {
687  HostInterfaceData *interfaceData = (HostInterfaceData *)msg->getContextPointer();
688  InterfaceEntry *ie = interfaceData->ie;
689  ASSERT(ie);
690 
691  EV_INFO << "Response timer to a General Query on interface '" << ie->getName() << "' has expired.\n";
692 
693  //HostInterfaceData *interfaceData = getHostInterfaceData(ie);
694  IGMPv3Report *report = new IGMPv3Report("IGMPv3 report");
695  unsigned int byteLength = 8; // IGMPv3Report header size
696  report->setType(IGMPV3_MEMBERSHIP_REPORT);
697  int counter = 0;
698  report->setGroupRecordArraySize(interfaceData->groups.size());
699 
700  // FIXME Do not create reports larger than MTU of the interface
701  //
702 
703  /*
704  * creating GroupRecord for each group on interface
705  */
706  for (auto & elem : interfaceData->groups) {
707  GroupRecord gr;
708  if (elem.second->filter == IGMPV3_FM_INCLUDE) {
709  gr.recordType = IGMPV3_RT_IS_IN;
710  }
711  else if (elem.second->filter == IGMPV3_FM_EXCLUDE) {
712  gr.recordType = IGMPV3_RT_IS_EX;
713  }
714  gr.groupAddress = elem.second->groupAddr;
715  gr.sourceList = elem.second->sourceAddressList;
716  report->setGroupRecord(counter++, gr);
717  byteLength += 8 + gr.sourceList.size() * 4; // 8 byte header + n * 4 byte (IPv4Address)
718  }
719  report->setByteLength(byteLength);
720 
721  if (counter != 0) { //if no record created, dont need to send report
722  EV_INFO << "Sending response to a General Query on interface '" << ie->getName() << "'.\n";
724  numReportsSent++;
725  }
726  else {
727  EV_INFO << "There are no multicast listeners, no response is sent to a General Query on interface '" << ie->getName() << "'.\n";
728  delete report;
729  }
730 }
Definition: IGMPMessage_m.h:62
virtual void sendReportToIP(IGMPv3Report *msg, InterfaceEntry *ie, IPv4Address dest)
Definition: IGMPv3.cc:656
static const IPv4Address ALL_IGMPV3_ROUTERS_MCAST
224.0.0.22 All IGMPv3 routers
Definition: IPv4Address.h:112
Definition: IGMPv3.h:69
int numReportsSent
Definition: IGMPv3.h:206
Definition: IGMPv3.h:63
Definition: IGMPv3.h:64
Definition: IGMPv3.h:68
void inet::IGMPv3::processHostGroupQueryTimer ( cMessage *  msg)
protectedvirtual

Referenced by handleMessage().

734 {
735  HostGroupData *group = (HostGroupData *)msg->getContextPointer();
736  InterfaceEntry *ie = group->parent->ie;
737 
738  vector<GroupRecord> records(1);
739 
740  //checking if query is group or group-and-source specific
741  if (group->queriedSources.empty()) {
742  // Send report for a Group-Specific Query
743  EV_INFO << "Response timer for a Group-Specific Query for group '" << group->groupAddr << "' on interface '" << ie->getName() << "'\n";
744 
745  records[0].groupAddress = group->groupAddr;
746  records[0].recordType = group->filter == IGMPV3_FM_INCLUDE ? IGMPV3_RT_IS_IN : IGMPV3_RT_IS_EX;
747  records[0].sourceList = group->sourceAddressList;
748  sendGroupReport(ie, records);
749  }
750  else {
751  // Send report for a Group-and-Source-Specific Query
752  EV_INFO << "Response timer for a Group-and-Source-Specific Query for group '" << group->groupAddr << "' on interface '" << ie->getName() << "'\n";
753 
754  records[0].groupAddress = group->groupAddr;
755  records[0].recordType = IGMPV3_RT_IS_IN;
756  records[0].sourceList = group->filter == IGMPV3_FM_INCLUDE ? set_intersection(group->sourceAddressList, group->queriedSources) :
757  set_complement(group->queriedSources, group->sourceAddressList);
758  sendGroupReport(ie, records);
759  }
760 
761  group->queriedSources.clear();
762 }
virtual void sendGroupReport(InterfaceEntry *ie, const std::vector< GroupRecord > &records)
Definition: IGMPv3.cc:974
Definition: IGMPv3.h:69
Definition: IGMPv3.h:63
Definition: IGMPv3.h:68
void inet::IGMPv3::processIgmpMessage ( IGMPMessage msg)
protectedvirtual

Referenced by handleMessage().

548 {
549  switch (msg->getType()) {
551  if (dynamic_cast<IGMPv3Query *>(msg))
552  processQuery((IGMPv3Query *)msg);
553  else
554  /* TODO process v1 and v2 queries*/;
555  break;
556 
558  processReport(check_and_cast<IGMPv3Report *>(msg));
559  break;
560 
561  // TODO process v1/v2 reports
562  default:
563  //delete msg;
564  throw cRuntimeError("IGMPv3: Unhandled message type (%dq)", msg->getType());
565  }
566 }
Definition: IGMPMessage_m.h:62
Definition: IGMPMessage_m.h:58
virtual void processReport(IGMPv3Report *msg)
Definition: IGMPv3.cc:993
virtual void processQuery(IGMPv3Query *msg)
Definition: IGMPv3.cc:853
void inet::IGMPv3::processQuery ( IGMPv3Query msg)
protectedvirtual

Referenced by processIgmpMessage().

854 {
855  IPv4ControlInfo *controlInfo = (IPv4ControlInfo *)msg->getControlInfo();
856  InterfaceEntry *ie = ift->getInterfaceById(controlInfo->getInterfaceId());
857  IPv4Address groupAddr = msg->getGroupAddress();
858  IPv4AddressVector& queriedSources = msg->getSourceList();
859  double maxRespTime = decodeTime(msg->getMaxRespCode());
860 
861  ASSERT(ie->isMulticast());
862 
863  EV_INFO << "Received IGMPv3 query on interface '" << ie->getName() << "' for group '" << groupAddr << "'.\n";
864 
865  HostInterfaceData *interfaceData = getHostInterfaceData(ie);
866 
867  numQueriesRecv++;
868 
869  double delay = uniform(0.0, maxRespTime);
870 
871  // Rules from RFC page 22:
872  if (interfaceData->generalQueryTimer->isScheduled() && interfaceData->generalQueryTimer->getArrivalTime() < simTime() + delay) {
873  // 1. If there is a pending response to a previous General Query
874  // scheduled sooner than the selected delay, no additional response
875  // needs to be scheduled.
876  EV_DETAIL << "There is a pending response to a previous General Query, no further response is scheduled.\n";
877  }
878  else if (groupAddr.isUnspecified() && queriedSources.empty()) {
879  // 2. If the received Query is a General Query, the interface timer is
880  // used to schedule a response to the General Query after the
881  // selected delay. Any previously pending response to a General
882  // Query is canceled.
883  EV_DETAIL << "Received a General Query, scheduling report with delay=" << delay << ".\n";
884  startTimer(interfaceData->generalQueryTimer, delay);
885  }
886  else if (!groupAddr.isUnspecified()) {
887  HostGroupData *groupData = interfaceData->getOrCreateGroupData(groupAddr);
888 
889  if (!groupData->timer->isScheduled()) {
890  // 3. If the received Query is a Group-Specific Query or a Group-and-
891  // Source-Specific Query and there is no pending response to a
892  // previous Query for this group, then the group timer is used to
893  // schedule a report. If the received Query is a Group-and-Source-
894  // Specific Query, the list of queried sources is recorded to be used
895  // when generating a response.
896  EV_DETAIL << "Received Group" << (queriedSources.empty() ? "" : "-and-Source") << "-Specific Query, "
897  << "scheduling report with delay=" << delay << ".\n";
898 
899  sort(queriedSources.begin(), queriedSources.end());
900  groupData->queriedSources = queriedSources;
901  startTimer(groupData->timer, delay);
902  }
903  else if (queriedSources.empty()) {
904  //4. If there already is a pending response to a previous Query
905  // scheduled for this group, and either the new Query is a Group-
906  // Specific Query or the recorded source-list associated with the
907  // group is empty, then the group source-list is cleared and a single
908  // response is scheduled using the group timer. The new response is
909  // scheduled to be sent at the earliest of the remaining time for the
910  // pending report and the selected delay.
911  EV_DETAIL << "Received Group-Specific Query, scheduling report with delay="
912  << min(delay, SIMTIME_DBL(groupData->timer->getArrivalTime() - simTime())) << ".\n";
913 
914  sort(queriedSources.begin(), queriedSources.end());
915  groupData->queriedSources = queriedSources;
916  if (groupData->timer->getArrivalTime() > simTime() + delay)
917  startTimer(groupData->timer, delay);
918  }
919  else {
920  // 5. If the received Query is a Group-and-Source-Specific Query and
921  // there is a pending response for this group with a non-empty
922  // source-list, then the group source list is augmented to contain
923  // the list of sources in the new Query and a single response is
924  // scheduled using the group timer. The new response is scheduled to
925  // be sent at the earliest of the remaining time for the pending
926  // report and the selected delay.
927  EV_DETAIL << "Received Group-and-Source-Specific Query, combining sources with the sources of pending report, "
928  << "and scheduling a new report with delay="
929  << min(delay, SIMTIME_DBL(groupData->timer->getArrivalTime() - simTime())) << ".\n";
930 
931  if (groupData->timer->getArrivalTime() > simTime() + delay) {
932  sort(queriedSources.begin(), queriedSources.end());
933  groupData->queriedSources = set_union(groupData->queriedSources, queriedSources);
934  startTimer(groupData->timer, delay);
935  }
936  }
937  }
938 
939 // Router part | Querier Election
941  //Querier Election
942  RouterInterfaceData *routerInterfaceData = getRouterInterfaceData(ie);
943  if (controlInfo->getSrcAddr() < ie->ipv4Data()->getIPAddress()) {
944  startTimer(routerInterfaceData->generalQueryTimer, otherQuerierPresentInterval);
945  routerInterfaceData->state = IGMPV3_RS_NON_QUERIER;
946  }
947 
948  if (!groupAddr.isUnspecified() && routerInterfaceData->state == IGMPV3_RS_NON_QUERIER) { // group specific query
949  RouterGroupData *groupData = routerInterfaceData->getOrCreateGroupData(groupAddr);
950  if (groupData->state == IGMPV3_RGS_MEMBERS_PRESENT) {
951  double maxResponseTime = maxRespTime;
952  startTimer(groupData->timer, maxResponseTime * lastMemberQueryCount);
953  groupData->state = IGMPV3_RGS_CHECKING_MEMBERSHIP;
954  }
955  }
956  }
957  delete msg;
958 }
virtual double decodeTime(unsigned char code)
Function for computing the time value in seconds from an encoded value.
Definition: IGMPv3.cc:960
IInterfaceTable * ift
Definition: IGMPv3.h:174
virtual InterfaceEntry * getInterfaceById(int id) const =0
Returns an interface by its Id.
virtual RouterInterfaceData * getRouterInterfaceData(InterfaceEntry *ie)
Definition: IGMPv3.cc:348
double lastMemberQueryCount
Definition: IGMPv3.h:185
double min(const double a, const double b)
Returns the minimum of a and b.
Definition: SCTPAssociation.h:270
virtual HostInterfaceData * getHostInterfaceData(InterfaceEntry *ie)
Definition: IGMPv3.cc:336
double otherQuerierPresentInterval
Definition: IGMPv3.h:181
void sort(std::vector< T > &v)
Definition: stlutils.h:112
virtual bool isMulticastForwardingEnabled() const =0
Multicast forwarding on/off.
int numQueriesRecv
Definition: IGMPv3.h:199
IRoutingTable * rt
Definition: IGMPv3.h:173
std::vector< IPv4Address > IPv4AddressVector
Definition: IGMPv3.h:42
virtual void startTimer(cMessage *timer, double interval)
Definition: IGMPv3.cc:568
void inet::IGMPv3::processReport ( IGMPv3Report msg)
protectedvirtual

Referenced by processIgmpMessage().

994 {
995  IPv4ControlInfo *controlInfo = (IPv4ControlInfo *)msg->getControlInfo();
996  InterfaceEntry *ie = ift->getInterfaceById(controlInfo->getInterfaceId());
997  ASSERT(ie->isMulticast());
998 
999  EV_INFO << "Received IGMPv3 Membership Report on interface '" << ie->getName() << "'.\n";
1000 
1001  numReportsRecv++;
1002 
1004  RouterInterfaceData *interfaceData = getRouterInterfaceData(ie);
1005 
1006  for (unsigned int i = 0; i < msg->getGroupRecordArraySize(); i++) {
1007  GroupRecord gr = msg->getGroupRecord(i);
1008  EV_DETAIL << "Found a record for group '" << gr.groupAddress << "'.\n";
1009 
1010  // ensure that the received sources are sorted
1011  sort(gr.sourceList.begin(), gr.sourceList.end());
1012  IPv4AddressVector& receivedSources = gr.sourceList; // sorted
1013 
1014  RouterGroupData *groupData = interfaceData->getOrCreateGroupData(gr.groupAddress);
1015 
1016  IPv4MulticastSourceList oldSourceList;
1017  groupData->collectForwardedSources(oldSourceList);
1018 
1019  EV_DETAIL << "Router State is " << groupData->getStateInfo() << ".\n";
1020 
1021  // RFC 3376 6.4.1: Reception of Current State Record
1022  if (gr.recordType == IGMPV3_RT_IS_IN) {
1023  EV_DETAIL << "Received IS_IN" << receivedSources << " report.\n";
1024  // INCLUDE(A) -> IS_IN(B) -> INCLUDE(A+B) : (B) = GMI
1025  // EXCLUDE(X,Y) -> IS_IN(A) -> EXCLUDE(X+A,Y-A): (A) = GMI
1026  for (auto & receivedSource : receivedSources) {
1027  EV_DETAIL << "Setting source timer of '" << receivedSource << "' to '" << groupMembershipInterval << "'.\n";
1028  SourceRecord *record = groupData->getOrCreateSourceRecord(receivedSource);
1029  startTimer(record->sourceTimer, groupMembershipInterval);
1030  }
1031  }
1032  else if (gr.recordType == IGMPV3_RT_IS_EX) {
1033  EV_DETAIL << "Received IS_EX" << receivedSources << " report.\n";
1034 
1035  // Group Timer = GMI
1036  EV_DETAIL << "Setting group timer to '" << groupMembershipInterval << "'.\n";
1037  startTimer(groupData->timer, groupMembershipInterval);
1038 
1039  // INCLUDE(A) -> IS_EX(B) -> EXCLUDE(A*B,B-A): Delete (A-B)
1040  // EXCLUDE(X,Y) -> IS_EX(A) -> EXCLUDE(A-Y,Y*A): Delete (X-A) Delete (Y-A)
1041  for (auto it = groupData->sources.begin(); it != groupData->sources.end(); ++it) {
1042  if (find(receivedSources.begin(), receivedSources.end(), it->first) == receivedSources.end()) {
1043  EV_DETAIL << "Deleting source record of '" << it->first << "'.\n";
1044  groupData->deleteSourceRecord(it->first);
1045  }
1046  }
1047 
1048  // Router State == INCLUDE(A), Report == IS_EX(B): (B-A) = 0
1049  // Router State == EXCLUDE(X,Y), Report == IS_EX(A): (A-X-Y) = GMI
1050  for (auto & receivedSource : receivedSources) {
1051  if (!groupData->hasSourceRecord(receivedSource)) {
1052  SourceRecord *record = groupData->createSourceRecord(receivedSource);
1053  double timerValue = groupData->filter == IGMPV3_FM_INCLUDE ? 0.0 : groupMembershipInterval;
1054  EV_DETAIL << "Setting source timer of '" << receivedSource << "' to '" << timerValue << "'.\n";
1055  if (timerValue > 0)
1056  startTimer(record->sourceTimer, groupMembershipInterval);
1057  }
1058  }
1059 
1060  groupData->filter = IGMPV3_FM_EXCLUDE;
1061  }
1062  // RFC 3376 6.4.2: Reception of Filter-Mode-Change and Source-List-Change Records
1063  else if (gr.recordType == IGMPV3_RT_ALLOW) {
1064  EV_DETAIL << "Received ALLOW" << receivedSources << " report.\n";
1065 
1066  // INCLUDE(A) -> ALLOW(B) -> INCLUDE(A+B): (B) = GMI
1067  // EXCLUDE(X,Y) -> ALLOW(A) -> EXCLUDE(X+A,Y-A): (A) = GMI
1068  for (auto & receivedSource : receivedSources) {
1069  EV_DETAIL << "Setting source timer of '" << receivedSource << "' to '" << groupMembershipInterval << "'.\n";
1070  SourceRecord *record = groupData->getOrCreateSourceRecord(receivedSource);
1071  startTimer(record->sourceTimer, groupMembershipInterval);
1072  }
1073  }
1074  else if (gr.recordType == IGMPV3_RT_BLOCK) {
1075  EV_DETAIL << "Received BLOCK" << receivedSources << " report.\n";
1076 
1077  if (groupData->filter == IGMPV3_FM_INCLUDE) {
1078  // INCLUDE(A) -> BLOCK(B) -> INCLUDE(A): Send Q(G,A*B)
1079  IPv4AddressVector sourcesA;
1080  for (auto & elem : groupData->sources)
1081  sourcesA.push_back(elem.first);
1082 
1083  IPv4AddressVector aIntersectB = set_intersection(sourcesA, receivedSources);
1084  if (!aIntersectB.empty()) {
1085  EV_INFO << "Sending Group-and-Source-Specific Query for group '" << groupData->groupAddr
1086  << "' on interface '" << ie->getName() << "'.\n";
1087  sendGroupAndSourceSpecificQuery(groupData, aIntersectB);
1088  }
1089  }
1090  else if (groupData->filter == IGMPV3_FM_EXCLUDE) {
1091  // EXCLUDE (X,Y) -> BLOCK (A) -> EXCLUDE (X+(A-Y),Y): (A-X-Y)=Group Timer
1092  for (auto it = groupData->sources.begin(); it != groupData->sources.end(); ++it) {
1093  if (!groupData->hasSourceRecord(it->first)) {
1094  SourceRecord *record = groupData->createSourceRecord(it->first);
1095  double grouptimertime = groupData->timer->getArrivalTime().dbl() - simTime().dbl();
1096  EV_DETAIL << "Setting source timer of '" << it->first << "' to '" << grouptimertime << "'.\n";
1097  startTimer(record->sourceTimer, grouptimertime);
1098  }
1099  }
1100  // Send Q(G,A-Y)
1101  IPv4AddressVector ySources;
1102  for (auto & elem : groupData->sources) {
1103  if (!elem.second->sourceTimer->isScheduled()) {
1104  ySources.push_back(elem.first);
1105  }
1106  }
1107  IPv4AddressVector aMinusY = set_complement(receivedSources, ySources);
1108  if (!aMinusY.empty()) {
1109  EV_INFO << "Sending Group-and-Source-Specific Query for group '" << groupData->groupAddr
1110  << "' on interface '" << ie->getName() << "'.\n";
1111  sendGroupAndSourceSpecificQuery(groupData, aMinusY);
1112  }
1113  }
1114  }
1115  else if (gr.recordType == IGMPV3_RT_TO_IN) {
1116  EV_DETAIL << "Received TO_IN" << receivedSources << " report.\n";
1117 
1118  if (groupData->filter == IGMPV3_FM_INCLUDE) {
1119  // INCLUDE(A) -> TO_IN (B) -> INCLUDE (A+B): (B)=GMI
1120  for (auto & receivedSource : receivedSources) {
1121  EV_DETAIL << "Setting source timer of '" << receivedSource << "' to '" << groupMembershipInterval << "'.\n";
1122  SourceRecord *record = groupData->getOrCreateSourceRecord(receivedSource);
1123  startTimer(record->sourceTimer, groupMembershipInterval);
1124  }
1125  // Send Q(G,A-B)
1126  IPv4AddressVector sourcesA;
1127  for (auto & elem : groupData->sources)
1128  sourcesA.push_back(elem.first);
1129  IPv4AddressVector aMinusB = set_complement(sourcesA, receivedSources);
1130  if (!aMinusB.empty()) {
1131  EV_INFO << "Sending Group-and-Source-Specific Query for group '" << groupData->groupAddr
1132  << "' on interface '" << ie->getName() << "'.\n";
1133  sendGroupAndSourceSpecificQuery(groupData, aMinusB);
1134  }
1135  }
1136  else if (groupData->filter == IGMPV3_FM_EXCLUDE) {
1137  // compute X before modifying the state
1138  IPv4AddressVector sourcesX;
1139  for (auto & elem : groupData->sources) {
1140  if (elem.second->sourceTimer->isScheduled())
1141  sourcesX.push_back(elem.first);
1142  }
1143 
1144  // EXCLUDE(X,Y) -> TO_IN(A) -> EXCLUDE(X+A,Y-A): (A) = GMI
1145  for (auto & receivedSource : receivedSources) {
1146  EV_DETAIL << "Setting source timer of '" << receivedSource << "' to '" << groupMembershipInterval << "'.\n";
1147  SourceRecord *record = groupData->getOrCreateSourceRecord(receivedSource);
1148  startTimer(record->sourceTimer, groupMembershipInterval);
1149  }
1150 
1151  // Send Q(G,X-A)
1152  IPv4AddressVector xMinusA = set_complement(sourcesX, receivedSources);
1153  if (!xMinusA.empty()) {
1154  EV_INFO << "Sending Group-and-Source-Specific Query for group '" << groupData->groupAddr
1155  << "' on interface '" << ie->getName() << "'.\n";
1156  sendGroupAndSourceSpecificQuery(groupData, xMinusA);
1157  }
1158 
1159  // Send Q(G)
1160  EV_INFO << "Sending Group-Specific Query for group '" << groupData->groupAddr
1161  << "' on interface '" << ie->getName() << "'.\n";
1162  sendGroupSpecificQuery(groupData);
1163  }
1164  }
1165  else if (gr.recordType == IGMPV3_RT_TO_EX) {
1166  EV_DETAIL << "Received TO_EX" << receivedSources << " report.\n";
1167 
1168  if (groupData->filter == IGMPV3_FM_INCLUDE) {
1169  // INCLUDE (A) -> TO_EX(B) -> EXCLUDE (A*B,B-A): Group Timer = GMI
1170  EV_DETAIL << "Setting group timer to '" << groupMembershipInterval << "'.\n";
1171  startTimer(groupData->timer, groupMembershipInterval);
1172 
1173  //change to mode exclude
1174  groupData->filter = IGMPV3_FM_EXCLUDE;
1175 
1176  // save A
1177  IPv4AddressVector sourcesA;
1178  for (auto & elem : groupData->sources)
1179  sourcesA.push_back(elem.first);
1180 
1181  // (B-A) = 0
1182  for (auto & receivedSource : receivedSources) {
1183  if (!groupData->hasSourceRecord(receivedSource)) {
1184  EV_DETAIL << "Setting source timer of '" << receivedSource << "' to '0'.\n";
1185  groupData->createSourceRecord(receivedSource);
1186  }
1187  }
1188 
1189  // Delete A-B
1190  for (auto & elem : sourcesA) {
1191  if (find(receivedSources.begin(), receivedSources.end(), elem) == receivedSources.end()) {
1192  EV_DETAIL << "Deleting source record of '" << elem << "'.\n";
1193  groupData->deleteSourceRecord(elem);
1194  }
1195  }
1196 
1197  // Send Q(G,A*B)
1198  IPv4AddressVector aIntersectB = set_intersection(sourcesA, receivedSources);
1199  if (!aIntersectB.empty()) {
1200  EV_INFO << "Sending Group-Specific Query for group '" << groupData->groupAddr
1201  << "' on interface '" << ie->getName() << "'.\n";
1202  sendGroupAndSourceSpecificQuery(groupData, aIntersectB);
1203  }
1204  }
1205  else if (groupData->filter == IGMPV3_FM_EXCLUDE) {
1206  // EXCLUDE (X,Y) -> TO_EX (A) -> EXCLUDE (A-Y,Y*A): Group Timer = GMI
1207  EV_DETAIL << "Setting group timer to '" << groupMembershipInterval << "'.\n";
1208  startTimer(groupData->timer, groupMembershipInterval);
1209 
1210  // save Y
1211  IPv4AddressVector sourcesY;
1212  for (auto & elem : groupData->sources) {
1213  if (!elem.second->sourceTimer->isScheduled())
1214  sourcesY.push_back(elem.first);
1215  }
1216 
1217  // Delete (X-A) Delete (Y-A)
1218  for (auto it = groupData->sources.begin(); it != groupData->sources.end(); ) {
1219  auto rec = it->first;
1220  ++it; // let's advance the iterator now because the deleteSourcerecord call will invalidate it and we wont be able to increment it after that
1221  if (find(receivedSources.begin(), receivedSources.end(), it->first) == receivedSources.end()) {
1222  EV_DETAIL << "Deleting source record of '" << rec << "'.\n";
1223  groupData->deleteSourceRecord(rec);
1224  }
1225  }
1226 
1227  // (A-X-Y) = GMI FIXME should be set to Group Timer
1228  for (auto & receivedSource : receivedSources) {
1229  if (!groupData->hasSourceRecord(receivedSource)) {
1230  EV_DETAIL << "Setting source timer of '" << receivedSource << "' to '" << groupMembershipInterval << "'.\n";
1231  SourceRecord *record = groupData->createSourceRecord(receivedSource);
1232  startTimer(record->sourceTimer, groupMembershipInterval);
1233  }
1234  }
1235 
1236  // Send Q(G,A-Y)
1237  IPv4AddressVector aMinusY = set_complement(receivedSources, sourcesY);
1238  if (!aMinusY.empty()) {
1239  EV_INFO << "Sending Group-Specific Query for group '" << groupData->groupAddr
1240  << "' on interface '" << ie->getName() << "'.\n";
1241  sendGroupAndSourceSpecificQuery(groupData, aMinusY);
1242  }
1243  }
1244  }
1245 
1246  EV_DETAIL << "New Router State is " << groupData->getStateInfo() << ".\n";
1247 
1248  // update interface state
1249  IPv4MulticastSourceList newSourceList;
1250  groupData->collectForwardedSources(newSourceList);
1251 
1252  if (newSourceList != oldSourceList) {
1253  ie->ipv4Data()->setMulticastListeners(groupData->groupAddr, newSourceList.filterMode, newSourceList.sources);
1254  // TODO notifications?
1255  }
1256  }
1257  }
1258  delete msg;
1259 }
IInterfaceTable * ift
Definition: IGMPv3.h:174
virtual InterfaceEntry * getInterfaceById(int id) const =0
Returns an interface by its Id.
Definition: IGMPv3.h:73
virtual RouterInterfaceData * getRouterInterfaceData(InterfaceEntry *ie)
Definition: IGMPv3.cc:348
Definition: IGMPv3.h:71
virtual void sendGroupSpecificQuery(RouterGroupData *group)
Definition: IGMPv3.cc:594
Definition: IGMPv3.h:69
Definition: IGMPv3.h:70
int numReportsRecv
Definition: IGMPv3.h:207
Definition: IGMPv3.h:63
virtual void sendGroupAndSourceSpecificQuery(RouterGroupData *group, const IPv4AddressVector &sources)
Definition: IGMPv3.cc:619
void sort(std::vector< T > &v)
Definition: stlutils.h:112
virtual bool isMulticastForwardingEnabled() const =0
Multicast forwarding on/off.
Definition: IGMPv3.h:64
double groupMembershipInterval
Definition: IGMPv3.h:180
IRoutingTable * rt
Definition: IGMPv3.h:173
std::vector< IPv4Address > IPv4AddressVector
Definition: IGMPv3.h:42
virtual void startTimer(cMessage *timer, double interval)
Definition: IGMPv3.cc:568
Definition: IGMPv3.h:72
Definition: IGMPv3.h:68
std::vector< T >::iterator find(std::vector< T > &v, const T &a)
Definition: stlutils.h:48
void inet::IGMPv3::processRouterGeneralQueryTimer ( cMessage *  msg)
protectedvirtual

Referenced by handleMessage().

640 {
641  RouterInterfaceData *interfaceData = (RouterInterfaceData *)msg->getContextPointer();
642  InterfaceEntry *ie = interfaceData->ie;
643  ASSERT(ie);
644  EV_INFO << "General Query timer expired on interface='" << ie->getName() << "'.\n";
645  RouterState state = interfaceData->state;
646  if (state == IGMPV3_RS_QUERIER || state == IGMPV3_RS_NON_QUERIER) {
647  EV_INFO << "Sending General Query on interface '" << ie->getName() << "', and scheduling next Query to '"
648  << (simTime() + queryInterval) << "'.\n";
649  interfaceData->state = IGMPV3_RS_QUERIER;
650  sendGeneralQuery(interfaceData, queryResponseInterval);
652  }
653 }
RouterState
Definition: IGMPv3.h:44
double queryResponseInterval
Definition: IGMPv3.h:179
Definition: IGMPv3.h:46
double queryInterval
Definition: IGMPv3.h:178
virtual void startTimer(cMessage *timer, double interval)
Definition: IGMPv3.cc:568
virtual void sendGeneralQuery(RouterInterfaceData *interface, double maxRespTime)
Definition: IGMPv3.cc:575
void inet::IGMPv3::processRouterGroupTimer ( cMessage *  msg)
protectedvirtual

Function for switching EXCLUDE filter mode back to INCLUDE If at least one source timer is still runing, it will switch to Include mode.

Else if no source timer is running, group record is deleted.

Referenced by handleMessage().

1267 {
1268  RouterGroupData *groupData = (RouterGroupData *)msg->getContextPointer();
1269  InterfaceEntry *ie = groupData->parent->ie;
1270 
1271  EV_INFO << "Group Timer for group '" << groupData->groupAddr << "' on interface '" << ie->getName() << "' has expired.\n";
1272  EV_DETAIL << "Router State is " << groupData->getStateInfo() << ".\n";
1273 
1274  if (groupData->filter == IGMPV3_FM_EXCLUDE) {
1275  bool timerRunning = false;
1276  for (auto it = groupData->sources.begin(); it != groupData->sources.end(); ++it) {
1277  if (!it->second->sourceTimer->isScheduled()) {
1278  EV_DETAIL << "Deleting source record of '" << it->first << "'.\n";
1279  groupData->deleteSourceRecord(it->first);
1280  }
1281  else {
1282  timerRunning = true;
1283  }
1284  }
1285  groupData->filter = IGMPV3_FM_INCLUDE;
1286  if (!timerRunning) {
1287  EV_DETAIL << "Deleting multicast listener for group '" << groupData->groupAddr << "' from the interface table.\n";
1288  ie->ipv4Data()->removeMulticastListener(groupData->groupAddr);
1289  groupData->parent->deleteGroupData(groupData->groupAddr);
1290 
1291  EV_DETAIL << "New Router State is <deleted>.\n";
1292  return;
1293  }
1294  }
1295 
1296  EV_DETAIL << "New Router State is " << groupData->getStateInfo() << ".\n";
1297 }
Definition: IGMPv3.h:63
Definition: IGMPv3.h:64
void inet::IGMPv3::processRouterSourceTimer ( cMessage *  msg)
protectedvirtual

Function for checking expired source timers if group is in INCLUDE filter mode.

Referenced by handleMessage().

1303 {
1304  SourceRecord *sourceRecord = (SourceRecord *)msg->getContextPointer();
1305  RouterGroupData *groupData = sourceRecord->parent;
1306  InterfaceEntry *ie = groupData->parent->ie;
1307 
1308  EV_INFO << "Source timer for group '" << groupData->groupAddr << "' and source '" << sourceRecord->sourceAddr
1309  << "' on interface '" << ie->getName() << "' has expired.\n";
1310 
1311  bool last = true;
1312  if (groupData->filter == IGMPV3_FM_INCLUDE) {
1313  groupData->deleteSourceRecord(sourceRecord->sourceAddr);
1314  }
1315  for (auto & elem : groupData->sources) {
1316  if (elem.second->sourceTimer->isScheduled()) {
1317  last = false;
1318  }
1319  }
1320  if (last) {
1321  ie->ipv4Data()->removeMulticastListener(groupData->groupAddr);
1322  groupData->parent->deleteGroupData(groupData->groupAddr);
1323  }
1324 }
Definition: IGMPv3.h:63
void inet::IGMPv3::receiveSignal ( cComponent *  source,
simsignal_t  signalID,
cObject *  obj,
cObject *  details 
)
overrideprotectedvirtual
467 {
468  Enter_Method_Silent();
469 
470  InterfaceEntry *ie;
471  int interfaceId;
472  const IPv4MulticastGroupSourceInfo *info;
473  if (signalID == NF_INTERFACE_CREATED) {
474  ie = const_cast<InterfaceEntry *>(check_and_cast<const InterfaceEntry *>(obj));
475  if (ie->isMulticast())
476  configureInterface(ie);
477  }
478  else if (signalID == NF_INTERFACE_DELETED) {
479  ie = const_cast<InterfaceEntry *>(check_and_cast<const InterfaceEntry *>(obj));
480  if (ie->isMulticast()) {
481  interfaceId = ie->getInterfaceId();
482  deleteHostInterfaceData(interfaceId);
483  deleteRouterInterfaceData(interfaceId);
484  }
485  }
486  else if (signalID == NF_IPv4_MCAST_CHANGE) {
487  info = check_and_cast<const IPv4MulticastGroupSourceInfo *>(obj);
488  multicastSourceListChanged(info->ie, info->groupAddress, info->sourceList);
489  }
490 }
virtual void deleteHostInterfaceData(int interfaceId)
Definition: IGMPv3.cc:360
simsignal_t NF_IPv4_MCAST_CHANGE
Definition: NotifierConsts.cc:66
simsignal_t NF_INTERFACE_CREATED
Definition: NotifierConsts.cc:48
virtual void deleteRouterInterfaceData(int interfaceId)
Definition: IGMPv3.cc:370
virtual void configureInterface(InterfaceEntry *ie)
Definition: IGMPv3.cc:492
simsignal_t NF_INTERFACE_DELETED
Definition: NotifierConsts.cc:49
virtual void multicastSourceListChanged(InterfaceEntry *ie, IPv4Address group, const IPv4MulticastSourceList &sourceList)
This function is sending report message if interface state was changed.
Definition: IGMPv3.cc:773
void inet::IGMPv3::sendGeneralQuery ( RouterInterfaceData interface,
double  maxRespTime 
)
protectedvirtual

Referenced by configureInterface(), and processRouterGeneralQueryTimer().

576 {
577  if (interfaceData->state == IGMPV3_RS_QUERIER) {
578  IGMPv3Query *msg = new IGMPv3Query("IGMPv3 query");
579  msg->setType(IGMP_MEMBERSHIP_QUERY);
580  msg->setMaxRespCode((int)(maxRespTime * 10.0));
581  msg->setByteLength(12);
582  sendQueryToIP(msg, interfaceData->ie, IPv4Address::ALL_HOSTS_MCAST);
583 
584  numQueriesSent++;
586  }
587 }
int numQueriesSent
Definition: IGMPv3.h:198
Definition: IGMPMessage_m.h:58
static const IPv4Address ALL_HOSTS_MCAST
224.0.0.1 All hosts on a subnet
Definition: IPv4Address.h:107
virtual void sendQueryToIP(IGMPv3Query *msg, InterfaceEntry *ie, IPv4Address dest)
Definition: IGMPv3.cc:670
Definition: IGMPv3.h:46
int numGeneralQueriesSent
Definition: IGMPv3.h:200
void inet::IGMPv3::sendGroupAndSourceSpecificQuery ( RouterGroupData group,
const IPv4AddressVector sources 
)
protectedvirtual

Referenced by processReport().

620 {
621  ASSERT(!sources.empty());
622 
623  RouterInterfaceData *interfaceData = groupData->parent;
624 
625  if (interfaceData->state == IGMPV3_RS_QUERIER) {
626  IGMPv3Query *msg = new IGMPv3Query("IGMPv3 query");
627  msg->setType(IGMP_MEMBERSHIP_QUERY);
628  msg->setGroupAddress(groupData->groupAddr);
629  msg->setMaxRespCode((int)(lastMemberQueryInterval * 10.0)); // FIXME compute code
630  msg->setSourceList(sources);
631  msg->setByteLength(12 + (4 * sources.size()));
632  sendQueryToIP(msg, interfaceData->ie, groupData->groupAddr);
633 
634  numQueriesSent++;
636  }
637 }
double lastMemberQueryInterval
Definition: IGMPv3.h:184
int numQueriesSent
Definition: IGMPv3.h:198
Definition: IGMPMessage_m.h:58
virtual void sendQueryToIP(IGMPv3Query *msg, InterfaceEntry *ie, IPv4Address dest)
Definition: IGMPv3.cc:670
Definition: IGMPv3.h:46
int numGroupAndSourceSpecificQueriesSent
Definition: IGMPv3.h:204
void inet::IGMPv3::sendGroupReport ( InterfaceEntry ie,
const std::vector< GroupRecord > &  records 
)
protectedvirtual

Referenced by multicastSourceListChanged(), and processHostGroupQueryTimer().

975 {
976  EV << "IGMPv3: sending Membership Report on iface=" << ie->getName() << "\n";
977  IGMPv3Report *msg = new IGMPv3Report("IGMPv3 report");
978  unsigned int byteLength = 8; // IGMPv3Report header size
979  msg->setType(IGMPV3_MEMBERSHIP_REPORT);
980  msg->setGroupRecordArraySize(records.size());
981  for (int i = 0; i < (int)records.size(); ++i) {
982  IPv4Address group = records[i].groupAddress;
983  ASSERT(group.isMulticast() && !group.isLinkLocalMulticast());
984  msg->setGroupRecord(i, records[i]);
985  byteLength += 8 + records[i].sourceList.size() * 4; // 8 byte header + n * 4 byte (IPv4Address)
986  }
987  msg->setByteLength(byteLength);
988 
990  numReportsSent++;
991 }
Definition: IGMPMessage_m.h:62
virtual void sendReportToIP(IGMPv3Report *msg, InterfaceEntry *ie, IPv4Address dest)
Definition: IGMPv3.cc:656
static const IPv4Address ALL_IGMPV3_ROUTERS_MCAST
224.0.0.22 All IGMPv3 routers
Definition: IPv4Address.h:112
int numReportsSent
Definition: IGMPv3.h:206
void inet::IGMPv3::sendGroupSpecificQuery ( RouterGroupData group)
protectedvirtual

Referenced by processReport().

595 {
596  RouterInterfaceData *interfaceData = groupData->parent;
597  bool suppressFlag = groupData->timer->isScheduled() && groupData->timer->getArrivalTime() > simTime() + lastMemberQueryTime;
598 
599  // Set group timer to LMQT
600  startTimer(groupData->timer, lastMemberQueryTime);
601 
602  if (interfaceData->state == IGMPV3_RS_QUERIER) {
603  IGMPv3Query *msg = new IGMPv3Query("IGMPv3 query");
604  msg->setType(IGMP_MEMBERSHIP_QUERY);
605  msg->setGroupAddress(groupData->groupAddr);
606  msg->setMaxRespCode((int)(lastMemberQueryInterval * 10.0)); // FIXME compute code
607  msg->setSuppressRouterProc(suppressFlag);
608  msg->setByteLength(12);
609  sendQueryToIP(msg, interfaceData->ie, groupData->groupAddr);
610 
611  numQueriesSent++;
613  }
614 
615  // TODO retransmission [Last Member Query Count]-1 times
616 }
double lastMemberQueryInterval
Definition: IGMPv3.h:184
int numQueriesSent
Definition: IGMPv3.h:198
Definition: IGMPMessage_m.h:58
virtual void sendQueryToIP(IGMPv3Query *msg, InterfaceEntry *ie, IPv4Address dest)
Definition: IGMPv3.cc:670
Definition: IGMPv3.h:46
double lastMemberQueryTime
Definition: IGMPv3.h:186
virtual void startTimer(cMessage *timer, double interval)
Definition: IGMPv3.cc:568
int numGroupSpecificQueriesSent
Definition: IGMPv3.h:202
void inet::IGMPv3::sendQueryToIP ( IGMPv3Query msg,
InterfaceEntry ie,
IPv4Address  dest 
)
protectedvirtual

Referenced by sendGeneralQuery(), sendGroupAndSourceSpecificQuery(), and sendGroupSpecificQuery().

671 {
672  ASSERT(ie->isMulticast());
673 
674  IPv4ControlInfo *controlInfo = new IPv4ControlInfo();
675  controlInfo->setProtocol(IP_PROT_IGMP);
676  controlInfo->setInterfaceId(ie->getInterfaceId());
677  controlInfo->setTimeToLive(1);
678  controlInfo->setDestAddr(dest);
679  msg->setControlInfo(controlInfo);
680 
681  send(msg, "ipOut");
682 }
Definition: IPProtocolId_m.h:78
void inet::IGMPv3::sendReportToIP ( IGMPv3Report msg,
InterfaceEntry ie,
IPv4Address  dest 
)
protectedvirtual

Referenced by processHostGeneralQueryTimer(), and sendGroupReport().

657 {
658  ASSERT(ie->isMulticast());
659 
660  IPv4ControlInfo *controlInfo = new IPv4ControlInfo();
661  controlInfo->setProtocol(IP_PROT_IGMP);
662  controlInfo->setInterfaceId(ie->getInterfaceId());
663  controlInfo->setTimeToLive(1);
664  controlInfo->setDestAddr(dest);
665  msg->setControlInfo(controlInfo);
666 
667  send(msg, "ipOut");
668 }
Definition: IPProtocolId_m.h:78
void inet::IGMPv3::startTimer ( cMessage *  timer,
double  interval 
)
protectedvirtual

Referenced by configureInterface(), processQuery(), processReport(), processRouterGeneralQueryTimer(), and sendGroupSpecificQuery().

569 {
570  ASSERT(timer);
571  cancelEvent(timer);
572  scheduleAt(simTime() + interval, timer);
573 }

Member Data Documentation

bool inet::IGMPv3::enabled
protected
double inet::IGMPv3::groupMembershipInterval
protected

Referenced by initialize(), and processReport().

InterfaceToHostDataMap inet::IGMPv3::hostData
protected
IInterfaceTable* inet::IGMPv3::ift
protected
double inet::IGMPv3::lastMemberQueryCount
protected

Referenced by initialize(), and processQuery().

double inet::IGMPv3::lastMemberQueryInterval
protected
double inet::IGMPv3::lastMemberQueryTime
protected
int inet::IGMPv3::numGeneralQueriesRecv
protected

Referenced by initialize().

int inet::IGMPv3::numGeneralQueriesSent
protected

Referenced by initialize(), and sendGeneralQuery().

int inet::IGMPv3::numGroupAndSourceSpecificQueriesRecv
protected

Referenced by initialize().

int inet::IGMPv3::numGroupAndSourceSpecificQueriesSent
protected
int inet::IGMPv3::numGroupSpecificQueriesRecv
protected

Referenced by initialize().

int inet::IGMPv3::numGroupSpecificQueriesSent
protected
int inet::IGMPv3::numQueriesRecv
protected

Referenced by initialize(), and processQuery().

int inet::IGMPv3::numQueriesSent
protected
int inet::IGMPv3::numReportsRecv
protected

Referenced by initialize(), and processReport().

int inet::IGMPv3::numReportsSent
protected
double inet::IGMPv3::otherQuerierPresentInterval
protected

Referenced by initialize(), and processQuery().

double inet::IGMPv3::queryInterval
protected
double inet::IGMPv3::queryResponseInterval
protected
int inet::IGMPv3::robustness
protected

Referenced by initialize().

IRoutingTable* inet::IGMPv3::rt
protected
double inet::IGMPv3::startupQueryCount
protected

Referenced by initialize().

double inet::IGMPv3::startupQueryInterval
protected

Referenced by configureInterface(), and initialize().

double inet::IGMPv3::unsolicitedReportInterval
protected

Referenced by initialize().


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