mirror of
https://git.proxmox.com/git/mirror_iproute2
synced 2025-10-19 07:17:58 +00:00
devlink: Support setting port function hardware address
Support setting devlink port function hardware address. Example of a PCI VF port which supports a port function: Set hardware address of the VF's port function. $ devlink port show pci/0000:06:00.0/2 pci/0000:06:00.0/2: type eth netdev enp6s0pf0vf1 flavour pcivf pfnum 0 vfnum 1 function: hw_addr 00:00:00:00:00:00 $ devlink port function set pci/0000:06:00.0/2 hw_addr 00:11:22:33:44:55 $ devlink port show pci/0000:06:00.0/2 pci/0000:06:00.0/2: type eth netdev enp6s0pf0vf1 flavour pcivf pfnum 0 vfnum 1 function: hw_addr 00:11:22:33:44:55 Signed-off-by: Parav Pandit <parav@mellanox.com> Reviewed-by: Jiri Pirko <jiri@mellanox.com> Signed-off-by: David Ahern <dsahern@kernel.org>
This commit is contained in:
parent
b3adafd154
commit
4dca81e9a8
@ -294,6 +294,7 @@ static void ifname_map_free(struct ifname_map *ifname_map)
|
||||
#define DL_OPT_TRAP_POLICER_RATE BIT(35)
|
||||
#define DL_OPT_TRAP_POLICER_BURST BIT(36)
|
||||
#define DL_OPT_HEALTH_REPORTER_AUTO_DUMP BIT(37)
|
||||
#define DL_OPT_PORT_FUNCTION_HW_ADDR BIT(38)
|
||||
|
||||
struct dl_opts {
|
||||
uint64_t present; /* flags of present items */
|
||||
@ -339,6 +340,8 @@ struct dl_opts {
|
||||
uint32_t trap_policer_id;
|
||||
uint64_t trap_policer_rate;
|
||||
uint64_t trap_policer_burst;
|
||||
char port_function_hw_addr[MAX_ADDR_LEN];
|
||||
uint32_t port_function_hw_addr_len;
|
||||
};
|
||||
|
||||
struct dl {
|
||||
@ -1302,6 +1305,17 @@ static int trap_action_get(const char *actionstr,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hw_addr_parse(const char *addrstr, char *hw_addr, uint32_t *len)
|
||||
{
|
||||
int alen;
|
||||
|
||||
alen = ll_addr_a2n(hw_addr, MAX_ADDR_LEN, addrstr);
|
||||
if (alen < 0)
|
||||
return -EINVAL;
|
||||
*len = alen;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct dl_args_metadata {
|
||||
uint64_t o_flag;
|
||||
char err_msg[DL_ARGS_REQUIRED_MAX_ERR_LEN];
|
||||
@ -1332,6 +1346,7 @@ static const struct dl_args_metadata dl_args_required[] = {
|
||||
{DL_OPT_HEALTH_REPORTER_NAME, "Reporter's name is expected."},
|
||||
{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."},
|
||||
};
|
||||
|
||||
static int dl_args_finding_required_validate(uint64_t o_required,
|
||||
@ -1698,6 +1713,20 @@ static int dl_argv_parse(struct dl *dl, uint64_t o_required,
|
||||
if (err)
|
||||
return err;
|
||||
o_found |= DL_OPT_TRAP_POLICER_BURST;
|
||||
} else if (dl_argv_match(dl, "hw_addr") &&
|
||||
(o_all & DL_OPT_PORT_FUNCTION_HW_ADDR)) {
|
||||
const char *addrstr;
|
||||
|
||||
dl_arg_inc(dl);
|
||||
err = dl_argv_str(dl, &addrstr);
|
||||
if (err)
|
||||
return err;
|
||||
err = hw_addr_parse(addrstr, opts->port_function_hw_addr,
|
||||
&opts->port_function_hw_addr_len);
|
||||
if (err)
|
||||
return err;
|
||||
o_found |= DL_OPT_PORT_FUNCTION_HW_ADDR;
|
||||
|
||||
} else {
|
||||
pr_err("Unknown option \"%s\"\n", dl_argv(dl));
|
||||
return -EINVAL;
|
||||
@ -1714,6 +1743,18 @@ static int dl_argv_parse(struct dl *dl, uint64_t o_required,
|
||||
return dl_args_finding_required_validate(o_required, o_found);
|
||||
}
|
||||
|
||||
static void
|
||||
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);
|
||||
mnl_attr_nest_end(nlh, nest);
|
||||
}
|
||||
|
||||
static void dl_opts_put(struct nlmsghdr *nlh, struct dl *dl)
|
||||
{
|
||||
struct dl_opts *opts = &dl->opts;
|
||||
@ -1837,6 +1878,8 @@ 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)
|
||||
dl_function_attr_put(nlh, opts);
|
||||
}
|
||||
|
||||
static int dl_argv_parse_put(struct nlmsghdr *nlh, struct dl *dl,
|
||||
@ -3221,6 +3264,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");
|
||||
}
|
||||
|
||||
static const char *port_type_name(uint32_t type)
|
||||
@ -3438,6 +3482,38 @@ static int cmd_port_unsplit(struct dl *dl)
|
||||
return _mnlg_socket_sndrcv(dl->nlg, nlh, NULL, NULL);
|
||||
}
|
||||
|
||||
static void cmd_port_function_help(void)
|
||||
{
|
||||
pr_err("Usage: devlink port function set DEV/PORT_INDEX [ hw_addr ADDR ]\n");
|
||||
}
|
||||
|
||||
static int cmd_port_function_set(struct dl *dl)
|
||||
{
|
||||
struct nlmsghdr *nlh;
|
||||
int err;
|
||||
|
||||
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);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return _mnlg_socket_sndrcv(dl->nlg, nlh, NULL, NULL);
|
||||
}
|
||||
|
||||
static int cmd_port_function(struct dl *dl)
|
||||
{
|
||||
if (dl_argv_match(dl, "help") || dl_no_arg(dl)) {
|
||||
cmd_port_function_help();
|
||||
return 0;
|
||||
} else if (dl_argv_match(dl, "set")) {
|
||||
dl_arg_inc(dl);
|
||||
return cmd_port_function_set(dl);
|
||||
}
|
||||
pr_err("Command \"%s\" not found\n", dl_argv(dl));
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static int cmd_port(struct dl *dl)
|
||||
{
|
||||
if (dl_argv_match(dl, "help")) {
|
||||
@ -3456,6 +3532,9 @@ static int cmd_port(struct dl *dl)
|
||||
} else if (dl_argv_match(dl, "unsplit")) {
|
||||
dl_arg_inc(dl);
|
||||
return cmd_port_unsplit(dl);
|
||||
} else if (dl_argv_match(dl, "function")) {
|
||||
dl_arg_inc(dl);
|
||||
return cmd_port_function(dl);
|
||||
}
|
||||
pr_err("Command \"%s\" not found\n", dl_argv(dl));
|
||||
return -ENOENT;
|
||||
|
Loading…
Reference in New Issue
Block a user