From 7aa38018be1fa4cff3e631f26bc821086ba90d29 Mon Sep 17 00:00:00 2001 From: Horatiu Vultur Date: Thu, 21 May 2020 23:19:05 +0000 Subject: [PATCH 1/3] bridge: mrp: Add br_mrp_unique_ifindex function It is not allow to have the same net bridge port part of multiple MRP rings. Therefore add a check if the port is used already in a different MRP. In that case return failure. Fixes: 9a9f26e8f7ea ("bridge: mrp: Connect MRP API with the switchdev API") Signed-off-by: Horatiu Vultur Signed-off-by: David S. Miller --- net/bridge/br_mrp.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/net/bridge/br_mrp.c b/net/bridge/br_mrp.c index d7bc09de4c13..854e31bf0151 100644 --- a/net/bridge/br_mrp.c +++ b/net/bridge/br_mrp.c @@ -37,6 +37,26 @@ static struct br_mrp *br_mrp_find_id(struct net_bridge *br, u32 ring_id) return res; } +static bool br_mrp_unique_ifindex(struct net_bridge *br, u32 ifindex) +{ + struct br_mrp *mrp; + + list_for_each_entry_rcu(mrp, &br->mrp_list, list, + lockdep_rtnl_is_held()) { + struct net_bridge_port *p; + + p = rtnl_dereference(mrp->p_port); + if (p && p->dev->ifindex == ifindex) + return false; + + p = rtnl_dereference(mrp->s_port); + if (p && p->dev->ifindex == ifindex) + return false; + } + + return true; +} + static struct br_mrp *br_mrp_find_port(struct net_bridge *br, struct net_bridge_port *p) { @@ -255,6 +275,11 @@ int br_mrp_add(struct net_bridge *br, struct br_mrp_instance *instance) !br_mrp_get_port(br, instance->s_ifindex)) return -EINVAL; + /* It is not possible to have the same port part of multiple rings */ + if (!br_mrp_unique_ifindex(br, instance->p_ifindex) || + !br_mrp_unique_ifindex(br, instance->s_ifindex)) + return -EINVAL; + mrp = kzalloc(sizeof(*mrp), GFP_KERNEL); if (!mrp) return -ENOMEM; From 89c1e111cb4860b51efef50474cd259c2702edc6 Mon Sep 17 00:00:00 2001 From: Horatiu Vultur Date: Thu, 21 May 2020 23:19:06 +0000 Subject: [PATCH 2/3] switchdev: mrp: Remove the variable mrp_ring_state Remove the variable mrp_ring_state from switchdev_attr because is not used anywhere. The ring state is set using SWITCHDEV_OBJ_ID_RING_STATE_MRP. Fixes: c284b5459008 ("switchdev: mrp: Extend switchdev API to offload MRP") Acked-by: Ivan Vecera Signed-off-by: Horatiu Vultur Signed-off-by: David S. Miller --- include/net/switchdev.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/net/switchdev.h b/include/net/switchdev.h index ae7aeb0d1f9c..db519957e134 100644 --- a/include/net/switchdev.h +++ b/include/net/switchdev.h @@ -62,7 +62,6 @@ struct switchdev_attr { #if IS_ENABLED(CONFIG_BRIDGE_MRP) u8 mrp_port_state; /* MRP_PORT_STATE */ u8 mrp_port_role; /* MRP_PORT_ROLE */ - u8 mrp_ring_state; /* MRP_RING_STATE */ #endif } u; }; From 4fb13499d3a0cc74cf9820c052481f0ccda2bb23 Mon Sep 17 00:00:00 2001 From: Horatiu Vultur Date: Thu, 21 May 2020 23:19:07 +0000 Subject: [PATCH 3/3] bridge: mrp: Restore port state when deleting MRP instance When a MRP instance is deleted, then restore the port according to the bridge state. If the bridge is up then the ports will be in forwarding state otherwise will be in disabled state. Fixes: 9a9f26e8f7ea ("bridge: mrp: Connect MRP API with the switchdev API") Acked-by: Nikolay Aleksandrov Signed-off-by: Horatiu Vultur Signed-off-by: David S. Miller --- net/bridge/br_mrp.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/net/bridge/br_mrp.c b/net/bridge/br_mrp.c index 854e31bf0151..528d767eb026 100644 --- a/net/bridge/br_mrp.c +++ b/net/bridge/br_mrp.c @@ -223,6 +223,7 @@ static void br_mrp_test_work_expired(struct work_struct *work) static void br_mrp_del_impl(struct net_bridge *br, struct br_mrp *mrp) { struct net_bridge_port *p; + u8 state; /* Stop sending MRP_Test frames */ cancel_delayed_work_sync(&mrp->test_work); @@ -234,20 +235,24 @@ static void br_mrp_del_impl(struct net_bridge *br, struct br_mrp *mrp) p = rtnl_dereference(mrp->p_port); if (p) { spin_lock_bh(&br->lock); - p->state = BR_STATE_FORWARDING; + state = netif_running(br->dev) ? + BR_STATE_FORWARDING : BR_STATE_DISABLED; + p->state = state; p->flags &= ~BR_MRP_AWARE; spin_unlock_bh(&br->lock); - br_mrp_port_switchdev_set_state(p, BR_STATE_FORWARDING); + br_mrp_port_switchdev_set_state(p, state); rcu_assign_pointer(mrp->p_port, NULL); } p = rtnl_dereference(mrp->s_port); if (p) { spin_lock_bh(&br->lock); - p->state = BR_STATE_FORWARDING; + state = netif_running(br->dev) ? + BR_STATE_FORWARDING : BR_STATE_DISABLED; + p->state = state; p->flags &= ~BR_MRP_AWARE; spin_unlock_bh(&br->lock); - br_mrp_port_switchdev_set_state(p, BR_STATE_FORWARDING); + br_mrp_port_switchdev_set_state(p, state); rcu_assign_pointer(mrp->s_port, NULL); }