Skip to content

Commit 24ea501

Browse files
mfijalkoAlexei Starovoitov
authored and
Alexei Starovoitov
committed
xsk: support mbuf on ZC RX
Given that skb_shared_info relies on skb_frag_t, in order to support xskb chaining, introduce xdp_buff_xsk::xskb_list_node and xsk_buff_pool::xskb_list. 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 xskb list from pool. 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. On bind() path, bail out if socket wants to use ZC multi-buffer but underlying netdev does not support it. Signed-off-by: Maciej Fijalkowski <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent 13ce2da commit 24ea501

File tree

4 files changed

+78
-1
lines changed

4 files changed

+78
-1
lines changed

include/net/xdp_sock_drv.h

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,10 +108,45 @@ static inline bool xsk_buff_can_alloc(struct xsk_buff_pool *pool, u32 count)
108108
static inline void xsk_buff_free(struct xdp_buff *xdp)
109109
{
110110
struct xdp_buff_xsk *xskb = container_of(xdp, struct xdp_buff_xsk, xdp);
111+
struct list_head *xskb_list = &xskb->pool->xskb_list;
112+
struct xdp_buff_xsk *pos, *tmp;
111113

114+
if (likely(!xdp_buff_has_frags(xdp)))
115+
goto out;
116+
117+
list_for_each_entry_safe(pos, tmp, xskb_list, xskb_list_node) {
118+
list_del(&pos->xskb_list_node);
119+
xp_free(pos);
120+
}
121+
122+
xdp_get_shared_info_from_buff(xdp)->nr_frags = 0;
123+
out:
112124
xp_free(xskb);
113125
}
114126

127+
static inline void xsk_buff_add_frag(struct xdp_buff *xdp)
128+
{
129+
struct xdp_buff_xsk *frag = container_of(xdp, struct xdp_buff_xsk, xdp);
130+
131+
list_add_tail(&frag->xskb_list_node, &frag->pool->xskb_list);
132+
}
133+
134+
static inline struct xdp_buff *xsk_buff_get_frag(struct xdp_buff *first)
135+
{
136+
struct xdp_buff_xsk *xskb = container_of(first, struct xdp_buff_xsk, xdp);
137+
struct xdp_buff *ret = NULL;
138+
struct xdp_buff_xsk *frag;
139+
140+
frag = list_first_entry_or_null(&xskb->pool->xskb_list,
141+
struct xdp_buff_xsk, xskb_list_node);
142+
if (frag) {
143+
list_del(&frag->xskb_list_node);
144+
ret = &frag->xdp;
145+
}
146+
147+
return ret;
148+
}
149+
115150
static inline void xsk_buff_set_size(struct xdp_buff *xdp, u32 size)
116151
{
117152
xdp->data = xdp->data_hard_start + XDP_PACKET_HEADROOM;
@@ -265,6 +300,15 @@ static inline void xsk_buff_free(struct xdp_buff *xdp)
265300
{
266301
}
267302

303+
static inline void xsk_buff_add_frag(struct xdp_buff *xdp)
304+
{
305+
}
306+
307+
static inline struct xdp_buff *xsk_buff_get_frag(struct xdp_buff *first)
308+
{
309+
return NULL;
310+
}
311+
268312
static inline void xsk_buff_set_size(struct xdp_buff *xdp, u32 size)
269313
{
270314
}

include/net/xsk_buff_pool.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ struct xdp_buff_xsk {
2929
struct xsk_buff_pool *pool;
3030
u64 orig_addr;
3131
struct list_head free_list_node;
32+
struct list_head xskb_list_node;
3233
};
3334

3435
#define XSK_CHECK_PRIV_TYPE(t) BUILD_BUG_ON(sizeof(t) > offsetofend(struct xdp_buff_xsk, cb))
@@ -54,6 +55,7 @@ struct xsk_buff_pool {
5455
struct xdp_umem *umem;
5556
struct work_struct work;
5657
struct list_head free_list;
58+
struct list_head xskb_list;
5759
u32 heads_cnt;
5860
u16 queue_id;
5961

net/xdp/xsk.c

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,32 @@ static int __xsk_rcv_zc(struct xdp_sock *xs, struct xdp_buff_xsk *xskb, u32 len,
155155
static int xsk_rcv_zc(struct xdp_sock *xs, struct xdp_buff *xdp, u32 len)
156156
{
157157
struct xdp_buff_xsk *xskb = container_of(xdp, struct xdp_buff_xsk, xdp);
158+
u32 frags = xdp_buff_has_frags(xdp);
159+
struct xdp_buff_xsk *pos, *tmp;
160+
struct list_head *xskb_list;
161+
u32 contd = 0;
162+
int err;
163+
164+
if (frags)
165+
contd = XDP_PKT_CONTD;
158166

159-
return __xsk_rcv_zc(xs, xskb, len, 0);
167+
err = __xsk_rcv_zc(xs, xskb, len, contd);
168+
if (err || likely(!frags))
169+
goto out;
170+
171+
xskb_list = &xskb->pool->xskb_list;
172+
list_for_each_entry_safe(pos, tmp, xskb_list, xskb_list_node) {
173+
if (list_is_singular(xskb_list))
174+
contd = 0;
175+
len = pos->xdp.data_end - pos->xdp.data;
176+
err = __xsk_rcv_zc(xs, pos, len, contd);
177+
if (err)
178+
return err;
179+
list_del(&pos->xskb_list_node);
180+
}
181+
182+
out:
183+
return err;
160184
}
161185

162186
static void *xsk_copy_xdp_start(struct xdp_buff *from)

net/xdp/xsk_buff_pool.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ struct xsk_buff_pool *xp_create_and_assign_umem(struct xdp_sock *xs,
8686
pool->umem = umem;
8787
pool->addrs = umem->addrs;
8888
INIT_LIST_HEAD(&pool->free_list);
89+
INIT_LIST_HEAD(&pool->xskb_list);
8990
INIT_LIST_HEAD(&pool->xsk_tx_list);
9091
spin_lock_init(&pool->xsk_tx_list_lock);
9192
spin_lock_init(&pool->cq_lock);
@@ -99,6 +100,7 @@ struct xsk_buff_pool *xp_create_and_assign_umem(struct xdp_sock *xs,
99100
xskb->pool = pool;
100101
xskb->xdp.frame_sz = umem->chunk_size - umem->headroom;
101102
INIT_LIST_HEAD(&xskb->free_list_node);
103+
INIT_LIST_HEAD(&xskb->xskb_list_node);
102104
if (pool->unaligned)
103105
pool->free_heads[i] = xskb;
104106
else
@@ -187,6 +189,11 @@ int xp_assign_dev(struct xsk_buff_pool *pool,
187189
goto err_unreg_pool;
188190
}
189191

192+
if (netdev->xdp_zc_max_segs == 1 && (flags & XDP_USE_SG)) {
193+
err = -EOPNOTSUPP;
194+
goto err_unreg_pool;
195+
}
196+
190197
bpf.command = XDP_SETUP_XSK_POOL;
191198
bpf.xsk.pool = pool;
192199
bpf.xsk.queue_id = queue_id;

0 commit comments

Comments
 (0)