port: add ethernet device SWX port
Add the Ethernet device input/output port type for the SWX pipeline. Used under the hood by the pipeline rx and tx instructions. Signed-off-by: Cristian Dumitrescu <cristian.dumitrescu@intel.com>
This commit is contained in:
parent
3ca60ceed7
commit
ecc5f43396
@ -171,7 +171,8 @@ The public API headers are grouped by topics:
|
||||
[extern] (@ref rte_swx_extern.h),
|
||||
[pipeline] (@ref rte_swx_pipeline.h)
|
||||
* SWX port:
|
||||
[port] (@ref rte_swx_port.h)
|
||||
[port] (@ref rte_swx_port.h),
|
||||
[ethdev] (@ref rte_swx_port_ethdev.h)
|
||||
* SWX table:
|
||||
[table] (@ref rte_swx_table.h)
|
||||
* [graph] (@ref rte_graph.h):
|
||||
|
@ -10,7 +10,8 @@ sources = files(
|
||||
'rte_port_sched.c',
|
||||
'rte_port_source_sink.c',
|
||||
'rte_port_sym_crypto.c',
|
||||
'rte_port_eventdev.c')
|
||||
'rte_port_eventdev.c',
|
||||
'rte_swx_port_ethdev.c',)
|
||||
headers = files(
|
||||
'rte_port_ethdev.h',
|
||||
'rte_port_fd.h',
|
||||
@ -22,7 +23,8 @@ headers = files(
|
||||
'rte_port_source_sink.h',
|
||||
'rte_port_sym_crypto.h',
|
||||
'rte_port_eventdev.h',
|
||||
'rte_swx_port.h',)
|
||||
'rte_swx_port.h',
|
||||
'rte_swx_port_ethdev.h',)
|
||||
deps += ['ethdev', 'sched', 'ip_frag', 'cryptodev', 'eventdev']
|
||||
|
||||
if dpdk_conf.has('RTE_PORT_PCAP')
|
||||
|
@ -34,8 +34,12 @@ DPDK_21 {
|
||||
EXPERIMENTAL {
|
||||
global:
|
||||
|
||||
# added in 19.11
|
||||
rte_port_eventdev_reader_ops;
|
||||
rte_port_eventdev_writer_ops;
|
||||
rte_port_eventdev_writer_nodrop_ops;
|
||||
rte_port_eventdev_writer_ops;
|
||||
|
||||
# added in 20.11
|
||||
rte_swx_port_ethdev_reader_ops;
|
||||
rte_swx_port_ethdev_writer_ops;
|
||||
};
|
||||
|
313
lib/librte_port/rte_swx_port_ethdev.c
Normal file
313
lib/librte_port/rte_swx_port_ethdev.c
Normal file
@ -0,0 +1,313 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause
|
||||
* Copyright(c) 2020 Intel Corporation
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <rte_mbuf.h>
|
||||
#include <rte_ethdev.h>
|
||||
#include <rte_hexdump.h>
|
||||
|
||||
#include "rte_swx_port_ethdev.h"
|
||||
|
||||
#define CHECK(condition) \
|
||||
do { \
|
||||
if (!(condition)) \
|
||||
return NULL; \
|
||||
} while (0)
|
||||
|
||||
#ifndef TRACE_LEVEL
|
||||
#define TRACE_LEVEL 0
|
||||
#endif
|
||||
|
||||
#if TRACE_LEVEL
|
||||
#define TRACE(...) printf(__VA_ARGS__)
|
||||
#else
|
||||
#define TRACE(...)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Port ETHDEV Reader
|
||||
*/
|
||||
struct reader {
|
||||
struct {
|
||||
uint16_t port_id;
|
||||
uint16_t queue_id;
|
||||
uint32_t burst_size;
|
||||
} params;
|
||||
struct rte_swx_port_in_stats stats;
|
||||
struct rte_mbuf **pkts;
|
||||
int n_pkts;
|
||||
int pos;
|
||||
};
|
||||
|
||||
static void *
|
||||
reader_create(void *args)
|
||||
{
|
||||
struct rte_eth_dev_info info;
|
||||
struct rte_swx_port_ethdev_reader_params *params = args;
|
||||
struct reader *p;
|
||||
int status;
|
||||
uint16_t port_id;
|
||||
|
||||
/* Check input parameters. */
|
||||
CHECK(params);
|
||||
|
||||
CHECK(params->dev_name);
|
||||
status = rte_eth_dev_get_port_by_name(params->dev_name, &port_id);
|
||||
CHECK(!status);
|
||||
|
||||
status = rte_eth_dev_info_get(port_id, &info);
|
||||
CHECK((status == -ENOTSUP) || (params->queue_id < info.nb_rx_queues));
|
||||
|
||||
CHECK(params->burst_size);
|
||||
|
||||
/* Memory allocation. */
|
||||
p = calloc(1, sizeof(struct reader));
|
||||
CHECK(p);
|
||||
|
||||
p->pkts = calloc(params->burst_size, sizeof(struct rte_mbuf *));
|
||||
if (!p->pkts) {
|
||||
free(p);
|
||||
CHECK(0);
|
||||
}
|
||||
|
||||
/* Initialization. */
|
||||
p->params.port_id = port_id;
|
||||
p->params.queue_id = params->queue_id;
|
||||
p->params.burst_size = params->burst_size;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static int
|
||||
reader_pkt_rx(void *port, struct rte_swx_pkt *pkt)
|
||||
{
|
||||
struct reader *p = port;
|
||||
struct rte_mbuf *m;
|
||||
|
||||
if (p->pos == p->n_pkts) {
|
||||
int n_pkts;
|
||||
|
||||
n_pkts = rte_eth_rx_burst(p->params.port_id,
|
||||
p->params.queue_id,
|
||||
p->pkts,
|
||||
p->params.burst_size);
|
||||
if (!n_pkts) {
|
||||
p->stats.n_empty++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
TRACE("[Ethdev RX port %u queue %u] %d packets in\n",
|
||||
(uint32_t)p->params.port_id,
|
||||
(uint32_t)p->params.queue_id,
|
||||
n_pkts);
|
||||
|
||||
p->n_pkts = n_pkts;
|
||||
p->pos = 0;
|
||||
}
|
||||
|
||||
m = p->pkts[p->pos++];
|
||||
pkt->handle = m;
|
||||
pkt->pkt = m->buf_addr;
|
||||
pkt->offset = m->data_off;
|
||||
pkt->length = m->pkt_len;
|
||||
|
||||
TRACE("[Ethdev RX port %u queue %u] Pkt %d (%u bytes at offset %u)\n",
|
||||
(uint32_t)p->params.port_id,
|
||||
(uint32_t)p->params.queue_id,
|
||||
p->pos - 1,
|
||||
pkt->length,
|
||||
pkt->offset);
|
||||
if (TRACE_LEVEL)
|
||||
rte_hexdump(stdout,
|
||||
NULL,
|
||||
&((uint8_t *)m->buf_addr)[m->data_off],
|
||||
m->data_len);
|
||||
|
||||
p->stats.n_pkts++;
|
||||
p->stats.n_bytes += pkt->length;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
reader_free(void *port)
|
||||
{
|
||||
struct reader *p = port;
|
||||
int i;
|
||||
|
||||
if (!p)
|
||||
return;
|
||||
|
||||
for (i = 0; i < p->n_pkts; i++) {
|
||||
struct rte_mbuf *pkt = p->pkts[i];
|
||||
|
||||
rte_pktmbuf_free(pkt);
|
||||
}
|
||||
|
||||
free(p->pkts);
|
||||
free(p);
|
||||
}
|
||||
|
||||
static void
|
||||
reader_stats_read(void *port, struct rte_swx_port_in_stats *stats)
|
||||
{
|
||||
struct reader *p = port;
|
||||
|
||||
memcpy(stats, &p->stats, sizeof(p->stats));
|
||||
}
|
||||
|
||||
/*
|
||||
* Port ETHDEV Writer
|
||||
*/
|
||||
struct writer {
|
||||
struct {
|
||||
uint16_t port_id;
|
||||
uint16_t queue_id;
|
||||
uint32_t burst_size;
|
||||
} params;
|
||||
struct rte_swx_port_out_stats stats;
|
||||
|
||||
struct rte_mbuf **pkts;
|
||||
int n_pkts;
|
||||
};
|
||||
|
||||
static void *
|
||||
writer_create(void *args)
|
||||
{
|
||||
struct rte_eth_dev_info info;
|
||||
struct rte_swx_port_ethdev_writer_params *params = args;
|
||||
struct writer *p;
|
||||
int status;
|
||||
uint16_t port_id;
|
||||
|
||||
/* Check input parameters. */
|
||||
CHECK(params);
|
||||
|
||||
CHECK(params->dev_name);
|
||||
status = rte_eth_dev_get_port_by_name(params->dev_name, &port_id);
|
||||
CHECK(!status);
|
||||
|
||||
status = rte_eth_dev_info_get(port_id, &info);
|
||||
CHECK((status == -ENOTSUP) || (params->queue_id < info.nb_tx_queues));
|
||||
|
||||
CHECK(params->burst_size);
|
||||
|
||||
/* Memory allocation. */
|
||||
p = calloc(1, sizeof(struct writer));
|
||||
CHECK(p);
|
||||
|
||||
p->pkts = calloc(params->burst_size, sizeof(struct rte_mbuf *));
|
||||
if (!p->pkts) {
|
||||
free(p);
|
||||
CHECK(0);
|
||||
}
|
||||
|
||||
/* Initialization. */
|
||||
p->params.port_id = port_id;
|
||||
p->params.queue_id = params->queue_id;
|
||||
p->params.burst_size = params->burst_size;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
static void
|
||||
__writer_flush(struct writer *p)
|
||||
{
|
||||
int n_pkts;
|
||||
|
||||
for (n_pkts = 0; ; ) {
|
||||
n_pkts += rte_eth_tx_burst(p->params.port_id,
|
||||
p->params.queue_id,
|
||||
p->pkts + n_pkts,
|
||||
p->n_pkts - n_pkts);
|
||||
|
||||
TRACE("[Ethdev TX port %u queue %u] %d packets out\n",
|
||||
(uint32_t)p->params.port_id,
|
||||
(uint32_t)p->params.queue_id,
|
||||
n_pkts);
|
||||
|
||||
if (n_pkts == p->n_pkts)
|
||||
break;
|
||||
}
|
||||
|
||||
p->n_pkts = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
writer_pkt_tx(void *port, struct rte_swx_pkt *pkt)
|
||||
{
|
||||
struct writer *p = port;
|
||||
struct rte_mbuf *m = pkt->handle;
|
||||
|
||||
TRACE("[Ethdev TX port %u queue %u] Pkt %d (%u bytes at offset %u)\n",
|
||||
(uint32_t)p->params.port_id,
|
||||
(uint32_t)p->params.queue_id,
|
||||
p->n_pkts - 1,
|
||||
pkt->length,
|
||||
pkt->offset);
|
||||
if (TRACE_LEVEL)
|
||||
rte_hexdump(stdout, NULL, &pkt->pkt[pkt->offset], pkt->length);
|
||||
|
||||
m->pkt_len = pkt->length;
|
||||
m->data_len = (uint16_t)pkt->length;
|
||||
m->data_off = (uint16_t)pkt->offset;
|
||||
|
||||
p->stats.n_pkts++;
|
||||
p->stats.n_bytes += pkt->length;
|
||||
|
||||
p->pkts[p->n_pkts++] = m;
|
||||
if (p->n_pkts == (int)p->params.burst_size)
|
||||
__writer_flush(p);
|
||||
}
|
||||
|
||||
static void
|
||||
writer_flush(void *port)
|
||||
{
|
||||
struct writer *p = port;
|
||||
|
||||
if (p->n_pkts)
|
||||
__writer_flush(p);
|
||||
}
|
||||
|
||||
static void
|
||||
writer_free(void *port)
|
||||
{
|
||||
struct writer *p = port;
|
||||
|
||||
if (!p)
|
||||
return;
|
||||
|
||||
writer_flush(p);
|
||||
free(p->pkts);
|
||||
free(port);
|
||||
}
|
||||
|
||||
static void
|
||||
writer_stats_read(void *port, struct rte_swx_port_out_stats *stats)
|
||||
{
|
||||
struct writer *p = port;
|
||||
|
||||
memcpy(stats, &p->stats, sizeof(p->stats));
|
||||
}
|
||||
|
||||
/*
|
||||
* Summary of port operations
|
||||
*/
|
||||
struct rte_swx_port_in_ops rte_swx_port_ethdev_reader_ops = {
|
||||
.create = reader_create,
|
||||
.free = reader_free,
|
||||
.pkt_rx = reader_pkt_rx,
|
||||
.stats_read = reader_stats_read,
|
||||
};
|
||||
|
||||
struct rte_swx_port_out_ops rte_swx_port_ethdev_writer_ops = {
|
||||
.create = writer_create,
|
||||
.free = writer_free,
|
||||
.pkt_tx = writer_pkt_tx,
|
||||
.flush = writer_flush,
|
||||
.stats_read = writer_stats_read,
|
||||
};
|
54
lib/librte_port/rte_swx_port_ethdev.h
Normal file
54
lib/librte_port/rte_swx_port_ethdev.h
Normal file
@ -0,0 +1,54 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause
|
||||
* Copyright(c) 2020 Intel Corporation
|
||||
*/
|
||||
#ifndef __INCLUDE_RTE_SWX_PORT_ETHDEV_H__
|
||||
#define __INCLUDE_RTE_SWX_PORT_ETHDEV_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @file
|
||||
* RTE SWX Ethernet Device Input and Output Ports
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "rte_swx_port.h"
|
||||
|
||||
/** Ethernet device input port (reader) creation parameters. */
|
||||
struct rte_swx_port_ethdev_reader_params {
|
||||
/** Name of a valid and fully configured Ethernet device. */
|
||||
const char *dev_name;
|
||||
|
||||
/** Ethernet device receive queue ID. */
|
||||
uint16_t queue_id;
|
||||
|
||||
/** Ethernet device receive burst size. */
|
||||
uint32_t burst_size;
|
||||
};
|
||||
|
||||
/** Ethernet device reader operations. */
|
||||
extern struct rte_swx_port_in_ops rte_swx_port_ethdev_reader_ops;
|
||||
|
||||
/** Ethernet device output port (writer) creation parameters. */
|
||||
struct rte_swx_port_ethdev_writer_params {
|
||||
/** Name of a valid and fully configured Ethernet device. */
|
||||
const char *dev_name;
|
||||
|
||||
/** Ethernet device transmit queue ID. */
|
||||
uint16_t queue_id;
|
||||
|
||||
/** Ethernet device transmit burst size. */
|
||||
uint32_t burst_size;
|
||||
};
|
||||
|
||||
/** Ethernet device writer operations. */
|
||||
extern struct rte_swx_port_out_ops rte_swx_port_ethdev_writer_ops;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user