diff options
author | Eric Dumazet <edumazet@google.com> | 2016-04-01 11:52:20 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-04-04 22:11:20 -0400 |
commit | 9caad864151e525929d323de96cad382da49c3b2 (patch) | |
tree | 76935ef9f746ebccd30c6cb397bc920ad1cb4b98 | |
parent | 532182cd610782db8c18230c2747626562032205 (diff) |
tcp: increment sk_drops for listeners
Goal: packets dropped by a listener are accounted for.
This adds tcp_listendrop() helper, and clears sk_drops in sk_clone_lock()
so that children do not inherit their parent drop count.
Note that we no longer increment LINUX_MIB_LISTENDROPS counter when
sending a SYNCOOKIE, since the SYN packet generated a SYNACK.
We already have a separate LINUX_MIB_SYNCOOKIESSENT
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/tcp.h | 13 | ||||
-rw-r--r-- | net/core/sock.c | 1 | ||||
-rw-r--r-- | net/ipv4/tcp_input.c | 8 | ||||
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 6 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 4 |
5 files changed, 24 insertions, 8 deletions
diff --git a/include/net/tcp.h b/include/net/tcp.h index a23282996ca9..74d3ed5eb219 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h | |||
@@ -1836,4 +1836,17 @@ static inline void tcp_segs_in(struct tcp_sock *tp, const struct sk_buff *skb) | |||
1836 | tp->data_segs_in += segs_in; | 1836 | tp->data_segs_in += segs_in; |
1837 | } | 1837 | } |
1838 | 1838 | ||
1839 | /* | ||
1840 | * TCP listen path runs lockless. | ||
1841 | * We forced "struct sock" to be const qualified to make sure | ||
1842 | * we don't modify one of its field by mistake. | ||
1843 | * Here, we increment sk_drops which is an atomic_t, so we can safely | ||
1844 | * make sock writable again. | ||
1845 | */ | ||
1846 | static inline void tcp_listendrop(const struct sock *sk) | ||
1847 | { | ||
1848 | atomic_inc(&((struct sock *)sk)->sk_drops); | ||
1849 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); | ||
1850 | } | ||
1851 | |||
1839 | #endif /* _TCP_H */ | 1852 | #endif /* _TCP_H */ |
diff --git a/net/core/sock.c b/net/core/sock.c index 7a6a063b28b3..2f517ea56786 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -1525,6 +1525,7 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority) | |||
1525 | newsk->sk_dst_cache = NULL; | 1525 | newsk->sk_dst_cache = NULL; |
1526 | newsk->sk_wmem_queued = 0; | 1526 | newsk->sk_wmem_queued = 0; |
1527 | newsk->sk_forward_alloc = 0; | 1527 | newsk->sk_forward_alloc = 0; |
1528 | atomic_set(&newsk->sk_drops, 0); | ||
1528 | newsk->sk_send_head = NULL; | 1529 | newsk->sk_send_head = NULL; |
1529 | newsk->sk_userlocks = sk->sk_userlocks & ~SOCK_BINDPORT_LOCK; | 1530 | newsk->sk_userlocks = sk->sk_userlocks & ~SOCK_BINDPORT_LOCK; |
1530 | 1531 | ||
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 0ffcd07e3409..983f04c11177 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -6339,8 +6339,10 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops, | |||
6339 | inet_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT); | 6339 | inet_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT); |
6340 | af_ops->send_synack(sk, dst, &fl, req, | 6340 | af_ops->send_synack(sk, dst, &fl, req, |
6341 | &foc, !want_cookie); | 6341 | &foc, !want_cookie); |
6342 | if (want_cookie) | 6342 | if (want_cookie) { |
6343 | goto drop_and_free; | 6343 | reqsk_free(req); |
6344 | return 0; | ||
6345 | } | ||
6344 | } | 6346 | } |
6345 | reqsk_put(req); | 6347 | reqsk_put(req); |
6346 | return 0; | 6348 | return 0; |
@@ -6350,7 +6352,7 @@ drop_and_release: | |||
6350 | drop_and_free: | 6352 | drop_and_free: |
6351 | reqsk_free(req); | 6353 | reqsk_free(req); |
6352 | drop: | 6354 | drop: |
6353 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); | 6355 | tcp_listendrop(sk); |
6354 | return 0; | 6356 | return 0; |
6355 | } | 6357 | } |
6356 | EXPORT_SYMBOL(tcp_conn_request); | 6358 | EXPORT_SYMBOL(tcp_conn_request); |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 059a98f5e7e1..f3ce0afe70aa 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -329,7 +329,7 @@ void tcp_req_err(struct sock *sk, u32 seq, bool abort) | |||
329 | * errors returned from accept(). | 329 | * errors returned from accept(). |
330 | */ | 330 | */ |
331 | inet_csk_reqsk_queue_drop(req->rsk_listener, req); | 331 | inet_csk_reqsk_queue_drop(req->rsk_listener, req); |
332 | NET_INC_STATS_BH(net, LINUX_MIB_LISTENDROPS); | 332 | tcp_listendrop(req->rsk_listener); |
333 | } | 333 | } |
334 | reqsk_put(req); | 334 | reqsk_put(req); |
335 | } | 335 | } |
@@ -1246,7 +1246,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1246 | &tcp_request_sock_ipv4_ops, sk, skb); | 1246 | &tcp_request_sock_ipv4_ops, sk, skb); |
1247 | 1247 | ||
1248 | drop: | 1248 | drop: |
1249 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); | 1249 | tcp_listendrop(sk); |
1250 | return 0; | 1250 | return 0; |
1251 | } | 1251 | } |
1252 | EXPORT_SYMBOL(tcp_v4_conn_request); | 1252 | EXPORT_SYMBOL(tcp_v4_conn_request); |
@@ -1348,7 +1348,7 @@ exit_overflow: | |||
1348 | exit_nonewsk: | 1348 | exit_nonewsk: |
1349 | dst_release(dst); | 1349 | dst_release(dst); |
1350 | exit: | 1350 | exit: |
1351 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); | 1351 | tcp_listendrop(sk); |
1352 | return NULL; | 1352 | return NULL; |
1353 | put_and_exit: | 1353 | put_and_exit: |
1354 | inet_csk_prepare_forced_close(newsk); | 1354 | inet_csk_prepare_forced_close(newsk); |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 5fa8fea394c9..7cde1b6fdda3 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -964,7 +964,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
964 | &tcp_request_sock_ipv6_ops, sk, skb); | 964 | &tcp_request_sock_ipv6_ops, sk, skb); |
965 | 965 | ||
966 | drop: | 966 | drop: |
967 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); | 967 | tcp_listendrop(sk); |
968 | return 0; /* don't send reset */ | 968 | return 0; /* don't send reset */ |
969 | } | 969 | } |
970 | 970 | ||
@@ -1169,7 +1169,7 @@ out_overflow: | |||
1169 | out_nonewsk: | 1169 | out_nonewsk: |
1170 | dst_release(dst); | 1170 | dst_release(dst); |
1171 | out: | 1171 | out: |
1172 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); | 1172 | tcp_listendrop(sk); |
1173 | return NULL; | 1173 | return NULL; |
1174 | } | 1174 | } |
1175 | 1175 | ||