2021-01-28 00:27:44

by Horatiu Vultur

[permalink] [raw]
Subject: [PATCH net-next v2 0/4] bridge: mrp: Extend br_mrp_switchdev_*

This patch series extends MRP switchdev to allow the SW to have a better
understanding if the HW can implement the MRP functionality or it needs
to help the HW to run it. There are 3 cases:
- when HW can't implement at all the functionality.
- when HW can implement a part of the functionality but needs the SW
implement the rest. For example if it can't detect when it stops
receiving MRP Test frames but it can copy the MRP frames to CPU to
allow the SW to determine this. Another example is generating the MRP
Test frames. If HW can't do that then the SW is used as backup.
- when HW can implement completely the functionality.

So, initially the SW tries to offload the entire functionality in HW, if
that fails it tries offload parts of the functionality in HW and use the
SW as helper and if also this fails then MRP can't run on this HW.

v2:
- fix typos in comments and in commit messages
- remove some of the comments
- move repeated code in helper function
- fix issue when deleting a node when sw_backup was true

Horatiu Vultur (4):
switchdev: mrp: Extend ring_role_mrp and in_role_mrp
bridge: mrp: Add 'enum br_mrp_hw_support'
bridge: mrp: Extend br_mrp_switchdev to detect better the errors
bridge: mrp: Update br_mrp to use new return values of
br_mrp_switchdev

include/net/switchdev.h | 2 +
net/bridge/br_mrp.c | 43 +++++----
net/bridge/br_mrp_switchdev.c | 171 +++++++++++++++++++++-------------
net/bridge/br_private_mrp.h | 38 ++++++--
4 files changed, 161 insertions(+), 93 deletions(-)

--
2.27.0


2021-01-28 00:28:01

by Horatiu Vultur

[permalink] [raw]
Subject: [PATCH net-next v2 1/4] switchdev: mrp: Extend ring_role_mrp and in_role_mrp

Add the member sw_backup to the structures switchdev_obj_ring_role_mrp
and switchdev_obj_in_role_mrp. In this way the SW can call the driver in
2 ways, once when sw_backup is set to false, meaning that the driver
should implement this completely in HW. And if that is not supported the
SW will call again but with sw_backup set to true, meaning that the
HW should help or allow the SW to run the protocol.

For example when role is MRM, if the HW can't detect when it stops
receiving MRP Test frames but it can trap these frames to CPU, then it
needs to return -EOPNOTSUPP when sw_backup is false and return 0 when
sw_backup is true.

Signed-off-by: Horatiu Vultur <[email protected]>
---
include/net/switchdev.h | 2 ++
1 file changed, 2 insertions(+)

diff --git a/include/net/switchdev.h b/include/net/switchdev.h
index 88fcac140966..3f236eaa4f3e 100644
--- a/include/net/switchdev.h
+++ b/include/net/switchdev.h
@@ -132,6 +132,7 @@ struct switchdev_obj_ring_role_mrp {
struct switchdev_obj obj;
u8 ring_role;
u32 ring_id;
+ u8 sw_backup;
};

#define SWITCHDEV_OBJ_RING_ROLE_MRP(OBJ) \
@@ -166,6 +167,7 @@ struct switchdev_obj_in_role_mrp {
u32 ring_id;
u16 in_id;
u8 in_role;
+ u8 sw_backup;
};

#define SWITCHDEV_OBJ_IN_ROLE_MRP(OBJ) \
--
2.27.0

2021-01-28 00:30:11

by Horatiu Vultur

[permalink] [raw]
Subject: [PATCH net-next v2 2/4] bridge: mrp: Add 'enum br_mrp_hw_support'

Add the enum br_mrp_hw_support that is used by the br_mrp_switchdev
functions to allow the SW to detect the cases where HW can't implement
the functionality or when SW is used as a backup.

Signed-off-by: Horatiu Vultur <[email protected]>
---
net/bridge/br_private_mrp.h | 14 ++++++++++++++
1 file changed, 14 insertions(+)

