diff options
Diffstat (limited to 'common/VIL/pipeline_passthrough/pipeline_passthrough_be.c')
-rw-r--r-- | common/VIL/pipeline_passthrough/pipeline_passthrough_be.c | 787 |
1 files changed, 787 insertions, 0 deletions
diff --git a/common/VIL/pipeline_passthrough/pipeline_passthrough_be.c b/common/VIL/pipeline_passthrough/pipeline_passthrough_be.c new file mode 100644 index 00000000..5b74d75b --- /dev/null +++ b/common/VIL/pipeline_passthrough/pipeline_passthrough_be.c @@ -0,0 +1,787 @@ +/* +// Copyright (c) 2017 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +*/ + +#include <string.h> + +#include <rte_common.h> +#include <rte_malloc.h> +#include <rte_byteorder.h> +#include <rte_table_stub.h> +#include <rte_table_hash.h> +#include <rte_pipeline.h> + +#include "pipeline_passthrough_be.h" +#include "pipeline_actions_common.h" +#include "parser.h" +#include "hash_func.h" + +struct pipeline_passthrough { + struct pipeline p; + struct pipeline_passthrough_params params; + rte_table_hash_op_hash f_hash; +} __rte_cache_aligned; + +static pipeline_msg_req_handler handlers[] = { + [PIPELINE_MSG_REQ_PING] = + pipeline_msg_req_ping_handler, + [PIPELINE_MSG_REQ_STATS_PORT_IN] = + pipeline_msg_req_stats_port_in_handler, + [PIPELINE_MSG_REQ_STATS_PORT_OUT] = + pipeline_msg_req_stats_port_out_handler, + [PIPELINE_MSG_REQ_STATS_TABLE] = + pipeline_msg_req_stats_table_handler, + [PIPELINE_MSG_REQ_PORT_IN_ENABLE] = + pipeline_msg_req_port_in_enable_handler, + [PIPELINE_MSG_REQ_PORT_IN_DISABLE] = + pipeline_msg_req_port_in_disable_handler, + [PIPELINE_MSG_REQ_CUSTOM] = + pipeline_msg_req_invalid_handler, +}; + +static inline __attribute__((always_inline)) void +pkt_work( + struct rte_mbuf *pkt, + void *arg, + uint32_t dma_size, + uint32_t hash_enabled, + uint32_t lb_hash, + uint32_t port_out_pow2) +{ + struct pipeline_passthrough *p = arg; + + uint64_t *dma_dst = RTE_MBUF_METADATA_UINT64_PTR(pkt, + p->params.dma_dst_offset); + uint64_t *dma_src = RTE_MBUF_METADATA_UINT64_PTR(pkt, + p->params.dma_src_offset); + uint64_t *dma_mask = (uint64_t *) p->params.dma_src_mask; + uint32_t *dma_hash = RTE_MBUF_METADATA_UINT32_PTR(pkt, + p->params.dma_hash_offset); + uint32_t i; + + /* Read (dma_src), compute (dma_dst), write (dma_dst) */ + for (i = 0; i < (dma_size / 8); i++) + dma_dst[i] = dma_src[i] & dma_mask[i]; + + /* Read (dma_dst), compute (hash), write (hash) */ + if (hash_enabled) { + uint32_t hash = p->f_hash(dma_dst, dma_size, 0); + *dma_hash = hash; + + if (lb_hash) { + uint32_t port_out; + + if (port_out_pow2) + port_out + = hash & (p->p.n_ports_out - 1); + else + port_out + = hash % p->p.n_ports_out; + + rte_pipeline_port_out_packet_insert(p->p.p, + port_out, pkt); + } + } +} + +static inline __attribute__((always_inline)) void +pkt4_work( + struct rte_mbuf **pkts, + void *arg, + uint32_t dma_size, + uint32_t hash_enabled, + uint32_t lb_hash, + uint32_t port_out_pow2) +{ + struct pipeline_passthrough *p = arg; + + uint64_t *dma_dst0 = RTE_MBUF_METADATA_UINT64_PTR(pkts[0], + p->params.dma_dst_offset); + uint64_t *dma_dst1 = RTE_MBUF_METADATA_UINT64_PTR(pkts[1], + p->params.dma_dst_offset); + uint64_t *dma_dst2 = RTE_MBUF_METADATA_UINT64_PTR(pkts[2], + p->params.dma_dst_offset); + uint64_t *dma_dst3 = RTE_MBUF_METADATA_UINT64_PTR(pkts[3], + p->params.dma_dst_offset); + + uint64_t *dma_src0 = RTE_MBUF_METADATA_UINT64_PTR(pkts[0], + p->params.dma_src_offset); + uint64_t *dma_src1 = RTE_MBUF_METADATA_UINT64_PTR(pkts[1], + p->params.dma_src_offset); + uint64_t *dma_src2 = RTE_MBUF_METADATA_UINT64_PTR(pkts[2], + p->params.dma_src_offset); + uint64_t *dma_src3 = RTE_MBUF_METADATA_UINT64_PTR(pkts[3], + p->params.dma_src_offset); + + uint64_t *dma_mask = (uint64_t *) p->params.dma_src_mask; + + uint32_t *dma_hash0 = RTE_MBUF_METADATA_UINT32_PTR(pkts[0], + p->params.dma_hash_offset); + uint32_t *dma_hash1 = RTE_MBUF_METADATA_UINT32_PTR(pkts[1], + p->params.dma_hash_offset); + uint32_t *dma_hash2 = RTE_MBUF_METADATA_UINT32_PTR(pkts[2], + p->params.dma_hash_offset); + uint32_t *dma_hash3 = RTE_MBUF_METADATA_UINT32_PTR(pkts[3], + p->params.dma_hash_offset); + + uint32_t i; + + /* Read (dma_src), compute (dma_dst), write (dma_dst) */ + for (i = 0; i < (dma_size / 8); i++) { + dma_dst0[i] = dma_src0[i] & dma_mask[i]; + dma_dst1[i] = dma_src1[i] & dma_mask[i]; + dma_dst2[i] = dma_src2[i] & dma_mask[i]; + dma_dst3[i] = dma_src3[i] & dma_mask[i]; + } + + /* Read (dma_dst), compute (hash), write (hash) */ + if (hash_enabled) { + uint32_t hash0 = p->f_hash(dma_dst0, dma_size, 0); + uint32_t hash1 = p->f_hash(dma_dst1, dma_size, 0); + uint32_t hash2 = p->f_hash(dma_dst2, dma_size, 0); + uint32_t hash3 = p->f_hash(dma_dst3, dma_size, 0); + + *dma_hash0 = hash0; + *dma_hash1 = hash1; + *dma_hash2 = hash2; + *dma_hash3 = hash3; + + if (lb_hash) { + uint32_t port_out0, port_out1, port_out2, port_out3; + + if (port_out_pow2) { + port_out0 + = hash0 & (p->p.n_ports_out - 1); + port_out1 + = hash1 & (p->p.n_ports_out - 1); + port_out2 + = hash2 & (p->p.n_ports_out - 1); + port_out3 + = hash3 & (p->p.n_ports_out - 1); + } else { + port_out0 + = hash0 % p->p.n_ports_out; + port_out1 + = hash1 % p->p.n_ports_out; + port_out2 + = hash2 % p->p.n_ports_out; + port_out3 + = hash3 % p->p.n_ports_out; + } + rte_pipeline_port_out_packet_insert(p->p.p, + port_out0, pkts[0]); + rte_pipeline_port_out_packet_insert(p->p.p, + port_out1, pkts[1]); + rte_pipeline_port_out_packet_insert(p->p.p, + port_out2, pkts[2]); + rte_pipeline_port_out_packet_insert(p->p.p, + port_out3, pkts[3]); + } + } +} + +#define PKT_WORK(dma_size, hash_enabled, lb_hash, port_pow2) \ +static inline void \ +pkt_work_size##dma_size##_hash##hash_enabled \ + ##_lb##lb_hash##_pw##port_pow2( \ + struct rte_mbuf *pkt, \ + void *arg) \ +{ \ + pkt_work(pkt, arg, dma_size, hash_enabled, lb_hash, port_pow2); \ +} + +#define PKT4_WORK(dma_size, hash_enabled, lb_hash, port_pow2) \ +static inline void \ +pkt4_work_size##dma_size##_hash##hash_enabled \ + ##_lb##lb_hash##_pw##port_pow2( \ + struct rte_mbuf **pkts, \ + void *arg) \ +{ \ + pkt4_work(pkts, arg, dma_size, hash_enabled, lb_hash, port_pow2); \ +} + +#define port_in_ah(dma_size, hash_enabled, lb_hash, port_pow2) \ +PKT_WORK(dma_size, hash_enabled, lb_hash, port_pow2) \ +PKT4_WORK(dma_size, hash_enabled, lb_hash, port_pow2) \ +PIPELINE_PORT_IN_AH(port_in_ah_size##dma_size##_hash \ + ##hash_enabled##_lb##lb_hash##_pw##port_pow2, \ + pkt_work_size##dma_size##_hash##hash_enabled \ + ##_lb##lb_hash##_pw##port_pow2, \ + pkt4_work_size##dma_size##_hash##hash_enabled \ + ##_lb##lb_hash##_pw##port_pow2) + + +#define port_in_ah_lb(dma_size, hash_enabled, lb_hash, port_pow2) \ +PKT_WORK(dma_size, hash_enabled, lb_hash, port_pow2) \ +PKT4_WORK(dma_size, hash_enabled, lb_hash, port_pow2) \ +PIPELINE_PORT_IN_AH_HIJACK_ALL( \ + port_in_ah_size##dma_size##_hash##hash_enabled \ + ##_lb##lb_hash##_pw##port_pow2, \ + pkt_work_size##dma_size##_hash##hash_enabled \ + ##_lb##lb_hash##_pw##port_pow2, \ + pkt4_work_size##dma_size##_hash##hash_enabled \ + ##_lb##lb_hash##_pw##port_pow2) + +/* Port in AH (dma_size, hash_enabled, lb_hash, port_pow2) */ + +port_in_ah(8, 0, 0, 0) +port_in_ah(8, 1, 0, 0) +port_in_ah_lb(8, 1, 1, 0) +port_in_ah_lb(8, 1, 1, 1) + +port_in_ah(16, 0, 0, 0) +port_in_ah(16, 1, 0, 0) +port_in_ah_lb(16, 1, 1, 0) +port_in_ah_lb(16, 1, 1, 1) + +port_in_ah(24, 0, 0, 0) +port_in_ah(24, 1, 0, 0) +port_in_ah_lb(24, 1, 1, 0) +port_in_ah_lb(24, 1, 1, 1) + +port_in_ah(32, 0, 0, 0) +port_in_ah(32, 1, 0, 0) +port_in_ah_lb(32, 1, 1, 0) +port_in_ah_lb(32, 1, 1, 1) + +port_in_ah(40, 0, 0, 0) +port_in_ah(40, 1, 0, 0) +port_in_ah_lb(40, 1, 1, 0) +port_in_ah_lb(40, 1, 1, 1) + +port_in_ah(48, 0, 0, 0) +port_in_ah(48, 1, 0, 0) +port_in_ah_lb(48, 1, 1, 0) +port_in_ah_lb(48, 1, 1, 1) + +port_in_ah(56, 0, 0, 0) +port_in_ah(56, 1, 0, 0) +port_in_ah_lb(56, 1, 1, 0) +port_in_ah_lb(56, 1, 1, 1) + +port_in_ah(64, 0, 0, 0) +port_in_ah(64, 1, 0, 0) +port_in_ah_lb(64, 1, 1, 0) +port_in_ah_lb(64, 1, 1, 1) + +static rte_pipeline_port_in_action_handler +get_port_in_ah(struct pipeline_passthrough *p) +{ + if (p->params.dma_enabled == 0) + return NULL; + + if (p->params.dma_hash_enabled) { + if (p->params.lb_hash_enabled) { + if (rte_is_power_of_2(p->p.n_ports_out)) + switch (p->params.dma_size) { + + case 8: return port_in_ah_size8_hash1_lb1_pw1; + case 16: return port_in_ah_size16_hash1_lb1_pw1; + case 24: return port_in_ah_size24_hash1_lb1_pw1; + case 32: return port_in_ah_size32_hash1_lb1_pw1; + case 40: return port_in_ah_size40_hash1_lb1_pw1; + case 48: return port_in_ah_size48_hash1_lb1_pw1; + case 56: return port_in_ah_size56_hash1_lb1_pw1; + case 64: return port_in_ah_size64_hash1_lb1_pw1; + default: return NULL; + } + else + switch (p->params.dma_size) { + + case 8: return port_in_ah_size8_hash1_lb1_pw0; + case 16: return port_in_ah_size16_hash1_lb1_pw0; + case 24: return port_in_ah_size24_hash1_lb1_pw0; + case 32: return port_in_ah_size32_hash1_lb1_pw0; + case 40: return port_in_ah_size40_hash1_lb1_pw0; + case 48: return port_in_ah_size48_hash1_lb1_pw0; + case 56: return port_in_ah_size56_hash1_lb1_pw0; + case 64: return port_in_ah_size64_hash1_lb1_pw0; + default: return NULL; + } + } else + switch (p->params.dma_size) { + + case 8: return port_in_ah_size8_hash1_lb0_pw0; + case 16: return port_in_ah_size16_hash1_lb0_pw0; + case 24: return port_in_ah_size24_hash1_lb0_pw0; + case 32: return port_in_ah_size32_hash1_lb0_pw0; + case 40: return port_in_ah_size40_hash1_lb0_pw0; + case 48: return port_in_ah_size48_hash1_lb0_pw0; + case 56: return port_in_ah_size56_hash1_lb0_pw0; + case 64: return port_in_ah_size64_hash1_lb0_pw0; + default: return NULL; + } + } else + switch (p->params.dma_size) { + + case 8: return port_in_ah_size8_hash0_lb0_pw0; + case 16: return port_in_ah_size16_hash0_lb0_pw0; + case 24: return port_in_ah_size24_hash0_lb0_pw0; + case 32: return port_in_ah_size32_hash0_lb0_pw0; + case 40: return port_in_ah_size40_hash0_lb0_pw0; + case 48: return port_in_ah_size48_hash0_lb0_pw0; + case 56: return port_in_ah_size56_hash0_lb0_pw0; + case 64: return port_in_ah_size64_hash0_lb0_pw0; + default: return NULL; + } +} + +int +pipeline_passthrough_parse_args(struct pipeline_passthrough_params *p, + struct pipeline_params *params) +{ + uint32_t dma_dst_offset_present = 0; + uint32_t dma_src_offset_present = 0; + uint32_t dma_src_mask_present = 0; + uint32_t dma_size_present = 0; + uint32_t dma_hash_offset_present = 0; + uint32_t lb_present = 0; + uint32_t i; + char dma_mask_str[PIPELINE_PASSTHROUGH_DMA_SIZE_MAX * 2]; + + /* default values */ + p->dma_enabled = 0; + p->dma_hash_enabled = 0; + p->lb_hash_enabled = 0; + memset(p->dma_src_mask, 0xFF, sizeof(p->dma_src_mask)); + + for (i = 0; i < params->n_args; i++) { + char *arg_name = params->args_name[i]; + char *arg_value = params->args_value[i]; + + /* dma_dst_offset */ + if (strcmp(arg_name, "dma_dst_offset") == 0) { + int status; + + PIPELINE_PARSE_ERR_DUPLICATE( + dma_dst_offset_present == 0, params->name, + arg_name); + dma_dst_offset_present = 1; + + status = parser_read_uint32(&p->dma_dst_offset, + arg_value); + PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL), + params->name, arg_name, arg_value); + PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE), + params->name, arg_name, arg_value); + + p->dma_enabled = 1; + + continue; + } + + /* dma_src_offset */ + if (strcmp(arg_name, "dma_src_offset") == 0) { + int status; + + PIPELINE_PARSE_ERR_DUPLICATE( + dma_src_offset_present == 0, params->name, + arg_name); + dma_src_offset_present = 1; + + status = parser_read_uint32(&p->dma_src_offset, + arg_value); + PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL), + params->name, arg_name, arg_value); + PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE), + params->name, arg_name, arg_value); + + p->dma_enabled = 1; + + continue; + } + + /* dma_size */ + if (strcmp(arg_name, "dma_size") == 0) { + int status; + + PIPELINE_PARSE_ERR_DUPLICATE( + dma_size_present == 0, params->name, + arg_name); + dma_size_present = 1; + + status = parser_read_uint32(&p->dma_size, + arg_value); + PIPELINE_PARSE_ERR_INV_VAL(((status != -EINVAL) && + (p->dma_size != 0) && + ((p->dma_size % 8) == 0)), + params->name, arg_name, arg_value); + PIPELINE_PARSE_ERR_OUT_RNG(((status != -ERANGE) && + (p->dma_size <= + PIPELINE_PASSTHROUGH_DMA_SIZE_MAX)), + params->name, arg_name, arg_value); + + p->dma_enabled = 1; + + continue; + } + + /* dma_src_mask */ + if (strcmp(arg_name, "dma_src_mask") == 0) { + int mask_str_len = strlen(arg_value); + + PIPELINE_PARSE_ERR_DUPLICATE( + dma_src_mask_present == 0, + params->name, arg_name); + dma_src_mask_present = 1; + + PIPELINE_ARG_CHECK((mask_str_len < + (PIPELINE_PASSTHROUGH_DMA_SIZE_MAX * 2)), + "Parse error in section \"%s\": entry " + "\"%s\" too long", params->name, + arg_name); + + snprintf(dma_mask_str, mask_str_len + 1, + "%s", arg_value); + + p->dma_enabled = 1; + + continue; + } + + /* dma_hash_offset */ + if (strcmp(arg_name, "dma_hash_offset") == 0) { + int status; + + PIPELINE_PARSE_ERR_DUPLICATE( + dma_hash_offset_present == 0, + params->name, arg_name); + dma_hash_offset_present = 1; + + status = parser_read_uint32(&p->dma_hash_offset, + arg_value); + PIPELINE_PARSE_ERR_INV_VAL((status != -EINVAL), + params->name, arg_name, arg_value); + PIPELINE_PARSE_ERR_OUT_RNG((status != -ERANGE), + params->name, arg_name, arg_value); + + p->dma_hash_enabled = 1; + p->dma_enabled = 1; + + continue; + } + + /* load_balance mode */ + if (strcmp(arg_name, "lb") == 0) { + PIPELINE_PARSE_ERR_DUPLICATE( + lb_present == 0, + params->name, arg_name); + lb_present = 1; + + if ((strcmp(arg_value, "hash") == 0) || + (strcmp(arg_value, "HASH") == 0)) + p->lb_hash_enabled = 1; + else + PIPELINE_PARSE_ERR_INV_VAL(0, + params->name, + arg_name, + arg_value); + + continue; + } + + /* any other */ + PIPELINE_PARSE_ERR_INV_ENT(0, params->name, arg_name); + } + + /* Check correlations between arguments */ + PIPELINE_ARG_CHECK((dma_dst_offset_present == p->dma_enabled), + "Parse error in section \"%s\": missing entry " + "\"dma_dst_offset\"", params->name); + PIPELINE_ARG_CHECK((dma_src_offset_present == p->dma_enabled), + "Parse error in section \"%s\": missing entry " + "\"dma_src_offset\"", params->name); + PIPELINE_ARG_CHECK((dma_size_present == p->dma_enabled), + "Parse error in section \"%s\": missing entry " + "\"dma_size\"", params->name); + PIPELINE_ARG_CHECK((dma_hash_offset_present == p->dma_enabled), + "Parse error in section \"%s\": missing entry " + "\"dma_hash_offset\"", params->name); + PIPELINE_ARG_CHECK((p->lb_hash_enabled <= p->dma_hash_enabled), + "Parse error in section \"%s\": missing entry " + "\"dma_hash_offset\"", params->name); + + if (dma_src_mask_present) { + uint32_t dma_size = p->dma_size; + int status; + + PIPELINE_ARG_CHECK((strlen(dma_mask_str) == + (dma_size * 2)), "Parse error in section " + "\"%s\": dma_src_mask should have exactly %u hex " + "digits", params->name, (dma_size * 2)); + + status = parse_hex_string(dma_mask_str, p->dma_src_mask, + &p->dma_size); + + PIPELINE_PARSE_ERR_INV_VAL(((status == 0) && + (dma_size == p->dma_size)), params->name, + "dma_src_mask", dma_mask_str); + } + + return 0; +} + + +static rte_table_hash_op_hash +get_hash_function(struct pipeline_passthrough *p) +{ + switch (p->params.dma_size) { + + case 8: return hash_default_key8; + case 16: return hash_default_key16; + case 24: return hash_default_key24; + case 32: return hash_default_key32; + case 40: return hash_default_key40; + case 48: return hash_default_key48; + case 56: return hash_default_key56; + case 64: return hash_default_key64; + default: return NULL; + } +} + +static void* +pipeline_passthrough_init(struct pipeline_params *params, + __rte_unused void *arg) +{ + struct pipeline *p; + struct pipeline_passthrough *p_pt; + uint32_t size, i; + + /* Check input arguments */ + if ((params == NULL) || + (params->n_ports_in == 0) || + (params->n_ports_out == 0) || + (params->n_ports_in < params->n_ports_out) || + (params->n_ports_in % params->n_ports_out)) + return NULL; + + /* Memory allocation */ + size = RTE_CACHE_LINE_ROUNDUP(sizeof(struct pipeline_passthrough)); + p = rte_zmalloc(NULL, size, RTE_CACHE_LINE_SIZE); + p_pt = (struct pipeline_passthrough *) p; + if (p == NULL) + return NULL; + + strcpy(p->name, params->name); + p->log_level = params->log_level; + + PLOG(p, HIGH, "Pass-through"); + + /* Parse arguments */ + if (pipeline_passthrough_parse_args(&p_pt->params, params)) + return NULL; + p_pt->f_hash = get_hash_function(p_pt); + + /* Pipeline */ + { + struct rte_pipeline_params pipeline_params = { + .name = "PASS-THROUGH", + .socket_id = params->socket_id, + .offset_port_id = 0, + }; + + p->p = rte_pipeline_create(&pipeline_params); + if (p->p == NULL) { + rte_free(p); + return NULL; + } + } + + p->n_ports_in = params->n_ports_in; + p->n_ports_out = params->n_ports_out; + p->n_tables = p->n_ports_in; + + /*Input ports*/ + for (i = 0; i < p->n_ports_in; i++) { + struct rte_pipeline_port_in_params port_params = { + .ops = pipeline_port_in_params_get_ops( + ¶ms->port_in[i]), + .arg_create = pipeline_port_in_params_convert( + ¶ms->port_in[i]), + .f_action = get_port_in_ah(p_pt), + .arg_ah = p_pt, + .burst_size = params->port_in[i].burst_size, + }; + + int status = rte_pipeline_port_in_create(p->p, + &port_params, + &p->port_in_id[i]); + + if (status) { + rte_pipeline_free(p->p); + rte_free(p); + return NULL; + } + } + + /* Output ports */ + for (i = 0; i < p->n_ports_out; i++) { + struct rte_pipeline_port_out_params port_params = { + .ops = pipeline_port_out_params_get_ops( + ¶ms->port_out[i]), + .arg_create = pipeline_port_out_params_convert( + ¶ms->port_out[i]), + .f_action = NULL, + .arg_ah = NULL, + }; + + int status = rte_pipeline_port_out_create(p->p, + &port_params, + &p->port_out_id[i]); + + if (status) { + rte_pipeline_free(p->p); + rte_free(p); + return NULL; + } + } + + /* Tables */ + for (i = 0; i < p->n_ports_in; i++) { + struct rte_pipeline_table_params table_params = { + .ops = &rte_table_stub_ops, + .arg_create = NULL, + .f_action_hit = NULL, + .f_action_miss = NULL, + .arg_ah = NULL, + .action_data_size = 0, + }; + + int status = rte_pipeline_table_create(p->p, + &table_params, + &p->table_id[i]); + + if (status) { + rte_pipeline_free(p->p); + rte_free(p); + return NULL; + } + } + + /* Connecting input ports to tables */ + for (i = 0; i < p->n_ports_in; i++) { + int status = rte_pipeline_port_in_connect_to_table(p->p, + p->port_in_id[i], + p->table_id[i]); + + if (status) { + rte_pipeline_free(p->p); + rte_free(p); + return NULL; + } + } + + /* Add entries to tables */ + for (i = 0; i < p->n_ports_in; i++) { + struct rte_pipeline_table_entry default_entry = { + .action = RTE_PIPELINE_ACTION_PORT, + {.port_id = p->port_out_id[ + i / (p->n_ports_in / p->n_ports_out)]}, + }; + + struct rte_pipeline_table_entry *default_entry_ptr; + + int status = rte_pipeline_table_default_entry_add(p->p, + p->table_id[i], + &default_entry, + &default_entry_ptr); + + if (status) { + rte_pipeline_free(p->p); + rte_free(p); + return NULL; + } + } + + /* Enable input ports */ + for (i = 0; i < p->n_ports_in; i++) { + int status = rte_pipeline_port_in_enable(p->p, + p->port_in_id[i]); + + if (status) { + rte_pipeline_free(p->p); + rte_free(p); + return NULL; + } + } + + /* Check pipeline consistency */ + if (rte_pipeline_check(p->p) < 0) { + rte_pipeline_free(p->p); + rte_free(p); + return NULL; + } + + /* Message queues */ + p->n_msgq = params->n_msgq; + for (i = 0; i < p->n_msgq; i++) + p->msgq_in[i] = params->msgq_in[i]; + for (i = 0; i < p->n_msgq; i++) + p->msgq_out[i] = params->msgq_out[i]; + + /* Message handlers */ + memcpy(p->handlers, handlers, sizeof(p->handlers)); + + return p; +} + +static int +pipeline_passthrough_free(void *pipeline) +{ + struct pipeline *p = (struct pipeline *) pipeline; + + /* Check input arguments */ + if (p == NULL) + return -1; + + /* Free resources */ + rte_pipeline_free(p->p); + rte_free(p); + return 0; +} + +static int +pipeline_passthrough_timer(void *pipeline) +{ + struct pipeline *p = (struct pipeline *) pipeline; + + pipeline_msg_req_handle(p); + rte_pipeline_flush(p->p); + + return 0; +} + +static int +pipeline_passthrough_track(void *pipeline, uint32_t port_in, uint32_t *port_out) +{ + struct pipeline *p = (struct pipeline *) pipeline; + + /* Check input arguments */ + if ((p == NULL) || + (port_in >= p->n_ports_in) || + (port_out == NULL)) + return -1; + + *port_out = port_in / p->n_ports_in; + return 0; +} + +struct pipeline_be_ops pipeline_passthrough_be_ops = { + .f_init = pipeline_passthrough_init, + .f_free = pipeline_passthrough_free, + .f_run = NULL, + .f_timer = pipeline_passthrough_timer, + .f_track = pipeline_passthrough_track, +}; |