@@ -1613,6 +1613,15 @@ void devlink_free(struct devlink *devlink);
* of event queues. Should be used by device drivers to
* configure maximum number of event queues
* of a function managed by the devlink port.
+ * @port_fn_bridge_offload_get: Callback used to get port function's bridge
+ * offload capability. Should be used by device drivers
+ * to report the current state of offload
+ * capability of a function managed by the devlink
+ * port.
+ * @port_fn_bridge_offload_get: Callback used to set port function's bridge
+ * offload capability. Should be used by device drivers to
+ * enable/disable offload capability of a
+ * function managed by the devlink port.
*
* Note: Driver should return -EOPNOTSUPP if it doesn't support
* port function (@port_fn_*) handling for a particular port.
@@ -1668,6 +1677,10 @@ struct devlink_port_ops {
int (*port_fn_max_io_eqs_set)(struct devlink_port *devlink_port,
u32 max_eqs,
struct netlink_ext_ack *extack);
+ void (*port_fn_bridge_offload_get)(struct devlink_port *devlink_port,
+ bool *is_enable);
+ void (*port_fn_bridge_offload_set)(struct devlink_port *devlink_port,
+ bool enable);
};
void devlink_port_init(struct devlink *devlink,
@@ -668,6 +668,7 @@ enum devlink_port_fn_attr_cap {
DEVLINK_PORT_FN_ATTR_CAP_MIGRATABLE_BIT,
DEVLINK_PORT_FN_ATTR_CAP_IPSEC_CRYPTO_BIT,
DEVLINK_PORT_FN_ATTR_CAP_IPSEC_PACKET_BIT,
+ DEVLINK_PORT_FN_ATTR_CAP_BRIDGE_OFFLOAD_BIT,
/* Add new caps above */
__DEVLINK_PORT_FN_ATTR_CAPS_MAX,
@@ -678,6 +679,7 @@ enum devlink_port_fn_attr_cap {
_BITUL(DEVLINK_PORT_FN_ATTR_CAP_MIGRATABLE_BIT)
#define DEVLINK_PORT_FN_CAP_IPSEC_CRYPTO _BITUL(DEVLINK_PORT_FN_ATTR_CAP_IPSEC_CRYPTO_BIT)
#define DEVLINK_PORT_FN_CAP_IPSEC_PACKET _BITUL(DEVLINK_PORT_FN_ATTR_CAP_IPSEC_PACKET_BIT)
+#define DEVLINK_PORT_FN_CAP_BRIDGE_OFFLOAD _BITUL(DEVLINK_PORT_FN_ATTR_CAP_BRIDGE_OFFLOAD_BIT)
enum devlink_port_function_attr {
DEVLINK_PORT_FUNCTION_ATTR_UNSPEC,
@@ -148,6 +148,21 @@ static int devlink_port_fn_ipsec_packet_fill(struct devlink_port *devlink_port,
return 0;
}
+static int devlink_port_bridge_offload_fill(struct devlink_port *devlink_port,
+ struct nla_bitfield32 *caps)
+{
+ bool is_enable;
+
+ if (!devlink_port->ops->port_fn_bridge_offload_get ||
+ devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_PHYSICAL)
+ return 0;
+
+ devlink_port->ops->port_fn_bridge_offload_get(devlink_port, &is_enable);
+
+ devlink_port_fn_cap_fill(caps, DEVLINK_PORT_FN_CAP_BRIDGE_OFFLOAD, is_enable);
+ return 0;
+}
+
static int devlink_port_fn_caps_fill(struct devlink_port *devlink_port,
struct sk_buff *msg,
struct netlink_ext_ack *extack,
@@ -172,6 +187,10 @@ static int devlink_port_fn_caps_fill(struct devlink_port *devlink_port,
if (err)
return err;
+ err = devlink_port_bridge_offload_fill(devlink_port, &caps);
+ if (err)
+ return err;
+
if (!caps.selector)
return 0;
err = nla_put_bitfield32(msg, DEVLINK_PORT_FN_ATTR_CAPS, caps.value,
@@ -393,6 +412,12 @@ devlink_port_fn_ipsec_packet_set(struct devlink_port *devlink_port, bool enable,
return devlink_port->ops->port_fn_ipsec_packet_set(devlink_port, enable, extack);
}
+static void
+devlink_port_fn_bridge_offload_set(struct devlink_port *devlink_port, bool enable)
+{
+ return devlink_port->ops->port_fn_bridge_offload_set(devlink_port, enable);
+}
+
static int devlink_port_fn_caps_set(struct devlink_port *devlink_port,
const struct nlattr *attr,
struct netlink_ext_ack *extack)
@@ -431,6 +456,10 @@ static int devlink_port_fn_caps_set(struct devlink_port *devlink_port,
if (err)
return err;
}
+ if (caps.selector & DEVLINK_PORT_FN_CAP_BRIDGE_OFFLOAD) {
+ devlink_port_fn_bridge_offload_set(devlink_port, caps_value &
+ DEVLINK_PORT_FN_CAP_BRIDGE_OFFLOAD);
+ }
return 0;
}
@@ -765,6 +794,18 @@ static int devlink_port_function_validate(struct devlink_port *devlink_port,
return -EOPNOTSUPP;
}
}
+ if (caps.selector & DEVLINK_PORT_FN_CAP_BRIDGE_OFFLOAD) {
+ if (!ops->port_fn_bridge_offload_set) {
+ NL_SET_ERR_MSG_ATTR(extack, attr,
+ "Port doesn't support bridge offload function attribute");
+ return -EOPNOTSUPP;
+ }
+ if (devlink_port->attrs.flavour != DEVLINK_PORT_FLAVOUR_PHYSICAL) {
+ NL_SET_ERR_MSG_ATTR(extack, attr,
+ "bridge offload function attribute supported for physical ports only");
+ return -EOPNOTSUPP;
+ }
+ }
}
if (tb[DEVLINK_PORT_FN_ATTR_MAX_IO_EQS] &&
!ops->port_fn_max_io_eqs_set) {
Add configurable devlink port attr for HW offloading. Most drivers (and DSA framework) will offload a bridge port to HW if there is mechanism available to do so. Adding a configurable devlink attr allows users to change this default setting, in cases where HW offload of a bridge port is not desired. Signed-off-by: Aryan Srivastava <aryan.srivastava@alliedtelesis.co.nz> --- include/net/devlink.h | 13 ++++++++++++ include/uapi/linux/devlink.h | 2 ++ net/devlink/port.c | 41 ++++++++++++++++++++++++++++++++++++ 3 files changed, 56 insertions(+)