1
2
3#include <errno.h>
4#include <stdio.h>
5#include <linux/dcbnl.h>
6
7#include "dcb.h"
8#include "utils.h"
9
10static void dcb_pfc_help_set(void)
11{
12 fprintf(stderr,
13 "Usage: dcb pfc set dev STRING\n"
14 " [ prio-pfc PFC-MAP ]\n"
15 " [ macsec-bypass { on | off } ]\n"
16 " [ delay INTEGER ]\n"
17 "\n"
18 " where PFC-MAP := [ PFC-MAP ] PFC-MAPPING\n"
19 " PFC-MAPPING := { all | TC }:PFC\n"
20 " TC := { 0 .. 7 }\n"
21 " PFC := { on | off }\n"
22 "\n"
23 );
24}
25
26static void dcb_pfc_help_show(void)
27{
28 fprintf(stderr,
29 "Usage: dcb [ -s ] pfc show dev STRING\n"
30 " [ pfc-cap ] [ prio-pfc ] [ macsec-bypass ]\n"
31 " [ delay ] [ requests ] [ indications ]\n"
32 "\n"
33 );
34}
35
36static void dcb_pfc_help(void)
37{
38 fprintf(stderr,
39 "Usage: dcb pfc help\n"
40 "\n"
41 );
42 dcb_pfc_help_show();
43 dcb_pfc_help_set();
44}
45
46static void dcb_pfc_to_array(__u8 array[IEEE_8021QAZ_MAX_TCS], __u8 pfc_en)
47{
48 int i;
49
50 for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++)
51 array[i] = !!(pfc_en & (1 << i));
52}
53
54static void dcb_pfc_from_array(__u8 array[IEEE_8021QAZ_MAX_TCS], __u8 *pfc_en_p)
55{
56 __u8 pfc_en = 0;
57 int i;
58
59 for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
60 if (array[i])
61 pfc_en |= 1 << i;
62 }
63
64 *pfc_en_p = pfc_en;
65}
66
67static int dcb_pfc_parse_mapping_prio_pfc(__u32 key, char *value, void *data)
68{
69 struct ieee_pfc *pfc = data;
70 __u8 pfc_en[IEEE_8021QAZ_MAX_TCS];
71 bool enabled;
72 int ret;
73
74 dcb_pfc_to_array(pfc_en, pfc->pfc_en);
75
76 enabled = parse_on_off("PFC", value, &ret);
77 if (ret)
78 return ret;
79
80 ret = dcb_parse_mapping("PRIO", key, IEEE_8021QAZ_MAX_TCS - 1,
81 "PFC", enabled, -1,
82 dcb_set_u8, pfc_en);
83 if (ret)
84 return ret;
85
86 dcb_pfc_from_array(pfc_en, &pfc->pfc_en);
87 return 0;
88}
89
90static void dcb_pfc_print_pfc_cap(const struct ieee_pfc *pfc)
91{
92 print_uint(PRINT_ANY, "pfc_cap", "pfc-cap %d ", pfc->pfc_cap);
93}
94
95static void dcb_pfc_print_macsec_bypass(const struct ieee_pfc *pfc)
96{
97 print_on_off(PRINT_ANY, "macsec_bypass", "macsec-bypass %s ", pfc->mbc);
98}
99
100static void dcb_pfc_print_delay(const struct ieee_pfc *pfc)
101{
102 print_uint(PRINT_ANY, "delay", "delay %d ", pfc->delay);
103}
104
105static void dcb_pfc_print_prio_pfc(const struct ieee_pfc *pfc)
106{
107 __u8 pfc_en[IEEE_8021QAZ_MAX_TCS];
108
109 dcb_pfc_to_array(pfc_en, pfc->pfc_en);
110 dcb_print_named_array("prio_pfc", "prio-pfc",
111 pfc_en, ARRAY_SIZE(pfc_en), &dcb_print_array_on_off);
112}
113
114static void dcb_pfc_print_requests(const struct ieee_pfc *pfc)
115{
116 open_json_array(PRINT_JSON, "requests");
117 print_string(PRINT_FP, NULL, "requests ", NULL);
118 dcb_print_array_u64(pfc->requests, ARRAY_SIZE(pfc->requests));
119 close_json_array(PRINT_JSON, "requests");
120}
121
122static void dcb_pfc_print_indications(const struct ieee_pfc *pfc)
123{
124 open_json_array(PRINT_JSON, "indications");
125 print_string(PRINT_FP, NULL, "indications ", NULL);
126 dcb_print_array_u64(pfc->indications, ARRAY_SIZE(pfc->indications));
127 close_json_array(PRINT_JSON, "indications");
128}
129
130static void dcb_pfc_print(const struct dcb *dcb, const struct ieee_pfc *pfc)
131{
132 dcb_pfc_print_pfc_cap(pfc);
133 dcb_pfc_print_macsec_bypass(pfc);
134 dcb_pfc_print_delay(pfc);
135 print_nl();
136
137 dcb_pfc_print_prio_pfc(pfc);
138 print_nl();
139
140 if (dcb->stats) {
141 dcb_pfc_print_requests(pfc);
142 print_nl();
143
144 dcb_pfc_print_indications(pfc);
145 print_nl();
146 }
147}
148
149static int dcb_pfc_get(struct dcb *dcb, const char *dev, struct ieee_pfc *pfc)
150{
151 return dcb_get_attribute(dcb, dev, DCB_ATTR_IEEE_PFC, pfc, sizeof(*pfc));
152}
153
154static int dcb_pfc_set(struct dcb *dcb, const char *dev, const struct ieee_pfc *pfc)
155{
156 return dcb_set_attribute(dcb, dev, DCB_ATTR_IEEE_PFC, pfc, sizeof(*pfc));
157}
158
159static int dcb_cmd_pfc_set(struct dcb *dcb, const char *dev, int argc, char **argv)
160{
161 struct ieee_pfc pfc;
162 int ret;
163
164 if (!argc) {
165 dcb_pfc_help_set();
166 return 0;
167 }
168
169 ret = dcb_pfc_get(dcb, dev, &pfc);
170 if (ret)
171 return ret;
172
173 do {
174 if (matches(*argv, "help") == 0) {
175 dcb_pfc_help_set();
176 return 0;
177 } else if (matches(*argv, "prio-pfc") == 0) {
178 NEXT_ARG();
179 ret = parse_mapping(&argc, &argv, true,
180 &dcb_pfc_parse_mapping_prio_pfc, &pfc);
181 if (ret) {
182 fprintf(stderr, "Invalid pfc mapping %s\n", *argv);
183 return ret;
184 }
185 continue;
186 } else if (matches(*argv, "macsec-bypass") == 0) {
187 NEXT_ARG();
188 pfc.mbc = parse_on_off("macsec-bypass", *argv, &ret);
189 if (ret)
190 return ret;
191 } else if (matches(*argv, "delay") == 0) {
192 NEXT_ARG();
193
194
195
196
197
198
199 if (get_u16(&pfc.delay, *argv, 0)) {
200 fprintf(stderr, "Invalid delay `%s', expected an integer 0..65535\n",
201 *argv);
202 return -EINVAL;
203 }
204 } else {
205 fprintf(stderr, "What is \"%s\"?\n", *argv);
206 dcb_pfc_help_set();
207 return -EINVAL;
208 }
209
210 NEXT_ARG_FWD();
211 } while (argc > 0);
212
213 return dcb_pfc_set(dcb, dev, &pfc);
214}
215
216static int dcb_cmd_pfc_show(struct dcb *dcb, const char *dev, int argc, char **argv)
217{
218 struct ieee_pfc pfc;
219 int ret;
220
221 ret = dcb_pfc_get(dcb, dev, &pfc);
222 if (ret)
223 return ret;
224
225 open_json_object(NULL);
226
227 if (!argc) {
228 dcb_pfc_print(dcb, &pfc);
229 goto out;
230 }
231
232 do {
233 if (matches(*argv, "help") == 0) {
234 dcb_pfc_help_show();
235 return 0;
236 } else if (matches(*argv, "prio-pfc") == 0) {
237 dcb_pfc_print_prio_pfc(&pfc);
238 print_nl();
239 } else if (matches(*argv, "pfc-cap") == 0) {
240 dcb_pfc_print_pfc_cap(&pfc);
241 print_nl();
242 } else if (matches(*argv, "macsec-bypass") == 0) {
243 dcb_pfc_print_macsec_bypass(&pfc);
244 print_nl();
245 } else if (matches(*argv, "delay") == 0) {
246 dcb_pfc_print_delay(&pfc);
247 print_nl();
248 } else if (matches(*argv, "requests") == 0) {
249 dcb_pfc_print_requests(&pfc);
250 print_nl();
251 } else if (matches(*argv, "indications") == 0) {
252 dcb_pfc_print_indications(&pfc);
253 print_nl();
254 } else {
255 fprintf(stderr, "What is \"%s\"?\n", *argv);
256 dcb_pfc_help_show();
257 return -EINVAL;
258 }
259
260 NEXT_ARG_FWD();
261 } while (argc > 0);
262
263out:
264 close_json_object();
265 return 0;
266}
267
268int dcb_cmd_pfc(struct dcb *dcb, int argc, char **argv)
269{
270 if (!argc || matches(*argv, "help") == 0) {
271 dcb_pfc_help();
272 return 0;
273 } else if (matches(*argv, "show") == 0) {
274 NEXT_ARG_FWD();
275 return dcb_cmd_parse_dev(dcb, argc, argv,
276 dcb_cmd_pfc_show, dcb_pfc_help_show);
277 } else if (matches(*argv, "set") == 0) {
278 NEXT_ARG_FWD();
279 return dcb_cmd_parse_dev(dcb, argc, argv,
280 dcb_cmd_pfc_set, dcb_pfc_help_set);
281 } else {
282 fprintf(stderr, "What is \"%s\"?\n", *argv);
283 dcb_pfc_help();
284 return -EINVAL;
285 }
286}
287