diff options
author | Pravin B Shelar <pshelar@nicira.com> | 2013-02-14 09:02:41 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-02-15 15:17:11 -0500 |
commit | 68c331631143f5f039baac99a650e0b9e1ea02b6 (patch) | |
tree | c69d73c5599aab5e92a8c99bc5343c9fc9ffbbd8 /net/core | |
parent | 05e8ef4ab2d8087d360e814d14da20b9f7fb2283 (diff) |
v4 GRE: Add TCP segmentation offload for GRE
Following patch adds GRE protocol offload handler so that
skb_gso_segment() can segment GRE packets.
SKB GSO CB is added to keep track of total header length so that
skb_segment can push entire header. e.g. in case of GRE, skb_segment
need to push inner and outer headers to every segment.
New NETIF_F_GRE_GSO feature is added for devices which support HW
GRE TSO offload. Currently none of devices support it therefore GRE GSO
always fall backs to software GSO.
[ Compute pkt_len before ip_local_out() invocation. -DaveM ]
Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/dev.c | 1 | ||||
-rw-r--r-- | net/core/ethtool.c | 1 | ||||
-rw-r--r-- | net/core/skbuff.c | 6 |
3 files changed, 7 insertions, 1 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index 67deae60214c..1cd6297fd34b 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -2413,6 +2413,7 @@ struct sk_buff *__skb_gso_segment(struct sk_buff *skb, | |||
2413 | return ERR_PTR(err); | 2413 | return ERR_PTR(err); |
2414 | } | 2414 | } |
2415 | 2415 | ||
2416 | SKB_GSO_CB(skb)->mac_offset = skb_headroom(skb); | ||
2416 | skb_reset_mac_header(skb); | 2417 | skb_reset_mac_header(skb); |
2417 | skb_reset_mac_len(skb); | 2418 | skb_reset_mac_len(skb); |
2418 | 2419 | ||
diff --git a/net/core/ethtool.c b/net/core/ethtool.c index d9d55209db67..3e9b2c3e30f0 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c | |||
@@ -77,6 +77,7 @@ static const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN] | |||
77 | [NETIF_F_TSO_ECN_BIT] = "tx-tcp-ecn-segmentation", | 77 | [NETIF_F_TSO_ECN_BIT] = "tx-tcp-ecn-segmentation", |
78 | [NETIF_F_TSO6_BIT] = "tx-tcp6-segmentation", | 78 | [NETIF_F_TSO6_BIT] = "tx-tcp6-segmentation", |
79 | [NETIF_F_FSO_BIT] = "tx-fcoe-segmentation", | 79 | [NETIF_F_FSO_BIT] = "tx-fcoe-segmentation", |
80 | [NETIF_F_GSO_GRE_BIT] = "tx-gre-segmentation", | ||
80 | 81 | ||
81 | [NETIF_F_FCOE_CRC_BIT] = "tx-checksum-fcoe-crc", | 82 | [NETIF_F_FCOE_CRC_BIT] = "tx-checksum-fcoe-crc", |
82 | [NETIF_F_SCTP_CSUM_BIT] = "tx-checksum-sctp", | 83 | [NETIF_F_SCTP_CSUM_BIT] = "tx-checksum-sctp", |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 6c1ad09f8796..2a3ca33c30aa 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -2738,6 +2738,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features) | |||
2738 | unsigned int mss = skb_shinfo(skb)->gso_size; | 2738 | unsigned int mss = skb_shinfo(skb)->gso_size; |
2739 | unsigned int doffset = skb->data - skb_mac_header(skb); | 2739 | unsigned int doffset = skb->data - skb_mac_header(skb); |
2740 | unsigned int offset = doffset; | 2740 | unsigned int offset = doffset; |
2741 | unsigned int tnl_hlen = skb_tnl_header_len(skb); | ||
2741 | unsigned int headroom; | 2742 | unsigned int headroom; |
2742 | unsigned int len; | 2743 | unsigned int len; |
2743 | int sg = !!(features & NETIF_F_SG); | 2744 | int sg = !!(features & NETIF_F_SG); |
@@ -2814,7 +2815,10 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features) | |||
2814 | skb_set_network_header(nskb, skb->mac_len); | 2815 | skb_set_network_header(nskb, skb->mac_len); |
2815 | nskb->transport_header = (nskb->network_header + | 2816 | nskb->transport_header = (nskb->network_header + |
2816 | skb_network_header_len(skb)); | 2817 | skb_network_header_len(skb)); |
2817 | skb_copy_from_linear_data(skb, nskb->data, doffset); | 2818 | |
2819 | skb_copy_from_linear_data_offset(skb, -tnl_hlen, | ||
2820 | nskb->data - tnl_hlen, | ||
2821 | doffset + tnl_hlen); | ||
2818 | 2822 | ||
2819 | if (fskb != skb_shinfo(skb)->frag_list) | 2823 | if (fskb != skb_shinfo(skb)->frag_list) |
2820 | continue; | 2824 | continue; |