igmp_host.c
Go to the documentation of this file.
1 /**
2  * @file igmp_host.c
3  * @brief IGMP host
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  * @section Description
28  *
29  * IGMP is used by IP hosts to report their multicast group memberships
30  * to routers. Refer to the following RFCs for complete details:
31  * - RFC 1112: Host Extensions for IP Multicasting
32  * - RFC 2236: Internet Group Management Protocol, Version 2
33  * - RFC 3376: Internet Group Management Protocol, Version 3
34  *
35  * @author Oryx Embedded SARL (www.oryx-embedded.com)
36  * @version 2.4.0
37  **/
38 
39 //Switch to the appropriate trace level
40 #define TRACE_LEVEL IGMP_TRACE_LEVEL
41 
42 //Dependencies
43 #include "core/net.h"
44 #include "ipv4/ipv4.h"
45 #include "igmp/igmp_host.h"
46 #include "igmp/igmp_host_misc.h"
47 #include "debug.h"
48 
49 //Check TCP/IP stack configuration
50 #if (IPV4_SUPPORT == ENABLED && IGMP_HOST_SUPPORT == ENABLED)
51 
52 
53 /**
54  * @brief IGMP host initialization
55  * @param[in] interface Underlying network interface
56  * @return Error code
57  **/
58 
60 {
61  IgmpHostContext *context;
62 
63  //Point to the IGMP host context
64  context = &interface->igmpHostContext;
65 
66  //Clear the IGMP host context
67  osMemset(context, 0, sizeof(IgmpHostContext));
68 
69  //The default host compatibility mode is IGMPv2
70  context->igmpv1RouterPresent = FALSE;
71 
72  //Start IGMPv1 router present timer
74 
75  //Successful initialization
76  return NO_ERROR;
77 }
78 
79 
80 /**
81  * @brief Join the specified host group
82  * @param[in] interface Underlying network interface
83  * @param[in] entry IPv4 filter entry identifying the host group to join
84  * @return Error code
85  **/
86 
88 {
89  //The all-systems group (address 224.0.0.1) is handled as a special
90  //case. The host starts in Idle Member state for that group on every
91  //interface and never transitions to another state
92  if(entry->addr == IGMP_ALL_SYSTEMS_ADDR)
93  {
94  //Clear flag
95  entry->flag = FALSE;
96  //Enter the Idle Member state
98  }
99  else
100  {
101  //Link is up?
102  if(interface->linkState)
103  {
104  //When a host joins a multicast group, it should immediately transmit
105  //an unsolicited Membership Report for that group
106  igmpHostSendMembershipReport(interface, entry->addr);
107 
108  //Set flag
109  entry->flag = TRUE;
110  //Start timer
112  //Enter the Delaying Member state
114  }
115  //Link is down?
116  else
117  {
118  //Clear flag
119  entry->flag = FALSE;
120  //Enter the Idle Member state
122  }
123  }
124 
125  //Successful processing
126  return NO_ERROR;
127 }
128 
129 
130 /**
131  * @brief Leave the specified host group
132  * @param[in] interface Underlying network interface
133  * @param[in] entry IPv4 filter entry identifying the host group to leave
134  * @return Error code
135  **/
136 
138 {
139  //Check link state
140  if(interface->linkState)
141  {
142  //Send a Leave Group message if the flag is set
143  if(entry->flag)
144  {
145  igmpHostSendLeaveGroup(interface, entry->addr);
146  }
147  }
148 
149  //Switch to the "Non-Member" state
151 
152  //Successful processing
153  return NO_ERROR;
154 }
155 
156 
157 /**
158  * @brief IGMP timer handler
159  *
160  * This routine must be periodically called by the TCP/IP stack to
161  * handle IGMP related timers
162  *
163  * @param[in] interface Underlying network interface
164  **/
165 
166 void igmpHostTick(NetInterface *interface)
167 {
168  uint_t i;
169  systime_t time;
170  Ipv4FilterEntry *entry;
171  IgmpHostContext *context;
172 
173  //Point to the IGMP host context
174  context = &interface->igmpHostContext;
175 
176  //Get current time
177  time = osGetSystemTime();
178 
179  //Check IGMP host state
180  if(context->igmpv1RouterPresent)
181  {
182  //Check IGMPv1 router present timer
183  if(netTimerExpired(&context->timer))
184  {
185  context->igmpv1RouterPresent = FALSE;
186  }
187  }
188 
189  //Go through the multicast filter table
190  for(i = 0; i < IPV4_MULTICAST_FILTER_SIZE; i++)
191  {
192  //Point to the current entry
193  entry = &interface->ipv4Context.multicastFilter[i];
194 
195  //Valid entry?
196  if(entry->refCount > 0)
197  {
198  //Delaying Member state?
200  {
201  //Timer expired?
202  if(timeCompare(time, entry->timer) >= 0)
203  {
204  //Send a Membership Report message for the group on the interface
205  igmpHostSendMembershipReport(interface, entry->addr);
206 
207  //Set flag
208  entry->flag = TRUE;
209  //Switch to the "Idle Member" state
211  }
212  }
213  }
214  }
215 }
216 
217 
218 /**
219  * @brief Callback function for link change event
220  * @param[in] interface Underlying network interface
221  **/
222 
224 {
225  uint_t i;
226  systime_t time;
227  Ipv4FilterEntry *entry;
228  IgmpHostContext *context;
229 
230  //Point to the IGMP host context
231  context = &interface->igmpHostContext;
232 
233  //Get current time
234  time = osGetSystemTime();
235 
236  //Link up event?
237  if(interface->linkState)
238  {
239  //The default host compatibility mode is IGMPv2
240  context->igmpv1RouterPresent = FALSE;
241  //Start IGMPv1 router present timer
243 
244  //Go through the multicast filter table
245  for(i = 0; i < IPV4_MULTICAST_FILTER_SIZE; i++)
246  {
247  //Point to the current entry
248  entry = &interface->ipv4Context.multicastFilter[i];
249 
250  //Valid entry?
251  if(entry->refCount > 0)
252  {
253  //The all-systems group (address 224.0.0.1) is handled as a special
254  //case. The host starts in Idle Member state for that group on every
255  //interface and never transitions to another state
256  if(entry->addr != IGMP_ALL_SYSTEMS_ADDR)
257  {
258  //Send an unsolicited Membership Report for that group
259  igmpHostSendMembershipReport(interface, entry->addr);
260 
261  //Set flag
262  entry->flag = TRUE;
263  //Start timer
265  //Enter the Delaying Member state
267  }
268  }
269  }
270  }
271  //Link down event?
272  else
273  {
274  //Go through the multicast filter table
275  for(i = 0; i < IPV4_MULTICAST_FILTER_SIZE; i++)
276  {
277  //Point to the current entry
278  entry = &interface->ipv4Context.multicastFilter[i];
279 
280  //Valid entry?
281  if(entry->refCount > 0)
282  {
283  //Clear flag
284  entry->flag = FALSE;
285  //Enter the Idle Member state
287  }
288  }
289  }
290 }
291 
292 #endif
unsigned int uint_t
Definition: compiler_port.h:50
Debugging facilities.
uint32_t time
error_t
Error codes.
Definition: error.h:43
@ NO_ERROR
Success.
Definition: error.h:44
#define IGMP_UNSOLICITED_REPORT_INTERVAL
Definition: igmp_common.h:107
#define IGMP_V1_ROUTER_PRESENT_TIMEOUT
Definition: igmp_common.h:114
#define IGMP_ALL_SYSTEMS_ADDR
Definition: igmp_common.h:130
error_t igmpHostJoinGroup(NetInterface *interface, Ipv4FilterEntry *entry)
Join the specified host group.
Definition: igmp_host.c:87
error_t igmpHostInit(NetInterface *interface)
IGMP host initialization.
Definition: igmp_host.c:59
void igmpHostLinkChangeEvent(NetInterface *interface)
Callback function for link change event.
Definition: igmp_host.c:223
void igmpHostTick(NetInterface *interface)
IGMP timer handler.
Definition: igmp_host.c:166
error_t igmpHostLeaveGroup(NetInterface *interface, Ipv4FilterEntry *entry)
Leave the specified host group.
Definition: igmp_host.c:137
IGMP host.
@ IGMP_HOST_GROUP_STATE_NON_MEMBER
Definition: igmp_host.h:57
@ IGMP_HOST_GROUP_STATE_IDLE_MEMBER
Definition: igmp_host.h:59
@ IGMP_HOST_GROUP_STATE_DELAYING_MEMBER
Definition: igmp_host.h:58
error_t igmpHostSendMembershipReport(NetInterface *interface, Ipv4Addr ipAddr)
Send Membership Report message.
error_t igmpHostSendLeaveGroup(NetInterface *interface, Ipv4Addr ipAddr)
Send Leave Group message.
Helper functions for IGMP host.
IPv4 (Internet Protocol Version 4)
#define IPV4_MULTICAST_FILTER_SIZE
Definition: ipv4.h:83
TCP/IP stack core.
#define NetInterface
Definition: net.h:36
void netStartTimer(NetTimer *timer, systime_t interval)
Start timer.
Definition: net_misc.c:763
bool_t netTimerExpired(NetTimer *timer)
Check whether the timer has expired.
Definition: net_misc.c:803
#define osMemset(p, value, length)
Definition: os_port.h:135
#define timeCompare(t1, t2)
Definition: os_port.h:40
#define TRUE
Definition: os_port.h:50
#define FALSE
Definition: os_port.h:46
systime_t osGetSystemTime(void)
Retrieve system time.
uint32_t systime_t
System time.
IGMP host context.
Definition: igmp_host.h:68
bool_t igmpv1RouterPresent
An IGMPv1 query has been recently heard.
Definition: igmp_host.h:69
NetTimer timer
IGMPv1 router present timer.
Definition: igmp_host.h:70
IPv4 multicast filter entry.
Definition: ipv4.h:357
uint_t state
IGMP host state.
Definition: ipv4.h:360
bool_t flag
IGMP flag.
Definition: ipv4.h:361
systime_t timer
Delay timer.
Definition: ipv4.h:362
Ipv4Addr addr
Multicast address.
Definition: ipv4.h:358
uint_t refCount
Reference count for the current entry.
Definition: ipv4.h:359