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

ipv6: tcp: enable flowlabel reflection in some RST packets

When RST packets are sent because no socket could be found,
it makes sense to use flowlabel_reflect sysctl to decide
if a reflection of the flowlabel is requested.

This extends commit 22b6722b ("ipv6: Add sysctl for per
namespace flow label reflection"), for some TCP RST packets.

In order to provide full control of this new feature,
flowlabel_reflect becomes a bitmask.
Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e736bf72
...@@ -1429,14 +1429,24 @@ flowlabel_state_ranges - BOOLEAN ...@@ -1429,14 +1429,24 @@ flowlabel_state_ranges - BOOLEAN
FALSE: disabled FALSE: disabled
Default: true Default: true
flowlabel_reflect - BOOLEAN flowlabel_reflect - INTEGER
Automatically reflect the flow label. Needed for Path MTU Control flow label reflection. Needed for Path MTU
Discovery to work with Equal Cost Multipath Routing in anycast Discovery to work with Equal Cost Multipath Routing in anycast
environments. See RFC 7690 and: environments. See RFC 7690 and:
https://tools.ietf.org/html/draft-wang-6man-flow-label-reflection-01 https://tools.ietf.org/html/draft-wang-6man-flow-label-reflection-01
TRUE: enabled
FALSE: disabled This is a mask of two bits.
Default: FALSE 1: enabled for established flows
Note that this prevents automatic flowlabel changes, as done
in "tcp: change IPv6 flow-label upon receiving spurious retransmission"
and "tcp: Change txhash on every SYN and RTO retransmit"
2: enabled for TCP RESET packets (no active listener)
If set, a RST packet sent in response to a SYN packet on a closed
port will reflect the incoming flow label.
Default: 0
fib_multipath_hash_policy - INTEGER fib_multipath_hash_policy - INTEGER
Controls which hash policy to use for multipath routes. Controls which hash policy to use for multipath routes.
......
...@@ -212,7 +212,7 @@ static int inet6_create(struct net *net, struct socket *sock, int protocol, ...@@ -212,7 +212,7 @@ static int inet6_create(struct net *net, struct socket *sock, int protocol,
np->mc_loop = 1; np->mc_loop = 1;
np->mc_all = 1; np->mc_all = 1;
np->pmtudisc = IPV6_PMTUDISC_WANT; np->pmtudisc = IPV6_PMTUDISC_WANT;
np->repflow = net->ipv6.sysctl.flowlabel_reflect; np->repflow = net->ipv6.sysctl.flowlabel_reflect & 1;
sk->sk_ipv6only = net->ipv6.sysctl.bindv6only; sk->sk_ipv6only = net->ipv6.sysctl.bindv6only;
/* Init the ipv4 part of the socket since we can have sockets /* Init the ipv4 part of the socket since we can have sockets
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
static int zero; static int zero;
static int one = 1; static int one = 1;
static int three = 3;
static int auto_flowlabels_min; static int auto_flowlabels_min;
static int auto_flowlabels_max = IP6_AUTO_FLOW_LABEL_MAX; static int auto_flowlabels_max = IP6_AUTO_FLOW_LABEL_MAX;
...@@ -114,6 +115,8 @@ static struct ctl_table ipv6_table_template[] = { ...@@ -114,6 +115,8 @@ static struct ctl_table ipv6_table_template[] = {
.maxlen = sizeof(int), .maxlen = sizeof(int),
.mode = 0644, .mode = 0644,
.proc_handler = proc_dointvec, .proc_handler = proc_dointvec,
.extra1 = &zero,
.extra2 = &three,
}, },
{ {
.procname = "max_dst_opts_number", .procname = "max_dst_opts_number",
......
...@@ -916,15 +916,17 @@ static void tcp_v6_send_response(const struct sock *sk, struct sk_buff *skb, u32 ...@@ -916,15 +916,17 @@ static void tcp_v6_send_response(const struct sock *sk, struct sk_buff *skb, u32
static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb) static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb)
{ {
const struct tcphdr *th = tcp_hdr(skb); const struct tcphdr *th = tcp_hdr(skb);
struct ipv6hdr *ipv6h = ipv6_hdr(skb);
u32 seq = 0, ack_seq = 0; u32 seq = 0, ack_seq = 0;
struct tcp_md5sig_key *key = NULL; struct tcp_md5sig_key *key = NULL;
#ifdef CONFIG_TCP_MD5SIG #ifdef CONFIG_TCP_MD5SIG
const __u8 *hash_location = NULL; const __u8 *hash_location = NULL;
struct ipv6hdr *ipv6h = ipv6_hdr(skb);
unsigned char newhash[16]; unsigned char newhash[16];
int genhash; int genhash;
struct sock *sk1 = NULL; struct sock *sk1 = NULL;
#endif #endif
__be32 label = 0;
struct net *net;
int oif = 0; int oif = 0;
if (th->rst) if (th->rst)
...@@ -936,6 +938,7 @@ static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb) ...@@ -936,6 +938,7 @@ static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb)
if (!sk && !ipv6_unicast_destination(skb)) if (!sk && !ipv6_unicast_destination(skb))
return; return;
net = dev_net(skb_dst(skb)->dev);
#ifdef CONFIG_TCP_MD5SIG #ifdef CONFIG_TCP_MD5SIG
rcu_read_lock(); rcu_read_lock();
hash_location = tcp_parse_md5sig_option(th); hash_location = tcp_parse_md5sig_option(th);
...@@ -949,7 +952,7 @@ static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb) ...@@ -949,7 +952,7 @@ static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb)
* Incoming packet is checked with md5 hash with finding key, * Incoming packet is checked with md5 hash with finding key,
* no RST generated if md5 hash doesn't match. * no RST generated if md5 hash doesn't match.
*/ */
sk1 = inet6_lookup_listener(dev_net(skb_dst(skb)->dev), sk1 = inet6_lookup_listener(net,
&tcp_hashinfo, NULL, 0, &tcp_hashinfo, NULL, 0,
&ipv6h->saddr, &ipv6h->saddr,
th->source, &ipv6h->daddr, th->source, &ipv6h->daddr,
...@@ -979,9 +982,13 @@ static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb) ...@@ -979,9 +982,13 @@ static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb)
oif = sk->sk_bound_dev_if; oif = sk->sk_bound_dev_if;
if (sk_fullsock(sk)) if (sk_fullsock(sk))
trace_tcp_send_reset(sk, skb); trace_tcp_send_reset(sk, skb);
} else {
if (net->ipv6.sysctl.flowlabel_reflect & 2)
label = ip6_flowlabel(ipv6h);
} }
tcp_v6_send_response(sk, skb, seq, ack_seq, 0, 0, 0, oif, key, 1, 0, 0); tcp_v6_send_response(sk, skb, seq, ack_seq, 0, 0, 0, oif, key, 1, 0,
label);
#ifdef CONFIG_TCP_MD5SIG #ifdef CONFIG_TCP_MD5SIG
out: out:
......
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