Skip to content

Commit b71b514

Browse files
cperera-audcarlescufi
authored andcommitted
net: ipv4: Added mechanism to add 224.0.0.1 address to a multicast filter
The purpose of the change was to have the Zephyr network stack internally add the IGMP all systems 224.0.0.1 multicast address to a multicast membership list so that multicast hash filter implementations can add this address to the hash filter. Fixes #53548 Signed-off-by: Chamira Perera <[email protected]>
1 parent 86f4860 commit b71b514

File tree

4 files changed

+81
-2
lines changed

4 files changed

+81
-2
lines changed

subsys/net/ip/Kconfig.ipv4

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ config NET_IF_UNICAST_IPV4_ADDR_COUNT
3434

3535
config NET_IF_MCAST_IPV4_ADDR_COUNT
3636
int "Max number of multicast IPv4 addresses per network interface"
37+
default 2 if NET_IPV4_IGMP
3738
default 1
3839

3940
config NET_ICMPV4_ACCEPT_BROADCAST

subsys/net/ip/igmp.c

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,15 @@ static int send_igmp_report(struct net_if *iface,
127127
}
128128

129129
for (i = 0; i < NET_IF_MAX_IPV4_MADDR; i++) {
130-
if (!ipv4->mcast[i].is_used || !ipv4->mcast[i].is_joined) {
130+
/* We don't need to send an IGMP membership report to the IGMP
131+
* all systems multicast address of 224.0.0.1 so skip over it.
132+
* Since the IGMP all systems multicast address is marked as
133+
* used and joined during init time, we have to check this
134+
* address separately to skip over it.
135+
*/
136+
if (!ipv4->mcast[i].is_used || !ipv4->mcast[i].is_joined ||
137+
net_ipv4_addr_cmp_raw((uint8_t *)&ipv4->mcast[i].address.in_addr,
138+
(uint8_t *)&all_systems)) {
131139
continue;
132140
}
133141

@@ -139,7 +147,15 @@ static int send_igmp_report(struct net_if *iface,
139147
}
140148

141149
for (i = 0; i < NET_IF_MAX_IPV4_MADDR; i++) {
142-
if (!ipv4->mcast[i].is_used || !ipv4->mcast[i].is_joined) {
150+
/* We don't need to send an IGMP membership report to the IGMP
151+
* all systems multicast address of 224.0.0.1 so skip over it.
152+
* Since the IGMP all systems multicast address is marked as
153+
* used and joined during init time, we have to check this
154+
* address separately to skip over it.
155+
*/
156+
if (!ipv4->mcast[i].is_used || !ipv4->mcast[i].is_joined ||
157+
net_ipv4_addr_cmp_raw((uint8_t *)&ipv4->mcast[i].address.in_addr,
158+
(uint8_t *)&all_systems)) {
143159
continue;
144160
}
145161

@@ -326,3 +342,39 @@ int net_ipv4_igmp_leave(struct net_if *iface, const struct in_addr *addr)
326342
sizeof(struct in_addr));
327343
return ret;
328344
}
345+
346+
void net_ipv4_igmp_init(struct net_if *iface)
347+
{
348+
struct net_if_mcast_addr *maddr;
349+
350+
/* Ensure multicast addresses are available */
351+
if (CONFIG_NET_IF_MCAST_IPV4_ADDR_COUNT < 1) {
352+
return;
353+
}
354+
355+
/* This code adds the IGMP all systems 224.0.0.1 multicast address
356+
* to the list of multicast addresses of the given interface.
357+
* The address is marked as joined. However, an IGMP membership
358+
* report is not generated for this address. Populating this
359+
* address in the list of multicast addresses of the interface
360+
* and marking it as joined is helpful for multicast hash filter
361+
* implementations that need a list of multicast addresses it needs
362+
* to add to the multicast hash filter after a multicast address
363+
* has been removed from the membership list.
364+
*/
365+
maddr = net_if_ipv4_maddr_lookup(&all_systems, &iface);
366+
if (maddr && net_if_ipv4_maddr_is_joined(maddr)) {
367+
return;
368+
}
369+
370+
if (!maddr) {
371+
maddr = net_if_ipv4_maddr_add(iface, &all_systems);
372+
if (!maddr) {
373+
return;
374+
}
375+
}
376+
377+
net_if_ipv4_maddr_join(maddr);
378+
379+
net_if_mcast_monitor(iface, &maddr->address, true);
380+
}

subsys/net/ip/net_if.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4159,6 +4159,21 @@ static void update_operational_state(struct net_if *iface)
41594159
}
41604160
}
41614161

4162+
static void init_igmp(struct net_if *iface)
4163+
{
4164+
#if defined(CONFIG_NET_IPV4_IGMP)
4165+
/* Ensure IPv4 is enabled for this interface */
4166+
if (iface->config.ip.ipv4 == NULL) {
4167+
return;
4168+
}
4169+
4170+
net_ipv4_igmp_init(iface);
4171+
#else
4172+
ARG_UNUSED(iface);
4173+
return;
4174+
#endif
4175+
}
4176+
41624177
int net_if_up(struct net_if *iface)
41634178
{
41644179
int status = 0;
@@ -4187,6 +4202,8 @@ int net_if_up(struct net_if *iface)
41874202
goto out;
41884203
}
41894204

4205+
init_igmp(iface);
4206+
41904207
done:
41914208
net_if_flag_set(iface, NET_IF_UP);
41924209
net_mgmt_event_notify(NET_EVENT_IF_ADMIN_UP, iface);

subsys/net/ip/net_private.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,15 @@ enum net_verdict net_context_packet_received(struct net_conn *conn,
173173
extern uint16_t net_calc_chksum_ipv4(struct net_pkt *pkt);
174174
#endif /* CONFIG_NET_IPV4 */
175175

176+
#if defined(CONFIG_NET_IPV4_IGMP)
177+
/**
178+
* @brief Initialise the IGMP module for a given interface
179+
*
180+
* @param iface Interface to init IGMP
181+
*/
182+
void net_ipv4_igmp_init(struct net_if *iface);
183+
#endif /* CONFIG_NET_IPV4_IGMP */
184+
176185
#if defined(CONFIG_NET_IPV4_IGMP)
177186
uint16_t net_calc_chksum_igmp(uint8_t *data, size_t len);
178187
enum net_verdict net_ipv4_igmp_input(struct net_pkt *pkt,

0 commit comments

Comments
 (0)