// SPDX-License-Identifier: GPL-2.0
#include <linux/err.h>
#include <linux/igmp.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/rculist.h>
#include <linux/skbuff.h>
#include <linux/if_ether.h>
#include <net/ip.h>
#include <net/netlink.h>
#include <net/switchdev.h>
#if IS_ENABLED(CONFIG_IPV6)
#include <net/ipv6.h>
#include <net/addrconf.h>
#endif
#include "br_private.h"
static bool
br_ip4_rports_get_timer(struct net_bridge_mcast_port *pmctx,
unsigned long *timer)
{
*timer = br_timer_value(&pmctx->ip4_mc_router_timer);
return !hlist_unhashed(&pmctx->ip4_rlist);
}
static bool
br_ip6_rports_get_timer(struct net_bridge_mcast_port *pmctx,
unsigned long *timer)
{
#if IS_ENABLED(CONFIG_IPV6)
*timer = br_timer_value(&pmctx->ip6_mc_router_timer);
return !hlist_unhashed(&pmctx->ip6_rlist);
#else
*timer = 0;
return false;
#endif
}
static size_t __br_rports_one_size(void)
{
return nla_total_size(sizeof(u32)) + /* MDBA_ROUTER_PORT */
nla_total_size(sizeof(u32)) + /* MDBA_ROUTER_PATTR_TIMER */
nla_total_size(sizeof(u8)) + /* MDBA_ROUTER_PATTR_TYPE */
nla_total_size(sizeof(u32)) + /* MDBA_ROUTER_PATTR_INET_TIMER */
nla_total_size(sizeof(u32)) + /* MDBA_ROUTER_PATTR_INET6_TIMER */
nla_total_size(sizeof(u32)); /* MDBA_ROUTER_PATTR_VID */
}
size_t br_rports_size(const struct net_bridge_mcast *brmctx)
{
struct net_bridge_mcast_port *pmctx;
size_t size = nla_total_size(0); /* MDBA_ROUTER */
rcu_read_lock();
hlist_for_each_entry_rcu(pmctx, &brmctx->ip4_mc_router_list,
ip4_rlist)
size += __br_rports_one_size();
#if IS_ENABLED(CONFIG_IPV6)
hlist_for_each_entry_rcu(pmctx, &brmctx->ip6_mc_router_list,
ip6_rlist)
size += __br_rports_one_size();
#endif
rcu_read_unlock();
return size;
}
int br_rports_fill_info(struct sk_buff *skb,
const struct net_bridge_mcast *brmctx)
{
u16 vid =