1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2018 Intel Corporation 3 */ 4 5 #include <stdlib.h> 6 7 #include <rte_common.h> 8 #include <rte_cycles.h> 9 #include <rte_lcore.h> 10 #include <rte_ring.h> 11 12 #include <rte_table_acl.h> 13 #include <rte_table_array.h> 14 #include <rte_table_hash.h> 15 #include <rte_table_lpm.h> 16 #include <rte_table_lpm_ipv6.h> 17 18 #include "common.h" 19 #include "thread.h" 20 #include "pipeline.h" 21 22 #ifndef THREAD_PIPELINES_MAX 23 #define THREAD_PIPELINES_MAX 256 24 #endif 25 26 #ifndef THREAD_MSGQ_SIZE 27 #define THREAD_MSGQ_SIZE 64 28 #endif 29 30 #ifndef THREAD_TIMER_PERIOD_MS 31 #define THREAD_TIMER_PERIOD_MS 100 32 #endif 33 34 /** 35 * Master thead: data plane thread context 36 */ 37 struct thread { 38 struct rte_ring *msgq_req; 39 struct rte_ring *msgq_rsp; 40 41 uint32_t enabled; 42 }; 43 44 static struct thread thread[RTE_MAX_LCORE]; 45 46 /** 47 * Data plane threads: context 48 */ 49 struct table_data { 50 struct rte_table_action *a; 51 }; 52 53 struct pipeline_data { 54 struct rte_pipeline *p; 55 struct table_data table_data[RTE_PIPELINE_TABLE_MAX]; 56 uint32_t n_tables; 57 58 struct rte_ring *msgq_req; 59 struct rte_ring *msgq_rsp; 60 uint64_t timer_period; /* Measured in CPU cycles. */ 61 uint64_t time_next; 62 63 uint8_t buffer[TABLE_RULE_ACTION_SIZE_MAX]; 64 }; 65 66 struct thread_data { 67 struct rte_pipeline *p[THREAD_PIPELINES_MAX]; 68 uint32_t n_pipelines; 69 70 struct pipeline_data pipeline_data[THREAD_PIPELINES_MAX]; 71 struct rte_ring *msgq_req; 72 struct rte_ring *msgq_rsp; 73 uint64_t timer_period; /* Measured in CPU cycles. */ 74 uint64_t time_next; 75 uint64_t time_next_min; 76 } __rte_cache_aligned; 77 78 static struct thread_data thread_data[RTE_MAX_LCORE]; 79 80 /** 81 * Master thread: data plane thread init 82 */ 83 static void 84 thread_free(void) 85 { 86 uint32_t i; 87 88 for (i = 0; i < RTE_MAX_LCORE; i++) { 89 struct thread *t = &thread[i]; 90 91 if (!rte_lcore_is_enabled(i)) 92 continue; 93 94 /* MSGQs */ 95 if (t->msgq_req) 96 rte_ring_free(t->msgq_req); 97 98 if (t->msgq_rsp) 99 rte_ring_free(t->msgq_rsp); 100 } 101 } 102 103 int 104 thread_init(void) 105 { 106 uint32_t i; 107 108 RTE_LCORE_FOREACH_SLAVE(i) { 109 char name[NAME_MAX]; 110 struct rte_ring *msgq_req, *msgq_rsp; 111 struct thread *t = &thread[i]; 112 struct thread_data *t_data = &thread_data[i]; 113 uint32_t cpu_id = rte_lcore_to_socket_id(i); 114 115 /* MSGQs */ 116 snprintf(name, sizeof(name), "THREAD-%04x-MSGQ-REQ", i); 117 118 msgq_req = rte_ring_create(name, 119 THREAD_MSGQ_SIZE, 120 cpu_id, 121 RING_F_SP_ENQ | RING_F_SC_DEQ); 122 123 if (msgq_req == NULL) { 124 thread_free(); 125 return -1; 126 } 127 128 snprintf(name, sizeof(name), "THREAD-%04x-MSGQ-RSP", i); 129 130 msgq_rsp = rte_ring_create(name, 131 THREAD_MSGQ_SIZE, 132 cpu_id, 133 RING_F_SP_ENQ | RING_F_SC_DEQ); 134 135 if (msgq_rsp == NULL) { 136 thread_free(); 137 return -1; 138 } 139 140 /* Master thread records */ 141 t->msgq_req = msgq_req; 142 t->msgq_rsp = msgq_rsp; 143 t->enabled = 1; 144 145 /* Data plane thread records */ 146 t_data->n_pipelines = 0; 147 t_data->msgq_req = msgq_req; 148 t_data->msgq_rsp = msgq_rsp; 149 t_data->timer_period = 150 (rte_get_tsc_hz() * THREAD_TIMER_PERIOD_MS) / 1000; 151 t_data->time_next = rte_get_tsc_cycles() + t_data->timer_period; 152 t_data->time_next_min = t_data->time_next; 153 } 154 155 return 0; 156 } 157 158 static inline int 159 thread_is_running(uint32_t thread_id) 160 { 161 enum rte_lcore_state_t thread_state; 162 163 thread_state = rte_eal_get_lcore_state(thread_id); 164 return (thread_state == RUNNING) ? 1 : 0; 165 } 166 167 /** 168 * Pipeline is running when: 169 * (A) Pipeline is mapped to a data plane thread AND 170 * (B) Its data plane thread is in RUNNING state. 171 */ 172 static inline int 173 pipeline_is_running(struct pipeline *p) 174 { 175 if (p->enabled == 0) 176 return 0; 177 178 return thread_is_running(p->thread_id); 179 } 180 181 /** 182 * Master thread & data plane threads: message passing 183 */ 184 enum thread_req_type { 185 THREAD_REQ_PIPELINE_ENABLE = 0, 186 THREAD_REQ_PIPELINE_DISABLE, 187 THREAD_REQ_MAX 188 }; 189 190 struct thread_msg_req { 191 enum thread_req_type type; 192 193 union { 194 struct { 195 struct rte_pipeline *p; 196 struct { 197 struct rte_table_action *a; 198 } table[RTE_PIPELINE_TABLE_MAX]; 199 struct rte_ring *msgq_req; 200 struct rte_ring *msgq_rsp; 201 uint32_t timer_period_ms; 202 uint32_t n_tables; 203 } pipeline_enable; 204 205 struct { 206 struct rte_pipeline *p; 207 } pipeline_disable; 208 }; 209 }; 210 211 struct thread_msg_rsp { 212 int status; 213 }; 214 215 /** 216 * Master thread 217 */ 218 static struct thread_msg_req * 219 thread_msg_alloc(void) 220 { 221 size_t size = RTE_MAX(sizeof(struct thread_msg_req), 222 sizeof(struct thread_msg_rsp)); 223 224 return calloc(1, size); 225 } 226 227 static void 228 thread_msg_free(struct thread_msg_rsp *rsp) 229 { 230 free(rsp); 231 } 232 233 static struct thread_msg_rsp * 234 thread_msg_send_recv(uint32_t thread_id, 235 struct thread_msg_req *req) 236 { 237 struct thread *t = &thread[thread_id]; 238 struct rte_ring *msgq_req = t->msgq_req; 239 struct rte_ring *msgq_rsp = t->msgq_rsp; 240 struct thread_msg_rsp *rsp; 241 int status; 242 243 /* send */ 244 do { 245 status = rte_ring_sp_enqueue(msgq_req, req); 246 } while (status == -ENOBUFS); 247 248 /* recv */ 249 do { 250 status = rte_ring_sc_dequeue(msgq_rsp, (void **) &rsp); 251 } while (status != 0); 252 253 return rsp; 254 } 255 256 int 257 thread_pipeline_enable(uint32_t thread_id, 258 const char *pipeline_name) 259 { 260 struct pipeline *p = pipeline_find(pipeline_name); 261 struct thread *t; 262 struct thread_msg_req *req; 263 struct thread_msg_rsp *rsp; 264 uint32_t i; 265 int status; 266 267 /* Check input params */ 268 if ((thread_id >= RTE_MAX_LCORE) || 269 (p == NULL) || 270 (p->n_ports_in == 0) || 271 (p->n_ports_out == 0) || 272 (p->n_tables == 0)) 273 return -1; 274 275 t = &thread[thread_id]; 276 if ((t->enabled == 0) || 277 p->enabled) 278 return -1; 279 280 if (!thread_is_running(thread_id)) { 281 struct thread_data *td = &thread_data[thread_id]; 282 struct pipeline_data *tdp = &td->pipeline_data[td->n_pipelines]; 283 284 if (td->n_pipelines >= THREAD_PIPELINES_MAX) 285 return -1; 286 287 /* Data plane thread */ 288 td->p[td->n_pipelines] = p->p; 289 290 tdp->p = p->p; 291 for (i = 0; i < p->n_tables; i++) 292 tdp->table_data[i].a = p->table[i].a; 293 294 tdp->n_tables = p->n_tables; 295 296 tdp->msgq_req = p->msgq_req; 297 tdp->msgq_rsp = p->msgq_rsp; 298 tdp->timer_period = (rte_get_tsc_hz() * p->timer_period_ms) / 1000; 299 tdp->time_next = rte_get_tsc_cycles() + tdp->timer_period; 300 301 td->n_pipelines++; 302 303 /* Pipeline */ 304 p->thread_id = thread_id; 305 p->enabled = 1; 306 307 return 0; 308 } 309 310 /* Allocate request */ 311 req = thread_msg_alloc(); 312 if (req == NULL) 313 return -1; 314 315 /* Write request */ 316 req->type = THREAD_REQ_PIPELINE_ENABLE; 317 req->pipeline_enable.p = p->p; 318 for (i = 0; i < p->n_tables; i++) 319 req->pipeline_enable.table[i].a = 320 p->table[i].a; 321 req->pipeline_enable.msgq_req = p->msgq_req; 322 req->pipeline_enable.msgq_rsp = p->msgq_rsp; 323 req->pipeline_enable.timer_period_ms = p->timer_period_ms; 324 req->pipeline_enable.n_tables = p->n_tables; 325 326 /* Send request and wait for response */ 327 rsp = thread_msg_send_recv(thread_id, req); 328 if (rsp == NULL) 329 return -1; 330 331 /* Read response */ 332 status = rsp->status; 333 334 /* Free response */ 335 thread_msg_free(rsp); 336 337 /* Request completion */ 338 if (status) 339 return status; 340 341 p->thread_id = thread_id; 342 p->enabled = 1; 343 344 return 0; 345 } 346 347 int 348 thread_pipeline_disable(uint32_t thread_id, 349 const char *pipeline_name) 350 { 351 struct pipeline *p = pipeline_find(pipeline_name); 352 struct thread *t; 353 struct thread_msg_req *req; 354 struct thread_msg_rsp *rsp; 355 int status; 356 357 /* Check input params */ 358 if ((thread_id >= RTE_MAX_LCORE) || 359 (p == NULL)) 360 return -1; 361 362 t = &thread[thread_id]; 363 if (t->enabled == 0) 364 return -1; 365 366 if (p->enabled == 0) 367 return 0; 368 369 if (p->thread_id != thread_id) 370 return -1; 371 372 if (!thread_is_running(thread_id)) { 373 struct thread_data *td = &thread_data[thread_id]; 374 uint32_t i; 375 376 for (i = 0; i < td->n_pipelines; i++) { 377 struct pipeline_data *tdp = &td->pipeline_data[i]; 378 379 if (tdp->p != p->p) 380 continue; 381 382 /* Data plane thread */ 383 if (i < td->n_pipelines - 1) { 384 struct rte_pipeline *pipeline_last = 385 td->p[td->n_pipelines - 1]; 386 struct pipeline_data *tdp_last = 387 &td->pipeline_data[td->n_pipelines - 1]; 388 389 td->p[i] = pipeline_last; 390 memcpy(tdp, tdp_last, sizeof(*tdp)); 391 } 392 393 td->n_pipelines--; 394 395 /* Pipeline */ 396 p->enabled = 0; 397 398 break; 399 } 400 401 return 0; 402 } 403 404 /* Allocate request */ 405 req = thread_msg_alloc(); 406 if (req == NULL) 407 return -1; 408 409 /* Write request */ 410 req->type = THREAD_REQ_PIPELINE_DISABLE; 411 req->pipeline_disable.p = p->p; 412 413 /* Send request and wait for response */ 414 rsp = thread_msg_send_recv(thread_id, req); 415 if (rsp == NULL) 416 return -1; 417 418 /* Read response */ 419 status = rsp->status; 420 421 /* Free response */ 422 thread_msg_free(rsp); 423 424 /* Request completion */ 425 if (status) 426 return status; 427 428 p->enabled = 0; 429 430 return 0; 431 } 432 433 /** 434 * Data plane threads: message handling 435 */ 436 static inline struct thread_msg_req * 437 thread_msg_recv(struct rte_ring *msgq_req) 438 { 439 struct thread_msg_req *req; 440 441 int status = rte_ring_sc_dequeue(msgq_req, (void **) &req); 442 443 if (status != 0) 444 return NULL; 445 446 return req; 447 } 448 449 static inline void 450 thread_msg_send(struct rte_ring *msgq_rsp, 451 struct thread_msg_rsp *rsp) 452 { 453 int status; 454 455 do { 456 status = rte_ring_sp_enqueue(msgq_rsp, rsp); 457 } while (status == -ENOBUFS); 458 } 459 460 static struct thread_msg_rsp * 461 thread_msg_handle_pipeline_enable(struct thread_data *t, 462 struct thread_msg_req *req) 463 { 464 struct thread_msg_rsp *rsp = (struct thread_msg_rsp *) req; 465 struct pipeline_data *p = &t->pipeline_data[t->n_pipelines]; 466 uint32_t i; 467 468 /* Request */ 469 if (t->n_pipelines >= THREAD_PIPELINES_MAX) { 470 rsp->status = -1; 471 return rsp; 472 } 473 474 t->p[t->n_pipelines] = req->pipeline_enable.p; 475 476 p->p = req->pipeline_enable.p; 477 for (i = 0; i < req->pipeline_enable.n_tables; i++) 478 p->table_data[i].a = 479 req->pipeline_enable.table[i].a; 480 481 p->n_tables = req->pipeline_enable.n_tables; 482 483 p->msgq_req = req->pipeline_enable.msgq_req; 484 p->msgq_rsp = req->pipeline_enable.msgq_rsp; 485 p->timer_period = 486 (rte_get_tsc_hz() * req->pipeline_enable.timer_period_ms) / 1000; 487 p->time_next = rte_get_tsc_cycles() + p->timer_period; 488 489 t->n_pipelines++; 490 491 /* Response */ 492 rsp->status = 0; 493 return rsp; 494 } 495 496 static struct thread_msg_rsp * 497 thread_msg_handle_pipeline_disable(struct thread_data *t, 498 struct thread_msg_req *req) 499 { 500 struct thread_msg_rsp *rsp = (struct thread_msg_rsp *) req; 501 uint32_t n_pipelines = t->n_pipelines; 502 struct rte_pipeline *pipeline = req->pipeline_disable.p; 503 uint32_t i; 504 505 /* find pipeline */ 506 for (i = 0; i < n_pipelines; i++) { 507 struct pipeline_data *p = &t->pipeline_data[i]; 508 509 if (p->p != pipeline) 510 continue; 511 512 if (i < n_pipelines - 1) { 513 struct rte_pipeline *pipeline_last = 514 t->p[n_pipelines - 1]; 515 struct pipeline_data *p_last = 516 &t->pipeline_data[n_pipelines - 1]; 517 518 t->p[i] = pipeline_last; 519 memcpy(p, p_last, sizeof(*p)); 520 } 521 522 t->n_pipelines--; 523 524 rsp->status = 0; 525 return rsp; 526 } 527 528 /* should not get here */ 529 rsp->status = 0; 530 return rsp; 531 } 532 533 static void 534 thread_msg_handle(struct thread_data *t) 535 { 536 for ( ; ; ) { 537 struct thread_msg_req *req; 538 struct thread_msg_rsp *rsp; 539 540 req = thread_msg_recv(t->msgq_req); 541 if (req == NULL) 542 break; 543 544 switch (req->type) { 545 case THREAD_REQ_PIPELINE_ENABLE: 546 rsp = thread_msg_handle_pipeline_enable(t, req); 547 break; 548 549 case THREAD_REQ_PIPELINE_DISABLE: 550 rsp = thread_msg_handle_pipeline_disable(t, req); 551 break; 552 553 default: 554 rsp = (struct thread_msg_rsp *) req; 555 rsp->status = -1; 556 } 557 558 thread_msg_send(t->msgq_rsp, rsp); 559 } 560 } 561 562 /** 563 * Master thread & data plane threads: message passing 564 */ 565 enum pipeline_req_type { 566 /* Port IN */ 567 PIPELINE_REQ_PORT_IN_STATS_READ, 568 PIPELINE_REQ_PORT_IN_ENABLE, 569 PIPELINE_REQ_PORT_IN_DISABLE, 570 571 /* Port OUT */ 572 PIPELINE_REQ_PORT_OUT_STATS_READ, 573 574 /* Table */ 575 PIPELINE_REQ_TABLE_STATS_READ, 576 PIPELINE_REQ_TABLE_RULE_ADD, 577 PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT, 578 PIPELINE_REQ_TABLE_RULE_ADD_BULK, 579 PIPELINE_REQ_TABLE_RULE_DELETE, 580 PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT, 581 PIPELINE_REQ_TABLE_RULE_STATS_READ, 582 PIPELINE_REQ_TABLE_MTR_PROFILE_ADD, 583 PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE, 584 PIPELINE_REQ_TABLE_RULE_MTR_READ, 585 PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE, 586 PIPELINE_REQ_TABLE_RULE_TTL_READ, 587 PIPELINE_REQ_TABLE_RULE_TIME_READ, 588 PIPELINE_REQ_MAX 589 }; 590 591 struct pipeline_msg_req_port_in_stats_read { 592 int clear; 593 }; 594 595 struct pipeline_msg_req_port_out_stats_read { 596 int clear; 597 }; 598 599 struct pipeline_msg_req_table_stats_read { 600 int clear; 601 }; 602 603 struct pipeline_msg_req_table_rule_add { 604 struct table_rule_match match; 605 struct table_rule_action action; 606 }; 607 608 struct pipeline_msg_req_table_rule_add_default { 609 struct table_rule_action action; 610 }; 611 612 struct pipeline_msg_req_table_rule_add_bulk { 613 struct table_rule_list *list; 614 int bulk; 615 }; 616 617 struct pipeline_msg_req_table_rule_delete { 618 struct table_rule_match match; 619 }; 620 621 struct pipeline_msg_req_table_rule_stats_read { 622 void *data; 623 int clear; 624 }; 625 626 struct pipeline_msg_req_table_mtr_profile_add { 627 uint32_t meter_profile_id; 628 struct rte_table_action_meter_profile profile; 629 }; 630 631 struct pipeline_msg_req_table_mtr_profile_delete { 632 uint32_t meter_profile_id; 633 }; 634 635 struct pipeline_msg_req_table_rule_mtr_read { 636 void *data; 637 uint32_t tc_mask; 638 int clear; 639 }; 640 641 struct pipeline_msg_req_table_dscp_table_update { 642 uint64_t dscp_mask; 643 struct rte_table_action_dscp_table dscp_table; 644 }; 645 646 struct pipeline_msg_req_table_rule_ttl_read { 647 void *data; 648 int clear; 649 }; 650 651 struct pipeline_msg_req_table_rule_time_read { 652 void *data; 653 }; 654 655 struct pipeline_msg_req { 656 enum pipeline_req_type type; 657 uint32_t id; /* Port IN, port OUT or table ID */ 658 659 RTE_STD_C11 660 union { 661 struct pipeline_msg_req_port_in_stats_read port_in_stats_read; 662 struct pipeline_msg_req_port_out_stats_read port_out_stats_read; 663 struct pipeline_msg_req_table_stats_read table_stats_read; 664 struct pipeline_msg_req_table_rule_add table_rule_add; 665 struct pipeline_msg_req_table_rule_add_default table_rule_add_default; 666 struct pipeline_msg_req_table_rule_add_bulk table_rule_add_bulk; 667 struct pipeline_msg_req_table_rule_delete table_rule_delete; 668 struct pipeline_msg_req_table_rule_stats_read table_rule_stats_read; 669 struct pipeline_msg_req_table_mtr_profile_add table_mtr_profile_add; 670 struct pipeline_msg_req_table_mtr_profile_delete table_mtr_profile_delete; 671 struct pipeline_msg_req_table_rule_mtr_read table_rule_mtr_read; 672 struct pipeline_msg_req_table_dscp_table_update table_dscp_table_update; 673 struct pipeline_msg_req_table_rule_ttl_read table_rule_ttl_read; 674 struct pipeline_msg_req_table_rule_time_read table_rule_time_read; 675 }; 676 }; 677 678 struct pipeline_msg_rsp_port_in_stats_read { 679 struct rte_pipeline_port_in_stats stats; 680 }; 681 682 struct pipeline_msg_rsp_port_out_stats_read { 683 struct rte_pipeline_port_out_stats stats; 684 }; 685 686 struct pipeline_msg_rsp_table_stats_read { 687 struct rte_pipeline_table_stats stats; 688 }; 689 690 struct pipeline_msg_rsp_table_rule_add { 691 void *data; 692 }; 693 694 struct pipeline_msg_rsp_table_rule_add_default { 695 void *data; 696 }; 697 698 struct pipeline_msg_rsp_table_rule_add_bulk { 699 uint32_t n_rules; 700 }; 701 702 struct pipeline_msg_rsp_table_rule_stats_read { 703 struct rte_table_action_stats_counters stats; 704 }; 705 706 struct pipeline_msg_rsp_table_rule_mtr_read { 707 struct rte_table_action_mtr_counters stats; 708 }; 709 710 struct pipeline_msg_rsp_table_rule_ttl_read { 711 struct rte_table_action_ttl_counters stats; 712 }; 713 714 struct pipeline_msg_rsp_table_rule_time_read { 715 uint64_t timestamp; 716 }; 717 718 struct pipeline_msg_rsp { 719 int status; 720 721 RTE_STD_C11 722 union { 723 struct pipeline_msg_rsp_port_in_stats_read port_in_stats_read; 724 struct pipeline_msg_rsp_port_out_stats_read port_out_stats_read; 725 struct pipeline_msg_rsp_table_stats_read table_stats_read; 726 struct pipeline_msg_rsp_table_rule_add table_rule_add; 727 struct pipeline_msg_rsp_table_rule_add_default table_rule_add_default; 728 struct pipeline_msg_rsp_table_rule_add_bulk table_rule_add_bulk; 729 struct pipeline_msg_rsp_table_rule_stats_read table_rule_stats_read; 730 struct pipeline_msg_rsp_table_rule_mtr_read table_rule_mtr_read; 731 struct pipeline_msg_rsp_table_rule_ttl_read table_rule_ttl_read; 732 struct pipeline_msg_rsp_table_rule_time_read table_rule_time_read; 733 }; 734 }; 735 736 /** 737 * Master thread 738 */ 739 static struct pipeline_msg_req * 740 pipeline_msg_alloc(void) 741 { 742 size_t size = RTE_MAX(sizeof(struct pipeline_msg_req), 743 sizeof(struct pipeline_msg_rsp)); 744 745 return calloc(1, size); 746 } 747 748 static void 749 pipeline_msg_free(struct pipeline_msg_rsp *rsp) 750 { 751 free(rsp); 752 } 753 754 static struct pipeline_msg_rsp * 755 pipeline_msg_send_recv(struct pipeline *p, 756 struct pipeline_msg_req *req) 757 { 758 struct rte_ring *msgq_req = p->msgq_req; 759 struct rte_ring *msgq_rsp = p->msgq_rsp; 760 struct pipeline_msg_rsp *rsp; 761 int status; 762 763 /* send */ 764 do { 765 status = rte_ring_sp_enqueue(msgq_req, req); 766 } while (status == -ENOBUFS); 767 768 /* recv */ 769 do { 770 status = rte_ring_sc_dequeue(msgq_rsp, (void **) &rsp); 771 } while (status != 0); 772 773 return rsp; 774 } 775 776 int 777 pipeline_port_in_stats_read(const char *pipeline_name, 778 uint32_t port_id, 779 struct rte_pipeline_port_in_stats *stats, 780 int clear) 781 { 782 struct pipeline *p; 783 struct pipeline_msg_req *req; 784 struct pipeline_msg_rsp *rsp; 785 int status; 786 787 /* Check input params */ 788 if ((pipeline_name == NULL) || 789 (stats == NULL)) 790 return -1; 791 792 p = pipeline_find(pipeline_name); 793 if ((p == NULL) || 794 (port_id >= p->n_ports_in)) 795 return -1; 796 797 if (!pipeline_is_running(p)) { 798 status = rte_pipeline_port_in_stats_read(p->p, 799 port_id, 800 stats, 801 clear); 802 803 return status; 804 } 805 806 /* Allocate request */ 807 req = pipeline_msg_alloc(); 808 if (req == NULL) 809 return -1; 810 811 /* Write request */ 812 req->type = PIPELINE_REQ_PORT_IN_STATS_READ; 813 req->id = port_id; 814 req->port_in_stats_read.clear = clear; 815 816 /* Send request and wait for response */ 817 rsp = pipeline_msg_send_recv(p, req); 818 if (rsp == NULL) 819 return -1; 820 821 /* Read response */ 822 status = rsp->status; 823 if (status == 0) 824 memcpy(stats, &rsp->port_in_stats_read.stats, sizeof(*stats)); 825 826 /* Free response */ 827 pipeline_msg_free(rsp); 828 829 return status; 830 } 831 832 int 833 pipeline_port_in_enable(const char *pipeline_name, 834 uint32_t port_id) 835 { 836 struct pipeline *p; 837 struct pipeline_msg_req *req; 838 struct pipeline_msg_rsp *rsp; 839 int status; 840 841 /* Check input params */ 842 if (pipeline_name == NULL) 843 return -1; 844 845 p = pipeline_find(pipeline_name); 846 if ((p == NULL) || 847 (port_id >= p->n_ports_in)) 848 return -1; 849 850 if (!pipeline_is_running(p)) { 851 status = rte_pipeline_port_in_enable(p->p, port_id); 852 return status; 853 } 854 855 /* Allocate request */ 856 req = pipeline_msg_alloc(); 857 if (req == NULL) 858 return -1; 859 860 /* Write request */ 861 req->type = PIPELINE_REQ_PORT_IN_ENABLE; 862 req->id = port_id; 863 864 /* Send request and wait for response */ 865 rsp = pipeline_msg_send_recv(p, req); 866 if (rsp == NULL) 867 return -1; 868 869 /* Read response */ 870 status = rsp->status; 871 872 /* Free response */ 873 pipeline_msg_free(rsp); 874 875 return status; 876 } 877 878 int 879 pipeline_port_in_disable(const char *pipeline_name, 880 uint32_t port_id) 881 { 882 struct pipeline *p; 883 struct pipeline_msg_req *req; 884 struct pipeline_msg_rsp *rsp; 885 int status; 886 887 /* Check input params */ 888 if (pipeline_name == NULL) 889 return -1; 890 891 p = pipeline_find(pipeline_name); 892 if ((p == NULL) || 893 (port_id >= p->n_ports_in)) 894 return -1; 895 896 if (!pipeline_is_running(p)) { 897 status = rte_pipeline_port_in_disable(p->p, port_id); 898 return status; 899 } 900 901 /* Allocate request */ 902 req = pipeline_msg_alloc(); 903 if (req == NULL) 904 return -1; 905 906 /* Write request */ 907 req->type = PIPELINE_REQ_PORT_IN_DISABLE; 908 req->id = port_id; 909 910 /* Send request and wait for response */ 911 rsp = pipeline_msg_send_recv(p, req); 912 if (rsp == NULL) 913 return -1; 914 915 /* Read response */ 916 status = rsp->status; 917 918 /* Free response */ 919 pipeline_msg_free(rsp); 920 921 return status; 922 } 923 924 int 925 pipeline_port_out_stats_read(const char *pipeline_name, 926 uint32_t port_id, 927 struct rte_pipeline_port_out_stats *stats, 928 int clear) 929 { 930 struct pipeline *p; 931 struct pipeline_msg_req *req; 932 struct pipeline_msg_rsp *rsp; 933 int status; 934 935 /* Check input params */ 936 if ((pipeline_name == NULL) || 937 (stats == NULL)) 938 return -1; 939 940 p = pipeline_find(pipeline_name); 941 if ((p == NULL) || 942 (port_id >= p->n_ports_out)) 943 return -1; 944 945 if (!pipeline_is_running(p)) { 946 status = rte_pipeline_port_out_stats_read(p->p, 947 port_id, 948 stats, 949 clear); 950 951 return status; 952 } 953 954 /* Allocate request */ 955 req = pipeline_msg_alloc(); 956 if (req == NULL) 957 return -1; 958 959 /* Write request */ 960 req->type = PIPELINE_REQ_PORT_OUT_STATS_READ; 961 req->id = port_id; 962 req->port_out_stats_read.clear = clear; 963 964 /* Send request and wait for response */ 965 rsp = pipeline_msg_send_recv(p, req); 966 if (rsp == NULL) 967 return -1; 968 969 /* Read response */ 970 status = rsp->status; 971 if (status == 0) 972 memcpy(stats, &rsp->port_out_stats_read.stats, sizeof(*stats)); 973 974 /* Free response */ 975 pipeline_msg_free(rsp); 976 977 return status; 978 } 979 980 int 981 pipeline_table_stats_read(const char *pipeline_name, 982 uint32_t table_id, 983 struct rte_pipeline_table_stats *stats, 984 int clear) 985 { 986 struct pipeline *p; 987 struct pipeline_msg_req *req; 988 struct pipeline_msg_rsp *rsp; 989 int status; 990 991 /* Check input params */ 992 if ((pipeline_name == NULL) || 993 (stats == NULL)) 994 return -1; 995 996 p = pipeline_find(pipeline_name); 997 if ((p == NULL) || 998 (table_id >= p->n_tables)) 999 return -1; 1000 1001 if (!pipeline_is_running(p)) { 1002 status = rte_pipeline_table_stats_read(p->p, 1003 table_id, 1004 stats, 1005 clear); 1006 1007 return status; 1008 } 1009 1010 /* Allocate request */ 1011 req = pipeline_msg_alloc(); 1012 if (req == NULL) 1013 return -1; 1014 1015 /* Write request */ 1016 req->type = PIPELINE_REQ_TABLE_STATS_READ; 1017 req->id = table_id; 1018 req->table_stats_read.clear = clear; 1019 1020 /* Send request and wait for response */ 1021 rsp = pipeline_msg_send_recv(p, req); 1022 if (rsp == NULL) 1023 return -1; 1024 1025 /* Read response */ 1026 status = rsp->status; 1027 if (status == 0) 1028 memcpy(stats, &rsp->table_stats_read.stats, sizeof(*stats)); 1029 1030 /* Free response */ 1031 pipeline_msg_free(rsp); 1032 1033 return status; 1034 } 1035 1036 static int 1037 match_check(struct table_rule_match *match, 1038 struct pipeline *p, 1039 uint32_t table_id) 1040 { 1041 struct table *table; 1042 1043 if ((match == NULL) || 1044 (p == NULL) || 1045 (table_id >= p->n_tables)) 1046 return -1; 1047 1048 table = &p->table[table_id]; 1049 if (match->match_type != table->params.match_type) 1050 return -1; 1051 1052 switch (match->match_type) { 1053 case TABLE_ACL: 1054 { 1055 struct table_acl_params *t = &table->params.match.acl; 1056 struct table_rule_match_acl *r = &match->match.acl; 1057 1058 if ((r->ip_version && (t->ip_version == 0)) || 1059 ((r->ip_version == 0) && t->ip_version)) 1060 return -1; 1061 1062 if (r->ip_version) { 1063 if ((r->sa_depth > 32) || 1064 (r->da_depth > 32)) 1065 return -1; 1066 } else { 1067 if ((r->sa_depth > 128) || 1068 (r->da_depth > 128)) 1069 return -1; 1070 } 1071 return 0; 1072 } 1073 1074 case TABLE_ARRAY: 1075 return 0; 1076 1077 case TABLE_HASH: 1078 return 0; 1079 1080 case TABLE_LPM: 1081 { 1082 struct table_lpm_params *t = &table->params.match.lpm; 1083 struct table_rule_match_lpm *r = &match->match.lpm; 1084 1085 if ((r->ip_version && (t->key_size != 4)) || 1086 ((r->ip_version == 0) && (t->key_size != 16))) 1087 return -1; 1088 1089 if (r->ip_version) { 1090 if (r->depth > 32) 1091 return -1; 1092 } else { 1093 if (r->depth > 128) 1094 return -1; 1095 } 1096 return 0; 1097 } 1098 1099 case TABLE_STUB: 1100 return -1; 1101 1102 default: 1103 return -1; 1104 } 1105 } 1106 1107 static int 1108 action_check(struct table_rule_action *action, 1109 struct pipeline *p, 1110 uint32_t table_id) 1111 { 1112 struct table_action_profile *ap; 1113 1114 if ((action == NULL) || 1115 (p == NULL) || 1116 (table_id >= p->n_tables)) 1117 return -1; 1118 1119 ap = p->table[table_id].ap; 1120 if (action->action_mask != ap->params.action_mask) 1121 return -1; 1122 1123 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) { 1124 if ((action->fwd.action == RTE_PIPELINE_ACTION_PORT) && 1125 (action->fwd.id >= p->n_ports_out)) 1126 return -1; 1127 1128 if ((action->fwd.action == RTE_PIPELINE_ACTION_TABLE) && 1129 (action->fwd.id >= p->n_tables)) 1130 return -1; 1131 } 1132 1133 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) { 1134 uint32_t tc_mask0 = (1 << ap->params.mtr.n_tc) - 1; 1135 uint32_t tc_mask1 = action->mtr.tc_mask; 1136 1137 if (tc_mask1 != tc_mask0) 1138 return -1; 1139 } 1140 1141 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) { 1142 uint32_t n_subports_per_port = 1143 ap->params.tm.n_subports_per_port; 1144 uint32_t n_pipes_per_subport = 1145 ap->params.tm.n_pipes_per_subport; 1146 uint32_t subport_id = action->tm.subport_id; 1147 uint32_t pipe_id = action->tm.pipe_id; 1148 1149 if ((subport_id >= n_subports_per_port) || 1150 (pipe_id >= n_pipes_per_subport)) 1151 return -1; 1152 } 1153 1154 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) { 1155 uint64_t encap_mask = ap->params.encap.encap_mask; 1156 enum rte_table_action_encap_type type = action->encap.type; 1157 1158 if ((encap_mask & (1LLU << type)) == 0) 1159 return -1; 1160 } 1161 1162 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) { 1163 int ip_version0 = ap->params.common.ip_version; 1164 int ip_version1 = action->nat.ip_version; 1165 1166 if ((ip_version1 && (ip_version0 == 0)) || 1167 ((ip_version1 == 0) && ip_version0)) 1168 return -1; 1169 } 1170 1171 return 0; 1172 } 1173 1174 static int 1175 action_default_check(struct table_rule_action *action, 1176 struct pipeline *p, 1177 uint32_t table_id) 1178 { 1179 if ((action == NULL) || 1180 (action->action_mask != (1LLU << RTE_TABLE_ACTION_FWD)) || 1181 (p == NULL) || 1182 (table_id >= p->n_tables)) 1183 return -1; 1184 1185 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) { 1186 if ((action->fwd.action == RTE_PIPELINE_ACTION_PORT) && 1187 (action->fwd.id >= p->n_ports_out)) 1188 return -1; 1189 1190 if ((action->fwd.action == RTE_PIPELINE_ACTION_TABLE) && 1191 (action->fwd.id >= p->n_tables)) 1192 return -1; 1193 } 1194 1195 return 0; 1196 } 1197 1198 union table_rule_match_low_level { 1199 struct rte_table_acl_rule_add_params acl_add; 1200 struct rte_table_acl_rule_delete_params acl_delete; 1201 struct rte_table_array_key array; 1202 uint8_t hash[TABLE_RULE_MATCH_SIZE_MAX]; 1203 struct rte_table_lpm_key lpm_ipv4; 1204 struct rte_table_lpm_ipv6_key lpm_ipv6; 1205 }; 1206 1207 static int 1208 match_convert(struct table_rule_match *mh, 1209 union table_rule_match_low_level *ml, 1210 int add); 1211 1212 static int 1213 action_convert(struct rte_table_action *a, 1214 struct table_rule_action *action, 1215 struct rte_pipeline_table_entry *data); 1216 1217 struct table_ll { 1218 struct rte_pipeline *p; 1219 int table_id; 1220 struct rte_table_action *a; 1221 int bulk_supported; 1222 }; 1223 1224 static int 1225 table_rule_add_bulk_ll(struct table_ll *table, 1226 struct table_rule_list *list, 1227 uint32_t *n_rules) 1228 { 1229 union table_rule_match_low_level *match_ll = NULL; 1230 uint8_t *action_ll = NULL; 1231 void **match_ll_ptr = NULL; 1232 struct rte_pipeline_table_entry **action_ll_ptr = NULL; 1233 struct rte_pipeline_table_entry **entries_ptr = NULL; 1234 int *found = NULL; 1235 struct table_rule *rule; 1236 uint32_t n, i; 1237 int status = 0; 1238 1239 n = 0; 1240 TAILQ_FOREACH(rule, list, node) 1241 n++; 1242 1243 /* Memory allocation */ 1244 match_ll = calloc(n, sizeof(union table_rule_match_low_level)); 1245 action_ll = calloc(n, TABLE_RULE_ACTION_SIZE_MAX); 1246 1247 match_ll_ptr = calloc(n, sizeof(void *)); 1248 action_ll_ptr = calloc(n, sizeof(struct rte_pipeline_table_entry *)); 1249 1250 entries_ptr = calloc(n, sizeof(struct rte_pipeline_table_entry *)); 1251 found = calloc(n, sizeof(int)); 1252 1253 if (match_ll == NULL || 1254 action_ll == NULL || 1255 match_ll_ptr == NULL || 1256 action_ll_ptr == NULL || 1257 entries_ptr == NULL || 1258 found == NULL) { 1259 status = -ENOMEM; 1260 goto table_rule_add_bulk_ll_free; 1261 } 1262 1263 /* Init */ 1264 for (i = 0; i < n; i++) { 1265 match_ll_ptr[i] = (void *)&match_ll[i]; 1266 action_ll_ptr[i] = (struct rte_pipeline_table_entry *) 1267 &action_ll[i * TABLE_RULE_ACTION_SIZE_MAX]; 1268 } 1269 1270 /* Rule (match, action) conversion */ 1271 i = 0; 1272 TAILQ_FOREACH(rule, list, node) { 1273 status = match_convert(&rule->match, match_ll_ptr[i], 1); 1274 if (status) 1275 goto table_rule_add_bulk_ll_free; 1276 1277 status = action_convert(table->a, &rule->action, action_ll_ptr[i]); 1278 if (status) 1279 goto table_rule_add_bulk_ll_free; 1280 1281 i++; 1282 } 1283 1284 /* Add rule (match, action) to table */ 1285 if (table->bulk_supported) { 1286 status = rte_pipeline_table_entry_add_bulk(table->p, 1287 table->table_id, 1288 match_ll_ptr, 1289 action_ll_ptr, 1290 n, 1291 found, 1292 entries_ptr); 1293 if (status) 1294 goto table_rule_add_bulk_ll_free; 1295 } else 1296 for (i = 0; i < n; i++) { 1297 status = rte_pipeline_table_entry_add(table->p, 1298 table->table_id, 1299 match_ll_ptr[i], 1300 action_ll_ptr[i], 1301 &found[i], 1302 &entries_ptr[i]); 1303 if (status) { 1304 if (i == 0) 1305 goto table_rule_add_bulk_ll_free; 1306 1307 /* No roll-back. */ 1308 status = 0; 1309 n = i; 1310 break; 1311 } 1312 } 1313 1314 /* Write back to the rule list. */ 1315 i = 0; 1316 TAILQ_FOREACH(rule, list, node) { 1317 if (i >= n) 1318 break; 1319 1320 rule->data = entries_ptr[i]; 1321 1322 i++; 1323 } 1324 1325 *n_rules = n; 1326 1327 /* Free */ 1328 table_rule_add_bulk_ll_free: 1329 free(found); 1330 free(entries_ptr); 1331 free(action_ll_ptr); 1332 free(match_ll_ptr); 1333 free(action_ll); 1334 free(match_ll); 1335 1336 return status; 1337 } 1338 1339 int 1340 pipeline_table_rule_add(const char *pipeline_name, 1341 uint32_t table_id, 1342 struct table_rule_match *match, 1343 struct table_rule_action *action) 1344 { 1345 struct pipeline *p; 1346 struct table *table; 1347 struct pipeline_msg_req *req; 1348 struct pipeline_msg_rsp *rsp; 1349 struct table_rule *rule; 1350 int status; 1351 1352 /* Check input params */ 1353 if ((pipeline_name == NULL) || 1354 (match == NULL) || 1355 (action == NULL)) 1356 return -1; 1357 1358 p = pipeline_find(pipeline_name); 1359 if ((p == NULL) || 1360 (table_id >= p->n_tables) || 1361 match_check(match, p, table_id) || 1362 action_check(action, p, table_id)) 1363 return -1; 1364 1365 table = &p->table[table_id]; 1366 1367 rule = calloc(1, sizeof(struct table_rule)); 1368 if (rule == NULL) 1369 return -1; 1370 1371 memcpy(&rule->match, match, sizeof(*match)); 1372 memcpy(&rule->action, action, sizeof(*action)); 1373 1374 if (!pipeline_is_running(p)) { 1375 union table_rule_match_low_level match_ll; 1376 struct rte_pipeline_table_entry *data_in, *data_out; 1377 int key_found; 1378 uint8_t *buffer; 1379 1380 buffer = calloc(TABLE_RULE_ACTION_SIZE_MAX, sizeof(uint8_t)); 1381 if (buffer == NULL) { 1382 free(rule); 1383 return -1; 1384 } 1385 1386 /* Table match-action rule conversion */ 1387 data_in = (struct rte_pipeline_table_entry *)buffer; 1388 1389 status = match_convert(match, &match_ll, 1); 1390 if (status) { 1391 free(buffer); 1392 free(rule); 1393 return -1; 1394 } 1395 1396 status = action_convert(table->a, action, data_in); 1397 if (status) { 1398 free(buffer); 1399 free(rule); 1400 return -1; 1401 } 1402 1403 /* Add rule (match, action) to table */ 1404 status = rte_pipeline_table_entry_add(p->p, 1405 table_id, 1406 &match_ll, 1407 data_in, 1408 &key_found, 1409 &data_out); 1410 if (status) { 1411 free(buffer); 1412 free(rule); 1413 return -1; 1414 } 1415 1416 /* Write Response */ 1417 rule->data = data_out; 1418 table_rule_add(table, rule); 1419 1420 free(buffer); 1421 return 0; 1422 } 1423 1424 /* Allocate request */ 1425 req = pipeline_msg_alloc(); 1426 if (req == NULL) { 1427 free(rule); 1428 return -1; 1429 } 1430 1431 /* Write request */ 1432 req->type = PIPELINE_REQ_TABLE_RULE_ADD; 1433 req->id = table_id; 1434 memcpy(&req->table_rule_add.match, match, sizeof(*match)); 1435 memcpy(&req->table_rule_add.action, action, sizeof(*action)); 1436 1437 /* Send request and wait for response */ 1438 rsp = pipeline_msg_send_recv(p, req); 1439 if (rsp == NULL) { 1440 free(rule); 1441 return -1; 1442 } 1443 1444 /* Read response */ 1445 status = rsp->status; 1446 if (status == 0) { 1447 rule->data = rsp->table_rule_add.data; 1448 table_rule_add(table, rule); 1449 } else 1450 free(rule); 1451 1452 /* Free response */ 1453 pipeline_msg_free(rsp); 1454 1455 return status; 1456 } 1457 1458 int 1459 pipeline_table_rule_add_default(const char *pipeline_name, 1460 uint32_t table_id, 1461 struct table_rule_action *action) 1462 { 1463 struct pipeline *p; 1464 struct table *table; 1465 struct pipeline_msg_req *req; 1466 struct pipeline_msg_rsp *rsp; 1467 struct table_rule *rule; 1468 int status; 1469 1470 /* Check input params */ 1471 if ((pipeline_name == NULL) || 1472 (action == NULL)) 1473 return -1; 1474 1475 p = pipeline_find(pipeline_name); 1476 if ((p == NULL) || 1477 (table_id >= p->n_tables) || 1478 action_default_check(action, p, table_id)) 1479 return -1; 1480 1481 table = &p->table[table_id]; 1482 1483 rule = calloc(1, sizeof(struct table_rule)); 1484 if (rule == NULL) 1485 return -1; 1486 1487 memcpy(&rule->action, action, sizeof(*action)); 1488 1489 if (!pipeline_is_running(p)) { 1490 struct rte_pipeline_table_entry *data_in, *data_out; 1491 uint8_t *buffer; 1492 1493 buffer = calloc(TABLE_RULE_ACTION_SIZE_MAX, sizeof(uint8_t)); 1494 if (buffer == NULL) { 1495 free(rule); 1496 return -1; 1497 } 1498 1499 /* Apply actions */ 1500 data_in = (struct rte_pipeline_table_entry *)buffer; 1501 1502 data_in->action = action->fwd.action; 1503 if (action->fwd.action == RTE_PIPELINE_ACTION_PORT) 1504 data_in->port_id = action->fwd.id; 1505 if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE) 1506 data_in->table_id = action->fwd.id; 1507 1508 /* Add default rule to table */ 1509 status = rte_pipeline_table_default_entry_add(p->p, 1510 table_id, 1511 data_in, 1512 &data_out); 1513 if (status) { 1514 free(buffer); 1515 free(rule); 1516 return -1; 1517 } 1518 1519 /* Write Response */ 1520 rule->data = data_out; 1521 table_rule_default_add(table, rule); 1522 1523 free(buffer); 1524 return 0; 1525 } 1526 1527 /* Allocate request */ 1528 req = pipeline_msg_alloc(); 1529 if (req == NULL) { 1530 free(rule); 1531 return -1; 1532 } 1533 1534 /* Write request */ 1535 req->type = PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT; 1536 req->id = table_id; 1537 memcpy(&req->table_rule_add_default.action, action, sizeof(*action)); 1538 1539 /* Send request and wait for response */ 1540 rsp = pipeline_msg_send_recv(p, req); 1541 if (rsp == NULL) { 1542 free(rule); 1543 return -1; 1544 } 1545 1546 /* Read response */ 1547 status = rsp->status; 1548 if (status == 0) { 1549 rule->data = rsp->table_rule_add_default.data; 1550 table_rule_default_add(table, rule); 1551 } else 1552 free(rule); 1553 1554 /* Free response */ 1555 pipeline_msg_free(rsp); 1556 1557 return status; 1558 } 1559 1560 static uint32_t 1561 table_rule_list_free(struct table_rule_list *list) 1562 { 1563 uint32_t n = 0; 1564 1565 if (!list) 1566 return 0; 1567 1568 for ( ; ; ) { 1569 struct table_rule *rule; 1570 1571 rule = TAILQ_FIRST(list); 1572 if (rule == NULL) 1573 break; 1574 1575 TAILQ_REMOVE(list, rule, node); 1576 free(rule); 1577 n++; 1578 } 1579 1580 free(list); 1581 return n; 1582 } 1583 1584 int 1585 pipeline_table_rule_add_bulk(const char *pipeline_name, 1586 uint32_t table_id, 1587 struct table_rule_list *list, 1588 uint32_t *n_rules_added, 1589 uint32_t *n_rules_not_added) 1590 { 1591 struct pipeline *p; 1592 struct table *table; 1593 struct pipeline_msg_req *req; 1594 struct pipeline_msg_rsp *rsp; 1595 struct table_rule *rule; 1596 int status = 0; 1597 1598 /* Check input params */ 1599 if ((pipeline_name == NULL) || 1600 (list == NULL) || 1601 TAILQ_EMPTY(list) || 1602 (n_rules_added == NULL) || 1603 (n_rules_not_added == NULL)) { 1604 table_rule_list_free(list); 1605 return -EINVAL; 1606 } 1607 1608 p = pipeline_find(pipeline_name); 1609 if ((p == NULL) || 1610 (table_id >= p->n_tables)) { 1611 table_rule_list_free(list); 1612 return -EINVAL; 1613 } 1614 1615 table = &p->table[table_id]; 1616 1617 TAILQ_FOREACH(rule, list, node) 1618 if (match_check(&rule->match, p, table_id) || 1619 action_check(&rule->action, p, table_id)) { 1620 table_rule_list_free(list); 1621 return -EINVAL; 1622 } 1623 1624 if (!pipeline_is_running(p)) { 1625 struct table_ll table_ll = { 1626 .p = p->p, 1627 .table_id = table_id, 1628 .a = table->a, 1629 .bulk_supported = table->params.match_type == TABLE_ACL, 1630 }; 1631 1632 status = table_rule_add_bulk_ll(&table_ll, list, n_rules_added); 1633 if (status) { 1634 table_rule_list_free(list); 1635 return status; 1636 } 1637 1638 table_rule_add_bulk(table, list, *n_rules_added); 1639 *n_rules_not_added = table_rule_list_free(list); 1640 return 0; 1641 } 1642 1643 /* Allocate request */ 1644 req = pipeline_msg_alloc(); 1645 if (req == NULL) { 1646 table_rule_list_free(list); 1647 return -ENOMEM; 1648 } 1649 1650 /* Write request */ 1651 req->type = PIPELINE_REQ_TABLE_RULE_ADD_BULK; 1652 req->id = table_id; 1653 req->table_rule_add_bulk.list = list; 1654 req->table_rule_add_bulk.bulk = table->params.match_type == TABLE_ACL; 1655 1656 /* Send request and wait for response */ 1657 rsp = pipeline_msg_send_recv(p, req); 1658 if (rsp == NULL) { 1659 table_rule_list_free(list); 1660 return -ENOMEM; 1661 } 1662 1663 /* Read response */ 1664 status = rsp->status; 1665 if (status == 0) { 1666 *n_rules_added = rsp->table_rule_add_bulk.n_rules; 1667 1668 table_rule_add_bulk(table, list, *n_rules_added); 1669 *n_rules_not_added = table_rule_list_free(list); 1670 } else 1671 table_rule_list_free(list); 1672 1673 1674 /* Free response */ 1675 pipeline_msg_free(rsp); 1676 1677 return status; 1678 } 1679 1680 int 1681 pipeline_table_rule_delete(const char *pipeline_name, 1682 uint32_t table_id, 1683 struct table_rule_match *match) 1684 { 1685 struct pipeline *p; 1686 struct table *table; 1687 struct pipeline_msg_req *req; 1688 struct pipeline_msg_rsp *rsp; 1689 int status; 1690 1691 /* Check input params */ 1692 if ((pipeline_name == NULL) || 1693 (match == NULL)) 1694 return -1; 1695 1696 p = pipeline_find(pipeline_name); 1697 if ((p == NULL) || 1698 (table_id >= p->n_tables) || 1699 match_check(match, p, table_id)) 1700 return -1; 1701 1702 table = &p->table[table_id]; 1703 1704 if (!pipeline_is_running(p)) { 1705 union table_rule_match_low_level match_ll; 1706 int key_found; 1707 1708 status = match_convert(match, &match_ll, 0); 1709 if (status) 1710 return -1; 1711 1712 status = rte_pipeline_table_entry_delete(p->p, 1713 table_id, 1714 &match_ll, 1715 &key_found, 1716 NULL); 1717 1718 if (status == 0) 1719 table_rule_delete(table, match); 1720 1721 return status; 1722 } 1723 1724 /* Allocate request */ 1725 req = pipeline_msg_alloc(); 1726 if (req == NULL) 1727 return -1; 1728 1729 /* Write request */ 1730 req->type = PIPELINE_REQ_TABLE_RULE_DELETE; 1731 req->id = table_id; 1732 memcpy(&req->table_rule_delete.match, match, sizeof(*match)); 1733 1734 /* Send request and wait for response */ 1735 rsp = pipeline_msg_send_recv(p, req); 1736 if (rsp == NULL) 1737 return -1; 1738 1739 /* Read response */ 1740 status = rsp->status; 1741 if (status == 0) 1742 table_rule_delete(table, match); 1743 1744 /* Free response */ 1745 pipeline_msg_free(rsp); 1746 1747 return status; 1748 } 1749 1750 int 1751 pipeline_table_rule_delete_default(const char *pipeline_name, 1752 uint32_t table_id) 1753 { 1754 struct pipeline *p; 1755 struct table *table; 1756 struct pipeline_msg_req *req; 1757 struct pipeline_msg_rsp *rsp; 1758 int status; 1759 1760 /* Check input params */ 1761 if (pipeline_name == NULL) 1762 return -1; 1763 1764 p = pipeline_find(pipeline_name); 1765 if ((p == NULL) || 1766 (table_id >= p->n_tables)) 1767 return -1; 1768 1769 table = &p->table[table_id]; 1770 1771 if (!pipeline_is_running(p)) { 1772 status = rte_pipeline_table_default_entry_delete(p->p, 1773 table_id, 1774 NULL); 1775 1776 if (status == 0) 1777 table_rule_default_delete(table); 1778 1779 return status; 1780 } 1781 1782 /* Allocate request */ 1783 req = pipeline_msg_alloc(); 1784 if (req == NULL) 1785 return -1; 1786 1787 /* Write request */ 1788 req->type = PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT; 1789 req->id = table_id; 1790 1791 /* Send request and wait for response */ 1792 rsp = pipeline_msg_send_recv(p, req); 1793 if (rsp == NULL) 1794 return -1; 1795 1796 /* Read response */ 1797 status = rsp->status; 1798 if (status == 0) 1799 table_rule_default_delete(table); 1800 1801 /* Free response */ 1802 pipeline_msg_free(rsp); 1803 1804 return status; 1805 } 1806 1807 int 1808 pipeline_table_rule_stats_read(const char *pipeline_name, 1809 uint32_t table_id, 1810 struct table_rule_match *match, 1811 struct rte_table_action_stats_counters *stats, 1812 int clear) 1813 { 1814 struct pipeline *p; 1815 struct table *table; 1816 struct pipeline_msg_req *req; 1817 struct pipeline_msg_rsp *rsp; 1818 struct table_rule *rule; 1819 int status; 1820 1821 /* Check input params */ 1822 if ((pipeline_name == NULL) || 1823 (match == NULL) || 1824 (stats == NULL)) 1825 return -1; 1826 1827 p = pipeline_find(pipeline_name); 1828 if ((p == NULL) || 1829 (table_id >= p->n_tables) || 1830 match_check(match, p, table_id)) 1831 return -1; 1832 1833 table = &p->table[table_id]; 1834 rule = table_rule_find(table, match); 1835 if (rule == NULL) 1836 return -1; 1837 1838 if (!pipeline_is_running(p)) { 1839 status = rte_table_action_stats_read(table->a, 1840 rule->data, 1841 stats, 1842 clear); 1843 1844 return status; 1845 } 1846 1847 /* Allocate request */ 1848 req = pipeline_msg_alloc(); 1849 if (req == NULL) 1850 return -1; 1851 1852 /* Write request */ 1853 req->type = PIPELINE_REQ_TABLE_RULE_STATS_READ; 1854 req->id = table_id; 1855 req->table_rule_stats_read.data = rule->data; 1856 req->table_rule_stats_read.clear = clear; 1857 1858 /* Send request and wait for response */ 1859 rsp = pipeline_msg_send_recv(p, req); 1860 if (rsp == NULL) 1861 return -1; 1862 1863 /* Read response */ 1864 status = rsp->status; 1865 if (status == 0) 1866 memcpy(stats, &rsp->table_rule_stats_read.stats, sizeof(*stats)); 1867 1868 /* Free response */ 1869 pipeline_msg_free(rsp); 1870 1871 return status; 1872 } 1873 1874 int 1875 pipeline_table_mtr_profile_add(const char *pipeline_name, 1876 uint32_t table_id, 1877 uint32_t meter_profile_id, 1878 struct rte_table_action_meter_profile *profile) 1879 { 1880 struct pipeline *p; 1881 struct pipeline_msg_req *req; 1882 struct pipeline_msg_rsp *rsp; 1883 int status; 1884 1885 /* Check input params */ 1886 if ((pipeline_name == NULL) || 1887 (profile == NULL)) 1888 return -1; 1889 1890 p = pipeline_find(pipeline_name); 1891 if ((p == NULL) || 1892 (table_id >= p->n_tables)) 1893 return -1; 1894 1895 if (!pipeline_is_running(p)) { 1896 struct rte_table_action *a = p->table[table_id].a; 1897 1898 status = rte_table_action_meter_profile_add(a, 1899 meter_profile_id, 1900 profile); 1901 1902 return status; 1903 } 1904 1905 /* Allocate request */ 1906 req = pipeline_msg_alloc(); 1907 if (req == NULL) 1908 return -1; 1909 1910 /* Write request */ 1911 req->type = PIPELINE_REQ_TABLE_MTR_PROFILE_ADD; 1912 req->id = table_id; 1913 req->table_mtr_profile_add.meter_profile_id = meter_profile_id; 1914 memcpy(&req->table_mtr_profile_add.profile, profile, sizeof(*profile)); 1915 1916 /* Send request and wait for response */ 1917 rsp = pipeline_msg_send_recv(p, req); 1918 if (rsp == NULL) 1919 return -1; 1920 1921 /* Read response */ 1922 status = rsp->status; 1923 1924 /* Free response */ 1925 pipeline_msg_free(rsp); 1926 1927 return status; 1928 } 1929 1930 int 1931 pipeline_table_mtr_profile_delete(const char *pipeline_name, 1932 uint32_t table_id, 1933 uint32_t meter_profile_id) 1934 { 1935 struct pipeline *p; 1936 struct pipeline_msg_req *req; 1937 struct pipeline_msg_rsp *rsp; 1938 int status; 1939 1940 /* Check input params */ 1941 if (pipeline_name == NULL) 1942 return -1; 1943 1944 p = pipeline_find(pipeline_name); 1945 if ((p == NULL) || 1946 (table_id >= p->n_tables)) 1947 return -1; 1948 1949 if (!pipeline_is_running(p)) { 1950 struct rte_table_action *a = p->table[table_id].a; 1951 1952 status = rte_table_action_meter_profile_delete(a, 1953 meter_profile_id); 1954 1955 return status; 1956 } 1957 1958 /* Allocate request */ 1959 req = pipeline_msg_alloc(); 1960 if (req == NULL) 1961 return -1; 1962 1963 /* Write request */ 1964 req->type = PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE; 1965 req->id = table_id; 1966 req->table_mtr_profile_delete.meter_profile_id = meter_profile_id; 1967 1968 /* Send request and wait for response */ 1969 rsp = pipeline_msg_send_recv(p, req); 1970 if (rsp == NULL) 1971 return -1; 1972 1973 /* Read response */ 1974 status = rsp->status; 1975 1976 /* Free response */ 1977 pipeline_msg_free(rsp); 1978 1979 return status; 1980 } 1981 1982 int 1983 pipeline_table_rule_mtr_read(const char *pipeline_name, 1984 uint32_t table_id, 1985 struct table_rule_match *match, 1986 struct rte_table_action_mtr_counters *stats, 1987 int clear) 1988 { 1989 struct pipeline *p; 1990 struct table *table; 1991 struct pipeline_msg_req *req; 1992 struct pipeline_msg_rsp *rsp; 1993 struct table_rule *rule; 1994 uint32_t tc_mask; 1995 int status; 1996 1997 /* Check input params */ 1998 if ((pipeline_name == NULL) || 1999 (match == NULL) || 2000 (stats == NULL)) 2001 return -1; 2002 2003 p = pipeline_find(pipeline_name); 2004 if ((p == NULL) || 2005 (table_id >= p->n_tables) || 2006 match_check(match, p, table_id)) 2007 return -1; 2008 2009 table = &p->table[table_id]; 2010 tc_mask = (1 << table->ap->params.mtr.n_tc) - 1; 2011 2012 rule = table_rule_find(table, match); 2013 if (rule == NULL) 2014 return -1; 2015 2016 if (!pipeline_is_running(p)) { 2017 status = rte_table_action_meter_read(table->a, 2018 rule->data, 2019 tc_mask, 2020 stats, 2021 clear); 2022 2023 return status; 2024 } 2025 2026 /* Allocate request */ 2027 req = pipeline_msg_alloc(); 2028 if (req == NULL) 2029 return -1; 2030 2031 /* Write request */ 2032 req->type = PIPELINE_REQ_TABLE_RULE_MTR_READ; 2033 req->id = table_id; 2034 req->table_rule_mtr_read.data = rule->data; 2035 req->table_rule_mtr_read.tc_mask = tc_mask; 2036 req->table_rule_mtr_read.clear = clear; 2037 2038 /* Send request and wait for response */ 2039 rsp = pipeline_msg_send_recv(p, req); 2040 if (rsp == NULL) 2041 return -1; 2042 2043 /* Read response */ 2044 status = rsp->status; 2045 if (status == 0) 2046 memcpy(stats, &rsp->table_rule_mtr_read.stats, sizeof(*stats)); 2047 2048 /* Free response */ 2049 pipeline_msg_free(rsp); 2050 2051 return status; 2052 } 2053 2054 int 2055 pipeline_table_dscp_table_update(const char *pipeline_name, 2056 uint32_t table_id, 2057 uint64_t dscp_mask, 2058 struct rte_table_action_dscp_table *dscp_table) 2059 { 2060 struct pipeline *p; 2061 struct pipeline_msg_req *req; 2062 struct pipeline_msg_rsp *rsp; 2063 int status; 2064 2065 /* Check input params */ 2066 if ((pipeline_name == NULL) || 2067 (dscp_table == NULL)) 2068 return -1; 2069 2070 p = pipeline_find(pipeline_name); 2071 if ((p == NULL) || 2072 (table_id >= p->n_tables)) 2073 return -1; 2074 2075 if (!pipeline_is_running(p)) { 2076 struct rte_table_action *a = p->table[table_id].a; 2077 2078 status = rte_table_action_dscp_table_update(a, 2079 dscp_mask, 2080 dscp_table); 2081 2082 return status; 2083 } 2084 2085 /* Allocate request */ 2086 req = pipeline_msg_alloc(); 2087 if (req == NULL) 2088 return -1; 2089 2090 /* Write request */ 2091 req->type = PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE; 2092 req->id = table_id; 2093 req->table_dscp_table_update.dscp_mask = dscp_mask; 2094 memcpy(&req->table_dscp_table_update.dscp_table, 2095 dscp_table, sizeof(*dscp_table)); 2096 2097 /* Send request and wait for response */ 2098 rsp = pipeline_msg_send_recv(p, req); 2099 if (rsp == NULL) 2100 return -1; 2101 2102 /* Read response */ 2103 status = rsp->status; 2104 2105 /* Free response */ 2106 pipeline_msg_free(rsp); 2107 2108 return status; 2109 } 2110 2111 int 2112 pipeline_table_rule_ttl_read(const char *pipeline_name, 2113 uint32_t table_id, 2114 struct table_rule_match *match, 2115 struct rte_table_action_ttl_counters *stats, 2116 int clear) 2117 { 2118 struct pipeline *p; 2119 struct table *table; 2120 struct pipeline_msg_req *req; 2121 struct pipeline_msg_rsp *rsp; 2122 struct table_rule *rule; 2123 int status; 2124 2125 /* Check input params */ 2126 if ((pipeline_name == NULL) || 2127 (match == NULL) || 2128 (stats == NULL)) 2129 return -1; 2130 2131 p = pipeline_find(pipeline_name); 2132 if ((p == NULL) || 2133 (table_id >= p->n_tables) || 2134 match_check(match, p, table_id)) 2135 return -1; 2136 2137 table = &p->table[table_id]; 2138 if (!table->ap->params.ttl.n_packets_enabled) 2139 return -1; 2140 2141 rule = table_rule_find(table, match); 2142 if (rule == NULL) 2143 return -1; 2144 2145 if (!pipeline_is_running(p)) { 2146 status = rte_table_action_ttl_read(table->a, 2147 rule->data, 2148 stats, 2149 clear); 2150 2151 return status; 2152 } 2153 2154 /* Allocate request */ 2155 req = pipeline_msg_alloc(); 2156 if (req == NULL) 2157 return -1; 2158 2159 /* Write request */ 2160 req->type = PIPELINE_REQ_TABLE_RULE_TTL_READ; 2161 req->id = table_id; 2162 req->table_rule_ttl_read.data = rule->data; 2163 req->table_rule_ttl_read.clear = clear; 2164 2165 /* Send request and wait for response */ 2166 rsp = pipeline_msg_send_recv(p, req); 2167 if (rsp == NULL) 2168 return -1; 2169 2170 /* Read response */ 2171 status = rsp->status; 2172 if (status == 0) 2173 memcpy(stats, &rsp->table_rule_ttl_read.stats, sizeof(*stats)); 2174 2175 /* Free response */ 2176 pipeline_msg_free(rsp); 2177 2178 return status; 2179 } 2180 2181 int 2182 pipeline_table_rule_time_read(const char *pipeline_name, 2183 uint32_t table_id, 2184 struct table_rule_match *match, 2185 uint64_t *timestamp) 2186 { 2187 struct pipeline *p; 2188 struct table *table; 2189 struct pipeline_msg_req *req; 2190 struct pipeline_msg_rsp *rsp; 2191 struct table_rule *rule; 2192 int status; 2193 2194 /* Check input params */ 2195 if ((pipeline_name == NULL) || 2196 (match == NULL) || 2197 (timestamp == NULL)) 2198 return -1; 2199 2200 p = pipeline_find(pipeline_name); 2201 if ((p == NULL) || 2202 (table_id >= p->n_tables) || 2203 match_check(match, p, table_id)) 2204 return -1; 2205 2206 table = &p->table[table_id]; 2207 2208 rule = table_rule_find(table, match); 2209 if (rule == NULL) 2210 return -1; 2211 2212 if (!pipeline_is_running(p)) { 2213 status = rte_table_action_time_read(table->a, 2214 rule->data, 2215 timestamp); 2216 2217 return status; 2218 } 2219 2220 /* Allocate request */ 2221 req = pipeline_msg_alloc(); 2222 if (req == NULL) 2223 return -1; 2224 2225 /* Write request */ 2226 req->type = PIPELINE_REQ_TABLE_RULE_TIME_READ; 2227 req->id = table_id; 2228 req->table_rule_time_read.data = rule->data; 2229 2230 /* Send request and wait for response */ 2231 rsp = pipeline_msg_send_recv(p, req); 2232 if (rsp == NULL) 2233 return -1; 2234 2235 /* Read response */ 2236 status = rsp->status; 2237 if (status == 0) 2238 *timestamp = rsp->table_rule_time_read.timestamp; 2239 2240 /* Free response */ 2241 pipeline_msg_free(rsp); 2242 2243 return status; 2244 } 2245 2246 /** 2247 * Data plane threads: message handling 2248 */ 2249 static inline struct pipeline_msg_req * 2250 pipeline_msg_recv(struct rte_ring *msgq_req) 2251 { 2252 struct pipeline_msg_req *req; 2253 2254 int status = rte_ring_sc_dequeue(msgq_req, (void **) &req); 2255 2256 if (status != 0) 2257 return NULL; 2258 2259 return req; 2260 } 2261 2262 static inline void 2263 pipeline_msg_send(struct rte_ring *msgq_rsp, 2264 struct pipeline_msg_rsp *rsp) 2265 { 2266 int status; 2267 2268 do { 2269 status = rte_ring_sp_enqueue(msgq_rsp, rsp); 2270 } while (status == -ENOBUFS); 2271 } 2272 2273 static struct pipeline_msg_rsp * 2274 pipeline_msg_handle_port_in_stats_read(struct pipeline_data *p, 2275 struct pipeline_msg_req *req) 2276 { 2277 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req; 2278 uint32_t port_id = req->id; 2279 int clear = req->port_in_stats_read.clear; 2280 2281 rsp->status = rte_pipeline_port_in_stats_read(p->p, 2282 port_id, 2283 &rsp->port_in_stats_read.stats, 2284 clear); 2285 2286 return rsp; 2287 } 2288 2289 static struct pipeline_msg_rsp * 2290 pipeline_msg_handle_port_in_enable(struct pipeline_data *p, 2291 struct pipeline_msg_req *req) 2292 { 2293 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req; 2294 uint32_t port_id = req->id; 2295 2296 rsp->status = rte_pipeline_port_in_enable(p->p, 2297 port_id); 2298 2299 return rsp; 2300 } 2301 2302 static struct pipeline_msg_rsp * 2303 pipeline_msg_handle_port_in_disable(struct pipeline_data *p, 2304 struct pipeline_msg_req *req) 2305 { 2306 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req; 2307 uint32_t port_id = req->id; 2308 2309 rsp->status = rte_pipeline_port_in_disable(p->p, 2310 port_id); 2311 2312 return rsp; 2313 } 2314 2315 static struct pipeline_msg_rsp * 2316 pipeline_msg_handle_port_out_stats_read(struct pipeline_data *p, 2317 struct pipeline_msg_req *req) 2318 { 2319 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req; 2320 uint32_t port_id = req->id; 2321 int clear = req->port_out_stats_read.clear; 2322 2323 rsp->status = rte_pipeline_port_out_stats_read(p->p, 2324 port_id, 2325 &rsp->port_out_stats_read.stats, 2326 clear); 2327 2328 return rsp; 2329 } 2330 2331 static struct pipeline_msg_rsp * 2332 pipeline_msg_handle_table_stats_read(struct pipeline_data *p, 2333 struct pipeline_msg_req *req) 2334 { 2335 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req; 2336 uint32_t port_id = req->id; 2337 int clear = req->table_stats_read.clear; 2338 2339 rsp->status = rte_pipeline_table_stats_read(p->p, 2340 port_id, 2341 &rsp->table_stats_read.stats, 2342 clear); 2343 2344 return rsp; 2345 } 2346 2347 static int 2348 match_convert_ipv6_depth(uint32_t depth, uint32_t *depth32) 2349 { 2350 if (depth > 128) 2351 return -1; 2352 2353 switch (depth / 32) { 2354 case 0: 2355 depth32[0] = depth; 2356 depth32[1] = 0; 2357 depth32[2] = 0; 2358 depth32[3] = 0; 2359 return 0; 2360 2361 case 1: 2362 depth32[0] = 32; 2363 depth32[1] = depth - 32; 2364 depth32[2] = 0; 2365 depth32[3] = 0; 2366 return 0; 2367 2368 case 2: 2369 depth32[0] = 32; 2370 depth32[1] = 32; 2371 depth32[2] = depth - 64; 2372 depth32[3] = 0; 2373 return 0; 2374 2375 case 3: 2376 depth32[0] = 32; 2377 depth32[1] = 32; 2378 depth32[2] = 32; 2379 depth32[3] = depth - 96; 2380 return 0; 2381 2382 case 4: 2383 depth32[0] = 32; 2384 depth32[1] = 32; 2385 depth32[2] = 32; 2386 depth32[3] = 32; 2387 return 0; 2388 2389 default: 2390 return -1; 2391 } 2392 } 2393 2394 static int 2395 match_convert(struct table_rule_match *mh, 2396 union table_rule_match_low_level *ml, 2397 int add) 2398 { 2399 memset(ml, 0, sizeof(*ml)); 2400 2401 switch (mh->match_type) { 2402 case TABLE_ACL: 2403 if (mh->match.acl.ip_version) 2404 if (add) { 2405 ml->acl_add.field_value[0].value.u8 = 2406 mh->match.acl.proto; 2407 ml->acl_add.field_value[0].mask_range.u8 = 2408 mh->match.acl.proto_mask; 2409 2410 ml->acl_add.field_value[1].value.u32 = 2411 mh->match.acl.ipv4.sa; 2412 ml->acl_add.field_value[1].mask_range.u32 = 2413 mh->match.acl.sa_depth; 2414 2415 ml->acl_add.field_value[2].value.u32 = 2416 mh->match.acl.ipv4.da; 2417 ml->acl_add.field_value[2].mask_range.u32 = 2418 mh->match.acl.da_depth; 2419 2420 ml->acl_add.field_value[3].value.u16 = 2421 mh->match.acl.sp0; 2422 ml->acl_add.field_value[3].mask_range.u16 = 2423 mh->match.acl.sp1; 2424 2425 ml->acl_add.field_value[4].value.u16 = 2426 mh->match.acl.dp0; 2427 ml->acl_add.field_value[4].mask_range.u16 = 2428 mh->match.acl.dp1; 2429 2430 ml->acl_add.priority = 2431 (int32_t) mh->match.acl.priority; 2432 } else { 2433 ml->acl_delete.field_value[0].value.u8 = 2434 mh->match.acl.proto; 2435 ml->acl_delete.field_value[0].mask_range.u8 = 2436 mh->match.acl.proto_mask; 2437 2438 ml->acl_delete.field_value[1].value.u32 = 2439 mh->match.acl.ipv4.sa; 2440 ml->acl_delete.field_value[1].mask_range.u32 = 2441 mh->match.acl.sa_depth; 2442 2443 ml->acl_delete.field_value[2].value.u32 = 2444 mh->match.acl.ipv4.da; 2445 ml->acl_delete.field_value[2].mask_range.u32 = 2446 mh->match.acl.da_depth; 2447 2448 ml->acl_delete.field_value[3].value.u16 = 2449 mh->match.acl.sp0; 2450 ml->acl_delete.field_value[3].mask_range.u16 = 2451 mh->match.acl.sp1; 2452 2453 ml->acl_delete.field_value[4].value.u16 = 2454 mh->match.acl.dp0; 2455 ml->acl_delete.field_value[4].mask_range.u16 = 2456 mh->match.acl.dp1; 2457 } 2458 else 2459 if (add) { 2460 uint32_t *sa32 = 2461 (uint32_t *) mh->match.acl.ipv6.sa; 2462 uint32_t *da32 = 2463 (uint32_t *) mh->match.acl.ipv6.da; 2464 uint32_t sa32_depth[4], da32_depth[4]; 2465 int status; 2466 2467 status = match_convert_ipv6_depth( 2468 mh->match.acl.sa_depth, 2469 sa32_depth); 2470 if (status) 2471 return status; 2472 2473 status = match_convert_ipv6_depth( 2474 mh->match.acl.da_depth, 2475 da32_depth); 2476 if (status) 2477 return status; 2478 2479 ml->acl_add.field_value[0].value.u8 = 2480 mh->match.acl.proto; 2481 ml->acl_add.field_value[0].mask_range.u8 = 2482 mh->match.acl.proto_mask; 2483 2484 ml->acl_add.field_value[1].value.u32 = 2485 rte_be_to_cpu_32(sa32[0]); 2486 ml->acl_add.field_value[1].mask_range.u32 = 2487 sa32_depth[0]; 2488 ml->acl_add.field_value[2].value.u32 = 2489 rte_be_to_cpu_32(sa32[1]); 2490 ml->acl_add.field_value[2].mask_range.u32 = 2491 sa32_depth[1]; 2492 ml->acl_add.field_value[3].value.u32 = 2493 rte_be_to_cpu_32(sa32[2]); 2494 ml->acl_add.field_value[3].mask_range.u32 = 2495 sa32_depth[2]; 2496 ml->acl_add.field_value[4].value.u32 = 2497 rte_be_to_cpu_32(sa32[3]); 2498 ml->acl_add.field_value[4].mask_range.u32 = 2499 sa32_depth[3]; 2500 2501 ml->acl_add.field_value[5].value.u32 = 2502 rte_be_to_cpu_32(da32[0]); 2503 ml->acl_add.field_value[5].mask_range.u32 = 2504 da32_depth[0]; 2505 ml->acl_add.field_value[6].value.u32 = 2506 rte_be_to_cpu_32(da32[1]); 2507 ml->acl_add.field_value[6].mask_range.u32 = 2508 da32_depth[1]; 2509 ml->acl_add.field_value[7].value.u32 = 2510 rte_be_to_cpu_32(da32[2]); 2511 ml->acl_add.field_value[7].mask_range.u32 = 2512 da32_depth[2]; 2513 ml->acl_add.field_value[8].value.u32 = 2514 rte_be_to_cpu_32(da32[3]); 2515 ml->acl_add.field_value[8].mask_range.u32 = 2516 da32_depth[3]; 2517 2518 ml->acl_add.field_value[9].value.u16 = 2519 mh->match.acl.sp0; 2520 ml->acl_add.field_value[9].mask_range.u16 = 2521 mh->match.acl.sp1; 2522 2523 ml->acl_add.field_value[10].value.u16 = 2524 mh->match.acl.dp0; 2525 ml->acl_add.field_value[10].mask_range.u16 = 2526 mh->match.acl.dp1; 2527 2528 ml->acl_add.priority = 2529 (int32_t) mh->match.acl.priority; 2530 } else { 2531 uint32_t *sa32 = 2532 (uint32_t *) mh->match.acl.ipv6.sa; 2533 uint32_t *da32 = 2534 (uint32_t *) mh->match.acl.ipv6.da; 2535 uint32_t sa32_depth[4], da32_depth[4]; 2536 int status; 2537 2538 status = match_convert_ipv6_depth( 2539 mh->match.acl.sa_depth, 2540 sa32_depth); 2541 if (status) 2542 return status; 2543 2544 status = match_convert_ipv6_depth( 2545 mh->match.acl.da_depth, 2546 da32_depth); 2547 if (status) 2548 return status; 2549 2550 ml->acl_delete.field_value[0].value.u8 = 2551 mh->match.acl.proto; 2552 ml->acl_delete.field_value[0].mask_range.u8 = 2553 mh->match.acl.proto_mask; 2554 2555 ml->acl_delete.field_value[1].value.u32 = 2556 rte_be_to_cpu_32(sa32[0]); 2557 ml->acl_delete.field_value[1].mask_range.u32 = 2558 sa32_depth[0]; 2559 ml->acl_delete.field_value[2].value.u32 = 2560 rte_be_to_cpu_32(sa32[1]); 2561 ml->acl_delete.field_value[2].mask_range.u32 = 2562 sa32_depth[1]; 2563 ml->acl_delete.field_value[3].value.u32 = 2564 rte_be_to_cpu_32(sa32[2]); 2565 ml->acl_delete.field_value[3].mask_range.u32 = 2566 sa32_depth[2]; 2567 ml->acl_delete.field_value[4].value.u32 = 2568 rte_be_to_cpu_32(sa32[3]); 2569 ml->acl_delete.field_value[4].mask_range.u32 = 2570 sa32_depth[3]; 2571 2572 ml->acl_delete.field_value[5].value.u32 = 2573 rte_be_to_cpu_32(da32[0]); 2574 ml->acl_delete.field_value[5].mask_range.u32 = 2575 da32_depth[0]; 2576 ml->acl_delete.field_value[6].value.u32 = 2577 rte_be_to_cpu_32(da32[1]); 2578 ml->acl_delete.field_value[6].mask_range.u32 = 2579 da32_depth[1]; 2580 ml->acl_delete.field_value[7].value.u32 = 2581 rte_be_to_cpu_32(da32[2]); 2582 ml->acl_delete.field_value[7].mask_range.u32 = 2583 da32_depth[2]; 2584 ml->acl_delete.field_value[8].value.u32 = 2585 rte_be_to_cpu_32(da32[3]); 2586 ml->acl_delete.field_value[8].mask_range.u32 = 2587 da32_depth[3]; 2588 2589 ml->acl_delete.field_value[9].value.u16 = 2590 mh->match.acl.sp0; 2591 ml->acl_delete.field_value[9].mask_range.u16 = 2592 mh->match.acl.sp1; 2593 2594 ml->acl_delete.field_value[10].value.u16 = 2595 mh->match.acl.dp0; 2596 ml->acl_delete.field_value[10].mask_range.u16 = 2597 mh->match.acl.dp1; 2598 } 2599 return 0; 2600 2601 case TABLE_ARRAY: 2602 ml->array.pos = mh->match.array.pos; 2603 return 0; 2604 2605 case TABLE_HASH: 2606 memcpy(ml->hash, mh->match.hash.key, sizeof(ml->hash)); 2607 return 0; 2608 2609 case TABLE_LPM: 2610 if (mh->match.lpm.ip_version) { 2611 ml->lpm_ipv4.ip = mh->match.lpm.ipv4; 2612 ml->lpm_ipv4.depth = mh->match.lpm.depth; 2613 } else { 2614 memcpy(ml->lpm_ipv6.ip, 2615 mh->match.lpm.ipv6, sizeof(ml->lpm_ipv6.ip)); 2616 ml->lpm_ipv6.depth = mh->match.lpm.depth; 2617 } 2618 2619 return 0; 2620 2621 default: 2622 return -1; 2623 } 2624 } 2625 2626 static int 2627 action_convert(struct rte_table_action *a, 2628 struct table_rule_action *action, 2629 struct rte_pipeline_table_entry *data) 2630 { 2631 int status; 2632 2633 /* Apply actions */ 2634 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_FWD)) { 2635 status = rte_table_action_apply(a, 2636 data, 2637 RTE_TABLE_ACTION_FWD, 2638 &action->fwd); 2639 2640 if (status) 2641 return status; 2642 } 2643 2644 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_LB)) { 2645 status = rte_table_action_apply(a, 2646 data, 2647 RTE_TABLE_ACTION_LB, 2648 &action->lb); 2649 2650 if (status) 2651 return status; 2652 } 2653 2654 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_MTR)) { 2655 status = rte_table_action_apply(a, 2656 data, 2657 RTE_TABLE_ACTION_MTR, 2658 &action->mtr); 2659 2660 if (status) 2661 return status; 2662 } 2663 2664 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TM)) { 2665 status = rte_table_action_apply(a, 2666 data, 2667 RTE_TABLE_ACTION_TM, 2668 &action->tm); 2669 2670 if (status) 2671 return status; 2672 } 2673 2674 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_ENCAP)) { 2675 status = rte_table_action_apply(a, 2676 data, 2677 RTE_TABLE_ACTION_ENCAP, 2678 &action->encap); 2679 2680 if (status) 2681 return status; 2682 } 2683 2684 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_NAT)) { 2685 status = rte_table_action_apply(a, 2686 data, 2687 RTE_TABLE_ACTION_NAT, 2688 &action->nat); 2689 2690 if (status) 2691 return status; 2692 } 2693 2694 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TTL)) { 2695 status = rte_table_action_apply(a, 2696 data, 2697 RTE_TABLE_ACTION_TTL, 2698 &action->ttl); 2699 2700 if (status) 2701 return status; 2702 } 2703 2704 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_STATS)) { 2705 status = rte_table_action_apply(a, 2706 data, 2707 RTE_TABLE_ACTION_STATS, 2708 &action->stats); 2709 2710 if (status) 2711 return status; 2712 } 2713 2714 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TIME)) { 2715 status = rte_table_action_apply(a, 2716 data, 2717 RTE_TABLE_ACTION_TIME, 2718 &action->time); 2719 2720 if (status) 2721 return status; 2722 } 2723 2724 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_SYM_CRYPTO)) { 2725 status = rte_table_action_apply(a, 2726 data, 2727 RTE_TABLE_ACTION_SYM_CRYPTO, 2728 &action->sym_crypto); 2729 2730 if (status) 2731 return status; 2732 } 2733 2734 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_TAG)) { 2735 status = rte_table_action_apply(a, 2736 data, 2737 RTE_TABLE_ACTION_TAG, 2738 &action->tag); 2739 2740 if (status) 2741 return status; 2742 } 2743 2744 if (action->action_mask & (1LLU << RTE_TABLE_ACTION_DECAP)) { 2745 status = rte_table_action_apply(a, 2746 data, 2747 RTE_TABLE_ACTION_DECAP, 2748 &action->decap); 2749 2750 if (status) 2751 return status; 2752 } 2753 2754 return 0; 2755 } 2756 2757 static struct pipeline_msg_rsp * 2758 pipeline_msg_handle_table_rule_add(struct pipeline_data *p, 2759 struct pipeline_msg_req *req) 2760 { 2761 union table_rule_match_low_level match_ll; 2762 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req; 2763 struct table_rule_match *match = &req->table_rule_add.match; 2764 struct table_rule_action *action = &req->table_rule_add.action; 2765 struct rte_pipeline_table_entry *data_in, *data_out; 2766 uint32_t table_id = req->id; 2767 int key_found, status; 2768 struct rte_table_action *a = p->table_data[table_id].a; 2769 2770 /* Apply actions */ 2771 memset(p->buffer, 0, sizeof(p->buffer)); 2772 data_in = (struct rte_pipeline_table_entry *) p->buffer; 2773 2774 status = match_convert(match, &match_ll, 1); 2775 if (status) { 2776 rsp->status = -1; 2777 return rsp; 2778 } 2779 2780 status = action_convert(a, action, data_in); 2781 if (status) { 2782 rsp->status = -1; 2783 return rsp; 2784 } 2785 2786 status = rte_pipeline_table_entry_add(p->p, 2787 table_id, 2788 &match_ll, 2789 data_in, 2790 &key_found, 2791 &data_out); 2792 if (status) { 2793 rsp->status = -1; 2794 return rsp; 2795 } 2796 2797 /* Write response */ 2798 rsp->status = 0; 2799 rsp->table_rule_add.data = data_out; 2800 2801 return rsp; 2802 } 2803 2804 static struct pipeline_msg_rsp * 2805 pipeline_msg_handle_table_rule_add_default(struct pipeline_data *p, 2806 struct pipeline_msg_req *req) 2807 { 2808 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req; 2809 struct table_rule_action *action = &req->table_rule_add_default.action; 2810 struct rte_pipeline_table_entry *data_in, *data_out; 2811 uint32_t table_id = req->id; 2812 int status; 2813 2814 /* Apply actions */ 2815 memset(p->buffer, 0, sizeof(p->buffer)); 2816 data_in = (struct rte_pipeline_table_entry *) p->buffer; 2817 2818 data_in->action = action->fwd.action; 2819 if (action->fwd.action == RTE_PIPELINE_ACTION_PORT) 2820 data_in->port_id = action->fwd.id; 2821 if (action->fwd.action == RTE_PIPELINE_ACTION_TABLE) 2822 data_in->table_id = action->fwd.id; 2823 2824 /* Add default rule to table */ 2825 status = rte_pipeline_table_default_entry_add(p->p, 2826 table_id, 2827 data_in, 2828 &data_out); 2829 if (status) { 2830 rsp->status = -1; 2831 return rsp; 2832 } 2833 2834 /* Write response */ 2835 rsp->status = 0; 2836 rsp->table_rule_add_default.data = data_out; 2837 2838 return rsp; 2839 } 2840 2841 static struct pipeline_msg_rsp * 2842 pipeline_msg_handle_table_rule_add_bulk(struct pipeline_data *p, 2843 struct pipeline_msg_req *req) 2844 { 2845 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req; 2846 2847 uint32_t table_id = req->id; 2848 struct table_rule_list *list = req->table_rule_add_bulk.list; 2849 uint32_t bulk = req->table_rule_add_bulk.bulk; 2850 2851 uint32_t n_rules_added; 2852 int status; 2853 2854 struct table_ll table_ll = { 2855 .p = p->p, 2856 .table_id = table_id, 2857 .a = p->table_data[table_id].a, 2858 .bulk_supported = bulk, 2859 }; 2860 2861 status = table_rule_add_bulk_ll(&table_ll, list, &n_rules_added); 2862 if (status) { 2863 rsp->status = -1; 2864 rsp->table_rule_add_bulk.n_rules = 0; 2865 return rsp; 2866 } 2867 2868 /* Write response */ 2869 rsp->status = 0; 2870 rsp->table_rule_add_bulk.n_rules = n_rules_added; 2871 return rsp; 2872 } 2873 2874 static struct pipeline_msg_rsp * 2875 pipeline_msg_handle_table_rule_delete(struct pipeline_data *p, 2876 struct pipeline_msg_req *req) 2877 { 2878 union table_rule_match_low_level match_ll; 2879 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req; 2880 struct table_rule_match *match = &req->table_rule_delete.match; 2881 uint32_t table_id = req->id; 2882 int key_found, status; 2883 2884 status = match_convert(match, &match_ll, 0); 2885 if (status) { 2886 rsp->status = -1; 2887 return rsp; 2888 } 2889 2890 rsp->status = rte_pipeline_table_entry_delete(p->p, 2891 table_id, 2892 &match_ll, 2893 &key_found, 2894 NULL); 2895 2896 return rsp; 2897 } 2898 2899 static struct pipeline_msg_rsp * 2900 pipeline_msg_handle_table_rule_delete_default(struct pipeline_data *p, 2901 struct pipeline_msg_req *req) 2902 { 2903 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req; 2904 uint32_t table_id = req->id; 2905 2906 rsp->status = rte_pipeline_table_default_entry_delete(p->p, 2907 table_id, 2908 NULL); 2909 2910 return rsp; 2911 } 2912 2913 static struct pipeline_msg_rsp * 2914 pipeline_msg_handle_table_rule_stats_read(struct pipeline_data *p, 2915 struct pipeline_msg_req *req) 2916 { 2917 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req; 2918 uint32_t table_id = req->id; 2919 void *data = req->table_rule_stats_read.data; 2920 int clear = req->table_rule_stats_read.clear; 2921 struct rte_table_action *a = p->table_data[table_id].a; 2922 2923 rsp->status = rte_table_action_stats_read(a, 2924 data, 2925 &rsp->table_rule_stats_read.stats, 2926 clear); 2927 2928 return rsp; 2929 } 2930 2931 static struct pipeline_msg_rsp * 2932 pipeline_msg_handle_table_mtr_profile_add(struct pipeline_data *p, 2933 struct pipeline_msg_req *req) 2934 { 2935 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req; 2936 uint32_t table_id = req->id; 2937 uint32_t meter_profile_id = req->table_mtr_profile_add.meter_profile_id; 2938 struct rte_table_action_meter_profile *profile = 2939 &req->table_mtr_profile_add.profile; 2940 struct rte_table_action *a = p->table_data[table_id].a; 2941 2942 rsp->status = rte_table_action_meter_profile_add(a, 2943 meter_profile_id, 2944 profile); 2945 2946 return rsp; 2947 } 2948 2949 static struct pipeline_msg_rsp * 2950 pipeline_msg_handle_table_mtr_profile_delete(struct pipeline_data *p, 2951 struct pipeline_msg_req *req) 2952 { 2953 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req; 2954 uint32_t table_id = req->id; 2955 uint32_t meter_profile_id = 2956 req->table_mtr_profile_delete.meter_profile_id; 2957 struct rte_table_action *a = p->table_data[table_id].a; 2958 2959 rsp->status = rte_table_action_meter_profile_delete(a, 2960 meter_profile_id); 2961 2962 return rsp; 2963 } 2964 2965 static struct pipeline_msg_rsp * 2966 pipeline_msg_handle_table_rule_mtr_read(struct pipeline_data *p, 2967 struct pipeline_msg_req *req) 2968 { 2969 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req; 2970 uint32_t table_id = req->id; 2971 void *data = req->table_rule_mtr_read.data; 2972 uint32_t tc_mask = req->table_rule_mtr_read.tc_mask; 2973 int clear = req->table_rule_mtr_read.clear; 2974 struct rte_table_action *a = p->table_data[table_id].a; 2975 2976 rsp->status = rte_table_action_meter_read(a, 2977 data, 2978 tc_mask, 2979 &rsp->table_rule_mtr_read.stats, 2980 clear); 2981 2982 return rsp; 2983 } 2984 2985 static struct pipeline_msg_rsp * 2986 pipeline_msg_handle_table_dscp_table_update(struct pipeline_data *p, 2987 struct pipeline_msg_req *req) 2988 { 2989 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req; 2990 uint32_t table_id = req->id; 2991 uint64_t dscp_mask = req->table_dscp_table_update.dscp_mask; 2992 struct rte_table_action_dscp_table *dscp_table = 2993 &req->table_dscp_table_update.dscp_table; 2994 struct rte_table_action *a = p->table_data[table_id].a; 2995 2996 rsp->status = rte_table_action_dscp_table_update(a, 2997 dscp_mask, 2998 dscp_table); 2999 3000 return rsp; 3001 } 3002 3003 static struct pipeline_msg_rsp * 3004 pipeline_msg_handle_table_rule_ttl_read(struct pipeline_data *p, 3005 struct pipeline_msg_req *req) 3006 { 3007 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req; 3008 uint32_t table_id = req->id; 3009 void *data = req->table_rule_ttl_read.data; 3010 int clear = req->table_rule_ttl_read.clear; 3011 struct rte_table_action *a = p->table_data[table_id].a; 3012 3013 rsp->status = rte_table_action_ttl_read(a, 3014 data, 3015 &rsp->table_rule_ttl_read.stats, 3016 clear); 3017 3018 return rsp; 3019 } 3020 3021 static struct pipeline_msg_rsp * 3022 pipeline_msg_handle_table_rule_time_read(struct pipeline_data *p, 3023 struct pipeline_msg_req *req) 3024 { 3025 struct pipeline_msg_rsp *rsp = (struct pipeline_msg_rsp *) req; 3026 uint32_t table_id = req->id; 3027 void *data = req->table_rule_time_read.data; 3028 struct rte_table_action *a = p->table_data[table_id].a; 3029 3030 rsp->status = rte_table_action_time_read(a, 3031 data, 3032 &rsp->table_rule_time_read.timestamp); 3033 3034 return rsp; 3035 } 3036 3037 static void 3038 pipeline_msg_handle(struct pipeline_data *p) 3039 { 3040 for ( ; ; ) { 3041 struct pipeline_msg_req *req; 3042 struct pipeline_msg_rsp *rsp; 3043 3044 req = pipeline_msg_recv(p->msgq_req); 3045 if (req == NULL) 3046 break; 3047 3048 switch (req->type) { 3049 case PIPELINE_REQ_PORT_IN_STATS_READ: 3050 rsp = pipeline_msg_handle_port_in_stats_read(p, req); 3051 break; 3052 3053 case PIPELINE_REQ_PORT_IN_ENABLE: 3054 rsp = pipeline_msg_handle_port_in_enable(p, req); 3055 break; 3056 3057 case PIPELINE_REQ_PORT_IN_DISABLE: 3058 rsp = pipeline_msg_handle_port_in_disable(p, req); 3059 break; 3060 3061 case PIPELINE_REQ_PORT_OUT_STATS_READ: 3062 rsp = pipeline_msg_handle_port_out_stats_read(p, req); 3063 break; 3064 3065 case PIPELINE_REQ_TABLE_STATS_READ: 3066 rsp = pipeline_msg_handle_table_stats_read(p, req); 3067 break; 3068 3069 case PIPELINE_REQ_TABLE_RULE_ADD: 3070 rsp = pipeline_msg_handle_table_rule_add(p, req); 3071 break; 3072 3073 case PIPELINE_REQ_TABLE_RULE_ADD_DEFAULT: 3074 rsp = pipeline_msg_handle_table_rule_add_default(p, req); 3075 break; 3076 3077 case PIPELINE_REQ_TABLE_RULE_ADD_BULK: 3078 rsp = pipeline_msg_handle_table_rule_add_bulk(p, req); 3079 break; 3080 3081 case PIPELINE_REQ_TABLE_RULE_DELETE: 3082 rsp = pipeline_msg_handle_table_rule_delete(p, req); 3083 break; 3084 3085 case PIPELINE_REQ_TABLE_RULE_DELETE_DEFAULT: 3086 rsp = pipeline_msg_handle_table_rule_delete_default(p, req); 3087 break; 3088 3089 case PIPELINE_REQ_TABLE_RULE_STATS_READ: 3090 rsp = pipeline_msg_handle_table_rule_stats_read(p, req); 3091 break; 3092 3093 case PIPELINE_REQ_TABLE_MTR_PROFILE_ADD: 3094 rsp = pipeline_msg_handle_table_mtr_profile_add(p, req); 3095 break; 3096 3097 case PIPELINE_REQ_TABLE_MTR_PROFILE_DELETE: 3098 rsp = pipeline_msg_handle_table_mtr_profile_delete(p, req); 3099 break; 3100 3101 case PIPELINE_REQ_TABLE_RULE_MTR_READ: 3102 rsp = pipeline_msg_handle_table_rule_mtr_read(p, req); 3103 break; 3104 3105 case PIPELINE_REQ_TABLE_DSCP_TABLE_UPDATE: 3106 rsp = pipeline_msg_handle_table_dscp_table_update(p, req); 3107 break; 3108 3109 case PIPELINE_REQ_TABLE_RULE_TTL_READ: 3110 rsp = pipeline_msg_handle_table_rule_ttl_read(p, req); 3111 break; 3112 3113 case PIPELINE_REQ_TABLE_RULE_TIME_READ: 3114 rsp = pipeline_msg_handle_table_rule_time_read(p, req); 3115 break; 3116 3117 default: 3118 rsp = (struct pipeline_msg_rsp *) req; 3119 rsp->status = -1; 3120 } 3121 3122 pipeline_msg_send(p->msgq_rsp, rsp); 3123 } 3124 } 3125 3126 /** 3127 * Data plane threads: main 3128 */ 3129 int 3130 thread_main(void *arg __rte_unused) 3131 { 3132 struct thread_data *t; 3133 uint32_t thread_id, i; 3134 3135 thread_id = rte_lcore_id(); 3136 t = &thread_data[thread_id]; 3137 3138 /* Dispatch loop */ 3139 for (i = 0; ; i++) { 3140 uint32_t j; 3141 3142 /* Data Plane */ 3143 for (j = 0; j < t->n_pipelines; j++) 3144 rte_pipeline_run(t->p[j]); 3145 3146 /* Control Plane */ 3147 if ((i & 0xF) == 0) { 3148 uint64_t time = rte_get_tsc_cycles(); 3149 uint64_t time_next_min = UINT64_MAX; 3150 3151 if (time < t->time_next_min) 3152 continue; 3153 3154 /* Pipeline message queues */ 3155 for (j = 0; j < t->n_pipelines; j++) { 3156 struct pipeline_data *p = 3157 &t->pipeline_data[j]; 3158 uint64_t time_next = p->time_next; 3159 3160 if (time_next <= time) { 3161 pipeline_msg_handle(p); 3162 rte_pipeline_flush(p->p); 3163 time_next = time + p->timer_period; 3164 p->time_next = time_next; 3165 } 3166 3167 if (time_next < time_next_min) 3168 time_next_min = time_next; 3169 } 3170 3171 /* Thread message queues */ 3172 { 3173 uint64_t time_next = t->time_next; 3174 3175 if (time_next <= time) { 3176 thread_msg_handle(t); 3177 time_next = time + t->timer_period; 3178 t->time_next = time_next; 3179 } 3180 3181 if (time_next < time_next_min) 3182 time_next_min = time_next; 3183 } 3184 3185 t->time_next_min = time_next_min; 3186 } 3187 } 3188 3189 return 0; 3190 } 3191