net: bridge: multicast: include router port vlan id in notifications
authorNikolay Aleksandrov <nikolay@nvidia.com>
Mon, 19 Jul 2021 17:06:33 +0000 (20:06 +0300)
committerDavid S. Miller <davem@davemloft.net>
Tue, 20 Jul 2021 12:41:20 +0000 (05:41 -0700)
Use the port multicast context to check if the router port is a vlan and
in case it is include its vlan id in the notification.

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_multicast.c
net/bridge/br_private.h

index 7927ad80ee861020855f5d9a616f21df942140ef..90ac9e11c15bb97c0fc873e62255c1bbe6decadc 100644 (file)
@@ -629,6 +629,7 @@ enum {
        MDBA_ROUTER_PATTR_TYPE,
        MDBA_ROUTER_PATTR_INET_TIMER,
        MDBA_ROUTER_PATTR_INET6_TIMER,
+       MDBA_ROUTER_PATTR_VID,
        __MDBA_ROUTER_PATTR_MAX
 };
 #define MDBA_ROUTER_PATTR_MAX (__MDBA_ROUTER_PATTR_MAX - 1)
index 5319587198eb4d33fb2445b748357572ffd45a6c..d3383a47a2f20fe05511c4f1b11cacfc73e49719 100644 (file)
@@ -781,12 +781,12 @@ errout:
 
 static int nlmsg_populate_rtr_fill(struct sk_buff *skb,
                                   struct net_device *dev,
-                                  int ifindex, u32 pid,
+                                  int ifindex, u16 vid, u32 pid,
                                   u32 seq, int type, unsigned int flags)
 {
+       struct nlattr *nest, *port_nest;
        struct br_port_msg *bpm;
        struct nlmsghdr *nlh;
-       struct nlattr *nest;
 
        nlh = nlmsg_put(skb, pid, seq, type, sizeof(*bpm), 0);
        if (!nlh)
@@ -800,8 +800,18 @@ static int nlmsg_populate_rtr_fill(struct sk_buff *skb,
        if (!nest)
                goto cancel;
 
-       if (nla_put_u32(skb, MDBA_ROUTER_PORT, ifindex))
+       port_nest = nla_nest_start_noflag(skb, MDBA_ROUTER_PORT);
+       if (!port_nest)
+               goto end;
+       if (nla_put_nohdr(skb, sizeof(u32), &ifindex)) {
+               nla_nest_cancel(skb, port_nest);
                goto end;
+       }
+       if (vid && nla_put_u16(skb, MDBA_ROUTER_PATTR_VID, vid)) {
+               nla_nest_cancel(skb, port_nest);
+               goto end;
+       }
+       nla_nest_end(skb, port_nest);
 
        nla_nest_end(skb, nest);
        nlmsg_end(skb, nlh);
@@ -817,23 +827,28 @@ cancel:
 static inline size_t rtnl_rtr_nlmsg_size(void)
 {
        return NLMSG_ALIGN(sizeof(struct br_port_msg))
-               + nla_total_size(sizeof(__u32));
+               + nla_total_size(sizeof(__u32))
+               + nla_total_size(sizeof(u16));
 }
 
-void br_rtr_notify(struct net_device *dev, struct net_bridge_port *port,
+void br_rtr_notify(struct net_device *dev, struct net_bridge_mcast_port *pmctx,
                   int type)
 {
        struct net *net = dev_net(dev);
        struct sk_buff *skb;
        int err = -ENOBUFS;
        int ifindex;
+       u16 vid;
 
-       ifindex = port ? port->dev->ifindex : 0;
+       ifindex = pmctx ? pmctx->port->dev->ifindex : 0;
+       vid = pmctx && br_multicast_port_ctx_is_vlan(pmctx) ? pmctx->vlan->vid :
+                                                             0;
        skb = nlmsg_new(rtnl_rtr_nlmsg_size(), GFP_ATOMIC);
        if (!skb)
                goto errout;
 
-       err = nlmsg_populate_rtr_fill(skb, dev, ifindex, 0, 0, type, NTF_SELF);
+       err = nlmsg_populate_rtr_fill(skb, dev, ifindex, vid, 0, 0, type,
+                                     NTF_SELF);
        if (err < 0) {
                kfree_skb(skb);
                goto errout;
index 9d4a18a711e48522e7b34317a272d60b15d25f15..fb5e5df571fd036cc6b54341c4c528b6d22d2d0f 100644 (file)
@@ -2979,7 +2979,7 @@ static void br_multicast_add_router(struct net_bridge_mcast *brmctx,
         * IPv4 or IPv6 multicast router.
         */
        if (br_multicast_no_router_otherpf(pmctx, rlist)) {
-               br_rtr_notify(pmctx->port->br->dev, pmctx->port, RTM_NEWMDB);
+               br_rtr_notify(pmctx->port->br->dev, pmctx, RTM_NEWMDB);
                br_port_mc_router_state_change(pmctx->port, true);
        }
 }
@@ -4078,7 +4078,7 @@ br_multicast_rport_del_notify(struct net_bridge_mcast_port *pmctx, bool deleted)
                return;
 #endif
 
-       br_rtr_notify(pmctx->port->br->dev, pmctx->port, RTM_DELMDB);
+       br_rtr_notify(pmctx->port->br->dev, pmctx, RTM_DELMDB);
        br_port_mc_router_state_change(pmctx->port, false);
 
        /* don't allow timer refresh */
index 0d019b0b00e5ffcb489ffb064afaa092ebae16a5..a18c27f581a32b09c871954486f9d95eb8691287 100644 (file)
@@ -872,7 +872,7 @@ int br_mdb_hash_init(struct net_bridge *br);
 void br_mdb_hash_fini(struct net_bridge *br);
 void br_mdb_notify(struct net_device *dev, struct net_bridge_mdb_entry *mp,
                   struct net_bridge_port_group *pg, int type);
-void br_rtr_notify(struct net_device *dev, struct net_bridge_port *port,
+void br_rtr_notify(struct net_device *dev, struct net_bridge_mcast_port *pmctx,
                   int type);
 void br_multicast_del_pg(struct net_bridge_mdb_entry *mp,
                         struct net_bridge_port_group *pg,