Series short description
Subsystems (3)
v3 cover Series short description
This patch set addresses a number of issues I found while sorting out enabling UDP GSO Segmentation support for ixgbe/ixgbevf. Specifically there were a number of issues related to the checksum and such that seemed to cause either minor irregularities or kernel panics in the case of the offload request being allowed to traverse between name spaces.
With this set applied I am was able to get UDP GSO traffic to pass over vxlan tunnels in both offloaded modes and non-offloaded modes for ixgbe and ixgbevf.
I submitted the driver specific patches earlier as an RFC:
https://patchwork.ozlabs.org/project/netdev/list/?series=42477&archive=both&state=*
v2: Updated patches based on feedback from Eric Dumazet
Split first patch into several patches based on feedback from Eric
v3: Drop patch that was calling pskb_may_pull as it was redundant.
Added code to use MANGLED_0 in case of UDP checksum
Drop patch adding NETIF_F_GSO_UDP_L4 to list of GSO software offloads Added Acked-by for patches reviewed by Willem and not changed
---
Alexander Duyck (6):
udp: Record gso_segs when supporting UDP segmentation offload
udp: Do not pass MSS as parameter to GSO segmentation
udp: Do not pass checksum as a parameter to GSO segmentation
udp: Partially unroll handling of first segment and last segment
udp: Add support for software checksum and GSO_PARTIAL with GSO offload
udp: Do not copy destructor if one is not present
include/net/udp.h | 3 +- net/ipv4/udp.c | 2 + net/ipv4/udp_offload.c | 94 +++++++++++++++++++++++++++++++----------------- net/ipv6/udp_offload.c | 16 +------- 4 files changed, 64 insertions(+), 51 deletions(-)
PATCH v3 1/6 udp: Record gso_segs when supporting UDP segmentation offload
From: Alexander Duyck <[email protected]>
We need to record the number of segments that will be generated when this frame is segmented. The expectation is that if gso_size is set then gso_segs is set as well. Without this some drivers such as ixgbe get confused if they attempt to offload this as they record 0 segments for the entire packet instead of the correct value.
--- net/ipv4/udp.c | 2 ++ 1 file changed, 2 insertions(+)
net/ipv4/udp.c +2 -0
@@ -793,6 +793,8 @@ static int udp_send_skb(struct sk_buff *skb, struct flowi4 *fl4,skb_shinfo (skb)->gso_size = cork->gso_size;skb_shinfo (skb)->gso_type =SKB_GSO_UDP_L4 ; +skb_shinfo (skb)->gso_segs =DIV_ROUND_UP (len -sizeof (uh), + cork->gso_size); goto csum_partial; }
PATCH v3 2/6 udp: Do not pass MSS as parameter to GSO segmentation
In reply to Alexander DuyckFrom: Alexander Duyck <[email protected]>
There is no point in passing MSS as a parameter for for the GSO segmentation call as it is already available via the shared info for the skb itself.
--- include/net/udp.h | 2 +- net/ipv4/udp_offload.c | 6 ++++-- net/ipv6/udp_offload.c | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-)
include/net/udp.h +1 -1
@@ -176,7 +176,7 @@ struct sk_buff **udp_gro_receive(struct sk_buff **head, struct sk_buff *skb,struct sk_buff *__udp_gso_segment (struct sk_buff *gso_skb,netdev_features_t features, -unsigned int mss,__sum16 check); +__sum16 check);static inline struct udphdr *udp_gro_udphdr (struct sk_buff *skb) {
net/ipv4/udp_offload.c +4 -2
@@ -189,14 +189,16 @@ struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb,struct sk_buff *__udp_gso_segment (struct sk_buff *gso_skb,netdev_features_t features, -unsigned int mss,__sum16 check) +__sum16 check) {struct sock *sk = gso_skb->sk;unsigned int sum_truesize =0 ;struct sk_buff *segs, *seg;unsigned int hdrlen;struct udphdr *uh; +unsigned int mss; + mss =skb_shinfo (gso_skb)->gso_size;if (gso_skb->len <=sizeof (*uh) + mss)return ERR_PTR (-EINVAL );
@@ -244,7 +246,7 @@ static struct sk_buff *__udp4_gso_segment(struct sk_buff *gso_skb,if (!can_checksum_protocol (features,htons (ETH_P_IP )))return ERR_PTR (-EIO ); -return __udp_gso_segment (gso_skb, features, mss, +return __udp_gso_segment (gso_skb, features,udp_v4_check (sizeof (struct udphdr ) + mss, iph->saddr, iph->daddr,0 )); }
net/ipv6/udp_offload.c +1 -1
@@ -26,7 +26,7 @@ static struct sk_buff *__udp6_gso_segment(struct sk_buff *gso_skb,if (!can_checksum_protocol (features,htons (ETH_P_IPV6 )))return ERR_PTR (-EIO ); -return __udp_gso_segment (gso_skb, features, mss, +return __udp_gso_segment (gso_skb, features,udp_v6_check (sizeof (struct udphdr ) + mss, &ip6h->saddr, &ip6h->daddr,0 )); }
PATCH v3 3/6 udp: Do not pass checksum as a parameter to GSO segmentation
In reply to Alexander DuyckFrom: Alexander Duyck <[email protected]>
This patch is meant to allow us to avoid having to recompute the checksum from scratch and have it passed as a parameter.
Instead of taking that approach we can take advantage of the fact that the length that was used to compute the existing checksum is included in the UDP header.
Finally to avoid the need to invert the result we can just call csum16_add and csum16_sub directly. By doing this we can avoid a number of instructions in the loop that is handling segmentation.
--- include/net/udp.h | 3 +-- net/ipv4/udp_offload.c | 32 ++++++++++++++++++-------------- net/ipv6/udp_offload.c | 7 +------ 3 files changed, 20 insertions(+), 22 deletions(-)
include/net/udp.h +1 -2
@@ -175,8 +175,7 @@ struct sk_buff **udp_gro_receive(struct sk_buff **head, struct sk_buff *skb,int udp_gro_complete (struct sk_buff *skb,int nhoff,udp_lookup_t lookup);struct sk_buff *__udp_gso_segment (struct sk_buff *gso_skb, -netdev_features_t features, -__sum16 check); +netdev_features_t features);static inline struct udphdr *udp_gro_udphdr (struct sk_buff *skb) {
net/ipv4/udp_offload.c +18 -14
@@ -188,8 +188,7 @@ struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb,EXPORT_SYMBOL (skb_udp_tunnel_segment);struct sk_buff *__udp_gso_segment (struct sk_buff *gso_skb, -netdev_features_t features, -__sum16 check) +netdev_features_t features) {struct sock *sk = gso_skb->sk;unsigned int sum_truesize =0 ;
@@ -197,6 +196,8 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,unsigned int hdrlen;struct udphdr *uh;unsigned int mss; +__sum16 check; +__be16 newlen; mss =skb_shinfo (gso_skb)->gso_size;if (gso_skb->len <=sizeof (*uh) + mss)
@@ -215,17 +216,25 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,return segs; } + uh =udp_hdr (segs); + +/* compute checksum adjustment based on old length versus new */ + newlen =htons (sizeof (*uh) + mss); + check =csum16_add (csum16_sub (uh->check, uh->len), newlen); +for (seg = segs; seg; seg = seg->next) { uh =udp_hdr (seg); - uh->len =htons (seg->len - hdrlen); - uh->check = check;/* last packet can be partial gso_size */ -if (!seg->next) -csum_replace2 (&uh->check,htons (mss), -htons (seg->len - hdrlen -sizeof (*uh))); +if (!seg->next) { + newlen =htons (seg->len - hdrlen); + check =csum16_add (csum16_sub (uh->check, uh->len), + newlen); + } + + uh->len = newlen; + uh->check = check; - uh->check = ~uh->check; seg->destructor = sock_wfree; seg->sk = sk; sum_truesize += seg->truesize;
@@ -240,15 +249,10 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,static struct sk_buff *__udp4_gso_segment (struct sk_buff *gso_skb,netdev_features_t features) { -const struct iphdr *iph =ip_hdr (gso_skb); -unsigned int mss =skb_shinfo (gso_skb)->gso_size; -if (!can_checksum_protocol (features,htons (ETH_P_IP )))return ERR_PTR (-EIO ); -return __udp_gso_segment (gso_skb, features, -udp_v4_check (sizeof (struct udphdr ) + mss, - iph->saddr, iph->daddr,0 )); +return __udp_gso_segment (gso_skb, features); } static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb,
net/ipv6/udp_offload.c +1 -6
@@ -20,15 +20,10 @@static struct sk_buff *__udp6_gso_segment (struct sk_buff *gso_skb,netdev_features_t features) { -const struct ipv6hdr *ip6h =ipv6_hdr (gso_skb); -unsigned int mss =skb_shinfo (gso_skb)->gso_size; -if (!can_checksum_protocol (features,htons (ETH_P_IPV6 )))return ERR_PTR (-EIO ); -return __udp_gso_segment (gso_skb, features, -udp_v6_check (sizeof (struct udphdr ) + mss, - &ip6h->saddr, &ip6h->daddr,0 )); +return __udp_gso_segment (gso_skb, features); } static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
Re: [net-next PATCH v3 3/6] udp: Do not pass checksum as a parameter to GSO segmentation
Quoted 9 lines · Alexander Duyck
From: Alexander Duyck <[email protected]>
This patch is meant to allow us to avoid having to recompute the checksum from scratch and have it passed as a parameter.
Instead of taking that approach we can take advantage of the fact that the length that was used to compute the existing checksum is included in the UDP header.
Quoted 5 lines
Finally to avoid the need to invert the result we can just call
csum16_addandcsum16_subdirectly. By doing this we can avoid a number of instructions in the loop that is handling segmentation.Signed-off-by Alexander Duyck <[email protected]>
Small aside: instead of open-coding the csum16 operations, it might make sense to define a pseudo_csum_replace2 function and convert csum_replace2 to call that and only do the inversion.
PATCH v3 4/6 udp: Partially unroll handling of first segment and last segment
In reply to Alexander DuyckFrom: Alexander Duyck <[email protected]>
This patch allows us to take care of unrolling the first segment and the last segment of the loop for processing the segmented skb. Part of the motivation for this is that it makes it easier to process the fact that the first fame and all of the frames in between should be mostly identical in terms of header data, and the last frame has differences in the length and partial checksum.
In addition I am dropping the header length calculation since we don't really need it for anything but the last frame and it can be easily obtained by just pulling the data_len and offset of tail from the transport header.
--- net/ipv4/udp_offload.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-)
net/ipv4/udp_offload.c +19 -14
@@ -193,7 +193,6 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,struct sock *sk = gso_skb->sk;unsigned int sum_truesize =0 ;struct sk_buff *segs, *seg; -unsigned int hdrlen;struct udphdr *uh;unsigned int mss;__sum16 check;
@@ -203,7 +202,6 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,if (gso_skb->len <=sizeof (*uh) + mss)return ERR_PTR (-EINVAL ); - hdrlen = gso_skb->data -skb_mac_header (gso_skb);skb_pull (gso_skb,sizeof (*uh));/* clear destructor to avoid skb_segment assigning it to tail */
@@ -216,30 +214,37 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,return segs; } - uh =udp_hdr (segs); + seg = segs; + uh =udp_hdr (seg);/* compute checksum adjustment based on old length versus new */ newlen =htons (sizeof (*uh) + mss); check =csum16_add (csum16_sub (uh->check, uh->len), newlen); -for (seg = segs; seg; seg = seg->next) { - uh =udp_hdr (seg); +for (;;) { + seg->destructor = sock_wfree; + seg->sk = sk; + sum_truesize += seg->truesize; -/* last packet can be partial gso_size */ -if (!seg->next) { - newlen =htons (seg->len - hdrlen); - check =csum16_add (csum16_sub (uh->check, uh->len), - newlen); - } +if (!seg->next) +break ; uh->len = newlen; uh->check = check; - seg->destructor = sock_wfree; - seg->sk = sk; - sum_truesize += seg->truesize; + seg = seg->next; + uh =udp_hdr (seg); } +/* last packet can be partial gso_size, account for that in checksum */ + newlen =htons (skb_tail_pointer (seg) -skb_transport_header (seg) + + seg->data_len); + check =csum16_add (csum16_sub (uh->check, uh->len), newlen); + + uh->len = newlen; + uh->check = check; + +/* update refcount for the packet */ refcount_add (sum_truesize - gso_skb->truesize, &sk->sk_wmem_alloc);return segs;
Re: [net-next PATCH v3 4/6] udp: Partially unroll handling of first segment and last segment
Quoted 9 lines · Alexander Duyck
From: Alexander Duyck <[email protected]>
This patch allows us to take care of unrolling the first segment and the last segment of the loop for processing the segmented skb. Part of the motivation for this is that it makes it easier to process the fact that the first fame and all of the frames in between should be mostly identical in terms of header data, and the last frame has differences in the length and partial checksum.
Quoted 6 lines
In addition I am dropping the header length calculation since we don't really need it for anything but the last frame and it can be easily obtained by just pulling the
data_lenand offset of tail from the transport header.Signed-off-by Alexander Duyck <[email protected]>
Willem de Bruijn
maintainerRe: [net-next PATCH v3 4/6] udp: Partially unroll handling of first segment and last segment
In reply to Alexander DuyckQuoted 9 lines · Alexander Duyck
From: Alexander Duyck <[email protected]>
This patch allows us to take care of unrolling the first segment and the last segment of the loop for processing the segmented skb. Part of the motivation for this is that it makes it easier to process the fact that the first fame and all of the frames in between should be mostly identical in terms of header data, and the last frame has differences in the length and partial checksum.
Quoted 6 lines
In addition I am dropping the header length calculation since we don't really need it for anything but the last frame and it can be easily obtained by just pulling the
data_lenand offset of tail from the transport header.Signed-off-by Alexander Duyck <[email protected]>
I'm not a fan of the more complicated control flow, as I pointed out before. It only seems to save one assignment to uh from segs.
Both follow-up patches are now more complex, because they need to add the same code in two locations.
Willem de Bruijn
maintainerRe: [net-next PATCH v3 4/6] udp: Partially unroll handling of first segment and last segment
Quoted 16 lines · Willem de Bruijn
Quoted 14 lines · Alexander Duyck
From: Alexander Duyck <[email protected]>
This patch allows us to take care of unrolling the first segment and the last segment of the loop for processing the segmented skb. Part of the motivation for this is that it makes it easier to process the fact that the first fame and all of the frames in between should be mostly identical in terms of header data, and the last frame has differences in the length and partial checksum.
In addition I am dropping the header length calculation since we don't really need it for anything but the last frame and it can be easily obtained by just pulling the
data_lenand offset of tail from the transport header.
Quoted 7 lines
Quoted 1 line
Signed-off-by Alexander Duyck <[email protected]>I'm not a fan of the more complicated control flow, as I pointed out before. It only seems to save one assignment to uh from segs.
Both follow-up patches are now more complex, because they need to add the same code in two locations.
With that said, if you feel strongly, I don't object.
The removal of hdrlen and simplification of arguments is definitely an improvement.
Re: [net-next PATCH v3 4/6] udp: Partially unroll handling of first segment and last segment
Quoted 23 lines · Willem de Bruijn
Quoted 21 lines · Willem de Bruijn
Quoted 9 lines · Alexander Duyck
From: Alexander Duyck <[email protected]>
This patch allows us to take care of unrolling the first segment and the last segment of the loop for processing the segmented skb. Part of the motivation for this is that it makes it easier to process the fact that the first fame and all of the frames in between should be mostly identical in terms of header data, and the last frame has differences in the length and partial checksum.
Quoted 6 lines
In addition I am dropping the header length calculation since we don't really need it for anything but the last frame and it can be easily obtained by just pulling the
data_lenand offset of tail from the transport header.Signed-off-by Alexander Duyck <[email protected]>I'm not a fan of the more complicated control flow, as I pointed out before. It only seems to save one assignment to uh from segs.
Quoted 7 lines
Quoted 2 lines
Both follow-up patches are now more complex, because they need to add the same code in two locations.
With that said, if you feel strongly, I don't object.
The removal of hdrlen and simplification of arguments is definitely an improvement.
Thanks for being understanding about this.
My preference is to keep the loop unrolled as it is since that way it is not too different from the way we handle this for TCP so it will maintenance of the two easier. Otherwise I have to add a bunch of conditional checks inside the loop.
The other advantage to unrolling it as I did is that I don't have to deal with a ton of extra indentation for an if statement inside of a while loop.
- Alex
Re: [net-next PATCH v3 4/6] udp: Partially unroll handling of first segment and last segment
Quoted 15 lines · Alexander Duyck
Quoted 13 lines · Willem de Bruijn
Quoted 11 lines · Willem de Bruijn
Quoted 9 lines · Alexander Duyck
From: Alexander Duyck <[email protected]>
This patch allows us to take care of unrolling the first segment and the last segment of the loop for processing the segmented skb. Part of the motivation for this is that it makes it easier to process the fact that the first fame and all of the frames in between should be mostly identical in terms of header data, and the last frame has differences in the length and partial checksum.
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
Quoted 6 lines
In addition I am dropping the header length calculation since we don't really need it for anything but the last frame and it can be easily obtained by just pulling the
data_lenand offset of tail from the transport header.Signed-off-by Alexander Duyck <[email protected]>
Quoted 13 lines
Quoted 10 lines
Quoted 5 lines
I'm not a fan of the more complicated control flow, as I pointed out before. It only seems to save one assignment to uh from segs.
Both follow-up patches are now more complex, because they need to add the same code in two locations.
With that said, if you feel strongly, I don't object.
The removal of hdrlen and simplification of arguments is definitely an improvement.
Thanks for being understanding about this.
Quoted 8 lines
My preference is to keep the loop unrolled as it is since that way it is not too different from the way we handle this for TCP so it will maintenance of the two easier. Otherwise I have to add a bunch of conditional checks inside the loop.
The other advantage to unrolling it as I did is that I don't have to deal with a ton of extra indentation for an if statement inside of a while loop.
Both good reasons. Thanks a lot for the overall cleanup.
PATCH v3 5/6 udp: Add support for software checksum and GSO_PARTIAL with GSO offload
In reply to Alexander DuyckFrom: Alexander Duyck <[email protected]>
This patch adds support for a software provided checksum and GSO_PARTIAL segmentation support. With this we can offload UDP segmentation on devices that only have partial support for tunnels.
Since we are no longer needing the hardware checksum we can drop the checks in the segmentation code that were verifying if it was present.
--- net/ipv4/udp_offload.c | 29 +++++++++++++++++++---------- net/ipv6/udp_offload.c | 11 +---------- 2 files changed, 20 insertions(+), 20 deletions(-)
net/ipv4/udp_offload.c +19 -10
@@ -214,6 +214,13 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,return segs; } +/* GSO partial and frag_list segmentation only requires splitting +* the frame into an MSS multiple and possibly a remainder, both +* cases return a GSO skb. So update the mss now. +*/ +if (skb_is_gso (segs)) + mss *=skb_shinfo (segs)->gso_segs; + seg = segs; uh =udp_hdr (seg);
@@ -232,6 +239,12 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb, uh->len = newlen; uh->check = check; +if (seg->ip_summed ==CHECKSUM_PARTIAL ) +gso_reset_checksum (seg, ~check); +else + uh->check =gso_make_checksum (seg, ~check) ? : +CSUM_MANGLED_0 ; + seg = seg->next; uh =udp_hdr (seg); }
@@ -244,6 +257,11 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb, uh->len = newlen; uh->check = check; +if (seg->ip_summed ==CHECKSUM_PARTIAL ) +gso_reset_checksum (seg, ~check); +else + uh->check =gso_make_checksum (seg, ~check) ? :CSUM_MANGLED_0 ; +/* update refcount for the packet */ refcount_add (sum_truesize - gso_skb->truesize, &sk->sk_wmem_alloc);
@@ -251,15 +269,6 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb, }EXPORT_SYMBOL_GPL (__udp_gso_segment); -static struct sk_buff *__udp4_gso_segment (struct sk_buff *gso_skb, -netdev_features_t features) -{ -if (!can_checksum_protocol (features,htons (ETH_P_IP ))) -return ERR_PTR (-EIO ); - -return __udp_gso_segment (gso_skb, features); -} -static struct sk_buff *udp4_ufo_fragment (struct sk_buff *skb,netdev_features_t features) {
@@ -283,7 +292,7 @@ static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb, goto out;if (skb_shinfo (skb)->gso_type &SKB_GSO_UDP_L4 ) -return __udp4_gso_segment (skb, features); +return __udp_gso_segment (skb, features); mss =skb_shinfo (skb)->gso_size;if (unlikely (skb->len <= mss))
net/ipv6/udp_offload.c +1 -10
@@ -17,15 +17,6 @@#include <net/ip6_checksum.h> #include "ip6_offload.h" -static struct sk_buff *__udp6_gso_segment (struct sk_buff *gso_skb, -netdev_features_t features) -{ -if (!can_checksum_protocol (features,htons (ETH_P_IPV6 ))) -return ERR_PTR (-EIO ); - -return __udp_gso_segment (gso_skb, features); -} -static struct sk_buff *udp6_ufo_fragment (struct sk_buff *skb,netdev_features_t features) {
@@ -58,7 +49,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, goto out;if (skb_shinfo (skb)->gso_type &SKB_GSO_UDP_L4 ) -return __udp6_gso_segment (skb, features); +return __udp_gso_segment (skb, features);/* Do software UFO. Complete and fill in the UDP checksum as HW cannot * do checksum of UDP packets sent as multiple IP fragments.
Re: [net-next PATCH v3 5/6] udp: Add support for software checksum and GSO_PARTIAL with GSO offload
Quoted 10 lines · Alexander Duyck
From: Alexander Duyck <[email protected]>
This patch adds support for a software provided checksum and
GSO_PARTIALsegmentation support. With this we can offload UDP segmentation on devices that only have partial support for tunnels.Since we are no longer needing the hardware checksum we can drop the checks in the segmentation code that were verifying if it was present.
Signed-off-by Alexander Duyck <[email protected]>
PATCH v3 6/6 udp: Do not copy destructor if one is not present
In reply to Alexander DuyckFrom: Alexander Duyck <[email protected]>
This patch makes it so that if a destructor is not present we avoid trying to update the skb socket or any reference counting that would be associated with the NULL socket and/or descriptor. By doing this we can support traffic coming from another namespace without any issues.
--- net/ipv4/udp_offload.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-)
net/ipv4/udp_offload.c +14 -8
@@ -195,6 +195,7 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,struct sk_buff *segs, *seg;struct udphdr *uh;unsigned int mss; +bool copy_dtor;__sum16 check;__be16 newlen;
@@ -205,12 +206,14 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb,skb_pull (gso_skb,sizeof (*uh));/* clear destructor to avoid skb_segment assigning it to tail */ -WARN_ON_ONCE (gso_skb->destructor != sock_wfree); - gso_skb->destructor =NULL ; + copy_dtor = gso_skb->destructor == sock_wfree; +if (copy_dtor) + gso_skb->destructor =NULL ; segs =skb_segment (gso_skb, features);if (unlikely (IS_ERR_OR_NULL (segs))) { - gso_skb->destructor = sock_wfree; +if (copy_dtor) + gso_skb->destructor = sock_wfree;return segs; }
@@ -229,9 +232,11 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb, check =csum16_add (csum16_sub (uh->check, uh->len), newlen);for (;;) { - seg->destructor = sock_wfree; - seg->sk = sk; - sum_truesize += seg->truesize; +if (copy_dtor) { + seg->destructor = sock_wfree; + seg->sk = sk; + sum_truesize += seg->truesize; + }if (!seg->next)break ;
@@ -263,8 +268,9 @@ struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb, uh->check =gso_make_checksum (seg, ~check) ? :CSUM_MANGLED_0 ;/* update refcount for the packet */ -refcount_add (sum_truesize - gso_skb->truesize, &sk->sk_wmem_alloc); - +if (copy_dtor) +refcount_add (sum_truesize - gso_skb->truesize, + &sk->sk_wmem_alloc);return segs; }EXPORT_SYMBOL_GPL (__udp_gso_segment);
Re: [net-next PATCH v3 6/6] udp: Do not copy destructor if one is not present
Quoted 9 lines · Alexander Duyck
From: Alexander Duyck <[email protected]>
This patch makes it so that if a destructor is not present we avoid trying to update the skb socket or any reference counting that would be associated with the NULL socket and/or descriptor. By doing this we can support traffic coming from another namespace without any issues.
Acked-by Willem de Bruijn <[email protected]>Signed-off-by Alexander Duyck <[email protected]>