1
2
3#include <errno.h>
4#include <linux/dcbnl.h>
5#include <stdio.h>
6
7#include "dcb.h"
8#include "utils.h"
9
10static void dcb_rewr_help_add(void)
11{
12 fprintf(stderr,
13 "Usage: dcb rewr { add | del | replace } dev STRING\n"
14 " [ prio-pcp PRIO:PCP ]\n"
15 " [ prio-dscp PRIO:DSCP ]\n"
16 "\n"
17 " where PRIO := { 0 .. 7 }\n"
18 " PCP := { 0(nd/de) .. 7(nd/de) }\n"
19 " DSCP := { 0 .. 63 }\n"
20 "\n"
21 );
22}
23
24static void dcb_rewr_help_show_flush(void)
25{
26 fprintf(stderr,
27 "Usage: dcb rewr { show | flush } dev STRING\n"
28 " [ prio-pcp ]\n"
29 " [ prio-dscp ]\n"
30 "\n"
31 );
32}
33
34static void dcb_rewr_help(void)
35{
36 fprintf(stderr,
37 "Usage: dcb rewr help\n"
38 "\n"
39 );
40 dcb_rewr_help_show_flush();
41 dcb_rewr_help_add();
42}
43
44static void dcb_rewr_parse_mapping_cb(__u32 key, __u64 value, void *data)
45{
46 struct dcb_app_parse_mapping *pm = data;
47 struct dcb_app app = {
48 .selector = pm->selector,
49 .priority = key,
50 .protocol = value,
51 };
52
53 if (pm->err)
54 return;
55
56 pm->err = dcb_app_table_push(pm->tab, &app);
57}
58
59static int dcb_rewr_parse_mapping_prio_pcp(__u32 key, char *value, void *data)
60{
61 __u32 pcp;
62
63 if (dcb_app_parse_pcp(&pcp, value))
64 return -EINVAL;
65
66 return dcb_parse_mapping("PRIO", key, IEEE_8021QAZ_MAX_TCS - 1,
67 "PCP", pcp, DCB_APP_PCP_MAX,
68 dcb_rewr_parse_mapping_cb, data);
69}
70
71static int dcb_rewr_parse_mapping_prio_dscp(__u32 key, char *value, void *data)
72{
73 __u32 dscp;
74
75 if (dcb_app_parse_dscp(&dscp, value))
76 return -EINVAL;
77
78 return dcb_parse_mapping("PRIO", key, IEEE_8021QAZ_MAX_TCS - 1,
79 "DSCP", dscp, DCB_APP_DSCP_MAX,
80 dcb_rewr_parse_mapping_cb, data);
81}
82
83static void dcb_rewr_print_prio_pid(int (*print_pid)(__u16 protocol),
84 const struct dcb_app *app)
85{
86 print_uint(PRINT_ANY, NULL, "%u:", app->priority);
87 print_pid(app->protocol);
88}
89
90static void dcb_rewr_print_prio_pcp(const struct dcb *dcb,
91 const struct dcb_app_table *tab)
92{
93 dcb_app_print_filtered(tab, dcb_app_is_pcp,
94 dcb_rewr_print_prio_pid,
95 dcb->numeric ? dcb_app_print_pid_dec :
96 dcb_app_print_pid_pcp,
97 "prio_pcp", "prio-pcp");
98}
99
100static void dcb_rewr_print_prio_dscp(const struct dcb *dcb,
101 const struct dcb_app_table *tab)
102{
103 dcb_app_print_filtered(tab, dcb_app_is_dscp,
104 dcb_rewr_print_prio_pid,
105 dcb->numeric ? dcb_app_print_pid_dec :
106 dcb_app_print_pid_dscp,
107 "prio_dscp", "prio-dscp");
108}
109
110static void dcb_rewr_print(const struct dcb *dcb,
111 const struct dcb_app_table *tab)
112{
113 dcb_rewr_print_prio_pcp(dcb, tab);
114 dcb_rewr_print_prio_dscp(dcb, tab);
115}
116
117static bool dcb_rewr_prio_eq(const struct dcb_app *aa, const struct dcb_app *ab)
118{
119 return aa->selector == ab->selector &&
120 aa->priority == ab->priority;
121}
122
123static int dcb_cmd_rewr_parse_add_del(struct dcb *dcb, const char *dev,
124 int argc, char **argv,
125 struct dcb_app_table *tab)
126{
127 struct dcb_app_parse_mapping pm = {
128 .tab = tab,
129 };
130 int ret;
131
132 if (!argc) {
133 dcb_rewr_help_add();
134 return 0;
135 }
136
137 do {
138 if (strcmp(*argv, "help") == 0) {
139 dcb_rewr_help_add();
140 return 0;
141 } else if (strcmp(*argv, "prio-pcp") == 0) {
142 NEXT_ARG();
143 pm.selector = DCB_APP_SEL_PCP;
144 ret = parse_mapping(&argc, &argv, false,
145 &dcb_rewr_parse_mapping_prio_pcp,
146 &pm);
147 } else if (strcmp(*argv, "prio-dscp") == 0) {
148 NEXT_ARG();
149 pm.selector = IEEE_8021QAZ_APP_SEL_DSCP;
150 ret = parse_mapping(&argc, &argv, false,
151 &dcb_rewr_parse_mapping_prio_dscp,
152 &pm);
153 } else {
154 fprintf(stderr, "What is \"%s\"?\n", *argv);
155 dcb_rewr_help_add();
156 return -EINVAL;
157 }
158
159 if (ret != 0) {
160 fprintf(stderr, "Invalid mapping %s\n", *argv);
161 return ret;
162 }
163 if (pm.err)
164 return pm.err;
165 } while (argc > 0);
166
167 return 0;
168}
169
170static int dcb_cmd_rewr_add(struct dcb *dcb, const char *dev, int argc,
171 char **argv)
172{
173 struct dcb_app_table tab = { .attr = DCB_ATTR_DCB_REWR_TABLE };
174 int ret;
175
176 ret = dcb_cmd_rewr_parse_add_del(dcb, dev, argc, argv, &tab);
177 if (ret != 0)
178 return ret;
179
180 ret = dcb_app_add_del(dcb, dev, DCB_CMD_IEEE_SET, &tab, NULL);
181 dcb_app_table_fini(&tab);
182 return ret;
183}
184
185static int dcb_cmd_rewr_del(struct dcb *dcb, const char *dev, int argc,
186 char **argv)
187{
188 struct dcb_app_table tab = { .attr = DCB_ATTR_DCB_REWR_TABLE };
189 int ret;
190
191 ret = dcb_cmd_rewr_parse_add_del(dcb, dev, argc, argv, &tab);
192 if (ret != 0)
193 return ret;
194
195 ret = dcb_app_add_del(dcb, dev, DCB_CMD_IEEE_DEL, &tab, NULL);
196 dcb_app_table_fini(&tab);
197 return ret;
198}
199
200static int dcb_cmd_rewr_replace(struct dcb *dcb, const char *dev, int argc,
201 char **argv)
202{
203 struct dcb_app_table orig = { .attr = DCB_ATTR_DCB_REWR_TABLE };
204 struct dcb_app_table tab = { .attr = DCB_ATTR_DCB_REWR_TABLE };
205 struct dcb_app_table new = { .attr = DCB_ATTR_DCB_REWR_TABLE };
206 int ret;
207
208 ret = dcb_app_get(dcb, dev, &orig);
209 if (ret != 0)
210 return ret;
211
212 ret = dcb_cmd_rewr_parse_add_del(dcb, dev, argc, argv, &tab);
213 if (ret != 0)
214 goto out;
215
216
217
218
219 ret = dcb_app_table_copy(&new, &tab);
220 if (ret != 0)
221 goto out;
222 dcb_app_table_remove_existing(&new, &orig);
223
224 ret = dcb_app_add_del(dcb, dev, DCB_CMD_IEEE_SET, &new, NULL);
225 if (ret != 0) {
226 fprintf(stderr, "Could not add new rewrite entries\n");
227 goto out;
228 }
229
230
231 dcb_app_table_remove_replaced(&orig, &tab, dcb_rewr_prio_eq);
232 ret = dcb_app_add_del(dcb, dev, DCB_CMD_IEEE_DEL, &orig, NULL);
233 if (ret != 0) {
234 fprintf(stderr, "Could not remove replaced rewrite entries\n");
235 goto out;
236 }
237
238out:
239 dcb_app_table_fini(&new);
240 dcb_app_table_fini(&tab);
241 dcb_app_table_fini(&orig);
242 return 0;
243}
244
245static int dcb_cmd_rewr_show(struct dcb *dcb, const char *dev, int argc,
246 char **argv)
247{
248 struct dcb_app_table tab = { .attr = DCB_ATTR_DCB_REWR_TABLE };
249 int ret;
250
251 ret = dcb_app_get(dcb, dev, &tab);
252 if (ret != 0)
253 return ret;
254
255 dcb_app_table_sort(&tab);
256
257 open_json_object(NULL);
258
259 if (!argc) {
260 dcb_rewr_print(dcb, &tab);
261 goto out;
262 }
263
264 do {
265 if (strcmp(*argv, "help") == 0) {
266 dcb_rewr_help_show_flush();
267 goto out;
268 } else if (strcmp(*argv, "prio-pcp") == 0) {
269 dcb_rewr_print_prio_pcp(dcb, &tab);
270 } else if (strcmp(*argv, "prio-dscp") == 0) {
271 dcb_rewr_print_prio_dscp(dcb, &tab);
272 } else {
273 fprintf(stderr, "What is \"%s\"?\n", *argv);
274 dcb_rewr_help_show_flush();
275 ret = -EINVAL;
276 goto out;
277 }
278
279 NEXT_ARG_FWD();
280 } while (argc > 0);
281
282out:
283 close_json_object();
284 dcb_app_table_fini(&tab);
285 return ret;
286}
287
288static int dcb_cmd_rewr_flush(struct dcb *dcb, const char *dev, int argc,
289 char **argv)
290{
291 struct dcb_app_table tab = { .attr = DCB_ATTR_DCB_REWR_TABLE };
292 int ret;
293
294 ret = dcb_app_get(dcb, dev, &tab);
295 if (ret != 0)
296 return ret;
297
298 if (!argc) {
299 ret = dcb_app_add_del(dcb, dev, DCB_CMD_IEEE_DEL, &tab,
300 NULL);
301 goto out;
302 }
303
304 do {
305 if (strcmp(*argv, "help") == 0) {
306 dcb_rewr_help_show_flush();
307 goto out;
308 } else if (strcmp(*argv, "prio-pcp") == 0) {
309 ret = dcb_app_add_del(dcb, dev, DCB_CMD_IEEE_DEL, &tab,
310 &dcb_app_is_pcp);
311 if (ret != 0)
312 goto out;
313 } else if (strcmp(*argv, "prio-dscp") == 0) {
314 ret = dcb_app_add_del(dcb, dev, DCB_CMD_IEEE_DEL, &tab,
315 &dcb_app_is_dscp);
316 if (ret != 0)
317 goto out;
318 } else {
319 fprintf(stderr, "What is \"%s\"?\n", *argv);
320 dcb_rewr_help_show_flush();
321 ret = -EINVAL;
322 goto out;
323 }
324
325 NEXT_ARG_FWD();
326 } while (argc > 0);
327
328out:
329 dcb_app_table_fini(&tab);
330 return ret;
331}
332
333int dcb_cmd_rewr(struct dcb *dcb, int argc, char **argv)
334{
335 if (!argc || strcmp(*argv, "help") == 0) {
336 dcb_rewr_help();
337 return 0;
338 } else if (strcmp(*argv, "show") == 0) {
339 NEXT_ARG_FWD();
340 return dcb_cmd_parse_dev(dcb, argc, argv, dcb_cmd_rewr_show,
341 dcb_rewr_help_show_flush);
342 } else if (strcmp(*argv, "flush") == 0) {
343 NEXT_ARG_FWD();
344 return dcb_cmd_parse_dev(dcb, argc, argv, dcb_cmd_rewr_flush,
345 dcb_rewr_help_show_flush);
346 } else if (strcmp(*argv, "add") == 0) {
347 NEXT_ARG_FWD();
348 return dcb_cmd_parse_dev(dcb, argc, argv, dcb_cmd_rewr_add,
349 dcb_rewr_help_add);
350 } else if (strcmp(*argv, "del") == 0) {
351 NEXT_ARG_FWD();
352 return dcb_cmd_parse_dev(dcb, argc, argv, dcb_cmd_rewr_del,
353 dcb_rewr_help_add);
354 } else if (strcmp(*argv, "replace") == 0) {
355 NEXT_ARG_FWD();
356 return dcb_cmd_parse_dev(dcb, argc, argv, dcb_cmd_rewr_replace,
357 dcb_rewr_help_add);
358 } else {
359 fprintf(stderr, "What is \"%s\"?\n", *argv);
360 dcb_rewr_help();
361 return -EINVAL;
362 }
363}
364