Skip to content

Commit ec01147

Browse files
committed
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 <[email protected]>
2 parents e736bf7 + 50a8acc commit ec01147

File tree

4 files changed

+31
-9
lines changed

4 files changed

+31
-9
lines changed

Documentation/networking/ip-sysctl.txt

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1429,14 +1429,24 @@ flowlabel_state_ranges - BOOLEAN
14291429
FALSE: disabled
14301430
Default: true
14311431

1432-
flowlabel_reflect - BOOLEAN
1433-
Automatically reflect the flow label. Needed for Path MTU
1432+
flowlabel_reflect - INTEGER
1433+
Control flow label reflection. Needed for Path MTU
14341434
Discovery to work with Equal Cost Multipath Routing in anycast
14351435
environments. See RFC 7690 and:
14361436
https://tools.ietf.org/html/draft-wang-6man-flow-label-reflection-01
1437-
TRUE: enabled
1438-
FALSE: disabled
1439-
Default: FALSE
1437+
1438+
This is a mask of two bits.
1439+
1: enabled for established flows
1440+
1441+
Note that this prevents automatic flowlabel changes, as done
1442+
in "tcp: change IPv6 flow-label upon receiving spurious retransmission"
1443+
and "tcp: Change txhash on every SYN and RTO retransmit"
1444+
1445+
2: enabled for TCP RESET packets (no active listener)
1446+
If set, a RST packet sent in response to a SYN packet on a closed
1447+
port will reflect the incoming flow label.
1448+
1449+
Default: 0
14401450

14411451
fib_multipath_hash_policy - INTEGER
14421452
Controls which hash policy to use for multipath routes.

net/ipv6/af_inet6.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ static int inet6_create(struct net *net, struct socket *sock, int protocol,
212212
np->mc_loop = 1;
213213
np->mc_all = 1;
214214
np->pmtudisc = IPV6_PMTUDISC_WANT;
215-
np->repflow = net->ipv6.sysctl.flowlabel_reflect;
215+
np->repflow = net->ipv6.sysctl.flowlabel_reflect & 1;
216216
sk->sk_ipv6only = net->ipv6.sysctl.bindv6only;
217217

218218
/* Init the ipv4 part of the socket since we can have sockets

net/ipv6/sysctl_net_ipv6.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
static int zero;
2525
static int one = 1;
26+
static int three = 3;
2627
static int auto_flowlabels_min;
2728
static int auto_flowlabels_max = IP6_AUTO_FLOW_LABEL_MAX;
2829

@@ -114,6 +115,8 @@ static struct ctl_table ipv6_table_template[] = {
114115
.maxlen = sizeof(int),
115116
.mode = 0644,
116117
.proc_handler = proc_dointvec,
118+
.extra1 = &zero,
119+
.extra2 = &three,
117120
},
118121
{
119122
.procname = "max_dst_opts_number",

net/ipv6/tcp_ipv6.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -916,15 +916,17 @@ static void tcp_v6_send_response(const struct sock *sk, struct sk_buff *skb, u32
916916
static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb)
917917
{
918918
const struct tcphdr *th = tcp_hdr(skb);
919+
struct ipv6hdr *ipv6h = ipv6_hdr(skb);
919920
u32 seq = 0, ack_seq = 0;
920921
struct tcp_md5sig_key *key = NULL;
921922
#ifdef CONFIG_TCP_MD5SIG
922923
const __u8 *hash_location = NULL;
923-
struct ipv6hdr *ipv6h = ipv6_hdr(skb);
924924
unsigned char newhash[16];
925925
int genhash;
926926
struct sock *sk1 = NULL;
927927
#endif
928+
__be32 label = 0;
929+
struct net *net;
928930
int oif = 0;
929931

930932
if (th->rst)
@@ -936,6 +938,7 @@ static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb)
936938
if (!sk && !ipv6_unicast_destination(skb))
937939
return;
938940

941+
net = dev_net(skb_dst(skb)->dev);
939942
#ifdef CONFIG_TCP_MD5SIG
940943
rcu_read_lock();
941944
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)
949952
* Incoming packet is checked with md5 hash with finding key,
950953
* no RST generated if md5 hash doesn't match.
951954
*/
952-
sk1 = inet6_lookup_listener(dev_net(skb_dst(skb)->dev),
955+
sk1 = inet6_lookup_listener(net,
953956
&tcp_hashinfo, NULL, 0,
954957
&ipv6h->saddr,
955958
th->source, &ipv6h->daddr,
@@ -979,9 +982,15 @@ static void tcp_v6_send_reset(const struct sock *sk, struct sk_buff *skb)
979982
oif = sk->sk_bound_dev_if;
980983
if (sk_fullsock(sk))
981984
trace_tcp_send_reset(sk, skb);
985+
if (sk->sk_state == TCP_TIME_WAIT)
986+
label = cpu_to_be32(inet_twsk(sk)->tw_flowlabel);
987+
} else {
988+
if (net->ipv6.sysctl.flowlabel_reflect & 2)
989+
label = ip6_flowlabel(ipv6h);
982990
}
983991

984-
tcp_v6_send_response(sk, skb, seq, ack_seq, 0, 0, 0, oif, key, 1, 0, 0);
992+
tcp_v6_send_response(sk, skb, seq, ack_seq, 0, 0, 0, oif, key, 1, 0,
993+
label);
985994

986995
#ifdef CONFIG_TCP_MD5SIG
987996
out:

0 commit comments

Comments
 (0)