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