net: ipv6: sysctl to specify IPv6 ND traffic class
Subsystems (4)
PATCH 1/1 net: ipv6: sysctl to specify IPv6 ND traffic class
From: Maciej Żenczykowski <[email protected]>
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:
jzem22:~# cat /proc/sys/net/ipv6/conf/eth0/ndisc_tclass 0 jzem22:~# echo -1 > /proc/sys/net/ipv6/conf/eth0/ndisc_tclass -bash: echo: write error: Invalid argument jzem22:~# echo 256 > /proc/sys/net/ipv6/conf/eth0/ndisc_tclass -bash: echo: write error: Invalid argument jzem22:~# echo 0 > /proc/sys/net/ipv6/conf/eth0/ndisc_tclass jzem22:~# echo 255 > /proc/sys/net/ipv6/conf/eth0/ndisc_tclass jzem22:~# cat /proc/sys/net/ipv6/conf/eth0/ndisc_tclass 255 jzem22:~# echo 34 > /proc/sys/net/ipv6/conf/eth0/ndisc_tclass jzem22:~# cat /proc/sys/net/ipv6/conf/eth0/ndisc_tclass 34
jzem22:~# echo $[0xDC] > /proc/sys/net/ipv6/conf/eth0/ndisc_tclass jzem22:~# tcpdump -v -i eth0 icmp6 and src host jzem22.pgc and dst host fe80::1 tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes IP6 (class 0xdc, hlim 255, next-header ICMPv6 (58) payload length: 24) jzem22.pgc > fe80::1: [icmp6 sum ok] ICMP6, neighbor advertisement, length 24, tgt is jzem22.pgc, Flags [solicited]
(based on original change written by Erik Kline, with minor changes)
--- Documentation/networking/ip-sysctl.txt | 9 +++++++++ include/linux/ipv6.h | 1 + include/uapi/linux/ipv6.h | 1 + net/ipv6/addrconf.c | 11 +++++++++++ net/ipv6/ndisc.c | 4 +++- 5 files changed, 25 insertions(+), 1 deletion(-)
Documentation/networking/ip-sysctl.txt +9 -0
@@ -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.
include/linux/ipv6.h +1 -0
@@ -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; };
include/uapi/linux/ipv6.h +1 -0
@@ -186,6 +186,7 @@ enum {DEVCONF_ADDR_GEN_MODE ,DEVCONF_DISABLE_POLICY ,DEVCONF_ACCEPT_RA_RT_INFO_MIN_PLEN , +DEVCONF_NDISC_TCLASS , DEVCONF_MAX };
net/ipv6/addrconf.c +11 -0
@@ -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 */ }
net/ipv6/ndisc.c +3 -1
@@ -427,12 +427,14 @@ static void ip6_nd_hdr(struct sk_buff *skb, int hop_limit, int len) {struct ipv6hdr *hdr; +struct inet6_dev *idev =__in6_dev_get (skb->dev); +unsigned tclass = idev ? idev->cnf.ndisc_tclass :0 ;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 ;
Signature · 1 line
2.15.0.403.gc27cc4dac6-goog
Thanks.
Quoted 172 lines · Maciej Żenczykowski
From: Maciej Żenczykowski <[email protected]>
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-11The expected primary use case is to properly prioritize ND over wifi.
Testing:
jzem22:~# cat /proc/sys/net/ipv6/conf/eth0/ndisc_tclass 0 jzem22:~# echo -1 > /proc/sys/net/ipv6/conf/eth0/ndisc_tclass -bash: echo: write error: Invalid argument jzem22:~# echo 256 > /proc/sys/net/ipv6/conf/eth0/ndisc_tclass -bash: echo: write error: Invalid argument jzem22:~# echo 0 > /proc/sys/net/ipv6/conf/eth0/ndisc_tclass jzem22:~# echo 255 > /proc/sys/net/ipv6/conf/eth0/ndisc_tclass jzem22:~# cat /proc/sys/net/ipv6/conf/eth0/ndisc_tclass 255 jzem22:~# echo 34 > /proc/sys/net/ipv6/conf/eth0/ndisc_tclass jzem22:~# cat /proc/sys/net/ipv6/conf/eth0/ndisc_tclass 34jzem22:~# echo $[0xDC] > /proc/sys/net/ipv6/conf/eth0/ndisc_tclass jzem22:~# tcpdump -v -i eth0 icmp6 and src host jzem22.pgc and dst host fe80::1 tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes IP6 (class 0xdc, hlim 255, next-header ICMPv6 (58) payload length: 24) jzem22.pgc > fe80::1: [icmp6 sum ok] ICMP6, neighbor advertisement, length 24, tgt is jzem22.pgc, Flags [solicited](based on original change written by Erik Kline, with minor changes)
Cc Lorenzo Colitti <[email protected]>Cc Erik Kline <[email protected]>Signed-off-by Maciej Żenczykowski <[email protected]>--- Documentation/networking/ip-sysctl.txt | 9 +++++++++ include/linux/ipv6.h | 1 + include/uapi/linux/ipv6.h | 1 + net/ipv6/addrconf.c | 11 +++++++++++ net/ipv6/ndisc.c | 4 +++- 5 files changed, 25 insertions(+), 1 deletion(-)Documentation/networking/ip-sysctl.txt +9
-0@@ -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.include/linux/ipv6.h +1
-0@@ -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; };include/uapi/linux/ipv6.h +1
-0@@ -186,6 +186,7 @@ enum {DEVCONF_ADDR_GEN_MODE ,DEVCONF_DISABLE_POLICY ,DEVCONF_ACCEPT_RA_RT_INFO_MIN_PLEN , +DEVCONF_NDISC_TCLASS , DEVCONF_MAX };net/ipv6/addrconf.c +11
-0@@ -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 */ }net/ipv6/ndisc.c +3
-2@@ -427,12 +427,14 @@ static void ip6_nd_hdr(struct sk_buff *skb, int hop_limit, int len) {struct ipv6hdr *hdr; +struct inet6_dev *idev =__in6_dev_get (skb->dev); +unsigned tclass = idev ? idev->cnf.ndisc_tclass :0 ;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 ; --2.15.0.403.gc27cc4dac6-goog
PATCH 1/1 net: ipv6: sysctl to specify IPv6 ND traffic class
In reply to Maciej ŻenczykowskiFrom: Maciej Żenczykowski <[email protected]>
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:
jzem22:~# cat /proc/sys/net/ipv6/conf/eth0/ndisc_tclass 0 jzem22:~# echo -1 > /proc/sys/net/ipv6/conf/eth0/ndisc_tclass -bash: echo: write error: Invalid argument jzem22:~# echo 256 > /proc/sys/net/ipv6/conf/eth0/ndisc_tclass -bash: echo: write error: Invalid argument jzem22:~# echo 0 > /proc/sys/net/ipv6/conf/eth0/ndisc_tclass jzem22:~# echo 255 > /proc/sys/net/ipv6/conf/eth0/ndisc_tclass jzem22:~# cat /proc/sys/net/ipv6/conf/eth0/ndisc_tclass 255 jzem22:~# echo 34 > /proc/sys/net/ipv6/conf/eth0/ndisc_tclass jzem22:~# cat /proc/sys/net/ipv6/conf/eth0/ndisc_tclass 34
jzem22:~# echo $[0xDC] > /proc/sys/net/ipv6/conf/eth0/ndisc_tclass jzem22:~# tcpdump -v -i eth0 icmp6 and src host jzem22.pgc and dst host fe80::1 tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes IP6 (class 0xdc, hlim 255, next-header ICMPv6 (58) payload length: 24) jzem22.pgc > fe80::1: [icmp6 sum ok] ICMP6, neighbor advertisement, length 24, tgt is jzem22.pgc, Flags [solicited]
(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.
--- Documentation/networking/ip-sysctl.txt | 9 +++++++++ include/linux/ipv6.h | 1 + include/uapi/linux/ipv6.h | 1 + net/ipv6/addrconf.c | 11 +++++++++++ net/ipv6/ndisc.c | 9 ++++++++- 5 files changed, 30 insertions(+), 1 deletion(-)
Documentation/networking/ip-sysctl.txt +9 -0
@@ -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.
include/linux/ipv6.h +1 -0
@@ -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; };
include/uapi/linux/ipv6.h +1 -0
@@ -186,6 +186,7 @@ enum {DEVCONF_ADDR_GEN_MODE ,DEVCONF_DISABLE_POLICY ,DEVCONF_ACCEPT_RA_RT_INFO_MIN_PLEN , +DEVCONF_NDISC_TCLASS , DEVCONF_MAX };
net/ipv6/addrconf.c +11 -0
@@ -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 */ }
net/ipv6/ndisc.c +8 -1
@@ -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 ;
Signature · 1 line
2.15.0.403.gc27cc4dac6-goog
From: Maciej Żenczykowski <[email protected]>
Date: Tue, 7 Nov 2017 21:52:09 -0800
Quoted 35 lines
From: Maciej Żenczykowski <[email protected]>
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-11The expected primary use case is to properly prioritize ND over wifi.
Testing:
...
Quoted 8 lines
(based on original change written by Erik Kline, with minor changes)
v2: fix 'suspicious
rcu_dereference_check()usage'
by explicitly grabbing thercu_read_lock.Cc Lorenzo Colitti <[email protected]>Signed-off-by Erik Kline <[email protected]>Signed-off-by Maciej Żenczykowski <[email protected]>
Applied to net-next, thanks.