igmp_snooping_misc.c
Go to the documentation of this file.
1 /**
2  * @file igmp_snooping_misc.c
3  * @brief Helper functions for IGMP snooping switch
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.4.0
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL IGMP_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/net.h"
36 #include "ipv4/ipv4.h"
37 #include "ipv4/ipv4_misc.h"
38 #include "igmp/igmp_snooping.h"
40 #include "debug.h"
41 
42 //Check TCP/IP stack configuration
43 #if (IPV4_SUPPORT == ENABLED && IGMP_SNOOPING_SUPPORT == ENABLED)
44 
45 
46 /**
47  * @brief Process incoming IGMP message
48  * @param[in] context Pointer to the IGMP snooping switch context
49  * @param[in] pseudoHeader IPv4 pseudo header
50  * @param[in] message Pointer to the incoming IGMP message
51  * @param[in] length Length of the IGMP message, in bytes
52  * @param[in] ancillary Additional options passed to the stack along with
53  * the packet
54  **/
55 
57  const Ipv4PseudoHeader *pseudoHeader, const IgmpMessage *message,
58  size_t length, const NetRxAncillary *ancillary)
59 {
60  //Check the ingress port the IGMP message was received on
61  if(ancillary->port == 0)
62  {
63  return;
64  }
65  else if(ancillary->port == SWITCH_CPU_PORT)
66  {
67  }
68  else if(ancillary->port > context->numPorts)
69  {
70  return;
71  }
72 
73  //Check IGMP message type
75  {
76  //Process Membership Query message
77  igmpSnoopingProcessMembershipQuery(context, pseudoHeader, message,
78  length, ancillary);
79  }
80  else if(message->type == IGMP_TYPE_MEMBERSHIP_REPORT_V1 ||
82  {
83  //Process Membership Report message
84  igmpSnoopingProcessMembershipReport(context, pseudoHeader, message,
85  length, ancillary);
86  }
87  else if(message->type == IGMP_TYPE_LEAVE_GROUP)
88  {
89  //Process Leave Group message
90  igmpSnoopingProcessLeaveGroup(context, pseudoHeader, message,
91  length, ancillary);
92  }
93  else
94  {
95  //Process unrecognized IGMP messages
96  igmpSnoopingProcessUnknownMessage(context, pseudoHeader, message,
97  length, ancillary);
98  }
99 }
100 
101 
102 /**
103  * @brief Process incoming Membership Query message
104  * @param[in] context Pointer to the IGMP snooping switch context
105  * @param[in] pseudoHeader IPv4 pseudo header
106  * @param[in] message Pointer to the incoming IGMP message
107  * @param[in] length Length of the IGMP message, in bytes
108  * @param[in] ancillary Additional options passed to the stack along with
109  * the packet
110  **/
111 
113  const Ipv4PseudoHeader *pseudoHeader, const IgmpMessage *message,
114  size_t length, const NetRxAncillary *ancillary)
115 {
116  uint_t i;
117  uint32_t portMap;
120  IgmpSnoopingGroup *group;
121 
122  //The group address in the IGMP header must either be zero or a valid
123  //multicast group address (refer to RFC 2236, section 6)
124  if(message->groupAddr != IPV4_UNSPECIFIED_ADDR &&
125  !ipv4IsMulticastAddr(message->groupAddr))
126  {
127  return;
128  }
129 
130  //Point to snooping switch port
131  port = &context->ports[ancillary->port - 1];
132 
133  //IGMPv1 or IGMPv2 Membership Query message?
134  if(message->maxRespTime == 0)
135  {
136  //The maximum response time is 10 seconds by default
138  }
139  else
140  {
141  //The Max Resp Time field specifies the maximum time allowed before
142  //sending a responding report
143  maxRespTime = message->maxRespTime * 100;
144  }
145 
146  //A switch supporting IGMP snooping must maintain a list of multicast
147  //routers and the ports on which they are attached. This list can be
148  //constructed by checking the arrival port for IGMP Queries (sent by
149  //multicast routers) where the source address is not 0.0.0.0
150  if(pseudoHeader->srcAddr != IPV4_UNSPECIFIED_ADDR)
151  {
152  //Check whether a new router has been detected
153  if(!port->routerPresent)
154  {
155  //Update the list of router ports
156  port->routerPresent = TRUE;
157 
158  //The snooping switch must update its forwarding table when the list of
159  //router ports has changed
160  for(i = 0; i < context->numGroups; i++)
161  {
162  //Point to the current group
163  group = &context->groups[i];
164 
165  //Check whether there are hosts on the network which have sent reports
166  //for this multicast group
168  {
169  //Update the corresponding entry in forwarding table
170  igmpSnoopingUpdateStaticFdbEntry(context, group->addr);
171  }
172  }
173 
174  //Check whether unregistered packets should be forwarded to router
175  //ports only
176  if(!context->floodUnknownMulticastPackets)
177  {
178  //Retrieve the port map identifying router ports
179  portMap = igmpSnoopingGetRouterPorts(context);
180 
181  //Forward unknown multicast packets on all ports to which
182  //an IGMP router is attached
183  igmpSnoopingSetUnknownMcastFwdPorts(context, TRUE, portMap);
184  }
185  }
186 
187  //Start timer
189  }
190 
191  //Group-Specific Query received?
192  if(ipv4IsMulticastAddr(message->groupAddr))
193  {
194  //Group-Specific Queries are used to learn if a particular group has any
195  //members on an attached network
196  for(i = 0; i < context->numGroups; i++)
197  {
198  //Point to the current group
199  group = &context->groups[i];
200 
201  //"Members Present" state?
203  group->addr == message->groupAddr)
204  {
205  //Set the timer to [Max Response Time] * [Last Member Query Count]
206  netStartTimer(&group->timer, maxRespTime * 100 *
208 
209  //Switch to the "Checking Membership" state
211  }
212  }
213  }
214 
215  //Flood all ports except the port the message was received on
216  portMap = ((1 << context->numPorts) - 1) & ~(1 << (ancillary->port - 1));
217 
218  //Forward the IGMP message
219  if(portMap != 0)
220  {
221  igmpSnoopingForwardMessage(context, portMap, &ancillary->destMacAddr,
222  pseudoHeader, message, length);
223  }
224 }
225 
226 
227 /**
228  * @brief Process incoming Membership Report message
229  * @param[in] context Pointer to the IGMP snooping switch context
230  * @param[in] pseudoHeader IPv4 pseudo header
231  * @param[in] message Pointer to the incoming IGMP message
232  * @param[in] length Length of the IGMP message, in bytes
233  * @param[in] ancillary Additional options passed to the stack along with
234  * the packet
235  **/
236 
238  const Ipv4PseudoHeader *pseudoHeader, const IgmpMessage *message,
239  size_t length, const NetRxAncillary *ancillary)
240 {
241  uint32_t portMap;
242  IgmpSnoopingGroup *group;
243 
244  //The group address in the IGMP header must be a valid multicast group
245  //address
246  if(!ipv4IsMulticastAddr(message->groupAddr))
247  return;
248 
249  //In a Membership Report, the group address field holds the IP multicast
250  //group address of the group being reported (refer to RFC 2236, section 2.4)
251  group = igmpSnoopingFindGroup(context, message->groupAddr, ancillary->port);
252 
253  //First report received for this multicast group?
254  if(group == NULL)
255  {
256  //Create a new multicast group
257  group = igmpSnoopingCreateGroup(context, message->groupAddr, ancillary->port);
258  }
259 
260  //Valid multicast group?
261  if(group != NULL)
262  {
263  //Start timer
265  //Switch to the "Members Present" state
267  }
268 
269  //A snooping switch should forward IGMP Membership Reports only to ports
270  //where multicast routers are attached (refer to RFC 4541, section 2.1.1)
271  portMap = igmpSnoopingGetRouterPorts(context);
272 
273  //An administrative control may be provided to override this restriction,
274  //allowing the report messages to be flooded to other ports
275  if(context->floodReports)
276  {
277  portMap = ((1 << context->numPorts) - 1);
278  }
279 
280  //Prevent the message from being forwarded to the port on which it arrived
281  portMap &= ~(1 << (ancillary->port - 1));
282 
283  //Forward the IGMP message
284  if(portMap != 0)
285  {
286  igmpSnoopingForwardMessage(context, portMap, &ancillary->destMacAddr,
287  pseudoHeader, message, length);
288  }
289 }
290 
291 
292 /**
293  * @brief Process incoming Leave Group message
294  * @param[in] context Pointer to the IGMP snooping switch context
295  * @param[in] pseudoHeader IPv4 pseudo header
296  * @param[in] message Pointer to the incoming IGMP message
297  * @param[in] length Length of the IGMP message, in bytes
298  * @param[in] ancillary Additional options passed to the stack along with
299  * the packet
300  **/
301 
303  const Ipv4PseudoHeader *pseudoHeader, const IgmpMessage *message,
304  size_t length, const NetRxAncillary *ancillary)
305 {
306  uint32_t portMap;
307  IgmpSnoopingGroup *group;
308 
309  //The group address in the IGMP header must be a valid multicast group
310  //address
311  if(!ipv4IsMulticastAddr(message->groupAddr))
312  return;
313 
314  //In a Leave Group message, the group address field holds the IP multicast
315  //group address of the group being left (refer to RFC 2236, section 2.4)
316  group = igmpSnoopingFindGroup(context, message->groupAddr, ancillary->port);
317 
318  //Valid multicast group?
319  if(group != NULL)
320  {
321  //Ignore Leave Group messages for which there are no group members
323  {
324  //The Last Member Query Time represents the "leave latency", or the
325  //difference between the transmission of a membership change and the
326  //change in the information given to the routing protocol
327  netStartTimer(&group->timer, context->lastMemberQueryTime);
328 
329  //Switch to the "Checking Membership" state
331  }
332  }
333 
334  //Flood all ports except the port the message was received on
335  portMap = ((1 << context->numPorts) - 1) & ~(1 << (ancillary->port - 1));
336 
337  //Forward the IGMP message
338  if(portMap != 0)
339  {
340  igmpSnoopingForwardMessage(context, portMap, &ancillary->destMacAddr,
341  pseudoHeader, message, length);
342  }
343 }
344 
345 
346 /**
347  * @brief Process unrecognized IGMP messages
348  * @param[in] context Pointer to the IGMP snooping switch context
349  * @param[in] pseudoHeader IPv4 pseudo header
350  * @param[in] message Pointer to the incoming IGMP message
351  * @param[in] length Length of the IGMP message, in bytes
352  * @param[in] ancillary Additional options passed to the stack along with
353  * the packet
354  **/
355 
357  const Ipv4PseudoHeader *pseudoHeader, const IgmpMessage *message,
358  size_t length, const NetRxAncillary *ancillary)
359 {
360  uint32_t portMap;
361 
362  //A switch that supports IGMP snooping must flood all unrecognized IGMP
363  //messages to all other ports and must not attempt to make use of any
364  //information beyond the end of the network layer header
365  portMap = ((1 << context->numPorts) - 1) & ~(1 << (ancillary->port - 1));
366 
367  //Forward the IGMP message
368  if(portMap != 0)
369  {
370  igmpSnoopingForwardMessage(context, portMap, &ancillary->destMacAddr,
371  pseudoHeader, message, length);
372  }
373 }
374 
375 
376 /**
377  * @brief Forward an IGMP message to the desired ports
378  * @param[in] context Pointer to the IGMP snooping switch context
379  * @param[in] forwardPorts Port map
380  * @param[in] destMacAddr Destination MAC address
381  * @param[in] pseudoHeader IPv4 pseudo header
382  * @param[in] message Pointer to the IGMP message
383  * @param[in] length Length of the IGMP message, in bytes
384  **/
385 
387  uint32_t forwardPorts, const MacAddr *destMacAddr,
388  const Ipv4PseudoHeader *pseudoHeader, const IgmpMessage *message,
389  size_t length)
390 {
391  error_t error;
392  size_t offset;
393  NetBuffer *buffer;
394  NetTxAncillary ancillary;
395 
396  //Debug message
397  TRACE_INFO("Forwarding IGMP message (%" PRIuSIZE " bytes)...\r\n", length);
398  //Dump port map
399  TRACE_INFO(" Switch Port Map = 0x%02" PRIX8 "\r\n", forwardPorts);
400 
401  //Allocate a memory buffer to hold an IGMP message
402  buffer = ipAllocBuffer(0, &offset);
403 
404  //Successful memory allocation?
405  if(buffer != NULL)
406  {
407  //Copy the IGMP message
408  error = netBufferAppend(buffer, message, length);
409 
410  //Check status code
411  if(!error)
412  {
413  //Additional options can be passed to the stack along with the packet
414  ancillary = NET_DEFAULT_TX_ANCILLARY;
415 
416  //All IGMP messages are sent with an IP TTL of 1 and contain an IP
417  //Router Alert option in their IP header (refer to RFC 2236, section 2)
418  ancillary.ttl = IGMP_TTL;
419  ancillary.routerAlert = TRUE;
420 
421  //Specify egress ports
422  ancillary.ports = forwardPorts;
423 
424  //Override port state if necessary
425  if(!context->floodUnknownMulticastPackets)
426  {
427  ancillary.override = TRUE;
428  }
429 
430  //Forward the IGMP message
431  error = ipv4SendDatagram(context->interface, pseudoHeader, buffer,
432  offset, &ancillary);
433  }
434 
435  //Free previously allocated memory
436  netBufferFree(buffer);
437  }
438  else
439  {
440  //Failed to allocate memory
441  error = ERROR_OUT_OF_MEMORY;
442  }
443 
444  //Return status code
445  return error;
446 }
447 
448 
449 /**
450  * @brief Create a new multicast group
451  * @param[in] context Pointer to the IGMP snooping switch context
452  * @param[in] groupAddr Multicast group address
453  * @param[in] port Port number associated with the multicast group
454  * @return Pointer to the newly created multicast group
455  **/
456 
458  Ipv4Addr groupAddr, uint8_t port)
459 {
460  uint_t i;
461  IgmpSnoopingGroup *group;
462 
463  //Initialize pointer
464  group = NULL;
465 
466  //Loop through multicast groups
467  for(i = 0; i < context->numGroups; i++)
468  {
469  //Check whether the entry is available
471  {
472  //Point to the current group
473  group = &context->groups[i];
474 
475  //Switch to the "Members Present" state
477  //Save the multicast group address
478  group->addr = groupAddr;
479  //Save port number
480  group->port = port;
481 
482  //Update the corresponding entry in forwarding table
484 
485  //We are done
486  break;
487  }
488  }
489 
490  //Return a pointer to the newly created multicast group
491  return group;
492 }
493 
494 
495 /**
496  * @brief Search the list of multicast groups for a given group address
497  * @param[in] context Pointer to the IGMP snooping switch context
498  * @param[in] groupAddr Multicast group address
499  * @param[in] port Port number
500  * @return Pointer to the matching multicast group, if any
501  **/
502 
504  Ipv4Addr groupAddr, uint8_t port)
505 {
506  uint_t i;
507  IgmpSnoopingGroup *group;
508 
509  //Initialize pointer
510  group = NULL;
511 
512  //Loop through multicast groups
513  for(i = 0; i < context->numGroups; i++)
514  {
515  //Check whether there are hosts on this port which have sent reports for
516  //this multicast group
518  context->groups[i].addr == groupAddr &&
519  context->groups[i].port == port)
520  {
521  //Point to the current group
522  group = &context->groups[i];
523  break;
524  }
525  }
526 
527  //Return a pointer to the matching multicast group
528  return group;
529 }
530 
531 
532 /**
533  * @brief Delete a multicast group
534  * @param[in] context Pointer to the IGMP snooping switch context
535  * @param[in] group Multicast group
536  **/
537 
539  IgmpSnoopingGroup *group)
540 {
541  //Switch to the "No Members Present" state
543 
544  //Update the corresponding entry in forwarding table
545  igmpSnoopingUpdateStaticFdbEntry(context, group->addr);
546 }
547 
548 
549 /**
550  * @brief Enable IGMP monitoring
551  * @param[in] context Pointer to the IGMP snooping switch context
552  * @param[in] enable Enable or disable MLD monitoring
553  **/
554 
556 {
557  NetInterface *interface;
558 
559  //Point to the underlying network interface
560  interface = context->interface;
561 
562  //Valid switch driver?
563  if(interface->switchDriver != NULL &&
564  interface->switchDriver->enableIgmpSnooping != NULL)
565  {
566  //Enable IGMP snooping
567  interface->switchDriver->enableIgmpSnooping(interface, enable);
568  }
569 }
570 
571 
572 /**
573  * @brief Update a entry of the static MAC table
574  * @param[in] context Pointer to the IGMP snooping switch context
575  * @param[in] groupAddr Multicast group address to be updated
576  **/
577 
580 {
581  uint_t i;
582  uint32_t forwardPorts;
583  SwitchFdbEntry entry;
584  NetInterface *interface;
585  IgmpSnoopingGroup *group;
586 
587  //Clear port map
588  forwardPorts = 0;
589 
590  //Point to the underlying network interface
591  interface = context->interface;
592 
593  //Packets should be forwarded according to group-based port membership
594  //tables (refer to RFC 4541, section 2.1.2)
595  for(i = 0; i < context->numGroups; i++)
596  {
597  //Point to the current group
598  group = &context->groups[i];
599 
600  //Check whether there are hosts on this port which have sent reports for
601  //this multicast group
603  group->addr == groupAddr)
604  {
605  //Valid port number?
606  if(group->port > 0 && group->port <= context->numPorts)
607  {
608  forwardPorts |= (1 << (group->port - 1));
609  }
610  else
611  {
612  forwardPorts |= SWITCH_CPU_PORT_MASK;
613  }
614  }
615  }
616 
617  //Check whether this multicast group has any members
618  if(forwardPorts != 0)
619  {
620  //Packets must also be forwarded on router ports
621  forwardPorts |= igmpSnoopingGetRouterPorts(context);
622 
623  //Valid switch driver?
624  if(interface->switchDriver != NULL &&
625  interface->switchDriver->addStaticFdbEntry != NULL)
626  {
627  //Format forwarding database entry
629  entry.srcPort = 0;
630  entry.destPorts = forwardPorts;
631  entry.override = FALSE;
632 
633  //Debug message
634  TRACE_DEBUG("IGMP Snooping: Adding FDB entry...\r\n");
635  TRACE_DEBUG(" MAC Address: %s\r\n", macAddrToString(&entry.macAddr, NULL));
636  TRACE_DEBUG(" Forward Ports: 0x%08X\r\n", entry.destPorts);
637 
638  //Update the static MAC table of the switch
639  interface->switchDriver->addStaticFdbEntry(context->interface, &entry);
640  }
641  }
642  else
643  {
644  //Valid switch driver?
645  if(interface->switchDriver != NULL &&
646  interface->switchDriver->deleteStaticFdbEntry != NULL)
647  {
648  //Format forwarding database entry
650  entry.srcPort = 0;
651  entry.destPorts = 0;
652  entry.override = FALSE;
653 
654  //Debug message
655  TRACE_DEBUG("IGMP Snooping: Deleting FDB entry...\r\n");
656  TRACE_DEBUG(" MAC Address: %s\r\n", macAddrToString(&entry.macAddr, NULL));
657 
658  //Update the static MAC table of the switch
659  interface->switchDriver->deleteStaticFdbEntry(context->interface,
660  &entry);
661  }
662  }
663 }
664 
665 
666 /**
667  * @brief Set forward ports for unknown multicast packets
668  * @param[in] context Pointer to the IGMP snooping switch context
669  * @param[in] enable Enable or disable forwarding of unknown multicast packets
670  * @param[in] forwardPorts Port map
671  **/
672 
674  bool_t enable, uint32_t forwardPorts)
675 {
676  NetInterface *interface;
677 
678  //Point to the underlying network interface
679  interface = context->interface;
680 
681  //Valid switch driver?
682  if(interface->switchDriver != NULL &&
683  interface->switchDriver->setUnknownMcastFwdPorts != NULL)
684  {
685  interface->switchDriver->setUnknownMcastFwdPorts(context->interface,
686  enable, forwardPorts);
687  }
688 }
689 
690 
691 /*
692  * @brief Retrieve the port map identifying router ports
693  * @param[in] context Pointer to the IGMP snooping switch context
694  * @return Port map identifying router ports
695  **/
696 
698 {
699  uint_t i;
700  uint32_t routerPorts;
701 
702  //Clear port map
703  routerPorts = 0;
704 
705  //Loop through the list of multicast routers
706  for(i = 0; i < context->numPorts; i++)
707  {
708  //Check whether any IGMP router is attached to this port
709  if(context->ports[i].routerPresent)
710  {
711  routerPorts |= (1 << i);
712  }
713  }
714 
715  //Return the port map that identifies router ports
716  return routerPorts;
717 }
718 
719 #endif
uint8_t message[]
Definition: chap.h:154
unsigned int uint_t
Definition: compiler_port.h:50
#define PRIuSIZE
int bool_t
Definition: compiler_port.h:53
Debugging facilities.
#define TRACE_DEBUG(...)
Definition: debug.h:107
#define TRACE_INFO(...)
Definition: debug.h:95
uint16_t port
Definition: dns_common.h:267
error_t
Error codes.
Definition: error.h:43
@ ERROR_OUT_OF_MEMORY
Definition: error.h:63
char_t * macAddrToString(const MacAddr *macAddr, char_t *str)
Convert a MAC address to a dash delimited string.
Definition: ethernet.c:917
MacAddr
Definition: ethernet.h:195
#define IGMP_LAST_MEMBER_QUERY_COUNT
Definition: igmp_common.h:96
IgmpMessage
Definition: igmp_common.h:172
#define IGMP_TTL
Definition: igmp_common.h:127
#define IGMP_V1_MAX_RESPONSE_TIME
Definition: igmp_common.h:121
@ IGMP_TYPE_LEAVE_GROUP
Definition: igmp_common.h:149
@ IGMP_TYPE_MEMBERSHIP_REPORT_V2
Definition: igmp_common.h:148
@ IGMP_TYPE_MEMBERSHIP_REPORT_V1
Definition: igmp_common.h:147
@ IGMP_TYPE_MEMBERSHIP_QUERY
Definition: igmp_common.h:146
Ipv4Addr groupAddr
Definition: igmp_common.h:171
uint8_t maxRespTime
Definition: igmp_common.h:169
#define IGMP_GROUP_MEMBERSHIP_INTERVAL
Definition: igmp_common.h:66
#define IGMP_OTHER_QUERIER_PRESENT_INTERVAL
Definition: igmp_common.h:70
IGMP snooping switch.
@ IGMP_SNOOPING_GROUP_STATE_MEMBERS_PRESENT
Definition: igmp_snooping.h:58
@ IGMP_SNOOPING_GROUP_STATE_NO_MEMBERS_PRESENT
Definition: igmp_snooping.h:57
@ IGMP_SNOOPING_GROUP_STATE_CHECKING_MEMBERSHIP
Definition: igmp_snooping.h:59
void igmpSnoopingProcessMembershipReport(IgmpSnoopingContext *context, const Ipv4PseudoHeader *pseudoHeader, const IgmpMessage *message, size_t length, const NetRxAncillary *ancillary)
Process incoming Membership Report message.
void igmpSnoopingUpdateStaticFdbEntry(IgmpSnoopingContext *context, Ipv4Addr groupAddr)
Update a entry of the static MAC table.
uint32_t igmpSnoopingGetRouterPorts(IgmpSnoopingContext *context)
void igmpSnoopingProcessUnknownMessage(IgmpSnoopingContext *context, const Ipv4PseudoHeader *pseudoHeader, const IgmpMessage *message, size_t length, const NetRxAncillary *ancillary)
Process unrecognized IGMP messages.
void igmpSnoopingSetUnknownMcastFwdPorts(IgmpSnoopingContext *context, bool_t enable, uint32_t forwardPorts)
Set forward ports for unknown multicast packets.
void igmpSnoopingDeleteGroup(IgmpSnoopingContext *context, IgmpSnoopingGroup *group)
Delete a multicast group.
IgmpSnoopingGroup * igmpSnoopingFindGroup(IgmpSnoopingContext *context, Ipv4Addr groupAddr, uint8_t port)
Search the list of multicast groups for a given group address.
void igmpSnoopingEnableMonitoring(IgmpSnoopingContext *context, bool_t enable)
Enable IGMP monitoring.
void igmpSnoopingProcessLeaveGroup(IgmpSnoopingContext *context, const Ipv4PseudoHeader *pseudoHeader, const IgmpMessage *message, size_t length, const NetRxAncillary *ancillary)
Process incoming Leave Group message.
IgmpSnoopingGroup * igmpSnoopingCreateGroup(IgmpSnoopingContext *context, Ipv4Addr groupAddr, uint8_t port)
Create a new multicast group.
void igmpSnoopingProcessMessage(IgmpSnoopingContext *context, const Ipv4PseudoHeader *pseudoHeader, const IgmpMessage *message, size_t length, const NetRxAncillary *ancillary)
Process incoming IGMP message.
void igmpSnoopingProcessMembershipQuery(IgmpSnoopingContext *context, const Ipv4PseudoHeader *pseudoHeader, const IgmpMessage *message, size_t length, const NetRxAncillary *ancillary)
Process incoming Membership Query message.
error_t igmpSnoopingForwardMessage(IgmpSnoopingContext *context, uint32_t forwardPorts, const MacAddr *destMacAddr, const Ipv4PseudoHeader *pseudoHeader, const IgmpMessage *message, size_t length)
Forward an IGMP message to the desired ports.
Helper functions for IGMP snooping switch.
NetBuffer * ipAllocBuffer(size_t length, size_t *offset)
Allocate a buffer to hold an IP packet.
Definition: ip.c:744
error_t ipv4SendDatagram(NetInterface *interface, const Ipv4PseudoHeader *pseudoHeader, NetBuffer *buffer, size_t offset, NetTxAncillary *ancillary)
Send an IPv4 datagram.
Definition: ipv4.c:1004
IPv4 (Internet Protocol Version 4)
#define Ipv4PseudoHeader
Definition: ipv4.h:39
uint32_t Ipv4Addr
IPv4 network address.
Definition: ipv4.h:267
#define IPV4_UNSPECIFIED_ADDR
Definition: ipv4.h:110
#define ipv4IsMulticastAddr(ipAddr)
Definition: ipv4.h:168
error_t ipv4MapMulticastAddrToMac(Ipv4Addr ipAddr, MacAddr *macAddr)
Map an host group address to a MAC-layer multicast address.
Definition: ipv4_misc.c:770
Helper functions for IPv4.
TCP/IP stack core.
#define NetInterface
Definition: net.h:36
void netBufferFree(NetBuffer *buffer)
Dispose a multi-part buffer.
Definition: net_mem.c:282
error_t netBufferAppend(NetBuffer *dest, const void *src, size_t length)
Append data a multi-part buffer.
Definition: net_mem.c:588
void netStartTimer(NetTimer *timer, systime_t interval)
Start timer.
Definition: net_misc.c:763
const NetTxAncillary NET_DEFAULT_TX_ANCILLARY
Definition: net_misc.c:71
#define NetRxAncillary
Definition: net_misc.h:40
#define NetTxAncillary
Definition: net_misc.h:36
#define SWITCH_CPU_PORT
Definition: nic.h:59
#define SWITCH_CPU_PORT_MASK
Definition: nic.h:60
#define TRUE
Definition: os_port.h:50
#define FALSE
Definition: os_port.h:46
uint32_t systime_t
System time.
IGMP snooping switch context.
IgmpSnoopingGroup * groups
Multicast groups.
systime_t lastMemberQueryTime
Leave latency.
uint_t numPorts
Number of ports.
bool_t floodReports
Flood IGMP report messages to all ports (not only to router ports)
IgmpSnoopingPort * ports
Ports.
uint_t numGroups
Maximum number of multicast groups.
bool_t floodUnknownMulticastPackets
Flood unregistered multicast traffic to all ports.
NetInterface * interface
The primary interface on an attached network.
Multicast group.
Definition: igmp_snooping.h:79
Ipv4Addr addr
Multicast group address.
Definition: igmp_snooping.h:81
IgmpSnoopingGroupState state
Multicast group state.
Definition: igmp_snooping.h:80
Snooping switch port.
Definition: igmp_snooping.h:68
Structure describing a buffer that spans multiple chunks.
Definition: net_mem.h:89
Forwarding database entry.
Definition: nic.h:149
MacAddr macAddr
Definition: nic.h:150
uint32_t destPorts
Definition: nic.h:152
bool_t override
Definition: nic.h:153
uint8_t srcPort
Definition: nic.h:151
uint8_t length
Definition: tcp.h:368