From d1fcbf56bd99e1ab189982201aa4bc84e1328021 Mon Sep 17 00:00:00 2001 From: Keith Wiles Date: Tue, 24 Feb 2026 09:06:14 -0600 Subject: [PATCH] Refactor buffer management and update configuration handling - Added support for unaligned buffers in the buffer management structure. - Renamed buffer management functions and updated their signatures to use mbuf_t for better type safety. - Updated the parsing of JSON configuration to include a new option for unaligned buffers. - Changed the handling of buffer sizes and headroom to improve clarity and consistency. - Modified the xskdev interface to accommodate the new buffer management structure and functions. - Improved error handling and logging for buffer management operations. - The uintr file needs '-mtls-dialect-gnu2' to build the uintr_handler.c file. Signed-off-by: Keith Wiles --- doc/guides/prog_guide/xskdev_buffer_mgmt.rst | 86 +++++--- examples/cndpfwd/main.c | 120 ++++++++--- examples/cndpfwd/main.h | 10 +- examples/cndpfwd/parse-args.c | 3 + examples/vpp-plugin/cndp/device.c | 30 ++- lib/core/pktmbuf/pktmbuf.h | 2 +- lib/core/xskdev/xskdev.c | 118 +++++----- lib/core/xskdev/xskdev.h | 215 ++++++++++--------- lib/include/cne_lport.h | 64 +++--- lib/usr/app/jcfg/jcfg.h | 29 +-- lib/usr/app/jcfg/jcfg_lport.c | 10 +- lib/usr/slib/ibroker/meson.build | 18 +- tools/cne-build.sh | 9 +- 13 files changed, 451 insertions(+), 263 deletions(-) diff --git a/doc/guides/prog_guide/xskdev_buffer_mgmt.rst b/doc/guides/prog_guide/xskdev_buffer_mgmt.rst index 324c903d..8aaf7bd2 100644 --- a/doc/guides/prog_guide/xskdev_buffer_mgmt.rst +++ b/doc/guides/prog_guide/xskdev_buffer_mgmt.rst @@ -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() @@ -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 { @@ -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:: @@ -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; diff --git a/examples/cndpfwd/main.c b/examples/cndpfwd/main.c index 351bbfd9..bc60837e 100644 --- a/examples/cndpfwd/main.c +++ b/examples/cndpfwd/main.c @@ -16,8 +16,12 @@ #include // for CNE_LOG_ERR, CNE_ERR, CNE_DEBUG, CNE_LOG_DEBUG #include // for metrics_destroy #include // for cne_lcore_id -#include // for jcfg_thd_t, jcfg_lport_t, jcfg_lport_by_index +#include +#include +#include +#include // for jcfg_thd_t, jcfg_lport_t, jcfg_lport_by_index #include +#include // for netdev_get_mac_addr #include "main.h" @@ -27,7 +31,7 @@ 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 */ @@ -35,11 +39,62 @@ enum thread_quit_state { 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, ð_hdr->s_addr); + if (ret) + CNE_ERR("netdev_get_mac_addr() failed\n"); + + memset(ð_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) @@ -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 *)ð[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; } @@ -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 *)ð[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; } @@ -521,14 +598,6 @@ 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; @@ -536,7 +605,7 @@ thread_func(void *arg) 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; } @@ -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); @@ -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; } @@ -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; diff --git a/examples/cndpfwd/main.h b/examples/cndpfwd/main.h index 6ebc49ee..2692e9fd 100644 --- a/examples/cndpfwd/main.h +++ b/examples/cndpfwd/main.h @@ -37,7 +37,9 @@ extern "C" { #include // for jcfg_info_t, jcfg_thd_t #include -#include // for CNE_IPV4 +#include // for cne_ether_hdr +#include // for CNE_IPV4 +#include // for cne_udp_hdr #include "metrics.h" // for metrics_info_t #include "pktmbuf.h" // for pktmbuf_t @@ -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 */ @@ -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 { diff --git a/examples/cndpfwd/parse-args.c b/examples/cndpfwd/parse-args.c index 79af594b..8658964f 100644 --- a/examples/cndpfwd/parse-args.c +++ b/examples/cndpfwd/parse-args.c @@ -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; @@ -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"); diff --git a/examples/vpp-plugin/cndp/device.c b/examples/vpp-plugin/cndp/device.c index ae0a2001..014bc21f 100644 --- a/examples/vpp-plugin/cndp/device.c +++ b/examples/vpp-plugin/cndp/device.c @@ -147,13 +147,34 @@ static inline uint16_t cndp_buf_get_data_len (void *mb) return b->current_length; } -static inline uint64_t cndp_buf_get_addr (void *mb) +static inline uint64_t cndp_buf_get_base_ptr (void *mb) { vlib_buffer_t *b = (vlib_buffer_t *)mb; return (pointer_to_uword (b)); } +static __cne_always_inline uint64_t cndp_buf_get_data_ptr (void *mb) +{ + vlib_buffer_t *b = (vlib_buffer_t *)mb; + + return (pointer_to_uword (b) + b->current_data); +} + +static __cne_always_inline void cndp_buf_set_data_off (void *mb, uint32_t off) +{ + vlib_buffer_t *b = (vlib_buffer_t *)mb; + + b->current_data = off; +} + +static __cne_always_inline uint32_t cndp_buf_get_data_off (void *mb) +{ + vlib_buffer_t *b = (vlib_buffer_t *)mb; + + return b->current_data; +} + static __cne_always_inline void **cndp_buf_inc_ptr (void **mbs) { vlib_buffer_t **b = (vlib_buffer_t **)mbs; @@ -273,10 +294,13 @@ clib_error_t *cndp_create_dev (vlib_main_t *vm, u8 *ifname, u32 nb_qs, p_config->buf_mgmt.buf_set_data = cndp_buf_set_data; p_config->buf_mgmt.buf_get_data_len = cndp_buf_get_data_len; p_config->buf_mgmt.buf_get_data = cndp_buf_get_data; - p_config->buf_mgmt.buf_get_addr = cndp_buf_get_addr; + p_config->buf_mgmt.buf_get_base_ptr = cndp_buf_get_base_ptr; + p_config->buf_mgmt.buf_get_data_ptr = cndp_buf_get_data_ptr; + p_config->buf_mgmt.buf_set_data_off = cndp_buf_set_data_off; + p_config->buf_mgmt.buf_get_data_off = cndp_buf_get_data_off; p_config->buf_mgmt.buf_inc_ptr = cndp_buf_inc_ptr; p_config->buf_mgmt.buf_reset = cndp_buf_reset; - p_config->buf_mgmt.buf_headroom = sizeof (vlib_buffer_t); + p_config->buf_mgmt.buf_header_sz = sizeof (vlib_buffer_t); p_config->buf_mgmt.frame_size = p_config->bufsz; p_config->buf_mgmt.pool_header_sz = 0; diff --git a/lib/core/pktmbuf/pktmbuf.h b/lib/core/pktmbuf/pktmbuf.h index 162666c7..406afa31 100644 --- a/lib/core/pktmbuf/pktmbuf.h +++ b/lib/core/pktmbuf/pktmbuf.h @@ -824,7 +824,7 @@ pktmbuf_free_bulk(pktmbuf_t **mbufs, unsigned int count) * set of mbufs. The private data are is not copied. * * @param m - * The packet mbuf to be copiedd. + * The packet mbuf to be copied. * @param pi * The pktmbuf_info_t from which the "clone" mbufs are allocated. * @param offset diff --git a/lib/core/xskdev/xskdev.c b/lib/core/xskdev/xskdev.c index fec1dc72..28e12147 100644 --- a/lib/core/xskdev/xskdev.c +++ b/lib/core/xskdev/xskdev.c @@ -246,10 +246,10 @@ fq_add(xskdev_info_t *xi, int times) for (uint32_t i = 0; i < nb_bufs; i++) { void *buf = bufs[i]; - uint64_t offset = (uint64_t)xskdev_buf_get_addr(xi, buf) - (uint64_t)ux->umem_addr - + uint64_t offset = (uint64_t)xskdev_buf_get_data_ptr(xi, buf) - (uint64_t)ux->umem_addr - (uint64_t)xi->buf_mgmt.pool_header_sz; - xskdev_buf_reset(xi, buf, ux->obj_sz, xi->buf_mgmt.buf_headroom); + xskdev_buf_reset(xi, buf, ux->obj_sz, xi->buf_mgmt.buf_header_sz); *xsk_ring_prod__fill_addr(fq, pos++) = offset; } @@ -274,13 +274,13 @@ __get_mbuf_rx_unaligned(void *_xi, void *umem_addr, const struct xdp_desc *d, vo *bufs = (void *)xsk_umem__get_data(umem_addr, addr + xi->buf_mgmt.pool_header_sz); xskdev_buf_set_data_len(xi, *bufs, d->len); - xskdev_buf_set_data(xi, *bufs, offset - xi->buf_mgmt.buf_headroom); + xskdev_buf_set_data_off(xi, *bufs, offset - xi->buf_mgmt.buf_header_sz); return d->len; } static __cne_always_inline uint16_t -__get_mbuf_rx_aligned(void *_xi, void *umem_addr, const struct xdp_desc *d, void **bufs) +__get_mbuf_rx_aligned(void *_xi, void *umem_addr, const struct xdp_desc *d, mbuf_t **bufs) { xskdev_info_t *xi = _xi; void *addr; @@ -294,7 +294,7 @@ __get_mbuf_rx_aligned(void *_xi, void *umem_addr, const struct xdp_desc *d, void *bufs = xsk_umem__get_data(umem_addr, (uint64_t)addr + xi->buf_mgmt.pool_header_sz); xskdev_buf_set_data_len(xi, *bufs, d->len); - xskdev_buf_set_data(xi, *bufs, offset - xi->buf_mgmt.buf_headroom); + xskdev_buf_set_data_off(xi, *bufs, offset - xi->buf_mgmt.buf_header_sz); return d->len; } @@ -396,18 +396,25 @@ kick_tx(xskdev_info_t *xi) static __cne_always_inline void * __pull_cq_addr_unaligned(uint64_t addr, uint64_t umem_addr, __cne_unused uint64_t mask, - uint64_t pool_header_sz) + uint32_t pool_header_sz) { - return (void *)(umem_addr + xsk_umem__extract_addr(addr) + pool_header_sz); + void *buf = NULL; + + buf = (void *)(umem_addr + xsk_umem__extract_addr(addr) + pool_header_sz); + + return buf; } static __cne_always_inline void * -__pull_cq_addr_aligned(uint64_t addr, uint64_t umem_addr, uint64_t mask, - __cne_unused uint64_t pool_header_sz) +__pull_cq_addr_aligned(uint64_t addr, uint64_t umem_addr, uint64_t mask, uint32_t pool_header_sz) { + void *buf; + /* Trim off the lower bits of offset to get the mbuf offset in umem. * Add the offset to the umem start address to find the umem address. */ - return (void *)(umem_addr + (addr & mask) + pool_header_sz); + buf = (void *)(umem_addr + (addr & mask) + pool_header_sz); + + return buf; } static void @@ -430,10 +437,10 @@ pull_umem_cq(xskdev_info_t *xi) } for (uint32_t i = 0; i < n && i < mbuf_cnt; i++) { - uint64_t offset = *xsk_ring_cons__comp_addr(cq, idx_cq++); + uint64_t offset_addr = *xsk_ring_cons__comp_addr(cq, idx_cq++); - mbufs[i] = xi->__pull_cq_addr(offset, umem_addr, mask, xi->buf_mgmt.pool_header_sz); - xskdev_buf_reset(xi, mbufs[i], xi->rxq.ux->obj_sz, xi->buf_mgmt.buf_headroom); + mbufs[i] = xi->__pull_cq_addr(offset_addr, umem_addr, mask, xi->buf_mgmt.pool_header_sz); + xskdev_buf_reset(xi, mbufs[i], xi->rxq.ux->obj_sz, xi->buf_mgmt.buf_header_sz); } xsk_ring_cons__release(cq, n); @@ -447,15 +454,17 @@ static __cne_always_inline uint64_t __get_mbuf_addr_tx_unaligned(void *_xi, void *mb, uint64_t umem_addr) { xskdev_info_t *xi = _xi; - uint64_t addr, offset; + uint64_t addr, offset, buf_addr, headroom; - addr = xskdev_buf_get_addr(xi, mb) - umem_addr - (uint64_t)xi->buf_mgmt.pool_header_sz; - addr = xsk_umem__extract_addr((uint64_t)addr); - offset = xskdev_buf_get_data(xi, mb) - xskdev_buf_get_addr(xi, mb) + - (uint64_t)xi->buf_mgmt.pool_header_sz; - offset = offset << XSK_UNALIGNED_BUF_OFFSET_SHIFT; + headroom = (uint64_t)(xi->buf_mgmt.buf_header_sz + xi->buf_mgmt.pool_header_sz); + buf_addr = xskdev_buf_get_base_ptr(xi, mb); + addr = (buf_addr - umem_addr) - headroom; + addr = xsk_umem__extract_addr((uint64_t)addr); + offset = (xskdev_buf_get_data_ptr(xi, mb) - buf_addr) + headroom; + offset = offset << XSK_UNALIGNED_BUF_OFFSET_SHIFT; + addr = addr | offset; - return addr | offset; + return addr; } static __cne_always_inline uint64_t @@ -463,8 +472,8 @@ __get_mbuf_addr_tx_aligned(void *_xi, void *mb, uint64_t umem_addr) { xskdev_info_t *xi = _xi; - return (xskdev_buf_get_addr(xi, mb) - umem_addr - xi->buf_mgmt.pool_header_sz) + - xskdev_buf_get_data(xi, mb); + return (xskdev_buf_get_base_ptr(xi, mb) - umem_addr - xskdev_buf_get_pool_hdr_sz(xi)) + + xskdev_buf_get_data_off(xi, mb); } static uint16_t @@ -545,7 +554,7 @@ umem_create(lport_cfg_t *cfg) umem_cfg.fill_size = (cfg->rx_nb_desc * 2); umem_cfg.comp_size = cfg->tx_nb_desc; umem_cfg.frame_size = cfg->bufsz; - umem_cfg.frame_headroom = cfg->buf_mgmt.buf_headroom; + umem_cfg.frame_headroom = (cfg->buf_mgmt.buf_header_sz + cfg->buf_mgmt.pool_header_sz); if (cfg->flags & LPORT_UMEM_UNALIGNED_BUFFERS) umem_cfg.flags = XDP_UMEM_UNALIGNED_CHUNK_FLAG; @@ -612,7 +621,7 @@ xskdev_recv_xsk_fd(xskdev_info_t *xi) } static __cne_always_inline int -xskdev_buf_alloc_default(void *arg, void **bufs, uint16_t nb_bufs) +xskdev_buf_alloc_default(void *arg, mbuf_t **bufs, uint16_t nb_bufs) { pktmbuf_info_t *pi = (pktmbuf_info_t *)arg; pktmbuf_t **mbs = (pktmbuf_t **)bufs; @@ -621,13 +630,13 @@ xskdev_buf_alloc_default(void *arg, void **bufs, uint16_t nb_bufs) } static __cne_always_inline void -xskdev_buf_free_default(__cne_unused void *arg, void **bufs, uint16_t nb_bufs) +xskdev_buf_free_default(__cne_unused void *arg, mbuf_t **bufs, uint16_t nb_bufs) { pktmbuf_free_bulk((pktmbuf_t **)bufs, nb_bufs); } static __cne_always_inline void -xskdev_buf_set_data_len_default(void *mb, int len) +xskdev_buf_set_data_len_default(mbuf_t *mb, uint16_t len) { pktmbuf_t *p = (pktmbuf_t *)mb; @@ -635,7 +644,7 @@ xskdev_buf_set_data_len_default(void *mb, int len) } static __cne_always_inline void -xskdev_buf_set_len_default(void *mb, int len) +xskdev_buf_set_len_default(mbuf_t *mb, uint16_t len) { pktmbuf_t *p = (pktmbuf_t *)mb; @@ -643,7 +652,7 @@ xskdev_buf_set_len_default(void *mb, int len) } static __cne_always_inline void -xskdev_buf_set_data_default(void *mb, uint64_t off) +xskdev_buf_set_data_off_default(mbuf_t *mb, uint16_t off) { pktmbuf_t *p = (pktmbuf_t *)mb; @@ -651,7 +660,7 @@ xskdev_buf_set_data_default(void *mb, uint64_t off) } static __cne_always_inline void -xskdev_buf_reset_default(void *mb, uint32_t buf_len, size_t headroom) +xskdev_buf_reset_default(mbuf_t *mb, uint16_t buf_len, uint16_t headroom) { /* Buffer reset of data is done in pktmbuf_alloc() */ CNE_SET_USED(mb); @@ -660,15 +669,15 @@ xskdev_buf_reset_default(void *mb, uint32_t buf_len, size_t headroom) } static __cne_always_inline uint16_t -xskdev_buf_get_data_len_default(void *mb) +xskdev_buf_get_data_len_default(mbuf_t *mb) { pktmbuf_t *p = (pktmbuf_t *)mb; return pktmbuf_data_len(p); } -static __cne_always_inline uint64_t -xskdev_buf_get_data_default(void *mb) +static __cne_always_inline uint16_t +xskdev_buf_get_data_off_default(mbuf_t *mb) { pktmbuf_t *p = (pktmbuf_t *)mb; @@ -676,7 +685,18 @@ xskdev_buf_get_data_default(void *mb) } static __cne_always_inline uint64_t -xskdev_buf_get_addr_default(void *mb) +xskdev_buf_get_data_ptr_default(mbuf_t *mb) +{ + pktmbuf_t *p = (pktmbuf_t *)mb; + uint64_t addr; + + addr = (uint64_t)CNE_PTR_ADD(pktmbuf_buf_addr(p), pktmbuf_data_off(p)); + + return addr; +} + +static __cne_always_inline uint64_t +xskdev_buf_get_base_ptr_default(mbuf_t *mb) { pktmbuf_t *p = (pktmbuf_t *)mb; @@ -684,7 +704,7 @@ xskdev_buf_get_addr_default(void *mb) } static __cne_always_inline void ** -xskdev_buf_inc_ptr_default(void **mb) +xskdev_buf_inc_ptr_default(mbuf_t **mb) { pktmbuf_t **p = (pktmbuf_t **)mb; @@ -762,22 +782,22 @@ xskdev_socket_create(struct lport_cfg *c) 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 || !c->buf_mgmt.buf_set_data_len) - CNE_ERR_GOTO(err, "Buffer management pointers to set data 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 || !c->buf_mgmt.buf_get_data_len) + 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 a are not set\n"); + CNE_ERR_GOTO(err, "Buffer management pointers to reset/inc buffer are not set\n"); - if (!c->buf_mgmt.buf_get_addr) - CNE_ERR_GOTO(err, "Buffer management pointers to get buffer addr is 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_headroom == 0) + 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); @@ -787,15 +807,16 @@ xskdev_socket_create(struct lport_cfg *c) 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_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); } if (!c->buf_mgmt.buf_rx_burst || !c->buf_mgmt.buf_tx_burst) { @@ -809,10 +830,9 @@ xskdev_socket_create(struct lport_cfg *c) 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; + 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; } umem = umem_create(c); diff --git a/lib/core/xskdev/xskdev.h b/lib/core/xskdev/xskdev.h index a67aa5f7..a50bf7c4 100644 --- a/lib/core/xskdev/xskdev.h +++ b/lib/core/xskdev/xskdev.h @@ -71,12 +71,12 @@ extern "C" { #endif typedef void *(*xskdev_pull_cq_addr_t)(uint64_t addr, uint64_t umem_addr, uint64_t mask, - uint64_t pool_header_sz); -typedef uint64_t (*xskdev_get_mbuf_addr_tx_t)(void *xi, void *mb, uint64_t umem_addr); + uint32_t pool_header_sz); +typedef uint64_t (*xskdev_get_mbuf_addr_tx_t)(void *xi, mbuf_t *mb, uint64_t umem_addr); typedef uint16_t (*xskdev_get_mbuf_t)(void *xi, void *umem_addr, const struct xdp_desc *d, - void *buf); + mbuf_t *buf); typedef uint16_t (*xskdev_get_mbuf_rx_t)(void *xi, void *umem_addr, const struct xdp_desc *d, - void **buf); + mbuf_t **buf); struct xskdev_umem { struct xsk_ring_prod fq; /**< The Fill Queue XSK structure */ @@ -152,42 +152,6 @@ CNDP_API xskdev_info_t *xskdev_socket_create(struct lport_cfg *c); */ CNDP_API void xskdev_socket_destroy(xskdev_info_t *xi); -/** - * Receive packets from the interface - * - * @param xi - * The void * type of xskdev_info_t structure - * @param bufs - * The list or vector or pktmbufs structures to send on the interface. - * @param nb_pkts - * The number of pktmbuf_t pointers in the list or vector bufs - * @return - * The number of packet sent to the interface or 0 if RX is empty. - */ -CNDP_API __cne_always_inline uint16_t -xskdev_rx_burst(xskdev_info_t *xi, void **bufs, uint16_t nb_pkts) -{ - return xi->buf_mgmt.buf_rx_burst(xi, bufs, nb_pkts); -} - -/** - * Send buffers to be transmitted - * - * @param xi - * The void * type of xskdev_info_t structure - * @param bufs - * The list or vector or pktmbufs structures to send on the interface. - * @param nb_pkts - * The number of pktmbuf_t pointers in the list or vector bufs - * @return - * The number of packet sent to the interface or 0 if RX is empty. - */ -CNDP_API __cne_always_inline uint16_t -xskdev_tx_burst(xskdev_info_t *xi, void **bufs, uint16_t nb_pkts) -{ - return xi->buf_mgmt.buf_tx_burst(xi, bufs, nb_pkts); -} - /** * Get the stats for the interface * @@ -256,6 +220,12 @@ xskdev_arg_get(xskdev_info_t *xi) return xi->buf_mgmt.buf_arg; } +CNDP_API __cne_always_inline uint32_t +xskdev_buf_get_pool_hdr_sz(xskdev_info_t *xi) +{ + return xi->buf_mgmt.pool_header_sz; +} + /** * Allocate the number of buffers requested. * @@ -269,7 +239,7 @@ xskdev_arg_get(xskdev_info_t *xi) * The number of bufs allocated in the bufs array. */ CNDP_API __cne_always_inline int -xskdev_buf_alloc(xskdev_info_t *xi, void **bufs, uint16_t nb_bufs) +xskdev_buf_alloc(xskdev_info_t *xi, mbuf_t **bufs, uint16_t nb_bufs) { return xi->buf_mgmt.buf_alloc(xskdev_arg_get(xi), bufs, nb_bufs); } @@ -285,11 +255,31 @@ xskdev_buf_alloc(xskdev_info_t *xi, void **bufs, uint16_t nb_bufs) * The max number of xbuf pointers to free in the array. */ CNDP_API __cne_always_inline void -xskdev_buf_free(xskdev_info_t *xi, void **bufs, uint16_t nb_bufs) +xskdev_buf_free(xskdev_info_t *xi, mbuf_t **bufs, uint16_t nb_bufs) { xi->buf_mgmt.buf_free(xskdev_arg_get(xi), bufs, nb_bufs); } +/** + * Reset a buffer. + * + * @param xi + * The pointer to the xskdev_info struct. + * @param buf + * The buffer to reset. + * @param buf_len + * The max data length able to be contained in the buffer. + * If the buffer is 2K and it contains a mbuf like header then + * buf_len = (2K - sizeof(mbuf)). + * @param headroom + * The buffer headroom to offset the data pointer by (if needed). + */ +CNDP_API __cne_always_inline void +xskdev_buf_reset(xskdev_info_t *xi, mbuf_t *buf, uint16_t buf_len, uint16_t headroom) +{ + xi->buf_mgmt.buf_reset(buf, buf_len, headroom); +} + /** * Set the buffer Length. * @@ -302,11 +292,77 @@ xskdev_buf_free(xskdev_info_t *xi, void **bufs, uint16_t nb_bufs) */ CNDP_API __cne_always_inline void -xskdev_buf_set_len(xskdev_info_t *xi, void *buf, int len) +xskdev_buf_set_len(xskdev_info_t *xi, mbuf_t *buf, uint16_t len) { xi->buf_mgmt.buf_set_len(buf, len); } +/** + * Increment the buffer array pointer + * + * @param xi + * The pointer to the xskdev_info struct. + * @param buf + * The buffer ptr to increment. + */ +CNDP_API __cne_always_inline void ** +xskdev_buf_inc_ptr(xskdev_info_t *xi, mbuf_t **buf) +{ + return xi->buf_mgmt.buf_inc_ptr(buf); +} + +/** + * Get the base address of the data buffer + * + * @param xi + * The pointer to the xskdev_info struct. + * @param buf + * The buffer to get the address of. + * @return + * The the base address of the data buffer + */ +CNDP_API __cne_always_inline uint64_t +xskdev_buf_get_base_ptr(xskdev_info_t *xi, mbuf_t *buf) +{ + return xi->buf_mgmt.buf_get_base_ptr(buf); +} + +/** + * Receive packets from the interface + * + * @param xi + * The void * type of xskdev_info_t structure + * @param bufs + * The list or vector or pktmbufs structures to send on the interface. + * @param nb_pkts + * The number of pktmbuf_t pointers in the list or vector bufs + * @return + * The number of packet sent to the interface or 0 if RX is empty. + */ +CNDP_API __cne_always_inline uint16_t +xskdev_rx_burst(xskdev_info_t *xi, mbuf_t **bufs, uint16_t nb_pkts) +{ + return xi->buf_mgmt.buf_rx_burst(xi, bufs, nb_pkts); +} + +/** + * Send buffers to be transmitted + * + * @param xi + * The void * type of xskdev_info_t structure + * @param bufs + * The list or vector or pktmbufs structures to send on the interface. + * @param nb_pkts + * The number of pktmbuf_t pointers in the list or vector bufs + * @return + * The number of packet sent to the interface or 0 if RX is empty. + */ +CNDP_API __cne_always_inline uint16_t +xskdev_tx_burst(xskdev_info_t *xi, mbuf_t **bufs, uint16_t nb_pkts) +{ + return xi->buf_mgmt.buf_tx_burst(xi, bufs, nb_pkts); +} + /** * Set the buffer data Length. * @@ -319,7 +375,7 @@ xskdev_buf_set_len(xskdev_info_t *xi, void *buf, int len) */ CNDP_API __cne_always_inline void -xskdev_buf_set_data_len(xskdev_info_t *xi, void *buf, int len) +xskdev_buf_set_data_len(xskdev_info_t *xi, mbuf_t *buf, uint16_t len) { xi->buf_mgmt.buf_set_data_len(buf, len); } @@ -335,9 +391,9 @@ xskdev_buf_set_data_len(xskdev_info_t *xi, void *buf, int len) * The offset to set the data pointer to. */ CNDP_API __cne_always_inline void -xskdev_buf_set_data(xskdev_info_t *xi, void *buf, uint64_t off) +xskdev_buf_set_data_off(xskdev_info_t *xi, mbuf_t *buf, uint64_t off) { - xi->buf_mgmt.buf_set_data(buf, off); + xi->buf_mgmt.buf_set_data_off(buf, off); } /** @@ -351,29 +407,29 @@ xskdev_buf_set_data(xskdev_info_t *xi, void *buf, uint64_t off) * The data length of the buffer. */ CNDP_API __cne_always_inline uint16_t -xskdev_buf_get_data_len(xskdev_info_t *xi, void *buf) +xskdev_buf_get_data_len(xskdev_info_t *xi, mbuf_t *buf) { return xi->buf_mgmt.buf_get_data_len(buf); } /** - * Get the buffer data pointer. + * Get the buffer data offset. * * @param xi * The pointer to the xskdev_info struct. * @param buf * The array of xbuf pointers to free. * @return - * The address of the data pointer. + * The data offset within the buffer. */ -CNDP_API __cne_always_inline uint64_t -xskdev_buf_get_data(xskdev_info_t *xi, void *buf) +CNDP_API __cne_always_inline uint16_t +xskdev_buf_get_data_off(xskdev_info_t *xi, mbuf_t *buf) { - return xi->buf_mgmt.buf_get_data(buf); + return xi->buf_mgmt.buf_get_data_off(buf); } /** - * Get the virtual address of the segment buffer. + * Get the pointer to the data inside the buffer * * @param xi * The pointer to the xskdev_info struct. @@ -383,43 +439,9 @@ xskdev_buf_get_data(xskdev_info_t *xi, void *buf) * The the virtual address of the segment buffer. */ CNDP_API __cne_always_inline uint64_t -xskdev_buf_get_addr(xskdev_info_t *xi, void *buf) +xskdev_buf_get_data_ptr(xskdev_info_t *xi, mbuf_t *buf) { - return xi->buf_mgmt.buf_get_addr(buf); -} - -/** - * Increment the buffer array pointer - * - * @param xi - * The pointer to the xskdev_info struct. - * @param buf - * The buffer ptr to increment. - */ -CNDP_API __cne_always_inline void ** -xskdev_buf_inc_ptr(xskdev_info_t *xi, void **buf) -{ - return xi->buf_mgmt.buf_inc_ptr(buf); -} - -/** - * Reset a buffer. - * - * @param xi - * The pointer to the xskdev_info struct. - * @param buf - * The buffer to reset. - * @param buf_len - * The max data length able to be contained in the buffer. - * If the buffer is 2K and it contains a mbuf like header then - * buf_len = (2K - sizeof(mbuf)). - * @param headroom - * The buffer headroom to offset the data pointer by (if needed). - */ -CNDP_API __cne_always_inline void -xskdev_buf_reset(xskdev_info_t *xi, void *buf, uint32_t buf_len, size_t headroom) -{ - xi->buf_mgmt.buf_reset(buf, buf_len, headroom); + return xi->buf_mgmt.buf_get_data_ptr(buf); } /** @@ -437,13 +459,14 @@ xskdev_buf_reset(xskdev_info_t *xi, void *buf, uint32_t buf_len, size_t headroom CNDP_API __cne_always_inline int xskdev_get_fd(xskdev_info_t *xi, int *rx_fd, int *tx_fd) { - if (!xi) - return -1; - if (rx_fd) - *rx_fd = xi->rxq.fds.fd; - if (tx_fd) - *tx_fd = xi->txq.fds.fd; - return 0; + if (xi) { + if (rx_fd) + *rx_fd = xi->rxq.fds.fd; + if (tx_fd) + *tx_fd = xi->txq.fds.fd; + return 0; + } + return -1; } #ifdef __cplusplus diff --git a/lib/include/cne_lport.h b/lib/include/cne_lport.h index 8363a8ac..afa85efd 100644 --- a/lib/include/cne_lport.h +++ b/lib/include/cne_lport.h @@ -34,37 +34,45 @@ extern "C" { #define LPORT_RX_BATCH_SIZE 256 #define LPORT_TX_BATCH_SIZE 256 -typedef int (*buf_alloc_t)(void *arg, void **bufs, uint16_t nb_pkts); -typedef void (*buf_free_t)(void *arg, 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_reset_t)(void *buf, uint32_t buf_len, size_t headroom); -typedef void **(*buf_inc_ptr_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 void mbuf_t; /**< Generic void pointer to a mbuf like structure */ +typedef void xinfo_t; /**< Generic void pointer to a xskdev_info_t like structure */ + +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_inc_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 uint64_t (*buf_get_base_ptr_t)(mbuf_t *buf); +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 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 struct lport_buf_mgmt { - 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_reset_t buf_reset; /**< Buffer reset function */ - 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_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 mgmt routines */ + 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_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 */ + 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; typedef struct lport_cfg { @@ -81,7 +89,7 @@ typedef struct lport_cfg { uint16_t busy_budget; /**< -1 disabled, 0 use default, >0 budget value */ void *addr; /**< Start address of the buffers */ char *umem_addr; /**< Address of the allocated UMEM area */ - char *pmd_opts; /**< options string from jasonc file */ + char *pmd_opts; /**< options string from jsonc file */ size_t umem_size; /**< Size of the umem region */ pktmbuf_info_t *pi; /**< pktmbuf_info_t structure pointer */ void *xsk_uds; /**< The UDS to connect to get xsk FDs */ diff --git a/lib/usr/app/jcfg/jcfg.h b/lib/usr/app/jcfg/jcfg.h index ad799e7a..9cc5f15e 100644 --- a/lib/usr/app/jcfg/jcfg.h +++ b/lib/usr/app/jcfg/jcfg.h @@ -181,20 +181,21 @@ typedef struct jcfg_lport { } jcfg_lport_t; /** JCFG lport configuration names */ -#define JCFG_LPORT_PMD_NAME "pmd" -#define JCFG_LPORT_UMEM_NAME "umem" -#define JCFG_LPORT_REGION_NAME "region" -#define JCFG_LPORT_QID_NAME "qid" -#define JCFG_LPORT_DESCRIPTION_NAME "description" -#define JCFG_LPORT_DESC_NAME "desc" -#define JCFG_LPORT_BUSY_POLL_NAME "busy_poll" -#define JCFG_LPORT_BUSY_POLLING_NAME "busy_polling" -#define JCFG_LPORT_BUSY_TIMEOUT_NAME "busy_timeout" -#define JCFG_LPORT_BUSY_BUDGET_NAME "busy_budget" -#define JCFG_PINNED_XSK_MAP_NAME "xsk_pin_path" -#define JCFG_UDS_NAME "uds_path" -#define JCFG_LPORT_FORCE_WAKEUP_NAME "force_wakeup" -#define JCFG_LPORT_SKB_MODE_NAME "skb_mode" +#define JCFG_LPORT_PMD_NAME "pmd" +#define JCFG_LPORT_UMEM_NAME "umem" +#define JCFG_LPORT_REGION_NAME "region" +#define JCFG_LPORT_QID_NAME "qid" +#define JCFG_LPORT_DESCRIPTION_NAME "description" +#define JCFG_LPORT_DESC_NAME "desc" +#define JCFG_LPORT_BUSY_POLL_NAME "busy_poll" +#define JCFG_LPORT_BUSY_POLLING_NAME "busy_polling" +#define JCFG_LPORT_BUSY_TIMEOUT_NAME "busy_timeout" +#define JCFG_LPORT_BUSY_BUDGET_NAME "busy_budget" +#define JCFG_PINNED_XSK_MAP_NAME "xsk_pin_path" +#define JCFG_UDS_NAME "uds_path" +#define JCFG_LPORT_FORCE_WAKEUP_NAME "force_wakeup" +#define JCFG_LPORT_SKB_MODE_NAME "skb_mode" +#define JCFG_LPORT_UNALIGNED_BUFFERS_NAME "unaligned_buffers" /** * JCFG lgroup for lcore allocations diff --git a/lib/usr/app/jcfg/jcfg_lport.c b/lib/usr/app/jcfg/jcfg_lport.c index 6169bd4c..7cc79a31 100644 --- a/lib/usr/app/jcfg/jcfg_lport.c +++ b/lib/usr/app/jcfg/jcfg_lport.c @@ -4,7 +4,7 @@ // IWYU pragma: no_include -#include // for strcmp, strdup, strchr +#include // for strncmp, strdup, strchr #include // for json_object_get_string, json_object_... #include // for json_c_visit, JSON_C_VISIT_RETURN_CO... #include // for NULL, calloc, free, size_t @@ -69,7 +69,7 @@ _lport(struct json_object *obj, int flags, struct json_object *parent __cne_unus enum json_type type; char *pmd_opt[JCFG_OPT_NUM] = {0}; char *pmd_str = NULL; - int ret = JSON_C_VISIT_RETURN_CONTINUE; + int val, ret = JSON_C_VISIT_RETURN_CONTINUE; if (flags == JSON_C_VISIT_SECOND) return ret; @@ -95,16 +95,12 @@ _lport(struct json_object *obj, int flags, struct json_object *parent __cne_unus !strncmp(key, JCFG_LPORT_DESCRIPTION_NAME, keylen)) lport->desc = strdup(json_object_get_string(obj)); else if (!strncmp(key, JCFG_LPORT_BUSY_TIMEOUT_NAME, keylen)) { - int val; - val = json_object_get_int(obj); if (val < 0 || val > USHRT_MAX) CNE_ERR_RET_VAL(JSON_C_VISIT_RETURN_ERROR, "%s: Invalid Range\n", JCFG_LPORT_BUSY_TIMEOUT_NAME); lport->busy_timeout = (uint16_t)val; } else if (!strncmp(key, JCFG_LPORT_BUSY_BUDGET_NAME, keylen)) { - int val; - val = json_object_get_int(obj); if (val < 0 || val > USHRT_MAX) CNE_ERR_RET_VAL(JSON_C_VISIT_RETURN_ERROR, "%s: Invalid Range\n", @@ -123,6 +119,8 @@ _lport(struct json_object *obj, int flags, struct json_object *parent __cne_unus else if (!strncmp(key, JCFG_LPORT_BUSY_POLL_NAME, keylen) || !strncmp(key, JCFG_LPORT_BUSY_POLLING_NAME, keylen)) lport->flags |= json_object_get_boolean(obj) ? LPORT_BUSY_POLLING : 0; + else if (!strncmp(key, JCFG_LPORT_UNALIGNED_BUFFERS_NAME, keylen)) + lport->flags |= json_object_get_boolean(obj) ? LPORT_UMEM_UNALIGNED_BUFFERS : 0; else CNE_WARN("Unknown lport key (%s)\n", key); } diff --git a/lib/usr/slib/ibroker/meson.build b/lib/usr/slib/ibroker/meson.build index 90d2ce22..39e346ba 100644 --- a/lib/usr/slib/ibroker/meson.build +++ b/lib/usr/slib/ibroker/meson.build @@ -1,10 +1,24 @@ # SPDX-License-Identifier: BSD-3-Clause # Copyright (c) 2017-2025 Intel Corporation -sources = files('ibroker.c', 'uintr_handler.c') +sources = files('ibroker.c') +uintr_sources = files('uintr_handler.c') headers = files('ibroker.h') -libibroker = library(libname, sources, install: true, dependencies: deps) +uintr_c_args = [] +if cc.has_argument('-mtls-dialect=gnu2') + uintr_c_args += ['-mtls-dialect=gnu2'] +endif + +ibroker_uintr_obj = static_library('ibroker_uintr_obj', uintr_sources, + c_args: uintr_c_args, + install: false, + dependencies: deps) + +libibroker = library(libname, sources, + install: true, + dependencies: deps, + link_whole: ibroker_uintr_obj) ibroker = declare_dependency(link_with: libibroker, include_directories: include_directories('.')) cndp_libs += ibroker diff --git a/tools/cne-build.sh b/tools/cne-build.sh index 8dad4ef7..87654b22 100755 --- a/tools/cne-build.sh +++ b/tools/cne-build.sh @@ -59,18 +59,21 @@ echo "" function run_meson() { btype="-Dbuildtype=$buildtype" - meson $configure $static $coverity $btype $tcp $ipv6 --prefix="/$target_dir" "$build_path" "$sdk_dir" + if [[ -n "$CNE_VERBOSE" ]]; then + echo "meson $configure $static $coverity $btype $tcp $ipv6 --prefix=\"/$target_dir\" \"$build_path\" $sdk_dir" + fi + meson $configure $static $coverity $btype $tcp $ipv6 --prefix="/$target_dir" "$build_path" $sdk_dir configure="" } function ninja_build() { - echo ">>> Ninja build in $build_path buildtype= $buildtype" + echo ">>> Ninja build in $build_path buildtype=$buildtype" if [[ -d $build_path ]] || [[ -f $build_path/build.ninja ]]; then # add reconfigure command if meson dir already exists configure="configure" # sdk_dir must be empty if we're reconfiguring - sdk_dir="" + sdk_dir= else configure="setup" fi