X-Git-Url: http://git.droids-corp.org/?a=blobdiff_plain;f=lib%2Fpipeline%2Frte_swx_pipeline.c;h=8c4670e11172283fdc76b50dbcebf652e7510646;hb=1e1bfd078e581c155cd5a2b5c9191d87714dfc93;hp=1cd09a4b441deb4a51513ee0a8d89f4321ffdc22;hpb=175d213bf833624c501188ca8f2dd7fe4bf599b3;p=dpdk.git diff --git a/lib/pipeline/rte_swx_pipeline.c b/lib/pipeline/rte_swx_pipeline.c index 1cd09a4b44..8c4670e111 100644 --- a/lib/pipeline/rte_swx_pipeline.c +++ b/lib/pipeline/rte_swx_pipeline.c @@ -4,9 +4,16 @@ #include #include #include -#include #include +#include +#include +#include +#include "rte_swx_port_source_sink.h" + +#include +#include + #include "rte_swx_pipeline_internal.h" #define CHECK(condition, err_code) \ @@ -1370,6 +1377,7 @@ instruction_is_tx(enum instruction_type type) switch (type) { case INSTR_TX: case INSTR_TX_I: + case INSTR_DROP: return 1; default: @@ -1383,6 +1391,7 @@ instruction_does_tx(struct instruction *instr) switch (instr->type) { case INSTR_TX: case INSTR_TX_I: + case INSTR_DROP: case INSTR_HDR_EMIT_TX: case INSTR_HDR_EMIT2_TX: case INSTR_HDR_EMIT3_TX: @@ -1591,7 +1600,7 @@ instr_tx_translate(struct rte_swx_pipeline *p, } static int -instr_drop_translate(struct rte_swx_pipeline *p, +instr_drop_translate(struct rte_swx_pipeline *p __rte_unused, struct action *action __rte_unused, char **tokens __rte_unused, int n_tokens, @@ -1600,9 +1609,8 @@ instr_drop_translate(struct rte_swx_pipeline *p, { CHECK(n_tokens == 1, EINVAL); - /* TX_I. */ - instr->type = INSTR_TX_I; - instr->io.io.val = p->n_ports_out - 1; + /* DROP. */ + instr->type = INSTR_DROP; return 0; } @@ -1632,6 +1640,19 @@ instr_tx_i_exec(struct rte_swx_pipeline *p) instr_rx_exec(p); } +static inline void +instr_drop_exec(struct rte_swx_pipeline *p) +{ + struct thread *t = &p->threads[p->thread_id]; + struct instruction *ip = t->ip; + + __instr_drop_exec(p, t, ip); + + /* Thread. */ + thread_ip_reset(p, t); + instr_rx_exec(p); +} + /* * extract. */ @@ -2865,8 +2886,8 @@ instr_alu_ckadd_translate(struct rte_swx_pipeline *p, CHECK(n_tokens == 3, EINVAL); fdst = header_field_parse(p, dst, &hdst); - CHECK(fdst && (fdst->n_bits == 16), EINVAL); - CHECK(!fdst->var_size, EINVAL); + CHECK(fdst, EINVAL); + CHECK(!fdst->var_size && (fdst->n_bits == 16), EINVAL); /* CKADD_FIELD. */ fsrc = header_field_parse(p, src, &hsrc); @@ -2886,17 +2907,16 @@ instr_alu_ckadd_translate(struct rte_swx_pipeline *p, /* CKADD_STRUCT, CKADD_STRUCT20. */ hsrc = header_parse(p, src); CHECK(hsrc, EINVAL); - CHECK(!hsrc->st->var_size, EINVAL); instr->type = INSTR_ALU_CKADD_STRUCT; - if ((hsrc->st->n_bits / 8) == 20) + if (!hsrc->st->var_size && ((hsrc->st->n_bits / 8) == 20)) instr->type = INSTR_ALU_CKADD_STRUCT20; instr->alu.dst.struct_id = (uint8_t)hdst->struct_id; instr->alu.dst.n_bits = fdst->n_bits; instr->alu.dst.offset = fdst->offset / 8; instr->alu.src.struct_id = (uint8_t)hsrc->struct_id; - instr->alu.src.n_bits = hsrc->st->n_bits; + instr->alu.src.n_bits = (uint8_t)hsrc->id; /* The src header ID is stored here. */ instr->alu.src.offset = 0; /* Unused. */ return 0; } @@ -2916,8 +2936,8 @@ instr_alu_cksub_translate(struct rte_swx_pipeline *p, CHECK(n_tokens == 3, EINVAL); fdst = header_field_parse(p, dst, &hdst); - CHECK(fdst && (fdst->n_bits == 16), EINVAL); - CHECK(!fdst->var_size, EINVAL); + CHECK(fdst, EINVAL); + CHECK(!fdst->var_size && (fdst->n_bits == 16), EINVAL); fsrc = header_field_parse(p, src, &hsrc); CHECK(fsrc, EINVAL); @@ -4539,8 +4559,6 @@ instr_meter_translate(struct rte_swx_pipeline *p, instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id; instr->meter.color_out.n_bits = fcout->n_bits; instr->meter.color_out.offset = fcout->offset / 8; - - return 0; } /* index = HMEFT, length = HMEFT, color_in = I, color_out = MEF. */ @@ -4575,8 +4593,6 @@ instr_meter_translate(struct rte_swx_pipeline *p, instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id; instr->meter.color_out.n_bits = fcout->n_bits; instr->meter.color_out.offset = fcout->offset / 8; - - return 0; } /* index = I, length = HMEFT, color_in = MEFT, color_out = MEF. */ @@ -4607,8 +4623,6 @@ instr_meter_translate(struct rte_swx_pipeline *p, instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id; instr->meter.color_out.n_bits = fcout->n_bits; instr->meter.color_out.offset = fcout->offset / 8; - - return 0; } /* index = I, length = HMEFT, color_in = I, color_out = MEF. */ @@ -4638,11 +4652,9 @@ instr_meter_translate(struct rte_swx_pipeline *p, instr->meter.color_out.struct_id = (uint8_t)color_out_struct_id; instr->meter.color_out.n_bits = fcout->n_bits; instr->meter.color_out.offset = fcout->offset / 8; - - return 0; } - CHECK(0, EINVAL); + return 0; } static inline void @@ -5937,7 +5949,7 @@ instr_translate(struct rte_swx_pipeline *p, instr, data); - CHECK(0, EINVAL); + return -EINVAL; } static struct instruction_data * @@ -5983,7 +5995,20 @@ instr_label_check(struct instruction_data *instruction_data, continue; for (j = i + 1; j < n_instructions; j++) - CHECK(strcmp(label, data[j].label), EINVAL); + CHECK(strcmp(label, instruction_data[j].label), EINVAL); + } + + /* Check that no jump instruction (either conditional or not) can jump to itself (loop). */ + for (i = 0; i < n_instructions; i++) { + struct instruction_data *data = &instruction_data[i]; + char *label = data->label; + char *jmp_label = data->jmp_label; + + /* Continue if this instruction does not have a label or it is not a jump. */ + if (!label[0] || !jmp_label[0]) + continue; + + CHECK(strcmp(label, jmp_label), EINVAL); } /* Get users for each instruction label. */ @@ -6207,7 +6232,7 @@ instr_pattern_emit_many_tx_search(struct instruction *instr, if (!i) return 0; - if (!instruction_is_tx(instr[i].type)) + if (instr[i].type != INSTR_TX) return 0; if (data[i].n_users) @@ -6651,6 +6676,7 @@ static instr_exec_t instruction_table[] = { [INSTR_RX] = instr_rx_exec, [INSTR_TX] = instr_tx_exec, [INSTR_TX_I] = instr_tx_i_exec, + [INSTR_DROP] = instr_drop_exec, [INSTR_HDR_EXTRACT] = instr_hdr_extract_exec, [INSTR_HDR_EXTRACT2] = instr_hdr_extract2_exec, @@ -7309,7 +7335,7 @@ rte_swx_pipeline_table_config(struct rte_swx_pipeline *p, uint32_t size) { struct table_type *type; - struct table *t; + struct table *t = NULL; struct action *default_action; struct header *header = NULL; uint32_t action_data_size_max = 0, i; @@ -7336,6 +7362,7 @@ rte_swx_pipeline_table_config(struct rte_swx_pipeline *p, const char *action_name = params->action_names[i]; struct action *a; uint32_t action_data_size; + int action_is_for_table_entries = 1, action_is_for_default_entry = 1; CHECK_NAME(action_name, EINVAL); @@ -7346,6 +7373,12 @@ rte_swx_pipeline_table_config(struct rte_swx_pipeline *p, action_data_size = a->st ? a->st->n_bits / 8 : 0; if (action_data_size > action_data_size_max) action_data_size_max = action_data_size; + + if (params->action_is_for_table_entries) + action_is_for_table_entries = params->action_is_for_table_entries[i]; + if (params->action_is_for_default_entry) + action_is_for_default_entry = params->action_is_for_default_entry[i]; + CHECK(action_is_for_table_entries || action_is_for_default_entry, EINVAL); } CHECK_NAME(params->default_action_name, EINVAL); @@ -7354,6 +7387,9 @@ rte_swx_pipeline_table_config(struct rte_swx_pipeline *p, params->default_action_name)) break; CHECK(i < params->n_actions, EINVAL); + CHECK(!params->action_is_for_default_entry || params->action_is_for_default_entry[i], + EINVAL); + default_action = action_find(p, params->default_action_name); CHECK((default_action->st && params->default_action_data) || !params->default_action_data, EINVAL); @@ -7377,31 +7413,31 @@ rte_swx_pipeline_table_config(struct rte_swx_pipeline *p, /* Memory allocation. */ t = calloc(1, sizeof(struct table)); - CHECK(t, ENOMEM); + if (!t) + goto nomem; t->fields = calloc(params->n_fields, sizeof(struct match_field)); - if (!t->fields) { - free(t); - CHECK(0, ENOMEM); - } + if (!t->fields) + goto nomem; t->actions = calloc(params->n_actions, sizeof(struct action *)); - if (!t->actions) { - free(t->fields); - free(t); - CHECK(0, ENOMEM); - } + if (!t->actions) + goto nomem; if (action_data_size_max) { t->default_action_data = calloc(1, action_data_size_max); - if (!t->default_action_data) { - free(t->actions); - free(t->fields); - free(t); - CHECK(0, ENOMEM); - } + if (!t->default_action_data) + goto nomem; } + t->action_is_for_table_entries = calloc(params->n_actions, sizeof(int)); + if (!t->action_is_for_table_entries) + goto nomem; + + t->action_is_for_default_entry = calloc(params->n_actions, sizeof(int)); + if (!t->action_is_for_default_entry) + goto nomem; + /* Node initialization. */ strcpy(t->name, name); if (args && args[0]) @@ -7420,8 +7456,18 @@ rte_swx_pipeline_table_config(struct rte_swx_pipeline *p, t->n_fields = params->n_fields; t->header = header; - for (i = 0; i < params->n_actions; i++) + for (i = 0; i < params->n_actions; i++) { + int action_is_for_table_entries = 1, action_is_for_default_entry = 1; + + if (params->action_is_for_table_entries) + action_is_for_table_entries = params->action_is_for_table_entries[i]; + if (params->action_is_for_default_entry) + action_is_for_default_entry = params->action_is_for_default_entry[i]; + t->actions[i] = action_find(p, params->action_names[i]); + t->action_is_for_table_entries[i] = action_is_for_table_entries; + t->action_is_for_default_entry[i] = action_is_for_default_entry; + } t->default_action = default_action; if (default_action->st) memcpy(t->default_action_data, @@ -7439,6 +7485,19 @@ rte_swx_pipeline_table_config(struct rte_swx_pipeline *p, p->n_tables++; return 0; + +nomem: + if (!t) + return -ENOMEM; + + free(t->action_is_for_default_entry); + free(t->action_is_for_table_entries); + free(t->default_action_data); + free(t->actions); + free(t->fields); + free(t); + + return -ENOMEM; } static struct rte_swx_table_params * @@ -8179,12 +8238,12 @@ rte_swx_pipeline_learner_config(struct rte_swx_pipeline *p, /* Action checks. */ CHECK(params->n_actions, EINVAL); - CHECK(params->action_names, EINVAL); for (i = 0; i < params->n_actions; i++) { const char *action_name = params->action_names[i]; struct action *a; uint32_t action_data_size; + int action_is_for_table_entries = 1, action_is_for_default_entry = 1; CHECK_NAME(action_name, EINVAL); @@ -8201,6 +8260,12 @@ rte_swx_pipeline_learner_config(struct rte_swx_pipeline *p, action_data_size = a->st ? a->st->n_bits / 8 : 0; if (action_data_size > action_data_size_max) action_data_size_max = action_data_size; + + if (params->action_is_for_table_entries) + action_is_for_table_entries = params->action_is_for_table_entries[i]; + if (params->action_is_for_default_entry) + action_is_for_default_entry = params->action_is_for_default_entry[i]; + CHECK(action_is_for_table_entries || action_is_for_default_entry, EINVAL); } CHECK_NAME(params->default_action_name, EINVAL); @@ -8209,6 +8274,8 @@ rte_swx_pipeline_learner_config(struct rte_swx_pipeline *p, params->default_action_name)) break; CHECK(i < params->n_actions, EINVAL); + CHECK(!params->action_is_for_default_entry || params->action_is_for_default_entry[i], + EINVAL); default_action = action_find(p, params->default_action_name); CHECK((default_action->st && params->default_action_data) || @@ -8237,6 +8304,14 @@ rte_swx_pipeline_learner_config(struct rte_swx_pipeline *p, goto nomem; } + l->action_is_for_table_entries = calloc(params->n_actions, sizeof(int)); + if (!l->action_is_for_table_entries) + goto nomem; + + l->action_is_for_default_entry = calloc(params->n_actions, sizeof(int)); + if (!l->action_is_for_default_entry) + goto nomem; + /* Node initialization. */ strcpy(l->name, name); @@ -8252,8 +8327,18 @@ rte_swx_pipeline_learner_config(struct rte_swx_pipeline *p, l->header = header; - for (i = 0; i < params->n_actions; i++) + for (i = 0; i < params->n_actions; i++) { + int action_is_for_table_entries = 1, action_is_for_default_entry = 1; + + if (params->action_is_for_table_entries) + action_is_for_table_entries = params->action_is_for_table_entries[i]; + if (params->action_is_for_default_entry) + action_is_for_default_entry = params->action_is_for_default_entry[i]; + l->actions[i] = action_find(p, params->action_names[i]); + l->action_is_for_table_entries[i] = action_is_for_table_entries; + l->action_is_for_default_entry[i] = action_is_for_default_entry; + } l->default_action = default_action; @@ -8284,6 +8369,9 @@ nomem: if (!l) return -ENOMEM; + free(l->action_is_for_default_entry); + free(l->action_is_for_table_entries); + free(l->default_action_data); free(l->actions); free(l->fields); free(l); @@ -8477,7 +8565,7 @@ table_state_build(struct rte_swx_pipeline *p) struct selector *s; struct learner *l; - p->table_state = calloc(p->n_tables + p->n_selectors, + p->table_state = calloc(p->n_tables + p->n_selectors + p->n_learners, sizeof(struct rte_swx_table_state)); CHECK(p->table_state, ENOMEM); @@ -8913,17 +9001,144 @@ metarray_free(struct rte_swx_pipeline *p) /* * Pipeline. */ +void +rte_swx_pipeline_free(struct rte_swx_pipeline *p) +{ + void *lib; + + if (!p) + return; + + lib = p->lib; + + free(p->instruction_data); + free(p->instructions); + + metarray_free(p); + regarray_free(p); + table_state_free(p); + learner_free(p); + selector_free(p); + table_free(p); + action_free(p); + instruction_table_free(p); + metadata_free(p); + header_free(p); + extern_func_free(p); + extern_obj_free(p); + port_out_free(p); + port_in_free(p); + struct_free(p); + + free(p); + + if (lib) + dlclose(lib); +} + +static int +port_in_types_register(struct rte_swx_pipeline *p) +{ + int status; + + status = rte_swx_pipeline_port_in_type_register(p, + "ethdev", + &rte_swx_port_ethdev_reader_ops); + if (status) + return status; + + status = rte_swx_pipeline_port_in_type_register(p, + "ring", + &rte_swx_port_ring_reader_ops); + if (status) + return status; + +#ifdef RTE_PORT_PCAP + status = rte_swx_pipeline_port_in_type_register(p, + "source", + &rte_swx_port_source_ops); + if (status) + return status; +#endif + + status = rte_swx_pipeline_port_in_type_register(p, + "fd", + &rte_swx_port_fd_reader_ops); + if (status) + return status; + + return 0; +} + +static int +port_out_types_register(struct rte_swx_pipeline *p) +{ + int status; + + status = rte_swx_pipeline_port_out_type_register(p, + "ethdev", + &rte_swx_port_ethdev_writer_ops); + if (status) + return status; + + status = rte_swx_pipeline_port_out_type_register(p, + "ring", + &rte_swx_port_ring_writer_ops); + if (status) + return status; + + status = rte_swx_pipeline_port_out_type_register(p, + "sink", + &rte_swx_port_sink_ops); + if (status) + return status; + + status = rte_swx_pipeline_port_out_type_register(p, + "fd", + &rte_swx_port_fd_writer_ops); + if (status) + return status; + + return 0; +} + +static int +table_types_register(struct rte_swx_pipeline *p) +{ + int status; + + status = rte_swx_pipeline_table_type_register(p, + "exact", + RTE_SWX_TABLE_MATCH_EXACT, + &rte_swx_table_exact_match_ops); + if (status) + return status; + + status = rte_swx_pipeline_table_type_register(p, + "wildcard", + RTE_SWX_TABLE_MATCH_WILDCARD, + &rte_swx_table_wildcard_match_ops); + if (status) + return status; + + return 0; +} + int rte_swx_pipeline_config(struct rte_swx_pipeline **p, int numa_node) { - struct rte_swx_pipeline *pipeline; + struct rte_swx_pipeline *pipeline = NULL; + int status = 0; /* Check input parameters. */ CHECK(p, EINVAL); /* Memory allocation. */ pipeline = calloc(1, sizeof(struct rte_swx_pipeline)); - CHECK(pipeline, ENOMEM); + if (!pipeline) { + status = -ENOMEM; + goto error; + } /* Initialization. */ TAILQ_INIT(&pipeline->struct_types); @@ -8947,43 +9162,24 @@ rte_swx_pipeline_config(struct rte_swx_pipeline **p, int numa_node) pipeline->n_structs = 1; /* Struct 0 is reserved for action_data. */ pipeline->numa_node = numa_node; - *p = pipeline; - return 0; -} - -void -rte_swx_pipeline_free(struct rte_swx_pipeline *p) -{ - void *lib; - - if (!p) - return; - - lib = p->lib; + status = port_in_types_register(pipeline); + if (status) + goto error; - free(p->instruction_data); - free(p->instructions); + status = port_out_types_register(pipeline); + if (status) + goto error; - metarray_free(p); - regarray_free(p); - table_state_free(p); - learner_free(p); - selector_free(p); - table_free(p); - action_free(p); - instruction_table_free(p); - metadata_free(p); - header_free(p); - extern_func_free(p); - extern_obj_free(p); - port_out_free(p); - port_in_free(p); - struct_free(p); + status = table_types_register(pipeline); + if (status) + goto error; - free(p); + *p = pipeline; + return 0; - if (lib) - dlclose(lib); +error: + rte_swx_pipeline_free(pipeline); + return status; } int @@ -9014,6 +9210,9 @@ pipeline_compile(struct rte_swx_pipeline *p); int rte_swx_pipeline_build(struct rte_swx_pipeline *p) { + struct rte_swx_port_sink_params drop_port_params = { + .file_name = NULL, + }; int status; CHECK(p, EINVAL); @@ -9023,6 +9222,14 @@ rte_swx_pipeline_build(struct rte_swx_pipeline *p) if (status) goto error; + /* Drop port. */ + status = rte_swx_pipeline_port_out_config(p, + p->n_ports_out, + "sink", + &drop_port_params); + if (status) + goto error; + status = port_out_build(p); if (status) goto error; @@ -9277,6 +9484,9 @@ rte_swx_ctl_table_action_info_get(struct rte_swx_pipeline *p, table_action->action_id = t->actions[table_action_id]->id; + table_action->action_is_for_table_entries = t->action_is_for_table_entries[table_action_id]; + table_action->action_is_for_default_entry = t->action_is_for_default_entry[table_action_id]; + return 0; } @@ -9464,6 +9674,12 @@ rte_swx_ctl_learner_action_info_get(struct rte_swx_pipeline *p, learner_action->action_id = l->actions[learner_action_id]->id; + learner_action->action_is_for_table_entries = + l->action_is_for_table_entries[learner_action_id]; + + learner_action->action_is_for_default_entry = + l->action_is_for_default_entry[learner_action_id]; + return 0; } @@ -9838,6 +10054,7 @@ instr_type_to_name(struct instruction *instr) case INSTR_TX: return "INSTR_TX"; case INSTR_TX_I: return "INSTR_TX_I"; + case INSTR_DROP: return "INSTR_DROP"; case INSTR_HDR_EXTRACT: return "INSTR_HDR_EXTRACT"; case INSTR_HDR_EXTRACT2: return "INSTR_HDR_EXTRACT2"; @@ -10063,8 +10280,9 @@ instr_io_export(struct instruction *instr, FILE *f) instr_type_to_name(instr)); /* instr.io. */ - fprintf(f, - "\t\t.io = {\n"); + if (n_io || n_io_imm || n_hdrs) + fprintf(f, + "\t\t.io = {\n"); /* instr.io.io. */ if (n_io) @@ -10130,8 +10348,9 @@ instr_io_export(struct instruction *instr, FILE *f) } /* instr.io - closing curly brace. */ - fprintf(f, - "\t\t},\n"); + if (n_io || n_io_imm || n_hdrs) + fprintf(f, + "\t\t},\n"); /* instr - closing curly brace. */ fprintf(f, @@ -10704,6 +10923,7 @@ static instruction_export_t export_table[] = { [INSTR_TX] = instr_io_export, [INSTR_TX_I] = instr_io_export, + [INSTR_DROP] = instr_io_export, [INSTR_HDR_EXTRACT] = instr_io_export, [INSTR_HDR_EXTRACT2] = instr_io_export, @@ -10921,6 +11141,7 @@ instr_type_to_func(struct instruction *instr) case INSTR_TX: return "__instr_tx_exec"; case INSTR_TX_I: return "__instr_tx_i_exec"; + case INSTR_DROP: return "__instr_drop_exec"; case INSTR_HDR_EXTRACT: return "__instr_hdr_extract_exec"; case INSTR_HDR_EXTRACT2: return "__instr_hdr_extract2_exec";