Still using IPTOS_TOS() in kernel? Really???
Subsystems (3)
[ Posted to linux-net a couple of days ago and didn't hear back... so reposting here since this might be more appropriate. ]
I'm looking at net/ipv4/ip_sockglue.c:
512 case IP_TOS: /* This sets both TOS and Precedence */
513 if (sk->sk_type == SOCK_STREAM) {
514 val &= ~3;
515 val |= inet->tos & 3;
516 }
517 if (inet->tos != val) {
518 inet->tos = val;
519 sk->sk_priority = rt_tos2priority(val);
520 sk_dst_reset(sk);
521 }
522 break;and include/net/route.h:
141 extern const __u8 ip_tos2prio[16];
142
143 static inline char rt_tos2priority(u8 tos)
144 {
145 return ip_tos2prio[IPTOS_TOS(tos)>>1];
146 }and finally net/ipv4/route.c:
165 #define ECN_OR_COST(class) TC_PRIO_##class
166
167 const __u8 ip_tos2prio[16] = {
168 TC_PRIO_BESTEFFORT,
169 ECN_OR_COST(FILLER),
170 TC_PRIO_BESTEFFORT,
171 ECN_OR_COST(BESTEFFORT),
172 TC_PRIO_BULK,
173 ECN_OR_COST(BULK),
174 TC_PRIO_BULK,
175 ECN_OR_COST(BULK),
176 TC_PRIO_INTERACTIVE,
177 ECN_OR_COST(INTERACTIVE),
178 TC_PRIO_INTERACTIVE,
179 ECN_OR_COST(INTERACTIVE),
180 TC_PRIO_INTERACTIVE_BULK,
181 ECN_OR_COST(INTERACTIVE_BULK),
182 TC_PRIO_INTERACTIVE_BULK,
183 ECN_OR_COST(INTERACTIVE_BULK)
184 };and it's slowly dawning on me that we're using an interpretation of the IP_TOS (and ip.ip_tos field) values that have been deprecated since 1998! Quoting RFC 2474:
3. Differentiated Services Field Definition
A replacement header field, called the DS field, is defined, which is intended to supersede the existing definitions of the IPv4 TOS octet [RFC791] and the IPv6 Traffic Class octet [IPv6].
Seems pretty clear, right? That DSCP is the new testament, here to replace the old testament... although if you look closely, the precedence values of IPTOS_PREC_ROUTINE looks a lot like IPTOS_CLASS_CS0, etc... so some backward compatibility was maintained. (See http://sourceware.org/bugzilla/show_bug.cgi?id=11027 and http://sourceware.org/bugzilla/show_bug.cgi?id=10789 if your glibc doesn't yet include the the IPTOS_CLASS_CSn and IPTOS_DSCP_AFxx values).
And indeed, only routers seem to pay attention to bits in the 0x1c space... I.e. between the upper 3 bits which still mean precedence, and the lower 2 bits which now signify experienced-congestion-notification (ECN).
Assuming that whatever the local host does to the output of the packet, that it's not going to sufficiently delay the packet enough because we're connected to some fast media (Fast ethernet, etc) then what we do locally shouldn't matter... unless of course we're using 802.1p tagging, in which case we can seriously mess up what happens next.
So how is it that no one noticed this issue yet, and given that Linux is used in a fair number of commercial embedded real-time boxes (like satellite and IPTV set-top boxes)... how are they not impacted by this?
Assuming my crusade to get various common apps and services (wget, TB, FF, Sendmail, Cyrus, ProFTPd, etc) to use DSCP/CS marking (very few apps currently use DSCP or precedence marking), then kernels with the proper default behavior will need to start shipping, right? I.e. out-of-the-box kernels should handle such apps without further configuration, such as needing to have the DSCP iptables module installed. They should "just work".
Thanks,
-Philip
Hi Philip,
interesting .. i am on the way to implement a DSCP/CS statistic to the kernel. We need this for network traffic accounting. The concept is the following:
We create a virtual file /pro/net/ipdscp , this includes several DSCP/CS counters. See http://www.iana.org/assignments/dscp-registry/. Every time ip_rcv_finish() is called, we take a look at the DSCP/CS (iph->tos) value and increment the related counter. If you're interested in, i will send you a patch ? ..
Maybe this is a good starting point for an DSCP/CS implementation. I was also shocked that the kernel do not really handle DiffServ thinks.
Quoted 7 lines
Assuming my crusade to get various common apps and services (wget, TB, FF,
Sendmail, Cyrus, ProFTPd, etc) to use DSCP/CS marking (very few apps currently use DSCP or precedence marking), then kernels with the proper default behavior will need to start shipping, right? I.e. out-of-the-box kernels should handle such apps without further configuration, such as needing to have the DSCP iptables module installed. They should "just work".
Right.
Best regards,
Torsten
Quoted 10 lines · Torsten Schmidt
Hi Philip,
interesting .. i am on the way to implement a DSCP/CS statistic to the kernel. We need this for network traffic accounting. The concept is the following:
We create a virtual file /pro/net/ipdscp , this includes several DSCP/CS counters. See http://www.iana.org/assignments/dscp-registry/. Every time
ip_rcv_finish()is called, we take a look at the DSCP/CS (iph->tos) value and increment the related counter. If you're interested in, i will send you a patch ? ..
That would be great.
Quoted 2 lines
Maybe this is a good starting point for an DSCP/CS implementation. I was also shocked that the kernel do not really handle DiffServ thinks.
I think it would also be useful to rework the existing definition of rt_tos2priority() to have a DSCP/CS version that people could then select and build in their kernel via a simple CONFIG_DIFFSERV_COMPLIANT flag.
It could be selectable and default to off until a set cut-over point in the future, then it could become the default.
RFC-2474 is now 11 years old... Odd that we're still not compliant.
-Philip
Quoted 11 lines
Quoted 7 lines
Assuming my crusade to get various common apps and services (wget, TB, FF,
Sendmail, Cyrus, ProFTPd, etc) to use DSCP/CS marking (very few apps currently use DSCP or precedence marking), then kernels with the proper default behavior will need to start shipping, right? I.e. out-of-the-box kernels should handle such apps without further configuration, such as needing to have the DSCP iptables module installed. They should "just work".Right.
Best regards,
Torsten
Quoted 7 lines · On Thursday 17 December 2009 20:45:32 you wrote:
Quoted 6 lines · Torsten Schmidt
Hi Philip,
interesting .. i am on the way to implement a DSCP/CS statistic to the kernel. We need this for network traffic accounting. The concept is the following:
Quoted 7 lines
Quoted 5 lines
We create a virtual file /pro/net/ipdscp , this includes several DSCP/CS counters. See http://www.iana.org/assignments/dscp-registry/. Every time
ip_rcv_finish()is called, we take a look at the DSCP/CS (iph->tos) value and increment the related counter. If you're interested in, i will send you a patch ? ..That would be great.
Here is a first PATCH, tested against 2.6.32. At the time we only support DSCP
class: CS0 and EF PHB. All other classes are shown in /proc/net/ipdscp, but always referenced with 0. Please take a look at ...
For debugging use:
# ping -Q 0xAB localhost # cat /pro/net/ipdscp
in which 0xAB is:
0x00 for CS0, ore
0xB8 for EF PHB
Torsten
From aacc531f2c3f992f3acee65d8806c2c67df348b7 Mon Sep 17 00:00:00 2001
From: Torsten Schmidt <[email protected]>
Date: Fri, 18 Dec 2009 15:18:52 +0100
Subject: [PATCH] ipv4: add DSCP statistic
This adds IPv4 DSCP statistic to the kernel. See:
* /proc/net/ipdscp
* IANA dscp-registry
* RFC 2474
--- include/linux/snmp.h | 28 +++++++++++ include/net/ipdscp.h | 65 ++++++++++++++++++++++++++ include/net/netns/mib.h | 4 ++ include/net/snmp.h | 6 +++ net/ipv4/Kconfig | 11 +++++ net/ipv4/Makefile | 2 +- net/ipv4/af_inet.c | 3 + net/ipv4/ip_input.c | 5 ++ net/ipv4/ipdscp.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 239 insertions(+), 1 deletions(-) create mode 100644 include/net/ipdscp.h create mode 100644 net/ipv4/ipdscp.c
include/linux/snmp.h +28 -0
@@ -260,4 +260,32 @@ enum__LINUX_MIB_XFRMMAX }; + +/* IPv4 DSCP */ +enum +{ +LINUX_MIB_IPDSCP_CS0 , +LINUX_MIB_IPDSCP_CS1 , +LINUX_MIB_IPDSCP_CS2 , +LINUX_MIB_IPDSCP_CS3 , +LINUX_MIB_IPDSCP_CS4 , +LINUX_MIB_IPDSCP_CS5 , +LINUX_MIB_IPDSCP_CS6 , +LINUX_MIB_IPDSCP_CS7 , +LINUX_MIB_IPDSCP_AF11 , +LINUX_MIB_IPDSCP_AF12 , +LINUX_MIB_IPDSCP_AF13 , +LINUX_MIB_IPDSCP_AF21 , +LINUX_MIB_IPDSCP_AF22 , +LINUX_MIB_IPDSCP_AF23 , +LINUX_MIB_IPDSCP_AF31 , +LINUX_MIB_IPDSCP_AF32 , +LINUX_MIB_IPDSCP_AF33 , +LINUX_MIB_IPDSCP_AF41 , +LINUX_MIB_IPDSCP_AF42 , +LINUX_MIB_IPDSCP_AF43 , +LINUX_MIB_IPDSCP_EF , + __IPDSCP_MIB_MAX +}; +#endif /* _LINUX_SNMP_H */
include/net/ipdscp.h new file +65 -0
65 lines not on this page · raw message
include/net/netns/mib.h +4 -0
@@ -23,6 +23,10 @@ struct netns_mib {#ifdef CONFIG_XFRM_STATISTICS DEFINE_SNMP_STAT(struct linux_xfrm_mib, xfrm_statistics);#endif +#ifdef CONFIG_IP_DSCP_STAT +struct proc_dir_entry *proc_net_ipdscp; + DEFINE_SNMP_STAT(struct ipdscp_mib, ipdscp_statistics); +#endif };#endif
include/net/snmp.h +6 -0
@@ -122,6 +122,12 @@ struct linux_xfrm_mib {unsigned long mibs[LINUX_MIB_XFRMMAX ]; }; +/* Linux IPv4 DSCP */ +#define IPDSCP_MIB_MAX __IPDSCP_MIB_MAX +struct ipdscp_mib { +unsigned long mibs[IPDSCP_MIB_MAX ]; +}; +/* * FIXME: On x86 and some other CPUs the split into user and softirq parts * is not needed because addl $1,memory is atomic against interrupts (but
net/ipv4/Kconfig +11 -0
@@ -272,6 +272,17 @@ config IP_PIMSM_V2 gated-5). This routing protocol is not used widely, so say N unless you want to play with it. +config IP_DSCP_STAT + bool "IP: DSCP statistic" + help + This adds IPv4 DSCP statistic to the kernel. + See: + * /proc/net/ipdscp + * IANA dscp-registry + * RFC 2474 + + If unsure, say N. + config ARPD bool "IP: ARP daemon support" ---help---
net/ipv4/Makefile +1 -1
@@ -11,7 +11,7 @@ obj-y := route.o inetpeer.o protocol.o \ datagram.o raw.o udp.o udplite.o \ arp.o icmp.o devinet.o af_inet.o igmp.o \ fib_frontend.o fib_semantics.o \ - inet_fragment.o + inet_fragment.o ipdscp.o obj-$(CONFIG_SYSCTL) += sysctl_net_ipv4.o obj-$(CONFIG_IP_FIB_HASH) += fib_hash.o
net/ipv4/af_inet.c +3 -0
@@ -112,6 +112,7 @@#include <net/inet_common.h> #include <net/xfrm.h> #include <net/net_namespace.h> +#include <net/ipdscp.h> #ifdef CONFIG_IP_MROUTE #include <linux/mroute.h> #endif
@@ -1485,6 +1486,7 @@ static __net_init int ipv4_mib_init_net(struct net *net) goto err_icmpmsg_mib;tcp_mib_init (net); +ipdscp_stat_init (net);return 0 ; err_icmpmsg_mib:
@@ -1512,6 +1514,7 @@ static __net_exit void ipv4_mib_exit_net(struct net *net)snmp_mib_free ((void **)net->mib.net_statistics);snmp_mib_free ((void **)net->mib.ip_statistics);snmp_mib_free ((void **)net->mib.tcp_statistics); +ipdscp_stat_fini (net); }static __net_initdata struct pernet_operations ipv4_mib_ops = {
net/ipv4/ip_input.c +5 -0
@@ -143,6 +143,7 @@#include <net/xfrm.h> #include <linux/mroute.h> #include <linux/netlink.h> +#include <net/ipdscp.h> /* * Process Router Attention IP option
@@ -365,6 +366,10 @@ static int ip_rcv_finish(struct sk_buff *skb)IP_UPD_PO_STATS_BH (dev_net (rt->u.dst.dev),IPSTATS_MIB_INBCAST , skb->len); +#ifdef CONFIG_IP_DSCP_STAT +ipv4_dscp_stat (dev_net (rt->u.dst.dev), iph->tos); +#endif +return dst_input (skb); drop:
net/ipv4/ipdscp.c new file +116 -0
116 lines not on this page · raw message
Signature · 1 line
1.6.3.3
Hi Philip,
here a second PATCH to add the missing DSCP classes to ipv4_dscp_stat(), also tested against 2.6.32.
Next step is to add IN / OUT statistic to DSCP. Maybe /proc/net/ipdscp will look like:
CS0 in out
CS1 in out
...
EF in out
any comments ?
Torsten
From 58a2a79f4083fa614637cab13fe7df99b92b6fcf Mon Sep 17 00:00:00 2001
From: Torsten Schmidt <[email protected]>
Date: Mon, 21 Dec 2009 21:30:44 +0100
Subject: [PATCH 2/2] ipv4: add missing DSCP classes
This patch adds the missing IANA DSCP registry entries to ipv4 DSCP statistic counter. See /proc/net/ipdscp
--- include/net/ipdscp.h | 20 +++++++++++++++++++- 1 files changed, 19 insertions(+), 1 deletions(-)
include/net/ipdscp.h +19 -1
@@ -58,7 +58,25 @@ static inline void ipv4_dscp_stat(struct net *net, __u8 dsfield)switch (dsfield >>2 ) {case IP_DSCP_CS0 :IP_DSCP_INC_STATS_BH (net,LINUX_MIB_IPDSCP_CS0 );break ;case IP_DSCP_EF :IP_DSCP_INC_STATS_BH (net,LINUX_MIB_IPDSCP_EF );break ; -/* add new entrys here ... */ +case IP_DSCP_CS1 :IP_DSCP_INC_STATS_BH (net,LINUX_MIB_IPDSCP_CS1 );break ; +case IP_DSCP_CS2 :IP_DSCP_INC_STATS_BH (net,LINUX_MIB_IPDSCP_CS2 );break ; +case IP_DSCP_CS3 :IP_DSCP_INC_STATS_BH (net,LINUX_MIB_IPDSCP_CS3 );break ; +case IP_DSCP_CS4 :IP_DSCP_INC_STATS_BH (net,LINUX_MIB_IPDSCP_CS4 );break ; +case IP_DSCP_CS5 :IP_DSCP_INC_STATS_BH (net,LINUX_MIB_IPDSCP_CS5 );break ; +case IP_DSCP_CS6 :IP_DSCP_INC_STATS_BH (net,LINUX_MIB_IPDSCP_CS6 );break ; +case IP_DSCP_CS7 :IP_DSCP_INC_STATS_BH (net,LINUX_MIB_IPDSCP_CS7 );break ; +case IP_DSCP_AF11 :IP_DSCP_INC_STATS_BH (net,LINUX_MIB_IPDSCP_AF11 );break ; +case IP_DSCP_AF12 :IP_DSCP_INC_STATS_BH (net,LINUX_MIB_IPDSCP_AF12 );break ; +case IP_DSCP_AF13 :IP_DSCP_INC_STATS_BH (net,LINUX_MIB_IPDSCP_AF13 );break ; +case IP_DSCP_AF21 :IP_DSCP_INC_STATS_BH (net,LINUX_MIB_IPDSCP_AF21 );break ; +case IP_DSCP_AF22 :IP_DSCP_INC_STATS_BH (net,LINUX_MIB_IPDSCP_AF22 );break ; +case IP_DSCP_AF23 :IP_DSCP_INC_STATS_BH (net,LINUX_MIB_IPDSCP_AF23 );break ; +case IP_DSCP_AF31 :IP_DSCP_INC_STATS_BH (net,LINUX_MIB_IPDSCP_AF31 );break ; +case IP_DSCP_AF32 :IP_DSCP_INC_STATS_BH (net,LINUX_MIB_IPDSCP_AF32 );break ; +case IP_DSCP_AF33 :IP_DSCP_INC_STATS_BH (net,LINUX_MIB_IPDSCP_AF33 );break ; +case IP_DSCP_AF41 :IP_DSCP_INC_STATS_BH (net,LINUX_MIB_IPDSCP_AF41 );break ; +case IP_DSCP_AF42 :IP_DSCP_INC_STATS_BH (net,LINUX_MIB_IPDSCP_AF42 );break ; +case IP_DSCP_AF43 :IP_DSCP_INC_STATS_BH (net,LINUX_MIB_IPDSCP_AF43 );break ; } }
Signature · 1 line
1.6.3.3
Quoted 13 lines · Torsten Schmidt
Hi Philip,
here a second PATCH to add the missing DSCP classes to
ipv4_dscp_stat(), also tested against 2.6.32.Next step is to add IN / OUT statistic to DSCP. Maybe
/proc/net/ipdscpwill look like:
CS0 in out
CS1 in out
...
EF in out
Quoted 2 lines
any comments ?
Torsten
Hi Torsten,
Yes, the MIB changes are certainly important... we are more focused though on actually updating the default queuing strategies.
I'll poke around and see if I can figure out how that works...
Looking at include/linux/pkt_sched.h:
#define TC_PRIO_BESTEFFORT 0 #define TC_PRIO_FILLER 1 #define TC_PRIO_BULK 2 #define TC_PRIO_INTERACTIVE_BULK 4 #define TC_PRIO_INTERACTIVE 6 #define TC_PRIO_CONTROL 7
it seems that these TC priorities are just random, unrelated buckets and their ordinality has no relation to their priority. Is that correct?
If that's the case, then you *can't* just do:
static inline char rt_dscp2priority(u8 tos)
{
return IPTOS_PREC(tos)>>5;
}for instance. No, that would be too easy. :-)
-Philip
Quoted 11 lines
I'll poke around and see if I can figure out how that works...
Looking at
include/linux/pkt_sched.h:#define TC_PRIO_BESTEFFORT 0 #define TC_PRIO_FILLER 1 #define TC_PRIO_BULK 2 #define TC_PRIO_INTERACTIVE_BULK 4 #define TC_PRIO_INTERACTIVE 6 #define TC_PRIO_CONTROL 7
Quoted 2 lines
it seems that these TC priorities are just random, unrelated buckets and
their ordinality has no relation to their priority. Is that correct?
No.
1.Type Of Service Field is defined in RFC 791:
Bits 0-2: Precedence. Bit 3: 0 = Normal Delay, 1 = Low Delay. Bit 4: 0 = Normal Throughput, 1 = High Throughput. Bit 5: 0 = Normal Reliability, 1 = High Reliability. Bits 6-7: ECN (RFC 3168). ECN-ECT, ECN-CE
2. include/net/route.h
static inline char rt_tos2priority(u8 tos)
{
return ip_tos2prio[IPTOS_TOS(tos)>>1];
}- IPTOS_TOS(tos), masks 0001.1110
(from left: Delay, Throughput, Reliability, ECN-ECT)
- IPTOS_TOS(tos)>>1, generates: 0000.1111 value range: 0 .. 15.
- ip_tos2prio [ IPTOS_TOS(tos)>>1 ],
lookup table:
3. net/ipv4/route.c
const __u8 ip_tos2prio[16] = {
TC_PRIO_BESTEFFORT,
ECN_OR_COST(FILLER),
TC_PRIO_BESTEFFORT,
ECN_OR_COST(BESTEFFORT),
TC_PRIO_BULK,
ECN_OR_COST(BULK),
TC_PRIO_BULK,
ECN_OR_COST(BULK),
TC_PRIO_INTERACTIVE,
ECN_OR_COST(INTERACTIVE),
TC_PRIO_INTERACTIVE,
ECN_OR_COST(INTERACTIVE),
TC_PRIO_INTERACTIVE_BULK,
ECN_OR_COST(INTERACTIVE_BULK),
TC_PRIO_INTERACTIVE_BULK,
ECN_OR_COST(INTERACTIVE_BULK)
};with resolved defines it would look like:
const __u8 ip_tos2prio[16] = {0 1 0 0 2 2 2 2 6 6 6 6 4 4 4 4 };
So y = rt_tos2priority(x) maps:
- - - - - - - - - - -
x y bin(x)
0 0 0000
1 1 0001 -> ECN - ECT bit set
2 0 0010 -> High Reliability bit set
3 0 0011
4 2 0100 -> High Throughput bit set
5 2 0101
6 2 0110
7 2 0111
8 6 1000 -> Low Delay bit set
9 6 1001
10 6 1010
11 6 1011
12 4 1100
13 4 1101
14 4 1110
15 4 1111
4.
High Reliability gets priority 0.
High Throughput gets priority 2.
Low Delay gets highest priority 6.
priority:
-> Low Delay (6), High Throughput (2), High Reliability (0) !
5.
Quoted 7 lines
If that's the case, then you *can't* just do:
static inline charrt_dscp2priority(u8 tos){ return IPTOS_PREC(tos)>>5; }for instance. No, that would be too easy. :-)
No, thats right. You map:
y = rt_dscp2priority(x)
y x
- - - - - - - -
0 CS0
1 CS1
2 CS2
3 CS3
4 CS4
5 CS5
6 CS6
7 CS7
This IMHO is compliant to RFC 2474.
6. So we simply need to do:
static inline char rt_tos2priority(u8 tos)
{
#ifdef CONFIG_IP_DIFFSERV_COMPLIANT return tos >> 5; #else return ip_tos2prio[IPTOS_TOS(tos)>>1];
#endif
}
7. -> See [PATCH]: ipv4: add DiffServ priority based routing
Enables IPv4 Differentiated Services support for IP priority based routing. Notice that the IP TOS field was redefined 1998 to DiffServ (RFC 2474). Type Of Service is deprecated since 1998 !
This patch adds a compliant flag to net/ipv4/Kconfig, which allows the user to select DiffServ ore TOS priority based routing. Default answer is TOS.
Torsten
From e7539f1d3620286559d298b81dc5ca1672af4733 Mon Sep 17 00:00:00 2001
From: Torsten Schmidt <[email protected]>
Date: Tue, 22 Dec 2009 12:49:54 +0100
Subject: [PATCH] ipv4: add DiffServ priority based routing
Enables IPv4 Differentiated Services support for IP priority based routing. Notice that the IP TOS field was redefined 1998 to DiffServ (RFC 2474). Type Of Service is deprecated since 1998 !
This patch adds a compliant flag to net/ipv4/Kconfig, which allows the user to select DiffServ ore TOS priority based routing. Default answer is TOS.
--- include/net/route.h | 4 ++++ net/ipv4/Kconfig | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 0 deletions(-)
include/net/route.h +4 -0
@@ -141,7 +141,11 @@ extern const __u8 ip_tos2prio[16];static inline char rt_tos2priority (u8 tos) { +#ifdef CONFIG_IP_DIFFSERV_COMPLIANT +return tos >>5 ; +#else return ip_tos2prio[IPTOS_TOS (tos)>>1 ]; +#endif } static inline int ip_route_connect(struct rtable **rp, __be32 dst,
net/ipv4/Kconfig +15 -0
@@ -272,6 +272,21 @@ config IP_PIMSM_V2 gated-5). This routing protocol is not used widely, so say N unless you want to play with it. +config IP_DIFFSERV_COMPLIANT + bool "IP: DiffServ priority routing" + default n + help + Enables IPv4 Differentiated Services support for IP priority based + routing. If you say YES here, TOS priority based routing is disabled. + Notice that the IP TOS field was redefined 1998 to DiffServ (RFC 2474). + Type Of Service is deprecated since 1998 ! So in future default answer + should be YES. + + Y: DiffServ + N: Type Of Service + + If unsure, say N. + config IP_DSCP_STAT bool "IP: DSCP statistic" help
Signature · 1 line
1.6.3.3
Quoted 126 lines · Torsten Schmidt
Quoted 11 lines
I'll poke around and see if I can figure out how that works...
Looking at
include/linux/pkt_sched.h:#define TC_PRIO_BESTEFFORT 0 #define TC_PRIO_FILLER 1 #define TC_PRIO_BULK 2 #define TC_PRIO_INTERACTIVE_BULK 4 #define TC_PRIO_INTERACTIVE 6 #define TC_PRIO_CONTROL 7Quoted 2 lines
it seems that these TC priorities are just random, unrelated buckets and
their ordinality has no relation to their priority. Is that correct?No.
1.Type Of Service Field is defined in RFC 791:
Bits 0-2: Precedence. Bit 3: 0 = Normal Delay, 1 = Low Delay. Bit 4: 0 = Normal Throughput, 1 = High Throughput. Bit 5: 0 = Normal Reliability, 1 = High Reliability. Bits 6-7: ECN (RFC 3168). ECN-ECT, ECN-CE2.
include/net/route.h
static inline charrt_tos2priority(u8 tos){ return ip_tos2prio[IPTOS_TOS(tos)>>1]; }-
IPTOS_TOS(tos), masks 0001.1110
(from left: Delay, Throughput, Reliability, ECN-ECT)
- IPTOS_TOS(tos)>>1, generates: 0000.1111 value range: 0 .. 15.
-ip_tos2prio[ IPTOS_TOS(tos)>>1 ],
lookup table:3.
net/ipv4/route.cconst __u8 ip_tos2prio[16] = { TC_PRIO_BESTEFFORT, ECN_OR_COST(FILLER), TC_PRIO_BESTEFFORT, ECN_OR_COST(BESTEFFORT), TC_PRIO_BULK, ECN_OR_COST(BULK), TC_PRIO_BULK, ECN_OR_COST(BULK), TC_PRIO_INTERACTIVE, ECN_OR_COST(INTERACTIVE), TC_PRIO_INTERACTIVE, ECN_OR_COST(INTERACTIVE), TC_PRIO_INTERACTIVE_BULK, ECN_OR_COST(INTERACTIVE_BULK), TC_PRIO_INTERACTIVE_BULK, ECN_OR_COST(INTERACTIVE_BULK) };with resolved defines it would look like:
const__u8ip_tos2prio[16] = {0 1 0 0 2 2 2 2 6 6 6 6 4 4 4 4 };So y =
rt_tos2priority(x)maps:
- - - - - - - - - - -
x y bin(x)
0 0 0000
1 1 0001 -> ECN - ECT bit set
2 0 0010 -> High Reliability bit set
3 0 0011
4 2 0100 -> High Throughput bit set
5 2 0101
6 2 0110
7 2 0111
8 6 1000 -> Low Delay bit set
9 6 1001
10 6 1010
11 6 1011
12 4 1100
13 4 1101
14 4 1110
15 4 11114.
High Reliability gets priority 0.
High Throughput gets priority 2.
Low Delay gets highest priority 6.priority:
-> Low Delay (6), High Throughput (2), High Reliability (0) !5.
Quoted 7 lines
If that's the case, then you *can't* just do:
static inline charrt_dscp2priority(u8 tos){ return IPTOS_PREC(tos)>>5; }for instance. No, that would be too easy. :-)
No, thats right. You map:
y =
rt_dscp2priority(x)
y x
- - - - - - - -
0 CS0
1 CS1
2 CS2
3 CS3
4 CS4
5 CS5
6 CS6
7 CS7This IMHO is compliant to RFC 2474.
6. So we simply need to do:
static inline charrt_tos2priority(u8 tos)
{#ifdef CONFIG_IP_DIFFSERV_COMPLIANT return tos >> 5; #else return ip_tos2prio[IPTOS_TOS(tos)>>1];#endif
}7. -> See [PATCH]: ipv4: add DiffServ priority based routing
Enables IPv4 Differentiated Services support for IP priority based routing. Notice that the IP TOS field was redefined 1998 to DiffServ (RFC 2474). Type Of Service is deprecated since 1998 !
Quoted 10 lines
This patch adds a compliant flag to
net/ipv4/Kconfig, which allows the user to select DiffServ ore TOS priority based routing. Default answer is TOS.Signed-off-by Torsten Schmidt <[email protected]>Torsten
Can you extend the patch to include classify_1d() in net/mac80211/wme.c?
I'm thinking:
}
- if (dscp & 0x1c)
+#if !defined(CONFIG_IP_DIFFSERV_COMPLIANT)
+ if (IPTOS_TOS(dscp) & ~IPTOS_LOWCOST)
return 0;
+#endif
return dscp >> 5;}
should do it.
-Philip
Review
Quoted 13 lines
Can you extend the patch to include
classify_1d()innet/mac80211/wme.c?I'm thinking:
}(quoted diff) +3
-1- if (dscp & 0x1c) +#if !defined(CONFIG_IP_DIFFSERV_COMPLIANT) + if (IPTOS_TOS(dscp) & ~IPTOS_LOWCOST) return 0; +#endif return dscp >> 5; }
This code segment seems to be older stuff. Its not in 2.6.32.
Torsten
Quoted 15 lines · Torsten Schmidt
Review
Quoted 13 lines
Can you extend the patch to include
classify_1d()innet/mac80211/wme.c?I'm thinking:
}(quoted diff) +3
-1- if (dscp & 0x1c) +#if !defined(CONFIG_IP_DIFFSERV_COMPLIANT) + if (IPTOS_TOS(dscp) & ~IPTOS_LOWCOST) return 0; +#endif return dscp >> 5; }This code segment seems to be older stuff. Its not in 2.6.32.
Quoted 1 line
Torsten
I'm running 2.6.27.42.
Hi Philip,
this patch series adds IP DiffServ OUT counters and renames /proc/net/ipdscp to /proc/net/ip_dscp to stay compatible.
See:
---
ipv4: prepare DSCP statistic for IN/OUT counters
ipv4: add DSCP OUT statistic
ipv4: change DSCP proc file name
---
Torsten
From 1e34debd128e09f22ffc00b4cb7cc5f1de52e2ff Mon Sep 17 00:00:00 2001
From: Torsten Schmidt <[email protected]>
Date: Tue, 5 Jan 2010 09:34:02 +0100
Subject: [PATCH 1/3] ipv4: prepare DSCP statistic for IN/OUT counters
some renames and cleanups.
--- include/net/ipdscp.h | 52 +++++++++++++++++++++------------------------- include/net/netns/mib.h | 2 +- net/ipv4/ip_input.c | 2 +- net/ipv4/ipdscp.c | 8 +++--- 4 files changed, 30 insertions(+), 34 deletions(-)
include/net/ipdscp.h +24 -28
@@ -39,13 +39,9 @@#define IP_DSCP_EF (0x2E)#ifdef CONFIG_IP_DSCP_STAT -#define IP_DSCP_INC_STATS (net, field) SNMP_INC_STATS((net)->mib.ipdscp_statistics, field) -#define IP_DSCP_INC_STATS_BH (net, field) SNMP_INC_STATS_BH((net)->mib.ipdscp_statistics, field) -#define IP_DSCP_INC_STATS_USER (net, field) SNMP_INC_STATS_USER((net)-mib.ipdscp_statistics, field) +#define IP_DSCPIN_INC_STATS_BH (net, field) SNMP_INC_STATS_BH((net)->mib.ipdscp_in_statistics, field)#else -#define IP_DSCP_INC_STATS (net, field) ((void)(net)) -#define IP_DSCP_INC_STATS_BH (net, field) ((void)(net)) -#define IP_DSCP_INC_STATS_USER (net, field) ((void)(net)) +#define IP_DSCPIN_INC_STATS_BH (net, field) ((void)(net))#endif
@@ -53,30 +49,30 @@ int __net_init ipdscp_stat_init(struct net *net);void ipdscp_stat_fini (struct net *net); -static inline void ipv4_dscp_stat (struct net *net,__u8 dsfield) +static inline void ipv4_dscp_stat_in (struct net *net,__u8 dsfield) {switch (dsfield >>2 ) { -case IP_DSCP_CS0 :IP_DSCP_INC_STATS_BH (net,LINUX_MIB_IPDSCP_CS0 );break ; -case IP_DSCP_EF :IP_DSCP_INC_STATS_BH (net,LINUX_MIB_IPDSCP_EF );break ; -case IP_DSCP_CS1 :IP_DSCP_INC_STATS_BH (net,LINUX_MIB_IPDSCP_CS1 );break ; -case IP_DSCP_CS2 :IP_DSCP_INC_STATS_BH (net,LINUX_MIB_IPDSCP_CS2 );break ; -case IP_DSCP_CS3 :IP_DSCP_INC_STATS_BH (net,LINUX_MIB_IPDSCP_CS3 );break ; -case IP_DSCP_CS4 :IP_DSCP_INC_STATS_BH (net,LINUX_MIB_IPDSCP_CS4 );break ; -case IP_DSCP_CS5 :IP_DSCP_INC_STATS_BH (net,LINUX_MIB_IPDSCP_CS5 );break ; -case IP_DSCP_CS6 :IP_DSCP_INC_STATS_BH (net,LINUX_MIB_IPDSCP_CS6 );break ; -case IP_DSCP_CS7 :IP_DSCP_INC_STATS_BH (net,LINUX_MIB_IPDSCP_CS7 );break ; -case IP_DSCP_AF11 :IP_DSCP_INC_STATS_BH (net,LINUX_MIB_IPDSCP_AF11 );break ; -case IP_DSCP_AF12 :IP_DSCP_INC_STATS_BH (net,LINUX_MIB_IPDSCP_AF12 );break ; -case IP_DSCP_AF13 :IP_DSCP_INC_STATS_BH (net,LINUX_MIB_IPDSCP_AF13 );break ; -case IP_DSCP_AF21 :IP_DSCP_INC_STATS_BH (net,LINUX_MIB_IPDSCP_AF21 );break ; -case IP_DSCP_AF22 :IP_DSCP_INC_STATS_BH (net,LINUX_MIB_IPDSCP_AF22 );break ; -case IP_DSCP_AF23 :IP_DSCP_INC_STATS_BH (net,LINUX_MIB_IPDSCP_AF23 );break ; -case IP_DSCP_AF31 :IP_DSCP_INC_STATS_BH (net,LINUX_MIB_IPDSCP_AF31 );break ; -case IP_DSCP_AF32 :IP_DSCP_INC_STATS_BH (net,LINUX_MIB_IPDSCP_AF32 );break ; -case IP_DSCP_AF33 :IP_DSCP_INC_STATS_BH (net,LINUX_MIB_IPDSCP_AF33 );break ; -case IP_DSCP_AF41 :IP_DSCP_INC_STATS_BH (net,LINUX_MIB_IPDSCP_AF41 );break ; -case IP_DSCP_AF42 :IP_DSCP_INC_STATS_BH (net,LINUX_MIB_IPDSCP_AF42 );break ; -case IP_DSCP_AF43 :IP_DSCP_INC_STATS_BH (net,LINUX_MIB_IPDSCP_AF43 );break ; +case IP_DSCP_CS0 :IP_DSCPIN_INC_STATS_BH (net,LINUX_MIB_IPDSCP_CS0 );break ; +case IP_DSCP_EF :IP_DSCPIN_INC_STATS_BH (net,LINUX_MIB_IPDSCP_EF );break ; +case IP_DSCP_CS1 :IP_DSCPIN_INC_STATS_BH (net,LINUX_MIB_IPDSCP_CS1 );break ; +case IP_DSCP_CS2 :IP_DSCPIN_INC_STATS_BH (net,LINUX_MIB_IPDSCP_CS2 );break ; +case IP_DSCP_CS3 :IP_DSCPIN_INC_STATS_BH (net,LINUX_MIB_IPDSCP_CS3 );break ; +case IP_DSCP_CS4 :IP_DSCPIN_INC_STATS_BH (net,LINUX_MIB_IPDSCP_CS4 );break ; +case IP_DSCP_CS5 :IP_DSCPIN_INC_STATS_BH (net,LINUX_MIB_IPDSCP_CS5 );break ; +case IP_DSCP_CS6 :IP_DSCPIN_INC_STATS_BH (net,LINUX_MIB_IPDSCP_CS6 );break ; +case IP_DSCP_CS7 :IP_DSCPIN_INC_STATS_BH (net,LINUX_MIB_IPDSCP_CS7 );break ; +case IP_DSCP_AF11 :IP_DSCPIN_INC_STATS_BH (net,LINUX_MIB_IPDSCP_AF11 );break ; +case IP_DSCP_AF12 :IP_DSCPIN_INC_STATS_BH (net,LINUX_MIB_IPDSCP_AF12 );break ; +case IP_DSCP_AF13 :IP_DSCPIN_INC_STATS_BH (net,LINUX_MIB_IPDSCP_AF13 );break ; +case IP_DSCP_AF21 :IP_DSCPIN_INC_STATS_BH (net,LINUX_MIB_IPDSCP_AF21 );break ; +case IP_DSCP_AF22 :IP_DSCPIN_INC_STATS_BH (net,LINUX_MIB_IPDSCP_AF22 );break ; +case IP_DSCP_AF23 :IP_DSCPIN_INC_STATS_BH (net,LINUX_MIB_IPDSCP_AF23 );break ; +case IP_DSCP_AF31 :IP_DSCPIN_INC_STATS_BH (net,LINUX_MIB_IPDSCP_AF31 );break ; +case IP_DSCP_AF32 :IP_DSCPIN_INC_STATS_BH (net,LINUX_MIB_IPDSCP_AF32 );break ; +case IP_DSCP_AF33 :IP_DSCPIN_INC_STATS_BH (net,LINUX_MIB_IPDSCP_AF33 );break ; +case IP_DSCP_AF41 :IP_DSCPIN_INC_STATS_BH (net,LINUX_MIB_IPDSCP_AF41 );break ; +case IP_DSCP_AF42 :IP_DSCPIN_INC_STATS_BH (net,LINUX_MIB_IPDSCP_AF42 );break ; +case IP_DSCP_AF43 :IP_DSCPIN_INC_STATS_BH (net,LINUX_MIB_IPDSCP_AF43 );break ; } }
include/net/netns/mib.h +1 -1
@@ -25,7 +25,7 @@ struct netns_mib {#endif #ifdef CONFIG_IP_DSCP_STAT struct proc_dir_entry *proc_net_ipdscp; - DEFINE_SNMP_STAT(struct ipdscp_mib, ipdscp_statistics); + DEFINE_SNMP_STAT(struct ipdscp_mib, ipdscp_in_statistics);#endif };
net/ipv4/ip_input.c +1 -1
@@ -367,7 +367,7 @@ static int ip_rcv_finish(struct sk_buff *skb) skb->len);#ifdef CONFIG_IP_DSCP_STAT -ipv4_dscp_stat (dev_net (rt->u.dst.dev), iph->tos); +ipv4_dscp_stat_in (dev_net (rt->u.dst.dev), iph->tos);#endif return dst_input (skb);
net/ipv4/ipdscp.c +4 -4
@@ -47,7 +47,7 @@ static int ipdscp_statistics_seq_show(struct seq_file *seq, void *v)int i;for (i=0 ; ipdscp_mib_list[i].name; i++)seq_printf (seq,"%-24s\t%lu\n" , ipdscp_mib_list[i].name, -snmp_fold_field ((void **)net->mib.ipdscp_statistics, +snmp_fold_field ((void **)net->mib.ipdscp_in_statistics, ipdscp_mib_list[i].entry));return 0 ; }
@@ -87,19 +87,19 @@ int __net_init ipdscp_stat_init(struct net *net) {int rv; -if (snmp_mib_init ((void **)net->mib.ipdscp_statistics, +if (snmp_mib_init ((void **)net->mib.ipdscp_in_statistics,sizeof (struct ipdscp_mib )) <0 )return -ENOMEM ; rv =ipdscp_proc_init (net);if (rv <0 ) -snmp_mib_free ((void **)net->mib.ipdscp_statistics); +snmp_mib_free ((void **)net->mib.ipdscp_in_statistics);return rv; }void ipdscp_stat_fini (struct net *net) {ipdscp_proc_fini (net); -snmp_mib_free ((void **)net->mib.ipdscp_statistics); +snmp_mib_free ((void **)net->mib.ipdscp_in_statistics); }
Signature · 1 line
1.6.3.3
From 6ee7c2ef1260fd9b700893aa05c3d2a770d65e45 Mon Sep 17 00:00:00 2001
From: Torsten Schmidt <[email protected]>
Date: Tue, 5 Jan 2010 09:34:51 +0100
Subject: [PATCH 2/3] ipv4: add DSCP OUT statistic
--- include/net/ipdscp.h | 31 +++++++++++++++++++++++++++++++ include/net/netns/mib.h | 1 + net/ipv4/ip_output.c | 5 +++++ net/ipv4/ipdscp.c | 21 ++++++++++++++++----- 4 files changed, 53 insertions(+), 5 deletions(-)
include/net/ipdscp.h +31 -0
@@ -38,10 +38,13 @@#define IP_DSCP_AF43 (0x26)#define IP_DSCP_EF (0x2E) +#ifdef CONFIG_IP_DSCP_STAT #define IP_DSCPIN_INC_STATS_BH (net, field) SNMP_INC_STATS_BH((net)->mib.ipdscp_in_statistics, field) +#define IP_DSCPOUT_INC_STATS (net, field) SNMP_INC_STATS((net)->mib.ipdscp_out_statistics, field)#else #define IP_DSCPIN_INC_STATS_BH (net, field) ((void)(net)) +#define IP_DSCPOUT_INC_STATS (net, field) ((void)(net))#endif
@@ -76,4 +79,32 @@ static inline void ipv4_dscp_stat_in(struct net *net, __u8 dsfield) } } + +static inline void ipv4_dscp_stat_out (struct net *net,__u8 dsfield) +{ +switch (dsfield >>2 ) { +case IP_DSCP_CS0 :IP_DSCPOUT_INC_STATS (net,LINUX_MIB_IPDSCP_CS0 );break ; +case IP_DSCP_EF :IP_DSCPOUT_INC_STATS (net,LINUX_MIB_IPDSCP_EF );break ; +case IP_DSCP_CS1 :IP_DSCPOUT_INC_STATS (net,LINUX_MIB_IPDSCP_CS1 );break ; +case IP_DSCP_CS2 :IP_DSCPOUT_INC_STATS (net,LINUX_MIB_IPDSCP_CS2 );break ; +case IP_DSCP_CS3 :IP_DSCPOUT_INC_STATS (net,LINUX_MIB_IPDSCP_CS3 );break ; +case IP_DSCP_CS4 :IP_DSCPOUT_INC_STATS (net,LINUX_MIB_IPDSCP_CS4 );break ; +case IP_DSCP_CS5 :IP_DSCPOUT_INC_STATS (net,LINUX_MIB_IPDSCP_CS5 );break ; +case IP_DSCP_CS6 :IP_DSCPOUT_INC_STATS (net,LINUX_MIB_IPDSCP_CS6 );break ; +case IP_DSCP_CS7 :IP_DSCPOUT_INC_STATS (net,LINUX_MIB_IPDSCP_CS7 );break ; +case IP_DSCP_AF11 :IP_DSCPOUT_INC_STATS (net,LINUX_MIB_IPDSCP_AF11 );break ; +case IP_DSCP_AF12 :IP_DSCPOUT_INC_STATS (net,LINUX_MIB_IPDSCP_AF12 );break ; +case IP_DSCP_AF13 :IP_DSCPOUT_INC_STATS (net,LINUX_MIB_IPDSCP_AF13 );break ; +case IP_DSCP_AF21 :IP_DSCPOUT_INC_STATS (net,LINUX_MIB_IPDSCP_AF21 );break ; +case IP_DSCP_AF22 :IP_DSCPOUT_INC_STATS (net,LINUX_MIB_IPDSCP_AF22 );break ; +case IP_DSCP_AF23 :IP_DSCPOUT_INC_STATS (net,LINUX_MIB_IPDSCP_AF23 );break ; +case IP_DSCP_AF31 :IP_DSCPOUT_INC_STATS (net,LINUX_MIB_IPDSCP_AF31 );break ; +case IP_DSCP_AF32 :IP_DSCPOUT_INC_STATS (net,LINUX_MIB_IPDSCP_AF32 );break ; +case IP_DSCP_AF33 :IP_DSCPOUT_INC_STATS (net,LINUX_MIB_IPDSCP_AF33 );break ; +case IP_DSCP_AF41 :IP_DSCPOUT_INC_STATS (net,LINUX_MIB_IPDSCP_AF41 );break ; +case IP_DSCP_AF42 :IP_DSCPOUT_INC_STATS (net,LINUX_MIB_IPDSCP_AF42 );break ; +case IP_DSCP_AF43 :IP_DSCPOUT_INC_STATS (net,LINUX_MIB_IPDSCP_AF43 );break ; + } +} +#endif
include/net/netns/mib.h +1 -0
@@ -26,6 +26,7 @@ struct netns_mib {#ifdef CONFIG_IP_DSCP_STAT struct proc_dir_entry *proc_net_ipdscp; DEFINE_SNMP_STAT(struct ipdscp_mib, ipdscp_in_statistics); + DEFINE_SNMP_STAT(struct ipdscp_mib, ipdscp_out_statistics);#endif };
net/ipv4/ip_output.c +5 -0
@@ -79,6 +79,7 @@#include <linux/mroute.h> #include <linux/netlink.h> #include <linux/tcp.h> +#include <net/ipdscp.h> int sysctl_ip_default_ttl__read_mostly =IPDEFTTL ;
@@ -300,6 +301,10 @@ int ip_output(struct sk_buff *skb)IP_UPD_PO_STATS (dev_net (dev),IPSTATS_MIB_OUT , skb->len); +#ifdef CONFIG_IP_DSCP_STAT +ipv4_dscp_stat_out (dev_net (dev),ip_hdr (skb)->tos); +#endif + skb->dev = dev; skb->protocol =htons (ETH_P_IP );
net/ipv4/ipdscp.c +16 -5
@@ -46,8 +46,10 @@ static int ipdscp_statistics_seq_show(struct seq_file *seq, void *v)struct net *net = seq->private;int i;for (i=0 ; ipdscp_mib_list[i].name; i++) -seq_printf (seq,"%-24s\t%lu\n" , ipdscp_mib_list[i].name, +seq_printf (seq,"%-24s\t%lu\t%lu\n" , ipdscp_mib_list[i].name,snmp_fold_field ((void **)net->mib.ipdscp_in_statistics, + ipdscp_mib_list[i].entry), +snmp_fold_field ((void **)net->mib.ipdscp_out_statistics, ipdscp_mib_list[i].entry));return 0 ; }
@@ -89,11 +91,20 @@ int __net_init ipdscp_stat_init(struct net *net)if (snmp_mib_init ((void **)net->mib.ipdscp_in_statistics,sizeof (struct ipdscp_mib )) <0 ) -return -ENOMEM ; + goto err_ipdscp_in; +if (snmp_mib_init ((void **)net->mib.ipdscp_out_statistics, +sizeof (struct ipdscp_mib )) <0 ) + goto err_ipdscp_out; + rv =ipdscp_proc_init (net); -if (rv <0 ) -snmp_mib_free ((void **)net->mib.ipdscp_in_statistics); -return rv; +if (rv >=0 ) +return 0 ; + +err_ipdscp_out: +snmp_mib_free ((void **)net->mib.ipdscp_out_statistics); +err_ipdscp_in: +snmp_mib_free ((void **)net->mib.ipdscp_in_statistics); +return -ENOMEM ; }void ipdscp_stat_fini (struct net *net)
Signature · 1 line
1.6.3.3
From 54f9a93d6476dc47c9ca87f3350187011039adf9 Mon Sep 17 00:00:00 2001
From: Torsten Schmidt <[email protected]>
Date: Mon, 11 Jan 2010 14:49:48 +0100
Subject: [PATCH 3/3] ipv4: change DSCP proc file name
--- net/ipv4/ipdscp.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
net/ipv4/ipdscp.c +1 -1
@@ -72,7 +72,7 @@ static const struct file_operations ipdscp_statistics_seq_fops = {static int __net_init ipdscp_proc_init (struct net *net) { -if (!proc_net_fops_create (net,"ipdscp" ,S_IRUGO , +if (!proc_net_fops_create (net,"ip_dscp" ,S_IRUGO , &ipdscp_statistics_seq_fops))return -ENOMEM ;return 0 ;
Signature · 1 line
1.6.3.3
Digging some more (at least through the 2.6.27.38 source) I also find:
/* Given a data frame determine the 802.1p/1d tag to use. */ static unsigned int classify_1d(struct sk_buff *skb)
{
unsigned int dscp;
/* skb->priority values from 256->263 are magic values to
* directly indicate a specific 802.1d priority. This is used
* to allow 802.1d priority to be passed directly in from VLAN
* tags, etc.
*/
if (skb->priority >= 256 && skb->priority <= 263)
return skb->priority - 256;
switch (skb->protocol) {
case __constant_htons(ETH_P_IP):
dscp = ip_hdr(skb)->tos & 0xfc;
break;
default:
return 0;
}
if (dscp & 0x1c)
return 0;
return dscp >> 5;
}in net/mac80211/wme.c
This won't work with DSCP values because they do set bits 0x10 and 0x80. In fact... looking at netinet/ip.h:
/*
* Definitions for IP type of service (ip_tos)
*/
#define IPTOS_TOS_MASK 0x1E #define IPTOS_TOS(tos) ((tos) & IPTOS_TOS_MASK) #define IPTOS_LOWDELAY 0x10 #define IPTOS_THROUGHPUT 0x08 #define IPTOS_RELIABILITY 0x04 #define IPTOS_LOWCOST 0x02 #define IPTOS_MINCOST IPTOS_LOWCOST
I'm not even sure why the IPTOS_LOWCOST bit is left out of the check...
-Philip
Quoted 80 lines · Philip A. Prindeville
[ Posted to linux-net a couple of days ago and didn't hear back... so reposting here since this might be more appropriate. ]
I'm looking at
net/ipv4/ip_sockglue.c:512 case IP_TOS: /* This sets both TOS and Precedence */ 513 if (sk->sk_type == SOCK_STREAM) { 514 val &= ~3; 515 val |= inet->tos & 3; 516 } 517 if (inet->tos != val) { 518 inet->tos = val; 519 sk->sk_priority = rt_tos2priority(val); 520 sk_dst_reset(sk); 521 } 522 break;and
include/net/route.h:141 extern const __u8 ip_tos2prio[16]; 142 143 static inline char rt_tos2priority(u8 tos) 144 { 145 return ip_tos2prio[IPTOS_TOS(tos)>>1]; 146 }and finally
net/ipv4/route.c:165 #define ECN_OR_COST(class) TC_PRIO_##class 166 167 const __u8 ip_tos2prio[16] = { 168 TC_PRIO_BESTEFFORT, 169 ECN_OR_COST(FILLER), 170 TC_PRIO_BESTEFFORT, 171 ECN_OR_COST(BESTEFFORT), 172 TC_PRIO_BULK, 173 ECN_OR_COST(BULK), 174 TC_PRIO_BULK, 175 ECN_OR_COST(BULK), 176 TC_PRIO_INTERACTIVE, 177 ECN_OR_COST(INTERACTIVE), 178 TC_PRIO_INTERACTIVE, 179 ECN_OR_COST(INTERACTIVE), 180 TC_PRIO_INTERACTIVE_BULK, 181 ECN_OR_COST(INTERACTIVE_BULK), 182 TC_PRIO_INTERACTIVE_BULK, 183 ECN_OR_COST(INTERACTIVE_BULK) 184 };and it's slowly dawning on me that we're using an interpretation of the
IP_TOS(and ip.ip_tos field) values that have been deprecated since 1998! Quoting RFC 2474:3. Differentiated Services Field Definition
A replacement header field, called the DS field, is defined, which is intended to supersede the existing definitions of the IPv4 TOS octet [RFC791] and the IPv6 Traffic Class octet [IPv6].
Seems pretty clear, right? That DSCP is the new testament, here to replace the old testament... although if you look closely, the precedence values of
IPTOS_PREC_ROUTINElooks a lot likeIPTOS_CLASS_CS0, etc... so some backward compatibility was maintained. (See http://sourceware.org/bugzilla/show_bug.cgi?id=11027 and http://sourceware.org/bugzilla/show_bug.cgi?id=10789 if your glibc doesn't yet include the theIPTOS_CLASS_CSnandIPTOS_DSCP_AFxxvalues).And indeed, only routers seem to pay attention to bits in the
0x1cspace... I.e. between the upper 3 bits which still mean precedence, and the lower 2 bits which now signify experienced-congestion-notification (ECN).Assuming that whatever the local host does to the output of the packet, that it's not going to sufficiently delay the packet enough because we're connected to some fast media (Fast ethernet, etc) then what we do locally shouldn't matter... unless of course we're using 802.1p tagging, in which case we can seriously mess up what happens next.
So how is it that no one noticed this issue yet, and given that Linux is used in a fair number of commercial embedded real-time boxes (like satellite and IPTV set-top boxes)... how are they not impacted by this?
Assuming my crusade to get various common apps and services (wget, TB, FF, Sendmail, Cyrus, ProFTPd, etc) to use DSCP/CS marking (very few apps currently use DSCP or precedence marking), then kernels with the proper default behavior will need to start shipping, right? I.e. out-of-the-box kernels should handle such apps without further configuration, such as needing to have the DSCP iptables module installed. They should "just work".
Thanks,
-Philip
--
To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html