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