devlink: Add e-switch support
Implement kernel devlink e-switch interface. Currently we allow to get and set the device e-switch mode. Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com> Signed-off-by: Roi Dayan <roid@mellanox.com> Acked-by: Jiri Pirko <jiri@mellanox.com>
This commit is contained in:
parent
27d2b08e23
commit
f57856fab2
|
|
@ -26,6 +26,9 @@
|
||||||
#include "mnlg.h"
|
#include "mnlg.h"
|
||||||
#include "json_writer.h"
|
#include "json_writer.h"
|
||||||
|
|
||||||
|
#define ESWITCH_MODE_LEGACY "legacy"
|
||||||
|
#define ESWITCH_MODE_SWITCHDEV "switchdev"
|
||||||
|
|
||||||
#define pr_err(args...) fprintf(stderr, ##args)
|
#define pr_err(args...) fprintf(stderr, ##args)
|
||||||
#define pr_out(args...) fprintf(stdout, ##args)
|
#define pr_out(args...) fprintf(stdout, ##args)
|
||||||
#define pr_out_sp(num, args...) \
|
#define pr_out_sp(num, args...) \
|
||||||
|
|
@ -128,6 +131,7 @@ static void ifname_map_free(struct ifname_map *ifname_map)
|
||||||
#define DL_OPT_SB_THTYPE BIT(8)
|
#define DL_OPT_SB_THTYPE BIT(8)
|
||||||
#define DL_OPT_SB_TH BIT(9)
|
#define DL_OPT_SB_TH BIT(9)
|
||||||
#define DL_OPT_SB_TC BIT(10)
|
#define DL_OPT_SB_TC BIT(10)
|
||||||
|
#define DL_OPT_ESWITCH_MODE BIT(11)
|
||||||
|
|
||||||
struct dl_opts {
|
struct dl_opts {
|
||||||
uint32_t present; /* flags of present items */
|
uint32_t present; /* flags of present items */
|
||||||
|
|
@ -143,6 +147,7 @@ struct dl_opts {
|
||||||
enum devlink_sb_threshold_type sb_pool_thtype;
|
enum devlink_sb_threshold_type sb_pool_thtype;
|
||||||
uint32_t sb_threshold;
|
uint32_t sb_threshold;
|
||||||
uint16_t sb_tc_index;
|
uint16_t sb_tc_index;
|
||||||
|
enum devlink_eswitch_mode eswitch_mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dl {
|
struct dl {
|
||||||
|
|
@ -297,6 +302,9 @@ static int attr_cb(const struct nlattr *attr, void *data)
|
||||||
if (type == DEVLINK_ATTR_SB_OCC_MAX &&
|
if (type == DEVLINK_ATTR_SB_OCC_MAX &&
|
||||||
mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
|
mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
|
||||||
return MNL_CB_ERROR;
|
return MNL_CB_ERROR;
|
||||||
|
if (type == DEVLINK_ATTR_ESWITCH_MODE &&
|
||||||
|
mnl_attr_validate(attr, MNL_TYPE_U16) < 0)
|
||||||
|
return MNL_CB_ERROR;
|
||||||
tb[type] = attr;
|
tb[type] = attr;
|
||||||
return MNL_CB_OK;
|
return MNL_CB_OK;
|
||||||
}
|
}
|
||||||
|
|
@ -661,6 +669,19 @@ static int threshold_type_get(const char *typestr,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int eswitch_mode_get(const char *typestr, enum devlink_eswitch_mode *p_mode)
|
||||||
|
{
|
||||||
|
if (strcmp(typestr, ESWITCH_MODE_LEGACY) == 0) {
|
||||||
|
*p_mode = DEVLINK_ESWITCH_MODE_LEGACY;
|
||||||
|
} else if (strcmp(typestr, ESWITCH_MODE_SWITCHDEV) == 0) {
|
||||||
|
*p_mode = DEVLINK_ESWITCH_MODE_SWITCHDEV;
|
||||||
|
} else {
|
||||||
|
pr_err("Unknown eswitch mode \"%s\"\n", typestr);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int dl_argv_parse(struct dl *dl, uint32_t o_required,
|
static int dl_argv_parse(struct dl *dl, uint32_t o_required,
|
||||||
uint32_t o_optional)
|
uint32_t o_optional)
|
||||||
{
|
{
|
||||||
|
|
@ -770,6 +791,17 @@ static int dl_argv_parse(struct dl *dl, uint32_t o_required,
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
o_found |= DL_OPT_SB_TC;
|
o_found |= DL_OPT_SB_TC;
|
||||||
|
} else if (dl_argv_match(dl, "mode") &&
|
||||||
|
(o_all & DL_OPT_ESWITCH_MODE)) {
|
||||||
|
const char *typestr;
|
||||||
|
dl_arg_inc(dl);
|
||||||
|
err = dl_argv_str(dl, &typestr);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
err = eswitch_mode_get(typestr, &opts->eswitch_mode);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
o_found |= DL_OPT_ESWITCH_MODE;
|
||||||
} else {
|
} else {
|
||||||
pr_err("Unknown option \"%s\"\n", dl_argv(dl));
|
pr_err("Unknown option \"%s\"\n", dl_argv(dl));
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
@ -823,6 +855,12 @@ static int dl_argv_parse(struct dl *dl, uint32_t o_required,
|
||||||
pr_err("TC index option expected.\n");
|
pr_err("TC index option expected.\n");
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((o_required & DL_OPT_ESWITCH_MODE) && !(o_found & DL_OPT_ESWITCH_MODE)) {
|
||||||
|
pr_err("E-Switch mode option expected.\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -866,6 +904,9 @@ static void dl_opts_put(struct nlmsghdr *nlh, struct dl *dl)
|
||||||
if (opts->present & DL_OPT_SB_TC)
|
if (opts->present & DL_OPT_SB_TC)
|
||||||
mnl_attr_put_u16(nlh, DEVLINK_ATTR_SB_TC_INDEX,
|
mnl_attr_put_u16(nlh, DEVLINK_ATTR_SB_TC_INDEX,
|
||||||
opts->sb_tc_index);
|
opts->sb_tc_index);
|
||||||
|
if (opts->present & DL_OPT_ESWITCH_MODE)
|
||||||
|
mnl_attr_put_u16(nlh, DEVLINK_ATTR_ESWITCH_MODE,
|
||||||
|
opts->eswitch_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int dl_argv_parse_put(struct nlmsghdr *nlh, struct dl *dl,
|
static int dl_argv_parse_put(struct nlmsghdr *nlh, struct dl *dl,
|
||||||
|
|
@ -1149,6 +1190,84 @@ static void pr_out_section_end(struct dl *dl)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *eswitch_mode_name(uint32_t mode)
|
||||||
|
{
|
||||||
|
switch (mode) {
|
||||||
|
case DEVLINK_ESWITCH_MODE_LEGACY: return ESWITCH_MODE_LEGACY;
|
||||||
|
case DEVLINK_ESWITCH_MODE_SWITCHDEV: return ESWITCH_MODE_SWITCHDEV;
|
||||||
|
default: return "<unknown mode>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void pr_out_eswitch(struct dl *dl, struct nlattr **tb)
|
||||||
|
{
|
||||||
|
__pr_out_handle_start(dl, tb, true, false);
|
||||||
|
|
||||||
|
if (tb[DEVLINK_ATTR_ESWITCH_MODE])
|
||||||
|
pr_out_str(dl, "mode",
|
||||||
|
eswitch_mode_name(mnl_attr_get_u16(tb[DEVLINK_ATTR_ESWITCH_MODE])));
|
||||||
|
pr_out_handle_end(dl);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cmd_dev_eswitch_show_cb(const struct nlmsghdr *nlh, void *data)
|
||||||
|
{
|
||||||
|
struct dl *dl = data;
|
||||||
|
struct nlattr *tb[DEVLINK_ATTR_MAX + 1] = {};
|
||||||
|
struct genlmsghdr *genl = mnl_nlmsg_get_payload(nlh);
|
||||||
|
|
||||||
|
mnl_attr_parse(nlh, sizeof(*genl), attr_cb, tb);
|
||||||
|
if (!tb[DEVLINK_ATTR_BUS_NAME] || !tb[DEVLINK_ATTR_DEV_NAME])
|
||||||
|
return MNL_CB_ERROR;
|
||||||
|
pr_out_eswitch(dl, tb);
|
||||||
|
return MNL_CB_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cmd_dev_eswitch_show(struct dl *dl)
|
||||||
|
{
|
||||||
|
struct nlmsghdr *nlh;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_ESWITCH_MODE_GET,
|
||||||
|
NLM_F_REQUEST | NLM_F_ACK);
|
||||||
|
|
||||||
|
err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE, 0);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
pr_out_section_start(dl, "dev");
|
||||||
|
err = _mnlg_socket_sndrcv(dl->nlg, nlh, cmd_dev_eswitch_show_cb, dl);
|
||||||
|
pr_out_section_end(dl);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cmd_dev_eswitch_set(struct dl *dl)
|
||||||
|
{
|
||||||
|
struct nlmsghdr *nlh;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_ESWITCH_MODE_SET,
|
||||||
|
NLM_F_REQUEST | NLM_F_ACK);
|
||||||
|
|
||||||
|
err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE | DL_OPT_ESWITCH_MODE, 0);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
return _mnlg_socket_sndrcv(dl->nlg, nlh, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cmd_dev_eswitch(struct dl *dl)
|
||||||
|
{
|
||||||
|
if (dl_argv_match(dl, "set")) {
|
||||||
|
dl_arg_inc(dl);
|
||||||
|
return cmd_dev_eswitch_set(dl);
|
||||||
|
} else if (dl_argv_match(dl, "show")) {
|
||||||
|
dl_arg_inc(dl);
|
||||||
|
return cmd_dev_eswitch_show(dl);
|
||||||
|
}
|
||||||
|
pr_err("Command \"%s\" not found\n", dl_argv(dl));
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
static int cmd_dev_show_cb(const struct nlmsghdr *nlh, void *data)
|
static int cmd_dev_show_cb(const struct nlmsghdr *nlh, void *data)
|
||||||
{
|
{
|
||||||
struct dl *dl = data;
|
struct dl *dl = data;
|
||||||
|
|
@ -1194,6 +1313,9 @@ static int cmd_dev(struct dl *dl)
|
||||||
dl_argv_match(dl, "list") || dl_no_arg(dl)) {
|
dl_argv_match(dl, "list") || dl_no_arg(dl)) {
|
||||||
dl_arg_inc(dl);
|
dl_arg_inc(dl);
|
||||||
return cmd_dev_show(dl);
|
return cmd_dev_show(dl);
|
||||||
|
} else if (dl_argv_match(dl, "eswitch")) {
|
||||||
|
dl_arg_inc(dl);
|
||||||
|
return cmd_dev_eswitch(dl);
|
||||||
}
|
}
|
||||||
pr_err("Command \"%s\" not found\n", dl_argv(dl));
|
pr_err("Command \"%s\" not found\n", dl_argv(dl));
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,17 @@ devlink-dev \- devlink device configuration
|
||||||
.ti -8
|
.ti -8
|
||||||
.B devlink dev help
|
.B devlink dev help
|
||||||
|
|
||||||
|
.ti -8
|
||||||
|
.BR "devlink dev eswitch set"
|
||||||
|
.IR DEV
|
||||||
|
.RI "[ "
|
||||||
|
.BR mode " { " legacy " | " switchdev " } "
|
||||||
|
.RI "]"
|
||||||
|
|
||||||
|
.ti -8
|
||||||
|
.BR "devlink dev eswitch show"
|
||||||
|
.IR DEV
|
||||||
|
|
||||||
.SH "DESCRIPTION"
|
.SH "DESCRIPTION"
|
||||||
.SS devlink dev show - display devlink device attributes
|
.SS devlink dev show - display devlink device attributes
|
||||||
|
|
||||||
|
|
@ -38,6 +49,19 @@ Format is:
|
||||||
.in +2
|
.in +2
|
||||||
BUS_NAME/BUS_ADDRESS
|
BUS_NAME/BUS_ADDRESS
|
||||||
|
|
||||||
|
.SS devlink dev eswitch show - display devlink device eswitch attributes
|
||||||
|
.SS devlink dev eswitch set - sets devlink device eswitch attributes
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.BR mode " { " legacy " | " switchdev " } "
|
||||||
|
set eswitch mode
|
||||||
|
|
||||||
|
.I legacy
|
||||||
|
- Legacy SRIOV
|
||||||
|
|
||||||
|
.I switchdev
|
||||||
|
- SRIOV switchdev offloads
|
||||||
|
|
||||||
.SH "EXAMPLES"
|
.SH "EXAMPLES"
|
||||||
.PP
|
.PP
|
||||||
devlink dev show
|
devlink dev show
|
||||||
|
|
@ -48,6 +72,16 @@ Shows the state of all devlink devices on the system.
|
||||||
devlink dev show pci/0000:01:00.0
|
devlink dev show pci/0000:01:00.0
|
||||||
.RS 4
|
.RS 4
|
||||||
Shows the state of specified devlink device.
|
Shows the state of specified devlink device.
|
||||||
|
.RE
|
||||||
|
.PP
|
||||||
|
devlink dev eswitch show pci/0000:01:00.0
|
||||||
|
.RS 4
|
||||||
|
Shows the eswitch mode of specified devlink device.
|
||||||
|
.RE
|
||||||
|
.PP
|
||||||
|
devlink dev eswitch set pci/0000:01:00.0 mode switchdev
|
||||||
|
.RS 4
|
||||||
|
Sets the eswitch mode of specified devlink device to switchdev.
|
||||||
|
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
.BR devlink (8),
|
.BR devlink (8),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue