Commit d6fb396c authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller

ipv4: tcp: fix ACK/RST sent with a transmit delay

If we want to set a EDT time for the skb we want to send
via ip_send_unicast_reply(), we have to pass a new parameter
and initialize ipc.sockc.transmit_time with it.

This fixes the EDT time for ACK/RST packets sent on behalf of
a TIME_WAIT socket.

Fixes: a842fe14 ("tcp: add optional per socket transmit delay")
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 3e189433
...@@ -279,7 +279,7 @@ void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb, ...@@ -279,7 +279,7 @@ void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb,
const struct ip_options *sopt, const struct ip_options *sopt,
__be32 daddr, __be32 saddr, __be32 daddr, __be32 saddr,
const struct ip_reply_arg *arg, const struct ip_reply_arg *arg,
unsigned int len); unsigned int len, u64 transmit_time);
#define IP_INC_STATS(net, field) SNMP_INC_STATS64((net)->mib.ip_statistics, field) #define IP_INC_STATS(net, field) SNMP_INC_STATS64((net)->mib.ip_statistics, field)
#define __IP_INC_STATS(net, field) __SNMP_INC_STATS64((net)->mib.ip_statistics, field) #define __IP_INC_STATS(net, field) __SNMP_INC_STATS64((net)->mib.ip_statistics, field)
......
...@@ -2240,15 +2240,18 @@ static inline void tcp_add_tx_delay(struct sk_buff *skb, ...@@ -2240,15 +2240,18 @@ static inline void tcp_add_tx_delay(struct sk_buff *skb,
skb->skb_mstamp_ns += (u64)tp->tcp_tx_delay * NSEC_PER_USEC; skb->skb_mstamp_ns += (u64)tp->tcp_tx_delay * NSEC_PER_USEC;
} }
static inline void tcp_set_tx_time(struct sk_buff *skb, /* Compute Earliest Departure Time for some control packets
const struct sock *sk) * like ACK or RST for TIME_WAIT or non ESTABLISHED sockets.
*/
static inline u64 tcp_transmit_time(const struct sock *sk)
{ {
if (static_branch_unlikely(&tcp_tx_delay_enabled)) { if (static_branch_unlikely(&tcp_tx_delay_enabled)) {
u32 delay = (sk->sk_state == TCP_TIME_WAIT) ? u32 delay = (sk->sk_state == TCP_TIME_WAIT) ?
tcp_twsk(sk)->tw_tx_delay : tcp_sk(sk)->tcp_tx_delay; tcp_twsk(sk)->tw_tx_delay : tcp_sk(sk)->tcp_tx_delay;
skb->skb_mstamp_ns = tcp_clock_ns() + (u64)delay * NSEC_PER_USEC; return tcp_clock_ns() + (u64)delay * NSEC_PER_USEC;
} }
return 0;
} }
#endif /* _TCP_H */ #endif /* _TCP_H */
...@@ -1632,7 +1632,7 @@ void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb, ...@@ -1632,7 +1632,7 @@ void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb,
const struct ip_options *sopt, const struct ip_options *sopt,
__be32 daddr, __be32 saddr, __be32 daddr, __be32 saddr,
const struct ip_reply_arg *arg, const struct ip_reply_arg *arg,
unsigned int len) unsigned int len, u64 transmit_time)
{ {
struct ip_options_data replyopts; struct ip_options_data replyopts;
struct ipcm_cookie ipc; struct ipcm_cookie ipc;
...@@ -1648,6 +1648,7 @@ void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb, ...@@ -1648,6 +1648,7 @@ void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb,
ipcm_init(&ipc); ipcm_init(&ipc);
ipc.addr = daddr; ipc.addr = daddr;
ipc.sockc.transmit_time = transmit_time;
if (replyopts.opt.opt.optlen) { if (replyopts.opt.opt.optlen) {
ipc.opt = &replyopts.opt; ipc.opt = &replyopts.opt;
......
...@@ -662,8 +662,9 @@ static void tcp_v4_send_reset(const struct sock *sk, struct sk_buff *skb) ...@@ -662,8 +662,9 @@ static void tcp_v4_send_reset(const struct sock *sk, struct sk_buff *skb)
int genhash; int genhash;
struct sock *sk1 = NULL; struct sock *sk1 = NULL;
#endif #endif
struct net *net; u64 transmit_time = 0;
struct sock *ctl_sk; struct sock *ctl_sk;
struct net *net;
/* Never send a reset in response to a reset. */ /* Never send a reset in response to a reset. */
if (th->rst) if (th->rst)
...@@ -770,12 +771,13 @@ static void tcp_v4_send_reset(const struct sock *sk, struct sk_buff *skb) ...@@ -770,12 +771,13 @@ static void tcp_v4_send_reset(const struct sock *sk, struct sk_buff *skb)
if (sk) { if (sk) {
ctl_sk->sk_mark = (sk->sk_state == TCP_TIME_WAIT) ? ctl_sk->sk_mark = (sk->sk_state == TCP_TIME_WAIT) ?
inet_twsk(sk)->tw_mark : sk->sk_mark; inet_twsk(sk)->tw_mark : sk->sk_mark;
tcp_set_tx_time(skb, sk); transmit_time = tcp_transmit_time(sk);
} }
ip_send_unicast_reply(ctl_sk, ip_send_unicast_reply(ctl_sk,
skb, &TCP_SKB_CB(skb)->header.h4.opt, skb, &TCP_SKB_CB(skb)->header.h4.opt,
ip_hdr(skb)->saddr, ip_hdr(skb)->daddr, ip_hdr(skb)->saddr, ip_hdr(skb)->daddr,
&arg, arg.iov[0].iov_len); &arg, arg.iov[0].iov_len,
transmit_time);
ctl_sk->sk_mark = 0; ctl_sk->sk_mark = 0;
__TCP_INC_STATS(net, TCP_MIB_OUTSEGS); __TCP_INC_STATS(net, TCP_MIB_OUTSEGS);
...@@ -810,6 +812,7 @@ static void tcp_v4_send_ack(const struct sock *sk, ...@@ -810,6 +812,7 @@ static void tcp_v4_send_ack(const struct sock *sk,
struct net *net = sock_net(sk); struct net *net = sock_net(sk);
struct ip_reply_arg arg; struct ip_reply_arg arg;
struct sock *ctl_sk; struct sock *ctl_sk;
u64 transmit_time;
memset(&rep.th, 0, sizeof(struct tcphdr)); memset(&rep.th, 0, sizeof(struct tcphdr));
memset(&arg, 0, sizeof(arg)); memset(&arg, 0, sizeof(arg));
...@@ -863,11 +866,12 @@ static void tcp_v4_send_ack(const struct sock *sk, ...@@ -863,11 +866,12 @@ static void tcp_v4_send_ack(const struct sock *sk,
ctl_sk = this_cpu_read(*net->ipv4.tcp_sk); ctl_sk = this_cpu_read(*net->ipv4.tcp_sk);
ctl_sk->sk_mark = (sk->sk_state == TCP_TIME_WAIT) ? ctl_sk->sk_mark = (sk->sk_state == TCP_TIME_WAIT) ?
inet_twsk(sk)->tw_mark : sk->sk_mark; inet_twsk(sk)->tw_mark : sk->sk_mark;
tcp_set_tx_time(skb, sk); transmit_time = tcp_transmit_time(sk);
ip_send_unicast_reply(ctl_sk, ip_send_unicast_reply(ctl_sk,
skb, &TCP_SKB_CB(skb)->header.h4.opt, skb, &TCP_SKB_CB(skb)->header.h4.opt,
ip_hdr(skb)->saddr, ip_hdr(skb)->daddr, ip_hdr(skb)->saddr, ip_hdr(skb)->daddr,
&arg, arg.iov[0].iov_len); &arg, arg.iov[0].iov_len,
transmit_time);
ctl_sk->sk_mark = 0; ctl_sk->sk_mark = 0;
__TCP_INC_STATS(net, TCP_MIB_OUTSEGS); __TCP_INC_STATS(net, TCP_MIB_OUTSEGS);
......
...@@ -892,7 +892,7 @@ static void tcp_v6_send_response(const struct sock *sk, struct sk_buff *skb, u32 ...@@ -892,7 +892,7 @@ static void tcp_v6_send_response(const struct sock *sk, struct sk_buff *skb, u32
} else { } else {
mark = sk->sk_mark; mark = sk->sk_mark;
} }
tcp_set_tx_time(buff, sk); buff->tstamp = tcp_transmit_time(sk);
} }
fl6.flowi6_mark = IP6_REPLY_MARK(net, skb->mark) ?: mark; fl6.flowi6_mark = IP6_REPLY_MARK(net, skb->mark) ?: mark;
fl6.fl6_dport = t1->dest; fl6.fl6_dport = t1->dest;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment