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:
parent
86f48609fb
commit
b71b514e93
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue