Skip to content

Commit 5841e06

Browse files
wendanilguohan
authored andcommitted
Add dot1p to tc mapping support (#871)
Signed-off-by: Wenda Ni <[email protected]>
1 parent 39fe568 commit 5841e06

File tree

4 files changed

+191
-2
lines changed

4 files changed

+191
-2
lines changed

orchagent/orchdaemon.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ bool OrchDaemon::init()
129129
CFG_TC_TO_QUEUE_MAP_TABLE_NAME,
130130
CFG_SCHEDULER_TABLE_NAME,
131131
CFG_DSCP_TO_TC_MAP_TABLE_NAME,
132+
CFG_DOT1P_TO_TC_MAP_TABLE_NAME,
132133
CFG_QUEUE_TABLE_NAME,
133134
CFG_PORT_QOS_MAP_TABLE_NAME,
134135
CFG_WRED_PROFILE_TABLE_NAME,

orchagent/qosorch.cpp

+74
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include "qosorch.h"
33
#include "logger.h"
44
#include "crmorch.h"
5+
#include "sai_serialize.h"
56

67
#include <inttypes.h>
78
#include <stdlib.h>
@@ -41,8 +42,10 @@ enum {
4142
RED_DROP_PROBABILITY_SET = (1U << 2)
4243
};
4344

45+
// field_name is what is expected in CONFIG_DB PORT_QOS_MAP table
4446
map<string, sai_port_attr_t> qos_to_attr_map = {
4547
{dscp_to_tc_field_name, SAI_PORT_ATTR_QOS_DSCP_TO_TC_MAP},
48+
{dot1p_to_tc_field_name, SAI_PORT_ATTR_QOS_DOT1P_TO_TC_MAP},
4649
{tc_to_queue_field_name, SAI_PORT_ATTR_QOS_TC_TO_QUEUE_MAP},
4750
{tc_to_pg_map_field_name, SAI_PORT_ATTR_QOS_TC_TO_PRIORITY_GROUP_MAP},
4851
{pfc_to_pg_map_name, SAI_PORT_ATTR_QOS_PFC_PRIORITY_TO_PRIORITY_GROUP_MAP},
@@ -51,6 +54,7 @@ map<string, sai_port_attr_t> qos_to_attr_map = {
5154

5255
type_map QosOrch::m_qos_maps = {
5356
{CFG_DSCP_TO_TC_MAP_TABLE_NAME, new object_map()},
57+
{CFG_DOT1P_TO_TC_MAP_TABLE_NAME, new object_map()},
5458
{CFG_TC_TO_QUEUE_MAP_TABLE_NAME, new object_map()},
5559
{CFG_SCHEDULER_TABLE_NAME, new object_map()},
5660
{CFG_WRED_PROFILE_TABLE_NAME, new object_map()},
@@ -216,6 +220,75 @@ task_process_status QosOrch::handleDscpToTcTable(Consumer& consumer)
216220
return dscp_tc_handler.processWorkItem(consumer);
217221
}
218222

223+
bool Dot1pToTcMapHandler::convertFieldValuesToAttributes(KeyOpFieldsValuesTuple &tuple, vector<sai_attribute_t> &attributes)
224+
{
225+
SWSS_LOG_ENTER();
226+
sai_qos_map_list_t dot1p_map_list;
227+
228+
// Allocated resources are freed in freeAttribResources() call
229+
dot1p_map_list.list = new sai_qos_map_t[kfvFieldsValues(tuple).size()];
230+
int i = 0;
231+
for (const auto &fv : kfvFieldsValues(tuple))
232+
{
233+
try
234+
{
235+
dot1p_map_list.list[i].key.dot1p = static_cast<sai_uint8_t>(stoi(fvField(fv)));
236+
dot1p_map_list.list[i].value.tc = static_cast<sai_cos_t>(stoi(fvValue(fv)));
237+
}
238+
catch (const std::invalid_argument &e)
239+
{
240+
SWSS_LOG_ERROR("Invalid dot1p to tc argument %s:%s to %s()", fvField(fv).c_str(), fvValue(fv).c_str(), e.what());
241+
continue;
242+
}
243+
catch (const std::out_of_range &e)
244+
{
245+
SWSS_LOG_ERROR("Out of range dot1p to tc argument %s:%s to %s()", fvField(fv).c_str(), fvValue(fv).c_str(), e.what());
246+
continue;
247+
}
248+
249+
i++;
250+
}
251+
dot1p_map_list.count = static_cast<uint32_t>(i);
252+
253+
sai_attribute_t attr;
254+
attr.id = SAI_QOS_MAP_ATTR_MAP_TO_VALUE_LIST;
255+
attr.value.qosmap.count = dot1p_map_list.count;
256+
attr.value.qosmap.list = dot1p_map_list.list;
257+
attributes.push_back(attr);
258+
259+
return true;
260+
}
261+
262+
sai_object_id_t Dot1pToTcMapHandler::addQosItem(const vector<sai_attribute_t> &attributes)
263+
{
264+
SWSS_LOG_ENTER();
265+
vector<sai_attribute_t> attrs;
266+
267+
sai_attribute_t attr;
268+
attr.id = SAI_QOS_MAP_ATTR_TYPE;
269+
attr.value.u32 = SAI_QOS_MAP_TYPE_DOT1P_TO_TC;
270+
attrs.push_back(attr);
271+
272+
attrs.push_back(attributes[0]);
273+
274+
sai_object_id_t object_id;
275+
sai_status_t sai_status = sai_qos_map_api->create_qos_map(&object_id, gSwitchId, (uint32_t)attrs.size(), attrs.data());
276+
if (SAI_STATUS_SUCCESS != sai_status)
277+
{
278+
SWSS_LOG_ERROR("Failed to create dot1p_to_tc map. status: %s", sai_serialize_status(sai_status).c_str());
279+
return SAI_NULL_OBJECT_ID;
280+
}
281+
SWSS_LOG_DEBUG("created QosMap object: 0x%lx", object_id);
282+
return object_id;
283+
}
284+
285+
task_process_status QosOrch::handleDot1pToTcTable(Consumer &consumer)
286+
{
287+
SWSS_LOG_ENTER();
288+
Dot1pToTcMapHandler dot1p_tc_handler;
289+
return dot1p_tc_handler.processWorkItem(consumer);
290+
}
291+
219292
bool TcToQueueMapHandler::convertFieldValuesToAttributes(KeyOpFieldsValuesTuple &tuple, vector<sai_attribute_t> &attributes)
220293
{
221294
SWSS_LOG_ENTER();
@@ -800,6 +873,7 @@ void QosOrch::initTableHandlers()
800873
{
801874
SWSS_LOG_ENTER();
802875
m_qos_handler_map.insert(qos_handler_pair(CFG_DSCP_TO_TC_MAP_TABLE_NAME, &QosOrch::handleDscpToTcTable));
876+
m_qos_handler_map.insert(qos_handler_pair(CFG_DOT1P_TO_TC_MAP_TABLE_NAME, &QosOrch::handleDot1pToTcTable));
803877
m_qos_handler_map.insert(qos_handler_pair(CFG_TC_TO_QUEUE_MAP_TABLE_NAME, &QosOrch::handleTcToQueueTable));
804878
m_qos_handler_map.insert(qos_handler_pair(CFG_SCHEDULER_TABLE_NAME, &QosOrch::handleSchedulerTable));
805879
m_qos_handler_map.insert(qos_handler_pair(CFG_QUEUE_TABLE_NAME, &QosOrch::handleQueueTable));

orchagent/qosorch.h

+11-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "portsorch.h"
99

1010
const string dscp_to_tc_field_name = "dscp_to_tc_map";
11+
const string dot1p_to_tc_field_name = "dot1p_to_tc_map";
1112
const string pfc_to_pg_map_name = "pfc_to_pg_map";
1213
const string pfc_to_queue_map_name = "pfc_to_queue_map";
1314
const string pfc_enable_name = "pfc_enable";
@@ -65,8 +66,15 @@ class QosMapHandler
6566
class DscpToTcMapHandler : public QosMapHandler
6667
{
6768
public:
68-
bool convertFieldValuesToAttributes(KeyOpFieldsValuesTuple &tuple, vector<sai_attribute_t> &attributes);
69-
sai_object_id_t addQosItem(const vector<sai_attribute_t> &attributes);
69+
bool convertFieldValuesToAttributes(KeyOpFieldsValuesTuple &tuple, vector<sai_attribute_t> &attributes) override;
70+
sai_object_id_t addQosItem(const vector<sai_attribute_t> &attributes) override;
71+
};
72+
73+
class Dot1pToTcMapHandler : public QosMapHandler
74+
{
75+
public:
76+
bool convertFieldValuesToAttributes(KeyOpFieldsValuesTuple &tuple, vector<sai_attribute_t> &attributes) override;
77+
sai_object_id_t addQosItem(const vector<sai_attribute_t> &attributes) override;
7078
};
7179

7280
class TcToQueueMapHandler : public QosMapHandler
@@ -134,6 +142,7 @@ class QosOrch : public Orch
134142
void initTableHandlers();
135143

136144
task_process_status handleDscpToTcTable(Consumer& consumer);
145+
task_process_status handleDot1pToTcTable(Consumer& consumer);
137146
task_process_status handlePfcPrioToPgTable(Consumer& consumer);
138147
task_process_status handlePfcToQueueTable(Consumer& consumer);
139148
task_process_status handlePortQosMapTable(Consumer& consumer);

tests/test_qos_map.py

+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import pytest
2+
import json
3+
import sys
4+
import time
5+
from swsscommon import swsscommon
6+
7+
CFG_DOT1P_TO_TC_MAP_TABLE_NAME = "DOT1P_TO_TC_MAP"
8+
CFG_DOT1P_TO_TC_MAP_KEY = "AZURE"
9+
DOT1P_TO_TC_MAP = {
10+
"0": "0",
11+
"1": "6",
12+
"2": "5",
13+
"3": "3",
14+
"4": "4",
15+
"5": "2",
16+
"6": "1",
17+
"7": "7",
18+
}
19+
20+
CFG_PORT_QOS_MAP_TABLE_NAME = "PORT_QOS_MAP"
21+
CFG_PORT_QOS_MAP_FIELD = "dot1p_to_tc_map"
22+
CFG_PORT_TABLE_NAME = "PORT"
23+
24+
25+
class TestDot1p(object):
26+
def connect_dbs(self, dvs):
27+
self.asic_db = swsscommon.DBConnector(1, dvs.redis_sock, 0)
28+
self.config_db = swsscommon.DBConnector(4, dvs.redis_sock, 0)
29+
30+
31+
def create_dot1p_profile(self):
32+
tbl = swsscommon.Table(self.config_db, CFG_DOT1P_TO_TC_MAP_TABLE_NAME)
33+
fvs = swsscommon.FieldValuePairs(DOT1P_TO_TC_MAP.items())
34+
tbl.set(CFG_DOT1P_TO_TC_MAP_KEY, fvs)
35+
time.sleep(1)
36+
37+
38+
def find_dot1p_profile(self):
39+
found = False
40+
dot1p_tc_map_raw = None
41+
dot1p_tc_map_key = None
42+
tbl = swsscommon.Table(self.asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_QOS_MAP")
43+
keys = tbl.getKeys()
44+
for key in keys:
45+
(status, fvs) = tbl.get(key)
46+
assert status == True
47+
48+
for fv in fvs:
49+
if fv[0] == "SAI_QOS_MAP_ATTR_MAP_TO_VALUE_LIST":
50+
dot1p_tc_map_raw = fv[1]
51+
elif fv[0] == "SAI_QOS_MAP_ATTR_TYPE" and fv[1] == "SAI_QOS_MAP_TYPE_DOT1P_TO_TC":
52+
dot1p_tc_map_key = key
53+
found = True
54+
55+
if found:
56+
break
57+
58+
assert found == True
59+
60+
return (key, dot1p_tc_map_raw)
61+
62+
63+
def apply_dot1p_profile_on_all_ports(self):
64+
tbl = swsscommon.Table(self.config_db, CFG_PORT_QOS_MAP_TABLE_NAME)
65+
fvs = swsscommon.FieldValuePairs([(CFG_PORT_QOS_MAP_FIELD, "[" + CFG_DOT1P_TO_TC_MAP_TABLE_NAME + "|" + CFG_DOT1P_TO_TC_MAP_KEY + "]")])
66+
ports = swsscommon.Table(self.config_db, CFG_PORT_TABLE_NAME).getKeys()
67+
for port in ports:
68+
tbl.set(port, fvs)
69+
70+
time.sleep(1)
71+
72+
73+
def test_dot1p_cfg(self, dvs):
74+
self.connect_dbs(dvs)
75+
self.create_dot1p_profile()
76+
oid, dot1p_tc_map_raw = self.find_dot1p_profile()
77+
78+
dot1p_tc_map = json.loads(dot1p_tc_map_raw);
79+
for dot1p2tc in dot1p_tc_map['list']:
80+
dot1p = str(dot1p2tc['key']['dot1p'])
81+
tc = str(dot1p2tc['value']['tc'])
82+
assert tc == DOT1P_TO_TC_MAP[dot1p]
83+
84+
85+
def test_port_dot1p(self, dvs):
86+
self.connect_dbs(dvs)
87+
self.create_dot1p_profile()
88+
oid, dot1p_tc_map_raw = self.find_dot1p_profile()
89+
90+
self.apply_dot1p_profile_on_all_ports()
91+
92+
cnt = 0
93+
tbl = swsscommon.Table(self.asic_db, "ASIC_STATE:SAI_OBJECT_TYPE_PORT")
94+
keys = tbl.getKeys()
95+
for key in keys:
96+
(status, fvs) = tbl.get(key)
97+
assert status == True
98+
99+
for fv in fvs:
100+
if fv[0] == "SAI_PORT_ATTR_QOS_DOT1P_TO_TC_MAP":
101+
cnt += 1
102+
assert fv[1] == oid
103+
104+
port_cnt = len(swsscommon.Table(self.config_db, CFG_PORT_TABLE_NAME).getKeys())
105+
assert port_cnt == cnt

0 commit comments

Comments
 (0)