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
 

Public Member Functions

void insertCrc (const Ptr< IgmpMessage > &igmpMsg, Packet *payload)
 
bool verifyCrc (const Packet *packet)
 

Static Public Member Functions

static Ipv4AddressVector set_complement (const Ipv4AddressVector &first, const Ipv4AddressVector &second)
 
static Ipv4AddressVector set_intersection (const Ipv4AddressVector &first, const Ipv4AddressVector &second)
 
static Ipv4AddressVector set_union (const Ipv4AddressVector &first, const Ipv4AddressVector &second)
 
static const std::string getRouterStateString (RouterState rs)
 
static const std::string getRouterGroupStateString (RouterGroupState rgs)
 
static const std::string getHostGroupStateString (HostGroupState hgs)
 
static const std::string getFilterModeString (FilterMode fm)
 
static void insertCrc (CrcMode crcMode, const Ptr< IgmpMessage > &igmpMsg, Packet *payload)
 
static uint16_t decodeTime (uint8_t code)
 Function for computing the time value in seconds from an encoded value. More...
 
static uint8_t codeTime (uint16_t timevalue)
 

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::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 ()
 
void addWatches ()
 
virtual HostInterfaceDatacreateHostInterfaceData (NetworkInterface *ie)
 
virtual RouterInterfaceDatacreateRouterInterfaceData (NetworkInterface *ie)
 
virtual HostInterfaceDatagetHostInterfaceData (NetworkInterface *ie)
 
virtual RouterInterfaceDatagetRouterInterfaceData (NetworkInterface *ie)
 
virtual void deleteHostInterfaceData (int interfaceId)
 
virtual void deleteRouterInterfaceData (int interfaceId)
 
