1
2
3#include <errno.h>
4#include <inttypes.h>
5#include <stdio.h>
6#include <linux/dcbnl.h>
7
8#include "dcb.h"
9#include "utils.h"
10
11static void dcb_dcbx_help_set(void)
12{
13 fprintf(stderr,
14 "Usage: dcb dcbx set dev STRING\n"
15 " [ host | lld-managed ]\n"
16 " [ cee | ieee ] [ static ]\n"
17 "\n"
18 );
19}
20
21static void dcb_dcbx_help_show(void)
22{
23 fprintf(stderr,
24 "Usage: dcb dcbx show dev STRING\n"
25 "\n"
26 );
27}
28
29static void dcb_dcbx_help(void)
30{
31 fprintf(stderr,
32 "Usage: dcb dcbx help\n"
33 "\n"
34 );
35 dcb_dcbx_help_show();
36 dcb_dcbx_help_set();
37}
38
39struct dcb_dcbx_flag {
40 __u8 value;
41 const char *key_fp;
42 const char *key_json;
43};
44
45static struct dcb_dcbx_flag dcb_dcbx_flags[] = {
46 {DCB_CAP_DCBX_HOST, "host"},
47 {DCB_CAP_DCBX_LLD_MANAGED, "lld-managed", "lld_managed"},
48 {DCB_CAP_DCBX_VER_CEE, "cee"},
49 {DCB_CAP_DCBX_VER_IEEE, "ieee"},
50 {DCB_CAP_DCBX_STATIC, "static"},
51};
52
53static void dcb_dcbx_print(__u8 dcbx)
54{
55 int bit;
56 int i;
57
58 while ((bit = ffs(dcbx))) {
59 bool found = false;
60
61 bit--;
62 for (i = 0; i < ARRAY_SIZE(dcb_dcbx_flags); i++) {
63 struct dcb_dcbx_flag *flag = &dcb_dcbx_flags[i];
64
65 if (flag->value == 1 << bit) {
66 print_bool(PRINT_JSON, flag->key_json ?: flag->key_fp,
67 NULL, true);
68 print_string(PRINT_FP, NULL, "%s ", flag->key_fp);
69 found = true;
70 break;
71 }
72 }
73
74 if (!found)
75 fprintf(stderr, "Unknown DCBX bit %#x.\n", 1 << bit);
76
77 dcbx &= ~(1 << bit);
78 }
79
80 print_nl();
81}
82
83static int dcb_dcbx_get(struct dcb *dcb, const char *dev, __u8 *dcbx)
84{
85 __u16 payload_len;
86 void *payload;
87 int err;
88
89 err = dcb_get_attribute_bare(dcb, DCB_CMD_IEEE_GET, dev, DCB_ATTR_DCBX,
90 &payload, &payload_len);
91 if (err != 0)
92 return err;
93
94 if (payload_len != 1) {
95 fprintf(stderr, "DCB_ATTR_DCBX payload has size %d, expected 1.\n",
96 payload_len);
97 return -EINVAL;
98 }
99 *dcbx = *(__u8 *) payload;
100 return 0;
101}
102
103static int dcb_dcbx_set(struct dcb *dcb, const char *dev, __u8 dcbx)
104{
105 return dcb_set_attribute_bare(dcb, DCB_CMD_SDCBX, dev, DCB_ATTR_DCBX,
106 &dcbx, 1, DCB_ATTR_DCBX);
107}
108
109static int dcb_cmd_dcbx_set(struct dcb *dcb, const char *dev, int argc, char **argv)
110{
111 __u8 dcbx = 0;
112 __u8 i;
113
114 if (!argc) {
115 dcb_dcbx_help_set();
116 return 0;
117 }
118
119 do {
120 if (matches(*argv, "help") == 0) {
121 dcb_dcbx_help_set();
122 return 0;
123 }
124
125 for (i = 0; i < ARRAY_SIZE(dcb_dcbx_flags); i++) {
126 struct dcb_dcbx_flag *flag = &dcb_dcbx_flags[i];
127
128 if (matches(*argv, flag->key_fp) == 0) {
129 dcbx |= flag->value;
130 NEXT_ARG_FWD();
131 goto next;
132 }
133 }
134
135 fprintf(stderr, "What is \"%s\"?\n", *argv);
136 dcb_dcbx_help_set();
137 return -EINVAL;
138
139next:
140 ;
141 } while (argc > 0);
142
143 return dcb_dcbx_set(dcb, dev, dcbx);
144}
145
146static int dcb_cmd_dcbx_show(struct dcb *dcb, const char *dev, int argc, char **argv)
147{
148 __u8 dcbx;
149 int ret;
150
151 ret = dcb_dcbx_get(dcb, dev, &dcbx);
152 if (ret != 0)
153 return ret;
154
155 while (argc > 0) {
156 if (matches(*argv, "help") == 0) {
157 dcb_dcbx_help_show();
158 return 0;
159 } else {
160 fprintf(stderr, "What is \"%s\"?\n", *argv);
161 dcb_dcbx_help_show();
162 return -EINVAL;
163 }
164
165 NEXT_ARG_FWD();
166 }
167
168 open_json_object(NULL);
169 dcb_dcbx_print(dcbx);
170 close_json_object();
171 return 0;
172}
173
174int dcb_cmd_dcbx(struct dcb *dcb, int argc, char **argv)
175{
176 if (!argc || matches(*argv, "help") == 0) {
177 dcb_dcbx_help();
178 return 0;
179 } else if (matches(*argv, "show") == 0) {
180 NEXT_ARG_FWD();
181 return dcb_cmd_parse_dev(dcb, argc, argv,
182 dcb_cmd_dcbx_show, dcb_dcbx_help_show);
183 } else if (matches(*argv, "set") == 0) {
184 NEXT_ARG_FWD();
185 return dcb_cmd_parse_dev(dcb, argc, argv,
186 dcb_cmd_dcbx_set, dcb_dcbx_help_set);
187 } else {
188 fprintf(stderr, "What is \"%s\"?\n", *argv);
189 dcb_dcbx_help();
190 return -EINVAL;
191 }
192}
193