diff --git a/net/bridge/br_private_mrp.h b/net/bridge/br_private_mrp.h
index 1883118aae55..31e666ae6955 100644
--- a/net/bridge/br_private_mrp.h
+++ b/net/bridge/br_private_mrp.h
@@ -46,6 +46,20 @@ struct br_mrp {
struct rcu_head rcu;
};

+/* This type is returned by br_mrp_switchdev functions that allow to have a SW
+ * backup in case the HW can't implement completely the protocol.
+ * BR_MRP_NONE - means the HW can't run at all the protocol, so the SW stops
+ * configuring the node anymore.
+ * BR_MRP_SW - the HW can help the SW to run the protocol, by redirecting MRP
+ * frames to CPU.
+ * BR_MRP_HW - the HW can implement completely the protocol.
+ */
+enum br_mrp_hw_support {
+ BR_MRP_NONE,
+ BR_MRP_SW,
+ BR_MRP_HW,
+};
+
/* br_mrp.c */
int br_mrp_add(struct net_bridge *br, struct br_mrp_instance *instance);
int br_mrp_del(struct net_bridge *br, struct br_mrp_instance *instance);
--
2.27.0

2021-01-28 00:30:16

by Horatiu Vultur

[permalink] [raw]
Subject: [PATCH net-next v2 4/4] bridge: mrp: Update br_mrp to use new return values of br_mrp_switchdev

Check the return values of the br_mrp_switchdev function.
In case of:
- BR_MRP_NONE, return the error to userspace,
- BR_MRP_SW, continue with SW implementation,
- BR_MRP_HW, continue without SW implementation,

Signed-off-by: Horatiu Vultur <[email protected]>
---
net/bridge/br_mrp.c | 43 +++++++++++++++++++++++++++----------------
1 file changed, 27 insertions(+), 16 deletions(-)

