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