OSDN Git Service

net: bridge: mdb: dump host-joined entries as well
authorNikolay Aleksandrov <nikolay@cumulusnetworks.com>
Sat, 17 Aug 2019 11:22:12 +0000 (14:22 +0300)
committerDavid S. Miller <davem@davemloft.net>
Sat, 17 Aug 2019 19:36:57 +0000 (12:36 -0700)
Currently we dump only the port mdb entries but we can have host-joined
entries on the bridge itself and they should be treated as normal temp
mdbs, they're already notified:
$ bridge monitor all
[MDB]dev br0 port br0 grp ff02::8 temp

The group will not be shown in the bridge mdb output, but it takes 1 slot
and it's timing out. If it's only host-joined then the mdb show output
can even be empty.

After this patch we show the host-joined groups:
$ bridge mdb show
dev br0 port br0 grp ff02::8 temp

Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/bridge/br_mdb.c

index 7773098..9852734 100644 (file)
@@ -78,22 +78,35 @@ static void __mdb_entry_to_br_ip(struct br_mdb_entry *entry, struct br_ip *ip)
 }
 
 static int __mdb_fill_info(struct sk_buff *skb,
+                          struct net_bridge_mdb_entry *mp,
                           struct net_bridge_port_group *p)
 {
+       struct timer_list *mtimer;
        struct nlattr *nest_ent;
        struct br_mdb_entry e;
+       u8 flags = 0;
+       int ifindex;
 
        memset(&e, 0, sizeof(e));
-       __mdb_entry_fill_flags(&e, p->flags);
-       e.ifindex = p->port->dev->ifindex;
-       e.vid = p->addr.vid;
-       if (p->addr.proto == htons(ETH_P_IP))
-               e.addr.u.ip4 = p->addr.u.ip4;
+       if (p) {
+               ifindex = p->port->dev->ifindex;
+               mtimer = &p->timer;
+               flags = p->flags;
+       } else {
+               ifindex = mp->br->dev->ifindex;
+               mtimer = &mp->timer;
+       }
+
+       __mdb_entry_fill_flags(&e, flags);
+       e.ifindex = ifindex;
+       e.vid = mp->addr.vid;
+       if (mp->addr.proto == htons(ETH_P_IP))
+               e.addr.u.ip4 = mp->addr.u.ip4;
 #if IS_ENABLED(CONFIG_IPV6)
-       if (p->addr.proto == htons(ETH_P_IPV6))
-               e.addr.u.ip6 = p->addr.u.ip6;
+       if (mp->addr.proto == htons(ETH_P_IPV6))
+               e.addr.u.ip6 = mp->addr.u.ip6;
 #endif
-       e.addr.proto = p->addr.proto;
+       e.addr.proto = mp->addr.proto;
        nest_ent = nla_nest_start_noflag(skb,
                                         MDBA_MDB_ENTRY_INFO);
        if (!nest_ent)
@@ -102,7 +115,7 @@ static int __mdb_fill_info(struct sk_buff *skb,
        if (nla_put_nohdr(skb, sizeof(e), &e) ||
            nla_put_u32(skb,
                        MDBA_MDB_EATTR_TIMER,
-                       br_timer_value(&p->timer))) {
+                       br_timer_value(mtimer))) {
                nla_nest_cancel(skb, nest_ent);
                return -EMSGSIZE;
        }
@@ -139,12 +152,20 @@ static int br_mdb_fill_info(struct sk_buff *skb, struct netlink_callback *cb,
                        break;
                }
 
+               if (mp->host_joined) {
+                       err = __mdb_fill_info(skb, mp, NULL);
+                       if (err) {
+                               nla_nest_cancel(skb, nest2);
+                               break;
+                       }
+               }
+
                for (pp = &mp->ports; (p = rcu_dereference(*pp)) != NULL;
                      pp = &p->next) {
                        if (!p->port)
                                continue;
 
-                       err = __mdb_fill_info(skb, p);
+                       err = __mdb_fill_info(skb, mp, p);
                        if (err) {
                                nla_nest_cancel(skb, nest2);
                                goto out;