Skip to content

Commit

Permalink
Merge branch 'bridge-mcast-tmp-router-port'
Browse files Browse the repository at this point in the history
Nikolay Aleksandrov says:

====================
bridge: mcast: add support for temp router port

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
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Mar 1, 2016
2 parents ec1606c + 59f78f9 commit 4ec6207
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 32 deletions.
22 changes: 21 additions & 1 deletion include/uapi/linux/if_bridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,10 @@ struct bridge_vlan_info {
* }
* }
* [MDBA_ROUTER] = {
* [MDBA_ROUTER_PORT]
* [MDBA_ROUTER_PORT] = {
* u32 ifindex
* [MDBA_ROUTER_PATTR attributes]
* }
* }
*/
enum {
Expand Down Expand Up @@ -177,13 +180,30 @@ 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,
MDB_RTR_TYPE_TEMP
};

enum {
MDBA_ROUTER_UNSPEC,
MDBA_ROUTER_PORT,
__MDBA_ROUTER_MAX,
};
#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;
Expand Down
16 changes: 14 additions & 2 deletions net/bridge/br_mdb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand Down
83 changes: 54 additions & 29 deletions net/bridge/br_multicast.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 != 1 ||
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);
Expand Down Expand Up @@ -912,7 +916,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);
Expand Down Expand Up @@ -959,7 +963,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:
Expand All @@ -980,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);
Expand Down Expand Up @@ -1227,13 +1235,14 @@ 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_DISABLED ||
port->multicast_router == MDB_RTR_TYPE_PERM)
return;

br_multicast_add_router(br, port);
Expand Down Expand Up @@ -1713,7 +1722,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;
Expand Down Expand Up @@ -1823,11 +1832,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;
Expand All @@ -1838,37 +1847,53 @@ 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;
unsigned long now = jiffies;
int err = -EINVAL;

spin_lock(&br->multicast_lock);

switch (val) {
case 0:
case 1:
case 2:
p->multicast_router = val;
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;

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;

goto unlock;
}
switch (val) {
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;
case MDB_RTR_TYPE_TEMP:
p->multicast_router = MDB_RTR_TYPE_TEMP;
br_multicast_mark_router(br, p);
break;
default:
goto unlock;
}

err = 0;
unlock:
spin_unlock(&br->multicast_lock);

return err;
Expand Down

0 comments on commit 4ec6207

Please sign in to comment.