tcp: split tcp_ecn sysctl knob to distinguish between IPv4 and IPv6
Subsystems (5)
PATCH v2 1/1 tcp: split tcp_ecn sysctl knob to distinguish between IPv4 and IPv6
ECN could be more reliable when used with IPv6 (I don't have proofs). For people who want to try ECN with IPv6 but still have problems connecting to destinations because of broken IPv4 routers this switch allows one to enable ECN just for IPv6.
Perhaps ECN could be enabled by default in future.
No code changes since initial submission, just added documentation.
--- Documentation/networking/ip-sysctl.txt | 28 +++++++++++++++++++++------- include/net/sock.h | 1 + include/net/tcp.h | 8 +++++--- net/ipv4/syncookies.c | 6 ++++-- net/ipv4/sysctl_net_ipv4.c | 2 +- net/ipv4/tcp_input.c | 2 -- net/ipv4/tcp_ipv4.c | 3 ++- net/ipv4/tcp_output.c | 2 +- net/ipv6/syncookies.c | 3 ++- net/ipv6/sysctl_net_ipv6.c | 8 ++++++++ net/ipv6/tcp_ipv6.c | 4 +++- 11 files changed, 48 insertions(+), 19 deletions(-)
Documentation/networking/ip-sysctl.txt +21 -7
@@ -207,11 +207,11 @@ tcp_early_retrans - INTEGER Default: 2 tcp_ecn - INTEGER - Control use of Explicit Congestion Notification (ECN) by TCP. - ECN is used only when both ends of the TCP connection indicate - support for it. This feature is useful in avoiding losses due - to congestion by allowing supporting routers to signal - congestion before having to drop packets. + Control use of Explicit Congestion Notification (ECN) by TCP + over IPv4. ECN is used only when both ends of the TCP + connection indicate support for it. This feature is useful in + avoiding losses due to congestion by allowing supporting + routers to signal congestion before having to drop packets. Possible values are: 0 Disable ECN. Neither initiate nor accept ECN. 1 Always request ECN on outgoing connection attempts.
@@ -1065,8 +1065,9 @@ [email protected] /proc/sys/net/ipv6/* Variables: -IPv6 has no global variables such as tcp_*. tcp_* settings under ipv4/ also -apply to IPv6 [XXX?]. +IPv6 has no global variables such as tcp_*. Most tcp_* settings under +ipv4/ also apply to IPv6 (currently the only exception is tcp_ecn) +[XXX?]. bindv6only - BOOLEAN Default value for IPV6_V6ONLY socket option,
@@ -1077,6 +1078,19 @@ bindv6only - BOOLEAN Default: FALSE (as specified in RFC3493) +tcp_ecn - INTEGER + Control use of Explicit Congestion Notification (ECN) by TCP + over IPv6. ECN is used only when both ends of the TCP + connection indicate support for it. This feature is useful in + avoiding losses due to congestion by allowing supporting + routers to signal congestion before having to drop packets. + Possible values are: + 0 Disable ECN. Neither initiate nor accept ECN. + 1 Always request ECN on outgoing connection attempts. + 2 Enable ECN when requested by incomming connections + but do not request ECN on outgoing connections. + Default: 2 + IPv6 Fragmentation: ip6frag_high_thresh - INTEGER
include/net/sock.h +1 -0
@@ -944,6 +944,7 @@ struct proto {int *sysctl_rmem;int max_header;bool no_autobind; +int ecn;struct kmem_cache *slab;unsigned int obj_size;
include/net/tcp.h +5 -3
@@ -266,7 +266,6 @@ extern int sysctl_tcp_abort_on_overflow;extern int sysctl_tcp_max_orphans;extern int sysctl_tcp_fack;extern int sysctl_tcp_reordering; -extern int sysctl_tcp_ecn;extern int sysctl_tcp_dsack;extern int sysctl_tcp_wmem[3 ];extern int sysctl_tcp_rmem[3 ];
@@ -351,6 +350,7 @@ static inline bool tcp_synq_no_recent_overflow(const struct sock *sk) }extern struct proto tcp_prot; +extern struct proto tcpv6_prot;#define TCP_INC_STATS (net, field) SNMP_INC_STATS((net)->mib.tcp_statistics, field)#define TCP_INC_STATS_BH (net, field) SNMP_INC_STATS_BH((net)->mib.tcp_statistics, field)
@@ -504,7 +504,8 @@ static inline __u32 cookie_v4_init_sequence(struct sock *sk,#endif extern __u32 cookie_init_timestamp (struct request_sock *req); -extern bool cookie_check_timestamp (struct tcp_options_received *opt,bool *); +extern bool cookie_check_timestamp (struct tcp_options_received *opt, +int sysctl_tcp_ecn,bool *ecn_ok);/* From net/ipv6/syncookies.c */ extern struct sock *cookie_v6_check (struct sock *sk,struct sk_buff *skb);
@@ -728,7 +729,8 @@ struct tcp_skb_cb {* notifications, we disable TCP ECN negociation. */ static inline void -TCP_ECN_create_request (struct request_sock *req,const struct sk_buff *skb) +TCP_ECN_create_request (struct request_sock *req, +const struct sk_buff *skb,int sysctl_tcp_ecn) {const struct tcphdr *th =tcp_hdr (skb);
net/ipv4/syncookies.c +4 -2
@@ -232,7 +232,8 @@ static inline struct sock *get_cookie_sock(struct sock *sk, struct sk_buff *skb,* * return false if we decode an option that should not be. */ -bool cookie_check_timestamp (struct tcp_options_received *tcp_opt,bool *ecn_ok) +bool cookie_check_timestamp (struct tcp_options_received *tcp_opt, +int sysctl_tcp_ecn,bool *ecn_ok) {/* echoed timestamp, lowest bits contain options */ u32 options = tcp_opt->rcv_tsecr &TSMASK ;
@@ -278,6 +279,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,struct rtable *rt;__u8 rcv_wscale;bool ecn_ok = false; +int sysctl_tcp_ecn = sk->sk_prot->ecn;struct flowi4 fl4;if (!sysctl_tcp_syncookies || !th->ack || th->rst)
@@ -295,7 +297,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,memset (&tcp_opt,0 ,sizeof (tcp_opt));tcp_parse_options (skb, &tcp_opt, &hash_location,0 ,NULL ); -if (!cookie_check_timestamp (&tcp_opt, &ecn_ok)) +if (!cookie_check_timestamp (&tcp_opt, sysctl_tcp_ecn, &ecn_ok)) goto out; ret =NULL ;
net/ipv4/sysctl_net_ipv4.c +1 -1
@@ -539,7 +539,7 @@ static struct ctl_table ipv4_table[] = { }, { .procname = "tcp_ecn", - .data = &sysctl_tcp_ecn, + .data = &tcp_prot.ecn, .maxlen = sizeof(int), .mode =0644 , .proc_handler = proc_dointvec
net/ipv4/tcp_input.c +0 -2
@@ -81,8 +81,6 @@ int sysctl_tcp_sack __read_mostly = 1;int sysctl_tcp_fack__read_mostly =1 ;int sysctl_tcp_reordering__read_mostly =TCP_FASTRETRANS_THRESH ;EXPORT_SYMBOL (sysctl_tcp_reordering); -int sysctl_tcp_ecn__read_mostly =2 ; -EXPORT_SYMBOL (sysctl_tcp_ecn);int sysctl_tcp_dsack__read_mostly =1 ;int sysctl_tcp_app_win__read_mostly =31 ;int sysctl_tcp_adv_win_scale__read_mostly =1 ;
net/ipv4/tcp_ipv4.c +2 -1
@@ -1568,7 +1568,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) goto drop_and_free;if (!want_cookie || tmp_opt.tstamp_ok) -TCP_ECN_create_request (req, skb); +TCP_ECN_create_request (req, skb, tcp_prot.ecn);if (want_cookie) { isn =cookie_v4_init_sequence (sk, skb, &req->mss);
@@ -2874,6 +2874,7 @@ struct proto tcp_prot = { .rsk_prot = &tcp_request_sock_ops, .h.hashinfo = &tcp_hashinfo, .no_autobind = true, + .ecn =2 , #ifdef CONFIG_COMPAT .compat_setsockopt = compat_tcp_setsockopt, .compat_getsockopt = compat_tcp_getsockopt,
net/ipv4/tcp_output.c +1 -1
@@ -314,7 +314,7 @@ static inline void TCP_ECN_send_syn(struct sock *sk, struct sk_buff *skb)struct tcp_sock *tp =tcp_sk (sk); tp->ecn_flags =0 ; -if (sysctl_tcp_ecn ==1 ) { +if (sk->sk_prot->ecn ==1 ) {TCP_SKB_CB (skb)->tcp_flags |=TCPHDR_ECE |TCPHDR_CWR ; tp->ecn_flags =TCP_ECN_OK ; }
net/ipv6/syncookies.c +2 -1
@@ -163,6 +163,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)struct dst_entry *dst;__u8 rcv_wscale;bool ecn_ok = false; +int sysctl_tcp_ecn = sk->sk_prot->ecn;if (!sysctl_tcp_syncookies || !th->ack || th->rst) goto out;
@@ -179,7 +180,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)memset (&tcp_opt,0 ,sizeof (tcp_opt));tcp_parse_options (skb, &tcp_opt, &hash_location,0 ,NULL ); -if (!cookie_check_timestamp (&tcp_opt, &ecn_ok)) +if (!cookie_check_timestamp (&tcp_opt, sysctl_tcp_ecn, &ecn_ok)) goto out; ret =NULL ;
net/ipv6/sysctl_net_ipv6.c +8 -0
@@ -15,6 +15,7 @@#include <net/ipv6.h> #include <net/addrconf.h> #include <net/inet_frag.h> +#include <net/tcp.h> static ctl_table ipv6_table_template[] = { {
@@ -24,6 +25,13 @@ static ctl_table ipv6_table_template[] = { .mode = 0644, .proc_handler = proc_dointvec }, + { + .procname = "tcp_ecn", + .data = &tcpv6_prot.ecn, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec + }, { } };
net/ipv6/tcp_ipv6.c +3 -1
@@ -1027,7 +1027,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) treq->rmt_addr =ipv6_hdr (skb)->saddr; treq->loc_addr =ipv6_hdr (skb)->daddr;if (!want_cookie || tmp_opt.tstamp_ok) -TCP_ECN_create_request (req, skb); +TCP_ECN_create_request (req, skb, tcpv6_prot.ecn); treq->iif = sk->sk_bound_dev_if;
@@ -1955,6 +1955,7 @@ struct proto tcpv6_prot = { .rsk_prot = &tcp6_request_sock_ops, .h.hashinfo = &tcp_hashinfo, .no_autobind = true, + .ecn =2 , #ifdef CONFIG_COMPAT .compat_setsockopt = compat_tcp_setsockopt, .compat_getsockopt = compat_tcp_getsockopt,
@@ -1963,6 +1964,7 @@ struct proto tcpv6_prot = { .proto_cgroup = tcp_proto_cgroup,#endif }; +EXPORT_SYMBOL (tcpv6_prot);static const struct inet6_protocol tcpv6_protocol = { .early_demux = tcp_v6_early_demux,
Signature · 1 line
1.7.11.7
Quoted 8 lines · Hannes Frederic Sowa
ECN could be more reliable when used with IPv6 (I don't have proofs). For people who want to try ECN with IPv6 but still have problems connecting to destinations because of broken IPv4 routers this switch allows one to enable ECN just for IPv6.
Perhaps ECN could be enabled by default in future.
No code changes since initial submission, just added documentation.
May I ask what lead to the rejection of the patch?
David Miller
maintainerFrom: Hannes Frederic Sowa <[email protected]>
Date: Thu, 3 Jan 2013 13:28:44 +0100
Quoted 11 lines · Hannes Frederic Sowa
Quoted 8 lines
ECN could be more reliable when used with IPv6 (I don't have proofs). For people who want to try ECN with IPv6 but still have problems connecting to destinations because of broken IPv4 routers this switch allows one to enable ECN just for IPv6.
Perhaps ECN could be enabled by default in future.
No code changes since initial submission, just added documentation.
May I ask what lead to the rejection of the patch?
I don't see any value in splitting up ipv4 and ipv6.
I think we should turn the existing knob on unliaterally by default. That would be a much better patch.
Quoted 11 lines · David Miller
From: Hannes Frederic Sowa <[email protected]>
Date: Thu, 3 Jan 2013 13:28:44 +0100Quoted 8 lines · Hannes Frederic Sowa
Quoted 7 lines
ECN could be more reliable when used with IPv6 (I don't have proofs). For people who want to try ECN with IPv6 but still have problems connecting to destinations because of broken IPv4 routers this switch allows one to enable ECN just for IPv6.
Perhaps ECN could be enabled by default in future.
Quoted 8 lines
Quoted 3 lines
Quoted 1 line
No code changes since initial submission, just added documentation.
May I ask what lead to the rejection of the patch?
I don't see any value in splitting up ipv4 and ipv6.
I think we should turn the existing knob on unliaterally by default. That would be a much better patch.
Oh, I would be happy to do that. :)
Quoted 14 lines · On Thu, 3 Jan 2013 13:58:12 +0100 Hannes Frederic Sowa…
Quoted 13 lines · David Miller
From: Hannes Frederic Sowa <[email protected]>
Date: Thu, 3 Jan 2013 13:28:44 +0100Quoted 10 lines · Hannes Frederic Sowa
Quoted 8 lines
ECN could be more reliable when used with IPv6 (I don't have proofs). For people who want to try ECN with IPv6 but still have problems connecting to destinations because of broken IPv4 routers this switch allows one to enable ECN just for IPv6.
Perhaps ECN could be enabled by default in future.
No code changes since initial submission, just added documentation.
Quoted 8 lines
Quoted 6 lines
Quoted 1 line
May I ask what lead to the rejection of the patch?
I don't see any value in splitting up ipv4 and ipv6.
I think we should turn the existing knob on unliaterally by default. That would be a much better patch.
Oh, I would be happy to do that. :)
Perhaps, ECN should be a property of the route. There is RTAX_FEATURE_ECN but it appears to have been lost as part of the removal of route cache.
Quoted 21 lines · Stephen Hemminger
Quoted 18 lines · On Thu, 3 Jan 2013 13:58:12 +0100 Hannes Frederic Sowa…
Quoted 17 lines · David Miller
From: Hannes Frederic Sowa <[email protected]>
Date: Thu, 3 Jan 2013 13:28:44 +0100Quoted 11 lines · Hannes Frederic Sowa
Quoted 8 lines
ECN could be more reliable when used with IPv6 (I don't have proofs). For people who want to try ECN with IPv6 but still have problems connecting to destinations because of broken IPv4 routers this switch allows one to enable ECN just for IPv6.
Perhaps ECN could be enabled by default in future.
No code changes since initial submission, just added documentation.
May I ask what lead to the rejection of the patch?
I don't see any value in splitting up ipv4 and ipv6.
Quoted 8 lines
Quoted 4 lines
Quoted 2 lines
I think we should turn the existing knob on unliaterally by default. That would be a much better patch.
Oh, I would be happy to do that. :)
Perhaps, ECN should be a property of the route. There is
RTAX_FEATURE_ECNbut it appears to have been lost as part of the removal of route cache.
I suggested something like this in the discussion on bufferbloat:
<http://thread.gmane.org/gmane.network.routing.bufferbloat/1086>
Especially if RFC5562 would be implemented one day, this could really be helpful.
Quoted 8 lines · David Miller
Quoted 8 lines · Hannes Frederic Sowa
Quoted 7 lines
ECN could be more reliable when used with IPv6 (I don't have proofs). For people who want to try ECN with IPv6 but still have problems connecting to destinations because of broken IPv4 routers this switch allows one to enable ECN just for IPv6.
Perhaps ECN could be enabled by default in future.
Quoted 8 lines
Quoted 3 lines
Quoted 1 line
No code changes since initial submission, just added documentation.
May I ask what lead to the rejection of the patch?
I don't see any value in splitting up ipv4 and ipv6.
I think we should turn the existing knob on unliaterally by default. That would be a much better patch.
I wonder if we really should go down this route to turn on ecn by default or if I should try to come up with a patch which marks non working ecn paths in the destination cache and suppress ecn for those connections. Any advice?
Quoted 11 lines · Hannes Frederic Sowa
ECN could be more reliable when used with IPv6 (I don't have proofs). For people who want to try ECN with IPv6 but still have problems connecting to destinations because of broken IPv4 routers this switch allows one to enable ECN just for IPv6.
Perhaps ECN could be enabled by default in future.
No code changes since initial submission, just added documentation.
Signed-off-by Hannes Frederic Sowa <[email protected]>---
It would be nice to make the ecn sysctl per net namespace.
Do you have an idea of how to adapt your patch to get this as well ?
Quoted 8 lines · Eric Dumazet
Quoted 7 lines · Hannes Frederic Sowa
ECN could be more reliable when used with IPv6 (I don't have proofs). For people who want to try ECN with IPv6 but still have problems connecting to destinations because of broken IPv4 routers this switch allows one to enable ECN just for IPv6.
Perhaps ECN could be enabled by default in future.
Quoted 8 lines
Quoted 4 lines
No code changes since initial submission, just added documentation.
Signed-off-by Hannes Frederic Sowa <[email protected]>---
It would be nice to make the ecn sysctl per net namespace.
Do you have an idea of how to adapt your patch to get this as well ?
Currently not, but I will try. :)
Is the direction to split the sysctl ok? Or should it be a unified sysctl for ipv4/ipv6 and only be separate per namespace?
Thanks!
Quoted 5 lines · Hannes Frederic Sowa
Currently not, but I will try. :)
Is the direction to split the sysctl ok? Or should it be a unified sysctl for ipv4/ipv6 and only be separate per namespace?
I fixed some ECN glitches in IPv6 in the past, I am not sure we can assume IPv6 gear is ECN bug free. In fact it might be the opposite.
So adding a per net sysctl would allow a better tuning for experiments, and allow some applications to use a private netns and change their sysctl.