devlink: Support set of port function state

Support set operation of the devlink port function state.

Example of a PCI SF port function which supports the state:

$ devlink dev eswitch set pci/0000:06:00.0 mode switchdev

$ devlink port show
pci/0000:06:00.0/65535: type eth netdev ens2f0np0 flavour physical port 0 splittable false

$ devlink port add pci/0000:06:00.0 flavour pcisf pfnum 0 sfnum 88
pci/0000:08:00.0/32768: type eth netdev eth6 flavour pcisf controller 0 pfnum 0 sfnum 88 splittable false
  function:
    hw_addr 00:00:00:00:00:00 state inactive opstate detached

$ devlink port show pci/0000:06:00.0/32768
pci/0000:06:00.0/32768: type eth netdev ens2f0npf0sf88 flavour pcisf controller 0 pfnum 0 sfnum 88 splittable false
  function:
    hw_addr 00:00:00:00:00:00 state inactive opstate detached

$ devlink port function set pci/0000:06:00.0/32768 hw_addr 00:00:00:00:88:88 state active

$ devlink port show pci/0000:06:00.0/32768 -jp
{
    "port": {
        "pci/0000:06:00.0/32768": {
            "type": "eth",
            "netdev": "ens2f0npf0sf88",
            "flavour": "pcisf",
            "controller": 0,
            "pfnum": 0,
            "sfnum": 88,
            "splittable": false,
            "function": {
                "hw_addr": "00:00:00:00:88:88",
                "state": "active",
                "opstate": "attached"
            }
        }
    }
}

Signed-off-by: Parav Pandit <parav@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: David Ahern <dsahern@kernel.org>
This commit is contained in:
Parav Pandit 2021-02-01 23:35:51 +02:00 committed by David Ahern
parent 249465d3bf
commit bdfb9f1bd6
2 changed files with 110 additions and 9 deletions

View File

@ -309,6 +309,7 @@ static void ifname_map_free(struct ifname_map *ifname_map)
#define DL_OPT_PORT_FLAVOUR BIT(42)
#define DL_OPT_PORT_PFNUMBER BIT(43)
#define DL_OPT_PORT_SFNUMBER BIT(44)
#define DL_OPT_PORT_FUNCTION_STATE BIT(45)
struct dl_opts {
uint64_t present; /* flags of present items */
@ -362,6 +363,7 @@ struct dl_opts {
uint32_t port_sfnumber;
uint16_t port_flavour;
uint16_t port_pfnumber;
uint8_t port_fn_state;
};
struct dl {
@ -747,6 +749,7 @@ static int attr_stats_cb(const struct nlattr *attr, void *data)
static const enum mnl_attr_data_type
devlink_function_policy[DEVLINK_PORT_FUNCTION_ATTR_MAX + 1] = {
[DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR ] = MNL_TYPE_BINARY,
[DEVLINK_PORT_FN_ATTR_STATE] = MNL_TYPE_U8,
};
static int function_attr_cb(const struct nlattr *attr, void *data)
@ -1423,6 +1426,17 @@ static int port_flavour_parse(const char *flavour, uint16_t *value)
return 0;
}
static int port_fn_state_parse(const char *statestr, uint8_t *state)
{
int num;
num = str_map_lookup_str(port_fn_state_map, statestr);
if (num < 0)
return num;
*state = num;
return 0;
}
struct dl_args_metadata {
uint64_t o_flag;
char err_msg[DL_ARGS_REQUIRED_MAX_ERR_LEN];
@ -1874,6 +1888,19 @@ static int dl_argv_parse(struct dl *dl, uint64_t o_required,
if (err)
return err;
o_found |= DL_OPT_PORT_FUNCTION_HW_ADDR;
} else if (dl_argv_match(dl, "state") &&
(o_all & DL_OPT_PORT_FUNCTION_STATE)) {
const char *statestr;
dl_arg_inc(dl);
err = dl_argv_str(dl, &statestr);
if (err)
return err;
err = port_fn_state_parse(statestr, &opts->port_fn_state);
if (err)
return err;
o_found |= DL_OPT_PORT_FUNCTION_STATE;
} else if (dl_argv_match(dl, "flavour") && (o_all & DL_OPT_PORT_FLAVOUR)) {
const char *flavourstr;
@ -1919,9 +1946,14 @@ dl_function_attr_put(struct nlmsghdr *nlh, const struct dl_opts *opts)
struct nlattr *nest;
nest = mnl_attr_nest_start(nlh, DEVLINK_ATTR_PORT_FUNCTION);
mnl_attr_put(nlh, DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR,
opts->port_function_hw_addr_len,
opts->port_function_hw_addr);
if (opts->present & DL_OPT_PORT_FUNCTION_HW_ADDR)
mnl_attr_put(nlh, DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR,
opts->port_function_hw_addr_len,
opts->port_function_hw_addr);
if (opts->present & DL_OPT_PORT_FUNCTION_STATE)
mnl_attr_put_u8(nlh, DEVLINK_PORT_FN_ATTR_STATE,
opts->port_fn_state);
mnl_attr_nest_end(nlh, nest);
}
@ -2077,7 +2109,7 @@ static void dl_opts_put(struct nlmsghdr *nlh, struct dl *dl)
if (opts->present & DL_OPT_TRAP_POLICER_BURST)
mnl_attr_put_u64(nlh, DEVLINK_ATTR_TRAP_POLICER_BURST,
opts->trap_policer_burst);
if (opts->present & DL_OPT_PORT_FUNCTION_HW_ADDR)
if (opts->present & (DL_OPT_PORT_FUNCTION_HW_ADDR | DL_OPT_PORT_FUNCTION_STATE))
dl_function_attr_put(nlh, opts);
if (opts->present & DL_OPT_PORT_FLAVOUR)
mnl_attr_put_u16(nlh, DEVLINK_ATTR_PORT_FLAVOUR, opts->port_flavour);
@ -3770,7 +3802,7 @@ static void cmd_port_help(void)
pr_err(" devlink port set DEV/PORT_INDEX [ type { eth | ib | auto} ]\n");
pr_err(" devlink port split DEV/PORT_INDEX count COUNT\n");
pr_err(" devlink port unsplit DEV/PORT_INDEX\n");
pr_err(" devlink port function set DEV/PORT_INDEX [ hw_addr ADDR ]\n");
pr_err(" devlink port function set DEV/PORT_INDEX [ hw_addr ADDR ] [ state STATE ]\n");
pr_err(" devlink port health show [ DEV/PORT_INDEX reporter REPORTER_NAME ]\n");
pr_err(" devlink port add DEV/PORT_INDEX flavour FLAVOUR pfnum PFNUM [ sfnum SFNUM ]\n");
pr_err(" devlink port del DEV/PORT_INDEX\n");
@ -4035,7 +4067,7 @@ static int cmd_port_unsplit(struct dl *dl)
static void cmd_port_function_help(void)
{
pr_err("Usage: devlink port function set DEV/PORT_INDEX [ hw_addr ADDR ]\n");
pr_err("Usage: devlink port function set DEV/PORT_INDEX [ hw_addr ADDR ] [ state STATE ]\n");
}
static int cmd_port_function_set(struct dl *dl)
@ -4043,9 +4075,14 @@ static int cmd_port_function_set(struct dl *dl)
struct nlmsghdr *nlh;
int err;
if (dl_no_arg(dl)) {
cmd_port_function_help();
return 0;
}
nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_PORT_SET, NLM_F_REQUEST | NLM_F_ACK);
err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLEP | DL_OPT_PORT_FUNCTION_HW_ADDR, 0);
err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLEP,
DL_OPT_PORT_FUNCTION_HW_ADDR | DL_OPT_PORT_FUNCTION_STATE);
if (err)
return err;

