mirror of
https://github.com/xdp-project/bpf-examples.git
synced 2024-05-06 15:54:53 +00:00
AF_XDP-interaction: refactor FQ+CQ per xsk_socket_info
Cannot share/associate the FQ (Fill Queue) and CQ (Completion Q) with umem container (xsk_umem_info). This is the reason current program cannot handle packets for each queue ID. As described in [1] we need more FQ and CQ ring pairs, a pair per for each unique netdev and queue IP tuple. Thus, add FQ and CQ for each queue id in struct xsk_socket_info. [1] https://www.kernel.org/doc/html/latest/networking/af_xdp.html Signed-off-by: Jesper Dangaard Brouer <brouer@redhat.com>
This commit is contained in:
@@ -46,8 +46,8 @@ struct mem_frame_allocator {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct xsk_umem_info {
|
struct xsk_umem_info {
|
||||||
struct xsk_ring_prod fq;
|
struct xsk_ring_prod init_fq;
|
||||||
struct xsk_ring_cons cq;
|
struct xsk_ring_cons init_cq;
|
||||||
struct xsk_umem *umem;
|
struct xsk_umem *umem;
|
||||||
void *buffer;
|
void *buffer;
|
||||||
struct mem_frame_allocator mem;
|
struct mem_frame_allocator mem;
|
||||||
@@ -66,6 +66,8 @@ struct xsk_socket_info {
|
|||||||
struct xsk_ring_prod tx;
|
struct xsk_ring_prod tx;
|
||||||
struct xsk_umem_info *umem;
|
struct xsk_umem_info *umem;
|
||||||
struct xsk_socket *xsk;
|
struct xsk_socket *xsk;
|
||||||
|
struct xsk_ring_prod fq;
|
||||||
|
struct xsk_ring_cons cq;
|
||||||
|
|
||||||
uint32_t outstanding_tx;
|
uint32_t outstanding_tx;
|
||||||
int queue_id;
|
int queue_id;
|
||||||
@@ -305,7 +307,8 @@ static struct xsk_umem_info *configure_xsk_umem(void *buffer, uint64_t size)
|
|||||||
if (!umem)
|
if (!umem)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
ret = xsk_umem__create(&umem->umem, buffer, size, &umem->fq, &umem->cq,
|
ret = xsk_umem__create(&umem->umem, buffer, size,
|
||||||
|
&umem->init_fq, &umem->init_cq,
|
||||||
&xsk_umem_cfg);
|
&xsk_umem_cfg);
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
@@ -321,13 +324,14 @@ static struct xsk_umem_info *configure_xsk_umem(void *buffer, uint64_t size)
|
|||||||
return umem;
|
return umem;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int xsk_populate_fill_ring(struct xsk_umem_info *umem)
|
static int xsk_populate_fill_ring(struct xsk_ring_prod *fq,
|
||||||
|
struct xsk_umem_info *umem)
|
||||||
{
|
{
|
||||||
int ret, i;
|
int ret, i;
|
||||||
uint32_t idx;
|
uint32_t idx;
|
||||||
|
|
||||||
/* Stuff the receive path with buffers, we assume we have enough */
|
/* Stuff the receive path with buffers, we assume we have enough */
|
||||||
ret = xsk_ring_prod__reserve(&umem->fq,
|
ret = xsk_ring_prod__reserve(fq,
|
||||||
XSK_RING_PROD__DEFAULT_NUM_DESCS,
|
XSK_RING_PROD__DEFAULT_NUM_DESCS,
|
||||||
&idx);
|
&idx);
|
||||||
|
|
||||||
@@ -335,10 +339,10 @@ static int xsk_populate_fill_ring(struct xsk_umem_info *umem)
|
|||||||
goto error_exit;
|
goto error_exit;
|
||||||
|
|
||||||
for (i = 0; i < XSK_RING_PROD__DEFAULT_NUM_DESCS; i++)
|
for (i = 0; i < XSK_RING_PROD__DEFAULT_NUM_DESCS; i++)
|
||||||
*xsk_ring_prod__fill_addr(&umem->fq, idx++) =
|
*xsk_ring_prod__fill_addr(fq, idx++) =
|
||||||
mem_alloc_umem_frame(&umem->mem);
|
mem_alloc_umem_frame(&umem->mem);
|
||||||
|
|
||||||
xsk_ring_prod__submit(&umem->fq,
|
xsk_ring_prod__submit(fq,
|
||||||
XSK_RING_PROD__DEFAULT_NUM_DESCS);
|
XSK_RING_PROD__DEFAULT_NUM_DESCS);
|
||||||
return 0;
|
return 0;
|
||||||
error_exit:
|
error_exit:
|
||||||
@@ -365,8 +369,6 @@ static struct xsk_socket_info *xsk_configure_socket(struct config *cfg,
|
|||||||
if (cfg->xsk_if_queue >= 0)
|
if (cfg->xsk_if_queue >= 0)
|
||||||
_queue_id = cfg->xsk_if_queue;
|
_queue_id = cfg->xsk_if_queue;
|
||||||
xsk_info->queue_id = _queue_id;
|
xsk_info->queue_id = _queue_id;
|
||||||
printf("XXX _queue_id:%d\n", _queue_id);
|
|
||||||
/* BUG: Program only seems works if _queue_id is same for all XSK sockets */
|
|
||||||
|
|
||||||
xsk_info->umem = umem;
|
xsk_info->umem = umem;
|
||||||
xsk_cfg.rx_size = XSK_RING_CONS__DEFAULT_NUM_DESCS;
|
xsk_cfg.rx_size = XSK_RING_CONS__DEFAULT_NUM_DESCS;
|
||||||
@@ -383,8 +385,8 @@ static struct xsk_socket_info *xsk_configure_socket(struct config *cfg,
|
|||||||
_queue_id, umem->umem,
|
_queue_id, umem->umem,
|
||||||
&xsk_info->rx,
|
&xsk_info->rx,
|
||||||
&xsk_info->tx,
|
&xsk_info->tx,
|
||||||
&umem->fq,
|
&xsk_info->fq,
|
||||||
&umem->cq,
|
&xsk_info->cq,
|
||||||
&xsk_cfg);
|
&xsk_cfg);
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
@@ -418,17 +420,17 @@ static void complete_tx(struct xsk_socket_info *xsk)
|
|||||||
|
|
||||||
|
|
||||||
/* Collect/free completed TX buffers */
|
/* Collect/free completed TX buffers */
|
||||||
completed = xsk_ring_cons__peek(&xsk->umem->cq,
|
completed = xsk_ring_cons__peek(&xsk->cq,
|
||||||
XSK_RING_CONS__DEFAULT_NUM_DESCS,
|
XSK_RING_CONS__DEFAULT_NUM_DESCS,
|
||||||
&idx_cq);
|
&idx_cq);
|
||||||
|
|
||||||
if (completed > 0) {
|
if (completed > 0) {
|
||||||
for (int i = 0; i < completed; i++)
|
for (int i = 0; i < completed; i++)
|
||||||
mem_free_umem_frame(&xsk->umem->mem,
|
mem_free_umem_frame(&xsk->umem->mem,
|
||||||
*xsk_ring_cons__comp_addr(&xsk->umem->cq,
|
*xsk_ring_cons__comp_addr(&xsk->cq,
|
||||||
idx_cq++));
|
idx_cq++));
|
||||||
|
|
||||||
xsk_ring_cons__release(&xsk->umem->cq, completed);
|
xsk_ring_cons__release(&xsk->cq, completed);
|
||||||
xsk->outstanding_tx -= completed < xsk->outstanding_tx ?
|
xsk->outstanding_tx -= completed < xsk->outstanding_tx ?
|
||||||
completed : xsk->outstanding_tx;
|
completed : xsk->outstanding_tx;
|
||||||
}
|
}
|
||||||
@@ -663,12 +665,12 @@ void restock_receive_fill_queue(struct xsk_socket_info *xsk)
|
|||||||
__u64 start = gettime();
|
__u64 start = gettime();
|
||||||
|
|
||||||
/* Stuff the ring with as much frames as possible */
|
/* Stuff the ring with as much frames as possible */
|
||||||
stock_frames = xsk_prod_nb_free(&xsk->umem->fq,
|
stock_frames = xsk_prod_nb_free(&xsk->fq,
|
||||||
mem_avail_umem_frames(&xsk->umem->mem));
|
mem_avail_umem_frames(&xsk->umem->mem));
|
||||||
|
|
||||||
if (stock_frames > 0) {
|
if (stock_frames > 0) {
|
||||||
|
|
||||||
ret = xsk_ring_prod__reserve(&xsk->umem->fq, stock_frames,
|
ret = xsk_ring_prod__reserve(&xsk->fq, stock_frames,
|
||||||
&idx_fq);
|
&idx_fq);
|
||||||
|
|
||||||
/* This should not happen, but just in case */
|
/* This should not happen, but just in case */
|
||||||
@@ -679,10 +681,10 @@ void restock_receive_fill_queue(struct xsk_socket_info *xsk)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < stock_frames; i++)
|
for (i = 0; i < stock_frames; i++)
|
||||||
*xsk_ring_prod__fill_addr(&xsk->umem->fq, idx_fq++) =
|
*xsk_ring_prod__fill_addr(&xsk->fq, idx_fq++) =
|
||||||
mem_alloc_umem_frame(&xsk->umem->mem);
|
mem_alloc_umem_frame(&xsk->umem->mem);
|
||||||
|
|
||||||
xsk_ring_prod__submit(&xsk->umem->fq, stock_frames);
|
xsk_ring_prod__submit(&xsk->fq, stock_frames);
|
||||||
}
|
}
|
||||||
__u64 now = gettime();
|
__u64 now = gettime();
|
||||||
if (debug && (stock_frames || free_frames))
|
if (debug && (stock_frames || free_frames))
|
||||||
@@ -954,20 +956,24 @@ int main(int argc, char **argv)
|
|||||||
strerror(errno));
|
strerror(errno));
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
if (xsk_populate_fill_ring(umem)) {
|
|
||||||
fprintf(stderr, "ERROR: Can't populate fill ring\n");
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Open and configure the AF_XDP (xsk) socket(s) */
|
/* Open and configure the AF_XDP (xsk) socket(s) */
|
||||||
for (i = 0; i < xsks.num; i++) {
|
for (i = 0; i < xsks.num; i++) {
|
||||||
|
struct xsk_socket_info *xski;
|
||||||
|
|
||||||
printf("XXX i:%d\n", i);
|
printf("XXX i:%d\n", i);
|
||||||
xsks.sockets[i] = xsk_configure_socket(&cfg, umem, i, xsks_map_fd);
|
xski = xsk_configure_socket(&cfg, umem, i, xsks_map_fd);
|
||||||
if (xsks.sockets[i] == NULL) {
|
if (xski == NULL) {
|
||||||
fprintf(stderr, "ERROR(%d): Can't setup AF_XDP socket "
|
fprintf(stderr, "ERROR(%d): Can't setup AF_XDP socket "
|
||||||
"\"%s\"\n", errno, strerror(errno));
|
"\"%s\"\n", errno, strerror(errno));
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
xsks.sockets[i] = xski;
|
||||||
|
|
||||||
|
if (xsk_populate_fill_ring(&xski->fq, umem)) {
|
||||||
|
fprintf(stderr, "ERROR: Can't populate fill ring\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
enter_xsks_into_map(xsks_map_fd, &xsks);
|
enter_xsks_into_map(xsks_map_fd, &xsks);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user