pipeline: add SWX pipeline output port

Add output ports to the newly introduced SWX pipeline type. Each port
instantiates a port type that defines the port operations, e.g. ethdev
port, PCAP port, etc. The TX interface is single packet, with packet
batching internally for performance.

Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
This commit is contained in:
Cristian Dumitrescu 2020-10-01 11:19:31 +01:00 committed by David Marchand
parent 6e0ca01c93
commit 99a0ba8f4c
4 changed files with 336 additions and 0 deletions

View File

@ -65,4 +65,6 @@ EXPERIMENTAL {
rte_swx_pipeline_free;
rte_swx_pipeline_port_in_config;
rte_swx_pipeline_port_in_type_register;
rte_swx_pipeline_port_out_config;
rte_swx_pipeline_port_out_type_register;
};

View File

@ -45,16 +45,46 @@ struct port_in_runtime {
void *obj;
};
/*
* Output port.
*/
struct port_out_type {
TAILQ_ENTRY(port_out_type) node;
char name[RTE_SWX_NAME_SIZE];
struct rte_swx_port_out_ops ops;
};
TAILQ_HEAD(port_out_type_tailq, port_out_type);
struct port_out {
TAILQ_ENTRY(port_out) node;
struct port_out_type *type;
void *obj;
uint32_t id;
};
TAILQ_HEAD(port_out_tailq, port_out);
struct port_out_runtime {
rte_swx_port_out_pkt_tx_t pkt_tx;
rte_swx_port_out_flush_t flush;
void *obj;
};
/*
* Pipeline.
*/
struct rte_swx_pipeline {
struct port_in_type_tailq port_in_types;
struct port_in_tailq ports_in;
struct port_out_type_tailq port_out_types;
struct port_out_tailq ports_out;
struct port_in_runtime *in;
struct port_out_runtime *out;
uint32_t n_ports_in;
uint32_t n_ports_out;
int build_done;
int numa_node;
};
@ -221,6 +251,168 @@ port_in_free(struct rte_swx_pipeline *p)
}
}
/*
* Output port.
*/
static struct port_out_type *
port_out_type_find(struct rte_swx_pipeline *p, const char *name)
{
struct port_out_type *elem;
if (!name)
return NULL;
TAILQ_FOREACH(elem, &p->port_out_types, node)
if (!strcmp(elem->name, name))
return elem;
return NULL;
}
int
rte_swx_pipeline_port_out_type_register(struct rte_swx_pipeline *p,
const char *name,
struct rte_swx_port_out_ops *ops)
{
struct port_out_type *elem;
CHECK(p, EINVAL);
CHECK_NAME(name, EINVAL);
CHECK(ops, EINVAL);
CHECK(ops->create, EINVAL);
CHECK(ops->free, EINVAL);
CHECK(ops->pkt_tx, EINVAL);
CHECK(ops->stats_read, EINVAL);
CHECK(!port_out_type_find(p, name), EEXIST);
/* Node allocation. */
elem = calloc(1, sizeof(struct port_out_type));
CHECK(elem, ENOMEM);
/* Node initialization. */
strcpy(elem->name, name);
memcpy(&elem->ops, ops, sizeof(*ops));
/* Node add to tailq. */
TAILQ_INSERT_TAIL(&p->port_out_types, elem, node);
return 0;
}
static struct port_out *
port_out_find(struct rte_swx_pipeline *p, uint32_t port_id)
{
struct port_out *port;
TAILQ_FOREACH(port, &p->ports_out, node)
if (port->id == port_id)
return port;
return NULL;
}
int
rte_swx_pipeline_port_out_config(struct rte_swx_pipeline *p,
uint32_t port_id,
const char *port_type_name,
void *args)
{
struct port_out_type *type = NULL;
struct port_out *port = NULL;
void *obj = NULL;
CHECK(p, EINVAL);
CHECK(!port_out_find(p, port_id), EINVAL);
CHECK_NAME(port_type_name, EINVAL);
type = port_out_type_find(p, port_type_name);
CHECK(type, EINVAL);
obj = type->ops.create(args);
CHECK(obj, ENODEV);
/* Node allocation. */
port = calloc(1, sizeof(struct port_out));
CHECK(port, ENOMEM);
/* Node initialization. */
port->type = type;
port->obj = obj;
port->id = port_id;
/* Node add to tailq. */
TAILQ_INSERT_TAIL(&p->ports_out, port, node);
if (p->n_ports_out < port_id + 1)
p->n_ports_out = port_id + 1;
return 0;
}
static int
port_out_build(struct rte_swx_pipeline *p)
{
struct port_out *port;
uint32_t i;
CHECK(p->n_ports_out, EINVAL);
for (i = 0; i < p->n_ports_out; i++)
CHECK(port_out_find(p, i), EINVAL);
p->out = calloc(p->n_ports_out, sizeof(struct port_out_runtime));
CHECK(p->out, ENOMEM);
TAILQ_FOREACH(port, &p->ports_out, node) {
struct port_out_runtime *out = &p->out[port->id];
out->pkt_tx = port->type->ops.pkt_tx;
out->flush = port->type->ops.flush;
out->obj = port->obj;
}
return 0;
}
static void
port_out_build_free(struct rte_swx_pipeline *p)
{
free(p->out);
p->out = NULL;
}
static void
port_out_free(struct rte_swx_pipeline *p)
{
port_out_build_free(p);
/* Output ports. */
for ( ; ; ) {
struct port_out *port;
port = TAILQ_FIRST(&p->ports_out);
if (!port)
break;
TAILQ_REMOVE(&p->ports_out, port, node);
port->type->ops.free(port->obj);
free(port);
}
/* Output port types. */
for ( ; ; ) {
struct port_out_type *elem;
elem = TAILQ_FIRST(&p->port_out_types);
if (!elem)
break;
TAILQ_REMOVE(&p->port_out_types, elem, node);
free(elem);
}
}
/*
* Pipeline.
*/
@ -239,6 +431,8 @@ rte_swx_pipeline_config(struct rte_swx_pipeline **p, int numa_node)
/* Initialization. */
TAILQ_INIT(&pipeline->port_in_types);
TAILQ_INIT(&pipeline->ports_in);
TAILQ_INIT(&pipeline->port_out_types);
TAILQ_INIT(&pipeline->ports_out);
pipeline->numa_node = numa_node;
@ -252,6 +446,7 @@ rte_swx_pipeline_free(struct rte_swx_pipeline *p)
if (!p)
return;
port_out_free(p);
port_in_free(p);
free(p);
@ -269,10 +464,15 @@ rte_swx_pipeline_build(struct rte_swx_pipeline *p)
if (status)
goto error;
status = port_out_build(p);
if (status)
goto error;
p->build_done = 1;
return 0;
error:
port_out_build_free(p);
port_in_build_free(p);
return status;

