diff options
Diffstat (limited to 'net')
| -rw-r--r-- | net/xdp/xsk.c | 26 | ||||
| -rw-r--r-- | net/xdp/xsk_buff_pool.c | 7 | 
2 files changed, 32 insertions, 1 deletions
| diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c index ba755fed3750..4f1e0599146e 100644 --- a/net/xdp/xsk.c +++ b/net/xdp/xsk.c @@ -155,8 +155,32 @@ 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; +	struct list_head *xskb_list; +	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; + +	xskb_list = &xskb->pool->xskb_list; +	list_for_each_entry_safe(pos, tmp, xskb_list, xskb_list_node) { +		if (list_is_singular(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) diff --git a/net/xdp/xsk_buff_pool.c b/net/xdp/xsk_buff_pool.c index 26f6d304451e..b3f7b310811e 100644 --- a/net/xdp/xsk_buff_pool.c +++ b/net/xdp/xsk_buff_pool.c @@ -86,6 +86,7 @@ struct xsk_buff_pool *xp_create_and_assign_umem(struct xdp_sock *xs,  	pool->umem = umem;  	pool->addrs = umem->addrs;  	INIT_LIST_HEAD(&pool->free_list); +	INIT_LIST_HEAD(&pool->xskb_list);  	INIT_LIST_HEAD(&pool->xsk_tx_list);  	spin_lock_init(&pool->xsk_tx_list_lock);  	spin_lock_init(&pool->cq_lock); @@ -99,6 +100,7 @@ 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);  		if (pool->unaligned)  			pool->free_heads[i] = xskb;  		else @@ -187,6 +189,11 @@ int xp_assign_dev(struct xsk_buff_pool *pool,  		goto err_unreg_pool;  	} +	if (netdev->xdp_zc_max_segs == 1 && (flags & XDP_USE_SG)) { +		err = -EOPNOTSUPP; +		goto err_unreg_pool; +	} +  	bpf.command = XDP_SETUP_XSK_POOL;  	bpf.xsk.pool = pool;  	bpf.xsk.queue_id = queue_id; | 
