Skip to content
This repository was archived by the owner on Mar 1, 2023. It is now read-only.

Commit 4acb2c3

Browse files
authored
fix bugs and enhance Transformer (#35)
Optimize transformer for GET performance For any request URI and its children, table-name & db-key are queried for the first time and cached internally by the transformer infra. This cache block will be subsequently referred by the infra to avoid redundant callback invocations while the yang model tree is being traversed for GET operation. The cache block is local & valid for a single transaction. Data from Redis DB is queried only once for a table & cached in the infra for further reference. This cache is local & valid for a single transaction On-change, sample based subscription support for gNMI On receipt of subscription request uri, the transformer infra translates it to corresponding Redis Db-table and key, using YANG extensions and provides this info along with other subscription parameters to the translib, which takes care of sending notifications on-change of table/key. YANG extensions introduced : "subscribe-preference", "subscribe-on-change", "subscribe-min-interval". rpc callback support RPC statements defined in both OpenConfig and SONiC yang can be annotated with YANG extension “rpc-callback” to invoke the callback to take an action for the given rpc node YANG default value support Infra has been enhanced to fill the oc yang defaults by referring internal yang-metadata for terminal nodes, if it is not present in the request payload. These defaults will be pushed along with other payload data when a resource is created. RFC compliance support - resource check etc. Parent resource is checked for CRUD and GET requests for the incoming URI, before processing the request. If the parent resource is not available in DB, the transaction is rejected with 404 / "Resource not found" error. Cascade delete to de-configure all related nodes Cascade delete enables dependent config clean up for a DELETE request, based on SONiC yang table dependency. YANG extension "cascade-delete" can be annotated to a node that can be deleted along with all dependent nodes. value xfmr callback The value-xfmr callback supports data conversion before writing into the DB for CRUD request and after reading from DB for GET request. Value-xfmr annotated for a leaf will also be invoked, for all other leaves having a leaf-ref to it. The value-xfmr callback is valid only for the SONIC yang. Operation and tables ordering, dependent tables watch list For a set of DB table/instances, grouped by operation, resulting from processing a request URI, infra supports the following : CRUD Operation ordering, sequencing tables before operating based on sonic-yang/Redis dependencies providing translib, with a list of Redis-tables to watch for changes, when performing operations on dependent tables. Yang model capability Provide yang module name, organization and version information to translib in order to serve model capability request. Miscellaneous bug fixes
1 parent 49e5a22 commit 4acb2c3

18 files changed

+6455
-2233
lines changed

translib/common_app.go

+543-145
Large diffs are not rendered by default.

translib/tlerr/tlerr.go

+11-4
Original file line numberDiff line numberDiff line change
@@ -103,12 +103,19 @@ func (e TranslibSyntaxValidationError) Error() string {
103103
}
104104

105105
type TranslibUnsupportedClientVersion struct {
106-
ClientVersion string
107-
ServerVersion string
108-
ServerBaseVersion string
106+
ClientVersion string
107+
ServerVersion string
108+
ServerBaseVersion string
109109
}
110110

111111
func (e TranslibUnsupportedClientVersion) Error() string {
112-
return p.Sprintf("Unsupported client version %s", e.ClientVersion)
112+
return p.Sprintf("Unsupported client version %s", e.ClientVersion)
113113
}
114114

115+
type TranslibXfmrRetError struct {
116+
XlateFailDelReq bool
117+
}
118+
119+
func (e TranslibXfmrRetError) Error() string {
120+
return p.Sprintf("Translib transformer return %s", e.XlateFailDelReq)
121+
}

translib/transformer/transformer.go

+45-18
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ package transformer
2121
import (
2222
"fmt"
2323
"github.com/openconfig/goyang/pkg/yang"
24-
"github.com/openconfig/ygot/ygot"
2524
"os"
2625
"strings"
2726
"bufio"
@@ -30,15 +29,8 @@ import (
3029
)
3130

3231
var YangPath = "/usr/models/yang/" // OpenConfig-*.yang and sonic yang models path
33-
34-
var entries = map[string]*yang.Entry{}
35-
36-
//Interface for xfmr methods
37-
type xfmrInterface interface {
38-
tableXfmr(s *ygot.GoStruct, t *interface{}) (string, error)
39-
keyXfmr(s *ygot.GoStruct, t *interface{}) (string, error)
40-
fieldXfmr(s *ygot.GoStruct, t *interface{}) (string, error)
41-
}
32+
var ModelsListFile = "models_list"
33+
var TblInfoJsonFile = "sonic_table_info.json"
4234

4335
func reportIfError(errs []error) {
4436
if len(errs) > 0 {
@@ -50,15 +42,15 @@ func reportIfError(errs []error) {
5042

5143
func getOcModelsList () ([]string) {
5244
var fileList []string
53-
file, err := os.Open(YangPath + "models_list")
45+
file, err := os.Open(YangPath + ModelsListFile)
5446
if err != nil {
5547
return fileList
5648
}
5749
defer file.Close()
5850
scanner := bufio.NewScanner(file)
5951
for scanner.Scan() {
6052
fileEntry := scanner.Text()
61-
if strings.HasPrefix(fileEntry, "#") != true {
53+
if !strings.HasPrefix(fileEntry, "#") {
6254
_, err := os.Stat(YangPath + fileEntry)
6355
if err != nil {
6456
continue
@@ -86,9 +78,9 @@ func getDefaultModelsList () ([]string) {
8678

8779
func init() {
8880
initYangModelsPath()
89-
yangFiles := []string{}
81+
initRegex()
9082
ocList := getOcModelsList()
91-
yangFiles = getDefaultModelsList()
83+
yangFiles := getDefaultModelsList()
9284
yangFiles = append(yangFiles, ocList...)
9385
fmt.Println("Yang model List:", yangFiles)
9486
err := loadYangModules(yangFiles...)
@@ -105,7 +97,7 @@ func initYangModelsPath() {
10597
YangPath = path
10698
}
10799

108-
fmt.Println("Yang models path:", YangPath)
100+
fmt.Println("Yang modles path:", YangPath)
109101
}
110102

111103
func loadYangModules(files ...string) error {
@@ -147,15 +139,19 @@ func loadYangModules(files ...string) error {
147139
}
148140
}
149141

150-
sonic_entries := make([]*yang.Entry, len(names))
142+
sonic_entries := make([]*yang.Entry, 0)
151143
oc_entries := make(map[string]*yang.Entry)
152-
oc_annot_entries := make([]*yang.Entry, len(names))
153-
sonic_annot_entries := make([]*yang.Entry, len(names))
144+
oc_annot_entries := make([]*yang.Entry, 0)
145+
sonic_annot_entries := make([]*yang.Entry, 0)
154146

155147
for _, n := range names {
156148
if strings.Contains(n, "annot") && strings.Contains(n, "sonic") {
157149
sonic_annot_entries = append(sonic_annot_entries, yang.ToEntry(mods[n]))
158150
} else if strings.Contains(n, "annot") {
151+
yangMdlNmDt := strings.Split(n, "-annot")
152+
if len(yangMdlNmDt) > 0 {
153+
addMdlCpbltEntry(yangMdlNmDt[0])
154+
}
159155
oc_annot_entries = append(oc_annot_entries, yang.ToEntry(mods[n]))
160156
} else if strings.Contains(n, "sonic") {
161157
sonic_entries = append(sonic_entries, yang.ToEntry(mods[n]))
@@ -164,6 +160,37 @@ func loadYangModules(files ...string) error {
164160
}
165161
}
166162

163+
// populate model capabilities data
164+
for yngMdlNm := range(xMdlCpbltMap) {
165+
org := ""
166+
ver := ""
167+
ocVerSet := false
168+
yngEntry := oc_entries[yngMdlNm]
169+
if (yngEntry != nil) {
170+
// OC yang has version in standard extension oc-ext:openconfig-version
171+
if strings.HasPrefix(yngMdlNm, "openconfig-") {
172+
for _, ext := range yngEntry.Exts {
173+
dataTagArr := strings.Split(ext.Keyword, ":")
174+
tagType := dataTagArr[len(dataTagArr)-1]
175+
if tagType == "openconfig-version" {
176+
ver = ext.NName()
177+
fmt.Printf("Found version %v for yang module %v", ver, yngMdlNm)
178+
if len(strings.TrimSpace(ver)) > 0 {
179+
ocVerSet = true
180+
}
181+
break
182+
}
183+
184+
}
185+
}
186+
}
187+
if ((strings.HasPrefix(yngMdlNm, "ietf-")) || (!ocVerSet)) {
188+
// as per RFC7895 revision date to be used as version
189+
ver = mods[yngMdlNm].Current() //gives the most recent revision date for yang module
190+
}
191+
org = mods[yngMdlNm].Organization.Name
192+
addMdlCpbltData(yngMdlNm, ver, org)
193+
}
167194
dbMapBuild(sonic_entries)
168195
annotDbSpecMap(sonic_annot_entries)
169196
annotToDbMapBuild(oc_annot_entries)

translib/transformer/xconst.go

+39
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ const (
2424
YANG_CONTAINER = "container"
2525
YANG_LEAF = "leaf"
2626
YANG_LEAF_LIST = "leaf-list"
27+
YANG_CHOICE = "choice"
28+
YANG_CASE = "case"
2729

2830
YANG_ANNOT_DB_NAME = "db-name"
2931
YANG_ANNOT_TABLE_NAME = "table-name"
@@ -46,6 +48,43 @@ const (
4648

4749
XPATH_SEP_FWD_SLASH = "/"
4850
XFMR_EMPTY_STRING = ""
51+
XFMR_NONE_STRING = "NONE"
4952
SONIC_TABLE_INDEX = 2
53+
SONIC_LIST_INDEX = 3
54+
SONIC_FIELD_INDEX = 4
55+
SONIC_MDL_PFX = "sonic"
56+
OC_MDL_PFX = "openconfig-"
57+
IETF_MDL_PFX = "ietf-"
58+
IANA_MDL_PFX = "iana-"
59+
YTDB_KEY_XFMR_RET_ARGS = 2
60+
YTDB_KEY_XFMR_RET_VAL_INDX = 0
61+
YTDB_KEY_XFMR_RET_ERR_INDX = 1
62+
YTDB_SBT_XFMR_RET_ARGS = 2
63+
YTDB_SBT_XFMR_RET_VAL_INDX = 0
64+
YTDB_SBT_XFMR_RET_ERR_INDX = 1
65+
YTDB_FLD_XFMR_RET_ARGS = 2
66+
YTDB_FLD_XFMR_RET_VAL_INDX = 0
67+
YTDB_FLD_XFMR_RET_ERR_INDX = 1
68+
DBTY_KEY_XFMR_RET_ARGS = 2
69+
DBTY_KEY_XFMR_RET_VAL_INDX = 0
70+
DBTY_KEY_XFMR_RET_ERR_INDX = 1
71+
DBTY_FLD_XFMR_RET_ARGS = 2
72+
DBTY_FLD_XFMR_RET_VAL_INDX = 0
73+
DBTY_FLD_XFMR_RET_ERR_INDX = 1
74+
SUBSC_SBT_XFMR_RET_ARGS = 2
75+
SUBSC_SBT_XFMR_RET_VAL_INDX = 0
76+
SUBSC_SBT_XFMR_RET_ERR_INDX = 1
77+
DBTY_SBT_XFMR_RET_ERR_INDX = 0
78+
TBL_XFMR_RET_ARGS = 2
79+
TBL_XFMR_RET_VAL_INDX = 0
80+
TBL_XFMR_RET_ERR_INDX = 1
81+
POST_XFMR_RET_ARGS = 2
82+
POST_XFMR_RET_VAL_INDX = 0
83+
POST_XFMR_RET_ERR_INDX = 1
84+
PRE_XFMR_RET_ARGS = 1
85+
PRE_XFMR_RET_ERR_INDX = 0
5086

87+
XFMR_INVALID = -1
88+
XFMR_DISABLE = 0
89+
XFMR_ENABLE = 1
5190
)

0 commit comments

Comments
 (0)