diff --git a/net/bridge/br_mrp.c b/net/bridge/br_mrp.c
index fc0a98874bfc..faa4ccb20f0a 100644
--- a/net/bridge/br_mrp.c
+++ b/net/bridge/br_mrp.c
@@ -636,7 +636,7 @@ int br_mrp_set_ring_role(struct net_bridge *br,
struct br_mrp_ring_role *role)
{
struct br_mrp *mrp = br_mrp_find_id(br, role->ring_id);
- int err;
+ enum br_mrp_hw_support support;

if (!mrp)
return -EINVAL;
@@ -644,9 +644,9 @@ int br_mrp_set_ring_role(struct net_bridge *br,
mrp->ring_role = role->ring_role;

/* If there is an error just bailed out */
- err = br_mrp_switchdev_set_ring_role(br, mrp, role->ring_role);
- if (err && err != -EOPNOTSUPP)
- return err;
+ support = br_mrp_switchdev_set_ring_role(br, mrp, role->ring_role);
+ if (support == BR_MRP_NONE)
+ return -EOPNOTSUPP;

/* Now detect if the HW actually applied the role or not. If the HW
* applied the role it means that the SW will not to do those operations
@@ -654,7 +654,7 @@ int br_mrp_set_ring_role(struct net_bridge *br,
* SW when ring is open, but if the is not pushed to the HW the SW will
* need to detect when the ring is open
*/
- mrp->ring_role_offloaded = err == -EOPNOTSUPP ? 0 : 1;
+ mrp->ring_role_offloaded = support == BR_MRP_SW ? 0 : 1;

return 0;
}
@@ -667,6 +667,7 @@ int br_mrp_start_test(struct net_bridge *br,
struct br_mrp_start_test *test)
{
struct br_mrp *mrp = br_mrp_find_id(br, test->ring_id);
+ enum br_mrp_hw_support support;

if (!mrp)
return -EINVAL;
@@ -674,9 +675,13 @@ int br_mrp_start_test(struct net_bridge *br,
/* Try to push it to the HW and if it fails then continue with SW
* implementation and if that also fails then return error.
*/
- if (!br_mrp_switchdev_send_ring_test(br, mrp, test->interval,
- test->max_miss, test->period,
- test->monitor))
+ support = br_mrp_switchdev_send_ring_test(br, mrp, test->interval,
+ test->max_miss, test->period,
+ test->monitor);
+ if (support == BR_MRP_NONE)
+ return -EOPNOTSUPP;
+
+ if (support == BR_MRP_HW)
return 0;

mrp->test_interval = test->interval;
@@ -718,8 +723,8 @@ int br_mrp_set_in_state(struct net_bridge *br, struct br_mrp_in_state *state)
int br_mrp_set_in_role(struct net_bridge *br, struct br_mrp_in_role *role)
{
struct br_mrp *mrp = br_mrp_find_id(br, role->ring_id);
+ enum br_mrp_hw_support support;
struct net_bridge_port *p;
- int err;

if (!mrp)
return -EINVAL;
@@ -777,10 +782,10 @@ int br_mrp_set_in_role(struct net_bridge *br, struct br_mrp_in_role *role)
mrp->in_id = role->in_id;

/* If there is an error just bailed out */
- err = br_mrp_switchdev_set_in_role(br, mrp, role->in_id,
- role->ring_id, role->in_role);
- if (err && err != -EOPNOTSUPP)
- return err;
+ support = br_mrp_switchdev_set_in_role(br, mrp, role->in_id,
+ role->ring_id, role->in_role);
+ if (support == BR_MRP_NONE)
+ return -EOPNOTSUPP;

/* Now detect if the HW actually applied the role or not. If the HW
* applied the role it means that the SW will not to do those operations
@@ -788,7 +793,7 @@ int br_mrp_set_in_role(struct net_bridge *br, struct br_mrp_in_role *role)
* SW when interconnect ring is open, but if the is not pushed to the HW
* the SW will need to detect when the interconnect ring is open.
*/
- mrp->in_role_offloaded = err == -EOPNOTSUPP ? 0 : 1;
+ mrp->in_role_offloaded = support == BR_MRP_SW ? 0 : 1;

return 0;
}
@@ -801,6 +806,7 @@ int br_mrp_start_in_test(struct net_bridge *br,
struct br_mrp_start_in_test *in_test)
{
struct br_mrp *mrp = br_mrp_find_in_id(br, in_test->in_id);
+ enum br_mrp_hw_support support;

if (!mrp)
return -EINVAL;
@@ -811,8 +817,13 @@ int br_mrp_start_in_test(struct net_bridge *br,
/* Try to push it to the HW and if it fails then continue with SW
* implementation and if that also fails then return error.
*/
- if (!br_mrp_switchdev_send_in_test(br, mrp, in_test->interval,
- in_test->max_miss, in_test->period))
+ support = br_mrp_switchdev_send_in_test(br, mrp, in_test->interval,
+ in_test->max_miss,
+ in_test->period);
+ if (support == BR_MRP_NONE)
+ return -EOPNOTSUPP;
+
+ if (support == BR_MRP_HW)
return 0;

mrp->in_test_interval = in_test->interval;
--
2.27.0

2021-01-28 01:40:06

by Horatiu Vultur

[permalink] [raw]
Subject: [PATCH net-next v2 3/4] bridge: mrp: Extend br_mrp_switchdev to detect better the errors

This patch extends the br_mrp_switchdev functions to be able to have a
better understanding what cause the issue and if the SW needs to be used
as a backup.

There are the following cases:
- when the code is compiled without CONFIG_NET_SWITCHDEV. In this case
return success so the SW can continue with the protocol. Depending
on the function, it returns 0 or BR_MRP_SW.
- when code is compiled with CONFIG_NET_SWITCHDEV and the driver doesn't
implement any MRP callbacks. In this case the HW can't run MRP so it
just returns -EOPNOTSUPP. So the SW will stop further to configure the
node.
- when code is compiled with CONFIG_NET_SWITCHDEV and the driver fully
supports any MRP functionality. In this case the SW doesn't need to do
anything. The functions will return 0 or BR_MRP_HW.
- when code is compiled with CONFIG_NET_SWITCHDEV and the HW can't run
completely the protocol but it can help the SW to run it. For
example, the HW can't support completely MRM role(can't detect when it
stops receiving MRP Test frames) but it can redirect these frames to
CPU. In this case it is possible to have a SW fallback. The SW will
try initially to call the driver with sw_backup set to false, meaning
that the HW should implement completely the role. If the driver returns
-EOPNOTSUPP, the SW will try again with sw_backup set to false,
meaning that the SW will detect when it stops receiving the frames but
it needs HW support to redirect the frames to CPU. In case the driver
returns 0 then the SW will continue to configure the node accordingly.

Signed-off-by: Horatiu Vultur <[email protected]>
---
net/bridge/br_mrp_switchdev.c | 171 +++++++++++++++++++++-------------
net/bridge/br_private_mrp.h | 24 +++--
2 files changed, 118 insertions(+), 77 deletions(-)

diff --git a/net/bridge/br_mrp_switchdev.c b/net/bridge/br_mrp_switchdev.c
index ed547e03ace1..ffd844e9be6b 100644
--- a/net/bridge/br_mrp_switchdev.c
+++ b/net/bridge/br_mrp_switchdev.c
@@ -4,6 +4,30 @@

#include "br_private_mrp.h"

+static enum br_mrp_hw_support
+br_mrp_switchdev_port_obj(struct net_bridge *br,
+ const struct switchdev_obj *obj, bool add)
+{
+ int err;
+
+ if (add)
+ err = switchdev_port_obj_add(br->dev, obj, NULL);
+ else
+ err = switchdev_port_obj_del(br->dev, obj);
+
+ /* In case of success just return and notify the SW that doesn't need
+ * to do anything
+ */
+ if (!err)
+ return BR_MRP_HW;
+
+ if (err != -EOPNOTSUPP)
+ return BR_MRP_NONE;
+
+ /* Continue with SW backup */
+ return BR_MRP_SW;
+}
+
int br_mrp_switchdev_add(struct net_bridge *br, struct br_mrp *mrp)
{
struct switchdev_obj_mrp mrp_obj = {
@@ -14,14 +38,11 @@ int br_mrp_switchdev_add(struct net_bridge *br, struct br_mrp *mrp)
.ring_id = mrp->ring_id,
.prio = mrp->prio,
};
- int err;

- err = switchdev_port_obj_add(br->dev, &mrp_obj.obj, NULL);
+ if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
+ return 0;

- if (err && err != -EOPNOTSUPP)
- return err;
-
- return 0;
+ return switchdev_port_obj_add(br->dev, &mrp_obj.obj, NULL);
}

int br_mrp_switchdev_del(struct net_bridge *br, struct br_mrp *mrp)
@@ -33,40 +54,54 @@ int br_mrp_switchdev_del(struct net_bridge *br, struct br_mrp *mrp)
.s_port = NULL,
.ring_id = mrp->ring_id,
};
- int err;
-
- err = switchdev_port_obj_del(br->dev, &mrp_obj.obj);

- if (err && err != -EOPNOTSUPP)
- return err;
+ if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
+ return 0;

- return 0;
+ return switchdev_port_obj_del(br->dev, &mrp_obj.obj);
}

-int br_mrp_switchdev_set_ring_role(struct net_bridge *br,
- struct br_mrp *mrp,
- enum br_mrp_ring_role_type role)
+enum br_mrp_hw_support
+br_mrp_switchdev_set_ring_role(struct net_bridge *br, struct br_mrp *mrp,
+ enum br_mrp_ring_role_type role)
{
struct switchdev_obj_ring_role_mrp mrp_role = {
.obj.orig_dev = br->dev,
.obj.id = SWITCHDEV_OBJ_ID_RING_ROLE_MRP,
.ring_role = role,
.ring_id = mrp->ring_id,
+ .sw_backup = false,
};
+ enum br_mrp_hw_support support;
int err;

- if (role == BR_MRP_RING_ROLE_DISABLED)
- err = switchdev_port_obj_del(br->dev, &mrp_role.obj);
- else
+ if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
+ return BR_MRP_SW;
+
+ support = br_mrp_switchdev_port_obj(br, &mrp_role.obj,
+ role != BR_MRP_RING_ROLE_DISABLED);
+ if (support != BR_MRP_SW)
+ return support;
+
+ /* If the driver can't configure to run completely the protocol in HW,
+ * then try again to configure the HW so the SW can run the protocol.
+ */
+ mrp_role.sw_backup = true;
+ if (role != BR_MRP_RING_ROLE_DISABLED)
err = switchdev_port_obj_add(br->dev, &mrp_role.obj, NULL);
+ else
+ err = switchdev_port_obj_del(br->dev, &mrp_role.obj);

- return err;
+ if (!err)
+ return BR_MRP_SW;
+
+ return BR_MRP_NONE;
}

-int br_mrp_switchdev_send_ring_test(struct net_bridge *br,
- struct br_mrp *mrp, u32 interval,
- u8 max_miss, u32 period,
- bool monitor)
+enum br_mrp_hw_support
+br_mrp_switchdev_send_ring_test(struct net_bridge *br, struct br_mrp *mrp,
+ u32 interval, u8 max_miss, u32 period,
+ bool monitor)
{
struct switchdev_obj_ring_test_mrp test = {
.obj.orig_dev = br->dev,
@@ -77,14 +112,11 @@ int br_mrp_switchdev_send_ring_test(struct net_bridge *br,
.period = period,
.monitor = monitor,
};
- int err;

- if (interval == 0)
- err = switchdev_port_obj_del(br->dev, &test.obj);
- else
- err = switchdev_port_obj_add(br->dev, &test.obj, NULL);
+ if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
+ return BR_MRP_SW;

- return err;
+ return br_mrp_switchdev_port_obj(br, &test.obj, interval != 0);
}

int br_mrp_switchdev_set_ring_state(struct net_bridge *br,
@@ -97,19 +129,17 @@ int br_mrp_switchdev_set_ring_state(struct net_bridge *br,
.ring_state = state,
.ring_id = mrp->ring_id,
};
- int err;
-
- err = switchdev_port_obj_add(br->dev, &mrp_state.obj, NULL);

- if (err && err != -EOPNOTSUPP)
- return err;
+ if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
+ return 0;

- return 0;
+ return switchdev_port_obj_add(br->dev, &mrp_state.obj, NULL);
}

-int br_mrp_switchdev_set_in_role(struct net_bridge *br, struct br_mrp *mrp,
- u16 in_id, u32 ring_id,
- enum br_mrp_in_role_type role)
+enum br_mrp_hw_support
+br_mrp_switchdev_set_in_role(struct net_bridge *br, struct br_mrp *mrp,
+ u16 in_id, u32 ring_id,
+ enum br_mrp_in_role_type role)
{
struct switchdev_obj_in_role_mrp mrp_role = {
.obj.orig_dev = br->dev,
@@ -118,15 +148,32 @@ int br_mrp_switchdev_set_in_role(struct net_bridge *br, struct br_mrp *mrp,
.in_id = mrp->in_id,
.ring_id = mrp->ring_id,
.i_port = rtnl_dereference(mrp->i_port)->dev,
+ .sw_backup = false,
};
+ enum br_mrp_hw_support support;
int err;

- if (role == BR_MRP_IN_ROLE_DISABLED)
- err = switchdev_port_obj_del(br->dev, &mrp_role.obj);
- else
+ if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
+ return BR_MRP_SW;
+
+ support = br_mrp_switchdev_port_obj(br, &mrp_role.obj,
+ role != BR_MRP_IN_ROLE_DISABLED);
+ if (support != BR_MRP_NONE)
+ return support;
+
+ /* If the driver can't configure to run completely the protocol in HW,
+ * then try again to configure the HW so the SW can run the protocol.
+ */
+ mrp_role.sw_backup = true;
+ if (role != BR_MRP_IN_ROLE_DISABLED)
err = switchdev_port_obj_add(br->dev, &mrp_role.obj, NULL);
+ else
+ err = switchdev_port_obj_del(br->dev, &mrp_role.obj);
+
+ if (!err)
+ return BR_MRP_SW;

- return err;
+ return BR_MRP_NONE;
}

int br_mrp_switchdev_set_in_state(struct net_bridge *br, struct br_mrp *mrp,
@@ -138,18 +185,16 @@ int br_mrp_switchdev_set_in_state(struct net_bridge *br, struct br_mrp *mrp,
.in_state = state,
.in_id = mrp->in_id,
};
- int err;
-
- err = switchdev_port_obj_add(br->dev, &mrp_state.obj, NULL);

- if (err && err != -EOPNOTSUPP)
- return err;
+ if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
+ return 0;

- return 0;
+ return switchdev_port_obj_add(br->dev, &mrp_state.obj, NULL);
}

-int br_mrp_switchdev_send_in_test(struct net_bridge *br, struct br_mrp *mrp,
- u32 interval, u8 max_miss, u32 period)
+enum br_mrp_hw_support
+br_mrp_switchdev_send_in_test(struct net_bridge *br, struct br_mrp *mrp,
+ u32 interval, u8 max_miss, u32 period)
{
struct switchdev_obj_in_test_mrp test = {
.obj.orig_dev = br->dev,
@@ -159,14 +204,11 @@ int br_mrp_switchdev_send_in_test(struct net_bridge *br, struct br_mrp *mrp,
.in_id = mrp->in_id,
.period = period,
};
- int err;

- if (interval == 0)
- err = switchdev_port_obj_del(br->dev, &test.obj);
- else
- err = switchdev_port_obj_add(br->dev, &test.obj, NULL);
+ if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
+ return BR_MRP_SW;

- return err;
+ return br_mrp_switchdev_port_obj(br, &test.obj, interval != 0);
}

int br_mrp_port_switchdev_set_state(struct net_bridge_port *p,
@@ -177,14 +219,11 @@ int br_mrp_port_switchdev_set_state(struct net_bridge_port *p,
.id = SWITCHDEV_ATTR_ID_MRP_PORT_STATE,
.u.mrp_port_state = state,
};
- int err;

- err = switchdev_port_attr_set(p->dev, &attr);
- if (err && err != -EOPNOTSUPP)
- br_warn(p->br, "error setting offload MRP state on port %u(%s)\n",
- (unsigned int)p->port_no, p->dev->name);
+ if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
+ return 0;

- return err;
+ return switchdev_port_attr_set(p->dev, &attr);
}

int br_mrp_port_switchdev_set_role(struct net_bridge_port *p,
@@ -195,11 +234,9 @@ int br_mrp_port_switchdev_set_role(struct net_bridge_port *p,
.id = SWITCHDEV_ATTR_ID_MRP_PORT_ROLE,
.u.mrp_port_role = role,
};
- int err;

- err = switchdev_port_attr_set(p->dev, &attr);
- if (err && err != -EOPNOTSUPP)
- return err;
+ if (!IS_ENABLED(CONFIG_NET_SWITCHDEV))
+ return 0;

- return 0;
+ return switchdev_port_attr_set(p->dev, &attr);
}
diff --git a/net/bridge/br_private_mrp.h b/net/bridge/br_private_mrp.h
index 31e666ae6955..e941dad398cf 100644
--- a/net/bridge/br_private_mrp.h
+++ b/net/bridge/br_private_mrp.h
@@ -79,24 +79,28 @@ int br_mrp_start_in_test(struct net_bridge *br,
/* br_mrp_switchdev.c */
int br_mrp_switchdev_add(struct net_bridge *br, struct br_mrp *mrp);
int br_mrp_switchdev_del(struct net_bridge *br, struct br_mrp *mrp);
-int br_mrp_switchdev_set_ring_role(struct net_bridge *br, struct br_mrp *mrp,
- enum br_mrp_ring_role_type role);
+enum br_mrp_hw_support
+br_mrp_switchdev_set_ring_role(struct net_bridge *br, struct br_mrp *mrp,
+ enum br_mrp_ring_role_type role);
int br_mrp_switchdev_set_ring_state(struct net_bridge *br, struct br_mrp *mrp,
enum br_mrp_ring_state_type state);
-int br_mrp_switchdev_send_ring_test(struct net_bridge *br, struct br_mrp *mrp,
- u32 interval, u8 max_miss, u32 period,
- bool monitor);
+enum br_mrp_hw_support
+br_mrp_switchdev_send_ring_test(struct net_bridge *br, struct br_mrp *mrp,
+ u32 interval, u8 max_miss, u32 period,
+ bool monitor);
int br_mrp_port_switchdev_set_state(struct net_bridge_port *p,
enum br_mrp_port_state_type state);
int br_mrp_port_switchdev_set_role(struct net_bridge_port *p,
enum br_mrp_port_role_type role);
-int br_mrp_switchdev_set_in_role(struct net_bridge *br, struct br_mrp *mrp,
- u16 in_id, u32 ring_id,
- enum br_mrp_in_role_type role);
+enum br_mrp_hw_support
+br_mrp_switchdev_set_in_role(struct net_bridge *br, struct br_mrp *mrp,
+ u16 in_id, u32 ring_id,
+ enum br_mrp_in_role_type role);
int br_mrp_switchdev_set_in_state(struct net_bridge *br, struct br_mrp *mrp,
enum br_mrp_in_state_type state);
-int br_mrp_switchdev_send_in_test(struct net_bridge *br, struct br_mrp *mrp,
- u32 interval, u8 max_miss, u32 period);
+enum br_mrp_hw_support
+br_mrp_switchdev_send_in_test(struct net_bridge *br, struct br_mrp *mrp,
+ u32 interval, u8 max_miss, u32 period);

/* br_mrp_netlink.c */
int br_mrp_ring_port_open(struct net_device *dev, u8 loc);
--
2.27.0

2021-01-30 09:53:49

by Jakub Kicinski

[permalink] [raw]
Subject: Re: [PATCH net-next v2 0/4] bridge: mrp: Extend br_mrp_switchdev_*

On Wed, 27 Jan 2021 21:52:37 +0100 Horatiu Vultur wrote:
> This patch series extends MRP switchdev to allow the SW to have a better
> understanding if the HW can implement the MRP functionality or it needs
> to help the HW to run it. There are 3 cases:
> - when HW can't implement at all the functionality.
> - when HW can implement a part of the functionality but needs the SW
> implement the rest. For example if it can't detect when it stops
> receiving MRP Test frames but it can copy the MRP frames to CPU to
> allow the SW to determine this. Another example is generating the MRP
> Test frames. If HW can't do that then the SW is used as backup.
> - when HW can implement completely the functionality.
>
> So, initially the SW tries to offload the entire functionality in HW, if
> that fails it tries offload parts of the functionality in HW and use the
> SW as helper and if also this fails then MRP can't run on this HW.
>
> v2:
> - fix typos in comments and in commit messages
> - remove some of the comments
> - move repeated code in helper function
> - fix issue when deleting a node when sw_backup was true

Folks who were involved in previous MRP conversations - does this look
good to you? Anyone planning to test?

2021-02-02 07:44:36

by Rasmus Villemoes

[permalink] [raw]
Subject: Re: [PATCH net-next v2 0/4] bridge: mrp: Extend br_mrp_switchdev_*

On 30/01/2021 04.01, Jakub Kicinski wrote:
> On Wed, 27 Jan 2021 21:52:37 +0100 Horatiu Vultur wrote:
>> This patch series extends MRP switchdev to allow the SW to have a better
>> understanding if the HW can implement the MRP functionality or it needs
>> to help the HW to run it. There are 3 cases:

>> v2:
>> - fix typos in comments and in commit messages
>> - remove some of the comments
>> - move repeated code in helper function
>> - fix issue when deleting a node when sw_backup was true
>
> Folks who were involved in previous MRP conversations - does this look
> good to you? Anyone planning to test?
>

I am planning to test these, but it's unlikely I'll get around to it
this week unfortunately.

Rasmus

2021-02-03 00:50:01

by Jakub Kicinski

[permalink] [raw]
Subject: Re: [PATCH net-next v2 0/4] bridge: mrp: Extend br_mrp_switchdev_*

On Tue, 2 Feb 2021 08:40:02 +0100 Rasmus Villemoes wrote:
> On 30/01/2021 04.01, Jakub Kicinski wrote:
> > On Wed, 27 Jan 2021 21:52:37 +0100 Horatiu Vultur wrote:
> >> This patch series extends MRP switchdev to allow the SW to have a better
> >> understanding if the HW can implement the MRP functionality or it needs
> >> to help the HW to run it. There are 3 cases:
>
> >> v2:
> >> - fix typos in comments and in commit messages
> >> - remove some of the comments
> >> - move repeated code in helper function
> >> - fix issue when deleting a node when sw_backup was true
> >
> > Folks who were involved in previous MRP conversations - does this look
> > good to you? Anyone planning to test?
>
> I am planning to test these, but it's unlikely I'll get around to it
> this week unfortunately.

Horatiu are you okay with deferring the series until Rasmus validates?
Given none of this HW is upstream now (AFAIU) this is an awkward set
to handle. Having a confirmation from Rasmus would make us a little bit
more comfortable.

2021-02-03 00:51:37

by Horatiu Vultur

[permalink] [raw]
Subject: Re: [PATCH net-next v2 0/4] bridge: mrp: Extend br_mrp_switchdev_*

The 02/02/2021 11:50, Jakub Kicinski wrote:
>
> On Tue, 2 Feb 2021 08:40:02 +0100 Rasmus Villemoes wrote:
> > On 30/01/2021 04.01, Jakub Kicinski wrote:
> > > On Wed, 27 Jan 2021 21:52:37 +0100 Horatiu Vultur wrote:
> > >> This patch series extends MRP switchdev to allow the SW to have a better
> > >> understanding if the HW can implement the MRP functionality or it needs
> > >> to help the HW to run it. There are 3 cases:
> >
> > >> v2:
> > >> - fix typos in comments and in commit messages
> > >> - remove some of the comments
> > >> - move repeated code in helper function
> > >> - fix issue when deleting a node when sw_backup was true
> > >
> > > Folks who were involved in previous MRP conversations - does this look
> > > good to you? Anyone planning to test?
> >
> > I am planning to test these, but it's unlikely I'll get around to it
> > this week unfortunately.
>
> Horatiu are you okay with deferring the series until Rasmus validates?
> Given none of this HW is upstream now (AFAIU) this is an awkward set
> to handle. Having a confirmation from Rasmus would make us a little bit
> more comfortable.

It is perfectly fine for me to wait for Rasmus to validate this series.
Also I have started to have a look how to implement the switchdev calls
for Ocelot driver. I might have something by the end of the week, but
lets see.

--
/Horatiu

2021-02-03 00:52:30

by Jakub Kicinski

[permalink] [raw]
Subject: Re: [PATCH net-next v2 0/4] bridge: mrp: Extend br_mrp_switchdev_*

On Tue, 2 Feb 2021 21:06:49 +0100 Horatiu Vultur wrote:
> The 02/02/2021 11:50, Jakub Kicinski wrote:
> > On Tue, 2 Feb 2021 08:40:02 +0100 Rasmus Villemoes wrote:
> > > I am planning to test these, but it's unlikely I'll get around to it
> > > this week unfortunately.
> >
> > Horatiu are you okay with deferring the series until Rasmus validates?
> > Given none of this HW is upstream now (AFAIU) this is an awkward set
> > to handle. Having a confirmation from Rasmus would make us a little bit
> > more comfortable.
>
> It is perfectly fine for me to wait for Rasmus to validate this series.
> Also I have started to have a look how to implement the switchdev calls
> for Ocelot driver. I might have something by the end of the week, but
> lets see.

Great, thanks! Please repost once we got the confirmation.