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); 243
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.