Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 52 additions & 34 deletions doc/guides/prog_guide/xskdev_buffer_mgmt.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,37 +38,39 @@ ones own RX/TX function is also available should one prefer to provide their own

.. code-block:: C

typedef int (*buf_alloc_t)(void *arg, void **bufs, uint16_t nb_pkts);
typedef void (*buf_free_t)(void **bufs, uint16_t nb_pkts);
typedef void (*buf_set_len_t)(void *buf, int len);
typedef void (*buf_set_data_len_t)(void *buf, int len);
typedef void (*buf_set_data_t)(void *buf, uint64_t off);
typedef void **(*buf_inc_ptr_t)(void **buf);
typedef uint16_t (*buf_get_len_t)(void *buf);
typedef uint16_t (*buf_get_data_len_t)(void *buf);
typedef uint64_t (*buf_get_data_t)(void *buf);
typedef uint64_t (*buf_get_addr_t)(void *buf);
typedef uint16_t (*buf_rx_burst_t)(void *arg, void **bufs, uint16_t nb_pkts);
typedef uint16_t (*buf_tx_burst_t)(void *arg, void **bufs, uint16_t nb_pkts);
typedef int (*buf_alloc_t)(xinfo_t *arg, mbuf_t **bufs, uint16_t nb_pkts);
typedef void (*buf_free_t)(xinfo_t *arg, mbuf_t **bufs, uint16_t nb_pkts);
typedef void (*buf_reset_t)(mbuf_t *buf, uint16_t buf_len, uint16_t headroom);
typedef void (*buf_set_len_t)(mbuf_t *buf, uint16_t len);
typedef void (*buf_set_data_len_t)(mbuf_t *buf, uint16_t len);
typedef void (*buf_set_data_off_t)(mbuf_t *buf, uint16_t off);
typedef void **(*buf_inc_ptr_t)(mbuf_t **buf);
typedef uint16_t (*buf_get_data_len_t)(mbuf_t *buf);
typedef uint16_t (*buf_get_data_off_t)(mbuf_t *buf);
typedef uint64_t (*buf_get_data_ptr_t)(mbuf_t *buf);
typedef uint64_t (*buf_get_base_ptr_t)(mbuf_t *buf);
typedef uint16_t (*buf_rx_burst_t)(xinfo_t *arg, mbuf_t **bufs, uint16_t nb_pkts);
typedef uint16_t (*buf_tx_burst_t)(xinfo_t *arg, mbuf_t **bufs, uint16_t nb_pkts);

typedef struct lport_buf_mgmt {
void *buf_arg; /**< Argument for the buffer mgmt routines */
buf_alloc_t buf_alloc; /**< Allocate buffer routine */
buf_free_t buf_free; /**< Free buffer routine */
buf_set_len_t buf_set_len; /**< Set buffer length routine */
buf_set_data_len_t buf_set_data_len; /**< Set buffer data length routine */
buf_set_data_t buf_set_data; /**< Set buffer data pointer routine*/
buf_get_len_t buf_get_len; /**< Get buffer length routine */
buf_get_data_len_t buf_get_data_len; /**< Get buffer data length routine */
buf_get_data_t buf_get_data; /**< Get buffer data pointer routine */
buf_get_addr_t buf_get_addr; /**< Get buffer base address routine */
buf_reset_t buf_reset; /**< Buffer reset function */
buf_set_len_t buf_set_len; /**< Set total buffer length routine */
buf_inc_ptr_t buf_inc_ptr; /**< Increment the buffer pointer */
uint32_t frame_size; /**< Frame size in umem */
size_t buf_headroom; /**< Buffer headroom size */
size_t pool_header_sz; /**< Pool header size for external buffer pool*/
void *buf_arg; /**< Argument for the buffer alloc/free routines */
buf_rx_burst_t buf_rx_burst; /**< RX burst callback */
buf_tx_burst_t buf_tx_burst; /**< TX burst callback */
bool unaligned_buff; /**< Unaligned buffer support */
buf_get_base_ptr_t buf_get_base_ptr; /**< Get buffer base address routine */
buf_set_data_len_t buf_set_data_len; /**< Set buffer data length routine */
buf_set_data_off_t buf_set_data_off; /**< Set buffer data offset routine */
buf_get_data_len_t buf_get_data_len; /**< Get buffer data length routine */
buf_get_data_off_t buf_get_data_off; /**< Get buffer data offset routine */
buf_get_data_ptr_t buf_get_data_ptr; /**< Get buffer data pointer address routine */
uint32_t frame_size; /**< Frame size in umem */
uint32_t buf_header_sz; /**< Buffer headroom size */
uint32_t pool_header_sz; /**< Pool header size for external buffer pool*/
uint32_t reserved; /**< Reserved space for alignment */
} lport_buf_mgmt_t;

