From: Jason Xing Batch xmit mode needs to allocate and build skbs at one time. To avoid reinvent the wheel, use xsk_build_skb() as the second half process of the whole initialization of each skb. The original xsk_build_skb() itself allocates a new skb by calling sock_alloc_send_skb whether in copy mode or zerocopy mode. Add a new parameter allocated skb to let other callers to pass an already allocated skb to support later xmit batch feature. At that time, another building skb function will generate a new skb and pass it to xsk_build_skb() to finish the rest of building process, like initializing structures and copying data. Signed-off-by: Jason Xing --- include/net/xdp_sock.h | 4 ++++ net/xdp/xsk.c | 23 ++++++++++++++++------- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/include/net/xdp_sock.h b/include/net/xdp_sock.h index c2b05268b8ad..cbba880c27c3 100644 --- a/include/net/xdp_sock.h +++ b/include/net/xdp_sock.h @@ -123,6 +123,10 @@ struct xsk_tx_metadata_ops { void (*tmo_request_launch_time)(u64 launch_time, void *priv); }; + +struct sk_buff *xsk_build_skb(struct xdp_sock *xs, + struct sk_buff *allocated_skb, + struct xdp_desc *desc); #ifdef CONFIG_XDP_SOCKETS int xsk_generic_rcv(struct xdp_sock *xs, struct xdp_buff *xdp); diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c index 173ad49379c3..213d6100e405 100644 --- a/net/xdp/xsk.c +++ b/net/xdp/xsk.c @@ -605,6 +605,7 @@ static void xsk_drop_skb(struct sk_buff *skb) } static struct sk_buff *xsk_build_skb_zerocopy(struct xdp_sock *xs, + struct sk_buff *allocated_skb, struct xdp_desc *desc) { struct xsk_buff_pool *pool = xs->pool; @@ -618,7 +619,10 @@ static struct sk_buff *xsk_build_skb_zerocopy(struct xdp_sock *xs, if (!skb) { hr = max(NET_SKB_PAD, L1_CACHE_ALIGN(xs->dev->needed_headroom)); - skb = sock_alloc_send_skb(&xs->sk, hr, 1, &err); + if (!allocated_skb) + skb = sock_alloc_send_skb(&xs->sk, hr, 1, &err); + else + skb = allocated_skb; if (unlikely(!skb)) return ERR_PTR(err); @@ -657,8 +661,9 @@ static struct sk_buff *xsk_build_skb_zerocopy(struct xdp_sock *xs, return skb; } -static struct sk_buff *xsk_build_skb(struct xdp_sock *xs, - struct xdp_desc *desc) +struct sk_buff *xsk_build_skb(struct xdp_sock *xs, + struct sk_buff *allocated_skb, + struct xdp_desc *desc) { struct xsk_tx_metadata *meta = NULL; struct net_device *dev = xs->dev; @@ -667,7 +672,7 @@ static struct sk_buff *xsk_build_skb(struct xdp_sock *xs, int err; if (dev->priv_flags & IFF_TX_SKB_NO_LINEAR) { - skb = xsk_build_skb_zerocopy(xs, desc); + skb = xsk_build_skb_zerocopy(xs, allocated_skb, desc); if (IS_ERR(skb)) { err = PTR_ERR(skb); goto free_err; @@ -683,8 +688,12 @@ static struct sk_buff *xsk_build_skb(struct xdp_sock *xs, first_frag = true; hr = max(NET_SKB_PAD, L1_CACHE_ALIGN(dev->needed_headroom)); - tr = dev->needed_tailroom; - skb = sock_alloc_send_skb(&xs->sk, hr + len + tr, 1, &err); + if (!allocated_skb) { + tr = dev->needed_tailroom; + skb = sock_alloc_send_skb(&xs->sk, hr + len + tr, 1, &err); + } else { + skb = allocated_skb; + } if (unlikely(!skb)) goto free_err; @@ -818,7 +827,7 @@ static int __xsk_generic_xmit(struct sock *sk) goto out; } - skb = xsk_build_skb(xs, &desc); + skb = xsk_build_skb(xs, NULL, &desc); if (IS_ERR(skb)) { err = PTR_ERR(skb); if (err != -EOVERFLOW) -- 2.41.3