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 (params->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 (params->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 (params->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 (params->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 (params->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 (params->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 (params->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 (params->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 (params->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 (params->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 (params->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 (params->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 (params->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 } __rte_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 } __rte_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 } __rte_packed; 3382 3383 struct pkt_key_ipv4_addr { 3384 uint32_t addr; 3385 } __rte_packed; 3386 3387 struct pkt_key_ipv6_addr { 3388 uint8_t addr[16]; 3389 } __rte_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 free(p->cipher_auth.cipher_iv.val); 4486 free(p->cipher_auth.cipher_iv_update.val); 4487 break; 4488 case RTE_CRYPTO_SYM_XFORM_AUTH: 4489 if (p->cipher_auth.auth_iv.val) 4490 free(p->cipher_auth.cipher_iv.val); 4491 if (p->cipher_auth.auth_iv_update.val) 4492 free(p->cipher_auth.cipher_iv_update.val); 4493 break; 4494 case RTE_CRYPTO_SYM_XFORM_AEAD: 4495 free(p->aead.iv.val); 4496 free(p->aead.aad.val); 4497 break; 4498 default: 4499 continue; 4500 } 4501 } 4502 4503 } 4504 4505 static struct rte_crypto_sym_xform * 4506 parse_table_action_cipher(struct rte_table_action_sym_crypto_params *p, 4507 uint8_t *key, uint32_t max_key_len, char **tokens, 4508 uint32_t n_tokens, uint32_t encrypt, uint32_t *used_n_tokens) 4509 { 4510 struct rte_crypto_sym_xform *xform_cipher; 4511 int status; 4512 size_t len; 4513 4514 if (n_tokens < 7 || strcmp(tokens[1], "cipher_algo") || 4515 strcmp(tokens[3], "cipher_key") || 4516 strcmp(tokens[5], "cipher_iv")) 4517 return NULL; 4518 4519 xform_cipher = calloc(1, sizeof(*xform_cipher)); 4520 if (xform_cipher == NULL) 4521 return NULL; 4522 4523 xform_cipher->type = RTE_CRYPTO_SYM_XFORM_CIPHER; 4524 xform_cipher->cipher.op = encrypt ? RTE_CRYPTO_CIPHER_OP_ENCRYPT : 4525 RTE_CRYPTO_CIPHER_OP_DECRYPT; 4526 4527 /* cipher_algo */ 4528 status = rte_cryptodev_get_cipher_algo_enum( 4529 &xform_cipher->cipher.algo, tokens[2]); 4530 if (status < 0) 4531 goto error_exit; 4532 4533 /* cipher_key */ 4534 len = strlen(tokens[4]); 4535 if (len / 2 > max_key_len) { 4536 status = -ENOMEM; 4537 goto error_exit; 4538 } 4539 4540 status = softnic_parse_hex_string(tokens[4], key, (uint32_t *)&len); 4541 if (status < 0) 4542 goto error_exit; 4543 4544 xform_cipher->cipher.key.data = key; 4545 xform_cipher->cipher.key.length = (uint16_t)len; 4546 4547 /* cipher_iv */ 4548 len = strlen(tokens[6]); 4549 4550 p->cipher_auth.cipher_iv.val = calloc(1, len / 2 + 1); 4551 if (p->cipher_auth.cipher_iv.val == NULL) 4552 goto error_exit; 4553 4554 status = softnic_parse_hex_string(tokens[6], 4555 p->cipher_auth.cipher_iv.val, 4556 (uint32_t *)&len); 4557 if (status < 0) 4558 goto error_exit; 4559 4560 xform_cipher->cipher.iv.length = (uint16_t)len; 4561 xform_cipher->cipher.iv.offset = RTE_TABLE_ACTION_SYM_CRYPTO_IV_OFFSET; 4562 p->cipher_auth.cipher_iv.length = (uint32_t)len; 4563 *used_n_tokens = 7; 4564 4565 return xform_cipher; 4566 4567 error_exit: 4568 if (p->cipher_auth.cipher_iv.val) { 4569 free(p->cipher_auth.cipher_iv.val); 4570 p->cipher_auth.cipher_iv.val = NULL; 4571 } 4572 4573 free(xform_cipher); 4574 4575 return NULL; 4576 } 4577 4578 static struct rte_crypto_sym_xform * 4579 parse_table_action_cipher_auth(struct rte_table_action_sym_crypto_params *p, 4580 uint8_t *key, uint32_t max_key_len, char **tokens, 4581 uint32_t n_tokens, uint32_t encrypt, uint32_t *used_n_tokens) 4582 { 4583 struct rte_crypto_sym_xform *xform_cipher; 4584 struct rte_crypto_sym_xform *xform_auth; 4585 int status; 4586 size_t len; 4587 4588 if (n_tokens < 13 || 4589 strcmp(tokens[7], "auth_algo") || 4590 strcmp(tokens[9], "auth_key") || 4591 strcmp(tokens[11], "digest_size")) 4592 return NULL; 4593 4594 xform_auth = calloc(1, sizeof(*xform_auth)); 4595 if (xform_auth == NULL) 4596 return NULL; 4597 4598 xform_auth->type = RTE_CRYPTO_SYM_XFORM_AUTH; 4599 xform_auth->auth.op = encrypt ? RTE_CRYPTO_AUTH_OP_GENERATE : 4600 RTE_CRYPTO_AUTH_OP_VERIFY; 4601 4602 /* auth_algo */ 4603 status = rte_cryptodev_get_auth_algo_enum(&xform_auth->auth.algo, 4604 tokens[8]); 4605 if (status < 0) 4606 goto error_exit; 4607 4608 /* auth_key */ 4609 len = strlen(tokens[10]); 4610 if (len / 2 > max_key_len) { 4611 status = -ENOMEM; 4612 goto error_exit; 4613 } 4614 4615 status = softnic_parse_hex_string(tokens[10], key, (uint32_t *)&len); 4616 if (status < 0) 4617 goto error_exit; 4618 4619 xform_auth->auth.key.data = key; 4620 xform_auth->auth.key.length = (uint16_t)len; 4621 4622 key += xform_auth->auth.key.length; 4623 max_key_len -= xform_auth->auth.key.length; 4624 4625 if (strcmp(tokens[11], "digest_size")) 4626 goto error_exit; 4627 4628 status = softnic_parser_read_uint16(&xform_auth->auth.digest_length, 4629 tokens[12]); 4630 if (status < 0) 4631 goto error_exit; 4632 4633 xform_cipher = parse_table_action_cipher(p, key, max_key_len, tokens, 7, 4634 encrypt, used_n_tokens); 4635 if (xform_cipher == NULL) 4636 goto error_exit; 4637 4638 *used_n_tokens += 6; 4639 4640 if (encrypt) { 4641 xform_cipher->next = xform_auth; 4642 return xform_cipher; 4643 } else { 4644 xform_auth->next = xform_cipher; 4645 return xform_auth; 4646 } 4647 4648 error_exit: 4649 if (p->cipher_auth.auth_iv.val) { 4650 free(p->cipher_auth.auth_iv.val); 4651 p->cipher_auth.auth_iv.val = 0; 4652 } 4653 4654 free(xform_auth); 4655 4656 return NULL; 4657 } 4658 4659 static struct rte_crypto_sym_xform * 4660 parse_table_action_aead(struct rte_table_action_sym_crypto_params *p, 4661 uint8_t *key, uint32_t max_key_len, char **tokens, 4662 uint32_t n_tokens, uint32_t encrypt, uint32_t *used_n_tokens) 4663 { 4664 struct rte_crypto_sym_xform *xform_aead; 4665 int status; 4666 size_t len; 4667 4668 if (n_tokens < 11 || strcmp(tokens[1], "aead_algo") || 4669 strcmp(tokens[3], "aead_key") || 4670 strcmp(tokens[5], "aead_iv") || 4671 strcmp(tokens[7], "aead_aad") || 4672 strcmp(tokens[9], "digest_size")) 4673 return NULL; 4674 4675 xform_aead = calloc(1, sizeof(*xform_aead)); 4676 if (xform_aead == NULL) 4677 return NULL; 4678 4679 xform_aead->type = RTE_CRYPTO_SYM_XFORM_AEAD; 4680 xform_aead->aead.op = encrypt ? RTE_CRYPTO_AEAD_OP_ENCRYPT : 4681 RTE_CRYPTO_AEAD_OP_DECRYPT; 4682 4683 /* aead_algo */ 4684 status = rte_cryptodev_get_aead_algo_enum(&xform_aead->aead.algo, 4685 tokens[2]); 4686 if (status < 0) 4687 goto error_exit; 4688 4689 /* aead_key */ 4690 len = strlen(tokens[4]); 4691 if (len / 2 > max_key_len) { 4692 status = -ENOMEM; 4693 goto error_exit; 4694 } 4695 4696 status = softnic_parse_hex_string(tokens[4], key, (uint32_t *)&len); 4697 if (status < 0) 4698 goto error_exit; 4699 4700 xform_aead->aead.key.data = key; 4701 xform_aead->aead.key.length = (uint16_t)len; 4702 4703 /* aead_iv */ 4704 len = strlen(tokens[6]); 4705 p->aead.iv.val = calloc(1, len / 2 + 1); 4706 if (p->aead.iv.val == NULL) 4707 goto error_exit; 4708 4709 status = softnic_parse_hex_string(tokens[6], p->aead.iv.val, 4710 (uint32_t *)&len); 4711 if (status < 0) 4712 goto error_exit; 4713 4714 xform_aead->aead.iv.length = (uint16_t)len; 4715 xform_aead->aead.iv.offset = RTE_TABLE_ACTION_SYM_CRYPTO_IV_OFFSET; 4716 p->aead.iv.length = (uint32_t)len; 4717 4718 /* aead_aad */ 4719 len = strlen(tokens[8]); 4720 p->aead.aad.val = calloc(1, len / 2 + 1); 4721 if (p->aead.aad.val == NULL) 4722 goto error_exit; 4723 4724 status = softnic_parse_hex_string(tokens[8], p->aead.aad.val, (uint32_t *)&len); 4725 if (status < 0) 4726 goto error_exit; 4727 4728 xform_aead->aead.aad_length = (uint16_t)len; 4729 p->aead.aad.length = (uint32_t)len; 4730 4731 /* digest_size */ 4732 status = softnic_parser_read_uint16(&xform_aead->aead.digest_length, 4733 tokens[10]); 4734 if (status < 0) 4735 goto error_exit; 4736 4737 *used_n_tokens = 11; 4738 4739 return xform_aead; 4740 4741 error_exit: 4742 if (p->aead.iv.val) { 4743 free(p->aead.iv.val); 4744 p->aead.iv.val = NULL; 4745 } 4746 if (p->aead.aad.val) { 4747 free(p->aead.aad.val); 4748 p->aead.aad.val = NULL; 4749 } 4750 4751 free(xform_aead); 4752 4753 return NULL; 4754 } 4755 4756 4757 static uint32_t 4758 parse_table_action_sym_crypto(char **tokens, 4759 uint32_t n_tokens, 4760 struct softnic_table_rule_action *a) 4761 { 4762 struct rte_table_action_sym_crypto_params *p = &a->sym_crypto; 4763 struct rte_crypto_sym_xform *xform = NULL; 4764 uint8_t *key = a->sym_crypto_key; 4765 uint32_t max_key_len = SYM_CRYPTO_MAX_KEY_SIZE; 4766 uint32_t used_n_tokens; 4767 uint32_t encrypt; 4768 int status; 4769 4770 if ((n_tokens < 12) || 4771 strcmp(tokens[0], "sym_crypto") || 4772 strcmp(tokens[2], "type")) 4773 return 0; 4774 4775 memset(p, 0, sizeof(*p)); 4776 4777 if (strcmp(tokens[1], "encrypt") == 0) 4778 encrypt = 1; 4779 else 4780 encrypt = 0; 4781 4782 status = softnic_parser_read_uint32(&p->data_offset, tokens[n_tokens - 1]); 4783 if (status < 0) 4784 return 0; 4785 4786 if (strcmp(tokens[3], "cipher") == 0) { 4787 tokens += 3; 4788 n_tokens -= 3; 4789 4790 xform = parse_table_action_cipher(p, key, max_key_len, tokens, 4791 n_tokens, encrypt, &used_n_tokens); 4792 } else if (strcmp(tokens[3], "cipher_auth") == 0) { 4793 tokens += 3; 4794 n_tokens -= 3; 4795 4796 xform = parse_table_action_cipher_auth(p, key, max_key_len, 4797 tokens, n_tokens, encrypt, &used_n_tokens); 4798 } else if (strcmp(tokens[3], "aead") == 0) { 4799 tokens += 3; 4800 n_tokens -= 3; 4801 4802 xform = parse_table_action_aead(p, key, max_key_len, tokens, 4803 n_tokens, encrypt, &used_n_tokens); 4804 } 4805 4806 if (xform == NULL) 4807 return 0; 4808 4809 p->xform = xform; 4810 4811 if (strcmp(tokens[used_n_tokens], "data_offset")) { 4812 parse_free_sym_crypto_param_data(p); 4813 return 0; 4814 } 4815 4816 a->action_mask |= 1 << RTE_TABLE_ACTION_SYM_CRYPTO; 4817 4818 return used_n_tokens + 5; 4819 } 4820 4821 static uint32_t 4822 parse_table_action_tag(char **tokens, 4823 uint32_t n_tokens, 4824 struct softnic_table_rule_action *a) 4825 { 4826 if (n_tokens < 2 || 4827 strcmp(tokens[0], "tag")) 4828 return 0; 4829 4830 if (softnic_parser_read_uint32(&a->tag.tag, tokens[1])) 4831 return 0; 4832 4833 a->action_mask |= 1 << RTE_TABLE_ACTION_TAG; 4834 return 2; 4835 } 4836 4837 static uint32_t 4838 parse_table_action_decap(char **tokens, 4839 uint32_t n_tokens, 4840 struct softnic_table_rule_action *a) 4841 { 4842 if (n_tokens < 2 || 4843 strcmp(tokens[0], "decap")) 4844 return 0; 4845 4846 if (softnic_parser_read_uint16(&a->decap.n, tokens[1])) 4847 return 0; 4848 4849 a->action_mask |= 1 << RTE_TABLE_ACTION_DECAP; 4850 return 2; 4851 } 4852 4853 static uint32_t 4854 parse_table_action(char **tokens, 4855 uint32_t n_tokens, 4856 char *out, 4857 size_t out_size, 4858 struct softnic_table_rule_action *a) 4859 { 4860 uint32_t n_tokens0 = n_tokens; 4861 4862 memset(a, 0, sizeof(*a)); 4863 4864 if (n_tokens < 2 || 4865 strcmp(tokens[0], "action")) 4866 return 0; 4867 4868 tokens++; 4869 n_tokens--; 4870 4871 if (n_tokens && (strcmp(tokens[0], "fwd") == 0)) { 4872 uint32_t n; 4873 4874 n = parse_table_action_fwd(tokens, n_tokens, a); 4875 if (n == 0) { 4876 snprintf(out, out_size, MSG_ARG_INVALID, 4877 "action fwd"); 4878 return 0; 4879 } 4880 4881 tokens += n; 4882 n_tokens -= n; 4883 } 4884 4885 if (n_tokens && (strcmp(tokens[0], "balance") == 0)) { 4886 uint32_t n; 4887 4888 n = parse_table_action_balance(tokens, n_tokens, a); 4889 if (n == 0) { 4890 snprintf(out, out_size, MSG_ARG_INVALID, 4891 "action balance"); 4892 return 0; 4893 } 4894 4895 tokens += n; 4896 n_tokens -= n; 4897 } 4898 4899 if (n_tokens && (strcmp(tokens[0], "meter") == 0)) { 4900 uint32_t n; 4901 4902 n = parse_table_action_meter(tokens, n_tokens, a); 4903 if (n == 0) { 4904 snprintf(out, out_size, MSG_ARG_INVALID, 4905 "action meter"); 4906 return 0; 4907 } 4908 4909 tokens += n; 4910 n_tokens -= n; 4911 } 4912 4913 if (n_tokens && (strcmp(tokens[0], "tm") == 0)) { 4914 uint32_t n; 4915 4916 n = parse_table_action_tm(tokens, n_tokens, a); 4917 if (n == 0) { 4918 snprintf(out, out_size, MSG_ARG_INVALID, 4919 "action tm"); 4920 return 0; 4921 } 4922 4923 tokens += n; 4924 n_tokens -= n; 4925 } 4926 4927 if (n_tokens && (strcmp(tokens[0], "encap") == 0)) { 4928 uint32_t n; 4929 4930 n = parse_table_action_encap(tokens, n_tokens, a); 4931 if (n == 0) { 4932 snprintf(out, out_size, MSG_ARG_INVALID, 4933 "action encap"); 4934 return 0; 4935 } 4936 4937 tokens += n; 4938 n_tokens -= n; 4939 } 4940 4941 if (n_tokens && (strcmp(tokens[0], "nat") == 0)) { 4942 uint32_t n; 4943 4944 n = parse_table_action_nat(tokens, n_tokens, a); 4945 if (n == 0) { 4946 snprintf(out, out_size, MSG_ARG_INVALID, 4947 "action nat"); 4948 return 0; 4949 } 4950 4951 tokens += n; 4952 n_tokens -= n; 4953 } 4954 4955 if (n_tokens && (strcmp(tokens[0], "ttl") == 0)) { 4956 uint32_t n; 4957 4958 n = parse_table_action_ttl(tokens, n_tokens, a); 4959 if (n == 0) { 4960 snprintf(out, out_size, MSG_ARG_INVALID, 4961 "action ttl"); 4962 return 0; 4963 } 4964 4965 tokens += n; 4966 n_tokens -= n; 4967 } 4968 4969 if (n_tokens && (strcmp(tokens[0], "stats") == 0)) { 4970 uint32_t n; 4971 4972 n = parse_table_action_stats(tokens, n_tokens, a); 4973 if (n == 0) { 4974 snprintf(out, out_size, MSG_ARG_INVALID, 4975 "action stats"); 4976 return 0; 4977 } 4978 4979 tokens += n; 4980 n_tokens -= n; 4981 } 4982 4983 if (n_tokens && (strcmp(tokens[0], "time") == 0)) { 4984 uint32_t n; 4985 4986 n = parse_table_action_time(tokens, n_tokens, a); 4987 if (n == 0) { 4988 snprintf(out, out_size, MSG_ARG_INVALID, 4989 "action time"); 4990 return 0; 4991 } 4992 4993 tokens += n; 4994 n_tokens -= n; 4995 } 4996 4997 if (n_tokens && (strcmp(tokens[0], "tag") == 0)) { 4998 uint32_t n; 4999 5000 n = parse_table_action_tag(tokens, n_tokens, a); 5001 if (n == 0) { 5002 snprintf(out, out_size, MSG_ARG_INVALID, 5003 "action tag"); 5004 return 0; 5005 } 5006 5007 tokens += n; 5008 n_tokens -= n; 5009 } 5010 5011 if (n_tokens && (strcmp(tokens[0], "decap") == 0)) { 5012 uint32_t n; 5013 5014 n = parse_table_action_decap(tokens, n_tokens, a); 5015 if (n == 0) { 5016 snprintf(out, out_size, MSG_ARG_INVALID, 5017 "action decap"); 5018 return 0; 5019 } 5020 5021 tokens += n; 5022 n_tokens -= n; 5023 } 5024 5025 if (n_tokens && (strcmp(tokens[0], "sym_crypto") == 0)) { 5026 uint32_t n; 5027 5028 n = parse_table_action_sym_crypto(tokens, n_tokens, a); 5029 if (n == 0) { 5030 snprintf(out, out_size, MSG_ARG_INVALID, 5031 "action sym_crypto"); 5032 } 5033 5034 tokens += n; 5035 n_tokens -= n; 5036 } 5037 5038 if (n_tokens0 - n_tokens == 1) { 5039 snprintf(out, out_size, MSG_ARG_INVALID, "action"); 5040 return 0; 5041 } 5042 5043 return n_tokens0 - n_tokens; 5044 } 5045 5046 /** 5047 * pipeline <pipeline_name> table <table_id> rule add 5048 * match <match> 5049 * action <table_action> 5050 */ 5051 static void 5052 cmd_softnic_pipeline_table_rule_add(struct pmd_internals *softnic, 5053 char **tokens, 5054 uint32_t n_tokens, 5055 char *out, 5056 size_t out_size) 5057 { 5058 struct softnic_table_rule_match m; 5059 struct softnic_table_rule_action a; 5060 char *pipeline_name; 5061 void *data; 5062 uint32_t table_id, t0, n_tokens_parsed; 5063 int status; 5064 5065 if (n_tokens < 8) { 5066 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5067 return; 5068 } 5069 5070 pipeline_name = tokens[1]; 5071 5072 if (strcmp(tokens[2], "table") != 0) { 5073 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); 5074 return; 5075 } 5076 5077 if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) { 5078 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 5079 return; 5080 } 5081 5082 if (strcmp(tokens[4], "rule") != 0) { 5083 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule"); 5084 return; 5085 } 5086 5087 if (strcmp(tokens[5], "add") != 0) { 5088 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add"); 5089 return; 5090 } 5091 5092 t0 = 6; 5093 5094 /* match */ 5095 n_tokens_parsed = parse_match(tokens + t0, 5096 n_tokens - t0, 5097 out, 5098 out_size, 5099 &m); 5100 if (n_tokens_parsed == 0) 5101 return; 5102 t0 += n_tokens_parsed; 5103 5104 /* action */ 5105 n_tokens_parsed = parse_table_action(tokens + t0, 5106 n_tokens - t0, 5107 out, 5108 out_size, 5109 &a); 5110 if (n_tokens_parsed == 0) 5111 return; 5112 t0 += n_tokens_parsed; 5113 5114 if (t0 != n_tokens) { 5115 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]); 5116 return; 5117 } 5118 5119 status = softnic_pipeline_table_rule_add(softnic, 5120 pipeline_name, 5121 table_id, 5122 &m, 5123 &a, 5124 &data); 5125 if (status) { 5126 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 5127 return; 5128 } 5129 } 5130 5131 /** 5132 * pipeline <pipeline_name> table <table_id> rule add 5133 * match 5134 * default 5135 * action 5136 * fwd 5137 * drop 5138 * | port <port_id> 5139 * | meta 5140 * | table <table_id> 5141 */ 5142 static void 5143 cmd_softnic_pipeline_table_rule_add_default(struct pmd_internals *softnic, 5144 char **tokens, 5145 uint32_t n_tokens, 5146 char *out, 5147 size_t out_size) 5148 { 5149 struct softnic_table_rule_action action; 5150 void *data; 5151 char *pipeline_name; 5152 uint32_t table_id; 5153 int status; 5154 5155 if (n_tokens != 11 && 5156 n_tokens != 12) { 5157 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5158 return; 5159 } 5160 5161 pipeline_name = tokens[1]; 5162 5163 if (strcmp(tokens[2], "table") != 0) { 5164 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); 5165 return; 5166 } 5167 5168 if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) { 5169 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 5170 return; 5171 } 5172 5173 if (strcmp(tokens[4], "rule") != 0) { 5174 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule"); 5175 return; 5176 } 5177 5178 if (strcmp(tokens[5], "add") != 0) { 5179 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add"); 5180 return; 5181 } 5182 5183 if (strcmp(tokens[6], "match") != 0) { 5184 snprintf(out, out_size, MSG_ARG_INVALID, "match"); 5185 return; 5186 } 5187 5188 if (strcmp(tokens[7], "default") != 0) { 5189 snprintf(out, out_size, MSG_ARG_INVALID, "default"); 5190 return; 5191 } 5192 5193 if (strcmp(tokens[8], "action") != 0) { 5194 snprintf(out, out_size, MSG_ARG_INVALID, "action"); 5195 return; 5196 } 5197 5198 if (strcmp(tokens[9], "fwd") != 0) { 5199 snprintf(out, out_size, MSG_ARG_INVALID, "fwd"); 5200 return; 5201 } 5202 5203 action.action_mask = 1 << RTE_TABLE_ACTION_FWD; 5204 5205 if (strcmp(tokens[10], "drop") == 0) { 5206 if (n_tokens != 11) { 5207 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5208 return; 5209 } 5210 5211 action.fwd.action = RTE_PIPELINE_ACTION_DROP; 5212 } else if (strcmp(tokens[10], "port") == 0) { 5213 uint32_t id; 5214 5215 if (n_tokens != 12) { 5216 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5217 return; 5218 } 5219 5220 if (softnic_parser_read_uint32(&id, tokens[11]) != 0) { 5221 snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); 5222 return; 5223 } 5224 5225 action.fwd.action = RTE_PIPELINE_ACTION_PORT; 5226 action.fwd.id = id; 5227 } else if (strcmp(tokens[10], "meta") == 0) { 5228 if (n_tokens != 11) { 5229 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5230 return; 5231 } 5232 5233 action.fwd.action = RTE_PIPELINE_ACTION_PORT_META; 5234 } else if (strcmp(tokens[10], "table") == 0) { 5235 uint32_t id; 5236 5237 if (n_tokens != 12) { 5238 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5239 return; 5240 } 5241 5242 if (softnic_parser_read_uint32(&id, tokens[11]) != 0) { 5243 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 5244 return; 5245 } 5246 5247 action.fwd.action = RTE_PIPELINE_ACTION_TABLE; 5248 action.fwd.id = id; 5249 } else { 5250 snprintf(out, out_size, MSG_ARG_INVALID, 5251 "drop or port or meta or table"); 5252 return; 5253 } 5254 5255 status = softnic_pipeline_table_rule_add_default(softnic, 5256 pipeline_name, 5257 table_id, 5258 &action, 5259 &data); 5260 if (status) { 5261 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 5262 return; 5263 } 5264 } 5265 5266 /** 5267 * pipeline <pipeline_name> table <table_id> rule add bulk <file_name> <n_rules> 5268 * 5269 * File <file_name>: 5270 * - line format: match <match> action <action> 5271 */ 5272 static int 5273 cli_rule_file_process(const char *file_name, 5274 size_t line_len_max, 5275 struct softnic_table_rule_match *m, 5276 struct softnic_table_rule_action *a, 5277 uint32_t *n_rules, 5278 uint32_t *line_number, 5279 char *out, 5280 size_t out_size); 5281 5282 static void 5283 cmd_softnic_pipeline_table_rule_add_bulk(struct pmd_internals *softnic, 5284 char **tokens, 5285 uint32_t n_tokens, 5286 char *out, 5287 size_t out_size) 5288 { 5289 struct softnic_table_rule_match *match; 5290 struct softnic_table_rule_action *action; 5291 void **data; 5292 char *pipeline_name, *file_name; 5293 uint32_t table_id, n_rules, n_rules_parsed, line_number; 5294 int status; 5295 5296 if (n_tokens != 9) { 5297 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5298 return; 5299 } 5300 5301 pipeline_name = tokens[1]; 5302 5303 if (strcmp(tokens[2], "table") != 0) { 5304 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); 5305 return; 5306 } 5307 5308 if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) { 5309 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 5310 return; 5311 } 5312 5313 if (strcmp(tokens[4], "rule") != 0) { 5314 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule"); 5315 return; 5316 } 5317 5318 if (strcmp(tokens[5], "add") != 0) { 5319 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add"); 5320 return; 5321 } 5322 5323 if (strcmp(tokens[6], "bulk") != 0) { 5324 snprintf(out, out_size, MSG_ARG_INVALID, "bulk"); 5325 return; 5326 } 5327 5328 file_name = tokens[7]; 5329 5330 if ((softnic_parser_read_uint32(&n_rules, tokens[8]) != 0) || 5331 n_rules == 0) { 5332 snprintf(out, out_size, MSG_ARG_INVALID, "n_rules"); 5333 return; 5334 } 5335 5336 /* Memory allocation. */ 5337 match = calloc(n_rules, sizeof(struct softnic_table_rule_match)); 5338 action = calloc(n_rules, sizeof(struct softnic_table_rule_action)); 5339 data = calloc(n_rules, sizeof(void *)); 5340 if (match == NULL || 5341 action == NULL || 5342 data == NULL) { 5343 snprintf(out, out_size, MSG_OUT_OF_MEMORY); 5344 free(data); 5345 free(action); 5346 free(match); 5347 return; 5348 } 5349 5350 /* Load rule file */ 5351 n_rules_parsed = n_rules; 5352 status = cli_rule_file_process(file_name, 5353 1024, 5354 match, 5355 action, 5356 &n_rules_parsed, 5357 &line_number, 5358 out, 5359 out_size); 5360 if (status) { 5361 snprintf(out, out_size, MSG_FILE_ERR, file_name, line_number); 5362 free(data); 5363 free(action); 5364 free(match); 5365 return; 5366 } 5367 if (n_rules_parsed != n_rules) { 5368 snprintf(out, out_size, MSG_FILE_NOT_ENOUGH, file_name); 5369 free(data); 5370 free(action); 5371 free(match); 5372 return; 5373 } 5374 5375 /* Rule bulk add */ 5376 status = softnic_pipeline_table_rule_add_bulk(softnic, 5377 pipeline_name, 5378 table_id, 5379 match, 5380 action, 5381 data, 5382 &n_rules); 5383 if (status) { 5384 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 5385 free(data); 5386 free(action); 5387 free(match); 5388 return; 5389 } 5390 5391 /* Memory free */ 5392 free(data); 5393 free(action); 5394 free(match); 5395 } 5396 5397 /** 5398 * pipeline <pipeline_name> table <table_id> rule delete 5399 * match <match> 5400 */ 5401 static void 5402 cmd_softnic_pipeline_table_rule_delete(struct pmd_internals *softnic, 5403 char **tokens, 5404 uint32_t n_tokens, 5405 char *out, 5406 size_t out_size) 5407 { 5408 struct softnic_table_rule_match m; 5409 char *pipeline_name; 5410 uint32_t table_id, n_tokens_parsed, t0; 5411 int status; 5412 5413 if (n_tokens < 8) { 5414 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5415 return; 5416 } 5417 5418 pipeline_name = tokens[1]; 5419 5420 if (strcmp(tokens[2], "table") != 0) { 5421 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); 5422 return; 5423 } 5424 5425 if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) { 5426 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 5427 return; 5428 } 5429 5430 if (strcmp(tokens[4], "rule") != 0) { 5431 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule"); 5432 return; 5433 } 5434 5435 if (strcmp(tokens[5], "delete") != 0) { 5436 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete"); 5437 return; 5438 } 5439 5440 t0 = 6; 5441 5442 /* match */ 5443 n_tokens_parsed = parse_match(tokens + t0, 5444 n_tokens - t0, 5445 out, 5446 out_size, 5447 &m); 5448 if (n_tokens_parsed == 0) 5449 return; 5450 t0 += n_tokens_parsed; 5451 5452 if (n_tokens != t0) { 5453 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5454 return; 5455 } 5456 5457 status = softnic_pipeline_table_rule_delete(softnic, 5458 pipeline_name, 5459 table_id, 5460 &m); 5461 if (status) { 5462 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 5463 return; 5464 } 5465 } 5466 5467 /** 5468 * pipeline <pipeline_name> table <table_id> rule delete 5469 * match 5470 * default 5471 */ 5472 static void 5473 cmd_softnic_pipeline_table_rule_delete_default(struct pmd_internals *softnic, 5474 char **tokens, 5475 uint32_t n_tokens, 5476 char *out, 5477 size_t out_size) 5478 { 5479 char *pipeline_name; 5480 uint32_t table_id; 5481 int status; 5482 5483 if (n_tokens != 8) { 5484 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5485 return; 5486 } 5487 5488 pipeline_name = tokens[1]; 5489 5490 if (strcmp(tokens[2], "table") != 0) { 5491 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); 5492 return; 5493 } 5494 5495 if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) { 5496 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 5497 return; 5498 } 5499 5500 if (strcmp(tokens[4], "rule") != 0) { 5501 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rule"); 5502 return; 5503 } 5504 5505 if (strcmp(tokens[5], "delete") != 0) { 5506 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete"); 5507 return; 5508 } 5509 5510 if (strcmp(tokens[6], "match") != 0) { 5511 snprintf(out, out_size, MSG_ARG_INVALID, "match"); 5512 return; 5513 } 5514 5515 if (strcmp(tokens[7], "default") != 0) { 5516 snprintf(out, out_size, MSG_ARG_INVALID, "default"); 5517 return; 5518 } 5519 5520 status = softnic_pipeline_table_rule_delete_default(softnic, 5521 pipeline_name, 5522 table_id); 5523 if (status) { 5524 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 5525 return; 5526 } 5527 } 5528 5529 /** 5530 * pipeline <pipeline_name> table <table_id> rule read stats [clear] 5531 */ 5532 static void 5533 cmd_softnic_pipeline_table_rule_stats_read(struct pmd_internals *softnic __rte_unused, 5534 char **tokens, 5535 uint32_t n_tokens __rte_unused, 5536 char *out, 5537 size_t out_size) 5538 { 5539 snprintf(out, out_size, MSG_CMD_UNIMPLEM, tokens[0]); 5540 } 5541 5542 /** 5543 * pipeline <pipeline_name> table <table_id> meter profile <meter_profile_id> 5544 * add srtcm cir <cir> cbs <cbs> ebs <ebs> 5545 * | trtcm cir <cir> pir <pir> cbs <cbs> pbs <pbs> 5546 */ 5547 static void 5548 cmd_pipeline_table_meter_profile_add(struct pmd_internals *softnic, 5549 char **tokens, 5550 uint32_t n_tokens, 5551 char *out, 5552 size_t out_size) 5553 { 5554 struct rte_table_action_meter_profile p; 5555 char *pipeline_name; 5556 uint32_t table_id, meter_profile_id; 5557 int status; 5558 5559 if (n_tokens < 9) { 5560 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5561 return; 5562 } 5563 5564 pipeline_name = tokens[1]; 5565 5566 if (strcmp(tokens[2], "table") != 0) { 5567 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 5568 return; 5569 } 5570 5571 if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) { 5572 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 5573 return; 5574 } 5575 5576 if (strcmp(tokens[4], "meter") != 0) { 5577 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter"); 5578 return; 5579 } 5580 5581 if (strcmp(tokens[5], "profile") != 0) { 5582 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile"); 5583 return; 5584 } 5585 5586 if (softnic_parser_read_uint32(&meter_profile_id, tokens[6]) != 0) { 5587 snprintf(out, out_size, MSG_ARG_INVALID, "meter_profile_id"); 5588 return; 5589 } 5590 5591 if (strcmp(tokens[7], "add") != 0) { 5592 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "add"); 5593 return; 5594 } 5595 5596 if (strcmp(tokens[8], "srtcm") == 0) { 5597 if (n_tokens != 15) { 5598 snprintf(out, out_size, MSG_ARG_MISMATCH, 5599 tokens[0]); 5600 return; 5601 } 5602 5603 p.alg = RTE_TABLE_ACTION_METER_SRTCM; 5604 5605 if (strcmp(tokens[9], "cir") != 0) { 5606 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cir"); 5607 return; 5608 } 5609 5610 if (softnic_parser_read_uint64(&p.srtcm.cir, tokens[10]) != 0) { 5611 snprintf(out, out_size, MSG_ARG_INVALID, "cir"); 5612 return; 5613 } 5614 5615 if (strcmp(tokens[11], "cbs") != 0) { 5616 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cbs"); 5617 return; 5618 } 5619 5620 if (softnic_parser_read_uint64(&p.srtcm.cbs, tokens[12]) != 0) { 5621 snprintf(out, out_size, MSG_ARG_INVALID, "cbs"); 5622 return; 5623 } 5624 5625 if (strcmp(tokens[13], "ebs") != 0) { 5626 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "ebs"); 5627 return; 5628 } 5629 5630 if (softnic_parser_read_uint64(&p.srtcm.ebs, tokens[14]) != 0) { 5631 snprintf(out, out_size, MSG_ARG_INVALID, "ebs"); 5632 return; 5633 } 5634 } else if (strcmp(tokens[8], "trtcm") == 0) { 5635 if (n_tokens != 17) { 5636 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5637 return; 5638 } 5639 5640 p.alg = RTE_TABLE_ACTION_METER_TRTCM; 5641 5642 if (strcmp(tokens[9], "cir") != 0) { 5643 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cir"); 5644 return; 5645 } 5646 5647 if (softnic_parser_read_uint64(&p.trtcm.cir, tokens[10]) != 0) { 5648 snprintf(out, out_size, MSG_ARG_INVALID, "cir"); 5649 return; 5650 } 5651 5652 if (strcmp(tokens[11], "pir") != 0) { 5653 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pir"); 5654 return; 5655 } 5656 5657 if (softnic_parser_read_uint64(&p.trtcm.pir, tokens[12]) != 0) { 5658 snprintf(out, out_size, MSG_ARG_INVALID, "pir"); 5659 return; 5660 } 5661 if (strcmp(tokens[13], "cbs") != 0) { 5662 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cbs"); 5663 return; 5664 } 5665 5666 if (softnic_parser_read_uint64(&p.trtcm.cbs, tokens[14]) != 0) { 5667 snprintf(out, out_size, MSG_ARG_INVALID, "cbs"); 5668 return; 5669 } 5670 5671 if (strcmp(tokens[15], "pbs") != 0) { 5672 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pbs"); 5673 return; 5674 } 5675 5676 if (softnic_parser_read_uint64(&p.trtcm.pbs, tokens[16]) != 0) { 5677 snprintf(out, out_size, MSG_ARG_INVALID, "pbs"); 5678 return; 5679 } 5680 } else { 5681 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5682 return; 5683 } 5684 5685 status = softnic_pipeline_table_mtr_profile_add(softnic, 5686 pipeline_name, 5687 table_id, 5688 meter_profile_id, 5689 &p); 5690 if (status) { 5691 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 5692 return; 5693 } 5694 } 5695 5696 /** 5697 * pipeline <pipeline_name> table <table_id> 5698 * meter profile <meter_profile_id> delete 5699 */ 5700 static void 5701 cmd_pipeline_table_meter_profile_delete(struct pmd_internals *softnic, 5702 char **tokens, 5703 uint32_t n_tokens, 5704 char *out, 5705 size_t out_size) 5706 { 5707 char *pipeline_name; 5708 uint32_t table_id, meter_profile_id; 5709 int status; 5710 5711 if (n_tokens != 8) { 5712 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5713 return; 5714 } 5715 5716 pipeline_name = tokens[1]; 5717 5718 if (strcmp(tokens[2], "table") != 0) { 5719 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 5720 return; 5721 } 5722 5723 if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) { 5724 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 5725 return; 5726 } 5727 5728 if (strcmp(tokens[4], "meter") != 0) { 5729 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "meter"); 5730 return; 5731 } 5732 5733 if (strcmp(tokens[5], "profile") != 0) { 5734 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile"); 5735 return; 5736 } 5737 5738 if (softnic_parser_read_uint32(&meter_profile_id, tokens[6]) != 0) { 5739 snprintf(out, out_size, MSG_ARG_INVALID, "meter_profile_id"); 5740 return; 5741 } 5742 5743 if (strcmp(tokens[7], "delete") != 0) { 5744 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "delete"); 5745 return; 5746 } 5747 5748 status = softnic_pipeline_table_mtr_profile_delete(softnic, 5749 pipeline_name, 5750 table_id, 5751 meter_profile_id); 5752 if (status) { 5753 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 5754 return; 5755 } 5756 } 5757 5758 /** 5759 * pipeline <pipeline_name> table <table_id> rule read meter [clear] 5760 */ 5761 static void 5762 cmd_pipeline_table_rule_meter_read(struct pmd_internals *softnic __rte_unused, 5763 char **tokens, 5764 uint32_t n_tokens __rte_unused, 5765 char *out, 5766 size_t out_size) 5767 { 5768 snprintf(out, out_size, MSG_CMD_UNIMPLEM, tokens[0]); 5769 } 5770 5771 /** 5772 * pipeline <pipeline_name> table <table_id> dscp <file_name> 5773 * 5774 * File <file_name>: 5775 * - exactly 64 lines 5776 * - line format: <tc_id> <tc_queue_id> <color>, with <color> as: g | y | r 5777 */ 5778 static int 5779 load_dscp_table(struct rte_table_action_dscp_table *dscp_table, 5780 const char *file_name, 5781 uint32_t *line_number) 5782 { 5783 FILE *f = NULL; 5784 uint32_t dscp, l; 5785 5786 /* Check input arguments */ 5787 if (dscp_table == NULL || 5788 file_name == NULL || 5789 line_number == NULL) { 5790 if (line_number) 5791 *line_number = 0; 5792 return -EINVAL; 5793 } 5794 5795 /* Open input file */ 5796 f = fopen(file_name, "r"); 5797 if (f == NULL) { 5798 *line_number = 0; 5799 return -EINVAL; 5800 } 5801 5802 /* Read file */ 5803 for (dscp = 0, l = 1; ; l++) { 5804 char line[64]; 5805 char *tokens[3]; 5806 enum rte_color color; 5807 uint32_t tc_id, tc_queue_id, n_tokens = RTE_DIM(tokens); 5808 5809 if (fgets(line, sizeof(line), f) == NULL) 5810 break; 5811 5812 if (is_comment(line)) 5813 continue; 5814 5815 if (softnic_parse_tokenize_string(line, tokens, &n_tokens)) { 5816 *line_number = l; 5817 fclose(f); 5818 return -EINVAL; 5819 } 5820 5821 if (n_tokens == 0) 5822 continue; 5823 5824 if (dscp >= RTE_DIM(dscp_table->entry) || 5825 n_tokens != RTE_DIM(tokens) || 5826 softnic_parser_read_uint32(&tc_id, tokens[0]) || 5827 tc_id >= RTE_TABLE_ACTION_TC_MAX || 5828 softnic_parser_read_uint32(&tc_queue_id, tokens[1]) || 5829 tc_queue_id >= RTE_TABLE_ACTION_TC_QUEUE_MAX || 5830 (strlen(tokens[2]) != 1)) { 5831 *line_number = l; 5832 fclose(f); 5833 return -EINVAL; 5834 } 5835 5836 switch (tokens[2][0]) { 5837 case 'g': 5838 case 'G': 5839 color = RTE_COLOR_GREEN; 5840 break; 5841 5842 case 'y': 5843 case 'Y': 5844 color = RTE_COLOR_YELLOW; 5845 break; 5846 5847 case 'r': 5848 case 'R': 5849 color = RTE_COLOR_RED; 5850 break; 5851 5852 default: 5853 *line_number = l; 5854 fclose(f); 5855 return -EINVAL; 5856 } 5857 5858 dscp_table->entry[dscp].tc_id = tc_id; 5859 dscp_table->entry[dscp].tc_queue_id = tc_queue_id; 5860 dscp_table->entry[dscp].color = color; 5861 dscp++; 5862 } 5863 5864 /* Close file */ 5865 fclose(f); 5866 return 0; 5867 } 5868 5869 static void 5870 cmd_pipeline_table_dscp(struct pmd_internals *softnic, 5871 char **tokens, 5872 uint32_t n_tokens, 5873 char *out, 5874 size_t out_size) 5875 { 5876 struct rte_table_action_dscp_table dscp_table; 5877 char *pipeline_name, *file_name; 5878 uint32_t table_id, line_number; 5879 int status; 5880 5881 if (n_tokens != 6) { 5882 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5883 return; 5884 } 5885 5886 pipeline_name = tokens[1]; 5887 5888 if (strcmp(tokens[2], "table") != 0) { 5889 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 5890 return; 5891 } 5892 5893 if (softnic_parser_read_uint32(&table_id, tokens[3]) != 0) { 5894 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 5895 return; 5896 } 5897 5898 if (strcmp(tokens[4], "dscp") != 0) { 5899 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "dscp"); 5900 return; 5901 } 5902 5903 file_name = tokens[5]; 5904 5905 status = load_dscp_table(&dscp_table, file_name, &line_number); 5906 if (status) { 5907 snprintf(out, out_size, MSG_FILE_ERR, file_name, line_number); 5908 return; 5909 } 5910 5911 status = softnic_pipeline_table_dscp_table_update(softnic, 5912 pipeline_name, 5913 table_id, 5914 UINT64_MAX, 5915 &dscp_table); 5916 if (status) { 5917 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 5918 return; 5919 } 5920 } 5921 5922 /** 5923 * pipeline <pipeline_name> table <table_id> rule read ttl [clear] 5924 */ 5925 static void 5926 cmd_softnic_pipeline_table_rule_ttl_read(struct pmd_internals *softnic __rte_unused, 5927 char **tokens, 5928 uint32_t n_tokens __rte_unused, 5929 char *out, 5930 size_t out_size) 5931 { 5932 snprintf(out, out_size, MSG_CMD_UNIMPLEM, tokens[0]); 5933 } 5934 5935 /** 5936 * thread <thread_id> pipeline <pipeline_name> enable 5937 */ 5938 static void 5939 cmd_softnic_thread_pipeline_enable(struct pmd_internals *softnic, 5940 char **tokens, 5941 uint32_t n_tokens, 5942 char *out, 5943 size_t out_size) 5944 { 5945 char *pipeline_name; 5946 uint32_t thread_id; 5947 int status; 5948 5949 if (n_tokens != 5) { 5950 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5951 return; 5952 } 5953 5954 if (softnic_parser_read_uint32(&thread_id, tokens[1]) != 0) { 5955 snprintf(out, out_size, MSG_ARG_INVALID, "thread_id"); 5956 return; 5957 } 5958 5959 if (strcmp(tokens[2], "pipeline") != 0) { 5960 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline"); 5961 return; 5962 } 5963 5964 pipeline_name = tokens[3]; 5965 5966 if (strcmp(tokens[4], "enable") != 0) { 5967 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "enable"); 5968 return; 5969 } 5970 5971 status = softnic_thread_pipeline_enable(softnic, thread_id, pipeline_name); 5972 if (status) { 5973 snprintf(out, out_size, MSG_CMD_FAIL, "thread pipeline enable"); 5974 return; 5975 } 5976 } 5977 5978 /** 5979 * thread <thread_id> pipeline <pipeline_name> disable 5980 */ 5981 static void 5982 cmd_softnic_thread_pipeline_disable(struct pmd_internals *softnic, 5983 char **tokens, 5984 uint32_t n_tokens, 5985 char *out, 5986 size_t out_size) 5987 { 5988 char *pipeline_name; 5989 uint32_t thread_id; 5990 int status; 5991 5992 if (n_tokens != 5) { 5993 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 5994 return; 5995 } 5996 5997 if (softnic_parser_read_uint32(&thread_id, tokens[1]) != 0) { 5998 snprintf(out, out_size, MSG_ARG_INVALID, "thread_id"); 5999 return; 6000 } 6001 6002 if (strcmp(tokens[2], "pipeline") != 0) { 6003 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline"); 6004 return; 6005 } 6006 6007 pipeline_name = tokens[3]; 6008 6009 if (strcmp(tokens[4], "disable") != 0) { 6010 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "disable"); 6011 return; 6012 } 6013 6014 status = softnic_thread_pipeline_disable(softnic, thread_id, pipeline_name); 6015 if (status) { 6016 snprintf(out, out_size, MSG_CMD_FAIL, 6017 "thread pipeline disable"); 6018 return; 6019 } 6020 } 6021 6022 /** 6023 * flowapi map 6024 * group <group_id> 6025 * ingress | egress 6026 * pipeline <pipeline_name> 6027 * table <table_id> 6028 */ 6029 static void 6030 cmd_softnic_flowapi_map(struct pmd_internals *softnic, 6031 char **tokens, 6032 uint32_t n_tokens, 6033 char *out, 6034 size_t out_size) 6035 { 6036 char *pipeline_name; 6037 uint32_t group_id, table_id; 6038 int ingress, status; 6039 6040 if (n_tokens != 9) { 6041 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 6042 return; 6043 } 6044 6045 if (strcmp(tokens[1], "map") != 0) { 6046 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "map"); 6047 return; 6048 } 6049 6050 if (strcmp(tokens[2], "group") != 0) { 6051 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "group"); 6052 return; 6053 } 6054 6055 if (softnic_parser_read_uint32(&group_id, tokens[3]) != 0) { 6056 snprintf(out, out_size, MSG_ARG_INVALID, "group_id"); 6057 return; 6058 } 6059 6060 if (strcmp(tokens[4], "ingress") == 0) { 6061 ingress = 1; 6062 } else if (strcmp(tokens[4], "egress") == 0) { 6063 ingress = 0; 6064 } else { 6065 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "ingress | egress"); 6066 return; 6067 } 6068 6069 if (strcmp(tokens[5], "pipeline") != 0) { 6070 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pipeline"); 6071 return; 6072 } 6073 6074 pipeline_name = tokens[6]; 6075 6076 if (strcmp(tokens[7], "table") != 0) { 6077 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); 6078 return; 6079 } 6080 6081 if (softnic_parser_read_uint32(&table_id, tokens[8]) != 0) { 6082 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 6083 return; 6084 } 6085 6086 status = flow_attr_map_set(softnic, 6087 group_id, 6088 ingress, 6089 pipeline_name, 6090 table_id); 6091 if (status) { 6092 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 6093 return; 6094 } 6095 } 6096 6097 void 6098 softnic_cli_process(char *in, char *out, size_t out_size, void *arg) 6099 { 6100 char *tokens[CMD_MAX_TOKENS]; 6101 uint32_t n_tokens = RTE_DIM(tokens); 6102 struct pmd_internals *softnic = arg; 6103 int status; 6104 6105 if (is_comment(in)) 6106 return; 6107 6108 status = softnic_parse_tokenize_string(in, tokens, &n_tokens); 6109 if (status) { 6110 snprintf(out, out_size, MSG_ARG_TOO_MANY, ""); 6111 return; 6112 } 6113 6114 if (n_tokens == 0) 6115 return; 6116 6117 if (strcmp(tokens[0], "mempool") == 0) { 6118 cmd_mempool(softnic, tokens, n_tokens, out, out_size); 6119 return; 6120 } 6121 6122 if (strcmp(tokens[0], "link") == 0) { 6123 cmd_link(softnic, tokens, n_tokens, out, out_size); 6124 return; 6125 } 6126 6127 if (strcmp(tokens[0], "swq") == 0) { 6128 cmd_swq(softnic, tokens, n_tokens, out, out_size); 6129 return; 6130 } 6131 6132 if (strcmp(tokens[0], "tmgr") == 0) { 6133 if (n_tokens == 2) { 6134 cmd_tmgr(softnic, tokens, n_tokens, out, out_size); 6135 return; 6136 } 6137 6138 if (n_tokens >= 3 && 6139 (strcmp(tokens[1], "shaper") == 0) && 6140 (strcmp(tokens[2], "profile") == 0)) { 6141 cmd_tmgr_shaper_profile(softnic, tokens, n_tokens, out, out_size); 6142 return; 6143 } 6144 6145 if (n_tokens >= 3 && 6146 (strcmp(tokens[1], "shared") == 0) && 6147 (strcmp(tokens[2], "shaper") == 0)) { 6148 cmd_tmgr_shared_shaper(softnic, tokens, n_tokens, out, out_size); 6149 return; 6150 } 6151 6152 if (n_tokens >= 2 && 6153 (strcmp(tokens[1], "node") == 0)) { 6154 cmd_tmgr_node(softnic, tokens, n_tokens, out, out_size); 6155 return; 6156 } 6157 6158 if (n_tokens >= 2 && 6159 (strcmp(tokens[1], "hierarchy-default") == 0)) { 6160 cmd_tmgr_hierarchy_default(softnic, tokens, n_tokens, out, out_size); 6161 return; 6162 } 6163 6164 if (n_tokens >= 3 && 6165 (strcmp(tokens[1], "hierarchy") == 0) && 6166 (strcmp(tokens[2], "commit") == 0)) { 6167 cmd_tmgr_hierarchy_commit(softnic, tokens, n_tokens, out, out_size); 6168 return; 6169 } 6170 } 6171 6172 if (strcmp(tokens[0], "tap") == 0) { 6173 cmd_tap(softnic, tokens, n_tokens, out, out_size); 6174 return; 6175 } 6176 6177 if (strcmp(tokens[0], "cryptodev") == 0) { 6178 cmd_cryptodev(softnic, tokens, n_tokens, out, out_size); 6179 return; 6180 } 6181 6182 if (strcmp(tokens[0], "port") == 0) { 6183 cmd_port_in_action_profile(softnic, tokens, n_tokens, out, out_size); 6184 return; 6185 } 6186 6187 if (strcmp(tokens[0], "table") == 0) { 6188 cmd_table_action_profile(softnic, tokens, n_tokens, out, out_size); 6189 return; 6190 } 6191 6192 if (strcmp(tokens[0], "pipeline") == 0) { 6193 if (n_tokens >= 3 && 6194 (strcmp(tokens[2], "period") == 0)) { 6195 cmd_pipeline(softnic, tokens, n_tokens, out, out_size); 6196 return; 6197 } 6198 6199 if (n_tokens >= 5 && 6200 (strcmp(tokens[2], "port") == 0) && 6201 (strcmp(tokens[3], "in") == 0) && 6202 (strcmp(tokens[4], "bsz") == 0)) { 6203 cmd_pipeline_port_in(softnic, tokens, n_tokens, out, out_size); 6204 return; 6205 } 6206 6207 if (n_tokens >= 5 && 6208 (strcmp(tokens[2], "port") == 0) && 6209 (strcmp(tokens[3], "out") == 0) && 6210 (strcmp(tokens[4], "bsz") == 0)) { 6211 cmd_pipeline_port_out(softnic, tokens, n_tokens, out, out_size); 6212 return; 6213 } 6214 6215 if (n_tokens >= 4 && 6216 (strcmp(tokens[2], "table") == 0) && 6217 (strcmp(tokens[3], "match") == 0)) { 6218 cmd_pipeline_table(softnic, tokens, n_tokens, out, out_size); 6219 return; 6220 } 6221 6222 if (n_tokens >= 6 && 6223 (strcmp(tokens[2], "port") == 0) && 6224 (strcmp(tokens[3], "in") == 0) && 6225 (strcmp(tokens[5], "table") == 0)) { 6226 cmd_pipeline_port_in_table(softnic, tokens, n_tokens, 6227 out, out_size); 6228 return; 6229 } 6230 6231 if (n_tokens >= 6 && 6232 (strcmp(tokens[2], "port") == 0) && 6233 (strcmp(tokens[3], "in") == 0) && 6234 (strcmp(tokens[5], "stats") == 0)) { 6235 cmd_pipeline_port_in_stats(softnic, tokens, n_tokens, 6236 out, out_size); 6237 return; 6238 } 6239 6240 if (n_tokens >= 6 && 6241 (strcmp(tokens[2], "port") == 0) && 6242 (strcmp(tokens[3], "in") == 0) && 6243 (strcmp(tokens[5], "enable") == 0)) { 6244 cmd_softnic_pipeline_port_in_enable(softnic, tokens, n_tokens, 6245 out, out_size); 6246 return; 6247 } 6248 6249 if (n_tokens >= 6 && 6250 (strcmp(tokens[2], "port") == 0) && 6251 (strcmp(tokens[3], "in") == 0) && 6252 (strcmp(tokens[5], "disable") == 0)) { 6253 cmd_softnic_pipeline_port_in_disable(softnic, tokens, n_tokens, 6254 out, out_size); 6255 return; 6256 } 6257 6258 if (n_tokens >= 6 && 6259 (strcmp(tokens[2], "port") == 0) && 6260 (strcmp(tokens[3], "out") == 0) && 6261 (strcmp(tokens[5], "stats") == 0)) { 6262 cmd_pipeline_port_out_stats(softnic, tokens, n_tokens, 6263 out, out_size); 6264 return; 6265 } 6266 6267 if (n_tokens >= 5 && 6268 (strcmp(tokens[2], "table") == 0) && 6269 (strcmp(tokens[4], "stats") == 0)) { 6270 cmd_pipeline_table_stats(softnic, tokens, n_tokens, 6271 out, out_size); 6272 return; 6273 } 6274 6275 if (n_tokens >= 7 && 6276 (strcmp(tokens[2], "table") == 0) && 6277 (strcmp(tokens[4], "rule") == 0) && 6278 (strcmp(tokens[5], "add") == 0) && 6279 (strcmp(tokens[6], "match") == 0)) { 6280 if (n_tokens >= 8 && 6281 (strcmp(tokens[7], "default") == 0)) { 6282 cmd_softnic_pipeline_table_rule_add_default(softnic, tokens, 6283 n_tokens, out, out_size); 6284 return; 6285 } 6286 6287 cmd_softnic_pipeline_table_rule_add(softnic, tokens, n_tokens, 6288 out, out_size); 6289 return; 6290 } 6291 6292 if (n_tokens >= 7 && 6293 (strcmp(tokens[2], "table") == 0) && 6294 (strcmp(tokens[4], "rule") == 0) && 6295 (strcmp(tokens[5], "add") == 0) && 6296 (strcmp(tokens[6], "bulk") == 0)) { 6297 cmd_softnic_pipeline_table_rule_add_bulk(softnic, tokens, 6298 n_tokens, out, out_size); 6299 return; 6300 } 6301 6302 if (n_tokens >= 7 && 6303 (strcmp(tokens[2], "table") == 0) && 6304 (strcmp(tokens[4], "rule") == 0) && 6305 (strcmp(tokens[5], "delete") == 0) && 6306 (strcmp(tokens[6], "match") == 0)) { 6307 if (n_tokens >= 8 && 6308 (strcmp(tokens[7], "default") == 0)) { 6309 cmd_softnic_pipeline_table_rule_delete_default(softnic, tokens, 6310 n_tokens, out, out_size); 6311 return; 6312 } 6313 6314 cmd_softnic_pipeline_table_rule_delete(softnic, tokens, n_tokens, 6315 out, out_size); 6316 return; 6317 } 6318 6319 if (n_tokens >= 7 && 6320 (strcmp(tokens[2], "table") == 0) && 6321 (strcmp(tokens[4], "rule") == 0) && 6322 (strcmp(tokens[5], "read") == 0) && 6323 (strcmp(tokens[6], "stats") == 0)) { 6324 cmd_softnic_pipeline_table_rule_stats_read(softnic, tokens, n_tokens, 6325 out, out_size); 6326 return; 6327 } 6328 6329 if (n_tokens >= 8 && 6330 (strcmp(tokens[2], "table") == 0) && 6331 (strcmp(tokens[4], "meter") == 0) && 6332 (strcmp(tokens[5], "profile") == 0) && 6333 (strcmp(tokens[7], "add") == 0)) { 6334 cmd_pipeline_table_meter_profile_add(softnic, tokens, n_tokens, 6335 out, out_size); 6336 return; 6337 } 6338 6339 if (n_tokens >= 8 && 6340 (strcmp(tokens[2], "table") == 0) && 6341 (strcmp(tokens[4], "meter") == 0) && 6342 (strcmp(tokens[5], "profile") == 0) && 6343 (strcmp(tokens[7], "delete") == 0)) { 6344 cmd_pipeline_table_meter_profile_delete(softnic, tokens, 6345 n_tokens, out, out_size); 6346 return; 6347 } 6348 6349 if (n_tokens >= 7 && 6350 (strcmp(tokens[2], "table") == 0) && 6351 (strcmp(tokens[4], "rule") == 0) && 6352 (strcmp(tokens[5], "read") == 0) && 6353 (strcmp(tokens[6], "meter") == 0)) { 6354 cmd_pipeline_table_rule_meter_read(softnic, tokens, n_tokens, 6355 out, out_size); 6356 return; 6357 } 6358 6359 if (n_tokens >= 5 && 6360 (strcmp(tokens[2], "table") == 0) && 6361 (strcmp(tokens[4], "dscp") == 0)) { 6362 cmd_pipeline_table_dscp(softnic, tokens, n_tokens, 6363 out, out_size); 6364 return; 6365 } 6366 6367 if (n_tokens >= 7 && 6368 (strcmp(tokens[2], "table") == 0) && 6369 (strcmp(tokens[4], "rule") == 0) && 6370 (strcmp(tokens[5], "read") == 0) && 6371 (strcmp(tokens[6], "ttl") == 0)) { 6372 cmd_softnic_pipeline_table_rule_ttl_read(softnic, tokens, n_tokens, 6373 out, out_size); 6374 return; 6375 } 6376 } 6377 6378 if (strcmp(tokens[0], "thread") == 0) { 6379 if (n_tokens >= 5 && 6380 (strcmp(tokens[4], "enable") == 0)) { 6381 cmd_softnic_thread_pipeline_enable(softnic, tokens, n_tokens, 6382 out, out_size); 6383 return; 6384 } 6385 6386 if (n_tokens >= 5 && 6387 (strcmp(tokens[4], "disable") == 0)) { 6388 cmd_softnic_thread_pipeline_disable(softnic, tokens, n_tokens, 6389 out, out_size); 6390 return; 6391 } 6392 } 6393 6394 if (strcmp(tokens[0], "flowapi") == 0) { 6395 cmd_softnic_flowapi_map(softnic, tokens, n_tokens, out, 6396 out_size); 6397 return; 6398 } 6399 6400 snprintf(out, out_size, MSG_CMD_UNKNOWN, tokens[0]); 6401 } 6402 6403 int 6404 softnic_cli_script_process(struct pmd_internals *softnic, 6405 const char *file_name, 6406 size_t msg_in_len_max, 6407 size_t msg_out_len_max) 6408 { 6409 char *msg_in = NULL, *msg_out = NULL; 6410 FILE *f = NULL; 6411 6412 /* Check input arguments */ 6413 if (file_name == NULL || 6414 (strlen(file_name) == 0) || 6415 msg_in_len_max == 0 || 6416 msg_out_len_max == 0) 6417 return -EINVAL; 6418 6419 msg_in = malloc(msg_in_len_max + 1); 6420 msg_out = malloc(msg_out_len_max + 1); 6421 if (msg_in == NULL || 6422 msg_out == NULL) { 6423 free(msg_out); 6424 free(msg_in); 6425 return -ENOMEM; 6426 } 6427 6428 /* Open input file */ 6429 f = fopen(file_name, "r"); 6430 if (f == NULL) { 6431 free(msg_out); 6432 free(msg_in); 6433 return -EIO; 6434 } 6435 6436 /* Read file */ 6437 for ( ; ; ) { 6438 if (fgets(msg_in, msg_in_len_max + 1, f) == NULL) 6439 break; 6440 6441 printf("%s", msg_in); 6442 msg_out[0] = 0; 6443 6444 softnic_cli_process(msg_in, 6445 msg_out, 6446 msg_out_len_max, 6447 softnic); 6448 6449 if (strlen(msg_out)) 6450 printf("%s", msg_out); 6451 } 6452 6453 /* Close file */ 6454 fclose(f); 6455 free(msg_out); 6456 free(msg_in); 6457 return 0; 6458 } 6459 6460 static int 6461 cli_rule_file_process(const char *file_name, 6462 size_t line_len_max, 6463 struct softnic_table_rule_match *m, 6464 struct softnic_table_rule_action *a, 6465 uint32_t *n_rules, 6466 uint32_t *line_number, 6467 char *out, 6468 size_t out_size) 6469 { 6470 FILE *f = NULL; 6471 char *line = NULL; 6472 uint32_t rule_id, line_id; 6473 int status = 0; 6474 6475 /* Check input arguments */ 6476 if (file_name == NULL || 6477 (strlen(file_name) == 0) || 6478 line_len_max == 0) { 6479 *line_number = 0; 6480 return -EINVAL; 6481 } 6482 6483 /* Memory allocation */ 6484 line = malloc(line_len_max + 1); 6485 if (line == NULL) { 6486 *line_number = 0; 6487 return -ENOMEM; 6488 } 6489 6490 /* Open file */ 6491 f = fopen(file_name, "r"); 6492 if (f == NULL) { 6493 *line_number = 0; 6494 free(line); 6495 return -EIO; 6496 } 6497 6498 /* Read file */ 6499 for (line_id = 1, rule_id = 0; rule_id < *n_rules; line_id++) { 6500 char *tokens[CMD_MAX_TOKENS]; 6501 uint32_t n_tokens, n_tokens_parsed, t0; 6502 6503 /* Read next line from file. */ 6504 if (fgets(line, line_len_max + 1, f) == NULL) 6505 break; 6506 6507 /* Comment. */ 6508 if (is_comment(line)) 6509 continue; 6510 6511 /* Parse line. */ 6512 n_tokens = RTE_DIM(tokens); 6513 status = softnic_parse_tokenize_string(line, tokens, &n_tokens); 6514 if (status) { 6515 status = -EINVAL; 6516 break; 6517 } 6518 6519 /* Empty line. */ 6520 if (n_tokens == 0) 6521 continue; 6522 t0 = 0; 6523 6524 /* Rule match. */ 6525 n_tokens_parsed = parse_match(tokens + t0, 6526 n_tokens - t0, 6527 out, 6528 out_size, 6529 &m[rule_id]); 6530 if (n_tokens_parsed == 0) { 6531 status = -EINVAL; 6532 break; 6533 } 6534 t0 += n_tokens_parsed; 6535 6536 /* Rule action. */ 6537 n_tokens_parsed = parse_table_action(tokens + t0, 6538 n_tokens - t0, 6539 out, 6540 out_size, 6541 &a[rule_id]); 6542 if (n_tokens_parsed == 0) { 6543 status = -EINVAL; 6544 break; 6545 } 6546 t0 += n_tokens_parsed; 6547 6548 /* Line completed. */ 6549 if (t0 < n_tokens) { 6550 status = -EINVAL; 6551 break; 6552 } 6553 6554 /* Increment rule count */ 6555 rule_id++; 6556 } 6557 6558 /* Close file */ 6559 fclose(f); 6560 6561 /* Memory free */ 6562 free(line); 6563 6564 *n_rules = rule_id; 6565 *line_number = line_id; 6566 return status; 6567 } 6568