@@ -2302,6 +2302,88 @@ static int dl_argv_dry_parse(struct dl *dl, uint64_t o_required,
return err;
}
+/* List of extented handles with two slashes. */
+static const uint64_t dl_opt_extended_handle[] = {
+ DL_OPT_HANDLEP,
+ DL_OPT_HANDLE_REGION,
+ DL_OPT_PORT_FN_RATE_NODE_NAME,
+};
+
+static int dl_argv_parse_with_selector(struct dl *dl, uint16_t *flags,
+ uint8_t cmd,
+ uint64_t o_required,
+ uint64_t o_optional,
+ uint64_t o_dump_required,
+ uint64_t o_dump_optional)
+{
+ int err;
+ int i;
+
+ if (dl_no_arg(dl))
+ goto flag_set;
+
+ /* In case the handle suggests it, do dry parsing first
+ * to see if all required options are there. Proceed with
+ * dump selector in case there are missing options on the
+ * command line. That means user provided partial
+ * object identification.
+ */
+
+ if ((o_required & (DL_OPT_HANDLE | DL_OPT_HANDLEP)) ==
+ (DL_OPT_HANDLE | DL_OPT_HANDLEP)) {
+ /* Handle case when both devlink handle and port handle
+ * are allowed. Try both alone, if parsing of either
+ * is successful, we have a do parse case.
+ */
+ err = dl_argv_dry_parse(dl, o_required & ~DL_OPT_HANDLEP,
+ o_optional);
+ if (err == -ENOENT)
+ goto dump_parse;
+ else if (!err)
+ goto do_parse;
+ err = dl_argv_dry_parse(dl, o_required & ~DL_OPT_HANDLE,
+ o_optional);
+ if (err == -ENOENT)
+ goto dump_parse;
+ goto do_parse;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(dl_opt_extended_handle); i++) {
+ uint64_t handle = dl_opt_extended_handle[i];
+
+ if ((o_required & handle) == handle) {
+ err = dl_argv_dry_parse(dl, (o_required & ~handle) |
+ DL_OPT_HANDLE,
+ o_optional);
+ if (err == -ENOENT || !err)
+ goto dump_parse;
+ goto do_parse;
+ }
+ }
+
+ err = dl_argv_dry_parse(dl, o_required, o_optional);
+ if (err == -ENOENT)
+ goto dump_parse;
+
+do_parse:
+ return dl_argv_parse(dl, o_required, o_optional);
+
+dump_parse:
+ err = mnlu_gen_cmd_dump_policy(&dl->nlg, cmd);
+ if (err) {
+ pr_err("Dump selectors are not supported by kernel for this command\n");
+ return -ENOTSUP;
+ }
+
+ err = dl_argv_parse(dl, o_dump_required, o_dump_optional);
+ if (err)
+ return err;
+
+flag_set:
+ *flags |= NLM_F_DUMP;
+ return 0;
+}
+
static void
dl_function_attr_put(struct nlmsghdr *nlh, const struct dl_opts *opts)
{
@@ -3580,13 +3662,11 @@ static int cmd_dev_param_show(struct dl *dl)
struct nlmsghdr *nlh;
int err;
- if (dl_no_arg(dl)) {
- flags |= NLM_F_DUMP;
- } else {
- err = dl_argv_parse(dl, DL_OPT_HANDLE | DL_OPT_PARAM_NAME, 0);
- if (err)
- return err;
- }
+ err = dl_argv_parse_with_selector(dl, &flags, DEVLINK_CMD_PARAM_GET,
+ DL_OPT_HANDLE | DL_OPT_PARAM_NAME, 0,
+ DL_OPT_HANDLE, 0);
+ if (err)
+ return err;
nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_PARAM_GET, flags);
@@ -4784,14 +4864,11 @@ static int cmd_port_show(struct dl *dl)
uint16_t flags = NLM_F_REQUEST | NLM_F_ACK;
int err;
- if (dl_no_arg(dl)) {
- flags |= NLM_F_DUMP;
- }
- else {
- err = dl_argv_parse(dl, DL_OPT_HANDLEP, 0);
- if (err)
- return err;
- }
+ err = dl_argv_parse_with_selector(dl, &flags, DEVLINK_CMD_PORT_GET,
+ DL_OPT_HANDLEP, 0,
+ DL_OPT_HANDLE, 0);
+ if (err)
+ return err;
nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_PORT_GET, flags);
@@ -4860,14 +4937,12 @@ static int cmd_port_param_show(struct dl *dl)
struct nlmsghdr *nlh;
int err;
- if (dl_no_arg(dl)) {
- flags |= NLM_F_DUMP;
- }
- else {
- err = dl_argv_parse(dl, DL_OPT_HANDLEP | DL_OPT_PARAM_NAME, 0);
- if (err)
- return err;
- }
+ err = dl_argv_parse_with_selector(dl, &flags,
+ DEVLINK_CMD_PORT_PARAM_GET,
+ DL_OPT_HANDLE | DL_OPT_PARAM_NAME, 0,
+ DL_OPT_HANDLE | DL_OPT_HANDLEP, 0);
+ if (err)
+ return err;
nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_PORT_PARAM_GET,
flags);
@@ -5234,16 +5309,9 @@ static int cmd_port_fn_rate_show(struct dl *dl)
uint16_t flags = NLM_F_REQUEST | NLM_F_ACK;
int err;
- if (dl_no_arg(dl)) {
- flags |= NLM_F_DUMP;
- }
- else {
- err = dl_argv_parse(dl,
- DL_OPT_HANDLEP | DL_OPT_PORT_FN_RATE_NODE_NAME,
- 0);
- if (err)
- return err;
- }
+ err = dl_argv_parse_with_selector(dl, &flags, DEVLINK_CMD_RATE_GET,
+ DL_OPT_HANDLEP | DL_OPT_PORT_FN_RATE_NODE_NAME,
+ 0, DL_OPT_HANDLE, 0);
nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_RATE_GET, flags);
@@ -5622,14 +5690,11 @@ static int cmd_linecard_show(struct dl *dl)
uint16_t flags = NLM_F_REQUEST | NLM_F_ACK;
int err;
- if (dl_no_arg(dl)) {
- flags |= NLM_F_DUMP;
- }
- else {
- err = dl_argv_parse(dl, DL_OPT_HANDLE, DL_OPT_LINECARD);
- if (err)
- return err;
- }
+ err = dl_argv_parse_with_selector(dl, &flags, DEVLINK_CMD_LINECARD_GET,
+ DL_OPT_HANDLE | DL_OPT_LINECARD, 0,
+ DL_OPT_HANDLE, 0);
+ if (err)
+ return err;
nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_LINECARD_GET,
flags);
@@ -5740,14 +5805,11 @@ static int cmd_sb_show(struct dl *dl)
uint16_t flags = NLM_F_REQUEST | NLM_F_ACK;
int err;
- if (dl_no_arg(dl)) {
- flags |= NLM_F_DUMP;
- }
- else {
- err = dl_argv_parse(dl, DL_OPT_HANDLE | DL_OPT_SB, 0);
- if (err)
- return err;
- }
+ err = dl_argv_parse_with_selector(dl, &flags, DEVLINK_CMD_SB_GET,
+ DL_OPT_HANDLE | DL_OPT_SB, 0,
+ DL_OPT_HANDLE, DL_OPT_SB);
+ if (err)
+ return err;
nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_SB_GET, flags);
@@ -5819,15 +5881,12 @@ static int cmd_sb_pool_show(struct dl *dl)
uint16_t flags = NLM_F_REQUEST | NLM_F_ACK;
int err;
- if (dl_no_arg(dl)) {
- flags |= NLM_F_DUMP;
- }
- else {
- err = dl_argv_parse(dl, DL_OPT_HANDLE | DL_OPT_SB |
- DL_OPT_SB_POOL, 0);
- if (err)
- return err;
- }
+ err = dl_argv_parse_with_selector(dl, &flags, DEVLINK_CMD_SB_POOL_GET,
+ DL_OPT_HANDLE | DL_OPT_SB |
+ DL_OPT_SB_POOL, 0,
+ DL_OPT_HANDLE, DL_OPT_SB);
+ if (err)
+ return err;
nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_SB_POOL_GET, flags);
@@ -5908,15 +5967,13 @@ static int cmd_sb_port_pool_show(struct dl *dl)
uint16_t flags = NLM_F_REQUEST | NLM_F_ACK;
int err;
- if (dl_no_arg(dl)) {
- flags |= NLM_F_DUMP;
- }
- else {
- err = dl_argv_parse(dl, DL_OPT_HANDLEP | DL_OPT_SB |
- DL_OPT_SB_POOL, 0);
- if (err)
- return err;
- }
+ err = dl_argv_parse_with_selector(dl, &flags,
+ DEVLINK_CMD_SB_PORT_POOL_GET,
+ DL_OPT_HANDLEP | DL_OPT_SB |
+ DL_OPT_SB_POOL, 0,
+ DL_OPT_HANDLE | DL_OPT_HANDLEP, DL_OPT_SB);
+ if (err)
+ return err;
nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_SB_PORT_POOL_GET, flags);
@@ -6015,15 +6072,14 @@ static int cmd_sb_tc_bind_show(struct dl *dl)
uint16_t flags = NLM_F_REQUEST | NLM_F_ACK;
int err;
- if (dl_no_arg(dl)) {
- flags |= NLM_F_DUMP;
- }
- else {
- err = dl_argv_parse(dl, DL_OPT_HANDLEP | DL_OPT_SB | DL_OPT_SB_TC |
- DL_OPT_SB_TYPE, 0);
- if (err)
- return err;
- }
+ err = dl_argv_parse_with_selector(dl, &flags,
+ DEVLINK_CMD_SB_TC_POOL_BIND_GET,
+ DL_OPT_HANDLEP | DL_OPT_SB |
+ DL_OPT_SB_TC | DL_OPT_SB_TYPE, 0,
+ DL_OPT_HANDLE | DL_OPT_HANDLEP,
+ DL_OPT_SB);
+ if (err)
+ return err;
nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_SB_TC_POOL_BIND_GET, flags);
@@ -8697,14 +8753,11 @@ static int cmd_region_show(struct dl *dl)
uint16_t flags = NLM_F_REQUEST | NLM_F_ACK;
int err;
- if (dl_no_arg(dl)) {
- flags |= NLM_F_DUMP;
- }
- else {
- err = dl_argv_parse(dl, DL_OPT_HANDLE_REGION, 0);
- if (err)
- return err;
- }
+ err = dl_argv_parse_with_selector(dl, &flags, DEVLINK_CMD_REGION_GET,
+ DL_OPT_HANDLE_REGION, 0,
+ DL_OPT_HANDLE, 0);
+ if (err)
+ return err;
nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_REGION_GET, flags);
@@ -9388,19 +9441,20 @@ static int __cmd_health_show(struct dl *dl, bool show_device, bool show_port)
uint16_t flags = NLM_F_REQUEST | NLM_F_ACK;
int err;
- if (dl_no_arg(dl)) {
- flags |= NLM_F_DUMP;
- } else {
+ err = dl_argv_parse_with_selector(dl, &flags,
+ DEVLINK_CMD_HEALTH_REPORTER_GET,
+ DL_OPT_HANDLE | DL_OPT_HANDLEP |
+ DL_OPT_HEALTH_REPORTER_NAME, 0,
+ DL_OPT_HANDLE | DL_OPT_HANDLEP, 0);
+ if (err)
+ return err;
+
+ if (!(flags & NLM_F_DUMP))
ctx.show_port = true;
- err = dl_argv_parse(dl,
- DL_OPT_HANDLE | DL_OPT_HANDLEP |
- DL_OPT_HEALTH_REPORTER_NAME, 0);
- if (err)
- return err;
- }
nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_HEALTH_REPORTER_GET,
flags);
+
dl_opts_put(nlh, dl);
pr_out_section_start(dl, "health");
@@ -9582,14 +9636,11 @@ static int cmd_trap_show(struct dl *dl)
struct nlmsghdr *nlh;
int err;
- if (dl_no_arg(dl)) {
- flags |= NLM_F_DUMP;
- }
- else {
- err = dl_argv_parse(dl, DL_OPT_HANDLE | DL_OPT_TRAP_NAME, 0);
- if (err)
- return err;
- }
+ err = dl_argv_parse_with_selector(dl, &flags, DEVLINK_CMD_TRAP_GET,
+ DL_OPT_HANDLE | DL_OPT_TRAP_NAME, 0,
+ DL_OPT_HANDLE, 0);
+ if (err)
+ return err;
nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_TRAP_GET, flags);
@@ -9660,15 +9711,12 @@ static int cmd_trap_group_show(struct dl *dl)
struct nlmsghdr *nlh;
int err;
- if (dl_no_arg(dl)) {
- flags |= NLM_F_DUMP;
- }
- else {
- err = dl_argv_parse(dl,
- DL_OPT_HANDLE | DL_OPT_TRAP_GROUP_NAME, 0);
- if (err)
- return err;
- }
+ err = dl_argv_parse_with_selector(dl, &flags,
+ DEVLINK_CMD_TRAP_GROUP_GET,
+ DL_OPT_HANDLE | DL_OPT_TRAP_GROUP_NAME, 0,
+ DL_OPT_HANDLE, 0);
+ if (err)
+ return err;
nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_TRAP_GROUP_GET, flags);
@@ -9759,15 +9807,12 @@ static int cmd_trap_policer_show(struct dl *dl)
struct nlmsghdr *nlh;
int err;
- if (dl_no_arg(dl)) {
- flags |= NLM_F_DUMP;
- }
- else {
- err = dl_argv_parse(dl,
- DL_OPT_HANDLE | DL_OPT_TRAP_POLICER_ID, 0);
- if (err)
- return err;
- }
+ err = dl_argv_parse_with_selector(dl, &flags,
+ DEVLINK_CMD_TRAP_POLICER_GET,
+ DL_OPT_HANDLE | DL_OPT_TRAP_POLICER_ID, 0,
+ DL_OPT_HANDLE, 0);
+ if (err)
+ return err;
nlh = mnlu_gen_socket_cmd_prepare(&dl->nlg, DEVLINK_CMD_TRAP_POLICER_GET, flags);