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