View File

@ -60,6 +60,16 @@ devlink-port \- devlink port configuration
.B devlink port del
.IR DEV/PORT_INDEX
.ti -8
.BR "devlink port function set "
.IR DEV/PORT_INDEX
.RI "{ "
.BR "hw_addr "
.RI "ADDR }"
.RI "{ "
.BR "state"
.RI "STATE }"
.ti -8
.B devlink port help
@ -144,7 +154,30 @@ Specifies PCI pfnumber to use on which a SF device to create
.TP
.BR sfnum " { " sfnumber " } "
Specifies sfnumber to assign to the device of the SF.
This field is optional for those devices which supports auto assignment of the SF number.
This field is optional for those devices which supports auto assignment of the
SF number.
.ti -8
.SS devlink port function set - Set the port function attribute(s).
.PP
.B "DEV/PORT_INDEX"
- specifies the devlink port to operate on.
.TP
.BR hw_addr " ADDR"
- hardware address of the function to set. This is a Ethernet MAC address when
port type is Ethernet.
.TP
.BR state " { " active " | " inactive " } "
- new state of the function to change to.
.I active
- Once configuration of the function is done, activate the function.
.I inactive
- To inactivate the function and its device(s), set to inactive.
.ti -8
.SS devlink port del - delete a devlink port
@ -192,11 +225,42 @@ Shows status and configuration of tx reporter registered on pci/0000:01:00.0/1 d
devlink port add pci/0000:06:00.0 flavour pcisf pfnum 0 sfnum 88
.RS 4
Add a devlink port of flavour PCI SF on PCI PF having number 0 with SF number 88.
To make use of the function an example sequence is to add a port, configure the
function attribute and activate the function. Once function usage is completed,
inactivate the function and finally delete the port. When there is desire to
reuse the port without deletion, it can be reconfigured and activated again when
function is in inactive state and function's operational state is detached.
.RE
.PP
devlink port del pci/0000:06:00.0/1
.RS 4
Delete previously created devlink port.
Delete previously created devlink port. It is recommended to first deactivate
the function if the function supports state management.
.RE
.PP
devlink port function set pci/0000:01:00.0/1 hw_addr 00:00:00:11:22:33
.RS 4
Configure hardware address of the PCI function represented by devlink port.
If the port supports change in function state, hardware address must be configured
before activating the function.
.RE
.PP
devlink port function set pci/0000:01:00.0/1 state active
.RS 4
Activate the function. This will initiate the function enumeration and driver loading.
.RE
.PP
devlink port function set pci/0000:01:00.0/1 state inactive
.RS 4
Deactivate the function. This will initiate the function teardown which results
in driver unload and device removal.
.RE
.PP
devlink port function set pci/0000:01:00.0/1 hw_addr 00:00:00:11:22:33 state active
.RS 4
Configure hardware address and also active the function. When a function is
activated together with other configuration in a single command, all the
configuration is applied first before changing the state to active.
.RE
.SH SEE ALSO