1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2018 Intel Corporation 3 */ 4 5 #include <stdio.h> 6 #include <stdint.h> 7 #include <stdlib.h> 8 #include <string.h> 9 10 #include <rte_common.h> 11 #include <rte_cycles.h> 12 #include <rte_string_fns.h> 13 #include <rte_cryptodev.h> 14 15 #include "rte_eth_softnic_internals.h" 16 #include "parser.h" 17 18 #ifndef CMD_MAX_TOKENS 19 #define CMD_MAX_TOKENS 256 20 #endif 21 22 #define MSG_OUT_OF_MEMORY "Not enough memory.\n" 23 #define MSG_CMD_UNKNOWN "Unknown command \"%s\".\n" 24 #define MSG_CMD_UNIMPLEM "Command \"%s\" not implemented.\n" 25 #define MSG_ARG_NOT_ENOUGH "Not enough arguments for command \"%s\".\n" 26 #define MSG_ARG_TOO_MANY "Too many arguments for command \"%s\".\n" 27 #define MSG_ARG_MISMATCH "Wrong number of arguments for command \"%s\".\n" 28 #define MSG_ARG_NOT_FOUND "Argument \"%s\" not found.\n" 29 #define MSG_ARG_INVALID "Invalid value for argument \"%s\".\n" 30 #define MSG_FILE_ERR "Error in file \"%s\" at line %u.\n" 31 #define MSG_FILE_NOT_ENOUGH "Not enough rules in file \"%s\".\n" 32 #define MSG_CMD_FAIL "Command \"%s\" failed.\n" 33 34 static int 35 is_comment(char *in) 36 { 37 if ((strlen(in) && index("!#%;", in[0])) || 38 (strncmp(in, "//", 2) == 0) || 39 (strncmp(in, "--", 2) == 0)) 40 return 1; 41 42 return 0; 43 } 44 45 /** 46 * mempool <mempool_name> 47 * buffer <buffer_size> 48 * pool <pool_size> 49 * cache <cache_size> 50 */ 51 static void 52 cmd_mempool(struct pmd_internals *softnic, 53 char **tokens, 54 uint32_t n_tokens, 55 char *out, 56 size_t out_size) 57 { 58 struct softnic_mempool_params p; 59 char *name; 60 struct softnic_mempool *mempool; 61 62 if (n_tokens != 8) { 63 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 64 return; 65 } 66 67 name = tokens[1]; 68 69 if (strcmp(tokens[2], "buffer") != 0) { 70 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "buffer"); 71 return; 72 } 73 74 if (softnic_parser_read_uint32(&p.buffer_size, tokens[3]) != 0) { 75 snprintf(out, out_size, MSG_ARG_INVALID, "buffer_size"); 76 return; 77 } 78 79 if (strcmp(tokens[4], "pool") != 0) { 80 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pool"); 81 return; 82 } 83 84 if (softnic_parser_read_uint32(&p.pool_size, tokens[5]) != 0) { 85 snprintf(out, out_size, MSG_ARG_INVALID, "pool_size"); 86 return; 87 } 88 89 if (strcmp(tokens[6], "cache") != 0) { 90 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cache"); 91 return; 92 } 93 94 if (softnic_parser_read_uint32(&p.cache_size, tokens[7]) != 0) { 95 snprintf(out, out_size, MSG_ARG_INVALID, "cache_size"); 96 return; 97 } 98 99 mempool = softnic_mempool_create(softnic, name, &p); 100 if (mempool == NULL) { 101 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 102 return; 103 } 104 } 105 106 /** 107 * link <link_name> 108 * dev <device_name> | port <port_id> 109 */ 110 static void 111 cmd_link(struct pmd_internals *softnic, 112 char **tokens, 113 uint32_t n_tokens, 114 char *out, 115 size_t out_size) 116 { 117 struct softnic_link_params p; 118 struct softnic_link *link; 119 char *name; 120 121 memset(&p, 0, sizeof(p)); 122 123 if (n_tokens != 4) { 124 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 125 return; 126 } 127 name = tokens[1]; 128 129 if (strcmp(tokens[2], "dev") == 0) { 130 p.dev_name = tokens[3]; 131 } else if (strcmp(tokens[2], "port") == 0) { 132 p.dev_name = NULL; 133 134 if (softnic_parser_read_uint16(&p.port_id, tokens[3]) != 0) { 135 snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); 136 return; 137 } 138 } else { 139 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "dev or port"); 140 return; 141 } 142 143 link = softnic_link_create(softnic, name, &p); 144 if (link == NULL) { 145 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 146 return; 147 } 148 } 149 150 /** 151 * swq <swq_name> 152 * size <size> 153 */ 154 static void 155 cmd_swq(struct pmd_internals *softnic, 156 char **tokens, 157 uint32_t n_tokens, 158 char *out, 159 size_t out_size) 160 { 161 struct softnic_swq_params p; 162 char *name; 163 struct softnic_swq *swq; 164 165 if (n_tokens != 4) { 166 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 167 return; 168 } 169 170 name = tokens[1]; 171 172 if (strcmp(tokens[2], "size") != 0) { 173 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size"); 174 return; 175 } 176 177 if (softnic_parser_read_uint32(&p.size, tokens[3]) != 0) { 178 snprintf(out, out_size, MSG_ARG_INVALID, "size"); 179 return; 180 } 181 182 swq = softnic_swq_create(softnic, name, &p); 183 if (swq == NULL) { 184 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 185 return; 186 } 187 } 188 189 /** 190 * tmgr shaper profile 191 * id <profile_id> 192 * rate <tb_rate> size <tb_size> 193 * adj <packet_length_adjust> 194 */ 195 static void 196 cmd_tmgr_shaper_profile(struct pmd_internals *softnic, 197 char **tokens, 198 uint32_t n_tokens, 199 char *out, 200 size_t out_size) 201 { 202 struct rte_tm_shaper_params sp; 203 struct rte_tm_error error; 204 uint32_t shaper_profile_id; 205 uint16_t port_id; 206 int status; 207 208 memset(&sp, 0, sizeof(struct rte_tm_shaper_params)); 209 210 if (n_tokens != 11) { 211 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 212 return; 213 } 214 215 if (strcmp(tokens[1], "shaper") != 0) { 216 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "shaper"); 217 return; 218 } 219 220 if (strcmp(tokens[2], "profile") != 0) { 221 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile"); 222 return; 223 } 224 225 if (strcmp(tokens[3], "id") != 0) { 226 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "id"); 227 return; 228 } 229 230 if (softnic_parser_read_uint32(&shaper_profile_id, tokens[4]) != 0) { 231 snprintf(out, out_size, MSG_ARG_INVALID, "profile_id"); 232 return; 233 } 234 235 if (strcmp(tokens[5], "rate") != 0) { 236 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rate"); 237 return; 238 } 239 240 if (softnic_parser_read_uint64(&sp.peak.rate, tokens[6]) != 0) { 241 snprintf(out, out_size, MSG_ARG_INVALID, "tb_rate"); 242 return; 243 } 244 245 if (strcmp(tokens[7], "size") != 0) { 246 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size"); 247 return; 248 } 249 250 if (softnic_parser_read_uint64(&sp.peak.size, tokens[8]) != 0) { 251 snprintf(out, out_size, MSG_ARG_INVALID, "tb_size"); 252 return; 253 } 254 255 if (strcmp(tokens[9], "adj") != 0) { 256 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "adj"); 257 return; 258 } 259 260 if (softnic_parser_read_int32(&sp.pkt_length_adjust, tokens[10]) != 0) { 261 snprintf(out, out_size, MSG_ARG_INVALID, "packet_length_adjust"); 262 return; 263 } 264 265 status = rte_eth_dev_get_port_by_name(softnic->params.name, &port_id); 266 if (status) 267 return; 268 269 status = rte_tm_shaper_profile_add(port_id, shaper_profile_id, &sp, &error); 270 if (status != 0) { 271 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 272 return; 273 } 274 } 275 276 /** 277 * tmgr shared shaper 278 * id <shared_shaper_id> 279 * profile <shaper_profile_id> 280 */ 281 static void 282 cmd_tmgr_shared_shaper(struct pmd_internals *softnic, 283 char **tokens, 284 uint32_t n_tokens, 285 char *out, 286 size_t out_size) 287 { 288 struct rte_tm_error error; 289 uint32_t shared_shaper_id, shaper_profile_id; 290 uint16_t port_id; 291 int status; 292 293 if (n_tokens != 7) { 294 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 295 return; 296 } 297 298 if (strcmp(tokens[1], "shared") != 0) { 299 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "shared"); 300 return; 301 } 302 303 if (strcmp(tokens[2], "shaper") != 0) { 304 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "shaper"); 305 return; 306 } 307 308 if (strcmp(tokens[3], "id") != 0) { 309 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "id"); 310 return; 311 } 312 313 if (softnic_parser_read_uint32(&shared_shaper_id, tokens[4]) != 0) { 314 snprintf(out, out_size, MSG_ARG_INVALID, "shared_shaper_id"); 315 return; 316 } 317 318 if (strcmp(tokens[5], "profile") != 0) { 319 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile"); 320 return; 321 } 322 323 if (softnic_parser_read_uint32(&shaper_profile_id, tokens[6]) != 0) { 324 snprintf(out, out_size, MSG_ARG_INVALID, "shaper_profile_id"); 325 return; 326 } 327 328 status = rte_eth_dev_get_port_by_name(softnic->params.name, &port_id); 329 if (status) 330 return; 331 332 status = rte_tm_shared_shaper_add_update(port_id, 333 shared_shaper_id, 334 shaper_profile_id, 335 &error); 336 if (status != 0) { 337 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 338 return; 339 } 340 } 341 342 /** 343 * tmgr node 344 * id <node_id> 345 * parent <parent_node_id | none> 346 * priority <priority> 347 * weight <weight> 348 * [shaper profile <shaper_profile_id>] 349 * [shared shaper <shared_shaper_id>] 350 * [nonleaf sp <n_sp_priorities>] 351 */ 352 static void 353 cmd_tmgr_node(struct pmd_internals *softnic, 354 char **tokens, 355 uint32_t n_tokens, 356 char *out, 357 size_t out_size) 358 { 359 struct rte_tm_error error; 360 struct rte_tm_node_params np; 361 uint32_t node_id, parent_node_id, priority, weight, shared_shaper_id; 362 uint16_t port_id; 363 int status; 364 365 memset(&np, 0, sizeof(struct rte_tm_node_params)); 366 np.shaper_profile_id = RTE_TM_SHAPER_PROFILE_ID_NONE; 367 np.nonleaf.n_sp_priorities = 1; 368 369 if (n_tokens < 10) { 370 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 371 return; 372 } 373 374 if (strcmp(tokens[1], "node") != 0) { 375 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "node"); 376 return; 377 } 378 379 if (strcmp(tokens[2], "id") != 0) { 380 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "id"); 381 return; 382 } 383 384 if (softnic_parser_read_uint32(&node_id, tokens[3]) != 0) { 385 snprintf(out, out_size, MSG_ARG_INVALID, "node_id"); 386 return; 387 } 388 389 if (strcmp(tokens[4], "parent") != 0) { 390 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "parent"); 391 return; 392 } 393 394 if (strcmp(tokens[5], "none") == 0) 395 parent_node_id = RTE_TM_NODE_ID_NULL; 396 else { 397 if (softnic_parser_read_uint32(&parent_node_id, tokens[5]) != 0) { 398 snprintf(out, out_size, MSG_ARG_INVALID, "parent_node_id"); 399 return; 400 } 401 } 402 403 if (strcmp(tokens[6], "priority") != 0) { 404 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "priority"); 405 return; 406 } 407 408 if (softnic_parser_read_uint32(&priority, tokens[7]) != 0) { 409 snprintf(out, out_size, MSG_ARG_INVALID, "priority"); 410 return; 411 } 412 413 if (strcmp(tokens[8], "weight") != 0) { 414 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "weight"); 415 return; 416 } 417 418 if (softnic_parser_read_uint32(&weight, tokens[9]) != 0) { 419 snprintf(out, out_size, MSG_ARG_INVALID, "weight"); 420 return; 421 } 422 423 tokens += 10; 424 n_tokens -= 10; 425 426 if (n_tokens >= 2 && 427 (strcmp(tokens[0], "shaper") == 0) && 428 (strcmp(tokens[1], "profile") == 0)) { 429 if (n_tokens < 3) { 430 snprintf(out, out_size, MSG_ARG_MISMATCH, "tmgr node"); 431 return; 432 } 433 434 if (strcmp(tokens[2], "none") == 0) { 435 np.shaper_profile_id = RTE_TM_SHAPER_PROFILE_ID_NONE; 436 } else { 437 if (softnic_parser_read_uint32(&np.shaper_profile_id, tokens[2]) != 0) { 438 snprintf(out, out_size, MSG_ARG_INVALID, "shaper_profile_id"); 439 return; 440 } 441 } 442 443 tokens += 3; 444 n_tokens -= 3; 445 } /* shaper profile */ 446 447 if (n_tokens >= 2 && 448 (strcmp(tokens[0], "shared") == 0) && 449 (strcmp(tokens[1], "shaper") == 0)) { 450 if (n_tokens < 3) { 451 snprintf(out, out_size, MSG_ARG_MISMATCH, "tmgr node"); 452 return; 453 } 454 455 if (softnic_parser_read_uint32(&shared_shaper_id, tokens[2]) != 0) { 456 snprintf(out, out_size, MSG_ARG_INVALID, "shared_shaper_id"); 457 return; 458 } 459 460 np.shared_shaper_id = &shared_shaper_id; 461 np.n_shared_shapers = 1; 462 463 tokens += 3; 464 n_tokens -= 3; 465 } /* shared shaper */ 466 467 if (n_tokens >= 2 && 468 (strcmp(tokens[0], "nonleaf") == 0) && 469 (strcmp(tokens[1], "sp") == 0)) { 470 if (n_tokens < 3) { 471 snprintf(out, out_size, MSG_ARG_MISMATCH, "tmgr node"); 472 return; 473 } 474 475 if (softnic_parser_read_uint32(&np.nonleaf.n_sp_priorities, tokens[2]) != 0) { 476 snprintf(out, out_size, MSG_ARG_INVALID, "n_sp_priorities"); 477 return; 478 } 479 480 tokens += 3; 481 n_tokens -= 3; 482 } /* nonleaf sp <n_sp_priorities> */ 483 484 if (n_tokens) { 485 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 486 return; 487 } 488 489 status = rte_eth_dev_get_port_by_name(softnic->params.name, &port_id); 490 if (status != 0) 491 return; 492 493 status = rte_tm_node_add(port_id, 494 node_id, 495 parent_node_id, 496 priority, 497 weight, 498 RTE_TM_NODE_LEVEL_ID_ANY, 499 &np, 500 &error); 501 if (status != 0) { 502 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 503 return; 504 } 505 } 506 507 static uint32_t 508 root_node_id(uint32_t n_spp, 509 uint32_t n_pps) 510 { 511 uint32_t n_queues = n_spp * n_pps * RTE_SCHED_QUEUES_PER_PIPE; 512 uint32_t n_tc = n_spp * n_pps * RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; 513 uint32_t n_pipes = n_spp * n_pps; 514 515 return n_queues + n_tc + n_pipes + n_spp; 516 } 517 518 static uint32_t 519 subport_node_id(uint32_t n_spp, 520 uint32_t n_pps, 521 uint32_t subport_id) 522 { 523 uint32_t n_pipes = n_spp * n_pps; 524 uint32_t n_tc = n_pipes * RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; 525 uint32_t n_queues = n_pipes * RTE_SCHED_QUEUES_PER_PIPE; 526 527 return n_queues + n_tc + n_pipes + subport_id; 528 } 529 530 static uint32_t 531 pipe_node_id(uint32_t n_spp, 532 uint32_t n_pps, 533 uint32_t subport_id, 534 uint32_t pipe_id) 535 { 536 uint32_t n_pipes = n_spp * n_pps; 537 uint32_t n_tc = n_pipes * RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; 538 uint32_t n_queues = n_pipes * RTE_SCHED_QUEUES_PER_PIPE; 539 540 return n_queues + 541 n_tc + 542 pipe_id + 543 subport_id * n_pps; 544 } 545 546 static uint32_t 547 tc_node_id(uint32_t n_spp, 548 uint32_t n_pps, 549 uint32_t subport_id, 550 uint32_t pipe_id, 551 uint32_t tc_id) 552 { 553 uint32_t n_pipes = n_spp * n_pps; 554 uint32_t n_queues = n_pipes * RTE_SCHED_QUEUES_PER_PIPE; 555 556 return n_queues + 557 tc_id + 558 (pipe_id + subport_id * n_pps) * RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; 559 } 560 561 static uint32_t 562 queue_node_id(uint32_t n_spp __rte_unused, 563 uint32_t n_pps, 564 uint32_t subport_id, 565 uint32_t pipe_id, 566 uint32_t tc_id, 567 uint32_t queue_id) 568 { 569 return queue_id + tc_id + 570 (pipe_id + subport_id * n_pps) * RTE_SCHED_QUEUES_PER_PIPE; 571 } 572 573 struct tmgr_hierarchy_default_params { 574 uint32_t n_spp; /**< Number of subports per port. */ 575 uint32_t n_pps; /**< Number of pipes per subport. */ 576 577 struct { 578 uint32_t port; 579 uint32_t subport; 580 uint32_t pipe; 581 uint32_t tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; 582 } shaper_profile_id; 583 584 struct { 585 uint32_t tc[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; 586 uint32_t tc_valid[RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE]; 587 } shared_shaper_id; 588 589 struct { 590 uint32_t queue[RTE_SCHED_QUEUES_PER_PIPE]; 591 } weight; 592 }; 593 594 static int 595 tmgr_hierarchy_default(struct pmd_internals *softnic, 596 struct tmgr_hierarchy_default_params *params) 597 { 598 struct rte_tm_node_params root_node_params = { 599 .shaper_profile_id = params->shaper_profile_id.port, 600 .nonleaf = { 601 .n_sp_priorities = 1, 602 }, 603 }; 604 605 struct rte_tm_node_params subport_node_params = { 606 .shaper_profile_id = params->shaper_profile_id.subport, 607 .nonleaf = { 608 .n_sp_priorities = 1, 609 }, 610 }; 611 612 struct rte_tm_node_params pipe_node_params = { 613 .shaper_profile_id = params->shaper_profile_id.pipe, 614 .nonleaf = { 615 .n_sp_priorities = RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE, 616 }, 617 }; 618 619 uint32_t *shared_shaper_id = 620 (uint32_t *)calloc(RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE, 621 sizeof(uint32_t)); 622 623 if (shared_shaper_id == NULL) 624 return -1; 625 626 memcpy(shared_shaper_id, params->shared_shaper_id.tc, 627 sizeof(params->shared_shaper_id.tc)); 628 629 struct rte_tm_node_params tc_node_params[] = { 630 [0] = { 631 .shaper_profile_id = params->shaper_profile_id.tc[0], 632 .shared_shaper_id = &shared_shaper_id[0], 633 .n_shared_shapers = 634 (¶ms->shared_shaper_id.tc_valid[0]) ? 1 : 0, 635 .nonleaf = { 636 .n_sp_priorities = 1, 637 }, 638 }, 639 640 [1] = { 641 .shaper_profile_id = params->shaper_profile_id.tc[1], 642 .shared_shaper_id = &shared_shaper_id[1], 643 .n_shared_shapers = 644 (¶ms->shared_shaper_id.tc_valid[1]) ? 1 : 0, 645 .nonleaf = { 646 .n_sp_priorities = 1, 647 }, 648 }, 649 650 [2] = { 651 .shaper_profile_id = params->shaper_profile_id.tc[2], 652 .shared_shaper_id = &shared_shaper_id[2], 653 .n_shared_shapers = 654 (¶ms->shared_shaper_id.tc_valid[2]) ? 1 : 0, 655 .nonleaf = { 656 .n_sp_priorities = 1, 657 }, 658 }, 659 660 [3] = { 661 .shaper_profile_id = params->shaper_profile_id.tc[3], 662 .shared_shaper_id = &shared_shaper_id[3], 663 .n_shared_shapers = 664 (¶ms->shared_shaper_id.tc_valid[3]) ? 1 : 0, 665 .nonleaf = { 666 .n_sp_priorities = 1, 667 }, 668 }, 669 670 [4] = { 671 .shaper_profile_id = params->shaper_profile_id.tc[4], 672 .shared_shaper_id = &shared_shaper_id[4], 673 .n_shared_shapers = 674 (¶ms->shared_shaper_id.tc_valid[4]) ? 1 : 0, 675 .nonleaf = { 676 .n_sp_priorities = 1, 677 }, 678 }, 679 680 [5] = { 681 .shaper_profile_id = params->shaper_profile_id.tc[5], 682 .shared_shaper_id = &shared_shaper_id[5], 683 .n_shared_shapers = 684 (¶ms->shared_shaper_id.tc_valid[5]) ? 1 : 0, 685 .nonleaf = { 686 .n_sp_priorities = 1, 687 }, 688 }, 689 690 [6] = { 691 .shaper_profile_id = params->shaper_profile_id.tc[6], 692 .shared_shaper_id = &shared_shaper_id[6], 693 .n_shared_shapers = 694 (¶ms->shared_shaper_id.tc_valid[6]) ? 1 : 0, 695 .nonleaf = { 696 .n_sp_priorities = 1, 697 }, 698 }, 699 700 [7] = { 701 .shaper_profile_id = params->shaper_profile_id.tc[7], 702 .shared_shaper_id = &shared_shaper_id[7], 703 .n_shared_shapers = 704 (¶ms->shared_shaper_id.tc_valid[7]) ? 1 : 0, 705 .nonleaf = { 706 .n_sp_priorities = 1, 707 }, 708 }, 709 710 [8] = { 711 .shaper_profile_id = params->shaper_profile_id.tc[8], 712 .shared_shaper_id = &shared_shaper_id[8], 713 .n_shared_shapers = 714 (¶ms->shared_shaper_id.tc_valid[8]) ? 1 : 0, 715 .nonleaf = { 716 .n_sp_priorities = 1, 717 }, 718 }, 719 720 [9] = { 721 .shaper_profile_id = params->shaper_profile_id.tc[9], 722 .shared_shaper_id = &shared_shaper_id[9], 723 .n_shared_shapers = 724 (¶ms->shared_shaper_id.tc_valid[9]) ? 1 : 0, 725 .nonleaf = { 726 .n_sp_priorities = 1, 727 }, 728 }, 729 730 [10] = { 731 .shaper_profile_id = params->shaper_profile_id.tc[10], 732 .shared_shaper_id = &shared_shaper_id[10], 733 .n_shared_shapers = 734 (¶ms->shared_shaper_id.tc_valid[10]) ? 1 : 0, 735 .nonleaf = { 736 .n_sp_priorities = 1, 737 }, 738 }, 739 740 [11] = { 741 .shaper_profile_id = params->shaper_profile_id.tc[11], 742 .shared_shaper_id = &shared_shaper_id[11], 743 .n_shared_shapers = 744 (¶ms->shared_shaper_id.tc_valid[11]) ? 1 : 0, 745 .nonleaf = { 746 .n_sp_priorities = 1, 747 }, 748 }, 749 750 [12] = { 751 .shaper_profile_id = params->shaper_profile_id.tc[12], 752 .shared_shaper_id = &shared_shaper_id[12], 753 .n_shared_shapers = 754 (¶ms->shared_shaper_id.tc_valid[12]) ? 1 : 0, 755 .nonleaf = { 756 .n_sp_priorities = 1, 757 }, 758 }, 759 }; 760 761 struct rte_tm_node_params queue_node_params = { 762 .shaper_profile_id = RTE_TM_SHAPER_PROFILE_ID_NONE, 763 }; 764 765 struct rte_tm_error error; 766 uint32_t n_spp = params->n_spp, n_pps = params->n_pps, s; 767 int status; 768 uint16_t port_id; 769 770 status = rte_eth_dev_get_port_by_name(softnic->params.name, &port_id); 771 if (status) 772 return -1; 773 774 /* Hierarchy level 0: Root node */ 775 status = rte_tm_node_add(port_id, 776 root_node_id(n_spp, n_pps), 777 RTE_TM_NODE_ID_NULL, 778 0, 779 1, 780 RTE_TM_NODE_LEVEL_ID_ANY, 781 &root_node_params, 782 &error); 783 if (status) 784 return -1; 785 786 /* Hierarchy level 1: Subport nodes */ 787 for (s = 0; s < params->n_spp; s++) { 788 uint32_t p; 789 790 status = rte_tm_node_add(port_id, 791 subport_node_id(n_spp, n_pps, s), 792 root_node_id(n_spp, n_pps), 793 0, 794 1, 795 RTE_TM_NODE_LEVEL_ID_ANY, 796 &subport_node_params, 797 &error); 798 if (status) 799 return -1; 800 801 /* Hierarchy level 2: Pipe nodes */ 802 for (p = 0; p < params->n_pps; p++) { 803 uint32_t t; 804 805 status = rte_tm_node_add(port_id, 806 pipe_node_id(n_spp, n_pps, s, p), 807 subport_node_id(n_spp, n_pps, s), 808 0, 809 1, 810 RTE_TM_NODE_LEVEL_ID_ANY, 811 &pipe_node_params, 812 &error); 813 if (status) 814 return -1; 815 816 /* Hierarchy level 3: Traffic class nodes */ 817 for (t = 0; t < RTE_SCHED_TRAFFIC_CLASSES_PER_PIPE; t++) { 818 uint32_t q; 819 820 status = rte_tm_node_add(port_id, 821 tc_node_id(n_spp, n_pps, s, p, t), 822 pipe_node_id(n_spp, n_pps, s, p), 823 t, 824 1, 825 RTE_TM_NODE_LEVEL_ID_ANY, 826 &tc_node_params[t], 827 &error); 828 if (status) 829 return -1; 830 831 /* Hierarchy level 4: Queue nodes */ 832 if (t < RTE_SCHED_TRAFFIC_CLASS_BE) { 833 /* Strict-priority traffic class queues */ 834 q = 0; 835 status = rte_tm_node_add(port_id, 836 queue_node_id(n_spp, n_pps, s, p, t, q), 837 tc_node_id(n_spp, n_pps, s, p, t), 838 0, 839 params->weight.queue[q], 840 RTE_TM_NODE_LEVEL_ID_ANY, 841 &queue_node_params, 842 &error); 843 if (status) 844 return -1; 845 846 continue; 847 } 848 /* Best-effort traffic class queues */ 849 for (q = 0; q < RTE_SCHED_BE_QUEUES_PER_PIPE; q++) { 850 status = rte_tm_node_add(port_id, 851 queue_node_id(n_spp, n_pps, s, p, t, q), 852 tc_node_id(n_spp, n_pps, s, p, t), 853 0, 854 params->weight.queue[q], 855 RTE_TM_NODE_LEVEL_ID_ANY, 856 &queue_node_params, 857 &error); 858 if (status) 859 return -1; 860 } 861 } /* TC */ 862 } /* Pipe */ 863 } /* Subport */ 864 865 return 0; 866 } 867 868 869 /** 870 * tmgr hierarchy-default 871 * spp <n_subports_per_port> 872 * pps <n_pipes_per_subport> 873 * shaper profile 874 * port <profile_id> 875 * subport <profile_id> 876 * pipe <profile_id> 877 * tc0 <profile_id> 878 * tc1 <profile_id> 879 * tc2 <profile_id> 880 * tc3 <profile_id> 881 * tc4 <profile_id> 882 * tc5 <profile_id> 883 * tc6 <profile_id> 884 * tc7 <profile_id> 885 * tc8 <profile_id> 886 * tc9 <profile_id> 887 * tc10 <profile_id> 888 * tc11 <profile_id> 889 * tc12 <profile_id> 890 * shared shaper 891 * tc0 <id | none> 892 * tc1 <id | none> 893 * tc2 <id | none> 894 * tc3 <id | none> 895 * tc4 <id | none> 896 * tc5 <id | none> 897 * tc6 <id | none> 898 * tc7 <id | none> 899 * tc8 <id | none> 900 * tc9 <id | none> 901 * tc10 <id | none> 902 * tc11 <id | none> 903 * tc12 <id | none> 904 * weight 905 * queue <q12> ... <q15> 906 */ 907 static void 908 cmd_tmgr_hierarchy_default(struct pmd_internals *softnic, 909 char **tokens, 910 uint32_t n_tokens, 911 char *out, 912 size_t out_size) 913 { 914 struct tmgr_hierarchy_default_params p; 915 int i, j, status; 916 917 memset(&p, 0, sizeof(p)); 918 919 if (n_tokens != 74) { 920 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 921 return; 922 } 923 924 if (strcmp(tokens[1], "hierarchy-default") != 0) { 925 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "hierarchy-default"); 926 return; 927 } 928 929 if (strcmp(tokens[2], "spp") != 0) { 930 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "spp"); 931 return; 932 } 933 934 if (softnic_parser_read_uint32(&p.n_spp, tokens[3]) != 0) { 935 snprintf(out, out_size, MSG_ARG_INVALID, "n_subports_per_port"); 936 return; 937 } 938 939 if (strcmp(tokens[4], "pps") != 0) { 940 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pps"); 941 return; 942 } 943 944 if (softnic_parser_read_uint32(&p.n_pps, tokens[5]) != 0) { 945 snprintf(out, out_size, MSG_ARG_INVALID, "n_pipes_per_subport"); 946 return; 947 } 948 949 /* Shaper profile */ 950 951 if (strcmp(tokens[6], "shaper") != 0) { 952 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "shaper"); 953 return; 954 } 955 956 if (strcmp(tokens[7], "profile") != 0) { 957 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile"); 958 return; 959 } 960 961 if (strcmp(tokens[8], "port") != 0) { 962 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 963 return; 964 } 965 966 if (softnic_parser_read_uint32(&p.shaper_profile_id.port, tokens[9]) != 0) { 967 snprintf(out, out_size, MSG_ARG_INVALID, "port profile id"); 968 return; 969 } 970 971 if (strcmp(tokens[10], "subport") != 0) { 972 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "subport"); 973 return; 974 } 975 976 if (softnic_parser_read_uint32(&p.shaper_profile_id.subport, tokens[11]) != 0) { 977 snprintf(out, out_size, MSG_ARG_INVALID, "subport profile id"); 978 return; 979 } 980 981 if (strcmp(tokens[12], "pipe") != 0) { 982 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipe"); 983 return; 984 } 985 986 if (softnic_parser_read_uint32(&p.shaper_profile_id.pipe, tokens[13]) != 0) { 987 snprintf(out, out_size, MSG_ARG_INVALID, "pipe_profile_id"); 988 return; 989 } 990 991 if (strcmp(tokens[14], "tc0") != 0) { 992 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc0"); 993 return; 994 } 995 996 if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[0], tokens[15]) != 0) { 997 snprintf(out, out_size, MSG_ARG_INVALID, "tc0 profile id"); 998 return; 999 } 1000 1001 if (strcmp(tokens[16], "tc1") != 0) { 1002 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc1"); 1003 return; 1004 } 1005 1006 if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[1], tokens[17]) != 0) { 1007 snprintf(out, out_size, MSG_ARG_INVALID, "tc1 profile id"); 1008 return; 1009 } 1010 1011 if (strcmp(tokens[18], "tc2") != 0) { 1012 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc2"); 1013 return; 1014 } 1015 1016 if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[2], tokens[19]) != 0) { 1017 snprintf(out, out_size, MSG_ARG_INVALID, "tc2 profile id"); 1018 return; 1019 } 1020 1021 if (strcmp(tokens[20], "tc3") != 0) { 1022 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc3"); 1023 return; 1024 } 1025 1026 if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[3], tokens[21]) != 0) { 1027 snprintf(out, out_size, MSG_ARG_INVALID, "tc3 profile id"); 1028 return; 1029 } 1030 1031 if (strcmp(tokens[22], "tc4") != 0) { 1032 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc4"); 1033 return; 1034 } 1035 1036 if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[4], tokens[23]) != 0) { 1037 snprintf(out, out_size, MSG_ARG_INVALID, "tc4 profile id"); 1038 return; 1039 } 1040 1041 if (strcmp(tokens[24], "tc5") != 0) { 1042 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc5"); 1043 return; 1044 } 1045 1046 if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[5], tokens[25]) != 0) { 1047 snprintf(out, out_size, MSG_ARG_INVALID, "tc5 profile id"); 1048 return; 1049 } 1050 1051 if (strcmp(tokens[26], "tc6") != 0) { 1052 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc6"); 1053 return; 1054 } 1055 1056 if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[6], tokens[27]) != 0) { 1057 snprintf(out, out_size, MSG_ARG_INVALID, "tc6 profile id"); 1058 return; 1059 } 1060 1061 if (strcmp(tokens[28], "tc7") != 0) { 1062 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc7"); 1063 return; 1064 } 1065 1066 if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[7], tokens[29]) != 0) { 1067 snprintf(out, out_size, MSG_ARG_INVALID, "tc7 profile id"); 1068 return; 1069 } 1070 1071 if (strcmp(tokens[30], "tc8") != 0) { 1072 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc8"); 1073 return; 1074 } 1075 1076 if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[8], tokens[31]) != 0) { 1077 snprintf(out, out_size, MSG_ARG_INVALID, "tc8 profile id"); 1078 return; 1079 } 1080 1081 if (strcmp(tokens[32], "tc9") != 0) { 1082 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc9"); 1083 return; 1084 } 1085 1086 if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[9], tokens[33]) != 0) { 1087 snprintf(out, out_size, MSG_ARG_INVALID, "tc9 profile id"); 1088 return; 1089 } 1090 1091 if (strcmp(tokens[34], "tc10") != 0) { 1092 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc10"); 1093 return; 1094 } 1095 1096 if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[10], tokens[35]) != 0) { 1097 snprintf(out, out_size, MSG_ARG_INVALID, "tc10 profile id"); 1098 return; 1099 } 1100 1101 if (strcmp(tokens[36], "tc11") != 0) { 1102 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc11"); 1103 return; 1104 } 1105 1106 if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[11], tokens[37]) != 0) { 1107 snprintf(out, out_size, MSG_ARG_INVALID, "tc11 profile id"); 1108 return; 1109 } 1110 1111 if (strcmp(tokens[38], "tc12") != 0) { 1112 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc12"); 1113 return; 1114 } 1115 1116 if (softnic_parser_read_uint32(&p.shaper_profile_id.tc[12], tokens[39]) != 0) { 1117 snprintf(out, out_size, MSG_ARG_INVALID, "tc12 profile id"); 1118 return; 1119 } 1120 1121 /* Shared shaper */ 1122 1123 if (strcmp(tokens[40], "shared") != 0) { 1124 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "shared"); 1125 return; 1126 } 1127 1128 if (strcmp(tokens[41], "shaper") != 0) { 1129 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "shaper"); 1130 return; 1131 } 1132 1133 if (strcmp(tokens[42], "tc0") != 0) { 1134 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc0"); 1135 return; 1136 } 1137 1138 if (strcmp(tokens[43], "none") == 0) 1139 p.shared_shaper_id.tc_valid[0] = 0; 1140 else { 1141 if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[0], 1142 tokens[43]) != 0) { 1143 snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc0"); 1144 return; 1145 } 1146 1147 p.shared_shaper_id.tc_valid[0] = 1; 1148 } 1149 1150 if (strcmp(tokens[44], "tc1") != 0) { 1151 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc1"); 1152 return; 1153 } 1154 1155 if (strcmp(tokens[45], "none") == 0) 1156 p.shared_shaper_id.tc_valid[1] = 0; 1157 else { 1158 if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[1], 1159 tokens[45]) != 0) { 1160 snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc1"); 1161 return; 1162 } 1163 1164 p.shared_shaper_id.tc_valid[1] = 1; 1165 } 1166 1167 if (strcmp(tokens[46], "tc2") != 0) { 1168 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc2"); 1169 return; 1170 } 1171 1172 if (strcmp(tokens[47], "none") == 0) 1173 p.shared_shaper_id.tc_valid[2] = 0; 1174 else { 1175 if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[2], 1176 tokens[47]) != 0) { 1177 snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc2"); 1178 return; 1179 } 1180 1181 p.shared_shaper_id.tc_valid[2] = 1; 1182 } 1183 1184 if (strcmp(tokens[48], "tc3") != 0) { 1185 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc3"); 1186 return; 1187 } 1188 1189 if (strcmp(tokens[49], "none") == 0) 1190 p.shared_shaper_id.tc_valid[3] = 0; 1191 else { 1192 if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[3], 1193 tokens[49]) != 0) { 1194 snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc3"); 1195 return; 1196 } 1197 1198 p.shared_shaper_id.tc_valid[3] = 1; 1199 } 1200 1201 if (strcmp(tokens[50], "tc4") != 0) { 1202 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc4"); 1203 return; 1204 } 1205 1206 if (strcmp(tokens[51], "none") == 0) { 1207 p.shared_shaper_id.tc_valid[4] = 0; 1208 } else { 1209 if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[4], 1210 tokens[51]) != 0) { 1211 snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc4"); 1212 return; 1213 } 1214 1215 p.shared_shaper_id.tc_valid[4] = 1; 1216 } 1217 1218 if (strcmp(tokens[52], "tc5") != 0) { 1219 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc5"); 1220 return; 1221 } 1222 1223 if (strcmp(tokens[53], "none") == 0) { 1224 p.shared_shaper_id.tc_valid[5] = 0; 1225 } else { 1226 if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[5], 1227 tokens[53]) != 0) { 1228 snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc5"); 1229 return; 1230 } 1231 1232 p.shared_shaper_id.tc_valid[5] = 1; 1233 } 1234 1235 if (strcmp(tokens[54], "tc6") != 0) { 1236 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc6"); 1237 return; 1238 } 1239 1240 if (strcmp(tokens[55], "none") == 0) { 1241 p.shared_shaper_id.tc_valid[6] = 0; 1242 } else { 1243 if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[6], 1244 tokens[55]) != 0) { 1245 snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc6"); 1246 return; 1247 } 1248 1249 p.shared_shaper_id.tc_valid[6] = 1; 1250 } 1251 1252 if (strcmp(tokens[56], "tc7") != 0) { 1253 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc7"); 1254 return; 1255 } 1256 1257 if (strcmp(tokens[57], "none") == 0) { 1258 p.shared_shaper_id.tc_valid[7] = 0; 1259 } else { 1260 if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[7], 1261 tokens[57]) != 0) { 1262 snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc7"); 1263 return; 1264 } 1265 1266 p.shared_shaper_id.tc_valid[7] = 1; 1267 } 1268 1269 if (strcmp(tokens[58], "tc8") != 0) { 1270 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc8"); 1271 return; 1272 } 1273 1274 if (strcmp(tokens[59], "none") == 0) { 1275 p.shared_shaper_id.tc_valid[8] = 0; 1276 } else { 1277 if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[8], 1278 tokens[59]) != 0) { 1279 snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc8"); 1280 return; 1281 } 1282 1283 p.shared_shaper_id.tc_valid[8] = 1; 1284 } 1285 1286 if (strcmp(tokens[60], "tc9") != 0) { 1287 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc9"); 1288 return; 1289 } 1290 1291 if (strcmp(tokens[61], "none") == 0) { 1292 p.shared_shaper_id.tc_valid[9] = 0; 1293 } else { 1294 if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[9], 1295 tokens[61]) != 0) { 1296 snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc9"); 1297 return; 1298 } 1299 1300 p.shared_shaper_id.tc_valid[9] = 1; 1301 } 1302 1303 if (strcmp(tokens[62], "tc10") != 0) { 1304 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc10"); 1305 return; 1306 } 1307 1308 if (strcmp(tokens[63], "none") == 0) { 1309 p.shared_shaper_id.tc_valid[10] = 0; 1310 } else { 1311 if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[10], 1312 tokens[63]) != 0) { 1313 snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc10"); 1314 return; 1315 } 1316 1317 p.shared_shaper_id.tc_valid[10] = 1; 1318 } 1319 1320 if (strcmp(tokens[64], "tc11") != 0) { 1321 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc11"); 1322 return; 1323 } 1324 1325 if (strcmp(tokens[65], "none") == 0) { 1326 p.shared_shaper_id.tc_valid[11] = 0; 1327 } else { 1328 if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[11], 1329 tokens[65]) != 0) { 1330 snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc11"); 1331 return; 1332 } 1333 1334 p.shared_shaper_id.tc_valid[11] = 1; 1335 } 1336 1337 if (strcmp(tokens[66], "tc12") != 0) { 1338 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc12"); 1339 return; 1340 } 1341 1342 if (strcmp(tokens[67], "none") == 0) { 1343 p.shared_shaper_id.tc_valid[12] = 0; 1344 } else { 1345 if (softnic_parser_read_uint32(&p.shared_shaper_id.tc[12], 1346 tokens[67]) != 0) { 1347 snprintf(out, out_size, MSG_ARG_INVALID, "shared shaper tc12"); 1348 return; 1349 } 1350 1351 p.shared_shaper_id.tc_valid[12] = 1; 1352 } 1353 1354 /* Weight */ 1355 1356 if (strcmp(tokens[68], "weight") != 0) { 1357 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "weight"); 1358 return; 1359 } 1360 1361 if (strcmp(tokens[69], "queue") != 0) { 1362 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "queue"); 1363 return; 1364 } 1365 1366 for (i = 0, j = 0; i < 16; i++) { 1367 if (i < RTE_SCHED_TRAFFIC_CLASS_BE) { 1368 p.weight.queue[i] = 1; 1369 } else { 1370 if (softnic_parser_read_uint32(&p.weight.queue[i], 1371 tokens[70 + j]) != 0) { 1372 snprintf(out, out_size, MSG_ARG_INVALID, "weight queue"); 1373 return; 1374 } 1375 j++; 1376 } 1377 } 1378 1379 status = tmgr_hierarchy_default(softnic, &p); 1380 if (status != 0) { 1381 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 1382 return; 1383 } 1384 } 1385 1386 /** 1387 * tmgr hierarchy commit 1388 */ 1389 static void 1390 cmd_tmgr_hierarchy_commit(struct pmd_internals *softnic, 1391 char **tokens, 1392 uint32_t n_tokens, 1393 char *out, 1394 size_t out_size) 1395 { 1396 struct rte_tm_error error; 1397 uint16_t port_id; 1398 int status; 1399 1400 if (n_tokens != 3) { 1401 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1402 return; 1403 } 1404 1405 if (strcmp(tokens[1], "hierarchy") != 0) { 1406 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "hierarchy"); 1407 return; 1408 } 1409 1410 if (strcmp(tokens[2], "commit") != 0) { 1411 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "commit"); 1412 return; 1413 } 1414 1415 status = rte_eth_dev_get_port_by_name(softnic->params.name, &port_id); 1416 if (status != 0) 1417 return; 1418 1419 status = rte_tm_hierarchy_commit(port_id, 1, &error); 1420 if (status) { 1421 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 1422 return; 1423 } 1424 } 1425 1426 /** 1427 * tmgr <tmgr_name> 1428 */ 1429 static void 1430 cmd_tmgr(struct pmd_internals *softnic, 1431 char **tokens, 1432 uint32_t n_tokens, 1433 char *out, 1434 size_t out_size) 1435 { 1436 char *name; 1437 struct softnic_tmgr_port *tmgr_port; 1438 1439 if (n_tokens != 2) { 1440 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1441 return; 1442 } 1443 1444 name = tokens[1]; 1445 1446 tmgr_port = softnic_tmgr_port_create(softnic, name); 1447 if (tmgr_port == NULL) { 1448 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 1449 return; 1450 } 1451 } 1452 1453 /** 1454 * tap <tap_name> 1455 */ 1456 static void 1457 cmd_tap(struct pmd_internals *softnic, 1458 char **tokens, 1459 uint32_t n_tokens, 1460 char *out, 1461 size_t out_size) 1462 { 1463 char *name; 1464 struct softnic_tap *tap; 1465 1466 if (n_tokens != 2) { 1467 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1468 return; 1469 } 1470 1471 name = tokens[1]; 1472 1473 tap = softnic_tap_create(softnic, name); 1474 if (tap == NULL) { 1475 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 1476 return; 1477 } 1478 } 1479 1480 /** 1481 * cryptodev <tap_name> dev <device_name> | dev_id <device_id> 1482 * queue <n_queues> <queue_size> max_sessions <n_sessions> 1483 **/ 1484 1485 static void 1486 cmd_cryptodev(struct pmd_internals *softnic, 1487 char **tokens, 1488 uint32_t n_tokens, 1489 char *out, 1490 size_t out_size) 1491 { 1492 struct softnic_cryptodev_params params; 1493 char *name; 1494 1495 memset(¶ms, 0, sizeof(params)); 1496 if (n_tokens != 9) { 1497 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1498 return; 1499 } 1500 1501 name = tokens[1]; 1502 1503 if (strcmp(tokens[2], "dev") == 0) 1504 params.dev_name = tokens[3]; 1505 else if (strcmp(tokens[2], "dev_id") == 0) { 1506 if (softnic_parser_read_uint32(¶ms.dev_id, tokens[3]) < 0) { 1507 snprintf(out, out_size, MSG_ARG_INVALID, 1508 "dev_id"); 1509 return; 1510 } 1511 } else { 1512 snprintf(out, out_size, MSG_ARG_INVALID, 1513 "cryptodev"); 1514 return; 1515 } 1516 1517 if (strcmp(tokens[4], "queue")) { 1518 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 1519 "4"); 1520 return; 1521 } 1522 1523 if (softnic_parser_read_uint32(¶ms.n_queues, tokens[5]) < 0) { 1524 snprintf(out, out_size, MSG_ARG_INVALID, 1525 "q"); 1526 return; 1527 } 1528 1529 if (softnic_parser_read_uint32(¶ms.queue_size, tokens[6]) < 0) { 1530 snprintf(out, out_size, MSG_ARG_INVALID, 1531 "queue_size"); 1532 return; 1533 } 1534 1535 if (strcmp(tokens[7], "max_sessions")) { 1536 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 1537 "4"); 1538 return; 1539 } 1540 1541 if (softnic_parser_read_uint32(¶ms.session_pool_size, tokens[8]) 1542 < 0) { 1543 snprintf(out, out_size, MSG_ARG_INVALID, 1544 "q"); 1545 return; 1546 } 1547 1548 if (softnic_cryptodev_create(softnic, name, ¶ms) == NULL) { 1549 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 1550 return; 1551 } 1552 } 1553 1554 /** 1555 * port in action profile <profile_name> 1556 * [filter match | mismatch offset <key_offset> mask <key_mask> key <key_value> port <port_id>] 1557 * [balance offset <key_offset> mask <key_mask> port <port_id0> ... <port_id15>] 1558 */ 1559 static void 1560 cmd_port_in_action_profile(struct pmd_internals *softnic, 1561 char **tokens, 1562 uint32_t n_tokens, 1563 char *out, 1564 size_t out_size) 1565 { 1566 struct softnic_port_in_action_profile_params p; 1567 struct softnic_port_in_action_profile *ap; 1568 char *name; 1569 uint32_t t0; 1570 1571 memset(&p, 0, sizeof(p)); 1572 1573 if (n_tokens < 5) { 1574 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1575 return; 1576 } 1577 1578 if (strcmp(tokens[1], "in") != 0) { 1579 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in"); 1580 return; 1581 } 1582 1583 if (strcmp(tokens[2], "action") != 0) { 1584 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "action"); 1585 return; 1586 } 1587 1588 if (strcmp(tokens[3], "profile") != 0) { 1589 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile"); 1590 return; 1591 } 1592 1593 name = tokens[4]; 1594 1595 t0 = 5; 1596 1597 if (t0 < n_tokens && 1598 (strcmp(tokens[t0], "filter") == 0)) { 1599 uint32_t size; 1600 1601 if (n_tokens < t0 + 10) { 1602 snprintf(out, out_size, MSG_ARG_MISMATCH, "port in action profile filter"); 1603 return; 1604 } 1605 1606 if (strcmp(tokens[t0 + 1], "match") == 0) { 1607 p.fltr.filter_on_match = 1; 1608 } else if (strcmp(tokens[t0 + 1], "mismatch") == 0) { 1609 p.fltr.filter_on_match = 0; 1610 } else { 1611 snprintf(out, out_size, MSG_ARG_INVALID, "match or mismatch"); 1612 return; 1613 } 1614 1615 if (strcmp(tokens[t0 + 2], "offset") != 0) { 1616 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); 1617 return; 1618 } 1619 1620 if (softnic_parser_read_uint32(&p.fltr.key_offset, 1621 tokens[t0 + 3]) != 0) { 1622 snprintf(out, out_size, MSG_ARG_INVALID, "key_offset"); 1623 return; 1624 } 1625 1626 if (strcmp(tokens[t0 + 4], "mask") != 0) { 1627 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask"); 1628 return; 1629 } 1630 1631 size = RTE_PORT_IN_ACTION_FLTR_KEY_SIZE; 1632 if ((softnic_parse_hex_string(tokens[t0 + 5], 1633 p.fltr.key_mask, &size) != 0) || 1634 size != RTE_PORT_IN_ACTION_FLTR_KEY_SIZE) { 1635 snprintf(out, out_size, MSG_ARG_INVALID, "key_mask"); 1636 return; 1637 } 1638 1639 if (strcmp(tokens[t0 + 6], "key") != 0) { 1640 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "key"); 1641 return; 1642 } 1643 1644 size = RTE_PORT_IN_ACTION_FLTR_KEY_SIZE; 1645 if ((softnic_parse_hex_string(tokens[t0 + 7], 1646 p.fltr.key, &size) != 0) || 1647 size != RTE_PORT_IN_ACTION_FLTR_KEY_SIZE) { 1648 snprintf(out, out_size, MSG_ARG_INVALID, "key_value"); 1649 return; 1650 } 1651 1652 if (strcmp(tokens[t0 + 8], "port") != 0) { 1653 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 1654 return; 1655 } 1656 1657 if (softnic_parser_read_uint32(&p.fltr.port_id, 1658 tokens[t0 + 9]) != 0) { 1659 snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); 1660 return; 1661 } 1662 1663 p.action_mask |= 1LLU << RTE_PORT_IN_ACTION_FLTR; 1664 t0 += 10; 1665 } /* filter */ 1666 1667 if (t0 < n_tokens && 1668 (strcmp(tokens[t0], "balance") == 0)) { 1669 uint32_t i; 1670 1671 if (n_tokens < t0 + 22) { 1672 snprintf(out, out_size, MSG_ARG_MISMATCH, 1673 "port in action profile balance"); 1674 return; 1675 } 1676 1677 if (strcmp(tokens[t0 + 1], "offset") != 0) { 1678 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); 1679 return; 1680 } 1681 1682 if (softnic_parser_read_uint32(&p.lb.key_offset, 1683 tokens[t0 + 2]) != 0) { 1684 snprintf(out, out_size, MSG_ARG_INVALID, "key_offset"); 1685 return; 1686 } 1687 1688 if (strcmp(tokens[t0 + 3], "mask") != 0) { 1689 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask"); 1690 return; 1691 } 1692 1693 p.lb.key_size = RTE_PORT_IN_ACTION_LB_KEY_SIZE_MAX; 1694 if (softnic_parse_hex_string(tokens[t0 + 4], 1695 p.lb.key_mask, &p.lb.key_size) != 0) { 1696 snprintf(out, out_size, MSG_ARG_INVALID, "key_mask"); 1697 return; 1698 } 1699 1700 if (strcmp(tokens[t0 + 5], "port") != 0) { 1701 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 1702 return; 1703 } 1704 1705 for (i = 0; i < 16; i++) 1706 if (softnic_parser_read_uint32(&p.lb.port_id[i], 1707 tokens[t0 + 6 + i]) != 0) { 1708 snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); 1709 return; 1710 } 1711 1712 p.action_mask |= 1LLU << RTE_PORT_IN_ACTION_LB; 1713 t0 += 22; 1714 } /* balance */ 1715 1716 if (t0 < n_tokens) { 1717 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1718 return; 1719 } 1720 1721 ap = softnic_port_in_action_profile_create(softnic, name, &p); 1722 if (ap == NULL) { 1723 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 1724 return; 1725 } 1726 } 1727 1728 /** 1729 * table action profile <profile_name> 1730 * ipv4 | ipv6 1731 * offset <ip_offset> 1732 * fwd 1733 * [balance offset <key_offset> mask <key_mask> outoffset <out_offset>] 1734 * [meter srtcm | trtcm 1735 * tc <n_tc> 1736 * stats none | pkts | bytes | both] 1737 * [tm spp <n_subports_per_port> pps <n_pipes_per_subport>] 1738 * [encap ether | vlan | qinq | mpls | pppoe | qinq_pppoe | 1739 * vxlan offset <ether_offset> ipv4 | ipv6 vlan on | off] 1740 * [nat src | dst 1741 * proto udp | tcp] 1742 * [ttl drop | fwd 1743 * stats none | pkts] 1744 * [stats pkts | bytes | both] 1745 * [time] 1746 * [tag] 1747 * [decap] 1748 * 1749 */ 1750 static void 1751 cmd_table_action_profile(struct pmd_internals *softnic, 1752 char **tokens, 1753 uint32_t n_tokens, 1754 char *out, 1755 size_t out_size) 1756 { 1757 struct softnic_table_action_profile_params p; 1758 struct softnic_table_action_profile *ap; 1759 char *name; 1760 uint32_t t0; 1761 1762 memset(&p, 0, sizeof(p)); 1763 1764 if (n_tokens < 8) { 1765 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1766 return; 1767 } 1768 1769 if (strcmp(tokens[1], "action") != 0) { 1770 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "action"); 1771 return; 1772 } 1773 1774 if (strcmp(tokens[2], "profile") != 0) { 1775 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile"); 1776 return; 1777 } 1778 1779 name = tokens[3]; 1780 1781 if (strcmp(tokens[4], "ipv4") == 0) { 1782 p.common.ip_version = 1; 1783 } else if (strcmp(tokens[4], "ipv6") == 0) { 1784 p.common.ip_version = 0; 1785 } else { 1786 snprintf(out, out_size, MSG_ARG_INVALID, "ipv4 or ipv6"); 1787 return; 1788 } 1789 1790 if (strcmp(tokens[5], "offset") != 0) { 1791 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); 1792 return; 1793 } 1794 1795 if (softnic_parser_read_uint32(&p.common.ip_offset, 1796 tokens[6]) != 0) { 1797 snprintf(out, out_size, MSG_ARG_INVALID, "ip_offset"); 1798 return; 1799 } 1800 1801 if (strcmp(tokens[7], "fwd") != 0) { 1802 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "fwd"); 1803 return; 1804 } 1805 1806 p.action_mask |= 1LLU << RTE_TABLE_ACTION_FWD; 1807 1808 t0 = 8; 1809 if (t0 < n_tokens && 1810 (strcmp(tokens[t0], "balance") == 0)) { 1811 if (n_tokens < t0 + 7) { 1812 snprintf(out, out_size, MSG_ARG_MISMATCH, "table action profile balance"); 1813 return; 1814 } 1815 1816 if (strcmp(tokens[t0 + 1], "offset") != 0) { 1817 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); 1818 return; 1819 } 1820 1821 if (softnic_parser_read_uint32(&p.lb.key_offset, 1822 tokens[t0 + 2]) != 0) { 1823 snprintf(out, out_size, MSG_ARG_INVALID, "key_offset"); 1824 return; 1825 } 1826 1827 if (strcmp(tokens[t0 + 3], "mask") != 0) { 1828 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask"); 1829 return; 1830 } 1831 1832 p.lb.key_size = RTE_PORT_IN_ACTION_LB_KEY_SIZE_MAX; 1833 if (softnic_parse_hex_string(tokens[t0 + 4], 1834 p.lb.key_mask, &p.lb.key_size) != 0) { 1835 snprintf(out, out_size, MSG_ARG_INVALID, "key_mask"); 1836 return; 1837 } 1838 1839 if (strcmp(tokens[t0 + 5], "outoffset") != 0) { 1840 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "outoffset"); 1841 return; 1842 } 1843 1844 if (softnic_parser_read_uint32(&p.lb.out_offset, 1845 tokens[t0 + 6]) != 0) { 1846 snprintf(out, out_size, MSG_ARG_INVALID, "out_offset"); 1847 return; 1848 } 1849 1850 p.action_mask |= 1LLU << RTE_TABLE_ACTION_LB; 1851 t0 += 7; 1852 } /* balance */ 1853 1854 if (t0 < n_tokens && 1855 (strcmp(tokens[t0], "meter") == 0)) { 1856 if (n_tokens < t0 + 6) { 1857 snprintf(out, out_size, MSG_ARG_MISMATCH, 1858 "table action profile meter"); 1859 return; 1860 } 1861 1862 if (strcmp(tokens[t0 + 1], "srtcm") == 0) { 1863 p.mtr.alg = RTE_TABLE_ACTION_METER_SRTCM; 1864 } else if (strcmp(tokens[t0 + 1], "trtcm") == 0) { 1865 p.mtr.alg = RTE_TABLE_ACTION_METER_TRTCM; 1866 } else { 1867 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 1868 "srtcm or trtcm"); 1869 return; 1870 } 1871 1872 if (strcmp(tokens[t0 + 2], "tc") != 0) { 1873 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc"); 1874 return; 1875 } 1876 1877 if (softnic_parser_read_uint32(&p.mtr.n_tc, 1878 tokens[t0 + 3]) != 0) { 1879 snprintf(out, out_size, MSG_ARG_INVALID, "n_tc"); 1880 return; 1881 } 1882 1883 if (strcmp(tokens[t0 + 4], "stats") != 0) { 1884 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats"); 1885 return; 1886 } 1887 1888 if (strcmp(tokens[t0 + 5], "none") == 0) { 1889 p.mtr.n_packets_enabled = 0; 1890 p.mtr.n_bytes_enabled = 0; 1891 } else if (strcmp(tokens[t0 + 5], "pkts") == 0) { 1892 p.mtr.n_packets_enabled = 1; 1893 p.mtr.n_bytes_enabled = 0; 1894 } else if (strcmp(tokens[t0 + 5], "bytes") == 0) { 1895 p.mtr.n_packets_enabled = 0; 1896 p.mtr.n_bytes_enabled = 1; 1897 } else if (strcmp(tokens[t0 + 5], "both") == 0) { 1898 p.mtr.n_packets_enabled = 1; 1899 p.mtr.n_bytes_enabled = 1; 1900 } else { 1901 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 1902 "none or pkts or bytes or both"); 1903 return; 1904 } 1905 1906 p.action_mask |= 1LLU << RTE_TABLE_ACTION_MTR; 1907 t0 += 6; 1908 } /* meter */ 1909 1910 if (t0 < n_tokens && 1911 (strcmp(tokens[t0], "tm") == 0)) { 1912 if (n_tokens < t0 + 5) { 1913 snprintf(out, out_size, MSG_ARG_MISMATCH, 1914 "table action profile tm"); 1915 return; 1916 } 1917 1918 if (strcmp(tokens[t0 + 1], "spp") != 0) { 1919 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "spp"); 1920 return; 1921 } 1922 1923 if (softnic_parser_read_uint32(&p.tm.n_subports_per_port, 1924 tokens[t0 + 2]) != 0) { 1925 snprintf(out, out_size, MSG_ARG_INVALID, 1926 "n_subports_per_port"); 1927 return; 1928 } 1929 1930 if (strcmp(tokens[t0 + 3], "pps") != 0) { 1931 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pps"); 1932 return; 1933 } 1934 1935 if (softnic_parser_read_uint32(&p.tm.n_pipes_per_subport, 1936 tokens[t0 + 4]) != 0) { 1937 snprintf(out, out_size, MSG_ARG_INVALID, 1938 "n_pipes_per_subport"); 1939 return; 1940 } 1941 1942 p.action_mask |= 1LLU << RTE_TABLE_ACTION_TM; 1943 t0 += 5; 1944 } /* tm */ 1945 1946 if (t0 < n_tokens && 1947 (strcmp(tokens[t0], "encap") == 0)) { 1948 uint32_t n_extra_tokens = 0; 1949 1950 if (n_tokens < t0 + 2) { 1951 snprintf(out, out_size, MSG_ARG_MISMATCH, 1952 "action profile encap"); 1953 return; 1954 } 1955 1956 if (strcmp(tokens[t0 + 1], "ether") == 0) { 1957 p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_ETHER; 1958 } else if (strcmp(tokens[t0 + 1], "vlan") == 0) { 1959 p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_VLAN; 1960 } else if (strcmp(tokens[t0 + 1], "qinq") == 0) { 1961 p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_QINQ; 1962 } else if (strcmp(tokens[t0 + 1], "mpls") == 0) { 1963 p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_MPLS; 1964 } else if (strcmp(tokens[t0 + 1], "pppoe") == 0) { 1965 p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_PPPOE; 1966 } else if (strcmp(tokens[t0 + 1], "vxlan") == 0) { 1967 if (n_tokens < t0 + 2 + 5) { 1968 snprintf(out, out_size, MSG_ARG_MISMATCH, 1969 "action profile encap vxlan"); 1970 return; 1971 } 1972 1973 if (strcmp(tokens[t0 + 2], "offset") != 0) { 1974 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 1975 "vxlan: offset"); 1976 return; 1977 } 1978 1979 if (softnic_parser_read_uint32(&p.encap.vxlan.data_offset, 1980 tokens[t0 + 2 + 1]) != 0) { 1981 snprintf(out, out_size, MSG_ARG_INVALID, 1982 "vxlan: ether_offset"); 1983 return; 1984 } 1985 1986 if (strcmp(tokens[t0 + 2 + 2], "ipv4") == 0) 1987 p.encap.vxlan.ip_version = 1; 1988 else if (strcmp(tokens[t0 + 2 + 2], "ipv6") == 0) 1989 p.encap.vxlan.ip_version = 0; 1990 else { 1991 snprintf(out, out_size, MSG_ARG_INVALID, 1992 "vxlan: ipv4 or ipv6"); 1993 return; 1994 } 1995 1996 if (strcmp(tokens[t0 + 2 + 3], "vlan") != 0) { 1997 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 1998 "vxlan: vlan"); 1999 return; 2000 } 2001 2002 if (strcmp(tokens[t0 + 2 + 4], "on") == 0) 2003 p.encap.vxlan.vlan = 1; 2004 else if (strcmp(tokens[t0 + 2 + 4], "off") == 0) 2005 p.encap.vxlan.vlan = 0; 2006 else { 2007 snprintf(out, out_size, MSG_ARG_INVALID, 2008 "vxlan: on or off"); 2009 return; 2010 } 2011 2012 p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_VXLAN; 2013 n_extra_tokens = 5; 2014 2015 } else if (strcmp(tokens[t0 + 1], "qinq_pppoe") == 0) { 2016 p.encap.encap_mask = 2017 1LLU << RTE_TABLE_ACTION_ENCAP_QINQ_PPPOE; 2018 } else { 2019 snprintf(out, out_size, MSG_ARG_MISMATCH, "encap"); 2020 return; 2021 } 2022 2023 p.action_mask |= 1LLU << RTE_TABLE_ACTION_ENCAP; 2024 t0 += 2 + n_extra_tokens; 2025 } /* encap */ 2026 2027 if (t0 < n_tokens && 2028 (strcmp(tokens[t0], "nat") == 0)) { 2029 if (n_tokens < t0 + 4) { 2030 snprintf(out, out_size, MSG_ARG_MISMATCH, 2031 "table action profile nat"); 2032 return; 2033 } 2034 2035 if (strcmp(tokens[t0 + 1], "src") == 0) { 2036 p.nat.source_nat = 1; 2037 } else if (strcmp(tokens[t0 + 1], "dst") == 0) { 2038 p.nat.source_nat = 0; 2039 } else { 2040 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 2041 "src or dst"); 2042 return; 2043 } 2044 2045 if (strcmp(tokens[t0 + 2], "proto") != 0) { 2046 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "proto"); 2047 return; 2048 } 2049 2050 if (strcmp(tokens[t0 + 3], "tcp") == 0) { 2051 p.nat.proto = 0x06; 2052 } else if (strcmp(tokens[t0 + 3], "udp") == 0) { 2053 p.nat.proto = 0x11; 2054 } else { 2055 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 2056 "tcp or udp"); 2057 return; 2058 } 2059 2060 p.action_mask |= 1LLU << RTE_TABLE_ACTION_NAT; 2061 t0 += 4; 2062 } /* nat */ 2063 2064 if (t0 < n_tokens && 2065 (strcmp(tokens[t0], "ttl") == 0)) { 2066 if (n_tokens < t0 + 4) { 2067 snprintf(out, out_size, MSG_ARG_MISMATCH, 2068 "table action profile ttl"); 2069 return; 2070 } 2071 2072 if (strcmp(tokens[t0 + 1], "drop") == 0) { 2073 p.ttl.drop = 1; 2074 } else if (strcmp(tokens[t0 + 1], "fwd") == 0) { 2075 p.ttl.drop = 0; 2076 } else { 2077 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 2078 "drop or fwd"); 2079 return; 2080 } 2081 2082 if (strcmp(tokens[t0 + 2], "stats") != 0) { 2083 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats"); 2084 return; 2085 } 2086 2087 if (strcmp(tokens[t0 + 3], "none") == 0) { 2088 p.ttl.n_packets_enabled = 0; 2089 } else if (strcmp(tokens[t0 + 3], "pkts") == 0) { 2090 p.ttl.n_packets_enabled = 1; 2091 } else { 2092 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 2093 "none or pkts"); 2094 return; 2095 } 2096 2097 p.action_mask |= 1LLU << RTE_TABLE_ACTION_TTL; 2098 t0 += 4; 2099 } /* ttl */ 2100 2101 if (t0 < n_tokens && 2102 (strcmp(tokens[t0], "stats") == 0)) { 2103 if (n_tokens < t0 + 2) { 2104 snprintf(out, out_size, MSG_ARG_MISMATCH, 2105 "table action profile stats"); 2106 return; 2107 } 2108 2109 if (strcmp(tokens[t0 + 1], "pkts") == 0) { 2110 p.stats.n_packets_enabled = 1; 2111 p.stats.n_bytes_enabled = 0; 2112 } else if (strcmp(tokens[t0 + 1], "bytes") == 0) { 2113 p.stats.n_packets_enabled = 0; 2114 p.stats.n_bytes_enabled = 1; 2115 } else if (strcmp(tokens[t0 + 1], "both") == 0) { 2116 p.stats.n_packets_enabled = 1; 2117 p.stats.n_bytes_enabled = 1; 2118 } else { 2119 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 2120 "pkts or bytes or both"); 2121 return; 2122 } 2123 2124 p.action_mask |= 1LLU << RTE_TABLE_ACTION_STATS; 2125 t0 += 2; 2126 } /* stats */ 2127 2128 if (t0 < n_tokens && 2129 (strcmp(tokens[t0], "time") == 0)) { 2130 p.action_mask |= 1LLU << RTE_TABLE_ACTION_TIME; 2131 t0 += 1; 2132 } /* time */ 2133 2134 if (t0 < n_tokens && 2135 (strcmp(tokens[t0], "tag") == 0)) { 2136 p.action_mask |= 1LLU << RTE_TABLE_ACTION_TAG; 2137 t0 += 1; 2138 } /* tag */ 2139 2140 if (t0 < n_tokens && 2141 (strcmp(tokens[t0], "decap") == 0)) { 2142 p.action_mask |= 1LLU << RTE_TABLE_ACTION_DECAP; 2143 t0 += 1; 2144 } /* decap */ 2145 2146 if (t0 < n_tokens && (strcmp(tokens[t0], "sym_crypto") == 0)) { 2147 struct softnic_cryptodev *cryptodev; 2148 2149 if (n_tokens < t0 + 5 || 2150 strcmp(tokens[t0 + 1], "dev") || 2151 strcmp(tokens[t0 + 3], "offset")) { 2152 snprintf(out, out_size, MSG_ARG_MISMATCH, 2153 "table action profile sym_crypto"); 2154 return; 2155 } 2156 2157 cryptodev = softnic_cryptodev_find(softnic, tokens[t0 + 2]); 2158 if (cryptodev == NULL) { 2159 snprintf(out, out_size, MSG_ARG_INVALID, 2160 "table action profile sym_crypto"); 2161 return; 2162 } 2163 2164 p.sym_crypto.cryptodev_id = cryptodev->dev_id; 2165 2166 if (softnic_parser_read_uint32(&p.sym_crypto.op_offset, 2167 tokens[t0 + 4]) != 0) { 2168 snprintf(out, out_size, MSG_ARG_INVALID, 2169 "table action profile sym_crypto"); 2170 return; 2171 } 2172 2173 p.sym_crypto.mp_create = cryptodev->mp_create; 2174 p.sym_crypto.mp_init = cryptodev->mp_init; 2175 2176 p.action_mask |= 1LLU << RTE_TABLE_ACTION_SYM_CRYPTO; 2177 2178 t0 += 5; 2179 } /* sym_crypto */ 2180 2181 if (t0 < n_tokens) { 2182 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2183 return; 2184 } 2185 2186 ap = softnic_table_action_profile_create(softnic, name, &p); 2187 if (ap == NULL) { 2188 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 2189 return; 2190 } 2191 } 2192 2193 /** 2194 * pipeline <pipeline_name> 2195 * period <timer_period_ms> 2196 * offset_port_id <offset_port_id> 2197 */ 2198 static void 2199 cmd_pipeline(struct pmd_internals *softnic, 2200 char **tokens, 2201 uint32_t n_tokens, 2202 char *out, 2203 size_t out_size) 2204 { 2205 struct pipeline_params p; 2206 char *name; 2207 struct pipeline *pipeline; 2208 2209 if (n_tokens != 6) { 2210 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2211 return; 2212 } 2213 2214 name = tokens[1]; 2215 2216 if (strcmp(tokens[2], "period") != 0) { 2217 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "period"); 2218 return; 2219 } 2220 2221 if (softnic_parser_read_uint32(&p.timer_period_ms, 2222 tokens[3]) != 0) { 2223 snprintf(out, out_size, MSG_ARG_INVALID, "timer_period_ms"); 2224 return; 2225 } 2226 2227 if (strcmp(tokens[4], "offset_port_id") != 0) { 2228 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset_port_id"); 2229 return; 2230 } 2231 2232 if (softnic_parser_read_uint32(&p.offset_port_id, 2233 tokens[5]) != 0) { 2234 snprintf(out, out_size, MSG_ARG_INVALID, "offset_port_id"); 2235 return; 2236 } 2237 2238 pipeline = softnic_pipeline_create(softnic, name, &p); 2239 if (pipeline == NULL) { 2240 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 2241 return; 2242 } 2243 } 2244 2245 /** 2246 * pipeline <pipeline_name> port in 2247 * bsz <burst_size> 2248 * link <link_name> rxq <queue_id> 2249 * | swq <swq_name> 2250 * | tmgr <tmgr_name> 2251 * | tap <tap_name> mempool <mempool_name> mtu <mtu> 2252 * | source mempool <mempool_name> file <file_name> bpp <n_bytes_per_pkt> 2253 * | cryptodev <cryptodev_name> rxq <queue_id> 2254 * [action <port_in_action_profile_name>] 2255 * [disabled] 2256 */ 2257 static void 2258 cmd_pipeline_port_in(struct pmd_internals *softnic, 2259 char **tokens, 2260 uint32_t n_tokens, 2261 char *out, 2262 size_t out_size) 2263 { 2264 struct softnic_port_in_params p; 2265 char *pipeline_name; 2266 uint32_t t0; 2267 int enabled, status; 2268 2269 memset(&p, 0, sizeof(p)); 2270 2271 if (n_tokens < 7) { 2272 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2273 return; 2274 } 2275 2276 pipeline_name = tokens[1]; 2277 2278 if (strcmp(tokens[2], "port") != 0) { 2279 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 2280 return; 2281 } 2282 2283 if (strcmp(tokens[3], "in") != 0) { 2284 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in"); 2285 return; 2286 } 2287 2288 if (strcmp(tokens[4], "bsz") != 0) { 2289 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz"); 2290 return; 2291 } 2292 2293 if (softnic_parser_read_uint32(&p.burst_size, tokens[5]) != 0) { 2294 snprintf(out, out_size, MSG_ARG_INVALID, "burst_size"); 2295 return; 2296 } 2297 2298 t0 = 6; 2299 2300 if (strcmp(tokens[t0], "link") == 0) { 2301 if (n_tokens < t0 + 4) { 2302 snprintf(out, out_size, MSG_ARG_MISMATCH, 2303 "pipeline port in link"); 2304 return; 2305 } 2306 2307 p.type = PORT_IN_RXQ; 2308 2309 strlcpy(p.dev_name, tokens[t0 + 1], sizeof(p.dev_name)); 2310 2311 if (strcmp(tokens[t0 + 2], "rxq") != 0) { 2312 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rxq"); 2313 return; 2314 } 2315 2316 if (softnic_parser_read_uint16(&p.rxq.queue_id, 2317 tokens[t0 + 3]) != 0) { 2318 snprintf(out, out_size, MSG_ARG_INVALID, 2319 "queue_id"); 2320 return; 2321 } 2322 t0 += 4; 2323 } else if (strcmp(tokens[t0], "swq") == 0) { 2324 if (n_tokens < t0 + 2) { 2325 snprintf(out, out_size, MSG_ARG_MISMATCH, 2326 "pipeline port in swq"); 2327 return; 2328 } 2329 2330 p.type = PORT_IN_SWQ; 2331 2332 strlcpy(p.dev_name, tokens[t0 + 1], sizeof(p.dev_name)); 2333 2334 t0 += 2; 2335 } else if (strcmp(tokens[t0], "tmgr") == 0) { 2336 if (n_tokens < t0 + 2) { 2337 snprintf(out, out_size, MSG_ARG_MISMATCH, 2338 "pipeline port in tmgr"); 2339 return; 2340 } 2341 2342 p.type = PORT_IN_TMGR; 2343 2344 strlcpy(p.dev_name, tokens[t0 + 1], sizeof(p.dev_name)); 2345 2346 t0 += 2; 2347 } else if (strcmp(tokens[t0], "tap") == 0) { 2348 if (n_tokens < t0 + 6) { 2349 snprintf(out, out_size, MSG_ARG_MISMATCH, 2350 "pipeline port in tap"); 2351 return; 2352 } 2353 2354 p.type = PORT_IN_TAP; 2355 2356 strlcpy(p.dev_name, tokens[t0 + 1], sizeof(p.dev_name)); 2357 2358 if (strcmp(tokens[t0 + 2], "mempool") != 0) { 2359 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 2360 "mempool"); 2361 return; 2362 } 2363 2364 p.tap.mempool_name = tokens[t0 + 3]; 2365 2366 if (strcmp(tokens[t0 + 4], "mtu") != 0) { 2367 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 2368 "mtu"); 2369 return; 2370 } 2371 2372 if (softnic_parser_read_uint32(&p.tap.mtu, 2373 tokens[t0 + 5]) != 0) { 2374 snprintf(out, out_size, MSG_ARG_INVALID, "mtu"); 2375 return; 2376 } 2377 2378 t0 += 6; 2379 } else if (strcmp(tokens[t0], "source") == 0) { 2380 if (n_tokens < t0 + 6) { 2381 snprintf(out, out_size, MSG_ARG_MISMATCH, 2382 "pipeline port in source"); 2383 return; 2384 } 2385 2386 p.type = PORT_IN_SOURCE; 2387 2388 if (strcmp(tokens[t0 + 1], "mempool") != 0) { 2389 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 2390 "mempool"); 2391 return; 2392 } 2393 2394 p.source.mempool_name = tokens[t0 + 2]; 2395 2396 if (strcmp(tokens[t0 + 3], "file") != 0) { 2397 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 2398 "file"); 2399 return; 2400 } 2401 2402 p.source.file_name = tokens[t0 + 4]; 2403 2404 if (strcmp(tokens[t0 + 5], "bpp") != 0) { 2405 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 2406 "bpp"); 2407 return; 2408 } 2409 2410 if (softnic_parser_read_uint32(&p.source.n_bytes_per_pkt, 2411 tokens[t0 + 6]) != 0) { 2412 snprintf(out, out_size, MSG_ARG_INVALID, 2413 "n_bytes_per_pkt"); 2414 return; 2415 } 2416 2417 t0 += 7; 2418 } else if (strcmp(tokens[t0], "cryptodev") == 0) { 2419 if (n_tokens < t0 + 3) { 2420 snprintf(out, out_size, MSG_ARG_MISMATCH, 2421 "pipeline port in cryptodev"); 2422 return; 2423 } 2424 2425 p.type = PORT_IN_CRYPTODEV; 2426 2427 strlcpy(p.dev_name, tokens[t0 + 1], sizeof(p.dev_name)); 2428 if (softnic_parser_read_uint16(&p.rxq.queue_id, 2429 tokens[t0 + 3]) != 0) { 2430 snprintf(out, out_size, MSG_ARG_INVALID, 2431 "rxq"); 2432 return; 2433 } 2434 2435 p.cryptodev.arg_callback = NULL; 2436 p.cryptodev.f_callback = NULL; 2437 2438 t0 += 4; 2439 } else { 2440 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]); 2441 return; 2442 } 2443 2444 if (n_tokens > t0 && 2445 (strcmp(tokens[t0], "action") == 0)) { 2446 if (n_tokens < t0 + 2) { 2447 snprintf(out, out_size, MSG_ARG_MISMATCH, "action"); 2448 return; 2449 } 2450 2451 strlcpy(p.action_profile_name, tokens[t0 + 1], 2452 sizeof(p.action_profile_name)); 2453 2454 t0 += 2; 2455 } 2456 2457 enabled = 1; 2458 if (n_tokens > t0 && 2459 (strcmp(tokens[t0], "disabled") == 0)) { 2460 enabled = 0; 2461 2462 t0 += 1; 2463 } 2464 2465 if (n_tokens != t0) { 2466 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2467 return; 2468 } 2469 2470 status = softnic_pipeline_port_in_create(softnic, 2471 pipeline_name, 2472 &p, 2473 enabled); 2474 if (status) { 2475 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 2476 return; 2477 } 2478 } 2479 2480 /** 2481 * pipeline <pipeline_name> port out 2482 * bsz <burst_size> 2483 * link <link_name> txq <txq_id> 2484 * | swq <swq_name> 2485 * | tmgr <tmgr_name> 2486 * | tap <tap_name> 2487 * | sink [file <file_name> pkts <max_n_pkts>] 2488 * | cryptodev <cryptodev_name> txq <txq_id> offset <crypto_op_offset> 2489 */ 2490 static void 2491 cmd_pipeline_port_out(struct pmd_internals *softnic, 2492 char **tokens, 2493 uint32_t n_tokens, 2494 char *out, 2495 size_t out_size) 2496 { 2497 struct softnic_port_out_params p; 2498 char *pipeline_name; 2499 int status; 2500 2501 memset(&p, 0, sizeof(p)); 2502 2503 if (n_tokens < 7) { 2504 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2505 return; 2506 } 2507 2508 pipeline_name = tokens[1]; 2509 2510 if (strcmp(tokens[2], "port") != 0) { 2511 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 2512 return; 2513 } 2514 2515 if (strcmp(tokens[3], "out") != 0) { 2516 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "out"); 2517 return; 2518 } 2519 2520 if (strcmp(tokens[4], "bsz") != 0) { 2521 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz"); 2522 return; 2523 } 2524 2525 if (softnic_parser_read_uint32(&p.burst_size, tokens[5]) != 0) { 2526 snprintf(out, out_size, MSG_ARG_INVALID, "burst_size"); 2527 return; 2528 } 2529 2530 if (strcmp(tokens[6], "link") == 0) { 2531 if (n_tokens != 10) { 2532 snprintf(out, out_size, MSG_ARG_MISMATCH, 2533 "pipeline port out link"); 2534 return; 2535 } 2536 2537 p.type = PORT_OUT_TXQ; 2538 2539 strlcpy(p.dev_name, tokens[7], sizeof(p.dev_name)); 2540 2541 if (strcmp(tokens[8], "txq") != 0) { 2542 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "txq"); 2543 return; 2544 } 2545 2546 if (softnic_parser_read_uint16(&p.txq.queue_id, 2547 tokens[9]) != 0) { 2548 snprintf(out, out_size, MSG_ARG_INVALID, "queue_id"); 2549 return; 2550 } 2551 } else if (strcmp(tokens[6], "swq") == 0) { 2552 if (n_tokens != 8) { 2553 snprintf(out, out_size, MSG_ARG_MISMATCH, 2554 "pipeline port out swq"); 2555 return; 2556 } 2557 2558 p.type = PORT_OUT_SWQ; 2559 2560 strlcpy(p.dev_name, tokens[7], sizeof(p.dev_name)); 2561 } else if (strcmp(tokens[6], "tmgr") == 0) { 2562 if (n_tokens != 8) { 2563 snprintf(out, out_size, MSG_ARG_MISMATCH, 2564 "pipeline port out tmgr"); 2565 return; 2566 } 2567 2568 p.type = PORT_OUT_TMGR; 2569 2570 strlcpy(p.dev_name, tokens[7], sizeof(p.dev_name)); 2571 } else if (strcmp(tokens[6], "tap") == 0) { 2572 if (n_tokens != 8) { 2573 snprintf(out, out_size, MSG_ARG_MISMATCH, 2574 "pipeline port out tap"); 2575 return; 2576 } 2577 2578 p.type = PORT_OUT_TAP; 2579 2580 strlcpy(p.dev_name, tokens[7], sizeof(p.dev_name)); 2581 } else if (strcmp(tokens[6], "sink") == 0) { 2582 if ((n_tokens != 7) && (n_tokens != 11)) { 2583 snprintf(out, out_size, MSG_ARG_MISMATCH, 2584 "pipeline port out sink"); 2585 return; 2586 } 2587 2588 p.type = PORT_OUT_SINK; 2589 2590 if (n_tokens == 7) { 2591 p.sink.file_name = NULL; 2592 p.sink.max_n_pkts = 0; 2593 } else { 2594 if (strcmp(tokens[7], "file") != 0) { 2595 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 2596 "file"); 2597 return; 2598 } 2599 2600 p.sink.file_name = tokens[8]; 2601 2602 if (strcmp(tokens[9], "pkts") != 0) { 2603 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pkts"); 2604 return; 2605 } 2606 2607 if (softnic_parser_read_uint32(&p.sink.max_n_pkts, 2608 tokens[10]) != 0) { 2609 snprintf(out, out_size, MSG_ARG_INVALID, "max_n_pkts"); 2610 return; 2611 } 2612 } 2613 } else if (strcmp(tokens[6], "cryptodev") == 0) { 2614 if (n_tokens != 12) { 2615 snprintf(out, out_size, MSG_ARG_MISMATCH, 2616 "pipeline port out cryptodev"); 2617 return; 2618 } 2619 2620 p.type = PORT_OUT_CRYPTODEV; 2621 2622 strlcpy(p.dev_name, tokens[7], sizeof(p.dev_name)); 2623 2624 if (strcmp(tokens[8], "txq")) { 2625 snprintf(out, out_size, MSG_ARG_MISMATCH, 2626 "pipeline port out cryptodev"); 2627 return; 2628 } 2629 2630 if (softnic_parser_read_uint16(&p.cryptodev.queue_id, tokens[9]) 2631 != 0) { 2632 snprintf(out, out_size, MSG_ARG_INVALID, "queue_id"); 2633 return; 2634 } 2635 2636 if (strcmp(tokens[10], "offset")) { 2637 snprintf(out, out_size, MSG_ARG_MISMATCH, 2638 "pipeline port out cryptodev"); 2639 return; 2640 } 2641 2642 if (softnic_parser_read_uint32(&p.cryptodev.op_offset, 2643 tokens[11]) != 0) { 2644 snprintf(out, out_size, MSG_ARG_INVALID, "queue_id"); 2645 return; 2646 } 2647 } else { 2648 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]); 2649 return; 2650 } 2651 2652 status = softnic_pipeline_port_out_create(softnic, pipeline_name, &p); 2653 if (status) { 2654 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 2655 return; 2656 } 2657 } 2658 2659 /** 2660 * pipeline <pipeline_name> table 2661 * match 2662 * acl 2663 * ipv4 | ipv6 2664 * offset <ip_header_offset> 2665 * size <n_rules> 2666 * | array 2667 * offset <key_offset> 2668 * size <n_keys> 2669 * | hash 2670 * ext | lru 2671 * key <key_size> 2672 * mask <key_mask> 2673 * offset <key_offset> 2674 * buckets <n_buckets> 2675 * size <n_keys> 2676 * | lpm 2677 * ipv4 | ipv6 2678 * offset <ip_header_offset> 2679 * size <n_rules> 2680 * | stub 2681 * [action <table_action_profile_name>] 2682 */ 2683 static void 2684 cmd_pipeline_table(struct pmd_internals *softnic, 2685 char **tokens, 2686 uint32_t n_tokens, 2687 char *out, 2688 size_t out_size) 2689 { 2690 struct softnic_table_params p; 2691 char *pipeline_name; 2692 uint32_t t0; 2693 int status; 2694 2695 memset(&p, 0, sizeof(p)); 2696 2697 if (n_tokens < 5) { 2698 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2699 return; 2700 } 2701 2702 pipeline_name = tokens[1]; 2703 2704 if (strcmp(tokens[2], "table") != 0) { 2705 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); 2706 return; 2707 } 2708 2709 if (strcmp(tokens[3], "match") != 0) { 2710 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match"); 2711 return; 2712 } 2713 2714 t0 = 4; 2715 if (strcmp(tokens[t0], "acl") == 0) { 2716 if (n_tokens < t0 + 6) { 2717 snprintf(out, out_size, MSG_ARG_MISMATCH, 2718 "pipeline table acl"); 2719 return; 2720 } 2721 2722 p.match_type = TABLE_ACL; 2723 2724 if (strcmp(tokens[t0 + 1], "ipv4") == 0) { 2725 p.match.acl.ip_version = 1; 2726 } else if (strcmp(tokens[t0 + 1], "ipv6") == 0) { 2727 p.match.acl.ip_version = 0; 2728 } else { 2729 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 2730 "ipv4 or ipv6"); 2731 return; 2732 } 2733 2734 if (strcmp(tokens[t0 + 2], "offset") != 0) { 2735 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); 2736 return; 2737 } 2738 2739 if (softnic_parser_read_uint32(&p.match.acl.ip_header_offset, 2740 tokens[t0 + 3]) != 0) { 2741 snprintf(out, out_size, MSG_ARG_INVALID, 2742 "ip_header_offset"); 2743 return; 2744 } 2745 2746 if (strcmp(tokens[t0 + 4], "size") != 0) { 2747 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size"); 2748 return; 2749 } 2750 2751 if (softnic_parser_read_uint32(&p.match.acl.n_rules, 2752 tokens[t0 + 5]) != 0) { 2753 snprintf(out, out_size, MSG_ARG_INVALID, "n_rules"); 2754 return; 2755 } 2756 2757 t0 += 6; 2758 } else if (strcmp(tokens[t0], "array") == 0) { 2759 if (n_tokens < t0 + 5) { 2760 snprintf(out, out_size, MSG_ARG_MISMATCH, 2761 "pipeline table array"); 2762 return; 2763 } 2764 2765 p.match_type = TABLE_ARRAY; 2766 2767 if (strcmp(tokens[t0 + 1], "offset") != 0) { 2768 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); 2769 return; 2770 } 2771 2772 if (softnic_parser_read_uint32(&p.match.array.key_offset, 2773 tokens[t0 + 2]) != 0) { 2774 snprintf(out, out_size, MSG_ARG_INVALID, "key_offset"); 2775 return; 2776 } 2777 2778 if (strcmp(tokens[t0 + 3], "size") != 0) { 2779 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size"); 2780 return; 2781 } 2782 2783 if (softnic_parser_read_uint32(&p.match.array.n_keys, 2784 tokens[t0 + 4]) != 0) { 2785 snprintf(out, out_size, MSG_ARG_INVALID, "n_keys"); 2786 return; 2787 } 2788 2789 t0 += 5; 2790 } else if (strcmp(tokens[t0], "hash") == 0) { 2791 uint32_t key_mask_size = TABLE_RULE_MATCH_SIZE_MAX; 2792 2793 if (n_tokens < t0 + 12) { 2794 snprintf(out, out_size, MSG_ARG_MISMATCH, 2795 "pipeline table hash"); 2796 return; 2797 } 2798 2799 p.match_type = TABLE_HASH; 2800 2801 if (strcmp(tokens[t0 + 1], "ext") == 0) { 2802 p.match.hash.extendable_bucket = 1; 2803 } else if (strcmp(tokens[t0 + 1], "lru") == 0) { 2804 p.match.hash.extendable_bucket = 0; 2805 } else { 2806 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 2807 "ext or lru"); 2808 return; 2809 } 2810 2811 if (strcmp(tokens[t0 + 2], "key") != 0) { 2812 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "key"); 2813 return; 2814 } 2815 2816 if ((softnic_parser_read_uint32(&p.match.hash.key_size, 2817 tokens[t0 + 3]) != 0) || 2818 p.match.hash.key_size == 0 || 2819 p.match.hash.key_size > TABLE_RULE_MATCH_SIZE_MAX) { 2820 snprintf(out, out_size, MSG_ARG_INVALID, "key_size"); 2821 return; 2822 } 2823 2824 if (strcmp(tokens[t0 + 4], "mask") != 0) { 2825 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask"); 2826 return; 2827 } 2828 2829 if ((softnic_parse_hex_string(tokens[t0 + 5], 2830 p.match.hash.key_mask, &key_mask_size) != 0) || 2831 key_mask_size != p.match.hash.key_size) { 2832 snprintf(out, out_size, MSG_ARG_INVALID, "key_mask"); 2833 return; 2834 } 2835 2836 if (strcmp(tokens[t0 + 6], "offset") != 0) { 2837 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); 2838 return; 2839 } 2840 2841 if (softnic_parser_read_uint32(&p.match.hash.key_offset, 2842 tokens[t0 + 7]) != 0) { 2843 snprintf(out, out_size, MSG_ARG_INVALID, "key_offset"); 2844 return; 2845 } 2846 2847 if (strcmp(tokens[t0 + 8], "buckets") != 0) { 2848 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "buckets"); 2849 return; 2850 } 2851 2852 if (softnic_parser_read_uint32(&p.match.hash.n_buckets, 2853 tokens[t0 + 9]) != 0) { 2854 snprintf(out, out_size, MSG_ARG_INVALID, "n_buckets"); 2855 return; 2856 } 2857 2858 if (strcmp(tokens[t0 + 10], "size") != 0) { 2859 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size"); 2860 return; 2861 } 2862 2863 if (softnic_parser_read_uint32(&p.match.hash.n_keys, 2864 tokens[t0 + 11]) != 0) { 2865 snprintf(out, out_size, MSG_ARG_INVALID, "n_keys"); 2866 return; 2867 } 2868 2869 t0 += 12; 2870 } else if (strcmp(tokens[t0], "lpm") == 0) { 2871 if (n_tokens < t0 + 6) { 2872 snprintf(out, out_size, MSG_ARG_MISMATCH, 2873 "pipeline table lpm"); 2874 return; 2875 } 2876 2877 p.match_type = TABLE_LPM; 2878 2879 if (strcmp(tokens[t0 + 1], "ipv4") == 0) { 2880 p.match.lpm.key_size = 4; 2881 } else if (strcmp(tokens[t0 + 1], "ipv6") == 0) { 2882 p.match.lpm.key_size = 16; 2883 } else { 2884 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 2885 "ipv4 or ipv6"); 2886 return; 2887 } 2888 2889 if (strcmp(tokens[t0 + 2], "offset") != 0) { 2890 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); 2891 return; 2892 } 2893 2894 if (softnic_parser_read_uint32(&p.match.lpm.key_offset, 2895 tokens[t0 + 3]) != 0) { 2896 snprintf(out, out_size, MSG_ARG_INVALID, "key_offset"); 2897 return; 2898 } 2899 2900 if (strcmp(tokens[t0 + 4], "size") != 0) { 2901 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size"); 2902 return; 2903 } 2904 2905 if (softnic_parser_read_uint32(&p.match.lpm.n_rules, 2906 tokens[t0 + 5]) != 0) { 2907 snprintf(out, out_size, MSG_ARG_INVALID, "n_rules"); 2908 return; 2909 } 2910 2911 t0 += 6; 2912 } else if (strcmp(tokens[t0], "stub") == 0) { 2913 p.match_type = TABLE_STUB; 2914 2915 t0 += 1; 2916 } else { 2917 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]); 2918 return; 2919 } 2920 2921 if (n_tokens > t0 && 2922 (strcmp(tokens[t0], "action") == 0)) { 2923 if (n_tokens < t0 + 2) { 2924 snprintf(out, out_size, MSG_ARG_MISMATCH, "action"); 2925 return; 2926 } 2927 2928 strlcpy(p.action_profile_name, tokens[t0 + 1], 2929 sizeof(p.action_profile_name)); 2930 2931 t0 += 2; 2932 } 2933 2934 if (n_tokens > t0) { 2935 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2936 return; 2937 } 2938 2939 status = softnic_pipeline_table_create(softnic, pipeline_name, &p); 2940 if (status) { 2941 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 2942 return; 2943 } 2944 } 2945 2946 /** 2947 * pipeline <pipeline_name> port in <port_id> table <table_id> 2948 */ 2949 static void 2950 cmd_pipeline_port_in_table(struct pmd_internals *softnic, 2951 char **tokens, 2952 uint32_t n_tokens, 2953 char *out, 2954 size_t out_size) 2955 { 2956 char *pipeline_name; 2957 uint32_t port_id, table_id; 2958 int status; 2959 2960 if (n_tokens != 7) { 2961 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 2962 return; 2963 } 2964 2965 pipeline_name = tokens[1]; 2966 2967 if (strcmp(tokens[2], "port") != 0) { 2968 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 2969 return; 2970 } 2971 2972 if (strcmp(tokens[3], "in") != 0) { 2973 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in"); 2974 return; 2975 } 2976 2977 if (softnic_parser_read_uint32(&port_id, tokens[4]) != 0) { 2978 snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); 2979 return; 2980 } 2981 2982 if (strcmp(tokens[5], "table") != 0) { 2983 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); 2984 return; 2985 } 2986 2987 if (softnic_parser_read_uint32(&table_id, tokens[6]) != 0) { 2988 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 2989 return; 2990 } 2991 2992 status = softnic_pipeline_port_in_connect_to_table(softnic, 2993 pipeline_name, 2994 port_id, 2995 table_id); 2996 if (status) { 2997 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 2998 return; 2999 } 3000 } 3001 3002 /** 3003 * pipeline <pipeline_name> port in <port_id> stats read [clear] 3004 */ 3005 3006 #define MSG_PIPELINE_PORT_IN_STATS \ 3007 "Pkts in: %" PRIu64 "\n" \ 3008 "Pkts dropped by AH: %" PRIu64 "\n" \ 3009 "Pkts dropped by other: %" PRIu64 "\n" 3010 3011 static void 3012 cmd_pipeline_port_in_stats(struct pmd_internals *softnic, 3013 char **tokens, 3014 uint32_t n_tokens, 3015 char *out, 3016 size_t out_size) 3017 { 3018 struct rte_pipeline_port_in_stats stats; 3019 char *pipeline_name; 3020 uint32_t port_id; 3021 int clear, status; 3022 3023 if (n_tokens != 7 && 3024 n_tokens != 8) { 3025 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 3026 return; 3027 } 3028 3029 pipeline_name = tokens[1]; 3030 3031 if (strcmp(tokens[2], "port") != 0) { 3032 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 3033 return; 3034 } 3035 3036 if (strcmp(tokens[3], "in") != 0) { 3037 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in"); 3038 return; 3039 } 3040 3041 if (softnic_parser_read_uint32(&port_id, tokens[4]) != 0) { 3042 snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); 3043 return; 3044 } 3045 3046 if (strcmp(tokens[5], "stats") != 0) { 3047 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats"); 3048 return; 3049 } 3050 3051 if (strcmp(tokens[6], "read") != 0) { 3052 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "read"); 3053 return; 3054 } 3055 3056 clear = 0; 3057 if (n_tokens == 8) { 3058 if (strcmp(tokens[7], "clear") != 0) { 3059 snprintf(out, out_size, MSG_ARG_INVALID, "clear"); 3060 return; 3061 } 3062 3063 clear = 1; 3064 } 3065 3066 status = softnic_pipeline_port_in_stats_read(softnic, 3067 pipeline_name, 3068 port_id, 3069 &stats, 3070 clear); 3071 if (status) { 3072 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 3073 return; 3074 } 3075 3076 snprintf(out, out_size, MSG_PIPELINE_PORT_IN_STATS, 3077 stats.stats.n_pkts_in, 3078 stats.n_pkts_dropped_by_ah, 3079 stats.stats.n_pkts_drop); 3080 } 3081 3082 /** 3083 * pipeline <pipeline_name> port in <port_id> enable 3084 */ 3085 static void 3086 cmd_softnic_pipeline_port_in_enable(struct pmd_internals *softnic, 3087 char **tokens, 3088 uint32_t n_tokens, 3089 char *out, 3090 size_t out_size) 3091 { 3092 char *pipeline_name; 3093 uint32_t port_id; 3094 int status; 3095 3096 if (n_tokens != 6) { 3097 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 3098 return; 3099 } 3100 3101 pipeline_name = tokens[1]; 3102 3103 if (strcmp(tokens[2], "port") != 0) { 3104 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 3105 return; 3106 } 3107 3108 if (strcmp(tokens[3], "in") != 0) { 3109 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in"); 3110 return; 3111 } 3112 3113 if (softnic_parser_read_uint32(&port_id, tokens[4]) != 0) { 3114 snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); 3115 return; 3116 } 3117 3118 if (strcmp(tokens[5], "enable") != 0) { 3119 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "enable"); 3120 return; 3121 } 3122 3123 status = softnic_pipeline_port_in_enable(softnic, pipeline_name, port_id); 3124 if (status) { 3125 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 3126 return; 3127 } 3128 } 3129 3130 /** 3131 * pipeline <pipeline_name> port in <port_id> disable 3132 */ 3133 static void 3134 cmd_softnic_pipeline_port_in_disable(struct pmd_internals *softnic, 3135 char **tokens, 3136 uint32_t n_tokens, 3137 char *out, 3138 size_t out_size) 3139 { 3140 char *pipeline_name; 3141 uint32_t port_id; 3142 int status; 3143 3144 if (n_tokens != 6) { 3145 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 3146 return; 3147 } 3148 3149 pipeline_name = tokens[1]; 3150 3151 if (strcmp(tokens[2], "port") != 0) { 3152 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 3153 return; 3154 } 3155 3156 if (strcmp(tokens[3], "in") != 0) { 3157 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in"); 3158 return; 3159 } 3160 3161 if (softnic_parser_read_uint32(&port_id, tokens[4]) != 0) { 3162 snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); 3163 return; 3164 } 3165 3166 if (strcmp(tokens[5], "disable") != 0) { 3167 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "disable"); 3168 return; 3169 } 3170 3171 status = softnic_pipeline_port_in_disable(softnic, pipeline_name, port_id); 3172 if (status) { 3173 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 3174 return; 3175 } 3176 } 3177 3178 /** 3179 * pipeline <pipeline_name> port out <port_id> stats read [clear] 3180 */ 3181 #define MSG_PIPELINE_PORT_OUT_STATS \ 3182 "Pkts in: %" PRIu64 "\n" \ 3183 "Pkts dropped by AH: %" PRIu64 "\n" \ 3184 "Pkts dropped by other: %" PRIu64 "\n" 3185 3186 static void 3187 cmd_pipeline_port_out_stats(struct pmd_internals *softnic, 3188 char **tokens, 3189 uint32_t n_tokens, 3190 char *out, 3191 size_t out_size) 3192 { 3193 struct rte_pipeline_port_out_stats stats; 3194 char *pipeline_name; 3195 uint32_t port_id; 3196 int clear, status; 3197 3198 if (n_tokens != 7 && 3199 n_tokens != 8) { 3200 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 3201 return; 3202 } 3203 3204 pipeline_name = tokens[1]; 3205 3206 if (strcmp(tokens[2], "port") != 0) { 3207 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 3208 return; 3209 } 3210 3211 if (strcmp(tokens[3], "out") != 0) { 3212 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "out"); 3213 return; 3214 } 3215 3216 if (softnic_parser_read_uint32(&port_id, tokens[4]) != 0) { 3217 snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); 3218 return; 3219 } 3220 3221 if (strcmp(tokens[5], "stats") != 0) { 3222 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats"); 3223 return; 3224 } 3225 3226 if (strcmp(tokens[6], "read") != 0) { 3227 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "read"); 3228 return; 3229 } 3230 3231 clear = 0; 3232 if (n_tokens == 8) { 3233 if (strcmp(tokens[7], "clear") != 0) { 3234 snprintf(out, out_size, MSG_ARG_INVALID, "clear"); 3235 return; 3236 } 3237 3238 clear = 1; 3239 } 3240 3241 status = softnic_pipeline_port_out_stats_read(softnic, 3242 pipeline_name, 3243 port_id, 3244 &stats, 3245 clear); 3246 if (status) { 3247 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 3248 return; 3249 } 3250 3251 snprintf(out, out_size, MSG_PIPELINE_PORT_OUT_STATS, 3252 stats.stats.n_pkts_in, 3253 stats.n_pkts_dropped_by_ah, 3254 stats.stats.n_pkts_drop); 3255 } 3256 3257 /** 3258 * pipeline <pipeline_name> table <table_id> stats read [clear] 3259 */ 3260 #define MSG_PIPELINE_TABLE_STATS \ 3261 "Pkts in: %" PRIu64 "\n" \ 3262 "Pkts in with lookup miss: %" PRIu64 "\n" \ 3263 "Pkts in with lookup hit dropped by AH: %" PRIu64 "\n" \ 3264 "Pkts in with lookup hit dropped by others: %" PRIu64 "\n" \ 3265 "Pkts in with lookup miss dropped by AH: %" PRIu64 "\n" \ 3266 "Pkts in with lookup miss dropped by others: %" PRIu64 "\n" 3267 3268 static void 3269 cmd_pipeline_table_stats(struct pmd_internals *softnic, 3270 char **tokens, 3271 uint32_t n_tokens, 3272 char *out, 3273 size_t out_size) 3274 { 3275 struct rte_pipeline_table_stats stats; 3276 char *pipeline_name; 3277 uint32_t table_id; 3278 int clear, status; 3279 3280 if (n_tokens != 6 && 3281 n_tokens != 7) { 3282 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 3283 return; 3284 } 3285 3286 pipeline_name = tokens[1]; 3287 3288 if (strcmp(tokens[2], "table") != 0) { 3289 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 3290 return; 3291 } 3292 3293 if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) { 3294 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 3295 return; 3296 } 3297 3298 if (strcmp(tokens[4], "stats") != 0) { 3299 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats"); 3300 return; 3301 } 3302 3303 if (strcmp(tokens[5], "read") != 0) { 3304 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "read"); 3305 return; 3306 } 3307 3308 clear = 0; 3309 if (n_tokens == 7) { 3310 if (strcmp(tokens[6], "clear") != 0) { 3311 snprintf(out, out_size, MSG_ARG_INVALID, "clear"); 3312 return; 3313 } 3314 3315 clear = 1; 3316 } 3317 3318 status = softnic_pipeline_table_stats_read(softnic, 3319 pipeline_name, 3320 table_id, 3321 &stats, 3322 clear); 3323 if (status) { 3324 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 3325 return; 3326 } 3327 3328 snprintf(out, out_size, MSG_PIPELINE_TABLE_STATS, 3329 stats.stats.n_pkts_in, 3330 stats.stats.n_pkts_lookup_miss, 3331 stats.n_pkts_dropped_by_lkp_hit_ah, 3332 stats.n_pkts_dropped_lkp_hit, 3333 stats.n_pkts_dropped_by_lkp_miss_ah, 3334 stats.n_pkts_dropped_lkp_miss); 3335 } 3336 3337 /** 3338 * <match> ::= 3339 * 3340 * match 3341 * acl 3342 * priority <priority> 3343 * ipv4 | ipv6 <sa> <sa_depth> <da> <da_depth> 3344 * <sp0> <sp1> <dp0> <dp1> <proto> 3345 * | array <pos> 3346 * | hash 3347 * raw <key> 3348 * | ipv4_5tuple <sa> <da> <sp> <dp> <proto> 3349 * | ipv6_5tuple <sa> <da> <sp> <dp> <proto> 3350 * | ipv4_addr <addr> 3351 * | ipv6_addr <addr> 3352 * | qinq <svlan> <cvlan> 3353 * | lpm 3354 * ipv4 | ipv6 <addr> <depth> 3355 */ 3356 struct pkt_key_qinq { 3357 uint16_t ethertype_svlan; 3358 uint16_t svlan; 3359 uint16_t ethertype_cvlan; 3360 uint16_t cvlan; 3361 } __attribute__((__packed__)); 3362 3363 struct pkt_key_ipv4_5tuple { 3364 uint8_t time_to_live; 3365 uint8_t proto; 3366 uint16_t hdr_checksum; 3367 uint32_t sa; 3368 uint32_t da; 3369 uint16_t sp; 3370 uint16_t dp; 3371 } __attribute__((__packed__)); 3372 3373 struct pkt_key_ipv6_5tuple { 3374 uint16_t payload_length; 3375 uint8_t proto; 3376 uint8_t hop_limit; 3377 uint8_t sa[16]; 3378 uint8_t da[16]; 3379 uint16_t sp; 3380 uint16_t dp; 3381 } __attribute__((__packed__)); 3382 3383 struct pkt_key_ipv4_addr { 3384 uint32_t addr; 3385 } __attribute__((__packed__)); 3386 3387 struct pkt_key_ipv6_addr { 3388 uint8_t addr[16]; 3389 } __attribute__((__packed__)); 3390 3391 static uint32_t 3392 parse_match(char **tokens, 3393 uint32_t n_tokens, 3394 char *out, 3395 size_t out_size, 3396 struct softnic_table_rule_match *m) 3397 { 3398 memset(m, 0, sizeof(*m)); 3399 3400 if (n_tokens < 2) 3401 return 0; 3402 3403 if (strcmp(tokens[0], "match") != 0) { 3404 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match"); 3405 return 0; 3406 } 3407 3408 if (strcmp(tokens[1], "acl") == 0) { 3409 if (n_tokens < 14) { 3410 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 3411 return 0; 3412 } 3413 3414 m->match_type = TABLE_ACL; 3415 3416 if (strcmp(tokens[2], "priority") != 0) { 3417 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "priority"); 3418 return 0; 3419 } 3420 3421 if (softnic_parser_read_uint32(&m->match.acl.priority, 3422 tokens[3]) != 0) { 3423 snprintf(out, out_size, MSG_ARG_INVALID, "priority"); 3424 return 0; 3425 } 3426 3427 if (strcmp(tokens[4], "ipv4") == 0) { 3428 struct in_addr saddr, daddr; 3429 3430 m->match.acl.ip_version = 1; 3431 3432 if (softnic_parse_ipv4_addr(tokens[5], &saddr) != 0) { 3433 snprintf(out, out_size, MSG_ARG_INVALID, "sa"); 3434 return 0; 3435 } 3436 m->match.acl.ipv4.sa = rte_be_to_cpu_32(saddr.s_addr); 3437 3438 if (softnic_parse_ipv4_addr(tokens[7], &daddr) != 0) { 3439 snprintf(out, out_size, MSG_ARG_INVALID, "da"); 3440 return 0; 3441 } 3442 m->match.acl.ipv4.da = rte_be_to_cpu_32(daddr.s_addr); 3443 } else if (strcmp(tokens[4], "ipv6") == 0) { 3444 struct in6_addr saddr, daddr; 3445 3446 m->match.acl.ip_version = 0; 3447 3448 if (softnic_parse_ipv6_addr(tokens[5], &saddr) != 0) { 3449 snprintf(out, out_size, MSG_ARG_INVALID, "sa"); 3450 return 0; 3451 } 3452 memcpy(m->match.acl.ipv6.sa, saddr.s6_addr, 16); 3453 3454 if (softnic_parse_ipv6_addr(tokens[7], &daddr) != 0) { 3455 snprintf(out, out_size, MSG_ARG_INVALID, "da"); 3456 return 0; 3457 } 3458 memcpy(m->match.acl.ipv6.da, daddr.s6_addr, 16); 3459 } else { 3460 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 3461 "ipv4 or ipv6"); 3462 return 0; 3463 } 3464 3465 if (softnic_parser_read_uint32(&m->match.acl.sa_depth, 3466 tokens[6]) != 0) { 3467 snprintf(out, out_size, MSG_ARG_INVALID, "sa_depth"); 3468 return 0; 3469 } 3470 3471 if (softnic_parser_read_uint32(&m->match.acl.da_depth, 3472 tokens[8]) != 0) { 3473 snprintf(out, out_size, MSG_ARG_INVALID, "da_depth"); 3474 return 0; 3475 } 3476 3477 if (softnic_parser_read_uint16(&m->match.acl.sp0, tokens[9]) != 0) { 3478 snprintf(out, out_size, MSG_ARG_INVALID, "sp0"); 3479 return 0; 3480 } 3481 3482 if (softnic_parser_read_uint16(&m->match.acl.sp1, tokens[10]) != 0) { 3483 snprintf(out, out_size, MSG_ARG_INVALID, "sp1"); 3484 return 0; 3485 } 3486 3487 if (softnic_parser_read_uint16(&m->match.acl.dp0, tokens[11]) != 0) { 3488 snprintf(out, out_size, MSG_ARG_INVALID, "dp0"); 3489 return 0; 3490 } 3491 3492 if (softnic_parser_read_uint16(&m->match.acl.dp1, tokens[12]) != 0) { 3493 snprintf(out, out_size, MSG_ARG_INVALID, "dp1"); 3494 return 0; 3495 } 3496 3497 if (softnic_parser_read_uint8(&m->match.acl.proto, tokens[13]) != 0) { 3498 snprintf(out, out_size, MSG_ARG_INVALID, "proto"); 3499 return 0; 3500 } 3501 3502 m->match.acl.proto_mask = 0xff; 3503 3504 return 14; 3505 } /* acl */ 3506 3507 if (strcmp(tokens[1], "array") == 0) { 3508 if (n_tokens < 3) { 3509 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 3510 return 0; 3511 } 3512 3513 m->match_type = TABLE_ARRAY; 3514 3515 if (softnic_parser_read_uint32(&m->match.array.pos, tokens[2]) != 0) { 3516 snprintf(out, out_size, MSG_ARG_INVALID, "pos"); 3517 return 0; 3518 } 3519 3520 return 3; 3521 } /* array */ 3522 3523 if (strcmp(tokens[1], "hash") == 0) { 3524 if (n_tokens < 3) { 3525 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 3526 return 0; 3527 } 3528 3529 m->match_type = TABLE_HASH; 3530 3531 if (strcmp(tokens[2], "raw") == 0) { 3532 uint32_t key_size = TABLE_RULE_MATCH_SIZE_MAX; 3533 3534 if (n_tokens < 4) { 3535 snprintf(out, out_size, MSG_ARG_MISMATCH, 3536 tokens[0]); 3537 return 0; 3538 } 3539 3540 if (softnic_parse_hex_string(tokens[3], 3541 m->match.hash.key, &key_size) != 0) { 3542 snprintf(out, out_size, MSG_ARG_INVALID, "key"); 3543 return 0; 3544 } 3545 3546 return 4; 3547 } /* hash raw */ 3548 3549 if (strcmp(tokens[2], "ipv4_5tuple") == 0) { 3550 struct pkt_key_ipv4_5tuple *ipv4 = 3551 (struct pkt_key_ipv4_5tuple *)m->match.hash.key; 3552 struct in_addr saddr, daddr; 3553 uint16_t sp, dp; 3554 uint8_t proto; 3555 3556 if (n_tokens < 8) { 3557 snprintf(out, out_size, MSG_ARG_MISMATCH, 3558 tokens[0]); 3559 return 0; 3560 } 3561 3562 if (softnic_parse_ipv4_addr(tokens[3], &saddr) != 0) { 3563 snprintf(out, out_size, MSG_ARG_INVALID, "sa"); 3564 return 0; 3565 } 3566 3567 if (softnic_parse_ipv4_addr(tokens[4], &daddr) != 0) { 3568 snprintf(out, out_size, MSG_ARG_INVALID, "da"); 3569 return 0; 3570 } 3571 3572 if (softnic_parser_read_uint16(&sp, tokens[5]) != 0) { 3573 snprintf(out, out_size, MSG_ARG_INVALID, "sp"); 3574 return 0; 3575 } 3576 3577 if (softnic_parser_read_uint16(&dp, tokens[6]) != 0) { 3578 snprintf(out, out_size, MSG_ARG_INVALID, "dp"); 3579 return 0; 3580 } 3581 3582 if (softnic_parser_read_uint8(&proto, tokens[7]) != 0) { 3583 snprintf(out, out_size, MSG_ARG_INVALID, 3584 "proto"); 3585 return 0; 3586 } 3587 3588 ipv4->sa = saddr.s_addr; 3589 ipv4->da = daddr.s_addr; 3590 ipv4->sp = rte_cpu_to_be_16(sp); 3591 ipv4->dp = rte_cpu_to_be_16(dp); 3592 ipv4->proto = proto; 3593 3594 return 8; 3595 } /* hash ipv4_5tuple */ 3596 3597 if (strcmp(tokens[2], "ipv6_5tuple") == 0) { 3598 struct pkt_key_ipv6_5tuple *ipv6 = 3599 (struct pkt_key_ipv6_5tuple *)m->match.hash.key; 3600 struct in6_addr saddr, daddr; 3601 uint16_t sp, dp; 3602 uint8_t proto; 3603 3604 if (n_tokens < 8) { 3605 snprintf(out, out_size, MSG_ARG_MISMATCH, 3606 tokens[0]); 3607 return 0; 3608 } 3609 3610 if (softnic_parse_ipv6_addr(tokens[3], &saddr) != 0) { 3611 snprintf(out, out_size, MSG_ARG_INVALID, "sa"); 3612 return 0; 3613 } 3614 3615 if (softnic_parse_ipv6_addr(tokens[4], &daddr) != 0) { 3616 snprintf(out, out_size, MSG_ARG_INVALID, "da"); 3617 return 0; 3618 } 3619 3620 if (softnic_parser_read_uint16(&sp, tokens[5]) != 0) { 3621 snprintf(out, out_size, MSG_ARG_INVALID, "sp"); 3622 return 0; 3623 } 3624 3625 if (softnic_parser_read_uint16(&dp, tokens[6]) != 0) { 3626 snprintf(out, out_size, MSG_ARG_INVALID, "dp"); 3627 return 0; 3628 } 3629 3630 if (softnic_parser_read_uint8(&proto, tokens[7]) != 0) { 3631 snprintf(out, out_size, MSG_ARG_INVALID, 3632 "proto"); 3633 return 0; 3634 } 3635 3636 memcpy(ipv6->sa, saddr.s6_addr, 16); 3637 memcpy(ipv6->da, daddr.s6_addr, 16); 3638 ipv6->sp = rte_cpu_to_be_16(sp); 3639 ipv6->dp = rte_cpu_to_be_16(dp); 3640 ipv6->proto = proto; 3641 3642 return 8; 3643 } /* hash ipv6_5tuple */ 3644 3645 if (strcmp(tokens[2], "ipv4_addr") == 0) { 3646 struct pkt_key_ipv4_addr *ipv4_addr = 3647 (struct pkt_key_ipv4_addr *)m->match.hash.key; 3648 struct in_addr addr; 3649 3650 if (n_tokens < 4) { 3651 snprintf(out, out_size, MSG_ARG_MISMATCH, 3652 tokens[0]); 3653 return 0; 3654 } 3655 3656 if (softnic_parse_ipv4_addr(tokens[3], &addr) != 0) { 3657 snprintf(out, out_size, MSG_ARG_INVALID, 3658 "addr"); 3659 return 0; 3660 } 3661 3662 ipv4_addr->addr = addr.s_addr; 3663 3664 return 4; 3665 } /* hash ipv4_addr */ 3666 3667 if (strcmp(tokens[2], "ipv6_addr") == 0) { 3668 struct pkt_key_ipv6_addr *ipv6_addr = 3669 (struct pkt_key_ipv6_addr *)m->match.hash.key; 3670 struct in6_addr addr; 3671 3672 if (n_tokens < 4) { 3673 snprintf(out, out_size, MSG_ARG_MISMATCH, 3674 tokens[0]); 3675 return 0; 3676 } 3677 3678 if (softnic_parse_ipv6_addr(tokens[3], &addr) != 0) { 3679 snprintf(out, out_size, MSG_ARG_INVALID, 3680 "addr"); 3681 return 0; 3682 } 3683 3684 memcpy(ipv6_addr->addr, addr.s6_addr, 16); 3685 3686 return 4; 3687 } /* hash ipv6_5tuple */ 3688 3689 if (strcmp(tokens[2], "qinq") == 0) { 3690 struct pkt_key_qinq *qinq = 3691 (struct pkt_key_qinq *)m->match.hash.key; 3692 uint16_t svlan, cvlan; 3693 3694 if (n_tokens < 5) { 3695 snprintf(out, out_size, MSG_ARG_MISMATCH, 3696 tokens[0]); 3697 return 0; 3698 } 3699 3700 if ((softnic_parser_read_uint16(&svlan, tokens[3]) != 0) || 3701 svlan > 0xFFF) { 3702 snprintf(out, out_size, MSG_ARG_INVALID, 3703 "svlan"); 3704 return 0; 3705 } 3706 3707 if ((softnic_parser_read_uint16(&cvlan, tokens[4]) != 0) || 3708 cvlan > 0xFFF) { 3709 snprintf(out, out_size, MSG_ARG_INVALID, 3710 "cvlan"); 3711 return 0; 3712 } 3713 3714 qinq->svlan = rte_cpu_to_be_16(svlan); 3715 qinq->cvlan = rte_cpu_to_be_16(cvlan); 3716 3717 return 5; 3718 } /* hash qinq */ 3719 3720 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 3721 return 0; 3722 } /* hash */ 3723 3724 if (strcmp(tokens[1], "lpm") == 0) { 3725 if (n_tokens < 5) { 3726 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 3727 return 0; 3728 } 3729 3730 m->match_type = TABLE_LPM; 3731 3732 if (strcmp(tokens[2], "ipv4") == 0) { 3733 struct in_addr addr; 3734 3735 m->match.lpm.ip_version = 1; 3736 3737 if (softnic_parse_ipv4_addr(tokens[3], &addr) != 0) { 3738 snprintf(out, out_size, MSG_ARG_INVALID, 3739 "addr"); 3740 return 0; 3741 } 3742 3743 m->match.lpm.ipv4 = rte_be_to_cpu_32(addr.s_addr); 3744 } else if (strcmp(tokens[2], "ipv6") == 0) { 3745 struct in6_addr addr; 3746 3747 m->match.lpm.ip_version = 0; 3748 3749 if (softnic_parse_ipv6_addr(tokens[3], &addr) != 0) { 3750 snprintf(out, out_size, MSG_ARG_INVALID, 3751 "addr"); 3752 return 0; 3753 } 3754 3755 memcpy(m->match.lpm.ipv6, addr.s6_addr, 16); 3756 } else { 3757 snprintf(out, out_size, MSG_ARG_MISMATCH, 3758 "ipv4 or ipv6"); 3759 return 0; 3760 } 3761 3762 if (softnic_parser_read_uint8(&m->match.lpm.depth, tokens[4]) != 0) { 3763 snprintf(out, out_size, MSG_ARG_INVALID, "depth"); 3764 return 0; 3765 } 3766 3767 return 5; 3768 } /* lpm */ 3769 3770 snprintf(out, out_size, MSG_ARG_MISMATCH, 3771 "acl or array or hash or lpm"); 3772 return 0; 3773 } 3774 3775 /** 3776 * table_action ::= 3777 * 3778 * action 3779 * fwd 3780 * drop 3781 * | port <port_id> 3782 * | meta 3783 * | table <table_id> 3784 * [balance <out0> ... <out7>] 3785 * [meter 3786 * tc0 meter <meter_profile_id> policer g <pa> y <pa> r <pa> 3787 * [tc1 meter <meter_profile_id> policer g <pa> y <pa> r <pa> 3788 * tc2 meter <meter_profile_id> policer g <pa> y <pa> r <pa> 3789 * tc3 meter <meter_profile_id> policer g <pa> y <pa> r <pa>]] 3790 * [tm subport <subport_id> pipe <pipe_id>] 3791 * [encap 3792 * ether <da> <sa> 3793 * | vlan <da> <sa> <pcp> <dei> <vid> 3794 * | qinq <da> <sa> <pcp> <dei> <vid> <pcp> <dei> <vid> 3795 * | qinq_pppoe <da> <sa> <pcp> <dei> <vid> <pcp> <dei> <vid> <session_id> 3796 * | mpls unicast | multicast 3797 * <da> <sa> 3798 * label0 <label> <tc> <ttl> 3799 * [label1 <label> <tc> <ttl> 3800 * [label2 <label> <tc> <ttl> 3801 * [label3 <label> <tc> <ttl>]]] 3802 * | pppoe <da> <sa> <session_id>] 3803 * | vxlan ether <da> <sa> 3804 * [vlan <pcp> <dei> <vid>] 3805 * ipv4 <sa> <da> <dscp> <ttl> 3806 * | ipv6 <sa> <da> <flow_label> <dscp> <hop_limit> 3807 * udp <sp> <dp> 3808 * vxlan <vni>] 3809 * [nat ipv4 | ipv6 <addr> <port>] 3810 * [ttl dec | keep] 3811 * [stats] 3812 * [time] 3813 * [tag <tag>] 3814 * [decap <n>] 3815 * [sym_crypto 3816 * encrypt | decrypt 3817 * type 3818 * | cipher 3819 * cipher_algo <algo> cipher_key <key> cipher_iv <iv> 3820 * | cipher_auth 3821 * cipher_algo <algo> cipher_key <key> cipher_iv <iv> 3822 * auth_algo <algo> auth_key <key> digest_size <size> 3823 * | aead 3824 * aead_algo <algo> aead_key <key> aead_iv <iv> aead_aad <aad> 3825 * digest_size <size> 3826 * data_offset <data_offset>] 3827 * 3828 * where: 3829 * <pa> ::= g | y | r | drop 3830 */ 3831 static uint32_t 3832 parse_table_action_fwd(char **tokens, 3833 uint32_t n_tokens, 3834 struct softnic_table_rule_action *a) 3835 { 3836 if (n_tokens == 0 || 3837 (strcmp(tokens[0], "fwd") != 0)) 3838 return 0; 3839 3840 tokens++; 3841 n_tokens--; 3842 3843 if (n_tokens && (strcmp(tokens[0], "drop") == 0)) { 3844 a->fwd.action = RTE_PIPELINE_ACTION_DROP; 3845 a->action_mask |= 1 << RTE_TABLE_ACTION_FWD; 3846 return 1 + 1; 3847 } 3848 3849 if (n_tokens && (strcmp(tokens[0], "port") == 0)) { 3850 uint32_t id; 3851 3852 if (n_tokens < 2 || 3853 softnic_parser_read_uint32(&id, tokens[1])) 3854 return 0; 3855 3856 a->fwd.action = RTE_PIPELINE_ACTION_PORT; 3857 a->fwd.id = id; 3858 a->action_mask |= 1 << RTE_TABLE_ACTION_FWD; 3859 return 1 + 2; 3860 } 3861 3862 if (n_tokens && (strcmp(tokens[0], "meta") == 0)) { 3863 a->fwd.action = RTE_PIPELINE_ACTION_PORT_META; 3864 a->action_mask |= 1 << RTE_TABLE_ACTION_FWD; 3865 return 1 + 1; 3866 } 3867 3868 if (n_tokens && (strcmp(tokens[0], "table") == 0)) { 3869 uint32_t id; 3870 3871 if (n_tokens < 2 || 3872 softnic_parser_read_uint32(&id, tokens[1])) 3873 return 0; 3874 3875 a->fwd.action = RTE_PIPELINE_ACTION_TABLE; 3876 a->fwd.id = id; 3877 a->action_mask |= 1 << RTE_TABLE_ACTION_FWD; 3878 return 1 + 2; 3879 } 3880 3881 return 0; 3882 } 3883 3884 static uint32_t 3885 parse_table_action_balance(char **tokens, 3886 uint32_t n_tokens, 3887 struct softnic_table_rule_action *a) 3888 { 3889 uint32_t i; 3890 3891 if (n_tokens == 0 || 3892 (strcmp(tokens[0], "balance") != 0)) 3893 return 0; 3894 3895 tokens++; 3896 n_tokens--; 3897 3898 if (n_tokens < RTE_TABLE_ACTION_LB_TABLE_SIZE) 3899 return 0; 3900 3901 for (i = 0; i < RTE_TABLE_ACTION_LB_TABLE_SIZE; i++) 3902 if (softnic_parser_read_uint32(&a->lb.out[i], tokens[i]) != 0) 3903 return 0; 3904 3905 a->action_mask |= 1 << RTE_TABLE_ACTION_LB; 3906 return 1 + RTE_TABLE_ACTION_LB_TABLE_SIZE; 3907 } 3908 3909 static int 3910 parse_policer_action(char *token, enum rte_table_action_policer *a) 3911 { 3912 if (strcmp(token, "g") == 0) { 3913 *a = RTE_TABLE_ACTION_POLICER_COLOR_GREEN; 3914 return 0; 3915 } 3916 3917 if (strcmp(token, "y") == 0) { 3918 *a = RTE_TABLE_ACTION_POLICER_COLOR_YELLOW; 3919 return 0; 3920 } 3921 3922 if (strcmp(token, "r") == 0) { 3923 *a = RTE_TABLE_ACTION_POLICER_COLOR_RED; 3924 return 0; 3925 } 3926 3927 if (strcmp(token, "drop") == 0) { 3928 *a = RTE_TABLE_ACTION_POLICER_DROP; 3929 return 0; 3930 } 3931 3932 return -1; 3933 } 3934 3935 static uint32_t 3936 parse_table_action_meter_tc(char **tokens, 3937 uint32_t n_tokens, 3938 struct rte_table_action_mtr_tc_params *mtr) 3939 { 3940 if (n_tokens < 9 || 3941 strcmp(tokens[0], "meter") || 3942 softnic_parser_read_uint32(&mtr->meter_profile_id, tokens[1]) || 3943 strcmp(tokens[2], "policer") || 3944 strcmp(tokens[3], "g") || 3945 parse_policer_action(tokens[4], &mtr->policer[RTE_COLOR_GREEN]) || 3946 strcmp(tokens[5], "y") || 3947 parse_policer_action(tokens[6], &mtr->policer[RTE_COLOR_YELLOW]) || 3948 strcmp(tokens[7], "r") || 3949 parse_policer_action(tokens[8], &mtr->policer[RTE_COLOR_RED])) 3950 return 0; 3951 3952 return 9; 3953 } 3954 3955 static uint32_t 3956 parse_table_action_meter(char **tokens, 3957 uint32_t n_tokens, 3958 struct softnic_table_rule_action *a) 3959 { 3960 if (n_tokens == 0 || 3961 strcmp(tokens[0], "meter")) 3962 return 0; 3963 3964 tokens++; 3965 n_tokens--; 3966 3967 if (n_tokens < 10 || 3968 strcmp(tokens[0], "tc0") || 3969 (parse_table_action_meter_tc(tokens + 1, 3970 n_tokens - 1, 3971 &a->mtr.mtr[0]) == 0)) 3972 return 0; 3973 3974 tokens += 10; 3975 n_tokens -= 10; 3976 3977 if (n_tokens == 0 || 3978 strcmp(tokens[0], "tc1")) { 3979 a->mtr.tc_mask = 1; 3980 a->action_mask |= 1 << RTE_TABLE_ACTION_MTR; 3981 return 1 + 10; 3982 } 3983 3984 if (n_tokens < 30 || 3985 (parse_table_action_meter_tc(tokens + 1, 3986 n_tokens - 1, &a->mtr.mtr[1]) == 0) || 3987 strcmp(tokens[10], "tc2") || 3988 (parse_table_action_meter_tc(tokens + 11, 3989 n_tokens - 11, &a->mtr.mtr[2]) == 0) || 3990 strcmp(tokens[20], "tc3") || 3991 (parse_table_action_meter_tc(tokens + 21, 3992 n_tokens - 21, &a->mtr.mtr[3]) == 0)) 3993 return 0; 3994 3995 a->mtr.tc_mask = 0xF; 3996 a->action_mask |= 1 << RTE_TABLE_ACTION_MTR; 3997 return 1 + 10 + 3 * 10; 3998 } 3999 4000 static uint32_t 4001 parse_table_action_tm(char **tokens, 4002 uint32_t n_tokens, 4003 struct softnic_table_rule_action *a) 4004 { 4005 uint32_t subport_id, pipe_id; 4006 4007 if (n_tokens < 5 || 4008 strcmp(tokens[0], "tm") || 4009 strcmp(tokens[1], "subport") || 4010 softnic_parser_read_uint32(&subport_id, tokens[2]) || 4011 strcmp(tokens[3], "pipe") || 4012 softnic_parser_read_uint32(&pipe_id, tokens[4])) 4013 return 0; 4014 4015 a->tm.subport_id = subport_id; 4016 a->tm.pipe_id = pipe_id; 4017 a->action_mask |= 1 << RTE_TABLE_ACTION_TM; 4018 return 5; 4019 } 4020 4021 static uint32_t 4022 parse_table_action_encap(char **tokens, 4023 uint32_t n_tokens, 4024 struct softnic_table_rule_action *a) 4025 { 4026 if (n_tokens == 0 || 4027 strcmp(tokens[0], "encap")) 4028 return 0; 4029 4030 tokens++; 4031 n_tokens--; 4032 4033 /* ether */ 4034 if (n_tokens && (strcmp(tokens[0], "ether") == 0)) { 4035 if (n_tokens < 3 || 4036 softnic_parse_mac_addr(tokens[1], &a->encap.ether.ether.da) || 4037 softnic_parse_mac_addr(tokens[2], &a->encap.ether.ether.sa)) 4038 return 0; 4039 4040 a->encap.type = RTE_TABLE_ACTION_ENCAP_ETHER; 4041 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP; 4042 return 1 + 3; 4043 } 4044 4045 /* vlan */ 4046 if (n_tokens && (strcmp(tokens[0], "vlan") == 0)) { 4047 uint32_t pcp, dei, vid; 4048 4049 if (n_tokens < 6 || 4050 softnic_parse_mac_addr(tokens[1], &a->encap.vlan.ether.da) || 4051 softnic_parse_mac_addr(tokens[2], &a->encap.vlan.ether.sa) || 4052 softnic_parser_read_uint32(&pcp, tokens[3]) || 4053 pcp > 0x7 || 4054 softnic_parser_read_uint32(&dei, tokens[4]) || 4055 dei > 0x1 || 4056 softnic_parser_read_uint32(&vid, tokens[5]) || 4057 vid > 0xFFF) 4058 return 0; 4059 4060 a->encap.vlan.vlan.pcp = pcp & 0x7; 4061 a->encap.vlan.vlan.dei = dei & 0x1; 4062 a->encap.vlan.vlan.vid = vid & 0xFFF; 4063 a->encap.type = RTE_TABLE_ACTION_ENCAP_VLAN; 4064 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP; 4065 return 1 + 6; 4066 } 4067 4068 /* qinq */ 4069 if (n_tokens && (strcmp(tokens[0], "qinq") == 0)) { 4070 uint32_t svlan_pcp, svlan_dei, svlan_vid; 4071 uint32_t cvlan_pcp, cvlan_dei, cvlan_vid; 4072 4073 if (n_tokens < 9 || 4074 softnic_parse_mac_addr(tokens[1], &a->encap.qinq.ether.da) || 4075 softnic_parse_mac_addr(tokens[2], &a->encap.qinq.ether.sa) || 4076 softnic_parser_read_uint32(&svlan_pcp, tokens[3]) || 4077 svlan_pcp > 0x7 || 4078 softnic_parser_read_uint32(&svlan_dei, tokens[4]) || 4079 svlan_dei > 0x1 || 4080 softnic_parser_read_uint32(&svlan_vid, tokens[5]) || 4081 svlan_vid > 0xFFF || 4082 softnic_parser_read_uint32(&cvlan_pcp, tokens[6]) || 4083 cvlan_pcp > 0x7 || 4084 softnic_parser_read_uint32(&cvlan_dei, tokens[7]) || 4085 cvlan_dei > 0x1 || 4086 softnic_parser_read_uint32(&cvlan_vid, tokens[8]) || 4087 cvlan_vid > 0xFFF) 4088 return 0; 4089 4090 a->encap.qinq.svlan.pcp = svlan_pcp & 0x7; 4091 a->encap.qinq.svlan.dei = svlan_dei & 0x1; 4092 a->encap.qinq.svlan.vid = svlan_vid & 0xFFF; 4093 a->encap.qinq.cvlan.pcp = cvlan_pcp & 0x7; 4094 a->encap.qinq.cvlan.dei = cvlan_dei & 0x1; 4095 a->encap.qinq.cvlan.vid = cvlan_vid & 0xFFF; 4096 a->encap.type = RTE_TABLE_ACTION_ENCAP_QINQ; 4097 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP; 4098 return 1 + 9; 4099 } 4100 4101 /* qinq_pppoe */ 4102 if (n_tokens && (strcmp(tokens[0], "qinq_pppoe") == 0)) { 4103 uint32_t svlan_pcp, svlan_dei, svlan_vid; 4104 uint32_t cvlan_pcp, cvlan_dei, cvlan_vid; 4105 4106 if (n_tokens < 10 || 4107 softnic_parse_mac_addr(tokens[1], 4108 &a->encap.qinq_pppoe.ether.da) || 4109 softnic_parse_mac_addr(tokens[2], 4110 &a->encap.qinq_pppoe.ether.sa) || 4111 softnic_parser_read_uint32(&svlan_pcp, tokens[3]) || 4112 svlan_pcp > 0x7 || 4113 softnic_parser_read_uint32(&svlan_dei, tokens[4]) || 4114 svlan_dei > 0x1 || 4115 softnic_parser_read_uint32(&svlan_vid, tokens[5]) || 4116 svlan_vid > 0xFFF || 4117 softnic_parser_read_uint32(&cvlan_pcp, tokens[6]) || 4118 cvlan_pcp > 0x7 || 4119 softnic_parser_read_uint32(&cvlan_dei, tokens[7]) || 4120 cvlan_dei > 0x1 || 4121 softnic_parser_read_uint32(&cvlan_vid, tokens[8]) || 4122 cvlan_vid > 0xFFF || 4123 softnic_parser_read_uint16(&a->encap.qinq_pppoe.pppoe.session_id, 4124 tokens[9])) 4125 return 0; 4126 4127 a->encap.qinq_pppoe.svlan.pcp = svlan_pcp & 0x7; 4128 a->encap.qinq_pppoe.svlan.dei = svlan_dei & 0x1; 4129 a->encap.qinq_pppoe.svlan.vid = svlan_vid & 0xFFF; 4130 a->encap.qinq_pppoe.cvlan.pcp = cvlan_pcp & 0x7; 4131 a->encap.qinq_pppoe.cvlan.dei = cvlan_dei & 0x1; 4132 a->encap.qinq_pppoe.cvlan.vid = cvlan_vid & 0xFFF; 4133 a->encap.type = RTE_TABLE_ACTION_ENCAP_QINQ_PPPOE; 4134 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP; 4135 return 1 + 10; 4136 } 4137 4138 /* mpls */ 4139 if (n_tokens && (strcmp(tokens[0], "mpls") == 0)) { 4140 uint32_t label, tc, ttl; 4141 4142 if (n_tokens < 8) 4143 return 0; 4144 4145 if (strcmp(tokens[1], "unicast") == 0) 4146 a->encap.mpls.unicast = 1; 4147 else if (strcmp(tokens[1], "multicast") == 0) 4148 a->encap.mpls.unicast = 0; 4149 else 4150 return 0; 4151 4152 if (softnic_parse_mac_addr(tokens[2], &a->encap.mpls.ether.da) || 4153 softnic_parse_mac_addr(tokens[3], &a->encap.mpls.ether.sa) || 4154 strcmp(tokens[4], "label0") || 4155 softnic_parser_read_uint32(&label, tokens[5]) || 4156 label > 0xFFFFF || 4157 softnic_parser_read_uint32(&tc, tokens[6]) || 4158 tc > 0x7 || 4159 softnic_parser_read_uint32(&ttl, tokens[7]) || 4160 ttl > 0x3F) 4161 return 0; 4162 4163 a->encap.mpls.mpls[0].label = label; 4164 a->encap.mpls.mpls[0].tc = tc; 4165 a->encap.mpls.mpls[0].ttl = ttl; 4166 4167 tokens += 8; 4168 n_tokens -= 8; 4169 4170 if (n_tokens == 0 || 4171 strcmp(tokens[0], "label1")) { 4172 a->encap.mpls.mpls_count = 1; 4173 a->encap.type = RTE_TABLE_ACTION_ENCAP_MPLS; 4174 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP; 4175 return 1 + 8; 4176 } 4177 4178 if (n_tokens < 4 || 4179 softnic_parser_read_uint32(&label, tokens[1]) || 4180 label > 0xFFFFF || 4181 softnic_parser_read_uint32(&tc, tokens[2]) || 4182 tc > 0x7 || 4183 softnic_parser_read_uint32(&ttl, tokens[3]) || 4184 ttl > 0x3F) 4185 return 0; 4186 4187 a->encap.mpls.mpls[1].label = label; 4188 a->encap.mpls.mpls[1].tc = tc; 4189 a->encap.mpls.mpls[1].ttl = ttl; 4190 4191 tokens += 4; 4192 n_tokens -= 4; 4193 4194 if (n_tokens == 0 || 4195 strcmp(tokens[0], "label2")) { 4196 a->encap.mpls.mpls_count = 2; 4197 a->encap.type = RTE_TABLE_ACTION_ENCAP_MPLS; 4198 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP; 4199 return 1 + 8 + 4; 4200 } 4201 4202 if (n_tokens < 4 || 4203 softnic_parser_read_uint32(&label, tokens[1]) || 4204 label > 0xFFFFF || 4205 softnic_parser_read_uint32(&tc, tokens[2]) || 4206 tc > 0x7 || 4207 softnic_parser_read_uint32(&ttl, tokens[3]) || 4208 ttl > 0x3F) 4209 return 0; 4210 4211 a->encap.mpls.mpls[2].label = label; 4212 a->encap.mpls.mpls[2].tc = tc; 4213 a->encap.mpls.mpls[2].ttl = ttl; 4214 4215 tokens += 4; 4216 n_tokens -= 4; 4217 4218 if (n_tokens == 0 || 4219 strcmp(tokens[0], "label3")) { 4220 a->encap.mpls.mpls_count = 3; 4221 a->encap.type = RTE_TABLE_ACTION_ENCAP_MPLS; 4222 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP; 4223 return 1 + 8 + 4 + 4; 4224 } 4225 4226 if (n_tokens < 4 || 4227 softnic_parser_read_uint32(&label, tokens[1]) || 4228 label > 0xFFFFF || 4229 softnic_parser_read_uint32(&tc, tokens[2]) || 4230 tc > 0x7 || 4231 softnic_parser_read_uint32(&ttl, tokens[3]) || 4232 ttl > 0x3F) 4233 return 0; 4234 4235 a->encap.mpls.mpls[3].label = label; 4236 a->encap.mpls.mpls[3].tc = tc; 4237 a->encap.mpls.mpls[3].ttl = ttl; 4238 4239 a->encap.mpls.mpls_count = 4; 4240 a->encap.type = RTE_TABLE_ACTION_ENCAP_MPLS; 4241 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP; 4242 return 1 + 8 + 4 + 4 + 4; 4243 } 4244 4245 /* pppoe */ 4246 if (n_tokens && (strcmp(tokens[0], "pppoe") == 0)) { 4247 if (n_tokens < 4 || 4248 softnic_parse_mac_addr(tokens[1], &a->encap.pppoe.ether.da) || 4249 softnic_parse_mac_addr(tokens[2], &a->encap.pppoe.ether.sa) || 4250 softnic_parser_read_uint16(&a->encap.pppoe.pppoe.session_id, 4251 tokens[3])) 4252 return 0; 4253 4254 a->encap.type = RTE_TABLE_ACTION_ENCAP_PPPOE; 4255 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP; 4256 return 1 + 4; 4257 } 4258 4259 /* vxlan */ 4260 if (n_tokens && (strcmp(tokens[0], "vxlan") == 0)) { 4261 uint32_t n = 0; 4262 4263 n_tokens--; 4264 tokens++; 4265 n++; 4266 4267 /* ether <da> <sa> */ 4268 if ((n_tokens < 3) || 4269 strcmp(tokens[0], "ether") || 4270 softnic_parse_mac_addr(tokens[1], &a->encap.vxlan.ether.da) || 4271 softnic_parse_mac_addr(tokens[2], &a->encap.vxlan.ether.sa)) 4272 return 0; 4273 4274 n_tokens -= 3; 4275 tokens += 3; 4276 n += 3; 4277 4278 /* [vlan <pcp> <dei> <vid>] */ 4279 if (strcmp(tokens[0], "vlan") == 0) { 4280 uint32_t pcp, dei, vid; 4281 4282 if ((n_tokens < 4) || 4283 softnic_parser_read_uint32(&pcp, tokens[1]) || 4284 (pcp > 7) || 4285 softnic_parser_read_uint32(&dei, tokens[2]) || 4286 (dei > 1) || 4287 softnic_parser_read_uint32(&vid, tokens[3]) || 4288 (vid > 0xFFF)) 4289 return 0; 4290 4291 a->encap.vxlan.vlan.pcp = pcp; 4292 a->encap.vxlan.vlan.dei = dei; 4293 a->encap.vxlan.vlan.vid = vid; 4294 4295 n_tokens -= 4; 4296 tokens += 4; 4297 n += 4; 4298 } 4299 4300 /* ipv4 <sa> <da> <dscp> <ttl> 4301 | ipv6 <sa> <da> <flow_label> <dscp> <hop_limit> */ 4302 if (strcmp(tokens[0], "ipv4") == 0) { 4303 struct in_addr sa, da; 4304 uint8_t dscp, ttl; 4305 4306 if ((n_tokens < 5) || 4307 softnic_parse_ipv4_addr(tokens[1], &sa) || 4308 softnic_parse_ipv4_addr(tokens[2], &da) || 4309 softnic_parser_read_uint8(&dscp, tokens[3]) || 4310 (dscp > 64) || 4311 softnic_parser_read_uint8(&ttl, tokens[4])) 4312 return 0; 4313 4314 a->encap.vxlan.ipv4.sa = rte_be_to_cpu_32(sa.s_addr); 4315 a->encap.vxlan.ipv4.da = rte_be_to_cpu_32(da.s_addr); 4316 a->encap.vxlan.ipv4.dscp = dscp; 4317 a->encap.vxlan.ipv4.ttl = ttl; 4318 4319 n_tokens -= 5; 4320 tokens += 5; 4321 n += 5; 4322 } else if (strcmp(tokens[0], "ipv6") == 0) { 4323 struct in6_addr sa, da; 4324 uint32_t flow_label; 4325 uint8_t dscp, hop_limit; 4326 4327 if ((n_tokens < 6) || 4328 softnic_parse_ipv6_addr(tokens[1], &sa) || 4329 softnic_parse_ipv6_addr(tokens[2], &da) || 4330 softnic_parser_read_uint32(&flow_label, tokens[3]) || 4331 softnic_parser_read_uint8(&dscp, tokens[4]) || 4332 (dscp > 64) || 4333 softnic_parser_read_uint8(&hop_limit, tokens[5])) 4334 return 0; 4335 4336 memcpy(a->encap.vxlan.ipv6.sa, sa.s6_addr, 16); 4337 memcpy(a->encap.vxlan.ipv6.da, da.s6_addr, 16); 4338 a->encap.vxlan.ipv6.flow_label = flow_label; 4339 a->encap.vxlan.ipv6.dscp = dscp; 4340 a->encap.vxlan.ipv6.hop_limit = hop_limit; 4341 4342 n_tokens -= 6; 4343 tokens += 6; 4344 n += 6; 4345 } else 4346 return 0; 4347 4348 /* udp <sp> <dp> */ 4349 if ((n_tokens < 3) || 4350 strcmp(tokens[0], "udp") || 4351 softnic_parser_read_uint16(&a->encap.vxlan.udp.sp, tokens[1]) || 4352 softnic_parser_read_uint16(&a->encap.vxlan.udp.dp, tokens[2])) 4353 return 0; 4354 4355 n_tokens -= 3; 4356 tokens += 3; 4357 n += 3; 4358 4359 /* vxlan <vni> */ 4360 if ((n_tokens < 2) || 4361 strcmp(tokens[0], "vxlan") || 4362 softnic_parser_read_uint32(&a->encap.vxlan.vxlan.vni, tokens[1]) || 4363 (a->encap.vxlan.vxlan.vni > 0xFFFFFF)) 4364 return 0; 4365 4366 n_tokens -= 2; 4367 tokens += 2; 4368 n += 2; 4369 4370 a->encap.type = RTE_TABLE_ACTION_ENCAP_VXLAN; 4371 a->action_mask |= 1 << RTE_TABLE_ACTION_ENCAP; 4372 return 1 + n; 4373 } 4374 4375 return 0; 4376 } 4377 4378 static uint32_t 4379 parse_table_action_nat(char **tokens, 4380 uint32_t n_tokens, 4381 struct softnic_table_rule_action *a) 4382 { 4383 if (n_tokens < 4 || 4384 strcmp(tokens[0], "nat")) 4385 return 0; 4386 4387 if (strcmp(tokens[1], "ipv4") == 0) { 4388 struct in_addr addr; 4389 uint16_t port; 4390 4391 if (softnic_parse_ipv4_addr(tokens[2], &addr) || 4392 softnic_parser_read_uint16(&port, tokens[3])) 4393 return 0; 4394 4395 a->nat.ip_version = 1; 4396 a->nat.addr.ipv4 = rte_be_to_cpu_32(addr.s_addr); 4397 a->nat.port = port; 4398 a->action_mask |= 1 << RTE_TABLE_ACTION_NAT; 4399 return 4; 4400 } 4401 4402 if (strcmp(tokens[1], "ipv6") == 0) { 4403 struct in6_addr addr; 4404 uint16_t port; 4405 4406 if (softnic_parse_ipv6_addr(tokens[2], &addr) || 4407 softnic_parser_read_uint16(&port, tokens[3])) 4408 return 0; 4409 4410 a->nat.ip_version = 0; 4411 memcpy(a->nat.addr.ipv6, addr.s6_addr, 16); 4412 a->nat.port = port; 4413 a->action_mask |= 1 << RTE_TABLE_ACTION_NAT; 4414 return 4; 4415 } 4416 4417 return 0; 4418 } 4419 4420 static uint32_t 4421 parse_table_action_ttl(char **tokens, 4422 uint32_t n_tokens, 4423 struct softnic_table_rule_action *a) 4424 { 4425 if (n_tokens < 2 || 4426 strcmp(tokens[0], "ttl")) 4427 return 0; 4428 4429 if (strcmp(tokens[1], "dec") == 0) 4430 a->ttl.decrement = 1; 4431 else if (strcmp(tokens[1], "keep") == 0) 4432 a->ttl.decrement = 0; 4433 else 4434 return 0; 4435 4436 a->action_mask |= 1 << RTE_TABLE_ACTION_TTL; 4437 return 2; 4438 } 4439 4440 static uint32_t 4441 parse_table_action_stats(char **tokens, 4442 uint32_t n_tokens, 4443 struct softnic_table_rule_action *a) 4444 { 4445 if (n_tokens < 1 || 4446 strcmp(tokens[0], "stats")) 4447 return 0; 4448 4449 a->stats.n_packets = 0; 4450 a->stats.n_bytes = 0; 4451 a->action_mask |= 1 << RTE_TABLE_ACTION_STATS; 4452 return 1; 4453 } 4454 4455 static uint32_t 4456 parse_table_action_time(char **tokens, 4457 uint32_t n_tokens, 4458 struct softnic_table_rule_action *a) 4459 { 4460 if (n_tokens < 1 || 4461 strcmp(tokens[0], "time")) 4462 return 0; 4463 4464 a->time.time = rte_rdtsc(); 4465 a->action_mask |= 1 << RTE_TABLE_ACTION_TIME; 4466 return 1; 4467 } 4468 4469 static void 4470 parse_free_sym_crypto_param_data(struct rte_table_action_sym_crypto_params *p) 4471 { 4472 struct rte_crypto_sym_xform *xform[2] = {NULL}; 4473 uint32_t i; 4474 4475 xform[0] = p->xform; 4476 if (xform[0]) 4477 xform[1] = xform[0]->next; 4478 4479 for (i = 0; i < 2; i++) { 4480 if (xform[i] == NULL) 4481 continue; 4482 4483 switch (xform[i]->type) { 4484 case RTE_CRYPTO_SYM_XFORM_CIPHER: 4485 if (p->cipher_auth.cipher_iv.val) 4486 free(p->cipher_auth.cipher_iv.val); 4487 if (p->cipher_auth.cipher_iv_update.val) 4488 free(p->cipher_auth.cipher_iv_update.val); 4489 break; 4490 case RTE_CRYPTO_SYM_XFORM_AUTH: 4491 if (p->cipher_auth.auth_iv.val) 4492 free(p->cipher_auth.cipher_iv.val); 4493 if (p->cipher_auth.auth_iv_update.val) 4494 free(p->cipher_auth.cipher_iv_update.val); 4495 break; 4496 case RTE_CRYPTO_SYM_XFORM_AEAD: 4497 if (p->aead.iv.val) 4498 free(p->aead.iv.val); 4499 if (p->aead.aad.val) 4500 free(p->aead.aad.val); 4501 break; 4502 default: 4503 continue; 4504 } 4505 } 4506 4507 } 4508 4509 static struct rte_crypto_sym_xform * 4510 parse_table_action_cipher(struct rte_table_action_sym_crypto_params *p, 4511 uint8_t *key, uint32_t max_key_len, char **tokens, 4512 uint32_t n_tokens, uint32_t encrypt, uint32_t *used_n_tokens) 4513 { 4514 struct rte_crypto_sym_xform *xform_cipher; 4515 int status; 4516 size_t len; 4517 4518 if (n_tokens < 7 || strcmp(tokens[1], "cipher_algo") || 4519 strcmp(tokens[3], "cipher_key") || 4520 strcmp(tokens[5], "cipher_iv")) 4521 return NULL; 4522 4523 xform_cipher = calloc(1, sizeof(*xform_cipher)); 4524 if (xform_cipher == NULL) 4525 return NULL; 4526 4527 xform_cipher->type = RTE_CRYPTO_SYM_XFORM_CIPHER; 4528 xform_cipher->cipher.op = encrypt ? RTE_CRYPTO_CIPHER_OP_ENCRYPT : 4529 RTE_CRYPTO_CIPHER_OP_DECRYPT; 4530 4531 /* cipher_algo */ 4532 status = rte_cryptodev_get_cipher_algo_enum( 4533 &xform_cipher->cipher.algo, tokens[2]); 4534 if (status < 0) 4535 goto error_exit; 4536 4537 /* cipher_key */ 4538 len = strlen(tokens[4]); 4539 if (len / 2 > max_key_len) { 4540 status = -ENOMEM; 4541 goto error_exit; 4542 } 4543 4544 status = softnic_parse_hex_string(tokens[4], key, (uint32_t *)&len); 4545 if (status < 0) 4546 goto error_exit; 4547 4548 xform_cipher->cipher.key.data = key; 4549 xform_cipher->cipher.key.length = (uint16_t)len; 4550 4551 /* cipher_iv */ 4552 len = strlen(tokens[6]); 4553 4554 p->cipher_auth.cipher_iv.val = calloc(1, len / 2 + 1); 4555 if (p->cipher_auth.cipher_iv.val == NULL) 4556 goto error_exit; 4557 4558 status = softnic_parse_hex_string(tokens[6], 4559 p->cipher_auth.cipher_iv.val, 4560 (uint32_t *)&len); 4561 if (status < 0) 4562 goto error_exit; 4563 4564 xform_cipher->cipher.iv.length = (uint16_t)len; 4565 xform_cipher->cipher.iv.offset = RTE_TABLE_ACTION_SYM_CRYPTO_IV_OFFSET; 4566 p->cipher_auth.cipher_iv.length = (uint32_t)len; 4567 *used_n_tokens = 7; 4568 4569 return xform_cipher; 4570 4571 error_exit: 4572 if (p->cipher_auth.cipher_iv.val) { 4573 free(p->cipher_auth.cipher_iv.val); 4574 p->cipher_auth.cipher_iv.val = NULL; 4575 } 4576 4577 free(xform_cipher); 4578 4579 return NULL; 4580 } 4581 4582 static struct rte_crypto_sym_xform * 4583 parse_table_action_cipher_auth(struct rte_table_action_sym_crypto_params *p, 4584 uint8_t *key, uint32_t max_key_len, char **tokens, 4585 uint32_t n_tokens, uint32_t encrypt, uint32_t *used_n_tokens) 4586 { 4587 struct rte_crypto_sym_xform *xform_cipher; 4588 struct rte_crypto_sym_xform *xform_auth; 4589 int status; 4590 size_t len; 4591 4592 if (n_tokens < 13 || 4593 strcmp(tokens[7], "auth_algo") || 4594 strcmp(tokens[9], "auth_key") || 4595 strcmp(tokens[11], "digest_size")) 4596 return NULL; 4597 4598 xform_auth = calloc(1, sizeof(*xform_auth)); 4599 if (xform_auth == NULL) 4600 return NULL; 4601 4602 xform_auth->type = RTE_CRYPTO_SYM_XFORM_AUTH; 4603 xform_auth->auth.op = encrypt ? RTE_CRYPTO_AUTH_OP_GENERATE : 4604 RTE_CRYPTO_AUTH_OP_VERIFY; 4605 4606 /* auth_algo */ 4607 status = rte_cryptodev_get_auth_algo_enum(&xform_auth->auth.algo, 4608 tokens[8]); 4609 if (status < 0) 4610 goto error_exit; 4611 4612 /* auth_key */ 4613 len = strlen(tokens[10]); 4614 if (len / 2 > max_key_len) { 4615 status = -ENOMEM; 4616 goto error_exit; 4617 } 4618 4619 status = softnic_parse_hex_string(tokens[10], key, (uint32_t *)&len); 4620 if (status < 0) 4621 goto error_exit; 4622 4623 xform_auth->auth.key.data = key; 4624 xform_auth->auth.key.length = (uint16_t)len; 4625 4626 key += xform_auth->auth.key.length; 4627 max_key_len -= xform_auth->auth.key.length; 4628 4629 if (strcmp(tokens[11], "digest_size")) 4630 goto error_exit; 4631 4632 status = softnic_parser_read_uint16(&xform_auth->auth.digest_length, 4633 tokens[12]); 4634 if (status < 0) 4635 goto error_exit; 4636 4637 xform_cipher = parse_table_action_cipher(p, key, max_key_len, tokens, 7, 4638 encrypt, used_n_tokens); 4639 if (xform_cipher == NULL) 4640 goto error_exit; 4641 4642 *used_n_tokens += 6; 4643 4644 if (encrypt) { 4645 xform_cipher->next = xform_auth; 4646 return xform_cipher; 4647 } else { 4648 xform_auth->next = xform_cipher; 4649 return xform_auth; 4650 } 4651 4652 error_exit: 4653 if (p->cipher_auth.auth_iv.val) { 4654 free(p->cipher_auth.auth_iv.val); 4655 p->cipher_auth.auth_iv.val = 0; 4656 } 4657 4658 free(xform_auth); 4659 4660 return NULL; 4661 } 4662 4663 static struct rte_crypto_sym_xform * 4664 parse_table_action_aead(struct rte_table_action_sym_crypto_params *p, 4665 uint8_t *key, uint32_t max_key_len, char **tokens, 4666 uint32_t n_tokens, uint32_t encrypt, uint32_t *used_n_tokens) 4667 { 4668 struct rte_crypto_sym_xform *xform_aead; 4669 int status; 4670 size_t len; 4671 4672 if (n_tokens < 11 || strcmp(tokens[1], "aead_algo") || 4673 strcmp(tokens[3], "aead_key") || 4674 strcmp(tokens[5], "aead_iv") || 4675 strcmp(tokens[7], "aead_aad") || 4676 strcmp(tokens[9], "digest_size")) 4677 return NULL; 4678 4679 xform_aead = calloc(1, sizeof(*xform_aead)); 4680 if (xform_aead == NULL) 4681 return NULL; 4682 4683 xform_aead->type = RTE_CRYPTO_SYM_XFORM_AEAD; 4684 xform_aead->aead.op = encrypt ? RTE_CRYPTO_AEAD_OP_ENCRYPT : 4685 RTE_CRYPTO_AEAD_OP_DECRYPT; 4686 4687 /* aead_algo */ 4688 status = rte_cryptodev_get_aead_algo_enum(&xform_aead->aead.algo, 4689 tokens[2]); 4690 if (status < 0) 4691 goto error_exit; 4692 4693 /* aead_key */ 4694 len = strlen(tokens[4]); 4695 if (len / 2 > max_key_len) { 4696 status = -ENOMEM; 4697 goto error_exit; 4698 } 4699 4700 status = softnic_parse_hex_string(tokens[4], key, (uint32_t *)&len); 4701 if (status < 0) 4702 goto error_exit; 4703 4704 xform_aead->aead.key.data = key; 4705 xform_aead->aead.key.length = (uint16_t)len; 4706 4707 /* aead_iv */ 4708 len = strlen(tokens[6]); 4709 p->aead.iv.val = calloc(1, len / 2 + 1); 4710 if (p->aead.iv.val == NULL) 4711 goto error_exit; 4712 4713 status = softnic_parse_hex_string(tokens[6], p->aead.iv.val, 4714 (uint32_t *)&len); 4715 if (status < 0) 4716 goto error_exit; 4717 4718 xform_aead->aead.iv.length = (uint16_t)len; 4719 xform_aead->aead.iv.offset = RTE_TABLE_ACTION_SYM_CRYPTO_IV_OFFSET; 4720 p->aead.iv.length = (uint32_t)len; 4721 4722 /* aead_aad */ 4723 len = strlen(tokens[8]); 4724 p->aead.aad.val = calloc(1, len / 2 + 1); 4725 if (p->aead.aad.val == NULL) 4726 goto error_exit; 4727 4728 status = softnic_parse_hex_string(tokens[8], p->aead.aad.val, (uint32_t *)&len); 4729 if (status < 0) 4730 goto error_exit; 4731 4732 xform_aead->aead.aad_length = (uint16_t)len; 4733 p->aead.aad.length = (uint32_t)len; 4734 4735 /* digest_size */ 4736 status = softnic_parser_read_uint16(&xform_aead->aead.digest_length, 4737 tokens[10]); 4738 if (status < 0) 4739 goto error_exit; 4740 4741 *used_n_tokens = 11; 4742 4743 return xform_aead; 4744 4745 error_exit: 4746 if (p->aead.iv.val) { 4747 free(p->aead.iv.val); 4748 p->aead.iv.val = NULL; 4749 } 4750 if (p->aead.aad.val) { 4751 free(p->aead.aad.val); 4752 p->aead.aad.val = NULL; 4753 } 4754 4755 free(xform_aead); 4756 4757 return NULL; 4758 } 4759 4760 4761 static uint32_t 4762 parse_table_action_sym_crypto(char **tokens, 4763 uint32_t n_tokens, 4764 struct softnic_table_rule_action *a) 4765 { 4766 struct rte_table_action_sym_crypto_params *p = &a->sym_crypto; 4767 struct rte_crypto_sym_xform *xform = NULL; 4768 uint8_t *key = a->sym_crypto_key; 4769 uint32_t max_key_len = SYM_CRYPTO_MAX_KEY_SIZE; 4770 uint32_t used_n_tokens; 4771 uint32_t encrypt; 4772 int status; 4773 4774 if ((n_tokens < 12) || 4775 strcmp(tokens[0], "sym_crypto") || 4776 strcmp(tokens[2], "type")) 4777 return 0; 4778 4779 memset(p, 0, sizeof(*p)); 4780 4781 if (strcmp(tokens[1], "encrypt") == 0) 4782 encrypt = 1; 4783 else 4784 encrypt = 0; 4785 4786 status = softnic_parser_read_uint32(&p->data_offset, tokens[n_tokens - 1]); 4787 if (status < 0) 4788 return 0; 4789 4790 if (strcmp(tokens[3], "cipher") == 0) { 4791 tokens += 3; 4792 n_tokens -= 3; 4793 4794 xform = parse_table_action_cipher(p, key, max_key_len, tokens, 4795 n_tokens, encrypt, &used_n_tokens); 4796 } else if (strcmp(tokens[3], "cipher_auth") == 0) { 4797 tokens += 3; 4798 n_tokens -= 3; 4799 4800 xform = parse_table_action_cipher_auth(p, key, max_key_len, 4801 tokens, n_tokens, encrypt, &used_n_tokens); 4802 } else if (strcmp(tokens[3], "aead") == 0) { 4803 tokens += 3; 4804 n_tokens -= 3; 4805 4806 xform = parse_table_action_aead(p, key, max_key_len, tokens, 4807 n_tokens, encrypt, &used_n_tokens); 4808 } 4809 4810 if (xform == NULL) 4811 return 0; 4812 4813 p->xform = xform; 4814 4815 if (strcmp(tokens[used_n_tokens], "data_offset")) { 4816 parse_free_sym_crypto_param_data(p); 4817 return 0; 4818 } 4819 4820 a->action_mask |= 1 << RTE_TABLE_ACTION_SYM_CRYPTO; 4821 4822 return used_n_tokens + 5; 4823 } 4824 4825 static uint32_t 4826 parse_table_action_tag(char **tokens, 4827 uint32_t n_tokens, 4828 struct softnic_table_rule_action *a) 4829 { 4830 if (n_tokens < 2 || 4831 strcmp(tokens[0], "tag")) 4832 return 0; 4833 4834 if (softnic_parser_read_uint32(&a->tag.tag, tokens[1])) 4835 return 0; 4836 4837 a->action_mask |= 1 << RTE_TABLE_ACTION_TAG; 4838 return 2; 4839 } 4840 4841 static uint32_t 4842 parse_table_action_decap(char **tokens, 4843 uint32_t n_tokens, 4844 struct softnic_table_rule_action *a) 4845 { 4846 if (n_tokens < 2 || 4847 strcmp(tokens[0], "decap")) 4848 return 0; 4849 4850 if (softnic_parser_read_uint16(&a->decap.n, tokens[1])) 4851 return 0; 4852 4853 a->action_mask |= 1 << RTE_TABLE_ACTION_DECAP; 4854 return 2; 4855 } 4856 4857 static uint32_t 4858 parse_table_action(char **tokens, 4859 uint32_t n_tokens, 4860 char *out, 4861 size_t out_size, 4862 struct softnic_table_rule_action *a) 4863 { 4864 uint32_t n_tokens0 = n_tokens; 4865 4866 memset(a, 0, sizeof(*a)); 4867 4868 if (n_tokens < 2 || 4869 strcmp(tokens[0], "action")) 4870 return 0; 4871 4872 tokens++; 4873 n_tokens--; 4874 4875 if (n_tokens && (strcmp(tokens[0], "fwd") == 0)) { 4876 uint32_t n; 4877 4878 n = parse_table_action_fwd(tokens, n_tokens, a); 4879 if (n == 0) { 4880 snprintf(out, out_size, MSG_ARG_INVALID, 4881 "action fwd"); 4882 return 0; 4883 } 4884 4885 tokens += n; 4886 n_tokens -= n; 4887 } 4888 4889 if (n_tokens && (strcmp(tokens[0], "balance") == 0)) { 4890 uint32_t n; 4891 4892 n = parse_table_action_balance(tokens, n_tokens, a); 4893 if (n == 0) { 4894 snprintf(out, out_size, MSG_ARG_INVALID, 4895 "action balance"); 4896 return 0; 4897 } 4898 4899 tokens += n; 4900 n_tokens -= n; 4901 } 4902 4903 if (n_tokens && (strcmp(tokens[0], "meter") == 0)) { 4904 uint32_t n; 4905 4906 n = parse_table_action_meter(tokens, n_tokens, a); 4907 if (n == 0) { 4908 snprintf(out, out_size, MSG_ARG_INVALID, 4909 "action meter"); 4910 return 0; 4911 } 4912 4913 tokens += n; 4914 n_tokens -= n; 4915 } 4916 4917 if (n_tokens && (strcmp(tokens[0], "tm") == 0)) { 4918 uint32_t n; 4919 4920 n = parse_table_action_tm(tokens, n_tokens, a); 4921 if (n == 0) { 4922 snprintf(out, out_size, MSG_ARG_INVALID, 4923 "action tm"); 4924 return 0; 4925 } 4926 4927 tokens += n; 4928 n_tokens -= n; 4929 } 4930 4931 if (n_tokens && (strcmp(tokens[0], "encap") == 0)) { 4932 uint32_t n; 4933 4934 n = parse_table_action_encap(tokens, n_tokens, a); 4935 if (n == 0) { 4936 snprintf(out, out_size, MSG_ARG_INVALID, 4937 "action encap"); 4938 return 0; 4939 } 4940 4941 tokens += n; 4942 n_tokens -= n; 4943 } 4944 4945 if (n_tokens && (strcmp(tokens[0], "nat") == 0)) { 4946 uint32_t n; 4947 4948 n = parse_table_action_nat(tokens, n_tokens, a); 4949 if (n == 0) { 4950 snprintf(out, out_size, MSG_ARG_INVALID, 4951 "action nat"); 4952 return 0; 4953 } 4954 4955 tokens += n; 4956 n_tokens -= n; 4957 } 4958 4959 if (n_tokens && (strcmp(tokens[0], "ttl") == 0)) { 4960 uint32_t n; 4961 4962 n = parse_table_action_ttl(tokens, n_tokens, a); 4963 if (n == 0) { 4964 snprintf(out, out_size, MSG_ARG_INVALID, 4965 "action ttl"); 4966 return 0; 4967 } 4968 4969 tokens += n; 4970 n_tokens -= n; 4971 } 4972 4973 if (n_tokens && (strcmp(tokens[0], "stats") == 0)) { 4974 uint32_t n; 4975 4976 n = parse_table_action_stats(tokens, n_tokens, a); 4977 if (n == 0) { 4978 snprintf(out, out_size, MSG_ARG_INVALID, 4979 "action stats"); 4980 return 0; 4981 } 4982 4983 tokens += n; 4984 n_tokens -= n; 4985 } 4986 4987 if (n_tokens && (strcmp(tokens[0], "time") == 0)) { 4988 uint32_t n; 4989 4990 n = parse_table_action_time(tokens, n_tokens, a); 4991 if (n == 0) { 4992 snprintf(out, out_size, MSG_ARG_INVALID, 4993 "action time"); 4994 return 0; 4995 } 4996 4997 tokens += n; 4998 n_tokens -= n; 4999 } 5000 5001 if (n_tokens && (strcmp(tokens[0], "tag") == 0)) { 5002 uint32_t n; 5003 5004 n = parse_table_action_tag(tokens, n_tokens, a); 5005 if (n == 0) { 5006 snprintf(out, out_size, MSG_ARG_INVALID, 5007 "action tag"); 5008 return 0; 5009 } 5010 5011 tokens += n; 5012 n_tokens -= n; 5013 } 5014 5015 if (n_tokens && (strcmp(tokens[0], "decap") == 0)) { 5016 uint32_t n; 5017 5018 n = parse_table_action_decap(tokens, n_tokens, a); 5019 if (n == 0) { 5020 snprintf(out, out_size, MSG_ARG_INVALID, 5021 "action decap"); 5022 return 0; 5023 } 5024 5025 tokens += n; 5026 n_tokens -= n; 5027 } 5028 5029 if (n_tokens && (strcmp(tokens[0], "sym_crypto") == 0)) { 5030 uint32_t n; 5031 5032 n = parse_table_action_sym_crypto(tokens, n_tokens, a); 5033 if (n == 0) { 5034 snprintf(out, out_size, MSG_ARG_INVALID, 5035 "action sym_crypto"); 5036 } 5037 5038 tokens += n; 5039 n_tokens -= n; 5040 } 5041 5042 if (n_tokens0 - n_tokens == 1) { 5043 snprintf(out, out_size, MSG_ARG_INVALID, "action"); 5044 return 0; 5045 } 5046 5047 return n_tokens0 - n_tokens; 5048 } 5049 5050 /** 5051 * pipeline <pipeline_name> table <table_id> rule add 5052 * match <match> 5053 * action <table_action> 5054 */ 5055 static void 5056 cmd_softnic_pipeline_table_rule_add(struct pmd_internals *softnic, 5057 char **tokens, 5058 uint32_t n_tokens, 5059 char *out, 5060 size_t out_size) 5061 { 5062 struct softnic_table_rule_match m; 5063 struct softnic_table_rule_action a; 5064 char *pipeline_name; 5065 void *data; 5066 uint32_t table_id, t0, n_tokens_parsed; 5067 int status; 5068 5069 if (n_tokens < 8) { 5070 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5071 return; 5072 } 5073 5074 pipeline_name = tokens[1]; 5075 5076 if (strcmp(tokens[2], "table") != 0) { 5077 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); 5078 return; 5079 } 5080 5081 if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) { 5082 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 5083 return; 5084 } 5085 5086 if (strcmp(tokens[4], "rule") != 0) { 5087 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule"); 5088 return; 5089 } 5090 5091 if (strcmp(tokens[5], "add") != 0) { 5092 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add"); 5093 return; 5094 } 5095 5096 t0 = 6; 5097 5098 /* match */ 5099 n_tokens_parsed = parse_match(tokens + t0, 5100 n_tokens - t0, 5101 out, 5102 out_size, 5103 &m); 5104 if (n_tokens_parsed == 0) 5105 return; 5106 t0 += n_tokens_parsed; 5107 5108 /* action */ 5109 n_tokens_parsed = parse_table_action(tokens + t0, 5110 n_tokens - t0, 5111 out, 5112 out_size, 5113 &a); 5114 if (n_tokens_parsed == 0) 5115 return; 5116 t0 += n_tokens_parsed; 5117 5118 if (t0 != n_tokens) { 5119 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]); 5120 return; 5121 } 5122 5123 status = softnic_pipeline_table_rule_add(softnic, 5124 pipeline_name, 5125 table_id, 5126 &m, 5127 &a, 5128 &data); 5129 if (status) { 5130 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 5131 return; 5132 } 5133 } 5134 5135 /** 5136 * pipeline <pipeline_name> table <table_id> rule add 5137 * match 5138 * default 5139 * action 5140 * fwd 5141 * drop 5142 * | port <port_id> 5143 * | meta 5144 * | table <table_id> 5145 */ 5146 static void 5147 cmd_softnic_pipeline_table_rule_add_default(struct pmd_internals *softnic, 5148 char **tokens, 5149 uint32_t n_tokens, 5150 char *out, 5151 size_t out_size) 5152 { 5153 struct softnic_table_rule_action action; 5154 void *data; 5155 char *pipeline_name; 5156 uint32_t table_id; 5157 int status; 5158 5159 if (n_tokens != 11 && 5160 n_tokens != 12) { 5161 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5162 return; 5163 } 5164 5165 pipeline_name = tokens[1]; 5166 5167 if (strcmp(tokens[2], "table") != 0) { 5168 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); 5169 return; 5170 } 5171 5172 if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) { 5173 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 5174 return; 5175 } 5176 5177 if (strcmp(tokens[4], "rule") != 0) { 5178 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule"); 5179 return; 5180 } 5181 5182 if (strcmp(tokens[5], "add") != 0) { 5183 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add"); 5184 return; 5185 } 5186 5187 if (strcmp(tokens[6], "match") != 0) { 5188 snprintf(out, out_size, MSG_ARG_INVALID, "match"); 5189 return; 5190 } 5191 5192 if (strcmp(tokens[7], "default") != 0) { 5193 snprintf(out, out_size, MSG_ARG_INVALID, "default"); 5194 return; 5195 } 5196 5197 if (strcmp(tokens[8], "action") != 0) { 5198 snprintf(out, out_size, MSG_ARG_INVALID, "action"); 5199 return; 5200 } 5201 5202 if (strcmp(tokens[9], "fwd") != 0) { 5203 snprintf(out, out_size, MSG_ARG_INVALID, "fwd"); 5204 return; 5205 } 5206 5207 action.action_mask = 1 << RTE_TABLE_ACTION_FWD; 5208 5209 if (strcmp(tokens[10], "drop") == 0) { 5210 if (n_tokens != 11) { 5211 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5212 return; 5213 } 5214 5215 action.fwd.action = RTE_PIPELINE_ACTION_DROP; 5216 } else if (strcmp(tokens[10], "port") == 0) { 5217 uint32_t id; 5218 5219 if (n_tokens != 12) { 5220 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5221 return; 5222 } 5223 5224 if (softnic_parser_read_uint32(&id, tokens[11]) != 0) { 5225 snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); 5226 return; 5227 } 5228 5229 action.fwd.action = RTE_PIPELINE_ACTION_PORT; 5230 action.fwd.id = id; 5231 } else if (strcmp(tokens[10], "meta") == 0) { 5232 if (n_tokens != 11) { 5233 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5234 return; 5235 } 5236 5237 action.fwd.action = RTE_PIPELINE_ACTION_PORT_META; 5238 } else if (strcmp(tokens[10], "table") == 0) { 5239 uint32_t id; 5240 5241 if (n_tokens != 12) { 5242 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5243 return; 5244 } 5245 5246 if (softnic_parser_read_uint32(&id, tokens[11]) != 0) { 5247 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 5248 return; 5249 } 5250 5251 action.fwd.action = RTE_PIPELINE_ACTION_TABLE; 5252 action.fwd.id = id; 5253 } else { 5254 snprintf(out, out_size, MSG_ARG_INVALID, 5255 "drop or port or meta or table"); 5256 return; 5257 } 5258 5259 status = softnic_pipeline_table_rule_add_default(softnic, 5260 pipeline_name, 5261 table_id, 5262 &action, 5263 &data); 5264 if (status) { 5265 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 5266 return; 5267 } 5268 } 5269 5270 /** 5271 * pipeline <pipeline_name> table <table_id> rule add bulk <file_name> <n_rules> 5272 * 5273 * File <file_name>: 5274 * - line format: match <match> action <action> 5275 */ 5276 static int 5277 cli_rule_file_process(const char *file_name, 5278 size_t line_len_max, 5279 struct softnic_table_rule_match *m, 5280 struct softnic_table_rule_action *a, 5281 uint32_t *n_rules, 5282 uint32_t *line_number, 5283 char *out, 5284 size_t out_size); 5285 5286 static void 5287 cmd_softnic_pipeline_table_rule_add_bulk(struct pmd_internals *softnic, 5288 char **tokens, 5289 uint32_t n_tokens, 5290 char *out, 5291 size_t out_size) 5292 { 5293 struct softnic_table_rule_match *match; 5294 struct softnic_table_rule_action *action; 5295 void **data; 5296 char *pipeline_name, *file_name; 5297 uint32_t table_id, n_rules, n_rules_parsed, line_number; 5298 int status; 5299 5300 if (n_tokens != 9) { 5301 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5302 return; 5303 } 5304 5305 pipeline_name = tokens[1]; 5306 5307 if (strcmp(tokens[2], "table") != 0) { 5308 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); 5309 return; 5310 } 5311 5312 if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) { 5313 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 5314 return; 5315 } 5316 5317 if (strcmp(tokens[4], "rule") != 0) { 5318 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule"); 5319 return; 5320 } 5321 5322 if (strcmp(tokens[5], "add") != 0) { 5323 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add"); 5324 return; 5325 } 5326 5327 if (strcmp(tokens[6], "bulk") != 0) { 5328 snprintf(out, out_size, MSG_ARG_INVALID, "bulk"); 5329 return; 5330 } 5331 5332 file_name = tokens[7]; 5333 5334 if ((softnic_parser_read_uint32(&n_rules, tokens[8]) != 0) || 5335 n_rules == 0) { 5336 snprintf(out, out_size, MSG_ARG_INVALID, "n_rules"); 5337 return; 5338 } 5339 5340 /* Memory allocation. */ 5341 match = calloc(n_rules, sizeof(struct softnic_table_rule_match)); 5342 action = calloc(n_rules, sizeof(struct softnic_table_rule_action)); 5343 data = calloc(n_rules, sizeof(void *)); 5344 if (match == NULL || 5345 action == NULL || 5346 data == NULL) { 5347 snprintf(out, out_size, MSG_OUT_OF_MEMORY); 5348 free(data); 5349 free(action); 5350 free(match); 5351 return; 5352 } 5353 5354 /* Load rule file */ 5355 n_rules_parsed = n_rules; 5356 status = cli_rule_file_process(file_name, 5357 1024, 5358 match, 5359 action, 5360 &n_rules_parsed, 5361 &line_number, 5362 out, 5363 out_size); 5364 if (status) { 5365 snprintf(out, out_size, MSG_FILE_ERR, file_name, line_number); 5366 free(data); 5367 free(action); 5368 free(match); 5369 return; 5370 } 5371 if (n_rules_parsed != n_rules) { 5372 snprintf(out, out_size, MSG_FILE_NOT_ENOUGH, file_name); 5373 free(data); 5374 free(action); 5375 free(match); 5376 return; 5377 } 5378 5379 /* Rule bulk add */ 5380 status = softnic_pipeline_table_rule_add_bulk(softnic, 5381 pipeline_name, 5382 table_id, 5383 match, 5384 action, 5385 data, 5386 &n_rules); 5387 if (status) { 5388 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 5389 free(data); 5390 free(action); 5391 free(match); 5392 return; 5393 } 5394 5395 /* Memory free */ 5396 free(data); 5397 free(action); 5398 free(match); 5399 } 5400 5401 /** 5402 * pipeline <pipeline_name> table <table_id> rule delete 5403 * match <match> 5404 */ 5405 static void 5406 cmd_softnic_pipeline_table_rule_delete(struct pmd_internals *softnic, 5407 char **tokens, 5408 uint32_t n_tokens, 5409 char *out, 5410 size_t out_size) 5411 { 5412 struct softnic_table_rule_match m; 5413 char *pipeline_name; 5414 uint32_t table_id, n_tokens_parsed, t0; 5415 int status; 5416 5417 if (n_tokens < 8) { 5418 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5419 return; 5420 } 5421 5422 pipeline_name = tokens[1]; 5423 5424 if (strcmp(tokens[2], "table") != 0) { 5425 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); 5426 return; 5427 } 5428 5429 if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) { 5430 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 5431 return; 5432 } 5433 5434 if (strcmp(tokens[4], "rule") != 0) { 5435 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule"); 5436 return; 5437 } 5438 5439 if (strcmp(tokens[5], "delete") != 0) { 5440 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete"); 5441 return; 5442 } 5443 5444 t0 = 6; 5445 5446 /* match */ 5447 n_tokens_parsed = parse_match(tokens + t0, 5448 n_tokens - t0, 5449 out, 5450 out_size, 5451 &m); 5452 if (n_tokens_parsed == 0) 5453 return; 5454 t0 += n_tokens_parsed; 5455 5456 if (n_tokens != t0) { 5457 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5458 return; 5459 } 5460 5461 status = softnic_pipeline_table_rule_delete(softnic, 5462 pipeline_name, 5463 table_id, 5464 &m); 5465 if (status) { 5466 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 5467 return; 5468 } 5469 } 5470 5471 /** 5472 * pipeline <pipeline_name> table <table_id> rule delete 5473 * match 5474 * default 5475 */ 5476 static void 5477 cmd_softnic_pipeline_table_rule_delete_default(struct pmd_internals *softnic, 5478 char **tokens, 5479 uint32_t n_tokens, 5480 char *out, 5481 size_t out_size) 5482 { 5483 char *pipeline_name; 5484 uint32_t table_id; 5485 int status; 5486 5487 if (n_tokens != 8) { 5488 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5489 return; 5490 } 5491 5492 pipeline_name = tokens[1]; 5493 5494 if (strcmp(tokens[2], "table") != 0) { 5495 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); 5496 return; 5497 } 5498 5499 if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) { 5500 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 5501 return; 5502 } 5503 5504 if (strcmp(tokens[4], "rule") != 0) { 5505 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule"); 5506 return; 5507 } 5508 5509 if (strcmp(tokens[5], "delete") != 0) { 5510 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete"); 5511 return; 5512 } 5513 5514 if (strcmp(tokens[6], "match") != 0) { 5515 snprintf(out, out_size, MSG_ARG_INVALID, "match"); 5516 return; 5517 } 5518 5519 if (strcmp(tokens[7], "default") != 0) { 5520 snprintf(out, out_size, MSG_ARG_INVALID, "default"); 5521 return; 5522 } 5523 5524 status = softnic_pipeline_table_rule_delete_default(softnic, 5525 pipeline_name, 5526 table_id); 5527 if (status) { 5528 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 5529 return; 5530 } 5531 } 5532 5533 /** 5534 * pipeline <pipeline_name> table <table_id> rule read stats [clear] 5535 */ 5536 static void 5537 cmd_softnic_pipeline_table_rule_stats_read(struct pmd_internals *softnic __rte_unused, 5538 char **tokens, 5539 uint32_t n_tokens __rte_unused, 5540 char *out, 5541 size_t out_size) 5542 { 5543 snprintf(out, out_size, MSG_CMD_UNIMPLEM, tokens[0]); 5544 } 5545 5546 /** 5547 * pipeline <pipeline_name> table <table_id> meter profile <meter_profile_id> 5548 * add srtcm cir <cir> cbs <cbs> ebs <ebs> 5549 * | trtcm cir <cir> pir <pir> cbs <cbs> pbs <pbs> 5550 */ 5551 static void 5552 cmd_pipeline_table_meter_profile_add(struct pmd_internals *softnic, 5553 char **tokens, 5554 uint32_t n_tokens, 5555 char *out, 5556 size_t out_size) 5557 { 5558 struct rte_table_action_meter_profile p; 5559 char *pipeline_name; 5560 uint32_t table_id, meter_profile_id; 5561 int status; 5562 5563 if (n_tokens < 9) { 5564 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5565 return; 5566 } 5567 5568 pipeline_name = tokens[1]; 5569 5570 if (strcmp(tokens[2], "table") != 0) { 5571 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 5572 return; 5573 } 5574 5575 if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) { 5576 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 5577 return; 5578 } 5579 5580 if (strcmp(tokens[4], "meter") != 0) { 5581 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter"); 5582 return; 5583 } 5584 5585 if (strcmp(tokens[5], "profile") != 0) { 5586 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile"); 5587 return; 5588 } 5589 5590 if (softnic_parser_read_uint32(&meter_profile_id, tokens[6]) != 0) { 5591 snprintf(out, out_size, MSG_ARG_INVALID, "meter_profile_id"); 5592 return; 5593 } 5594 5595 if (strcmp(tokens[7], "add") != 0) { 5596 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add"); 5597 return; 5598 } 5599 5600 if (strcmp(tokens[8], "srtcm") == 0) { 5601 if (n_tokens != 15) { 5602 snprintf(out, out_size, MSG_ARG_MISMATCH, 5603 tokens[0]); 5604 return; 5605 } 5606 5607 p.alg = RTE_TABLE_ACTION_METER_SRTCM; 5608 5609 if (strcmp(tokens[9], "cir") != 0) { 5610 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cir"); 5611 return; 5612 } 5613 5614 if (softnic_parser_read_uint64(&p.srtcm.cir, tokens[10]) != 0) { 5615 snprintf(out, out_size, MSG_ARG_INVALID, "cir"); 5616 return; 5617 } 5618 5619 if (strcmp(tokens[11], "cbs") != 0) { 5620 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cbs"); 5621 return; 5622 } 5623 5624 if (softnic_parser_read_uint64(&p.srtcm.cbs, tokens[12]) != 0) { 5625 snprintf(out, out_size, MSG_ARG_INVALID, "cbs"); 5626 return; 5627 } 5628 5629 if (strcmp(tokens[13], "ebs") != 0) { 5630 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "ebs"); 5631 return; 5632 } 5633 5634 if (softnic_parser_read_uint64(&p.srtcm.ebs, tokens[14]) != 0) { 5635 snprintf(out, out_size, MSG_ARG_INVALID, "ebs"); 5636 return; 5637 } 5638 } else if (strcmp(tokens[8], "trtcm") == 0) { 5639 if (n_tokens != 17) { 5640 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5641 return; 5642 } 5643 5644 p.alg = RTE_TABLE_ACTION_METER_TRTCM; 5645 5646 if (strcmp(tokens[9], "cir") != 0) { 5647 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cir"); 5648 return; 5649 } 5650 5651 if (softnic_parser_read_uint64(&p.trtcm.cir, tokens[10]) != 0) { 5652 snprintf(out, out_size, MSG_ARG_INVALID, "cir"); 5653 return; 5654 } 5655 5656 if (strcmp(tokens[11], "pir") != 0) { 5657 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pir"); 5658 return; 5659 } 5660 5661 if (softnic_parser_read_uint64(&p.trtcm.pir, tokens[12]) != 0) { 5662 snprintf(out, out_size, MSG_ARG_INVALID, "pir"); 5663 return; 5664 } 5665 if (strcmp(tokens[13], "cbs") != 0) { 5666 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cbs"); 5667 return; 5668 } 5669 5670 if (softnic_parser_read_uint64(&p.trtcm.cbs, tokens[14]) != 0) { 5671 snprintf(out, out_size, MSG_ARG_INVALID, "cbs"); 5672 return; 5673 } 5674 5675 if (strcmp(tokens[15], "pbs") != 0) { 5676 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pbs"); 5677 return; 5678 } 5679 5680 if (softnic_parser_read_uint64(&p.trtcm.pbs, tokens[16]) != 0) { 5681 snprintf(out, out_size, MSG_ARG_INVALID, "pbs"); 5682 return; 5683 } 5684 } else { 5685 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5686 return; 5687 } 5688 5689 status = softnic_pipeline_table_mtr_profile_add(softnic, 5690 pipeline_name, 5691 table_id, 5692 meter_profile_id, 5693 &p); 5694 if (status) { 5695 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 5696 return; 5697 } 5698 } 5699 5700 /** 5701 * pipeline <pipeline_name> table <table_id> 5702 * meter profile <meter_profile_id> delete 5703 */ 5704 static void 5705 cmd_pipeline_table_meter_profile_delete(struct pmd_internals *softnic, 5706 char **tokens, 5707 uint32_t n_tokens, 5708 char *out, 5709 size_t out_size) 5710 { 5711 char *pipeline_name; 5712 uint32_t table_id, meter_profile_id; 5713 int status; 5714 5715 if (n_tokens != 8) { 5716 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5717 return; 5718 } 5719 5720 pipeline_name = tokens[1]; 5721 5722 if (strcmp(tokens[2], "table") != 0) { 5723 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 5724 return; 5725 } 5726 5727 if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) { 5728 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 5729 return; 5730 } 5731 5732 if (strcmp(tokens[4], "meter") != 0) { 5733 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter"); 5734 return; 5735 } 5736 5737 if (strcmp(tokens[5], "profile") != 0) { 5738 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile"); 5739 return; 5740 } 5741 5742 if (softnic_parser_read_uint32(&meter_profile_id, tokens[6]) != 0) { 5743 snprintf(out, out_size, MSG_ARG_INVALID, "meter_profile_id"); 5744 return; 5745 } 5746 5747 if (strcmp(tokens[7], "delete") != 0) { 5748 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete"); 5749 return; 5750 } 5751 5752 status = softnic_pipeline_table_mtr_profile_delete(softnic, 5753 pipeline_name, 5754 table_id, 5755 meter_profile_id); 5756 if (status) { 5757 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 5758 return; 5759 } 5760 } 5761 5762 /** 5763 * pipeline <pipeline_name> table <table_id> rule read meter [clear] 5764 */ 5765 static void 5766 cmd_pipeline_table_rule_meter_read(struct pmd_internals *softnic __rte_unused, 5767 char **tokens, 5768 uint32_t n_tokens __rte_unused, 5769 char *out, 5770 size_t out_size) 5771 { 5772 snprintf(out, out_size, MSG_CMD_UNIMPLEM, tokens[0]); 5773 } 5774 5775 /** 5776 * pipeline <pipeline_name> table <table_id> dscp <file_name> 5777 * 5778 * File <file_name>: 5779 * - exactly 64 lines 5780 * - line format: <tc_id> <tc_queue_id> <color>, with <color> as: g | y | r 5781 */ 5782 static int 5783 load_dscp_table(struct rte_table_action_dscp_table *dscp_table, 5784 const char *file_name, 5785 uint32_t *line_number) 5786 { 5787 FILE *f = NULL; 5788 uint32_t dscp, l; 5789 5790 /* Check input arguments */ 5791 if (dscp_table == NULL || 5792 file_name == NULL || 5793 line_number == NULL) { 5794 if (line_number) 5795 *line_number = 0; 5796 return -EINVAL; 5797 } 5798 5799 /* Open input file */ 5800 f = fopen(file_name, "r"); 5801 if (f == NULL) { 5802 *line_number = 0; 5803 return -EINVAL; 5804 } 5805 5806 /* Read file */ 5807 for (dscp = 0, l = 1; ; l++) { 5808 char line[64]; 5809 char *tokens[3]; 5810 enum rte_color color; 5811 uint32_t tc_id, tc_queue_id, n_tokens = RTE_DIM(tokens); 5812 5813 if (fgets(line, sizeof(line), f) == NULL) 5814 break; 5815 5816 if (is_comment(line)) 5817 continue; 5818 5819 if (softnic_parse_tokenize_string(line, tokens, &n_tokens)) { 5820 *line_number = l; 5821 fclose(f); 5822 return -EINVAL; 5823 } 5824 5825 if (n_tokens == 0) 5826 continue; 5827 5828 if (dscp >= RTE_DIM(dscp_table->entry) || 5829 n_tokens != RTE_DIM(tokens) || 5830 softnic_parser_read_uint32(&tc_id, tokens[0]) || 5831 tc_id >= RTE_TABLE_ACTION_TC_MAX || 5832 softnic_parser_read_uint32(&tc_queue_id, tokens[1]) || 5833 tc_queue_id >= RTE_TABLE_ACTION_TC_QUEUE_MAX || 5834 (strlen(tokens[2]) != 1)) { 5835 *line_number = l; 5836 fclose(f); 5837 return -EINVAL; 5838 } 5839 5840 switch (tokens[2][0]) { 5841 case 'g': 5842 case 'G': 5843 color = RTE_COLOR_GREEN; 5844 break; 5845 5846 case 'y': 5847 case 'Y': 5848 color = RTE_COLOR_YELLOW; 5849 break; 5850 5851 case 'r': 5852 case 'R': 5853 color = RTE_COLOR_RED; 5854 break; 5855 5856 default: 5857 *line_number = l; 5858 fclose(f); 5859 return -EINVAL; 5860 } 5861 5862 dscp_table->entry[dscp].tc_id = tc_id; 5863 dscp_table->entry[dscp].tc_queue_id = tc_queue_id; 5864 dscp_table->entry[dscp].color = color; 5865 dscp++; 5866 } 5867 5868 /* Close file */ 5869 fclose(f); 5870 return 0; 5871 } 5872 5873 static void 5874 cmd_pipeline_table_dscp(struct pmd_internals *softnic, 5875 char **tokens, 5876 uint32_t n_tokens, 5877 char *out, 5878 size_t out_size) 5879 { 5880 struct rte_table_action_dscp_table dscp_table; 5881 char *pipeline_name, *file_name; 5882 uint32_t table_id, line_number; 5883 int status; 5884 5885 if (n_tokens != 6) { 5886 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5887 return; 5888 } 5889 5890 pipeline_name = tokens[1]; 5891 5892 if (strcmp(tokens[2], "table") != 0) { 5893 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 5894 return; 5895 } 5896 5897 if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) { 5898 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 5899 return; 5900 } 5901 5902 if (strcmp(tokens[4], "dscp") != 0) { 5903 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "dscp"); 5904 return; 5905 } 5906 5907 file_name = tokens[5]; 5908 5909 status = load_dscp_table(&dscp_table, file_name, &line_number); 5910 if (status) { 5911 snprintf(out, out_size, MSG_FILE_ERR, file_name, line_number); 5912 return; 5913 } 5914 5915 status = softnic_pipeline_table_dscp_table_update(softnic, 5916 pipeline_name, 5917 table_id, 5918 UINT64_MAX, 5919 &dscp_table); 5920 if (status) { 5921 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 5922 return; 5923 } 5924 } 5925 5926 /** 5927 * pipeline <pipeline_name> table <table_id> rule read ttl [clear] 5928 */ 5929 static void 5930 cmd_softnic_pipeline_table_rule_ttl_read(struct pmd_internals *softnic __rte_unused, 5931 char **tokens, 5932 uint32_t n_tokens __rte_unused, 5933 char *out, 5934 size_t out_size) 5935 { 5936 snprintf(out, out_size, MSG_CMD_UNIMPLEM, tokens[0]); 5937 } 5938 5939 /** 5940 * thread <thread_id> pipeline <pipeline_name> enable 5941 */ 5942 static void 5943 cmd_softnic_thread_pipeline_enable(struct pmd_internals *softnic, 5944 char **tokens, 5945 uint32_t n_tokens, 5946 char *out, 5947 size_t out_size) 5948 { 5949 char *pipeline_name; 5950 uint32_t thread_id; 5951 int status; 5952 5953 if (n_tokens != 5) { 5954 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5955 return; 5956 } 5957 5958 if (softnic_parser_read_uint32(&thread_id, tokens[1]) != 0) { 5959 snprintf(out, out_size, MSG_ARG_INVALID, "thread_id"); 5960 return; 5961 } 5962 5963 if (strcmp(tokens[2], "pipeline") != 0) { 5964 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline"); 5965 return; 5966 } 5967 5968 pipeline_name = tokens[3]; 5969 5970 if (strcmp(tokens[4], "enable") != 0) { 5971 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "enable"); 5972 return; 5973 } 5974 5975 status = softnic_thread_pipeline_enable(softnic, thread_id, pipeline_name); 5976 if (status) { 5977 snprintf(out, out_size, MSG_CMD_FAIL, "thread pipeline enable"); 5978 return; 5979 } 5980 } 5981 5982 /** 5983 * thread <thread_id> pipeline <pipeline_name> disable 5984 */ 5985 static void 5986 cmd_softnic_thread_pipeline_disable(struct pmd_internals *softnic, 5987 char **tokens, 5988 uint32_t n_tokens, 5989 char *out, 5990 size_t out_size) 5991 { 5992 char *pipeline_name; 5993 uint32_t thread_id; 5994 int status; 5995 5996 if (n_tokens != 5) { 5997 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5998 return; 5999 } 6000 6001 if (softnic_parser_read_uint32(&thread_id, tokens[1]) != 0) { 6002 snprintf(out, out_size, MSG_ARG_INVALID, "thread_id"); 6003 return; 6004 } 6005 6006 if (strcmp(tokens[2], "pipeline") != 0) { 6007 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline"); 6008 return; 6009 } 6010 6011 pipeline_name = tokens[3]; 6012 6013 if (strcmp(tokens[4], "disable") != 0) { 6014 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "disable"); 6015 return; 6016 } 6017 6018 status = softnic_thread_pipeline_disable(softnic, thread_id, pipeline_name); 6019 if (status) { 6020 snprintf(out, out_size, MSG_CMD_FAIL, 6021 "thread pipeline disable"); 6022 return; 6023 } 6024 } 6025 6026 /** 6027 * flowapi map 6028 * group <group_id> 6029 * ingress | egress 6030 * pipeline <pipeline_name> 6031 * table <table_id> 6032 */ 6033 static void 6034 cmd_softnic_flowapi_map(struct pmd_internals *softnic, 6035 char **tokens, 6036 uint32_t n_tokens, 6037 char *out, 6038 size_t out_size) 6039 { 6040 char *pipeline_name; 6041 uint32_t group_id, table_id; 6042 int ingress, status; 6043 6044 if (n_tokens != 9) { 6045 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 6046 return; 6047 } 6048 6049 if (strcmp(tokens[1], "map") != 0) { 6050 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "map"); 6051 return; 6052 } 6053 6054 if (strcmp(tokens[2], "group") != 0) { 6055 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "group"); 6056 return; 6057 } 6058 6059 if (softnic_parser_read_uint32(&group_id, tokens[3]) != 0) { 6060 snprintf(out, out_size, MSG_ARG_INVALID, "group_id"); 6061 return; 6062 } 6063 6064 if (strcmp(tokens[4], "ingress") == 0) { 6065 ingress = 1; 6066 } else if (strcmp(tokens[4], "egress") == 0) { 6067 ingress = 0; 6068 } else { 6069 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "ingress | egress"); 6070 return; 6071 } 6072 6073 if (strcmp(tokens[5], "pipeline") != 0) { 6074 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline"); 6075 return; 6076 } 6077 6078 pipeline_name = tokens[6]; 6079 6080 if (strcmp(tokens[7], "table") != 0) { 6081 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); 6082 return; 6083 } 6084 6085 if (softnic_parser_read_uint32(&table_id, tokens[8]) != 0) { 6086 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 6087 return; 6088 } 6089 6090 status = flow_attr_map_set(softnic, 6091 group_id, 6092 ingress, 6093 pipeline_name, 6094 table_id); 6095 if (status) { 6096 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 6097 return; 6098 } 6099 } 6100 6101 void 6102 softnic_cli_process(char *in, char *out, size_t out_size, void *arg) 6103 { 6104 char *tokens[CMD_MAX_TOKENS]; 6105 uint32_t n_tokens = RTE_DIM(tokens); 6106 struct pmd_internals *softnic = arg; 6107 int status; 6108 6109 if (is_comment(in)) 6110 return; 6111 6112 status = softnic_parse_tokenize_string(in, tokens, &n_tokens); 6113 if (status) { 6114 snprintf(out, out_size, MSG_ARG_TOO_MANY, ""); 6115 return; 6116 } 6117 6118 if (n_tokens == 0) 6119 return; 6120 6121 if (strcmp(tokens[0], "mempool") == 0) { 6122 cmd_mempool(softnic, tokens, n_tokens, out, out_size); 6123 return; 6124 } 6125 6126 if (strcmp(tokens[0], "link") == 0) { 6127 cmd_link(softnic, tokens, n_tokens, out, out_size); 6128 return; 6129 } 6130 6131 if (strcmp(tokens[0], "swq") == 0) { 6132 cmd_swq(softnic, tokens, n_tokens, out, out_size); 6133 return; 6134 } 6135 6136 if (strcmp(tokens[0], "tmgr") == 0) { 6137 if (n_tokens == 2) { 6138 cmd_tmgr(softnic, tokens, n_tokens, out, out_size); 6139 return; 6140 } 6141 6142 if (n_tokens >= 3 && 6143 (strcmp(tokens[1], "shaper") == 0) && 6144 (strcmp(tokens[2], "profile") == 0)) { 6145 cmd_tmgr_shaper_profile(softnic, tokens, n_tokens, out, out_size); 6146 return; 6147 } 6148 6149 if (n_tokens >= 3 && 6150 (strcmp(tokens[1], "shared") == 0) && 6151 (strcmp(tokens[2], "shaper") == 0)) { 6152 cmd_tmgr_shared_shaper(softnic, tokens, n_tokens, out, out_size); 6153 return; 6154 } 6155 6156 if (n_tokens >= 2 && 6157 (strcmp(tokens[1], "node") == 0)) { 6158 cmd_tmgr_node(softnic, tokens, n_tokens, out, out_size); 6159 return; 6160 } 6161 6162 if (n_tokens >= 2 && 6163 (strcmp(tokens[1], "hierarchy-default") == 0)) { 6164 cmd_tmgr_hierarchy_default(softnic, tokens, n_tokens, out, out_size); 6165 return; 6166 } 6167 6168 if (n_tokens >= 3 && 6169 (strcmp(tokens[1], "hierarchy") == 0) && 6170 (strcmp(tokens[2], "commit") == 0)) { 6171 cmd_tmgr_hierarchy_commit(softnic, tokens, n_tokens, out, out_size); 6172 return; 6173 } 6174 } 6175 6176 if (strcmp(tokens[0], "tap") == 0) { 6177 cmd_tap(softnic, tokens, n_tokens, out, out_size); 6178 return; 6179 } 6180 6181 if (strcmp(tokens[0], "cryptodev") == 0) { 6182 cmd_cryptodev(softnic, tokens, n_tokens, out, out_size); 6183 return; 6184 } 6185 6186 if (strcmp(tokens[0], "port") == 0) { 6187 cmd_port_in_action_profile(softnic, tokens, n_tokens, out, out_size); 6188 return; 6189 } 6190 6191 if (strcmp(tokens[0], "table") == 0) { 6192 cmd_table_action_profile(softnic, tokens, n_tokens, out, out_size); 6193 return; 6194 } 6195 6196 if (strcmp(tokens[0], "pipeline") == 0) { 6197 if (n_tokens >= 3 && 6198 (strcmp(tokens[2], "period") == 0)) { 6199 cmd_pipeline(softnic, tokens, n_tokens, out, out_size); 6200 return; 6201 } 6202 6203 if (n_tokens >= 5 && 6204 (strcmp(tokens[2], "port") == 0) && 6205 (strcmp(tokens[3], "in") == 0) && 6206 (strcmp(tokens[4], "bsz") == 0)) { 6207 cmd_pipeline_port_in(softnic, tokens, n_tokens, out, out_size); 6208 return; 6209 } 6210 6211 if (n_tokens >= 5 && 6212 (strcmp(tokens[2], "port") == 0) && 6213 (strcmp(tokens[3], "out") == 0) && 6214 (strcmp(tokens[4], "bsz") == 0)) { 6215 cmd_pipeline_port_out(softnic, tokens, n_tokens, out, out_size); 6216 return; 6217 } 6218 6219 if (n_tokens >= 4 && 6220 (strcmp(tokens[2], "table") == 0) && 6221 (strcmp(tokens[3], "match") == 0)) { 6222 cmd_pipeline_table(softnic, tokens, n_tokens, out, out_size); 6223 return; 6224 } 6225 6226 if (n_tokens >= 6 && 6227 (strcmp(tokens[2], "port") == 0) && 6228 (strcmp(tokens[3], "in") == 0) && 6229 (strcmp(tokens[5], "table") == 0)) { 6230 cmd_pipeline_port_in_table(softnic, tokens, n_tokens, 6231 out, out_size); 6232 return; 6233 } 6234 6235 if (n_tokens >= 6 && 6236 (strcmp(tokens[2], "port") == 0) && 6237 (strcmp(tokens[3], "in") == 0) && 6238 (strcmp(tokens[5], "stats") == 0)) { 6239 cmd_pipeline_port_in_stats(softnic, tokens, n_tokens, 6240 out, out_size); 6241 return; 6242 } 6243 6244 if (n_tokens >= 6 && 6245 (strcmp(tokens[2], "port") == 0) && 6246 (strcmp(tokens[3], "in") == 0) && 6247 (strcmp(tokens[5], "enable") == 0)) { 6248 cmd_softnic_pipeline_port_in_enable(softnic, tokens, n_tokens, 6249 out, out_size); 6250 return; 6251 } 6252 6253 if (n_tokens >= 6 && 6254 (strcmp(tokens[2], "port") == 0) && 6255 (strcmp(tokens[3], "in") == 0) && 6256 (strcmp(tokens[5], "disable") == 0)) { 6257 cmd_softnic_pipeline_port_in_disable(softnic, tokens, n_tokens, 6258 out, out_size); 6259 return; 6260 } 6261 6262 if (n_tokens >= 6 && 6263 (strcmp(tokens[2], "port") == 0) && 6264 (strcmp(tokens[3], "out") == 0) && 6265 (strcmp(tokens[5], "stats") == 0)) { 6266 cmd_pipeline_port_out_stats(softnic, tokens, n_tokens, 6267 out, out_size); 6268 return; 6269 } 6270 6271 if (n_tokens >= 5 && 6272 (strcmp(tokens[2], "table") == 0) && 6273 (strcmp(tokens[4], "stats") == 0)) { 6274 cmd_pipeline_table_stats(softnic, tokens, n_tokens, 6275 out, out_size); 6276 return; 6277 } 6278 6279 if (n_tokens >= 7 && 6280 (strcmp(tokens[2], "table") == 0) && 6281 (strcmp(tokens[4], "rule") == 0) && 6282 (strcmp(tokens[5], "add") == 0) && 6283 (strcmp(tokens[6], "match") == 0)) { 6284 if (n_tokens >= 8 && 6285 (strcmp(tokens[7], "default") == 0)) { 6286 cmd_softnic_pipeline_table_rule_add_default(softnic, tokens, 6287 n_tokens, out, out_size); 6288 return; 6289 } 6290 6291 cmd_softnic_pipeline_table_rule_add(softnic, tokens, n_tokens, 6292 out, out_size); 6293 return; 6294 } 6295 6296 if (n_tokens >= 7 && 6297 (strcmp(tokens[2], "table") == 0) && 6298 (strcmp(tokens[4], "rule") == 0) && 6299 (strcmp(tokens[5], "add") == 0) && 6300 (strcmp(tokens[6], "bulk") == 0)) { 6301 cmd_softnic_pipeline_table_rule_add_bulk(softnic, tokens, 6302 n_tokens, out, out_size); 6303 return; 6304 } 6305 6306 if (n_tokens >= 7 && 6307 (strcmp(tokens[2], "table") == 0) && 6308 (strcmp(tokens[4], "rule") == 0) && 6309 (strcmp(tokens[5], "delete") == 0) && 6310 (strcmp(tokens[6], "match") == 0)) { 6311 if (n_tokens >= 8 && 6312 (strcmp(tokens[7], "default") == 0)) { 6313 cmd_softnic_pipeline_table_rule_delete_default(softnic, tokens, 6314 n_tokens, out, out_size); 6315 return; 6316 } 6317 6318 cmd_softnic_pipeline_table_rule_delete(softnic, tokens, n_tokens, 6319 out, out_size); 6320 return; 6321 } 6322 6323 if (n_tokens >= 7 && 6324 (strcmp(tokens[2], "table") == 0) && 6325 (strcmp(tokens[4], "rule") == 0) && 6326 (strcmp(tokens[5], "read") == 0) && 6327 (strcmp(tokens[6], "stats") == 0)) { 6328 cmd_softnic_pipeline_table_rule_stats_read(softnic, tokens, n_tokens, 6329 out, out_size); 6330 return; 6331 } 6332 6333 if (n_tokens >= 8 && 6334 (strcmp(tokens[2], "table") == 0) && 6335 (strcmp(tokens[4], "meter") == 0) && 6336 (strcmp(tokens[5], "profile") == 0) && 6337 (strcmp(tokens[7], "add") == 0)) { 6338 cmd_pipeline_table_meter_profile_add(softnic, tokens, n_tokens, 6339 out, out_size); 6340 return; 6341 } 6342 6343 if (n_tokens >= 8 && 6344 (strcmp(tokens[2], "table") == 0) && 6345 (strcmp(tokens[4], "meter") == 0) && 6346 (strcmp(tokens[5], "profile") == 0) && 6347 (strcmp(tokens[7], "delete") == 0)) { 6348 cmd_pipeline_table_meter_profile_delete(softnic, tokens, 6349 n_tokens, out, out_size); 6350 return; 6351 } 6352 6353 if (n_tokens >= 7 && 6354 (strcmp(tokens[2], "table") == 0) && 6355 (strcmp(tokens[4], "rule") == 0) && 6356 (strcmp(tokens[5], "read") == 0) && 6357 (strcmp(tokens[6], "meter") == 0)) { 6358 cmd_pipeline_table_rule_meter_read(softnic, tokens, n_tokens, 6359 out, out_size); 6360 return; 6361 } 6362 6363 if (n_tokens >= 5 && 6364 (strcmp(tokens[2], "table") == 0) && 6365 (strcmp(tokens[4], "dscp") == 0)) { 6366 cmd_pipeline_table_dscp(softnic, tokens, n_tokens, 6367 out, out_size); 6368 return; 6369 } 6370 6371 if (n_tokens >= 7 && 6372 (strcmp(tokens[2], "table") == 0) && 6373 (strcmp(tokens[4], "rule") == 0) && 6374 (strcmp(tokens[5], "read") == 0) && 6375 (strcmp(tokens[6], "ttl") == 0)) { 6376 cmd_softnic_pipeline_table_rule_ttl_read(softnic, tokens, n_tokens, 6377 out, out_size); 6378 return; 6379 } 6380 } 6381 6382 if (strcmp(tokens[0], "thread") == 0) { 6383 if (n_tokens >= 5 && 6384 (strcmp(tokens[4], "enable") == 0)) { 6385 cmd_softnic_thread_pipeline_enable(softnic, tokens, n_tokens, 6386 out, out_size); 6387 return; 6388 } 6389 6390 if (n_tokens >= 5 && 6391 (strcmp(tokens[4], "disable") == 0)) { 6392 cmd_softnic_thread_pipeline_disable(softnic, tokens, n_tokens, 6393 out, out_size); 6394 return; 6395 } 6396 } 6397 6398 if (strcmp(tokens[0], "flowapi") == 0) { 6399 cmd_softnic_flowapi_map(softnic, tokens, n_tokens, out, 6400 out_size); 6401 return; 6402 } 6403 6404 snprintf(out, out_size, MSG_CMD_UNKNOWN, tokens[0]); 6405 } 6406 6407 int 6408 softnic_cli_script_process(struct pmd_internals *softnic, 6409 const char *file_name, 6410 size_t msg_in_len_max, 6411 size_t msg_out_len_max) 6412 { 6413 char *msg_in = NULL, *msg_out = NULL; 6414 FILE *f = NULL; 6415 6416 /* Check input arguments */ 6417 if (file_name == NULL || 6418 (strlen(file_name) == 0) || 6419 msg_in_len_max == 0 || 6420 msg_out_len_max == 0) 6421 return -EINVAL; 6422 6423 msg_in = malloc(msg_in_len_max + 1); 6424 msg_out = malloc(msg_out_len_max + 1); 6425 if (msg_in == NULL || 6426 msg_out == NULL) { 6427 free(msg_out); 6428 free(msg_in); 6429 return -ENOMEM; 6430 } 6431 6432 /* Open input file */ 6433 f = fopen(file_name, "r"); 6434 if (f == NULL) { 6435 free(msg_out); 6436 free(msg_in); 6437 return -EIO; 6438 } 6439 6440 /* Read file */ 6441 for ( ; ; ) { 6442 if (fgets(msg_in, msg_in_len_max + 1, f) == NULL) 6443 break; 6444 6445 printf("%s", msg_in); 6446 msg_out[0] = 0; 6447 6448 softnic_cli_process(msg_in, 6449 msg_out, 6450 msg_out_len_max, 6451 softnic); 6452 6453 if (strlen(msg_out)) 6454 printf("%s", msg_out); 6455 } 6456 6457 /* Close file */ 6458 fclose(f); 6459 free(msg_out); 6460 free(msg_in); 6461 return 0; 6462 } 6463 6464 static int 6465 cli_rule_file_process(const char *file_name, 6466 size_t line_len_max, 6467 struct softnic_table_rule_match *m, 6468 struct softnic_table_rule_action *a, 6469 uint32_t *n_rules, 6470 uint32_t *line_number, 6471 char *out, 6472 size_t out_size) 6473 { 6474 FILE *f = NULL; 6475 char *line = NULL; 6476 uint32_t rule_id, line_id; 6477 int status = 0; 6478 6479 /* Check input arguments */ 6480 if (file_name == NULL || 6481 (strlen(file_name) == 0) || 6482 line_len_max == 0) { 6483 *line_number = 0; 6484 return -EINVAL; 6485 } 6486 6487 /* Memory allocation */ 6488 line = malloc(line_len_max + 1); 6489 if (line == NULL) { 6490 *line_number = 0; 6491 return -ENOMEM; 6492 } 6493 6494 /* Open file */ 6495 f = fopen(file_name, "r"); 6496 if (f == NULL) { 6497 *line_number = 0; 6498 free(line); 6499 return -EIO; 6500 } 6501 6502 /* Read file */ 6503 for (line_id = 1, rule_id = 0; rule_id < *n_rules; line_id++) { 6504 char *tokens[CMD_MAX_TOKENS]; 6505 uint32_t n_tokens, n_tokens_parsed, t0; 6506 6507 /* Read next line from file. */ 6508 if (fgets(line, line_len_max + 1, f) == NULL) 6509 break; 6510 6511 /* Comment. */ 6512 if (is_comment(line)) 6513 continue; 6514 6515 /* Parse line. */ 6516 n_tokens = RTE_DIM(tokens); 6517 status = softnic_parse_tokenize_string(line, tokens, &n_tokens); 6518 if (status) { 6519 status = -EINVAL; 6520 break; 6521 } 6522 6523 /* Empty line. */ 6524 if (n_tokens == 0) 6525 continue; 6526 t0 = 0; 6527 6528 /* Rule match. */ 6529 n_tokens_parsed = parse_match(tokens + t0, 6530 n_tokens - t0, 6531 out, 6532 out_size, 6533 &m[rule_id]); 6534 if (n_tokens_parsed == 0) { 6535 status = -EINVAL; 6536 break; 6537 } 6538 t0 += n_tokens_parsed; 6539 6540 /* Rule action. */ 6541 n_tokens_parsed = parse_table_action(tokens + t0, 6542 n_tokens - t0, 6543 out, 6544 out_size, 6545 &a[rule_id]); 6546 if (n_tokens_parsed == 0) { 6547 status = -EINVAL; 6548 break; 6549 } 6550 t0 += n_tokens_parsed; 6551 6552 /* Line completed. */ 6553 if (t0 < n_tokens) { 6554 status = -EINVAL; 6555 break; 6556 } 6557 6558 /* Increment rule count */ 6559 rule_id++; 6560 } 6561 6562 /* Close file */ 6563 fclose(f); 6564 6565 /* Memory free */ 6566 free(line); 6567 6568 *n_rules = rule_id; 6569 *line_number = line_id; 6570 return status; 6571 } 6572