* [patch iproute2/net-next RFC] devlink: add support for linecard show and provision [not found] <20210113121222.733517-1-jiri@resnulli.u> @ 2021-01-13 12:15 ` Jiri Pirko 2021-01-13 13:40 ` Jiri Pirko 0 siblings, 1 reply; 3+ messages in thread From: Jiri Pirko @ 2021-01-13 12:15 UTC (permalink / raw) To: netdev; +Cc: davem, kuba, jacob.e.keller, roopa, mlxsw From: Jiri Pirko <jiri@nvidia.com> Signed-off-by: Jiri Pirko <jiri@nvidia.com> --- devlink/devlink.c | 218 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 214 insertions(+), 4 deletions(-) diff --git a/devlink/devlink.c b/devlink/devlink.c index a2e066441e8a..960f1078591e 100644 --- a/devlink/devlink.c +++ b/devlink/devlink.c @@ -306,6 +306,8 @@ 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_LINECARD BIT(42) +#define DL_OPT_LINECARD_TYPE BIT(43) struct dl_opts { uint64_t present; /* flags of present items */ @@ -356,6 +358,8 @@ struct dl_opts { uint32_t overwrite_mask; enum devlink_reload_action reload_action; enum devlink_reload_limit reload_limit; + uint32_t linecard_index; + const char *linecard_type; }; struct dl { @@ -1414,6 +1418,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_LINECARD, "Linecard index expected."}, + {DL_OPT_LINECARD_TYPE, "Linecard type expected."}, }; static int dl_args_finding_required_validate(uint64_t o_required, @@ -1832,7 +1838,20 @@ 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, "lc") && + (o_all & DL_OPT_LINECARD)) { + dl_arg_inc(dl); + err = dl_argv_uint32_t(dl, &opts->linecard_index); + if (err) + return err; + o_found |= DL_OPT_LINECARD; + } else if (dl_argv_match(dl, "type") && + (o_all & DL_OPT_LINECARD_TYPE)) { + dl_arg_inc(dl); + err = dl_argv_str(dl, &opts->linecard_type); + if (err) + return err; + o_found |= DL_OPT_LINECARD_TYPE; } else { pr_err("Unknown option \"%s\"\n", dl_argv(dl)); return -EINVAL; @@ -2015,6 +2034,12 @@ static void dl_opts_put(struct nlmsghdr *nlh, struct dl *dl) opts->trap_policer_burst); if (opts->present & DL_OPT_PORT_FUNCTION_HW_ADDR) dl_function_attr_put(nlh, opts); + if (opts->present & DL_OPT_LINECARD) + mnl_attr_put_u32(nlh, DEVLINK_ATTR_LINECARD_INDEX, + opts->linecard_index); + if (opts->present & DL_OPT_LINECARD_TYPE) + mnl_attr_put_strz(nlh, DEVLINK_ATTR_LINECARD_TYPE, + opts->linecard_type); } static int dl_argv_parse_put(struct nlmsghdr *nlh, struct dl *dl, @@ -2036,6 +2061,7 @@ static bool dl_dump_filter(struct dl *dl, struct nlattr **tb) struct nlattr *attr_dev_name = tb[DEVLINK_ATTR_DEV_NAME]; struct nlattr *attr_port_index = tb[DEVLINK_ATTR_PORT_INDEX]; struct nlattr *attr_sb_index = tb[DEVLINK_ATTR_SB_INDEX]; + struct nlattr *attr_linecard_index = tb[DEVLINK_ATTR_LINECARD_INDEX]; if (opts->present & DL_OPT_HANDLE && attr_bus_name && attr_dev_name) { @@ -2063,6 +2089,12 @@ static bool dl_dump_filter(struct dl *dl, struct nlattr **tb) if (sb_index != opts->sb_index) return false; } + if (opts->present & DL_OPT_LINECARD && attr_linecard_index) { + uint32_t linecard_index = mnl_attr_get_u32(attr_linecard_index); + + if (linecard_index != opts->linecard_index) + return false; + } return true; } @@ -3833,6 +3865,9 @@ static void pr_out_port(struct dl *dl, struct nlattr **tb) break; } } + if (tb[DEVLINK_ATTR_LINECARD_INDEX]) + print_uint(PRINT_ANY, "lc", " lc %u", + mnl_attr_get_u32(tb[DEVLINK_ATTR_LINECARD_INDEX])); if (tb[DEVLINK_ATTR_PORT_NUMBER]) { uint32_t port_number; @@ -4005,6 +4040,156 @@ static int cmd_port(struct dl *dl) return -ENOENT; } +static void cmd_linecard_help(void) +{ + pr_err("Usage: devlink lc show [ DEV [ lc LC_INDEX ] ]\n"); + pr_err(" devlink lc provision DEV lc LC_INDEX type LC_TYPE\n"); + pr_err(" devlink lc unprovision DEV lc LC_INDEX\n"); +} + +static const char *linecard_state_name(uint16_t flavour) +{ + switch (flavour) { + case DEVLINK_LINECARD_STATE_UNPROVISIONED: + return "unprovisioned"; + case DEVLINK_LINECARD_STATE_UNPROVISIONING: + return "unprovisioning"; + case DEVLINK_LINECARD_STATE_PROVISIONING: + return "provisioning"; + case DEVLINK_LINECARD_STATE_PROVISIONED: + return "provisioned"; + case DEVLINK_LINECARD_STATE_ACTIVE: + return "active"; + default: + return "<unknown state>"; + } +} + +static void pr_out_linecard_supported_types(struct dl *dl, struct nlattr **tb) +{ + struct nlattr *nla_types = tb[DEVLINK_ATTR_LINECARD_SUPPORTED_TYPES]; + struct nlattr *nla_type; + + if (!nla_types) + return; + + pr_out_array_start(dl, "supported_types"); + check_indent_newline(dl); + mnl_attr_for_each_nested(nla_type, nla_types) { + print_string(PRINT_ANY, NULL, " %s", + mnl_attr_get_str(nla_type)); + } + pr_out_array_end(dl); +} + +static void pr_out_linecard(struct dl *dl, struct nlattr **tb) +{ + uint8_t state; + + pr_out_handle_start_arr(dl, tb); + check_indent_newline(dl); + print_uint(PRINT_ANY, "lc", "lc %u", + mnl_attr_get_u32(tb[DEVLINK_ATTR_LINECARD_INDEX])); + state = mnl_attr_get_u8(tb[DEVLINK_ATTR_LINECARD_STATE]); + print_string(PRINT_ANY, "state", " state %s", + linecard_state_name(state)); + if (tb[DEVLINK_ATTR_LINECARD_TYPE]) + print_string(PRINT_ANY, "type", " type %s", + mnl_attr_get_str(tb[DEVLINK_ATTR_LINECARD_TYPE])); + pr_out_linecard_supported_types(dl, tb); + pr_out_handle_end(dl); +} + +static int cmd_linecard_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] || + !tb[DEVLINK_ATTR_LINECARD_INDEX] || + !tb[DEVLINK_ATTR_LINECARD_STATE]) + return MNL_CB_ERROR; + pr_out_linecard(dl, tb); + return MNL_CB_OK; +} + +static int cmd_linecard_show(struct dl *dl) +{ + struct nlmsghdr *nlh; + uint16_t flags = NLM_F_REQUEST | NLM_F_ACK; + int err; + + if (dl_argc(dl) == 0) + flags |= NLM_F_DUMP; + + nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_LINECARD_GET, flags); + + if (dl_argc(dl) > 0) { + err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE, + DL_OPT_LINECARD); + if (err) + return err; + } + + pr_out_section_start(dl, "lc"); + err = _mnlg_socket_sndrcv(dl->nlg, nlh, cmd_linecard_show_cb, dl); + pr_out_section_end(dl); + return err; +} + +static int cmd_linecard_provision(struct dl *dl) +{ + struct nlmsghdr *nlh; + int err; + + nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_LINECARD_PROVISION, + NLM_F_REQUEST | NLM_F_ACK); + + err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE | DL_OPT_LINECARD | + DL_OPT_LINECARD_TYPE, 0); + if (err) + return err; + + return _mnlg_socket_sndrcv(dl->nlg, nlh, NULL, NULL); +} + +static int cmd_linecard_unprovision(struct dl *dl) +{ + struct nlmsghdr *nlh; + int err; + + nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_LINECARD_UNPROVISION, + NLM_F_REQUEST | NLM_F_ACK); + + err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE | DL_OPT_LINECARD, 0); + if (err) + return err; + + return _mnlg_socket_sndrcv(dl->nlg, nlh, NULL, NULL); +} + +static int cmd_linecard(struct dl *dl) +{ + if (dl_argv_match(dl, "help")) { + cmd_linecard_help(); + return 0; + } else if (dl_argv_match(dl, "show") || + dl_argv_match(dl, "list") || dl_no_arg(dl)) { + dl_arg_inc(dl); + return cmd_linecard_show(dl); + } else if (dl_argv_match(dl, "provision")) { + dl_arg_inc(dl); + return cmd_linecard_provision(dl); + } else if (dl_argv_match(dl, "unprovision")) { + dl_arg_inc(dl); + return cmd_linecard_unprovision(dl); + } + pr_err("Command \"%s\" not found\n", dl_argv(dl)); + return -ENOENT; +} + static void cmd_sb_help(void) { pr_err("Usage: devlink sb show [ DEV [ sb SB_INDEX ] ]\n"); @@ -4818,6 +5003,10 @@ static const char *cmd_name(uint8_t cmd) case DEVLINK_CMD_TRAP_POLICER_SET: return "set"; case DEVLINK_CMD_TRAP_POLICER_NEW: return "new"; case DEVLINK_CMD_TRAP_POLICER_DEL: return "del"; + case DEVLINK_CMD_LINECARD_GET: return "get"; + case DEVLINK_CMD_LINECARD_SET: return "set"; + case DEVLINK_CMD_LINECARD_NEW: return "new"; + case DEVLINK_CMD_LINECARD_DEL: return "del"; default: return "<unknown cmd>"; } } @@ -4867,6 +5056,11 @@ static const char *cmd_obj(uint8_t cmd) case DEVLINK_CMD_TRAP_POLICER_NEW: case DEVLINK_CMD_TRAP_POLICER_DEL: return "trap-policer"; + case DEVLINK_CMD_LINECARD_GET: + case DEVLINK_CMD_LINECARD_SET: + case DEVLINK_CMD_LINECARD_NEW: + case DEVLINK_CMD_LINECARD_DEL: + return "lc"; default: return "<unknown obj>"; } } @@ -5059,6 +5253,18 @@ static int cmd_mon_show_cb(const struct nlmsghdr *nlh, void *data) pr_out_mon_header(genl->cmd); pr_out_trap_policer(dl, tb, false); break; + case DEVLINK_CMD_LINECARD_GET: /* fall through */ + case DEVLINK_CMD_LINECARD_SET: /* fall through */ + case DEVLINK_CMD_LINECARD_NEW: /* fall through */ + case DEVLINK_CMD_LINECARD_DEL: + mnl_attr_parse(nlh, sizeof(*genl), attr_cb, tb); + if (!tb[DEVLINK_ATTR_BUS_NAME] || !tb[DEVLINK_ATTR_DEV_NAME] || + !tb[DEVLINK_ATTR_LINECARD_INDEX]) + return MNL_CB_ERROR; + pr_out_mon_header(genl->cmd); + pr_out_linecard(dl, tb); + pr_out_mon_footer(); + break; } fflush(stdout); return MNL_CB_OK; @@ -5077,7 +5283,8 @@ static int cmd_mon_show(struct dl *dl) strcmp(cur_obj, "health") != 0 && strcmp(cur_obj, "trap") != 0 && strcmp(cur_obj, "trap-group") != 0 && - strcmp(cur_obj, "trap-policer") != 0) { + strcmp(cur_obj, "trap-policer") != 0 && + strcmp(cur_obj, "lc") != 0) { pr_err("Unknown object \"%s\"\n", cur_obj); return -EINVAL; } @@ -5098,7 +5305,7 @@ static int cmd_mon_show(struct dl *dl) static void cmd_mon_help(void) { pr_err("Usage: devlink monitor [ all | OBJECT-LIST ]\n" - "where OBJECT-LIST := { dev | port | health | trap | trap-group | trap-policer }\n"); + "where OBJECT-LIST := { dev | port | lc | health | trap | trap-group | trap-policer }\n"); } static int cmd_mon(struct dl *dl) @@ -8073,7 +8280,7 @@ static void help(void) { pr_err("Usage: devlink [ OPTIONS ] OBJECT { COMMAND | help }\n" " devlink [ -f[orce] ] -b[atch] filename -N[etns] netnsname\n" - "where OBJECT := { dev | port | sb | monitor | dpipe | resource | region | health | trap }\n" + "where OBJECT := { dev | port | lc | sb | monitor | dpipe | resource | region | health | trap }\n" " OPTIONS := { -V[ersion] | -n[o-nice-names] | -j[son] | -p[retty] | -v[erbose] -s[tatistics] }\n"); } @@ -8112,6 +8319,9 @@ static int dl_cmd(struct dl *dl, int argc, char **argv) } else if (dl_argv_match(dl, "trap")) { dl_arg_inc(dl); return cmd_trap(dl); + } else if (dl_argv_match(dl, "lc")) { + dl_arg_inc(dl); + return cmd_linecard(dl); } pr_err("Object \"%s\" not found\n", dl_argv(dl)); return -ENOENT; -- 2.26.2 ^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [patch iproute2/net-next RFC] devlink: add support for linecard show and provision 2021-01-13 12:15 ` [patch iproute2/net-next RFC] devlink: add support for linecard show and provision Jiri Pirko @ 2021-01-13 13:40 ` Jiri Pirko 0 siblings, 0 replies; 3+ messages in thread From: Jiri Pirko @ 2021-01-13 13:40 UTC (permalink / raw) To: netdev; +Cc: davem, kuba, jacob.e.keller, roopa, mlxsw Please ignore this, I messed up the threading. Reposted. ^ permalink raw reply [flat|nested] 3+ messages in thread
* [patch net-next RFC 00/10] introduce line card support for modular switch
@ 2021-01-13 12:12 Jiri Pirko
2021-01-13 13:39 ` [patch iproute2/net-next RFC] devlink: add support for linecard show and provision Jiri Pirko
0 siblings, 1 reply; 3+ messages in thread
From: Jiri Pirko @ 2021-01-13 12:12 UTC (permalink / raw)
To: netdev; +Cc: davem, kuba, jacob.e.keller, roopa, mlxsw
From: Jiri Pirko <jiri@nvidia.com>
This patchset introduces support for modular switch systems.
NVIDIA Mellanox SN4800 is an example of such. It contains 8 slots
to accomodate line cards. Available line cards include:
16X 100GbE (QSFP28)
8X 200GbE (QSFP56)
4X 400GbE (QSFP-DD)
Similar to split cabels, it is essencial for the correctness of
configuration and funcionality to treat the line card entities
in the same way, no matter the line card is inserted or not.
Meaning, the netdevice of a line card port cannot just disappear
when line card is removed. Also, system admin needs to be able
to apply configuration on netdevices belonging to line card port
even before the linecard gets inserted.
To resolve this, a concept of "provisioning" is introduced.
The user may "provision" certain slot with a line card type.
Driver then creates all instances (devlink ports, netdevices, etc)
related to this line card type. The carrier of netdevices stays down.
Once the line card is inserted and activated, the carrier of the
related netdevices goes up.
Once user does not want to use the line card related instances
anymore, he can "unprovision" the slot. Driver then removes the
instances.
Patches 1-5 are extending devlink driver API and UAPI in order to
register, show, dump, provision and activate the line card.
Patches 6-9 are implementing the introduced API in netdevsim
Example:
# Create a new netdevsim device, with no ports and 2 line cards:
$ echo "10 0 2" >/sys/bus/netdevsim/new_device
$ devlink port # No ports are listed
$ devlink lc
netdevsim/netdevsim10:
lc 0 state unprovisioned
supported_types:
card1port card2ports card4ports
lc 1 state unprovisioned
supported_types:
card1port card2ports card4ports
# Note that driver advertizes supported line card types. In case of
# netdevsim, these are 3.
$ devlink lc provision netdevsim/netdevsim10 lc 0 type card4ports
$ devlink lc
netdevsim/netdevsim10:
lc 0 state provisioned type card4ports
supported_types:
card1port card2ports card4ports
lc 1 state unprovisioned
supported_types:
card1port card2ports card4ports
$ devlink port
netdevsim/netdevsim10/1000: type eth netdev eni10nl0p1 flavour physical lc 0 port 1 splittable false
netdevsim/netdevsim10/1001: type eth netdev eni10nl0p2 flavour physical lc 0 port 2 splittable false
netdevsim/netdevsim10/1002: type eth netdev eni10nl0p3 flavour physical lc 0 port 3 splittable false
netdevsim/netdevsim10/1003: type eth netdev eni10nl0p4 flavour physical lc 0 port 4 splittable false
# ^^ ^^^^
# netdev name adjusted index of a line card this port belongs to
$ ip link set eni10nl0p1 up
$ ip link show eni10nl0p1
165: eni10nl0p1: <NO-CARRIER,BROADCAST,NOARP,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default qlen 1000
link/ether 7e:2d:05:93:d3:d1 brd ff:ff:ff:ff:ff:ff
# Now activate the line card using debugfs. That emulates plug-in event
# on real hardware:
$ echo "Y"> /sys/kernel/debug/netdevsim/netdevsim10/linecards/0/active
$ ip link show eni10nl0p1
165: eni10nl0p1: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
link/ether 7e:2d:05:93:d3:d1 brd ff:ff:ff:ff:ff:ff
# The carrier is UP now.
Jiri Pirko (10):
devlink: add support to create line card and expose to user
devlink: implement line card provisioning
devlink: implement line card active state
devlink: append split port number to the port name
devlink: add port to line card relationship set
netdevsim: introduce line card support
netdevsim: allow port objects to be linked with line cards
netdevsim: create devlink line card object and implement provisioning
netdevsim: implement line card activation
selftests: add netdevsim devlink lc test
drivers/net/netdevsim/bus.c | 21 +-
drivers/net/netdevsim/dev.c | 370 ++++++++++++++-
drivers/net/netdevsim/netdev.c | 2 +
drivers/net/netdevsim/netdevsim.h | 23 +
include/net/devlink.h | 44 ++
include/uapi/linux/devlink.h | 25 +
net/core/devlink.c | 443 +++++++++++++++++-
.../drivers/net/netdevsim/devlink.sh | 62 ++-
8 files changed, 964 insertions(+), 26 deletions(-)
--
2.26.2
^ permalink raw reply [flat|nested] 3+ messages in thread* [patch iproute2/net-next RFC] devlink: add support for linecard show and provision 2021-01-13 12:12 [patch net-next RFC 00/10] introduce line card support for modular switch Jiri Pirko @ 2021-01-13 13:39 ` Jiri Pirko 0 siblings, 0 replies; 3+ messages in thread From: Jiri Pirko @ 2021-01-13 13:39 UTC (permalink / raw) To: netdev; +Cc: davem, kuba, jacob.e.keller, roopa, mlxsw From: Jiri Pirko <jiri@nvidia.com> Signed-off-by: Jiri Pirko <jiri@nvidia.com> --- devlink/devlink.c | 218 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 214 insertions(+), 4 deletions(-) diff --git a/devlink/devlink.c b/devlink/devlink.c index a2e066441e8a..960f1078591e 100644 --- a/devlink/devlink.c +++ b/devlink/devlink.c @@ -306,6 +306,8 @@ 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_LINECARD BIT(42) +#define DL_OPT_LINECARD_TYPE BIT(43) struct dl_opts { uint64_t present; /* flags of present items */ @@ -356,6 +358,8 @@ struct dl_opts { uint32_t overwrite_mask; enum devlink_reload_action reload_action; enum devlink_reload_limit reload_limit; + uint32_t linecard_index; + const char *linecard_type; }; struct dl { @@ -1414,6 +1418,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_LINECARD, "Linecard index expected."}, + {DL_OPT_LINECARD_TYPE, "Linecard type expected."}, }; static int dl_args_finding_required_validate(uint64_t o_required, @@ -1832,7 +1838,20 @@ 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, "lc") && + (o_all & DL_OPT_LINECARD)) { + dl_arg_inc(dl); + err = dl_argv_uint32_t(dl, &opts->linecard_index); + if (err) + return err; + o_found |= DL_OPT_LINECARD; + } else if (dl_argv_match(dl, "type") && + (o_all & DL_OPT_LINECARD_TYPE)) { + dl_arg_inc(dl); + err = dl_argv_str(dl, &opts->linecard_type); + if (err) + return err; + o_found |= DL_OPT_LINECARD_TYPE; } else { pr_err("Unknown option \"%s\"\n", dl_argv(dl)); return -EINVAL; @@ -2015,6 +2034,12 @@ static void dl_opts_put(struct nlmsghdr *nlh, struct dl *dl) opts->trap_policer_burst); if (opts->present & DL_OPT_PORT_FUNCTION_HW_ADDR) dl_function_attr_put(nlh, opts); + if (opts->present & DL_OPT_LINECARD) + mnl_attr_put_u32(nlh, DEVLINK_ATTR_LINECARD_INDEX, + opts->linecard_index); + if (opts->present & DL_OPT_LINECARD_TYPE) + mnl_attr_put_strz(nlh, DEVLINK_ATTR_LINECARD_TYPE, + opts->linecard_type); } static int dl_argv_parse_put(struct nlmsghdr *nlh, struct dl *dl, @@ -2036,6 +2061,7 @@ static bool dl_dump_filter(struct dl *dl, struct nlattr **tb) struct nlattr *attr_dev_name = tb[DEVLINK_ATTR_DEV_NAME]; struct nlattr *attr_port_index = tb[DEVLINK_ATTR_PORT_INDEX]; struct nlattr *attr_sb_index = tb[DEVLINK_ATTR_SB_INDEX]; + struct nlattr *attr_linecard_index = tb[DEVLINK_ATTR_LINECARD_INDEX]; if (opts->present & DL_OPT_HANDLE && attr_bus_name && attr_dev_name) { @@ -2063,6 +2089,12 @@ static bool dl_dump_filter(struct dl *dl, struct nlattr **tb) if (sb_index != opts->sb_index) return false; } + if (opts->present & DL_OPT_LINECARD && attr_linecard_index) { + uint32_t linecard_index = mnl_attr_get_u32(attr_linecard_index); + + if (linecard_index != opts->linecard_index) + return false; + } return true; } @@ -3833,6 +3865,9 @@ static void pr_out_port(struct dl *dl, struct nlattr **tb) break; } } + if (tb[DEVLINK_ATTR_LINECARD_INDEX]) + print_uint(PRINT_ANY, "lc", " lc %u", + mnl_attr_get_u32(tb[DEVLINK_ATTR_LINECARD_INDEX])); if (tb[DEVLINK_ATTR_PORT_NUMBER]) { uint32_t port_number; @@ -4005,6 +4040,156 @@ static int cmd_port(struct dl *dl) return -ENOENT; } +static void cmd_linecard_help(void) +{ + pr_err("Usage: devlink lc show [ DEV [ lc LC_INDEX ] ]\n"); + pr_err(" devlink lc provision DEV lc LC_INDEX type LC_TYPE\n"); + pr_err(" devlink lc unprovision DEV lc LC_INDEX\n"); +} + +static const char *linecard_state_name(uint16_t flavour) +{ + switch (flavour) { + case DEVLINK_LINECARD_STATE_UNPROVISIONED: + return "unprovisioned"; + case DEVLINK_LINECARD_STATE_UNPROVISIONING: + return "unprovisioning"; + case DEVLINK_LINECARD_STATE_PROVISIONING: + return "provisioning"; + case DEVLINK_LINECARD_STATE_PROVISIONED: + return "provisioned"; + case DEVLINK_LINECARD_STATE_ACTIVE: + return "active"; + default: + return "<unknown state>"; + } +} + +static void pr_out_linecard_supported_types(struct dl *dl, struct nlattr **tb) +{ + struct nlattr *nla_types = tb[DEVLINK_ATTR_LINECARD_SUPPORTED_TYPES]; + struct nlattr *nla_type; + + if (!nla_types) + return; + + pr_out_array_start(dl, "supported_types"); + check_indent_newline(dl); + mnl_attr_for_each_nested(nla_type, nla_types) { + print_string(PRINT_ANY, NULL, " %s", + mnl_attr_get_str(nla_type)); + } + pr_out_array_end(dl); +} + +static void pr_out_linecard(struct dl *dl, struct nlattr **tb) +{ + uint8_t state; + + pr_out_handle_start_arr(dl, tb); + check_indent_newline(dl); + print_uint(PRINT_ANY, "lc", "lc %u", + mnl_attr_get_u32(tb[DEVLINK_ATTR_LINECARD_INDEX])); + state = mnl_attr_get_u8(tb[DEVLINK_ATTR_LINECARD_STATE]); + print_string(PRINT_ANY, "state", " state %s", + linecard_state_name(state)); + if (tb[DEVLINK_ATTR_LINECARD_TYPE]) + print_string(PRINT_ANY, "type", " type %s", + mnl_attr_get_str(tb[DEVLINK_ATTR_LINECARD_TYPE])); + pr_out_linecard_supported_types(dl, tb); + pr_out_handle_end(dl); +} + +static int cmd_linecard_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] || + !tb[DEVLINK_ATTR_LINECARD_INDEX] || + !tb[DEVLINK_ATTR_LINECARD_STATE]) + return MNL_CB_ERROR; + pr_out_linecard(dl, tb); + return MNL_CB_OK; +} + +static int cmd_linecard_show(struct dl *dl) +{ + struct nlmsghdr *nlh; + uint16_t flags = NLM_F_REQUEST | NLM_F_ACK; + int err; + + if (dl_argc(dl) == 0) + flags |= NLM_F_DUMP; + + nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_LINECARD_GET, flags); + + if (dl_argc(dl) > 0) { + err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE, + DL_OPT_LINECARD); + if (err) + return err; + } + + pr_out_section_start(dl, "lc"); + err = _mnlg_socket_sndrcv(dl->nlg, nlh, cmd_linecard_show_cb, dl); + pr_out_section_end(dl); + return err; +} + +static int cmd_linecard_provision(struct dl *dl) +{ + struct nlmsghdr *nlh; + int err; + + nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_LINECARD_PROVISION, + NLM_F_REQUEST | NLM_F_ACK); + + err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE | DL_OPT_LINECARD | + DL_OPT_LINECARD_TYPE, 0); + if (err) + return err; + + return _mnlg_socket_sndrcv(dl->nlg, nlh, NULL, NULL); +} + +static int cmd_linecard_unprovision(struct dl *dl) +{ + struct nlmsghdr *nlh; + int err; + + nlh = mnlg_msg_prepare(dl->nlg, DEVLINK_CMD_LINECARD_UNPROVISION, + NLM_F_REQUEST | NLM_F_ACK); + + err = dl_argv_parse_put(nlh, dl, DL_OPT_HANDLE | DL_OPT_LINECARD, 0); + if (err) + return err; + + return _mnlg_socket_sndrcv(dl->nlg, nlh, NULL, NULL); +} + +static int cmd_linecard(struct dl *dl) +{ + if (dl_argv_match(dl, "help")) { + cmd_linecard_help(); + return 0; + } else if (dl_argv_match(dl, "show") || + dl_argv_match(dl, "list") || dl_no_arg(dl)) { + dl_arg_inc(dl); + return cmd_linecard_show(dl); + } else if (dl_argv_match(dl, "provision")) { + dl_arg_inc(dl); + return cmd_linecard_provision(dl); + } else if (dl_argv_match(dl, "unprovision")) { + dl_arg_inc(dl); + return cmd_linecard_unprovision(dl); + } + pr_err("Command \"%s\" not found\n", dl_argv(dl)); + return -ENOENT; +} + static void cmd_sb_help(void) { pr_err("Usage: devlink sb show [ DEV [ sb SB_INDEX ] ]\n"); @@ -4818,6 +5003,10 @@ static const char *cmd_name(uint8_t cmd) case DEVLINK_CMD_TRAP_POLICER_SET: return "set"; case DEVLINK_CMD_TRAP_POLICER_NEW: return "new"; case DEVLINK_CMD_TRAP_POLICER_DEL: return "del"; + case DEVLINK_CMD_LINECARD_GET: return "get"; + case DEVLINK_CMD_LINECARD_SET: return "set"; + case DEVLINK_CMD_LINECARD_NEW: return "new"; + case DEVLINK_CMD_LINECARD_DEL: return "del"; default: return "<unknown cmd>"; } } @@ -4867,6 +5056,11 @@ static const char *cmd_obj(uint8_t cmd) case DEVLINK_CMD_TRAP_POLICER_NEW: case DEVLINK_CMD_TRAP_POLICER_DEL: return "trap-policer"; + case DEVLINK_CMD_LINECARD_GET: + case DEVLINK_CMD_LINECARD_SET: + case DEVLINK_CMD_LINECARD_NEW: + case DEVLINK_CMD_LINECARD_DEL: + return "lc"; default: return "<unknown obj>"; } } @@ -5059,6 +5253,18 @@ static int cmd_mon_show_cb(const struct nlmsghdr *nlh, void *data) pr_out_mon_header(genl->cmd); pr_out_trap_policer(dl, tb, false); break; + case DEVLINK_CMD_LINECARD_GET: /* fall through */ + case DEVLINK_CMD_LINECARD_SET: /* fall through */ + case DEVLINK_CMD_LINECARD_NEW: /* fall through */ + case DEVLINK_CMD_LINECARD_DEL: + mnl_attr_parse(nlh, sizeof(*genl), attr_cb, tb); + if (!tb[DEVLINK_ATTR_BUS_NAME] || !tb[DEVLINK_ATTR_DEV_NAME] || + !tb[DEVLINK_ATTR_LINECARD_INDEX]) + return MNL_CB_ERROR; + pr_out_mon_header(genl->cmd); + pr_out_linecard(dl, tb); + pr_out_mon_footer(); + break; } fflush(stdout); return MNL_CB_OK; @@ -5077,7 +5283,8 @@ static int cmd_mon_show(struct dl *dl) strcmp(cur_obj, "health") != 0 && strcmp(cur_obj, "trap") != 0 && strcmp(cur_obj, "trap-group") != 0 && - strcmp(cur_obj, "trap-policer") != 0) { + strcmp(cur_obj, "trap-policer") != 0 && + strcmp(cur_obj, "lc") != 0) { pr_err("Unknown object \"%s\"\n", cur_obj); return -EINVAL; } @@ -5098,7 +5305,7 @@ static int cmd_mon_show(struct dl *dl) static void cmd_mon_help(void) { pr_err("Usage: devlink monitor [ all | OBJECT-LIST ]\n" - "where OBJECT-LIST := { dev | port | health | trap | trap-group | trap-policer }\n"); + "where OBJECT-LIST := { dev | port | lc | health | trap | trap-group | trap-policer }\n"); } static int cmd_mon(struct dl *dl) @@ -8073,7 +8280,7 @@ static void help(void) { pr_err("Usage: devlink [ OPTIONS ] OBJECT { COMMAND | help }\n" " devlink [ -f[orce] ] -b[atch] filename -N[etns] netnsname\n" - "where OBJECT := { dev | port | sb | monitor | dpipe | resource | region | health | trap }\n" + "where OBJECT := { dev | port | lc | sb | monitor | dpipe | resource | region | health | trap }\n" " OPTIONS := { -V[ersion] | -n[o-nice-names] | -j[son] | -p[retty] | -v[erbose] -s[tatistics] }\n"); } @@ -8112,6 +8319,9 @@ static int dl_cmd(struct dl *dl, int argc, char **argv) } else if (dl_argv_match(dl, "trap")) { dl_arg_inc(dl); return cmd_trap(dl); + } else if (dl_argv_match(dl, "lc")) { + dl_arg_inc(dl); + return cmd_linecard(dl); } pr_err("Object \"%s\" not found\n", dl_argv(dl)); return -ENOENT; -- 2.26.2 ^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2021-01-13 13:41 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20210113121222.733517-1-jiri@resnulli.u>
2021-01-13 12:15 ` [patch iproute2/net-next RFC] devlink: add support for linecard show and provision Jiri Pirko
2021-01-13 13:40 ` Jiri Pirko
2021-01-13 12:12 [patch net-next RFC 00/10] introduce line card support for modular switch Jiri Pirko
2021-01-13 13:39 ` [patch iproute2/net-next RFC] devlink: add support for linecard show and provision Jiri Pirko
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox