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

Commit ec01147a authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'tcp-flowlabel'



Eric Dumazet says:

====================
ipv6: tcp: more control on RST flowlabels

First patch allows to reflect incoming IPv6 flowlabel
on RST packets sent when no socket could handle the packet.

Second patch makes sure we send the same flowlabel
for RST or ACK packets on behalf of TIME_WAIT sockets.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents e736bf72 50a8accf
Loading
Loading
Loading
Loading
+15 −5
Original line number Diff line number Diff line
@@ -1429,14 +1429,24 @@ flowlabel_state_ranges - BOOLEAN
	FALSE: disabled
	Default: true

flowlabel_reflect - BOOLEAN
	Automatically reflect the flow label. Needed for Path MTU
flowlabel_reflect - INTEGER
	Control flow label reflection. Needed for Path MTU
	Discovery to work with Equal Cost Multipath Routing in anycast
	environments. See RFC 7690 and:
	https://tools.ietf.org/html/draft-wang-6man-flow-label-reflection-01
	TRUE: enabled
	FALSE: disabled
	Default: FALSE

	This is a mask of two bits.
	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
	Controls which hash policy to use for multipath routes.
+1 −1
Original line number 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_all	= 1;
	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;

	/* Init the ipv4 part of the socket since we can have sockets
+3 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@

static int zero;
static int one = 1;
static int three = 3;
static int auto_flowlabels_min;
static int auto_flowlabels_max = IP6_AUTO_FLOW_LABEL_MAX;

@@ -114,6 +115,8 @@ static struct ctl_table ipv6_table_template[] = {
		.maxlen		= sizeof(int),
		.mode		= 0644,
		.proc_handler	= proc_dointvec,
		.extra1		= &zero,
		.extra2		= &three,
	},
	{
		.procname	= "max_dst_opts_number",
+12 −3
Original line number 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)
{
	const struct tcphdr *th = tcp_hdr(skb);
	struct ipv6hdr *ipv6h = ipv6_hdr(skb);
	u32 seq = 0, ack_seq = 0;
	struct tcp_md5sig_key *key = NULL;
#ifdef CONFIG_TCP_MD5SIG
	const __u8 *hash_location = NULL;
	struct ipv6hdr *ipv6h = ipv6_hdr(skb);
	unsigned char newhash[16];
	int genhash;
	struct sock *sk1 = NULL;
#endif
	__be32 label = 0;
	struct net *net;
	int oif = 0;

	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))
		return;

	net = dev_net(skb_dst(skb)->dev);
#ifdef CONFIG_TCP_MD5SIG
	rcu_read_lock();
	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,
		 * 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,
					   &ipv6h->saddr,
					   th->source, &ipv6h->daddr,
@@ -979,9 +982,15 @@ static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb)
		oif = sk->sk_bound_dev_if;
		if (sk_fullsock(sk))
			trace_tcp_send_reset(sk, skb);
		if (sk->sk_state == TCP_TIME_WAIT)
			label = cpu_to_be32(inet_twsk(sk)->tw_flowlabel);
	} 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
out: