diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2010-05-16 03:36:33 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-05-16 03:36:33 -0400 |
commit | a465419b1febb603821f924805529cff89cafeed (patch) | |
tree | 5131fa2dbf624ebeb6cf61bf4dc1bc9464fe0bbd /include/net | |
parent | 3b098e2d7c693796cc4dffb07caa249fc0f70771 (diff) |
net: Introduce sk_route_nocaps
TCP-MD5 sessions have intermittent failures, when route cache is
invalidated. ip_queue_xmit() has to find a new route, calls
sk_setup_caps(sk, &rt->u.dst), destroying the
sk->sk_route_caps &= ~NETIF_F_GSO_MASK
that MD5 desperately try to make all over its way (from
tcp_transmit_skb() for example)
So we send few bad packets, and everything is fine when
tcp_transmit_skb() is called again for this socket.
Since ip_queue_xmit() is at a lower level than TCP-MD5, I chose to use a
socket field, sk_route_nocaps, containing bits to mask on sk_route_caps.
Reported-by: Bhaskar Dutta <bhaskie@gmail.com>
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include/net')
-rw-r--r-- | include/net/sock.h | 8 |
1 files changed, 8 insertions, 0 deletions
diff --git a/include/net/sock.h b/include/net/sock.h index 328e03f47dd1..aed16eb9db4b 100644 --- a/include/net/sock.h +++ b/include/net/sock.h | |||
@@ -177,6 +177,7 @@ struct sock_common { | |||
177 | * %SO_OOBINLINE settings, %SO_TIMESTAMPING settings | 177 | * %SO_OOBINLINE settings, %SO_TIMESTAMPING settings |
178 | * @sk_no_check: %SO_NO_CHECK setting, wether or not checkup packets | 178 | * @sk_no_check: %SO_NO_CHECK setting, wether or not checkup packets |
179 | * @sk_route_caps: route capabilities (e.g. %NETIF_F_TSO) | 179 | * @sk_route_caps: route capabilities (e.g. %NETIF_F_TSO) |
180 | * @sk_route_nocaps: forbidden route capabilities (e.g NETIF_F_GSO_MASK) | ||
180 | * @sk_gso_type: GSO type (e.g. %SKB_GSO_TCPV4) | 181 | * @sk_gso_type: GSO type (e.g. %SKB_GSO_TCPV4) |
181 | * @sk_gso_max_size: Maximum GSO segment size to build | 182 | * @sk_gso_max_size: Maximum GSO segment size to build |
182 | * @sk_lingertime: %SO_LINGER l_linger setting | 183 | * @sk_lingertime: %SO_LINGER l_linger setting |
@@ -276,6 +277,7 @@ struct sock { | |||
276 | int sk_forward_alloc; | 277 | int sk_forward_alloc; |
277 | gfp_t sk_allocation; | 278 | gfp_t sk_allocation; |
278 | int sk_route_caps; | 279 | int sk_route_caps; |
280 | int sk_route_nocaps; | ||
279 | int sk_gso_type; | 281 | int sk_gso_type; |
280 | unsigned int sk_gso_max_size; | 282 | unsigned int sk_gso_max_size; |
281 | int sk_rcvlowat; | 283 | int sk_rcvlowat; |
@@ -1335,6 +1337,12 @@ static inline int sk_can_gso(const struct sock *sk) | |||
1335 | 1337 | ||
1336 | extern void sk_setup_caps(struct sock *sk, struct dst_entry *dst); | 1338 | extern void sk_setup_caps(struct sock *sk, struct dst_entry *dst); |
1337 | 1339 | ||
1340 | static inline void sk_nocaps_add(struct sock *sk, int flags) | ||
1341 | { | ||
1342 | sk->sk_route_nocaps |= flags; | ||
1343 | sk->sk_route_caps &= ~flags; | ||
1344 | } | ||
1345 | |||
1338 | static inline int skb_copy_to_page(struct sock *sk, char __user *from, | 1346 | static inline int skb_copy_to_page(struct sock *sk, char __user *from, |
1339 | struct sk_buff *skb, struct page *page, | 1347 | struct sk_buff *skb, struct page *page, |
1340 | int off, int copy) | 1348 | int off, int copy) |