xref: /dpdk/lib/pipeline/rte_pipeline.c (revision c6552d9a8deffa448de2d5e2e726f50508c1efd2)
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