Commit 77041420 authored by Yotam Gigi's avatar Yotam Gigi Committed by David S. Miller

net: bridge: Notify on bridge device mrouter state changes

Add the SWITCHDEV_ATTR_ID_BRIDGE_MROUTER switchdev notification type, used
to indicate whether the bridge is or isn't mrouter. Notify when the bridge
changes its state, similarly to the already existing bridged port mrouter
notifications.

The notification uses the switchdev_attr.u.mrouter boolean flag to indicate
the current bridge mrouter status. Thus, it only indicates whether the
bridge is currently used as an mrouter or not, and does not indicate the
exact mrouter state of the bridge (learning, permanent, etc.).
Signed-off-by: default avatarYotam Gigi <yotamg@mellanox.com>
Signed-off-by: default avatarJiri Pirko <jiri@mellanox.com>
Signed-off-by: default avatarNikolay Aleksandrov <nikolay@cumulusnetworks.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 31070e7f
...@@ -51,6 +51,7 @@ enum switchdev_attr_id { ...@@ -51,6 +51,7 @@ enum switchdev_attr_id {
SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME, SWITCHDEV_ATTR_ID_BRIDGE_AGEING_TIME,
SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING, SWITCHDEV_ATTR_ID_BRIDGE_VLAN_FILTERING,
SWITCHDEV_ATTR_ID_BRIDGE_MC_DISABLED, SWITCHDEV_ATTR_ID_BRIDGE_MC_DISABLED,
SWITCHDEV_ATTR_ID_BRIDGE_MROUTER,
}; };
struct switchdev_attr { struct switchdev_attr {
......
...@@ -859,8 +859,32 @@ static void br_multicast_router_expired(unsigned long data) ...@@ -859,8 +859,32 @@ static void br_multicast_router_expired(unsigned long data)
spin_unlock(&br->multicast_lock); spin_unlock(&br->multicast_lock);
} }
static void br_mc_router_state_change(struct net_bridge *p,
bool is_mc_router)
{
struct switchdev_attr attr = {
.orig_dev = p->dev,
.id = SWITCHDEV_ATTR_ID_BRIDGE_MROUTER,
.flags = SWITCHDEV_F_DEFER,
.u.mrouter = is_mc_router,
};
switchdev_port_attr_set(p->dev, &attr);
}
static void br_multicast_local_router_expired(unsigned long data) static void br_multicast_local_router_expired(unsigned long data)
{ {
struct net_bridge *br = (struct net_bridge *)data;
spin_lock(&br->multicast_lock);
if (br->multicast_router == MDB_RTR_TYPE_DISABLED ||
br->multicast_router == MDB_RTR_TYPE_PERM ||
timer_pending(&br->multicast_router_timer))
goto out;
br_mc_router_state_change(br, false);
out:
spin_unlock(&br->multicast_lock);
} }
static void br_multicast_querier_expired(struct net_bridge *br, static void br_multicast_querier_expired(struct net_bridge *br,
...@@ -1364,9 +1388,12 @@ static void br_multicast_mark_router(struct net_bridge *br, ...@@ -1364,9 +1388,12 @@ static void br_multicast_mark_router(struct net_bridge *br,
unsigned long now = jiffies; unsigned long now = jiffies;
if (!port) { if (!port) {
if (br->multicast_router == MDB_RTR_TYPE_TEMP_QUERY) if (br->multicast_router == MDB_RTR_TYPE_TEMP_QUERY) {
if (!timer_pending(&br->multicast_router_timer))
br_mc_router_state_change(br, true);
mod_timer(&br->multicast_router_timer, mod_timer(&br->multicast_router_timer,
now + br->multicast_querier_interval); now + br->multicast_querier_interval);
}
return; return;
} }
...@@ -1952,7 +1979,7 @@ void br_multicast_init(struct net_bridge *br) ...@@ -1952,7 +1979,7 @@ void br_multicast_init(struct net_bridge *br)
spin_lock_init(&br->multicast_lock); spin_lock_init(&br->multicast_lock);
setup_timer(&br->multicast_router_timer, setup_timer(&br->multicast_router_timer,
br_multicast_local_router_expired, 0); br_multicast_local_router_expired, (unsigned long)br);
setup_timer(&br->ip4_other_query.timer, setup_timer(&br->ip4_other_query.timer,
br_ip4_multicast_querier_expired, (unsigned long)br); br_ip4_multicast_querier_expired, (unsigned long)br);
setup_timer(&br->ip4_own_query.timer, br_ip4_multicast_query_expired, setup_timer(&br->ip4_own_query.timer, br_ip4_multicast_query_expired,
...@@ -2042,9 +2069,14 @@ int br_multicast_set_router(struct net_bridge *br, unsigned long val) ...@@ -2042,9 +2069,14 @@ int br_multicast_set_router(struct net_bridge *br, unsigned long val)
switch (val) { switch (val) {
case MDB_RTR_TYPE_DISABLED: case MDB_RTR_TYPE_DISABLED:
case MDB_RTR_TYPE_PERM: case MDB_RTR_TYPE_PERM:
br_mc_router_state_change(br, val == MDB_RTR_TYPE_PERM);
del_timer(&br->multicast_router_timer); del_timer(&br->multicast_router_timer);
/* fall through */ br->multicast_router = val;
err = 0;
break;
case MDB_RTR_TYPE_TEMP_QUERY: case MDB_RTR_TYPE_TEMP_QUERY:
if (br->multicast_router != MDB_RTR_TYPE_TEMP_QUERY)
br_mc_router_state_change(br, false);
br->multicast_router = val; br->multicast_router = val;
err = 0; err = 0;
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment