Skip to content

Commit

Permalink
Support for tc-dot1p and tc-dscp qosmap (sonic-net#2559)
Browse files Browse the repository at this point in the history
* Support for tc-dot1p and tc-dscp qosmap
  • Loading branch information
dmukun committed Feb 20, 2023
1 parent 35385ad commit f66abed
Show file tree
Hide file tree
Showing 4 changed files with 258 additions and 4 deletions.
1 change: 1 addition & 0 deletions orchagent/orchdaemon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ bool OrchDaemon::init()
CFG_PFC_PRIORITY_TO_QUEUE_MAP_TABLE_NAME,
CFG_DSCP_TO_FC_MAP_TABLE_NAME,
CFG_EXP_TO_FC_MAP_TABLE_NAME,
CFG_TC_TO_DOT1P_MAP_TABLE_NAME,
CFG_TC_TO_DSCP_MAP_TABLE_NAME
};
gQosOrch = new QosOrch(m_configDb, qos_tables);
Expand Down
68 changes: 64 additions & 4 deletions orchagent/qosorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ map<string, sai_port_attr_t> qos_to_attr_map = {
{mpls_tc_to_tc_field_name, SAI_PORT_ATTR_QOS_MPLS_EXP_TO_TC_MAP},
{dot1p_to_tc_field_name, SAI_PORT_ATTR_QOS_DOT1P_TO_TC_MAP},
{tc_to_queue_field_name, SAI_PORT_ATTR_QOS_TC_TO_QUEUE_MAP},
{tc_to_dot1p_field_name, SAI_PORT_ATTR_QOS_TC_AND_COLOR_TO_DOT1P_MAP},
{tc_to_dscp_field_name, SAI_PORT_ATTR_QOS_TC_AND_COLOR_TO_DSCP_MAP},
{tc_to_pg_map_field_name, SAI_PORT_ATTR_QOS_TC_TO_PRIORITY_GROUP_MAP},
{pfc_to_pg_map_name, SAI_PORT_ATTR_QOS_PFC_PRIORITY_TO_PRIORITY_GROUP_MAP},
{pfc_to_queue_map_name, SAI_PORT_ATTR_QOS_PFC_PRIORITY_TO_QUEUE_MAP},
Expand Down Expand Up @@ -85,6 +87,7 @@ type_map QosOrch::m_qos_maps = {
{CFG_PFC_PRIORITY_TO_QUEUE_MAP_TABLE_NAME, new object_reference_map()},
{CFG_DSCP_TO_FC_MAP_TABLE_NAME, new object_reference_map()},
{CFG_EXP_TO_FC_MAP_TABLE_NAME, new object_reference_map()},
{CFG_TC_TO_DOT1P_MAP_TABLE_NAME, new object_reference_map()},
{CFG_TC_TO_DSCP_MAP_TABLE_NAME, new object_reference_map()},
{APP_TUNNEL_DECAP_TABLE_NAME, new object_reference_map()}
};
Expand All @@ -94,6 +97,8 @@ map<string, string> qos_to_ref_table_map = {
{mpls_tc_to_tc_field_name, CFG_MPLS_TC_TO_TC_MAP_TABLE_NAME},
{dot1p_to_tc_field_name, CFG_DOT1P_TO_TC_MAP_TABLE_NAME},
{tc_to_queue_field_name, CFG_TC_TO_QUEUE_MAP_TABLE_NAME},
{tc_to_dot1p_field_name, CFG_TC_TO_DOT1P_MAP_TABLE_NAME},
{tc_to_dscp_field_name, CFG_TC_TO_DSCP_MAP_TABLE_NAME},
{tc_to_pg_map_field_name, CFG_TC_TO_PRIORITY_GROUP_MAP_TABLE_NAME},
{pfc_to_pg_map_name, CFG_PFC_PRIORITY_TO_PRIORITY_GROUP_MAP_TABLE_NAME},
{pfc_to_queue_map_name, CFG_PFC_PRIORITY_TO_QUEUE_MAP_TABLE_NAME},
Expand Down Expand Up @@ -178,7 +183,7 @@ task_process_status QosMapHandler::processWorkItem(Consumer& consumer, KeyOpFiel
}
if (!removeQosItem(sai_object))
{
SWSS_LOG_ERROR("Failed to remove dscp_to_tc map. db name:%s sai object:%" PRIx64, qos_object_name.c_str(), sai_object);
SWSS_LOG_ERROR("Failed to remove QoS map. db name:%s sai object:%" PRIx64, qos_object_name.c_str(), sai_object);
return task_process_status::task_failed;
}
auto it_to_delete = (QosOrch::getTypeMap()[qos_map_type_name])->find(qos_object_name);
Expand Down Expand Up @@ -470,6 +475,60 @@ task_process_status QosOrch::handleTcToQueueTable(Consumer& consumer, KeyOpField
return tc_queue_handler.processWorkItem(consumer, tuple);
}

//Functions for TC-to-DOT1P qos map handling
bool TcToDot1pMapHandler::convertFieldValuesToAttributes(KeyOpFieldsValuesTuple &tuple, vector<sai_attribute_t> &attributes)
{
SWSS_LOG_ENTER();
sai_attribute_t list_attr;
sai_qos_map_list_t tc_map_list;
tc_map_list.count = (uint32_t)kfvFieldsValues(tuple).size();
tc_map_list.list = new sai_qos_map_t[tc_map_list.count]();
uint32_t ind = 0;
for (auto i = kfvFieldsValues(tuple).begin(); i != kfvFieldsValues(tuple).end(); i++, ind++)
{
tc_map_list.list[ind].key.tc = (uint8_t)stoi(fvField(*i));
tc_map_list.list[ind].value.dot1p = (uint8_t)stoi(fvValue(*i));
}
list_attr.id = SAI_QOS_MAP_ATTR_MAP_TO_VALUE_LIST;
list_attr.value.qosmap.count = tc_map_list.count;
list_attr.value.qosmap.list = tc_map_list.list;
attributes.push_back(list_attr);
return true;
}

sai_object_id_t TcToDot1pMapHandler::addQosItem(const vector<sai_attribute_t> &attributes)
{
SWSS_LOG_ENTER();
sai_status_t sai_status;
sai_object_id_t sai_object;
vector<sai_attribute_t> qos_map_attrs;
sai_attribute_t qos_map_attr;

qos_map_attr.id = SAI_QOS_MAP_ATTR_TYPE;
qos_map_attr.value.s32 = SAI_QOS_MAP_TYPE_TC_AND_COLOR_TO_DOT1P;
qos_map_attrs.push_back(qos_map_attr);

qos_map_attr.id = SAI_QOS_MAP_ATTR_MAP_TO_VALUE_LIST;
qos_map_attr.value.qosmap.count = attributes[0].value.qosmap.count;
qos_map_attr.value.qosmap.list = attributes[0].value.qosmap.list;
qos_map_attrs.push_back(qos_map_attr);

sai_status = sai_qos_map_api->create_qos_map(&sai_object, gSwitchId, (uint32_t)qos_map_attrs.size(), qos_map_attrs.data());
if (SAI_STATUS_SUCCESS != sai_status)
{
SWSS_LOG_ERROR("Failed to create tc_to_dot1p qos map. status:%d", sai_status);
return SAI_NULL_OBJECT_ID;
}
return sai_object;
}

task_process_status QosOrch::handleTcToDot1pTable(Consumer& consumer, KeyOpFieldsValuesTuple &tuple)
{
SWSS_LOG_ENTER();
TcToDot1pMapHandler tc_dot1p_handler;
return tc_dot1p_handler.processWorkItem(consumer, tuple);
}

void WredMapHandler::freeAttribResources(vector<sai_attribute_t> &attributes)
{
SWSS_LOG_ENTER();
Expand Down Expand Up @@ -857,7 +916,7 @@ sai_object_id_t TcToPgHandler::addQosItem(const vector<sai_attribute_t> &attribu
sai_status = sai_qos_map_api->create_qos_map(&sai_object, gSwitchId, (uint32_t)qos_map_attrs.size(), qos_map_attrs.data());
if (SAI_STATUS_SUCCESS != sai_status)
{
SWSS_LOG_ERROR("Failed to create tc_to_queue map. status:%d", sai_status);
SWSS_LOG_ERROR("Failed to create tc_to_pg map. status:%d", sai_status);
return SAI_NULL_OBJECT_ID;
}
return sai_object;
Expand Down Expand Up @@ -911,7 +970,7 @@ sai_object_id_t PfcPrioToPgHandler::addQosItem(const vector<sai_attribute_t> &at
sai_status = sai_qos_map_api->create_qos_map(&sai_object, gSwitchId, (uint32_t)qos_map_attrs.size(), qos_map_attrs.data());
if (SAI_STATUS_SUCCESS != sai_status)
{
SWSS_LOG_ERROR("Failed to create tc_to_queue map. status:%d", sai_status);
SWSS_LOG_ERROR("Failed to create pfc_priority_to_queue map. status:%d", sai_status);
return SAI_NULL_OBJECT_ID;
}
return sai_object;
Expand Down Expand Up @@ -966,7 +1025,7 @@ sai_object_id_t PfcToQueueHandler::addQosItem(const vector<sai_attribute_t> &att
sai_status = sai_qos_map_api->create_qos_map(&sai_object, gSwitchId, (uint32_t)qos_map_attrs.size(), qos_map_attrs.data());
if (SAI_STATUS_SUCCESS != sai_status)
{
SWSS_LOG_ERROR("Failed to create tc_to_queue map. status:%d", sai_status);
SWSS_LOG_ERROR("Failed to create pfc_priority_to_queue map. status:%d", sai_status);
return SAI_NULL_OBJECT_ID;
}
return sai_object;
Expand Down Expand Up @@ -1274,6 +1333,7 @@ void QosOrch::initTableHandlers()
m_qos_handler_map.insert(qos_handler_pair(CFG_DSCP_TO_FC_MAP_TABLE_NAME, &QosOrch::handleDscpToFcTable));
m_qos_handler_map.insert(qos_handler_pair(CFG_EXP_TO_FC_MAP_TABLE_NAME, &QosOrch::handleExpToFcTable));
m_qos_handler_map.insert(qos_handler_pair(CFG_TC_TO_DSCP_MAP_TABLE_NAME, &QosOrch::handleTcToDscpTable));
m_qos_handler_map.insert(qos_handler_pair(CFG_TC_TO_DOT1P_MAP_TABLE_NAME, &QosOrch::handleTcToDot1pTable));

m_qos_handler_map.insert(qos_handler_pair(CFG_TC_TO_PRIORITY_GROUP_MAP_TABLE_NAME, &QosOrch::handleTcToPgTable));
m_qos_handler_map.insert(qos_handler_pair(CFG_PFC_PRIORITY_TO_PRIORITY_GROUP_MAP_TABLE_NAME, &QosOrch::handlePfcPrioToPgTable));
Expand Down
10 changes: 10 additions & 0 deletions orchagent/qosorch.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ const string pfc_enable_name = "pfc_enable";
const string pfcwd_sw_enable_name = "pfcwd_sw_enable";
const string tc_to_pg_map_field_name = "tc_to_pg_map";
const string tc_to_queue_field_name = "tc_to_queue_map";
const string tc_to_dot1p_field_name = "tc_to_dot1p_map";
const string tc_to_dscp_field_name = "tc_to_dscp_map";
const string scheduler_field_name = "scheduler";
const string red_max_threshold_field_name = "red_max_threshold";
const string red_min_threshold_field_name = "red_min_threshold";
Expand Down Expand Up @@ -175,6 +177,13 @@ class TcToDscpMapHandler : public QosMapHandler
sai_object_id_t addQosItem(const vector<sai_attribute_t> &attributes) override;
};

class TcToDot1pMapHandler : public QosMapHandler
{
public:
bool convertFieldValuesToAttributes(KeyOpFieldsValuesTuple &tuple, vector<sai_attribute_t> &attributes);
sai_object_id_t addQosItem(const vector<sai_attribute_t> &attributes);
};

class QosOrch : public Orch
{
public:
Expand Down Expand Up @@ -209,6 +218,7 @@ class QosOrch : public Orch
task_process_status handleDscpToFcTable(Consumer& consumer, KeyOpFieldsValuesTuple &tuple);
task_process_status handleExpToFcTable(Consumer& consumer, KeyOpFieldsValuesTuple &tuple);
task_process_status handleTcToDscpTable(Consumer& consumer, KeyOpFieldsValuesTuple &tuple);
task_process_status handleTcToDot1pTable(Consumer& consumer, KeyOpFieldsValuesTuple &tuple);

task_process_status handleGlobalQosMap(const string &op, KeyOpFieldsValuesTuple &tuple);

Expand Down
183 changes: 183 additions & 0 deletions tests/test_qos_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,32 @@

from swsscommon import swsscommon

CFG_TC_TO_DSCP_MAP_TABLE_NAME = "TC_TO_DSCP_MAP"
CFG_TC_TO_DSCP_MAP_KEY = "AZURE"
TC_TO_DSCP_MAP = {
"0": "20",
"1": "16",
"2": "5",
"3": "43",
"4": "34",
"5": "52",
"6": "61",
"7": "17",
}

CFG_TC_TO_DOT1P_MAP_TABLE_NAME = "TC_TO_DOT1P_MAP"
CFG_TC_TO_DOT1P_MAP_KEY = "AZURE"
TC_TO_DOT1P_MAP = {
"0": "0",
"1": "6",
"2": "5",
"3": "3",
"4": "4",
"5": "2",
"6": "1",
"7": "7",
}

CFG_DOT1P_TO_TC_MAP_TABLE_NAME = "DOT1P_TO_TC_MAP"
CFG_DOT1P_TO_TC_MAP_KEY = "AZURE"
DOT1P_TO_TC_MAP = {
Expand Down Expand Up @@ -32,9 +58,166 @@
CFG_PORT_QOS_MAP_TABLE_NAME = "PORT_QOS_MAP"
CFG_PORT_QOS_DOT1P_MAP_FIELD = "dot1p_to_tc_map"
CFG_PORT_QOS_MPLS_TC_MAP_FIELD = "mpls_tc_to_tc_map"
CFG_PORT_QOS_TC_DOT1P_MAP_FIELD = "tc_to_dot1p_map"
CFG_PORT_QOS_TC_DSCP_MAP_FIELD = "tc_to_dscp_map"
CFG_PORT_TABLE_NAME = "PORT"

#Tests for TC-to-DSCP qos map configuration
class TestTcDscp(object):
def connect_dbs(self, dvs):
self.asic_db = swsscommon.DBConnector(1, dvs.redis_sock, 0)
self.config_db = swsscommon.DBConnector(4, dvs.redis_sock, 0)

def create_tc_dscp_profile(self):
tbl = swsscommon.Table(self.config_db, CFG_TC_TO_DSCP_MAP_TABLE_NAME)
fvs = swsscommon.FieldValuePairs(list(TC_TO_DSCP_MAP.items()))
tbl.set(CFG_TC_TO_DSCP_MAP_KEY, fvs)
time.sleep(1)

def find_tc_dscp_profile(self):
found = False
tc_dscp_map_raw = None
tbl = swsscommon.Table(self.asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_QOS_MAP")
keys = tbl.getKeys()
for key in keys:
(status, fvs) = tbl.get(key)
assert status == True

for fv in fvs:
if fv[0] == "SAI_QOS_MAP_ATTR_MAP_TO_VALUE_LIST":
tc_dscp_map_raw = fv[1]
elif fv[0] == "SAI_QOS_MAP_ATTR_TYPE" and fv[1] == "SAI_QOS_MAP_TYPE_TC_AND_COLOR_TO_DSCP":
found = True

if found:
break

assert found == True

return (key, tc_dscp_map_raw)

def apply_tc_dscp_profile_on_all_ports(self):
tbl = swsscommon.Table(self.config_db, CFG_PORT_QOS_MAP_TABLE_NAME)
fvs = swsscommon.FieldValuePairs([(CFG_PORT_QOS_TC_DSCP_MAP_FIELD, CFG_TC_TO_DSCP_MAP_KEY)])
ports = swsscommon.Table(self.config_db, CFG_PORT_TABLE_NAME).getKeys()
for port in ports:
tbl.set(port, fvs)

time.sleep(1)


def test_tc_dscp_cfg(self, dvs):
self.connect_dbs(dvs)
self.create_tc_dscp_profile()
_, tc_dscp_map_raw = self.find_tc_dscp_profile()

tc_dscp_map = json.loads(tc_dscp_map_raw)
for tc2dscp in tc_dscp_map['list']:
tc_val = str(tc2dscp['key']['tc'])
dscp_val = str(tc2dscp['value']['dscp'])
assert dscp_val == TC_TO_DSCP_MAP[tc_val]

def test_port_tc_dscp(self, dvs):
self.connect_dbs(dvs)
self.create_tc_dscp_profile()
oid, _ = self.find_tc_dscp_profile()

self.apply_tc_dscp_profile_on_all_ports()

cnt = 0
tbl = swsscommon.Table(self.asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_PORT")
keys = tbl.getKeys()
for key in keys:
(status, fvs) = tbl.get(key)
assert status == True

for fv in fvs:
if fv[0] == "SAI_PORT_ATTR_QOS_TC_AND_COLOR_TO_DSCP_MAP":
cnt += 1
assert fv[1] == oid

port_cnt = len(swsscommon.Table(self.config_db, CFG_PORT_TABLE_NAME).getKeys())
assert port_cnt == cnt


#Tests for TC-to-Dot1p qos map configuration
class TestTcDot1p(object):
def connect_dbs(self, dvs):
self.asic_db = swsscommon.DBConnector(1, dvs.redis_sock, 0)
self.config_db = swsscommon.DBConnector(4, dvs.redis_sock, 0)

def create_tc_dot1p_profile(self):
tbl = swsscommon.Table(self.config_db, CFG_TC_TO_DOT1P_MAP_TABLE_NAME)
fvs = swsscommon.FieldValuePairs(list(TC_TO_DOT1P_MAP.items()))
tbl.set(CFG_TC_TO_DOT1P_MAP_KEY, fvs)
time.sleep(1)

def find_tc_dot1p_profile(self):
found = False
tc_dot1p_map_raw = None
tbl = swsscommon.Table(self.asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_QOS_MAP")
keys = tbl.getKeys()
for key in keys:
(status, fvs) = tbl.get(key)
assert status == True

for fv in fvs:
if fv[0] == "SAI_QOS_MAP_ATTR_MAP_TO_VALUE_LIST":
tc_dot1p_map_raw = fv[1]
elif fv[0] == "SAI_QOS_MAP_ATTR_TYPE" and fv[1] == "SAI_QOS_MAP_TYPE_TC_AND_COLOR_TO_DOT1P":
found = True

if found:
break

assert found == True

return (key, tc_dot1p_map_raw)

def apply_tc_dot1p_profile_on_all_ports(self):
tbl = swsscommon.Table(self.config_db, CFG_PORT_QOS_MAP_TABLE_NAME)
fvs = swsscommon.FieldValuePairs([(CFG_PORT_QOS_TC_DOT1P_MAP_FIELD, CFG_TC_TO_DOT1P_MAP_KEY)])
ports = swsscommon.Table(self.config_db, CFG_PORT_TABLE_NAME).getKeys()
for port in ports:
tbl.set(port, fvs)

time.sleep(1)


def test_tc_dot1p_cfg(self, dvs):
self.connect_dbs(dvs)
self.create_tc_dot1p_profile()
_, tc_dot1p_map_raw = self.find_tc_dot1p_profile()

tc_dot1p_map = json.loads(tc_dot1p_map_raw)
for tc2dot1p in tc_dot1p_map['list']:
tc_val = str(tc2dot1p['key']['tc'])
dot1p_val = str(tc2dot1p['value']['dot1p'])
assert dot1p_val == TC_TO_DOT1P_MAP[tc_val]

def test_port_tc_dot1p(self, dvs):
self.connect_dbs(dvs)
self.create_tc_dot1p_profile()
oid, _ = self.find_tc_dot1p_profile()

self.apply_tc_dot1p_profile_on_all_ports()

cnt = 0
tbl = swsscommon.Table(self.asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_PORT")
keys = tbl.getKeys()
for key in keys:
(status, fvs) = tbl.get(key)
assert status == True

for fv in fvs:
if fv[0] == "SAI_PORT_ATTR_QOS_TC_AND_COLOR_TO_DOT1P_MAP":
cnt += 1
assert fv[1] == oid

port_cnt = len(swsscommon.Table(self.config_db, CFG_PORT_TABLE_NAME).getKeys())
assert port_cnt == cnt

#Tests for Dot1p-to-TC qos map configuration
class TestDot1p(object):
def connect_dbs(self, dvs):
self.asic_db = swsscommon.DBConnector(1, dvs.redis_sock, 0)
Expand Down

0 comments on commit f66abed

Please sign in to comment.