diff options
author | David Lebrun <dlebrun@google.com> | 2018-03-29 12:59:36 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-03-30 14:14:33 -0400 |
commit | 5807b22c9164a21cd1077a9bc587f0bba361f72d (patch) | |
tree | 094028b3af4651eff263ba249e34946b24fbe0b7 /net | |
parent | f97c3dc3c0e8d23a5c4357d182afeef4c67f5c33 (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.c | 16 |
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 | ||