Skip to content

Commit 3c6cdb3

Browse files
authored
CVL Changes sonic-net#8: 'must' and 'when' expression evaluation (sonic-net#31)
Adding support for evaluating 'must' and 'when' expression based on customized xpath engine.
1 parent dabf231 commit 3c6cdb3

File tree

2 files changed

+399
-15
lines changed

2 files changed

+399
-15
lines changed

cvl/cvl.go

+33-15
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,27 @@ var dbNameToDbNum map[string]uint8
6363
//map of lua script loaded
6464
var luaScripts map[string]*redis.Script
6565

66+
type whenInfo struct {
67+
expr string //when expression
68+
exprTree *xpath.Expr //compiled expression tree
69+
nodeNames []string //list of nodes under when condition
70+
yangListNames []string //all yang list in expression
71+
}
72+
6673
type leafRefInfo struct {
6774
path string //leafref path
6875
exprTree *xpath.Expr //compiled expression tree
6976
yangListNames []string //all yang list in path
7077
targetNodeName string //target node name
7178
}
7279

80+
type mustInfo struct {
81+
expr string //must expression
82+
exprTree *xpath.Expr //compiled expression tree
83+
errCode string //err-app-tag
84+
errStr string //error message
85+
}
86+
7387
//Important schema information to be loaded at bootup time
7488
type modelTableInfo struct {
7589
dbNum uint8
@@ -82,7 +96,8 @@ type modelTableInfo struct {
8296
mapLeaf []string //for 'mapping list'
8397
leafRef map[string][]*leafRefInfo //for storing all leafrefs for a leaf in a table,
8498
//multiple leafref possible for union
85-
mustExp map[string]string
99+
mustExpr map[string][]*mustInfo
100+
whenExpr map[string][]*whenInfo
86101
tablesForMustExp map[string]CVLOperation
87102
refFromTables []tblFieldPair //list of table or table/field referring to this table
88103
dfltLeafVal map[string]string //map of leaf names and default value
@@ -370,7 +385,7 @@ func storeModelInfo(modelFile string, module *yparser.YParserModule) { //such mo
370385
fieldCount++
371386
keypattern := []string{tableName}
372387

373-
/* Create the default key pattern of the form Table Name|{key1}|{key2}. */
388+
// Create the default key pattern of the form Table Name|{key1}|{key2}.
374389
for _ , key := range tableInfo.keys {
375390
keypattern = append(keypattern, fmt.Sprintf("{%s}",key))
376391
}
@@ -420,7 +435,7 @@ func storeModelInfo(modelFile string, module *yparser.YParserModule) { //such mo
420435
continue
421436
}
422437

423-
tableInfo.leafRef = make(map[string][]*leafRefInfo)
438+
tableInfo.leafRef = make(map[string][]*leafRefInfo)
424439

425440
for _, leafRefNode := range leafRefNodes {
426441
if (leafRefNode.Parent == nil || leafRefNode.FirstChild == nil) {
@@ -452,7 +467,7 @@ func storeModelInfo(modelFile string, module *yparser.YParserModule) { //such mo
452467
continue
453468
}
454469

455-
tableInfo.mustExp = make(map[string]string)
470+
tableInfo.mustExpr = make(map[string][]*mustInfo)
456471
for _, mustExp := range mustExps {
457472
if (mustExp.Parent == nil) {
458473
continue
@@ -467,7 +482,10 @@ func storeModelInfo(modelFile string, module *yparser.YParserModule) { //such mo
467482
}
468483
}
469484
if (parentName != "") {
470-
tableInfo.mustExp[parentName] = getXmlNodeAttr(mustExp, "condition")
485+
tableInfo.mustExpr[parentName] = append(tableInfo.mustExpr[parentName],
486+
&mustInfo{
487+
expr: getXmlNodeAttr(mustExp, "condition"),
488+
})
471489
}
472490
}
473491

@@ -559,22 +577,22 @@ func buildRefTableInfo() {
559577
func addTableNamesForMustExp() {
560578

561579
for tblName, tblInfo := range modelInfo.tableInfo {
562-
if (tblInfo.mustExp == nil) {
580+
if (tblInfo.mustExpr == nil) {
563581
continue
564582
}
565583

566584
tblInfo.tablesForMustExp = make(map[string]CVLOperation)
567585

568-
for _, mustExp := range tblInfo.mustExp {
586+
for _, mustExp := range tblInfo.mustExpr {
569587
var op CVLOperation = OP_NONE
570588
//Check if 'must' expression should be executed for a particular operation
571-
if (strings.Contains(mustExp,
589+
if (strings.Contains(mustExp[0].expr,
572590
"/scommon:operation/scommon:operation != CREATE") == true) {
573591
op = op | OP_CREATE
574-
} else if (strings.Contains(mustExp,
592+
} else if (strings.Contains(mustExp[0].expr,
575593
"/scommon:operation/scommon:operation != UPDATE") == true) {
576594
op = op | OP_UPDATE
577-
} else if (strings.Contains(mustExp,
595+
} else if (strings.Contains(mustExp[0].expr,
578596
"/scommon:operation/scommon:operation != DELETE") == true) {
579597
op = op | OP_DELETE
580598
}
@@ -592,7 +610,7 @@ func addTableNamesForMustExp() {
592610
//Table name should appear like "../VLAN_MEMBER/tagging_mode' or '
593611
// "/prt:PORT/prt:ifname"
594612
re := regexp.MustCompile(fmt.Sprintf(".*[/]([a-zA-Z]*:)?%s[\\[/]", tblNameSrch))
595-
matches := re.FindStringSubmatch(mustExp)
613+
matches := re.FindStringSubmatch(mustExp[0].expr)
596614
if (len(matches) > 0) {
597615
//stores the table name
598616
tblInfo.tablesForMustExp[tblNameSrch] = op
@@ -881,11 +899,11 @@ func (c *CVL) checkPathForTableEntry(tableName string, currentValue string, cfgD
881899
//Node-set function such count() can be quite expensive and
882900
//should be avoided through this function
883901
func (c *CVL) addTableEntryForMustExp(cfgData *CVLEditConfigData, tableName string) CVLRetCode {
884-
if (modelInfo.tableInfo[tableName].mustExp == nil) {
902+
if (modelInfo.tableInfo[tableName].mustExpr == nil) {
885903
return CVL_SUCCESS
886904
}
887905

888-
for fieldName, mustExp := range modelInfo.tableInfo[tableName].mustExp {
906+
for fieldName, mustExp := range modelInfo.tableInfo[tableName].mustExpr {
889907

890908
currentValue := "" // Current value for current() function
891909

@@ -927,7 +945,7 @@ func (c *CVL) addTableEntryForMustExp(cfgData *CVLEditConfigData, tableName stri
927945
}
928946

929947
mustExpStk := []string{} //Use the string slice as stack
930-
mustExpStr := "(" + mustExp + ")"
948+
mustExpStr := "(" + mustExp[0].expr + ")"
931949
strLen := len(mustExpStr)
932950
strTmp := ""
933951
//Parse the xpath expression and fetch Redis entry by looking at xpath,
@@ -1005,7 +1023,7 @@ func (c *CVL) addTableEntryForMustExp(cfgData *CVLEditConfigData, tableName stri
10051023

10061024
//Add all other table data for validating all 'must' exp for tableName
10071025
func (c *CVL) addTableDataForMustExp(op CVLOperation, tableName string) CVLRetCode {
1008-
if (modelInfo.tableInfo[tableName].mustExp == nil) {
1026+
if (modelInfo.tableInfo[tableName].mustExpr == nil) {
10091027
return CVL_SUCCESS
10101028
}
10111029

0 commit comments

Comments
 (0)