199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
299a2dd95SBruce Richardson * Copyright(c) 2010-2016 Intel Corporation
399a2dd95SBruce Richardson */
499a2dd95SBruce Richardson
599a2dd95SBruce Richardson #include <string.h>
699a2dd95SBruce Richardson #include <stdio.h>
799a2dd95SBruce Richardson
899a2dd95SBruce Richardson #include <rte_common.h>
999a2dd95SBruce Richardson #include <rte_mbuf.h>
1099a2dd95SBruce Richardson #include <rte_malloc.h>
1199a2dd95SBruce Richardson #include <rte_string_fns.h>
1299a2dd95SBruce Richardson
1399a2dd95SBruce Richardson #include "rte_pipeline.h"
1499a2dd95SBruce Richardson
15d4af9a82SStephen Hemminger RTE_LOG_REGISTER_DEFAULT(pipeline_logtype, INFO);
16d4af9a82SStephen Hemminger #define RTE_LOGTYPE_PIPELINE pipeline_logtype
17d4af9a82SStephen Hemminger
1897433132SDavid Marchand #define PIPELINE_LOG(level, ...) \
1997433132SDavid Marchand RTE_LOG_LINE(level, PIPELINE, "" __VA_ARGS__)
20ae67895bSDavid Marchand
2199a2dd95SBruce Richardson #define RTE_TABLE_INVALID UINT32_MAX
2299a2dd95SBruce Richardson
2399a2dd95SBruce Richardson #ifdef RTE_PIPELINE_STATS_COLLECT
2499a2dd95SBruce Richardson
2599a2dd95SBruce Richardson #define RTE_PIPELINE_STATS_AH_DROP_WRITE(p, mask) \
2693998f3cSTyler Retzlaff __extension__ ({ (p)->n_pkts_ah_drop = rte_popcount64(mask); })
2799a2dd95SBruce Richardson
2899a2dd95SBruce Richardson #define RTE_PIPELINE_STATS_AH_DROP_READ(p, counter) \
2993998f3cSTyler Retzlaff __extension__ ({ (counter) += (p)->n_pkts_ah_drop; (p)->n_pkts_ah_drop = 0; })
3099a2dd95SBruce Richardson
3199a2dd95SBruce Richardson #define RTE_PIPELINE_STATS_TABLE_DROP0(p) \
3293998f3cSTyler Retzlaff __extension__ ({ (p)->pkts_drop_mask = (p)->action_mask0[RTE_PIPELINE_ACTION_DROP]; })
3399a2dd95SBruce Richardson
3499a2dd95SBruce Richardson #define RTE_PIPELINE_STATS_TABLE_DROP1(p, counter) \
3593998f3cSTyler Retzlaff __extension__ ({ \
3699a2dd95SBruce Richardson uint64_t mask = (p)->action_mask0[RTE_PIPELINE_ACTION_DROP]; \
3799a2dd95SBruce Richardson mask ^= (p)->pkts_drop_mask; \
383d4e27fdSDavid Marchand (counter) += rte_popcount64(mask); \
3999a2dd95SBruce Richardson })
4099a2dd95SBruce Richardson
4199a2dd95SBruce Richardson #else
4299a2dd95SBruce Richardson
4399a2dd95SBruce Richardson #define RTE_PIPELINE_STATS_AH_DROP_WRITE(p, mask)
4499a2dd95SBruce Richardson #define RTE_PIPELINE_STATS_AH_DROP_READ(p, counter)
4599a2dd95SBruce Richardson #define RTE_PIPELINE_STATS_TABLE_DROP0(p)
4699a2dd95SBruce Richardson #define RTE_PIPELINE_STATS_TABLE_DROP1(p, counter)
4799a2dd95SBruce Richardson
4899a2dd95SBruce Richardson #endif
4999a2dd95SBruce Richardson
5099a2dd95SBruce Richardson struct rte_port_in {
5199a2dd95SBruce Richardson /* Input parameters */
5299a2dd95SBruce Richardson struct rte_port_in_ops ops;
5399a2dd95SBruce Richardson rte_pipeline_port_in_action_handler f_action;
5499a2dd95SBruce Richardson void *arg_ah;
5599a2dd95SBruce Richardson uint32_t burst_size;
5699a2dd95SBruce Richardson
5799a2dd95SBruce Richardson /* The table to which this port is connected */
5899a2dd95SBruce Richardson uint32_t table_id;
5999a2dd95SBruce Richardson
6099a2dd95SBruce Richardson /* Handle to low-level port */
6199a2dd95SBruce Richardson void *h_port;
6299a2dd95SBruce Richardson
6399a2dd95SBruce Richardson /* List of enabled ports */
6499a2dd95SBruce Richardson struct rte_port_in *next;
6599a2dd95SBruce Richardson
6699a2dd95SBruce Richardson /* Statistics */
6799a2dd95SBruce Richardson uint64_t n_pkts_dropped_by_ah;
6899a2dd95SBruce Richardson };
6999a2dd95SBruce Richardson
7099a2dd95SBruce Richardson struct rte_port_out {
7199a2dd95SBruce Richardson /* Input parameters */
7299a2dd95SBruce Richardson struct rte_port_out_ops ops;
7399a2dd95SBruce Richardson rte_pipeline_port_out_action_handler f_action;
7499a2dd95SBruce Richardson void *arg_ah;
7599a2dd95SBruce Richardson
7699a2dd95SBruce Richardson /* Handle to low-level port */
7799a2dd95SBruce Richardson void *h_port;
7899a2dd95SBruce Richardson
7999a2dd95SBruce Richardson /* Statistics */
8099a2dd95SBruce Richardson uint64_t n_pkts_dropped_by_ah;
8199a2dd95SBruce Richardson };
8299a2dd95SBruce Richardson
8399a2dd95SBruce Richardson struct rte_table {
8499a2dd95SBruce Richardson /* Input parameters */
8599a2dd95SBruce Richardson struct rte_table_ops ops;
8699a2dd95SBruce Richardson rte_pipeline_table_action_handler_hit f_action_hit;
8799a2dd95SBruce Richardson rte_pipeline_table_action_handler_miss f_action_miss;
8899a2dd95SBruce Richardson void *arg_ah;
8999a2dd95SBruce Richardson struct rte_pipeline_table_entry *default_entry;
9099a2dd95SBruce Richardson uint32_t entry_size;
9199a2dd95SBruce Richardson
9299a2dd95SBruce Richardson uint32_t table_next_id;
9399a2dd95SBruce Richardson uint32_t table_next_id_valid;
9499a2dd95SBruce Richardson
9599a2dd95SBruce Richardson /* Handle to the low-level table object */
9699a2dd95SBruce Richardson void *h_table;
9799a2dd95SBruce Richardson
9899a2dd95SBruce Richardson /* Statistics */
9999a2dd95SBruce Richardson uint64_t n_pkts_dropped_by_lkp_hit_ah;
10099a2dd95SBruce Richardson uint64_t n_pkts_dropped_by_lkp_miss_ah;
10199a2dd95SBruce Richardson uint64_t n_pkts_dropped_lkp_hit;
10299a2dd95SBruce Richardson uint64_t n_pkts_dropped_lkp_miss;
10399a2dd95SBruce Richardson };
10499a2dd95SBruce Richardson
10599a2dd95SBruce Richardson #define RTE_PIPELINE_MAX_NAME_SZ 124
10699a2dd95SBruce Richardson
107*c6552d9aSTyler Retzlaff struct __rte_cache_aligned rte_pipeline {
10899a2dd95SBruce Richardson /* Input parameters */
10999a2dd95SBruce Richardson char name[RTE_PIPELINE_MAX_NAME_SZ];
11099a2dd95SBruce Richardson int socket_id;
11199a2dd95SBruce Richardson uint32_t offset_port_id;
11299a2dd95SBruce Richardson
11399a2dd95SBruce Richardson /* Internal tables */
11499a2dd95SBruce Richardson struct rte_port_in ports_in[RTE_PIPELINE_PORT_IN_MAX];
11599a2dd95SBruce Richardson struct rte_port_out ports_out[RTE_PIPELINE_PORT_OUT_MAX];
11699a2dd95SBruce Richardson struct rte_table tables[RTE_PIPELINE_TABLE_MAX];
11799a2dd95SBruce Richardson
11899a2dd95SBruce Richardson /* Occupancy of internal tables */
11999a2dd95SBruce Richardson uint32_t num_ports_in;
12099a2dd95SBruce Richardson uint32_t num_ports_out;
12199a2dd95SBruce Richardson uint32_t num_tables;
12299a2dd95SBruce Richardson
12399a2dd95SBruce Richardson /* List of enabled ports */
12499a2dd95SBruce Richardson uint64_t enabled_port_in_mask;
12599a2dd95SBruce Richardson struct rte_port_in *port_in_next;
12699a2dd95SBruce Richardson
12799a2dd95SBruce Richardson /* Pipeline run structures */
12899a2dd95SBruce Richardson struct rte_mbuf *pkts[RTE_PORT_IN_BURST_SIZE_MAX];
12999a2dd95SBruce Richardson struct rte_pipeline_table_entry *entries[RTE_PORT_IN_BURST_SIZE_MAX];
13099a2dd95SBruce Richardson uint64_t action_mask0[RTE_PIPELINE_ACTIONS];
13199a2dd95SBruce Richardson uint64_t action_mask1[RTE_PIPELINE_ACTIONS];
13299a2dd95SBruce Richardson uint64_t pkts_mask;
13399a2dd95SBruce Richardson uint64_t n_pkts_ah_drop;
13499a2dd95SBruce Richardson uint64_t pkts_drop_mask;
135*c6552d9aSTyler Retzlaff };
13699a2dd95SBruce Richardson
13799a2dd95SBruce Richardson static inline uint32_t
rte_mask_get_next(uint64_t mask,uint32_t pos)13899a2dd95SBruce Richardson rte_mask_get_next(uint64_t mask, uint32_t pos)
13999a2dd95SBruce Richardson {
14099a2dd95SBruce Richardson uint64_t mask_rot = (mask << ((63 - pos) & 0x3F)) |
14199a2dd95SBruce Richardson (mask >> ((pos + 1) & 0x3F));
1423d4e27fdSDavid Marchand return (rte_ctz64(mask_rot) - (63 - pos)) & 0x3F;
14399a2dd95SBruce Richardson }
14499a2dd95SBruce Richardson
14599a2dd95SBruce Richardson static inline uint32_t
rte_mask_get_prev(uint64_t mask,uint32_t pos)14699a2dd95SBruce Richardson rte_mask_get_prev(uint64_t mask, uint32_t pos)
14799a2dd95SBruce Richardson {
14899a2dd95SBruce Richardson uint64_t mask_rot = (mask >> (pos & 0x3F)) |
14999a2dd95SBruce Richardson (mask << ((64 - pos) & 0x3F));
1503d4e27fdSDavid Marchand return ((63 - rte_clz64(mask_rot)) + pos) & 0x3F;
15199a2dd95SBruce Richardson }
15299a2dd95SBruce Richardson
15399a2dd95SBruce Richardson static void
15499a2dd95SBruce Richardson rte_pipeline_table_free(struct rte_table *table);
15599a2dd95SBruce Richardson
15699a2dd95SBruce Richardson static void
15799a2dd95SBruce Richardson rte_pipeline_port_in_free(struct rte_port_in *port);
15899a2dd95SBruce Richardson
15999a2dd95SBruce Richardson static void
16099a2dd95SBruce Richardson rte_pipeline_port_out_free(struct rte_port_out *port);
16199a2dd95SBruce Richardson
16299a2dd95SBruce Richardson /*
16399a2dd95SBruce Richardson * Pipeline
16499a2dd95SBruce Richardson */
16599a2dd95SBruce Richardson static int
rte_pipeline_check_params(struct rte_pipeline_params * params)16699a2dd95SBruce Richardson rte_pipeline_check_params(struct rte_pipeline_params *params)
16799a2dd95SBruce Richardson {
16899a2dd95SBruce Richardson if (params == NULL) {
169ae67895bSDavid Marchand PIPELINE_LOG(ERR,
170ae67895bSDavid Marchand "%s: Incorrect value for parameter params", __func__);
17199a2dd95SBruce Richardson return -EINVAL;
17299a2dd95SBruce Richardson }
17399a2dd95SBruce Richardson
17499a2dd95SBruce Richardson /* name */
17599a2dd95SBruce Richardson if (params->name == NULL) {
176ae67895bSDavid Marchand PIPELINE_LOG(ERR,
177ae67895bSDavid Marchand "%s: Incorrect value for parameter name", __func__);
17899a2dd95SBruce Richardson return -EINVAL;
17999a2dd95SBruce Richardson }
18099a2dd95SBruce Richardson
18199a2dd95SBruce Richardson /* socket */
18299a2dd95SBruce Richardson if (params->socket_id < 0) {
183ae67895bSDavid Marchand PIPELINE_LOG(ERR,
184ae67895bSDavid Marchand "%s: Incorrect value for parameter socket_id",
18599a2dd95SBruce Richardson __func__);
18699a2dd95SBruce Richardson return -EINVAL;
18799a2dd95SBruce Richardson }
18899a2dd95SBruce Richardson
18999a2dd95SBruce Richardson return 0;
19099a2dd95SBruce Richardson }
19199a2dd95SBruce Richardson
19299a2dd95SBruce Richardson struct rte_pipeline *
rte_pipeline_create(struct rte_pipeline_params * params)19399a2dd95SBruce Richardson rte_pipeline_create(struct rte_pipeline_params *params)
19499a2dd95SBruce Richardson {
19599a2dd95SBruce Richardson struct rte_pipeline *p;
19699a2dd95SBruce Richardson int status;
19799a2dd95SBruce Richardson
19899a2dd95SBruce Richardson /* Check input parameters */
19999a2dd95SBruce Richardson status = rte_pipeline_check_params(params);
20099a2dd95SBruce Richardson if (status != 0) {
201ae67895bSDavid Marchand PIPELINE_LOG(ERR,
202ae67895bSDavid Marchand "%s: Pipeline params check failed (%d)",
20399a2dd95SBruce Richardson __func__, status);
20499a2dd95SBruce Richardson return NULL;
20599a2dd95SBruce Richardson }
20699a2dd95SBruce Richardson
20799a2dd95SBruce Richardson /* Allocate memory for the pipeline on requested socket */
20899a2dd95SBruce Richardson p = rte_zmalloc_socket("PIPELINE", sizeof(struct rte_pipeline),
20999a2dd95SBruce Richardson RTE_CACHE_LINE_SIZE, params->socket_id);
21099a2dd95SBruce Richardson
21199a2dd95SBruce Richardson if (p == NULL) {
212ae67895bSDavid Marchand PIPELINE_LOG(ERR,
213ae67895bSDavid Marchand "%s: Pipeline memory allocation failed", __func__);
21499a2dd95SBruce Richardson return NULL;
21599a2dd95SBruce Richardson }
21699a2dd95SBruce Richardson
21799a2dd95SBruce Richardson /* Save input parameters */
21899a2dd95SBruce Richardson strlcpy(p->name, params->name, RTE_PIPELINE_MAX_NAME_SZ);
21999a2dd95SBruce Richardson p->socket_id = params->socket_id;
22099a2dd95SBruce Richardson p->offset_port_id = params->offset_port_id;
22199a2dd95SBruce Richardson
22299a2dd95SBruce Richardson /* Initialize pipeline internal data structure */
22399a2dd95SBruce Richardson p->num_ports_in = 0;
22499a2dd95SBruce Richardson p->num_ports_out = 0;
22599a2dd95SBruce Richardson p->num_tables = 0;
22699a2dd95SBruce Richardson p->enabled_port_in_mask = 0;
22799a2dd95SBruce Richardson p->port_in_next = NULL;
22899a2dd95SBruce Richardson p->pkts_mask = 0;
22999a2dd95SBruce Richardson p->n_pkts_ah_drop = 0;
23099a2dd95SBruce Richardson
23199a2dd95SBruce Richardson return p;
23299a2dd95SBruce Richardson }
23399a2dd95SBruce Richardson
23499a2dd95SBruce Richardson int
rte_pipeline_free(struct rte_pipeline * p)23599a2dd95SBruce Richardson rte_pipeline_free(struct rte_pipeline *p)
23699a2dd95SBruce Richardson {
23799a2dd95SBruce Richardson uint32_t i;
23899a2dd95SBruce Richardson
23999a2dd95SBruce Richardson /* Check input parameters */
24099a2dd95SBruce Richardson if (p == NULL) {
241ae67895bSDavid Marchand PIPELINE_LOG(ERR,
242ae67895bSDavid Marchand "%s: rte_pipeline parameter is NULL", __func__);
24399a2dd95SBruce Richardson return -EINVAL;
24499a2dd95SBruce Richardson }
24599a2dd95SBruce Richardson
24699a2dd95SBruce Richardson /* Free input ports */
24799a2dd95SBruce Richardson for (i = 0; i < p->num_ports_in; i++) {
24899a2dd95SBruce Richardson struct rte_port_in *port = &p->ports_in[i];
24999a2dd95SBruce Richardson
25099a2dd95SBruce Richardson rte_pipeline_port_in_free(port);
25199a2dd95SBruce Richardson }
25299a2dd95SBruce Richardson
25399a2dd95SBruce Richardson /* Free tables */
25499a2dd95SBruce Richardson for (i = 0; i < p->num_tables; i++) {
25599a2dd95SBruce Richardson struct rte_table *table = &p->tables[i];
25699a2dd95SBruce Richardson
25799a2dd95SBruce Richardson rte_pipeline_table_free(table);
25899a2dd95SBruce Richardson }
25999a2dd95SBruce Richardson
26099a2dd95SBruce Richardson /* Free output ports */
26199a2dd95SBruce Richardson for (i = 0; i < p->num_ports_out; i++) {
26299a2dd95SBruce Richardson struct rte_port_out *port = &p->ports_out[i];
26399a2dd95SBruce Richardson
26499a2dd95SBruce Richardson rte_pipeline_port_out_free(port);
26599a2dd95SBruce Richardson }
26699a2dd95SBruce Richardson
26799a2dd95SBruce Richardson /* Free pipeline memory */
26899a2dd95SBruce Richardson rte_free(p);
26999a2dd95SBruce Richardson
27099a2dd95SBruce Richardson return 0;
27199a2dd95SBruce Richardson }
27299a2dd95SBruce Richardson
27399a2dd95SBruce Richardson /*
27499a2dd95SBruce Richardson * Table
27599a2dd95SBruce Richardson */
27699a2dd95SBruce Richardson static int
rte_table_check_params(struct rte_pipeline * p,struct rte_pipeline_table_params * params,uint32_t * table_id)27799a2dd95SBruce Richardson rte_table_check_params(struct rte_pipeline *p,
27899a2dd95SBruce Richardson struct rte_pipeline_table_params *params,
27999a2dd95SBruce Richardson uint32_t *table_id)
28099a2dd95SBruce Richardson {
28199a2dd95SBruce Richardson if (p == NULL) {
282ae67895bSDavid Marchand PIPELINE_LOG(ERR, "%s: pipeline parameter is NULL",
28399a2dd95SBruce Richardson __func__);
28499a2dd95SBruce Richardson return -EINVAL;
28599a2dd95SBruce Richardson }
28699a2dd95SBruce Richardson if (params == NULL) {
287ae67895bSDavid Marchand PIPELINE_LOG(ERR, "%s: params parameter is NULL",
28899a2dd95SBruce Richardson __func__);
28999a2dd95SBruce Richardson return -EINVAL;
29099a2dd95SBruce Richardson }
29199a2dd95SBruce Richardson if (table_id == NULL) {
292ae67895bSDavid Marchand PIPELINE_LOG(ERR, "%s: table_id parameter is NULL",
29399a2dd95SBruce Richardson __func__);
29499a2dd95SBruce Richardson return -EINVAL;
29599a2dd95SBruce Richardson }
29699a2dd95SBruce Richardson
29799a2dd95SBruce Richardson /* ops */
29899a2dd95SBruce Richardson if (params->ops == NULL) {
299ae67895bSDavid Marchand PIPELINE_LOG(ERR, "%s: params->ops is NULL",
30099a2dd95SBruce Richardson __func__);
30199a2dd95SBruce Richardson return -EINVAL;
30299a2dd95SBruce Richardson }
30399a2dd95SBruce Richardson
30499a2dd95SBruce Richardson if (params->ops->f_create == NULL) {
305ae67895bSDavid Marchand PIPELINE_LOG(ERR,
306ae67895bSDavid Marchand "%s: f_create function pointer is NULL", __func__);
30799a2dd95SBruce Richardson return -EINVAL;
30899a2dd95SBruce Richardson }
30999a2dd95SBruce Richardson
31099a2dd95SBruce Richardson if (params->ops->f_lookup == NULL) {
311ae67895bSDavid Marchand PIPELINE_LOG(ERR,
312ae67895bSDavid Marchand "%s: f_lookup function pointer is NULL", __func__);
31399a2dd95SBruce Richardson return -EINVAL;
31499a2dd95SBruce Richardson }
31599a2dd95SBruce Richardson
31699a2dd95SBruce Richardson /* De we have room for one more table? */
31799a2dd95SBruce Richardson if (p->num_tables == RTE_PIPELINE_TABLE_MAX) {
318ae67895bSDavid Marchand PIPELINE_LOG(ERR,
319ae67895bSDavid Marchand "%s: Incorrect value for num_tables parameter",
32099a2dd95SBruce Richardson __func__);
32199a2dd95SBruce Richardson return -EINVAL;
32299a2dd95SBruce Richardson }
32399a2dd95SBruce Richardson
32499a2dd95SBruce Richardson return 0;
32599a2dd95SBruce Richardson }
32699a2dd95SBruce Richardson
32799a2dd95SBruce Richardson int
rte_pipeline_table_create(struct rte_pipeline * p,struct rte_pipeline_table_params * params,uint32_t * table_id)32899a2dd95SBruce Richardson rte_pipeline_table_create(struct rte_pipeline *p,
32999a2dd95SBruce Richardson struct rte_pipeline_table_params *params,
33099a2dd95SBruce Richardson uint32_t *table_id)
33199a2dd95SBruce Richardson {
33299a2dd95SBruce Richardson struct rte_table *table;
33399a2dd95SBruce Richardson struct rte_pipeline_table_entry *default_entry;
33499a2dd95SBruce Richardson void *h_table;
33599a2dd95SBruce Richardson uint32_t entry_size, id;
33699a2dd95SBruce Richardson int status;
33799a2dd95SBruce Richardson
33899a2dd95SBruce Richardson /* Check input arguments */
33999a2dd95SBruce Richardson status = rte_table_check_params(p, params, table_id);
34099a2dd95SBruce Richardson if (status != 0)
34199a2dd95SBruce Richardson return status;
34299a2dd95SBruce Richardson
34399a2dd95SBruce Richardson id = p->num_tables;
34499a2dd95SBruce Richardson table = &p->tables[id];
34599a2dd95SBruce Richardson
34699a2dd95SBruce Richardson /* Allocate space for the default table entry */
34799a2dd95SBruce Richardson entry_size = sizeof(struct rte_pipeline_table_entry) +
34899a2dd95SBruce Richardson params->action_data_size;
34999a2dd95SBruce Richardson default_entry = rte_zmalloc_socket(
35099a2dd95SBruce Richardson "PIPELINE", entry_size, RTE_CACHE_LINE_SIZE, p->socket_id);
35199a2dd95SBruce Richardson if (default_entry == NULL) {
352ae67895bSDavid Marchand PIPELINE_LOG(ERR,
353ae67895bSDavid Marchand "%s: Failed to allocate default entry", __func__);
35499a2dd95SBruce Richardson return -EINVAL;
35599a2dd95SBruce Richardson }
35699a2dd95SBruce Richardson
35799a2dd95SBruce Richardson /* Create the table */
35899a2dd95SBruce Richardson h_table = params->ops->f_create(params->arg_create, p->socket_id,
35999a2dd95SBruce Richardson entry_size);
36099a2dd95SBruce Richardson if (h_table == NULL) {
36199a2dd95SBruce Richardson rte_free(default_entry);
362ae67895bSDavid Marchand PIPELINE_LOG(ERR, "%s: Table creation failed", __func__);
36399a2dd95SBruce Richardson return -EINVAL;
36499a2dd95SBruce Richardson }
36599a2dd95SBruce Richardson
36699a2dd95SBruce Richardson /* Commit current table to the pipeline */
36799a2dd95SBruce Richardson p->num_tables++;
36899a2dd95SBruce Richardson *table_id = id;
36999a2dd95SBruce Richardson
37099a2dd95SBruce Richardson /* Save input parameters */
37199a2dd95SBruce Richardson memcpy(&table->ops, params->ops, sizeof(struct rte_table_ops));
37299a2dd95SBruce Richardson table->f_action_hit = params->f_action_hit;
37399a2dd95SBruce Richardson table->f_action_miss = params->f_action_miss;
37499a2dd95SBruce Richardson table->arg_ah = params->arg_ah;
37599a2dd95SBruce Richardson table->entry_size = entry_size;
37699a2dd95SBruce Richardson
37799a2dd95SBruce Richardson /* Clear the lookup miss actions (to be set later through API) */
37899a2dd95SBruce Richardson table->default_entry = default_entry;
37999a2dd95SBruce Richardson table->default_entry->action = RTE_PIPELINE_ACTION_DROP;
38099a2dd95SBruce Richardson
38199a2dd95SBruce Richardson /* Initialize table internal data structure */
38299a2dd95SBruce Richardson table->h_table = h_table;
38399a2dd95SBruce Richardson table->table_next_id = 0;
38499a2dd95SBruce Richardson table->table_next_id_valid = 0;
38599a2dd95SBruce Richardson
38699a2dd95SBruce Richardson return 0;
38799a2dd95SBruce Richardson }
38899a2dd95SBruce Richardson
38999a2dd95SBruce Richardson void
rte_pipeline_table_free(struct rte_table * table)39099a2dd95SBruce Richardson rte_pipeline_table_free(struct rte_table *table)
39199a2dd95SBruce Richardson {
39299a2dd95SBruce Richardson if (table->ops.f_free != NULL)
39399a2dd95SBruce Richardson table->ops.f_free(table->h_table);
39499a2dd95SBruce Richardson
39599a2dd95SBruce Richardson rte_free(table->default_entry);
39699a2dd95SBruce Richardson }
39799a2dd95SBruce Richardson
39899a2dd95SBruce Richardson int
rte_pipeline_table_default_entry_add(struct rte_pipeline * p,uint32_t table_id,struct rte_pipeline_table_entry * default_entry,struct rte_pipeline_table_entry ** default_entry_ptr)39999a2dd95SBruce Richardson rte_pipeline_table_default_entry_add(struct rte_pipeline *p,
40099a2dd95SBruce Richardson uint32_t table_id,
40199a2dd95SBruce Richardson struct rte_pipeline_table_entry *default_entry,
40299a2dd95SBruce Richardson struct rte_pipeline_table_entry **default_entry_ptr)
40399a2dd95SBruce Richardson {
40499a2dd95SBruce Richardson struct rte_table *table;
40599a2dd95SBruce Richardson
40699a2dd95SBruce Richardson /* Check input arguments */
40799a2dd95SBruce Richardson if (p == NULL) {
408ae67895bSDavid Marchand PIPELINE_LOG(ERR, "%s: pipeline parameter is NULL",
40999a2dd95SBruce Richardson __func__);
41099a2dd95SBruce Richardson return -EINVAL;
41199a2dd95SBruce Richardson }
41299a2dd95SBruce Richardson
41399a2dd95SBruce Richardson if (default_entry == NULL) {
414ae67895bSDavid Marchand PIPELINE_LOG(ERR,
415ae67895bSDavid Marchand "%s: default_entry parameter is NULL", __func__);
41699a2dd95SBruce Richardson return -EINVAL;
41799a2dd95SBruce Richardson }
41899a2dd95SBruce Richardson
41999a2dd95SBruce Richardson if (table_id >= p->num_tables) {
420ae67895bSDavid Marchand PIPELINE_LOG(ERR,
421ae67895bSDavid Marchand "%s: table_id %d out of range", __func__, table_id);
42299a2dd95SBruce Richardson return -EINVAL;
42399a2dd95SBruce Richardson }
42499a2dd95SBruce Richardson
42599a2dd95SBruce Richardson table = &p->tables[table_id];
42699a2dd95SBruce Richardson
42799a2dd95SBruce Richardson if ((default_entry->action == RTE_PIPELINE_ACTION_TABLE) &&
42899a2dd95SBruce Richardson table->table_next_id_valid &&
42999a2dd95SBruce Richardson (default_entry->table_id != table->table_next_id)) {
430ae67895bSDavid Marchand PIPELINE_LOG(ERR,
431ae67895bSDavid Marchand "%s: Tree-like topologies not allowed", __func__);
43299a2dd95SBruce Richardson return -EINVAL;
43399a2dd95SBruce Richardson }
43499a2dd95SBruce Richardson
43599a2dd95SBruce Richardson /* Set the lookup miss actions */
43699a2dd95SBruce Richardson if ((default_entry->action == RTE_PIPELINE_ACTION_TABLE) &&
43799a2dd95SBruce Richardson (table->table_next_id_valid == 0)) {
43899a2dd95SBruce Richardson table->table_next_id = default_entry->table_id;
43999a2dd95SBruce Richardson table->table_next_id_valid = 1;
44099a2dd95SBruce Richardson }
44199a2dd95SBruce Richardson
44299a2dd95SBruce Richardson memcpy(table->default_entry, default_entry, table->entry_size);
44399a2dd95SBruce Richardson
44499a2dd95SBruce Richardson *default_entry_ptr = table->default_entry;
44599a2dd95SBruce Richardson return 0;
44699a2dd95SBruce Richardson }
44799a2dd95SBruce Richardson
44899a2dd95SBruce Richardson int
rte_pipeline_table_default_entry_delete(struct rte_pipeline * p,uint32_t table_id,struct rte_pipeline_table_entry * entry)44999a2dd95SBruce Richardson rte_pipeline_table_default_entry_delete(struct rte_pipeline *p,
45099a2dd95SBruce Richardson uint32_t table_id,
45199a2dd95SBruce Richardson struct rte_pipeline_table_entry *entry)
45299a2dd95SBruce Richardson {
45399a2dd95SBruce Richardson struct rte_table *table;
45499a2dd95SBruce Richardson
45599a2dd95SBruce Richardson /* Check input arguments */
45699a2dd95SBruce Richardson if (p == NULL) {
457ae67895bSDavid Marchand PIPELINE_LOG(ERR,
458ae67895bSDavid Marchand "%s: pipeline parameter is NULL", __func__);
45999a2dd95SBruce Richardson return -EINVAL;
46099a2dd95SBruce Richardson }
46199a2dd95SBruce Richardson
46299a2dd95SBruce Richardson if (table_id >= p->num_tables) {
463ae67895bSDavid Marchand PIPELINE_LOG(ERR,
464ae67895bSDavid Marchand "%s: table_id %d out of range", __func__, table_id);
46599a2dd95SBruce Richardson return -EINVAL;
46699a2dd95SBruce Richardson }
46799a2dd95SBruce Richardson
46899a2dd95SBruce Richardson table = &p->tables[table_id];
46999a2dd95SBruce Richardson
47099a2dd95SBruce Richardson /* Save the current contents of the default entry */
47199a2dd95SBruce Richardson if (entry)
47299a2dd95SBruce Richardson memcpy(entry, table->default_entry, table->entry_size);
47399a2dd95SBruce Richardson
47499a2dd95SBruce Richardson /* Clear the lookup miss actions */
47599a2dd95SBruce Richardson memset(table->default_entry, 0, table->entry_size);
47699a2dd95SBruce Richardson table->default_entry->action = RTE_PIPELINE_ACTION_DROP;
47799a2dd95SBruce Richardson
47899a2dd95SBruce Richardson return 0;
47999a2dd95SBruce Richardson }
48099a2dd95SBruce Richardson
48199a2dd95SBruce Richardson int
rte_pipeline_table_entry_add(struct rte_pipeline * p,uint32_t table_id,void * key,struct rte_pipeline_table_entry * entry,int * key_found,struct rte_pipeline_table_entry ** entry_ptr)48299a2dd95SBruce Richardson rte_pipeline_table_entry_add(struct rte_pipeline *p,
48399a2dd95SBruce Richardson uint32_t table_id,
48499a2dd95SBruce Richardson void *key,
48599a2dd95SBruce Richardson struct rte_pipeline_table_entry *entry,
48699a2dd95SBruce Richardson int *key_found,
48799a2dd95SBruce Richardson struct rte_pipeline_table_entry **entry_ptr)
48899a2dd95SBruce Richardson {
48999a2dd95SBruce Richardson struct rte_table *table;
49099a2dd95SBruce Richardson
49199a2dd95SBruce Richardson /* Check input arguments */
49299a2dd95SBruce Richardson if (p == NULL) {
493ae67895bSDavid Marchand PIPELINE_LOG(ERR, "%s: pipeline parameter is NULL",
49499a2dd95SBruce Richardson __func__);
49599a2dd95SBruce Richardson return -EINVAL;
49699a2dd95SBruce Richardson }
49799a2dd95SBruce Richardson
49899a2dd95SBruce Richardson if (key == NULL) {
499ae67895bSDavid Marchand PIPELINE_LOG(ERR, "%s: key parameter is NULL", __func__);
50099a2dd95SBruce Richardson return -EINVAL;
50199a2dd95SBruce Richardson }
50299a2dd95SBruce Richardson
50399a2dd95SBruce Richardson if (entry == NULL) {
504ae67895bSDavid Marchand PIPELINE_LOG(ERR, "%s: entry parameter is NULL",
50599a2dd95SBruce Richardson __func__);
50699a2dd95SBruce Richardson return -EINVAL;
50799a2dd95SBruce Richardson }
50899a2dd95SBruce Richardson
50999a2dd95SBruce Richardson if (table_id >= p->num_tables) {
510ae67895bSDavid Marchand PIPELINE_LOG(ERR,
511ae67895bSDavid Marchand "%s: table_id %d out of range", __func__, table_id);
51299a2dd95SBruce Richardson return -EINVAL;
51399a2dd95SBruce Richardson }
51499a2dd95SBruce Richardson
51599a2dd95SBruce Richardson table = &p->tables[table_id];
51699a2dd95SBruce Richardson
51799a2dd95SBruce Richardson if (table->ops.f_add == NULL) {
518ae67895bSDavid Marchand PIPELINE_LOG(ERR, "%s: f_add function pointer NULL",
51999a2dd95SBruce Richardson __func__);
52099a2dd95SBruce Richardson return -EINVAL;
52199a2dd95SBruce Richardson }
52299a2dd95SBruce Richardson
52399a2dd95SBruce Richardson if ((entry->action == RTE_PIPELINE_ACTION_TABLE) &&
52499a2dd95SBruce Richardson table->table_next_id_valid &&
52599a2dd95SBruce Richardson (entry->table_id != table->table_next_id)) {
526ae67895bSDavid Marchand PIPELINE_LOG(ERR,
527ae67895bSDavid Marchand "%s: Tree-like topologies not allowed", __func__);
52899a2dd95SBruce Richardson return -EINVAL;
52999a2dd95SBruce Richardson }
53099a2dd95SBruce Richardson
53199a2dd95SBruce Richardson /* Add entry */
53299a2dd95SBruce Richardson if ((entry->action == RTE_PIPELINE_ACTION_TABLE) &&
53399a2dd95SBruce Richardson (table->table_next_id_valid == 0)) {
53499a2dd95SBruce Richardson table->table_next_id = entry->table_id;
53599a2dd95SBruce Richardson table->table_next_id_valid = 1;
53699a2dd95SBruce Richardson }
53799a2dd95SBruce Richardson
53899a2dd95SBruce Richardson return (table->ops.f_add)(table->h_table, key, (void *) entry,
53999a2dd95SBruce Richardson key_found, (void **) entry_ptr);
54099a2dd95SBruce Richardson }
54199a2dd95SBruce Richardson
54299a2dd95SBruce Richardson int
rte_pipeline_table_entry_delete(struct rte_pipeline * p,uint32_t table_id,void * key,int * key_found,struct rte_pipeline_table_entry * entry)54399a2dd95SBruce Richardson rte_pipeline_table_entry_delete(struct rte_pipeline *p,
54499a2dd95SBruce Richardson uint32_t table_id,
54599a2dd95SBruce Richardson void *key,
54699a2dd95SBruce Richardson int *key_found,
54799a2dd95SBruce Richardson struct rte_pipeline_table_entry *entry)
54899a2dd95SBruce Richardson {
54999a2dd95SBruce Richardson struct rte_table *table;
55099a2dd95SBruce Richardson
55199a2dd95SBruce Richardson /* Check input arguments */
55299a2dd95SBruce Richardson if (p == NULL) {
553ae67895bSDavid Marchand PIPELINE_LOG(ERR, "%s: pipeline parameter NULL",
55499a2dd95SBruce Richardson __func__);
55599a2dd95SBruce Richardson return -EINVAL;
55699a2dd95SBruce Richardson }
55799a2dd95SBruce Richardson
55899a2dd95SBruce Richardson if (key == NULL) {
559ae67895bSDavid Marchand PIPELINE_LOG(ERR, "%s: key parameter is NULL",
56099a2dd95SBruce Richardson __func__);
56199a2dd95SBruce Richardson return -EINVAL;
56299a2dd95SBruce Richardson }
56399a2dd95SBruce Richardson
56499a2dd95SBruce Richardson if (table_id >= p->num_tables) {
565ae67895bSDavid Marchand PIPELINE_LOG(ERR,
566ae67895bSDavid Marchand "%s: table_id %d out of range", __func__, table_id);
56799a2dd95SBruce Richardson return -EINVAL;
56899a2dd95SBruce Richardson }
56999a2dd95SBruce Richardson
57099a2dd95SBruce Richardson table = &p->tables[table_id];
57199a2dd95SBruce Richardson
57299a2dd95SBruce Richardson if (table->ops.f_delete == NULL) {
573ae67895bSDavid Marchand PIPELINE_LOG(ERR,
574ae67895bSDavid Marchand "%s: f_delete function pointer NULL", __func__);
57599a2dd95SBruce Richardson return -EINVAL;
57699a2dd95SBruce Richardson }
57799a2dd95SBruce Richardson
57899a2dd95SBruce Richardson return (table->ops.f_delete)(table->h_table, key, key_found, entry);
57999a2dd95SBruce Richardson }
58099a2dd95SBruce Richardson
rte_pipeline_table_entry_add_bulk(struct rte_pipeline * p,uint32_t table_id,void ** keys,struct rte_pipeline_table_entry ** entries,uint32_t n_keys,int * key_found,struct rte_pipeline_table_entry ** entries_ptr)58199a2dd95SBruce Richardson int rte_pipeline_table_entry_add_bulk(struct rte_pipeline *p,
58299a2dd95SBruce Richardson uint32_t table_id,
58399a2dd95SBruce Richardson void **keys,
58499a2dd95SBruce Richardson struct rte_pipeline_table_entry **entries,
58599a2dd95SBruce Richardson uint32_t n_keys,
58699a2dd95SBruce Richardson int *key_found,
58799a2dd95SBruce Richardson struct rte_pipeline_table_entry **entries_ptr)
58899a2dd95SBruce Richardson {
58999a2dd95SBruce Richardson struct rte_table *table;
59099a2dd95SBruce Richardson uint32_t i;
59199a2dd95SBruce Richardson
59299a2dd95SBruce Richardson /* Check input arguments */
59399a2dd95SBruce Richardson if (p == NULL) {
594ae67895bSDavid Marchand PIPELINE_LOG(ERR, "%s: pipeline parameter is NULL",
59599a2dd95SBruce Richardson __func__);
59699a2dd95SBruce Richardson return -EINVAL;
59799a2dd95SBruce Richardson }
59899a2dd95SBruce Richardson
59999a2dd95SBruce Richardson if (keys == NULL) {
600ae67895bSDavid Marchand PIPELINE_LOG(ERR, "%s: keys parameter is NULL", __func__);
60199a2dd95SBruce Richardson return -EINVAL;
60299a2dd95SBruce Richardson }
60399a2dd95SBruce Richardson
60499a2dd95SBruce Richardson if (entries == NULL) {
605ae67895bSDavid Marchand PIPELINE_LOG(ERR, "%s: entries parameter is NULL",
60699a2dd95SBruce Richardson __func__);
60799a2dd95SBruce Richardson return -EINVAL;
60899a2dd95SBruce Richardson }
60999a2dd95SBruce Richardson
61099a2dd95SBruce Richardson if (table_id >= p->num_tables) {
611ae67895bSDavid Marchand PIPELINE_LOG(ERR,
612ae67895bSDavid Marchand "%s: table_id %d out of range", __func__, table_id);
61399a2dd95SBruce Richardson return -EINVAL;
61499a2dd95SBruce Richardson }
61599a2dd95SBruce Richardson
61699a2dd95SBruce Richardson table = &p->tables[table_id];
61799a2dd95SBruce Richardson
61899a2dd95SBruce Richardson if (table->ops.f_add_bulk == NULL) {
619ae67895bSDavid Marchand PIPELINE_LOG(ERR, "%s: f_add_bulk function pointer NULL",
62099a2dd95SBruce Richardson __func__);
62199a2dd95SBruce Richardson return -EINVAL;
62299a2dd95SBruce Richardson }
62399a2dd95SBruce Richardson
62499a2dd95SBruce Richardson for (i = 0; i < n_keys; i++) {
62599a2dd95SBruce Richardson if ((entries[i]->action == RTE_PIPELINE_ACTION_TABLE) &&
62699a2dd95SBruce Richardson table->table_next_id_valid &&
62799a2dd95SBruce Richardson (entries[i]->table_id != table->table_next_id)) {
628ae67895bSDavid Marchand PIPELINE_LOG(ERR,
629ae67895bSDavid Marchand "%s: Tree-like topologies not allowed", __func__);
63099a2dd95SBruce Richardson return -EINVAL;
63199a2dd95SBruce Richardson }
63299a2dd95SBruce Richardson }
63399a2dd95SBruce Richardson
63499a2dd95SBruce Richardson /* Add entry */
63599a2dd95SBruce Richardson for (i = 0; i < n_keys; i++) {
63699a2dd95SBruce Richardson if ((entries[i]->action == RTE_PIPELINE_ACTION_TABLE) &&
63799a2dd95SBruce Richardson (table->table_next_id_valid == 0)) {
63899a2dd95SBruce Richardson table->table_next_id = entries[i]->table_id;
63999a2dd95SBruce Richardson table->table_next_id_valid = 1;
64099a2dd95SBruce Richardson }
64199a2dd95SBruce Richardson }
64299a2dd95SBruce Richardson
64399a2dd95SBruce Richardson return (table->ops.f_add_bulk)(table->h_table, keys, (void **) entries,
64499a2dd95SBruce Richardson n_keys, key_found, (void **) entries_ptr);
64599a2dd95SBruce Richardson }
64699a2dd95SBruce Richardson
rte_pipeline_table_entry_delete_bulk(struct rte_pipeline * p,uint32_t table_id,void ** keys,uint32_t n_keys,int * key_found,struct rte_pipeline_table_entry ** entries)64799a2dd95SBruce Richardson int rte_pipeline_table_entry_delete_bulk(struct rte_pipeline *p,
64899a2dd95SBruce Richardson uint32_t table_id,
64999a2dd95SBruce Richardson void **keys,
65099a2dd95SBruce Richardson uint32_t n_keys,
65199a2dd95SBruce Richardson int *key_found,
65299a2dd95SBruce Richardson struct rte_pipeline_table_entry **entries)
65399a2dd95SBruce Richardson {
65499a2dd95SBruce Richardson struct rte_table *table;
65599a2dd95SBruce Richardson
65699a2dd95SBruce Richardson /* Check input arguments */
65799a2dd95SBruce Richardson if (p == NULL) {
658ae67895bSDavid Marchand PIPELINE_LOG(ERR, "%s: pipeline parameter NULL",
65999a2dd95SBruce Richardson __func__);
66099a2dd95SBruce Richardson return -EINVAL;
66199a2dd95SBruce Richardson }
66299a2dd95SBruce Richardson
66399a2dd95SBruce Richardson if (keys == NULL) {
664ae67895bSDavid Marchand PIPELINE_LOG(ERR, "%s: key parameter is NULL",
66599a2dd95SBruce Richardson __func__);
66699a2dd95SBruce Richardson return -EINVAL;
66799a2dd95SBruce Richardson }
66899a2dd95SBruce Richardson
66999a2dd95SBruce Richardson if (table_id >= p->num_tables) {
670ae67895bSDavid Marchand PIPELINE_LOG(ERR,
671ae67895bSDavid Marchand "%s: table_id %d out of range", __func__, table_id);
67299a2dd95SBruce Richardson return -EINVAL;
67399a2dd95SBruce Richardson }
67499a2dd95SBruce Richardson
67599a2dd95SBruce Richardson table = &p->tables[table_id];
67699a2dd95SBruce Richardson
67799a2dd95SBruce Richardson if (table->ops.f_delete_bulk == NULL) {
678ae67895bSDavid Marchand PIPELINE_LOG(ERR,
679ae67895bSDavid Marchand "%s: f_delete function pointer NULL", __func__);
68099a2dd95SBruce Richardson return -EINVAL;
68199a2dd95SBruce Richardson }
68299a2dd95SBruce Richardson
68399a2dd95SBruce Richardson return (table->ops.f_delete_bulk)(table->h_table, keys, n_keys, key_found,
68499a2dd95SBruce Richardson (void **) entries);
68599a2dd95SBruce Richardson }
68699a2dd95SBruce Richardson
68799a2dd95SBruce Richardson /*
68899a2dd95SBruce Richardson * Port
68999a2dd95SBruce Richardson */
69099a2dd95SBruce Richardson static int
rte_pipeline_port_in_check_params(struct rte_pipeline * p,struct rte_pipeline_port_in_params * params,uint32_t * port_id)69199a2dd95SBruce Richardson rte_pipeline_port_in_check_params(struct rte_pipeline *p,
69299a2dd95SBruce Richardson struct rte_pipeline_port_in_params *params,
69399a2dd95SBruce Richardson uint32_t *port_id)
69499a2dd95SBruce Richardson {
69599a2dd95SBruce Richardson if (p == NULL) {
696ae67895bSDavid Marchand PIPELINE_LOG(ERR, "%s: pipeline parameter NULL",
69799a2dd95SBruce Richardson __func__);
69899a2dd95SBruce Richardson return -EINVAL;
69999a2dd95SBruce Richardson }
70099a2dd95SBruce Richardson if (params == NULL) {
701ae67895bSDavid Marchand PIPELINE_LOG(ERR, "%s: params parameter NULL", __func__);
70299a2dd95SBruce Richardson return -EINVAL;
70399a2dd95SBruce Richardson }
70499a2dd95SBruce Richardson if (port_id == NULL) {
705ae67895bSDavid Marchand PIPELINE_LOG(ERR, "%s: port_id parameter NULL",
70699a2dd95SBruce Richardson __func__);
70799a2dd95SBruce Richardson return -EINVAL;
70899a2dd95SBruce Richardson }
70999a2dd95SBruce Richardson
71099a2dd95SBruce Richardson /* ops */
71199a2dd95SBruce Richardson if (params->ops == NULL) {
712ae67895bSDavid Marchand PIPELINE_LOG(ERR, "%s: params->ops parameter NULL",
71399a2dd95SBruce Richardson __func__);
71499a2dd95SBruce Richardson return -EINVAL;
71599a2dd95SBruce Richardson }
71699a2dd95SBruce Richardson
71799a2dd95SBruce Richardson if (params->ops->f_create == NULL) {
718ae67895bSDavid Marchand PIPELINE_LOG(ERR,
719ae67895bSDavid Marchand "%s: f_create function pointer NULL", __func__);
72099a2dd95SBruce Richardson return -EINVAL;
72199a2dd95SBruce Richardson }
72299a2dd95SBruce Richardson
72399a2dd95SBruce Richardson if (params->ops->f_rx == NULL) {
724ae67895bSDavid Marchand PIPELINE_LOG(ERR, "%s: f_rx function pointer NULL",
72599a2dd95SBruce Richardson __func__);
72699a2dd95SBruce Richardson return -EINVAL;
72799a2dd95SBruce Richardson }
72899a2dd95SBruce Richardson
72999a2dd95SBruce Richardson /* burst_size */
73099a2dd95SBruce Richardson if ((params->burst_size == 0) ||
73199a2dd95SBruce Richardson (params->burst_size > RTE_PORT_IN_BURST_SIZE_MAX)) {
732ae67895bSDavid Marchand PIPELINE_LOG(ERR, "%s: invalid value for burst_size",
73399a2dd95SBruce Richardson __func__);
73499a2dd95SBruce Richardson return -EINVAL;
73599a2dd95SBruce Richardson }
73699a2dd95SBruce Richardson
73799a2dd95SBruce Richardson /* Do we have room for one more port? */
73899a2dd95SBruce Richardson if (p->num_ports_in == RTE_PIPELINE_PORT_IN_MAX) {
739ae67895bSDavid Marchand PIPELINE_LOG(ERR,
740ae67895bSDavid Marchand "%s: invalid value for num_ports_in", __func__);
74199a2dd95SBruce Richardson return -EINVAL;
74299a2dd95SBruce Richardson }
74399a2dd95SBruce Richardson
74499a2dd95SBruce Richardson return 0;
74599a2dd95SBruce Richardson }
74699a2dd95SBruce Richardson
74799a2dd95SBruce Richardson static int
rte_pipeline_port_out_check_params(struct rte_pipeline * p,struct rte_pipeline_port_out_params * params,uint32_t * port_id)74899a2dd95SBruce Richardson rte_pipeline_port_out_check_params(struct rte_pipeline *p,
74999a2dd95SBruce Richardson struct rte_pipeline_port_out_params *params,
75099a2dd95SBruce Richardson uint32_t *port_id)
75199a2dd95SBruce Richardson {
75299a2dd95SBruce Richardson if (p == NULL) {
753ae67895bSDavid Marchand PIPELINE_LOG(ERR, "%s: pipeline parameter NULL",
75499a2dd95SBruce Richardson __func__);
75599a2dd95SBruce Richardson return -EINVAL;
75699a2dd95SBruce Richardson }
75799a2dd95SBruce Richardson
75899a2dd95SBruce Richardson if (params == NULL) {
759ae67895bSDavid Marchand PIPELINE_LOG(ERR, "%s: params parameter NULL", __func__);
76099a2dd95SBruce Richardson return -EINVAL;
76199a2dd95SBruce Richardson }
76299a2dd95SBruce Richardson
76399a2dd95SBruce Richardson if (port_id == NULL) {
764ae67895bSDavid Marchand PIPELINE_LOG(ERR, "%s: port_id parameter NULL",
76599a2dd95SBruce Richardson __func__);
76699a2dd95SBruce Richardson return -EINVAL;
76799a2dd95SBruce Richardson }
76899a2dd95SBruce Richardson
76999a2dd95SBruce Richardson /* ops */
77099a2dd95SBruce Richardson if (params->ops == NULL) {
771ae67895bSDavid Marchand PIPELINE_LOG(ERR, "%s: params->ops parameter NULL",
77299a2dd95SBruce Richardson __func__);
77399a2dd95SBruce Richardson return -EINVAL;
77499a2dd95SBruce Richardson }
77599a2dd95SBruce Richardson
77699a2dd95SBruce Richardson if (params->ops->f_create == NULL) {
777ae67895bSDavid Marchand PIPELINE_LOG(ERR,
778ae67895bSDavid Marchand "%s: f_create function pointer NULL", __func__);
77999a2dd95SBruce Richardson return -EINVAL;
78099a2dd95SBruce Richardson }
78199a2dd95SBruce Richardson
78299a2dd95SBruce Richardson if (params->ops->f_tx == NULL) {
783ae67895bSDavid Marchand PIPELINE_LOG(ERR,
784ae67895bSDavid Marchand "%s: f_tx function pointer NULL", __func__);
78599a2dd95SBruce Richardson return -EINVAL;
78699a2dd95SBruce Richardson }
78799a2dd95SBruce Richardson
78899a2dd95SBruce Richardson if (params->ops->f_tx_bulk == NULL) {
789ae67895bSDavid Marchand PIPELINE_LOG(ERR,
790ae67895bSDavid Marchand "%s: f_tx_bulk function pointer NULL", __func__);
79199a2dd95SBruce Richardson return -EINVAL;
79299a2dd95SBruce Richardson }
79399a2dd95SBruce Richardson
79499a2dd95SBruce Richardson /* Do we have room for one more port? */
79599a2dd95SBruce Richardson if (p->num_ports_out == RTE_PIPELINE_PORT_OUT_MAX) {
796ae67895bSDavid Marchand PIPELINE_LOG(ERR,
797ae67895bSDavid Marchand "%s: invalid value for num_ports_out", __func__);
79899a2dd95SBruce Richardson return -EINVAL;
79999a2dd95SBruce Richardson }
80099a2dd95SBruce Richardson
80199a2dd95SBruce Richardson return 0;
80299a2dd95SBruce Richardson }
80399a2dd95SBruce Richardson
80499a2dd95SBruce Richardson int
rte_pipeline_port_in_create(struct rte_pipeline * p,struct rte_pipeline_port_in_params * params,uint32_t * port_id)80599a2dd95SBruce Richardson rte_pipeline_port_in_create(struct rte_pipeline *p,
80699a2dd95SBruce Richardson struct rte_pipeline_port_in_params *params,
80799a2dd95SBruce Richardson uint32_t *port_id)
80899a2dd95SBruce Richardson {
80999a2dd95SBruce Richardson struct rte_port_in *port;
81099a2dd95SBruce Richardson void *h_port;
81199a2dd95SBruce Richardson uint32_t id;
81299a2dd95SBruce Richardson int status;
81399a2dd95SBruce Richardson
81499a2dd95SBruce Richardson /* Check input arguments */
81599a2dd95SBruce Richardson status = rte_pipeline_port_in_check_params(p, params, port_id);
81699a2dd95SBruce Richardson if (status != 0)
81799a2dd95SBruce Richardson return status;
81899a2dd95SBruce Richardson
81999a2dd95SBruce Richardson id = p->num_ports_in;
82099a2dd95SBruce Richardson port = &p->ports_in[id];
82199a2dd95SBruce Richardson
82299a2dd95SBruce Richardson /* Create the port */
82399a2dd95SBruce Richardson h_port = params->ops->f_create(params->arg_create, p->socket_id);
82499a2dd95SBruce Richardson if (h_port == NULL) {
825ae67895bSDavid Marchand PIPELINE_LOG(ERR, "%s: Port creation failed", __func__);
82699a2dd95SBruce Richardson return -EINVAL;
82799a2dd95SBruce Richardson }
82899a2dd95SBruce Richardson
82999a2dd95SBruce Richardson /* Commit current table to the pipeline */
83099a2dd95SBruce Richardson p->num_ports_in++;
83199a2dd95SBruce Richardson *port_id = id;
83299a2dd95SBruce Richardson
83399a2dd95SBruce Richardson /* Save input parameters */
83499a2dd95SBruce Richardson memcpy(&port->ops, params->ops, sizeof(struct rte_port_in_ops));
83599a2dd95SBruce Richardson port->f_action = params->f_action;
83699a2dd95SBruce Richardson port->arg_ah = params->arg_ah;
83799a2dd95SBruce Richardson port->burst_size = params->burst_size;
83899a2dd95SBruce Richardson
83999a2dd95SBruce Richardson /* Initialize port internal data structure */
84099a2dd95SBruce Richardson port->table_id = RTE_TABLE_INVALID;
84199a2dd95SBruce Richardson port->h_port = h_port;
84299a2dd95SBruce Richardson port->next = NULL;
84399a2dd95SBruce Richardson
84499a2dd95SBruce Richardson return 0;
84599a2dd95SBruce Richardson }
84699a2dd95SBruce Richardson
84799a2dd95SBruce Richardson void
rte_pipeline_port_in_free(struct rte_port_in * port)84899a2dd95SBruce Richardson rte_pipeline_port_in_free(struct rte_port_in *port)
84999a2dd95SBruce Richardson {
85099a2dd95SBruce Richardson if (port->ops.f_free != NULL)
85199a2dd95SBruce Richardson port->ops.f_free(port->h_port);
85299a2dd95SBruce Richardson }
85399a2dd95SBruce Richardson
85499a2dd95SBruce Richardson int
rte_pipeline_port_out_create(struct rte_pipeline * p,struct rte_pipeline_port_out_params * params,uint32_t * port_id)85599a2dd95SBruce Richardson rte_pipeline_port_out_create(struct rte_pipeline *p,
85699a2dd95SBruce Richardson struct rte_pipeline_port_out_params *params,
85799a2dd95SBruce Richardson uint32_t *port_id)
85899a2dd95SBruce Richardson {
85999a2dd95SBruce Richardson struct rte_port_out *port;
86099a2dd95SBruce Richardson void *h_port;
86199a2dd95SBruce Richardson uint32_t id;
86299a2dd95SBruce Richardson int status;
86399a2dd95SBruce Richardson
86499a2dd95SBruce Richardson /* Check input arguments */
86599a2dd95SBruce Richardson status = rte_pipeline_port_out_check_params(p, params, port_id);
86699a2dd95SBruce Richardson if (status != 0)
86799a2dd95SBruce Richardson return status;
86899a2dd95SBruce Richardson
86999a2dd95SBruce Richardson id = p->num_ports_out;
87099a2dd95SBruce Richardson port = &p->ports_out[id];
87199a2dd95SBruce Richardson
87299a2dd95SBruce Richardson /* Create the port */
87399a2dd95SBruce Richardson h_port = params->ops->f_create(params->arg_create, p->socket_id);
87499a2dd95SBruce Richardson if (h_port == NULL) {
875ae67895bSDavid Marchand PIPELINE_LOG(ERR, "%s: Port creation failed", __func__);
87699a2dd95SBruce Richardson return -EINVAL;
87799a2dd95SBruce Richardson }
87899a2dd95SBruce Richardson
87999a2dd95SBruce Richardson /* Commit current table to the pipeline */
88099a2dd95SBruce Richardson p->num_ports_out++;
88199a2dd95SBruce Richardson *port_id = id;
88299a2dd95SBruce Richardson
88399a2dd95SBruce Richardson /* Save input parameters */
88499a2dd95SBruce Richardson memcpy(&port->ops, params->ops, sizeof(struct rte_port_out_ops));
88599a2dd95SBruce Richardson port->f_action = params->f_action;
88699a2dd95SBruce Richardson port->arg_ah = params->arg_ah;
88799a2dd95SBruce Richardson
88899a2dd95SBruce Richardson /* Initialize port internal data structure */
88999a2dd95SBruce Richardson port->h_port = h_port;
89099a2dd95SBruce Richardson
89199a2dd95SBruce Richardson return 0;
89299a2dd95SBruce Richardson }
89399a2dd95SBruce Richardson
89499a2dd95SBruce Richardson void
rte_pipeline_port_out_free(struct rte_port_out * port)89599a2dd95SBruce Richardson rte_pipeline_port_out_free(struct rte_port_out *port)
89699a2dd95SBruce Richardson {
89799a2dd95SBruce Richardson if (port->ops.f_free != NULL)
89899a2dd95SBruce Richardson port->ops.f_free(port->h_port);
89999a2dd95SBruce Richardson }
90099a2dd95SBruce Richardson
90199a2dd95SBruce Richardson int
rte_pipeline_port_in_connect_to_table(struct rte_pipeline * p,uint32_t port_id,uint32_t table_id)90299a2dd95SBruce Richardson rte_pipeline_port_in_connect_to_table(struct rte_pipeline *p,
90399a2dd95SBruce Richardson uint32_t port_id,
90499a2dd95SBruce Richardson uint32_t table_id)
90599a2dd95SBruce Richardson {
90699a2dd95SBruce Richardson struct rte_port_in *port;
90799a2dd95SBruce Richardson
90899a2dd95SBruce Richardson /* Check input arguments */
90999a2dd95SBruce Richardson if (p == NULL) {
910ae67895bSDavid Marchand PIPELINE_LOG(ERR, "%s: pipeline parameter NULL",
91199a2dd95SBruce Richardson __func__);
91299a2dd95SBruce Richardson return -EINVAL;
91399a2dd95SBruce Richardson }
91499a2dd95SBruce Richardson
91599a2dd95SBruce Richardson if (port_id >= p->num_ports_in) {
916ae67895bSDavid Marchand PIPELINE_LOG(ERR,
917ae67895bSDavid Marchand "%s: port IN ID %u is out of range",
91899a2dd95SBruce Richardson __func__, port_id);
91999a2dd95SBruce Richardson return -EINVAL;
92099a2dd95SBruce Richardson }
92199a2dd95SBruce Richardson
92299a2dd95SBruce Richardson if (table_id >= p->num_tables) {
923ae67895bSDavid Marchand PIPELINE_LOG(ERR,
924ae67895bSDavid Marchand "%s: Table ID %u is out of range",
92599a2dd95SBruce Richardson __func__, table_id);
92699a2dd95SBruce Richardson return -EINVAL;
92799a2dd95SBruce Richardson }
92899a2dd95SBruce Richardson
92999a2dd95SBruce Richardson port = &p->ports_in[port_id];
93099a2dd95SBruce Richardson port->table_id = table_id;
93199a2dd95SBruce Richardson
93299a2dd95SBruce Richardson return 0;
93399a2dd95SBruce Richardson }
93499a2dd95SBruce Richardson
93599a2dd95SBruce Richardson int
rte_pipeline_port_in_enable(struct rte_pipeline * p,uint32_t port_id)93699a2dd95SBruce Richardson rte_pipeline_port_in_enable(struct rte_pipeline *p, uint32_t port_id)
93799a2dd95SBruce Richardson {
93899a2dd95SBruce Richardson struct rte_port_in *port, *port_prev, *port_next;
93999a2dd95SBruce Richardson uint64_t port_mask;
94099a2dd95SBruce Richardson uint32_t port_prev_id, port_next_id;
94199a2dd95SBruce Richardson
94299a2dd95SBruce Richardson /* Check input arguments */
94399a2dd95SBruce Richardson if (p == NULL) {
944ae67895bSDavid Marchand PIPELINE_LOG(ERR, "%s: pipeline parameter NULL",
94599a2dd95SBruce Richardson __func__);
94699a2dd95SBruce Richardson return -EINVAL;
94799a2dd95SBruce Richardson }
94899a2dd95SBruce Richardson
94999a2dd95SBruce Richardson if (port_id >= p->num_ports_in) {
950ae67895bSDavid Marchand PIPELINE_LOG(ERR,
951ae67895bSDavid Marchand "%s: port IN ID %u is out of range",
95299a2dd95SBruce Richardson __func__, port_id);
95399a2dd95SBruce Richardson return -EINVAL;
95499a2dd95SBruce Richardson }
95599a2dd95SBruce Richardson
95699a2dd95SBruce Richardson port = &p->ports_in[port_id];
95799a2dd95SBruce Richardson
95899a2dd95SBruce Richardson /* Return if current input port is already enabled */
95999a2dd95SBruce Richardson port_mask = 1LLU << port_id;
96099a2dd95SBruce Richardson if (p->enabled_port_in_mask & port_mask)
96199a2dd95SBruce Richardson return 0;
96299a2dd95SBruce Richardson
96399a2dd95SBruce Richardson p->enabled_port_in_mask |= port_mask;
96499a2dd95SBruce Richardson
96599a2dd95SBruce Richardson /* Add current input port to the pipeline chain of enabled ports */
96699a2dd95SBruce Richardson port_prev_id = rte_mask_get_prev(p->enabled_port_in_mask, port_id);
96799a2dd95SBruce Richardson port_next_id = rte_mask_get_next(p->enabled_port_in_mask, port_id);
96899a2dd95SBruce Richardson
96999a2dd95SBruce Richardson port_prev = &p->ports_in[port_prev_id];
97099a2dd95SBruce Richardson port_next = &p->ports_in[port_next_id];
97199a2dd95SBruce Richardson
97299a2dd95SBruce Richardson port_prev->next = port;
97399a2dd95SBruce Richardson port->next = port_next;
97499a2dd95SBruce Richardson
97599a2dd95SBruce Richardson /* Check if list of enabled ports was previously empty */
97699a2dd95SBruce Richardson if (p->enabled_port_in_mask == port_mask)
97799a2dd95SBruce Richardson p->port_in_next = port;
97899a2dd95SBruce Richardson
97999a2dd95SBruce Richardson return 0;
98099a2dd95SBruce Richardson }
98199a2dd95SBruce Richardson
98299a2dd95SBruce Richardson int
rte_pipeline_port_in_disable(struct rte_pipeline * p,uint32_t port_id)98399a2dd95SBruce Richardson rte_pipeline_port_in_disable(struct rte_pipeline *p, uint32_t port_id)
98499a2dd95SBruce Richardson {
98599a2dd95SBruce Richardson struct rte_port_in *port, *port_prev, *port_next;
98699a2dd95SBruce Richardson uint64_t port_mask;
98799a2dd95SBruce Richardson uint32_t port_prev_id, port_next_id;
98899a2dd95SBruce Richardson
98999a2dd95SBruce Richardson /* Check input arguments */
99099a2dd95SBruce Richardson if (p == NULL) {
991ae67895bSDavid Marchand PIPELINE_LOG(ERR, "%s: pipeline parameter NULL",
99299a2dd95SBruce Richardson __func__);
99399a2dd95SBruce Richardson return -EINVAL;
99499a2dd95SBruce Richardson }
99599a2dd95SBruce Richardson
99699a2dd95SBruce Richardson if (port_id >= p->num_ports_in) {
997ae67895bSDavid Marchand PIPELINE_LOG(ERR, "%s: port IN ID %u is out of range",
99899a2dd95SBruce Richardson __func__, port_id);
99999a2dd95SBruce Richardson return -EINVAL;
100099a2dd95SBruce Richardson }
100199a2dd95SBruce Richardson
100299a2dd95SBruce Richardson port = &p->ports_in[port_id];
100399a2dd95SBruce Richardson
100499a2dd95SBruce Richardson /* Return if current input port is already disabled */
100599a2dd95SBruce Richardson port_mask = 1LLU << port_id;
100699a2dd95SBruce Richardson if ((p->enabled_port_in_mask & port_mask) == 0)
100799a2dd95SBruce Richardson return 0;
100899a2dd95SBruce Richardson
100999a2dd95SBruce Richardson p->enabled_port_in_mask &= ~port_mask;
101099a2dd95SBruce Richardson
101199a2dd95SBruce Richardson /* Return if no other enabled ports */
101299a2dd95SBruce Richardson if (p->enabled_port_in_mask == 0) {
101399a2dd95SBruce Richardson p->port_in_next = NULL;
101499a2dd95SBruce Richardson
101599a2dd95SBruce Richardson return 0;
101699a2dd95SBruce Richardson }
101799a2dd95SBruce Richardson
101899a2dd95SBruce Richardson /* Add current input port to the pipeline chain of enabled ports */
101999a2dd95SBruce Richardson port_prev_id = rte_mask_get_prev(p->enabled_port_in_mask, port_id);
102099a2dd95SBruce Richardson port_next_id = rte_mask_get_next(p->enabled_port_in_mask, port_id);
102199a2dd95SBruce Richardson
102299a2dd95SBruce Richardson port_prev = &p->ports_in[port_prev_id];
102399a2dd95SBruce Richardson port_next = &p->ports_in[port_next_id];
102499a2dd95SBruce Richardson
102599a2dd95SBruce Richardson port_prev->next = port_next;
102699a2dd95SBruce Richardson
102799a2dd95SBruce Richardson /* Check if the port which has just been disabled is next to serve */
102899a2dd95SBruce Richardson if (port == p->port_in_next)
102999a2dd95SBruce Richardson p->port_in_next = port_next;
103099a2dd95SBruce Richardson
103199a2dd95SBruce Richardson return 0;
103299a2dd95SBruce Richardson }
103399a2dd95SBruce Richardson
103499a2dd95SBruce Richardson /*
103599a2dd95SBruce Richardson * Pipeline run-time
103699a2dd95SBruce Richardson */
103799a2dd95SBruce Richardson int
rte_pipeline_check(struct rte_pipeline * p)103899a2dd95SBruce Richardson rte_pipeline_check(struct rte_pipeline *p)
103999a2dd95SBruce Richardson {
104099a2dd95SBruce Richardson uint32_t port_in_id;
104199a2dd95SBruce Richardson
104299a2dd95SBruce Richardson /* Check input arguments */
104399a2dd95SBruce Richardson if (p == NULL) {
1044ae67895bSDavid Marchand PIPELINE_LOG(ERR, "%s: pipeline parameter NULL",
104599a2dd95SBruce Richardson __func__);
104699a2dd95SBruce Richardson return -EINVAL;
104799a2dd95SBruce Richardson }
104899a2dd95SBruce Richardson
104999a2dd95SBruce Richardson /* Check that pipeline has at least one input port, one table and one
105099a2dd95SBruce Richardson output port */
105199a2dd95SBruce Richardson if (p->num_ports_in == 0) {
1052ae67895bSDavid Marchand PIPELINE_LOG(ERR, "%s: must have at least 1 input port",
105399a2dd95SBruce Richardson __func__);
105499a2dd95SBruce Richardson return -EINVAL;
105599a2dd95SBruce Richardson }
105699a2dd95SBruce Richardson if (p->num_tables == 0) {
1057ae67895bSDavid Marchand PIPELINE_LOG(ERR, "%s: must have at least 1 table",
105899a2dd95SBruce Richardson __func__);
105999a2dd95SBruce Richardson return -EINVAL;
106099a2dd95SBruce Richardson }
106199a2dd95SBruce Richardson if (p->num_ports_out == 0) {
1062ae67895bSDavid Marchand PIPELINE_LOG(ERR, "%s: must have at least 1 output port",
106399a2dd95SBruce Richardson __func__);
106499a2dd95SBruce Richardson return -EINVAL;
106599a2dd95SBruce Richardson }
106699a2dd95SBruce Richardson
106799a2dd95SBruce Richardson /* Check that all input ports are connected */
106899a2dd95SBruce Richardson for (port_in_id = 0; port_in_id < p->num_ports_in; port_in_id++) {
106999a2dd95SBruce Richardson struct rte_port_in *port_in = &p->ports_in[port_in_id];
107099a2dd95SBruce Richardson
107199a2dd95SBruce Richardson if (port_in->table_id == RTE_TABLE_INVALID) {
1072ae67895bSDavid Marchand PIPELINE_LOG(ERR,
1073ae67895bSDavid Marchand "%s: Port IN ID %u is not connected",
107499a2dd95SBruce Richardson __func__, port_in_id);
107599a2dd95SBruce Richardson return -EINVAL;
107699a2dd95SBruce Richardson }
107799a2dd95SBruce Richardson }
107899a2dd95SBruce Richardson
107999a2dd95SBruce Richardson return 0;
108099a2dd95SBruce Richardson }
108199a2dd95SBruce Richardson
108299a2dd95SBruce Richardson static inline void
rte_pipeline_compute_masks(struct rte_pipeline * p,uint64_t pkts_mask)108399a2dd95SBruce Richardson rte_pipeline_compute_masks(struct rte_pipeline *p, uint64_t pkts_mask)
108499a2dd95SBruce Richardson {
108599a2dd95SBruce Richardson p->action_mask1[RTE_PIPELINE_ACTION_DROP] = 0;
108699a2dd95SBruce Richardson p->action_mask1[RTE_PIPELINE_ACTION_PORT] = 0;
108799a2dd95SBruce Richardson p->action_mask1[RTE_PIPELINE_ACTION_PORT_META] = 0;
108899a2dd95SBruce Richardson p->action_mask1[RTE_PIPELINE_ACTION_TABLE] = 0;
108999a2dd95SBruce Richardson
109099a2dd95SBruce Richardson if ((pkts_mask & (pkts_mask + 1)) == 0) {
10913d4e27fdSDavid Marchand uint64_t n_pkts = rte_popcount64(pkts_mask);
109299a2dd95SBruce Richardson uint32_t i;
109399a2dd95SBruce Richardson
109499a2dd95SBruce Richardson for (i = 0; i < n_pkts; i++) {
109599a2dd95SBruce Richardson uint64_t pkt_mask = 1LLU << i;
109699a2dd95SBruce Richardson uint32_t pos = p->entries[i]->action;
109799a2dd95SBruce Richardson
109899a2dd95SBruce Richardson p->action_mask1[pos] |= pkt_mask;
109999a2dd95SBruce Richardson }
110099a2dd95SBruce Richardson } else {
110199a2dd95SBruce Richardson uint32_t i;
110299a2dd95SBruce Richardson
110399a2dd95SBruce Richardson for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++) {
110499a2dd95SBruce Richardson uint64_t pkt_mask = 1LLU << i;
110599a2dd95SBruce Richardson uint32_t pos;
110699a2dd95SBruce Richardson
110799a2dd95SBruce Richardson if ((pkt_mask & pkts_mask) == 0)
110899a2dd95SBruce Richardson continue;
110999a2dd95SBruce Richardson
111099a2dd95SBruce Richardson pos = p->entries[i]->action;
111199a2dd95SBruce Richardson p->action_mask1[pos] |= pkt_mask;
111299a2dd95SBruce Richardson }
111399a2dd95SBruce Richardson }
111499a2dd95SBruce Richardson }
111599a2dd95SBruce Richardson
111699a2dd95SBruce Richardson static inline void
rte_pipeline_action_handler_port_bulk(struct rte_pipeline * p,uint64_t pkts_mask,uint32_t port_id)111799a2dd95SBruce Richardson rte_pipeline_action_handler_port_bulk(struct rte_pipeline *p,
111899a2dd95SBruce Richardson uint64_t pkts_mask, uint32_t port_id)
111999a2dd95SBruce Richardson {
112099a2dd95SBruce Richardson struct rte_port_out *port_out = &p->ports_out[port_id];
112199a2dd95SBruce Richardson
112299a2dd95SBruce Richardson p->pkts_mask = pkts_mask;
112399a2dd95SBruce Richardson
112499a2dd95SBruce Richardson /* Output port user actions */
112599a2dd95SBruce Richardson if (port_out->f_action != NULL) {
112699a2dd95SBruce Richardson port_out->f_action(p, p->pkts, pkts_mask, port_out->arg_ah);
112799a2dd95SBruce Richardson
112899a2dd95SBruce Richardson RTE_PIPELINE_STATS_AH_DROP_READ(p,
112999a2dd95SBruce Richardson port_out->n_pkts_dropped_by_ah);
113099a2dd95SBruce Richardson }
113199a2dd95SBruce Richardson
113299a2dd95SBruce Richardson /* Output port TX */
113399a2dd95SBruce Richardson if (p->pkts_mask != 0)
113499a2dd95SBruce Richardson port_out->ops.f_tx_bulk(port_out->h_port,
113599a2dd95SBruce Richardson p->pkts,
113699a2dd95SBruce Richardson p->pkts_mask);
113799a2dd95SBruce Richardson }
113899a2dd95SBruce Richardson
113999a2dd95SBruce Richardson static inline void
rte_pipeline_action_handler_port(struct rte_pipeline * p,uint64_t pkts_mask)114099a2dd95SBruce Richardson rte_pipeline_action_handler_port(struct rte_pipeline *p, uint64_t pkts_mask)
114199a2dd95SBruce Richardson {
114299a2dd95SBruce Richardson p->pkts_mask = pkts_mask;
114399a2dd95SBruce Richardson
114499a2dd95SBruce Richardson if ((pkts_mask & (pkts_mask + 1)) == 0) {
11453d4e27fdSDavid Marchand uint64_t n_pkts = rte_popcount64(pkts_mask);
114699a2dd95SBruce Richardson uint32_t i;
114799a2dd95SBruce Richardson
114899a2dd95SBruce Richardson for (i = 0; i < n_pkts; i++) {
114999a2dd95SBruce Richardson struct rte_mbuf *pkt = p->pkts[i];
115099a2dd95SBruce Richardson uint32_t port_out_id = p->entries[i]->port_id;
115199a2dd95SBruce Richardson struct rte_port_out *port_out =
115299a2dd95SBruce Richardson &p->ports_out[port_out_id];
115399a2dd95SBruce Richardson
115499a2dd95SBruce Richardson /* Output port user actions */
115599a2dd95SBruce Richardson if (port_out->f_action == NULL) /* Output port TX */
115699a2dd95SBruce Richardson port_out->ops.f_tx(port_out->h_port, pkt);
115799a2dd95SBruce Richardson else {
115899a2dd95SBruce Richardson uint64_t pkt_mask = 1LLU << i;
115999a2dd95SBruce Richardson
116099a2dd95SBruce Richardson port_out->f_action(p,
116199a2dd95SBruce Richardson p->pkts,
116299a2dd95SBruce Richardson pkt_mask,
116399a2dd95SBruce Richardson port_out->arg_ah);
116499a2dd95SBruce Richardson
116599a2dd95SBruce Richardson RTE_PIPELINE_STATS_AH_DROP_READ(p,
116699a2dd95SBruce Richardson port_out->n_pkts_dropped_by_ah);
116799a2dd95SBruce Richardson
116899a2dd95SBruce Richardson /* Output port TX */
116999a2dd95SBruce Richardson if (pkt_mask & p->pkts_mask)
117099a2dd95SBruce Richardson port_out->ops.f_tx(port_out->h_port,
117199a2dd95SBruce Richardson pkt);
117299a2dd95SBruce Richardson }
117399a2dd95SBruce Richardson }
117499a2dd95SBruce Richardson } else {
117599a2dd95SBruce Richardson uint32_t i;
117699a2dd95SBruce Richardson
117799a2dd95SBruce Richardson for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++) {
117899a2dd95SBruce Richardson uint64_t pkt_mask = 1LLU << i;
117999a2dd95SBruce Richardson struct rte_mbuf *pkt;
118099a2dd95SBruce Richardson struct rte_port_out *port_out;
118199a2dd95SBruce Richardson uint32_t port_out_id;
118299a2dd95SBruce Richardson
118399a2dd95SBruce Richardson if ((pkt_mask & pkts_mask) == 0)
118499a2dd95SBruce Richardson continue;
118599a2dd95SBruce Richardson
118699a2dd95SBruce Richardson pkt = p->pkts[i];
118799a2dd95SBruce Richardson port_out_id = p->entries[i]->port_id;
118899a2dd95SBruce Richardson port_out = &p->ports_out[port_out_id];
118999a2dd95SBruce Richardson
119099a2dd95SBruce Richardson /* Output port user actions */
119199a2dd95SBruce Richardson if (port_out->f_action == NULL) /* Output port TX */
119299a2dd95SBruce Richardson port_out->ops.f_tx(port_out->h_port, pkt);
119399a2dd95SBruce Richardson else {
119499a2dd95SBruce Richardson port_out->f_action(p,
119599a2dd95SBruce Richardson p->pkts,
119699a2dd95SBruce Richardson pkt_mask,
119799a2dd95SBruce Richardson port_out->arg_ah);
119899a2dd95SBruce Richardson
119999a2dd95SBruce Richardson RTE_PIPELINE_STATS_AH_DROP_READ(p,
120099a2dd95SBruce Richardson port_out->n_pkts_dropped_by_ah);
120199a2dd95SBruce Richardson
120299a2dd95SBruce Richardson /* Output port TX */
120399a2dd95SBruce Richardson if (pkt_mask & p->pkts_mask)
120499a2dd95SBruce Richardson port_out->ops.f_tx(port_out->h_port,
120599a2dd95SBruce Richardson pkt);
120699a2dd95SBruce Richardson }
120799a2dd95SBruce Richardson }
120899a2dd95SBruce Richardson }
120999a2dd95SBruce Richardson }
121099a2dd95SBruce Richardson
121199a2dd95SBruce Richardson static inline void
rte_pipeline_action_handler_port_meta(struct rte_pipeline * p,uint64_t pkts_mask)121299a2dd95SBruce Richardson rte_pipeline_action_handler_port_meta(struct rte_pipeline *p,
121399a2dd95SBruce Richardson uint64_t pkts_mask)
121499a2dd95SBruce Richardson {
121599a2dd95SBruce Richardson p->pkts_mask = pkts_mask;
121699a2dd95SBruce Richardson
121799a2dd95SBruce Richardson if ((pkts_mask & (pkts_mask + 1)) == 0) {
12183d4e27fdSDavid Marchand uint64_t n_pkts = rte_popcount64(pkts_mask);
121999a2dd95SBruce Richardson uint32_t i;
122099a2dd95SBruce Richardson
122199a2dd95SBruce Richardson for (i = 0; i < n_pkts; i++) {
122299a2dd95SBruce Richardson struct rte_mbuf *pkt = p->pkts[i];
122399a2dd95SBruce Richardson uint32_t port_out_id =
122499a2dd95SBruce Richardson RTE_MBUF_METADATA_UINT32(pkt,
122599a2dd95SBruce Richardson p->offset_port_id);
122699a2dd95SBruce Richardson struct rte_port_out *port_out = &p->ports_out[
122799a2dd95SBruce Richardson port_out_id];
122899a2dd95SBruce Richardson
122999a2dd95SBruce Richardson /* Output port user actions */
123099a2dd95SBruce Richardson if (port_out->f_action == NULL) /* Output port TX */
123199a2dd95SBruce Richardson port_out->ops.f_tx(port_out->h_port, pkt);
123299a2dd95SBruce Richardson else {
123399a2dd95SBruce Richardson uint64_t pkt_mask = 1LLU << i;
123499a2dd95SBruce Richardson
123599a2dd95SBruce Richardson port_out->f_action(p,
123699a2dd95SBruce Richardson p->pkts,
123799a2dd95SBruce Richardson pkt_mask,
123899a2dd95SBruce Richardson port_out->arg_ah);
123999a2dd95SBruce Richardson
124099a2dd95SBruce Richardson RTE_PIPELINE_STATS_AH_DROP_READ(p,
124199a2dd95SBruce Richardson port_out->n_pkts_dropped_by_ah);
124299a2dd95SBruce Richardson
124399a2dd95SBruce Richardson /* Output port TX */
124499a2dd95SBruce Richardson if (pkt_mask & p->pkts_mask)
124599a2dd95SBruce Richardson port_out->ops.f_tx(port_out->h_port,
124699a2dd95SBruce Richardson pkt);
124799a2dd95SBruce Richardson }
124899a2dd95SBruce Richardson }
124999a2dd95SBruce Richardson } else {
125099a2dd95SBruce Richardson uint32_t i;
125199a2dd95SBruce Richardson
125299a2dd95SBruce Richardson for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++) {
125399a2dd95SBruce Richardson uint64_t pkt_mask = 1LLU << i;
125499a2dd95SBruce Richardson struct rte_mbuf *pkt;
125599a2dd95SBruce Richardson struct rte_port_out *port_out;
125699a2dd95SBruce Richardson uint32_t port_out_id;
125799a2dd95SBruce Richardson
125899a2dd95SBruce Richardson if ((pkt_mask & pkts_mask) == 0)
125999a2dd95SBruce Richardson continue;
126099a2dd95SBruce Richardson
126199a2dd95SBruce Richardson pkt = p->pkts[i];
126299a2dd95SBruce Richardson port_out_id = RTE_MBUF_METADATA_UINT32(pkt,
126399a2dd95SBruce Richardson p->offset_port_id);
126499a2dd95SBruce Richardson port_out = &p->ports_out[port_out_id];
126599a2dd95SBruce Richardson
126699a2dd95SBruce Richardson /* Output port user actions */
126799a2dd95SBruce Richardson if (port_out->f_action == NULL) /* Output port TX */
126899a2dd95SBruce Richardson port_out->ops.f_tx(port_out->h_port, pkt);
126999a2dd95SBruce Richardson else {
127099a2dd95SBruce Richardson port_out->f_action(p,
127199a2dd95SBruce Richardson p->pkts,
127299a2dd95SBruce Richardson pkt_mask,
127399a2dd95SBruce Richardson port_out->arg_ah);
127499a2dd95SBruce Richardson
127599a2dd95SBruce Richardson RTE_PIPELINE_STATS_AH_DROP_READ(p,
127699a2dd95SBruce Richardson port_out->n_pkts_dropped_by_ah);
127799a2dd95SBruce Richardson
127899a2dd95SBruce Richardson /* Output port TX */
127999a2dd95SBruce Richardson if (pkt_mask & p->pkts_mask)
128099a2dd95SBruce Richardson port_out->ops.f_tx(port_out->h_port,
128199a2dd95SBruce Richardson pkt);
128299a2dd95SBruce Richardson }
128399a2dd95SBruce Richardson }
128499a2dd95SBruce Richardson }
128599a2dd95SBruce Richardson }
128699a2dd95SBruce Richardson
128799a2dd95SBruce Richardson static inline void
rte_pipeline_action_handler_drop(struct rte_pipeline * p,uint64_t pkts_mask)128899a2dd95SBruce Richardson rte_pipeline_action_handler_drop(struct rte_pipeline *p, uint64_t pkts_mask)
128999a2dd95SBruce Richardson {
129099a2dd95SBruce Richardson if ((pkts_mask & (pkts_mask + 1)) == 0) {
12913d4e27fdSDavid Marchand uint64_t n_pkts = rte_popcount64(pkts_mask);
129299a2dd95SBruce Richardson uint32_t i;
129399a2dd95SBruce Richardson
129499a2dd95SBruce Richardson for (i = 0; i < n_pkts; i++)
129599a2dd95SBruce Richardson rte_pktmbuf_free(p->pkts[i]);
129699a2dd95SBruce Richardson } else {
129799a2dd95SBruce Richardson uint32_t i;
129899a2dd95SBruce Richardson
129999a2dd95SBruce Richardson for (i = 0; i < RTE_PORT_IN_BURST_SIZE_MAX; i++) {
130099a2dd95SBruce Richardson uint64_t pkt_mask = 1LLU << i;
130199a2dd95SBruce Richardson
130299a2dd95SBruce Richardson if ((pkt_mask & pkts_mask) == 0)
130399a2dd95SBruce Richardson continue;
130499a2dd95SBruce Richardson
130599a2dd95SBruce Richardson rte_pktmbuf_free(p->pkts[i]);
130699a2dd95SBruce Richardson }
130799a2dd95SBruce Richardson }
130899a2dd95SBruce Richardson }
130999a2dd95SBruce Richardson
131099a2dd95SBruce Richardson int
rte_pipeline_run(struct rte_pipeline * p)131199a2dd95SBruce Richardson rte_pipeline_run(struct rte_pipeline *p)
131299a2dd95SBruce Richardson {
131399a2dd95SBruce Richardson struct rte_port_in *port_in = p->port_in_next;
131499a2dd95SBruce Richardson uint32_t n_pkts, table_id;
131599a2dd95SBruce Richardson
131699a2dd95SBruce Richardson if (port_in == NULL)
131799a2dd95SBruce Richardson return 0;
131899a2dd95SBruce Richardson
131999a2dd95SBruce Richardson /* Input port RX */
132099a2dd95SBruce Richardson n_pkts = port_in->ops.f_rx(port_in->h_port, p->pkts,
132199a2dd95SBruce Richardson port_in->burst_size);
132299a2dd95SBruce Richardson if (n_pkts == 0) {
132399a2dd95SBruce Richardson p->port_in_next = port_in->next;
132499a2dd95SBruce Richardson return 0;
132599a2dd95SBruce Richardson }
132699a2dd95SBruce Richardson
132799a2dd95SBruce Richardson p->pkts_mask = RTE_LEN2MASK(n_pkts, uint64_t);
132899a2dd95SBruce Richardson p->action_mask0[RTE_PIPELINE_ACTION_DROP] = 0;
132999a2dd95SBruce Richardson p->action_mask0[RTE_PIPELINE_ACTION_PORT] = 0;
133099a2dd95SBruce Richardson p->action_mask0[RTE_PIPELINE_ACTION_PORT_META] = 0;
133199a2dd95SBruce Richardson p->action_mask0[RTE_PIPELINE_ACTION_TABLE] = 0;
133299a2dd95SBruce Richardson
133399a2dd95SBruce Richardson /* Input port user actions */
133499a2dd95SBruce Richardson if (port_in->f_action != NULL) {
133599a2dd95SBruce Richardson port_in->f_action(p, p->pkts, n_pkts, port_in->arg_ah);
133699a2dd95SBruce Richardson
133799a2dd95SBruce Richardson RTE_PIPELINE_STATS_AH_DROP_READ(p,
133899a2dd95SBruce Richardson port_in->n_pkts_dropped_by_ah);
133999a2dd95SBruce Richardson }
134099a2dd95SBruce Richardson
134199a2dd95SBruce Richardson /* Table */
134299a2dd95SBruce Richardson for (table_id = port_in->table_id; p->pkts_mask != 0; ) {
134399a2dd95SBruce Richardson struct rte_table *table;
134499a2dd95SBruce Richardson uint64_t lookup_hit_mask, lookup_miss_mask;
134599a2dd95SBruce Richardson
134699a2dd95SBruce Richardson /* Lookup */
134799a2dd95SBruce Richardson table = &p->tables[table_id];
134899a2dd95SBruce Richardson table->ops.f_lookup(table->h_table, p->pkts, p->pkts_mask,
134999a2dd95SBruce Richardson &lookup_hit_mask, (void **) p->entries);
135099a2dd95SBruce Richardson lookup_miss_mask = p->pkts_mask & (~lookup_hit_mask);
135199a2dd95SBruce Richardson
135299a2dd95SBruce Richardson /* Lookup miss */
135399a2dd95SBruce Richardson if (lookup_miss_mask != 0) {
135499a2dd95SBruce Richardson struct rte_pipeline_table_entry *default_entry =
135599a2dd95SBruce Richardson table->default_entry;
135699a2dd95SBruce Richardson
135799a2dd95SBruce Richardson p->pkts_mask = lookup_miss_mask;
135899a2dd95SBruce Richardson
135999a2dd95SBruce Richardson /* Table user actions */
136099a2dd95SBruce Richardson if (table->f_action_miss != NULL) {
136199a2dd95SBruce Richardson table->f_action_miss(p,
136299a2dd95SBruce Richardson p->pkts,
136399a2dd95SBruce Richardson lookup_miss_mask,
136499a2dd95SBruce Richardson default_entry,
136599a2dd95SBruce Richardson table->arg_ah);
136699a2dd95SBruce Richardson
136799a2dd95SBruce Richardson RTE_PIPELINE_STATS_AH_DROP_READ(p,
136899a2dd95SBruce Richardson table->n_pkts_dropped_by_lkp_miss_ah);
136999a2dd95SBruce Richardson }
137099a2dd95SBruce Richardson
137199a2dd95SBruce Richardson /* Table reserved actions */
137299a2dd95SBruce Richardson if ((default_entry->action == RTE_PIPELINE_ACTION_PORT) &&
137399a2dd95SBruce Richardson (p->pkts_mask != 0))
137499a2dd95SBruce Richardson rte_pipeline_action_handler_port_bulk(p,
137599a2dd95SBruce Richardson p->pkts_mask,
137699a2dd95SBruce Richardson default_entry->port_id);
137799a2dd95SBruce Richardson else {
137899a2dd95SBruce Richardson uint32_t pos = default_entry->action;
137999a2dd95SBruce Richardson
138099a2dd95SBruce Richardson RTE_PIPELINE_STATS_TABLE_DROP0(p);
138199a2dd95SBruce Richardson
138299a2dd95SBruce Richardson p->action_mask0[pos] |= p->pkts_mask;
138399a2dd95SBruce Richardson
138499a2dd95SBruce Richardson RTE_PIPELINE_STATS_TABLE_DROP1(p,
138599a2dd95SBruce Richardson table->n_pkts_dropped_lkp_miss);
138699a2dd95SBruce Richardson }
138799a2dd95SBruce Richardson }
138899a2dd95SBruce Richardson
138999a2dd95SBruce Richardson /* Lookup hit */
139099a2dd95SBruce Richardson if (lookup_hit_mask != 0) {
139199a2dd95SBruce Richardson p->pkts_mask = lookup_hit_mask;
139299a2dd95SBruce Richardson
139399a2dd95SBruce Richardson /* Table user actions */
139499a2dd95SBruce Richardson if (table->f_action_hit != NULL) {
139599a2dd95SBruce Richardson table->f_action_hit(p,
139699a2dd95SBruce Richardson p->pkts,
139799a2dd95SBruce Richardson lookup_hit_mask,
139899a2dd95SBruce Richardson p->entries,
139999a2dd95SBruce Richardson table->arg_ah);
140099a2dd95SBruce Richardson
140199a2dd95SBruce Richardson RTE_PIPELINE_STATS_AH_DROP_READ(p,
140299a2dd95SBruce Richardson table->n_pkts_dropped_by_lkp_hit_ah);
140399a2dd95SBruce Richardson }
140499a2dd95SBruce Richardson
140599a2dd95SBruce Richardson /* Table reserved actions */
140699a2dd95SBruce Richardson RTE_PIPELINE_STATS_TABLE_DROP0(p);
140799a2dd95SBruce Richardson rte_pipeline_compute_masks(p, p->pkts_mask);
140899a2dd95SBruce Richardson p->action_mask0[RTE_PIPELINE_ACTION_DROP] |=
140999a2dd95SBruce Richardson p->action_mask1[
141099a2dd95SBruce Richardson RTE_PIPELINE_ACTION_DROP];
141199a2dd95SBruce Richardson p->action_mask0[RTE_PIPELINE_ACTION_PORT] |=
141299a2dd95SBruce Richardson p->action_mask1[
141399a2dd95SBruce Richardson RTE_PIPELINE_ACTION_PORT];
141499a2dd95SBruce Richardson p->action_mask0[RTE_PIPELINE_ACTION_PORT_META] |=
141599a2dd95SBruce Richardson p->action_mask1[
141699a2dd95SBruce Richardson RTE_PIPELINE_ACTION_PORT_META];
141799a2dd95SBruce Richardson p->action_mask0[RTE_PIPELINE_ACTION_TABLE] |=
141899a2dd95SBruce Richardson p->action_mask1[
141999a2dd95SBruce Richardson RTE_PIPELINE_ACTION_TABLE];
142099a2dd95SBruce Richardson
142199a2dd95SBruce Richardson RTE_PIPELINE_STATS_TABLE_DROP1(p,
142299a2dd95SBruce Richardson table->n_pkts_dropped_lkp_hit);
142399a2dd95SBruce Richardson }
142499a2dd95SBruce Richardson
142599a2dd95SBruce Richardson /* Prepare for next iteration */
142699a2dd95SBruce Richardson p->pkts_mask = p->action_mask0[RTE_PIPELINE_ACTION_TABLE];
142799a2dd95SBruce Richardson table_id = table->table_next_id;
142899a2dd95SBruce Richardson p->action_mask0[RTE_PIPELINE_ACTION_TABLE] = 0;
142999a2dd95SBruce Richardson }
143099a2dd95SBruce Richardson
143199a2dd95SBruce Richardson /* Table reserved action PORT */
143299a2dd95SBruce Richardson rte_pipeline_action_handler_port(p,
143399a2dd95SBruce Richardson p->action_mask0[RTE_PIPELINE_ACTION_PORT]);
143499a2dd95SBruce Richardson
143599a2dd95SBruce Richardson /* Table reserved action PORT META */
143699a2dd95SBruce Richardson rte_pipeline_action_handler_port_meta(p,
143799a2dd95SBruce Richardson p->action_mask0[RTE_PIPELINE_ACTION_PORT_META]);
143899a2dd95SBruce Richardson
143999a2dd95SBruce Richardson /* Table reserved action DROP */
144099a2dd95SBruce Richardson rte_pipeline_action_handler_drop(p,
144199a2dd95SBruce Richardson p->action_mask0[RTE_PIPELINE_ACTION_DROP]);
144299a2dd95SBruce Richardson
144399a2dd95SBruce Richardson /* Pick candidate for next port IN to serve */
144499a2dd95SBruce Richardson p->port_in_next = port_in->next;
144599a2dd95SBruce Richardson
144699a2dd95SBruce Richardson return (int) n_pkts;
144799a2dd95SBruce Richardson }
144899a2dd95SBruce Richardson
144999a2dd95SBruce Richardson int
rte_pipeline_flush(struct rte_pipeline * p)145099a2dd95SBruce Richardson rte_pipeline_flush(struct rte_pipeline *p)
145199a2dd95SBruce Richardson {
145299a2dd95SBruce Richardson uint32_t port_id;
145399a2dd95SBruce Richardson
145499a2dd95SBruce Richardson /* Check input arguments */
145599a2dd95SBruce Richardson if (p == NULL) {
1456ae67895bSDavid Marchand PIPELINE_LOG(ERR, "%s: pipeline parameter NULL",
145799a2dd95SBruce Richardson __func__);
145899a2dd95SBruce Richardson return -EINVAL;
145999a2dd95SBruce Richardson }
146099a2dd95SBruce Richardson
146199a2dd95SBruce Richardson for (port_id = 0; port_id < p->num_ports_out; port_id++) {
146299a2dd95SBruce Richardson struct rte_port_out *port = &p->ports_out[port_id];
146399a2dd95SBruce Richardson
146499a2dd95SBruce Richardson if (port->ops.f_flush != NULL)
146599a2dd95SBruce Richardson port->ops.f_flush(port->h_port);
146699a2dd95SBruce Richardson }
146799a2dd95SBruce Richardson
146899a2dd95SBruce Richardson return 0;
146999a2dd95SBruce Richardson }
147099a2dd95SBruce Richardson
147199a2dd95SBruce Richardson int
rte_pipeline_port_out_packet_insert(struct rte_pipeline * p,uint32_t port_id,struct rte_mbuf * pkt)147299a2dd95SBruce Richardson rte_pipeline_port_out_packet_insert(struct rte_pipeline *p,
147399a2dd95SBruce Richardson uint32_t port_id, struct rte_mbuf *pkt)
147499a2dd95SBruce Richardson {
147599a2dd95SBruce Richardson struct rte_port_out *port_out = &p->ports_out[port_id];
147699a2dd95SBruce Richardson
147799a2dd95SBruce Richardson port_out->ops.f_tx(port_out->h_port, pkt); /* Output port TX */
147899a2dd95SBruce Richardson
147999a2dd95SBruce Richardson return 0;
148099a2dd95SBruce Richardson }
148199a2dd95SBruce Richardson
rte_pipeline_ah_packet_hijack(struct rte_pipeline * p,uint64_t pkts_mask)148299a2dd95SBruce Richardson int rte_pipeline_ah_packet_hijack(struct rte_pipeline *p,
148399a2dd95SBruce Richardson uint64_t pkts_mask)
148499a2dd95SBruce Richardson {
148599a2dd95SBruce Richardson pkts_mask &= p->pkts_mask;
148699a2dd95SBruce Richardson p->pkts_mask &= ~pkts_mask;
148799a2dd95SBruce Richardson
148899a2dd95SBruce Richardson return 0;
148999a2dd95SBruce Richardson }
149099a2dd95SBruce Richardson
rte_pipeline_ah_packet_drop(struct rte_pipeline * p,uint64_t pkts_mask)149199a2dd95SBruce Richardson int rte_pipeline_ah_packet_drop(struct rte_pipeline *p,
149299a2dd95SBruce Richardson uint64_t pkts_mask)
149399a2dd95SBruce Richardson {
149499a2dd95SBruce Richardson pkts_mask &= p->pkts_mask;
149599a2dd95SBruce Richardson p->pkts_mask &= ~pkts_mask;
149699a2dd95SBruce Richardson p->action_mask0[RTE_PIPELINE_ACTION_DROP] |= pkts_mask;
149799a2dd95SBruce Richardson
149899a2dd95SBruce Richardson RTE_PIPELINE_STATS_AH_DROP_WRITE(p, pkts_mask);
149999a2dd95SBruce Richardson return 0;
150099a2dd95SBruce Richardson }
150199a2dd95SBruce Richardson
rte_pipeline_port_in_stats_read(struct rte_pipeline * p,uint32_t port_id,struct rte_pipeline_port_in_stats * stats,int clear)150299a2dd95SBruce Richardson int rte_pipeline_port_in_stats_read(struct rte_pipeline *p, uint32_t port_id,
150399a2dd95SBruce Richardson struct rte_pipeline_port_in_stats *stats, int clear)
150499a2dd95SBruce Richardson {
150599a2dd95SBruce Richardson struct rte_port_in *port;
150699a2dd95SBruce Richardson int retval;
150799a2dd95SBruce Richardson
150899a2dd95SBruce Richardson if (p == NULL) {
1509ae67895bSDavid Marchand PIPELINE_LOG(ERR, "%s: pipeline parameter NULL",
151099a2dd95SBruce Richardson __func__);
151199a2dd95SBruce Richardson return -EINVAL;
151299a2dd95SBruce Richardson }
151399a2dd95SBruce Richardson
151499a2dd95SBruce Richardson if (port_id >= p->num_ports_in) {
1515ae67895bSDavid Marchand PIPELINE_LOG(ERR,
1516ae67895bSDavid Marchand "%s: port IN ID %u is out of range",
151799a2dd95SBruce Richardson __func__, port_id);
151899a2dd95SBruce Richardson return -EINVAL;
151999a2dd95SBruce Richardson }
152099a2dd95SBruce Richardson
152199a2dd95SBruce Richardson port = &p->ports_in[port_id];
152299a2dd95SBruce Richardson
152399a2dd95SBruce Richardson if (port->ops.f_stats != NULL) {
152499a2dd95SBruce Richardson retval = port->ops.f_stats(port->h_port, &stats->stats, clear);
152599a2dd95SBruce Richardson if (retval)
152699a2dd95SBruce Richardson return retval;
152799a2dd95SBruce Richardson } else if (stats != NULL)
152899a2dd95SBruce Richardson memset(&stats->stats, 0, sizeof(stats->stats));
152999a2dd95SBruce Richardson
153099a2dd95SBruce Richardson if (stats != NULL)
153199a2dd95SBruce Richardson stats->n_pkts_dropped_by_ah = port->n_pkts_dropped_by_ah;
153299a2dd95SBruce Richardson
153399a2dd95SBruce Richardson if (clear != 0)
153499a2dd95SBruce Richardson port->n_pkts_dropped_by_ah = 0;
153599a2dd95SBruce Richardson
153699a2dd95SBruce Richardson return 0;
153799a2dd95SBruce Richardson }
153899a2dd95SBruce Richardson
rte_pipeline_port_out_stats_read(struct rte_pipeline * p,uint32_t port_id,struct rte_pipeline_port_out_stats * stats,int clear)153999a2dd95SBruce Richardson int rte_pipeline_port_out_stats_read(struct rte_pipeline *p, uint32_t port_id,
154099a2dd95SBruce Richardson struct rte_pipeline_port_out_stats *stats, int clear)
154199a2dd95SBruce Richardson {
154299a2dd95SBruce Richardson struct rte_port_out *port;
154399a2dd95SBruce Richardson int retval;
154499a2dd95SBruce Richardson
154599a2dd95SBruce Richardson if (p == NULL) {
1546ae67895bSDavid Marchand PIPELINE_LOG(ERR, "%s: pipeline parameter NULL", __func__);
154799a2dd95SBruce Richardson return -EINVAL;
154899a2dd95SBruce Richardson }
154999a2dd95SBruce Richardson
155099a2dd95SBruce Richardson if (port_id >= p->num_ports_out) {
1551ae67895bSDavid Marchand PIPELINE_LOG(ERR,
1552ae67895bSDavid Marchand "%s: port OUT ID %u is out of range", __func__, port_id);
155399a2dd95SBruce Richardson return -EINVAL;
155499a2dd95SBruce Richardson }
155599a2dd95SBruce Richardson
155699a2dd95SBruce Richardson port = &p->ports_out[port_id];
155799a2dd95SBruce Richardson if (port->ops.f_stats != NULL) {
155899a2dd95SBruce Richardson retval = port->ops.f_stats(port->h_port, &stats->stats, clear);
155999a2dd95SBruce Richardson if (retval != 0)
156099a2dd95SBruce Richardson return retval;
156199a2dd95SBruce Richardson } else if (stats != NULL)
156299a2dd95SBruce Richardson memset(&stats->stats, 0, sizeof(stats->stats));
156399a2dd95SBruce Richardson
156499a2dd95SBruce Richardson if (stats != NULL)
156599a2dd95SBruce Richardson stats->n_pkts_dropped_by_ah = port->n_pkts_dropped_by_ah;
156699a2dd95SBruce Richardson
156799a2dd95SBruce Richardson if (clear != 0)
156899a2dd95SBruce Richardson port->n_pkts_dropped_by_ah = 0;
156999a2dd95SBruce Richardson
157099a2dd95SBruce Richardson return 0;
157199a2dd95SBruce Richardson }
157299a2dd95SBruce Richardson
rte_pipeline_table_stats_read(struct rte_pipeline * p,uint32_t table_id,struct rte_pipeline_table_stats * stats,int clear)157399a2dd95SBruce Richardson int rte_pipeline_table_stats_read(struct rte_pipeline *p, uint32_t table_id,
157499a2dd95SBruce Richardson struct rte_pipeline_table_stats *stats, int clear)
157599a2dd95SBruce Richardson {
157699a2dd95SBruce Richardson struct rte_table *table;
157799a2dd95SBruce Richardson int retval;
157899a2dd95SBruce Richardson
157999a2dd95SBruce Richardson if (p == NULL) {
1580ae67895bSDavid Marchand PIPELINE_LOG(ERR, "%s: pipeline parameter NULL",
158199a2dd95SBruce Richardson __func__);
158299a2dd95SBruce Richardson return -EINVAL;
158399a2dd95SBruce Richardson }
158499a2dd95SBruce Richardson
158599a2dd95SBruce Richardson if (table_id >= p->num_tables) {
1586ae67895bSDavid Marchand PIPELINE_LOG(ERR,
1587ae67895bSDavid Marchand "%s: table %u is out of range", __func__, table_id);
158899a2dd95SBruce Richardson return -EINVAL;
158999a2dd95SBruce Richardson }
159099a2dd95SBruce Richardson
159199a2dd95SBruce Richardson table = &p->tables[table_id];
159299a2dd95SBruce Richardson if (table->ops.f_stats != NULL) {
159399a2dd95SBruce Richardson retval = table->ops.f_stats(table->h_table, &stats->stats, clear);
159499a2dd95SBruce Richardson if (retval != 0)
159599a2dd95SBruce Richardson return retval;
159699a2dd95SBruce Richardson } else if (stats != NULL)
159799a2dd95SBruce Richardson memset(&stats->stats, 0, sizeof(stats->stats));
159899a2dd95SBruce Richardson
159999a2dd95SBruce Richardson if (stats != NULL) {
160099a2dd95SBruce Richardson stats->n_pkts_dropped_by_lkp_hit_ah =
160199a2dd95SBruce Richardson table->n_pkts_dropped_by_lkp_hit_ah;
160299a2dd95SBruce Richardson stats->n_pkts_dropped_by_lkp_miss_ah =
160399a2dd95SBruce Richardson table->n_pkts_dropped_by_lkp_miss_ah;
160499a2dd95SBruce Richardson stats->n_pkts_dropped_lkp_hit = table->n_pkts_dropped_lkp_hit;
160599a2dd95SBruce Richardson stats->n_pkts_dropped_lkp_miss = table->n_pkts_dropped_lkp_miss;
160699a2dd95SBruce Richardson }
160799a2dd95SBruce Richardson
160899a2dd95SBruce Richardson if (clear != 0) {
160999a2dd95SBruce Richardson table->n_pkts_dropped_by_lkp_hit_ah = 0;
161099a2dd95SBruce Richardson table->n_pkts_dropped_by_lkp_miss_ah = 0;
161199a2dd95SBruce Richardson table->n_pkts_dropped_lkp_hit = 0;
161299a2dd95SBruce Richardson table->n_pkts_dropped_lkp_miss = 0;
161399a2dd95SBruce Richardson }
161499a2dd95SBruce Richardson
161599a2dd95SBruce Richardson return 0;
161699a2dd95SBruce Richardson }
1617