@@ -7,7 +7,8 @@ DCBOBJ = dcb.o \
dcb_dcbx.o \
dcb_ets.o \
dcb_maxrate.o \
- dcb_pfc.o
+ dcb_pfc.o \
+ dcb_apptrust.o
TARGETS += dcb
LDLIBS += -lm
@@ -470,7 +470,7 @@ static void dcb_help(void)
fprintf(stderr,
"Usage: dcb [ OPTIONS ] OBJECT { COMMAND | help }\n"
" dcb [ -f | --force ] { -b | --batch } filename [ -n | --netns ] netnsname\n"
- "where OBJECT := { app | buffer | dcbx | ets | maxrate | pfc }\n"
+ "where OBJECT := { app | apptrust | buffer | dcbx | ets | maxrate | pfc }\n"
" OPTIONS := [ -V | --Version | -i | --iec | -j | --json\n"
" | -N | --Numeric | -p | --pretty\n"
" | -s | --statistics | -v | --verbose]\n");
@@ -483,6 +483,8 @@ static int dcb_cmd(struct dcb *dcb, int argc, char **argv)
return 0;
} else if (matches(*argv, "app") == 0) {
return dcb_cmd_app(dcb, argc - 1, argv + 1);
+ } else if (strcmp(*argv, "apptrust") == 0) {
+ return dcb_cmd_apptrust(dcb, argc - 1, argv + 1);
} else if (matches(*argv, "buffer") == 0) {
return dcb_cmd_buffer(dcb, argc - 1, argv + 1);
} else if (matches(*argv, "dcbx") == 0) {
@@ -61,6 +61,10 @@ enum ieee_attrs_app dcb_app_attr_type_get(__u8 selector);
bool dcb_app_attr_type_validate(enum ieee_attrs_app type);
bool dcb_app_selector_validate(enum ieee_attrs_app type, __u8 selector);
+/* dcb_apptrust.c */
+
+int dcb_cmd_apptrust(struct dcb *dcb, int argc, char **argv);
+
/* dcb_buffer.c */
int dcb_cmd_buffer(struct dcb *dcb, int argc, char **argv);
new file mode 100644
@@ -0,0 +1,307 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <errno.h>
+#include <linux/dcbnl.h>
+
+#include "dcb.h"
+#include "utils.h"
+
+static void dcb_apptrust_help_set(void)
+{
+ fprintf(stderr,
+ "Usage: dcb apptrust set dev STRING\n"
+ " [ order [ ethtype | stream-port | dgram-port | port | dscp | pcp ] ]\n"
+ "\n");
+}
+
+static void dcb_apptrust_help_show(void)
+{
+ fprintf(stderr, "Usage: dcb apptrust show dev STRING\n"
+ " [ order ]\n"
+ "\n");
+}
+
+static void dcb_apptrust_help(void)
+{
+ fprintf(stderr, "Usage: dcb apptrust help\n"
+ "\n");
+ dcb_apptrust_help_show();
+ dcb_apptrust_help_set();
+}
+
+static const char *const selector_names[] = {
+ [IEEE_8021QAZ_APP_SEL_ETHERTYPE] = "ethtype",
+ [IEEE_8021QAZ_APP_SEL_STREAM] = "stream-port",
+ [IEEE_8021QAZ_APP_SEL_DGRAM] = "dgram-port",
+ [IEEE_8021QAZ_APP_SEL_ANY] = "port",
+ [IEEE_8021QAZ_APP_SEL_DSCP] = "dscp",
+ [DCB_APP_SEL_PCP] = "pcp",
+};
+
+struct dcb_apptrust_table {
+ __u8 selectors[IEEE_8021QAZ_APP_SEL_MAX + 1];
+ int nselectors;
+};
+
+static bool dcb_apptrust_contains(const struct dcb_apptrust_table *table,
+ __u8 selector)
+{
+ int i;
+
+ for (i = 0; i < table->nselectors; i++)
+ if (table->selectors[i] == selector)
+ return true;
+
+ return false;
+}
+
+static void dcb_apptrust_print_order(const struct dcb_apptrust_table *table)
+{
+ const char *str;
+ __u8 selector;
+ int i;
+
+ open_json_array(PRINT_JSON, "order");
+ print_string(PRINT_FP, NULL, "order: ", NULL);
+
+ for (i = 0; i < table->nselectors; i++) {
+ selector = table->selectors[i];
+ str = selector_names[selector];
+ print_string(PRINT_ANY, NULL, "%s ", str);
+ }
+ print_nl();
+
+ close_json_array(PRINT_JSON, "order");
+}
+
+static void dcb_apptrust_print(const struct dcb_apptrust_table *table)
+{
+ dcb_apptrust_print_order(table);
+ print_nl();
+}
+
+static int dcb_apptrust_get_cb(const struct nlattr *attr, void *data)
+{
+ struct dcb_apptrust_table *table = data;
+ uint16_t type;
+ __u8 selector;
+
+ type = mnl_attr_get_type(attr);
+
+ if (!dcb_app_attr_type_validate(type)) {
+ fprintf(stderr,
+ "Unknown attribute in DCB_ATTR_IEEE_APP_TRUST_TABLE: %d\n",
+ type);
+ return MNL_CB_OK;
+ }
+
+ if (mnl_attr_get_payload_len(attr) < 1) {
+ fprintf(stderr,
+ "DCB_ATTR_IEEE_APP_TRUST payload expected to have size %zd, not %d\n",
+ sizeof(struct dcb_app), mnl_attr_get_payload_len(attr));
+ return MNL_CB_OK;
+ }
+
+ selector = mnl_attr_get_u8(attr);
+
+ /* Check that selector is encapsulated in the right attribute */
+ if (!dcb_app_selector_validate(type, selector)) {
+ fprintf(stderr, "Wrong type for selector: %s\n",
+ selector_names[selector]);
+ return MNL_CB_OK;
+ }
+
+ table->selectors[table->nselectors++] = selector;
+
+ return MNL_CB_OK;
+}
+
+static int dcb_apptrust_get(struct dcb *dcb, const char *dev,
+ struct dcb_apptrust_table *table)
+{
+ uint16_t payload_len;
+ void *payload;
+ int ret;
+
+ ret = dcb_get_attribute_va(dcb, dev, DCB_ATTR_DCB_APP_TRUST_TABLE,
+ &payload, &payload_len);
+ if (ret != 0)
+ return ret;
+
+ ret = mnl_attr_parse_payload(payload, payload_len, dcb_apptrust_get_cb,
+ table);
+ if (ret != MNL_CB_OK)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int dcb_apptrust_set_cb(struct dcb *dcb, struct nlmsghdr *nlh,
+ void *data)
+{
+ const struct dcb_apptrust_table *table = data;
+ enum ieee_attrs_app type;
+ struct nlattr *nest;
+ int i;
+
+ nest = mnl_attr_nest_start(nlh, DCB_ATTR_DCB_APP_TRUST_TABLE);
+
+ for (i = 0; i < table->nselectors; i++) {
+ type = dcb_app_attr_type_get(table->selectors[i]);
+ mnl_attr_put_u8(nlh, type, table->selectors[i]);
+ }
+
+ mnl_attr_nest_end(nlh, nest);
+
+ return 0;
+}
+
+static int dcb_apptrust_set(struct dcb *dcb, const char *dev,
+ const struct dcb_apptrust_table *table)
+{
+ return dcb_set_attribute_va(dcb, DCB_CMD_IEEE_SET, dev,
+ &dcb_apptrust_set_cb, (void *)table);
+}
+
+static __u8 dcb_apptrust_parse_selector(const char *selector, int *err)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(selector_names); i++) {
+ if (selector_names[i] &&
+ strcmp(selector, selector_names[i]) == 0) {
+ *err = 0;
+ return i;
+ }
+ }
+
+ *err = -EINVAL;
+ return 0;
+}
+
+static int dcb_apptrust_parse_selector_list(int *argcp, char ***argvp,
+ struct dcb_apptrust_table *table)
+{
+ int argc = *argcp, err;
+ char **argv = *argvp;
+ __u8 selector;
+
+ /* No trusted selectors ? */
+ if (argc == 0)
+ goto out;
+
+ while (argc > 0) {
+ selector = dcb_apptrust_parse_selector(*argv, &err);
+ if (err < 0)
+ goto out;
+
+ if (table->nselectors > IEEE_8021QAZ_APP_SEL_MAX)
+ return -ERANGE;
+
+ if (dcb_apptrust_contains(table, selector)) {
+ fprintf(stderr, "Duplicate selector: %s\n",
+ selector_names[selector]);
+ return -EINVAL;
+ }
+
+ table->selectors[table->nselectors++] = selector;
+
+ NEXT_ARG_FWD();
+ }
+
+out:
+ *argcp = argc;
+ *argvp = argv;
+
+ return 0;
+}
+
+static int dcb_cmd_apptrust_set(struct dcb *dcb, const char *dev, int argc,
+ char **argv)
+{
+ struct dcb_apptrust_table table = { 0 };
+ int ret;
+
+ if (!argc) {
+ dcb_apptrust_help_set();
+ return 0;
+ }
+
+ do {
+ if (strcmp(*argv, "help") == 0) {
+ dcb_apptrust_help_set();
+ return 0;
+ } else if (strcmp(*argv, "order") == 0) {
+ NEXT_ARG_FWD();
+ ret = dcb_apptrust_parse_selector_list(&argc, &argv,
+ &table);
+ if (ret < 0) {
+ fprintf(stderr, "Invalid list of selectors\n");
+ return -EINVAL;
+ }
+ } else {
+ fprintf(stderr, "What is \"%s\"?\n", *argv);
+ dcb_apptrust_help_set();
+ return -EINVAL;
+ }
+ } while (argc > 0);
+
+ return dcb_apptrust_set(dcb, dev, &table);
+}
+
+static int dcb_cmd_apptrust_show(struct dcb *dcb, const char *dev, int argc,
+ char **argv)
+{
+ struct dcb_apptrust_table table = { 0 };
+ int ret;
+
+ ret = dcb_apptrust_get(dcb, dev, &table);
+ if (ret)
+ return ret;
+
+ open_json_object(NULL);
+
+ if (!argc) {
+ dcb_apptrust_print(&table);
+ goto out;
+ }
+
+ do {
+ if (strcmp(*argv, "help") == 0) {
+ dcb_apptrust_help_show();
+ return 0;
+ } else if (strcmp(*argv, "order") == 0) {
+ dcb_apptrust_print_order(&table);
+ } else {
+ fprintf(stderr, "What is \"%s\"?\n", *argv);
+ dcb_apptrust_help_show();
+ return -EINVAL;
+ }
+
+ NEXT_ARG_FWD();
+ } while (argc > 0);
+
+out:
+ close_json_object();
+ return 0;
+}
+
+int dcb_cmd_apptrust(struct dcb *dcb, int argc, char **argv)
+{
+ if (!argc || strcmp(*argv, "help") == 0) {
+ dcb_apptrust_help();
+ return 0;
+ } else if (strcmp(*argv, "show") == 0) {
+ NEXT_ARG_FWD();
+ return dcb_cmd_parse_dev(dcb, argc, argv, dcb_cmd_apptrust_show,
+ dcb_apptrust_help_show);
+ } else if (strcmp(*argv, "set") == 0) {
+ NEXT_ARG_FWD();
+ return dcb_cmd_parse_dev(dcb, argc, argv, dcb_cmd_apptrust_set,
+ dcb_apptrust_help_set);
+ } else {
+ fprintf(stderr, "What is \"%s\"?\n", *argv);
+ dcb_apptrust_help();
+ return -EINVAL;
+ }
+}
new file mode 100644
@@ -0,0 +1,109 @@
+.TH DCB-APPTRUST 8 "22 November 2022" "iproute2" "Linux"
+.SH NAME
+dcb-apptrust \- show / configure per-selector trust and trust order of the
+application priority table of the DCB (Data Center Bridging) subsystem.
+.SH SYNOPSIS
+.sp
+.ad l
+.in +8
+
+.ti -8
+.B dcb
+.RI "[ " OPTIONS " ] "
+.B apptrust
+.RI "{ " COMMAND " | " help " }"
+.sp
+
+.ti -8
+.B dcb apptrust show dev
+.RI DEV
+.RB "[ " order " ]"
+
+.ti -8
+.B dcb apptrust set dev
+.RI DEV
+.RB "[ " order " " \fiSEL-LIST\fB " ]"
+
+.ti -8
+.IR SEL-LIST " := [ " SEL-LIST " ] " SEL
+
+.ti -8
+.IR SEL " := { " ethtype " | " stream-port " | " dgram-port " | " port " | " dscp " | " pcp " } "
+
+.SH DESCRIPTION
+
+.B dcb apptrust
+is used to configure per-selector trust and trust order of the
+Application Priority Table, see
+.BR dcb-app (8)
+for details on how to configure app table entries.
+
+Selector trust can be used by the
+software stack, or drivers (most likely the latter), when querying the APP
+table, to determine if an APP entry should take effect, or not. Additionaly, the
+order of the trusted selectors will dictate which selector should take
+precedence, in the case of multiple different APP table selectors being present.
+
+.SH COMMANDS
+
+.TP
+.B show
+Display all trusted selectors.
+
+.TP
+.B set
+Set new list of trusted selectors. Empty list is effectively the same as
+removing trust entirely.
+
+.SH PARAMETERS
+
+The following describes only the write direction, i.e. as used with the
+\fBset\fR command. For the \fBshow\fR command, the parameter name is to be used
+as a simple keyword without further arguments. This instructs the tool to show
+the values of a given parameter.
+
+.TP
+.B order \fISEL-LIST
+\fISEL-LIST\fR is a space-separated list of selector names. Possible selector
+values are:
+.B ethtype,
+.B stream-port,
+.B dgram-port,
+.B port,
+.B dscp,
+and
+.B pcp
+
+
+.SH EXAMPLE & USAGE
+
+Set trust order to: dscp, pcp for eth0:
+.P
+# dcb apptrust set dev eth0 order dscp pcp
+
+Set trust order to: port (stream or dgram), pcp, ethtype for eth1:
+.P
+# dcb apptrust set dev eth1 order port pcp ethtype
+
+Show what was set:
+
+.P
+# dcb apptrust show dev eth0
+.br
+order: port pcp ethtype
+
+.SH EXIT STATUS
+Exit status is 0 if command was successful or a positive integer upon failure.
+
+.SH SEE ALSO
+.BR dcb (8),
+.BR dcb-app (8)
+
+.SH REPORTING BUGS
+Report any bugs to the Network Developers mailing list
+.B <netdev@vger.kernel.org>
+where the development and maintenance is primarily done.
+You do not have to be subscribed to the list to send a message there.
+
+.SH AUTHOR
+Daniel Machon <daniel.machon@microchip.com>