Commit 5807b22c authored by David Lebrun's avatar David Lebrun Committed by David S. Miller

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: default avatarTom Herbert <tom@quantonium.net>
Fixes: 6c8702c6 ("ipv6: sr: add support for SRH encapsulation and injection with lwtunnels")
Signed-off-by: default avatarDavid Lebrun <dlebrun@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f97c3dc3
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include <linux/net.h> #include <linux/net.h>
#include <linux/module.h> #include <linux/module.h>
#include <net/ip.h> #include <net/ip.h>
#include <net/ip_tunnels.h>
#include <net/lwtunnel.h> #include <net/lwtunnel.h>
#include <net/netevent.h> #include <net/netevent.h>
#include <net/netns/generic.h> #include <net/netns/generic.h>
...@@ -211,11 +212,6 @@ static int seg6_do_srh(struct sk_buff *skb) ...@@ -211,11 +212,6 @@ static int seg6_do_srh(struct sk_buff *skb)
tinfo = seg6_encap_lwtunnel(dst->lwtstate); tinfo = seg6_encap_lwtunnel(dst->lwtstate);
if (likely(!skb->encapsulation)) {
skb_reset_inner_headers(skb);
skb->encapsulation = 1;
}
switch (tinfo->mode) { switch (tinfo->mode) {
case SEG6_IPTUN_MODE_INLINE: case SEG6_IPTUN_MODE_INLINE:
if (skb->protocol != htons(ETH_P_IPV6)) if (skb->protocol != htons(ETH_P_IPV6))
...@@ -224,10 +220,12 @@ static int seg6_do_srh(struct sk_buff *skb) ...@@ -224,10 +220,12 @@ static int seg6_do_srh(struct sk_buff *skb)
err = seg6_do_srh_inline(skb, tinfo->srh); err = seg6_do_srh_inline(skb, tinfo->srh);
if (err) if (err)
return err; return err;
skb_reset_inner_headers(skb);
break; break;
case SEG6_IPTUN_MODE_ENCAP: case SEG6_IPTUN_MODE_ENCAP:
err = iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6);
if (err)
return err;
if (skb->protocol == htons(ETH_P_IPV6)) if (skb->protocol == htons(ETH_P_IPV6))
proto = IPPROTO_IPV6; proto = IPPROTO_IPV6;
else if (skb->protocol == htons(ETH_P_IP)) else if (skb->protocol == htons(ETH_P_IP))
...@@ -239,6 +237,8 @@ static int seg6_do_srh(struct sk_buff *skb) ...@@ -239,6 +237,8 @@ static int seg6_do_srh(struct sk_buff *skb)
if (err) if (err)
return err; return err;
skb_set_inner_transport_header(skb, skb_transport_offset(skb));
skb_set_inner_protocol(skb, skb->protocol);
skb->protocol = htons(ETH_P_IPV6); skb->protocol = htons(ETH_P_IPV6);
break; break;
case SEG6_IPTUN_MODE_L2ENCAP: case SEG6_IPTUN_MODE_L2ENCAP:
...@@ -262,8 +262,6 @@ static int seg6_do_srh(struct sk_buff *skb) ...@@ -262,8 +262,6 @@ static int seg6_do_srh(struct sk_buff *skb)
ipv6_hdr(skb)->payload_len = htons(skb->len - sizeof(struct ipv6hdr)); ipv6_hdr(skb)->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
skb_set_transport_header(skb, sizeof(struct ipv6hdr)); skb_set_transport_header(skb, sizeof(struct ipv6hdr));
skb_set_inner_protocol(skb, skb->protocol);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment