Skip to content

Commit 768cf84

Browse files
oleremdavem330
authored andcommitted
net: add IEEE 802.1q specific helpers
IEEE 802.1q specification provides recommendation and examples which can be used as good default values for different drivers. This patch implements mapping examples documented in IEEE 802.1Q-2022 in Annex I "I.3 Traffic type to traffic class mapping" and IETF DSCP naming and mapping DSCP to Traffic Type inspired by RFC8325. This helpers will be used in followup patches for dsa/microchip DCB implementation. Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 97278f8 commit 768cf84

File tree

5 files changed

+379
-0
lines changed

5 files changed

+379
-0
lines changed

include/net/dscp.h

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/* Copyright (c) 2024 Pengutronix, Oleksij Rempel <kernel@pengutronix.de> */
3+
4+
#ifndef __DSCP_H__
5+
#define __DSCP_H__
6+
7+
/*
8+
* DSCP Pools and Codepoint Space Division:
9+
*
10+
* The Differentiated Services (Diffserv) architecture defines a method for
11+
* classifying and managing network traffic using the DS field in IPv4 and IPv6
12+
* packet headers. This field can carry one of 64 distinct DSCP (Differentiated
13+
* Services Code Point) values, which are divided into three pools based on
14+
* their Least Significant Bits (LSB) patterns and intended usage. Each pool has
15+
* a specific registration procedure for assigning DSCP values:
16+
*
17+
* Pool 1 (Standards Action Pool):
18+
* - Codepoint Space: xxxxx0
19+
* This pool includes DSCP values ending in '0' (binary), allocated via
20+
* Standards Action. It is intended for globally recognized traffic classes,
21+
* ensuring interoperability across the internet. This pool encompasses
22+
* well-known DSCP values such as CS0-CS7, AFxx, EF, and VOICE-ADMIT.
23+
*
24+
* Pool 2 (Experimental/Local Use Pool):
25+
* - Codepoint Space: xxxx11
26+
* Reserved for DSCP values ending in '11' (binary), this pool is designated
27+
* for Experimental or Local Use. It allows for private or temporary traffic
28+
* marking schemes not intended for standardized global use, facilitating
29+
* testing and network-specific configurations without impacting
30+
* interoperability.
31+
*
32+
* Pool 3 (Preferential Standardization Pool):
33+
* - Codepoint Space: xxxx01
34+
* Initially reserved for experimental or local use, this pool now serves as
35+
* a secondary standardization resource should Pool 1 become exhausted. DSCP
36+
* values ending in '01' (binary) are assigned via Standards Action, with a
37+
* focus on adopting new, standardized traffic classes as the need arises.
38+
*
39+
* For pool updates see:
40+
* https://www.iana.org/assignments/dscp-registry/dscp-registry.xhtml
41+
*/
42+
43+
/* Pool 1: Standardized DSCP values as per [RFC8126] */
44+
#define DSCP_CS0 0 /* 000000, [RFC2474] */
45+
/* CS0 is some times called default (DF) */
46+
#define DSCP_DF 0 /* 000000, [RFC2474] */
47+
#define DSCP_CS1 8 /* 001000, [RFC2474] */
48+
#define DSCP_CS2 16 /* 010000, [RFC2474] */
49+
#define DSCP_CS3 24 /* 011000, [RFC2474] */
50+
#define DSCP_CS4 32 /* 100000, [RFC2474] */
51+
#define DSCP_CS5 40 /* 101000, [RFC2474] */
52+
#define DSCP_CS6 48 /* 110000, [RFC2474] */
53+
#define DSCP_CS7 56 /* 111000, [RFC2474] */
54+
#define DSCP_AF11 10 /* 001010, [RFC2597] */
55+
#define DSCP_AF12 12 /* 001100, [RFC2597] */
56+
#define DSCP_AF13 14 /* 001110, [RFC2597] */
57+
#define DSCP_AF21 18 /* 010010, [RFC2597] */
58+
#define DSCP_AF22 20 /* 010100, [RFC2597] */
59+
#define DSCP_AF23 22 /* 010110, [RFC2597] */
60+
#define DSCP_AF31 26 /* 011010, [RFC2597] */
61+
#define DSCP_AF32 28 /* 011100, [RFC2597] */
62+
#define DSCP_AF33 30 /* 011110, [RFC2597] */
63+
#define DSCP_AF41 34 /* 100010, [RFC2597] */
64+
#define DSCP_AF42 36 /* 100100, [RFC2597] */
65+
#define DSCP_AF43 38 /* 100110, [RFC2597] */
66+
#define DSCP_EF 46 /* 101110, [RFC3246] */
67+
#define DSCP_VOICE_ADMIT 44 /* 101100, [RFC5865] */
68+
69+
/* Pool 3: Standardized assignments, previously available for experimental/local
70+
* use
71+
*/
72+
#define DSCP_LE 1 /* 000001, [RFC8622] */
73+
74+
#define DSCP_MAX 64
75+
76+
#endif /* __DSCP_H__ */

