diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/netdevice.h | 17 | ||||
-rw-r--r-- | include/linux/skbuff.h | 6 | ||||
-rw-r--r-- | include/net/ip6_route.h | 2 | ||||
-rw-r--r-- | include/net/protocol.h | 6 | ||||
-rw-r--r-- | include/net/sock.h | 13 | ||||
-rw-r--r-- | include/net/tcp.h | 2 | ||||
-rw-r--r-- | include/net/tcp_ecn.h | 4 |
7 files changed, 35 insertions, 15 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index aa2d3c12c4d8..85f99f60deea 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
@@ -313,10 +313,12 @@ struct net_device | |||
313 | 313 | ||
314 | /* Segmentation offload features */ | 314 | /* Segmentation offload features */ |
315 | #define NETIF_F_GSO_SHIFT 16 | 315 | #define NETIF_F_GSO_SHIFT 16 |
316 | #define NETIF_F_GSO_MASK 0xffff0000 | ||
316 | #define NETIF_F_TSO (SKB_GSO_TCPV4 << NETIF_F_GSO_SHIFT) | 317 | #define NETIF_F_TSO (SKB_GSO_TCPV4 << NETIF_F_GSO_SHIFT) |
317 | #define NETIF_F_UFO (SKB_GSO_UDPV4 << NETIF_F_GSO_SHIFT) | 318 | #define NETIF_F_UFO (SKB_GSO_UDP << NETIF_F_GSO_SHIFT) |
318 | #define NETIF_F_GSO_ROBUST (SKB_GSO_DODGY << NETIF_F_GSO_SHIFT) | 319 | #define NETIF_F_GSO_ROBUST (SKB_GSO_DODGY << NETIF_F_GSO_SHIFT) |
319 | #define NETIF_F_TSO_ECN (SKB_GSO_TCPV4_ECN << NETIF_F_GSO_SHIFT) | 320 | #define NETIF_F_TSO_ECN (SKB_GSO_TCP_ECN << NETIF_F_GSO_SHIFT) |
321 | #define NETIF_F_TSO6 (SKB_GSO_TCPV6 << NETIF_F_GSO_SHIFT) | ||
320 | 322 | ||
321 | #define NETIF_F_GEN_CSUM (NETIF_F_NO_CSUM | NETIF_F_HW_CSUM) | 323 | #define NETIF_F_GEN_CSUM (NETIF_F_NO_CSUM | NETIF_F_HW_CSUM) |
322 | #define NETIF_F_ALL_CSUM (NETIF_F_IP_CSUM | NETIF_F_GEN_CSUM) | 324 | #define NETIF_F_ALL_CSUM (NETIF_F_IP_CSUM | NETIF_F_GEN_CSUM) |
@@ -991,13 +993,18 @@ extern void dev_seq_stop(struct seq_file *seq, void *v); | |||
991 | 993 | ||
992 | extern void linkwatch_run_queue(void); | 994 | extern void linkwatch_run_queue(void); |
993 | 995 | ||
994 | static inline int skb_gso_ok(struct sk_buff *skb, int features) | 996 | static inline int net_gso_ok(int features, int gso_type) |
995 | { | 997 | { |
996 | int feature = skb_shinfo(skb)->gso_size ? | 998 | int feature = gso_type << NETIF_F_GSO_SHIFT; |
997 | skb_shinfo(skb)->gso_type << NETIF_F_GSO_SHIFT : 0; | ||
998 | return (features & feature) == feature; | 999 | return (features & feature) == feature; |
999 | } | 1000 | } |
1000 | 1001 | ||
1002 | static inline int skb_gso_ok(struct sk_buff *skb, int features) | ||
1003 | { | ||
1004 | return net_gso_ok(features, skb_shinfo(skb)->gso_size ? | ||
1005 | skb_shinfo(skb)->gso_type : 0); | ||
1006 | } | ||
1007 | |||
1001 | static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb) | 1008 | static inline int netif_needs_gso(struct net_device *dev, struct sk_buff *skb) |
1002 | { | 1009 | { |
1003 | return !skb_gso_ok(skb, dev->features); | 1010 | return !skb_gso_ok(skb, dev->features); |
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 59918be91d0a..57d7d4965f9a 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h | |||
@@ -171,13 +171,15 @@ enum { | |||
171 | 171 | ||
172 | enum { | 172 | enum { |
173 | SKB_GSO_TCPV4 = 1 << 0, | 173 | SKB_GSO_TCPV4 = 1 << 0, |
174 | SKB_GSO_UDPV4 = 1 << 1, | 174 | SKB_GSO_UDP = 1 << 1, |
175 | 175 | ||
176 | /* This indicates the skb is from an untrusted source. */ | 176 | /* This indicates the skb is from an untrusted source. */ |
177 | SKB_GSO_DODGY = 1 << 2, | 177 | SKB_GSO_DODGY = 1 << 2, |
178 | 178 | ||
179 | /* This indicates the tcp segment has CWR set. */ | 179 | /* This indicates the tcp segment has CWR set. */ |
180 | SKB_GSO_TCPV4_ECN = 1 << 3, | 180 | SKB_GSO_TCP_ECN = 1 << 3, |
181 | |||
182 | SKB_GSO_TCPV6 = 1 << 4, | ||
181 | }; | 183 | }; |
182 | 184 | ||
183 | /** | 185 | /** |
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h index a398ae5e30f9..ab29dafb1a6a 100644 --- a/include/net/ip6_route.h +++ b/include/net/ip6_route.h | |||
@@ -146,7 +146,7 @@ static inline void ip6_dst_store(struct sock *sk, struct dst_entry *dst, | |||
146 | struct rt6_info *rt = (struct rt6_info *) dst; | 146 | struct rt6_info *rt = (struct rt6_info *) dst; |
147 | 147 | ||
148 | write_lock(&sk->sk_dst_lock); | 148 | write_lock(&sk->sk_dst_lock); |
149 | __sk_dst_set(sk, dst); | 149 | sk_setup_caps(sk, dst); |
150 | np->daddr_cache = daddr; | 150 | np->daddr_cache = daddr; |
151 | np->dst_cookie = rt->rt6i_node ? rt->rt6i_node->fn_sernum : 0; | 151 | np->dst_cookie = rt->rt6i_node ? rt->rt6i_node->fn_sernum : 0; |
152 | write_unlock(&sk->sk_dst_lock); | 152 | write_unlock(&sk->sk_dst_lock); |
diff --git a/include/net/protocol.h b/include/net/protocol.h index 40b6b9c9973f..a225d6371cb1 100644 --- a/include/net/protocol.h +++ b/include/net/protocol.h | |||
@@ -50,11 +50,17 @@ struct inet6_protocol | |||
50 | struct inet6_skb_parm *opt, | 50 | struct inet6_skb_parm *opt, |
51 | int type, int code, int offset, | 51 | int type, int code, int offset, |
52 | __u32 info); | 52 | __u32 info); |
53 | |||
54 | struct sk_buff *(*gso_segment)(struct sk_buff *skb, | ||
55 | int features); | ||
56 | |||
53 | unsigned int flags; /* INET6_PROTO_xxx */ | 57 | unsigned int flags; /* INET6_PROTO_xxx */ |
54 | }; | 58 | }; |
55 | 59 | ||
56 | #define INET6_PROTO_NOPOLICY 0x1 | 60 | #define INET6_PROTO_NOPOLICY 0x1 |
57 | #define INET6_PROTO_FINAL 0x2 | 61 | #define INET6_PROTO_FINAL 0x2 |
62 | /* This should be set for any extension header which is compatible with GSO. */ | ||
63 | #define INET6_PROTO_GSO_EXTHDR 0x4 | ||
58 | #endif | 64 | #endif |
59 | 65 | ||
60 | /* This is used to register socket interfaces for IP protocols. */ | 66 | /* This is used to register socket interfaces for IP protocols. */ |
diff --git a/include/net/sock.h b/include/net/sock.h index 7136bae48c2f..7b3d6b856946 100644 --- a/include/net/sock.h +++ b/include/net/sock.h | |||
@@ -140,6 +140,7 @@ struct sock_common { | |||
140 | * @sk_flags: %SO_LINGER (l_onoff), %SO_BROADCAST, %SO_KEEPALIVE, %SO_OOBINLINE settings | 140 | * @sk_flags: %SO_LINGER (l_onoff), %SO_BROADCAST, %SO_KEEPALIVE, %SO_OOBINLINE settings |
141 | * @sk_no_check: %SO_NO_CHECK setting, wether or not checkup packets | 141 | * @sk_no_check: %SO_NO_CHECK setting, wether or not checkup packets |
142 | * @sk_route_caps: route capabilities (e.g. %NETIF_F_TSO) | 142 | * @sk_route_caps: route capabilities (e.g. %NETIF_F_TSO) |
143 | * @sk_gso_type: GSO type (e.g. %SKB_GSO_TCPV4) | ||
143 | * @sk_lingertime: %SO_LINGER l_linger setting | 144 | * @sk_lingertime: %SO_LINGER l_linger setting |
144 | * @sk_backlog: always used with the per-socket spinlock held | 145 | * @sk_backlog: always used with the per-socket spinlock held |
145 | * @sk_callback_lock: used with the callbacks in the end of this struct | 146 | * @sk_callback_lock: used with the callbacks in the end of this struct |
@@ -211,6 +212,7 @@ struct sock { | |||
211 | gfp_t sk_allocation; | 212 | gfp_t sk_allocation; |
212 | int sk_sndbuf; | 213 | int sk_sndbuf; |
213 | int sk_route_caps; | 214 | int sk_route_caps; |
215 | int sk_gso_type; | ||
214 | int sk_rcvlowat; | 216 | int sk_rcvlowat; |
215 | unsigned long sk_flags; | 217 | unsigned long sk_flags; |
216 | unsigned long sk_lingertime; | 218 | unsigned long sk_lingertime; |
@@ -1025,15 +1027,20 @@ extern struct dst_entry *__sk_dst_check(struct sock *sk, u32 cookie); | |||
1025 | 1027 | ||
1026 | extern struct dst_entry *sk_dst_check(struct sock *sk, u32 cookie); | 1028 | extern struct dst_entry *sk_dst_check(struct sock *sk, u32 cookie); |
1027 | 1029 | ||
1030 | static inline int sk_can_gso(const struct sock *sk) | ||
1031 | { | ||
1032 | return net_gso_ok(sk->sk_route_caps, sk->sk_gso_type); | ||
1033 | } | ||
1034 | |||
1028 | static inline void sk_setup_caps(struct sock *sk, struct dst_entry *dst) | 1035 | static inline void sk_setup_caps(struct sock *sk, struct dst_entry *dst) |
1029 | { | 1036 | { |
1030 | __sk_dst_set(sk, dst); | 1037 | __sk_dst_set(sk, dst); |
1031 | sk->sk_route_caps = dst->dev->features; | 1038 | sk->sk_route_caps = dst->dev->features; |
1032 | if (sk->sk_route_caps & NETIF_F_GSO) | 1039 | if (sk->sk_route_caps & NETIF_F_GSO) |
1033 | sk->sk_route_caps |= NETIF_F_TSO; | 1040 | sk->sk_route_caps |= NETIF_F_GSO_MASK; |
1034 | if (sk->sk_route_caps & NETIF_F_TSO) { | 1041 | if (sk_can_gso(sk)) { |
1035 | if (dst->header_len) | 1042 | if (dst->header_len) |
1036 | sk->sk_route_caps &= ~NETIF_F_TSO; | 1043 | sk->sk_route_caps &= ~NETIF_F_GSO_MASK; |
1037 | else | 1044 | else |
1038 | sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM; | 1045 | sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM; |
1039 | } | 1046 | } |
diff --git a/include/net/tcp.h b/include/net/tcp.h index 624921e76332..3cd803b0d7a5 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h | |||
@@ -751,7 +751,7 @@ static inline int tcp_is_cwnd_limited(const struct sock *sk, u32 in_flight) | |||
751 | if (in_flight >= tp->snd_cwnd) | 751 | if (in_flight >= tp->snd_cwnd) |
752 | return 1; | 752 | return 1; |
753 | 753 | ||
754 | if (!(sk->sk_route_caps & NETIF_F_TSO)) | 754 | if (!sk_can_gso(sk)) |
755 | return 0; | 755 | return 0; |
756 | 756 | ||
757 | left = tp->snd_cwnd - in_flight; | 757 | left = tp->snd_cwnd - in_flight; |
diff --git a/include/net/tcp_ecn.h b/include/net/tcp_ecn.h index 7bb366f70934..4629d77173f2 100644 --- a/include/net/tcp_ecn.h +++ b/include/net/tcp_ecn.h | |||
@@ -55,9 +55,7 @@ static inline void TCP_ECN_send(struct sock *sk, struct tcp_sock *tp, | |||
55 | if (tp->ecn_flags&TCP_ECN_QUEUE_CWR) { | 55 | if (tp->ecn_flags&TCP_ECN_QUEUE_CWR) { |
56 | tp->ecn_flags &= ~TCP_ECN_QUEUE_CWR; | 56 | tp->ecn_flags &= ~TCP_ECN_QUEUE_CWR; |
57 | skb->h.th->cwr = 1; | 57 | skb->h.th->cwr = 1; |
58 | if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4) | 58 | skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_ECN; |
59 | skb_shinfo(skb)->gso_type |= | ||
60 | SKB_GSO_TCPV4_ECN; | ||
61 | } | 59 | } |
62 | } else { | 60 | } else { |
63 | /* ACK or retransmitted segment: clear ECT|CE */ | 61 | /* ACK or retransmitted segment: clear ECT|CE */ |