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