include/net/ieee8021q.h

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/* Copyright (c) 2024 Pengutronix, Oleksij Rempel <kernel@pengutronix.de> */
3+
4+
#ifndef _NET_IEEE8021Q_H
5+
#define _NET_IEEE8021Q_H
6+
7+
#include <linux/errno.h>
8+
9+
/**
10+
* enum ieee8021q_traffic_type - 802.1Q traffic type priority values (802.1Q-2022)
11+
*
12+
* @IEEE8021Q_TT_BK: Background
13+
* @IEEE8021Q_TT_BE: Best Effort (default). According to 802.1Q-2022, BE is 0
14+
* but has higher priority than BK which is 1.
15+
* @IEEE8021Q_TT_EE: Excellent Effort
16+
* @IEEE8021Q_TT_CA: Critical Applications
17+
* @IEEE8021Q_TT_VI: Video, < 100 ms latency and jitter
18+
* @IEEE8021Q_TT_VO: Voice, < 10 ms latency and jitter
19+
* @IEEE8021Q_TT_IC: Internetwork Control
20+
* @IEEE8021Q_TT_NC: Network Control
21+
*/
22+
enum ieee8021q_traffic_type {
23+
IEEE8021Q_TT_BK = 0,
24+
IEEE8021Q_TT_BE = 1,
25+
IEEE8021Q_TT_EE = 2,
26+
IEEE8021Q_TT_CA = 3,
27+
IEEE8021Q_TT_VI = 4,
28+
IEEE8021Q_TT_VO = 5,
29+
IEEE8021Q_TT_IC = 6,
30+
IEEE8021Q_TT_NC = 7,
31+
32+
/* private: */
33+
IEEE8021Q_TT_MAX,
34+
};
35+
36+
#define SIMPLE_IETF_DSCP_TO_IEEE8021Q_TT(dscp) ((dscp >> 3) & 0x7)
37+
38+
#if IS_ENABLED(CONFIG_NET_IEEE8021Q_HELPERS)
39+
40+
int ietf_dscp_to_ieee8021q_tt(u8 dscp);
41+
int ieee8021q_tt_to_tc(enum ieee8021q_traffic_type tt, unsigned int num_queues);
42+
43+
#else
44+
45+
static inline int ietf_dscp_to_ieee8021q_tt(u8 dscp)
46+
{
47+
return -EOPNOTSUPP;
48+
}
49+
50+
static inline int ieee8021q_tt_to_tc(enum ieee8021q_traffic_type tt,
51+
unsigned int num_queues)
52+
{
53+
return -EOPNOTSUPP;
54+
}
55+
56+
#endif
57+
#endif /* _NET_IEEE8021Q_H */

net/Kconfig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,9 @@ config GRO_CELLS
452452
config SOCK_VALIDATE_XMIT
453453
bool
454454

455+
config NET_IEEE8021Q_HELPERS
456+
bool
457+
455458
config NET_SELFTESTS
456459
def_tristate PHYLIB
457460
depends on PHYLIB && INET

net/core/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ obj-$(CONFIG_NETPOLL) += netpoll.o
2626
obj-$(CONFIG_FIB_RULES) += fib_rules.o
2727
obj-$(CONFIG_TRACEPOINTS) += net-traces.o
2828
obj-$(CONFIG_NET_DROP_MONITOR) += drop_monitor.o
29+
obj-$(CONFIG_NET_IEEE8021Q_HELPERS) += ieee8021q_helpers.o
2930
obj-$(CONFIG_NET_SELFTESTS) += selftests.o
3031
obj-$(CONFIG_NETWORK_PHY_TIMESTAMPING) += timestamping.o
3132
obj-$(CONFIG_NET_PTP_CLASSIFY) += ptp_classifier.o

