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_eth_softnic_internals.h" 11 #include "parser.h" 12 13 #ifndef CMD_MAX_TOKENS 14 #define CMD_MAX_TOKENS 256 15 #endif 16 17 #define MSG_OUT_OF_MEMORY "Not enough memory.\n" 18 #define MSG_CMD_UNKNOWN "Unknown command \"%s\".\n" 19 #define MSG_CMD_UNIMPLEM "Command \"%s\" not implemented.\n" 20 #define MSG_ARG_NOT_ENOUGH "Not enough arguments for command \"%s\".\n" 21 #define MSG_ARG_TOO_MANY "Too many arguments for command \"%s\".\n" 22 #define MSG_ARG_MISMATCH "Wrong number of arguments for command \"%s\".\n" 23 #define MSG_ARG_NOT_FOUND "Argument \"%s\" not found.\n" 24 #define MSG_ARG_INVALID "Invalid value for argument \"%s\".\n" 25 #define MSG_FILE_ERR "Error in file \"%s\" at line %u.\n" 26 #define MSG_FILE_NOT_ENOUGH "Not enough rules in file \"%s\".\n" 27 #define MSG_CMD_FAIL "Command \"%s\" failed.\n" 28 29 static int 30 is_comment(char *in) 31 { 32 if ((strlen(in) && index("!#%;", in[0])) || 33 (strncmp(in, "//", 2) == 0) || 34 (strncmp(in, "--", 2) == 0)) 35 return 1; 36 37 return 0; 38 } 39 40 /** 41 * mempool <mempool_name> 42 * buffer <buffer_size> 43 * pool <pool_size> 44 * cache <cache_size> 45 */ 46 static void 47 cmd_mempool(struct pmd_internals *softnic, 48 char **tokens, 49 uint32_t n_tokens, 50 char *out, 51 size_t out_size) 52 { 53 struct softnic_mempool_params p; 54 char *name; 55 struct softnic_mempool *mempool; 56 57 if (n_tokens != 8) { 58 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 59 return; 60 } 61 62 name = tokens[1]; 63 64 if (strcmp(tokens[2], "buffer") != 0) { 65 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "buffer"); 66 return; 67 } 68 69 if (softnic_parser_read_uint32(&p.buffer_size, tokens[3]) != 0) { 70 snprintf(out, out_size, MSG_ARG_INVALID, "buffer_size"); 71 return; 72 } 73 74 if (strcmp(tokens[4], "pool") != 0) { 75 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pool"); 76 return; 77 } 78 79 if (softnic_parser_read_uint32(&p.pool_size, tokens[5]) != 0) { 80 snprintf(out, out_size, MSG_ARG_INVALID, "pool_size"); 81 return; 82 } 83 84 if (strcmp(tokens[6], "cache") != 0) { 85 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "cache"); 86 return; 87 } 88 89 if (softnic_parser_read_uint32(&p.cache_size, tokens[7]) != 0) { 90 snprintf(out, out_size, MSG_ARG_INVALID, "cache_size"); 91 return; 92 } 93 94 mempool = softnic_mempool_create(softnic, name, &p); 95 if (mempool == NULL) { 96 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 97 return; 98 } 99 } 100 101 /** 102 * link <link_name> 103 * dev <device_name> | port <port_id> 104 */ 105 static void 106 cmd_link(struct pmd_internals *softnic, 107 char **tokens, 108 uint32_t n_tokens, 109 char *out, 110 size_t out_size) 111 { 112 struct softnic_link_params p; 113 struct softnic_link *link; 114 char *name; 115 116 memset(&p, 0, sizeof(p)); 117 118 if (n_tokens != 4) { 119 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 120 return; 121 } 122 name = tokens[1]; 123 124 if (strcmp(tokens[2], "dev") == 0) { 125 p.dev_name = tokens[3]; 126 } else if (strcmp(tokens[2], "port") == 0) { 127 p.dev_name = NULL; 128 129 if (softnic_parser_read_uint16(&p.port_id, tokens[3]) != 0) { 130 snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); 131 return; 132 } 133 } else { 134 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "dev or port"); 135 return; 136 } 137 138 link = softnic_link_create(softnic, name, &p); 139 if (link == NULL) { 140 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 141 return; 142 } 143 } 144 145 /** 146 * swq <swq_name> 147 * size <size> 148 */ 149 static void 150 cmd_swq(struct pmd_internals *softnic, 151 char **tokens, 152 uint32_t n_tokens, 153 char *out, 154 size_t out_size) 155 { 156 struct softnic_swq_params p; 157 char *name; 158 struct softnic_swq *swq; 159 160 if (n_tokens != 4) { 161 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 162 return; 163 } 164 165 name = tokens[1]; 166 167 if (strcmp(tokens[2], "size") != 0) { 168 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size"); 169 return; 170 } 171 172 if (softnic_parser_read_uint32(&p.size, tokens[3]) != 0) { 173 snprintf(out, out_size, MSG_ARG_INVALID, "size"); 174 return; 175 } 176 177 swq = softnic_swq_create(softnic, name, &p); 178 if (swq == NULL) { 179 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 180 return; 181 } 182 } 183 184 /** 185 * tap <tap_name> 186 */ 187 static void 188 cmd_tap(struct pmd_internals *softnic, 189 char **tokens, 190 uint32_t n_tokens, 191 char *out, 192 size_t out_size) 193 { 194 char *name; 195 struct softnic_tap *tap; 196 197 if (n_tokens != 2) { 198 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 199 return; 200 } 201 202 name = tokens[1]; 203 204 tap = softnic_tap_create(softnic, name); 205 if (tap == NULL) { 206 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 207 return; 208 } 209 } 210 211 /** 212 * port in action profile <profile_name> 213 * [filter match | mismatch offset <key_offset> mask <key_mask> key <key_value> port <port_id>] 214 * [balance offset <key_offset> mask <key_mask> port <port_id0> ... <port_id15>] 215 */ 216 static void 217 cmd_port_in_action_profile(struct pmd_internals *softnic, 218 char **tokens, 219 uint32_t n_tokens, 220 char *out, 221 size_t out_size) 222 { 223 struct softnic_port_in_action_profile_params p; 224 struct softnic_port_in_action_profile *ap; 225 char *name; 226 uint32_t t0; 227 228 memset(&p, 0, sizeof(p)); 229 230 if (n_tokens < 5) { 231 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 232 return; 233 } 234 235 if (strcmp(tokens[1], "in") != 0) { 236 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in"); 237 return; 238 } 239 240 if (strcmp(tokens[2], "action") != 0) { 241 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "action"); 242 return; 243 } 244 245 if (strcmp(tokens[3], "profile") != 0) { 246 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile"); 247 return; 248 } 249 250 name = tokens[4]; 251 252 t0 = 5; 253 254 if (t0 < n_tokens && 255 (strcmp(tokens[t0], "filter") == 0)) { 256 uint32_t size; 257 258 if (n_tokens < t0 + 10) { 259 snprintf(out, out_size, MSG_ARG_MISMATCH, "port in action profile filter"); 260 return; 261 } 262 263 if (strcmp(tokens[t0 + 1], "match") == 0) { 264 p.fltr.filter_on_match = 1; 265 } else if (strcmp(tokens[t0 + 1], "mismatch") == 0) { 266 p.fltr.filter_on_match = 0; 267 } else { 268 snprintf(out, out_size, MSG_ARG_INVALID, "match or mismatch"); 269 return; 270 } 271 272 if (strcmp(tokens[t0 + 2], "offset") != 0) { 273 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); 274 return; 275 } 276 277 if (softnic_parser_read_uint32(&p.fltr.key_offset, 278 tokens[t0 + 3]) != 0) { 279 snprintf(out, out_size, MSG_ARG_INVALID, "key_offset"); 280 return; 281 } 282 283 if (strcmp(tokens[t0 + 4], "mask") != 0) { 284 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask"); 285 return; 286 } 287 288 size = RTE_PORT_IN_ACTION_FLTR_KEY_SIZE; 289 if ((softnic_parse_hex_string(tokens[t0 + 5], 290 p.fltr.key_mask, &size) != 0) || 291 size != RTE_PORT_IN_ACTION_FLTR_KEY_SIZE) { 292 snprintf(out, out_size, MSG_ARG_INVALID, "key_mask"); 293 return; 294 } 295 296 if (strcmp(tokens[t0 + 6], "key") != 0) { 297 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "key"); 298 return; 299 } 300 301 size = RTE_PORT_IN_ACTION_FLTR_KEY_SIZE; 302 if ((softnic_parse_hex_string(tokens[t0 + 7], 303 p.fltr.key, &size) != 0) || 304 size != RTE_PORT_IN_ACTION_FLTR_KEY_SIZE) { 305 snprintf(out, out_size, MSG_ARG_INVALID, "key_value"); 306 return; 307 } 308 309 if (strcmp(tokens[t0 + 8], "port") != 0) { 310 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 311 return; 312 } 313 314 if (softnic_parser_read_uint32(&p.fltr.port_id, 315 tokens[t0 + 9]) != 0) { 316 snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); 317 return; 318 } 319 320 p.action_mask |= 1LLU << RTE_PORT_IN_ACTION_FLTR; 321 t0 += 10; 322 } /* filter */ 323 324 if (t0 < n_tokens && 325 (strcmp(tokens[t0], "balance") == 0)) { 326 uint32_t i; 327 328 if (n_tokens < t0 + 22) { 329 snprintf(out, out_size, MSG_ARG_MISMATCH, 330 "port in action profile balance"); 331 return; 332 } 333 334 if (strcmp(tokens[t0 + 1], "offset") != 0) { 335 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); 336 return; 337 } 338 339 if (softnic_parser_read_uint32(&p.lb.key_offset, 340 tokens[t0 + 2]) != 0) { 341 snprintf(out, out_size, MSG_ARG_INVALID, "key_offset"); 342 return; 343 } 344 345 if (strcmp(tokens[t0 + 3], "mask") != 0) { 346 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask"); 347 return; 348 } 349 350 p.lb.key_size = RTE_PORT_IN_ACTION_LB_KEY_SIZE_MAX; 351 if (softnic_parse_hex_string(tokens[t0 + 4], 352 p.lb.key_mask, &p.lb.key_size) != 0) { 353 snprintf(out, out_size, MSG_ARG_INVALID, "key_mask"); 354 return; 355 } 356 357 if (strcmp(tokens[t0 + 5], "port") != 0) { 358 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 359 return; 360 } 361 362 for (i = 0; i < 16; i++) 363 if (softnic_parser_read_uint32(&p.lb.port_id[i], 364 tokens[t0 + 6 + i]) != 0) { 365 snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); 366 return; 367 } 368 369 p.action_mask |= 1LLU << RTE_PORT_IN_ACTION_LB; 370 t0 += 22; 371 } /* balance */ 372 373 if (t0 < n_tokens) { 374 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 375 return; 376 } 377 378 ap = softnic_port_in_action_profile_create(softnic, name, &p); 379 if (ap == NULL) { 380 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 381 return; 382 } 383 } 384 385 /** 386 * table action profile <profile_name> 387 * ipv4 | ipv6 388 * offset <ip_offset> 389 * fwd 390 * [balance offset <key_offset> mask <key_mask> outoffset <out_offset>] 391 * [meter srtcm | trtcm 392 * tc <n_tc> 393 * stats none | pkts | bytes | both] 394 * [tm spp <n_subports_per_port> pps <n_pipes_per_subport>] 395 * [encap ether | vlan | qinq | mpls | pppoe] 396 * [nat src | dst 397 * proto udp | tcp] 398 * [ttl drop | fwd 399 * stats none | pkts] 400 * [stats pkts | bytes | both] 401 * [time] 402 */ 403 static void 404 cmd_table_action_profile(struct pmd_internals *softnic, 405 char **tokens, 406 uint32_t n_tokens, 407 char *out, 408 size_t out_size) 409 { 410 struct softnic_table_action_profile_params p; 411 struct softnic_table_action_profile *ap; 412 char *name; 413 uint32_t t0; 414 415 memset(&p, 0, sizeof(p)); 416 417 if (n_tokens < 8) { 418 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 419 return; 420 } 421 422 if (strcmp(tokens[1], "action") != 0) { 423 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "action"); 424 return; 425 } 426 427 if (strcmp(tokens[2], "profile") != 0) { 428 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "profile"); 429 return; 430 } 431 432 name = tokens[3]; 433 434 if (strcmp(tokens[4], "ipv4") == 0) { 435 p.common.ip_version = 1; 436 } else if (strcmp(tokens[4], "ipv6") == 0) { 437 p.common.ip_version = 0; 438 } else { 439 snprintf(out, out_size, MSG_ARG_INVALID, "ipv4 or ipv6"); 440 return; 441 } 442 443 if (strcmp(tokens[5], "offset") != 0) { 444 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); 445 return; 446 } 447 448 if (softnic_parser_read_uint32(&p.common.ip_offset, 449 tokens[6]) != 0) { 450 snprintf(out, out_size, MSG_ARG_INVALID, "ip_offset"); 451 return; 452 } 453 454 if (strcmp(tokens[7], "fwd") != 0) { 455 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "fwd"); 456 return; 457 } 458 459 p.action_mask |= 1LLU << RTE_TABLE_ACTION_FWD; 460 461 t0 = 8; 462 if (t0 < n_tokens && 463 (strcmp(tokens[t0], "balance") == 0)) { 464 if (n_tokens < t0 + 7) { 465 snprintf(out, out_size, MSG_ARG_MISMATCH, "table action profile balance"); 466 return; 467 } 468 469 if (strcmp(tokens[t0 + 1], "offset") != 0) { 470 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); 471 return; 472 } 473 474 if (softnic_parser_read_uint32(&p.lb.key_offset, 475 tokens[t0 + 2]) != 0) { 476 snprintf(out, out_size, MSG_ARG_INVALID, "key_offset"); 477 return; 478 } 479 480 if (strcmp(tokens[t0 + 3], "mask") != 0) { 481 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask"); 482 return; 483 } 484 485 p.lb.key_size = RTE_PORT_IN_ACTION_LB_KEY_SIZE_MAX; 486 if (softnic_parse_hex_string(tokens[t0 + 4], 487 p.lb.key_mask, &p.lb.key_size) != 0) { 488 snprintf(out, out_size, MSG_ARG_INVALID, "key_mask"); 489 return; 490 } 491 492 if (strcmp(tokens[t0 + 5], "outoffset") != 0) { 493 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "outoffset"); 494 return; 495 } 496 497 if (softnic_parser_read_uint32(&p.lb.out_offset, 498 tokens[t0 + 6]) != 0) { 499 snprintf(out, out_size, MSG_ARG_INVALID, "out_offset"); 500 return; 501 } 502 503 p.action_mask |= 1LLU << RTE_TABLE_ACTION_LB; 504 t0 += 7; 505 } /* balance */ 506 507 if (t0 < n_tokens && 508 (strcmp(tokens[t0], "meter") == 0)) { 509 if (n_tokens < t0 + 6) { 510 snprintf(out, out_size, MSG_ARG_MISMATCH, 511 "table action profile meter"); 512 return; 513 } 514 515 if (strcmp(tokens[t0 + 1], "srtcm") == 0) { 516 p.mtr.alg = RTE_TABLE_ACTION_METER_SRTCM; 517 } else if (strcmp(tokens[t0 + 1], "trtcm") == 0) { 518 p.mtr.alg = RTE_TABLE_ACTION_METER_TRTCM; 519 } else { 520 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 521 "srtcm or trtcm"); 522 return; 523 } 524 525 if (strcmp(tokens[t0 + 2], "tc") != 0) { 526 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "tc"); 527 return; 528 } 529 530 if (softnic_parser_read_uint32(&p.mtr.n_tc, 531 tokens[t0 + 3]) != 0) { 532 snprintf(out, out_size, MSG_ARG_INVALID, "n_tc"); 533 return; 534 } 535 536 if (strcmp(tokens[t0 + 4], "stats") != 0) { 537 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats"); 538 return; 539 } 540 541 if (strcmp(tokens[t0 + 5], "none") == 0) { 542 p.mtr.n_packets_enabled = 0; 543 p.mtr.n_bytes_enabled = 0; 544 } else if (strcmp(tokens[t0 + 5], "pkts") == 0) { 545 p.mtr.n_packets_enabled = 1; 546 p.mtr.n_bytes_enabled = 0; 547 } else if (strcmp(tokens[t0 + 5], "bytes") == 0) { 548 p.mtr.n_packets_enabled = 0; 549 p.mtr.n_bytes_enabled = 1; 550 } else if (strcmp(tokens[t0 + 5], "both") == 0) { 551 p.mtr.n_packets_enabled = 1; 552 p.mtr.n_bytes_enabled = 1; 553 } else { 554 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 555 "none or pkts or bytes or both"); 556 return; 557 } 558 559 p.action_mask |= 1LLU << RTE_TABLE_ACTION_MTR; 560 t0 += 6; 561 } /* meter */ 562 563 if (t0 < n_tokens && 564 (strcmp(tokens[t0], "tm") == 0)) { 565 if (n_tokens < t0 + 5) { 566 snprintf(out, out_size, MSG_ARG_MISMATCH, 567 "table action profile tm"); 568 return; 569 } 570 571 if (strcmp(tokens[t0 + 1], "spp") != 0) { 572 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "spp"); 573 return; 574 } 575 576 if (softnic_parser_read_uint32(&p.tm.n_subports_per_port, 577 tokens[t0 + 2]) != 0) { 578 snprintf(out, out_size, MSG_ARG_INVALID, 579 "n_subports_per_port"); 580 return; 581 } 582 583 if (strcmp(tokens[t0 + 3], "pps") != 0) { 584 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pps"); 585 return; 586 } 587 588 if (softnic_parser_read_uint32(&p.tm.n_pipes_per_subport, 589 tokens[t0 + 4]) != 0) { 590 snprintf(out, out_size, MSG_ARG_INVALID, 591 "n_pipes_per_subport"); 592 return; 593 } 594 595 p.action_mask |= 1LLU << RTE_TABLE_ACTION_TM; 596 t0 += 5; 597 } /* tm */ 598 599 if (t0 < n_tokens && 600 (strcmp(tokens[t0], "encap") == 0)) { 601 if (n_tokens < t0 + 2) { 602 snprintf(out, out_size, MSG_ARG_MISMATCH, 603 "action profile encap"); 604 return; 605 } 606 607 if (strcmp(tokens[t0 + 1], "ether") == 0) { 608 p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_ETHER; 609 } else if (strcmp(tokens[t0 + 1], "vlan") == 0) { 610 p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_VLAN; 611 } else if (strcmp(tokens[t0 + 1], "qinq") == 0) { 612 p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_QINQ; 613 } else if (strcmp(tokens[t0 + 1], "mpls") == 0) { 614 p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_MPLS; 615 } else if (strcmp(tokens[t0 + 1], "pppoe") == 0) { 616 p.encap.encap_mask = 1LLU << RTE_TABLE_ACTION_ENCAP_PPPOE; 617 } else { 618 snprintf(out, out_size, MSG_ARG_MISMATCH, "encap"); 619 return; 620 } 621 622 p.action_mask |= 1LLU << RTE_TABLE_ACTION_ENCAP; 623 t0 += 2; 624 } /* encap */ 625 626 if (t0 < n_tokens && 627 (strcmp(tokens[t0], "nat") == 0)) { 628 if (n_tokens < t0 + 4) { 629 snprintf(out, out_size, MSG_ARG_MISMATCH, 630 "table action profile nat"); 631 return; 632 } 633 634 if (strcmp(tokens[t0 + 1], "src") == 0) { 635 p.nat.source_nat = 1; 636 } else if (strcmp(tokens[t0 + 1], "dst") == 0) { 637 p.nat.source_nat = 0; 638 } else { 639 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 640 "src or dst"); 641 return; 642 } 643 644 if (strcmp(tokens[t0 + 2], "proto") != 0) { 645 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "proto"); 646 return; 647 } 648 649 if (strcmp(tokens[t0 + 3], "tcp") == 0) { 650 p.nat.proto = 0x06; 651 } else if (strcmp(tokens[t0 + 3], "udp") == 0) { 652 p.nat.proto = 0x11; 653 } else { 654 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 655 "tcp or udp"); 656 return; 657 } 658 659 p.action_mask |= 1LLU << RTE_TABLE_ACTION_NAT; 660 t0 += 4; 661 } /* nat */ 662 663 if (t0 < n_tokens && 664 (strcmp(tokens[t0], "ttl") == 0)) { 665 if (n_tokens < t0 + 4) { 666 snprintf(out, out_size, MSG_ARG_MISMATCH, 667 "table action profile ttl"); 668 return; 669 } 670 671 if (strcmp(tokens[t0 + 1], "drop") == 0) { 672 p.ttl.drop = 1; 673 } else if (strcmp(tokens[t0 + 1], "fwd") == 0) { 674 p.ttl.drop = 0; 675 } else { 676 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 677 "drop or fwd"); 678 return; 679 } 680 681 if (strcmp(tokens[t0 + 2], "stats") != 0) { 682 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "stats"); 683 return; 684 } 685 686 if (strcmp(tokens[t0 + 3], "none") == 0) { 687 p.ttl.n_packets_enabled = 0; 688 } else if (strcmp(tokens[t0 + 3], "pkts") == 0) { 689 p.ttl.n_packets_enabled = 1; 690 } else { 691 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 692 "none or pkts"); 693 return; 694 } 695 696 p.action_mask |= 1LLU << RTE_TABLE_ACTION_TTL; 697 t0 += 4; 698 } /* ttl */ 699 700 if (t0 < n_tokens && 701 (strcmp(tokens[t0], "stats") == 0)) { 702 if (n_tokens < t0 + 2) { 703 snprintf(out, out_size, MSG_ARG_MISMATCH, 704 "table action profile stats"); 705 return; 706 } 707 708 if (strcmp(tokens[t0 + 1], "pkts") == 0) { 709 p.stats.n_packets_enabled = 1; 710 p.stats.n_bytes_enabled = 0; 711 } else if (strcmp(tokens[t0 + 1], "bytes") == 0) { 712 p.stats.n_packets_enabled = 0; 713 p.stats.n_bytes_enabled = 1; 714 } else if (strcmp(tokens[t0 + 1], "both") == 0) { 715 p.stats.n_packets_enabled = 1; 716 p.stats.n_bytes_enabled = 1; 717 } else { 718 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 719 "pkts or bytes or both"); 720 return; 721 } 722 723 p.action_mask |= 1LLU << RTE_TABLE_ACTION_STATS; 724 t0 += 2; 725 } /* stats */ 726 727 if (t0 < n_tokens && 728 (strcmp(tokens[t0], "time") == 0)) { 729 p.action_mask |= 1LLU << RTE_TABLE_ACTION_TIME; 730 t0 += 1; 731 } /* time */ 732 733 if (t0 < n_tokens) { 734 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 735 return; 736 } 737 738 ap = softnic_table_action_profile_create(softnic, name, &p); 739 if (ap == NULL) { 740 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 741 return; 742 } 743 } 744 745 /** 746 * pipeline <pipeline_name> 747 * period <timer_period_ms> 748 * offset_port_id <offset_port_id> 749 */ 750 static void 751 cmd_pipeline(struct pmd_internals *softnic, 752 char **tokens, 753 uint32_t n_tokens, 754 char *out, 755 size_t out_size) 756 { 757 struct pipeline_params p; 758 char *name; 759 struct pipeline *pipeline; 760 761 if (n_tokens != 6) { 762 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 763 return; 764 } 765 766 name = tokens[1]; 767 768 if (strcmp(tokens[2], "period") != 0) { 769 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "period"); 770 return; 771 } 772 773 if (softnic_parser_read_uint32(&p.timer_period_ms, 774 tokens[3]) != 0) { 775 snprintf(out, out_size, MSG_ARG_INVALID, "timer_period_ms"); 776 return; 777 } 778 779 if (strcmp(tokens[4], "offset_port_id") != 0) { 780 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset_port_id"); 781 return; 782 } 783 784 if (softnic_parser_read_uint32(&p.offset_port_id, 785 tokens[5]) != 0) { 786 snprintf(out, out_size, MSG_ARG_INVALID, "offset_port_id"); 787 return; 788 } 789 790 pipeline = softnic_pipeline_create(softnic, name, &p); 791 if (pipeline == NULL) { 792 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 793 return; 794 } 795 } 796 797 /** 798 * pipeline <pipeline_name> port in 799 * bsz <burst_size> 800 * link <link_name> rxq <queue_id> 801 * | swq <swq_name> 802 * | tmgr <tmgr_name> 803 * | tap <tap_name> mempool <mempool_name> mtu <mtu> 804 * | source mempool <mempool_name> file <file_name> bpp <n_bytes_per_pkt> 805 * [action <port_in_action_profile_name>] 806 * [disabled] 807 */ 808 static void 809 cmd_pipeline_port_in(struct pmd_internals *softnic, 810 char **tokens, 811 uint32_t n_tokens, 812 char *out, 813 size_t out_size) 814 { 815 struct softnic_port_in_params p; 816 char *pipeline_name; 817 uint32_t t0; 818 int enabled, status; 819 820 if (n_tokens < 7) { 821 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 822 return; 823 } 824 825 pipeline_name = tokens[1]; 826 827 if (strcmp(tokens[2], "port") != 0) { 828 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 829 return; 830 } 831 832 if (strcmp(tokens[3], "in") != 0) { 833 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in"); 834 return; 835 } 836 837 if (strcmp(tokens[4], "bsz") != 0) { 838 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz"); 839 return; 840 } 841 842 if (softnic_parser_read_uint32(&p.burst_size, tokens[5]) != 0) { 843 snprintf(out, out_size, MSG_ARG_INVALID, "burst_size"); 844 return; 845 } 846 847 t0 = 6; 848 849 if (strcmp(tokens[t0], "link") == 0) { 850 if (n_tokens < t0 + 4) { 851 snprintf(out, out_size, MSG_ARG_MISMATCH, 852 "pipeline port in link"); 853 return; 854 } 855 856 p.type = PORT_IN_RXQ; 857 858 p.dev_name = tokens[t0 + 1]; 859 860 if (strcmp(tokens[t0 + 2], "rxq") != 0) { 861 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "rxq"); 862 return; 863 } 864 865 if (softnic_parser_read_uint16(&p.rxq.queue_id, 866 tokens[t0 + 3]) != 0) { 867 snprintf(out, out_size, MSG_ARG_INVALID, 868 "queue_id"); 869 return; 870 } 871 t0 += 4; 872 } else if (strcmp(tokens[t0], "swq") == 0) { 873 if (n_tokens < t0 + 2) { 874 snprintf(out, out_size, MSG_ARG_MISMATCH, 875 "pipeline port in swq"); 876 return; 877 } 878 879 p.type = PORT_IN_SWQ; 880 881 p.dev_name = tokens[t0 + 1]; 882 883 t0 += 2; 884 } else if (strcmp(tokens[t0], "tmgr") == 0) { 885 if (n_tokens < t0 + 2) { 886 snprintf(out, out_size, MSG_ARG_MISMATCH, 887 "pipeline port in tmgr"); 888 return; 889 } 890 891 p.type = PORT_IN_TMGR; 892 893 p.dev_name = tokens[t0 + 1]; 894 895 t0 += 2; 896 } else if (strcmp(tokens[t0], "tap") == 0) { 897 if (n_tokens < t0 + 6) { 898 snprintf(out, out_size, MSG_ARG_MISMATCH, 899 "pipeline port in tap"); 900 return; 901 } 902 903 p.type = PORT_IN_TAP; 904 905 p.dev_name = tokens[t0 + 1]; 906 907 if (strcmp(tokens[t0 + 2], "mempool") != 0) { 908 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 909 "mempool"); 910 return; 911 } 912 913 p.tap.mempool_name = tokens[t0 + 3]; 914 915 if (strcmp(tokens[t0 + 4], "mtu") != 0) { 916 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 917 "mtu"); 918 return; 919 } 920 921 if (softnic_parser_read_uint32(&p.tap.mtu, 922 tokens[t0 + 5]) != 0) { 923 snprintf(out, out_size, MSG_ARG_INVALID, "mtu"); 924 return; 925 } 926 927 t0 += 6; 928 } else if (strcmp(tokens[t0], "source") == 0) { 929 if (n_tokens < t0 + 6) { 930 snprintf(out, out_size, MSG_ARG_MISMATCH, 931 "pipeline port in source"); 932 return; 933 } 934 935 p.type = PORT_IN_SOURCE; 936 937 p.dev_name = NULL; 938 939 if (strcmp(tokens[t0 + 1], "mempool") != 0) { 940 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 941 "mempool"); 942 return; 943 } 944 945 p.source.mempool_name = tokens[t0 + 2]; 946 947 if (strcmp(tokens[t0 + 3], "file") != 0) { 948 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 949 "file"); 950 return; 951 } 952 953 p.source.file_name = tokens[t0 + 4]; 954 955 if (strcmp(tokens[t0 + 5], "bpp") != 0) { 956 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 957 "bpp"); 958 return; 959 } 960 961 if (softnic_parser_read_uint32(&p.source.n_bytes_per_pkt, 962 tokens[t0 + 6]) != 0) { 963 snprintf(out, out_size, MSG_ARG_INVALID, 964 "n_bytes_per_pkt"); 965 return; 966 } 967 968 t0 += 7; 969 } else { 970 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]); 971 return; 972 } 973 974 p.action_profile_name = NULL; 975 if (n_tokens > t0 && 976 (strcmp(tokens[t0], "action") == 0)) { 977 if (n_tokens < t0 + 2) { 978 snprintf(out, out_size, MSG_ARG_MISMATCH, "action"); 979 return; 980 } 981 982 p.action_profile_name = tokens[t0 + 1]; 983 984 t0 += 2; 985 } 986 987 enabled = 1; 988 if (n_tokens > t0 && 989 (strcmp(tokens[t0], "disabled") == 0)) { 990 enabled = 0; 991 992 t0 += 1; 993 } 994 995 if (n_tokens != t0) { 996 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 997 return; 998 } 999 1000 status = softnic_pipeline_port_in_create(softnic, 1001 pipeline_name, 1002 &p, 1003 enabled); 1004 if (status) { 1005 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 1006 return; 1007 } 1008 } 1009 1010 /** 1011 * pipeline <pipeline_name> port out 1012 * bsz <burst_size> 1013 * link <link_name> txq <txq_id> 1014 * | swq <swq_name> 1015 * | tmgr <tmgr_name> 1016 * | tap <tap_name> 1017 * | sink [file <file_name> pkts <max_n_pkts>] 1018 */ 1019 static void 1020 cmd_pipeline_port_out(struct pmd_internals *softnic, 1021 char **tokens, 1022 uint32_t n_tokens, 1023 char *out, 1024 size_t out_size) 1025 { 1026 struct softnic_port_out_params p; 1027 char *pipeline_name; 1028 int status; 1029 1030 memset(&p, 0, sizeof(p)); 1031 1032 if (n_tokens < 7) { 1033 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1034 return; 1035 } 1036 1037 pipeline_name = tokens[1]; 1038 1039 if (strcmp(tokens[2], "port") != 0) { 1040 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 1041 return; 1042 } 1043 1044 if (strcmp(tokens[3], "out") != 0) { 1045 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "out"); 1046 return; 1047 } 1048 1049 if (strcmp(tokens[4], "bsz") != 0) { 1050 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "bsz"); 1051 return; 1052 } 1053 1054 if (softnic_parser_read_uint32(&p.burst_size, tokens[5]) != 0) { 1055 snprintf(out, out_size, MSG_ARG_INVALID, "burst_size"); 1056 return; 1057 } 1058 1059 if (strcmp(tokens[6], "link") == 0) { 1060 if (n_tokens != 10) { 1061 snprintf(out, out_size, MSG_ARG_MISMATCH, 1062 "pipeline port out link"); 1063 return; 1064 } 1065 1066 p.type = PORT_OUT_TXQ; 1067 1068 p.dev_name = tokens[7]; 1069 1070 if (strcmp(tokens[8], "txq") != 0) { 1071 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "txq"); 1072 return; 1073 } 1074 1075 if (softnic_parser_read_uint16(&p.txq.queue_id, 1076 tokens[9]) != 0) { 1077 snprintf(out, out_size, MSG_ARG_INVALID, "queue_id"); 1078 return; 1079 } 1080 } else if (strcmp(tokens[6], "swq") == 0) { 1081 if (n_tokens != 8) { 1082 snprintf(out, out_size, MSG_ARG_MISMATCH, 1083 "pipeline port out swq"); 1084 return; 1085 } 1086 1087 p.type = PORT_OUT_SWQ; 1088 1089 p.dev_name = tokens[7]; 1090 } else if (strcmp(tokens[6], "tmgr") == 0) { 1091 if (n_tokens != 8) { 1092 snprintf(out, out_size, MSG_ARG_MISMATCH, 1093 "pipeline port out tmgr"); 1094 return; 1095 } 1096 1097 p.type = PORT_OUT_TMGR; 1098 1099 p.dev_name = tokens[7]; 1100 } else if (strcmp(tokens[6], "tap") == 0) { 1101 if (n_tokens != 8) { 1102 snprintf(out, out_size, MSG_ARG_MISMATCH, 1103 "pipeline port out tap"); 1104 return; 1105 } 1106 1107 p.type = PORT_OUT_TAP; 1108 1109 p.dev_name = tokens[7]; 1110 } else if (strcmp(tokens[6], "sink") == 0) { 1111 if ((n_tokens != 7) && (n_tokens != 11)) { 1112 snprintf(out, out_size, MSG_ARG_MISMATCH, 1113 "pipeline port out sink"); 1114 return; 1115 } 1116 1117 p.type = PORT_OUT_SINK; 1118 1119 p.dev_name = NULL; 1120 1121 if (n_tokens == 7) { 1122 p.sink.file_name = NULL; 1123 p.sink.max_n_pkts = 0; 1124 } else { 1125 if (strcmp(tokens[7], "file") != 0) { 1126 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 1127 "file"); 1128 return; 1129 } 1130 1131 p.sink.file_name = tokens[8]; 1132 1133 if (strcmp(tokens[9], "pkts") != 0) { 1134 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "pkts"); 1135 return; 1136 } 1137 1138 if (softnic_parser_read_uint32(&p.sink.max_n_pkts, 1139 tokens[10]) != 0) { 1140 snprintf(out, out_size, MSG_ARG_INVALID, "max_n_pkts"); 1141 return; 1142 } 1143 } 1144 } else { 1145 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]); 1146 return; 1147 } 1148 1149 status = softnic_pipeline_port_out_create(softnic, pipeline_name, &p); 1150 if (status) { 1151 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 1152 return; 1153 } 1154 } 1155 1156 /** 1157 * pipeline <pipeline_name> table 1158 * match 1159 * acl 1160 * ipv4 | ipv6 1161 * offset <ip_header_offset> 1162 * size <n_rules> 1163 * | array 1164 * offset <key_offset> 1165 * size <n_keys> 1166 * | hash 1167 * ext | lru 1168 * key <key_size> 1169 * mask <key_mask> 1170 * offset <key_offset> 1171 * buckets <n_buckets> 1172 * size <n_keys> 1173 * | lpm 1174 * ipv4 | ipv6 1175 * offset <ip_header_offset> 1176 * size <n_rules> 1177 * | stub 1178 * [action <table_action_profile_name>] 1179 */ 1180 static void 1181 cmd_pipeline_table(struct pmd_internals *softnic, 1182 char **tokens, 1183 uint32_t n_tokens, 1184 char *out, 1185 size_t out_size) 1186 { 1187 uint8_t key_mask[TABLE_RULE_MATCH_SIZE_MAX]; 1188 struct softnic_table_params p; 1189 char *pipeline_name; 1190 uint32_t t0; 1191 int status; 1192 1193 if (n_tokens < 5) { 1194 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1195 return; 1196 } 1197 1198 pipeline_name = tokens[1]; 1199 1200 if (strcmp(tokens[2], "table") != 0) { 1201 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); 1202 return; 1203 } 1204 1205 if (strcmp(tokens[3], "match") != 0) { 1206 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "match"); 1207 return; 1208 } 1209 1210 t0 = 4; 1211 if (strcmp(tokens[t0], "acl") == 0) { 1212 if (n_tokens < t0 + 6) { 1213 snprintf(out, out_size, MSG_ARG_MISMATCH, 1214 "pipeline table acl"); 1215 return; 1216 } 1217 1218 p.match_type = TABLE_ACL; 1219 1220 if (strcmp(tokens[t0 + 1], "ipv4") == 0) { 1221 p.match.acl.ip_version = 1; 1222 } else if (strcmp(tokens[t0 + 1], "ipv6") == 0) { 1223 p.match.acl.ip_version = 0; 1224 } else { 1225 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 1226 "ipv4 or ipv6"); 1227 return; 1228 } 1229 1230 if (strcmp(tokens[t0 + 2], "offset") != 0) { 1231 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); 1232 return; 1233 } 1234 1235 if (softnic_parser_read_uint32(&p.match.acl.ip_header_offset, 1236 tokens[t0 + 3]) != 0) { 1237 snprintf(out, out_size, MSG_ARG_INVALID, 1238 "ip_header_offset"); 1239 return; 1240 } 1241 1242 if (strcmp(tokens[t0 + 4], "size") != 0) { 1243 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size"); 1244 return; 1245 } 1246 1247 if (softnic_parser_read_uint32(&p.match.acl.n_rules, 1248 tokens[t0 + 5]) != 0) { 1249 snprintf(out, out_size, MSG_ARG_INVALID, "n_rules"); 1250 return; 1251 } 1252 1253 t0 += 6; 1254 } else if (strcmp(tokens[t0], "array") == 0) { 1255 if (n_tokens < t0 + 5) { 1256 snprintf(out, out_size, MSG_ARG_MISMATCH, 1257 "pipeline table array"); 1258 return; 1259 } 1260 1261 p.match_type = TABLE_ARRAY; 1262 1263 if (strcmp(tokens[t0 + 1], "offset") != 0) { 1264 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); 1265 return; 1266 } 1267 1268 if (softnic_parser_read_uint32(&p.match.array.key_offset, 1269 tokens[t0 + 2]) != 0) { 1270 snprintf(out, out_size, MSG_ARG_INVALID, "key_offset"); 1271 return; 1272 } 1273 1274 if (strcmp(tokens[t0 + 3], "size") != 0) { 1275 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size"); 1276 return; 1277 } 1278 1279 if (softnic_parser_read_uint32(&p.match.array.n_keys, 1280 tokens[t0 + 4]) != 0) { 1281 snprintf(out, out_size, MSG_ARG_INVALID, "n_keys"); 1282 return; 1283 } 1284 1285 t0 += 5; 1286 } else if (strcmp(tokens[t0], "hash") == 0) { 1287 uint32_t key_mask_size = TABLE_RULE_MATCH_SIZE_MAX; 1288 1289 if (n_tokens < t0 + 12) { 1290 snprintf(out, out_size, MSG_ARG_MISMATCH, 1291 "pipeline table hash"); 1292 return; 1293 } 1294 1295 p.match_type = TABLE_HASH; 1296 1297 if (strcmp(tokens[t0 + 1], "ext") == 0) { 1298 p.match.hash.extendable_bucket = 1; 1299 } else if (strcmp(tokens[t0 + 1], "lru") == 0) { 1300 p.match.hash.extendable_bucket = 0; 1301 } else { 1302 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 1303 "ext or lru"); 1304 return; 1305 } 1306 1307 if (strcmp(tokens[t0 + 2], "key") != 0) { 1308 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "key"); 1309 return; 1310 } 1311 1312 if ((softnic_parser_read_uint32(&p.match.hash.key_size, 1313 tokens[t0 + 3]) != 0) || 1314 p.match.hash.key_size == 0 || 1315 p.match.hash.key_size > TABLE_RULE_MATCH_SIZE_MAX) { 1316 snprintf(out, out_size, MSG_ARG_INVALID, "key_size"); 1317 return; 1318 } 1319 1320 if (strcmp(tokens[t0 + 4], "mask") != 0) { 1321 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "mask"); 1322 return; 1323 } 1324 1325 if ((softnic_parse_hex_string(tokens[t0 + 5], 1326 key_mask, &key_mask_size) != 0) || 1327 key_mask_size != p.match.hash.key_size) { 1328 snprintf(out, out_size, MSG_ARG_INVALID, "key_mask"); 1329 return; 1330 } 1331 p.match.hash.key_mask = key_mask; 1332 1333 if (strcmp(tokens[t0 + 6], "offset") != 0) { 1334 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); 1335 return; 1336 } 1337 1338 if (softnic_parser_read_uint32(&p.match.hash.key_offset, 1339 tokens[t0 + 7]) != 0) { 1340 snprintf(out, out_size, MSG_ARG_INVALID, "key_offset"); 1341 return; 1342 } 1343 1344 if (strcmp(tokens[t0 + 8], "buckets") != 0) { 1345 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "buckets"); 1346 return; 1347 } 1348 1349 if (softnic_parser_read_uint32(&p.match.hash.n_buckets, 1350 tokens[t0 + 9]) != 0) { 1351 snprintf(out, out_size, MSG_ARG_INVALID, "n_buckets"); 1352 return; 1353 } 1354 1355 if (strcmp(tokens[t0 + 10], "size") != 0) { 1356 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size"); 1357 return; 1358 } 1359 1360 if (softnic_parser_read_uint32(&p.match.hash.n_keys, 1361 tokens[t0 + 11]) != 0) { 1362 snprintf(out, out_size, MSG_ARG_INVALID, "n_keys"); 1363 return; 1364 } 1365 1366 t0 += 12; 1367 } else if (strcmp(tokens[t0], "lpm") == 0) { 1368 if (n_tokens < t0 + 6) { 1369 snprintf(out, out_size, MSG_ARG_MISMATCH, 1370 "pipeline table lpm"); 1371 return; 1372 } 1373 1374 p.match_type = TABLE_LPM; 1375 1376 if (strcmp(tokens[t0 + 1], "ipv4") == 0) { 1377 p.match.lpm.key_size = 4; 1378 } else if (strcmp(tokens[t0 + 1], "ipv6") == 0) { 1379 p.match.lpm.key_size = 16; 1380 } else { 1381 snprintf(out, out_size, MSG_ARG_NOT_FOUND, 1382 "ipv4 or ipv6"); 1383 return; 1384 } 1385 1386 if (strcmp(tokens[t0 + 2], "offset") != 0) { 1387 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "offset"); 1388 return; 1389 } 1390 1391 if (softnic_parser_read_uint32(&p.match.lpm.key_offset, 1392 tokens[t0 + 3]) != 0) { 1393 snprintf(out, out_size, MSG_ARG_INVALID, "key_offset"); 1394 return; 1395 } 1396 1397 if (strcmp(tokens[t0 + 4], "size") != 0) { 1398 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "size"); 1399 return; 1400 } 1401 1402 if (softnic_parser_read_uint32(&p.match.lpm.n_rules, 1403 tokens[t0 + 5]) != 0) { 1404 snprintf(out, out_size, MSG_ARG_INVALID, "n_rules"); 1405 return; 1406 } 1407 1408 t0 += 6; 1409 } else if (strcmp(tokens[t0], "stub") == 0) { 1410 p.match_type = TABLE_STUB; 1411 1412 t0 += 1; 1413 } else { 1414 snprintf(out, out_size, MSG_ARG_INVALID, tokens[0]); 1415 return; 1416 } 1417 1418 p.action_profile_name = NULL; 1419 if (n_tokens > t0 && 1420 (strcmp(tokens[t0], "action") == 0)) { 1421 if (n_tokens < t0 + 2) { 1422 snprintf(out, out_size, MSG_ARG_MISMATCH, "action"); 1423 return; 1424 } 1425 1426 p.action_profile_name = tokens[t0 + 1]; 1427 1428 t0 += 2; 1429 } 1430 1431 if (n_tokens > t0) { 1432 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1433 return; 1434 } 1435 1436 status = softnic_pipeline_table_create(softnic, pipeline_name, &p); 1437 if (status) { 1438 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 1439 return; 1440 } 1441 } 1442 1443 /** 1444 * pipeline <pipeline_name> port in <port_id> table <table_id> 1445 */ 1446 static void 1447 cmd_pipeline_port_in_table(struct pmd_internals *softnic, 1448 char **tokens, 1449 uint32_t n_tokens, 1450 char *out, 1451 size_t out_size) 1452 { 1453 char *pipeline_name; 1454 uint32_t port_id, table_id; 1455 int status; 1456 1457 if (n_tokens != 7) { 1458 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1459 return; 1460 } 1461 1462 pipeline_name = tokens[1]; 1463 1464 if (strcmp(tokens[2], "port") != 0) { 1465 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 1466 return; 1467 } 1468 1469 if (strcmp(tokens[3], "in") != 0) { 1470 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in"); 1471 return; 1472 } 1473 1474 if (softnic_parser_read_uint32(&port_id, tokens[4]) != 0) { 1475 snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); 1476 return; 1477 } 1478 1479 if (strcmp(tokens[5], "table") != 0) { 1480 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "table"); 1481 return; 1482 } 1483 1484 if (softnic_parser_read_uint32(&table_id, tokens[6]) != 0) { 1485 snprintf(out, out_size, MSG_ARG_INVALID, "table_id"); 1486 return; 1487 } 1488 1489 status = softnic_pipeline_port_in_connect_to_table(softnic, 1490 pipeline_name, 1491 port_id, 1492 table_id); 1493 if (status) { 1494 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 1495 return; 1496 } 1497 } 1498 1499 /** 1500 * pipeline <pipeline_name> port in <port_id> enable 1501 */ 1502 static void 1503 cmd_softnic_pipeline_port_in_enable(struct pmd_internals *softnic, 1504 char **tokens, 1505 uint32_t n_tokens, 1506 char *out, 1507 size_t out_size) 1508 { 1509 char *pipeline_name; 1510 uint32_t port_id; 1511 int status; 1512 1513 if (n_tokens != 6) { 1514 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1515 return; 1516 } 1517 1518 pipeline_name = tokens[1]; 1519 1520 if (strcmp(tokens[2], "port") != 0) { 1521 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 1522 return; 1523 } 1524 1525 if (strcmp(tokens[3], "in") != 0) { 1526 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in"); 1527 return; 1528 } 1529 1530 if (softnic_parser_read_uint32(&port_id, tokens[4]) != 0) { 1531 snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); 1532 return; 1533 } 1534 1535 if (strcmp(tokens[5], "enable") != 0) { 1536 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "enable"); 1537 return; 1538 } 1539 1540 status = softnic_pipeline_port_in_enable(softnic, pipeline_name, port_id); 1541 if (status) { 1542 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 1543 return; 1544 } 1545 } 1546 1547 /** 1548 * pipeline <pipeline_name> port in <port_id> disable 1549 */ 1550 static void 1551 cmd_softnic_pipeline_port_in_disable(struct pmd_internals *softnic, 1552 char **tokens, 1553 uint32_t n_tokens, 1554 char *out, 1555 size_t out_size) 1556 { 1557 char *pipeline_name; 1558 uint32_t port_id; 1559 int status; 1560 1561 if (n_tokens != 6) { 1562 snprintf(out, out_size, MSG_ARG_MISMATCH, tokens[0]); 1563 return; 1564 } 1565 1566 pipeline_name = tokens[1]; 1567 1568 if (strcmp(tokens[2], "port") != 0) { 1569 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "port"); 1570 return; 1571 } 1572 1573 if (strcmp(tokens[3], "in") != 0) { 1574 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "in"); 1575 return; 1576 } 1577 1578 if (softnic_parser_read_uint32(&port_id, tokens[4]) != 0) { 1579 snprintf(out, out_size, MSG_ARG_INVALID, "port_id"); 1580 return; 1581 } 1582 1583 if (strcmp(tokens[5], "disable") != 0) { 1584 snprintf(out, out_size, MSG_ARG_NOT_FOUND, "disable"); 1585 return; 1586 } 1587 1588 status = softnic_pipeline_port_in_disable(softnic, pipeline_name, port_id); 1589 if (status) { 1590 snprintf(out, out_size, MSG_CMD_FAIL, tokens[0]); 1591 return; 1592 } 1593 } 1594 1595 void 1596 softnic_cli_process(char *in, char *out, size_t out_size, void *arg) 1597 { 1598 char *tokens[CMD_MAX_TOKENS]; 1599 uint32_t n_tokens = RTE_DIM(tokens); 1600 struct pmd_internals *softnic = arg; 1601 int status; 1602 1603 if (is_comment(in)) 1604 return; 1605 1606 status = softnic_parse_tokenize_string(in, tokens, &n_tokens); 1607 if (status) { 1608 snprintf(out, out_size, MSG_ARG_TOO_MANY, ""); 1609 return; 1610 } 1611 1612 if (n_tokens == 0) 1613 return; 1614 1615 if (strcmp(tokens[0], "mempool") == 0) { 1616 cmd_mempool(softnic, tokens, n_tokens, out, out_size); 1617 return; 1618 } 1619 1620 if (strcmp(tokens[0], "link") == 0) { 1621 cmd_link(softnic, tokens, n_tokens, out, out_size); 1622 return; 1623 } 1624 1625 if (strcmp(tokens[0], "swq") == 0) { 1626 cmd_swq(softnic, tokens, n_tokens, out, out_size); 1627 return; 1628 } 1629 1630 if (strcmp(tokens[0], "tap") == 0) { 1631 cmd_tap(softnic, tokens, n_tokens, out, out_size); 1632 return; 1633 } 1634 1635 if (strcmp(tokens[0], "port") == 0) { 1636 cmd_port_in_action_profile(softnic, tokens, n_tokens, out, out_size); 1637 return; 1638 } 1639 1640 if (strcmp(tokens[0], "table") == 0) { 1641 cmd_table_action_profile(softnic, tokens, n_tokens, out, out_size); 1642 return; 1643 } 1644 1645 if (strcmp(tokens[0], "pipeline") == 0) { 1646 if (n_tokens >= 3 && 1647 (strcmp(tokens[2], "period") == 0)) { 1648 cmd_pipeline(softnic, tokens, n_tokens, out, out_size); 1649 return; 1650 } 1651 1652 if (n_tokens >= 5 && 1653 (strcmp(tokens[2], "port") == 0) && 1654 (strcmp(tokens[3], "in") == 0) && 1655 (strcmp(tokens[4], "bsz") == 0)) { 1656 cmd_pipeline_port_in(softnic, tokens, n_tokens, out, out_size); 1657 return; 1658 } 1659 1660 if (n_tokens >= 5 && 1661 (strcmp(tokens[2], "port") == 0) && 1662 (strcmp(tokens[3], "out") == 0) && 1663 (strcmp(tokens[4], "bsz") == 0)) { 1664 cmd_pipeline_port_out(softnic, tokens, n_tokens, out, out_size); 1665 return; 1666 } 1667 1668 if (n_tokens >= 4 && 1669 (strcmp(tokens[2], "table") == 0) && 1670 (strcmp(tokens[3], "match") == 0)) { 1671 cmd_pipeline_table(softnic, tokens, n_tokens, out, out_size); 1672 return; 1673 } 1674 1675 if (n_tokens >= 6 && 1676 (strcmp(tokens[2], "port") == 0) && 1677 (strcmp(tokens[3], "in") == 0) && 1678 (strcmp(tokens[5], "table") == 0)) { 1679 cmd_pipeline_port_in_table(softnic, tokens, n_tokens, 1680 out, out_size); 1681 return; 1682 } 1683 1684 if (n_tokens >= 6 && 1685 (strcmp(tokens[2], "port") == 0) && 1686 (strcmp(tokens[3], "in") == 0) && 1687 (strcmp(tokens[5], "enable") == 0)) { 1688 cmd_softnic_pipeline_port_in_enable(softnic, tokens, n_tokens, 1689 out, out_size); 1690 return; 1691 } 1692 1693 if (n_tokens >= 6 && 1694 (strcmp(tokens[2], "port") == 0) && 1695 (strcmp(tokens[3], "in") == 0) && 1696 (strcmp(tokens[5], "disable") == 0)) { 1697 cmd_softnic_pipeline_port_in_disable(softnic, tokens, n_tokens, 1698 out, out_size); 1699 return; 1700 } 1701 } 1702 1703 snprintf(out, out_size, MSG_CMD_UNKNOWN, tokens[0]); 1704 } 1705 1706 int 1707 softnic_cli_script_process(struct pmd_internals *softnic, 1708 const char *file_name, 1709 size_t msg_in_len_max, 1710 size_t msg_out_len_max) 1711 { 1712 char *msg_in = NULL, *msg_out = NULL; 1713 FILE *f = NULL; 1714 1715 /* Check input arguments */ 1716 if (file_name == NULL || 1717 strlen(file_name) == 0 || 1718 msg_in_len_max == 0 || 1719 msg_out_len_max == 0) 1720 return -EINVAL; 1721 1722 msg_in = malloc(msg_in_len_max + 1); 1723 msg_out = malloc(msg_out_len_max + 1); 1724 if (msg_in == NULL || 1725 msg_out == NULL) { 1726 free(msg_out); 1727 free(msg_in); 1728 return -ENOMEM; 1729 } 1730 1731 /* Open input file */ 1732 f = fopen(file_name, "r"); 1733 if (f == NULL) { 1734 free(msg_out); 1735 free(msg_in); 1736 return -EIO; 1737 } 1738 1739 /* Read file */ 1740 for ( ; ; ) { 1741 if (fgets(msg_in, msg_in_len_max + 1, f) == NULL) 1742 break; 1743 1744 printf("%s", msg_in); 1745 msg_out[0] = 0; 1746 1747 softnic_cli_process(msg_in, 1748 msg_out, 1749 msg_out_len_max, 1750 softnic); 1751 1752 if (strlen(msg_out)) 1753 printf("%s", msg_out); 1754 } 1755 1756 /* Close file */ 1757 fclose(f); 1758 free(msg_out); 1759 free(msg_in); 1760 return 0; 1761 } 1762