This commit separates the function receive_mergeable(),
put the logic of appending frag to the skb as an independent function.
The subsequent commit will reuse it.

Signed-off-by: Xuan Zhuo <xuanz...@linux.alibaba.com>
---
 drivers/net/virtio/main.c       | 77 ++++++++++++++++++++-------------
 drivers/net/virtio/virtio_net.h |  4 ++
 2 files changed, 51 insertions(+), 30 deletions(-)

diff --git a/drivers/net/virtio/main.c b/drivers/net/virtio/main.c
index e64d52e7d95b..3ea75c62b384 100644
--- a/drivers/net/virtio/main.c
+++ b/drivers/net/virtio/main.c
@@ -1405,6 +1405,49 @@ static struct sk_buff *receive_mergeable_xdp(struct 
net_device *dev,
        return NULL;
 }
 
+struct sk_buff *virtnet_skb_append_frag(struct sk_buff *head_skb,
+                                       struct sk_buff *curr_skb,
+                                       struct page *page, void *buf,
+                                       int len, int truesize)
+{
+       int num_skb_frags;
+       int offset;
+
+       num_skb_frags = skb_shinfo(curr_skb)->nr_frags;
+       if (unlikely(num_skb_frags == MAX_SKB_FRAGS)) {
+               struct sk_buff *nskb = alloc_skb(0, GFP_ATOMIC);
+
+               if (unlikely(!nskb))
+                       return NULL;
+
+               if (curr_skb == head_skb)
+                       skb_shinfo(curr_skb)->frag_list = nskb;
+               else
+                       curr_skb->next = nskb;
+               curr_skb = nskb;
+               head_skb->truesize += nskb->truesize;
+               num_skb_frags = 0;
+       }
+
+       if (curr_skb != head_skb) {
+               head_skb->data_len += len;
+               head_skb->len += len;
+               head_skb->truesize += truesize;
+       }
+
+       offset = buf - page_address(page);
+       if (skb_can_coalesce(curr_skb, num_skb_frags, page, offset)) {
+               put_page(page);
+               skb_coalesce_rx_frag(curr_skb, num_skb_frags - 1,
+                                    len, truesize);
+       } else {
+               skb_add_rx_frag(curr_skb, num_skb_frags, page,
+                               offset, len, truesize);
+       }
+
+       return curr_skb;
+}
+
 static struct sk_buff *receive_mergeable(struct net_device *dev,
                                         struct virtnet_info *vi,
                                         struct virtnet_rq *rq,
@@ -1454,8 +1497,6 @@ static struct sk_buff *receive_mergeable(struct 
net_device *dev,
        if (unlikely(!curr_skb))
                goto err_skb;
        while (--num_buf) {
-               int num_skb_frags;
-
                buf = virtnet_rq_get_buf(rq, &len, &ctx);
                if (unlikely(!buf)) {
                        pr_debug("%s: rx error: %d buffers out of %d missing\n",
@@ -1480,34 +1521,10 @@ static struct sk_buff *receive_mergeable(struct 
net_device *dev,
                        goto err_skb;
                }
 
-               num_skb_frags = skb_shinfo(curr_skb)->nr_frags;
-               if (unlikely(num_skb_frags == MAX_SKB_FRAGS)) {
-                       struct sk_buff *nskb = alloc_skb(0, GFP_ATOMIC);
-
-                       if (unlikely(!nskb))
-                               goto err_skb;
-                       if (curr_skb == head_skb)
-                               skb_shinfo(curr_skb)->frag_list = nskb;
-                       else
-                               curr_skb->next = nskb;
-                       curr_skb = nskb;
-                       head_skb->truesize += nskb->truesize;
-                       num_skb_frags = 0;
-               }
-               if (curr_skb != head_skb) {
-                       head_skb->data_len += len;
-                       head_skb->len += len;
-                       head_skb->truesize += truesize;
-               }
-               offset = buf - page_address(page);
-               if (skb_can_coalesce(curr_skb, num_skb_frags, page, offset)) {
-                       put_page(page);
-                       skb_coalesce_rx_frag(curr_skb, num_skb_frags - 1,
-                                            len, truesize);
-               } else {
-                       skb_add_rx_frag(curr_skb, num_skb_frags, page,
-                                       offset, len, truesize);
-               }
+               curr_skb  = virtnet_skb_append_frag(head_skb, curr_skb, page,
+                                                   buf, len, truesize);
+               if (!curr_skb)
+                       goto err_skb;
        }
 
        ewma_pkt_len_add(&rq->mrg_avg_pkt_len, head_skb->len);
diff --git a/drivers/net/virtio/virtio_net.h b/drivers/net/virtio/virtio_net.h
index 480b533bd61e..1ca92eea8203 100644
--- a/drivers/net/virtio/virtio_net.h
+++ b/drivers/net/virtio/virtio_net.h
@@ -339,4 +339,8 @@ void virtnet_rq_free_unused_bufs(struct virtqueue *vq);
 void virtnet_check_sq_full_and_disable(struct virtnet_info *vi,
                                       struct net_device *dev,
                                       struct virtnet_sq *sq);
+struct sk_buff *virtnet_skb_append_frag(struct sk_buff *head_skb,
+                                       struct sk_buff *curr_skb,
+                                       struct page *page, void *buf,
+                                       int len, int truesize);
 #endif
-- 
2.32.0.3.g01195cf9f


Reply via email to