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:
parent
6e0ca01c93
commit
99a0ba8f4c
@ -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;
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
*
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user