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 22b6722bfa
("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: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
e736bf72af
commit
323a53c412
|
@ -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.
|
||||
|
|
|
@ -212,7 +212,7 @@ lookup_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
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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,13 @@ 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);
|
||||
} 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:
|
||||
|
|
Loading…
Reference in New Issue