aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2016-04-01 11:52:20 -0400
committerDavid S. Miller <davem@davemloft.net>2016-04-04 22:11:20 -0400
commit9caad864151e525929d323de96cad382da49c3b2 (patch)
tree76935ef9f746ebccd30c6cb397bc920ad1cb4b98
parent532182cd610782db8c18230c2747626562032205 (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.h13
-rw-r--r--net/core/sock.c1
-rw-r--r--net/ipv4/tcp_input.c8
-rw-r--r--net/ipv4/tcp_ipv4.c6
-rw-r--r--net/ipv6/tcp_ipv6.c4
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 */
1846static 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:
6350drop_and_free: 6352drop_and_free:
6351 reqsk_free(req); 6353 reqsk_free(req);
6352drop: 6354drop:
6353 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); 6355 tcp_listendrop(sk);
6354 return 0; 6356 return 0;
6355} 6357}
6356EXPORT_SYMBOL(tcp_conn_request); 6358EXPORT_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
1248drop: 1248drop:
1249 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); 1249 tcp_listendrop(sk);
1250 return 0; 1250 return 0;
1251} 1251}
1252EXPORT_SYMBOL(tcp_v4_conn_request); 1252EXPORT_SYMBOL(tcp_v4_conn_request);
@@ -1348,7 +1348,7 @@ exit_overflow:
1348exit_nonewsk: 1348exit_nonewsk:
1349 dst_release(dst); 1349 dst_release(dst);
1350exit: 1350exit:
1351 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); 1351 tcp_listendrop(sk);
1352 return NULL; 1352 return NULL;
1353put_and_exit: 1353put_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
966drop: 966drop:
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:
1169out_nonewsk: 1169out_nonewsk:
1170 dst_release(dst); 1170 dst_release(dst);
1171out: 1171out:
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