]> err.no Git - linux-2.6/blobdiff - net/ipv4/tcp.c
[netdrvr] via-velocity: misc. cleanups
[linux-2.6] / net / ipv4 / tcp.c
index a97450e9eb34692558246464101ff58259aadda6..f6a2d9223d07ca1503aecfdaa9124e09b8e22247 100644 (file)
@@ -642,7 +642,7 @@ static inline int select_size(struct sock *sk, struct tcp_sock *tp)
        int tmp = tp->mss_cache;
 
        if (sk->sk_route_caps & NETIF_F_SG) {
-               if (sk->sk_route_caps & NETIF_F_TSO)
+               if (sk_can_gso(sk))
                        tmp = 0;
                else {
                        int pgbreak = SKB_MAX_HEAD(MAX_TCP_HEADER);
@@ -2165,13 +2165,30 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features)
        if (!pskb_may_pull(skb, thlen))
                goto out;
 
-       segs = NULL;
-       if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST))
-               goto out;
-
        oldlen = (u16)~skb->len;
        __skb_pull(skb, thlen);
 
+       if (skb_gso_ok(skb, features | NETIF_F_GSO_ROBUST)) {
+               /* Packet is from an untrusted source, reset gso_segs. */
+               int type = skb_shinfo(skb)->gso_type;
+               int mss;
+
+               if (unlikely(type &
+                            ~(SKB_GSO_TCPV4 |
+                              SKB_GSO_DODGY |
+                              SKB_GSO_TCP_ECN |
+                              SKB_GSO_TCPV6 |
+                              0) ||
+                            !(type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))))
+                       goto out;
+
+               mss = skb_shinfo(skb)->gso_size;
+               skb_shinfo(skb)->gso_segs = (skb->len + mss - 1) / mss;
+
+               segs = NULL;
+               goto out;
+       }
+
        segs = skb_segment(skb, features);
        if (IS_ERR(segs))
                goto out;
@@ -2208,6 +2225,7 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb, int features)
 out:
        return segs;
 }
+EXPORT_SYMBOL(tcp_tso_segment);
 
 extern void __skb_cb_too_small_for_tcp(int, int);
 extern struct tcp_congestion_ops tcp_reno;