net: bridge: vlan: use br_rports_fill_info() to export mcast router ports
authorNikolay Aleksandrov <nikolay@nvidia.com>
Tue, 10 Aug 2021 15:29:33 +0000 (18:29 +0300)
committerDavid S. Miller <davem@davemloft.net>
Wed, 11 Aug 2021 12:34:41 +0000 (13:34 +0100)
Embed the standard multicast router port export by br_rports_fill_info()
into a new global vlan attribute BRIDGE_VLANDB_GOPTS_MCAST_ROUTER_PORTS.
In order to have the same format for the global bridge mcast context and
the per-vlan mcast context we need a double-nesting:
 - BRIDGE_VLANDB_GOPTS_MCAST_ROUTER_PORTS
   - MDBA_ROUTER

Currently we don't compare router lists, if any router port exists in
the bridge mcast contexts we consider their option sets as different and
export them separately.

In addition we export the router port vlan id when dumping similar to
the router port notification format.

Signed-off-by: Nikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/uapi/linux/if_bridge.h
net/bridge/br_mdb.c
net/bridge/br_private.h
net/bridge/br_vlan_options.c

index 2104dd3557b40480ad24d3aa1f7a7fc37b1ff923..620d86e825b89e9cb9fe8d59bc1f42c9ddbbb074 100644 (file)
@@ -562,6 +562,7 @@ enum {
        BRIDGE_VLANDB_GOPTS_MCAST_STARTUP_QUERY_INTVL,
        BRIDGE_VLANDB_GOPTS_MCAST_QUERIER,
        BRIDGE_VLANDB_GOPTS_MCAST_ROUTER,
+       BRIDGE_VLANDB_GOPTS_MCAST_ROUTER_PORTS,
        __BRIDGE_VLANDB_GOPTS_MAX
 };
 #define BRIDGE_VLANDB_GOPTS_MAX (__BRIDGE_VLANDB_GOPTS_MAX - 1)
index 7c16e2c762207d8664bc0e6ef9a8cd2e4864e62d..389ff3c1e9d93501d6d537d46a2aefe153b0592c 100644 (file)
 
 #include "br_private.h"
 
-static bool br_rports_have_mc_router(const struct net_bridge_mcast *brmctx)
-{
-#if IS_ENABLED(CONFIG_IPV6)
-       return !hlist_empty(&brmctx->ip4_mc_router_list) ||
-              !hlist_empty(&brmctx->ip6_mc_router_list);
-#else
-       return !hlist_empty(&brmctx->ip4_mc_router_list);
-#endif
-}
-
 static bool
 br_ip4_rports_get_timer(struct net_bridge_mcast_port *pmctx,
                        unsigned long *timer)
@@ -47,8 +37,8 @@ br_ip6_rports_get_timer(struct net_bridge_mcast_port *pmctx,
 #endif
 }
 
-static int br_rports_fill_info(struct sk_buff *skb,
-                              const struct net_bridge_mcast *brmctx)
+int br_rports_fill_info(struct sk_buff *skb,
+                       const struct net_bridge_mcast *brmctx)
 {
        u16 vid = brmctx->vlan ? brmctx->vlan->vid : 0;
        bool have_ip4_mc_rtr, have_ip6_mc_rtr;
@@ -97,7 +87,8 @@ static int br_rports_fill_info(struct sk_buff *skb,
                                 ip4_timer)) ||
                    (have_ip6_mc_rtr &&
                     nla_put_u32(skb, MDBA_ROUTER_PATTR_INET6_TIMER,
-                                ip6_timer))) {
+                                ip6_timer)) ||
+                   (vid && nla_put_u16(skb, MDBA_ROUTER_PATTR_VID, vid))) {
                        nla_nest_cancel(skb, port_nest);
                        goto fail;
                }
index 6d5681ca8d2f221293f1dee2553cbf586dc5ff47..32c218aa3f36704ea44a80611c2e8c30cbf2b6be 100644 (file)
@@ -945,6 +945,8 @@ bool br_multicast_toggle_global_vlan(struct net_bridge_vlan *vlan, bool on);
 int br_mdb_replay(struct net_device *br_dev, struct net_device *dev,
                  const void *ctx, bool adding, struct notifier_block *nb,
                  struct netlink_ext_ack *extack);
+int br_rports_fill_info(struct sk_buff *skb,
+                       const struct net_bridge_mcast *brmctx);
 
 static inline bool br_group_is_l2(const struct br_ip *group)
 {
@@ -1168,6 +1170,17 @@ br_multicast_port_ctx_state_stopped(const struct net_bridge_mcast_port *pmctx)
                pmctx->vlan->state == BR_STATE_BLOCKING);
 }
 
+static inline bool
+br_rports_have_mc_router(const struct net_bridge_mcast *brmctx)
+{
+#if IS_ENABLED(CONFIG_IPV6)
+       return !hlist_empty(&brmctx->ip4_mc_router_list) ||
+              !hlist_empty(&brmctx->ip6_mc_router_list);
+#else
+       return !hlist_empty(&brmctx->ip4_mc_router_list);
+#endif
+}
+
 static inline bool
 br_multicast_ctx_options_equal(const struct net_bridge_mcast *brmctx1,
                               const struct net_bridge_mcast *brmctx2)
@@ -1192,6 +1205,8 @@ br_multicast_ctx_options_equal(const struct net_bridge_mcast *brmctx1,
               brmctx2->multicast_startup_query_interval &&
               brmctx1->multicast_querier == brmctx2->multicast_querier &&
               brmctx1->multicast_router == brmctx2->multicast_router &&
+              !br_rports_have_mc_router(brmctx1) &&
+              !br_rports_have_mc_router(brmctx2) &&
 #if IS_ENABLED(CONFIG_IPV6)
               brmctx1->multicast_mld_version ==
               brmctx2->multicast_mld_version &&
index 6ba45b73931f2e225b83f8123f7bc5978c0c16c2..b4fd5fa441b7c8162568d0dae8ad2c037fc4c2fc 100644 (file)
@@ -272,6 +272,7 @@ bool br_vlan_global_opts_can_enter_range(const struct net_bridge_vlan *v_curr,
 bool br_vlan_global_opts_fill(struct sk_buff *skb, u16 vid, u16 vid_range,
                              const struct net_bridge_vlan *v_opts)
 {
+       struct nlattr *nest2 __maybe_unused;
        u64 clockval __maybe_unused;
        struct nlattr *nest;
 
@@ -326,6 +327,23 @@ bool br_vlan_global_opts_fill(struct sk_buff *skb, u16 vid, u16 vid_range,
                              clockval, BRIDGE_VLANDB_GOPTS_PAD))
                goto out_err;
 
+       if (br_rports_have_mc_router(&v_opts->br_mcast_ctx)) {
+               nest2 = nla_nest_start(skb,
+                                      BRIDGE_VLANDB_GOPTS_MCAST_ROUTER_PORTS);
+               if (!nest2)
+                       goto out_err;
+
+               rcu_read_lock();
+               if (br_rports_fill_info(skb, &v_opts->br_mcast_ctx)) {
+                       rcu_read_unlock();
+                       nla_nest_cancel(skb, nest2);
+                       goto out_err;
+               }
+               rcu_read_unlock();
+
+               nla_nest_end(skb, nest2);
+       }
+
 #if IS_ENABLED(CONFIG_IPV6)
        if (nla_put_u8(skb, BRIDGE_VLANDB_GOPTS_MCAST_MLD_VERSION,
                       v_opts->br_mcast_ctx.multicast_mld_version))