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