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 <chamira.perera@audinate.com>
This commit is contained in:
Chamira Perera 2023-01-12 18:23:38 +11:00 committed by Carles Cufí
parent 86f48609fb
commit b71b514e93
4 changed files with 81 additions and 2 deletions

View File

@ -34,6 +34,7 @@ config NET_IF_UNICAST_IPV4_ADDR_COUNT
config NET_IF_MCAST_IPV4_ADDR_COUNT
int "Max number of multicast IPv4 addresses per network interface"
default 2 if NET_IPV4_IGMP
default 1
config NET_ICMPV4_ACCEPT_BROADCAST

View File

@ -127,7 +127,15 @@ static int send_igmp_report(struct net_if *iface,
}
for (i = 0; i < NET_IF_MAX_IPV4_MADDR; i++) {
if (!ipv4->mcast[i].is_used || !ipv4->mcast[i].is_joined) {
/* We don't need to send an IGMP membership report to the IGMP
* all systems multicast address of 224.0.0.1 so skip over it.
* Since the IGMP all systems multicast address is marked as
* used and joined during init time, we have to check this
* address separately to skip over it.
*/
if (!ipv4->mcast[i].is_used || !ipv4->mcast[i].is_joined ||
net_ipv4_addr_cmp_raw((uint8_t *)&ipv4->mcast[i].address.in_addr,
(uint8_t *)&all_systems)) {
continue;
}
@ -139,7 +147,15 @@ static int send_igmp_report(struct net_if *iface,
}
for (i = 0; i < NET_IF_MAX_IPV4_MADDR; i++) {
if (!ipv4->mcast[i].is_used || !ipv4->mcast[i].is_joined) {
/* We don't need to send an IGMP membership report to the IGMP
* all systems multicast address of 224.0.0.1 so skip over it.
* Since the IGMP all systems multicast address is marked as
* used and joined during init time, we have to check this
* address separately to skip over it.
*/
if (!ipv4->mcast[i].is_used || !ipv4->mcast[i].is_joined ||
net_ipv4_addr_cmp_raw((uint8_t *)&ipv4->mcast[i].address.in_addr,
(uint8_t *)&all_systems)) {
continue;
}
@ -326,3 +342,39 @@ int net_ipv4_igmp_leave(struct net_if *iface, const struct in_addr *addr)
sizeof(struct in_addr));
return ret;
}
void net_ipv4_igmp_init(struct net_if *iface)
{
struct net_if_mcast_addr *maddr;
/* Ensure multicast addresses are available */
if (CONFIG_NET_IF_MCAST_IPV4_ADDR_COUNT < 1) {
return;
}
/* This code adds the IGMP all systems 224.0.0.1 multicast address
* to the list of multicast addresses of the given interface.
* The address is marked as joined. However, an IGMP membership
* report is not generated for this address. Populating this
* address in the list of multicast addresses of the interface
* and marking it as joined is helpful for multicast hash filter
* implementations that need a list of multicast addresses it needs
* to add to the multicast hash filter after a multicast address
* has been removed from the membership list.
*/
maddr = net_if_ipv4_maddr_lookup(&all_systems, &iface);
if (maddr && net_if_ipv4_maddr_is_joined(maddr)) {
return;
}
if (!maddr) {
maddr = net_if_ipv4_maddr_add(iface, &all_systems);
if (!maddr) {
return;
}
}
net_if_ipv4_maddr_join(maddr);
net_if_mcast_monitor(iface, &maddr->address, true);
}

View File

@ -4159,6 +4159,21 @@ exit:
}
}
static void init_igmp(struct net_if *iface)
{
#if defined(CONFIG_NET_IPV4_IGMP)
/* Ensure IPv4 is enabled for this interface */
if (iface->config.ip.ipv4 == NULL) {
return;
}
net_ipv4_igmp_init(iface);
#else
ARG_UNUSED(iface);
return;
#endif
}
int net_if_up(struct net_if *iface)
{
int status = 0;
@ -4187,6 +4202,8 @@ int net_if_up(struct net_if *iface)
goto out;
}
init_igmp(iface);
done:
net_if_flag_set(iface, NET_IF_UP);
net_mgmt_event_notify(NET_EVENT_IF_ADMIN_UP, iface);

View File

@ -173,6 +173,15 @@ enum net_verdict net_context_packet_received(struct net_conn *conn,
extern uint16_t net_calc_chksum_ipv4(struct net_pkt *pkt);
#endif /* CONFIG_NET_IPV4 */
#if defined(CONFIG_NET_IPV4_IGMP)
/**
* @brief Initialise the IGMP module for a given interface
*
* @param iface Interface to init IGMP
*/
void net_ipv4_igmp_init(struct net_if *iface);
#endif /* CONFIG_NET_IPV4_IGMP */
#if defined(CONFIG_NET_IPV4_IGMP)
uint16_t net_calc_chksum_igmp(uint8_t *data, size_t len);
enum net_verdict net_ipv4_igmp_input(struct net_pkt *pkt,