These functions are set in the xskdev_info_t during the call to xskdev_socket_create()
Expand All @@ -85,10 +87,26 @@ These functions are shown below:
.. code-block:: C

if (c->flags & LPORT_USER_MANAGED_BUFFERS) {
if (!c->buf_mgmt.buf_arg || !c->buf_mgmt.buf_alloc || !c->buf_mgmt.buf_free ||
!c->buf_mgmt.buf_set_len || !c->buf_mgmt.buf_set_data || !c->buf_mgmt.buf_get_len ||
!c->buf_mgmt.buf_get_data || c->buf_mgmt.buf_headroom == 0 || !c->buf_mgmt.buf_get_addr)
CNE_ERR_GOTO(err, "Buffer alloc/free pointers are not set\n");
if (!c->buf_mgmt.buf_arg || !c->buf_mgmt.buf_alloc || !c->buf_mgmt.buf_free)
CNE_ERR_GOTO(err, "Buffer management alloc/free/arg pointers are not set\n");

if (!c->buf_mgmt.buf_set_data_off || !c->buf_mgmt.buf_set_data_len)
CNE_ERR_GOTO(err, "Buffer management to set data len/offset are not set\n");

if (!c->buf_mgmt.buf_get_data_off || !c->buf_mgmt.buf_get_data_len)
CNE_ERR_GOTO(err, "Buffer management pointers to get data are not set\n");

if (!c->buf_mgmt.buf_reset || !c->buf_mgmt.buf_inc_ptr)
CNE_ERR_GOTO(err, "Buffer management pointers to reset/inc buffer are not set\n");

if (!c->buf_mgmt.buf_get_base_ptr)
CNE_ERR_GOTO(err, "Buffer management pointer to get buffer base address is not set\n");

if (c->buf_mgmt.frame_size == 0)
CNE_ERR_GOTO(err, "Buffer management invalid frame size\n");

if (c->buf_mgmt.buf_header_sz == 0)
CNE_ERR_GOTO(err, "Buffer management invalid headroom size\n");

xskdev_buf_set_buf_mgmt_ops(&xi->buf_mgmt, &c->buf_mgmt);
} else {
Expand All @@ -97,15 +115,16 @@ These functions are shown below:
xi->buf_mgmt.buf_free = xskdev_buf_free_default;
xi->buf_mgmt.buf_set_len = xskdev_buf_set_len_default;
xi->buf_mgmt.buf_set_data_len = xskdev_buf_set_data_len_default;
xi->buf_mgmt.buf_set_data = xskdev_buf_set_data_default;
xi->buf_mgmt.buf_set_data_off = xskdev_buf_set_data_off_default;
xi->buf_mgmt.buf_get_data_len = xskdev_buf_get_data_len_default;
xi->buf_mgmt.buf_get_len = xskdev_buf_get_len_default;
xi->buf_mgmt.buf_get_data = xskdev_buf_get_data_default;
xi->buf_mgmt.buf_get_data_off = xskdev_buf_get_data_off_default;
xi->buf_mgmt.buf_get_data_ptr = xskdev_buf_get_data_ptr_default;
xi->buf_mgmt.buf_inc_ptr = xskdev_buf_inc_ptr_default;
xi->buf_mgmt.buf_headroom = sizeof(pktmbuf_t);
xi->buf_mgmt.buf_get_addr = xskdev_buf_get_addr_default;
xi->buf_mgmt.buf_get_base_ptr = xskdev_buf_get_base_ptr_default;
xi->buf_mgmt.buf_reset = xskdev_buf_reset_default;
xi->buf_mgmt.frame_size = c->bufsz;
xi->buf_mgmt.pool_header_sz = 0;
xi->buf_mgmt.buf_header_sz = sizeof(pktmbuf_t);
}

