Skip to content

Commit

Permalink
Add dot1p to tc mapping support (#871)
Browse files Browse the repository at this point in the history
Signed-off-by: Wenda Ni <wenni@microsoft.com>
  • Loading branch information
wendani authored and lguohan committed Sep 6, 2019
1 parent 39fe568 commit 5841e06
Show file tree
Hide file tree
Showing 4 changed files with 191 additions and 2 deletions.
1 change: 1 addition & 0 deletions orchagent/orchdaemon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ bool OrchDaemon::init()
CFG_TC_TO_QUEUE_MAP_TABLE_NAME,
CFG_SCHEDULER_TABLE_NAME,
CFG_DSCP_TO_TC_MAP_TABLE_NAME,
CFG_DOT1P_TO_TC_MAP_TABLE_NAME,
CFG_QUEUE_TABLE_NAME,
CFG_PORT_QOS_MAP_TABLE_NAME,
CFG_WRED_PROFILE_TABLE_NAME,
Expand Down
74 changes: 74 additions & 0 deletions orchagent/qosorch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "qosorch.h"
#include "logger.h"
#include "crmorch.h"
#include "sai_serialize.h"

#include <inttypes.h>
#include <stdlib.h>
Expand Down Expand Up @@ -41,8 +42,10 @@ enum {
RED_DROP_PROBABILITY_SET = (1U << 2)
};

// 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},
{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},
{pfc_to_pg_map_name, SAI_PORT_ATTR_QOS_PFC_PRIORITY_TO_PRIORITY_GROUP_MAP},
Expand All @@ -51,6 +54,7 @@ map<string, sai_port_attr_t> qos_to_attr_map = {

type_map QosOrch::m_qos_maps = {
{CFG_DSCP_TO_TC_MAP_TABLE_NAME, new object_map()},
{CFG_DOT1P_TO_TC_MAP_TABLE_NAME, new object_map()},
{CFG_TC_TO_QUEUE_MAP_TABLE_NAME, new object_map()},
{CFG_SCHEDULER_TABLE_NAME, new object_map()},
{CFG_WRED_PROFILE_TABLE_NAME, new object_map()},
Expand Down Expand Up @@ -216,6 +220,75 @@ task_process_status QosOrch::handleDscpToTcTable(Consumer& consumer)
return dscp_tc_handler.processWorkItem(consumer);
}

bool Dot1pToTcMapHandler::convertFieldValuesToAttributes(KeyOpFieldsValuesTuple &tuple, vector<sai_attribute_t> &attributes)
{
SWSS_LOG_ENTER();
sai_qos_map_list_t dot1p_map_list;

// Allocated resources are freed in freeAttribResources() call
dot1p_map_list.list = new sai_qos_map_t[kfvFieldsValues(tuple).size()];
int i = 0;
for (const auto &fv : kfvFieldsValues(tuple))
{
try
{
dot1p_map_list.list[i].key.dot1p = static_cast<sai_uint8_t>(stoi(fvField(fv)));
dot1p_map_list.list[i].value.tc = static_cast<sai_cos_t>(stoi(fvValue(fv)));
}
catch (const std::invalid_argument &e)
{
SWSS_LOG_ERROR("Invalid dot1p to tc argument %s:%s to %s()", fvField(fv).c_str(), fvValue(fv).c_str(), e.what());
continue;
}
catch (const std::out_of_range &e)
{
SWSS_LOG_ERROR("Out of range dot1p to tc argument %s:%s to %s()", fvField(fv).c_str(), fvValue(fv).c_str(), e.what());
continue;
}

i++;
}
dot1p_map_list.count = static_cast<uint32_t>(i);

sai_attribute_t attr;
attr.id = SAI_QOS_MAP_ATTR_MAP_TO_VALUE_LIST;
attr.value.qosmap.count = dot1p_map_list.count;
attr.value.qosmap.list = dot1p_map_list.list;
attributes.push_back(attr);

return true;
}

sai_object_id_t Dot1pToTcMapHandler::addQosItem(const vector<sai_attribute_t> &attributes)
{
SWSS_LOG_ENTER();
vector<sai_attribute_t> attrs;

sai_attribute_t attr;
attr.id = SAI_QOS_MAP_ATTR_TYPE;
attr.value.u32 = SAI_QOS_MAP_TYPE_DOT1P_TO_TC;
attrs.push_back(attr);

attrs.push_back(attributes[0]);

sai_object_id_t object_id;
sai_status_t sai_status = sai_qos_map_api->create_qos_map(&object_id, gSwitchId, (uint32_t)attrs.size(), attrs.data());
if (SAI_STATUS_SUCCESS != sai_status)
{
SWSS_LOG_ERROR("Failed to create dot1p_to_tc map. status: %s", sai_serialize_status(sai_status).c_str());
return SAI_NULL_OBJECT_ID;
}
SWSS_LOG_DEBUG("created QosMap object: 0x%lx", object_id);
return object_id;
}

task_process_status QosOrch::handleDot1pToTcTable(Consumer &consumer)
{
SWSS_LOG_ENTER();
Dot1pToTcMapHandler dot1p_tc_handler;
return dot1p_tc_handler.processWorkItem(consumer);
}

bool TcToQueueMapHandler::convertFieldValuesToAttributes(KeyOpFieldsValuesTuple &tuple, vector<sai_attribute_t> &attributes)
{
SWSS_LOG_ENTER();
Expand Down Expand Up @@ -800,6 +873,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_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));
m_qos_handler_map.insert(qos_handler_pair(CFG_QUEUE_TABLE_NAME, &QosOrch::handleQueueTable));
Expand Down
13 changes: 11 additions & 2 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 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";
const string pfc_enable_name = "pfc_enable";
Expand Down Expand Up @@ -65,8 +66,15 @@ class QosMapHandler
class DscpToTcMapHandler : public QosMapHandler
{
public:
bool convertFieldValuesToAttributes(KeyOpFieldsValuesTuple &tuple, vector<sai_attribute_t> &attributes);
sai_object_id_t addQosItem(const vector<sai_attribute_t> &attributes);
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:
bool convertFieldValuesToAttributes(KeyOpFieldsValuesTuple &tuple, vector<sai_attribute_t> &attributes) override;
sai_object_id_t addQosItem(const vector<sai_attribute_t> &attributes) override;
};

class TcToQueueMapHandler : public QosMapHandler
Expand Down Expand Up @@ -134,6 +142,7 @@ class QosOrch : public Orch
void initTableHandlers();

task_process_status handleDscpToTcTable(Consumer& consumer);
task_process_status handleDot1pToTcTable(Consumer& consumer);
task_process_status handlePfcPrioToPgTable(Consumer& consumer);
task_process_status handlePfcToQueueTable(Consumer& consumer);
task_process_status handlePortQosMapTable(Consumer& consumer);
Expand Down
105 changes: 105 additions & 0 deletions tests/test_qos_map.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import pytest
import json
import sys
import time
from swsscommon import swsscommon

CFG_DOT1P_TO_TC_MAP_TABLE_NAME = "DOT1P_TO_TC_MAP"
CFG_DOT1P_TO_TC_MAP_KEY = "AZURE"
DOT1P_TO_TC_MAP = {
"0": "0",
"1": "6",
"2": "5",
"3": "3",
"4": "4",
"5": "2",
"6": "1",
"7": "7",
}

CFG_PORT_QOS_MAP_TABLE_NAME = "PORT_QOS_MAP"
CFG_PORT_QOS_MAP_FIELD = "dot1p_to_tc_map"
CFG_PORT_TABLE_NAME = "PORT"


class TestDot1p(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_dot1p_profile(self):
tbl = swsscommon.Table(self.config_db, CFG_DOT1P_TO_TC_MAP_TABLE_NAME)
fvs = swsscommon.FieldValuePairs(DOT1P_TO_TC_MAP.items())
tbl.set(CFG_DOT1P_TO_TC_MAP_KEY, fvs)
time.sleep(1)


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:
(status, fvs) = tbl.get(key)
assert status == True

for fv in fvs:
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:
break

assert found == True

return (key, dot1p_tc_map_raw)


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_TABLE_NAME + "|" + 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)

time.sleep(1)


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 = json.loads(dot1p_tc_map_raw);
for dot1p2tc in dot1p_tc_map['list']:
dot1p = str(dot1p2tc['key']['dot1p'])
tc = str(dot1p2tc['value']['tc'])
assert tc == DOT1P_TO_TC_MAP[dot1p]


def test_port_dot1p(self, dvs):
self.connect_dbs(dvs)
self.create_dot1p_profile()
oid, dot1p_tc_map_raw = self.find_dot1p_profile()

self.apply_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_DOT1P_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

0 comments on commit 5841e06

Please sign in to comment.