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: 6c8702c60b
("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>
This commit is contained in:
Родитель
f97c3dc3c0
Коммит
5807b22c91
|
@ -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)
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче