summaryrefslogtreecommitdiffstats
path: root/dcb/dcb_dcbx.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--dcb/dcb_dcbx.c192
1 files changed, 192 insertions, 0 deletions
diff --git a/dcb/dcb_dcbx.c b/dcb/dcb_dcbx.c
new file mode 100644
index 0000000..244b671
--- /dev/null
+++ b/dcb/dcb_dcbx.c
@@ -0,0 +1,192 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <linux/dcbnl.h>
+
+#include "dcb.h"
+#include "utils.h"
+
+static void dcb_dcbx_help_set(void)
+{
+ fprintf(stderr,
+ "Usage: dcb dcbx set dev STRING\n"
+ " [ host | lld-managed ]\n"
+ " [ cee | ieee ] [ static ]\n"
+ "\n"
+ );
+}
+
+static void dcb_dcbx_help_show(void)
+{
+ fprintf(stderr,
+ "Usage: dcb dcbx show dev STRING\n"
+ "\n"
+ );
+}
+
+static void dcb_dcbx_help(void)
+{
+ fprintf(stderr,
+ "Usage: dcb dcbx help\n"
+ "\n"
+ );
+ dcb_dcbx_help_show();
+ dcb_dcbx_help_set();
+}
+
+struct dcb_dcbx_flag {
+ __u8 value;
+ const char *key_fp;
+ const char *key_json;
+};
+
+static struct dcb_dcbx_flag dcb_dcbx_flags[] = {
+ {DCB_CAP_DCBX_HOST, "host"},
+ {DCB_CAP_DCBX_LLD_MANAGED, "lld-managed", "lld_managed"},
+ {DCB_CAP_DCBX_VER_CEE, "cee"},
+ {DCB_CAP_DCBX_VER_IEEE, "ieee"},
+ {DCB_CAP_DCBX_STATIC, "static"},
+};
+
+static void dcb_dcbx_print(__u8 dcbx)
+{
+ int bit;
+ int i;
+
+ while ((bit = ffs(dcbx))) {
+ bool found = false;
+
+ bit--;
+ for (i = 0; i < ARRAY_SIZE(dcb_dcbx_flags); i++) {
+ struct dcb_dcbx_flag *flag = &dcb_dcbx_flags[i];
+
+ if (flag->value == 1 << bit) {
+ print_bool(PRINT_JSON, flag->key_json ?: flag->key_fp,
+ NULL, true);
+ print_string(PRINT_FP, NULL, "%s ", flag->key_fp);
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ fprintf(stderr, "Unknown DCBX bit %#x.\n", 1 << bit);
+
+ dcbx &= ~(1 << bit);
+ }
+
+ print_nl();
+}
+
+static int dcb_dcbx_get(struct dcb *dcb, const char *dev, __u8 *dcbx)
+{
+ __u16 payload_len;
+ void *payload;
+ int err;
+
+ err = dcb_get_attribute_bare(dcb, DCB_CMD_IEEE_GET, dev, DCB_ATTR_DCBX,
+ &payload, &payload_len);
+ if (err != 0)
+ return err;
+
+ if (payload_len != 1) {
+ fprintf(stderr, "DCB_ATTR_DCBX payload has size %d, expected 1.\n",
+ payload_len);
+ return -EINVAL;
+ }
+ *dcbx = *(__u8 *) payload;
+ return 0;
+}
+
+static int dcb_dcbx_set(struct dcb *dcb, const char *dev, __u8 dcbx)
+{
+ return dcb_set_attribute_bare(dcb, DCB_CMD_SDCBX, dev, DCB_ATTR_DCBX,
+ &dcbx, 1, DCB_ATTR_DCBX);
+}
+
+static int dcb_cmd_dcbx_set(struct dcb *dcb, const char *dev, int argc, char **argv)
+{
+ __u8 dcbx = 0;
+ __u8 i;
+
+ if (!argc) {
+ dcb_dcbx_help_set();
+ return 0;
+ }
+
+ do {
+ if (matches(*argv, "help") == 0) {
+ dcb_dcbx_help_set();
+ return 0;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(dcb_dcbx_flags); i++) {
+ struct dcb_dcbx_flag *flag = &dcb_dcbx_flags[i];
+
+ if (matches(*argv, flag->key_fp) == 0) {
+ dcbx |= flag->value;
+ NEXT_ARG_FWD();
+ goto next;
+ }
+ }
+
+ fprintf(stderr, "What is \"%s\"?\n", *argv);
+ dcb_dcbx_help_set();
+ return -EINVAL;
+
+next:
+ ;
+ } while (argc > 0);
+
+ return dcb_dcbx_set(dcb, dev, dcbx);
+}
+
+static int dcb_cmd_dcbx_show(struct dcb *dcb, const char *dev, int argc, char **argv)
+{
+ __u8 dcbx;
+ int ret;
+
+ ret = dcb_dcbx_get(dcb, dev, &dcbx);
+ if (ret != 0)
+ return ret;
+
+ while (argc > 0) {
+ if (matches(*argv, "help") == 0) {
+ dcb_dcbx_help_show();
+ return 0;
+ } else {
+ fprintf(stderr, "What is \"%s\"?\n", *argv);
+ dcb_dcbx_help_show();
+ return -EINVAL;
+ }
+
+ NEXT_ARG_FWD();
+ }
+
+ open_json_object(NULL);
+ dcb_dcbx_print(dcbx);
+ close_json_object();
+ return 0;
+}
+
+int dcb_cmd_dcbx(struct dcb *dcb, int argc, char **argv)
+{
+ if (!argc || matches(*argv, "help") == 0) {
+ dcb_dcbx_help();
+ return 0;
+ } else if (matches(*argv, "show") == 0) {
+ NEXT_ARG_FWD();
+ return dcb_cmd_parse_dev(dcb, argc, argv,
+ dcb_cmd_dcbx_show, dcb_dcbx_help_show);
+ } else if (matches(*argv, "set") == 0) {
+ NEXT_ARG_FWD();
+ return dcb_cmd_parse_dev(dcb, argc, argv,
+ dcb_cmd_dcbx_set, dcb_dcbx_help_set);
+ } else {
+ fprintf(stderr, "What is \"%s\"?\n", *argv);
+ dcb_dcbx_help();
+ return -EINVAL;
+ }
+}