aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorTom Herbert <therbert@google.com>2014-07-02 00:33:10 -0400
committerDavid S. Miller <davem@davemloft.net>2014-07-08 00:14:21 -0400
commitcb1ce2ef387b01686469487edd45994872d52d73 (patch)
tree4e905772c627b902b2f1aeaa752ae8b4a6b1b1fb /include
parent19469a873bafd4e65daef3597db2bd724c1b03c9 (diff)
ipv6: Implement automatic flow label generation on transmit
Automatically generate flow labels for IPv6 packets on transmit. The flow label is computed based on skb_get_hash. The flow label will only automatically be set when it is zero otherwise (i.e. flow label manager hasn't set one). This supports the transmit side functionality of RFC 6438. Added an IPv6 sysctl auto_flowlabels to enable/disable this behavior system wide, and added IPV6_AUTOFLOWLABEL socket option to enable this functionality per socket. By default, auto flowlabels are disabled to avoid possible conflicts with flow label manager, however if this feature proves useful we may want to enable it by default. It should also be noted that FreeBSD has already implemented automatic flow labels (including the sysctl and socket option). In FreeBSD, automatic flow labels default to enabled. Performance impact: Running super_netperf with 200 flows for TCP_RR and UDP_RR for IPv6. Note that in UDP case, __skb_get_hash will be called for every packet with explains slight regression. In the TCP case the hash is saved in the socket so there is no regression. Automatic flow labels disabled: TCP_RR: 86.53% CPU utilization 127/195/322 90/95/99% latencies 1.40498e+06 tps UDP_RR: 90.70% CPU utilization 118/168/243 90/95/99% latencies 1.50309e+06 tps Automatic flow labels enabled: TCP_RR: 85.90% CPU utilization 128/199/337 90/95/99% latencies 1.40051e+06 UDP_RR 92.61% CPU utilization 115/164/236 90/95/99% latencies 1.4687e+06 Signed-off-by: Tom Herbert <therbert@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'include')
-rw-r--r--include/linux/ipv6.h3
-rw-r--r--include/net/ipv6.h20
-rw-r--r--include/net/netns/ipv6.h1
-rw-r--r--include/uapi/linux/in6.h1
4 files changed, 24 insertions, 1 deletions
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index 5dc68c3ebcbd..ff560537dd61 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -199,7 +199,8 @@ struct ipv6_pinfo {
199 * 010: prefer public address 199 * 010: prefer public address
200 * 100: prefer care-of address 200 * 100: prefer care-of address
201 */ 201 */
202 dontfrag:1; 202 dontfrag:1,
203 autoflowlabel:1;
203 __u8 min_hopcount; 204 __u8 min_hopcount;
204 __u8 tclass; 205 __u8 tclass;
205 __be32 rcv_flowinfo; 206 __be32 rcv_flowinfo;
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index 2aa86e1135a1..4308f2ada8b3 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -699,6 +699,26 @@ static inline void ip6_set_txhash(struct sock *sk)
699 sk->sk_txhash = flow_hash_from_keys(&keys); 699 sk->sk_txhash = flow_hash_from_keys(&keys);
700} 700}
701 701
702static inline __be32 ip6_make_flowlabel(struct net *net, struct sk_buff *skb,
703 __be32 flowlabel, bool autolabel)
704{
705 if (!flowlabel && (autolabel || net->ipv6.sysctl.auto_flowlabels)) {
706 __be32 hash;
707
708 hash = skb_get_hash(skb);
709
710 /* Since this is being sent on the wire obfuscate hash a bit
711 * to minimize possbility that any useful information to an
712 * attacker is leaked. Only lower 20 bits are relevant.
713 */
714 hash ^= hash >> 12;
715
716 flowlabel = hash & IPV6_FLOWLABEL_MASK;
717 }
718
719 return flowlabel;
720}
721
702/* 722/*
703 * Header manipulation 723 * Header manipulation
704 */ 724 */
diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h
index 19d3446e59d2..eade27adecf3 100644
--- a/include/net/netns/ipv6.h
+++ b/include/net/netns/ipv6.h
@@ -28,6 +28,7 @@ struct netns_sysctl_ipv6 {
28 int ip6_rt_mtu_expires; 28 int ip6_rt_mtu_expires;
29 int ip6_rt_min_advmss; 29 int ip6_rt_min_advmss;
30 int flowlabel_consistency; 30 int flowlabel_consistency;
31 int auto_flowlabels;
31 int icmpv6_time; 32 int icmpv6_time;
32 int anycast_src_echo_reply; 33 int anycast_src_echo_reply;
33 int fwmark_reflect; 34 int fwmark_reflect;
diff --git a/include/uapi/linux/in6.h b/include/uapi/linux/in6.h
index 0d8e0f0342dc..22b7a69619d8 100644
--- a/include/uapi/linux/in6.h
+++ b/include/uapi/linux/in6.h
@@ -233,6 +233,7 @@ struct in6_flowlabel_req {
233#if 0 /* not yet */ 233#if 0 /* not yet */
234#define IPV6_USE_MIN_MTU 63 234#define IPV6_USE_MIN_MTU 63
235#endif 235#endif
236#define IPV6_AUTOFLOWLABEL 64
236 237
237/* 238/*
238 * Netfilter (1) 239 * Netfilter (1)