Nikolay Aleksandrov
2016-Feb-26 20:20 UTC
[Bridge] [PATCH net-next v2 0/4] bridge: mcast: add support for temp router port
Hi, This set adds support for temporary router port which doesn't depend only on the incoming queries. It can be refreshed by setting multicast_router to the same value (3). The first two patches are minor changes that prepare the code for the third which adds this new type of router port. In order to be able to dump its information the mdb router port format is changed in patch 04 and extended similar to how mdb entries format was done recently. The related iproute2 changes will be posted if this is accepted. v2: set val first and adjust router type later in patch 01, patch 03 was split in 2 Thanks, Nik Nikolay Aleksandrov (4): bridge: mcast: use names for the different multicast_router types bridge: mcast: do nothing if port's multicast_router is set to the same val bridge: mcast: add support for temporary port router bridge: mcast: add support for more router port information dumping include/uapi/linux/if_bridge.h | 22 ++++++++++- net/bridge/br_mdb.c | 16 +++++++- net/bridge/br_multicast.c | 83 +++++++++++++++++++++++++++--------------- 3 files changed, 89 insertions(+), 32 deletions(-) -- 2.4.3
Nikolay Aleksandrov
2016-Feb-26 20:20 UTC
[Bridge] [PATCH net-next v2 1/4] bridge: mcast: use names for the different multicast_router types
Using raw values makes it difficult to extend and also understand the code, give them names and do explicit per-option manipulation in br_multicast_set_port_router. Signed-off-by: Nikolay Aleksandrov <nikolay at cumulusnetworks.com> --- v2: set multicast_router first include/uapi/linux/if_bridge.h | 7 +++++ net/bridge/br_multicast.c | 61 +++++++++++++++++++++++------------------- 2 files changed, 40 insertions(+), 28 deletions(-) diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h index 610932b477c4..f2764b739f38 100644 --- a/include/uapi/linux/if_bridge.h +++ b/include/uapi/linux/if_bridge.h @@ -194,6 +194,13 @@ enum { }; #define MDBA_MDB_EATTR_MAX (__MDBA_MDB_EATTR_MAX - 1) +/* multicast router types */ +enum { + MDB_RTR_TYPE_DISABLED, + MDB_RTR_TYPE_TEMP_QUERY, + MDB_RTR_TYPE_PERM, +}; + enum { MDBA_ROUTER_UNSPEC, MDBA_ROUTER_PORT, diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 8b6e4249be1b..71c109b0943f 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -759,7 +759,7 @@ static void br_multicast_router_expired(unsigned long data) struct net_bridge *br = port->br; spin_lock(&br->multicast_lock); - if (port->multicast_router != 1 || + if (port->multicast_router != MDB_RTR_TYPE_TEMP_QUERY || timer_pending(&port->multicast_router_timer) || hlist_unhashed(&port->rlist)) goto out; @@ -912,7 +912,7 @@ static void br_ip6_multicast_port_query_expired(unsigned long data) void br_multicast_add_port(struct net_bridge_port *port) { - port->multicast_router = 1; + port->multicast_router = MDB_RTR_TYPE_TEMP_QUERY; setup_timer(&port->multicast_router_timer, br_multicast_router_expired, (unsigned long)port); @@ -959,7 +959,8 @@ void br_multicast_enable_port(struct net_bridge_port *port) #if IS_ENABLED(CONFIG_IPV6) br_multicast_enable(&port->ip6_own_query); #endif - if (port->multicast_router == 2 && hlist_unhashed(&port->rlist)) + if (port->multicast_router == MDB_RTR_TYPE_PERM && + hlist_unhashed(&port->rlist)) br_multicast_add_router(br, port); out: @@ -1227,13 +1228,13 @@ static void br_multicast_mark_router(struct net_bridge *br, unsigned long now = jiffies; if (!port) { - if (br->multicast_router == 1) + if (br->multicast_router == MDB_RTR_TYPE_TEMP_QUERY) mod_timer(&br->multicast_router_timer, now + br->multicast_querier_interval); return; } - if (port->multicast_router != 1) + if (port->multicast_router != MDB_RTR_TYPE_TEMP_QUERY) return; br_multicast_add_router(br, port); @@ -1713,7 +1714,7 @@ void br_multicast_init(struct net_bridge *br) br->hash_elasticity = 4; br->hash_max = 512; - br->multicast_router = 1; + br->multicast_router = MDB_RTR_TYPE_TEMP_QUERY; br->multicast_querier = 0; br->multicast_query_use_ifaddr = 0; br->multicast_last_member_count = 2; @@ -1823,11 +1824,11 @@ int br_multicast_set_router(struct net_bridge *br, unsigned long val) spin_lock_bh(&br->multicast_lock); switch (val) { - case 0: - case 2: + case MDB_RTR_TYPE_DISABLED: + case MDB_RTR_TYPE_PERM: del_timer(&br->multicast_router_timer); /* fall through */ - case 1: + case MDB_RTR_TYPE_TEMP_QUERY: br->multicast_router = val; err = 0; break; @@ -1838,6 +1839,14 @@ int br_multicast_set_router(struct net_bridge *br, unsigned long val) return err; } +static void __del_port_router(struct net_bridge_port *p) +{ + if (hlist_unhashed(&p->rlist)) + return; + hlist_del_init_rcu(&p->rlist); + br_rtr_notify(p->br->dev, p, RTM_DELMDB); +} + int br_multicast_set_port_router(struct net_bridge_port *p, unsigned long val) { struct net_bridge *br = p->br; @@ -1846,29 +1855,25 @@ int br_multicast_set_port_router(struct net_bridge_port *p, unsigned long val) spin_lock(&br->multicast_lock); switch (val) { - case 0: - case 1: - case 2: - p->multicast_router = val; - err = 0; - - if (val < 2 && !hlist_unhashed(&p->rlist)) { - hlist_del_init_rcu(&p->rlist); - br_rtr_notify(br->dev, p, RTM_DELMDB); - } - - if (val == 1) - break; - + case MDB_RTR_TYPE_DISABLED: + p->multicast_router = MDB_RTR_TYPE_DISABLED; + __del_port_router(p); + del_timer(&p->multicast_router_timer); + break; + case MDB_RTR_TYPE_TEMP_QUERY: + p->multicast_router = MDB_RTR_TYPE_TEMP_QUERY; + __del_port_router(p); + break; + case MDB_RTR_TYPE_PERM: + p->multicast_router = MDB_RTR_TYPE_PERM; del_timer(&p->multicast_router_timer); - - if (val == 0) - break; - br_multicast_add_router(br, p); break; + default: + goto unlock; } - + err = 0; +unlock: spin_unlock(&br->multicast_lock); return err; -- 2.4.3
Nikolay Aleksandrov
2016-Feb-26 20:20 UTC
[Bridge] [PATCH net-next v2 2/4] bridge: mcast: do nothing if port's multicast_router is set to the same val
This is needed for the upcoming temporary port router. There's no point to go through the logic if the value is the same. Signed-off-by: Nikolay Aleksandrov <nikolay at cumulusnetworks.com> --- v2: no change net/bridge/br_multicast.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 71c109b0943f..f1140cf5168d 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -1853,7 +1853,10 @@ int br_multicast_set_port_router(struct net_bridge_port *p, unsigned long val) int err = -EINVAL; spin_lock(&br->multicast_lock); - + if (p->multicast_router == val) { + err = 0; + goto unlock; + } switch (val) { case MDB_RTR_TYPE_DISABLED: p->multicast_router = MDB_RTR_TYPE_DISABLED; -- 2.4.3
Nikolay Aleksandrov
2016-Feb-26 20:20 UTC
[Bridge] [PATCH net-next v2 3/4] bridge: mcast: add support for temporary port router
Add support for a temporary router port which doesn't depend only on the incoming query. It can be refreshed if set to the same value, which is a no-op for the rest. Signed-off-by: Nikolay Aleksandrov <nikolay at cumulusnetworks.com> --- v2: split in two, this only adds the new temp router port type include/uapi/linux/if_bridge.h | 1 + net/bridge/br_multicast.c | 21 +++++++++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h index f2764b739f38..b281d02051cc 100644 --- a/include/uapi/linux/if_bridge.h +++ b/include/uapi/linux/if_bridge.h @@ -199,6 +199,7 @@ enum { MDB_RTR_TYPE_DISABLED, MDB_RTR_TYPE_TEMP_QUERY, MDB_RTR_TYPE_PERM, + MDB_RTR_TYPE_TEMP }; enum { diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index f1140cf5168d..a4c15df2b792 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -759,13 +759,17 @@ static void br_multicast_router_expired(unsigned long data) struct net_bridge *br = port->br; spin_lock(&br->multicast_lock); - if (port->multicast_router != MDB_RTR_TYPE_TEMP_QUERY || + if (port->multicast_router == MDB_RTR_TYPE_DISABLED || + port->multicast_router == MDB_RTR_TYPE_PERM || timer_pending(&port->multicast_router_timer) || hlist_unhashed(&port->rlist)) goto out; hlist_del_init_rcu(&port->rlist); br_rtr_notify(br->dev, port, RTM_DELMDB); + /* Don't allow timer refresh if the router expired */ + if (port->multicast_router == MDB_RTR_TYPE_TEMP) + port->multicast_router = MDB_RTR_TYPE_TEMP_QUERY; out: spin_unlock(&br->multicast_lock); @@ -981,6 +985,9 @@ void br_multicast_disable_port(struct net_bridge_port *port) if (!hlist_unhashed(&port->rlist)) { hlist_del_init_rcu(&port->rlist); br_rtr_notify(br->dev, port, RTM_DELMDB); + /* Don't allow timer refresh if disabling */ + if (port->multicast_router == MDB_RTR_TYPE_TEMP) + port->multicast_router = MDB_RTR_TYPE_TEMP_QUERY; } del_timer(&port->multicast_router_timer); del_timer(&port->ip4_own_query.timer); @@ -1234,7 +1241,8 @@ static void br_multicast_mark_router(struct net_bridge *br, return; } - if (port->multicast_router != MDB_RTR_TYPE_TEMP_QUERY) + if (port->multicast_router == MDB_RTR_TYPE_DISABLED || + port->multicast_router == MDB_RTR_TYPE_PERM) return; br_multicast_add_router(br, port); @@ -1850,10 +1858,15 @@ static void __del_port_router(struct net_bridge_port *p) int br_multicast_set_port_router(struct net_bridge_port *p, unsigned long val) { struct net_bridge *br = p->br; + unsigned long now = jiffies; int err = -EINVAL; spin_lock(&br->multicast_lock); if (p->multicast_router == val) { + /* Refresh the temp router port timer */ + if (p->multicast_router == MDB_RTR_TYPE_TEMP) + mod_timer(&p->multicast_router_timer, + now + br->multicast_querier_interval); err = 0; goto unlock; } @@ -1872,6 +1885,10 @@ int br_multicast_set_port_router(struct net_bridge_port *p, unsigned long val) del_timer(&p->multicast_router_timer); br_multicast_add_router(br, p); break; + case MDB_RTR_TYPE_TEMP: + p->multicast_router = MDB_RTR_TYPE_TEMP; + br_multicast_mark_router(br, p); + break; default: goto unlock; } -- 2.4.3
Nikolay Aleksandrov
2016-Feb-26 20:20 UTC
[Bridge] [PATCH net-next v2 4/4] bridge: mcast: add support for more router port information dumping
Allow for more multicast router port information to be dumped such as timer and type attributes. For that that purpose we need to extend the MDBA_ROUTER_PORT attribute similar to how it was done for the mdb entries recently. The new format is thus: [MDBA_ROUTER_PORT] = { <- nested attribute u32 ifindex <- router port ifindex for user-space compatibility [MDBA_ROUTER_PATTR attributes] } This way it remains compatible with older users (they'll simply retrieve the u32 in the beginning) and new users can parse the remaining attributes. It would also allow to add future extensions to the router port without breaking compatibility. Signed-off-by: Nikolay Aleksandrov <nikolay at cumulusnetworks.com> --- v2: new patch, adds the extended router port netlink information include/uapi/linux/if_bridge.h | 14 +++++++++++++- net/bridge/br_mdb.c | 16 ++++++++++++++-- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/include/uapi/linux/if_bridge.h b/include/uapi/linux/if_bridge.h index b281d02051cc..af98f6855b7e 100644 --- a/include/uapi/linux/if_bridge.h +++ b/include/uapi/linux/if_bridge.h @@ -161,7 +161,10 @@ enum { * } * } * [MDBA_ROUTER] = { - * [MDBA_ROUTER_PORT] + * [MDBA_ROUTER_PORT] = { + * u32 ifindex + * [MDBA_ROUTER_PATTR attributes] + * } * } */ enum { @@ -209,6 +212,15 @@ enum { }; #define MDBA_ROUTER_MAX (__MDBA_ROUTER_MAX - 1) +/* router port attributes */ +enum { + MDBA_ROUTER_PATTR_UNSPEC, + MDBA_ROUTER_PATTR_TIMER, + MDBA_ROUTER_PATTR_TYPE, + __MDBA_ROUTER_PATTR_MAX +}; +#define MDBA_ROUTER_PATTR_MAX (__MDBA_ROUTER_PATTR_MAX - 1) + struct br_port_msg { __u8 family; __u32 ifindex; diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c index 73786e2fe065..253bc77eda3b 100644 --- a/net/bridge/br_mdb.c +++ b/net/bridge/br_mdb.c @@ -20,7 +20,7 @@ static int br_rports_fill_info(struct sk_buff *skb, struct netlink_callback *cb, { struct net_bridge *br = netdev_priv(dev); struct net_bridge_port *p; - struct nlattr *nest; + struct nlattr *nest, *port_nest; if (!br->multicast_router || hlist_empty(&br->router_list)) return 0; @@ -30,8 +30,20 @@ static int br_rports_fill_info(struct sk_buff *skb, struct netlink_callback *cb, return -EMSGSIZE; hlist_for_each_entry_rcu(p, &br->router_list, rlist) { - if (p && nla_put_u32(skb, MDBA_ROUTER_PORT, p->dev->ifindex)) + if (!p) + continue; + port_nest = nla_nest_start(skb, MDBA_ROUTER_PORT); + if (!port_nest) goto fail; + if (nla_put_nohdr(skb, sizeof(u32), &p->dev->ifindex) || + nla_put_u32(skb, MDBA_ROUTER_PATTR_TIMER, + br_timer_value(&p->multicast_router_timer)) || + nla_put_u8(skb, MDBA_ROUTER_PATTR_TYPE, + p->multicast_router)) { + nla_nest_cancel(skb, port_nest); + goto fail; + } + nla_nest_end(skb, port_nest); } nla_nest_end(skb, nest); -- 2.4.3
David Miller
2016-Mar-01 21:55 UTC
[Bridge] [PATCH net-next v2 0/4] bridge: mcast: add support for temp router port
From: Nikolay Aleksandrov <nikolay at cumulusnetworks.com> Date: Fri, 26 Feb 2016 21:20:00 +0100> This set adds support for temporary router port which doesn't depend only > on the incoming queries. It can be refreshed by setting multicast_router to > the same value (3). The first two patches are minor changes that prepare > the code for the third which adds this new type of router port. > In order to be able to dump its information the mdb router port format > is changed in patch 04 and extended similar to how mdb entries format was > done recently. > The related iproute2 changes will be posted if this is accepted. > > v2: set val first and adjust router type later in patch 01, patch 03 was > split in 2Series applied, thanks Nik.