Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+15 −5
Original line number Original line Diff line number Diff line
@@ -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.
+1 −1
Original line number Original line Diff line number Diff line
@@ -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
+3 −0
Original line number Original line Diff line number Diff line
@@ -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[] = {
		.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",
+10 −3
Original line number Original line Diff line number Diff line
@@ -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)
	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)
		 * 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)
		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: