diff --git a/examples/ip_pipeline/app.h b/examples/ip_pipeline/app.h index 521e3a01a0..943466e10c 100644 --- a/examples/ip_pipeline/app.h +++ b/examples/ip_pipeline/app.h @@ -107,6 +107,14 @@ struct app_pktq_swq_params { uint32_t dropless; uint64_t n_retries; uint32_t cpu_socket_id; + uint32_t ipv4_frag; + uint32_t ipv6_frag; + uint32_t ipv4_ras; + uint32_t ipv6_ras; + uint32_t mtu; + uint32_t metadata_size; + uint32_t mempool_direct_id; + uint32_t mempool_indirect_id; }; #ifndef APP_FILE_NAME_SIZE @@ -405,6 +413,10 @@ struct app_params { char app_name[APP_APPNAME_SIZE]; const char *config_file; const char *script_file; + const char *parser_file; + const char *output_file; + const char *preproc; + const char *preproc_args; uint64_t port_mask; uint32_t log_level; @@ -880,6 +892,8 @@ int app_config_init(struct app_params *app); int app_config_args(struct app_params *app, int argc, char **argv); +int app_config_preproc(struct app_params *app); + int app_config_parse(struct app_params *app, const char *file_name); diff --git a/examples/ip_pipeline/config_check.c b/examples/ip_pipeline/config_check.c index 07f4c8b95e..8052bc40f8 100644 --- a/examples/ip_pipeline/config_check.c +++ b/examples/ip_pipeline/config_check.c @@ -33,6 +33,8 @@ #include +#include + #include "app.h" static void @@ -193,6 +195,7 @@ check_swqs(struct app_params *app) struct app_pktq_swq_params *p = &app->swq_params[i]; uint32_t n_readers = app_swq_get_readers(app, p); uint32_t n_writers = app_swq_get_writers(app, p); + uint32_t n_flags; APP_CHECK((p->size > 0), "%s size is 0\n", p->name); @@ -217,14 +220,48 @@ check_swqs(struct app_params *app) APP_CHECK((n_readers != 0), "%s has no reader\n", p->name); - APP_CHECK((n_readers == 1), - "%s has more than one reader\n", p->name); + if (n_readers > 1) + APP_LOG(app, LOW, "%s has more than one reader", p->name); APP_CHECK((n_writers != 0), "%s has no writer\n", p->name); - APP_CHECK((n_writers == 1), - "%s has more than one writer\n", p->name); + if (n_writers > 1) + APP_LOG(app, LOW, "%s has more than one writer", p->name); + + n_flags = p->ipv4_frag + p->ipv6_frag + p->ipv4_ras + p->ipv6_ras; + + APP_CHECK((n_flags < 2), + "%s has more than one fragmentation or reassembly mode enabled\n", + p->name); + + APP_CHECK((!((n_readers > 1) && (n_flags == 1))), + "%s has more than one reader when fragmentation or reassembly" + " mode enabled\n", + p->name); + + APP_CHECK((!((n_writers > 1) && (n_flags == 1))), + "%s has more than one writer when fragmentation or reassembly" + " mode enabled\n", + p->name); + + n_flags = p->ipv4_ras + p->ipv6_ras; + + APP_CHECK((!((p->dropless == 1) && (n_flags == 1))), + "%s has dropless when reassembly mode enabled\n", p->name); + + n_flags = p->ipv4_frag + p->ipv6_frag; + + if (n_flags == 1) { + uint16_t ip_hdr_size = (p->ipv4_frag) ? sizeof(struct ipv4_hdr) : + sizeof(struct ipv6_hdr); + + APP_CHECK((p->mtu > ip_hdr_size), + "%s mtu size is smaller than ip header\n", p->name); + + APP_CHECK((!((p->mtu - ip_hdr_size) % 8)), + "%s mtu size is incorrect\n", p->name); + } } } diff --git a/examples/ip_pipeline/config_parse.c b/examples/ip_pipeline/config_parse.c index c9b78f9eb5..a35bd3e3e5 100644 --- a/examples/ip_pipeline/config_parse.c +++ b/examples/ip_pipeline/config_parse.c @@ -156,6 +156,14 @@ static const struct app_pktq_swq_params default_swq_params = { .dropless = 0, .n_retries = 0, .cpu_socket_id = 0, + .ipv4_frag = 0, + .ipv6_frag = 0, + .ipv4_ras = 0, + .ipv6_ras = 0, + .mtu = 0, + .metadata_size = 0, + .mempool_direct_id = 0, + .mempool_indirect_id = 0, }; struct app_pktq_tm_params default_tm_params = { @@ -196,13 +204,15 @@ struct app_pipeline_params default_pipeline_params = { static const char app_usage[] = "Usage: %s [-f CONFIG_FILE] [-s SCRIPT_FILE] -p PORT_MASK " - "[-l LOG_LEVEL]\n" + "[-l LOG_LEVEL] [--preproc PREPROCESSOR] [--preproc-args ARGS]\n" "\n" "Arguments:\n" "\t-f CONFIG_FILE: Default config file is %s\n" "\t-p PORT_MASK: Mask of NIC port IDs in hexadecimal format\n" "\t-s SCRIPT_FILE: No CLI script file is run when not specified\n" "\t-l LOG_LEVEL: 0 = NONE, 1 = HIGH PRIO (default), 2 = LOW PRIO\n" + "\t--preproc PREPROCESSOR: Configuration file pre-processor\n" + "\t--preproc-args ARGS: Arguments to be passed to pre-processor\n" "\n"; static void @@ -1107,6 +1117,10 @@ parse_pipeline(struct app_params *app, ret = parser_read_uint32(¶m->timer_period, ent->value); else { + APP_CHECK((param->n_args < APP_MAX_PIPELINE_ARGS), + "CFG: [%s] out of memory", + section_name); + param->args_name[param->n_args] = strdup(ent->name); param->args_value[param->n_args] = strdup(ent->value); @@ -1397,6 +1411,7 @@ parse_swq(struct app_params *app, struct app_pktq_swq_params *param; struct rte_cfgfile_entry *entries; int n_entries, ret, i; + unsigned frag_entries = 0; ssize_t param_idx; n_entries = rte_cfgfile_section_num_entries(cfg, section_name); @@ -1438,6 +1453,71 @@ parse_swq(struct app_params *app, else if (strcmp(ent->name, "cpu") == 0) ret = parser_read_uint32(¶m->cpu_socket_id, ent->value); + else if (strcmp(ent->name, "ipv4_frag") == 0) { + ret = parser_read_arg_bool(ent->value); + if (ret >= 0) { + param->ipv4_frag = ret; + if (param->mtu == 0) + param->mtu = 1500; + ret = 0; + } + } else if (strcmp(ent->name, "ipv6_frag") == 0) { + ret = parser_read_arg_bool(ent->value); + if (ret >= 0) { + param->ipv6_frag = ret; + if (param->mtu == 0) + param->mtu = 1320; + ret = 0; + } + } else if (strcmp(ent->name, "ipv4_ras") == 0) { + ret = parser_read_arg_bool(ent->value); + if (ret >= 0) { + param->ipv4_ras = ret; + ret = 0; + } + } else if (strcmp(ent->name, "ipv6_ras") == 0) { + ret = parser_read_arg_bool(ent->value); + if (ret >= 0) { + param->ipv6_ras = ret; + ret = 0; + } + } else if (strcmp(ent->name, "mtu") == 0) { + frag_entries = 1; + ret = parser_read_uint32(¶m->mtu, + ent->value); + } else if (strcmp(ent->name, "metadata_size") == 0) { + frag_entries = 1; + ret = parser_read_uint32(¶m->metadata_size, + ent->value); + } else if (strcmp(ent->name, "mempool_direct") == 0) { + int status = validate_name(ent->value, "MEMPOOL", 1); + ssize_t idx; + + APP_CHECK((status == 0), + "CFG: [%s] entry '%s': invalid mempool\n", + section_name, + ent->name); + + idx = APP_PARAM_ADD(app->mempool_params, ent->value); + PARSER_IMPLICIT_PARAM_ADD_CHECK(idx, section_name); + param->mempool_direct_id = idx; + frag_entries = 1; + ret = 0; + } else if (strcmp(ent->name, "mempool_indirect") == 0) { + int status = validate_name(ent->value, "MEMPOOL", 1); + ssize_t idx; + + APP_CHECK((status == 0), + "CFG: [%s] entry '%s': invalid mempool\n", + section_name, + ent->name); + + idx = APP_PARAM_ADD(app->mempool_params, ent->value); + PARSER_IMPLICIT_PARAM_ADD_CHECK(idx, section_name); + param->mempool_indirect_id = idx; + frag_entries = 1; + ret = 0; + } APP_CHECK(ret != -ESRCH, "CFG: [%s] entry '%s': unknown entry\n", @@ -1450,6 +1530,13 @@ parse_swq(struct app_params *app, ent->value); } + if (frag_entries == 1) { + APP_CHECK(((param->ipv4_frag == 1) || (param->ipv6_frag == 1)), + "CFG: [%s] ipv4/ipv6 frag is off : unsupported entries on this" + " configuration\n", + section_name); + } + free(entries); } @@ -1769,7 +1856,6 @@ parse_port_mask(struct app_params *app, uint64_t port_mask) int app_config_parse(struct app_params *app, const char *file_name) { - char config_file_out[APP_FILE_NAME_SIZE]; struct rte_cfgfile *cfg; char **section_names; int i, j, sect_count; @@ -1851,11 +1937,7 @@ app_config_parse(struct app_params *app, const char *file_name) APP_PARAM_COUNT(app->pipeline_params, app->n_pipelines); /* Save configuration to output file */ - snprintf(config_file_out, - APP_FILE_NAME_SIZE, - "%s.out", - app->config_file); - app_config_save(app, config_file_out); + app_config_save(app, app->output_file); /* Load TM configuration files */ app_config_parse_tm(app); @@ -2069,6 +2151,20 @@ save_swq_params(struct app_params *app, FILE *f) fprintf(f, "%s = %s\n", "dropless", p->dropless ? "yes" : "no"); fprintf(f, "%s = %" PRIu64 "\n", "n_retries", p->n_retries); fprintf(f, "%s = %" PRIu32 "\n", "cpu", p->cpu_socket_id); + fprintf(f, "%s = %s\n", "ipv4_frag", p->ipv4_frag ? "yes" : "no"); + fprintf(f, "%s = %s\n", "ipv6_frag", p->ipv6_frag ? "yes" : "no"); + fprintf(f, "%s = %s\n", "ipv4_ras", p->ipv4_ras ? "yes" : "no"); + fprintf(f, "%s = %s\n", "ipv6_ras", p->ipv6_ras ? "yes" : "no"); + if ((p->ipv4_frag == 1) || (p->ipv6_frag == 1)) { + fprintf(f, "%s = %" PRIu32 "\n", "mtu", p->mtu); + fprintf(f, "%s = %" PRIu32 "\n", "metadata_size", p->metadata_size); + fprintf(f, "%s = %s\n", + "mempool_direct", + app->mempool_params[p->mempool_direct_id].name); + fprintf(f, "%s = %s\n", + "mempool_indirect", + app->mempool_params[p->mempool_indirect_id].name); + } fputc('\n', f); } @@ -2360,15 +2456,31 @@ app_config_init(struct app_params *app) return 0; } +static char * +filenamedup(const char *filename, const char *suffix) +{ + char *s = malloc(strlen(filename) + strlen(suffix) + 1); + + if (!s) + return NULL; + + sprintf(s, "%s%s", filename, suffix); + return s; +} + int app_config_args(struct app_params *app, int argc, char **argv) { - int opt; - int option_index, f_present, s_present, p_present, l_present; + const char *optname; + int opt, option_index; + int f_present, s_present, p_present, l_present; + int preproc_present, preproc_params_present; int scaned = 0; static struct option lgopts[] = { - {NULL, 0, 0, 0} + { "preproc", 1, 0, 0 }, + { "preproc-args", 1, 0, 0 }, + { NULL, 0, 0, 0 } }; /* Copy application name */ @@ -2378,6 +2490,8 @@ app_config_args(struct app_params *app, int argc, char **argv) s_present = 0; p_present = 0; l_present = 0; + preproc_present = 0; + preproc_params_present = 0; while ((opt = getopt_long(argc, argv, "f:s:p:l:", lgopts, &option_index)) != EOF) @@ -2443,6 +2557,32 @@ app_config_args(struct app_params *app, int argc, char **argv) break; + case 0: + optname = lgopts[option_index].name; + + if (strcmp(optname, "preproc") == 0) { + if (preproc_present) + rte_panic("Error: Preprocessor argument " + "is provided more than once\n"); + preproc_present = 1; + + app->preproc = strdup(optarg); + break; + } + + if (strcmp(optname, "preproc-args") == 0) { + if (preproc_params_present) + rte_panic("Error: Preprocessor args " + "are provided more than once\n"); + preproc_params_present = 1; + + app->preproc_args = strdup(optarg); + break; + } + + app_print_usage(argv[0]); + break; + default: app_print_usage(argv[0]); } @@ -2453,5 +2593,40 @@ app_config_args(struct app_params *app, int argc, char **argv) if (!p_present) rte_panic("Error: PORT_MASK is not provided\n"); + /* Check dependencies between args */ + if (preproc_params_present && (preproc_present == 0)) + rte_panic("Error: Preprocessor args specified while " + "preprocessor is not defined\n"); + + app->parser_file = preproc_present ? + filenamedup(app->config_file, ".preproc") : + strdup(app->config_file); + app->output_file = filenamedup(app->config_file, ".out"); + return 0; } + +int +app_config_preproc(struct app_params *app) +{ + char buffer[256]; + int status; + + if (app->preproc == NULL) + return 0; + + status = access(app->config_file, F_OK | R_OK); + APP_CHECK((status == 0), "Unable to open file %s", app->config_file); + + snprintf(buffer, sizeof(buffer), "%s %s %s > %s", + app->preproc, + app->preproc_args ? app->preproc_args : "", + app->config_file, + app->parser_file); + + status = system(buffer); + APP_CHECK((WIFEXITED(status) && (WEXITSTATUS(status) == 0)), + "Error while preprocessing file \"%s\"\n", app->config_file); + + return status; +} diff --git a/examples/ip_pipeline/init.c b/examples/ip_pipeline/init.c index 3f9c68dce7..46d044ec20 100644 --- a/examples/ip_pipeline/init.c +++ b/examples/ip_pipeline/init.c @@ -803,11 +803,43 @@ app_check_link(struct app_params *app) rte_panic("Some links are DOWN\n"); } +static uint32_t +is_any_swq_frag_or_ras(struct app_params *app) +{ + uint32_t i; + + for (i = 0; i < app->n_pktq_swq; i++) { + struct app_pktq_swq_params *p = &app->swq_params[i]; + + if ((p->ipv4_frag == 1) || (p->ipv6_frag == 1) || + (p->ipv4_ras == 1) || (p->ipv6_ras == 1)) + return 1; + } + + return 0; +} + +static void +app_init_link_frag_ras(struct app_params *app) +{ + uint32_t i; + + if (is_any_swq_frag_or_ras(app)) { + for (i = 0; i < app->n_pktq_hwq_out; i++) { + struct app_pktq_hwq_out_params *p_txq = &app->hwq_out_params[i]; + + p_txq->conf.txq_flags &= ~ETH_TXQ_FLAGS_NOMULTSEGS; + } + } +} + static void app_init_link(struct app_params *app) { uint32_t i; + app_init_link_frag_ras(app); + for (i = 0; i < app->n_links; i++) { struct app_link_params *p_link = &app->link_params[i]; uint32_t link_id, n_hwq_in, n_hwq_out, j; @@ -916,13 +948,19 @@ app_init_swq(struct app_params *app) for (i = 0; i < app->n_pktq_swq; i++) { struct app_pktq_swq_params *p = &app->swq_params[i]; + unsigned flags = 0; + + if (app_swq_get_readers(app, p) == 1) + flags |= RING_F_SC_DEQ; + if (app_swq_get_writers(app, p) == 1) + flags |= RING_F_SP_ENQ; APP_LOG(app, HIGH, "Initializing %s...", p->name); app->swq[i] = rte_ring_create( p->name, p->size, p->cpu_socket_id, - RING_F_SP_ENQ | RING_F_SC_DEQ); + flags); if (app->swq[i] == NULL) rte_panic("%s init error\n", p->name); @@ -1059,11 +1097,50 @@ static void app_pipeline_params_get(struct app_params *app, break; } case APP_PKTQ_IN_SWQ: - out->type = PIPELINE_PORT_IN_RING_READER; - out->params.ring.ring = app->swq[in->id]; - out->burst_size = app->swq_params[in->id].burst_read; - /* What about frag and ras ports? */ + { + struct app_pktq_swq_params *swq_params = &app->swq_params[in->id]; + + if ((swq_params->ipv4_frag == 0) && (swq_params->ipv6_frag == 0)) { + if (app_swq_get_readers(app, swq_params) == 1) { + out->type = PIPELINE_PORT_IN_RING_READER; + out->params.ring.ring = app->swq[in->id]; + out->burst_size = app->swq_params[in->id].burst_read; + } else { + out->type = PIPELINE_PORT_IN_RING_MULTI_READER; + out->params.ring_multi.ring = app->swq[in->id]; + out->burst_size = swq_params->burst_read; + } + } else { + if (swq_params->ipv4_frag == 1) { + struct rte_port_ring_reader_ipv4_frag_params *params = + &out->params.ring_ipv4_frag; + + out->type = PIPELINE_PORT_IN_RING_READER_IPV4_FRAG; + params->ring = app->swq[in->id]; + params->mtu = swq_params->mtu; + params->metadata_size = swq_params->metadata_size; + params->pool_direct = + app->mempool[swq_params->mempool_direct_id]; + params->pool_indirect = + app->mempool[swq_params->mempool_indirect_id]; + out->burst_size = swq_params->burst_read; + } else { + struct rte_port_ring_reader_ipv6_frag_params *params = + &out->params.ring_ipv6_frag; + + out->type = PIPELINE_PORT_IN_RING_READER_IPV6_FRAG; + params->ring = app->swq[in->id]; + params->mtu = swq_params->mtu; + params->metadata_size = swq_params->metadata_size; + params->pool_direct = + app->mempool[swq_params->mempool_direct_id]; + params->pool_indirect = + app->mempool[swq_params->mempool_indirect_id]; + out->burst_size = swq_params->burst_read; + } + } break; + } case APP_PKTQ_IN_TM: out->type = PIPELINE_PORT_IN_SCHED_READER; out->params.sched.sched = app->tm[in->id]; @@ -1122,28 +1199,68 @@ static void app_pipeline_params_get(struct app_params *app, break; } case APP_PKTQ_OUT_SWQ: - if (app->swq_params[in->id].dropless == 0) { - struct rte_port_ring_writer_params *params = - &out->params.ring; + { + struct app_pktq_swq_params *swq_params = &app->swq_params[in->id]; - out->type = PIPELINE_PORT_OUT_RING_WRITER; - params->ring = app->swq[in->id]; - params->tx_burst_sz = - app->swq_params[in->id].burst_write; + if ((swq_params->ipv4_ras == 0) && (swq_params->ipv6_ras == 0)) { + if (app_swq_get_writers(app, swq_params) == 1) { + if (app->swq_params[in->id].dropless == 0) { + struct rte_port_ring_writer_params *params = + &out->params.ring; + + out->type = PIPELINE_PORT_OUT_RING_WRITER; + params->ring = app->swq[in->id]; + params->tx_burst_sz = + app->swq_params[in->id].burst_write; + } else { + struct rte_port_ring_writer_nodrop_params + *params = &out->params.ring_nodrop; + + out->type = + PIPELINE_PORT_OUT_RING_WRITER_NODROP; + params->ring = app->swq[in->id]; + params->tx_burst_sz = + app->swq_params[in->id].burst_write; + params->n_retries = + app->swq_params[in->id].n_retries; + } + } else { + if (swq_params->dropless == 0) { + struct rte_port_ring_multi_writer_params *params = + &out->params.ring_multi; + + out->type = PIPELINE_PORT_OUT_RING_MULTI_WRITER; + params->ring = app->swq[in->id]; + params->tx_burst_sz = swq_params->burst_write; + } else { + struct rte_port_ring_multi_writer_nodrop_params + *params = &out->params.ring_multi_nodrop; + + out->type = PIPELINE_PORT_OUT_RING_MULTI_WRITER_NODROP; + params->ring = app->swq[in->id]; + params->tx_burst_sz = swq_params->burst_write; + params->n_retries = swq_params->n_retries; + } + } } else { - struct rte_port_ring_writer_nodrop_params - *params = &out->params.ring_nodrop; + if (swq_params->ipv4_ras == 1) { + struct rte_port_ring_writer_ipv4_ras_params *params = + &out->params.ring_ipv4_ras; - out->type = - PIPELINE_PORT_OUT_RING_WRITER_NODROP; - params->ring = app->swq[in->id]; - params->tx_burst_sz = - app->swq_params[in->id].burst_write; - params->n_retries = - app->swq_params[in->id].n_retries; + out->type = PIPELINE_PORT_OUT_RING_WRITER_IPV4_RAS; + params->ring = app->swq[in->id]; + params->tx_burst_sz = swq_params->burst_write; + } else { + struct rte_port_ring_writer_ipv6_ras_params *params = + &out->params.ring_ipv6_ras; + + out->type = PIPELINE_PORT_OUT_RING_WRITER_IPV6_RAS; + params->ring = app->swq[in->id]; + params->tx_burst_sz = swq_params->burst_write; + } } - /* What about frag and ras ports? */ break; + } case APP_PKTQ_OUT_TM: { struct rte_port_sched_writer_params *params = &out->params.sched; diff --git a/examples/ip_pipeline/main.c b/examples/ip_pipeline/main.c index 862e2f23a5..4944dcfbde 100644 --- a/examples/ip_pipeline/main.c +++ b/examples/ip_pipeline/main.c @@ -45,7 +45,9 @@ main(int argc, char **argv) app_config_args(&app, argc, argv); - app_config_parse(&app, app.config_file); + app_config_preproc(&app); + + app_config_parse(&app, app.parser_file); app_config_check(&app); diff --git a/examples/ip_pipeline/pipeline_be.h b/examples/ip_pipeline/pipeline_be.h index 51f1e4f596..f7269c091b 100644 --- a/examples/ip_pipeline/pipeline_be.h +++ b/examples/ip_pipeline/pipeline_be.h @@ -45,6 +45,7 @@ enum pipeline_port_in_type { PIPELINE_PORT_IN_ETHDEV_READER, PIPELINE_PORT_IN_RING_READER, + PIPELINE_PORT_IN_RING_MULTI_READER, PIPELINE_PORT_IN_RING_READER_IPV4_FRAG, PIPELINE_PORT_IN_RING_READER_IPV6_FRAG, PIPELINE_PORT_IN_SCHED_READER, @@ -56,6 +57,7 @@ struct pipeline_port_in_params { union { struct rte_port_ethdev_reader_params ethdev; struct rte_port_ring_reader_params ring; + struct rte_port_ring_multi_reader_params ring_multi; struct rte_port_ring_reader_ipv4_frag_params ring_ipv4_frag; struct rte_port_ring_reader_ipv6_frag_params ring_ipv6_frag; struct rte_port_sched_reader_params sched; @@ -72,6 +74,8 @@ pipeline_port_in_params_convert(struct pipeline_port_in_params *p) return (void *) &p->params.ethdev; case PIPELINE_PORT_IN_RING_READER: return (void *) &p->params.ring; + case PIPELINE_PORT_IN_RING_MULTI_READER: + return (void *) &p->params.ring_multi; case PIPELINE_PORT_IN_RING_READER_IPV4_FRAG: return (void *) &p->params.ring_ipv4_frag; case PIPELINE_PORT_IN_RING_READER_IPV6_FRAG: @@ -93,6 +97,8 @@ pipeline_port_in_params_get_ops(struct pipeline_port_in_params *p) return &rte_port_ethdev_reader_ops; case PIPELINE_PORT_IN_RING_READER: return &rte_port_ring_reader_ops; + case PIPELINE_PORT_IN_RING_MULTI_READER: + return &rte_port_ring_multi_reader_ops; case PIPELINE_PORT_IN_RING_READER_IPV4_FRAG: return &rte_port_ring_reader_ipv4_frag_ops; case PIPELINE_PORT_IN_RING_READER_IPV6_FRAG: @@ -110,7 +116,9 @@ enum pipeline_port_out_type { PIPELINE_PORT_OUT_ETHDEV_WRITER, PIPELINE_PORT_OUT_ETHDEV_WRITER_NODROP, PIPELINE_PORT_OUT_RING_WRITER, + PIPELINE_PORT_OUT_RING_MULTI_WRITER, PIPELINE_PORT_OUT_RING_WRITER_NODROP, + PIPELINE_PORT_OUT_RING_MULTI_WRITER_NODROP, PIPELINE_PORT_OUT_RING_WRITER_IPV4_RAS, PIPELINE_PORT_OUT_RING_WRITER_IPV6_RAS, PIPELINE_PORT_OUT_SCHED_WRITER, @@ -123,7 +131,9 @@ struct pipeline_port_out_params { struct rte_port_ethdev_writer_params ethdev; struct rte_port_ethdev_writer_nodrop_params ethdev_nodrop; struct rte_port_ring_writer_params ring; + struct rte_port_ring_multi_writer_params ring_multi; struct rte_port_ring_writer_nodrop_params ring_nodrop; + struct rte_port_ring_multi_writer_nodrop_params ring_multi_nodrop; struct rte_port_ring_writer_ipv4_ras_params ring_ipv4_ras; struct rte_port_ring_writer_ipv6_ras_params ring_ipv6_ras; struct rte_port_sched_writer_params sched; @@ -140,8 +150,12 @@ pipeline_port_out_params_convert(struct pipeline_port_out_params *p) return (void *) &p->params.ethdev_nodrop; case PIPELINE_PORT_OUT_RING_WRITER: return (void *) &p->params.ring; + case PIPELINE_PORT_OUT_RING_MULTI_WRITER: + return (void *) &p->params.ring_multi; case PIPELINE_PORT_OUT_RING_WRITER_NODROP: return (void *) &p->params.ring_nodrop; + case PIPELINE_PORT_OUT_RING_MULTI_WRITER_NODROP: + return (void *) &p->params.ring_multi_nodrop; case PIPELINE_PORT_OUT_RING_WRITER_IPV4_RAS: return (void *) &p->params.ring_ipv4_ras; case PIPELINE_PORT_OUT_RING_WRITER_IPV6_RAS: @@ -164,8 +178,12 @@ pipeline_port_out_params_get_ops(struct pipeline_port_out_params *p) return &rte_port_ethdev_writer_nodrop_ops; case PIPELINE_PORT_OUT_RING_WRITER: return &rte_port_ring_writer_ops; + case PIPELINE_PORT_OUT_RING_MULTI_WRITER: + return &rte_port_ring_multi_writer_ops; case PIPELINE_PORT_OUT_RING_WRITER_NODROP: return &rte_port_ring_writer_nodrop_ops; + case PIPELINE_PORT_OUT_RING_MULTI_WRITER_NODROP: + return &rte_port_ring_multi_writer_nodrop_ops; case PIPELINE_PORT_OUT_RING_WRITER_IPV4_RAS: return &rte_port_ring_writer_ipv4_ras_ops; case PIPELINE_PORT_OUT_RING_WRITER_IPV6_RAS: