Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions doc/Configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,26 @@ instance is supported in SONiC.

```


### MPLS_TC_TO_TC_MAP
```
{
"MPLS_TC_TO_TC_MAP": {
"AZURE": {
"0": "0",
"1": "1",
"2": "1",
"3": "2",
"4": "2",
"5": "3",
"6": "3",
"7": "4"
}
}
}

```

### FLEX_COUNTER_TABLE

```
Expand Down
25 changes: 25 additions & 0 deletions doc/swss-schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,16 @@ Stores information for physical switch ports managed by the switch chip. Ports t
;QOS Mappings
map_dscp_to_tc = ref_hash_key_reference
map_tc_to_queue = ref_hash_key_reference
map_mpls_tc_to_tc = ref_hash_key_reference

Example:
127.0.0.1:6379> hgetall PORT_TABLE:ETHERNET4
1) "dscp_to_tc_map"
2) "AZURE"
3) "tc_to_queue_map"
4) "AZURE"
5) "mpls_tc_to_tc_map"
6) "AZURE"

---------------------------------------------
### INTF_TABLE
Expand Down Expand Up @@ -279,6 +282,28 @@ and reflects the LAG ports into the redis under: `LAG_TABLE:<team0>:port`
9) "9"
10) "8"

---------------------------------------------
### MPLS\_TC\_TO\_TC\_MAP\_TABLE
; MPLS TC to TC map
;SAI mapping - qos_map object with SAI_QOS_MAP_ATTR_TYPE == sai_qos_map_type_t::SAI_QOS_MAP_EXP_TO_TC
key = "MPLS_TC_TO_TC_MAP_TABLE:"name
;field value
mpls_tc_value = 1*DIGIT
tc_value = 1*DIGIT

Example:
127.0.0.1:6379> hgetall "MPLS_TC_TO_TC_MAP_TABLE:AZURE"
1) "0" ;mpls_tc
2) "3" ;tc
3) "1"
4) "5"
5) "2"
6) "5"
7) "3"
8) "7"
9) "4"
10) "8"

