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
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;
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);
#include <stdio.h>
+#include <rte_ip.h>
+
#include "app.h"
static void
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);
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);
+ }
}
}
.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 = {
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
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);
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);
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",
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);
}
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;
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);
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);
}
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 */
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)
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]);
}
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;
+}
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;
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);
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];
break;
}
case APP_PKTQ_OUT_SWQ:
- 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;
+ {
+ struct app_pktq_swq_params *swq_params = &app->swq_params[in->id];
+
+ 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;
-
- 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;
+ 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_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;
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);
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,
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;
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:
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:
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,
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;
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:
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: