#include <linux/array_size.h>
#include <linux/printk.h>
#include <linux/types.h>
#include <net/dscp.h>
#include <net/ieee8021q.h>
#define TT_MAP_SIZE_OK(tbl) \
compiletime_assert(ARRAY_SIZE(tbl) == IEEE8021Q_TT_MAX, \
#tbl " size mismatch")
static const u8 ieee8021q_8queue_tt_tc_map[] = {
[IEEE8021Q_TT_BK] = 0,
[IEEE8021Q_TT_BE] = 1,
[IEEE8021Q_TT_EE] = 2,
[IEEE8021Q_TT_CA] = 3,
[IEEE8021Q_TT_VI] = 4,
[IEEE8021Q_TT_VO] = 5,
[IEEE8021Q_TT_IC] = 6,
[IEEE8021Q_TT_NC] = 7,
};
static const u8 ieee8021q_7queue_tt_tc_map[] = {
[IEEE8021Q_TT_BK] = 0,
[IEEE8021Q_TT_BE] = 1,
[IEEE8021Q_TT_EE] = 2,
[IEEE8021Q_TT_CA] = 3,
[IEEE8021Q_TT_VI] = 4, [IEEE8021Q_TT_VO] = 4,
[IEEE8021Q_TT_IC] = 5,
[IEEE8021Q_TT_NC] = 6,
};
static const u8 ieee8021q_6queue_tt_tc_map[] = {
[IEEE8021Q_TT_BK] = 0,
[IEEE8021Q_TT_BE] = 1,
[IEEE8021Q_TT_EE] = 2, [IEEE8021Q_TT_CA] = 2,
[IEEE8021Q_TT_VI] = 3, [IEEE8021Q_TT_VO] = 3,
[IEEE8021Q_TT_IC] = 4,
[IEEE8021Q_TT_NC] = 5,
};
static const u8 ieee8021q_5queue_tt_tc_map[] = {
[IEEE8021Q_TT_BK] = 0, [IEEE8021Q_TT_BE] = 0,
[IEEE8021Q_TT_EE] = 1, [IEEE8021Q_TT_CA] = 1,
[IEEE8021Q_TT_VI] = 2, [IEEE8021Q_TT_VO] = 2,
[IEEE8021Q_TT_IC] = 3,
[IEEE8021Q_TT_NC] = 4,
};
static const u8 ieee8021q_4queue_tt_tc_map[] = {
[IEEE8021Q_TT_BK] = 0, [IEEE8021Q_TT_BE] = 0,
[IEEE8021Q_TT_EE] = 1, [IEEE8021Q_TT_CA] = 1,
[IEEE8021Q_TT_VI] = 2, [IEEE8021Q_TT_VO] = 2,
[IEEE8021Q_TT_IC] = 3, [IEEE8021Q_TT_NC] = 3,
};
static const u8 ieee8021q_3queue_tt_tc_map[] = {
[IEEE8021Q_TT_BK] = 0, [IEEE8021Q_TT_BE] = 0,
[IEEE8021Q_TT_EE] = 0, [IEEE8021Q_TT_CA] = 0,
[IEEE8021Q_TT_VI] = 1, [IEEE8021Q_TT_VO] = 1,
[IEEE8021Q_TT_IC] = 2, [IEEE8021Q_TT_NC] = 2,
};
static const u8 ieee8021q_2queue_tt_tc_map[] = {
[IEEE8021Q_TT_BK] = 0, [IEEE8021Q_TT_BE] = 0,
[IEEE8021Q_TT_EE] = 0, [IEEE8021Q_TT_CA] = 0,
[IEEE8021Q_TT_VI] = 1, [IEEE8021Q_TT_VO] = 1,
[IEEE8021Q_TT_IC] = 1, [IEEE8021Q_TT_NC] = 1,
};
static const u8 ieee8021q_1queue_tt_tc_map[] = {
[IEEE8021Q_TT_BK] = 0, [IEEE8021Q_TT_BE] = 0,
[IEEE8021Q_TT_EE] = 0, [IEEE8021Q_TT_CA] = 0,
[IEEE8021Q_TT_VI] = 0, [IEEE8021Q_TT_VO] = 0,
[IEEE8021Q_TT_IC] = 0, [IEEE8021Q_TT_NC] = 0,
};
int ieee8021q_tt_to_tc(enum ieee8021q_traffic_type tt, unsigned int num_queues)
{
if (tt < 0 || tt >= IEEE8021Q_TT_MAX) {
pr_err("Requested Traffic Type (%d) is out of range (%d)\n", tt,
IEEE8021Q_TT_MAX);
return -EINVAL;
}
switch (num_queues) {
case 8:
TT_MAP_SIZE_OK(ieee8021q_8queue_tt_tc_map);
return ieee8021q_8queue_tt_tc_map[tt];
case 7:
TT_MAP_SIZE_OK(ieee8021q_7queue_tt_tc_map);
return ieee8021q_7queue_tt_tc_map[tt];
case 6:
TT_MAP_SIZE_OK(ieee8021q_6queue_tt_tc_map);
return ieee8021q_6queue_tt_tc_map[tt];
case 5:
TT_MAP_SIZE_OK(ieee8021q_5queue_tt_tc_map);
return ieee8021q_5queue_tt_tc_map[tt];
case 4:
TT_MAP_SIZE_OK(ieee8021q_4queue_tt_tc_map);
return ieee8021q_4queue_tt_tc_map[tt];
case 3:
TT_MAP_SIZE_OK(ieee8021q_3queue_tt_tc_map);
return ieee8021q_3queue_tt_tc_map[tt];
case 2:
TT_MAP_SIZE_OK(ieee8021q_2queue_tt_tc_map);
return ieee8021q_2queue_tt_tc_map[tt];
case 1:
TT_MAP_SIZE_OK(ieee8021q_1queue_tt_tc_map);
return ieee8021q_1queue_tt_tc_map[tt];
}
pr_err("Invalid number of queues %d\n", num_queues);
return -EINVAL;
}
EXPORT_SYMBOL_GPL(ieee8021q_tt_to_tc);
int ietf_dscp_to_ieee8021q_tt(u8 dscp)
{
switch (dscp) {
case DSCP_CS0:
case DSCP_AF11:
case DSCP_AF12:
case DSCP_AF13:
return IEEE8021Q_TT_BE;
case DSCP_CS1:
return IEEE8021Q_TT_BK;
case DSCP_CS2:
case DSCP_AF21:
case DSCP_AF22:
case DSCP_AF23:
return IEEE8021Q_TT_EE;
case DSCP_CS3:
case DSCP_AF31:
case DSCP_AF32:
case DSCP_AF33:
return IEEE8021Q_TT_CA;
case DSCP_CS4:
case DSCP_AF41:
case DSCP_AF42:
case DSCP_AF43:
return IEEE8021Q_TT_VI;
case DSCP_CS5:
case DSCP_EF:
case DSCP_VOICE_ADMIT:
return IEEE8021Q_TT_VO;
case DSCP_CS6:
return IEEE8021Q_TT_IC;
case DSCP_CS7:
return IEEE8021Q_TT_NC;
}
return SIMPLE_IETF_DSCP_TO_IEEE8021Q_TT(dscp);
}
EXPORT_SYMBOL_GPL(ietf_dscp_to_ieee8021q_tt);