Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add dot1p to tc mapping support #871

Merged
merged 15 commits into from
Sep 6, 2019
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
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