From patchwork Wed Jul 27 23:01:21 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cristian Dumitrescu X-Patchwork-Id: 114318 X-Patchwork-Delegate: thomas@monjalon.net Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 20498A00C4; Thu, 28 Jul 2022 01:02:10 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 6240442BA8; Thu, 28 Jul 2022 01:01:43 +0200 (CEST) Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by mails.dpdk.org (Postfix) with ESMTP id E558C42B7A for ; Thu, 28 Jul 2022 01:01:39 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1658962900; x=1690498900; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=mypTbadyUjL6rCZqn0FzsdW+MU0EF0QJY1woIO74AGw=; b=P/acu80ay7xAtB0wE6yVSOTRDd0Ld1h5uByg7DwXXRfw/eqcjt/+Cz1M lEuaxApgZJIP/fT7BnY3Gb/Xjwuk023TwFClLs7q1E3UxnTFloSeUlCKk HyMC4Brd7IUYzbx2YjyWvISnXosknQ6/94yGO6vfJMnVeOevkApAbp6U3 Y2m3eER34v1pmGNjrOfcXpwxmidCGscCisWQzKINFaARTrqmSSHtEQ3yB QP2cHO5FAhGLI0NwPzZmi3lD3JEuZT1sYBmfDW2XO7qxSejhIbvjiuk1T ikBzSe6716ZNQTcsICkN9vSL5KPWCE0kGeXNWRPzxgICfdyPezHR7JGRR w==; X-IronPort-AV: E=McAfee;i="6400,9594,10421"; a="314150905" X-IronPort-AV: E=Sophos;i="5.93,196,1654585200"; d="scan'208";a="314150905" Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 27 Jul 2022 16:01:39 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.93,196,1654585200"; d="scan'208";a="846444319" Received: from silpixa00400573.ir.intel.com (HELO silpixa00400573.ger.corp.intel.com.) ([10.237.223.157]) by fmsmga006.fm.intel.com with ESMTP; 27 Jul 2022 16:01:38 -0700 From: Cristian Dumitrescu To: dev@dpdk.org Cc: "Kamalakannan R ." Subject: [PATCH V5 06/17] pipeline: add support for pipeline I/O specification Date: Wed, 27 Jul 2022 23:01:21 +0000 Message-Id: <20220727230132.601114-6-cristian.dumitrescu@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220727230132.601114-1-cristian.dumitrescu@intel.com> References: <20220727225431.600913-1-cristian.dumitrescu@intel.com> <20220727230132.601114-1-cristian.dumitrescu@intel.com> MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Add specification data structure and API for the pipeline I/O ports and related pipeline configuration such as packet mirroring. Signed-off-by: Cristian Dumitrescu Signed-off-by: Kamalakannan R. --- lib/pipeline/rte_swx_pipeline_spec.c | 852 +++++++++++++++++++++++++++ lib/pipeline/rte_swx_pipeline_spec.h | 58 ++ 2 files changed, 910 insertions(+) diff --git a/lib/pipeline/rte_swx_pipeline_spec.c b/lib/pipeline/rte_swx_pipeline_spec.c index bf21fe17ba..f34803793d 100644 --- a/lib/pipeline/rte_swx_pipeline_spec.c +++ b/lib/pipeline/rte_swx_pipeline_spec.c @@ -9,6 +9,12 @@ #include #include +#include + +#include +#include +#include +#include #include "rte_swx_pipeline_spec.h" @@ -3566,3 +3572,849 @@ rte_swx_pipeline_build_from_spec(struct rte_swx_pipeline *p, pipeline_spec_free(s); return status; } + +static void +port_in_params_free(void *params, const char *port_type) +{ + uintptr_t dev_name; + + if (!params || !port_type) + return; + + if (!strcmp(port_type, "ethdev")) { + struct rte_swx_port_ethdev_reader_params *p = params; + + dev_name = (uintptr_t)p->dev_name; + } else if (!strcmp(port_type, "ring")) { + struct rte_swx_port_ring_reader_params *p = params; + + dev_name = (uintptr_t)p->name; + } else if (!strcmp(port_type, "source")) { + struct rte_swx_port_source_params *p = params; + + dev_name = (uintptr_t)p->file_name; + } else + dev_name = (uintptr_t)NULL; + + free((void *)dev_name); + free(params); +} + +static void +port_out_params_free(void *params, const char *port_type) +{ + uintptr_t dev_name; + + if (!params || !port_type) + return; + + if (!strcmp(port_type, "ethdev")) { + struct rte_swx_port_ethdev_writer_params *p = params; + + dev_name = (uintptr_t)p->dev_name; + } else if (!strcmp(port_type, "ring")) { + struct rte_swx_port_ring_writer_params *p = params; + + dev_name = (uintptr_t)p->name; + } else if (!strcmp(port_type, "sink")) { + struct rte_swx_port_sink_params *p = params; + + dev_name = (uintptr_t)p->file_name; + } else + dev_name = (uintptr_t)NULL; + + free((void *)dev_name); + free(params); +} + +void +pipeline_iospec_free(struct pipeline_iospec *s) +{ + uint32_t i; + + if (!s) + return; + + /* Input ports. */ + for (i = 0; i < s->n_ports_in; i++) { + uintptr_t name = (uintptr_t)s->port_in_type[i]; + + port_in_params_free(s->port_in_params[i], s->port_in_type[i]); + free((void *)name); + } + + free(s->port_in_type); + free(s->port_in_params); + + /* Output ports. */ + for (i = 0; i < s->n_ports_out; i++) { + uintptr_t name = (uintptr_t)s->port_out_type[i]; + + port_out_params_free(s->port_out_params[i], s->port_out_type[i]); + free((void *)name); + } + + free(s->port_out_type); + free(s->port_out_params); + + free(s); +} + +static int +mirroring_parse(struct rte_swx_pipeline_mirroring_params *p, + char **tokens, + uint32_t n_tokens, + const char **err_msg) +{ + char *token; + + if ((n_tokens != 4) || strcmp(tokens[0], "slots") || strcmp(tokens[2], "sessions")) { + if (err_msg) + *err_msg = "Invalid statement."; + return -EINVAL; + } + + /* . */ + token = tokens[1]; + p->n_slots = strtoul(token, &token, 0); + if (token[0]) { + if (err_msg) + *err_msg = "Invalid parameter."; + return -EINVAL; + } + + /* . */ + token = tokens[3]; + p->n_sessions = strtoul(token, &token, 0); + if (token[0]) { + if (err_msg) + *err_msg = "Invalid parameter."; + return -EINVAL; + } + + return 0; +} + +static void * +port_in_ethdev_parse(char **tokens, uint32_t n_tokens, const char **err_msg) +{ + struct rte_swx_port_ethdev_reader_params *p = NULL; + char *token, *dev_name = NULL; + uint32_t queue_id, burst_size; + + if ((n_tokens != 5) || strcmp(tokens[1], "rxq") || strcmp(tokens[3], "bsz")) { + if (err_msg) + *err_msg = "Invalid statement."; + return NULL; + } + + /* . */ + token = tokens[2]; + queue_id = strtoul(token, &token, 0); + if (token[0]) { + if (err_msg) + *err_msg = "Invalid parameter."; + return NULL; + } + + /* . */ + token = tokens[4]; + burst_size = strtoul(token, &token, 0); + if (token[0]) { + if (err_msg) + *err_msg = "Invalid parameter."; + return NULL; + } + + /* Memory allocation. */ + dev_name = strdup(tokens[0]); + p = malloc(sizeof(struct rte_swx_port_ethdev_reader_params)); + if (!dev_name || !p) { + free(dev_name); + free(p); + + if (err_msg) + *err_msg = "Memory allocation failed."; + return NULL; + } + + /* Initialization. */ + p->dev_name = dev_name; + p->queue_id = queue_id; + p->burst_size = burst_size; + + return p; +} + +static void * +port_in_ring_parse(char **tokens, uint32_t n_tokens, const char **err_msg) +{ + struct rte_swx_port_ring_reader_params *p = NULL; + char *token, *name = NULL; + uint32_t burst_size; + + if ((n_tokens != 3) || strcmp(tokens[1], "bsz")) { + if (err_msg) + *err_msg = "Invalid statement."; + return NULL; + } + + /* . */ + token = tokens[2]; + burst_size = strtoul(token, &token, 0); + if (token[0]) { + if (err_msg) + *err_msg = "Invalid parameter."; + return NULL; + } + + /* Memory allocation. */ + name = strdup(tokens[0]); + p = malloc(sizeof(struct rte_swx_port_ring_reader_params)); + if (!name || !p) { + free(name); + free(p); + + if (err_msg) + *err_msg = "Memory allocation failed."; + return NULL; + } + + /* Initialization. */ + p->name = name; + p->burst_size = burst_size; + + return p; +} + +static void * +port_in_source_parse(char **tokens, uint32_t n_tokens, const char **err_msg) +{ + struct rte_swx_port_source_params *p = NULL; + struct rte_mempool *pool = NULL; + char *token, *file_name = NULL; + uint32_t n_loops, n_pkts_max; + + if ((n_tokens != 8) || + strcmp(tokens[0], "mempool") || + strcmp(tokens[2], "file") || + strcmp(tokens[4], "loop") || + strcmp(tokens[6], "packets")) { + if (err_msg) + *err_msg = "Invalid statement."; + return NULL; + } + + /* . */ + pool = rte_mempool_lookup(tokens[1]); + if (!pool) { + if (err_msg) + *err_msg = "Invalid parameter."; + return NULL; + } + + /* . */ + token = tokens[5]; + n_loops = strtoul(token, &token, 0); + if (token[0]) { + if (err_msg) + *err_msg = "Invalid parameter."; + return NULL; + } + + /* . */ + token = tokens[7]; + n_pkts_max = strtoul(token, &token, 0); + if (token[0]) { + if (err_msg) + *err_msg = "Invalid parameter."; + return NULL; + } + + /* Memory allocation. */ + file_name = strdup(tokens[3]); + p = malloc(sizeof(struct rte_swx_port_source_params)); + if (!file_name || !p) { + free(file_name); + free(p); + + if (err_msg) + *err_msg = "Memory allocation failed."; + return NULL; + } + + /* Initialization. */ + p->pool = pool; + p->file_name = file_name; + p->n_loops = n_loops; + p->n_pkts_max = n_pkts_max; + + return p; +} + +static void * +port_in_fd_parse(char **tokens, + uint32_t n_tokens, + const char **err_msg) +{ + struct rte_swx_port_fd_reader_params *p = NULL; + struct rte_mempool *mempool = NULL; + char *token; + uint32_t mtu, burst_size; + int fd; + + if ((n_tokens != 7) || + strcmp(tokens[1], "mtu") || + strcmp(tokens[3], "mempool") || + strcmp(tokens[5], "bsz")) { + if (err_msg) + *err_msg = "Invalid statement."; + return NULL; + } + + /* . */ + token = tokens[0]; + fd = strtol(token, &token, 0); + if (token[0]) { + if (err_msg) + *err_msg = "Invalid parameter."; + return NULL; + } + + /* . */ + token = tokens[2]; + mtu = strtoul(token, &token, 0); + if (token[0]) { + if (err_msg) + *err_msg = "Invalid parameter."; + return NULL; + } + + /* . */ + mempool = rte_mempool_lookup(tokens[4]); + if (!mempool) { + if (err_msg) + *err_msg = "Invalid parameter."; + return NULL; + } + + /* . */ + token = tokens[6]; + burst_size = strtoul(token, &token, 0); + if (token[0]) { + if (err_msg) + *err_msg = "Invalid parameter."; + return NULL; + } + + /* Memory allocation. */ + p = malloc(sizeof(struct rte_swx_port_fd_reader_params)); + if (!p) { + if (err_msg) + *err_msg = "Memory allocation failed."; + return NULL; + } + + /* Initialization. */ + p->fd = fd; + p->mtu = mtu; + p->mempool = mempool; + p->burst_size = burst_size; + + return p; +} + +static void * +port_out_ethdev_parse(char **tokens, uint32_t n_tokens, const char **err_msg) +{ + struct rte_swx_port_ethdev_writer_params *p = NULL; + char *token, *dev_name = NULL; + uint32_t queue_id, burst_size; + + if ((n_tokens != 5) || strcmp(tokens[1], "txq") || strcmp(tokens[3], "bsz")) { + if (err_msg) + *err_msg = "Invalid statement."; + return NULL; + } + + /* . */ + token = tokens[2]; + queue_id = strtoul(token, &token, 0); + if (token[0]) { + if (err_msg) + *err_msg = "Invalid parameter."; + return NULL; + } + + /* . */ + token = tokens[4]; + burst_size = strtoul(token, &token, 0); + if (token[0]) { + if (err_msg) + *err_msg = "Invalid parameter."; + return NULL; + } + + /* Memory allocation. */ + dev_name = strdup(tokens[0]); + p = malloc(sizeof(struct rte_swx_port_ethdev_writer_params)); + if (!dev_name || !p) { + free(dev_name); + free(p); + + if (err_msg) + *err_msg = "Memory allocation failed."; + return NULL; + } + + /* Initialization. */ + p->dev_name = dev_name; + p->queue_id = queue_id; + p->burst_size = burst_size; + + return p; +} + +static void * +port_out_ring_parse(char **tokens, uint32_t n_tokens, const char **err_msg) +{ + struct rte_swx_port_ring_writer_params *p = NULL; + char *token, *name = NULL; + uint32_t burst_size; + + if ((n_tokens != 3) || strcmp(tokens[1], "bsz")) { + if (err_msg) + *err_msg = "Invalid statement."; + return NULL; + } + + /* . */ + token = tokens[2]; + burst_size = strtoul(token, &token, 0); + if (token[0]) { + if (err_msg) + *err_msg = "Invalid parameter."; + return NULL; + } + + /* Memory allocation. */ + name = strdup(tokens[0]); + p = malloc(sizeof(struct rte_swx_port_ring_writer_params)); + if (!name || !p) { + free(name); + free(p); + + if (err_msg) + *err_msg = "Memory allocation failed."; + return NULL; + } + + /* Initialization. */ + p->name = name; + p->burst_size = burst_size; + + return p; +} + +static void * +port_out_sink_parse(char **tokens, uint32_t n_tokens, const char **err_msg) +{ + struct rte_swx_port_sink_params *p = NULL; + char *file_name = NULL; + int file_name_valid = 0; + + if ((n_tokens != 2) || strcmp(tokens[0], "file")) { + if (err_msg) + *err_msg = "Invalid statement."; + return NULL; + } + + /* Memory allocation. */ + if (strcmp(tokens[1], "none")) { + file_name_valid = 1; + file_name = strdup(tokens[1]); + } + + p = malloc(sizeof(struct rte_swx_port_ring_writer_params)); + if ((file_name_valid && !file_name) || !p) { + free(file_name); + free(p); + + if (err_msg) + *err_msg = "Memory allocation failed."; + return NULL; + } + + /* Initialization. */ + p->file_name = file_name; + + return p; +} + +static void * +port_out_fd_parse(char **tokens, + uint32_t n_tokens, + const char **err_msg) +{ + struct rte_swx_port_fd_writer_params *p = NULL; + char *token; + uint32_t burst_size; + int fd; + + if ((n_tokens != 3) || strcmp(tokens[1], "bsz")) { + if (err_msg) + *err_msg = "Invalid statement."; + return NULL; + } + + /* . */ + token = tokens[0]; + fd = strtol(token, &token, 0); + if (token[0]) { + if (err_msg) + *err_msg = "Invalid parameter."; + return NULL; + } + + /* . */ + token = tokens[2]; + burst_size = strtoul(token, &token, 0); + if (token[0]) { + if (err_msg) + *err_msg = "Invalid parameter."; + return NULL; + } + + /* Memory allocation. */ + p = malloc(sizeof(struct rte_swx_port_fd_writer_params)); + if (!p) { + if (err_msg) + *err_msg = "Memory allocation failed."; + return NULL; + } + + /* Initialization. */ + p->fd = fd; + p->burst_size = burst_size; + + return p; +} + +struct pipeline_iospec * +pipeline_iospec_parse(FILE *spec, + uint32_t *err_line, + const char **err_msg) +{ + struct pipeline_iospec *s = NULL; + uint32_t n_lines = 0; + + /* Check the input arguments. */ + if (!spec) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Invalid input argument."; + goto error; + } + + /* Memory allocation. */ + s = calloc(sizeof(struct pipeline_iospec), 1); + if (!s) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Memory allocation failed."; + goto error; + } + + /* Initialize with the default values. */ + s->mirroring_params.n_slots = RTE_SWX_PACKET_MIRRORING_SLOTS_DEFAULT; + s->mirroring_params.n_sessions = RTE_SWX_PACKET_MIRRORING_SESSIONS_DEFAULT; + + for (n_lines = 1; ; n_lines++) { + char line[MAX_LINE_LENGTH]; + char *tokens[MAX_TOKENS], *ptr = line; + uint32_t n_tokens = 0; + + /* Read next line. */ + if (!fgets(line, sizeof(line), spec)) + break; + + /* Parse the line into tokens. */ + for ( ; ; ) { + char *token; + + /* Get token. */ + token = strtok_r(ptr, " \f\n\r\t\v", &ptr); + if (!token) + break; + + /* Handle comments. */ + if ((token[0] == '#') || + (token[0] == ';') || + ((token[0] == '/') && (token[1] == '/'))) { + break; + } + + /* Handle excessively long lines. */ + if (n_tokens >= RTE_DIM(tokens)) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Too many tokens."; + goto error; + } + + /* Handle excessively long tokens. */ + if (strnlen(token, RTE_SWX_NAME_SIZE) >= + RTE_SWX_NAME_SIZE) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Token too big."; + goto error; + } + + /* Save token. */ + tokens[n_tokens] = token; + n_tokens++; + } + + /* Handle empty lines. */ + if (!n_tokens) + continue; + + /* mirroring. */ + if ((n_tokens >= 1) && !strcmp(tokens[0], "mirroring")) { + int status = 0; + + status = mirroring_parse(&s->mirroring_params, + &tokens[1], + n_tokens - 1, + err_msg); + if (status) { + if (err_line) + *err_line = n_lines; + goto error; + } + + continue; + } + + /* port in. */ + if ((n_tokens >= 4) && !strcmp(tokens[0], "port") && !strcmp(tokens[1], "in")) { + char *token = tokens[2]; + uint32_t *new_id = NULL; + const char **new_type = NULL, *port_type = NULL; + void **new_params = NULL, *p = NULL; + uint32_t port_id; + + /* . */ + port_id = strtoul(token, &token, 0); + if (token[0]) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Invalid port ID."; + goto error; + } + + /* . */ + if (!strcmp(tokens[3], "ethdev")) + p = port_in_ethdev_parse(&tokens[4], n_tokens - 4, err_msg); + else if (!strcmp(tokens[3], "ring")) + p = port_in_ring_parse(&tokens[4], n_tokens - 4, err_msg); + else if (!strcmp(tokens[3], "source")) + p = port_in_source_parse(&tokens[4], n_tokens - 4, err_msg); + else if (!strcmp(tokens[3], "fd")) + p = port_in_fd_parse(&tokens[4], n_tokens - 4, err_msg); + else { + p = NULL; + if (err_msg) + *err_msg = "Invalid port type."; + } + + if (!p) { + if (err_line) + *err_line = n_lines; + goto error; + } + + /* New port. */ + port_type = strdup(tokens[3]); + new_id = realloc(s->port_in_id, + (s->n_ports_in + 1) * sizeof(uint32_t)); + new_type = realloc(s->port_in_type, + (s->n_ports_in + 1) * sizeof(char *)); + new_params = realloc(s->port_in_params, + (s->n_ports_in + 1) * sizeof(void *)); + if (!port_type || !new_id || !new_type || !new_params) { + uintptr_t pt = (uintptr_t)port_type; + + port_in_params_free(p, tokens[3]); + free((void *)pt); + free(new_id); + free(new_type); + free(new_params); + + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Memory allocation failed."; + goto error; + } + + s->port_in_id = new_id; + s->port_in_type = new_type; + s->port_in_params = new_params; + + s->port_in_id[s->n_ports_in] = port_id; + s->port_in_type[s->n_ports_in] = port_type; + s->port_in_params[s->n_ports_in] = p; + s->n_ports_in++; + + continue; + } + + /* port out. */ + if ((n_tokens >= 4) && !strcmp(tokens[0], "port") && !strcmp(tokens[1], "out")) { + char *token = tokens[2]; + uint32_t *new_id = NULL; + const char **new_type = NULL, *port_type = NULL; + void **new_params = NULL, *p = NULL; + uint32_t port_id; + + /* . */ + port_id = strtoul(token, &token, 0); + if (token[0]) { + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Invalid port ID."; + goto error; + } + + /* . */ + if (!strcmp(tokens[3], "ethdev")) + p = port_out_ethdev_parse(&tokens[4], n_tokens - 4, err_msg); + else if (!strcmp(tokens[3], "ring")) + p = port_out_ring_parse(&tokens[4], n_tokens - 4, err_msg); + else if (!strcmp(tokens[3], "sink")) + p = port_out_sink_parse(&tokens[4], n_tokens - 4, err_msg); + else if (!strcmp(tokens[3], "fd")) + p = port_out_fd_parse(&tokens[4], n_tokens - 4, err_msg); + else { + p = NULL; + if (err_msg) + *err_msg = "Invalid port type."; + } + + if (!p) { + if (err_line) + *err_line = n_lines; + goto error; + } + + /* New port. */ + port_type = strdup(tokens[3]); + new_id = realloc(s->port_out_id, + (s->n_ports_out + 1) * sizeof(uint32_t)); + new_type = realloc(s->port_out_type, + (s->n_ports_out + 1) * sizeof(char *)); + new_params = realloc(s->port_out_params, + (s->n_ports_out + 1) * sizeof(void *)); + if (!port_type || !new_id || !new_type || !new_params) { + uintptr_t pt = (uintptr_t)port_type; + + port_out_params_free(p, tokens[3]); + free((void *)pt); + free(new_id); + free(new_type); + free(new_params); + + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Memory allocation failed."; + goto error; + } + + s->port_out_id = new_id; + s->port_out_type = new_type; + s->port_out_params = new_params; + + s->port_out_id[s->n_ports_out] = port_id; + s->port_out_type[s->n_ports_out] = port_type; + s->port_out_params[s->n_ports_out] = p; + s->n_ports_out++; + + continue; + } + + /* Anything else. */ + if (err_line) + *err_line = n_lines; + if (err_msg) + *err_msg = "Unknown I/O statement."; + goto error; + } + + return s; + +error: + pipeline_iospec_free(s); + + return NULL; +} + +int +pipeline_iospec_configure(struct rte_swx_pipeline *p, + struct pipeline_iospec *s, + const char **err_msg) +{ + uint32_t i; + int status = 0; + + /* Check input arguments. */ + if (!p || !s) { + if (err_msg) + *err_msg = "Invalid input argument"; + return -EINVAL; + } + + /* Mirroring. */ + status = rte_swx_pipeline_mirroring_config(p, &s->mirroring_params); + if (status) { + if (err_msg) + *err_msg = "Pipeline mirroring configuration error."; + return status; + } + + /* Input ports. */ + for (i = 0; i < s->n_ports_in; i++) { + status = rte_swx_pipeline_port_in_config(p, + i, + s->port_in_type[i], + s->port_in_params[i]); + if (status) { + if (err_msg) + *err_msg = "Pipeline input port configuration error."; + return status; + } + } + + /* Output ports. */ + for (i = 0; i < s->n_ports_out; i++) { + status = rte_swx_pipeline_port_out_config(p, + i, + s->port_out_type[i], + s->port_out_params[i]); + if (status) { + if (err_msg) + *err_msg = "Pipeline output port configuration error."; + return status; + } + } + + return 0; +} diff --git a/lib/pipeline/rte_swx_pipeline_spec.h b/lib/pipeline/rte_swx_pipeline_spec.h index 707b99ba09..62ac4ecfc4 100644 --- a/lib/pipeline/rte_swx_pipeline_spec.h +++ b/lib/pipeline/rte_swx_pipeline_spec.h @@ -1,6 +1,13 @@ /* SPDX-License-Identifier: BSD-3-Clause * Copyright(c) 2022 Intel Corporation */ +#ifndef __INCLUDE_RTE_SWX_PIPELINE_SPEC_H__ +#define __INCLUDE_RTE_SWX_PIPELINE_SPEC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + #include #include @@ -204,6 +211,38 @@ struct pipeline_spec { uint32_t n_apply; }; +/* + * Mirroring: + * mirroring slots sessions + * + * Input ports: + * port in ethdev rxq bsz + * port in ring bsz + * port in source mempool file loop + * packets + * port in fd mtu mempool bsz + * + * Output ports: + * port out ethdev txq bsz + * port out ring bsz + * port out sink file | none + * port out fd bsz + */ +struct pipeline_iospec { + struct rte_swx_pipeline_mirroring_params mirroring_params; + + uint32_t *port_in_id; + const char **port_in_type; + void **port_in_params; + + uint32_t *port_out_id; + const char **port_out_type; + void **port_out_params; + + uint32_t n_ports_in; + uint32_t n_ports_out; +}; + void pipeline_spec_free(struct pipeline_spec *s); @@ -220,3 +259,22 @@ int pipeline_spec_configure(struct rte_swx_pipeline *p, struct pipeline_spec *s, const char **err_msg); + +void +pipeline_iospec_free(struct pipeline_iospec *s); + +struct pipeline_iospec * +pipeline_iospec_parse(FILE *spec, + uint32_t *err_line, + const char **err_msg); + +int +pipeline_iospec_configure(struct rte_swx_pipeline *p, + struct pipeline_iospec *s, + const char **err_msg); + +#ifdef __cplusplus +} +#endif + +#endif