TCP keepalive question
Subsystems (3)
Hi,
I'm reading the RFC 1122 and it says the following:
...
Keep-alive packets MUST only be sent when no data or acknowledgement packets have been received for the connection within an interval.
...
The receiving acknowledgement part seems to be ok and handled by tcp_keepalive_timer() when it does
elapsed = tcp_time_stamp - tp->rcv_tstamp;
However, if one side just receive data and reply with ACK, the keepalive probes is sent anyway - 2.6.32.9-70.fc12.i686.PAE.
Any reason to not reset keepalive timer when data is received?
Socket options used:SO_KEEPALIVE, TCP_KEEPIDLE=40, TCP_KEEPCNT=6, TCP_KEEPINTVL=5
Traffic dump attached.
thanks!
Signature · 1 line
Flavio
PATCH 1/1 TCP: avoid to send keepalive probes if it is receiving data
RFC 1122 says the following:
...
Keep-alive packets MUST only be sent when no data or acknowledgement packets have been received for the connection within an interval.
...
Fix this by storing the timestamp of last received data packet and checking for it when the keepalive timer expires.
--- include/linux/tcp.h | 1 + net/ipv4/tcp_input.c | 3 +++ net/ipv4/tcp_timer.c | 8 ++++++++ 3 files changed, 12 insertions(+), 0 deletions(-)
include/linux/tcp.h +1 -0
@@ -314,6 +314,7 @@ struct tcp_sock {u32 snd_sml;/* Last byte of the most recently transmitted small packet */ u32 rcv_tstamp;/* timestamp of last received ACK (for keepalives) */ u32 lsndtime;/* timestamp of last sent data packet (for restart window) */ +u32 lrcvtime;/* timestamp of last received data packet (for keepalives) */ /* Data for direct copy to user */ struct {
net/ipv4/tcp_input.c +3 -0
@@ -5391,6 +5391,8 @@ no_ack:__kfree_skb (skb); else sk->sk_data_ready(sk, 0); + + tp->lrcvtime = tcp_time_stamp;return 0 ; } }
@@ -5421,6 +5423,7 @@ step5:tcp_data_snd_check (sk);tcp_ack_snd_check (sk); + tp->lrcvtime = tcp_time_stamp;return 0 ; csum_error:
net/ipv4/tcp_timer.c +8 -0
@@ -554,6 +554,14 @@ static void tcp_keepalive_timer (unsigned long data)if (tp->packets_out ||tcp_send_head (sk)) goto resched; + elapsed = tcp_time_stamp - tp->lrcvtime; + +/* receiving data means alive */ +if (elapsed <keepalive_time_when (tp)) { + elapsed =keepalive_time_when (tp) - elapsed; + goto resched; + } + elapsed = tcp_time_stamp - tp->rcv_tstamp;if (elapsed >=keepalive_time_when (tp)) {
Signature · 1 line
1.6.6.1
Re: [PATCH] TCP: avoid to send keepalive probes if it is receiving data
Quoted 11 lines · Flavio Leitner
RFC 1122 says the following:
...
Keep-alive packets MUST only be sent when no data or acknowledgement packets have been received for the connection within an interval.
...Fix this by storing the timestamp of last received data packet and checking for it when the keepalive timer expires.
Signed-off-by Flavio Leitner <[email protected]>
Thanks Flavio !
Shouldnt you also change do_tcp_setsockopt() TCP_KEEPIDLE for consistency ?
net/ipv4/tcp.c +4 -1
@@ -2298,7 +2298,10 @@ static int do_tcp_setsockopt(struct sock *sk, int level,if (sock_flag (sk,SOCK_KEEPOPEN ) && !((1 << sk->sk_state) & (TCPF_CLOSE |TCPF_LISTEN ))) { -__u32 elapsed = tcp_time_stamp - tp->rcv_tstamp; +u32 elapsed =min_t (u32, + tcp_time_stamp - tp->rcv_tstamp, + tcp_time_stamp - tp->lrcvtime); +if (tp->keepalive_time > elapsed) elapsed = tp->keepalive_time - elapsed;else
Quoted 58 lines
--- include/linux/tcp.h | 1 + net/ipv4/tcp_input.c | 3 +++ net/ipv4/tcp_timer.c | 8 ++++++++ 3 files changed, 12 insertions(+), 0 deletions(-)include/linux/tcp.h +1
-0@@ -314,6 +314,7 @@ struct tcp_sock {u32 snd_sml;/* Last byte of the most recently transmitted small packet */ u32 rcv_tstamp;/* timestamp of last received ACK (for keepalives) */ u32 lsndtime;/* timestamp of last sent data packet (for restart window) */ +u32 lrcvtime;/* timestamp of last received data packet (for keepalives) */ /* Data for direct copy to user */ struct {net/ipv4/tcp_input.c +3
-0@@ -5391,6 +5391,8 @@ no_ack:__kfree_skb (skb); else sk->sk_data_ready(sk, 0); + + tp->lrcvtime = tcp_time_stamp;return 0 ; } }@@ -5421,6 +5423,7 @@ step5:tcp_data_snd_check (sk);tcp_ack_snd_check (sk); + tp->lrcvtime = tcp_time_stamp;return 0 ; csum_error:net/ipv4/tcp_timer.c +8
-0@@ -554,6 +554,14 @@ static void tcp_keepalive_timer (unsigned long data)if (tp->packets_out ||tcp_send_head (sk)) goto resched; + elapsed = tcp_time_stamp - tp->lrcvtime; + +/* receiving data means alive */ +if (elapsed <keepalive_time_when (tp)) { + elapsed =keepalive_time_when (tp) - elapsed; + goto resched; + } + elapsed = tcp_time_stamp - tp->rcv_tstamp;if (elapsed >=keepalive_time_when (tp)) {
PATCH v2 1/1 TCP: avoid to send keepalive probes if it is receiving data
RFC 1122 says the following:
...
Keep-alive packets MUST only be sent when no data or acknowledgement packets have been received for the connection within an interval.
...
Fix this by storing the timestamp of last received data packet and checking for it when the keepalive timer expires.
-v2 fix do_tcp_setsockopt() as pointed by Eric Dumazet <[email protected]>
--- include/linux/tcp.h | 1 + net/ipv4/tcp.c | 5 ++++- net/ipv4/tcp_input.c | 3 +++ net/ipv4/tcp_timer.c | 8 ++++++++ 4 files changed, 16 insertions(+), 1 deletions(-)
include/linux/tcp.h +1 -0
@@ -314,6 +314,7 @@ struct tcp_sock {u32 snd_sml;/* Last byte of the most recently transmitted small packet */ u32 rcv_tstamp;/* timestamp of last received ACK (for keepalives) */ u32 lsndtime;/* timestamp of last sent data packet (for restart window) */ +u32 lrcvtime;/* timestamp of last received data packet (for keepalives) */ /* Data for direct copy to user */ struct {
net/ipv4/tcp.c +4 -1
@@ -2298,7 +2298,10 @@ static int do_tcp_setsockopt(struct sock *sk, int level,if (sock_flag (sk,SOCK_KEEPOPEN ) && !((1 << sk->sk_state) & (TCPF_CLOSE |TCPF_LISTEN ))) { -__u32 elapsed = tcp_time_stamp - tp->rcv_tstamp; +u32 elapsed =min_t (u32, + tcp_time_stamp - tp->rcv_tstamp, + tcp_time_stamp - tp->lrcvtime); +if (tp->keepalive_time > elapsed) elapsed = tp->keepalive_time - elapsed;else
net/ipv4/tcp_input.c +3 -0
@@ -5391,6 +5391,8 @@ no_ack:__kfree_skb (skb); else sk->sk_data_ready(sk, 0); + + tp->lrcvtime = tcp_time_stamp;return 0 ; } }
@@ -5421,6 +5423,7 @@ step5:tcp_data_snd_check (sk);tcp_ack_snd_check (sk); + tp->lrcvtime = tcp_time_stamp;return 0 ; csum_error:
net/ipv4/tcp_timer.c +8 -0
@@ -554,6 +554,14 @@ static void tcp_keepalive_timer (unsigned long data)if (tp->packets_out ||tcp_send_head (sk)) goto resched; + elapsed = tcp_time_stamp - tp->lrcvtime; + +/* receiving data means alive */ +if (elapsed <keepalive_time_when (tp)) { + elapsed =keepalive_time_when (tp) - elapsed; + goto resched; + } + elapsed = tcp_time_stamp - tp->rcv_tstamp;if (elapsed >=keepalive_time_when (tp)) {
Signature · 1 line
1.5.5.6
Re: [PATCH v2] TCP: avoid to send keepalive probes if it is receiving data
Quoted 7 lines · Flavio Leitner
RFC 1122 says the following:
...
Keep-alive packets MUST only be sent when no data or acknowledgement packets have been received for the connection within an interval.
...
Quoted 6 lines
Fix this by storing the timestamp of last received data packet and checking for it when the keepalive timer expires.
-v2 fix
do_tcp_setsockopt()as pointed by Eric Dumazet <[email protected]>Signed-off-by Flavio Leitner <[email protected]>
I find this patch very welcome, and we could easily use this new lrcvtime information available in diagnostic tools (ss command)
But are you sure you update it for all valid packets ?
If we receive a pure ACK, it seems you do not ...
Quoted 75 lines
--- include/linux/tcp.h | 1 + net/ipv4/tcp.c | 5 ++++- net/ipv4/tcp_input.c | 3 +++ net/ipv4/tcp_timer.c | 8 ++++++++ 4 files changed, 16 insertions(+), 1 deletions(-)include/linux/tcp.h +1
-0@@ -314,6 +314,7 @@ struct tcp_sock {u32 snd_sml;/* Last byte of the most recently transmitted small packet */ u32 rcv_tstamp;/* timestamp of last received ACK (for keepalives) */ u32 lsndtime;/* timestamp of last sent data packet (for restart window) */ +u32 lrcvtime;/* timestamp of last received data packet (for keepalives) */ /* Data for direct copy to user */ struct {net/ipv4/tcp.c +4
-1@@ -2298,7 +2298,10 @@ static int do_tcp_setsockopt(struct sock *sk, int level,if (sock_flag (sk,SOCK_KEEPOPEN ) && !((1 << sk->sk_state) & (TCPF_CLOSE |TCPF_LISTEN ))) { -__u32 elapsed = tcp_time_stamp - tp->rcv_tstamp; +u32 elapsed =min_t (u32, + tcp_time_stamp - tp->rcv_tstamp, + tcp_time_stamp - tp->lrcvtime); +if (tp->keepalive_time > elapsed) elapsed = tp->keepalive_time - elapsed;else net/ipv4/tcp_input.c +3
-0@@ -5391,6 +5391,8 @@ no_ack:__kfree_skb (skb); else sk->sk_data_ready(sk, 0); + + tp->lrcvtime = tcp_time_stamp;return 0 ; } }@@ -5421,6 +5423,7 @@ step5:tcp_data_snd_check (sk);tcp_ack_snd_check (sk); + tp->lrcvtime = tcp_time_stamp;return 0 ; csum_error:net/ipv4/tcp_timer.c +8
-0@@ -554,6 +554,14 @@ static void tcp_keepalive_timer (unsigned long data)if (tp->packets_out ||tcp_send_head (sk)) goto resched; + elapsed = tcp_time_stamp - tp->lrcvtime; + +/* receiving data means alive */ +if (elapsed <keepalive_time_when (tp)) { + elapsed =keepalive_time_when (tp) - elapsed; + goto resched; + } + elapsed = tcp_time_stamp - tp->rcv_tstamp;if (elapsed >=keepalive_time_when (tp)) {
Re: [PATCH v2] TCP: avoid to send keepalive probes if it is receiving data
Quoted 16 lines · Eric Dumazet
Quoted 7 lines · Flavio Leitner
RFC 1122 says the following:
...
Keep-alive packets MUST only be sent when no data or acknowledgement packets have been received for the connection within an interval.
...Quoted 6 lines
Fix this by storing the timestamp of last received data packet and checking for it when the keepalive timer expires.
-v2 fix
do_tcp_setsockopt()as pointed by Eric Dumazet <[email protected]>Signed-off-by Flavio Leitner <[email protected]>
Quoted 6 lines
I find this patch very welcome, and we could easily use this new lrcvtime information available in diagnostic tools (ss command)
But are you sure you update it for all valid packets ?
If we receive a pure ACK, it seems you do not ...
I fail to see why the addition of this new variable is necessary at all, could either of you enlight me why exactly it's necessary and rcv_tstamp will not suffice?
Quoted 75 lines
Quoted 75 lines
--- include/linux/tcp.h | 1 + net/ipv4/tcp.c | 5 ++++- net/ipv4/tcp_input.c | 3 +++ net/ipv4/tcp_timer.c | 8 ++++++++ 4 files changed, 16 insertions(+), 1 deletions(-)include/linux/tcp.h +1
-0@@ -314,6 +314,7 @@ struct tcp_sock {u32 snd_sml;/* Last byte of the most recently transmitted small packet */ u32 rcv_tstamp;/* timestamp of last received ACK (for keepalives) */ u32 lsndtime;/* timestamp of last sent data packet (for restart window) */ +u32 lrcvtime;/* timestamp of last received data packet (for keepalives) */ /* Data for direct copy to user */ struct {net/ipv4/tcp.c +4
-1@@ -2298,7 +2298,10 @@ static int do_tcp_setsockopt(struct sock *sk, int level,if (sock_flag (sk,SOCK_KEEPOPEN ) && !((1 << sk->sk_state) & (TCPF_CLOSE |TCPF_LISTEN ))) { -__u32 elapsed = tcp_time_stamp - tp->rcv_tstamp; +u32 elapsed =min_t (u32, + tcp_time_stamp - tp->rcv_tstamp, + tcp_time_stamp - tp->lrcvtime); +if (tp->keepalive_time > elapsed) elapsed = tp->keepalive_time - elapsed;else net/ipv4/tcp_input.c +3
-0@@ -5391,6 +5391,8 @@ no_ack:__kfree_skb (skb); else sk->sk_data_ready(sk, 0); + + tp->lrcvtime = tcp_time_stamp;return 0 ; } }@@ -5421,6 +5423,7 @@ step5:tcp_data_snd_check (sk);tcp_ack_snd_check (sk); + tp->lrcvtime = tcp_time_stamp;return 0 ; csum_error:net/ipv4/tcp_timer.c +8
-0@@ -554,6 +554,14 @@ static void tcp_keepalive_timer (unsigned long data)if (tp->packets_out ||tcp_send_head (sk)) goto resched; + elapsed = tcp_time_stamp - tp->lrcvtime; + +/* receiving data means alive */ +if (elapsed <keepalive_time_when (tp)) { + elapsed =keepalive_time_when (tp) - elapsed; + goto resched; + } + elapsed = tcp_time_stamp - tp->rcv_tstamp;if (elapsed >=keepalive_time_when (tp)) {
Signature · 1 line
i.
David Miller
maintainerRe: [PATCH v2] TCP: avoid to send keepalive probes if it is receiving data
From: "Ilpo Järvinen" <[email protected]>
Date: Sun, 18 Apr 2010 23:34:15 +0300 (EEST)
Quoted 3 lines
I fail to see why the addition of this new variable is necessary at all, could either of you enlight me why exactly it's necessary and
rcv_tstampwill not suffice?
I agree, the existing rcv_tstamp should serve this purpose just fine.
Re: [PATCH v2] TCP: avoid to send keepalive probes if it is receiving data
Quoted 9 lines · David Miller
From: "Ilpo Järvinen" <[email protected]>
Date: Sun, 18 Apr 2010 23:34:15 +0300 (EEST)Quoted 3 lines
I fail to see why the addition of this new variable is necessary at all, could either of you enlight me why exactly it's necessary and
rcv_tstampwill not suffice?I agree, the existing
rcv_tstampshould serve this purpose just fine.
I thought it would break TCP_INFO/tcp_get_info(). Actually, reviewing the code again I found another variable which does exactly what is needed.
I'll post a new patch for review.
thanks,
Signature · 1 line
Flavio
PATCH v3 1/1 TCP: avoid to send keepalive probes if receiving data
RFC 1122 says the following:
...
Keep-alive packets MUST only be sent when no data or acknowledgement packets have been received for the connection within an interval.
...
The acknowledgement packet is reseting the keepalive timer but the data packet isn't. This patch fixes it by checking the timestamp of the last received data packet too when the keepalive timer expires.
--- net/ipv4/tcp.c | 5 ++++- net/ipv4/tcp_timer.c | 8 ++++++++ 2 files changed, 12 insertions(+), 1 deletions(-)
net/ipv4/tcp.c +4 -1
@@ -2298,7 +2298,10 @@ static int do_tcp_setsockopt(struct sock *sk, int level,if (sock_flag (sk,SOCK_KEEPOPEN ) && !((1 << sk->sk_state) & (TCPF_CLOSE |TCPF_LISTEN ))) { -__u32 elapsed = tcp_time_stamp - tp->rcv_tstamp; +u32 elapsed =min_t (u32, + tcp_time_stamp - icsk->icsk_ack.lrcvtime, + tcp_time_stamp - tp->rcv_tstamp); +if (tp->keepalive_time > elapsed) elapsed = tp->keepalive_time - elapsed;else
net/ipv4/tcp_timer.c +8 -0
@@ -554,6 +554,14 @@ static void tcp_keepalive_timer (unsigned long data)if (tp->packets_out ||tcp_send_head (sk)) goto resched; + elapsed = tcp_time_stamp - icsk->icsk_ack.lrcvtime; + +/* receiving data means alive */ +if (elapsed <keepalive_time_when (tp)) { + elapsed =keepalive_time_when (tp) - elapsed; + goto resched; + } + elapsed = tcp_time_stamp - tp->rcv_tstamp;if (elapsed >=keepalive_time_when (tp)) {
Signature · 1 line
1.5.5.6
Re: [PATCH v3] TCP: avoid to send keepalive probes if receiving data
Quoted 23 lines · Flavio Leitner
RFC 1122 says the following:
...
Keep-alive packets MUST only be sent when no data or acknowledgement packets have been received for the connection within an interval.
...The acknowledgement packet is reseting the keepalive timer but the data packet isn't. This patch fixes it by checking the timestamp of the last received data packet too when the keepalive timer expires.
Signed-off-by Flavio Leitner <[email protected]>--- net/ipv4/tcp.c | 5 ++++- net/ipv4/tcp_timer.c | 8 ++++++++ 2 files changed, 12 insertions(+), 1 deletions(-)net/ipv4/tcp.c +0
-0
net/ipv4/tcp.c static int do_tcp_setsockopt(struct sock *sk, int level, · line 2304
Quoted 8 lines
net/ipv4/tcp.c +4
-1@@ -2298,7 +2298,10 @@ static int do_tcp_setsockopt(struct sock *sk, int level,if (sock_flag (sk,SOCK_KEEPOPEN ) && !((1 << sk->sk_state) & (TCPF_CLOSE |TCPF_LISTEN ))) { -__u32 elapsed = tcp_time_stamp - tp->rcv_tstamp; +u32 elapsed =min_t (u32, + tcp_time_stamp - icsk->icsk_ack.lrcvtime, + tcp_time_stamp - tp->rcv_tstamp); +
I'd put this into a helper in include/net/tcp.h
Quoted 10 lines
net/ipv4/tcp.c +0
-0if (tp->keepalive_time > elapsed) elapsed = tp->keepalive_time - elapsed;else net/ipv4/tcp_timer.c +0
-0@@ -554,6 +554,14 @@ static void tcp_keepalive_timer (unsigned long data)if (tp->packets_out ||tcp_send_head (sk)) goto resched;
net/ipv4/tcp_timer.c static void tcp_keepalive_timer (unsigned long data) · line 565
Quoted 10 lines
net/ipv4/tcp_timer.c +8
-0+ elapsed = tcp_time_stamp - icsk->icsk_ack.lrcvtime; + +/* receiving data means alive */ +if (elapsed <keepalive_time_when (tp)) { + elapsed =keepalive_time_when (tp) - elapsed; + goto resched; + } + elapsed = tcp_time_stamp - tp->rcv_tstamp;
...And then use it here too for setting the elapsed and doing the test and what follows only once?
Quoted 2 lines
net/ipv4/tcp_timer.c +0
-0if (elapsed >=keepalive_time_when (tp)) {
Signature · 1 line
i.
David Miller
maintainerRe: [PATCH v3] TCP: avoid to send keepalive probes if receiving data
From: "Ilpo Järvinen" <[email protected]>
Date: Mon, 26 Apr 2010 12:47:13 +0300 (EEST)
Quoted 10 lines
net/ipv4/tcp.c static int do_tcp_setsockopt(struct sock *sk, int level, · line 2304
Quoted 7 lines
net/ipv4/tcp.c +4
-1!((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN))) { -__u32 elapsed = tcp_time_stamp - tp->rcv_tstamp; +u32 elapsed =min_t (u32, + tcp_time_stamp - icsk->icsk_ack.lrcvtime, + tcp_time_stamp - tp->rcv_tstamp); +I'd put this into a helper in
include/net/tcp.h
...
Quoted 10 lines
net/ipv4/tcp_timer.c static void tcp_keepalive_timer (unsigned long data) · line 565
Quoted 6 lines
net/ipv4/tcp_timer.c +5
-0+if (elapsed <keepalive_time_when (tp)) { + elapsed =keepalive_time_when (tp) - elapsed; + goto resched; + } + elapsed = tcp_time_stamp - tp->rcv_tstamp;...And then use it here too for setting the elapsed and doing the test and what follows only once?
Agreed.
PATCH v4 1/1 TCP: avoid to send keepalive probes if receiving data
RFC 1122 says the following:
...
Keep-alive packets MUST only be sent when no data or acknowledgement packets have been received for the connection within an interval.
...
The acknowledgement packet is reseting the keepalive timer but the data packet isn't. This patch fixes it by checking the timestamp of the last received data packet too when the keepalive timer expires.
--- include/net/tcp.h | 8 ++++++++ net/ipv4/tcp.c | 2 +- net/ipv4/tcp_timer.c | 4 ++-- 3 files changed, 11 insertions(+), 3 deletions(-)
include/net/tcp.h +8 -0
@@ -1032,6 +1032,14 @@ static inline int keepalive_probes(const struct tcp_sock *tp)return tp->keepalive_probes ? : sysctl_tcp_keepalive_probes; } +static inline u32 keepalive_time_elapsed (const struct tcp_sock *tp) +{ +const struct inet_connection_sock *icsk = &tp->inet_conn; + +return min_t (u32, tcp_time_stamp - icsk->icsk_ack.lrcvtime, + tcp_time_stamp - tp->rcv_tstamp); +} +static inline int tcp_fin_time (const struct sock *sk) {int fin_timeout =tcp_sk (sk)->linger2 ? : sysctl_tcp_fin_timeout;
net/ipv4/tcp.c +1 -1
@@ -2298,7 +2298,7 @@ static int do_tcp_setsockopt(struct sock *sk, int level,if (sock_flag (sk,SOCK_KEEPOPEN ) && !((1 << sk->sk_state) & (TCPF_CLOSE |TCPF_LISTEN ))) { -__u32 elapsed = tcp_time_stamp - tp->rcv_tstamp; +u32 elapsed =keepalive_time_elapsed (tp);if (tp->keepalive_time > elapsed) elapsed = tp->keepalive_time - elapsed;else
net/ipv4/tcp_timer.c +2 -2
@@ -517,7 +517,7 @@ static void tcp_keepalive_timer (unsigned long data)struct sock *sk = (struct sock *) data;struct inet_connection_sock *icsk =inet_csk (sk);struct tcp_sock *tp =tcp_sk (sk); -__u32 elapsed; +u32 elapsed;/* Only process if socket is not in use. */ bh_lock_sock (sk);
@@ -554,7 +554,7 @@ static void tcp_keepalive_timer (unsigned long data)if (tp->packets_out ||tcp_send_head (sk)) goto resched; - elapsed = tcp_time_stamp - tp->rcv_tstamp; + elapsed =keepalive_time_elapsed (tp);if (elapsed >=keepalive_time_when (tp)) {if (icsk->icsk_probes_out >=keepalive_probes (tp)) {
Signature · 1 line
1.5.5.6
Re: [PATCH v4] TCP: avoid to send keepalive probes if receiving data
Quoted 7 lines · Flavio Leitner
RFC 1122 says the following:
...
Keep-alive packets MUST only be sent when no data or acknowledgement packets have been received for the connection within an interval.
...
Quoted 7 lines
The acknowledgement packet is reseting the keepalive timer but the data packet isn't. This patch fixes it by checking the timestamp of the last received data packet too when the keepalive timer expires.
Signed-off-by Flavio Leitner <[email protected]>---
Quoted 59 lines
include/net/tcp.h | 8 ++++++++ net/ipv4/tcp.c | 2 +- net/ipv4/tcp_timer.c | 4 ++-- 3 files changed, 11 insertions(+), 3 deletions(-)include/net/tcp.h +8
-0@@ -1032,6 +1032,14 @@ static inline int keepalive_probes(const struct tcp_sock *tp)return tp->keepalive_probes ? : sysctl_tcp_keepalive_probes; } +static inline u32 keepalive_time_elapsed (const struct tcp_sock *tp) +{ +const struct inet_connection_sock *icsk = &tp->inet_conn; + +return min_t (u32, tcp_time_stamp - icsk->icsk_ack.lrcvtime, + tcp_time_stamp - tp->rcv_tstamp); +} +static inline int tcp_fin_time (const struct sock *sk) {int fin_timeout =tcp_sk (sk)->linger2 ? : sysctl_tcp_fin_timeout;net/ipv4/tcp.c +1
-1@@ -2298,7 +2298,7 @@ static int do_tcp_setsockopt(struct sock *sk, int level,if (sock_flag (sk,SOCK_KEEPOPEN ) && !((1 << sk->sk_state) & (TCPF_CLOSE |TCPF_LISTEN ))) { -__u32 elapsed = tcp_time_stamp - tp->rcv_tstamp; +u32 elapsed =keepalive_time_elapsed (tp);if (tp->keepalive_time > elapsed) elapsed = tp->keepalive_time - elapsed;else net/ipv4/tcp_timer.c +2
-2@@ -517,7 +517,7 @@ static void tcp_keepalive_timer (unsigned long data)struct sock *sk = (struct sock *) data;struct inet_connection_sock *icsk =inet_csk (sk);struct tcp_sock *tp =tcp_sk (sk); -__u32 elapsed; +u32 elapsed;/* Only process if socket is not in use. */ bh_lock_sock (sk);@@ -554,7 +554,7 @@ static void tcp_keepalive_timer (unsigned long data)if (tp->packets_out ||tcp_send_head (sk)) goto resched; - elapsed = tcp_time_stamp - tp->rcv_tstamp; + elapsed =keepalive_time_elapsed (tp);if (elapsed >=keepalive_time_when (tp)) {if (icsk->icsk_probes_out >=keepalive_probes (tp)) {
Re: [PATCH v4] TCP: avoid to send keepalive probes if receiving data
In reply to Flavio LeitnerQuoted 65 lines · Flavio Leitner
RFC 1122 says the following:
...
Keep-alive packets MUST only be sent when no data or acknowledgement packets have been received for the connection within an interval.
...The acknowledgement packet is reseting the keepalive timer but the data packet isn't. This patch fixes it by checking the timestamp of the last received data packet too when the keepalive timer expires.
Signed-off-by Flavio Leitner <[email protected]>--- include/net/tcp.h | 8 ++++++++ net/ipv4/tcp.c | 2 +- net/ipv4/tcp_timer.c | 4 ++-- 3 files changed, 11 insertions(+), 3 deletions(-)include/net/tcp.h +8
-0@@ -1032,6 +1032,14 @@ static inline int keepalive_probes(const struct tcp_sock *tp)return tp->keepalive_probes ? : sysctl_tcp_keepalive_probes; } +static inline u32 keepalive_time_elapsed (const struct tcp_sock *tp) +{ +const struct inet_connection_sock *icsk = &tp->inet_conn; + +return min_t (u32, tcp_time_stamp - icsk->icsk_ack.lrcvtime, + tcp_time_stamp - tp->rcv_tstamp); +} +static inline int tcp_fin_time (const struct sock *sk) {int fin_timeout =tcp_sk (sk)->linger2 ? : sysctl_tcp_fin_timeout;net/ipv4/tcp.c +1
-1@@ -2298,7 +2298,7 @@ static int do_tcp_setsockopt(struct sock *sk, int level,if (sock_flag (sk,SOCK_KEEPOPEN ) && !((1 << sk->sk_state) & (TCPF_CLOSE |TCPF_LISTEN ))) { -__u32 elapsed = tcp_time_stamp - tp->rcv_tstamp; +u32 elapsed =keepalive_time_elapsed (tp);if (tp->keepalive_time > elapsed) elapsed = tp->keepalive_time - elapsed;else net/ipv4/tcp_timer.c +1
-1@@ -517,7 +517,7 @@ static void tcp_keepalive_timer (unsigned long data)struct sock *sk = (struct sock *) data;struct inet_connection_sock *icsk =inet_csk (sk);struct tcp_sock *tp =tcp_sk (sk); -__u32 elapsed; +u32 elapsed;/* Only process if socket is not in use. */ bh_lock_sock (sk);
net/ipv4/tcp_timer.c static void tcp_keepalive_timer (unsigned long data) · line 560
Quoted 8 lines
net/ipv4/tcp_timer.c +1
-1@@ -554,7 +554,7 @@ static void tcp_keepalive_timer (unsigned long data)if (tp->packets_out ||tcp_send_head (sk)) goto resched; - elapsed = tcp_time_stamp - tp->rcv_tstamp; + elapsed =keepalive_time_elapsed (tp);if (elapsed >=keepalive_time_when (tp)) {if (icsk->icsk_probes_out >=keepalive_probes (tp)) {
Thanks. Looks very nice now.
Signature · 1 line
i.
Re: [PATCH v4] TCP: avoid to send keepalive probes if receiving data
From: "Ilpo Järvinen" <[email protected]>
Date: Tue, 27 Apr 2010 09:08:08 +0300 (EEST)
Quoted 15 lines · Flavio Leitner
Quoted 14 lines
RFC 1122 says the following:
...
Keep-alive packets MUST only be sent when no data or acknowledgement packets have been received for the connection within an interval.
...The acknowledgement packet is reseting the keepalive timer but the data packet isn't. This patch fixes it by checking the timestamp of the last received data packet too when the keepalive timer expires.
Signed-off-by Flavio Leitner <[email protected]>
...
Quoted 1 line
Signed-off-by Eric Dumazet <[email protected]>
...
Quoted 1 line
Acked-by Ilpo Järvinen <[email protected]>
Applied, thanks everyone.
Re: [PATCH v2] TCP: avoid to send keepalive probes if it is receiving data
In reply to Eric DumazetQuoted 16 lines · Eric Dumazet
Quoted 7 lines · Flavio Leitner
RFC 1122 says the following:
...
Keep-alive packets MUST only be sent when no data or acknowledgement packets have been received for the connection within an interval.
...Quoted 6 lines
Fix this by storing the timestamp of last received data packet and checking for it when the keepalive timer expires.
-v2 fix
do_tcp_setsockopt()as pointed by Eric Dumazet <[email protected]>Signed-off-by Flavio Leitner <[email protected]>
Quoted 6 lines
I find this patch very welcome, and we could easily use this new lrcvtime information available in diagnostic tools (ss command)
But are you sure you update it for all valid packets ?
If we receive a pure ACK, it seems you do not ...
Pure ack is handled by rcv_tstamp in the struct which is considered in tcp_keepalive_time() too.
The idea of exporting those variables is nice, I'll see how 'ss' works.
thanks for reviewing the patch!
Quoted 81 lines
Quoted 65 lines
--- include/linux/tcp.h | 1 + net/ipv4/tcp.c | 5 ++++- net/ipv4/tcp_input.c | 3 +++ net/ipv4/tcp_timer.c | 8 ++++++++ 4 files changed, 16 insertions(+), 1 deletions(-)include/linux/tcp.h +1
-0@@ -314,6 +314,7 @@ struct tcp_sock {u32 snd_sml;/* Last byte of the most recently transmitted small packet */ u32 rcv_tstamp;/* timestamp of last received ACK (for keepalives) */ u32 lsndtime;/* timestamp of last sent data packet (for restart window) */ +u32 lrcvtime;/* timestamp of last received data packet (for keepalives) */ /* Data for direct copy to user */ struct {net/ipv4/tcp.c +4
-1@@ -2298,7 +2298,10 @@ static int do_tcp_setsockopt(struct sock *sk, int level,if (sock_flag (sk,SOCK_KEEPOPEN ) && !((1 << sk->sk_state) & (TCPF_CLOSE |TCPF_LISTEN ))) { -__u32 elapsed = tcp_time_stamp - tp->rcv_tstamp; +u32 elapsed =min_t (u32, + tcp_time_stamp - tp->rcv_tstamp, + tcp_time_stamp - tp->lrcvtime); +if (tp->keepalive_time > elapsed) elapsed = tp->keepalive_time - elapsed;else net/ipv4/tcp_input.c +3
-0@@ -5391,6 +5391,8 @@ no_ack:__kfree_skb (skb); else sk->sk_data_ready(sk, 0); + + tp->lrcvtime = tcp_time_stamp;return 0 ; } }@@ -5421,6 +5423,7 @@ step5:tcp_data_snd_check (sk);tcp_ack_snd_check (sk); + tp->lrcvtime = tcp_time_stamp;return 0 ; csum_error:net/ipv4/tcp_timer.c +1
-0@@ -554,6 +554,14 @@ static void tcp_keepalive_timer (unsigned long data)if (tp->packets_out ||tcp_send_head (sk)) goto resched; + elapsed = tcp_time_stamp - tp->lrcvtime;net/ipv4/tcp_timer.c static void tcp_keepalive_timer (unsigned long data) · line 567
Quoted 10 lines
net/ipv4/tcp_timer.c +7
-0+ +/* receiving data means alive */ +if (elapsed <keepalive_time_when (tp)) { + elapsed =keepalive_time_when (tp) - elapsed; + goto resched; + } + elapsed = tcp_time_stamp - tp->rcv_tstamp;if (elapsed >=keepalive_time_when (tp)) {--
To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Signature · 1 line
Flavio