aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid Lebrun <dlebrun@google.com>2018-03-29 12:59:36 -0400
committerDavid S. Miller <davem@davemloft.net>2018-03-30 14:14:33 -0400
commit5807b22c9164a21cd1077a9bc587f0bba361f72d (patch)
tree094028b3af4651eff263ba249e34946b24fbe0b7 /net
parentf97c3dc3c0e8d23a5c4357d182afeef4c67f5c33 (diff)
ipv6: sr: fix seg6 encap performances with TSO enabled
Enabling TSO can lead to abysmal performances when using seg6 in encap mode, such as with the ixgbe driver. This patch adds a call to iptunnel_handle_offloads() to remove the encapsulation bit if needed. Before: root@comp4-seg6bpf:~# iperf3 -c fc00::55 Connecting to host fc00::55, port 5201 [ 4] local fc45::4 port 36592 connected to fc00::55 port 5201 [ ID] Interval Transfer Bandwidth Retr Cwnd [ 4] 0.00-1.00 sec 196 KBytes 1.60 Mbits/sec 47 6.66 KBytes [ 4] 1.00-2.00 sec 304 KBytes 2.49 Mbits/sec 100 5.33 KBytes [ 4] 2.00-3.00 sec 284 KBytes 2.32 Mbits/sec 92 5.33 KBytes After: root@comp4-seg6bpf:~# iperf3 -c fc00::55 Connecting to host fc00::55, port 5201 [ 4] local fc45::4 port 43062 connected to fc00::55 port 5201 [ ID] Interval Transfer Bandwidth Retr Cwnd [ 4] 0.00-1.00 sec 1.03 GBytes 8.89 Gbits/sec 0 743 KBytes [ 4] 1.00-2.00 sec 1.03 GBytes 8.87 Gbits/sec 0 743 KBytes [ 4] 2.00-3.00 sec 1.03 GBytes 8.87 Gbits/sec 0 743 KBytes Reported-by: Tom Herbert <tom@quantonium.net> Fixes: 6c8702c60b88 ("ipv6: sr: add support for SRH encapsulation and injection with lwtunnels") Signed-off-by: David Lebrun <dlebrun@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/ipv6/seg6_iptunnel.c16
1 files changed, 7 insertions, 9 deletions
diff --git a/net/ipv6/seg6_iptunnel.c b/net/ipv6/seg6_iptunnel.c
index 7a78dcfda68a..f343e6f0fc95 100644
--- a/net/ipv6/seg6_iptunnel.c
+++ b/net/ipv6/seg6_iptunnel.c
@@ -16,6 +16,7 @@
16#include <linux/net.h> 16#include <linux/net.h>
17#include <linux/module.h> 17#include <linux/module.h>
18#include <net/ip.h> 18#include <net/ip.h>
19#include <net/ip_tunnels.h>
19#include <net/lwtunnel.h> 20#include <net/lwtunnel.h>
20#include <net/netevent.h> 21#include <net/netevent.h>
21#include <net/netns/generic.h> 22#include <net/netns/generic.h>
@@ -211,11 +212,6 @@ static int seg6_do_srh(struct sk_buff *skb)
211 212
212 tinfo = seg6_encap_lwtunnel(dst->lwtstate); 213 tinfo = seg6_encap_lwtunnel(dst->lwtstate);
213 214
214 if (likely(!skb->encapsulation)) {
215 skb_reset_inner_headers(skb);
216 skb->encapsulation = 1;
217 }
218
219 switch (tinfo->mode) { 215 switch (tinfo->mode) {
220 case SEG6_IPTUN_MODE_INLINE: 216 case SEG6_IPTUN_MODE_INLINE:
221 if (skb->protocol != htons(ETH_P_IPV6)) 217 if (skb->protocol != htons(ETH_P_IPV6))
@@ -224,10 +220,12 @@ static int seg6_do_srh(struct sk_buff *skb)
224 err = seg6_do_srh_inline(skb, tinfo->srh); 220 err = seg6_do_srh_inline(skb, tinfo->srh);
225 if (err) 221 if (err)
226 return err; 222 return err;
227
228 skb_reset_inner_headers(skb);
229 break; 223 break;
230 case SEG6_IPTUN_MODE_ENCAP: 224 case SEG6_IPTUN_MODE_ENCAP:
225 err = iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6);
226 if (err)
227 return err;
228
231 if (skb->protocol == htons(ETH_P_IPV6)) 229 if (skb->protocol == htons(ETH_P_IPV6))
232 proto = IPPROTO_IPV6; 230 proto = IPPROTO_IPV6;
233 else if (skb->protocol == htons(ETH_P_IP)) 231 else if (skb->protocol == htons(ETH_P_IP))
@@ -239,6 +237,8 @@ static int seg6_do_srh(struct sk_buff *skb)
239 if (err) 237 if (err)
240 return err; 238 return err;
241 239
240 skb_set_inner_transport_header(skb, skb_transport_offset(skb));
241 skb_set_inner_protocol(skb, skb->protocol);
242 skb->protocol = htons(ETH_P_IPV6); 242 skb->protocol = htons(ETH_P_IPV6);
243 break; 243 break;
244 case SEG6_IPTUN_MODE_L2ENCAP: 244 case SEG6_IPTUN_MODE_L2ENCAP:
@@ -262,8 +262,6 @@ static int seg6_do_srh(struct sk_buff *skb)
262 ipv6_hdr(skb)->payload_len = htons(skb->len - sizeof(struct ipv6hdr)); 262 ipv6_hdr(skb)->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
263 skb_set_transport_header(skb, sizeof(struct ipv6hdr)); 263 skb_set_transport_header(skb, sizeof(struct ipv6hdr));
264 264
265 skb_set_inner_protocol(skb, skb->protocol);
266
267 return 0; 265 return 0;
268} 266}
269 267