summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2019-06-14 00:22:35 -0400
committerDavid S. Miller <davem@davemloft.net>2019-06-14 22:51:12 -0400
commitd6fb396cfaa71afc9f38d573b8ec6409fe3716de (patch)
tree81f13c19c7e214129cb08ef7301b4941f435b52f
parent3e18943333404b03d17fc4a008da7c3676523f05 (diff)
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: a842fe1425cb ("tcp: add optional per socket transmit delay") Signed-off-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/ip.h2
-rw-r--r--include/net/tcp.h9
-rw-r--r--net/ipv4/ip_output.c3
-rw-r--r--net/ipv4/tcp_ipv4.c14
-rw-r--r--net/ipv6/tcp_ipv6.c2
5 files changed, 19 insertions, 11 deletions
diff --git a/include/net/ip.h b/include/net/ip.h
index 6dbf88ea07f1..29d89de39822 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -279,7 +279,7 @@ void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb,
279 const struct ip_options *sopt, 279 const struct ip_options *sopt,
280 __be32 daddr, __be32 saddr, 280 __be32 daddr, __be32 saddr,
281 const struct ip_reply_arg *arg, 281 const struct ip_reply_arg *arg,
282 unsigned int len); 282 unsigned int len, u64 transmit_time);
283 283
284#define IP_INC_STATS(net, field) SNMP_INC_STATS64((net)->mib.ip_statistics, field) 284#define IP_INC_STATS(net, field) SNMP_INC_STATS64((net)->mib.ip_statistics, field)
285#define __IP_INC_STATS(net, field) __SNMP_INC_STATS64((net)->mib.ip_statistics, field) 285#define __IP_INC_STATS(net, field) __SNMP_INC_STATS64((net)->mib.ip_statistics, field)
diff --git a/include/net/tcp.h b/include/net/tcp.h
index 49a178b8d5b2..96e0e53ff440 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -2240,15 +2240,18 @@ static inline void tcp_add_tx_delay(struct sk_buff *skb,
2240 skb->skb_mstamp_ns += (u64)tp->tcp_tx_delay * NSEC_PER_USEC; 2240 skb->skb_mstamp_ns += (u64)tp->tcp_tx_delay * NSEC_PER_USEC;
2241} 2241}
2242 2242
2243static inline void tcp_set_tx_time(struct sk_buff *skb, 2243/* Compute Earliest Departure Time for some control packets
2244 const struct sock *sk) 2244 * like ACK or RST for TIME_WAIT or non ESTABLISHED sockets.
2245 */
2246static inline u64 tcp_transmit_time(const struct sock *sk)
2245{ 2247{
2246 if (static_branch_unlikely(&tcp_tx_delay_enabled)) { 2248 if (static_branch_unlikely(&tcp_tx_delay_enabled)) {
2247 u32 delay = (sk->sk_state == TCP_TIME_WAIT) ? 2249 u32 delay = (sk->sk_state == TCP_TIME_WAIT) ?
2248 tcp_twsk(sk)->tw_tx_delay : tcp_sk(sk)->tcp_tx_delay; 2250 tcp_twsk(sk)->tw_tx_delay : tcp_sk(sk)->tcp_tx_delay;
2249 2251
2250 skb->skb_mstamp_ns = tcp_clock_ns() + (u64)delay * NSEC_PER_USEC; 2252 return tcp_clock_ns() + (u64)delay * NSEC_PER_USEC;
2251 } 2253 }
2254 return 0;
2252} 2255}
2253 2256
2254#endif /* _TCP_H */ 2257#endif /* _TCP_H */
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index f5636ab0b9c3..e0ac39072a9c 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -1632,7 +1632,7 @@ void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb,
1632 const struct ip_options *sopt, 1632 const struct ip_options *sopt,
1633 __be32 daddr, __be32 saddr, 1633 __be32 daddr, __be32 saddr,
1634 const struct ip_reply_arg *arg, 1634 const struct ip_reply_arg *arg,
1635 unsigned int len) 1635 unsigned int len, u64 transmit_time)
1636{ 1636{
1637 struct ip_options_data replyopts; 1637 struct ip_options_data replyopts;
1638 struct ipcm_cookie ipc; 1638 struct ipcm_cookie ipc;
@@ -1648,6 +1648,7 @@ void ip_send_unicast_reply(struct sock *sk, struct sk_buff *skb,
1648 1648
1649 ipcm_init(&ipc); 1649 ipcm_init(&ipc);
1650 ipc.addr = daddr; 1650 ipc.addr = daddr;
1651 ipc.sockc.transmit_time = transmit_time;
1651 1652
1652 if (replyopts.opt.opt.optlen) { 1653 if (replyopts.opt.opt.optlen) {
1653 ipc.opt = &replyopts.opt; 1654 ipc.opt = &replyopts.opt;
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 1b7e9e1fbd3b..633e8244ed5b 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -662,8 +662,9 @@ static void tcp_v4_send_reset(const struct sock *sk, struct sk_buff *skb)
662 int genhash; 662 int genhash;
663 struct sock *sk1 = NULL; 663 struct sock *sk1 = NULL;
664#endif 664#endif
665 struct net *net; 665 u64 transmit_time = 0;
666 struct sock *ctl_sk; 666 struct sock *ctl_sk;
667 struct net *net;
667 668
668 /* Never send a reset in response to a reset. */ 669 /* Never send a reset in response to a reset. */
669 if (th->rst) 670 if (th->rst)
@@ -770,12 +771,13 @@ static void tcp_v4_send_reset(const struct sock *sk, struct sk_buff *skb)
770 if (sk) { 771 if (sk) {
771 ctl_sk->sk_mark = (sk->sk_state == TCP_TIME_WAIT) ? 772 ctl_sk->sk_mark = (sk->sk_state == TCP_TIME_WAIT) ?
772 inet_twsk(sk)->tw_mark : sk->sk_mark; 773 inet_twsk(sk)->tw_mark : sk->sk_mark;
773 tcp_set_tx_time(skb, sk); 774 transmit_time = tcp_transmit_time(sk);
774 } 775 }
775 ip_send_unicast_reply(ctl_sk, 776 ip_send_unicast_reply(ctl_sk,
776 skb, &TCP_SKB_CB(skb)->header.h4.opt, 777 skb, &TCP_SKB_CB(skb)->header.h4.opt,
777 ip_hdr(skb)->saddr, ip_hdr(skb)->daddr, 778 ip_hdr(skb)->saddr, ip_hdr(skb)->daddr,
778 &arg, arg.iov[0].iov_len); 779 &arg, arg.iov[0].iov_len,
780 transmit_time);
779 781
780 ctl_sk->sk_mark = 0; 782 ctl_sk->sk_mark = 0;
781 __TCP_INC_STATS(net, TCP_MIB_OUTSEGS); 783 __TCP_INC_STATS(net, TCP_MIB_OUTSEGS);
@@ -810,6 +812,7 @@ static void tcp_v4_send_ack(const struct sock *sk,
810 struct net *net = sock_net(sk); 812 struct net *net = sock_net(sk);
811 struct ip_reply_arg arg; 813 struct ip_reply_arg arg;
812 struct sock *ctl_sk; 814 struct sock *ctl_sk;
815 u64 transmit_time;
813 816
814 memset(&rep.th, 0, sizeof(struct tcphdr)); 817 memset(&rep.th, 0, sizeof(struct tcphdr));
815 memset(&arg, 0, sizeof(arg)); 818 memset(&arg, 0, sizeof(arg));
@@ -863,11 +866,12 @@ static void tcp_v4_send_ack(const struct sock *sk,
863 ctl_sk = this_cpu_read(*net->ipv4.tcp_sk); 866 ctl_sk = this_cpu_read(*net->ipv4.tcp_sk);
864 ctl_sk->sk_mark = (sk->sk_state == TCP_TIME_WAIT) ? 867 ctl_sk->sk_mark = (sk->sk_state == TCP_TIME_WAIT) ?
865 inet_twsk(sk)->tw_mark : sk->sk_mark; 868 inet_twsk(sk)->tw_mark : sk->sk_mark;
866 tcp_set_tx_time(skb, sk); 869 transmit_time = tcp_transmit_time(sk);
867 ip_send_unicast_reply(ctl_sk, 870 ip_send_unicast_reply(ctl_sk,
868 skb, &TCP_SKB_CB(skb)->header.h4.opt, 871 skb, &TCP_SKB_CB(skb)->header.h4.opt,
869 ip_hdr(skb)->saddr, ip_hdr(skb)->daddr, 872 ip_hdr(skb)->saddr, ip_hdr(skb)->daddr,
870 &arg, arg.iov[0].iov_len); 873 &arg, arg.iov[0].iov_len,
874 transmit_time);
871 875
872 ctl_sk->sk_mark = 0; 876 ctl_sk->sk_mark = 0;
873 __TCP_INC_STATS(net, TCP_MIB_OUTSEGS); 877 __TCP_INC_STATS(net, TCP_MIB_OUTSEGS);
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 5606b2131b65..408d9ec26971 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -892,7 +892,7 @@ static void tcp_v6_send_response(const struct sock *sk, struct sk_buff *skb, u32
892 } else { 892 } else {
893 mark = sk->sk_mark; 893 mark = sk->sk_mark;
894 } 894 }
895 tcp_set_tx_time(buff, sk); 895 buff->tstamp = tcp_transmit_time(sk);
896 } 896 }
897 fl6.flowi6_mark = IP6_REPLY_MARK(net, skb->mark) ?: mark; 897 fl6.flowi6_mark = IP6_REPLY_MARK(net, skb->mark) ?: mark;
898 fl6.fl6_dport = t1->dest; 898 fl6.fl6_dport = t1->dest;