aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPravin B Shelar <pshelar@nicira.com>2013-05-02 12:14:19 -0400
committerDavid S. Miller <davem@davemloft.net>2013-05-03 16:08:58 -0400
commit9b3eb5edf33897dc9128aa27300066153d4f8b9c (patch)
treef4881f9cc2e54a7741ba4b0ef9e04e4094c2c43d
parent83401eb4990ff6af55aeed8f49681558544192e6 (diff)
gre: Fix GREv4 TCPv6 segmentation.
For ipv6 traffic, GRE can generate packet with strange GSO bits, e.g. ipv4 packet with SKB_GSO_TCPV6 flag set. Therefore following patch relaxes check in inet gso handler to allow such packet for segmentation. This patch also fixes wrong skb->protocol set that was done in gre_gso_segment() handler. Reported-by: Steinar H. Gunderson <sesse@google.com> CC: Eric Dumazet <eric.dumazet@gmail.com> Signed-off-by: Pravin B Shelar <pshelar@nicira.com> Acked-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/ipv4/af_inet.c1
-rw-r--r--net/ipv4/gre.c4
2 files changed, 4 insertions, 1 deletions
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index c61b3bb87a16..d01be2a3ae53 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1293,6 +1293,7 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb,
1293 SKB_GSO_DODGY | 1293 SKB_GSO_DODGY |
1294 SKB_GSO_TCP_ECN | 1294 SKB_GSO_TCP_ECN |
1295 SKB_GSO_GRE | 1295 SKB_GSO_GRE |
1296 SKB_GSO_TCPV6 |
1296 SKB_GSO_UDP_TUNNEL | 1297 SKB_GSO_UDP_TUNNEL |
1297 0))) 1298 0)))
1298 goto out; 1299 goto out;
diff --git a/net/ipv4/gre.c b/net/ipv4/gre.c
index d2d5a99fba09..cc22363965d2 100644
--- a/net/ipv4/gre.c
+++ b/net/ipv4/gre.c
@@ -121,6 +121,7 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
121 int ghl = GRE_HEADER_SECTION; 121 int ghl = GRE_HEADER_SECTION;
122 struct gre_base_hdr *greh; 122 struct gre_base_hdr *greh;
123 int mac_len = skb->mac_len; 123 int mac_len = skb->mac_len;
124 __be16 protocol = skb->protocol;
124 int tnl_hlen; 125 int tnl_hlen;
125 bool csum; 126 bool csum;
126 127
@@ -150,7 +151,7 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
150 151
151 /* setup inner skb. */ 152 /* setup inner skb. */
152 if (greh->protocol == htons(ETH_P_TEB)) { 153 if (greh->protocol == htons(ETH_P_TEB)) {
153 struct ethhdr *eth = eth_hdr(skb); 154 struct ethhdr *eth = (struct ethhdr *)skb_inner_mac_header(skb);
154 skb->protocol = eth->h_proto; 155 skb->protocol = eth->h_proto;
155 } else { 156 } else {
156 skb->protocol = greh->protocol; 157 skb->protocol = greh->protocol;
@@ -199,6 +200,7 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
199 skb_reset_mac_header(skb); 200 skb_reset_mac_header(skb);
200 skb_set_network_header(skb, mac_len); 201 skb_set_network_header(skb, mac_len);
201 skb->mac_len = mac_len; 202 skb->mac_len = mac_len;
203 skb->protocol = protocol;
202 } while ((skb = skb->next)); 204 } while ((skb = skb->next));
203out: 205out:
204 return segs; 206 return segs;