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