diff options
author | Eric Dumazet <edumazet@google.com> | 2013-10-19 14:42:57 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-10-19 19:36:19 -0400 |
commit | cb32f511a70be8967ac9025cf49c44324ced9a39 (patch) | |
tree | 9e3fa3245096053bcf67cc61b60a72f3bb946008 | |
parent | 3347c960295583eee3fd58e5c539fb1972fbc005 (diff) |
ipip: add GSO/TSO support
Now inet_gso_segment() is stackable, its relatively easy to
implement GSO/TSO support for IPIP
Performance results, when segmentation is done after tunnel
device (as no NIC is yet enabled for TSO IPIP support) :
Before patch :
lpq83:~# ./netperf -H 7.7.9.84 -Cc
MIGRATED TCP STREAM TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to 7.7.9.84 () port 0 AF_INET
Recv Send Send Utilization Service Demand
Socket Socket Message Elapsed Send Recv Send Recv
Size Size Size Time Throughput local remote local remote
bytes bytes bytes secs. 10^6bits/s % S % S us/KB us/KB
87380 16384 16384 10.00 3357.88 5.09 3.70 2.983 2.167
After patch :
lpq83:~# ./netperf -H 7.7.9.84 -Cc
MIGRATED TCP STREAM TEST from 0.0.0.0 (0.0.0.0) port 0 AF_INET to 7.7.9.84 () port 0 AF_INET
Recv Send Send Utilization Service Demand
Socket Socket Message Elapsed Send Recv Send Recv
Size Size Size Time Throughput local remote local remote
bytes bytes bytes secs. 10^6bits/s % S % S us/KB us/KB
87380 16384 16384 10.00 7710.19 4.52 6.62 1.152 1.687
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/linux/netdev_features.h | 2 | ||||
-rw-r--r-- | include/linux/skbuff.h | 6 | ||||
-rw-r--r-- | net/core/ethtool.c | 1 | ||||
-rw-r--r-- | net/ipv4/af_inet.c | 9 | ||||
-rw-r--r-- | net/ipv4/gre_offload.c | 3 | ||||
-rw-r--r-- | net/ipv4/ipip.c | 11 | ||||
-rw-r--r-- | net/ipv4/tcp_offload.c | 1 | ||||
-rw-r--r-- | net/ipv4/udp_offload.c | 1 | ||||
-rw-r--r-- | net/ipv6/ip6_offload.c | 1 | ||||
-rw-r--r-- | net/ipv6/udp_offload.c | 1 | ||||
-rw-r--r-- | net/mpls/mpls_gso.c | 1 |
11 files changed, 29 insertions, 8 deletions
diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h index a2a89a5c7be5..8dad68cede1c 100644 --- a/include/linux/netdev_features.h +++ b/include/linux/netdev_features.h | |||
@@ -42,6 +42,7 @@ enum { | |||
42 | NETIF_F_TSO6_BIT, /* ... TCPv6 segmentation */ | 42 | NETIF_F_TSO6_BIT, /* ... TCPv6 segmentation */ |
43 | NETIF_F_FSO_BIT, /* ... FCoE segmentation */ | 43 | NETIF_F_FSO_BIT, /* ... FCoE segmentation */ |
44 | NETIF_F_GSO_GRE_BIT, /* ... GRE with TSO */ | 44 | NETIF_F_GSO_GRE_BIT, /* ... GRE with TSO */ |
45 | NETIF_F_GSO_IPIP_BIT, /* ... IPIP tunnel with TSO */ | ||
45 | NETIF_F_GSO_UDP_TUNNEL_BIT, /* ... UDP TUNNEL with TSO */ | 46 | NETIF_F_GSO_UDP_TUNNEL_BIT, /* ... UDP TUNNEL with TSO */ |
46 | NETIF_F_GSO_MPLS_BIT, /* ... MPLS segmentation */ | 47 | NETIF_F_GSO_MPLS_BIT, /* ... MPLS segmentation */ |
47 | /**/NETIF_F_GSO_LAST = /* last bit, see GSO_MASK */ | 48 | /**/NETIF_F_GSO_LAST = /* last bit, see GSO_MASK */ |
@@ -107,6 +108,7 @@ enum { | |||
107 | #define NETIF_F_RXFCS __NETIF_F(RXFCS) | 108 | #define NETIF_F_RXFCS __NETIF_F(RXFCS) |
108 | #define NETIF_F_RXALL __NETIF_F(RXALL) | 109 | #define NETIF_F_RXALL __NETIF_F(RXALL) |
109 | #define NETIF_F_GSO_GRE __NETIF_F(GSO_GRE) | 110 | #define NETIF_F_GSO_GRE __NETIF_F(GSO_GRE) |
111 | #define NETIF_F_GSO_IPIP __NETIF_F(GSO_IPIP) | ||
110 | #define NETIF_F_GSO_UDP_TUNNEL __NETIF_F(GSO_UDP_TUNNEL) | 112 | #define NETIF_F_GSO_UDP_TUNNEL __NETIF_F(GSO_UDP_TUNNEL) |
111 | #define NETIF_F_GSO_MPLS __NETIF_F(GSO_MPLS) | 113 | #define NETIF_F_GSO_MPLS __NETIF_F(GSO_MPLS) |
112 | #define NETIF_F_HW_VLAN_STAG_FILTER __NETIF_F(HW_VLAN_STAG_FILTER) | 114 | #define NETIF_F_HW_VLAN_STAG_FILTER __NETIF_F(HW_VLAN_STAG_FILTER) |
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index cad1e0c5cc04..60729134d253 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h | |||
@@ -318,9 +318,11 @@ enum { | |||
318 | 318 | ||
319 | SKB_GSO_GRE = 1 << 6, | 319 | SKB_GSO_GRE = 1 << 6, |
320 | 320 | ||
321 | SKB_GSO_UDP_TUNNEL = 1 << 7, | 321 | SKB_GSO_IPIP = 1 << 7, |
322 | 322 | ||
323 | SKB_GSO_MPLS = 1 << 8, | 323 | SKB_GSO_UDP_TUNNEL = 1 << 8, |
324 | |||
325 | SKB_GSO_MPLS = 1 << 9, | ||
324 | }; | 326 | }; |
325 | 327 | ||
326 | #if BITS_PER_LONG > 32 | 328 | #if BITS_PER_LONG > 32 |
diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 78e9d9223e40..8cab7744790e 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c | |||
@@ -81,6 +81,7 @@ static const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN] | |||
81 | [NETIF_F_TSO6_BIT] = "tx-tcp6-segmentation", | 81 | [NETIF_F_TSO6_BIT] = "tx-tcp6-segmentation", |
82 | [NETIF_F_FSO_BIT] = "tx-fcoe-segmentation", | 82 | [NETIF_F_FSO_BIT] = "tx-fcoe-segmentation", |
83 | [NETIF_F_GSO_GRE_BIT] = "tx-gre-segmentation", | 83 | [NETIF_F_GSO_GRE_BIT] = "tx-gre-segmentation", |
84 | [NETIF_F_GSO_IPIP_BIT] = "tx-ipip-segmentation", | ||
84 | [NETIF_F_GSO_UDP_TUNNEL_BIT] = "tx-udp_tnl-segmentation", | 85 | [NETIF_F_GSO_UDP_TUNNEL_BIT] = "tx-udp_tnl-segmentation", |
85 | [NETIF_F_GSO_MPLS_BIT] = "tx-mpls-segmentation", | 86 | [NETIF_F_GSO_MPLS_BIT] = "tx-mpls-segmentation", |
86 | 87 | ||
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 5783ab5b5ef8..4049906010f7 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c | |||
@@ -1291,6 +1291,7 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb, | |||
1291 | SKB_GSO_DODGY | | 1291 | SKB_GSO_DODGY | |
1292 | SKB_GSO_TCP_ECN | | 1292 | SKB_GSO_TCP_ECN | |
1293 | SKB_GSO_GRE | | 1293 | SKB_GSO_GRE | |
1294 | SKB_GSO_IPIP | | ||
1294 | SKB_GSO_TCPV6 | | 1295 | SKB_GSO_TCPV6 | |
1295 | SKB_GSO_UDP_TUNNEL | | 1296 | SKB_GSO_UDP_TUNNEL | |
1296 | SKB_GSO_MPLS | | 1297 | SKB_GSO_MPLS | |
@@ -1656,6 +1657,13 @@ static struct packet_offload ip_packet_offload __read_mostly = { | |||
1656 | }, | 1657 | }, |
1657 | }; | 1658 | }; |
1658 | 1659 | ||
1660 | static const struct net_offload ipip_offload = { | ||
1661 | .callbacks = { | ||
1662 | .gso_send_check = inet_gso_send_check, | ||
1663 | .gso_segment = inet_gso_segment, | ||
1664 | }, | ||
1665 | }; | ||
1666 | |||
1659 | static int __init ipv4_offload_init(void) | 1667 | static int __init ipv4_offload_init(void) |
1660 | { | 1668 | { |
1661 | /* | 1669 | /* |
@@ -1667,6 +1675,7 @@ static int __init ipv4_offload_init(void) | |||
1667 | pr_crit("%s: Cannot add TCP protocol offload\n", __func__); | 1675 | pr_crit("%s: Cannot add TCP protocol offload\n", __func__); |
1668 | 1676 | ||
1669 | dev_add_offload(&ip_packet_offload); | 1677 | dev_add_offload(&ip_packet_offload); |
1678 | inet_add_offload(&ipip_offload, IPPROTO_IPIP); | ||
1670 | return 0; | 1679 | return 0; |
1671 | } | 1680 | } |
1672 | 1681 | ||
diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c index 55e6bfb3a289..e5d436188464 100644 --- a/net/ipv4/gre_offload.c +++ b/net/ipv4/gre_offload.c | |||
@@ -39,7 +39,8 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb, | |||
39 | SKB_GSO_UDP | | 39 | SKB_GSO_UDP | |
40 | SKB_GSO_DODGY | | 40 | SKB_GSO_DODGY | |
41 | SKB_GSO_TCP_ECN | | 41 | SKB_GSO_TCP_ECN | |
42 | SKB_GSO_GRE))) | 42 | SKB_GSO_GRE | |
43 | SKB_GSO_IPIP))) | ||
43 | goto out; | 44 | goto out; |
44 | 45 | ||
45 | if (unlikely(!pskb_may_pull(skb, sizeof(*greh)))) | 46 | if (unlikely(!pskb_may_pull(skb, sizeof(*greh)))) |
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index 7f80fb4b82d3..fe3e9f7f1f0b 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c | |||
@@ -220,17 +220,17 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
220 | if (unlikely(skb->protocol != htons(ETH_P_IP))) | 220 | if (unlikely(skb->protocol != htons(ETH_P_IP))) |
221 | goto tx_error; | 221 | goto tx_error; |
222 | 222 | ||
223 | if (likely(!skb->encapsulation)) { | 223 | skb = iptunnel_handle_offloads(skb, false, SKB_GSO_IPIP); |
224 | skb_reset_inner_headers(skb); | 224 | if (IS_ERR(skb)) |
225 | skb->encapsulation = 1; | 225 | goto out; |
226 | } | ||
227 | 226 | ||
228 | ip_tunnel_xmit(skb, dev, tiph, tiph->protocol); | 227 | ip_tunnel_xmit(skb, dev, tiph, tiph->protocol); |
229 | return NETDEV_TX_OK; | 228 | return NETDEV_TX_OK; |
230 | 229 | ||
231 | tx_error: | 230 | tx_error: |
232 | dev->stats.tx_errors++; | ||
233 | dev_kfree_skb(skb); | 231 | dev_kfree_skb(skb); |
232 | out: | ||
233 | dev->stats.tx_errors++; | ||
234 | return NETDEV_TX_OK; | 234 | return NETDEV_TX_OK; |
235 | } | 235 | } |
236 | 236 | ||
@@ -275,6 +275,7 @@ static const struct net_device_ops ipip_netdev_ops = { | |||
275 | #define IPIP_FEATURES (NETIF_F_SG | \ | 275 | #define IPIP_FEATURES (NETIF_F_SG | \ |
276 | NETIF_F_FRAGLIST | \ | 276 | NETIF_F_FRAGLIST | \ |
277 | NETIF_F_HIGHDMA | \ | 277 | NETIF_F_HIGHDMA | \ |
278 | NETIF_F_GSO_SOFTWARE | \ | ||
278 | NETIF_F_HW_CSUM) | 279 | NETIF_F_HW_CSUM) |
279 | 280 | ||
280 | static void ipip_tunnel_setup(struct net_device *dev) | 281 | static void ipip_tunnel_setup(struct net_device *dev) |
diff --git a/net/ipv4/tcp_offload.c b/net/ipv4/tcp_offload.c index 8e3113f46ec1..dfc96b00673e 100644 --- a/net/ipv4/tcp_offload.c +++ b/net/ipv4/tcp_offload.c | |||
@@ -56,6 +56,7 @@ struct sk_buff *tcp_gso_segment(struct sk_buff *skb, | |||
56 | SKB_GSO_TCP_ECN | | 56 | SKB_GSO_TCP_ECN | |
57 | SKB_GSO_TCPV6 | | 57 | SKB_GSO_TCPV6 | |
58 | SKB_GSO_GRE | | 58 | SKB_GSO_GRE | |
59 | SKB_GSO_IPIP | | ||
59 | SKB_GSO_MPLS | | 60 | SKB_GSO_MPLS | |
60 | SKB_GSO_UDP_TUNNEL | | 61 | SKB_GSO_UDP_TUNNEL | |
61 | 0) || | 62 | 0) || |
diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c index f35eccaa855e..83206de2bc76 100644 --- a/net/ipv4/udp_offload.c +++ b/net/ipv4/udp_offload.c | |||
@@ -52,6 +52,7 @@ static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb, | |||
52 | 52 | ||
53 | if (unlikely(type & ~(SKB_GSO_UDP | SKB_GSO_DODGY | | 53 | if (unlikely(type & ~(SKB_GSO_UDP | SKB_GSO_DODGY | |
54 | SKB_GSO_UDP_TUNNEL | | 54 | SKB_GSO_UDP_TUNNEL | |
55 | SKB_GSO_IPIP | | ||
55 | SKB_GSO_GRE | SKB_GSO_MPLS) || | 56 | SKB_GSO_GRE | SKB_GSO_MPLS) || |
56 | !(type & (SKB_GSO_UDP)))) | 57 | !(type & (SKB_GSO_UDP)))) |
57 | goto out; | 58 | goto out; |
diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c index b405fba91c72..5c2fc1d04196 100644 --- a/net/ipv6/ip6_offload.c +++ b/net/ipv6/ip6_offload.c | |||
@@ -96,6 +96,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, | |||
96 | SKB_GSO_DODGY | | 96 | SKB_GSO_DODGY | |
97 | SKB_GSO_TCP_ECN | | 97 | SKB_GSO_TCP_ECN | |
98 | SKB_GSO_GRE | | 98 | SKB_GSO_GRE | |
99 | SKB_GSO_IPIP | | ||
99 | SKB_GSO_UDP_TUNNEL | | 100 | SKB_GSO_UDP_TUNNEL | |
100 | SKB_GSO_MPLS | | 101 | SKB_GSO_MPLS | |
101 | SKB_GSO_TCPV6 | | 102 | SKB_GSO_TCPV6 | |
diff --git a/net/ipv6/udp_offload.c b/net/ipv6/udp_offload.c index 60559511bd9c..f63780ff3732 100644 --- a/net/ipv6/udp_offload.c +++ b/net/ipv6/udp_offload.c | |||
@@ -64,6 +64,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, | |||
64 | SKB_GSO_DODGY | | 64 | SKB_GSO_DODGY | |
65 | SKB_GSO_UDP_TUNNEL | | 65 | SKB_GSO_UDP_TUNNEL | |
66 | SKB_GSO_GRE | | 66 | SKB_GSO_GRE | |
67 | SKB_GSO_IPIP | | ||
67 | SKB_GSO_MPLS) || | 68 | SKB_GSO_MPLS) || |
68 | !(type & (SKB_GSO_UDP)))) | 69 | !(type & (SKB_GSO_UDP)))) |
69 | goto out; | 70 | goto out; |
diff --git a/net/mpls/mpls_gso.c b/net/mpls/mpls_gso.c index 1bec1219ab81..851cd880b0c0 100644 --- a/net/mpls/mpls_gso.c +++ b/net/mpls/mpls_gso.c | |||
@@ -33,6 +33,7 @@ static struct sk_buff *mpls_gso_segment(struct sk_buff *skb, | |||
33 | SKB_GSO_DODGY | | 33 | SKB_GSO_DODGY | |
34 | SKB_GSO_TCP_ECN | | 34 | SKB_GSO_TCP_ECN | |
35 | SKB_GSO_GRE | | 35 | SKB_GSO_GRE | |
36 | SKB_GSO_IPIP | | ||
36 | SKB_GSO_MPLS))) | 37 | SKB_GSO_MPLS))) |
37 | goto out; | 38 | goto out; |
38 | 39 | ||