1b77f6600SCristian Dumitrescu /* SPDX-License-Identifier: BSD-3-Clause 2b77f6600SCristian Dumitrescu * Copyright(c) 2020 Intel Corporation 3b77f6600SCristian Dumitrescu */ 4b77f6600SCristian Dumitrescu 5b77f6600SCristian Dumitrescu #include <stdlib.h> 6b77f6600SCristian Dumitrescu 7b77f6600SCristian Dumitrescu #include <rte_common.h> 8b77f6600SCristian Dumitrescu #include <rte_cycles.h> 9b77f6600SCristian Dumitrescu #include <rte_lcore.h> 10b77f6600SCristian Dumitrescu #include <rte_ring.h> 11b77f6600SCristian Dumitrescu 12b77f6600SCristian Dumitrescu #include <rte_table_acl.h> 13b77f6600SCristian Dumitrescu #include <rte_table_array.h> 14b77f6600SCristian Dumitrescu #include <rte_table_hash.h> 15b77f6600SCristian Dumitrescu #include <rte_table_lpm.h> 16b77f6600SCristian Dumitrescu #include <rte_table_lpm_ipv6.h> 17b77f6600SCristian Dumitrescu 18b77f6600SCristian Dumitrescu #include "obj.h" 19b77f6600SCristian Dumitrescu #include "thread.h" 20b77f6600SCristian Dumitrescu 21b77f6600SCristian Dumitrescu #ifndef THREAD_PIPELINES_MAX 22b77f6600SCristian Dumitrescu #define THREAD_PIPELINES_MAX 256 23b77f6600SCristian Dumitrescu #endif 24b77f6600SCristian Dumitrescu 25b77f6600SCristian Dumitrescu #ifndef THREAD_MSGQ_SIZE 26b77f6600SCristian Dumitrescu #define THREAD_MSGQ_SIZE 64 27b77f6600SCristian Dumitrescu #endif 28b77f6600SCristian Dumitrescu 29b77f6600SCristian Dumitrescu #ifndef THREAD_TIMER_PERIOD_MS 30b77f6600SCristian Dumitrescu #define THREAD_TIMER_PERIOD_MS 100 31b77f6600SCristian Dumitrescu #endif 32b77f6600SCristian Dumitrescu 33b77f6600SCristian Dumitrescu /** 34b77f6600SCristian Dumitrescu * Control thread: data plane thread context 35b77f6600SCristian Dumitrescu */ 36b77f6600SCristian Dumitrescu struct thread { 37b77f6600SCristian Dumitrescu struct rte_ring *msgq_req; 38b77f6600SCristian Dumitrescu struct rte_ring *msgq_rsp; 39b77f6600SCristian Dumitrescu 40b77f6600SCristian Dumitrescu uint32_t enabled; 41b77f6600SCristian Dumitrescu }; 42b77f6600SCristian Dumitrescu 43b77f6600SCristian Dumitrescu static struct thread thread[RTE_MAX_LCORE]; 44b77f6600SCristian Dumitrescu 45b77f6600SCristian Dumitrescu /** 46b77f6600SCristian Dumitrescu * Data plane threads: context 47b77f6600SCristian Dumitrescu */ 48b77f6600SCristian Dumitrescu struct pipeline_data { 49b77f6600SCristian Dumitrescu struct rte_swx_pipeline *p; 50b77f6600SCristian Dumitrescu uint64_t timer_period; /* Measured in CPU cycles. */ 51b77f6600SCristian Dumitrescu uint64_t time_next; 52b77f6600SCristian Dumitrescu }; 53b77f6600SCristian Dumitrescu 54b77f6600SCristian Dumitrescu struct thread_data { 55b77f6600SCristian Dumitrescu struct rte_swx_pipeline *p[THREAD_PIPELINES_MAX]; 56b77f6600SCristian Dumitrescu uint32_t n_pipelines; 57b77f6600SCristian Dumitrescu 58b77f6600SCristian Dumitrescu struct pipeline_data pipeline_data[THREAD_PIPELINES_MAX]; 59b77f6600SCristian Dumitrescu struct rte_ring *msgq_req; 60b77f6600SCristian Dumitrescu struct rte_ring *msgq_rsp; 61b77f6600SCristian Dumitrescu uint64_t timer_period; /* Measured in CPU cycles. */ 62b77f6600SCristian Dumitrescu uint64_t time_next; 63b77f6600SCristian Dumitrescu uint64_t time_next_min; 64b77f6600SCristian Dumitrescu } __rte_cache_aligned; 65b77f6600SCristian Dumitrescu 66b77f6600SCristian Dumitrescu static struct thread_data thread_data[RTE_MAX_LCORE]; 67b77f6600SCristian Dumitrescu 68b77f6600SCristian Dumitrescu /** 69b77f6600SCristian Dumitrescu * Control thread: data plane thread init 70b77f6600SCristian Dumitrescu */ 71b77f6600SCristian Dumitrescu static void 72b77f6600SCristian Dumitrescu thread_free(void) 73b77f6600SCristian Dumitrescu { 74b77f6600SCristian Dumitrescu uint32_t i; 75b77f6600SCristian Dumitrescu 76b77f6600SCristian Dumitrescu for (i = 0; i < RTE_MAX_LCORE; i++) { 77b77f6600SCristian Dumitrescu struct thread *t = &thread[i]; 78b77f6600SCristian Dumitrescu 79b77f6600SCristian Dumitrescu if (!rte_lcore_is_enabled(i)) 80b77f6600SCristian Dumitrescu continue; 81b77f6600SCristian Dumitrescu 82b77f6600SCristian Dumitrescu /* MSGQs */ 83b77f6600SCristian Dumitrescu if (t->msgq_req) 84b77f6600SCristian Dumitrescu rte_ring_free(t->msgq_req); 85b77f6600SCristian Dumitrescu 86b77f6600SCristian Dumitrescu if (t->msgq_rsp) 87b77f6600SCristian Dumitrescu rte_ring_free(t->msgq_rsp); 88b77f6600SCristian Dumitrescu } 89b77f6600SCristian Dumitrescu } 90b77f6600SCristian Dumitrescu 91b77f6600SCristian Dumitrescu int 92b77f6600SCristian Dumitrescu thread_init(void) 93b77f6600SCristian Dumitrescu { 94b77f6600SCristian Dumitrescu uint32_t i; 95b77f6600SCristian Dumitrescu 96*cb056611SStephen Hemminger RTE_LCORE_FOREACH_WORKER(i) { 97b77f6600SCristian Dumitrescu char name[NAME_MAX]; 98b77f6600SCristian Dumitrescu struct rte_ring *msgq_req, *msgq_rsp; 99b77f6600SCristian Dumitrescu struct thread *t = &thread[i]; 100b77f6600SCristian Dumitrescu struct thread_data *t_data = &thread_data[i]; 101b77f6600SCristian Dumitrescu uint32_t cpu_id = rte_lcore_to_socket_id(i); 102b77f6600SCristian Dumitrescu 103b77f6600SCristian Dumitrescu /* MSGQs */ 104b77f6600SCristian Dumitrescu snprintf(name, sizeof(name), "THREAD-%04x-MSGQ-REQ", i); 105b77f6600SCristian Dumitrescu 106b77f6600SCristian Dumitrescu msgq_req = rte_ring_create(name, 107b77f6600SCristian Dumitrescu THREAD_MSGQ_SIZE, 108b77f6600SCristian Dumitrescu cpu_id, 109b77f6600SCristian Dumitrescu RING_F_SP_ENQ | RING_F_SC_DEQ); 110b77f6600SCristian Dumitrescu 111b77f6600SCristian Dumitrescu if (msgq_req == NULL) { 112b77f6600SCristian Dumitrescu thread_free(); 113b77f6600SCristian Dumitrescu return -1; 114b77f6600SCristian Dumitrescu } 115b77f6600SCristian Dumitrescu 116b77f6600SCristian Dumitrescu snprintf(name, sizeof(name), "THREAD-%04x-MSGQ-RSP", i); 117b77f6600SCristian Dumitrescu 118b77f6600SCristian Dumitrescu msgq_rsp = rte_ring_create(name, 119b77f6600SCristian Dumitrescu THREAD_MSGQ_SIZE, 120b77f6600SCristian Dumitrescu cpu_id, 121b77f6600SCristian Dumitrescu RING_F_SP_ENQ | RING_F_SC_DEQ); 122b77f6600SCristian Dumitrescu 123b77f6600SCristian Dumitrescu if (msgq_rsp == NULL) { 124b77f6600SCristian Dumitrescu thread_free(); 125b77f6600SCristian Dumitrescu return -1; 126b77f6600SCristian Dumitrescu } 127b77f6600SCristian Dumitrescu 128b77f6600SCristian Dumitrescu /* Control thread records */ 129b77f6600SCristian Dumitrescu t->msgq_req = msgq_req; 130b77f6600SCristian Dumitrescu t->msgq_rsp = msgq_rsp; 131b77f6600SCristian Dumitrescu t->enabled = 1; 132b77f6600SCristian Dumitrescu 133b77f6600SCristian Dumitrescu /* Data plane thread records */ 134b77f6600SCristian Dumitrescu t_data->n_pipelines = 0; 135b77f6600SCristian Dumitrescu t_data->msgq_req = msgq_req; 136b77f6600SCristian Dumitrescu t_data->msgq_rsp = msgq_rsp; 137b77f6600SCristian Dumitrescu t_data->timer_period = 138b77f6600SCristian Dumitrescu (rte_get_tsc_hz() * THREAD_TIMER_PERIOD_MS) / 1000; 139b77f6600SCristian Dumitrescu t_data->time_next = rte_get_tsc_cycles() + t_data->timer_period; 140b77f6600SCristian Dumitrescu t_data->time_next_min = t_data->time_next; 141b77f6600SCristian Dumitrescu } 142b77f6600SCristian Dumitrescu 143b77f6600SCristian Dumitrescu return 0; 144b77f6600SCristian Dumitrescu } 145b77f6600SCristian Dumitrescu 146b77f6600SCristian Dumitrescu static inline int 147b77f6600SCristian Dumitrescu thread_is_running(uint32_t thread_id) 148b77f6600SCristian Dumitrescu { 149b77f6600SCristian Dumitrescu enum rte_lcore_state_t thread_state; 150b77f6600SCristian Dumitrescu 151b77f6600SCristian Dumitrescu thread_state = rte_eal_get_lcore_state(thread_id); 152b77f6600SCristian Dumitrescu return (thread_state == RUNNING) ? 1 : 0; 153b77f6600SCristian Dumitrescu } 154b77f6600SCristian Dumitrescu 155b77f6600SCristian Dumitrescu /** 156b77f6600SCristian Dumitrescu * Control thread & data plane threads: message passing 157b77f6600SCristian Dumitrescu */ 158b77f6600SCristian Dumitrescu enum thread_req_type { 159b77f6600SCristian Dumitrescu THREAD_REQ_PIPELINE_ENABLE = 0, 160b77f6600SCristian Dumitrescu THREAD_REQ_PIPELINE_DISABLE, 161b77f6600SCristian Dumitrescu THREAD_REQ_MAX 162b77f6600SCristian Dumitrescu }; 163b77f6600SCristian Dumitrescu 164b77f6600SCristian Dumitrescu struct thread_msg_req { 165b77f6600SCristian Dumitrescu enum thread_req_type type; 166b77f6600SCristian Dumitrescu 167b77f6600SCristian Dumitrescu union { 168b77f6600SCristian Dumitrescu struct { 169b77f6600SCristian Dumitrescu struct rte_swx_pipeline *p; 170b77f6600SCristian Dumitrescu uint32_t timer_period_ms; 171b77f6600SCristian Dumitrescu } pipeline_enable; 172b77f6600SCristian Dumitrescu 173b77f6600SCristian Dumitrescu struct { 174b77f6600SCristian Dumitrescu struct rte_swx_pipeline *p; 175b77f6600SCristian Dumitrescu } pipeline_disable; 176b77f6600SCristian Dumitrescu }; 177b77f6600SCristian Dumitrescu }; 178b77f6600SCristian Dumitrescu 179b77f6600SCristian Dumitrescu struct thread_msg_rsp { 180b77f6600SCristian Dumitrescu int status; 181b77f6600SCristian Dumitrescu }; 182b77f6600SCristian Dumitrescu 183b77f6600SCristian Dumitrescu /** 184b77f6600SCristian Dumitrescu * Control thread 185b77f6600SCristian Dumitrescu */ 186b77f6600SCristian Dumitrescu static struct thread_msg_req * 187b77f6600SCristian Dumitrescu thread_msg_alloc(void) 188b77f6600SCristian Dumitrescu { 189b77f6600SCristian Dumitrescu size_t size = RTE_MAX(sizeof(struct thread_msg_req), 190b77f6600SCristian Dumitrescu sizeof(struct thread_msg_rsp)); 191b77f6600SCristian Dumitrescu 192b77f6600SCristian Dumitrescu return calloc(1, size); 193b77f6600SCristian Dumitrescu } 194b77f6600SCristian Dumitrescu 195b77f6600SCristian Dumitrescu static void 196b77f6600SCristian Dumitrescu thread_msg_free(struct thread_msg_rsp *rsp) 197b77f6600SCristian Dumitrescu { 198b77f6600SCristian Dumitrescu free(rsp); 199b77f6600SCristian Dumitrescu } 200b77f6600SCristian Dumitrescu 201b77f6600SCristian Dumitrescu static struct thread_msg_rsp * 202b77f6600SCristian Dumitrescu thread_msg_send_recv(uint32_t thread_id, 203b77f6600SCristian Dumitrescu struct thread_msg_req *req) 204b77f6600SCristian Dumitrescu { 205b77f6600SCristian Dumitrescu struct thread *t = &thread[thread_id]; 206b77f6600SCristian Dumitrescu struct rte_ring *msgq_req = t->msgq_req; 207b77f6600SCristian Dumitrescu struct rte_ring *msgq_rsp = t->msgq_rsp; 208b77f6600SCristian Dumitrescu struct thread_msg_rsp *rsp; 209b77f6600SCristian Dumitrescu int status; 210b77f6600SCristian Dumitrescu 211b77f6600SCristian Dumitrescu /* send */ 212b77f6600SCristian Dumitrescu do { 213b77f6600SCristian Dumitrescu status = rte_ring_sp_enqueue(msgq_req, req); 214b77f6600SCristian Dumitrescu } while (status == -ENOBUFS); 215b77f6600SCristian Dumitrescu 216b77f6600SCristian Dumitrescu /* recv */ 217b77f6600SCristian Dumitrescu do { 218b77f6600SCristian Dumitrescu status = rte_ring_sc_dequeue(msgq_rsp, (void **) &rsp); 219b77f6600SCristian Dumitrescu } while (status != 0); 220b77f6600SCristian Dumitrescu 221b77f6600SCristian Dumitrescu return rsp; 222b77f6600SCristian Dumitrescu } 223b77f6600SCristian Dumitrescu 224b77f6600SCristian Dumitrescu int 225b77f6600SCristian Dumitrescu thread_pipeline_enable(uint32_t thread_id, 226b77f6600SCristian Dumitrescu struct obj *obj, 227b77f6600SCristian Dumitrescu const char *pipeline_name) 228b77f6600SCristian Dumitrescu { 229b77f6600SCristian Dumitrescu struct pipeline *p = pipeline_find(obj, pipeline_name); 230b77f6600SCristian Dumitrescu struct thread *t; 231b77f6600SCristian Dumitrescu struct thread_msg_req *req; 232b77f6600SCristian Dumitrescu struct thread_msg_rsp *rsp; 233b77f6600SCristian Dumitrescu int status; 234b77f6600SCristian Dumitrescu 235b77f6600SCristian Dumitrescu /* Check input params */ 236b77f6600SCristian Dumitrescu if ((thread_id >= RTE_MAX_LCORE) || 237b77f6600SCristian Dumitrescu (p == NULL)) 238b77f6600SCristian Dumitrescu return -1; 239b77f6600SCristian Dumitrescu 240b77f6600SCristian Dumitrescu t = &thread[thread_id]; 241b77f6600SCristian Dumitrescu if (t->enabled == 0) 242b77f6600SCristian Dumitrescu return -1; 243b77f6600SCristian Dumitrescu 244b77f6600SCristian Dumitrescu if (!thread_is_running(thread_id)) { 245b77f6600SCristian Dumitrescu struct thread_data *td = &thread_data[thread_id]; 246b77f6600SCristian Dumitrescu struct pipeline_data *tdp = &td->pipeline_data[td->n_pipelines]; 247b77f6600SCristian Dumitrescu 248b77f6600SCristian Dumitrescu if (td->n_pipelines >= THREAD_PIPELINES_MAX) 249b77f6600SCristian Dumitrescu return -1; 250b77f6600SCristian Dumitrescu 251b77f6600SCristian Dumitrescu /* Data plane thread */ 252b77f6600SCristian Dumitrescu td->p[td->n_pipelines] = p->p; 253b77f6600SCristian Dumitrescu 254b77f6600SCristian Dumitrescu tdp->p = p->p; 255b77f6600SCristian Dumitrescu tdp->timer_period = 256b77f6600SCristian Dumitrescu (rte_get_tsc_hz() * p->timer_period_ms) / 1000; 257b77f6600SCristian Dumitrescu tdp->time_next = rte_get_tsc_cycles() + tdp->timer_period; 258b77f6600SCristian Dumitrescu 259b77f6600SCristian Dumitrescu td->n_pipelines++; 260b77f6600SCristian Dumitrescu 261b77f6600SCristian Dumitrescu /* Pipeline */ 262b77f6600SCristian Dumitrescu p->thread_id = thread_id; 263b77f6600SCristian Dumitrescu p->enabled = 1; 264b77f6600SCristian Dumitrescu 265b77f6600SCristian Dumitrescu return 0; 266b77f6600SCristian Dumitrescu } 267b77f6600SCristian Dumitrescu 268b77f6600SCristian Dumitrescu /* Allocate request */ 269b77f6600SCristian Dumitrescu req = thread_msg_alloc(); 270b77f6600SCristian Dumitrescu if (req == NULL) 271b77f6600SCristian Dumitrescu return -1; 272b77f6600SCristian Dumitrescu 273b77f6600SCristian Dumitrescu /* Write request */ 274b77f6600SCristian Dumitrescu req->type = THREAD_REQ_PIPELINE_ENABLE; 275b77f6600SCristian Dumitrescu req->pipeline_enable.p = p->p; 276b77f6600SCristian Dumitrescu req->pipeline_enable.timer_period_ms = p->timer_period_ms; 277b77f6600SCristian Dumitrescu 278b77f6600SCristian Dumitrescu /* Send request and wait for response */ 279b77f6600SCristian Dumitrescu rsp = thread_msg_send_recv(thread_id, req); 280b77f6600SCristian Dumitrescu 281b77f6600SCristian Dumitrescu /* Read response */ 282b77f6600SCristian Dumitrescu status = rsp->status; 283b77f6600SCristian Dumitrescu 284b77f6600SCristian Dumitrescu /* Free response */ 285b77f6600SCristian Dumitrescu thread_msg_free(rsp); 286b77f6600SCristian Dumitrescu 287b77f6600SCristian Dumitrescu /* Request completion */ 288b77f6600SCristian Dumitrescu if (status) 289b77f6600SCristian Dumitrescu return status; 290b77f6600SCristian Dumitrescu 291b77f6600SCristian Dumitrescu p->thread_id = thread_id; 292b77f6600SCristian Dumitrescu p->enabled = 1; 293b77f6600SCristian Dumitrescu 294b77f6600SCristian Dumitrescu return 0; 295b77f6600SCristian Dumitrescu } 296b77f6600SCristian Dumitrescu 297b77f6600SCristian Dumitrescu int 298b77f6600SCristian Dumitrescu thread_pipeline_disable(uint32_t thread_id, 299b77f6600SCristian Dumitrescu struct obj *obj, 300b77f6600SCristian Dumitrescu const char *pipeline_name) 301b77f6600SCristian Dumitrescu { 302b77f6600SCristian Dumitrescu struct pipeline *p = pipeline_find(obj, pipeline_name); 303b77f6600SCristian Dumitrescu struct thread *t; 304b77f6600SCristian Dumitrescu struct thread_msg_req *req; 305b77f6600SCristian Dumitrescu struct thread_msg_rsp *rsp; 306b77f6600SCristian Dumitrescu int status; 307b77f6600SCristian Dumitrescu 308b77f6600SCristian Dumitrescu /* Check input params */ 309b77f6600SCristian Dumitrescu if ((thread_id >= RTE_MAX_LCORE) || 310b77f6600SCristian Dumitrescu (p == NULL)) 311b77f6600SCristian Dumitrescu return -1; 312b77f6600SCristian Dumitrescu 313b77f6600SCristian Dumitrescu t = &thread[thread_id]; 314b77f6600SCristian Dumitrescu if (t->enabled == 0) 315b77f6600SCristian Dumitrescu return -1; 316b77f6600SCristian Dumitrescu 317b77f6600SCristian Dumitrescu if (p->enabled == 0) 318b77f6600SCristian Dumitrescu return 0; 319b77f6600SCristian Dumitrescu 320b77f6600SCristian Dumitrescu if (p->thread_id != thread_id) 321b77f6600SCristian Dumitrescu return -1; 322b77f6600SCristian Dumitrescu 323b77f6600SCristian Dumitrescu if (!thread_is_running(thread_id)) { 324b77f6600SCristian Dumitrescu struct thread_data *td = &thread_data[thread_id]; 325b77f6600SCristian Dumitrescu uint32_t i; 326b77f6600SCristian Dumitrescu 327b77f6600SCristian Dumitrescu for (i = 0; i < td->n_pipelines; i++) { 328b77f6600SCristian Dumitrescu struct pipeline_data *tdp = &td->pipeline_data[i]; 329b77f6600SCristian Dumitrescu 330b77f6600SCristian Dumitrescu if (tdp->p != p->p) 331b77f6600SCristian Dumitrescu continue; 332b77f6600SCristian Dumitrescu 333b77f6600SCristian Dumitrescu /* Data plane thread */ 334b77f6600SCristian Dumitrescu if (i < td->n_pipelines - 1) { 335b77f6600SCristian Dumitrescu struct rte_swx_pipeline *pipeline_last = 336b77f6600SCristian Dumitrescu td->p[td->n_pipelines - 1]; 337b77f6600SCristian Dumitrescu struct pipeline_data *tdp_last = 338b77f6600SCristian Dumitrescu &td->pipeline_data[td->n_pipelines - 1]; 339b77f6600SCristian Dumitrescu 340b77f6600SCristian Dumitrescu td->p[i] = pipeline_last; 341b77f6600SCristian Dumitrescu memcpy(tdp, tdp_last, sizeof(*tdp)); 342b77f6600SCristian Dumitrescu } 343b77f6600SCristian Dumitrescu 344b77f6600SCristian Dumitrescu td->n_pipelines--; 345b77f6600SCristian Dumitrescu 346b77f6600SCristian Dumitrescu /* Pipeline */ 347b77f6600SCristian Dumitrescu p->enabled = 0; 348b77f6600SCristian Dumitrescu 349b77f6600SCristian Dumitrescu break; 350b77f6600SCristian Dumitrescu } 351b77f6600SCristian Dumitrescu 352b77f6600SCristian Dumitrescu return 0; 353b77f6600SCristian Dumitrescu } 354b77f6600SCristian Dumitrescu 355b77f6600SCristian Dumitrescu /* Allocate request */ 356b77f6600SCristian Dumitrescu req = thread_msg_alloc(); 357b77f6600SCristian Dumitrescu if (req == NULL) 358b77f6600SCristian Dumitrescu return -1; 359b77f6600SCristian Dumitrescu 360b77f6600SCristian Dumitrescu /* Write request */ 361b77f6600SCristian Dumitrescu req->type = THREAD_REQ_PIPELINE_DISABLE; 362b77f6600SCristian Dumitrescu req->pipeline_disable.p = p->p; 363b77f6600SCristian Dumitrescu 364b77f6600SCristian Dumitrescu /* Send request and wait for response */ 365b77f6600SCristian Dumitrescu rsp = thread_msg_send_recv(thread_id, req); 366b77f6600SCristian Dumitrescu 367b77f6600SCristian Dumitrescu /* Read response */ 368b77f6600SCristian Dumitrescu status = rsp->status; 369b77f6600SCristian Dumitrescu 370b77f6600SCristian Dumitrescu /* Free response */ 371b77f6600SCristian Dumitrescu thread_msg_free(rsp); 372b77f6600SCristian Dumitrescu 373b77f6600SCristian Dumitrescu /* Request completion */ 374b77f6600SCristian Dumitrescu if (status) 375b77f6600SCristian Dumitrescu return status; 376b77f6600SCristian Dumitrescu 377b77f6600SCristian Dumitrescu p->enabled = 0; 378b77f6600SCristian Dumitrescu 379b77f6600SCristian Dumitrescu return 0; 380b77f6600SCristian Dumitrescu } 381b77f6600SCristian Dumitrescu 382b77f6600SCristian Dumitrescu /** 383b77f6600SCristian Dumitrescu * Data plane threads: message handling 384b77f6600SCristian Dumitrescu */ 385b77f6600SCristian Dumitrescu static inline struct thread_msg_req * 386b77f6600SCristian Dumitrescu thread_msg_recv(struct rte_ring *msgq_req) 387b77f6600SCristian Dumitrescu { 388b77f6600SCristian Dumitrescu struct thread_msg_req *req; 389b77f6600SCristian Dumitrescu 390b77f6600SCristian Dumitrescu int status = rte_ring_sc_dequeue(msgq_req, (void **) &req); 391b77f6600SCristian Dumitrescu 392b77f6600SCristian Dumitrescu if (status != 0) 393b77f6600SCristian Dumitrescu return NULL; 394b77f6600SCristian Dumitrescu 395b77f6600SCristian Dumitrescu return req; 396b77f6600SCristian Dumitrescu } 397b77f6600SCristian Dumitrescu 398b77f6600SCristian Dumitrescu static inline void 399b77f6600SCristian Dumitrescu thread_msg_send(struct rte_ring *msgq_rsp, 400b77f6600SCristian Dumitrescu struct thread_msg_rsp *rsp) 401b77f6600SCristian Dumitrescu { 402b77f6600SCristian Dumitrescu int status; 403b77f6600SCristian Dumitrescu 404b77f6600SCristian Dumitrescu do { 405b77f6600SCristian Dumitrescu status = rte_ring_sp_enqueue(msgq_rsp, rsp); 406b77f6600SCristian Dumitrescu } while (status == -ENOBUFS); 407b77f6600SCristian Dumitrescu } 408b77f6600SCristian Dumitrescu 409b77f6600SCristian Dumitrescu static struct thread_msg_rsp * 410b77f6600SCristian Dumitrescu thread_msg_handle_pipeline_enable(struct thread_data *t, 411b77f6600SCristian Dumitrescu struct thread_msg_req *req) 412b77f6600SCristian Dumitrescu { 413b77f6600SCristian Dumitrescu struct thread_msg_rsp *rsp = (struct thread_msg_rsp *) req; 414b77f6600SCristian Dumitrescu struct pipeline_data *p = &t->pipeline_data[t->n_pipelines]; 415b77f6600SCristian Dumitrescu 416b77f6600SCristian Dumitrescu /* Request */ 417b77f6600SCristian Dumitrescu if (t->n_pipelines >= THREAD_PIPELINES_MAX) { 418b77f6600SCristian Dumitrescu rsp->status = -1; 419b77f6600SCristian Dumitrescu return rsp; 420b77f6600SCristian Dumitrescu } 421b77f6600SCristian Dumitrescu 422b77f6600SCristian Dumitrescu t->p[t->n_pipelines] = req->pipeline_enable.p; 423b77f6600SCristian Dumitrescu 424b77f6600SCristian Dumitrescu p->p = req->pipeline_enable.p; 425b77f6600SCristian Dumitrescu p->timer_period = (rte_get_tsc_hz() * 426b77f6600SCristian Dumitrescu req->pipeline_enable.timer_period_ms) / 1000; 427b77f6600SCristian Dumitrescu p->time_next = rte_get_tsc_cycles() + p->timer_period; 428b77f6600SCristian Dumitrescu 429b77f6600SCristian Dumitrescu t->n_pipelines++; 430b77f6600SCristian Dumitrescu 431b77f6600SCristian Dumitrescu /* Response */ 432b77f6600SCristian Dumitrescu rsp->status = 0; 433b77f6600SCristian Dumitrescu return rsp; 434b77f6600SCristian Dumitrescu } 435b77f6600SCristian Dumitrescu 436b77f6600SCristian Dumitrescu static struct thread_msg_rsp * 437b77f6600SCristian Dumitrescu thread_msg_handle_pipeline_disable(struct thread_data *t, 438b77f6600SCristian Dumitrescu struct thread_msg_req *req) 439b77f6600SCristian Dumitrescu { 440b77f6600SCristian Dumitrescu struct thread_msg_rsp *rsp = (struct thread_msg_rsp *) req; 441b77f6600SCristian Dumitrescu uint32_t n_pipelines = t->n_pipelines; 442b77f6600SCristian Dumitrescu struct rte_swx_pipeline *pipeline = req->pipeline_disable.p; 443b77f6600SCristian Dumitrescu uint32_t i; 444b77f6600SCristian Dumitrescu 445b77f6600SCristian Dumitrescu /* find pipeline */ 446b77f6600SCristian Dumitrescu for (i = 0; i < n_pipelines; i++) { 447b77f6600SCristian Dumitrescu struct pipeline_data *p = &t->pipeline_data[i]; 448b77f6600SCristian Dumitrescu 449b77f6600SCristian Dumitrescu if (p->p != pipeline) 450b77f6600SCristian Dumitrescu continue; 451b77f6600SCristian Dumitrescu 452b77f6600SCristian Dumitrescu if (i < n_pipelines - 1) { 453b77f6600SCristian Dumitrescu struct rte_swx_pipeline *pipeline_last = 454b77f6600SCristian Dumitrescu t->p[n_pipelines - 1]; 455b77f6600SCristian Dumitrescu struct pipeline_data *p_last = 456b77f6600SCristian Dumitrescu &t->pipeline_data[n_pipelines - 1]; 457b77f6600SCristian Dumitrescu 458b77f6600SCristian Dumitrescu t->p[i] = pipeline_last; 459b77f6600SCristian Dumitrescu memcpy(p, p_last, sizeof(*p)); 460b77f6600SCristian Dumitrescu } 461b77f6600SCristian Dumitrescu 462b77f6600SCristian Dumitrescu t->n_pipelines--; 463b77f6600SCristian Dumitrescu 464b77f6600SCristian Dumitrescu rsp->status = 0; 465b77f6600SCristian Dumitrescu return rsp; 466b77f6600SCristian Dumitrescu } 467b77f6600SCristian Dumitrescu 468b77f6600SCristian Dumitrescu /* should not get here */ 469b77f6600SCristian Dumitrescu rsp->status = 0; 470b77f6600SCristian Dumitrescu return rsp; 471b77f6600SCristian Dumitrescu } 472b77f6600SCristian Dumitrescu 473b77f6600SCristian Dumitrescu static void 474b77f6600SCristian Dumitrescu thread_msg_handle(struct thread_data *t) 475b77f6600SCristian Dumitrescu { 476b77f6600SCristian Dumitrescu for ( ; ; ) { 477b77f6600SCristian Dumitrescu struct thread_msg_req *req; 478b77f6600SCristian Dumitrescu struct thread_msg_rsp *rsp; 479b77f6600SCristian Dumitrescu 480b77f6600SCristian Dumitrescu req = thread_msg_recv(t->msgq_req); 481b77f6600SCristian Dumitrescu if (req == NULL) 482b77f6600SCristian Dumitrescu break; 483b77f6600SCristian Dumitrescu 484b77f6600SCristian Dumitrescu switch (req->type) { 485b77f6600SCristian Dumitrescu case THREAD_REQ_PIPELINE_ENABLE: 486b77f6600SCristian Dumitrescu rsp = thread_msg_handle_pipeline_enable(t, req); 487b77f6600SCristian Dumitrescu break; 488b77f6600SCristian Dumitrescu 489b77f6600SCristian Dumitrescu case THREAD_REQ_PIPELINE_DISABLE: 490b77f6600SCristian Dumitrescu rsp = thread_msg_handle_pipeline_disable(t, req); 491b77f6600SCristian Dumitrescu break; 492b77f6600SCristian Dumitrescu 493b77f6600SCristian Dumitrescu default: 494b77f6600SCristian Dumitrescu rsp = (struct thread_msg_rsp *) req; 495b77f6600SCristian Dumitrescu rsp->status = -1; 496b77f6600SCristian Dumitrescu } 497b77f6600SCristian Dumitrescu 498b77f6600SCristian Dumitrescu thread_msg_send(t->msgq_rsp, rsp); 499b77f6600SCristian Dumitrescu } 500b77f6600SCristian Dumitrescu } 501b77f6600SCristian Dumitrescu 502b77f6600SCristian Dumitrescu /** 503b77f6600SCristian Dumitrescu * Data plane threads: main 504b77f6600SCristian Dumitrescu */ 505b77f6600SCristian Dumitrescu int 506b77f6600SCristian Dumitrescu thread_main(void *arg __rte_unused) 507b77f6600SCristian Dumitrescu { 508b77f6600SCristian Dumitrescu struct thread_data *t; 509b77f6600SCristian Dumitrescu uint32_t thread_id, i; 510b77f6600SCristian Dumitrescu 511b77f6600SCristian Dumitrescu thread_id = rte_lcore_id(); 512b77f6600SCristian Dumitrescu t = &thread_data[thread_id]; 513b77f6600SCristian Dumitrescu 514b77f6600SCristian Dumitrescu /* Dispatch loop */ 515b77f6600SCristian Dumitrescu for (i = 0; ; i++) { 516b77f6600SCristian Dumitrescu uint32_t j; 517b77f6600SCristian Dumitrescu 518b77f6600SCristian Dumitrescu /* Data Plane */ 519b77f6600SCristian Dumitrescu for (j = 0; j < t->n_pipelines; j++) 520b77f6600SCristian Dumitrescu rte_swx_pipeline_run(t->p[j], 1000000); 521b77f6600SCristian Dumitrescu 522b77f6600SCristian Dumitrescu /* Control Plane */ 523b77f6600SCristian Dumitrescu if ((i & 0xF) == 0) { 524b77f6600SCristian Dumitrescu uint64_t time = rte_get_tsc_cycles(); 525b77f6600SCristian Dumitrescu uint64_t time_next_min = UINT64_MAX; 526b77f6600SCristian Dumitrescu 527b77f6600SCristian Dumitrescu if (time < t->time_next_min) 528b77f6600SCristian Dumitrescu continue; 529b77f6600SCristian Dumitrescu 530b77f6600SCristian Dumitrescu /* Thread message queues */ 531b77f6600SCristian Dumitrescu { 532b77f6600SCristian Dumitrescu uint64_t time_next = t->time_next; 533b77f6600SCristian Dumitrescu 534b77f6600SCristian Dumitrescu if (time_next <= time) { 535b77f6600SCristian Dumitrescu thread_msg_handle(t); 536b77f6600SCristian Dumitrescu time_next = time + t->timer_period; 537b77f6600SCristian Dumitrescu t->time_next = time_next; 538b77f6600SCristian Dumitrescu } 539b77f6600SCristian Dumitrescu 540b77f6600SCristian Dumitrescu if (time_next < time_next_min) 541b77f6600SCristian Dumitrescu time_next_min = time_next; 542b77f6600SCristian Dumitrescu } 543b77f6600SCristian Dumitrescu 544b77f6600SCristian Dumitrescu t->time_next_min = time_next_min; 545b77f6600SCristian Dumitrescu } 546b77f6600SCristian Dumitrescu } 547b77f6600SCristian Dumitrescu 548b77f6600SCristian Dumitrescu return 0; 549b77f6600SCristian Dumitrescu } 550