Skip to content

Commit 459d3d1

Browse files
authored
SONiC QoS MAPs and PORT_QOS_MAP Yang (sonic-net#7375)
Why I did it Created SONiC Yang model for the following QOS MAPs and PORT QOS MAP: DSCP_TO_TC_MAP DOT1P_TO_TC_MAP TC_TO_QUEUE_MAP TC_TO_PRIORITY_GROUP_MAP MAP_PFC_PRIORITY_TO_QUEUE PORT_QOS_MAP How I did it Defined Yang models for QOS MAPs based on Guideline doc: https://github.com/Azure/SONiC/blob/master/doc/mgmt/SONiC_YANG_Model_Guidelines.md and https://github.com/Azure/sonic-utilities/blob/master/doc/Command-Reference.md How to verify it sonic_yang_models package build The infra code was modified to handle the nested list definition in YANG and translate it to a flat list in DB.
1 parent e6733e9 commit 459d3d1

12 files changed

+1640
-4
lines changed

src/sonic-yang-mgmt/sonic_yang_ext.py

+200-4
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,17 @@
44
from __future__ import print_function
55
import yang as ly
66
import syslog
7-
87
from json import dump, dumps, loads
98
from xmltodict import parse
109
from glob import glob
1110

11+
qos_maps_model = ['DSCP_TO_TC_MAP_LIST',
12+
'DOT1P_TO_TC_MAP_LIST',
13+
'TC_TO_PRIORITY_GROUP_MAP_LIST',
14+
'TC_TO_QUEUE_MAP_LIST',
15+
'MAP_PFC_PRIORITY_TO_QUEUE_LIST',
16+
'PFC_PRIORITY_TO_PRIORITY_GROUP_MAP_LIST']
17+
1218
"""
1319
This is the Exception thrown out of all public function of this class.
1420
"""
@@ -406,6 +412,108 @@ def _yangConvert(val):
406412

407413
return vValue
408414

415+
"""
416+
Xlate a Qos Maps list
417+
This function will xlate from a dict in config DB to a Yang JSON list
418+
using yang model. Output will be go in self.xlateJson
419+
420+
Note: Exceptions from this function are collected in exceptionList and
421+
are displayed only when an entry is not xlated properly from ConfigDB
422+
to sonic_yang.json.
423+
424+
QOS MAPS Yang has inner list, which is diffrent from config DB.
425+
Each field value in config db should be converted to inner list with
426+
key and value.
427+
Example:
428+
429+
Config DB:
430+
"DSCP_TO_TC_MAP": {
431+
"Dscp_to_tc_map1": {
432+
"1": "1",
433+
"2": "2"
434+
}
435+
}
436+
437+
YANG Model:
438+
module: sonic-dscp-tc-map
439+
+--rw sonic-dscp-tc-map
440+
+--rw DSCP_TO_TC_MAP
441+
+--rw DSCP_TO_TC_MAP_LIST* [name]
442+
+--rw name string
443+
+--rw DSCP_TO_TC_MAP* [dscp]
444+
+--rw dscp string
445+
+--rw tc? string
446+
447+
YANG JSON:
448+
"sonic-dscp-tc-map:sonic-dscp-tc-map": {
449+
"sonic-dscp-tc-map:DSCP_TO_TC_MAP": {
450+
"DSCP_TO_TC_MAP_LIST": [
451+
{
452+
"name": "map3",
453+
"DSCP_TO_TC_MAP": [
454+
{
455+
"dscp": "64",
456+
"tc": "1"
457+
},
458+
{
459+
"dscp":"2",
460+
"tc":"2"
461+
}
462+
]
463+
}
464+
]
465+
}
466+
}
467+
"""
468+
def _xlateQosMapList(self, model, yang, config, table, exceptionList):
469+
470+
#create a dict to map each key under primary key with a dict yang model.
471+
#This is done to improve performance of mapping from values of TABLEs in
472+
#config DB to leaf in YANG LIST.
473+
inner_clist = model.get('list')
474+
if inner_clist:
475+
inner_listKey = inner_clist['key']['@value']
476+
inner_leafDict = self._createLeafDict(inner_clist, table)
477+
for lkey in inner_leafDict:
478+
if inner_listKey != lkey:
479+
inner_listVal = lkey
480+
481+
# get keys from YANG model list itself
482+
listKeys = model['key']['@value']
483+
self.sysLog(msg="xlateList keyList:{}".format(listKeys))
484+
primaryKeys = list(config.keys())
485+
for pkey in primaryKeys:
486+
try:
487+
vKey = None
488+
self.sysLog(syslog.LOG_DEBUG, "xlateList Extract pkey:{}".\
489+
format(pkey))
490+
# Find and extracts key from each dict in config
491+
keyDict = self._extractKey(pkey, listKeys)
492+
493+
if inner_clist:
494+
inner_yang_list = list()
495+
for vKey in config[pkey]:
496+
inner_keyDict = dict()
497+
self.sysLog(syslog.LOG_DEBUG, "xlateList Key {} vkey {} Val {} vval {}".\
498+
format(inner_listKey, str(vKey), inner_listVal, str(config[pkey][vKey])))
499+
inner_keyDict[inner_listKey] = str(vKey)
500+
inner_keyDict[inner_listVal] = str(config[pkey][vKey])
501+
inner_yang_list.append(inner_keyDict)
502+
503+
keyDict[inner_clist['@name']] = inner_yang_list
504+
yang.append(keyDict)
505+
# delete pkey from config, done to match one key with one list
506+
del config[pkey]
507+
508+
except Exception as e:
509+
# log debug, because this exception may occur with multilists
510+
self.sysLog(msg="xlateList Exception:{}".format(str(e)), \
511+
debug=syslog.LOG_DEBUG, doPrint=True)
512+
exceptionList.append(str(e))
513+
# with multilist, we continue matching other keys.
514+
continue
515+
return
516+
409517
"""
410518
Xlate a list
411519
This function will xlate from a dict in config DB to a Yang JSON list
@@ -416,16 +524,22 @@ def _yangConvert(val):
416524
to sonic_yang.json.
417525
"""
418526
def _xlateList(self, model, yang, config, table, exceptionList):
527+
528+
#Qos Map lists needs special handling because of inner yang list and
529+
#config db format.
530+
if model['@name'] in qos_maps_model:
531+
self.sysLog(msg="_xlateQosMapList: {}".format(model['@name']))
532+
self._xlateQosMapList(model, yang,config, table, exceptionList)
533+
return
419534

420535
#create a dict to map each key under primary key with a dict yang model.
421536
#This is done to improve performance of mapping from values of TABLEs in
422537
#config DB to leaf in YANG LIST.
423-
leafDict = self._createLeafDict(model, table)
424538

539+
leafDict = self._createLeafDict(model, table)
425540
# get keys from YANG model list itself
426541
listKeys = model['key']['@value']
427542
self.sysLog(msg="xlateList keyList:{}".format(listKeys))
428-
429543
primaryKeys = list(config.keys())
430544
for pkey in primaryKeys:
431545
try:
@@ -459,7 +573,6 @@ def _xlateList(self, model, yang, config, table, exceptionList):
459573
"""
460574
def _xlateListInContainer(self, model, yang, configC, table, exceptionList):
461575
clist = model
462-
#print(clist['@name'])
463576
yang[clist['@name']] = list()
464577
self.sysLog(msg="xlateProcessListOfContainer: {}".format(clist['@name']))
465578
self._xlateList(clist, yang[clist['@name']], configC, table, exceptionList)
@@ -629,10 +742,93 @@ def _revYangConvert(val):
629742

630743
return vValue
631744

745+
"""
746+
Rev xlate from <TABLE>_LIST to table in config DB
747+
QOS MAP Yang has inner list, each inner list key:val should
748+
be mapped to field:value in Config DB.
749+
Example:
750+
751+
YANG:
752+
module: sonic-dscp-tc-map
753+
+--rw sonic-dscp-tc-map
754+
+--rw DSCP_TO_TC_MAP
755+
+--rw DSCP_TO_TC_MAP_LIST* [name]
756+
+--rw name string
757+
+--rw DSCP_TO_TC_MAP* [dscp]
758+
+--rw dscp string
759+
+--rw tc? string
760+
761+
YANG JSON:
762+
"sonic-dscp-tc-map:sonic-dscp-tc-map": {
763+
"sonic-dscp-tc-map:DSCP_TO_TC_MAP": {
764+
"DSCP_TO_TC_MAP_LIST": [
765+
{
766+
"name": "map3",
767+
"DSCP_TO_TC_MAP": [
768+
{
769+
"dscp": "64",
770+
"tc": "1"
771+
},
772+
{
773+
"dscp":"2",
774+
"tc":"2"
775+
}
776+
]
777+
}
778+
]
779+
}
780+
}
781+
782+
Config DB:
783+
"DSCP_TO_TC_MAP": {
784+
"Dscp_to_tc_map1": {
785+
"1": "1",
786+
"2": "2"
787+
}
788+
}
789+
"""
790+
791+
def _revQosMapXlateList(self, model, yang, config, table):
792+
# get keys from YANG model list itself
793+
listKeys = model['key']['@value']
794+
# create a dict to map each key under primary key with a dict yang model.
795+
# This is done to improve performance of mapping from values of TABLEs in
796+
# config DB to leaf in YANG LIST.
797+
798+
# Gather inner list key and value from model
799+
inner_clist = model.get('list')
800+
if inner_clist:
801+
inner_listKey = inner_clist['key']['@value']
802+
inner_leafDict = self._createLeafDict(inner_clist, table)
803+
for lkey in inner_leafDict:
804+
if inner_listKey != lkey:
805+
inner_listVal = lkey
806+
807+
# list with name <NAME>_LIST should be removed,
808+
if "_LIST" in model['@name']:
809+
for entry in yang:
810+
# create key of config DB table
811+
pkey, pkeydict = self._createKey(entry, listKeys)
812+
self.sysLog(syslog.LOG_DEBUG, "revXlateList pkey:{}".format(pkey))
813+
config[pkey]= dict()
814+
# fill rest of the entries
815+
inner_list = entry[inner_clist['@name']]
816+
for index in range(len(inner_list)):
817+
self.sysLog(syslog.LOG_DEBUG, "revXlateList fkey:{} fval {}".\
818+
format(str(inner_list[index][inner_listKey]),\
819+
str(inner_list[index][inner_listVal])))
820+
config[pkey][str(inner_list[index][inner_listKey])] = str(inner_list[index][inner_listVal])
821+
return
822+
632823
"""
633824
Rev xlate from <TABLE>_LIST to table in config DB
634825
"""
635826
def _revXlateList(self, model, yang, config, table):
827+
828+
# special processing for QOS Map table.
829+
if model['@name'] in qos_maps_model:
830+
self._revQosMapXlateList(model, yang, config, table)
831+
return
636832

637833
# get keys from YANG model list itself
638834
listKeys = model['key']['@value']

src/sonic-yang-models/setup.py

+7
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,13 @@
7979
'./yang-models/sonic-scheduler.yang',
8080
'./yang-models/sonic-wred-profile.yang',
8181
'./yang-models/sonic-queue.yang',
82+
'./yang-models/sonic-dscp-tc-map.yang',
83+
'./yang-models/sonic-dot1p-tc-map.yang',
84+
'./yang-models/sonic-tc-priority-group-map.yang',
85+
'./yang-models/sonic-tc-queue-map.yang',
86+
'./yang-models/sonic-pfc-priority-queue-map.yang',
87+
'./yang-models/sonic-pfc-priority-priority-group-map.yang',
88+
'./yang-models/sonic-port-qos-map.yang',
8289
'./yang-models/sonic_yang_tree']),
8390
],
8491
zip_safe=False,

src/sonic-yang-models/tests/files/sample_config_db.json

+87
Original file line numberDiff line numberDiff line change
@@ -1188,6 +1188,93 @@
11881188
"scheduler": "TEST@1",
11891189
"wred_profile": "Wred1"
11901190
}
1191+
},
1192+
1193+
"DSCP_TO_TC_MAP": {
1194+
"Dscp_to_tc_map1": {
1195+
"1": "1",
1196+
"2": "2"
1197+
},
1198+
"Dscp_to_tc_map2": {
1199+
"3": "3",
1200+
"4": "4"
1201+
}
1202+
},
1203+
1204+
"DOT1P_TO_TC_MAP": {
1205+
"Dot1p_to_tc_map1": {
1206+
"1": "1",
1207+
"2": "2"
1208+
},
1209+
"Dot1p_to_tc_map2": {
1210+
"3": "3",
1211+
"4": "4"
1212+
}
1213+
},
1214+
1215+
"TC_TO_PRIORITY_GROUP_MAP": {
1216+
"tc_to_pg_map1": {
1217+
"1": "1",
1218+
"2": "2"
1219+
},
1220+
"tc_to_pg_map2": {
1221+
"3": "3",
1222+
"4": "4"
1223+
}
1224+
},
1225+
1226+
"TC_TO_QUEUE_MAP": {
1227+
"tc_to_q_map1": {
1228+
"1": "1",
1229+
"2": "2"
1230+
},
1231+
"tc_to_q_map2": {
1232+
"3": "3",
1233+
"4": "4"
1234+
}
1235+
},
1236+
1237+
"MAP_PFC_PRIORITY_TO_QUEUE": {
1238+
"pfc_prio_to_q_map1": {
1239+
"1": "1",
1240+
"2": "2"
1241+
},
1242+
"pfc_prio_to_q_map2": {
1243+
"3": "3",
1244+
"4": "4"
1245+
}
1246+
},
1247+
1248+
"PFC_PRIORITY_TO_PRIORITY_GROUP_MAP": {
1249+
"pfc_prio_to_pg_map1": {
1250+
"1": "1",
1251+
"2": "2"
1252+
},
1253+
"pfc_prio_to_pg_map2": {
1254+
"3": "3",
1255+
"4": "4"
1256+
}
1257+
},
1258+
1259+
"PORT_QOS_MAP": {
1260+
"Ethernet0": {
1261+
"dot1p_to_tc_map" : "Dot1p_to_tc_map1",
1262+
"dscp_to_tc_map": "Dscp_to_tc_map1",
1263+
"tc_to_queue_map": "tc_to_q_map1",
1264+
"tc_to_pg_map": "tc_to_pg_map1",
1265+
"pfc_to_queue_map": "pfc_prio_to_q_map1",
1266+
"pfc_to_pg_map" : "pfc_prio_to_pg_map1",
1267+
"pfc_enable" : "3,4"
1268+
},
1269+
"Ethernet4": {
1270+
"dot1p_to_tc_map" : "Dot1p_to_tc_map2",
1271+
"dscp_to_tc_map": "Dscp_to_tc_map2",
1272+
"tc_to_queue_map": "tc_to_q_map2",
1273+
"tc_to_pg_map": "tc_to_pg_map2",
1274+
"pfc_to_queue_map": "pfc_prio_to_q_map2",
1275+
"pfc_to_pg_map" : "pfc_prio_to_pg_map2",
1276+
"pfc_enable" : "3,4"
1277+
}
11911278
}
11921279
},
11931280

0 commit comments

Comments
 (0)