net/core/ieee8021q_helpers.c

Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
// Copyright (c) 2024 Pengutronix, Oleksij Rempel <kernel@pengutronix.de>
3+
4+
#include <linux/array_size.h>
5+
#include <linux/printk.h>
6+
#include <linux/types.h>
7+
#include <net/dscp.h>
8+
#include <net/ieee8021q.h>
9+
10+
/* The following arrays map Traffic Types (TT) to traffic classes (TC) for
11+
* different number of queues as shown in the example provided by
12+
* IEEE 802.1Q-2022 in Annex I "I.3 Traffic type to traffic class mapping" and
13+
* Table I-1 "Traffic type to traffic class mapping".
14+
*/
15+
static const u8 ieee8021q_8queue_tt_tc_map[] = {
16+
[IEEE8021Q_TT_BK] = 0,
17+
[IEEE8021Q_TT_BE] = 1,
18+
[IEEE8021Q_TT_EE] = 2,
19+
[IEEE8021Q_TT_CA] = 3,
20+
[IEEE8021Q_TT_VI] = 4,
21+
[IEEE8021Q_TT_VO] = 5,
22+
[IEEE8021Q_TT_IC] = 6,
23+
[IEEE8021Q_TT_NC] = 7,
24+
};
25+
26+
static const u8 ieee8021q_7queue_tt_tc_map[] = {
27+
[IEEE8021Q_TT_BK] = 0,
28+
[IEEE8021Q_TT_BE] = 1,
29+
[IEEE8021Q_TT_EE] = 2,
30+
[IEEE8021Q_TT_CA] = 3,
31+
[IEEE8021Q_TT_VI] = 4, [IEEE8021Q_TT_VO] = 4,
32+
[IEEE8021Q_TT_IC] = 5,
33+
[IEEE8021Q_TT_NC] = 6,
34+
};
35+
36+
static const u8 ieee8021q_6queue_tt_tc_map[] = {
37+
[IEEE8021Q_TT_BK] = 0,
38+
[IEEE8021Q_TT_BE] = 1,
39+
[IEEE8021Q_TT_EE] = 2, [IEEE8021Q_TT_CA] = 2,
40+
[IEEE8021Q_TT_VI] = 3, [IEEE8021Q_TT_VO] = 3,
41+
[IEEE8021Q_TT_IC] = 4,
42+
[IEEE8021Q_TT_NC] = 5,
43+
};
44+
45+
static const u8 ieee8021q_5queue_tt_tc_map[] = {
46+
[IEEE8021Q_TT_BK] = 0, [IEEE8021Q_TT_BE] = 0,
47+
[IEEE8021Q_TT_EE] = 1, [IEEE8021Q_TT_CA] = 1,
48+
[IEEE8021Q_TT_VI] = 2, [IEEE8021Q_TT_VO] = 2,
49+
[IEEE8021Q_TT_IC] = 3,
50+
[IEEE8021Q_TT_NC] = 4,
51+
};
52+
53+
static const u8 ieee8021q_4queue_tt_tc_map[] = {
54+
[IEEE8021Q_TT_BK] = 0, [IEEE8021Q_TT_BE] = 0,
55+
[IEEE8021Q_TT_EE] = 1, [IEEE8021Q_TT_CA] = 1,
56+
[IEEE8021Q_TT_VI] = 2, [IEEE8021Q_TT_VO] = 2,
57+
[IEEE8021Q_TT_IC] = 3, [IEEE8021Q_TT_NC] = 3,
58+
};
59+
60+
static const u8 ieee8021q_3queue_tt_tc_map[] = {
61+
[IEEE8021Q_TT_BK] = 0, [IEEE8021Q_TT_BE] = 0,
62+
[IEEE8021Q_TT_EE] = 0, [IEEE8021Q_TT_CA] = 0,
63+
[IEEE8021Q_TT_VI] = 1, [IEEE8021Q_TT_VO] = 1,
64+
[IEEE8021Q_TT_IC] = 2, [IEEE8021Q_TT_NC] = 2,
65+
};
66+
67+
static const u8 ieee8021q_2queue_tt_tc_map[] = {
68+
[IEEE8021Q_TT_BK] = 0, [IEEE8021Q_TT_BE] = 0,
69+
[IEEE8021Q_TT_EE] = 0, [IEEE8021Q_TT_CA] = 0,
70+
[IEEE8021Q_TT_VI] = 1, [IEEE8021Q_TT_VO] = 1,
71+
[IEEE8021Q_TT_IC] = 1, [IEEE8021Q_TT_NC] = 1,
72+
};
73+
74+
static const u8 ieee8021q_1queue_tt_tc_map[] = {
75+
[IEEE8021Q_TT_BK] = 0, [IEEE8021Q_TT_BE] = 0,
76+
[IEEE8021Q_TT_EE] = 0, [IEEE8021Q_TT_CA] = 0,
77+
[IEEE8021Q_TT_VI] = 0, [IEEE8021Q_TT_VO] = 0,
78+
[IEEE8021Q_TT_IC] = 0, [IEEE8021Q_TT_NC] = 0,
79+
};
80+
81+
/**
82+
* ieee8021q_tt_to_tc - Map IEEE 802.1Q Traffic Type to Traffic Class
83+
* @tt: IEEE 802.1Q Traffic Type
84+
* @num_queues: Number of queues
85+
*
86+
* This function maps an IEEE 802.1Q Traffic Type to a Traffic Class (TC) based
87+
* on the number of queues configured on the NIC. The mapping is based on the
88+
* example provided by IEEE 802.1Q-2022 in Annex I "I.3 Traffic type to traffic
89+
* class mapping" and Table I-1 "Traffic type to traffic class mapping".
90+
*
91+
* Return: Traffic Class corresponding to the given Traffic Type or negative
92+
* value in case of error.
93+
*/
94+
int ieee8021q_tt_to_tc(enum ieee8021q_traffic_type tt, unsigned int num_queues)
95+
{
96+
if (tt < 0 || tt >= IEEE8021Q_TT_MAX) {
97+
pr_err("Requested Traffic Type (%d) is out of range (%d)\n", tt,
98+
IEEE8021Q_TT_MAX);
99+
return -EINVAL;
100+
}
101+
102+
switch (num_queues) {
103+
case 8:
104+
compiletime_assert(ARRAY_SIZE(ieee8021q_8queue_tt_tc_map) !=
105+
IEEE8021Q_TT_MAX - 1,
106+
"ieee8021q_8queue_tt_tc_map != max - 1");
107+
return ieee8021q_8queue_tt_tc_map[tt];
108+
case 7:
109+
compiletime_assert(ARRAY_SIZE(ieee8021q_7queue_tt_tc_map) !=
110+
IEEE8021Q_TT_MAX - 1,
111+
"ieee8021q_7queue_tt_tc_map != max - 1");
112+
113+
return ieee8021q_7queue_tt_tc_map[tt];
114+
case 6:
115+
compiletime_assert(ARRAY_SIZE(ieee8021q_6queue_tt_tc_map) !=
116+
IEEE8021Q_TT_MAX - 1,
117+
"ieee8021q_6queue_tt_tc_map != max - 1");
118+
119+
return ieee8021q_6queue_tt_tc_map[tt];
120+
case 5:
121+
compiletime_assert(ARRAY_SIZE(ieee8021q_5queue_tt_tc_map) !=
122+
IEEE8021Q_TT_MAX - 1,
123+
"ieee8021q_5queue_tt_tc_map != max - 1");
124+
125+
return ieee8021q_5queue_tt_tc_map[tt];
126+
case 4:
127+
compiletime_assert(ARRAY_SIZE(ieee8021q_4queue_tt_tc_map) !=
128+
IEEE8021Q_TT_MAX - 1,
129+
"ieee8021q_4queue_tt_tc_map != max - 1");
130+
131+
return ieee8021q_4queue_tt_tc_map[tt];
132+
case 3:
133+
compiletime_assert(ARRAY_SIZE(ieee8021q_3queue_tt_tc_map) !=
134+
IEEE8021Q_TT_MAX - 1,
135+
"ieee8021q_3queue_tt_tc_map != max - 1");
136+
137+
return ieee8021q_3queue_tt_tc_map[tt];
138+
case 2:
139+
compiletime_assert(ARRAY_SIZE(ieee8021q_2queue_tt_tc_map) !=
140+
IEEE8021Q_TT_MAX - 1,
141+
"ieee8021q_2queue_tt_tc_map != max - 1");
142+
143+
return ieee8021q_2queue_tt_tc_map[tt];
144+
case 1:
145+
compiletime_assert(ARRAY_SIZE(ieee8021q_1queue_tt_tc_map) !=
146+
IEEE8021Q_TT_MAX - 1,
147+
"ieee8021q_1queue_tt_tc_map != max - 1");
148+
149+
return ieee8021q_1queue_tt_tc_map[tt];
150+
}
151+
152+
pr_err("Invalid number of queues %d\n", num_queues);
153+
154+
return -EINVAL;
155+
}
156+
EXPORT_SYMBOL_GPL(ieee8021q_tt_to_tc);
157+
158+
/**
159+
* ietf_dscp_to_ieee8021q_tt - Map IETF DSCP to IEEE 802.1Q Traffic Type
160+
* @dscp: IETF DSCP value
161+
*
162+
* This function maps an IETF DSCP value to an IEEE 802.1Q Traffic Type (TT).
163+
* Since there is no corresponding mapping between DSCP and IEEE 802.1Q Traffic
164+
* Type, this function is inspired by the RFC8325 documentation which describe
165+
* the mapping between DSCP and 802.11 User Priority (UP) values.
166+
*
167+
* Return: IEEE 802.1Q Traffic Type corresponding to the given DSCP value
168+
*/
169+
int ietf_dscp_to_ieee8021q_tt(u8 dscp)
170+
{
171+
switch (dscp) {
172+
case DSCP_CS0:
173+
/* Comment from RFC8325:
174+
* [RFC4594], Section 4.8, recommends High-Throughput Data be marked
175+
* AF1x (that is, AF11, AF12, and AF13, according to the rules defined
176+
* in [RFC2475]).
177+
*
178+
* By default (as described in Section 2.3), High-Throughput Data will
179+
* map to UP 1 and, thus, to the Background Access Category (AC_BK),
180+
* which is contrary to the intent expressed in [RFC4594].
181+
182+
* Unfortunately, there really is no corresponding fit for the High-
183+
* Throughput Data service class within the constrained 4 Access
184+
* Category [IEEE.802.11-2016] model. If the High-Throughput Data
185+
* service class is assigned to the Best Effort Access Category (AC_BE),
186+
* then it would contend with Low-Latency Data (while [RFC4594]
187+
* recommends a distinction in servicing between these service classes)
188+
* as well as with the default service class; alternatively, if it is
189+
* assigned to the Background Access Category (AC_BK), then it would
190+
* receive a less-then-best-effort service and contend with Low-Priority
191+
* Data (as discussed in Section 4.2.10).
192+
*
193+
* As such, since there is no directly corresponding fit for the High-
194+
* Throughout Data service class within the [IEEE.802.11-2016] model, it
195+
* is generally RECOMMENDED to map High-Throughput Data to UP 0, thereby
196+
* admitting it to the Best Effort Access Category (AC_BE).
197+
*
198+
* Note: The above text is from RFC8325 which is describing the mapping
199+
* between DSCP and 802.11 User Priority (UP) values. The mapping
200+
* between UP and IEEE 802.1Q Traffic Type is not defined in the RFC but
201+
* the 802.11 AC_BK and AC_BE are closely related to the IEEE 802.1Q
202+
* Traffic Types BE and BK.
203+
*/
204+
case DSCP_AF11:
205+
case DSCP_AF12:
206+
case DSCP_AF13:
207+
return IEEE8021Q_TT_BE;
208+
/* Comment from RFC8325:
209+
* RFC3662 and RFC4594 both recommend Low-Priority Data be marked
210+
* with DSCP CS1. The Low-Priority Data service class loosely
211+
* corresponds to the [IEEE.802.11-2016] Background Access Category
212+
*/
213+
case DSCP_CS1:
214+
return IEEE8021Q_TT_BK;
215+
case DSCP_CS2:
216+
case DSCP_AF21:
217+
case DSCP_AF22:
218+
case DSCP_AF23:
219+
return IEEE8021Q_TT_EE;
220+
case DSCP_CS3:
221+
case DSCP_AF31:
222+
case DSCP_AF32:
223+
case DSCP_AF33:
224+
return IEEE8021Q_TT_CA;
225+
case DSCP_CS4:
226+
case DSCP_AF41:
227+
case DSCP_AF42:
228+
case DSCP_AF43:
229+
return IEEE8021Q_TT_VI;
230+
case DSCP_CS5:
231+
case DSCP_EF:
232+
case DSCP_VOICE_ADMIT:
233+
return IEEE8021Q_TT_VO;
234+
case DSCP_CS6:
235+
return IEEE8021Q_TT_IC;
236+
case DSCP_CS7:
237+
return IEEE8021Q_TT_NC;
238+
}
239+
240+
return SIMPLE_IETF_DSCP_TO_IEEE8021Q_TT(dscp);
241+
}
242+
EXPORT_SYMBOL_GPL(ietf_dscp_to_ieee8021q_tt);

0 commit comments

Comments
 (0)