1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2018 Intel Corporation 3 */ 4 5 #include <stdlib.h> 6 #include <string.h> 7 8 #include <rte_common.h> 9 #include <rte_ip.h> 10 #include <rte_tcp.h> 11 12 #include <rte_string_fns.h> 13 #include <rte_port_ethdev.h> 14 #include <rte_port_ring.h> 15 #include <rte_port_source_sink.h> 16 #include <rte_port_fd.h> 17 #include <rte_port_sched.h> 18 19 #include <rte_table_acl.h> 20 #include <rte_table_array.h> 21 #include <rte_table_hash.h> 22 #include <rte_table_hash_func.h> 23 #include <rte_table_lpm.h> 24 #include <rte_table_lpm_ipv6.h> 25 #include <rte_table_stub.h> 26 27 #include "rte_eth_softnic_internals.h" 28 29 #ifndef PIPELINE_MSGQ_SIZE 30 #define PIPELINE_MSGQ_SIZE 64 31 #endif 32 33 #ifndef TABLE_LPM_NUMBER_TBL8 34 #define TABLE_LPM_NUMBER_TBL8 256 35 #endif 36 37 int 38 softnic_pipeline_init(struct pmd_internals *p) 39 { 40 TAILQ_INIT(&p->pipeline_list); 41 42 return 0; 43 } 44 45 static void 46 softnic_pipeline_table_free(struct softnic_table *table) 47 { 48 for ( ; ; ) { 49 struct rte_flow *flow; 50 51 flow = TAILQ_FIRST(&table->flows); 52 if (flow == NULL) 53 break; 54 55 TAILQ_REMOVE(&table->flows, flow, node); 56 free(flow); 57 } 58 59 for ( ; ; ) { 60 struct softnic_table_meter_profile *mp; 61 62 mp = TAILQ_FIRST(&table->meter_profiles); 63 if (mp == NULL) 64 break; 65 66 TAILQ_REMOVE(&table->meter_profiles, mp, node); 67 free(mp); 68 } 69 } 70 71 void 72 softnic_pipeline_free(struct pmd_internals *p) 73 { 74 for ( ; ; ) { 75 struct pipeline *pipeline; 76 uint32_t table_id; 77 78 pipeline = TAILQ_FIRST(&p->pipeline_list); 79 if (pipeline == NULL) 80 break; 81 82 TAILQ_REMOVE(&p->pipeline_list, pipeline, node); 83 84 for (table_id = 0; table_id < pipeline->n_tables; table_id++) { 85 struct softnic_table *table = 86 &pipeline->table[table_id]; 87 88 softnic_pipeline_table_free(table); 89 } 90 91 rte_ring_free(pipeline->msgq_req); 92 rte_ring_free(pipeline->msgq_rsp); 93 rte_pipeline_free(pipeline->p); 94 free(pipeline); 95 } 96 } 97 98 void 99 softnic_pipeline_disable_all(struct pmd_internals *p) 100 { 101 struct pipeline *pipeline; 102 103 TAILQ_FOREACH(pipeline, &p->pipeline_list, node) 104 if (pipeline->enabled) 105 softnic_thread_pipeline_disable(p, 106 pipeline->thread_id, 107 pipeline->name); 108 } 109 110 struct pipeline * 111 softnic_pipeline_find(struct pmd_internals *p, 112 const char *name) 113 { 114 struct pipeline *pipeline; 115 116 if (name == NULL) 117 return NULL; 118 119 TAILQ_FOREACH(pipeline, &p->pipeline_list, node) 120 if (strcmp(name, pipeline->name) == 0) 121 return pipeline; 122 123 return NULL; 124 } 125 126 struct pipeline * 127 softnic_pipeline_create(struct pmd_internals *softnic, 128 const char *name, 129 struct pipeline_params *params) 130 { 131 char resource_name[NAME_MAX]; 132 struct rte_pipeline_params pp; 133 struct pipeline *pipeline; 134 struct rte_pipeline *p; 135 struct rte_ring *msgq_req; 136 struct rte_ring *msgq_rsp; 137 138 /* Check input params */ 139 if (name == NULL || 140 softnic_pipeline_find(softnic, name) || 141 params == NULL || 142 params->timer_period_ms == 0) 143 return NULL; 144 145 /* Resource create */ 146 snprintf(resource_name, sizeof(resource_name), "%s-%s-REQ", 147 softnic->params.name, 148 name); 149 150 msgq_req = rte_ring_create(resource_name, 151 PIPELINE_MSGQ_SIZE, 152 softnic->params.cpu_id, 153 RING_F_SP_ENQ | RING_F_SC_DEQ); 154 if (msgq_req == NULL) 155 return NULL; 156 157 snprintf(resource_name, sizeof(resource_name), "%s-%s-RSP", 158 softnic->params.name, 159 name); 160 161 msgq_rsp = rte_ring_create(resource_name, 162 PIPELINE_MSGQ_SIZE, 163 softnic->params.cpu_id, 164 RING_F_SP_ENQ | RING_F_SC_DEQ); 165 if (msgq_rsp == NULL) { 166 rte_ring_free(msgq_req); 167 return NULL; 168 } 169 170 snprintf(resource_name, sizeof(resource_name), "%s_%s", 171 softnic->params.name, 172 name); 173 174 pp.name = resource_name; 175 pp.socket_id = (int)softnic->params.cpu_id; 176 pp.offset_port_id = params->offset_port_id; 177 178 p = rte_pipeline_create(&pp); 179 if (p == NULL) { 180 rte_ring_free(msgq_rsp); 181 rte_ring_free(msgq_req); 182 return NULL; 183 } 184 185 /* Node allocation */ 186 pipeline = calloc(1, sizeof(struct pipeline)); 187 if (pipeline == NULL) { 188 rte_pipeline_free(p); 189 rte_ring_free(msgq_rsp); 190 rte_ring_free(msgq_req); 191 return NULL; 192 } 193 194 /* Node fill in */ 195 strlcpy(pipeline->name, name, sizeof(pipeline->name)); 196 pipeline->p = p; 197 memcpy(&pipeline->params, params, sizeof(*params)); 198 pipeline->n_ports_in = 0; 199 pipeline->n_ports_out = 0; 200 pipeline->n_tables = 0; 201 pipeline->msgq_req = msgq_req; 202 pipeline->msgq_rsp = msgq_rsp; 203 pipeline->timer_period_ms = params->timer_period_ms; 204 pipeline->enabled = 0; 205 pipeline->cpu_id = softnic->params.cpu_id; 206 207 /* Node add to list */ 208 TAILQ_INSERT_TAIL(&softnic->pipeline_list, pipeline, node); 209 210 return pipeline; 211 } 212 213 int 214 softnic_pipeline_port_in_create(struct pmd_internals *softnic, 215 const char *pipeline_name, 216 struct softnic_port_in_params *params, 217 int enabled) 218 { 219 struct rte_pipeline_port_in_params p; 220 221 union { 222 struct rte_port_ethdev_reader_params ethdev; 223 struct rte_port_ring_reader_params ring; 224 struct rte_port_sched_reader_params sched; 225 struct rte_port_fd_reader_params fd; 226 struct rte_port_source_params source; 227 } pp; 228 229 struct pipeline *pipeline; 230 struct softnic_port_in *port_in; 231 struct softnic_port_in_action_profile *ap; 232 struct rte_port_in_action *action; 233 uint32_t port_id; 234 int status; 235 236 memset(&p, 0, sizeof(p)); 237 memset(&pp, 0, sizeof(pp)); 238 239 /* Check input params */ 240 if (pipeline_name == NULL || 241 params == NULL || 242 params->burst_size == 0 || 243 params->burst_size > RTE_PORT_IN_BURST_SIZE_MAX) 244 return -1; 245 246 pipeline = softnic_pipeline_find(softnic, pipeline_name); 247 if (pipeline == NULL) 248 return -1; 249 250 ap = NULL; 251 if (strlen(params->action_profile_name)) { 252 ap = softnic_port_in_action_profile_find(softnic, 253 params->action_profile_name); 254 if (ap == NULL) 255 return -1; 256 } 257 258 switch (params->type) { 259 case PORT_IN_RXQ: 260 { 261 struct softnic_link *link; 262 263 link = softnic_link_find(softnic, params->dev_name); 264 if (link == NULL) 265 return -1; 266 267 if (params->rxq.queue_id >= link->n_rxq) 268 return -1; 269 270 pp.ethdev.port_id = link->port_id; 271 pp.ethdev.queue_id = params->rxq.queue_id; 272 273 p.ops = &rte_port_ethdev_reader_ops; 274 p.arg_create = &pp.ethdev; 275 break; 276 } 277 278 case PORT_IN_SWQ: 279 { 280 struct softnic_swq *swq; 281 282 swq = softnic_swq_find(softnic, params->dev_name); 283 if (swq == NULL) 284 return -1; 285 286 pp.ring.ring = swq->r; 287 288 p.ops = &rte_port_ring_reader_ops; 289 p.arg_create = &pp.ring; 290 break; 291 } 292 293 case PORT_IN_TMGR: 294 { 295 struct softnic_tmgr_port *tmgr_port; 296 297 tmgr_port = softnic_tmgr_port_find(softnic, params->dev_name); 298 if (tmgr_port == NULL) 299 return -1; 300 301 pp.sched.sched = tmgr_port->s; 302 303 p.ops = &rte_port_sched_reader_ops; 304 p.arg_create = &pp.sched; 305 break; 306 } 307 308 case PORT_IN_TAP: 309 { 310 struct softnic_tap *tap; 311 struct softnic_mempool *mempool; 312 313 tap = softnic_tap_find(softnic, params->dev_name); 314 mempool = softnic_mempool_find(softnic, params->tap.mempool_name); 315 if (tap == NULL || mempool == NULL) 316 return -1; 317 318 pp.fd.fd = tap->fd; 319 pp.fd.mempool = mempool->m; 320 pp.fd.mtu = params->tap.mtu; 321 322 p.ops = &rte_port_fd_reader_ops; 323 p.arg_create = &pp.fd; 324 break; 325 } 326 327 case PORT_IN_SOURCE: 328 { 329 struct softnic_mempool *mempool; 330 331 mempool = softnic_mempool_find(softnic, params->source.mempool_name); 332 if (mempool == NULL) 333 return -1; 334 335 pp.source.mempool = mempool->m; 336 pp.source.file_name = params->source.file_name; 337 pp.source.n_bytes_per_pkt = params->source.n_bytes_per_pkt; 338 339 p.ops = &rte_port_source_ops; 340 p.arg_create = &pp.source; 341 break; 342 } 343 344 default: 345 return -1; 346 } 347 348 p.burst_size = params->burst_size; 349 350 /* Resource create */ 351 action = NULL; 352 p.f_action = NULL; 353 p.arg_ah = NULL; 354 355 if (ap) { 356 action = rte_port_in_action_create(ap->ap, 357 softnic->params.cpu_id); 358 if (action == NULL) 359 return -1; 360 361 status = rte_port_in_action_params_get(action, 362 &p); 363 if (status) { 364 rte_port_in_action_free(action); 365 return -1; 366 } 367 } 368 369 status = rte_pipeline_port_in_create(pipeline->p, 370 &p, 371 &port_id); 372 if (status) { 373 rte_port_in_action_free(action); 374 return -1; 375 } 376 377 if (enabled) 378 rte_pipeline_port_in_enable(pipeline->p, port_id); 379 380 /* Pipeline */ 381 port_in = &pipeline->port_in[pipeline->n_ports_in]; 382 memcpy(&port_in->params, params, sizeof(*params)); 383 port_in->ap = ap; 384 port_in->a = action; 385 pipeline->n_ports_in++; 386 387 return 0; 388 } 389 390 int 391 softnic_pipeline_port_in_connect_to_table(struct pmd_internals *softnic, 392 const char *pipeline_name, 393 uint32_t port_id, 394 uint32_t table_id) 395 { 396 struct pipeline *pipeline; 397 int status; 398 399 /* Check input params */ 400 if (pipeline_name == NULL) 401 return -1; 402 403 pipeline = softnic_pipeline_find(softnic, pipeline_name); 404 if (pipeline == NULL || 405 port_id >= pipeline->n_ports_in || 406 table_id >= pipeline->n_tables) 407 return -1; 408 409 /* Resource */ 410 status = rte_pipeline_port_in_connect_to_table(pipeline->p, 411 port_id, 412 table_id); 413 414 return status; 415 } 416 417 int 418 softnic_pipeline_port_out_create(struct pmd_internals *softnic, 419 const char *pipeline_name, 420 struct softnic_port_out_params *params) 421 { 422 struct rte_pipeline_port_out_params p; 423 424 union { 425 struct rte_port_ethdev_writer_params ethdev; 426 struct rte_port_ring_writer_params ring; 427 struct rte_port_sched_writer_params sched; 428 struct rte_port_fd_writer_params fd; 429 struct rte_port_sink_params sink; 430 } pp; 431 432 union { 433 struct rte_port_ethdev_writer_nodrop_params ethdev; 434 struct rte_port_ring_writer_nodrop_params ring; 435 struct rte_port_fd_writer_nodrop_params fd; 436 } pp_nodrop; 437 438 struct pipeline *pipeline; 439 struct softnic_port_out *port_out; 440 uint32_t port_id; 441 int status; 442 443 memset(&p, 0, sizeof(p)); 444 memset(&pp, 0, sizeof(pp)); 445 memset(&pp_nodrop, 0, sizeof(pp_nodrop)); 446 447 /* Check input params */ 448 if (pipeline_name == NULL || 449 params == NULL || 450 params->burst_size == 0 || 451 params->burst_size > RTE_PORT_IN_BURST_SIZE_MAX) 452 return -1; 453 454 pipeline = softnic_pipeline_find(softnic, pipeline_name); 455 if (pipeline == NULL) 456 return -1; 457 458 switch (params->type) { 459 case PORT_OUT_TXQ: 460 { 461 struct softnic_link *link; 462 463 link = softnic_link_find(softnic, params->dev_name); 464 if (link == NULL) 465 return -1; 466 467 if (params->txq.queue_id >= link->n_txq) 468 return -1; 469 470 pp.ethdev.port_id = link->port_id; 471 pp.ethdev.queue_id = params->txq.queue_id; 472 pp.ethdev.tx_burst_sz = params->burst_size; 473 474 pp_nodrop.ethdev.port_id = link->port_id; 475 pp_nodrop.ethdev.queue_id = params->txq.queue_id; 476 pp_nodrop.ethdev.tx_burst_sz = params->burst_size; 477 pp_nodrop.ethdev.n_retries = params->n_retries; 478 479 if (params->retry == 0) { 480 p.ops = &rte_port_ethdev_writer_ops; 481 p.arg_create = &pp.ethdev; 482 } else { 483 p.ops = &rte_port_ethdev_writer_nodrop_ops; 484 p.arg_create = &pp_nodrop.ethdev; 485 } 486 break; 487 } 488 489 case PORT_OUT_SWQ: 490 { 491 struct softnic_swq *swq; 492 493 swq = softnic_swq_find(softnic, params->dev_name); 494 if (swq == NULL) 495 return -1; 496 497 pp.ring.ring = swq->r; 498 pp.ring.tx_burst_sz = params->burst_size; 499 500 pp_nodrop.ring.ring = swq->r; 501 pp_nodrop.ring.tx_burst_sz = params->burst_size; 502 pp_nodrop.ring.n_retries = params->n_retries; 503 504 if (params->retry == 0) { 505 p.ops = &rte_port_ring_writer_ops; 506 p.arg_create = &pp.ring; 507 } else { 508 p.ops = &rte_port_ring_writer_nodrop_ops; 509 p.arg_create = &pp_nodrop.ring; 510 } 511 break; 512 } 513 514 case PORT_OUT_TMGR: 515 { 516 struct softnic_tmgr_port *tmgr_port; 517 518 tmgr_port = softnic_tmgr_port_find(softnic, params->dev_name); 519 if (tmgr_port == NULL) 520 return -1; 521 522 pp.sched.sched = tmgr_port->s; 523 pp.sched.tx_burst_sz = params->burst_size; 524 525 p.ops = &rte_port_sched_writer_ops; 526 p.arg_create = &pp.sched; 527 break; 528 } 529 530 case PORT_OUT_TAP: 531 { 532 struct softnic_tap *tap; 533 534 tap = softnic_tap_find(softnic, params->dev_name); 535 if (tap == NULL) 536 return -1; 537 538 pp.fd.fd = tap->fd; 539 pp.fd.tx_burst_sz = params->burst_size; 540 541 pp_nodrop.fd.fd = tap->fd; 542 pp_nodrop.fd.tx_burst_sz = params->burst_size; 543 pp_nodrop.fd.n_retries = params->n_retries; 544 545 if (params->retry == 0) { 546 p.ops = &rte_port_fd_writer_ops; 547 p.arg_create = &pp.fd; 548 } else { 549 p.ops = &rte_port_fd_writer_nodrop_ops; 550 p.arg_create = &pp_nodrop.fd; 551 } 552 break; 553 } 554 555 case PORT_OUT_SINK: 556 { 557 pp.sink.file_name = params->sink.file_name; 558 pp.sink.max_n_pkts = params->sink.max_n_pkts; 559 560 p.ops = &rte_port_sink_ops; 561 p.arg_create = &pp.sink; 562 break; 563 } 564 565 default: 566 return -1; 567 } 568 569 p.f_action = NULL; 570 p.arg_ah = NULL; 571 572 /* Resource create */ 573 status = rte_pipeline_port_out_create(pipeline->p, 574 &p, 575 &port_id); 576 577 if (status) 578 return -1; 579 580 /* Pipeline */ 581 port_out = &pipeline->port_out[pipeline->n_ports_out]; 582 memcpy(&port_out->params, params, sizeof(*params)); 583 pipeline->n_ports_out++; 584 585 return 0; 586 } 587 588 static const struct rte_acl_field_def table_acl_field_format_ipv4[] = { 589 /* Protocol */ 590 [0] = { 591 .type = RTE_ACL_FIELD_TYPE_BITMASK, 592 .size = sizeof(uint8_t), 593 .field_index = 0, 594 .input_index = 0, 595 .offset = offsetof(struct ipv4_hdr, next_proto_id), 596 }, 597 598 /* Source IP address (IPv4) */ 599 [1] = { 600 .type = RTE_ACL_FIELD_TYPE_MASK, 601 .size = sizeof(uint32_t), 602 .field_index = 1, 603 .input_index = 1, 604 .offset = offsetof(struct ipv4_hdr, src_addr), 605 }, 606 607 /* Destination IP address (IPv4) */ 608 [2] = { 609 .type = RTE_ACL_FIELD_TYPE_MASK, 610 .size = sizeof(uint32_t), 611 .field_index = 2, 612 .input_index = 2, 613 .offset = offsetof(struct ipv4_hdr, dst_addr), 614 }, 615 616 /* Source Port */ 617 [3] = { 618 .type = RTE_ACL_FIELD_TYPE_RANGE, 619 .size = sizeof(uint16_t), 620 .field_index = 3, 621 .input_index = 3, 622 .offset = sizeof(struct ipv4_hdr) + 623 offsetof(struct tcp_hdr, src_port), 624 }, 625 626 /* Destination Port */ 627 [4] = { 628 .type = RTE_ACL_FIELD_TYPE_RANGE, 629 .size = sizeof(uint16_t), 630 .field_index = 4, 631 .input_index = 3, 632 .offset = sizeof(struct ipv4_hdr) + 633 offsetof(struct tcp_hdr, dst_port), 634 }, 635 }; 636 637 static const struct rte_acl_field_def table_acl_field_format_ipv6[] = { 638 /* Protocol */ 639 [0] = { 640 .type = RTE_ACL_FIELD_TYPE_BITMASK, 641 .size = sizeof(uint8_t), 642 .field_index = 0, 643 .input_index = 0, 644 .offset = offsetof(struct ipv6_hdr, proto), 645 }, 646 647 /* Source IP address (IPv6) */ 648 [1] = { 649 .type = RTE_ACL_FIELD_TYPE_MASK, 650 .size = sizeof(uint32_t), 651 .field_index = 1, 652 .input_index = 1, 653 .offset = offsetof(struct ipv6_hdr, src_addr[0]), 654 }, 655 656 [2] = { 657 .type = RTE_ACL_FIELD_TYPE_MASK, 658 .size = sizeof(uint32_t), 659 .field_index = 2, 660 .input_index = 2, 661 .offset = offsetof(struct ipv6_hdr, src_addr[4]), 662 }, 663 664 [3] = { 665 .type = RTE_ACL_FIELD_TYPE_MASK, 666 .size = sizeof(uint32_t), 667 .field_index = 3, 668 .input_index = 3, 669 .offset = offsetof(struct ipv6_hdr, src_addr[8]), 670 }, 671 672 [4] = { 673 .type = RTE_ACL_FIELD_TYPE_MASK, 674 .size = sizeof(uint32_t), 675 .field_index = 4, 676 .input_index = 4, 677 .offset = offsetof(struct ipv6_hdr, src_addr[12]), 678 }, 679 680 /* Destination IP address (IPv6) */ 681 [5] = { 682 .type = RTE_ACL_FIELD_TYPE_MASK, 683 .size = sizeof(uint32_t), 684 .field_index = 5, 685 .input_index = 5, 686 .offset = offsetof(struct ipv6_hdr, dst_addr[0]), 687 }, 688 689 [6] = { 690 .type = RTE_ACL_FIELD_TYPE_MASK, 691 .size = sizeof(uint32_t), 692 .field_index = 6, 693 .input_index = 6, 694 .offset = offsetof(struct ipv6_hdr, dst_addr[4]), 695 }, 696 697 [7] = { 698 .type = RTE_ACL_FIELD_TYPE_MASK, 699 .size = sizeof(uint32_t), 700 .field_index = 7, 701 .input_index = 7, 702 .offset = offsetof(struct ipv6_hdr, dst_addr[8]), 703 }, 704 705 [8] = { 706 .type = RTE_ACL_FIELD_TYPE_MASK, 707 .size = sizeof(uint32_t), 708 .field_index = 8, 709 .input_index = 8, 710 .offset = offsetof(struct ipv6_hdr, dst_addr[12]), 711 }, 712 713 /* Source Port */ 714 [9] = { 715 .type = RTE_ACL_FIELD_TYPE_RANGE, 716 .size = sizeof(uint16_t), 717 .field_index = 9, 718 .input_index = 9, 719 .offset = sizeof(struct ipv6_hdr) + 720 offsetof(struct tcp_hdr, src_port), 721 }, 722 723 /* Destination Port */ 724 [10] = { 725 .type = RTE_ACL_FIELD_TYPE_RANGE, 726 .size = sizeof(uint16_t), 727 .field_index = 10, 728 .input_index = 9, 729 .offset = sizeof(struct ipv6_hdr) + 730 offsetof(struct tcp_hdr, dst_port), 731 }, 732 }; 733 734 int 735 softnic_pipeline_table_create(struct pmd_internals *softnic, 736 const char *pipeline_name, 737 struct softnic_table_params *params) 738 { 739 char name[NAME_MAX]; 740 struct rte_pipeline_table_params p; 741 742 union { 743 struct rte_table_acl_params acl; 744 struct rte_table_array_params array; 745 struct rte_table_hash_params hash; 746 struct rte_table_lpm_params lpm; 747 struct rte_table_lpm_ipv6_params lpm_ipv6; 748 } pp; 749 750 struct pipeline *pipeline; 751 struct softnic_table *table; 752 struct softnic_table_action_profile *ap; 753 struct rte_table_action *action; 754 uint32_t table_id; 755 int status; 756 757 memset(&p, 0, sizeof(p)); 758 memset(&pp, 0, sizeof(pp)); 759 760 /* Check input params */ 761 if (pipeline_name == NULL || 762 params == NULL) 763 return -1; 764 765 pipeline = softnic_pipeline_find(softnic, pipeline_name); 766 if (pipeline == NULL || 767 pipeline->n_tables >= RTE_PIPELINE_TABLE_MAX) 768 return -1; 769 770 ap = NULL; 771 if (strlen(params->action_profile_name)) { 772 ap = softnic_table_action_profile_find(softnic, 773 params->action_profile_name); 774 if (ap == NULL) 775 return -1; 776 } 777 778 snprintf(name, NAME_MAX, "%s_%s_table%u", 779 softnic->params.name, pipeline_name, pipeline->n_tables); 780 781 switch (params->match_type) { 782 case TABLE_ACL: 783 { 784 uint32_t ip_header_offset = params->match.acl.ip_header_offset - 785 (sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM); 786 uint32_t i; 787 788 if (params->match.acl.n_rules == 0) 789 return -1; 790 791 pp.acl.name = name; 792 pp.acl.n_rules = params->match.acl.n_rules; 793 if (params->match.acl.ip_version) { 794 memcpy(&pp.acl.field_format, 795 &table_acl_field_format_ipv4, 796 sizeof(table_acl_field_format_ipv4)); 797 pp.acl.n_rule_fields = 798 RTE_DIM(table_acl_field_format_ipv4); 799 } else { 800 memcpy(&pp.acl.field_format, 801 &table_acl_field_format_ipv6, 802 sizeof(table_acl_field_format_ipv6)); 803 pp.acl.n_rule_fields = 804 RTE_DIM(table_acl_field_format_ipv6); 805 } 806 807 for (i = 0; i < pp.acl.n_rule_fields; i++) 808 pp.acl.field_format[i].offset += ip_header_offset; 809 810 p.ops = &rte_table_acl_ops; 811 p.arg_create = &pp.acl; 812 break; 813 } 814 815 case TABLE_ARRAY: 816 { 817 if (params->match.array.n_keys == 0) 818 return -1; 819 820 pp.array.n_entries = params->match.array.n_keys; 821 pp.array.offset = params->match.array.key_offset; 822 823 p.ops = &rte_table_array_ops; 824 p.arg_create = &pp.array; 825 break; 826 } 827 828 case TABLE_HASH: 829 { 830 struct rte_table_ops *ops; 831 rte_table_hash_op_hash f_hash; 832 833 if (params->match.hash.n_keys == 0) 834 return -1; 835 836 switch (params->match.hash.key_size) { 837 case 8: 838 f_hash = rte_table_hash_crc_key8; 839 break; 840 case 16: 841 f_hash = rte_table_hash_crc_key16; 842 break; 843 case 24: 844 f_hash = rte_table_hash_crc_key24; 845 break; 846 case 32: 847 f_hash = rte_table_hash_crc_key32; 848 break; 849 case 40: 850 f_hash = rte_table_hash_crc_key40; 851 break; 852 case 48: 853 f_hash = rte_table_hash_crc_key48; 854 break; 855 case 56: 856 f_hash = rte_table_hash_crc_key56; 857 break; 858 case 64: 859 f_hash = rte_table_hash_crc_key64; 860 break; 861 default: 862 return -1; 863 } 864 865 pp.hash.name = name; 866 pp.hash.key_size = params->match.hash.key_size; 867 pp.hash.key_offset = params->match.hash.key_offset; 868 pp.hash.key_mask = params->match.hash.key_mask; 869 pp.hash.n_keys = params->match.hash.n_keys; 870 pp.hash.n_buckets = params->match.hash.n_buckets; 871 pp.hash.f_hash = f_hash; 872 pp.hash.seed = 0; 873 874 if (params->match.hash.extendable_bucket) 875 switch (params->match.hash.key_size) { 876 case 8: 877 ops = &rte_table_hash_key8_ext_ops; 878 break; 879 case 16: 880 ops = &rte_table_hash_key16_ext_ops; 881 break; 882 default: 883 ops = &rte_table_hash_ext_ops; 884 } 885 else 886 switch (params->match.hash.key_size) { 887 case 8: 888 ops = &rte_table_hash_key8_lru_ops; 889 break; 890 case 16: 891 ops = &rte_table_hash_key16_lru_ops; 892 break; 893 default: 894 ops = &rte_table_hash_lru_ops; 895 } 896 897 p.ops = ops; 898 p.arg_create = &pp.hash; 899 break; 900 } 901 902 case TABLE_LPM: 903 { 904 if (params->match.lpm.n_rules == 0) 905 return -1; 906 907 switch (params->match.lpm.key_size) { 908 case 4: 909 { 910 pp.lpm.name = name; 911 pp.lpm.n_rules = params->match.lpm.n_rules; 912 pp.lpm.number_tbl8s = TABLE_LPM_NUMBER_TBL8; 913 pp.lpm.flags = 0; 914 pp.lpm.entry_unique_size = p.action_data_size + 915 sizeof(struct rte_pipeline_table_entry); 916 pp.lpm.offset = params->match.lpm.key_offset; 917 918 p.ops = &rte_table_lpm_ops; 919 p.arg_create = &pp.lpm; 920 break; 921 } 922 923 case 16: 924 { 925 pp.lpm_ipv6.name = name; 926 pp.lpm_ipv6.n_rules = params->match.lpm.n_rules; 927 pp.lpm_ipv6.number_tbl8s = TABLE_LPM_NUMBER_TBL8; 928 pp.lpm_ipv6.entry_unique_size = p.action_data_size + 929 sizeof(struct rte_pipeline_table_entry); 930 pp.lpm_ipv6.offset = params->match.lpm.key_offset; 931 932 p.ops = &rte_table_lpm_ipv6_ops; 933 p.arg_create = &pp.lpm_ipv6; 934 break; 935 } 936 937 default: 938 return -1; 939 } 940 941 break; 942 } 943 944 case TABLE_STUB: 945 { 946 p.ops = &rte_table_stub_ops; 947 p.arg_create = NULL; 948 break; 949 } 950 951 default: 952 return -1; 953 } 954 955 /* Resource create */ 956 action = NULL; 957 p.f_action_hit = NULL; 958 p.f_action_miss = NULL; 959 p.arg_ah = NULL; 960 961 if (ap) { 962 action = rte_table_action_create(ap->ap, 963 softnic->params.cpu_id); 964 if (action == NULL) 965 return -1; 966 967 status = rte_table_action_table_params_get(action, 968 &p); 969 if (status || 970 ((p.action_data_size + 971 sizeof(struct rte_pipeline_table_entry)) > 972 TABLE_RULE_ACTION_SIZE_MAX)) { 973 rte_table_action_free(action); 974 return -1; 975 } 976 } 977 978 if (params->match_type == TABLE_LPM) { 979 if (params->match.lpm.key_size == 4) 980 pp.lpm.entry_unique_size = p.action_data_size + 981 sizeof(struct rte_pipeline_table_entry); 982 983 if (params->match.lpm.key_size == 16) 984 pp.lpm_ipv6.entry_unique_size = p.action_data_size + 985 sizeof(struct rte_pipeline_table_entry); 986 } 987 988 status = rte_pipeline_table_create(pipeline->p, 989 &p, 990 &table_id); 991 if (status) { 992 rte_table_action_free(action); 993 return -1; 994 } 995 996 /* Pipeline */ 997 table = &pipeline->table[pipeline->n_tables]; 998 memcpy(&table->params, params, sizeof(*params)); 999 table->ap = ap; 1000 table->a = action; 1001 TAILQ_INIT(&table->flows); 1002 TAILQ_INIT(&table->meter_profiles); 1003 memset(&table->dscp_table, 0, sizeof(table->dscp_table)); 1004 pipeline->n_tables++; 1005 1006 return 0; 1007 } 1008 1009 int 1010 softnic_pipeline_port_out_find(struct pmd_internals *softnic, 1011 const char *pipeline_name, 1012 const char *name, 1013 uint32_t *port_id) 1014 { 1015 struct pipeline *pipeline; 1016 uint32_t i; 1017 1018 if (softnic == NULL || 1019 pipeline_name == NULL || 1020 name == NULL || 1021 port_id == NULL) 1022 return -1; 1023 1024 pipeline = softnic_pipeline_find(softnic, pipeline_name); 1025 if (pipeline == NULL) 1026 return -1; 1027 1028 for (i = 0; i < pipeline->n_ports_out; i++) 1029 if (strcmp(pipeline->port_out[i].params.dev_name, name) == 0) { 1030 *port_id = i; 1031 return 0; 1032 } 1033 1034 return -1; 1035 } 1036 1037 struct softnic_table_meter_profile * 1038 softnic_pipeline_table_meter_profile_find(struct softnic_table *table, 1039 uint32_t meter_profile_id) 1040 { 1041 struct softnic_table_meter_profile *mp; 1042 1043 TAILQ_FOREACH(mp, &table->meter_profiles, node) 1044 if (mp->meter_profile_id == meter_profile_id) 1045 return mp; 1046 1047 return NULL; 1048 } 1049