From: Parav Pandit Introduce a new state to eswitch (active/inactive) and enable user to set it dynamically. A user can start the eswitch in switchdev mode in either active or inactive state. Active: Traffic is enabled on this eswitch FDB. Inactive: Traffic is ignored/dropped on this eswitch FDB. An example of starting the switch in active state is following. 1. devlink dev eswitch set pci/0000:08:00.1 mode switchdev (default is active, backward compatible) 2. devlink dev eswitch set pci/0000:08:00.1 mode switchdev state active To bring up the esw in 'inactive' state: devlink dev eswitch set pci/0000:08:00.1 mode switchdev state inactive Signed-off-by: Parav Pandit Signed-off-by: Saeed Mahameed Signed-off-by: Adithya Jayachandran --- Documentation/netlink/specs/devlink.yaml | 13 ++++++++ .../devlink/devlink-eswitch-attr.rst | 15 ++++++++++ include/net/devlink.h | 5 ++++ include/uapi/linux/devlink.h | 7 +++++ net/devlink/dev.c | 30 +++++++++++++++++++ net/devlink/netlink_gen.c | 5 ++-- 6 files changed, 73 insertions(+), 2 deletions(-) diff --git a/Documentation/netlink/specs/devlink.yaml b/Documentation/netlink/specs/devlink.yaml index 3db59c965869..4242a3431320 100644 --- a/Documentation/netlink/specs/devlink.yaml +++ b/Documentation/netlink/specs/devlink.yaml @@ -119,6 +119,14 @@ definitions: name: none - name: basic + - + type: enum + name: eswitch-state + entries: + - + name: none + - + name: basic - type: enum name: dpipe-header-id @@ -857,6 +865,10 @@ attribute-sets: name: health-reporter-burst-period type: u64 doc: Time (in msec) for recoveries before starting the grace period. + - + name: eswitch-state + type: u8 + enum: eswitch-state - name: dl-dev-stats subset-of: devlink @@ -1609,6 +1621,7 @@ operations: - eswitch-mode - eswitch-inline-mode - eswitch-encap-mode + - eswitch-state - name: eswitch-set diff --git a/Documentation/networking/devlink/devlink-eswitch-attr.rst b/Documentation/networking/devlink/devlink-eswitch-attr.rst index 08bb39ab1528..13ad1ed300ee 100644 --- a/Documentation/networking/devlink/devlink-eswitch-attr.rst +++ b/Documentation/networking/devlink/devlink-eswitch-attr.rst @@ -57,6 +57,18 @@ The following is a list of E-Switch attributes. * ``none`` Disable encapsulation support. * ``basic`` Enable encapsulation support. + * - ``state`` + - enum + - The state of the E-Switch. + In situations where the user want to bring up the e-switch, they want to + have the ability to block traffic towards the FDB until FDB is fully + programmed. + The state can be one of the following: + + * ``active`` Traffic is enabled on this eswitch FDB - default mode + * ``inactive`` Traffic is disabled on this eswitch FDB - no traffic + will be forwarded to/from this eswitch FDB + Example Usage ============= @@ -74,3 +86,6 @@ Example Usage # enable encap-mode with legacy mode $ devlink dev eswitch set pci/0000:08:00.0 mode legacy inline-mode none encap-mode basic + + # enable switchdev mode in inactive state + $ devlink dev eswitch set pci/0000:08:00.0 mode switchdev state inactive diff --git a/include/net/devlink.h b/include/net/devlink.h index 8d4362f010e4..aca56a905ab8 100644 --- a/include/net/devlink.h +++ b/include/net/devlink.h @@ -1369,6 +1369,11 @@ struct devlink_ops { int (*eswitch_encap_mode_set)(struct devlink *devlink, enum devlink_eswitch_encap_mode encap_mode, struct netlink_ext_ack *extack); + int (*eswitch_state_get)(struct devlink *devlink, + enum devlink_eswitch_state *state); + int (*eswitch_state_set)(struct devlink *devlink, + enum devlink_eswitch_state state, + struct netlink_ext_ack *extack); int (*info_get)(struct devlink *devlink, struct devlink_info_req *req, struct netlink_ext_ack *extack); /** diff --git a/include/uapi/linux/devlink.h b/include/uapi/linux/devlink.h index bcad11a787a5..a01443810658 100644 --- a/include/uapi/linux/devlink.h +++ b/include/uapi/linux/devlink.h @@ -195,6 +195,11 @@ enum devlink_eswitch_encap_mode { DEVLINK_ESWITCH_ENCAP_MODE_BASIC, }; +enum devlink_eswitch_state { + DEVLINK_ESWITCH_STATE_INACTIVE, + DEVLINK_ESWITCH_STATE_ACTIVE, +}; + enum devlink_port_flavour { DEVLINK_PORT_FLAVOUR_PHYSICAL, /* Any kind of a port physically * facing the user. @@ -638,6 +643,8 @@ enum devlink_attr { DEVLINK_ATTR_HEALTH_REPORTER_BURST_PERIOD, /* u64 */ + DEVLINK_ATTR_ESWITCH_STATE, /* u8 */ + /* Add new attributes above here, update the spec in * Documentation/netlink/specs/devlink.yaml and re-generate * net/devlink/netlink_gen.c. diff --git a/net/devlink/dev.c b/net/devlink/dev.c index 02602704bdea..1eea3e2c1ade 100644 --- a/net/devlink/dev.c +++ b/net/devlink/dev.c @@ -672,6 +672,17 @@ static int devlink_nl_eswitch_fill(struct sk_buff *msg, struct devlink *devlink, goto nla_put_failure; } + if (ops->eswitch_state_get) { + enum devlink_eswitch_state state; + + err = ops->eswitch_state_get(devlink, &state); + if (err) + return err; + err = nla_put_u8(msg, DEVLINK_ATTR_ESWITCH_STATE, state); + if (err) + return err; + } + genlmsg_end(msg, hdr); return 0; @@ -706,6 +717,7 @@ int devlink_nl_eswitch_set_doit(struct sk_buff *skb, struct genl_info *info) struct devlink *devlink = info->user_ptr[0]; const struct devlink_ops *ops = devlink->ops; enum devlink_eswitch_encap_mode encap_mode; + enum devlink_eswitch_state state; u8 inline_mode; int err = 0; u16 mode; @@ -722,6 +734,24 @@ int devlink_nl_eswitch_set_doit(struct sk_buff *skb, struct genl_info *info) return err; } + state = DEVLINK_ESWITCH_STATE_ACTIVE; + if (info->attrs[DEVLINK_ATTR_ESWITCH_STATE]) { + if (!ops->eswitch_state_set) + return -EOPNOTSUPP; + state = nla_get_u8(info->attrs[DEVLINK_ATTR_ESWITCH_STATE]); + } + /* If user did not supply the state attribute, the default is + * active state. If the state was not explicitly set, set the default + * state for drivers that support eswitch state. + * Keep this after mode-set as state handling can be dependent on + * the eswitch mode. + */ + if (ops->eswitch_state_set) { + err = ops->eswitch_state_set(devlink, state, info->extack); + if (err) + return err; + } + if (info->attrs[DEVLINK_ATTR_ESWITCH_INLINE_MODE]) { if (!ops->eswitch_inline_mode_set) return -EOPNOTSUPP; diff --git a/net/devlink/netlink_gen.c b/net/devlink/netlink_gen.c index 9fd00977d59e..e0910fb2214d 100644 --- a/net/devlink/netlink_gen.c +++ b/net/devlink/netlink_gen.c @@ -226,12 +226,13 @@ static const struct nla_policy devlink_eswitch_get_nl_policy[DEVLINK_ATTR_DEV_NA }; /* DEVLINK_CMD_ESWITCH_SET - do */ -static const struct nla_policy devlink_eswitch_set_nl_policy[DEVLINK_ATTR_ESWITCH_ENCAP_MODE + 1] = { +static const struct nla_policy devlink_eswitch_set_nl_policy[DEVLINK_ATTR_ESWITCH_STATE + 1] = { [DEVLINK_ATTR_BUS_NAME] = { .type = NLA_NUL_STRING, }, [DEVLINK_ATTR_DEV_NAME] = { .type = NLA_NUL_STRING, }, [DEVLINK_ATTR_ESWITCH_MODE] = NLA_POLICY_MAX(NLA_U16, 1), [DEVLINK_ATTR_ESWITCH_INLINE_MODE] = NLA_POLICY_MAX(NLA_U8, 3), [DEVLINK_ATTR_ESWITCH_ENCAP_MODE] = NLA_POLICY_MAX(NLA_U8, 1), + [DEVLINK_ATTR_ESWITCH_STATE] = NLA_POLICY_MAX(NLA_U8, 1), }; /* DEVLINK_CMD_DPIPE_TABLE_GET - do */ @@ -822,7 +823,7 @@ const struct genl_split_ops devlink_nl_ops[74] = { .doit = devlink_nl_eswitch_set_doit, .post_doit = devlink_nl_post_doit, .policy = devlink_eswitch_set_nl_policy, - .maxattr = DEVLINK_ATTR_ESWITCH_ENCAP_MODE, + .maxattr = DEVLINK_ATTR_ESWITCH_STATE, .flags = GENL_ADMIN_PERM | GENL_CMD_CAP_DO, }, { -- 2.51.0