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