---------------------------------------------
### SCHEDULER_TABLE
; Scheduler table
Expand Down
1 change: 1 addition & 0 deletions orchagent/orchdaemon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ bool OrchDaemon::init()
CFG_TC_TO_QUEUE_MAP_TABLE_NAME,
CFG_SCHEDULER_TABLE_NAME,
CFG_DSCP_TO_TC_MAP_TABLE_NAME,
CFG_MPLS_TC_TO_TC_MAP_TABLE_NAME,
CFG_DOT1P_TO_TC_MAP_TABLE_NAME,
CFG_QUEUE_TABLE_NAME,
CFG_PORT_QOS_MAP_TABLE_NAME,
Expand Down
59 changes: 59 additions & 0 deletions orchagent/qosorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ enum {
// field_name is what is expected in CONFIG_DB PORT_QOS_MAP table
map<string, sai_port_attr_t> qos_to_attr_map = {
{dscp_to_tc_field_name, SAI_PORT_ATTR_QOS_DSCP_TO_TC_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_pg_map_field_name, SAI_PORT_ATTR_QOS_TC_TO_PRIORITY_GROUP_MAP},
Expand All @@ -60,6 +61,7 @@ map<string, sai_meter_type_t> scheduler_meter_map = {

type_map QosOrch::m_qos_maps = {
{CFG_DSCP_TO_TC_MAP_TABLE_NAME, new object_reference_map()},
{CFG_MPLS_TC_TO_TC_MAP_TABLE_NAME, new object_reference_map()},
{CFG_DOT1P_TO_TC_MAP_TABLE_NAME, new object_reference_map()},
{CFG_TC_TO_QUEUE_MAP_TABLE_NAME, new object_reference_map()},
{CFG_SCHEDULER_TABLE_NAME, new object_reference_map()},
Expand All @@ -73,6 +75,7 @@ type_map QosOrch::m_qos_maps = {

map<string, string> qos_to_ref_table_map = {
{dscp_to_tc_field_name, CFG_DSCP_TO_TC_MAP_TABLE_NAME},
{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_pg_map_field_name, CFG_TC_TO_PRIORITY_GROUP_MAP_TABLE_NAME},
Expand Down Expand Up @@ -238,6 +241,61 @@ task_process_status QosOrch::handleDscpToTcTable(Consumer& consumer)
return dscp_tc_handler.processWorkItem(consumer);
}

bool MplsTcToTcMapHandler::convertFieldValuesToAttributes(KeyOpFieldsValuesTuple &tuple, vector<sai_attribute_t> &attributes)
{
SWSS_LOG_ENTER();
sai_attribute_t list_attr;
sai_qos_map_list_t exp_map_list;
exp_map_list.count = (uint32_t)kfvFieldsValues(tuple).size();
exp_map_list.list = new sai_qos_map_t[exp_map_list.count]();
uint32_t ind = 0;
for (auto i = kfvFieldsValues(tuple).begin(); i != kfvFieldsValues(tuple).end(); i++, ind++)
{
exp_map_list.list[ind].key.mpls_exp = (uint8_t)stoi(fvField(*i));
exp_map_list.list[ind].value.tc = (uint8_t)stoi(fvValue(*i));
SWSS_LOG_DEBUG("key.exp:%d, value.tc:%d", exp_map_list.list[ind].key.mpls_exp, exp_map_list.list[ind].value.tc);
}
list_attr.id = SAI_QOS_MAP_ATTR_MAP_TO_VALUE_LIST;
list_attr.value.qosmap.count = exp_map_list.count;
list_attr.value.qosmap.list = exp_map_list.list;
attributes.push_back(list_attr);
return true;
}

sai_object_id_t MplsTcToTcMapHandler::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.u32 = SAI_QOS_MAP_TYPE_MPLS_EXP_TO_TC;
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 exp_to_tc map. status:%d", sai_status);
return SAI_NULL_OBJECT_ID;
}
SWSS_LOG_DEBUG("created QosMap object:%" PRIx64, sai_object);
return sai_object;
}

task_process_status QosOrch::handleMplsTcToTcTable(Consumer& consumer)
{
SWSS_LOG_ENTER();
MplsTcToTcMapHandler mpls_tc_to_tc_handler;
return mpls_tc_to_tc_handler.processWorkItem(consumer);
}

bool Dot1pToTcMapHandler::convertFieldValuesToAttributes(KeyOpFieldsValuesTuple &tuple, vector<sai_attribute_t> &attributes)
{
SWSS_LOG_ENTER();
Expand Down Expand Up @@ -760,6 +818,7 @@ void QosOrch::initTableHandlers()
{
SWSS_LOG_ENTER();
m_qos_handler_map.insert(qos_handler_pair(CFG_DSCP_TO_TC_MAP_TABLE_NAME, &QosOrch::handleDscpToTcTable));
m_qos_handler_map.insert(qos_handler_pair(CFG_MPLS_TC_TO_TC_MAP_TABLE_NAME, &QosOrch::handleMplsTcToTcTable));
m_qos_handler_map.insert(qos_handler_pair(CFG_DOT1P_TO_TC_MAP_TABLE_NAME, &QosOrch::handleDot1pToTcTable));
m_qos_handler_map.insert(qos_handler_pair(CFG_TC_TO_QUEUE_MAP_TABLE_NAME, &QosOrch::handleTcToQueueTable));
m_qos_handler_map.insert(qos_handler_pair(CFG_SCHEDULER_TABLE_NAME, &QosOrch::handleSchedulerTable));
Expand Down
9 changes: 9 additions & 0 deletions orchagent/qosorch.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "portsorch.h"

const string dscp_to_tc_field_name = "dscp_to_tc_map";
const string mpls_tc_to_tc_field_name = "mpls_tc_to_tc_map";
const string dot1p_to_tc_field_name = "dot1p_to_tc_map";
const string pfc_to_pg_map_name = "pfc_to_pg_map";
const string pfc_to_queue_map_name = "pfc_to_queue_map";
Expand Down Expand Up @@ -70,6 +71,13 @@ class DscpToTcMapHandler : public QosMapHandler
sai_object_id_t addQosItem(const vector<sai_attribute_t> &attributes) override;
};

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

class Dot1pToTcMapHandler : public QosMapHandler
{
public:
Expand Down Expand Up @@ -137,6 +145,7 @@ class QosOrch : public Orch
void initTableHandlers();

task_process_status handleDscpToTcTable(Consumer& consumer);
task_process_status handleMplsTcToTcTable(Consumer& consumer);
task_process_status handleDot1pToTcTable(Consumer& consumer);
task_process_status handlePfcPrioToPgTable(Consumer& consumer);
task_process_status handlePfcToQueueTable(Consumer& consumer);
Expand Down
107 changes: 99 additions & 8 deletions tests/test_qos_map.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import pytest
import json
import sys
import time

from swsscommon import swsscommon
Expand All @@ -18,8 +16,22 @@
"7": "7",
}

CFG_MPLS_TC_TO_TC_MAP_TABLE_NAME = "MPLS_TC_TO_TC_MAP"
CFG_MPLS_TC_TO_TC_MAP_KEY = "AZURE_MPLS_TC"
MPLS_TC_TO_TC_MAP = {
"0": "0",
"1": "4",
"2": "1",
"3": "3",
"4": "5",
"5": "2",
"6": "7",
"7": "6",
}

CFG_PORT_QOS_MAP_TABLE_NAME = "PORT_QOS_MAP"
CFG_PORT_QOS_MAP_FIELD = "dot1p_to_tc_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_TABLE_NAME = "PORT"


Expand All @@ -39,7 +51,6 @@ def create_dot1p_profile(self):
def find_dot1p_profile(self):
found = False
dot1p_tc_map_raw = None
dot1p_tc_map_key = None
tbl = swsscommon.Table(self.asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_QOS_MAP")
keys = tbl.getKeys()
for key in keys:
Expand All @@ -50,7 +61,6 @@ def find_dot1p_profile(self):
if fv[0] == "SAI_QOS_MAP_ATTR_MAP_TO_VALUE_LIST":
dot1p_tc_map_raw = fv[1]
elif fv[0] == "SAI_QOS_MAP_ATTR_TYPE" and fv[1] == "SAI_QOS_MAP_TYPE_DOT1P_TO_TC":
dot1p_tc_map_key = key
found = True

if found:
Expand All @@ -63,7 +73,7 @@ def find_dot1p_profile(self):

def apply_dot1p_profile_on_all_ports(self):
tbl = swsscommon.Table(self.config_db, CFG_PORT_QOS_MAP_TABLE_NAME)
fvs = swsscommon.FieldValuePairs([(CFG_PORT_QOS_MAP_FIELD, CFG_DOT1P_TO_TC_MAP_KEY)])
fvs = swsscommon.FieldValuePairs([(CFG_PORT_QOS_DOT1P_MAP_FIELD, CFG_DOT1P_TO_TC_MAP_KEY)])
ports = swsscommon.Table(self.config_db, CFG_PORT_TABLE_NAME).getKeys()
for port in ports:
tbl.set(port, fvs)
Expand All @@ -74,7 +84,7 @@ def apply_dot1p_profile_on_all_ports(self):
def test_dot1p_cfg(self, dvs):
self.connect_dbs(dvs)
self.create_dot1p_profile()
oid, dot1p_tc_map_raw = self.find_dot1p_profile()
_, dot1p_tc_map_raw = self.find_dot1p_profile()

dot1p_tc_map = json.loads(dot1p_tc_map_raw);
for dot1p2tc in dot1p_tc_map['list']:
Expand All @@ -86,7 +96,7 @@ def test_dot1p_cfg(self, dvs):
def test_port_dot1p(self, dvs):
self.connect_dbs(dvs)
self.create_dot1p_profile()
oid, dot1p_tc_map_raw = self.find_dot1p_profile()
oid, _ = self.find_dot1p_profile()

self.apply_dot1p_profile_on_all_ports()

Expand All @@ -106,6 +116,87 @@ def test_port_dot1p(self, dvs):
assert port_cnt == cnt


class TestMplsTc(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_mpls_tc_profile(self):
tbl = swsscommon.Table(self.config_db, CFG_MPLS_TC_TO_TC_MAP_TABLE_NAME)
fvs = swsscommon.FieldValuePairs(list(MPLS_TC_TO_TC_MAP.items()))
tbl.set(CFG_MPLS_TC_TO_TC_MAP_KEY, fvs)
time.sleep(1)


def find_mpls_tc_profile(self):
found = False
mpls_tc_tc_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":
mpls_tc_tc_map_raw = fv[1]
elif fv[0] == "SAI_QOS_MAP_ATTR_TYPE" and fv[1] == "SAI_QOS_MAP_TYPE_MPLS_EXP_TO_TC":
found = True

if found:
break

assert found == True

return (key, mpls_tc_tc_map_raw)


def apply_mpls_tc_profile_on_all_ports(self):
tbl = swsscommon.Table(self.config_db, CFG_PORT_QOS_MAP_TABLE_NAME)
fvs = swsscommon.FieldValuePairs([(CFG_PORT_QOS_MPLS_TC_MAP_FIELD, CFG_MPLS_TC_TO_TC_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_mpls_tc_cfg(self, dvs):
self.connect_dbs(dvs)
self.create_mpls_tc_profile()
_, mpls_tc_tc_map_raw = self.find_mpls_tc_profile()

mpls_tc_tc_map = json.loads(mpls_tc_tc_map_raw)
for mplstc2tc in mpls_tc_tc_map['list']:
mpls_tc = str(mplstc2tc['key']['mpls_exp'])
tc = str(mplstc2tc['value']['tc'])
assert tc == MPLS_TC_TO_TC_MAP[mpls_tc]


def test_port_mpls_tc(self, dvs):
self.connect_dbs(dvs)
self.create_mpls_tc_profile()
oid, _ = self.find_mpls_tc_profile()

self.apply_mpls_tc_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_MPLS_EXP_TO_TC_MAP":
cnt += 1
assert fv[1] == oid

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


# Add Dummy always-pass test at end as workaroud
# for issue when Flaky fail on final test it invokes module tear-down before retrying
def test_nonflaky_dummy():
Expand Down