xref: /linux/net/core/ieee8021q_helpers.c (revision 621cde16e49b3ecf7d59a8106a20aaebfb4a59a9)
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  */
ieee8021q_tt_to_tc(enum ieee8021q_traffic_type tt,unsigned int num_queues)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  */
ietf_dscp_to_ieee8021q_tt(u8 dscp)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);
243