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