* [PATCH net-next 0/4] net: bridge: mdb: allow dump/add/del of host-joined entries @ 2019-08-14 14:40 Nikolay Aleksandrov 2019-08-14 14:40 ` [PATCH net-next 1/4] net: bridge: mdb: move vlan comments Nikolay Aleksandrov ` (4 more replies) 0 siblings, 5 replies; 18+ messages in thread From: Nikolay Aleksandrov @ 2019-08-14 14:40 UTC (permalink / raw) To: netdev; +Cc: davem, roopa, bridge, Nikolay Aleksandrov Hi, This set makes the bridge dump host-joined mdb entries, they should be treated as normal entries since they take a slot and are aging out. We already have notifications for them but we couldn't dump them until now so they remained hidden. We dump them similar to how they're notified, in order to keep user-space compatibility with the dumped objects (e.g. iproute2 dumps mdbs in a format which can be fed into add/del commands) we allow host-joined groups also to be added/deleted via mdb commands. That can later be used for L2 mcast MAC manipulation as was recently discussed. Note that iproute2 changes are not necessary, this set will work with the current user-space mdb code. Patch 01 - a trivial comment move Patch 02 - factors out the mdb filling code so it can be re-used for the host-joined entries Patch 03 - dumps host-joined entries Patch 04 - allows manipulation of host-joined entries via standard mdb calls Thanks, Nik Nikolay Aleksandrov (4): net: bridge: mdb: move vlan comments net: bridge: mdb: factor out mdb filling net: bridge: mdb: dump host-joined entries as well net: bridge: mdb: allow add/delete for host-joined groups net/bridge/br_mdb.c | 171 +++++++++++++++++++++++++------------- net/bridge/br_multicast.c | 24 ++++-- net/bridge/br_private.h | 2 + 3 files changed, 133 insertions(+), 64 deletions(-) -- 2.21.0 ^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH net-next 1/4] net: bridge: mdb: move vlan comments 2019-08-14 14:40 [PATCH net-next 0/4] net: bridge: mdb: allow dump/add/del of host-joined entries Nikolay Aleksandrov @ 2019-08-14 14:40 ` Nikolay Aleksandrov 2019-08-14 14:40 ` [PATCH net-next 2/4] net: bridge: mdb: factor out mdb filling Nikolay Aleksandrov ` (3 subsequent siblings) 4 siblings, 0 replies; 18+ messages in thread From: Nikolay Aleksandrov @ 2019-08-14 14:40 UTC (permalink / raw) To: netdev; +Cc: davem, roopa, bridge, Nikolay Aleksandrov Trivial patch to move the vlan comments in their proper places above the vid 0 checks. Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com> --- net/bridge/br_mdb.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c index 428af1abf8cc..ee6208c6d946 100644 --- a/net/bridge/br_mdb.c +++ b/net/bridge/br_mdb.c @@ -653,9 +653,6 @@ static int br_mdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, br = netdev_priv(dev); - /* If vlan filtering is enabled and VLAN is not specified - * install mdb entry on all vlans configured on the port. - */ pdev = __dev_get_by_index(net, entry->ifindex); if (!pdev) return -ENODEV; @@ -665,6 +662,9 @@ static int br_mdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, return -EINVAL; vg = nbp_vlan_group(p); + /* If vlan filtering is enabled and VLAN is not specified + * install mdb entry on all vlans configured on the port. + */ if (br_vlan_enabled(br->dev) && vg && entry->vid == 0) { list_for_each_entry(v, &vg->vlan_list, vlist) { entry->vid = v->vid; @@ -745,9 +745,6 @@ static int br_mdb_del(struct sk_buff *skb, struct nlmsghdr *nlh, br = netdev_priv(dev); - /* If vlan filtering is enabled and VLAN is not specified - * delete mdb entry on all vlans configured on the port. - */ pdev = __dev_get_by_index(net, entry->ifindex); if (!pdev) return -ENODEV; @@ -757,6 +754,9 @@ static int br_mdb_del(struct sk_buff *skb, struct nlmsghdr *nlh, return -EINVAL; vg = nbp_vlan_group(p); + /* If vlan filtering is enabled and VLAN is not specified + * delete mdb entry on all vlans configured on the port. + */ if (br_vlan_enabled(br->dev) && vg && entry->vid == 0) { list_for_each_entry(v, &vg->vlan_list, vlist) { entry->vid = v->vid; -- 2.21.0 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH net-next 2/4] net: bridge: mdb: factor out mdb filling 2019-08-14 14:40 [PATCH net-next 0/4] net: bridge: mdb: allow dump/add/del of host-joined entries Nikolay Aleksandrov 2019-08-14 14:40 ` [PATCH net-next 1/4] net: bridge: mdb: move vlan comments Nikolay Aleksandrov @ 2019-08-14 14:40 ` Nikolay Aleksandrov 2019-08-14 14:40 ` [PATCH net-next 3/4] net: bridge: mdb: dump host-joined entries as well Nikolay Aleksandrov ` (2 subsequent siblings) 4 siblings, 0 replies; 18+ messages in thread From: Nikolay Aleksandrov @ 2019-08-14 14:40 UTC (permalink / raw) To: netdev; +Cc: davem, roopa, bridge, Nikolay Aleksandrov We have to factor out the mdb fill portion in order to re-use it later for the bridge mdb entries. No functional changes intended. Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com> --- net/bridge/br_mdb.c | 68 ++++++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 31 deletions(-) diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c index ee6208c6d946..77730983097e 100644 --- a/net/bridge/br_mdb.c +++ b/net/bridge/br_mdb.c @@ -77,6 +77,40 @@ static void __mdb_entry_to_br_ip(struct br_mdb_entry *entry, struct br_ip *ip) #endif } +static int __mdb_fill_info(struct sk_buff *skb, + struct net_bridge_port_group *p) +{ + struct nlattr *nest_ent; + struct br_mdb_entry e; + + 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 IS_ENABLED(CONFIG_IPV6) + if (p->addr.proto == htons(ETH_P_IPV6)) + e.addr.u.ip6 = p->addr.u.ip6; +#endif + e.addr.proto = p->addr.proto; + nest_ent = nla_nest_start_noflag(skb, + MDBA_MDB_ENTRY_INFO); + if (!nest_ent) + return -EMSGSIZE; + + if (nla_put_nohdr(skb, sizeof(e), &e) || + nla_put_u32(skb, + MDBA_MDB_EATTR_TIMER, + br_timer_value(&p->timer))) { + nla_nest_cancel(skb, nest_ent); + return -EMSGSIZE; + } + nla_nest_end(skb, nest_ent); + + return 0; +} + static int br_mdb_fill_info(struct sk_buff *skb, struct netlink_callback *cb, struct net_device *dev) { @@ -95,7 +129,6 @@ static int br_mdb_fill_info(struct sk_buff *skb, struct netlink_callback *cb, hlist_for_each_entry_rcu(mp, &br->mdb_list, mdb_node) { struct net_bridge_port_group *p; struct net_bridge_port_group __rcu **pp; - struct net_bridge_port *port; if (idx < s_idx) goto skip; @@ -108,41 +141,14 @@ static int br_mdb_fill_info(struct sk_buff *skb, struct netlink_callback *cb, for (pp = &mp->ports; (p = rcu_dereference(*pp)) != NULL; pp = &p->next) { - struct nlattr *nest_ent; - struct br_mdb_entry e; - - port = p->port; - if (!port) + if (!p->port) continue; - memset(&e, 0, sizeof(e)); - e.ifindex = port->dev->ifindex; - e.vid = p->addr.vid; - __mdb_entry_fill_flags(&e, p->flags); - if (p->addr.proto == htons(ETH_P_IP)) - e.addr.u.ip4 = p->addr.u.ip4; -#if IS_ENABLED(CONFIG_IPV6) - if (p->addr.proto == htons(ETH_P_IPV6)) - e.addr.u.ip6 = p->addr.u.ip6; -#endif - e.addr.proto = p->addr.proto; - nest_ent = nla_nest_start_noflag(skb, - MDBA_MDB_ENTRY_INFO); - if (!nest_ent) { - nla_nest_cancel(skb, nest2); - err = -EMSGSIZE; - goto out; - } - if (nla_put_nohdr(skb, sizeof(e), &e) || - nla_put_u32(skb, - MDBA_MDB_EATTR_TIMER, - br_timer_value(&p->timer))) { - nla_nest_cancel(skb, nest_ent); + err = __mdb_fill_info(skb, p); + if (err) { nla_nest_cancel(skb, nest2); - err = -EMSGSIZE; goto out; } - nla_nest_end(skb, nest_ent); } nla_nest_end(skb, nest2); skip: -- 2.21.0 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH net-next 3/4] net: bridge: mdb: dump host-joined entries as well 2019-08-14 14:40 [PATCH net-next 0/4] net: bridge: mdb: allow dump/add/del of host-joined entries Nikolay Aleksandrov 2019-08-14 14:40 ` [PATCH net-next 1/4] net: bridge: mdb: move vlan comments Nikolay Aleksandrov 2019-08-14 14:40 ` [PATCH net-next 2/4] net: bridge: mdb: factor out mdb filling Nikolay Aleksandrov @ 2019-08-14 14:40 ` Nikolay Aleksandrov 2019-08-14 14:40 ` [PATCH net-next 4/4] net: bridge: mdb: allow add/delete for host-joined groups Nikolay Aleksandrov 2019-08-14 16:01 ` [PATCH net-next 0/4] net: bridge: mdb: allow dump/add/del of host-joined entries Nikolay Aleksandrov 4 siblings, 0 replies; 18+ messages in thread From: Nikolay Aleksandrov @ 2019-08-14 14:40 UTC (permalink / raw) To: netdev; +Cc: davem, roopa, bridge, Nikolay Aleksandrov 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> --- net/bridge/br_mdb.c | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c index 77730983097e..985273425117 100644 --- a/net/bridge/br_mdb.c +++ b/net/bridge/br_mdb.c @@ -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; -- 2.21.0 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH net-next 4/4] net: bridge: mdb: allow add/delete for host-joined groups 2019-08-14 14:40 [PATCH net-next 0/4] net: bridge: mdb: allow dump/add/del of host-joined entries Nikolay Aleksandrov ` (2 preceding siblings ...) 2019-08-14 14:40 ` [PATCH net-next 3/4] net: bridge: mdb: dump host-joined entries as well Nikolay Aleksandrov @ 2019-08-14 14:40 ` Nikolay Aleksandrov 2019-08-14 16:01 ` [PATCH net-next 0/4] net: bridge: mdb: allow dump/add/del of host-joined entries Nikolay Aleksandrov 4 siblings, 0 replies; 18+ messages in thread From: Nikolay Aleksandrov @ 2019-08-14 14:40 UTC (permalink / raw) To: netdev; +Cc: davem, roopa, bridge, Nikolay Aleksandrov Currently this is needed only for user-space compatibility, so similar object adds/deletes as the dumped ones would succeed. Later it can be used for L2 mcast MAC add/delete. Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com> --- net/bridge/br_mdb.c | 74 +++++++++++++++++++++++++++------------ net/bridge/br_multicast.c | 24 +++++++++---- net/bridge/br_private.h | 2 ++ 3 files changed, 71 insertions(+), 29 deletions(-) diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c index 985273425117..331a130b83b1 100644 --- a/net/bridge/br_mdb.c +++ b/net/bridge/br_mdb.c @@ -616,6 +616,19 @@ static int br_mdb_add_group(struct net_bridge *br, struct net_bridge_port *port, return err; } + /* host join */ + if (!port) { + /* don't allow any flags for host-joined groups */ + if (state) + return -EINVAL; + if (mp->host_joined) + return -EEXIST; + + br_multicast_host_join(mp); + + return 0; + } + for (pp = &mp->ports; (p = mlock_dereference(*pp, br)) != NULL; pp = &p->next) { @@ -640,19 +653,21 @@ static int __br_mdb_add(struct net *net, struct net_bridge *br, { struct br_ip ip; struct net_device *dev; - struct net_bridge_port *p; + struct net_bridge_port *p = NULL; int ret; if (!netif_running(br->dev) || !br_opt_get(br, BROPT_MULTICAST_ENABLED)) return -EINVAL; - dev = __dev_get_by_index(net, entry->ifindex); - if (!dev) - return -ENODEV; + if (entry->ifindex != br->dev->ifindex) { + dev = __dev_get_by_index(net, entry->ifindex); + if (!dev) + return -ENODEV; - p = br_port_get_rtnl(dev); - if (!p || p->br != br || p->state == BR_STATE_DISABLED) - return -EINVAL; + p = br_port_get_rtnl(dev); + if (!p || p->br != br || p->state == BR_STATE_DISABLED) + return -EINVAL; + } __mdb_entry_to_br_ip(entry, &ip); @@ -680,15 +695,19 @@ static int br_mdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, br = netdev_priv(dev); - pdev = __dev_get_by_index(net, entry->ifindex); - if (!pdev) - return -ENODEV; + if (entry->ifindex != br->dev->ifindex) { + pdev = __dev_get_by_index(net, entry->ifindex); + if (!pdev) + return -ENODEV; - p = br_port_get_rtnl(pdev); - if (!p || p->br != br || p->state == BR_STATE_DISABLED) - return -EINVAL; + p = br_port_get_rtnl(pdev); + if (!p || p->br != br || p->state == BR_STATE_DISABLED) + return -EINVAL; + vg = nbp_vlan_group(p); + } else { + vg = br_vlan_group(br); + } - vg = nbp_vlan_group(p); /* If vlan filtering is enabled and VLAN is not specified * install mdb entry on all vlans configured on the port. */ @@ -727,6 +746,13 @@ static int __br_mdb_del(struct net_bridge *br, struct br_mdb_entry *entry) if (!mp) goto unlock; + /* host leave */ + if (entry->ifindex == mp->br->dev->ifindex && mp->host_joined) { + br_multicast_host_leave(mp); + err = 0; + goto unlock; + } + for (pp = &mp->ports; (p = mlock_dereference(*pp, br)) != NULL; pp = &p->next) { @@ -759,9 +785,9 @@ static int br_mdb_del(struct sk_buff *skb, struct nlmsghdr *nlh, { struct net *net = sock_net(skb->sk); struct net_bridge_vlan_group *vg; + struct net_bridge_port *p = NULL; struct net_device *dev, *pdev; struct br_mdb_entry *entry; - struct net_bridge_port *p; struct net_bridge_vlan *v; struct net_bridge *br; int err; @@ -772,15 +798,19 @@ static int br_mdb_del(struct sk_buff *skb, struct nlmsghdr *nlh, br = netdev_priv(dev); - pdev = __dev_get_by_index(net, entry->ifindex); - if (!pdev) - return -ENODEV; + if (entry->ifindex != br->dev->ifindex) { + pdev = __dev_get_by_index(net, entry->ifindex); + if (!pdev) + return -ENODEV; - p = br_port_get_rtnl(pdev); - if (!p || p->br != br || p->state == BR_STATE_DISABLED) - return -EINVAL; + p = br_port_get_rtnl(pdev); + if (!p || p->br != br || p->state == BR_STATE_DISABLED) + return -EINVAL; + vg = nbp_vlan_group(p); + } else { + vg = br_vlan_group(br); + } - vg = nbp_vlan_group(p); /* If vlan filtering is enabled and VLAN is not specified * delete mdb entry on all vlans configured on the port. */ diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 9b379e110129..f92cb6751898 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -148,8 +148,7 @@ static void br_multicast_group_expired(struct timer_list *t) if (!netif_running(br->dev) || timer_pending(&mp->timer)) goto out; - mp->host_joined = false; - br_mdb_notify(br->dev, NULL, &mp->addr, RTM_DELMDB, 0); + br_multicast_host_leave(mp); if (mp->ports) goto out; @@ -512,6 +511,21 @@ static bool br_port_group_equal(struct net_bridge_port_group *p, return ether_addr_equal(src, p->eth_addr); } +void br_multicast_host_join(struct net_bridge_mdb_entry *mp) +{ + if (!mp->host_joined) { + mp->host_joined = true; + br_mdb_notify(mp->br->dev, NULL, &mp->addr, RTM_NEWMDB, 0); + } + mod_timer(&mp->timer, jiffies + mp->br->multicast_membership_interval); +} + +void br_multicast_host_leave(struct net_bridge_mdb_entry *mp) +{ + mp->host_joined = false; + br_mdb_notify(mp->br->dev, NULL, &mp->addr, RTM_DELMDB, 0); +} + static int br_multicast_add_group(struct net_bridge *br, struct net_bridge_port *port, struct br_ip *group, @@ -534,11 +548,7 @@ static int br_multicast_add_group(struct net_bridge *br, goto err; if (!port) { - if (!mp->host_joined) { - mp->host_joined = true; - br_mdb_notify(br->dev, NULL, &mp->addr, RTM_NEWMDB, 0); - } - mod_timer(&mp->timer, now + br->multicast_membership_interval); + br_multicast_host_join(mp); goto out; } diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index b7a4942ff1b3..a99dcbb9825c 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -702,6 +702,8 @@ void br_multicast_get_stats(const struct net_bridge *br, struct br_mcast_stats *dest); void br_mdb_init(void); void br_mdb_uninit(void); +void br_multicast_host_join(struct net_bridge_mdb_entry *mp); +void br_multicast_host_leave(struct net_bridge_mdb_entry *mp); #define mlock_dereference(X, br) \ rcu_dereference_protected(X, lockdep_is_held(&br->multicast_lock)) -- 2.21.0 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH net-next 0/4] net: bridge: mdb: allow dump/add/del of host-joined entries 2019-08-14 14:40 [PATCH net-next 0/4] net: bridge: mdb: allow dump/add/del of host-joined entries Nikolay Aleksandrov ` (3 preceding siblings ...) 2019-08-14 14:40 ` [PATCH net-next 4/4] net: bridge: mdb: allow add/delete for host-joined groups Nikolay Aleksandrov @ 2019-08-14 16:01 ` Nikolay Aleksandrov 2019-08-14 17:04 ` [PATCH net-next v2 " Nikolay Aleksandrov 4 siblings, 1 reply; 18+ messages in thread From: Nikolay Aleksandrov @ 2019-08-14 16:01 UTC (permalink / raw) To: netdev; +Cc: davem, roopa, bridge On 8/14/19 5:40 PM, Nikolay Aleksandrov wrote: > Hi, > This set makes the bridge dump host-joined mdb entries, they should be > treated as normal entries since they take a slot and are aging out. > We already have notifications for them but we couldn't dump them until > now so they remained hidden. We dump them similar to how they're > notified, in order to keep user-space compatibility with the dumped > objects (e.g. iproute2 dumps mdbs in a format which can be fed into > add/del commands) we allow host-joined groups also to be added/deleted via > mdb commands. That can later be used for L2 mcast MAC manipulation as > was recently discussed. Note that iproute2 changes are not necessary, > this set will work with the current user-space mdb code. > > Patch 01 - a trivial comment move > Patch 02 - factors out the mdb filling code so it can be > re-used for the host-joined entries > Patch 03 - dumps host-joined entries > Patch 04 - allows manipulation of host-joined entries via standard mdb > calls > > Thanks, > Nik > > Nikolay Aleksandrov (4): > net: bridge: mdb: move vlan comments > net: bridge: mdb: factor out mdb filling > net: bridge: mdb: dump host-joined entries as well > net: bridge: mdb: allow add/delete for host-joined groups > > net/bridge/br_mdb.c | 171 +++++++++++++++++++++++++------------- > net/bridge/br_multicast.c | 24 ++++-- > net/bridge/br_private.h | 2 + > 3 files changed, 133 insertions(+), 64 deletions(-) > Self-NAK There's a double notification sent for manual add/del of host groups. It's a trivial fix, I'll spin v2 later after running more tests. ^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH net-next v2 0/4] net: bridge: mdb: allow dump/add/del of host-joined entries 2019-08-14 16:01 ` [PATCH net-next 0/4] net: bridge: mdb: allow dump/add/del of host-joined entries Nikolay Aleksandrov @ 2019-08-14 17:04 ` Nikolay Aleksandrov 2019-08-14 17:04 ` [PATCH net-next v2 1/4] net: bridge: mdb: move vlan comments Nikolay Aleksandrov ` (4 more replies) 0 siblings, 5 replies; 18+ messages in thread From: Nikolay Aleksandrov @ 2019-08-14 17:04 UTC (permalink / raw) To: netdev; +Cc: davem, roopa, bridge, Nikolay Aleksandrov Hi, This set makes the bridge dump host-joined mdb entries, they should be treated as normal entries since they take a slot and are aging out. We already have notifications for them but we couldn't dump them until now so they remained hidden. We dump them similar to how they're notified, in order to keep user-space compatibility with the dumped objects (e.g. iproute2 dumps mdbs in a format which can be fed into add/del commands) we allow host-joined groups also to be added/deleted via mdb commands. That can later be used for L2 mcast MAC manipulation as was recently discussed. Note that iproute2 changes are not necessary, this set will work with the current user-space mdb code. Patch 01 - a trivial comment move Patch 02 - factors out the mdb filling code so it can be re-used for the host-joined entries Patch 03 - dumps host-joined entries Patch 04 - allows manipulation of host-joined entries via standard mdb calls v2: change patch 04 to avoid double notification and improve host group manual removal if no ports are present in the group Thanks, Nik Nikolay Aleksandrov (4): net: bridge: mdb: move vlan comments net: bridge: mdb: factor out mdb filling net: bridge: mdb: dump host-joined entries as well net: bridge: mdb: allow add/delete for host-joined groups net/bridge/br_mdb.c | 173 +++++++++++++++++++++++++------------- net/bridge/br_multicast.c | 30 +++++-- net/bridge/br_private.h | 2 + 3 files changed, 141 insertions(+), 64 deletions(-) -- 2.21.0 ^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH net-next v2 1/4] net: bridge: mdb: move vlan comments 2019-08-14 17:04 ` [PATCH net-next v2 " Nikolay Aleksandrov @ 2019-08-14 17:04 ` Nikolay Aleksandrov 2019-08-14 17:04 ` [PATCH net-next v2 2/4] net: bridge: mdb: factor out mdb filling Nikolay Aleksandrov ` (3 subsequent siblings) 4 siblings, 0 replies; 18+ messages in thread From: Nikolay Aleksandrov @ 2019-08-14 17:04 UTC (permalink / raw) To: netdev; +Cc: davem, roopa, bridge, Nikolay Aleksandrov Trivial patch to move the vlan comments in their proper places above the vid 0 checks. Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com> --- net/bridge/br_mdb.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c index 428af1abf8cc..ee6208c6d946 100644 --- a/net/bridge/br_mdb.c +++ b/net/bridge/br_mdb.c @@ -653,9 +653,6 @@ static int br_mdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, br = netdev_priv(dev); - /* If vlan filtering is enabled and VLAN is not specified - * install mdb entry on all vlans configured on the port. - */ pdev = __dev_get_by_index(net, entry->ifindex); if (!pdev) return -ENODEV; @@ -665,6 +662,9 @@ static int br_mdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, return -EINVAL; vg = nbp_vlan_group(p); + /* If vlan filtering is enabled and VLAN is not specified + * install mdb entry on all vlans configured on the port. + */ if (br_vlan_enabled(br->dev) && vg && entry->vid == 0) { list_for_each_entry(v, &vg->vlan_list, vlist) { entry->vid = v->vid; @@ -745,9 +745,6 @@ static int br_mdb_del(struct sk_buff *skb, struct nlmsghdr *nlh, br = netdev_priv(dev); - /* If vlan filtering is enabled and VLAN is not specified - * delete mdb entry on all vlans configured on the port. - */ pdev = __dev_get_by_index(net, entry->ifindex); if (!pdev) return -ENODEV; @@ -757,6 +754,9 @@ static int br_mdb_del(struct sk_buff *skb, struct nlmsghdr *nlh, return -EINVAL; vg = nbp_vlan_group(p); + /* If vlan filtering is enabled and VLAN is not specified + * delete mdb entry on all vlans configured on the port. + */ if (br_vlan_enabled(br->dev) && vg && entry->vid == 0) { list_for_each_entry(v, &vg->vlan_list, vlist) { entry->vid = v->vid; -- 2.21.0 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH net-next v2 2/4] net: bridge: mdb: factor out mdb filling 2019-08-14 17:04 ` [PATCH net-next v2 " Nikolay Aleksandrov 2019-08-14 17:04 ` [PATCH net-next v2 1/4] net: bridge: mdb: move vlan comments Nikolay Aleksandrov @ 2019-08-14 17:04 ` Nikolay Aleksandrov 2019-08-14 17:05 ` [PATCH net-next v2 3/4] net: bridge: mdb: dump host-joined entries as well Nikolay Aleksandrov ` (2 subsequent siblings) 4 siblings, 0 replies; 18+ messages in thread From: Nikolay Aleksandrov @ 2019-08-14 17:04 UTC (permalink / raw) To: netdev; +Cc: davem, roopa, bridge, Nikolay Aleksandrov We have to factor out the mdb fill portion in order to re-use it later for the bridge mdb entries. No functional changes intended. Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com> --- net/bridge/br_mdb.c | 68 ++++++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 31 deletions(-) diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c index ee6208c6d946..77730983097e 100644 --- a/net/bridge/br_mdb.c +++ b/net/bridge/br_mdb.c @@ -77,6 +77,40 @@ static void __mdb_entry_to_br_ip(struct br_mdb_entry *entry, struct br_ip *ip) #endif } +static int __mdb_fill_info(struct sk_buff *skb, + struct net_bridge_port_group *p) +{ + struct nlattr *nest_ent; + struct br_mdb_entry e; + + 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 IS_ENABLED(CONFIG_IPV6) + if (p->addr.proto == htons(ETH_P_IPV6)) + e.addr.u.ip6 = p->addr.u.ip6; +#endif + e.addr.proto = p->addr.proto; + nest_ent = nla_nest_start_noflag(skb, + MDBA_MDB_ENTRY_INFO); + if (!nest_ent) + return -EMSGSIZE; + + if (nla_put_nohdr(skb, sizeof(e), &e) || + nla_put_u32(skb, + MDBA_MDB_EATTR_TIMER, + br_timer_value(&p->timer))) { + nla_nest_cancel(skb, nest_ent); + return -EMSGSIZE; + } + nla_nest_end(skb, nest_ent); + + return 0; +} + static int br_mdb_fill_info(struct sk_buff *skb, struct netlink_callback *cb, struct net_device *dev) { @@ -95,7 +129,6 @@ static int br_mdb_fill_info(struct sk_buff *skb, struct netlink_callback *cb, hlist_for_each_entry_rcu(mp, &br->mdb_list, mdb_node) { struct net_bridge_port_group *p; struct net_bridge_port_group __rcu **pp; - struct net_bridge_port *port; if (idx < s_idx) goto skip; @@ -108,41 +141,14 @@ static int br_mdb_fill_info(struct sk_buff *skb, struct netlink_callback *cb, for (pp = &mp->ports; (p = rcu_dereference(*pp)) != NULL; pp = &p->next) { - struct nlattr *nest_ent; - struct br_mdb_entry e; - - port = p->port; - if (!port) + if (!p->port) continue; - memset(&e, 0, sizeof(e)); - e.ifindex = port->dev->ifindex; - e.vid = p->addr.vid; - __mdb_entry_fill_flags(&e, p->flags); - if (p->addr.proto == htons(ETH_P_IP)) - e.addr.u.ip4 = p->addr.u.ip4; -#if IS_ENABLED(CONFIG_IPV6) - if (p->addr.proto == htons(ETH_P_IPV6)) - e.addr.u.ip6 = p->addr.u.ip6; -#endif - e.addr.proto = p->addr.proto; - nest_ent = nla_nest_start_noflag(skb, - MDBA_MDB_ENTRY_INFO); - if (!nest_ent) { - nla_nest_cancel(skb, nest2); - err = -EMSGSIZE; - goto out; - } - if (nla_put_nohdr(skb, sizeof(e), &e) || - nla_put_u32(skb, - MDBA_MDB_EATTR_TIMER, - br_timer_value(&p->timer))) { - nla_nest_cancel(skb, nest_ent); + err = __mdb_fill_info(skb, p); + if (err) { nla_nest_cancel(skb, nest2); - err = -EMSGSIZE; goto out; } - nla_nest_end(skb, nest_ent); } nla_nest_end(skb, nest2); skip: -- 2.21.0 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH net-next v2 3/4] net: bridge: mdb: dump host-joined entries as well 2019-08-14 17:04 ` [PATCH net-next v2 " Nikolay Aleksandrov 2019-08-14 17:04 ` [PATCH net-next v2 1/4] net: bridge: mdb: move vlan comments Nikolay Aleksandrov 2019-08-14 17:04 ` [PATCH net-next v2 2/4] net: bridge: mdb: factor out mdb filling Nikolay Aleksandrov @ 2019-08-14 17:05 ` Nikolay Aleksandrov 2019-08-14 17:05 ` [PATCH net-next v2 4/4] net: bridge: mdb: allow add/delete for host-joined groups Nikolay Aleksandrov 2019-08-16 20:04 ` [PATCH net-next v2 0/4] net: bridge: mdb: allow dump/add/del of host-joined entries David Miller 4 siblings, 0 replies; 18+ messages in thread From: Nikolay Aleksandrov @ 2019-08-14 17:05 UTC (permalink / raw) To: netdev; +Cc: davem, roopa, bridge, Nikolay Aleksandrov 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> --- net/bridge/br_mdb.c | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c index 77730983097e..985273425117 100644 --- a/net/bridge/br_mdb.c +++ b/net/bridge/br_mdb.c @@ -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; -- 2.21.0 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH net-next v2 4/4] net: bridge: mdb: allow add/delete for host-joined groups 2019-08-14 17:04 ` [PATCH net-next v2 " Nikolay Aleksandrov ` (2 preceding siblings ...) 2019-08-14 17:05 ` [PATCH net-next v2 3/4] net: bridge: mdb: dump host-joined entries as well Nikolay Aleksandrov @ 2019-08-14 17:05 ` Nikolay Aleksandrov 2019-08-16 20:04 ` [PATCH net-next v2 0/4] net: bridge: mdb: allow dump/add/del of host-joined entries David Miller 4 siblings, 0 replies; 18+ messages in thread From: Nikolay Aleksandrov @ 2019-08-14 17:05 UTC (permalink / raw) To: netdev; +Cc: davem, roopa, bridge, Nikolay Aleksandrov Currently this is needed only for user-space compatibility, so similar object adds/deletes as the dumped ones would succeed. Later it can be used for L2 mcast MAC add/delete. v2: don't send a notification when used from user-space, arm the group timer if no ports are left after host entry del Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com> --- net/bridge/br_mdb.c | 76 +++++++++++++++++++++++++++------------ net/bridge/br_multicast.c | 30 ++++++++++++---- net/bridge/br_private.h | 2 ++ 3 files changed, 79 insertions(+), 29 deletions(-) diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c index 985273425117..e0f789296920 100644 --- a/net/bridge/br_mdb.c +++ b/net/bridge/br_mdb.c @@ -616,6 +616,19 @@ static int br_mdb_add_group(struct net_bridge *br, struct net_bridge_port *port, return err; } + /* host join */ + if (!port) { + /* don't allow any flags for host-joined groups */ + if (state) + return -EINVAL; + if (mp->host_joined) + return -EEXIST; + + br_multicast_host_join(mp, false); + + return 0; + } + for (pp = &mp->ports; (p = mlock_dereference(*pp, br)) != NULL; pp = &p->next) { @@ -640,19 +653,21 @@ static int __br_mdb_add(struct net *net, struct net_bridge *br, { struct br_ip ip; struct net_device *dev; - struct net_bridge_port *p; + struct net_bridge_port *p = NULL; int ret; if (!netif_running(br->dev) || !br_opt_get(br, BROPT_MULTICAST_ENABLED)) return -EINVAL; - dev = __dev_get_by_index(net, entry->ifindex); - if (!dev) - return -ENODEV; + if (entry->ifindex != br->dev->ifindex) { + dev = __dev_get_by_index(net, entry->ifindex); + if (!dev) + return -ENODEV; - p = br_port_get_rtnl(dev); - if (!p || p->br != br || p->state == BR_STATE_DISABLED) - return -EINVAL; + p = br_port_get_rtnl(dev); + if (!p || p->br != br || p->state == BR_STATE_DISABLED) + return -EINVAL; + } __mdb_entry_to_br_ip(entry, &ip); @@ -680,15 +695,19 @@ static int br_mdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, br = netdev_priv(dev); - pdev = __dev_get_by_index(net, entry->ifindex); - if (!pdev) - return -ENODEV; + if (entry->ifindex != br->dev->ifindex) { + pdev = __dev_get_by_index(net, entry->ifindex); + if (!pdev) + return -ENODEV; - p = br_port_get_rtnl(pdev); - if (!p || p->br != br || p->state == BR_STATE_DISABLED) - return -EINVAL; + p = br_port_get_rtnl(pdev); + if (!p || p->br != br || p->state == BR_STATE_DISABLED) + return -EINVAL; + vg = nbp_vlan_group(p); + } else { + vg = br_vlan_group(br); + } - vg = nbp_vlan_group(p); /* If vlan filtering is enabled and VLAN is not specified * install mdb entry on all vlans configured on the port. */ @@ -727,6 +746,15 @@ static int __br_mdb_del(struct net_bridge *br, struct br_mdb_entry *entry) if (!mp) goto unlock; + /* host leave */ + if (entry->ifindex == mp->br->dev->ifindex && mp->host_joined) { + br_multicast_host_leave(mp, false); + err = 0; + if (!mp->ports && netif_running(br->dev)) + mod_timer(&mp->timer, jiffies); + goto unlock; + } + for (pp = &mp->ports; (p = mlock_dereference(*pp, br)) != NULL; pp = &p->next) { @@ -759,9 +787,9 @@ static int br_mdb_del(struct sk_buff *skb, struct nlmsghdr *nlh, { struct net *net = sock_net(skb->sk); struct net_bridge_vlan_group *vg; + struct net_bridge_port *p = NULL; struct net_device *dev, *pdev; struct br_mdb_entry *entry; - struct net_bridge_port *p; struct net_bridge_vlan *v; struct net_bridge *br; int err; @@ -772,15 +800,19 @@ static int br_mdb_del(struct sk_buff *skb, struct nlmsghdr *nlh, br = netdev_priv(dev); - pdev = __dev_get_by_index(net, entry->ifindex); - if (!pdev) - return -ENODEV; + if (entry->ifindex != br->dev->ifindex) { + pdev = __dev_get_by_index(net, entry->ifindex); + if (!pdev) + return -ENODEV; - p = br_port_get_rtnl(pdev); - if (!p || p->br != br || p->state == BR_STATE_DISABLED) - return -EINVAL; + p = br_port_get_rtnl(pdev); + if (!p || p->br != br || p->state == BR_STATE_DISABLED) + return -EINVAL; + vg = nbp_vlan_group(p); + } else { + vg = br_vlan_group(br); + } - vg = nbp_vlan_group(p); /* If vlan filtering is enabled and VLAN is not specified * delete mdb entry on all vlans configured on the port. */ diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 9b379e110129..ad12fe3fca8c 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -148,8 +148,7 @@ static void br_multicast_group_expired(struct timer_list *t) if (!netif_running(br->dev) || timer_pending(&mp->timer)) goto out; - mp->host_joined = false; - br_mdb_notify(br->dev, NULL, &mp->addr, RTM_DELMDB, 0); + br_multicast_host_leave(mp, true); if (mp->ports) goto out; @@ -512,6 +511,27 @@ static bool br_port_group_equal(struct net_bridge_port_group *p, return ether_addr_equal(src, p->eth_addr); } +void br_multicast_host_join(struct net_bridge_mdb_entry *mp, bool notify) +{ + if (!mp->host_joined) { + mp->host_joined = true; + if (notify) + br_mdb_notify(mp->br->dev, NULL, &mp->addr, + RTM_NEWMDB, 0); + } + mod_timer(&mp->timer, jiffies + mp->br->multicast_membership_interval); +} + +void br_multicast_host_leave(struct net_bridge_mdb_entry *mp, bool notify) +{ + if (!mp->host_joined) + return; + + mp->host_joined = false; + if (notify) + br_mdb_notify(mp->br->dev, NULL, &mp->addr, RTM_DELMDB, 0); +} + static int br_multicast_add_group(struct net_bridge *br, struct net_bridge_port *port, struct br_ip *group, @@ -534,11 +554,7 @@ static int br_multicast_add_group(struct net_bridge *br, goto err; if (!port) { - if (!mp->host_joined) { - mp->host_joined = true; - br_mdb_notify(br->dev, NULL, &mp->addr, RTM_NEWMDB, 0); - } - mod_timer(&mp->timer, now + br->multicast_membership_interval); + br_multicast_host_join(mp, true); goto out; } diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index b7a4942ff1b3..ce2ab14ee605 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -702,6 +702,8 @@ void br_multicast_get_stats(const struct net_bridge *br, struct br_mcast_stats *dest); void br_mdb_init(void); void br_mdb_uninit(void); +void br_multicast_host_join(struct net_bridge_mdb_entry *mp, bool notify); +void br_multicast_host_leave(struct net_bridge_mdb_entry *mp, bool notify); #define mlock_dereference(X, br) \ rcu_dereference_protected(X, lockdep_is_held(&br->multicast_lock)) -- 2.21.0 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH net-next v2 0/4] net: bridge: mdb: allow dump/add/del of host-joined entries 2019-08-14 17:04 ` [PATCH net-next v2 " Nikolay Aleksandrov ` (3 preceding siblings ...) 2019-08-14 17:05 ` [PATCH net-next v2 4/4] net: bridge: mdb: allow add/delete for host-joined groups Nikolay Aleksandrov @ 2019-08-16 20:04 ` David Miller 2019-08-17 11:22 ` [PATCH net-next v3 " Nikolay Aleksandrov 4 siblings, 1 reply; 18+ messages in thread From: David Miller @ 2019-08-16 20:04 UTC (permalink / raw) To: nikolay; +Cc: netdev, roopa, bridge From: Nikolay Aleksandrov <nikolay@cumulusnetworks.com> Date: Wed, 14 Aug 2019 20:04:57 +0300 > This set makes the bridge dump host-joined mdb entries, they should be > treated as normal entries since they take a slot and are aging out. ... Please respin with this warning fixed: net/bridge/br_mdb.c: In function ‘br_mdb_add’: net/bridge/br_mdb.c:725:4: warning: ‘p’ may be used uninitialized in this function [-Wmaybe-uninitialized] __br_mdb_notify(dev, p, entry, RTM_NEWMDB); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [davem@localhost net-next]$ gcc --version gcc (GCC) 8.3.1 20190223 (Red Hat 8.3.1-2) Copyright (C) 2018 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. ^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH net-next v3 0/4] net: bridge: mdb: allow dump/add/del of host-joined entries 2019-08-16 20:04 ` [PATCH net-next v2 0/4] net: bridge: mdb: allow dump/add/del of host-joined entries David Miller @ 2019-08-17 11:22 ` Nikolay Aleksandrov 2019-08-17 11:22 ` [PATCH net-next v3 1/4] net: bridge: mdb: move vlan comments Nikolay Aleksandrov ` (4 more replies) 0 siblings, 5 replies; 18+ messages in thread From: Nikolay Aleksandrov @ 2019-08-17 11:22 UTC (permalink / raw) To: netdev; +Cc: davem, roopa, bridge, Nikolay Aleksandrov Hi, This set makes the bridge dump host-joined mdb entries, they should be treated as normal entries since they take a slot and are aging out. We already have notifications for them but we couldn't dump them until now so they remained hidden. We dump them similar to how they're notified, in order to keep user-space compatibility with the dumped objects (e.g. iproute2 dumps mdbs in a format which can be fed into add/del commands) we allow host-joined groups also to be added/deleted via mdb commands. That can later be used for L2 mcast MAC manipulation as was recently discussed. Note that iproute2 changes are not necessary, this set will work with the current user-space mdb code. Patch 01 - a trivial comment move Patch 02 - factors out the mdb filling code so it can be re-used for the host-joined entries Patch 03 - dumps host-joined entries Patch 04 - allows manipulation of host-joined entries via standard mdb calls v3: fix compiler warning in patch 04 (DaveM) v2: change patch 04 to avoid double notification and improve host group manual removal if no ports are present in the group Thanks, Nik Nikolay Aleksandrov (4): net: bridge: mdb: move vlan comments net: bridge: mdb: factor out mdb filling net: bridge: mdb: dump host-joined entries as well net: bridge: mdb: allow add/delete for host-joined groups net/bridge/br_mdb.c | 175 +++++++++++++++++++++++++------------- net/bridge/br_multicast.c | 30 +++++-- net/bridge/br_private.h | 2 + 3 files changed, 142 insertions(+), 65 deletions(-) -- 2.21.0 ^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH net-next v3 1/4] net: bridge: mdb: move vlan comments 2019-08-17 11:22 ` [PATCH net-next v3 " Nikolay Aleksandrov @ 2019-08-17 11:22 ` Nikolay Aleksandrov 2019-08-17 11:22 ` [PATCH net-next v3 2/4] net: bridge: mdb: factor out mdb filling Nikolay Aleksandrov ` (3 subsequent siblings) 4 siblings, 0 replies; 18+ messages in thread From: Nikolay Aleksandrov @ 2019-08-17 11:22 UTC (permalink / raw) To: netdev; +Cc: davem, roopa, bridge, Nikolay Aleksandrov Trivial patch to move the vlan comments in their proper places above the vid 0 checks. Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com> --- net/bridge/br_mdb.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c index 428af1abf8cc..ee6208c6d946 100644 --- a/net/bridge/br_mdb.c +++ b/net/bridge/br_mdb.c @@ -653,9 +653,6 @@ static int br_mdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, br = netdev_priv(dev); - /* If vlan filtering is enabled and VLAN is not specified - * install mdb entry on all vlans configured on the port. - */ pdev = __dev_get_by_index(net, entry->ifindex); if (!pdev) return -ENODEV; @@ -665,6 +662,9 @@ static int br_mdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, return -EINVAL; vg = nbp_vlan_group(p); + /* If vlan filtering is enabled and VLAN is not specified + * install mdb entry on all vlans configured on the port. + */ if (br_vlan_enabled(br->dev) && vg && entry->vid == 0) { list_for_each_entry(v, &vg->vlan_list, vlist) { entry->vid = v->vid; @@ -745,9 +745,6 @@ static int br_mdb_del(struct sk_buff *skb, struct nlmsghdr *nlh, br = netdev_priv(dev); - /* If vlan filtering is enabled and VLAN is not specified - * delete mdb entry on all vlans configured on the port. - */ pdev = __dev_get_by_index(net, entry->ifindex); if (!pdev) return -ENODEV; @@ -757,6 +754,9 @@ static int br_mdb_del(struct sk_buff *skb, struct nlmsghdr *nlh, return -EINVAL; vg = nbp_vlan_group(p); + /* If vlan filtering is enabled and VLAN is not specified + * delete mdb entry on all vlans configured on the port. + */ if (br_vlan_enabled(br->dev) && vg && entry->vid == 0) { list_for_each_entry(v, &vg->vlan_list, vlist) { entry->vid = v->vid; -- 2.21.0 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH net-next v3 2/4] net: bridge: mdb: factor out mdb filling 2019-08-17 11:22 ` [PATCH net-next v3 " Nikolay Aleksandrov 2019-08-17 11:22 ` [PATCH net-next v3 1/4] net: bridge: mdb: move vlan comments Nikolay Aleksandrov @ 2019-08-17 11:22 ` Nikolay Aleksandrov 2019-08-17 11:22 ` [PATCH net-next v3 3/4] net: bridge: mdb: dump host-joined entries as well Nikolay Aleksandrov ` (2 subsequent siblings) 4 siblings, 0 replies; 18+ messages in thread From: Nikolay Aleksandrov @ 2019-08-17 11:22 UTC (permalink / raw) To: netdev; +Cc: davem, roopa, bridge, Nikolay Aleksandrov We have to factor out the mdb fill portion in order to re-use it later for the bridge mdb entries. No functional changes intended. Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com> --- net/bridge/br_mdb.c | 68 ++++++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 31 deletions(-) diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c index ee6208c6d946..77730983097e 100644 --- a/net/bridge/br_mdb.c +++ b/net/bridge/br_mdb.c @@ -77,6 +77,40 @@ static void __mdb_entry_to_br_ip(struct br_mdb_entry *entry, struct br_ip *ip) #endif } +static int __mdb_fill_info(struct sk_buff *skb, + struct net_bridge_port_group *p) +{ + struct nlattr *nest_ent; + struct br_mdb_entry e; + + 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 IS_ENABLED(CONFIG_IPV6) + if (p->addr.proto == htons(ETH_P_IPV6)) + e.addr.u.ip6 = p->addr.u.ip6; +#endif + e.addr.proto = p->addr.proto; + nest_ent = nla_nest_start_noflag(skb, + MDBA_MDB_ENTRY_INFO); + if (!nest_ent) + return -EMSGSIZE; + + if (nla_put_nohdr(skb, sizeof(e), &e) || + nla_put_u32(skb, + MDBA_MDB_EATTR_TIMER, + br_timer_value(&p->timer))) { + nla_nest_cancel(skb, nest_ent); + return -EMSGSIZE; + } + nla_nest_end(skb, nest_ent); + + return 0; +} + static int br_mdb_fill_info(struct sk_buff *skb, struct netlink_callback *cb, struct net_device *dev) { @@ -95,7 +129,6 @@ static int br_mdb_fill_info(struct sk_buff *skb, struct netlink_callback *cb, hlist_for_each_entry_rcu(mp, &br->mdb_list, mdb_node) { struct net_bridge_port_group *p; struct net_bridge_port_group __rcu **pp; - struct net_bridge_port *port; if (idx < s_idx) goto skip; @@ -108,41 +141,14 @@ static int br_mdb_fill_info(struct sk_buff *skb, struct netlink_callback *cb, for (pp = &mp->ports; (p = rcu_dereference(*pp)) != NULL; pp = &p->next) { - struct nlattr *nest_ent; - struct br_mdb_entry e; - - port = p->port; - if (!port) + if (!p->port) continue; - memset(&e, 0, sizeof(e)); - e.ifindex = port->dev->ifindex; - e.vid = p->addr.vid; - __mdb_entry_fill_flags(&e, p->flags); - if (p->addr.proto == htons(ETH_P_IP)) - e.addr.u.ip4 = p->addr.u.ip4; -#if IS_ENABLED(CONFIG_IPV6) - if (p->addr.proto == htons(ETH_P_IPV6)) - e.addr.u.ip6 = p->addr.u.ip6; -#endif - e.addr.proto = p->addr.proto; - nest_ent = nla_nest_start_noflag(skb, - MDBA_MDB_ENTRY_INFO); - if (!nest_ent) { - nla_nest_cancel(skb, nest2); - err = -EMSGSIZE; - goto out; - } - if (nla_put_nohdr(skb, sizeof(e), &e) || - nla_put_u32(skb, - MDBA_MDB_EATTR_TIMER, - br_timer_value(&p->timer))) { - nla_nest_cancel(skb, nest_ent); + err = __mdb_fill_info(skb, p); + if (err) { nla_nest_cancel(skb, nest2); - err = -EMSGSIZE; goto out; } - nla_nest_end(skb, nest_ent); } nla_nest_end(skb, nest2); skip: -- 2.21.0 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH net-next v3 3/4] net: bridge: mdb: dump host-joined entries as well 2019-08-17 11:22 ` [PATCH net-next v3 " Nikolay Aleksandrov 2019-08-17 11:22 ` [PATCH net-next v3 1/4] net: bridge: mdb: move vlan comments Nikolay Aleksandrov 2019-08-17 11:22 ` [PATCH net-next v3 2/4] net: bridge: mdb: factor out mdb filling Nikolay Aleksandrov @ 2019-08-17 11:22 ` Nikolay Aleksandrov 2019-08-17 11:22 ` [PATCH net-next v3 4/4] net: bridge: mdb: allow add/delete for host-joined groups Nikolay Aleksandrov 2019-08-17 19:37 ` [PATCH net-next v3 0/4] net: bridge: mdb: allow dump/add/del of host-joined entries David Miller 4 siblings, 0 replies; 18+ messages in thread From: Nikolay Aleksandrov @ 2019-08-17 11:22 UTC (permalink / raw) To: netdev; +Cc: davem, roopa, bridge, Nikolay Aleksandrov 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> --- net/bridge/br_mdb.c | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c index 77730983097e..985273425117 100644 --- a/net/bridge/br_mdb.c +++ b/net/bridge/br_mdb.c @@ -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; -- 2.21.0 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [PATCH net-next v3 4/4] net: bridge: mdb: allow add/delete for host-joined groups 2019-08-17 11:22 ` [PATCH net-next v3 " Nikolay Aleksandrov ` (2 preceding siblings ...) 2019-08-17 11:22 ` [PATCH net-next v3 3/4] net: bridge: mdb: dump host-joined entries as well Nikolay Aleksandrov @ 2019-08-17 11:22 ` Nikolay Aleksandrov 2019-08-17 19:37 ` [PATCH net-next v3 0/4] net: bridge: mdb: allow dump/add/del of host-joined entries David Miller 4 siblings, 0 replies; 18+ messages in thread From: Nikolay Aleksandrov @ 2019-08-17 11:22 UTC (permalink / raw) To: netdev; +Cc: davem, roopa, bridge, Nikolay Aleksandrov Currently this is needed only for user-space compatibility, so similar object adds/deletes as the dumped ones would succeed. Later it can be used for L2 mcast MAC add/delete. v3: fix compiler warning (DaveM) v2: don't send a notification when used from user-space, arm the group timer if no ports are left after host entry del Signed-off-by: Nikolay Aleksandrov <nikolay@cumulusnetworks.com> --- net/bridge/br_mdb.c | 78 +++++++++++++++++++++++++++------------ net/bridge/br_multicast.c | 30 +++++++++++---- net/bridge/br_private.h | 2 + 3 files changed, 80 insertions(+), 30 deletions(-) diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c index 985273425117..44594635a972 100644 --- a/net/bridge/br_mdb.c +++ b/net/bridge/br_mdb.c @@ -616,6 +616,19 @@ static int br_mdb_add_group(struct net_bridge *br, struct net_bridge_port *port, return err; } + /* host join */ + if (!port) { + /* don't allow any flags for host-joined groups */ + if (state) + return -EINVAL; + if (mp->host_joined) + return -EEXIST; + + br_multicast_host_join(mp, false); + + return 0; + } + for (pp = &mp->ports; (p = mlock_dereference(*pp, br)) != NULL; pp = &p->next) { @@ -640,19 +653,21 @@ static int __br_mdb_add(struct net *net, struct net_bridge *br, { struct br_ip ip; struct net_device *dev; - struct net_bridge_port *p; + struct net_bridge_port *p = NULL; int ret; if (!netif_running(br->dev) || !br_opt_get(br, BROPT_MULTICAST_ENABLED)) return -EINVAL; - dev = __dev_get_by_index(net, entry->ifindex); - if (!dev) - return -ENODEV; + if (entry->ifindex != br->dev->ifindex) { + dev = __dev_get_by_index(net, entry->ifindex); + if (!dev) + return -ENODEV; - p = br_port_get_rtnl(dev); - if (!p || p->br != br || p->state == BR_STATE_DISABLED) - return -EINVAL; + p = br_port_get_rtnl(dev); + if (!p || p->br != br || p->state == BR_STATE_DISABLED) + return -EINVAL; + } __mdb_entry_to_br_ip(entry, &ip); @@ -667,9 +682,9 @@ static int br_mdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, { struct net *net = sock_net(skb->sk); struct net_bridge_vlan_group *vg; + struct net_bridge_port *p = NULL; struct net_device *dev, *pdev; struct br_mdb_entry *entry; - struct net_bridge_port *p; struct net_bridge_vlan *v; struct net_bridge *br; int err; @@ -680,15 +695,19 @@ static int br_mdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, br = netdev_priv(dev); - pdev = __dev_get_by_index(net, entry->ifindex); - if (!pdev) - return -ENODEV; + if (entry->ifindex != br->dev->ifindex) { + pdev = __dev_get_by_index(net, entry->ifindex); + if (!pdev) + return -ENODEV; - p = br_port_get_rtnl(pdev); - if (!p || p->br != br || p->state == BR_STATE_DISABLED) - return -EINVAL; + p = br_port_get_rtnl(pdev); + if (!p || p->br != br || p->state == BR_STATE_DISABLED) + return -EINVAL; + vg = nbp_vlan_group(p); + } else { + vg = br_vlan_group(br); + } - vg = nbp_vlan_group(p); /* If vlan filtering is enabled and VLAN is not specified * install mdb entry on all vlans configured on the port. */ @@ -727,6 +746,15 @@ static int __br_mdb_del(struct net_bridge *br, struct br_mdb_entry *entry) if (!mp) goto unlock; + /* host leave */ + if (entry->ifindex == mp->br->dev->ifindex && mp->host_joined) { + br_multicast_host_leave(mp, false); + err = 0; + if (!mp->ports && netif_running(br->dev)) + mod_timer(&mp->timer, jiffies); + goto unlock; + } + for (pp = &mp->ports; (p = mlock_dereference(*pp, br)) != NULL; pp = &p->next) { @@ -759,9 +787,9 @@ static int br_mdb_del(struct sk_buff *skb, struct nlmsghdr *nlh, { struct net *net = sock_net(skb->sk); struct net_bridge_vlan_group *vg; + struct net_bridge_port *p = NULL; struct net_device *dev, *pdev; struct br_mdb_entry *entry; - struct net_bridge_port *p; struct net_bridge_vlan *v; struct net_bridge *br; int err; @@ -772,15 +800,19 @@ static int br_mdb_del(struct sk_buff *skb, struct nlmsghdr *nlh, br = netdev_priv(dev); - pdev = __dev_get_by_index(net, entry->ifindex); - if (!pdev) - return -ENODEV; + if (entry->ifindex != br->dev->ifindex) { + pdev = __dev_get_by_index(net, entry->ifindex); + if (!pdev) + return -ENODEV; - p = br_port_get_rtnl(pdev); - if (!p || p->br != br || p->state == BR_STATE_DISABLED) - return -EINVAL; + p = br_port_get_rtnl(pdev); + if (!p || p->br != br || p->state == BR_STATE_DISABLED) + return -EINVAL; + vg = nbp_vlan_group(p); + } else { + vg = br_vlan_group(br); + } - vg = nbp_vlan_group(p); /* If vlan filtering is enabled and VLAN is not specified * delete mdb entry on all vlans configured on the port. */ diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 9b379e110129..ad12fe3fca8c 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -148,8 +148,7 @@ static void br_multicast_group_expired(struct timer_list *t) if (!netif_running(br->dev) || timer_pending(&mp->timer)) goto out; - mp->host_joined = false; - br_mdb_notify(br->dev, NULL, &mp->addr, RTM_DELMDB, 0); + br_multicast_host_leave(mp, true); if (mp->ports) goto out; @@ -512,6 +511,27 @@ static bool br_port_group_equal(struct net_bridge_port_group *p, return ether_addr_equal(src, p->eth_addr); } +void br_multicast_host_join(struct net_bridge_mdb_entry *mp, bool notify) +{ + if (!mp->host_joined) { + mp->host_joined = true; + if (notify) + br_mdb_notify(mp->br->dev, NULL, &mp->addr, + RTM_NEWMDB, 0); + } + mod_timer(&mp->timer, jiffies + mp->br->multicast_membership_interval); +} + +void br_multicast_host_leave(struct net_bridge_mdb_entry *mp, bool notify) +{ + if (!mp->host_joined) + return; + + mp->host_joined = false; + if (notify) + br_mdb_notify(mp->br->dev, NULL, &mp->addr, RTM_DELMDB, 0); +} + static int br_multicast_add_group(struct net_bridge *br, struct net_bridge_port *port, struct br_ip *group, @@ -534,11 +554,7 @@ static int br_multicast_add_group(struct net_bridge *br, goto err; if (!port) { - if (!mp->host_joined) { - mp->host_joined = true; - br_mdb_notify(br->dev, NULL, &mp->addr, RTM_NEWMDB, 0); - } - mod_timer(&mp->timer, now + br->multicast_membership_interval); + br_multicast_host_join(mp, true); goto out; } diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index b7a4942ff1b3..ce2ab14ee605 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -702,6 +702,8 @@ void br_multicast_get_stats(const struct net_bridge *br, struct br_mcast_stats *dest); void br_mdb_init(void); void br_mdb_uninit(void); +void br_multicast_host_join(struct net_bridge_mdb_entry *mp, bool notify); +void br_multicast_host_leave(struct net_bridge_mdb_entry *mp, bool notify); #define mlock_dereference(X, br) \ rcu_dereference_protected(X, lockdep_is_held(&br->multicast_lock)) -- 2.21.0 ^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH net-next v3 0/4] net: bridge: mdb: allow dump/add/del of host-joined entries 2019-08-17 11:22 ` [PATCH net-next v3 " Nikolay Aleksandrov ` (3 preceding siblings ...) 2019-08-17 11:22 ` [PATCH net-next v3 4/4] net: bridge: mdb: allow add/delete for host-joined groups Nikolay Aleksandrov @ 2019-08-17 19:37 ` David Miller 4 siblings, 0 replies; 18+ messages in thread From: David Miller @ 2019-08-17 19:37 UTC (permalink / raw) To: nikolay; +Cc: netdev, roopa, bridge From: Nikolay Aleksandrov <nikolay@cumulusnetworks.com> Date: Sat, 17 Aug 2019 14:22:09 +0300 > This set makes the bridge dump host-joined mdb entries, they should be > treated as normal entries since they take a slot and are aging out. > We already have notifications for them but we couldn't dump them until > now so they remained hidden. We dump them similar to how they're > notified, in order to keep user-space compatibility with the dumped > objects (e.g. iproute2 dumps mdbs in a format which can be fed into > add/del commands) we allow host-joined groups also to be added/deleted via > mdb commands. That can later be used for L2 mcast MAC manipulation as > was recently discussed. Note that iproute2 changes are not necessary, > this set will work with the current user-space mdb code. > > Patch 01 - a trivial comment move > Patch 02 - factors out the mdb filling code so it can be > re-used for the host-joined entries > Patch 03 - dumps host-joined entries > Patch 04 - allows manipulation of host-joined entries via standard mdb > calls > > v3: fix compiler warning in patch 04 (DaveM) > v2: change patch 04 to avoid double notification and improve host group > manual removal if no ports are present in the group Series applied. ^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2019-08-17 19:37 UTC | newest] Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2019-08-14 14:40 [PATCH net-next 0/4] net: bridge: mdb: allow dump/add/del of host-joined entries Nikolay Aleksandrov 2019-08-14 14:40 ` [PATCH net-next 1/4] net: bridge: mdb: move vlan comments Nikolay Aleksandrov 2019-08-14 14:40 ` [PATCH net-next 2/4] net: bridge: mdb: factor out mdb filling Nikolay Aleksandrov 2019-08-14 14:40 ` [PATCH net-next 3/4] net: bridge: mdb: dump host-joined entries as well Nikolay Aleksandrov 2019-08-14 14:40 ` [PATCH net-next 4/4] net: bridge: mdb: allow add/delete for host-joined groups Nikolay Aleksandrov 2019-08-14 16:01 ` [PATCH net-next 0/4] net: bridge: mdb: allow dump/add/del of host-joined entries Nikolay Aleksandrov 2019-08-14 17:04 ` [PATCH net-next v2 " Nikolay Aleksandrov 2019-08-14 17:04 ` [PATCH net-next v2 1/4] net: bridge: mdb: move vlan comments Nikolay Aleksandrov 2019-08-14 17:04 ` [PATCH net-next v2 2/4] net: bridge: mdb: factor out mdb filling Nikolay Aleksandrov 2019-08-14 17:05 ` [PATCH net-next v2 3/4] net: bridge: mdb: dump host-joined entries as well Nikolay Aleksandrov 2019-08-14 17:05 ` [PATCH net-next v2 4/4] net: bridge: mdb: allow add/delete for host-joined groups Nikolay Aleksandrov 2019-08-16 20:04 ` [PATCH net-next v2 0/4] net: bridge: mdb: allow dump/add/del of host-joined entries David Miller 2019-08-17 11:22 ` [PATCH net-next v3 " Nikolay Aleksandrov 2019-08-17 11:22 ` [PATCH net-next v3 1/4] net: bridge: mdb: move vlan comments Nikolay Aleksandrov 2019-08-17 11:22 ` [PATCH net-next v3 2/4] net: bridge: mdb: factor out mdb filling Nikolay Aleksandrov 2019-08-17 11:22 ` [PATCH net-next v3 3/4] net: bridge: mdb: dump host-joined entries as well Nikolay Aleksandrov 2019-08-17 11:22 ` [PATCH net-next v3 4/4] net: bridge: mdb: allow add/delete for host-joined groups Nikolay Aleksandrov 2019-08-17 19:37 ` [PATCH net-next v3 0/4] net: bridge: mdb: allow dump/add/del of host-joined entries David Miller
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).