Message ID | 20171108055209.54459-1-zenczykowski@gmail.com |
---|---|
State | Accepted, archived |
Delegated to: | David Miller |
Headers | show |
Series | net: ipv6: sysctl to specify IPv6 ND traffic class | expand |
From: Maciej Żenczykowski <zenczykowski@gmail.com> Date: Tue, 7 Nov 2017 21:52:09 -0800 > From: Maciej Żenczykowski <maze@google.com> > > Add a per-device sysctl to specify the default traffic class to use for > kernel originated IPv6 Neighbour Discovery packets. > > Currently this includes: > > - Router Solicitation (ICMPv6 type 133) > ndisc_send_rs() -> ndisc_send_skb() -> ip6_nd_hdr() > > - Neighbour Solicitation (ICMPv6 type 135) > ndisc_send_ns() -> ndisc_send_skb() -> ip6_nd_hdr() > > - Neighbour Advertisement (ICMPv6 type 136) > ndisc_send_na() -> ndisc_send_skb() -> ip6_nd_hdr() > > - Redirect (ICMPv6 type 137) > ndisc_send_redirect() -> ndisc_send_skb() -> ip6_nd_hdr() > > and if the kernel ever gets around to generating RA's, > it would presumably also include: > > - Router Advertisement (ICMPv6 type 134) > (radvd daemon could pick up on the kernel setting and use it) > > Interface drivers may examine the Traffic Class value and translate > the DiffServ Code Point into a link-layer appropriate traffic > prioritization scheme. An example of mapping IETF DSCP values to > IEEE 802.11 User Priority values can be found here: > > https://tools.ietf.org/html/draft-ietf-tsvwg-ieee-802-11 > > The expected primary use case is to properly prioritize ND over wifi. > > Testing: ... > (based on original change written by Erik Kline, with minor changes) > > v2: fix 'suspicious rcu_dereference_check() usage' > by explicitly grabbing the rcu_read_lock. > > Cc: Lorenzo Colitti <lorenzo@google.com> > Signed-off-by: Erik Kline <ek@google.com> > Signed-off-by: Maciej Żenczykowski <maze@google.com> Applied to net-next, thanks.
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index 54410a1d4065..d8676dda7fa6 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -1732,6 +1732,15 @@ ndisc_notify - BOOLEAN 1 - Generate unsolicited neighbour advertisements when device is brought up or hardware address changes. +ndisc_tclass - INTEGER + The IPv6 Traffic Class to use by default when sending IPv6 Neighbor + Discovery (Router Solicitation, Router Advertisement, Neighbor + Solicitation, Neighbor Advertisement, Redirect) messages. + These 8 bits can be interpreted as 6 high order bits holding the DSCP + value and 2 low order bits representing ECN (which you probably want + to leave cleared). + 0 - (default) + mldv1_unsolicited_report_interval - INTEGER The interval in milliseconds in which the next unsolicited MLDv1 report retransmit will take place. diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h index ea04ca024f0d..cb18c6290ca8 100644 --- a/include/linux/ipv6.h +++ b/include/linux/ipv6.h @@ -73,6 +73,7 @@ struct ipv6_devconf { __u32 enhanced_dad; __u32 addr_gen_mode; __s32 disable_policy; + __s32 ndisc_tclass; struct ctl_table_header *sysctl_header; }; diff --git a/include/uapi/linux/ipv6.h b/include/uapi/linux/ipv6.h index b22a9c4e1b12..9c0f4a92bcff 100644 --- a/include/uapi/linux/ipv6.h +++ b/include/uapi/linux/ipv6.h @@ -186,6 +186,7 @@ enum { DEVCONF_ADDR_GEN_MODE, DEVCONF_DISABLE_POLICY, DEVCONF_ACCEPT_RA_RT_INFO_MIN_PLEN, + DEVCONF_NDISC_TCLASS, DEVCONF_MAX }; diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 6233e06fa35c..a6dffd65eb9d 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -5059,6 +5059,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf, array[DEVCONF_ENHANCED_DAD] = cnf->enhanced_dad; array[DEVCONF_ADDR_GEN_MODE] = cnf->addr_gen_mode; array[DEVCONF_DISABLE_POLICY] = cnf->disable_policy; + array[DEVCONF_NDISC_TCLASS] = cnf->ndisc_tclass; } static inline size_t inet6_ifla6_size(void) @@ -5986,6 +5987,7 @@ int addrconf_sysctl_disable_policy(struct ctl_table *ctl, int write, } static int minus_one = -1; +static const int zero = 0; static const int one = 1; static const int two_five_five = 255; @@ -6356,6 +6358,15 @@ static const struct ctl_table addrconf_sysctl[] = { .mode = 0644, .proc_handler = addrconf_sysctl_disable_policy, }, + { + .procname = "ndisc_tclass", + .data = &ipv6_devconf.ndisc_tclass, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, + .extra1 = (void *)&zero, + .extra2 = (void *)&two_five_five, + }, { /* sentinel */ } diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index f9c3ffe04382..b3cea200c85e 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -427,12 +427,19 @@ static void ip6_nd_hdr(struct sk_buff *skb, int hop_limit, int len) { struct ipv6hdr *hdr; + struct inet6_dev *idev; + unsigned tclass; + + rcu_read_lock(); + idev = __in6_dev_get(skb->dev); + tclass = idev ? idev->cnf.ndisc_tclass : 0; + rcu_read_unlock(); skb_push(skb, sizeof(*hdr)); skb_reset_network_header(skb); hdr = ipv6_hdr(skb); - ip6_flow_hdr(hdr, 0, 0); + ip6_flow_hdr(hdr, tclass, 0); hdr->payload_len = htons(len); hdr->nexthdr = IPPROTO_ICMPV6;