From 37824758ff7838f77bc821a0440d63644b22b0c5 Mon Sep 17 00:00:00 2001 From: Ilan Tayari Date: Sat, 8 Apr 2017 02:07:08 +0300 Subject: [PATCH] gso: Support frag_list splitting with head_frag A driver may use build_skb() for received packets. These SKBs then have a head_frag. Since commit 6ea616cbc94c ("net: make GRO aware of skb->head_frag"), GRO may build frag_list SKBs out of head_frag received SKBs. In such a case, the chained SKBs end up with a head_frag. Commit 32fc9df3b6ee ("gso: Support partial splitting at the frag_list pointer") adds partial segmentation of frag_list SKB chains into individual SKBs. However, this is not done if the chained SKBs have any linear part, because the device may not be able to DMA the private linear buffer. A chained frag_list SKB with head_frag is wrongfully detected in this case as having a private linear part and thus falls back to software GSO, while in fact the linear part is backed by a DMA page just like any other frag. This causes low performance when forwarding those packets that were built with build_skb() Allow partial segmentation at the frag_list pointer for chained SKBs with head_frag. Note that such SKBs can only be created by GRO, when applied to received packets with head_frag. Also note that this change only affects the data path that performs the partial segmentation at frag_list pointer, and not any of the other more common data paths. Signed-off-by: Ilan Tayari Signed-off-by: David S. Miller --- net/core/skbuff.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 9f781092fda9c..5d9a11eafbf56 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -3093,7 +3093,7 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb, * containing the same amount of data. */ skb_walk_frags(head_skb, iter) { - if (skb_headlen(iter)) + if (skb_headlen(iter) && !iter->head_frag) goto normal; len -= iter->len; -- 2.39.5