virtual void configureInterface (NetworkInterface *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 (NetworkInterface *ie, const std::vector< GroupRecord > &records)
 
virtual void sendQueryToIP (Packet *msg, NetworkInterface *ie, Ipv4Address dest)
 
virtual void sendReportToIP (Packet *msg, NetworkInterface *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 (Packet *msg)
 
virtual void processQuery (Packet *msg)
 
virtual void processReport (Packet *msg)
 
virtual void multicastSourceListChanged (NetworkInterface *ie, Ipv4Address group, const Ipv4MulticastSourceList &sourceList)
 This function is sending report message if interface state was changed. More...
 

Protected Attributes

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

Member Typedef Documentation

◆ GroupToHostDataMap

◆ GroupToRouterDataMap

◆ InterfaceToHostDataMap

typedef std::map<int, HostInterfaceData *> inet::Igmpv3::InterfaceToHostDataMap
protected

◆ InterfaceToRouterDataMap

typedef std::map<int, RouterInterfaceData *> inet::Igmpv3::InterfaceToRouterDataMap
protected

◆ SourceToSourceRecordMap

Member Enumeration Documentation

◆ FilterMode

enum inet::Igmpv3::FilterMode
protected
Enumerator
IGMPV3_FM_INCLUDE 
IGMPV3_FM_EXCLUDE 
53  {
56  };

◆ HostGroupState

Enumerator
IGMPV3_HGS_NON_MEMBER 
IGMPV3_HGS_DELAYING_MEMBER 
IGMPV3_HGS_IDLE_MEMBER 

◆ IgmpTimerKind

Enumerator
IGMPV3_R_GENERAL_QUERY_TIMER 
IGMPV3_R_GROUP_TIMER 
IGMPV3_R_SOURCE_TIMER 
IGMPV3_H_GENERAL_QUERY_TIMER 
IGMPV3_H_GROUP_TIMER 

◆ ReportType

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 
58  {
59  IGMPV3_RT_IS_IN = 1,
60  IGMPV3_RT_IS_EX = 2,
61  IGMPV3_RT_TO_IN = 3,
62  IGMPV3_RT_TO_EX = 4,
63  IGMPV3_RT_ALLOW = 5,
64  IGMPV3_RT_BLOCK = 6,
65  };

◆ RouterGroupState

Enumerator
IGMPV3_RGS_NO_MEMBERS_PRESENT 
IGMPV3_RGS_MEMBERS_PRESENT 
IGMPV3_RGS_CHECKING_MEMBERSHIP 

◆ RouterState

enum inet::Igmpv3::RouterState
protected
Enumerator
IGMPV3_RS_INITIAL 
IGMPV3_RS_QUERIER 
IGMPV3_RS_NON_QUERIER 
35  {
39  };

Constructor & Destructor Documentation

◆ ~Igmpv3()

inet::Igmpv3::~Igmpv3 ( )
protectedvirtual
55 {
56  while (!hostData.empty())
57  deleteHostInterfaceData(hostData.begin()->first);
58 
59  while (!routerData.empty())
60  deleteRouterInterfaceData(routerData.begin()->first);
61 }

Member Function Documentation

◆ addWatches()

void inet::Igmpv3::addWatches ( )
protected
121 {
122  WATCH(numGroups);
123  WATCH(numHostGroups);
124  WATCH(numRouterGroups);
125 
126  WATCH(numQueriesSent);
127  WATCH(numQueriesRecv);
128  WATCH(numGeneralQueriesSent);
129  WATCH(numGeneralQueriesRecv);
134  WATCH(numReportsSent);
135  WATCH(numReportsRecv);
136 
137  WATCH_PTRMAP(hostData);
138  WATCH_PTRMAP(routerData);
139 }

◆ codeTime()

uint8_t inet::Igmpv3::codeTime ( uint16_t  timevalue)
static
1374 {
1375  uint8_t code;
1376  if (time < 128)
1377  code = (uint8_t)time;
1378  else if (time >= (0x1f << 10))
1379  code = 0xff;
1380  else {
1381  unsigned exp = 0;
1382  time >>= 3;
1383  while (time > 0x1f) {
1384  time >>= 1;
1385  exp++;
1386  }
1387  ASSERT(exp <= 7);
1388  ASSERT(time <= 15);
1389  code = 0x80 | ((exp << 4) & 0x70) | (time & 0x0f);
1390  }
1391 
1392  return code;
1393 }

◆ configureInterface()

void inet::Igmpv3::configureInterface ( NetworkInterface ie)
protectedvirtual
252 {
253  if (enabled && rt->isMulticastForwardingEnabled()) {
254  // start querier on this interface
255  EV_INFO << "Sending General Query on interface '" << ie->getInterfaceName() << "', and scheduling next Query to '"
256  << (simTime() + startupQueryInterval) << "'.\n";
257  RouterInterfaceData *routerData = getRouterInterfaceData(ie);
258  routerData->state = IGMPV3_RS_QUERIER;
259 
261  startTimer(routerData->generalQueryTimer, startupQueryInterval);
262  }
263 }

◆ createHostInterfaceData()

Igmpv3::HostInterfaceData * inet::Igmpv3::createHostInterfaceData ( NetworkInterface ie)
protectedvirtual
1090 {
1091  return new HostInterfaceData(this, ie);
1092 }

Referenced by getHostInterfaceData().

◆ createRouterInterfaceData()

Igmpv3::RouterInterfaceData * inet::Igmpv3::createRouterInterfaceData ( NetworkInterface ie)
protectedvirtual
1073 {
1074  return new RouterInterfaceData(this, ie);
1075 }

Referenced by getRouterInterfaceData().

◆ decodeTime()

uint16_t inet::Igmpv3::decodeTime ( uint8_t  code)
static

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.

1360 {
1361  uint16_t time;
1362  if (code < 128)
1363  time = code;
1364  else {
1365  unsigned mantis = code & 0x0f;
1366  unsigned exp = (code >> 4) & 0x07;
1367  time = (mantis | 0x10) << (exp + 3);
1368  }
1369 
1370  return time;
1371 }

Referenced by inet::IgmpProtocolPrinter::print().

◆ deleteHostInterfaceData()

void inet::Igmpv3::deleteHostInterfaceData ( int  interfaceId)
protectedvirtual
266 {
267  auto interfaceIt = hostData.find(interfaceId);
268  if (interfaceIt != hostData.end()) {
269  HostInterfaceData *interface = interfaceIt->second;
270  hostData.erase(interfaceIt);
271  delete interface;
272  }
273 }

◆ deleteRouterInterfaceData()

void inet::Igmpv3::deleteRouterInterfaceData ( int  interfaceId)
protectedvirtual
276 {
277  auto interfaceIt = routerData.find(interfaceId);
278  if (interfaceIt != routerData.end()) {
279  RouterInterfaceData *interface = interfaceIt->second;
280  routerData.erase(interfaceIt);
281  delete interface;
282  }
283 }

◆ getFilterModeString()

const std::string inet::Igmpv3::getFilterModeString ( Igmpv3::FilterMode  fm)
static
1432 {
1433  if (fm == IGMPV3_FM_INCLUDE)
1434  return "INCLUDE";
1435  else if (fm == IGMPV3_FM_EXCLUDE)
1436  return "EXCLUDE";
1437 
1438  return "UNKNOWN";
1439 }

◆ getHostGroupStateString()

const std::string inet::Igmpv3::getHostGroupStateString ( Igmpv3::HostGroupState  hgs)
static
1420 {
1421  if (hgs == IGMPV3_HGS_NON_MEMBER)
1422  return "NON_MEMBER";
1423  else if (hgs == IGMPV3_HGS_DELAYING_MEMBER)
1424  return "DELAYING_MEMBER";
1425  else if (hgs == IGMPV3_HGS_IDLE_MEMBER)
1426  return "IDLE_MEMBER";
1427 
1428  return "UNKNOWN";
1429 }

◆ getHostInterfaceData()

Igmpv3::HostInterfaceData * inet::Igmpv3::getHostInterfaceData ( NetworkInterface ie)
protectedvirtual
1078 {
1079  int interfaceId = ie->getInterfaceId();
1080  auto it = hostData.find(interfaceId);
1081  if (it != hostData.end())
1082  return it->second;
1083 
1084  HostInterfaceData *data = createHostInterfaceData(ie);
1085  hostData[interfaceId] = data;
1086  return data;
1087 }

◆ getRouterGroupStateString()

const std::string inet::Igmpv3::getRouterGroupStateString ( Igmpv3::RouterGroupState  rgs)
static
1408 {
1409  if (rgs == IGMPV3_RGS_NO_MEMBERS_PRESENT)
1410  return "NO_MEMBERS_PRESENT";
1411  else if (rgs == IGMPV3_RGS_MEMBERS_PRESENT)
1412  return "MEMBERS_PRESENT";
1413  else if (rgs == IGMPV3_RGS_CHECKING_MEMBERSHIP)
1414  return "CHECKING_MEMBERSHIP";
1415 
1416  return "UNKNOWN";
1417 }

◆ getRouterInterfaceData()

Igmpv3::RouterInterfaceData * inet::Igmpv3::getRouterInterfaceData ( NetworkInterface ie)
protectedvirtual
1061 {
1062  int interfaceId = ie->getInterfaceId();
1063  auto it = routerData.find(interfaceId);
1064  if (it != routerData.end())
1065  return it->second;
1066 
1067  RouterInterfaceData *data = createRouterInterfaceData(ie);
1068  routerData[interfaceId] = data;
1069  return data;
1070 }

◆ getRouterStateString()

const std::string inet::Igmpv3::getRouterStateString ( Igmpv3::RouterState  rs)
static
1396 {
1397  if (rs == IGMPV3_RS_INITIAL)
1398  return "INITIAL";
1399  else if (rs == IGMPV3_RS_QUERIER)
1400  return "QUERIER";
1401  else if (rs == IGMPV3_RS_NON_QUERIER)
1402  return "NON_QUERIER";
1403 
1404  return "UNKNOWN";
1405 }

◆ handleMessage()

void inet::Igmpv3::handleMessage ( cMessage *  msg)
overrideprotectedvirtual
286 {
287  if (!enabled) {
288  if (!msg->isSelfMessage()) {
289  EV << "Igmpv3 disabled, dropping packet.\n";
290  delete msg;
291  }
292  return;
293  }
294 
295  if (msg->isSelfMessage()) {
296  switch (msg->getKind()) {
299  break;
300 
303  break;
304 
307  break;
308 
311  break;
312 
315  break;
316 
317  default:
318  ASSERT(false);
319  break;
320  }
321  }
322  else
323  processIgmpMessage(check_and_cast<Packet *>(msg));
324 }

◆ initialize()

void inet::Igmpv3::initialize ( int  stage)
overrideprotectedvirtual
64 {
65  if (stage == INITSTAGE_LOCAL) {
66  ift.reference(this, "interfaceTableModule", true);
67  rt.reference(this, "routingTableModule", true);
68 
69  enabled = par("enabled");
70  robustness = par("robustnessVariable");
71  queryInterval = par("queryInterval");
72  queryResponseInterval = par("queryResponseInterval");
73  groupMembershipInterval = par("groupMembershipInterval");
74  otherQuerierPresentInterval = par("otherQuerierPresentInterval");
75  startupQueryInterval = par("startupQueryInterval");
76  startupQueryCount = par("startupQueryCount");
77  lastMemberQueryInterval = par("lastMemberQueryInterval");
78  lastMemberQueryCount = par("lastMemberQueryCount");
79  lastMemberQueryTime = lastMemberQueryInterval * lastMemberQueryCount; // todo checknut ci je to takto..
80  unsolicitedReportInterval = par("unsolicitedReportInterval");
81  const char *crcModeString = par("crcMode");
82  crcMode = parseCrcMode(crcModeString, false);
83 
84  addWatches();
85  }
86  // TODO INITSTAGE
87  else if (stage == INITSTAGE_NETWORK_LAYER_PROTOCOLS) {
88  cModule *host = getContainingNode(this);
89  registerProtocol(Protocol::igmp, gate("ipOut"), gate("ipIn"));
90  for (int i = 0; i < ift->getNumInterfaces(); ++i) {
91  NetworkInterface *ie = ift->getInterface(i);
92  if (ie->isMulticast()) {
94  if (auto ipv4interfaceData = ie->findProtocolDataForUpdate<Ipv4InterfaceData>()) {
95  int n = ipv4interfaceData->getNumOfJoinedMulticastGroups();
96  for (int j = 0; j < n; j++) {
97  auto groupAddress = ipv4interfaceData->getJoinedMulticastGroup(j);
98  const auto& sourceList = ipv4interfaceData->getJoinedMulticastSources(j);
99  multicastSourceListChanged(ie, groupAddress, sourceList);
100  }
101  }
102  }
103  }
104 
105  host->subscribe(interfaceCreatedSignal, this);
106  host->subscribe(interfaceDeletedSignal, this);
107  host->subscribe(ipv4MulticastChangeSignal, this);
108 
109  // in multicast routers: join to ALL_IGMPv3_ROUTERS_MCAST address on all interfaces
110  if (enabled && rt->isMulticastForwardingEnabled()) {
111  for (int i = 0; i < ift->getNumInterfaces(); ++i) {
112  NetworkInterface *ie = ift->getInterface(i);
113  if (ie->isMulticast())
114  ie->getProtocolDataForUpdate<Ipv4InterfaceData>()->joinMulticastGroup(Ipv4Address::ALL_IGMPV3_ROUTERS_MCAST);
115  }
116  }
117  }
118 }

◆ insertCrc() [1/2]

void inet::Igmpv3::insertCrc ( const Ptr< IgmpMessage > &  igmpMsg,
Packet payload 
)
inline
287 { insertCrc(crcMode, igmpMsg, payload); }

Referenced by insertCrc().

◆ insertCrc() [2/2]

void inet::Igmpv3::insertCrc ( CrcMode  crcMode,
const Ptr< IgmpMessage > &  igmpMsg,
Packet payload 
)
static
1442 {
1443  igmpMsg->setCrcMode(crcMode);
1444  switch (crcMode) {
1445  case CRC_DECLARED_CORRECT:
1446  // if the CRC mode is declared to be correct, then set the CRC to an easily recognizable value
1447  igmpMsg->setCrc(0xC00D);
1448  break;
1450  // if the CRC mode is declared to be incorrect, then set the CRC to an easily recognizable value
1451  igmpMsg->setCrc(0xBAAD);
1452  break;
1453  case CRC_COMPUTED: {
1454  // if the CRC mode is computed, then compute the CRC and set it
1455  igmpMsg->setCrc(0x0000); // make sure that the CRC is 0 in the header before computing the CRC
1456  MemoryOutputStream igmpStream;
1457  Chunk::serialize(igmpStream, igmpMsg);
1458  if (packet->getDataLength() > b(0))
1459  Chunk::serialize(igmpStream, packet->peekDataAsBytes());
1460  uint16_t crc = TcpIpChecksum::checksum(igmpStream.getData());
1461  igmpMsg->setCrc(crc);
1462  break;
1463  }
1464  default:
1465  throw cRuntimeError("Unknown CRC mode");
1466  }
1467 }

◆ multicastSourceListChanged()

void inet::Igmpv3::multicastSourceListChanged ( NetworkInterface ie,
Ipv4Address  group,
const Ipv4MulticastSourceList sourceList 
)
protectedvirtual

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

See RFC 3376 5.1.

173 {
174  ASSERT(ie);
175  ASSERT(isSorted(sourceList.sources));
176 
177  if (!enabled || group.isLinkLocalMulticast())
178  return;
179 
180  HostInterfaceData *interfaceData = getHostInterfaceData(ie);
181  HostGroupData *groupData = interfaceData->getOrCreateGroupData(group);
182 
183  FilterMode filter = sourceList.filterMode == MCAST_INCLUDE_SOURCES ? IGMPV3_FM_INCLUDE : IGMPV3_FM_EXCLUDE;
184 
185  EV_DETAIL_C("test") << "State of group '" << group << "' on interface '" << ie->getInterfaceName() << "' has changed:\n";
186  EV_DETAIL_C("test") << " Old state: " << groupData->getStateInfo() << ".\n";
187  EV_DETAIL_C("test") << " New state: " << (filter == IGMPV3_FM_INCLUDE ? "INCLUDE" : "EXCLUDE") << sourceList.sources << ".\n";
188 
189  // Check if IF state is different
190  if (!(groupData->filter == filter) || !(groupData->sourceAddressList == sourceList.sources)) {
191  // INCLUDE(A) -> INCLUDE(B): Send ALLOW(B-A), BLOCK(A-B)
192  if (groupData->filter == IGMPV3_FM_INCLUDE && filter == IGMPV3_FM_INCLUDE && groupData->sourceAddressList != sourceList.sources) {
193  EV_DETAIL << "Sending ALLOW/BLOCK report.\n";
194  vector<GroupRecord> records(2);
195  records[0].setGroupAddress(group);
196  records[0].setRecordType(IGMPV3_RT_ALLOW);
197  records[0].setSourceList(set_complement(sourceList.sources, groupData->sourceAddressList));
198  records[1].setGroupAddress(group);
199  records[1].setRecordType(IGMPV3_RT_BLOCK);
200  records[1].setSourceList(set_complement(groupData->sourceAddressList, sourceList.sources));
201  records.erase(remove_if(records.begin(), records.end(), isEmptyRecord), records.end());
202  if (!records.empty())
203  sendGroupReport(ie, records);
204  }
205  // EXCLUDE(A) -> EXCLUDE(B): Send ALLOW(A-B), BLOCK(B-A)
206  else if (groupData->filter == IGMPV3_FM_EXCLUDE && filter == IGMPV3_FM_EXCLUDE && groupData->sourceAddressList != sourceList.sources) {
207  EV_DETAIL << "Sending ALLOW/BLOCK report.\n";
208  vector<GroupRecord> records(2);
209  records[0].setGroupAddress(group);
210  records[0].setRecordType(IGMPV3_RT_ALLOW);
211  records[0].setSourceList(set_complement(groupData->sourceAddressList, sourceList.sources));
212  records[1].setGroupAddress(group);
213  records[1].setRecordType(IGMPV3_RT_BLOCK);
214  records[1].setSourceList(set_complement(sourceList.sources, groupData->sourceAddressList));
215  records.erase(remove_if(records.begin(), records.end(), isEmptyRecord), records.end());
216  if (!records.empty())
217  sendGroupReport(ie, records);
218  }
219  // INCLUDE(A) -> EXCLUDE(B): Send TO_EX(B)
220  else if (groupData->filter == IGMPV3_FM_INCLUDE && filter == IGMPV3_FM_EXCLUDE) {
221  EV_DETAIL << "Sending TO_EX report.\n";
222  vector<GroupRecord> records(1);
223  records[0].setGroupAddress(group);
224  records[0].setRecordType(IGMPV3_RT_TO_EX);
225  records[0].setSourceList(sourceList.sources);
226  sendGroupReport(ie, records);
227  }
228  // EXCLUDE(A) -> INCLUDE(B): Send TO_IN(B)
229  else if (groupData->filter == IGMPV3_FM_EXCLUDE && filter == IGMPV3_FM_INCLUDE) {
230  EV_DETAIL << "Sending TO_IN report.\n";
231  vector<GroupRecord> records(1);
232  records[0].setGroupAddress(group);
233  records[0].setRecordType(IGMPV3_RT_TO_IN);
234  records[0].setSourceList(sourceList.sources);
235  sendGroupReport(ie, records);
236  }
237 
238  // Go to new state
239  groupData->filter = filter;
240  groupData->sourceAddressList = sourceList.sources;
241  sort(groupData->sourceAddressList.begin(), groupData->sourceAddressList.end());
242  }
243 
244  // FIXME missing: the report is retransmitted [Robustness Variable] - 1 more times,
245  // at intervals chosen at random from the range (0, [Unsolicited Report Interval])
246 
247  // FIXME if an interface change occured when there is a pending report, then
248  // the groups of the old report and the new report are to be merged.
249 }

◆ numInitStages()

virtual int inet::Igmpv3::numInitStages ( ) const
inlineoverrideprotectedvirtual
246 { return NUM_INIT_STAGES; }

◆ processHostGeneralQueryTimer()

void inet::Igmpv3::processHostGeneralQueryTimer ( cMessage *  msg)
protectedvirtual
411 {
412  HostInterfaceData *interfaceData = (HostInterfaceData *)msg->getContextPointer();
413  NetworkInterface *ie = interfaceData->ie;
414  ASSERT(ie);
415 
416  EV_INFO << "Response timer to a General Query on interface '" << ie->getInterfaceName() << "' has expired.\n";
417 
418 // HostInterfaceData *interfaceData = getHostInterfaceData(ie);
419  Packet *outPacket = new Packet("Igmpv3 report");
420  const auto& report = makeShared<Igmpv3Report>();
421  unsigned int byteLength = 8; // Igmpv3Report header size
422  report->setType(IGMPV3_MEMBERSHIP_REPORT);
423  int counter = 0;
424  report->setGroupRecordArraySize(interfaceData->groups.size());
425 
426  // FIXME Do not create reports larger than MTU of the interface
427  //
428 
429  /*
430  * creating GroupRecord for each group on interface
431  */
432  for (auto& elem : interfaceData->groups) {
433  GroupRecord gr;
434  if (elem.second->filter == IGMPV3_FM_INCLUDE) {
435  gr.setRecordType(IGMPV3_RT_IS_IN);
436  }
437  else if (elem.second->filter == IGMPV3_FM_EXCLUDE) {
438  gr.setRecordType(IGMPV3_RT_IS_EX);
439  }
440  gr.setGroupAddress(elem.second->groupAddr);
441  gr.setSourceList(elem.second->sourceAddressList);
442  report->setGroupRecord(counter++, gr);
443  byteLength += 8 + gr.getSourceList().size() * 4; // 8 byte header + n * 4 byte (Ipv4Address)
444  }
445  report->setChunkLength(B(byteLength));
446 
447  if (counter != 0) { // if no record created, dont need to send report
448  EV_INFO << "Sending response to a General Query on interface '" << ie->getInterfaceName() << "'.\n";
449  insertCrc(report, outPacket);
450  outPacket->insertAtFront(report);
452  numReportsSent++;
453  }
454  else {
455  EV_INFO << "There are no multicast listeners, no response is sent to a General Query on interface '" << ie->getInterfaceName() << "'.\n";
456  delete outPacket;
457  }
458 }

◆ processHostGroupQueryTimer()

void inet::Igmpv3::processHostGroupQueryTimer ( cMessage *  msg)
protectedvirtual
462 {
463  HostGroupData *group = (HostGroupData *)msg->getContextPointer();
464  NetworkInterface *ie = group->parent->ie;
465 
466  vector<GroupRecord> records(1);
467 
468  // checking if query is group or group-and-source specific
469  if (group->queriedSources.empty()) {
470  // Send report for a Group-Specific Query
471  EV_INFO << "Response timer for a Group-Specific Query for group '" << group->groupAddr << "' on interface '" << ie->getInterfaceName() << "'\n";
472 
473  records[0].setGroupAddress(group->groupAddr);
474  records[0].setRecordType(group->filter == IGMPV3_FM_INCLUDE ? IGMPV3_RT_IS_IN : IGMPV3_RT_IS_EX);
475  records[0].setSourceList(group->sourceAddressList);
476  sendGroupReport(ie, records);
477  }
478  else {
479  // Send report for a Group-and-Source-Specific Query
480  EV_INFO << "Response timer for a Group-and-Source-Specific Query for group '" << group->groupAddr << "' on interface '" << ie->getInterfaceName() << "'\n";
481 
482  records[0].setGroupAddress(group->groupAddr);
483  records[0].setRecordType(IGMPV3_RT_IS_IN);
484  records[0].setSourceList(group->filter == IGMPV3_FM_INCLUDE ? set_intersection(group->sourceAddressList, group->queriedSources) :
485  set_complement(group->queriedSources, group->sourceAddressList));
486  sendGroupReport(ie, records);
487  }
488 
489  group->queriedSources.clear();
490 }

◆ processIgmpMessage()

void inet::Igmpv3::processIgmpMessage ( Packet msg)
protectedvirtual
501 {
502  if (!verifyCrc(packet)) {
503  EV_WARN << "incoming IGMP packet has wrong CRC, dropped\n";
504  // drop packet
505  PacketDropDetails details;
506  details.setReason(INCORRECTLY_RECEIVED);
507  emit(packetDroppedSignal, packet, &details);
508  delete packet;
509  return;
510  }
511 
512  const auto& msg = packet->peekAtFront<IgmpMessage>();
513  switch (msg->getType()) {
515  processQuery(packet);
516  break;
517 
519  processReport(packet);
520  break;
521 
522  default:
523 // delete msg;
524  throw cRuntimeError("Igmpv3: Unhandled message type (%dq)", msg->getType());
525  }
526 }

◆ processQuery()

void inet::Igmpv3::processQuery ( Packet msg)
protectedvirtual
530 {
531  NetworkInterface *ie = ift->getInterfaceById(packet->getTag<InterfaceInd>()->getInterfaceId());
532  const auto& msg = packet->peekAtFront<Igmpv3Query>(); // TODO should processing Igmpv1Query and Igmpv2Query, too
533  assert(msg != nullptr);
534 
535  Ipv4Address groupAddr = msg->getGroupAddress();
536  Ipv4AddressVector queriedSources = msg->getSourceList();
537  double maxRespTime = 0.1 * decodeTime(msg->getMaxRespTimeCode());
538 
539  ASSERT(ie->isMulticast());
540 
541  EV_INFO << "Received Igmpv3 query on interface '" << ie->getInterfaceName() << "' for group '" << groupAddr << "'.\n";
542 
543  HostInterfaceData *interfaceData = getHostInterfaceData(ie);
544 
545  numQueriesRecv++;
546 
547  double delay = uniform(0.0, maxRespTime);
548 
549  // Rules from RFC page 22:
550  if (interfaceData->generalQueryTimer->isScheduled() && interfaceData->generalQueryTimer->getArrivalTime() < simTime() + delay) {
551  // 1. If there is a pending response to a previous General Query
552  // scheduled sooner than the selected delay, no additional response
553  // needs to be scheduled.
554  EV_DETAIL << "There is a pending response to a previous General Query, no further response is scheduled.\n";
555  }
556  else if (groupAddr.isUnspecified() && queriedSources.empty()) {
557  // 2. If the received Query is a General Query, the interface timer is
558  // used to schedule a response to the General Query after the
559  // selected delay. Any previously pending response to a General
560  // Query is canceled.
561  EV_DETAIL << "Received a General Query, scheduling report with delay=" << delay << ".\n";
562  startTimer(interfaceData->generalQueryTimer, delay);
563  }
564  else if (!groupAddr.isUnspecified()) {
565  HostGroupData *groupData = interfaceData->getOrCreateGroupData(groupAddr);
566 
567  if (!groupData->timer->isScheduled()) {
568  // 3. If the received Query is a Group-Specific Query or a Group-and-
569  // Source-Specific Query and there is no pending response to a
570  // previous Query for this group, then the group timer is used to
571  // schedule a report. If the received Query is a Group-and-Source-
572  // Specific Query, the list of queried sources is recorded to be used
573  // when generating a response.
574  EV_DETAIL << "Received Group" << (queriedSources.empty() ? "" : "-and-Source") << "-Specific Query, "
575  << "scheduling report with delay=" << delay << ".\n";
576 
577  sort(queriedSources.begin(), queriedSources.end());
578  groupData->queriedSources = queriedSources;
579  startTimer(groupData->timer, delay);
580  }
581  else if (queriedSources.empty()) {
582  //4. If there already is a pending response to a previous Query
583  // scheduled for this group, and either the new Query is a Group-
584  // Specific Query or the recorded source-list associated with the
585  // group is empty, then the group source-list is cleared and a single
586  // response is scheduled using the group timer. The new response is
587  // scheduled to be sent at the earliest of the remaining time for the
588  // pending report and the selected delay.
589  EV_DETAIL << "Received Group-Specific Query, scheduling report with delay="
590  << min(delay, SIMTIME_DBL(groupData->timer->getArrivalTime() - simTime())) << ".\n";
591 
592  sort(queriedSources.begin(), queriedSources.end());
593  groupData->queriedSources = queriedSources;
594  if (groupData->timer->getArrivalTime() > simTime() + delay)
595  startTimer(groupData->timer, delay);
596  }
597  else {
598  // 5. If the received Query is a Group-and-Source-Specific Query and
599  // there is a pending response for this group with a non-empty
600  // source-list, then the group source list is augmented to contain
601  // the list of sources in the new Query and a single response is
602  // scheduled using the group timer. The new response is scheduled to
603  // be sent at the earliest of the remaining time for the pending
604  // report and the selected delay.
605  EV_DETAIL << "Received Group-and-Source-Specific Query, combining sources with the sources of pending report, "
606  << "and scheduling a new report with delay="
607  << min(delay, SIMTIME_DBL(groupData->timer->getArrivalTime() - simTime())) << ".\n";
608 
609  if (groupData->timer->getArrivalTime() > simTime() + delay) {
610  sort(queriedSources.begin(), queriedSources.end());
611  groupData->queriedSources = set_union(groupData->queriedSources, queriedSources);
612  startTimer(groupData->timer, delay);
613  }
614  }
615  }
616 
617  // Router part | Querier Election
618  if (rt->isMulticastForwardingEnabled()) {
619  // Querier Election
620  RouterInterfaceData *routerInterfaceData = getRouterInterfaceData(ie);
621  if (packet->getTag<L3AddressInd>()->getSrcAddress().toIpv4() < ie->getProtocolData<Ipv4InterfaceData>()->getIPAddress()) {
622  startTimer(routerInterfaceData->generalQueryTimer, otherQuerierPresentInterval);
623  routerInterfaceData->state = IGMPV3_RS_NON_QUERIER;
624  }
625 
626  if (!groupAddr.isUnspecified() && routerInterfaceData->state == IGMPV3_RS_NON_QUERIER) { // group specific query
627  RouterGroupData *groupData = routerInterfaceData->getOrCreateGroupData(groupAddr);
628  if (groupData->state == IGMPV3_RGS_MEMBERS_PRESENT) {
629  double maxResponseTime = maxRespTime;
630  startTimer(groupData->timer, maxResponseTime * lastMemberQueryCount);
631  groupData->state = IGMPV3_RGS_CHECKING_MEMBERSHIP;
632  }
633  }
634  }
635  delete packet;
636 }

◆ processReport()

void inet::Igmpv3::processReport ( Packet msg)
protectedvirtual
639 {
640  const auto& msg = packet->peekAtFront<Igmpv3Report>(); // FIXME also accept Igmpv1Report and Igmpv2Report
641  assert(msg != nullptr);
642  NetworkInterface *ie = ift->getInterfaceById(packet->getTag<InterfaceInd>()->getInterfaceId());
643 
644  ASSERT(ie->isMulticast());
645 
646  EV_INFO << "Received Igmpv3 Membership Report on interface '" << ie->getInterfaceName() << "'.\n";
647 
648  numReportsRecv++;
649 
650  if (rt->isMulticastForwardingEnabled()) {
651  RouterInterfaceData *interfaceData = getRouterInterfaceData(ie);
652 
653  for (unsigned int i = 0; i < msg->getGroupRecordArraySize(); i++) {
654  GroupRecord gr = msg->getGroupRecord(i);
655  EV_DETAIL << "Found a record for group '" << gr.getGroupAddress() << "'.\n";
656 
657  // ensure that the received sources are sorted
658  sort(gr.getSourceListForUpdate().begin(), gr.getSourceListForUpdate().end());
659  Ipv4AddressVector& receivedSources = gr.getSourceListForUpdate(); // sorted
660 
661  RouterGroupData *groupData = interfaceData->getOrCreateGroupData(gr.getGroupAddress());
662 
663  Ipv4MulticastSourceList oldSourceList;
664  groupData->collectForwardedSources(oldSourceList);
665 
666  EV_DETAIL << "Router State is " << groupData->getStateInfo() << ".\n";
667 
668  // RFC 3376 6.4.1: Reception of Current State Record
669  if (gr.getRecordType() == IGMPV3_RT_IS_IN) {
670  EV_DETAIL << "Received IS_IN" << receivedSources << " report.\n";
671  // INCLUDE(A) -> IS_IN(B) -> INCLUDE(A+B) : (B) = GMI
672  // EXCLUDE(X,Y) -> IS_IN(A) -> EXCLUDE(X+A,Y-A): (A) = GMI
673  for (auto& receivedSource : receivedSources) {
674  EV_DETAIL << "Setting source timer of '" << receivedSource << "' to '" << groupMembershipInterval << "'.\n";
675  SourceRecord *record = groupData->getOrCreateSourceRecord(receivedSource);
676  startTimer(record->sourceTimer, groupMembershipInterval);
677  }
678  }
679  else if (gr.getRecordType() == IGMPV3_RT_IS_EX) {
680  EV_DETAIL << "Received IS_EX" << receivedSources << " report.\n";
681 
682  // Group Timer = GMI
683  EV_DETAIL << "Setting group timer to '" << groupMembershipInterval << "'.\n";
684  startTimer(groupData->timer, groupMembershipInterval);
685 
686  // INCLUDE(A) -> IS_EX(B) -> EXCLUDE(A*B,B-A): Delete (A-B)
687  // EXCLUDE(X,Y) -> IS_EX(A) -> EXCLUDE(A-Y,Y*A): Delete (X-A) Delete (Y-A)
688  for (auto it = groupData->sources.begin(); it != groupData->sources.end(); ++it) {
689  if (!contains(receivedSources, it->first)) {
690  EV_DETAIL << "Deleting source record of '" << it->first << "'.\n";
691  groupData->deleteSourceRecord(it->first);
692  }
693  }
694 
695  // Router State == INCLUDE(A), Report == IS_EX(B): (B-A) = 0
696  // Router State == EXCLUDE(X,Y), Report == IS_EX(A): (A-X-Y) = GMI
697  for (auto& receivedSource : receivedSources) {
698  if (!groupData->hasSourceRecord(receivedSource)) {
699  SourceRecord *record = groupData->createSourceRecord(receivedSource);
700  double timerValue = groupData->filter == IGMPV3_FM_INCLUDE ? 0.0 : groupMembershipInterval;
701  EV_DETAIL << "Setting source timer of '" << receivedSource << "' to '" << timerValue << "'.\n";
702  if (timerValue > 0)
703  startTimer(record->sourceTimer, groupMembershipInterval);
704  }
705  }
706 
707  groupData->filter = IGMPV3_FM_EXCLUDE;
708  }
709  // RFC 3376 6.4.2: Reception of Filter-Mode-Change and Source-List-Change Records
710  else if (gr.getRecordType() == IGMPV3_RT_ALLOW) {
711  EV_DETAIL << "Received ALLOW" << receivedSources << " report.\n";
712 
713  // INCLUDE(A) -> ALLOW(B) -> INCLUDE(A+B): (B) = GMI
714  // EXCLUDE(X,Y) -> ALLOW(A) -> EXCLUDE(X+A,Y-A): (A) = GMI
715  for (auto& receivedSource : receivedSources) {
716  EV_DETAIL << "Setting source timer of '" << receivedSource << "' to '" << groupMembershipInterval << "'.\n";
717  SourceRecord *record = groupData->getOrCreateSourceRecord(receivedSource);
718  startTimer(record->sourceTimer, groupMembershipInterval);
719  }
720  }
721  else if (gr.getRecordType() == IGMPV3_RT_BLOCK) {
722  EV_DETAIL << "Received BLOCK" << receivedSources << " report.\n";
723 
724  if (groupData->filter == IGMPV3_FM_INCLUDE) {
725  // INCLUDE(A) -> BLOCK(B) -> INCLUDE(A): Send Q(G,A*B)
726  Ipv4AddressVector sourcesA;
727  for (auto& elem : groupData->sources)
728  sourcesA.push_back(elem.first);
729 
730  Ipv4AddressVector aIntersectB = set_intersection(sourcesA, receivedSources);
731  if (!aIntersectB.empty()) {
732  EV_INFO << "Sending Group-and-Source-Specific Query for group '" << groupData->groupAddr
733  << "' on interface '" << ie->getInterfaceName() << "'.\n";
734  sendGroupAndSourceSpecificQuery(groupData, aIntersectB);
735  }
736  }
737  else if (groupData->filter == IGMPV3_FM_EXCLUDE) {
738  // EXCLUDE (X,Y) -> BLOCK (A) -> EXCLUDE (X+(A-Y),Y): (A-X-Y)=Group Timer
739  for (auto it = groupData->sources.begin(); it != groupData->sources.end(); ++it) {
740  if (!groupData->hasSourceRecord(it->first)) {
741  SourceRecord *record = groupData->createSourceRecord(it->first);
742  double grouptimertime = groupData->timer->getArrivalTime().dbl() - simTime().dbl();
743  EV_DETAIL << "Setting source timer of '" << it->first << "' to '" << grouptimertime << "'.\n";
744  startTimer(record->sourceTimer, grouptimertime);
745  }
746  }
747  // Send Q(G,A-Y)
748  Ipv4AddressVector ySources;
749  for (auto& elem : groupData->sources) {
750  if (!elem.second->sourceTimer->isScheduled()) {
751  ySources.push_back(elem.first);
752  }
753  }
754  Ipv4AddressVector aMinusY = set_complement(receivedSources, ySources);
755  if (!aMinusY.empty()) {
756  EV_INFO << "Sending Group-and-Source-Specific Query for group '" << groupData->groupAddr
757  << "' on interface '" << ie->getInterfaceName() << "'.\n";
758  sendGroupAndSourceSpecificQuery(groupData, aMinusY);
759  }
760  }
761  }
762  else if (gr.getRecordType() == IGMPV3_RT_TO_IN) {
763  EV_DETAIL << "Received TO_IN" << receivedSources << " report.\n";
764 
765  if (groupData->filter == IGMPV3_FM_INCLUDE) {
766  // INCLUDE(A) -> TO_IN (B) -> INCLUDE (A+B): (B)=GMI
767  for (auto& receivedSource : receivedSources) {
768  EV_DETAIL << "Setting source timer of '" << receivedSource << "' to '" << groupMembershipInterval << "'.\n";
769  SourceRecord *record = groupData->getOrCreateSourceRecord(receivedSource);
770  startTimer(record->sourceTimer, groupMembershipInterval);
771  }
772  // Send Q(G,A-B)
773  Ipv4AddressVector sourcesA;
774  for (auto& elem : groupData->sources)
775  sourcesA.push_back(elem.first);
776  Ipv4AddressVector aMinusB = set_complement(sourcesA, receivedSources);
777  if (!aMinusB.empty()) {
778  EV_INFO << "Sending Group-and-Source-Specific Query for group '" << groupData->groupAddr
779  << "' on interface '" << ie->getInterfaceName() << "'.\n";
780  sendGroupAndSourceSpecificQuery(groupData, aMinusB);
781  }
782  }
783  else if (groupData->filter == IGMPV3_FM_EXCLUDE) {
784  // compute X before modifying the state
785  Ipv4AddressVector sourcesX;
786  for (auto& elem : groupData->sources) {
787  if (elem.second->sourceTimer->isScheduled())
788  sourcesX.push_back(elem.first);
789  }
790 
791  // EXCLUDE(X,Y) -> TO_IN(A) -> EXCLUDE(X+A,Y-A): (A) = GMI
792  for (auto& receivedSource : receivedSources) {
793  EV_DETAIL << "Setting source timer of '" << receivedSource << "' to '" << groupMembershipInterval << "'.\n";
794  SourceRecord *record = groupData->getOrCreateSourceRecord(receivedSource);
795  startTimer(record->sourceTimer, groupMembershipInterval);
796  }
797 
798  // Send Q(G,X-A)
799  Ipv4AddressVector xMinusA = set_complement(sourcesX, receivedSources);
800  if (!xMinusA.empty()) {
801  EV_INFO << "Sending Group-and-Source-Specific Query for group '" << groupData->groupAddr
802  << "' on interface '" << ie->getInterfaceName() << "'.\n";
803  sendGroupAndSourceSpecificQuery(groupData, xMinusA);
804  }
805 
806  // Send Q(G)
807  EV_INFO << "Sending Group-Specific Query for group '" << groupData->groupAddr
808  << "' on interface '" << ie->getInterfaceName() << "'.\n";
809  sendGroupSpecificQuery(groupData);
810  }
811  }
812  else if (gr.getRecordType() == IGMPV3_RT_TO_EX) {
813  EV_DETAIL << "Received TO_EX" << receivedSources << " report.\n";
814 
815  if (groupData->filter == IGMPV3_FM_INCLUDE) {
816  // INCLUDE (A) -> TO_EX(B) -> EXCLUDE (A*B,B-A): Group Timer = GMI
817  EV_DETAIL << "Setting group timer to '" << groupMembershipInterval << "'.\n";
818  startTimer(groupData->timer, groupMembershipInterval);
819 
820  // change to mode exclude
821  groupData->filter = IGMPV3_FM_EXCLUDE;
822 
823  // save A
824  Ipv4AddressVector sourcesA;
825  for (auto& elem : groupData->sources)
826  sourcesA.push_back(elem.first);
827 
828  // (B-A) = 0
829  for (auto& receivedSource : receivedSources) {
830  if (!groupData->hasSourceRecord(receivedSource)) {
831  EV_DETAIL << "Setting source timer of '" << receivedSource << "' to '0'.\n";
832  groupData->createSourceRecord(receivedSource);
833  }
834  }
835 
836  // Delete A-B
837  for (auto& elem : sourcesA) {
838  if (!contains(receivedSources, elem)) {
839  EV_DETAIL << "Deleting source record of '" << elem << "'.\n";
840  groupData->deleteSourceRecord(elem);
841  }
842  }
843 
844  // Send Q(G,A*B)
845  Ipv4AddressVector aIntersectB = set_intersection(sourcesA, receivedSources);
846  if (!aIntersectB.empty()) {
847  EV_INFO << "Sending Group-Specific Query for group '" << groupData->groupAddr
848  << "' on interface '" << ie->getInterfaceName() << "'.\n";
849  sendGroupAndSourceSpecificQuery(groupData, aIntersectB);
850  }
851  }
852  else if (groupData->filter == IGMPV3_FM_EXCLUDE) {
853  // EXCLUDE (X,Y) -> TO_EX (A) -> EXCLUDE (A-Y,Y*A): Group Timer = GMI
854  EV_DETAIL << "Setting group timer to '" << groupMembershipInterval << "'.\n";
855  startTimer(groupData->timer, groupMembershipInterval);
856 
857  // save Y
858  Ipv4AddressVector sourcesY;
859  for (auto& elem : groupData->sources) {
860  if (!elem.second->sourceTimer->isScheduled())
861  sourcesY.push_back(elem.first);
862  }
863 
864  // Delete (X-A) Delete (Y-A)
865  for (auto it = groupData->sources.begin(); it != groupData->sources.end();) {
866  auto rec = it->first;
867  ++it; // let's advance the iterator now because the deleteSourcerecord call will invalidate it and we wont be able to increment it after that
868  if (!contains(receivedSources, it->first)) {
869  EV_DETAIL << "Deleting source record of '" << rec << "'.\n";
870  groupData->deleteSourceRecord(rec);
871  }
872  }
873 
874  // (A-X-Y) = GMI FIXME should be set to Group Timer
875  for (auto& receivedSource : receivedSources) {
876  if (!groupData->hasSourceRecord(receivedSource)) {
877  EV_DETAIL << "Setting source timer of '" << receivedSource << "' to '" << groupMembershipInterval << "'.\n";
878  SourceRecord *record = groupData->createSourceRecord(receivedSource);
879  startTimer(record->sourceTimer, groupMembershipInterval);
880  }
881  }
882 
883  // Send Q(G,A-Y)
884  Ipv4AddressVector aMinusY = set_complement(receivedSources, sourcesY);
885  if (!aMinusY.empty()) {
886  EV_INFO << "Sending Group-Specific Query for group '" << groupData->groupAddr
887  << "' on interface '" << ie->getInterfaceName() << "'.\n";
888  sendGroupAndSourceSpecificQuery(groupData, aMinusY);
889  }
890  }
891  }
892 
893  EV_DETAIL << "New Router State is " << groupData->getStateInfo() << ".\n";
894 
895  // update interface state
896  Ipv4MulticastSourceList newSourceList;
897  groupData->collectForwardedSources(newSourceList);
898 
899  if (newSourceList != oldSourceList) {
900  ie->getProtocolDataForUpdate<Ipv4InterfaceData>()->setMulticastListeners(groupData->groupAddr, newSourceList.filterMode, newSourceList.sources);
901  // TODO notifications?
902  }
903  }
904  }
905  delete packet;
906 }

◆ processRouterGeneralQueryTimer()

void inet::Igmpv3::processRouterGeneralQueryTimer ( cMessage *  msg)
protectedvirtual
329 {
330  RouterInterfaceData *interfaceData = (RouterInterfaceData *)msg->getContextPointer();
331  NetworkInterface *ie = interfaceData->ie;
332  ASSERT(ie);
333  EV_INFO << "General Query timer expired on interface='" << ie->getInterfaceName() << "'.\n";
334  RouterState state = interfaceData->state;
335  if (state == IGMPV3_RS_QUERIER || state == IGMPV3_RS_NON_QUERIER) {
336  EV_INFO << "Sending General Query on interface '" << ie->getInterfaceName() << "', and scheduling next Query to '"
337  << (simTime() + queryInterval) << "'.\n";
338  interfaceData->state = IGMPV3_RS_QUERIER;
339  sendGeneralQuery(interfaceData, queryResponseInterval);
341  }
342 }

◆ processRouterGroupTimer()

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.

350 {
351  RouterGroupData *groupData = (RouterGroupData *)msg->getContextPointer();
352  NetworkInterface *ie = groupData->parent->ie;
353 
354  EV_INFO << "Group Timer for group '" << groupData->groupAddr << "' on interface '" << ie->getInterfaceName() << "' has expired.\n";
355  EV_DETAIL << "Router State is " << groupData->getStateInfo() << ".\n";
356 
357  if (groupData->filter == IGMPV3_FM_EXCLUDE) {
358  bool timerRunning = false;
359  for (auto it = groupData->sources.begin(); it != groupData->sources.end(); ++it) {
360  if (!it->second->sourceTimer->isScheduled()) {
361  EV_DETAIL << "Deleting source record of '" << it->first << "'.\n";
362  groupData->deleteSourceRecord(it->first);
363  }
364  else {
365  timerRunning = true;
366  }
367  }
368  groupData->filter = IGMPV3_FM_INCLUDE;
369  if (!timerRunning) {
370  EV_DETAIL << "Deleting multicast listener for group '" << groupData->groupAddr << "' from the interface table.\n";
371  ie->getProtocolDataForUpdate<Ipv4InterfaceData>()->removeMulticastListener(groupData->groupAddr);
372  groupData->parent->deleteGroupData(groupData->groupAddr);
373 
374  EV_DETAIL << "New Router State is <deleted>.\n";
375  return;
376  }
377  }
378 
379  EV_DETAIL << "New Router State is " << groupData->getStateInfo() << ".\n";
380 }

◆ processRouterSourceTimer()

void inet::Igmpv3::processRouterSourceTimer ( cMessage *  msg)
protectedvirtual

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

386 {
387  SourceRecord *sourceRecord = (SourceRecord *)msg->getContextPointer();
388  RouterGroupData *groupData = sourceRecord->parent;
389  NetworkInterface *ie = groupData->parent->ie;
390 
391  EV_INFO << "Source timer for group '" << groupData->groupAddr << "' and source '" << sourceRecord->sourceAddr
392  << "' on interface '" << ie->getInterfaceName() << "' has expired.\n";
393 
394  bool last = true;
395  if (groupData->filter == IGMPV3_FM_INCLUDE) {
396  groupData->deleteSourceRecord(sourceRecord->sourceAddr);
397  }
398  for (auto& elem : groupData->sources) {
399  if (elem.second->sourceTimer->isScheduled()) {
400  last = false;
401  }
402  }
403  if (last) {
404  ie->getProtocolDataForUpdate<Ipv4InterfaceData>()->removeMulticastListener(groupData->groupAddr);
405  groupData->parent->deleteGroupData(groupData->groupAddr);
406  }
407 }

◆ receiveSignal()

void inet::Igmpv3::receiveSignal ( cComponent *  source,
simsignal_t  signalID,
cObject *  obj,
cObject *  details 
)
overrideprotectedvirtual
142 {
143  Enter_Method("%s", cComponent::getSignalName(signalID));
144 
145  NetworkInterface *ie;
146  int interfaceId;
147  const Ipv4MulticastGroupSourceInfo *info;
148 
149  if (signalID == ipv4MulticastChangeSignal) {
150  info = check_and_cast<const Ipv4MulticastGroupSourceInfo *>(obj);
151  multicastSourceListChanged(info->ie, info->groupAddress, info->sourceList);
152  }
153  else if (signalID == interfaceCreatedSignal) {
154  ie = const_cast<NetworkInterface *>(check_and_cast<const NetworkInterface *>(obj));
155  if (ie->isMulticast())
156  configureInterface(ie);
157  }
158  else if (signalID == interfaceDeletedSignal) {
159  ie = const_cast<NetworkInterface *>(check_and_cast<const NetworkInterface *>(obj));
160  if (ie->isMulticast()) {
161  interfaceId = ie->getInterfaceId();
162  deleteHostInterfaceData(interfaceId);
163  deleteRouterInterfaceData(interfaceId);
164  }
165  }
166 }

◆ sendGeneralQuery()

void inet::Igmpv3::sendGeneralQuery ( RouterInterfaceData interface,
double  maxRespTime 
)
protectedvirtual
911 {
912  if (interfaceData->state == IGMPV3_RS_QUERIER) {
913  Packet *packet = new Packet("Igmpv3 query");
914  const auto& msg = makeShared<Igmpv3Query>();
915  msg->setType(IGMP_MEMBERSHIP_QUERY);
916  msg->setMaxRespTimeCode(codeTime((uint16_t)(maxRespTime * 10.0)));
917  msg->setChunkLength(B(12));
918  insertCrc(msg, packet);
919  packet->insertAtFront(msg);
920  sendQueryToIP(packet, interfaceData->ie, Ipv4Address::ALL_HOSTS_MCAST);
921 
922  numQueriesSent++;
924  }
925 }

◆ sendGroupAndSourceSpecificQuery()

void inet::Igmpv3::sendGroupAndSourceSpecificQuery ( RouterGroupData group,
const Ipv4AddressVector sources 
)
protectedvirtual
982 {
983  ASSERT(!sources.empty());
984 
985  RouterInterfaceData *interfaceData = groupData->parent;
986 
987  if (interfaceData->state == IGMPV3_RS_QUERIER) {
988  Packet *packet = new Packet("Igmpv3 query");
989  const auto& msg = makeShared<Igmpv3Query>();
990  msg->setType(IGMP_MEMBERSHIP_QUERY);
991  msg->setGroupAddress(groupData->groupAddr);
992  msg->setMaxRespTimeCode(codeTime((uint16_t)(10.0 * lastMemberQueryInterval)));
993  msg->setSourceList(sources);
994  msg->setChunkLength(B(12 + (4 * sources.size())));
995  insertCrc(msg, packet);
996  packet->insertAtFront(msg);
997  sendQueryToIP(packet, interfaceData->ie, groupData->groupAddr);
998 
999  numQueriesSent++;
1001  }
1002 }

◆ sendGroupReport()

void inet::Igmpv3::sendGroupReport ( NetworkInterface ie,
const std::vector< GroupRecord > &  records 
)
protectedvirtual
960 {
961  EV << "Igmpv3: sending Membership Report on iface=" << ie->getInterfaceName() << "\n";
962  Packet *packet = new Packet("Igmpv3 report");
963  const auto& msg = makeShared<Igmpv3Report>();
964  unsigned int byteLength = 8; // Igmpv3Report header size
965  msg->setType(IGMPV3_MEMBERSHIP_REPORT);
966  msg->setGroupRecordArraySize(records.size());
967  for (size_t i = 0; i < records.size(); ++i) {
968  Ipv4Address group = records[i].getGroupAddress();
969  ASSERT(group.isMulticast() && !group.isLinkLocalMulticast());
970  msg->setGroupRecord(i, records[i]);
971  byteLength += 8 + records[i].getSourceList().size() * 4; // 8 byte header + n * 4 byte (Ipv4Address)
972  }
973  msg->setChunkLength(B(byteLength));
974  insertCrc(msg, packet);
975  packet->insertAtFront(msg);
977  numReportsSent++;
978 }

◆ sendGroupSpecificQuery()

void inet::Igmpv3::sendGroupSpecificQuery ( RouterGroupData group)
protectedvirtual
933 {
934  RouterInterfaceData *interfaceData = groupData->parent;
935  bool suppressFlag = groupData->timer->isScheduled() && groupData->timer->getArrivalTime() > simTime() + lastMemberQueryTime;
936 
937  // Set group timer to LMQT
938  startTimer(groupData->timer, lastMemberQueryTime);
939 
940  if (interfaceData->state == IGMPV3_RS_QUERIER) {
941  Packet *packet = new Packet("Igmpv3 query");
942  const auto& msg = makeShared<Igmpv3Query>();
943  msg->setType(IGMP_MEMBERSHIP_QUERY);
944  msg->setGroupAddress(groupData->groupAddr);
945  msg->setMaxRespTimeCode(codeTime((uint16_t)(10.0 * lastMemberQueryInterval)));
946  msg->setSuppressRouterProc(suppressFlag);
947  msg->setChunkLength(B(12));
948  insertCrc(msg, packet);
949  packet->insertAtFront(msg);
950  sendQueryToIP(packet, interfaceData->ie, groupData->groupAddr);
951 
952  numQueriesSent++;
954  }
955 
956  // TODO retransmission [Last Member Query Count]-1 times
957 }

◆ sendQueryToIP()

void inet::Igmpv3::sendQueryToIP ( Packet msg,
NetworkInterface ie,
Ipv4Address  dest 
)
protectedvirtual
1024 {
1025  ASSERT(ie->isMulticast());
1026 
1027  msg->addTagIfAbsent<PacketProtocolTag>()->setProtocol(&Protocol::igmp);
1028  msg->addTagIfAbsent<DispatchProtocolInd>()->setProtocol(&Protocol::igmp);
1029  msg->addTagIfAbsent<DispatchProtocolReq>()->setProtocol(&Protocol::ipv4);
1030  msg->addTagIfAbsent<InterfaceReq>()->setInterfaceId(ie->getInterfaceId());
1031  msg->addTagIfAbsent<L3AddressReq>()->setDestAddress(dest);
1032  msg->addTagIfAbsent<HopLimitReq>()->setHopLimit(1);
1033 
1034  // TODO fill Router Alert option
1035  auto raOption = new Ipv4OptionRouterAlert();
1036  msg->addTag<Ipv4OptionsReq>()->appendOption(raOption);
1037  // set Type of Service to 0xc0
1038  msg->addTag<DscpReq>()->setDifferentiatedServicesCodePoint(0xc0 >> 2);
1039  send(msg, "ipOut");
1040 }

◆ sendReportToIP()

void inet::Igmpv3::sendReportToIP ( Packet msg,
NetworkInterface ie,
Ipv4Address  dest 
)
protectedvirtual
1005 {
1006  ASSERT(ie->isMulticast());
1007 
1008  msg->addTagIfAbsent<PacketProtocolTag>()->setProtocol(&Protocol::igmp);
1009  msg->addTagIfAbsent<DispatchProtocolInd>()->setProtocol(&Protocol::igmp);
1010  msg->addTagIfAbsent<DispatchProtocolReq>()->setProtocol(&Protocol::ipv4);
1011  msg->addTagIfAbsent<InterfaceReq>()->setInterfaceId(ie->getInterfaceId());
1012  msg->addTagIfAbsent<L3AddressReq>()->setDestAddress(dest);
1013  msg->addTagIfAbsent<HopLimitReq>()->setHopLimit(1);
1014 
1015  // TODO fill Router Alert option
1016  auto raOption = new Ipv4OptionRouterAlert();
1017  msg->addTag<Ipv4OptionsReq>()->appendOption(raOption);
1018  // TODO set Type of Service to 0xc0
1019 // msg->addTag<DscpReq>()->setDifferentiatedServicesCodePoint(0xc0 >> 2);
1020  send(msg, "ipOut");
1021 }

◆ set_complement()

Ipv4AddressVector inet::Igmpv3::set_complement ( const Ipv4AddressVector first,
const Ipv4AddressVector second 
)
static
1322 {
1323  ASSERT(isSorted(first));
1324  ASSERT(isSorted(second));
1325 
1326  Ipv4AddressVector complement(first.size());
1327 
1328  auto it = set_difference(first.begin(), first.end(), second.begin(), second.end(), complement.begin());
1329  complement.resize(it - complement.begin());
1330  return complement;
1331 }

◆ set_intersection()

Ipv4AddressVector inet::Igmpv3::set_intersection ( const Ipv4AddressVector first,
const Ipv4AddressVector second 
)
static
1334 {
1335  ASSERT(isSorted(first));
1336  ASSERT(isSorted(second));
1337 
1338  Ipv4AddressVector intersection(min(first.size(), second.size()));
1339 
1340  auto it = std::set_intersection(first.begin(), first.end(), second.begin(), second.end(), intersection.begin());
1341  intersection.resize(it - intersection.begin());
1342  return intersection;
1343 }

◆ set_union()

Ipv4AddressVector inet::Igmpv3::set_union ( const Ipv4AddressVector first,
const Ipv4AddressVector second 
)
static
1346 {
1347  ASSERT(isSorted(first));
1348  ASSERT(isSorted(second));
1349 
1350  Ipv4AddressVector result(first.size() + second.size());
1351 
1352  auto it = std::set_union(first.begin(), first.end(), second.begin(), second.end(), result.begin());
1353  result.resize(it - result.begin());
1354  return result;
1355 }

◆ startTimer()

void inet::Igmpv3::startTimer ( cMessage *  timer,
double  interval 
)
protectedvirtual
493 {
494  ASSERT(timer);
495  rescheduleAfter(interval, timer);
496 }

◆ verifyCrc()

bool inet::Igmpv3::verifyCrc ( const Packet packet)
1470 {
1471  const auto& igmpMsg = packet->peekAtFront<IgmpMessage>(b(-1), Chunk::PF_ALLOW_INCORRECT);
1472  switch (igmpMsg->getCrcMode()) {
1473  case CRC_DECLARED_CORRECT:
1474  // if the CRC mode is declared to be correct, then the check passes if and only if the chunks are correct
1475  return igmpMsg->isCorrect();
1477  // if the CRC mode is declared to be incorrect, then the check fails
1478  return false;
1479  case CRC_COMPUTED: {
1480  // otherwise compute the CRC, the check passes if the result is 0xFFFF (includes the received CRC)
1481  auto dataBytes = packet->peekDataAsBytes(Chunk::PF_ALLOW_INCORRECT);
1482  uint16_t crc = TcpIpChecksum::checksum(dataBytes->getBytes());
1483  // TODO delete these isCorrect calls, rely on CRC only
1484  return crc == 0 && igmpMsg->isCorrect();
1485  }
1486  default:
1487  throw cRuntimeError("Unknown CRC mode");
1488  }
1489 }

Member Data Documentation

◆ crcMode

CrcMode inet::Igmpv3::crcMode = CRC_MODE_UNDEFINED
protected

Referenced by insertCrc().

◆ enabled

bool inet::Igmpv3::enabled
protected

◆ groupMembershipInterval

double inet::Igmpv3::groupMembershipInterval
protected

◆ hostData

InterfaceToHostDataMap inet::Igmpv3::hostData
protected

Referenced by getHostInterfaceData().

◆ ift

ModuleRefByPar<IInterfaceTable> inet::Igmpv3::ift
protected

◆ lastMemberQueryCount

int inet::Igmpv3::lastMemberQueryCount
protected

◆ lastMemberQueryInterval

double inet::Igmpv3::lastMemberQueryInterval
protected

◆ lastMemberQueryTime

double inet::Igmpv3::lastMemberQueryTime
protected

◆ numGeneralQueriesRecv

int inet::Igmpv3::numGeneralQueriesRecv = 0
protected

◆ numGeneralQueriesSent

int inet::Igmpv3::numGeneralQueriesSent = 0
protected

◆ numGroupAndSourceSpecificQueriesRecv

int inet::Igmpv3::numGroupAndSourceSpecificQueriesRecv = 0
protected

◆ numGroupAndSourceSpecificQueriesSent

int inet::Igmpv3::numGroupAndSourceSpecificQueriesSent = 0
protected

◆ numGroups

int inet::Igmpv3::numGroups = 0
protected

◆ numGroupSpecificQueriesRecv

int inet::Igmpv3::numGroupSpecificQueriesRecv = 0
protected

◆ numGroupSpecificQueriesSent

int inet::Igmpv3::numGroupSpecificQueriesSent = 0
protected

◆ numHostGroups

int inet::Igmpv3::numHostGroups = 0
protected

◆ numQueriesRecv

int inet::Igmpv3::numQueriesRecv = 0
protected

◆ numQueriesSent

int inet::Igmpv3::numQueriesSent = 0
protected

◆ numReportsRecv

int inet::Igmpv3::numReportsRecv = 0
protected

◆ numReportsSent

int inet::Igmpv3::numReportsSent = 0
protected

◆ numRouterGroups

int inet::Igmpv3::numRouterGroups = 0
protected

◆ otherQuerierPresentInterval

double inet::Igmpv3::otherQuerierPresentInterval
protected

◆ queryInterval

double inet::Igmpv3::queryInterval
protected

◆ queryResponseInterval

double inet::Igmpv3::queryResponseInterval
protected

◆ robustness

int inet::Igmpv3::robustness
protected

◆ routerData

InterfaceToRouterDataMap inet::Igmpv3::routerData
protected

Referenced by getRouterInterfaceData().

◆ rt

ModuleRefByPar<IRoutingTable> inet::Igmpv3::rt
protected

◆ startupQueryCount

int inet::Igmpv3::startupQueryCount
protected

◆ startupQueryInterval

double inet::Igmpv3::startupQueryInterval
protected

◆ unsolicitedReportInterval

double inet::Igmpv3::unsolicitedReportInterval
protected

The documentation for this class was generated from the following files:
inet::Igmpv3::sendGeneralQuery
virtual void sendGeneralQuery(RouterInterfaceData *interface, double maxRespTime)
Definition: Igmpv3.cc:910
inet::Igmpv3::insertCrc
static void insertCrc(CrcMode crcMode, const Ptr< IgmpMessage > &igmpMsg, Packet *payload)
Definition: Igmpv3.cc:1441
inet::Igmpv3::numGroupAndSourceSpecificQueriesRecv
int numGroupAndSourceSpecificQueriesRecv
Definition: Igmpv3.h:224
inet::Igmpv3::IGMPV3_RS_INITIAL
@ IGMPV3_RS_INITIAL
Definition: Igmpv3.h:36
inet::Igmpv3::IGMPV3_RT_IS_EX
@ IGMPV3_RT_IS_EX
Definition: Igmpv3.h:60
inet::Igmpv3::set_union
static Ipv4AddressVector set_union(const Ipv4AddressVector &first, const Ipv4AddressVector &second)
Definition: Igmpv3.cc:1345
inet::Igmpv3::numRouterGroups
int numRouterGroups
Definition: Igmpv3.h:214
inet::Igmpv3::IGMPV3_HGS_DELAYING_MEMBER
@ IGMPV3_HGS_DELAYING_MEMBER
Definition: Igmpv3.h:49
inet::Igmpv3::processReport
virtual void processReport(Packet *msg)
Definition: Igmpv3.cc:638
inet::Igmpv3::deleteRouterInterfaceData
virtual void deleteRouterInterfaceData(int interfaceId)
Definition: Igmpv3.cc:275
inet::Igmpv3::IGMPV3_H_GENERAL_QUERY_TIMER
@ IGMPV3_H_GENERAL_QUERY_TIMER
Definition: Igmpv3.h:71
inet::Igmpv3::addWatches
void addWatches()
Definition: Igmpv3.cc:120
inet::Igmpv3::sendGroupSpecificQuery
virtual void sendGroupSpecificQuery(RouterGroupData *group)
Definition: Igmpv3.cc:932
inet::Igmpv3::createRouterInterfaceData
virtual RouterInterfaceData * createRouterInterfaceData(NetworkInterface *ie)
Definition: Igmpv3.cc:1072
inet::sort
void sort(std::vector< T > &v)
Definition: stlutils.h:129
inet::Igmpv3::startTimer
virtual void startTimer(cMessage *timer, double interval)
Definition: Igmpv3.cc:492
DscpReq
removed DscpReq Ipv4ControlInfo Ipv6ControlInfo up L3AddressInd DispatchProtocolReq L4PortInd Ipv4ControlInfo Ipv6ControlInfo down DscpReq
Definition: IUdp-gates.txt:25
inet::Igmpv3::numGeneralQueriesSent
int numGeneralQueriesSent
Definition: Igmpv3.h:219
inet::Igmpv3::ift
ModuleRefByPar< IInterfaceTable > ift
Definition: Igmpv3.h:193
inet::Igmpv3::processRouterGeneralQueryTimer
virtual void processRouterGeneralQueryTimer(cMessage *msg)
Definition: Igmpv3.cc:328
inet::Igmpv3::numReportsSent
int numReportsSent
Definition: Igmpv3.h:225
inet::INCORRECTLY_RECEIVED
@ INCORRECTLY_RECEIVED
Definition: Simsignals_m.h:71
inet::Protocol::ipv4
static const Protocol ipv4
Definition: Protocol.h:93
inet::Igmpv3::startupQueryCount
int startupQueryCount
Definition: Igmpv3.h:202
inet::Igmpv3::IGMPV3_RGS_NO_MEMBERS_PRESENT
@ IGMPV3_RGS_NO_MEMBERS_PRESENT
Definition: Igmpv3.h:42
inet::Igmpv3::IGMPV3_HGS_IDLE_MEMBER
@ IGMPV3_HGS_IDLE_MEMBER
Definition: Igmpv3.h:50
inet::IGMPV3_MEMBERSHIP_REPORT
@ IGMPV3_MEMBERSHIP_REPORT
Definition: IgmpMessage_m.h:75
inet::Igmpv3::processIgmpMessage
virtual void processIgmpMessage(Packet *msg)
Definition: Igmpv3.cc:500
inet::sctp::min
double min(const double a, const double b)
Returns the minimum of a and b.
Definition: SctpAssociation.h:261
inet::Igmpv3::unsolicitedReportInterval
double unsolicitedReportInterval
Definition: Igmpv3.h:206
inet::Igmpv3::IGMPV3_R_SOURCE_TIMER
@ IGMPV3_R_SOURCE_TIMER
Definition: Igmpv3.h:70
inet::getContainingNode
cModule * getContainingNode(const cModule *from)
Find the node containing the given module.
Definition: ModuleAccess.cc:40
inet::Igmpv3::FilterMode
FilterMode
Definition: Igmpv3.h:53
inet::CRC_COMPUTED
@ CRC_COMPUTED
Definition: CrcMode_m.h:59
InterfaceReq
removed InterfaceReq
Definition: IUdp-gates.txt:11
inet::Chunk::serialize
static void serialize(MemoryOutputStream &stream, const Ptr< const Chunk > &chunk, b offset=b(0), b length=b(-1))
Serializes a chunk into the given stream.
Definition: Chunk.cc:175
inet::Igmpv3::IGMPV3_RT_ALLOW
@ IGMPV3_RT_ALLOW
Definition: Igmpv3.h:63
inet::Igmpv3::crcMode
CrcMode crcMode
Definition: Igmpv3.h:209
DispatchProtocolReq
removed DscpReq Ipv4ControlInfo Ipv6ControlInfo up L3AddressInd DispatchProtocolReq L4PortInd Ipv4ControlInfo Ipv6ControlInfo down DispatchProtocolReq
Definition: IUdp-gates.txt:25
L3AddressInd
removed DscpReq Ipv4ControlInfo Ipv6ControlInfo up L3AddressInd L3AddressInd
Definition: IUdp-gates.txt:20
inet::ipv4MulticastChangeSignal
simsignal_t ipv4MulticastChangeSignal
Definition: Simsignals.cc:51
inet::Igmpv3::set_intersection
static Ipv4AddressVector set_intersection(const Ipv4AddressVector &first, const Ipv4AddressVector &second)
Definition: Igmpv3.cc:1333
inet::IGMP_MEMBERSHIP_QUERY
@ IGMP_MEMBERSHIP_QUERY
Definition: IgmpMessage_m.h:71
inet::Igmpv3::lastMemberQueryInterval
double lastMemberQueryInterval
Definition: Igmpv3.h:203
inet::parseCrcMode
CrcMode parseCrcMode(const char *crcModeString, bool allowDisable)
Definition: CrcMode.cc:14
inet::Igmpv3::set_complement
static Ipv4AddressVector set_complement(const Ipv4AddressVector &first, const Ipv4AddressVector &second)
Definition: Igmpv3.cc:1321
inet::Ipv4Address::ALL_IGMPV3_ROUTERS_MCAST
static const Ipv4Address ALL_IGMPV3_ROUTERS_MCAST
224.0.0.22 All IGMPv3 routers
Definition: Ipv4Address.h:101
inet::Igmpv3::IGMPV3_RGS_MEMBERS_PRESENT
@ IGMPV3_RGS_MEMBERS_PRESENT
Definition: Igmpv3.h:43
inet::Igmpv3::routerData
InterfaceToRouterDataMap routerData
Definition: Igmpv3.h:233
inet::packetDroppedSignal
simsignal_t packetDroppedSignal
Definition: Simsignals.cc:85
inet::Ipv4AddressVector
std::vector< Ipv4Address > Ipv4AddressVector
Definition: Ipv4Address_m.h:46
inet::Igmpv3::multicastSourceListChanged
virtual void multicastSourceListChanged(NetworkInterface *ie, Ipv4Address group, const Ipv4MulticastSourceList &sourceList)
This function is sending report message if interface state was changed.
Definition: Igmpv3.cc:172
inet::Igmpv3::numReportsRecv
int numReportsRecv
Definition: Igmpv3.h:226
PacketProtocolTag
removed DscpReq Ipv4ControlInfo Ipv6ControlInfo up L3AddressInd DispatchProtocolReq L4PortInd Ipv4ControlInfo Ipv6ControlInfo down PacketProtocolTag
Definition: IUdp-gates.txt:25
inet::Igmpv3::lastMemberQueryCount
int lastMemberQueryCount
Definition: Igmpv3.h:204
inet::Igmpv3::groupMembershipInterval
double groupMembershipInterval
Definition: Igmpv3.h:199
inet::Igmpv3::otherQuerierPresentInterval
double otherQuerierPresentInterval
Definition: Igmpv3.h:200
inet::Igmpv3::deleteHostInterfaceData
virtual void deleteHostInterfaceData(int interfaceId)
Definition: Igmpv3.cc:265
inet::interfaceDeletedSignal
simsignal_t interfaceDeletedSignal
Definition: Simsignals.cc:31
inet::Igmpv3::processQuery
virtual void processQuery(Packet *msg)
Definition: Igmpv3.cc:529
inet::units::units::B
intscale< b, 1, 8 > B
Definition: Units.h:1168
inet::Igmpv3::hostData
InterfaceToHostDataMap hostData
Definition: Igmpv3.h:232
inet::Igmpv3::codeTime
static uint8_t codeTime(uint16_t timevalue)
Definition: Igmpv3.cc:1373
inet::Igmpv3::numGroupSpecificQueriesSent
int numGroupSpecificQueriesSent
Definition: Igmpv3.h:221
inet::Igmpv3::numHostGroups
int numHostGroups
Definition: Igmpv3.h:213
inet::Igmpv3::processRouterSourceTimer
virtual void processRouterSourceTimer(cMessage *msg)
Function for checking expired source timers if group is in INCLUDE filter mode.
Definition: Igmpv3.cc:385
inet::Igmpv3::IGMPV3_RT_TO_EX
@ IGMPV3_RT_TO_EX
Definition: Igmpv3.h:62
inet::Igmpv3::decodeTime
static uint16_t decodeTime(uint8_t code)
Function for computing the time value in seconds from an encoded value.
Definition: Igmpv3.cc:1359
inet::Igmpv3::sendReportToIP
virtual void sendReportToIP(Packet *msg, NetworkInterface *ie, Ipv4Address dest)
Definition: Igmpv3.cc:1004
if
if(cwndVector) cwndVector -> record(state->snd_cwnd)
inet::Igmpv3::processRouterGroupTimer
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:349
inet::contains
bool contains(const std::vector< T > &v, const Tk &a)
Definition: stlutils.h:65
inet::Igmpv3::IGMPV3_FM_INCLUDE
@ IGMPV3_FM_INCLUDE
Definition: Igmpv3.h:54
HopLimitReq
removed HopLimitReq
Definition: IUdp-gates.txt:11
inet::Igmpv3::IGMPV3_HGS_NON_MEMBER
@ IGMPV3_HGS_NON_MEMBER
Definition: Igmpv3.h:48
inet::Igmpv3::processHostGroupQueryTimer
virtual void processHostGroupQueryTimer(cMessage *msg)
Definition: Igmpv3.cc:461
inet::Igmpv3::configureInterface
virtual void configureInterface(NetworkInterface *ie)
Definition: Igmpv3.cc:251
inet::Igmpv3::RouterState
RouterState
Definition: Igmpv3.h:35
inet::INITSTAGE_LOCAL
INET_API InitStage INITSTAGE_LOCAL
Initialization of local state that don't use or affect other modules includes:
inet::Igmpv3::IGMPV3_R_GROUP_TIMER
@ IGMPV3_R_GROUP_TIMER
Definition: Igmpv3.h:69
inet::Igmpv3::numGeneralQueriesRecv
int numGeneralQueriesRecv
Definition: Igmpv3.h:220
inet::Igmpv3::queryInterval
double queryInterval
Definition: Igmpv3.h:197
inet::Igmpv3::IGMPV3_RS_QUERIER
@ IGMPV3_RS_QUERIER
Definition: Igmpv3.h:37
inet::Igmpv3::IGMPV3_H_GROUP_TIMER
@ IGMPV3_H_GROUP_TIMER
Definition: Igmpv3.h:72
inet::Igmpv3::createHostInterfaceData
virtual HostInterfaceData * createHostInterfaceData(NetworkInterface *ie)
Definition: Igmpv3.cc:1089
inet::units::values::b
value< int64_t, units::b > b
Definition: Units.h:1241
NUM_INIT_STAGES
#define NUM_INIT_STAGES
Definition: InitStageRegistry.h:73
inet::Chunk::PF_ALLOW_INCORRECT
@ PF_ALLOW_INCORRECT
Definition: Chunk.h:281
inet::Igmpv3::rt
ModuleRefByPar< IRoutingTable > rt
Definition: Igmpv3.h:192
inet::Protocol::igmp
static const Protocol igmp
Definition: Protocol.h:91
inet::TcpIpChecksum::checksum
static uint16_t checksum(const void *addr, unsigned int count)
Definition: TcpIpChecksum.h:33
inet::Igmpv3::IGMPV3_RS_NON_QUERIER
@ IGMPV3_RS_NON_QUERIER
Definition: Igmpv3.h:38
inet::CRC_DECLARED_CORRECT
@ CRC_DECLARED_CORRECT
Definition: CrcMode_m.h:57
inet::CRC_DECLARED_INCORRECT
@ CRC_DECLARED_INCORRECT
Definition: CrcMode_m.h:58
inet::Igmpv3::IGMPV3_RT_TO_IN
@ IGMPV3_RT_TO_IN
Definition: Igmpv3.h:61
inet::Igmpv3::IGMPV3_RT_IS_IN
@ IGMPV3_RT_IS_IN
Definition: Igmpv3.h:59
inet::Igmpv3::queryResponseInterval
double queryResponseInterval
Definition: Igmpv3.h:198
inet::Igmpv3::numGroupAndSourceSpecificQueriesSent
int numGroupAndSourceSpecificQueriesSent
Definition: Igmpv3.h:223
Enter_Method
#define Enter_Method(...)
Definition: SelfDoc.h:71
inet::Igmpv3::getHostInterfaceData
virtual HostInterfaceData * getHostInterfaceData(NetworkInterface *ie)
Definition: Igmpv3.cc:1077
inet::Igmpv3::numGroupSpecificQueriesRecv
int numGroupSpecificQueriesRecv
Definition: Igmpv3.h:222
inet::Igmpv3::numQueriesRecv
int numQueriesRecv
Definition: Igmpv3.h:218
inet::Igmpv3::robustness
int robustness
Definition: Igmpv3.h:196
inet::Igmpv3::numGroups
int numGroups
Definition: Igmpv3.h:212
inet::Igmpv3::sendGroupReport
virtual void sendGroupReport(NetworkInterface *ie, const std::vector< GroupRecord > &records)
Definition: Igmpv3.cc:959
inet::Ipv4Address::ALL_HOSTS_MCAST
static const Ipv4Address ALL_HOSTS_MCAST
224.0.0.1 All hosts on a subnet
Definition: Ipv4Address.h:96
inet::Igmpv3::startupQueryInterval
double startupQueryInterval
Definition: Igmpv3.h:201
inet::Igmpv3::sendGroupAndSourceSpecificQuery
virtual void sendGroupAndSourceSpecificQuery(RouterGroupData *group, const Ipv4AddressVector &sources)
Definition: Igmpv3.cc:981
inet::Igmpv3::IGMPV3_FM_EXCLUDE
@ IGMPV3_FM_EXCLUDE
Definition: Igmpv3.h:55
inet::Igmpv3::IGMPV3_RGS_CHECKING_MEMBERSHIP
@ IGMPV3_RGS_CHECKING_MEMBERSHIP
Definition: Igmpv3.h:44
inet::interfaceCreatedSignal
simsignal_t interfaceCreatedSignal
Definition: Simsignals.cc:30
inet::MCAST_INCLUDE_SOURCES
@ MCAST_INCLUDE_SOURCES
Definition: NetworkInterface.h:33
inet::Igmpv3::IGMPV3_RT_BLOCK
@ IGMPV3_RT_BLOCK
Definition: Igmpv3.h:64
inet::registerProtocol
void registerProtocol(const Protocol &protocol, cGate *gate, ServicePrimitive servicePrimitive)
Registers a protocol primitive (PDU processing) at the given gate.
Definition: IProtocolRegistrationListener.cc:83
inet::Igmpv3::getRouterInterfaceData
virtual RouterInterfaceData * getRouterInterfaceData(NetworkInterface *ie)
Definition: Igmpv3.cc:1060
inet::Igmpv3::sendQueryToIP
virtual void sendQueryToIP(Packet *msg, NetworkInterface *ie, Ipv4Address dest)
Definition: Igmpv3.cc:1023
inet::Igmpv3::enabled
bool enabled
Definition: Igmpv3.h:195
inet::INITSTAGE_NETWORK_LAYER_PROTOCOLS
INET_API InitStage INITSTAGE_NETWORK_LAYER_PROTOCOLS
Initialization of network layer protocols over IP.
inet::Igmpv3::numQueriesSent
int numQueriesSent
Definition: Igmpv3.h:217
inet::Igmpv3::verifyCrc
bool verifyCrc(const Packet *packet)
Definition: Igmpv3.cc:1469
inet::Igmpv3::IGMPV3_R_GENERAL_QUERY_TIMER
@ IGMPV3_R_GENERAL_QUERY_TIMER
Definition: Igmpv3.h:68
inet::Igmpv3::lastMemberQueryTime
double lastMemberQueryTime
Definition: Igmpv3.h:205
inet::Igmpv3::processHostGeneralQueryTimer
virtual void processHostGeneralQueryTimer(cMessage *msg)
Definition: Igmpv3.cc:410