1
2
3
4
5
6
7#include <stdint.h>
8#include <stdlib.h>
9#include <string.h>
10
11#include <rte_common.h>
12#include <rte_cfgfile.h>
13#include <rte_log.h>
14#include <rte_lcore.h>
15#include <rte_malloc.h>
16#include <rte_string_fns.h>
17
18#include "mrvl_qos.h"
19
20
21#define MRVL_TOK_DEFAULT "default"
22#define MRVL_TOK_DSA_MODE "dsa_mode"
23#define MRVL_TOK_START_HDR "start_hdr"
24#define MRVL_TOK_START_HDR_NONE "none"
25#define MRVL_TOK_START_HDR_DSA "dsa"
26#define MRVL_TOK_START_HDR_CUSTOM "custom"
27#define MRVL_TOK_START_HDR_EXT_DSA "ext_dsa"
28#define MRVL_TOK_DEFAULT_TC "default_tc"
29#define MRVL_TOK_DSCP "dscp"
30#define MRVL_TOK_MAPPING_PRIORITY "mapping_priority"
31#define MRVL_TOK_IP "ip"
32#define MRVL_TOK_IP_VLAN "ip/vlan"
33#define MRVL_TOK_PCP "pcp"
34#define MRVL_TOK_PORT "port"
35#define MRVL_TOK_RXQ "rxq"
36#define MRVL_TOK_TC "tc"
37#define MRVL_TOK_TXQ "txq"
38#define MRVL_TOK_VLAN "vlan"
39#define MRVL_TOK_VLAN_IP "vlan/ip"
40#define MRVL_TOK_PARSER_UDF "parser udf"
41
42
43#define MRVL_TOK_BURST_SIZE "burst_size"
44#define MRVL_TOK_RATE_LIMIT "rate_limit"
45#define MRVL_TOK_RATE_LIMIT_ENABLE "rate_limit_enable"
46#define MRVL_TOK_SCHED_MODE "sched_mode"
47#define MRVL_TOK_SCHED_MODE_SP "sp"
48#define MRVL_TOK_SCHED_MODE_WRR "wrr"
49#define MRVL_TOK_WRR_WEIGHT "wrr_weight"
50
51
52#define MRVL_TOK_PLCR "policer"
53#define MRVL_TOK_PLCR_DEFAULT "default_policer"
54#define MRVL_TOK_PLCR_UNIT "token_unit"
55#define MRVL_TOK_PLCR_UNIT_BYTES "bytes"
56#define MRVL_TOK_PLCR_UNIT_PACKETS "packets"
57#define MRVL_TOK_PLCR_COLOR "color_mode"
58#define MRVL_TOK_PLCR_COLOR_BLIND "blind"
59#define MRVL_TOK_PLCR_COLOR_AWARE "aware"
60#define MRVL_TOK_PLCR_CIR "cir"
61#define MRVL_TOK_PLCR_CBS "cbs"
62#define MRVL_TOK_PLCR_EBS "ebs"
63#define MRVL_TOK_PLCR_DEFAULT_COLOR "default_color"
64#define MRVL_TOK_PLCR_DEFAULT_COLOR_GREEN "green"
65#define MRVL_TOK_PLCR_DEFAULT_COLOR_YELLOW "yellow"
66#define MRVL_TOK_PLCR_DEFAULT_COLOR_RED "red"
67
68
69#define MRVL_TOK_PARSER_UDF_PROTO "proto"
70#define MRVL_TOK_PARSER_UDF_FIELD "field"
71#define MRVL_TOK_PARSER_UDF_KEY "key"
72#define MRVL_TOK_PARSER_UDF_MASK "mask"
73#define MRVL_TOK_PARSER_UDF_OFFSET "offset"
74#define MRVL_TOK_PARSER_UDF_PROTO_ETH "eth"
75#define MRVL_TOK_PARSER_UDF_FIELD_ETH_TYPE "type"
76#define MRVL_TOK_PARSER_UDF_PROTO_UDP "udp"
77#define MRVL_TOK_PARSER_UDF_FIELD_UDP_DPORT "dport"
78
79
80#define MRVL_TOK_FWD_BAD_FRAMES "forward_bad_frames"
81
82
83#define MRVL_TOK_FILL_BPOOL_BUFFS "fill_bpool_buffs"
84
85
86#define MAX_RNG_TOKENS 2
87
88
89#define MAX_PCP 7
90
91
92#define MAX_DSCP 63
93
94
95struct mrvl_cfg *mrvl_cfg;
96
97
98
99
100
101
102
103
104
105
106static int
107get_outq_cfg(struct rte_cfgfile *file, int port, int outq,
108 struct mrvl_cfg *cfg)
109{
110 char sec_name[32];
111 const char *entry;
112 uint32_t val;
113
114 snprintf(sec_name, sizeof(sec_name), "%s %d %s %d",
115 MRVL_TOK_PORT, port, MRVL_TOK_TXQ, outq);
116
117
118 if (rte_cfgfile_num_sections(file, sec_name, strlen(sec_name)) <= 0)
119 return 0;
120
121
122 entry = rte_cfgfile_get_entry(file, sec_name, MRVL_TOK_SCHED_MODE);
123 if (entry) {
124 if (!strncmp(entry, MRVL_TOK_SCHED_MODE_SP,
125 strlen(MRVL_TOK_SCHED_MODE_SP))) {
126 cfg->port[port].outq[outq].sched_mode =
127 PP2_PPIO_SCHED_M_SP;
128 } else if (!strncmp(entry, MRVL_TOK_SCHED_MODE_WRR,
129 strlen(MRVL_TOK_SCHED_MODE_WRR))) {
130 cfg->port[port].outq[outq].sched_mode =
131 PP2_PPIO_SCHED_M_WRR;
132 } else {
133 MRVL_LOG(ERR, "Unknown token: %s", entry);
134 return -1;
135 }
136 }
137
138
139 if (cfg->port[port].outq[outq].sched_mode == PP2_PPIO_SCHED_M_WRR) {
140 entry = rte_cfgfile_get_entry(file, sec_name,
141 MRVL_TOK_WRR_WEIGHT);
142 if (entry) {
143 if (get_val_securely(entry, &val) < 0)
144 return -1;
145 cfg->port[port].outq[outq].weight = val;
146 }
147 }
148
149
150
151
152
153 if (cfg->port[port].rate_limit_enable) {
154 MRVL_LOG(WARNING, "Port %d rate limiting already enabled",
155 port);
156 return 0;
157 }
158
159 entry = rte_cfgfile_get_entry(file, sec_name,
160 MRVL_TOK_RATE_LIMIT_ENABLE);
161 if (entry) {
162 if (get_val_securely(entry, &val) < 0)
163 return -1;
164 cfg->port[port].outq[outq].rate_limit_enable = val;
165 }
166
167 if (!cfg->port[port].outq[outq].rate_limit_enable)
168 return 0;
169
170
171 entry = rte_cfgfile_get_entry(file, sec_name, MRVL_TOK_BURST_SIZE);
172 if (entry) {
173 if (get_val_securely(entry, &val) < 0)
174 return -1;
175 cfg->port[port].outq[outq].rate_limit_params.cbs = val;
176 }
177
178
179 entry = rte_cfgfile_get_entry(file, sec_name, MRVL_TOK_RATE_LIMIT);
180 if (entry) {
181 if (get_val_securely(entry, &val) < 0)
182 return -1;
183 cfg->port[port].outq[outq].rate_limit_params.cir = val;
184 }
185
186 return 0;
187}
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214static int
215get_entry_values(const char *entry, uint8_t *tab,
216 size_t elem_sz, uint8_t max_elems, uint8_t max_val)
217{
218
219
220
221 char *tokens[max_elems + 1];
222
223
224 char *rng_tokens[MAX_RNG_TOKENS + 1];
225 long beg, end;
226 uint32_t token_val;
227 int nb_tokens, nb_rng_tokens;
228 int i;
229 int values = 0;
230 char val;
231 char entry_cpy[CFG_VALUE_LEN];
232
233 if (elem_sz != 1)
234 return -1;
235
236
237 strlcpy(entry_cpy, entry, RTE_DIM(entry_cpy));
238
239
240
241
242
243 nb_tokens = rte_strsplit(entry_cpy, strlen(entry_cpy),
244 tokens, max_elems + 1, ' ');
245
246
247 if (nb_tokens > max_elems)
248 return -2;
249
250 for (i = 0; i < nb_tokens; ++i) {
251 if (strchr(tokens[i], '-') != NULL) {
252
253
254
255
256
257 nb_rng_tokens = rte_strsplit(tokens[i],
258 strlen(tokens[i]), rng_tokens,
259 RTE_DIM(rng_tokens), '-');
260 if (nb_rng_tokens != 2)
261 return -3;
262
263
264 if (get_val_securely(rng_tokens[0], &token_val) < 0)
265 return -4;
266 beg = (char)token_val;
267 if (get_val_securely(rng_tokens[1], &token_val) < 0)
268 return -4;
269 end = (char)token_val;
270 if (beg < 0 || beg > UCHAR_MAX ||
271 end < 0 || end > UCHAR_MAX || end < beg)
272 return -4;
273
274 for (val = beg; val <= end; ++val) {
275 if (val > max_val)
276 return -5;
277
278 *tab = val;
279 tab = RTE_PTR_ADD(tab, elem_sz);
280 ++values;
281 if (values >= max_elems)
282 return -2;
283 }
284 } else {
285
286 if (get_val_securely(tokens[i], &token_val) < 0)
287 return -5;
288 val = (char)token_val;
289 if (val > max_val)
290 return -5;
291
292 *tab = val;
293 tab = RTE_PTR_ADD(tab, elem_sz);
294 ++values;
295 if (values >= max_elems)
296 return -2;
297 }
298 }
299
300 return values;
301}
302
303
304
305
306
307
308
309
310
311
312static int
313parse_tc_cfg(struct rte_cfgfile *file, int port, int tc,
314 struct mrvl_cfg *cfg)
315{
316 char sec_name[32];
317 const char *entry;
318 int n;
319
320 snprintf(sec_name, sizeof(sec_name), "%s %d %s %d",
321 MRVL_TOK_PORT, port, MRVL_TOK_TC, tc);
322
323
324 if (rte_cfgfile_num_sections(file, sec_name, strlen(sec_name)) <= 0)
325 return 0;
326
327 cfg->port[port].use_qos_global_defaults = 0;
328 entry = rte_cfgfile_get_entry(file, sec_name, MRVL_TOK_RXQ);
329 if (entry) {
330 n = get_entry_values(entry,
331 cfg->port[port].tc[tc].inq,
332 sizeof(cfg->port[port].tc[tc].inq[0]),
333 RTE_DIM(cfg->port[port].tc[tc].inq),
334 MRVL_PP2_RXQ_MAX);
335 if (n < 0) {
336 MRVL_LOG(ERR, "Error %d while parsing: %s",
337 n, entry);
338 return n;
339 }
340 cfg->port[port].tc[tc].inqs = n;
341 }
342
343 entry = rte_cfgfile_get_entry(file, sec_name, MRVL_TOK_PCP);
344 if (entry) {
345 n = get_entry_values(entry,
346 cfg->port[port].tc[tc].pcp,
347 sizeof(cfg->port[port].tc[tc].pcp[0]),
348 RTE_DIM(cfg->port[port].tc[tc].pcp),
349 MAX_PCP);
350 if (n < 0) {
351 MRVL_LOG(ERR, "Error %d while parsing: %s",
352 n, entry);
353 return n;
354 }
355 cfg->port[port].tc[tc].pcps = n;
356 }
357
358 entry = rte_cfgfile_get_entry(file, sec_name, MRVL_TOK_DSCP);
359 if (entry) {
360 n = get_entry_values(entry,
361 cfg->port[port].tc[tc].dscp,
362 sizeof(cfg->port[port].tc[tc].dscp[0]),
363 RTE_DIM(cfg->port[port].tc[tc].dscp),
364 MAX_DSCP);
365 if (n < 0) {
366 MRVL_LOG(ERR, "Error %d while parsing: %s",
367 n, entry);
368 return n;
369 }
370 cfg->port[port].tc[tc].dscps = n;
371 }
372
373 if (!cfg->port[port].setup_policer)
374 return 0;
375
376 entry = rte_cfgfile_get_entry(file, sec_name,
377 MRVL_TOK_PLCR_DEFAULT_COLOR);
378 if (entry) {
379 if (!strncmp(entry, MRVL_TOK_PLCR_DEFAULT_COLOR_GREEN,
380 sizeof(MRVL_TOK_PLCR_DEFAULT_COLOR_GREEN))) {
381 cfg->port[port].tc[tc].color = PP2_PPIO_COLOR_GREEN;
382 } else if (!strncmp(entry, MRVL_TOK_PLCR_DEFAULT_COLOR_YELLOW,
383 sizeof(MRVL_TOK_PLCR_DEFAULT_COLOR_YELLOW))) {
384 cfg->port[port].tc[tc].color = PP2_PPIO_COLOR_YELLOW;
385 } else if (!strncmp(entry, MRVL_TOK_PLCR_DEFAULT_COLOR_RED,
386 sizeof(MRVL_TOK_PLCR_DEFAULT_COLOR_RED))) {
387 cfg->port[port].tc[tc].color = PP2_PPIO_COLOR_RED;
388 } else {
389 MRVL_LOG(ERR, "Error while parsing: %s", entry);
390 return -1;
391 }
392 }
393
394 return 0;
395}
396
397
398
399
400
401
402
403
404
405
406static int
407parse_policer(struct rte_cfgfile *file, int port, const char *sec_name,
408 struct mrvl_cfg *cfg)
409{
410 const char *entry;
411 uint32_t val;
412
413
414 entry = rte_cfgfile_get_entry(file, sec_name, MRVL_TOK_PLCR_UNIT);
415 if (entry) {
416 if (!strncmp(entry, MRVL_TOK_PLCR_UNIT_BYTES,
417 sizeof(MRVL_TOK_PLCR_UNIT_BYTES))) {
418 cfg->port[port].policer_params.token_unit =
419 PP2_CLS_PLCR_BYTES_TOKEN_UNIT;
420 } else if (!strncmp(entry, MRVL_TOK_PLCR_UNIT_PACKETS,
421 sizeof(MRVL_TOK_PLCR_UNIT_PACKETS))) {
422 cfg->port[port].policer_params.token_unit =
423 PP2_CLS_PLCR_PACKETS_TOKEN_UNIT;
424 } else {
425 MRVL_LOG(ERR, "Unknown token: %s", entry);
426 return -1;
427 }
428 }
429
430
431 entry = rte_cfgfile_get_entry(file, sec_name, MRVL_TOK_PLCR_COLOR);
432 if (entry) {
433 if (!strncmp(entry, MRVL_TOK_PLCR_COLOR_BLIND,
434 sizeof(MRVL_TOK_PLCR_COLOR_BLIND))) {
435 cfg->port[port].policer_params.color_mode =
436 PP2_CLS_PLCR_COLOR_BLIND_MODE;
437 } else if (!strncmp(entry, MRVL_TOK_PLCR_COLOR_AWARE,
438 sizeof(MRVL_TOK_PLCR_COLOR_AWARE))) {
439 cfg->port[port].policer_params.color_mode =
440 PP2_CLS_PLCR_COLOR_AWARE_MODE;
441 } else {
442 MRVL_LOG(ERR, "Error in parsing: %s", entry);
443 return -1;
444 }
445 }
446
447
448 entry = rte_cfgfile_get_entry(file, sec_name, MRVL_TOK_PLCR_CIR);
449 if (entry) {
450 if (get_val_securely(entry, &val) < 0)
451 return -1;
452 cfg->port[port].policer_params.cir = val;
453 }
454
455
456 entry = rte_cfgfile_get_entry(file, sec_name, MRVL_TOK_PLCR_CBS);
457 if (entry) {
458 if (get_val_securely(entry, &val) < 0)
459 return -1;
460 cfg->port[port].policer_params.cbs = val;
461 }
462
463
464 entry = rte_cfgfile_get_entry(file, sec_name, MRVL_TOK_PLCR_EBS);
465 if (entry) {
466 if (get_val_securely(entry, &val) < 0)
467 return -1;
468 cfg->port[port].policer_params.ebs = val;
469 }
470
471 cfg->port[port].setup_policer = 1;
472
473 return 0;
474}
475
476
477
478
479
480
481
482
483
484
485static int
486parse_udf(struct rte_cfgfile *file, const char *sec_name, int udf,
487 struct mrvl_cfg *cfg)
488{
489 struct pp2_parse_udf_params *udf_params;
490 const char *entry, *entry_field;
491 uint32_t val, i;
492 uint8_t field_size;
493 char malloc_name[32], tmp_arr[3];
494
495#define FIELD_LEN_IN_CHARS(field_size) (uint32_t)(2 + (field_size) * 2)
496
497 udf_params = &cfg->pp2_cfg.prs_udfs.udfs[udf];
498
499
500 entry = rte_cfgfile_get_entry(file, sec_name,
501 MRVL_TOK_PARSER_UDF_PROTO);
502 if (!entry) {
503 MRVL_LOG(ERR, "UDF[%d]: '%s' field must be set\n", udf,
504 MRVL_TOK_PARSER_UDF_PROTO);
505 return -1;
506 }
507
508
509 entry_field = rte_cfgfile_get_entry(file, sec_name,
510 MRVL_TOK_PARSER_UDF_FIELD);
511 if (!entry_field) {
512 MRVL_LOG(ERR, "UDF[%d]: '%s' field must be set\n", udf,
513 MRVL_TOK_PARSER_UDF_FIELD);
514 return -1;
515 }
516
517 if (!strncmp(entry, MRVL_TOK_PARSER_UDF_PROTO_ETH,
518 sizeof(MRVL_TOK_PARSER_UDF_PROTO_ETH))) {
519 udf_params->match_proto = MV_NET_PROTO_ETH;
520 if (!strncmp(entry_field, MRVL_TOK_PARSER_UDF_FIELD_ETH_TYPE,
521 sizeof(MRVL_TOK_PARSER_UDF_FIELD_ETH_TYPE))) {
522 udf_params->match_field.eth = MV_NET_ETH_F_TYPE;
523 field_size = 2;
524 } else {
525 MRVL_LOG(ERR, "UDF[%d]: mismatch between '%s' proto "
526 "and '%s' field\n", udf,
527 MRVL_TOK_PARSER_UDF_PROTO_ETH,
528 entry_field);
529 return -1;
530 }
531 } else if (!strncmp(entry, MRVL_TOK_PARSER_UDF_PROTO_UDP,
532 sizeof(MRVL_TOK_PARSER_UDF_PROTO_UDP))) {
533 udf_params->match_proto = MV_NET_PROTO_UDP;
534 if (!strncmp(entry_field, MRVL_TOK_PARSER_UDF_FIELD_UDP_DPORT,
535 sizeof(MRVL_TOK_PARSER_UDF_FIELD_UDP_DPORT))) {
536 udf_params->match_field.udp = MV_NET_UDP_F_DP;
537 field_size = 2;
538 } else {
539 MRVL_LOG(ERR, "UDF[%d]: mismatch between '%s' proto "
540 "and '%s' field\n", udf,
541 MRVL_TOK_PARSER_UDF_PROTO_UDP,
542 entry_field);
543 return -1;
544 }
545 } else {
546 MRVL_LOG(ERR, "UDF[%d]: Unsupported '%s' proto\n", udf, entry);
547 return -1;
548 }
549
550 snprintf(malloc_name, sizeof(malloc_name), "mrvl_udf_%d_key", udf);
551 udf_params->match_key = rte_zmalloc(malloc_name, field_size, 0);
552 if (udf_params->match_key == NULL) {
553 MRVL_LOG(ERR, "Cannot allocate udf %d key\n", udf);
554 return -1;
555 }
556 snprintf(malloc_name, sizeof(malloc_name), "mrvl_udf_%d_mask", udf);
557 udf_params->match_mask = rte_zmalloc(malloc_name, field_size, 0);
558 if (udf_params->match_mask == NULL) {
559 MRVL_LOG(ERR, "Cannot allocate udf %d mask\n", udf);
560 return -1;
561 }
562
563
564 entry = rte_cfgfile_get_entry(file, sec_name, MRVL_TOK_PARSER_UDF_KEY);
565 if (!entry) {
566 MRVL_LOG(ERR, "UDF[%d]: '%s' field must be set\n", udf,
567 MRVL_TOK_PARSER_UDF_KEY);
568 return -1;
569 }
570
571 if (strncmp(entry, "0x", 2) != 0) {
572 MRVL_LOG(ERR, "UDF[%d]: '%s' field must start with '0x'\n",
573 udf, MRVL_TOK_PARSER_UDF_KEY);
574 return -EINVAL;
575 }
576
577 if (strlen(entry) != FIELD_LEN_IN_CHARS(field_size)) {
578 MRVL_LOG(ERR, "UDF[%d]: '%s' field's len must be %d\n", udf,
579 MRVL_TOK_PARSER_UDF_KEY,
580 FIELD_LEN_IN_CHARS(field_size));
581 return -EINVAL;
582 }
583
584 entry += 2;
585 for (i = 0; i < field_size; i++) {
586 strncpy(tmp_arr, entry, 2);
587 tmp_arr[2] = '\0';
588 if (get_val_securely8(tmp_arr, 16,
589 &udf_params->match_key[i]) < 0) {
590 MRVL_LOG(ERR, "UDF[%d]: '%s' field's value is not in "
591 "hex format\n", udf, MRVL_TOK_PARSER_UDF_KEY);
592 return -EINVAL;
593 }
594 entry += 2;
595 }
596
597
598 entry = rte_cfgfile_get_entry(file, sec_name, MRVL_TOK_PARSER_UDF_MASK);
599 if (!entry) {
600 MRVL_LOG(ERR, "UDF[%d]: '%s' field must be set\n", udf,
601 MRVL_TOK_PARSER_UDF_MASK);
602 return -1;
603 }
604 if (strncmp(entry, "0x", 2) != 0) {
605 MRVL_LOG(ERR, "UDF[%d]: '%s' field must start with '0x'\n",
606 udf, MRVL_TOK_PARSER_UDF_MASK);
607 return -EINVAL;
608 }
609
610 if (strlen(entry) != FIELD_LEN_IN_CHARS(field_size)) {
611 MRVL_LOG(ERR, "UDF[%d]: '%s' field's len must be %d\n", udf,
612 MRVL_TOK_PARSER_UDF_MASK,
613 FIELD_LEN_IN_CHARS(field_size));
614 return -EINVAL;
615 }
616
617 entry += 2;
618 for (i = 0; i < field_size; i++) {
619 strncpy(tmp_arr, entry, 2);
620 tmp_arr[2] = '\0';
621 if (get_val_securely8(tmp_arr, 16,
622 &udf_params->match_mask[i]) < 0) {
623 MRVL_LOG(ERR, "UDF[%d]: '%s' field's value is not in "
624 "hex format\n", udf, MRVL_TOK_PARSER_UDF_MASK);
625 return -EINVAL;
626 }
627 entry += 2;
628 }
629
630
631 entry = rte_cfgfile_get_entry(file, sec_name,
632 MRVL_TOK_PARSER_UDF_OFFSET);
633 if (!entry) {
634 MRVL_LOG(ERR, "UDF[%d]: '%s' field must be set\n", udf,
635 MRVL_TOK_PARSER_UDF_OFFSET);
636 return -1;
637 }
638 if (get_val_securely(entry, &val) < 0)
639 return -1;
640 udf_params->offset = val;
641
642 return 0;
643}
644
645
646
647
648
649
650
651
652
653
654
655int
656mrvl_get_cfg(const char *key __rte_unused, const char *path, void *extra_args)
657{
658 struct mrvl_cfg **cfg = extra_args;
659 struct rte_cfgfile *file = rte_cfgfile_load(path, 0);
660 uint32_t val;
661 int n, i, ret;
662 const char *entry;
663 char sec_name[32];
664
665 if (file == NULL) {
666 MRVL_LOG(ERR, "Cannot load configuration %s\n", path);
667 return -1;
668 }
669
670
671
672
673 *cfg = rte_zmalloc("mrvl_cfg", sizeof(struct mrvl_cfg), 0);
674 if (*cfg == NULL) {
675 MRVL_LOG(ERR, "Cannot allocate configuration %s\n", path);
676 return -1;
677 }
678
679
680 n = rte_cfgfile_num_sections(file, MRVL_TOK_PARSER_UDF,
681 sizeof(MRVL_TOK_PARSER_UDF) - 1);
682
683 if (n && n > PP2_MAX_UDFS_SUPPORTED) {
684 MRVL_LOG(ERR, "found %d udf sections, but only %d are supported\n",
685 n, PP2_MAX_UDFS_SUPPORTED);
686 return -1;
687 }
688 (*cfg)->pp2_cfg.prs_udfs.num_udfs = n;
689 for (i = 0; i < n; i++) {
690 snprintf(sec_name, sizeof(sec_name), "%s %d",
691 MRVL_TOK_PARSER_UDF, i);
692
693
694 if (rte_cfgfile_num_sections(file, sec_name,
695 strlen(sec_name)) <= 0) {
696 MRVL_LOG(ERR, "udf sections must be sequential (0 - %d)\n",
697 PP2_MAX_UDFS_SUPPORTED - 1);
698 return -1;
699 }
700
701 ret = parse_udf(file, sec_name, i, *cfg);
702 if (ret) {
703 MRVL_LOG(ERR, "Error in parsing %s!\n", sec_name);
704 return -1;
705 }
706 }
707
708
709 n = rte_cfgfile_num_sections(file, MRVL_TOK_PORT,
710 sizeof(MRVL_TOK_PORT) - 1);
711
712 if (n == 0) {
713
714 MRVL_LOG(WARNING, "Empty configuration file?");
715 return 0;
716 }
717
718
719 for (n = 0; n < (PP2_NUM_ETH_PPIO * PP2_NUM_PKT_PROC); ++n) {
720 snprintf(sec_name, sizeof(sec_name), "%s %d %s",
721 MRVL_TOK_PORT, n, MRVL_TOK_DEFAULT);
722
723
724 (*cfg)->port[n].use_qos_global_defaults = 1;
725
726
727
728
729 (*cfg)->port[n].fill_bpool_buffs = MRVL_BURST_SIZE;
730
731
732 if (rte_cfgfile_num_sections(file, sec_name,
733 strlen(sec_name)) <= 0) {
734 continue;
735 }
736
737
738
739
740
741 entry = rte_cfgfile_get_entry(file, sec_name,
742 MRVL_TOK_START_HDR);
743
744 if (entry == NULL)
745 entry = rte_cfgfile_get_entry(file, sec_name,
746 MRVL_TOK_DSA_MODE);
747 if (entry) {
748 if (!strncmp(entry, MRVL_TOK_START_HDR_NONE,
749 sizeof(MRVL_TOK_START_HDR_NONE)))
750 (*cfg)->port[n].eth_start_hdr =
751 PP2_PPIO_HDR_ETH;
752 else if (!strncmp(entry, MRVL_TOK_START_HDR_DSA,
753 sizeof(MRVL_TOK_START_HDR_DSA)))
754 (*cfg)->port[n].eth_start_hdr =
755 PP2_PPIO_HDR_ETH_DSA;
756 else if (!strncmp(entry, MRVL_TOK_START_HDR_CUSTOM,
757 sizeof(MRVL_TOK_START_HDR_CUSTOM)))
758 (*cfg)->port[n].eth_start_hdr =
759 PP2_PPIO_HDR_ETH_CUSTOM;
760 else if (!strncmp(entry, MRVL_TOK_START_HDR_EXT_DSA,
761 sizeof(MRVL_TOK_START_HDR_EXT_DSA))) {
762 (*cfg)->port[n].eth_start_hdr =
763 PP2_PPIO_HDR_ETH_EXT_DSA;
764 } else {
765 MRVL_LOG(ERR,
766 "Error in parsing %s value (%s)!\n",
767 MRVL_TOK_START_HDR, entry);
768 return -1;
769 }
770 } else {
771 (*cfg)->port[n].eth_start_hdr = PP2_PPIO_HDR_ETH;
772 }
773
774
775
776
777
778 entry = rte_cfgfile_get_entry(file, sec_name,
779 MRVL_TOK_RATE_LIMIT_ENABLE);
780 if (entry) {
781 if (get_val_securely(entry, &val) < 0)
782 return -1;
783 (*cfg)->port[n].rate_limit_enable = val;
784 }
785
786 if ((*cfg)->port[n].rate_limit_enable) {
787 entry = rte_cfgfile_get_entry(file, sec_name,
788 MRVL_TOK_BURST_SIZE);
789 if (entry) {
790 if (get_val_securely(entry, &val) < 0)
791 return -1;
792 (*cfg)->port[n].rate_limit_params.cbs = val;
793 }
794
795 entry = rte_cfgfile_get_entry(file, sec_name,
796 MRVL_TOK_RATE_LIMIT);
797 if (entry) {
798 if (get_val_securely(entry, &val) < 0)
799 return -1;
800 (*cfg)->port[n].rate_limit_params.cir = val;
801 }
802 }
803
804 entry = rte_cfgfile_get_entry(file, sec_name,
805 MRVL_TOK_MAPPING_PRIORITY);
806 if (entry) {
807 (*cfg)->port[n].use_qos_global_defaults = 0;
808 if (!strncmp(entry, MRVL_TOK_VLAN_IP,
809 sizeof(MRVL_TOK_VLAN_IP)))
810 (*cfg)->port[n].mapping_priority =
811 PP2_CLS_QOS_TBL_VLAN_IP_PRI;
812 else if (!strncmp(entry, MRVL_TOK_IP_VLAN,
813 sizeof(MRVL_TOK_IP_VLAN)))
814 (*cfg)->port[n].mapping_priority =
815 PP2_CLS_QOS_TBL_IP_VLAN_PRI;
816 else if (!strncmp(entry, MRVL_TOK_IP,
817 sizeof(MRVL_TOK_IP)))
818 (*cfg)->port[n].mapping_priority =
819 PP2_CLS_QOS_TBL_IP_PRI;
820 else if (!strncmp(entry, MRVL_TOK_VLAN,
821 sizeof(MRVL_TOK_VLAN))) {
822 (*cfg)->port[n].mapping_priority =
823 PP2_CLS_QOS_TBL_VLAN_PRI;
824 } else {
825 MRVL_LOG(ERR,
826 "Error in parsing %s value (%s)!\n",
827 MRVL_TOK_MAPPING_PRIORITY, entry);
828 return -1;
829 }
830 } else {
831 (*cfg)->port[n].mapping_priority =
832 PP2_CLS_QOS_TBL_NONE;
833 }
834
835
836 entry = rte_cfgfile_get_entry(file, sec_name,
837 MRVL_TOK_PLCR_DEFAULT);
838 if (entry) {
839 (*cfg)->port[n].use_qos_global_defaults = 0;
840 if (get_val_securely(entry, &val) < 0)
841 return -1;
842
843 snprintf(sec_name, sizeof(sec_name), "%s %d",
844 MRVL_TOK_PLCR, val);
845 ret = parse_policer(file, n, sec_name, *cfg);
846 if (ret)
847 return -1;
848 }
849
850 for (i = 0; i < MRVL_PP2_RXQ_MAX; ++i) {
851 ret = get_outq_cfg(file, n, i, *cfg);
852 if (ret < 0) {
853 MRVL_LOG(ERR,
854 "Error %d parsing port %d outq %d!\n",
855 ret, n, i);
856 return -1;
857 }
858 }
859
860 for (i = 0; i < MRVL_PP2_TC_MAX; ++i) {
861 ret = parse_tc_cfg(file, n, i, *cfg);
862 if (ret < 0) {
863 MRVL_LOG(ERR,
864 "Error %d parsing port %d tc %d!\n",
865 ret, n, i);
866 return -1;
867 }
868 }
869
870 entry = rte_cfgfile_get_entry(file, sec_name,
871 MRVL_TOK_DEFAULT_TC);
872 if (entry) {
873 if (get_val_securely(entry, &val) < 0 ||
874 val > USHRT_MAX)
875 return -1;
876 (*cfg)->port[n].default_tc = (uint8_t)val;
877 } else {
878 if ((*cfg)->port[n].use_qos_global_defaults == 0) {
879 MRVL_LOG(ERR,
880 "Default Traffic Class required in "
881 "custom configuration!");
882 return -1;
883 }
884 }
885
886
887 entry = rte_cfgfile_get_entry(file, sec_name,
888 MRVL_TOK_FWD_BAD_FRAMES);
889 if (entry) {
890 if (get_val_securely(entry, &val) < 0) {
891 MRVL_LOG(ERR,
892 "Error in parsing %s value (%s)!\n",
893 MRVL_TOK_FWD_BAD_FRAMES, entry);
894 return -1;
895 }
896 (*cfg)->port[n].forward_bad_frames = (uint8_t)val;
897 } else {
898 (*cfg)->port[n].forward_bad_frames = 0;
899 }
900
901
902 entry = rte_cfgfile_get_entry(file, sec_name,
903 MRVL_TOK_FILL_BPOOL_BUFFS);
904 if (entry) {
905 if (get_val_securely(entry, &val) < 0) {
906 MRVL_LOG(ERR,
907 "Error in parsing %s value (%s)!\n",
908 MRVL_TOK_FILL_BPOOL_BUFFS, entry);
909 return -1;
910 }
911 (*cfg)->port[n].fill_bpool_buffs = val;
912 }
913 }
914
915 return 0;
916}
917
918
919
920
921
922
923
924
925
926
927
928static int
929setup_tc(struct pp2_ppio_tc_params *param, uint8_t inqs,
930 struct pp2_bpool *bpool, enum pp2_ppio_color color)
931{
932 struct pp2_ppio_inq_params *inq_params;
933
934 param->pkt_offset = MRVL_PKT_OFFS;
935 param->pools[0][0] = bpool;
936 param->pools[0][1] = dummy_pool[bpool->pp2_id];
937 param->default_color = color;
938
939 inq_params = rte_zmalloc_socket("inq_params",
940 inqs * sizeof(*inq_params),
941 0, rte_socket_id());
942 if (!inq_params)
943 return -ENOMEM;
944
945 param->num_in_qs = inqs;
946
947
948 if (param->inqs_params)
949 rte_free(param->inqs_params);
950
951 param->inqs_params = inq_params;
952
953 return 0;
954}
955
956
957
958
959
960
961
962
963
964static int
965setup_policer(struct mrvl_priv *priv, struct pp2_cls_plcr_params *params)
966{
967 char match[16];
968 int ret;
969
970
971
972
973
974
975
976 sprintf(match, "policer-%d:%d\n", priv->pp_id, 0);
977 params->match = match;
978
979 ret = pp2_cls_plcr_init(params, &priv->default_policer);
980 if (ret) {
981 MRVL_LOG(ERR, "Failed to setup %s", match);
982 return -1;
983 }
984
985 priv->ppio_params.inqs_params.plcr = priv->default_policer;
986 priv->used_plcrs = BIT(0);
987
988 return 0;
989}
990
991
992
993
994
995
996
997
998
999
1000
1001int
1002mrvl_configure_rxqs(struct mrvl_priv *priv, uint16_t portid,
1003 uint16_t max_queues)
1004{
1005 size_t i, tc;
1006
1007 if (mrvl_cfg == NULL ||
1008 mrvl_cfg->port[portid].use_qos_global_defaults) {
1009
1010
1011
1012
1013 priv->ppio_params.inqs_params.num_tcs = 1;
1014 setup_tc(&priv->ppio_params.inqs_params.tcs_params[0],
1015 max_queues, priv->bpool, PP2_PPIO_COLOR_GREEN);
1016
1017
1018 for (i = 0; i < max_queues; ++i) {
1019 priv->rxq_map[i].tc = 0;
1020 priv->rxq_map[i].inq = i;
1021 }
1022 return 0;
1023 }
1024
1025
1026 struct port_cfg *port_cfg = &mrvl_cfg->port[portid];
1027
1028 priv->qos_tbl_params.type = port_cfg->mapping_priority;
1029
1030
1031
1032
1033
1034
1035 for (i = 0; i < RTE_DIM(priv->qos_tbl_params.pcp_cos_map); ++i)
1036 priv->qos_tbl_params.pcp_cos_map[i].tc = port_cfg->default_tc;
1037
1038
1039 for (tc = 0; tc < RTE_DIM(port_cfg->tc); ++tc) {
1040 if (port_cfg->tc[tc].pcps > RTE_DIM(port_cfg->tc[0].pcp)) {
1041
1042 MRVL_LOG(ERR,
1043 "Too many PCPs configured in TC %zu!", tc);
1044 return -1;
1045 }
1046 for (i = 0; i < port_cfg->tc[tc].pcps; ++i) {
1047 priv->qos_tbl_params.pcp_cos_map[
1048 port_cfg->tc[tc].pcp[i]].tc = tc;
1049 }
1050 }
1051
1052
1053
1054
1055
1056 for (i = 0; i < RTE_DIM(priv->qos_tbl_params.dscp_cos_map); ++i)
1057 priv->qos_tbl_params.dscp_cos_map[i].tc =
1058 port_cfg->default_tc;
1059
1060
1061 for (tc = 0; tc < RTE_DIM(port_cfg->tc); ++tc) {
1062 if (port_cfg->tc[tc].dscps > RTE_DIM(port_cfg->tc[0].dscp)) {
1063
1064 MRVL_LOG(ERR,
1065 "Too many DSCPs configured in TC %zu!", tc);
1066 return -1;
1067 }
1068 for (i = 0; i < port_cfg->tc[tc].dscps; ++i) {
1069 priv->qos_tbl_params.dscp_cos_map[
1070 port_cfg->tc[tc].dscp[i]].tc = tc;
1071 }
1072 }
1073
1074
1075
1076
1077
1078
1079 for (i = 0; i < RTE_DIM(priv->rxq_map); ++i)
1080 priv->rxq_map[i].tc = MRVL_UNKNOWN_TC;
1081
1082
1083 for (tc = 0; tc < RTE_DIM(port_cfg->tc); ++tc) {
1084 if (port_cfg->tc[tc].inqs > RTE_DIM(port_cfg->tc[0].inq)) {
1085
1086 MRVL_LOG(ERR,
1087 "Too many RX queues configured per TC %zu!",
1088 tc);
1089 return -1;
1090 }
1091 for (i = 0; i < port_cfg->tc[tc].inqs; ++i) {
1092 uint8_t idx = port_cfg->tc[tc].inq[i];
1093
1094 if (idx > RTE_DIM(priv->rxq_map)) {
1095 MRVL_LOG(ERR, "Bad queue index %d!", idx);
1096 return -1;
1097 }
1098
1099 priv->rxq_map[idx].tc = tc;
1100 priv->rxq_map[idx].inq = i;
1101 }
1102 }
1103
1104
1105
1106
1107
1108 for (i = 0; i < MRVL_PP2_TC_MAX; ++i) {
1109 if (port_cfg->tc[i].inqs == 0)
1110 break;
1111 setup_tc(&priv->ppio_params.inqs_params.tcs_params[i],
1112 port_cfg->tc[i].inqs,
1113 priv->bpool, port_cfg->tc[i].color);
1114 }
1115
1116 priv->ppio_params.inqs_params.num_tcs = i;
1117
1118 if (port_cfg->setup_policer)
1119 return setup_policer(priv, &port_cfg->policer_params);
1120
1121 return 0;
1122}
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134int
1135mrvl_configure_txqs(struct mrvl_priv *priv, uint16_t portid,
1136 uint16_t max_queues)
1137{
1138
1139 struct port_cfg *port_cfg = &mrvl_cfg->port[portid];
1140 int i;
1141
1142 if (mrvl_cfg == NULL)
1143 return 0;
1144
1145 priv->ppio_params.rate_limit_enable = port_cfg->rate_limit_enable;
1146 if (port_cfg->rate_limit_enable)
1147 priv->ppio_params.rate_limit_params =
1148 port_cfg->rate_limit_params;
1149
1150 for (i = 0; i < max_queues; i++) {
1151 struct pp2_ppio_outq_params *params =
1152 &priv->ppio_params.outqs_params.outqs_params[i];
1153
1154 params->sched_mode = port_cfg->outq[i].sched_mode;
1155 params->weight = port_cfg->outq[i].weight;
1156 params->rate_limit_enable = port_cfg->outq[i].rate_limit_enable;
1157 params->rate_limit_params = port_cfg->outq[i].rate_limit_params;
1158 }
1159
1160 return 0;
1161}
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172int
1173mrvl_start_qos_mapping(struct mrvl_priv *priv)
1174{
1175 size_t i;
1176
1177 if (priv->qos_tbl_params.type == PP2_CLS_QOS_TBL_NONE)
1178 return 0;
1179
1180 if (priv->ppio == NULL) {
1181 MRVL_LOG(ERR, "ppio must not be NULL here!");
1182 return -1;
1183 }
1184
1185 for (i = 0; i < RTE_DIM(priv->qos_tbl_params.pcp_cos_map); ++i)
1186 priv->qos_tbl_params.pcp_cos_map[i].ppio = priv->ppio;
1187
1188 for (i = 0; i < RTE_DIM(priv->qos_tbl_params.dscp_cos_map); ++i)
1189 priv->qos_tbl_params.dscp_cos_map[i].ppio = priv->ppio;
1190
1191
1192
1193 return pp2_cls_qos_tbl_init(&priv->qos_tbl_params, &priv->qos_tbl);
1194}
1195