pipeline: add SWX pipeline input port
Add input 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 RX 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
56492fd536
commit
6e0ca01c93
@ -168,6 +168,8 @@ The public API headers are grouped by topics:
|
||||
[table_action] (@ref rte_table_action.h)
|
||||
* SWX pipeline:
|
||||
[pipeline] (@ref rte_swx_pipeline.h)
|
||||
* SWX port:
|
||||
[port] (@ref rte_swx_port.h)
|
||||
* [graph] (@ref rte_graph.h):
|
||||
[graph_worker] (@ref rte_graph_worker.h)
|
||||
* graph_nodes:
|
||||
|
@ -63,4 +63,6 @@ EXPERIMENTAL {
|
||||
rte_swx_pipeline_build;
|
||||
rte_swx_pipeline_config;
|
||||
rte_swx_pipeline_free;
|
||||
rte_swx_pipeline_port_in_config;
|
||||
rte_swx_pipeline_port_in_type_register;
|
||||
};
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <sys/queue.h>
|
||||
|
||||
#include <rte_common.h>
|
||||
|
||||
@ -19,14 +20,206 @@ do { \
|
||||
#define CHECK_NAME(name, err_code) \
|
||||
CHECK((name) && (name)[0], err_code)
|
||||
|
||||
/*
|
||||
* Input port.
|
||||
*/
|
||||
struct port_in_type {
|
||||
TAILQ_ENTRY(port_in_type) node;
|
||||
char name[RTE_SWX_NAME_SIZE];
|
||||
struct rte_swx_port_in_ops ops;
|
||||
};
|
||||
|
||||
TAILQ_HEAD(port_in_type_tailq, port_in_type);
|
||||
|
||||
struct port_in {
|
||||
TAILQ_ENTRY(port_in) node;
|
||||
struct port_in_type *type;
|
||||
void *obj;
|
||||
uint32_t id;
|
||||
};
|
||||
|
||||
TAILQ_HEAD(port_in_tailq, port_in);
|
||||
|
||||
struct port_in_runtime {
|
||||
rte_swx_port_in_pkt_rx_t pkt_rx;
|
||||
void *obj;
|
||||
};
|
||||
|
||||
/*
|
||||
* Pipeline.
|
||||
*/
|
||||
struct rte_swx_pipeline {
|
||||
struct port_in_type_tailq port_in_types;
|
||||
struct port_in_tailq ports_in;
|
||||
|
||||
struct port_in_runtime *in;
|
||||
|
||||
uint32_t n_ports_in;
|
||||
int build_done;
|
||||
int numa_node;
|
||||
};
|
||||
|
||||
/*
|
||||
* Input port.
|
||||
*/
|
||||
static struct port_in_type *
|
||||
port_in_type_find(struct rte_swx_pipeline *p, const char *name)
|
||||
{
|
||||
struct port_in_type *elem;
|
||||
|
||||
if (!name)
|
||||
return NULL;
|
||||
|
||||
TAILQ_FOREACH(elem, &p->port_in_types, node)
|
||||
if (strcmp(elem->name, name) == 0)
|
||||
return elem;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
rte_swx_pipeline_port_in_type_register(struct rte_swx_pipeline *p,
|
||||
const char *name,
|
||||
struct rte_swx_port_in_ops *ops)
|
||||
{
|
||||
struct port_in_type *elem;
|
||||
|
||||
CHECK(p, EINVAL);
|
||||
CHECK_NAME(name, EINVAL);
|
||||
CHECK(ops, EINVAL);
|
||||
CHECK(ops->create, EINVAL);
|
||||
CHECK(ops->free, EINVAL);
|
||||
CHECK(ops->pkt_rx, EINVAL);
|
||||
CHECK(ops->stats_read, EINVAL);
|
||||
|
||||
CHECK(!port_in_type_find(p, name), EEXIST);
|
||||
|
||||
/* Node allocation. */
|
||||
elem = calloc(1, sizeof(struct port_in_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_in_types, elem, node);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct port_in *
|
||||
port_in_find(struct rte_swx_pipeline *p, uint32_t port_id)
|
||||
{
|
||||
struct port_in *port;
|
||||
|
||||
TAILQ_FOREACH(port, &p->ports_in, node)
|
||||
if (port->id == port_id)
|
||||
return port;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
rte_swx_pipeline_port_in_config(struct rte_swx_pipeline *p,
|
||||
uint32_t port_id,
|
||||
const char *port_type_name,
|
||||
void *args)
|
||||
{
|
||||
struct port_in_type *type = NULL;
|
||||
struct port_in *port = NULL;
|
||||
void *obj = NULL;
|
||||
|
||||
CHECK(p, EINVAL);
|
||||
|
||||
CHECK(!port_in_find(p, port_id), EINVAL);
|
||||
|
||||
CHECK_NAME(port_type_name, EINVAL);
|
||||
type = port_in_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_in));
|
||||
CHECK(port, ENOMEM);
|
||||
|
||||
/* Node initialization. */
|
||||
port->type = type;
|
||||
port->obj = obj;
|
||||
port->id = port_id;
|
||||
|
||||
/* Node add to tailq. */
|
||||
TAILQ_INSERT_TAIL(&p->ports_in, port, node);
|
||||
if (p->n_ports_in < port_id + 1)
|
||||
p->n_ports_in = port_id + 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
port_in_build(struct rte_swx_pipeline *p)
|
||||
{
|
||||
struct port_in *port;
|
||||
uint32_t i;
|
||||
|
||||
CHECK(p->n_ports_in, EINVAL);
|
||||
CHECK(rte_is_power_of_2(p->n_ports_in), EINVAL);
|
||||
|
||||
for (i = 0; i < p->n_ports_in; i++)
|
||||
CHECK(port_in_find(p, i), EINVAL);
|
||||
|
||||
p->in = calloc(p->n_ports_in, sizeof(struct port_in_runtime));
|
||||
CHECK(p->in, ENOMEM);
|
||||
|
||||
TAILQ_FOREACH(port, &p->ports_in, node) {
|
||||
struct port_in_runtime *in = &p->in[port->id];
|
||||
|
||||
in->pkt_rx = port->type->ops.pkt_rx;
|
||||
in->obj = port->obj;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
port_in_build_free(struct rte_swx_pipeline *p)
|
||||
{
|
||||
free(p->in);
|
||||
p->in = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
port_in_free(struct rte_swx_pipeline *p)
|
||||
{
|
||||
port_in_build_free(p);
|
||||
|
||||
/* Input ports. */
|
||||
for ( ; ; ) {
|
||||
struct port_in *port;
|
||||
|
||||
port = TAILQ_FIRST(&p->ports_in);
|
||||
if (!port)
|
||||
break;
|
||||
|
||||
TAILQ_REMOVE(&p->ports_in, port, node);
|
||||
port->type->ops.free(port->obj);
|
||||
free(port);
|
||||
}
|
||||
|
||||
/* Input port types. */
|
||||
for ( ; ; ) {
|
||||
struct port_in_type *elem;
|
||||
|
||||
elem = TAILQ_FIRST(&p->port_in_types);
|
||||
if (!elem)
|
||||
break;
|
||||
|
||||
TAILQ_REMOVE(&p->port_in_types, elem, node);
|
||||
free(elem);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Pipeline.
|
||||
@ -44,6 +237,9 @@ rte_swx_pipeline_config(struct rte_swx_pipeline **p, int numa_node)
|
||||
CHECK(pipeline, ENOMEM);
|
||||
|
||||
/* Initialization. */
|
||||
TAILQ_INIT(&pipeline->port_in_types);
|
||||
TAILQ_INIT(&pipeline->ports_in);
|
||||
|
||||
pipeline->numa_node = numa_node;
|
||||
|
||||
*p = pipeline;
|
||||
@ -56,15 +252,28 @@ rte_swx_pipeline_free(struct rte_swx_pipeline *p)
|
||||
if (!p)
|
||||
return;
|
||||
|
||||
port_in_free(p);
|
||||
|
||||
free(p);
|
||||
}
|
||||
|
||||
int
|
||||
rte_swx_pipeline_build(struct rte_swx_pipeline *p)
|
||||
{
|
||||
int status;
|
||||
|
||||
CHECK(p, EINVAL);
|
||||
CHECK(p->build_done == 0, EEXIST);
|
||||
|
||||
status = port_in_build(p);
|
||||
if (status)
|
||||
goto error;
|
||||
|
||||
p->build_done = 1;
|
||||
return 0;
|
||||
|
||||
error:
|
||||
port_in_build_free(p);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
@ -18,6 +18,12 @@ extern "C" {
|
||||
|
||||
#include <rte_compat.h>
|
||||
|
||||
#include "rte_swx_port.h"
|
||||
|
||||
/** Name size. */
|
||||
#ifndef RTE_SWX_NAME_SIZE
|
||||
#define RTE_SWX_NAME_SIZE 64
|
||||
#endif
|
||||
/*
|
||||
* Pipeline setup and operation
|
||||
*/
|
||||
@ -43,6 +49,54 @@ int
|
||||
rte_swx_pipeline_config(struct rte_swx_pipeline **p,
|
||||
int numa_node);
|
||||
|
||||
/*
|
||||
* Pipeline input ports
|
||||
*/
|
||||
|
||||
/**
|
||||
* Pipeline input port type register
|
||||
*
|
||||
* @param[in] p
|
||||
* Pipeline handle.
|
||||
* @param[in] name
|
||||
* Input port type name.
|
||||
* @param[in] ops
|
||||
* Input port type operations.
|
||||
* @return
|
||||
* 0 on success or the following error codes otherwise:
|
||||
* -EINVAL: Invalid argument;
|
||||
* -ENOMEM: Not enough space/cannot allocate memory;
|
||||
* -EEXIST: Input port type with this name already exists.
|
||||
*/
|
||||
__rte_experimental
|
||||
int
|
||||
rte_swx_pipeline_port_in_type_register(struct rte_swx_pipeline *p,
|
||||
const char *name,
|
||||
struct rte_swx_port_in_ops *ops);
|
||||
|
||||
/**
|
||||
* Pipeline input port configure
|
||||
*
|
||||
* @param[in] p
|
||||
* Pipeline handle.
|
||||
* @param[in] port_id
|
||||
* Input port ID.
|
||||
* @param[in] port_type_name
|
||||
* Existing input port type name.
|
||||
* @param[in] args
|
||||
* Input port creation arguments.
|
||||
* @return
|
||||
* 0 on success or the following error codes otherwise:
|
||||
* -EINVAL: Invalid argument;
|
||||
* -ENOMEM: Not enough space/cannot allocate memory;
|
||||
* -ENODEV: Input port object creation error.
|
||||
*/
|
||||
__rte_experimental
|
||||
int
|
||||
rte_swx_pipeline_port_in_config(struct rte_swx_pipeline *p,
|
||||
uint32_t port_id,
|
||||
const char *port_type_name,
|
||||
void *args);
|
||||
/**
|
||||
* Pipeline build
|
||||
*
|
||||
|
@ -21,7 +21,8 @@ headers = files(
|
||||
'rte_port_sched.h',
|
||||
'rte_port_source_sink.h',
|
||||
'rte_port_sym_crypto.h',
|
||||
'rte_port_eventdev.h')
|
||||
'rte_port_eventdev.h',
|
||||
'rte_swx_port.h',)
|
||||
deps += ['ethdev', 'sched', 'ip_frag', 'cryptodev', 'eventdev']
|
||||
|
||||
if dpdk_conf.has('RTE_PORT_PCAP')
|
||||
|
118
lib/librte_port/rte_swx_port.h
Normal file
118
lib/librte_port/rte_swx_port.h
Normal file
@ -0,0 +1,118 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause
|
||||
* Copyright(c) 2020 Intel Corporation
|
||||
*/
|
||||
#ifndef __INCLUDE_RTE_SWX_PORT_H__
|
||||
#define __INCLUDE_RTE_SWX_PORT_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @file
|
||||
* RTE SWX Port
|
||||
*
|
||||
* Packet I/O port interface.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/** Packet. */
|
||||
struct rte_swx_pkt {
|
||||
/** Opaque packet handle. */
|
||||
void *handle;
|
||||
|
||||
/** Buffer where the packet is stored. */
|
||||
uint8_t *pkt;
|
||||
|
||||
/** Packet buffer offset of the first packet byte. */
|
||||
uint32_t offset;
|
||||
|
||||
/** Packet length in bytes. */
|
||||
uint32_t length;
|
||||
};
|
||||
|
||||
/*
|
||||
* Input port
|
||||
*/
|
||||
|
||||
/**
|
||||
* Input port create
|
||||
*
|
||||
* @param[in] args
|
||||
* Arguments for input port creation. Format specific to each port type.
|
||||
* @return
|
||||
* Handle to input port instance on success, NULL on error.
|
||||
*/
|
||||
typedef void *
|
||||
(*rte_swx_port_in_create_t)(void *args);
|
||||
|
||||
/**
|
||||
* Input port free
|
||||
*
|
||||
* @param[in] args
|
||||
* Input port handle.
|
||||
*/
|
||||
typedef void
|
||||
(*rte_swx_port_in_free_t)(void *port);
|
||||
|
||||
/**
|
||||
* Input port packet receive
|
||||
*
|
||||
* @param[in] port
|
||||
* Input port handle.
|
||||
* @param[out] pkt
|
||||
* Received packet. Only valid when the function returns 1. Must point to
|
||||
* valid memory.
|
||||
* @return
|
||||
* 0 when no packet was received, 1 when a packet was received. No other
|
||||
* return values are allowed.
|
||||
*/
|
||||
typedef int
|
||||
(*rte_swx_port_in_pkt_rx_t)(void *port,
|
||||
struct rte_swx_pkt *pkt);
|
||||
|
||||
/** Input port statistics counters. */
|
||||
struct rte_swx_port_in_stats {
|
||||
/** Number of packets. */
|
||||
uint64_t n_pkts;
|
||||
|
||||
/** Number of bytes. */
|
||||
uint64_t n_bytes;
|
||||
|
||||
/** Number of empty polls. */
|
||||
uint64_t n_empty;
|
||||
};
|
||||
|
||||
/**
|
||||
* Input port statistics counters read
|
||||
*
|
||||
* @param[in] port
|
||||
* Input port handle.
|
||||
* @param[out] stats
|
||||
* Input port statistics counters. Must point to valid memory.
|
||||
*/
|
||||
typedef void
|
||||
(*rte_swx_port_in_stats_read_t)(void *port,
|
||||
struct rte_swx_port_in_stats *stats);
|
||||
|
||||
/** Input port operations. */
|
||||
struct rte_swx_port_in_ops {
|
||||
/** Create. Must be non-NULL. */
|
||||
rte_swx_port_in_create_t create;
|
||||
|
||||
/** Free. Must be non-NULL. */
|
||||
rte_swx_port_in_free_t free;
|
||||
|
||||
/** Packet reception. Must be non-NULL. */
|
||||
rte_swx_port_in_pkt_rx_t pkt_rx;
|
||||
|
||||
/** Statistics counters read. Must be non-NULL. */
|
||||
rte_swx_port_in_stats_read_t stats_read;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user