diff options
author | Octavian Purdila <opurdila@ixiacom.com> | 2010-01-17 22:09:39 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-01-17 22:09:39 -0500 |
commit | 72659ecce68588b74f6c46862c2b4cec137d7a5a (patch) | |
tree | 791c5900e2a2b219774904cef7fab90fa462b81c | |
parent | 0ec00f0392b807d57a2281576a96552d7694b6bb (diff) |
tcp: account SYN-ACK timeouts & retransmissions
Currently we don't increment SYN-ACK timeouts & retransmissions
although we do increment the same stats for SYN. We seem to have lost
the SYN-ACK accounting with the introduction of tcp_syn_recv_timer
(commit 2248761e in the netdev-vger-cvs tree).
This patch fixes this issue. In the process we also rename the v4/v6
syn/ack retransmit functions for clarity. We also add a new
request_socket operations (syn_ack_timeout) so we can keep code in
inet_connection_sock.c protocol agnostic.
Signed-off-by: Octavian Purdila <opurdila@ixiacom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/request_sock.h | 2 | ||||
-rw-r--r-- | include/net/tcp.h | 2 | ||||
-rw-r--r-- | net/ipv4/inet_connection_sock.c | 2 | ||||
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 18 | ||||
-rw-r--r-- | net/ipv4/tcp_timer.c | 6 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 12 |
6 files changed, 32 insertions, 10 deletions
diff --git a/include/net/request_sock.h b/include/net/request_sock.h index c9b50ebd9ce9..99e6e19b57c2 100644 --- a/include/net/request_sock.h +++ b/include/net/request_sock.h | |||
@@ -45,6 +45,8 @@ struct request_sock_ops { | |||
45 | void (*send_reset)(struct sock *sk, | 45 | void (*send_reset)(struct sock *sk, |
46 | struct sk_buff *skb); | 46 | struct sk_buff *skb); |
47 | void (*destructor)(struct request_sock *req); | 47 | void (*destructor)(struct request_sock *req); |
48 | void (*syn_ack_timeout)(struct sock *sk, | ||
49 | struct request_sock *req); | ||
48 | }; | 50 | }; |
49 | 51 | ||
50 | /* struct request_sock - mini sock to represent a connection request | 52 | /* struct request_sock - mini sock to represent a connection request |
diff --git a/include/net/tcp.h b/include/net/tcp.h index 788c99f98597..87d164b9bd8f 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h | |||
@@ -400,6 +400,8 @@ extern int compat_tcp_setsockopt(struct sock *sk, | |||
400 | int level, int optname, | 400 | int level, int optname, |
401 | char __user *optval, unsigned int optlen); | 401 | char __user *optval, unsigned int optlen); |
402 | extern void tcp_set_keepalive(struct sock *sk, int val); | 402 | extern void tcp_set_keepalive(struct sock *sk, int val); |
403 | extern void tcp_syn_ack_timeout(struct sock *sk, | ||
404 | struct request_sock *req); | ||
403 | extern int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, | 405 | extern int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, |
404 | struct msghdr *msg, | 406 | struct msghdr *msg, |
405 | size_t len, int nonblock, | 407 | size_t len, int nonblock, |
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index ee16475f8fc3..8da6429269dd 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c | |||
@@ -529,6 +529,8 @@ void inet_csk_reqsk_queue_prune(struct sock *parent, | |||
529 | syn_ack_recalc(req, thresh, max_retries, | 529 | syn_ack_recalc(req, thresh, max_retries, |
530 | queue->rskq_defer_accept, | 530 | queue->rskq_defer_accept, |
531 | &expire, &resend); | 531 | &expire, &resend); |
532 | if (req->rsk_ops->syn_ack_timeout) | ||
533 | req->rsk_ops->syn_ack_timeout(parent, req); | ||
532 | if (!expire && | 534 | if (!expire && |
533 | (!resend || | 535 | (!resend || |
534 | !req->rsk_ops->rtx_syn_ack(parent, req, NULL) || | 536 | !req->rsk_ops->rtx_syn_ack(parent, req, NULL) || |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 382f667238ec..356f544c4c10 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -742,9 +742,9 @@ static void tcp_v4_reqsk_send_ack(struct sock *sk, struct sk_buff *skb, | |||
742 | * This still operates on a request_sock only, not on a big | 742 | * This still operates on a request_sock only, not on a big |
743 | * socket. | 743 | * socket. |
744 | */ | 744 | */ |
745 | static int __tcp_v4_send_synack(struct sock *sk, struct dst_entry *dst, | 745 | static int tcp_v4_send_synack(struct sock *sk, struct dst_entry *dst, |
746 | struct request_sock *req, | 746 | struct request_sock *req, |
747 | struct request_values *rvp) | 747 | struct request_values *rvp) |
748 | { | 748 | { |
749 | const struct inet_request_sock *ireq = inet_rsk(req); | 749 | const struct inet_request_sock *ireq = inet_rsk(req); |
750 | int err = -1; | 750 | int err = -1; |
@@ -775,10 +775,11 @@ static int __tcp_v4_send_synack(struct sock *sk, struct dst_entry *dst, | |||
775 | return err; | 775 | return err; |
776 | } | 776 | } |
777 | 777 | ||
778 | static int tcp_v4_send_synack(struct sock *sk, struct request_sock *req, | 778 | static int tcp_v4_rtx_synack(struct sock *sk, struct request_sock *req, |
779 | struct request_values *rvp) | 779 | struct request_values *rvp) |
780 | { | 780 | { |
781 | return __tcp_v4_send_synack(sk, NULL, req, rvp); | 781 | TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS); |
782 | return tcp_v4_send_synack(sk, NULL, req, rvp); | ||
782 | } | 783 | } |
783 | 784 | ||
784 | /* | 785 | /* |
@@ -1192,10 +1193,11 @@ static int tcp_v4_inbound_md5_hash(struct sock *sk, struct sk_buff *skb) | |||
1192 | struct request_sock_ops tcp_request_sock_ops __read_mostly = { | 1193 | struct request_sock_ops tcp_request_sock_ops __read_mostly = { |
1193 | .family = PF_INET, | 1194 | .family = PF_INET, |
1194 | .obj_size = sizeof(struct tcp_request_sock), | 1195 | .obj_size = sizeof(struct tcp_request_sock), |
1195 | .rtx_syn_ack = tcp_v4_send_synack, | 1196 | .rtx_syn_ack = tcp_v4_rtx_synack, |
1196 | .send_ack = tcp_v4_reqsk_send_ack, | 1197 | .send_ack = tcp_v4_reqsk_send_ack, |
1197 | .destructor = tcp_v4_reqsk_destructor, | 1198 | .destructor = tcp_v4_reqsk_destructor, |
1198 | .send_reset = tcp_v4_send_reset, | 1199 | .send_reset = tcp_v4_send_reset, |
1200 | .syn_ack_timeout = tcp_syn_ack_timeout, | ||
1199 | }; | 1201 | }; |
1200 | 1202 | ||
1201 | #ifdef CONFIG_TCP_MD5SIG | 1203 | #ifdef CONFIG_TCP_MD5SIG |
@@ -1373,8 +1375,8 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1373 | } | 1375 | } |
1374 | tcp_rsk(req)->snt_isn = isn; | 1376 | tcp_rsk(req)->snt_isn = isn; |
1375 | 1377 | ||
1376 | if (__tcp_v4_send_synack(sk, dst, req, | 1378 | if (tcp_v4_send_synack(sk, dst, req, |
1377 | (struct request_values *)&tmp_ext) || | 1379 | (struct request_values *)&tmp_ext) || |
1378 | want_cookie) | 1380 | want_cookie) |
1379 | goto drop_and_free; | 1381 | goto drop_and_free; |
1380 | 1382 | ||
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index 8816a20c2597..de7d1bf9114f 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c | |||
@@ -474,6 +474,12 @@ static void tcp_synack_timer(struct sock *sk) | |||
474 | TCP_TIMEOUT_INIT, TCP_RTO_MAX); | 474 | TCP_TIMEOUT_INIT, TCP_RTO_MAX); |
475 | } | 475 | } |
476 | 476 | ||
477 | void tcp_syn_ack_timeout(struct sock *sk, struct request_sock *req) | ||
478 | { | ||
479 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPTIMEOUTS); | ||
480 | } | ||
481 | EXPORT_SYMBOL(tcp_syn_ack_timeout); | ||
482 | |||
477 | void tcp_set_keepalive(struct sock *sk, int val) | 483 | void tcp_set_keepalive(struct sock *sk, int val) |
478 | { | 484 | { |
479 | if ((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN)) | 485 | if ((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN)) |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 1c832bf198b3..82f2dea0e39e 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -520,6 +520,13 @@ done: | |||
520 | return err; | 520 | return err; |
521 | } | 521 | } |
522 | 522 | ||
523 | static int tcp_v6_rtx_synack(struct sock *sk, struct request_sock *req, | ||
524 | struct request_values *rvp) | ||
525 | { | ||
526 | TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS); | ||
527 | return tcp_v6_send_synack(sk, req, rvp); | ||
528 | } | ||
529 | |||
523 | static inline void syn_flood_warning(struct sk_buff *skb) | 530 | static inline void syn_flood_warning(struct sk_buff *skb) |
524 | { | 531 | { |
525 | #ifdef CONFIG_SYN_COOKIES | 532 | #ifdef CONFIG_SYN_COOKIES |
@@ -890,10 +897,11 @@ static int tcp_v6_inbound_md5_hash (struct sock *sk, struct sk_buff *skb) | |||
890 | struct request_sock_ops tcp6_request_sock_ops __read_mostly = { | 897 | struct request_sock_ops tcp6_request_sock_ops __read_mostly = { |
891 | .family = AF_INET6, | 898 | .family = AF_INET6, |
892 | .obj_size = sizeof(struct tcp6_request_sock), | 899 | .obj_size = sizeof(struct tcp6_request_sock), |
893 | .rtx_syn_ack = tcp_v6_send_synack, | 900 | .rtx_syn_ack = tcp_v6_rtx_synack, |
894 | .send_ack = tcp_v6_reqsk_send_ack, | 901 | .send_ack = tcp_v6_reqsk_send_ack, |
895 | .destructor = tcp_v6_reqsk_destructor, | 902 | .destructor = tcp_v6_reqsk_destructor, |
896 | .send_reset = tcp_v6_send_reset | 903 | .send_reset = tcp_v6_send_reset, |
904 | .syn_ack_timeout = tcp_syn_ack_timeout, | ||
897 | }; | 905 | }; |
898 | 906 | ||
899 | #ifdef CONFIG_TCP_MD5SIG | 907 | #ifdef CONFIG_TCP_MD5SIG |