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