.. note::
Expand All @@ -130,7 +149,6 @@ support of an unaligned memory model.
xi->__pull_cq_addr = __pull_cq_addr_aligned;
xi->__get_mbuf_rx = __get_mbuf_rx_aligned;
} else {
xi->buf_mgmt.unaligned_buff = true;
xi->__get_mbuf_addr_tx = __get_mbuf_addr_tx_unaligned;
xi->__pull_cq_addr = __pull_cq_addr_unaligned;
xi->__get_mbuf_rx = __get_mbuf_rx_unaligned;
Expand Down
120 changes: 95 additions & 25 deletions examples/cndpfwd/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,12 @@
#include <cne_log.h> // for CNE_LOG_ERR, CNE_ERR, CNE_DEBUG, CNE_LOG_DEBUG
#include <metrics.h> // for metrics_destroy
#include <cne_system.h> // for cne_lcore_id
#include <jcfg.h> // for jcfg_thd_t, jcfg_lport_t, jcfg_lport_by_index
#include <net/cne_ether.h>
#include <net/cne_ip.h>
#include <net/cne_udp.h>
#include <jcfg.h> // for jcfg_thd_t, jcfg_lport_t, jcfg_lport_by_index
#include <idlemgr.h>
#include <netdev_funcs.h> // for netdev_get_mac_addr

#include "main.h"

Expand All @@ -27,19 +31,70 @@ static struct fwd_info *fwd = &fwd_info;
#define foreach_thd_lport(_t, _lp) \
for (int _i = 0; _i < _t->lport_cnt && (_lp = _t->lports[_i]); _i++, _lp = _t->lports[_i])

#define TIMEOUT_VALUE 1000 /* Number of times to wait for each usleep() time */
#define TIMEOUT_1MS 1000 /* Number of microseconds for timeout */

enum thread_quit_state {
THD_RUN = 0, /**< Thread should continue running */
THD_QUIT, /**< Thread should stop itself */
THD_DONE, /**< Thread should set this state when done */
};

static uint8_t frame_data[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45,
0x00, 0x00, 0x2e, 0x60, 0xac, 0x00, 0x00, 0x40, 0x11, 0x8c, 0xec, 0xc6, 0x12, 0x00, 0x01,
0xc6, 0x12, 0x01, 0x01, 0x04, 0xd2, 0x16, 0x2e, 0x00, 0x1a, 0x00, 0x00, 0x6b, 0x6c, 0x6d,
0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x30, 0x31};
/* use RFC863 Discard Protocol */
uint16_t tx_udp_src_port = 9;
uint16_t tx_udp_dst_port = 9;

/* use RFC5735 / RFC2544 reserved network test addresses */
uint32_t tx_ip_src_addr = (198U << 24) | (18 << 16) | (0 << 8) | 1;
uint32_t tx_ip_dst_addr = (198U << 24) | (18 << 16) | (0 << 8) | 2;

#define IP_DEFTTL 64 /* from RFC 1340. */

static void
setup_pkt_udp_ip_headers(char *netdev, struct cne_ether_hdr *eth_hdr, struct cne_ipv4_hdr *ip_hdr,
struct cne_udp_hdr *udp_hdr, uint16_t pkt_data_len)
{
uint16_t pkt_len;

memset(eth_hdr, 0, sizeof(*eth_hdr));
memset(ip_hdr, 0, sizeof(*ip_hdr));
memset(udp_hdr, 0, sizeof(*udp_hdr));

int ret = netdev_get_mac_addr(netdev, &eth_hdr->s_addr);
if (ret)
CNE_ERR("netdev_get_mac_addr() failed\n");

memset(&eth_hdr->d_addr, 0xFF, ETH_ALEN);
eth_hdr->ether_type = htons(CNE_ETHER_TYPE_IPV4);

/*
* Initialize IP header.
*/
pkt_len = (uint16_t)(pkt_data_len - sizeof(struct cne_ether_hdr));
ip_hdr->version_ihl = CNE_IPV4_VHL_DEF;
ip_hdr->type_of_service = 0;
ip_hdr->fragment_offset = 0;
ip_hdr->time_to_live = IP_DEFTTL;
ip_hdr->next_proto_id = IPPROTO_UDP;
ip_hdr->packet_id = 0;
ip_hdr->total_length = htons(pkt_len);
ip_hdr->src_addr = htonl(tx_ip_src_addr);
ip_hdr->dst_addr = htonl(tx_ip_dst_addr);

/*
* Initialize UDP header.
*/
pkt_len =
(uint16_t)((pkt_data_len - sizeof(struct cne_ether_hdr) - sizeof(struct cne_ipv4_hdr)));
udp_hdr->src_port = htons(tx_udp_src_port);
udp_hdr->dst_port = htons(tx_udp_dst_port);
udp_hdr->dgram_len = htons(pkt_len);

/*
* Compute IP and UDP checksums.
*/
ip_hdr->hdr_checksum = cne_ipv4_cksum(ip_hdr);
udp_hdr->dgram_cksum = cne_ipv4_udptcp_cksum(ip_hdr, udp_hdr);
}

static __cne_always_inline int
__rx_burst(pkt_api_t api, struct fwd_port *pd, pktmbuf_t **mbufs, int n_pkts)
Expand Down Expand Up @@ -296,11 +351,22 @@ _txonly_test(jcfg_lport_t *lport, struct fwd_info *fwd)
n_pkts = __buf_alloc_bulk(fwd->pkt_api, lport, tx_mbufs, fwd->burst);

if (n_pkts > 0) {
if (!pd->pkt_built) {
setup_pkt_udp_ip_headers(lport->netdev, &pd->pkt_eth_hdr, &pd->pkt_ip_hdr,
&pd->pkt_udp_hdr, 60);
pd->pkt_built = true;
}

for (int j = 0; j < n_pkts; j++) {
pktmbuf_t *xb = tx_mbufs[j];
uint64_t *p = pktmbuf_mtod(xb, uint64_t *);
pktmbuf_t *xb = tx_mbufs[j];
struct cne_ether_hdr *eth = pktmbuf_mtod(xb, struct cne_ether_hdr *);
struct cne_ipv4_hdr *ip = (struct cne_ipv4_hdr *)&eth[1];
struct cne_udp_hdr *udp = (struct cne_udp_hdr *)&ip[1];

memcpy(eth, &pd->pkt_eth_hdr, sizeof(pd->pkt_eth_hdr));
memcpy(ip, &pd->pkt_ip_hdr, sizeof(pd->pkt_ip_hdr));
memcpy(udp, &pd->pkt_udp_hdr, sizeof(pd->pkt_udp_hdr));

memcpy(p, lport->frame_data, lport->frame_len);
pktmbuf_data_len(xb) = 60;
}

Expand Down Expand Up @@ -333,11 +399,22 @@ _txonly_rx_test(jcfg_lport_t *lport, struct fwd_info *fwd)
n_pkts = __buf_alloc_bulk(fwd->pkt_api, lport, tx_mbufs, fwd->burst);

if (n_pkts > 0) {
if (!pd->pkt_built) {
setup_pkt_udp_ip_headers(lport->netdev, &pd->pkt_eth_hdr, &pd->pkt_ip_hdr,
&pd->pkt_udp_hdr, 60);
pd->pkt_built = true;
}

for (int j = 0; j < n_pkts; j++) {
pktmbuf_t *xb = tx_mbufs[j];
uint64_t *p = pktmbuf_mtod(xb, uint64_t *);
pktmbuf_t *xb = tx_mbufs[j];
struct cne_ether_hdr *eth = pktmbuf_mtod(xb, struct cne_ether_hdr *);
struct cne_ipv4_hdr *ip = (struct cne_ipv4_hdr *)&eth[1];
struct cne_udp_hdr *udp = (struct cne_udp_hdr *)&ip[1];

memcpy(eth, &pd->pkt_eth_hdr, sizeof(pd->pkt_eth_hdr));
memcpy(ip, &pd->pkt_ip_hdr, sizeof(pd->pkt_ip_hdr));
memcpy(udp, &pd->pkt_udp_hdr, sizeof(pd->pkt_udp_hdr));

memcpy(p, lport->frame_data, lport->frame_len);
pktmbuf_data_len(xb) = 60;
}

Expand Down Expand Up @@ -521,22 +598,14 @@ thread_func(void *arg)
}
}

// Construct the transmit frame
foreach_thd_lport (thd, lport) {
lport->frame_len = sizeof(frame_data);
memcpy(lport->frame_data, frame_data, lport->frame_len);
memcpy(lport->frame_data, &fwd->dst_mac, ETH_ALEN);
memcpy(lport->frame_data + ETH_ALEN, &lport->mac_addr, ETH_ALEN);
}

for (;;) {
foreach_thd_lport (thd, lport) {
int n_pkts;

if (thd->quit == THD_QUIT) /* Make sure we check quit often to break out ASAP */
goto leave;
if (thd->pause) {
usleep(1000); // sleep for 1ms
usleep(TIMEOUT_1MS); // sleep for 1ms
continue;
}

Expand All @@ -559,7 +628,7 @@ thread_func(void *arg)
idlemgr_destroy(imgr);

while (thd->quit != THD_QUIT)
usleep(1000);
usleep(TIMEOUT_1MS);
// Free thread_func_arg_t.
free(func_arg);

Expand All @@ -575,6 +644,7 @@ _thread_quit(jcfg_info_t *j __cne_unused, void *obj, void *arg __cne_unused, int
jcfg_thd_t *thd = obj;

thd->quit = THD_QUIT;
usleep(TIMEOUT_1MS * 10);
return 0;
}

Expand Down Expand Up @@ -619,11 +689,11 @@ static int
_check_thread_quit(jcfg_info_t *j __cne_unused, void *obj, void *arg __cne_unused, int idx)
{
jcfg_thd_t *thd = obj;
uint32_t timo = TIMEOUT_VALUE;
uint32_t timo = 1000;

/* Make sure worker threads are done. Ignore main thread (idx=0) */
while (--timo && thd->quit != THD_DONE && idx > 0)
usleep(10000); /* 10ms */
usleep(10 * TIMEOUT_1MS); /* 10ms */

if (timo == 0)
return -1;
Expand Down
10 changes: 8 additions & 2 deletions examples/cndpfwd/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ extern "C" {
#include <jcfg.h> // for jcfg_info_t, jcfg_thd_t
#include <jcfg_process.h>

#include <net/cne_ip.h> // for CNE_IPV4
#include <net/cne_ether.h> // for cne_ether_hdr
#include <net/cne_ip.h> // for CNE_IPV4
#include <net/cne_udp.h> // for cne_udp_hdr

#include "metrics.h" // for metrics_info_t
#include "pktmbuf.h" // for pktmbuf_t
Expand All @@ -52,7 +54,7 @@ enum {
FWD_NO_METRICS = (1 << 1), /**< Disable the Metrics function */
FWD_NO_RESTAPI = (1 << 2), /**< Disable the REST API */
FWD_CLI_ENABLE = (1 << 3), /**< Enable the CLI */
FWD_ACL_STATS = (1 << 4), /**< Enable printing ACL stats */
FWD_ACL_STATS = (1 << 4) /**< Enable printing ACL stats */
};

#define PKT_API_TAG "pkt_api" /**< Packet API json tag */
Expand Down Expand Up @@ -128,6 +130,10 @@ struct fwd_port {
uint64_t tx_overrun; /**< Number of mbufs failing to flush */
struct acl_fwd_stats acl_stats; /**< ACL-related stats */
struct acl_fwd_stats prev_acl_stats; /**< previous values for ACL stats */
struct cne_ether_hdr pkt_eth_hdr; /**< Cached Ethernet header for TX-only mode */
struct cne_ipv4_hdr pkt_ip_hdr; /**< Cached IPv4 header for TX-only mode */
struct cne_udp_hdr pkt_udp_hdr; /**< Cached UDP header for TX-only mode */
bool pkt_built; /**< True once per-lport TX headers have been built */
};

struct app_options {
Expand Down
3 changes: 3 additions & 0 deletions examples/cndpfwd/parse-args.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,8 @@ process_callback(jcfg_info_t *j __cne_unused, void *_obj, void *arg, int idx)
cne_printf("[yellow]**** [green]SKB_MODE is [red]enabled[]\n");
if (lport->flags & LPORT_BUSY_POLLING)
cne_printf("[yellow]**** [green]BUSY_POLLING is [red]enabled[]\n");
if (lport->flags & LPORT_UMEM_UNALIGNED_BUFFERS)
cne_printf("[yellow]**** [green]UMEM_UNALIGNED_BUFFERS is [red]enabled[]\n");

pcfg.qid = lport->qid;
pcfg.bufsz = umem->bufsz;
Expand All @@ -189,6 +191,7 @@ process_callback(jcfg_info_t *j __cne_unused, void *_obj, void *arg, int idx)
pcfg.busy_budget = lport->busy_budget;
pcfg.flags = lport->flags;
pcfg.flags |= (umem->shared_umem == 1) ? LPORT_SHARED_UMEM : 0;
pcfg.buf_mgmt.pool_header_sz = sizeof(pktmbuf_t);

if (lport->xsk_map_path) {
cne_printf("[yellow]**** [green]PINNED_BPF_MAP is [red]enabled[]\n");
Expand Down
Loading
Loading