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: David S. Miller <davem@davemloft.net>
This commit is contained in:
@ -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,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:
|
||||
|
Reference in New Issue
Block a user