From: Cristian Dumitrescu Date: Mon, 13 Sep 2021 16:44:36 +0000 (+0100) Subject: pipeline: introduce action functions X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=5dc6a5f2e7eb20bdab82068f0e2d01331ca703a2;p=dpdk.git pipeline: introduce action functions For better performance, the option to run a single function per action is now provided, which requires a single function call per action that can be better optimized by the C compiler, as opposed to one function call per instruction. Special table lookup instructions are added to to support this feature. Signed-off-by: Cristian Dumitrescu --- diff --git a/lib/pipeline/rte_swx_pipeline.c b/lib/pipeline/rte_swx_pipeline.c index 4099e364f5..0d02548137 100644 --- a/lib/pipeline/rte_swx_pipeline.c +++ b/lib/pipeline/rte_swx_pipeline.c @@ -2097,6 +2097,62 @@ instr_table_exec(struct rte_swx_pipeline *p) thread_ip_action_call(p, t, action_id); } +static inline void +instr_table_af_exec(struct rte_swx_pipeline *p) +{ + struct thread *t = &p->threads[p->thread_id]; + struct instruction *ip = t->ip; + uint32_t table_id = ip->table.table_id; + struct rte_swx_table_state *ts = &t->table_state[table_id]; + struct table_runtime *table = &t->tables[table_id]; + struct table_statistics *stats = &p->table_stats[table_id]; + uint64_t action_id, n_pkts_hit, n_pkts_action; + uint8_t *action_data; + action_func_t action_func; + int done, hit; + + /* Table. */ + done = table->func(ts->obj, + table->mailbox, + table->key, + &action_id, + &action_data, + &hit); + if (!done) { + /* Thread. */ + TRACE("[Thread %2u] table %u (not finalized)\n", + p->thread_id, + table_id); + + thread_yield(p); + return; + } + + action_id = hit ? action_id : ts->default_action_id; + action_data = hit ? action_data : ts->default_action_data; + action_func = p->action_funcs[action_id]; + n_pkts_hit = stats->n_pkts_hit[hit]; + n_pkts_action = stats->n_pkts_action[action_id]; + + TRACE("[Thread %2u] table %u (%s, action %u)\n", + p->thread_id, + table_id, + hit ? "hit" : "miss", + (uint32_t)action_id); + + t->action_id = action_id; + t->structs[0] = action_data; + t->hit = hit; + stats->n_pkts_hit[hit] = n_pkts_hit + 1; + stats->n_pkts_action[action_id] = n_pkts_action + 1; + + /* Thread. */ + thread_ip_inc(p); + + /* Action. */ + action_func(p); +} + static inline void instr_selector_exec(struct rte_swx_pipeline *p) { @@ -2193,6 +2249,68 @@ instr_learner_exec(struct rte_swx_pipeline *p) thread_ip_action_call(p, t, action_id); } +static inline void +instr_learner_af_exec(struct rte_swx_pipeline *p) +{ + struct thread *t = &p->threads[p->thread_id]; + struct instruction *ip = t->ip; + uint32_t learner_id = ip->table.table_id; + struct rte_swx_table_state *ts = &t->table_state[p->n_tables + + p->n_selectors + learner_id]; + struct learner_runtime *l = &t->learners[learner_id]; + struct learner_statistics *stats = &p->learner_stats[learner_id]; + uint64_t action_id, n_pkts_hit, n_pkts_action, time; + uint8_t *action_data; + action_func_t action_func; + int done, hit; + + /* Table. */ + time = rte_get_tsc_cycles(); + + done = rte_swx_table_learner_lookup(ts->obj, + l->mailbox, + time, + l->key, + &action_id, + &action_data, + &hit); + if (!done) { + /* Thread. */ + TRACE("[Thread %2u] learner %u (not finalized)\n", + p->thread_id, + learner_id); + + thread_yield(p); + return; + } + + action_id = hit ? action_id : ts->default_action_id; + action_data = hit ? action_data : ts->default_action_data; + action_func = p->action_funcs[action_id]; + n_pkts_hit = stats->n_pkts_hit[hit]; + n_pkts_action = stats->n_pkts_action[action_id]; + + TRACE("[Thread %2u] learner %u (%s, action %u)\n", + p->thread_id, + learner_id, + hit ? "hit" : "miss", + (uint32_t)action_id); + + t->action_id = action_id; + t->structs[0] = action_data; + t->hit = hit; + t->learner_id = learner_id; + t->time = time; + stats->n_pkts_hit[hit] = n_pkts_hit + 1; + stats->n_pkts_action[action_id] = n_pkts_action + 1; + + /* Thread. */ + thread_ip_action_call(p, t, action_id); + + /* Action */ + action_func(p); +} + /* * learn. */ @@ -6618,8 +6736,10 @@ static instr_exec_t instruction_table[] = { [INSTR_METER_IMI] = instr_meter_imi_exec, [INSTR_TABLE] = instr_table_exec, + [INSTR_TABLE_AF] = instr_table_af_exec, [INSTR_SELECTOR] = instr_selector_exec, [INSTR_LEARNER] = instr_learner_exec, + [INSTR_LEARNER_AF] = instr_learner_af_exec, [INSTR_LEARNER_LEARN] = instr_learn_exec, [INSTR_LEARNER_FORGET] = instr_forget_exec, [INSTR_EXTERN_OBJ] = instr_extern_obj_exec, @@ -6819,12 +6939,19 @@ action_build(struct rte_swx_pipeline *p) TAILQ_FOREACH(action, &p->actions, node) p->action_instructions[action->id] = action->instructions; + /* p->action_funcs. */ + p->action_funcs = calloc(p->n_actions, sizeof(action_func_t)); + CHECK(p->action_funcs, ENOMEM); + return 0; } static void action_build_free(struct rte_swx_pipeline *p) { + free(p->action_funcs); + p->action_funcs = NULL; + free(p->action_instructions); p->action_instructions = NULL; } diff --git a/lib/pipeline/rte_swx_pipeline_internal.h b/lib/pipeline/rte_swx_pipeline_internal.h index 7a02d6cb5f..3578a10501 100644 --- a/lib/pipeline/rte_swx_pipeline_internal.h +++ b/lib/pipeline/rte_swx_pipeline_internal.h @@ -443,8 +443,10 @@ enum instruction_type { /* table TABLE */ INSTR_TABLE, + INSTR_TABLE_AF, INSTR_SELECTOR, INSTR_LEARNER, + INSTR_LEARNER_AF, /* learn LEARNER ACTION_NAME */ INSTR_LEARNER_LEARN, @@ -687,6 +689,9 @@ struct instruction_data { /* * Action. */ +typedef void +(*action_func_t)(struct rte_swx_pipeline *p); + struct action { TAILQ_ENTRY(action) node; char name[RTE_SWX_NAME_SIZE]; @@ -1382,6 +1387,7 @@ struct rte_swx_pipeline { struct port_in_runtime *in; struct port_out_runtime *out; struct instruction **action_instructions; + action_func_t *action_funcs; struct rte_swx_table_state *table_state; struct table_statistics *table_stats; struct selector_statistics *selector_stats;