aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2019-06-08 20:58:51 -0400
committerDavid S. Miller <davem@davemloft.net>2019-06-09 23:10:19 -0400
commitc67b85558ff20cb1ff20874461d12af456bee5d0 (patch)
tree74fbc1da8b19b683614d91c512a4a73c04a873a9
parent6566cd3690c19759b57757b171e9d605bd38432b (diff)
ipv6: tcp: send consistent autoflowlabel in TIME_WAIT state
In case autoflowlabel is in action, skb_get_hash_flowi6() derives a non zero skb->hash to the flowlabel. If skb->hash is zero, a flow dissection is performed. Since all TCP skbs sent from ESTABLISH state inherit their skb->hash from sk->sk_txhash, we better keep a copy of sk->sk_txhash into the TIME_WAIT socket. After this patch, ACK or RST packets sent on behalf of a TIME_WAIT socket have the flowlabel that was previously used by the flow. Signed-off-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/inet_timewait_sock.h1
-rw-r--r--net/ipv4/tcp_minisocks.c1
-rw-r--r--net/ipv6/tcp_ipv6.c13
3 files changed, 12 insertions, 3 deletions
diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h
index c2f756aedc54..aef38c140014 100644
--- a/include/net/inet_timewait_sock.h
+++ b/include/net/inet_timewait_sock.h
@@ -70,6 +70,7 @@ struct inet_timewait_sock {
70 tw_flowlabel : 20, 70 tw_flowlabel : 20,
71 tw_pad : 2, /* 2 bits hole */ 71 tw_pad : 2, /* 2 bits hole */
72 tw_tos : 8; 72 tw_tos : 8;
73 u32 tw_txhash;
73 struct timer_list tw_timer; 74 struct timer_list tw_timer;
74 struct inet_bind_bucket *tw_tb; 75 struct inet_bind_bucket *tw_tb;
75}; 76};
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index 7c35731816e2..11011e8386dc 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -283,6 +283,7 @@ void tcp_time_wait(struct sock *sk, int state, int timeo)
283 tw->tw_v6_rcv_saddr = sk->sk_v6_rcv_saddr; 283 tw->tw_v6_rcv_saddr = sk->sk_v6_rcv_saddr;
284 tw->tw_tclass = np->tclass; 284 tw->tw_tclass = np->tclass;
285 tw->tw_flowlabel = be32_to_cpu(np->flow_label & IPV6_FLOWLABEL_MASK); 285 tw->tw_flowlabel = be32_to_cpu(np->flow_label & IPV6_FLOWLABEL_MASK);
286 tw->tw_txhash = sk->sk_txhash;
286 tw->tw_ipv6only = sk->sk_ipv6only; 287 tw->tw_ipv6only = sk->sk_ipv6only;
287 } 288 }
288#endif 289#endif
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index c1da52c7f990..ad7039137a20 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -883,9 +883,16 @@ static void tcp_v6_send_response(const struct sock *sk, struct sk_buff *skb, u32
883 fl6.flowi6_oif = oif; 883 fl6.flowi6_oif = oif;
884 } 884 }
885 885
886 if (sk) 886 if (sk) {
887 mark = (sk->sk_state == TCP_TIME_WAIT) ? 887 if (sk->sk_state == TCP_TIME_WAIT) {
888 inet_twsk(sk)->tw_mark : sk->sk_mark; 888 mark = inet_twsk(sk)->tw_mark;
889 /* autoflowlabel relies on buff->hash */
890 skb_set_hash(buff, inet_twsk(sk)->tw_txhash,
891 PKT_HASH_TYPE_L4);
892 } else {
893 mark = sk->sk_mark;
894 }
895 }
889 fl6.flowi6_mark = IP6_REPLY_MARK(net, skb->mark) ?: mark; 896 fl6.flowi6_mark = IP6_REPLY_MARK(net, skb->mark) ?: mark;
890 fl6.fl6_dport = t1->dest; 897 fl6.fl6_dport = t1->dest;
891 fl6.fl6_sport = t1->source; 898 fl6.fl6_sport = t1->source;