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