veth: rely on skb_pp_cow_data utility routine
authorLorenzo Bianconi <lorenzo@kernel.org>
Mon, 12 Feb 2024 09:50:57 +0000 (10:50 +0100)
committerJakub Kicinski <kuba@kernel.org>
Wed, 14 Feb 2024 03:22:30 +0000 (19:22 -0800)
Rely on skb_pp_cow_data utility routine and remove duplicated code.

Acked-by: Jesper Dangaard Brouer <hawk@kernel.org>
Reviewed-by: Toke Hoiland-Jorgensen <toke@redhat.com>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Link: https://lore.kernel.org/r/029cc14cce41cb242ee7efdcf32acc81f1ce4e9f.1707729884.git.lorenzo@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/veth.c
include/linux/skbuff.h
net/core/skbuff.c

index de1f1383778295874a7fb641103d940bba8881f0..500b9dfccd08ee8f91b22d78e3d8195f3de26088 100644 (file)
@@ -729,80 +729,10 @@ static int veth_convert_skb_to_xdp_buff(struct veth_rq *rq,
        if (skb_shared(skb) || skb_head_is_locked(skb) ||
            skb_shinfo(skb)->nr_frags ||
            skb_headroom(skb) < XDP_PACKET_HEADROOM) {
-               u32 size, len, max_head_size, off, truesize, page_offset;
-               struct sk_buff *nskb;
-               struct page *page;
-               int i, head_off;
-               void *va;
-
-               /* We need a private copy of the skb and data buffers since
-                * the ebpf program can modify it. We segment the original skb
-                * into order-0 pages without linearize it.
-                *
-                * Make sure we have enough space for linear and paged area
-                */
-               max_head_size = SKB_WITH_OVERHEAD(PAGE_SIZE -
-                                                 VETH_XDP_HEADROOM);
-               if (skb->len > PAGE_SIZE * MAX_SKB_FRAGS + max_head_size)
-                       goto drop;
-
-               size = min_t(u32, skb->len, max_head_size);
-               truesize = SKB_HEAD_ALIGN(size) + VETH_XDP_HEADROOM;
-
-               /* Allocate skb head */
-               va = page_pool_dev_alloc_va(rq->page_pool, &truesize);
-               if (!va)
-                       goto drop;
-
-               nskb = napi_build_skb(va, truesize);
-               if (!nskb) {
-                       page_pool_free_va(rq->page_pool, va, true);
+               if (skb_pp_cow_data(rq->page_pool, pskb, XDP_PACKET_HEADROOM))
                        goto drop;
-               }
-
-               skb_reserve(nskb, VETH_XDP_HEADROOM);
-               skb_copy_header(nskb, skb);
-               skb_mark_for_recycle(nskb);
-
-               if (skb_copy_bits(skb, 0, nskb->data, size)) {
-                       consume_skb(nskb);
-                       goto drop;
-               }
-               skb_put(nskb, size);
 
-               head_off = skb_headroom(nskb) - skb_headroom(skb);
-               skb_headers_offset_update(nskb, head_off);
-
-               /* Allocate paged area of new skb */
-               off = size;
-               len = skb->len - off;
-
-               for (i = 0; i < MAX_SKB_FRAGS && off < skb->len; i++) {
-                       size = min_t(u32, len, PAGE_SIZE);
-                       truesize = size;
-
-                       page = page_pool_dev_alloc(rq->page_pool, &page_offset,
-                                                  &truesize);
-                       if (!page) {
-                               consume_skb(nskb);
-                               goto drop;
-                       }
-
-                       skb_add_rx_frag(nskb, i, page, page_offset, size,
-                                       truesize);
-                       if (skb_copy_bits(skb, off,
-                                         page_address(page) + page_offset,
-                                         size)) {
-                               consume_skb(nskb);
-                               goto drop;
-                       }
-
-                       len -= size;
-                       off += size;
-               }
-
-               consume_skb(skb);
-               skb = nskb;
+               skb = *pskb;
        }
 
        /* SKB "head" area always have tailroom for skb_shared_info */
index def3d8689c3ddf77597843b1b9a249c7b38e8a19..696e7680656f5364a4f874770fbe53063b319bb0 100644 (file)
@@ -3446,6 +3446,8 @@ static inline void skb_frag_ref(struct sk_buff *skb, int f)
        __skb_frag_ref(&skb_shinfo(skb)->frags[f]);
 }
 
+int skb_pp_cow_data(struct page_pool *pool, struct sk_buff **pskb,
+                   unsigned int headroom);
 int skb_cow_data_for_xdp(struct page_pool *pool, struct sk_buff **pskb,
                         struct bpf_prog *prog);
 bool napi_pp_put_page(struct page *page, bool napi_safe);
index bdb94749f05dfc72e6d9d6cb9904e69c365153f0..0d9a489e6ae1805c397ea70e0596e4fb7c990aa7 100644 (file)
@@ -895,8 +895,8 @@ static bool is_pp_page(struct page *page)
        return (page->pp_magic & ~0x3UL) == PP_SIGNATURE;
 }
 
-static int skb_pp_cow_data(struct page_pool *pool, struct sk_buff **pskb,
-                          unsigned int headroom)
+int skb_pp_cow_data(struct page_pool *pool, struct sk_buff **pskb,
+                   unsigned int headroom)
 {
 #if IS_ENABLED(CONFIG_PAGE_POOL)
        u32 size, truesize, len, max_head_size, off;
@@ -975,6 +975,7 @@ static int skb_pp_cow_data(struct page_pool *pool, struct sk_buff **pskb,
        return -EOPNOTSUPP;
 #endif
 }
+EXPORT_SYMBOL(skb_pp_cow_data);
 
 int skb_cow_data_for_xdp(struct page_pool *pool, struct sk_buff **pskb,
                         struct bpf_prog *prog)