Merge branch 'devlink-port-mgmt' into next
Parav Pandit says:
====================
This patchset implements devlink port add, delete and function state
management commands.
An example sequence for a PCI SF:
Set the device in switchdev mode:
$ devlink dev eswitch set pci/0000:06:00.0 mode switchdev
View ports in switchdev mode:
$ devlink port show
pci/0000:06:00.0/65535: type eth netdev ens2f0np0 flavour physical port 0 s=
plittable false
Add a subfunction port for PCI PF 0 with sfnumber 88:
$ 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 pfn=
um 0 sfnum 88 splittable false
function:
hw_addr 00:00:00:00:00:00 state inactive opstate detached
Show a newly added port:
$ devlink port show pci/0000:06:00.0/32768
pci/0000:06:00.0/32768: type eth netdev ens2f0npf0sf88 flavour pcisf contro=
ller 0 pfnum 0 sfnum 88 splittable false
function:
hw_addr 00:00:00:00:00:00 state inactive opstate detached
Set the function state to active:
$ devlink port function set pci/0000:06:00.0/32768 hw_addr 00:00:00:00:88:8=
8 state active
Show the port in JSON format:
$ 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"
}
}
}
}
Set the function state to active:
$ devlink port function set pci/0000:06:00.0/32768 state inactive
Delete the port after use:
$ devlink port del pci/0000:06:00.0/32768
====================
Signed-off-by: David Ahern <dsahern@kernel.org>
This commit is contained in:
commit
d10f2a4bd8
|
|
@ -306,6 +306,10 @@ static void ifname_map_free(struct ifname_map *ifname_map)
|
|||
#define DL_OPT_FLASH_OVERWRITE BIT(39)
|
||||
#define DL_OPT_RELOAD_ACTION BIT(40)
|
||||
#define DL_OPT_RELOAD_LIMIT BIT(41)
|
||||
#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 */
|
||||
|
|
@ -356,6 +360,10 @@ struct dl_opts {
|
|||
uint32_t overwrite_mask;
|
||||
enum devlink_reload_action reload_action;
|
||||
enum devlink_reload_limit reload_limit;
|
||||
uint32_t port_sfnumber;
|
||||
uint16_t port_flavour;
|
||||
uint16_t port_pfnumber;
|
||||
uint8_t port_fn_state;
|
||||
};
|
||||
|
||||
struct dl {
|
||||
|
|
@ -741,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)
|
||||
|
|
@ -1383,6 +1392,51 @@ static int reload_limit_get(struct dl *dl, const char *limitstr,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct str_num_map port_flavour_map[] = {
|
||||
{ .str = "physical", .num = DEVLINK_PORT_FLAVOUR_PHYSICAL },
|
||||
{ .str = "cpu", .num = DEVLINK_PORT_FLAVOUR_CPU },
|
||||
{ .str = "dsa", .num = DEVLINK_PORT_FLAVOUR_DSA },
|
||||
{ .str = "pcipf", .num = DEVLINK_PORT_FLAVOUR_PCI_PF },
|
||||
{ .str = "pcivf", .num = DEVLINK_PORT_FLAVOUR_PCI_VF },
|
||||
{ .str = "pcisf", .num = DEVLINK_PORT_FLAVOUR_PCI_SF },
|
||||
{ .str = "virtual", .num = DEVLINK_PORT_FLAVOUR_VIRTUAL},
|
||||
{ .str = NULL, },
|
||||
};
|
||||
|
||||
static struct str_num_map port_fn_state_map[] = {
|
||||
{ .str = "inactive", .num = DEVLINK_PORT_FN_STATE_INACTIVE},
|
||||
{ .str = "active", .num = DEVLINK_PORT_FN_STATE_ACTIVE },
|
||||
{ .str = NULL, }
|
||||
};
|
||||
|
||||
static struct str_num_map port_fn_opstate_map[] = {
|
||||
{ .str = "attached", .num = DEVLINK_PORT_FN_OPSTATE_ATTACHED},
|
||||
{ .str = "detached", .num = DEVLINK_PORT_FN_OPSTATE_DETACHED},
|
||||
{ .str = NULL, }
|
||||
};
|
||||
|
||||
static int port_flavour_parse(const char *flavour, uint16_t *value)
|
||||
{
|
||||
int num;
|
||||
|
||||
num = str_map_lookup_str(port_flavour_map, flavour);
|
||||
if (num < 0)
|
||||
return num;
|
||||
*value = num;
|
||||
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];
|
||||
|
|
@ -1414,6 +1468,8 @@ static const struct dl_args_metadata dl_args_required[] = {
|
|||
{DL_OPT_TRAP_NAME, "Trap's name is expected."},
|
||||
{DL_OPT_TRAP_GROUP_NAME, "Trap group's name is expected."},
|
||||
{DL_OPT_PORT_FUNCTION_HW_ADDR, "Port function's hardware address is expected."},
|
||||
{DL_OPT_PORT_FLAVOUR, "Port flavour is expected."},
|
||||
{DL_OPT_PORT_PFNUMBER, "Port PCI PF number is expected."},
|
||||
};
|
||||
|
||||
static int dl_args_finding_required_validate(uint64_t o_required,
|
||||
|
|
@ -1832,7 +1888,42 @@ 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;
|
||||
|
||||
dl_arg_inc(dl);
|
||||
err = dl_argv_str(dl, &flavourstr);
|
||||
if (err)
|
||||
return err;
|
||||
err = port_flavour_parse(flavourstr, &opts->port_flavour);
|
||||
if (err)
|
||||
return err;
|
||||
o_found |= DL_OPT_PORT_FLAVOUR;
|
||||
} else if (dl_argv_match(dl, "pfnum") && (o_all & DL_OPT_PORT_PFNUMBER)) {
|
||||
dl_arg_inc(dl);
|
||||
err = dl_argv_uint16_t(dl, &opts->port_pfnumber);
|
||||
if (err)
|
||||
return err;
|
||||
o_found |= DL_OPT_PORT_PFNUMBER;
|
||||
} else if (dl_argv_match(dl, "sfnum") && (o_all & DL_OPT_PORT_SFNUMBER)) {
|
||||
dl_arg_inc(dl);
|
||||
err = dl_argv_uint32_t(dl, &opts->port_sfnumber);
|
||||
if (err)
|
||||
return err;
|
||||
o_found |= DL_OPT_PORT_SFNUMBER;
|
||||
} else {
|
||||
pr_err("Unknown option \"%s\"\n", dl_argv(dl));
|
||||
return -EINVAL;
|
||||
|
|
@ -1855,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);
|
||||
}
|
||||
|
||||
|
|
@ -2013,8 +2109,14 @@ 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);
|
||||
if (opts->present & DL_OPT_PORT_PFNUMBER)
|
||||
mnl_attr_put_u16(nlh, DEVLINK_ATTR_PORT_PCI_PF_NUMBER, opts->port_pfnumber);
|
||||
if (opts->present & DL_OPT_PORT_SFNUMBER)
|
||||
mnl_attr_put_u32(nlh, DEVLINK_ATTR_PORT_PCI_SF_NUMBER, opts->port_sfnumber);
|
||||
}
|
||||
|
||||
static int dl_argv_parse_put(struct nlmsghdr *nlh, struct dl *dl,
|
||||
|
|
@ -3700,8 +3802,10 @@ 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");
|
||||
}
|
||||
|
||||
static const char *port_type_name(uint32_t type)
|
||||
|
|
@ -3717,25 +3821,13 @@ static const char *port_type_name(uint32_t type)
|
|||
|
||||
static const char *port_flavour_name(uint16_t flavour)
|
||||
{
|
||||
switch (flavour) {
|
||||
case DEVLINK_PORT_FLAVOUR_PHYSICAL:
|
||||
return "physical";
|
||||
case DEVLINK_PORT_FLAVOUR_CPU:
|
||||
return "cpu";
|
||||
case DEVLINK_PORT_FLAVOUR_DSA:
|
||||
return "dsa";
|
||||
case DEVLINK_PORT_FLAVOUR_PCI_PF:
|
||||
return "pcipf";
|
||||
case DEVLINK_PORT_FLAVOUR_PCI_VF:
|
||||
return "pcivf";
|
||||
case DEVLINK_PORT_FLAVOUR_VIRTUAL:
|
||||
return "virtual";
|
||||
default:
|
||||
return "<unknown flavour>";
|
||||
}
|
||||
const char *str;
|
||||
|
||||
str = str_map_lookup_u16(port_flavour_map, flavour);
|
||||
return str ? str : "<unknown flavour>";
|
||||
}
|
||||
|
||||
static void pr_out_port_pfvf_num(struct dl *dl, struct nlattr **tb)
|
||||
static void pr_out_port_pfvfsf_num(struct dl *dl, struct nlattr **tb)
|
||||
{
|
||||
uint16_t fn_num;
|
||||
|
||||
|
|
@ -3750,6 +3842,10 @@ static void pr_out_port_pfvf_num(struct dl *dl, struct nlattr **tb)
|
|||
fn_num = mnl_attr_get_u16(tb[DEVLINK_ATTR_PORT_PCI_VF_NUMBER]);
|
||||
print_uint(PRINT_ANY, "vfnum", " vfnum %u", fn_num);
|
||||
}
|
||||
if (tb[DEVLINK_ATTR_PORT_PCI_SF_NUMBER]) {
|
||||
fn_num = mnl_attr_get_u32(tb[DEVLINK_ATTR_PORT_PCI_SF_NUMBER]);
|
||||
print_uint(PRINT_ANY, "sfnum", " sfnum %u", fn_num);
|
||||
}
|
||||
if (tb[DEVLINK_ATTR_PORT_EXTERNAL]) {
|
||||
uint8_t external;
|
||||
|
||||
|
|
@ -3758,6 +3854,22 @@ static void pr_out_port_pfvf_num(struct dl *dl, struct nlattr **tb)
|
|||
}
|
||||
}
|
||||
|
||||
static const char *port_fn_state(uint8_t state)
|
||||
{
|
||||
const char *str;
|
||||
|
||||
str = str_map_lookup_u8(port_fn_state_map, state);
|
||||
return str ? str : "<unknown state>";
|
||||
}
|
||||
|
||||
static const char *port_fn_opstate(uint8_t state)
|
||||
{
|
||||
const char *str;
|
||||
|
||||
str = str_map_lookup_u8(port_fn_opstate_map, state);
|
||||
return str ? str : "<unknown state>";
|
||||
}
|
||||
|
||||
static void pr_out_port_function(struct dl *dl, struct nlattr **tb_port)
|
||||
{
|
||||
struct nlattr *tb[DEVLINK_PORT_FUNCTION_ATTR_MAX + 1] = {};
|
||||
|
|
@ -3774,16 +3886,33 @@ static void pr_out_port_function(struct dl *dl, struct nlattr **tb_port)
|
|||
if (err != MNL_CB_OK)
|
||||
return;
|
||||
|
||||
if (!tb[DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR])
|
||||
return;
|
||||
|
||||
len = mnl_attr_get_payload_len(tb[DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR]);
|
||||
data = mnl_attr_get_payload(tb[DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR]);
|
||||
|
||||
pr_out_object_start(dl, "function");
|
||||
check_indent_newline(dl);
|
||||
print_string(PRINT_ANY, "hw_addr", "hw_addr %s",
|
||||
ll_addr_n2a(data, len, 0, hw_addr, sizeof(hw_addr)));
|
||||
|
||||
if (tb[DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR]) {
|
||||
len = mnl_attr_get_payload_len(tb[DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR]);
|
||||
data = mnl_attr_get_payload(tb[DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR]);
|
||||
|
||||
print_string(PRINT_ANY, "hw_addr", "hw_addr %s",
|
||||
ll_addr_n2a(data, len, 0, hw_addr, sizeof(hw_addr)));
|
||||
}
|
||||
if (tb[DEVLINK_PORT_FN_ATTR_STATE]) {
|
||||
uint8_t state;
|
||||
|
||||
state = mnl_attr_get_u8(tb[DEVLINK_PORT_FN_ATTR_STATE]);
|
||||
|
||||
print_string(PRINT_ANY, "state", " state %s",
|
||||
port_fn_state(state));
|
||||
}
|
||||
if (tb[DEVLINK_PORT_FN_ATTR_OPSTATE]) {
|
||||
uint8_t state;
|
||||
|
||||
state = mnl_attr_get_u8(tb[DEVLINK_PORT_FN_ATTR_OPSTATE]);
|
||||
|
||||
print_string(PRINT_ANY, "opstate", " opstate %s",
|
||||
port_fn_opstate(state));
|
||||
}
|
||||
|
||||
if (!dl->json_output)
|
||||
__pr_out_indent_dec();
|
||||
pr_out_object_end(dl);
|
||||
|
|
@ -3827,7 +3956,8 @@ static void pr_out_port(struct dl *dl, struct nlattr **tb)
|
|||
switch (port_flavour) {
|
||||
case DEVLINK_PORT_FLAVOUR_PCI_PF:
|
||||
case DEVLINK_PORT_FLAVOUR_PCI_VF:
|
||||
pr_out_port_pfvf_num(dl, tb);
|
||||
case DEVLINK_PORT_FLAVOUR_PCI_SF:
|
||||
pr_out_port_pfvfsf_num(dl, tb);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
@ -3937,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)
|
||||
|
|
@ -3945,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;
|
||||
|
||||
|
|
@ -3970,6 +4105,58 @@ static int cmd_port_function(struct dl *dl)
|
|||
static int cmd_health(struct dl *dl);
|
||||
static int __cmd_health_show(struct dl *dl, bool show_device, bool show_port);
|
||||
|
||||
static void cmd_port_add_help(void)
|
||||
{
|
||||
pr_err(" devlink port add { DEV | DEV/PORT_INDEX } flavour FLAVOUR pfnum PFNUM [ sfnum SFNUM ]\n");
|
||||
}
|
||||
|
||||
static int cmd_port_add(struct dl *dl)
|
||||
{
|
||||
struct nlmsghdr *nlh;
|
||||
int err;
|
||||
|
||||
if (dl_argv_match(dl, "help") || dl_no_arg(dl)) {
|
||||
cmd_port_add_help();
|
||||
return 0;
|
||||
}
|
||||
|
||||
nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_PORT_NEW,
|
||||
NLM_F_REQUEST | NLM_F_ACK);
|
||||
|
||||
err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE | DL_OPT_HANDLEP |
|
||||
DL_OPT_PORT_FLAVOUR | DL_OPT_PORT_PFNUMBER,
|
||||
DL_OPT_PORT_SFNUMBER);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return _mnlg_socket_sndrcv(dl->nlg, nlh, cmd_port_show_cb, dl);
|
||||
}
|
||||
|
||||
static void cmd_port_del_help(void)
|
||||
{
|
||||
pr_err(" devlink port del DEV/PORT_INDEX\n");
|
||||
}
|
||||
|
||||
static int cmd_port_del(struct dl *dl)
|
||||
{
|
||||
struct nlmsghdr *nlh;
|
||||
int err;
|
||||
|
||||
if (dl_argv_match(dl, "help") || dl_no_arg(dl)) {
|
||||
cmd_port_del_help();
|
||||
return 0;
|
||||
}
|
||||
|
||||
nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_PORT_DEL,
|
||||
NLM_F_REQUEST | NLM_F_ACK);
|
||||
|
||||
err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLEP, 0);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return _mnlg_socket_sndrcv(dl->nlg, nlh, NULL, NULL);
|
||||
}
|
||||
|
||||
static int cmd_port(struct dl *dl)
|
||||
{
|
||||
if (dl_argv_match(dl, "help")) {
|
||||
|
|
@ -4000,7 +4187,14 @@ static int cmd_port(struct dl *dl)
|
|||
} else {
|
||||
return cmd_health(dl);
|
||||
}
|
||||
} else if (dl_argv_match(dl, "add")) {
|
||||
dl_arg_inc(dl);
|
||||
return cmd_port_add(dl);
|
||||
} else if (dl_argv_match(dl, "del")) {
|
||||
dl_arg_inc(dl);
|
||||
return cmd_port_del(dl);
|
||||
}
|
||||
|
||||
pr_err("Command \"%s\" not found\n", dl_argv(dl));
|
||||
return -ENOENT;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -340,4 +340,13 @@ int parse_mapping(int *argcp, char ***argvp, bool allow_all,
|
|||
int (*mapping_cb)(__u32 key, char *value, void *data),
|
||||
void *mapping_cb_data);
|
||||
|
||||
struct str_num_map {
|
||||
const char *str;
|
||||
int num;
|
||||
};
|
||||
|
||||
int str_map_lookup_str(const struct str_num_map *map, const char *needle);
|
||||
const char *str_map_lookup_u16(const struct str_num_map *map, uint16_t val);
|
||||
const char *str_map_lookup_u8(const struct str_num_map *map, uint8_t val);
|
||||
|
||||
#endif /* __UTILS_H__ */
|
||||
|
|
|
|||
41
lib/utils.c
41
lib/utils.c
|
|
@ -1937,3 +1937,44 @@ int parse_mapping(int *argcp, char ***argvp, bool allow_all,
|
|||
return parse_mapping_gen(argcp, argvp, parse_mapping_num,
|
||||
mapping_cb, mapping_cb_data);
|
||||
}
|
||||
|
||||
int str_map_lookup_str(const struct str_num_map *map, const char *needle)
|
||||
{
|
||||
if (!needle)
|
||||
return -EINVAL;
|
||||
|
||||
/* Process array which is NULL terminated by the string. */
|
||||
while (map && map->str) {
|
||||
if (strcmp(map->str, needle) == 0)
|
||||
return map->num;
|
||||
|
||||
map++;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
const char *str_map_lookup_u16(const struct str_num_map *map, uint16_t val)
|
||||
{
|
||||
int num = val;
|
||||
|
||||
while (map && map->str) {
|
||||
if (num == map->num)
|
||||
return map->str;
|
||||
|
||||
map++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *str_map_lookup_u8(const struct str_num_map *map, uint8_t val)
|
||||
{
|
||||
int num = val;
|
||||
|
||||
while (map && map->str) {
|
||||
if (num == map->num)
|
||||
return map->str;
|
||||
|
||||
map++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,33 @@ devlink-port \- devlink port configuration
|
|||
.B devlink port health
|
||||
.RI "{ " show " | " recover " | " diagnose " | " dump " | " set " }"
|
||||
|
||||
.ti -8
|
||||
.BI "devlink port add"
|
||||
.RB "["
|
||||
.IR "DEV | DEV/PORT_INDEX"
|
||||
.RB "] "
|
||||
.RB "[ " flavour
|
||||
.IR FLAVOUR " ]"
|
||||
.RB "[ " pcipf
|
||||
.IR PFNUMBER " ]"
|
||||
.RB "{ " pcisf
|
||||
.IR SFNUMBER " }"
|
||||
.br
|
||||
|
||||
.ti -8
|
||||
.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
|
||||
|
||||
|
|
@ -99,6 +126,65 @@ If this argument is omitted all ports are listed.
|
|||
Is an alias for
|
||||
.BR devlink-health (8).
|
||||
|
||||
.ti -8
|
||||
.SS devlink port add - add a devlink port
|
||||
.PP
|
||||
.B "DEV"
|
||||
- specifies the devlink device to operate on. or
|
||||
|
||||
.PP
|
||||
.B "DEV/PORT_INDEX"
|
||||
- specifies the devlink port index to use for the requested new port.
|
||||
This is optional. When ommited, driver allocates unique port index.
|
||||
|
||||
.TP
|
||||
.BR flavour " { " pcipf " | " pcisf " } "
|
||||
set port flavour
|
||||
|
||||
.I pcipf
|
||||
- PCI PF port
|
||||
|
||||
.I pcisf
|
||||
- PCI SF port
|
||||
|
||||
.TP
|
||||
.BR pfnum " { " pfnumber " } "
|
||||
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.
|
||||
|
||||
.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
|
||||
.PP
|
||||
.B "DEV/PORT_INDEX"
|
||||
- specifies the devlink port to delete.
|
||||
|
||||
.SH "EXAMPLES"
|
||||
.PP
|
||||
devlink port show
|
||||
|
|
@ -135,6 +221,47 @@ devlink port health show pci/0000:01:00.0/1 reporter tx
|
|||
.RS 4
|
||||
Shows status and configuration of tx reporter registered on pci/0000:01:00.0/1 devlink port.
|
||||
.RE
|
||||
.PP
|
||||
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. 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
|
||||
.BR devlink (8),
|
||||
|
|
|
|||
Loading…
Reference in New Issue