The 04/01/2020 19:33, Nikolay Aleksandrov wrote: > EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe > > On 01/04/2020 19:10, Horatiu Vultur wrote: > > Hi Nik, > > > > The 03/30/2020 19:16, Nikolay Aleksandrov wrote: > >> EXTERNAL EMAIL: Do not click links or open attachments unless you know the content is safe > >> > >> On 27/03/2020 11:21, Horatiu Vultur wrote: > >>> To integrate MRP into the bridge, the bridge needs to do the following: > >>> - add new flag(BR_MPP_AWARE) to the net bridge ports, this bit will be set when > >>> the port is added to an MRP instance. In this way it knows if the frame was > >>> received on MRP ring port > >>> - detect if the MRP frame was received on MRP ring port in that case it would be > >>> processed otherwise just forward it as usual. > >>> - enable parsing of MRP > >>> - before whenever the bridge was set up, it would set all the ports in > >>> forwarding state. Add an extra check to not set ports in forwarding state if > >>> the port is an MRP ring port. The reason of this change is that if the MRP > >>> instance initially sets the port in blocked state by setting the bridge up it > >>> would overwrite this setting. > >>> > >>> Signed-off-by: Horatiu Vultur <horatiu.vultur@xxxxxxxxxxxxx> > >>> --- > >>> include/linux/if_bridge.h | 1 + > >>> net/bridge/br_device.c | 3 +++ > >>> net/bridge/br_input.c | 3 +++ > >>> net/bridge/br_netlink.c | 5 +++++ > >>> net/bridge/br_private.h | 22 ++++++++++++++++++++++ > >>> net/bridge/br_stp.c | 6 ++++++ > >>> 6 files changed, 40 insertions(+) > >>> > >>> diff --git a/include/linux/if_bridge.h b/include/linux/if_bridge.h > >>> index 9e57c4411734..10baa9efdae8 100644 > >>> --- a/include/linux/if_bridge.h > >>> +++ b/include/linux/if_bridge.h > >>> @@ -47,6 +47,7 @@ struct br_ip_list { > >>> #define BR_BCAST_FLOOD BIT(14) > >>> #define BR_NEIGH_SUPPRESS BIT(15) > >>> #define BR_ISOLATED BIT(16) > >>> +#define BR_MRP_AWARE BIT(17) > >>> > >>> #define BR_DEFAULT_AGEING_TIME (300 * HZ) > >>> > >>> diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c > >>> index 0e3dbc5f3c34..8ec1362588af 100644 > >>> --- a/net/bridge/br_device.c > >>> +++ b/net/bridge/br_device.c > >>> @@ -463,6 +463,9 @@ void br_dev_setup(struct net_device *dev) > >>> spin_lock_init(&br->lock); > >>> INIT_LIST_HEAD(&br->port_list); > >>> INIT_HLIST_HEAD(&br->fdb_list); > >>> +#if IS_ENABLED(CONFIG_BRIDGE_MRP) > >>> + INIT_LIST_HEAD(&br->mrp_list); > >>> +#endif > >>> spin_lock_init(&br->hash_lock); > >>> > >>> br->bridge_id.prio[0] = 0x80; > >>> diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c > >>> index fcc260840028..d5c34f36f0f4 100644 > >>> --- a/net/bridge/br_input.c > >>> +++ b/net/bridge/br_input.c > >>> @@ -342,6 +342,9 @@ rx_handler_result_t br_handle_frame(struct sk_buff **pskb) > >>> } > >>> } > >>> > >>> + if (unlikely(br_mrp_process(p, skb))) > >>> + return RX_HANDLER_PASS; > >>> + > >>> forward: > >>> switch (p->state) { > >>> case BR_STATE_FORWARDING: > >>> diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c > >>> index 43dab4066f91..77bc96745be6 100644 > >>> --- a/net/bridge/br_netlink.c > >>> +++ b/net/bridge/br_netlink.c > >>> @@ -669,6 +669,11 @@ static int br_afspec(struct net_bridge *br, > >>> if (err) > >>> return err; > >>> break; > >>> + case IFLA_BRIDGE_MRP: > >>> + err = br_mrp_parse(br, p, attr, cmd); > >>> + if (err) > >>> + return err; > >>> + break; > >>> } > >>> } > >>> > >>> diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h > >>> index 1f97703a52ff..38894f2cf98f 100644 > >>> --- a/net/bridge/br_private.h > >>> +++ b/net/bridge/br_private.h > >>> @@ -428,6 +428,10 @@ struct net_bridge { > >>> int offload_fwd_mark; > >>> #endif > >>> struct hlist_head fdb_list; > >>> + > >>> +#if IS_ENABLED(CONFIG_BRIDGE_MRP) > >>> + struct list_head __rcu mrp_list; > >>> +#endif > >>> }; > >>> > >>> struct br_input_skb_cb { > >>> @@ -1304,6 +1308,24 @@ unsigned long br_timer_value(const struct timer_list *timer); > >>> extern int (*br_fdb_test_addr_hook)(struct net_device *dev, unsigned char *addr); > >>> #endif > >>> > >>> +/* br_mrp.c */ > >>> +#if IS_ENABLED(CONFIG_BRIDGE_MRP) > >>> +int br_mrp_parse(struct net_bridge *br, struct net_bridge_port *p, > >>> + struct nlattr *attr, int cmd); > >>> +int br_mrp_process(struct net_bridge_port *p, struct sk_buff *skb); > >>> +#else > >>> +static inline int br_mrp_parse(struct net_bridge *br, struct net_bridge_port *p, > >>> + struct nlattr *attr, int cmd) > >>> +{ > >>> + return -1; > >> > >> You should return proper error here. > > > > It will return -EOPNOTSUPP. > > > >> > >>> +} > >>> + > >>> +static inline int br_mrp_process(struct net_bridge_port *p, struct sk_buff *skb) > >>> +{ > >>> + return -1; > >> > >> The bridge can't possibly work with MRP disabled with this. > > > > Good catch, it will return 0. > > > >> > >>> +} > >>> +#endif > >>> + > >>> /* br_netlink.c */ > >>> extern struct rtnl_link_ops br_link_ops; > >>> int br_netlink_init(void); > >>> diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c > >>> index 1f14b8455345..3e88be7aa269 100644 > >>> --- a/net/bridge/br_stp.c > >>> +++ b/net/bridge/br_stp.c > >>> @@ -36,6 +36,12 @@ void br_set_state(struct net_bridge_port *p, unsigned int state) > >>> }; > >>> int err; > >>> > >>> + /* Don't change the state of the ports if they are driven by a different > >>> + * protocol. > >>> + */ > >>> + if (p->flags & BR_MRP_AWARE) > >>> + return; > >>> + > >> > >> Maybe disallow STP type (kernel/user-space/no-stp) changing as well, force it to no-stp. > > > > I am not sure that I understand completely here, do you want me to > > disable STP if MRP is started? > > > > I think it should be one of the two since they can step on each other's toes. If MRP is > enabled then STP must be already disabled and should not be possible to enable while MRP > is active and vice-versa. I will update this in the next patch series. > > >> > >>> p->state = state; > >>> err = switchdev_port_attr_set(p->dev, &attr); > >>> if (err && err != -EOPNOTSUPP) > >>> > >> > > > -- /Horatiu