Currently, we have repeated code to check the received mergeable buffer's
length with allocated size. This commit creates a helper to do that and
converts current code to use it.

Signed-off-by: Bui Quang Minh <minhquangbu...@gmail.com>
---
 drivers/net/virtio_net.c | 68 +++++++++++++++++-----------------------
 1 file changed, 29 insertions(+), 39 deletions(-)

diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 6f9fedad4a5e..844cb2a78be0 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -778,6 +778,26 @@ static unsigned int mergeable_ctx_to_truesize(void 
*mrg_ctx)
        return (unsigned long)mrg_ctx & ((1 << MRG_CTX_HEADER_SHIFT) - 1);
 }
 
+static int check_mergeable_len(struct net_device *dev, void *mrg_ctx,
+                              unsigned int len)
+{
+       unsigned int headroom, tailroom, room, truesize;
+
+       truesize = mergeable_ctx_to_truesize(mrg_ctx);
+       headroom = mergeable_ctx_to_headroom(mrg_ctx);
+       tailroom = headroom ? sizeof(struct skb_shared_info) : 0;
+       room = SKB_DATA_ALIGN(headroom + tailroom);
+
+       if (len > truesize - room) {
+               pr_debug("%s: rx error: len %u exceeds truesize %lu\n",
+                        dev->name, len, (unsigned long)(truesize - room));
+               DEV_STATS_INC(dev, rx_length_errors);
+               return -1;
+       }
+
+       return 0;
+}
+
 static struct sk_buff *virtnet_build_skb(void *buf, unsigned int buflen,
                                         unsigned int headroom,
                                         unsigned int len)
@@ -1819,8 +1839,7 @@ static struct page *xdp_linearize_page(struct net_device 
*dev,
        page_off += *len;
 
        while (--*num_buf) {
-               unsigned int headroom, tailroom, room;
-               unsigned int truesize, buflen;
+               unsigned int buflen;
                void *buf;
                void *ctx;
                int off;
@@ -1832,17 +1851,8 @@ static struct page *xdp_linearize_page(struct net_device 
*dev,
                p = virt_to_head_page(buf);
                off = buf - page_address(p);
 
-               truesize = mergeable_ctx_to_truesize(ctx);
-               headroom = mergeable_ctx_to_headroom(ctx);
-               tailroom = headroom ? sizeof(struct skb_shared_info) : 0;
-               room = SKB_DATA_ALIGN(headroom + tailroom);
-
-               if (unlikely(buflen > truesize - room)) {
+               if (check_mergeable_len(dev, ctx, buflen)) {
                        put_page(p);
-                       pr_debug("%s: rx error: len %u exceeds truesize %lu\n",
-                                dev->name, buflen,
-                                (unsigned long)(truesize - room));
-                       DEV_STATS_INC(dev, rx_length_errors);
                        goto err_buf;
                }
 
@@ -2143,7 +2153,6 @@ static int virtnet_build_xdp_buff_mrg(struct net_device 
*dev,
                                      struct virtnet_rq_stats *stats)
 {
        struct virtio_net_hdr_mrg_rxbuf *hdr = buf;
-       unsigned int headroom, tailroom, room;
        struct skb_shared_info *shinfo;
        unsigned int xdp_frags_truesz = 0;
        unsigned int truesize;
@@ -2189,20 +2198,14 @@ static int virtnet_build_xdp_buff_mrg(struct net_device 
*dev,
                page = virt_to_head_page(buf);
                offset = buf - page_address(page);
 
-               truesize = mergeable_ctx_to_truesize(ctx);
-               headroom = mergeable_ctx_to_headroom(ctx);
-               tailroom = headroom ? sizeof(struct skb_shared_info) : 0;
-               room = SKB_DATA_ALIGN(headroom + tailroom);
-
-               xdp_frags_truesz += truesize;
-               if (unlikely(len > truesize - room)) {
+               if (check_mergeable_len(dev, ctx, len)) {
                        put_page(page);
-                       pr_debug("%s: rx error: len %u exceeds truesize %lu\n",
-                                dev->name, len, (unsigned long)(truesize - 
room));
-                       DEV_STATS_INC(dev, rx_length_errors);
                        goto err;
                }
 
+               truesize = mergeable_ctx_to_truesize(ctx);
+               xdp_frags_truesz += truesize;
+
                frag = &shinfo->frags[shinfo->nr_frags++];
                skb_frag_fill_page_desc(frag, page, offset, len);
                if (page_is_pfmemalloc(page))
@@ -2416,18 +2419,12 @@ static struct sk_buff *receive_mergeable(struct 
net_device *dev,
        struct sk_buff *head_skb, *curr_skb;
        unsigned int truesize = mergeable_ctx_to_truesize(ctx);
        unsigned int headroom = mergeable_ctx_to_headroom(ctx);
-       unsigned int tailroom = headroom ? sizeof(struct skb_shared_info) : 0;
-       unsigned int room = SKB_DATA_ALIGN(headroom + tailroom);
 
        head_skb = NULL;
        u64_stats_add(&stats->bytes, len - vi->hdr_len);
 
-       if (unlikely(len > truesize - room)) {
-               pr_debug("%s: rx error: len %u exceeds truesize %lu\n",
-                        dev->name, len, (unsigned long)(truesize - room));
-               DEV_STATS_INC(dev, rx_length_errors);
+       if (check_mergeable_len(dev, ctx, len))
                goto err_skb;
-       }
 
        if (unlikely(vi->xdp_enabled)) {
                struct bpf_prog *xdp_prog;
@@ -2462,17 +2459,10 @@ static struct sk_buff *receive_mergeable(struct 
net_device *dev,
                u64_stats_add(&stats->bytes, len);
                page = virt_to_head_page(buf);
 
-               truesize = mergeable_ctx_to_truesize(ctx);
-               headroom = mergeable_ctx_to_headroom(ctx);
-               tailroom = headroom ? sizeof(struct skb_shared_info) : 0;
-               room = SKB_DATA_ALIGN(headroom + tailroom);
-               if (unlikely(len > truesize - room)) {
-                       pr_debug("%s: rx error: len %u exceeds truesize %lu\n",
-                                dev->name, len, (unsigned long)(truesize - 
room));
-                       DEV_STATS_INC(dev, rx_length_errors);
+               if (check_mergeable_len(dev, ctx, len))
                        goto err_skb;
-               }
 
+               truesize = mergeable_ctx_to_truesize(ctx);
                curr_skb  = virtnet_skb_append_frag(head_skb, curr_skb, page,
                                                    buf, len, truesize);
                if (!curr_skb)
-- 
2.43.0


Reply via email to