View File

@ -97,6 +97,56 @@ rte_swx_pipeline_port_in_config(struct rte_swx_pipeline *p,
uint32_t port_id,
const char *port_type_name,
void *args);
/*
* Pipeline output ports
*/
/**
* Pipeline output port type register
*
* @param[in] p
* Pipeline handle.
* @param[in] name
* Output port type name.
* @param[in] ops
* Output port type operations.
* @return
* 0 on success or the following error codes otherwise:
* -EINVAL: Invalid argument;
* -ENOMEM: Not enough space/cannot allocate memory;
* -EEXIST: Output port type with this name already exists.
*/
__rte_experimental
int
rte_swx_pipeline_port_out_type_register(struct rte_swx_pipeline *p,
const char *name,
struct rte_swx_port_out_ops *ops);
/**
* Pipeline output port configure
*
* @param[in] p
* Pipeline handle.
* @param[in] port_id
* Output port ID.
* @param[in] port_type_name
* Existing output port type name.
* @param[in] args
* Output port creation arguments.
* @return
* 0 on success or the following error codes otherwise:
* -EINVAL: Invalid argument;
* -ENOMEM: Not enough space/cannot allocate memory;
* -ENODEV: Output port object creation error.
*/
__rte_experimental
int
rte_swx_pipeline_port_out_config(struct rte_swx_pipeline *p,
uint32_t port_id,
const char *port_type_name,
void *args);
/**
* Pipeline build
*

View File

@ -111,6 +111,90 @@ struct rte_swx_port_in_ops {
rte_swx_port_in_stats_read_t stats_read;
};
/*
* Output port
*/
/**
* Output port create
*
* @param[in] args
* Arguments for output port creation. Format specific to each port type.
* @return
* Handle to output port instance on success, NULL on error.
*/
typedef void *
(*rte_swx_port_out_create_t)(void *args);
/**
* Output port free
*
* @param[in] args
* Output port handle.
*/
typedef void
(*rte_swx_port_out_free_t)(void *port);
/**
* Output port packet transmit
*
* @param[in] port
* Output port handle.
* @param[in] pkt
* Packet to be transmitted.
*/
typedef void
(*rte_swx_port_out_pkt_tx_t)(void *port,
struct rte_swx_pkt *pkt);
/**
* Output port flush
*
* @param[in] port
* Output port handle.
*/
typedef void
(*rte_swx_port_out_flush_t)(void *port);
/** Output port statistics counters. */
struct rte_swx_port_out_stats {
/** Number of packets. */
uint64_t n_pkts;
/** Number of bytes. */
uint64_t n_bytes;
};
/**
* Output port statistics counters read
*
* @param[in] port
* Output port handle.
* @param[out] stats
* Output port statistics counters. Must point to valid memory.
*/
typedef void
(*rte_swx_port_out_stats_read_t)(void *port,
struct rte_swx_port_out_stats *stats);
/** Output port operations. */
struct rte_swx_port_out_ops {
/** Create. Must be non-NULL. */
rte_swx_port_out_create_t create;
/** Free. Must be non-NULL. */
rte_swx_port_out_free_t free;
/** Packet transmission. Must be non-NULL. */
rte_swx_port_out_pkt_tx_t pkt_tx;
/** Flush. May be NULL. */
rte_swx_port_out_flush_t flush;
/** Statistics counters read. Must be non-NULL. */
rte_swx_port_out_stats_read_t stats_read;
};
#ifdef __cplusplus
}
#endif