// SPDX-License-Identifier: GPL-2.01// Copyright (c) 2024 Pengutronix, Oleksij Rempel <[email protected]>23#include <linux/array_size.h>4#include <linux/printk.h>5#include <linux/types.h>6#include <net/dscp.h>7#include <net/ieee8021q.h>89/* verify that table covers all 8 traffic types */10#define TT_MAP_SIZE_OK(tbl) \11compiletime_assert(ARRAY_SIZE(tbl) == IEEE8021Q_TT_MAX, \12#tbl " size mismatch")1314/* The following arrays map Traffic Types (TT) to traffic classes (TC) for15* different number of queues as shown in the example provided by16* IEEE 802.1Q-2022 in Annex I "I.3 Traffic type to traffic class mapping" and17* Table I-1 "Traffic type to traffic class mapping".18*/19static const u8 ieee8021q_8queue_tt_tc_map[] = {20[IEEE8021Q_TT_BK] = 0,21[IEEE8021Q_TT_BE] = 1,22[IEEE8021Q_TT_EE] = 2,23[IEEE8021Q_TT_CA] = 3,24[IEEE8021Q_TT_VI] = 4,25[IEEE8021Q_TT_VO] = 5,26[IEEE8021Q_TT_IC] = 6,27[IEEE8021Q_TT_NC] = 7,28};2930static const u8 ieee8021q_7queue_tt_tc_map[] = {31[IEEE8021Q_TT_BK] = 0,32[IEEE8021Q_TT_BE] = 1,33[IEEE8021Q_TT_EE] = 2,34[IEEE8021Q_TT_CA] = 3,35[IEEE8021Q_TT_VI] = 4, [IEEE8021Q_TT_VO] = 4,36[IEEE8021Q_TT_IC] = 5,37[IEEE8021Q_TT_NC] = 6,38};3940static const u8 ieee8021q_6queue_tt_tc_map[] = {41[IEEE8021Q_TT_BK] = 0,42[IEEE8021Q_TT_BE] = 1,43[IEEE8021Q_TT_EE] = 2, [IEEE8021Q_TT_CA] = 2,44[IEEE8021Q_TT_VI] = 3, [IEEE8021Q_TT_VO] = 3,45[IEEE8021Q_TT_IC] = 4,46[IEEE8021Q_TT_NC] = 5,47};4849static const u8 ieee8021q_5queue_tt_tc_map[] = {50[IEEE8021Q_TT_BK] = 0, [IEEE8021Q_TT_BE] = 0,51[IEEE8021Q_TT_EE] = 1, [IEEE8021Q_TT_CA] = 1,52[IEEE8021Q_TT_VI] = 2, [IEEE8021Q_TT_VO] = 2,53[IEEE8021Q_TT_IC] = 3,54[IEEE8021Q_TT_NC] = 4,55};5657static const u8 ieee8021q_4queue_tt_tc_map[] = {58[IEEE8021Q_TT_BK] = 0, [IEEE8021Q_TT_BE] = 0,59[IEEE8021Q_TT_EE] = 1, [IEEE8021Q_TT_CA] = 1,60[IEEE8021Q_TT_VI] = 2, [IEEE8021Q_TT_VO] = 2,61[IEEE8021Q_TT_IC] = 3, [IEEE8021Q_TT_NC] = 3,62};6364static const u8 ieee8021q_3queue_tt_tc_map[] = {65[IEEE8021Q_TT_BK] = 0, [IEEE8021Q_TT_BE] = 0,66[IEEE8021Q_TT_EE] = 0, [IEEE8021Q_TT_CA] = 0,67[IEEE8021Q_TT_VI] = 1, [IEEE8021Q_TT_VO] = 1,68[IEEE8021Q_TT_IC] = 2, [IEEE8021Q_TT_NC] = 2,69};7071static const u8 ieee8021q_2queue_tt_tc_map[] = {72[IEEE8021Q_TT_BK] = 0, [IEEE8021Q_TT_BE] = 0,73[IEEE8021Q_TT_EE] = 0, [IEEE8021Q_TT_CA] = 0,74[IEEE8021Q_TT_VI] = 1, [IEEE8021Q_TT_VO] = 1,75[IEEE8021Q_TT_IC] = 1, [IEEE8021Q_TT_NC] = 1,76};7778static const u8 ieee8021q_1queue_tt_tc_map[] = {79[IEEE8021Q_TT_BK] = 0, [IEEE8021Q_TT_BE] = 0,80[IEEE8021Q_TT_EE] = 0, [IEEE8021Q_TT_CA] = 0,81[IEEE8021Q_TT_VI] = 0, [IEEE8021Q_TT_VO] = 0,82[IEEE8021Q_TT_IC] = 0, [IEEE8021Q_TT_NC] = 0,83};8485/**86* ieee8021q_tt_to_tc - Map IEEE 802.1Q Traffic Type to Traffic Class87* @tt: IEEE 802.1Q Traffic Type88* @num_queues: Number of queues89*90* This function maps an IEEE 802.1Q Traffic Type to a Traffic Class (TC) based91* on the number of queues configured on the NIC. The mapping is based on the92* example provided by IEEE 802.1Q-2022 in Annex I "I.3 Traffic type to traffic93* class mapping" and Table I-1 "Traffic type to traffic class mapping".94*95* Return: Traffic Class corresponding to the given Traffic Type or negative96* value in case of error.97*/98int ieee8021q_tt_to_tc(enum ieee8021q_traffic_type tt, unsigned int num_queues)99{100if (tt < 0 || tt >= IEEE8021Q_TT_MAX) {101pr_err("Requested Traffic Type (%d) is out of range (%d)\n", tt,102IEEE8021Q_TT_MAX);103return -EINVAL;104}105106switch (num_queues) {107case 8:108TT_MAP_SIZE_OK(ieee8021q_8queue_tt_tc_map);109return ieee8021q_8queue_tt_tc_map[tt];110case 7:111TT_MAP_SIZE_OK(ieee8021q_7queue_tt_tc_map);112return ieee8021q_7queue_tt_tc_map[tt];113case 6:114TT_MAP_SIZE_OK(ieee8021q_6queue_tt_tc_map);115return ieee8021q_6queue_tt_tc_map[tt];116case 5:117TT_MAP_SIZE_OK(ieee8021q_5queue_tt_tc_map);118return ieee8021q_5queue_tt_tc_map[tt];119case 4:120TT_MAP_SIZE_OK(ieee8021q_4queue_tt_tc_map);121return ieee8021q_4queue_tt_tc_map[tt];122case 3:123TT_MAP_SIZE_OK(ieee8021q_3queue_tt_tc_map);124return ieee8021q_3queue_tt_tc_map[tt];125case 2:126TT_MAP_SIZE_OK(ieee8021q_2queue_tt_tc_map);127return ieee8021q_2queue_tt_tc_map[tt];128case 1:129TT_MAP_SIZE_OK(ieee8021q_1queue_tt_tc_map);130return ieee8021q_1queue_tt_tc_map[tt];131}132133pr_err("Invalid number of queues %d\n", num_queues);134135return -EINVAL;136}137EXPORT_SYMBOL_GPL(ieee8021q_tt_to_tc);138139/**140* ietf_dscp_to_ieee8021q_tt - Map IETF DSCP to IEEE 802.1Q Traffic Type141* @dscp: IETF DSCP value142*143* This function maps an IETF DSCP value to an IEEE 802.1Q Traffic Type (TT).144* Since there is no corresponding mapping between DSCP and IEEE 802.1Q Traffic145* Type, this function is inspired by the RFC8325 documentation which describe146* the mapping between DSCP and 802.11 User Priority (UP) values.147*148* Return: IEEE 802.1Q Traffic Type corresponding to the given DSCP value149*/150int ietf_dscp_to_ieee8021q_tt(u8 dscp)151{152switch (dscp) {153case DSCP_CS0:154/* Comment from RFC8325:155* [RFC4594], Section 4.8, recommends High-Throughput Data be marked156* AF1x (that is, AF11, AF12, and AF13, according to the rules defined157* in [RFC2475]).158*159* By default (as described in Section 2.3), High-Throughput Data will160* map to UP 1 and, thus, to the Background Access Category (AC_BK),161* which is contrary to the intent expressed in [RFC4594].162163* Unfortunately, there really is no corresponding fit for the High-164* Throughput Data service class within the constrained 4 Access165* Category [IEEE.802.11-2016] model. If the High-Throughput Data166* service class is assigned to the Best Effort Access Category (AC_BE),167* then it would contend with Low-Latency Data (while [RFC4594]168* recommends a distinction in servicing between these service classes)169* as well as with the default service class; alternatively, if it is170* assigned to the Background Access Category (AC_BK), then it would171* receive a less-then-best-effort service and contend with Low-Priority172* Data (as discussed in Section 4.2.10).173*174* As such, since there is no directly corresponding fit for the High-175* Throughout Data service class within the [IEEE.802.11-2016] model, it176* is generally RECOMMENDED to map High-Throughput Data to UP 0, thereby177* admitting it to the Best Effort Access Category (AC_BE).178*179* Note: The above text is from RFC8325 which is describing the mapping180* between DSCP and 802.11 User Priority (UP) values. The mapping181* between UP and IEEE 802.1Q Traffic Type is not defined in the RFC but182* the 802.11 AC_BK and AC_BE are closely related to the IEEE 802.1Q183* Traffic Types BE and BK.184*/185case DSCP_AF11:186case DSCP_AF12:187case DSCP_AF13:188return IEEE8021Q_TT_BE;189/* Comment from RFC8325:190* RFC3662 and RFC4594 both recommend Low-Priority Data be marked191* with DSCP CS1. The Low-Priority Data service class loosely192* corresponds to the [IEEE.802.11-2016] Background Access Category193*/194case DSCP_CS1:195return IEEE8021Q_TT_BK;196case DSCP_CS2:197case DSCP_AF21:198case DSCP_AF22:199case DSCP_AF23:200return IEEE8021Q_TT_EE;201case DSCP_CS3:202case DSCP_AF31:203case DSCP_AF32:204case DSCP_AF33:205return IEEE8021Q_TT_CA;206case DSCP_CS4:207case DSCP_AF41:208case DSCP_AF42:209case DSCP_AF43:210return IEEE8021Q_TT_VI;211case DSCP_CS5:212case DSCP_EF:213case DSCP_VOICE_ADMIT:214return IEEE8021Q_TT_VO;215case DSCP_CS6:216return IEEE8021Q_TT_IC;217case DSCP_CS7:218return IEEE8021Q_TT_NC;219}220221return SIMPLE_IETF_DSCP_TO_IEEE8021Q_TT(dscp);222}223EXPORT_SYMBOL_GPL(ietf_dscp_to_ieee8021q_tt);224225226