Skip to content

Commit

Permalink
xsk: support mbuf on ZC RX
Browse files Browse the repository at this point in the history
Extend xdp_buff_xsk with two new list_head members - xskb_list and
xskb_list_node. This means that each xdp_buff_xsk can be a node in the
chain of these structs and also each xskb can carry the list by itself.
This is needed so ZC drivers can add frags as xskb nodes which will make
it possible to handle it both when producing AF_XDP Rx descriptors as
well as freeing/recycling all the frags that a single frame carries.

Speaking of latter, update xsk_buff_free() to take care of list nodes.
For the former (adding as frags), introduce xsk_buff_add_frag() for ZC
drivers usage that is going to be used to add a frag to the first xskb.

xsk_buff_get_frag() will be utilized by XDP_TX and, on contrary, will
return xdp_buff.

One of the previous patches added a wrapper for ZC Rx so implement xskb
list walk and production of Rx descriptors there.

Signed-off-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
  • Loading branch information
mfijalko authored and intel-lab-lkp committed May 18, 2023
1 parent 946f0b1 commit 06a192e
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 1 deletion.
45 changes: 45 additions & 0 deletions include/net/xdp_sock_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,46 @@ static inline bool xsk_buff_can_alloc(struct xsk_buff_pool *pool, u32 count)
static inline void xsk_buff_free(struct xdp_buff *xdp)
{
struct xdp_buff_xsk *xskb = container_of(xdp, struct xdp_buff_xsk, xdp);
struct xdp_buff_xsk *pos, *tmp;

if (likely(!xdp_buff_has_frags(xdp)))
goto out;

list_for_each_entry_safe(pos, tmp, &xskb->xskb_list, xskb_list_node) {
list_del(&pos->xskb_list_node);
xp_free(pos);
}

xdp_get_shared_info_from_buff(xdp)->nr_frags = 0;
out:
xp_free(xskb);
}

static inline void xsk_buff_add_frag(struct xdp_buff *first,
struct xdp_buff *xdp)
{
struct xdp_buff_xsk *xskb = container_of(first, struct xdp_buff_xsk, xdp);
struct xdp_buff_xsk *frag = container_of(xdp, struct xdp_buff_xsk, xdp);

list_add_tail(&frag->xskb_list_node, &xskb->xskb_list);
}

static inline struct xdp_buff *xsk_buff_get_frag(struct xdp_buff *first)
{
struct xdp_buff_xsk *xskb = container_of(first, struct xdp_buff_xsk, xdp);
struct xdp_buff *ret = NULL;
struct xdp_buff_xsk *frag;

frag = list_first_entry_or_null(&xskb->xskb_list, struct xdp_buff_xsk,
xskb_list_node);
if (frag) {
list_del(&frag->xskb_list_node);
ret = &frag->xdp;
}

return ret;
}

static inline void xsk_buff_set_size(struct xdp_buff *xdp, u32 size)
{
xdp->data = xdp->data_hard_start + XDP_PACKET_HEADROOM;
Expand Down Expand Up @@ -265,6 +301,15 @@ static inline void xsk_buff_free(struct xdp_buff *xdp)
{
}

static inline void xsk_buff_add_frag(struct xdp_buff *first,
struct xdp_buff *xdp)
{
}

static inline struct xdp_buff *xsk_buff_get_frag(struct xdp_buff *first)
{
}

static inline void xsk_buff_discard(struct xdp_buff *xdp)
{
}
Expand Down
2 changes: 2 additions & 0 deletions include/net/xsk_buff_pool.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ struct xdp_buff_xsk {
struct xsk_buff_pool *pool;
u64 orig_addr;
struct list_head free_list_node;
struct list_head xskb_list_node;
struct list_head xskb_list;
};

#define XSK_CHECK_PRIV_TYPE(t) BUILD_BUG_ON(sizeof(t) > offsetofend(struct xdp_buff_xsk, cb))
Expand Down
24 changes: 23 additions & 1 deletion net/xdp/xsk.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,30 @@ static int __xsk_rcv_zc(struct xdp_sock *xs, struct xdp_buff_xsk *xskb, u32 len,
static int xsk_rcv_zc(struct xdp_sock *xs, struct xdp_buff *xdp, u32 len)
{
struct xdp_buff_xsk *xskb = container_of(xdp, struct xdp_buff_xsk, xdp);
u32 frags = xdp_buff_has_frags(xdp);
struct xdp_buff_xsk *pos, *tmp;
u32 contd = 0;
int err;

if (frags)
contd = XDP_PKT_CONTD;

return __xsk_rcv_zc(xs, xskb, len, 0);
err = __xsk_rcv_zc(xs, xskb, len, contd);
if (err || likely(!frags))
goto out;

list_for_each_entry_safe(pos, tmp, &xskb->xskb_list, xskb_list_node) {
if (list_is_singular(&xskb->xskb_list))
contd = 0;
len = pos->xdp.data_end - pos->xdp.data;
err = __xsk_rcv_zc(xs, pos, len, contd);
if (err)
return err;
list_del(&pos->xskb_list_node);
}

out:
return err;
}

static void *xsk_copy_xdp_start(struct xdp_buff *from)
Expand Down
2 changes: 2 additions & 0 deletions net/xdp/xsk_buff_pool.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ struct xsk_buff_pool *xp_create_and_assign_umem(struct xdp_sock *xs,
xskb->pool = pool;
xskb->xdp.frame_sz = umem->chunk_size - umem->headroom;
INIT_LIST_HEAD(&xskb->free_list_node);
INIT_LIST_HEAD(&xskb->xskb_list_node);
INIT_LIST_HEAD(&xskb->xskb_list);
if (pool->unaligned)
pool->free_heads[i] = xskb;
else
Expand Down

0 comments on commit 06a192e

Please sign in to comment.