diff options
Diffstat (limited to 'net/ipv4/tcp.c')
| -rw-r--r-- | net/ipv4/tcp.c | 29 |
1 files changed, 23 insertions, 6 deletions
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 0336422c88a0..f6a2d9223d07 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
| @@ -247,7 +247,6 @@ | |||
| 247 | * TCP_CLOSE socket is finished | 247 | * TCP_CLOSE socket is finished |
| 248 | */ | 248 | */ |
| 249 | 249 | ||
| 250 | #include <linux/config.h> | ||
| 251 | #include <linux/module.h> | 250 | #include <linux/module.h> |
| 252 | #include <linux/types.h> | 251 | #include <linux/types.h> |
| 253 | #include <linux/fcntl.h> | 252 | #include <linux/fcntl.h> |
| @@ -643,7 +642,7 @@ static inline int select_size(struct sock *sk, struct tcp_sock *tp) | |||
| 643 | int tmp = tp->mss_cache; | 642 | int tmp = tp->mss_cache; |
| 644 | 643 | ||
| 645 | if (sk->sk_route_caps & NETIF_F_SG) { | 644 | if (sk->sk_route_caps & NETIF_F_SG) { |
| 646 | if (sk->sk_route_caps & NETIF_F_TSO) | 645 | if (sk_can_gso(sk)) |
| 647 | tmp = 0; | 646 | tmp = 0; |
| 648 | else { | 647 | else { |
| 649 | int pgbreak = SKB_MAX_HEAD(MAX_TCP_HEADER); | 648 | int pgbreak = SKB_MAX_HEAD(MAX_TCP_HEADER); |
| @@ -2166,13 +2165,30 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features) | |||
| 2166 | if (!pskb_may_pull(skb, thlen)) | 2165 | if (!pskb_may_pull(skb, thlen)) |
| 2167 | goto out; | 2166 | goto out; |
| 2168 | 2167 | ||
| 2169 | segs = NULL; | ||
| 2170 | if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) | ||
| 2171 | goto out; | ||
| 2172 | |||
| 2173 | oldlen = (u16)~skb->len; | 2168 | oldlen = (u16)~skb->len; |
| 2174 | __skb_pull(skb, thlen); | 2169 | __skb_pull(skb, thlen); |
| 2175 | 2170 | ||
| 2171 | if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) { | ||
| 2172 | /* Packet is from an untrusted source, reset gso_segs. */ | ||
| 2173 | int type = skb_shinfo(skb)->gso_type; | ||
| 2174 | int mss; | ||
| 2175 | |||
| 2176 | if (unlikely(type & | ||
| 2177 | ~(SKB_GSO_TCPV4 | | ||
| 2178 | SKB_GSO_DODGY | | ||
| 2179 | SKB_GSO_TCP_ECN | | ||
| 2180 | SKB_GSO_TCPV6 | | ||
| 2181 | 0) || | ||
| 2182 | !(type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)))) | ||
| 2183 | goto out; | ||
| 2184 | |||
| 2185 | mss = skb_shinfo(skb)->gso_size; | ||
| 2186 | skb_shinfo(skb)->gso_segs = (skb->len + mss - 1) / mss; | ||
| 2187 | |||
| 2188 | segs = NULL; | ||
| 2189 | goto out; | ||
| 2190 | } | ||
| 2191 | |||
| 2176 | segs = skb_segment(skb, features); | 2192 | segs = skb_segment(skb, features); |
| 2177 | if (IS_ERR(segs)) | 2193 | if (IS_ERR(segs)) |
| 2178 | goto out; | 2194 | goto out; |
| @@ -2209,6 +2225,7 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features) | |||
| 2209 | out: | 2225 | out: |
| 2210 | return segs; | 2226 | return segs; |
| 2211 | } | 2227 | } |
| 2228 | EXPORT_SYMBOL(tcp_tso_segment); | ||
| 2212 | 2229 | ||
| 2213 | extern void __skb_cb_too_small_for_tcp(int, int); | 2230 | extern void __skb_cb_too_small_for_tcp(int, int); |
| 2214 | extern struct tcp_congestion_ops tcp_reno; | 2231 | extern struct tcp_congestion_ops tcp_reno; |
