From 38d673da32b0b919a03b25a027e1aa533ee56ea6 Mon Sep 17 00:00:00 2001 From: kwangsuk Date: Sat, 27 Jul 2019 08:05:10 -0700 Subject: [PATCH 001/214] load the yang to dynamically build in-memory metadata tree --- src/translib/acl_app.go | 7 +++ src/translib/transformer/transformer.go | 71 +++++++++++++++++++++++++ 2 files changed, 78 insertions(+) create mode 100644 src/translib/transformer/transformer.go diff --git a/src/translib/acl_app.go b/src/translib/acl_app.go index 8eb92141db..90b552d41e 100644 --- a/src/translib/acl_app.go +++ b/src/translib/acl_app.go @@ -19,6 +19,7 @@ import ( "strings" "translib/db" "translib/ocbinds" + "translib/transformer" ) const ( @@ -97,6 +98,12 @@ func init() { if err != nil { log.Fatal("Adding model data to appinterface failed with error=", err) } + + yangFiles := []string{"../../../models/yang/openconfig-acl.yang"} + err = transformer.LoadYangModules(yangFiles...) + if err != nil { + log.Fatal("Loading Yang modules failed with error=", err) + } } func (app *AclApp) initialize(data appData) { diff --git a/src/translib/transformer/transformer.go b/src/translib/transformer/transformer.go new file mode 100644 index 0000000000..e70027ac2b --- /dev/null +++ b/src/translib/transformer/transformer.go @@ -0,0 +1,71 @@ +package transformer + +import ( + "fmt" + "os" + "sort" + "github.com/openconfig/goyang/pkg/yang" +) + +var entries = map[string]*yang.Entry{} + +func reportIfError(errs []error) { + if len(errs) > 0 { + for _, err := range errs { + fmt.Fprintln(os.Stderr, err) + } + } +} + +func init() { + // TODO - define the path for YANG files from container +} + +func LoadYangModules(files ...string) error { + + var err error + + paths := []string{"../../../models/yang/common", "../../../models/yang"} + + for _, path := range paths { + expanded, err := yang.PathsWithModules(path) + if err != nil { + fmt.Fprintln(os.Stderr, err) + continue + } + yang.AddPath(expanded...) + } + + ms := yang.NewModules() + + for _, name := range files { + if err := ms.Read(name); err != nil { + fmt.Fprintln(os.Stderr, err) + continue + } + } + + // Process the Yang files + reportIfError(ms.Process()) + + // Keep track of the top level modules we read in. + // Those are the only modules we want to print below. + mods := map[string]*yang.Module{} + var names []string + + for _, m := range ms.Modules { + if mods[m.Name] == nil { + mods[m.Name] = m + names = append(names, m.Name) + } + } + sort.Strings(names) + entries = make(map[string]*yang.Entry) + for _, n := range names { + if entries[n] == nil { + entries[n] = yang.ToEntry(mods[n]) + } + } + + return err +} From e28113baf8382e66214337bcea6bc3ca9ebffb63 Mon Sep 17 00:00:00 2001 From: kwangsuk Date: Mon, 29 Jul 2019 00:01:05 -0700 Subject: [PATCH 002/214] add xslate code, yang extension etc. --- models/yang/common/sonic-extensions.yang | 53 ++++++++++++++++++++++++ models/yang/openconfig-acl.yang | 8 +++- src/translib/acl_app.go | 8 +++- src/translib/transformer/transformer.go | 14 ++++++- src/translib/transformer/xfmr_acl.go | 36 ++++++++++++++++ src/translib/transformer/xlate.go | 53 ++++++++++++++++++++++++ 6 files changed, 169 insertions(+), 3 deletions(-) create mode 100644 models/yang/common/sonic-extensions.yang create mode 100644 src/translib/transformer/xfmr_acl.go create mode 100644 src/translib/transformer/xlate.go diff --git a/models/yang/common/sonic-extensions.yang b/models/yang/common/sonic-extensions.yang new file mode 100644 index 0000000000..8087d99568 --- /dev/null +++ b/models/yang/common/sonic-extensions.yang @@ -0,0 +1,53 @@ +module sonic-extensions { + + yang-version "1"; + + // namespace + namespace "http://openconfig.net/yang/sonic-ext"; + + prefix "sonic-ext"; + + // meta + organization "Sonic working group"; + + contact + "OpenConfig working group + www.openconfig.net"; + + description + "This module provides extensions to the YANG language to allow + Sonic specific functionality and meta-data to be defined."; + + revision "2019-07-26" { + description + "Add extensionis for redis DB mappings for table, table-keys, table-fields and corresponding transformer methods."; + } + + + // extension statements + extension table-name { + argument "table-name"; + description "Db table name."; + } + + extension key-xfmr { + argument "key-xfmr-name"; + description "Db table key transformer name indicating that the list keys together form db table keys."; + } + + extension field-name { + argument "field-name"; + description "Db table field name."; + } + + extension field-xfmr { + argument "field-xfmr-name"; + description "Db table field transformer name.This can be applied to either transform yang value to some different format + or choose a specific DB field based on the type of yang value."; + } + + extension table-xfmr { + argument "object-xfmr-name"; + description "Object level transformer name that will have db mappings for an object."; + } +} diff --git a/models/yang/openconfig-acl.yang b/models/yang/openconfig-acl.yang index fe8098889b..0bb84fc16b 100644 --- a/models/yang/openconfig-acl.yang +++ b/models/yang/openconfig-acl.yang @@ -11,6 +11,7 @@ module openconfig-acl { import openconfig-interfaces { prefix oc-if; } import openconfig-yang-types { prefix oc-yang; } import openconfig-extensions { prefix oc-ext; } + import sonic-extensions { prefix sonic-ext; } // meta organization "OpenConfig working group"; @@ -433,6 +434,7 @@ module openconfig-acl { type identityref { base ACL_TYPE; } + sonic-ext:field-name "type"; description "The type determines the fields allowed in the ACL entries belonging to the ACL set (e.g., IPv4, IPv6, etc.)"; @@ -440,6 +442,7 @@ module openconfig-acl { leaf description { type string; + sonic-ext:field-name "policy_desc"; description "Description, or comment, for the ACL set"; } @@ -460,6 +463,8 @@ module openconfig-acl { "Access list entries variables enclosing container"; list acl-set { + sonic-ext:table-name "ACL_TABLE"; + sonic-ext:key-xfmr "acl_set_key_xfmr"; key "name type"; description "List of ACL sets, each comprising of a list of ACL @@ -535,6 +540,7 @@ module openconfig-acl { "Enclosing container for list of references to ACLs"; list acl-entry { + sonic-ext:table-name "ACL_RULE"; key "sequence-id"; description "List of ACL entries assigned to an interface"; @@ -751,6 +757,7 @@ module openconfig-acl { ACLs are set"; list interface { + sonic-ext:table-xfmr "port_bindings_xfmr"; key "id"; description "List of interfaces on which ACLs are set"; @@ -818,7 +825,6 @@ module openconfig-acl { container config { description "Global config data for ACLs"; - uses acl-config; } diff --git a/src/translib/acl_app.go b/src/translib/acl_app.go index 90b552d41e..1e4fc0a74c 100644 --- a/src/translib/acl_app.go +++ b/src/translib/acl_app.go @@ -99,7 +99,7 @@ func init() { log.Fatal("Adding model data to appinterface failed with error=", err) } - yangFiles := []string{"../../../models/yang/openconfig-acl.yang"} + yangFiles := []string{"../../../models/yang/openconfig-acl.yang", "../../cvl/schema/sonic-acl.yang"} err = transformer.LoadYangModules(yangFiles...) if err != nil { log.Fatal("Loading Yang modules failed with error=", err) @@ -590,6 +590,12 @@ func (app *AclApp) translateCRUCommon(d *db.DB, opcode int) ([]db.WatchKeys, err log.Info("translateCRUCommon:acl:path =", app.path) aclObj := app.getAppRootObject() + + // translate yang to db + //payload, err := dumpIetfJson(aclObj, false) + result, err := transformer.XlateToDb((*app).ygotRoot, (*app).ygotTarget) + fmt.Println(result) + app.aclTableMap = app.convertOCAclsToInternal(aclObj) app.ruleTableMap = app.convertOCAclRulesToInternal(aclObj) app.bindAclFlag, err = app.convertOCAclBindingsToInternal(d, app.aclTableMap, aclObj) diff --git a/src/translib/transformer/transformer.go b/src/translib/transformer/transformer.go index e70027ac2b..3b9fbcee4d 100644 --- a/src/translib/transformer/transformer.go +++ b/src/translib/transformer/transformer.go @@ -5,10 +5,20 @@ import ( "os" "sort" "github.com/openconfig/goyang/pkg/yang" + "github.com/openconfig/ygot/ygot" +// "translib/db" +// "translib/ocbinds" ) var entries = map[string]*yang.Entry{} +//Interface for xfmr methods +type xfmrInterface interface { + tableXfmr(s *ygot.GoStruct, t *interface{}) (string, error) + keyXfmr(s *ygot.GoStruct, t *interface{}) (string, error) + fieldXfmr(s *ygot.GoStruct, t *interface{}) (string, error) +} + func reportIfError(errs []error) { if len(errs) > 0 { for _, err := range errs { @@ -25,7 +35,7 @@ func LoadYangModules(files ...string) error { var err error - paths := []string{"../../../models/yang/common", "../../../models/yang"} + paths := []string{"../../../models/yang/common", "../../../models/yang", "../../cvl/schema"} for _, path := range paths { expanded, err := yang.PathsWithModules(path) @@ -66,6 +76,8 @@ func LoadYangModules(files ...string) error { entries[n] = yang.ToEntry(mods[n]) } } + + // TODO - build the inverse map for GET, from OC to Sonic return err } diff --git a/src/translib/transformer/xfmr_acl.go b/src/translib/transformer/xfmr_acl.go new file mode 100644 index 0000000000..b3a6fc8195 --- /dev/null +++ b/src/translib/transformer/xfmr_acl.go @@ -0,0 +1,36 @@ +package transformer + +import ( + "fmt" +// "os" +// "sort" +// "github.com/openconfig/goyang/pkg/yang" +// "github.com/openconfig/ygot/ygot" + "translib/db" +// "translib/ocbinds" +) + + +func acl_set_key_xfmr(json []byte) (map[string]map[string]db.Value, error) { + + var err error + + // table.key.fields + var result = make(map[string]map[string]db.Value) + fmt.Println(string(json)) + + // TODO - traverse JSON with the metadata to translate to DB + // xfmr method dynamically invoked + + return result, err +} + +func port_bindings_xfmr(data map[string]map[string]db.Value) ([]byte, error) { + var err error + + // table.key.fields + var result []byte + + //TODO - implement me + return result, err +} \ No newline at end of file diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go new file mode 100644 index 0000000000..0ed6c179bc --- /dev/null +++ b/src/translib/transformer/xlate.go @@ -0,0 +1,53 @@ +package transformer + +import ( + "fmt" +// "os" +// "sort" +// "github.com/openconfig/goyang/pkg/yang" + "github.com/openconfig/ygot/ygot" + "translib/db" + "translib/ocbinds" +) + + + +func XlateToDb(s *ygot.GoStruct, t *interface{}) (map[string]map[string]db.Value, error) { + + var err error + + d := (*s).(*ocbinds.Device) + jsonStr, err := ygot.EmitJSON(d, &ygot.EmitJSONConfig{ + Format: ygot.RFC7951, + Indent: " ", + SkipValidation: true, + RFC7951Config: &ygot.RFC7951JSONConfig{ + AppendModuleName: true, + }, + }) + fmt.Println(jsonStr) + + // table.key.fields + var result = make(map[string]map[string]db.Value) + + + // TODO - traverse ygot/JSON with the metadata to translate to DB + // xfmr method dynamically invoked + + // use reflect to call the xfmr method from yang extension "key_xfmr", "tanle_xfmr", "field_xfmr" + //var xfmr keyXfmr + + + + return result, err +} + +func XlateFromDb(data map[string]map[string]db.Value) ([]byte, error) { + var err error + + // table.key.fields + var result []byte + + //TODO - implement me + return result, err +} \ No newline at end of file From 772be7e21b624c991d93aa01f324a9e45d718b20 Mon Sep 17 00:00:00 2001 From: Ravi Vasanthm Date: Mon, 29 Jul 2019 12:40:54 -0700 Subject: [PATCH 003/214] Adding yang models as part of installer. --- Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Makefile b/Makefile index 72a7312d67..cc0ffe8d38 100644 --- a/Makefile +++ b/Makefile @@ -96,7 +96,11 @@ install: $(INSTALL) -D $(CERTGEN_BIN) $(DESTDIR)/usr/sbin/generate_cert $(INSTALL) -d $(DESTDIR)/usr/sbin/schema/ $(INSTALL) -d $(DESTDIR)/usr/sbin/lib/ + $(INSTALL) -d $(DESTDIR)/models/yang/ $(INSTALL) -D $(TOPDIR)/src/cvl/schema/*.yin $(DESTDIR)/usr/sbin/schema/ + $(INSTALL) -D $(TOPDIR)/src/cvl/schema/*.yang $(DESTDIR)/models/yang/ + $(INSTALL) -D $(TOPDIR)/models/yang/*.yang $(DESTDIR)/models/yang/ + $(INSTALL) -D $(TOPDIR)/models/yang/common/*.yang $(DESTDIR)/models/yang/ cp -rf $(TOPDIR)/build/rest_server/dist/ui/ $(DESTDIR)/rest_ui/ cp -rf $(TOPDIR)/build/cli $(DESTDIR)/usr/sbin/ cp -rf $(TOPDIR)/build/swagger_client_py/ $(DESTDIR)/usr/sbin/lib/ From 6d08c82a3574aa119babf6d18f9b67e4dca01957 Mon Sep 17 00:00:00 2001 From: Ravi Vasanthm Date: Mon, 29 Jul 2019 16:03:53 -0700 Subject: [PATCH 004/214] Update yang files path on target, Defined yang path in transformer package. --- Makefile | 8 ++++---- src/translib/acl_app.go | 4 +++- src/translib/transformer/transformer.go | 4 +++- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index cc0ffe8d38..857ad7c007 100644 --- a/Makefile +++ b/Makefile @@ -96,11 +96,11 @@ install: $(INSTALL) -D $(CERTGEN_BIN) $(DESTDIR)/usr/sbin/generate_cert $(INSTALL) -d $(DESTDIR)/usr/sbin/schema/ $(INSTALL) -d $(DESTDIR)/usr/sbin/lib/ - $(INSTALL) -d $(DESTDIR)/models/yang/ + $(INSTALL) -d $(DESTDIR)/usr/models/yang/ $(INSTALL) -D $(TOPDIR)/src/cvl/schema/*.yin $(DESTDIR)/usr/sbin/schema/ - $(INSTALL) -D $(TOPDIR)/src/cvl/schema/*.yang $(DESTDIR)/models/yang/ - $(INSTALL) -D $(TOPDIR)/models/yang/*.yang $(DESTDIR)/models/yang/ - $(INSTALL) -D $(TOPDIR)/models/yang/common/*.yang $(DESTDIR)/models/yang/ + $(INSTALL) -D $(TOPDIR)/src/cvl/schema/*.yang $(DESTDIR)/usr/models/yang/ + $(INSTALL) -D $(TOPDIR)/models/yang/*.yang $(DESTDIR)/usr/models/yang/ + $(INSTALL) -D $(TOPDIR)/models/yang/common/*.yang $(DESTDIR)/usr/models/yang/ cp -rf $(TOPDIR)/build/rest_server/dist/ui/ $(DESTDIR)/rest_ui/ cp -rf $(TOPDIR)/build/cli $(DESTDIR)/usr/sbin/ cp -rf $(TOPDIR)/build/swagger_client_py/ $(DESTDIR)/usr/sbin/lib/ diff --git a/src/translib/acl_app.go b/src/translib/acl_app.go index 1e4fc0a74c..15bb4a4916 100644 --- a/src/translib/acl_app.go +++ b/src/translib/acl_app.go @@ -22,6 +22,7 @@ import ( "translib/transformer" ) + const ( TABLE_SEPARATOR = "|" KEY_SEPARATOR = "|" @@ -99,7 +100,8 @@ func init() { log.Fatal("Adding model data to appinterface failed with error=", err) } - yangFiles := []string{"../../../models/yang/openconfig-acl.yang", "../../cvl/schema/sonic-acl.yang"} + yangFiles := []string{transformer.YangPath + "openconfig-acl.yang", transformer.YangPath + "sonic-acl.yang"} + log.Info("Init transformer yang files :", yangFiles) err = transformer.LoadYangModules(yangFiles...) if err != nil { log.Fatal("Loading Yang modules failed with error=", err) diff --git a/src/translib/transformer/transformer.go b/src/translib/transformer/transformer.go index 3b9fbcee4d..d0050d6bab 100644 --- a/src/translib/transformer/transformer.go +++ b/src/translib/transformer/transformer.go @@ -10,6 +10,8 @@ import ( // "translib/ocbinds" ) +const YangPath = "/usr/models/yang/" // OpenConfig-*.yang and sonic yang models path + var entries = map[string]*yang.Entry{} //Interface for xfmr methods @@ -35,7 +37,7 @@ func LoadYangModules(files ...string) error { var err error - paths := []string{"../../../models/yang/common", "../../../models/yang", "../../cvl/schema"} + paths := []string{YangPath} for _, path := range paths { expanded, err := yang.PathsWithModules(path) From 61205f499312ff0c53a8486f0808201487b734b4 Mon Sep 17 00:00:00 2001 From: Marimuthu Sakthivel Date: Tue, 30 Jul 2019 16:54:00 -0700 Subject: [PATCH 005/214] Added code to dynamically create tranformer-spec-map having yang to db translation table. --- src/translib/transformer/transformer.go | 5 +- src/translib/transformer/xSpec.go | 144 ++++++++++++++++++++++++ 2 files changed, 147 insertions(+), 2 deletions(-) create mode 100644 src/translib/transformer/xSpec.go diff --git a/src/translib/transformer/transformer.go b/src/translib/transformer/transformer.go index d0050d6bab..b2b7875200 100644 --- a/src/translib/transformer/transformer.go +++ b/src/translib/transformer/transformer.go @@ -38,7 +38,7 @@ func LoadYangModules(files ...string) error { var err error paths := []string{YangPath} - + for _, path := range paths { expanded, err := yang.PathsWithModules(path) if err != nil { @@ -78,7 +78,8 @@ func LoadYangModules(files ...string) error { entries[n] = yang.ToEntry(mods[n]) } } - + mapBuild(entries) + // TODO - build the inverse map for GET, from OC to Sonic return err diff --git a/src/translib/transformer/xSpec.go b/src/translib/transformer/xSpec.go new file mode 100644 index 0000000000..54cb2c72d5 --- /dev/null +++ b/src/translib/transformer/xSpec.go @@ -0,0 +1,144 @@ +package main +import ( + "fmt" +) + +/* Data needed to construct lookup table from yang */ +type yangXpathInfo struct { + children *[]string + yangDataType string + tableName *string + keyXpath map[int]*[]string + delim *[]string + fieldName string + xfmrFunc string +} + +var xSpecMap map[string]*yangXpathInfo + +/* Recursive api to fill the map with yang details */ +func fillMap (xSpecMap map[string]*yangXpathInfo, entry *yang.Entry, xpathPrefix string) { + + xpath := xpathPrefix + "/" + entry.Name + xpathData := new(yangXpathInfo) + + fmt.Printf("MARI: pfx(%s), nd(%s)\r\n", xpathPrefix, entry.Name) + parentXpathData, ok := xSpecMap[xpathPrefix] + /* init current xpath table data with its parent data, change only if needed. */ + if ok { + xpathData.tableName = parentXpathData.tableName + } + + /* fill yang data type i.e. module, container, list, leaf etc. */ + xpathData.yangDataType = entry.Node.Statement().Keyword + + inheritParentKey := true + /* fill table with yang extension data. */ + if len(entry.Exts) > 0 { + for _, ext := range entry.Exts { + dataTagArr := strings.Split(ext.Kind(), ":") + tagType := dataTagArr[len(dataTagArr)-1] + switch tagType { + case "redis-table-name" : + xpathData.tableName = new(string) + *xpathData.tableName = ext.NName() + case "redis-field-name" : + xpathData.fieldName = ext.NName() + case "xfmr" : + xpathData.xfmrFunc = ext.NName() + case "use-self-key" : + xpathData.keyXpath = nil + inheritParentKey = false + } + } + } + + /* fill table with key data. */ + if len(entry.Key) != 0 { + parentKeyLen := 0 + + /* create list with current keys */ + keyXpath := make([]string, len(strings.Split(entry.Key, " "))) + for id, keyName := range(strings.Split(entry.Key, " ")) { + keyXpath[id] = xpath + "/" + keyName + } + if inheritParentKey { + /* init parentKeyLen to the number of parent-key list */ + parentKeyLen = len(parentXpathData.keyXpath) + } + + xpathData.keyXpath = make(map[int]*[]string, (parentKeyLen + 1)) + k := 0 + for ; k < parentKeyLen; k++ { + /* copy parent key-list to child key-list*/ + xpathData.keyXpath[k] = parentXpathData.keyXpath[k] + } + xpathData.keyXpath[k] = &keyXpath + } else if parentXpathData != nil && parentXpathData.keyXpath != nil { + xpathData.keyXpath = parentXpathData.keyXpath + } + + /* get current obj's children */ + var childList []string + for k := range entry.Dir { + childList = append(childList, k) + } + sort.Strings(childList) + + /* copy children of current obj */ + if len(childList) > 0 { + children := make([]string, len(entry.Dir)) + copy(children, childList) + xpathData.children = &children + } + /* update yang-map with xpath and table info. */ + xSpecMap[xpath] = xpathData + + /* now recurse, filling the map with current node's children info */ + for _, child := range childList { + fillMap(xSpecMap, entry.Dir[child], xpath) + } +} + +/* Build lookup hash table based of yang xpath */ +func mapBuild(entries map[string]*yang.Entry) { + if entries == nil { + return + } + xSpecMap = make(map[string]*yangXpathInfo) + for _, e := range entries { + if len(e.Dir) == 0 { + continue + } + + /* Start to fill xpath based map with yang data */ + fillMap(xSpecMap, e, "") + } + mapPrint(xSpecMap) +} + +/* Debug function to print the map data into file */ +func mapPrint(inMap map[string]*yangXpathInfo) { + fp, err := os.Create("/tmp/xspec.txt") + if err != nil { + return + } + defer fp.Close() + + for k, d := range inMap { + fmt.Fprintf (fp, "-----------------------------------------------------------------\r\n") + fmt.Fprintf(fp, "%v:\r\n", k) + fmt.Fprintf(fp, " yangDataType: %v", d.yangDataType) + fmt.Fprintf(fp, " tableName: ") + if d.tableName != nil { + fmt.Fprintf(fp, "%v", *d.tableName) + } + fmt.Fprintf(fp, "\r\n keyXpath: %d\r\n", d.keyXpath) + for i, kd := range d.keyXpath { + fmt.Fprintf(fp, " %d. %#v\r\n", i, kd) + } + fmt.Fprintf(fp, " children (%p : %v)\r\n", d.children, d.children) + } + fmt.Fprintf (fp, "-----------------------------------------------------------------\r\n") + +} From 0ad30b091ff7e5730da9219d40558ed70410181e Mon Sep 17 00:00:00 2001 From: Ravi Vasanthm Date: Tue, 30 Jul 2019 17:11:36 -0700 Subject: [PATCH 006/214] Added infrastructure to populate xlate function map and invoke xfmr functions defined by applications using single interface. --- src/translib/transformer/xfmr_acl.go | 6 +- src/translib/transformer/xlate.go | 124 +++++++++++++++++---------- 2 files changed, 86 insertions(+), 44 deletions(-) diff --git a/src/translib/transformer/xfmr_acl.go b/src/translib/transformer/xfmr_acl.go index b3a6fc8195..b57ebfee20 100644 --- a/src/translib/transformer/xfmr_acl.go +++ b/src/translib/transformer/xfmr_acl.go @@ -10,6 +10,10 @@ import ( // "translib/ocbinds" ) +func init () { + XlateFuncBind("acl_set_key_xfmr", acl_set_key_xfmr) + XlateFuncBind("port_bindings_xfmr", port_bindings_xfmr) +} func acl_set_key_xfmr(json []byte) (map[string]map[string]db.Value, error) { @@ -33,4 +37,4 @@ func port_bindings_xfmr(data map[string]map[string]db.Value) ([]byte, error) { //TODO - implement me return result, err -} \ No newline at end of file +} diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index 0ed6c179bc..ea6fe3ebff 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -1,53 +1,91 @@ package transformer import ( - "fmt" -// "os" -// "sort" -// "github.com/openconfig/goyang/pkg/yang" - "github.com/openconfig/ygot/ygot" - "translib/db" - "translib/ocbinds" + "fmt" + // "os" + // "sort" + // "github.com/openconfig/goyang/pkg/yang" + "github.com/openconfig/ygot/ygot" + "translib/db" + "translib/ocbinds" + "reflect" + "errors" + log "github.com/golang/glog" ) - - +var XlateFuncs = make(map[string]reflect.Value) + +var ( + ErrParamsNotAdapted = errors.New("The number of params is not adapted.") +) + +func XlateFuncBind (name string, fn interface{}) (err error) { + defer func() { + if e := recover(); e != nil { + err = errors.New(name + " is not callable.") + } + }() + + v :=reflect.ValueOf(fn) + v.Type().NumIn() + XlateFuncs[name] = v + log.Info("XlateFuncs map: ", XlateFuncs) + return +} + +func XlateFuncCall(name string, params ... interface{}) (result []reflect.Value, err error) { + if _, ok := XlateFuncs[name]; !ok { + err = errors.New(name + " does not exist.") + return + } + if len(params) != XlateFuncs[name].Type().NumIn() { + err = ErrParamsNotAdapted + return + } + in := make([]reflect.Value, len(params)) + for k, param := range params { + in[k] = reflect.ValueOf(param) + } + result = XlateFuncs[name].Call(in) + return +} + func XlateToDb(s *ygot.GoStruct, t *interface{}) (map[string]map[string]db.Value, error) { - var err error - - d := (*s).(*ocbinds.Device) - jsonStr, err := ygot.EmitJSON(d, &ygot.EmitJSONConfig{ - Format: ygot.RFC7951, - Indent: " ", - SkipValidation: true, - RFC7951Config: &ygot.RFC7951JSONConfig{ - AppendModuleName: true, - }, - }) - fmt.Println(jsonStr) - - // table.key.fields - var result = make(map[string]map[string]db.Value) - - - // TODO - traverse ygot/JSON with the metadata to translate to DB - // xfmr method dynamically invoked - - // use reflect to call the xfmr method from yang extension "key_xfmr", "tanle_xfmr", "field_xfmr" - //var xfmr keyXfmr - - - - return result, err + var err error + + d := (*s).(*ocbinds.Device) + jsonStr, err := ygot.EmitJSON(d, &ygot.EmitJSONConfig{ + Format: ygot.RFC7951, + Indent: " ", + SkipValidation: true, + RFC7951Config: &ygot.RFC7951JSONConfig{ + AppendModuleName: true, + }, + }) + fmt.Println(jsonStr) + + // table.key.fields + var result = make(map[string]map[string]db.Value) + + + // TODO - traverse ygot/JSON with the metadata to translate to DB + // xfmr method dynamically invoked + + // use reflect to call the xfmr method from yang extension "key_xfmr", "tanle_xfmr", "field_xfmr" + //var xfmr keyXfmr + + + + return result, err } func XlateFromDb(data map[string]map[string]db.Value) ([]byte, error) { - var err error - - // table.key.fields - var result []byte - - //TODO - implement me - return result, err -} \ No newline at end of file + var err error + + // table.key.fields + var result []byte + + //TODO - implement me + return result, err +} From 5476d9516869fa5368cc5b14ff8606008003ed87 Mon Sep 17 00:00:00 2001 From: Marimuthu Sakthivel Date: Tue, 30 Jul 2019 18:52:13 -0700 Subject: [PATCH 007/214] Removed dbg print and renames the filename. --- src/translib/transformer/{xSpec.go => xspec.go} | 1 - 1 file changed, 1 deletion(-) rename src/translib/transformer/{xSpec.go => xspec.go} (98%) diff --git a/src/translib/transformer/xSpec.go b/src/translib/transformer/xspec.go similarity index 98% rename from src/translib/transformer/xSpec.go rename to src/translib/transformer/xspec.go index 54cb2c72d5..3871ac6179 100644 --- a/src/translib/transformer/xSpec.go +++ b/src/translib/transformer/xspec.go @@ -22,7 +22,6 @@ func fillMap (xSpecMap map[string]*yangXpathInfo, entry *yang.Entry, xpathPrefix xpath := xpathPrefix + "/" + entry.Name xpathData := new(yangXpathInfo) - fmt.Printf("MARI: pfx(%s), nd(%s)\r\n", xpathPrefix, entry.Name) parentXpathData, ok := xSpecMap[xpathPrefix] /* init current xpath table data with its parent data, change only if needed. */ if ok { From 3da205ebf3a605dcb692a884289c907e394c8718 Mon Sep 17 00:00:00 2001 From: Ravi Vasanthm Date: Wed, 31 Jul 2019 10:18:35 -0700 Subject: [PATCH 008/214] Added check in XlateFuncBind function to avoid updating the existing entry. --- src/translib/transformer/xlate.go | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index ea6fe3ebff..7609e5bc65 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -22,20 +22,23 @@ var ( func XlateFuncBind (name string, fn interface{}) (err error) { defer func() { if e := recover(); e != nil { - err = errors.New(name + " is not callable.") + err = errors.New(name + " is not valid Xfmr function.") } }() - v :=reflect.ValueOf(fn) - v.Type().NumIn() - XlateFuncs[name] = v - log.Info("XlateFuncs map: ", XlateFuncs) + if _, ok := XlateFuncs[name]; !ok { + v :=reflect.ValueOf(fn) + v.Type().NumIn() + XlateFuncs[name] = v + } else { + log.Info("Duplicate entry found in the XlateFunc map " + name) + } return } func XlateFuncCall(name string, params ... interface{}) (result []reflect.Value, err error) { if _, ok := XlateFuncs[name]; !ok { - err = errors.New(name + " does not exist.") + err = errors.New(name + " Xfmr function does not exist.") return } if len(params) != XlateFuncs[name].Type().NumIn() { From de40ab93da6c04ed81f94378feb75864890e6dda Mon Sep 17 00:00:00 2001 From: Marimuthu Sakthivel Date: Wed, 31 Jul 2019 23:53:29 -0700 Subject: [PATCH 009/214] Imported required packages and changed the package name. --- src/translib/transformer/xspec.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/translib/transformer/xspec.go b/src/translib/transformer/xspec.go index 3871ac6179..222f59f379 100644 --- a/src/translib/transformer/xspec.go +++ b/src/translib/transformer/xspec.go @@ -1,6 +1,11 @@ -package main +package transformer import ( "fmt" + "os" + "sort" + "strings" + + "github.com/openconfig/goyang/pkg/yang" ) /* Data needed to construct lookup table from yang */ @@ -100,7 +105,7 @@ func fillMap (xSpecMap map[string]*yangXpathInfo, entry *yang.Entry, xpathPrefix } /* Build lookup hash table based of yang xpath */ -func mapBuild(entries map[string]*yang.Entry) { +func mapBuild(entries []*yang.Entry) { if entries == nil { return } From 9a2bce602aaf5cb9e8191c7ea9d63bbb384f3342 Mon Sep 17 00:00:00 2001 From: Marimuthu Sakthivel Date: Thu, 1 Aug 2019 15:57:16 -0700 Subject: [PATCH 010/214] Addressed compilation error. --- src/translib/transformer/xspec.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/translib/transformer/xspec.go b/src/translib/transformer/xspec.go index 222f59f379..1614ec4dc7 100644 --- a/src/translib/transformer/xspec.go +++ b/src/translib/transformer/xspec.go @@ -105,7 +105,7 @@ func fillMap (xSpecMap map[string]*yangXpathInfo, entry *yang.Entry, xpathPrefix } /* Build lookup hash table based of yang xpath */ -func mapBuild(entries []*yang.Entry) { +func mapBuild(entries map[string]*yang.Entry) { if entries == nil { return } From 35728faf2a81615de6a3b0714e8e9f1ea1453077 Mon Sep 17 00:00:00 2001 From: Amruta Sali Date: Fri, 2 Aug 2019 11:21:24 -0700 Subject: [PATCH 011/214] Added sonic-extensions Applied sonic-extensions to openconfig-acl.yang --- .../yang/common/openconfig-packet-match.yang | 8 ++++++ models/yang/common/sonic-extensions.yang | 27 +++++++++++++------ models/yang/openconfig-acl.yang | 8 +++--- 3 files changed, 32 insertions(+), 11 deletions(-) diff --git a/models/yang/common/openconfig-packet-match.yang b/models/yang/common/openconfig-packet-match.yang index 510bc57686..36fb4e4193 100644 --- a/models/yang/common/openconfig-packet-match.yang +++ b/models/yang/common/openconfig-packet-match.yang @@ -12,6 +12,7 @@ module openconfig-packet-match { import openconfig-yang-types { prefix oc-yang; } import openconfig-packet-match-types { prefix oc-pkt-match-types; } import openconfig-extensions { prefix oc-ext; } + import sonic-extensions { prefix sonic-ext; } // meta organization "OpenConfig working group"; @@ -175,12 +176,14 @@ module openconfig-packet-match { "IP protocol fields common to IPv4 and IPv6"; leaf dscp { + //sonic-ext:field-name "DSCP"; type oc-inet:dscp; description "Value of diffserv codepoint."; } leaf protocol { + sonic-ext:field-xfmr "oc_match_ip_protocol_xfmr"; type oc-pkt-match-types:ip-protocol-type; description "The protocol carried in the IP packet, expressed either @@ -205,12 +208,14 @@ module openconfig-packet-match { for IPv4"; leaf source-address { + sonic-ext:field-name "SRC_IP"; type oc-inet:ipv4-prefix; description "Source IPv4 address prefix."; } leaf destination-address { + sonic-ext:field-name "DST_IP"; type oc-inet:ipv4-prefix; description "Destination IPv4 address prefix."; @@ -319,18 +324,21 @@ module openconfig-packet-match { "Configuration data of transport-layer packet fields"; leaf source-port { + sonic-ext:field-xfmr "oc_match_transport_port_xfmr"; type oc-pkt-match-types:port-num-range; description "Source port or range"; } leaf destination-port { + sonic-ext:field-xfmr "oc_match_transport_port_xfmr"; type oc-pkt-match-types:port-num-range; description "Destination port or range"; } leaf-list tcp-flags { + sonic-ext:field-xfmr "oc_match_transport_tcpflags_xfmr"; type identityref { base oc-pkt-match-types:TCP_FLAGS; } diff --git a/models/yang/common/sonic-extensions.yang b/models/yang/common/sonic-extensions.yang index 8087d99568..18bddd1a09 100644 --- a/models/yang/common/sonic-extensions.yang +++ b/models/yang/common/sonic-extensions.yang @@ -26,28 +26,39 @@ module sonic-extensions { // extension statements extension table-name { - argument "table-name"; + argument "table-name"; description "Db table name."; } extension key-xfmr { - argument "key-xfmr-name"; + argument "key-xfmr-name"; description "Db table key transformer name indicating that the list keys together form db table keys."; } + extension key-delimiter { + argument "key-delimiter-string"; + description "Db table key values delimiter."; + } + extension field-name { - argument "field-name"; + argument "field-name"; description "Db table field name."; } extension field-xfmr { - argument "field-xfmr-name"; - description "Db table field transformer name.This can be applied to either transform yang value to some different format + argument "field-xfmr-name"; + description "Db table field transformer name.This can be applied to either transform yang value to some different format or choose a specific DB field based on the type of yang value."; } - extension table-xfmr { - argument "object-xfmr-name"; - description "Object level transformer name that will have db mappings for an object."; + extension subtree-xfmr { + argument "subtree-xfmr-name"; + description "Subtree/node level transformer name that will have db mappings for an entire yang subtree."; } + + extension post-xfmr { + argument "post-xfmr-name"; + description "Transformer name that will perform post-translation tasks."; + } + } diff --git a/models/yang/openconfig-acl.yang b/models/yang/openconfig-acl.yang index 0bb84fc16b..0c6eead639 100644 --- a/models/yang/openconfig-acl.yang +++ b/models/yang/openconfig-acl.yang @@ -220,6 +220,7 @@ module openconfig-acl { leaf forwarding-action { + sonic-ext:field-name "PACKET_ACTION"; type identityref { base FORWARDING_ACTION; } @@ -359,6 +360,8 @@ module openconfig-acl { "Access list entries container"; list acl-entry { + sonic-ext:table-name "ACL_RULE"; + sonic-ext:key-xfmr "acl_entry_key_xfmr"; key "sequence-id"; description "List of ACL entries comprising an ACL set"; @@ -464,7 +467,7 @@ module openconfig-acl { list acl-set { sonic-ext:table-name "ACL_TABLE"; - sonic-ext:key-xfmr "acl_set_key_xfmr"; + sonic-ext:key-delimiter "_"; key "name type"; description "List of ACL sets, each comprising of a list of ACL @@ -540,7 +543,6 @@ module openconfig-acl { "Enclosing container for list of references to ACLs"; list acl-entry { - sonic-ext:table-name "ACL_RULE"; key "sequence-id"; description "List of ACL entries assigned to an interface"; @@ -757,7 +759,7 @@ module openconfig-acl { ACLs are set"; list interface { - sonic-ext:table-xfmr "port_bindings_xfmr"; + sonic-ext:subtree-xfmr "port_bindings_xfmr"; key "id"; description "List of interfaces on which ACLs are set"; From af113fabe91038e6387eca4b2b5e7386376afef0 Mon Sep 17 00:00:00 2001 From: Amruta Sali Date: Mon, 5 Aug 2019 11:04:24 -0700 Subject: [PATCH 012/214] Added initial version of deviations for openconfig-acl covering Set cases. --- .../yang/common/openconfig-packet-match.yang | 8 -- models/yang/common/sonic-extensions.yang | 16 +-- models/yang/openconfig-acl-annot.yang | 98 +++++++++++++++++++ models/yang/openconfig-acl.yang | 9 -- 4 files changed, 106 insertions(+), 25 deletions(-) create mode 100644 models/yang/openconfig-acl-annot.yang diff --git a/models/yang/common/openconfig-packet-match.yang b/models/yang/common/openconfig-packet-match.yang index 36fb4e4193..510bc57686 100644 --- a/models/yang/common/openconfig-packet-match.yang +++ b/models/yang/common/openconfig-packet-match.yang @@ -12,7 +12,6 @@ module openconfig-packet-match { import openconfig-yang-types { prefix oc-yang; } import openconfig-packet-match-types { prefix oc-pkt-match-types; } import openconfig-extensions { prefix oc-ext; } - import sonic-extensions { prefix sonic-ext; } // meta organization "OpenConfig working group"; @@ -176,14 +175,12 @@ module openconfig-packet-match { "IP protocol fields common to IPv4 and IPv6"; leaf dscp { - //sonic-ext:field-name "DSCP"; type oc-inet:dscp; description "Value of diffserv codepoint."; } leaf protocol { - sonic-ext:field-xfmr "oc_match_ip_protocol_xfmr"; type oc-pkt-match-types:ip-protocol-type; description "The protocol carried in the IP packet, expressed either @@ -208,14 +205,12 @@ module openconfig-packet-match { for IPv4"; leaf source-address { - sonic-ext:field-name "SRC_IP"; type oc-inet:ipv4-prefix; description "Source IPv4 address prefix."; } leaf destination-address { - sonic-ext:field-name "DST_IP"; type oc-inet:ipv4-prefix; description "Destination IPv4 address prefix."; @@ -324,21 +319,18 @@ module openconfig-packet-match { "Configuration data of transport-layer packet fields"; leaf source-port { - sonic-ext:field-xfmr "oc_match_transport_port_xfmr"; type oc-pkt-match-types:port-num-range; description "Source port or range"; } leaf destination-port { - sonic-ext:field-xfmr "oc_match_transport_port_xfmr"; type oc-pkt-match-types:port-num-range; description "Destination port or range"; } leaf-list tcp-flags { - sonic-ext:field-xfmr "oc_match_transport_tcpflags_xfmr"; type identityref { base oc-pkt-match-types:TCP_FLAGS; } diff --git a/models/yang/common/sonic-extensions.yang b/models/yang/common/sonic-extensions.yang index 18bddd1a09..60c44164bc 100644 --- a/models/yang/common/sonic-extensions.yang +++ b/models/yang/common/sonic-extensions.yang @@ -30,8 +30,8 @@ module sonic-extensions { description "Db table name."; } - extension key-xfmr { - argument "key-xfmr-name"; + extension key-transformer { + argument "key-transformer-name"; description "Db table key transformer name indicating that the list keys together form db table keys."; } @@ -45,19 +45,19 @@ module sonic-extensions { description "Db table field name."; } - extension field-xfmr { - argument "field-xfmr-name"; + extension field-transformer { + argument "field-transformer-name"; description "Db table field transformer name.This can be applied to either transform yang value to some different format or choose a specific DB field based on the type of yang value."; } - extension subtree-xfmr { - argument "subtree-xfmr-name"; + extension subtree-transformer { + argument "subtree-transformer-name"; description "Subtree/node level transformer name that will have db mappings for an entire yang subtree."; } - extension post-xfmr { - argument "post-xfmr-name"; + extension post-transformer { + argument "post-transformer-name"; description "Transformer name that will perform post-translation tasks."; } diff --git a/models/yang/openconfig-acl-annot.yang b/models/yang/openconfig-acl-annot.yang new file mode 100644 index 0000000000..159b5b96b8 --- /dev/null +++ b/models/yang/openconfig-acl-annot.yang @@ -0,0 +1,98 @@ +module openconfig-acl-annot { + + yang-version "1"; + + namespace "http://openconfig.net/yang/annotation"; + prefix "oc-acl-annot"; + + import sonic-extensions { prefix sonic-ext; } + import openconfig-acl { prefix oc-acl; } + + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set { + deviate add { + sonic-ext:table-name "ACL_TABLE"; + sonic-ext:key-delimiter "_"; + } + } + + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:config/oc-acl:description { + deviate add { + sonic-ext:field-name "policy_desc"; + } + } + + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry { + deviate add { + sonic-ext:table-name "ACL_RULE"; + sonic-ext:key-transformer "acl_entry_key_xfmr"; + } + } + + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-acl:ipv4/oc-acl:config/oc-acl:source-address { + deviate add { + sonic-ext:field-name "SRC_IP"; + } + } + + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-acl:ipv4/oc-acl:config/oc-acl:destination-address { + deviate add { + sonic-ext:field-name "DST_IP"; + } + } + + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-acl:ipv4/oc-acl:config/oc-acl:protocol { + deviate add { + sonic-ext:field-transformer "acl_ip_protocol_xfmr"; + } + } + + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-acl:ipv6/oc-acl:config/oc-acl:source-address { + deviate add { + sonic-ext:field-name "SRC_IP"; + } + } + + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-acl:ipv6/oc-acl:config/oc-acl:destination-address { + deviate add { + sonic-ext:field-name "DST_IP"; + } + } + + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-acl:ipv6/oc-acl:config/oc-acl:protocol { + deviate add { + sonic-ext:field-transformer "acl_ip_protocol_xfmr"; + } + } + + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-acl:transport/oc-acl:config/oc-acl:source-port { + deviate add { + sonic-ext:field-transformer "acl_source_port_xfmr"; + } + } + + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-acl:transport/oc-acl:config/oc-acl:destination-port { + deviate add { + sonic-ext:field-transformer "acl_destination_port_xfmr"; + } + } + + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-acl:transport/oc-acl:config/oc-acl:tcp_flags { + deviate add { + sonic-ext:field-transformer "acl_tcp_flags_xfmr"; + } + } + + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-acl:actions/oc-acl:config/oc-acl:forwrding-action { + deviate add { + sonic-ext:field-name "PACKET_ACTION"; + } + } + + deviation /oc-acl:acl/oc-acl:interfaces { + deviate add { + sonic-ext:subtree-trasnformer "acl_port_bindings_xfmr"; + } + } + +} + diff --git a/models/yang/openconfig-acl.yang b/models/yang/openconfig-acl.yang index 0c6eead639..67c75ff47c 100644 --- a/models/yang/openconfig-acl.yang +++ b/models/yang/openconfig-acl.yang @@ -11,7 +11,6 @@ module openconfig-acl { import openconfig-interfaces { prefix oc-if; } import openconfig-yang-types { prefix oc-yang; } import openconfig-extensions { prefix oc-ext; } - import sonic-extensions { prefix sonic-ext; } // meta organization "OpenConfig working group"; @@ -220,7 +219,6 @@ module openconfig-acl { leaf forwarding-action { - sonic-ext:field-name "PACKET_ACTION"; type identityref { base FORWARDING_ACTION; } @@ -360,8 +358,6 @@ module openconfig-acl { "Access list entries container"; list acl-entry { - sonic-ext:table-name "ACL_RULE"; - sonic-ext:key-xfmr "acl_entry_key_xfmr"; key "sequence-id"; description "List of ACL entries comprising an ACL set"; @@ -437,7 +433,6 @@ module openconfig-acl { type identityref { base ACL_TYPE; } - sonic-ext:field-name "type"; description "The type determines the fields allowed in the ACL entries belonging to the ACL set (e.g., IPv4, IPv6, etc.)"; @@ -445,7 +440,6 @@ module openconfig-acl { leaf description { type string; - sonic-ext:field-name "policy_desc"; description "Description, or comment, for the ACL set"; } @@ -466,8 +460,6 @@ module openconfig-acl { "Access list entries variables enclosing container"; list acl-set { - sonic-ext:table-name "ACL_TABLE"; - sonic-ext:key-delimiter "_"; key "name type"; description "List of ACL sets, each comprising of a list of ACL @@ -759,7 +751,6 @@ module openconfig-acl { ACLs are set"; list interface { - sonic-ext:subtree-xfmr "port_bindings_xfmr"; key "id"; description "List of interfaces on which ACLs are set"; From 64ad0059fb7b1fa8dbc454b595049acf92e22c41 Mon Sep 17 00:00:00 2001 From: Amruta Sali Date: Tue, 6 Aug 2019 06:35:14 -0700 Subject: [PATCH 013/214] Moved openconfig-acl-annot.yang to annotations directory and added Makefile rule to have it installed on target --- Makefile | 1 + .../openconfig-acl-annot.yang | 18 +++++++++--------- 2 files changed, 10 insertions(+), 9 deletions(-) rename models/yang/{ => annotations}/openconfig-acl-annot.yang (74%) diff --git a/Makefile b/Makefile index 857ad7c007..a64d21e6d3 100644 --- a/Makefile +++ b/Makefile @@ -101,6 +101,7 @@ install: $(INSTALL) -D $(TOPDIR)/src/cvl/schema/*.yang $(DESTDIR)/usr/models/yang/ $(INSTALL) -D $(TOPDIR)/models/yang/*.yang $(DESTDIR)/usr/models/yang/ $(INSTALL) -D $(TOPDIR)/models/yang/common/*.yang $(DESTDIR)/usr/models/yang/ + $(INSTALL) -D $(TOPDIR)/models/yang/annotations/*.yang $(DESTDIR)/usr/models/yang/ cp -rf $(TOPDIR)/build/rest_server/dist/ui/ $(DESTDIR)/rest_ui/ cp -rf $(TOPDIR)/build/cli $(DESTDIR)/usr/sbin/ cp -rf $(TOPDIR)/build/swagger_client_py/ $(DESTDIR)/usr/sbin/lib/ diff --git a/models/yang/openconfig-acl-annot.yang b/models/yang/annotations/openconfig-acl-annot.yang similarity index 74% rename from models/yang/openconfig-acl-annot.yang rename to models/yang/annotations/openconfig-acl-annot.yang index 159b5b96b8..d5363aa382 100644 --- a/models/yang/openconfig-acl-annot.yang +++ b/models/yang/annotations/openconfig-acl-annot.yang @@ -28,55 +28,55 @@ module openconfig-acl-annot { } } - deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-acl:ipv4/oc-acl:config/oc-acl:source-address { + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-pkt-match:ipv4/oc-pkt-match:config/oc-pkt-match:source-address { deviate add { sonic-ext:field-name "SRC_IP"; } } - deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-acl:ipv4/oc-acl:config/oc-acl:destination-address { + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-pkt-match:ipv4/oc-pkt-match:config/oc-pkt-match:destination-address { deviate add { sonic-ext:field-name "DST_IP"; } } - deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-acl:ipv4/oc-acl:config/oc-acl:protocol { + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-pkt-match:ipv4/oc-pkt-match:config/oc-pkt-match:protocol { deviate add { sonic-ext:field-transformer "acl_ip_protocol_xfmr"; } } - deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-acl:ipv6/oc-acl:config/oc-acl:source-address { + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-pkt-match:ipv6/oc-pkt-match:config/oc-pkt-match:source-address { deviate add { sonic-ext:field-name "SRC_IP"; } } - deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-acl:ipv6/oc-acl:config/oc-acl:destination-address { + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-pkt-match:ipv6/oc-pkt-match:config/oc-pkt-match:destination-address { deviate add { sonic-ext:field-name "DST_IP"; } } - deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-acl:ipv6/oc-acl:config/oc-acl:protocol { + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-pkt-match:ipv6/oc-pkt-match:config/oc-pkt-match:protocol { deviate add { sonic-ext:field-transformer "acl_ip_protocol_xfmr"; } } - deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-acl:transport/oc-acl:config/oc-acl:source-port { + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-pkt-match:transport/oc-pkt-match:config/oc-pkt-match:source-port { deviate add { sonic-ext:field-transformer "acl_source_port_xfmr"; } } - deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-acl:transport/oc-acl:config/oc-acl:destination-port { + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-pkt-match:transport/oc-pkt-match:config/oc-pkt-match:destination-port { deviate add { sonic-ext:field-transformer "acl_destination_port_xfmr"; } } - deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-acl:transport/oc-acl:config/oc-acl:tcp_flags { + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-pkt-match:transport/oc-pkt-match:config/oc-pkt-match:tcp_flags { deviate add { sonic-ext:field-transformer "acl_tcp_flags_xfmr"; } From 51f2528395e1accd2cf3b7dfff8d330050bd6363 Mon Sep 17 00:00:00 2001 From: Ravi Vasanthm Date: Tue, 6 Aug 2019 09:57:31 -0700 Subject: [PATCH 014/214] Fixed issue in passing the yang files list to transformer LoadYangModules method. --- src/translib/acl_app.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/translib/acl_app.go b/src/translib/acl_app.go index 15bb4a4916..5e257f6cca 100644 --- a/src/translib/acl_app.go +++ b/src/translib/acl_app.go @@ -100,7 +100,7 @@ func init() { log.Fatal("Adding model data to appinterface failed with error=", err) } - yangFiles := []string{transformer.YangPath + "openconfig-acl.yang", transformer.YangPath + "sonic-acl.yang"} + yangFiles := []string{"openconfig-acl.yang", "sonic-acl.yang"} log.Info("Init transformer yang files :", yangFiles) err = transformer.LoadYangModules(yangFiles...) if err != nil { From fe2bff15b1491e4f1b35dbed86c00fde7c76600a Mon Sep 17 00:00:00 2001 From: Amruta Sali Date: Tue, 6 Aug 2019 10:55:23 -0700 Subject: [PATCH 015/214] Excluded annotations directory from ocbindings Corrected path in acl annotations --- models/yang/annotations/openconfig-acl-annot.yang | 5 +++-- src/translib/ocbinds/oc.go | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/models/yang/annotations/openconfig-acl-annot.yang b/models/yang/annotations/openconfig-acl-annot.yang index d5363aa382..d52099b7cb 100644 --- a/models/yang/annotations/openconfig-acl-annot.yang +++ b/models/yang/annotations/openconfig-acl-annot.yang @@ -7,6 +7,7 @@ module openconfig-acl-annot { import sonic-extensions { prefix sonic-ext; } import openconfig-acl { prefix oc-acl; } + import openconfig-packet-match { prefix oc-pkt-match; } deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set { deviate add { @@ -76,13 +77,13 @@ module openconfig-acl-annot { } } - deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-pkt-match:transport/oc-pkt-match:config/oc-pkt-match:tcp_flags { + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-pkt-match:transport/oc-pkt-match:config/oc-pkt-match:tcp-flags { deviate add { sonic-ext:field-transformer "acl_tcp_flags_xfmr"; } } - deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-acl:actions/oc-acl:config/oc-acl:forwrding-action { + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-acl:actions/oc-acl:config/oc-acl:forwarding-action { deviate add { sonic-ext:field-name "PACKET_ACTION"; } diff --git a/src/translib/ocbinds/oc.go b/src/translib/ocbinds/oc.go index 91b532c907..e6946a4351 100644 --- a/src/translib/ocbinds/oc.go +++ b/src/translib/ocbinds/oc.go @@ -1,3 +1,3 @@ package ocbinds -//go:generate sh -c "/usr/local/go/bin/go run $BUILD_GOPATH/src/github.com/openconfig/ygot/generator/generator.go -generate_fakeroot -output_file ocbinds.go -package_name ocbinds -generate_fakeroot -fakeroot_name=device -compress_paths=false -exclude_modules ietf-interfaces -path . $(find ../../../models/yang -name '*.yang' | sort)" +//go:generate sh -c "/usr/local/go/bin/go run $BUILD_GOPATH/src/github.com/openconfig/ygot/generator/generator.go -generate_fakeroot -output_file ocbinds.go -package_name ocbinds -generate_fakeroot -fakeroot_name=device -compress_paths=false -exclude_modules ietf-interfaces -path . $(find ../../../models/yang -name '*.yang' -not -path '*yang/annotations/*' | sort)" From 0df904d6be639e6407763aac2cc23e7f3f31c43a Mon Sep 17 00:00:00 2001 From: Amruta Sali Date: Fri, 9 Aug 2019 13:46:10 -0700 Subject: [PATCH 016/214] Initial commit - Common app registration --- src/translib/common_app.go | 187 +++++++++++++++++++++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100644 src/translib/common_app.go diff --git a/src/translib/common_app.go b/src/translib/common_app.go new file mode 100644 index 0000000000..d4e7258da0 --- /dev/null +++ b/src/translib/common_app.go @@ -0,0 +1,187 @@ +package translib + +import ( +// "bytes" + "errors" + "fmt" + log "github.com/golang/glog" +// "github.com/openconfig/ygot/util" + "github.com/openconfig/ygot/ygot" + "reflect" +// "strconv" +// "strings" + "translib/db" + //"translib/ocbinds" + "translib/transformer" +) + +var ( + +) +type CommonApp struct { + path string + ygotRoot *ygot.GoStruct + ygotTarget *interface{} +} + +func init() { + + // @todo : Optimize to register supported paths/yang via common app and report error for unsupported + register_model_path := []string{"/sonic-"} // register yang model path(s) to be supported via common app + for _, mdl_pth := range register_model_path { + err := register(mdl_pth, + &appInfo{appType: reflect.TypeOf(CommonApp{}), + ygotRootType: nil, //interface{}, + isNative: false, + tablesToWatch: nil}) + + if err != nil { + log.Fatal("Register Common app module with App Interface failed with error=", err, "for path=", mdl_pth) + } + } + + // @todo : Add support for all yang models that will use common app + //err = addModel(&ModelData{}) + yangFiles := []string{"sonic-acl.yang"} + log.Info("Init transformer yang files :", yangFiles) + err := transformer.LoadYangModules(yangFiles...) + if err != nil { + log.Fatal("Common App - Transformer call for loading yang modules failed with error=", err) + } +} + +func (app *CommonApp) initialize(data appData) { + log.Info("initialize:path =", data.path) + *app = CommonApp{path: data.path, ygotRoot: data.ygotRoot, ygotTarget: data.ygotTarget} + +} + +func (app *CommonApp) translateCreate(d *db.DB) ([]db.WatchKeys, error) { + var err error + var keys []db.WatchKeys + log.Info("translateCreate:path =", app.path) + + keys, err = app.translateCRUCommon(d, CREATE) + + return keys, err +} + +func (app *CommonApp) translateUpdate(d *db.DB) ([]db.WatchKeys, error) { + var err error + var keys []db.WatchKeys + log.Info("translateUpdate:path =", app.path) + + keys, err = app.translateCRUCommon(d, UPDATE) + + return keys, err +} + +func (app *CommonApp) translateReplace(d *db.DB) ([]db.WatchKeys, error) { + var err error + var keys []db.WatchKeys + log.Info("translateReplace:path =", app.path) + + //keys, err = app.translateCRUCommon(d, REPLACE) + + err = errors.New("Not implemented") + return keys, err +} + +func (app *CommonApp) translateDelete(d *db.DB) ([]db.WatchKeys, error) { + var err error + var keys []db.WatchKeys + log.Info("translateDelete:path =", app.path) + + keys, err = app.generateDbWatchKeys(d, true) + + return keys, err +} + +func (app *CommonApp) translateGet(dbs [db.MaxDB]*db.DB) error { + var err error + log.Info("translateGet:path =", app.path) + return err +} + +func (app *CommonApp) translateSubscribe(dbs [db.MaxDB]*db.DB, path string) (*notificationOpts, *notificationInfo, error) { + err := errors.New("Not supported") + //configDb := dbs[db.ConfigDB] + //pathInfo := NewPathInfo(path) + notifInfo := notificationInfo{dbno: db.ConfigDB} + return nil, ¬ifInfo, err +} + +func (app *CommonApp) processCreate(d *db.DB) (SetResponse, error) { + var err error + var resp SetResponse + + log.Info("processCreate:path =", app.path) + targetType := reflect.TypeOf(*app.ygotTarget) + log.Infof("processCreate: Target object is a <%s> of Type: %s", targetType.Kind().String(), targetType.Elem().Name()) + + + return resp, err +} + +func (app *CommonApp) processUpdate(d *db.DB) (SetResponse, error) { + var err error + var resp SetResponse + log.Info("processUpdate:path =", app.path) + + return resp, err +} + +func (app *CommonApp) processReplace(d *db.DB) (SetResponse, error) { + var err error + var resp SetResponse + log.Info("processReplace:path =", app.path) + err = errors.New("Not implemented") + return resp, err +} + +func (app *CommonApp) processDelete(d *db.DB) (SetResponse, error) { + var err error + var resp SetResponse + + log.Info("processDelete:path =", app.path) + + //aclObj := app.getAppRootObject() + + //targetUriPath, err := getYangPathFromUri(app.path) + + + return resp, err +} + +func (app *CommonApp) processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error) { + var err error + var payload []byte + + return GetResponse{Payload: payload}, err +} + +func (app *CommonApp) translateCRUCommon(d *db.DB, opcode int) ([]db.WatchKeys, error) { + var err error + var keys []db.WatchKeys + log.Info("translateCRUCommon:path =", app.path) + + // translate yang to db + result, err := transformer.XlateToDb((*app).ygotRoot, (*app).ygotTarget) + fmt.Println(result) + + if err != nil { + log.Error(err) + return keys, err + } + + keys, err = app.generateDbWatchKeys(d, false) + + return keys, err +} + +func (app *CommonApp) generateDbWatchKeys(d *db.DB, isDeleteOp bool) ([]db.WatchKeys, error) { + var err error + var keys []db.WatchKeys + + return keys, err +} From 23196f6fc50f6ecc036d7e72e4e2864c186810fd Mon Sep 17 00:00:00 2001 From: s-mari Date: Fri, 9 Aug 2019 15:15:14 -0700 Subject: [PATCH 017/214] Transformer spec enhancement, oc yang & cvl yang incoming request handler. --- src/translib/transformer/transformer.go | 2 +- src/translib/transformer/xlate.go | 5 + src/translib/transformer/xlateToDb.go | 195 +++++++++++++++++++ src/translib/transformer/xlate_utils.go | 51 +++++ src/translib/transformer/xspec.go | 245 ++++++++++++++++++------ 5 files changed, 443 insertions(+), 55 deletions(-) create mode 100644 src/translib/transformer/xlateToDb.go create mode 100644 src/translib/transformer/xlate_utils.go diff --git a/src/translib/transformer/transformer.go b/src/translib/transformer/transformer.go index b2b7875200..d353b06061 100644 --- a/src/translib/transformer/transformer.go +++ b/src/translib/transformer/transformer.go @@ -78,7 +78,7 @@ func LoadYangModules(files ...string) error { entries[n] = yang.ToEntry(mods[n]) } } - mapBuild(entries) + mapBuild(entries) // TODO - build the inverse map for GET, from OC to Sonic diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index 7609e5bc65..df76887b95 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -70,7 +70,12 @@ func XlateToDb(s *ygot.GoStruct, t *interface{}) (map[string]map[string]db.Value // table.key.fields var result = make(map[string]map[string]db.Value) + err = dbMapCreate("", "/openconfig-acl:acl", jsonStr, result) + if err != nil { + log.Errorf("Error: Data translation from yang to db failed.") + return result, err + } // TODO - traverse ygot/JSON with the metadata to translate to DB // xfmr method dynamically invoked diff --git a/src/translib/transformer/xlateToDb.go b/src/translib/transformer/xlateToDb.go new file mode 100644 index 0000000000..e157f25ac0 --- /dev/null +++ b/src/translib/transformer/xlateToDb.go @@ -0,0 +1,195 @@ +package transformer + +import ( + "fmt" + "translib/db" + "os" + "reflect" + "regexp" + "strings" + "errors" + + log "github.com/golang/glog" +) + +/* Fill the redis-db map with data */ +func mapFillData(dbKey string, result map[string]map[string]db.Value, xpathPrefix string, name string, value string) error { + xpath := xpathPrefix + "/" + name + xpathInfo := xSpecMap[xpath] + log.Info("name: \"%v\", xpathPrefix(\"%v\").", name, xpathPrefix) + + if xpathInfo == nil { + log.Errorf("Yang path(\"%v\") not found.", xpath) + return errors.New("Invalid URI") + } + + if xpathInfo.tableName == nil { + log.Errorf("Table for yang-path(\"%v\") not found.", xpath) + return errors.New("Invalid table name") + } + + if len(dbKey) == 0 { + log.Errorf("Table key for yang path(\"%v\") not found.", xpath) + return errors.New("Invalid table key") + } + + if len(xpathInfo.fieldName) == 0 { + log.Info("Field for yang-path(\"%v\") not found in DB.", xpath) + return errors.New("Invalid field name") + } + fieldName := xpathInfo.fieldName + + if len(xpathInfo.xfmrFunc) > 0 { + log.Info("Transformer function(\"%v\") invoked for yang path(\"%v\").", xpathInfo.xfmrFunc, xpath) + //fieldName[] = XlateFuncCall(xpathInfo.xfmrFunc, name, value) + //return errors.New("Invalid field name") + return nil + } + + _, ok := result[*xpathInfo.tableName] + if !ok { + result[*xpathInfo.tableName] = make(map[string]db.Value) + } + + _, ok = result[*xpathInfo.tableName][dbKey] + if !ok { + result[*xpathInfo.tableName][dbKey] = db.Value{Field: make(map[string]string)} + } + + result[*xpathInfo.tableName][dbKey].Field[fieldName] = value + log.Info("TblName: \"%v\", key: \"%v\", field: \"%v\", value: \"%v\".", + *xpathInfo.tableName, dbKey, fieldName, value) + return nil +} + +func callXfmr() map[string]map[string]db.Value { + result := make(map[string]map[string]db.Value) + result["ACL_TABLE"] = make(map[string]db.Value) + result["ACL_TABLE"]["MyACL1_ACL_IPV4"] = db.Value{Field: make(map[string]string)} + result["ACL_TABLE"]["MyACL1_ACL_IPV4"].Field["stage"] = "INGRESS" + result["ACL_TABLE"]["MyACL1_ACL_IPV4"].Field["ports@"] = "Ethernet0" + result["ACL_TABLE"]["MyACL2_ACL_IPV4"] = db.Value{Field: make(map[string]string)} + result["ACL_TABLE"]["MyACL2_ACL_IPV4"].Field["stage"] = "INGRESS" + result["ACL_TABLE"]["MyACL2_ACL_IPV4"].Field["ports@"] = "Ethernet4" + return result +} + +func directDbMapData(tableName string, jsonData interface{}, result map[string]map[string]db.Value) bool { + dbSpecData, ok := xDbSpecMap[tableName] + + if ok && reflect.ValueOf(jsonData).Kind() == reflect.Slice { + tblKeyName := strings.Split(dbSpecData.Key, " ") + data := reflect.ValueOf(jsonData) + keyName := "" + result[tableName] = make(map[string]db.Value) + + for idx := 0; idx < data.Len(); idx++ { + d := data.Index(idx).Interface().(map[string]interface{}) + for i, k := range tblKeyName { + if i > 0 { keyName += "|" } + keyName += fmt.Sprintf("%v", d[k]) + delete(d, k) + } + + result[tableName][keyName] = db.Value{Field: make(map[string]string)} + for field, value := range d { + result[tableName][keyName].Field[field] = fmt.Sprintf("%v", value) + } + } + return true + } + return false +} + +/* Get the data from incoming request, create map and fill with dbValue(ie. field:value + to write into redis-db */ +func dbMapCreate(keyName string, xpathPrefix string, jsonData interface{}, result map[string]map[string]db.Value) error { + log.Info("key(\"%v\"), xpathPrefix(\"%v\").", keyName, xpathPrefix) + + if reflect.ValueOf(jsonData).Kind() == reflect.Slice { + log.Info("slice data: key(\"%v\"), xpathPrefix(\"%v\").", keyName, xpathPrefix) + jData := reflect.ValueOf(jsonData) + dataMap := make([]interface{}, jData.Len()) + for idx := 0; idx < jData.Len(); idx++ { + dataMap[idx] = jData.Index(idx).Interface() + } + for _, data := range dataMap { + keyName := keyCreate(keyName, xpathPrefix, data) + return dbMapCreate(keyName, xpathPrefix, data, result) + } + } else { + if reflect.ValueOf(jsonData).Kind() == reflect.Map { + jData := reflect.ValueOf(jsonData) + for _, key := range jData.MapKeys() { + typeOfValue := reflect.TypeOf(jData.MapIndex(key).Interface()).Kind() + + if typeOfValue == reflect.Map || typeOfValue == reflect.Slice { + log.Info("slice/map data: key(\"%v\"), xpathPrefix(\"%v\").", keyName, xpathPrefix) + if directDbMapData(key.String(), jData.MapIndex(key).Interface(), result) { + continue + } else { + xpath := xpathPrefix + "/" + key.String() + + if len(xSpecMap[xpath].xfmrFunc) > 0 { + subMap := callXfmr() + //subMap := XlateFuncCall(xpathInfo.xfmrFunc, name, value) + mapCopy(result, subMap) + return nil + } else { + return dbMapCreate(keyName, xpath, jData.MapIndex(key).Interface(), result) + } + } + } else { + value := jData.MapIndex(key).Interface() + log.Info("data field: key(\"%v\"), value(\"%v\").", key, value) + err := mapFillData(keyName, result, xpathPrefix, key.String(), fmt.Sprintf("%v", value)) + log.Errorf("Failed constructing data for db write: key(\"%v\"), value(\"%v\"), path(\"%v\").", key, value, xpathPrefix) + return err + } + } + } + } + return nil +} + +/* Extract key vars, create db key and xpath */ +func xpathKeyExtract(path string) (string, string) { + yangXpath := "" + keyStr := "" + rgp := regexp.MustCompile(`\[(.*?)\]`) + for i, k := range (strings.Split(path, "/")) { + if i > 0 { yangXpath += "/" } + xpath := k + if strings.Contains(k, "[") { + kval := keyFromXpathCreate(rgp.FindStringSubmatch(k)[1]) + xpath = strings.Split(k, "[")[0] + if len(keyStr) > 0 { keyStr += "|" } + keyStr += kval + } + yangXpath += xpath + } + + return yangXpath, keyStr +} + +/* Debug function to print the map data into file */ +func printDbData (db map[string]map[string]db.Value, fileName string) { + fp, err := os.Create(fileName) + if err != nil { + return + } + defer fp.Close() + + for k, v := range db { + fmt.Fprintf (fp, "-----------------------------------------------------------------\r\n") + fmt.Fprintf(fp, "table name : %v\r\n", k) + for ik, iv := range v { + fmt.Fprintf(fp, " key : %v\r\n", ik) + for k, d := range iv.Field { + fmt.Fprintf(fp, " %v :%v\r\n", k, d) + } + } + } + fmt.Fprintf (fp, "-----------------------------------------------------------------\r\n") + return +} diff --git a/src/translib/transformer/xlate_utils.go b/src/translib/transformer/xlate_utils.go new file mode 100644 index 0000000000..c532622b8c --- /dev/null +++ b/src/translib/transformer/xlate_utils.go @@ -0,0 +1,51 @@ +package transformer + +import ( + "fmt" + "strings" + "translib/db" +) + +/* Create db key from datd xpath(request) */ +func keyFromXpathCreate(keys string) string { + keyOut := "" + for i, k := range (strings.Split(keys, " ")) { + if i > 0 { keyOut += "_" } + keyOut += strings.Split(k, "=")[1] + } + return keyOut +} + +/* Create db key from datd xpath(request) */ +func keyCreate(keyPrefix string, xpath string, data interface{}) string { + yangEntry := xSpecMap[xpath].yangEntry + if len(keyPrefix) > 0 { keyPrefix += "|" } + + keyVal := "" + for i, k := range (strings.Split(yangEntry.Key, " ")) { + if i > 0 { keyVal = keyVal + "_" } + keyVal += fmt.Sprintf("%v", data.(map[string]interface{})[k]) + } + keyPrefix += string(keyVal) + return keyPrefix +} + +/* Copy redis-db source to destn map */ +func mapCopy(destnMap map[string]map[string]db.Value, srcMap map[string]map[string]db.Value) { + for table, tableData := range srcMap { + _, ok := destnMap[table] + if !ok { + destnMap[table] = make(map[string]db.Value) + } + for rule, ruleData := range tableData { + _, ok = destnMap[table][rule] + if !ok { + destnMap[table][rule] = db.Value{Field: make(map[string]string)} + } + for field, value := range ruleData.Field { + destnMap[table][rule].Field[field] = value + } + } + } +} + diff --git a/src/translib/transformer/xspec.go b/src/translib/transformer/xspec.go index 1614ec4dc7..98eeabbb4a 100644 --- a/src/translib/transformer/xspec.go +++ b/src/translib/transformer/xspec.go @@ -1,4 +1,5 @@ package transformer + import ( "fmt" "os" @@ -10,51 +11,60 @@ import ( /* Data needed to construct lookup table from yang */ type yangXpathInfo struct { - children *[]string yangDataType string tableName *string + dbEntry *yang.Entry + yangEntry *yang.Entry keyXpath map[int]*[]string - delim *[]string + delim string fieldName string xfmrFunc string + xfmrKey string } var xSpecMap map[string]*yangXpathInfo +var xDbSpecMap map[string]*yang.Entry + +/* update transformer spec with db-node */ +func updateDbTableData (xpathData *yangXpathInfo, tableName string) { + _, ok := xDbSpecMap[tableName] + if ok { + xpathData.dbEntry = xDbSpecMap[tableName] + } +} /* Recursive api to fill the map with yang details */ func fillMap (xSpecMap map[string]*yangXpathInfo, entry *yang.Entry, xpathPrefix string) { + xpath := "" + /* create the yang xpath */ + if xSpecMap[xpathPrefix] != nil && xSpecMap[xpathPrefix].yangDataType == "module" { + /* module name is separated from the rest of xpath with ":" */ + xpath = xpathPrefix + ":" + entry.Name + } else { + xpath = xpathPrefix + "/" + entry.Name + } - xpath := xpathPrefix + "/" + entry.Name - xpathData := new(yangXpathInfo) + xpathData, ok := xSpecMap[xpath] + if !ok { + xpathData = new(yangXpathInfo) + xSpecMap[xpath] = xpathData + } else { + xpathData = xSpecMap[xpath] + } + xpathData.yangDataType = entry.Node.Statement().Keyword parentXpathData, ok := xSpecMap[xpathPrefix] /* init current xpath table data with its parent data, change only if needed. */ - if ok { + if ok && xpathData.tableName == nil && parentXpathData.tableName != nil { xpathData.tableName = parentXpathData.tableName } - /* fill yang data type i.e. module, container, list, leaf etc. */ - xpathData.yangDataType = entry.Node.Statement().Keyword - - inheritParentKey := true - /* fill table with yang extension data. */ - if len(entry.Exts) > 0 { - for _, ext := range entry.Exts { - dataTagArr := strings.Split(ext.Kind(), ":") - tagType := dataTagArr[len(dataTagArr)-1] - switch tagType { - case "redis-table-name" : - xpathData.tableName = new(string) - *xpathData.tableName = ext.NName() - case "redis-field-name" : - xpathData.fieldName = ext.NName() - case "xfmr" : - xpathData.xfmrFunc = ext.NName() - case "use-self-key" : - xpathData.keyXpath = nil - inheritParentKey = false - } - } + if xpathData.yangDataType == "leaf" && len(xpathData.fieldName) == 0 { + if xpathData.tableName != nil && xDbSpecMap[*xpathData.tableName] != nil && + (xDbSpecMap[*xpathData.tableName].Dir[entry.Name] != nil || + xDbSpecMap[*xpathData.tableName].Dir[strings.ToUpper(entry.Name)] != nil) { + xpathData.fieldName = strings.ToUpper(entry.Name) + } } /* fill table with key data. */ @@ -62,15 +72,10 @@ func fillMap (xSpecMap map[string]*yangXpathInfo, entry *yang.Entry, xpathPrefix parentKeyLen := 0 /* create list with current keys */ - keyXpath := make([]string, len(strings.Split(entry.Key, " "))) + keyXpath := make([]string, len(strings.Split(entry.Key, " "))) for id, keyName := range(strings.Split(entry.Key, " ")) { keyXpath[id] = xpath + "/" + keyName } - if inheritParentKey { - /* init parentKeyLen to the number of parent-key list */ - parentKeyLen = len(parentXpathData.keyXpath) - } - xpathData.keyXpath = make(map[int]*[]string, (parentKeyLen + 1)) k := 0 for ; k < parentKeyLen; k++ { @@ -87,62 +92,194 @@ func fillMap (xSpecMap map[string]*yangXpathInfo, entry *yang.Entry, xpathPrefix for k := range entry.Dir { childList = append(childList, k) } - sort.Strings(childList) - - /* copy children of current obj */ - if len(childList) > 0 { - children := make([]string, len(entry.Dir)) - copy(children, childList) - xpathData.children = &children - } - /* update yang-map with xpath and table info. */ - xSpecMap[xpath] = xpathData + sort.Strings(childList) + xpathData.yangEntry = entry /* now recurse, filling the map with current node's children info */ for _, child := range childList { fillMap(xSpecMap, entry.Dir[child], xpath) } } -/* Build lookup hash table based of yang xpath */ +/* Build lookup table based of yang xpath */ func mapBuild(entries map[string]*yang.Entry) { if entries == nil { return } - xSpecMap = make(map[string]*yangXpathInfo) for _, e := range entries { - if len(e.Dir) == 0 { + if e == nil || len(e.Dir) == 0 { continue } /* Start to fill xpath based map with yang data */ fillMap(xSpecMap, e, "") } - mapPrint(xSpecMap) + mapPrint(xSpecMap, "/tmp/fullSpec.txt") } -/* Debug function to print the map data into file */ -func mapPrint(inMap map[string]*yangXpathInfo) { - fp, err := os.Create("/tmp/xspec.txt") - if err != nil { - return +/* Fill the map with db details */ +func fillDbMap (xDbSpecMap map[string]*yang.Entry, entry *yang.Entry) { + entryType := entry.Node.Statement().Keyword + if entryType == "list" { + xDbSpecMap[entry.Name] = entry + } + + var childList []string + for k := range entry.Dir { + childList = append(childList, k) + } + sort.Strings(childList) + for _, child := range childList { + fillDbMap(xDbSpecMap, entry.Dir[child]) + } +} + +/* Build redis db lookup map */ +func dbMapBuild(entries []*yang.Entry) { + if entries == nil { + return + } + xDbSpecMap = make(map[string]*yang.Entry) + + for _, e := range entries { + if e == nil || len(e.Dir) == 0 { + continue } + fillDbMap(xDbSpecMap, e) + } + dbMapPrint(xSpecMap) +} + +/* Build lookup map based on yang xpath */ +func annotEntryFill(xSpecMap map[string]*yangXpathInfo, xpath string, entry *yang.Entry) { + xpathData := new(yangXpathInfo) + _, ok := xSpecMap[xpath] + if !ok { + fmt.Printf("Xpath not found(%v) \r\n", xpath) + } + + /* fill table with yang extension data. */ + if len(entry.Exts) > 0 { + for _, ext := range entry.Exts { + dataTagArr := strings.Split(ext.Keyword, ":") + tagType := dataTagArr[len(dataTagArr)-1] + switch tagType { + case "table-name" : + if xpathData.tableName == nil { + xpathData.tableName = new(string) + } + *xpathData.tableName = ext.NName() + updateDbTableData(xpathData, ext.NName()) + case "field-name" : + xpathData.fieldName = ext.NName() + case "subtree-transformer" : + xpathData.xfmrFunc = ext.NName() + case "key-transformer" : + xpathData.xfmrKey = ext.NName() + case "key-delimiter" : + xpathData.delim = ext.NName() + case "field-transformer" : + xpathData.xfmrFunc = ext.NName() + case "post-transformer" : + xpathData.xfmrFunc = ext.NName() + case "use-self-key" : + xpathData.keyXpath = nil + } + } + } + xSpecMap[xpath] = xpathData +} + +/* Build xpath from yang-annotation */ +func xpathFromDevCreate(path string) string { + xpath := "" + for _, k := range (strings.Split(path, "/")) { + if len(k) > 0 { + xpath += strings.Split(k, ":")[1] + "/" + } + } + return xpath[:len(xpath)-1] +} + +/* Build lookup map based on yang xpath */ +func yangToDbMapBuilt(annotEntries []*yang.Entry) { + if annotEntries == nil { + return + } + + xSpecMap = make(map[string]*yangXpathInfo) + for _, e := range annotEntries { + if e != nil && len(e.Deviations) > 0 { + for _, d := range e.Deviations { + xpath := xpathFromDevCreate(d.Name) + xpath = "/" + strings.Replace(e.Name, "-annot", "", -1) + ":" + xpath + for i, deviate := range d.Deviate { + if i == 2 { + for _, ye := range deviate { + fmt.Println(ye.Name) + fmt.Printf(" Annot fill:(%v)\r\n", xpath) + annotEntryFill(xSpecMap, xpath, ye) + } + } + } + } + } + } + mapPrint(xSpecMap, "/tmp/annotSpec.txt") +} + +/* Debug function to print the yang xpath lookup map */ +func mapPrint(inMap map[string]*yangXpathInfo, fileName string) { + fp, err := os.Create(fileName) + if err != nil { + return + } defer fp.Close() for k, d := range inMap { fmt.Fprintf (fp, "-----------------------------------------------------------------\r\n") fmt.Fprintf(fp, "%v:\r\n", k) - fmt.Fprintf(fp, " yangDataType: %v", d.yangDataType) + fmt.Fprintf(fp, " yangDataType: %v\r\n", d.yangDataType) fmt.Fprintf(fp, " tableName: ") if d.tableName != nil { fmt.Fprintf(fp, "%v", *d.tableName) } + fmt.Fprintf(fp, "\r\n FieldName: ") + if len(d.fieldName) > 0 { + fmt.Fprintf(fp, "%v", d.fieldName) + } + fmt.Fprintf(fp, "\r\n keyXfmr: ") + if d.dbEntry != nil { + fmt.Fprintf(fp, "%v\r\n", d.xfmrKey) + } + fmt.Fprintf(fp, "\r\n SubTreeXfmr: ") + if d.dbEntry != nil { + fmt.Fprintf(fp, "%v\r\n", d.xfmrFunc) + } + fmt.Fprintf(fp, "\r\n yangEntry: ") + if d.dbEntry != nil { + fmt.Fprintf(fp, "%v", *d.yangEntry) + } + fmt.Fprintf(fp, "\r\n dbEntry: ") + if d.dbEntry != nil { + fmt.Fprintf(fp, "%v", *d.dbEntry) + } fmt.Fprintf(fp, "\r\n keyXpath: %d\r\n", d.keyXpath) for i, kd := range d.keyXpath { fmt.Fprintf(fp, " %d. %#v\r\n", i, kd) } - fmt.Fprintf(fp, " children (%p : %v)\r\n", d.children, d.children) } fmt.Fprintf (fp, "-----------------------------------------------------------------\r\n") } + +/* Debug function to print redis db lookup map */ +func dbMapPrint(inMap map[string]*yangXpathInfo) { + fp, err := os.Create("/tmp/dbTmplt.txt") + if err != nil { + return + } + defer fp.Close() + fmt.Fprintf(fp, "%v", xDbSpecMap) +} + From 5a8b43dacb64e02de9aab9f135bf6f813d2893cb Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Fri, 9 Aug 2019 15:34:12 -0700 Subject: [PATCH 018/214] Extend goyang to generate template annotation file --- Makefile | 6 +- goyang-modified-files/README.md | 50 +++++++ goyang-modified-files/annotate.go | 143 ++++++++++++++++++++ goyang-modified-files/yang.go | 216 ++++++++++++++++++++++++++++++ 4 files changed, 414 insertions(+), 1 deletion(-) create mode 100644 goyang-modified-files/README.md create mode 100644 goyang-modified-files/annotate.go create mode 100644 goyang-modified-files/yang.go diff --git a/Makefile b/Makefile index a64d21e6d3..4759dcdfd2 100644 --- a/Makefile +++ b/Makefile @@ -89,7 +89,11 @@ cp $(TOPDIR)/ygot-modified-files/schema.go $(BUILD_GOPATH)/src/github.com/openco cp $(TOPDIR)/ygot-modified-files/unmarshal.go $(BUILD_GOPATH)/src/github.com/openconfig/ygot/ytypes/unmarshal.go; \ cp $(TOPDIR)/ygot-modified-files/validate.go $(BUILD_GOPATH)/src/github.com/openconfig/ygot/ytypes/validate.go; \ cp $(TOPDIR)/ygot-modified-files/reflect.go $(BUILD_GOPATH)/src/github.com/openconfig/ygot/ytypes/../util/reflect.go; \ -$(GO) install -v -gcflags "-N -l" $(BUILD_GOPATH)/src/github.com/openconfig/ygot/ygot +cp $(TOPDIR)/goyang-modified-files/README.md $(BUILD_GOPATH)/src/github.com/openconfig/goyang/README.md; \ +cp $(TOPDIR)/goyang-modified-files/yang.go $(BUILD_GOPATH)/src/github.com/openconfig/goyang/yang.go; \ +cp $(TOPDIR)/goyang-modified-files/annotate.go $(BUILD_GOPATH)/src/github.com/openconfig/goyang/annotate.go; \ +$(GO) install -v -gcflags "-N -l" $(BUILD_GOPATH)/src/github.com/openconfig/ygot/ygot; \ +$(GO) install -v -gcflags "-N -l" $(BUILD_GOPATH)/src/github.com/openconfig/goyang install: $(INSTALL) -D $(REST_BIN) $(DESTDIR)/usr/sbin/rest_server diff --git a/goyang-modified-files/README.md b/goyang-modified-files/README.md new file mode 100644 index 0000000000..805adb59b7 --- /dev/null +++ b/goyang-modified-files/README.md @@ -0,0 +1,50 @@ +# goyang +YANG parser and compiler for Go programs. + +The yang package (pkg/yang) is used to convert a YANG schema into either an +in memory abstract syntax trees (ast) or more fully resolved, in memory, "Entry" +trees. An Entry tree consists only of Entry structures and has had +augmentation, imports, and includes all applied. + +goyang is a sample program that uses the yang (pkg/yang) package. + +goyang uses the yang package to create an in-memory tree representation of +schemas defined in YANG and then dumps out the contents in several forms. +The forms include: + +* tree - a simple tree representation +* types - list understood types extracted from the schema +* annotate - a template file to annotate the yang modules + +The yang package, and the goyang program, are not complete and are a work in +progress. + +For more complex output types, such as Go structs, and protobuf messages +please use the [openconfig/ygot](https://github.com/openconfig/ygot) package, +which uses this package as its backend. + +### Getting started + +To build goyang, ensure you have go language tools installed +(available at [golang.org](https://golang.org/dl)) and that the `GOPATH` +environment variable is set to your Go workspace. + +1. `go get github.com/openconfig/goyang` + * This will download goyang code and dependencies into the src +subdirectory in your workspace. + +2. `cd /src/github.com/openconfig/goyang` + +3. `go build` + + * This will build the goyang binary and place it in the bin +subdirectory in your workspace. + +### Contributing to goyang + +goyang is still a work-in-progress and we welcome contributions. Please see +the `CONTRIBUTING` file for information about how to contribute to the codebase. + +### Disclaimer + +This is not an official Google product. diff --git a/goyang-modified-files/annotate.go b/goyang-modified-files/annotate.go new file mode 100644 index 0000000000..47237b4e15 --- /dev/null +++ b/goyang-modified-files/annotate.go @@ -0,0 +1,143 @@ +// Copyright 2015 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "fmt" + "io" + "strings" + + "github.com/openconfig/goyang/pkg/yang" +) + +var allimports = make(map[string]string) +var modules = make(map[string]*yang.Module) + +func init() { + register(&formatter{ + name: "annotate", + f: genAnnotate, + utilf: getFile, + help: "generate template file for yang annotations", + }) +} + +// Get the modules for which annotation file needs to be generated +func getFile(files []string, mods map[string]*yang.Module) { + for _, name := range files { + slash := strings.Split(name, "/") + if strings.HasSuffix(name, ".yang") { + modname := slash[len(slash)-1] + modname = strings.TrimSuffix(modname, ".yang"); + /* Save the yang.Module entries we are interested in */ + modules[modname] = mods[modname] + } + } +} + +func genAnnotate(w io.Writer, entries []*yang.Entry) { + /* Get all the imported modules in the entries */ + GetAllImports(entries) + for _, e := range entries { + if _, ok := modules[e.Name]; ok { + var path string = "" + generate(w, e, path) + // { Add closing brace for each module + fmt.Fprintln(w, "}") + fmt.Fprintln(w) + } + } +} + +// generate writes to stdoutput a template annotation file entry for the selected modules. +func generate(w io.Writer, e *yang.Entry, path string) { + if e.Parent == nil { + if e.Name != "" { + fmt.Fprintf(w, "module %s-annot {\n", e.Name) //} + fmt.Fprintln(w) + fmt.Fprintf(w, " yang-version \"%s\"\n", getYangVersion(e.Name, modules)) + fmt.Fprintln(w) + fmt.Fprintf(w, " namespace \"http://openconfig.net/yang/annotation\";\n") + if e.Prefix != nil { + fmt.Fprintf(w, " prefix \"%s-annot\" \n", e.Prefix.Name) + } + fmt.Fprintln(w) + + var imports = make(map[string]string) + imports = getImportModules(e.Name, modules) + for k := range imports { + if e.Name != k { + fmt.Fprintf(w, " import %s { prefix %s }\n", k, allimports[k]) + } + } + + fmt.Fprintln(w) + } + } + + name := e.Name + if e.Prefix != nil { + name = e.Prefix.Name + ":" + name + } + + delim := "" + if path != "" { + delim = "/" + } + path = path + delim + name + + fmt.Fprintf(w, " deviation %s {\n", path) + fmt.Fprintf(w, " deviate add {\n") + fmt.Fprintf(w, " }\n") + fmt.Fprintf(w, " }\n") + fmt.Fprintln(w) + + var names []string + for k := range e.Dir { + names = append(names, k) + } + + for _, k := range names { + generate(w, e.Dir[k], path) + } + +} + +// Save to map all imported modules +func GetAllImports(entries []*yang.Entry) { + for _, e := range entries { + allimports[e.Name] = e.Prefix.Name + } +} + +//Get Yang version from the yang.Modules +func getYangVersion(modname string, mods map[string]*yang.Module) string { + if (mods[modname].YangVersion != nil) { + return mods[modname].YangVersion.Name + } + return "" + +} + +// Get imported modules for a given module from yang.Module +func getImportModules(modname string, mods map[string]*yang.Module) map[string]string { + imports := map[string]string{} + if (mods[modname].Import != nil) { + for _, imp := range mods[modname].Import { + imports[imp.Name] = imp.Prefix.Name + } + } + return imports +} diff --git a/goyang-modified-files/yang.go b/goyang-modified-files/yang.go new file mode 100644 index 0000000000..515d1b33b0 --- /dev/null +++ b/goyang-modified-files/yang.go @@ -0,0 +1,216 @@ +// Copyright 2015 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Program yang parses YANG files, displays errors, and possibly writes +// something related to the input on output. +// +// Usage: yang [--path DIR] [--format FORMAT] [FORMAT OPTIONS] [MODULE] [FILE ...] +// +// If MODULE is specified (an argument that does not end in .yang), it is taken +// as the name of the module to display. Any FILEs specified are read, and the +// tree for MODULE is displayed. If MODULE was not defined in FILEs (or no +// files were specified), then the file MODULES.yang is read as well. An error +// is displayed if no definition for MODULE was found. +// +// If MODULE is missing, then all base modules read from the FILEs are +// displayed. If there are no arguments then standard input is parsed. +// +// If DIR is specified, it is considered a comma separated list of paths +// to append to the search directory. If DIR appears as DIR/... then +// DIR and all direct and indirect subdirectories are checked. +// +// FORMAT, which defaults to "tree", specifes the format of output to produce. +// Use "goyang --help" for a list of available formats. +// +// FORMAT OPTIONS are flags that apply to a specific format. They must follow +// --format. +// +// THIS PROGRAM IS STILL JUST A DEVELOPMENT TOOL. +package main + +import ( + "fmt" + "io" + "io/ioutil" + "os" + "runtime/trace" + "sort" + "strings" + + "github.com/openconfig/goyang/pkg/indent" + "github.com/openconfig/goyang/pkg/yang" + "github.com/pborman/getopt" +) + +// Each format must register a formatter with register. The function f will +// be called once with the set of yang Entry trees generated. +type formatter struct { + name string + f func(io.Writer, []*yang.Entry) + utilf func([]string, map[string]*yang.Module) + help string + flags *getopt.Set +} + +var formatters = map[string]*formatter{} + +func register(f *formatter) { + formatters[f.name] = f +} + +// exitIfError writes errs to standard error and exits with an exit status of 1. +// If errs is empty then exitIfError does nothing and simply returns. +func exitIfError(errs []error) { + if len(errs) > 0 { + for _, err := range errs { + fmt.Fprintln(os.Stderr, err) + } + stop(1) + } +} + +var stop = os.Exit + +func main() { + var format string + formats := make([]string, 0, len(formatters)) + for k := range formatters { + formats = append(formats, k) + } + sort.Strings(formats) + + var traceP string + var help bool + var paths []string + getopt.ListVarLong(&paths, "path", 0, "comma separated list of directories to add to search path", "DIR[,DIR...]") + getopt.StringVarLong(&format, "format", 0, "format to display: "+strings.Join(formats, ", "), "FORMAT") + getopt.StringVarLong(&traceP, "trace", 0, "write trace into to TRACEFILE", "TRACEFILE") + getopt.BoolVarLong(&help, "help", '?', "display help") + getopt.BoolVarLong(&yang.ParseOptions.IgnoreSubmoduleCircularDependencies, "ignore-circdep", 0, "ignore circular dependencies between submodules") + getopt.SetParameters("[FORMAT OPTIONS] [SOURCE] [...]") + + if err := getopt.Getopt(func(o getopt.Option) bool { + if o.Name() == "--format" { + f, ok := formatters[format] + if !ok { + fmt.Fprintf(os.Stderr, "%s: invalid format. Choices are %s\n", format, strings.Join(formats, ", ")) + stop(1) + } + if f.flags != nil { + f.flags.VisitAll(func(o getopt.Option) { + getopt.AddOption(o) + }) + } + } + return true + }); err != nil { + fmt.Fprintln(os.Stderr, err) + getopt.PrintUsage(os.Stderr) + os.Exit(1) + } + + if traceP != "" { + fp, err := os.Create(traceP) + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + trace.Start(fp) + stop = func(c int) { trace.Stop(); os.Exit(c) } + defer func() { trace.Stop() }() + } + + if help { + getopt.CommandLine.PrintUsage(os.Stderr) + fmt.Fprintf(os.Stderr, ` +SOURCE may be a module name or a .yang file. + +Formats: +`) + for _, fn := range formats { + f := formatters[fn] + fmt.Fprintf(os.Stderr, " %s - %s\n", f.name, f.help) + if f.flags != nil { + f.flags.PrintOptions(indent.NewWriter(os.Stderr, " ")) + } + fmt.Fprintln(os.Stderr) + } + stop(0) + } + + for _, path := range paths { + expanded, err := yang.PathsWithModules(path) + if err != nil { + fmt.Fprintln(os.Stderr, err) + continue + } + yang.AddPath(expanded...) + } + + if format == "" { + format = "tree" + } + if _, ok := formatters[format]; !ok { + fmt.Fprintf(os.Stderr, "%s: invalid format. Choices are %s\n", format, strings.Join(formats, ", ")) + stop(1) + + } + + files := getopt.Args() + + ms := yang.NewModules() + + if len(files) == 0 { + data, err := ioutil.ReadAll(os.Stdin) + if err == nil { + err = ms.Parse(string(data), "") + } + if err != nil { + fmt.Fprintln(os.Stderr, err) + stop(1) + } + } + + for _, name := range files { + if err := ms.Read(name); err != nil { + fmt.Fprintln(os.Stderr, err) + continue + } + } + + // Process the read files, exiting if any errors were found. + exitIfError(ms.Process()) + + // Keep track of the top level modules we read in. + // Those are the only modules we want to print below. + mods := map[string]*yang.Module{} + var names []string + + for _, m := range ms.Modules { + if mods[m.Name] == nil { + mods[m.Name] = m + names = append(names, m.Name) + } + } + sort.Strings(names) + entries := make([]*yang.Entry, len(names)) + for x, n := range names { + entries[x] = yang.ToEntry(mods[n]) + } + + if format == "annotate" { + formatters[format].utilf(files, mods) + } + formatters[format].f(os.Stdout, entries) +} From 5d038f25fedac72b11559f02b2c09b0c3524a68a Mon Sep 17 00:00:00 2001 From: s-mari Date: Sat, 10 Aug 2019 00:07:08 -0700 Subject: [PATCH 019/214] Changed the function names and file name --- src/translib/transformer/transformer.go | 2 +- .../transformer/{xlateToDb.go => xlate_to_db.go} | 5 ++++- src/translib/transformer/xspec.go | 16 ++++++++-------- 3 files changed, 13 insertions(+), 10 deletions(-) rename src/translib/transformer/{xlateToDb.go => xlate_to_db.go} (97%) diff --git a/src/translib/transformer/transformer.go b/src/translib/transformer/transformer.go index d353b06061..12b9e6f108 100644 --- a/src/translib/transformer/transformer.go +++ b/src/translib/transformer/transformer.go @@ -78,7 +78,7 @@ func LoadYangModules(files ...string) error { entries[n] = yang.ToEntry(mods[n]) } } - mapBuild(entries) + yangToDbMapBuild(entries) // TODO - build the inverse map for GET, from OC to Sonic diff --git a/src/translib/transformer/xlateToDb.go b/src/translib/transformer/xlate_to_db.go similarity index 97% rename from src/translib/transformer/xlateToDb.go rename to src/translib/transformer/xlate_to_db.go index e157f25ac0..57c68f3707 100644 --- a/src/translib/transformer/xlateToDb.go +++ b/src/translib/transformer/xlate_to_db.go @@ -41,7 +41,8 @@ func mapFillData(dbKey string, result map[string]map[string]db.Value, xpathPrefi if len(xpathInfo.xfmrFunc) > 0 { log.Info("Transformer function(\"%v\") invoked for yang path(\"%v\").", xpathInfo.xfmrFunc, xpath) - //fieldName[] = XlateFuncCall(xpathInfo.xfmrFunc, name, value) + // map[string]string + //fieldName := XlateFuncCall(xpathInfo.xfmrFunc, name, value) //return errors.New("Invalid field name") return nil } @@ -113,6 +114,7 @@ func dbMapCreate(keyName string, xpathPrefix string, jsonData interface{}, resul for idx := 0; idx < jData.Len(); idx++ { dataMap[idx] = jData.Index(idx).Interface() } + // string for _, data := range dataMap { keyName := keyCreate(keyName, xpathPrefix, data) return dbMapCreate(keyName, xpathPrefix, data, result) @@ -132,6 +134,7 @@ func dbMapCreate(keyName string, xpathPrefix string, jsonData interface{}, resul if len(xSpecMap[xpath].xfmrFunc) > 0 { subMap := callXfmr() + // map[string]map[string]db.Value //subMap := XlateFuncCall(xpathInfo.xfmrFunc, name, value) mapCopy(result, subMap) return nil diff --git a/src/translib/transformer/xspec.go b/src/translib/transformer/xspec.go index 98eeabbb4a..a36a53c76b 100644 --- a/src/translib/transformer/xspec.go +++ b/src/translib/transformer/xspec.go @@ -34,7 +34,7 @@ func updateDbTableData (xpathData *yangXpathInfo, tableName string) { } /* Recursive api to fill the map with yang details */ -func fillMap (xSpecMap map[string]*yangXpathInfo, entry *yang.Entry, xpathPrefix string) { +func yangToDbMapFill (xSpecMap map[string]*yangXpathInfo, entry *yang.Entry, xpathPrefix string) { xpath := "" /* create the yang xpath */ if xSpecMap[xpathPrefix] != nil && xSpecMap[xpathPrefix].yangDataType == "module" { @@ -97,12 +97,12 @@ func fillMap (xSpecMap map[string]*yangXpathInfo, entry *yang.Entry, xpathPrefix xpathData.yangEntry = entry /* now recurse, filling the map with current node's children info */ for _, child := range childList { - fillMap(xSpecMap, entry.Dir[child], xpath) + yangToDbMapFill(xSpecMap, entry.Dir[child], xpath) } } /* Build lookup table based of yang xpath */ -func mapBuild(entries map[string]*yang.Entry) { +func yangToDbMapBuild(entries map[string]*yang.Entry) { if entries == nil { return } @@ -112,13 +112,13 @@ func mapBuild(entries map[string]*yang.Entry) { } /* Start to fill xpath based map with yang data */ - fillMap(xSpecMap, e, "") + yangToDbMapFill(xSpecMap, e, "") } mapPrint(xSpecMap, "/tmp/fullSpec.txt") } /* Fill the map with db details */ -func fillDbMap (xDbSpecMap map[string]*yang.Entry, entry *yang.Entry) { +func dbMapFill(xDbSpecMap map[string]*yang.Entry, entry *yang.Entry) { entryType := entry.Node.Statement().Keyword if entryType == "list" { xDbSpecMap[entry.Name] = entry @@ -130,7 +130,7 @@ func fillDbMap (xDbSpecMap map[string]*yang.Entry, entry *yang.Entry) { } sort.Strings(childList) for _, child := range childList { - fillDbMap(xDbSpecMap, entry.Dir[child]) + dbMapFill(xDbSpecMap, entry.Dir[child]) } } @@ -145,7 +145,7 @@ func dbMapBuild(entries []*yang.Entry) { if e == nil || len(e.Dir) == 0 { continue } - fillDbMap(xDbSpecMap, e) + dbMapFill(xDbSpecMap, e) } dbMapPrint(xSpecMap) } @@ -202,7 +202,7 @@ func xpathFromDevCreate(path string) string { } /* Build lookup map based on yang xpath */ -func yangToDbMapBuilt(annotEntries []*yang.Entry) { +func annotToDbMapBuild(annotEntries []*yang.Entry) { if annotEntries == nil { return } From c5b2665f4cb3bca8769d2fdb048888c182cde702 Mon Sep 17 00:00:00 2001 From: Ravi Vasanthm Date: Sat, 10 Aug 2019 19:04:36 -0700 Subject: [PATCH 020/214] Initial changes for transformer methods prototypes and ACL transformer method implementation. --- src/translib/transformer/xfmr_acl.go | 689 +++++++++++++++++++- src/translib/transformer/xfmr_interface.go | 79 +++ src/translib/transformer/xfmr_path_utils.go | 162 +++++ 3 files changed, 897 insertions(+), 33 deletions(-) create mode 100644 src/translib/transformer/xfmr_interface.go create mode 100644 src/translib/transformer/xfmr_path_utils.go diff --git a/src/translib/transformer/xfmr_acl.go b/src/translib/transformer/xfmr_acl.go index b57ebfee20..9b036280a3 100644 --- a/src/translib/transformer/xfmr_acl.go +++ b/src/translib/transformer/xfmr_acl.go @@ -1,40 +1,663 @@ package transformer import ( - "fmt" -// "os" -// "sort" -// "github.com/openconfig/goyang/pkg/yang" -// "github.com/openconfig/ygot/ygot" - "translib/db" -// "translib/ocbinds" + "fmt" + "bytes" + "errors" + "strings" + // "os" + // "sort" + // "github.com/openconfig/goyang/pkg/yang" + "github.com/openconfig/ygot/ygot" + "strconv" + "translib/db" + "reflect" + log "github.com/golang/glog" + "translib/ocbinds" + "translib/tlerr" ) func init () { - XlateFuncBind("acl_set_key_xfmr", acl_set_key_xfmr) - XlateFuncBind("port_bindings_xfmr", port_bindings_xfmr) -} - -func acl_set_key_xfmr(json []byte) (map[string]map[string]db.Value, error) { - - var err error - - // table.key.fields - var result = make(map[string]map[string]db.Value) - fmt.Println(string(json)) - - // TODO - traverse JSON with the metadata to translate to DB - // xfmr method dynamically invoked - - return result, err -} - -func port_bindings_xfmr(data map[string]map[string]db.Value) ([]byte, error) { - var err error - - // table.key.fields - var result []byte - - //TODO - implement me - return result, err + XlateFuncBind("Read_acl_entry_key_xfmr", Read_acl_entry_key_xfmr) + XlateFuncBind("Write_acl_entry_key_xfmr", Write_acl_entry_key_xfmr) + XlateFuncBind("Read_acl_l2_ethertype_xfmr", Read_acl_l2_ethertype_xfmr) + XlateFuncBind("Write_acl_l2_ethertype_xfmr", Write_acl_l2_ethertype_xfmr) + XlateFuncBind("Read_acl_ip_protocol_xfmr", Read_acl_ip_protocol_xfmr) + XlateFuncBind("Write_acl_ip_protocol_xfmr", Write_acl_ip_protocol_xfmr) + XlateFuncBind("Read_acl_source_port_xfmr", Read_acl_source_port_xfmr) + XlateFuncBind("Write_acl_source_port_xfmr", Write_acl_source_port_xfmr) + XlateFuncBind("Read_acl_destination_port_xfmr", Read_acl_destination_port_xfmr) + XlateFuncBind("Write_acl_destination_port_xfmr", Write_acl_destination_port_xfmr) + XlateFuncBind("Read_acl_tcp_flags_xfmr", Read_acl_tcp_flags_xfmr) + XlateFuncBind("Write_acl_tcp_flags_xfmr", Write_acl_tcp_flags_xfmr) + XlateFuncBind("Read_acl_port_bindings_xfmr", Read_acl_port_bindings_xfmr) + XlateFuncBind("Write_acl_port_bindings_xfmr", Write_acl_port_bindings_xfmr) +} + +const ( + ACL_TABLE = "ACL_TABLE" + RULE_TABLE = "ACL_RULE" + SONIC_ACL_TYPE_IPV4 = "L3" + SONIC_ACL_TYPE_L2 = "L2" + SONIC_ACL_TYPE_IPV6 = "L3V6" + OPENCONFIG_ACL_TYPE_IPV4 = "ACL_IPV4" + OPENCONFIG_ACL_TYPE_IPV6 = "ACL_IPV6" + OPENCONFIG_ACL_TYPE_L2 = "ACL_L2" +) + +var IP_PROTOCOL_MAP = map[ocbinds.E_OpenconfigPacketMatchTypes_IP_PROTOCOL]uint8{ + ocbinds.OpenconfigPacketMatchTypes_IP_PROTOCOL_IP_ICMP: 1, + ocbinds.OpenconfigPacketMatchTypes_IP_PROTOCOL_IP_IGMP: 2, + ocbinds.OpenconfigPacketMatchTypes_IP_PROTOCOL_IP_TCP: 6, + ocbinds.OpenconfigPacketMatchTypes_IP_PROTOCOL_IP_UDP: 17, + ocbinds.OpenconfigPacketMatchTypes_IP_PROTOCOL_IP_RSVP: 46, + ocbinds.OpenconfigPacketMatchTypes_IP_PROTOCOL_IP_GRE: 47, + ocbinds.OpenconfigPacketMatchTypes_IP_PROTOCOL_IP_AUTH: 51, + ocbinds.OpenconfigPacketMatchTypes_IP_PROTOCOL_IP_PIM: 103, + ocbinds.OpenconfigPacketMatchTypes_IP_PROTOCOL_IP_L2TP: 115, +} + +var ETHERTYPE_MAP = map[ocbinds.E_OpenconfigPacketMatchTypes_ETHERTYPE]uint32{ + ocbinds.OpenconfigPacketMatchTypes_ETHERTYPE_ETHERTYPE_LLDP: 0x88CC, + ocbinds.OpenconfigPacketMatchTypes_ETHERTYPE_ETHERTYPE_VLAN: 0x8100, + ocbinds.OpenconfigPacketMatchTypes_ETHERTYPE_ETHERTYPE_ROCE: 0x8915, + ocbinds.OpenconfigPacketMatchTypes_ETHERTYPE_ETHERTYPE_ARP: 0x0806, + ocbinds.OpenconfigPacketMatchTypes_ETHERTYPE_ETHERTYPE_IPV4: 0x0800, + ocbinds.OpenconfigPacketMatchTypes_ETHERTYPE_ETHERTYPE_IPV6: 0x86DD, + ocbinds.OpenconfigPacketMatchTypes_ETHERTYPE_ETHERTYPE_MPLS: 0x8847, +} + + +func getAclRoot (s *ygot.GoStruct) *ocbinds.OpenconfigAcl_Acl { + deviceObj := (*s).(*ocbinds.Device) + return deviceObj.Acl +} + +func getAclTypeOCEnumFromName(val string) (ocbinds.E_OpenconfigAcl_ACL_TYPE, error) { + switch val { + case "ACL_IPV4", "openconfig-acl:ACL_IPV4": + return ocbinds.OpenconfigAcl_ACL_TYPE_ACL_IPV4, nil + case "ACL_IPV6", "openconfig-acl:ACL_IPV6": + return ocbinds.OpenconfigAcl_ACL_TYPE_ACL_IPV6, nil + case "ACL_L2", "openconfig-acl:ACL_L2": + return ocbinds.OpenconfigAcl_ACL_TYPE_ACL_L2, nil + default: + return ocbinds.OpenconfigAcl_ACL_TYPE_UNSET, + tlerr.NotSupported("ACL Type '%s' not supported", val) + } +} +func getAclKeyStrFromOCKey(aclname string, acltype ocbinds.E_OpenconfigAcl_ACL_TYPE) string { + aclN := strings.Replace(strings.Replace(aclname, " ", "_", -1), "-", "_", -1) + aclT := acltype.ΛMap()["E_OpenconfigAcl_ACL_TYPE"][int64(acltype)].Name + return aclN + "_" + aclT +} + +func getOCAclKeysFromStrDBKey(aclKey string) (string, ocbinds.E_OpenconfigAcl_ACL_TYPE) { + var aclOrigName string + var aclOrigType ocbinds.E_OpenconfigAcl_ACL_TYPE + + if strings.Contains(aclKey, "_"+OPENCONFIG_ACL_TYPE_IPV4) { + aclOrigName = strings.Replace(aclKey, "_"+OPENCONFIG_ACL_TYPE_IPV4, "", 1) + aclOrigType = ocbinds.OpenconfigAcl_ACL_TYPE_ACL_IPV4 + } else if strings.Contains(aclKey, "_"+OPENCONFIG_ACL_TYPE_IPV6) { + aclOrigName = strings.Replace(aclKey, "_"+OPENCONFIG_ACL_TYPE_IPV6, "", 1) + aclOrigType = ocbinds.OpenconfigAcl_ACL_TYPE_ACL_IPV6 + } else if strings.Contains(aclKey, "_"+OPENCONFIG_ACL_TYPE_L2) { + aclOrigName = strings.Replace(aclKey, "_"+OPENCONFIG_ACL_TYPE_L2, "", 1) + aclOrigType = ocbinds.OpenconfigAcl_ACL_TYPE_ACL_L2 + } + + return aclOrigName, aclOrigType +} + +func getIpProtocol(proto int64) interface{} { + for k, v := range IP_PROTOCOL_MAP { + if uint8(proto) == v { + return k + } + } + return uint8(proto) +} + +func getTransportSrcDestPorts(portVal string, portType string) interface{} { + var portRange string = "" + + portNum, err := strconv.Atoi(portVal) + if err != nil && strings.Contains(portVal, "-") { + portRange = portVal + } + + if len(portRange) > 0 { + return portRange + } else if portNum > 0 { + return uint16(portNum) + } else { + if "src" == portType { + return ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort_ANY + } else if "dest" == portType { + return ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort_ANY + } + } + return nil +} + +func getTransportConfigTcpFlags(tcpFlags string) []ocbinds.E_OpenconfigPacketMatchTypes_TCP_FLAGS { + var flags []ocbinds.E_OpenconfigPacketMatchTypes_TCP_FLAGS + if len(tcpFlags) > 0 { + flagStr := strings.Split(tcpFlags, "/")[0] + flagNumber, _ := strconv.ParseUint(strings.Replace(flagStr, "0x", "", -1), 16, 32) + for i := 0; i < 8; i++ { + mask := 1 << uint(i) + if (int(flagNumber) & mask) > 0 { + switch int(flagNumber) & mask { + case 0x01: + flags = append(flags, ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_FIN) + case 0x02: + flags = append(flags, ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_SYN) + case 0x04: + flags = append(flags, ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_RST) + case 0x08: + flags = append(flags, ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_PSH) + case 0x10: + flags = append(flags, ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_ACK) + case 0x20: + flags = append(flags, ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_URG) + case 0x40: + flags = append(flags, ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_ECE) + case 0x80: + flags = append(flags, ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_CWR) + default: + } + } + } + } + return flags +} + +func getL2EtherType(etherType uint64) interface{} { + for k, v := range ETHERTYPE_MAP { + if uint32(etherType) == v { + return k + } + } + return uint16(etherType) +} + + + + +var Read_acl_entry_key_xfmr KeyXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, xpath string) (string, error) { + var entry_key string + var err error + var oc_aclType ocbinds.E_OpenconfigAcl_ACL_TYPE + log.Info("Read_acl_entry_key_xfmr: ", ygRoot, xpath) + pathInfo := NewPathInfo(xpath) + + if len(pathInfo.Vars) < 3 { + err = errors.New("Invalid xpath, key attributes not found") + return entry_key, err + } + + oc_aclType, err = getAclTypeOCEnumFromName(pathInfo.Var("type")) + if err != nil { + err = errors.New("OC Acl type name to OC Acl Enum failed") + return entry_key, err + } + + aclkey := getAclKeyStrFromOCKey(pathInfo.Var("name"), oc_aclType) + var rulekey string + if strings.Contains(pathInfo.Template, "/acl-entry{sequence-id}") { + rulekey = "RULE_" + pathInfo.Var("sequence-id") + } + entry_key = aclkey + "|" + rulekey + + log.Info("Read_acl_entry_key_xfmr - entry_key : ", entry_key) + + return entry_key, err +} + +var Write_acl_entry_key_xfmr KeyXfmrDbToYang = func (d *db.DB, entry_key string) (map[string]map[string]string, error) { + res_map := make(map[string]map[string]string) + var err error + log.Info("Write_acl_entry_key_xfmr: ", entry_key) + + key := strings.Split(entry_key, "|") + if len(key) < 2 { + err = errors.New("Invalid key for acl entries.") + log.Info("Invalid Keys for acl enmtries", entry_key) + return res_map, err + } + + dbAclName := key[0] + dbAclRule := key[1] + aclName, aclType := getOCAclKeysFromStrDBKey(dbAclName) + res_map["oc-acl:acl-set"]["name"] = aclName + res_map["oc-acl:acl-set"]["type"] = aclType.ΛMap()["E_OpenconfigAcl_ACL_TYPE"][int64(aclType)].Name + seqId := strings.Replace(dbAclRule, "RULE_", "", 1) + res_map["acl-entry"]["sequence-id"] = seqId + log.Info("Write_acl_entry_key_xfmr - res_map: ", res_map) + return res_map, err +} + +func getAclRule(acl *ocbinds.OpenconfigAcl_Acl, aclName string, aclType ocbinds.E_OpenconfigAcl_ACL_TYPE, seqId uint32) (*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry, error) { + var err error + var aclSetKey ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_Key + aclSetKey.Name = aclName + aclSetKey.Type = aclType + + if _, ok := acl.AclSets.AclSet[aclSetKey]; !ok { + err = errors.New("AclSet not found " + aclName) + return nil, err + } + + aclSet := acl.AclSets.AclSet[aclSetKey] + if _, ok := aclSet.AclEntries.AclEntry[seqId]; !ok { + err = errors.New("Acl Rule not found " + aclName + strconv.FormatInt(int64(seqId), 10)) + return nil, err + } + + rule := aclSet.AclEntries.AclEntry[seqId] + return rule, err +} + +var Read_acl_l2_ethertype_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, xpath string, ethertype interface {}) (map[string]string, error) { + res_map := make(map[string]string) + var err error + log.Info("Read_acl_l2_ethertype_xfmr :", ygRoot, xpath) + + ethertypeType := reflect.TypeOf(ethertype).Elem() + var b bytes.Buffer + switch ethertypeType { + case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_L2_Config_Ethertype_Union_E_OpenconfigPacketMatchTypes_ETHERTYPE{}): + v := (ethertype).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_L2_Config_Ethertype_Union_E_OpenconfigPacketMatchTypes_ETHERTYPE) + fmt.Fprintf(&b, "0x%0.4x", ETHERTYPE_MAP[v.E_OpenconfigPacketMatchTypes_ETHERTYPE]) + res_map["ETHER_TYPE"] = b.String() + break + case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_L2_Config_Ethertype_Union_Uint16{}): + v := (ethertype).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_L2_Config_Ethertype_Union_Uint16) + fmt.Fprintf(&b, "0x%0.4x", v.Uint16) + res_map["ETHER_TYPE"] = b.String() + break + } + return res_map, err +} + +var Write_acl_l2_ethertype_xfmr FieldXfmrDbtoYang = func (d *db.DB, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct) (error) { + var err error + log.Info("Write_acl_l2_ethertype_xfmr", data, ygRoot) + + if _, ok := data[RULE_TABLE]; !ok { + err = errors.New("RULE_TABLE entry not found in the input param") + return err + } + ruleTbl := data[RULE_TABLE] + + for aclRuleKey := range ruleTbl { + ruleData := ruleTbl[aclRuleKey] + var entrySet *ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry + entrySet, err = getAclSetEntry(aclRuleKey, ygRoot) + if err != nil { + log.Info("getAclSetEntry failed for :", aclRuleKey) + continue // If its not map doesnt need to loop just return from here. + } + ruleKey := "ETHER_TYPE" + if !ruleData.Has(ruleKey) { + log.Info("No entry found for the field ", ruleKey) + err = errors.New("ETHER_TYPE field not found in DB") + continue + } + ethType, _ := strconv.ParseUint(strings.Replace(ruleData.Get(ruleKey), "0x", "", -1), 16, 32) + ethertype := getL2EtherType(ethType) + entrySet.L2.Config.Ethertype, _ = entrySet.L2.Config.To_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_L2_Config_Ethertype_Union(ethertype) + entrySet.L2.State.Ethertype, _ = entrySet.L2.State.To_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_L2_State_Ethertype_Union(ethertype) + + } + + + return err +} + +var Read_acl_ip_protocol_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, xpath string, protocol interface {}) (map[string]string, error) { + res_map := make(map[string]string) + var err error + log.Info("Read_acl_ip_protocol_xfmr: ", ygRoot, xpath) + + protocolType := reflect.TypeOf(protocol).Elem() + switch (protocolType) { + case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Ipv4_Config_Protocol_Union_E_OpenconfigPacketMatchTypes_IP_PROTOCOL{}): + v := (protocol).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Ipv4_Config_Protocol_Union_E_OpenconfigPacketMatchTypes_IP_PROTOCOL) + res_map["IP_PROTOCOL"] = strconv.FormatInt(int64(IP_PROTOCOL_MAP[v.E_OpenconfigPacketMatchTypes_IP_PROTOCOL]), 10) + break + case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Ipv4_Config_Protocol_Union_Uint8{}): + v := (protocol).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Ipv4_Config_Protocol_Union_Uint8) + res_map["IP_PROTOCOL"] = strconv.FormatInt(int64(v.Uint8), 10) + break + } + return res_map, err +} + +var Write_acl_ip_protocol_xfmr FieldXfmrDbtoYang = func (d *db.DB, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct) (error) { + var err error + log.Info("Write_acl_ip_protocol_xfmr ", data, ygRoot) + if _, ok := data[RULE_TABLE]; !ok { + err = errors.New("RULE_TABLE entry not found in the input param") + return err + } + ruleTbl := data[RULE_TABLE] + + for aclRuleKey := range ruleTbl { + ruleData := ruleTbl[aclRuleKey] + var entrySet *ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry + entrySet, err = getAclSetEntry(aclRuleKey, ygRoot) + if err != nil { + log.Info("getAclSetEntry failed for :", aclRuleKey) + continue // If its not map doesnt need to loop just return from here. + } + ruleKey := "IP_PROTOCOL" + if !ruleData.Has(ruleKey) { + log.Info("No entry found for the field ", ruleKey) + err = errors.New("IP_PROTOCOL field not found in DB") + continue + } + + ipProto, _ := strconv.ParseInt(ruleData.Get(ruleKey), 10, 64) + protocolVal := getIpProtocol(ipProto) + entrySet.Ipv6.Config.Protocol, _ = entrySet.Ipv6.Config.To_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Ipv6_Config_Protocol_Union(protocolVal) + entrySet.Ipv6.State.Protocol, _ = entrySet.Ipv6.State.To_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Ipv6_State_Protocol_Union(protocolVal) + } + return err +} + +var Read_acl_source_port_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, xpath string, value interface {}) (map[string]string, error) { + res_map := make(map[string]string) + var err error; + log.Info("Read_acl_source_port_xfmr: ", ygRoot, xpath) + sourceportType := reflect.TypeOf(value).Elem() + switch sourceportType { + case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort_Union_E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort{}): + v := (value).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort_Union_E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort) + res_map["L4_SRC_PORT"] = v.E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort.ΛMap()["E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort"][int64(v.E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort)].Name + break + case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort_Union_String{}): + v := (value).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort_Union_String) + res_map["L4_SRC_PORT_RANGE"] = strings.Replace(v.String, "..", "-", 1) + break + case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort_Union_Uint16{}): + v := (value).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort_Union_Uint16) + res_map["L4_SRC_PORT"] = strconv.FormatInt(int64(v.Uint16), 10) + break + } + + return res_map, err +} + +func getAclSetEntry (aclRuleKey string, ygRoot *ygot.GoStruct) (*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry, error) { + var err error + var entrySet *ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry + + aclObj := getAclRoot(ygRoot) + + key := strings.Split(aclRuleKey, "|") + if len(key) < 2 { + log.Info("Invalid Keys for acl entries", aclRuleKey) + err = errors.New("Invalid Keys for acl entries") + return entrySet, err + } + dbAclName := key[0] + dbAclRule := key[1] + var aclSetKey ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_Key + aclSetKey.Name, aclSetKey.Type = getOCAclKeysFromStrDBKey(dbAclName) + seqId,_ := strconv.Atoi(strings.Replace(dbAclRule, "RULE_", "", 1)) + + log.Info("Accessing Ygot tree for ACL rule", aclSetKey.Name, aclSetKey.Type, seqId) + var aclSet *ocbinds.OpenconfigAcl_Acl_AclSets_AclSet + if _, ok := aclObj.AclSets.AclSet[aclSetKey]; !ok { + log.Info("ACL set not allocated") + aclSet, _ = aclObj.AclSets.NewAclSet(aclSetKey.Name, aclSetKey.Type) + ygot.BuildEmptyTree(aclSet) + } else { + aclSet = aclObj.AclSets.AclSet[aclSetKey] + } + if _, ok := aclSet.AclEntries.AclEntry[uint32(seqId)]; !ok { + log.Info("ACL rule not allocated") + entrySet_, _ := aclSet.AclEntries.NewAclEntry(uint32(seqId)) + entrySet = entrySet_ + ygot.BuildEmptyTree(entrySet) + } else { + entrySet = aclSet.AclEntries.AclEntry[uint32(seqId)] + } + + return entrySet, err + +} + +var Write_acl_source_port_xfmr FieldXfmrDbtoYang = func (d *db.DB, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct) (error) { + var err error + log.Info("Write_acl_source_port_xfmr: ", data, ygRoot) + + if _, ok := data[RULE_TABLE]; !ok { + err = errors.New("RULE_TABLE entry not found in the input param") + return err + } + ruleTbl := data[RULE_TABLE] + + for aclRuleKey := range ruleTbl { + ruleData := ruleTbl[aclRuleKey] + sp := ruleData.Has("L4_SRC_PORT") + spr := ruleData.Has("L4_SRC_PORT_RANGE") + + if !sp && !spr { + log.Info("Src port field is not present in the field.") + continue + } + var entrySet *ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry + entrySet, err = getAclSetEntry(aclRuleKey, ygRoot) + if err != nil { + log.Info("getAclSetEntry failed for :", aclRuleKey) + continue // If its not map doesnt need to loop just return from here. + } + var ruleKey string + if sp { + ruleKey = "L4_SRC_PORT" + } else { + ruleKey = "L4_SRC_PORT_RANGE" + } + port := ruleData.Get(ruleKey) + srcPort := getTransportSrcDestPorts(port, "src") + entrySet.Transport.Config.SourcePort, _ = entrySet.Transport.Config.To_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort_Union(srcPort) + entrySet.Transport.State.SourcePort, _ = entrySet.Transport.State.To_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_State_SourcePort_Union(srcPort) + } + return err +} + +var Read_acl_destination_port_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, xpath string, value interface{}) (map[string]string, error) { + res_map := make(map[string]string) + var err error; + log.Info("Read_acl_destination_port_xfmr: ", ygRoot, xpath) + destportType := reflect.TypeOf(value).Elem() + switch destportType { + case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort_Union_E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort{}): + v := (value).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort_Union_E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort) + res_map["L4_DST_PORT"] = v.E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort.ΛMap()["E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort"][int64(v.E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort)].Name + break + case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort_Union_String{}): + v := (value).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort_Union_String) + res_map["L4_DST_PORT_RANGE"] = strings.Replace(v.String, "..", "-", 1) + break + case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort_Union_Uint16{}): + v := (value).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort_Union_Uint16) + res_map["L4_DST_PORT"] = strconv.FormatInt(int64(v.Uint16), 10) + break + } + return res_map, err +} + +var Write_acl_destination_port_xfmr FieldXfmrDbtoYang = func (d *db.DB, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct) (error) { + var err error + log.Info("Write_acl_destination_port_xfmr: ", data, ygRoot) + if _, ok := data[RULE_TABLE]; !ok { + err = errors.New("RULE_TABLE entry not found in the input param") + return err + } + ruleTbl := data[RULE_TABLE] + for aclRuleKey := range ruleTbl { + ruleData := ruleTbl[aclRuleKey] + dp := ruleData.Has("L4_DST_PORT") + dpr := ruleData.Has("L4_DST_PORT_RANGE") + if !dp && !dpr { + log.Info("DST port field is not present in the field.") + continue + } + + var entrySet *ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry + entrySet, err = getAclSetEntry(aclRuleKey, ygRoot) + if err != nil { + log.Info("getAclSetEntry failed for :", aclRuleKey) + continue // If its not map doesnt need to loop just return from here. + var ruleKey string + if dp { + ruleKey = "L4_DST_PORT" + } else { + ruleKey = "L4_DST_PORT_RANGE" + } + port := ruleData.Get(ruleKey) + destPort := getTransportSrcDestPorts(port, "dest") + entrySet.Transport.Config.DestinationPort, _ = entrySet.Transport.Config.To_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort_Union(destPort) + entrySet.Transport.State.DestinationPort, _ = entrySet.Transport.State.To_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_State_DestinationPort_Union(destPort) + } + + } + return err +} + +var Read_acl_tcp_flags_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, xpath string, value interface {}) (map[string]string, error) { + res_map := make(map[string]string) + var err error; + log.Info("Read_acl_tcp_flags_xfmr: ", ygRoot, xpath) + var tcpFlags uint32 = 0x00 + v := reflect.ValueOf(value) + + flags := v.Interface().([]ocbinds.E_OpenconfigPacketMatchTypes_TCP_FLAGS) + for _, flag := range flags { + fmt.Println("TCP Flag name: " + flag.ΛMap()["E_OpenconfigPacketMatchTypes_TCP_FLAGS"][int64(flag)].Name) + switch flag { + case ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_FIN: + tcpFlags |= 0x01 + break + case ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_SYN: + tcpFlags |= 0x02 + break + case ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_RST: + tcpFlags |= 0x04 + break + case ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_PSH: + tcpFlags |= 0x08 + break + case ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_ACK: + tcpFlags |= 0x10 + break + case ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_URG: + tcpFlags |= 0x20 + break + case ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_ECE: + tcpFlags |= 0x40 + break + case ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_CWR: + tcpFlags |= 0x80 + break + } + } + var b bytes.Buffer + fmt.Fprintf(&b, "0x%0.2x/0x%0.2x", tcpFlags, tcpFlags) + res_map["TCP_FLAGS"] = b.String() + return res_map, err +} + +var Write_acl_tcp_flags_xfmr FieldXfmrDbtoYang = func (d *db.DB, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct) (error) { + var err error + log.Info("Write_acl_tcp_flags_xfmr: ", data, ygRoot) + + if _, ok := data[RULE_TABLE]; !ok { + err = errors.New("RULE_TABLE entry not found in the input param") + return err + } + ruleTbl := data[RULE_TABLE] + + for aclRuleKey := range ruleTbl { + ruleData := ruleTbl[aclRuleKey] + var entrySet *ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry + entrySet, err = getAclSetEntry(aclRuleKey, ygRoot) + if err != nil { + log.Info("getAclSetEntry failed for :", aclRuleKey) + continue // If its not map doesnt need to loop just return from here. + } + ruleKey := "TCP_FLAGS" + if !ruleData.Has(ruleKey) { + log.Info("No entry found for the field ", ruleKey) + err = errors.New("TCP_FLAGS field not found in DB") + continue + } + tcpFlags := ruleData.Get(ruleKey) + entrySet.Transport.Config.TcpFlags = getTransportConfigTcpFlags(tcpFlags) + entrySet.Transport.State.TcpFlags = getTransportConfigTcpFlags(tcpFlags) + } + return err +} + +var Read_acl_port_bindings_xfmr SubTreeXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, xpath string) (map[string]map[string]db.Value, error) { + res_map := make(map[string]map[string]db.Value) + aclTableMap := make(map[string]db.Value) + var err error; + log.Info("Read_acl_port_bindings_xfmr: ", ygRoot, xpath) + + aclObj := getAclRoot(ygRoot) + + if aclObj.Interfaces != nil && len(aclObj.Interfaces.Interface) > 0 { + aclInterfacesMap := make(map[string][]string) + for intfId, _ := range aclObj.Interfaces.Interface { + intf := aclObj.Interfaces.Interface[intfId] + if intf != nil { + if intf.IngressAclSets != nil && len(intf.IngressAclSets.IngressAclSet) > 0 { + for inAclKey, _ := range intf.IngressAclSets.IngressAclSet { + aclName := getAclKeyStrFromOCKey(inAclKey.SetName, inAclKey.Type) + if intf.InterfaceRef != nil && intf.InterfaceRef.Config.Interface != nil { + aclInterfacesMap[aclName] = append(aclInterfacesMap[aclName], *intf.InterfaceRef.Config.Interface) + } else { + aclInterfacesMap[aclName] = append(aclInterfacesMap[aclName], *intf.Id) + } + if len(aclTableMap) == 0 { + aclTableMap[aclName] = db.Value{Field: map[string]string{}} + } + aclTableMap[aclName].Field["stage"] = "INGRESS" + } + } + if intf.EgressAclSets != nil && len(intf.EgressAclSets.EgressAclSet) > 0 { + for outAclKey, _ := range intf.EgressAclSets.EgressAclSet { + aclName := getAclKeyStrFromOCKey(outAclKey.SetName, outAclKey.Type) + if intf.InterfaceRef != nil && intf.InterfaceRef.Config.Interface != nil { + aclInterfacesMap[aclName] = append(aclInterfacesMap[aclName], *intf.InterfaceRef.Config.Interface) + } else { + aclInterfacesMap[aclName] = append(aclInterfacesMap[aclName], *intf.Id) + } + if len(aclTableMap) == 0 { + aclTableMap[aclName] = db.Value{Field: map[string]string{}} + } + aclTableMap[aclName].Field["stage"] = "EGRESS" + } + } + } + } + for k, _ := range aclInterfacesMap { + val := aclTableMap[k] + (&val).SetList("ports", aclInterfacesMap[k]) + } + } + res_map[ACL_TABLE] = aclTableMap + return res_map, err +} + +var Write_acl_port_bindings_xfmr SubTreeXfmrDbToYang = func (d *db.DB, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct) (error) { + var err error + log.Info("Write_acl_port_bindings_xfmr: ", data, ygRoot) + return err } diff --git a/src/translib/transformer/xfmr_interface.go b/src/translib/transformer/xfmr_interface.go new file mode 100644 index 0000000000..4c62e7d7bd --- /dev/null +++ b/src/translib/transformer/xfmr_interface.go @@ -0,0 +1,79 @@ +package transformer + +import ( + "github.com/openconfig/ygot/ygot" + "translib/db" + log "github.com/golang/glog" +// "translib/ocbinds" +) +/** + * KeyXfmrYangToDb type is defined to use for conversion of Yang key to DB Key + * Transformer function definition. + * Param: Database info, YgotRoot, Xpath + * Return: Database keys to access db entry, error + **/ +type KeyXfmrYangToDb func (*db.DB, *ygot.GoStruct, string) (string, error) +/** + * KeyXfmrDbToYang type is defined to use for conversion of DB key to Yang key + * Transformer function definition. + * Param: Database info, Database keys to access db entry + * Return: multi dimensional map to hold the yang key attributes of complete xpath, error + **/ +type KeyXfmrDbToYang func (*db.DB, string) (map[string]map[string]string, error) + +/** + * FieldXfmrYangToDb type is defined to use for conversion of yang Field to DB field + * Transformer function definition. + * Param: Database info, YgotRoot, Xpath + * Return: multi dimensional map to hold the DB data, error + **/ +type FieldXfmrYangToDb func (*db.DB, *ygot.GoStruct, string, interface {}) (map[string]string, error) +/** + * FieldXfmrDbtoYang type is defined to use for conversion of DB field to Yang field + * Transformer function definition. + * Param: Database info, DB data in multidimensional map, output param YgotRoot + * Return: error + **/ +type FieldXfmrDbtoYang func (*db.DB, map[string]map[string]db.Value, *ygot.GoStruct) (error) + +/** + * SubTreeXfmrYangToDb type is defined to use for handling the yang subtree to DB + * Transformer function definition. + * Param: Database info, YgotRoot, Xpath + * Return: multi dimensional map to hold the DB data, error + **/ +type SubTreeXfmrYangToDb func (*db.DB, *ygot.GoStruct, string) (map[string]map[string]db.Value, error) +/** + * SubTreeXfmrDbToYang type is defined to use for handling the DB to Yang subtree + * Transformer function definition. + * Param : Database info, DB data in multidimensional map, output param YgotRoot + * Return : error + **/ +type SubTreeXfmrDbToYang func (*db.DB, map[string]map[string]db.Value, *ygot.GoStruct) (error) + +/** + * Xfmr validation interface for validating the callback registration of app modules + * transformer methods. + **/ +type XfmrInterface interface { + xfmrInterfaceValiidate() +} + +func (KeyXfmrYangToDb) xfmrInterfaceValiidate () { + log.Info("xfmrInterfaceValiidate for KeyXfmrYangToDb") +} +func (KeyXfmrDbToYang) xfmrInterfaceValiidate () { + log.Info("xfmrInterfaceValiidate for KeyXfmrDbToYang") +} +func (FieldXfmrYangToDb) xfmrInterfaceValiidate () { + log.Info("xfmrInterfaceValiidate for FieldXfmrYangToDb") +} +func (FieldXfmrDbtoYang) xfmrInterfaceValiidate () { + log.Info("xfmrInterfaceValiidate for FieldXfmrDbtoYang") +} +func (SubTreeXfmrYangToDb) xfmrInterfaceValiidate () { + log.Info("xfmrInterfaceValiidate for SubTreeXfmrYangToDb") +} +func (SubTreeXfmrDbToYang) xfmrInterfaceValiidate () { + log.Info("xfmrInterfaceValiidate for SubTreeXfmrDbToYang") +} diff --git a/src/translib/transformer/xfmr_path_utils.go b/src/translib/transformer/xfmr_path_utils.go new file mode 100644 index 0000000000..06989cb116 --- /dev/null +++ b/src/translib/transformer/xfmr_path_utils.go @@ -0,0 +1,162 @@ +/////////////////////////////////////////////////////////////////////// +// +// Copyright 2019 Broadcom. All rights reserved. +// The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. +// +/////////////////////////////////////////////////////////////////////// + +package transformer + +import ( + //"errors" + "fmt" + //log "github.com/golang/glog" + //"reflect" + "strconv" + "strings" + //"translib/ocbinds" +) + +// PathInfo structure contains parsed path information. +type PathInfo struct { + Path string + Template string + Vars map[string]string +} + +// Var returns the string value for a path variable. Returns +// empty string if no such variable exists. +func (p *PathInfo) Var(name string) string { + return p.Vars[name] +} + +// IntVar returns the value for a path variable as an int. +// Returns 0 if no such variable exists. Returns an error +// if the value is not an integer. +func (p *PathInfo) IntVar(name string) (int, error) { + val := p.Vars[name] + if len(val) == 0 { + return 0, nil + } + + return strconv.Atoi(val) +} + +// NewPathInfo parses given path string into a PathInfo structure. +func NewPathInfo(path string) *PathInfo { + var info PathInfo + info.Path = path + info.Vars = make(map[string]string) + + //TODO optimize using regexp + var template strings.Builder + r := strings.NewReader(path) + + for r.Len() > 0 { + c, _ := r.ReadByte() + if c != '[' { + template.WriteByte(c) + continue + } + + name := readUntil(r, '=') + value := readUntil(r, ']') + if len(name) != 0 { + fmt.Fprintf(&template, "{%s}", name) + info.Vars[name] = value + } + } + + info.Template = template.String() + + return &info +} + +func readUntil(r *strings.Reader, delim byte) string { + var buff strings.Builder + for { + c, err := r.ReadByte() + if err == nil && c != delim { + buff.WriteByte(c) + } else { + break + } + } + + return buff.String() +} +/* +func getParentNode(targetUri *string, deviceObj *ocbinds.Device) (*interface{}, *yang.Entry, error) { + path, err := ygot.StringToPath(*targetUri, ygot.StructuredPath, ygot.StringSlicePath) + if err != nil { + return nil, nil, err + } + + var pathList []*gnmi.PathElem = path.Elem + + parentPath := &gnmi.Path{} + + for i := 0; i < (len(pathList) - 1); i++ { + pathSlice := strings.Split(pathList[i].Name, ":") + pathList[i].Name = pathSlice[len(pathSlice)-1] + parentPath.Elem = append(parentPath.Elem, pathList[i]) + } + + treeNodeList, err2 := ytypes.GetNode(ygSchema.RootSchema(), deviceObj, parentPath) + if err2 != nil { + return nil, nil, err2 + } + + if len(treeNodeList) == 0 { + return nil, nil, errors.New("Invalid URI") + } + + return &(treeNodeList[0].Data), treeNodeList[0].Schema, nil +} + +func getNodeName(targetUri *string, deviceObj *ocbinds.Device) (string, error) { + path, err := ygot.StringToPath(*targetUri, ygot.StructuredPath, ygot.StringSlicePath) + if err != nil { + log.Error("Error in uri to path conversion: ", err) + return "", err + } + + pathList := path.Elem + for i := 0; i < len(pathList); i++ { + pathSlice := strings.Split(pathList[i].Name, ":") + pathList[i].Name = pathSlice[len(pathSlice)-1] + } + + treeNodeList, err := ytypes.GetNode(ygSchema.RootSchema(), deviceObj, path) + if err != nil { + log.Error("Error in uri to path conversion: ", err) + return "", err + } + + if len(treeNodeList) == 0 { + return "", errors.New("Invalid URI") + } + + return treeNodeList[0].Schema.Name, nil +} + +func getObjectFieldName(targetUri *string, deviceObj *ocbinds.Device, ygotTarget *interface{}) (string, error) { + parentObjIntf, _, err := getParentNode(targetUri, deviceObj) + if err != nil { + return "", err + } + valObj := reflect.ValueOf(*parentObjIntf).Elem() + parentObjType := reflect.TypeOf(*parentObjIntf).Elem() + + for i := 0; i < parentObjType.NumField(); i++ { + if reflect.ValueOf(*ygotTarget).Kind() == reflect.Ptr && valObj.Field(i).Kind() == reflect.Ptr { + if valObj.Field(i).Pointer() == reflect.ValueOf(*ygotTarget).Pointer() { + return parentObjType.Field(i).Name, nil + } + } else if valObj.Field(i).String() == reflect.ValueOf(*ygotTarget).String() { + return parentObjType.Field(i).Name, nil + } + } + return "", errors.New("Target object not found") +} +*/ From 64fc36479ecdb363ec9ff5e0f5323cd380eb8b93 Mon Sep 17 00:00:00 2001 From: amrutasali Date: Mon, 12 Aug 2019 19:59:42 +0000 Subject: [PATCH 021/214] Build tool chain changes to generate : 1.) Swagger end points for Sonic/CVL yangs 2.) ocbindings/ygot bindings for Sonic/CVL yang --- models/yang/Makefile | 2 +- src/cvl/schema/Makefile | 50 +++++++++++++++++++++++++++++++++++++- src/rest/Makefile | 1 + src/translib/ocbinds/oc.go | 2 +- 4 files changed, 52 insertions(+), 3 deletions(-) diff --git a/models/yang/Makefile b/models/yang/Makefile index 721feecb21..c04e98622c 100644 --- a/models/yang/Makefile +++ b/models/yang/Makefile @@ -46,7 +46,7 @@ allyangs_tree.html: $(YANG_MOD_FILES) $(YANG_COMMON_FILES) #====================================================================== $(YANGAPI_DIR)/.done: $(YANG_MOD_FILES) $(YANG_COMMON_FILES) @echo "+++++ Generating YAML files for Yang modules +++++" - mkdir -p $(YANGAPI_DIR) + #mkdir -p $(YANGAPI_DIR) $(PYANG_BIN) \ -f swaggerapi \ --outdir $(YANGAPI_DIR) \ diff --git a/src/cvl/schema/Makefile b/src/cvl/schema/Makefile index 1408bb1f58..9ce8519c0c 100644 --- a/src/cvl/schema/Makefile +++ b/src/cvl/schema/Makefile @@ -1,11 +1,25 @@ +TOPDIR := ../../.. +CVL_YANGAPI_DIR := $(TOPDIR)/build/yaml +CVL_YANGDIR := $(TOPDIR)/src/cvl/schema +CVL_YANGDIR_COMMON := $(TOPDIR)/src/cvl/schema/ietf +CVL_YANG_MOD_FILES := $(shell find $(CVL_YANGDIR) -maxdepth 1 -name '*.yang' | sort) +CVL_YANG_COMMON_FILES := $(shell find $(CVL_YANGDIR_COMMON) -name '*.yang' | sort) + +CVL_TOOLS_DIR := $(TOPDIR)/tools +CVL_PYANG_DIR := $(CVL_TOOLS_DIR)/pyang +CVL_PYANG_PLUGIN_DIR := $(CVL_PYANG_DIR)/pyang_plugins +CVL_PYANG_BIN := pyang + src_files=$(wildcard *.yang) out=$(patsubst %.yang, %.yin, $(src_files)) out_ext=$(patsubst %.yang, %.tree, $(src_files)) -all:schema +all: yamlGen allyangs.tree allyangs_tree.html schema schema: $(out) +#yamlGen: $(CVL_YANGAPI_DIR)/.done + %.yin:%.yang @echo "Generating $@ ..." @devFile="`echo $< | cut -d . -f1`-dev.yang"; \ @@ -14,6 +28,38 @@ schema: $(out) @xmllint --noblanks $@.tmp > $@ @rm -rf $@.tmp +allyangs.tree: $(YANG_MOD_FILES) $(YANG_COMMON_FILES) + $(CVL_PYANG_BIN) \ + -f tree \ + -o $(CVL_YANGDIR)/$@ \ + -p $(CVL_YANGDIR_COMMON):$(CVL_YANGDIR) \ + $(CVL_YANG_MOD_FILES) + @echo "+++++ Generation of YANG tree for Sonic Yang modules completed +++++" + +allyangs_tree.html: $(CVL_YANG_MOD_FILES) $(CVL_YANG_COMMON_FILES) + $(CVL_PYANG_BIN) \ + -f jstree \ + -o $(CVL_YANGDIR)/$@ \ + -p $(CVL_YANGDIR_COMMON):$(CVL_YANGDIR) \ + $(CVL_YANG_MOD_FILES) + @echo "+++++ Generation of HTML tree for Sonic Yang modules completed +++++" + +#====================================================================== +# Generate YAML files for Sonic Yang modules +#====================================================================== +yamlGen: + @echo "+++++ Generating YAML files for Sonic Yang modules +++++" + mkdir -p $(CVL_YANGAPI_DIR) + $(CVL_PYANG_BIN) \ + -f swaggerapi \ + --outdir $(CVL_YANGAPI_DIR) \ + --plugindir $(CVL_PYANG_PLUGIN_DIR) \ + -p $(CVL_YANGDIR_COMMON):$(CVL_YANGDIR) \ + $(CVL_YANG_MOD_FILES) + @echo "+++++ Generation of YAML files for Sonic Yang modules completed +++++" + # touch $@ + + %.tree:%.yang @echo "Generating $@ ..." @devFile="`echo $< | cut -d . -f1`-dev.yang"; \ @@ -24,3 +70,5 @@ clean: @echo "Removing files ..." rm -rf $(out) rm -rf $(out_ext) + rm -rf $(CVL_YANGAPI_DIR) + rm -rf allyangs.tree allyangs_tree.html diff --git a/src/rest/Makefile b/src/rest/Makefile index 0e4b3128ab..389afd4b79 100644 --- a/src/rest/Makefile +++ b/src/rest/Makefile @@ -32,6 +32,7 @@ REST_BIN := $(REST_BUILD_DIR)/main # Source files affecting REST server REST_SRCS := $(shell find $(TOPDIR)/src -name '*.go' | sort) \ $(shell find $(TOPDIR)/models/yang -name '*.yang' | sort) \ + $(shell find $(TOPDIR)/src/cvl/schema '*.yang' | sort) \ $(shell find $(TOPDIR)/models/openapi -name '*.yaml' | sort) REST_GOPATH := $(GOPATH):$(abspath $(REST_BUILD_DIR)/dist) diff --git a/src/translib/ocbinds/oc.go b/src/translib/ocbinds/oc.go index e6946a4351..2740caabbc 100644 --- a/src/translib/ocbinds/oc.go +++ b/src/translib/ocbinds/oc.go @@ -1,3 +1,3 @@ package ocbinds -//go:generate sh -c "/usr/local/go/bin/go run $BUILD_GOPATH/src/github.com/openconfig/ygot/generator/generator.go -generate_fakeroot -output_file ocbinds.go -package_name ocbinds -generate_fakeroot -fakeroot_name=device -compress_paths=false -exclude_modules ietf-interfaces -path . $(find ../../../models/yang -name '*.yang' -not -path '*yang/annotations/*' | sort)" +//go:generate sh -c "/usr/local/go/bin/go run $BUILD_GOPATH/src/github.com/openconfig/ygot/generator/generator.go -generate_fakeroot -output_file ocbinds.go -package_name ocbinds -generate_fakeroot -fakeroot_name=device -compress_paths=false -exclude_modules ietf-interfaces -path . $(find ../../../models/yang ../../../src/cvl/schema -name '*.yang' | sort)" From 4ee1541a3f780ec26ac075a99419a301060d4ea6 Mon Sep 17 00:00:00 2001 From: amrutasali Date: Mon, 12 Aug 2019 21:19:52 +0000 Subject: [PATCH 022/214] Corrected the src/cvl/schema/Makefile and fixed a commented out line --- models/yang/Makefile | 2 +- src/cvl/schema/Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/models/yang/Makefile b/models/yang/Makefile index c04e98622c..721feecb21 100644 --- a/models/yang/Makefile +++ b/models/yang/Makefile @@ -46,7 +46,7 @@ allyangs_tree.html: $(YANG_MOD_FILES) $(YANG_COMMON_FILES) #====================================================================== $(YANGAPI_DIR)/.done: $(YANG_MOD_FILES) $(YANG_COMMON_FILES) @echo "+++++ Generating YAML files for Yang modules +++++" - #mkdir -p $(YANGAPI_DIR) + mkdir -p $(YANGAPI_DIR) $(PYANG_BIN) \ -f swaggerapi \ --outdir $(YANGAPI_DIR) \ diff --git a/src/cvl/schema/Makefile b/src/cvl/schema/Makefile index 9ce8519c0c..0b69a53964 100644 --- a/src/cvl/schema/Makefile +++ b/src/cvl/schema/Makefile @@ -28,7 +28,7 @@ schema: $(out) @xmllint --noblanks $@.tmp > $@ @rm -rf $@.tmp -allyangs.tree: $(YANG_MOD_FILES) $(YANG_COMMON_FILES) +allyangs.tree: $(CVL_YANG_MOD_FILES) $(CVL_YANG_COMMON_FILES) $(CVL_PYANG_BIN) \ -f tree \ -o $(CVL_YANGDIR)/$@ \ From 025d3061446ec0350450b8374b32f523745f371e Mon Sep 17 00:00:00 2001 From: s-mari Date: Mon, 12 Aug 2019 14:39:25 -0700 Subject: [PATCH 023/214] Added support to get child table name and corrected the key gen from uri --- src/translib/transformer/xlate_to_db.go | 34 +++++++++++++++++-------- src/translib/transformer/xlate_utils.go | 16 ++++++++++-- src/translib/transformer/xspec.go | 21 ++++++++++++++- 3 files changed, 58 insertions(+), 13 deletions(-) diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index 57c68f3707..f2e77575f2 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -130,9 +130,13 @@ func dbMapCreate(keyName string, xpathPrefix string, jsonData interface{}, resul if directDbMapData(key.String(), jData.MapIndex(key).Interface(), result) { continue } else { - xpath := xpathPrefix + "/" + key.String() + pathAttr := key.String() + if strings.Contains(pathAttr, ":") { + pathAttr = strings.Split(pathAttr, ":")[1] + } + xpath := xpathPrefix + "/" + pathAttr - if len(xSpecMap[xpath].xfmrFunc) > 0 { + if xSpecMap[xpath] != nil && len(xSpecMap[xpath].xfmrFunc) > 0 { subMap := callXfmr() // map[string]map[string]db.Value //subMap := XlateFuncCall(xpathInfo.xfmrFunc, name, value) @@ -143,11 +147,18 @@ func dbMapCreate(keyName string, xpathPrefix string, jsonData interface{}, resul } } } else { + pathAttr := key.String() + if strings.Contains(pathAttr, ":") { + pathAttr = strings.Split(pathAttr, ":")[1] + } value := jData.MapIndex(key).Interface() log.Info("data field: key(\"%v\"), value(\"%v\").", key, value) - err := mapFillData(keyName, result, xpathPrefix, key.String(), fmt.Sprintf("%v", value)) - log.Errorf("Failed constructing data for db write: key(\"%v\"), value(\"%v\"), path(\"%v\").", key, value, xpathPrefix) - return err + err := mapFillData(keyName, result, xpathPrefix, pathAttr, fmt.Sprintf("%v", value)) + if err != nil { + log.Errorf("Failed constructing data for db write: key(\"%v\"), value(\"%v\"), path(\"%v\").", + pathAttr, value, xpathPrefix) + return err + } } } } @@ -159,19 +170,22 @@ func dbMapCreate(keyName string, xpathPrefix string, jsonData interface{}, resul func xpathKeyExtract(path string) (string, string) { yangXpath := "" keyStr := "" - rgp := regexp.MustCompile(`\[(.*?)\]`) + rgp := regexp.MustCompile(`\[([^\[\]]*)\]`) + for i, k := range (strings.Split(path, "/")) { if i > 0 { yangXpath += "/" } xpath := k if strings.Contains(k, "[") { - kval := keyFromXpathCreate(rgp.FindStringSubmatch(k)[1]) - xpath = strings.Split(k, "[")[0] if len(keyStr) > 0 { keyStr += "|" } - keyStr += kval + xpath = strings.Split(k, "[")[0] + var keyl []string + for _, kname := range rgp.FindAllString(k, -1) { + keyl = append(keyl, strings.TrimRight(strings.TrimLeft(kname, "["), "]")) + } + keyStr += keyFromXpathCreate(keyl) } yangXpath += xpath } - return yangXpath, keyStr } diff --git a/src/translib/transformer/xlate_utils.go b/src/translib/transformer/xlate_utils.go index c532622b8c..a79a28a87e 100644 --- a/src/translib/transformer/xlate_utils.go +++ b/src/translib/transformer/xlate_utils.go @@ -7,10 +7,13 @@ import ( ) /* Create db key from datd xpath(request) */ -func keyFromXpathCreate(keys string) string { +func keyFromXpathCreate(keyList []string) string { keyOut := "" - for i, k := range (strings.Split(keys, " ")) { + for i, k := range keyList { if i > 0 { keyOut += "_" } + if strings.Contains(k, ":") { + k = strings.Split(k, ":")[1] + } keyOut += strings.Split(k, "=")[1] } return keyOut @@ -49,3 +52,12 @@ func mapCopy(destnMap map[string]map[string]db.Value, srcMap map[string]map[stri } } +func parentXpathGet(xpath string) string { + path := "" + if len(xpath) > 0 { + p := strings.Split(xpath, "/") + path = strings.Join(p[:len(p)-1], "/") + } + return path +} + diff --git a/src/translib/transformer/xspec.go b/src/translib/transformer/xspec.go index a36a53c76b..c7ed6e83ff 100644 --- a/src/translib/transformer/xspec.go +++ b/src/translib/transformer/xspec.go @@ -13,6 +13,7 @@ import ( type yangXpathInfo struct { yangDataType string tableName *string + childTable []string dbEntry *yang.Entry yangEntry *yang.Entry keyXpath map[int]*[]string @@ -150,6 +151,23 @@ func dbMapBuild(entries []*yang.Entry) { dbMapPrint(xSpecMap) } +func childToUpdateParent( xpath string, tableName string) { + var xpathData *yangXpathInfo + parent := parentXpathGet(xpath) + if len(parent) == 0 || parent == "/" { + return + } + + fmt.Printf(" Parent Table: %v\r\n", parent) + _, ok := xSpecMap[parent] + if !ok { + xpathData = new(yangXpathInfo) + xSpecMap[parent] = xpathData + } + xSpecMap[parent].childTable = append(xSpecMap[parent].childTable, tableName) + childToUpdateParent(parent, tableName) +} + /* Build lookup map based on yang xpath */ func annotEntryFill(xSpecMap map[string]*yangXpathInfo, xpath string, entry *yang.Entry) { xpathData := new(yangXpathInfo) @@ -169,7 +187,8 @@ func annotEntryFill(xSpecMap map[string]*yangXpathInfo, xpath string, entry *yan xpathData.tableName = new(string) } *xpathData.tableName = ext.NName() - updateDbTableData(xpathData, ext.NName()) + updateDbTableData(xpathData, *xpathData.tableName) + childToUpdateParent(xpath, *xpathData.tableName) case "field-name" : xpathData.fieldName = ext.NName() case "subtree-transformer" : From fa0b4ac7b06b62c66a3c78187d58216666fb9710 Mon Sep 17 00:00:00 2001 From: s-mari Date: Mon, 12 Aug 2019 16:51:46 -0700 Subject: [PATCH 024/214] Support for update, replace and delete request --- src/translib/transformer/xlate_to_db.go | 30 ++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index f2e77575f2..0b30b4c854 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -102,7 +102,35 @@ func directDbMapData(tableName string, jsonData interface{}, result map[string]m return false } -/* Get the data from incoming request, create map and fill with dbValue(ie. field:value +/* Get the db table, key and field name for the incoming delete request */ +func dbMapDelete(path string, jsonData interface{}, result map[string]map[string]db.Value) error { + xpathPrefix, keyName := xpathKeyExtract(path) + log.Info("Delete req: path(\"%v\"), key(\"%v\"), xpathPrefix(\"%v\").", path, keyName, xpathPrefix) + spec, ok := xSpecMap[xpathPrefix] + if ok && spec.tableName != nil { + result[*spec.tableName] = make(map[string]db.Value) + if len(keyName) > 0 { + result[*spec.tableName][keyName] = db.Value{Field: make(map[string]string)} + if spec.yangEntry != nil && spec.yangEntry.Node.Statement().Keyword == "leaf" { + result[*spec.tableName][keyName].Field[spec.fieldName] = "" + } + } + } + log.Info("Delete req: path(\"%v\") result(\"%v\").", path, result) + return nil +} + +/* Get the data from incoming update/replace request, create map and fill with dbValue(ie. field:value + to write into redis-db */ +func dbMapUpdate(path string, jsonData interface{}, result map[string]map[string]db.Value) error { + xpathPrefix, keyName := xpathKeyExtract(path) + log.Info("Update/replace req: path(\"%v\"), key(\"%v\"), xpathPrefix(\"%v\").", path, keyName, xpathPrefix) + dbMapCreate(keyName, parentXpathGet(xpathPrefix), jsonData, result) + log.Info("Update/replace req: path(\"%v\") result(\"%v\").", path, result) + return nil +} + +/* Get the data from incoming create request, create map and fill with dbValue(ie. field:value to write into redis-db */ func dbMapCreate(keyName string, xpathPrefix string, jsonData interface{}, result map[string]map[string]db.Value) error { log.Info("key(\"%v\"), xpathPrefix(\"%v\").", keyName, xpathPrefix) From 11b497d39902db3134c2ed4d205871235dcfe3dc Mon Sep 17 00:00:00 2001 From: s-mari Date: Tue, 13 Aug 2019 00:07:00 -0700 Subject: [PATCH 025/214] Updated xdbspec to include yang-xpath info and modified db-xpath creation only for valid types --- src/translib/transformer/xlate_to_db.go | 7 +-- src/translib/transformer/xlate_utils.go | 7 +++ src/translib/transformer/xspec.go | 59 ++++++++++++++++++------- 3 files changed, 54 insertions(+), 19 deletions(-) diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index 0b30b4c854..84ffea52e6 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -76,15 +76,16 @@ func callXfmr() map[string]map[string]db.Value { } func directDbMapData(tableName string, jsonData interface{}, result map[string]map[string]db.Value) bool { - dbSpecData, ok := xDbSpecMap[tableName] + _, ok := xDbSpecMap[tableName] - if ok && reflect.ValueOf(jsonData).Kind() == reflect.Slice { + if ok && xDbSpecMap[tableName].dbEntry != nil && reflect.ValueOf(jsonData).Kind() == reflect.Slice { + dbSpecData := xDbSpecMap[tableName].dbEntry tblKeyName := strings.Split(dbSpecData.Key, " ") data := reflect.ValueOf(jsonData) - keyName := "" result[tableName] = make(map[string]db.Value) for idx := 0; idx < data.Len(); idx++ { + keyName := "" d := data.Index(idx).Interface().(map[string]interface{}) for i, k := range tblKeyName { if i > 0 { keyName += "|" } diff --git a/src/translib/transformer/xlate_utils.go b/src/translib/transformer/xlate_utils.go index a79a28a87e..a72d1963b7 100644 --- a/src/translib/transformer/xlate_utils.go +++ b/src/translib/transformer/xlate_utils.go @@ -61,3 +61,10 @@ func parentXpathGet(xpath string) string { return path } +func isYangResType(ytype string) bool { + if ytype == "choose" || ytype == "case" { + return true + } + return false +} + diff --git a/src/translib/transformer/xspec.go b/src/translib/transformer/xspec.go index c7ed6e83ff..b72567cb3e 100644 --- a/src/translib/transformer/xspec.go +++ b/src/translib/transformer/xspec.go @@ -23,14 +23,21 @@ type yangXpathInfo struct { xfmrKey string } +type dbInfo struct { + fieldType string + dbEntry *yang.Entry + yangXpath []string +} + var xSpecMap map[string]*yangXpathInfo -var xDbSpecMap map[string]*yang.Entry +var xDbSpecMap map[string]*dbInfo /* update transformer spec with db-node */ -func updateDbTableData (xpathData *yangXpathInfo, tableName string) { +func updateDbTableData (xpath string, xpathData *yangXpathInfo, tableName string) { _, ok := xDbSpecMap[tableName] if ok { - xpathData.dbEntry = xDbSpecMap[tableName] + xDbSpecMap[tableName].yangXpath = append(xDbSpecMap[tableName].yangXpath, xpath) + xpathData.dbEntry = xDbSpecMap[tableName].dbEntry } } @@ -61,13 +68,22 @@ func yangToDbMapFill (xSpecMap map[string]*yangXpathInfo, entry *yang.Entry, xpa } if xpathData.yangDataType == "leaf" && len(xpathData.fieldName) == 0 { - if xpathData.tableName != nil && xDbSpecMap[*xpathData.tableName] != nil && - (xDbSpecMap[*xpathData.tableName].Dir[entry.Name] != nil || - xDbSpecMap[*xpathData.tableName].Dir[strings.ToUpper(entry.Name)] != nil) { - xpathData.fieldName = strings.ToUpper(entry.Name) - } + if xpathData.tableName != nil && xDbSpecMap[*xpathData.tableName] != nil { + if xDbSpecMap[*xpathData.tableName].dbEntry.Dir[entry.Name] != nil { + xpathData.fieldName = entry.Name + } else if xDbSpecMap[*xpathData.tableName].dbEntry.Dir[strings.ToUpper(entry.Name)] != nil { + xpathData.fieldName = strings.ToUpper(entry.Name) + } + } } + if xpathData.yangDataType == "leaf" && len(xpathData.fieldName) > 0 && xpathData.tableName != nil { + dbPath := *xpathData.tableName + "/" + xpathData.fieldName + if xDbSpecMap[dbPath] != nil { + xDbSpecMap[dbPath].yangXpath = append(xDbSpecMap[dbPath].yangXpath, xpath) + } + } + /* fill table with key data. */ if len(entry.Key) != 0 { parentKeyLen := 0 @@ -119,10 +135,20 @@ func yangToDbMapBuild(entries map[string]*yang.Entry) { } /* Fill the map with db details */ -func dbMapFill(xDbSpecMap map[string]*yang.Entry, entry *yang.Entry) { +func dbMapFill(prefixPath string, curPath string, xDbSpecMap map[string]*dbInfo, entry *yang.Entry) { entryType := entry.Node.Statement().Keyword if entryType == "list" { - xDbSpecMap[entry.Name] = entry + prefixPath = entry.Name + } + + if !isYangResType(entryType) { + dbXpath := prefixPath + if entryType != "list" { + dbXpath = prefixPath + "/" + entry.Name + } + xDbSpecMap[dbXpath] = new(dbInfo) + xDbSpecMap[dbXpath].dbEntry = entry + xDbSpecMap[dbXpath].fieldType = entryType } var childList []string @@ -131,7 +157,7 @@ func dbMapFill(xDbSpecMap map[string]*yang.Entry, entry *yang.Entry) { } sort.Strings(childList) for _, child := range childList { - dbMapFill(xDbSpecMap, entry.Dir[child]) + dbMapFill(prefixPath, prefixPath + "/" + entry.Dir[child].Name, xDbSpecMap, entry.Dir[child]) } } @@ -140,13 +166,13 @@ func dbMapBuild(entries []*yang.Entry) { if entries == nil { return } - xDbSpecMap = make(map[string]*yang.Entry) + xDbSpecMap = make(map[string]*dbInfo) for _, e := range entries { if e == nil || len(e.Dir) == 0 { continue } - dbMapFill(xDbSpecMap, e) + dbMapFill("", "", xDbSpecMap, e) } dbMapPrint(xSpecMap) } @@ -158,13 +184,15 @@ func childToUpdateParent( xpath string, tableName string) { return } - fmt.Printf(" Parent Table: %v\r\n", parent) _, ok := xSpecMap[parent] if !ok { xpathData = new(yangXpathInfo) xSpecMap[parent] = xpathData } xSpecMap[parent].childTable = append(xSpecMap[parent].childTable, tableName) + if xSpecMap[parent].yangEntry != nil && xSpecMap[parent].yangEntry.Node.Statement().Keyword == "list" { + return + } childToUpdateParent(parent, tableName) } @@ -187,7 +215,7 @@ func annotEntryFill(xSpecMap map[string]*yangXpathInfo, xpath string, entry *yan xpathData.tableName = new(string) } *xpathData.tableName = ext.NName() - updateDbTableData(xpathData, *xpathData.tableName) + updateDbTableData(xpath, xpathData, *xpathData.tableName) childToUpdateParent(xpath, *xpathData.tableName) case "field-name" : xpathData.fieldName = ext.NName() @@ -236,7 +264,6 @@ func annotToDbMapBuild(annotEntries []*yang.Entry) { if i == 2 { for _, ye := range deviate { fmt.Println(ye.Name) - fmt.Printf(" Annot fill:(%v)\r\n", xpath) annotEntryFill(xSpecMap, xpath, ye) } } From 3834a8dfeac0d9486bcc30310e4165941e3f5cb7 Mon Sep 17 00:00:00 2001 From: amrutasali Date: Tue, 13 Aug 2019 14:03:28 +0000 Subject: [PATCH 026/214] Added PathInfo to Common App structure --- src/translib/common_app.go | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/translib/common_app.go b/src/translib/common_app.go index d4e7258da0..555bfbf649 100644 --- a/src/translib/common_app.go +++ b/src/translib/common_app.go @@ -19,7 +19,7 @@ var ( ) type CommonApp struct { - path string + pathInfo *PathInfo ygotRoot *ygot.GoStruct ygotTarget *interface{} } @@ -52,14 +52,15 @@ func init() { func (app *CommonApp) initialize(data appData) { log.Info("initialize:path =", data.path) - *app = CommonApp{path: data.path, ygotRoot: data.ygotRoot, ygotTarget: data.ygotTarget} + pathInfo := NewPathInfo(data.path) + *app = CommonApp{pathInfo: pathInfo, ygotRoot: data.ygotRoot, ygotTarget: data.ygotTarget} } func (app *CommonApp) translateCreate(d *db.DB) ([]db.WatchKeys, error) { var err error var keys []db.WatchKeys - log.Info("translateCreate:path =", app.path) + log.Info("translateCreate:path =", app.pathInfo.Path) keys, err = app.translateCRUCommon(d, CREATE) @@ -69,7 +70,7 @@ func (app *CommonApp) translateCreate(d *db.DB) ([]db.WatchKeys, error) { func (app *CommonApp) translateUpdate(d *db.DB) ([]db.WatchKeys, error) { var err error var keys []db.WatchKeys - log.Info("translateUpdate:path =", app.path) + log.Info("translateUpdate:path =", app.pathInfo.Path) keys, err = app.translateCRUCommon(d, UPDATE) @@ -79,7 +80,7 @@ func (app *CommonApp) translateUpdate(d *db.DB) ([]db.WatchKeys, error) { func (app *CommonApp) translateReplace(d *db.DB) ([]db.WatchKeys, error) { var err error var keys []db.WatchKeys - log.Info("translateReplace:path =", app.path) + log.Info("translateReplace:path =", app.pathInfo.Path) //keys, err = app.translateCRUCommon(d, REPLACE) @@ -90,7 +91,7 @@ func (app *CommonApp) translateReplace(d *db.DB) ([]db.WatchKeys, error) { func (app *CommonApp) translateDelete(d *db.DB) ([]db.WatchKeys, error) { var err error var keys []db.WatchKeys - log.Info("translateDelete:path =", app.path) + log.Info("translateDelete:path =", app.pathInfo.Path) keys, err = app.generateDbWatchKeys(d, true) @@ -99,7 +100,7 @@ func (app *CommonApp) translateDelete(d *db.DB) ([]db.WatchKeys, error) { func (app *CommonApp) translateGet(dbs [db.MaxDB]*db.DB) error { var err error - log.Info("translateGet:path =", app.path) + log.Info("translateGet:path =", app.pathInfo.Path) return err } @@ -115,7 +116,7 @@ func (app *CommonApp) processCreate(d *db.DB) (SetResponse, error) { var err error var resp SetResponse - log.Info("processCreate:path =", app.path) + log.Info("processCreate:path =", app.pathInfo.Path) targetType := reflect.TypeOf(*app.ygotTarget) log.Infof("processCreate: Target object is a <%s> of Type: %s", targetType.Kind().String(), targetType.Elem().Name()) @@ -126,7 +127,7 @@ func (app *CommonApp) processCreate(d *db.DB) (SetResponse, error) { func (app *CommonApp) processUpdate(d *db.DB) (SetResponse, error) { var err error var resp SetResponse - log.Info("processUpdate:path =", app.path) + log.Info("processUpdate:path =", app.pathInfo.Path) return resp, err } @@ -134,7 +135,7 @@ func (app *CommonApp) processUpdate(d *db.DB) (SetResponse, error) { func (app *CommonApp) processReplace(d *db.DB) (SetResponse, error) { var err error var resp SetResponse - log.Info("processReplace:path =", app.path) + log.Info("processReplace:path =", app.pathInfo.Path) err = errors.New("Not implemented") return resp, err } @@ -143,11 +144,11 @@ func (app *CommonApp) processDelete(d *db.DB) (SetResponse, error) { var err error var resp SetResponse - log.Info("processDelete:path =", app.path) + log.Info("processDelete:path =", app.pathInfo.Path) //aclObj := app.getAppRootObject() - //targetUriPath, err := getYangPathFromUri(app.path) + //targetUriPath, err := getYangPathFromUri(app.pathInfo.Path) return resp, err @@ -163,7 +164,7 @@ func (app *CommonApp) processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error) { func (app *CommonApp) translateCRUCommon(d *db.DB, opcode int) ([]db.WatchKeys, error) { var err error var keys []db.WatchKeys - log.Info("translateCRUCommon:path =", app.path) + log.Info("translateCRUCommon:path =", app.pathInfo.Path) // translate yang to db result, err := transformer.XlateToDb((*app).ygotRoot, (*app).ygotTarget) From 6a26fa6b9c6db7934e05fc244d38fc5359685f61 Mon Sep 17 00:00:00 2001 From: Ravi Vasanthm Date: Tue, 13 Aug 2019 11:26:08 -0700 Subject: [PATCH 027/214] Modified acl xfmr methods prefix Read_/Write_ to YangToDb_/DbToYang_ --- src/translib/transformer/xfmr_acl.go | 88 ++++++++++++++-------------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/src/translib/transformer/xfmr_acl.go b/src/translib/transformer/xfmr_acl.go index 9b036280a3..03d37bfc30 100644 --- a/src/translib/transformer/xfmr_acl.go +++ b/src/translib/transformer/xfmr_acl.go @@ -18,20 +18,20 @@ import ( ) func init () { - XlateFuncBind("Read_acl_entry_key_xfmr", Read_acl_entry_key_xfmr) - XlateFuncBind("Write_acl_entry_key_xfmr", Write_acl_entry_key_xfmr) - XlateFuncBind("Read_acl_l2_ethertype_xfmr", Read_acl_l2_ethertype_xfmr) - XlateFuncBind("Write_acl_l2_ethertype_xfmr", Write_acl_l2_ethertype_xfmr) - XlateFuncBind("Read_acl_ip_protocol_xfmr", Read_acl_ip_protocol_xfmr) - XlateFuncBind("Write_acl_ip_protocol_xfmr", Write_acl_ip_protocol_xfmr) - XlateFuncBind("Read_acl_source_port_xfmr", Read_acl_source_port_xfmr) - XlateFuncBind("Write_acl_source_port_xfmr", Write_acl_source_port_xfmr) - XlateFuncBind("Read_acl_destination_port_xfmr", Read_acl_destination_port_xfmr) - XlateFuncBind("Write_acl_destination_port_xfmr", Write_acl_destination_port_xfmr) - XlateFuncBind("Read_acl_tcp_flags_xfmr", Read_acl_tcp_flags_xfmr) - XlateFuncBind("Write_acl_tcp_flags_xfmr", Write_acl_tcp_flags_xfmr) - XlateFuncBind("Read_acl_port_bindings_xfmr", Read_acl_port_bindings_xfmr) - XlateFuncBind("Write_acl_port_bindings_xfmr", Write_acl_port_bindings_xfmr) + XlateFuncBind("YangToDb_acl_entry_key_xfmr", YangToDb_acl_entry_key_xfmr) + XlateFuncBind("DbToYang_acl_entry_key_xfmr", DbToYang_acl_entry_key_xfmr) + XlateFuncBind("YangToDb_acl_l2_ethertype_xfmr", YangToDb_acl_l2_ethertype_xfmr) + XlateFuncBind("DbToYang_acl_l2_ethertype_xfmr", DbToYang_acl_l2_ethertype_xfmr) + XlateFuncBind("YangToDb_acl_ip_protocol_xfmr", YangToDb_acl_ip_protocol_xfmr) + XlateFuncBind("DbToYang_acl_ip_protocol_xfmr", DbToYang_acl_ip_protocol_xfmr) + XlateFuncBind("YangToDb_acl_source_port_xfmr", YangToDb_acl_source_port_xfmr) + XlateFuncBind("DbToYang_acl_source_port_xfmr", DbToYang_acl_source_port_xfmr) + XlateFuncBind("YangToDb_acl_destination_port_xfmr", YangToDb_acl_destination_port_xfmr) + XlateFuncBind("DbToYang_acl_destination_port_xfmr", DbToYang_acl_destination_port_xfmr) + XlateFuncBind("YangToDb_acl_tcp_flags_xfmr", YangToDb_acl_tcp_flags_xfmr) + XlateFuncBind("DbToYang_acl_tcp_flags_xfmr", DbToYang_acl_tcp_flags_xfmr) + XlateFuncBind("YangToDb_acl_port_bindings_xfmr", YangToDb_acl_port_bindings_xfmr) + XlateFuncBind("DbToYang_acl_port_bindings_xfmr", DbToYang_acl_port_bindings_xfmr) } const ( @@ -186,11 +186,11 @@ func getL2EtherType(etherType uint64) interface{} { -var Read_acl_entry_key_xfmr KeyXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, xpath string) (string, error) { +var YangToDb_acl_entry_key_xfmr KeyXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, xpath string) (string, error) { var entry_key string var err error var oc_aclType ocbinds.E_OpenconfigAcl_ACL_TYPE - log.Info("Read_acl_entry_key_xfmr: ", ygRoot, xpath) + log.Info("YangToDb_acl_entry_key_xfmr: ", ygRoot, xpath) pathInfo := NewPathInfo(xpath) if len(pathInfo.Vars) < 3 { @@ -211,15 +211,15 @@ var Read_acl_entry_key_xfmr KeyXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStr } entry_key = aclkey + "|" + rulekey - log.Info("Read_acl_entry_key_xfmr - entry_key : ", entry_key) + log.Info("YangToDb_acl_entry_key_xfmr - entry_key : ", entry_key) return entry_key, err } -var Write_acl_entry_key_xfmr KeyXfmrDbToYang = func (d *db.DB, entry_key string) (map[string]map[string]string, error) { +var DbToYang_acl_entry_key_xfmr KeyXfmrDbToYang = func (d *db.DB, entry_key string) (map[string]map[string]string, error) { res_map := make(map[string]map[string]string) var err error - log.Info("Write_acl_entry_key_xfmr: ", entry_key) + log.Info("DbToYang_acl_entry_key_xfmr: ", entry_key) key := strings.Split(entry_key, "|") if len(key) < 2 { @@ -235,7 +235,7 @@ var Write_acl_entry_key_xfmr KeyXfmrDbToYang = func (d *db.DB, entry_key string) res_map["oc-acl:acl-set"]["type"] = aclType.ΛMap()["E_OpenconfigAcl_ACL_TYPE"][int64(aclType)].Name seqId := strings.Replace(dbAclRule, "RULE_", "", 1) res_map["acl-entry"]["sequence-id"] = seqId - log.Info("Write_acl_entry_key_xfmr - res_map: ", res_map) + log.Info("DbToYang_acl_entry_key_xfmr - res_map: ", res_map) return res_map, err } @@ -260,10 +260,10 @@ func getAclRule(acl *ocbinds.OpenconfigAcl_Acl, aclName string, aclType ocbinds. return rule, err } -var Read_acl_l2_ethertype_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, xpath string, ethertype interface {}) (map[string]string, error) { +var YangToDb_acl_l2_ethertype_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, xpath string, ethertype interface {}) (map[string]string, error) { res_map := make(map[string]string) var err error - log.Info("Read_acl_l2_ethertype_xfmr :", ygRoot, xpath) + log.Info("YangToDb_acl_l2_ethertype_xfmr :", ygRoot, xpath) ethertypeType := reflect.TypeOf(ethertype).Elem() var b bytes.Buffer @@ -282,9 +282,9 @@ var Read_acl_l2_ethertype_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot. return res_map, err } -var Write_acl_l2_ethertype_xfmr FieldXfmrDbtoYang = func (d *db.DB, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct) (error) { +var DbToYang_acl_l2_ethertype_xfmr FieldXfmrDbtoYang = func (d *db.DB, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct) (error) { var err error - log.Info("Write_acl_l2_ethertype_xfmr", data, ygRoot) + log.Info("DbToYang_acl_l2_ethertype_xfmr", data, ygRoot) if _, ok := data[RULE_TABLE]; !ok { err = errors.New("RULE_TABLE entry not found in the input param") @@ -317,10 +317,10 @@ var Write_acl_l2_ethertype_xfmr FieldXfmrDbtoYang = func (d *db.DB, data map[str return err } -var Read_acl_ip_protocol_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, xpath string, protocol interface {}) (map[string]string, error) { +var YangToDb_acl_ip_protocol_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, xpath string, protocol interface {}) (map[string]string, error) { res_map := make(map[string]string) var err error - log.Info("Read_acl_ip_protocol_xfmr: ", ygRoot, xpath) + log.Info("YangToDb_acl_ip_protocol_xfmr: ", ygRoot, xpath) protocolType := reflect.TypeOf(protocol).Elem() switch (protocolType) { @@ -336,9 +336,9 @@ var Read_acl_ip_protocol_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.G return res_map, err } -var Write_acl_ip_protocol_xfmr FieldXfmrDbtoYang = func (d *db.DB, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct) (error) { +var DbToYang_acl_ip_protocol_xfmr FieldXfmrDbtoYang = func (d *db.DB, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct) (error) { var err error - log.Info("Write_acl_ip_protocol_xfmr ", data, ygRoot) + log.Info("DbToYang_acl_ip_protocol_xfmr ", data, ygRoot) if _, ok := data[RULE_TABLE]; !ok { err = errors.New("RULE_TABLE entry not found in the input param") return err @@ -368,10 +368,10 @@ var Write_acl_ip_protocol_xfmr FieldXfmrDbtoYang = func (d *db.DB, data map[stri return err } -var Read_acl_source_port_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, xpath string, value interface {}) (map[string]string, error) { +var YangToDb_acl_source_port_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, xpath string, value interface {}) (map[string]string, error) { res_map := make(map[string]string) var err error; - log.Info("Read_acl_source_port_xfmr: ", ygRoot, xpath) + log.Info("YangToDb_acl_source_port_xfmr: ", ygRoot, xpath) sourceportType := reflect.TypeOf(value).Elem() switch sourceportType { case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort_Union_E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort{}): @@ -431,9 +431,9 @@ func getAclSetEntry (aclRuleKey string, ygRoot *ygot.GoStruct) (*ocbinds.Opencon } -var Write_acl_source_port_xfmr FieldXfmrDbtoYang = func (d *db.DB, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct) (error) { +var DbToYang_acl_source_port_xfmr FieldXfmrDbtoYang = func (d *db.DB, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct) (error) { var err error - log.Info("Write_acl_source_port_xfmr: ", data, ygRoot) + log.Info("DbToYang_acl_source_port_xfmr: ", data, ygRoot) if _, ok := data[RULE_TABLE]; !ok { err = errors.New("RULE_TABLE entry not found in the input param") @@ -470,10 +470,10 @@ var Write_acl_source_port_xfmr FieldXfmrDbtoYang = func (d *db.DB, data map[stri return err } -var Read_acl_destination_port_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, xpath string, value interface{}) (map[string]string, error) { +var YangToDb_acl_destination_port_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, xpath string, value interface{}) (map[string]string, error) { res_map := make(map[string]string) var err error; - log.Info("Read_acl_destination_port_xfmr: ", ygRoot, xpath) + log.Info("YangToDb_acl_destination_port_xfmr: ", ygRoot, xpath) destportType := reflect.TypeOf(value).Elem() switch destportType { case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort_Union_E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort{}): @@ -492,9 +492,9 @@ var Read_acl_destination_port_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *y return res_map, err } -var Write_acl_destination_port_xfmr FieldXfmrDbtoYang = func (d *db.DB, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct) (error) { +var DbToYang_acl_destination_port_xfmr FieldXfmrDbtoYang = func (d *db.DB, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct) (error) { var err error - log.Info("Write_acl_destination_port_xfmr: ", data, ygRoot) + log.Info("DbToYang_acl_destination_port_xfmr: ", data, ygRoot) if _, ok := data[RULE_TABLE]; !ok { err = errors.New("RULE_TABLE entry not found in the input param") return err @@ -530,10 +530,10 @@ var Write_acl_destination_port_xfmr FieldXfmrDbtoYang = func (d *db.DB, data map return err } -var Read_acl_tcp_flags_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, xpath string, value interface {}) (map[string]string, error) { +var YangToDb_acl_tcp_flags_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, xpath string, value interface {}) (map[string]string, error) { res_map := make(map[string]string) var err error; - log.Info("Read_acl_tcp_flags_xfmr: ", ygRoot, xpath) + log.Info("YangToDb_acl_tcp_flags_xfmr: ", ygRoot, xpath) var tcpFlags uint32 = 0x00 v := reflect.ValueOf(value) @@ -573,9 +573,9 @@ var Read_acl_tcp_flags_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoS return res_map, err } -var Write_acl_tcp_flags_xfmr FieldXfmrDbtoYang = func (d *db.DB, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct) (error) { +var DbToYang_acl_tcp_flags_xfmr FieldXfmrDbtoYang = func (d *db.DB, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct) (error) { var err error - log.Info("Write_acl_tcp_flags_xfmr: ", data, ygRoot) + log.Info("DbToYang_acl_tcp_flags_xfmr: ", data, ygRoot) if _, ok := data[RULE_TABLE]; !ok { err = errors.New("RULE_TABLE entry not found in the input param") @@ -604,11 +604,11 @@ var Write_acl_tcp_flags_xfmr FieldXfmrDbtoYang = func (d *db.DB, data map[string return err } -var Read_acl_port_bindings_xfmr SubTreeXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, xpath string) (map[string]map[string]db.Value, error) { +var YangToDb_acl_port_bindings_xfmr SubTreeXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, xpath string) (map[string]map[string]db.Value, error) { res_map := make(map[string]map[string]db.Value) aclTableMap := make(map[string]db.Value) var err error; - log.Info("Read_acl_port_bindings_xfmr: ", ygRoot, xpath) + log.Info("YangToDb_acl_port_bindings_xfmr: ", ygRoot, xpath) aclObj := getAclRoot(ygRoot) @@ -656,8 +656,8 @@ var Read_acl_port_bindings_xfmr SubTreeXfmrYangToDb = func (d *db.DB, ygRoot *yg return res_map, err } -var Write_acl_port_bindings_xfmr SubTreeXfmrDbToYang = func (d *db.DB, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct) (error) { +var DbToYang_acl_port_bindings_xfmr SubTreeXfmrDbToYang = func (d *db.DB, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct) (error) { var err error - log.Info("Write_acl_port_bindings_xfmr: ", data, ygRoot) + log.Info("DbToYang_acl_port_bindings_xfmr: ", data, ygRoot) return err } From c1c19e5bcbbf78b472e4b45459f8813350b57c20 Mon Sep 17 00:00:00 2001 From: amrutasali Date: Wed, 14 Aug 2019 06:30:37 +0000 Subject: [PATCH 028/214] In common app added support to generate Tables to Watch dynamically --- src/translib/app_interface.go | 12 +++++------- src/translib/common_app.go | 25 ++++++++++++++++++++----- src/translib/translib.go | 6 +++--- 3 files changed, 28 insertions(+), 15 deletions(-) diff --git a/src/translib/app_interface.go b/src/translib/app_interface.go index ff91ebbeb6..6730e66259 100644 --- a/src/translib/app_interface.go +++ b/src/translib/app_interface.go @@ -43,7 +43,7 @@ type appData struct { } //map containing the base path to app module info -var appMap map[string]appInfo +var appMap map[string]*appInfo //array containg all the supported models var models []ModelData @@ -70,12 +70,12 @@ func register(path string, info *appInfo) error { log.Info("Registering for path =", path) if appMap == nil { - appMap = make(map[string]appInfo) + appMap = make(map[string]*appInfo) } if _, ok := appMap[path]; ok == false { - appMap[path] = *info + appMap[path] = info } else { log.Fatal("Duplicate path being registered. Path =", path) @@ -111,7 +111,7 @@ func unregister(path string) error { } //Translib infra will use this function get the app info for a given path -func getAppModuleInfo(path string) (appInfo, error) { +func getAppModuleInfo(path string) (*appInfo, error) { var err error log.Info("getAppModule called for path =", path) @@ -126,11 +126,9 @@ func getAppModuleInfo(path string) (appInfo, error) { } errStr := "Unsupported path=" + path - err = errors.New(errStr) log.Error(errStr) - - var app appInfo + var app *appInfo return app, err } diff --git a/src/translib/common_app.go b/src/translib/common_app.go index 555bfbf649..555fe71307 100644 --- a/src/translib/common_app.go +++ b/src/translib/common_app.go @@ -24,16 +24,18 @@ type CommonApp struct { ygotTarget *interface{} } +var cmnAppInfo = appInfo{appType: reflect.TypeOf(CommonApp{}), + ygotRootType: nil, + isNative: false, + tablesToWatch: nil} + + func init() { // @todo : Optimize to register supported paths/yang via common app and report error for unsupported register_model_path := []string{"/sonic-"} // register yang model path(s) to be supported via common app for _, mdl_pth := range register_model_path { - err := register(mdl_pth, - &appInfo{appType: reflect.TypeOf(CommonApp{}), - ygotRootType: nil, //interface{}, - isNative: false, - tablesToWatch: nil}) + err := register(mdl_pth, &cmnAppInfo) if err != nil { log.Fatal("Register Common app module with App Interface failed with error=", err, "for path=", mdl_pth) @@ -164,16 +166,29 @@ func (app *CommonApp) processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error) { func (app *CommonApp) translateCRUCommon(d *db.DB, opcode int) ([]db.WatchKeys, error) { var err error var keys []db.WatchKeys + var tblsToWatch []*db.TableSpec log.Info("translateCRUCommon:path =", app.pathInfo.Path) // translate yang to db result, err := transformer.XlateToDb((*app).ygotRoot, (*app).ygotTarget) fmt.Println(result) + log.Info("transformer.XlateToDb() returned", result) if err != nil { log.Error(err) return keys, err } + if len(result) == 0 { + log.Error("XlatetoDB() returned empty map") + fmt.Println("XlatetoDB() returned empty map") + } + for tblnm, _ := range result { + log.Error("Table name ", tblnm) + tblsToWatch = append(tblsToWatch, &db.TableSpec{Name: tblnm}) + } + log.Info("Tables to watch", tblsToWatch) + + cmnAppInfo.tablesToWatch = tblsToWatch keys, err = app.generateDbWatchKeys(d, false) diff --git a/src/translib/translib.go b/src/translib/translib.go index 7a323196c5..e71e699ff3 100644 --- a/src/translib/translib.go +++ b/src/translib/translib.go @@ -696,16 +696,16 @@ func getAppModule (path string) (*appInterface, *appInfo, error) { aInfo, err := getAppModuleInfo(path) if err != nil { - return nil, &aInfo, err + return nil, aInfo, err } app, err = getAppInterface(aInfo.appType) if err != nil { - return nil, &aInfo, err + return nil, aInfo, err } - return &app, &aInfo, err + return &app, aInfo, err } func appInitialize (app *appInterface, appInfo *appInfo, path string, payload *[]byte, opCode int) error { From c8b083090c2bfabfe9fa9e0e74b4093555e92913 Mon Sep 17 00:00:00 2001 From: s-mari Date: Wed, 14 Aug 2019 01:46:17 -0700 Subject: [PATCH 029/214] Updated details of nested child table in xspec map. Support to convert top-level db-map data to output json file, for get request. --- src/translib/transformer/xlate_from_db.go | 134 ++++++++++++++++++++++ src/translib/transformer/xlate_to_db.go | 1 - src/translib/transformer/xlate_utils.go | 12 ++ src/translib/transformer/xspec.go | 37 +++--- 4 files changed, 170 insertions(+), 14 deletions(-) create mode 100644 src/translib/transformer/xlate_from_db.go diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go new file mode 100644 index 0000000000..85317bd426 --- /dev/null +++ b/src/translib/transformer/xlate_from_db.go @@ -0,0 +1,134 @@ +package transformer + +import ( + "fmt" + "translib/db" + "strings" + "os" + + //log "github.com/golang/glog" +) + +/* Traverse db map and add data to json */ +func dataToJsonAdd(xpath string, fieldData map[string]string, key string, dbDataMap map[string]map[string]db.Value) string { + spec, ok := xSpecMap[xpath] + jsonData := "" + + if ok { + for fld := range spec.yangEntry.Dir { + fldXpath := xpath+"/"+fld + if xSpecMap[fldXpath] != nil && xSpecMap[fldXpath].yangEntry != nil { + ftype := yangTypeGet(xSpecMap[fldXpath].yangEntry) + if ftype == "leaf" { + /* Add db field and value to json, call xfmr if needed */ + fldName := xSpecMap[fldXpath].fieldName + if len(fldName) > 0 { + val, ok := fieldData[fldName] + if ok { + jsonData += fmt.Sprintf("\"%v\" : \"%v\",", xSpecMap[fldXpath].yangEntry.Name, val) + } + } + } else if ftype == "container" && xSpecMap[fldXpath].yangEntry.Name != "state" { + /* Create container enclosure and attach container name and add to json */ + data := dataToJsonAdd(fldXpath, fieldData, key, dbDataMap) + if len(data) > 0 { + jsonData += fmt.Sprintf("\"%v\" : { \r\n %v \r\n },", xSpecMap[fldXpath].yangEntry.Name, data) + } + } else if ftype == "list" { + /* Inner(child) list, traverse this list */ + childMap, ok := dbDataMap[*xSpecMap[fldXpath].tableName] + if ok { + var xpathl []string + xpathl = append(xpathl, fldXpath) + jsonData += listDataToJsonAdd(xpathl, childMap, key, dbDataMap) + } + } + } + } + /* Last node in json data in current context, trim extra "," in data, so that json data is valid */ + jsonData = strings.TrimRight(jsonData, ",") + } + return jsonData +} + +/* Traverse list data and add to json */ +func listDataToJsonAdd(xpathl []string, dataMap map[string]db.Value, key string, dbDataMap map[string]map[string]db.Value) string { + jsonData := "" + + for _, xpath := range xpathl { + for kname, data := range dataMap { + if len(key) > 0 && !strings.HasPrefix(kname, key) { + continue + } + dbKeyToYangDataConvert(kname, xpath) + /* Traverse list members and add to json */ + data := dataToJsonAdd(xpath, data.Field, kname, dbDataMap) + if len(data) > 0 { + /* Enclose all list instances with {} */ + jsonData += fmt.Sprintf("{\r\n %v },", data) + } + /* Added data to json, so delete current instance data */ + delete(dataMap, kname) + } + if len(jsonData) > 0 { + /* Last data in list,so trim extra "," in data, so that the json is valid */ + jsonData = strings.TrimRight(jsonData, ",") + /* Create list enclosure, attach list-name and add to json */ + jsonData = fmt.Sprintf("\"%v\" : [\r\n %v\r\n ]\r\n", xSpecMap[xpath].yangEntry.Name, jsonData) + } + } + return jsonData +} + +/* Traverse linear db-map data and add to nested json data */ +func dbDataToYangJsonCreate(dbDataMap map[string]map[string]db.Value) error { + jsonData := "" + curXpath := "" + for tblName, tblData := range dbDataMap { + if len(curXpath) == 0 || strings.HasPrefix(curXpath, xDbSpecMap[tblName].yangXpath[0]) { + curXpath = xDbSpecMap[tblName].yangXpath[0] + } + jsonData += listDataToJsonAdd(xDbSpecMap[tblName].yangXpath, tblData, "", dbDataMap) + } + jsonData = parentJsonDataUpdate(curXpath, jsonData) + jsonDataPrint(jsonData) + return nil +} + +func parentJsonDataUpdate(xpath string, data string) string { + curXpath := parentXpathGet(xpath) + if len(curXpath) == 0 && strings.Contains(xpath, ":") { + curXpath = strings.Split(xpath, ":")[0] + } + if xSpecMap[curXpath] != nil { + entry := xSpecMap[curXpath].yangEntry + entryType := entry.Node.Statement().Keyword + switch entryType { + case "container": + data = fmt.Sprintf("\"%v\" : { \r\n %v \r\n }", xSpecMap[curXpath].yangEntry.Name, data) + return parentJsonDataUpdate(curXpath, data) + case "list": + data = fmt.Sprintf("\"%v\" : [\r\n %v\r\n ]\r\n", xSpecMap[curXpath].yangEntry.Name, data) + return parentJsonDataUpdate(curXpath, data) + case "module": + data = fmt.Sprintf("\"%v\" : { \r\n %v \r\n }", xSpecMap[curXpath].yangEntry.Name, data) + return data + default: + return "" + } + } + return "" +} + +func jsonDataPrint(data string) { + fp, err := os.Create("/tmp/dbToYangJson.txt") + if err != nil { + return + } + defer fp.Close() + + fmt.Fprintf (fp, "-----------------------------------------------------------------\r\n") + fmt.Fprintf (fp, "%v \r\n", data) + fmt.Fprintf (fp, "-----------------------------------------------------------------\r\n") +} + diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index 84ffea52e6..71d291deee 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -186,7 +186,6 @@ func dbMapCreate(keyName string, xpathPrefix string, jsonData interface{}, resul if err != nil { log.Errorf("Failed constructing data for db write: key(\"%v\"), value(\"%v\"), path(\"%v\").", pathAttr, value, xpathPrefix) - return err } } } diff --git a/src/translib/transformer/xlate_utils.go b/src/translib/transformer/xlate_utils.go index a72d1963b7..3201e0b146 100644 --- a/src/translib/transformer/xlate_utils.go +++ b/src/translib/transformer/xlate_utils.go @@ -4,6 +4,7 @@ import ( "fmt" "strings" "translib/db" + "github.com/openconfig/goyang/pkg/yang" ) /* Create db key from datd xpath(request) */ @@ -68,3 +69,14 @@ func isYangResType(ytype string) bool { return false } +func yangTypeGet(entry *yang.Entry) string { + if entry != nil && entry.Node != nil { + return entry.Node.Statement().Keyword + } + return "" +} + +func dbKeyToYangDataConvert(dbKey string, xpath string) { + return +} + diff --git a/src/translib/transformer/xspec.go b/src/translib/transformer/xspec.go index b72567cb3e..19a84255b9 100644 --- a/src/translib/transformer/xspec.go +++ b/src/translib/transformer/xspec.go @@ -59,7 +59,11 @@ func yangToDbMapFill (xSpecMap map[string]*yangXpathInfo, entry *yang.Entry, xpa } else { xpathData = xSpecMap[xpath] } + xpathData.yangDataType = entry.Node.Statement().Keyword + if entry.Node.Statement().Keyword == "list" && xpathData.tableName != nil { + childToUpdateParent(xpath, *xpathData.tableName) + } parentXpathData, ok := xSpecMap[xpathPrefix] /* init current xpath table data with its parent data, change only if needed. */ @@ -89,10 +93,11 @@ func yangToDbMapFill (xSpecMap map[string]*yangXpathInfo, entry *yang.Entry, xpa parentKeyLen := 0 /* create list with current keys */ - keyXpath := make([]string, len(strings.Split(entry.Key, " "))) + keyXpath := make([]string, len(strings.Split(entry.Key, " "))) for id, keyName := range(strings.Split(entry.Key, " ")) { keyXpath[id] = xpath + "/" + keyName } + xpathData.keyXpath = make(map[int]*[]string, (parentKeyLen + 1)) k := 0 for ; k < parentKeyLen; k++ { @@ -132,6 +137,7 @@ func yangToDbMapBuild(entries map[string]*yang.Entry) { yangToDbMapFill(xSpecMap, e, "") } mapPrint(xSpecMap, "/tmp/fullSpec.txt") + dbMapPrint() } /* Fill the map with db details */ @@ -174,7 +180,6 @@ func dbMapBuild(entries []*yang.Entry) { } dbMapFill("", "", xDbSpecMap, e) } - dbMapPrint(xSpecMap) } func childToUpdateParent( xpath string, tableName string) { @@ -205,7 +210,7 @@ func annotEntryFill(xSpecMap map[string]*yangXpathInfo, xpath string, entry *yan } /* fill table with yang extension data. */ - if len(entry.Exts) > 0 { + if entry != nil && len(entry.Exts) > 0 { for _, ext := range entry.Exts { dataTagArr := strings.Split(ext.Keyword, ":") tagType := dataTagArr[len(dataTagArr)-1] @@ -216,7 +221,7 @@ func annotEntryFill(xSpecMap map[string]*yangXpathInfo, xpath string, entry *yan } *xpathData.tableName = ext.NName() updateDbTableData(xpath, xpathData, *xpathData.tableName) - childToUpdateParent(xpath, *xpathData.tableName) + //childToUpdateParent(xpath, *xpathData.tableName) case "field-name" : xpathData.fieldName = ext.NName() case "subtree-transformer" : @@ -239,13 +244,11 @@ func annotEntryFill(xSpecMap map[string]*yangXpathInfo, xpath string, entry *yan /* Build xpath from yang-annotation */ func xpathFromDevCreate(path string) string { - xpath := "" - for _, k := range (strings.Split(path, "/")) { - if len(k) > 0 { - xpath += strings.Split(k, ":")[1] + "/" - } - } - return xpath[:len(xpath)-1] + p := strings.Split(path, "/") + for i, k := range p { + if len(k) > 0 { p[i] = strings.Split(k, ":")[1] } + } + return strings.Join(p[1:], "/") } /* Build lookup map based on yang xpath */ @@ -320,12 +323,20 @@ func mapPrint(inMap map[string]*yangXpathInfo, fileName string) { } /* Debug function to print redis db lookup map */ -func dbMapPrint(inMap map[string]*yangXpathInfo) { +func dbMapPrint() { fp, err := os.Create("/tmp/dbTmplt.txt") if err != nil { return } defer fp.Close() - fmt.Fprintf(fp, "%v", xDbSpecMap) + fmt.Fprintf (fp, "-----------------------------------------------------------------\r\n") + for k, v := range xDbSpecMap { + fmt.Fprintf(fp, " field:%v \r\n", k) + fmt.Fprintf(fp, " type :%v \r\n", v.fieldType) + fmt.Fprintf(fp, " Yang :%v \r\n", v.yangXpath) + fmt.Fprintf(fp, " DB :%v \r\n", v.dbEntry) + fmt.Fprintf (fp, "-----------------------------------------------------------------\r\n") + + } } From e3beda0f9740de8e25e44e66ceb3316d5e058725 Mon Sep 17 00:00:00 2001 From: Ravi Vasanthm Date: Wed, 14 Aug 2019 11:45:07 -0700 Subject: [PATCH 030/214] Added DbToYang_acl_port_bindings_xfmr method to handle db to OC conversion of port mapping to acl set --- src/translib/transformer/xfmr_acl.go | 452 ++++++++++++++++++--- src/translib/transformer/xfmr_interface.go | 2 +- src/translib/transformer/xlate_utils.go | 36 ++ 3 files changed, 430 insertions(+), 60 deletions(-) diff --git a/src/translib/transformer/xfmr_acl.go b/src/translib/transformer/xfmr_acl.go index 03d37bfc30..1dafd3fb36 100644 --- a/src/translib/transformer/xfmr_acl.go +++ b/src/translib/transformer/xfmr_acl.go @@ -5,9 +5,6 @@ import ( "bytes" "errors" "strings" - // "os" - // "sort" - // "github.com/openconfig/goyang/pkg/yang" "github.com/openconfig/ygot/ygot" "strconv" "translib/db" @@ -43,6 +40,10 @@ const ( OPENCONFIG_ACL_TYPE_IPV4 = "ACL_IPV4" OPENCONFIG_ACL_TYPE_IPV6 = "ACL_IPV6" OPENCONFIG_ACL_TYPE_L2 = "ACL_L2" + ACL_TYPE = "type" + + MIN_PRIORITY = 1 + MAX_PRIORITY = 65535 ) var IP_PROTOCOL_MAP = map[ocbinds.E_OpenconfigPacketMatchTypes_IP_PROTOCOL]uint8{ @@ -73,6 +74,7 @@ func getAclRoot (s *ygot.GoStruct) *ocbinds.OpenconfigAcl_Acl { return deviceObj.Acl } + func getAclTypeOCEnumFromName(val string) (ocbinds.E_OpenconfigAcl_ACL_TYPE, error) { switch val { case "ACL_IPV4", "openconfig-acl:ACL_IPV4": @@ -239,27 +241,6 @@ var DbToYang_acl_entry_key_xfmr KeyXfmrDbToYang = func (d *db.DB, entry_key stri return res_map, err } -func getAclRule(acl *ocbinds.OpenconfigAcl_Acl, aclName string, aclType ocbinds.E_OpenconfigAcl_ACL_TYPE, seqId uint32) (*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry, error) { - var err error - var aclSetKey ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_Key - aclSetKey.Name = aclName - aclSetKey.Type = aclType - - if _, ok := acl.AclSets.AclSet[aclSetKey]; !ok { - err = errors.New("AclSet not found " + aclName) - return nil, err - } - - aclSet := acl.AclSets.AclSet[aclSetKey] - if _, ok := aclSet.AclEntries.AclEntry[seqId]; !ok { - err = errors.New("Acl Rule not found " + aclName + strconv.FormatInt(int64(seqId), 10)) - return nil, err - } - - rule := aclSet.AclEntries.AclEntry[seqId] - return rule, err -} - var YangToDb_acl_l2_ethertype_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, xpath string, ethertype interface {}) (map[string]string, error) { res_map := make(map[string]string) var err error @@ -312,8 +293,6 @@ var DbToYang_acl_l2_ethertype_xfmr FieldXfmrDbtoYang = func (d *db.DB, data map[ entrySet.L2.State.Ethertype, _ = entrySet.L2.State.To_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_L2_State_Ethertype_Union(ethertype) } - - return err } @@ -604,6 +583,86 @@ var DbToYang_acl_tcp_flags_xfmr FieldXfmrDbtoYang = func (d *db.DB, data map[str return err } +func convertDBAclRulesToInternal(dbCl *db.DB, aclName string, seqId int64, ruleKey db.Key) (ruleTableMap map[string]map[string]db.Value, ferr error) { + ruleTs := &db.TableSpec{Name: RULE_TABLE} + if seqId != -1 { + ruleKey.Comp = []string{aclName, "RULE_" + strconv.FormatInt(int64(seqId), 10)} + } + if ruleKey.Len() > 1 { + ruleName := ruleKey.Get(1) + if ruleName != "DEFAULT_RULE" { + ruleData, err := dbCl.GetEntry(ruleTs, ruleKey) + if err != nil { + ferr = err + return + } + if ruleTableMap[aclName] == nil { + ruleTableMap[aclName] = make(map[string]db.Value) + } + ruleTableMap[aclName][ruleName] = ruleData + } + } else { + ruleKeys, err := dbCl.GetKeys(ruleTs) + if err != nil { + ferr = err + return + } + for i, _ := range ruleKeys { + if aclName == ruleKeys[i].Get(0) { + ruleTableMap, ferr = convertDBAclRulesToInternal(dbCl, aclName, -1, ruleKeys[i]) + } + } + } + return +} + +func convertDBAclToInternal(dbCl *db.DB, aclkey db.Key) (aclTableMap map[string]db.Value, ruleTableMap map[string]map[string]db.Value, ferr error) { + aclTs := &db.TableSpec{Name: ACL_TABLE} + if aclkey.Len() > 0 { + // Get one particular ACL + entry, err := dbCl.GetEntry(aclTs, aclkey) + if err != nil { + ferr = err + return + } + if entry.IsPopulated() { + aclTableMap[aclkey.Get(0)] = entry + ruleTableMap[aclkey.Get(0)] = make(map[string]db.Value) + ruleTableMap, ferr = convertDBAclRulesToInternal(dbCl, aclkey.Get(0), -1, db.Key{}) + if err != nil { + ferr = err + return + } + } else { + ferr = tlerr.NotFound("Acl %s is not configured", aclkey.Get(0)) + return + } + } else { + // Get all ACLs + tbl, err := dbCl.GetTable(aclTs) + if err != nil { + ferr = err + return + } + keys, _ := tbl.GetKeys() + for i, _ := range keys { + aclTableMap, ruleTableMap, ferr = convertDBAclToInternal(dbCl, keys[i]) + } + } + return +} + +func getDbAlcTblsData (d *db.DB) (map[string]db.Value, map[string]map[string]db.Value, error) { + var err error + + aclTableMap := make(map[string]db.Value) + ruleTableMap := make(map[string]map[string]db.Value) + + aclTableMap, ruleTableMap, err = convertDBAclToInternal (d, db.Key{}) + + return aclTableMap, ruleTableMap, err +} + var YangToDb_acl_port_bindings_xfmr SubTreeXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, xpath string) (map[string]map[string]db.Value, error) { res_map := make(map[string]map[string]db.Value) aclTableMap := make(map[string]db.Value) @@ -612,52 +671,327 @@ var YangToDb_acl_port_bindings_xfmr SubTreeXfmrYangToDb = func (d *db.DB, ygRoot aclObj := getAclRoot(ygRoot) - if aclObj.Interfaces != nil && len(aclObj.Interfaces.Interface) > 0 { - aclInterfacesMap := make(map[string][]string) - for intfId, _ := range aclObj.Interfaces.Interface { - intf := aclObj.Interfaces.Interface[intfId] - if intf != nil { - if intf.IngressAclSets != nil && len(intf.IngressAclSets.IngressAclSet) > 0 { - for inAclKey, _ := range intf.IngressAclSets.IngressAclSet { - aclName := getAclKeyStrFromOCKey(inAclKey.SetName, inAclKey.Type) - if intf.InterfaceRef != nil && intf.InterfaceRef.Config.Interface != nil { - aclInterfacesMap[aclName] = append(aclInterfacesMap[aclName], *intf.InterfaceRef.Config.Interface) - } else { - aclInterfacesMap[aclName] = append(aclInterfacesMap[aclName], *intf.Id) - } - if len(aclTableMap) == 0 { - aclTableMap[aclName] = db.Value{Field: map[string]string{}} + if aclObj.Interfaces != nil { + if len(aclObj.Interfaces.Interface) > 0 { + aclInterfacesMap := make(map[string][]string) + for intfId, _ := range aclObj.Interfaces.Interface { + intf := aclObj.Interfaces.Interface[intfId] + if intf != nil { + if intf.IngressAclSets != nil && len(intf.IngressAclSets.IngressAclSet) > 0 { + for inAclKey, _ := range intf.IngressAclSets.IngressAclSet { + aclName := getAclKeyStrFromOCKey(inAclKey.SetName, inAclKey.Type) + if intf.InterfaceRef != nil && intf.InterfaceRef.Config.Interface != nil { + aclInterfacesMap[aclName] = append(aclInterfacesMap[aclName], *intf.InterfaceRef.Config.Interface) + } else { + aclInterfacesMap[aclName] = append(aclInterfacesMap[aclName], *intf.Id) + } + if len(aclTableMap) == 0 { + aclTableMap[aclName] = db.Value{Field: map[string]string{}} + } + aclTableMap[aclName].Field["stage"] = "INGRESS" } - aclTableMap[aclName].Field["stage"] = "INGRESS" } - } - if intf.EgressAclSets != nil && len(intf.EgressAclSets.EgressAclSet) > 0 { - for outAclKey, _ := range intf.EgressAclSets.EgressAclSet { - aclName := getAclKeyStrFromOCKey(outAclKey.SetName, outAclKey.Type) - if intf.InterfaceRef != nil && intf.InterfaceRef.Config.Interface != nil { - aclInterfacesMap[aclName] = append(aclInterfacesMap[aclName], *intf.InterfaceRef.Config.Interface) - } else { - aclInterfacesMap[aclName] = append(aclInterfacesMap[aclName], *intf.Id) - } - if len(aclTableMap) == 0 { - aclTableMap[aclName] = db.Value{Field: map[string]string{}} + if intf.EgressAclSets != nil && len(intf.EgressAclSets.EgressAclSet) > 0 { + for outAclKey, _ := range intf.EgressAclSets.EgressAclSet { + aclName := getAclKeyStrFromOCKey(outAclKey.SetName, outAclKey.Type) + if intf.InterfaceRef != nil && intf.InterfaceRef.Config.Interface != nil { + aclInterfacesMap[aclName] = append(aclInterfacesMap[aclName], *intf.InterfaceRef.Config.Interface) + } else { + aclInterfacesMap[aclName] = append(aclInterfacesMap[aclName], *intf.Id) + } + if len(aclTableMap) == 0 { + aclTableMap[aclName] = db.Value{Field: map[string]string{}} + } + aclTableMap[aclName].Field["stage"] = "EGRESS" } - aclTableMap[aclName].Field["stage"] = "EGRESS" } } } - } - for k, _ := range aclInterfacesMap { - val := aclTableMap[k] - (&val).SetList("ports", aclInterfacesMap[k]) + for k, _ := range aclInterfacesMap { + val := aclTableMap[k] + (&val).SetList("ports", aclInterfacesMap[k]) + } + } else { + aclTableMapDb := make(map[string]db.Value) + aclTableMapDb, _, err = convertDBAclToInternal (d, db.Key{}) + if err != nil { + log.Info("YangToDb_acl_port_bindings_xfmr: getDbAlcTblsData not able to populate acl tables.") + err = errors.New("getDbAlcTblsData failed to populate tables.") + return res_map, err + } + for aclName := range aclTableMapDb { + if len(aclTableMap) == 0 { + aclTableMap[aclName] = db.Value{Field: map[string]string{}} + } + aclEntryDb := aclTableMapDb[aclName] + aclTableMap[aclName].Field["stage"] = aclEntryDb.Get("stage") + val := aclTableMap[aclName] + (&val).SetList("ports", aclEntryDb.GetList("ports")) + } } } res_map[ACL_TABLE] = aclTableMap return res_map, err } -var DbToYang_acl_port_bindings_xfmr SubTreeXfmrDbToYang = func (d *db.DB, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct) (error) { +var DbToYang_acl_port_bindings_xfmr SubTreeXfmrDbToYang = func (d *db.DB, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct, xpath string) (error) { var err error log.Info("DbToYang_acl_port_bindings_xfmr: ", data, ygRoot) + + aclTbl, ruleTbl, err := getDbAlcTblsData(d) + + if err != nil { + log.Info("getDbAlcTblsData not able to populate acl tables.") + err = errors.New("getDbAlcTblsData failed to populate tables.") + return err + } + pathInfo := NewPathInfo(xpath) + acl := getAclRoot(ygRoot) + targetUriPath, _ := getYangPathFromUri(pathInfo.Path) + if isSubtreeRequest(pathInfo.Template, "/openconfig-acl:acl/interfaces/interface{}") { + for intfId := range acl.Interfaces.Interface { + intfData := acl.Interfaces.Interface[intfId] + ygot.BuildEmptyTree(intfData) + if isSubtreeRequest(targetUriPath, "/openconfig-acl:acl/interfaces/interface/ingress-acl-sets") { + err = getAclBindingInfoForInterfaceData(aclTbl, ruleTbl, intfData, intfId, "INGRESS") + } else if isSubtreeRequest(targetUriPath, "/openconfig-acl:acl/interfaces/interface/egress-acl-sets") { + err = getAclBindingInfoForInterfaceData(aclTbl, ruleTbl, intfData, intfId, "EGRESS") + } else { + err = getAclBindingInfoForInterfaceData(aclTbl, ruleTbl, intfData, intfId, "INGRESS") + if err != nil { + return err + } + err = getAclBindingInfoForInterfaceData(aclTbl, ruleTbl, intfData, intfId, "EGRESS") + } + } + } else { + err = getAllBindingsInfo(aclTbl, ruleTbl, ygRoot) + } + + return err +} +func convertInternalToOCAclRuleBinding(aclTableMap map[string]db.Value, ruleTableMap map[string]map[string]db.Value, priority uint32, seqId int64, direction string, aclSet ygot.GoStruct, entrySet ygot.GoStruct) { + if seqId == -1 { + seqId = int64(MAX_PRIORITY - priority) + } + + var num uint64 + num = 0 + var ruleId uint32 = uint32(seqId) + + if direction == "INGRESS" { + var ingressEntrySet *ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_IngressAclSets_IngressAclSet_AclEntries_AclEntry + var ok bool + if entrySet == nil { + ingressAclSet := aclSet.(*ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_IngressAclSets_IngressAclSet) + if ingressEntrySet, ok = ingressAclSet.AclEntries.AclEntry[ruleId]; !ok { + ingressEntrySet, _ = ingressAclSet.AclEntries.NewAclEntry(ruleId) + } + } else { + ingressEntrySet = entrySet.(*ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_IngressAclSets_IngressAclSet_AclEntries_AclEntry) + } + if ingressEntrySet != nil { + ygot.BuildEmptyTree(ingressEntrySet) + ingressEntrySet.State.SequenceId = &ruleId + ingressEntrySet.State.MatchedPackets = &num + ingressEntrySet.State.MatchedOctets = &num + } + } else if direction == "EGRESS" { + var egressEntrySet *ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_EgressAclSets_EgressAclSet_AclEntries_AclEntry + var ok bool + if entrySet == nil { + egressAclSet := aclSet.(*ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_EgressAclSets_EgressAclSet) + if egressEntrySet, ok = egressAclSet.AclEntries.AclEntry[ruleId]; !ok { + egressEntrySet, _ = egressAclSet.AclEntries.NewAclEntry(ruleId) + } + } else { + egressEntrySet = entrySet.(*ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_EgressAclSets_EgressAclSet_AclEntries_AclEntry) + } + if egressEntrySet != nil { + ygot.BuildEmptyTree(egressEntrySet) + egressEntrySet.State.SequenceId = &ruleId + egressEntrySet.State.MatchedPackets = &num + egressEntrySet.State.MatchedOctets = &num + } + } +} + +func convertInternalToOCAclBinding(aclTableMap map[string]db.Value, ruleTableMap map[string]map[string]db.Value, aclName string, intfId string, direction string, intfAclSet ygot.GoStruct) error { + var err error + if _, ok := aclTableMap[aclName]; !ok { + err = errors.New("Acl entry not found, convertInternalToOCAclBinding") + return err + } else { + aclEntry := aclTableMap[aclName] + if !contains(aclEntry.GetList("ports"), intfId) { + return tlerr.InvalidArgs("Acl %s not binded with %s", aclName, intfId) + } + } + + for ruleName := range ruleTableMap[aclName] { + if ruleName != "DEFAULT_RULE" { + seqId, _ := strconv.Atoi(strings.Replace(ruleName, "RULE_", "", 1)) + convertInternalToOCAclRuleBinding(aclTableMap, ruleTableMap, 0, int64(seqId), direction, intfAclSet, nil) + } + } + + return err +} + +func getAllBindingsInfo(aclTableMap map[string]db.Value, ruleTableMap map[string]map[string]db.Value, ygRoot *ygot.GoStruct) error { + var err error + acl := getAclRoot(ygRoot) + + var interfaces []string + for aclName := range aclTableMap { + aclData := aclTableMap[aclName] + if len(aclData.Get("ports@")) > 0 { + aclIntfs := aclData.GetList("ports") + for i, _ := range aclIntfs { + if !contains(interfaces, aclIntfs[i]) && aclIntfs[i] != "" { + interfaces = append(interfaces, aclIntfs[i]) + } + } + } + } + + for _, intfId := range interfaces { + var intfData *ocbinds.OpenconfigAcl_Acl_Interfaces_Interface + intfData, ok := acl.Interfaces.Interface[intfId] + if !ok { + intfData, _ = acl.Interfaces.NewInterface(intfId) + } + ygot.BuildEmptyTree(intfData) + err = getAclBindingInfoForInterfaceData(aclTableMap, ruleTableMap, intfData, intfId, "INGRESS") + err = getAclBindingInfoForInterfaceData(aclTableMap, ruleTableMap, intfData, intfId, "EGRESS") + } + return err +} + +func getAclBindingInfoForInterfaceData(aclTableMap map[string]db.Value, ruleTableMap map[string]map[string]db.Value, intfData *ocbinds.OpenconfigAcl_Acl_Interfaces_Interface, intfId string, direction string) error { + var err error + if intfData != nil { + intfData.Config.Id = intfData.Id + intfData.State.Id = intfData.Id + } + if direction == "INGRESS" { + if intfData.IngressAclSets != nil && len(intfData.IngressAclSets.IngressAclSet) > 0 { + for ingressAclSetKey, _ := range intfData.IngressAclSets.IngressAclSet { + aclName := strings.Replace(strings.Replace(ingressAclSetKey.SetName, " ", "_", -1), "-", "_", -1) + aclType := ingressAclSetKey.Type.ΛMap()["E_OpenconfigAcl_ACL_TYPE"][int64(ingressAclSetKey.Type)].Name + aclKey := aclName + "_" + aclType + + ingressAclSet := intfData.IngressAclSets.IngressAclSet[ingressAclSetKey] + if ingressAclSet != nil && ingressAclSet.AclEntries != nil && len(ingressAclSet.AclEntries.AclEntry) > 0 { + for seqId, _ := range ingressAclSet.AclEntries.AclEntry { + rulekey := "RULE_" + strconv.Itoa(int(seqId)) + entrySet := ingressAclSet.AclEntries.AclEntry[seqId] + _, ok := ruleTableMap[aclKey][rulekey] + if !ok { + log.Info("Acl Rule not found ", aclKey, rulekey) + err = errors.New("Acl Rule not found ingress, getAclBindingInfoForInterfaceData") + return err + } + convertInternalToOCAclRuleBinding(aclTableMap, ruleTableMap, 0, int64(seqId), direction, nil, entrySet) + } + } else { + ygot.BuildEmptyTree(ingressAclSet) + ingressAclSet.Config = &ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_IngressAclSets_IngressAclSet_Config{SetName: &aclName, Type: ingressAclSetKey.Type} + ingressAclSet.State = &ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_IngressAclSets_IngressAclSet_State{SetName: &aclName, Type: ingressAclSetKey.Type} + err = convertInternalToOCAclBinding(aclTableMap, ruleTableMap, aclKey, intfId, direction, ingressAclSet) + } + } + } else { + err = findAndGetAclBindingInfoForInterfaceData(aclTableMap, ruleTableMap, intfId, direction, intfData) + } + } else if direction == "EGRESS" { + if intfData.EgressAclSets != nil && len(intfData.EgressAclSets.EgressAclSet) > 0 { + for egressAclSetKey, _ := range intfData.EgressAclSets.EgressAclSet { + aclName := strings.Replace(strings.Replace(egressAclSetKey.SetName, " ", "_", -1), "-", "_", -1) + aclType := egressAclSetKey.Type.ΛMap()["E_OpenconfigAcl_ACL_TYPE"][int64(egressAclSetKey.Type)].Name + aclKey := aclName + "_" + aclType + + egressAclSet := intfData.EgressAclSets.EgressAclSet[egressAclSetKey] + if egressAclSet != nil && egressAclSet.AclEntries != nil && len(egressAclSet.AclEntries.AclEntry) > 0 { + for seqId, _ := range egressAclSet.AclEntries.AclEntry { + rulekey := "RULE_" + strconv.Itoa(int(seqId)) + entrySet := egressAclSet.AclEntries.AclEntry[seqId] + _, ok := ruleTableMap[aclKey][rulekey] + if !ok { + log.Info("Acl Rule not found ", aclKey, rulekey) + err = errors.New("Acl Rule not found egress, getAclBindingInfoForInterfaceData") + return err + } + convertInternalToOCAclRuleBinding(aclTableMap, ruleTableMap, 0, int64(seqId), direction, nil, entrySet) + } + } else { + ygot.BuildEmptyTree(egressAclSet) + egressAclSet.Config = &ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_EgressAclSets_EgressAclSet_Config{SetName: &aclName, Type: egressAclSetKey.Type} + egressAclSet.State = &ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_EgressAclSets_EgressAclSet_State{SetName: &aclName, Type: egressAclSetKey.Type} + err = convertInternalToOCAclBinding(aclTableMap, ruleTableMap, aclKey, intfId, direction, egressAclSet) + } + } + } else { + err = findAndGetAclBindingInfoForInterfaceData(aclTableMap, ruleTableMap, intfId, direction, intfData) + } + } else { + log.Error("Unknown direction") + } + return err +} + +func findAndGetAclBindingInfoForInterfaceData(aclTableMap map[string]db.Value, ruleTableMap map[string]map[string]db.Value, intfId string, direction string, intfData *ocbinds.OpenconfigAcl_Acl_Interfaces_Interface) error { + var err error + for aclName, _ := range aclTableMap { + aclData := aclTableMap[aclName] + aclIntfs := aclData.GetList("ports") + aclType := aclData.Get(ACL_TYPE) + var aclOrigName string + var aclOrigType ocbinds.E_OpenconfigAcl_ACL_TYPE + if SONIC_ACL_TYPE_IPV4 == aclType { + aclOrigName = strings.Replace(aclName, "_"+OPENCONFIG_ACL_TYPE_IPV4, "", 1) + aclOrigType = ocbinds.OpenconfigAcl_ACL_TYPE_ACL_IPV4 + } else if SONIC_ACL_TYPE_IPV6 == aclType { + aclOrigName = strings.Replace(aclName, "_"+OPENCONFIG_ACL_TYPE_IPV6, "", 1) + aclOrigType = ocbinds.OpenconfigAcl_ACL_TYPE_ACL_IPV6 + } else if SONIC_ACL_TYPE_L2 == aclType { + aclOrigName = strings.Replace(aclName, "_"+OPENCONFIG_ACL_TYPE_L2, "", 1) + aclOrigType = ocbinds.OpenconfigAcl_ACL_TYPE_ACL_L2 + } + + if contains(aclIntfs, intfId) && direction == aclData.Get("stage") { + if direction == "INGRESS" { + if intfData.IngressAclSets != nil { + aclSetKey := ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_IngressAclSets_IngressAclSet_Key{SetName: aclOrigName, Type: aclOrigType} + ingressAclSet, ok := intfData.IngressAclSets.IngressAclSet[aclSetKey] + if !ok { + ingressAclSet, _ = intfData.IngressAclSets.NewIngressAclSet(aclOrigName, aclOrigType) + ygot.BuildEmptyTree(ingressAclSet) + ingressAclSet.Config = &ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_IngressAclSets_IngressAclSet_Config{SetName: &aclOrigName, Type: aclOrigType} + ingressAclSet.State = &ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_IngressAclSets_IngressAclSet_State{SetName: &aclOrigName, Type: aclOrigType} + } + err = convertInternalToOCAclBinding(aclTableMap, ruleTableMap, aclName, intfId, direction, ingressAclSet) + if err != nil { + return err + } + } + } else if direction == "EGRESS" { + if intfData.EgressAclSets != nil { + aclSetKey := ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_EgressAclSets_EgressAclSet_Key{SetName: aclOrigName, Type: aclOrigType} + egressAclSet, ok := intfData.EgressAclSets.EgressAclSet[aclSetKey] + if !ok { + egressAclSet, _ = intfData.EgressAclSets.NewEgressAclSet(aclOrigName, aclOrigType) + ygot.BuildEmptyTree(egressAclSet) + egressAclSet.Config = &ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_EgressAclSets_EgressAclSet_Config{SetName: &aclOrigName, Type: aclOrigType} + egressAclSet.State = &ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_EgressAclSets_EgressAclSet_State{SetName: &aclOrigName, Type: aclOrigType} + } + err = convertInternalToOCAclBinding(aclTableMap, ruleTableMap, aclName, intfId, direction, egressAclSet) + if err != nil { + return err + } + } + } + } + } return err } diff --git a/src/translib/transformer/xfmr_interface.go b/src/translib/transformer/xfmr_interface.go index 4c62e7d7bd..1b1095f562 100644 --- a/src/translib/transformer/xfmr_interface.go +++ b/src/translib/transformer/xfmr_interface.go @@ -49,7 +49,7 @@ type SubTreeXfmrYangToDb func (*db.DB, *ygot.GoStruct, string) (map[string]map[s * Param : Database info, DB data in multidimensional map, output param YgotRoot * Return : error **/ -type SubTreeXfmrDbToYang func (*db.DB, map[string]map[string]db.Value, *ygot.GoStruct) (error) +type SubTreeXfmrDbToYang func (*db.DB, map[string]map[string]db.Value, *ygot.GoStruct, string) (error) /** * Xfmr validation interface for validating the callback registration of app modules diff --git a/src/translib/transformer/xlate_utils.go b/src/translib/transformer/xlate_utils.go index 3201e0b146..8532147d5f 100644 --- a/src/translib/transformer/xlate_utils.go +++ b/src/translib/transformer/xlate_utils.go @@ -5,6 +5,9 @@ import ( "strings" "translib/db" "github.com/openconfig/goyang/pkg/yang" + "github.com/openconfig/gnmi/proto/gnmi" + "github.com/openconfig/ygot/ygot" + log "github.com/golang/glog" ) /* Create db key from datd xpath(request) */ @@ -80,3 +83,36 @@ func dbKeyToYangDataConvert(dbKey string, xpath string) { return } +func contains(sl []string, str string) bool { + for _, v := range sl { + if v == str { + return true + } + } + return false +} + + +func isSubtreeRequest(targetUriPath string, nodePath string) bool { + return strings.HasPrefix(targetUriPath, nodePath) +} + +func getYangPathFromUri(uri string) (string, error) { + var path *gnmi.Path + var err error + + path, err = ygot.StringToPath(uri, ygot.StructuredPath, ygot.StringSlicePath) + if err != nil { + log.Errorf("Error in uri to path conversion: %v", err) + return "", err + } + + yangPath, yperr := ygot.PathToSchemaPath(path) + if yperr != nil { + log.Errorf("Error in Gnmi path to Yang path conversion: %v", yperr) + return "", yperr + } + + return yangPath, err +} + From b7376e0c3e35ade4f8008875a888e48710c7ecdc Mon Sep 17 00:00:00 2001 From: kwangsuk Date: Wed, 14 Aug 2019 13:51:01 -0700 Subject: [PATCH 031/214] part 1 - integrate translib with transformer --- src/translib/acl_app.go | 62 ++-- src/translib/app_interface.go | 5 +- src/translib/common_app.go | 10 +- src/translib/subscribe.go | 4 +- src/translib/transformer/transformer.go | 33 +- src/translib/transformer/xlate.go | 458 +++++++++++++++++++++++- src/translib/transformer/xlate_to_db.go | 3 + src/translib/transformer/xspec.go | 9 +- src/translib/translib.go | 6 +- 9 files changed, 520 insertions(+), 70 deletions(-) diff --git a/src/translib/acl_app.go b/src/translib/acl_app.go index 07d6bea96f..37b8b6aad9 100644 --- a/src/translib/acl_app.go +++ b/src/translib/acl_app.go @@ -96,13 +96,6 @@ func init() { if err != nil { log.Fatal("Adding model data to appinterface failed with error=", err) } - - yangFiles := []string{"openconfig-acl.yang", "sonic-acl.yang"} - log.Info("Init transformer yang files :", yangFiles) - err = transformer.LoadYangModules(yangFiles...) - if err != nil { - log.Fatal("Loading Yang modules failed with error=", err) - } } func (app *AclApp) initialize(data appData) { @@ -157,10 +150,13 @@ func (app *AclApp) translateDelete(d *db.DB) ([]db.WatchKeys, error) { return keys, err } -func (app *AclApp) translateGet(dbs [db.MaxDB]*db.DB) error { - var err error - log.Info("translateGet:acl:path =", app.pathInfo.Template) - return err +func (app *AclApp) translateGet(dbs [db.MaxDB]*db.DB) (*map[db.DBNum][]transformer.KeySpec, error) { + var err error + log.Info("translateGet:acl:path =", app.pathInfo.Template) + + keySpec, err := transformer.XlateUriTotKeySpec(app.ygotRoot, app.ygotTarget) + + return keySpec, err } func (app *AclApp) translateSubscribe(dbs [db.MaxDB]*db.DB, path string) (*notificationOpts, *notificationInfo, error) { @@ -267,22 +263,28 @@ func (app *AclApp) processDelete(d *db.DB) (SetResponse, error) { return resp, err } -func (app *AclApp) processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error) { - var err error - var payload []byte - - configDb := dbs[db.ConfigDB] - err = app.processCommon(configDb, GET) - if err != nil { - return GetResponse{Payload: payload, ErrSrc: AppErr}, err - } - - payload, err = generateGetResponsePayload(app.pathInfo.Path, (*app.ygotRoot).(*ocbinds.Device), app.ygotTarget) - if err != nil { - return GetResponse{Payload: payload, ErrSrc: AppErr}, err - } - - return GetResponse{Payload: payload}, err +func (app *AclApp) processGet(dbs [db.MaxDB]*db.DB, keyspec *map[db.DBNum][]transformer.KeySpec) (GetResponse, error) { + var err error + var payload []byte + + // table.key.fields + var result = make(map[string]map[string]db.Value) + + for dbnum, specs := range *keyspec { + for _, spec := range specs { + err := transformer.TraverseDb(dbs[dbnum], spec, &result, nil) + if err != nil { + return GetResponse{Payload: payload}, err + } + } + } + + payload, err = transformer.XlateFromDb(result) + if err != nil { + return GetResponse{Payload: payload, ErrSrc: AppErr}, err + } + + return GetResponse{Payload: payload}, err } func (app *AclApp) translateCRUCommon(d *db.DB, opcode int) ([]db.WatchKeys, error) { @@ -290,6 +292,12 @@ func (app *AclApp) translateCRUCommon(d *db.DB, opcode int) ([]db.WatchKeys, err var keys []db.WatchKeys log.Info("translateCRUCommon:acl:path =", app.pathInfo.Template) + // TODO - once it's fully verfied, restrcuture the rest code + result, err := transformer.XlateToDb(app.pathInfo.Path, app.ygotRoot, app.ygotTarget) + if err != nil { + fmt.Println(result) + } + app.convertOCAclsToInternal() app.convertOCAclRulesToInternal(d) app.convertOCAclBindingsToInternal() diff --git a/src/translib/app_interface.go b/src/translib/app_interface.go index 6730e66259..f35c4dffa9 100644 --- a/src/translib/app_interface.go +++ b/src/translib/app_interface.go @@ -22,6 +22,7 @@ import ( "reflect" "strings" "translib/db" + "translib/transformer" log "github.com/golang/glog" "github.com/openconfig/ygot/ygot" ) @@ -55,13 +56,13 @@ type appInterface interface { translateUpdate(d *db.DB) ([]db.WatchKeys, error) translateReplace(d *db.DB) ([]db.WatchKeys, error) translateDelete(d *db.DB) ([]db.WatchKeys, error) - translateGet(dbs [db.MaxDB]*db.DB) error + translateGet(dbs [db.MaxDB]*db.DB) (*map[db.DBNum][]transformer.KeySpec, error) translateSubscribe(dbs [db.MaxDB]*db.DB, path string) (*notificationOpts, *notificationInfo, error) processCreate(d *db.DB) (SetResponse, error) processUpdate(d *db.DB) (SetResponse, error) processReplace(d *db.DB) (SetResponse, error) processDelete(d *db.DB) (SetResponse, error) - processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error) + processGet(dbs [db.MaxDB]*db.DB, spec *map[db.DBNum][]transformer.KeySpec) (GetResponse, error) } //App modules will use this function to register with App interface during boot up diff --git a/src/translib/common_app.go b/src/translib/common_app.go index 555fe71307..5abab624ba 100644 --- a/src/translib/common_app.go +++ b/src/translib/common_app.go @@ -42,14 +42,6 @@ func init() { } } - // @todo : Add support for all yang models that will use common app - //err = addModel(&ModelData{}) - yangFiles := []string{"sonic-acl.yang"} - log.Info("Init transformer yang files :", yangFiles) - err := transformer.LoadYangModules(yangFiles...) - if err != nil { - log.Fatal("Common App - Transformer call for loading yang modules failed with error=", err) - } } func (app *CommonApp) initialize(data appData) { @@ -170,7 +162,7 @@ func (app *CommonApp) translateCRUCommon(d *db.DB, opcode int) ([]db.WatchKeys, log.Info("translateCRUCommon:path =", app.pathInfo.Path) // translate yang to db - result, err := transformer.XlateToDb((*app).ygotRoot, (*app).ygotTarget) + result, err := transformer.XlateToDb(app.pathInfo.Path, (*app).ygotRoot, (*app).ygotTarget) fmt.Println(result) log.Info("transformer.XlateToDb() returned", result) diff --git a/src/translib/subscribe.go b/src/translib/subscribe.go index d48c9ac12d..0fd5910419 100644 --- a/src/translib/subscribe.go +++ b/src/translib/subscribe.go @@ -233,13 +233,13 @@ func getJson (nInfo *notificationInfo) ([]byte, error) { dbs := nInfo.dbs - err = (*app).translateGet (dbs) + keySpec, err := (*app).translateGet (dbs) if err != nil { return payload, err } - resp, err := (*app).processGet(dbs) + resp, err := (*app).processGet(dbs, keySpec) if err == nil { payload = resp.Payload diff --git a/src/translib/transformer/transformer.go b/src/translib/transformer/transformer.go index 12b9e6f108..a01a3b21af 100644 --- a/src/translib/transformer/transformer.go +++ b/src/translib/transformer/transformer.go @@ -3,7 +3,7 @@ package transformer import ( "fmt" "os" - "sort" + "strings" "github.com/openconfig/goyang/pkg/yang" "github.com/openconfig/ygot/ygot" // "translib/db" @@ -30,10 +30,11 @@ func reportIfError(errs []error) { } func init() { - // TODO - define the path for YANG files from container + yangFiles := []string{"sonic-acl.yang", "sonic-extensions.yang", "openconfig-acl-annot.yang", "openconfig-acl.yang" } + loadYangModules(yangFiles...) } -func LoadYangModules(files ...string) error { +func loadYangModules(files ...string) error { var err error @@ -71,16 +72,28 @@ func LoadYangModules(files ...string) error { names = append(names, m.Name) } } - sort.Strings(names) - entries = make(map[string]*yang.Entry) + + sonic_entries := make(map[string]*yang.Entry) + oc_entries := make(map[string]*yang.Entry) + annot_entries := make([]*yang.Entry, len(names)) + var i int + for _, n := range names { - if entries[n] == nil { - entries[n] = yang.ToEntry(mods[n]) - } + if strings.Contains(n, "annot") { + annot_entries[i] = yang.ToEntry(mods[n]) + i++ + } else if strings.Contains(n, "sonic") { + if sonic_entries[n] == nil { + sonic_entries[n] = yang.ToEntry(mods[n]) + } + } else if oc_entries[n] == nil { + oc_entries[n] = yang.ToEntry(mods[n]) + } } - yangToDbMapBuild(entries) - // TODO - build the inverse map for GET, from OC to Sonic + yangToDbMapBuild(sonic_entries) + annotToDbMapBuild(annot_entries) + yangToDbMapBuild(oc_entries) return err } diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index df76887b95..3959e6cfdf 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -1,7 +1,7 @@ package transformer import ( - "fmt" + //"fmt" // "os" // "sort" // "github.com/openconfig/goyang/pkg/yang" @@ -10,9 +10,17 @@ import ( "translib/ocbinds" "reflect" "errors" + "strings" + "encoding/json" log "github.com/golang/glog" ) +type KeySpec struct { + Ts db.TableSpec + Key db.Key + Child *KeySpec +} + var XlateFuncs = make(map[string]reflect.Value) var ( @@ -53,12 +61,87 @@ func XlateFuncCall(name string, params ... interface{}) (result []reflect.Value, return } -func XlateToDb(s *ygot.GoStruct, t *interface{}) (map[string]map[string]db.Value, error) { +func TraverseDb(d *db.DB, spec KeySpec, result *map[string]map[string]db.Value, parentKey *db.Key) error { + var err error + + if spec.Key.Len() > 0 { + // get an entry with a specific key + data, err := d.GetEntry(&spec.Ts, spec.Key) + if err != nil { + return err + } + + if (*result)[spec.Ts.Name] == nil { + (*result)[spec.Ts.Name] = map[string]db.Value{strings.Join(spec.Key.Comp, "|"): data} + } else { + (*result)[spec.Ts.Name][strings.Join(spec.Key.Comp, "|")] = data + } + + if spec.Child != nil { + err = TraverseDb(d, *spec.Child, result, &spec.Key) + } + } else { + // TODO - GetEntry suuport with regex patten, 'abc*' for optimization + keys, err := d.GetKeys(&spec.Ts) + if err != nil { + return err + } + for i, _ := range keys { + if parentKey != nil { + // TODO - multi-depth with a custom delimiter + if strings.Index(strings.Join(keys[i].Comp, "|"), strings.Join((*parentKey).Comp, "|")) == -1 { + continue + } + } + spec.Key = keys[i] + err = TraverseDb(d, spec, result, parentKey) + } + } + return err +} + +func XlateUriTotKeySpec(uri *ygot.GoStruct, t *interface{}) (*map[db.DBNum][]KeySpec, error) { + var err error + + var result = make(map[db.DBNum][]KeySpec) + + // 1 - mock data for a URI /openconfig-acl:acl/acl-sets/acl-set=MyACL1,ACL_IPV4 + result[db.ConfigDB] = []KeySpec{ + { + Ts: db.TableSpec{Name: "ACL_TABLE"}, + Key: db.Key{Comp: []string{"MyACL1_ACL_IPV4"}}, + Child: &KeySpec{ + Ts: db.TableSpec{Name: "ACL_RULE"}, + Key: db.Key{}}}, + } + // 2 - mock data for a URI /openconfig-acl:acl/acl-sets/acl-set=MyACL1,ACL_IPV4/acl-entires/ecl-entry=1 +// result[db.ConfigDB] = []KeySpec{ +// { +// Ts: db.TableSpec{Name: "ACL_RULE"}, +// Key: db.Key{Comp: []string{"MyACL1_ACL_IPV4|RULE_1"}}, +// } +// } + + // 3 - mock data for a URI /openconfig-acl:acl +// result[db.ConfigDB] = []KeySpec{ +// { +// Ts: db.TableSpec{Name: "ACL_TABLE"}, +// Key: db.Key{}, +// Child: &KeySpec{ +// Ts: db.TableSpec{Name: "ACL_RULE"}, +// Key: db.Key{}}}, +// } + + return &result, err +} + + +func XlateToDb(path string, yg *ygot.GoStruct, yt *interface{}) (map[string]map[string]db.Value, error) { var err error - d := (*s).(*ocbinds.Device) - jsonStr, err := ygot.EmitJSON(d, &ygot.EmitJSONConfig{ + device := (*yg).(*ocbinds.Device) + jsonStr, err := ygot.EmitJSON(device, &ygot.EmitJSONConfig{ Format: ygot.RFC7951, Indent: " ", SkipValidation: true, @@ -66,34 +149,377 @@ func XlateToDb(s *ygot.GoStruct, t *interface{}) (map[string]map[string]db.Value AppendModuleName: true, }, }) - fmt.Println(jsonStr) + + jsonData := make(map[string]interface{}) + err = json.Unmarshal([]byte(jsonStr), &jsonData) + if err != nil { + log.Errorf("Error: failed to unmarshal json.") + return nil,err + } // table.key.fields var result = make(map[string]map[string]db.Value) - err = dbMapCreate("", "/openconfig-acl:acl", jsonStr, result) + err = dbMapCreate("", path, jsonData, result) if err != nil { log.Errorf("Error: Data translation from yang to db failed.") return result, err } - // TODO - traverse ygot/JSON with the metadata to translate to DB - // xfmr method dynamically invoked - - // use reflect to call the xfmr method from yang extension "key_xfmr", "tanle_xfmr", "field_xfmr" - //var xfmr keyXfmr - - - return result, err } func XlateFromDb(data map[string]map[string]db.Value) ([]byte, error) { var err error - // table.key.fields - var result []byte + // please implement me - data translated by transforme + // here is a mock data + payload := `{ + "acl-sets": { + "acl-set": [ + { + "name": "MyACL1", + "type": "ACL_IPV4", + "config": { + "name": "MyACL1", + "type": "ACL_IPV4", + "description": "Description for MyACL1" + }, + "acl-entries": { + "acl-entry": [ + { + "sequence-id": 1, + "config": { + "sequence-id": 1, + "description": "Description for MyACL1 Rule Seq 1" + }, + "ipv4": { + "config": { + "source-address": "11.1.1.1/32", + "destination-address": "21.1.1.1/32", + "dscp": 1, + "protocol": "IP_TCP" + } + }, + "transport": { + "config": { + "source-port": 101, + "destination-port": 201 + } + }, + "actions": { + "config": { + "forwarding-action": "ACCEPT" + } + } + }, + { + "sequence-id": 2, + "config": { + "sequence-id": 2, + "description": "Description for MyACL1 Rule Seq 2" + }, + "ipv4": { + "config": { + "source-address": "11.1.1.2/32", + "destination-address": "21.1.1.2/32", + "dscp": 2, + "protocol": "IP_TCP" + } + }, + "transport": { + "config": { + "source-port": 102, + "destination-port": 202 + } + }, + "actions": { + "config": { + "forwarding-action": "DROP" + } + } + }, + { + "sequence-id": 3, + "config": { + "sequence-id": 3, + "description": "Description for MyACL1 Rule Seq 3" + }, + "ipv4": { + "config": { + "source-address": "11.1.1.3/32", + "destination-address": "21.1.1.3/32", + "dscp": 3, + "protocol": "IP_TCP" + } + }, + "transport": { + "config": { + "source-port": 103, + "destination-port": 203 + } + }, + "actions": { + "config": { + "forwarding-action": "ACCEPT" + } + } + }, + { + "sequence-id": 4, + "config": { + "sequence-id": 4, + "description": "Description for MyACL1 Rule Seq 4" + }, + "ipv4": { + "config": { + "source-address": "11.1.1.4/32", + "destination-address": "21.1.1.4/32", + "dscp": 4, + "protocol": "IP_TCP" + } + }, + "transport": { + "config": { + "source-port": 104, + "destination-port": 204 + } + }, + "actions": { + "config": { + "forwarding-action": "DROP" + } + } + }, + { + "sequence-id": 5, + "config": { + "sequence-id": 5, + "description": "Description for MyACL1 Rule Seq 5" + }, + "ipv4": { + "config": { + "source-address": "11.1.1.5/32", + "destination-address": "21.1.1.5/32", + "dscp": 5, + "protocol": "IP_TCP" + } + }, + "transport": { + "config": { + "source-port": 105, + "destination-port": 205 + } + }, + "actions": { + "config": { + "forwarding-action": "ACCEPT" + } + } + } + ] + } + }, + { + "name": "MyACL2", + "type": "ACL_IPV4", + "config": { + "name": "MyACL2", + "type": "ACL_IPV4", + "description": "Description for MyACL2" + }, + "acl-entries": { + "acl-entry": [ + { + "sequence-id": 1, + "config": { + "sequence-id": 1, + "description": "Description for Rule Seq 1" + }, + "ipv4": { + "config": { + "source-address": "12.1.1.1/32", + "destination-address": "22.1.1.1/32", + "dscp": 1, + "protocol": "IP_TCP" + } + }, + "transport": { + "config": { + "source-port": 101, + "destination-port": 201 + } + }, + "actions": { + "config": { + "forwarding-action": "ACCEPT" + } + } + }, + { + "sequence-id": 2, + "config": { + "sequence-id": 2, + "description": "Description for Rule Seq 2" + }, + "ipv4": { + "config": { + "source-address": "12.1.1.2/32", + "destination-address": "22.1.1.2/32", + "dscp": 2, + "protocol": "IP_TCP" + } + }, + "transport": { + "config": { + "source-port": 102, + "destination-port": 202 + } + }, + "actions": { + "config": { + "forwarding-action": "ACCEPT" + } + } + }, + { + "sequence-id": 3, + "config": { + "sequence-id": 3, + "description": "Description for Rule Seq 3" + }, + "ipv4": { + "config": { + "source-address": "12.1.1.3/32", + "destination-address": "22.1.1.3/32", + "dscp": 3, + "protocol": "IP_TCP" + } + }, + "transport": { + "config": { + "source-port": 103, + "destination-port": 203 + } + }, + "actions": { + "config": { + "forwarding-action": "ACCEPT" + } + } + }, + { + "sequence-id": 4, + "config": { + "sequence-id": 4, + "description": "Description for Rule Seq 4" + }, + "ipv4": { + "config": { + "source-address": "12.1.1.4/32", + "destination-address": "22.1.1.4/32", + "dscp": 4, + "protocol": "IP_TCP" + } + }, + "transport": { + "config": { + "source-port": 104, + "destination-port": 204 + } + }, + "actions": { + "config": { + "forwarding-action": "ACCEPT" + } + } + }, + { + "sequence-id": 5, + "config": { + "sequence-id": 5, + "description": "Description for Rule Seq 5" + }, + "ipv4": { + "config": { + "source-address": "12.1.1.5/32", + "destination-address": "22.1.1.5/32", + "dscp": 5, + "protocol": "IP_TCP" + } + }, + "transport": { + "config": { + "source-port": 105, + "destination-port": 205 + } + }, + "actions": { + "config": { + "forwarding-action": "ACCEPT" + } + } + } + ] + } + } + ] + }, + "interfaces": { + "interface": [ + { + "id": "Ethernet0", + "config": { + "id": "Ethernet0" + }, + "interface-ref": { + "config": { + "interface": "Ethernet0" + } + }, + "ingress-acl-sets": { + "ingress-acl-set": [ + { + "set-name": "MyACL1", + "type": "ACL_IPV4", + "config": { + "set-name": "MyACL1", + "type": "ACL_IPV4" + } + } + ] + } + }, + { + "id": "Ethernet4", + "config": { + "id": "Ethernet4" + }, + "interface-ref": { + "config": { + "interface": "Ethernet4" + } + }, + "ingress-acl-sets": { + "ingress-acl-set": [ + { + "set-name": "MyACL2", + "type": "ACL_IPV4", + "config": { + "set-name": "MyACL2", + "type": "ACL_IPV4" + } + } + ] + } + } + ] + } +}` + + result := []byte(payload) //TODO - implement me return result, err + } diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index 71d291deee..824f69a4a5 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -159,6 +159,9 @@ func dbMapCreate(keyName string, xpathPrefix string, jsonData interface{}, resul if directDbMapData(key.String(), jData.MapIndex(key).Interface(), result) { continue } else { + if xpathPrefix == "/"+key.String() { + return dbMapCreate(keyName, xpathPrefix, jData.MapIndex(key).Interface(), result) + } pathAttr := key.String() if strings.Contains(pathAttr, ":") { pathAttr = strings.Split(pathAttr, ":")[1] diff --git a/src/translib/transformer/xspec.go b/src/translib/transformer/xspec.go index 19a84255b9..22540b0879 100644 --- a/src/translib/transformer/xspec.go +++ b/src/translib/transformer/xspec.go @@ -128,6 +128,11 @@ func yangToDbMapBuild(entries map[string]*yang.Entry) { if entries == nil { return } + + if xSpecMap == nil { + xSpecMap = make(map[string]*yangXpathInfo) + } + for _, e := range entries { if e == nil || len(e.Dir) == 0 { continue @@ -256,8 +261,10 @@ func annotToDbMapBuild(annotEntries []*yang.Entry) { if annotEntries == nil { return } + if xSpecMap == nil { + xSpecMap = make(map[string]*yangXpathInfo) + } - xSpecMap = make(map[string]*yangXpathInfo) for _, e := range annotEntries { if e != nil && len(e.Deviations) > 0 { for _, d := range e.Deviations { diff --git a/src/translib/translib.go b/src/translib/translib.go index e71e699ff3..2d3bd5d174 100644 --- a/src/translib/translib.go +++ b/src/translib/translib.go @@ -406,15 +406,15 @@ func Get(req GetRequest) (GetResponse, error){ } defer closeAllDbs(dbs[:]) - - err = (*app).translateGet (dbs) + + keySpec, err := (*app).translateGet (dbs) if err != nil { resp = GetResponse{Payload:payload, ErrSrc:AppErr} return resp, err } - resp, err = (*app).processGet(dbs) + resp, err = (*app).processGet(dbs, keySpec) return resp, err } From d72f107de7cd54ea25d7b4b387f330c2fc58a096 Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Wed, 14 Aug 2019 15:48:56 -0700 Subject: [PATCH 032/214] Integrate Translate yangpath to redisDB KeySpec (XlateUriToKeySpec) --- .../annotations/openconfig-acl-annot.yang | 2 +- src/translib/acl_app.go | 4 +- src/translib/transformer/transformer.go | 21 +++--- src/translib/transformer/xlate.go | 66 +++++++++++++++---- src/translib/transformer/xspec.go | 4 +- 5 files changed, 69 insertions(+), 28 deletions(-) diff --git a/models/yang/annotations/openconfig-acl-annot.yang b/models/yang/annotations/openconfig-acl-annot.yang index d52099b7cb..be0bfeeb7c 100644 --- a/models/yang/annotations/openconfig-acl-annot.yang +++ b/models/yang/annotations/openconfig-acl-annot.yang @@ -91,7 +91,7 @@ module openconfig-acl-annot { deviation /oc-acl:acl/oc-acl:interfaces { deviate add { - sonic-ext:subtree-trasnformer "acl_port_bindings_xfmr"; + sonic-ext:subtree-transformer "acl_port_bindings_xfmr"; } } diff --git a/src/translib/acl_app.go b/src/translib/acl_app.go index 37b8b6aad9..2fa0b83c30 100644 --- a/src/translib/acl_app.go +++ b/src/translib/acl_app.go @@ -154,7 +154,7 @@ func (app *AclApp) translateGet(dbs [db.MaxDB]*db.DB) (*map[db.DBNum][]transform var err error log.Info("translateGet:acl:path =", app.pathInfo.Template) - keySpec, err := transformer.XlateUriTotKeySpec(app.ygotRoot, app.ygotTarget) + keySpec, err := transformer.XlateUriToKeySpec(app.pathInfo.Path, app.ygotRoot, app.ygotTarget) return keySpec, err } @@ -269,7 +269,7 @@ func (app *AclApp) processGet(dbs [db.MaxDB]*db.DB, keyspec *map[db.DBNum][]tran // table.key.fields var result = make(map[string]map[string]db.Value) - + for dbnum, specs := range *keyspec { for _, spec := range specs { err := transformer.TraverseDb(dbs[dbnum], spec, &result, nil) diff --git a/src/translib/transformer/transformer.go b/src/translib/transformer/transformer.go index a01a3b21af..aec692d086 100644 --- a/src/translib/transformer/transformer.go +++ b/src/translib/transformer/transformer.go @@ -72,26 +72,25 @@ func loadYangModules(files ...string) error { names = append(names, m.Name) } } - - sonic_entries := make(map[string]*yang.Entry) + + sonic_entries := make([]*yang.Entry, len(names)) oc_entries := make(map[string]*yang.Entry) annot_entries := make([]*yang.Entry, len(names)) - var i int - + var i, j int + for _, n := range names { if strings.Contains(n, "annot") { annot_entries[i] = yang.ToEntry(mods[n]) i++ } else if strings.Contains(n, "sonic") { - if sonic_entries[n] == nil { - sonic_entries[n] = yang.ToEntry(mods[n]) - } - } else if oc_entries[n] == nil { - oc_entries[n] = yang.ToEntry(mods[n]) - } + sonic_entries[j] = yang.ToEntry(mods[n]) + j++ + } else if oc_entries[n] == nil { + oc_entries[n] = yang.ToEntry(mods[n]) + } } - yangToDbMapBuild(sonic_entries) + dbMapBuild(sonic_entries) annotToDbMapBuild(annot_entries) yangToDbMapBuild(oc_entries) diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index 3959e6cfdf..42b419578d 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -2,7 +2,7 @@ package transformer import ( //"fmt" - // "os" + //"os" // "sort" // "github.com/openconfig/goyang/pkg/yang" "github.com/openconfig/ygot/ygot" @@ -100,20 +100,30 @@ func TraverseDb(d *db.DB, spec KeySpec, result *map[string]map[string]db.Value, return err } -func XlateUriTotKeySpec(uri *ygot.GoStruct, t *interface{}) (*map[db.DBNum][]KeySpec, error) { - var err error +func XlateUriToKeySpec(path string, uri *ygot.GoStruct, t *interface{}) (*map[db.DBNum][]KeySpec, error) { + var err error var result = make(map[db.DBNum][]KeySpec) + var retdbFormat = make([]KeySpec, 1) + var dbFormat KeySpec + retdbFormat[0] = dbFormat + + /* Extract the xpath and key from input xpath */ + yangXpath, keyStr := xpathKeyExtract(path); + + fillKeySpec(yangXpath, keyStr, &dbFormat) + + result[db.ConfigDB] = retdbFormat // 1 - mock data for a URI /openconfig-acl:acl/acl-sets/acl-set=MyACL1,ACL_IPV4 - result[db.ConfigDB] = []KeySpec{ - { - Ts: db.TableSpec{Name: "ACL_TABLE"}, - Key: db.Key{Comp: []string{"MyACL1_ACL_IPV4"}}, - Child: &KeySpec{ - Ts: db.TableSpec{Name: "ACL_RULE"}, - Key: db.Key{}}}, - } + //result[db.ConfigDB] = []KeySpec{ + // { + // Ts: db.TableSpec{Name: "ACL_TABLE"}, + // Key: db.Key{Comp: []string{"MyACL1_ACL_IPV4"}}, + // Child: &KeySpec{ + // Ts: db.TableSpec{Name: "ACL_RULE"}, + // Key: db.Key{}}}, + // } // 2 - mock data for a URI /openconfig-acl:acl/acl-sets/acl-set=MyACL1,ACL_IPV4/acl-entires/ecl-entry=1 // result[db.ConfigDB] = []KeySpec{ // { @@ -132,7 +142,39 @@ func XlateUriTotKeySpec(uri *ygot.GoStruct, t *interface{}) (*map[db.DBNum][]Key // Key: db.Key{}}}, // } - return &result, err + return &result, err +} + +func fillKeySpec(yangXpath string , keyStr string, dbFormat *KeySpec) { + + if xSpecMap == nil { + return; + } + _, ok := xSpecMap[yangXpath] + if ok { + xpathInfo := xSpecMap[yangXpath] + if xpathInfo.tableName != nil { + dbFormat.Ts.Name = *xpathInfo.tableName + dbFormat.Key.Comp = append(dbFormat.Key.Comp, keyStr) + } + for _, child := range xpathInfo.childTable { + /* Current support for one child. Should change the KeySpec.Child + to array of pointers later when we support all children */ + if xDbSpecMap != nil { + if len(xDbSpecMap[child].yangXpath) > 0 { + var childXpath = xDbSpecMap[child].yangXpath[0] + if xpathInfo.tableName == nil { + fillKeySpec(childXpath, "", dbFormat) + } else { + dbFormat.Child = new(KeySpec) + fillKeySpec(childXpath, "", dbFormat.Child) + } + } + } + } + } else { + return; + } } diff --git a/src/translib/transformer/xspec.go b/src/translib/transformer/xspec.go index 22540b0879..c4c6bf10a0 100644 --- a/src/translib/transformer/xspec.go +++ b/src/translib/transformer/xspec.go @@ -132,7 +132,7 @@ func yangToDbMapBuild(entries map[string]*yang.Entry) { if xSpecMap == nil { xSpecMap = make(map[string]*yangXpathInfo) } - + for _, e := range entries { if e == nil || len(e.Dir) == 0 { continue @@ -313,7 +313,7 @@ func mapPrint(inMap map[string]*yangXpathInfo, fileName string) { fmt.Fprintf(fp, "%v\r\n", d.xfmrFunc) } fmt.Fprintf(fp, "\r\n yangEntry: ") - if d.dbEntry != nil { + if d.yangEntry != nil { fmt.Fprintf(fp, "%v", *d.yangEntry) } fmt.Fprintf(fp, "\r\n dbEntry: ") From f6ec0915ff7c7ceb25d7401bcbc6262547f1a12f Mon Sep 17 00:00:00 2001 From: amrutasali Date: Wed, 14 Aug 2019 23:07:18 +0000 Subject: [PATCH 033/214] modified common app translateGet and processGet signatures --- src/translib/common_app.go | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/src/translib/common_app.go b/src/translib/common_app.go index 5abab624ba..670d8f4f91 100644 --- a/src/translib/common_app.go +++ b/src/translib/common_app.go @@ -92,10 +92,13 @@ func (app *CommonApp) translateDelete(d *db.DB) ([]db.WatchKeys, error) { return keys, err } -func (app *CommonApp) translateGet(dbs [db.MaxDB]*db.DB) error { - var err error - log.Info("translateGet:path =", app.pathInfo.Path) - return err +func (app *CommonApp) translateGet(dbs [db.MaxDB]*db.DB) (*map[db.DBNum][]transformer.KeySpec, error) { + var err error + log.Info("translateGet:path =", app.pathInfo.Path) + + keySpec, err := transformer.XlateUriTotKeySpec(app.ygotRoot, app.ygotTarget) + + return keySpec, err } func (app *CommonApp) translateSubscribe(dbs [db.MaxDB]*db.DB, path string) (*notificationOpts, *notificationInfo, error) { @@ -148,13 +151,32 @@ func (app *CommonApp) processDelete(d *db.DB) (SetResponse, error) { return resp, err } -func (app *CommonApp) processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error) { - var err error - var payload []byte +func (app *CommonApp) processGet(dbs [db.MaxDB]*db.DB, keyspec *map[db.DBNum][]transformer.KeySpec) (GetResponse, error) { + var err error + var payload []byte + log.Info("processGet:path =", app.pathInfo.Path) + + // table.key.fields + var result = make(map[string]map[string]db.Value) - return GetResponse{Payload: payload}, err + for dbnum, specs := range *keyspec { + for _, spec := range specs { + err := transformer.TraverseDb(dbs[dbnum], spec, &result, nil) + if err != nil { + return GetResponse{Payload: payload}, err + } + } + } + + payload, err = transformer.XlateFromDb(result) + if err != nil { + return GetResponse{Payload: payload, ErrSrc: AppErr}, err + } + + return GetResponse{Payload: payload}, err } + func (app *CommonApp) translateCRUCommon(d *db.DB, opcode int) ([]db.WatchKeys, error) { var err error var keys []db.WatchKeys From 87ebf1b7f01119fb4a89fb6c5c72011ef79bc78e Mon Sep 17 00:00:00 2001 From: amrutasali Date: Wed, 14 Aug 2019 23:41:26 +0000 Subject: [PATCH 034/214] corrected function siganature in common app for transformer.XlateUriToKeySpec --- src/translib/common_app.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/translib/common_app.go b/src/translib/common_app.go index 670d8f4f91..903b64f637 100644 --- a/src/translib/common_app.go +++ b/src/translib/common_app.go @@ -96,7 +96,7 @@ func (app *CommonApp) translateGet(dbs [db.MaxDB]*db.DB) (*map[db.DBNum][]transf var err error log.Info("translateGet:path =", app.pathInfo.Path) - keySpec, err := transformer.XlateUriTotKeySpec(app.ygotRoot, app.ygotTarget) + keySpec, err := transformer.XlateUriToKeySpec(app.pathInfo.Path, app.ygotRoot, app.ygotTarget) return keySpec, err } From 8aad9cb7d9b8f45ec2d2c59cbff977a28e9cb09a Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Wed, 14 Aug 2019 17:50:52 -0700 Subject: [PATCH 035/214] XlateUriToKeySpec: Use parent with empty table name and add children to it --- src/translib/transformer/xlate.go | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index 42b419578d..17ecfdb487 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -106,7 +106,7 @@ func XlateUriToKeySpec(path string, uri *ygot.GoStruct, t *interface{}) (*map[db var result = make(map[db.DBNum][]KeySpec) var retdbFormat = make([]KeySpec, 1) var dbFormat KeySpec - retdbFormat[0] = dbFormat + retdbFormat = append(retdbFormat, dbFormat) /* Extract the xpath and key from input xpath */ yangXpath, keyStr := xpathKeyExtract(path); @@ -163,12 +163,8 @@ func fillKeySpec(yangXpath string , keyStr string, dbFormat *KeySpec) { if xDbSpecMap != nil { if len(xDbSpecMap[child].yangXpath) > 0 { var childXpath = xDbSpecMap[child].yangXpath[0] - if xpathInfo.tableName == nil { - fillKeySpec(childXpath, "", dbFormat) - } else { - dbFormat.Child = new(KeySpec) - fillKeySpec(childXpath, "", dbFormat.Child) - } + dbFormat.Child = new(KeySpec) + fillKeySpec(childXpath, "", dbFormat.Child) } } } From 6f695ba3640b1b88fe1f6aeae4179db807921424 Mon Sep 17 00:00:00 2001 From: s-mari Date: Thu, 15 Aug 2019 10:32:29 -0700 Subject: [PATCH 036/214] cvl yang get support from top-level container and added util functions --- src/translib/transformer/xlate_from_db.go | 28 ++++++++++++++-- src/translib/transformer/xlate_to_db.go | 3 -- src/translib/transformer/xlate_utils.go | 40 +++++++++++++++++++++++ src/translib/transformer/xspec.go | 4 +-- 4 files changed, 68 insertions(+), 7 deletions(-) diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index 85317bd426..7953fcbc5d 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -80,9 +80,33 @@ func listDataToJsonAdd(xpathl []string, dataMap map[string]db.Value, key string, return jsonData } +/* Traverse db map and create json for cvl yang */ +func directDbToYangJsonCreate(dbDataMap map[string]map[string]db.Value, jsonData string) string { + for tblName, tblData := range dbDataMap { + dataInst := "" + for keyStr, dbFldValData := range tblData { + fldValPair := "" + for field, value := range dbFldValData.Field { + fldValPair += fmt.Sprintf("\"%v\" : \"%v\",\r\n", field, value) + } + yangKeys := yangKeyFromEntryGet(xDbSpecMap[tblName].dbEntry) + fldValPair = keyJsonDataAdd(yangKeys, keyStr, fldValPair) + dataInst = fmt.Sprintf("{ \r\n %v \r\n },", fldValPair) + } + dataInst = strings.TrimRight(dataInst, ",") + jsonData += fmt.Sprintf("\"%v\" : [\r\n %v\r\n ],", tblName, dataInst) + } + jsonData = strings.TrimRight(jsonData, ",") + return jsonData +} + /* Traverse linear db-map data and add to nested json data */ -func dbDataToYangJsonCreate(dbDataMap map[string]map[string]db.Value) error { +func dbDataToYangJsonCreate(xpath string, dbDataMap map[string]map[string]db.Value) (string, error) { jsonData := "" + if isCvlYang(xpath) { + jsonData := directDbToYangJsonCreate(dbDataMap, jsonData) + return jsonData, nil + } curXpath := "" for tblName, tblData := range dbDataMap { if len(curXpath) == 0 || strings.HasPrefix(curXpath, xDbSpecMap[tblName].yangXpath[0]) { @@ -92,7 +116,7 @@ func dbDataToYangJsonCreate(dbDataMap map[string]map[string]db.Value) error { } jsonData = parentJsonDataUpdate(curXpath, jsonData) jsonDataPrint(jsonData) - return nil + return jsonData, nil } func parentJsonDataUpdate(xpath string, data string) string { diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index 824f69a4a5..71d291deee 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -159,9 +159,6 @@ func dbMapCreate(keyName string, xpathPrefix string, jsonData interface{}, resul if directDbMapData(key.String(), jData.MapIndex(key).Interface(), result) { continue } else { - if xpathPrefix == "/"+key.String() { - return dbMapCreate(keyName, xpathPrefix, jData.MapIndex(key).Interface(), result) - } pathAttr := key.String() if strings.Contains(pathAttr, ":") { pathAttr = strings.Split(pathAttr, ":")[1] diff --git a/src/translib/transformer/xlate_utils.go b/src/translib/transformer/xlate_utils.go index 8532147d5f..a48c42537c 100644 --- a/src/translib/transformer/xlate_utils.go +++ b/src/translib/transformer/xlate_utils.go @@ -116,3 +116,43 @@ func getYangPathFromUri(uri string) (string, error) { return yangPath, err } +func yangKeyFromEntryGet(entry *yang.Entry) []string { + var keyList []string + for _, key := range strings.Split(entry.Key, " ") { + keyList = append(keyList, key) + } + return keyList +} + +func isCvlYang(path string) bool { + if strings.HasPrefix(path, "/sonic") { + return true + } + return false +} + +func keyJsonDataAdd(keyNameList []string, keyStr string, jsonData string) string { + keyValList := strings.Split(keyStr, "|") + if len(keyNameList) != len(keyValList) { + return "" + } + + for i, keyName := range keyNameList { + jsonData += fmt.Sprintf("\"%v\" : \"%v\",", keyName, keyValList[i]) + } + jsonData = strings.TrimRight(jsonData, ",") + return jsonData +} + +func yangToDbXfmrFunc(funcName string) string { + return ("YangToDB_" + funcName) +} + +func uriWithKeyCreate (uri string, xpathTmplt string, data interface{}) string { + yangEntry := xSpecMap[xpathTmplt].yangEntry + for _, k := range (strings.Split(yangEntry.Key, " ")) { + uri += fmt.Sprintf("[%v=%v]", k, data.(map[string]interface{})[k]) + } + return uri +} + diff --git a/src/translib/transformer/xspec.go b/src/translib/transformer/xspec.go index c4c6bf10a0..c36b5114c5 100644 --- a/src/translib/transformer/xspec.go +++ b/src/translib/transformer/xspec.go @@ -304,11 +304,11 @@ func mapPrint(inMap map[string]*yangXpathInfo, fileName string) { if len(d.fieldName) > 0 { fmt.Fprintf(fp, "%v", d.fieldName) } - fmt.Fprintf(fp, "\r\n keyXfmr: ") + fmt.Fprintf(fp, "\r\n xfmrKeyFn: ") if d.dbEntry != nil { fmt.Fprintf(fp, "%v\r\n", d.xfmrKey) } - fmt.Fprintf(fp, "\r\n SubTreeXfmr: ") + fmt.Fprintf(fp, "\r\n xfmrFunc: ") if d.dbEntry != nil { fmt.Fprintf(fp, "%v\r\n", d.xfmrFunc) } From f8d8677e2c8c6e08819f3f33363bdece8345e41a Mon Sep 17 00:00:00 2001 From: Ravi Vasanthm Date: Thu, 15 Aug 2019 10:34:16 -0700 Subject: [PATCH 037/214] Fixed issue in handling interface binding if stage is not specified by the client in YangToDb_acl_port_bindings_xfmr xfmr method. --- src/translib/transformer/xfmr_acl.go | 32 ++++++++++++++++++---------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/src/translib/transformer/xfmr_acl.go b/src/translib/transformer/xfmr_acl.go index 1dafd3fb36..56d66ba26e 100644 --- a/src/translib/transformer/xfmr_acl.go +++ b/src/translib/transformer/xfmr_acl.go @@ -185,9 +185,6 @@ func getL2EtherType(etherType uint64) interface{} { return uint16(etherType) } - - - var YangToDb_acl_entry_key_xfmr KeyXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, xpath string) (string, error) { var entry_key string var err error @@ -666,11 +663,15 @@ func getDbAlcTblsData (d *db.DB) (map[string]db.Value, map[string]map[string]db. var YangToDb_acl_port_bindings_xfmr SubTreeXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, xpath string) (map[string]map[string]db.Value, error) { res_map := make(map[string]map[string]db.Value) aclTableMap := make(map[string]db.Value) - var err error; log.Info("YangToDb_acl_port_bindings_xfmr: ", ygRoot, xpath) aclObj := getAclRoot(ygRoot) + aclTableMapDb, _, err := getDbAlcTblsData(d) + if err != nil { + log.Info("YangToDb_acl_port_bindings_xfmr: getDbAlcTblsData not able to populate acl tables.") + } + if aclObj.Interfaces != nil { if len(aclObj.Interfaces.Interface) > 0 { aclInterfacesMap := make(map[string][]string) @@ -705,6 +706,22 @@ var YangToDb_acl_port_bindings_xfmr SubTreeXfmrYangToDb = func (d *db.DB, ygRoot aclTableMap[aclName].Field["stage"] = "EGRESS" } } + if intf.IngressAclSets == nil && intf.EgressAclSets == nil { + for aclName := range aclTableMapDb { + if len(aclTableMap) == 0 { + aclTableMap[aclName] = db.Value{Field: map[string]string{}} + } + aclEntryDb := aclTableMapDb[aclName] + intfsDb := aclEntryDb.GetList("ports") + if contains(intfsDb, intfId) { + var intfs [] string + intfs = append(intfs, intfId) + aclTableMap[aclName].Field["stage"] = aclEntryDb.Get("stage") + val := aclTableMap[aclName] + (&val).SetList("ports", intfs) + } + } + } } } for k, _ := range aclInterfacesMap { @@ -712,13 +729,6 @@ var YangToDb_acl_port_bindings_xfmr SubTreeXfmrYangToDb = func (d *db.DB, ygRoot (&val).SetList("ports", aclInterfacesMap[k]) } } else { - aclTableMapDb := make(map[string]db.Value) - aclTableMapDb, _, err = convertDBAclToInternal (d, db.Key{}) - if err != nil { - log.Info("YangToDb_acl_port_bindings_xfmr: getDbAlcTblsData not able to populate acl tables.") - err = errors.New("getDbAlcTblsData failed to populate tables.") - return res_map, err - } for aclName := range aclTableMapDb { if len(aclTableMap) == 0 { aclTableMap[aclName] = db.Value{Field: map[string]string{}} From 4af90767b480f048825fbee9ad93d431c2dddef6 Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Thu, 15 Aug 2019 11:01:22 -0700 Subject: [PATCH 038/214] XlateyangtoDB return sibilings as array of KeySpecs --- src/translib/transformer/xlate.go | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index 17ecfdb487..ceb0a8205c 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -104,15 +104,30 @@ func XlateUriToKeySpec(path string, uri *ygot.GoStruct, t *interface{}) (*map[db var err error var result = make(map[db.DBNum][]KeySpec) - var retdbFormat = make([]KeySpec, 1) - var dbFormat KeySpec - retdbFormat = append(retdbFormat, dbFormat) + var retdbFormat = make([]KeySpec, 0) /* Extract the xpath and key from input xpath */ yangXpath, keyStr := xpathKeyExtract(path); - fillKeySpec(yangXpath, keyStr, &dbFormat) - + if xSpecMap == nil { + return &result, err + } + _, ok := xSpecMap[yangXpath] + if ok { + xpathInfo := xSpecMap[yangXpath] + if xpathInfo.tableName != nil { + dbFormat := KeySpec{} + fillKeySpec(yangXpath, keyStr, &dbFormat) + retdbFormat = append(retdbFormat, dbFormat) + } else { + for _, child := range xpathInfo.childTable { + dbFormat := KeySpec{} + var childXpath = xDbSpecMap[child].yangXpath[0] + fillKeySpec(childXpath, "", &dbFormat) + retdbFormat = append(retdbFormat, dbFormat) + } + } + } result[db.ConfigDB] = retdbFormat // 1 - mock data for a URI /openconfig-acl:acl/acl-sets/acl-set=MyACL1,ACL_IPV4 @@ -132,6 +147,7 @@ func XlateUriToKeySpec(path string, uri *ygot.GoStruct, t *interface{}) (*map[db // } // } + // 3 - mock data for a URI /openconfig-acl:acl // result[db.ConfigDB] = []KeySpec{ // { @@ -158,8 +174,8 @@ func fillKeySpec(yangXpath string , keyStr string, dbFormat *KeySpec) { dbFormat.Key.Comp = append(dbFormat.Key.Comp, keyStr) } for _, child := range xpathInfo.childTable { - /* Current support for one child. Should change the KeySpec.Child - to array of pointers later when we support all children */ + // Current support for one child. Should change the KeySpec.Child + // to array of pointers later when we support all children if xDbSpecMap != nil { if len(xDbSpecMap[child].yangXpath) > 0 { var childXpath = xDbSpecMap[child].yangXpath[0] @@ -173,7 +189,6 @@ func fillKeySpec(yangXpath string , keyStr string, dbFormat *KeySpec) { } } - func XlateToDb(path string, yg *ygot.GoStruct, yt *interface{}) (map[string]map[string]db.Value, error) { var err error From df641e373916de4bb65377cf741f440733f12832 Mon Sep 17 00:00:00 2001 From: s-mari Date: Thu, 15 Aug 2019 15:29:06 -0700 Subject: [PATCH 039/214] updated cvl-yang handling for create request --- src/translib/transformer/xlate.go | 2 +- src/translib/transformer/xlate_to_db.go | 67 ++++++++++++++++--------- 2 files changed, 45 insertions(+), 24 deletions(-) diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index 17ecfdb487..7d5891f51a 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -197,7 +197,7 @@ func XlateToDb(path string, yg *ygot.GoStruct, yt *interface{}) (map[string]map[ // table.key.fields var result = make(map[string]map[string]db.Value) - err = dbMapCreate("", path, jsonData, result) + err = dbMapCreate(path, jsonData, result) if err != nil { log.Errorf("Error: Data translation from yang to db failed.") diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index 71d291deee..fbc6c2d52a 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -75,10 +75,25 @@ func callXfmr() map[string]map[string]db.Value { return result } +func cvlYangReqToDbMapCreate(uri string, jsonData interface{}, result map[string]map[string]db.Value) error { + if reflect.ValueOf(jsonData).Kind() == reflect.Map { + data := reflect.ValueOf(jsonData) + for _, key := range data.MapKeys() { + _, ok := xDbSpecMap[key.String()] + if ok { + directDbMapData(key.String(), data.MapIndex(key).Interface(), result) + } else { + cvlYangReqToDbMapCreate(key.String(), data.MapIndex(key).Interface(), result) + } + } + } + return nil +} + func directDbMapData(tableName string, jsonData interface{}, result map[string]map[string]db.Value) bool { _, ok := xDbSpecMap[tableName] - if ok && xDbSpecMap[tableName].dbEntry != nil && reflect.ValueOf(jsonData).Kind() == reflect.Slice { + if ok && xDbSpecMap[tableName].dbEntry != nil { dbSpecData := xDbSpecMap[tableName].dbEntry tblKeyName := strings.Split(dbSpecData.Key, " ") data := reflect.ValueOf(jsonData) @@ -126,14 +141,24 @@ func dbMapDelete(path string, jsonData interface{}, result map[string]map[string func dbMapUpdate(path string, jsonData interface{}, result map[string]map[string]db.Value) error { xpathPrefix, keyName := xpathKeyExtract(path) log.Info("Update/replace req: path(\"%v\"), key(\"%v\"), xpathPrefix(\"%v\").", path, keyName, xpathPrefix) - dbMapCreate(keyName, parentXpathGet(xpathPrefix), jsonData, result) + dbMapCreate(parentXpathGet(xpathPrefix), jsonData, result) log.Info("Update/replace req: path(\"%v\") result(\"%v\").", path, result) return nil } /* Get the data from incoming create request, create map and fill with dbValue(ie. field:value to write into redis-db */ -func dbMapCreate(keyName string, xpathPrefix string, jsonData interface{}, result map[string]map[string]db.Value) error { +func dbMapCreate(uri string, jsonData interface{}, result map[string]map[string]db.Value) error { + xpathTmplt, keyName := xpathKeyExtract(uri) + if isCvlYang(uri) { + cvlYangReqToDbMapCreate(uri, jsonData, result) + } else { + yangReqToDbMapCreate(uri, xpathTmplt, keyName, jsonData, result) + } + return nil +} + +func yangReqToDbMapCreate(uri string, xpathPrefix string, keyName string, jsonData interface{}, result map[string]map[string]db.Value) error { log.Info("key(\"%v\"), xpathPrefix(\"%v\").", keyName, xpathPrefix) if reflect.ValueOf(jsonData).Kind() == reflect.Slice { @@ -146,7 +171,7 @@ func dbMapCreate(keyName string, xpathPrefix string, jsonData interface{}, resul // string for _, data := range dataMap { keyName := keyCreate(keyName, xpathPrefix, data) - return dbMapCreate(keyName, xpathPrefix, data, result) + yangReqToDbMapCreate(uri, xpathPrefix, keyName, data, result) } } else { if reflect.ValueOf(jsonData).Kind() == reflect.Map { @@ -156,25 +181,21 @@ func dbMapCreate(keyName string, xpathPrefix string, jsonData interface{}, resul if typeOfValue == reflect.Map || typeOfValue == reflect.Slice { log.Info("slice/map data: key(\"%v\"), xpathPrefix(\"%v\").", keyName, xpathPrefix) - if directDbMapData(key.String(), jData.MapIndex(key).Interface(), result) { - continue - } else { - pathAttr := key.String() - if strings.Contains(pathAttr, ":") { - pathAttr = strings.Split(pathAttr, ":")[1] - } - xpath := xpathPrefix + "/" + pathAttr - - if xSpecMap[xpath] != nil && len(xSpecMap[xpath].xfmrFunc) > 0 { - subMap := callXfmr() - // map[string]map[string]db.Value - //subMap := XlateFuncCall(xpathInfo.xfmrFunc, name, value) - mapCopy(result, subMap) - return nil - } else { - return dbMapCreate(keyName, xpath, jData.MapIndex(key).Interface(), result) - } - } + pathAttr := key.String() + if strings.Contains(pathAttr, ":") { + pathAttr = strings.Split(pathAttr, ":")[1] + } + xpath := xpathPrefix + "/" + pathAttr + + if xSpecMap[xpath] != nil && len(xSpecMap[xpath].xfmrFunc) > 0 { + subMap := callXfmr() + // map[string]map[string]db.Value + //subMap := XlateFuncCall(xpathInfo.xfmrFunc, name, value) + mapCopy(result, subMap) + return nil + } else { + return yangReqToDbMapCreate(uri, xpath, keyName, jData.MapIndex(key).Interface(), result) + } } else { pathAttr := key.String() if strings.Contains(pathAttr, ":") { From 7fd76e0f50d67d15e5af8b0ad52925696146c8f3 Mon Sep 17 00:00:00 2001 From: Tejaswi Goel Date: Thu, 15 Aug 2019 16:41:38 -0700 Subject: [PATCH 040/214] Add sonic-acl UT tests Signed-off-by: Tejaswi Goel --- .../acl-sonic/01_create_MyACL1_1Rule.json | 22 ++++++++++++ .../acl-sonic/01_create_MyACL1_1Rule_cmd.txt | 1 + .../acl-sonic/01_delete_MyACL1_1Rule_cmd.txt | 1 + .../test/acl-sonic/01_delete_MyACL1_cmd.txt | 1 + .../acl-sonic/01_delete_all_Rules_cmd.txt | 1 + .../acl-sonic/01_get_MyACL1_1Rule_cmd.txt | 1 + .../test/acl-sonic/01_get_MyACL1_command.txt | 4 +++ .../test/acl-sonic/01_replace_MyACL1.json | 22 ++++++++++++ .../test/acl-sonic/01_replace_MyACL1_cmd.txt | 1 + .../test/acl-sonic/01_update_MyACL1.json | 33 +++++++++++++++++ .../test/acl-sonic/01_update_MyACL1_cmd.txt | 1 + .../acl-sonic/02_create_MyACL3_MyACL4.json | 35 +++++++++++++++++++ .../test/acl-sonic/02_get_all_Rules_cmd.txt | 1 + 13 files changed, 124 insertions(+) create mode 100644 src/translib/test/acl-sonic/01_create_MyACL1_1Rule.json create mode 100644 src/translib/test/acl-sonic/01_create_MyACL1_1Rule_cmd.txt create mode 100644 src/translib/test/acl-sonic/01_delete_MyACL1_1Rule_cmd.txt create mode 100644 src/translib/test/acl-sonic/01_delete_MyACL1_cmd.txt create mode 100644 src/translib/test/acl-sonic/01_delete_all_Rules_cmd.txt create mode 100644 src/translib/test/acl-sonic/01_get_MyACL1_1Rule_cmd.txt create mode 100644 src/translib/test/acl-sonic/01_get_MyACL1_command.txt create mode 100644 src/translib/test/acl-sonic/01_replace_MyACL1.json create mode 100644 src/translib/test/acl-sonic/01_replace_MyACL1_cmd.txt create mode 100644 src/translib/test/acl-sonic/01_update_MyACL1.json create mode 100644 src/translib/test/acl-sonic/01_update_MyACL1_cmd.txt create mode 100644 src/translib/test/acl-sonic/02_create_MyACL3_MyACL4.json create mode 100644 src/translib/test/acl-sonic/02_get_all_Rules_cmd.txt diff --git a/src/translib/test/acl-sonic/01_create_MyACL1_1Rule.json b/src/translib/test/acl-sonic/01_create_MyACL1_1Rule.json new file mode 100644 index 0000000000..c59e8e3269 --- /dev/null +++ b/src/translib/test/acl-sonic/01_create_MyACL1_1Rule.json @@ -0,0 +1,22 @@ +{ + "ACL_TABLE": [ + { + "aclname": "MyACL1_ACL_IPV4", + "policy_desc": "Description for MyACL1" + } + ], + "ACL_RULE": [ + { + "aclname": "MyACL1_ACL_IPV4", + "rulename": "RULE_1", + "PRIORITY": 65534, + "RULE_DESCRIPTION": "Description for MyACL1", + "PACKET_ACTION": "FORWARD", + "IP_TYPE": "ipv4", + "IP_PROTOCOL": 6, + "SRC_IP": "10.1.1.1/32", + "DST_IP": "20.2.2.2/32" + } + ] + +} diff --git a/src/translib/test/acl-sonic/01_create_MyACL1_1Rule_cmd.txt b/src/translib/test/acl-sonic/01_create_MyACL1_1Rule_cmd.txt new file mode 100644 index 0000000000..fc6aa77e30 --- /dev/null +++ b/src/translib/test/acl-sonic/01_create_MyACL1_1Rule_cmd.txt @@ -0,0 +1 @@ +./translibtest -o "create" -u "/sonic-acl:sonic-acl" -p "./acl-sonic/01_create_MyACL1.json" -logtostderr diff --git a/src/translib/test/acl-sonic/01_delete_MyACL1_1Rule_cmd.txt b/src/translib/test/acl-sonic/01_delete_MyACL1_1Rule_cmd.txt new file mode 100644 index 0000000000..1813ec6ed0 --- /dev/null +++ b/src/translib/test/acl-sonic/01_delete_MyACL1_1Rule_cmd.txt @@ -0,0 +1 @@ +./translibtest -o "delete" -u "/sonic-acl:sonic-acl/ACL_RULE[aclname=MyACL1_ACL_IPV4][rulename=RULE_1]" -logtostderr diff --git a/src/translib/test/acl-sonic/01_delete_MyACL1_cmd.txt b/src/translib/test/acl-sonic/01_delete_MyACL1_cmd.txt new file mode 100644 index 0000000000..59153ec876 --- /dev/null +++ b/src/translib/test/acl-sonic/01_delete_MyACL1_cmd.txt @@ -0,0 +1 @@ +./translibtest -o "delete" -u "/sonic-acl:sonic-acl/ACL_TABLE[aclname=MyACL1_ACL_IPV4]" -logtostderr diff --git a/src/translib/test/acl-sonic/01_delete_all_Rules_cmd.txt b/src/translib/test/acl-sonic/01_delete_all_Rules_cmd.txt new file mode 100644 index 0000000000..120c24ece8 --- /dev/null +++ b/src/translib/test/acl-sonic/01_delete_all_Rules_cmd.txt @@ -0,0 +1 @@ +./translibtest -o "delete" -u "/sonic-acl:sonic-acl" -logtostderr diff --git a/src/translib/test/acl-sonic/01_get_MyACL1_1Rule_cmd.txt b/src/translib/test/acl-sonic/01_get_MyACL1_1Rule_cmd.txt new file mode 100644 index 0000000000..84ca9596a6 --- /dev/null +++ b/src/translib/test/acl-sonic/01_get_MyACL1_1Rule_cmd.txt @@ -0,0 +1 @@ +./translibtest -o "get" -u "/sonic-acl:sonic-acl/ACL_RULE[aclname=MyACL1_ACL_IPV4][rulename=RULE_1]" -logtostderr diff --git a/src/translib/test/acl-sonic/01_get_MyACL1_command.txt b/src/translib/test/acl-sonic/01_get_MyACL1_command.txt new file mode 100644 index 0000000000..c5bcaa74b5 --- /dev/null +++ b/src/translib/test/acl-sonic/01_get_MyACL1_command.txt @@ -0,0 +1,4 @@ +./translibtest -o "get" -u "/sonic-acl:sonic-acl/ACL_TABLE[aclname=MyACL1_ACL_IPV4]" -logtostderr + + + diff --git a/src/translib/test/acl-sonic/01_replace_MyACL1.json b/src/translib/test/acl-sonic/01_replace_MyACL1.json new file mode 100644 index 0000000000..0767ab34e6 --- /dev/null +++ b/src/translib/test/acl-sonic/01_replace_MyACL1.json @@ -0,0 +1,22 @@ +{ + "ACL_TABLE": [ + { + "aclname": "MyACL1_ACL_IPV4", + "policy_desc": "Updated MyACL1", + "type": "L3" + } + ], + "ACL_RULE": [ + { + "aclname": "MyACL1_ACL_IPV4", + "rulename": "RULE_1", + "PRIORITY": 65536, + "RULE_DESCRIPTION": "Description for MyACL1 Rule1", + "PACKET_ACTION": "FORWARD", + "IP_TYPE": "ipv4", + "IP_PROTOCOL": 6, + "SRC_IP": "10.1.1.1/32", + "DST_IP": "any" + } + ] +} diff --git a/src/translib/test/acl-sonic/01_replace_MyACL1_cmd.txt b/src/translib/test/acl-sonic/01_replace_MyACL1_cmd.txt new file mode 100644 index 0000000000..cff3a546b9 --- /dev/null +++ b/src/translib/test/acl-sonic/01_replace_MyACL1_cmd.txt @@ -0,0 +1 @@ +./translibtest -o "replace" -u "/sonic-acl:sonic-acl" -p "./acl-sonic/01_replace_MyACL1.json" -logtostderr diff --git a/src/translib/test/acl-sonic/01_update_MyACL1.json b/src/translib/test/acl-sonic/01_update_MyACL1.json new file mode 100644 index 0000000000..5a4ec83182 --- /dev/null +++ b/src/translib/test/acl-sonic/01_update_MyACL1.json @@ -0,0 +1,33 @@ +{ + "ACL_TABLE": [ + { + "aclname": "MyACL1_ACL_IPV4", + "policy_desc": "Updated MyACL1", + "type": "L3" + } + ], + "ACL_RULE": [ + { + "aclname": "MyACL1_ACL_IPV4", + "rulename": "RULE_1", + "PRIORITY": 65534, + "RULE_DESCRIPTION": "Description for MyACL1 Rule1", + "PACKET_ACTION": "FORWARD", + "IP_TYPE": "ipv4", + "IP_PROTOCOL": 6, + "SRC_IP": "11.1.1.1/32", + "DST_IP": "22.2.2.2/32" + }, + { + "aclname": "MyACL1_ACL_IPV4", + "rulename": "RULE_2", + "PRIORITY": 65536, + "RULE_DESCRIPTION": "Description for MyACL1 Rule2", + "PACKET_ACTION": "FORWARD", + "IP_TYPE": "ipv4", + "IP_PROTOCOL": 6, + "SRC_IP": "any", + "DST_IP": "any" + } + ] +} diff --git a/src/translib/test/acl-sonic/01_update_MyACL1_cmd.txt b/src/translib/test/acl-sonic/01_update_MyACL1_cmd.txt new file mode 100644 index 0000000000..e56bad6729 --- /dev/null +++ b/src/translib/test/acl-sonic/01_update_MyACL1_cmd.txt @@ -0,0 +1 @@ +./translibtest -o "update" -u "/sonic-acl:sonic-acl" -p "./acl-sonic/01_update_MyACL1.json" -logtostderr diff --git a/src/translib/test/acl-sonic/02_create_MyACL3_MyACL4.json b/src/translib/test/acl-sonic/02_create_MyACL3_MyACL4.json new file mode 100644 index 0000000000..fbc6211df4 --- /dev/null +++ b/src/translib/test/acl-sonic/02_create_MyACL3_MyACL4.json @@ -0,0 +1,35 @@ +{ + "ACL_TABLE": [ + { + "aclname": "MyACL3_ACL_IPV4", + "policy_desc": "Description for MyACL3", + "stage": "EGRESS", + "type": "L3", + "ports": ["Ethernet0"] + }, + { + "aclname": "MyACL4_ACL_IPV4", + "policy_desc": "Description for MyACL4", + "stage": "EGRESS", + "type": "L3", + "ports": ["Ethernet4","Ethernet8"] + } + ], + "ACL_RULE": [ + { + "aclname": "MyACL3_ACL_IPV4", + "rulename": "RULE_1", + "PRIORITY": 65536, + "RULE_DESCRIPTION": "MyACL3_ACL_IPV4 rule description", + "PACKET_ACTION": "FORWARD", + "IP_TYPE": "ipv4", + "IP_PROTOCOL": 6, + "SRC_IP": "10.1.1.1/32", + "DST_IP": "20.2.2.2/32", + "L4_SRC_PORT_RANGE": "13000-14000", + "L4_DST_PORT_RANGE": "9000-12000", + "DSCP": 2 + } + ] + +} diff --git a/src/translib/test/acl-sonic/02_get_all_Rules_cmd.txt b/src/translib/test/acl-sonic/02_get_all_Rules_cmd.txt new file mode 100644 index 0000000000..c46ec3db33 --- /dev/null +++ b/src/translib/test/acl-sonic/02_get_all_Rules_cmd.txt @@ -0,0 +1 @@ +./translibtest -o "get" -u "/sonic-acl:sonic-acl" -logtostderr From 85fd40189f0ffc7d750170ae761213313b91202a Mon Sep 17 00:00:00 2001 From: amrutasali Date: Fri, 16 Aug 2019 00:34:44 +0000 Subject: [PATCH 041/214] common app - Added support for basic level DB operations --- src/cvl/schema/allyangs_tree.html | 3763 +++++++++++++++++++++++++++++ src/translib/common_app.go | 136 +- 2 files changed, 3885 insertions(+), 14 deletions(-) create mode 100644 src/cvl/schema/allyangs_tree.html diff --git a/src/cvl/schema/allyangs_tree.html b/src/cvl/schema/allyangs_tree.html new file mode 100644 index 0000000000..66547fabfe --- /dev/null +++ b/src/cvl/schema/allyangs_tree.html @@ -0,0 +1,3763 @@ + sonic-acl-dev sonic-acl sonic-bgp-neighbor sonic-buffer-pg sonic-buffer-pool sonic-buffer-profile sonic-cablelength sonic-common sonic-device-metadata sonic-device-neighbor sonic-dscp-tc-map sonic-interface sonic-mirror-session sonic-pfc-priority-queue-map sonic-pf-limits sonic-portchannel-interface sonic-portchannel sonic-port-qos-map sonic-port sonic-queue sonic-scheduler sonic-tc-priority-group-map sonic-tc-queue-map sonic-vlan-dev sonic-vlan-interface sonic-vlan sonic-wred-profile + + + + + + + + + +
+
+

Module: sonic-acl-dev, Namespace: + http://github.com/Azure/sonic-acl-dev, Prefix: + acld

+

Module: sonic-acl, Namespace: + http://github.com/Azure/sonic-acl, Prefix: + sacl

+

Module: sonic-bgp-neighbor, Namespace: + http://github.com/Azure/sonic-bgp-neighbor, Prefix: + sbn

+

Module: sonic-buffer-pg, Namespace: + http://github.com/Azure/sonic-buffer-pg, Prefix: + bpg

+

Module: sonic-buffer-pool, Namespace: + http://github.com/Azure/sonic-buffer-pool, Prefix: + bpl

+

Module: sonic-buffer-profile, Namespace: + http://github.com/Azure/sonic-buffer-profile, Prefix: + bpf

+

Module: sonic-cablelength, Namespace: + http://github.com/Azure/sonic-cablelength, Prefix: + scl

+

Module: sonic-common, Namespace: + http://github.com/Azure/sonic-common, Prefix: + sv

+

Module: sonic-device-metadata, Namespace: + http://github.com/Azure/sonic-device-metadata, Prefix: + sdm

+

Module: sonic-device-neighbor, Namespace: + http://github.com/Azure/sonic-device-neighbor, Prefix: + sdn

+

Module: sonic-dscp-tc-map, Namespace: + http://github.com/Azure/sonic-dscp-tc-map, Prefix: + dtm

+

Module: sonic-interface, Namespace: + http://github.com/Azure/sonic-interface, Prefix: + sint

+

Module: sonic-mirror-session, Namespace: + http://github.com/Azure/sonic-mirror-session, Prefix: + sms

+

Module: sonic-pfc-priority-queue-map, Namespace: + http://github.com/Azure/sonic-pfc-priority-queue-map, Prefix: + ppq

+

Module: sonic-pf-limits, Namespace: + http://github.com/Azure/sonic-pf-limits, Prefix: + spf

+

Module: sonic-portchannel-interface, Namespace: + http://github.com/Azure/sonic-portchannel-interface, Prefix: + spchint

+

Module: sonic-portchannel, Namespace: + http://github.com/Azure/sonic-portchannel, Prefix: + spc

+

Module: sonic-port-qos-map, Namespace: + http://github.com/Azure/sonic-port-qos-map, Prefix: + pqm

+

Module: sonic-port, Namespace: + http://github.com/Azure/sonic-port, Prefix: + prt

+

Module: sonic-queue, Namespace: + http://github.com/Azure/sonic-queue, Prefix: + squeue

+

Module: sonic-scheduler, Namespace: + http://github.com/Azure/sonic-scheduler, Prefix: + sch

+

Module: sonic-tc-priority-group-map, Namespace: + http://github.com/Azure/sonic-tc-priority-group-map, Prefix: + tpg

+

Module: sonic-tc-queue-map, Namespace: + http://github.com/Azure/sonic-tc-queue-map, Prefix: + tqm

+

Module: sonic-vlan-dev, Namespace: + http://github.com/Azure/sonic-vlan-dev, Prefix: + svd

+

Module: sonic-vlan-interface, Namespace: + http://github.com/Azure/sonic-vlan-interface, Prefix: + svint

+

Module: sonic-vlan, Namespace: + http://github.com/Azure/sonic-vlan, Prefix: + svlan

+

Module: sonic-wred-profile, Namespace: + http://github.com/Azure/sonic-wred-profile, Prefix: + wrd

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Element + [+]Expand all + [-]Collapse all + SchemaTypeFlagsOptsStatusPath
+
+   + + sonic-acl +
+
module +
+
+   + + sonic-acl +
+
containerconfigcurrent/sacl:sonic-acl
+
+   + + ACL_TABLE[aclname] +
+
listconfigcurrent/sacl:sonic-acl/sacl:ACL_TABLE
+
+   + aclname +
+
leafstringconfigcurrent/sacl:sonic-acl/sacl:ACL_TABLE/sacl:aclname +
+
+   + policy_desc +
+
leafstringconfig?current/sacl:sonic-acl/sacl:ACL_TABLE/sacl:policy_desc +
+
+   + stage +
+
leafenumerationconfig?current/sacl:sonic-acl/sacl:ACL_TABLE/sacl:stage +
+
+   + type +
+
leafenumerationconfig?current/sacl:sonic-acl/sacl:ACL_TABLE/sacl:type +
+
+   + ports +
+
leaf-listleafrefconfig*current/sacl:sonic-acl/sacl:ACL_TABLE/sacl:ports +
+
+   + + ACL_RULE[aclname rulename] +
+
listconfigcurrent/sacl:sonic-acl/sacl:ACL_RULE
+
+   + aclname +
+
leafleafrefconfigcurrent/sacl:sonic-acl/sacl:ACL_RULE/sacl:aclname +
+
+   + rulename +
+
leafstringconfigcurrent/sacl:sonic-acl/sacl:ACL_RULE/sacl:rulename +
+
+   + PRIORITY +
+
leafuint16config?current/sacl:sonic-acl/sacl:ACL_RULE/sacl:PRIORITY +
+
+   + RULE_DESCRIPTION +
+
leafstringconfig?current/sacl:sonic-acl/sacl:ACL_RULE/sacl:RULE_DESCRIPTION +
+
+   + PACKET_ACTION +
+
leafenumerationconfig?current/sacl:sonic-acl/sacl:ACL_RULE/sacl:PACKET_ACTION +
+
+   + MIRROR_ACTION +
+
leafleafrefconfig?current/sacl:sonic-acl/sacl:ACL_RULE/sacl:MIRROR_ACTION +
+
+   + IP_TYPE +
+
leafenumerationconfig?current/sacl:sonic-acl/sacl:ACL_RULE/sacl:IP_TYPE +
+
+   + IP_PROTOCOL +
+
leafuint8config?current/sacl:sonic-acl/sacl:ACL_RULE/sacl:IP_PROTOCOL +
+
+   + ETHER_TYPE +
+
leafstringconfig?current/sacl:sonic-acl/sacl:ACL_RULE/sacl:ETHER_TYPE +
+
+   + + (ip_src_dst) +
+
choiceconfigChoicecurrent/sacl:sonic-acl/sacl:ACL_RULE
+
+   + + :(ipv4_src_dst) +
+
caseconfigcurrent/sacl:sonic-acl/sacl:ACL_RULE
+
+   + SRC_IP +
+
leafinet:ipv4-prefixconfigcurrent/sacl:sonic-acl/sacl:ACL_RULE/sacl:SRC_IP +
+
+   + DST_IP +
+
leafinet:ipv4-prefixconfigcurrent/sacl:sonic-acl/sacl:ACL_RULE/sacl:DST_IP +
+
+   + + :(ipv6_src_dst) +
+
caseconfigcurrent/sacl:sonic-acl/sacl:ACL_RULE
+
+   + SRC_IPV6 +
+
leafinet:ipv6-prefixconfigcurrent/sacl:sonic-acl/sacl:ACL_RULE/sacl:SRC_IPV6 +
+
+   + DST_IPV6 +
+
leafinet:ipv6-prefixconfigcurrent/sacl:sonic-acl/sacl:ACL_RULE/sacl:DST_IPV6 +
+
+   + + (src_port) +
+
choiceconfigChoicecurrent/sacl:sonic-acl/sacl:ACL_RULE
+
+   + + :(l4_src_port) +
+
caseconfigcurrent/sacl:sonic-acl/sacl:ACL_RULE
+
+   + L4_SRC_PORT +
+
leafuint16config?current/sacl:sonic-acl/sacl:ACL_RULE/sacl:L4_SRC_PORT +
+
+   + + :(l4_src_port_range) +
+
caseconfigcurrent/sacl:sonic-acl/sacl:ACL_RULE
+
+   + L4_SRC_PORT_RANGE +
+
leafstringconfig?current/sacl:sonic-acl/sacl:ACL_RULE/sacl:L4_SRC_PORT_RANGE +
+
+   + + (dst_port) +
+
choiceconfigChoicecurrent/sacl:sonic-acl/sacl:ACL_RULE
+
+   + + :(l4_dst_port) +
+
caseconfigcurrent/sacl:sonic-acl/sacl:ACL_RULE
+
+   + L4_DST_PORT +
+
leafuint16config?current/sacl:sonic-acl/sacl:ACL_RULE/sacl:L4_DST_PORT +
+
+   + + :(l4_dst_port_range) +
+
caseconfigcurrent/sacl:sonic-acl/sacl:ACL_RULE
+
+   + L4_DST_PORT_RANGE +
+
leafstringconfig?current/sacl:sonic-acl/sacl:ACL_RULE/sacl:L4_DST_PORT_RANGE +
+
+   + TCP_FLAGS +
+
leafstringconfig?current/sacl:sonic-acl/sacl:ACL_RULE/sacl:TCP_FLAGS +
+
+   + DSCP +
+
leafuint8config?current/sacl:sonic-acl/sacl:ACL_RULE/sacl:DSCP +
+
+   + + sonic-bgp-neighbor +
+
module +
+
+   + + sonic-bgp-neighbor +
+
containerconfigcurrent/sbn:sonic-bgp-neighbor
+
+   + + BGP_NEIGHBOR[ipaddress] +
+
listconfigcurrent/sbn:sonic-bgp-neighbor/sbn:BGP_NEIGHBOR
+
+   + ipaddress +
+
leafinet:ip-addressconfigcurrent/sbn:sonic-bgp-neighbor/sbn:BGP_NEIGHBOR/sbn:ipaddress +
+
+   + rrclient +
+
leafuint8config?current/sbn:sonic-bgp-neighbor/sbn:BGP_NEIGHBOR/sbn:rrclient +
+
+   + admin_status +
+
leafscommon:admin-statusconfig?current/sbn:sonic-bgp-neighbor/sbn:BGP_NEIGHBOR/sbn:admin_status +
+
+   + peer_addr +
+
leafinet:ip-addressconfig?current/sbn:sonic-bgp-neighbor/sbn:BGP_NEIGHBOR/sbn:peer_addr +
+
+   + name +
+
leafstringconfig?current/sbn:sonic-bgp-neighbor/sbn:BGP_NEIGHBOR/sbn:name +
+
+   + local_addr +
+
leafinet:ipv4-addressconfig?current/sbn:sonic-bgp-neighbor/sbn:BGP_NEIGHBOR/sbn:local_addr +
+
+   + nhopself +
+
leafuint8config?current/sbn:sonic-bgp-neighbor/sbn:BGP_NEIGHBOR/sbn:nhopself +
+
+   + holdtime +
+
leafuint8config?current/sbn:sonic-bgp-neighbor/sbn:BGP_NEIGHBOR/sbn:holdtime +
+
+   + asn +
+
leafuint64config?current/sbn:sonic-bgp-neighbor/sbn:BGP_NEIGHBOR/sbn:asn +
+
+   + keepalive +
+
leafuint8config?current/sbn:sonic-bgp-neighbor/sbn:BGP_NEIGHBOR/sbn:keepalive +
+
+   + + sonic-buffer-pg +
+
module +
+
+   + + sonic-buffer-pg +
+
containerconfigcurrent/bpg:sonic-buffer-pg
+
+   + + BUFFER_PG[ifname pg_num] +
+
listconfigcurrent/bpg:sonic-buffer-pg/bpg:BUFFER_PG
+
+   + ifname +
+
leafleafrefconfigcurrent/bpg:sonic-buffer-pg/bpg:BUFFER_PG/bpg:ifname +
+
+   + pg_num +
+
leafstringconfigcurrent/bpg:sonic-buffer-pg/bpg:BUFFER_PG/bpg:pg_num +
+
+   + profile +
+
leafleafrefconfig?current/bpg:sonic-buffer-pg/bpg:BUFFER_PG/bpg:profile +
+
+   + + sonic-buffer-pool +
+
module +
+
+   + + sonic-buffer-pool +
+
containerconfigcurrent/bpl:sonic-buffer-pool
+
+   + + BUFFER_POOL[name] +
+
listconfigcurrent/bpl:sonic-buffer-pool/bpl:BUFFER_POOL
+
+   + name +
+
leafstringconfigcurrent/bpl:sonic-buffer-pool/bpl:BUFFER_POOL/bpl:name +
+
+   + type +
+
leafenumerationconfig?current/bpl:sonic-buffer-pool/bpl:BUFFER_POOL/bpl:type +
+
+   + mode +
+
leafenumerationconfig?current/bpl:sonic-buffer-pool/bpl:BUFFER_POOL/bpl:mode +
+
+   + size +
+
leafuint64config?current/bpl:sonic-buffer-pool/bpl:BUFFER_POOL/bpl:size +
+
+   + + sonic-buffer-profile +
+
module +
+
+   + + sonic-buffer-profile +
+
containerconfigcurrent/bpf:sonic-buffer-profile
+
+   + + BUFFER_PROFILE[name] +
+
listconfigcurrent/bpf:sonic-buffer-profile/bpf:BUFFER_PROFILE
+
+   + name +
+
leafstringconfigcurrent/bpf:sonic-buffer-profile/bpf:BUFFER_PROFILE/bpf:name +
+
+   + static_th +
+
leafuint64config?current/bpf:sonic-buffer-profile/bpf:BUFFER_PROFILE/bpf:static_th +
+
+   + dynamic_th +
+
leafint64config?current/bpf:sonic-buffer-profile/bpf:BUFFER_PROFILE/bpf:dynamic_th +
+
+   + size +
+
leafuint64config?current/bpf:sonic-buffer-profile/bpf:BUFFER_PROFILE/bpf:size +
+
+   + pool +
+
leafleafrefconfig?current/bpf:sonic-buffer-profile/bpf:BUFFER_PROFILE/bpf:pool +
+
+   + xon_offset +
+
leafuint64config?current/bpf:sonic-buffer-profile/bpf:BUFFER_PROFILE/bpf:xon_offset +
+
+   + xon +
+
leafuint64config?current/bpf:sonic-buffer-profile/bpf:BUFFER_PROFILE/bpf:xon +
+
+   + xoff +
+
leafuint64config?current/bpf:sonic-buffer-profile/bpf:BUFFER_PROFILE/bpf:xoff +
+
+   + + sonic-cablelength +
+
module +
+
+   + + sonic-cablelength +
+
containerconfigcurrent/scl:sonic-cablelength
+
+   + + CABLE_LENGTH[name] +
+
listconfigcurrent/scl:sonic-cablelength/scl:CABLE_LENGTH
+
+   + name +
+
leafstringconfigcurrent/scl:sonic-cablelength/scl:CABLE_LENGTH/scl:name +
+
+   + + CABLE_LENGTH[port length] +
+
listconfigcurrent/scl:sonic-cablelength/scl:CABLE_LENGTH/scl:CABLE_LENGTH
+
+   + port +
+
leafleafrefconfigcurrent/scl:sonic-cablelength/scl:CABLE_LENGTH/scl:CABLE_LENGTH/scl:port +
+
+   + length +
+
leafstringconfigcurrent/scl:sonic-cablelength/scl:CABLE_LENGTH/scl:CABLE_LENGTH/scl:length +
+
+   + + sonic-common +
+
module +
+
+   + + operation +
+
containerconfigcurrent/sv:operation
+
+   + operation +
+
leafstringconfig?current/sv:operation/sv:operation +
+
+   + + sonic-device-metadata +
+
module +
+
+   + + sonic-device-metadata +
+
containerconfigcurrent/sdm:sonic-device-metadata
+
+   + + DEVICE_METADATA[name] +
+
listconfigcurrent/sdm:sonic-device-metadata/sdm:DEVICE_METADATA
+
+   + name +
+
leafstringconfigcurrent/sdm:sonic-device-metadata/sdm:DEVICE_METADATA/sdm:name +
+
+   + hwsku +
+
leafstringconfig?current/sdm:sonic-device-metadata/sdm:DEVICE_METADATA/sdm:hwsku +
+
+   + hostname +
+
leafstringconfig?current/sdm:sonic-device-metadata/sdm:DEVICE_METADATA/sdm:hostname +
+
+   + platform +
+
leafstringconfig?current/sdm:sonic-device-metadata/sdm:DEVICE_METADATA/sdm:platform +
+
+   + mac +
+
leafyang:mac-addressconfig?current/sdm:sonic-device-metadata/sdm:DEVICE_METADATA/sdm:mac +
+
+   + bgp_asn +
+
leafleafrefconfig?current/sdm:sonic-device-metadata/sdm:DEVICE_METADATA/sdm:bgp_asn +
+
+   + default_pfcwd_status +
+
leafenumerationconfig?current/sdm:sonic-device-metadata/sdm:DEVICE_METADATA/sdm:default_pfcwd_status +
+
+   + default_bgp_status +
+
leafscommon:admin-statusconfig?current/sdm:sonic-device-metadata/sdm:DEVICE_METADATA/sdm:default_bgp_status +
+
+   + docker_routing_config_mode +
+
leafenumerationconfig?current/sdm:sonic-device-metadata/sdm:DEVICE_METADATA/sdm:docker_routing_config_mode +
+
+   + deployment_id +
+
leafuint8config?current/sdm:sonic-device-metadata/sdm:DEVICE_METADATA/sdm:deployment_id +
+
+   + type +
+
leafenumerationconfig?current/sdm:sonic-device-metadata/sdm:DEVICE_METADATA/sdm:type +
+
+   + + sonic-device-neighbor +
+
module +
+
+   + + sonic-device-neighbor +
+
containerconfigcurrent/sdn:sonic-device-neighbor
+
+   + + DEVICE_NEIGHBOR[name] +
+
listconfigcurrent/sdn:sonic-device-neighbor/sdn:DEVICE_NEIGHBOR
+
+   + name +
+
leafstringconfigcurrent/sdn:sonic-device-neighbor/sdn:DEVICE_NEIGHBOR/sdn:name +
+
+   + mgmt_addr +
+
leafinet:ip-addressconfig?current/sdn:sonic-device-neighbor/sdn:DEVICE_NEIGHBOR/sdn:mgmt_addr +
+
+   + hwsku +
+
leafstringconfig?current/sdn:sonic-device-neighbor/sdn:DEVICE_NEIGHBOR/sdn:hwsku +
+
+   + lo_addr +
+
leafinet:ip-addressconfig?current/sdn:sonic-device-neighbor/sdn:DEVICE_NEIGHBOR/sdn:lo_addr +
+
+   + local_port +
+
leafleafrefconfig?current/sdn:sonic-device-neighbor/sdn:DEVICE_NEIGHBOR/sdn:local_port +
+
+   + type +
+
leafenumerationconfig?current/sdn:sonic-device-neighbor/sdn:DEVICE_NEIGHBOR/sdn:type +
+
+   + port +
+
leafleafrefconfig?current/sdn:sonic-device-neighbor/sdn:DEVICE_NEIGHBOR/sdn:port +
+
+   + + sonic-dscp-tc-map +
+
module +
+
+   + + sonic-dscp-tc-map +
+
containerconfigcurrent/dtm:sonic-dscp-tc-map
+
+   + + DSCP_TO_TC_MAP[name] +
+
listconfigcurrent/dtm:sonic-dscp-tc-map/dtm:DSCP_TO_TC_MAP
+
+   + name +
+
leafstringconfigcurrent/dtm:sonic-dscp-tc-map/dtm:DSCP_TO_TC_MAP/dtm:name +
+
+   + + DSCP_TO_TC_MAP[dscp tc_num] +
+
listconfigcurrent/dtm:sonic-dscp-tc-map/dtm:DSCP_TO_TC_MAP/dtm:DSCP_TO_TC_MAP
+
+   + tc_num +
+
leafstringconfigcurrent/dtm:sonic-dscp-tc-map/dtm:DSCP_TO_TC_MAP/dtm:DSCP_TO_TC_MAP/dtm:tc_num +
+
+   + dscp +
+
leafstringconfigcurrent/dtm:sonic-dscp-tc-map/dtm:DSCP_TO_TC_MAP/dtm:DSCP_TO_TC_MAP/dtm:dscp +
+
+   + + sonic-interface +
+
module +
+
+   + + sonic-interface +
+
containerconfigcurrent/sint:sonic-interface
+
+   + + INTERFACE[portname ip_prefix] +
+
listconfigcurrent/sint:sonic-interface/sint:INTERFACE
+
+   + portname +
+
leafleafrefconfigcurrent/sint:sonic-interface/sint:INTERFACE/sint:portname +
+
+   + ip_prefix +
+
leafinet:ip-prefixconfigcurrent/sint:sonic-interface/sint:INTERFACE/sint:ip_prefix +
+
+   + + sonic-mirror-session +
+
module +
+
+   + + sonic-mirror-session +
+
containerconfigcurrent/sms:sonic-mirror-session
+
+   + + MIRROR_SESSION[name] +
+
listconfigcurrent/sms:sonic-mirror-session/sms:MIRROR_SESSION
+
+   + name +
+
leafstringconfigcurrent/sms:sonic-mirror-session/sms:MIRROR_SESSION/sms:name +
+
+   + src_ip +
+
leafinet:ipv4-addressconfig?current/sms:sonic-mirror-session/sms:MIRROR_SESSION/sms:src_ip +
+
+   + dst_ip +
+
leafinet:ipv4-addressconfig?current/sms:sonic-mirror-session/sms:MIRROR_SESSION/sms:dst_ip +
+
+   + gre_type +
+
leafstringconfig?current/sms:sonic-mirror-session/sms:MIRROR_SESSION/sms:gre_type +
+
+   + dscp +
+
leafuint8config?current/sms:sonic-mirror-session/sms:MIRROR_SESSION/sms:dscp +
+
+   + ttl +
+
leafuint8config?current/sms:sonic-mirror-session/sms:MIRROR_SESSION/sms:ttl +
+
+   + queue +
+
leafuint8config?current/sms:sonic-mirror-session/sms:MIRROR_SESSION/sms:queue +
+
+   + + sonic-pfc-priority-queue-map +
+
module +
+
+   + + sonic-pfc-priority-queue-map +
+
containerconfigcurrent/ppq:sonic-pfc-priority-queue-map
+
+   + + MAP_PFC_PRIORITY_TO_QUEUE[name] +
+
listconfigcurrent/ppq:sonic-pfc-priority-queue-map/ppq:MAP_PFC_PRIORITY_TO_QUEUE
+
+   + name +
+
leafstringconfigcurrent/ppq:sonic-pfc-priority-queue-map/ppq:MAP_PFC_PRIORITY_TO_QUEUE/ppq:name +
+
+   + + MAP_PFC_PRIORITY_TO_QUEUE[pfc_priority qindex] +
+
listconfigcurrent/ppq:sonic-pfc-priority-queue-map/ppq:MAP_PFC_PRIORITY_TO_QUEUE/ppq:MAP_PFC_PRIORITY_TO_QUEUE
+
+   + pfc_priority +
+
leafstringconfigcurrent/ppq:sonic-pfc-priority-queue-map/ppq:MAP_PFC_PRIORITY_TO_QUEUE/ppq:MAP_PFC_PRIORITY_TO_QUEUE/ppq:pfc_priority +
+
+   + qindex +
+
leafstringconfigcurrent/ppq:sonic-pfc-priority-queue-map/ppq:MAP_PFC_PRIORITY_TO_QUEUE/ppq:MAP_PFC_PRIORITY_TO_QUEUE/ppq:qindex +
+
+   + + sonic-pf-limits +
+
module +
+
+   + + sonic-pf-limits +
+
containerconfigcurrent/spf:sonic-pf-limits
+
+   + + acl +
+
containerconfigcurrent/spf:sonic-pf-limits/spf:acl
+
+   + MAX_ACL_RULES +
+
leafuint16config?current/spf:sonic-pf-limits/spf:acl/spf:MAX_ACL_RULES +
+
+   + MAX_PRIORITY +
+
leafuint16config?current/spf:sonic-pf-limits/spf:acl/spf:MAX_PRIORITY +
+
+   + + vlan +
+
containerconfigcurrent/spf:sonic-pf-limits/spf:vlan
+
+   + MAX_VLANS +
+
leafuint16config?current/spf:sonic-pf-limits/spf:vlan/spf:MAX_VLANS +
+
+   + + sonic-portchannel-interface +
+
module +
+
+   + + sonic-portchannel-interface +
+
containerconfigcurrent/spchint:sonic-portchannel-interface
+
+   + + PORTCHANNEL_INTERFACE[pch_name ip_prefix] +
+
listconfigcurrent/spchint:sonic-portchannel-interface/spchint:PORTCHANNEL_INTERFACE
+
+   + pch_name +
+
leafleafrefconfigcurrent/spchint:sonic-portchannel-interface/spchint:PORTCHANNEL_INTERFACE/spchint:pch_name +
+
+   + ip_prefix +
+
leafinet:ip-prefixconfigcurrent/spchint:sonic-portchannel-interface/spchint:PORTCHANNEL_INTERFACE/spchint:ip_prefix +
+
+   + + sonic-portchannel +
+
module +
+
+   + + sonic-portchannel +
+
containerconfigcurrent/spc:sonic-portchannel
+
+   + + PORTCHANNEL[name] +
+
listconfigcurrent/spc:sonic-portchannel/spc:PORTCHANNEL
+
+   + name +
+
leafstringconfigcurrent/spc:sonic-portchannel/spc:PORTCHANNEL/spc:name +
+
+   + admin_status +
+
leafscommon:admin-statusconfig?current/spc:sonic-portchannel/spc:PORTCHANNEL/spc:admin_status +
+
+   + mtu +
+
leafuint16config?current/spc:sonic-portchannel/spc:PORTCHANNEL/spc:mtu +
+
+   + min_links +
+
leafuint8config?current/spc:sonic-portchannel/spc:PORTCHANNEL/spc:min_links +
+
+   + fallback +
+
leafbooleanconfig?current/spc:sonic-portchannel/spc:PORTCHANNEL/spc:fallback +
+
+   + + PORTCHANNEL_MEMBER[name ifname] +
+
listconfigcurrent/spc:sonic-portchannel/spc:PORTCHANNEL_MEMBER
+
+   + name +
+
leafleafrefconfigcurrent/spc:sonic-portchannel/spc:PORTCHANNEL_MEMBER/spc:name +
+
+   + ifname +
+
leafleafrefconfigcurrent/spc:sonic-portchannel/spc:PORTCHANNEL_MEMBER/spc:ifname +
+
+   + + sonic-port-qos-map +
+
module +
+
+   + + sonic-port-qos-map +
+
containerconfigcurrent/pqm:sonic-port-qos-map
+
+   + + PORT_QOS_MAP[ifname] +
+
listconfigcurrent/pqm:sonic-port-qos-map/pqm:PORT_QOS_MAP
+
+   + ifname +
+
leafleafrefconfigcurrent/pqm:sonic-port-qos-map/pqm:PORT_QOS_MAP/pqm:ifname +
+
+   + tc_to_pg_map +
+
leafleafrefconfig?current/pqm:sonic-port-qos-map/pqm:PORT_QOS_MAP/pqm:tc_to_pg_map +
+
+   + tc_to_queue_map +
+
leafleafrefconfig?current/pqm:sonic-port-qos-map/pqm:PORT_QOS_MAP/pqm:tc_to_queue_map +
+
+   + pfc-enable +
+
leafstringconfig?current/pqm:sonic-port-qos-map/pqm:PORT_QOS_MAP/pqm:pfc-enable +
+
+   + pfc_to_queue_map +
+
leafleafrefconfig?current/pqm:sonic-port-qos-map/pqm:PORT_QOS_MAP/pqm:pfc_to_queue_map +
+
+   + dscp_to_tc_map +
+
leafleafrefconfig?current/pqm:sonic-port-qos-map/pqm:PORT_QOS_MAP/pqm:dscp_to_tc_map +
+
+   + + sonic-port +
+
module +
+
+   + + sonic-port +
+
containerconfigcurrent/prt:sonic-port
+
+   + + PORT[ifname] +
+
listconfigcurrent/prt:sonic-port/prt:PORT
+
+   + ifname +
+
leafstringconfigcurrent/prt:sonic-port/prt:PORT/prt:ifname +
+
+   + index +
+
leafuint16config?current/prt:sonic-port/prt:PORT/prt:index +
+
+   + speed +
+
leafuint64config?current/prt:sonic-port/prt:PORT/prt:speed +
+
+   + valid_speeds +
+
leafstringconfig?current/prt:sonic-port/prt:PORT/prt:valid_speeds +
+
+   + alias +
+
leafstringconfig?current/prt:sonic-port/prt:PORT/prt:alias +
+
+   + description +
+
leafstringconfig?current/prt:sonic-port/prt:PORT/prt:description +
+
+   + mtu +
+
leafuint32config?current/prt:sonic-port/prt:PORT/prt:mtu +
+
+   + lanes +
+
leafstringconfig?current/prt:sonic-port/prt:PORT/prt:lanes +
+
+   + admin_status +
+
leafscommon:admin-statusconfig?current/prt:sonic-port/prt:PORT/prt:admin_status +
+
+   + + sonic-queue +
+
module +
+
+   + + sonic-queue +
+
containerconfigcurrent/squeue:sonic-queue
+
+   + + QUEUE[ifname qindex] +
+
listconfigcurrent/squeue:sonic-queue/squeue:QUEUE
+
+   + ifname +
+
leafleafrefconfigcurrent/squeue:sonic-queue/squeue:QUEUE/squeue:ifname +
+
+   + qindex +
+
leafstringconfigcurrent/squeue:sonic-queue/squeue:QUEUE/squeue:qindex +
+
+   + scheduler +
+
leafleafrefconfig?current/squeue:sonic-queue/squeue:QUEUE/squeue:scheduler +
+
+   + wred_profile +
+
leafleafrefconfig?current/squeue:sonic-queue/squeue:QUEUE/squeue:wred_profile +
+
+   + + sonic-scheduler +
+
module +
+
+   + + sonic-scheduler +
+
containerconfigcurrent/sch:sonic-scheduler
+
+   + + SCHEDULER[name] +
+
listconfigcurrent/sch:sonic-scheduler/sch:SCHEDULER
+
+   + name +
+
leafstringconfigcurrent/sch:sonic-scheduler/sch:SCHEDULER/sch:name +
+
+   + type +
+
leafenumerationconfig?current/sch:sonic-scheduler/sch:SCHEDULER/sch:type +
+
+   + weight +
+
leafuint8config?current/sch:sonic-scheduler/sch:SCHEDULER/sch:weight +
+
+   + priority +
+
leafuint8config?current/sch:sonic-scheduler/sch:SCHEDULER/sch:priority +
+
+   + + sonic-tc-priority-group-map +
+
module +
+
+   + + sonic-tc-priority-group-map +
+
containerconfigcurrent/tpg:sonic-tc-priority-group-map
+
+   + + TC_TO_PRIORITY_GROUP_MAP[name] +
+
listconfigcurrent/tpg:sonic-tc-priority-group-map/tpg:TC_TO_PRIORITY_GROUP_MAP
+
+   + name +
+
leafstringconfigcurrent/tpg:sonic-tc-priority-group-map/tpg:TC_TO_PRIORITY_GROUP_MAP/tpg:name +
+
+   + + TC_TO_PRIORITY_GROUP_MAP[tc_num pg_num] +
+
listconfigcurrent/tpg:sonic-tc-priority-group-map/tpg:TC_TO_PRIORITY_GROUP_MAP/tpg:TC_TO_PRIORITY_GROUP_MAP
+
+   + tc_num +
+
leafstringconfigcurrent/tpg:sonic-tc-priority-group-map/tpg:TC_TO_PRIORITY_GROUP_MAP/tpg:TC_TO_PRIORITY_GROUP_MAP/tpg:tc_num +
+
+   + pg_num +
+
leafstringconfigcurrent/tpg:sonic-tc-priority-group-map/tpg:TC_TO_PRIORITY_GROUP_MAP/tpg:TC_TO_PRIORITY_GROUP_MAP/tpg:pg_num +
+
+   + + sonic-tc-queue-map +
+
module +
+
+   + + sonic-tc-queue-map +
+
containerconfigcurrent/tqm:sonic-tc-queue-map
+
+   + + TC_TO_QUEUE_MAP[name] +
+
listconfigcurrent/tqm:sonic-tc-queue-map/tqm:TC_TO_QUEUE_MAP
+
+   + name +
+
leafstringconfigcurrent/tqm:sonic-tc-queue-map/tqm:TC_TO_QUEUE_MAP/tqm:name +
+
+   + + TC_TO_QUEUE_MAP[tc_num qindex] +
+
listconfigcurrent/tqm:sonic-tc-queue-map/tqm:TC_TO_QUEUE_MAP/tqm:TC_TO_QUEUE_MAP
+
+   + tc_num +
+
leafstringconfigcurrent/tqm:sonic-tc-queue-map/tqm:TC_TO_QUEUE_MAP/tqm:TC_TO_QUEUE_MAP/tqm:tc_num +
+
+   + qindex +
+
leafstringconfigcurrent/tqm:sonic-tc-queue-map/tqm:TC_TO_QUEUE_MAP/tqm:TC_TO_QUEUE_MAP/tqm:qindex +
+
+   + + sonic-vlan-interface +
+
module +
+
+   + + sonic-vlan-interface +
+
containerconfigcurrent/svint:sonic-vlan-interface
+
+   + + VLAN_INTERFACE[portname ip_prefix] +
+
listconfigcurrent/svint:sonic-vlan-interface/svint:VLAN_INTERFACE
+
+   + portname +
+
leafleafrefconfigcurrent/svint:sonic-vlan-interface/svint:VLAN_INTERFACE/svint:portname +
+
+   + ip_prefix +
+
leafinet:ip-prefixconfigcurrent/svint:sonic-vlan-interface/svint:VLAN_INTERFACE/svint:ip_prefix +
+
+   + + sonic-vlan +
+
module +
+
+   + + sonic-vlan +
+
containerconfigcurrent/svlan:sonic-vlan
+
+   + + VLAN[name] +
+
listconfigcurrent/svlan:sonic-vlan/svlan:VLAN
+
+   + name +
+
leafstringconfigcurrent/svlan:sonic-vlan/svlan:VLAN/svlan:name +
+
+   + vlanid +
+
leafuint16configcurrent/svlan:sonic-vlan/svlan:VLAN/svlan:vlanid +
+
+   + members +
+
leaf-listleafrefconfig*current/svlan:sonic-vlan/svlan:VLAN/svlan:members +
+
+   + + VLAN_MEMBER[name ifname] +
+
listconfigcurrent/svlan:sonic-vlan/svlan:VLAN_MEMBER
+
+   + name +
+
leafleafrefconfigcurrent/svlan:sonic-vlan/svlan:VLAN_MEMBER/svlan:name +
+
+   + ifname +
+
leafleafrefconfigcurrent/svlan:sonic-vlan/svlan:VLAN_MEMBER/svlan:ifname +
+
+   + tagging_mode +
+
leafscommon:tagging_modeconfig?current/svlan:sonic-vlan/svlan:VLAN_MEMBER/svlan:tagging_mode +
+
+   + + sonic-wred-profile +
+
module +
+
+   + + sonic-wred-profile +
+
containerconfigcurrent/wrd:sonic-wred-profile
+
+   + + WRED_PROFILE[name] +
+
listconfigcurrent/wrd:sonic-wred-profile/wrd:WRED_PROFILE
+
+   + name +
+
leafstringconfigcurrent/wrd:sonic-wred-profile/wrd:WRED_PROFILE/wrd:name +
+
+   + yellow_min_threshold +
+
leafuint64config?current/wrd:sonic-wred-profile/wrd:WRED_PROFILE/wrd:yellow_min_threshold +
+
+   + green_min_threshold +
+
leafuint64config?current/wrd:sonic-wred-profile/wrd:WRED_PROFILE/wrd:green_min_threshold +
+
+   + red_min_threshold +
+
leafuint64config?current/wrd:sonic-wred-profile/wrd:WRED_PROFILE/wrd:red_min_threshold +
+
+   + yellow_max_threshold +
+
leafuint64config?current/wrd:sonic-wred-profile/wrd:WRED_PROFILE/wrd:yellow_max_threshold +
+
+   + green_max_threshold +
+
leafuint64config?current/wrd:sonic-wred-profile/wrd:WRED_PROFILE/wrd:green_max_threshold +
+
+   + red_max_threshold +
+
leafuint64config?current/wrd:sonic-wred-profile/wrd:WRED_PROFILE/wrd:red_max_threshold +
+
+   + ecn +
+
leafenumerationconfig?current/wrd:sonic-wred-profile/wrd:WRED_PROFILE/wrd:ecn +
+
+   + wred_green_enable +
+
leafbooleanconfig?current/wrd:sonic-wred-profile/wrd:WRED_PROFILE/wrd:wred_green_enable +
+
+   + wred_yellow_enable +
+
leafbooleanconfig?current/wrd:sonic-wred-profile/wrd:WRED_PROFILE/wrd:wred_yellow_enable +
+
+   + wred_red_enable +
+
leafbooleanconfig?current/wrd:sonic-wred-profile/wrd:WRED_PROFILE/wrd:wred_red_enable + +
+
+ + + diff --git a/src/translib/common_app.go b/src/translib/common_app.go index 903b64f637..6a73768901 100644 --- a/src/translib/common_app.go +++ b/src/translib/common_app.go @@ -22,6 +22,7 @@ type CommonApp struct { pathInfo *PathInfo ygotRoot *ygot.GoStruct ygotTarget *interface{} + cmnAppTableMap map[string]map[string]db.Value } var cmnAppInfo = appInfo{appType: reflect.TypeOf(CommonApp{}), @@ -76,9 +77,8 @@ func (app *CommonApp) translateReplace(d *db.DB) ([]db.WatchKeys, error) { var keys []db.WatchKeys log.Info("translateReplace:path =", app.pathInfo.Path) - //keys, err = app.translateCRUCommon(d, REPLACE) + keys, err = app.translateCRUCommon(d, REPLACE) - err = errors.New("Not implemented") return keys, err } @@ -86,8 +86,7 @@ func (app *CommonApp) translateDelete(d *db.DB) ([]db.WatchKeys, error) { var err error var keys []db.WatchKeys log.Info("translateDelete:path =", app.pathInfo.Path) - - keys, err = app.generateDbWatchKeys(d, true) + keys, err = app.translateCRUCommon(d, DELETE) return keys, err } @@ -103,8 +102,6 @@ func (app *CommonApp) translateGet(dbs [db.MaxDB]*db.DB) (*map[db.DBNum][]transf func (app *CommonApp) translateSubscribe(dbs [db.MaxDB]*db.DB, path string) (*notificationOpts, *notificationInfo, error) { err := errors.New("Not supported") - //configDb := dbs[db.ConfigDB] - //pathInfo := NewPathInfo(path) notifInfo := notificationInfo{dbno: db.ConfigDB} return nil, ¬ifInfo, err } @@ -116,6 +113,10 @@ func (app *CommonApp) processCreate(d *db.DB) (SetResponse, error) { log.Info("processCreate:path =", app.pathInfo.Path) targetType := reflect.TypeOf(*app.ygotTarget) log.Infof("processCreate: Target object is a <%s> of Type: %s", targetType.Kind().String(), targetType.Elem().Name()) + if err = app.processCommon(d, CREATE); err != nil { + log.Error(err) + resp = SetResponse{ErrSrc: AppErr} + } return resp, err @@ -125,6 +126,10 @@ func (app *CommonApp) processUpdate(d *db.DB) (SetResponse, error) { var err error var resp SetResponse log.Info("processUpdate:path =", app.pathInfo.Path) + if err = app.processCommon(d, UPDATE); err != nil { + log.Error(err) + resp = SetResponse{ErrSrc: AppErr} + } return resp, err } @@ -133,7 +138,10 @@ func (app *CommonApp) processReplace(d *db.DB) (SetResponse, error) { var err error var resp SetResponse log.Info("processReplace:path =", app.pathInfo.Path) - err = errors.New("Not implemented") + if err = app.processCommon(d, REPLACE); err != nil { + log.Error(err) + resp = SetResponse{ErrSrc: AppErr} + } return resp, err } @@ -143,9 +151,11 @@ func (app *CommonApp) processDelete(d *db.DB) (SetResponse, error) { log.Info("processDelete:path =", app.pathInfo.Path) - //aclObj := app.getAppRootObject() + if err = app.processCommon(d, DELETE); err != nil { + log.Error(err) + resp = SetResponse{ErrSrc: AppErr} + } - //targetUriPath, err := getYangPathFromUri(app.pathInfo.Path) return resp, err @@ -194,9 +204,11 @@ func (app *CommonApp) translateCRUCommon(d *db.DB, opcode int) ([]db.WatchKeys, } if len(result) == 0 { log.Error("XlatetoDB() returned empty map") - fmt.Println("XlatetoDB() returned empty map") + err = errors.New("transformer.XlatetoDB() returned empty map") + return keys, err } - for tblnm, _ := range result { + app.cmnAppTableMap = result + for tblnm, _ := range app.cmnAppTableMap { log.Error("Table name ", tblnm) tblsToWatch = append(tblsToWatch, &db.TableSpec{Name: tblnm}) } @@ -209,9 +221,105 @@ func (app *CommonApp) translateCRUCommon(d *db.DB, opcode int) ([]db.WatchKeys, return keys, err } +func (app *CommonApp) processCommon(d *db.DB, opcode int) error { + var err error + err = app.cmnAppDataDbOperation(d, opcode, app.cmnAppTableMap) + return err +} + +func (app *CommonApp) cmnAppDataDbOperation(d *db.DB, opcode int, cmnAppDataDbMap map[string]map[string]db.Value) error { + var err error + log.Info("Processing DB operation for ", cmnAppDataDbMap) + var cmnAppTs *db.TableSpec + for tblNm, tblInst := range cmnAppDataDbMap { + log.Info("Table name ", tblNm) + cmnAppTs = &db.TableSpec{Name: tblNm} + for tblKey, tblRw := range tblInst { + log.Info("Table key and row ", tblKey, tblRw) + switch opcode { + case CREATE: + log.Info("CREATE case") + existingEntry, err := d.GetEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}) + if existingEntry.IsPopulated() { + log.Info("Entry already exists hence modifying it.") + err := d.ModEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}, tblRw) + if err != nil { + log.Error("CREATE case - d.ModEntry() failure") + return err + } + } else { + err = d.CreateEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}, tblRw) + if err != nil { + log.Error("CREATE case - d.CreateEntry() failure") + return err + } + } + case UPDATE: + log.Info("UPDATE case") + existingEntry, err := d.GetEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}) + if existingEntry.IsPopulated() { + log.Info("Entry already exists hence modifying it.") + err = d.ModEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}, tblRw) + if err != nil { + log.Error("UPDATE case - d.ModEntry() failure") + return err + } + } else { + err = d.CreateEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}, tblRw) + if err != nil { + log.Error("UPDATE case - d.CreateEntry() failure") + return err + } + } + + case REPLACE: + log.Info("REPLACE case") + existingEntry, err := d.GetEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}) + if existingEntry.IsPopulated() { + log.Info("Entry already exists hence execute db.SetEntry") + err := d.SetEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}, tblRw) + if err != nil { + log.Error("REPLACE case - d.SetEntry() failure") + return err + } + } else { + log.Info("Entry doesn't exist hence create it.") + err = d.CreateEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}, tblRw) + if err != nil { + log.Error("REPLACE case - d.CreateEntry() failure") + return err + } + } + //TODO : should the table level replace be handled?? + case DELETE: + log.Info("DELETE case") + if len(tblRw.Field) == 0 { + log.Info("DELETE case - no fields/cols to delete hence delete the entire row.") + err := d.DeleteEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}) + if err != nil { + log.Error("DELETE case - d.DeleteEntry() failure") + return err + } + } else { + log.Info("DELETE case - fields/cols to delete hence delete only those fields.") + err := d.DeleteEntryFields(cmnAppTs, db.Key{Comp: []string{tblKey}}, tblRw) + if err != nil { + log.Error("DELETE case - d.DeleteEntryFields() failure") + return err + } + } + } + } + } + + return err + +} + func (app *CommonApp) generateDbWatchKeys(d *db.DB, isDeleteOp bool) ([]db.WatchKeys, error) { - var err error - var keys []db.WatchKeys + var err error + var keys []db.WatchKeys - return keys, err + return keys, err } + From 7a25984b36b339299ceae02157c5d38f7c65e7e6 Mon Sep 17 00:00:00 2001 From: amrutasali Date: Fri, 16 Aug 2019 01:22:26 +0000 Subject: [PATCH 042/214] Added support to pass in the operation type from apps to transformer XlatetoDB --- src/translib/acl_app.go | 2 +- src/translib/common_app.go | 2 +- src/translib/transformer/xlate.go | 32 ++++++++++++++++++++++++------- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/src/translib/acl_app.go b/src/translib/acl_app.go index 2fa0b83c30..35066d7f57 100644 --- a/src/translib/acl_app.go +++ b/src/translib/acl_app.go @@ -293,7 +293,7 @@ func (app *AclApp) translateCRUCommon(d *db.DB, opcode int) ([]db.WatchKeys, err log.Info("translateCRUCommon:acl:path =", app.pathInfo.Template) // TODO - once it's fully verfied, restrcuture the rest code - result, err := transformer.XlateToDb(app.pathInfo.Path, app.ygotRoot, app.ygotTarget) + result, err := transformer.XlateToDb(app.pathInfo.Path, opcode, app.ygotRoot, app.ygotTarget) if err != nil { fmt.Println(result) } diff --git a/src/translib/common_app.go b/src/translib/common_app.go index 6a73768901..94166ed1be 100644 --- a/src/translib/common_app.go +++ b/src/translib/common_app.go @@ -194,7 +194,7 @@ func (app *CommonApp) translateCRUCommon(d *db.DB, opcode int) ([]db.WatchKeys, log.Info("translateCRUCommon:path =", app.pathInfo.Path) // translate yang to db - result, err := transformer.XlateToDb(app.pathInfo.Path, (*app).ygotRoot, (*app).ygotTarget) + result, err := transformer.XlateToDb(app.pathInfo.Path, opcode, (*app).ygotRoot, (*app).ygotTarget) fmt.Println(result) log.Info("transformer.XlateToDb() returned", result) diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index 4131cefa06..2b7649c7a6 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -15,6 +15,14 @@ import ( log "github.com/golang/glog" ) +const ( + GET = 1 + iota + CREATE + REPLACE + UPDATE + DELETE +) + type KeySpec struct { Ts db.TableSpec Key db.Key @@ -189,7 +197,7 @@ func fillKeySpec(yangXpath string , keyStr string, dbFormat *KeySpec) { } } -func XlateToDb(path string, yg *ygot.GoStruct, yt *interface{}) (map[string]map[string]db.Value, error) { +func XlateToDb(path string, opcode int, yg *ygot.GoStruct, yt *interface{}) (map[string]map[string]db.Value, error) { var err error @@ -212,14 +220,24 @@ func XlateToDb(path string, yg *ygot.GoStruct, yt *interface{}) (map[string]map[ // table.key.fields var result = make(map[string]map[string]db.Value) - err = dbMapCreate(path, jsonData, result) + switch opcode { + case CREATE: + log.Info("CREATE case") + err = dbMapCreate(path, jsonData, result) + if err != nil { + log.Errorf("Error: Data translation from yang to db failed.") + } - if err != nil { - log.Errorf("Error: Data translation from yang to db failed.") - return result, err - } + case UPDATE: + log.Info("UPDATE case") - return result, err + case REPLACE: + log.Info("REPLACE case") + + case DELETE: + log.Info("DELETE case") + } + return result, err } func XlateFromDb(data map[string]map[string]db.Value) ([]byte, error) { From 857276044ea4319c48f62ad015a66cee3348d707 Mon Sep 17 00:00:00 2001 From: amrutasali Date: Fri, 16 Aug 2019 01:26:41 +0000 Subject: [PATCH 043/214] Removed accidently added src/cvl/schema/allyangs_tree.html --- src/cvl/schema/allyangs_tree.html | 3763 ----------------------------- 1 file changed, 3763 deletions(-) delete mode 100644 src/cvl/schema/allyangs_tree.html diff --git a/src/cvl/schema/allyangs_tree.html b/src/cvl/schema/allyangs_tree.html deleted file mode 100644 index 66547fabfe..0000000000 --- a/src/cvl/schema/allyangs_tree.html +++ /dev/null @@ -1,3763 +0,0 @@ - sonic-acl-dev sonic-acl sonic-bgp-neighbor sonic-buffer-pg sonic-buffer-pool sonic-buffer-profile sonic-cablelength sonic-common sonic-device-metadata sonic-device-neighbor sonic-dscp-tc-map sonic-interface sonic-mirror-session sonic-pfc-priority-queue-map sonic-pf-limits sonic-portchannel-interface sonic-portchannel sonic-port-qos-map sonic-port sonic-queue sonic-scheduler sonic-tc-priority-group-map sonic-tc-queue-map sonic-vlan-dev sonic-vlan-interface sonic-vlan sonic-wred-profile - - - - - - - - - -
-
-

Module: sonic-acl-dev, Namespace: - http://github.com/Azure/sonic-acl-dev, Prefix: - acld

-

Module: sonic-acl, Namespace: - http://github.com/Azure/sonic-acl, Prefix: - sacl

-

Module: sonic-bgp-neighbor, Namespace: - http://github.com/Azure/sonic-bgp-neighbor, Prefix: - sbn

-

Module: sonic-buffer-pg, Namespace: - http://github.com/Azure/sonic-buffer-pg, Prefix: - bpg

-

Module: sonic-buffer-pool, Namespace: - http://github.com/Azure/sonic-buffer-pool, Prefix: - bpl

-

Module: sonic-buffer-profile, Namespace: - http://github.com/Azure/sonic-buffer-profile, Prefix: - bpf

-

Module: sonic-cablelength, Namespace: - http://github.com/Azure/sonic-cablelength, Prefix: - scl

-

Module: sonic-common, Namespace: - http://github.com/Azure/sonic-common, Prefix: - sv

-

Module: sonic-device-metadata, Namespace: - http://github.com/Azure/sonic-device-metadata, Prefix: - sdm

-

Module: sonic-device-neighbor, Namespace: - http://github.com/Azure/sonic-device-neighbor, Prefix: - sdn

-

Module: sonic-dscp-tc-map, Namespace: - http://github.com/Azure/sonic-dscp-tc-map, Prefix: - dtm

-

Module: sonic-interface, Namespace: - http://github.com/Azure/sonic-interface, Prefix: - sint

-

Module: sonic-mirror-session, Namespace: - http://github.com/Azure/sonic-mirror-session, Prefix: - sms

-

Module: sonic-pfc-priority-queue-map, Namespace: - http://github.com/Azure/sonic-pfc-priority-queue-map, Prefix: - ppq

-

Module: sonic-pf-limits, Namespace: - http://github.com/Azure/sonic-pf-limits, Prefix: - spf

-

Module: sonic-portchannel-interface, Namespace: - http://github.com/Azure/sonic-portchannel-interface, Prefix: - spchint

-

Module: sonic-portchannel, Namespace: - http://github.com/Azure/sonic-portchannel, Prefix: - spc

-

Module: sonic-port-qos-map, Namespace: - http://github.com/Azure/sonic-port-qos-map, Prefix: - pqm

-

Module: sonic-port, Namespace: - http://github.com/Azure/sonic-port, Prefix: - prt

-

Module: sonic-queue, Namespace: - http://github.com/Azure/sonic-queue, Prefix: - squeue

-

Module: sonic-scheduler, Namespace: - http://github.com/Azure/sonic-scheduler, Prefix: - sch

-

Module: sonic-tc-priority-group-map, Namespace: - http://github.com/Azure/sonic-tc-priority-group-map, Prefix: - tpg

-

Module: sonic-tc-queue-map, Namespace: - http://github.com/Azure/sonic-tc-queue-map, Prefix: - tqm

-

Module: sonic-vlan-dev, Namespace: - http://github.com/Azure/sonic-vlan-dev, Prefix: - svd

-

Module: sonic-vlan-interface, Namespace: - http://github.com/Azure/sonic-vlan-interface, Prefix: - svint

-

Module: sonic-vlan, Namespace: - http://github.com/Azure/sonic-vlan, Prefix: - svlan

-

Module: sonic-wred-profile, Namespace: - http://github.com/Azure/sonic-wred-profile, Prefix: - wrd

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Element - [+]Expand all - [-]Collapse all - SchemaTypeFlagsOptsStatusPath
-
-   - - sonic-acl -
-
module -
-
-   - - sonic-acl -
-
containerconfigcurrent/sacl:sonic-acl
-
-   - - ACL_TABLE[aclname] -
-
listconfigcurrent/sacl:sonic-acl/sacl:ACL_TABLE
-
-   - aclname -
-
leafstringconfigcurrent/sacl:sonic-acl/sacl:ACL_TABLE/sacl:aclname -
-
-   - policy_desc -
-
leafstringconfig?current/sacl:sonic-acl/sacl:ACL_TABLE/sacl:policy_desc -
-
-   - stage -
-
leafenumerationconfig?current/sacl:sonic-acl/sacl:ACL_TABLE/sacl:stage -
-
-   - type -
-
leafenumerationconfig?current/sacl:sonic-acl/sacl:ACL_TABLE/sacl:type -
-
-   - ports -
-
leaf-listleafrefconfig*current/sacl:sonic-acl/sacl:ACL_TABLE/sacl:ports -
-
-   - - ACL_RULE[aclname rulename] -
-
listconfigcurrent/sacl:sonic-acl/sacl:ACL_RULE
-
-   - aclname -
-
leafleafrefconfigcurrent/sacl:sonic-acl/sacl:ACL_RULE/sacl:aclname -
-
-   - rulename -
-
leafstringconfigcurrent/sacl:sonic-acl/sacl:ACL_RULE/sacl:rulename -
-
-   - PRIORITY -
-
leafuint16config?current/sacl:sonic-acl/sacl:ACL_RULE/sacl:PRIORITY -
-
-   - RULE_DESCRIPTION -
-
leafstringconfig?current/sacl:sonic-acl/sacl:ACL_RULE/sacl:RULE_DESCRIPTION -
-
-   - PACKET_ACTION -
-
leafenumerationconfig?current/sacl:sonic-acl/sacl:ACL_RULE/sacl:PACKET_ACTION -
-
-   - MIRROR_ACTION -
-
leafleafrefconfig?current/sacl:sonic-acl/sacl:ACL_RULE/sacl:MIRROR_ACTION -
-
-   - IP_TYPE -
-
leafenumerationconfig?current/sacl:sonic-acl/sacl:ACL_RULE/sacl:IP_TYPE -
-
-   - IP_PROTOCOL -
-
leafuint8config?current/sacl:sonic-acl/sacl:ACL_RULE/sacl:IP_PROTOCOL -
-
-   - ETHER_TYPE -
-
leafstringconfig?current/sacl:sonic-acl/sacl:ACL_RULE/sacl:ETHER_TYPE -
-
-   - - (ip_src_dst) -
-
choiceconfigChoicecurrent/sacl:sonic-acl/sacl:ACL_RULE
-
-   - - :(ipv4_src_dst) -
-
caseconfigcurrent/sacl:sonic-acl/sacl:ACL_RULE
-
-   - SRC_IP -
-
leafinet:ipv4-prefixconfigcurrent/sacl:sonic-acl/sacl:ACL_RULE/sacl:SRC_IP -
-
-   - DST_IP -
-
leafinet:ipv4-prefixconfigcurrent/sacl:sonic-acl/sacl:ACL_RULE/sacl:DST_IP -
-
-   - - :(ipv6_src_dst) -
-
caseconfigcurrent/sacl:sonic-acl/sacl:ACL_RULE
-
-   - SRC_IPV6 -
-
leafinet:ipv6-prefixconfigcurrent/sacl:sonic-acl/sacl:ACL_RULE/sacl:SRC_IPV6 -
-
-   - DST_IPV6 -
-
leafinet:ipv6-prefixconfigcurrent/sacl:sonic-acl/sacl:ACL_RULE/sacl:DST_IPV6 -
-
-   - - (src_port) -
-
choiceconfigChoicecurrent/sacl:sonic-acl/sacl:ACL_RULE
-
-   - - :(l4_src_port) -
-
caseconfigcurrent/sacl:sonic-acl/sacl:ACL_RULE
-
-   - L4_SRC_PORT -
-
leafuint16config?current/sacl:sonic-acl/sacl:ACL_RULE/sacl:L4_SRC_PORT -
-
-   - - :(l4_src_port_range) -
-
caseconfigcurrent/sacl:sonic-acl/sacl:ACL_RULE
-
-   - L4_SRC_PORT_RANGE -
-
leafstringconfig?current/sacl:sonic-acl/sacl:ACL_RULE/sacl:L4_SRC_PORT_RANGE -
-
-   - - (dst_port) -
-
choiceconfigChoicecurrent/sacl:sonic-acl/sacl:ACL_RULE
-
-   - - :(l4_dst_port) -
-
caseconfigcurrent/sacl:sonic-acl/sacl:ACL_RULE
-
-   - L4_DST_PORT -
-
leafuint16config?current/sacl:sonic-acl/sacl:ACL_RULE/sacl:L4_DST_PORT -
-
-   - - :(l4_dst_port_range) -
-
caseconfigcurrent/sacl:sonic-acl/sacl:ACL_RULE
-
-   - L4_DST_PORT_RANGE -
-
leafstringconfig?current/sacl:sonic-acl/sacl:ACL_RULE/sacl:L4_DST_PORT_RANGE -
-
-   - TCP_FLAGS -
-
leafstringconfig?current/sacl:sonic-acl/sacl:ACL_RULE/sacl:TCP_FLAGS -
-
-   - DSCP -
-
leafuint8config?current/sacl:sonic-acl/sacl:ACL_RULE/sacl:DSCP -
-
-   - - sonic-bgp-neighbor -
-
module -
-
-   - - sonic-bgp-neighbor -
-
containerconfigcurrent/sbn:sonic-bgp-neighbor
-
-   - - BGP_NEIGHBOR[ipaddress] -
-
listconfigcurrent/sbn:sonic-bgp-neighbor/sbn:BGP_NEIGHBOR
-
-   - ipaddress -
-
leafinet:ip-addressconfigcurrent/sbn:sonic-bgp-neighbor/sbn:BGP_NEIGHBOR/sbn:ipaddress -
-
-   - rrclient -
-
leafuint8config?current/sbn:sonic-bgp-neighbor/sbn:BGP_NEIGHBOR/sbn:rrclient -
-
-   - admin_status -
-
leafscommon:admin-statusconfig?current/sbn:sonic-bgp-neighbor/sbn:BGP_NEIGHBOR/sbn:admin_status -
-
-   - peer_addr -
-
leafinet:ip-addressconfig?current/sbn:sonic-bgp-neighbor/sbn:BGP_NEIGHBOR/sbn:peer_addr -
-
-   - name -
-
leafstringconfig?current/sbn:sonic-bgp-neighbor/sbn:BGP_NEIGHBOR/sbn:name -
-
-   - local_addr -
-
leafinet:ipv4-addressconfig?current/sbn:sonic-bgp-neighbor/sbn:BGP_NEIGHBOR/sbn:local_addr -
-
-   - nhopself -
-
leafuint8config?current/sbn:sonic-bgp-neighbor/sbn:BGP_NEIGHBOR/sbn:nhopself -
-
-   - holdtime -
-
leafuint8config?current/sbn:sonic-bgp-neighbor/sbn:BGP_NEIGHBOR/sbn:holdtime -
-
-   - asn -
-
leafuint64config?current/sbn:sonic-bgp-neighbor/sbn:BGP_NEIGHBOR/sbn:asn -
-
-   - keepalive -
-
leafuint8config?current/sbn:sonic-bgp-neighbor/sbn:BGP_NEIGHBOR/sbn:keepalive -
-
-   - - sonic-buffer-pg -
-
module -
-
-   - - sonic-buffer-pg -
-
containerconfigcurrent/bpg:sonic-buffer-pg
-
-   - - BUFFER_PG[ifname pg_num] -
-
listconfigcurrent/bpg:sonic-buffer-pg/bpg:BUFFER_PG
-
-   - ifname -
-
leafleafrefconfigcurrent/bpg:sonic-buffer-pg/bpg:BUFFER_PG/bpg:ifname -
-
-   - pg_num -
-
leafstringconfigcurrent/bpg:sonic-buffer-pg/bpg:BUFFER_PG/bpg:pg_num -
-
-   - profile -
-
leafleafrefconfig?current/bpg:sonic-buffer-pg/bpg:BUFFER_PG/bpg:profile -
-
-   - - sonic-buffer-pool -
-
module -
-
-   - - sonic-buffer-pool -
-
containerconfigcurrent/bpl:sonic-buffer-pool
-
-   - - BUFFER_POOL[name] -
-
listconfigcurrent/bpl:sonic-buffer-pool/bpl:BUFFER_POOL
-
-   - name -
-
leafstringconfigcurrent/bpl:sonic-buffer-pool/bpl:BUFFER_POOL/bpl:name -
-
-   - type -
-
leafenumerationconfig?current/bpl:sonic-buffer-pool/bpl:BUFFER_POOL/bpl:type -
-
-   - mode -
-
leafenumerationconfig?current/bpl:sonic-buffer-pool/bpl:BUFFER_POOL/bpl:mode -
-
-   - size -
-
leafuint64config?current/bpl:sonic-buffer-pool/bpl:BUFFER_POOL/bpl:size -
-
-   - - sonic-buffer-profile -
-
module -
-
-   - - sonic-buffer-profile -
-
containerconfigcurrent/bpf:sonic-buffer-profile
-
-   - - BUFFER_PROFILE[name] -
-
listconfigcurrent/bpf:sonic-buffer-profile/bpf:BUFFER_PROFILE
-
-   - name -
-
leafstringconfigcurrent/bpf:sonic-buffer-profile/bpf:BUFFER_PROFILE/bpf:name -
-
-   - static_th -
-
leafuint64config?current/bpf:sonic-buffer-profile/bpf:BUFFER_PROFILE/bpf:static_th -
-
-   - dynamic_th -
-
leafint64config?current/bpf:sonic-buffer-profile/bpf:BUFFER_PROFILE/bpf:dynamic_th -
-
-   - size -
-
leafuint64config?current/bpf:sonic-buffer-profile/bpf:BUFFER_PROFILE/bpf:size -
-
-   - pool -
-
leafleafrefconfig?current/bpf:sonic-buffer-profile/bpf:BUFFER_PROFILE/bpf:pool -
-
-   - xon_offset -
-
leafuint64config?current/bpf:sonic-buffer-profile/bpf:BUFFER_PROFILE/bpf:xon_offset -
-
-   - xon -
-
leafuint64config?current/bpf:sonic-buffer-profile/bpf:BUFFER_PROFILE/bpf:xon -
-
-   - xoff -
-
leafuint64config?current/bpf:sonic-buffer-profile/bpf:BUFFER_PROFILE/bpf:xoff -
-
-   - - sonic-cablelength -
-
module -
-
-   - - sonic-cablelength -
-
containerconfigcurrent/scl:sonic-cablelength
-
-   - - CABLE_LENGTH[name] -
-
listconfigcurrent/scl:sonic-cablelength/scl:CABLE_LENGTH
-
-   - name -
-
leafstringconfigcurrent/scl:sonic-cablelength/scl:CABLE_LENGTH/scl:name -
-
-   - - CABLE_LENGTH[port length] -
-
listconfigcurrent/scl:sonic-cablelength/scl:CABLE_LENGTH/scl:CABLE_LENGTH
-
-   - port -
-
leafleafrefconfigcurrent/scl:sonic-cablelength/scl:CABLE_LENGTH/scl:CABLE_LENGTH/scl:port -
-
-   - length -
-
leafstringconfigcurrent/scl:sonic-cablelength/scl:CABLE_LENGTH/scl:CABLE_LENGTH/scl:length -
-
-   - - sonic-common -
-
module -
-
-   - - operation -
-
containerconfigcurrent/sv:operation
-
-   - operation -
-
leafstringconfig?current/sv:operation/sv:operation -
-
-   - - sonic-device-metadata -
-
module -
-
-   - - sonic-device-metadata -
-
containerconfigcurrent/sdm:sonic-device-metadata
-
-   - - DEVICE_METADATA[name] -
-
listconfigcurrent/sdm:sonic-device-metadata/sdm:DEVICE_METADATA
-
-   - name -
-
leafstringconfigcurrent/sdm:sonic-device-metadata/sdm:DEVICE_METADATA/sdm:name -
-
-   - hwsku -
-
leafstringconfig?current/sdm:sonic-device-metadata/sdm:DEVICE_METADATA/sdm:hwsku -
-
-   - hostname -
-
leafstringconfig?current/sdm:sonic-device-metadata/sdm:DEVICE_METADATA/sdm:hostname -
-
-   - platform -
-
leafstringconfig?current/sdm:sonic-device-metadata/sdm:DEVICE_METADATA/sdm:platform -
-
-   - mac -
-
leafyang:mac-addressconfig?current/sdm:sonic-device-metadata/sdm:DEVICE_METADATA/sdm:mac -
-
-   - bgp_asn -
-
leafleafrefconfig?current/sdm:sonic-device-metadata/sdm:DEVICE_METADATA/sdm:bgp_asn -
-
-   - default_pfcwd_status -
-
leafenumerationconfig?current/sdm:sonic-device-metadata/sdm:DEVICE_METADATA/sdm:default_pfcwd_status -
-
-   - default_bgp_status -
-
leafscommon:admin-statusconfig?current/sdm:sonic-device-metadata/sdm:DEVICE_METADATA/sdm:default_bgp_status -
-
-   - docker_routing_config_mode -
-
leafenumerationconfig?current/sdm:sonic-device-metadata/sdm:DEVICE_METADATA/sdm:docker_routing_config_mode -
-
-   - deployment_id -
-
leafuint8config?current/sdm:sonic-device-metadata/sdm:DEVICE_METADATA/sdm:deployment_id -
-
-   - type -
-
leafenumerationconfig?current/sdm:sonic-device-metadata/sdm:DEVICE_METADATA/sdm:type -
-
-   - - sonic-device-neighbor -
-
module -
-
-   - - sonic-device-neighbor -
-
containerconfigcurrent/sdn:sonic-device-neighbor
-
-   - - DEVICE_NEIGHBOR[name] -
-
listconfigcurrent/sdn:sonic-device-neighbor/sdn:DEVICE_NEIGHBOR
-
-   - name -
-
leafstringconfigcurrent/sdn:sonic-device-neighbor/sdn:DEVICE_NEIGHBOR/sdn:name -
-
-   - mgmt_addr -
-
leafinet:ip-addressconfig?current/sdn:sonic-device-neighbor/sdn:DEVICE_NEIGHBOR/sdn:mgmt_addr -
-
-   - hwsku -
-
leafstringconfig?current/sdn:sonic-device-neighbor/sdn:DEVICE_NEIGHBOR/sdn:hwsku -
-
-   - lo_addr -
-
leafinet:ip-addressconfig?current/sdn:sonic-device-neighbor/sdn:DEVICE_NEIGHBOR/sdn:lo_addr -
-
-   - local_port -
-
leafleafrefconfig?current/sdn:sonic-device-neighbor/sdn:DEVICE_NEIGHBOR/sdn:local_port -
-
-   - type -
-
leafenumerationconfig?current/sdn:sonic-device-neighbor/sdn:DEVICE_NEIGHBOR/sdn:type -
-
-   - port -
-
leafleafrefconfig?current/sdn:sonic-device-neighbor/sdn:DEVICE_NEIGHBOR/sdn:port -
-
-   - - sonic-dscp-tc-map -
-
module -
-
-   - - sonic-dscp-tc-map -
-
containerconfigcurrent/dtm:sonic-dscp-tc-map
-
-   - - DSCP_TO_TC_MAP[name] -
-
listconfigcurrent/dtm:sonic-dscp-tc-map/dtm:DSCP_TO_TC_MAP
-
-   - name -
-
leafstringconfigcurrent/dtm:sonic-dscp-tc-map/dtm:DSCP_TO_TC_MAP/dtm:name -
-
-   - - DSCP_TO_TC_MAP[dscp tc_num] -
-
listconfigcurrent/dtm:sonic-dscp-tc-map/dtm:DSCP_TO_TC_MAP/dtm:DSCP_TO_TC_MAP
-
-   - tc_num -
-
leafstringconfigcurrent/dtm:sonic-dscp-tc-map/dtm:DSCP_TO_TC_MAP/dtm:DSCP_TO_TC_MAP/dtm:tc_num -
-
-   - dscp -
-
leafstringconfigcurrent/dtm:sonic-dscp-tc-map/dtm:DSCP_TO_TC_MAP/dtm:DSCP_TO_TC_MAP/dtm:dscp -
-
-   - - sonic-interface -
-
module -
-
-   - - sonic-interface -
-
containerconfigcurrent/sint:sonic-interface
-
-   - - INTERFACE[portname ip_prefix] -
-
listconfigcurrent/sint:sonic-interface/sint:INTERFACE
-
-   - portname -
-
leafleafrefconfigcurrent/sint:sonic-interface/sint:INTERFACE/sint:portname -
-
-   - ip_prefix -
-
leafinet:ip-prefixconfigcurrent/sint:sonic-interface/sint:INTERFACE/sint:ip_prefix -
-
-   - - sonic-mirror-session -
-
module -
-
-   - - sonic-mirror-session -
-
containerconfigcurrent/sms:sonic-mirror-session
-
-   - - MIRROR_SESSION[name] -
-
listconfigcurrent/sms:sonic-mirror-session/sms:MIRROR_SESSION
-
-   - name -
-
leafstringconfigcurrent/sms:sonic-mirror-session/sms:MIRROR_SESSION/sms:name -
-
-   - src_ip -
-
leafinet:ipv4-addressconfig?current/sms:sonic-mirror-session/sms:MIRROR_SESSION/sms:src_ip -
-
-   - dst_ip -
-
leafinet:ipv4-addressconfig?current/sms:sonic-mirror-session/sms:MIRROR_SESSION/sms:dst_ip -
-
-   - gre_type -
-
leafstringconfig?current/sms:sonic-mirror-session/sms:MIRROR_SESSION/sms:gre_type -
-
-   - dscp -
-
leafuint8config?current/sms:sonic-mirror-session/sms:MIRROR_SESSION/sms:dscp -
-
-   - ttl -
-
leafuint8config?current/sms:sonic-mirror-session/sms:MIRROR_SESSION/sms:ttl -
-
-   - queue -
-
leafuint8config?current/sms:sonic-mirror-session/sms:MIRROR_SESSION/sms:queue -
-
-   - - sonic-pfc-priority-queue-map -
-
module -
-
-   - - sonic-pfc-priority-queue-map -
-
containerconfigcurrent/ppq:sonic-pfc-priority-queue-map
-
-   - - MAP_PFC_PRIORITY_TO_QUEUE[name] -
-
listconfigcurrent/ppq:sonic-pfc-priority-queue-map/ppq:MAP_PFC_PRIORITY_TO_QUEUE
-
-   - name -
-
leafstringconfigcurrent/ppq:sonic-pfc-priority-queue-map/ppq:MAP_PFC_PRIORITY_TO_QUEUE/ppq:name -
-
-   - - MAP_PFC_PRIORITY_TO_QUEUE[pfc_priority qindex] -
-
listconfigcurrent/ppq:sonic-pfc-priority-queue-map/ppq:MAP_PFC_PRIORITY_TO_QUEUE/ppq:MAP_PFC_PRIORITY_TO_QUEUE
-
-   - pfc_priority -
-
leafstringconfigcurrent/ppq:sonic-pfc-priority-queue-map/ppq:MAP_PFC_PRIORITY_TO_QUEUE/ppq:MAP_PFC_PRIORITY_TO_QUEUE/ppq:pfc_priority -
-
-   - qindex -
-
leafstringconfigcurrent/ppq:sonic-pfc-priority-queue-map/ppq:MAP_PFC_PRIORITY_TO_QUEUE/ppq:MAP_PFC_PRIORITY_TO_QUEUE/ppq:qindex -
-
-   - - sonic-pf-limits -
-
module -
-
-   - - sonic-pf-limits -
-
containerconfigcurrent/spf:sonic-pf-limits
-
-   - - acl -
-
containerconfigcurrent/spf:sonic-pf-limits/spf:acl
-
-   - MAX_ACL_RULES -
-
leafuint16config?current/spf:sonic-pf-limits/spf:acl/spf:MAX_ACL_RULES -
-
-   - MAX_PRIORITY -
-
leafuint16config?current/spf:sonic-pf-limits/spf:acl/spf:MAX_PRIORITY -
-
-   - - vlan -
-
containerconfigcurrent/spf:sonic-pf-limits/spf:vlan
-
-   - MAX_VLANS -
-
leafuint16config?current/spf:sonic-pf-limits/spf:vlan/spf:MAX_VLANS -
-
-   - - sonic-portchannel-interface -
-
module -
-
-   - - sonic-portchannel-interface -
-
containerconfigcurrent/spchint:sonic-portchannel-interface
-
-   - - PORTCHANNEL_INTERFACE[pch_name ip_prefix] -
-
listconfigcurrent/spchint:sonic-portchannel-interface/spchint:PORTCHANNEL_INTERFACE
-
-   - pch_name -
-
leafleafrefconfigcurrent/spchint:sonic-portchannel-interface/spchint:PORTCHANNEL_INTERFACE/spchint:pch_name -
-
-   - ip_prefix -
-
leafinet:ip-prefixconfigcurrent/spchint:sonic-portchannel-interface/spchint:PORTCHANNEL_INTERFACE/spchint:ip_prefix -
-
-   - - sonic-portchannel -
-
module -
-
-   - - sonic-portchannel -
-
containerconfigcurrent/spc:sonic-portchannel
-
-   - - PORTCHANNEL[name] -
-
listconfigcurrent/spc:sonic-portchannel/spc:PORTCHANNEL
-
-   - name -
-
leafstringconfigcurrent/spc:sonic-portchannel/spc:PORTCHANNEL/spc:name -
-
-   - admin_status -
-
leafscommon:admin-statusconfig?current/spc:sonic-portchannel/spc:PORTCHANNEL/spc:admin_status -
-
-   - mtu -
-
leafuint16config?current/spc:sonic-portchannel/spc:PORTCHANNEL/spc:mtu -
-
-   - min_links -
-
leafuint8config?current/spc:sonic-portchannel/spc:PORTCHANNEL/spc:min_links -
-
-   - fallback -
-
leafbooleanconfig?current/spc:sonic-portchannel/spc:PORTCHANNEL/spc:fallback -
-
-   - - PORTCHANNEL_MEMBER[name ifname] -
-
listconfigcurrent/spc:sonic-portchannel/spc:PORTCHANNEL_MEMBER
-
-   - name -
-
leafleafrefconfigcurrent/spc:sonic-portchannel/spc:PORTCHANNEL_MEMBER/spc:name -
-
-   - ifname -
-
leafleafrefconfigcurrent/spc:sonic-portchannel/spc:PORTCHANNEL_MEMBER/spc:ifname -
-
-   - - sonic-port-qos-map -
-
module -
-
-   - - sonic-port-qos-map -
-
containerconfigcurrent/pqm:sonic-port-qos-map
-
-   - - PORT_QOS_MAP[ifname] -
-
listconfigcurrent/pqm:sonic-port-qos-map/pqm:PORT_QOS_MAP
-
-   - ifname -
-
leafleafrefconfigcurrent/pqm:sonic-port-qos-map/pqm:PORT_QOS_MAP/pqm:ifname -
-
-   - tc_to_pg_map -
-
leafleafrefconfig?current/pqm:sonic-port-qos-map/pqm:PORT_QOS_MAP/pqm:tc_to_pg_map -
-
-   - tc_to_queue_map -
-
leafleafrefconfig?current/pqm:sonic-port-qos-map/pqm:PORT_QOS_MAP/pqm:tc_to_queue_map -
-
-   - pfc-enable -
-
leafstringconfig?current/pqm:sonic-port-qos-map/pqm:PORT_QOS_MAP/pqm:pfc-enable -
-
-   - pfc_to_queue_map -
-
leafleafrefconfig?current/pqm:sonic-port-qos-map/pqm:PORT_QOS_MAP/pqm:pfc_to_queue_map -
-
-   - dscp_to_tc_map -
-
leafleafrefconfig?current/pqm:sonic-port-qos-map/pqm:PORT_QOS_MAP/pqm:dscp_to_tc_map -
-
-   - - sonic-port -
-
module -
-
-   - - sonic-port -
-
containerconfigcurrent/prt:sonic-port
-
-   - - PORT[ifname] -
-
listconfigcurrent/prt:sonic-port/prt:PORT
-
-   - ifname -
-
leafstringconfigcurrent/prt:sonic-port/prt:PORT/prt:ifname -
-
-   - index -
-
leafuint16config?current/prt:sonic-port/prt:PORT/prt:index -
-
-   - speed -
-
leafuint64config?current/prt:sonic-port/prt:PORT/prt:speed -
-
-   - valid_speeds -
-
leafstringconfig?current/prt:sonic-port/prt:PORT/prt:valid_speeds -
-
-   - alias -
-
leafstringconfig?current/prt:sonic-port/prt:PORT/prt:alias -
-
-   - description -
-
leafstringconfig?current/prt:sonic-port/prt:PORT/prt:description -
-
-   - mtu -
-
leafuint32config?current/prt:sonic-port/prt:PORT/prt:mtu -
-
-   - lanes -
-
leafstringconfig?current/prt:sonic-port/prt:PORT/prt:lanes -
-
-   - admin_status -
-
leafscommon:admin-statusconfig?current/prt:sonic-port/prt:PORT/prt:admin_status -
-
-   - - sonic-queue -
-
module -
-
-   - - sonic-queue -
-
containerconfigcurrent/squeue:sonic-queue
-
-   - - QUEUE[ifname qindex] -
-
listconfigcurrent/squeue:sonic-queue/squeue:QUEUE
-
-   - ifname -
-
leafleafrefconfigcurrent/squeue:sonic-queue/squeue:QUEUE/squeue:ifname -
-
-   - qindex -
-
leafstringconfigcurrent/squeue:sonic-queue/squeue:QUEUE/squeue:qindex -
-
-   - scheduler -
-
leafleafrefconfig?current/squeue:sonic-queue/squeue:QUEUE/squeue:scheduler -
-
-   - wred_profile -
-
leafleafrefconfig?current/squeue:sonic-queue/squeue:QUEUE/squeue:wred_profile -
-
-   - - sonic-scheduler -
-
module -
-
-   - - sonic-scheduler -
-
containerconfigcurrent/sch:sonic-scheduler
-
-   - - SCHEDULER[name] -
-
listconfigcurrent/sch:sonic-scheduler/sch:SCHEDULER
-
-   - name -
-
leafstringconfigcurrent/sch:sonic-scheduler/sch:SCHEDULER/sch:name -
-
-   - type -
-
leafenumerationconfig?current/sch:sonic-scheduler/sch:SCHEDULER/sch:type -
-
-   - weight -
-
leafuint8config?current/sch:sonic-scheduler/sch:SCHEDULER/sch:weight -
-
-   - priority -
-
leafuint8config?current/sch:sonic-scheduler/sch:SCHEDULER/sch:priority -
-
-   - - sonic-tc-priority-group-map -
-
module -
-
-   - - sonic-tc-priority-group-map -
-
containerconfigcurrent/tpg:sonic-tc-priority-group-map
-
-   - - TC_TO_PRIORITY_GROUP_MAP[name] -
-
listconfigcurrent/tpg:sonic-tc-priority-group-map/tpg:TC_TO_PRIORITY_GROUP_MAP
-
-   - name -
-
leafstringconfigcurrent/tpg:sonic-tc-priority-group-map/tpg:TC_TO_PRIORITY_GROUP_MAP/tpg:name -
-
-   - - TC_TO_PRIORITY_GROUP_MAP[tc_num pg_num] -
-
listconfigcurrent/tpg:sonic-tc-priority-group-map/tpg:TC_TO_PRIORITY_GROUP_MAP/tpg:TC_TO_PRIORITY_GROUP_MAP
-
-   - tc_num -
-
leafstringconfigcurrent/tpg:sonic-tc-priority-group-map/tpg:TC_TO_PRIORITY_GROUP_MAP/tpg:TC_TO_PRIORITY_GROUP_MAP/tpg:tc_num -
-
-   - pg_num -
-
leafstringconfigcurrent/tpg:sonic-tc-priority-group-map/tpg:TC_TO_PRIORITY_GROUP_MAP/tpg:TC_TO_PRIORITY_GROUP_MAP/tpg:pg_num -
-
-   - - sonic-tc-queue-map -
-
module -
-
-   - - sonic-tc-queue-map -
-
containerconfigcurrent/tqm:sonic-tc-queue-map
-
-   - - TC_TO_QUEUE_MAP[name] -
-
listconfigcurrent/tqm:sonic-tc-queue-map/tqm:TC_TO_QUEUE_MAP
-
-   - name -
-
leafstringconfigcurrent/tqm:sonic-tc-queue-map/tqm:TC_TO_QUEUE_MAP/tqm:name -
-
-   - - TC_TO_QUEUE_MAP[tc_num qindex] -
-
listconfigcurrent/tqm:sonic-tc-queue-map/tqm:TC_TO_QUEUE_MAP/tqm:TC_TO_QUEUE_MAP
-
-   - tc_num -
-
leafstringconfigcurrent/tqm:sonic-tc-queue-map/tqm:TC_TO_QUEUE_MAP/tqm:TC_TO_QUEUE_MAP/tqm:tc_num -
-
-   - qindex -
-
leafstringconfigcurrent/tqm:sonic-tc-queue-map/tqm:TC_TO_QUEUE_MAP/tqm:TC_TO_QUEUE_MAP/tqm:qindex -
-
-   - - sonic-vlan-interface -
-
module -
-
-   - - sonic-vlan-interface -
-
containerconfigcurrent/svint:sonic-vlan-interface
-
-   - - VLAN_INTERFACE[portname ip_prefix] -
-
listconfigcurrent/svint:sonic-vlan-interface/svint:VLAN_INTERFACE
-
-   - portname -
-
leafleafrefconfigcurrent/svint:sonic-vlan-interface/svint:VLAN_INTERFACE/svint:portname -
-
-   - ip_prefix -
-
leafinet:ip-prefixconfigcurrent/svint:sonic-vlan-interface/svint:VLAN_INTERFACE/svint:ip_prefix -
-
-   - - sonic-vlan -
-
module -
-
-   - - sonic-vlan -
-
containerconfigcurrent/svlan:sonic-vlan
-
-   - - VLAN[name] -
-
listconfigcurrent/svlan:sonic-vlan/svlan:VLAN
-
-   - name -
-
leafstringconfigcurrent/svlan:sonic-vlan/svlan:VLAN/svlan:name -
-
-   - vlanid -
-
leafuint16configcurrent/svlan:sonic-vlan/svlan:VLAN/svlan:vlanid -
-
-   - members -
-
leaf-listleafrefconfig*current/svlan:sonic-vlan/svlan:VLAN/svlan:members -
-
-   - - VLAN_MEMBER[name ifname] -
-
listconfigcurrent/svlan:sonic-vlan/svlan:VLAN_MEMBER
-
-   - name -
-
leafleafrefconfigcurrent/svlan:sonic-vlan/svlan:VLAN_MEMBER/svlan:name -
-
-   - ifname -
-
leafleafrefconfigcurrent/svlan:sonic-vlan/svlan:VLAN_MEMBER/svlan:ifname -
-
-   - tagging_mode -
-
leafscommon:tagging_modeconfig?current/svlan:sonic-vlan/svlan:VLAN_MEMBER/svlan:tagging_mode -
-
-   - - sonic-wred-profile -
-
module -
-
-   - - sonic-wred-profile -
-
containerconfigcurrent/wrd:sonic-wred-profile
-
-   - - WRED_PROFILE[name] -
-
listconfigcurrent/wrd:sonic-wred-profile/wrd:WRED_PROFILE
-
-   - name -
-
leafstringconfigcurrent/wrd:sonic-wred-profile/wrd:WRED_PROFILE/wrd:name -
-
-   - yellow_min_threshold -
-
leafuint64config?current/wrd:sonic-wred-profile/wrd:WRED_PROFILE/wrd:yellow_min_threshold -
-
-   - green_min_threshold -
-
leafuint64config?current/wrd:sonic-wred-profile/wrd:WRED_PROFILE/wrd:green_min_threshold -
-
-   - red_min_threshold -
-
leafuint64config?current/wrd:sonic-wred-profile/wrd:WRED_PROFILE/wrd:red_min_threshold -
-
-   - yellow_max_threshold -
-
leafuint64config?current/wrd:sonic-wred-profile/wrd:WRED_PROFILE/wrd:yellow_max_threshold -
-
-   - green_max_threshold -
-
leafuint64config?current/wrd:sonic-wred-profile/wrd:WRED_PROFILE/wrd:green_max_threshold -
-
-   - red_max_threshold -
-
leafuint64config?current/wrd:sonic-wred-profile/wrd:WRED_PROFILE/wrd:red_max_threshold -
-
-   - ecn -
-
leafenumerationconfig?current/wrd:sonic-wred-profile/wrd:WRED_PROFILE/wrd:ecn -
-
-   - wred_green_enable -
-
leafbooleanconfig?current/wrd:sonic-wred-profile/wrd:WRED_PROFILE/wrd:wred_green_enable -
-
-   - wred_yellow_enable -
-
leafbooleanconfig?current/wrd:sonic-wred-profile/wrd:WRED_PROFILE/wrd:wred_yellow_enable -
-
-   - wred_red_enable -
-
leafbooleanconfig?current/wrd:sonic-wred-profile/wrd:WRED_PROFILE/wrd:wred_red_enable - -
-
- - - From 90425772202457025298d23b2fde00542712746e Mon Sep 17 00:00:00 2001 From: s-mari Date: Thu, 15 Aug 2019 21:44:20 -0700 Subject: [PATCH 044/214] enabled oc yang to db map create creat request --- src/translib/transformer/xlate_to_db.go | 17 ++++++++++++----- src/translib/transformer/xlate_utils.go | 6 +++++- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index fbc6c2d52a..27cdcf5434 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -38,6 +38,9 @@ func mapFillData(dbKey string, result map[string]map[string]db.Value, xpathPrefi return errors.New("Invalid field name") } fieldName := xpathInfo.fieldName + if strings.Contains(value, ":") { + value = strings.Split(value, ":")[1] + } if len(xpathInfo.xfmrFunc) > 0 { log.Info("Transformer function(\"%v\") invoked for yang path(\"%v\").", xpathInfo.xfmrFunc, xpath) @@ -153,8 +156,9 @@ func dbMapCreate(uri string, jsonData interface{}, result map[string]map[string] if isCvlYang(uri) { cvlYangReqToDbMapCreate(uri, jsonData, result) } else { - yangReqToDbMapCreate(uri, xpathTmplt, keyName, jsonData, result) + yangReqToDbMapCreate(uri, parentXpathGet(xpathTmplt), keyName, jsonData, result) } + printDbData(result, "/tmp/yangToDbData.txt") return nil } @@ -181,11 +185,14 @@ func yangReqToDbMapCreate(uri string, xpathPrefix string, keyName string, jsonDa if typeOfValue == reflect.Map || typeOfValue == reflect.Slice { log.Info("slice/map data: key(\"%v\"), xpathPrefix(\"%v\").", keyName, xpathPrefix) + xpath := uri pathAttr := key.String() - if strings.Contains(pathAttr, ":") { - pathAttr = strings.Split(pathAttr, ":")[1] + if len(xpathPrefix) > 0 { + if strings.Contains(pathAttr, ":") { + pathAttr = strings.Split(pathAttr, ":")[1] + } + xpath = xpathPrefix + "/" + pathAttr } - xpath := xpathPrefix + "/" + pathAttr if xSpecMap[xpath] != nil && len(xSpecMap[xpath].xfmrFunc) > 0 { subMap := callXfmr() @@ -194,7 +201,7 @@ func yangReqToDbMapCreate(uri string, xpathPrefix string, keyName string, jsonDa mapCopy(result, subMap) return nil } else { - return yangReqToDbMapCreate(uri, xpath, keyName, jData.MapIndex(key).Interface(), result) + yangReqToDbMapCreate(uri, xpath, keyName, jData.MapIndex(key).Interface(), result) } } else { pathAttr := key.String() diff --git a/src/translib/transformer/xlate_utils.go b/src/translib/transformer/xlate_utils.go index a48c42537c..53af60e68b 100644 --- a/src/translib/transformer/xlate_utils.go +++ b/src/translib/transformer/xlate_utils.go @@ -31,7 +31,11 @@ func keyCreate(keyPrefix string, xpath string, data interface{}) string { keyVal := "" for i, k := range (strings.Split(yangEntry.Key, " ")) { if i > 0 { keyVal = keyVal + "_" } - keyVal += fmt.Sprintf("%v", data.(map[string]interface{})[k]) + val := fmt.Sprint(data.(map[string]interface{})[k]) + if strings.Contains(val, ":") { + val = strings.Split(val, ":")[1] + } + keyVal += val } keyPrefix += string(keyVal) return keyPrefix From 896bdc9b9cfd982b50672e061162f785f2a7eade Mon Sep 17 00:00:00 2001 From: s-mari Date: Fri, 16 Aug 2019 00:00:17 -0700 Subject: [PATCH 045/214] updated transformer function signature to include db, got and oper type. --- src/translib/transformer/xlate.go | 2 +- src/translib/transformer/xlate_to_db.go | 60 ++++++++++++++----------- 2 files changed, 35 insertions(+), 27 deletions(-) diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index 2b7649c7a6..9a0983e35b 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -223,7 +223,7 @@ func XlateToDb(path string, opcode int, yg *ygot.GoStruct, yt *interface{}) (map switch opcode { case CREATE: log.Info("CREATE case") - err = dbMapCreate(path, jsonData, result) + err = dbMapCreate(nil, yg, opcode, path, jsonData, result) if err != nil { log.Errorf("Error: Data translation from yang to db failed.") } diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index 27cdcf5434..7d649a70be 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -8,12 +8,29 @@ import ( "regexp" "strings" "errors" + "github.com/openconfig/ygot/ygot" log "github.com/golang/glog" ) +/* Fill redis-db map with field & value info */ +func dataToDBMapAdd(tableName string, dbKey string, result map[string]map[string]db.Value, field string, value string) { + _, ok := result[tableName] + if !ok { + result[tableName] = make(map[string]db.Value) + } + + _, ok = result[tableName][dbKey] + if !ok { + result[tableName][dbKey] = db.Value{Field: make(map[string]string)} + } + + result[tableName][dbKey].Field[field] = value + return +} + /* Fill the redis-db map with data */ -func mapFillData(dbKey string, result map[string]map[string]db.Value, xpathPrefix string, name string, value string) error { +func mapFillData(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, dbKey string, result map[string]map[string]db.Value, xpathPrefix string, name string, value string) error { xpath := xpathPrefix + "/" + name xpathInfo := xSpecMap[xpath] log.Info("name: \"%v\", xpathPrefix(\"%v\").", name, xpathPrefix) @@ -50,17 +67,7 @@ func mapFillData(dbKey string, result map[string]map[string]db.Value, xpathPrefi return nil } - _, ok := result[*xpathInfo.tableName] - if !ok { - result[*xpathInfo.tableName] = make(map[string]db.Value) - } - - _, ok = result[*xpathInfo.tableName][dbKey] - if !ok { - result[*xpathInfo.tableName][dbKey] = db.Value{Field: make(map[string]string)} - } - - result[*xpathInfo.tableName][dbKey].Field[fieldName] = value + dataToDBMapAdd(*xpathInfo.tableName, dbKey, result, fieldName, value) log.Info("TblName: \"%v\", key: \"%v\", field: \"%v\", value: \"%v\".", *xpathInfo.tableName, dbKey, fieldName, value) return nil @@ -78,7 +85,7 @@ func callXfmr() map[string]map[string]db.Value { return result } -func cvlYangReqToDbMapCreate(uri string, jsonData interface{}, result map[string]map[string]db.Value) error { +func cvlYangReqToDbMapCreate(jsonData interface{}, result map[string]map[string]db.Value) error { if reflect.ValueOf(jsonData).Kind() == reflect.Map { data := reflect.ValueOf(jsonData) for _, key := range data.MapKeys() { @@ -86,7 +93,7 @@ func cvlYangReqToDbMapCreate(uri string, jsonData interface{}, result map[string if ok { directDbMapData(key.String(), data.MapIndex(key).Interface(), result) } else { - cvlYangReqToDbMapCreate(key.String(), data.MapIndex(key).Interface(), result) + cvlYangReqToDbMapCreate(data.MapIndex(key).Interface(), result) } } } @@ -122,7 +129,7 @@ func directDbMapData(tableName string, jsonData interface{}, result map[string]m } /* Get the db table, key and field name for the incoming delete request */ -func dbMapDelete(path string, jsonData interface{}, result map[string]map[string]db.Value) error { +func dbMapDelete(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string, jsonData interface{}, result map[string]map[string]db.Value) error { xpathPrefix, keyName := xpathKeyExtract(path) log.Info("Delete req: path(\"%v\"), key(\"%v\"), xpathPrefix(\"%v\").", path, keyName, xpathPrefix) spec, ok := xSpecMap[xpathPrefix] @@ -141,28 +148,28 @@ func dbMapDelete(path string, jsonData interface{}, result map[string]map[string /* Get the data from incoming update/replace request, create map and fill with dbValue(ie. field:value to write into redis-db */ -func dbMapUpdate(path string, jsonData interface{}, result map[string]map[string]db.Value) error { +func dbMapUpdate(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string, jsonData interface{}, result map[string]map[string]db.Value) error { xpathPrefix, keyName := xpathKeyExtract(path) log.Info("Update/replace req: path(\"%v\"), key(\"%v\"), xpathPrefix(\"%v\").", path, keyName, xpathPrefix) - dbMapCreate(parentXpathGet(xpathPrefix), jsonData, result) + dbMapCreate(d, ygRoot, oper, parentXpathGet(xpathPrefix), jsonData, result) log.Info("Update/replace req: path(\"%v\") result(\"%v\").", path, result) return nil } /* Get the data from incoming create request, create map and fill with dbValue(ie. field:value to write into redis-db */ -func dbMapCreate(uri string, jsonData interface{}, result map[string]map[string]db.Value) error { - xpathTmplt, keyName := xpathKeyExtract(uri) - if isCvlYang(uri) { - cvlYangReqToDbMapCreate(uri, jsonData, result) +func dbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string, jsonData interface{}, result map[string]map[string]db.Value) error { + xpathTmplt, keyName := xpathKeyExtract(path) + if isCvlYang(path) { + cvlYangReqToDbMapCreate(jsonData, result) } else { - yangReqToDbMapCreate(uri, parentXpathGet(xpathTmplt), keyName, jsonData, result) + yangReqToDbMapCreate(d, ygRoot, oper, path, parentXpathGet(xpathTmplt), keyName, jsonData, result) } printDbData(result, "/tmp/yangToDbData.txt") return nil } -func yangReqToDbMapCreate(uri string, xpathPrefix string, keyName string, jsonData interface{}, result map[string]map[string]db.Value) error { +func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, xpathPrefix string, keyName string, jsonData interface{}, result map[string]map[string]db.Value) error { log.Info("key(\"%v\"), xpathPrefix(\"%v\").", keyName, xpathPrefix) if reflect.ValueOf(jsonData).Kind() == reflect.Slice { @@ -175,7 +182,7 @@ func yangReqToDbMapCreate(uri string, xpathPrefix string, keyName string, jsonDa // string for _, data := range dataMap { keyName := keyCreate(keyName, xpathPrefix, data) - yangReqToDbMapCreate(uri, xpathPrefix, keyName, data, result) + yangReqToDbMapCreate(d, ygRoot, oper, uri, xpathPrefix, keyName, data, result) } } else { if reflect.ValueOf(jsonData).Kind() == reflect.Map { @@ -201,7 +208,7 @@ func yangReqToDbMapCreate(uri string, xpathPrefix string, keyName string, jsonDa mapCopy(result, subMap) return nil } else { - yangReqToDbMapCreate(uri, xpath, keyName, jData.MapIndex(key).Interface(), result) + yangReqToDbMapCreate(d, ygRoot, oper, uri, xpath, keyName, jData.MapIndex(key).Interface(), result) } } else { pathAttr := key.String() @@ -210,7 +217,8 @@ func yangReqToDbMapCreate(uri string, xpathPrefix string, keyName string, jsonDa } value := jData.MapIndex(key).Interface() log.Info("data field: key(\"%v\"), value(\"%v\").", key, value) - err := mapFillData(keyName, result, xpathPrefix, pathAttr, fmt.Sprintf("%v", value)) + err := mapFillData(d, ygRoot, oper, uri, keyName, result, xpathPrefix, + pathAttr, fmt.Sprintf("%v", value)) if err != nil { log.Errorf("Failed constructing data for db write: key(\"%v\"), value(\"%v\"), path(\"%v\").", pathAttr, value, xpathPrefix) From 8c65dc2f86e02eda8f0bd988797cfd698de7a11c Mon Sep 17 00:00:00 2001 From: amrutasali Date: Fri, 16 Aug 2019 18:57:07 +0000 Subject: [PATCH 046/214] Added db pointer argument to transformer.XlateToDb() --- src/translib/acl_app.go | 2 +- src/translib/common_app.go | 2 +- src/translib/transformer/xlate.go | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/translib/acl_app.go b/src/translib/acl_app.go index 35066d7f57..c7863afdcc 100644 --- a/src/translib/acl_app.go +++ b/src/translib/acl_app.go @@ -293,7 +293,7 @@ func (app *AclApp) translateCRUCommon(d *db.DB, opcode int) ([]db.WatchKeys, err log.Info("translateCRUCommon:acl:path =", app.pathInfo.Template) // TODO - once it's fully verfied, restrcuture the rest code - result, err := transformer.XlateToDb(app.pathInfo.Path, opcode, app.ygotRoot, app.ygotTarget) + result, err := transformer.XlateToDb(app.pathInfo.Path, opcode, d, app.ygotRoot, app.ygotTarget) if err != nil { fmt.Println(result) } diff --git a/src/translib/common_app.go b/src/translib/common_app.go index 94166ed1be..5ee2a8c958 100644 --- a/src/translib/common_app.go +++ b/src/translib/common_app.go @@ -194,7 +194,7 @@ func (app *CommonApp) translateCRUCommon(d *db.DB, opcode int) ([]db.WatchKeys, log.Info("translateCRUCommon:path =", app.pathInfo.Path) // translate yang to db - result, err := transformer.XlateToDb(app.pathInfo.Path, opcode, (*app).ygotRoot, (*app).ygotTarget) + result, err := transformer.XlateToDb(app.pathInfo.Path, opcode, d, (*app).ygotRoot, (*app).ygotTarget) fmt.Println(result) log.Info("transformer.XlateToDb() returned", result) diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index 9a0983e35b..729c75ec96 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -197,7 +197,7 @@ func fillKeySpec(yangXpath string , keyStr string, dbFormat *KeySpec) { } } -func XlateToDb(path string, opcode int, yg *ygot.GoStruct, yt *interface{}) (map[string]map[string]db.Value, error) { +func XlateToDb(path string, opcode int, d *db.DB, yg *ygot.GoStruct, yt *interface{}) (map[string]map[string]db.Value, error) { var err error @@ -223,7 +223,7 @@ func XlateToDb(path string, opcode int, yg *ygot.GoStruct, yt *interface{}) (map switch opcode { case CREATE: log.Info("CREATE case") - err = dbMapCreate(nil, yg, opcode, path, jsonData, result) + err = dbMapCreate(d, yg, opcode, path, jsonData, result) if err != nil { log.Errorf("Error: Data translation from yang to db failed.") } From 3de79fd19330dc195d3eaa82b05ed807892863c1 Mon Sep 17 00:00:00 2001 From: Ravi Vasanthm Date: Fri, 16 Aug 2019 12:15:36 -0700 Subject: [PATCH 047/214] Modified Transformer method prototypes to pass operation type for xfmr methods. --- src/translib/transformer/xfmr_acl.go | 28 +++++++++++----------- src/translib/transformer/xfmr_interface.go | 24 +++++++++---------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/translib/transformer/xfmr_acl.go b/src/translib/transformer/xfmr_acl.go index 56d66ba26e..e848aa31fe 100644 --- a/src/translib/transformer/xfmr_acl.go +++ b/src/translib/transformer/xfmr_acl.go @@ -185,7 +185,7 @@ func getL2EtherType(etherType uint64) interface{} { return uint16(etherType) } -var YangToDb_acl_entry_key_xfmr KeyXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, xpath string) (string, error) { +var YangToDb_acl_entry_key_xfmr KeyXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, opType int, xpath string) (string, error) { var entry_key string var err error var oc_aclType ocbinds.E_OpenconfigAcl_ACL_TYPE @@ -215,7 +215,7 @@ var YangToDb_acl_entry_key_xfmr KeyXfmrYangToDb = func (d *db.DB, ygRoot *ygot.G return entry_key, err } -var DbToYang_acl_entry_key_xfmr KeyXfmrDbToYang = func (d *db.DB, entry_key string) (map[string]map[string]string, error) { +var DbToYang_acl_entry_key_xfmr KeyXfmrDbToYang = func (d *db.DB, opType int, entry_key string) (map[string]map[string]string, error) { res_map := make(map[string]map[string]string) var err error log.Info("DbToYang_acl_entry_key_xfmr: ", entry_key) @@ -238,7 +238,7 @@ var DbToYang_acl_entry_key_xfmr KeyXfmrDbToYang = func (d *db.DB, entry_key stri return res_map, err } -var YangToDb_acl_l2_ethertype_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, xpath string, ethertype interface {}) (map[string]string, error) { +var YangToDb_acl_l2_ethertype_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, opType int, xpath string, ethertype interface {}) (map[string]string, error) { res_map := make(map[string]string) var err error log.Info("YangToDb_acl_l2_ethertype_xfmr :", ygRoot, xpath) @@ -260,7 +260,7 @@ var YangToDb_acl_l2_ethertype_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *y return res_map, err } -var DbToYang_acl_l2_ethertype_xfmr FieldXfmrDbtoYang = func (d *db.DB, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct) (error) { +var DbToYang_acl_l2_ethertype_xfmr FieldXfmrDbtoYang = func (d *db.DB, opType int, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct) (error) { var err error log.Info("DbToYang_acl_l2_ethertype_xfmr", data, ygRoot) @@ -293,7 +293,7 @@ var DbToYang_acl_l2_ethertype_xfmr FieldXfmrDbtoYang = func (d *db.DB, data map[ return err } -var YangToDb_acl_ip_protocol_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, xpath string, protocol interface {}) (map[string]string, error) { +var YangToDb_acl_ip_protocol_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, opType int, xpath string, protocol interface {}) (map[string]string, error) { res_map := make(map[string]string) var err error log.Info("YangToDb_acl_ip_protocol_xfmr: ", ygRoot, xpath) @@ -312,7 +312,7 @@ var YangToDb_acl_ip_protocol_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *yg return res_map, err } -var DbToYang_acl_ip_protocol_xfmr FieldXfmrDbtoYang = func (d *db.DB, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct) (error) { +var DbToYang_acl_ip_protocol_xfmr FieldXfmrDbtoYang = func (d *db.DB, opType int, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct) (error) { var err error log.Info("DbToYang_acl_ip_protocol_xfmr ", data, ygRoot) if _, ok := data[RULE_TABLE]; !ok { @@ -344,7 +344,7 @@ var DbToYang_acl_ip_protocol_xfmr FieldXfmrDbtoYang = func (d *db.DB, data map[s return err } -var YangToDb_acl_source_port_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, xpath string, value interface {}) (map[string]string, error) { +var YangToDb_acl_source_port_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, opType int, xpath string, value interface {}) (map[string]string, error) { res_map := make(map[string]string) var err error; log.Info("YangToDb_acl_source_port_xfmr: ", ygRoot, xpath) @@ -407,7 +407,7 @@ func getAclSetEntry (aclRuleKey string, ygRoot *ygot.GoStruct) (*ocbinds.Opencon } -var DbToYang_acl_source_port_xfmr FieldXfmrDbtoYang = func (d *db.DB, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct) (error) { +var DbToYang_acl_source_port_xfmr FieldXfmrDbtoYang = func (d *db.DB, opType int, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct) (error) { var err error log.Info("DbToYang_acl_source_port_xfmr: ", data, ygRoot) @@ -446,7 +446,7 @@ var DbToYang_acl_source_port_xfmr FieldXfmrDbtoYang = func (d *db.DB, data map[s return err } -var YangToDb_acl_destination_port_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, xpath string, value interface{}) (map[string]string, error) { +var YangToDb_acl_destination_port_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, opType int, xpath string, value interface{}) (map[string]string, error) { res_map := make(map[string]string) var err error; log.Info("YangToDb_acl_destination_port_xfmr: ", ygRoot, xpath) @@ -468,7 +468,7 @@ var YangToDb_acl_destination_port_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoo return res_map, err } -var DbToYang_acl_destination_port_xfmr FieldXfmrDbtoYang = func (d *db.DB, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct) (error) { +var DbToYang_acl_destination_port_xfmr FieldXfmrDbtoYang = func (d *db.DB, opType int, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct) (error) { var err error log.Info("DbToYang_acl_destination_port_xfmr: ", data, ygRoot) if _, ok := data[RULE_TABLE]; !ok { @@ -506,7 +506,7 @@ var DbToYang_acl_destination_port_xfmr FieldXfmrDbtoYang = func (d *db.DB, data return err } -var YangToDb_acl_tcp_flags_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, xpath string, value interface {}) (map[string]string, error) { +var YangToDb_acl_tcp_flags_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, opType int, xpath string, value interface {}) (map[string]string, error) { res_map := make(map[string]string) var err error; log.Info("YangToDb_acl_tcp_flags_xfmr: ", ygRoot, xpath) @@ -549,7 +549,7 @@ var YangToDb_acl_tcp_flags_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot return res_map, err } -var DbToYang_acl_tcp_flags_xfmr FieldXfmrDbtoYang = func (d *db.DB, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct) (error) { +var DbToYang_acl_tcp_flags_xfmr FieldXfmrDbtoYang = func (d *db.DB, opType int, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct) (error) { var err error log.Info("DbToYang_acl_tcp_flags_xfmr: ", data, ygRoot) @@ -660,7 +660,7 @@ func getDbAlcTblsData (d *db.DB) (map[string]db.Value, map[string]map[string]db. return aclTableMap, ruleTableMap, err } -var YangToDb_acl_port_bindings_xfmr SubTreeXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, xpath string) (map[string]map[string]db.Value, error) { +var YangToDb_acl_port_bindings_xfmr SubTreeXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, opType int, xpath string) (map[string]map[string]db.Value, error) { res_map := make(map[string]map[string]db.Value) aclTableMap := make(map[string]db.Value) log.Info("YangToDb_acl_port_bindings_xfmr: ", ygRoot, xpath) @@ -744,7 +744,7 @@ var YangToDb_acl_port_bindings_xfmr SubTreeXfmrYangToDb = func (d *db.DB, ygRoot return res_map, err } -var DbToYang_acl_port_bindings_xfmr SubTreeXfmrDbToYang = func (d *db.DB, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct, xpath string) (error) { +var DbToYang_acl_port_bindings_xfmr SubTreeXfmrDbToYang = func (d *db.DB, opType int, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct, xpath string) (error) { var err error log.Info("DbToYang_acl_port_bindings_xfmr: ", data, ygRoot) diff --git a/src/translib/transformer/xfmr_interface.go b/src/translib/transformer/xfmr_interface.go index 1b1095f562..42407075f2 100644 --- a/src/translib/transformer/xfmr_interface.go +++ b/src/translib/transformer/xfmr_interface.go @@ -9,47 +9,47 @@ import ( /** * KeyXfmrYangToDb type is defined to use for conversion of Yang key to DB Key * Transformer function definition. - * Param: Database info, YgotRoot, Xpath + * Param: Database info, YgotRoot, operation, Xpath * Return: Database keys to access db entry, error **/ -type KeyXfmrYangToDb func (*db.DB, *ygot.GoStruct, string) (string, error) +type KeyXfmrYangToDb func (*db.DB, *ygot.GoStruct, int, string) (string, error) /** * KeyXfmrDbToYang type is defined to use for conversion of DB key to Yang key * Transformer function definition. - * Param: Database info, Database keys to access db entry + * Param: Database info, operation, Database keys to access db entry * Return: multi dimensional map to hold the yang key attributes of complete xpath, error **/ -type KeyXfmrDbToYang func (*db.DB, string) (map[string]map[string]string, error) +type KeyXfmrDbToYang func (*db.DB, int, string) (map[string]map[string]string, error) /** * FieldXfmrYangToDb type is defined to use for conversion of yang Field to DB field * Transformer function definition. - * Param: Database info, YgotRoot, Xpath + * Param: Database info, YgotRoot, operation, Xpath * Return: multi dimensional map to hold the DB data, error **/ -type FieldXfmrYangToDb func (*db.DB, *ygot.GoStruct, string, interface {}) (map[string]string, error) +type FieldXfmrYangToDb func (*db.DB, *ygot.GoStruct, int, string, interface {}) (map[string]string, error) /** * FieldXfmrDbtoYang type is defined to use for conversion of DB field to Yang field * Transformer function definition. - * Param: Database info, DB data in multidimensional map, output param YgotRoot + * Param: Database info, operation, DB data in multidimensional map, output param YgotRoot * Return: error **/ -type FieldXfmrDbtoYang func (*db.DB, map[string]map[string]db.Value, *ygot.GoStruct) (error) +type FieldXfmrDbtoYang func (*db.DB, int, map[string]map[string]db.Value, *ygot.GoStruct) (error) /** * SubTreeXfmrYangToDb type is defined to use for handling the yang subtree to DB * Transformer function definition. - * Param: Database info, YgotRoot, Xpath + * Param: Database info, YgotRoot, operation, Xpath * Return: multi dimensional map to hold the DB data, error **/ -type SubTreeXfmrYangToDb func (*db.DB, *ygot.GoStruct, string) (map[string]map[string]db.Value, error) +type SubTreeXfmrYangToDb func (*db.DB, *ygot.GoStruct, int, string) (map[string]map[string]db.Value, error) /** * SubTreeXfmrDbToYang type is defined to use for handling the DB to Yang subtree * Transformer function definition. - * Param : Database info, DB data in multidimensional map, output param YgotRoot + * Param : Database info, operation, DB data in multidimensional map, output param YgotRoot * Return : error **/ -type SubTreeXfmrDbToYang func (*db.DB, map[string]map[string]db.Value, *ygot.GoStruct, string) (error) +type SubTreeXfmrDbToYang func (*db.DB, int, map[string]map[string]db.Value, *ygot.GoStruct, string) (error) /** * Xfmr validation interface for validating the callback registration of app modules From 4a337542d84cad54184e88f3ea95b79d69d1a3a0 Mon Sep 17 00:00:00 2001 From: amrutasali Date: Fri, 16 Aug 2019 22:34:42 +0000 Subject: [PATCH 048/214] call transformer.XlateUriToKeySpec() from processGet instead of tranlateCreate() Reverted the siganture chnage of translateCreate() and processGet() due to above change --- src/translib/acl_app.go | 13 ++++++------- src/translib/app_interface.go | 5 ++--- src/translib/common_app.go | 13 ++++++------- src/translib/subscribe.go | 4 ++-- src/translib/translib.go | 6 +++--- 5 files changed, 19 insertions(+), 22 deletions(-) diff --git a/src/translib/acl_app.go b/src/translib/acl_app.go index c7863afdcc..1d91dfe7fc 100644 --- a/src/translib/acl_app.go +++ b/src/translib/acl_app.go @@ -150,13 +150,10 @@ func (app *AclApp) translateDelete(d *db.DB) ([]db.WatchKeys, error) { return keys, err } -func (app *AclApp) translateGet(dbs [db.MaxDB]*db.DB) (*map[db.DBNum][]transformer.KeySpec, error) { +func (app *AclApp) translateGet(dbs [db.MaxDB]*db.DB) error { var err error log.Info("translateGet:acl:path =", app.pathInfo.Template) - - keySpec, err := transformer.XlateUriToKeySpec(app.pathInfo.Path, app.ygotRoot, app.ygotTarget) - - return keySpec, err + return err } func (app *AclApp) translateSubscribe(dbs [db.MaxDB]*db.DB, path string) (*notificationOpts, *notificationInfo, error) { @@ -263,14 +260,16 @@ func (app *AclApp) processDelete(d *db.DB) (SetResponse, error) { return resp, err } -func (app *AclApp) processGet(dbs [db.MaxDB]*db.DB, keyspec *map[db.DBNum][]transformer.KeySpec) (GetResponse, error) { +func (app *AclApp) processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error) { var err error var payload []byte + keySpec, err := transformer.XlateUriToKeySpec(app.pathInfo.Path, app.ygotRoot, app.ygotTarget) + // table.key.fields var result = make(map[string]map[string]db.Value) - for dbnum, specs := range *keyspec { + for dbnum, specs := range *keySpec { for _, spec := range specs { err := transformer.TraverseDb(dbs[dbnum], spec, &result, nil) if err != nil { diff --git a/src/translib/app_interface.go b/src/translib/app_interface.go index f35c4dffa9..6730e66259 100644 --- a/src/translib/app_interface.go +++ b/src/translib/app_interface.go @@ -22,7 +22,6 @@ import ( "reflect" "strings" "translib/db" - "translib/transformer" log "github.com/golang/glog" "github.com/openconfig/ygot/ygot" ) @@ -56,13 +55,13 @@ type appInterface interface { translateUpdate(d *db.DB) ([]db.WatchKeys, error) translateReplace(d *db.DB) ([]db.WatchKeys, error) translateDelete(d *db.DB) ([]db.WatchKeys, error) - translateGet(dbs [db.MaxDB]*db.DB) (*map[db.DBNum][]transformer.KeySpec, error) + translateGet(dbs [db.MaxDB]*db.DB) error translateSubscribe(dbs [db.MaxDB]*db.DB, path string) (*notificationOpts, *notificationInfo, error) processCreate(d *db.DB) (SetResponse, error) processUpdate(d *db.DB) (SetResponse, error) processReplace(d *db.DB) (SetResponse, error) processDelete(d *db.DB) (SetResponse, error) - processGet(dbs [db.MaxDB]*db.DB, spec *map[db.DBNum][]transformer.KeySpec) (GetResponse, error) + processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error) } //App modules will use this function to register with App interface during boot up diff --git a/src/translib/common_app.go b/src/translib/common_app.go index 5ee2a8c958..cae4479f94 100644 --- a/src/translib/common_app.go +++ b/src/translib/common_app.go @@ -91,13 +91,10 @@ func (app *CommonApp) translateDelete(d *db.DB) ([]db.WatchKeys, error) { return keys, err } -func (app *CommonApp) translateGet(dbs [db.MaxDB]*db.DB) (*map[db.DBNum][]transformer.KeySpec, error) { +func (app *CommonApp) translateGet(dbs [db.MaxDB]*db.DB) error { var err error log.Info("translateGet:path =", app.pathInfo.Path) - - keySpec, err := transformer.XlateUriToKeySpec(app.pathInfo.Path, app.ygotRoot, app.ygotTarget) - - return keySpec, err + return err } func (app *CommonApp) translateSubscribe(dbs [db.MaxDB]*db.DB, path string) (*notificationOpts, *notificationInfo, error) { @@ -161,15 +158,17 @@ func (app *CommonApp) processDelete(d *db.DB) (SetResponse, error) { return resp, err } -func (app *CommonApp) processGet(dbs [db.MaxDB]*db.DB, keyspec *map[db.DBNum][]transformer.KeySpec) (GetResponse, error) { +func (app *CommonApp) processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error) { var err error var payload []byte log.Info("processGet:path =", app.pathInfo.Path) + keySpec, err := transformer.XlateUriToKeySpec(app.pathInfo.Path, app.ygotRoot, app.ygotTarget) + // table.key.fields var result = make(map[string]map[string]db.Value) - for dbnum, specs := range *keyspec { + for dbnum, specs := range *keySpec { for _, spec := range specs { err := transformer.TraverseDb(dbs[dbnum], spec, &result, nil) if err != nil { diff --git a/src/translib/subscribe.go b/src/translib/subscribe.go index 0fd5910419..d48c9ac12d 100644 --- a/src/translib/subscribe.go +++ b/src/translib/subscribe.go @@ -233,13 +233,13 @@ func getJson (nInfo *notificationInfo) ([]byte, error) { dbs := nInfo.dbs - keySpec, err := (*app).translateGet (dbs) + err = (*app).translateGet (dbs) if err != nil { return payload, err } - resp, err := (*app).processGet(dbs, keySpec) + resp, err := (*app).processGet(dbs) if err == nil { payload = resp.Payload diff --git a/src/translib/translib.go b/src/translib/translib.go index 2d3bd5d174..5085d9f1bf 100644 --- a/src/translib/translib.go +++ b/src/translib/translib.go @@ -406,15 +406,15 @@ func Get(req GetRequest) (GetResponse, error){ } defer closeAllDbs(dbs[:]) - - keySpec, err := (*app).translateGet (dbs) + + err = (*app).translateGet (dbs) if err != nil { resp = GetResponse{Payload:payload, ErrSrc:AppErr} return resp, err } - resp, err = (*app).processGet(dbs, keySpec) + resp, err = (*app).processGet(dbs) return resp, err } From c88231cb9830922b13b762b776be50967879fb9e Mon Sep 17 00:00:00 2001 From: s-mari Date: Fri, 16 Aug 2019 16:08:35 -0700 Subject: [PATCH 049/214] Enabled key, field and subtree overloaded-transformer-function exec from transformer infra --- src/translib/transformer/xlate_to_db.go | 35 ++++++++++++++++++------- src/translib/transformer/xlate_utils.go | 2 +- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index 7d649a70be..10b8bcecf9 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -60,10 +60,15 @@ func mapFillData(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, dbKey st } if len(xpathInfo.xfmrFunc) > 0 { + /* field transformer present */ log.Info("Transformer function(\"%v\") invoked for yang path(\"%v\").", xpathInfo.xfmrFunc, xpath) - // map[string]string - //fieldName := XlateFuncCall(xpathInfo.xfmrFunc, name, value) - //return errors.New("Invalid field name") + ret, err := XlateFuncCall(yangToDbXfmrFunc(xSpecMap[xpath].xfmrFunc), d, ygRoot, oper, uri, value) + if err != nil { return err } + retData := ret[0].Interface().(map[string]string) + log.Info("Transformer function \"%v\" for \"%v\" returned(%v).", xpathInfo.xfmrFunc, xpath, retData) + for f, v := range retData { + dataToDBMapAdd(*xpathInfo.tableName, dbKey, result, f, v) + } return nil } @@ -179,10 +184,18 @@ func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, for idx := 0; idx < jData.Len(); idx++ { dataMap[idx] = jData.Index(idx).Interface() } - // string for _, data := range dataMap { - keyName := keyCreate(keyName, xpathPrefix, data) - yangReqToDbMapCreate(d, ygRoot, oper, uri, xpathPrefix, keyName, data, result) + curKey := "" + uri = uriWithKeyCreate(uri, xpathPrefix, data) + if len(xSpecMap[xpathPrefix].xfmrKey) > 0 { + /* key transformer present */ + ret, err := XlateFuncCall(yangToDbXfmrFunc(xSpecMap[xpathPrefix].xfmrKey), d, ygRoot, oper, uri) + if err != nil { return err } + curKey = ret[0].Interface().(string) + } else { + curKey = keyCreate(keyName, xpathPrefix, data) + } + yangReqToDbMapCreate(d, ygRoot, oper, uri, xpathPrefix, curKey, data, result) } } else { if reflect.ValueOf(jsonData).Kind() == reflect.Map { @@ -199,13 +212,15 @@ func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, pathAttr = strings.Split(pathAttr, ":")[1] } xpath = xpathPrefix + "/" + pathAttr + uri = uri + "/" + pathAttr } if xSpecMap[xpath] != nil && len(xSpecMap[xpath].xfmrFunc) > 0 { - subMap := callXfmr() - // map[string]map[string]db.Value - //subMap := XlateFuncCall(xpathInfo.xfmrFunc, name, value) - mapCopy(result, subMap) + /* subtree transformer present */ + ret, err := XlateFuncCall(yangToDbXfmrFunc(xSpecMap[xpath].xfmrFunc), d, ygRoot, oper, uri) + if err != nil { return nil } + //subMap := callXfmr() + mapCopy(result, ret[0].Interface().(map[string]map[string]db.Value)) return nil } else { yangReqToDbMapCreate(d, ygRoot, oper, uri, xpath, keyName, jData.MapIndex(key).Interface(), result) diff --git a/src/translib/transformer/xlate_utils.go b/src/translib/transformer/xlate_utils.go index 53af60e68b..f34e7f9a68 100644 --- a/src/translib/transformer/xlate_utils.go +++ b/src/translib/transformer/xlate_utils.go @@ -149,7 +149,7 @@ func keyJsonDataAdd(keyNameList []string, keyStr string, jsonData string) string } func yangToDbXfmrFunc(funcName string) string { - return ("YangToDB_" + funcName) + return ("YangToDb_" + funcName) } func uriWithKeyCreate (uri string, xpathTmplt string, data interface{}) string { From 289d53b4e120192308ef0c418f1b7f1c4e864dab Mon Sep 17 00:00:00 2001 From: amrutasali Date: Fri, 16 Aug 2019 23:13:24 +0000 Subject: [PATCH 050/214] Modifed DB operations in common app : For CREATE operation if entry/row instance already exists then return error For UPDATE operation if entry/row instance does not exist then return error --- src/translib/common_app.go | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/translib/common_app.go b/src/translib/common_app.go index cae4479f94..93785914ff 100644 --- a/src/translib/common_app.go +++ b/src/translib/common_app.go @@ -13,6 +13,7 @@ import ( "translib/db" //"translib/ocbinds" "translib/transformer" + "translib/tlerr" ) var ( @@ -240,12 +241,8 @@ func (app *CommonApp) cmnAppDataDbOperation(d *db.DB, opcode int, cmnAppDataDbMa log.Info("CREATE case") existingEntry, err := d.GetEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}) if existingEntry.IsPopulated() { - log.Info("Entry already exists hence modifying it.") - err := d.ModEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}, tblRw) - if err != nil { - log.Error("CREATE case - d.ModEntry() failure") - return err - } + log.Info("Entry already exists hence return error.") + return tlerr.AlreadyExists("Entry %s already exists", tblKey) } else { err = d.CreateEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}, tblRw) if err != nil { @@ -253,7 +250,7 @@ func (app *CommonApp) cmnAppDataDbOperation(d *db.DB, opcode int, cmnAppDataDbMa return err } } - case UPDATE: + case UPDATE: log.Info("UPDATE case") existingEntry, err := d.GetEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}) if existingEntry.IsPopulated() { @@ -264,11 +261,9 @@ func (app *CommonApp) cmnAppDataDbOperation(d *db.DB, opcode int, cmnAppDataDbMa return err } } else { - err = d.CreateEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}, tblRw) - if err != nil { - log.Error("UPDATE case - d.CreateEntry() failure") - return err - } + log.Info("Entry to be modified does not exist hence return error.") + return tlerr.NotFound("Entry %s to be modified does not exist.", tblKey) + } case REPLACE: From 3e6697bb44a4534a04405b532bf01db5820fdb16 Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Fri, 16 Aug 2019 19:55:47 -0700 Subject: [PATCH 051/214] Get handling: Send DB data to transformer to form json response --- src/translib/acl_app.go | 2 +- src/translib/common_app.go | 2 +- src/translib/transformer/xlate.go | 12 ++++++++++-- src/translib/transformer/xlate_from_db.go | 2 +- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/translib/acl_app.go b/src/translib/acl_app.go index 1d91dfe7fc..0f1839b277 100644 --- a/src/translib/acl_app.go +++ b/src/translib/acl_app.go @@ -278,7 +278,7 @@ func (app *AclApp) processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error) { } } - payload, err = transformer.XlateFromDb(result) + payload, err = transformer.XlateFromDb(app.pathInfo.Path, result) if err != nil { return GetResponse{Payload: payload, ErrSrc: AppErr}, err } diff --git a/src/translib/common_app.go b/src/translib/common_app.go index 93785914ff..3470b16bd0 100644 --- a/src/translib/common_app.go +++ b/src/translib/common_app.go @@ -178,7 +178,7 @@ func (app *CommonApp) processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error) { } } - payload, err = transformer.XlateFromDb(result) + payload, err = transformer.XlateFromDb(app.pathInfo.Path, result) if err != nil { return GetResponse{Payload: payload, ErrSrc: AppErr}, err } diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index 729c75ec96..a807d2d995 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -240,11 +240,19 @@ func XlateToDb(path string, opcode int, d *db.DB, yg *ygot.GoStruct, yt *interfa return result, err } -func XlateFromDb(data map[string]map[string]db.Value) ([]byte, error) { +func XlateFromDb(xpath string, data map[string]map[string]db.Value) ([]byte, error) { var err error + payload, err := dbDataToYangJsonCreate(xpath, data) + + if err != nil { + log.Errorf("Error: failed to create json response from DB data.") + return nil,err + } + // please implement me - data translated by transforme // here is a mock data + /* payload := `{ "acl-sets": { "acl-set": [ @@ -587,7 +595,7 @@ func XlateFromDb(data map[string]map[string]db.Value) ([]byte, error) { ] } }` - + */ result := []byte(payload) //TODO - implement me diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index 7953fcbc5d..5d710143ed 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -114,7 +114,7 @@ func dbDataToYangJsonCreate(xpath string, dbDataMap map[string]map[string]db.Val } jsonData += listDataToJsonAdd(xDbSpecMap[tblName].yangXpath, tblData, "", dbDataMap) } - jsonData = parentJsonDataUpdate(curXpath, jsonData) + //jsonData = parentJsonDataUpdate(curXpath, jsonData) jsonDataPrint(jsonData) return jsonData, nil } From 059ed1d84212e1f8643f0da791a64e95d9e998b0 Mon Sep 17 00:00:00 2001 From: kwangsuk Date: Sat, 17 Aug 2019 00:15:33 -0700 Subject: [PATCH 052/214] restructure acl_app.go --- src/translib/acl_app.go | 1511 ++--------------------- src/translib/app_utils.go | 8 + src/translib/common_app.go | 314 +++-- src/translib/path_utils.go | 29 + src/translib/transformer/transformer.go | 35 +- 5 files changed, 330 insertions(+), 1567 deletions(-) diff --git a/src/translib/acl_app.go b/src/translib/acl_app.go index 0f1839b277..02966dbfda 100644 --- a/src/translib/acl_app.go +++ b/src/translib/acl_app.go @@ -8,63 +8,25 @@ package translib import ( - "bytes" - "fmt" "reflect" - "strconv" "strings" "translib/db" "translib/ocbinds" - "translib/transformer" "translib/tlerr" + "translib/transformer" log "github.com/golang/glog" - "github.com/openconfig/ygot/util" "github.com/openconfig/ygot/ygot" ) - const ( - TABLE_SEPARATOR = "|" - KEY_SEPARATOR = "|" - ACL_TABLE = "ACL_TABLE" - RULE_TABLE = "ACL_RULE" - ACL_TYPE = "type" - ACL_DESCRIPTION = "policy_desc" - SONIC_ACL_TYPE_L2 = "L2" - SONIC_ACL_TYPE_IPV4 = "L3" - SONIC_ACL_TYPE_IPV6 = "L3V6" - OPENCONFIG_ACL_TYPE_IPV4 = "ACL_IPV4" - OPENCONFIG_ACL_TYPE_IPV6 = "ACL_IPV6" - OPENCONFIG_ACL_TYPE_L2 = "ACL_L2" - OC_ACL_APP_MODULE_NAME = "/openconfig-acl:acl" - OC_ACL_YANG_PATH_PREFIX = "/device/acl" - - MIN_PRIORITY = 1 - MAX_PRIORITY = 65535 + TABLE_SEPARATOR = "|" + KEY_SEPARATOR = "|" + ACL_TABLE = "ACL_TABLE" + RULE_TABLE = "ACL_RULE" ) -var IP_PROTOCOL_MAP = map[ocbinds.E_OpenconfigPacketMatchTypes_IP_PROTOCOL]uint8{ - ocbinds.OpenconfigPacketMatchTypes_IP_PROTOCOL_IP_ICMP: 1, - ocbinds.OpenconfigPacketMatchTypes_IP_PROTOCOL_IP_IGMP: 2, - ocbinds.OpenconfigPacketMatchTypes_IP_PROTOCOL_IP_TCP: 6, - ocbinds.OpenconfigPacketMatchTypes_IP_PROTOCOL_IP_UDP: 17, - ocbinds.OpenconfigPacketMatchTypes_IP_PROTOCOL_IP_RSVP: 46, - ocbinds.OpenconfigPacketMatchTypes_IP_PROTOCOL_IP_GRE: 47, - ocbinds.OpenconfigPacketMatchTypes_IP_PROTOCOL_IP_AUTH: 51, - ocbinds.OpenconfigPacketMatchTypes_IP_PROTOCOL_IP_PIM: 103, - ocbinds.OpenconfigPacketMatchTypes_IP_PROTOCOL_IP_L2TP: 115, -} - -var ETHERTYPE_MAP = map[ocbinds.E_OpenconfigPacketMatchTypes_ETHERTYPE]uint32{ - ocbinds.OpenconfigPacketMatchTypes_ETHERTYPE_ETHERTYPE_LLDP: 0x88CC, - ocbinds.OpenconfigPacketMatchTypes_ETHERTYPE_ETHERTYPE_VLAN: 0x8100, - ocbinds.OpenconfigPacketMatchTypes_ETHERTYPE_ETHERTYPE_ROCE: 0x8915, - ocbinds.OpenconfigPacketMatchTypes_ETHERTYPE_ETHERTYPE_ARP: 0x0806, - ocbinds.OpenconfigPacketMatchTypes_ETHERTYPE_ETHERTYPE_IPV4: 0x0800, - ocbinds.OpenconfigPacketMatchTypes_ETHERTYPE_ETHERTYPE_IPV6: 0x86DD, - ocbinds.OpenconfigPacketMatchTypes_ETHERTYPE_ETHERTYPE_MPLS: 0x8847, -} +type configHandler func(*db.DB, *AclApp, int) error type AclApp struct { pathInfo *PathInfo @@ -75,7 +37,9 @@ type AclApp struct { ruleTs *db.TableSpec aclTableMap map[string]db.Value - ruleTableMap map[string]map[string]db.Value + ruleTableMap map[string]db.Value + //ruleTableMap map[string]map[string]db.Value + callpoints map[string]configHandler } func init() { @@ -107,7 +71,16 @@ func (app *AclApp) initialize(data appData) { app.ruleTs = &db.TableSpec{Name: RULE_TABLE} app.aclTableMap = make(map[string]db.Value) - app.ruleTableMap = make(map[string]map[string]db.Value) + app.ruleTableMap = make(map[string]db.Value) + + app.callpoints = map[string]configHandler{ + "/openconfig-acl:acl": handleAcl, + "/openconfig-acl:acl/acl-sets": handleAclSet, + "/openconfig-acl:acl/acl-sets/acl-set": handleAclSet, + "/openconfig-acl:acl/acl-sets/acl-set/acl-entries": handleAclEntry, + "/openconfig-acl:acl/acl-sets/acl-set/acl-entries/acl-entry": handleAclEntry, + "/openconfig-acl:acl/interfaces": handleAclInterface, + } } func (app *AclApp) getAppRootObject() *ocbinds.OpenconfigAcl_Acl { @@ -147,73 +120,19 @@ func (app *AclApp) translateDelete(d *db.DB) ([]db.WatchKeys, error) { var keys []db.WatchKeys log.Info("translateDelete:acl:path =", app.pathInfo.Template) + keys, err = app.translateCRUCommon(d, DELETE) return keys, err } func (app *AclApp) translateGet(dbs [db.MaxDB]*db.DB) error { - var err error - log.Info("translateGet:acl:path =", app.pathInfo.Template) - return err + var err error + log.Info("translateGet:acl:path =", app.pathInfo.Template) + return err } func (app *AclApp) translateSubscribe(dbs [db.MaxDB]*db.DB, path string) (*notificationOpts, *notificationInfo, error) { - pathInfo := NewPathInfo(path) - notifInfo := notificationInfo{dbno: db.ConfigDB} - notSupported := tlerr.NotSupportedError{ - Format: "Subscribe not supported", Path: path} - - if isSubtreeRequest(pathInfo.Template, "/openconfig-acl:acl/acl-sets") { - // Subscribing to top level ACL record is not supported. It requires listening - // to 2 tables (ACL and ACL_RULE); TransLib does not support it yet - if pathInfo.HasSuffix("/acl-sets") || - pathInfo.HasSuffix("/acl-set") || - pathInfo.HasSuffix("/acl-set{}{}") { - log.Errorf("Subscribe not supported for top level ACL %s", pathInfo.Template) - return nil, nil, notSupported - } - - t, err := getAclTypeOCEnumFromName(pathInfo.Var("type")) - if err != nil { - return nil, nil, err - } - - aclkey := getAclKeyStrFromOCKey(pathInfo.Var("name"), t) - - if strings.Contains(pathInfo.Template, "/acl-entry{}") { - // Subscribe for one rule - rulekey := "RULE_" + pathInfo.Var("sequence-id") - notifInfo.table = db.TableSpec{Name: RULE_TABLE} - notifInfo.key = asKey(aclkey, rulekey) - notifInfo.needCache = !pathInfo.HasSuffix("/acl-entry{}") - - } else if pathInfo.HasSuffix("/acl-entries") || pathInfo.HasSuffix("/acl-entry") { - // Subscribe for all rules of an ACL - notifInfo.table = db.TableSpec{Name: RULE_TABLE} - notifInfo.key = asKey(aclkey, "*") - - } else { - // Subscibe for ACL fields only - notifInfo.table = db.TableSpec{Name: ACL_TABLE} - notifInfo.key = asKey(aclkey) - notifInfo.needCache = true - } - } else if isSubtreeRequest(pathInfo.Template, "/openconfig-acl:acl/interfaces") { - // Right now interface binding config is maintained within ACL - // table itself. Multiple ACLs can be bound to one intf; one - // inname can occur in multiple ACL entries. So we cannot map - // interface binding xpaths to specific ACL table entry keys. - // For now subscribe for full ACL table!! - notifInfo.table = db.TableSpec{Name: ACL_TABLE} - notifInfo.key = asKey("*") - notifInfo.needCache = true - - } else { - log.Errorf("Unknown path %s", pathInfo.Template) - return nil, nil, notSupported - } - - return nil, ¬ifInfo, nil + return nil, nil, nil } func (app *AclApp) processCreate(d *db.DB) (SetResponse, error) { @@ -261,29 +180,29 @@ func (app *AclApp) processDelete(d *db.DB) (SetResponse, error) { } func (app *AclApp) processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error) { - var err error - var payload []byte + var err error + var payload []byte - keySpec, err := transformer.XlateUriToKeySpec(app.pathInfo.Path, app.ygotRoot, app.ygotTarget) + keyspec, err := transformer.XlateUriToKeySpec(app.pathInfo.Path, app.ygotRoot, app.ygotTarget) - // table.key.fields - var result = make(map[string]map[string]db.Value) + // table.key.fields + var result = make(map[string]map[string]db.Value) - for dbnum, specs := range *keySpec { - for _, spec := range specs { - err := transformer.TraverseDb(dbs[dbnum], spec, &result, nil) - if err != nil { - return GetResponse{Payload: payload}, err - } - } - } + for dbnum, specs := range *keyspec { + for _, spec := range specs { + err := transformer.TraverseDb(dbs[dbnum], spec, &result, nil) + if err != nil { + return GetResponse{Payload: payload}, err + } + } + } - payload, err = transformer.XlateFromDb(app.pathInfo.Path, result) - if err != nil { - return GetResponse{Payload: payload, ErrSrc: AppErr}, err - } + payload, err = transformer.XlateFromDb(app.pathInfo.Path, result) + if err != nil { + return GetResponse{Payload: payload, ErrSrc: AppErr}, err + } - return GetResponse{Payload: payload}, err + return GetResponse{Payload: payload}, err } func (app *AclApp) translateCRUCommon(d *db.DB, opcode int) ([]db.WatchKeys, error) { @@ -291,1320 +210,144 @@ func (app *AclApp) translateCRUCommon(d *db.DB, opcode int) ([]db.WatchKeys, err var keys []db.WatchKeys log.Info("translateCRUCommon:acl:path =", app.pathInfo.Template) - // TODO - once it's fully verfied, restrcuture the rest code - result, err := transformer.XlateToDb(app.pathInfo.Path, opcode, d, app.ygotRoot, app.ygotTarget) - if err != nil { - fmt.Println(result) - } + result, err := transformer.XlateToDb(app.pathInfo.Path, opcode, d, app.ygotRoot, app.ygotTarget) + if err != nil { + return nil, err + } - app.convertOCAclsToInternal() - app.convertOCAclRulesToInternal(d) - app.convertOCAclBindingsToInternal() + app.aclTableMap = result["ACL_TABLE"] + app.ruleTableMap = result["ACL_RULE"] + // add app specific as needed, e.g. default rule return keys, err } -func (app *AclApp) processCommon(d *db.DB, opcode int) error { +func handleAclInterface(d *db.DB, app *AclApp, opcode int) error { var err error - var topmostPath bool = false - acl := app.getAppRootObject() - - log.Infof("processCommon--Path Received: %s", app.pathInfo.Template) - targetType := reflect.TypeOf(*app.ygotTarget) - if !util.IsValueScalar(reflect.ValueOf(*app.ygotTarget)) && util.IsValuePtr(reflect.ValueOf(*app.ygotTarget)) { - log.Infof("processCommon: Target object is a <%s> of Type: %s", targetType.Kind().String(), targetType.Elem().Name()) - if targetType.Elem().Name() == "OpenconfigAcl_Acl" { - topmostPath = true - } - } - - targetUriPath, _ := getYangPathFromUri(app.pathInfo.Path) - if isSubtreeRequest(app.pathInfo.Template, "/openconfig-acl:acl/acl-sets") { - if isSubtreeRequest(app.pathInfo.Template, "/openconfig-acl:acl/acl-sets/acl-set{}{}") { - for aclSetKey, _ := range acl.AclSets.AclSet { - aclSet := acl.AclSets.AclSet[aclSetKey] - aclKey := getAclKeyStrFromOCKey(aclSetKey.Name, aclSetKey.Type) - - if isSubtreeRequest(app.pathInfo.Template, "/openconfig-acl:acl/acl-sets/acl-set{}{}/acl-entries/acl-entry{}") { - // Subtree of one Rule - for seqId, _ := range aclSet.AclEntries.AclEntry { - ruleKey := "RULE_" + strconv.Itoa(int(seqId)) - entrySet := aclSet.AclEntries.AclEntry[seqId] - - ruleNodeYangPath := getYangPathFromYgotStruct(entrySet, OC_ACL_YANG_PATH_PREFIX, OC_ACL_APP_MODULE_NAME) - isRuleNodeSubtree := len(targetUriPath) > len(ruleNodeYangPath) - switch opcode { - case CREATE: - if isRuleNodeSubtree { - err = app.setAclRuleDataInConfigDb(d, app.ruleTableMap, false) - } else if *app.ygotTarget == entrySet { - err = app.setAclRuleDataInConfigDb(d, app.ruleTableMap, true) - } else { - log.Errorf("processCommon: Given CREATE path %s not handled", targetUriPath) - } - case REPLACE: - err = d.SetEntry(app.ruleTs, db.Key{Comp: []string{aclKey, ruleKey}}, app.ruleTableMap[aclKey][ruleKey]) - case UPDATE: - err = d.ModEntry(app.ruleTs, db.Key{Comp: []string{aclKey, ruleKey}}, app.ruleTableMap[aclKey][ruleKey]) - case DELETE: - if isRuleNodeSubtree { - err = d.SetEntry(app.ruleTs, db.Key{Comp: []string{aclKey, ruleKey}}, app.ruleTableMap[aclKey][ruleKey]) - } else if *app.ygotTarget == entrySet { - err = d.DeleteEntry(app.ruleTs, db.Key{Comp: []string{aclKey, ruleKey}}) - } else { - log.Errorf("processCommon: Given DELETE path %s not handled", targetUriPath) - } - case GET: - err = app.convertDBAclRulesToInternal(d, aclKey, int64(seqId), db.Key{}) - ygot.BuildEmptyTree(entrySet) - app.convertInternalToOCAclRule(aclKey, aclSetKey.Type, int64(seqId), nil, entrySet) - } - } - } else { - isAclEntriesSubtree := isSubtreeRequest(app.pathInfo.Template, "/openconfig-acl:acl/acl-sets/acl-set{}{}/acl-entries") - switch opcode { - case CREATE: - if *app.ygotTarget == aclSet { - err = app.setAclDataInConfigDb(d, app.aclTableMap, true) - if err != nil { - return err - } - err = app.setAclRuleDataInConfigDb(d, app.ruleTableMap, true) - } else if isAclEntriesSubtree { - err = app.setAclRuleDataInConfigDb(d, app.ruleTableMap, true) - } else { - err = d.SetEntry(app.aclTs, db.Key{Comp: []string{aclKey}}, app.aclTableMap[aclKey]) - } - case REPLACE: - if *app.ygotTarget == aclSet || isAclEntriesSubtree { - err = d.DeleteKeys(app.ruleTs, db.Key{Comp: []string{aclKey + TABLE_SEPARATOR + "*"}}) - if err != nil { - return err - } - err = app.setAclRuleDataInConfigDb(d, app.ruleTableMap, true) - if err != nil { - return err - } - } - if !isAclEntriesSubtree { - err = d.SetEntry(app.aclTs, db.Key{Comp: []string{aclKey}}, app.aclTableMap[aclKey]) - } - case UPDATE: - if !isAclEntriesSubtree { - err = app.setAclDataInConfigDb(d, app.aclTableMap, false) - //err = d.ModEntry(app.aclTs, db.Key{Comp: []string{aclKey}}, app.aclTableMap[aclKey]) - if err != nil { - return err - } - } - if *app.ygotTarget == aclSet || isAclEntriesSubtree { - err = app.setAclRuleDataInConfigDb(d, app.ruleTableMap, false) - } - case DELETE: - if *app.ygotTarget == aclSet { - err = d.DeleteKeys(app.ruleTs, db.Key{Comp: []string{aclKey + TABLE_SEPARATOR + "*"}}) - if err != nil { - return err - } - err = d.DeleteEntry(app.aclTs, db.Key{Comp: []string{aclKey}}) - } else if isAclEntriesSubtree { - err = d.DeleteKeys(app.ruleTs, db.Key{Comp: []string{aclKey + TABLE_SEPARATOR + "*"}}) - } else { - err = d.SetEntry(app.aclTs, db.Key{Comp: []string{aclKey}}, app.aclTableMap[aclKey]) - } - case GET: - err = app.convertDBAclToInternal(d, db.Key{Comp: []string{aclKey}}) - if err != nil { - return err - } - ygot.BuildEmptyTree(aclSet) - app.convertInternalToOCAcl(aclKey, acl.AclSets, aclSet) - } - } - } - } else { - // All Acls and their rules - err = app.processCommonToplevelPath(d, acl, opcode, false) + for key, data := range app.aclTableMap { + existingEntry, err := d.GetEntry(app.aclTs, db.Key{Comp: []string{key}}) + if !existingEntry.IsPopulated() { + return tlerr.AlreadyExists("Acl %s already exists", key) } - } else if isSubtreeRequest(app.pathInfo.Template, "/openconfig-acl:acl/interfaces") { + // !!! Overloaded xfmr methods tale care for bindings, to set the data switch opcode { - case CREATE, REPLACE, UPDATE: - err = app.setAclBindDataInConfigDb(d, app.aclTableMap, opcode) + case CREATE: + case REPLACE: + case UPDATE: case DELETE: - err = app.handleBindingsDeletion(d) - case GET: - if isSubtreeRequest(app.pathInfo.Template, "/openconfig-acl:acl/interfaces/interface{}") { - for intfId := range acl.Interfaces.Interface { - intfData := acl.Interfaces.Interface[intfId] - ygot.BuildEmptyTree(intfData) - if isSubtreeRequest(targetUriPath, "/openconfig-acl:acl/interfaces/interface/ingress-acl-sets") { - err = app.getAclBindingInfoForInterfaceData(d, intfData, intfId, "INGRESS") - } else if isSubtreeRequest(targetUriPath, "/openconfig-acl:acl/interfaces/interface/egress-acl-sets") { - err = app.getAclBindingInfoForInterfaceData(d, intfData, intfId, "EGRESS") - } else { - // Direction unknown. Check ACL Table for binding information. - err = app.getAclBindingInfoForInterfaceData(d, intfData, intfId, "INGRESS") - if err != nil { - return err - } - err = app.getAclBindingInfoForInterfaceData(d, intfData, intfId, "EGRESS") - } - } - } else { - err = app.getAllBindingsInfo(d) - } - } - } else { - err = app.processCommonToplevelPath(d, acl, opcode, true) - } - - if !topmostPath && !isSubtreeRequest(targetUriPath, "/openconfig-acl:acl/acl-sets") && !isSubtreeRequest(targetUriPath, "/openconfig-acl:acl/interfaces") { - err = tlerr.NotSupported("URL %s is not supported", app.pathInfo.Template) - } - - return err -} - -func (app *AclApp) processCommonToplevelPath(d *db.DB, acl *ocbinds.OpenconfigAcl_Acl, opcode int, isTopmostPath bool) error { - var err error - switch opcode { - case CREATE: - err = app.setAclDataInConfigDb(d, app.aclTableMap, true) - if err != nil { - return err - } - err = app.setAclRuleDataInConfigDb(d, app.ruleTableMap, true) - case REPLACE: - err = d.DeleteTable(app.aclTs) - if err != nil { - return err - } - err = d.DeleteTable(app.ruleTs) - if err != nil { - return err + err = d.SetEntry(app.aclTs, db.Key{Comp: []string{key}}, data) } - err = app.setAclDataInConfigDb(d, app.aclTableMap, true) if err != nil { - return err - } - err = app.setAclRuleDataInConfigDb(d, app.ruleTableMap, true) - case UPDATE: - err = app.setAclDataInConfigDb(d, app.aclTableMap, false) - if err != nil { - return err - } - err = app.setAclRuleDataInConfigDb(d, app.ruleTableMap, false) - case DELETE: - err = d.DeleteTable(app.ruleTs) - if err != nil { - return err - } - err = d.DeleteTable(app.aclTs) - case GET: - ygot.BuildEmptyTree(acl) - err = app.convertDBAclToInternal(d, db.Key{}) - if err != nil { - return err - } - app.convertInternalToOCAcl("", acl.AclSets, nil) - if isTopmostPath { - err = app.getAllBindingsInfo(d) - } - } - return err -} - -/*********** These are Translation Helper Function ***********/ -func (app *AclApp) convertDBAclRulesToInternal(dbCl *db.DB, aclName string, seqId int64, ruleKey db.Key) error { - var err error - if seqId != -1 { - ruleKey.Comp = []string{aclName, "RULE_" + strconv.FormatInt(int64(seqId), 10)} - } - if ruleKey.Len() > 1 { - ruleName := ruleKey.Get(1) - if ruleName != "DEFAULT_RULE" { - ruleData, err := dbCl.GetEntry(app.ruleTs, ruleKey) - if err != nil { - return err - } - if app.ruleTableMap[aclName] == nil { - app.ruleTableMap[aclName] = make(map[string]db.Value) - } - app.ruleTableMap[aclName][ruleName] = ruleData - } - } else { - ruleKeys, err := dbCl.GetKeys(app.ruleTs) - if err != nil { - return err - } - for i, _ := range ruleKeys { - if aclName == ruleKeys[i].Get(0) { - app.convertDBAclRulesToInternal(dbCl, aclName, -1, ruleKeys[i]) - } + break } } return err } -func (app *AclApp) convertDBAclToInternal(dbCl *db.DB, aclkey db.Key) error { +func handleAclSet(d *db.DB, app *AclApp, opcode int) error { var err error - if aclkey.Len() > 0 { - // Get one particular ACL - entry, err := dbCl.GetEntry(app.aclTs, aclkey) - if err != nil { - return err - } - if entry.IsPopulated() { - app.aclTableMap[aclkey.Get(0)] = entry - app.ruleTableMap[aclkey.Get(0)] = make(map[string]db.Value) - err = app.convertDBAclRulesToInternal(dbCl, aclkey.Get(0), -1, db.Key{}) - if err != nil { - return err - } - } else { - return tlerr.NotFound("Acl %s is not configured", aclkey.Get(0)) - } - } else { - // Get all ACLs - tbl, err := dbCl.GetTable(app.aclTs) - if err != nil { - return err - } - keys, _ := tbl.GetKeys() - for i, _ := range keys { - app.convertDBAclToInternal(dbCl, keys[i]) - } - } - return err -} - -func (app *AclApp) convertInternalToOCAcl(aclName string, aclSets *ocbinds.OpenconfigAcl_Acl_AclSets, aclSet *ocbinds.OpenconfigAcl_Acl_AclSets_AclSet) { - if len(aclName) > 0 { - aclData := app.aclTableMap[aclName] - if aclSet != nil { - aclSet.Config.Name = aclSet.Name - aclSet.Config.Type = aclSet.Type - aclSet.State.Name = aclSet.Name - aclSet.State.Type = aclSet.Type - - for k := range aclData.Field { - if ACL_DESCRIPTION == k { - descr := aclData.Get(k) - aclSet.Config.Description = &descr - aclSet.State.Description = &descr - } else if "ports@" == k { - continue - } - } - - app.convertInternalToOCAclRule(aclName, aclSet.Type, -1, aclSet, nil) - } - } else { - for acln := range app.aclTableMap { - acldata := app.aclTableMap[acln] - var aclNameStr string - var aclType ocbinds.E_OpenconfigAcl_ACL_TYPE - if acldata.Get(ACL_TYPE) == SONIC_ACL_TYPE_IPV4 { - aclNameStr = strings.Replace(acln, "_"+OPENCONFIG_ACL_TYPE_IPV4, "", 1) - aclType = ocbinds.OpenconfigAcl_ACL_TYPE_ACL_IPV4 - } else if acldata.Get(ACL_TYPE) == SONIC_ACL_TYPE_IPV6 { - aclNameStr = strings.Replace(acln, "_"+OPENCONFIG_ACL_TYPE_IPV6, "", 1) - aclType = ocbinds.OpenconfigAcl_ACL_TYPE_ACL_IPV6 - } else if acldata.Get(ACL_TYPE) == SONIC_ACL_TYPE_L2 { - aclNameStr = strings.Replace(acln, "_"+OPENCONFIG_ACL_TYPE_L2, "", 1) - aclType = ocbinds.OpenconfigAcl_ACL_TYPE_ACL_L2 - } - aclSetPtr, aclErr := aclSets.NewAclSet(aclNameStr, aclType) - if aclErr != nil { - fmt.Println("Error handling: ", aclErr) - } - ygot.BuildEmptyTree(aclSetPtr) - app.convertInternalToOCAcl(acln, nil, aclSetPtr) - } - } -} -func (app *AclApp) convertInternalToOCAclRule(aclName string, aclType ocbinds.E_OpenconfigAcl_ACL_TYPE, seqId int64, aclSet *ocbinds.OpenconfigAcl_Acl_AclSets_AclSet, entrySet *ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry) { - if seqId != -1 { - ruleName := "RULE_" + strconv.FormatInt(int64(seqId), 10) - app.convertInternalToOCAclRuleProperties(app.ruleTableMap[aclName][ruleName], aclType, nil, entrySet) - } else { - for ruleName := range app.ruleTableMap[aclName] { - app.convertInternalToOCAclRuleProperties(app.ruleTableMap[aclName][ruleName], aclType, aclSet, nil) - } - } -} - -func (app *AclApp) convertInternalToOCAclRuleProperties(ruleData db.Value, aclType ocbinds.E_OpenconfigAcl_ACL_TYPE, aclSet *ocbinds.OpenconfigAcl_Acl_AclSets_AclSet, entrySet *ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry) { - priority, _ := strconv.ParseInt(ruleData.Get("PRIORITY"), 10, 32) - seqId := uint32(MAX_PRIORITY - priority) - //ruleDescr := ruleData.Get("RULE_DESCRIPTION") - - if entrySet == nil { - if aclSet != nil { - entrySet_, _ := aclSet.AclEntries.NewAclEntry(seqId) - entrySet = entrySet_ - ygot.BuildEmptyTree(entrySet) + // acl table + for key, data := range app.aclTableMap { + existingEntry, err := d.GetEntry(app.aclTs, db.Key{Comp: []string{key}}) + if opcode == CREATE && existingEntry.IsPopulated() { + return tlerr.AlreadyExists("Acl %s already exists", key) } - } - - entrySet.Config.SequenceId = &seqId - //entrySet.Config.Description = &ruleDescr - entrySet.State.SequenceId = &seqId - //entrySet.State.Description = &ruleDescr - - var num uint64 - num = 0 - entrySet.State.MatchedOctets = &num - entrySet.State.MatchedPackets = &num - - ygot.BuildEmptyTree(entrySet.Transport) - ygot.BuildEmptyTree(entrySet.Actions) - - for ruleKey := range ruleData.Field { - if "L4_SRC_PORT" == ruleKey || "L4_SRC_PORT_RANGE" == ruleKey { - port := ruleData.Get(ruleKey) - srcPort := getTransportSrcDestPorts(port, "src") - entrySet.Transport.Config.SourcePort, _ = entrySet.Transport.Config.To_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort_Union(srcPort) - entrySet.Transport.State.SourcePort, _ = entrySet.Transport.State.To_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_State_SourcePort_Union(srcPort) - } else if "L4_DST_PORT" == ruleKey || "L4_DST_PORT_RANGE" == ruleKey { - port := ruleData.Get(ruleKey) - destPort := getTransportSrcDestPorts(port, "dest") - entrySet.Transport.Config.DestinationPort, _ = entrySet.Transport.Config.To_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort_Union(destPort) - entrySet.Transport.State.DestinationPort, _ = entrySet.Transport.State.To_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_State_DestinationPort_Union(destPort) - } else if "TCP_FLAGS" == ruleKey { - tcpFlags := ruleData.Get(ruleKey) - entrySet.Transport.Config.TcpFlags = getTransportConfigTcpFlags(tcpFlags) - entrySet.Transport.State.TcpFlags = getTransportConfigTcpFlags(tcpFlags) - } else if "PACKET_ACTION" == ruleKey { - if "FORWARD" == ruleData.Get(ruleKey) { - entrySet.Actions.Config.ForwardingAction = ocbinds.OpenconfigAcl_FORWARDING_ACTION_ACCEPT - entrySet.Actions.State.ForwardingAction = ocbinds.OpenconfigAcl_FORWARDING_ACTION_ACCEPT + switch opcode { + case CREATE: + err = d.CreateEntry(app.aclTs, db.Key{Comp: []string{key}}, data) + case REPLACE: + if !existingEntry.IsPopulated() { + err = d.CreateEntry(app.aclTs, db.Key{Comp: []string{key}}, data) } else { - entrySet.Actions.Config.ForwardingAction = ocbinds.OpenconfigAcl_FORWARDING_ACTION_DROP - entrySet.Actions.State.ForwardingAction = ocbinds.OpenconfigAcl_FORWARDING_ACTION_DROP - } - } - } - - if aclType == ocbinds.OpenconfigAcl_ACL_TYPE_ACL_IPV4 { - ygot.BuildEmptyTree(entrySet.Ipv4) - for ruleKey := range ruleData.Field { - if "IP_PROTOCOL" == ruleKey { - ipProto, _ := strconv.ParseInt(ruleData.Get(ruleKey), 10, 64) - protocolVal := getIpProtocol(ipProto) - entrySet.Ipv4.Config.Protocol, _ = entrySet.Ipv4.Config.To_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Ipv4_Config_Protocol_Union(protocolVal) - entrySet.Ipv4.State.Protocol, _ = entrySet.Ipv4.State.To_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Ipv4_State_Protocol_Union(protocolVal) - } else if "DSCP" == ruleKey { - var dscp uint8 - dscpData, _ := strconv.ParseInt(ruleData.Get(ruleKey), 10, 64) - dscp = uint8(dscpData) - entrySet.Ipv4.Config.Dscp = &dscp - entrySet.Ipv4.State.Dscp = &dscp - } else if "SRC_IP" == ruleKey { - addr := ruleData.Get(ruleKey) - entrySet.Ipv4.Config.SourceAddress = &addr - entrySet.Ipv4.State.SourceAddress = &addr - } else if "DST_IP" == ruleKey { - addr := ruleData.Get(ruleKey) - entrySet.Ipv4.Config.DestinationAddress = &addr - entrySet.Ipv4.State.DestinationAddress = &addr - } - } - } else if aclType == ocbinds.OpenconfigAcl_ACL_TYPE_ACL_IPV6 { - ygot.BuildEmptyTree(entrySet.Ipv6) - for ruleKey := range ruleData.Field { - if "IP_PROTOCOL" == ruleKey { - ipProto, _ := strconv.ParseInt(ruleData.Get(ruleKey), 10, 64) - protocolVal := getIpProtocol(ipProto) - entrySet.Ipv6.Config.Protocol, _ = entrySet.Ipv6.Config.To_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Ipv6_Config_Protocol_Union(protocolVal) - entrySet.Ipv6.State.Protocol, _ = entrySet.Ipv6.State.To_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Ipv6_State_Protocol_Union(protocolVal) - } else if "DSCP" == ruleKey { - var dscp uint8 - dscpData, _ := strconv.ParseInt(ruleData.Get(ruleKey), 10, 64) - dscp = uint8(dscpData) - entrySet.Ipv6.Config.Dscp = &dscp - entrySet.Ipv6.State.Dscp = &dscp - } else if "SRC_IPV6" == ruleKey { - addr := ruleData.Get(ruleKey) - entrySet.Ipv6.Config.SourceAddress = &addr - entrySet.Ipv6.State.SourceAddress = &addr - } else if "DST_IPV6" == ruleKey { - addr := ruleData.Get(ruleKey) - entrySet.Ipv6.Config.DestinationAddress = &addr - entrySet.Ipv6.State.DestinationAddress = &addr - } - } - } else if aclType == ocbinds.OpenconfigAcl_ACL_TYPE_ACL_L2 { - ygot.BuildEmptyTree(entrySet.L2) - for ruleKey := range ruleData.Field { - if "ETHER_TYPE" == ruleKey { - ethType, _ := strconv.ParseUint(strings.Replace(ruleData.Get(ruleKey), "0x", "", -1), 16, 32) - ethertype := getL2EtherType(ethType) - entrySet.L2.Config.Ethertype, _ = entrySet.L2.Config.To_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_L2_Config_Ethertype_Union(ethertype) - entrySet.L2.State.Ethertype, _ = entrySet.L2.State.To_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_L2_State_Ethertype_Union(ethertype) - } - } - } -} - -func convertInternalToOCAclRuleBinding(d *db.DB, priority uint32, seqId int64, direction string, aclSet ygot.GoStruct, entrySet ygot.GoStruct) { - if seqId == -1 { - seqId = int64(MAX_PRIORITY - priority) - } - - var num uint64 - num = 0 - var ruleId uint32 = uint32(seqId) - - if direction == "INGRESS" { - var ingressEntrySet *ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_IngressAclSets_IngressAclSet_AclEntries_AclEntry - var ok bool - if entrySet == nil { - ingressAclSet := aclSet.(*ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_IngressAclSets_IngressAclSet) - if ingressEntrySet, ok = ingressAclSet.AclEntries.AclEntry[ruleId]; !ok { - ingressEntrySet, _ = ingressAclSet.AclEntries.NewAclEntry(ruleId) - } - } else { - ingressEntrySet = entrySet.(*ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_IngressAclSets_IngressAclSet_AclEntries_AclEntry) - } - if ingressEntrySet != nil { - ygot.BuildEmptyTree(ingressEntrySet) - ingressEntrySet.State.SequenceId = &ruleId - ingressEntrySet.State.MatchedPackets = &num - ingressEntrySet.State.MatchedOctets = &num - } - } else if direction == "EGRESS" { - var egressEntrySet *ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_EgressAclSets_EgressAclSet_AclEntries_AclEntry - var ok bool - if entrySet == nil { - egressAclSet := aclSet.(*ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_EgressAclSets_EgressAclSet) - if egressEntrySet, ok = egressAclSet.AclEntries.AclEntry[ruleId]; !ok { - egressEntrySet, _ = egressAclSet.AclEntries.NewAclEntry(ruleId) - } - } else { - egressEntrySet = entrySet.(*ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_EgressAclSets_EgressAclSet_AclEntries_AclEntry) - } - if egressEntrySet != nil { - ygot.BuildEmptyTree(egressEntrySet) - egressEntrySet.State.SequenceId = &ruleId - egressEntrySet.State.MatchedPackets = &num - egressEntrySet.State.MatchedOctets = &num - } - } -} - -func (app *AclApp) convertInternalToOCAclBinding(d *db.DB, aclName string, intfId string, direction string, intfAclSet ygot.GoStruct) error { - var err error - if _, ok := app.aclTableMap[aclName]; !ok { - aclEntry, err1 := d.GetEntry(app.aclTs, db.Key{Comp: []string{aclName}}) - if err1 != nil { - return err1 - } - if !contains(aclEntry.GetList("ports"), intfId) { - return tlerr.InvalidArgs("Acl %s not binded with %s", aclName, intfId) - } - } - - if _, ok := app.ruleTableMap[aclName]; !ok { - ruleKeys, _ := d.GetKeys(app.ruleTs) - for i, _ := range ruleKeys { - rulekey := ruleKeys[i] - // Rulekey has two keys, first aclkey and second rulename - if rulekey.Get(0) == aclName && rulekey.Get(1) != "DEFAULT_RULE" { - seqId, _ := strconv.Atoi(strings.Replace(rulekey.Get(1), "RULE_", "", 1)) - convertInternalToOCAclRuleBinding(d, 0, int64(seqId), direction, intfAclSet, nil) - } - } - } else { - for ruleName := range app.ruleTableMap[aclName] { - if ruleName != "DEFAULT_RULE" { - seqId, _ := strconv.Atoi(strings.Replace(ruleName, "RULE_", "", 1)) - convertInternalToOCAclRuleBinding(d, 0, int64(seqId), direction, intfAclSet, nil) - } - } - } - - return err -} - -func (app *AclApp) getAllBindingsInfo(d *db.DB) error { - var err error - acl := app.getAppRootObject() - if len(app.aclTableMap) == 0 { - aclKeys, _ := d.GetKeys(app.aclTs) - for i, _ := range aclKeys { - aclEntry, _ := d.GetEntry(app.aclTs, aclKeys[i]) - app.aclTableMap[(aclKeys[i]).Get(0)] = aclEntry - } - } - var interfaces []string - for aclName := range app.aclTableMap { - aclData := app.aclTableMap[aclName] - if len(aclData.Get("ports@")) > 0 { - aclIntfs := aclData.GetList("ports") - for i, _ := range aclIntfs { - if !contains(interfaces, aclIntfs[i]) && aclIntfs[i] != "" { - interfaces = append(interfaces, aclIntfs[i]) - } + // !!! delete & add an entry?? Here just shows the set operation as showcase + err = d.SetEntry(app.aclTs, db.Key{Comp: []string{key}}, data) } + case UPDATE: + err = d.ModEntry(app.aclTs, db.Key{Comp: []string{key}}, data) + case DELETE: + err = d.DeleteKeys(app.aclTs, db.Key{Comp: []string{key}}) } - } - - for _, intfId := range interfaces { - var intfData *ocbinds.OpenconfigAcl_Acl_Interfaces_Interface - intfData, ok := acl.Interfaces.Interface[intfId] - if !ok { - intfData, _ = acl.Interfaces.NewInterface(intfId) + if err != nil { + break } - ygot.BuildEmptyTree(intfData) - err = app.getAclBindingInfoForInterfaceData(d, intfData, intfId, "INGRESS") - err = app.getAclBindingInfoForInterfaceData(d, intfData, intfId, "EGRESS") } - return err -} - -func (app *AclApp) getAclBindingInfoForInterfaceData(d *db.DB, intfData *ocbinds.OpenconfigAcl_Acl_Interfaces_Interface, intfId string, direction string) error { - var err error - if intfData != nil { - intfData.Config.Id = intfData.Id - intfData.State.Id = intfData.Id + // acl rule + if err == nil { + err = handleAclEntry(d, app, opcode) } - if direction == "INGRESS" { - if intfData.IngressAclSets != nil && len(intfData.IngressAclSets.IngressAclSet) > 0 { - for ingressAclSetKey, _ := range intfData.IngressAclSets.IngressAclSet { - aclName := strings.Replace(strings.Replace(ingressAclSetKey.SetName, " ", "_", -1), "-", "_", -1) - aclType := ingressAclSetKey.Type.ΛMap()["E_OpenconfigAcl_ACL_TYPE"][int64(ingressAclSetKey.Type)].Name - aclKey := aclName + "_" + aclType - - ingressAclSet := intfData.IngressAclSets.IngressAclSet[ingressAclSetKey] - if ingressAclSet != nil && ingressAclSet.AclEntries != nil && len(ingressAclSet.AclEntries.AclEntry) > 0 { - for seqId, _ := range ingressAclSet.AclEntries.AclEntry { - rulekey := "RULE_" + strconv.Itoa(int(seqId)) - entrySet := ingressAclSet.AclEntries.AclEntry[seqId] - _, err := d.GetEntry(app.ruleTs, db.Key{Comp: []string{aclKey, rulekey}}) - if err != nil { - return err - } - convertInternalToOCAclRuleBinding(d, 0, int64(seqId), direction, nil, entrySet) - } - } else { - ygot.BuildEmptyTree(ingressAclSet) - ingressAclSet.Config = &ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_IngressAclSets_IngressAclSet_Config{SetName: &aclName, Type: ingressAclSetKey.Type} - ingressAclSet.State = &ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_IngressAclSets_IngressAclSet_State{SetName: &aclName, Type: ingressAclSetKey.Type} - err = app.convertInternalToOCAclBinding(d, aclKey, intfId, direction, ingressAclSet) - } - } - } else { - err = app.findAndGetAclBindingInfoForInterfaceData(d, intfId, direction, intfData) - } - } else if direction == "EGRESS" { - if intfData.EgressAclSets != nil && len(intfData.EgressAclSets.EgressAclSet) > 0 { - for egressAclSetKey, _ := range intfData.EgressAclSets.EgressAclSet { - aclName := strings.Replace(strings.Replace(egressAclSetKey.SetName, " ", "_", -1), "-", "_", -1) - aclType := egressAclSetKey.Type.ΛMap()["E_OpenconfigAcl_ACL_TYPE"][int64(egressAclSetKey.Type)].Name - aclKey := aclName + "_" + aclType - egressAclSet := intfData.EgressAclSets.EgressAclSet[egressAclSetKey] - if egressAclSet != nil && egressAclSet.AclEntries != nil && len(egressAclSet.AclEntries.AclEntry) > 0 { - for seqId, _ := range egressAclSet.AclEntries.AclEntry { - rulekey := "RULE_" + strconv.Itoa(int(seqId)) - entrySet := egressAclSet.AclEntries.AclEntry[seqId] - _, err := d.GetEntry(app.ruleTs, db.Key{Comp: []string{aclKey, rulekey}}) - if err != nil { - return err - } - convertInternalToOCAclRuleBinding(d, 0, int64(seqId), direction, nil, entrySet) - } - } else { - ygot.BuildEmptyTree(egressAclSet) - egressAclSet.Config = &ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_EgressAclSets_EgressAclSet_Config{SetName: &aclName, Type: egressAclSetKey.Type} - egressAclSet.State = &ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_EgressAclSets_EgressAclSet_State{SetName: &aclName, Type: egressAclSetKey.Type} - err = app.convertInternalToOCAclBinding(d, aclKey, intfId, direction, egressAclSet) - } - } - } else { - err = app.findAndGetAclBindingInfoForInterfaceData(d, intfId, direction, intfData) - } - } else { - log.Error("Unknown direction") - } return err } - -func (app *AclApp) findAndGetAclBindingInfoForInterfaceData(d *db.DB, intfId string, direction string, intfData *ocbinds.OpenconfigAcl_Acl_Interfaces_Interface) error { +func handleAclEntry(d *db.DB, app *AclApp, opcode int) error { var err error - if len(app.aclTableMap) == 0 { - aclKeys, _ := d.GetKeys(app.aclTs) - for i, _ := range aclKeys { - aclEntry, _ := d.GetEntry(app.aclTs, aclKeys[i]) - app.aclTableMap[aclKeys[i].Get(0)] = aclEntry - } - } - - for aclName, _ := range app.aclTableMap { - aclData := app.aclTableMap[aclName] - aclIntfs := aclData.GetList("ports") - aclType := aclData.Get(ACL_TYPE) - var aclOrigName string - var aclOrigType ocbinds.E_OpenconfigAcl_ACL_TYPE - if SONIC_ACL_TYPE_IPV4 == aclType { - aclOrigName = strings.Replace(aclName, "_"+OPENCONFIG_ACL_TYPE_IPV4, "", 1) - aclOrigType = ocbinds.OpenconfigAcl_ACL_TYPE_ACL_IPV4 - } else if SONIC_ACL_TYPE_IPV6 == aclType { - aclOrigName = strings.Replace(aclName, "_"+OPENCONFIG_ACL_TYPE_IPV6, "", 1) - aclOrigType = ocbinds.OpenconfigAcl_ACL_TYPE_ACL_IPV6 - } else if SONIC_ACL_TYPE_L2 == aclType { - aclOrigName = strings.Replace(aclName, "_"+OPENCONFIG_ACL_TYPE_L2, "", 1) - aclOrigType = ocbinds.OpenconfigAcl_ACL_TYPE_ACL_L2 - } - - if contains(aclIntfs, intfId) && direction == aclData.Get("stage") { - if direction == "INGRESS" { - if intfData.IngressAclSets != nil { - aclSetKey := ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_IngressAclSets_IngressAclSet_Key{SetName: aclOrigName, Type: aclOrigType} - ingressAclSet, ok := intfData.IngressAclSets.IngressAclSet[aclSetKey] - if !ok { - ingressAclSet, _ = intfData.IngressAclSets.NewIngressAclSet(aclOrigName, aclOrigType) - ygot.BuildEmptyTree(ingressAclSet) - ingressAclSet.Config = &ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_IngressAclSets_IngressAclSet_Config{SetName: &aclOrigName, Type: aclOrigType} - ingressAclSet.State = &ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_IngressAclSets_IngressAclSet_State{SetName: &aclOrigName, Type: aclOrigType} - } - err = app.convertInternalToOCAclBinding(d, aclName, intfId, direction, ingressAclSet) - if err != nil { - return err - } - } - } else if direction == "EGRESS" { - if intfData.EgressAclSets != nil { - aclSetKey := ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_EgressAclSets_EgressAclSet_Key{SetName: aclOrigName, Type: aclOrigType} - egressAclSet, ok := intfData.EgressAclSets.EgressAclSet[aclSetKey] - if !ok { - egressAclSet, _ = intfData.EgressAclSets.NewEgressAclSet(aclOrigName, aclOrigType) - ygot.BuildEmptyTree(egressAclSet) - egressAclSet.Config = &ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_EgressAclSets_EgressAclSet_Config{SetName: &aclOrigName, Type: aclOrigType} - egressAclSet.State = &ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_EgressAclSets_EgressAclSet_State{SetName: &aclOrigName, Type: aclOrigType} - } - err = app.convertInternalToOCAclBinding(d, aclName, intfId, direction, egressAclSet) - if err != nil { - return err - } - } - } - } - } - return err -} - -/*func (app *AclApp) isInterfaceBindWithACL(d *db.DB, intfId string) bool { - var isFound bool = false - if len(app.aclTableMap) == 0 { - aclKeys, _ := d.GetKeys(app.aclTs) - for i, _ := range aclKeys { - aclEntry, _ := d.GetEntry(app.aclTs, aclKeys[i]) - app.aclTableMap[(aclKeys[i]).Get(0)] = aclEntry + for key, data := range app.ruleTableMap { + ruleName := strings.Split(key, KEY_SEPARATOR)[1] + existingEntry, err := d.GetEntry(app.ruleTs, db.Key{Comp: []string{key}}) + if opcode == CREATE && existingEntry.IsPopulated() { + return tlerr.AlreadyExists("Acl rule %s already exists", ruleName) } - } - - var interfaces []string - for aclName := range app.aclTableMap { - aclData := app.aclTableMap[aclName] - if len(aclData.Get("ports@")) > 0 { - aclIntfs := aclData.GetList("ports") - for i, _ := range aclIntfs { - if !contains(interfaces, aclIntfs[i]) && aclIntfs[i] != "" { - interfaces = append(interfaces, aclIntfs[i]) - } - } - } - } - - isFound = contains(interfaces, intfId) - return isFound -}*/ - -func (app *AclApp) handleBindingsDeletion(d *db.DB) error { - var err error - - acl := app.getAppRootObject() - aclKeys, _ := d.GetKeys(app.aclTs) - for i, _ := range aclKeys { - aclEntry, _ := d.GetEntry(app.aclTs, aclKeys[i]) - var isRequestedAclFound = false - if len(aclEntry.GetList("ports")) > 0 { - if isSubtreeRequest(app.pathInfo.Template, "/openconfig-acl:acl/interfaces/interface{}") { - direction := aclEntry.Get("stage") - if isSubtreeRequest(app.pathInfo.Template, "/openconfig-acl:acl/interfaces/interface{}/ingress-acl-sets") && direction != "INGRESS" { - return tlerr.InvalidArgs("Acl %s is not Ingress", aclKeys[i].Get(0)) - } - if isSubtreeRequest(app.pathInfo.Template, "/openconfig-acl:acl/interfaces/interface{}/egress-acl-sets") && direction != "EGRESS" { - return tlerr.InvalidArgs("Acl %s is not Egress", aclKeys[i].Get(0)) - } - for intfId := range acl.Interfaces.Interface { - aclname, acltype := getAclKeysFromStrKey(aclKeys[i].Get(0), aclEntry.Get("type")) - intfData := acl.Interfaces.Interface[intfId] - if isSubtreeRequest(app.pathInfo.Template, "/openconfig-acl:acl/interfaces/interface{}/ingress-acl-sets/ingress-acl-set{}{}") { - for k := range intfData.IngressAclSets.IngressAclSet { - if aclname == k.SetName { - if acltype == k.Type { - isRequestedAclFound = true - } else { - return tlerr.InvalidArgs("Acl Type is not matching") - } - } else { - goto SkipDBProcessing - } - } - } else if isSubtreeRequest(app.pathInfo.Template, "/openconfig-acl:acl/interfaces/interface{}/egress-acl-sets/egress-acl-set{}{}") { - for k := range intfData.EgressAclSets.EgressAclSet { - if aclname == k.SetName { - if acltype == k.Type { - isRequestedAclFound = true - } else { - return tlerr.InvalidArgs("Acl Type is not matching") - } - } else { - goto SkipDBProcessing - } - } - } - intfs := aclEntry.GetList("ports") - intfs = removeElement(intfs, intfId) - aclEntry.SetList("ports", intfs) - err = d.SetEntry(app.aclTs, aclKeys[i], aclEntry) - if err != nil { - return err - } - // If last interface removed, then remove stage field also - if len(intfs) == 0 { - aclEntry.Remove("stage") - } - } - SkipDBProcessing: + switch opcode { + case CREATE: + err = d.CreateEntry(app.ruleTs, db.Key{Comp: []string{key}}, data) + case REPLACE: + if !existingEntry.IsPopulated() { + err = d.CreateEntry(app.ruleTs, db.Key{Comp: []string{key}}, data) } else { - aclEntry.Remove("stage") - aclEntry.SetList("ports", []string{}) - err = d.SetEntry(app.aclTs, aclKeys[i], aclEntry) - if err != nil { - return err - } + // !!! delete & add an entry?? Here just shows the merge operation as showcase + err = d.SetEntry(app.ruleTs, db.Key{Comp: []string{key}}, data) } + case UPDATE: + err = d.ModEntry(app.ruleTs, db.Key{Comp: []string{key}}, data) + case DELETE: + err = d.DeleteKeys(app.ruleTs, db.Key{Comp: []string{key}}) } - if isRequestedAclFound { + if err != nil { break } } - return err } - -/******************** CREATE related *******************************/ -func (app *AclApp) convertOCAclsToInternal() { - acl := app.getAppRootObject() - if acl != nil { - app.aclTableMap = make(map[string]db.Value) - if acl.AclSets != nil && len(acl.AclSets.AclSet) > 0 { - for aclSetKey, _ := range acl.AclSets.AclSet { - aclSet := acl.AclSets.AclSet[aclSetKey] - aclKey := getAclKeyStrFromOCKey(aclSetKey.Name, aclSetKey.Type) - app.aclTableMap[aclKey] = db.Value{Field: map[string]string{}} - - if aclSet.Config != nil { - if aclSet.Config.Type == ocbinds.OpenconfigAcl_ACL_TYPE_ACL_IPV4 { - app.aclTableMap[aclKey].Field[ACL_TYPE] = SONIC_ACL_TYPE_IPV4 - } else if aclSet.Config.Type == ocbinds.OpenconfigAcl_ACL_TYPE_ACL_IPV6 { - app.aclTableMap[aclKey].Field[ACL_TYPE] = SONIC_ACL_TYPE_IPV6 - } else if aclSet.Config.Type == ocbinds.OpenconfigAcl_ACL_TYPE_ACL_L2 { - app.aclTableMap[aclKey].Field[ACL_TYPE] = SONIC_ACL_TYPE_L2 - } - - if aclSet.Config.Description != nil && len(*aclSet.Config.Description) > 0 { - app.aclTableMap[aclKey].Field[ACL_DESCRIPTION] = *aclSet.Config.Description - } - } - } - } - } -} - -func (app *AclApp) convertOCAclRulesToInternal(d *db.DB) { - acl := app.getAppRootObject() - if acl != nil { - app.ruleTableMap = make(map[string]map[string]db.Value) - if acl.AclSets != nil && len(acl.AclSets.AclSet) > 0 { - for aclSetKey, _ := range acl.AclSets.AclSet { - aclSet := acl.AclSets.AclSet[aclSetKey] - aclKey := getAclKeyStrFromOCKey(aclSetKey.Name, aclSetKey.Type) - app.ruleTableMap[aclKey] = make(map[string]db.Value) - - if aclSet.AclEntries != nil { - for seqId, _ := range aclSet.AclEntries.AclEntry { - entrySet := aclSet.AclEntries.AclEntry[seqId] - ruleName := "RULE_" + strconv.Itoa(int(seqId)) - app.ruleTableMap[aclKey][ruleName] = db.Value{Field: map[string]string{}} - convertOCAclRuleToInternalAclRule(app.ruleTableMap[aclKey][ruleName], seqId, aclKey, aclSet.Type, entrySet) - } - } - - yangPathStr, _ := getYangPathFromUri(app.pathInfo.Path) - if yangPathStr != "/openconfig-acl:acl/acl-sets/acl-set/acl-entries" && yangPathStr != "/openconfig-acl:acl/acl-sets/acl-set/acl-entries/acl-entry" { - app.createDefaultDenyAclRule(d, aclKey, app.ruleTableMap[aclKey]) - } - } - } - } -} - -func (app *AclApp) convertOCAclBindingsToInternal() { - aclObj := app.getAppRootObject() - - if aclObj.Interfaces != nil && len(aclObj.Interfaces.Interface) > 0 { - aclInterfacesMap := make(map[string][]string) - // Below code assumes that an ACL can be either INGRESS or EGRESS but not both. - for intfId, _ := range aclObj.Interfaces.Interface { - intf := aclObj.Interfaces.Interface[intfId] - if intf != nil { - if intf.IngressAclSets != nil && len(intf.IngressAclSets.IngressAclSet) > 0 { - for inAclKey, _ := range intf.IngressAclSets.IngressAclSet { - aclName := getAclKeyStrFromOCKey(inAclKey.SetName, inAclKey.Type) - // TODO: Need to handle Subinterface also - if intf.InterfaceRef != nil && intf.InterfaceRef.Config.Interface != nil { - aclInterfacesMap[aclName] = append(aclInterfacesMap[aclName], *intf.InterfaceRef.Config.Interface) - } else { - aclInterfacesMap[aclName] = append(aclInterfacesMap[aclName], *intf.Id) - } - if len(app.aclTableMap) == 0 { - app.aclTableMap[aclName] = db.Value{Field: map[string]string{}} - } - app.aclTableMap[aclName].Field["stage"] = "INGRESS" - } - } - - if intf.EgressAclSets != nil && len(intf.EgressAclSets.EgressAclSet) > 0 { - for outAclKey, _ := range intf.EgressAclSets.EgressAclSet { - aclName := getAclKeyStrFromOCKey(outAclKey.SetName, outAclKey.Type) - if intf.InterfaceRef != nil && intf.InterfaceRef.Config.Interface != nil { - aclInterfacesMap[aclName] = append(aclInterfacesMap[aclName], *intf.InterfaceRef.Config.Interface) - } else { - aclInterfacesMap[aclName] = append(aclInterfacesMap[aclName], *intf.Id) - } - if len(app.aclTableMap) == 0 { - app.aclTableMap[aclName] = db.Value{Field: map[string]string{}} - } - app.aclTableMap[aclName].Field["stage"] = "EGRESS" - } - } - } - } - for k, _ := range aclInterfacesMap { - val := app.aclTableMap[k] - (&val).SetList("ports", aclInterfacesMap[k]) - } - } -} - -func (app *AclApp) createDefaultDenyAclRule(d *db.DB, aclName string, rulesInfo map[string]db.Value) { - existingRuleEntry, err := d.GetEntry(app.ruleTs, db.Key{Comp: []string{aclName, "DEFAULT_RULE"}}) - // If Default Rule already exists, Do not add new Default Rule - if existingRuleEntry.IsPopulated() && err == nil { - return - } - m := make(map[string]string) - rulesInfo["DEFAULT_RULE"] = db.Value{Field: m} - rulesInfo["DEFAULT_RULE"].Field["PRIORITY"] = strconv.FormatInt(int64(MIN_PRIORITY), 10) - rulesInfo["DEFAULT_RULE"].Field["PACKET_ACTION"] = "DROP" -} - -func convertOCAclRuleToInternalAclRule(ruleData db.Value, seqId uint32, aclName string, aclType ocbinds.E_OpenconfigAcl_ACL_TYPE, rule *ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry) { - ruleIndex := seqId - ruleData.Field["PRIORITY"] = strconv.FormatInt(int64(MAX_PRIORITY-ruleIndex), 10) - // Rule Description is not supported in Sonic. So commenting this out. - /* - if rule.Config != nil && rule.Config.Description != nil { - ruleData.Field["RULE_DESCRIPTION"] = *rule.Config.Description - } - */ - - if ocbinds.OpenconfigAcl_ACL_TYPE_ACL_IPV4 == aclType { - convertOCToInternalIPv4(ruleData, aclName, ruleIndex, rule) - } else if ocbinds.OpenconfigAcl_ACL_TYPE_ACL_IPV6 == aclType { - convertOCToInternalIPv6(ruleData, aclName, ruleIndex, rule) - } else if ocbinds.OpenconfigAcl_ACL_TYPE_ACL_L2 == aclType { - convertOCToInternalL2(ruleData, aclName, ruleIndex, rule) - } /*else if ocbinds.OpenconfigAcl_ACL_TYPE_ACL_MIXED == aclType { - } */ - - convertOCToInternalTransport(ruleData, aclName, ruleIndex, rule) - convertOCToInternalInputInterface(ruleData, aclName, ruleIndex, rule) - convertOCToInternalInputAction(ruleData, aclName, ruleIndex, rule) -} - -func convertOCToInternalL2(ruleData db.Value, aclName string, ruleIndex uint32, rule *ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry) { - if rule.L2 == nil { - return - } - if rule.L2.Config.Ethertype != nil && util.IsTypeStructPtr(reflect.TypeOf(rule.L2.Config.Ethertype)) { - ethertypeType := reflect.TypeOf(rule.L2.Config.Ethertype).Elem() - var b bytes.Buffer - switch ethertypeType { - case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_L2_Config_Ethertype_Union_E_OpenconfigPacketMatchTypes_ETHERTYPE{}): - v := (rule.L2.Config.Ethertype).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_L2_Config_Ethertype_Union_E_OpenconfigPacketMatchTypes_ETHERTYPE) - //ruleData["ETHER_TYPE"] = v.E_OpenconfigPacketMatchTypes_ETHERTYPE.ΛMap()["E_OpenconfigPacketMatchTypes_ETHERTYPE"][int64(v.E_OpenconfigPacketMatchTypes_ETHERTYPE)].Name - fmt.Fprintf(&b, "0x%0.4x", ETHERTYPE_MAP[v.E_OpenconfigPacketMatchTypes_ETHERTYPE]) - ruleData.Field["ETHER_TYPE"] = b.String() - case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_L2_Config_Ethertype_Union_Uint16{}): - v := (rule.L2.Config.Ethertype).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_L2_Config_Ethertype_Union_Uint16) - fmt.Fprintf(&b, "0x%0.4x", v.Uint16) - ruleData.Field["ETHER_TYPE"] = b.String() - } - } -} - -func convertOCToInternalIPv4(ruleData db.Value, aclName string, ruleIndex uint32, rule *ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry) { - if rule.Ipv4.Config.Protocol != nil && util.IsTypeStructPtr(reflect.TypeOf(rule.Ipv4.Config.Protocol)) { - protocolType := reflect.TypeOf(rule.Ipv4.Config.Protocol).Elem() - switch protocolType { - case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Ipv4_Config_Protocol_Union_E_OpenconfigPacketMatchTypes_IP_PROTOCOL{}): - v := (rule.Ipv4.Config.Protocol).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Ipv4_Config_Protocol_Union_E_OpenconfigPacketMatchTypes_IP_PROTOCOL) - //ruleData["IP_PROTOCOL"] = v.E_OpenconfigPacketMatchTypes_IP_PROTOCOL.ΛMap()["E_OpenconfigPacketMatchTypes_IP_PROTOCOL"][int64(v.E_OpenconfigPacketMatchTypes_IP_PROTOCOL)].Name - ruleData.Field["IP_PROTOCOL"] = strconv.FormatInt(int64(IP_PROTOCOL_MAP[v.E_OpenconfigPacketMatchTypes_IP_PROTOCOL]), 10) - case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Ipv4_Config_Protocol_Union_Uint8{}): - v := (rule.Ipv4.Config.Protocol).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Ipv4_Config_Protocol_Union_Uint8) - ruleData.Field["IP_PROTOCOL"] = strconv.FormatInt(int64(v.Uint8), 10) - } - } - - if rule.Ipv4.Config.Dscp != nil { - ruleData.Field["DSCP"] = strconv.FormatInt(int64(*rule.Ipv4.Config.Dscp), 10) - } - if rule.Ipv4.Config.SourceAddress != nil { - ruleData.Field["SRC_IP"] = *rule.Ipv4.Config.SourceAddress - } - if rule.Ipv4.Config.DestinationAddress != nil { - ruleData.Field["DST_IP"] = *rule.Ipv4.Config.DestinationAddress - } -} - -func convertOCToInternalIPv6(ruleData db.Value, aclName string, ruleIndex uint32, rule *ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry) { - if rule.Ipv6.Config.Protocol != nil && util.IsTypeStructPtr(reflect.TypeOf(rule.Ipv6.Config.Protocol)) { - protocolType := reflect.TypeOf(rule.Ipv6.Config.Protocol).Elem() - switch protocolType { - case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Ipv6_Config_Protocol_Union_E_OpenconfigPacketMatchTypes_IP_PROTOCOL{}): - v := (rule.Ipv6.Config.Protocol).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Ipv6_Config_Protocol_Union_E_OpenconfigPacketMatchTypes_IP_PROTOCOL) - //ruleData["IP_PROTOCOL"] = v.E_OpenconfigPacketMatchTypes_IP_PROTOCOL.ΛMap()["E_OpenconfigPacketMatchTypes_IP_PROTOCOL"][int64(v.E_OpenconfigPacketMatchTypes_IP_PROTOCOL)].Name - ruleData.Field["IP_PROTOCOL"] = strconv.FormatInt(int64(IP_PROTOCOL_MAP[v.E_OpenconfigPacketMatchTypes_IP_PROTOCOL]), 10) - case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Ipv6_Config_Protocol_Union_Uint8{}): - v := (rule.Ipv6.Config.Protocol).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Ipv6_Config_Protocol_Union_Uint8) - ruleData.Field["IP_PROTOCOL"] = strconv.FormatInt(int64(v.Uint8), 10) - } - } - - if rule.Ipv6.Config.Dscp != nil { - ruleData.Field["DSCP"] = strconv.FormatInt(int64(*rule.Ipv6.Config.Dscp), 10) - } - if rule.Ipv6.Config.SourceAddress != nil { - ruleData.Field["SRC_IPV6"] = *rule.Ipv6.Config.SourceAddress - } - if rule.Ipv6.Config.DestinationAddress != nil { - ruleData.Field["DST_IPV6"] = *rule.Ipv6.Config.DestinationAddress - } - if rule.Ipv6.Config.SourceFlowLabel != nil { - ruleData.Field["SRC_FLOWLABEL"] = strconv.FormatInt(int64(*rule.Ipv6.Config.SourceFlowLabel), 10) - } - if rule.Ipv6.Config.DestinationFlowLabel != nil { - ruleData.Field["DST_FLOWLABEL"] = strconv.FormatInt(int64(*rule.Ipv6.Config.DestinationFlowLabel), 10) - } -} - -func convertOCToInternalTransport(ruleData db.Value, aclName string, ruleIndex uint32, rule *ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry) { - if rule.Transport == nil { - return - } - if rule.Transport.Config.SourcePort != nil && util.IsTypeStructPtr(reflect.TypeOf(rule.Transport.Config.SourcePort)) { - sourceportType := reflect.TypeOf(rule.Transport.Config.SourcePort).Elem() - switch sourceportType { - case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort_Union_E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort{}): - v := (rule.Transport.Config.SourcePort).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort_Union_E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort) - ruleData.Field["L4_SRC_PORT"] = v.E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort.ΛMap()["E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort"][int64(v.E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort)].Name - case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort_Union_String{}): - v := (rule.Transport.Config.SourcePort).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort_Union_String) - ruleData.Field["L4_SRC_PORT_RANGE"] = strings.Replace(v.String, "..", "-", 1) - case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort_Union_Uint16{}): - v := (rule.Transport.Config.SourcePort).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort_Union_Uint16) - ruleData.Field["L4_SRC_PORT"] = strconv.FormatInt(int64(v.Uint16), 10) - } - } - - if rule.Transport.Config.DestinationPort != nil && util.IsTypeStructPtr(reflect.TypeOf(rule.Transport.Config.DestinationPort)) { - destportType := reflect.TypeOf(rule.Transport.Config.DestinationPort).Elem() - switch destportType { - case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort_Union_E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort{}): - v := (rule.Transport.Config.DestinationPort).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort_Union_E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort) - ruleData.Field["L4_DST_PORT"] = v.E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort.ΛMap()["E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort"][int64(v.E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort)].Name - case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort_Union_String{}): - v := (rule.Transport.Config.DestinationPort).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort_Union_String) - ruleData.Field["L4_DST_PORT_RANGE"] = strings.Replace(v.String, "..", "-", 1) - case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort_Union_Uint16{}): - v := (rule.Transport.Config.DestinationPort).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort_Union_Uint16) - ruleData.Field["L4_DST_PORT"] = strconv.FormatInt(int64(v.Uint16), 10) - } - } - - var tcpFlags uint32 = 0x00 - if len(rule.Transport.Config.TcpFlags) > 0 { - for _, flag := range rule.Transport.Config.TcpFlags { - switch flag { - case ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_FIN: - tcpFlags |= 0x01 - case ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_SYN: - tcpFlags |= 0x02 - case ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_RST: - tcpFlags |= 0x04 - case ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_PSH: - tcpFlags |= 0x08 - case ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_ACK: - tcpFlags |= 0x10 - case ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_URG: - tcpFlags |= 0x20 - case ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_ECE: - tcpFlags |= 0x40 - case ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_CWR: - tcpFlags |= 0x80 - } - } - var b bytes.Buffer - fmt.Fprintf(&b, "0x%0.2x/0x%0.2x", tcpFlags, tcpFlags) - ruleData.Field["TCP_FLAGS"] = b.String() - } -} - -func convertOCToInternalInputInterface(ruleData db.Value, aclName string, ruleIndex uint32, rule *ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry) { - if rule.InputInterface != nil && rule.InputInterface.InterfaceRef != nil { - ruleData.Field["IN_PORTS"] = *rule.InputInterface.InterfaceRef.Config.Interface - } -} - -func convertOCToInternalInputAction(ruleData db.Value, aclName string, ruleIndex uint32, rule *ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry) { - if rule.Actions != nil && rule.Actions.Config != nil { - switch rule.Actions.Config.ForwardingAction { - case ocbinds.OpenconfigAcl_FORWARDING_ACTION_ACCEPT: - ruleData.Field["PACKET_ACTION"] = "FORWARD" - case ocbinds.OpenconfigAcl_FORWARDING_ACTION_DROP, ocbinds.OpenconfigAcl_FORWARDING_ACTION_REJECT: - ruleData.Field["PACKET_ACTION"] = "DROP" - default: - } - } -} - -func (app *AclApp) setAclDataInConfigDb(d *db.DB, aclData map[string]db.Value, createFlag bool) error { +func handleAcl(d *db.DB, app *AclApp, opcode int) error { var err error - for key := range aclData { - existingEntry, err := d.GetEntry(app.aclTs, db.Key{Comp: []string{key}}) - // If Create ACL request comes and ACL already exists, throw error - if createFlag && existingEntry.IsPopulated() { - return tlerr.AlreadyExists("Acl %s already exists", key) - } - if createFlag || (!createFlag && err != nil && !existingEntry.IsPopulated()) { - err := d.CreateEntry(app.aclTs, db.Key{Comp: []string{key}}, aclData[key]) - if err != nil { - return err - } - } else { - if existingEntry.IsPopulated() { - if existingEntry.Get(ACL_DESCRIPTION) != aclData[key].Field[ACL_DESCRIPTION] { - err := d.ModEntry(app.aclTs, db.Key{Comp: []string{key}}, aclData[key]) - if err != nil { - return err - } - } - } - } + //err = app.processCommonToplevelPath(d, acl, opcode, true) + err = handleAclSet(d, app, opcode) + if err == nil { + err = handleAclInterface(d, app, opcode) } return err } -func (app *AclApp) setAclRuleDataInConfigDb(d *db.DB, ruleData map[string]map[string]db.Value, createFlag bool) error { - var err error - for aclName := range ruleData { - for ruleName := range ruleData[aclName] { - existingRuleEntry, err := d.GetEntry(app.ruleTs, db.Key{Comp: []string{aclName, ruleName}}) - // If Create Rule request comes and Rule already exists, throw error - if createFlag && existingRuleEntry.IsPopulated() { - return tlerr.AlreadyExists("Rule %s already exists", ruleName) - } - if createFlag || (!createFlag && err != nil && !existingRuleEntry.IsPopulated()) { - err := d.CreateEntry(app.ruleTs, db.Key{Comp: []string{aclName, ruleName}}, ruleData[aclName][ruleName]) - if err != nil { - return err - } - } else { - if existingRuleEntry.IsPopulated() && ruleName != "DEFAULT_RULE" { - err := d.ModEntry(app.ruleTs, db.Key{Comp: []string{aclName, ruleName}}, ruleData[aclName][ruleName]) - if err != nil { - return err - } - } - } - } - } - return err -} - -func (app *AclApp) setAclBindDataInConfigDb(d *db.DB, aclData map[string]db.Value, opcode int) error { +func (app *AclApp) processCommon(d *db.DB, opcode int) error { var err error - for aclKey, aclInfo := range aclData { - // Get ACL info from DB - dbAcl, err := d.GetEntry(app.aclTs, db.Key{Comp: []string{aclKey}}) - if err != nil { - return err - } - if REPLACE == opcode { - dbAcl.SetList("ports", aclInfo.GetList("ports")) - dbAcl.Set("stage", aclInfo.Get("stage")) - } else { - dbAclIntfs := dbAcl.GetList("ports") - if len(dbAclIntfs) > 0 { - // Merge interfaces from DB to list in aclInfo and set back in DB - intfs := aclInfo.GetList("ports") - for _, ifId := range dbAclIntfs { - if !contains(intfs, ifId) { - intfs = append(intfs, ifId) - } - } - dbAcl.SetList("ports", intfs) - } else { - dbAcl.SetList("ports", aclInfo.GetList("ports")) - } - if len(dbAcl.Get("stage")) == 0 { - dbAcl.Set("stage", aclInfo.Get("stage")) - } - } - err = d.SetEntry(app.aclTs, db.Key{Comp: []string{aclKey}}, dbAcl) - //err = d.ModEntry(app.aclTs, db.Key{Comp: []string{aclKey}}, dbAcl) - if err != nil { - return err - } - } - return err -} - -func getIpProtocol(proto int64) interface{} { - for k, v := range IP_PROTOCOL_MAP { - if uint8(proto) == v { - return k - } - } - return uint8(proto) -} + log.Infof("processCommon--Path Received: %s", app.pathInfo.Template) + // test + d.Opts.DisableCVLCheck = true -func getTransportSrcDestPorts(portVal string, portType string) interface{} { - var portRange string = "" + targetType := reflect.TypeOf(*app.ygotTarget) - portNum, err := strconv.Atoi(portVal) - if err != nil && strings.Contains(portVal, "-") { - portRange = portVal + xpath, err := RemoveXPATHPredicates(app.pathInfo.Path) + if err != nil { + log.Errorf("processCommon: Failed to remove Xpath Predicates from path %s", app.pathInfo.Template) } - if len(portRange) > 0 { - return portRange - } else if portNum > 0 { - return uint16(portNum) - } else { - if "src" == portType { - return ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort_ANY - } else if "dest" == portType { - return ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort_ANY + if _, ok := app.callpoints[xpath]; ok { + if err = app.callpoints[xpath](d, app, opcode); err != nil { + log.Errorf("processCommon: Given path %s not handled", app.pathInfo.Template) } - } - return nil -} - -func getTransportConfigTcpFlags(tcpFlags string) []ocbinds.E_OpenconfigPacketMatchTypes_TCP_FLAGS { - var flags []ocbinds.E_OpenconfigPacketMatchTypes_TCP_FLAGS - if len(tcpFlags) > 0 { - flagStr := strings.Split(tcpFlags, "/")[0] - flagNumber, _ := strconv.ParseUint(strings.Replace(flagStr, "0x", "", -1), 16, 32) - for i := 0; i < 8; i++ { - mask := 1 << uint(i) - if (int(flagNumber) & mask) > 0 { - switch int(flagNumber) & mask { - case 0x01: - flags = append(flags, ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_FIN) - case 0x02: - flags = append(flags, ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_SYN) - case 0x04: - flags = append(flags, ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_RST) - case 0x08: - flags = append(flags, ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_PSH) - case 0x10: - flags = append(flags, ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_ACK) - case 0x20: - flags = append(flags, ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_URG) - case 0x40: - flags = append(flags, ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_ECE) - case 0x80: - flags = append(flags, ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_CWR) - default: - } - } + } else { + // fallback callpoints + if strings.Contains(xpath, "/openconfig-acl:acl/acl-sets/acl-set/acl-entries/acl-entry") { + err = handleAclEntry(d, app, opcode) + } else if strings.Contains(targetType.Elem().Name(), "/openconfig-acl:acl/interfaces") { + err = handleAclInterface(d, app, opcode) } - } - return flags -} - -func getL2EtherType(etherType uint64) interface{} { - for k, v := range ETHERTYPE_MAP { - if uint32(etherType) == v { - return k + if err == nil { + err = tlerr.NotSupported("URL %s is not supported", app.pathInfo.Template) } } - return uint16(etherType) -} - -func getAclKeysFromStrKey(aclKey string, aclType string) (string, ocbinds.E_OpenconfigAcl_ACL_TYPE) { - var aclOrigName string - var aclOrigType ocbinds.E_OpenconfigAcl_ACL_TYPE - - if SONIC_ACL_TYPE_IPV4 == aclType { - aclOrigName = strings.Replace(aclKey, "_"+OPENCONFIG_ACL_TYPE_IPV4, "", 1) - aclOrigType = ocbinds.OpenconfigAcl_ACL_TYPE_ACL_IPV4 - } else if SONIC_ACL_TYPE_IPV6 == aclType { - aclOrigName = strings.Replace(aclKey, "_"+OPENCONFIG_ACL_TYPE_IPV6, "", 1) - aclOrigType = ocbinds.OpenconfigAcl_ACL_TYPE_ACL_IPV6 - } else if SONIC_ACL_TYPE_L2 == aclType { - aclOrigName = strings.Replace(aclKey, "_"+OPENCONFIG_ACL_TYPE_L2, "", 1) - aclOrigType = ocbinds.OpenconfigAcl_ACL_TYPE_ACL_L2 - } - return aclOrigName, aclOrigType -} - -// getAclTypeOCEnumFromName returns the ACL_TYPE enum from name -func getAclTypeOCEnumFromName(val string) (ocbinds.E_OpenconfigAcl_ACL_TYPE, error) { - switch val { - case "ACL_IPV4", "openconfig-acl:ACL_IPV4": - return ocbinds.OpenconfigAcl_ACL_TYPE_ACL_IPV4, nil - case "ACL_IPV6", "openconfig-acl:ACL_IPV6": - return ocbinds.OpenconfigAcl_ACL_TYPE_ACL_IPV6, nil - case "ACL_L2", "openconfig-acl:ACL_L2": - return ocbinds.OpenconfigAcl_ACL_TYPE_ACL_L2, nil - default: - return ocbinds.OpenconfigAcl_ACL_TYPE_UNSET, - tlerr.NotSupported("ACL Type '%s' not supported", val) - } -} -func getAclKeyStrFromOCKey(aclname string, acltype ocbinds.E_OpenconfigAcl_ACL_TYPE) string { - aclN := strings.Replace(strings.Replace(aclname, " ", "_", -1), "-", "_", -1) - aclT := acltype.ΛMap()["E_OpenconfigAcl_ACL_TYPE"][int64(acltype)].Name - return aclN + "_" + aclT -} - -/* Check if targetUriPath is child (subtree) of nodePath -The return value can be used to decide if subtrees needs -to visited to fill the data or not. -*/ -func isSubtreeRequest(targetUriPath string, nodePath string) bool { - return strings.HasPrefix(targetUriPath, nodePath) + return err } diff --git a/src/translib/app_utils.go b/src/translib/app_utils.go index 19611ecb64..80c50feadc 100644 --- a/src/translib/app_utils.go +++ b/src/translib/app_utils.go @@ -180,3 +180,11 @@ func isNotFoundError(err error) bool { func asKey(parts ...string) db.Key { return db.Key{Comp: parts} } + +/* Check if targetUriPath is child (subtree) of nodePath +The return value can be used to decide if subtrees needs +to visited to fill the data or not. +*/ +func isSubtreeRequest(targetUriPath string, nodePath string) bool { + return strings.HasPrefix(targetUriPath, nodePath) +} \ No newline at end of file diff --git a/src/translib/common_app.go b/src/translib/common_app.go index 3470b16bd0..9efb448001 100644 --- a/src/translib/common_app.go +++ b/src/translib/common_app.go @@ -1,48 +1,41 @@ package translib import ( -// "bytes" "errors" "fmt" log "github.com/golang/glog" -// "github.com/openconfig/ygot/util" "github.com/openconfig/ygot/ygot" "reflect" -// "strconv" -// "strings" "translib/db" - //"translib/ocbinds" - "translib/transformer" "translib/tlerr" + "translib/transformer" ) -var ( +var () -) type CommonApp struct { - pathInfo *PathInfo - ygotRoot *ygot.GoStruct - ygotTarget *interface{} + pathInfo *PathInfo + ygotRoot *ygot.GoStruct + ygotTarget *interface{} cmnAppTableMap map[string]map[string]db.Value } var cmnAppInfo = appInfo{appType: reflect.TypeOf(CommonApp{}), - ygotRootType: nil, - isNative: false, - tablesToWatch: nil} - + ygotRootType: nil, + isNative: false, + tablesToWatch: nil} func init() { - // @todo : Optimize to register supported paths/yang via common app and report error for unsupported - register_model_path := []string{"/sonic-"} // register yang model path(s) to be supported via common app - for _, mdl_pth := range register_model_path { - err := register(mdl_pth, &cmnAppInfo) + // @todo : Optimize to register supported paths/yang via common app and report error for unsupported + register_model_path := []string{"/sonic-"} // register yang model path(s) to be supported via common app + for _, mdl_pth := range register_model_path { + err := register(mdl_pth, &cmnAppInfo) - if err != nil { - log.Fatal("Register Common app module with App Interface failed with error=", err, "for path=", mdl_pth) - } - } + if err != nil { + log.Fatal("Register Common app module with App Interface failed with error=", err, "for path=", mdl_pth) + } + } } @@ -93,15 +86,15 @@ func (app *CommonApp) translateDelete(d *db.DB) ([]db.WatchKeys, error) { } func (app *CommonApp) translateGet(dbs [db.MaxDB]*db.DB) error { - var err error - log.Info("translateGet:path =", app.pathInfo.Path) - return err + var err error + log.Info("translateGet:path =", app.pathInfo.Path) + return err } func (app *CommonApp) translateSubscribe(dbs [db.MaxDB]*db.DB, path string) (*notificationOpts, *notificationInfo, error) { - err := errors.New("Not supported") - notifInfo := notificationInfo{dbno: db.ConfigDB} - return nil, ¬ifInfo, err + err := errors.New("Not supported") + notifInfo := notificationInfo{dbno: db.ConfigDB} + return nil, ¬ifInfo, err } func (app *CommonApp) processCreate(d *db.DB) (SetResponse, error) { @@ -112,10 +105,9 @@ func (app *CommonApp) processCreate(d *db.DB) (SetResponse, error) { targetType := reflect.TypeOf(*app.ygotTarget) log.Infof("processCreate: Target object is a <%s> of Type: %s", targetType.Kind().String(), targetType.Elem().Name()) if err = app.processCommon(d, CREATE); err != nil { - log.Error(err) - resp = SetResponse{ErrSrc: AppErr} - } - + log.Error(err) + resp = SetResponse{ErrSrc: AppErr} + } return resp, err } @@ -125,9 +117,9 @@ func (app *CommonApp) processUpdate(d *db.DB) (SetResponse, error) { var resp SetResponse log.Info("processUpdate:path =", app.pathInfo.Path) if err = app.processCommon(d, UPDATE); err != nil { - log.Error(err) - resp = SetResponse{ErrSrc: AppErr} - } + log.Error(err) + resp = SetResponse{ErrSrc: AppErr} + } return resp, err } @@ -137,9 +129,9 @@ func (app *CommonApp) processReplace(d *db.DB) (SetResponse, error) { var resp SetResponse log.Info("processReplace:path =", app.pathInfo.Path) if err = app.processCommon(d, REPLACE); err != nil { - log.Error(err) - resp = SetResponse{ErrSrc: AppErr} - } + log.Error(err) + resp = SetResponse{ErrSrc: AppErr} + } return resp, err } @@ -150,42 +142,39 @@ func (app *CommonApp) processDelete(d *db.DB) (SetResponse, error) { log.Info("processDelete:path =", app.pathInfo.Path) if err = app.processCommon(d, DELETE); err != nil { - log.Error(err) - resp = SetResponse{ErrSrc: AppErr} - } - - + log.Error(err) + resp = SetResponse{ErrSrc: AppErr} + } return resp, err } func (app *CommonApp) processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error) { - var err error - var payload []byte - log.Info("processGet:path =", app.pathInfo.Path) - - keySpec, err := transformer.XlateUriToKeySpec(app.pathInfo.Path, app.ygotRoot, app.ygotTarget) - - // table.key.fields - var result = make(map[string]map[string]db.Value) - - for dbnum, specs := range *keySpec { - for _, spec := range specs { - err := transformer.TraverseDb(dbs[dbnum], spec, &result, nil) - if err != nil { - return GetResponse{Payload: payload}, err - } - } - } - - payload, err = transformer.XlateFromDb(app.pathInfo.Path, result) - if err != nil { - return GetResponse{Payload: payload, ErrSrc: AppErr}, err - } - - return GetResponse{Payload: payload}, err -} + var err error + var payload []byte + log.Info("processGet:path =", app.pathInfo.Path) + keySpec, err := transformer.XlateUriToKeySpec(app.pathInfo.Path, app.ygotRoot, app.ygotTarget) + + // table.key.fields + var result = make(map[string]map[string]db.Value) + + for dbnum, specs := range *keySpec { + for _, spec := range specs { + err := transformer.TraverseDb(dbs[dbnum], spec, &result, nil) + if err != nil { + return GetResponse{Payload: payload}, err + } + } + } + + payload, err = transformer.XlateFromDb(app.pathInfo.Path, result) + if err != nil { + return GetResponse{Payload: payload, ErrSrc: AppErr}, err + } + + return GetResponse{Payload: payload}, err +} func (app *CommonApp) translateCRUCommon(d *db.DB, opcode int) ([]db.WatchKeys, error) { var err error @@ -204,17 +193,17 @@ func (app *CommonApp) translateCRUCommon(d *db.DB, opcode int) ([]db.WatchKeys, } if len(result) == 0 { log.Error("XlatetoDB() returned empty map") - err = errors.New("transformer.XlatetoDB() returned empty map") - return keys, err + err = errors.New("transformer.XlatetoDB() returned empty map") + return keys, err } app.cmnAppTableMap = result - for tblnm, _ := range app.cmnAppTableMap { - log.Error("Table name ", tblnm) - tblsToWatch = append(tblsToWatch, &db.TableSpec{Name: tblnm}) - } - log.Info("Tables to watch", tblsToWatch) + for tblnm, _ := range app.cmnAppTableMap { + log.Error("Table name ", tblnm) + tblsToWatch = append(tblsToWatch, &db.TableSpec{Name: tblnm}) + } + log.Info("Tables to watch", tblsToWatch) - cmnAppInfo.tablesToWatch = tblsToWatch + cmnAppInfo.tablesToWatch = tblsToWatch keys, err = app.generateDbWatchKeys(d, false) @@ -222,98 +211,97 @@ func (app *CommonApp) translateCRUCommon(d *db.DB, opcode int) ([]db.WatchKeys, } func (app *CommonApp) processCommon(d *db.DB, opcode int) error { - var err error - err = app.cmnAppDataDbOperation(d, opcode, app.cmnAppTableMap) - return err + var err error + err = app.cmnAppDataDbOperation(d, opcode, app.cmnAppTableMap) + return err } func (app *CommonApp) cmnAppDataDbOperation(d *db.DB, opcode int, cmnAppDataDbMap map[string]map[string]db.Value) error { - var err error - log.Info("Processing DB operation for ", cmnAppDataDbMap) - var cmnAppTs *db.TableSpec - for tblNm, tblInst := range cmnAppDataDbMap { - log.Info("Table name ", tblNm) - cmnAppTs = &db.TableSpec{Name: tblNm} - for tblKey, tblRw := range tblInst { - log.Info("Table key and row ", tblKey, tblRw) - switch opcode { - case CREATE: - log.Info("CREATE case") - existingEntry, err := d.GetEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}) - if existingEntry.IsPopulated() { - log.Info("Entry already exists hence return error.") - return tlerr.AlreadyExists("Entry %s already exists", tblKey) - } else { - err = d.CreateEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}, tblRw) - if err != nil { - log.Error("CREATE case - d.CreateEntry() failure") - return err - } - } - case UPDATE: - log.Info("UPDATE case") - existingEntry, err := d.GetEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}) - if existingEntry.IsPopulated() { - log.Info("Entry already exists hence modifying it.") - err = d.ModEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}, tblRw) - if err != nil { - log.Error("UPDATE case - d.ModEntry() failure") - return err - } - } else { - log.Info("Entry to be modified does not exist hence return error.") - return tlerr.NotFound("Entry %s to be modified does not exist.", tblKey) - - } - - case REPLACE: - log.Info("REPLACE case") - existingEntry, err := d.GetEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}) - if existingEntry.IsPopulated() { - log.Info("Entry already exists hence execute db.SetEntry") - err := d.SetEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}, tblRw) - if err != nil { - log.Error("REPLACE case - d.SetEntry() failure") - return err - } - } else { - log.Info("Entry doesn't exist hence create it.") - err = d.CreateEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}, tblRw) - if err != nil { - log.Error("REPLACE case - d.CreateEntry() failure") - return err - } - } - //TODO : should the table level replace be handled?? - case DELETE: - log.Info("DELETE case") - if len(tblRw.Field) == 0 { - log.Info("DELETE case - no fields/cols to delete hence delete the entire row.") - err := d.DeleteEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}) - if err != nil { - log.Error("DELETE case - d.DeleteEntry() failure") - return err - } - } else { - log.Info("DELETE case - fields/cols to delete hence delete only those fields.") - err := d.DeleteEntryFields(cmnAppTs, db.Key{Comp: []string{tblKey}}, tblRw) - if err != nil { - log.Error("DELETE case - d.DeleteEntryFields() failure") - return err - } - } - } - } - } - - return err + var err error + log.Info("Processing DB operation for ", cmnAppDataDbMap) + var cmnAppTs *db.TableSpec + for tblNm, tblInst := range cmnAppDataDbMap { + log.Info("Table name ", tblNm) + cmnAppTs = &db.TableSpec{Name: tblNm} + for tblKey, tblRw := range tblInst { + log.Info("Table key and row ", tblKey, tblRw) + switch opcode { + case CREATE: + log.Info("CREATE case") + existingEntry, err := d.GetEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}) + if existingEntry.IsPopulated() { + log.Info("Entry already exists hence return error.") + return tlerr.AlreadyExists("Entry %s already exists", tblKey) + } else { + err = d.CreateEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}, tblRw) + if err != nil { + log.Error("CREATE case - d.CreateEntry() failure") + return err + } + } + case UPDATE: + log.Info("UPDATE case") + existingEntry, err := d.GetEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}) + if existingEntry.IsPopulated() { + log.Info("Entry already exists hence modifying it.") + err = d.ModEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}, tblRw) + if err != nil { + log.Error("UPDATE case - d.ModEntry() failure") + return err + } + } else { + log.Info("Entry to be modified does not exist hence return error.") + return tlerr.NotFound("Entry %s to be modified does not exist.", tblKey) + + } + + case REPLACE: + log.Info("REPLACE case") + existingEntry, err := d.GetEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}) + if existingEntry.IsPopulated() { + log.Info("Entry already exists hence execute db.SetEntry") + err := d.SetEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}, tblRw) + if err != nil { + log.Error("REPLACE case - d.SetEntry() failure") + return err + } + } else { + log.Info("Entry doesn't exist hence create it.") + err = d.CreateEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}, tblRw) + if err != nil { + log.Error("REPLACE case - d.CreateEntry() failure") + return err + } + } + //TODO : should the table level replace be handled?? + case DELETE: + log.Info("DELETE case") + if len(tblRw.Field) == 0 { + log.Info("DELETE case - no fields/cols to delete hence delete the entire row.") + err := d.DeleteEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}) + if err != nil { + log.Error("DELETE case - d.DeleteEntry() failure") + return err + } + } else { + log.Info("DELETE case - fields/cols to delete hence delete only those fields.") + err := d.DeleteEntryFields(cmnAppTs, db.Key{Comp: []string{tblKey}}, tblRw) + if err != nil { + log.Error("DELETE case - d.DeleteEntryFields() failure") + return err + } + } + } + } + } + + return err } func (app *CommonApp) generateDbWatchKeys(d *db.DB, isDeleteOp bool) ([]db.WatchKeys, error) { - var err error - var keys []db.WatchKeys + var err error + var keys []db.WatchKeys - return keys, err + return keys, err } - diff --git a/src/translib/path_utils.go b/src/translib/path_utils.go index 8d12ecdfcd..70f01a93ab 100644 --- a/src/translib/path_utils.go +++ b/src/translib/path_utils.go @@ -13,6 +13,7 @@ import ( "reflect" "strconv" "strings" + "bytes" "translib/ocbinds" @@ -177,3 +178,31 @@ func getObjectFieldName(targetUri *string, deviceObj *ocbinds.Device, ygotTarget } return "", errors.New("Target object not found") } + +func RemoveXPATHPredicates(s string) (string, error) { + var b bytes.Buffer + for i := 0; i < len(s); { + ss := s[i:] + si, ei := strings.Index(ss, "["), strings.Index(ss, "]") + switch { + case si == -1 && ei == -1: + // This substring didn't contain a [] pair, therefore write it + // to the buffer. + b.WriteString(ss) + // Move to the last character of the substring. + i += len(ss) + case si == -1 || ei == -1: + // This substring contained a mismatched pair of []s. + return "", fmt.Errorf("Mismatched brackets within substring %s of %s, [ pos: %d, ] pos: %d", ss, s, si, ei) + case si > ei: + // This substring contained a ] before a [. + return "", fmt.Errorf("Incorrect ordering of [] within substring %s of %s, [ pos: %d, ] pos: %d", ss, s, si, ei) + default: + // This substring contained a matched set of []s. + b.WriteString(ss[0:si]) + i += ei + 1 + } + } + + return b.String(), nil +} diff --git a/src/translib/transformer/transformer.go b/src/translib/transformer/transformer.go index aec692d086..0d75c409ff 100644 --- a/src/translib/transformer/transformer.go +++ b/src/translib/transformer/transformer.go @@ -2,15 +2,13 @@ package transformer import ( "fmt" - "os" - "strings" "github.com/openconfig/goyang/pkg/yang" "github.com/openconfig/ygot/ygot" -// "translib/db" -// "translib/ocbinds" + "os" + "strings" ) -const YangPath = "/usr/models/yang/" // OpenConfig-*.yang and sonic yang models path +const YangPath = "/usr/models/yang/" // OpenConfig-*.yang and sonic yang models path var entries = map[string]*yang.Entry{} @@ -30,8 +28,8 @@ func reportIfError(errs []error) { } func init() { - yangFiles := []string{"sonic-acl.yang", "sonic-extensions.yang", "openconfig-acl-annot.yang", "openconfig-acl.yang" } - loadYangModules(yangFiles...) + yangFiles := []string{"sonic-acl.yang", "sonic-extensions.yang", "openconfig-acl-annot.yang", "openconfig-acl.yang"} + loadYangModules(yangFiles...) } func loadYangModules(files ...string) error { @@ -76,23 +74,20 @@ func loadYangModules(files ...string) error { sonic_entries := make([]*yang.Entry, len(names)) oc_entries := make(map[string]*yang.Entry) annot_entries := make([]*yang.Entry, len(names)) - var i, j int for _, n := range names { - if strings.Contains(n, "annot") { - annot_entries[i] = yang.ToEntry(mods[n]) - i++ - } else if strings.Contains(n, "sonic") { - sonic_entries[j] = yang.ToEntry(mods[n]) - j++ - } else if oc_entries[n] == nil { - oc_entries[n] = yang.ToEntry(mods[n]) - } + if strings.Contains(n, "annot") { + annot_entries = append(annot_entries, yang.ToEntry(mods[n])) + } else if strings.Contains(n, "sonic") { + sonic_entries = append(sonic_entries, yang.ToEntry(mods[n])) + } else if oc_entries[n] == nil { + oc_entries[n] = yang.ToEntry(mods[n]) + } } - dbMapBuild(sonic_entries) - annotToDbMapBuild(annot_entries) - yangToDbMapBuild(oc_entries) + dbMapBuild(sonic_entries) + annotToDbMapBuild(annot_entries) + yangToDbMapBuild(oc_entries) return err } From 35ec93790594459a1e50fe31b67f675e8d22b699 Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Sat, 17 Aug 2019 02:18:23 -0700 Subject: [PATCH 053/214] Initial support for leaf value retrieval in Get. Include only required field data in dbResponse --- src/translib/transformer/xlate.go | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index a807d2d995..36b5e11928 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -242,8 +242,36 @@ func XlateToDb(path string, opcode int, d *db.DB, yg *ygot.GoStruct, yt *interfa func XlateFromDb(xpath string, data map[string]map[string]db.Value) ([]byte, error) { var err error + var dbData = make(map[string]map[string]db.Value) - payload, err := dbDataToYangJsonCreate(xpath, data) + yangXpath, keyStr := xpathKeyExtract(xpath); + + + if xSpecMap == nil { + return nil,err + } + _, ok := xSpecMap[yangXpath] + if !ok { + return nil,err + } + if xSpecMap[yangXpath].yangDataType == "leaf" { + + var fieldName, tableName string + var dbVal db.Value + + fieldName = xSpecMap[yangXpath].fieldName + tableName = *xSpecMap[yangXpath].tableName + + if (data[tableName][keyStr].Field != nil) { + dbData[tableName] = make(map[string]db.Value) + dbVal.Field = make(map[string]string) + dbVal.Field[fieldName] = data[tableName][keyStr].Field[fieldName] + dbData[tableName][keyStr] = dbVal + } + } else { + dbData = data + } + payload, err := dbDataToYangJsonCreate(yangXpath, dbData) if err != nil { log.Errorf("Error: failed to create json response from DB data.") From 122c0eac54a926bb7d6d804d1916a4f3a82c7286 Mon Sep 17 00:00:00 2001 From: kwangsuk Date: Sat, 17 Aug 2019 18:42:47 -0700 Subject: [PATCH 054/214] fix xpath build from uri --- src/translib/acl_app.go | 2 +- src/translib/path_utils.go | 28 - src/translib/transformer/xfmr_path_utils.go | 33 +- src/translib/transformer/xlate.go | 807 ++++++-------------- src/translib/transformer/xlate_to_db.go | 465 +++++------ 5 files changed, 482 insertions(+), 853 deletions(-) diff --git a/src/translib/acl_app.go b/src/translib/acl_app.go index 02966dbfda..f8e2d8eeea 100644 --- a/src/translib/acl_app.go +++ b/src/translib/acl_app.go @@ -328,7 +328,7 @@ func (app *AclApp) processCommon(d *db.DB, opcode int) error { targetType := reflect.TypeOf(*app.ygotTarget) - xpath, err := RemoveXPATHPredicates(app.pathInfo.Path) + xpath, err := transformer.RemoveXPATHPredicates(app.pathInfo.Path) if err != nil { log.Errorf("processCommon: Failed to remove Xpath Predicates from path %s", app.pathInfo.Template) } diff --git a/src/translib/path_utils.go b/src/translib/path_utils.go index 70f01a93ab..771b36c43c 100644 --- a/src/translib/path_utils.go +++ b/src/translib/path_utils.go @@ -13,8 +13,6 @@ import ( "reflect" "strconv" "strings" - "bytes" - "translib/ocbinds" log "github.com/golang/glog" @@ -179,30 +177,4 @@ func getObjectFieldName(targetUri *string, deviceObj *ocbinds.Device, ygotTarget return "", errors.New("Target object not found") } -func RemoveXPATHPredicates(s string) (string, error) { - var b bytes.Buffer - for i := 0; i < len(s); { - ss := s[i:] - si, ei := strings.Index(ss, "["), strings.Index(ss, "]") - switch { - case si == -1 && ei == -1: - // This substring didn't contain a [] pair, therefore write it - // to the buffer. - b.WriteString(ss) - // Move to the last character of the substring. - i += len(ss) - case si == -1 || ei == -1: - // This substring contained a mismatched pair of []s. - return "", fmt.Errorf("Mismatched brackets within substring %s of %s, [ pos: %d, ] pos: %d", ss, s, si, ei) - case si > ei: - // This substring contained a ] before a [. - return "", fmt.Errorf("Incorrect ordering of [] within substring %s of %s, [ pos: %d, ] pos: %d", ss, s, si, ei) - default: - // This substring contained a matched set of []s. - b.WriteString(ss[0:si]) - i += ei + 1 - } - } - return b.String(), nil -} diff --git a/src/translib/transformer/xfmr_path_utils.go b/src/translib/transformer/xfmr_path_utils.go index 06989cb116..557e0f3e82 100644 --- a/src/translib/transformer/xfmr_path_utils.go +++ b/src/translib/transformer/xfmr_path_utils.go @@ -8,13 +8,10 @@ package transformer import ( - //"errors" + "bytes" "fmt" - //log "github.com/golang/glog" - //"reflect" "strconv" "strings" - //"translib/ocbinds" ) // PathInfo structure contains parsed path information. @@ -85,6 +82,34 @@ func readUntil(r *strings.Reader, delim byte) string { return buff.String() } + +func RemoveXPATHPredicates(s string) (string, error) { + var b bytes.Buffer + for i := 0; i < len(s); { + ss := s[i:] + si, ei := strings.Index(ss, "["), strings.Index(ss, "]") + switch { + case si == -1 && ei == -1: + // This substring didn't contain a [] pair, therefore write it + // to the buffer. + b.WriteString(ss) + // Move to the last character of the substring. + i += len(ss) + case si == -1 || ei == -1: + // This substring contained a mismatched pair of []s. + return "", fmt.Errorf("Mismatched brackets within substring %s of %s, [ pos: %d, ] pos: %d", ss, s, si, ei) + case si > ei: + // This substring contained a ] before a [. + return "", fmt.Errorf("Incorrect ordering of [] within substring %s of %s, [ pos: %d, ] pos: %d", ss, s, si, ei) + default: + // This substring contained a matched set of []s. + b.WriteString(ss[0:si]) + i += ei + 1 + } + } + + return b.String(), nil +} /* func getParentNode(targetUri *string, deviceObj *ocbinds.Device) (*interface{}, *yang.Entry, error) { path, err := ygot.StringToPath(*targetUri, ygot.StructuredPath, ygot.StringSlicePath) diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index 36b5e11928..516bff0036 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -1,18 +1,18 @@ package transformer import ( - //"fmt" - //"os" - // "sort" - // "github.com/openconfig/goyang/pkg/yang" - "github.com/openconfig/ygot/ygot" - "translib/db" - "translib/ocbinds" - "reflect" - "errors" - "strings" - "encoding/json" - log "github.com/golang/glog" + //"fmt" + //"os" + // "sort" + // "github.com/openconfig/goyang/pkg/yang" + "encoding/json" + "errors" + log "github.com/golang/glog" + "github.com/openconfig/ygot/ygot" + "reflect" + "strings" + "translib/db" + "translib/ocbinds" ) const ( @@ -24,609 +24,234 @@ const ( ) type KeySpec struct { - Ts db.TableSpec - Key db.Key - Child *KeySpec + Ts db.TableSpec + Key db.Key + Child *KeySpec } var XlateFuncs = make(map[string]reflect.Value) var ( - ErrParamsNotAdapted = errors.New("The number of params is not adapted.") + ErrParamsNotAdapted = errors.New("The number of params is not adapted.") ) -func XlateFuncBind (name string, fn interface{}) (err error) { - defer func() { - if e := recover(); e != nil { - err = errors.New(name + " is not valid Xfmr function.") - } - }() - - if _, ok := XlateFuncs[name]; !ok { - v :=reflect.ValueOf(fn) - v.Type().NumIn() - XlateFuncs[name] = v - } else { - log.Info("Duplicate entry found in the XlateFunc map " + name) - } - return +func XlateFuncBind(name string, fn interface{}) (err error) { + defer func() { + if e := recover(); e != nil { + err = errors.New(name + " is not valid Xfmr function.") + } + }() + + if _, ok := XlateFuncs[name]; !ok { + v := reflect.ValueOf(fn) + v.Type().NumIn() + XlateFuncs[name] = v + } else { + log.Info("Duplicate entry found in the XlateFunc map " + name) + } + return } -func XlateFuncCall(name string, params ... interface{}) (result []reflect.Value, err error) { - if _, ok := XlateFuncs[name]; !ok { - err = errors.New(name + " Xfmr function does not exist.") - return - } - if len(params) != XlateFuncs[name].Type().NumIn() { - err = ErrParamsNotAdapted - return - } - in := make([]reflect.Value, len(params)) - for k, param := range params { - in[k] = reflect.ValueOf(param) - } - result = XlateFuncs[name].Call(in) - return +func XlateFuncCall(name string, params ...interface{}) (result []reflect.Value, err error) { + if _, ok := XlateFuncs[name]; !ok { + err = errors.New(name + " Xfmr function does not exist.") + return + } + if len(params) != XlateFuncs[name].Type().NumIn() { + err = ErrParamsNotAdapted + return + } + in := make([]reflect.Value, len(params)) + for k, param := range params { + in[k] = reflect.ValueOf(param) + } + result = XlateFuncs[name].Call(in) + return } func TraverseDb(d *db.DB, spec KeySpec, result *map[string]map[string]db.Value, parentKey *db.Key) error { - var err error - - if spec.Key.Len() > 0 { - // get an entry with a specific key - data, err := d.GetEntry(&spec.Ts, spec.Key) - if err != nil { - return err - } - - if (*result)[spec.Ts.Name] == nil { - (*result)[spec.Ts.Name] = map[string]db.Value{strings.Join(spec.Key.Comp, "|"): data} - } else { - (*result)[spec.Ts.Name][strings.Join(spec.Key.Comp, "|")] = data - } - - if spec.Child != nil { - err = TraverseDb(d, *spec.Child, result, &spec.Key) - } - } else { - // TODO - GetEntry suuport with regex patten, 'abc*' for optimization - keys, err := d.GetKeys(&spec.Ts) - if err != nil { - return err - } - for i, _ := range keys { - if parentKey != nil { - // TODO - multi-depth with a custom delimiter - if strings.Index(strings.Join(keys[i].Comp, "|"), strings.Join((*parentKey).Comp, "|")) == -1 { - continue - } - } - spec.Key = keys[i] - err = TraverseDb(d, spec, result, parentKey) - } - } - return err + var err error + + if spec.Key.Len() > 0 { + // get an entry with a specific key + data, err := d.GetEntry(&spec.Ts, spec.Key) + if err != nil { + return err + } + + if (*result)[spec.Ts.Name] == nil { + (*result)[spec.Ts.Name] = map[string]db.Value{strings.Join(spec.Key.Comp, "|"): data} + } else { + (*result)[spec.Ts.Name][strings.Join(spec.Key.Comp, "|")] = data + } + + if spec.Child != nil { + err = TraverseDb(d, *spec.Child, result, &spec.Key) + } + } else { + // TODO - GetEntry suuport with regex patten, 'abc*' for optimization + keys, err := d.GetKeys(&spec.Ts) + if err != nil { + return err + } + for i, _ := range keys { + if parentKey != nil { + // TODO - multi-depth with a custom delimiter + if strings.Index(strings.Join(keys[i].Comp, "|"), strings.Join((*parentKey).Comp, "|")) == -1 { + continue + } + } + spec.Key = keys[i] + err = TraverseDb(d, spec, result, parentKey) + } + } + return err } func XlateUriToKeySpec(path string, uri *ygot.GoStruct, t *interface{}) (*map[db.DBNum][]KeySpec, error) { - var err error - var result = make(map[db.DBNum][]KeySpec) - var retdbFormat = make([]KeySpec, 0) - - /* Extract the xpath and key from input xpath */ - yangXpath, keyStr := xpathKeyExtract(path); - - if xSpecMap == nil { - return &result, err - } - _, ok := xSpecMap[yangXpath] - if ok { - xpathInfo := xSpecMap[yangXpath] - if xpathInfo.tableName != nil { - dbFormat := KeySpec{} - fillKeySpec(yangXpath, keyStr, &dbFormat) - retdbFormat = append(retdbFormat, dbFormat) - } else { - for _, child := range xpathInfo.childTable { - dbFormat := KeySpec{} - var childXpath = xDbSpecMap[child].yangXpath[0] - fillKeySpec(childXpath, "", &dbFormat) - retdbFormat = append(retdbFormat, dbFormat) - } - } - } - result[db.ConfigDB] = retdbFormat - - // 1 - mock data for a URI /openconfig-acl:acl/acl-sets/acl-set=MyACL1,ACL_IPV4 - //result[db.ConfigDB] = []KeySpec{ - // { - // Ts: db.TableSpec{Name: "ACL_TABLE"}, - // Key: db.Key{Comp: []string{"MyACL1_ACL_IPV4"}}, - // Child: &KeySpec{ - // Ts: db.TableSpec{Name: "ACL_RULE"}, - // Key: db.Key{}}}, - // } - // 2 - mock data for a URI /openconfig-acl:acl/acl-sets/acl-set=MyACL1,ACL_IPV4/acl-entires/ecl-entry=1 -// result[db.ConfigDB] = []KeySpec{ -// { -// Ts: db.TableSpec{Name: "ACL_RULE"}, -// Key: db.Key{Comp: []string{"MyACL1_ACL_IPV4|RULE_1"}}, -// } -// } - - - // 3 - mock data for a URI /openconfig-acl:acl -// result[db.ConfigDB] = []KeySpec{ -// { -// Ts: db.TableSpec{Name: "ACL_TABLE"}, -// Key: db.Key{}, -// Child: &KeySpec{ -// Ts: db.TableSpec{Name: "ACL_RULE"}, -// Key: db.Key{}}}, -// } - - return &result, err + var err error + var result = make(map[db.DBNum][]KeySpec) + var retdbFormat = make([]KeySpec, 0) + + /* Extract the xpath and key from input xpath */ + yangXpath, keyStr := xpathKeyExtract(path) + + if xSpecMap == nil { + return &result, err + } + _, ok := xSpecMap[yangXpath] + if ok { + xpathInfo := xSpecMap[yangXpath] + if xpathInfo.tableName != nil { + dbFormat := KeySpec{} + fillKeySpec(yangXpath, keyStr, &dbFormat) + retdbFormat = append(retdbFormat, dbFormat) + } else { + for _, child := range xpathInfo.childTable { + dbFormat := KeySpec{} + var childXpath = xDbSpecMap[child].yangXpath[0] + fillKeySpec(childXpath, "", &dbFormat) + retdbFormat = append(retdbFormat, dbFormat) + } + } + } + result[db.ConfigDB] = retdbFormat + + return &result, err } -func fillKeySpec(yangXpath string , keyStr string, dbFormat *KeySpec) { - - if xSpecMap == nil { - return; - } - _, ok := xSpecMap[yangXpath] - if ok { - xpathInfo := xSpecMap[yangXpath] - if xpathInfo.tableName != nil { - dbFormat.Ts.Name = *xpathInfo.tableName - dbFormat.Key.Comp = append(dbFormat.Key.Comp, keyStr) - } - for _, child := range xpathInfo.childTable { - // Current support for one child. Should change the KeySpec.Child - // to array of pointers later when we support all children - if xDbSpecMap != nil { - if len(xDbSpecMap[child].yangXpath) > 0 { - var childXpath = xDbSpecMap[child].yangXpath[0] - dbFormat.Child = new(KeySpec) - fillKeySpec(childXpath, "", dbFormat.Child) - } - } - } - } else { - return; - } +func fillKeySpec(yangXpath string, keyStr string, dbFormat *KeySpec) { + + if xSpecMap == nil { + return + } + _, ok := xSpecMap[yangXpath] + if ok { + xpathInfo := xSpecMap[yangXpath] + if xpathInfo.tableName != nil { + dbFormat.Ts.Name = *xpathInfo.tableName + dbFormat.Key.Comp = append(dbFormat.Key.Comp, keyStr) + } + for _, child := range xpathInfo.childTable { + // Current support for one child. Should change the KeySpec.Child + // to array of pointers later when we support all children + if xDbSpecMap != nil { + if len(xDbSpecMap[child].yangXpath) > 0 { + var childXpath = xDbSpecMap[child].yangXpath[0] + dbFormat.Child = new(KeySpec) + fillKeySpec(childXpath, "", dbFormat.Child) + } + } + } + } else { + return + } } func XlateToDb(path string, opcode int, d *db.DB, yg *ygot.GoStruct, yt *interface{}) (map[string]map[string]db.Value, error) { - var err error - - device := (*yg).(*ocbinds.Device) - jsonStr, err := ygot.EmitJSON(device, &ygot.EmitJSONConfig{ - Format: ygot.RFC7951, - Indent: " ", - SkipValidation: true, - RFC7951Config: &ygot.RFC7951JSONConfig{ - AppendModuleName: true, - }, - }) - - jsonData := make(map[string]interface{}) - err = json.Unmarshal([]byte(jsonStr), &jsonData) - if err != nil { - log.Errorf("Error: failed to unmarshal json.") - return nil,err - } - - // table.key.fields - var result = make(map[string]map[string]db.Value) - switch opcode { - case CREATE: - log.Info("CREATE case") - err = dbMapCreate(d, yg, opcode, path, jsonData, result) - if err != nil { - log.Errorf("Error: Data translation from yang to db failed.") - } - - case UPDATE: - log.Info("UPDATE case") - - case REPLACE: - log.Info("REPLACE case") - - case DELETE: - log.Info("DELETE case") - } - return result, err + var err error + + device := (*yg).(*ocbinds.Device) + jsonStr, err := ygot.EmitJSON(device, &ygot.EmitJSONConfig{ + Format: ygot.RFC7951, + Indent: " ", + SkipValidation: true, + RFC7951Config: &ygot.RFC7951JSONConfig{ + AppendModuleName: true, + }, + }) + + jsonData := make(map[string]interface{}) + err = json.Unmarshal([]byte(jsonStr), &jsonData) + if err != nil { + log.Errorf("Error: failed to unmarshal json.") + return nil, err + } + + // table.key.fields + var result = make(map[string]map[string]db.Value) + switch opcode { + case CREATE: + log.Info("CREATE case") + err = dbMapCreate(d, yg, opcode, path, jsonData, result) + if err != nil { + log.Errorf("Error: Data translation from yang to db failed.") + } + + case UPDATE: + log.Info("UPDATE case") + + case REPLACE: + log.Info("REPLACE case") + + case DELETE: + log.Info("DELETE case") + } + return result, err } func XlateFromDb(xpath string, data map[string]map[string]db.Value) ([]byte, error) { - var err error - var dbData = make(map[string]map[string]db.Value) - - yangXpath, keyStr := xpathKeyExtract(xpath); - - - if xSpecMap == nil { - return nil,err - } - _, ok := xSpecMap[yangXpath] - if !ok { - return nil,err - } - if xSpecMap[yangXpath].yangDataType == "leaf" { - - var fieldName, tableName string - var dbVal db.Value - - fieldName = xSpecMap[yangXpath].fieldName - tableName = *xSpecMap[yangXpath].tableName - - if (data[tableName][keyStr].Field != nil) { - dbData[tableName] = make(map[string]db.Value) - dbVal.Field = make(map[string]string) - dbVal.Field[fieldName] = data[tableName][keyStr].Field[fieldName] - dbData[tableName][keyStr] = dbVal - } - } else { - dbData = data - } - payload, err := dbDataToYangJsonCreate(yangXpath, dbData) - - if err != nil { - log.Errorf("Error: failed to create json response from DB data.") - return nil,err - } - - // please implement me - data translated by transforme - // here is a mock data - /* - payload := `{ - "acl-sets": { - "acl-set": [ - { - "name": "MyACL1", - "type": "ACL_IPV4", - "config": { - "name": "MyACL1", - "type": "ACL_IPV4", - "description": "Description for MyACL1" - }, - "acl-entries": { - "acl-entry": [ - { - "sequence-id": 1, - "config": { - "sequence-id": 1, - "description": "Description for MyACL1 Rule Seq 1" - }, - "ipv4": { - "config": { - "source-address": "11.1.1.1/32", - "destination-address": "21.1.1.1/32", - "dscp": 1, - "protocol": "IP_TCP" - } - }, - "transport": { - "config": { - "source-port": 101, - "destination-port": 201 - } - }, - "actions": { - "config": { - "forwarding-action": "ACCEPT" - } - } - }, - { - "sequence-id": 2, - "config": { - "sequence-id": 2, - "description": "Description for MyACL1 Rule Seq 2" - }, - "ipv4": { - "config": { - "source-address": "11.1.1.2/32", - "destination-address": "21.1.1.2/32", - "dscp": 2, - "protocol": "IP_TCP" - } - }, - "transport": { - "config": { - "source-port": 102, - "destination-port": 202 - } - }, - "actions": { - "config": { - "forwarding-action": "DROP" - } - } - }, - { - "sequence-id": 3, - "config": { - "sequence-id": 3, - "description": "Description for MyACL1 Rule Seq 3" - }, - "ipv4": { - "config": { - "source-address": "11.1.1.3/32", - "destination-address": "21.1.1.3/32", - "dscp": 3, - "protocol": "IP_TCP" - } - }, - "transport": { - "config": { - "source-port": 103, - "destination-port": 203 - } - }, - "actions": { - "config": { - "forwarding-action": "ACCEPT" - } - } - }, - { - "sequence-id": 4, - "config": { - "sequence-id": 4, - "description": "Description for MyACL1 Rule Seq 4" - }, - "ipv4": { - "config": { - "source-address": "11.1.1.4/32", - "destination-address": "21.1.1.4/32", - "dscp": 4, - "protocol": "IP_TCP" - } - }, - "transport": { - "config": { - "source-port": 104, - "destination-port": 204 - } - }, - "actions": { - "config": { - "forwarding-action": "DROP" - } - } - }, - { - "sequence-id": 5, - "config": { - "sequence-id": 5, - "description": "Description for MyACL1 Rule Seq 5" - }, - "ipv4": { - "config": { - "source-address": "11.1.1.5/32", - "destination-address": "21.1.1.5/32", - "dscp": 5, - "protocol": "IP_TCP" - } - }, - "transport": { - "config": { - "source-port": 105, - "destination-port": 205 - } - }, - "actions": { - "config": { - "forwarding-action": "ACCEPT" - } - } - } - ] - } - }, - { - "name": "MyACL2", - "type": "ACL_IPV4", - "config": { - "name": "MyACL2", - "type": "ACL_IPV4", - "description": "Description for MyACL2" - }, - "acl-entries": { - "acl-entry": [ - { - "sequence-id": 1, - "config": { - "sequence-id": 1, - "description": "Description for Rule Seq 1" - }, - "ipv4": { - "config": { - "source-address": "12.1.1.1/32", - "destination-address": "22.1.1.1/32", - "dscp": 1, - "protocol": "IP_TCP" - } - }, - "transport": { - "config": { - "source-port": 101, - "destination-port": 201 - } - }, - "actions": { - "config": { - "forwarding-action": "ACCEPT" - } - } - }, - { - "sequence-id": 2, - "config": { - "sequence-id": 2, - "description": "Description for Rule Seq 2" - }, - "ipv4": { - "config": { - "source-address": "12.1.1.2/32", - "destination-address": "22.1.1.2/32", - "dscp": 2, - "protocol": "IP_TCP" - } - }, - "transport": { - "config": { - "source-port": 102, - "destination-port": 202 - } - }, - "actions": { - "config": { - "forwarding-action": "ACCEPT" - } - } - }, - { - "sequence-id": 3, - "config": { - "sequence-id": 3, - "description": "Description for Rule Seq 3" - }, - "ipv4": { - "config": { - "source-address": "12.1.1.3/32", - "destination-address": "22.1.1.3/32", - "dscp": 3, - "protocol": "IP_TCP" - } - }, - "transport": { - "config": { - "source-port": 103, - "destination-port": 203 - } - }, - "actions": { - "config": { - "forwarding-action": "ACCEPT" - } - } - }, - { - "sequence-id": 4, - "config": { - "sequence-id": 4, - "description": "Description for Rule Seq 4" - }, - "ipv4": { - "config": { - "source-address": "12.1.1.4/32", - "destination-address": "22.1.1.4/32", - "dscp": 4, - "protocol": "IP_TCP" - } - }, - "transport": { - "config": { - "source-port": 104, - "destination-port": 204 - } - }, - "actions": { - "config": { - "forwarding-action": "ACCEPT" - } - } - }, - { - "sequence-id": 5, - "config": { - "sequence-id": 5, - "description": "Description for Rule Seq 5" - }, - "ipv4": { - "config": { - "source-address": "12.1.1.5/32", - "destination-address": "22.1.1.5/32", - "dscp": 5, - "protocol": "IP_TCP" - } - }, - "transport": { - "config": { - "source-port": 105, - "destination-port": 205 - } - }, - "actions": { - "config": { - "forwarding-action": "ACCEPT" - } - } - } - ] - } - } - ] - }, - "interfaces": { - "interface": [ - { - "id": "Ethernet0", - "config": { - "id": "Ethernet0" - }, - "interface-ref": { - "config": { - "interface": "Ethernet0" - } - }, - "ingress-acl-sets": { - "ingress-acl-set": [ - { - "set-name": "MyACL1", - "type": "ACL_IPV4", - "config": { - "set-name": "MyACL1", - "type": "ACL_IPV4" - } - } - ] - } - }, - { - "id": "Ethernet4", - "config": { - "id": "Ethernet4" - }, - "interface-ref": { - "config": { - "interface": "Ethernet4" - } - }, - "ingress-acl-sets": { - "ingress-acl-set": [ - { - "set-name": "MyACL2", - "type": "ACL_IPV4", - "config": { - "set-name": "MyACL2", - "type": "ACL_IPV4" - } - } - ] - } - } - ] - } -}` - */ - result := []byte(payload) - - //TODO - implement me - return result, err + var err error + var dbData = make(map[string]map[string]db.Value) + + yangXpath, keyStr := xpathKeyExtract(xpath) + + if xSpecMap == nil { + return nil, err + } + _, ok := xSpecMap[yangXpath] + if !ok { + return nil, err + } + if xSpecMap[yangXpath].yangDataType == "leaf" { + + var fieldName, tableName string + var dbVal db.Value + + fieldName = xSpecMap[yangXpath].fieldName + tableName = *xSpecMap[yangXpath].tableName + + if data[tableName][keyStr].Field != nil { + dbData[tableName] = make(map[string]db.Value) + dbVal.Field = make(map[string]string) + dbVal.Field[fieldName] = data[tableName][keyStr].Field[fieldName] + dbData[tableName][keyStr] = dbVal + } + } else { + dbData = data + } + payload, err := dbDataToYangJsonCreate(yangXpath, dbData) + + if err != nil { + log.Errorf("Error: failed to create json response from DB data.") + return nil, err + } + + result := []byte(payload) + + //TODO - implement me + return result, err } diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index 10b8bcecf9..80f430b771 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -1,291 +1,298 @@ package transformer import ( - "fmt" - "translib/db" - "os" - "reflect" - "regexp" - "strings" - "errors" + "errors" + "fmt" "github.com/openconfig/ygot/ygot" + "os" + "reflect" + "regexp" + "strings" + "translib/db" - log "github.com/golang/glog" + log "github.com/golang/glog" ) /* Fill redis-db map with field & value info */ func dataToDBMapAdd(tableName string, dbKey string, result map[string]map[string]db.Value, field string, value string) { - _, ok := result[tableName] - if !ok { - result[tableName] = make(map[string]db.Value) - } + _, ok := result[tableName] + if !ok { + result[tableName] = make(map[string]db.Value) + } - _, ok = result[tableName][dbKey] - if !ok { - result[tableName][dbKey] = db.Value{Field: make(map[string]string)} - } + _, ok = result[tableName][dbKey] + if !ok { + result[tableName][dbKey] = db.Value{Field: make(map[string]string)} + } - result[tableName][dbKey].Field[field] = value - return + result[tableName][dbKey].Field[field] = value + return } /* Fill the redis-db map with data */ func mapFillData(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, dbKey string, result map[string]map[string]db.Value, xpathPrefix string, name string, value string) error { - xpath := xpathPrefix + "/" + name - xpathInfo := xSpecMap[xpath] - log.Info("name: \"%v\", xpathPrefix(\"%v\").", name, xpathPrefix) + xpath := xpathPrefix + "/" + name + xpathInfo := xSpecMap[xpath] + log.Info("name: \"%v\", xpathPrefix(\"%v\").", name, xpathPrefix) - if xpathInfo == nil { - log.Errorf("Yang path(\"%v\") not found.", xpath) - return errors.New("Invalid URI") - } + if xpathInfo == nil { + log.Errorf("Yang path(\"%v\") not found.", xpath) + return errors.New("Invalid URI") + } - if xpathInfo.tableName == nil { - log.Errorf("Table for yang-path(\"%v\") not found.", xpath) - return errors.New("Invalid table name") - } + if xpathInfo.tableName == nil { + log.Errorf("Table for yang-path(\"%v\") not found.", xpath) + return errors.New("Invalid table name") + } - if len(dbKey) == 0 { - log.Errorf("Table key for yang path(\"%v\") not found.", xpath) - return errors.New("Invalid table key") - } + if len(dbKey) == 0 { + log.Errorf("Table key for yang path(\"%v\") not found.", xpath) + return errors.New("Invalid table key") + } - if len(xpathInfo.fieldName) == 0 { - log.Info("Field for yang-path(\"%v\") not found in DB.", xpath) - return errors.New("Invalid field name") - } - fieldName := xpathInfo.fieldName - if strings.Contains(value, ":") { - value = strings.Split(value, ":")[1] - } + if len(xpathInfo.fieldName) == 0 { + log.Info("Field for yang-path(\"%v\") not found in DB.", xpath) + return errors.New("Invalid field name") + } + fieldName := xpathInfo.fieldName + if strings.Contains(value, ":") { + value = strings.Split(value, ":")[1] + } - if len(xpathInfo.xfmrFunc) > 0 { - /* field transformer present */ - log.Info("Transformer function(\"%v\") invoked for yang path(\"%v\").", xpathInfo.xfmrFunc, xpath) - ret, err := XlateFuncCall(yangToDbXfmrFunc(xSpecMap[xpath].xfmrFunc), d, ygRoot, oper, uri, value) - if err != nil { return err } - retData := ret[0].Interface().(map[string]string) - log.Info("Transformer function \"%v\" for \"%v\" returned(%v).", xpathInfo.xfmrFunc, xpath, retData) - for f, v := range retData { - dataToDBMapAdd(*xpathInfo.tableName, dbKey, result, f, v) - } - return nil - } + if len(xpathInfo.xfmrFunc) > 0 { + /* field transformer present */ + log.Info("Transformer function(\"%v\") invoked for yang path(\"%v\").", xpathInfo.xfmrFunc, xpath) + ret, err := XlateFuncCall(yangToDbXfmrFunc(xSpecMap[xpath].xfmrFunc), d, ygRoot, oper, uri, value) + if err != nil { + return err + } + retData := ret[0].Interface().(map[string]string) + log.Info("Transformer function \"%v\" for \"%v\" returned(%v).", xpathInfo.xfmrFunc, xpath, retData) + for f, v := range retData { + dataToDBMapAdd(*xpathInfo.tableName, dbKey, result, f, v) + } + return nil + } dataToDBMapAdd(*xpathInfo.tableName, dbKey, result, fieldName, value) - log.Info("TblName: \"%v\", key: \"%v\", field: \"%v\", value: \"%v\".", - *xpathInfo.tableName, dbKey, fieldName, value) - return nil + log.Info("TblName: \"%v\", key: \"%v\", field: \"%v\", value: \"%v\".", + *xpathInfo.tableName, dbKey, fieldName, value) + return nil } func callXfmr() map[string]map[string]db.Value { - result := make(map[string]map[string]db.Value) - result["ACL_TABLE"] = make(map[string]db.Value) - result["ACL_TABLE"]["MyACL1_ACL_IPV4"] = db.Value{Field: make(map[string]string)} - result["ACL_TABLE"]["MyACL1_ACL_IPV4"].Field["stage"] = "INGRESS" - result["ACL_TABLE"]["MyACL1_ACL_IPV4"].Field["ports@"] = "Ethernet0" - result["ACL_TABLE"]["MyACL2_ACL_IPV4"] = db.Value{Field: make(map[string]string)} - result["ACL_TABLE"]["MyACL2_ACL_IPV4"].Field["stage"] = "INGRESS" - result["ACL_TABLE"]["MyACL2_ACL_IPV4"].Field["ports@"] = "Ethernet4" - return result + result := make(map[string]map[string]db.Value) + result["ACL_TABLE"] = make(map[string]db.Value) + result["ACL_TABLE"]["MyACL1_ACL_IPV4"] = db.Value{Field: make(map[string]string)} + result["ACL_TABLE"]["MyACL1_ACL_IPV4"].Field["stage"] = "INGRESS" + result["ACL_TABLE"]["MyACL1_ACL_IPV4"].Field["ports@"] = "Ethernet0" + result["ACL_TABLE"]["MyACL2_ACL_IPV4"] = db.Value{Field: make(map[string]string)} + result["ACL_TABLE"]["MyACL2_ACL_IPV4"].Field["stage"] = "INGRESS" + result["ACL_TABLE"]["MyACL2_ACL_IPV4"].Field["ports@"] = "Ethernet4" + return result } func cvlYangReqToDbMapCreate(jsonData interface{}, result map[string]map[string]db.Value) error { - if reflect.ValueOf(jsonData).Kind() == reflect.Map { - data := reflect.ValueOf(jsonData) - for _, key := range data.MapKeys() { - _, ok := xDbSpecMap[key.String()] - if ok { - directDbMapData(key.String(), data.MapIndex(key).Interface(), result) - } else { - cvlYangReqToDbMapCreate(data.MapIndex(key).Interface(), result) - } - } - } - return nil + if reflect.ValueOf(jsonData).Kind() == reflect.Map { + data := reflect.ValueOf(jsonData) + for _, key := range data.MapKeys() { + _, ok := xDbSpecMap[key.String()] + if ok { + directDbMapData(key.String(), data.MapIndex(key).Interface(), result) + } else { + cvlYangReqToDbMapCreate(data.MapIndex(key).Interface(), result) + } + } + } + return nil } func directDbMapData(tableName string, jsonData interface{}, result map[string]map[string]db.Value) bool { - _, ok := xDbSpecMap[tableName] + _, ok := xDbSpecMap[tableName] - if ok && xDbSpecMap[tableName].dbEntry != nil { - dbSpecData := xDbSpecMap[tableName].dbEntry - tblKeyName := strings.Split(dbSpecData.Key, " ") - data := reflect.ValueOf(jsonData) - result[tableName] = make(map[string]db.Value) + if ok && xDbSpecMap[tableName].dbEntry != nil { + dbSpecData := xDbSpecMap[tableName].dbEntry + tblKeyName := strings.Split(dbSpecData.Key, " ") + data := reflect.ValueOf(jsonData) + result[tableName] = make(map[string]db.Value) - for idx := 0; idx < data.Len(); idx++ { - keyName := "" - d := data.Index(idx).Interface().(map[string]interface{}) - for i, k := range tblKeyName { - if i > 0 { keyName += "|" } - keyName += fmt.Sprintf("%v", d[k]) - delete(d, k) - } + for idx := 0; idx < data.Len(); idx++ { + keyName := "" + d := data.Index(idx).Interface().(map[string]interface{}) + for i, k := range tblKeyName { + if i > 0 { + keyName += "|" + } + keyName += fmt.Sprintf("%v", d[k]) + delete(d, k) + } - result[tableName][keyName] = db.Value{Field: make(map[string]string)} - for field, value := range d { - result[tableName][keyName].Field[field] = fmt.Sprintf("%v", value) - } - } - return true - } - return false + result[tableName][keyName] = db.Value{Field: make(map[string]string)} + for field, value := range d { + result[tableName][keyName].Field[field] = fmt.Sprintf("%v", value) + } + } + return true + } + return false } /* Get the db table, key and field name for the incoming delete request */ func dbMapDelete(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string, jsonData interface{}, result map[string]map[string]db.Value) error { - xpathPrefix, keyName := xpathKeyExtract(path) - log.Info("Delete req: path(\"%v\"), key(\"%v\"), xpathPrefix(\"%v\").", path, keyName, xpathPrefix) - spec, ok := xSpecMap[xpathPrefix] - if ok && spec.tableName != nil { - result[*spec.tableName] = make(map[string]db.Value) - if len(keyName) > 0 { - result[*spec.tableName][keyName] = db.Value{Field: make(map[string]string)} - if spec.yangEntry != nil && spec.yangEntry.Node.Statement().Keyword == "leaf" { - result[*spec.tableName][keyName].Field[spec.fieldName] = "" - } - } - } - log.Info("Delete req: path(\"%v\") result(\"%v\").", path, result) - return nil + xpathPrefix, keyName := xpathKeyExtract(path) + log.Info("Delete req: path(\"%v\"), key(\"%v\"), xpathPrefix(\"%v\").", path, keyName, xpathPrefix) + spec, ok := xSpecMap[xpathPrefix] + if ok && spec.tableName != nil { + result[*spec.tableName] = make(map[string]db.Value) + if len(keyName) > 0 { + result[*spec.tableName][keyName] = db.Value{Field: make(map[string]string)} + if spec.yangEntry != nil && spec.yangEntry.Node.Statement().Keyword == "leaf" { + result[*spec.tableName][keyName].Field[spec.fieldName] = "" + } + } + } + log.Info("Delete req: path(\"%v\") result(\"%v\").", path, result) + return nil } -/* Get the data from incoming update/replace request, create map and fill with dbValue(ie. field:value +/* Get the data from incoming update/replace request, create map and fill with dbValue(ie. field:value to write into redis-db */ func dbMapUpdate(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string, jsonData interface{}, result map[string]map[string]db.Value) error { - xpathPrefix, keyName := xpathKeyExtract(path) - log.Info("Update/replace req: path(\"%v\"), key(\"%v\"), xpathPrefix(\"%v\").", path, keyName, xpathPrefix) - dbMapCreate(d, ygRoot, oper, parentXpathGet(xpathPrefix), jsonData, result) - log.Info("Update/replace req: path(\"%v\") result(\"%v\").", path, result) - return nil + xpathPrefix, keyName := xpathKeyExtract(path) + log.Info("Update/replace req: path(\"%v\"), key(\"%v\"), xpathPrefix(\"%v\").", path, keyName, xpathPrefix) + dbMapCreate(d, ygRoot, oper, parentXpathGet(xpathPrefix), jsonData, result) + log.Info("Update/replace req: path(\"%v\") result(\"%v\").", path, result) + return nil } -/* Get the data from incoming create request, create map and fill with dbValue(ie. field:value +/* Get the data from incoming create request, create map and fill with dbValue(ie. field:value to write into redis-db */ func dbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string, jsonData interface{}, result map[string]map[string]db.Value) error { - xpathTmplt, keyName := xpathKeyExtract(path) - if isCvlYang(path) { - cvlYangReqToDbMapCreate(jsonData, result) - } else { - yangReqToDbMapCreate(d, ygRoot, oper, path, parentXpathGet(xpathTmplt), keyName, jsonData, result) - } - printDbData(result, "/tmp/yangToDbData.txt") - return nil + xpathTmplt, keyName := xpathKeyExtract(path) + if isCvlYang(path) { + cvlYangReqToDbMapCreate(jsonData, result) + } else { + yangReqToDbMapCreate(d, ygRoot, oper, path, parentXpathGet(xpathTmplt), keyName, jsonData, result) + } + printDbData(result, "/tmp/yangToDbData.txt") + return nil } func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, xpathPrefix string, keyName string, jsonData interface{}, result map[string]map[string]db.Value) error { - log.Info("key(\"%v\"), xpathPrefix(\"%v\").", keyName, xpathPrefix) + log.Info("key(\"%v\"), xpathPrefix(\"%v\").", keyName, xpathPrefix) - if reflect.ValueOf(jsonData).Kind() == reflect.Slice { - log.Info("slice data: key(\"%v\"), xpathPrefix(\"%v\").", keyName, xpathPrefix) - jData := reflect.ValueOf(jsonData) - dataMap := make([]interface{}, jData.Len()) - for idx := 0; idx < jData.Len(); idx++ { - dataMap[idx] = jData.Index(idx).Interface() - } - for _, data := range dataMap { - curKey := "" - uri = uriWithKeyCreate(uri, xpathPrefix, data) - if len(xSpecMap[xpathPrefix].xfmrKey) > 0 { - /* key transformer present */ - ret, err := XlateFuncCall(yangToDbXfmrFunc(xSpecMap[xpathPrefix].xfmrKey), d, ygRoot, oper, uri) - if err != nil { return err } - curKey = ret[0].Interface().(string) - } else { - curKey = keyCreate(keyName, xpathPrefix, data) - } - yangReqToDbMapCreate(d, ygRoot, oper, uri, xpathPrefix, curKey, data, result) - } - } else { - if reflect.ValueOf(jsonData).Kind() == reflect.Map { - jData := reflect.ValueOf(jsonData) - for _, key := range jData.MapKeys() { - typeOfValue := reflect.TypeOf(jData.MapIndex(key).Interface()).Kind() + if reflect.ValueOf(jsonData).Kind() == reflect.Slice { + log.Info("slice data: key(\"%v\"), xpathPrefix(\"%v\").", keyName, xpathPrefix) + jData := reflect.ValueOf(jsonData) + dataMap := make([]interface{}, jData.Len()) + for idx := 0; idx < jData.Len(); idx++ { + dataMap[idx] = jData.Index(idx).Interface() + } + for _, data := range dataMap { + curKey := "" + uri = uriWithKeyCreate(uri, xpathPrefix, data) + if len(xSpecMap[xpathPrefix].xfmrKey) > 0 { + /* key transformer present */ + ret, err := XlateFuncCall(yangToDbXfmrFunc(xSpecMap[xpathPrefix].xfmrKey), d, ygRoot, oper, uri) + if err != nil { + return err + } + curKey = ret[0].Interface().(string) + } else { + curKey = keyCreate(keyName, xpathPrefix, data) + } + yangReqToDbMapCreate(d, ygRoot, oper, uri, xpathPrefix, curKey, data, result) + } + } else { + if reflect.ValueOf(jsonData).Kind() == reflect.Map { + jData := reflect.ValueOf(jsonData) + for _, key := range jData.MapKeys() { + typeOfValue := reflect.TypeOf(jData.MapIndex(key).Interface()).Kind() - if typeOfValue == reflect.Map || typeOfValue == reflect.Slice { - log.Info("slice/map data: key(\"%v\"), xpathPrefix(\"%v\").", keyName, xpathPrefix) - xpath := uri - pathAttr := key.String() - if len(xpathPrefix) > 0 { - if strings.Contains(pathAttr, ":") { - pathAttr = strings.Split(pathAttr, ":")[1] - } - xpath = xpathPrefix + "/" + pathAttr - uri = uri + "/" + pathAttr - } + if typeOfValue == reflect.Map || typeOfValue == reflect.Slice { + log.Info("slice/map data: key(\"%v\"), xpathPrefix(\"%v\").", keyName, xpathPrefix) + xpath, err := RemoveXPATHPredicates(uri) + if err != nil { + log.Errorf("yangReqToDbMapCreate: Failed to remove Xpath Predicates from uri %s", uri) + } - if xSpecMap[xpath] != nil && len(xSpecMap[xpath].xfmrFunc) > 0 { - /* subtree transformer present */ - ret, err := XlateFuncCall(yangToDbXfmrFunc(xSpecMap[xpath].xfmrFunc), d, ygRoot, oper, uri) - if err != nil { return nil } - //subMap := callXfmr() - mapCopy(result, ret[0].Interface().(map[string]map[string]db.Value)) - return nil - } else { - yangReqToDbMapCreate(d, ygRoot, oper, uri, xpath, keyName, jData.MapIndex(key).Interface(), result) - } - } else { - pathAttr := key.String() - if strings.Contains(pathAttr, ":") { - pathAttr = strings.Split(pathAttr, ":")[1] - } - value := jData.MapIndex(key).Interface() - log.Info("data field: key(\"%v\"), value(\"%v\").", key, value) - err := mapFillData(d, ygRoot, oper, uri, keyName, result, xpathPrefix, - pathAttr, fmt.Sprintf("%v", value)) - if err != nil { - log.Errorf("Failed constructing data for db write: key(\"%v\"), value(\"%v\"), path(\"%v\").", - pathAttr, value, xpathPrefix) - } - } - } - } - } - return nil + if xSpecMap[xpath] != nil && len(xSpecMap[xpath].xfmrFunc) > 0 { + /* subtree transformer present */ + ret, err := XlateFuncCall(yangToDbXfmrFunc(xSpecMap[xpath].xfmrFunc), d, ygRoot, oper, uri) + if err != nil { + return nil + } + //subMap := callXfmr() + mapCopy(result, ret[0].Interface().(map[string]map[string]db.Value)) + return nil + } else { + yangReqToDbMapCreate(d, ygRoot, oper, uri, xpath, keyName, jData.MapIndex(key).Interface(), result) + } + } else { + pathAttr := key.String() + if strings.Contains(pathAttr, ":") { + pathAttr = strings.Split(pathAttr, ":")[1] + } + value := jData.MapIndex(key).Interface() + log.Info("data field: key(\"%v\"), value(\"%v\").", key, value) + err := mapFillData(d, ygRoot, oper, uri, keyName, result, xpathPrefix, + pathAttr, fmt.Sprintf("%v", value)) + if err != nil { + log.Errorf("Failed constructing data for db write: key(\"%v\"), value(\"%v\"), path(\"%v\").", + pathAttr, value, xpathPrefix) + } + } + } + } + } + return nil } /* Extract key vars, create db key and xpath */ func xpathKeyExtract(path string) (string, string) { - yangXpath := "" - keyStr := "" - rgp := regexp.MustCompile(`\[([^\[\]]*)\]`) + yangXpath := "" + keyStr := "" + rgp := regexp.MustCompile(`\[([^\[\]]*)\]`) - for i, k := range (strings.Split(path, "/")) { - if i > 0 { yangXpath += "/" } - xpath := k - if strings.Contains(k, "[") { - if len(keyStr) > 0 { keyStr += "|" } - xpath = strings.Split(k, "[")[0] - var keyl []string - for _, kname := range rgp.FindAllString(k, -1) { - keyl = append(keyl, strings.TrimRight(strings.TrimLeft(kname, "["), "]")) - } - keyStr += keyFromXpathCreate(keyl) - } - yangXpath += xpath - } - return yangXpath, keyStr + for i, k := range strings.Split(path, "/") { + if i > 0 { + yangXpath += "/" + } + xpath := k + if strings.Contains(k, "[") { + if len(keyStr) > 0 { + keyStr += "|" + } + xpath = strings.Split(k, "[")[0] + var keyl []string + for _, kname := range rgp.FindAllString(k, -1) { + keyl = append(keyl, strings.TrimRight(strings.TrimLeft(kname, "["), "]")) + } + keyStr += keyFromXpathCreate(keyl) + } + yangXpath += xpath + } + return yangXpath, keyStr } /* Debug function to print the map data into file */ -func printDbData (db map[string]map[string]db.Value, fileName string) { - fp, err := os.Create(fileName) - if err != nil { - return - } - defer fp.Close() +func printDbData(db map[string]map[string]db.Value, fileName string) { + fp, err := os.Create(fileName) + if err != nil { + return + } + defer fp.Close() - for k, v := range db { - fmt.Fprintf (fp, "-----------------------------------------------------------------\r\n") - fmt.Fprintf(fp, "table name : %v\r\n", k) - for ik, iv := range v { - fmt.Fprintf(fp, " key : %v\r\n", ik) - for k, d := range iv.Field { - fmt.Fprintf(fp, " %v :%v\r\n", k, d) - } - } - } - fmt.Fprintf (fp, "-----------------------------------------------------------------\r\n") - return + for k, v := range db { + fmt.Fprintf(fp, "-----------------------------------------------------------------\r\n") + fmt.Fprintf(fp, "table name : %v\r\n", k) + for ik, iv := range v { + fmt.Fprintf(fp, " key : %v\r\n", ik) + for k, d := range iv.Field { + fmt.Fprintf(fp, " %v :%v\r\n", k, d) + } + } + } + fmt.Fprintf(fp, "-----------------------------------------------------------------\r\n") + return } From 0dd97717d50b4f7d73dd81ed7b786e19cd9d4b42 Mon Sep 17 00:00:00 2001 From: s-mari Date: Sun, 18 Aug 2019 00:59:31 -0700 Subject: [PATCH 055/214] fixed crash in app transformer special handling code, added code to create full uri with key name-value pair and enabled the field transformer handling part. --- src/translib/transformer/xfmr_acl.go | 20 ++++++++++--- src/translib/transformer/xlate.go | 10 ++++++- src/translib/transformer/xlate_to_db.go | 38 ++++++++----------------- src/translib/transformer/xspec.go | 16 ++--------- 4 files changed, 40 insertions(+), 44 deletions(-) diff --git a/src/translib/transformer/xfmr_acl.go b/src/translib/transformer/xfmr_acl.go index e848aa31fe..d18c5881fe 100644 --- a/src/translib/transformer/xfmr_acl.go +++ b/src/translib/transformer/xfmr_acl.go @@ -687,7 +687,10 @@ var YangToDb_acl_port_bindings_xfmr SubTreeXfmrYangToDb = func (d *db.DB, ygRoot aclInterfacesMap[aclName] = append(aclInterfacesMap[aclName], *intf.Id) } if len(aclTableMap) == 0 { - aclTableMap[aclName] = db.Value{Field: map[string]string{}} + _, ok := aclTableMap[aclName] + if !ok { + aclTableMap[aclName] = db.Value{Field: make(map[string]string)} + } } aclTableMap[aclName].Field["stage"] = "INGRESS" } @@ -701,7 +704,10 @@ var YangToDb_acl_port_bindings_xfmr SubTreeXfmrYangToDb = func (d *db.DB, ygRoot aclInterfacesMap[aclName] = append(aclInterfacesMap[aclName], *intf.Id) } if len(aclTableMap) == 0 { - aclTableMap[aclName] = db.Value{Field: map[string]string{}} + _, ok := aclTableMap[aclName] + if !ok { + aclTableMap[aclName] = db.Value{Field: make(map[string]string)} + } } aclTableMap[aclName].Field["stage"] = "EGRESS" } @@ -709,7 +715,10 @@ var YangToDb_acl_port_bindings_xfmr SubTreeXfmrYangToDb = func (d *db.DB, ygRoot if intf.IngressAclSets == nil && intf.EgressAclSets == nil { for aclName := range aclTableMapDb { if len(aclTableMap) == 0 { - aclTableMap[aclName] = db.Value{Field: map[string]string{}} + _, ok := aclTableMap[aclName] + if !ok { + aclTableMap[aclName] = db.Value{Field: make(map[string]string)} + } } aclEntryDb := aclTableMapDb[aclName] intfsDb := aclEntryDb.GetList("ports") @@ -731,7 +740,10 @@ var YangToDb_acl_port_bindings_xfmr SubTreeXfmrYangToDb = func (d *db.DB, ygRoot } else { for aclName := range aclTableMapDb { if len(aclTableMap) == 0 { - aclTableMap[aclName] = db.Value{Field: map[string]string{}} + _, ok := aclTableMap[aclName] + if !ok { + aclTableMap[aclName] = db.Value{Field: make(map[string]string)} + } } aclEntryDb := aclTableMapDb[aclName] aclTableMap[aclName].Field["stage"] = aclEntryDb.Get("stage") diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index 516bff0036..de723d4e65 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -197,14 +197,22 @@ func XlateToDb(path string, opcode int, d *db.DB, yg *ygot.GoStruct, yt *interfa log.Info("CREATE case") err = dbMapCreate(d, yg, opcode, path, jsonData, result) if err != nil { - log.Errorf("Error: Data translation from yang to db failed.") + log.Errorf("Error: Data translation from yang to db failed for create request.") } case UPDATE: log.Info("UPDATE case") + err = dbMapUpdate(d, yg, opcode, path, jsonData, result) + if err != nil { + log.Errorf("Error: Data translation from yang to db failed for update request.") + } case REPLACE: log.Info("REPLACE case") + err = dbMapUpdate(d, yg, opcode, path, jsonData, result) + if err != nil { + log.Errorf("Error: Data translation from yang to db failed for replace request.") + } case DELETE: log.Info("DELETE case") diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index 80f430b771..6f0008fff7 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -50,15 +50,6 @@ func mapFillData(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, dbKey st return errors.New("Invalid table key") } - if len(xpathInfo.fieldName) == 0 { - log.Info("Field for yang-path(\"%v\") not found in DB.", xpath) - return errors.New("Invalid field name") - } - fieldName := xpathInfo.fieldName - if strings.Contains(value, ":") { - value = strings.Split(value, ":")[1] - } - if len(xpathInfo.xfmrFunc) > 0 { /* field transformer present */ log.Info("Transformer function(\"%v\") invoked for yang path(\"%v\").", xpathInfo.xfmrFunc, xpath) @@ -74,24 +65,21 @@ func mapFillData(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, dbKey st return nil } + if len(xpathInfo.fieldName) == 0 { + log.Info("Field for yang-path(\"%v\") not found in DB.", xpath) + return errors.New("Invalid field name") + } + fieldName := xpathInfo.fieldName + if strings.Contains(value, ":") { + value = strings.Split(value, ":")[1] + } + dataToDBMapAdd(*xpathInfo.tableName, dbKey, result, fieldName, value) log.Info("TblName: \"%v\", key: \"%v\", field: \"%v\", value: \"%v\".", *xpathInfo.tableName, dbKey, fieldName, value) return nil } -func callXfmr() map[string]map[string]db.Value { - result := make(map[string]map[string]db.Value) - result["ACL_TABLE"] = make(map[string]db.Value) - result["ACL_TABLE"]["MyACL1_ACL_IPV4"] = db.Value{Field: make(map[string]string)} - result["ACL_TABLE"]["MyACL1_ACL_IPV4"].Field["stage"] = "INGRESS" - result["ACL_TABLE"]["MyACL1_ACL_IPV4"].Field["ports@"] = "Ethernet0" - result["ACL_TABLE"]["MyACL2_ACL_IPV4"] = db.Value{Field: make(map[string]string)} - result["ACL_TABLE"]["MyACL2_ACL_IPV4"].Field["stage"] = "INGRESS" - result["ACL_TABLE"]["MyACL2_ACL_IPV4"].Field["ports@"] = "Ethernet4" - return result -} - func cvlYangReqToDbMapCreate(jsonData interface{}, result map[string]map[string]db.Value) error { if reflect.ValueOf(jsonData).Kind() == reflect.Map { data := reflect.ValueOf(jsonData) @@ -190,10 +178,10 @@ func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, } for _, data := range dataMap { curKey := "" - uri = uriWithKeyCreate(uri, xpathPrefix, data) + curUri := uriWithKeyCreate(uri, xpathPrefix, data) if len(xSpecMap[xpathPrefix].xfmrKey) > 0 { /* key transformer present */ - ret, err := XlateFuncCall(yangToDbXfmrFunc(xSpecMap[xpathPrefix].xfmrKey), d, ygRoot, oper, uri) + ret, err := XlateFuncCall(yangToDbXfmrFunc(xSpecMap[xpathPrefix].xfmrKey), d, ygRoot, oper, curUri) if err != nil { return err } @@ -201,7 +189,7 @@ func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, } else { curKey = keyCreate(keyName, xpathPrefix, data) } - yangReqToDbMapCreate(d, ygRoot, oper, uri, xpathPrefix, curKey, data, result) + yangReqToDbMapCreate(d, ygRoot, oper, curUri, xpathPrefix, curKey, data, result) } } else { if reflect.ValueOf(jsonData).Kind() == reflect.Map { @@ -222,9 +210,7 @@ func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, if err != nil { return nil } - //subMap := callXfmr() mapCopy(result, ret[0].Interface().(map[string]map[string]db.Value)) - return nil } else { yangReqToDbMapCreate(d, ygRoot, oper, uri, xpath, keyName, jData.MapIndex(key).Interface(), result) } diff --git a/src/translib/transformer/xspec.go b/src/translib/transformer/xspec.go index c36b5114c5..b9eed6efd0 100644 --- a/src/translib/transformer/xspec.go +++ b/src/translib/transformer/xspec.go @@ -273,7 +273,6 @@ func annotToDbMapBuild(annotEntries []*yang.Entry) { for i, deviate := range d.Deviate { if i == 2 { for _, ye := range deviate { - fmt.Println(ye.Name) annotEntryFill(xSpecMap, xpath, ye) } } @@ -300,18 +299,9 @@ func mapPrint(inMap map[string]*yangXpathInfo, fileName string) { if d.tableName != nil { fmt.Fprintf(fp, "%v", *d.tableName) } - fmt.Fprintf(fp, "\r\n FieldName: ") - if len(d.fieldName) > 0 { - fmt.Fprintf(fp, "%v", d.fieldName) - } - fmt.Fprintf(fp, "\r\n xfmrKeyFn: ") - if d.dbEntry != nil { - fmt.Fprintf(fp, "%v\r\n", d.xfmrKey) - } - fmt.Fprintf(fp, "\r\n xfmrFunc: ") - if d.dbEntry != nil { - fmt.Fprintf(fp, "%v\r\n", d.xfmrFunc) - } + fmt.Fprintf(fp, "\r\n FieldName: %v", d.fieldName) + fmt.Fprintf(fp, "\r\n xfmrKeyFn: %v", d.xfmrKey) + fmt.Fprintf(fp, "\r\n xfmrFunc : %v", d.xfmrFunc) fmt.Fprintf(fp, "\r\n yangEntry: ") if d.yangEntry != nil { fmt.Fprintf(fp, "%v", *d.yangEntry) From 8b037098c9d3faa3361509fc394a61da1ccb49b6 Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Sun, 18 Aug 2019 01:42:39 -0700 Subject: [PATCH 056/214] Add support for cvl yang db KeySpec creation and filter dbData for json creation --- src/translib/transformer/xlate.go | 100 +++++++++++++++--------- src/translib/transformer/xlate_to_db.go | 20 +++-- 2 files changed, 77 insertions(+), 43 deletions(-) diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index de723d4e65..a1c697a030 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -115,24 +115,32 @@ func XlateUriToKeySpec(path string, uri *ygot.GoStruct, t *interface{}) (*map[db var retdbFormat = make([]KeySpec, 0) /* Extract the xpath and key from input xpath */ - yangXpath, keyStr := xpathKeyExtract(path) - - if xSpecMap == nil { - return &result, err - } - _, ok := xSpecMap[yangXpath] - if ok { - xpathInfo := xSpecMap[yangXpath] - if xpathInfo.tableName != nil { - dbFormat := KeySpec{} - fillKeySpec(yangXpath, keyStr, &dbFormat) - retdbFormat = append(retdbFormat, dbFormat) - } else { - for _, child := range xpathInfo.childTable { + yangXpath, keyStr, tableName := xpathKeyExtract(path) + + // In case of CVL yang, the tablename and key info is available in the xpath + if tableName != "" { + dbFormat := KeySpec{} + dbFormat.Ts.Name = tableName + dbFormat.Key.Comp = append(dbFormat.Key.Comp, keyStr) + retdbFormat = append(retdbFormat, dbFormat) + } else { + if xSpecMap == nil { + return &result, err + } + _, ok := xSpecMap[yangXpath] + if ok { + xpathInfo := xSpecMap[yangXpath] + if xpathInfo.tableName != nil { dbFormat := KeySpec{} - var childXpath = xDbSpecMap[child].yangXpath[0] - fillKeySpec(childXpath, "", &dbFormat) + fillKeySpec(yangXpath, keyStr, &dbFormat) retdbFormat = append(retdbFormat, dbFormat) + } else { + for _, child := range xpathInfo.childTable { + dbFormat := KeySpec{} + var childXpath = xDbSpecMap[child].yangXpath[0] + fillKeySpec(childXpath, "", &dbFormat) + retdbFormat = append(retdbFormat, dbFormat) + } } } } @@ -222,33 +230,33 @@ func XlateToDb(path string, opcode int, d *db.DB, yg *ygot.GoStruct, yt *interfa func XlateFromDb(xpath string, data map[string]map[string]db.Value) ([]byte, error) { var err error + var fieldName, tableName string var dbData = make(map[string]map[string]db.Value) - yangXpath, keyStr := xpathKeyExtract(xpath) - - if xSpecMap == nil { - return nil, err - } - _, ok := xSpecMap[yangXpath] - if !ok { - return nil, err - } - if xSpecMap[yangXpath].yangDataType == "leaf" { - - var fieldName, tableName string - var dbVal db.Value - - fieldName = xSpecMap[yangXpath].fieldName - tableName = *xSpecMap[yangXpath].tableName + dbData = data + yangXpath, keyStr, tblName := xpathKeyExtract(xpath) - if data[tableName][keyStr].Field != nil { - dbData[tableName] = make(map[string]db.Value) - dbVal.Field = make(map[string]string) - dbVal.Field[fieldName] = data[tableName][keyStr].Field[fieldName] - dbData[tableName][keyStr] = dbVal + if isCvlYang(xpath) { + tableName = tblName + tokens:= strings.Split(xpath, "/") + // Format /module:container/tableName[key]/fieldName + if len(tokens) > 3 { + fieldName = tokens[len(tokens)-1] + dbData = extractFieldFromDb(tableName, keyStr, fieldName, data) } } else { - dbData = data + if xSpecMap == nil { + return nil, err + } + _, ok := xSpecMap[yangXpath] + if !ok { + return nil, err + } + if xSpecMap[yangXpath].yangDataType == "leaf" { + fieldName = xSpecMap[yangXpath].fieldName + tableName = *xSpecMap[yangXpath].tableName + dbData = extractFieldFromDb(tableName, keyStr, fieldName, data) + } } payload, err := dbDataToYangJsonCreate(yangXpath, dbData) @@ -263,3 +271,19 @@ func XlateFromDb(xpath string, data map[string]map[string]db.Value) ([]byte, err return result, err } + +func extractFieldFromDb(tableName string, keyStr string, fieldName string, data map[string]map[string]db.Value) (map[string]map[string]db.Value) { + + var dbVal db.Value + var dbData = make(map[string]map[string]db.Value) + + if tableName != "" && keyStr != "" && fieldName != "" { + if data[tableName][keyStr].Field != nil { + dbData[tableName] = make(map[string]db.Value) + dbVal.Field = make(map[string]string) + dbVal.Field[fieldName] = data[tableName][keyStr].Field[fieldName] + dbData[tableName][keyStr] = dbVal + } + } + return dbData +} diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index 6f0008fff7..e64c34ff32 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -127,7 +127,7 @@ func directDbMapData(tableName string, jsonData interface{}, result map[string]m /* Get the db table, key and field name for the incoming delete request */ func dbMapDelete(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string, jsonData interface{}, result map[string]map[string]db.Value) error { - xpathPrefix, keyName := xpathKeyExtract(path) + xpathPrefix, keyName, _ := xpathKeyExtract(path) log.Info("Delete req: path(\"%v\"), key(\"%v\"), xpathPrefix(\"%v\").", path, keyName, xpathPrefix) spec, ok := xSpecMap[xpathPrefix] if ok && spec.tableName != nil { @@ -146,7 +146,7 @@ func dbMapDelete(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string, jsonDat /* Get the data from incoming update/replace request, create map and fill with dbValue(ie. field:value to write into redis-db */ func dbMapUpdate(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string, jsonData interface{}, result map[string]map[string]db.Value) error { - xpathPrefix, keyName := xpathKeyExtract(path) + xpathPrefix, keyName , _ := xpathKeyExtract(path) log.Info("Update/replace req: path(\"%v\"), key(\"%v\"), xpathPrefix(\"%v\").", path, keyName, xpathPrefix) dbMapCreate(d, ygRoot, oper, parentXpathGet(xpathPrefix), jsonData, result) log.Info("Update/replace req: path(\"%v\") result(\"%v\").", path, result) @@ -156,7 +156,7 @@ func dbMapUpdate(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string, jsonDat /* Get the data from incoming create request, create map and fill with dbValue(ie. field:value to write into redis-db */ func dbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string, jsonData interface{}, result map[string]map[string]db.Value) error { - xpathTmplt, keyName := xpathKeyExtract(path) + xpathTmplt, keyName, _ := xpathKeyExtract(path) if isCvlYang(path) { cvlYangReqToDbMapCreate(jsonData, result) } else { @@ -235,9 +235,10 @@ func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, } /* Extract key vars, create db key and xpath */ -func xpathKeyExtract(path string) (string, string) { +func xpathKeyExtract(path string) (string, string, string) { yangXpath := "" keyStr := "" + tableName := "" rgp := regexp.MustCompile(`\[([^\[\]]*)\]`) for i, k := range strings.Split(path, "/") { @@ -257,8 +258,17 @@ func xpathKeyExtract(path string) (string, string) { keyStr += keyFromXpathCreate(keyl) } yangXpath += xpath + if i == 2 { + if isCvlYang(path) { + //Format- /module:container/table[key]/field + // table name is the 3rd entry in tokenized string + tableName = xpath + } + } } - return yangXpath, keyStr + + fmt.Println(tableName) + return yangXpath, keyStr, tableName } /* Debug function to print the map data into file */ From 92e77cb8a0ebef6a9924f8d0d7699d420c921058 Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Mon, 19 Aug 2019 11:14:14 -0700 Subject: [PATCH 057/214] Avoid using index values to identify the table and field names in cvl xpath parsing --- src/translib/transformer/xlate.go | 4 ++-- src/translib/transformer/xlate_to_db.go | 6 ++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index a1c697a030..4d234057ed 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -238,9 +238,9 @@ func XlateFromDb(xpath string, data map[string]map[string]db.Value) ([]byte, err if isCvlYang(xpath) { tableName = tblName - tokens:= strings.Split(xpath, "/") + tokens:= strings.Split(yangXpath, "/") // Format /module:container/tableName[key]/fieldName - if len(tokens) > 3 { + if tokens[len(tokens)-2] == tableName { fieldName = tokens[len(tokens)-1] dbData = extractFieldFromDb(tableName, keyStr, fieldName, data) } diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index e64c34ff32..3ad05dde7a 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -256,15 +256,13 @@ func xpathKeyExtract(path string) (string, string, string) { keyl = append(keyl, strings.TrimRight(strings.TrimLeft(kname, "["), "]")) } keyStr += keyFromXpathCreate(keyl) - } - yangXpath += xpath - if i == 2 { if isCvlYang(path) { //Format- /module:container/table[key]/field - // table name is the 3rd entry in tokenized string + // table name extracted from the string token having key entry tableName = xpath } } + yangXpath += xpath } fmt.Println(tableName) From 8ff86830682340fb5f1f37e943ea96c4b47d278b Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Mon, 19 Aug 2019 12:52:02 -0700 Subject: [PATCH 058/214] Goyang patch to introduce "ordered by insertion" list entry in yang.Entry --- Makefile | 1 + goyang-modified-files/entry.go | 1453 ++++++++++++++++++++++++++++++++ 2 files changed, 1454 insertions(+) create mode 100644 goyang-modified-files/entry.go diff --git a/Makefile b/Makefile index d7504ab0bc..a9e4fb7c45 100644 --- a/Makefile +++ b/Makefile @@ -92,6 +92,7 @@ cp $(TOPDIR)/ygot-modified-files/reflect.go $(BUILD_GOPATH)/src/github.com/openc cp $(TOPDIR)/goyang-modified-files/README.md $(BUILD_GOPATH)/src/github.com/openconfig/goyang/README.md; \ cp $(TOPDIR)/goyang-modified-files/yang.go $(BUILD_GOPATH)/src/github.com/openconfig/goyang/yang.go; \ cp $(TOPDIR)/goyang-modified-files/annotate.go $(BUILD_GOPATH)/src/github.com/openconfig/goyang/annotate.go; \ +cp $(TOPDIR)/goyang-modified-files/entry.go $(BUILD_GOPATH)/src/github.com/openconfig/goyang/pkg/yang/entry.go; \ $(GO) install -v -gcflags "-N -l" $(BUILD_GOPATH)/src/github.com/openconfig/ygot/ygot; \ $(GO) install -v -gcflags "-N -l" $(BUILD_GOPATH)/src/github.com/openconfig/goyang diff --git a/goyang-modified-files/entry.go b/goyang-modified-files/entry.go new file mode 100644 index 0000000000..6b7870f924 --- /dev/null +++ b/goyang-modified-files/entry.go @@ -0,0 +1,1453 @@ +// Copyright 2015 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package yang + +// The file contains the code to convert an AST (Node) tree into an Entry tree +// via the ToEntry function. The entry tree, once fully resolved, is the +// product of this package. The tree should have all types and references +// resolved. +// +// TODO(borman): handle types, leafrefs, and extensions + +import ( + "errors" + "fmt" + "io" + "reflect" + "sort" + "strconv" + "strings" + + "github.com/openconfig/goyang/pkg/indent" +) + +// A TriState may be true, false, or unset +type TriState int + +// The possible states of a TriState. +const ( + TSUnset = TriState(iota) + TSTrue + TSFalse +) + +// Value returns the value of t as a boolean. Unset is returned as false. +func (t TriState) Value() bool { + return t == TSTrue +} + +// String displays t as a string. +func (t TriState) String() string { + switch t { + case TSUnset: + return "unset" + case TSTrue: + return "true" + case TSFalse: + return "false" + default: + return fmt.Sprintf("ts-%d", t) + } +} + +// An Entry represents a single node (directory or leaf) created from the +// AST. Directory entries have a non-nil Dir entry. Leaf nodes have a nil +// Dir entry. If Errors is not nil then the only other valid field is Node. +type Entry struct { + Parent *Entry `json:"-"` + Node Node `json:"-"` // the base node this Entry was derived from. + Name string // our name, same as the key in our parent Dirs + Description string `json:",omitempty"` // description from node, if any + Default string `json:",omitempty"` // default from node, if any + Units string `json:",omitempty"` // units associated with the type, if any + Errors []error `json:"-"` // list of errors encountered on this node + Kind EntryKind // kind of Entry + Config TriState // config state of this entry, if known + Prefix *Value `json:",omitempty"` // prefix to use from this point down + Mandatory TriState `json:",omitempty"` // whether this entry is mandatory in the tree + + // Fields associated with directory nodes + Dir map[string]*Entry `json:",omitempty"` + DirOKeys []string // Ordered Keys list in Dir + Key string `json:",omitempty"` // Optional key name for lists (i.e., maps) + + // Fields associated with leaf nodes + Type *YangType `json:",omitempty"` + Exts []*Statement `json:",omitempty"` // extensions found + + // Fields associated with list nodes (both lists and leaf-lists) + ListAttr *ListAttr `json:",omitempty"` + + RPC *RPCEntry `json:",omitempty"` // set if we are an RPC + + // Identities that are defined in this context, this is set if the Entry + // is a module only. + Identities []*Identity `json:",omitempty"` + + Augments []*Entry `json:",omitempty"` // Augments defined in this entry. + Augmented []*Entry `json:",omitempty"` // Augments merged into this entry. + Deviations []*DeviatedEntry `json:"-"` // Deviations associated with this entry. + Deviate map[deviationType][]*Entry `json:"-"` + Uses []*UsesStmt `json:",omitempty"` // Uses merged into this entry. + + // Extra maps all the unsupported fields to their values + Extra map[string][]interface{} `json:"-"` + + // Annotation stores annotated values, and is not populated by this + // library but rather can be used by calling code where additional + // information should be stored alongside the Entry. + Annotation map[string]interface{} `json:",omitempty"` + + // namespace stores the namespace of the Entry if it overrides the + // root namespace within the schema tree. This is the case where an + // entry is augmented into the tree, and it retains the namespace of + // the augmenting entity per RFC6020 Section 7.15.2. The namespace + // of the Entry should be accessed using the Namespace function. + namespace *Value +} + +// An RPCEntry contains information related to an RPC Node. +type RPCEntry struct { + Input *Entry + Output *Entry +} + +// A ListAttr is associated with an Entry that represents a List node +type ListAttr struct { + MinElements *Value // leaf-list or list MUST have at least min-elements + MaxElements *Value // leaf-list or list has at most max-elements + OrderedBy *Value // order of entries determined by "system" or "user" +} + +// A UsesStmt associates a *Uses with its referenced grouping *Entry +type UsesStmt struct { + Uses *Uses + Grouping *Entry +} + +// Modules returns the Modules structure that e is part of. This is needed +// when looking for rooted nodes not part of this Entry tree. +func (e *Entry) Modules() *Modules { + for e.Parent != nil { + e = e.Parent + } + return e.Node.(*Module).modules +} + +// IsDir returns true if e is a directory. +func (e *Entry) IsDir() bool { + return e.Dir != nil +} + +// IsLeaf returns true if e is a leaf i.e. is not a container, list, leaf-list, +// choice or case statement. +func (e *Entry) IsLeaf() bool { + return !e.IsDir() && e.Kind == LeafEntry && e.ListAttr == nil +} + +// IsLeafList returns true if e is a leaf-list. +func (e *Entry) IsLeafList() bool { + return !e.IsDir() && e.Kind == LeafEntry && e.ListAttr != nil +} + +// IsList returns true if e is a list. +func (e *Entry) IsList() bool { + return e.IsDir() && e.ListAttr != nil +} + +// IsContainer returns true if e is a container. +func (e *Entry) IsContainer() bool { + return e.Kind == DirectoryEntry && e.ListAttr == nil +} + +// IsChoice returns true if the entry is a choice node within the schema. +func (e *Entry) IsChoice() bool { + return e.Kind == ChoiceEntry +} + +// IsCase returns true if the entry is a case node within the schema. +func (e *Entry) IsCase() bool { + return e.Kind == CaseEntry +} + +// Print prints e to w in human readable form. +func (e *Entry) Print(w io.Writer) { + if e.Description != "" { + fmt.Fprintln(w) + fmt.Fprintln(indent.NewWriter(w, "// "), e.Description) + } + if e.ReadOnly() { + fmt.Fprintf(w, "RO: ") + } else { + fmt.Fprintf(w, "rw: ") + } + if e.Type != nil { + fmt.Fprintf(w, "%s ", e.Type.Name) + } + switch { + case e.Dir == nil && e.ListAttr != nil: + fmt.Fprintf(w, "[]%s\n", e.Name) + return + case e.Dir == nil: + fmt.Fprintf(w, "%s\n", e.Name) + return + case e.ListAttr != nil: + fmt.Fprintf(w, "[%s]%s {\n", e.Key, e.Name) //} + default: + fmt.Fprintf(w, "%s {\n", e.Name) //} + } + var names []string + for k := range e.Dir { + names = append(names, k) + } + sort.Strings(names) + for _, k := range names { + e.Dir[k].Print(indent.NewWriter(w, " ")) + } + // { to match the brace below to keep brace matching working + fmt.Fprintln(w, "}") +} + +// An EntryKind is the kind of node an Entry is. All leaf nodes are of kind +// LeafEntry. A LeafList is also considered a leaf node. All other kinds are +// directory nodes. +type EntryKind int + +// Enumeration of the types of entries. +const ( + LeafEntry = EntryKind(iota) + DirectoryEntry + AnyDataEntry + AnyXMLEntry + CaseEntry + ChoiceEntry + InputEntry + NotificationEntry + OutputEntry + DeviateEntry +) + +// EntryKindToName maps EntryKind to their names +var EntryKindToName = map[EntryKind]string{ + LeafEntry: "Leaf", + DirectoryEntry: "Directory", + AnyDataEntry: "AnyData", + AnyXMLEntry: "AnyXML", + CaseEntry: "Case", + ChoiceEntry: "Choice", + InputEntry: "Input", + NotificationEntry: "Notification", + OutputEntry: "Output", + DeviateEntry: "Deviate", +} + +func (k EntryKind) String() string { + if s := EntryKindToName[k]; s != "" { + return s + } + return fmt.Sprintf("unknown-entry-%d", k) +} + +// newDirectory returns an empty directory Entry. +func newDirectory(n Node) *Entry { + return &Entry{ + Kind: DirectoryEntry, + Dir: make(map[string]*Entry), + DirOKeys: make([]string, 0), + Node: n, + Name: n.NName(), + Extra: map[string][]interface{}{}, + } +} + +// newLeaf returns an empty leaf Entry. +func newLeaf(n Node) *Entry { + return &Entry{ + Kind: LeafEntry, + Node: n, + Name: n.NName(), + Extra: map[string][]interface{}{}, + } +} + +// newError returns an error node using format and v to create the error +// contained in the node. The location of the error is prepended. +func newError(n Node, format string, v ...interface{}) *Entry { + e := &Entry{Node: n} + e.errorf("%s: "+format, append([]interface{}{Source(n)}, v...)...) + return e +} + +// errorf appends the entry constructed from string and v to the list of errors +// on e. +func (e *Entry) errorf(format string, v ...interface{}) { + e.Errors = append(e.Errors, fmt.Errorf(format, v...)) +} + +// addError appends err to the list of errors on e if err is not nil. +func (e *Entry) addError(err error) { + if err != nil { + e.Errors = append(e.Errors, err) + } +} + +// importErrors imports all the errors from c and its children into e. +func (e *Entry) importErrors(c *Entry) { + if c == nil { + return + } + for _, err := range c.Errors { + e.addError(err) + } + // TODO(borman): need to determine if the extensions have errors + // for _, ce := range e.Exts { + // e.importErrors(ce) + // } + for _, ce := range c.Dir { + e.importErrors(ce) + } +} + +// checkErrors calls f on every error found in the tree e and its children. +func (e *Entry) checkErrors(f func(error)) { + if e == nil { + return + } + for _, e := range e.Dir { + e.checkErrors(f) + } + for _, err := range e.Errors { + f(err) + } + // TODO(borman): need to determine if the extensions have errors + // for _, e := range e.Exts { + // e.checkErrors(f) + // } +} + +// GetErrors returns a sorted list of errors found in e. +func (e *Entry) GetErrors() []error { + // the seen map is used to eliminate duplicate errors. + // Some entries will be processed more than once + // (groupings in particular) and as such may cause + // duplication of errors. + seen := map[error]bool{} + var errs []error + e.checkErrors(func(err error) { + if !seen[err] { + errs = append(errs, err) + seen[err] = true + } + }) + return errorSort(errs) +} + +// asKind sets the kind of e to k and returns e. +func (e *Entry) asKind(k EntryKind) *Entry { + e.Kind = k + return e +} + +// add adds the directory entry key assigned to the provided value. +func (e *Entry) add(key string, value *Entry) *Entry { + value.Parent = e + if e.Dir[key] != nil { + e.errorf("%s: duplicate key from %s: %s", Source(e.Node), Source(value.Node), key) + return e + } + e.Dir[key] = value + e.DirOKeys = append(e.DirOKeys, key) + return e +} + +// delete removes the directory entry key from the entry. +func (e *Entry) delete(key string) { + if _, ok := e.Dir[key]; !ok { + e.errorf("%s: unknown child key %s", Source(e.Node), key) + } + delete(e.Dir, key) +} + +// GetWhenXPath returns the when XPath statement of e if able. +func (e *Entry) GetWhenXPath() (string, bool) { + switch n := e.Node.(type) { + case *Container: + if n.When != nil && n.When.Statement() != nil { + return n.When.Statement().Arg() + } + case *Leaf: + if n.When != nil && n.When.Statement() != nil { + return n.When.Statement().Arg() + } + case *LeafList: + if n.When != nil && n.When.Statement() != nil { + return n.When.Statement().Arg() + } + case *List: + if n.When != nil && n.When.Statement() != nil { + return n.When.Statement().Arg() + } + case *Choice: + if n.When != nil && n.When.Statement() != nil { + return n.When.Statement().Arg() + } + case *Case: + if n.When != nil && n.When.Statement() != nil { + return n.When.Statement().Arg() + } + case *AnyXML: + if n.When != nil && n.When.Statement() != nil { + return n.When.Statement().Arg() + } + case *AnyData: + if n.When != nil && n.When.Statement() != nil { + return n.When.Statement().Arg() + } + case *Augment: + if n.When != nil && n.When.Statement() != nil { + return n.When.Statement().Arg() + } + } + return "", false +} + +// entryCache is used to prevent unnecessary recursion into previously +// converted nodes. +var entryCache = map[Node]*Entry{} + +// mergedSubmodule is used to prevent re-parsing a submodule that has already +// been merged into a particular entity when circular dependencies are being +// ignored. The keys of the map are a string that is formed by concatenating +// the name of the including (sub)module and the included submodule. +var mergedSubmodule = map[string]bool{} + +var depth = 0 + +// deviationType specifies an enumerated value covering the different substmts +// to the deviate statement. +type deviationType int64 + +const ( + // DeviationUnset specifies that the argument was unset, which is invalid. + DeviationUnset deviationType = iota + // DeviationNotSupported corresponds to the not-supported deviate argument. + DeviationNotSupported + // DeviationAdd corresponds to the add deviate argument to the deviate stmt. + DeviationAdd + // DeviationReplace corresponds to the replace argument to the deviate stmt. + DeviationReplace + // DeviationDelete corresponds to the delete argument to the deviate stmt. + DeviationDelete +) + +var ( + // fromDeviation maps from an enumerated deviation type to the YANG keyword. + fromDeviation = map[deviationType]string{ + DeviationNotSupported: "not-supported", + DeviationAdd: "add", + DeviationReplace: "replace", + DeviationDelete: "delete", + DeviationUnset: "unknown", + } + + // toDeviation maps from the YANG keyword to an enumerated deviation typee. + toDeviation = map[string]deviationType{ + "not-supported": DeviationNotSupported, + "add": DeviationAdd, + "replace": DeviationReplace, + "delete": DeviationDelete, + } +) + +func (d deviationType) String() string { + return fromDeviation[d] +} + +// DeviatedEntry stores a wrapped Entry that corresponds to a deviation. +type DeviatedEntry struct { + Type deviationType // Type specifies the deviation type. + DeviatedPath string // DeviatedPath corresponds to the path that is being deviated. + // Entry is the embedded Entry storing the deviations that are made. Fields + // are set to the value in the schema after the deviation has been applied. + *Entry +} + +// ToEntry expands node n into a directory Entry. Expansion is based on the +// YANG tags in the structure behind n. ToEntry must only be used +// with nodes that are directories, such as top level modules and sub-modules. +// ToEntry never returns nil. Any errors encountered are found in the Errors +// fields of the returned Entry and its children. Use GetErrors to determine +// if there were any errors. +func ToEntry(n Node) (e *Entry) { + if n == nil { + err := errors.New("ToEntry called with nil") + return &Entry{ + Node: &ErrorNode{Error: err}, + Errors: []error{err}, + } + } + if e := entryCache[n]; e != nil { + return e + } + defer func() { + entryCache[n] = e + }() + + // Copy in the extensions from our Node, if any. + defer func(n Node) { + if e != nil { + for _, ext := range n.Exts() { + e.Exts = append(e.Exts, ext) + } + } + }(n) + + // tristateValue returns TSTrue if i contains the value of true, TSFalse + // if it contains the value of false, and TSUnset if i does not have + // a set value (for instance, i is nil). An error is returned if i + // contains a value other than true or false. + tristateValue := func(i interface{}) (TriState, error) { + if v, ok := i.(*Value); ok && v != nil { + switch v.Name { + case "true": + return TSTrue, nil + case "false": + return TSFalse, nil + default: + return TSUnset, fmt.Errorf("%s: invalid config value: %s", Source(n), v.Name) + } + } + return TSUnset, nil + } + + var err error + // Handle non-directory nodes (leaf, leafref, and oddly enough, uses). + switch s := n.(type) { + case *Leaf: + e := newLeaf(n) + if errs := s.Type.resolve(); errs != nil { + e.Errors = errs + } + if s.Description != nil { + e.Description = s.Description.Name + } + if s.Default != nil { + e.Default = s.Default.Name + } + e.Type = s.Type.YangType + entryCache[n] = e + e.Config, err = tristateValue(s.Config) + e.addError(err) + e.Prefix = getRootPrefix(e) + return e + case *LeafList: + // Create the equivalent leaf element that we are a list of. + // We can then just annotate it as a list rather than a leaf. + leaf := &Leaf{ + Name: s.Name, + Source: s.Source, + Parent: s.Parent, + Extensions: s.Extensions, + Config: s.Config, + Description: s.Description, + IfFeature: s.IfFeature, + Must: s.Must, + Reference: s.Reference, + Status: s.Status, + Type: s.Type, + Units: s.Units, + When: s.When, + } + + e := ToEntry(leaf) + e.ListAttr = &ListAttr{ + MinElements: s.MinElements, + MaxElements: s.MaxElements, + OrderedBy: s.OrderedBy, + } + e.Prefix = getRootPrefix(e) + return e + case *Uses: + g := FindGrouping(s, s.Name, map[string]bool{}) + if g == nil { + return newError(n, "unknown group: %s", s.Name) + } + // We need to return a duplicate so we resolve properly + // when the group is used in multiple locations and the + // grouping has a leafref that references outside the group. + return ToEntry(g).dup() + } + + e = newDirectory(n) + + // Special handling for individual Node types. Lists are like any other + // node except a List has a ListAttr. + // + // Nodes of identified special kinds have their Kind set here. + switch s := n.(type) { + case *List: + e.ListAttr = &ListAttr{ + MinElements: s.MinElements, + MaxElements: s.MaxElements, + OrderedBy: s.OrderedBy, + } + case *Choice: + e.Kind = ChoiceEntry + if s.Default != nil { + e.Default = s.Default.Name + } + case *Case: + e.Kind = CaseEntry + case *AnyData: + e.Kind = AnyDataEntry + case *AnyXML: + e.Kind = AnyXMLEntry + case *Input: + e.Kind = InputEntry + case *Output: + e.Kind = OutputEntry + case *Notification: + e.Kind = NotificationEntry + case *Deviate: + e.Kind = DeviateEntry + } + + // Use Elem to get the Value of structure that n is pointing to, not + // the Value of the pointer. + v := reflect.ValueOf(n).Elem() + t := v.Type() + found := false + + for i := t.NumField() - 1; i > 0; i-- { + f := t.Field(i) + yang := f.Tag.Get("yang") + if yang == "" { + continue + } + fv := v.Field(i) + name := strings.Split(yang, ",")[0] + switch name { + case "": + e.addError(fmt.Errorf("%s: nil statement", Source(n))) + case "config": + e.Config, err = tristateValue(fv.Interface()) + e.addError(err) + case "description": + if v := fv.Interface().(*Value); v != nil { + e.Description = v.Name + } + case "prefix": + if v := fv.Interface().(*Value); v != nil { + e.Prefix = v + } + case "action": + for _, r := range fv.Interface().([]*Action) { + e.add(r.Name, ToEntry(r)) + } + case "augment": + for _, a := range fv.Interface().([]*Augment) { + ne := ToEntry(a) + ne.Parent = e + e.Augments = append(e.Augments, ne) + } + case "anydata": + for _, a := range fv.Interface().([]*AnyData) { + e.add(a.Name, ToEntry(a)) + } + case "anyxml": + for _, a := range fv.Interface().([]*AnyXML) { + e.add(a.Name, ToEntry(a)) + } + case "case": + for _, a := range fv.Interface().([]*Case) { + e.add(a.Name, ToEntry(a)) + } + case "choice": + for _, a := range fv.Interface().([]*Choice) { + e.add(a.Name, ToEntry(a)) + } + case "container": + for _, a := range fv.Interface().([]*Container) { + e.add(a.Name, ToEntry(a)) + } + case "grouping": + for _, a := range fv.Interface().([]*Grouping) { + // We just want to parse the grouping to + // collect errors. + e.importErrors(ToEntry(a)) + } + case "import": + // Apparently import only makes types and such + // available. There is nothing else for us to do. + case "include": + for _, a := range fv.Interface().([]*Include) { + // Handle circular dependencies between submodules. This can occur in + // two ways: + // - Where submodule A imports submodule B, and vice versa then the + // whilst processing A we will also try and process A (learnt via + // B). The default case of the switch handles this case. + // - Where submodule A imports submodule B that imports C, which also + // imports A, then we need to check whether we already have merged + // the specified module during this parse attempt. We check this + // against a map of merged submodules. + // The key of the map used is a synthesised value which is formed by + // concatenating the name of this node and the included submodule, + // separated by a ":". + srcToIncluded := a.Module.Name + ":" + n.NName() + includedToSrc := n.NName() + ":" + a.Module.Name + + switch { + case mergedSubmodule[srcToIncluded]: + // We have already merged this module, so don't try and do it + // again. + continue + case !mergedSubmodule[includedToSrc] && a.Module.NName() != n.NName(): + // We have not merged A->B, and B != B hence go ahead and merge. + includedToParent := a.Module.Name + ":" + a.Module.BelongsTo.Name + if mergedSubmodule[includedToParent] { + // Don't try and re-import submodules that have already been imported + // into the top-level module. Note that this ensures that we get to the + // top the tree (whichever the actual module for the chain of + // submodules is). The tracking of the immediate parent is achieved + // through 'key', which ensures that we do not end up in loops + // walking through a sub-cycle of the include graph. + continue + } + mergedSubmodule[srcToIncluded] = true + mergedSubmodule[includedToParent] = true + e.merge(a.Module.Prefix, nil, ToEntry(a.Module)) + case ParseOptions.IgnoreSubmoduleCircularDependencies: + continue + default: + e.addError(fmt.Errorf("%s: has a circular dependency, importing %s", n.NName(), a.Module.NName())) + } + } + case "leaf": + for _, a := range fv.Interface().([]*Leaf) { + e.add(a.Name, ToEntry(a)) + } + case "leaf-list": + for _, a := range fv.Interface().([]*LeafList) { + e.add(a.Name, ToEntry(a)) + } + case "list": + for _, a := range fv.Interface().([]*List) { + e.add(a.Name, ToEntry(a)) + } + case "key": + if v := fv.Interface().(*Value); v != nil { + e.Key = v.Name + } + case "notification": + for _, a := range fv.Interface().([]*Notification) { + e.add(a.Name, ToEntry(a)) + } + case "rpc": + // TODO(borman): what do we do with these? + // seems fine to ignore them for now, we are + // just interested in the tree structure. + for _, r := range fv.Interface().([]*RPC) { + switch rpc := ToEntry(r); { + case rpc.RPC == nil: + // When "rpc" has no "input" or "output" children + rpc.RPC = &RPCEntry{} + fallthrough + default: + e.add(r.Name, rpc) + } + } + + case "input": + if i := fv.Interface().(*Input); i != nil { + if e.RPC == nil { + e.RPC = &RPCEntry{} + } + in := ToEntry(i) + in.Parent = e + e.RPC.Input = in + e.RPC.Input.Name = "input" + e.RPC.Input.Kind = InputEntry + } + case "output": + if o := fv.Interface().(*Output); o != nil { + if e.RPC == nil { + e.RPC = &RPCEntry{} + } + out := ToEntry(o) + out.Parent = e + e.RPC.Output = out + e.RPC.Output.Name = "output" + e.RPC.Output.Kind = OutputEntry + } + case "identity": + if i := fv.Interface().([]*Identity); i != nil { + e.Identities = i + } + case "uses": + for _, a := range fv.Interface().([]*Uses) { + grouping := ToEntry(a) + e.merge(nil, nil, grouping) + if ParseOptions.StoreUses { + e.Uses = append(e.Uses, &UsesStmt{a, grouping.shallowDup()}) + } + } + case "type": + // The type keyword is specific to deviate to change a type. Other type handling + // (e.g., leaf type resolution) is done outside of this case. + n, ok := n.(*Deviate) + if !ok { + e.addError(fmt.Errorf("unexpected type found, only valid under Deviate, is %T", n)) + continue + } + + if n.Type != nil { + if errs := n.Type.resolve(); errs != nil { + e.addError(fmt.Errorf("deviation has unresolvable type, %v", errs)) + continue + } + e.Type = n.Type.YangType + } + continue + // Keywords that do not need to be handled as an Entry as they are added + // to other dictionaries. + case "default": + if e.Kind == LeafEntry { + // default is handled separately for a leaf, but in a deviate statement + // we must deal with it here. + continue + } + d, ok := fv.Interface().(*Value) + if !ok { + e.addError(fmt.Errorf("%s: unexpected default type in %s:%s", Source(n), n.Kind(), n.NName())) + } + e.Default = d.asString() + case "typedef": + continue + case "deviation": + if a := fv.Interface().([]*Deviation); a != nil { + for _, d := range a { + e.Deviations = append(e.Deviations, &DeviatedEntry{ + Entry: ToEntry(d), + DeviatedPath: d.Statement().Argument, + }) + + for _, sd := range d.Deviate { + if sd.Type != nil { + sd.Type.resolve() + } + } + } + } + case "deviate": + if a := fv.Interface().([]*Deviate); a != nil { + for _, d := range a { + de := ToEntry(d) + + dt, ok := toDeviation[d.Statement().Argument] + if !ok { + e.addError(fmt.Errorf("%s: unknown deviation type in %s:%s", Source(n), n.Kind(), n.NName())) + continue + } + + if e.Deviate == nil { + e.Deviate = map[deviationType][]*Entry{} + } + + e.Deviate[dt] = append(e.Deviate[dt], de) + } + } + case "mandatory": + v, ok := fv.Interface().(*Value) + if !ok { + e.addError(fmt.Errorf("%s: did not get expected value type", Source(n))) + } + e.Mandatory, err = tristateValue(v) + e.addError(err) + case "max-elements", "min-elements": + if e.Kind != DeviateEntry { + continue + } + // we can get max-elements or min-elements in a deviate statement, so create the + // corresponding logic. + v, ok := fv.Interface().(*Value) + if !ok { + e.addError(fmt.Errorf("%s: max or min elements had wrong type, %s:%s", Source(n), n.Kind(), n.NName())) + continue + } + + if e.ListAttr == nil { + e.ListAttr = &ListAttr{} + } + + if name == "max-elements" { + e.ListAttr.MaxElements = v + } else { + e.ListAttr.MinElements = v + } + case "units": + v, ok := fv.Interface().(*Value) + if !ok { + e.addError(fmt.Errorf("%s: units had wrong type, %s:%s", Source(n), n.Kind(), n.NName())) + } + if v != nil { + e.Units = v.asString() + } + // TODO(borman): unimplemented keywords + case "belongs-to", + "contact", + "extension", + "feature", + "if-feature", + "must", + "namespace", + "ordered-by", + "organization", + "presence", + "reference", + "revision", + "status", + "unique", + "when", + "yang-version": + e.Extra[name] = append(e.Extra[name], fv.Interface()) + continue + + case "Ext", "Name", "Parent", "Statement": + // These are meta-keywords used internally + continue + default: + e.addError(fmt.Errorf("%s: unexpected statement: %s", Source(n), name)) + continue + + } + // We found at least one field. + found = true + } + if !found { + return newError(n, "%T: cannot be converted to a *Entry", n) + } + // If prefix isn't set, provide it based on our root node (module) + if e.Prefix == nil { + e.Prefix = getRootPrefix(e) + } + + return e +} + +// getRootPrefix returns the prefix of e's root node (module) +func getRootPrefix(e *Entry) *Value { + if m := RootNode(e.Node); m != nil { + return m.getPrefix() + } + return nil +} + +// Augment processes augments in e, return the number of augments processed +// and the augments skipped. If addErrors is true then missing augments will +// generate errors. +func (e *Entry) Augment(addErrors bool) (processed, skipped int) { + // Now process the augments we found + // NOTE(borman): is it possible this will fail if the augment refers + // to some removed sibling that has not been processed? Perhaps this + // should be done after the entire tree is built. Is it correct to + // assume augment paths are data tree paths and not schema tree paths? + // Augments can depend upon augments. We need to figure out how to + // order the augments (or just keep trying until we can make no further + // progress) + var sa []*Entry + for _, a := range e.Augments { + ae := a.Find(a.Name) + if ae == nil { + if addErrors { + e.errorf("%s: augment %s not found", Source(a.Node), a.Name) + } + skipped++ + sa = append(sa, a) + continue + } + // Augments do not have a prefix we merge in, just a node. + // We retain the namespace from the original context of the + // augment since the nodes have this namespace even though they + // are merged into another entry. + processed++ + ae.merge(nil, a.Namespace(), a) + ae.Augmented = append(ae.Augmented, a.shallowDup()) + } + e.Augments = sa + return processed, skipped +} + +// ApplyDeviate walks the deviations within the supplied entry, and applies them to the +// schema. +func (e *Entry) ApplyDeviate() []error { + var errs []error + appendErr := func(err error) { errs = append(errs, err) } + for _, d := range e.Deviations { + deviatedNode := e.Find(d.DeviatedPath) + if deviatedNode == nil { + appendErr(fmt.Errorf("cannot find target node to deviate, %s", d.DeviatedPath)) + continue + } + + for dt, dv := range d.Deviate { + for _, devSpec := range dv { + switch dt { + case DeviationAdd, DeviationReplace: + if devSpec.Config != TSUnset { + deviatedNode.Config = devSpec.Config + } + + if devSpec.Default != "" { + deviatedNode.Default = "" + } + + if devSpec.Mandatory != TSUnset { + deviatedNode.Mandatory = devSpec.Mandatory + } + + if devSpec.ListAttr != nil && devSpec.ListAttr.MinElements != nil { + if !deviatedNode.IsList() && !deviatedNode.IsLeafList() { + appendErr(fmt.Errorf("tried to deviate min-elements on a non-list type %s", deviatedNode.Kind)) + continue + } + deviatedNode.ListAttr.MinElements = devSpec.ListAttr.MinElements + } + + if devSpec.ListAttr != nil && devSpec.ListAttr.MaxElements != nil { + if !deviatedNode.IsList() && !deviatedNode.IsLeafList() { + appendErr(fmt.Errorf("tried to deviate max-elements on a non-list type %s", deviatedNode.Kind)) + continue + } + deviatedNode.ListAttr.MaxElements = devSpec.ListAttr.MaxElements + } + + if devSpec.Units != "" { + deviatedNode.Units = devSpec.Units + } + + if devSpec.Type != nil { + deviatedNode.Type = devSpec.Type + } + + case DeviationNotSupported: + dp := deviatedNode.Parent + if dp == nil { + appendErr(fmt.Errorf("%s: node %s does not have a valid parent, but deviate not-supported references one", Source(e.Node), e.Name)) + continue + } + dp.delete(deviatedNode.Name) + case DeviationDelete: + if devSpec.Config != TSUnset { + deviatedNode.Config = TSUnset + } + + if devSpec.Default == "" { + deviatedNode.Default = "" + } + + if devSpec.Mandatory != TSUnset { + devSpec.Mandatory = TSUnset + } + default: + appendErr(fmt.Errorf("invalid deviation type %s", dt)) + } + } + } + } + + return errs + +} + +// FixChoice inserts missing Case entries in a choice +func (e *Entry) FixChoice() { + if e.Kind == ChoiceEntry && len(e.Errors) == 0 { + for k, ce := range e.Dir { + if ce.Kind != CaseEntry { + ne := &Entry{ + Parent: e, + Node: &Case{ + Parent: ce.Node.ParentNode(), + Name: ce.Node.NName(), + Source: ce.Node.Statement(), + Extensions: ce.Node.Exts(), + }, + Name: ce.Name, + Kind: CaseEntry, + Config: ce.Config, + Prefix: ce.Prefix, + Dir: map[string]*Entry{ce.Name: ce}, + Extra: map[string][]interface{}{}, + } + ce.Parent = ne + e.Dir[k] = ne + e.DirOKeys = append(e.DirOKeys, k) + } + } + } + for _, ce := range e.Dir { + ce.FixChoice() + } +} + +// ReadOnly returns true if e is a read-only variable (config == false). +// If Config is unset in e, then false is returned if e has no parent, +// otherwise the value parent's ReadOnly is returned. +func (e *Entry) ReadOnly() bool { + switch { + case e == nil: + // We made it all the way to the root of the tree + return false + case e.Kind == OutputEntry: + return true + case e.Config == TSUnset: + return e.Parent.ReadOnly() + default: + return !e.Config.Value() + } +} + +// Find finds the Entry named by name relative to e. +func (e *Entry) Find(name string) *Entry { + if e == nil || name == "" { + return nil + } + parts := strings.Split(name, "/") + + // If parts[0] is "" then this path started with a / + // and we need to find our parent. + if parts[0] == "" { + for e.Parent != nil { + e = e.Parent + } + parts = parts[1:] + + // Since this module might use a different prefix that isn't + // the prefix that the module itself uses then we need to resolve + // the module into its local prefix to find it. + pfxMap := map[string]string{ + // Seed the map with the local module - we use GetPrefix just + // in case the module is a submodule. + e.Node.(*Module).GetPrefix(): e.Prefix.Name, + } + + // Add a map between the prefix used in the import statement, and + // the prefix that is used in the module itself. + for _, i := range e.Node.(*Module).Import { + // Resolve the module using the current module set, since we may + // not have populated the Module for the entry yet. + m, ok := e.Node.(*Module).modules.Modules[i.Name] + if !ok { + e.addError(fmt.Errorf("cannot find a module with name %s when looking at imports in %s", i.Name, e.Path())) + return nil + } + + pfxMap[i.Prefix.Name] = m.Prefix.Name + } + + if prefix, _ := getPrefix(parts[0]); prefix != "" { + pfx, ok := pfxMap[prefix] + if !ok { + // This is an undefined prefix within our context, so + // we can't do anything about resolving it. + e.addError(fmt.Errorf("invalid module prefix %s within module %s, defined prefix map: %v", prefix, e.Name, pfxMap)) + return nil + } + m, err := e.Modules().FindModuleByPrefix(pfx) + if err != nil { + e.addError(err) + return nil + } + if e.Node.(*Module) != m { + e = ToEntry(m) + } + } + } + + for _, part := range parts { + switch { + case e == nil: + return nil + case part == ".": + case part == "..": + e = e.Parent + case e.RPC != nil: + switch part { + case "input": + e = e.RPC.Input + case "output": + e = e.RPC.Output + } + default: + _, part = getPrefix(part) + switch part { + case ".": + case "", "..": + return nil + default: + e = e.Dir[part] + } + } + } + return e +} + +// Path returns the path to e. A nil Entry returns "". +func (e *Entry) Path() string { + if e == nil { + return "" + } + return e.Parent.Path() + "/" + e.Name +} + +// Namespace returns the YANG/XML namespace Value for e as mounted in the Entry +// tree (e.g., as placed by grouping statements). +// +// Per RFC6020 section 7.12, the namespace on elements in the tree due to a +// "uses" statement is that of the where the uses statement occurs, i.e., the +// user, rather than creator (grouping) of those elements, so we follow the +// usage (Entry) tree up to the parent before obtaining the (then adjacent) root +// node for its namespace Value. +func (e *Entry) Namespace() *Value { + // Make e the root parent entry + for ; e.Parent != nil; e = e.Parent { + if e.namespace != nil { + return e.namespace + } + } + + // Return the namespace of a valid root parent entry + if e != nil && e.Node != nil { + if root := RootNode(e.Node); root != nil { + return root.Namespace + } + } + + // Otherwise return an empty namespace Value (rather than nil) + return new(Value) +} + +// InstantiatingModule returns the YANG module which instanitated the Entry +// within the schema tree - using the same rules described in the documentation +// of the Namespace function. The namespace is resolved in the module name. This +// approach to namespacing is used when serialising YANG-modelled data to JSON as +// per RFC7951. +func (e *Entry) InstantiatingModule() (string, error) { + n := e.Namespace() + if n == nil { + return "", fmt.Errorf("entry %s had nil namespace", e.Name) + } + + ns, err := e.Modules().FindModuleByNamespace(n.Name) + if err != nil { + return "", fmt.Errorf("could not find module %s when retrieving namespace for %s", n.Name, e.Name) + } + return ns.Name, nil +} + +// shallowDup makes a shallow duplicate of e (only direct children are +// duplicated; grandchildren and deeper descedents are deleted). +func (e *Entry) shallowDup() *Entry { + // Warning: if we add any elements to Entry that should not be + // copied we will have to explicitly uncopy them. + ne := *e + + //Copy the ordered Dir keys to new entry + if len(e.DirOKeys) > 0 { + ne.DirOKeys = make([]string, 0) + for _, key := range e.DirOKeys { + ne.DirOKeys = append(ne.DirOKeys, key) + } + } + + // Now only copy direct children, clear their Dir, and fix up + // Parent pointers. + if e.Dir != nil { + ne.Dir = make(map[string]*Entry, len(e.Dir)) + for k, v := range e.Dir { + de := *v + de.Dir = nil + de.Parent = &ne + ne.Dir[k] = &de + } + } + return &ne +} + +// dup makes a deep duplicate of e. +func (e *Entry) dup() *Entry { + // Warning: if we add any elements to Entry that should not be + // copied we will have to explicitly uncopy them. + // It is possible we may want to do a deep copy on some other fields, + // such as Exts, Choice and Case, but it is not clear that we need + // to do that. + ne := *e + + //Copy the ordered Dir keys to new entry + if len(e.DirOKeys) > 0 { + ne.DirOKeys = make([]string, 0) + for _, key := range e.DirOKeys { + ne.DirOKeys = append(ne.DirOKeys, key) + } + } + + // Now recurse down to all of our children, fixing up Parent + // pointers as we go. + if e.Dir != nil { + ne.Dir = make(map[string]*Entry, len(e.Dir)) + for k, v := range e.Dir { + de := v.dup() + de.Parent = &ne + ne.Dir[k] = de + } + } + return &ne +} + +// merge merges a duplicate of oe.Dir into e.Dir, setting the prefix of each +// element to prefix, if not nil. It is an error if e and oe contain common +// elements. +func (e *Entry) merge(prefix *Value, namespace *Value, oe *Entry) { + e.importErrors(oe) + for k, v := range oe.Dir { + v := v.dup() + if prefix != nil { + v.Prefix = prefix + } + if namespace != nil { + v.namespace = namespace + } + if se := e.Dir[k]; se != nil { + er := newError(oe.Node, `Duplicate node %q in %q from: + %s: %s + %s: %s`, k, e.Name, Source(v.Node), v.Name, Source(se.Node), se.Name) + e.addError(er.Errors[0]) + } else { + v.Parent = e + e.Dir[k] = v + e.DirOKeys = append(e.DirOKeys, k) + } + } +} + +// nless returns -1 if a is less than b, 0 if a == b, and 1 if a > b. +// If a and b are both numeric, then nless compares them as numbers, +// otherwise they are compared lexicographically. +func nless(a, b string) int { + an, ae := strconv.Atoi(a) + bn, be := strconv.Atoi(b) + switch { + case ae == nil && be == nil: + switch { + case an < bn: + return -1 + case an > bn: + return 1 + default: + return 0 + } + case a < b: + return -1 + case a > b: + return 1 + default: + return 0 + } +} + +type sError struct { + s string + err error +} + +type sortedErrors []sError + +func (s sortedErrors) Len() int { return len(s) } +func (s sortedErrors) Swap(i, j int) { s[i], s[j] = s[j], s[i] } +func (s sortedErrors) Less(i, j int) bool { + fi := strings.SplitN(s[i].s, ":", 4) + fj := strings.SplitN(s[j].s, ":", 4) + if fi[0] < fj[0] { + return true + } + if fi[0] > fj[0] { + return false + } + + // compare compares field x to see which is less. + // numbers are compared as numbers. + compare := func(x int) int { + switch { + case len(fi) == x && len(fj) > x: + return -1 + case len(fj) == x && len(fi) > x: + return 1 + case len(fj) < x && len(fi) < x: + return 0 + } + return nless(fi[x], fj[x]) + } + for x := 1; x < 4; x++ { + switch compare(1) { + case -1: + return true + case 1: + return false + } + } + return false +} + +// errorSort sorts the strings in the errors slice assuming each line starts +// with file:line:col. Line and column number are sorted numerically. +// Duplicate errors are stripped. +func errorSort(errors []error) []error { + switch len(errors) { + case 0: + return nil + case 1: + return errors + } + elist := make(sortedErrors, len(errors)) + for x, err := range errors { + elist[x] = sError{err.Error(), err} + } + sort.Sort(elist) + errors = make([]error, len(errors)) + i := 0 + for _, err := range elist { + if i > 0 && reflect.DeepEqual(err.err, errors[i-1]) { + continue + } + errors[i] = err.err + i++ + } + return errors[:i] +} + +// DefaultValue returns the schema default value for e, if any. If the leaf +// has no explicit default, its type default (if any) will be used. +func (e *Entry) DefaultValue() string { + if len(e.Default) > 0 { + return e.Default + } else if typ := e.Type; typ != nil { + if leaf, ok := e.Node.(*Leaf); ok { + if leaf.Mandatory == nil || leaf.Mandatory.Name == "false" { + return typ.Default + } + } + } + return "" +} From 47d4dfc4df8b9f9288ec725b6cbfd38ebd1a782f Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Mon, 19 Aug 2019 15:07:46 -0700 Subject: [PATCH 059/214] Handle DB Spec creation for CVL yang case --- src/translib/transformer/xlate.go | 36 +++++++++++++++++++++---- src/translib/transformer/xlate_to_db.go | 1 - 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index 4d234057ed..fad8cb9e4e 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -118,11 +118,8 @@ func XlateUriToKeySpec(path string, uri *ygot.GoStruct, t *interface{}) (*map[db yangXpath, keyStr, tableName := xpathKeyExtract(path) // In case of CVL yang, the tablename and key info is available in the xpath - if tableName != "" { - dbFormat := KeySpec{} - dbFormat.Ts.Name = tableName - dbFormat.Key.Comp = append(dbFormat.Key.Comp, keyStr) - retdbFormat = append(retdbFormat, dbFormat) + if isCvlYang(yangXpath) { + retdbFormat = fillCvlKeySpec(yangXpath, tableName, keyStr) } else { if xSpecMap == nil { return &result, err @@ -149,6 +146,35 @@ func XlateUriToKeySpec(path string, uri *ygot.GoStruct, t *interface{}) (*map[db return &result, err } +func fillCvlKeySpec(yangXpath string , tableName string, keyStr string) ( []KeySpec ) { + + var retdbFormat = make([]KeySpec, 0) + + if tableName != "" { + dbFormat := KeySpec{} + dbFormat.Ts.Name = tableName + if keyStr != "" { + dbFormat.Key.Comp = append(dbFormat.Key.Comp, keyStr) + } + retdbFormat = append(retdbFormat, dbFormat) + } else { + // If table name not available in xpath get top container name + tokens:= strings.Split(yangXpath, ":") + container := "/" + tokens[len(tokens)-1] + if xDbSpecMap[container] != nil { + dbInfo := xDbSpecMap[container] + if dbInfo.fieldType == "container" { + for dir, _ := range dbInfo.dbEntry.Dir { + dbFormat := KeySpec{} + dbFormat.Ts.Name = dir + retdbFormat = append(retdbFormat, dbFormat) + } + } + } + } + return retdbFormat +} + func fillKeySpec(yangXpath string, keyStr string, dbFormat *KeySpec) { if xSpecMap == nil { diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index 3ad05dde7a..667df84b7c 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -265,7 +265,6 @@ func xpathKeyExtract(path string) (string, string, string) { yangXpath += xpath } - fmt.Println(tableName) return yangXpath, keyStr, tableName } From b5f9afece2edb0949bb8a1b03c147358184dd127 Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Mon, 19 Aug 2019 15:52:17 -0700 Subject: [PATCH 060/214] Handle container level DbData creation for CVL yang to generate JSON response --- src/translib/transformer/xlate.go | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index fad8cb9e4e..29d85e3764 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -263,12 +263,14 @@ func XlateFromDb(xpath string, data map[string]map[string]db.Value) ([]byte, err yangXpath, keyStr, tblName := xpathKeyExtract(xpath) if isCvlYang(xpath) { - tableName = tblName - tokens:= strings.Split(yangXpath, "/") - // Format /module:container/tableName[key]/fieldName - if tokens[len(tokens)-2] == tableName { - fieldName = tokens[len(tokens)-1] - dbData = extractFieldFromDb(tableName, keyStr, fieldName, data) + if (tblName != "") { + tableName = tblName + tokens:= strings.Split(yangXpath, "/") + // Format /module:container/tableName[key]/fieldName + if tokens[len(tokens)-2] == tableName { + fieldName = tokens[len(tokens)-1] + dbData = extractFieldFromDb(tableName, keyStr, fieldName, data) + } } } else { if xSpecMap == nil { From d1e0464397c21471cbd5e07e6ab03477151d94d7 Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Mon, 19 Aug 2019 16:31:40 -0700 Subject: [PATCH 061/214] Fix data being overwritten to JSON response. Include print to file --- src/translib/transformer/xlate_from_db.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index 5d710143ed..22cf2edae7 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -93,7 +93,7 @@ func directDbToYangJsonCreate(dbDataMap map[string]map[string]db.Value, jsonData fldValPair = keyJsonDataAdd(yangKeys, keyStr, fldValPair) dataInst = fmt.Sprintf("{ \r\n %v \r\n },", fldValPair) } - dataInst = strings.TrimRight(dataInst, ",") + dataInst += strings.TrimRight(dataInst, ",") jsonData += fmt.Sprintf("\"%v\" : [\r\n %v\r\n ],", tblName, dataInst) } jsonData = strings.TrimRight(jsonData, ",") @@ -105,6 +105,7 @@ func dbDataToYangJsonCreate(xpath string, dbDataMap map[string]map[string]db.Val jsonData := "" if isCvlYang(xpath) { jsonData := directDbToYangJsonCreate(dbDataMap, jsonData) + jsonDataPrint(jsonData) return jsonData, nil } curXpath := "" From ac377090a3209326aa02959652cf746de61841ca Mon Sep 17 00:00:00 2001 From: s-mari Date: Mon, 19 Aug 2019 18:48:21 -0700 Subject: [PATCH 062/214] changed the value parsing in xfmr handler funtions --- src/translib/transformer/xfmr_acl.go | 42 ++++++++++--------------- src/translib/transformer/xlate_to_db.go | 28 ++++++++++------- 2 files changed, 34 insertions(+), 36 deletions(-) diff --git a/src/translib/transformer/xfmr_acl.go b/src/translib/transformer/xfmr_acl.go index d18c5881fe..424fa70c04 100644 --- a/src/translib/transformer/xfmr_acl.go +++ b/src/translib/transformer/xfmr_acl.go @@ -243,7 +243,7 @@ var YangToDb_acl_l2_ethertype_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *y var err error log.Info("YangToDb_acl_l2_ethertype_xfmr :", ygRoot, xpath) - ethertypeType := reflect.TypeOf(ethertype).Elem() + ethertypeType := reflect.TypeOf(ethertype) var b bytes.Buffer switch ethertypeType { case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_L2_Config_Ethertype_Union_E_OpenconfigPacketMatchTypes_ETHERTYPE{}): @@ -298,7 +298,7 @@ var YangToDb_acl_ip_protocol_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *yg var err error log.Info("YangToDb_acl_ip_protocol_xfmr: ", ygRoot, xpath) - protocolType := reflect.TypeOf(protocol).Elem() + protocolType := reflect.TypeOf(protocol) switch (protocolType) { case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Ipv4_Config_Protocol_Union_E_OpenconfigPacketMatchTypes_IP_PROTOCOL{}): v := (protocol).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Ipv4_Config_Protocol_Union_E_OpenconfigPacketMatchTypes_IP_PROTOCOL) @@ -348,7 +348,7 @@ var YangToDb_acl_source_port_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *yg res_map := make(map[string]string) var err error; log.Info("YangToDb_acl_source_port_xfmr: ", ygRoot, xpath) - sourceportType := reflect.TypeOf(value).Elem() + sourceportType := reflect.TypeOf(value) switch sourceportType { case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort_Union_E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort{}): v := (value).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort_Union_E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort) @@ -450,7 +450,7 @@ var YangToDb_acl_destination_port_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoo res_map := make(map[string]string) var err error; log.Info("YangToDb_acl_destination_port_xfmr: ", ygRoot, xpath) - destportType := reflect.TypeOf(value).Elem() + destportType := reflect.TypeOf(value) switch destportType { case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort_Union_E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort{}): v := (value).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort_Union_E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort) @@ -686,11 +686,9 @@ var YangToDb_acl_port_bindings_xfmr SubTreeXfmrYangToDb = func (d *db.DB, ygRoot } else { aclInterfacesMap[aclName] = append(aclInterfacesMap[aclName], *intf.Id) } - if len(aclTableMap) == 0 { - _, ok := aclTableMap[aclName] - if !ok { - aclTableMap[aclName] = db.Value{Field: make(map[string]string)} - } + _, ok := aclTableMap[aclName] + if !ok { + aclTableMap[aclName] = db.Value{Field: make(map[string]string)} } aclTableMap[aclName].Field["stage"] = "INGRESS" } @@ -703,27 +701,23 @@ var YangToDb_acl_port_bindings_xfmr SubTreeXfmrYangToDb = func (d *db.DB, ygRoot } else { aclInterfacesMap[aclName] = append(aclInterfacesMap[aclName], *intf.Id) } - if len(aclTableMap) == 0 { - _, ok := aclTableMap[aclName] - if !ok { - aclTableMap[aclName] = db.Value{Field: make(map[string]string)} - } + _, ok := aclTableMap[aclName] + if !ok { + aclTableMap[aclName] = db.Value{Field: make(map[string]string)} } aclTableMap[aclName].Field["stage"] = "EGRESS" } } if intf.IngressAclSets == nil && intf.EgressAclSets == nil { for aclName := range aclTableMapDb { - if len(aclTableMap) == 0 { - _, ok := aclTableMap[aclName] - if !ok { - aclTableMap[aclName] = db.Value{Field: make(map[string]string)} - } + _, ok := aclTableMap[aclName] + if !ok { + aclTableMap[aclName] = db.Value{Field: make(map[string]string)} } aclEntryDb := aclTableMapDb[aclName] intfsDb := aclEntryDb.GetList("ports") if contains(intfsDb, intfId) { - var intfs [] string + var intfs []string intfs = append(intfs, intfId) aclTableMap[aclName].Field["stage"] = aclEntryDb.Get("stage") val := aclTableMap[aclName] @@ -739,11 +733,9 @@ var YangToDb_acl_port_bindings_xfmr SubTreeXfmrYangToDb = func (d *db.DB, ygRoot } } else { for aclName := range aclTableMapDb { - if len(aclTableMap) == 0 { - _, ok := aclTableMap[aclName] - if !ok { - aclTableMap[aclName] = db.Value{Field: make(map[string]string)} - } + _, ok := aclTableMap[aclName] + if !ok { + aclTableMap[aclName] = db.Value{Field: make(map[string]string)} } aclEntryDb := aclTableMapDb[aclName] aclTableMap[aclName].Field["stage"] = aclEntryDb.Get("stage") diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index 3ad05dde7a..299aebe61b 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -30,7 +30,7 @@ func dataToDBMapAdd(tableName string, dbKey string, result map[string]map[string } /* Fill the redis-db map with data */ -func mapFillData(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, dbKey string, result map[string]map[string]db.Value, xpathPrefix string, name string, value string) error { +func mapFillData(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, dbKey string, result map[string]map[string]db.Value, xpathPrefix string, name string, value interface{}) error { xpath := xpathPrefix + "/" + name xpathInfo := xSpecMap[xpath] log.Info("name: \"%v\", xpathPrefix(\"%v\").", name, xpathPrefix) @@ -70,13 +70,14 @@ func mapFillData(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, dbKey st return errors.New("Invalid field name") } fieldName := xpathInfo.fieldName - if strings.Contains(value, ":") { - value = strings.Split(value, ":")[1] + valueStr := fmt.Sprintf("%v", value) + if strings.Contains(valueStr, ":") { + valueStr = strings.Split(valueStr, ":")[1] } - dataToDBMapAdd(*xpathInfo.tableName, dbKey, result, fieldName, value) - log.Info("TblName: \"%v\", key: \"%v\", field: \"%v\", value: \"%v\".", - *xpathInfo.tableName, dbKey, fieldName, value) + dataToDBMapAdd(*xpathInfo.tableName, dbKey, result, fieldName, valueStr) + log.Info("TblName: \"%v\", key: \"%v\", field: \"%v\", valueStr: \"%v\".", + *xpathInfo.tableName, dbKey, fieldName, valueStr) return nil } @@ -199,10 +200,15 @@ func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, if typeOfValue == reflect.Map || typeOfValue == reflect.Slice { log.Info("slice/map data: key(\"%v\"), xpathPrefix(\"%v\").", keyName, xpathPrefix) - xpath, err := RemoveXPATHPredicates(uri) - if err != nil { - log.Errorf("yangReqToDbMapCreate: Failed to remove Xpath Predicates from uri %s", uri) - } + xpath := uri + pathAttr := key.String() + if len(xpathPrefix) > 0 { + if strings.Contains(pathAttr, ":") { + pathAttr = strings.Split(pathAttr, ":")[1] + } + xpath = xpathPrefix + "/" + pathAttr + uri = uri + "/" + pathAttr + } if xSpecMap[xpath] != nil && len(xSpecMap[xpath].xfmrFunc) > 0 { /* subtree transformer present */ @@ -222,7 +228,7 @@ func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, value := jData.MapIndex(key).Interface() log.Info("data field: key(\"%v\"), value(\"%v\").", key, value) err := mapFillData(d, ygRoot, oper, uri, keyName, result, xpathPrefix, - pathAttr, fmt.Sprintf("%v", value)) + pathAttr, value) if err != nil { log.Errorf("Failed constructing data for db write: key(\"%v\"), value(\"%v\"), path(\"%v\").", pathAttr, value, xpathPrefix) From cf254d89028c1bf70e179e3f007e09a55bc649e4 Mon Sep 17 00:00:00 2001 From: amrutasali Date: Tue, 20 Aug 2019 19:05:10 +0000 Subject: [PATCH 063/214] Transformer Infra support to create a yang schema ordered DB table list for CVL yang --- src/translib/common_app.go | 165 +++++++++++++++++------------- src/translib/transformer/xlate.go | 28 ++++- src/translib/transformer/xspec.go | 24 ++++- 3 files changed, 144 insertions(+), 73 deletions(-) diff --git a/src/translib/common_app.go b/src/translib/common_app.go index 9efb448001..b47e036369 100644 --- a/src/translib/common_app.go +++ b/src/translib/common_app.go @@ -18,6 +18,7 @@ type CommonApp struct { ygotRoot *ygot.GoStruct ygotTarget *interface{} cmnAppTableMap map[string]map[string]db.Value + cmnAppSchemaOrdTbllist []string } var cmnAppInfo = appInfo{appType: reflect.TypeOf(CommonApp{}), @@ -180,7 +181,26 @@ func (app *CommonApp) translateCRUCommon(d *db.DB, opcode int) ([]db.WatchKeys, var err error var keys []db.WatchKeys var tblsToWatch []*db.TableSpec + var schemaOrdTblList []string + var moduleNm string log.Info("translateCRUCommon:path =", app.pathInfo.Path) + d.Opts.DisableCVLCheck = true + + /* retrieve schema table order for incoming maodule name request */ + moduleNm, err = transformer.GetModuleNmFromPath(app.pathInfo.Path) + if (err != nil) || (len(moduleNm) == 0) { + log.Error("GetModuleNmFromPath() failed") + return keys, err + } + log.Info("getModuleNmFromPath() returned module name = ", moduleNm) + schemaOrdTblList, err = transformer.GetSchemaOrdDBTblList(moduleNm) + if (err != nil) || (len(schemaOrdTblList) == 0) { + log.Error("GetSchemaOrdDBTblList() failed") + return keys, err + } + + log.Info("getSchemaOrdDBTblList() returned ordered table list = ", schemaOrdTblList) + app.cmnAppSchemaOrdTbllist = schemaOrdTblList // translate yang to db result, err := transformer.XlateToDb(app.pathInfo.Path, opcode, d, (*app).ygotRoot, (*app).ygotTarget) @@ -220,76 +240,83 @@ func (app *CommonApp) cmnAppDataDbOperation(d *db.DB, opcode int, cmnAppDataDbMa var err error log.Info("Processing DB operation for ", cmnAppDataDbMap) var cmnAppTs *db.TableSpec - for tblNm, tblInst := range cmnAppDataDbMap { - log.Info("Table name ", tblNm) - cmnAppTs = &db.TableSpec{Name: tblNm} - for tblKey, tblRw := range tblInst { - log.Info("Table key and row ", tblKey, tblRw) - switch opcode { - case CREATE: - log.Info("CREATE case") - existingEntry, err := d.GetEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}) - if existingEntry.IsPopulated() { - log.Info("Entry already exists hence return error.") - return tlerr.AlreadyExists("Entry %s already exists", tblKey) - } else { - err = d.CreateEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}, tblRw) - if err != nil { - log.Error("CREATE case - d.CreateEntry() failure") - return err - } - } - case UPDATE: - log.Info("UPDATE case") - existingEntry, err := d.GetEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}) - if existingEntry.IsPopulated() { - log.Info("Entry already exists hence modifying it.") - err = d.ModEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}, tblRw) - if err != nil { - log.Error("UPDATE case - d.ModEntry() failure") - return err - } - } else { - log.Info("Entry to be modified does not exist hence return error.") - return tlerr.NotFound("Entry %s to be modified does not exist.", tblKey) - } - - case REPLACE: - log.Info("REPLACE case") - existingEntry, err := d.GetEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}) - if existingEntry.IsPopulated() { - log.Info("Entry already exists hence execute db.SetEntry") - err := d.SetEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}, tblRw) - if err != nil { - log.Error("REPLACE case - d.SetEntry() failure") - return err - } - } else { - log.Info("Entry doesn't exist hence create it.") - err = d.CreateEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}, tblRw) - if err != nil { - log.Error("REPLACE case - d.CreateEntry() failure") - return err - } - } - //TODO : should the table level replace be handled?? - case DELETE: - log.Info("DELETE case") - if len(tblRw.Field) == 0 { - log.Info("DELETE case - no fields/cols to delete hence delete the entire row.") - err := d.DeleteEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}) - if err != nil { - log.Error("DELETE case - d.DeleteEntry() failure") - return err - } - } else { - log.Info("DELETE case - fields/cols to delete hence delete only those fields.") - err := d.DeleteEntryFields(cmnAppTs, db.Key{Comp: []string{tblKey}}, tblRw) - if err != nil { - log.Error("DELETE case - d.DeleteEntryFields() failure") - return err - } + log.Info("getSchemaOrdDBTblList() returned ordered table list = ", app.cmnAppSchemaOrdTbllist) + //return err + + /* order by schema table order */ + for _, tbl := range app.cmnAppSchemaOrdTbllist { + log.Info("In Yang to DB map returned from transformer looking for table = ", tbl) + if tblVal, ok := cmnAppDataDbMap[tbl]; ok { + log.Info("Found table entry in yang to DB map") + for tblKey, tblRw := range tblVal { + log.Info("Processing Table key and row ", tblKey, tblRw) + switch opcode { + case CREATE: + log.Info("CREATE case") + existingEntry, err := d.GetEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}) + if existingEntry.IsPopulated() { + log.Info("Entry already exists hence return error.") + return tlerr.AlreadyExists("Entry %s already exists", tblKey) + } else { + err = d.CreateEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}, tblRw) + if err != nil { + log.Error("CREATE case - d.CreateEntry() failure") + return err + } + } + + case UPDATE: + log.Info("UPDATE case") + existingEntry, err := d.GetEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}) + if existingEntry.IsPopulated() { + log.Info("Entry already exists hence modifying it.") + err = d.ModEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}, tblRw) + if err != nil { + log.Error("UPDATE case - d.ModEntry() failure") + return err + } + } else { + log.Info("Entry to be modified does not exist hence return error.") + return tlerr.NotFound("Entry %s to be modified does not exist.", tblKey) + } + + case REPLACE: + log.Info("REPLACE case") + existingEntry, err := d.GetEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}) + if existingEntry.IsPopulated() { + log.Info("Entry already exists hence execute db.SetEntry") + err := d.SetEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}, tblRw) + if err != nil { + log.Error("REPLACE case - d.SetEntry() failure") + return err + } + } else { + log.Info("Entry doesn't exist hence create it.") + err = d.CreateEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}, tblRw) + if err != nil { + log.Error("REPLACE case - d.CreateEntry() failure") + return err + } + } + //TODO : should the table level replace be handled?? + case DELETE: + log.Info("DELETE case") + if len(tblRw.Field) == 0 { + log.Info("DELETE case - no fields/cols to delete hence delete the entire row.") + err := d.DeleteEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}) + if err != nil { + log.Error("DELETE case - d.DeleteEntry() failure") + return err + } + } else { + log.Info("DELETE case - fields/cols to delete hence delete only those fields.") + err := d.DeleteEntryFields(cmnAppTs, db.Key{Comp: []string{tblKey}}, tblRw) + if err != nil { + log.Error("DELETE case - d.DeleteEntryFields() failure") + return err + } + } } } } diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index 29d85e3764..3a9d8ddbc5 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -1,7 +1,7 @@ package transformer import ( - //"fmt" + "fmt" //"os" // "sort" // "github.com/openconfig/goyang/pkg/yang" @@ -315,3 +315,29 @@ func extractFieldFromDb(tableName string, keyStr string, fieldName string, data } return dbData } + +func GetModuleNmFromPath(uri string) (string, error) { + path, err := ygot.StringToPath(uri, ygot.StructuredPath, ygot.StringSlicePath) + if err != nil { + log.Error("Error in uri to path conversion: ", err) + return "", err + } + pathSlice := strings.Split(path.Elem[0].Name, ":") + moduleNm := pathSlice[0] + log.Info("Module name for given path = ", moduleNm) + return moduleNm, err +} + +func GetSchemaOrdDBTblList(ygModuleNm string) ([]string, error) { + var result []string + var err error + if dbTblList, ok := xDbSpecOrdTblMap[ygModuleNm]; ok { + result = dbTblList + log.Error("Ordered DB Table list is empty for module name = ", ygModuleNm) + err = fmt.Errorf("Ordered DB Table list is empty for module name %v", ygModuleNm) + } else { + log.Error("No entry found in the map of module names to ordered list of DB Tables for module = ", ygModuleNm) + err = fmt.Errorf("No entry found in the map of module names to ordered list of DB Tables for module = %v", ygModuleNm) + } + return result, err +} diff --git a/src/translib/transformer/xspec.go b/src/translib/transformer/xspec.go index b9eed6efd0..9a469c4731 100644 --- a/src/translib/transformer/xspec.go +++ b/src/translib/transformer/xspec.go @@ -5,6 +5,7 @@ import ( "os" "sort" "strings" + log "github.com/golang/glog" "github.com/openconfig/goyang/pkg/yang" ) @@ -31,6 +32,7 @@ type dbInfo struct { var xSpecMap map[string]*yangXpathInfo var xDbSpecMap map[string]*dbInfo +var xDbSpecOrdTblMap map[string][]string //map of module-name to ordered list of db tables { "sonic-acl" : ["ACL_TABLE", "ACL_RULE"] } /* update transformer spec with db-node */ func updateDbTableData (xpath string, xpathData *yangXpathInfo, tableName string) { @@ -146,7 +148,7 @@ func yangToDbMapBuild(entries map[string]*yang.Entry) { } /* Fill the map with db details */ -func dbMapFill(prefixPath string, curPath string, xDbSpecMap map[string]*dbInfo, entry *yang.Entry) { +func dbMapFill(prefixPath string, curPath string, moduleNm string, trkTpCnt bool, xDbSpecMap map[string]*dbInfo, entry *yang.Entry) { entryType := entry.Node.Statement().Keyword if entryType == "list" { prefixPath = entry.Name @@ -162,13 +164,21 @@ func dbMapFill(prefixPath string, curPath string, xDbSpecMap map[string]*dbInfo, xDbSpecMap[dbXpath].fieldType = entryType } + var childList []string for k := range entry.Dir { childList = append(childList, k) } + + if entryType == "container" && trkTpCnt { + xDbSpecOrdTblMap[moduleNm] = childList + log.Info("xDbSpecOrdTblMap after appending ", xDbSpecOrdTblMap) + trkTpCnt = false + } + sort.Strings(childList) for _, child := range childList { - dbMapFill(prefixPath, prefixPath + "/" + entry.Dir[child].Name, xDbSpecMap, entry.Dir[child]) + dbMapFill(prefixPath, prefixPath + "/" + entry.Dir[child].Name, moduleNm, trkTpCnt, xDbSpecMap, entry.Dir[child]) } } @@ -178,15 +188,23 @@ func dbMapBuild(entries []*yang.Entry) { return } xDbSpecMap = make(map[string]*dbInfo) + xDbSpecOrdTblMap = make(map[string][]string) for _, e := range entries { if e == nil || len(e.Dir) == 0 { continue } - dbMapFill("", "", xDbSpecMap, e) + moduleNm := e.Name + log.Info("Module name", moduleNm) + xDbSpecOrdTblMap[moduleNm] = []string{} + trkTpCnt := true + dbMapFill("", "", moduleNm, trkTpCnt, xDbSpecMap, e) } } +/***************************************/ + + func childToUpdateParent( xpath string, tableName string) { var xpathData *yangXpathInfo parent := parentXpathGet(xpath) From cf83ec3fb0f981573c254e7a214027797f7d0804 Mon Sep 17 00:00:00 2001 From: amrutasali Date: Tue, 20 Aug 2019 20:54:45 +0000 Subject: [PATCH 064/214] For CVL yang modified accessing yag entries to accessing them in yang yang schema order maintained in DirOKeys field of yang-entry generated by goyang-patch --- src/translib/transformer/xspec.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/translib/transformer/xspec.go b/src/translib/transformer/xspec.go index 9a469c4731..58e2640c93 100644 --- a/src/translib/transformer/xspec.go +++ b/src/translib/transformer/xspec.go @@ -166,7 +166,7 @@ func dbMapFill(prefixPath string, curPath string, moduleNm string, trkTpCnt bool var childList []string - for k := range entry.Dir { + for _, k := range entry.DirOKeys { childList = append(childList, k) } @@ -176,7 +176,7 @@ func dbMapFill(prefixPath string, curPath string, moduleNm string, trkTpCnt bool trkTpCnt = false } - sort.Strings(childList) + //sort.Strings(childList) for _, child := range childList { dbMapFill(prefixPath, prefixPath + "/" + entry.Dir[child].Name, moduleNm, trkTpCnt, xDbSpecMap, entry.Dir[child]) } From c9094c44caaa0f9832304601318ee4a5072c1236 Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Tue, 20 Aug 2019 15:56:05 -0700 Subject: [PATCH 065/214] Delete case:: Handle db request create for CVL yang --- src/translib/transformer/xlate.go | 8 +++- src/translib/transformer/xlate_to_db.go | 61 +++++++++++++++++++++---- 2 files changed, 58 insertions(+), 11 deletions(-) diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index 3a9d8ddbc5..fe8bbd0b43 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -236,20 +236,24 @@ func XlateToDb(path string, opcode int, d *db.DB, yg *ygot.GoStruct, yt *interfa case UPDATE: log.Info("UPDATE case") - err = dbMapUpdate(d, yg, opcode, path, jsonData, result) + err = dbMapUpdate(d, yg, opcode, path, jsonData, result) if err != nil { log.Errorf("Error: Data translation from yang to db failed for update request.") } case REPLACE: log.Info("REPLACE case") - err = dbMapUpdate(d, yg, opcode, path, jsonData, result) + err = dbMapUpdate(d, yg, opcode, path, jsonData, result) if err != nil { log.Errorf("Error: Data translation from yang to db failed for replace request.") } case DELETE: log.Info("DELETE case") + err = dbMapDelete(d, yg, opcode, path, jsonData, result) + if err != nil { + log.Errorf("Error: Data translation from yang to db failed for delete request.") + } } return result, err } diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index 46027aedc7..1a9dc4865e 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -128,19 +128,62 @@ func directDbMapData(tableName string, jsonData interface{}, result map[string]m /* Get the db table, key and field name for the incoming delete request */ func dbMapDelete(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string, jsonData interface{}, result map[string]map[string]db.Value) error { - xpathPrefix, keyName, _ := xpathKeyExtract(path) - log.Info("Delete req: path(\"%v\"), key(\"%v\"), xpathPrefix(\"%v\").", path, keyName, xpathPrefix) - spec, ok := xSpecMap[xpathPrefix] - if ok && spec.tableName != nil { - result[*spec.tableName] = make(map[string]db.Value) - if len(keyName) > 0 { - result[*spec.tableName][keyName] = db.Value{Field: make(map[string]string)} - if spec.yangEntry != nil && spec.yangEntry.Node.Statement().Keyword == "leaf" { - result[*spec.tableName][keyName].Field[spec.fieldName] = "" + xpathPrefix, keyName, tableName := xpathKeyExtract(path) + log.Info("Delete req: path(\"%v\"), key(\"%v\"), xpathPrefix(\"%v\"), tableName(\"%v\").", path, keyName, xpathPrefix, tableName) + var err error + if isCvlYang(xpathPrefix) { + err = cvlYangReqToDbMapDelete(xpathPrefix, tableName, keyName, result) + } else { + spec, ok := xSpecMap[xpathPrefix] + if ok && spec.tableName != nil { + result[*spec.tableName] = make(map[string]db.Value) + if len(keyName) > 0 { + result[*spec.tableName][keyName] = db.Value{Field: make(map[string]string)} + if spec.yangEntry != nil && spec.yangEntry.Node.Statement().Keyword == "leaf" { + result[*spec.tableName][keyName].Field[spec.fieldName] = "" + } } } } log.Info("Delete req: path(\"%v\") result(\"%v\").", path, result) + return err +} + +func cvlYangReqToDbMapDelete(xpathPrefix string, tableName string, keyName string, result map[string]map[string]db.Value) error { + if (tableName != "") { + // Specific table entry case + result[tableName] = make(map[string]db.Value) + if (keyName != "") { + // Specific key case + var dbVal db.Value + tokens:= strings.Split(xpathPrefix, "/") + // Format /module:container/tableName[key]/fieldName + if tokens[len(tokens)-2] == tableName { + // Specific leaf case + fieldName := tokens[len(tokens)-1] + dbVal.Field = make(map[string]string) + dbVal.Field[fieldName] = "" + } + result[tableName][keyName] = dbVal + } else { + // Get all keys + fmt.Println("No Key. Return table name") + } + } else { + // Get all table entries + fmt.Println("No table name. Delete all entries") + // If table name not available in xpath get top container name + tokens:= strings.Split(xpathPrefix, ":") + container := "/" + tokens[len(tokens)-1] + if xDbSpecMap[container] != nil { + dbInfo := xDbSpecMap[container] + if dbInfo.fieldType == "container" { + for dir, _ := range dbInfo.dbEntry.Dir { + result[dir] = make(map[string]db.Value) + } + } + } + } return nil } From 93d224fe5fde511d93c6afe775dc3816bb500696 Mon Sep 17 00:00:00 2001 From: amrutasali Date: Wed, 21 Aug 2019 00:16:33 +0000 Subject: [PATCH 066/214] Added support for table level delete in common app --- src/translib/common_app.go | 49 +++++++++++++++++++++---------- src/translib/transformer/xlate.go | 7 +++-- 2 files changed, 38 insertions(+), 18 deletions(-) diff --git a/src/translib/common_app.go b/src/translib/common_app.go index b47e036369..76fda96749 100644 --- a/src/translib/common_app.go +++ b/src/translib/common_app.go @@ -184,7 +184,6 @@ func (app *CommonApp) translateCRUCommon(d *db.DB, opcode int) ([]db.WatchKeys, var schemaOrdTblList []string var moduleNm string log.Info("translateCRUCommon:path =", app.pathInfo.Path) - d.Opts.DisableCVLCheck = true /* retrieve schema table order for incoming maodule name request */ moduleNm, err = transformer.GetModuleNmFromPath(app.pathInfo.Path) @@ -245,15 +244,16 @@ func (app *CommonApp) cmnAppDataDbOperation(d *db.DB, opcode int, cmnAppDataDbMa //return err /* order by schema table order */ - for _, tbl := range app.cmnAppSchemaOrdTbllist { - log.Info("In Yang to DB map returned from transformer looking for table = ", tbl) - if tblVal, ok := cmnAppDataDbMap[tbl]; ok { + for _, tblNm := range app.cmnAppSchemaOrdTbllist { + log.Info("In Yang to DB map returned from transformer looking for table = ", tblNm) + if tblVal, ok := cmnAppDataDbMap[tblNm]; ok { + cmnAppTs = &db.TableSpec{Name: tblNm} log.Info("Found table entry in yang to DB map") - for tblKey, tblRw := range tblVal { - log.Info("Processing Table key and row ", tblKey, tblRw) - switch opcode { - case CREATE: - log.Info("CREATE case") + switch opcode { + case CREATE: + log.Info("CREATE case") + for tblKey, tblRw := range tblVal { + log.Info("Processing Table key and row ", tblKey, tblRw) existingEntry, err := d.GetEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}) if existingEntry.IsPopulated() { log.Info("Entry already exists hence return error.") @@ -266,8 +266,11 @@ func (app *CommonApp) cmnAppDataDbOperation(d *db.DB, opcode int, cmnAppDataDbMa } } - case UPDATE: - log.Info("UPDATE case") + } + + case UPDATE: + log.Info("UPDATE case") + for tblKey, tblRw := range tblVal { existingEntry, err := d.GetEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}) if existingEntry.IsPopulated() { log.Info("Entry already exists hence modifying it.") @@ -280,9 +283,11 @@ func (app *CommonApp) cmnAppDataDbOperation(d *db.DB, opcode int, cmnAppDataDbMa log.Info("Entry to be modified does not exist hence return error.") return tlerr.NotFound("Entry %s to be modified does not exist.", tblKey) } + } - case REPLACE: - log.Info("REPLACE case") + case REPLACE: + log.Info("REPLACE case") + for tblKey, tblRw := range tblVal { existingEntry, err := d.GetEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}) if existingEntry.IsPopulated() { log.Info("Entry already exists hence execute db.SetEntry") @@ -300,8 +305,20 @@ func (app *CommonApp) cmnAppDataDbOperation(d *db.DB, opcode int, cmnAppDataDbMa } } //TODO : should the table level replace be handled?? - case DELETE: - log.Info("DELETE case") + } + case DELETE: + log.Info("DELETE case") + if len(tblVal) == 0 { + log.Info("DELETE case - No table instances hence delete entire table = ", tblNm) + err = d.DeleteTable(cmnAppTs) + if err != nil { + log.Error("DELETE case - d.DeleteTable() failure for Table = ", tblNm) + return err + } + log.Info("DELETE case - Deleted entire table = ", tblNm) + continue + } + for tblKey, tblRw := range tblVal { if len(tblRw.Field) == 0 { log.Info("DELETE case - no fields/cols to delete hence delete the entire row.") err := d.DeleteEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}) @@ -317,7 +334,7 @@ func (app *CommonApp) cmnAppDataDbOperation(d *db.DB, opcode int, cmnAppDataDbMa return err } } - } + } } } } diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index fe8bbd0b43..f8380f19e0 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -337,8 +337,11 @@ func GetSchemaOrdDBTblList(ygModuleNm string) ([]string, error) { var err error if dbTblList, ok := xDbSpecOrdTblMap[ygModuleNm]; ok { result = dbTblList - log.Error("Ordered DB Table list is empty for module name = ", ygModuleNm) - err = fmt.Errorf("Ordered DB Table list is empty for module name %v", ygModuleNm) + if len(dbTblList) == 0 { + log.Error("Ordered DB Table list is empty for module name = ", ygModuleNm) + err = fmt.Errorf("Ordered DB Table list is empty for module name %v", ygModuleNm) + + } } else { log.Error("No entry found in the map of module names to ordered list of DB Tables for module = ", ygModuleNm) err = fmt.Errorf("No entry found in the map of module names to ordered list of DB Tables for module = %v", ygModuleNm) From 3a5ee1af5f22bc81053159341d7e2ca46151811c Mon Sep 17 00:00:00 2001 From: s-mari Date: Tue, 20 Aug 2019 17:17:00 -0700 Subject: [PATCH 067/214] fixed crash in update request --- src/translib/transformer/xlate_to_db.go | 12 ++++++------ src/translib/transformer/xlate_utils.go | 7 ++++++- src/translib/transformer/xspec.go | 7 ++----- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index 1a9dc4865e..7e9c06c1f0 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -190,23 +190,23 @@ func cvlYangReqToDbMapDelete(xpathPrefix string, tableName string, keyName strin /* Get the data from incoming update/replace request, create map and fill with dbValue(ie. field:value to write into redis-db */ func dbMapUpdate(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string, jsonData interface{}, result map[string]map[string]db.Value) error { - xpathPrefix, keyName , _ := xpathKeyExtract(path) - log.Info("Update/replace req: path(\"%v\"), key(\"%v\"), xpathPrefix(\"%v\").", path, keyName, xpathPrefix) - dbMapCreate(d, ygRoot, oper, parentXpathGet(xpathPrefix), jsonData, result) + log.Info("Update/replace req: path(\"%v\").", path) + dbMapCreate(d, ygRoot, oper, path, jsonData, result) log.Info("Update/replace req: path(\"%v\") result(\"%v\").", path, result) + printDbData(result, "/tmp/yangToDbDataUpRe.txt") return nil } /* Get the data from incoming create request, create map and fill with dbValue(ie. field:value to write into redis-db */ func dbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string, jsonData interface{}, result map[string]map[string]db.Value) error { - xpathTmplt, keyName, _ := xpathKeyExtract(path) + root := xpathRootNameGet(path) if isCvlYang(path) { cvlYangReqToDbMapCreate(jsonData, result) } else { - yangReqToDbMapCreate(d, ygRoot, oper, path, parentXpathGet(xpathTmplt), keyName, jsonData, result) + yangReqToDbMapCreate(d, ygRoot, oper, root, "", "", jsonData, result) } - printDbData(result, "/tmp/yangToDbData.txt") + printDbData(result, "/tmp/yangToDbDataCreate.txt") return nil } diff --git a/src/translib/transformer/xlate_utils.go b/src/translib/transformer/xlate_utils.go index f34e7f9a68..bab7ebc9fa 100644 --- a/src/translib/transformer/xlate_utils.go +++ b/src/translib/transformer/xlate_utils.go @@ -23,7 +23,7 @@ func keyFromXpathCreate(keyList []string) string { return keyOut } -/* Create db key from datd xpath(request) */ +/* Create db key from data xpath(request) */ func keyCreate(keyPrefix string, xpath string, data interface{}) string { yangEntry := xSpecMap[xpath].yangEntry if len(keyPrefix) > 0 { keyPrefix += "|" } @@ -160,3 +160,8 @@ func uriWithKeyCreate (uri string, xpathTmplt string, data interface{}) string { return uri } +func xpathRootNameGet(path string) string { + pathl := strings.Split(path, "/") + return ("/" + pathl[1]) +} + diff --git a/src/translib/transformer/xspec.go b/src/translib/transformer/xspec.go index 58e2640c93..cf1ab21d32 100644 --- a/src/translib/transformer/xspec.go +++ b/src/translib/transformer/xspec.go @@ -176,9 +176,9 @@ func dbMapFill(prefixPath string, curPath string, moduleNm string, trkTpCnt bool trkTpCnt = false } - //sort.Strings(childList) for _, child := range childList { - dbMapFill(prefixPath, prefixPath + "/" + entry.Dir[child].Name, moduleNm, trkTpCnt, xDbSpecMap, entry.Dir[child]) + childPath := prefixPath + "/" + entry.Dir[child].Name + dbMapFill(prefixPath, childPath, moduleNm, trkTpCnt, xDbSpecMap, entry.Dir[child]) } } @@ -202,9 +202,6 @@ func dbMapBuild(entries []*yang.Entry) { } } -/***************************************/ - - func childToUpdateParent( xpath string, tableName string) { var xpathData *yangXpathInfo parent := parentXpathGet(xpath) From b57c2aa726e683e8eb2845498a35ee6f16cc85f9 Mon Sep 17 00:00:00 2001 From: s-mari Date: Wed, 21 Aug 2019 18:08:10 -0700 Subject: [PATCH 068/214] xpath, tablename and key extraction for cvl yang --- src/translib/transformer/xlate.go | 4 +++- src/translib/transformer/xlate_to_db.go | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index f8380f19e0..0c1a34856b 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -185,7 +185,9 @@ func fillKeySpec(yangXpath string, keyStr string, dbFormat *KeySpec) { xpathInfo := xSpecMap[yangXpath] if xpathInfo.tableName != nil { dbFormat.Ts.Name = *xpathInfo.tableName - dbFormat.Key.Comp = append(dbFormat.Key.Comp, keyStr) + if keyStr != "" { + dbFormat.Key.Comp = append(dbFormat.Key.Comp, keyStr) + } } for _, child := range xpathInfo.childTable { // Current support for one child. Should change the KeySpec.Child diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index 7e9c06c1f0..fc4adbed26 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -283,6 +283,22 @@ func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, return nil } +func sonicXpathKeyExtract(path string) (string, string, string){ + rgp := regexp.MustCompile(`\[([^\[\]]*)\]`) + tableName := strings.Split(strings.Split(path , "/")[2], "[")[0] + xpath, err := RemoveXPATHPredicates(path) + if err != nil { + return "", "", "" + } + keyStr := "" + for i, kname := range rgp.FindAllString(path, -1) { + if i > 0 { keyStr += "|" } + val := strings.Split(kname, "=")[1] + keyStr += strings.TrimRight(val, "]") + } + return xpath, keyStr, tableName +} + /* Extract key vars, create db key and xpath */ func xpathKeyExtract(path string) (string, string, string) { yangXpath := "" From 164ebcf87d2caed896984af2bd6605dc1b9f39e3 Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Wed, 21 Aug 2019 19:17:00 -0700 Subject: [PATCH 069/214] Send proper key formed for cvl yang delete case --- src/translib/transformer/xlate_to_db.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index fc4adbed26..347aec4047 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -128,12 +128,14 @@ func directDbMapData(tableName string, jsonData interface{}, result map[string]m /* Get the db table, key and field name for the incoming delete request */ func dbMapDelete(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string, jsonData interface{}, result map[string]map[string]db.Value) error { - xpathPrefix, keyName, tableName := xpathKeyExtract(path) - log.Info("Delete req: path(\"%v\"), key(\"%v\"), xpathPrefix(\"%v\"), tableName(\"%v\").", path, keyName, xpathPrefix, tableName) var err error - if isCvlYang(xpathPrefix) { + if isCvlYang(path) { + xpathPrefix, keyName, tableName := sonicXpathKeyExtract(path) + log.Info("Delete req: path(\"%v\"), key(\"%v\"), xpathPrefix(\"%v\"), tableName(\"%v\").", path, keyName, xpathPrefix, tableName) err = cvlYangReqToDbMapDelete(xpathPrefix, tableName, keyName, result) } else { + xpathPrefix, keyName, tableName := xpathKeyExtract(path) + log.Info("Delete req: path(\"%v\"), key(\"%v\"), xpathPrefix(\"%v\"), tableName(\"%v\").", path, keyName, xpathPrefix, tableName) spec, ok := xSpecMap[xpathPrefix] if ok && spec.tableName != nil { result[*spec.tableName] = make(map[string]db.Value) From 8991985b83c9c7d9557659b53af05ee7d60cff80 Mon Sep 17 00:00:00 2001 From: amrutasali Date: Thu, 22 Aug 2019 02:23:18 +0000 Subject: [PATCH 070/214] Set case for Sonic yang - Added support for leaf-list handling in transformer --- src/translib/transformer/xlate_to_db.go | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index fc4adbed26..3a0faa620a 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -118,6 +118,28 @@ func directDbMapData(tableName string, jsonData interface{}, result map[string]m result[tableName][keyName] = db.Value{Field: make(map[string]string)} for field, value := range d { + fieldXpath := tableName + "/" + field + if _, fieldOk := xDbSpecMap[fieldXpath]; (fieldOk && (xDbSpecMap[fieldXpath].dbEntry != nil)) { + log.Info("Found non-nil yang entry in xDbSpecMap for field xpath = ", fieldXpath) + if xDbSpecMap[fieldXpath].dbEntry.IsLeafList() { + log.Info("Yang type is Leaflist for field = ", field) + field += "@" + fieldDt := reflect.ValueOf(value) + fieldValue := "" + for fidx := 0; fidx < fieldDt.Len(); fidx++ { + if fidx > 0 { + fieldValue += "," + } + fVal := fmt.Sprintf("%v", fieldDt.Index(fidx).Interface()) + fieldValue = fieldValue + fVal + } + result[tableName][keyName].Field[field] = fieldValue + continue + } + } else { + // should ideally never happen , just adding for safety + log.Info("Did not find entry in xDbSpecMap for field xpath = ", fieldXpath) + } result[tableName][keyName].Field[field] = fmt.Sprintf("%v", value) } } From 68b856ee68e6923c9e0096485098d5e950dd2d12 Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Thu, 22 Aug 2019 14:22:15 -0700 Subject: [PATCH 071/214] Use "|" as delimited for CVL keys --- src/translib/transformer/xlate.go | 19 +++++++++++-------- src/translib/transformer/xlate_from_db.go | 6 +++--- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index 0c1a34856b..6330175198 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -114,13 +114,14 @@ func XlateUriToKeySpec(path string, uri *ygot.GoStruct, t *interface{}) (*map[db var result = make(map[db.DBNum][]KeySpec) var retdbFormat = make([]KeySpec, 0) - /* Extract the xpath and key from input xpath */ - yangXpath, keyStr, tableName := xpathKeyExtract(path) - // In case of CVL yang, the tablename and key info is available in the xpath - if isCvlYang(yangXpath) { + if isCvlYang(path) { + /* Extract the xpath and key from input xpath */ + yangXpath, keyStr, tableName := sonicXpathKeyExtract(path) retdbFormat = fillCvlKeySpec(yangXpath, tableName, keyStr) } else { + /* Extract the xpath and key from input xpath */ + yangXpath, keyStr, _ := xpathKeyExtract(path) if xSpecMap == nil { return &result, err } @@ -262,15 +263,15 @@ func XlateToDb(path string, opcode int, d *db.DB, yg *ygot.GoStruct, yt *interfa func XlateFromDb(xpath string, data map[string]map[string]db.Value) ([]byte, error) { var err error - var fieldName, tableName string + var fieldName, tableName, yangXpath string var dbData = make(map[string]map[string]db.Value) dbData = data - yangXpath, keyStr, tblName := xpathKeyExtract(xpath) if isCvlYang(xpath) { - if (tblName != "") { - tableName = tblName + yXpath, keyStr, tableName := sonicXpathKeyExtract(xpath) + yangXpath = yXpath + if (tableName != "") { tokens:= strings.Split(yangXpath, "/") // Format /module:container/tableName[key]/fieldName if tokens[len(tokens)-2] == tableName { @@ -279,6 +280,8 @@ func XlateFromDb(xpath string, data map[string]map[string]db.Value) ([]byte, err } } } else { + yXpath, keyStr, _ := xpathKeyExtract(xpath) + yangXpath = yXpath if xSpecMap == nil { return nil, err } diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index 22cf2edae7..324678de7e 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -89,11 +89,11 @@ func directDbToYangJsonCreate(dbDataMap map[string]map[string]db.Value, jsonData for field, value := range dbFldValData.Field { fldValPair += fmt.Sprintf("\"%v\" : \"%v\",\r\n", field, value) } - yangKeys := yangKeyFromEntryGet(xDbSpecMap[tblName].dbEntry) + yangKeys := yangKeyFromEntryGet(xDbSpecMap[tblName].dbEntry) fldValPair = keyJsonDataAdd(yangKeys, keyStr, fldValPair) - dataInst = fmt.Sprintf("{ \r\n %v \r\n },", fldValPair) + dataInst += fmt.Sprintf("{ \r\n %v \r\n },", fldValPair) } - dataInst += strings.TrimRight(dataInst, ",") + dataInst = strings.TrimRight(dataInst, ",") jsonData += fmt.Sprintf("\"%v\" : [\r\n %v\r\n ],", tblName, dataInst) } jsonData = strings.TrimRight(jsonData, ",") From e14f7f6e6ff8533fe744688bfa21919de883d75e Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Thu, 22 Aug 2019 17:16:55 -0700 Subject: [PATCH 072/214] Fix get request for top level container --- src/translib/transformer/xlate_to_db.go | 31 ++++++++++++++----------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index 97fd730b37..3b01f841b6 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -13,6 +13,9 @@ import ( log "github.com/golang/glog" ) +const SONIC_TABLE_INDEX = 2 +const SONIC_FIELD_INDEX = 3 + /* Fill redis-db map with field & value info */ func dataToDBMapAdd(tableName string, dbKey string, result map[string]map[string]db.Value, field string, value string) { _, ok := result[tableName] @@ -191,11 +194,9 @@ func cvlYangReqToDbMapDelete(xpathPrefix string, tableName string, keyName strin result[tableName][keyName] = dbVal } else { // Get all keys - fmt.Println("No Key. Return table name") } } else { // Get all table entries - fmt.Println("No table name. Delete all entries") // If table name not available in xpath get top container name tokens:= strings.Split(xpathPrefix, ":") container := "/" + tokens[len(tokens)-1] @@ -307,18 +308,22 @@ func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, return nil } -func sonicXpathKeyExtract(path string) (string, string, string){ +func sonicXpathKeyExtract(path string) (string, string, string) { + xpath, keyStr, tableName := "", "", "" + var err error + xpath, err = RemoveXPATHPredicates(path) + if err != nil { + return xpath, keyStr, tableName + } rgp := regexp.MustCompile(`\[([^\[\]]*)\]`) - tableName := strings.Split(strings.Split(path , "/")[2], "[")[0] - xpath, err := RemoveXPATHPredicates(path) - if err != nil { - return "", "", "" - } - keyStr := "" - for i, kname := range rgp.FindAllString(path, -1) { - if i > 0 { keyStr += "|" } - val := strings.Split(kname, "=")[1] - keyStr += strings.TrimRight(val, "]") + pathsubStr := strings.Split(path , "/") + if len(pathsubStr) > SONIC_TABLE_INDEX { + tableName = strings.Split(pathsubStr[SONIC_TABLE_INDEX], "[")[0] + for i, kname := range rgp.FindAllString(path, -1) { + if i > 0 { keyStr += "|" } + val := strings.Split(kname, "=")[1] + keyStr += strings.TrimRight(val, "]") + } } return xpath, keyStr, tableName } From 014c2faeee41a637588159ae320a80aca0cd3ed6 Mon Sep 17 00:00:00 2001 From: amrutasali Date: Mon, 26 Aug 2019 08:33:19 +0000 Subject: [PATCH 073/214] For delete case added support for deletion as per table ordering, restructured common app accordingly --- src/translib/common_app.go | 243 ++++++++++++++++++------------ src/translib/transformer/xlate.go | 2 +- 2 files changed, 145 insertions(+), 100 deletions(-) diff --git a/src/translib/common_app.go b/src/translib/common_app.go index 76fda96749..f998556814 100644 --- a/src/translib/common_app.go +++ b/src/translib/common_app.go @@ -18,7 +18,7 @@ type CommonApp struct { ygotRoot *ygot.GoStruct ygotTarget *interface{} cmnAppTableMap map[string]map[string]db.Value - cmnAppSchemaOrdTbllist []string + cmnAppOrdTbllist []string } var cmnAppInfo = appInfo{appType: reflect.TypeOf(CommonApp{}), @@ -52,7 +52,7 @@ func (app *CommonApp) translateCreate(d *db.DB) ([]db.WatchKeys, error) { var keys []db.WatchKeys log.Info("translateCreate:path =", app.pathInfo.Path) - keys, err = app.translateCRUCommon(d, CREATE) + keys, err = app.translateCRUDCommon(d, CREATE) return keys, err } @@ -62,7 +62,7 @@ func (app *CommonApp) translateUpdate(d *db.DB) ([]db.WatchKeys, error) { var keys []db.WatchKeys log.Info("translateUpdate:path =", app.pathInfo.Path) - keys, err = app.translateCRUCommon(d, UPDATE) + keys, err = app.translateCRUDCommon(d, UPDATE) return keys, err } @@ -72,7 +72,7 @@ func (app *CommonApp) translateReplace(d *db.DB) ([]db.WatchKeys, error) { var keys []db.WatchKeys log.Info("translateReplace:path =", app.pathInfo.Path) - keys, err = app.translateCRUCommon(d, REPLACE) + keys, err = app.translateCRUDCommon(d, REPLACE) return keys, err } @@ -81,7 +81,7 @@ func (app *CommonApp) translateDelete(d *db.DB) ([]db.WatchKeys, error) { var err error var keys []db.WatchKeys log.Info("translateDelete:path =", app.pathInfo.Path) - keys, err = app.translateCRUCommon(d, DELETE) + keys, err = app.translateCRUDCommon(d, DELETE) return keys, err } @@ -157,7 +157,6 @@ func (app *CommonApp) processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error) { keySpec, err := transformer.XlateUriToKeySpec(app.pathInfo.Path, app.ygotRoot, app.ygotTarget) - // table.key.fields var result = make(map[string]map[string]db.Value) for dbnum, specs := range *keySpec { @@ -177,29 +176,29 @@ func (app *CommonApp) processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error) { return GetResponse{Payload: payload}, err } -func (app *CommonApp) translateCRUCommon(d *db.DB, opcode int) ([]db.WatchKeys, error) { +func (app *CommonApp) translateCRUDCommon(d *db.DB, opcode int) ([]db.WatchKeys, error) { var err error var keys []db.WatchKeys var tblsToWatch []*db.TableSpec - var schemaOrdTblList []string + var OrdTblList []string var moduleNm string - log.Info("translateCRUCommon:path =", app.pathInfo.Path) + log.Info("translateCRUDCommon:path =", app.pathInfo.Path) - /* retrieve schema table order for incoming maodule name request */ + /* retrieve schema table order for incoming module name request */ moduleNm, err = transformer.GetModuleNmFromPath(app.pathInfo.Path) if (err != nil) || (len(moduleNm) == 0) { log.Error("GetModuleNmFromPath() failed") return keys, err } log.Info("getModuleNmFromPath() returned module name = ", moduleNm) - schemaOrdTblList, err = transformer.GetSchemaOrdDBTblList(moduleNm) - if (err != nil) || (len(schemaOrdTblList) == 0) { - log.Error("GetSchemaOrdDBTblList() failed") + OrdTblList, err = transformer.GetOrdDBTblList(moduleNm) + if (err != nil) || (len(OrdTblList) == 0) { + log.Error("GetOrdDBTblList() failed") return keys, err } - log.Info("getSchemaOrdDBTblList() returned ordered table list = ", schemaOrdTblList) - app.cmnAppSchemaOrdTbllist = schemaOrdTblList + log.Info("GetOrdDBTblList() returned ordered table list = ", OrdTblList) + app.cmnAppOrdTbllist = OrdTblList // translate yang to db result, err := transformer.XlateToDb(app.pathInfo.Path, opcode, d, (*app).ygotRoot, (*app).ygotTarget) @@ -216,6 +215,8 @@ func (app *CommonApp) translateCRUCommon(d *db.DB, opcode int) ([]db.WatchKeys, return keys, err } app.cmnAppTableMap = result + + /* enhance this to handle dependent tables - need CVL to provide list of such tables for a given request */ for tblnm, _ := range app.cmnAppTableMap { log.Error("Table name ", tblnm) tblsToWatch = append(tblsToWatch, &db.TableSpec{Name: tblnm}) @@ -223,6 +224,8 @@ func (app *CommonApp) translateCRUCommon(d *db.DB, opcode int) ([]db.WatchKeys, log.Info("Tables to watch", tblsToWatch) cmnAppInfo.tablesToWatch = tblsToWatch + /* In case all related tables need to be watched + cmnAppInfo.tablesToWatch = OrdTblList */ keys, err = app.generateDbWatchKeys(d, false) @@ -230,117 +233,159 @@ func (app *CommonApp) translateCRUCommon(d *db.DB, opcode int) ([]db.WatchKeys, } func (app *CommonApp) processCommon(d *db.DB, opcode int) error { + var err error - err = app.cmnAppDataDbOperation(d, opcode, app.cmnAppTableMap) + + log.Info("Processing DB operation for ", app.cmnAppTableMap) + switch opcode { + case CREATE: + log.Info("CREATE case") + err = app.cmnAppCRUCommonDbOpn(d, opcode) + case UPDATE: + log.Info("UPDATE case") + err = app.cmnAppCRUCommonDbOpn(d, opcode) + case REPLACE: + log.Info("REPLACE case") + err = app.cmnAppCRUCommonDbOpn(d, opcode) + case DELETE: + log.Info("DELETE case") + err = app.cmnAppDelDbOpn(d, opcode) + } + if err != nil { + log.Info("Returning from processCommon() - fail") + } else { + log.Info("Returning from processCommon() - success") + } return err } -func (app *CommonApp) cmnAppDataDbOperation(d *db.DB, opcode int, cmnAppDataDbMap map[string]map[string]db.Value) error { +func (app *CommonApp) cmnAppCRUCommonDbOpn(d *db.DB, opcode int) error { var err error - log.Info("Processing DB operation for ", cmnAppDataDbMap) var cmnAppTs *db.TableSpec - log.Info("getSchemaOrdDBTblList() returned ordered table list = ", app.cmnAppSchemaOrdTbllist) - //return err - - /* order by schema table order */ - for _, tblNm := range app.cmnAppSchemaOrdTbllist { + /* currently ordered by schema table order needs to be discussed */ + for _, tblNm := range app.cmnAppOrdTbllist { log.Info("In Yang to DB map returned from transformer looking for table = ", tblNm) - if tblVal, ok := cmnAppDataDbMap[tblNm]; ok { + if tblVal, ok := app.cmnAppTableMap[tblNm]; ok { cmnAppTs = &db.TableSpec{Name: tblNm} log.Info("Found table entry in yang to DB map") - switch opcode { + for tblKey, tblRw := range tblVal { + log.Info("Processing Table key and row ", tblKey, tblRw) + existingEntry, _ := d.GetEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}) + switch opcode { case CREATE: - log.Info("CREATE case") - for tblKey, tblRw := range tblVal { - log.Info("Processing Table key and row ", tblKey, tblRw) - existingEntry, err := d.GetEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}) - if existingEntry.IsPopulated() { - log.Info("Entry already exists hence return error.") - return tlerr.AlreadyExists("Entry %s already exists", tblKey) - } else { - err = d.CreateEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}, tblRw) - if err != nil { - log.Error("CREATE case - d.CreateEntry() failure") - return err - } + if existingEntry.IsPopulated() { + log.Info("Entry already exists hence return error.") + return tlerr.AlreadyExists("Entry %s already exists", tblKey) + } else { + err = d.CreateEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}, tblRw) + if err != nil { + log.Error("CREATE case - d.CreateEntry() failure") + return err } - } - case UPDATE: - log.Info("UPDATE case") - for tblKey, tblRw := range tblVal { - existingEntry, err := d.GetEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}) - if existingEntry.IsPopulated() { - log.Info("Entry already exists hence modifying it.") - err = d.ModEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}, tblRw) - if err != nil { - log.Error("UPDATE case - d.ModEntry() failure") - return err - } - } else { - log.Info("Entry to be modified does not exist hence return error.") - return tlerr.NotFound("Entry %s to be modified does not exist.", tblKey) + if existingEntry.IsPopulated() { + log.Info("Entry already exists hence modifying it.") + err = d.ModEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}, tblRw) + if err != nil { + log.Error("UPDATE case - d.ModEntry() failure") + return err } + } else { + return err } - case REPLACE: - log.Info("REPLACE case") - for tblKey, tblRw := range tblVal { - existingEntry, err := d.GetEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}) - if existingEntry.IsPopulated() { - log.Info("Entry already exists hence execute db.SetEntry") - err := d.SetEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}, tblRw) - if err != nil { - log.Error("REPLACE case - d.SetEntry() failure") - return err - } - } else { - log.Info("Entry doesn't exist hence create it.") - err = d.CreateEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}, tblRw) - if err != nil { - log.Error("REPLACE case - d.CreateEntry() failure") - return err - } - } - //TODO : should the table level replace be handled?? - } - case DELETE: - log.Info("DELETE case") - if len(tblVal) == 0 { - log.Info("DELETE case - No table instances hence delete entire table = ", tblNm) - err = d.DeleteTable(cmnAppTs) + if existingEntry.IsPopulated() { + log.Info("Entry already exists hence execute db.SetEntry") + err := d.SetEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}, tblRw) if err != nil { - log.Error("DELETE case - d.DeleteTable() failure for Table = ", tblNm) + log.Error("REPLACE case - d.SetEntry() failure") return err } - log.Info("DELETE case - Deleted entire table = ", tblNm) - continue - } - for tblKey, tblRw := range tblVal { - if len(tblRw.Field) == 0 { - log.Info("DELETE case - no fields/cols to delete hence delete the entire row.") - err := d.DeleteEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}) - if err != nil { - log.Error("DELETE case - d.DeleteEntry() failure") - return err - } - } else { - log.Info("DELETE case - fields/cols to delete hence delete only those fields.") - err := d.DeleteEntryFields(cmnAppTs, db.Key{Comp: []string{tblKey}}, tblRw) - if err != nil { - log.Error("DELETE case - d.DeleteEntryFields() failure") - return err - } + } else { + log.Info("Entry doesn't exist hence create it.") + err = d.CreateEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}, tblRw) + if err != nil { + log.Error("REPLACE case - d.CreateEntry() failure") + return err } } + } } } } - return err +} + +func (app *CommonApp) cmnAppDelDbOpn(d *db.DB, opcode int) error { + var err error + var cmnAppTs, dbTblSpec *db.TableSpec + + /* needs enhancements from CVL to give table dependencies, and grouping of related tables only + if such a case where the sonic yang has unrelated tables */ + for tblidx, tblNm := range app.cmnAppOrdTbllist { + log.Info("In Yang to DB map returned from transformer looking for table = ", tblNm) + if tblVal, ok := app.cmnAppTableMap[tblNm]; ok { + cmnAppTs = &db.TableSpec{Name: tblNm} + log.Info("Found table entry in yang to DB map") + if len(tblVal) == 0 { + log.Info("DELETE case - No table instances/rows found hence delete entire table = ", tblNm) + for idx := len(app.cmnAppOrdTbllist)-1; idx >= tblidx+1; idx-- { + log.Info("Since parent table is to be deleted, first deleting child table = ", app.cmnAppOrdTbllist[idx]) + dbTblSpec = &db.TableSpec{Name: app.cmnAppOrdTbllist[idx]} + err = d.DeleteTable(dbTblSpec) + if err != nil { + log.Warning("DELETE case - d.DeleteTable() failure for Table = ", app.cmnAppOrdTbllist[idx]) + return err + } + } + err = d.DeleteTable(cmnAppTs) + if err != nil { + log.Warning("DELETE case - d.DeleteTable() failure for Table = ", tblNm) + return err + } + log.Info("DELETE case - Deleted entire table = ", tblNm) + log.Info("Done processing all tables.") + break + + } + for tblKey, tblRw := range tblVal { + if len(tblRw.Field) == 0 { + log.Info("DELETE case - no fields/cols to delete hence delete the entire row.") + log.Info("First, delete child table instances that correspond to parent table instance to be deleted = ", tblKey) + for idx := len(app.cmnAppOrdTbllist)-1; idx >= tblidx+1; idx-- { + dbTblSpec = &db.TableSpec{Name: app.cmnAppOrdTbllist[idx]} + keyPattern := tblKey + "|*" + log.Info("Key pattern to be matched for deletion = ", keyPattern) + err = d.DeleteKeys(dbTblSpec, db.Key{Comp: []string{keyPattern}}) + if err != nil { + log.Warning("DELETE case - d.DeleteTable() failure for Table = ", app.cmnAppOrdTbllist[idx]) + return err + } + log.Info("Deleted keys matching parent table key pattern for child table = ", app.cmnAppOrdTbllist[idx]) + + } + err = d.DeleteEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}) + if err != nil { + log.Warning("DELETE case - d.DeleteEntry() failure") + return err + } + log.Info("Finally deleted the parent table row with key = ", tblKey) + } else { + log.Info("DELETE case - fields/cols to delete hence delete only those fields.") + err := d.DeleteEntryFields(cmnAppTs, db.Key{Comp: []string{tblKey}}, tblRw) + if err != nil { + log.Error("DELETE case - d.DeleteEntryFields() failure") + return err + } + } + + } + } + } /* end of ordered table list for loop */ + return err } func (app *CommonApp) generateDbWatchKeys(d *db.DB, isDeleteOp bool) ([]db.WatchKeys, error) { diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index 6330175198..3d182b2875 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -337,7 +337,7 @@ func GetModuleNmFromPath(uri string) (string, error) { return moduleNm, err } -func GetSchemaOrdDBTblList(ygModuleNm string) ([]string, error) { +func GetOrdDBTblList(ygModuleNm string) ([]string, error) { var result []string var err error if dbTblList, ok := xDbSpecOrdTblMap[ygModuleNm]; ok { From 9cd3339a28fb7d252c331b8b307d18a9c6af6c79 Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Mon, 26 Aug 2019 13:31:04 -0700 Subject: [PATCH 074/214] Update the correct input json file name for create test case --- src/translib/test/acl-sonic/01_create_MyACL1_1Rule_cmd.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/translib/test/acl-sonic/01_create_MyACL1_1Rule_cmd.txt b/src/translib/test/acl-sonic/01_create_MyACL1_1Rule_cmd.txt index fc6aa77e30..1153b1beb3 100644 --- a/src/translib/test/acl-sonic/01_create_MyACL1_1Rule_cmd.txt +++ b/src/translib/test/acl-sonic/01_create_MyACL1_1Rule_cmd.txt @@ -1 +1 @@ -./translibtest -o "create" -u "/sonic-acl:sonic-acl" -p "./acl-sonic/01_create_MyACL1.json" -logtostderr +./translibtest -o "create" -u "/sonic-acl:sonic-acl" -p "./acl-sonic/01_create_MyACL1_1Rule.json" -logtostderr From c0ae3fb46b060ce8341b211b048a648cd8f75cd6 Mon Sep 17 00:00:00 2001 From: s-mari Date: Mon, 26 Aug 2019 16:37:07 -0700 Subject: [PATCH 075/214] fixed leaf level get for oc-yang --- src/translib/acl_app.go | 6 +- src/translib/transformer/xlate.go | 4 +- src/translib/transformer/xlate_from_db.go | 67 +++++++++++++++++++++-- src/translib/transformer/xlate_to_db.go | 30 ++++++---- src/translib/transformer/xspec.go | 2 - 5 files changed, 85 insertions(+), 24 deletions(-) diff --git a/src/translib/acl_app.go b/src/translib/acl_app.go index f8e2d8eeea..88a42552a2 100644 --- a/src/translib/acl_app.go +++ b/src/translib/acl_app.go @@ -226,7 +226,7 @@ func handleAclInterface(d *db.DB, app *AclApp, opcode int) error { var err error for key, data := range app.aclTableMap { existingEntry, err := d.GetEntry(app.aclTs, db.Key{Comp: []string{key}}) - if !existingEntry.IsPopulated() { + if opcode == CREATE && existingEntry.Field != nil { return tlerr.AlreadyExists("Acl %s already exists", key) } // !!! Overloaded xfmr methods tale care for bindings, to set the data @@ -250,7 +250,7 @@ func handleAclSet(d *db.DB, app *AclApp, opcode int) error { // acl table for key, data := range app.aclTableMap { existingEntry, err := d.GetEntry(app.aclTs, db.Key{Comp: []string{key}}) - if opcode == CREATE && existingEntry.IsPopulated() { + if opcode == CREATE && existingEntry.Field != nil { return tlerr.AlreadyExists("Acl %s already exists", key) } switch opcode { @@ -285,7 +285,7 @@ func handleAclEntry(d *db.DB, app *AclApp, opcode int) error { for key, data := range app.ruleTableMap { ruleName := strings.Split(key, KEY_SEPARATOR)[1] existingEntry, err := d.GetEntry(app.ruleTs, db.Key{Comp: []string{key}}) - if opcode == CREATE && existingEntry.IsPopulated() { + if opcode == CREATE && existingEntry.Field != nil { return tlerr.AlreadyExists("Acl rule %s already exists", ruleName) } switch opcode { diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index 0c1a34856b..3c2b531588 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -115,7 +115,7 @@ func XlateUriToKeySpec(path string, uri *ygot.GoStruct, t *interface{}) (*map[db var retdbFormat = make([]KeySpec, 0) /* Extract the xpath and key from input xpath */ - yangXpath, keyStr, tableName := xpathKeyExtract(path) + yangXpath, keyStr, tableName := xpathKeyExtract(nil, uri, 0, path) // In case of CVL yang, the tablename and key info is available in the xpath if isCvlYang(yangXpath) { @@ -266,7 +266,7 @@ func XlateFromDb(xpath string, data map[string]map[string]db.Value) ([]byte, err var dbData = make(map[string]map[string]db.Value) dbData = data - yangXpath, keyStr, tblName := xpathKeyExtract(xpath) + yangXpath, keyStr, tblName := xpathKeyExtract(nil, nil, 0, xpath) if isCvlYang(xpath) { if (tblName != "") { diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index 22cf2edae7..e7767398ad 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -77,6 +77,7 @@ func listDataToJsonAdd(xpathl []string, dataMap map[string]db.Value, key string, jsonData = fmt.Sprintf("\"%v\" : [\r\n %v\r\n ]\r\n", xSpecMap[xpath].yangEntry.Name, jsonData) } } + jsonData = strings.TrimRight(jsonData, ",") return jsonData } @@ -100,14 +101,38 @@ func directDbToYangJsonCreate(dbDataMap map[string]map[string]db.Value, jsonData return jsonData } +func tableNameAndKeyFromDbMapGet(dbDataMap map[string]map[string]db.Value) (string, string, error) { + tableName := "" + tableKey := "" + for tn, tblData := range dbDataMap { + tableName = tn + for kname, _ := range tblData { + tableKey = kname + } + } + return tableName, tableKey, nil +} + /* Traverse linear db-map data and add to nested json data */ func dbDataToYangJsonCreate(xpath string, dbDataMap map[string]map[string]db.Value) (string, error) { jsonData := "" + if isCvlYang(xpath) { jsonData := directDbToYangJsonCreate(dbDataMap, jsonData) jsonDataPrint(jsonData) return jsonData, nil } + + reqXpath, _, _ := xpathKeyExtract(nil, nil, 0, xpath) + ftype := yangTypeGet(xSpecMap[reqXpath].yangEntry) + if ftype == "leaf" { + fldName := xSpecMap[reqXpath].fieldName + tbl, key, _ := tableNameAndKeyFromDbMapGet(dbDataMap) + jsonData = fmt.Sprintf("{\r\n \"%v\" : \"%v\" \r\n }\r\n", xSpecMap[reqXpath].yangEntry.Name, + dbDataMap[tbl][key].Field[fldName]) + return jsonData, nil + } + curXpath := "" for tblName, tblData := range dbDataMap { if len(curXpath) == 0 || strings.HasPrefix(curXpath, xDbSpecMap[tblName].yangXpath[0]) { @@ -115,15 +140,45 @@ func dbDataToYangJsonCreate(xpath string, dbDataMap map[string]map[string]db.Val } jsonData += listDataToJsonAdd(xDbSpecMap[tblName].yangXpath, tblData, "", dbDataMap) } - //jsonData = parentJsonDataUpdate(curXpath, jsonData) + if strings.HasPrefix(reqXpath, curXpath) { + if ftype != "leaf" { + jsonData = fmt.Sprintf("{ \r\n %v \r\n }", jsonData) + } + return jsonData, nil + } + jsonData = parentJsonDataUpdate(reqXpath, curXpath, jsonData) jsonDataPrint(jsonData) return jsonData, nil } -func parentJsonDataUpdate(xpath string, data string) string { +func xpathLastAttrGet(xpath string) string { + attrList := strings.Split(xpath, "/") + return attrList[len(attrList)-1] +} + +func jsonPayloadComplete(reqXpath string, data string) string { + entry := xSpecMap[reqXpath].yangEntry + entryType := entry.Node.Statement().Keyword + name := xpathLastAttrGet(reqXpath) + switch entryType { + case "container": + data = fmt.Sprintf("\"%v\" : { \r\n %v \r\n }\r\n", name, data) + case "list": + data = fmt.Sprintf("\"%v\" : [\r\n %v\r\n ]\r\n", name, data) + } + data = fmt.Sprintf("{\r\n %v }\r\n", data) + return data +} + +func parentJsonDataUpdate(reqXpath string, xpath string, data string) string { curXpath := parentXpathGet(xpath) - if len(curXpath) == 0 && strings.Contains(xpath, ":") { - curXpath = strings.Split(xpath, ":")[0] + if reqXpath == xpath { + data = fmt.Sprintf("{\r\n %v }\r\n", data) + return data + } + if reqXpath == curXpath { + data = jsonPayloadComplete(reqXpath, data) + return data } if xSpecMap[curXpath] != nil { entry := xSpecMap[curXpath].yangEntry @@ -131,10 +186,10 @@ func parentJsonDataUpdate(xpath string, data string) string { switch entryType { case "container": data = fmt.Sprintf("\"%v\" : { \r\n %v \r\n }", xSpecMap[curXpath].yangEntry.Name, data) - return parentJsonDataUpdate(curXpath, data) + return parentJsonDataUpdate(reqXpath, curXpath, data) case "list": data = fmt.Sprintf("\"%v\" : [\r\n %v\r\n ]\r\n", xSpecMap[curXpath].yangEntry.Name, data) - return parentJsonDataUpdate(curXpath, data) + return parentJsonDataUpdate(reqXpath, curXpath, data) case "module": data = fmt.Sprintf("\"%v\" : { \r\n %v \r\n }", xSpecMap[curXpath].yangEntry.Name, data) return data diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index fc4adbed26..26c6ae84c0 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -128,7 +128,7 @@ func directDbMapData(tableName string, jsonData interface{}, result map[string]m /* Get the db table, key and field name for the incoming delete request */ func dbMapDelete(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string, jsonData interface{}, result map[string]map[string]db.Value) error { - xpathPrefix, keyName, tableName := xpathKeyExtract(path) + xpathPrefix, keyName, tableName := xpathKeyExtract(d, ygRoot, oper, path) log.Info("Delete req: path(\"%v\"), key(\"%v\"), xpathPrefix(\"%v\"), tableName(\"%v\").", path, keyName, xpathPrefix, tableName) var err error if isCvlYang(xpathPrefix) { @@ -300,37 +300,45 @@ func sonicXpathKeyExtract(path string) (string, string, string){ } /* Extract key vars, create db key and xpath */ -func xpathKeyExtract(path string) (string, string, string) { - yangXpath := "" - keyStr := "" +func xpathKeyExtract(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string) (string, string, string) { + keyStr := "" tableName := "" - rgp := regexp.MustCompile(`\[([^\[\]]*)\]`) + rgp := regexp.MustCompile(`\[([^\[\]]*)\]`) + curPathWithKey := "" - for i, k := range strings.Split(path, "/") { - if i > 0 { - yangXpath += "/" - } + for _, k := range strings.Split(path, "/") { xpath := k + curPathWithKey += k if strings.Contains(k, "[") { if len(keyStr) > 0 { keyStr += "|" } + yangXpath, _ := RemoveXPATHPredicates(curPathWithKey) xpath = strings.Split(k, "[")[0] + if len(xSpecMap[yangXpath].xfmrKey) > 0 { + ret, err := XlateFuncCall(yangToDbXfmrFunc(xSpecMap[yangXpath].xfmrKey), d, ygRoot, oper, curPathWithKey) + if err != nil { + return "", "", "" + } + keyStr = ret[0].Interface().(string) + } else { var keyl []string for _, kname := range rgp.FindAllString(k, -1) { keyl = append(keyl, strings.TrimRight(strings.TrimLeft(kname, "["), "]")) } keyStr += keyFromXpathCreate(keyl) + } if isCvlYang(path) { //Format- /module:container/table[key]/field // table name extracted from the string token having key entry tableName = xpath } } - yangXpath += xpath + curPathWithKey += "/" } + pfxPath, _ := RemoveXPATHPredicates(path) - return yangXpath, keyStr, tableName + return pfxPath, keyStr, tableName } /* Debug function to print the map data into file */ diff --git a/src/translib/transformer/xspec.go b/src/translib/transformer/xspec.go index cf1ab21d32..4725db08c9 100644 --- a/src/translib/transformer/xspec.go +++ b/src/translib/transformer/xspec.go @@ -3,7 +3,6 @@ package transformer import ( "fmt" "os" - "sort" "strings" log "github.com/golang/glog" @@ -117,7 +116,6 @@ func yangToDbMapFill (xSpecMap map[string]*yangXpathInfo, entry *yang.Entry, xpa childList = append(childList, k) } - sort.Strings(childList) xpathData.yangEntry = entry /* now recurse, filling the map with current node's children info */ for _, child := range childList { From 10d7f925987307cd0950fd9120cf5a7cde9b696c Mon Sep 17 00:00:00 2001 From: s-mari Date: Mon, 26 Aug 2019 20:49:34 -0700 Subject: [PATCH 076/214] corrected the uri for field transformer --- src/translib/transformer/xlate_from_db.go | 6 +++--- src/translib/transformer/xlate_to_db.go | 10 ++++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index d4277414fb..0fa976ad01 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -38,9 +38,9 @@ func dataToJsonAdd(xpath string, fieldData map[string]string, key string, dbData /* Inner(child) list, traverse this list */ childMap, ok := dbDataMap[*xSpecMap[fldXpath].tableName] if ok { - var xpathl []string - xpathl = append(xpathl, fldXpath) - jsonData += listDataToJsonAdd(xpathl, childMap, key, dbDataMap) + var xpathl []string + xpathl = append(xpathl, fldXpath) + jsonData += listDataToJsonAdd(xpathl, childMap, key, dbDataMap) } } } diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index cb44580649..ae42949d22 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -54,6 +54,7 @@ func mapFillData(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, dbKey st } if len(xpathInfo.xfmrFunc) > 0 { + uri = uri + "/" + name /* field transformer present */ log.Info("Transformer function(\"%v\") invoked for yang path(\"%v\").", xpathInfo.xfmrFunc, xpath) ret, err := XlateFuncCall(yangToDbXfmrFunc(xSpecMap[xpath].xfmrFunc), d, ygRoot, oper, uri, value) @@ -269,24 +270,25 @@ func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, if typeOfValue == reflect.Map || typeOfValue == reflect.Slice { log.Info("slice/map data: key(\"%v\"), xpathPrefix(\"%v\").", keyName, xpathPrefix) xpath := uri + curUri := uri pathAttr := key.String() if len(xpathPrefix) > 0 { if strings.Contains(pathAttr, ":") { pathAttr = strings.Split(pathAttr, ":")[1] } - xpath = xpathPrefix + "/" + pathAttr - uri = uri + "/" + pathAttr + xpath = xpathPrefix + "/" + pathAttr + curUri = uri + "/" + pathAttr } if xSpecMap[xpath] != nil && len(xSpecMap[xpath].xfmrFunc) > 0 { /* subtree transformer present */ - ret, err := XlateFuncCall(yangToDbXfmrFunc(xSpecMap[xpath].xfmrFunc), d, ygRoot, oper, uri) + ret, err := XlateFuncCall(yangToDbXfmrFunc(xSpecMap[xpath].xfmrFunc), d, ygRoot, oper, curUri) if err != nil { return nil } mapCopy(result, ret[0].Interface().(map[string]map[string]db.Value)) } else { - yangReqToDbMapCreate(d, ygRoot, oper, uri, xpath, keyName, jData.MapIndex(key).Interface(), result) + yangReqToDbMapCreate(d, ygRoot, oper, curUri, xpath, keyName, jData.MapIndex(key).Interface(), result) } } else { pathAttr := key.String() From e53095599d61fbea4203ab6a074ae1d6949bf68a Mon Sep 17 00:00:00 2001 From: Ravi Vasanthm Date: Tue, 27 Aug 2019 16:21:08 -0700 Subject: [PATCH 077/214] Added annotation for l2/config/ethertype attribute. --- models/yang/annotations/openconfig-acl-annot.yang | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/models/yang/annotations/openconfig-acl-annot.yang b/models/yang/annotations/openconfig-acl-annot.yang index be0bfeeb7c..887d4d43d2 100644 --- a/models/yang/annotations/openconfig-acl-annot.yang +++ b/models/yang/annotations/openconfig-acl-annot.yang @@ -59,6 +59,12 @@ module openconfig-acl-annot { } } + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-pkt-match:l2/oc-pkt-match:config/oc-pkt-match:ethertype { + deviate add { + sonic-ext:field-transformer "acl_l2_ethertype_xfmr"; + } + } + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-pkt-match:ipv6/oc-pkt-match:config/oc-pkt-match:protocol { deviate add { sonic-ext:field-transformer "acl_ip_protocol_xfmr"; From a4fad5fed2045ff40182c6a00cb0a8ddfa566400 Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Wed, 28 Aug 2019 01:22:53 -0700 Subject: [PATCH 078/214] support leaf value delete for oc yang --- src/translib/acl_app.go | 52 ++++++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/src/translib/acl_app.go b/src/translib/acl_app.go index 88a42552a2..917ef5b10c 100644 --- a/src/translib/acl_app.go +++ b/src/translib/acl_app.go @@ -93,7 +93,7 @@ func (app *AclApp) translateCreate(d *db.DB) ([]db.WatchKeys, error) { var keys []db.WatchKeys log.Info("translateCreate:acl:path =", app.pathInfo.Template) - keys, err = app.translateCRUCommon(d, CREATE) + keys, err = app.translateCRUDCommon(d, CREATE) return keys, err } @@ -102,7 +102,7 @@ func (app *AclApp) translateUpdate(d *db.DB) ([]db.WatchKeys, error) { var keys []db.WatchKeys log.Info("translateUpdate:acl:path =", app.pathInfo.Template) - keys, err = app.translateCRUCommon(d, UPDATE) + keys, err = app.translateCRUDCommon(d, UPDATE) return keys, err } @@ -111,16 +111,16 @@ func (app *AclApp) translateReplace(d *db.DB) ([]db.WatchKeys, error) { var keys []db.WatchKeys log.Info("translateReplace:acl:path =", app.pathInfo.Template) - keys, err = app.translateCRUCommon(d, REPLACE) + keys, err = app.translateCRUDCommon(d, REPLACE) return keys, err } func (app *AclApp) translateDelete(d *db.DB) ([]db.WatchKeys, error) { var err error var keys []db.WatchKeys - log.Info("translateDelete:acl:path =", app.pathInfo.Template) + log.Info("translateDelete:acl:path =", app.pathInfo.Path) - keys, err = app.translateCRUCommon(d, DELETE) + keys, err = app.translateCRUDCommon(d, DELETE) return keys, err } @@ -205,10 +205,10 @@ func (app *AclApp) processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error) { return GetResponse{Payload: payload}, err } -func (app *AclApp) translateCRUCommon(d *db.DB, opcode int) ([]db.WatchKeys, error) { +func (app *AclApp) translateCRUDCommon(d *db.DB, opcode int) ([]db.WatchKeys, error) { var err error var keys []db.WatchKeys - log.Info("translateCRUCommon:acl:path =", app.pathInfo.Template) + log.Info("translateCRUDCommon:acl:path =", app.pathInfo.Path) result, err := transformer.XlateToDb(app.pathInfo.Path, opcode, d, app.ygotRoot, app.ygotTarget) if err != nil { @@ -266,7 +266,7 @@ func handleAclSet(d *db.DB, app *AclApp, opcode int) error { case UPDATE: err = d.ModEntry(app.aclTs, db.Key{Comp: []string{key}}, data) case DELETE: - err = d.DeleteKeys(app.aclTs, db.Key{Comp: []string{key}}) + err = handleAclDelete(d, app.aclTs, key, data) } if err != nil { break @@ -301,7 +301,7 @@ func handleAclEntry(d *db.DB, app *AclApp, opcode int) error { case UPDATE: err = d.ModEntry(app.ruleTs, db.Key{Comp: []string{key}}, data) case DELETE: - err = d.DeleteKeys(app.ruleTs, db.Key{Comp: []string{key}}) + err = handleAclDelete(d, app.ruleTs, key, data) } if err != nil { break @@ -322,13 +322,12 @@ func handleAcl(d *db.DB, app *AclApp, opcode int) error { func (app *AclApp) processCommon(d *db.DB, opcode int) error { var err error - log.Infof("processCommon--Path Received: %s", app.pathInfo.Template) + log.Infof("processCommon--Path Received: %s", app.pathInfo.Path) // test d.Opts.DisableCVLCheck = true - targetType := reflect.TypeOf(*app.ygotTarget) - xpath, err := transformer.RemoveXPATHPredicates(app.pathInfo.Path) + log.Infof("processCommon--xPath to process: %s", xpath) if err != nil { log.Errorf("processCommon: Failed to remove Xpath Predicates from path %s", app.pathInfo.Template) } @@ -341,12 +340,33 @@ func (app *AclApp) processCommon(d *db.DB, opcode int) error { // fallback callpoints if strings.Contains(xpath, "/openconfig-acl:acl/acl-sets/acl-set/acl-entries/acl-entry") { err = handleAclEntry(d, app, opcode) - } else if strings.Contains(targetType.Elem().Name(), "/openconfig-acl:acl/interfaces") { + } else if strings.Contains(xpath, "/openconfig-acl:acl/acl-sets/acl-set") { + err = handleAclSet(d, app, opcode) + } else if strings.Contains(xpath, "/openconfig-acl:acl/interfaces") { err = handleAclInterface(d, app, opcode) + } else { + err = tlerr.NotSupported("URL %s is not supported", app.pathInfo.Path) } - if err == nil { - err = tlerr.NotSupported("URL %s is not supported", app.pathInfo.Template) - } + } + + return err +} + +func handleAclDelete(d *db.DB, ts *db.TableSpec, key string, value db.Value) error { + var err error + if len(value.Field) > 0 { + // Field entries exist + err = d.DeleteEntryFields(ts, db.Key{Comp: []string{key}}, value) + } else if len(key) > 0 { + // Delete entrire table instance with the required key + err = d.DeleteKeys(ts, db.Key{Comp: []string{key}}) + } else { + // Delete the whole table + err = d.DeleteTable(ts) + } + if err != nil { + log.Error("DELETE case - d.DeleteTable() failure for Table = ", ts.Name) + return err } return err From 69d84713061f6146e88950fd0fac98cc782ff9f7 Mon Sep 17 00:00:00 2001 From: Ravi Vasanthm Date: Wed, 28 Aug 2019 11:08:54 -0700 Subject: [PATCH 079/214] Added transformer config file to specify list of yang models needs to be loaded at startup --- Makefile | 1 + config/transformer/models | 4 ++++ 2 files changed, 5 insertions(+) create mode 100644 config/transformer/models diff --git a/Makefile b/Makefile index a9e4fb7c45..0414329098 100644 --- a/Makefile +++ b/Makefile @@ -105,6 +105,7 @@ install: $(INSTALL) -D $(TOPDIR)/src/cvl/schema/*.yin $(DESTDIR)/usr/sbin/schema/ $(INSTALL) -D $(TOPDIR)/src/cvl/schema/*.yang $(DESTDIR)/usr/models/yang/ $(INSTALL) -D $(TOPDIR)/models/yang/*.yang $(DESTDIR)/usr/models/yang/ + $(INSTALL) -D $(TOPDIR)/config/transformer/models $(DESTDIR)/usr/models/yang/ $(INSTALL) -D $(TOPDIR)/models/yang/common/*.yang $(DESTDIR)/usr/models/yang/ $(INSTALL) -D $(TOPDIR)/models/yang/annotations/*.yang $(DESTDIR)/usr/models/yang/ cp -rf $(TOPDIR)/build/rest_server/dist/ui/ $(DESTDIR)/rest_ui/ diff --git a/config/transformer/models b/config/transformer/models new file mode 100644 index 0000000000..bc192c902a --- /dev/null +++ b/config/transformer/models @@ -0,0 +1,4 @@ +#List yang models transformer need to load + +openconfig-acl.yang +openconfig-acl-annot.yang From 913132bb66a88b874d5be672b528e1c9f30dc391 Mon Sep 17 00:00:00 2001 From: Ravi Vasanthm Date: Wed, 28 Aug 2019 11:35:16 -0700 Subject: [PATCH 080/214] Renamed file models to models_list --- Makefile | 2 +- config/transformer/models_list | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 config/transformer/models_list diff --git a/Makefile b/Makefile index 0414329098..bfbb9fe30c 100644 --- a/Makefile +++ b/Makefile @@ -105,7 +105,7 @@ install: $(INSTALL) -D $(TOPDIR)/src/cvl/schema/*.yin $(DESTDIR)/usr/sbin/schema/ $(INSTALL) -D $(TOPDIR)/src/cvl/schema/*.yang $(DESTDIR)/usr/models/yang/ $(INSTALL) -D $(TOPDIR)/models/yang/*.yang $(DESTDIR)/usr/models/yang/ - $(INSTALL) -D $(TOPDIR)/config/transformer/models $(DESTDIR)/usr/models/yang/ + $(INSTALL) -D $(TOPDIR)/config/transformer/models_list $(DESTDIR)/usr/models/yang/ $(INSTALL) -D $(TOPDIR)/models/yang/common/*.yang $(DESTDIR)/usr/models/yang/ $(INSTALL) -D $(TOPDIR)/models/yang/annotations/*.yang $(DESTDIR)/usr/models/yang/ cp -rf $(TOPDIR)/build/rest_server/dist/ui/ $(DESTDIR)/rest_ui/ diff --git a/config/transformer/models_list b/config/transformer/models_list new file mode 100644 index 0000000000..bc192c902a --- /dev/null +++ b/config/transformer/models_list @@ -0,0 +1,4 @@ +#List yang models transformer need to load + +openconfig-acl.yang +openconfig-acl-annot.yang From fe88df34cd0068c9c92b097cbe4142549d62cffd Mon Sep 17 00:00:00 2001 From: Ravi Vasanthm Date: Wed, 28 Aug 2019 11:41:12 -0700 Subject: [PATCH 081/214] Really mv models models_list --- config/transformer/models | 4 ---- 1 file changed, 4 deletions(-) delete mode 100644 config/transformer/models diff --git a/config/transformer/models b/config/transformer/models deleted file mode 100644 index bc192c902a..0000000000 --- a/config/transformer/models +++ /dev/null @@ -1,4 +0,0 @@ -#List yang models transformer need to load - -openconfig-acl.yang -openconfig-acl-annot.yang From 287aca1c787c25c1133c4f48245032a1369530dc Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Wed, 28 Aug 2019 13:57:23 -0700 Subject: [PATCH 082/214] Handle delete for top level oc acl xpath request --- src/translib/acl_app.go | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/translib/acl_app.go b/src/translib/acl_app.go index 917ef5b10c..e148523f0f 100644 --- a/src/translib/acl_app.go +++ b/src/translib/acl_app.go @@ -311,11 +311,21 @@ func handleAclEntry(d *db.DB, app *AclApp, opcode int) error { } func handleAcl(d *db.DB, app *AclApp, opcode int) error { var err error - //err = app.processCommonToplevelPath(d, acl, opcode, true) - err = handleAclSet(d, app, opcode) - if err == nil { - err = handleAclInterface(d, app, opcode) + var val db.Value + + // Delete all acl rules + err = handleAclDelete(d, app.ruleTs, "", val) + if err != nil { + log.Errorf("handleAcl: Failed to delete Acl Rule Table") + return err } + + // Delete all acl tables + err = handleAclDelete(d, app.aclTs, "", val) + if err != nil { + log.Errorf("handleAcl: Failed to delete Acl Table") + } + return err } From cdbc35bc73aaa02acb606f4dbfccc2487989d78b Mon Sep 17 00:00:00 2001 From: Ravi Vasanthm Date: Wed, 28 Aug 2019 14:23:10 -0700 Subject: [PATCH 083/214] Populate Yang model list based on models_list manifest file and sonic yang files in /usr/models/yang dir --- src/translib/transformer/transformer.go | 45 ++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/src/translib/transformer/transformer.go b/src/translib/transformer/transformer.go index 0d75c409ff..f10c007c17 100644 --- a/src/translib/transformer/transformer.go +++ b/src/translib/transformer/transformer.go @@ -6,6 +6,9 @@ import ( "github.com/openconfig/ygot/ygot" "os" "strings" + "bufio" + "path/filepath" + "io/ioutil" ) const YangPath = "/usr/models/yang/" // OpenConfig-*.yang and sonic yang models path @@ -27,8 +30,48 @@ func reportIfError(errs []error) { } } +func getOcModelsList () ([] string) { + var fileList [] string + file, err := os.Open(YangPath + "models_list") + if err != nil { + return fileList + } + defer file.Close() + scanner := bufio.NewScanner(file) + for scanner.Scan() { + fileEntry := scanner.Text() + if strings.HasPrefix(fileEntry, "#") != true { + _, err := os.Stat(YangPath + fileEntry) + if err != nil { + continue + } + fileList = append(fileList, fileEntry) + } + } + return fileList +} + +func getDefaultModelsList () ([] string) { + var files []string + fileInfo, err := ioutil.ReadDir(YangPath) + if err != nil { + return files + } + + for _, file := range fileInfo { + if strings.HasPrefix(file.Name(), "sonic-") && !strings.HasSuffix(file.Name(), "-dev.yang") && filepath.Ext(file.Name()) == ".yang" { + files = append(files, file.Name()) + } + } + return files +} + func init() { - yangFiles := []string{"sonic-acl.yang", "sonic-extensions.yang", "openconfig-acl-annot.yang", "openconfig-acl.yang"} + yangFiles := []string{} + ocList := getOcModelsList() + yangFiles = getDefaultModelsList() + yangFiles = append(yangFiles, ocList...) + fmt.Println("Yang model List:", yangFiles) loadYangModules(yangFiles...) } From 7b6c2f935809efba33f42baaf53f146ea793a92c Mon Sep 17 00:00:00 2001 From: amrutasali Date: Thu, 29 Aug 2019 05:39:18 +0000 Subject: [PATCH 084/214] Support to have common app registered as default/fallback app when no registration found from any other app in translib for a particular yang path --- src/translib/app_interface.go | 9 +++------ src/translib/common_app.go | 3 +-- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/translib/app_interface.go b/src/translib/app_interface.go index a64d568065..b04770c889 100644 --- a/src/translib/app_interface.go +++ b/src/translib/app_interface.go @@ -125,12 +125,9 @@ func getAppModuleInfo(path string) (*appInfo, error) { return app, err } - errStr := "Unsupported path=" + path - - err = errors.New(errStr) - log.Error(errStr) - - var app *appInfo + /* If no specific app registered fallback to default/common app */ + log.Infof("No app module registered for path %s hence fallback to default/common app", path) + app := appMap["*"] return app, err } diff --git a/src/translib/common_app.go b/src/translib/common_app.go index f998556814..4f43ca3dc0 100644 --- a/src/translib/common_app.go +++ b/src/translib/common_app.go @@ -28,8 +28,7 @@ var cmnAppInfo = appInfo{appType: reflect.TypeOf(CommonApp{}), func init() { - // @todo : Optimize to register supported paths/yang via common app and report error for unsupported - register_model_path := []string{"/sonic-"} // register yang model path(s) to be supported via common app + register_model_path := []string{"/sonic-", "*"} // register yang model path(s) to be supported via common app for _, mdl_pth := range register_model_path { err := register(mdl_pth, &cmnAppInfo) From d869ce14847b51d2629181c1e406d0e85cc8c76d Mon Sep 17 00:00:00 2001 From: Ravi Vasanthm Date: Thu, 29 Aug 2019 10:08:55 -0700 Subject: [PATCH 085/214] Addressed issue in passing data to field transformer method, addresed issue in populating db entries in transformer methods. --- src/translib/transformer/xfmr_acl.go | 40 +- src/translib/transformer/xlate_to_db.go | 667 ++++++++++++------------ 2 files changed, 374 insertions(+), 333 deletions(-) diff --git a/src/translib/transformer/xfmr_acl.go b/src/translib/transformer/xfmr_acl.go index 424fa70c04..38d586aee5 100644 --- a/src/translib/transformer/xfmr_acl.go +++ b/src/translib/transformer/xfmr_acl.go @@ -241,9 +241,9 @@ var DbToYang_acl_entry_key_xfmr KeyXfmrDbToYang = func (d *db.DB, opType int, en var YangToDb_acl_l2_ethertype_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, opType int, xpath string, ethertype interface {}) (map[string]string, error) { res_map := make(map[string]string) var err error - log.Info("YangToDb_acl_l2_ethertype_xfmr :", ygRoot, xpath) - ethertypeType := reflect.TypeOf(ethertype) + ethertypeType := reflect.TypeOf(ethertype).Elem() + log.Info("YangToDb_acl_ip_protocol_xfmr: ", ygRoot, " Xpath: ", xpath, " ethertypeType: ", ethertypeType) var b bytes.Buffer switch ethertypeType { case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_L2_Config_Ethertype_Union_E_OpenconfigPacketMatchTypes_ETHERTYPE{}): @@ -296,9 +296,9 @@ var DbToYang_acl_l2_ethertype_xfmr FieldXfmrDbtoYang = func (d *db.DB, opType in var YangToDb_acl_ip_protocol_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, opType int, xpath string, protocol interface {}) (map[string]string, error) { res_map := make(map[string]string) var err error - log.Info("YangToDb_acl_ip_protocol_xfmr: ", ygRoot, xpath) - protocolType := reflect.TypeOf(protocol) + protocolType := reflect.TypeOf(protocol).Elem() + log.Info("YangToDb_acl_ip_protocol_xfmr: ", ygRoot, " Xpath: ", xpath, " protocolType: ", protocolType) switch (protocolType) { case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Ipv4_Config_Protocol_Union_E_OpenconfigPacketMatchTypes_IP_PROTOCOL{}): v := (protocol).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Ipv4_Config_Protocol_Union_E_OpenconfigPacketMatchTypes_IP_PROTOCOL) @@ -347,8 +347,8 @@ var DbToYang_acl_ip_protocol_xfmr FieldXfmrDbtoYang = func (d *db.DB, opType int var YangToDb_acl_source_port_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, opType int, xpath string, value interface {}) (map[string]string, error) { res_map := make(map[string]string) var err error; - log.Info("YangToDb_acl_source_port_xfmr: ", ygRoot, xpath) - sourceportType := reflect.TypeOf(value) + sourceportType := reflect.TypeOf(value).Elem() + log.Info("YangToDb_acl_ip_protocol_xfmr: ", ygRoot, " Xpath: ", xpath, " sourceportType: ", sourceportType) switch sourceportType { case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort_Union_E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort{}): v := (value).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort_Union_E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort) @@ -449,8 +449,8 @@ var DbToYang_acl_source_port_xfmr FieldXfmrDbtoYang = func (d *db.DB, opType int var YangToDb_acl_destination_port_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, opType int, xpath string, value interface{}) (map[string]string, error) { res_map := make(map[string]string) var err error; - log.Info("YangToDb_acl_destination_port_xfmr: ", ygRoot, xpath) - destportType := reflect.TypeOf(value) + destportType := reflect.TypeOf(value).Elem() + log.Info("YangToDb_acl_ip_protocol_xfmr: ", ygRoot, " Xpath: ", xpath, " destportType: ", destportType) switch destportType { case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort_Union_E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort{}): v := (value).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort_Union_E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort) @@ -593,8 +593,13 @@ func convertDBAclRulesToInternal(dbCl *db.DB, aclName string, seqId int64, ruleK ferr = err return } - if ruleTableMap[aclName] == nil { + if len(ruleTableMap) == 0 { + ruleTableMap = make(map[string]map[string]db.Value) + } + _, ok := ruleTableMap[aclName] + if !ok { ruleTableMap[aclName] = make(map[string]db.Value) + ruleTableMap[aclName][ruleName] = db.Value{Field: make(map[string]string)} } ruleTableMap[aclName][ruleName] = ruleData } @@ -623,8 +628,23 @@ func convertDBAclToInternal(dbCl *db.DB, aclkey db.Key) (aclTableMap map[string] return } if entry.IsPopulated() { + log.Info("convertDBAclToInternal : ", aclkey, aclTableMap, " ", aclTableMap[aclkey.Get(0)], " ", entry) + _, ok := aclTableMap[aclkey.Get(0)] + if !ok { + if len(aclTableMap) == 0 { + aclTableMap = make(map[string]db.Value) + } + aclTableMap[aclkey.Get(0)] = db.Value{Field: make(map[string]string)} + } + aclTableMap[aclkey.Get(0)] = entry - ruleTableMap[aclkey.Get(0)] = make(map[string]db.Value) + if len(ruleTableMap) == 0 { + ruleTableMap = make(map[string]map[string]db.Value) + } + _, rok := ruleTableMap[aclkey.Get(0)] + if !rok { + ruleTableMap[aclkey.Get(0)] = make(map[string]db.Value) + } ruleTableMap, ferr = convertDBAclRulesToInternal(dbCl, aclkey.Get(0), -1, db.Key{}) if err != nil { ferr = err diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index ae42949d22..107fb6035c 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -1,16 +1,18 @@ package transformer import ( - "errors" - "fmt" - "github.com/openconfig/ygot/ygot" - "os" - "reflect" - "regexp" - "strings" - "translib/db" - - log "github.com/golang/glog" + "errors" + "fmt" + "github.com/openconfig/ygot/ygot" + "os" + "reflect" + "regexp" + "strings" + "translib/db" + "translib/ocbinds" + "github.com/openconfig/ygot/ytypes" + + log "github.com/golang/glog" ) const SONIC_TABLE_INDEX = 2 @@ -18,334 +20,353 @@ const SONIC_FIELD_INDEX = 3 /* Fill redis-db map with field & value info */ func dataToDBMapAdd(tableName string, dbKey string, result map[string]map[string]db.Value, field string, value string) { - _, ok := result[tableName] - if !ok { - result[tableName] = make(map[string]db.Value) - } - - _, ok = result[tableName][dbKey] - if !ok { - result[tableName][dbKey] = db.Value{Field: make(map[string]string)} - } - - result[tableName][dbKey].Field[field] = value - return + _, ok := result[tableName] + if !ok { + result[tableName] = make(map[string]db.Value) + } + + _, ok = result[tableName][dbKey] + if !ok { + result[tableName][dbKey] = db.Value{Field: make(map[string]string)} + } + + result[tableName][dbKey].Field[field] = value + return } /* Fill the redis-db map with data */ func mapFillData(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, dbKey string, result map[string]map[string]db.Value, xpathPrefix string, name string, value interface{}) error { - xpath := xpathPrefix + "/" + name - xpathInfo := xSpecMap[xpath] - log.Info("name: \"%v\", xpathPrefix(\"%v\").", name, xpathPrefix) - - if xpathInfo == nil { - log.Errorf("Yang path(\"%v\") not found.", xpath) - return errors.New("Invalid URI") - } - - if xpathInfo.tableName == nil { - log.Errorf("Table for yang-path(\"%v\") not found.", xpath) - return errors.New("Invalid table name") - } - - if len(dbKey) == 0 { - log.Errorf("Table key for yang path(\"%v\") not found.", xpath) - return errors.New("Invalid table key") - } - - if len(xpathInfo.xfmrFunc) > 0 { + xpath := xpathPrefix + "/" + name + xpathInfo := xSpecMap[xpath] + log.Info("name: \"%v\", xpathPrefix(\"%v\").", name, xpathPrefix) + + if xpathInfo == nil { + log.Errorf("Yang path(\"%v\") not found.", xpath) + return errors.New("Invalid URI") + } + + if xpathInfo.tableName == nil { + log.Errorf("Table for yang-path(\"%v\") not found.", xpath) + return errors.New("Invalid table name") + } + + if len(dbKey) == 0 { + log.Errorf("Table key for yang path(\"%v\") not found.", xpath) + return errors.New("Invalid table key") + } + + if len(xpathInfo.xfmrFunc) > 0 { uri = uri + "/" + name - /* field transformer present */ - log.Info("Transformer function(\"%v\") invoked for yang path(\"%v\").", xpathInfo.xfmrFunc, xpath) - ret, err := XlateFuncCall(yangToDbXfmrFunc(xSpecMap[xpath].xfmrFunc), d, ygRoot, oper, uri, value) - if err != nil { - return err - } - retData := ret[0].Interface().(map[string]string) - log.Info("Transformer function \"%v\" for \"%v\" returned(%v).", xpathInfo.xfmrFunc, xpath, retData) - for f, v := range retData { - dataToDBMapAdd(*xpathInfo.tableName, dbKey, result, f, v) - } - return nil - } - - if len(xpathInfo.fieldName) == 0 { - log.Info("Field for yang-path(\"%v\") not found in DB.", xpath) - return errors.New("Invalid field name") - } - fieldName := xpathInfo.fieldName + + /* field transformer present */ + log.Info("Transformer function(\"%v\") invoked for yang path(\"%v\").", xpathInfo.xfmrFunc, xpath) + path, _ := ygot.StringToPath(uri, ygot.StructuredPath, ygot.StringSlicePath) + for _, p := range path.Elem { + pathSlice := strings.Split(p.Name, ":") + p.Name = pathSlice[len(pathSlice)-1] + if len(p.Key) > 0 { + for ekey, ent := range p.Key { + eslice := strings.Split(ent, ":") + p.Key[ekey] = eslice[len(eslice)-1] + } + } + } + ocbSch, _ := ocbinds.Schema() + schRoot := ocbSch.RootSchema() + node, nErr := ytypes.GetNode(schRoot, (*ygRoot).(*ocbinds.Device), path) + log.Info("GetNode data: ", node[0].Data, " nErr :", nErr) + if nErr != nil { + return nErr + } + ret, err := XlateFuncCall(yangToDbXfmrFunc(xSpecMap[xpath].xfmrFunc), d, ygRoot, oper, uri, node[0].Data) + if err != nil { + return err + } + retData := ret[0].Interface().(map[string]string) + log.Info("Transformer function :", xpathInfo.xfmrFunc, " Xpath: ", xpath, " retData: ", retData) + for f, v := range retData { + dataToDBMapAdd(*xpathInfo.tableName, dbKey, result, f, v) + } + return nil + } + + if len(xpathInfo.fieldName) == 0 { + log.Info("Field for yang-path(\"%v\") not found in DB.", xpath) + return errors.New("Invalid field name") + } + fieldName := xpathInfo.fieldName valueStr := fmt.Sprintf("%v", value) - if strings.Contains(valueStr, ":") { - valueStr = strings.Split(valueStr, ":")[1] - } - - dataToDBMapAdd(*xpathInfo.tableName, dbKey, result, fieldName, valueStr) - log.Info("TblName: \"%v\", key: \"%v\", field: \"%v\", valueStr: \"%v\".", - *xpathInfo.tableName, dbKey, fieldName, valueStr) - return nil + if strings.Contains(valueStr, ":") { + valueStr = strings.Split(valueStr, ":")[1] + } + + dataToDBMapAdd(*xpathInfo.tableName, dbKey, result, fieldName, valueStr) + log.Info("TblName: \"%v\", key: \"%v\", field: \"%v\", valueStr: \"%v\".", + *xpathInfo.tableName, dbKey, fieldName, valueStr) + return nil } func cvlYangReqToDbMapCreate(jsonData interface{}, result map[string]map[string]db.Value) error { - if reflect.ValueOf(jsonData).Kind() == reflect.Map { - data := reflect.ValueOf(jsonData) - for _, key := range data.MapKeys() { - _, ok := xDbSpecMap[key.String()] - if ok { - directDbMapData(key.String(), data.MapIndex(key).Interface(), result) - } else { - cvlYangReqToDbMapCreate(data.MapIndex(key).Interface(), result) - } - } - } - return nil + if reflect.ValueOf(jsonData).Kind() == reflect.Map { + data := reflect.ValueOf(jsonData) + for _, key := range data.MapKeys() { + _, ok := xDbSpecMap[key.String()] + if ok { + directDbMapData(key.String(), data.MapIndex(key).Interface(), result) + } else { + cvlYangReqToDbMapCreate(data.MapIndex(key).Interface(), result) + } + } + } + return nil } func directDbMapData(tableName string, jsonData interface{}, result map[string]map[string]db.Value) bool { - _, ok := xDbSpecMap[tableName] - - if ok && xDbSpecMap[tableName].dbEntry != nil { - dbSpecData := xDbSpecMap[tableName].dbEntry - tblKeyName := strings.Split(dbSpecData.Key, " ") - data := reflect.ValueOf(jsonData) - result[tableName] = make(map[string]db.Value) - - for idx := 0; idx < data.Len(); idx++ { - keyName := "" - d := data.Index(idx).Interface().(map[string]interface{}) - for i, k := range tblKeyName { - if i > 0 { - keyName += "|" - } - keyName += fmt.Sprintf("%v", d[k]) - delete(d, k) - } - - result[tableName][keyName] = db.Value{Field: make(map[string]string)} - for field, value := range d { - fieldXpath := tableName + "/" + field - if _, fieldOk := xDbSpecMap[fieldXpath]; (fieldOk && (xDbSpecMap[fieldXpath].dbEntry != nil)) { - log.Info("Found non-nil yang entry in xDbSpecMap for field xpath = ", fieldXpath) - if xDbSpecMap[fieldXpath].dbEntry.IsLeafList() { - log.Info("Yang type is Leaflist for field = ", field) - field += "@" - fieldDt := reflect.ValueOf(value) - fieldValue := "" - for fidx := 0; fidx < fieldDt.Len(); fidx++ { - if fidx > 0 { - fieldValue += "," - } - fVal := fmt.Sprintf("%v", fieldDt.Index(fidx).Interface()) - fieldValue = fieldValue + fVal - } - result[tableName][keyName].Field[field] = fieldValue - continue - } - } else { - // should ideally never happen , just adding for safety - log.Info("Did not find entry in xDbSpecMap for field xpath = ", fieldXpath) - } - result[tableName][keyName].Field[field] = fmt.Sprintf("%v", value) - } - } - return true - } - return false + _, ok := xDbSpecMap[tableName] + + if ok && xDbSpecMap[tableName].dbEntry != nil { + dbSpecData := xDbSpecMap[tableName].dbEntry + tblKeyName := strings.Split(dbSpecData.Key, " ") + data := reflect.ValueOf(jsonData) + result[tableName] = make(map[string]db.Value) + + for idx := 0; idx < data.Len(); idx++ { + keyName := "" + d := data.Index(idx).Interface().(map[string]interface{}) + for i, k := range tblKeyName { + if i > 0 { + keyName += "|" + } + keyName += fmt.Sprintf("%v", d[k]) + delete(d, k) + } + + result[tableName][keyName] = db.Value{Field: make(map[string]string)} + for field, value := range d { + fieldXpath := tableName + "/" + field + if _, fieldOk := xDbSpecMap[fieldXpath]; (fieldOk && (xDbSpecMap[fieldXpath].dbEntry != nil)) { + log.Info("Found non-nil yang entry in xDbSpecMap for field xpath = ", fieldXpath) + if xDbSpecMap[fieldXpath].dbEntry.IsLeafList() { + log.Info("Yang type is Leaflist for field = ", field) + field += "@" + fieldDt := reflect.ValueOf(value) + fieldValue := "" + for fidx := 0; fidx < fieldDt.Len(); fidx++ { + if fidx > 0 { + fieldValue += "," + } + fVal := fmt.Sprintf("%v", fieldDt.Index(fidx).Interface()) + fieldValue = fieldValue + fVal + } + result[tableName][keyName].Field[field] = fieldValue + continue + } + } else { + // should ideally never happen , just adding for safety + log.Info("Did not find entry in xDbSpecMap for field xpath = ", fieldXpath) + } + result[tableName][keyName].Field[field] = fmt.Sprintf("%v", value) + } + } + return true + } + return false } /* Get the db table, key and field name for the incoming delete request */ func dbMapDelete(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string, jsonData interface{}, result map[string]map[string]db.Value) error { - var err error - if isCvlYang(path) { - xpathPrefix, keyName, tableName := sonicXpathKeyExtract(path) - log.Info("Delete req: path(\"%v\"), key(\"%v\"), xpathPrefix(\"%v\"), tableName(\"%v\").", path, keyName, xpathPrefix, tableName) - err = cvlYangReqToDbMapDelete(xpathPrefix, tableName, keyName, result) - } else { - xpathPrefix, keyName, tableName := xpathKeyExtract(d, ygRoot, oper, path) - log.Info("Delete req: path(\"%v\"), key(\"%v\"), xpathPrefix(\"%v\"), tableName(\"%v\").", path, keyName, xpathPrefix, tableName) - spec, ok := xSpecMap[xpathPrefix] - if ok && spec.tableName != nil { - result[*spec.tableName] = make(map[string]db.Value) - if len(keyName) > 0 { - result[*spec.tableName][keyName] = db.Value{Field: make(map[string]string)} - if spec.yangEntry != nil && spec.yangEntry.Node.Statement().Keyword == "leaf" { - result[*spec.tableName][keyName].Field[spec.fieldName] = "" - } - } - } - } - log.Info("Delete req: path(\"%v\") result(\"%v\").", path, result) - return err + var err error + if isCvlYang(path) { + xpathPrefix, keyName, tableName := sonicXpathKeyExtract(path) + log.Info("Delete req: path(\"%v\"), key(\"%v\"), xpathPrefix(\"%v\"), tableName(\"%v\").", path, keyName, xpathPrefix, tableName) + err = cvlYangReqToDbMapDelete(xpathPrefix, tableName, keyName, result) + } else { + xpathPrefix, keyName, tableName := xpathKeyExtract(d, ygRoot, oper, path) + log.Info("Delete req: path(\"%v\"), key(\"%v\"), xpathPrefix(\"%v\"), tableName(\"%v\").", path, keyName, xpathPrefix, tableName) + spec, ok := xSpecMap[xpathPrefix] + if ok && spec.tableName != nil { + result[*spec.tableName] = make(map[string]db.Value) + if len(keyName) > 0 { + result[*spec.tableName][keyName] = db.Value{Field: make(map[string]string)} + if spec.yangEntry != nil && spec.yangEntry.Node.Statement().Keyword == "leaf" { + result[*spec.tableName][keyName].Field[spec.fieldName] = "" + } + } + } + } + log.Info("Delete req: path(\"%v\") result(\"%v\").", path, result) + return err } func cvlYangReqToDbMapDelete(xpathPrefix string, tableName string, keyName string, result map[string]map[string]db.Value) error { - if (tableName != "") { - // Specific table entry case - result[tableName] = make(map[string]db.Value) - if (keyName != "") { - // Specific key case - var dbVal db.Value - tokens:= strings.Split(xpathPrefix, "/") - // Format /module:container/tableName[key]/fieldName - if tokens[len(tokens)-2] == tableName { - // Specific leaf case - fieldName := tokens[len(tokens)-1] - dbVal.Field = make(map[string]string) - dbVal.Field[fieldName] = "" - } - result[tableName][keyName] = dbVal - } else { - // Get all keys - } - } else { - // Get all table entries - // If table name not available in xpath get top container name - tokens:= strings.Split(xpathPrefix, ":") - container := "/" + tokens[len(tokens)-1] - if xDbSpecMap[container] != nil { - dbInfo := xDbSpecMap[container] - if dbInfo.fieldType == "container" { - for dir, _ := range dbInfo.dbEntry.Dir { - result[dir] = make(map[string]db.Value) - } - } - } - } - return nil + if (tableName != "") { + // Specific table entry case + result[tableName] = make(map[string]db.Value) + if (keyName != "") { + // Specific key case + var dbVal db.Value + tokens:= strings.Split(xpathPrefix, "/") + // Format /module:container/tableName[key]/fieldName + if tokens[len(tokens)-2] == tableName { + // Specific leaf case + fieldName := tokens[len(tokens)-1] + dbVal.Field = make(map[string]string) + dbVal.Field[fieldName] = "" + } + result[tableName][keyName] = dbVal + } else { + // Get all keys + } + } else { + // Get all table entries + // If table name not available in xpath get top container name + tokens:= strings.Split(xpathPrefix, ":") + container := "/" + tokens[len(tokens)-1] + if xDbSpecMap[container] != nil { + dbInfo := xDbSpecMap[container] + if dbInfo.fieldType == "container" { + for dir, _ := range dbInfo.dbEntry.Dir { + result[dir] = make(map[string]db.Value) + } + } + } + } + return nil } /* Get the data from incoming update/replace request, create map and fill with dbValue(ie. field:value - to write into redis-db */ +to write into redis-db */ func dbMapUpdate(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string, jsonData interface{}, result map[string]map[string]db.Value) error { - log.Info("Update/replace req: path(\"%v\").", path) - dbMapCreate(d, ygRoot, oper, path, jsonData, result) - log.Info("Update/replace req: path(\"%v\") result(\"%v\").", path, result) - printDbData(result, "/tmp/yangToDbDataUpRe.txt") - return nil + log.Info("Update/replace req: path(\"%v\").", path) + dbMapCreate(d, ygRoot, oper, path, jsonData, result) + log.Info("Update/replace req: path(\"%v\") result(\"%v\").", path, result) + printDbData(result, "/tmp/yangToDbDataUpRe.txt") + return nil } /* Get the data from incoming create request, create map and fill with dbValue(ie. field:value - to write into redis-db */ +to write into redis-db */ func dbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string, jsonData interface{}, result map[string]map[string]db.Value) error { - root := xpathRootNameGet(path) - if isCvlYang(path) { - cvlYangReqToDbMapCreate(jsonData, result) - } else { - yangReqToDbMapCreate(d, ygRoot, oper, root, "", "", jsonData, result) - } - printDbData(result, "/tmp/yangToDbDataCreate.txt") - return nil + root := xpathRootNameGet(path) + if isCvlYang(path) { + cvlYangReqToDbMapCreate(jsonData, result) + } else { + yangReqToDbMapCreate(d, ygRoot, oper, root, "", "", jsonData, result) + } + printDbData(result, "/tmp/yangToDbDataCreate.txt") + return nil } func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, xpathPrefix string, keyName string, jsonData interface{}, result map[string]map[string]db.Value) error { - log.Info("key(\"%v\"), xpathPrefix(\"%v\").", keyName, xpathPrefix) - - if reflect.ValueOf(jsonData).Kind() == reflect.Slice { - log.Info("slice data: key(\"%v\"), xpathPrefix(\"%v\").", keyName, xpathPrefix) - jData := reflect.ValueOf(jsonData) - dataMap := make([]interface{}, jData.Len()) - for idx := 0; idx < jData.Len(); idx++ { - dataMap[idx] = jData.Index(idx).Interface() - } - for _, data := range dataMap { - curKey := "" - curUri := uriWithKeyCreate(uri, xpathPrefix, data) - if len(xSpecMap[xpathPrefix].xfmrKey) > 0 { - /* key transformer present */ - ret, err := XlateFuncCall(yangToDbXfmrFunc(xSpecMap[xpathPrefix].xfmrKey), d, ygRoot, oper, curUri) - if err != nil { - return err - } - curKey = ret[0].Interface().(string) - } else { - curKey = keyCreate(keyName, xpathPrefix, data) - } - yangReqToDbMapCreate(d, ygRoot, oper, curUri, xpathPrefix, curKey, data, result) - } - } else { - if reflect.ValueOf(jsonData).Kind() == reflect.Map { - jData := reflect.ValueOf(jsonData) - for _, key := range jData.MapKeys() { - typeOfValue := reflect.TypeOf(jData.MapIndex(key).Interface()).Kind() - - if typeOfValue == reflect.Map || typeOfValue == reflect.Slice { - log.Info("slice/map data: key(\"%v\"), xpathPrefix(\"%v\").", keyName, xpathPrefix) + log.Info("key(\"%v\"), xpathPrefix(\"%v\").", keyName, xpathPrefix) + + if reflect.ValueOf(jsonData).Kind() == reflect.Slice { + log.Info("slice data: key(\"%v\"), xpathPrefix(\"%v\").", keyName, xpathPrefix) + jData := reflect.ValueOf(jsonData) + dataMap := make([]interface{}, jData.Len()) + for idx := 0; idx < jData.Len(); idx++ { + dataMap[idx] = jData.Index(idx).Interface() + } + for _, data := range dataMap { + curKey := "" + curUri := uriWithKeyCreate(uri, xpathPrefix, data) + if len(xSpecMap[xpathPrefix].xfmrKey) > 0 { + /* key transformer present */ + ret, err := XlateFuncCall(yangToDbXfmrFunc(xSpecMap[xpathPrefix].xfmrKey), d, ygRoot, oper, curUri) + if err != nil { + return err + } + curKey = ret[0].Interface().(string) + } else { + curKey = keyCreate(keyName, xpathPrefix, data) + } + yangReqToDbMapCreate(d, ygRoot, oper, curUri, xpathPrefix, curKey, data, result) + } + } else { + if reflect.ValueOf(jsonData).Kind() == reflect.Map { + jData := reflect.ValueOf(jsonData) + for _, key := range jData.MapKeys() { + typeOfValue := reflect.TypeOf(jData.MapIndex(key).Interface()).Kind() + + if typeOfValue == reflect.Map || typeOfValue == reflect.Slice { + log.Info("slice/map data: key(\"%v\"), xpathPrefix(\"%v\").", keyName, xpathPrefix) xpath := uri curUri := uri pathAttr := key.String() if len(xpathPrefix) > 0 { - if strings.Contains(pathAttr, ":") { - pathAttr = strings.Split(pathAttr, ":")[1] - } - xpath = xpathPrefix + "/" + pathAttr - curUri = uri + "/" + pathAttr + if strings.Contains(pathAttr, ":") { + pathAttr = strings.Split(pathAttr, ":")[1] + } + xpath = xpathPrefix + "/" + pathAttr + curUri = uri + "/" + pathAttr } - if xSpecMap[xpath] != nil && len(xSpecMap[xpath].xfmrFunc) > 0 { - /* subtree transformer present */ - ret, err := XlateFuncCall(yangToDbXfmrFunc(xSpecMap[xpath].xfmrFunc), d, ygRoot, oper, curUri) - if err != nil { - return nil - } - mapCopy(result, ret[0].Interface().(map[string]map[string]db.Value)) - } else { - yangReqToDbMapCreate(d, ygRoot, oper, curUri, xpath, keyName, jData.MapIndex(key).Interface(), result) - } - } else { - pathAttr := key.String() - if strings.Contains(pathAttr, ":") { - pathAttr = strings.Split(pathAttr, ":")[1] - } - value := jData.MapIndex(key).Interface() - log.Info("data field: key(\"%v\"), value(\"%v\").", key, value) - err := mapFillData(d, ygRoot, oper, uri, keyName, result, xpathPrefix, - pathAttr, value) - if err != nil { - log.Errorf("Failed constructing data for db write: key(\"%v\"), value(\"%v\"), path(\"%v\").", - pathAttr, value, xpathPrefix) - } - } - } - } - } - return nil + if xSpecMap[xpath] != nil && len(xSpecMap[xpath].xfmrFunc) > 0 { + /* subtree transformer present */ + ret, err := XlateFuncCall(yangToDbXfmrFunc(xSpecMap[xpath].xfmrFunc), d, ygRoot, oper, curUri) + if err != nil { + return nil + } + mapCopy(result, ret[0].Interface().(map[string]map[string]db.Value)) + } else { + yangReqToDbMapCreate(d, ygRoot, oper, curUri, xpath, keyName, jData.MapIndex(key).Interface(), result) + } + } else { + pathAttr := key.String() + if strings.Contains(pathAttr, ":") { + pathAttr = strings.Split(pathAttr, ":")[1] + } + value := jData.MapIndex(key).Interface() + log.Info("data field: key(\"%v\"), value(\"%v\").", key, value) + err := mapFillData(d, ygRoot, oper, uri, keyName, result, xpathPrefix, + pathAttr, value) + if err != nil { + log.Errorf("Failed constructing data for db write: key(\"%v\"), value(\"%v\"), path(\"%v\").", + pathAttr, value, xpathPrefix) + } + } + } + } + } + return nil } func sonicXpathKeyExtract(path string) (string, string, string) { - xpath, keyStr, tableName := "", "", "" - var err error - xpath, err = RemoveXPATHPredicates(path) - if err != nil { - return xpath, keyStr, tableName - } - rgp := regexp.MustCompile(`\[([^\[\]]*)\]`) - pathsubStr := strings.Split(path , "/") - if len(pathsubStr) > SONIC_TABLE_INDEX { - tableName = strings.Split(pathsubStr[SONIC_TABLE_INDEX], "[")[0] - for i, kname := range rgp.FindAllString(path, -1) { - if i > 0 { keyStr += "|" } - val := strings.Split(kname, "=")[1] - keyStr += strings.TrimRight(val, "]") - } - } - return xpath, keyStr, tableName + xpath, keyStr, tableName := "", "", "" + var err error + xpath, err = RemoveXPATHPredicates(path) + if err != nil { + return xpath, keyStr, tableName + } + rgp := regexp.MustCompile(`\[([^\[\]]*)\]`) + pathsubStr := strings.Split(path , "/") + if len(pathsubStr) > SONIC_TABLE_INDEX { + tableName = strings.Split(pathsubStr[SONIC_TABLE_INDEX], "[")[0] + for i, kname := range rgp.FindAllString(path, -1) { + if i > 0 { keyStr += "|" } + val := strings.Split(kname, "=")[1] + keyStr += strings.TrimRight(val, "]") + } + } + return xpath, keyStr, tableName } /* Extract key vars, create db key and xpath */ func xpathKeyExtract(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string) (string, string, string) { - keyStr := "" - tableName := "" - rgp := regexp.MustCompile(`\[([^\[\]]*)\]`) - curPathWithKey := "" + keyStr := "" + tableName := "" + rgp := regexp.MustCompile(`\[([^\[\]]*)\]`) + curPathWithKey := "" - for _, k := range strings.Split(path, "/") { - xpath := k + for _, k := range strings.Split(path, "/") { + xpath := k curPathWithKey += k - if strings.Contains(k, "[") { - if len(keyStr) > 0 { - keyStr += "|" - } + if strings.Contains(k, "[") { + if len(keyStr) > 0 { + keyStr += "|" + } yangXpath, _ := RemoveXPATHPredicates(curPathWithKey) - xpath = strings.Split(k, "[")[0] + xpath = strings.Split(k, "[")[0] if len(xSpecMap[yangXpath].xfmrKey) > 0 { ret, err := XlateFuncCall(yangToDbXfmrFunc(xSpecMap[yangXpath].xfmrKey), d, ygRoot, oper, curPathWithKey) if err != nil { @@ -353,43 +374,43 @@ func xpathKeyExtract(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string) (st } keyStr = ret[0].Interface().(string) } else { - var keyl []string - for _, kname := range rgp.FindAllString(k, -1) { - keyl = append(keyl, strings.TrimRight(strings.TrimLeft(kname, "["), "]")) - } - keyStr += keyFromXpathCreate(keyl) + var keyl []string + for _, kname := range rgp.FindAllString(k, -1) { + keyl = append(keyl, strings.TrimRight(strings.TrimLeft(kname, "["), "]")) + } + keyStr += keyFromXpathCreate(keyl) + } + if isCvlYang(path) { + //Format- /module:container/table[key]/field + // table name extracted from the string token having key entry + tableName = xpath } - if isCvlYang(path) { - //Format- /module:container/table[key]/field - // table name extracted from the string token having key entry - tableName = xpath - } - } + } curPathWithKey += "/" - } + } pfxPath, _ := RemoveXPATHPredicates(path) - return pfxPath, keyStr, tableName + return pfxPath, keyStr, tableName } /* Debug function to print the map data into file */ func printDbData(db map[string]map[string]db.Value, fileName string) { - fp, err := os.Create(fileName) - if err != nil { - return - } - defer fp.Close() - - for k, v := range db { - fmt.Fprintf(fp, "-----------------------------------------------------------------\r\n") - fmt.Fprintf(fp, "table name : %v\r\n", k) - for ik, iv := range v { - fmt.Fprintf(fp, " key : %v\r\n", ik) - for k, d := range iv.Field { - fmt.Fprintf(fp, " %v :%v\r\n", k, d) - } - } - } - fmt.Fprintf(fp, "-----------------------------------------------------------------\r\n") - return + fp, err := os.Create(fileName) + if err != nil { + return + } + defer fp.Close() + + for k, v := range db { + fmt.Fprintf(fp, "-----------------------------------------------------------------\r\n") + fmt.Fprintf(fp, "table name : %v\r\n", k) + for ik, iv := range v { + fmt.Fprintf(fp, " key : %v\r\n", ik) + for k, d := range iv.Field { + fmt.Fprintf(fp, " %v :%v\r\n", k, d) + } + } + } + fmt.Fprintf(fp, "-----------------------------------------------------------------\r\n") + return } From 2e68e2f0780495413e78bb896d8a4b44e8e19ed8 Mon Sep 17 00:00:00 2001 From: amrutasali Date: Thu, 29 Aug 2019 23:41:01 +0000 Subject: [PATCH 086/214] Modify list of tables to watch to be the list of all tables in a module/yang corresponding to incoming request, instead of just the subset of tables derived from incoming request. --- src/translib/common_app.go | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/translib/common_app.go b/src/translib/common_app.go index 4f43ca3dc0..23e41b199d 100644 --- a/src/translib/common_app.go +++ b/src/translib/common_app.go @@ -199,6 +199,14 @@ func (app *CommonApp) translateCRUDCommon(d *db.DB, opcode int) ([]db.WatchKeys, log.Info("GetOrdDBTblList() returned ordered table list = ", OrdTblList) app.cmnAppOrdTbllist = OrdTblList + /* enhance this to handle dependent tables - need CVL to provide list of such tables for a given request */ + for _, tblnm := range OrdTblList { // OrdTblList already has has all tables corresponding to a module + tblsToWatch = append(tblsToWatch, &db.TableSpec{Name: tblnm}) + } + log.Info("Tables to watch", tblsToWatch) + + cmnAppInfo.tablesToWatch = tblsToWatch + // translate yang to db result, err := transformer.XlateToDb(app.pathInfo.Path, opcode, d, (*app).ygotRoot, (*app).ygotTarget) fmt.Println(result) @@ -215,17 +223,6 @@ func (app *CommonApp) translateCRUDCommon(d *db.DB, opcode int) ([]db.WatchKeys, } app.cmnAppTableMap = result - /* enhance this to handle dependent tables - need CVL to provide list of such tables for a given request */ - for tblnm, _ := range app.cmnAppTableMap { - log.Error("Table name ", tblnm) - tblsToWatch = append(tblsToWatch, &db.TableSpec{Name: tblnm}) - } - log.Info("Tables to watch", tblsToWatch) - - cmnAppInfo.tablesToWatch = tblsToWatch - /* In case all related tables need to be watched - cmnAppInfo.tablesToWatch = OrdTblList */ - keys, err = app.generateDbWatchKeys(d, false) return keys, err From e104fdc3f5ee15f389992655326d8dffb3898342 Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Fri, 30 Aug 2019 03:13:35 -0700 Subject: [PATCH 087/214] Update DB ordered map for oc yang --- src/translib/transformer/xlate.go | 102 ++++++++++++------------ src/translib/transformer/xlate_to_db.go | 3 + src/translib/transformer/xspec.go | 45 ++++++++++- 3 files changed, 95 insertions(+), 55 deletions(-) diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index 28b390064d..f64774150b 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -26,7 +26,7 @@ const ( type KeySpec struct { Ts db.TableSpec Key db.Key - Child *KeySpec + Child []KeySpec } var XlateFuncs = make(map[string]reflect.Value) @@ -85,8 +85,10 @@ func TraverseDb(d *db.DB, spec KeySpec, result *map[string]map[string]db.Value, (*result)[spec.Ts.Name][strings.Join(spec.Key.Comp, "|")] = data } - if spec.Child != nil { - err = TraverseDb(d, *spec.Child, result, &spec.Key) + if len(spec.Child) > 0 { + for _, ch := range spec.Child { + err = TraverseDb(d, ch, result, &spec.Key) + } } } else { // TODO - GetEntry suuport with regex patten, 'abc*' for optimization @@ -121,32 +123,56 @@ func XlateUriToKeySpec(path string, uri *ygot.GoStruct, t *interface{}) (*map[db retdbFormat = fillCvlKeySpec(yangXpath, tableName, keyStr) } else { /* Extract the xpath and key from input xpath */ - yangXpath, keyStr, _ := xpathKeyExtract(nil, uri, 0, path) - if xSpecMap == nil { - return &result, err - } - _, ok := xSpecMap[yangXpath] - if ok { - xpathInfo := xSpecMap[yangXpath] - if xpathInfo.tableName != nil { - dbFormat := KeySpec{} - fillKeySpec(yangXpath, keyStr, &dbFormat) - retdbFormat = append(retdbFormat, dbFormat) - } else { - for _, child := range xpathInfo.childTable { - dbFormat := KeySpec{} - var childXpath = xDbSpecMap[child].yangXpath[0] - fillKeySpec(childXpath, "", &dbFormat) - retdbFormat = append(retdbFormat, dbFormat) - } - } - } + yangXpath, keyStr, _ := xpathKeyExtract(nil, uri, 0, path) + retdbFormat = FillKeySpecs(yangXpath, keyStr, &retdbFormat) } result[db.ConfigDB] = retdbFormat return &result, err } +func FillKeySpecs(yangXpath string , keyStr string, retdbFormat *[]KeySpec) ([]KeySpec){ + if xSpecMap == nil { + return *retdbFormat + } + _, ok := xSpecMap[yangXpath] + if ok { + xpathInfo := xSpecMap[yangXpath] + if xpathInfo.tableName != nil { + dbFormat := KeySpec{} + dbFormat.Ts.Name = *xpathInfo.tableName + if keyStr != "" { + dbFormat.Key.Comp = append(dbFormat.Key.Comp, keyStr) + } + for _, child := range xpathInfo.childTable { + if xDbSpecMap != nil { + chlen := len(xDbSpecMap[child].yangXpath) + if chlen > 0 { + children := make([]KeySpec, 0) + for _, childXpath := range xDbSpecMap[child].yangXpath { + children = FillKeySpecs(childXpath, "", &children) + dbFormat.Child = append(dbFormat.Child, children...) + } + } + } + } + *retdbFormat = append(*retdbFormat, dbFormat) + } else { + for _, child := range xpathInfo.childTable { + if xDbSpecMap != nil { + chlen := len(xDbSpecMap[child].yangXpath) + if chlen > 0 { + for _, childXpath := range xDbSpecMap[child].yangXpath { + *retdbFormat = FillKeySpecs(childXpath, "", retdbFormat) + } + } + } + } + } + } + return *retdbFormat +} + func fillCvlKeySpec(yangXpath string , tableName string, keyStr string) ( []KeySpec ) { var retdbFormat = make([]KeySpec, 0) @@ -176,36 +202,6 @@ func fillCvlKeySpec(yangXpath string , tableName string, keyStr string) ( []KeyS return retdbFormat } -func fillKeySpec(yangXpath string, keyStr string, dbFormat *KeySpec) { - - if xSpecMap == nil { - return - } - _, ok := xSpecMap[yangXpath] - if ok { - xpathInfo := xSpecMap[yangXpath] - if xpathInfo.tableName != nil { - dbFormat.Ts.Name = *xpathInfo.tableName - if keyStr != "" { - dbFormat.Key.Comp = append(dbFormat.Key.Comp, keyStr) - } - } - for _, child := range xpathInfo.childTable { - // Current support for one child. Should change the KeySpec.Child - // to array of pointers later when we support all children - if xDbSpecMap != nil { - if len(xDbSpecMap[child].yangXpath) > 0 { - var childXpath = xDbSpecMap[child].yangXpath[0] - dbFormat.Child = new(KeySpec) - fillKeySpec(childXpath, "", dbFormat.Child) - } - } - } - } else { - return - } -} - func XlateToDb(path string, opcode int, d *db.DB, yg *ygot.GoStruct, yt *interface{}) (map[string]map[string]db.Value, error) { var err error diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index 107fb6035c..081d806930 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -367,6 +367,8 @@ func xpathKeyExtract(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string) (st } yangXpath, _ := RemoveXPATHPredicates(curPathWithKey) xpath = strings.Split(k, "[")[0] + _, ok := xSpecMap[yangXpath] + if ok { if len(xSpecMap[yangXpath].xfmrKey) > 0 { ret, err := XlateFuncCall(yangToDbXfmrFunc(xSpecMap[yangXpath].xfmrKey), d, ygRoot, oper, curPathWithKey) if err != nil { @@ -380,6 +382,7 @@ func xpathKeyExtract(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string) (st } keyStr += keyFromXpathCreate(keyl) } + } if isCvlYang(path) { //Format- /module:container/table[key]/field // table name extracted from the string token having key entry diff --git a/src/translib/transformer/xspec.go b/src/translib/transformer/xspec.go index 4725db08c9..dc615b7455 100644 --- a/src/translib/transformer/xspec.go +++ b/src/translib/transformer/xspec.go @@ -133,13 +133,16 @@ func yangToDbMapBuild(entries map[string]*yang.Entry) { xSpecMap = make(map[string]*yangXpathInfo) } - for _, e := range entries { + for module, e := range entries { if e == nil || len(e.Dir) == 0 { continue } - /* Start to fill xpath based map with yang data */ + /* Start to fill xpath based map with yang data */ yangToDbMapFill(xSpecMap, e, "") + + // Fill the ordered map of child tables list for oc yangs + updateSchemaOrderedMap(module, e) } mapPrint(xSpecMap, "/tmp/fullSpec.txt") dbMapPrint() @@ -350,3 +353,41 @@ func dbMapPrint() { } } +func updateSchemaOrderedMap(module string, entry *yang.Entry) { + var children []string + if entry.Node.Statement().Keyword == "module" { + for _, dir := range entry.DirOKeys { + // Gives the yang xpath for the top level container + xpath := "/" + module + ":" + dir + _, ok := xSpecMap[xpath] + if ok { + yentry := xSpecMap[xpath].yangEntry + if yentry.Node.Statement().Keyword == "container" { + var keyspec = make([]KeySpec, 0) + keyspec = FillKeySpecs(xpath, "" , &keyspec) + children = updateChildTable(keyspec, &children) + } + } + } + } + xDbSpecOrdTblMap[module] = children +} + +func updateChildTable(keyspec []KeySpec, chlist *[]string) ([]string) { + for _, ks := range keyspec { + if (ks.Ts.Name != "") { + var insert bool = true; + for _, tbl := range *chlist { + if tbl == ks.Ts.Name { + insert = false + break; + } + } + if insert { + *chlist = append(*chlist, ks.Ts.Name) + } + } + *chlist = updateChildTable(ks.Child, chlist) + } + return *chlist +} From 7956a3f740dc9f591f91e15e32b391aff523b7bd Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Fri, 30 Aug 2019 23:19:30 -0700 Subject: [PATCH 088/214] Initial support for YANG extension to allow the Transformer to set the DB names --- .../annotations/openconfig-acl-annot.yang | 53 ++++++++++++++++--- models/yang/common/sonic-extensions.yang | 9 ++++ src/translib/transformer/xlate.go | 6 ++- src/translib/transformer/xlate_utils.go | 9 ++++ src/translib/transformer/xspec.go | 38 +++++++++---- 5 files changed, 99 insertions(+), 16 deletions(-) diff --git a/models/yang/annotations/openconfig-acl-annot.yang b/models/yang/annotations/openconfig-acl-annot.yang index 887d4d43d2..c5292ee245 100644 --- a/models/yang/annotations/openconfig-acl-annot.yang +++ b/models/yang/annotations/openconfig-acl-annot.yang @@ -59,12 +59,6 @@ module openconfig-acl-annot { } } - deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-pkt-match:l2/oc-pkt-match:config/oc-pkt-match:ethertype { - deviate add { - sonic-ext:field-transformer "acl_l2_ethertype_xfmr"; - } - } - deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-pkt-match:ipv6/oc-pkt-match:config/oc-pkt-match:protocol { deviate add { sonic-ext:field-transformer "acl_ip_protocol_xfmr"; @@ -89,6 +83,12 @@ module openconfig-acl-annot { } } + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-pkt-match:l2/oc-pkt-match:config/oc-pkt-match:ethertype { + deviate add { + sonic-ext:field-transformer "acl_l2_ethertype_xfmr"; + } + } + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-acl:actions/oc-acl:config/oc-acl:forwarding-action { deviate add { sonic-ext:field-name "PACKET_ACTION"; @@ -101,5 +101,46 @@ module openconfig-acl-annot { } } + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:state { + deviate add { + sonic-ext:redis-db-name "STATE_DB"; + } + } + + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-acl:state { + deviate add { + sonic-ext:redis-db-name "STATE_DB"; + } + } + + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-acl:l2/oc-acl:state { + deviate add { + sonic-ext:redis-db-name "STATE_DB"; + } + } + + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-acl:ipv4/oc-acl:state { + deviate add { + sonic-ext:redis-db-name "STATE_DB"; + } + } + + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-acl:ipv6/oc-acl:state { + deviate add { + sonic-ext:redis-db-name "STATE_DB"; + } + } + + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-acl:transport/oc-acl:state { + deviate add { + sonic-ext:redis-db-name "STATE_DB"; + } + } + + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-acl:actions/oc-acl:state { + deviate add { + sonic-ext:redis-db-name "STATE_DB"; + } + } } diff --git a/models/yang/common/sonic-extensions.yang b/models/yang/common/sonic-extensions.yang index 60c44164bc..bcdd2187a4 100644 --- a/models/yang/common/sonic-extensions.yang +++ b/models/yang/common/sonic-extensions.yang @@ -18,6 +18,11 @@ module sonic-extensions { "This module provides extensions to the YANG language to allow Sonic specific functionality and meta-data to be defined."; + revision "2019-08-30" { + description + "Add extensions for redis DB mappings to identify the Redis DB name."; + } + revision "2019-07-26" { description "Add extensionis for redis DB mappings for table, table-keys, table-fields and corresponding transformer methods."; @@ -61,4 +66,8 @@ module sonic-extensions { description "Transformer name that will perform post-translation tasks."; } + extension redis-db-name { + argument "db-name"; + description "DB name that will indicate where data is stored. Eg: Config DB, App DB etc"; + } } diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index f64774150b..95767ddd97 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -115,6 +115,8 @@ func XlateUriToKeySpec(path string, uri *ygot.GoStruct, t *interface{}) (*map[db var err error var result = make(map[db.DBNum][]KeySpec) var retdbFormat = make([]KeySpec, 0) + // default DB number to read from + var dbInx db.DBNum = db.ConfigDB // In case of CVL yang, the tablename and key info is available in the xpath if isCvlYang(path) { @@ -125,8 +127,10 @@ func XlateUriToKeySpec(path string, uri *ygot.GoStruct, t *interface{}) (*map[db /* Extract the xpath and key from input xpath */ yangXpath, keyStr, _ := xpathKeyExtract(nil, uri, 0, path) retdbFormat = FillKeySpecs(yangXpath, keyStr, &retdbFormat) + dbInx = getDbNum(yangXpath) } - result[db.ConfigDB] = retdbFormat + + result[dbInx] = retdbFormat return &result, err } diff --git a/src/translib/transformer/xlate_utils.go b/src/translib/transformer/xlate_utils.go index bab7ebc9fa..c022e6ada5 100644 --- a/src/translib/transformer/xlate_utils.go +++ b/src/translib/transformer/xlate_utils.go @@ -165,3 +165,12 @@ func xpathRootNameGet(path string) string { return ("/" + pathl[1]) } +func getDbNum(xpath string ) db.DBNum { + _, ok := xSpecMap[xpath] + if ok { + xpathInfo := xSpecMap[xpath] + return xpathInfo.dbIndex + } + // Default is ConfigDB + return db.ConfigDB +} diff --git a/src/translib/transformer/xspec.go b/src/translib/transformer/xspec.go index dc615b7455..1dcd072ddf 100644 --- a/src/translib/transformer/xspec.go +++ b/src/translib/transformer/xspec.go @@ -5,6 +5,7 @@ import ( "os" "strings" log "github.com/golang/glog" + "translib/db" "github.com/openconfig/goyang/pkg/yang" ) @@ -21,6 +22,7 @@ type yangXpathInfo struct { fieldName string xfmrFunc string xfmrKey string + dbIndex db.DBNum } type dbInfo struct { @@ -57,6 +59,7 @@ func yangToDbMapFill (xSpecMap map[string]*yangXpathInfo, entry *yang.Entry, xpa if !ok { xpathData = new(yangXpathInfo) xSpecMap[xpath] = xpathData + xpathData.dbIndex = db.ConfigDB // default value } else { xpathData = xSpecMap[xpath] } @@ -72,6 +75,10 @@ func yangToDbMapFill (xSpecMap map[string]*yangXpathInfo, entry *yang.Entry, xpa xpathData.tableName = parentXpathData.tableName } + if ok && parentXpathData.dbIndex != db.ConfigDB { + xpathData.dbIndex = parentXpathData.dbIndex + } + if xpathData.yangDataType == "leaf" && len(xpathData.fieldName) == 0 { if xpathData.tableName != nil && xDbSpecMap[*xpathData.tableName] != nil { if xDbSpecMap[*xpathData.tableName].dbEntry.Dir[entry.Name] != nil { @@ -230,6 +237,7 @@ func annotEntryFill(xSpecMap map[string]*yangXpathInfo, xpath string, entry *yan fmt.Printf("Xpath not found(%v) \r\n", xpath) } + xpathData.dbIndex = db.ConfigDB // default value /* fill table with yang extension data. */ if entry != nil && len(entry.Exts) > 0 { for _, ext := range entry.Exts { @@ -257,6 +265,24 @@ func annotEntryFill(xSpecMap map[string]*yangXpathInfo, xpath string, entry *yan xpathData.xfmrFunc = ext.NName() case "use-self-key" : xpathData.keyXpath = nil + case "redis-db-name" : + if ext.NName() == "APPL_DB" { + xpathData.dbIndex = db.ApplDB + } else if ext.NName() == "ASIC_DB" { + xpathData.dbIndex = db.AsicDB + } else if ext.NName() == "COUNTERS_DB" { + xpathData.dbIndex = db.CountersDB + } else if ext.NName() == "LOGLEVEL_DB" { + xpathData.dbIndex = db.LogLevelDB + } else if ext.NName() == "CONFIG_DB" { + xpathData.dbIndex = db.ConfigDB + } else if ext.NName() == "FLEX_COUNTER_DB" { + xpathData.dbIndex = db.FlexCounterDB + } else if ext.NName() == "STATE_DB" { + xpathData.dbIndex = db.StateDB + } else { + xpathData.dbIndex = db.ConfigDB + } } } } @@ -318,6 +344,7 @@ func mapPrint(inMap map[string]*yangXpathInfo, fileName string) { fmt.Fprintf(fp, "\r\n FieldName: %v", d.fieldName) fmt.Fprintf(fp, "\r\n xfmrKeyFn: %v", d.xfmrKey) fmt.Fprintf(fp, "\r\n xfmrFunc : %v", d.xfmrFunc) + fmt.Fprintf(fp, "\r\n dbIndex : %v", d.dbIndex) fmt.Fprintf(fp, "\r\n yangEntry: ") if d.yangEntry != nil { fmt.Fprintf(fp, "%v", *d.yangEntry) @@ -376,16 +403,9 @@ func updateSchemaOrderedMap(module string, entry *yang.Entry) { func updateChildTable(keyspec []KeySpec, chlist *[]string) ([]string) { for _, ks := range keyspec { if (ks.Ts.Name != "") { - var insert bool = true; - for _, tbl := range *chlist { - if tbl == ks.Ts.Name { - insert = false - break; - } + if !contains(*chlist, ks.Ts.Name) { + *chlist = append(*chlist, ks.Ts.Name) } - if insert { - *chlist = append(*chlist, ks.Ts.Name) - } } *chlist = updateChildTable(ks.Child, chlist) } From 58ca40ac4436ffe95ce323f9b2b93eddb33fd932 Mon Sep 17 00:00:00 2001 From: s-mari Date: Tue, 3 Sep 2019 23:03:53 -0700 Subject: [PATCH 089/214] support to call transformer spl handler functions for get operation --- src/translib/transformer/xlate_from_db.go | 146 ++++++++++++++++------ src/translib/transformer/xlate_to_db.go | 8 +- src/translib/transformer/xlate_utils.go | 52 +++++++- src/translib/transformer/xspec.go | 11 +- 4 files changed, 173 insertions(+), 44 deletions(-) diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index 0fa976ad01..0fbcccdb0e 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -5,70 +5,138 @@ import ( "translib/db" "strings" "os" + "translib/ocbinds" + "github.com/openconfig/ygot/ygot" + "github.com/openconfig/ygot/ytypes" - //log "github.com/golang/glog" + log "github.com/golang/glog" ) +func xfmrHandlerFunc(d *db.DB, xpath string, uri string, dbDataMap map[string]map[string]db.Value) (string, error) { + var root ygot.ValidatedGoStruct + ygRoot := &root + ygot.BuildEmptyTree(root) + ret, err := XlateFuncCall(dbToYangXfmrFunc(xSpecMap[xpath].xfmrFunc), d, ygRoot, GET, uri, dbDataMap) + if err != nil { + return "", err + } + + errData := ret[0].Interface().(error) + if errData != nil { + return "", errData + } + ocbSch, _ := ocbinds.Schema() + schRoot := ocbSch.RootSchema() + device := (*ygRoot).(*ocbinds.Device) + + log.Info("Subtree transformer function(\"%v\") invoked for yang path(\"%v\").", xSpecMap[xpath].xfmrFunc, xpath) + path, _ := ygot.StringToPath(uri, ygot.StructuredPath, ygot.StringSlicePath) + for _, p := range path.Elem { + pathSlice := strings.Split(p.Name, ":") + p.Name = pathSlice[len(pathSlice)-1] + if len(p.Key) > 0 { + for ekey, ent := range p.Key { + eslice := strings.Split(ent, ":") + p.Key[ekey] = eslice[len(eslice)-1] + } + } + } + + nodeList, nErr := ytypes.GetNode(schRoot, device, path) + if nErr != nil { + return "", nErr + } + node := nodeList[0].Data + nodeYgot, _:= (node).(ygot.ValidatedGoStruct) + payload, err := ygot.EmitJSON(nodeYgot, &ygot.EmitJSONConfig{ Format: ygot.RFC7951, + Indent: " ", SkipValidation: true, + RFC7951Config: &ygot.RFC7951JSONConfig{ AppendModuleName: false, }, + }) + return payload, err +} + /* Traverse db map and add data to json */ -func dataToJsonAdd(xpath string, fieldData map[string]string, key string, dbDataMap map[string]map[string]db.Value) string { +func dataToJsonAdd(uri string, xpath string, fieldData map[string]string, key string, dbDataMap map[string]map[string]db.Value) (string, error) { spec, ok := xSpecMap[xpath] jsonData := "" if ok { for fld := range spec.yangEntry.Dir { fldXpath := xpath+"/"+fld + curUri := uri+"/"+fld if xSpecMap[fldXpath] != nil && xSpecMap[fldXpath].yangEntry != nil { ftype := yangTypeGet(xSpecMap[fldXpath].yangEntry) if ftype == "leaf" { - /* Add db field and value to json, call xfmr if needed */ - fldName := xSpecMap[fldXpath].fieldName - if len(fldName) > 0 { - val, ok := fieldData[fldName] - if ok { - jsonData += fmt.Sprintf("\"%v\" : \"%v\",", xSpecMap[fldXpath].yangEntry.Name, val) + if len(xSpecMap[fldXpath].xfmrFunc) > 0 { + /* field transformer present */ + jsonStr, err := xfmrHandlerFunc(nil, fldXpath, curUri, dbDataMap) + if err != nil { + return "", err + } + jsonData += jsonStr + } else { + /* Add db field and value to json, call xfmr if needed */ + fldName := xSpecMap[fldXpath].fieldName + if len(fldName) > 0 { + val, ok := fieldData[fldName] + if ok { + jsonData += fmt.Sprintf("\"%v\" : \"%v\",", xSpecMap[fldXpath].yangEntry.Name, val) + } } } } else if ftype == "container" && xSpecMap[fldXpath].yangEntry.Name != "state" { - /* Create container enclosure and attach container name and add to json */ - data := dataToJsonAdd(fldXpath, fieldData, key, dbDataMap) - if len(data) > 0 { - jsonData += fmt.Sprintf("\"%v\" : { \r\n %v \r\n },", xSpecMap[fldXpath].yangEntry.Name, data) - } + if len(xSpecMap[fldXpath].xfmrFunc) > 0 { + jsonStr, _ := xfmrHandlerFunc(nil, fldXpath, curUri, dbDataMap) + jsonData += jsonStr + } else { + /* Create container enclosure and attach container name and add to json */ + data, _:= dataToJsonAdd(curUri, fldXpath, fieldData, key, dbDataMap) + if len(data) > 0 { + jsonData += fmt.Sprintf("\"%v\" : { \r\n %v \r\n },", + xSpecMap[fldXpath].yangEntry.Name, data) + } + } } else if ftype == "list" { - /* Inner(child) list, traverse this list */ - childMap, ok := dbDataMap[*xSpecMap[fldXpath].tableName] - if ok { - var xpathl []string - xpathl = append(xpathl, fldXpath) - jsonData += listDataToJsonAdd(xpathl, childMap, key, dbDataMap) - } - } - } + if len(xSpecMap[fldXpath].xfmrFunc) > 0 { + jsonStr , _ := xfmrHandlerFunc(nil, fldXpath, curUri, dbDataMap) + jsonData += jsonStr + } else { + /* Inner(child) list, traverse this list */ + childMap, ok := dbDataMap[*xSpecMap[fldXpath].tableName] + if ok { + var xpathl []string + xpathl = append(xpathl, fldXpath) + jsonData += listDataToJsonAdd(curUri, xpathl, childMap, key, dbDataMap) + } + } + } + } } /* Last node in json data in current context, trim extra "," in data, so that json data is valid */ jsonData = strings.TrimRight(jsonData, ",") } - return jsonData + return jsonData, nil } /* Traverse list data and add to json */ -func listDataToJsonAdd(xpathl []string, dataMap map[string]db.Value, key string, dbDataMap map[string]map[string]db.Value) string { +func listDataToJsonAdd(uri string, xpathl []string, dataMap map[string]db.Value, key string, dbDataMap map[string]map[string]db.Value) string { jsonData := "" for _, xpath := range xpathl { - for kname, data := range dataMap { - if len(key) > 0 && !strings.HasPrefix(kname, key) { + for kval, data := range dataMap { + if len(key) > 0 && !strings.HasPrefix(kval, key) { continue } - dbKeyToYangDataConvert(kname, xpath) + curUri, kdata, _ := dbKeyToYangDataConvert(uri, xpath, kval) /* Traverse list members and add to json */ - data := dataToJsonAdd(xpath, data.Field, kname, dbDataMap) + data, _ := dataToJsonAdd(curUri, xpath, data.Field, kval, dbDataMap) + data += kdata if len(data) > 0 { /* Enclose all list instances with {} */ jsonData += fmt.Sprintf("{\r\n %v },", data) } /* Added data to json, so delete current instance data */ - delete(dataMap, kname) + delete(dataMap, kval) } if len(jsonData) > 0 { /* Last data in list,so trim extra "," in data, so that the json is valid */ @@ -114,16 +182,16 @@ func tableNameAndKeyFromDbMapGet(dbDataMap map[string]map[string]db.Value) (stri } /* Traverse linear db-map data and add to nested json data */ -func dbDataToYangJsonCreate(xpath string, dbDataMap map[string]map[string]db.Value) (string, error) { +func dbDataToYangJsonCreate(uri string, dbDataMap map[string]map[string]db.Value) (string, error) { jsonData := "" - if isCvlYang(xpath) { + if isCvlYang(uri) { jsonData := directDbToYangJsonCreate(dbDataMap, jsonData) jsonDataPrint(jsonData) return jsonData, nil } - reqXpath, _, _ := xpathKeyExtract(nil, nil, 0, xpath) + reqXpath, _, _ := xpathKeyExtract(nil, nil, GET, uri) ftype := yangTypeGet(xSpecMap[reqXpath].yangEntry) if ftype == "leaf" { fldName := xSpecMap[reqXpath].fieldName @@ -134,11 +202,15 @@ func dbDataToYangJsonCreate(xpath string, dbDataMap map[string]map[string]db.Val } curXpath := "" - for tblName, tblData := range dbDataMap { - if len(curXpath) == 0 || strings.HasPrefix(curXpath, xDbSpecMap[tblName].yangXpath[0]) { - curXpath = xDbSpecMap[tblName].yangXpath[0] - } - jsonData += listDataToJsonAdd(xDbSpecMap[tblName].yangXpath, tblData, "", dbDataMap) + tableOrder := [...]string{"ACL_TABLE", "ACL_RULE"} + for tblId := range tableOrder { + tblName := tableOrder[tblId] + if dbDataMap[tblName] != nil { + if len(curXpath) == 0 || strings.HasPrefix(curXpath, xDbSpecMap[tblName].yangXpath[0]) { + curXpath = xDbSpecMap[tblName].yangXpath[0] + } + jsonData += listDataToJsonAdd(uri, xDbSpecMap[tblName].yangXpath, dbDataMap[tblName], "", dbDataMap) + } } if strings.HasPrefix(reqXpath, curXpath) { if ftype != "leaf" { diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index 081d806930..0634c8a24e 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -370,7 +370,13 @@ func xpathKeyExtract(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string) (st _, ok := xSpecMap[yangXpath] if ok { if len(xSpecMap[yangXpath].xfmrKey) > 0 { - ret, err := XlateFuncCall(yangToDbXfmrFunc(xSpecMap[yangXpath].xfmrKey), d, ygRoot, oper, curPathWithKey) + xfmrFuncName := "" + if oper == GET { + xfmrFuncName = dbToYangXfmrFunc(xSpecMap[yangXpath].xfmrKey) + } else { + xfmrFuncName = yangToDbXfmrFunc(xSpecMap[yangXpath].xfmrKey) + } + ret, err := XlateFuncCall(xfmrFuncName, d, ygRoot, oper, curPathWithKey) if err != nil { return "", "", "" } diff --git a/src/translib/transformer/xlate_utils.go b/src/translib/transformer/xlate_utils.go index c022e6ada5..c36e0257b2 100644 --- a/src/translib/transformer/xlate_utils.go +++ b/src/translib/transformer/xlate_utils.go @@ -83,9 +83,49 @@ func yangTypeGet(entry *yang.Entry) string { return "" } -func dbKeyToYangDataConvert(dbKey string, xpath string) { - return -} +func dbKeyToYangDataConvert(uri string, xpath string, dbKey string) (string, string, error) { + fmt.Printf("MARI [in] (uri:%v)(xp:%v)\r\n", uri, xpath) + var kLvlValList []string + keyDataList := strings.Split(dbKey, "|") + keyNameList := yangKeyFromEntryGet(xSpecMap[xpath].yangEntry) + id := xSpecMap[xpath].keyLevel + jsonData := "" + uriWithKey := fmt.Sprintf("%v", xpath) + + /* if uri contins key, use it else use xpath */ + if strings.Contains(uri, "[") { + uriWithKey = fmt.Sprintf("%v", uri) + } + kLvlValList = append(kLvlValList, keyDataList[id]) + + if len(keyNameList) > 1 { + kLvlValList = strings.Split(keyDataList[id], "_") + } + + /* TODO: Need to add leaf-ref related code in here and remove this code*/ + kvalExceedFlag := false + chgId := -1 + if len(keyNameList) < len(kLvlValList) { + kvalExceedFlag = true + chgId = len(keyNameList) - 1 + } + + for i, kname := range keyNameList { + kval := kLvlValList[i] + + /* TODO: Need to add leaf-ref related code in here and remove this code*/ + if kvalExceedFlag && (i == chgId) { + kval = strings.Join(kLvlValList[chgId:], "_") + } + + jsonData += fmt.Sprintf("\"%v\" : \"%v\",", kname, kval) + uriWithKey += fmt.Sprintf("[%v=%v]", kname, kval) + } + + fmt.Printf("MARI [out] (uri:%v)(xp:%v)\r\n", uriWithKey, xpath) + return uriWithKey, jsonData, nil + } + func contains(sl []string, str string) bool { for _, v := range sl { @@ -174,3 +214,9 @@ func getDbNum(xpath string ) db.DBNum { // Default is ConfigDB return db.ConfigDB } + +func dbToYangXfmrFunc(funcName string) string { + return ("DbToYang_" + funcName) +} + + diff --git a/src/translib/transformer/xspec.go b/src/translib/transformer/xspec.go index 1dcd072ddf..20145b1475 100644 --- a/src/translib/transformer/xspec.go +++ b/src/translib/transformer/xspec.go @@ -23,6 +23,7 @@ type yangXpathInfo struct { xfmrFunc string xfmrKey string dbIndex db.DBNum + keyLevel int } type dbInfo struct { @@ -45,7 +46,7 @@ func updateDbTableData (xpath string, xpathData *yangXpathInfo, tableName string } /* Recursive api to fill the map with yang details */ -func yangToDbMapFill (xSpecMap map[string]*yangXpathInfo, entry *yang.Entry, xpathPrefix string) { +func yangToDbMapFill (keyLevel int, xSpecMap map[string]*yangXpathInfo, entry *yang.Entry, xpathPrefix string) { xpath := "" /* create the yang xpath */ if xSpecMap[xpathPrefix] != nil && xSpecMap[xpathPrefix].yangDataType == "module" { @@ -97,6 +98,7 @@ func yangToDbMapFill (xSpecMap map[string]*yangXpathInfo, entry *yang.Entry, xpa } /* fill table with key data. */ + curKeyLevel := keyLevel if len(entry.Key) != 0 { parentKeyLen := 0 @@ -113,6 +115,7 @@ func yangToDbMapFill (xSpecMap map[string]*yangXpathInfo, entry *yang.Entry, xpa xpathData.keyXpath[k] = parentXpathData.keyXpath[k] } xpathData.keyXpath[k] = &keyXpath + xpathData.keyLevel = curKeyLevel } else if parentXpathData != nil && parentXpathData.keyXpath != nil { xpathData.keyXpath = parentXpathData.keyXpath } @@ -126,7 +129,7 @@ func yangToDbMapFill (xSpecMap map[string]*yangXpathInfo, entry *yang.Entry, xpa xpathData.yangEntry = entry /* now recurse, filling the map with current node's children info */ for _, child := range childList { - yangToDbMapFill(xSpecMap, entry.Dir[child], xpath) + yangToDbMapFill(curKeyLevel, xSpecMap, entry.Dir[child], xpath) } } @@ -146,7 +149,8 @@ func yangToDbMapBuild(entries map[string]*yang.Entry) { } /* Start to fill xpath based map with yang data */ - yangToDbMapFill(xSpecMap, e, "") + keyLevel := 0 + yangToDbMapFill(keyLevel, xSpecMap, e, "") // Fill the ordered map of child tables list for oc yangs updateSchemaOrderedMap(module, e) @@ -342,6 +346,7 @@ func mapPrint(inMap map[string]*yangXpathInfo, fileName string) { fmt.Fprintf(fp, "%v", *d.tableName) } fmt.Fprintf(fp, "\r\n FieldName: %v", d.fieldName) + fmt.Fprintf(fp, "\r\n keyLevel : %v", d.keyLevel) fmt.Fprintf(fp, "\r\n xfmrKeyFn: %v", d.xfmrKey) fmt.Fprintf(fp, "\r\n xfmrFunc : %v", d.xfmrFunc) fmt.Fprintf(fp, "\r\n dbIndex : %v", d.dbIndex) From ca5e593f7c3bbe821371758db5ab278a9a8e6b4c Mon Sep 17 00:00:00 2001 From: amrutasali Date: Wed, 4 Sep 2019 20:17:58 +0000 Subject: [PATCH 090/214] Added API GetAndXlateFromDB() that clubs together genration of KeySpec and DB traversal for genric query(common app) --- src/translib/common_app.go | 16 ++-------------- src/translib/transformer/xlate.go | 27 +++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/src/translib/common_app.go b/src/translib/common_app.go index 23e41b199d..6ff18913ac 100644 --- a/src/translib/common_app.go +++ b/src/translib/common_app.go @@ -154,21 +154,9 @@ func (app *CommonApp) processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error) { var payload []byte log.Info("processGet:path =", app.pathInfo.Path) - keySpec, err := transformer.XlateUriToKeySpec(app.pathInfo.Path, app.ygotRoot, app.ygotTarget) - - var result = make(map[string]map[string]db.Value) - - for dbnum, specs := range *keySpec { - for _, spec := range specs { - err := transformer.TraverseDb(dbs[dbnum], spec, &result, nil) - if err != nil { - return GetResponse{Payload: payload}, err - } - } - } - - payload, err = transformer.XlateFromDb(app.pathInfo.Path, result) + payload, err = transformer.GetAndXlateFromDB(app.pathInfo.Path, app.ygotRoot, dbs) if err != nil { + log.Error("transformer.XlateFromDb() failure") return GetResponse{Payload: payload, ErrSrc: AppErr}, err } diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index 95767ddd97..8cadd2ca38 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -261,6 +261,33 @@ func XlateToDb(path string, opcode int, d *db.DB, yg *ygot.GoStruct, yt *interfa return result, err } +func GetAndXlateFromDB(xpath string, uri *ygot.GoStruct, dbs [db.MaxDB]*db.DB) ([]byte, error) { + var err error + var payload []byte + log.Info("received xpath =", xpath) + + keySpec, err := XlateUriToKeySpec(xpath, uri, nil) + var result = make(map[string]map[string]db.Value) + + for dbnum, specs := range *keySpec { + for _, spec := range specs { + err := TraverseDb(dbs[dbnum], spec, &result, nil) + if err != nil { + log.Error("TraverseDb() failure") + return payload, err + } + } + } + + payload, err = XlateFromDb(xpath, result) + if err != nil { + log.Error("XlateFromDb() failure.") + return payload, err + } + + return payload, err +} + func XlateFromDb(xpath string, data map[string]map[string]db.Value) ([]byte, error) { var err error var fieldName, tableName, yangXpath string From ffde97acbf72754453a4cd53e9d8d5d534c75406 Mon Sep 17 00:00:00 2001 From: amrutasali Date: Thu, 5 Sep 2019 18:46:03 +0000 Subject: [PATCH 091/214] Fix ygot issue in transformer by propagating ygRoot from app to transformer core --- src/translib/acl_app.go | 2 +- src/translib/transformer/xlate.go | 14 ++++++------ src/translib/transformer/xlate_from_db.go | 28 +++++++++++------------ 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/translib/acl_app.go b/src/translib/acl_app.go index e148523f0f..55a83be0e2 100644 --- a/src/translib/acl_app.go +++ b/src/translib/acl_app.go @@ -197,7 +197,7 @@ func (app *AclApp) processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error) { } } - payload, err = transformer.XlateFromDb(app.pathInfo.Path, result) + payload, err = transformer.XlateFromDb(app.pathInfo.Path, app.ygotRoot, result) if err != nil { return GetResponse{Payload: payload, ErrSrc: AppErr}, err } diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index 8cadd2ca38..e34df74875 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -110,7 +110,7 @@ func TraverseDb(d *db.DB, spec KeySpec, result *map[string]map[string]db.Value, return err } -func XlateUriToKeySpec(path string, uri *ygot.GoStruct, t *interface{}) (*map[db.DBNum][]KeySpec, error) { +func XlateUriToKeySpec(path string, ygRoot *ygot.GoStruct, t *interface{}) (*map[db.DBNum][]KeySpec, error) { var err error var result = make(map[db.DBNum][]KeySpec) @@ -125,7 +125,7 @@ func XlateUriToKeySpec(path string, uri *ygot.GoStruct, t *interface{}) (*map[db retdbFormat = fillCvlKeySpec(yangXpath, tableName, keyStr) } else { /* Extract the xpath and key from input xpath */ - yangXpath, keyStr, _ := xpathKeyExtract(nil, uri, 0, path) + yangXpath, keyStr, _ := xpathKeyExtract(nil, ygRoot, 0, path) retdbFormat = FillKeySpecs(yangXpath, keyStr, &retdbFormat) dbInx = getDbNum(yangXpath) } @@ -261,12 +261,12 @@ func XlateToDb(path string, opcode int, d *db.DB, yg *ygot.GoStruct, yt *interfa return result, err } -func GetAndXlateFromDB(xpath string, uri *ygot.GoStruct, dbs [db.MaxDB]*db.DB) ([]byte, error) { +func GetAndXlateFromDB(xpath string, ygRoot *ygot.GoStruct, dbs [db.MaxDB]*db.DB) ([]byte, error) { var err error var payload []byte log.Info("received xpath =", xpath) - keySpec, err := XlateUriToKeySpec(xpath, uri, nil) + keySpec, err := XlateUriToKeySpec(xpath, ygRoot, nil) var result = make(map[string]map[string]db.Value) for dbnum, specs := range *keySpec { @@ -279,7 +279,7 @@ func GetAndXlateFromDB(xpath string, uri *ygot.GoStruct, dbs [db.MaxDB]*db.DB) ( } } - payload, err = XlateFromDb(xpath, result) + payload, err = XlateFromDb(xpath, ygRoot, result) if err != nil { log.Error("XlateFromDb() failure.") return payload, err @@ -288,7 +288,7 @@ func GetAndXlateFromDB(xpath string, uri *ygot.GoStruct, dbs [db.MaxDB]*db.DB) ( return payload, err } -func XlateFromDb(xpath string, data map[string]map[string]db.Value) ([]byte, error) { +func XlateFromDb(xpath string, ygRoot *ygot.GoStruct, data map[string]map[string]db.Value) ([]byte, error) { var err error var fieldName, tableName, yangXpath string var dbData = make(map[string]map[string]db.Value) @@ -321,7 +321,7 @@ func XlateFromDb(xpath string, data map[string]map[string]db.Value) ([]byte, err dbData = extractFieldFromDb(tableName, keyStr, fieldName, data) } } - payload, err := dbDataToYangJsonCreate(yangXpath, dbData) + payload, err := dbDataToYangJsonCreate(yangXpath, ygRoot, dbData) if err != nil { log.Errorf("Error: failed to create json response from DB data.") diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index 0fbcccdb0e..2665972c24 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -12,10 +12,10 @@ import ( log "github.com/golang/glog" ) -func xfmrHandlerFunc(d *db.DB, xpath string, uri string, dbDataMap map[string]map[string]db.Value) (string, error) { - var root ygot.ValidatedGoStruct - ygRoot := &root - ygot.BuildEmptyTree(root) +func xfmrHandlerFunc(d *db.DB, xpath string, uri string, ygRoot *ygot.GoStruct, dbDataMap map[string]map[string]db.Value) (string, error) { + //var root ygot.ValidatedGoStruct + //ygRoot := &root + /*ygot.BuildEmptyTree(root)*/ ret, err := XlateFuncCall(dbToYangXfmrFunc(xSpecMap[xpath].xfmrFunc), d, ygRoot, GET, uri, dbDataMap) if err != nil { return "", err @@ -56,7 +56,7 @@ func xfmrHandlerFunc(d *db.DB, xpath string, uri string, dbDataMap map[string]ma } /* Traverse db map and add data to json */ -func dataToJsonAdd(uri string, xpath string, fieldData map[string]string, key string, dbDataMap map[string]map[string]db.Value) (string, error) { +func dataToJsonAdd(uri string, xpath string, ygRoot *ygot.GoStruct, fieldData map[string]string, key string, dbDataMap map[string]map[string]db.Value) (string, error) { spec, ok := xSpecMap[xpath] jsonData := "" @@ -69,7 +69,7 @@ func dataToJsonAdd(uri string, xpath string, fieldData map[string]string, key st if ftype == "leaf" { if len(xSpecMap[fldXpath].xfmrFunc) > 0 { /* field transformer present */ - jsonStr, err := xfmrHandlerFunc(nil, fldXpath, curUri, dbDataMap) + jsonStr, err := xfmrHandlerFunc(nil, fldXpath, curUri, ygRoot, dbDataMap) if err != nil { return "", err } @@ -86,11 +86,11 @@ func dataToJsonAdd(uri string, xpath string, fieldData map[string]string, key st } } else if ftype == "container" && xSpecMap[fldXpath].yangEntry.Name != "state" { if len(xSpecMap[fldXpath].xfmrFunc) > 0 { - jsonStr, _ := xfmrHandlerFunc(nil, fldXpath, curUri, dbDataMap) + jsonStr, _ := xfmrHandlerFunc(nil, fldXpath, curUri, ygRoot, dbDataMap) jsonData += jsonStr } else { /* Create container enclosure and attach container name and add to json */ - data, _:= dataToJsonAdd(curUri, fldXpath, fieldData, key, dbDataMap) + data, _:= dataToJsonAdd(curUri, fldXpath, ygRoot, fieldData, key, dbDataMap) if len(data) > 0 { jsonData += fmt.Sprintf("\"%v\" : { \r\n %v \r\n },", xSpecMap[fldXpath].yangEntry.Name, data) @@ -98,7 +98,7 @@ func dataToJsonAdd(uri string, xpath string, fieldData map[string]string, key st } } else if ftype == "list" { if len(xSpecMap[fldXpath].xfmrFunc) > 0 { - jsonStr , _ := xfmrHandlerFunc(nil, fldXpath, curUri, dbDataMap) + jsonStr , _ := xfmrHandlerFunc(nil, fldXpath, curUri, ygRoot, dbDataMap) jsonData += jsonStr } else { /* Inner(child) list, traverse this list */ @@ -106,7 +106,7 @@ func dataToJsonAdd(uri string, xpath string, fieldData map[string]string, key st if ok { var xpathl []string xpathl = append(xpathl, fldXpath) - jsonData += listDataToJsonAdd(curUri, xpathl, childMap, key, dbDataMap) + jsonData += listDataToJsonAdd(curUri, ygRoot, xpathl, childMap, key, dbDataMap) } } } @@ -119,7 +119,7 @@ func dataToJsonAdd(uri string, xpath string, fieldData map[string]string, key st } /* Traverse list data and add to json */ -func listDataToJsonAdd(uri string, xpathl []string, dataMap map[string]db.Value, key string, dbDataMap map[string]map[string]db.Value) string { +func listDataToJsonAdd(uri string, ygRoot *ygot.GoStruct, xpathl []string, dataMap map[string]db.Value, key string, dbDataMap map[string]map[string]db.Value) string { jsonData := "" for _, xpath := range xpathl { @@ -129,7 +129,7 @@ func listDataToJsonAdd(uri string, xpathl []string, dataMap map[string]db.Value, } curUri, kdata, _ := dbKeyToYangDataConvert(uri, xpath, kval) /* Traverse list members and add to json */ - data, _ := dataToJsonAdd(curUri, xpath, data.Field, kval, dbDataMap) + data, _ := dataToJsonAdd(curUri, xpath, ygRoot, data.Field, kval, dbDataMap) data += kdata if len(data) > 0 { /* Enclose all list instances with {} */ @@ -182,7 +182,7 @@ func tableNameAndKeyFromDbMapGet(dbDataMap map[string]map[string]db.Value) (stri } /* Traverse linear db-map data and add to nested json data */ -func dbDataToYangJsonCreate(uri string, dbDataMap map[string]map[string]db.Value) (string, error) { +func dbDataToYangJsonCreate(uri string, ygRoot *ygot.GoStruct, dbDataMap map[string]map[string]db.Value) (string, error) { jsonData := "" if isCvlYang(uri) { @@ -209,7 +209,7 @@ func dbDataToYangJsonCreate(uri string, dbDataMap map[string]map[string]db.Value if len(curXpath) == 0 || strings.HasPrefix(curXpath, xDbSpecMap[tblName].yangXpath[0]) { curXpath = xDbSpecMap[tblName].yangXpath[0] } - jsonData += listDataToJsonAdd(uri, xDbSpecMap[tblName].yangXpath, dbDataMap[tblName], "", dbDataMap) + jsonData += listDataToJsonAdd(uri, ygRoot, xDbSpecMap[tblName].yangXpath, dbDataMap[tblName], "", dbDataMap) } } if strings.HasPrefix(reqXpath, curXpath) { From ca1250d320f926a49ce2b21708fe3a137940749e Mon Sep 17 00:00:00 2001 From: amrutasali Date: Thu, 5 Sep 2019 18:53:35 +0000 Subject: [PATCH 092/214] remove commented out code from transformer xfmrHandlerFunc --- src/translib/transformer/xlate_from_db.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index 2665972c24..cb5a0e2f51 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -13,9 +13,6 @@ import ( ) func xfmrHandlerFunc(d *db.DB, xpath string, uri string, ygRoot *ygot.GoStruct, dbDataMap map[string]map[string]db.Value) (string, error) { - //var root ygot.ValidatedGoStruct - //ygRoot := &root - /*ygot.BuildEmptyTree(root)*/ ret, err := XlateFuncCall(dbToYangXfmrFunc(xSpecMap[xpath].xfmrFunc), d, ygRoot, GET, uri, dbDataMap) if err != nil { return "", err From bd42a11859c19035e85438680dbf6d21a6664c83 Mon Sep 17 00:00:00 2001 From: amrutasali Date: Fri, 6 Sep 2019 17:34:50 +0000 Subject: [PATCH 093/214] In dbDataToYangJsonCreate() added support to fetch table order from schema ordered table list maintained per module in xDbSpecOrdTblMap --- src/translib/transformer/xlate.go | 12 +++--------- src/translib/transformer/xlate_from_db.go | 11 +++++++++-- src/translib/transformer/xlate_utils.go | 22 +++++++++++++++++++++- 3 files changed, 33 insertions(+), 12 deletions(-) diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index e34df74875..9ac1a8a769 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -352,15 +352,9 @@ func extractFieldFromDb(tableName string, keyStr string, fieldName string, data } func GetModuleNmFromPath(uri string) (string, error) { - path, err := ygot.StringToPath(uri, ygot.StructuredPath, ygot.StringSlicePath) - if err != nil { - log.Error("Error in uri to path conversion: ", err) - return "", err - } - pathSlice := strings.Split(path.Elem[0].Name, ":") - moduleNm := pathSlice[0] - log.Info("Module name for given path = ", moduleNm) - return moduleNm, err + log.Infof("received uri %s to extract module name from ", uri) + moduleNm, err := uriModuleNameGet(uri) + return moduleNm, err } func GetOrdDBTblList(ygModuleNm string) ([]string, error) { diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index cb5a0e2f51..abf1f715ec 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -181,7 +181,14 @@ func tableNameAndKeyFromDbMapGet(dbDataMap map[string]map[string]db.Value) (stri /* Traverse linear db-map data and add to nested json data */ func dbDataToYangJsonCreate(uri string, ygRoot *ygot.GoStruct, dbDataMap map[string]map[string]db.Value) (string, error) { jsonData := "" - + moduleNm, err := uriModuleNameGet(uri) + if err != nil { + return jsonData, err + } + tableOrder, err := GetOrdDBTblList(moduleNm) + if err != nil { + return jsonData, err + } if isCvlYang(uri) { jsonData := directDbToYangJsonCreate(dbDataMap, jsonData) jsonDataPrint(jsonData) @@ -199,7 +206,7 @@ func dbDataToYangJsonCreate(uri string, ygRoot *ygot.GoStruct, dbDataMap map[str } curXpath := "" - tableOrder := [...]string{"ACL_TABLE", "ACL_RULE"} + //tableOrder := [...]string{"ACL_TABLE", "ACL_RULE"} for tblId := range tableOrder { tblName := tableOrder[tblId] if dbDataMap[tblName] != nil { diff --git a/src/translib/transformer/xlate_utils.go b/src/translib/transformer/xlate_utils.go index c36e0257b2..1cdc349e59 100644 --- a/src/translib/transformer/xlate_utils.go +++ b/src/translib/transformer/xlate_utils.go @@ -219,4 +219,24 @@ func dbToYangXfmrFunc(funcName string) string { return ("DbToYang_" + funcName) } - +func uriModuleNameGet(uri string) (string, error) { + var err error + result := "" + if len(uri) == 0 { + log.Error("Empty uri string supplied") + return result, err + } + urislice := strings.Split(uri, ":") + if len(urislice) == 1 { + log.Errorf("uri string %s does not have module name", uri) + return result, err + } + moduleNm := strings.Split(urislice[0], "/") + result = moduleNm[1] + if len(strings.Trim(result, " ")) == 0 { + log.Error("Empty module name") + err = fmt.Errorf("No module name found in uri %s", uri) + } + log.Info("module name = ", result) + return result, err +} From e4dd5b166b9825b282dc02b42ebc599814990d8f Mon Sep 17 00:00:00 2001 From: amrutasali Date: Fri, 6 Sep 2019 17:40:49 +0000 Subject: [PATCH 094/214] removed commented put code for table order in xlate_from_db.go --- src/translib/transformer/xlate_from_db.go | 1 - 1 file changed, 1 deletion(-) diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index abf1f715ec..bfc9fc997d 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -206,7 +206,6 @@ func dbDataToYangJsonCreate(uri string, ygRoot *ygot.GoStruct, dbDataMap map[str } curXpath := "" - //tableOrder := [...]string{"ACL_TABLE", "ACL_RULE"} for tblId := range tableOrder { tblName := tableOrder[tblId] if dbDataMap[tblName] != nil { From 0a1d4b28d065c3f2381ea6c59e2c30e0f7fb14e6 Mon Sep 17 00:00:00 2001 From: justinejose91 Date: Fri, 6 Sep 2019 15:11:34 -0700 Subject: [PATCH 095/214] Fix for not showing description when description is configured as part of #show interface command. --- src/CLI/renderer/templates/show_interface.j2 | 5 +++++ src/CLI/renderer/templates/show_interface_id.j2 | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/src/CLI/renderer/templates/show_interface.j2 b/src/CLI/renderer/templates/show_interface.j2 index c3c8e512f0..8e50d6fc74 100644 --- a/src/CLI/renderer/templates/show_interface.j2 +++ b/src/CLI/renderer/templates/show_interface.j2 @@ -4,6 +4,7 @@ {% set vars = {'admin_state': ""} %} {% set vars = {'oper_state': ""} %} {% set vars = {'index': ""} %} +{% set vars = {'description':""} %} {% set vars = {'mtu': ""} %} {% set vars = {'ipv4_src_pfx': ""} %} {% set vars = {'ipv6_src_pfx': ""} %} @@ -37,6 +38,7 @@ {% if vars.update({'admin_state':interface[key]["admin-status"]}) %}{% endif %} {% if vars.update({'oper_state':interface[key]["oper-status"]}) %}{% endif %} {% if vars.update({'index':interface[key]["ifindex"]}) %}{% endif %} + {% if vars.update({'description':interface[key]["description"]}) %}{% endif %} {% if vars.update({'mtu':interface[key]["mtu"]}) %}{% endif %} {% endif %} {% if "counters" in interface["state"] %} @@ -95,6 +97,9 @@ {{ vars.name }} is {{ vars.admin_state|lower() }}, line protocol is {{vars.oper_state|lower() }} Hardware is Eth Interface index is {{ vars.index }} +{% if vars.description %} +Description: {{ vars.description }} +{% endif %} {% if vars.ipv4_src_pfx %} {{ vars.ipv4 }} address is {{ vars.ipv4_src_pfx }} {% endif %} diff --git a/src/CLI/renderer/templates/show_interface_id.j2 b/src/CLI/renderer/templates/show_interface_id.j2 index 4663c65d21..b4b4b32eed 100644 --- a/src/CLI/renderer/templates/show_interface_id.j2 +++ b/src/CLI/renderer/templates/show_interface_id.j2 @@ -4,6 +4,7 @@ {% set vars = {'admin_state': ""} %} {% set vars = {'oper_state': ""} %} {% set vars = {'index': ""} %} +{% set vars = {'description':""} %} {% set vars = {'mtu': ""} %} {% set vars = {'ipv4_src_pfx': ""} %} {% set vars = {'ipv6_src_pfx': ""} %} @@ -37,6 +38,7 @@ {% if vars.update({'admin_state':interface[key]["admin-status"]}) %}{% endif %} {% if vars.update({'oper_state':interface[key]["oper-status"]}) %}{% endif %} {% if vars.update({'index':interface[key]["ifindex"]}) %}{% endif %} + {% if vars.update({'description':interface[key]["description"]}) %}{% endif %} {% if vars.update({'mtu':interface[key]["mtu"]}) %}{% endif %} {% if vars.update({'in_pkts':interface[key]["counters"]["in-pkts"]}) %}{% endif %} {% if vars.update({'in_octets':interface[key]["counters"]["in-octets"]}) %}{% endif %} @@ -92,6 +94,9 @@ Hardware is Eth Interface index is {{ vars.index }} +{% if vars.description %} +Description: {{ vars.description }} +{% endif %} {% if vars.ipv4_src_pfx %} {{ vars.ipv4 }} address is {{ vars.ipv4_src_pfx }} {% endif %} From 4cfd72fab86fa16e66caf8f74c5c17c8eba0555e Mon Sep 17 00:00:00 2001 From: s-mari Date: Sat, 7 Sep 2019 11:24:37 -0700 Subject: [PATCH 096/214] Enhanced the xfmr functions, added flag for key leaf, updated get req apis to use enhanced xfmr handlers --- src/translib/transformer/xfmr_acl.go | 130 +++++++++++++++++---- src/translib/transformer/xfmr_interface.go | 4 +- src/translib/transformer/xlate_from_db.go | 27 +++-- src/translib/transformer/xlate_to_db.go | 7 +- src/translib/transformer/xlate_utils.go | 18 ++- src/translib/transformer/xspec.go | 6 + 6 files changed, 152 insertions(+), 40 deletions(-) diff --git a/src/translib/transformer/xfmr_acl.go b/src/translib/transformer/xfmr_acl.go index 38d586aee5..3a16a56ee1 100644 --- a/src/translib/transformer/xfmr_acl.go +++ b/src/translib/transformer/xfmr_acl.go @@ -215,8 +215,8 @@ var YangToDb_acl_entry_key_xfmr KeyXfmrYangToDb = func (d *db.DB, ygRoot *ygot.G return entry_key, err } -var DbToYang_acl_entry_key_xfmr KeyXfmrDbToYang = func (d *db.DB, opType int, entry_key string) (map[string]map[string]string, error) { - res_map := make(map[string]map[string]string) +var DbToYang_acl_entry_key_xfmr KeyXfmrDbToYang = func (d *db.DB, opType int, entry_key string) (map[string]string, error) { + rmap := make(map[string]string) var err error log.Info("DbToYang_acl_entry_key_xfmr: ", entry_key) @@ -224,18 +224,13 @@ var DbToYang_acl_entry_key_xfmr KeyXfmrDbToYang = func (d *db.DB, opType int, en if len(key) < 2 { err = errors.New("Invalid key for acl entries.") log.Info("Invalid Keys for acl enmtries", entry_key) - return res_map, err + return rmap, err } - dbAclName := key[0] dbAclRule := key[1] - aclName, aclType := getOCAclKeysFromStrDBKey(dbAclName) - res_map["oc-acl:acl-set"]["name"] = aclName - res_map["oc-acl:acl-set"]["type"] = aclType.ΛMap()["E_OpenconfigAcl_ACL_TYPE"][int64(aclType)].Name seqId := strings.Replace(dbAclRule, "RULE_", "", 1) - res_map["acl-entry"]["sequence-id"] = seqId - log.Info("DbToYang_acl_entry_key_xfmr - res_map: ", res_map) - return res_map, err + rmap["sequence-id"] = seqId + return rmap, err } var YangToDb_acl_l2_ethertype_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, opType int, xpath string, ethertype interface {}) (map[string]string, error) { @@ -260,10 +255,28 @@ var YangToDb_acl_l2_ethertype_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *y return res_map, err } -var DbToYang_acl_l2_ethertype_xfmr FieldXfmrDbtoYang = func (d *db.DB, opType int, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct) (error) { +var DbToYang_acl_l2_ethertype_xfmr FieldXfmrDbtoYang = func (d *db.DB, opType int, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct, key string) (map[string]interface{}, error) { var err error + result := make(map[string]interface{}) log.Info("DbToYang_acl_l2_ethertype_xfmr", data, ygRoot) + if _, ok := data[RULE_TABLE]; !ok { + err = errors.New("RULE_TABLE entry not found in the input param") + return result, err + } + ruleTbl := data[RULE_TABLE] + ruleInst := ruleTbl[key] + etype, ok := ruleInst.Field["ETHER_TYPE"] + + if ok { + etypeVal, _ := strconv.ParseUint(strings.Replace(etype, "0x", "", -1), 16, 32) + result["protocol"] = getL2EtherType(etypeVal) + } else { + err = errors.New("ETHER_TYPE field not found in DB") + } + return result, nil + + /* if _, ok := data[RULE_TABLE]; !ok { err = errors.New("RULE_TABLE entry not found in the input param") return err @@ -291,6 +304,7 @@ var DbToYang_acl_l2_ethertype_xfmr FieldXfmrDbtoYang = func (d *db.DB, opType in } return err + */ } var YangToDb_acl_ip_protocol_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, opType int, xpath string, protocol interface {}) (map[string]string, error) { @@ -312,15 +326,28 @@ var YangToDb_acl_ip_protocol_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *yg return res_map, err } -var DbToYang_acl_ip_protocol_xfmr FieldXfmrDbtoYang = func (d *db.DB, opType int, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct) (error) { +var DbToYang_acl_ip_protocol_xfmr FieldXfmrDbtoYang = func (d *db.DB, opType int, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct, key string) (map[string]interface{}, error) { var err error + result := make(map[string]interface{}) log.Info("DbToYang_acl_ip_protocol_xfmr ", data, ygRoot) if _, ok := data[RULE_TABLE]; !ok { err = errors.New("RULE_TABLE entry not found in the input param") - return err + return result, err } - ruleTbl := data[RULE_TABLE] + ruleTbl := data[RULE_TABLE] + ruleInst := ruleTbl[key] + prot, ok := ruleInst.Field["IP_PROTOCOL"] + + if ok { + ipProto, _ := strconv.ParseInt(prot, 10, 64) + result["protocol"] = getIpProtocol(ipProto) + } else { + err = errors.New("IP_PROTOCOL field not found in DB") + } + return result, err + + /* for aclRuleKey := range ruleTbl { ruleData := ruleTbl[aclRuleKey] var entrySet *ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry @@ -341,7 +368,7 @@ var DbToYang_acl_ip_protocol_xfmr FieldXfmrDbtoYang = func (d *db.DB, opType int entrySet.Ipv6.Config.Protocol, _ = entrySet.Ipv6.Config.To_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Ipv6_Config_Protocol_Union(protocolVal) entrySet.Ipv6.State.Protocol, _ = entrySet.Ipv6.State.To_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Ipv6_State_Protocol_Union(protocolVal) } - return err + */ } var YangToDb_acl_source_port_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, opType int, xpath string, value interface {}) (map[string]string, error) { @@ -367,10 +394,10 @@ var YangToDb_acl_source_port_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *yg return res_map, err } + func getAclSetEntry (aclRuleKey string, ygRoot *ygot.GoStruct) (*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry, error) { var err error var entrySet *ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry - aclObj := getAclRoot(ygRoot) key := strings.Split(aclRuleKey, "|") @@ -387,7 +414,8 @@ func getAclSetEntry (aclRuleKey string, ygRoot *ygot.GoStruct) (*ocbinds.Opencon log.Info("Accessing Ygot tree for ACL rule", aclSetKey.Name, aclSetKey.Type, seqId) var aclSet *ocbinds.OpenconfigAcl_Acl_AclSets_AclSet - if _, ok := aclObj.AclSets.AclSet[aclSetKey]; !ok { + _, ok := aclObj.AclSets.AclSet[aclSetKey] + if !ok { log.Info("ACL set not allocated") aclSet, _ = aclObj.AclSets.NewAclSet(aclSetKey.Name, aclSetKey.Type) ygot.BuildEmptyTree(aclSet) @@ -407,9 +435,31 @@ func getAclSetEntry (aclRuleKey string, ygRoot *ygot.GoStruct) (*ocbinds.Opencon } -var DbToYang_acl_source_port_xfmr FieldXfmrDbtoYang = func (d *db.DB, opType int, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct) (error) { +var DbToYang_acl_source_port_xfmr FieldXfmrDbtoYang = func (d *db.DB, opType int, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct, key string) (map[string]interface{}, error) { var err error log.Info("DbToYang_acl_source_port_xfmr: ", data, ygRoot) + result := make(map[string]interface{}) + if _, ok := data[RULE_TABLE]; !ok { + err = errors.New("RULE_TABLE entry not found in the input param") + return result, err + } + ruleTbl := data[RULE_TABLE] + ruleInst := ruleTbl[key] + port, ok := ruleInst.Field["L4_SRC_PORT"] + if ok { + result["source-port"] = port + return result, nil + } + + portRange, ok := ruleInst.Field["L4_SRC_PORT_RANGE"] + if ok { + result["source-port"] = portRange + return result, nil + } else { + err = errors.New("PORT/PORT_RANGE field not found in DB") + } + return result, err + /* if _, ok := data[RULE_TABLE]; !ok { err = errors.New("RULE_TABLE entry not found in the input param") @@ -444,6 +494,7 @@ var DbToYang_acl_source_port_xfmr FieldXfmrDbtoYang = func (d *db.DB, opType int entrySet.Transport.State.SourcePort, _ = entrySet.Transport.State.To_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_State_SourcePort_Union(srcPort) } return err + */ } var YangToDb_acl_destination_port_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, opType int, xpath string, value interface{}) (map[string]string, error) { @@ -468,9 +519,31 @@ var YangToDb_acl_destination_port_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoo return res_map, err } -var DbToYang_acl_destination_port_xfmr FieldXfmrDbtoYang = func (d *db.DB, opType int, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct) (error) { +var DbToYang_acl_destination_port_xfmr FieldXfmrDbtoYang = func (d *db.DB, opType int, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct, key string) (map[string]interface{}, error) { var err error log.Info("DbToYang_acl_destination_port_xfmr: ", data, ygRoot) + result := make(map[string]interface{}) + if _, ok := data[RULE_TABLE]; !ok { + err = errors.New("RULE_TABLE entry not found in the input param") + return result, err + } + ruleTbl := data[RULE_TABLE] + ruleInst := ruleTbl[key] + port, ok := ruleInst.Field["L4_DST_PORT"] + if ok { + result["destination-port"] = port + return result, nil + } + + portRange, ok := ruleInst.Field["L4_DST_PORT_RANGE"] + if ok { + result["destination-port"] = portRange + return result, nil + } else { + err = errors.New("DST PORT/PORT_RANGE field not found in DB") + } + return result, err + /* if _, ok := data[RULE_TABLE]; !ok { err = errors.New("RULE_TABLE entry not found in the input param") return err @@ -504,6 +577,7 @@ var DbToYang_acl_destination_port_xfmr FieldXfmrDbtoYang = func (d *db.DB, opTyp } return err + */ } var YangToDb_acl_tcp_flags_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, opType int, xpath string, value interface {}) (map[string]string, error) { @@ -549,9 +623,23 @@ var YangToDb_acl_tcp_flags_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot return res_map, err } -var DbToYang_acl_tcp_flags_xfmr FieldXfmrDbtoYang = func (d *db.DB, opType int, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct) (error) { +var DbToYang_acl_tcp_flags_xfmr FieldXfmrDbtoYang = func (d *db.DB, opType int, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct, key string) (map[string]interface{}, error) { var err error log.Info("DbToYang_acl_tcp_flags_xfmr: ", data, ygRoot) + result := make(map[string]interface{}) + if _, ok := data[RULE_TABLE]; !ok { + err = errors.New("RULE_TABLE entry not found in the input param") + return result, err + } + ruleTbl := data[RULE_TABLE] + ruleInst := ruleTbl[key] + tcpFlag, ok := ruleInst.Field["TCP_FLAGS"] + if ok { + result["tcp-flags"] = getTransportConfigTcpFlags(tcpFlag) + return result, nil + } + return result, nil + /* if _, ok := data[RULE_TABLE]; !ok { err = errors.New("RULE_TABLE entry not found in the input param") @@ -578,6 +666,7 @@ var DbToYang_acl_tcp_flags_xfmr FieldXfmrDbtoYang = func (d *db.DB, opType int, entrySet.Transport.State.TcpFlags = getTransportConfigTcpFlags(tcpFlags) } return err + */ } func convertDBAclRulesToInternal(dbCl *db.DB, aclName string, seqId int64, ruleKey db.Key) (ruleTableMap map[string]map[string]db.Value, ferr error) { @@ -771,6 +860,7 @@ var YangToDb_acl_port_bindings_xfmr SubTreeXfmrYangToDb = func (d *db.DB, ygRoot var DbToYang_acl_port_bindings_xfmr SubTreeXfmrDbToYang = func (d *db.DB, opType int, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct, xpath string) (error) { var err error log.Info("DbToYang_acl_port_bindings_xfmr: ", data, ygRoot) + return nil aclTbl, ruleTbl, err := getDbAlcTblsData(d) diff --git a/src/translib/transformer/xfmr_interface.go b/src/translib/transformer/xfmr_interface.go index 42407075f2..78f15ce96d 100644 --- a/src/translib/transformer/xfmr_interface.go +++ b/src/translib/transformer/xfmr_interface.go @@ -19,7 +19,7 @@ type KeyXfmrYangToDb func (*db.DB, *ygot.GoStruct, int, string) (string, error) * Param: Database info, operation, Database keys to access db entry * Return: multi dimensional map to hold the yang key attributes of complete xpath, error **/ -type KeyXfmrDbToYang func (*db.DB, int, string) (map[string]map[string]string, error) +type KeyXfmrDbToYang func (*db.DB, int, string) (map[string]string, error) /** * FieldXfmrYangToDb type is defined to use for conversion of yang Field to DB field @@ -34,7 +34,7 @@ type FieldXfmrYangToDb func (*db.DB, *ygot.GoStruct, int, string, interface {}) * Param: Database info, operation, DB data in multidimensional map, output param YgotRoot * Return: error **/ -type FieldXfmrDbtoYang func (*db.DB, int, map[string]map[string]db.Value, *ygot.GoStruct) (error) +type FieldXfmrDbtoYang func (*db.DB, int, map[string]map[string]db.Value, *ygot.GoStruct, string) (map[string]interface{}, error) /** * SubTreeXfmrYangToDb type is defined to use for handling the yang subtree to DB diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index cb5a0e2f51..9ca58c6734 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -13,15 +13,11 @@ import ( ) func xfmrHandlerFunc(d *db.DB, xpath string, uri string, ygRoot *ygot.GoStruct, dbDataMap map[string]map[string]db.Value) (string, error) { - ret, err := XlateFuncCall(dbToYangXfmrFunc(xSpecMap[xpath].xfmrFunc), d, ygRoot, GET, uri, dbDataMap) + _, err := XlateFuncCall(dbToYangXfmrFunc(xSpecMap[xpath].xfmrFunc), d, GET, dbDataMap, ygRoot) if err != nil { return "", err } - errData := ret[0].Interface().(error) - if errData != nil { - return "", errData - } ocbSch, _ := ocbinds.Schema() schRoot := ocbSch.RootSchema() device := (*ygRoot).(*ocbinds.Device) @@ -52,6 +48,21 @@ func xfmrHandlerFunc(d *db.DB, xpath string, uri string, ygRoot *ygot.GoStruct, return payload, err } +func leafXfmrHandlerFunc(d *db.DB, xpath string, uri string, ygRoot *ygot.GoStruct, dbDataMap map[string]map[string]db.Value) (string, error) { + _, keyName, _ := xpathKeyExtract(d, ygRoot, GET, uri) + ret, err := XlateFuncCall(dbToYangXfmrFunc(xSpecMap[xpath].xfmrFunc), d, GET, dbDataMap, ygRoot, keyName) + if err != nil { + return "", err + } + fldValMap := ret[0].Interface().(map[string]interface{}) + data := "" + for f, v := range fldValMap { + value := fmt.Sprintf("%v", v) + data += fmt.Sprintf("\"%v\" : \"%v\",", f, value) + } + return data, nil +} + /* Traverse db map and add data to json */ func dataToJsonAdd(uri string, xpath string, ygRoot *ygot.GoStruct, fieldData map[string]string, key string, dbDataMap map[string]map[string]db.Value) (string, error) { spec, ok := xSpecMap[xpath] @@ -66,7 +77,7 @@ func dataToJsonAdd(uri string, xpath string, ygRoot *ygot.GoStruct, fieldData ma if ftype == "leaf" { if len(xSpecMap[fldXpath].xfmrFunc) > 0 { /* field transformer present */ - jsonStr, err := xfmrHandlerFunc(nil, fldXpath, curUri, ygRoot, dbDataMap) + jsonStr, err := leafXfmrHandlerFunc(nil, fldXpath, curUri, ygRoot, dbDataMap) if err != nil { return "", err } @@ -74,7 +85,7 @@ func dataToJsonAdd(uri string, xpath string, ygRoot *ygot.GoStruct, fieldData ma } else { /* Add db field and value to json, call xfmr if needed */ fldName := xSpecMap[fldXpath].fieldName - if len(fldName) > 0 { + if len(fldName) > 0 && !xSpecMap[fldXpath].isKey { val, ok := fieldData[fldName] if ok { jsonData += fmt.Sprintf("\"%v\" : \"%v\",", xSpecMap[fldXpath].yangEntry.Name, val) @@ -127,7 +138,7 @@ func listDataToJsonAdd(uri string, ygRoot *ygot.GoStruct, xpathl []string, dataM curUri, kdata, _ := dbKeyToYangDataConvert(uri, xpath, kval) /* Traverse list members and add to json */ data, _ := dataToJsonAdd(curUri, xpath, ygRoot, data.Field, kval, dbDataMap) - data += kdata + data = kdata + data if len(data) > 0 { /* Enclose all list instances with {} */ jsonData += fmt.Sprintf("{\r\n %v },", data) diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index 0634c8a24e..dfbd116c03 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -370,12 +370,7 @@ func xpathKeyExtract(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string) (st _, ok := xSpecMap[yangXpath] if ok { if len(xSpecMap[yangXpath].xfmrKey) > 0 { - xfmrFuncName := "" - if oper == GET { - xfmrFuncName = dbToYangXfmrFunc(xSpecMap[yangXpath].xfmrKey) - } else { - xfmrFuncName = yangToDbXfmrFunc(xSpecMap[yangXpath].xfmrKey) - } + xfmrFuncName := yangToDbXfmrFunc(xSpecMap[yangXpath].xfmrKey) ret, err := XlateFuncCall(xfmrFuncName, d, ygRoot, oper, curPathWithKey) if err != nil { return "", "", "" diff --git a/src/translib/transformer/xlate_utils.go b/src/translib/transformer/xlate_utils.go index c36e0257b2..9a601945d4 100644 --- a/src/translib/transformer/xlate_utils.go +++ b/src/translib/transformer/xlate_utils.go @@ -84,7 +84,6 @@ func yangTypeGet(entry *yang.Entry) string { } func dbKeyToYangDataConvert(uri string, xpath string, dbKey string) (string, string, error) { - fmt.Printf("MARI [in] (uri:%v)(xp:%v)\r\n", uri, xpath) var kLvlValList []string keyDataList := strings.Split(dbKey, "|") keyNameList := yangKeyFromEntryGet(xSpecMap[xpath].yangEntry) @@ -96,6 +95,20 @@ func dbKeyToYangDataConvert(uri string, xpath string, dbKey string) (string, str if strings.Contains(uri, "[") { uriWithKey = fmt.Sprintf("%v", uri) } + + if len(xSpecMap[xpath].xfmrKey) > 0 { + var d *db.DB + ret, err := XlateFuncCall(dbToYangXfmrFunc(xSpecMap[xpath].xfmrKey), d, GET, dbKey) + if err != nil { + return "","",err + } + rmap := ret[0].Interface().(map[string]string) + for k, v := range rmap { + jsonData += fmt.Sprintf("\"%v\" : \"%v\",\r\n", k, v) + uriWithKey += fmt.Sprintf("[%v=%v]", k, v) + } + return uriWithKey, jsonData, nil + } kLvlValList = append(kLvlValList, keyDataList[id]) if len(keyNameList) > 1 { @@ -122,7 +135,6 @@ func dbKeyToYangDataConvert(uri string, xpath string, dbKey string) (string, str uriWithKey += fmt.Sprintf("[%v=%v]", kname, kval) } - fmt.Printf("MARI [out] (uri:%v)(xp:%v)\r\n", uriWithKey, xpath) return uriWithKey, jsonData, nil } @@ -218,5 +230,3 @@ func getDbNum(xpath string ) db.DBNum { func dbToYangXfmrFunc(funcName string) string { return ("DbToYang_" + funcName) } - - diff --git a/src/translib/transformer/xspec.go b/src/translib/transformer/xspec.go index 20145b1475..c4a3580687 100644 --- a/src/translib/transformer/xspec.go +++ b/src/translib/transformer/xspec.go @@ -24,6 +24,7 @@ type yangXpathInfo struct { xfmrKey string dbIndex db.DBNum keyLevel int + isKey bool } type dbInfo struct { @@ -106,6 +107,9 @@ func yangToDbMapFill (keyLevel int, xSpecMap map[string]*yangXpathInfo, entry *y keyXpath := make([]string, len(strings.Split(entry.Key, " "))) for id, keyName := range(strings.Split(entry.Key, " ")) { keyXpath[id] = xpath + "/" + keyName + keyXpathData := new(yangXpathInfo) + xSpecMap[xpath + "/" + keyName] = keyXpathData + xSpecMap[xpath + "/" + keyName].isKey = true } xpathData.keyXpath = make(map[int]*[]string, (parentKeyLen + 1)) @@ -116,6 +120,7 @@ func yangToDbMapFill (keyLevel int, xSpecMap map[string]*yangXpathInfo, entry *y } xpathData.keyXpath[k] = &keyXpath xpathData.keyLevel = curKeyLevel + curKeyLevel++ } else if parentXpathData != nil && parentXpathData.keyXpath != nil { xpathData.keyXpath = parentXpathData.keyXpath } @@ -362,6 +367,7 @@ func mapPrint(inMap map[string]*yangXpathInfo, fileName string) { for i, kd := range d.keyXpath { fmt.Fprintf(fp, " %d. %#v\r\n", i, kd) } + fmt.Fprintf(fp, "\r\n isKey : %v\r\n", d.isKey) } fmt.Fprintf (fp, "-----------------------------------------------------------------\r\n") From c04c457cc47561ba14f5f8ddcb4efe6522ba6688 Mon Sep 17 00:00:00 2001 From: amrutasali Date: Sun, 8 Sep 2019 21:02:56 +0000 Subject: [PATCH 097/214] For Get case added support to retrieve attributes in config conatainers that serve as the keys for list enclosing that config conatiner. eg acl-entry/config/sequenec-id --- .../annotations/openconfig-acl-annot.yang | 12 +++++ src/translib/transformer/xfmr_acl.go | 53 ++++++++++++++++++- 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/models/yang/annotations/openconfig-acl-annot.yang b/models/yang/annotations/openconfig-acl-annot.yang index c5292ee245..812db798b8 100644 --- a/models/yang/annotations/openconfig-acl-annot.yang +++ b/models/yang/annotations/openconfig-acl-annot.yang @@ -16,6 +16,12 @@ module openconfig-acl-annot { } } + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:config/oc-acl:name { + deviate add { + sonic-ext:field-transformer "acl_set_name_xfmr"; + } + } + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:config/oc-acl:description { deviate add { sonic-ext:field-name "policy_desc"; @@ -29,6 +35,12 @@ module openconfig-acl-annot { } } + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-acl:config/oc-acl:sequence-id { + deviate add { + sonic-ext:field-transformer "acl_entry_sequenceid_xfmr"; + } + } + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-pkt-match:ipv4/oc-pkt-match:config/oc-pkt-match:source-address { deviate add { sonic-ext:field-name "SRC_IP"; diff --git a/src/translib/transformer/xfmr_acl.go b/src/translib/transformer/xfmr_acl.go index 3a16a56ee1..3720d6ecaf 100644 --- a/src/translib/transformer/xfmr_acl.go +++ b/src/translib/transformer/xfmr_acl.go @@ -15,8 +15,12 @@ import ( ) func init () { + XlateFuncBind("YangToDb_acl_set_name_xfmr", YangToDb_acl_set_name_xfmr) + XlateFuncBind("DbToYang_acl_set_name_xfmr", DbToYang_acl_set_name_xfmr) XlateFuncBind("YangToDb_acl_entry_key_xfmr", YangToDb_acl_entry_key_xfmr) XlateFuncBind("DbToYang_acl_entry_key_xfmr", DbToYang_acl_entry_key_xfmr) + XlateFuncBind("YangToDb_acl_entry_sequenceid_xfmr", YangToDb_acl_entry_sequenceid_xfmr) + XlateFuncBind("DbToYang_acl_entry_sequenceid_xfmr", DbToYang_acl_entry_sequenceid_xfmr) XlateFuncBind("YangToDb_acl_l2_ethertype_xfmr", YangToDb_acl_l2_ethertype_xfmr) XlateFuncBind("DbToYang_acl_l2_ethertype_xfmr", DbToYang_acl_l2_ethertype_xfmr) XlateFuncBind("YangToDb_acl_ip_protocol_xfmr", YangToDb_acl_ip_protocol_xfmr) @@ -185,6 +189,26 @@ func getL2EtherType(etherType uint64) interface{} { return uint16(etherType) } +var YangToDb_acl_set_name_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, opType int, xpath string, name interface {}) (map[string]string, error) { + res_map := make(map[string]string) + var err error + log.Info("YangToDb_acl_set_name_xfmr: ") + /*no-op since there is no redis table field to be filled corresponding to name attribute since its part of key */ + return res_map, err +} + +var DbToYang_acl_set_name_xfmr FieldXfmrDbtoYang = func (d *db.DB, opType int, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct, key string) (map[string]interface{}, error) { + res_map := make(map[string]interface{}) + var err error + log.Info("DbToYang_acl_set_name_xfmr: ", key) + /*name attribute corresponds to key in redis table*/ + aclName, _ := getOCAclKeysFromStrDBKey(key) + res_map["name"] = aclName + log.Info("acl-set/config/name ", res_map) + return res_map, err +} + + var YangToDb_acl_entry_key_xfmr KeyXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, opType int, xpath string) (string, error) { var entry_key string var err error @@ -233,6 +257,33 @@ var DbToYang_acl_entry_key_xfmr KeyXfmrDbToYang = func (d *db.DB, opType int, en return rmap, err } +var YangToDb_acl_entry_sequenceid_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, opType int, xpath string, sequence_id interface {}) (map[string]string, error) { + res_map := make(map[string]string) + var err error + log.Info("YangToDb_acl_entry_sequenceid_xfmr: ") + /*no-op since there is no redis table field to be filled corresponding to sequenec-id attribute since its part of key */ + return res_map, err +} + +var DbToYang_acl_entry_sequenceid_xfmr FieldXfmrDbtoYang = func (d *db.DB, opType int, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct, key string) (map[string]interface{}, error) { + res_map := make(map[string]interface{}) + var err error + log.Info("DbToYang_acl_entry_sequenceid_xfmr: ", key) + /*sequenec-id attribute corresponds to key in redis table*/ + res, err := DbToYang_acl_entry_key_xfmr(d, opType, key) + log.Info("acl-entry/config/sequence-id ", res) + if err != nil { + return res_map, err + } + if seqId, ok := res["sequence-id"]; !ok { + log.Error("sequence-id not found in acl entry") + return res_map, err + } else { + res_map["sequence-id"] = seqId + } + return res_map, err +} + var YangToDb_acl_l2_ethertype_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, opType int, xpath string, ethertype interface {}) (map[string]string, error) { res_map := make(map[string]string) var err error @@ -978,7 +1029,7 @@ func getAllBindingsInfo(aclTableMap map[string]db.Value, ruleTableMap map[string } } } - + //ygot.BuildEmptyTree(acl) for _, intfId := range interfaces { var intfData *ocbinds.OpenconfigAcl_Acl_Interfaces_Interface intfData, ok := acl.Interfaces.Interface[intfId] From c809ad059065827b58541e2dc6ea1d1b8813698a Mon Sep 17 00:00:00 2001 From: s-mari Date: Mon, 9 Sep 2019 14:41:51 -0700 Subject: [PATCH 098/214] Added map-format output data for get-request --- src/translib/transformer/xfmr_acl.go | 3 +- src/translib/transformer/xlate_from_db.go | 230 ++++++++++------------ src/translib/transformer/xlate_utils.go | 65 +++++- 3 files changed, 169 insertions(+), 129 deletions(-) diff --git a/src/translib/transformer/xfmr_acl.go b/src/translib/transformer/xfmr_acl.go index 3a16a56ee1..93ab3cca33 100644 --- a/src/translib/transformer/xfmr_acl.go +++ b/src/translib/transformer/xfmr_acl.go @@ -860,7 +860,6 @@ var YangToDb_acl_port_bindings_xfmr SubTreeXfmrYangToDb = func (d *db.DB, ygRoot var DbToYang_acl_port_bindings_xfmr SubTreeXfmrDbToYang = func (d *db.DB, opType int, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct, xpath string) (error) { var err error log.Info("DbToYang_acl_port_bindings_xfmr: ", data, ygRoot) - return nil aclTbl, ruleTbl, err := getDbAlcTblsData(d) @@ -978,7 +977,7 @@ func getAllBindingsInfo(aclTableMap map[string]db.Value, ruleTableMap map[string } } } - + ygot.BuildEmptyTree(acl) for _, intfId := range interfaces { var intfData *ocbinds.OpenconfigAcl_Acl_Interfaces_Interface intfData, ok := acl.Interfaces.Interface[intfId] diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index d5c93efd7f..1234f12ba3 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -4,6 +4,7 @@ import ( "fmt" "translib/db" "strings" + "encoding/json" "os" "translib/ocbinds" "github.com/openconfig/ygot/ygot" @@ -12,6 +13,8 @@ import ( log "github.com/golang/glog" ) +type typeMapOfInterface map[string]interface{} + func xfmrHandlerFunc(d *db.DB, xpath string, uri string, ygRoot *ygot.GoStruct, dbDataMap map[string]map[string]db.Value) (string, error) { _, err := XlateFuncCall(dbToYangXfmrFunc(xSpecMap[xpath].xfmrFunc), d, GET, dbDataMap, ygRoot) if err != nil { @@ -48,11 +51,11 @@ func xfmrHandlerFunc(d *db.DB, xpath string, uri string, ygRoot *ygot.GoStruct, return payload, err } -func leafXfmrHandlerFunc(d *db.DB, xpath string, uri string, ygRoot *ygot.GoStruct, dbDataMap map[string]map[string]db.Value) (string, error) { +func leafXfmrHandlerFunc(d *db.DB, xpath string, uri string, ygRoot *ygot.GoStruct, dbDataMap map[string]map[string]db.Value) (map[string]interface{}, string, error) { _, keyName, _ := xpathKeyExtract(d, ygRoot, GET, uri) ret, err := XlateFuncCall(dbToYangXfmrFunc(xSpecMap[xpath].xfmrFunc), d, GET, dbDataMap, ygRoot, keyName) if err != nil { - return "", err + return nil, "", err } fldValMap := ret[0].Interface().(map[string]interface{}) data := "" @@ -60,102 +63,9 @@ func leafXfmrHandlerFunc(d *db.DB, xpath string, uri string, ygRoot *ygot.GoStru value := fmt.Sprintf("%v", v) data += fmt.Sprintf("\"%v\" : \"%v\",", f, value) } - return data, nil -} - -/* Traverse db map and add data to json */ -func dataToJsonAdd(uri string, xpath string, ygRoot *ygot.GoStruct, fieldData map[string]string, key string, dbDataMap map[string]map[string]db.Value) (string, error) { - spec, ok := xSpecMap[xpath] - jsonData := "" - - if ok { - for fld := range spec.yangEntry.Dir { - fldXpath := xpath+"/"+fld - curUri := uri+"/"+fld - if xSpecMap[fldXpath] != nil && xSpecMap[fldXpath].yangEntry != nil { - ftype := yangTypeGet(xSpecMap[fldXpath].yangEntry) - if ftype == "leaf" { - if len(xSpecMap[fldXpath].xfmrFunc) > 0 { - /* field transformer present */ - jsonStr, err := leafXfmrHandlerFunc(nil, fldXpath, curUri, ygRoot, dbDataMap) - if err != nil { - return "", err - } - jsonData += jsonStr - } else { - /* Add db field and value to json, call xfmr if needed */ - fldName := xSpecMap[fldXpath].fieldName - if len(fldName) > 0 && !xSpecMap[fldXpath].isKey { - val, ok := fieldData[fldName] - if ok { - jsonData += fmt.Sprintf("\"%v\" : \"%v\",", xSpecMap[fldXpath].yangEntry.Name, val) - } - } - } - } else if ftype == "container" && xSpecMap[fldXpath].yangEntry.Name != "state" { - if len(xSpecMap[fldXpath].xfmrFunc) > 0 { - jsonStr, _ := xfmrHandlerFunc(nil, fldXpath, curUri, ygRoot, dbDataMap) - jsonData += jsonStr - } else { - /* Create container enclosure and attach container name and add to json */ - data, _:= dataToJsonAdd(curUri, fldXpath, ygRoot, fieldData, key, dbDataMap) - if len(data) > 0 { - jsonData += fmt.Sprintf("\"%v\" : { \r\n %v \r\n },", - xSpecMap[fldXpath].yangEntry.Name, data) - } - } - } else if ftype == "list" { - if len(xSpecMap[fldXpath].xfmrFunc) > 0 { - jsonStr , _ := xfmrHandlerFunc(nil, fldXpath, curUri, ygRoot, dbDataMap) - jsonData += jsonStr - } else { - /* Inner(child) list, traverse this list */ - childMap, ok := dbDataMap[*xSpecMap[fldXpath].tableName] - if ok { - var xpathl []string - xpathl = append(xpathl, fldXpath) - jsonData += listDataToJsonAdd(curUri, ygRoot, xpathl, childMap, key, dbDataMap) - } - } - } - } - } - /* Last node in json data in current context, trim extra "," in data, so that json data is valid */ - jsonData = strings.TrimRight(jsonData, ",") - } - return jsonData, nil + return fldValMap, data, nil } -/* Traverse list data and add to json */ -func listDataToJsonAdd(uri string, ygRoot *ygot.GoStruct, xpathl []string, dataMap map[string]db.Value, key string, dbDataMap map[string]map[string]db.Value) string { - jsonData := "" - - for _, xpath := range xpathl { - for kval, data := range dataMap { - if len(key) > 0 && !strings.HasPrefix(kval, key) { - continue - } - curUri, kdata, _ := dbKeyToYangDataConvert(uri, xpath, kval) - /* Traverse list members and add to json */ - data, _ := dataToJsonAdd(curUri, xpath, ygRoot, data.Field, kval, dbDataMap) - data = kdata + data - if len(data) > 0 { - /* Enclose all list instances with {} */ - jsonData += fmt.Sprintf("{\r\n %v },", data) - } - /* Added data to json, so delete current instance data */ - delete(dataMap, kval) - } - if len(jsonData) > 0 { - /* Last data in list,so trim extra "," in data, so that the json is valid */ - jsonData = strings.TrimRight(jsonData, ",") - /* Create list enclosure, attach list-name and add to json */ - jsonData = fmt.Sprintf("\"%v\" : [\r\n %v\r\n ]\r\n", xSpecMap[xpath].yangEntry.Name, jsonData) - } - } - jsonData = strings.TrimRight(jsonData, ",") - return jsonData -} /* Traverse db map and create json for cvl yang */ func directDbToYangJsonCreate(dbDataMap map[string]map[string]db.Value, jsonData string) string { @@ -189,24 +99,110 @@ func tableNameAndKeyFromDbMapGet(dbDataMap map[string]map[string]db.Value) (stri return tableName, tableKey, nil } +func yangListDataFill(d *db.DB, ygRoot *ygot.GoStruct, uri string, xpath string, dbDataMap map[string]map[string]db.Value, resultMap map[string]interface{}, tbl string, tblKey string) error { + tblData, ok := dbDataMap[tbl] + + if ok { + var mapSlice []typeMapOfInterface + for dbKey, _ := range tblData { + curMap := make(map[string]interface{}) + curKeyMap, curUri, _, _ := dbKeyToYangDataConvert(uri, xpath, dbKey) + if len(xSpecMap[xpath].xfmrFunc) > 0 { + jsonStr, _ := xfmrHandlerFunc(d, xpath, curUri, ygRoot, dbDataMap) + fmt.Printf("From leaf-xfmr(%v)\r\n", jsonStr) + } else { + _, keyFromCurUri, _ := xpathKeyExtract(d, ygRoot, GET, curUri) + if dbKey == keyFromCurUri { + for k, kv := range curKeyMap { + curMap[k] = kv + } + curXpath, _ := RemoveXPATHPredicates(curUri) + yangDataFill(d, ygRoot, curUri, curXpath, dbDataMap, curMap, tbl, dbKey) + mapSlice = append(mapSlice, curMap) + } + } + } + if len(mapSlice) > 0 { + resultMap[xSpecMap[xpath].yangEntry.Name] = mapSlice + } else { + fmt.Printf("Map slice is empty.\r\n ") + } + } + return nil +} + +func yangDataFill(d *db.DB, ygRoot *ygot.GoStruct, uri string, xpath string, dbDataMap map[string]map[string]db.Value, resultMap map[string]interface{}, tbl string, tblKey string) error { + var err error + yangNode, ok := xSpecMap[xpath] + + if ok && yangNode.yangEntry != nil { + for yangChldName := range yangNode.yangEntry.Dir { + chldXpath := xpath+"/"+yangChldName + chldUri := uri+"/"+yangChldName + if xSpecMap[chldXpath] != nil && xSpecMap[chldXpath].yangEntry != nil { + chldYangType := yangTypeGet(xSpecMap[chldXpath].yangEntry) + if chldYangType == "leaf" { + if len(xSpecMap[chldXpath].xfmrFunc) > 0 { + fldValMap, _, err := leafXfmrHandlerFunc(nil, chldXpath, chldUri, ygRoot, dbDataMap) + if err != nil { + return err + } + for lf, val := range fldValMap { + resultMap[lf] = val + } + } else { + dbFldName := xSpecMap[chldXpath].fieldName + if len(dbFldName) > 0 && !xSpecMap[chldXpath].isKey { + val, ok := dbDataMap[tbl][tblKey].Field[dbFldName] + if ok { + resultMap[xSpecMap[chldXpath].yangEntry.Name] = val + } + } + } + } else if chldYangType == "container" { + if len(xSpecMap[chldXpath].xfmrFunc) > 0 { + jsonStr, _ := xfmrHandlerFunc(nil, chldXpath, chldUri, ygRoot, dbDataMap) + fmt.Printf("From container-xfmr(%v)\r\n", jsonStr) + } else { + cname := xSpecMap[chldXpath].yangEntry.Name + cmap := make(map[string]interface{}) + err = yangDataFill(d, ygRoot, chldUri, chldXpath, dbDataMap, cmap, tbl, tblKey) + if len(cmap) > 0 { + resultMap[cname] = cmap + } else { + fmt.Printf("container : empty(%v) \r\n", cname) + } + } + } else if chldYangType == "list" { + if len(xSpecMap[chldXpath].xfmrFunc) > 0 { + jsonStr , _ := xfmrHandlerFunc(nil, chldXpath, chldUri, ygRoot, dbDataMap) + fmt.Printf("From list-xfmr(%v)\r\n", jsonStr) + } else { + ynode, ok := xSpecMap[chldXpath] + if ok && ynode.tableName != nil { + lTblName := *ynode.tableName + yangListDataFill(d, ygRoot, chldUri, chldXpath, dbDataMap, resultMap, lTblName, "") + } + } + } else { + return err + } + } + } + } + return err +} + /* Traverse linear db-map data and add to nested json data */ func dbDataToYangJsonCreate(uri string, ygRoot *ygot.GoStruct, dbDataMap map[string]map[string]db.Value) (string, error) { jsonData := "" - moduleNm, err := uriModuleNameGet(uri) - if err != nil { - return jsonData, err - } - tableOrder, err := GetOrdDBTblList(moduleNm) - if err != nil { - return jsonData, err - } if isCvlYang(uri) { jsonData := directDbToYangJsonCreate(dbDataMap, jsonData) jsonDataPrint(jsonData) return jsonData, nil } - reqXpath, _, _ := xpathKeyExtract(nil, nil, GET, uri) + reqXpath, keyName, tableName := xpathKeyExtract(nil, nil, GET, uri) ftype := yangTypeGet(xSpecMap[reqXpath].yangEntry) if ftype == "leaf" { fldName := xSpecMap[reqXpath].fieldName @@ -216,24 +212,12 @@ func dbDataToYangJsonCreate(uri string, ygRoot *ygot.GoStruct, dbDataMap map[str return jsonData, nil } - curXpath := "" - for tblId := range tableOrder { - tblName := tableOrder[tblId] - if dbDataMap[tblName] != nil { - if len(curXpath) == 0 || strings.HasPrefix(curXpath, xDbSpecMap[tblName].yangXpath[0]) { - curXpath = xDbSpecMap[tblName].yangXpath[0] - } - jsonData += listDataToJsonAdd(uri, ygRoot, xDbSpecMap[tblName].yangXpath, dbDataMap[tblName], "", dbDataMap) - } - } - if strings.HasPrefix(reqXpath, curXpath) { - if ftype != "leaf" { - jsonData = fmt.Sprintf("{ \r\n %v \r\n }", jsonData) - } - return jsonData, nil - } - jsonData = parentJsonDataUpdate(reqXpath, curXpath, jsonData) - jsonDataPrint(jsonData) + resultMap := make(map[string]interface{}) + var d *db.DB + yangDataFill(d, ygRoot, uri, reqXpath, dbDataMap, resultMap, tableName, keyName) + jsonMapData, _ := json.Marshal(resultMap) + jsonData = fmt.Sprintf("%v", string(jsonMapData)) + jsonDataPrint(jsonData) return jsonData, nil } diff --git a/src/translib/transformer/xlate_utils.go b/src/translib/transformer/xlate_utils.go index bcf6ac4147..b8540e1c5e 100644 --- a/src/translib/transformer/xlate_utils.go +++ b/src/translib/transformer/xlate_utils.go @@ -3,6 +3,7 @@ package transformer import ( "fmt" "strings" + "reflect" "translib/db" "github.com/openconfig/goyang/pkg/yang" "github.com/openconfig/gnmi/proto/gnmi" @@ -83,7 +84,7 @@ func yangTypeGet(entry *yang.Entry) string { return "" } -func dbKeyToYangDataConvert(uri string, xpath string, dbKey string) (string, string, error) { +func dbKeyToYangDataConvert(uri string, xpath string, dbKey string) (map[string]string, string, string, error) { var kLvlValList []string keyDataList := strings.Split(dbKey, "|") keyNameList := yangKeyFromEntryGet(xSpecMap[xpath].yangEntry) @@ -100,14 +101,14 @@ func dbKeyToYangDataConvert(uri string, xpath string, dbKey string) (string, str var d *db.DB ret, err := XlateFuncCall(dbToYangXfmrFunc(xSpecMap[xpath].xfmrKey), d, GET, dbKey) if err != nil { - return "","",err + return nil, "","",err } rmap := ret[0].Interface().(map[string]string) for k, v := range rmap { jsonData += fmt.Sprintf("\"%v\" : \"%v\",\r\n", k, v) uriWithKey += fmt.Sprintf("[%v=%v]", k, v) } - return uriWithKey, jsonData, nil + return rmap, uriWithKey, jsonData, nil } kLvlValList = append(kLvlValList, keyDataList[id]) @@ -123,6 +124,7 @@ func dbKeyToYangDataConvert(uri string, xpath string, dbKey string) (string, str chgId = len(keyNameList) - 1 } + rmap := make(map[string]string) for i, kname := range keyNameList { kval := kLvlValList[i] @@ -133,9 +135,10 @@ func dbKeyToYangDataConvert(uri string, xpath string, dbKey string) (string, str jsonData += fmt.Sprintf("\"%v\" : \"%v\",", kname, kval) uriWithKey += fmt.Sprintf("[%v=%v]", kname, kval) + rmap[kname] = kval } - return uriWithKey, jsonData, nil + return rmap, uriWithKey, jsonData, nil } @@ -252,3 +255,57 @@ func uriModuleNameGet(uri string) (string, error) { log.Info("module name = ", result) return result, err } + +func recMap(rMap interface{}, name []string, id int, max int) { + if id == max { + return + } + val := name[id] + if reflect.ValueOf(rMap).Kind() == reflect.Map { + data := reflect.ValueOf(rMap) + dMap := data.Interface().(map[string]interface{}) + _, ok := dMap[val] + if ok { + recMap(dMap[val], name, id+1, max) + } else { + dMap[val] = make(map[string]interface{}) + recMap(dMap[val], name, id+1, max) + } + } + return +} + +func mapCreate(xpath string) map[string]interface{} { + retMap := make(map[string]interface{}) + attrList := strings.Split(xpath, "/") + alLen := len(attrList) + recMap(retMap, attrList, 1, alLen) + return retMap +} + +func mapInstGet(name []string, id int, max int, inMap interface{}) map[string]interface{} { + result := reflect.ValueOf(inMap).Interface().(map[string]interface{}) + if id == max { + return result + } + val := name[id] + if reflect.ValueOf(inMap).Kind() == reflect.Map { + data := reflect.ValueOf(inMap) + dMap := data.Interface().(map[string]interface{}) + _, ok := dMap[val] + if ok { + result = mapInstGet(name, id+1, max, dMap[val]) + } else { + return result + } + } + return result +} + +func mapGet(xpath string, inMap map[string]interface{}) map[string]interface{} { + attrList := strings.Split(xpath, "/") + alLen := len(attrList) + recMap(inMap, attrList, 1, alLen) + retMap := mapInstGet(attrList, 1, alLen, inMap) + return retMap +} From d45ca090d849135329a003c8e4ab0cc3e8ce6a6f Mon Sep 17 00:00:00 2001 From: justinejose91 Date: Mon, 9 Sep 2019 15:53:46 -0700 Subject: [PATCH 099/214] Addressing the crash when max mtu is set as 9276. Currently supported max-mtu is 9216. --- src/CLI/clitree/cli-xml/sonic_types.xml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/CLI/clitree/cli-xml/sonic_types.xml b/src/CLI/clitree/cli-xml/sonic_types.xml index b8259d35af..7b4a108eda 100644 --- a/src/CLI/clitree/cli-xml/sonic_types.xml +++ b/src/CLI/clitree/cli-xml/sonic_types.xml @@ -1,5 +1,6 @@ @@ -47,9 +48,9 @@ Date: Mon, 9 Sep 2019 19:47:00 -0700 Subject: [PATCH 100/214] enhanced transformer to handle leaf level get-req --- src/translib/transformer/xlate.go | 28 ++---------------- src/translib/transformer/xlate_from_db.go | 36 +++++++++++++---------- src/translib/transformer/xlate_to_db.go | 13 ++++---- src/translib/transformer/xspec.go | 1 + 4 files changed, 29 insertions(+), 49 deletions(-) diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index 9ac1a8a769..4258d720a9 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -2,9 +2,6 @@ package transformer import ( "fmt" - //"os" - // "sort" - // "github.com/openconfig/goyang/pkg/yang" "encoding/json" "errors" log "github.com/golang/glog" @@ -290,38 +287,21 @@ func GetAndXlateFromDB(xpath string, ygRoot *ygot.GoStruct, dbs [db.MaxDB]*db.DB func XlateFromDb(xpath string, ygRoot *ygot.GoStruct, data map[string]map[string]db.Value) ([]byte, error) { var err error - var fieldName, tableName, yangXpath string var dbData = make(map[string]map[string]db.Value) dbData = data if isCvlYang(xpath) { - yXpath, keyStr, tableName := sonicXpathKeyExtract(xpath) - yangXpath = yXpath + yangXpath, keyStr, tableName := sonicXpathKeyExtract(xpath) if (tableName != "") { tokens:= strings.Split(yangXpath, "/") // Format /module:container/tableName[key]/fieldName if tokens[len(tokens)-2] == tableName { - fieldName = tokens[len(tokens)-1] + fieldName := tokens[len(tokens)-1] dbData = extractFieldFromDb(tableName, keyStr, fieldName, data) } } - } else { - yXpath, keyStr, _ := xpathKeyExtract(nil, nil, 0, xpath) - yangXpath = yXpath - if xSpecMap == nil { - return nil, err - } - _, ok := xSpecMap[yangXpath] - if !ok { - return nil, err - } - if xSpecMap[yangXpath].yangDataType == "leaf" { - fieldName = xSpecMap[yangXpath].fieldName - tableName = *xSpecMap[yangXpath].tableName - dbData = extractFieldFromDb(tableName, keyStr, fieldName, data) - } } - payload, err := dbDataToYangJsonCreate(yangXpath, ygRoot, dbData) + payload, err := dbDataToYangJsonCreate(xpath, ygRoot, dbData) if err != nil { log.Errorf("Error: failed to create json response from DB data.") @@ -329,8 +309,6 @@ func XlateFromDb(xpath string, ygRoot *ygot.GoStruct, data map[string]map[string } result := []byte(payload) - - //TODO - implement me return result, err } diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index 1234f12ba3..eaac0c0087 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -113,12 +113,12 @@ func yangListDataFill(d *db.DB, ygRoot *ygot.GoStruct, uri string, xpath string, } else { _, keyFromCurUri, _ := xpathKeyExtract(d, ygRoot, GET, curUri) if dbKey == keyFromCurUri { - for k, kv := range curKeyMap { - curMap[k] = kv - } - curXpath, _ := RemoveXPATHPredicates(curUri) - yangDataFill(d, ygRoot, curUri, curXpath, dbDataMap, curMap, tbl, dbKey) - mapSlice = append(mapSlice, curMap) + for k, kv := range curKeyMap { + curMap[k] = kv + } + curXpath, _ := RemoveXPATHPredicates(curUri) + yangDataFill(d, ygRoot, curUri, curXpath, dbDataMap, curMap, tbl, dbKey) + mapSlice = append(mapSlice, curMap) } } } @@ -202,19 +202,23 @@ func dbDataToYangJsonCreate(uri string, ygRoot *ygot.GoStruct, dbDataMap map[str return jsonData, nil } - reqXpath, keyName, tableName := xpathKeyExtract(nil, nil, GET, uri) - ftype := yangTypeGet(xSpecMap[reqXpath].yangEntry) - if ftype == "leaf" { - fldName := xSpecMap[reqXpath].fieldName - tbl, key, _ := tableNameAndKeyFromDbMapGet(dbDataMap) - jsonData = fmt.Sprintf("{\r\n \"%v\" : \"%v\" \r\n }\r\n", xSpecMap[reqXpath].yangEntry.Name, + var d *db.DB + resultMap := make(map[string]interface{}) + reqXpath, keyName, tableName := xpathKeyExtract(d, ygRoot, GET, uri) + yangNode, ok := xSpecMap[reqXpath] + if ok { + yangType := yangTypeGet(yangNode.yangEntry) + if yangType == "leaf" { + fldName := xSpecMap[reqXpath].fieldName + tbl, key, _ := tableNameAndKeyFromDbMapGet(dbDataMap) + jsonData = fmt.Sprintf("{\r\n \"%v\" : \"%v\" \r\n }\r\n", xSpecMap[reqXpath].yangEntry.Name, dbDataMap[tbl][key].Field[fldName]) - return jsonData, nil + return jsonData, nil + } else { + yangDataFill(d, ygRoot, uri, reqXpath, dbDataMap, resultMap, tableName, keyName) + } } - resultMap := make(map[string]interface{}) - var d *db.DB - yangDataFill(d, ygRoot, uri, reqXpath, dbDataMap, resultMap, tableName, keyName) jsonMapData, _ := json.Marshal(resultMap) jsonData = fmt.Sprintf("%v", string(jsonMapData)) jsonDataPrint(jsonData) diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index dfbd116c03..52dd9bea1c 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -359,15 +359,13 @@ func xpathKeyExtract(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string) (st curPathWithKey := "" for _, k := range strings.Split(path, "/") { - xpath := k curPathWithKey += k if strings.Contains(k, "[") { if len(keyStr) > 0 { keyStr += "|" } yangXpath, _ := RemoveXPATHPredicates(curPathWithKey) - xpath = strings.Split(k, "[")[0] - _, ok := xSpecMap[yangXpath] + _, ok := xSpecMap[yangXpath] if ok { if len(xSpecMap[yangXpath].xfmrKey) > 0 { xfmrFuncName := yangToDbXfmrFunc(xSpecMap[yangXpath].xfmrKey) @@ -384,15 +382,14 @@ func xpathKeyExtract(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string) (st keyStr += keyFromXpathCreate(keyl) } } - if isCvlYang(path) { - //Format- /module:container/table[key]/field - // table name extracted from the string token having key entry - tableName = xpath - } } curPathWithKey += "/" } pfxPath, _ := RemoveXPATHPredicates(path) + tblPtr := xSpecMap[pfxPath].tableName + if tblPtr != nil { + tableName = *tblPtr + } return pfxPath, keyStr, tableName } diff --git a/src/translib/transformer/xspec.go b/src/translib/transformer/xspec.go index c4a3580687..fd4bb28b3d 100644 --- a/src/translib/transformer/xspec.go +++ b/src/translib/transformer/xspec.go @@ -350,6 +350,7 @@ func mapPrint(inMap map[string]*yangXpathInfo, fileName string) { if d.tableName != nil { fmt.Fprintf(fp, "%v", *d.tableName) } + fmt.Fprintf(fp, "\r\n childTbl : %v", d.childTable) fmt.Fprintf(fp, "\r\n FieldName: %v", d.fieldName) fmt.Fprintf(fp, "\r\n keyLevel : %v", d.keyLevel) fmt.Fprintf(fp, "\r\n xfmrKeyFn: %v", d.xfmrKey) From bd0d89648a08bf2e5cc482a636da8aab9f9a2bec Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Mon, 9 Sep 2019 21:15:00 -0700 Subject: [PATCH 101/214] Initial Traverse multi DB support --- src/translib/acl_app.go | 18 +---- src/translib/transformer/xlate.go | 80 ++++++++++++----------- src/translib/transformer/xlate_from_db.go | 34 +++++----- 3 files changed, 61 insertions(+), 71 deletions(-) diff --git a/src/translib/acl_app.go b/src/translib/acl_app.go index 55a83be0e2..e5df355d9d 100644 --- a/src/translib/acl_app.go +++ b/src/translib/acl_app.go @@ -183,25 +183,10 @@ func (app *AclApp) processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error) { var err error var payload []byte - keyspec, err := transformer.XlateUriToKeySpec(app.pathInfo.Path, app.ygotRoot, app.ygotTarget) - - // table.key.fields - var result = make(map[string]map[string]db.Value) - - for dbnum, specs := range *keyspec { - for _, spec := range specs { - err := transformer.TraverseDb(dbs[dbnum], spec, &result, nil) - if err != nil { - return GetResponse{Payload: payload}, err - } - } - } - - payload, err = transformer.XlateFromDb(app.pathInfo.Path, app.ygotRoot, result) + payload, err = transformer.GetAndXlateFromDB(app.pathInfo.Path, app.ygotRoot, dbs) if err != nil { return GetResponse{Payload: payload, ErrSrc: AppErr}, err } - return GetResponse{Payload: payload}, err } @@ -209,6 +194,7 @@ func (app *AclApp) translateCRUDCommon(d *db.DB, opcode int) ([]db.WatchKeys, er var err error var keys []db.WatchKeys log.Info("translateCRUDCommon:acl:path =", app.pathInfo.Path) + d.Opts.DisableCVLCheck = true; result, err := transformer.XlateToDb(app.pathInfo.Path, opcode, d, app.ygotRoot, app.ygotTarget) if err != nil { diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index 4258d720a9..d320854edb 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -21,6 +21,7 @@ const ( ) type KeySpec struct { + dbNum db.DBNum Ts db.TableSpec Key db.Key Child []KeySpec @@ -66,30 +67,30 @@ func XlateFuncCall(name string, params ...interface{}) (result []reflect.Value, return } -func TraverseDb(d *db.DB, spec KeySpec, result *map[string]map[string]db.Value, parentKey *db.Key) error { +func TraverseDb(dbs [db.MaxDB]*db.DB, spec KeySpec, result *map[db.DBNum]map[string]map[string]db.Value, parentKey *db.Key) error { var err error if spec.Key.Len() > 0 { // get an entry with a specific key - data, err := d.GetEntry(&spec.Ts, spec.Key) + data, err := dbs[spec.dbNum].GetEntry(&spec.Ts, spec.Key) if err != nil { return err } - if (*result)[spec.Ts.Name] == nil { - (*result)[spec.Ts.Name] = map[string]db.Value{strings.Join(spec.Key.Comp, "|"): data} + if (*result)[spec.dbNum][spec.Ts.Name] == nil { + (*result)[spec.dbNum][spec.Ts.Name] = map[string]db.Value{strings.Join(spec.Key.Comp, "|"): data} } else { - (*result)[spec.Ts.Name][strings.Join(spec.Key.Comp, "|")] = data + (*result)[spec.dbNum][spec.Ts.Name][strings.Join(spec.Key.Comp, "|")] = data } if len(spec.Child) > 0 { for _, ch := range spec.Child { - err = TraverseDb(d, ch, result, &spec.Key) + err = TraverseDb(dbs, ch, result, &spec.Key) } } } else { // TODO - GetEntry suuport with regex patten, 'abc*' for optimization - keys, err := d.GetKeys(&spec.Ts) + keys, err := dbs[spec.dbNum].GetKeys(&spec.Ts) if err != nil { return err } @@ -101,35 +102,29 @@ func TraverseDb(d *db.DB, spec KeySpec, result *map[string]map[string]db.Value, } } spec.Key = keys[i] - err = TraverseDb(d, spec, result, parentKey) + err = TraverseDb(dbs, spec, result, parentKey) } } return err } -func XlateUriToKeySpec(path string, ygRoot *ygot.GoStruct, t *interface{}) (*map[db.DBNum][]KeySpec, error) { +func XlateUriToKeySpec(uri string, ygRoot *ygot.GoStruct, t *interface{}) (*[]KeySpec, error) { var err error - var result = make(map[db.DBNum][]KeySpec) var retdbFormat = make([]KeySpec, 0) - // default DB number to read from - var dbInx db.DBNum = db.ConfigDB // In case of CVL yang, the tablename and key info is available in the xpath - if isCvlYang(path) { + if isCvlYang(uri) { /* Extract the xpath and key from input xpath */ - yangXpath, keyStr, tableName := sonicXpathKeyExtract(path) + yangXpath, keyStr, tableName := sonicXpathKeyExtract(uri) retdbFormat = fillCvlKeySpec(yangXpath, tableName, keyStr) } else { /* Extract the xpath and key from input xpath */ - yangXpath, keyStr, _ := xpathKeyExtract(nil, ygRoot, 0, path) + yangXpath, keyStr, _ := xpathKeyExtract(nil, ygRoot, 0, uri) retdbFormat = FillKeySpecs(yangXpath, keyStr, &retdbFormat) - dbInx = getDbNum(yangXpath) } - result[dbInx] = retdbFormat - - return &result, err + return &retdbFormat, err } func FillKeySpecs(yangXpath string , keyStr string, retdbFormat *[]KeySpec) ([]KeySpec){ @@ -142,6 +137,7 @@ func FillKeySpecs(yangXpath string , keyStr string, retdbFormat *[]KeySpec) ([]K if xpathInfo.tableName != nil { dbFormat := KeySpec{} dbFormat.Ts.Name = *xpathInfo.tableName + dbFormat.dbNum = xpathInfo.dbIndex if keyStr != "" { dbFormat.Key.Comp = append(dbFormat.Key.Comp, keyStr) } @@ -181,6 +177,7 @@ func fillCvlKeySpec(yangXpath string , tableName string, keyStr string) ( []KeyS if tableName != "" { dbFormat := KeySpec{} dbFormat.Ts.Name = tableName + dbFormat.dbNum = db.ConfigDB if keyStr != "" { dbFormat.Key.Comp = append(dbFormat.Key.Comp, keyStr) } @@ -195,6 +192,7 @@ func fillCvlKeySpec(yangXpath string , tableName string, keyStr string) ( []KeyS for dir, _ := range dbInfo.dbEntry.Dir { dbFormat := KeySpec{} dbFormat.Ts.Name = dir + dbFormat.dbNum = db.ConfigDB retdbFormat = append(retdbFormat, dbFormat) } } @@ -258,25 +256,26 @@ func XlateToDb(path string, opcode int, d *db.DB, yg *ygot.GoStruct, yt *interfa return result, err } -func GetAndXlateFromDB(xpath string, ygRoot *ygot.GoStruct, dbs [db.MaxDB]*db.DB) ([]byte, error) { +func GetAndXlateFromDB(uri string, ygRoot *ygot.GoStruct, dbs [db.MaxDB]*db.DB) ([]byte, error) { var err error var payload []byte - log.Info("received xpath =", xpath) + log.Info("received xpath =", uri) - keySpec, err := XlateUriToKeySpec(xpath, ygRoot, nil) - var result = make(map[string]map[string]db.Value) + keySpec, err := XlateUriToKeySpec(uri, ygRoot, nil) + var dbresult = make(map[db.DBNum]map[string]map[string]db.Value) + for i := db.ApplDB; i < db.MaxDB; i++ { + dbresult[i] = make(map[string]map[string]db.Value) + } - for dbnum, specs := range *keySpec { - for _, spec := range specs { - err := TraverseDb(dbs[dbnum], spec, &result, nil) - if err != nil { - log.Error("TraverseDb() failure") - return payload, err - } + for _, spec := range *keySpec { + err := TraverseDb(dbs, spec, &dbresult, nil) + if err != nil { + log.Error("TraverseDb() failure") + return payload, err } } - payload, err = XlateFromDb(xpath, ygRoot, result) + payload, err = XlateFromDb(uri, ygRoot, dbs, dbresult) if err != nil { log.Error("XlateFromDb() failure.") return payload, err @@ -285,23 +284,28 @@ func GetAndXlateFromDB(xpath string, ygRoot *ygot.GoStruct, dbs [db.MaxDB]*db.DB return payload, err } -func XlateFromDb(xpath string, ygRoot *ygot.GoStruct, data map[string]map[string]db.Value) ([]byte, error) { +func XlateFromDb(uri string, ygRoot *ygot.GoStruct, dbs [db.MaxDB]*db.DB, data map[db.DBNum]map[string]map[string]db.Value) ([]byte, error) { + var err error - var dbData = make(map[string]map[string]db.Value) + var dbData = make(map[db.DBNum]map[string]map[string]db.Value) + var cdb db.DBNum dbData = data - if isCvlYang(xpath) { - yangXpath, keyStr, tableName := sonicXpathKeyExtract(xpath) + if isCvlYang(uri) { + yangXpath, keyStr, tableName := sonicXpathKeyExtract(uri) if (tableName != "") { tokens:= strings.Split(yangXpath, "/") // Format /module:container/tableName[key]/fieldName if tokens[len(tokens)-2] == tableName { - fieldName := tokens[len(tokens)-1] - dbData = extractFieldFromDb(tableName, keyStr, fieldName, data) + fieldName := tokens[len(tokens)-1] + cdb = xSpecMap[yangXpath].dbIndex + dbData[cdb] = extractFieldFromDb(tableName, keyStr, fieldName, data[cdb]) } } } - payload, err := dbDataToYangJsonCreate(xpath, ygRoot, dbData) + xpath, _ := RemoveXPATHPredicates(uri) + cdb = xSpecMap[xpath].dbIndex + payload, err := dbDataToYangJsonCreate(uri, ygRoot, dbs, dbData, cdb) if err != nil { log.Errorf("Error: failed to create json response from DB data.") diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index eaac0c0087..102dd122f4 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -99,8 +99,8 @@ func tableNameAndKeyFromDbMapGet(dbDataMap map[string]map[string]db.Value) (stri return tableName, tableKey, nil } -func yangListDataFill(d *db.DB, ygRoot *ygot.GoStruct, uri string, xpath string, dbDataMap map[string]map[string]db.Value, resultMap map[string]interface{}, tbl string, tblKey string) error { - tblData, ok := dbDataMap[tbl] +func yangListDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath string, dbDataMap map[db.DBNum]map[string]map[string]db.Value, resultMap map[string]interface{}, tbl string, tblKey string, cdb db.DBNum) error { + tblData, ok := dbDataMap[cdb][tbl] if ok { var mapSlice []typeMapOfInterface @@ -108,16 +108,16 @@ func yangListDataFill(d *db.DB, ygRoot *ygot.GoStruct, uri string, xpath string, curMap := make(map[string]interface{}) curKeyMap, curUri, _, _ := dbKeyToYangDataConvert(uri, xpath, dbKey) if len(xSpecMap[xpath].xfmrFunc) > 0 { - jsonStr, _ := xfmrHandlerFunc(d, xpath, curUri, ygRoot, dbDataMap) + jsonStr, _ := xfmrHandlerFunc(dbs[cdb], xpath, curUri, ygRoot, dbDataMap[cdb]) fmt.Printf("From leaf-xfmr(%v)\r\n", jsonStr) } else { - _, keyFromCurUri, _ := xpathKeyExtract(d, ygRoot, GET, curUri) + _, keyFromCurUri, _ := xpathKeyExtract(dbs[cdb], ygRoot, GET, curUri) if dbKey == keyFromCurUri { for k, kv := range curKeyMap { curMap[k] = kv } curXpath, _ := RemoveXPATHPredicates(curUri) - yangDataFill(d, ygRoot, curUri, curXpath, dbDataMap, curMap, tbl, dbKey) + yangDataFill(dbs, ygRoot, curUri, curXpath, dbDataMap, curMap, tbl, dbKey, cdb) mapSlice = append(mapSlice, curMap) } } @@ -131,7 +131,7 @@ func yangListDataFill(d *db.DB, ygRoot *ygot.GoStruct, uri string, xpath string, return nil } -func yangDataFill(d *db.DB, ygRoot *ygot.GoStruct, uri string, xpath string, dbDataMap map[string]map[string]db.Value, resultMap map[string]interface{}, tbl string, tblKey string) error { +func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath string, dbDataMap map[db.DBNum]map[string]map[string]db.Value, resultMap map[string]interface{}, tbl string, tblKey string, cdb db.DBNum) error { var err error yangNode, ok := xSpecMap[xpath] @@ -143,7 +143,7 @@ func yangDataFill(d *db.DB, ygRoot *ygot.GoStruct, uri string, xpath string, dbD chldYangType := yangTypeGet(xSpecMap[chldXpath].yangEntry) if chldYangType == "leaf" { if len(xSpecMap[chldXpath].xfmrFunc) > 0 { - fldValMap, _, err := leafXfmrHandlerFunc(nil, chldXpath, chldUri, ygRoot, dbDataMap) + fldValMap, _, err := leafXfmrHandlerFunc(dbs[cdb], chldXpath, chldUri, ygRoot, dbDataMap[cdb]) if err != nil { return err } @@ -153,7 +153,7 @@ func yangDataFill(d *db.DB, ygRoot *ygot.GoStruct, uri string, xpath string, dbD } else { dbFldName := xSpecMap[chldXpath].fieldName if len(dbFldName) > 0 && !xSpecMap[chldXpath].isKey { - val, ok := dbDataMap[tbl][tblKey].Field[dbFldName] + val, ok := dbDataMap[cdb][tbl][tblKey].Field[dbFldName] if ok { resultMap[xSpecMap[chldXpath].yangEntry.Name] = val } @@ -161,12 +161,12 @@ func yangDataFill(d *db.DB, ygRoot *ygot.GoStruct, uri string, xpath string, dbD } } else if chldYangType == "container" { if len(xSpecMap[chldXpath].xfmrFunc) > 0 { - jsonStr, _ := xfmrHandlerFunc(nil, chldXpath, chldUri, ygRoot, dbDataMap) + jsonStr, _ := xfmrHandlerFunc(dbs[cdb], chldXpath, chldUri, ygRoot, dbDataMap[cdb]) fmt.Printf("From container-xfmr(%v)\r\n", jsonStr) } else { cname := xSpecMap[chldXpath].yangEntry.Name cmap := make(map[string]interface{}) - err = yangDataFill(d, ygRoot, chldUri, chldXpath, dbDataMap, cmap, tbl, tblKey) + err = yangDataFill(dbs, ygRoot, chldUri, chldXpath, dbDataMap, cmap, tbl, tblKey, cdb) if len(cmap) > 0 { resultMap[cname] = cmap } else { @@ -175,13 +175,13 @@ func yangDataFill(d *db.DB, ygRoot *ygot.GoStruct, uri string, xpath string, dbD } } else if chldYangType == "list" { if len(xSpecMap[chldXpath].xfmrFunc) > 0 { - jsonStr , _ := xfmrHandlerFunc(nil, chldXpath, chldUri, ygRoot, dbDataMap) + jsonStr , _ := xfmrHandlerFunc(dbs[cdb], chldXpath, chldUri, ygRoot, dbDataMap[cdb]) fmt.Printf("From list-xfmr(%v)\r\n", jsonStr) } else { ynode, ok := xSpecMap[chldXpath] if ok && ynode.tableName != nil { lTblName := *ynode.tableName - yangListDataFill(d, ygRoot, chldUri, chldXpath, dbDataMap, resultMap, lTblName, "") + yangListDataFill(dbs, ygRoot, chldUri, chldXpath, dbDataMap, resultMap, lTblName, "", cdb) } } } else { @@ -194,10 +194,10 @@ func yangDataFill(d *db.DB, ygRoot *ygot.GoStruct, uri string, xpath string, dbD } /* Traverse linear db-map data and add to nested json data */ -func dbDataToYangJsonCreate(uri string, ygRoot *ygot.GoStruct, dbDataMap map[string]map[string]db.Value) (string, error) { +func dbDataToYangJsonCreate(uri string, ygRoot *ygot.GoStruct, dbs [db.MaxDB]*db.DB, dbDataMap map[db.DBNum]map[string]map[string]db.Value, cdb db.DBNum) (string, error) { jsonData := "" if isCvlYang(uri) { - jsonData := directDbToYangJsonCreate(dbDataMap, jsonData) + jsonData := directDbToYangJsonCreate(dbDataMap[cdb], jsonData) jsonDataPrint(jsonData) return jsonData, nil } @@ -210,12 +210,12 @@ func dbDataToYangJsonCreate(uri string, ygRoot *ygot.GoStruct, dbDataMap map[str yangType := yangTypeGet(yangNode.yangEntry) if yangType == "leaf" { fldName := xSpecMap[reqXpath].fieldName - tbl, key, _ := tableNameAndKeyFromDbMapGet(dbDataMap) + tbl, key, _ := tableNameAndKeyFromDbMapGet(dbDataMap[cdb]) jsonData = fmt.Sprintf("{\r\n \"%v\" : \"%v\" \r\n }\r\n", xSpecMap[reqXpath].yangEntry.Name, - dbDataMap[tbl][key].Field[fldName]) + dbDataMap[cdb][tbl][key].Field[fldName]) return jsonData, nil } else { - yangDataFill(d, ygRoot, uri, reqXpath, dbDataMap, resultMap, tableName, keyName) + yangDataFill(dbs, ygRoot, uri, reqXpath, dbDataMap, resultMap, tableName, keyName, cdb) } } From 0b38b71acd0c47fef477505f7f42e67c8df97690 Mon Sep 17 00:00:00 2001 From: amrutasali Date: Tue, 10 Sep 2019 18:16:31 +0000 Subject: [PATCH 102/214] Initial leaf-list support - common app modifications --- src/translib/common_app.go | 70 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 67 insertions(+), 3 deletions(-) diff --git a/src/translib/common_app.go b/src/translib/common_app.go index 6ff18913ac..2a536148f6 100644 --- a/src/translib/common_app.go +++ b/src/translib/common_app.go @@ -3,12 +3,14 @@ package translib import ( "errors" "fmt" + "strings" log "github.com/golang/glog" "github.com/openconfig/ygot/ygot" "reflect" "translib/db" "translib/tlerr" "translib/transformer" + "encoding/json" ) var () @@ -159,6 +161,10 @@ func (app *CommonApp) processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error) { log.Error("transformer.XlateFromDb() failure") return GetResponse{Payload: payload, ErrSrc: AppErr}, err } + var dat map[string]interface{} + err = json.Unmarshal(payload, &dat) + fmt.Println("RESULT ******* ", dat) + return GetResponse{Payload: payload}, err } @@ -170,6 +176,7 @@ func (app *CommonApp) translateCRUDCommon(d *db.DB, opcode int) ([]db.WatchKeys, var OrdTblList []string var moduleNm string log.Info("translateCRUDCommon:path =", app.pathInfo.Path) + d.Opts.DisableCVLCheck = true /* retrieve schema table order for incoming module name request */ moduleNm, err = transformer.GetModuleNmFromPath(app.pathInfo.Path) @@ -259,7 +266,7 @@ func (app *CommonApp) cmnAppCRUCommonDbOpn(d *db.DB, opcode int) error { switch opcode { case CREATE: if existingEntry.IsPopulated() { - log.Info("Entry already exists hence return error.") + log.Info("Entry already exists hence return do an update.") return tlerr.AlreadyExists("Entry %s already exists", tblKey) } else { err = d.CreateEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}, tblRw) @@ -271,7 +278,12 @@ func (app *CommonApp) cmnAppCRUCommonDbOpn(d *db.DB, opcode int) error { case UPDATE: if existingEntry.IsPopulated() { log.Info("Entry already exists hence modifying it.") - err = d.ModEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}, tblRw) + /* Handle leaf-list merge + A leaf-list field in redis has "@" suffix as per swsssdk convention. + */ + resTblRw := db.Value{Field: map[string]string{}} + resTblRw = processLeafList(existingEntry, tblRw, UPDATE, d, tblNm, tblKey) + err = d.ModEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}, resTblRw) if err != nil { log.Error("UPDATE case - d.ModEntry() failure") return err @@ -359,7 +371,14 @@ func (app *CommonApp) cmnAppDelDbOpn(d *db.DB, opcode int) error { log.Info("Finally deleted the parent table row with key = ", tblKey) } else { log.Info("DELETE case - fields/cols to delete hence delete only those fields.") - err := d.DeleteEntryFields(cmnAppTs, db.Key{Comp: []string{tblKey}}, tblRw) + existingEntry, _ := d.GetEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}) + if !existingEntry.IsPopulated() { + log.Info("Table Entry from which the fields are to be deleted does not exist") + return err + } + /*handle leaf-list merge*/ + resTblRw := processLeafList(existingEntry, tblRw, DELETE, d, tblNm, tblKey) + err := d.DeleteEntryFields(cmnAppTs, db.Key{Comp: []string{tblKey}}, resTblRw) if err != nil { log.Error("DELETE case - d.DeleteEntryFields() failure") return err @@ -378,3 +397,48 @@ func (app *CommonApp) generateDbWatchKeys(d *db.DB, isDeleteOp bool) ([]db.Watch return keys, err } + +func processLeafList(existingEntry db.Value, tblRw db.Value, opcode int, d *db.DB, tblNm string, tblKey string) db.Value { + log.Info("process leaf-list Fields in table row.") + dbTblSpec := &db.TableSpec{Name: tblNm} + mergeTblRw := db.Value{Field: map[string]string{}} + for field, value := range tblRw.Field { + if strings.HasSuffix(field, "@") { + exstLst := existingEntry.GetList(field) + if len(exstLst) != 0 { + valueLst := strings.Split(value, ",") + for _, item := range valueLst { + if !contains(exstLst, item) { + if opcode == UPDATE { + exstLst = append(exstLst, item) + } + } else { + if opcode == DELETE { + exstLst = removeElement(exstLst, item) + } + + } + } + log.Infof("For field %v value after merge %v", field, exstLst) + if opcode == DELETE { + mergeTblRw.SetList(field, exstLst) + delete(tblRw.Field, field) + } + } + tblRw.SetList(field, exstLst) + } + } + /* delete specific item from leaf-list */ + if opcode == DELETE { + if mergeTblRw.Field == nil { + return tblRw + } + err := d.ModEntry(dbTblSpec, db.Key{Comp: []string{tblKey}}, mergeTblRw) + if err != nil { + log.Warning("DELETE case(merge leaf-list) - d.ModEntry() failure") + } + } + log.Infof("Returning Table Row %v", tblRw) + return tblRw +} + From 28a3656cac2b899c00b11d21890e42e262353d08 Mon Sep 17 00:00:00 2001 From: amrutasali Date: Tue, 10 Sep 2019 18:23:52 +0000 Subject: [PATCH 103/214] removed mistakenly added CVL disabling in common_app.go --- src/translib/common_app.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/translib/common_app.go b/src/translib/common_app.go index 2a536148f6..5a5ea1f837 100644 --- a/src/translib/common_app.go +++ b/src/translib/common_app.go @@ -176,7 +176,6 @@ func (app *CommonApp) translateCRUDCommon(d *db.DB, opcode int) ([]db.WatchKeys, var OrdTblList []string var moduleNm string log.Info("translateCRUDCommon:path =", app.pathInfo.Path) - d.Opts.DisableCVLCheck = true /* retrieve schema table order for incoming module name request */ moduleNm, err = transformer.GetModuleNmFromPath(app.pathInfo.Path) @@ -266,7 +265,7 @@ func (app *CommonApp) cmnAppCRUCommonDbOpn(d *db.DB, opcode int) error { switch opcode { case CREATE: if existingEntry.IsPopulated() { - log.Info("Entry already exists hence return do an update.") + log.Info("Entry already exists hence return.") return tlerr.AlreadyExists("Entry %s already exists", tblKey) } else { err = d.CreateEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}, tblRw) From 3693d5db3513839f75365a72b61df014cecb2436 Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Tue, 10 Sep 2019 21:34:58 -0700 Subject: [PATCH 104/214] Signature chnage for transformer functions --- src/translib/transformer/xfmr_acl.go | 133 +++++++++++---------- src/translib/transformer/xfmr_interface.go | 27 +++-- src/translib/transformer/xlate.go | 2 +- src/translib/transformer/xlate_from_db.go | 46 ++++--- src/translib/transformer/xlate_to_db.go | 15 ++- src/translib/transformer/xlate_utils.go | 20 +++- 6 files changed, 146 insertions(+), 97 deletions(-) diff --git a/src/translib/transformer/xfmr_acl.go b/src/translib/transformer/xfmr_acl.go index ff9b127312..470073a5bd 100644 --- a/src/translib/transformer/xfmr_acl.go +++ b/src/translib/transformer/xfmr_acl.go @@ -189,7 +189,7 @@ func getL2EtherType(etherType uint64) interface{} { return uint16(etherType) } -var YangToDb_acl_set_name_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, opType int, xpath string, name interface {}) (map[string]string, error) { +var YangToDb_acl_set_name_xfmr FieldXfmrYangToDb = func (inParams XfmrParams) (map[string]string, error) { res_map := make(map[string]string) var err error log.Info("YangToDb_acl_set_name_xfmr: ") @@ -197,24 +197,23 @@ var YangToDb_acl_set_name_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot. return res_map, err } -var DbToYang_acl_set_name_xfmr FieldXfmrDbtoYang = func (d *db.DB, opType int, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct, key string) (map[string]interface{}, error) { +var DbToYang_acl_set_name_xfmr FieldXfmrDbtoYang = func (inParams XfmrParams) (map[string]interface{}, error) { res_map := make(map[string]interface{}) var err error - log.Info("DbToYang_acl_set_name_xfmr: ", key) + log.Info("DbToYang_acl_set_name_xfmr: ", inParams.key) /*name attribute corresponds to key in redis table*/ - aclName, _ := getOCAclKeysFromStrDBKey(key) + aclName, _ := getOCAclKeysFromStrDBKey(inParams.key) res_map["name"] = aclName log.Info("acl-set/config/name ", res_map) return res_map, err } - -var YangToDb_acl_entry_key_xfmr KeyXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, opType int, xpath string) (string, error) { +var YangToDb_acl_entry_key_xfmr KeyXfmrYangToDb = func (inParams XfmrParams) (string, error) { var entry_key string var err error var oc_aclType ocbinds.E_OpenconfigAcl_ACL_TYPE - log.Info("YangToDb_acl_entry_key_xfmr: ", ygRoot, xpath) - pathInfo := NewPathInfo(xpath) + log.Info("YangToDb_acl_entry_key_xfmr: ", inParams.ygRoot, inParams.uri) + pathInfo := NewPathInfo(inParams.uri) if len(pathInfo.Vars) < 3 { err = errors.New("Invalid xpath, key attributes not found") @@ -239,9 +238,10 @@ var YangToDb_acl_entry_key_xfmr KeyXfmrYangToDb = func (d *db.DB, ygRoot *ygot.G return entry_key, err } -var DbToYang_acl_entry_key_xfmr KeyXfmrDbToYang = func (d *db.DB, opType int, entry_key string) (map[string]string, error) { +var DbToYang_acl_entry_key_xfmr KeyXfmrDbToYang = func (inParams XfmrParams) (map[string]string, error) { rmap := make(map[string]string) var err error + entry_key := inParams.key log.Info("DbToYang_acl_entry_key_xfmr: ", entry_key) key := strings.Split(entry_key, "|") @@ -257,7 +257,7 @@ var DbToYang_acl_entry_key_xfmr KeyXfmrDbToYang = func (d *db.DB, opType int, en return rmap, err } -var YangToDb_acl_entry_sequenceid_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, opType int, xpath string, sequence_id interface {}) (map[string]string, error) { +var YangToDb_acl_entry_sequenceid_xfmr FieldXfmrYangToDb = func (inParams XfmrParams) (map[string]string, error) { res_map := make(map[string]string) var err error log.Info("YangToDb_acl_entry_sequenceid_xfmr: ") @@ -265,12 +265,12 @@ var YangToDb_acl_entry_sequenceid_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoo return res_map, err } -var DbToYang_acl_entry_sequenceid_xfmr FieldXfmrDbtoYang = func (d *db.DB, opType int, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct, key string) (map[string]interface{}, error) { +var DbToYang_acl_entry_sequenceid_xfmr FieldXfmrDbtoYang = func (inParams XfmrParams) (map[string]interface{}, error) { res_map := make(map[string]interface{}) var err error - log.Info("DbToYang_acl_entry_sequenceid_xfmr: ", key) + log.Info("DbToYang_acl_entry_sequenceid_xfmr: ", inParams.key) /*sequenec-id attribute corresponds to key in redis table*/ - res, err := DbToYang_acl_entry_key_xfmr(d, opType, key) + res, err := DbToYang_acl_entry_key_xfmr(inParams) log.Info("acl-entry/config/sequence-id ", res) if err != nil { return res_map, err @@ -284,21 +284,21 @@ var DbToYang_acl_entry_sequenceid_xfmr FieldXfmrDbtoYang = func (d *db.DB, opTyp return res_map, err } -var YangToDb_acl_l2_ethertype_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, opType int, xpath string, ethertype interface {}) (map[string]string, error) { +var YangToDb_acl_l2_ethertype_xfmr FieldXfmrYangToDb = func (inParams XfmrParams) (map[string]string, error) { res_map := make(map[string]string) var err error - ethertypeType := reflect.TypeOf(ethertype).Elem() - log.Info("YangToDb_acl_ip_protocol_xfmr: ", ygRoot, " Xpath: ", xpath, " ethertypeType: ", ethertypeType) + ethertypeType := reflect.TypeOf(inParams.param).Elem() + log.Info("YangToDb_acl_ip_protocol_xfmr: ", inParams.ygRoot, " Xpath: ", inParams.uri, " ethertypeType: ", ethertypeType) var b bytes.Buffer switch ethertypeType { case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_L2_Config_Ethertype_Union_E_OpenconfigPacketMatchTypes_ETHERTYPE{}): - v := (ethertype).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_L2_Config_Ethertype_Union_E_OpenconfigPacketMatchTypes_ETHERTYPE) + v := (inParams.param).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_L2_Config_Ethertype_Union_E_OpenconfigPacketMatchTypes_ETHERTYPE) fmt.Fprintf(&b, "0x%0.4x", ETHERTYPE_MAP[v.E_OpenconfigPacketMatchTypes_ETHERTYPE]) res_map["ETHER_TYPE"] = b.String() break case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_L2_Config_Ethertype_Union_Uint16{}): - v := (ethertype).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_L2_Config_Ethertype_Union_Uint16) + v := (inParams.param).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_L2_Config_Ethertype_Union_Uint16) fmt.Fprintf(&b, "0x%0.4x", v.Uint16) res_map["ETHER_TYPE"] = b.String() break @@ -306,17 +306,18 @@ var YangToDb_acl_l2_ethertype_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *y return res_map, err } -var DbToYang_acl_l2_ethertype_xfmr FieldXfmrDbtoYang = func (d *db.DB, opType int, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct, key string) (map[string]interface{}, error) { +var DbToYang_acl_l2_ethertype_xfmr FieldXfmrDbtoYang = func (inParams XfmrParams) (map[string]interface{}, error) { var err error result := make(map[string]interface{}) - log.Info("DbToYang_acl_l2_ethertype_xfmr", data, ygRoot) + data:= (*inParams.dbDataMap)[inParams.curDb] + log.Info("DbToYang_acl_l2_ethertype_xfmr", data, inParams.ygRoot) if _, ok := data[RULE_TABLE]; !ok { err = errors.New("RULE_TABLE entry not found in the input param") return result, err } ruleTbl := data[RULE_TABLE] - ruleInst := ruleTbl[key] + ruleInst := ruleTbl[inParams.key] etype, ok := ruleInst.Field["ETHER_TYPE"] if ok { @@ -358,36 +359,37 @@ var DbToYang_acl_l2_ethertype_xfmr FieldXfmrDbtoYang = func (d *db.DB, opType in */ } -var YangToDb_acl_ip_protocol_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, opType int, xpath string, protocol interface {}) (map[string]string, error) { +var YangToDb_acl_ip_protocol_xfmr FieldXfmrYangToDb = func (inParams XfmrParams) (map[string]string, error) { res_map := make(map[string]string) var err error - protocolType := reflect.TypeOf(protocol).Elem() - log.Info("YangToDb_acl_ip_protocol_xfmr: ", ygRoot, " Xpath: ", xpath, " protocolType: ", protocolType) + protocolType := reflect.TypeOf(inParams.param).Elem() + log.Info("YangToDb_acl_ip_protocol_xfmr: ", inParams.ygRoot, " Xpath: ", inParams.uri, " protocolType: ", protocolType) switch (protocolType) { case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Ipv4_Config_Protocol_Union_E_OpenconfigPacketMatchTypes_IP_PROTOCOL{}): - v := (protocol).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Ipv4_Config_Protocol_Union_E_OpenconfigPacketMatchTypes_IP_PROTOCOL) + v := (inParams.param).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Ipv4_Config_Protocol_Union_E_OpenconfigPacketMatchTypes_IP_PROTOCOL) res_map["IP_PROTOCOL"] = strconv.FormatInt(int64(IP_PROTOCOL_MAP[v.E_OpenconfigPacketMatchTypes_IP_PROTOCOL]), 10) break case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Ipv4_Config_Protocol_Union_Uint8{}): - v := (protocol).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Ipv4_Config_Protocol_Union_Uint8) + v := (inParams.param).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Ipv4_Config_Protocol_Union_Uint8) res_map["IP_PROTOCOL"] = strconv.FormatInt(int64(v.Uint8), 10) break } return res_map, err } -var DbToYang_acl_ip_protocol_xfmr FieldXfmrDbtoYang = func (d *db.DB, opType int, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct, key string) (map[string]interface{}, error) { +var DbToYang_acl_ip_protocol_xfmr FieldXfmrDbtoYang = func (inParams XfmrParams) (map[string]interface{}, error) { var err error result := make(map[string]interface{}) - log.Info("DbToYang_acl_ip_protocol_xfmr ", data, ygRoot) + data:= (*inParams.dbDataMap)[inParams.curDb] + log.Info("DbToYang_acl_ip_protocol_xfmr ", data, inParams.ygRoot) if _, ok := data[RULE_TABLE]; !ok { err = errors.New("RULE_TABLE entry not found in the input param") return result, err } ruleTbl := data[RULE_TABLE] - ruleInst := ruleTbl[key] + ruleInst := ruleTbl[inParams.key] prot, ok := ruleInst.Field["IP_PROTOCOL"] if ok { @@ -422,22 +424,22 @@ var DbToYang_acl_ip_protocol_xfmr FieldXfmrDbtoYang = func (d *db.DB, opType int */ } -var YangToDb_acl_source_port_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, opType int, xpath string, value interface {}) (map[string]string, error) { +var YangToDb_acl_source_port_xfmr FieldXfmrYangToDb = func (inParams XfmrParams) (map[string]string, error) { res_map := make(map[string]string) var err error; - sourceportType := reflect.TypeOf(value).Elem() - log.Info("YangToDb_acl_ip_protocol_xfmr: ", ygRoot, " Xpath: ", xpath, " sourceportType: ", sourceportType) + sourceportType := reflect.TypeOf(inParams.param).Elem() + log.Info("YangToDb_acl_ip_protocol_xfmr: ", inParams.ygRoot, " Xpath: ", inParams.uri, " sourceportType: ", sourceportType) switch sourceportType { case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort_Union_E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort{}): - v := (value).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort_Union_E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort) + v := (inParams.param).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort_Union_E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort) res_map["L4_SRC_PORT"] = v.E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort.ΛMap()["E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort"][int64(v.E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort)].Name break case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort_Union_String{}): - v := (value).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort_Union_String) + v := (inParams.param).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort_Union_String) res_map["L4_SRC_PORT_RANGE"] = strings.Replace(v.String, "..", "-", 1) break case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort_Union_Uint16{}): - v := (value).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort_Union_Uint16) + v := (inParams.param).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort_Union_Uint16) res_map["L4_SRC_PORT"] = strconv.FormatInt(int64(v.Uint16), 10) break } @@ -445,7 +447,6 @@ var YangToDb_acl_source_port_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *yg return res_map, err } - func getAclSetEntry (aclRuleKey string, ygRoot *ygot.GoStruct) (*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry, error) { var err error var entrySet *ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry @@ -486,16 +487,17 @@ func getAclSetEntry (aclRuleKey string, ygRoot *ygot.GoStruct) (*ocbinds.Opencon } -var DbToYang_acl_source_port_xfmr FieldXfmrDbtoYang = func (d *db.DB, opType int, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct, key string) (map[string]interface{}, error) { +var DbToYang_acl_source_port_xfmr FieldXfmrDbtoYang = func (inParams XfmrParams) (map[string]interface{}, error) { var err error - log.Info("DbToYang_acl_source_port_xfmr: ", data, ygRoot) + data:= (*inParams.dbDataMap)[inParams.curDb] + log.Info("DbToYang_acl_source_port_xfmr: ", data, inParams.ygRoot) result := make(map[string]interface{}) if _, ok := data[RULE_TABLE]; !ok { err = errors.New("RULE_TABLE entry not found in the input param") return result, err } ruleTbl := data[RULE_TABLE] - ruleInst := ruleTbl[key] + ruleInst := ruleTbl[inParams.key] port, ok := ruleInst.Field["L4_SRC_PORT"] if ok { result["source-port"] = port @@ -548,38 +550,39 @@ var DbToYang_acl_source_port_xfmr FieldXfmrDbtoYang = func (d *db.DB, opType int */ } -var YangToDb_acl_destination_port_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, opType int, xpath string, value interface{}) (map[string]string, error) { +var YangToDb_acl_destination_port_xfmr FieldXfmrYangToDb = func (inParams XfmrParams) (map[string]string, error) { res_map := make(map[string]string) var err error; - destportType := reflect.TypeOf(value).Elem() - log.Info("YangToDb_acl_ip_protocol_xfmr: ", ygRoot, " Xpath: ", xpath, " destportType: ", destportType) + destportType := reflect.TypeOf(inParams.param).Elem() + log.Info("YangToDb_acl_ip_protocol_xfmr: ", inParams.ygRoot, " Xpath: ", inParams.uri, " destportType: ", destportType) switch destportType { case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort_Union_E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort{}): - v := (value).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort_Union_E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort) + v := (inParams.param).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort_Union_E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort) res_map["L4_DST_PORT"] = v.E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort.ΛMap()["E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort"][int64(v.E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort)].Name break case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort_Union_String{}): - v := (value).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort_Union_String) + v := (inParams.param).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort_Union_String) res_map["L4_DST_PORT_RANGE"] = strings.Replace(v.String, "..", "-", 1) break case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort_Union_Uint16{}): - v := (value).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort_Union_Uint16) + v := (inParams.param).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort_Union_Uint16) res_map["L4_DST_PORT"] = strconv.FormatInt(int64(v.Uint16), 10) break } return res_map, err } -var DbToYang_acl_destination_port_xfmr FieldXfmrDbtoYang = func (d *db.DB, opType int, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct, key string) (map[string]interface{}, error) { +var DbToYang_acl_destination_port_xfmr FieldXfmrDbtoYang = func (inParams XfmrParams) (map[string]interface{}, error) { var err error - log.Info("DbToYang_acl_destination_port_xfmr: ", data, ygRoot) + data:= (*inParams.dbDataMap)[inParams.curDb] + log.Info("DbToYang_acl_destination_port_xfmr: ", data, inParams.ygRoot) result := make(map[string]interface{}) if _, ok := data[RULE_TABLE]; !ok { err = errors.New("RULE_TABLE entry not found in the input param") return result, err } ruleTbl := data[RULE_TABLE] - ruleInst := ruleTbl[key] + ruleInst := ruleTbl[inParams.key] port, ok := ruleInst.Field["L4_DST_PORT"] if ok { result["destination-port"] = port @@ -631,12 +634,12 @@ var DbToYang_acl_destination_port_xfmr FieldXfmrDbtoYang = func (d *db.DB, opTyp */ } -var YangToDb_acl_tcp_flags_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, opType int, xpath string, value interface {}) (map[string]string, error) { +var YangToDb_acl_tcp_flags_xfmr FieldXfmrYangToDb = func (inParams XfmrParams) (map[string]string, error) { res_map := make(map[string]string) var err error; - log.Info("YangToDb_acl_tcp_flags_xfmr: ", ygRoot, xpath) + log.Info("YangToDb_acl_tcp_flags_xfmr: ", inParams.ygRoot, inParams.uri) var tcpFlags uint32 = 0x00 - v := reflect.ValueOf(value) + v := reflect.ValueOf(inParams.param) flags := v.Interface().([]ocbinds.E_OpenconfigPacketMatchTypes_TCP_FLAGS) for _, flag := range flags { @@ -674,16 +677,17 @@ var YangToDb_acl_tcp_flags_xfmr FieldXfmrYangToDb = func (d *db.DB, ygRoot *ygot return res_map, err } -var DbToYang_acl_tcp_flags_xfmr FieldXfmrDbtoYang = func (d *db.DB, opType int, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct, key string) (map[string]interface{}, error) { +var DbToYang_acl_tcp_flags_xfmr FieldXfmrDbtoYang = func (inParams XfmrParams) (map[string]interface{}, error) { var err error - log.Info("DbToYang_acl_tcp_flags_xfmr: ", data, ygRoot) + data:= (*inParams.dbDataMap)[inParams.curDb] + log.Info("DbToYang_acl_tcp_flags_xfmr: ", data, inParams.ygRoot) result := make(map[string]interface{}) if _, ok := data[RULE_TABLE]; !ok { err = errors.New("RULE_TABLE entry not found in the input param") return result, err } ruleTbl := data[RULE_TABLE] - ruleInst := ruleTbl[key] + ruleInst := ruleTbl[inParams.key] tcpFlag, ok := ruleInst.Field["TCP_FLAGS"] if ok { result["tcp-flags"] = getTransportConfigTcpFlags(tcpFlag) @@ -820,14 +824,14 @@ func getDbAlcTblsData (d *db.DB) (map[string]db.Value, map[string]map[string]db. return aclTableMap, ruleTableMap, err } -var YangToDb_acl_port_bindings_xfmr SubTreeXfmrYangToDb = func (d *db.DB, ygRoot *ygot.GoStruct, opType int, xpath string) (map[string]map[string]db.Value, error) { +var YangToDb_acl_port_bindings_xfmr SubTreeXfmrYangToDb = func (inParams XfmrParams) (map[string]map[string]db.Value, error) { res_map := make(map[string]map[string]db.Value) aclTableMap := make(map[string]db.Value) - log.Info("YangToDb_acl_port_bindings_xfmr: ", ygRoot, xpath) + log.Info("YangToDb_acl_port_bindings_xfmr: ", inParams.ygRoot, inParams.uri) - aclObj := getAclRoot(ygRoot) + aclObj := getAclRoot(inParams.ygRoot) - aclTableMapDb, _, err := getDbAlcTblsData(d) + aclTableMapDb, _, err := getDbAlcTblsData(inParams.d) if err != nil { log.Info("YangToDb_acl_port_bindings_xfmr: getDbAlcTblsData not able to populate acl tables.") } @@ -908,19 +912,20 @@ var YangToDb_acl_port_bindings_xfmr SubTreeXfmrYangToDb = func (d *db.DB, ygRoot return res_map, err } -var DbToYang_acl_port_bindings_xfmr SubTreeXfmrDbToYang = func (d *db.DB, opType int, data map[string]map[string]db.Value, ygRoot *ygot.GoStruct, xpath string) (error) { +var DbToYang_acl_port_bindings_xfmr SubTreeXfmrDbToYang = func (inParams XfmrParams) (error) { var err error - log.Info("DbToYang_acl_port_bindings_xfmr: ", data, ygRoot) + data:= (*inParams.dbDataMap)[inParams.curDb] + log.Info("DbToYang_acl_port_bindings_xfmr: ", data, inParams.ygRoot) - aclTbl, ruleTbl, err := getDbAlcTblsData(d) + aclTbl, ruleTbl, err := getDbAlcTblsData(inParams.d) if err != nil { log.Info("getDbAlcTblsData not able to populate acl tables.") err = errors.New("getDbAlcTblsData failed to populate tables.") return err } - pathInfo := NewPathInfo(xpath) - acl := getAclRoot(ygRoot) + pathInfo := NewPathInfo(inParams.uri) + acl := getAclRoot(inParams.ygRoot) targetUriPath, _ := getYangPathFromUri(pathInfo.Path) if isSubtreeRequest(pathInfo.Template, "/openconfig-acl:acl/interfaces/interface{}") { for intfId := range acl.Interfaces.Interface { @@ -939,7 +944,7 @@ var DbToYang_acl_port_bindings_xfmr SubTreeXfmrDbToYang = func (d *db.DB, opType } } } else { - err = getAllBindingsInfo(aclTbl, ruleTbl, ygRoot) + err = getAllBindingsInfo(aclTbl, ruleTbl, inParams.ygRoot) } return err diff --git a/src/translib/transformer/xfmr_interface.go b/src/translib/transformer/xfmr_interface.go index 78f15ce96d..9fc7a68684 100644 --- a/src/translib/transformer/xfmr_interface.go +++ b/src/translib/transformer/xfmr_interface.go @@ -6,20 +6,33 @@ import ( log "github.com/golang/glog" // "translib/ocbinds" ) + +type XfmrParams struct { + d *db.DB + dbs [db.MaxDB]*db.DB + curDb db.DBNum + ygRoot *ygot.GoStruct + uri string + oper int + key string + dbDataMap *map[db.DBNum]map[string]map[string]db.Value + param interface{} +} + /** * KeyXfmrYangToDb type is defined to use for conversion of Yang key to DB Key * Transformer function definition. * Param: Database info, YgotRoot, operation, Xpath * Return: Database keys to access db entry, error **/ -type KeyXfmrYangToDb func (*db.DB, *ygot.GoStruct, int, string) (string, error) +type KeyXfmrYangToDb func (inParams XfmrParams) (string, error) /** * KeyXfmrDbToYang type is defined to use for conversion of DB key to Yang key * Transformer function definition. * Param: Database info, operation, Database keys to access db entry * Return: multi dimensional map to hold the yang key attributes of complete xpath, error **/ -type KeyXfmrDbToYang func (*db.DB, int, string) (map[string]string, error) +type KeyXfmrDbToYang func (inParams XfmrParams) (map[string]string, error) /** * FieldXfmrYangToDb type is defined to use for conversion of yang Field to DB field @@ -27,14 +40,14 @@ type KeyXfmrDbToYang func (*db.DB, int, string) (map[string]string, error) * Param: Database info, YgotRoot, operation, Xpath * Return: multi dimensional map to hold the DB data, error **/ -type FieldXfmrYangToDb func (*db.DB, *ygot.GoStruct, int, string, interface {}) (map[string]string, error) +type FieldXfmrYangToDb func (inParams XfmrParams) (map[string]string, error) /** * FieldXfmrDbtoYang type is defined to use for conversion of DB field to Yang field * Transformer function definition. * Param: Database info, operation, DB data in multidimensional map, output param YgotRoot * Return: error **/ -type FieldXfmrDbtoYang func (*db.DB, int, map[string]map[string]db.Value, *ygot.GoStruct, string) (map[string]interface{}, error) +type FieldXfmrDbtoYang func (inParams XfmrParams) (map[string]interface{}, error) /** * SubTreeXfmrYangToDb type is defined to use for handling the yang subtree to DB @@ -42,14 +55,14 @@ type FieldXfmrDbtoYang func (*db.DB, int, map[string]map[string]db.Value, *ygot. * Param: Database info, YgotRoot, operation, Xpath * Return: multi dimensional map to hold the DB data, error **/ -type SubTreeXfmrYangToDb func (*db.DB, *ygot.GoStruct, int, string) (map[string]map[string]db.Value, error) +type SubTreeXfmrYangToDb func (inParams XfmrParams) (map[string]map[string]db.Value, error) /** * SubTreeXfmrDbToYang type is defined to use for handling the DB to Yang subtree * Transformer function definition. - * Param : Database info, operation, DB data in multidimensional map, output param YgotRoot + * Param : Database pointers, current db, operation, DB data in multidimensional map, output param YgotRoot, uri * Return : error **/ -type SubTreeXfmrDbToYang func (*db.DB, int, map[string]map[string]db.Value, *ygot.GoStruct, string) (error) +type SubTreeXfmrDbToYang func (inParams XfmrParams) (error) /** * Xfmr validation interface for validating the callback registration of app modules diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index d320854edb..797a6a2354 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -305,7 +305,7 @@ func XlateFromDb(uri string, ygRoot *ygot.GoStruct, dbs [db.MaxDB]*db.DB, data m } xpath, _ := RemoveXPATHPredicates(uri) cdb = xSpecMap[xpath].dbIndex - payload, err := dbDataToYangJsonCreate(uri, ygRoot, dbs, dbData, cdb) + payload, err := dbDataToYangJsonCreate(uri, ygRoot, dbs, &dbData, cdb) if err != nil { log.Errorf("Error: failed to create json response from DB data.") diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index 102dd122f4..1b476dbc64 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -15,18 +15,19 @@ import ( type typeMapOfInterface map[string]interface{} -func xfmrHandlerFunc(d *db.DB, xpath string, uri string, ygRoot *ygot.GoStruct, dbDataMap map[string]map[string]db.Value) (string, error) { - _, err := XlateFuncCall(dbToYangXfmrFunc(xSpecMap[xpath].xfmrFunc), d, GET, dbDataMap, ygRoot) +func xfmrHandlerFunc(inParams XfmrParams) (string, error) { + xpath, _ := RemoveXPATHPredicates(inParams.uri) + _, err := XlateFuncCall(dbToYangXfmrFunc(xSpecMap[xpath].xfmrFunc), inParams) if err != nil { return "", err } ocbSch, _ := ocbinds.Schema() schRoot := ocbSch.RootSchema() - device := (*ygRoot).(*ocbinds.Device) + device := (*inParams.ygRoot).(*ocbinds.Device) log.Info("Subtree transformer function(\"%v\") invoked for yang path(\"%v\").", xSpecMap[xpath].xfmrFunc, xpath) - path, _ := ygot.StringToPath(uri, ygot.StructuredPath, ygot.StringSlicePath) + path, _ := ygot.StringToPath(inParams.uri, ygot.StructuredPath, ygot.StringSlicePath) for _, p := range path.Elem { pathSlice := strings.Split(p.Name, ":") p.Name = pathSlice[len(pathSlice)-1] @@ -51,9 +52,9 @@ func xfmrHandlerFunc(d *db.DB, xpath string, uri string, ygRoot *ygot.GoStruct, return payload, err } -func leafXfmrHandlerFunc(d *db.DB, xpath string, uri string, ygRoot *ygot.GoStruct, dbDataMap map[string]map[string]db.Value) (map[string]interface{}, string, error) { - _, keyName, _ := xpathKeyExtract(d, ygRoot, GET, uri) - ret, err := XlateFuncCall(dbToYangXfmrFunc(xSpecMap[xpath].xfmrFunc), d, GET, dbDataMap, ygRoot, keyName) +func leafXfmrHandlerFunc(inParams XfmrParams) (map[string]interface{}, string, error) { + xpath, _ := RemoveXPATHPredicates(inParams.uri) + ret, err := XlateFuncCall(dbToYangXfmrFunc(xSpecMap[xpath].xfmrFunc), inParams) if err != nil { return nil, "", err } @@ -99,8 +100,8 @@ func tableNameAndKeyFromDbMapGet(dbDataMap map[string]map[string]db.Value) (stri return tableName, tableKey, nil } -func yangListDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath string, dbDataMap map[db.DBNum]map[string]map[string]db.Value, resultMap map[string]interface{}, tbl string, tblKey string, cdb db.DBNum) error { - tblData, ok := dbDataMap[cdb][tbl] +func yangListDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath string, dbDataMap *map[db.DBNum]map[string]map[string]db.Value, resultMap map[string]interface{}, tbl string, tblKey string, cdb db.DBNum) error { + tblData, ok := (*dbDataMap)[cdb][tbl] if ok { var mapSlice []typeMapOfInterface @@ -108,7 +109,8 @@ func yangListDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, x curMap := make(map[string]interface{}) curKeyMap, curUri, _, _ := dbKeyToYangDataConvert(uri, xpath, dbKey) if len(xSpecMap[xpath].xfmrFunc) > 0 { - jsonStr, _ := xfmrHandlerFunc(dbs[cdb], xpath, curUri, ygRoot, dbDataMap[cdb]) + inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, curUri, GET, "", dbDataMap, nil) + jsonStr, _ := xfmrHandlerFunc(inParams) fmt.Printf("From leaf-xfmr(%v)\r\n", jsonStr) } else { _, keyFromCurUri, _ := xpathKeyExtract(dbs[cdb], ygRoot, GET, curUri) @@ -131,7 +133,7 @@ func yangListDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, x return nil } -func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath string, dbDataMap map[db.DBNum]map[string]map[string]db.Value, resultMap map[string]interface{}, tbl string, tblKey string, cdb db.DBNum) error { +func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath string, dbDataMap *map[db.DBNum]map[string]map[string]db.Value, resultMap map[string]interface{}, tbl string, tblKey string, cdb db.DBNum) error { var err error yangNode, ok := xSpecMap[xpath] @@ -141,9 +143,12 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath chldUri := uri+"/"+yangChldName if xSpecMap[chldXpath] != nil && xSpecMap[chldXpath].yangEntry != nil { chldYangType := yangTypeGet(xSpecMap[chldXpath].yangEntry) + cdb = xSpecMap[chldXpath].dbIndex if chldYangType == "leaf" { if len(xSpecMap[chldXpath].xfmrFunc) > 0 { - fldValMap, _, err := leafXfmrHandlerFunc(dbs[cdb], chldXpath, chldUri, ygRoot, dbDataMap[cdb]) + _, key, _ := xpathKeyExtract(dbs[cdb], ygRoot, GET, chldUri) + inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, chldUri, GET, key, dbDataMap, nil) + fldValMap, _, err := leafXfmrHandlerFunc(inParams) if err != nil { return err } @@ -153,7 +158,7 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath } else { dbFldName := xSpecMap[chldXpath].fieldName if len(dbFldName) > 0 && !xSpecMap[chldXpath].isKey { - val, ok := dbDataMap[cdb][tbl][tblKey].Field[dbFldName] + val, ok := (*dbDataMap)[cdb][tbl][tblKey].Field[dbFldName] if ok { resultMap[xSpecMap[chldXpath].yangEntry.Name] = val } @@ -161,7 +166,8 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath } } else if chldYangType == "container" { if len(xSpecMap[chldXpath].xfmrFunc) > 0 { - jsonStr, _ := xfmrHandlerFunc(dbs[cdb], chldXpath, chldUri, ygRoot, dbDataMap[cdb]) + inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, chldUri, GET, "", dbDataMap, nil) + jsonStr, _ := xfmrHandlerFunc(inParams) fmt.Printf("From container-xfmr(%v)\r\n", jsonStr) } else { cname := xSpecMap[chldXpath].yangEntry.Name @@ -174,8 +180,10 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath } } } else if chldYangType == "list" { + cdb = xSpecMap[chldXpath].dbIndex if len(xSpecMap[chldXpath].xfmrFunc) > 0 { - jsonStr , _ := xfmrHandlerFunc(dbs[cdb], chldXpath, chldUri, ygRoot, dbDataMap[cdb]) + inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, chldUri, GET, "", dbDataMap, nil) + jsonStr , _ := xfmrHandlerFunc(inParams) fmt.Printf("From list-xfmr(%v)\r\n", jsonStr) } else { ynode, ok := xSpecMap[chldXpath] @@ -194,10 +202,10 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath } /* Traverse linear db-map data and add to nested json data */ -func dbDataToYangJsonCreate(uri string, ygRoot *ygot.GoStruct, dbs [db.MaxDB]*db.DB, dbDataMap map[db.DBNum]map[string]map[string]db.Value, cdb db.DBNum) (string, error) { +func dbDataToYangJsonCreate(uri string, ygRoot *ygot.GoStruct, dbs [db.MaxDB]*db.DB, dbDataMap *map[db.DBNum]map[string]map[string]db.Value, cdb db.DBNum) (string, error) { jsonData := "" if isCvlYang(uri) { - jsonData := directDbToYangJsonCreate(dbDataMap[cdb], jsonData) + jsonData := directDbToYangJsonCreate((*dbDataMap)[cdb], jsonData) jsonDataPrint(jsonData) return jsonData, nil } @@ -210,9 +218,9 @@ func dbDataToYangJsonCreate(uri string, ygRoot *ygot.GoStruct, dbs [db.MaxDB]*db yangType := yangTypeGet(yangNode.yangEntry) if yangType == "leaf" { fldName := xSpecMap[reqXpath].fieldName - tbl, key, _ := tableNameAndKeyFromDbMapGet(dbDataMap[cdb]) + tbl, key, _ := tableNameAndKeyFromDbMapGet((*dbDataMap)[cdb]) jsonData = fmt.Sprintf("{\r\n \"%v\" : \"%v\" \r\n }\r\n", xSpecMap[reqXpath].yangEntry.Name, - dbDataMap[cdb][tbl][key].Field[fldName]) + (*dbDataMap)[cdb][tbl][key].Field[fldName]) return jsonData, nil } else { yangDataFill(dbs, ygRoot, uri, reqXpath, dbDataMap, resultMap, tableName, keyName, cdb) diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index 52dd9bea1c..9a92d3a3a5 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -78,7 +78,9 @@ func mapFillData(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, dbKey st if nErr != nil { return nErr } - ret, err := XlateFuncCall(yangToDbXfmrFunc(xSpecMap[xpath].xfmrFunc), d, ygRoot, oper, uri, node[0].Data) + var dbs [db.MaxDB]*db.DB + inParams := formXfmrInputRequest(d, dbs, db.MaxDB, ygRoot, uri, oper, "", nil, node[0].Data) + ret, err := XlateFuncCall(yangToDbXfmrFunc(xSpecMap[xpath].xfmrFunc), inParams) if err != nil { return err } @@ -259,6 +261,7 @@ func dbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string, jsonDat func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, xpathPrefix string, keyName string, jsonData interface{}, result map[string]map[string]db.Value) error { log.Info("key(\"%v\"), xpathPrefix(\"%v\").", keyName, xpathPrefix) + var dbs [db.MaxDB]*db.DB if reflect.ValueOf(jsonData).Kind() == reflect.Slice { log.Info("slice data: key(\"%v\"), xpathPrefix(\"%v\").", keyName, xpathPrefix) @@ -272,7 +275,8 @@ func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, curUri := uriWithKeyCreate(uri, xpathPrefix, data) if len(xSpecMap[xpathPrefix].xfmrKey) > 0 { /* key transformer present */ - ret, err := XlateFuncCall(yangToDbXfmrFunc(xSpecMap[xpathPrefix].xfmrKey), d, ygRoot, oper, curUri) + inParams := formXfmrInputRequest(d, dbs, db.MaxDB, ygRoot, curUri, oper, "", nil, nil) + ret, err := XlateFuncCall(yangToDbXfmrFunc(xSpecMap[xpathPrefix].xfmrKey), inParams) if err != nil { return err } @@ -303,7 +307,8 @@ func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, if xSpecMap[xpath] != nil && len(xSpecMap[xpath].xfmrFunc) > 0 { /* subtree transformer present */ - ret, err := XlateFuncCall(yangToDbXfmrFunc(xSpecMap[xpath].xfmrFunc), d, ygRoot, oper, curUri) + inParams := formXfmrInputRequest(d, dbs, db.MaxDB, ygRoot, curUri, oper, "", nil, nil) + ret, err := XlateFuncCall(yangToDbXfmrFunc(xSpecMap[xpath].xfmrFunc), inParams) if err != nil { return nil } @@ -357,6 +362,7 @@ func xpathKeyExtract(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string) (st tableName := "" rgp := regexp.MustCompile(`\[([^\[\]]*)\]`) curPathWithKey := "" + var dbs [db.MaxDB]*db.DB for _, k := range strings.Split(path, "/") { curPathWithKey += k @@ -369,7 +375,8 @@ func xpathKeyExtract(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string) (st if ok { if len(xSpecMap[yangXpath].xfmrKey) > 0 { xfmrFuncName := yangToDbXfmrFunc(xSpecMap[yangXpath].xfmrKey) - ret, err := XlateFuncCall(xfmrFuncName, d, ygRoot, oper, curPathWithKey) + inParams := formXfmrInputRequest(d, dbs, db.MaxDB, ygRoot, curPathWithKey, oper, "", nil, nil) + ret, err := XlateFuncCall(xfmrFuncName, inParams) if err != nil { return "", "", "" } diff --git a/src/translib/transformer/xlate_utils.go b/src/translib/transformer/xlate_utils.go index b8540e1c5e..6c96e09bc3 100644 --- a/src/translib/transformer/xlate_utils.go +++ b/src/translib/transformer/xlate_utils.go @@ -98,8 +98,9 @@ func dbKeyToYangDataConvert(uri string, xpath string, dbKey string) (map[string] } if len(xSpecMap[xpath].xfmrKey) > 0 { - var d *db.DB - ret, err := XlateFuncCall(dbToYangXfmrFunc(xSpecMap[xpath].xfmrKey), d, GET, dbKey) + var dbs [db.MaxDB]*db.DB + inParams := formXfmrInputRequest(nil, dbs, db.MaxDB, nil, uri, GET, dbKey, nil, nil) + ret, err := XlateFuncCall(dbToYangXfmrFunc(xSpecMap[xpath].xfmrKey), inParams) if err != nil { return nil, "","",err } @@ -309,3 +310,18 @@ func mapGet(xpath string, inMap map[string]interface{}) map[string]interface{} { retMap := mapInstGet(attrList, 1, alLen, inMap) return retMap } + +func formXfmrInputRequest(d *db.DB, dbs [db.MaxDB]*db.DB, cdb db.DBNum, ygRoot *ygot.GoStruct, uri string, oper int, key string, dbDataMap *map[db.DBNum]map[string]map[string]db.Value, param interface{}) XfmrParams { + var inParams XfmrParams + inParams.d = d + inParams.dbs = dbs + inParams.curDb = cdb + inParams.ygRoot = ygRoot + inParams.uri = uri + inParams.oper = oper + inParams.key = key + inParams.dbDataMap = dbDataMap + inParams.param = param // generic param + + return inParams +} From 583c16c6f4d84365ba64f132813fcf1078a4cae8 Mon Sep 17 00:00:00 2001 From: s-mari Date: Tue, 10 Sep 2019 22:45:51 -0700 Subject: [PATCH 105/214] modified acl-key xfmr to return integer and enhanced the get-req handling in common app. --- src/translib/common_app.go | 38 ++++++++++++++-------- src/translib/transformer/xfmr_acl.go | 6 ++-- src/translib/transformer/xfmr_interface.go | 5 ++- src/translib/transformer/xlate_from_db.go | 8 ++++- src/translib/transformer/xlate_utils.go | 6 ++-- 5 files changed, 40 insertions(+), 23 deletions(-) diff --git a/src/translib/common_app.go b/src/translib/common_app.go index 5a5ea1f837..d532fd14e0 100644 --- a/src/translib/common_app.go +++ b/src/translib/common_app.go @@ -8,6 +8,7 @@ import ( "github.com/openconfig/ygot/ygot" "reflect" "translib/db" + "translib/ocbinds" "translib/tlerr" "translib/transformer" "encoding/json" @@ -152,19 +153,30 @@ func (app *CommonApp) processDelete(d *db.DB) (SetResponse, error) { } func (app *CommonApp) processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error) { - var err error - var payload []byte - log.Info("processGet:path =", app.pathInfo.Path) - - payload, err = transformer.GetAndXlateFromDB(app.pathInfo.Path, app.ygotRoot, dbs) - if err != nil { - log.Error("transformer.XlateFromDb() failure") - return GetResponse{Payload: payload, ErrSrc: AppErr}, err - } - var dat map[string]interface{} - err = json.Unmarshal(payload, &dat) - fmt.Println("RESULT ******* ", dat) - + var err error + var payload []byte + log.Info("processGet:path =", app.pathInfo.Path) + + payload, err = transformer.GetAndXlateFromDB(app.pathInfo.Path, app.ygotRoot, dbs) + if err != nil { + log.Error("transformer.XlateFromDb() failure") + return GetResponse{Payload: payload, ErrSrc: AppErr}, err + } + + targetObj, _ := (*app.ygotTarget).(ygot.GoStruct) + err = ocbinds.Unmarshal(payload, targetObj) + if err != nil { + log.Error("ocbinds.Unmarshal() failed") + return GetResponse{Payload: payload, ErrSrc: AppErr}, err + } + + payload, err = generateGetResponsePayload(app.pathInfo.Path, (*app.ygotRoot).(*ocbinds.Device), app.ygotTarget) + if err != nil { + log.Error("generateGetResponsePayload() failed") + return GetResponse{Payload: payload, ErrSrc: AppErr}, err + } + var dat map[string]interface{} + err = json.Unmarshal(payload, &dat) return GetResponse{Payload: payload}, err } diff --git a/src/translib/transformer/xfmr_acl.go b/src/translib/transformer/xfmr_acl.go index 470073a5bd..436ae001d6 100644 --- a/src/translib/transformer/xfmr_acl.go +++ b/src/translib/transformer/xfmr_acl.go @@ -238,8 +238,8 @@ var YangToDb_acl_entry_key_xfmr KeyXfmrYangToDb = func (inParams XfmrParams) (st return entry_key, err } -var DbToYang_acl_entry_key_xfmr KeyXfmrDbToYang = func (inParams XfmrParams) (map[string]string, error) { - rmap := make(map[string]string) +var DbToYang_acl_entry_key_xfmr KeyXfmrDbToYang = func (inParams XfmrParams) (map[string]interface{}, error) { + rmap := make(map[string]interface{}) var err error entry_key := inParams.key log.Info("DbToYang_acl_entry_key_xfmr: ", entry_key) @@ -253,7 +253,7 @@ var DbToYang_acl_entry_key_xfmr KeyXfmrDbToYang = func (inParams XfmrParams) (ma dbAclRule := key[1] seqId := strings.Replace(dbAclRule, "RULE_", "", 1) - rmap["sequence-id"] = seqId + rmap["sequence-id"], _ = strconv.ParseFloat(seqId, 64) return rmap, err } diff --git a/src/translib/transformer/xfmr_interface.go b/src/translib/transformer/xfmr_interface.go index 9fc7a68684..77b512e992 100644 --- a/src/translib/transformer/xfmr_interface.go +++ b/src/translib/transformer/xfmr_interface.go @@ -3,8 +3,7 @@ package transformer import ( "github.com/openconfig/ygot/ygot" "translib/db" - log "github.com/golang/glog" -// "translib/ocbinds" + log "github.com/golang/glog" ) type XfmrParams struct { @@ -32,7 +31,7 @@ type KeyXfmrYangToDb func (inParams XfmrParams) (string, error) * Param: Database info, operation, Database keys to access db entry * Return: multi dimensional map to hold the yang key attributes of complete xpath, error **/ -type KeyXfmrDbToYang func (inParams XfmrParams) (map[string]string, error) +type KeyXfmrDbToYang func (inParams XfmrParams) (map[string]interface{}, error) /** * FieldXfmrYangToDb type is defined to use for conversion of yang Field to DB field diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index 1b476dbc64..b636c4351f 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -6,6 +6,7 @@ import ( "strings" "encoding/json" "os" + "strconv" "translib/ocbinds" "github.com/openconfig/ygot/ygot" "github.com/openconfig/ygot/ytypes" @@ -160,7 +161,12 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath if len(dbFldName) > 0 && !xSpecMap[chldXpath].isKey { val, ok := (*dbDataMap)[cdb][tbl][tblKey].Field[dbFldName] if ok { - resultMap[xSpecMap[chldXpath].yangEntry.Name] = val + valInt, err := strconv.Atoi(val) + if err == nil { + resultMap[xSpecMap[chldXpath].yangEntry.Name] = valInt + } else { + resultMap[xSpecMap[chldXpath].yangEntry.Name] = val + } } } } diff --git a/src/translib/transformer/xlate_utils.go b/src/translib/transformer/xlate_utils.go index 6c96e09bc3..d3dbe1d3ce 100644 --- a/src/translib/transformer/xlate_utils.go +++ b/src/translib/transformer/xlate_utils.go @@ -84,7 +84,7 @@ func yangTypeGet(entry *yang.Entry) string { return "" } -func dbKeyToYangDataConvert(uri string, xpath string, dbKey string) (map[string]string, string, string, error) { +func dbKeyToYangDataConvert(uri string, xpath string, dbKey string) (map[string]interface{}, string, string, error) { var kLvlValList []string keyDataList := strings.Split(dbKey, "|") keyNameList := yangKeyFromEntryGet(xSpecMap[xpath].yangEntry) @@ -104,7 +104,7 @@ func dbKeyToYangDataConvert(uri string, xpath string, dbKey string) (map[string] if err != nil { return nil, "","",err } - rmap := ret[0].Interface().(map[string]string) + rmap := ret[0].Interface().(map[string]interface{}) for k, v := range rmap { jsonData += fmt.Sprintf("\"%v\" : \"%v\",\r\n", k, v) uriWithKey += fmt.Sprintf("[%v=%v]", k, v) @@ -125,7 +125,7 @@ func dbKeyToYangDataConvert(uri string, xpath string, dbKey string) (map[string] chgId = len(keyNameList) - 1 } - rmap := make(map[string]string) + rmap := make(map[string]interface{}) for i, kname := range keyNameList { kval := kLvlValList[i] From df0f7ff23b6e60e8287ea2c293c7909f93e8a411 Mon Sep 17 00:00:00 2001 From: Kwan Kim Date: Wed, 11 Sep 2019 01:20:47 -0700 Subject: [PATCH 106/214] make common-app as default to handle acl, add the field-xfmr for acl type --- .../annotations/openconfig-acl-annot.yang | 6 + src/translib/acl_app.go | 369 ------------- src/translib/acl_app_test.go | 503 ------------------ src/translib/common_app.go | 8 +- src/translib/transformer/xfmr_acl.go | 33 ++ src/translib/transformer/xfmr_path_utils.go | 14 + src/translib/transformer/xlate_utils.go | 29 + 7 files changed, 89 insertions(+), 873 deletions(-) delete mode 100644 src/translib/acl_app.go delete mode 100644 src/translib/acl_app_test.go diff --git a/models/yang/annotations/openconfig-acl-annot.yang b/models/yang/annotations/openconfig-acl-annot.yang index 812db798b8..c4e6ecf54a 100644 --- a/models/yang/annotations/openconfig-acl-annot.yang +++ b/models/yang/annotations/openconfig-acl-annot.yang @@ -22,6 +22,12 @@ module openconfig-acl-annot { } } + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:config/oc-acl:type { + deviate add { + sonic-ext:field-transformer "acl_type_field_xfmr"; + } + } + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:config/oc-acl:description { deviate add { sonic-ext:field-name "policy_desc"; diff --git a/src/translib/acl_app.go b/src/translib/acl_app.go deleted file mode 100644 index e5df355d9d..0000000000 --- a/src/translib/acl_app.go +++ /dev/null @@ -1,369 +0,0 @@ -/////////////////////////////////////////////////////////////////////// -// -// Copyright 2019 Broadcom. All rights reserved. -// The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. -// -/////////////////////////////////////////////////////////////////////// - -package translib - -import ( - "reflect" - "strings" - "translib/db" - "translib/ocbinds" - "translib/tlerr" - "translib/transformer" - - log "github.com/golang/glog" - "github.com/openconfig/ygot/ygot" -) - -const ( - TABLE_SEPARATOR = "|" - KEY_SEPARATOR = "|" - ACL_TABLE = "ACL_TABLE" - RULE_TABLE = "ACL_RULE" -) - -type configHandler func(*db.DB, *AclApp, int) error - -type AclApp struct { - pathInfo *PathInfo - ygotRoot *ygot.GoStruct - ygotTarget *interface{} - - aclTs *db.TableSpec - ruleTs *db.TableSpec - - aclTableMap map[string]db.Value - ruleTableMap map[string]db.Value - //ruleTableMap map[string]map[string]db.Value - callpoints map[string]configHandler -} - -func init() { - - err := register("/openconfig-acl:acl", - &appInfo{appType: reflect.TypeOf(AclApp{}), - ygotRootType: reflect.TypeOf(ocbinds.OpenconfigAcl_Acl{}), - isNative: false, - tablesToWatch: []*db.TableSpec{&db.TableSpec{Name: ACL_TABLE}, &db.TableSpec{Name: RULE_TABLE}}}) - - if err != nil { - log.Fatal("Register ACL app module with App Interface failed with error=", err) - } - - err = addModel(&ModelData{Name: "openconfig-acl", - Org: "OpenConfig working group", - Ver: "1.0.2"}) - if err != nil { - log.Fatal("Adding model data to appinterface failed with error=", err) - } -} - -func (app *AclApp) initialize(data appData) { - log.Info("initialize:acl:path =", data.path) - pathInfo := NewPathInfo(data.path) - *app = AclApp{pathInfo: pathInfo, ygotRoot: data.ygotRoot, ygotTarget: data.ygotTarget} - - app.aclTs = &db.TableSpec{Name: ACL_TABLE} - app.ruleTs = &db.TableSpec{Name: RULE_TABLE} - - app.aclTableMap = make(map[string]db.Value) - app.ruleTableMap = make(map[string]db.Value) - - app.callpoints = map[string]configHandler{ - "/openconfig-acl:acl": handleAcl, - "/openconfig-acl:acl/acl-sets": handleAclSet, - "/openconfig-acl:acl/acl-sets/acl-set": handleAclSet, - "/openconfig-acl:acl/acl-sets/acl-set/acl-entries": handleAclEntry, - "/openconfig-acl:acl/acl-sets/acl-set/acl-entries/acl-entry": handleAclEntry, - "/openconfig-acl:acl/interfaces": handleAclInterface, - } -} - -func (app *AclApp) getAppRootObject() *ocbinds.OpenconfigAcl_Acl { - deviceObj := (*app.ygotRoot).(*ocbinds.Device) - return deviceObj.Acl -} - -func (app *AclApp) translateCreate(d *db.DB) ([]db.WatchKeys, error) { - var err error - var keys []db.WatchKeys - log.Info("translateCreate:acl:path =", app.pathInfo.Template) - - keys, err = app.translateCRUDCommon(d, CREATE) - return keys, err -} - -func (app *AclApp) translateUpdate(d *db.DB) ([]db.WatchKeys, error) { - var err error - var keys []db.WatchKeys - log.Info("translateUpdate:acl:path =", app.pathInfo.Template) - - keys, err = app.translateCRUDCommon(d, UPDATE) - return keys, err -} - -func (app *AclApp) translateReplace(d *db.DB) ([]db.WatchKeys, error) { - var err error - var keys []db.WatchKeys - log.Info("translateReplace:acl:path =", app.pathInfo.Template) - - keys, err = app.translateCRUDCommon(d, REPLACE) - return keys, err -} - -func (app *AclApp) translateDelete(d *db.DB) ([]db.WatchKeys, error) { - var err error - var keys []db.WatchKeys - log.Info("translateDelete:acl:path =", app.pathInfo.Path) - - keys, err = app.translateCRUDCommon(d, DELETE) - return keys, err -} - -func (app *AclApp) translateGet(dbs [db.MaxDB]*db.DB) error { - var err error - log.Info("translateGet:acl:path =", app.pathInfo.Template) - return err -} - -func (app *AclApp) translateSubscribe(dbs [db.MaxDB]*db.DB, path string) (*notificationOpts, *notificationInfo, error) { - - return nil, nil, nil -} - -func (app *AclApp) processCreate(d *db.DB) (SetResponse, error) { - var err error - var resp SetResponse - - if err = app.processCommon(d, CREATE); err != nil { - log.Error(err) - resp = SetResponse{ErrSrc: AppErr} - } - return resp, err -} - -func (app *AclApp) processUpdate(d *db.DB) (SetResponse, error) { - var err error - var resp SetResponse - - if err = app.processCommon(d, UPDATE); err != nil { - log.Error(err) - resp = SetResponse{ErrSrc: AppErr} - } - return resp, err -} - -func (app *AclApp) processReplace(d *db.DB) (SetResponse, error) { - var err error - var resp SetResponse - - if err = app.processCommon(d, REPLACE); err != nil { - log.Error(err) - resp = SetResponse{ErrSrc: AppErr} - } - return resp, err -} - -func (app *AclApp) processDelete(d *db.DB) (SetResponse, error) { - var err error - var resp SetResponse - - if err = app.processCommon(d, DELETE); err != nil { - log.Error(err) - resp = SetResponse{ErrSrc: AppErr} - } - return resp, err -} - -func (app *AclApp) processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error) { - var err error - var payload []byte - - payload, err = transformer.GetAndXlateFromDB(app.pathInfo.Path, app.ygotRoot, dbs) - if err != nil { - return GetResponse{Payload: payload, ErrSrc: AppErr}, err - } - return GetResponse{Payload: payload}, err -} - -func (app *AclApp) translateCRUDCommon(d *db.DB, opcode int) ([]db.WatchKeys, error) { - var err error - var keys []db.WatchKeys - log.Info("translateCRUDCommon:acl:path =", app.pathInfo.Path) - d.Opts.DisableCVLCheck = true; - - result, err := transformer.XlateToDb(app.pathInfo.Path, opcode, d, app.ygotRoot, app.ygotTarget) - if err != nil { - return nil, err - } - - app.aclTableMap = result["ACL_TABLE"] - app.ruleTableMap = result["ACL_RULE"] - // add app specific as needed, e.g. default rule - - return keys, err -} - -func handleAclInterface(d *db.DB, app *AclApp, opcode int) error { - var err error - for key, data := range app.aclTableMap { - existingEntry, err := d.GetEntry(app.aclTs, db.Key{Comp: []string{key}}) - if opcode == CREATE && existingEntry.Field != nil { - return tlerr.AlreadyExists("Acl %s already exists", key) - } - // !!! Overloaded xfmr methods tale care for bindings, to set the data - switch opcode { - case CREATE: - case REPLACE: - case UPDATE: - case DELETE: - err = d.SetEntry(app.aclTs, db.Key{Comp: []string{key}}, data) - } - if err != nil { - break - } - } - return err -} - -func handleAclSet(d *db.DB, app *AclApp, opcode int) error { - var err error - - // acl table - for key, data := range app.aclTableMap { - existingEntry, err := d.GetEntry(app.aclTs, db.Key{Comp: []string{key}}) - if opcode == CREATE && existingEntry.Field != nil { - return tlerr.AlreadyExists("Acl %s already exists", key) - } - switch opcode { - case CREATE: - err = d.CreateEntry(app.aclTs, db.Key{Comp: []string{key}}, data) - case REPLACE: - if !existingEntry.IsPopulated() { - err = d.CreateEntry(app.aclTs, db.Key{Comp: []string{key}}, data) - } else { - // !!! delete & add an entry?? Here just shows the set operation as showcase - err = d.SetEntry(app.aclTs, db.Key{Comp: []string{key}}, data) - } - case UPDATE: - err = d.ModEntry(app.aclTs, db.Key{Comp: []string{key}}, data) - case DELETE: - err = handleAclDelete(d, app.aclTs, key, data) - } - if err != nil { - break - } - } - // acl rule - if err == nil { - err = handleAclEntry(d, app, opcode) - } - - return err -} -func handleAclEntry(d *db.DB, app *AclApp, opcode int) error { - var err error - - for key, data := range app.ruleTableMap { - ruleName := strings.Split(key, KEY_SEPARATOR)[1] - existingEntry, err := d.GetEntry(app.ruleTs, db.Key{Comp: []string{key}}) - if opcode == CREATE && existingEntry.Field != nil { - return tlerr.AlreadyExists("Acl rule %s already exists", ruleName) - } - switch opcode { - case CREATE: - err = d.CreateEntry(app.ruleTs, db.Key{Comp: []string{key}}, data) - case REPLACE: - if !existingEntry.IsPopulated() { - err = d.CreateEntry(app.ruleTs, db.Key{Comp: []string{key}}, data) - } else { - // !!! delete & add an entry?? Here just shows the merge operation as showcase - err = d.SetEntry(app.ruleTs, db.Key{Comp: []string{key}}, data) - } - case UPDATE: - err = d.ModEntry(app.ruleTs, db.Key{Comp: []string{key}}, data) - case DELETE: - err = handleAclDelete(d, app.ruleTs, key, data) - } - if err != nil { - break - } - } - return err -} -func handleAcl(d *db.DB, app *AclApp, opcode int) error { - var err error - var val db.Value - - // Delete all acl rules - err = handleAclDelete(d, app.ruleTs, "", val) - if err != nil { - log.Errorf("handleAcl: Failed to delete Acl Rule Table") - return err - } - - // Delete all acl tables - err = handleAclDelete(d, app.aclTs, "", val) - if err != nil { - log.Errorf("handleAcl: Failed to delete Acl Table") - } - - return err -} - -func (app *AclApp) processCommon(d *db.DB, opcode int) error { - var err error - - log.Infof("processCommon--Path Received: %s", app.pathInfo.Path) - // test - d.Opts.DisableCVLCheck = true - - xpath, err := transformer.RemoveXPATHPredicates(app.pathInfo.Path) - log.Infof("processCommon--xPath to process: %s", xpath) - if err != nil { - log.Errorf("processCommon: Failed to remove Xpath Predicates from path %s", app.pathInfo.Template) - } - - if _, ok := app.callpoints[xpath]; ok { - if err = app.callpoints[xpath](d, app, opcode); err != nil { - log.Errorf("processCommon: Given path %s not handled", app.pathInfo.Template) - } - } else { - // fallback callpoints - if strings.Contains(xpath, "/openconfig-acl:acl/acl-sets/acl-set/acl-entries/acl-entry") { - err = handleAclEntry(d, app, opcode) - } else if strings.Contains(xpath, "/openconfig-acl:acl/acl-sets/acl-set") { - err = handleAclSet(d, app, opcode) - } else if strings.Contains(xpath, "/openconfig-acl:acl/interfaces") { - err = handleAclInterface(d, app, opcode) - } else { - err = tlerr.NotSupported("URL %s is not supported", app.pathInfo.Path) - } - } - - return err -} - -func handleAclDelete(d *db.DB, ts *db.TableSpec, key string, value db.Value) error { - var err error - if len(value.Field) > 0 { - // Field entries exist - err = d.DeleteEntryFields(ts, db.Key{Comp: []string{key}}, value) - } else if len(key) > 0 { - // Delete entrire table instance with the required key - err = d.DeleteKeys(ts, db.Key{Comp: []string{key}}) - } else { - // Delete the whole table - err = d.DeleteTable(ts) - } - if err != nil { - log.Error("DELETE case - d.DeleteTable() failure for Table = ", ts.Name) - return err - } - - return err -} diff --git a/src/translib/acl_app_test.go b/src/translib/acl_app_test.go deleted file mode 100644 index c6d6dced86..0000000000 --- a/src/translib/acl_app_test.go +++ /dev/null @@ -1,503 +0,0 @@ -package translib - -import ( - "errors" - "fmt" - "os" - "reflect" - "strings" - "testing" - db "translib/db" -) - -func init() { - fmt.Println("+++++ Init acl_app_test +++++") -} - -func TestMain(m *testing.M) { - if err := clearAclDataFromDb(); err != nil { - os.Exit(-1) - } - fmt.Println("+++++ Removed All Acl Data from Db +++++") - - ret := m.Run() - - if err := clearAclDataFromDb(); err != nil { - os.Exit(-1) - } - - os.Exit(ret) -} - -// This will test GET on /openconfig-acl:acl -func Test_AclApp_TopLevelPath(t *testing.T) { - url := "/openconfig-acl:acl" - - t.Run("Empty_Response_Top_Level", processGetRequest(url, emptyJson, false)) - - t.Run("Bulk_Create_Top_Level", processSetRequest(url, bulkAclCreateJsonRequest, "POST", false)) - - t.Run("Get_Full_Acl_Tree_Top_Level", processGetRequest(url, bulkAclCreateJsonResponse, false)) - - // Delete all bindings before deleting at top level - t.Run("Delete_All_Bindings_Top_Level", processDeleteRequest("/openconfig-acl:acl/interfaces")) - t.Run("Delete_Full_ACl_Tree_Top_Level", processDeleteRequest(url)) - - t.Run("Verify_Top_Level_Delete", processGetRequest(url, emptyJson, false)) -} - -func Test_AclApp_SingleAclOperations(t *testing.T) { - url := "/openconfig-acl:acl/acl-sets/acl-set[name=MyACL3][type=ACL_IPV4]" - - t.Run("Create_One_Acl_With_Multiple_Rules(PATCH)", processSetRequest(url, oneAclCreateWithRulesJsonRequest, "PATCH", false)) - - t.Run("Verify_Create_One_Acl_With_Multiple_Rules", processGetRequest(url, oneAclCreateWithRulesJsonResponse, false)) - - t.Run("Delete_One_Acl_With_All_Its_Rules", processDeleteRequest(url)) - - t.Run("Verify_One_Acl_Delete", processGetRequest(url, "", true)) -} - -func Test_AclApp_SingleRuleOperations(t *testing.T) { - aclUrl := "/openconfig-acl:acl/acl-sets/acl-set[name=MyACL5][type=ACL_IPV4]" - ruleUrl := "/openconfig-acl:acl/acl-sets/acl-set[name=MyACL5][type=ACL_IPV4]/acl-entries/acl-entry[sequence-id=8]" - - t.Run("Create_One_Acl_Without_Rule", processSetRequest(aclUrl, oneAclCreateJsonRequest, "POST", false)) - t.Run("Get_One_Acl_Without_Rule", processGetRequest(aclUrl, oneAclCreateJsonResponse, false)) - - t.Run("Create_One_Rule", processSetRequest(ruleUrl, requestOneRulePostJson, "POST", false)) - t.Run("Get_One_Rule", processGetRequest(ruleUrl, responseOneRuleJson, false)) - - // Change Source/Desination address and protocol - t.Run("Update_Existing_Rule", processSetRequest(ruleUrl, requestOneRulePatchJson, "PATCH", false)) - t.Run("Verify_One_Rule_Updation", processGetRequest(ruleUrl, responseOneRulePatchJson, false)) - - t.Run("Delete_One_Rule", processDeleteRequest(ruleUrl)) - t.Run("Verify_One_Rule_Delete", processGetRequest(ruleUrl, "", true)) - - t.Run("Delete_One_Acl", processDeleteRequest(aclUrl)) - t.Run("Verify_One_Acl_Delete", processGetRequest(aclUrl, "", true)) -} - -// This will test PUT (Replace) operation by Replacing multiple Rules with one Rule in an Acl -func Test_AclApp_ReplaceMultipleRulesWithOneRule(t *testing.T) { - url := "/openconfig-acl:acl/acl-sets/acl-set[name=MyACL3][type=ACL_IPV4]" - - t.Run("Create_One_Acl_With_Multiple_Rules(PATCH)", processSetRequest(url, oneAclCreateWithRulesJsonRequest, "PATCH", false)) - t.Run("Verify_Create_One_Acl_With_Multiple_Rules", processGetRequest(url, oneAclCreateWithRulesJsonResponse, false)) - - t.Run("Replace_All_Rules_With_One_Rule", processSetRequest(url, replaceMultiRulesWithOneRuleJsonRequest, "PUT", false)) - t.Run("Verify_Acl_With_Replaced_Rules", processGetRequest(url, replaceMultiRulesWithOneRuleJsonResponse, false)) - - t.Run("Delete_One_Acl_With_All_Its_Rules", processDeleteRequest(url)) - t.Run("Verify_One_Acl_Delete", processGetRequest(url, "", true)) -} - -// This will test PATCH operation by modifying Description of an Acl -func Test_AclApp_AclDescriptionUpdation(t *testing.T) { - aclUrl := "/openconfig-acl:acl/acl-sets/acl-set[name=MyACL5][type=ACL_IPV4]" - descrUrl := "/openconfig-acl:acl/acl-sets/acl-set[name=MyACL5][type=ACL_IPV4]/config/description" - - t.Run("Create_One_Acl_Without_Rule", processSetRequest(aclUrl, oneAclCreateJsonRequest, "POST", false)) - - t.Run("Update_Description_of_Acl", processSetRequest(descrUrl, aclDescrUpdateJson, "PATCH", false)) - t.Run("Verify_Description_of_Acl", processGetRequest(descrUrl, aclDescrUpdateJson, false)) - - t.Run("Delete_One_Acl", processDeleteRequest(aclUrl)) - t.Run("Verify_One_Acl_Delete", processGetRequest(aclUrl, "", true)) -} - -func Test_AclApp_AclIngressBindingOperations(t *testing.T) { - aclUrl := "/openconfig-acl:acl/acl-sets/acl-set[name=MyACL5][type=ACL_IPV4]" - ruleUrl := "/openconfig-acl:acl/acl-sets/acl-set[name=MyACL5][type=ACL_IPV4]/acl-entries/acl-entry[sequence-id=8]" - bindingUrl := "/openconfig-acl:acl/interfaces/interface[id=Ethernet4]/ingress-acl-sets/ingress-acl-set[set-name=MyACL5][type=ACL_IPV4]" - - t.Run("Create_One_Acl_Without_Rule", processSetRequest(aclUrl, oneAclCreateJsonRequest, "POST", false)) - - t.Run("Create_One_Rule", processSetRequest(ruleUrl, requestOneRulePostJson, "POST", false)) - - t.Run("Create_Ingress_Acl_set", processSetRequest(bindingUrl, ingressAclSetCreateJsonRequest, "POST", false)) - t.Run("Verify_Ingress_Aclset_Creation", processGetRequest(bindingUrl, ingressAclSetCreateJsonResponse, false)) - t.Run("Get_Port_Binding_From_Ingress_AclEntry_Level", processGetRequest(bindingUrl+"/acl-entries/acl-entry[sequence-id=8]", getBindingAclEntryResponse, false)) - - t.Run("Delete_Binding_From_Ingress_Aclset", processDeleteRequest(bindingUrl)) - t.Run("Verify_Binding_From_Ingress_Aclset_Deletion", processGetRequest(bindingUrl, "", true)) - t.Run("Delete_One_Rule", processDeleteRequest(ruleUrl)) - t.Run("Verify_One_Rule_Delete", processGetRequest(ruleUrl, "", true)) - - t.Run("Delete_One_Acl", processDeleteRequest(aclUrl)) - t.Run("Verify_One_Acl_Delete", processGetRequest(aclUrl, "", true)) -} - -func Test_AclApp_AclEgressBindingOperations(t *testing.T) { - aclUrl := "/openconfig-acl:acl/acl-sets/acl-set[name=MyACL5][type=ACL_IPV4]" - ruleUrl := "/openconfig-acl:acl/acl-sets/acl-set[name=MyACL5][type=ACL_IPV4]/acl-entries/acl-entry[sequence-id=8]" - bindingUrl := "/openconfig-acl:acl/interfaces/interface[id=Ethernet4]/egress-acl-sets/egress-acl-set[set-name=MyACL5][type=ACL_IPV4]" - - t.Run("Create_One_Acl_Without_Rule", processSetRequest(aclUrl, oneAclCreateJsonRequest, "POST", false)) - - t.Run("Create_One_Rule", processSetRequest(ruleUrl, requestOneRulePostJson, "POST", false)) - - t.Run("Create_Egress_Acl_set", processSetRequest(bindingUrl, ingressAclSetCreateJsonRequest, "POST", false)) - t.Run("Verify_Egress_Aclset_Creation", processGetRequest(bindingUrl, egressAclSetCreateJsonResponse, false)) - t.Run("Get_Port_Binding_From_Egress_AclEntry_Level", processGetRequest(bindingUrl+"/acl-entries/acl-entry[sequence-id=8]", getBindingAclEntryResponse, false)) - - t.Run("Delete_Binding_From_Egress_Aclset", processDeleteRequest(bindingUrl)) - t.Run("Verify_Binding_From_Egress_Aclset_Deletion", processGetRequest(bindingUrl, "", true)) - t.Run("Delete_One_Rule", processDeleteRequest(ruleUrl)) - t.Run("Verify_One_Rule_Delete", processGetRequest(ruleUrl, "", true)) - - t.Run("Delete_One_Acl", processDeleteRequest(aclUrl)) - t.Run("Verify_One_Acl_Delete", processGetRequest(aclUrl, "", true)) -} - -func Test_AclApp_GetOperationsFromMultipleTreeLevels(t *testing.T) { - aclUrl := "/openconfig-acl:acl/acl-sets/acl-set[name=MyACL5][type=ACL_IPV4]" - ruleUrl := "/openconfig-acl:acl/acl-sets/acl-set[name=MyACL5][type=ACL_IPV4]/acl-entries/acl-entry[sequence-id=8]" - bindingUrl := "/openconfig-acl:acl/interfaces/interface[id=Ethernet4]/egress-acl-sets/egress-acl-set[set-name=MyACL5][type=ACL_IPV4]" - - t.Run("Create_One_Acl_Without_Rule", processSetRequest(aclUrl, oneAclCreateJsonRequest, "POST", false)) - t.Run("Create_One_Rule", processSetRequest(ruleUrl, requestOneRulePostJson, "POST", false)) - t.Run("Create_Egress_Acl_set_Port_Binding", processSetRequest(bindingUrl, ingressAclSetCreateJsonRequest, "POST", false)) - - t.Run("Get_Acl_Tree_From_AclSets_level", processGetRequest("/openconfig-acl:acl/acl-sets", getFromAclSetsTreeLevelResponse, false)) - - t.Run("Get_All_Ports_Bindings_From_Interfaces_Tree_Level", processGetRequest("/openconfig-acl:acl/interfaces", getAllPortsFromInterfacesTreeLevelResponse, false)) - - t.Run("Get_One_Port_Binding_From_Interface_Tree_Level", processGetRequest("/openconfig-acl:acl/interfaces/interface[id=Ethernet4]", getPortBindingFromInterfaceTreeLevelResponse, false)) - - t.Run("Delete_Binding_From_Egress_Aclset", processDeleteRequest(bindingUrl)) - t.Run("Verify_Binding_From_Egress_Aclset_Deletion", processGetRequest(bindingUrl, "", true)) - - t.Run("Delete_One_Rule", processDeleteRequest(ruleUrl)) - t.Run("Verify_One_Rule_Delete", processGetRequest(ruleUrl, "", true)) - - t.Run("Delete_One_Acl", processDeleteRequest(aclUrl)) - t.Run("Verify_One_Acl_Delete", processGetRequest(aclUrl, "", true)) -} - -func Test_AclApp_AddNewPortBindingToAlreadyBindedAcl(t *testing.T) { - aclUrl := "/openconfig-acl:acl/acl-sets/acl-set[name=MyACL5][type=ACL_IPV4]" - ruleUrl := "/openconfig-acl:acl/acl-sets/acl-set[name=MyACL5][type=ACL_IPV4]/acl-entries/acl-entry[sequence-id=8]" - bindingUrl := "/openconfig-acl:acl/interfaces/interface[id=Ethernet4]/egress-acl-sets/egress-acl-set[set-name=MyACL5][type=ACL_IPV4]" - - t.Run("Create_One_Acl_Without_Rule", processSetRequest(aclUrl, oneAclCreateJsonRequest, "POST", false)) - t.Run("Create_One_Rule", processSetRequest(ruleUrl, requestOneRulePostJson, "POST", false)) - t.Run("Create_Egress_Acl_set_Port_Binding", processSetRequest(bindingUrl, ingressAclSetCreateJsonRequest, "POST", false)) - - newBindingUrl := "/openconfig-acl:acl/interfaces/interface[id=Ethernet0]/egress-acl-sets/egress-acl-set[set-name=MyACL5][type=ACL_IPV4]" - t.Run("Create_New_Egress_Acl_set_Port_Binding", processSetRequest(newBindingUrl, ingressAclSetCreateJsonRequest, "POST", false)) - - t.Run("Get_All_Ports_Bindings_From_Interfaces_Tree_Level", processGetRequest("/openconfig-acl:acl/interfaces", getMultiportBindingOnSingleAclResponse, false)) - - t.Run("Delete_All_Bindings_Top_Level", processDeleteRequest("/openconfig-acl:acl/interfaces")) - t.Run("Delete_All_Rules_Not_Acl", processDeleteRequest("/openconfig-acl:acl/acl-sets/acl-set[name=MyACL5][type=ACL_IPV4]/acl-entries")) - - t.Run("Delete_One_Acl", processDeleteRequest(aclUrl)) - t.Run("Verify_One_Acl_Delete", processGetRequest(aclUrl, "", true)) - - t.Run("Verify_Top_Level_Delete", processGetRequest("/openconfig-acl:acl", emptyJson, false)) -} - -func Test_AclApp_IPv6AclAndRule(t *testing.T) { - aclUrl := "/openconfig-acl:acl/acl-sets/acl-set[name=MyACL6][type=ACL_IPV6]" - ruleUrl := "/openconfig-acl:acl/acl-sets/acl-set[name=MyACL6][type=ACL_IPV6]/acl-entries/acl-entry[sequence-id=6]" - bindingUrl := "/openconfig-acl:acl/interfaces/interface[id=Ethernet4]/ingress-acl-sets/ingress-acl-set[set-name=MyACL6][type=ACL_IPV6]" - - t.Run("Create_One_IPv6_Acl_Without_Rule", processSetRequest(aclUrl, oneIPv6AclCreateJsonRequest, "POST", false)) - t.Run("Verify_One_IPv6_Acl_Without_Rule_Creation", processGetRequest(aclUrl, oneIPv6AclCreateJsonResponse, false)) - - t.Run("Create_One_IPv6_Rule", processSetRequest(ruleUrl, oneIPv6RuleCreateJsonRequest, "POST", false)) - t.Run("Verify_One_IPv6_Rule_Creation", processGetRequest(ruleUrl, oneIPv6RuleCreateJsonResponse, false)) - - t.Run("Create_Ingress_Acl_set", processSetRequest(bindingUrl, ingressIPv6AclSetCreateJsonRequest, "POST", false)) - t.Run("Verify_Ingress_Aclset_Creation", processGetRequest(bindingUrl, ingressIPv6AclSetCreateJsonResponse, false)) - - t.Run("Get_Acl_Tree_From_AclSet_level", processGetRequest("/openconfig-acl:acl/acl-sets/acl-set", getIPv6AclsFromAclSetListLevelResponse, false)) - t.Run("Get_All_Ports_Bindings_From_Interfaces_Tree_Level", processGetRequest("/openconfig-acl:acl/interfaces", getIPv6AllPortsBindingsResponse, false)) - - t.Run("Delete_Binding_From_Ingress_Aclset", processDeleteRequest(bindingUrl)) - t.Run("Verify_Binding_From_Ingress_Aclset_Deletion", processGetRequest(bindingUrl, "", true)) - t.Run("Delete_One_Rule", processDeleteRequest(ruleUrl)) - t.Run("Delete_One_Acl", processDeleteRequest(aclUrl)) - t.Run("Verify_One_Acl_Delete", processGetRequest(aclUrl, "", true)) -} - -func Test_AclApp_L2AclAndRule(t *testing.T) { - aclUrl := "/openconfig-acl:acl/acl-sets/acl-set[name=MyACL2][type=ACL_L2]" - ruleUrl := "/openconfig-acl:acl/acl-sets/acl-set[name=MyACL2][type=ACL_L2]/acl-entries/acl-entry[sequence-id=2]" - bindingUrl := "/openconfig-acl:acl/interfaces/interface[id=Ethernet0]/ingress-acl-sets/ingress-acl-set[set-name=MyACL2][type=ACL_L2]" - - t.Run("Create_One_L2_Acl_Without_Rule", processSetRequest(aclUrl, oneL2AclCreateJsonRequest, "POST", false)) - t.Run("Verify_One_L2_Acl_Without_Rule_Creation", processGetRequest(aclUrl, oneL2AclCreateJsonResponse, false)) - - t.Run("Create_One_L2_Rule", processSetRequest(ruleUrl, oneL2RuleCreateJsonRequest, "POST", false)) - t.Run("Verify_One_L2_Rule_Creation", processGetRequest(ruleUrl, oneL2RuleCreateJsonResponse, false)) - - t.Run("Create_Ingress_L2_Acl_set", processSetRequest(bindingUrl, ingressL2AclSetCreateJsonRequest, "POST", false)) - t.Run("Verify_Ingress_L2_Aclset_Creation", processGetRequest(bindingUrl, ingressL2AclSetCreateJsonResponse, false)) - - t.Run("Get_Acl_Tree_From_AclSet_level", processGetRequest("/openconfig-acl:acl/acl-sets/acl-set", getL2AclsFromAclSetListLevelResponse, false)) - t.Run("Get_All_Ports_Bindings_From_Interfaces_Tree_Level", processGetRequest("/openconfig-acl:acl/interfaces", getL2AllPortsBindingsResponse, false)) - - t.Run("Delete_Binding_From_Ingress_Aclset", processDeleteRequest(bindingUrl)) - t.Run("Verify_Binding_From_Ingress_Aclset_Deletion", processGetRequest(bindingUrl, "", true)) - t.Run("Delete_One_Rule", processDeleteRequest(ruleUrl)) - t.Run("Delete_One_Acl", processDeleteRequest(aclUrl)) - t.Run("Verify_One_Acl_Delete", processGetRequest(aclUrl, "", true)) -} - -func Test_AclApp_NegativeTests(t *testing.T) { - // Verify GET returns errors for non-existing ACL - aclUrl := "/openconfig-acl:acl/acl-sets/acl-set[name=MyACL2][type=ACL_L2]" - t.Run("Verify_Non_Existing_Acl_GET_Error", processGetRequest(aclUrl, "", true)) - - // Verify GET returns errors for non-existing Rule - ruleUrl := "/openconfig-acl:acl/acl-sets/acl-set[name=MyACL2][type=ACL_L2]/acl-entries/acl-entry[sequence-id=2]" - t.Run("Verify_Non_Existing_Rule_GET_Error", processGetRequest(ruleUrl, "", true)) - - // Verify Error on giving Invalid Interface in payload during binding creation - url := "/openconfig-acl:acl" - t.Run("Create_Acl_With_Invalid_Interface_Binding", processSetRequest(url, aclCreateWithInvalidInterfaceBinding, "POST", true)) - - // Verify error if duplicate Acl is created using POST - t.Run("Create_One_L2_Acl_Without_Rule", processSetRequest(aclUrl, oneL2AclCreateJsonRequest, "POST", false)) - t.Run("Verify_One_L2_Acl_Without_Rule_Creation", processGetRequest(aclUrl, oneL2AclCreateJsonResponse, false)) - t.Run("Verify_Error_On_Create_Duplicate_L2_Acl", processSetRequest(aclUrl, oneL2AclCreateJsonRequest, "POST", true)) - - // Verify error if duplicate Rule is created using POST - multiRuleUrl := "/openconfig-acl:acl/acl-sets/acl-set[name=MyACL3][type=ACL_IPV4]" - t.Run("Create_One_Acl_With_Multiple_Rules(PATCH)", processSetRequest(multiRuleUrl, oneAclCreateWithRulesJsonRequest, "PATCH", false)) - t.Run("Verify_Create_One_Acl_With_Multiple_Rules", processGetRequest(multiRuleUrl, oneAclCreateWithRulesJsonResponse, true)) - - duplicateRuleUrl := "/openconfig-acl:acl/acl-sets/acl-set[name=MyACL3][type=ACL_IPV4]/acl-entries/acl-entry[sequence-id=1]" - t.Run("Create_One_Duplicate_Rule", processSetRequest(duplicateRuleUrl, requestOneDuplicateRulePostJson, "POST", true)) - - topLevelUrl := "/openconfig-acl:acl" - t.Run("Delete_Full_ACl_Tree_Top_Level", processDeleteRequest(topLevelUrl)) - t.Run("Verify_Top_Level_Delete", processGetRequest(topLevelUrl, emptyJson, false)) -} - -func processGetRequest(url string, expectedRespJson string, errorCase bool) func(*testing.T) { - return func(t *testing.T) { - response, err := Get(GetRequest{url}) - if err != nil && !errorCase { - t.Errorf("Error %v received for Url: %s", err, url) - } - - respJson := response.Payload - if string(respJson) != expectedRespJson { - t.Errorf("Response received not matching with expected for Url: %s", url) - } - } -} - -func processSetRequest(url string, jsonPayload string, oper string, errorCase bool) func(*testing.T) { - return func(t *testing.T) { - var err error - switch oper { - case "POST": - _, err = Create(SetRequest{Path: url, Payload: []byte(jsonPayload)}) - case "PATCH": - _, err = Update(SetRequest{Path: url, Payload: []byte(jsonPayload)}) - case "PUT": - _, err = Replace(SetRequest{Path: url, Payload: []byte(jsonPayload)}) - default: - t.Errorf("Operation not supported") - } - if err != nil && !errorCase { - t.Errorf("Error %v received for Url: %s", err, url) - } - } -} - -func processDeleteRequest(url string) func(*testing.T) { - return func(t *testing.T) { - _, err := Delete(SetRequest{Path: url}) - if err != nil { - t.Errorf("Error %v received for Url: %s", err, url) - } - } -} - -// THis will delete ACL table and Rules Table from DB -func clearAclDataFromDb() error { - var err error - ruleTable := db.TableSpec{Name: "ACL_RULE"} - aclTable := db.TableSpec{Name: "ACL_TABLE"} - - d := getConfigDb() - if d == nil { - err = errors.New("Failed to connect to config Db") - return err - } - if err = d.DeleteTable(&ruleTable); err != nil { - err = errors.New("Failed to delete Rules Table") - return err - } - if err = d.DeleteTable(&aclTable); err != nil { - err = errors.New("Failed to delete Acl Table") - return err - } - return err -} - -func getConfigDb() *db.DB { - configDb, _ := db.NewDB(db.Options{ - DBNo: db.ConfigDB, - InitIndicator: "CONFIG_DB_INITIALIZED", - TableNameSeparator: "|", - KeySeparator: "|", - }) - - return configDb -} - -func TestAclApp_Subscribe(t *testing.T) { - app := new(AclApp) - - t.Run("top", testSubsError(app, "/")) - t.Run("unknown", testSubsError(app, "/some/unknown/path")) - t.Run("topacl", testSubsError(app, "/openconfig-acl:acl")) - t.Run("aclsets", testSubsError(app, "/openconfig-acl:acl/acl-sets")) - t.Run("aclset*", testSubsError(app, "/openconfig-acl:acl/acl-sets/acl-set")) - t.Run("aclset", testSubsError(app, "/openconfig-acl:acl/acl-sets/acl-set[name=X][type=ACL_IPV4]")) - - t.Run("acl_config", testSubs(app, - "/openconfig-acl:acl/acl-sets/acl-set[name=X][type=ACL_IPV4]/config/description", - "ACL_TABLE", "X_ACL_IPV4", true)) - - t.Run("acl_state", testSubs(app, - "/openconfig-acl:acl/acl-sets/acl-set[name=X][type=ACL_IPV4]/state", - "ACL_TABLE", "X_ACL_IPV4", true)) - - t.Run("entries", testSubs(app, - "/openconfig-acl:acl/acl-sets/acl-set[name=X][type=ACL_IPV4]/acl-entries", - "ACL_RULE", "X_ACL_IPV4|*", false)) - - t.Run("rule*", testSubs(app, - "/openconfig-acl:acl/acl-sets/acl-set[name=X][type=ACL_IPV4]/acl-entries/acl-entry", - "ACL_RULE", "X_ACL_IPV4|*", false)) - - t.Run("rule", testSubs(app, - "/openconfig-acl:acl/acl-sets/acl-set[name=X][type=ACL_IPV4]/acl-entries/acl-entry[sequence-id=1]", - "ACL_RULE", "X_ACL_IPV4|RULE_1", false)) - - t.Run("rule_state", testSubs(app, - "/openconfig-acl:acl/acl-sets/acl-set[name=X][type=ACL_IPV4]/acl-entries/acl-entry[sequence-id=100]/state", - "ACL_RULE", "X_ACL_IPV4|RULE_100", true)) - - t.Run("rule_sip", testSubs(app, - "/openconfig-acl:acl/acl-sets/acl-set[name=X][type=ACL_IPV4]/acl-entries/acl-entry[sequence-id=200]/ipv4/config/source-address", - "ACL_RULE", "X_ACL_IPV4|RULE_200", true)) - -} - -// testSubs creates a test case which invokes translateSubscribe on an -// app interafce and check returned notificationInfo matches given values. -func testSubs(app appInterface, path, oTable, oKey string, oCache bool) func(*testing.T) { - return func(t *testing.T) { - _, nt, err := app.translateSubscribe([db.MaxDB]*db.DB{}, path) - if err != nil { - t.Fatalf("Unexpected error processing '%s'; err=%v", path, err) - } - if nt == nil || nt.needCache != oCache || nt.table.Name != oTable || - !reflect.DeepEqual(nt.key.Comp, strings.Split(oKey, "|")) { - t.Logf("translateSubscribe for path '%s'", path) - t.Logf("Expected table '%s', key '%v', cache %v", oTable, oKey, oCache) - if nt == nil { - t.Fatalf("Found nil") - } else { - t.Fatalf("Found table '%s', key '%s', cache %v", - nt.table.Name, strings.Join(nt.key.Comp, "|"), nt.needCache) - } - } - } -} - -// testSubsError creates a test case which invokes translateSubscribe on -// an app interafce and expects it to return an error -func testSubsError(app appInterface, path string) func(*testing.T) { - return func(t *testing.T) { - _, _, err := app.translateSubscribe([db.MaxDB]*db.DB{}, path) - if err == nil { - t.Fatalf("Expected error for path '%s'", path) - } - } -} - -/***************************************************************************/ -/////////// JSON Data for Tests /////////////// -/***************************************************************************/ -var emptyJson string = "{}" - -var bulkAclCreateJsonRequest string = "{\"acl-sets\":{\"acl-set\":[{\"name\":\"MyACL1\",\"type\":\"ACL_IPV4\",\"config\":{\"name\":\"MyACL1\",\"type\":\"ACL_IPV4\",\"description\":\"Description for MyACL1\"},\"acl-entries\":{\"acl-entry\":[{\"sequence-id\":1,\"config\":{\"sequence-id\":1,\"description\":\"Description for MyACL1 Rule Seq 1\"},\"ipv4\":{\"config\":{\"source-address\":\"11.1.1.1/32\",\"destination-address\":\"21.1.1.1/32\",\"dscp\":1,\"protocol\":\"IP_TCP\"}},\"transport\":{\"config\":{\"source-port\":101,\"destination-port\":201}},\"actions\":{\"config\":{\"forwarding-action\":\"ACCEPT\"}}},{\"sequence-id\":2,\"config\":{\"sequence-id\":2,\"description\":\"Description for MyACL1 Rule Seq 2\"},\"ipv4\":{\"config\":{\"source-address\":\"11.1.1.2/32\",\"destination-address\":\"21.1.1.2/32\",\"dscp\":2,\"protocol\":\"IP_TCP\"}},\"transport\":{\"config\":{\"source-port\":102,\"destination-port\":202}},\"actions\":{\"config\":{\"forwarding-action\":\"DROP\"}}},{\"sequence-id\":3,\"config\":{\"sequence-id\":3,\"description\":\"Description for MyACL1 Rule Seq 3\"},\"ipv4\":{\"config\":{\"source-address\":\"11.1.1.3/32\",\"destination-address\":\"21.1.1.3/32\",\"dscp\":3,\"protocol\":\"IP_TCP\"}},\"transport\":{\"config\":{\"source-port\":103,\"destination-port\":203}},\"actions\":{\"config\":{\"forwarding-action\":\"ACCEPT\"}}},{\"sequence-id\":4,\"config\":{\"sequence-id\":4,\"description\":\"Description for MyACL1 Rule Seq 4\"},\"ipv4\":{\"config\":{\"source-address\":\"11.1.1.4/32\",\"destination-address\":\"21.1.1.4/32\",\"dscp\":4,\"protocol\":\"IP_TCP\"}},\"transport\":{\"config\":{\"source-port\":104,\"destination-port\":204}},\"actions\":{\"config\":{\"forwarding-action\":\"DROP\"}}},{\"sequence-id\":5,\"config\":{\"sequence-id\":5,\"description\":\"Description for MyACL1 Rule Seq 5\"},\"ipv4\":{\"config\":{\"source-address\":\"11.1.1.5/32\",\"destination-address\":\"21.1.1.5/32\",\"dscp\":5,\"protocol\":\"IP_TCP\"}},\"transport\":{\"config\":{\"source-port\":105,\"destination-port\":205}},\"actions\":{\"config\":{\"forwarding-action\":\"ACCEPT\"}}}]}},{\"name\":\"MyACL2\",\"type\":\"ACL_IPV4\",\"config\":{\"name\":\"MyACL2\",\"type\":\"ACL_IPV4\",\"description\":\"Description for MyACL2\"},\"acl-entries\":{\"acl-entry\":[{\"sequence-id\":1,\"config\":{\"sequence-id\":1,\"description\":\"Description for Rule Seq 1\"},\"ipv4\":{\"config\":{\"source-address\":\"12.1.1.1/32\",\"destination-address\":\"22.1.1.1/32\",\"dscp\":1,\"protocol\":\"IP_TCP\"}},\"transport\":{\"config\":{\"source-port\":101,\"destination-port\":201}},\"actions\":{\"config\":{\"forwarding-action\":\"ACCEPT\"}}},{\"sequence-id\":2,\"config\":{\"sequence-id\":2,\"description\":\"Description for Rule Seq 2\"},\"ipv4\":{\"config\":{\"source-address\":\"12.1.1.2/32\",\"destination-address\":\"22.1.1.2/32\",\"dscp\":2,\"protocol\":\"IP_TCP\"}},\"transport\":{\"config\":{\"source-port\":102,\"destination-port\":202}},\"actions\":{\"config\":{\"forwarding-action\":\"ACCEPT\"}}},{\"sequence-id\":3,\"config\":{\"sequence-id\":3,\"description\":\"Description for Rule Seq 3\"},\"ipv4\":{\"config\":{\"source-address\":\"12.1.1.3/32\",\"destination-address\":\"22.1.1.3/32\",\"dscp\":3,\"protocol\":\"IP_TCP\"}},\"transport\":{\"config\":{\"source-port\":103,\"destination-port\":203}},\"actions\":{\"config\":{\"forwarding-action\":\"ACCEPT\"}}},{\"sequence-id\":4,\"config\":{\"sequence-id\":4,\"description\":\"Description for Rule Seq 4\"},\"ipv4\":{\"config\":{\"source-address\":\"12.1.1.4/32\",\"destination-address\":\"22.1.1.4/32\",\"dscp\":4,\"protocol\":\"IP_TCP\"}},\"transport\":{\"config\":{\"source-port\":104,\"destination-port\":204}},\"actions\":{\"config\":{\"forwarding-action\":\"ACCEPT\"}}},{\"sequence-id\":5,\"config\":{\"sequence-id\":5,\"description\":\"Description for Rule Seq 5\"},\"ipv4\":{\"config\":{\"source-address\":\"12.1.1.5/32\",\"destination-address\":\"22.1.1.5/32\",\"dscp\":5,\"protocol\":\"IP_TCP\"}},\"transport\":{\"config\":{\"source-port\":105,\"destination-port\":205}},\"actions\":{\"config\":{\"forwarding-action\":\"ACCEPT\"}}}]}}]},\"interfaces\":{\"interface\":[{\"id\":\"Ethernet0\",\"config\":{\"id\":\"Ethernet0\"},\"interface-ref\":{\"config\":{\"interface\":\"Ethernet0\"}},\"ingress-acl-sets\":{\"ingress-acl-set\":[{\"set-name\":\"MyACL1\",\"type\":\"ACL_IPV4\",\"config\":{\"set-name\":\"MyACL1\",\"type\":\"ACL_IPV4\"}}]}},{\"id\":\"Ethernet4\",\"config\":{\"id\":\"Ethernet4\"},\"interface-ref\":{\"config\":{\"interface\":\"Ethernet4\"}},\"ingress-acl-sets\":{\"ingress-acl-set\":[{\"set-name\":\"MyACL2\",\"type\":\"ACL_IPV4\",\"config\":{\"set-name\":\"MyACL2\",\"type\":\"ACL_IPV4\"}}]}}]}}" - -var bulkAclCreateJsonResponse string = "{\"openconfig-acl:acl\":{\"acl-sets\":{\"acl-set\":[{\"acl-entries\":{\"acl-entry\":[{\"actions\":{\"config\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"},\"state\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"}},\"config\":{\"sequence-id\":1},\"ipv4\":{\"config\":{\"destination-address\":\"21.1.1.1/32\",\"dscp\":1,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"11.1.1.1/32\"},\"state\":{\"destination-address\":\"21.1.1.1/32\",\"dscp\":1,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"11.1.1.1/32\"}},\"sequence-id\":1,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":1},\"transport\":{\"config\":{\"destination-port\":201,\"source-port\":101},\"state\":{\"destination-port\":201,\"source-port\":101}}},{\"actions\":{\"config\":{\"forwarding-action\":\"openconfig-acl:DROP\"},\"state\":{\"forwarding-action\":\"openconfig-acl:DROP\"}},\"config\":{\"sequence-id\":2},\"ipv4\":{\"config\":{\"destination-address\":\"21.1.1.2/32\",\"dscp\":2,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"11.1.1.2/32\"},\"state\":{\"destination-address\":\"21.1.1.2/32\",\"dscp\":2,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"11.1.1.2/32\"}},\"sequence-id\":2,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":2},\"transport\":{\"config\":{\"destination-port\":202,\"source-port\":102},\"state\":{\"destination-port\":202,\"source-port\":102}}},{\"actions\":{\"config\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"},\"state\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"}},\"config\":{\"sequence-id\":3},\"ipv4\":{\"config\":{\"destination-address\":\"21.1.1.3/32\",\"dscp\":3,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"11.1.1.3/32\"},\"state\":{\"destination-address\":\"21.1.1.3/32\",\"dscp\":3,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"11.1.1.3/32\"}},\"sequence-id\":3,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":3},\"transport\":{\"config\":{\"destination-port\":203,\"source-port\":103},\"state\":{\"destination-port\":203,\"source-port\":103}}},{\"actions\":{\"config\":{\"forwarding-action\":\"openconfig-acl:DROP\"},\"state\":{\"forwarding-action\":\"openconfig-acl:DROP\"}},\"config\":{\"sequence-id\":4},\"ipv4\":{\"config\":{\"destination-address\":\"21.1.1.4/32\",\"dscp\":4,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"11.1.1.4/32\"},\"state\":{\"destination-address\":\"21.1.1.4/32\",\"dscp\":4,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"11.1.1.4/32\"}},\"sequence-id\":4,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":4},\"transport\":{\"config\":{\"destination-port\":204,\"source-port\":104},\"state\":{\"destination-port\":204,\"source-port\":104}}},{\"actions\":{\"config\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"},\"state\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"}},\"config\":{\"sequence-id\":5},\"ipv4\":{\"config\":{\"destination-address\":\"21.1.1.5/32\",\"dscp\":5,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"11.1.1.5/32\"},\"state\":{\"destination-address\":\"21.1.1.5/32\",\"dscp\":5,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"11.1.1.5/32\"}},\"sequence-id\":5,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":5},\"transport\":{\"config\":{\"destination-port\":205,\"source-port\":105},\"state\":{\"destination-port\":205,\"source-port\":105}}}]},\"config\":{\"description\":\"Description for MyACL1\",\"name\":\"MyACL1\",\"type\":\"openconfig-acl:ACL_IPV4\"},\"name\":\"MyACL1\",\"state\":{\"description\":\"Description for MyACL1\",\"name\":\"MyACL1\",\"type\":\"openconfig-acl:ACL_IPV4\"},\"type\":\"openconfig-acl:ACL_IPV4\"},{\"acl-entries\":{\"acl-entry\":[{\"actions\":{\"config\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"},\"state\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"}},\"config\":{\"sequence-id\":1},\"ipv4\":{\"config\":{\"destination-address\":\"22.1.1.1/32\",\"dscp\":1,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"12.1.1.1/32\"},\"state\":{\"destination-address\":\"22.1.1.1/32\",\"dscp\":1,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"12.1.1.1/32\"}},\"sequence-id\":1,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":1},\"transport\":{\"config\":{\"destination-port\":201,\"source-port\":101},\"state\":{\"destination-port\":201,\"source-port\":101}}},{\"actions\":{\"config\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"},\"state\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"}},\"config\":{\"sequence-id\":2},\"ipv4\":{\"config\":{\"destination-address\":\"22.1.1.2/32\",\"dscp\":2,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"12.1.1.2/32\"},\"state\":{\"destination-address\":\"22.1.1.2/32\",\"dscp\":2,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"12.1.1.2/32\"}},\"sequence-id\":2,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":2},\"transport\":{\"config\":{\"destination-port\":202,\"source-port\":102},\"state\":{\"destination-port\":202,\"source-port\":102}}},{\"actions\":{\"config\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"},\"state\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"}},\"config\":{\"sequence-id\":3},\"ipv4\":{\"config\":{\"destination-address\":\"22.1.1.3/32\",\"dscp\":3,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"12.1.1.3/32\"},\"state\":{\"destination-address\":\"22.1.1.3/32\",\"dscp\":3,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"12.1.1.3/32\"}},\"sequence-id\":3,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":3},\"transport\":{\"config\":{\"destination-port\":203,\"source-port\":103},\"state\":{\"destination-port\":203,\"source-port\":103}}},{\"actions\":{\"config\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"},\"state\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"}},\"config\":{\"sequence-id\":4},\"ipv4\":{\"config\":{\"destination-address\":\"22.1.1.4/32\",\"dscp\":4,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"12.1.1.4/32\"},\"state\":{\"destination-address\":\"22.1.1.4/32\",\"dscp\":4,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"12.1.1.4/32\"}},\"sequence-id\":4,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":4},\"transport\":{\"config\":{\"destination-port\":204,\"source-port\":104},\"state\":{\"destination-port\":204,\"source-port\":104}}},{\"actions\":{\"config\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"},\"state\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"}},\"config\":{\"sequence-id\":5},\"ipv4\":{\"config\":{\"destination-address\":\"22.1.1.5/32\",\"dscp\":5,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"12.1.1.5/32\"},\"state\":{\"destination-address\":\"22.1.1.5/32\",\"dscp\":5,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"12.1.1.5/32\"}},\"sequence-id\":5,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":5},\"transport\":{\"config\":{\"destination-port\":205,\"source-port\":105},\"state\":{\"destination-port\":205,\"source-port\":105}}}]},\"config\":{\"description\":\"Description for MyACL2\",\"name\":\"MyACL2\",\"type\":\"openconfig-acl:ACL_IPV4\"},\"name\":\"MyACL2\",\"state\":{\"description\":\"Description for MyACL2\",\"name\":\"MyACL2\",\"type\":\"openconfig-acl:ACL_IPV4\"},\"type\":\"openconfig-acl:ACL_IPV4\"}]},\"interfaces\":{\"interface\":[{\"config\":{\"id\":\"Ethernet0\"},\"id\":\"Ethernet0\",\"ingress-acl-sets\":{\"ingress-acl-set\":[{\"acl-entries\":{\"acl-entry\":[{\"sequence-id\":1,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":1}},{\"sequence-id\":2,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":2}},{\"sequence-id\":3,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":3}},{\"sequence-id\":4,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":4}},{\"sequence-id\":5,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":5}}]},\"config\":{\"set-name\":\"MyACL1\",\"type\":\"openconfig-acl:ACL_IPV4\"},\"set-name\":\"MyACL1\",\"state\":{\"set-name\":\"MyACL1\",\"type\":\"openconfig-acl:ACL_IPV4\"},\"type\":\"openconfig-acl:ACL_IPV4\"}]},\"state\":{\"id\":\"Ethernet0\"}},{\"config\":{\"id\":\"Ethernet4\"},\"id\":\"Ethernet4\",\"ingress-acl-sets\":{\"ingress-acl-set\":[{\"acl-entries\":{\"acl-entry\":[{\"sequence-id\":1,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":1}},{\"sequence-id\":2,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":2}},{\"sequence-id\":3,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":3}},{\"sequence-id\":4,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":4}},{\"sequence-id\":5,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":5}}]},\"config\":{\"set-name\":\"MyACL2\",\"type\":\"openconfig-acl:ACL_IPV4\"},\"set-name\":\"MyACL2\",\"state\":{\"set-name\":\"MyACL2\",\"type\":\"openconfig-acl:ACL_IPV4\"},\"type\":\"openconfig-acl:ACL_IPV4\"}]},\"state\":{\"id\":\"Ethernet4\"}}]}}}" - -var oneAclCreateWithRulesJsonRequest string = "{ \"name\": \"MyACL3\", \"type\": \"ACL_IPV4\", \"config\": { \"name\": \"MyACL3\", \"type\": \"ACL_IPV4\", \"description\": \"Description for MyACL3\" }, \"acl-entries\": { \"acl-entry\": [ { \"sequence-id\": 1, \"config\": { \"sequence-id\": 1, \"description\": \"Description for MyACL3 Rule Seq 1\" }, \"ipv4\": { \"config\": { \"source-address\": \"11.1.1.1/32\", \"destination-address\": \"21.1.1.1/32\", \"dscp\": 1, \"protocol\": \"IP_TCP\" } }, \"transport\": { \"config\": { \"source-port\": 101, \"destination-port\": 201 } }, \"actions\": { \"config\": { \"forwarding-action\": \"ACCEPT\" } } }, { \"sequence-id\": 2, \"config\": { \"sequence-id\": 2, \"description\": \"Description for MyACL3 Rule Seq 2\" }, \"ipv4\": { \"config\": { \"source-address\": \"11.1.1.2/32\", \"destination-address\": \"21.1.1.2/32\", \"dscp\": 2, \"protocol\": \"IP_UDP\" } }, \"transport\": { \"config\": { \"source-port\": 102, \"destination-port\": 202 } }, \"actions\": { \"config\": { \"forwarding-action\": \"DROP\" } } }, { \"sequence-id\": 3, \"config\": { \"sequence-id\": 3, \"description\": \"Description for MyACL3 Rule Seq 3\" }, \"ipv4\": { \"config\": { \"source-address\": \"11.1.1.3/32\", \"destination-address\": \"21.1.1.3/32\", \"dscp\": 3, \"protocol\": \"IP_TCP\" } }, \"transport\": { \"config\": { \"source-port\": 103, \"destination-port\": 203 } }, \"actions\": { \"config\": { \"forwarding-action\": \"ACCEPT\" } } }, { \"sequence-id\": 4, \"config\": { \"sequence-id\": 4, \"description\": \"Description for MyACL3 Rule Seq 4\" }, \"ipv4\": { \"config\": { \"source-address\": \"11.1.1.4/32\", \"destination-address\": \"21.1.1.4/32\", \"dscp\": 4, \"protocol\": \"IP_TCP\" } }, \"transport\": { \"config\": { \"source-port\": 104, \"destination-port\": 204 } }, \"actions\": { \"config\": { \"forwarding-action\": \"DROP\" } } }, { \"sequence-id\": 5, \"config\": { \"sequence-id\": 5, \"description\": \"Description for MyACL3 Rule Seq 5\" }, \"ipv4\": { \"config\": { \"source-address\": \"11.1.1.5/32\", \"destination-address\": \"21.1.1.5/32\", \"dscp\": 5, \"protocol\": \"IP_TCP\" } }, \"transport\": { \"config\": { \"source-port\": 105, \"destination-port\": 205 } }, \"actions\": { \"config\": { \"forwarding-action\": \"ACCEPT\" } } } ] }}" - -var oneAclCreateWithRulesJsonResponse string = "{\"openconfig-acl:acl-set\":[{\"acl-entries\":{\"acl-entry\":[{\"actions\":{\"config\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"},\"state\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"}},\"config\":{\"sequence-id\":1},\"ipv4\":{\"config\":{\"destination-address\":\"21.1.1.1/32\",\"dscp\":1,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"11.1.1.1/32\"},\"state\":{\"destination-address\":\"21.1.1.1/32\",\"dscp\":1,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"11.1.1.1/32\"}},\"sequence-id\":1,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":1},\"transport\":{\"config\":{\"destination-port\":201,\"source-port\":101},\"state\":{\"destination-port\":201,\"source-port\":101}}},{\"actions\":{\"config\":{\"forwarding-action\":\"openconfig-acl:DROP\"},\"state\":{\"forwarding-action\":\"openconfig-acl:DROP\"}},\"config\":{\"sequence-id\":2},\"ipv4\":{\"config\":{\"destination-address\":\"21.1.1.2/32\",\"dscp\":2,\"protocol\":\"openconfig-packet-match-types:IP_UDP\",\"source-address\":\"11.1.1.2/32\"},\"state\":{\"destination-address\":\"21.1.1.2/32\",\"dscp\":2,\"protocol\":\"openconfig-packet-match-types:IP_UDP\",\"source-address\":\"11.1.1.2/32\"}},\"sequence-id\":2,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":2},\"transport\":{\"config\":{\"destination-port\":202,\"source-port\":102},\"state\":{\"destination-port\":202,\"source-port\":102}}},{\"actions\":{\"config\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"},\"state\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"}},\"config\":{\"sequence-id\":3},\"ipv4\":{\"config\":{\"destination-address\":\"21.1.1.3/32\",\"dscp\":3,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"11.1.1.3/32\"},\"state\":{\"destination-address\":\"21.1.1.3/32\",\"dscp\":3,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"11.1.1.3/32\"}},\"sequence-id\":3,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":3},\"transport\":{\"config\":{\"destination-port\":203,\"source-port\":103},\"state\":{\"destination-port\":203,\"source-port\":103}}},{\"actions\":{\"config\":{\"forwarding-action\":\"openconfig-acl:DROP\"},\"state\":{\"forwarding-action\":\"openconfig-acl:DROP\"}},\"config\":{\"sequence-id\":4},\"ipv4\":{\"config\":{\"destination-address\":\"21.1.1.4/32\",\"dscp\":4,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"11.1.1.4/32\"},\"state\":{\"destination-address\":\"21.1.1.4/32\",\"dscp\":4,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"11.1.1.4/32\"}},\"sequence-id\":4,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":4},\"transport\":{\"config\":{\"destination-port\":204,\"source-port\":104},\"state\":{\"destination-port\":204,\"source-port\":104}}},{\"actions\":{\"config\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"},\"state\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"}},\"config\":{\"sequence-id\":5},\"ipv4\":{\"config\":{\"destination-address\":\"21.1.1.5/32\",\"dscp\":5,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"11.1.1.5/32\"},\"state\":{\"destination-address\":\"21.1.1.5/32\",\"dscp\":5,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"11.1.1.5/32\"}},\"sequence-id\":5,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":5},\"transport\":{\"config\":{\"destination-port\":205,\"source-port\":105},\"state\":{\"destination-port\":205,\"source-port\":105}}}]},\"config\":{\"description\":\"Description for MyACL3\",\"name\":\"MyACL3\",\"type\":\"openconfig-acl:ACL_IPV4\"},\"name\":\"MyACL3\",\"state\":{\"description\":\"Description for MyACL3\",\"name\":\"MyACL3\",\"type\":\"openconfig-acl:ACL_IPV4\"},\"type\":\"openconfig-acl:ACL_IPV4\"}]}" - -var oneAclCreateJsonRequest string = "{\"config\": {\"name\": \"MyACL5\",\"type\": \"ACL_IPV4\",\"description\": \"Description for MyACL5\"}}" -var oneAclCreateJsonResponse string = "{\"openconfig-acl:acl-set\":[{\"config\":{\"description\":\"Description for MyACL5\",\"name\":\"MyACL5\",\"type\":\"openconfig-acl:ACL_IPV4\"},\"name\":\"MyACL5\",\"state\":{\"description\":\"Description for MyACL5\",\"name\":\"MyACL5\",\"type\":\"openconfig-acl:ACL_IPV4\"},\"type\":\"openconfig-acl:ACL_IPV4\"}]}" - -var requestOneRulePostJson string = "{\"sequence-id\": 8,\"config\": {\"sequence-id\": 8,\"description\": \"Description for MyACL5 Rule Seq 8\"},\"ipv4\": {\"config\": {\"source-address\": \"4.4.4.4/24\",\"destination-address\": \"5.5.5.5/24\",\"protocol\": \"IP_TCP\"}},\"transport\": {\"config\": {\"source-port\": 101,\"destination-port\": 100,\"tcp-flags\": [\"TCP_FIN\",\"TCP_ACK\"]}},\"actions\": {\"config\": {\"forwarding-action\": \"ACCEPT\"}}}" - -var requestOneRulePatchJson string = "{\"sequence-id\": 8,\"config\": {\"sequence-id\": 8,\"description\": \"Description for MyACL5 Rule Seq 8\"},\"ipv4\": {\"config\": {\"source-address\": \"4.8.4.8/24\",\"destination-address\": \"15.5.15.5/24\",\"protocol\": \"IP_L2TP\"}},\"transport\": {\"config\": {\"source-port\": 101,\"destination-port\": 100,\"tcp-flags\": [\"TCP_FIN\",\"TCP_ACK\",\"TCP_RST\",\"TCP_ECE\"]}},\"actions\": {\"config\": {\"forwarding-action\": \"ACCEPT\"}}}" - -var responseOneRuleJson string = "{\"openconfig-acl:acl-entry\":[{\"actions\":{\"config\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"},\"state\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"}},\"config\":{\"sequence-id\":8},\"ipv4\":{\"config\":{\"destination-address\":\"5.5.5.5/24\",\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"4.4.4.4/24\"},\"state\":{\"destination-address\":\"5.5.5.5/24\",\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"4.4.4.4/24\"}},\"sequence-id\":8,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":8},\"transport\":{\"config\":{\"destination-port\":100,\"source-port\":101,\"tcp-flags\":[\"openconfig-packet-match-types:TCP_FIN\",\"openconfig-packet-match-types:TCP_ACK\"]},\"state\":{\"destination-port\":100,\"source-port\":101,\"tcp-flags\":[\"openconfig-packet-match-types:TCP_FIN\",\"openconfig-packet-match-types:TCP_ACK\"]}}}]}" - -var responseOneRulePatchJson string = "{\"openconfig-acl:acl-entry\":[{\"actions\":{\"config\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"},\"state\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"}},\"config\":{\"sequence-id\":8},\"ipv4\":{\"config\":{\"destination-address\":\"15.5.15.5/24\",\"protocol\":\"openconfig-packet-match-types:IP_L2TP\",\"source-address\":\"4.8.4.8/24\"},\"state\":{\"destination-address\":\"15.5.15.5/24\",\"protocol\":\"openconfig-packet-match-types:IP_L2TP\",\"source-address\":\"4.8.4.8/24\"}},\"sequence-id\":8,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":8},\"transport\":{\"config\":{\"destination-port\":100,\"source-port\":101,\"tcp-flags\":[\"openconfig-packet-match-types:TCP_FIN\",\"openconfig-packet-match-types:TCP_RST\",\"openconfig-packet-match-types:TCP_ACK\",\"openconfig-packet-match-types:TCP_ECE\"]},\"state\":{\"destination-port\":100,\"source-port\":101,\"tcp-flags\":[\"openconfig-packet-match-types:TCP_FIN\",\"openconfig-packet-match-types:TCP_RST\",\"openconfig-packet-match-types:TCP_ACK\",\"openconfig-packet-match-types:TCP_ECE\"]}}}]}" - -var aclDescrUpdateJson string = "{\"openconfig-acl:description\":\"Verifying ACL Description Update\"}" - -var ingressAclSetCreateJsonRequest string = "{ \"openconfig-acl:config\": { \"set-name\": \"MyACL5\", \"type\": \"ACL_IPV4\" }}" -var ingressAclSetCreateJsonResponse string = "{\"openconfig-acl:ingress-acl-set\":[{\"acl-entries\":{\"acl-entry\":[{\"sequence-id\":8,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":8}}]},\"config\":{\"set-name\":\"MyACL5\",\"type\":\"openconfig-acl:ACL_IPV4\"},\"set-name\":\"MyACL5\",\"state\":{\"set-name\":\"MyACL5\",\"type\":\"openconfig-acl:ACL_IPV4\"},\"type\":\"openconfig-acl:ACL_IPV4\"}]}" - -var egressAclSetCreateJsonResponse string = "{\"openconfig-acl:egress-acl-set\":[{\"acl-entries\":{\"acl-entry\":[{\"sequence-id\":8,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":8}}]},\"config\":{\"set-name\":\"MyACL5\",\"type\":\"openconfig-acl:ACL_IPV4\"},\"set-name\":\"MyACL5\",\"state\":{\"set-name\":\"MyACL5\",\"type\":\"openconfig-acl:ACL_IPV4\"},\"type\":\"openconfig-acl:ACL_IPV4\"}]}" - -var replaceMultiRulesWithOneRuleJsonRequest string = "{\"name\": \"MyACL3\",\"type\": \"ACL_IPV4\",\"config\": {\"name\": \"MyACL3\",\"type\": \"ACL_IPV4\",\"description\": \"Description for MyACL3\"},\"acl-entries\": {\"acl-entry\": [{\"sequence-id\": 8,\"config\": {\"sequence-id\": 8,\"description\": \"Description for MyACL3 Rule Seq 8\"},\"ipv4\": {\"config\": {\"source-address\": \"81.1.1.1/32\",\"destination-address\": \"91.1.1.1/32\",\"protocol\": \"IP_TCP\"}},\"transport\": {\"config\": {\"source-port\": \"801..811\",\"destination-port\": \"901..921\"}},\"actions\": {\"config\": {\"forwarding-action\": \"REJECT\"}}}]}}" - -var replaceMultiRulesWithOneRuleJsonResponse string = "{\"openconfig-acl:acl-set\":[{\"acl-entries\":{\"acl-entry\":[{\"actions\":{\"config\":{\"forwarding-action\":\"openconfig-acl:DROP\"},\"state\":{\"forwarding-action\":\"openconfig-acl:DROP\"}},\"config\":{\"sequence-id\":8},\"ipv4\":{\"config\":{\"destination-address\":\"91.1.1.1/32\",\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"81.1.1.1/32\"},\"state\":{\"destination-address\":\"91.1.1.1/32\",\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"81.1.1.1/32\"}},\"sequence-id\":8,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":8},\"transport\":{\"config\":{\"destination-port\":\"901-921\",\"source-port\":\"801-811\"},\"state\":{\"destination-port\":\"901-921\",\"source-port\":\"801-811\"}}}]},\"config\":{\"description\":\"Description for MyACL3\",\"name\":\"MyACL3\",\"type\":\"openconfig-acl:ACL_IPV4\"},\"name\":\"MyACL3\",\"state\":{\"description\":\"Description for MyACL3\",\"name\":\"MyACL3\",\"type\":\"openconfig-acl:ACL_IPV4\"},\"type\":\"openconfig-acl:ACL_IPV4\"}]}" - -var getFromAclSetsTreeLevelResponse string = "{\"openconfig-acl:acl-sets\":{\"acl-set\":[{\"acl-entries\":{\"acl-entry\":[{\"actions\":{\"config\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"},\"state\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"}},\"config\":{\"sequence-id\":8},\"ipv4\":{\"config\":{\"destination-address\":\"5.5.5.5/24\",\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"4.4.4.4/24\"},\"state\":{\"destination-address\":\"5.5.5.5/24\",\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"4.4.4.4/24\"}},\"sequence-id\":8,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":8},\"transport\":{\"config\":{\"destination-port\":100,\"source-port\":101,\"tcp-flags\":[\"openconfig-packet-match-types:TCP_FIN\",\"openconfig-packet-match-types:TCP_ACK\"]},\"state\":{\"destination-port\":100,\"source-port\":101,\"tcp-flags\":[\"openconfig-packet-match-types:TCP_FIN\",\"openconfig-packet-match-types:TCP_ACK\"]}}}]},\"config\":{\"description\":\"Description for MyACL5\",\"name\":\"MyACL5\",\"type\":\"openconfig-acl:ACL_IPV4\"},\"name\":\"MyACL5\",\"state\":{\"description\":\"Description for MyACL5\",\"name\":\"MyACL5\",\"type\":\"openconfig-acl:ACL_IPV4\"},\"type\":\"openconfig-acl:ACL_IPV4\"}]}}" - -var getAllPortsFromInterfacesTreeLevelResponse string = "{\"openconfig-acl:interfaces\":{\"interface\":[{\"config\":{\"id\":\"Ethernet4\"},\"egress-acl-sets\":{\"egress-acl-set\":[{\"acl-entries\":{\"acl-entry\":[{\"sequence-id\":8,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":8}}]},\"config\":{\"set-name\":\"MyACL5\",\"type\":\"openconfig-acl:ACL_IPV4\"},\"set-name\":\"MyACL5\",\"state\":{\"set-name\":\"MyACL5\",\"type\":\"openconfig-acl:ACL_IPV4\"},\"type\":\"openconfig-acl:ACL_IPV4\"}]},\"id\":\"Ethernet4\",\"state\":{\"id\":\"Ethernet4\"}}]}}" - -var getPortBindingFromInterfaceTreeLevelResponse string = "{\"openconfig-acl:interface\":[{\"config\":{\"id\":\"Ethernet4\"},\"egress-acl-sets\":{\"egress-acl-set\":[{\"acl-entries\":{\"acl-entry\":[{\"sequence-id\":8,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":8}}]},\"config\":{\"set-name\":\"MyACL5\",\"type\":\"openconfig-acl:ACL_IPV4\"},\"set-name\":\"MyACL5\",\"state\":{\"set-name\":\"MyACL5\",\"type\":\"openconfig-acl:ACL_IPV4\"},\"type\":\"openconfig-acl:ACL_IPV4\"}]},\"id\":\"Ethernet4\",\"state\":{\"id\":\"Ethernet4\"}}]}" - -var getBindingAclEntryResponse string = "{\"openconfig-acl:acl-entry\":[{\"sequence-id\":8,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":8}}]}" - -var getMultiportBindingOnSingleAclResponse string = "{\"openconfig-acl:interfaces\":{\"interface\":[{\"config\":{\"id\":\"Ethernet0\"},\"egress-acl-sets\":{\"egress-acl-set\":[{\"acl-entries\":{\"acl-entry\":[{\"sequence-id\":8,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":8}}]},\"config\":{\"set-name\":\"MyACL5\",\"type\":\"openconfig-acl:ACL_IPV4\"},\"set-name\":\"MyACL5\",\"state\":{\"set-name\":\"MyACL5\",\"type\":\"openconfig-acl:ACL_IPV4\"},\"type\":\"openconfig-acl:ACL_IPV4\"}]},\"id\":\"Ethernet0\",\"state\":{\"id\":\"Ethernet0\"}},{\"config\":{\"id\":\"Ethernet4\"},\"egress-acl-sets\":{\"egress-acl-set\":[{\"acl-entries\":{\"acl-entry\":[{\"sequence-id\":8,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":8}}]},\"config\":{\"set-name\":\"MyACL5\",\"type\":\"openconfig-acl:ACL_IPV4\"},\"set-name\":\"MyACL5\",\"state\":{\"set-name\":\"MyACL5\",\"type\":\"openconfig-acl:ACL_IPV4\"},\"type\":\"openconfig-acl:ACL_IPV4\"}]},\"id\":\"Ethernet4\",\"state\":{\"id\":\"Ethernet4\"}}]}}" - -var oneIPv6AclCreateJsonRequest string = "{\"config\": {\"name\": \"MyACL6\",\"type\": \"ACL_IPV6\",\"description\": \"Description for IPv6 ACL MyACL6\"}}" -var oneIPv6AclCreateJsonResponse string = "{\"openconfig-acl:acl-set\":[{\"config\":{\"description\":\"Description for IPv6 ACL MyACL6\",\"name\":\"MyACL6\",\"type\":\"openconfig-acl:ACL_IPV6\"},\"name\":\"MyACL6\",\"state\":{\"description\":\"Description for IPv6 ACL MyACL6\",\"name\":\"MyACL6\",\"type\":\"openconfig-acl:ACL_IPV6\"},\"type\":\"openconfig-acl:ACL_IPV6\"}]}" - -var oneIPv6RuleCreateJsonRequest string = "{\"sequence-id\": 6,\"config\": {\"sequence-id\": 6,\"description\": \"Description for MyACL6 Rule Seq 6\"},\"ipv6\": {\"config\": {\"source-address\": \"11::67/64\",\"destination-address\": \"22::87/64\",\"protocol\": \"IP_TCP\",\"dscp\": 11}},\"transport\": {\"config\": {\"source-port\": 101,\"destination-port\": 100,\"tcp-flags\": [\"TCP_FIN\",\"TCP_ACK\"]}},\"actions\": {\"config\": {\"forwarding-action\": \"ACCEPT\"}}}" -var oneIPv6RuleCreateJsonResponse string = "{\"openconfig-acl:acl-entry\":[{\"actions\":{\"config\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"},\"state\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"}},\"config\":{\"sequence-id\":6},\"ipv6\":{\"config\":{\"destination-address\":\"22::87/64\",\"dscp\":11,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"11::67/64\"},\"state\":{\"destination-address\":\"22::87/64\",\"dscp\":11,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"11::67/64\"}},\"sequence-id\":6,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":6},\"transport\":{\"config\":{\"destination-port\":100,\"source-port\":101,\"tcp-flags\":[\"openconfig-packet-match-types:TCP_FIN\",\"openconfig-packet-match-types:TCP_ACK\"]},\"state\":{\"destination-port\":100,\"source-port\":101,\"tcp-flags\":[\"openconfig-packet-match-types:TCP_FIN\",\"openconfig-packet-match-types:TCP_ACK\"]}}}]}" - -var ingressIPv6AclSetCreateJsonRequest string = "{ \"openconfig-acl:config\": { \"set-name\": \"MyACL6\", \"type\": \"ACL_IPV6\" }}" -var ingressIPv6AclSetCreateJsonResponse string = "{\"openconfig-acl:ingress-acl-set\":[{\"acl-entries\":{\"acl-entry\":[{\"sequence-id\":6,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":6}}]},\"config\":{\"set-name\":\"MyACL6\",\"type\":\"openconfig-acl:ACL_IPV6\"},\"set-name\":\"MyACL6\",\"state\":{\"set-name\":\"MyACL6\",\"type\":\"openconfig-acl:ACL_IPV6\"},\"type\":\"openconfig-acl:ACL_IPV6\"}]}" - -var getIPv6AclsFromAclSetListLevelResponse string = "{\"openconfig-acl:acl-set\":[{\"acl-entries\":{\"acl-entry\":[{\"actions\":{\"config\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"},\"state\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"}},\"config\":{\"sequence-id\":6},\"ipv6\":{\"config\":{\"destination-address\":\"22::87/64\",\"dscp\":11,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"11::67/64\"},\"state\":{\"destination-address\":\"22::87/64\",\"dscp\":11,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"11::67/64\"}},\"sequence-id\":6,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":6},\"transport\":{\"config\":{\"destination-port\":100,\"source-port\":101,\"tcp-flags\":[\"openconfig-packet-match-types:TCP_FIN\",\"openconfig-packet-match-types:TCP_ACK\"]},\"state\":{\"destination-port\":100,\"source-port\":101,\"tcp-flags\":[\"openconfig-packet-match-types:TCP_FIN\",\"openconfig-packet-match-types:TCP_ACK\"]}}}]},\"config\":{\"description\":\"Description for IPv6 ACL MyACL6\",\"name\":\"MyACL6\",\"type\":\"openconfig-acl:ACL_IPV6\"},\"name\":\"MyACL6\",\"state\":{\"description\":\"Description for IPv6 ACL MyACL6\",\"name\":\"MyACL6\",\"type\":\"openconfig-acl:ACL_IPV6\"},\"type\":\"openconfig-acl:ACL_IPV6\"}]}" - -var getIPv6AllPortsBindingsResponse string = "{\"openconfig-acl:interfaces\":{\"interface\":[{\"config\":{\"id\":\"Ethernet4\"},\"id\":\"Ethernet4\",\"ingress-acl-sets\":{\"ingress-acl-set\":[{\"acl-entries\":{\"acl-entry\":[{\"sequence-id\":6,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":6}}]},\"config\":{\"set-name\":\"MyACL6\",\"type\":\"openconfig-acl:ACL_IPV6\"},\"set-name\":\"MyACL6\",\"state\":{\"set-name\":\"MyACL6\",\"type\":\"openconfig-acl:ACL_IPV6\"},\"type\":\"openconfig-acl:ACL_IPV6\"}]},\"state\":{\"id\":\"Ethernet4\"}}]}}" - -var oneL2AclCreateJsonRequest string = "{\"config\": {\"name\": \"MyACL2\",\"type\": \"ACL_L2\",\"description\": \"Description for L2 ACL MyACL2\"}}" -var oneL2AclCreateJsonResponse string = "{\"openconfig-acl:acl-set\":[{\"config\":{\"description\":\"Description for L2 ACL MyACL2\",\"name\":\"MyACL2\",\"type\":\"openconfig-acl:ACL_L2\"},\"name\":\"MyACL2\",\"state\":{\"description\":\"Description for L2 ACL MyACL2\",\"name\":\"MyACL2\",\"type\":\"openconfig-acl:ACL_L2\"},\"type\":\"openconfig-acl:ACL_L2\"}]}" - -var oneL2RuleCreateJsonRequest string = "{\"sequence-id\": 2,\"config\": {\"sequence-id\": 2,\"description\": \"Description for MyACL2 Rule Seq 2\"},\"l2\": {\"config\": {\"ethertype\": \"ETHERTYPE_VLAN\"}},\"transport\": {\"config\": {\"source-port\": 101,\"destination-port\": 100,\"tcp-flags\": [\"TCP_FIN\",\"TCP_ACK\"]}},\"actions\": {\"config\": {\"forwarding-action\": \"ACCEPT\"}}}" - -var oneL2RuleCreateJsonResponse string = "{\"openconfig-acl:acl-entry\":[{\"actions\":{\"config\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"},\"state\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"}},\"config\":{\"sequence-id\":2},\"l2\":{\"config\":{\"ethertype\":\"openconfig-packet-match-types:ETHERTYPE_VLAN\"},\"state\":{\"ethertype\":\"openconfig-packet-match-types:ETHERTYPE_VLAN\"}},\"sequence-id\":2,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":2},\"transport\":{\"config\":{\"destination-port\":100,\"source-port\":101,\"tcp-flags\":[\"openconfig-packet-match-types:TCP_FIN\",\"openconfig-packet-match-types:TCP_ACK\"]},\"state\":{\"destination-port\":100,\"source-port\":101,\"tcp-flags\":[\"openconfig-packet-match-types:TCP_FIN\",\"openconfig-packet-match-types:TCP_ACK\"]}}}]}" - -var ingressL2AclSetCreateJsonRequest string = "{ \"openconfig-acl:config\": { \"set-name\": \"MyACL2\", \"type\": \"ACL_L2\" }}" -var ingressL2AclSetCreateJsonResponse string = "{\"openconfig-acl:ingress-acl-set\":[{\"acl-entries\":{\"acl-entry\":[{\"sequence-id\":2,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":2}}]},\"config\":{\"set-name\":\"MyACL2\",\"type\":\"openconfig-acl:ACL_L2\"},\"set-name\":\"MyACL2\",\"state\":{\"set-name\":\"MyACL2\",\"type\":\"openconfig-acl:ACL_L2\"},\"type\":\"openconfig-acl:ACL_L2\"}]}" - -var getL2AclsFromAclSetListLevelResponse string = "{\"openconfig-acl:acl-set\":[{\"acl-entries\":{\"acl-entry\":[{\"actions\":{\"config\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"},\"state\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"}},\"config\":{\"sequence-id\":2},\"l2\":{\"config\":{\"ethertype\":\"openconfig-packet-match-types:ETHERTYPE_VLAN\"},\"state\":{\"ethertype\":\"openconfig-packet-match-types:ETHERTYPE_VLAN\"}},\"sequence-id\":2,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":2},\"transport\":{\"config\":{\"destination-port\":100,\"source-port\":101,\"tcp-flags\":[\"openconfig-packet-match-types:TCP_FIN\",\"openconfig-packet-match-types:TCP_ACK\"]},\"state\":{\"destination-port\":100,\"source-port\":101,\"tcp-flags\":[\"openconfig-packet-match-types:TCP_FIN\",\"openconfig-packet-match-types:TCP_ACK\"]}}}]},\"config\":{\"description\":\"Description for L2 ACL MyACL2\",\"name\":\"MyACL2\",\"type\":\"openconfig-acl:ACL_L2\"},\"name\":\"MyACL2\",\"state\":{\"description\":\"Description for L2 ACL MyACL2\",\"name\":\"MyACL2\",\"type\":\"openconfig-acl:ACL_L2\"},\"type\":\"openconfig-acl:ACL_L2\"}]}" - -var getL2AllPortsBindingsResponse string = "{\"openconfig-acl:interfaces\":{\"interface\":[{\"config\":{\"id\":\"Ethernet0\"},\"id\":\"Ethernet0\",\"ingress-acl-sets\":{\"ingress-acl-set\":[{\"acl-entries\":{\"acl-entry\":[{\"sequence-id\":2,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":2}}]},\"config\":{\"set-name\":\"MyACL2\",\"type\":\"openconfig-acl:ACL_L2\"},\"set-name\":\"MyACL2\",\"state\":{\"set-name\":\"MyACL2\",\"type\":\"openconfig-acl:ACL_L2\"},\"type\":\"openconfig-acl:ACL_L2\"}]},\"state\":{\"id\":\"Ethernet0\"}}]}}" - -var aclCreateWithInvalidInterfaceBinding string = "{ \"acl-sets\": { \"acl-set\": [ { \"name\": \"MyACL1\", \"type\": \"ACL_IPV4\", \"config\": { \"name\": \"MyACL1\", \"type\": \"ACL_IPV4\", \"description\": \"Description for MyACL1\" }, \"acl-entries\": { \"acl-entry\": [ { \"sequence-id\": 1, \"config\": { \"sequence-id\": 1, \"description\": \"Description for MyACL1 Rule Seq 1\" }, \"ipv4\": { \"config\": { \"source-address\": \"11.1.1.1/32\", \"destination-address\": \"21.1.1.1/32\", \"dscp\": 1, \"protocol\": \"IP_TCP\" } }, \"transport\": { \"config\": { \"source-port\": 101, \"destination-port\": 201 } }, \"actions\": { \"config\": { \"forwarding-action\": \"ACCEPT\" } } } ] } } ] }, \"interfaces\": { \"interface\": [ { \"id\": \"Ethernet2112\", \"config\": { \"id\": \"Ethernet2112\" }, \"interface-ref\": { \"config\": { \"interface\": \"Ethernet2112\" } }, \"ingress-acl-sets\": { \"ingress-acl-set\": [ { \"set-name\": \"MyACL1\", \"type\": \"ACL_IPV4\", \"config\": { \"set-name\": \"MyACL1\", \"type\": \"ACL_IPV4\" } } ] } } ] }}" - -var requestOneDuplicateRulePostJson string = "{\"sequence-id\": 1,\"config\": {\"sequence-id\": 1,\"description\": \"Description for MyACL3 Rule Seq 1\"},\"ipv4\": {\"config\": {\"source-address\": \"4.4.4.4/24\",\"destination-address\": \"5.5.5.5/24\",\"protocol\": \"IP_TCP\"}},\"transport\": {\"config\": {\"source-port\": 101,\"destination-port\": 100,\"tcp-flags\": [\"TCP_FIN\",\"TCP_ACK\"]}},\"actions\": {\"config\": {\"forwarding-action\": \"ACCEPT\"}}}" diff --git a/src/translib/common_app.go b/src/translib/common_app.go index d532fd14e0..b548449e12 100644 --- a/src/translib/common_app.go +++ b/src/translib/common_app.go @@ -300,7 +300,13 @@ func (app *CommonApp) cmnAppCRUCommonDbOpn(d *db.DB, opcode int) error { return err } } else { - return err + // workaround to patch operation from CLI + log.Info("Create(pathc) an entry.") + err = d.CreateEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}, tblRw) + if err != nil { + log.Error("UPDATE case - d.CreateEntry() failure") + return err + } } case REPLACE: if existingEntry.IsPopulated() { diff --git a/src/translib/transformer/xfmr_acl.go b/src/translib/transformer/xfmr_acl.go index 436ae001d6..4130e07ca3 100644 --- a/src/translib/transformer/xfmr_acl.go +++ b/src/translib/transformer/xfmr_acl.go @@ -17,6 +17,8 @@ import ( func init () { XlateFuncBind("YangToDb_acl_set_name_xfmr", YangToDb_acl_set_name_xfmr) XlateFuncBind("DbToYang_acl_set_name_xfmr", DbToYang_acl_set_name_xfmr) + XlateFuncBind("YangToDb_acl_type_field_xfmr", YangToDb_acl_type_field_xfmr) + XlateFuncBind("DbToYang_acl_type_field_xfmr", DbToYang_acl_type_field_xfmr) XlateFuncBind("YangToDb_acl_entry_key_xfmr", YangToDb_acl_entry_key_xfmr) XlateFuncBind("DbToYang_acl_entry_key_xfmr", DbToYang_acl_entry_key_xfmr) XlateFuncBind("YangToDb_acl_entry_sequenceid_xfmr", YangToDb_acl_entry_sequenceid_xfmr) @@ -50,6 +52,13 @@ const ( MAX_PRIORITY = 65535 ) +/* E_OpenconfigAcl_ACL_TYPE */ +var ACL_TYPE_MAP = map[string]string{ + strconv.FormatInt(int64(ocbinds.OpenconfigAcl_ACL_TYPE_ACL_IPV4), 10): SONIC_ACL_TYPE_IPV4, + strconv.FormatInt(int64(ocbinds.OpenconfigAcl_ACL_TYPE_ACL_IPV6), 10): SONIC_ACL_TYPE_IPV6, + strconv.FormatInt(int64(ocbinds.OpenconfigAcl_ACL_TYPE_ACL_L2), 10): SONIC_ACL_TYPE_L2, +} + var IP_PROTOCOL_MAP = map[ocbinds.E_OpenconfigPacketMatchTypes_IP_PROTOCOL]uint8{ ocbinds.OpenconfigPacketMatchTypes_IP_PROTOCOL_IP_ICMP: 1, ocbinds.OpenconfigPacketMatchTypes_IP_PROTOCOL_IP_IGMP: 2, @@ -189,6 +198,30 @@ func getL2EtherType(etherType uint64) interface{} { return uint16(etherType) } +//////////////////////////////////////////// +// Bi-directoonal overloaded methods +//////////////////////////////////////////// + +var YangToDb_acl_type_field_xfmr FieldXfmrYangToDb = func (inParams XfmrParams) (map[string]string, error) { + res_map := make(map[string]string) + var err error + + acltype, _ := inParams.param.(ocbinds.E_OpenconfigAcl_ACL_TYPE) + log.Info("YangToDb_acl_type_field_xfmr: ", inParams.ygRoot, " Xpath: ", inParams.uri, " acltype: ", acltype) + res_map[ACL_TYPE] = findInMap(ACL_TYPE_MAP, strconv.FormatInt(int64(acltype), 10)) + return res_map, err +} +var DbToYang_acl_type_field_xfmr FieldXfmrDbtoYang = func (inParams XfmrParams) (map[string]interface{}, error) { + var err error + result := make(map[string]interface{}) + data:= (*inParams.dbDataMap)[inParams.curDb] + log.Info("DbToYang_acl_type_field_xfmr", data, inParams.ygRoot) + oc_acltype := findInMap(ACL_TYPE_MAP, data[ACL_TABLE][inParams.key].Field[ACL_TYPE]) + n, err := strconv.ParseInt(oc_acltype, 10, 64) + result[ACL_TYPE] = n + return result, err +} + var YangToDb_acl_set_name_xfmr FieldXfmrYangToDb = func (inParams XfmrParams) (map[string]string, error) { res_map := make(map[string]string) var err error diff --git a/src/translib/transformer/xfmr_path_utils.go b/src/translib/transformer/xfmr_path_utils.go index 557e0f3e82..494cf02759 100644 --- a/src/translib/transformer/xfmr_path_utils.go +++ b/src/translib/transformer/xfmr_path_utils.go @@ -110,6 +110,20 @@ func RemoveXPATHPredicates(s string) (string, error) { return b.String(), nil } + +// stripPrefix removes the prefix from a YANG path element. For example, removing +// foo from "foo:bar". Such qualified paths are used in YANG modules where remote +// paths are referenced. +func stripPrefix(name string) (string, error) { + ps := strings.Split(name, ":") + switch len(ps) { + case 1: + return name, nil + case 2: + return ps[1], nil + } + return "", fmt.Errorf("path element did not form a valid name (name, prefix:name): %v", name) +} /* func getParentNode(targetUri *string, deviceObj *ocbinds.Device) (*interface{}, *yang.Entry, error) { path, err := ygot.StringToPath(*targetUri, ygot.StructuredPath, ygot.StringSlicePath) diff --git a/src/translib/transformer/xlate_utils.go b/src/translib/transformer/xlate_utils.go index d3dbe1d3ce..85407ed0fe 100644 --- a/src/translib/transformer/xlate_utils.go +++ b/src/translib/transformer/xlate_utils.go @@ -325,3 +325,32 @@ func formXfmrInputRequest(d *db.DB, dbs [db.MaxDB]*db.DB, cdb db.DBNum, ygRoot * return inParams } + +func findByValue(m map[string]string, value string) string { + for key, val := range m { + if val == value { + return key + } + } + return "" +} +func findByKey(m map[string]string, key string) string { + if val, found := m[key]; found { + return val + } + return "" +} +func findInMap(m map[string]string, str string) string { + // Check if str exists as a value in map m. + if val := findByKey(m, str); val != "" { + return val + } + + // Check if str exists as a key in map m. + if val := findByValue(m, str); val != "" { + return val + } + + // str doesn't exist in map m. + return "" +} From f066a71fcca415e3cd4927a35d4f6712e7f518fe Mon Sep 17 00:00:00 2001 From: jjose Date: Wed, 11 Sep 2019 17:59:57 +0000 Subject: [PATCH 107/214] Fix for bugs 96, 97 and 107 --- src/translib/intf_app.go | 284 +++++++++++++++++++-------------------- 1 file changed, 140 insertions(+), 144 deletions(-) diff --git a/src/translib/intf_app.go b/src/translib/intf_app.go index 4dabe9a8e0..90f45e46d8 100644 --- a/src/translib/intf_app.go +++ b/src/translib/intf_app.go @@ -42,11 +42,10 @@ const ( type Table int const ( - IF_TABLE_MAP Table = iota - PORT_STAT_MAP + IF_TABLE_MAP Table = iota + PORT_STAT_MAP ) - type IntfApp struct { path *PathInfo reqData []byte @@ -359,29 +358,27 @@ func (app *IntfApp) processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error) { return GetResponse{Payload: payload, ErrSrc: AppErr}, err } - /*Check if the request is for a specific attribute in Interfaces state COUNTERS container*/ - counter_val := &ocbinds.OpenconfigInterfaces_Interfaces_Interface_State_Counters{} - ok, e = app.getSpecificCounterAttr(targetUriPath, ifKey, counter_val) - if ok { - if e != nil { - return GetResponse{Payload: payload, ErrSrc: AppErr}, e - } - - payload, err = dumpIetfJson(counter_val, false) - if err == nil { - return GetResponse{Payload: payload}, err - } else { - return GetResponse{Payload: payload, ErrSrc: AppErr}, err - } - } - + /*Check if the request is for a specific attribute in Interfaces state COUNTERS container*/ + counter_val := &ocbinds.OpenconfigInterfaces_Interfaces_Interface_State_Counters{} + ok, e = app.getSpecificCounterAttr(targetUriPath, ifKey, counter_val) + if ok { + if e != nil { + return GetResponse{Payload: payload, ErrSrc: AppErr}, e + } + payload, err = dumpIetfJson(counter_val, false) + if err == nil { + return GetResponse{Payload: payload}, err + } else { + return GetResponse{Payload: payload, ErrSrc: AppErr}, err + } + } - /* Filling Interface IP info to internal DS */ - err = app.convertDBIntfIPInfoToInternal(app.appDB, ifKey) - if err != nil { - return GetResponse{Payload: payload, ErrSrc: AppErr}, err - } + /* Filling Interface IP info to internal DS */ + err = app.convertDBIntfIPInfoToInternal(app.appDB, ifKey) + if err != nil { + return GetResponse{Payload: payload, ErrSrc: AppErr}, err + } /* Filling the tree with the info we have in Internal DS */ ygot.BuildEmptyTree(ifInfo) @@ -547,141 +544,139 @@ func (app *IntfApp) getSpecificAttr(targetUriPath string, ifKey string, oc_val * return true, e default: - log.Infof(targetUriPath + " - Not an interface state attribute") + log.Infof(targetUriPath + " - Not an interface state attribute") } return false, nil } func (app *IntfApp) getSpecificCounterAttr(targetUriPath string, ifKey string, counter_val *ocbinds.OpenconfigInterfaces_Interfaces_Interface_State_Counters) (bool, error) { - var e error - - switch targetUriPath { - case "/openconfig-interfaces:interfaces/interface/state/counters/in-octets": - e = app.getCounters(ifKey, "SAI_PORT_STAT_IF_IN_OCTETS", &counter_val.InOctets) - return true, e - - case "/openconfig-interfaces:interfaces/interface/state/counters/in-unicast-pkts": - e = app.getCounters(ifKey, "SAI_PORT_STAT_IF_IN_UCAST_PKTS", &counter_val.InUnicastPkts) - return true, e - - case "/openconfig-interfaces:interfaces/interface/state/counters/in-broadcast-pkts": - e = app.getCounters(ifKey, "SAI_PORT_STAT_IF_IN_BROADCAST_PKTS", &counter_val.InBroadcastPkts) - return true, e - - case "/openconfig-interfaces:interfaces/interface/state/counters/in-multicast-pkts": - e = app.getCounters(ifKey, "SAI_PORT_STAT_IF_IN_MULTICAST_PKTS", &counter_val.InMulticastPkts) - return true, e - - case "/openconfig-interfaces:interfaces/interface/state/counters/in-errors": - e = app.getCounters(ifKey, "SAI_PORT_STAT_IF_IN_ERRORS", &counter_val.InErrors) - return true, e - - case "/openconfig-interfaces:interfaces/interface/state/counters/in-discards": - e = app.getCounters(ifKey, "SAI_PORT_STAT_IF_IN_DISCARDS", &counter_val.InDiscards) - return true, e - - case "/openconfig-interfaces:interfaces/interface/state/counters/in-pkts": - var inNonUCastPkt, inUCastPkt *uint64 - var in_pkts uint64 - - e = app.getCounters(ifKey, "SAI_PORT_STAT_IF_IN_NON_UCAST_PKTS", &inNonUCastPkt) - if e == nil { - e = app.getCounters(ifKey, "SAI_PORT_STAT_IF_IN_UCAST_PKTS", &inUCastPkt) - if e != nil { - return true, e - } - in_pkts = *inUCastPkt + *inNonUCastPkt - counter_val.InPkts = &in_pkts - return true, e - } else { - return true, e - } - - case "/openconfig-interfaces:interfaces/interface/state/counters/out-octets": - e = app.getCounters(ifKey, "SAI_PORT_STAT_IF_OUT_OCTETS", &counter_val.OutOctets) - return true, e - - case "/openconfig-interfaces:interfaces/interface/state/counters/out-unicast-pkts": - e = app.getCounters(ifKey, "SAI_PORT_STAT_IF_OUT_UCAST_PKTS", &counter_val.OutUnicastPkts) - return true, e - - case "/openconfig-interfaces:interfaces/interface/state/counters/out-broadcast-pkts": - e = app.getCounters(ifKey, "SAI_PORT_STAT_IF_OUT_BROADCAST_PKTS", &counter_val.OutBroadcastPkts) - return true, e - - case "/openconfig-interfaces:interfaces/interface/state/counters/out-multicast-pkts": - e = app.getCounters(ifKey, "SAI_PORT_STAT_IF_OUT_MULTICAST_PKTS", &counter_val.OutMulticastPkts) - return true, e - - case "/openconfig-interfaces:interfaces/interface/state/counters/out-errors": - e = app.getCounters(ifKey, "SAI_PORT_STAT_IF_OUT_ERRORS", &counter_val.OutErrors) - return true, e - - case "/openconfig-interfaces:interfaces/interface/state/counters/out-discards": - e = app.getCounters(ifKey, "SAI_PORT_STAT_IF_OUT_DISCARDS", &counter_val.OutDiscards) - return true, e - - case "/openconfig-interfaces:interfaces/interface/state/counters/out-pkts": - var outNonUCastPkt, outUCastPkt *uint64 - var out_pkts uint64 - - e = app.getCounters(ifKey, "SAI_PORT_STAT_IF_OUT_NON_UCAST_PKTS", &outNonUCastPkt) - if e == nil { - e = app.getCounters(ifKey, "SAI_PORT_STAT_IF_OUT_UCAST_PKTS", &outUCastPkt) - if e != nil { - return true, e - } - out_pkts = *outUCastPkt + *outNonUCastPkt - counter_val.OutPkts = &out_pkts - return true, e - } else { - return true, e - } - - - default: - log.Infof(targetUriPath + " - Not an interface state counter attribute") - } - return false, nil + var e error + + switch targetUriPath { + case "/openconfig-interfaces:interfaces/interface/state/counters/in-octets": + e = app.getCounters(ifKey, "SAI_PORT_STAT_IF_IN_OCTETS", &counter_val.InOctets) + return true, e + + case "/openconfig-interfaces:interfaces/interface/state/counters/in-unicast-pkts": + e = app.getCounters(ifKey, "SAI_PORT_STAT_IF_IN_UCAST_PKTS", &counter_val.InUnicastPkts) + return true, e + + case "/openconfig-interfaces:interfaces/interface/state/counters/in-broadcast-pkts": + e = app.getCounters(ifKey, "SAI_PORT_STAT_IF_IN_BROADCAST_PKTS", &counter_val.InBroadcastPkts) + return true, e + + case "/openconfig-interfaces:interfaces/interface/state/counters/in-multicast-pkts": + e = app.getCounters(ifKey, "SAI_PORT_STAT_IF_IN_MULTICAST_PKTS", &counter_val.InMulticastPkts) + return true, e + + case "/openconfig-interfaces:interfaces/interface/state/counters/in-errors": + e = app.getCounters(ifKey, "SAI_PORT_STAT_IF_IN_ERRORS", &counter_val.InErrors) + return true, e + + case "/openconfig-interfaces:interfaces/interface/state/counters/in-discards": + e = app.getCounters(ifKey, "SAI_PORT_STAT_IF_IN_DISCARDS", &counter_val.InDiscards) + return true, e + + case "/openconfig-interfaces:interfaces/interface/state/counters/in-pkts": + var inNonUCastPkt, inUCastPkt *uint64 + var in_pkts uint64 + + e = app.getCounters(ifKey, "SAI_PORT_STAT_IF_IN_NON_UCAST_PKTS", &inNonUCastPkt) + if e == nil { + e = app.getCounters(ifKey, "SAI_PORT_STAT_IF_IN_UCAST_PKTS", &inUCastPkt) + if e != nil { + return true, e + } + in_pkts = *inUCastPkt + *inNonUCastPkt + counter_val.InPkts = &in_pkts + return true, e + } else { + return true, e + } + + case "/openconfig-interfaces:interfaces/interface/state/counters/out-octets": + e = app.getCounters(ifKey, "SAI_PORT_STAT_IF_OUT_OCTETS", &counter_val.OutOctets) + return true, e + + case "/openconfig-interfaces:interfaces/interface/state/counters/out-unicast-pkts": + e = app.getCounters(ifKey, "SAI_PORT_STAT_IF_OUT_UCAST_PKTS", &counter_val.OutUnicastPkts) + return true, e + + case "/openconfig-interfaces:interfaces/interface/state/counters/out-broadcast-pkts": + e = app.getCounters(ifKey, "SAI_PORT_STAT_IF_OUT_BROADCAST_PKTS", &counter_val.OutBroadcastPkts) + return true, e + + case "/openconfig-interfaces:interfaces/interface/state/counters/out-multicast-pkts": + e = app.getCounters(ifKey, "SAI_PORT_STAT_IF_OUT_MULTICAST_PKTS", &counter_val.OutMulticastPkts) + return true, e + + case "/openconfig-interfaces:interfaces/interface/state/counters/out-errors": + e = app.getCounters(ifKey, "SAI_PORT_STAT_IF_OUT_ERRORS", &counter_val.OutErrors) + return true, e + + case "/openconfig-interfaces:interfaces/interface/state/counters/out-discards": + e = app.getCounters(ifKey, "SAI_PORT_STAT_IF_OUT_DISCARDS", &counter_val.OutDiscards) + return true, e + + case "/openconfig-interfaces:interfaces/interface/state/counters/out-pkts": + var outNonUCastPkt, outUCastPkt *uint64 + var out_pkts uint64 + + e = app.getCounters(ifKey, "SAI_PORT_STAT_IF_OUT_NON_UCAST_PKTS", &outNonUCastPkt) + if e == nil { + e = app.getCounters(ifKey, "SAI_PORT_STAT_IF_OUT_UCAST_PKTS", &outUCastPkt) + if e != nil { + return true, e + } + out_pkts = *outUCastPkt + *outNonUCastPkt + counter_val.OutPkts = &out_pkts + return true, e + } else { + return true, e + } + + default: + log.Infof(targetUriPath + " - Not an interface state counter attribute") + } + return false, nil } -func (app *IntfApp) getCounters( ifKey string, attr string, counter_val **uint64 ) error { - val, e := app.getIntfAttr(ifKey, attr, PORT_STAT_MAP) - if len(val) > 0 { - v, e := strconv.ParseUint(val, 10, 64) - if e == nil { - *counter_val = &v - return nil - } - } - return e +func (app *IntfApp) getCounters(ifKey string, attr string, counter_val **uint64) error { + val, e := app.getIntfAttr(ifKey, attr, PORT_STAT_MAP) + if len(val) > 0 { + v, e := strconv.ParseUint(val, 10, 64) + if e == nil { + *counter_val = &v + return nil + } + } + return e } func (app *IntfApp) getIntfAttr(ifName string, attr string, table Table) (string, error) { - var ok bool = false - var entry dbEntry + var ok bool = false + var entry dbEntry - if table == IF_TABLE_MAP { - entry, ok = app.ifTableMap[ifName]; - } else if table == PORT_STAT_MAP { - entry, ok = app.portStatMap[ifName]; - } else { - return "", errors.New("Unsupported table") - } + if table == IF_TABLE_MAP { + entry, ok = app.ifTableMap[ifName] + } else if table == PORT_STAT_MAP { + entry, ok = app.portStatMap[ifName] + } else { + return "", errors.New("Unsupported table") + } if ok { - ifData := entry.entry + ifData := entry.entry - if val, ok := ifData.Field[attr]; ok { - return val, nil - } + if val, ok := ifData.Field[attr]; ok { + return val, nil + } } return "", errors.New("Attr " + attr + "doesn't exist in IF table Map!") } - /*********** Translation Helper fn to convert DB Interface info to Internal DS ***********/ func (app *IntfApp) getPortOidMapForCounters(dbCl *db.DB) error { var err error @@ -851,19 +846,20 @@ func (app *IntfApp) convertInternalToOCIntfAttrInfo(ifName *string, ifInfo *ocbi switch speed { case "40000": speedEnum = ocbinds.OpenconfigIfEthernet_ETHERNET_SPEED_SPEED_40GB - speedEnum = ocbinds.OpenconfigIfEthernet_ETHERNET_SPEED_SPEED_40GB case "25000": speedEnum = ocbinds.OpenconfigIfEthernet_ETHERNET_SPEED_SPEED_25GB - speedEnum = ocbinds.OpenconfigIfEthernet_ETHERNET_SPEED_SPEED_25GB case "10000": speedEnum = ocbinds.OpenconfigIfEthernet_ETHERNET_SPEED_SPEED_10GB - speedEnum = ocbinds.OpenconfigIfEthernet_ETHERNET_SPEED_SPEED_10GB case "5000": speedEnum = ocbinds.OpenconfigIfEthernet_ETHERNET_SPEED_SPEED_5GB - speedEnum = ocbinds.OpenconfigIfEthernet_ETHERNET_SPEED_SPEED_5GB case "1000": speedEnum = ocbinds.OpenconfigIfEthernet_ETHERNET_SPEED_SPEED_1GB - speedEnum = ocbinds.OpenconfigIfEthernet_ETHERNET_SPEED_SPEED_1GB + case "100000": + speedEnum = ocbinds.OpenconfigIfEthernet_ETHERNET_SPEED_SPEED_100GB + case "2500": + speedEnum = ocbinds.OpenconfigIfEthernet_ETHERNET_SPEED_SPEED_2500MB + case "50000": + speedEnum = ocbinds.OpenconfigIfEthernet_ETHERNET_SPEED_SPEED_50GB default: log.Infof("Not supported speed: %s!", speed) } From 12a708d66befd01bec1e13222f519c884311d8af Mon Sep 17 00:00:00 2001 From: jjose Date: Wed, 11 Sep 2019 18:30:31 +0000 Subject: [PATCH 108/214] Addressed the comment to sort the speed --- src/translib/intf_app.go | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/translib/intf_app.go b/src/translib/intf_app.go index 90f45e46d8..b74e978aa0 100644 --- a/src/translib/intf_app.go +++ b/src/translib/intf_app.go @@ -844,22 +844,22 @@ func (app *IntfApp) convertInternalToOCIntfAttrInfo(ifName *string, ifInfo *ocbi var speedEnum ocbinds.E_OpenconfigIfEthernet_ETHERNET_SPEED switch speed { - case "40000": - speedEnum = ocbinds.OpenconfigIfEthernet_ETHERNET_SPEED_SPEED_40GB - case "25000": - speedEnum = ocbinds.OpenconfigIfEthernet_ETHERNET_SPEED_SPEED_25GB - case "10000": - speedEnum = ocbinds.OpenconfigIfEthernet_ETHERNET_SPEED_SPEED_10GB - case "5000": - speedEnum = ocbinds.OpenconfigIfEthernet_ETHERNET_SPEED_SPEED_5GB - case "1000": - speedEnum = ocbinds.OpenconfigIfEthernet_ETHERNET_SPEED_SPEED_1GB - case "100000": - speedEnum = ocbinds.OpenconfigIfEthernet_ETHERNET_SPEED_SPEED_100GB case "2500": speedEnum = ocbinds.OpenconfigIfEthernet_ETHERNET_SPEED_SPEED_2500MB + case "1000": + speedEnum = ocbinds.OpenconfigIfEthernet_ETHERNET_SPEED_SPEED_1GB + case "5000": + speedEnum = ocbinds.OpenconfigIfEthernet_ETHERNET_SPEED_SPEED_5GB + case "10000": + speedEnum = ocbinds.OpenconfigIfEthernet_ETHERNET_SPEED_SPEED_10GB + case "25000": + speedEnum = ocbinds.OpenconfigIfEthernet_ETHERNET_SPEED_SPEED_25GB + case "40000": + speedEnum = ocbinds.OpenconfigIfEthernet_ETHERNET_SPEED_SPEED_40GB case "50000": speedEnum = ocbinds.OpenconfigIfEthernet_ETHERNET_SPEED_SPEED_50GB + case "100000": + speedEnum = ocbinds.OpenconfigIfEthernet_ETHERNET_SPEED_SPEED_100GB default: log.Infof("Not supported speed: %s!", speed) } From 2eb5d983e76bac112a88dcd0225f2d96cfb92cb5 Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Wed, 11 Sep 2019 11:57:55 -0700 Subject: [PATCH 109/214] Fix sonic get query failure --- src/translib/transformer/xlate.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index 797a6a2354..6aefb42a7b 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -288,7 +288,7 @@ func XlateFromDb(uri string, ygRoot *ygot.GoStruct, dbs [db.MaxDB]*db.DB, data m var err error var dbData = make(map[db.DBNum]map[string]map[string]db.Value) - var cdb db.DBNum + var cdb db.DBNum = db.ConfigDB dbData = data if isCvlYang(uri) { @@ -298,14 +298,15 @@ func XlateFromDb(uri string, ygRoot *ygot.GoStruct, dbs [db.MaxDB]*db.DB, data m // Format /module:container/tableName[key]/fieldName if tokens[len(tokens)-2] == tableName { fieldName := tokens[len(tokens)-1] - cdb = xSpecMap[yangXpath].dbIndex dbData[cdb] = extractFieldFromDb(tableName, keyStr, fieldName, data[cdb]) } } + } else { + xpath, _ := RemoveXPATHPredicates(uri) + cdb = xSpecMap[xpath].dbIndex } - xpath, _ := RemoveXPATHPredicates(uri) - cdb = xSpecMap[xpath].dbIndex payload, err := dbDataToYangJsonCreate(uri, ygRoot, dbs, &dbData, cdb) + log.Info("Payload generated:", payload) if err != nil { log.Errorf("Error: failed to create json response from DB data.") From 021c9034652d47f1c236f253aeb8ff0a2cdff1eb Mon Sep 17 00:00:00 2001 From: s-mari Date: Wed, 11 Sep 2019 12:40:03 -0700 Subject: [PATCH 110/214] fix to exclude key-leaf data populating db-filed value and removed commented lines in xmfr_acl --- src/translib/transformer/xfmr_acl.go | 152 ------------------------ src/translib/transformer/xlate_to_db.go | 9 +- 2 files changed, 6 insertions(+), 155 deletions(-) diff --git a/src/translib/transformer/xfmr_acl.go b/src/translib/transformer/xfmr_acl.go index 4130e07ca3..8e668228f0 100644 --- a/src/translib/transformer/xfmr_acl.go +++ b/src/translib/transformer/xfmr_acl.go @@ -360,36 +360,6 @@ var DbToYang_acl_l2_ethertype_xfmr FieldXfmrDbtoYang = func (inParams XfmrParams err = errors.New("ETHER_TYPE field not found in DB") } return result, nil - - /* - if _, ok := data[RULE_TABLE]; !ok { - err = errors.New("RULE_TABLE entry not found in the input param") - return err - } - ruleTbl := data[RULE_TABLE] - - for aclRuleKey := range ruleTbl { - ruleData := ruleTbl[aclRuleKey] - var entrySet *ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry - entrySet, err = getAclSetEntry(aclRuleKey, ygRoot) - if err != nil { - log.Info("getAclSetEntry failed for :", aclRuleKey) - continue // If its not map doesnt need to loop just return from here. - } - ruleKey := "ETHER_TYPE" - if !ruleData.Has(ruleKey) { - log.Info("No entry found for the field ", ruleKey) - err = errors.New("ETHER_TYPE field not found in DB") - continue - } - ethType, _ := strconv.ParseUint(strings.Replace(ruleData.Get(ruleKey), "0x", "", -1), 16, 32) - ethertype := getL2EtherType(ethType) - entrySet.L2.Config.Ethertype, _ = entrySet.L2.Config.To_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_L2_Config_Ethertype_Union(ethertype) - entrySet.L2.State.Ethertype, _ = entrySet.L2.State.To_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_L2_State_Ethertype_Union(ethertype) - - } - return err - */ } var YangToDb_acl_ip_protocol_xfmr FieldXfmrYangToDb = func (inParams XfmrParams) (map[string]string, error) { @@ -432,29 +402,6 @@ var DbToYang_acl_ip_protocol_xfmr FieldXfmrDbtoYang = func (inParams XfmrParams) err = errors.New("IP_PROTOCOL field not found in DB") } return result, err - - /* - for aclRuleKey := range ruleTbl { - ruleData := ruleTbl[aclRuleKey] - var entrySet *ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry - entrySet, err = getAclSetEntry(aclRuleKey, ygRoot) - if err != nil { - log.Info("getAclSetEntry failed for :", aclRuleKey) - continue // If its not map doesnt need to loop just return from here. - } - ruleKey := "IP_PROTOCOL" - if !ruleData.Has(ruleKey) { - log.Info("No entry found for the field ", ruleKey) - err = errors.New("IP_PROTOCOL field not found in DB") - continue - } - - ipProto, _ := strconv.ParseInt(ruleData.Get(ruleKey), 10, 64) - protocolVal := getIpProtocol(ipProto) - entrySet.Ipv6.Config.Protocol, _ = entrySet.Ipv6.Config.To_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Ipv6_Config_Protocol_Union(protocolVal) - entrySet.Ipv6.State.Protocol, _ = entrySet.Ipv6.State.To_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Ipv6_State_Protocol_Union(protocolVal) - } - */ } var YangToDb_acl_source_port_xfmr FieldXfmrYangToDb = func (inParams XfmrParams) (map[string]string, error) { @@ -545,42 +492,6 @@ var DbToYang_acl_source_port_xfmr FieldXfmrDbtoYang = func (inParams XfmrParams) err = errors.New("PORT/PORT_RANGE field not found in DB") } return result, err - /* - - if _, ok := data[RULE_TABLE]; !ok { - err = errors.New("RULE_TABLE entry not found in the input param") - return err - } - ruleTbl := data[RULE_TABLE] - - for aclRuleKey := range ruleTbl { - ruleData := ruleTbl[aclRuleKey] - sp := ruleData.Has("L4_SRC_PORT") - spr := ruleData.Has("L4_SRC_PORT_RANGE") - - if !sp && !spr { - log.Info("Src port field is not present in the field.") - continue - } - var entrySet *ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry - entrySet, err = getAclSetEntry(aclRuleKey, ygRoot) - if err != nil { - log.Info("getAclSetEntry failed for :", aclRuleKey) - continue // If its not map doesnt need to loop just return from here. - } - var ruleKey string - if sp { - ruleKey = "L4_SRC_PORT" - } else { - ruleKey = "L4_SRC_PORT_RANGE" - } - port := ruleData.Get(ruleKey) - srcPort := getTransportSrcDestPorts(port, "src") - entrySet.Transport.Config.SourcePort, _ = entrySet.Transport.Config.To_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort_Union(srcPort) - entrySet.Transport.State.SourcePort, _ = entrySet.Transport.State.To_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_State_SourcePort_Union(srcPort) - } - return err - */ } var YangToDb_acl_destination_port_xfmr FieldXfmrYangToDb = func (inParams XfmrParams) (map[string]string, error) { @@ -630,41 +541,6 @@ var DbToYang_acl_destination_port_xfmr FieldXfmrDbtoYang = func (inParams XfmrPa err = errors.New("DST PORT/PORT_RANGE field not found in DB") } return result, err - /* - if _, ok := data[RULE_TABLE]; !ok { - err = errors.New("RULE_TABLE entry not found in the input param") - return err - } - ruleTbl := data[RULE_TABLE] - for aclRuleKey := range ruleTbl { - ruleData := ruleTbl[aclRuleKey] - dp := ruleData.Has("L4_DST_PORT") - dpr := ruleData.Has("L4_DST_PORT_RANGE") - if !dp && !dpr { - log.Info("DST port field is not present in the field.") - continue - } - - var entrySet *ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry - entrySet, err = getAclSetEntry(aclRuleKey, ygRoot) - if err != nil { - log.Info("getAclSetEntry failed for :", aclRuleKey) - continue // If its not map doesnt need to loop just return from here. - var ruleKey string - if dp { - ruleKey = "L4_DST_PORT" - } else { - ruleKey = "L4_DST_PORT_RANGE" - } - port := ruleData.Get(ruleKey) - destPort := getTransportSrcDestPorts(port, "dest") - entrySet.Transport.Config.DestinationPort, _ = entrySet.Transport.Config.To_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort_Union(destPort) - entrySet.Transport.State.DestinationPort, _ = entrySet.Transport.State.To_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_State_DestinationPort_Union(destPort) - } - - } - return err - */ } var YangToDb_acl_tcp_flags_xfmr FieldXfmrYangToDb = func (inParams XfmrParams) (map[string]string, error) { @@ -727,34 +603,6 @@ var DbToYang_acl_tcp_flags_xfmr FieldXfmrDbtoYang = func (inParams XfmrParams) return result, nil } return result, nil - /* - - if _, ok := data[RULE_TABLE]; !ok { - err = errors.New("RULE_TABLE entry not found in the input param") - return err - } - ruleTbl := data[RULE_TABLE] - - for aclRuleKey := range ruleTbl { - ruleData := ruleTbl[aclRuleKey] - var entrySet *ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry - entrySet, err = getAclSetEntry(aclRuleKey, ygRoot) - if err != nil { - log.Info("getAclSetEntry failed for :", aclRuleKey) - continue // If its not map doesnt need to loop just return from here. - } - ruleKey := "TCP_FLAGS" - if !ruleData.Has(ruleKey) { - log.Info("No entry found for the field ", ruleKey) - err = errors.New("TCP_FLAGS field not found in DB") - continue - } - tcpFlags := ruleData.Get(ruleKey) - entrySet.Transport.Config.TcpFlags = getTransportConfigTcpFlags(tcpFlags) - entrySet.Transport.State.TcpFlags = getTransportConfigTcpFlags(tcpFlags) - } - return err - */ } func convertDBAclRulesToInternal(dbCl *db.DB, aclName string, seqId int64, ruleKey db.Key) (ruleTableMap map[string]map[string]db.Value, ferr error) { diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index 9a92d3a3a5..dba137508b 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -55,6 +55,9 @@ func mapFillData(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, dbKey st return errors.New("Invalid table key") } + if xpathInfo.isKey { + return nil + } if len(xpathInfo.xfmrFunc) > 0 { uri = uri + "/" + name @@ -78,8 +81,8 @@ func mapFillData(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, dbKey st if nErr != nil { return nErr } - var dbs [db.MaxDB]*db.DB - inParams := formXfmrInputRequest(d, dbs, db.MaxDB, ygRoot, uri, oper, "", nil, node[0].Data) + var dbs [db.MaxDB]*db.DB + inParams := formXfmrInputRequest(d, dbs, db.MaxDB, ygRoot, uri, oper, "", nil, node[0].Data) ret, err := XlateFuncCall(yangToDbXfmrFunc(xSpecMap[xpath].xfmrFunc), inParams) if err != nil { return err @@ -275,7 +278,7 @@ func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, curUri := uriWithKeyCreate(uri, xpathPrefix, data) if len(xSpecMap[xpathPrefix].xfmrKey) > 0 { /* key transformer present */ - inParams := formXfmrInputRequest(d, dbs, db.MaxDB, ygRoot, curUri, oper, "", nil, nil) + inParams := formXfmrInputRequest(d, dbs, db.MaxDB, ygRoot, curUri, oper, "", nil, nil) ret, err := XlateFuncCall(yangToDbXfmrFunc(xSpecMap[xpathPrefix].xfmrKey), inParams) if err != nil { return err From 2f0d6ecdd46337f6903801c97fcd3151964f497a Mon Sep 17 00:00:00 2001 From: jjose Date: Wed, 11 Sep 2019 20:56:44 +0000 Subject: [PATCH 111/214] Change MAX_MTU to 9216 in platform_dummy file as well, since it overwrites it. --- src/CLI/clitree/scripts/platform_dummy.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CLI/clitree/scripts/platform_dummy.xml b/src/CLI/clitree/scripts/platform_dummy.xml index 108e881454..191f0c51cc 100644 --- a/src/CLI/clitree/scripts/platform_dummy.xml +++ b/src/CLI/clitree/scripts/platform_dummy.xml @@ -20,6 +20,6 @@ MAX_PORT_ID START_SUB_PORT_ID MAX_SUB_PORT_ID - MAX_MTU + MAX_MTU From f2290f4e402b3944023b2bb4845020ff2675d61f Mon Sep 17 00:00:00 2001 From: s-mari Date: Wed, 11 Sep 2019 16:35:54 -0700 Subject: [PATCH 112/214] added unit8 yang data0type support for get-req --- src/translib/transformer/xlate_from_db.go | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index b636c4351f..06898f84de 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -16,6 +16,10 @@ import ( type typeMapOfInterface map[string]interface{} +const ( + Yuint8 = 5 +) + func xfmrHandlerFunc(inParams XfmrParams) (string, error) { xpath, _ := RemoveXPATHPredicates(inParams.uri) _, err := XlateFuncCall(dbToYangXfmrFunc(xSpecMap[xpath].xfmrFunc), inParams) @@ -161,11 +165,14 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath if len(dbFldName) > 0 && !xSpecMap[chldXpath].isKey { val, ok := (*dbDataMap)[cdb][tbl][tblKey].Field[dbFldName] if ok { - valInt, err := strconv.Atoi(val) - if err == nil { + /* this will be enhanced to support all yang data types */ + yNode := xSpecMap[chldXpath] + yDataType := yNode.yangEntry.Type.Kind + if yDataType == Yuint8 { + valInt, _ := strconv.Atoi(val) resultMap[xSpecMap[chldXpath].yangEntry.Name] = valInt } else { - resultMap[xSpecMap[chldXpath].yangEntry.Name] = val + resultMap[yNode.yangEntry.Name] = val } } } From 6ff960d617b01bd752184ca5f6f06fa4201f69b8 Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Wed, 11 Sep 2019 19:31:03 -0700 Subject: [PATCH 113/214] Fix crash for get leaf query --- src/translib/common_app.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/translib/common_app.go b/src/translib/common_app.go index b548449e12..f75ad72476 100644 --- a/src/translib/common_app.go +++ b/src/translib/common_app.go @@ -163,11 +163,13 @@ func (app *CommonApp) processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error) { return GetResponse{Payload: payload, ErrSrc: AppErr}, err } - targetObj, _ := (*app.ygotTarget).(ygot.GoStruct) - err = ocbinds.Unmarshal(payload, targetObj) - if err != nil { - log.Error("ocbinds.Unmarshal() failed") - return GetResponse{Payload: payload, ErrSrc: AppErr}, err + if targetObj != nil { + targetObj, _ := (*app.ygotTarget).(ygot.GoStruct) + err = ocbinds.Unmarshal(payload, targetObj) + if err != nil { + log.Error("ocbinds.Unmarshal() failed") + return GetResponse{Payload: payload, ErrSrc: AppErr}, err + } } payload, err = generateGetResponsePayload(app.pathInfo.Path, (*app.ygotRoot).(*ocbinds.Device), app.ygotTarget) From 02b246d6d2c9ee1df71483c592805080378966a8 Mon Sep 17 00:00:00 2001 From: Kwan Kim Date: Wed, 11 Sep 2019 20:44:16 -0700 Subject: [PATCH 114/214] cleanup code to showcase overloaded methods --- src/translib/transformer/xfmr_acl.go | 1938 +++++++++++--------------- 1 file changed, 786 insertions(+), 1152 deletions(-) diff --git a/src/translib/transformer/xfmr_acl.go b/src/translib/transformer/xfmr_acl.go index 4130e07ca3..645d7011fb 100644 --- a/src/translib/transformer/xfmr_acl.go +++ b/src/translib/transformer/xfmr_acl.go @@ -1,1209 +1,843 @@ package transformer import ( - "fmt" - "bytes" - "errors" - "strings" - "github.com/openconfig/ygot/ygot" - "strconv" - "translib/db" - "reflect" - log "github.com/golang/glog" - "translib/ocbinds" - "translib/tlerr" + "bytes" + "errors" + "fmt" + log "github.com/golang/glog" + "github.com/openconfig/ygot/ygot" + "reflect" + "strconv" + "strings" + "translib/db" + "translib/ocbinds" + "translib/tlerr" ) -func init () { - XlateFuncBind("YangToDb_acl_set_name_xfmr", YangToDb_acl_set_name_xfmr) - XlateFuncBind("DbToYang_acl_set_name_xfmr", DbToYang_acl_set_name_xfmr) - XlateFuncBind("YangToDb_acl_type_field_xfmr", YangToDb_acl_type_field_xfmr) - XlateFuncBind("DbToYang_acl_type_field_xfmr", DbToYang_acl_type_field_xfmr) - XlateFuncBind("YangToDb_acl_entry_key_xfmr", YangToDb_acl_entry_key_xfmr) - XlateFuncBind("DbToYang_acl_entry_key_xfmr", DbToYang_acl_entry_key_xfmr) - XlateFuncBind("YangToDb_acl_entry_sequenceid_xfmr", YangToDb_acl_entry_sequenceid_xfmr) - XlateFuncBind("DbToYang_acl_entry_sequenceid_xfmr", DbToYang_acl_entry_sequenceid_xfmr) - XlateFuncBind("YangToDb_acl_l2_ethertype_xfmr", YangToDb_acl_l2_ethertype_xfmr) - XlateFuncBind("DbToYang_acl_l2_ethertype_xfmr", DbToYang_acl_l2_ethertype_xfmr) - XlateFuncBind("YangToDb_acl_ip_protocol_xfmr", YangToDb_acl_ip_protocol_xfmr) - XlateFuncBind("DbToYang_acl_ip_protocol_xfmr", DbToYang_acl_ip_protocol_xfmr) - XlateFuncBind("YangToDb_acl_source_port_xfmr", YangToDb_acl_source_port_xfmr) - XlateFuncBind("DbToYang_acl_source_port_xfmr", DbToYang_acl_source_port_xfmr) - XlateFuncBind("YangToDb_acl_destination_port_xfmr", YangToDb_acl_destination_port_xfmr) - XlateFuncBind("DbToYang_acl_destination_port_xfmr", DbToYang_acl_destination_port_xfmr) - XlateFuncBind("YangToDb_acl_tcp_flags_xfmr", YangToDb_acl_tcp_flags_xfmr) - XlateFuncBind("DbToYang_acl_tcp_flags_xfmr", DbToYang_acl_tcp_flags_xfmr) - XlateFuncBind("YangToDb_acl_port_bindings_xfmr", YangToDb_acl_port_bindings_xfmr) - XlateFuncBind("DbToYang_acl_port_bindings_xfmr", DbToYang_acl_port_bindings_xfmr) +func init() { + XlateFuncBind("YangToDb_acl_set_name_xfmr", YangToDb_acl_set_name_xfmr) + XlateFuncBind("DbToYang_acl_set_name_xfmr", DbToYang_acl_set_name_xfmr) + XlateFuncBind("YangToDb_acl_type_field_xfmr", YangToDb_acl_type_field_xfmr) + XlateFuncBind("DbToYang_acl_type_field_xfmr", DbToYang_acl_type_field_xfmr) + XlateFuncBind("YangToDb_acl_entry_key_xfmr", YangToDb_acl_entry_key_xfmr) + XlateFuncBind("DbToYang_acl_entry_key_xfmr", DbToYang_acl_entry_key_xfmr) + XlateFuncBind("YangToDb_acl_entry_sequenceid_xfmr", YangToDb_acl_entry_sequenceid_xfmr) + XlateFuncBind("DbToYang_acl_entry_sequenceid_xfmr", DbToYang_acl_entry_sequenceid_xfmr) + XlateFuncBind("YangToDb_acl_l2_ethertype_xfmr", YangToDb_acl_l2_ethertype_xfmr) + XlateFuncBind("DbToYang_acl_l2_ethertype_xfmr", DbToYang_acl_l2_ethertype_xfmr) + XlateFuncBind("YangToDb_acl_ip_protocol_xfmr", YangToDb_acl_ip_protocol_xfmr) + XlateFuncBind("DbToYang_acl_ip_protocol_xfmr", DbToYang_acl_ip_protocol_xfmr) + XlateFuncBind("YangToDb_acl_source_port_xfmr", YangToDb_acl_source_port_xfmr) + XlateFuncBind("DbToYang_acl_source_port_xfmr", DbToYang_acl_source_port_xfmr) + XlateFuncBind("YangToDb_acl_destination_port_xfmr", YangToDb_acl_destination_port_xfmr) + XlateFuncBind("DbToYang_acl_destination_port_xfmr", DbToYang_acl_destination_port_xfmr) + XlateFuncBind("YangToDb_acl_tcp_flags_xfmr", YangToDb_acl_tcp_flags_xfmr) + XlateFuncBind("DbToYang_acl_tcp_flags_xfmr", DbToYang_acl_tcp_flags_xfmr) + XlateFuncBind("YangToDb_acl_port_bindings_xfmr", YangToDb_acl_port_bindings_xfmr) + XlateFuncBind("DbToYang_acl_port_bindings_xfmr", DbToYang_acl_port_bindings_xfmr) } const ( - ACL_TABLE = "ACL_TABLE" - RULE_TABLE = "ACL_RULE" - SONIC_ACL_TYPE_IPV4 = "L3" - SONIC_ACL_TYPE_L2 = "L2" - SONIC_ACL_TYPE_IPV6 = "L3V6" - OPENCONFIG_ACL_TYPE_IPV4 = "ACL_IPV4" - OPENCONFIG_ACL_TYPE_IPV6 = "ACL_IPV6" - OPENCONFIG_ACL_TYPE_L2 = "ACL_L2" - ACL_TYPE = "type" - - MIN_PRIORITY = 1 - MAX_PRIORITY = 65535 + ACL_TABLE = "ACL_TABLE" + RULE_TABLE = "ACL_RULE" + SONIC_ACL_TYPE_IPV4 = "L3" + SONIC_ACL_TYPE_L2 = "L2" + SONIC_ACL_TYPE_IPV6 = "L3V6" + OPENCONFIG_ACL_TYPE_IPV4 = "ACL_IPV4" + OPENCONFIG_ACL_TYPE_IPV6 = "ACL_IPV6" + OPENCONFIG_ACL_TYPE_L2 = "ACL_L2" + ACL_TYPE = "type" + + MIN_PRIORITY = 1 + MAX_PRIORITY = 65535 ) /* E_OpenconfigAcl_ACL_TYPE */ var ACL_TYPE_MAP = map[string]string{ - strconv.FormatInt(int64(ocbinds.OpenconfigAcl_ACL_TYPE_ACL_IPV4), 10): SONIC_ACL_TYPE_IPV4, - strconv.FormatInt(int64(ocbinds.OpenconfigAcl_ACL_TYPE_ACL_IPV6), 10): SONIC_ACL_TYPE_IPV6, - strconv.FormatInt(int64(ocbinds.OpenconfigAcl_ACL_TYPE_ACL_L2), 10): SONIC_ACL_TYPE_L2, + strconv.FormatInt(int64(ocbinds.OpenconfigAcl_ACL_TYPE_ACL_IPV4), 10): SONIC_ACL_TYPE_IPV4, + strconv.FormatInt(int64(ocbinds.OpenconfigAcl_ACL_TYPE_ACL_IPV6), 10): SONIC_ACL_TYPE_IPV6, + strconv.FormatInt(int64(ocbinds.OpenconfigAcl_ACL_TYPE_ACL_L2), 10): SONIC_ACL_TYPE_L2, } -var IP_PROTOCOL_MAP = map[ocbinds.E_OpenconfigPacketMatchTypes_IP_PROTOCOL]uint8{ - ocbinds.OpenconfigPacketMatchTypes_IP_PROTOCOL_IP_ICMP: 1, - ocbinds.OpenconfigPacketMatchTypes_IP_PROTOCOL_IP_IGMP: 2, - ocbinds.OpenconfigPacketMatchTypes_IP_PROTOCOL_IP_TCP: 6, - ocbinds.OpenconfigPacketMatchTypes_IP_PROTOCOL_IP_UDP: 17, - ocbinds.OpenconfigPacketMatchTypes_IP_PROTOCOL_IP_RSVP: 46, - ocbinds.OpenconfigPacketMatchTypes_IP_PROTOCOL_IP_GRE: 47, - ocbinds.OpenconfigPacketMatchTypes_IP_PROTOCOL_IP_AUTH: 51, - ocbinds.OpenconfigPacketMatchTypes_IP_PROTOCOL_IP_PIM: 103, - ocbinds.OpenconfigPacketMatchTypes_IP_PROTOCOL_IP_L2TP: 115, +/* E_OpenconfigPacketMatchTypes_IP_PROTOCOL */ +var IP_PROTOCOL_MAP = map[string]string{ + strconv.FormatInt(int64(ocbinds.OpenconfigPacketMatchTypes_IP_PROTOCOL_IP_ICMP), 10): "1", + strconv.FormatInt(int64(ocbinds.OpenconfigPacketMatchTypes_IP_PROTOCOL_IP_IGMP), 10): "2", + strconv.FormatInt(int64(ocbinds.OpenconfigPacketMatchTypes_IP_PROTOCOL_IP_TCP), 10): "6", + strconv.FormatInt(int64(ocbinds.OpenconfigPacketMatchTypes_IP_PROTOCOL_IP_UDP), 10): "17", + strconv.FormatInt(int64(ocbinds.OpenconfigPacketMatchTypes_IP_PROTOCOL_IP_RSVP), 10): "46", + strconv.FormatInt(int64(ocbinds.OpenconfigPacketMatchTypes_IP_PROTOCOL_IP_GRE), 10): "47", + strconv.FormatInt(int64(ocbinds.OpenconfigPacketMatchTypes_IP_PROTOCOL_IP_AUTH), 10): "51", + strconv.FormatInt(int64(ocbinds.OpenconfigPacketMatchTypes_IP_PROTOCOL_IP_PIM), 10): "103", + strconv.FormatInt(int64(ocbinds.OpenconfigPacketMatchTypes_IP_PROTOCOL_IP_L2TP), 10): "115", } var ETHERTYPE_MAP = map[ocbinds.E_OpenconfigPacketMatchTypes_ETHERTYPE]uint32{ - ocbinds.OpenconfigPacketMatchTypes_ETHERTYPE_ETHERTYPE_LLDP: 0x88CC, - ocbinds.OpenconfigPacketMatchTypes_ETHERTYPE_ETHERTYPE_VLAN: 0x8100, - ocbinds.OpenconfigPacketMatchTypes_ETHERTYPE_ETHERTYPE_ROCE: 0x8915, - ocbinds.OpenconfigPacketMatchTypes_ETHERTYPE_ETHERTYPE_ARP: 0x0806, - ocbinds.OpenconfigPacketMatchTypes_ETHERTYPE_ETHERTYPE_IPV4: 0x0800, - ocbinds.OpenconfigPacketMatchTypes_ETHERTYPE_ETHERTYPE_IPV6: 0x86DD, - ocbinds.OpenconfigPacketMatchTypes_ETHERTYPE_ETHERTYPE_MPLS: 0x8847, + ocbinds.OpenconfigPacketMatchTypes_ETHERTYPE_ETHERTYPE_LLDP: 0x88CC, + ocbinds.OpenconfigPacketMatchTypes_ETHERTYPE_ETHERTYPE_VLAN: 0x8100, + ocbinds.OpenconfigPacketMatchTypes_ETHERTYPE_ETHERTYPE_ROCE: 0x8915, + ocbinds.OpenconfigPacketMatchTypes_ETHERTYPE_ETHERTYPE_ARP: 0x0806, + ocbinds.OpenconfigPacketMatchTypes_ETHERTYPE_ETHERTYPE_IPV4: 0x0800, + ocbinds.OpenconfigPacketMatchTypes_ETHERTYPE_ETHERTYPE_IPV6: 0x86DD, + ocbinds.OpenconfigPacketMatchTypes_ETHERTYPE_ETHERTYPE_MPLS: 0x8847, } - -func getAclRoot (s *ygot.GoStruct) *ocbinds.OpenconfigAcl_Acl { - deviceObj := (*s).(*ocbinds.Device) - return deviceObj.Acl +func getAclRoot(s *ygot.GoStruct) *ocbinds.OpenconfigAcl_Acl { + deviceObj := (*s).(*ocbinds.Device) + return deviceObj.Acl } - func getAclTypeOCEnumFromName(val string) (ocbinds.E_OpenconfigAcl_ACL_TYPE, error) { - switch val { - case "ACL_IPV4", "openconfig-acl:ACL_IPV4": - return ocbinds.OpenconfigAcl_ACL_TYPE_ACL_IPV4, nil - case "ACL_IPV6", "openconfig-acl:ACL_IPV6": - return ocbinds.OpenconfigAcl_ACL_TYPE_ACL_IPV6, nil - case "ACL_L2", "openconfig-acl:ACL_L2": - return ocbinds.OpenconfigAcl_ACL_TYPE_ACL_L2, nil - default: - return ocbinds.OpenconfigAcl_ACL_TYPE_UNSET, - tlerr.NotSupported("ACL Type '%s' not supported", val) - } + switch val { + case "ACL_IPV4", "openconfig-acl:ACL_IPV4": + return ocbinds.OpenconfigAcl_ACL_TYPE_ACL_IPV4, nil + case "ACL_IPV6", "openconfig-acl:ACL_IPV6": + return ocbinds.OpenconfigAcl_ACL_TYPE_ACL_IPV6, nil + case "ACL_L2", "openconfig-acl:ACL_L2": + return ocbinds.OpenconfigAcl_ACL_TYPE_ACL_L2, nil + default: + return ocbinds.OpenconfigAcl_ACL_TYPE_UNSET, + tlerr.NotSupported("ACL Type '%s' not supported", val) + } } func getAclKeyStrFromOCKey(aclname string, acltype ocbinds.E_OpenconfigAcl_ACL_TYPE) string { - aclN := strings.Replace(strings.Replace(aclname, " ", "_", -1), "-", "_", -1) - aclT := acltype.ΛMap()["E_OpenconfigAcl_ACL_TYPE"][int64(acltype)].Name - return aclN + "_" + aclT + aclN := strings.Replace(strings.Replace(aclname, " ", "_", -1), "-", "_", -1) + aclT := acltype.ΛMap()["E_OpenconfigAcl_ACL_TYPE"][int64(acltype)].Name + return aclN + "_" + aclT } func getOCAclKeysFromStrDBKey(aclKey string) (string, ocbinds.E_OpenconfigAcl_ACL_TYPE) { - var aclOrigName string - var aclOrigType ocbinds.E_OpenconfigAcl_ACL_TYPE - - if strings.Contains(aclKey, "_"+OPENCONFIG_ACL_TYPE_IPV4) { - aclOrigName = strings.Replace(aclKey, "_"+OPENCONFIG_ACL_TYPE_IPV4, "", 1) - aclOrigType = ocbinds.OpenconfigAcl_ACL_TYPE_ACL_IPV4 - } else if strings.Contains(aclKey, "_"+OPENCONFIG_ACL_TYPE_IPV6) { - aclOrigName = strings.Replace(aclKey, "_"+OPENCONFIG_ACL_TYPE_IPV6, "", 1) - aclOrigType = ocbinds.OpenconfigAcl_ACL_TYPE_ACL_IPV6 - } else if strings.Contains(aclKey, "_"+OPENCONFIG_ACL_TYPE_L2) { - aclOrigName = strings.Replace(aclKey, "_"+OPENCONFIG_ACL_TYPE_L2, "", 1) - aclOrigType = ocbinds.OpenconfigAcl_ACL_TYPE_ACL_L2 - } - - return aclOrigName, aclOrigType -} + var aclOrigName string + var aclOrigType ocbinds.E_OpenconfigAcl_ACL_TYPE -func getIpProtocol(proto int64) interface{} { - for k, v := range IP_PROTOCOL_MAP { - if uint8(proto) == v { - return k - } - } - return uint8(proto) -} + if strings.Contains(aclKey, "_"+OPENCONFIG_ACL_TYPE_IPV4) { + aclOrigName = strings.Replace(aclKey, "_"+OPENCONFIG_ACL_TYPE_IPV4, "", 1) + aclOrigType = ocbinds.OpenconfigAcl_ACL_TYPE_ACL_IPV4 + } else if strings.Contains(aclKey, "_"+OPENCONFIG_ACL_TYPE_IPV6) { + aclOrigName = strings.Replace(aclKey, "_"+OPENCONFIG_ACL_TYPE_IPV6, "", 1) + aclOrigType = ocbinds.OpenconfigAcl_ACL_TYPE_ACL_IPV6 + } else if strings.Contains(aclKey, "_"+OPENCONFIG_ACL_TYPE_L2) { + aclOrigName = strings.Replace(aclKey, "_"+OPENCONFIG_ACL_TYPE_L2, "", 1) + aclOrigType = ocbinds.OpenconfigAcl_ACL_TYPE_ACL_L2 + } -func getTransportSrcDestPorts(portVal string, portType string) interface{} { - var portRange string = "" - - portNum, err := strconv.Atoi(portVal) - if err != nil && strings.Contains(portVal, "-") { - portRange = portVal - } - - if len(portRange) > 0 { - return portRange - } else if portNum > 0 { - return uint16(portNum) - } else { - if "src" == portType { - return ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort_ANY - } else if "dest" == portType { - return ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort_ANY - } - } - return nil + return aclOrigName, aclOrigType } func getTransportConfigTcpFlags(tcpFlags string) []ocbinds.E_OpenconfigPacketMatchTypes_TCP_FLAGS { - var flags []ocbinds.E_OpenconfigPacketMatchTypes_TCP_FLAGS - if len(tcpFlags) > 0 { - flagStr := strings.Split(tcpFlags, "/")[0] - flagNumber, _ := strconv.ParseUint(strings.Replace(flagStr, "0x", "", -1), 16, 32) - for i := 0; i < 8; i++ { - mask := 1 << uint(i) - if (int(flagNumber) & mask) > 0 { - switch int(flagNumber) & mask { - case 0x01: - flags = append(flags, ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_FIN) - case 0x02: - flags = append(flags, ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_SYN) - case 0x04: - flags = append(flags, ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_RST) - case 0x08: - flags = append(flags, ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_PSH) - case 0x10: - flags = append(flags, ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_ACK) - case 0x20: - flags = append(flags, ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_URG) - case 0x40: - flags = append(flags, ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_ECE) - case 0x80: - flags = append(flags, ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_CWR) - default: - } - } - } - } - return flags + var flags []ocbinds.E_OpenconfigPacketMatchTypes_TCP_FLAGS + if len(tcpFlags) > 0 { + flagStr := strings.Split(tcpFlags, "/")[0] + flagNumber, _ := strconv.ParseUint(strings.Replace(flagStr, "0x", "", -1), 16, 32) + for i := 0; i < 8; i++ { + mask := 1 << uint(i) + if (int(flagNumber) & mask) > 0 { + switch int(flagNumber) & mask { + case 0x01: + flags = append(flags, ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_FIN) + case 0x02: + flags = append(flags, ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_SYN) + case 0x04: + flags = append(flags, ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_RST) + case 0x08: + flags = append(flags, ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_PSH) + case 0x10: + flags = append(flags, ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_ACK) + case 0x20: + flags = append(flags, ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_URG) + case 0x40: + flags = append(flags, ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_ECE) + case 0x80: + flags = append(flags, ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_CWR) + default: + } + } + } + } + return flags } func getL2EtherType(etherType uint64) interface{} { - for k, v := range ETHERTYPE_MAP { - if uint32(etherType) == v { - return k - } - } - return uint16(etherType) + for k, v := range ETHERTYPE_MAP { + if uint32(etherType) == v { + return k + } + } + return uint16(etherType) } //////////////////////////////////////////// // Bi-directoonal overloaded methods //////////////////////////////////////////// -var YangToDb_acl_type_field_xfmr FieldXfmrYangToDb = func (inParams XfmrParams) (map[string]string, error) { - res_map := make(map[string]string) - var err error - - acltype, _ := inParams.param.(ocbinds.E_OpenconfigAcl_ACL_TYPE) - log.Info("YangToDb_acl_type_field_xfmr: ", inParams.ygRoot, " Xpath: ", inParams.uri, " acltype: ", acltype) - res_map[ACL_TYPE] = findInMap(ACL_TYPE_MAP, strconv.FormatInt(int64(acltype), 10)) - return res_map, err -} -var DbToYang_acl_type_field_xfmr FieldXfmrDbtoYang = func (inParams XfmrParams) (map[string]interface{}, error) { - var err error - result := make(map[string]interface{}) - data:= (*inParams.dbDataMap)[inParams.curDb] - log.Info("DbToYang_acl_type_field_xfmr", data, inParams.ygRoot) - oc_acltype := findInMap(ACL_TYPE_MAP, data[ACL_TABLE][inParams.key].Field[ACL_TYPE]) - n, err := strconv.ParseInt(oc_acltype, 10, 64) - result[ACL_TYPE] = n - return result, err -} - -var YangToDb_acl_set_name_xfmr FieldXfmrYangToDb = func (inParams XfmrParams) (map[string]string, error) { - res_map := make(map[string]string) - var err error - log.Info("YangToDb_acl_set_name_xfmr: ") - /*no-op since there is no redis table field to be filled corresponding to name attribute since its part of key */ - return res_map, err -} - -var DbToYang_acl_set_name_xfmr FieldXfmrDbtoYang = func (inParams XfmrParams) (map[string]interface{}, error) { - res_map := make(map[string]interface{}) - var err error - log.Info("DbToYang_acl_set_name_xfmr: ", inParams.key) - /*name attribute corresponds to key in redis table*/ - aclName, _ := getOCAclKeysFromStrDBKey(inParams.key) - res_map["name"] = aclName - log.Info("acl-set/config/name ", res_map) - return res_map, err -} - -var YangToDb_acl_entry_key_xfmr KeyXfmrYangToDb = func (inParams XfmrParams) (string, error) { - var entry_key string - var err error - var oc_aclType ocbinds.E_OpenconfigAcl_ACL_TYPE - log.Info("YangToDb_acl_entry_key_xfmr: ", inParams.ygRoot, inParams.uri) - pathInfo := NewPathInfo(inParams.uri) - - if len(pathInfo.Vars) < 3 { - err = errors.New("Invalid xpath, key attributes not found") - return entry_key, err - } - - oc_aclType, err = getAclTypeOCEnumFromName(pathInfo.Var("type")) - if err != nil { - err = errors.New("OC Acl type name to OC Acl Enum failed") - return entry_key, err - } - - aclkey := getAclKeyStrFromOCKey(pathInfo.Var("name"), oc_aclType) - var rulekey string - if strings.Contains(pathInfo.Template, "/acl-entry{sequence-id}") { - rulekey = "RULE_" + pathInfo.Var("sequence-id") - } - entry_key = aclkey + "|" + rulekey - - log.Info("YangToDb_acl_entry_key_xfmr - entry_key : ", entry_key) - - return entry_key, err -} - -var DbToYang_acl_entry_key_xfmr KeyXfmrDbToYang = func (inParams XfmrParams) (map[string]interface{}, error) { - rmap := make(map[string]interface{}) - var err error - entry_key := inParams.key - log.Info("DbToYang_acl_entry_key_xfmr: ", entry_key) - - key := strings.Split(entry_key, "|") - if len(key) < 2 { - err = errors.New("Invalid key for acl entries.") - log.Info("Invalid Keys for acl enmtries", entry_key) - return rmap, err - } - - dbAclRule := key[1] - seqId := strings.Replace(dbAclRule, "RULE_", "", 1) - rmap["sequence-id"], _ = strconv.ParseFloat(seqId, 64) - return rmap, err +var YangToDb_acl_type_field_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { + res_map := make(map[string]string) + var err error + + acltype, _ := inParams.param.(ocbinds.E_OpenconfigAcl_ACL_TYPE) + log.Info("YangToDb_acl_type_field_xfmr: ", inParams.ygRoot, " Xpath: ", inParams.uri, " acltype: ", acltype) + res_map[ACL_TYPE] = findInMap(ACL_TYPE_MAP, strconv.FormatInt(int64(acltype), 10)) + return res_map, err +} +var DbToYang_acl_type_field_xfmr FieldXfmrDbtoYang = func(inParams XfmrParams) (map[string]interface{}, error) { + var err error + result := make(map[string]interface{}) + data := (*inParams.dbDataMap)[inParams.curDb] + log.Info("DbToYang_acl_type_field_xfmr", data, inParams.ygRoot) + oc_acltype := findInMap(ACL_TYPE_MAP, data[ACL_TABLE][inParams.key].Field[ACL_TYPE]) + n, err := strconv.ParseInt(oc_acltype, 10, 64) + result[ACL_TYPE] = ocbinds.E_OpenconfigAcl_ACL_TYPE(n).ΛMap()["E_OpenconfigAcl_ACL_TYPE"][n].Name + return result, err +} + +var YangToDb_acl_set_name_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { + res_map := make(map[string]string) + var err error + log.Info("YangToDb_acl_set_name_xfmr: ") + /*no-op since there is no redis table field to be filled corresponding to name attribute since its part of key */ + return res_map, err +} + +var DbToYang_acl_set_name_xfmr FieldXfmrDbtoYang = func(inParams XfmrParams) (map[string]interface{}, error) { + res_map := make(map[string]interface{}) + var err error + log.Info("DbToYang_acl_set_name_xfmr: ", inParams.key) + /*name attribute corresponds to key in redis table*/ + aclName, _ := getOCAclKeysFromStrDBKey(inParams.key) + res_map["name"] = aclName + log.Info("acl-set/config/name ", res_map) + return res_map, err +} + +var YangToDb_acl_entry_key_xfmr KeyXfmrYangToDb = func(inParams XfmrParams) (string, error) { + var entry_key string + var err error + var oc_aclType ocbinds.E_OpenconfigAcl_ACL_TYPE + log.Info("YangToDb_acl_entry_key_xfmr: ", inParams.ygRoot, inParams.uri) + pathInfo := NewPathInfo(inParams.uri) + + if len(pathInfo.Vars) < 3 { + err = errors.New("Invalid xpath, key attributes not found") + return entry_key, err + } + + oc_aclType, err = getAclTypeOCEnumFromName(pathInfo.Var("type")) + if err != nil { + err = errors.New("OC Acl type name to OC Acl Enum failed") + return entry_key, err + } + + aclkey := getAclKeyStrFromOCKey(pathInfo.Var("name"), oc_aclType) + var rulekey string + if strings.Contains(pathInfo.Template, "/acl-entry{sequence-id}") { + rulekey = "RULE_" + pathInfo.Var("sequence-id") + } + entry_key = aclkey + "|" + rulekey + + log.Info("YangToDb_acl_entry_key_xfmr - entry_key : ", entry_key) + + return entry_key, err +} + +var DbToYang_acl_entry_key_xfmr KeyXfmrDbToYang = func(inParams XfmrParams) (map[string]interface{}, error) { + rmap := make(map[string]interface{}) + var err error + entry_key := inParams.key + log.Info("DbToYang_acl_entry_key_xfmr: ", entry_key) + + key := strings.Split(entry_key, "|") + if len(key) < 2 { + err = errors.New("Invalid key for acl entries.") + log.Info("Invalid Keys for acl enmtries", entry_key) + return rmap, err + } + + dbAclRule := key[1] + seqId := strings.Replace(dbAclRule, "RULE_", "", 1) + rmap["sequence-id"], _ = strconv.ParseFloat(seqId, 64) + return rmap, err +} + +var YangToDb_acl_entry_sequenceid_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { + res_map := make(map[string]string) + var err error + log.Info("YangToDb_acl_entry_sequenceid_xfmr: ") + /*no-op since there is no redis table field to be filled corresponding to sequenec-id attribute since its part of key */ + return res_map, err +} + +var DbToYang_acl_entry_sequenceid_xfmr FieldXfmrDbtoYang = func(inParams XfmrParams) (map[string]interface{}, error) { + res_map := make(map[string]interface{}) + var err error + log.Info("DbToYang_acl_entry_sequenceid_xfmr: ", inParams.key) + /*sequenec-id attribute corresponds to key in redis table*/ + res, err := DbToYang_acl_entry_key_xfmr(inParams) + log.Info("acl-entry/config/sequence-id ", res) + if err != nil { + return res_map, err + } + if seqId, ok := res["sequence-id"]; !ok { + log.Error("sequence-id not found in acl entry") + return res_map, err + } else { + res_map["sequence-id"] = seqId + } + return res_map, err +} + +var YangToDb_acl_l2_ethertype_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { + res_map := make(map[string]string) + var err error + + ethertypeType := reflect.TypeOf(inParams.param).Elem() + log.Info("YangToDb_acl_ip_protocol_xfmr: ", inParams.ygRoot, " Xpath: ", inParams.uri, " ethertypeType: ", ethertypeType) + var b bytes.Buffer + switch ethertypeType { + case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_L2_Config_Ethertype_Union_E_OpenconfigPacketMatchTypes_ETHERTYPE{}): + v := (inParams.param).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_L2_Config_Ethertype_Union_E_OpenconfigPacketMatchTypes_ETHERTYPE) + fmt.Fprintf(&b, "0x%0.4x", ETHERTYPE_MAP[v.E_OpenconfigPacketMatchTypes_ETHERTYPE]) + res_map["ETHER_TYPE"] = b.String() + break + case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_L2_Config_Ethertype_Union_Uint16{}): + v := (inParams.param).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_L2_Config_Ethertype_Union_Uint16) + fmt.Fprintf(&b, "0x%0.4x", v.Uint16) + res_map["ETHER_TYPE"] = b.String() + break + } + return res_map, err +} + +var DbToYang_acl_l2_ethertype_xfmr FieldXfmrDbtoYang = func(inParams XfmrParams) (map[string]interface{}, error) { + var err error + result := make(map[string]interface{}) + data := (*inParams.dbDataMap)[inParams.curDb] + log.Info("DbToYang_acl_l2_ethertype_xfmr", data, inParams.ygRoot) + if _, ok := data[RULE_TABLE]; !ok { + err = errors.New("RULE_TABLE entry not found in the input param") + return result, err + } + + ruleTbl := data[RULE_TABLE] + ruleInst := ruleTbl[inParams.key] + etype, ok := ruleInst.Field["ETHER_TYPE"] + + if ok { + etypeVal, _ := strconv.ParseUint(strings.Replace(etype, "0x", "", -1), 16, 32) + result["protocol"] = getL2EtherType(etypeVal) + } else { + err = errors.New("ETHER_TYPE field not found in DB") + } + return result, nil +} + +var YangToDb_acl_ip_protocol_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { + res_map := make(map[string]string) + var err error + + protocolType := reflect.TypeOf(inParams.param).Elem() + log.Info("YangToDb_acl_ip_protocol_xfmr: ", inParams.ygRoot, " Xpath: ", inParams.uri, " protocolType: ", protocolType) + switch protocolType { + case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Ipv4_Config_Protocol_Union_E_OpenconfigPacketMatchTypes_IP_PROTOCOL{}): + v := (inParams.param).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Ipv4_Config_Protocol_Union_E_OpenconfigPacketMatchTypes_IP_PROTOCOL) + res_map["IP_PROTOCOL"] = findInMap(IP_PROTOCOL_MAP, strconv.FormatInt(int64(v.E_OpenconfigPacketMatchTypes_IP_PROTOCOL), 10)) + v = nil + break + case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Ipv4_Config_Protocol_Union_Uint8{}): + v := (inParams.param).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Ipv4_Config_Protocol_Union_Uint8) + res_map["IP_PROTOCOL"] = strconv.FormatInt(int64(v.Uint8), 10) + break + } + return res_map, err +} + +var DbToYang_acl_ip_protocol_xfmr FieldXfmrDbtoYang = func(inParams XfmrParams) (map[string]interface{}, error) { + var err error + result := make(map[string]interface{}) + data := (*inParams.dbDataMap)[inParams.curDb] + log.Info("DbToYang_acl_ip_protocol_xfmr", data, inParams.ygRoot) + oc_protocol := findByValue(IP_PROTOCOL_MAP, data[RULE_TABLE][inParams.key].Field["IP_PROTOCOL"]) + n, err := strconv.ParseInt(oc_protocol, 10, 64) + result["protocol"] = ocbinds.E_OpenconfigPacketMatchTypes_IP_PROTOCOL(n).ΛMap()["E_OpenconfigPacketMatchTypes_IP_PROTOCOL"][n].Name + return result, err +} + +var YangToDb_acl_source_port_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { + res_map := make(map[string]string) + var err error + sourceportType := reflect.TypeOf(inParams.param).Elem() + log.Info("YangToDb_acl_ip_protocol_xfmr: ", inParams.ygRoot, " Xpath: ", inParams.uri, " sourceportType: ", sourceportType) + switch sourceportType { + case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort_Union_E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort{}): + v := (inParams.param).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort_Union_E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort) + res_map["L4_SRC_PORT"] = v.E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort.ΛMap()["E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort"][int64(v.E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort)].Name + break + case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort_Union_String{}): + v := (inParams.param).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort_Union_String) + res_map["L4_SRC_PORT_RANGE"] = strings.Replace(v.String, "..", "-", 1) + break + case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort_Union_Uint16{}): + v := (inParams.param).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort_Union_Uint16) + res_map["L4_SRC_PORT"] = strconv.FormatInt(int64(v.Uint16), 10) + break + } + + return res_map, err +} + +var DbToYang_acl_source_port_xfmr FieldXfmrDbtoYang = func(inParams XfmrParams) (map[string]interface{}, error) { + var err error + data := (*inParams.dbDataMap)[inParams.curDb] + log.Info("DbToYang_acl_source_port_xfmr: ", data, inParams.ygRoot) + result := make(map[string]interface{}) + if _, ok := data[RULE_TABLE]; !ok { + err = errors.New("RULE_TABLE entry not found in the input param") + return result, err + } + ruleTbl := data[RULE_TABLE] + ruleInst := ruleTbl[inParams.key] + port, ok := ruleInst.Field["L4_SRC_PORT"] + if ok { + result["source-port"] = port + return result, nil + } + + portRange, ok := ruleInst.Field["L4_SRC_PORT_RANGE"] + if ok { + result["source-port"] = portRange + return result, nil + } else { + err = errors.New("PORT/PORT_RANGE field not found in DB") + } + return result, err +} + +var YangToDb_acl_destination_port_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { + res_map := make(map[string]string) + var err error + destportType := reflect.TypeOf(inParams.param).Elem() + log.Info("YangToDb_acl_ip_protocol_xfmr: ", inParams.ygRoot, " Xpath: ", inParams.uri, " destportType: ", destportType) + switch destportType { + case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort_Union_E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort{}): + v := (inParams.param).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort_Union_E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort) + res_map["L4_DST_PORT"] = v.E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort.ΛMap()["E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort"][int64(v.E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort)].Name + break + case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort_Union_String{}): + v := (inParams.param).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort_Union_String) + res_map["L4_DST_PORT_RANGE"] = strings.Replace(v.String, "..", "-", 1) + break + case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort_Union_Uint16{}): + v := (inParams.param).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort_Union_Uint16) + res_map["L4_DST_PORT"] = strconv.FormatInt(int64(v.Uint16), 10) + break + } + return res_map, err +} + +var DbToYang_acl_destination_port_xfmr FieldXfmrDbtoYang = func(inParams XfmrParams) (map[string]interface{}, error) { + var err error + data := (*inParams.dbDataMap)[inParams.curDb] + log.Info("DbToYang_acl_destination_port_xfmr: ", data, inParams.ygRoot) + result := make(map[string]interface{}) + if _, ok := data[RULE_TABLE]; !ok { + err = errors.New("RULE_TABLE entry not found in the input param") + return result, err + } + ruleTbl := data[RULE_TABLE] + ruleInst := ruleTbl[inParams.key] + port, ok := ruleInst.Field["L4_DST_PORT"] + if ok { + result["destination-port"] = port + return result, nil + } + + portRange, ok := ruleInst.Field["L4_DST_PORT_RANGE"] + if ok { + result["destination-port"] = portRange + return result, nil + } else { + err = errors.New("DST PORT/PORT_RANGE field not found in DB") + } + return result, err +} + +var YangToDb_acl_tcp_flags_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { + res_map := make(map[string]string) + var err error + log.Info("YangToDb_acl_tcp_flags_xfmr: ", inParams.ygRoot, inParams.uri) + var tcpFlags uint32 = 0x00 + v := reflect.ValueOf(inParams.param) + + flags := v.Interface().([]ocbinds.E_OpenconfigPacketMatchTypes_TCP_FLAGS) + for _, flag := range flags { + fmt.Println("TCP Flag name: " + flag.ΛMap()["E_OpenconfigPacketMatchTypes_TCP_FLAGS"][int64(flag)].Name) + switch flag { + case ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_FIN: + tcpFlags |= 0x01 + break + case ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_SYN: + tcpFlags |= 0x02 + break + case ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_RST: + tcpFlags |= 0x04 + break + case ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_PSH: + tcpFlags |= 0x08 + break + case ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_ACK: + tcpFlags |= 0x10 + break + case ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_URG: + tcpFlags |= 0x20 + break + case ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_ECE: + tcpFlags |= 0x40 + break + case ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_CWR: + tcpFlags |= 0x80 + break + } + } + var b bytes.Buffer + fmt.Fprintf(&b, "0x%0.2x/0x%0.2x", tcpFlags, tcpFlags) + res_map["TCP_FLAGS"] = b.String() + return res_map, err +} + +var DbToYang_acl_tcp_flags_xfmr FieldXfmrDbtoYang = func(inParams XfmrParams) (map[string]interface{}, error) { + var err error + data := (*inParams.dbDataMap)[inParams.curDb] + log.Info("DbToYang_acl_tcp_flags_xfmr: ", data, inParams.ygRoot) + result := make(map[string]interface{}) + if _, ok := data[RULE_TABLE]; !ok { + err = errors.New("RULE_TABLE entry not found in the input param") + return result, err + } + ruleTbl := data[RULE_TABLE] + ruleInst := ruleTbl[inParams.key] + tcpFlag, ok := ruleInst.Field["TCP_FLAGS"] + if ok { + result["tcp-flags"] = getTransportConfigTcpFlags(tcpFlag) + return result, nil + } + return result, nil +} + +var YangToDb_acl_port_bindings_xfmr SubTreeXfmrYangToDb = func(inParams XfmrParams) (map[string]map[string]db.Value, error) { + var err error + res_map := make(map[string]map[string]db.Value) + aclTableMap := make(map[string]db.Value) + log.Info("YangToDb_acl_port_bindings_xfmr: ", inParams.ygRoot, inParams.uri) + + aclObj := getAclRoot(inParams.ygRoot) + if aclObj.Interfaces == nil { + return res_map, err + } + //aclset := &ocbinds.OpenconfigAcl_Acl_AclSets_AclSet{} + aclInterfacesMap := make(map[string][]string) + for intfId, _ := range aclObj.Interfaces.Interface { + intf := aclObj.Interfaces.Interface[intfId] + if intf != nil { + if intf.IngressAclSets != nil && len(intf.IngressAclSets.IngressAclSet) > 0 { + for inAclKey, _ := range intf.IngressAclSets.IngressAclSet { + aclName := getAclKeyStrFromOCKey(inAclKey.SetName, inAclKey.Type) + aclInterfacesMap[aclName] = append(aclInterfacesMap[aclName], *intf.Id) + _, ok := aclTableMap[aclName] + if !ok { + aclTableMap[aclName] = db.Value{Field: make(map[string]string)} + } + aclTableMap[aclName].Field["stage"] = "INGRESS" + } + } + if intf.EgressAclSets != nil && len(intf.EgressAclSets.EgressAclSet) > 0 { + for outAclKey, _ := range intf.EgressAclSets.EgressAclSet { + aclName := getAclKeyStrFromOCKey(outAclKey.SetName, outAclKey.Type) + aclInterfacesMap[aclName] = append(aclInterfacesMap[aclName], *intf.Id) + _, ok := aclTableMap[aclName] + if !ok { + aclTableMap[aclName] = db.Value{Field: make(map[string]string)} + } + aclTableMap[aclName].Field["stage"] = "EGRESS" + } + } + } + } + for k, _ := range aclInterfacesMap { + val := aclTableMap[k] + (&val).SetList("ports", aclInterfacesMap[k]) + } + res_map[ACL_TABLE] = aclTableMap + return res_map, err +} + +var DbToYang_acl_port_bindings_xfmr SubTreeXfmrDbToYang = func(inParams XfmrParams) error { + var err error + data := (*inParams.dbDataMap)[inParams.curDb] + log.Info("DbToYang_acl_port_bindings_xfmr: ", data, inParams.ygRoot) + + aclTbl := data["ACL_TABLE"] + var ruleTbl map[string]map[string]db.Value + + // repoluate to use existing code + ruleTbl = make(map[string]map[string]db.Value) + for key, element := range data["ACL_RULE"] { + // split into aclKey and ruleKey + tokens := strings.Split(key, "|") + if ruleTbl[tokens[0]] == nil { + ruleTbl[tokens[0]] = make(map[string]db.Value) + } + ruleTbl[tokens[0]][tokens[1]] = db.Value{Field: make(map[string]string)} + ruleTbl[tokens[0]][tokens[1]] = element + } + + pathInfo := NewPathInfo(inParams.uri) + + acl := getAclRoot(inParams.ygRoot) + targetUriPath, _ := getYangPathFromUri(pathInfo.Path) + if isSubtreeRequest(pathInfo.Template, "/openconfig-acl:acl/interfaces/interface{}") { + for intfId := range acl.Interfaces.Interface { + intfData := acl.Interfaces.Interface[intfId] + ygot.BuildEmptyTree(intfData) + if isSubtreeRequest(targetUriPath, "/openconfig-acl:acl/interfaces/interface/ingress-acl-sets") { + err = getAclBindingInfoForInterfaceData(aclTbl, ruleTbl, intfData, intfId, "INGRESS") + } else if isSubtreeRequest(targetUriPath, "/openconfig-acl:acl/interfaces/interface/egress-acl-sets") { + err = getAclBindingInfoForInterfaceData(aclTbl, ruleTbl, intfData, intfId, "EGRESS") + } else { + err = getAclBindingInfoForInterfaceData(aclTbl, ruleTbl, intfData, intfId, "INGRESS") + if err != nil { + return err + } + err = getAclBindingInfoForInterfaceData(aclTbl, ruleTbl, intfData, intfId, "EGRESS") + } + } + } else { + err = getAllBindingsInfo(aclTbl, ruleTbl, inParams.ygRoot) + } + + return err } -var YangToDb_acl_entry_sequenceid_xfmr FieldXfmrYangToDb = func (inParams XfmrParams) (map[string]string, error) { - res_map := make(map[string]string) - var err error - log.Info("YangToDb_acl_entry_sequenceid_xfmr: ") - /*no-op since there is no redis table field to be filled corresponding to sequenec-id attribute since its part of key */ - return res_map, err -} - -var DbToYang_acl_entry_sequenceid_xfmr FieldXfmrDbtoYang = func (inParams XfmrParams) (map[string]interface{}, error) { - res_map := make(map[string]interface{}) - var err error - log.Info("DbToYang_acl_entry_sequenceid_xfmr: ", inParams.key) - /*sequenec-id attribute corresponds to key in redis table*/ - res, err := DbToYang_acl_entry_key_xfmr(inParams) - log.Info("acl-entry/config/sequence-id ", res) - if err != nil { - return res_map, err - } - if seqId, ok := res["sequence-id"]; !ok { - log.Error("sequence-id not found in acl entry") - return res_map, err - } else { - res_map["sequence-id"] = seqId - } - return res_map, err -} - -var YangToDb_acl_l2_ethertype_xfmr FieldXfmrYangToDb = func (inParams XfmrParams) (map[string]string, error) { - res_map := make(map[string]string) - var err error - - ethertypeType := reflect.TypeOf(inParams.param).Elem() - log.Info("YangToDb_acl_ip_protocol_xfmr: ", inParams.ygRoot, " Xpath: ", inParams.uri, " ethertypeType: ", ethertypeType) - var b bytes.Buffer - switch ethertypeType { - case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_L2_Config_Ethertype_Union_E_OpenconfigPacketMatchTypes_ETHERTYPE{}): - v := (inParams.param).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_L2_Config_Ethertype_Union_E_OpenconfigPacketMatchTypes_ETHERTYPE) - fmt.Fprintf(&b, "0x%0.4x", ETHERTYPE_MAP[v.E_OpenconfigPacketMatchTypes_ETHERTYPE]) - res_map["ETHER_TYPE"] = b.String() - break - case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_L2_Config_Ethertype_Union_Uint16{}): - v := (inParams.param).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_L2_Config_Ethertype_Union_Uint16) - fmt.Fprintf(&b, "0x%0.4x", v.Uint16) - res_map["ETHER_TYPE"] = b.String() - break - } - return res_map, err -} - -var DbToYang_acl_l2_ethertype_xfmr FieldXfmrDbtoYang = func (inParams XfmrParams) (map[string]interface{}, error) { - var err error - result := make(map[string]interface{}) - data:= (*inParams.dbDataMap)[inParams.curDb] - log.Info("DbToYang_acl_l2_ethertype_xfmr", data, inParams.ygRoot) - if _, ok := data[RULE_TABLE]; !ok { - err = errors.New("RULE_TABLE entry not found in the input param") - return result, err - } - - ruleTbl := data[RULE_TABLE] - ruleInst := ruleTbl[inParams.key] - etype, ok := ruleInst.Field["ETHER_TYPE"] - - if ok { - etypeVal, _ := strconv.ParseUint(strings.Replace(etype, "0x", "", -1), 16, 32) - result["protocol"] = getL2EtherType(etypeVal) - } else { - err = errors.New("ETHER_TYPE field not found in DB") - } - return result, nil - - /* - if _, ok := data[RULE_TABLE]; !ok { - err = errors.New("RULE_TABLE entry not found in the input param") - return err - } - ruleTbl := data[RULE_TABLE] - - for aclRuleKey := range ruleTbl { - ruleData := ruleTbl[aclRuleKey] - var entrySet *ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry - entrySet, err = getAclSetEntry(aclRuleKey, ygRoot) - if err != nil { - log.Info("getAclSetEntry failed for :", aclRuleKey) - continue // If its not map doesnt need to loop just return from here. - } - ruleKey := "ETHER_TYPE" - if !ruleData.Has(ruleKey) { - log.Info("No entry found for the field ", ruleKey) - err = errors.New("ETHER_TYPE field not found in DB") - continue - } - ethType, _ := strconv.ParseUint(strings.Replace(ruleData.Get(ruleKey), "0x", "", -1), 16, 32) - ethertype := getL2EtherType(ethType) - entrySet.L2.Config.Ethertype, _ = entrySet.L2.Config.To_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_L2_Config_Ethertype_Union(ethertype) - entrySet.L2.State.Ethertype, _ = entrySet.L2.State.To_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_L2_State_Ethertype_Union(ethertype) - - } - return err - */ -} - -var YangToDb_acl_ip_protocol_xfmr FieldXfmrYangToDb = func (inParams XfmrParams) (map[string]string, error) { - res_map := make(map[string]string) - var err error - - protocolType := reflect.TypeOf(inParams.param).Elem() - log.Info("YangToDb_acl_ip_protocol_xfmr: ", inParams.ygRoot, " Xpath: ", inParams.uri, " protocolType: ", protocolType) - switch (protocolType) { - case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Ipv4_Config_Protocol_Union_E_OpenconfigPacketMatchTypes_IP_PROTOCOL{}): - v := (inParams.param).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Ipv4_Config_Protocol_Union_E_OpenconfigPacketMatchTypes_IP_PROTOCOL) - res_map["IP_PROTOCOL"] = strconv.FormatInt(int64(IP_PROTOCOL_MAP[v.E_OpenconfigPacketMatchTypes_IP_PROTOCOL]), 10) - break - case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Ipv4_Config_Protocol_Union_Uint8{}): - v := (inParams.param).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Ipv4_Config_Protocol_Union_Uint8) - res_map["IP_PROTOCOL"] = strconv.FormatInt(int64(v.Uint8), 10) - break - } - return res_map, err -} - -var DbToYang_acl_ip_protocol_xfmr FieldXfmrDbtoYang = func (inParams XfmrParams) (map[string]interface{}, error) { - var err error - result := make(map[string]interface{}) - data:= (*inParams.dbDataMap)[inParams.curDb] - log.Info("DbToYang_acl_ip_protocol_xfmr ", data, inParams.ygRoot) - if _, ok := data[RULE_TABLE]; !ok { - err = errors.New("RULE_TABLE entry not found in the input param") - return result, err - } - - ruleTbl := data[RULE_TABLE] - ruleInst := ruleTbl[inParams.key] - prot, ok := ruleInst.Field["IP_PROTOCOL"] - - if ok { - ipProto, _ := strconv.ParseInt(prot, 10, 64) - result["protocol"] = getIpProtocol(ipProto) - } else { - err = errors.New("IP_PROTOCOL field not found in DB") - } - return result, err - - /* - for aclRuleKey := range ruleTbl { - ruleData := ruleTbl[aclRuleKey] - var entrySet *ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry - entrySet, err = getAclSetEntry(aclRuleKey, ygRoot) - if err != nil { - log.Info("getAclSetEntry failed for :", aclRuleKey) - continue // If its not map doesnt need to loop just return from here. - } - ruleKey := "IP_PROTOCOL" - if !ruleData.Has(ruleKey) { - log.Info("No entry found for the field ", ruleKey) - err = errors.New("IP_PROTOCOL field not found in DB") - continue - } - - ipProto, _ := strconv.ParseInt(ruleData.Get(ruleKey), 10, 64) - protocolVal := getIpProtocol(ipProto) - entrySet.Ipv6.Config.Protocol, _ = entrySet.Ipv6.Config.To_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Ipv6_Config_Protocol_Union(protocolVal) - entrySet.Ipv6.State.Protocol, _ = entrySet.Ipv6.State.To_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Ipv6_State_Protocol_Union(protocolVal) - } - */ -} - -var YangToDb_acl_source_port_xfmr FieldXfmrYangToDb = func (inParams XfmrParams) (map[string]string, error) { - res_map := make(map[string]string) - var err error; - sourceportType := reflect.TypeOf(inParams.param).Elem() - log.Info("YangToDb_acl_ip_protocol_xfmr: ", inParams.ygRoot, " Xpath: ", inParams.uri, " sourceportType: ", sourceportType) - switch sourceportType { - case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort_Union_E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort{}): - v := (inParams.param).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort_Union_E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort) - res_map["L4_SRC_PORT"] = v.E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort.ΛMap()["E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort"][int64(v.E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort)].Name - break - case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort_Union_String{}): - v := (inParams.param).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort_Union_String) - res_map["L4_SRC_PORT_RANGE"] = strings.Replace(v.String, "..", "-", 1) - break - case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort_Union_Uint16{}): - v := (inParams.param).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort_Union_Uint16) - res_map["L4_SRC_PORT"] = strconv.FormatInt(int64(v.Uint16), 10) - break - } - - return res_map, err -} - -func getAclSetEntry (aclRuleKey string, ygRoot *ygot.GoStruct) (*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry, error) { - var err error - var entrySet *ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry - aclObj := getAclRoot(ygRoot) - - key := strings.Split(aclRuleKey, "|") - if len(key) < 2 { - log.Info("Invalid Keys for acl entries", aclRuleKey) - err = errors.New("Invalid Keys for acl entries") - return entrySet, err - } - dbAclName := key[0] - dbAclRule := key[1] - var aclSetKey ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_Key - aclSetKey.Name, aclSetKey.Type = getOCAclKeysFromStrDBKey(dbAclName) - seqId,_ := strconv.Atoi(strings.Replace(dbAclRule, "RULE_", "", 1)) - - log.Info("Accessing Ygot tree for ACL rule", aclSetKey.Name, aclSetKey.Type, seqId) - var aclSet *ocbinds.OpenconfigAcl_Acl_AclSets_AclSet - _, ok := aclObj.AclSets.AclSet[aclSetKey] - if !ok { - log.Info("ACL set not allocated") - aclSet, _ = aclObj.AclSets.NewAclSet(aclSetKey.Name, aclSetKey.Type) - ygot.BuildEmptyTree(aclSet) - } else { - aclSet = aclObj.AclSets.AclSet[aclSetKey] - } - if _, ok := aclSet.AclEntries.AclEntry[uint32(seqId)]; !ok { - log.Info("ACL rule not allocated") - entrySet_, _ := aclSet.AclEntries.NewAclEntry(uint32(seqId)) - entrySet = entrySet_ - ygot.BuildEmptyTree(entrySet) - } else { - entrySet = aclSet.AclEntries.AclEntry[uint32(seqId)] - } - - return entrySet, err - -} - -var DbToYang_acl_source_port_xfmr FieldXfmrDbtoYang = func (inParams XfmrParams) (map[string]interface{}, error) { - var err error - data:= (*inParams.dbDataMap)[inParams.curDb] - log.Info("DbToYang_acl_source_port_xfmr: ", data, inParams.ygRoot) - result := make(map[string]interface{}) - if _, ok := data[RULE_TABLE]; !ok { - err = errors.New("RULE_TABLE entry not found in the input param") - return result, err - } - ruleTbl := data[RULE_TABLE] - ruleInst := ruleTbl[inParams.key] - port, ok := ruleInst.Field["L4_SRC_PORT"] - if ok { - result["source-port"] = port - return result, nil - } - - portRange, ok := ruleInst.Field["L4_SRC_PORT_RANGE"] - if ok { - result["source-port"] = portRange - return result, nil - } else { - err = errors.New("PORT/PORT_RANGE field not found in DB") - } - return result, err - /* - - if _, ok := data[RULE_TABLE]; !ok { - err = errors.New("RULE_TABLE entry not found in the input param") - return err - } - ruleTbl := data[RULE_TABLE] - - for aclRuleKey := range ruleTbl { - ruleData := ruleTbl[aclRuleKey] - sp := ruleData.Has("L4_SRC_PORT") - spr := ruleData.Has("L4_SRC_PORT_RANGE") - - if !sp && !spr { - log.Info("Src port field is not present in the field.") - continue - } - var entrySet *ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry - entrySet, err = getAclSetEntry(aclRuleKey, ygRoot) - if err != nil { - log.Info("getAclSetEntry failed for :", aclRuleKey) - continue // If its not map doesnt need to loop just return from here. - } - var ruleKey string - if sp { - ruleKey = "L4_SRC_PORT" - } else { - ruleKey = "L4_SRC_PORT_RANGE" - } - port := ruleData.Get(ruleKey) - srcPort := getTransportSrcDestPorts(port, "src") - entrySet.Transport.Config.SourcePort, _ = entrySet.Transport.Config.To_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_SourcePort_Union(srcPort) - entrySet.Transport.State.SourcePort, _ = entrySet.Transport.State.To_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_State_SourcePort_Union(srcPort) - } - return err - */ -} - -var YangToDb_acl_destination_port_xfmr FieldXfmrYangToDb = func (inParams XfmrParams) (map[string]string, error) { - res_map := make(map[string]string) - var err error; - destportType := reflect.TypeOf(inParams.param).Elem() - log.Info("YangToDb_acl_ip_protocol_xfmr: ", inParams.ygRoot, " Xpath: ", inParams.uri, " destportType: ", destportType) - switch destportType { - case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort_Union_E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort{}): - v := (inParams.param).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort_Union_E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort) - res_map["L4_DST_PORT"] = v.E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort.ΛMap()["E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort"][int64(v.E_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort)].Name - break - case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort_Union_String{}): - v := (inParams.param).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort_Union_String) - res_map["L4_DST_PORT_RANGE"] = strings.Replace(v.String, "..", "-", 1) - break - case reflect.TypeOf(ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort_Union_Uint16{}): - v := (inParams.param).(*ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort_Union_Uint16) - res_map["L4_DST_PORT"] = strconv.FormatInt(int64(v.Uint16), 10) - break - } - return res_map, err -} - -var DbToYang_acl_destination_port_xfmr FieldXfmrDbtoYang = func (inParams XfmrParams) (map[string]interface{}, error) { - var err error - data:= (*inParams.dbDataMap)[inParams.curDb] - log.Info("DbToYang_acl_destination_port_xfmr: ", data, inParams.ygRoot) - result := make(map[string]interface{}) - if _, ok := data[RULE_TABLE]; !ok { - err = errors.New("RULE_TABLE entry not found in the input param") - return result, err - } - ruleTbl := data[RULE_TABLE] - ruleInst := ruleTbl[inParams.key] - port, ok := ruleInst.Field["L4_DST_PORT"] - if ok { - result["destination-port"] = port - return result, nil - } - - portRange, ok := ruleInst.Field["L4_DST_PORT_RANGE"] - if ok { - result["destination-port"] = portRange - return result, nil - } else { - err = errors.New("DST PORT/PORT_RANGE field not found in DB") - } - return result, err - /* - if _, ok := data[RULE_TABLE]; !ok { - err = errors.New("RULE_TABLE entry not found in the input param") - return err - } - ruleTbl := data[RULE_TABLE] - for aclRuleKey := range ruleTbl { - ruleData := ruleTbl[aclRuleKey] - dp := ruleData.Has("L4_DST_PORT") - dpr := ruleData.Has("L4_DST_PORT_RANGE") - if !dp && !dpr { - log.Info("DST port field is not present in the field.") - continue - } - - var entrySet *ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry - entrySet, err = getAclSetEntry(aclRuleKey, ygRoot) - if err != nil { - log.Info("getAclSetEntry failed for :", aclRuleKey) - continue // If its not map doesnt need to loop just return from here. - var ruleKey string - if dp { - ruleKey = "L4_DST_PORT" - } else { - ruleKey = "L4_DST_PORT_RANGE" - } - port := ruleData.Get(ruleKey) - destPort := getTransportSrcDestPorts(port, "dest") - entrySet.Transport.Config.DestinationPort, _ = entrySet.Transport.Config.To_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_Config_DestinationPort_Union(destPort) - entrySet.Transport.State.DestinationPort, _ = entrySet.Transport.State.To_OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry_Transport_State_DestinationPort_Union(destPort) - } - - } - return err - */ -} - -var YangToDb_acl_tcp_flags_xfmr FieldXfmrYangToDb = func (inParams XfmrParams) (map[string]string, error) { - res_map := make(map[string]string) - var err error; - log.Info("YangToDb_acl_tcp_flags_xfmr: ", inParams.ygRoot, inParams.uri) - var tcpFlags uint32 = 0x00 - v := reflect.ValueOf(inParams.param) - - flags := v.Interface().([]ocbinds.E_OpenconfigPacketMatchTypes_TCP_FLAGS) - for _, flag := range flags { - fmt.Println("TCP Flag name: " + flag.ΛMap()["E_OpenconfigPacketMatchTypes_TCP_FLAGS"][int64(flag)].Name) - switch flag { - case ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_FIN: - tcpFlags |= 0x01 - break - case ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_SYN: - tcpFlags |= 0x02 - break - case ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_RST: - tcpFlags |= 0x04 - break - case ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_PSH: - tcpFlags |= 0x08 - break - case ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_ACK: - tcpFlags |= 0x10 - break - case ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_URG: - tcpFlags |= 0x20 - break - case ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_ECE: - tcpFlags |= 0x40 - break - case ocbinds.OpenconfigPacketMatchTypes_TCP_FLAGS_TCP_CWR: - tcpFlags |= 0x80 - break - } - } - var b bytes.Buffer - fmt.Fprintf(&b, "0x%0.2x/0x%0.2x", tcpFlags, tcpFlags) - res_map["TCP_FLAGS"] = b.String() - return res_map, err -} - -var DbToYang_acl_tcp_flags_xfmr FieldXfmrDbtoYang = func (inParams XfmrParams) (map[string]interface{}, error) { - var err error - data:= (*inParams.dbDataMap)[inParams.curDb] - log.Info("DbToYang_acl_tcp_flags_xfmr: ", data, inParams.ygRoot) - result := make(map[string]interface{}) - if _, ok := data[RULE_TABLE]; !ok { - err = errors.New("RULE_TABLE entry not found in the input param") - return result, err - } - ruleTbl := data[RULE_TABLE] - ruleInst := ruleTbl[inParams.key] - tcpFlag, ok := ruleInst.Field["TCP_FLAGS"] - if ok { - result["tcp-flags"] = getTransportConfigTcpFlags(tcpFlag) - return result, nil - } - return result, nil - /* - - if _, ok := data[RULE_TABLE]; !ok { - err = errors.New("RULE_TABLE entry not found in the input param") - return err - } - ruleTbl := data[RULE_TABLE] - - for aclRuleKey := range ruleTbl { - ruleData := ruleTbl[aclRuleKey] - var entrySet *ocbinds.OpenconfigAcl_Acl_AclSets_AclSet_AclEntries_AclEntry - entrySet, err = getAclSetEntry(aclRuleKey, ygRoot) - if err != nil { - log.Info("getAclSetEntry failed for :", aclRuleKey) - continue // If its not map doesnt need to loop just return from here. - } - ruleKey := "TCP_FLAGS" - if !ruleData.Has(ruleKey) { - log.Info("No entry found for the field ", ruleKey) - err = errors.New("TCP_FLAGS field not found in DB") - continue - } - tcpFlags := ruleData.Get(ruleKey) - entrySet.Transport.Config.TcpFlags = getTransportConfigTcpFlags(tcpFlags) - entrySet.Transport.State.TcpFlags = getTransportConfigTcpFlags(tcpFlags) - } - return err - */ -} - -func convertDBAclRulesToInternal(dbCl *db.DB, aclName string, seqId int64, ruleKey db.Key) (ruleTableMap map[string]map[string]db.Value, ferr error) { - ruleTs := &db.TableSpec{Name: RULE_TABLE} - if seqId != -1 { - ruleKey.Comp = []string{aclName, "RULE_" + strconv.FormatInt(int64(seqId), 10)} - } - if ruleKey.Len() > 1 { - ruleName := ruleKey.Get(1) - if ruleName != "DEFAULT_RULE" { - ruleData, err := dbCl.GetEntry(ruleTs, ruleKey) - if err != nil { - ferr = err - return - } - if len(ruleTableMap) == 0 { - ruleTableMap = make(map[string]map[string]db.Value) - } - _, ok := ruleTableMap[aclName] - if !ok { - ruleTableMap[aclName] = make(map[string]db.Value) - ruleTableMap[aclName][ruleName] = db.Value{Field: make(map[string]string)} - } - ruleTableMap[aclName][ruleName] = ruleData - } - } else { - ruleKeys, err := dbCl.GetKeys(ruleTs) - if err != nil { - ferr = err - return - } - for i, _ := range ruleKeys { - if aclName == ruleKeys[i].Get(0) { - ruleTableMap, ferr = convertDBAclRulesToInternal(dbCl, aclName, -1, ruleKeys[i]) - } - } - } - return -} - -func convertDBAclToInternal(dbCl *db.DB, aclkey db.Key) (aclTableMap map[string]db.Value, ruleTableMap map[string]map[string]db.Value, ferr error) { - aclTs := &db.TableSpec{Name: ACL_TABLE} - if aclkey.Len() > 0 { - // Get one particular ACL - entry, err := dbCl.GetEntry(aclTs, aclkey) - if err != nil { - ferr = err - return - } - if entry.IsPopulated() { - log.Info("convertDBAclToInternal : ", aclkey, aclTableMap, " ", aclTableMap[aclkey.Get(0)], " ", entry) - _, ok := aclTableMap[aclkey.Get(0)] - if !ok { - if len(aclTableMap) == 0 { - aclTableMap = make(map[string]db.Value) - } - aclTableMap[aclkey.Get(0)] = db.Value{Field: make(map[string]string)} - } - - aclTableMap[aclkey.Get(0)] = entry - if len(ruleTableMap) == 0 { - ruleTableMap = make(map[string]map[string]db.Value) - } - _, rok := ruleTableMap[aclkey.Get(0)] - if !rok { - ruleTableMap[aclkey.Get(0)] = make(map[string]db.Value) - } - ruleTableMap, ferr = convertDBAclRulesToInternal(dbCl, aclkey.Get(0), -1, db.Key{}) - if err != nil { - ferr = err - return - } - } else { - ferr = tlerr.NotFound("Acl %s is not configured", aclkey.Get(0)) - return - } - } else { - // Get all ACLs - tbl, err := dbCl.GetTable(aclTs) - if err != nil { - ferr = err - return - } - keys, _ := tbl.GetKeys() - for i, _ := range keys { - aclTableMap, ruleTableMap, ferr = convertDBAclToInternal(dbCl, keys[i]) - } - } - return -} - -func getDbAlcTblsData (d *db.DB) (map[string]db.Value, map[string]map[string]db.Value, error) { - var err error - - aclTableMap := make(map[string]db.Value) - ruleTableMap := make(map[string]map[string]db.Value) - - aclTableMap, ruleTableMap, err = convertDBAclToInternal (d, db.Key{}) - - return aclTableMap, ruleTableMap, err -} - -var YangToDb_acl_port_bindings_xfmr SubTreeXfmrYangToDb = func (inParams XfmrParams) (map[string]map[string]db.Value, error) { - res_map := make(map[string]map[string]db.Value) - aclTableMap := make(map[string]db.Value) - log.Info("YangToDb_acl_port_bindings_xfmr: ", inParams.ygRoot, inParams.uri) - - aclObj := getAclRoot(inParams.ygRoot) - - aclTableMapDb, _, err := getDbAlcTblsData(inParams.d) - if err != nil { - log.Info("YangToDb_acl_port_bindings_xfmr: getDbAlcTblsData not able to populate acl tables.") - } - - if aclObj.Interfaces != nil { - if len(aclObj.Interfaces.Interface) > 0 { - aclInterfacesMap := make(map[string][]string) - for intfId, _ := range aclObj.Interfaces.Interface { - intf := aclObj.Interfaces.Interface[intfId] - if intf != nil { - if intf.IngressAclSets != nil && len(intf.IngressAclSets.IngressAclSet) > 0 { - for inAclKey, _ := range intf.IngressAclSets.IngressAclSet { - aclName := getAclKeyStrFromOCKey(inAclKey.SetName, inAclKey.Type) - if intf.InterfaceRef != nil && intf.InterfaceRef.Config.Interface != nil { - aclInterfacesMap[aclName] = append(aclInterfacesMap[aclName], *intf.InterfaceRef.Config.Interface) - } else { - aclInterfacesMap[aclName] = append(aclInterfacesMap[aclName], *intf.Id) - } - _, ok := aclTableMap[aclName] - if !ok { - aclTableMap[aclName] = db.Value{Field: make(map[string]string)} - } - aclTableMap[aclName].Field["stage"] = "INGRESS" - } - } - if intf.EgressAclSets != nil && len(intf.EgressAclSets.EgressAclSet) > 0 { - for outAclKey, _ := range intf.EgressAclSets.EgressAclSet { - aclName := getAclKeyStrFromOCKey(outAclKey.SetName, outAclKey.Type) - if intf.InterfaceRef != nil && intf.InterfaceRef.Config.Interface != nil { - aclInterfacesMap[aclName] = append(aclInterfacesMap[aclName], *intf.InterfaceRef.Config.Interface) - } else { - aclInterfacesMap[aclName] = append(aclInterfacesMap[aclName], *intf.Id) - } - _, ok := aclTableMap[aclName] - if !ok { - aclTableMap[aclName] = db.Value{Field: make(map[string]string)} - } - aclTableMap[aclName].Field["stage"] = "EGRESS" - } - } - if intf.IngressAclSets == nil && intf.EgressAclSets == nil { - for aclName := range aclTableMapDb { - _, ok := aclTableMap[aclName] - if !ok { - aclTableMap[aclName] = db.Value{Field: make(map[string]string)} - } - aclEntryDb := aclTableMapDb[aclName] - intfsDb := aclEntryDb.GetList("ports") - if contains(intfsDb, intfId) { - var intfs []string - intfs = append(intfs, intfId) - aclTableMap[aclName].Field["stage"] = aclEntryDb.Get("stage") - val := aclTableMap[aclName] - (&val).SetList("ports", intfs) - } - } - } - } - } - for k, _ := range aclInterfacesMap { - val := aclTableMap[k] - (&val).SetList("ports", aclInterfacesMap[k]) - } - } else { - for aclName := range aclTableMapDb { - _, ok := aclTableMap[aclName] - if !ok { - aclTableMap[aclName] = db.Value{Field: make(map[string]string)} - } - aclEntryDb := aclTableMapDb[aclName] - aclTableMap[aclName].Field["stage"] = aclEntryDb.Get("stage") - val := aclTableMap[aclName] - (&val).SetList("ports", aclEntryDb.GetList("ports")) - } - } - } - res_map[ACL_TABLE] = aclTableMap - return res_map, err -} - -var DbToYang_acl_port_bindings_xfmr SubTreeXfmrDbToYang = func (inParams XfmrParams) (error) { - var err error - data:= (*inParams.dbDataMap)[inParams.curDb] - log.Info("DbToYang_acl_port_bindings_xfmr: ", data, inParams.ygRoot) - - aclTbl, ruleTbl, err := getDbAlcTblsData(inParams.d) - - if err != nil { - log.Info("getDbAlcTblsData not able to populate acl tables.") - err = errors.New("getDbAlcTblsData failed to populate tables.") - return err - } - pathInfo := NewPathInfo(inParams.uri) - acl := getAclRoot(inParams.ygRoot) - targetUriPath, _ := getYangPathFromUri(pathInfo.Path) - if isSubtreeRequest(pathInfo.Template, "/openconfig-acl:acl/interfaces/interface{}") { - for intfId := range acl.Interfaces.Interface { - intfData := acl.Interfaces.Interface[intfId] - ygot.BuildEmptyTree(intfData) - if isSubtreeRequest(targetUriPath, "/openconfig-acl:acl/interfaces/interface/ingress-acl-sets") { - err = getAclBindingInfoForInterfaceData(aclTbl, ruleTbl, intfData, intfId, "INGRESS") - } else if isSubtreeRequest(targetUriPath, "/openconfig-acl:acl/interfaces/interface/egress-acl-sets") { - err = getAclBindingInfoForInterfaceData(aclTbl, ruleTbl, intfData, intfId, "EGRESS") - } else { - err = getAclBindingInfoForInterfaceData(aclTbl, ruleTbl, intfData, intfId, "INGRESS") - if err != nil { - return err - } - err = getAclBindingInfoForInterfaceData(aclTbl, ruleTbl, intfData, intfId, "EGRESS") - } - } - } else { - err = getAllBindingsInfo(aclTbl, ruleTbl, inParams.ygRoot) - } - - return err -} func convertInternalToOCAclRuleBinding(aclTableMap map[string]db.Value, ruleTableMap map[string]map[string]db.Value, priority uint32, seqId int64, direction string, aclSet ygot.GoStruct, entrySet ygot.GoStruct) { - if seqId == -1 { - seqId = int64(MAX_PRIORITY - priority) - } - - var num uint64 - num = 0 - var ruleId uint32 = uint32(seqId) - - if direction == "INGRESS" { - var ingressEntrySet *ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_IngressAclSets_IngressAclSet_AclEntries_AclEntry - var ok bool - if entrySet == nil { - ingressAclSet := aclSet.(*ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_IngressAclSets_IngressAclSet) - if ingressEntrySet, ok = ingressAclSet.AclEntries.AclEntry[ruleId]; !ok { - ingressEntrySet, _ = ingressAclSet.AclEntries.NewAclEntry(ruleId) - } - } else { - ingressEntrySet = entrySet.(*ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_IngressAclSets_IngressAclSet_AclEntries_AclEntry) - } - if ingressEntrySet != nil { - ygot.BuildEmptyTree(ingressEntrySet) - ingressEntrySet.State.SequenceId = &ruleId - ingressEntrySet.State.MatchedPackets = &num - ingressEntrySet.State.MatchedOctets = &num - } - } else if direction == "EGRESS" { - var egressEntrySet *ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_EgressAclSets_EgressAclSet_AclEntries_AclEntry - var ok bool - if entrySet == nil { - egressAclSet := aclSet.(*ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_EgressAclSets_EgressAclSet) - if egressEntrySet, ok = egressAclSet.AclEntries.AclEntry[ruleId]; !ok { - egressEntrySet, _ = egressAclSet.AclEntries.NewAclEntry(ruleId) - } - } else { - egressEntrySet = entrySet.(*ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_EgressAclSets_EgressAclSet_AclEntries_AclEntry) - } - if egressEntrySet != nil { - ygot.BuildEmptyTree(egressEntrySet) - egressEntrySet.State.SequenceId = &ruleId - egressEntrySet.State.MatchedPackets = &num - egressEntrySet.State.MatchedOctets = &num - } - } + if seqId == -1 { + seqId = int64(MAX_PRIORITY - priority) + } + + var num uint64 + num = 0 + var ruleId uint32 = uint32(seqId) + + if direction == "INGRESS" { + var ingressEntrySet *ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_IngressAclSets_IngressAclSet_AclEntries_AclEntry + var ok bool + if entrySet == nil { + ingressAclSet := aclSet.(*ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_IngressAclSets_IngressAclSet) + if ingressEntrySet, ok = ingressAclSet.AclEntries.AclEntry[ruleId]; !ok { + ingressEntrySet, _ = ingressAclSet.AclEntries.NewAclEntry(ruleId) + } + } else { + ingressEntrySet = entrySet.(*ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_IngressAclSets_IngressAclSet_AclEntries_AclEntry) + } + if ingressEntrySet != nil { + ygot.BuildEmptyTree(ingressEntrySet) + ingressEntrySet.State.SequenceId = &ruleId + ingressEntrySet.State.MatchedPackets = &num + ingressEntrySet.State.MatchedOctets = &num + } + } else if direction == "EGRESS" { + var egressEntrySet *ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_EgressAclSets_EgressAclSet_AclEntries_AclEntry + var ok bool + if entrySet == nil { + egressAclSet := aclSet.(*ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_EgressAclSets_EgressAclSet) + if egressEntrySet, ok = egressAclSet.AclEntries.AclEntry[ruleId]; !ok { + egressEntrySet, _ = egressAclSet.AclEntries.NewAclEntry(ruleId) + } + } else { + egressEntrySet = entrySet.(*ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_EgressAclSets_EgressAclSet_AclEntries_AclEntry) + } + if egressEntrySet != nil { + ygot.BuildEmptyTree(egressEntrySet) + egressEntrySet.State.SequenceId = &ruleId + egressEntrySet.State.MatchedPackets = &num + egressEntrySet.State.MatchedOctets = &num + } + } } func convertInternalToOCAclBinding(aclTableMap map[string]db.Value, ruleTableMap map[string]map[string]db.Value, aclName string, intfId string, direction string, intfAclSet ygot.GoStruct) error { - var err error - if _, ok := aclTableMap[aclName]; !ok { - err = errors.New("Acl entry not found, convertInternalToOCAclBinding") - return err - } else { - aclEntry := aclTableMap[aclName] - if !contains(aclEntry.GetList("ports"), intfId) { - return tlerr.InvalidArgs("Acl %s not binded with %s", aclName, intfId) - } - } - - for ruleName := range ruleTableMap[aclName] { - if ruleName != "DEFAULT_RULE" { - seqId, _ := strconv.Atoi(strings.Replace(ruleName, "RULE_", "", 1)) - convertInternalToOCAclRuleBinding(aclTableMap, ruleTableMap, 0, int64(seqId), direction, intfAclSet, nil) - } - } - - return err + var err error + if _, ok := aclTableMap[aclName]; !ok { + err = errors.New("Acl entry not found, convertInternalToOCAclBinding") + return err + } else { + aclEntry := aclTableMap[aclName] + if !contains(aclEntry.GetList("ports"), intfId) { + return tlerr.InvalidArgs("Acl %s not binded with %s", aclName, intfId) + } + } + + for ruleName := range ruleTableMap[aclName] { + if ruleName != "DEFAULT_RULE" { + seqId, _ := strconv.Atoi(strings.Replace(ruleName, "RULE_", "", 1)) + convertInternalToOCAclRuleBinding(aclTableMap, ruleTableMap, 0, int64(seqId), direction, intfAclSet, nil) + } + } + + return err } func getAllBindingsInfo(aclTableMap map[string]db.Value, ruleTableMap map[string]map[string]db.Value, ygRoot *ygot.GoStruct) error { - var err error - acl := getAclRoot(ygRoot) - - var interfaces []string - for aclName := range aclTableMap { - aclData := aclTableMap[aclName] - if len(aclData.Get("ports@")) > 0 { - aclIntfs := aclData.GetList("ports") - for i, _ := range aclIntfs { - if !contains(interfaces, aclIntfs[i]) && aclIntfs[i] != "" { - interfaces = append(interfaces, aclIntfs[i]) - } - } - } - } - ygot.BuildEmptyTree(acl) - for _, intfId := range interfaces { - var intfData *ocbinds.OpenconfigAcl_Acl_Interfaces_Interface - intfData, ok := acl.Interfaces.Interface[intfId] - if !ok { - intfData, _ = acl.Interfaces.NewInterface(intfId) - } - ygot.BuildEmptyTree(intfData) - err = getAclBindingInfoForInterfaceData(aclTableMap, ruleTableMap, intfData, intfId, "INGRESS") - err = getAclBindingInfoForInterfaceData(aclTableMap, ruleTableMap, intfData, intfId, "EGRESS") - } - return err + var err error + acl := getAclRoot(ygRoot) + + var interfaces []string + for aclName := range aclTableMap { + aclData := aclTableMap[aclName] + if len(aclData.Get("ports@")) > 0 { + aclIntfs := aclData.GetList("ports") + for i, _ := range aclIntfs { + if !contains(interfaces, aclIntfs[i]) && aclIntfs[i] != "" { + interfaces = append(interfaces, aclIntfs[i]) + } + } + } + } + ygot.BuildEmptyTree(acl) + for _, intfId := range interfaces { + var intfData *ocbinds.OpenconfigAcl_Acl_Interfaces_Interface + intfData, ok := acl.Interfaces.Interface[intfId] + if !ok { + intfData, _ = acl.Interfaces.NewInterface(intfId) + } + ygot.BuildEmptyTree(intfData) + err = getAclBindingInfoForInterfaceData(aclTableMap, ruleTableMap, intfData, intfId, "INGRESS") + err = getAclBindingInfoForInterfaceData(aclTableMap, ruleTableMap, intfData, intfId, "EGRESS") + } + return err } func getAclBindingInfoForInterfaceData(aclTableMap map[string]db.Value, ruleTableMap map[string]map[string]db.Value, intfData *ocbinds.OpenconfigAcl_Acl_Interfaces_Interface, intfId string, direction string) error { - var err error - if intfData != nil { - intfData.Config.Id = intfData.Id - intfData.State.Id = intfData.Id - } - if direction == "INGRESS" { - if intfData.IngressAclSets != nil && len(intfData.IngressAclSets.IngressAclSet) > 0 { - for ingressAclSetKey, _ := range intfData.IngressAclSets.IngressAclSet { - aclName := strings.Replace(strings.Replace(ingressAclSetKey.SetName, " ", "_", -1), "-", "_", -1) - aclType := ingressAclSetKey.Type.ΛMap()["E_OpenconfigAcl_ACL_TYPE"][int64(ingressAclSetKey.Type)].Name - aclKey := aclName + "_" + aclType - - ingressAclSet := intfData.IngressAclSets.IngressAclSet[ingressAclSetKey] - if ingressAclSet != nil && ingressAclSet.AclEntries != nil && len(ingressAclSet.AclEntries.AclEntry) > 0 { - for seqId, _ := range ingressAclSet.AclEntries.AclEntry { - rulekey := "RULE_" + strconv.Itoa(int(seqId)) - entrySet := ingressAclSet.AclEntries.AclEntry[seqId] - _, ok := ruleTableMap[aclKey][rulekey] - if !ok { - log.Info("Acl Rule not found ", aclKey, rulekey) - err = errors.New("Acl Rule not found ingress, getAclBindingInfoForInterfaceData") - return err - } - convertInternalToOCAclRuleBinding(aclTableMap, ruleTableMap, 0, int64(seqId), direction, nil, entrySet) - } - } else { - ygot.BuildEmptyTree(ingressAclSet) - ingressAclSet.Config = &ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_IngressAclSets_IngressAclSet_Config{SetName: &aclName, Type: ingressAclSetKey.Type} - ingressAclSet.State = &ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_IngressAclSets_IngressAclSet_State{SetName: &aclName, Type: ingressAclSetKey.Type} - err = convertInternalToOCAclBinding(aclTableMap, ruleTableMap, aclKey, intfId, direction, ingressAclSet) - } - } - } else { - err = findAndGetAclBindingInfoForInterfaceData(aclTableMap, ruleTableMap, intfId, direction, intfData) - } - } else if direction == "EGRESS" { - if intfData.EgressAclSets != nil && len(intfData.EgressAclSets.EgressAclSet) > 0 { - for egressAclSetKey, _ := range intfData.EgressAclSets.EgressAclSet { - aclName := strings.Replace(strings.Replace(egressAclSetKey.SetName, " ", "_", -1), "-", "_", -1) - aclType := egressAclSetKey.Type.ΛMap()["E_OpenconfigAcl_ACL_TYPE"][int64(egressAclSetKey.Type)].Name - aclKey := aclName + "_" + aclType - - egressAclSet := intfData.EgressAclSets.EgressAclSet[egressAclSetKey] - if egressAclSet != nil && egressAclSet.AclEntries != nil && len(egressAclSet.AclEntries.AclEntry) > 0 { - for seqId, _ := range egressAclSet.AclEntries.AclEntry { - rulekey := "RULE_" + strconv.Itoa(int(seqId)) - entrySet := egressAclSet.AclEntries.AclEntry[seqId] - _, ok := ruleTableMap[aclKey][rulekey] - if !ok { - log.Info("Acl Rule not found ", aclKey, rulekey) - err = errors.New("Acl Rule not found egress, getAclBindingInfoForInterfaceData") - return err - } - convertInternalToOCAclRuleBinding(aclTableMap, ruleTableMap, 0, int64(seqId), direction, nil, entrySet) - } - } else { - ygot.BuildEmptyTree(egressAclSet) - egressAclSet.Config = &ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_EgressAclSets_EgressAclSet_Config{SetName: &aclName, Type: egressAclSetKey.Type} - egressAclSet.State = &ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_EgressAclSets_EgressAclSet_State{SetName: &aclName, Type: egressAclSetKey.Type} - err = convertInternalToOCAclBinding(aclTableMap, ruleTableMap, aclKey, intfId, direction, egressAclSet) - } - } - } else { - err = findAndGetAclBindingInfoForInterfaceData(aclTableMap, ruleTableMap, intfId, direction, intfData) - } - } else { - log.Error("Unknown direction") - } - return err + var err error + if intfData != nil { + intfData.Config.Id = intfData.Id + intfData.State.Id = intfData.Id + } + if direction == "INGRESS" { + if intfData.IngressAclSets != nil && len(intfData.IngressAclSets.IngressAclSet) > 0 { + for ingressAclSetKey, _ := range intfData.IngressAclSets.IngressAclSet { + aclName := strings.Replace(strings.Replace(ingressAclSetKey.SetName, " ", "_", -1), "-", "_", -1) + aclType := ingressAclSetKey.Type.ΛMap()["E_OpenconfigAcl_ACL_TYPE"][int64(ingressAclSetKey.Type)].Name + aclKey := aclName + "_" + aclType + + ingressAclSet := intfData.IngressAclSets.IngressAclSet[ingressAclSetKey] + if ingressAclSet != nil && ingressAclSet.AclEntries != nil && len(ingressAclSet.AclEntries.AclEntry) > 0 { + for seqId, _ := range ingressAclSet.AclEntries.AclEntry { + rulekey := "RULE_" + strconv.Itoa(int(seqId)) + entrySet := ingressAclSet.AclEntries.AclEntry[seqId] + _, ok := ruleTableMap[aclKey+"|"+rulekey] + if !ok { + log.Info("Acl Rule not found ", aclKey, rulekey) + err = errors.New("Acl Rule not found ingress, getAclBindingInfoForInterfaceData") + return err + } + convertInternalToOCAclRuleBinding(aclTableMap, ruleTableMap, 0, int64(seqId), direction, nil, entrySet) + } + } else { + ygot.BuildEmptyTree(ingressAclSet) + ingressAclSet.Config = &ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_IngressAclSets_IngressAclSet_Config{SetName: &aclName, Type: ingressAclSetKey.Type} + ingressAclSet.State = &ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_IngressAclSets_IngressAclSet_State{SetName: &aclName, Type: ingressAclSetKey.Type} + err = convertInternalToOCAclBinding(aclTableMap, ruleTableMap, aclKey, intfId, direction, ingressAclSet) + } + } + } else { + err = findAndGetAclBindingInfoForInterfaceData(aclTableMap, ruleTableMap, intfId, direction, intfData) + } + } else if direction == "EGRESS" { + if intfData.EgressAclSets != nil && len(intfData.EgressAclSets.EgressAclSet) > 0 { + for egressAclSetKey, _ := range intfData.EgressAclSets.EgressAclSet { + aclName := strings.Replace(strings.Replace(egressAclSetKey.SetName, " ", "_", -1), "-", "_", -1) + aclType := egressAclSetKey.Type.ΛMap()["E_OpenconfigAcl_ACL_TYPE"][int64(egressAclSetKey.Type)].Name + aclKey := aclName + "_" + aclType + + egressAclSet := intfData.EgressAclSets.EgressAclSet[egressAclSetKey] + if egressAclSet != nil && egressAclSet.AclEntries != nil && len(egressAclSet.AclEntries.AclEntry) > 0 { + for seqId, _ := range egressAclSet.AclEntries.AclEntry { + rulekey := "RULE_" + strconv.Itoa(int(seqId)) + entrySet := egressAclSet.AclEntries.AclEntry[seqId] + _, ok := ruleTableMap[aclKey+"|"+rulekey] + if !ok { + log.Info("Acl Rule not found ", aclKey, rulekey) + err = errors.New("Acl Rule not found egress, getAclBindingInfoForInterfaceData") + return err + } + convertInternalToOCAclRuleBinding(aclTableMap, ruleTableMap, 0, int64(seqId), direction, nil, entrySet) + } + } else { + ygot.BuildEmptyTree(egressAclSet) + egressAclSet.Config = &ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_EgressAclSets_EgressAclSet_Config{SetName: &aclName, Type: egressAclSetKey.Type} + egressAclSet.State = &ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_EgressAclSets_EgressAclSet_State{SetName: &aclName, Type: egressAclSetKey.Type} + err = convertInternalToOCAclBinding(aclTableMap, ruleTableMap, aclKey, intfId, direction, egressAclSet) + } + } + } else { + err = findAndGetAclBindingInfoForInterfaceData(aclTableMap, ruleTableMap, intfId, direction, intfData) + } + } else { + log.Error("Unknown direction") + } + return err } func findAndGetAclBindingInfoForInterfaceData(aclTableMap map[string]db.Value, ruleTableMap map[string]map[string]db.Value, intfId string, direction string, intfData *ocbinds.OpenconfigAcl_Acl_Interfaces_Interface) error { - var err error - for aclName, _ := range aclTableMap { - aclData := aclTableMap[aclName] - aclIntfs := aclData.GetList("ports") - aclType := aclData.Get(ACL_TYPE) - var aclOrigName string - var aclOrigType ocbinds.E_OpenconfigAcl_ACL_TYPE - if SONIC_ACL_TYPE_IPV4 == aclType { - aclOrigName = strings.Replace(aclName, "_"+OPENCONFIG_ACL_TYPE_IPV4, "", 1) - aclOrigType = ocbinds.OpenconfigAcl_ACL_TYPE_ACL_IPV4 - } else if SONIC_ACL_TYPE_IPV6 == aclType { - aclOrigName = strings.Replace(aclName, "_"+OPENCONFIG_ACL_TYPE_IPV6, "", 1) - aclOrigType = ocbinds.OpenconfigAcl_ACL_TYPE_ACL_IPV6 - } else if SONIC_ACL_TYPE_L2 == aclType { - aclOrigName = strings.Replace(aclName, "_"+OPENCONFIG_ACL_TYPE_L2, "", 1) - aclOrigType = ocbinds.OpenconfigAcl_ACL_TYPE_ACL_L2 - } - - if contains(aclIntfs, intfId) && direction == aclData.Get("stage") { - if direction == "INGRESS" { - if intfData.IngressAclSets != nil { - aclSetKey := ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_IngressAclSets_IngressAclSet_Key{SetName: aclOrigName, Type: aclOrigType} - ingressAclSet, ok := intfData.IngressAclSets.IngressAclSet[aclSetKey] - if !ok { - ingressAclSet, _ = intfData.IngressAclSets.NewIngressAclSet(aclOrigName, aclOrigType) - ygot.BuildEmptyTree(ingressAclSet) - ingressAclSet.Config = &ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_IngressAclSets_IngressAclSet_Config{SetName: &aclOrigName, Type: aclOrigType} - ingressAclSet.State = &ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_IngressAclSets_IngressAclSet_State{SetName: &aclOrigName, Type: aclOrigType} - } - err = convertInternalToOCAclBinding(aclTableMap, ruleTableMap, aclName, intfId, direction, ingressAclSet) - if err != nil { - return err - } - } - } else if direction == "EGRESS" { - if intfData.EgressAclSets != nil { - aclSetKey := ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_EgressAclSets_EgressAclSet_Key{SetName: aclOrigName, Type: aclOrigType} - egressAclSet, ok := intfData.EgressAclSets.EgressAclSet[aclSetKey] - if !ok { - egressAclSet, _ = intfData.EgressAclSets.NewEgressAclSet(aclOrigName, aclOrigType) - ygot.BuildEmptyTree(egressAclSet) - egressAclSet.Config = &ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_EgressAclSets_EgressAclSet_Config{SetName: &aclOrigName, Type: aclOrigType} - egressAclSet.State = &ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_EgressAclSets_EgressAclSet_State{SetName: &aclOrigName, Type: aclOrigType} - } - err = convertInternalToOCAclBinding(aclTableMap, ruleTableMap, aclName, intfId, direction, egressAclSet) - if err != nil { - return err - } - } - } - } - } - return err + var err error + for aclName, _ := range aclTableMap { + aclData := aclTableMap[aclName] + aclIntfs := aclData.GetList("ports") + aclType := aclData.Get(ACL_TYPE) + var aclOrigName string + var aclOrigType ocbinds.E_OpenconfigAcl_ACL_TYPE + if SONIC_ACL_TYPE_IPV4 == aclType { + aclOrigName = strings.Replace(aclName, "_"+OPENCONFIG_ACL_TYPE_IPV4, "", 1) + aclOrigType = ocbinds.OpenconfigAcl_ACL_TYPE_ACL_IPV4 + } else if SONIC_ACL_TYPE_IPV6 == aclType { + aclOrigName = strings.Replace(aclName, "_"+OPENCONFIG_ACL_TYPE_IPV6, "", 1) + aclOrigType = ocbinds.OpenconfigAcl_ACL_TYPE_ACL_IPV6 + } else if SONIC_ACL_TYPE_L2 == aclType { + aclOrigName = strings.Replace(aclName, "_"+OPENCONFIG_ACL_TYPE_L2, "", 1) + aclOrigType = ocbinds.OpenconfigAcl_ACL_TYPE_ACL_L2 + } + + if contains(aclIntfs, intfId) && direction == aclData.Get("stage") { + if direction == "INGRESS" { + if intfData.IngressAclSets != nil { + aclSetKey := ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_IngressAclSets_IngressAclSet_Key{SetName: aclOrigName, Type: aclOrigType} + ingressAclSet, ok := intfData.IngressAclSets.IngressAclSet[aclSetKey] + if !ok { + ingressAclSet, _ = intfData.IngressAclSets.NewIngressAclSet(aclOrigName, aclOrigType) + ygot.BuildEmptyTree(ingressAclSet) + ingressAclSet.Config = &ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_IngressAclSets_IngressAclSet_Config{SetName: &aclOrigName, Type: aclOrigType} + ingressAclSet.State = &ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_IngressAclSets_IngressAclSet_State{SetName: &aclOrigName, Type: aclOrigType} + } + err = convertInternalToOCAclBinding(aclTableMap, ruleTableMap, aclName, intfId, direction, ingressAclSet) + if err != nil { + return err + } + } + } else if direction == "EGRESS" { + if intfData.EgressAclSets != nil { + aclSetKey := ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_EgressAclSets_EgressAclSet_Key{SetName: aclOrigName, Type: aclOrigType} + egressAclSet, ok := intfData.EgressAclSets.EgressAclSet[aclSetKey] + if !ok { + egressAclSet, _ = intfData.EgressAclSets.NewEgressAclSet(aclOrigName, aclOrigType) + ygot.BuildEmptyTree(egressAclSet) + egressAclSet.Config = &ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_EgressAclSets_EgressAclSet_Config{SetName: &aclOrigName, Type: aclOrigType} + egressAclSet.State = &ocbinds.OpenconfigAcl_Acl_Interfaces_Interface_EgressAclSets_EgressAclSet_State{SetName: &aclOrigName, Type: aclOrigType} + } + err = convertInternalToOCAclBinding(aclTableMap, ruleTableMap, aclName, intfId, direction, egressAclSet) + if err != nil { + return err + } + } + } + } + } + return err } From cdb8731a4997c669c8a74268f2ce1162be73d73c Mon Sep 17 00:00:00 2001 From: kwangsuk Date: Wed, 11 Sep 2019 22:24:57 -0700 Subject: [PATCH 115/214] fix the build error --- src/translib/common_app.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/translib/common_app.go b/src/translib/common_app.go index f75ad72476..eaba39df4c 100644 --- a/src/translib/common_app.go +++ b/src/translib/common_app.go @@ -163,14 +163,12 @@ func (app *CommonApp) processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error) { return GetResponse{Payload: payload, ErrSrc: AppErr}, err } - if targetObj != nil { targetObj, _ := (*app.ygotTarget).(ygot.GoStruct) err = ocbinds.Unmarshal(payload, targetObj) if err != nil { log.Error("ocbinds.Unmarshal() failed") return GetResponse{Payload: payload, ErrSrc: AppErr}, err } - } payload, err = generateGetResponsePayload(app.pathInfo.Path, (*app.ygotRoot).(*ocbinds.Device), app.ygotTarget) if err != nil { From e8efc95900f6c9173dd453c94e108c73cd0677d7 Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Wed, 11 Sep 2019 22:36:44 -0700 Subject: [PATCH 116/214] Fis get leaf crash, remove unsed annotations --- .../annotations/openconfig-acl-annot.yang | 41 ------------------- src/translib/common_app.go | 14 ++++--- 2 files changed, 8 insertions(+), 47 deletions(-) diff --git a/models/yang/annotations/openconfig-acl-annot.yang b/models/yang/annotations/openconfig-acl-annot.yang index c4e6ecf54a..886dff83db 100644 --- a/models/yang/annotations/openconfig-acl-annot.yang +++ b/models/yang/annotations/openconfig-acl-annot.yang @@ -119,46 +119,5 @@ module openconfig-acl-annot { } } - deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:state { - deviate add { - sonic-ext:redis-db-name "STATE_DB"; - } - } - - deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-acl:state { - deviate add { - sonic-ext:redis-db-name "STATE_DB"; - } - } - - deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-acl:l2/oc-acl:state { - deviate add { - sonic-ext:redis-db-name "STATE_DB"; - } - } - - deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-acl:ipv4/oc-acl:state { - deviate add { - sonic-ext:redis-db-name "STATE_DB"; - } - } - - deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-acl:ipv6/oc-acl:state { - deviate add { - sonic-ext:redis-db-name "STATE_DB"; - } - } - - deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-acl:transport/oc-acl:state { - deviate add { - sonic-ext:redis-db-name "STATE_DB"; - } - } - - deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-acl:actions/oc-acl:state { - deviate add { - sonic-ext:redis-db-name "STATE_DB"; - } - } } diff --git a/src/translib/common_app.go b/src/translib/common_app.go index eaba39df4c..38231615ad 100644 --- a/src/translib/common_app.go +++ b/src/translib/common_app.go @@ -163,12 +163,14 @@ func (app *CommonApp) processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error) { return GetResponse{Payload: payload, ErrSrc: AppErr}, err } - targetObj, _ := (*app.ygotTarget).(ygot.GoStruct) - err = ocbinds.Unmarshal(payload, targetObj) - if err != nil { - log.Error("ocbinds.Unmarshal() failed") - return GetResponse{Payload: payload, ErrSrc: AppErr}, err - } + targetObj, _ := (*app.ygotTarget).(ygot.GoStruct) + if targetObj != nil { + err = ocbinds.Unmarshal(payload, targetObj) + if err != nil { + log.Error("ocbinds.Unmarshal() failed") + return GetResponse{Payload: payload, ErrSrc: AppErr}, err + } + } payload, err = generateGetResponsePayload(app.pathInfo.Path, (*app.ygotRoot).(*ocbinds.Device), app.ygotTarget) if err != nil { From ff617fb50acefb3d9855192a785b49ba533bda58 Mon Sep 17 00:00:00 2001 From: jjose Date: Thu, 12 Sep 2019 18:10:53 +0000 Subject: [PATCH 117/214] Adding Interface table entry with just name, before the one with ifname and IP. --- src/translib/intf_app.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/translib/intf_app.go b/src/translib/intf_app.go index b74e978aa0..ce686e714e 100644 --- a/src/translib/intf_app.go +++ b/src/translib/intf_app.go @@ -1248,6 +1248,17 @@ func (app *IntfApp) processCommon(d *db.DB) (SetResponse, error) { } for key, entry1 := range app.ifIPTableMap { + ifEntry, err := d.GetEntry(app.intfIPTs, db.Key{Comp: []string{key}}) + if err != nil || !ifEntry.IsPopulated() { + log.Infof("Interface Entry not present for Key:%s for IP config!", key) + m := make(map[string]string) + m["NULL"] = "NULL" + err = d.CreateEntry(app.intfIPTs, db.Key{Comp: []string{key}}, db.Value{Field: m}) + if err != nil { + return resp, err + } + log.Infof("Created Interface entry with Interface name : %s alone!", key) + } for ip, entry := range entry1 { if entry.op == opCreate { log.Info("Creating entry for ", key, ":", ip) From 71d0eeb66b1429b375a54965ad5cc6d817da57e3 Mon Sep 17 00:00:00 2001 From: kwangsuk Date: Thu, 12 Sep 2019 14:46:53 -0700 Subject: [PATCH 118/214] add get-validate to validate a YANG node durin data translation back to YANG response --- .../yang/annotations/openconfig-acl-annot.yang | 12 ++++++++++++ models/yang/common/sonic-extensions.yang | 5 +++++ src/translib/transformer/xfmr_acl.go | 14 ++++++++++++++ src/translib/transformer/xfmr_interface.go | 6 ++++++ src/translib/transformer/xlate_from_db.go | 16 ++++++++++++++++ src/translib/transformer/xspec.go | 3 +++ 6 files changed, 56 insertions(+) diff --git a/models/yang/annotations/openconfig-acl-annot.yang b/models/yang/annotations/openconfig-acl-annot.yang index 886dff83db..b24d3f41c8 100644 --- a/models/yang/annotations/openconfig-acl-annot.yang +++ b/models/yang/annotations/openconfig-acl-annot.yang @@ -41,6 +41,18 @@ module openconfig-acl-annot { } } + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-acl:ipv4 { + deviate add { + sonic-ext:get-validate "validate_ipv4"; + } + } + + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-acl:ipv6 { + deviate add { + sonic-ext:get-validate "validate_ipv6"; + } + } + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-acl:config/oc-acl:sequence-id { deviate add { sonic-ext:field-transformer "acl_entry_sequenceid_xfmr"; diff --git a/models/yang/common/sonic-extensions.yang b/models/yang/common/sonic-extensions.yang index bcdd2187a4..ff3c315b3d 100644 --- a/models/yang/common/sonic-extensions.yang +++ b/models/yang/common/sonic-extensions.yang @@ -66,6 +66,11 @@ module sonic-extensions { description "Transformer name that will perform post-translation tasks."; } + extension get-validate { + argument "get-validate-name"; + description "Validation callpoint used to validate a YANG node during data translation back to YANG as a response to GET."; + } + extension redis-db-name { argument "db-name"; description "DB name that will indicate where data is stored. Eg: Config DB, App DB etc"; diff --git a/src/translib/transformer/xfmr_acl.go b/src/translib/transformer/xfmr_acl.go index 645d7011fb..05f0be252b 100644 --- a/src/translib/transformer/xfmr_acl.go +++ b/src/translib/transformer/xfmr_acl.go @@ -35,6 +35,8 @@ func init() { XlateFuncBind("DbToYang_acl_tcp_flags_xfmr", DbToYang_acl_tcp_flags_xfmr) XlateFuncBind("YangToDb_acl_port_bindings_xfmr", YangToDb_acl_port_bindings_xfmr) XlateFuncBind("DbToYang_acl_port_bindings_xfmr", DbToYang_acl_port_bindings_xfmr) + XlateFuncBind("validate_ipv4", validate_ipv4) + XlateFuncBind("validate_ipv6", validate_ipv6) } const ( @@ -166,6 +168,18 @@ func getL2EtherType(etherType uint64) interface{} { return uint16(etherType) } +//////////////////////////////////////////// +// Validate callpoints +//////////////////////////////////////////// +var validate_ipv4 ValidateCallpoint = func(inParams XfmrParams) (bool) { + var res bool = true + return res +} +var validate_ipv6 ValidateCallpoint = func(inParams XfmrParams) (bool) { + var res bool = false + return res +} + //////////////////////////////////////////// // Bi-directoonal overloaded methods //////////////////////////////////////////// diff --git a/src/translib/transformer/xfmr_interface.go b/src/translib/transformer/xfmr_interface.go index 77b512e992..472fbc3dff 100644 --- a/src/translib/transformer/xfmr_interface.go +++ b/src/translib/transformer/xfmr_interface.go @@ -62,6 +62,12 @@ type SubTreeXfmrYangToDb func (inParams XfmrParams) (map[string]map[string]db.Va * Return : error **/ type SubTreeXfmrDbToYang func (inParams XfmrParams) (error) +/** + * ValidateCallpoint is used to validate a YANG node during data translation back to YANG as a response to GET + * Param : Database pointers, current db, operation, DB data in multidimensional map, output param YgotRoot, uri + * Return : bool + **/ +type ValidateCallpoint func (inParams XfmrParams) (bool) /** * Xfmr validation interface for validating the callback registration of app modules diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index 06898f84de..626371b58b 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -72,6 +72,14 @@ func leafXfmrHandlerFunc(inParams XfmrParams) (map[string]interface{}, string, e return fldValMap, data, nil } +func validateHandlerFunc(inParams XfmrParams) (bool) { + xpath, _ := RemoveXPATHPredicates(inParams.uri) + ret, err := XlateFuncCall(xSpecMap[xpath].validateFunc, inParams) + if err != nil { + return false + } + return ret[0].Interface().(bool) +} /* Traverse db map and create json for cvl yang */ func directDbToYangJsonCreate(dbDataMap map[string]map[string]db.Value, jsonData string) string { @@ -147,6 +155,14 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath chldXpath := xpath+"/"+yangChldName chldUri := uri+"/"+yangChldName if xSpecMap[chldXpath] != nil && xSpecMap[chldXpath].yangEntry != nil { + if len(xSpecMap[chldXpath].validateFunc) > 0 { + // TODO - handle non CONFIG-DB + inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, chldUri, GET, "", dbDataMap, nil) + res := validateHandlerFunc(inParams) + if res != true { + continue + } + } chldYangType := yangTypeGet(xSpecMap[chldXpath].yangEntry) cdb = xSpecMap[chldXpath].dbIndex if chldYangType == "leaf" { diff --git a/src/translib/transformer/xspec.go b/src/translib/transformer/xspec.go index fd4bb28b3d..7af7321dd7 100644 --- a/src/translib/transformer/xspec.go +++ b/src/translib/transformer/xspec.go @@ -21,6 +21,7 @@ type yangXpathInfo struct { delim string fieldName string xfmrFunc string + validateFunc string xfmrKey string dbIndex db.DBNum keyLevel int @@ -272,6 +273,8 @@ func annotEntryFill(xSpecMap map[string]*yangXpathInfo, xpath string, entry *yan xpathData.xfmrFunc = ext.NName() case "post-transformer" : xpathData.xfmrFunc = ext.NName() + case "get-validate" : + xpathData.validateFunc = ext.NName() case "use-self-key" : xpathData.keyXpath = nil case "redis-db-name" : From 8d272a364c3d12999b0fef1ce6e38a4689e6a15d Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Thu, 12 Sep 2019 15:34:13 -0700 Subject: [PATCH 119/214] Fix crash during update request to leaflist --- src/translib/transformer/xfmr_acl.go | 31 ++++++++++++++++++++++--- src/translib/transformer/xlate_to_db.go | 22 +++++++++--------- 2 files changed, 39 insertions(+), 14 deletions(-) diff --git a/src/translib/transformer/xfmr_acl.go b/src/translib/transformer/xfmr_acl.go index 645d7011fb..d58b07e688 100644 --- a/src/translib/transformer/xfmr_acl.go +++ b/src/translib/transformer/xfmr_acl.go @@ -173,6 +173,10 @@ func getL2EtherType(etherType uint64) interface{} { var YangToDb_acl_type_field_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { res_map := make(map[string]string) var err error + if inParams.param == nil { + res_map[ACL_TYPE] = "" + return res_map, err + } acltype, _ := inParams.param.(ocbinds.E_OpenconfigAcl_ACL_TYPE) log.Info("YangToDb_acl_type_field_xfmr: ", inParams.ygRoot, " Xpath: ", inParams.uri, " acltype: ", acltype) @@ -289,6 +293,10 @@ var YangToDb_acl_l2_ethertype_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) res_map := make(map[string]string) var err error + if inParams.param == nil { + res_map["ETHER_TYPE"] = "" + return res_map, err + } ethertypeType := reflect.TypeOf(inParams.param).Elem() log.Info("YangToDb_acl_ip_protocol_xfmr: ", inParams.ygRoot, " Xpath: ", inParams.uri, " ethertypeType: ", ethertypeType) var b bytes.Buffer @@ -334,6 +342,10 @@ var YangToDb_acl_ip_protocol_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) res_map := make(map[string]string) var err error + if inParams.param == nil { + res_map["IP_PROTOCOL"] = "" + return res_map, err + } protocolType := reflect.TypeOf(inParams.param).Elem() log.Info("YangToDb_acl_ip_protocol_xfmr: ", inParams.ygRoot, " Xpath: ", inParams.uri, " protocolType: ", protocolType) switch protocolType { @@ -364,6 +376,10 @@ var DbToYang_acl_ip_protocol_xfmr FieldXfmrDbtoYang = func(inParams XfmrParams) var YangToDb_acl_source_port_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { res_map := make(map[string]string) var err error + if inParams.param == nil { + res_map["L4_SRC_PORT"] = "" + return res_map, err + } sourceportType := reflect.TypeOf(inParams.param).Elem() log.Info("YangToDb_acl_ip_protocol_xfmr: ", inParams.ygRoot, " Xpath: ", inParams.uri, " sourceportType: ", sourceportType) switch sourceportType { @@ -414,6 +430,10 @@ var DbToYang_acl_source_port_xfmr FieldXfmrDbtoYang = func(inParams XfmrParams) var YangToDb_acl_destination_port_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { res_map := make(map[string]string) var err error + if inParams.param == nil { + res_map["L4_DST_PORT_RANGE"] = "" + return res_map, err + } destportType := reflect.TypeOf(inParams.param).Elem() log.Info("YangToDb_acl_ip_protocol_xfmr: ", inParams.ygRoot, " Xpath: ", inParams.uri, " destportType: ", destportType) switch destportType { @@ -435,9 +455,9 @@ var YangToDb_acl_destination_port_xfmr FieldXfmrYangToDb = func(inParams XfmrPar var DbToYang_acl_destination_port_xfmr FieldXfmrDbtoYang = func(inParams XfmrParams) (map[string]interface{}, error) { var err error + result := make(map[string]interface{}) data := (*inParams.dbDataMap)[inParams.curDb] log.Info("DbToYang_acl_destination_port_xfmr: ", data, inParams.ygRoot) - result := make(map[string]interface{}) if _, ok := data[RULE_TABLE]; !ok { err = errors.New("RULE_TABLE entry not found in the input param") return result, err @@ -463,8 +483,14 @@ var DbToYang_acl_destination_port_xfmr FieldXfmrDbtoYang = func(inParams XfmrPar var YangToDb_acl_tcp_flags_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { res_map := make(map[string]string) var err error - log.Info("YangToDb_acl_tcp_flags_xfmr: ", inParams.ygRoot, inParams.uri) + log.Info("YangToDb_acl_tcp_flags_xfmr: ") var tcpFlags uint32 = 0x00 + var b bytes.Buffer + if inParams.param == nil { + res_map["TCP_FLAGS"] = b.String() + return res_map, err + } + log.Info("YangToDb_acl_tcp_flags_xfmr: ", inParams.ygRoot, inParams.uri) v := reflect.ValueOf(inParams.param) flags := v.Interface().([]ocbinds.E_OpenconfigPacketMatchTypes_TCP_FLAGS) @@ -497,7 +523,6 @@ var YangToDb_acl_tcp_flags_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (m break } } - var b bytes.Buffer fmt.Fprintf(&b, "0x%0.2x/0x%0.2x", tcpFlags, tcpFlags) res_map["TCP_FLAGS"] = b.String() return res_map, err diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index dba137508b..926327f5bf 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -295,19 +295,19 @@ func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, for _, key := range jData.MapKeys() { typeOfValue := reflect.TypeOf(jData.MapIndex(key).Interface()).Kind() - if typeOfValue == reflect.Map || typeOfValue == reflect.Slice { - log.Info("slice/map data: key(\"%v\"), xpathPrefix(\"%v\").", keyName, xpathPrefix) - xpath := uri - curUri := uri - pathAttr := key.String() - if len(xpathPrefix) > 0 { - if strings.Contains(pathAttr, ":") { - pathAttr = strings.Split(pathAttr, ":")[1] - } - xpath = xpathPrefix + "/" + pathAttr - curUri = uri + "/" + pathAttr + log.Info("slice/map data: key(\"%v\"), xpathPrefix(\"%v\").", keyName, xpathPrefix) + xpath := uri + curUri := uri + pathAttr := key.String() + if len(xpathPrefix) > 0 { + if strings.Contains(pathAttr, ":") { + pathAttr = strings.Split(pathAttr, ":")[1] } + xpath = xpathPrefix + "/" + pathAttr + curUri = uri + "/" + pathAttr + } + if (typeOfValue == reflect.Map || typeOfValue == reflect.Slice) && xSpecMap[xpath].yangDataType != "leaf-list" { if xSpecMap[xpath] != nil && len(xSpecMap[xpath].xfmrFunc) > 0 { /* subtree transformer present */ inParams := formXfmrInputRequest(d, dbs, db.MaxDB, ygRoot, curUri, oper, "", nil, nil) From 17787ff91aadc173345bf823108b79aa80de4aad Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Thu, 12 Sep 2019 17:37:32 -0700 Subject: [PATCH 120/214] Fix top level delete --- src/translib/transformer/xlate_to_db.go | 48 ++++++++++++++----------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index 926327f5bf..7bc9752abd 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -180,27 +180,33 @@ func directDbMapData(tableName string, jsonData interface{}, result map[string]m /* Get the db table, key and field name for the incoming delete request */ func dbMapDelete(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string, jsonData interface{}, result map[string]map[string]db.Value) error { - var err error - if isCvlYang(path) { - xpathPrefix, keyName, tableName := sonicXpathKeyExtract(path) - log.Info("Delete req: path(\"%v\"), key(\"%v\"), xpathPrefix(\"%v\"), tableName(\"%v\").", path, keyName, xpathPrefix, tableName) - err = cvlYangReqToDbMapDelete(xpathPrefix, tableName, keyName, result) - } else { - xpathPrefix, keyName, tableName := xpathKeyExtract(d, ygRoot, oper, path) - log.Info("Delete req: path(\"%v\"), key(\"%v\"), xpathPrefix(\"%v\"), tableName(\"%v\").", path, keyName, xpathPrefix, tableName) - spec, ok := xSpecMap[xpathPrefix] - if ok && spec.tableName != nil { - result[*spec.tableName] = make(map[string]db.Value) - if len(keyName) > 0 { - result[*spec.tableName][keyName] = db.Value{Field: make(map[string]string)} - if spec.yangEntry != nil && spec.yangEntry.Node.Statement().Keyword == "leaf" { - result[*spec.tableName][keyName].Field[spec.fieldName] = "" - } - } - } - } - log.Info("Delete req: path(\"%v\") result(\"%v\").", path, result) - return err + var err error + if isCvlYang(path) { + xpathPrefix, keyName, tableName := sonicXpathKeyExtract(path) + log.Info("Delete req: path(\"%v\"), key(\"%v\"), xpathPrefix(\"%v\"), tableName(\"%v\").", path, keyName, xpathPrefix, tableName) + err = cvlYangReqToDbMapDelete(xpathPrefix, tableName, keyName, result) + } else { + xpathPrefix, keyName, tableName := xpathKeyExtract(d, ygRoot, oper, path) + log.Info("Delete req: path(\"%v\"), key(\"%v\"), xpathPrefix(\"%v\"), tableName(\"%v\").", path, keyName, xpathPrefix, tableName) + spec, ok := xSpecMap[xpathPrefix] + if ok { + if spec.tableName != nil { + result[*spec.tableName] = make(map[string]db.Value) + if len(keyName) > 0 { + result[*spec.tableName][keyName] = db.Value{Field: make(map[string]string)} + if spec.yangEntry != nil && spec.yangEntry.Node.Statement().Keyword == "leaf" { + result[*spec.tableName][keyName].Field[spec.fieldName] = "" + } + } + } else if len(spec.childTable) > 0 { + for _, child := range spec.childTable { + result[child] = make(map[string]db.Value) + } + } + } + } + log.Info("Delete req: path(\"%v\") result(\"%v\").", path, result) + return err } func cvlYangReqToDbMapDelete(xpathPrefix string, tableName string, keyName string, result map[string]map[string]db.Value) error { From e79b679d270e6cc328598b4db981a9e03d1e7ef6 Mon Sep 17 00:00:00 2001 From: s-mari Date: Fri, 13 Sep 2019 10:30:00 -0700 Subject: [PATCH 121/214] added yang annotations --- .../annotations/openconfig-acl-annot.yang | 58 ++++++++++++++++++- src/translib/transformer/xlate_from_db.go | 4 +- 2 files changed, 58 insertions(+), 4 deletions(-) diff --git a/models/yang/annotations/openconfig-acl-annot.yang b/models/yang/annotations/openconfig-acl-annot.yang index b24d3f41c8..f6a9cb5032 100644 --- a/models/yang/annotations/openconfig-acl-annot.yang +++ b/models/yang/annotations/openconfig-acl-annot.yang @@ -1,5 +1,5 @@ module openconfig-acl-annot { - + yang-version "1"; namespace "http://openconfig.net/yang/annotation"; @@ -34,6 +34,24 @@ module openconfig-acl-annot { } } + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:state/oc-acl:name { + deviate add { + sonic-ext:field-transformer "acl_set_name_xfmr"; + } + } + + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:state/oc-acl:type { + deviate add { + sonic-ext:field-transformer "acl_type_field_xfmr"; + } + } + + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:state/oc-acl:description { + deviate add { + sonic-ext:field-name "policy_desc"; + } + } + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry { deviate add { sonic-ext:table-name "ACL_RULE"; @@ -75,7 +93,25 @@ module openconfig-acl-annot { deviate add { sonic-ext:field-transformer "acl_ip_protocol_xfmr"; } - } + } + + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-pkt-match:ipv4/oc-pkt-match:state/oc-pkt-match:source-address { + deviate add { + sonic-ext:field-name "SRC_IP"; + } + } + + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-pkt-match:ipv4/oc-pkt-match:state/oc-pkt-match:destination-address { + deviate add { + sonic-ext:field-name "DST_IP"; + } + } + + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-pkt-match:ipv4/oc-pkt-match:state/oc-pkt-match:protocol { + deviate add { + sonic-ext:field-transformer "acl_ip_protocol_xfmr"; + } + } deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-pkt-match:ipv6/oc-pkt-match:config/oc-pkt-match:source-address { deviate add { @@ -107,6 +143,18 @@ module openconfig-acl-annot { } } + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-pkt-match:transport/oc-pkt-match:state/oc-pkt-match:source-port { + deviate add { + sonic-ext:field-transformer "acl_source_port_xfmr"; + } + } + + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-pkt-match:transport/oc-pkt-match:state/oc-pkt-match:destination-port { + deviate add { + sonic-ext:field-transformer "acl_destination_port_xfmr"; + } + } + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-pkt-match:transport/oc-pkt-match:config/oc-pkt-match:tcp-flags { deviate add { sonic-ext:field-transformer "acl_tcp_flags_xfmr"; @@ -125,6 +173,12 @@ module openconfig-acl-annot { } } + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-acl:actions/oc-acl:state/oc-acl:forwarding-action { + deviate add { + sonic-ext:field-name "PACKET_ACTION"; + } + } + deviation /oc-acl:acl/oc-acl:interfaces { deviate add { sonic-ext:subtree-transformer "acl_port_bindings_xfmr"; diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index 626371b58b..f95545004d 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -221,8 +221,8 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath yangListDataFill(dbs, ygRoot, chldUri, chldXpath, dbDataMap, resultMap, lTblName, "", cdb) } } - } else { - return err + } else if chldYangType == "leaf-list" { + //Handle leaf-list } } } From 7acd5c83dbe71a8a7399515d9b8075f3bfa8cce6 Mon Sep 17 00:00:00 2001 From: amrutasali Date: Fri, 13 Sep 2019 18:50:02 +0000 Subject: [PATCH 122/214] Get case - leaf-list support in Transformer core for Sonic and OC yang. --- src/translib/transformer/xlate_from_db.go | 139 +++++++++++++++++++--- 1 file changed, 123 insertions(+), 16 deletions(-) diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index f95545004d..504a19dde8 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -7,7 +7,9 @@ import ( "encoding/json" "os" "strconv" + "errors" "translib/ocbinds" + "github.com/openconfig/goyang/pkg/yang" "github.com/openconfig/ygot/ygot" "github.com/openconfig/ygot/ytypes" @@ -81,6 +83,84 @@ func validateHandlerFunc(inParams XfmrParams) (bool) { return ret[0].Interface().(bool) } +func DbValToInt(dbFldVal string, base int, size int, isUint bool) (interface{}, error) { + var res interface{} + var err error + if res, err = strconv.ParseInt(dbFldVal, base, size); err != nil { + log.Warning("Non Yint%v type for yang leaf-list item %v", size, dbFldVal) + } + return res, err +} + +func DbToYangType(yngTerminalNdDtType yang.TypeKind, fldXpath string, dbFldVal string) (interface{}, error) { + log.Infof("Received FieldXpath %v, yngTerminalNdDtType %v and Db field value %v to be converted to yang data-type.", fldXpath, yngTerminalNdDtType, dbFldVal) + var res interface{} + var err error + const INTBASE = 10 + switch yngTerminalNdDtType { + case yang.Ynone: + log.Warning("Yang node data-type is non base yang type") + //TODO - enhance to handle non base data types depending on future use case + err = errors.New("Yang node data-type is non base yang type") + case yang.Yint8: + res, err = DbValToInt(dbFldVal, INTBASE, 8, false) + case yang.Yint16: + res, err = DbValToInt(dbFldVal, INTBASE, 16, false) + case yang.Yint32: + res, err = DbValToInt(dbFldVal, INTBASE, 32, false) + case yang.Yint64: + res, err = DbValToInt(dbFldVal, INTBASE, 64, false) + case yang.Yuint8: + res, err = DbValToInt(dbFldVal, INTBASE, 8, true) + case yang.Yuint16: + res, err = DbValToInt(dbFldVal, INTBASE, 16, true) + case yang.Yuint32: + res, err = DbValToInt(dbFldVal, INTBASE, 32, true) + case yang.Yuint64: + res, err = DbValToInt(dbFldVal, INTBASE, 64, true) + case yang.Ybool: + if res, err = strconv.ParseBool(dbFldVal); err != nil { + log.Warning("Non Bool type for yang leaf-list item %v", dbFldVal) + } + //TODO enhance Yunion using yangEntry way + case yang.Yenum, yang.Ystring, yang.Yidentityref, yang.Yunion: + log.Info("Yenum/Ystring/Yunion(having all members as strings) type for yangXpath ", fldXpath) + res = dbFldVal + case yang.Yempty: + logStr := fmt.Sprintf("Yang data type for xpath %v is Yempty.", fldXpath) + log.Error(logStr) + err = errors.New(logStr) + default: + logStr := fmt.Sprintf("Unrecognized/Unhandled yang-data type(%v) for xpath %v.", fldXpath, yang.TypeKindToName[yngTerminalNdDtType]) + log.Error(logStr) + err = errors.New(logStr) + } + return res, err +} + +/*convert leaf-list in Db to leaf-list in yang*/ +func processLfLstDbToYang(fieldXpath string, dbFldVal string) []interface{} { + valLst := strings.Split(dbFldVal, ",") + var resLst []interface{} + const INTBASE = 10 + yngTerminalNdDtType := xDbSpecMap[fieldXpath].dbEntry.Type.Kind + switch yngTerminalNdDtType { + case yang.Yenum, yang.Ystring, yang.Yunion: + log.Info("DB leaf-list and Yang leaf-list are of same data-type") + for _, fldVal := range valLst { + resLst = append(resLst, fldVal) + } + default: + for _, fldVal := range valLst { + resVal, err := DbToYangType(yngTerminalNdDtType, fieldXpath, fldVal) + if err == nil { + resLst = append(resLst, resVal) + } + } + } + return resLst +} + /* Traverse db map and create json for cvl yang */ func directDbToYangJsonCreate(dbDataMap map[string]map[string]db.Value, jsonData string) string { for tblName, tblData := range dbDataMap { @@ -88,7 +168,25 @@ func directDbToYangJsonCreate(dbDataMap map[string]map[string]db.Value, jsonData for keyStr, dbFldValData := range tblData { fldValPair := "" for field, value := range dbFldValData.Field { - fldValPair += fmt.Sprintf("\"%v\" : \"%v\",\r\n", field, value) + if strings.HasSuffix(field, "@") { + fldVals := strings.Split(field, "@") + field = fldVals[0] + fieldXpath := tblName + "/" + field + if xDbSpecMap[fieldXpath].dbEntry.IsLeafList() { + resLst := processLfLstDbToYang(fieldXpath, value) + fldValPair += fmt.Sprintf("\"%v\" : \"%v\",\r\n", field, resLst) + continue + } + } else { + fieldXpath := tblName + "/" + field + yngTerminalNdDtType := xDbSpecMap[fieldXpath].dbEntry.Type.Kind + resVal, err := DbToYangType(yngTerminalNdDtType, fieldXpath, value) + if err != nil { + log.Warning("Failure in converting Db value type to yang type for field", field) + } else { + fldValPair += fmt.Sprintf("\"%v\" : \"%v\",\r\n", field, resVal) + } + } } yangKeys := yangKeyFromEntryGet(xDbSpecMap[tblName].dbEntry) fldValPair = keyJsonDataAdd(yangKeys, keyStr, fldValPair) @@ -165,7 +263,7 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath } chldYangType := yangTypeGet(xSpecMap[chldXpath].yangEntry) cdb = xSpecMap[chldXpath].dbIndex - if chldYangType == "leaf" { + if xSpecMap[chldXpath].yangEntry.IsLeaf() || xSpecMap[chldXpath].yangEntry.IsLeafList() { if len(xSpecMap[chldXpath].xfmrFunc) > 0 { _, key, _ := xpathKeyExtract(dbs[cdb], ygRoot, GET, chldUri) inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, chldUri, GET, key, dbDataMap, nil) @@ -178,19 +276,28 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath } } else { dbFldName := xSpecMap[chldXpath].fieldName + /* if there is no transformer extension/annotation then it means leaf-list in yang is also leaflist in db */ if len(dbFldName) > 0 && !xSpecMap[chldXpath].isKey { - val, ok := (*dbDataMap)[cdb][tbl][tblKey].Field[dbFldName] - if ok { - /* this will be enhanced to support all yang data types */ - yNode := xSpecMap[chldXpath] - yDataType := yNode.yangEntry.Type.Kind - if yDataType == Yuint8 { - valInt, _ := strconv.Atoi(val) - resultMap[xSpecMap[chldXpath].yangEntry.Name] = valInt - } else { - resultMap[yNode.yangEntry.Name] = val - } - } + if xSpecMap[chldXpath].yangEntry.IsLeafList() { + dbFldName += "@" + val, ok := (*dbDataMap)[cdb][tbl][tblKey].Field[dbFldName] + if ok { + resLst := processLfLstDbToYang(chldXpath, val) + resultMap[xSpecMap[chldXpath].yangEntry.Name] = resLst + } + } else { + val, ok := (*dbDataMap)[cdb][tbl][tblKey].Field[dbFldName] + if ok { + /* this will be enhanced to support all yang data types */ + yngTerminalNdDtType := xSpecMap[chldXpath].yangEntry.Type.Kind + resVal, err := DbToYangType(yngTerminalNdDtType, chldXpath, val) + if err != nil { + log.Warning("Failure in converting Db value type to yang type for field", chldXpath) + } else { + resultMap[xSpecMap[chldXpath].yangEntry.Name] = resVal + } + } + } } } } else if chldYangType == "container" { @@ -221,8 +328,8 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath yangListDataFill(dbs, ygRoot, chldUri, chldXpath, dbDataMap, resultMap, lTblName, "", cdb) } } - } else if chldYangType == "leaf-list" { - //Handle leaf-list + } else { + return err } } } From f569d661222b39149626777f6381c25890fe13da Mon Sep 17 00:00:00 2001 From: Kwan Kim Date: Fri, 13 Sep 2019 12:00:48 -0700 Subject: [PATCH 123/214] add the field transformer for forwarding-action --- .../annotations/openconfig-acl-annot.yang | 2 ++ src/translib/transformer/xfmr_acl.go | 31 +++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/models/yang/annotations/openconfig-acl-annot.yang b/models/yang/annotations/openconfig-acl-annot.yang index f6a9cb5032..877629b319 100644 --- a/models/yang/annotations/openconfig-acl-annot.yang +++ b/models/yang/annotations/openconfig-acl-annot.yang @@ -170,12 +170,14 @@ module openconfig-acl-annot { deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-acl:actions/oc-acl:config/oc-acl:forwarding-action { deviate add { sonic-ext:field-name "PACKET_ACTION"; + sonic-ext:field-transformer "acl_forwarding_action_xfmr"; } } deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set/oc-acl:acl-entries/oc-acl:acl-entry/oc-acl:actions/oc-acl:state/oc-acl:forwarding-action { deviate add { sonic-ext:field-name "PACKET_ACTION"; + sonic-ext:field-transformer "acl_forwarding_action_xfmr"; } } diff --git a/src/translib/transformer/xfmr_acl.go b/src/translib/transformer/xfmr_acl.go index 75acaf6382..03f6e8b662 100644 --- a/src/translib/transformer/xfmr_acl.go +++ b/src/translib/transformer/xfmr_acl.go @@ -35,6 +35,8 @@ func init() { XlateFuncBind("DbToYang_acl_tcp_flags_xfmr", DbToYang_acl_tcp_flags_xfmr) XlateFuncBind("YangToDb_acl_port_bindings_xfmr", YangToDb_acl_port_bindings_xfmr) XlateFuncBind("DbToYang_acl_port_bindings_xfmr", DbToYang_acl_port_bindings_xfmr) + XlateFuncBind("YangToDb_acl_forwarding_action_xfmr", YangToDb_acl_forwarding_action_xfmr) + XlateFuncBind("DbToYang_acl_forwarding_action_xfmr", DbToYang_acl_forwarding_action_xfmr) XlateFuncBind("validate_ipv4", validate_ipv4) XlateFuncBind("validate_ipv6", validate_ipv6) } @@ -61,6 +63,13 @@ var ACL_TYPE_MAP = map[string]string{ strconv.FormatInt(int64(ocbinds.OpenconfigAcl_ACL_TYPE_ACL_L2), 10): SONIC_ACL_TYPE_L2, } +/* E_OpenconfigAcl_FORWARDING_ACTION */ +var ACL_FORWARDING_ACTION_MAP = map[string]string{ + strconv.FormatInt(int64(ocbinds.OpenconfigAcl_FORWARDING_ACTION_ACCEPT), 10): "FORWARD", + strconv.FormatInt(int64(ocbinds.OpenconfigAcl_FORWARDING_ACTION_DROP), 10): "DROP", + strconv.FormatInt(int64(ocbinds.OpenconfigAcl_FORWARDING_ACTION_REJECT), 10): "REDIRECT", +} + /* E_OpenconfigPacketMatchTypes_IP_PROTOCOL */ var IP_PROTOCOL_MAP = map[string]string{ strconv.FormatInt(int64(ocbinds.OpenconfigPacketMatchTypes_IP_PROTOCOL_IP_ICMP), 10): "1", @@ -183,6 +192,28 @@ var validate_ipv6 ValidateCallpoint = func(inParams XfmrParams) (bool) { //////////////////////////////////////////// // Bi-directoonal overloaded methods //////////////////////////////////////////// +var YangToDb_acl_forwarding_action_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { + res_map := make(map[string]string) + var err error + if inParams.param == nil { + res_map["PACKET_ACTION"] = "" + return res_map, err + } + action, _ := inParams.param.(ocbinds.E_OpenconfigAcl_FORWARDING_ACTION) + log.Info("YangToDb_acl_forwarding_action_xfmr: ", inParams.ygRoot, " Xpath: ", inParams.uri, " forwarding_action: ", action) + res_map["PACKET_ACTION"] = findInMap(ACL_FORWARDING_ACTION_MAP, strconv.FormatInt(int64(action), 10)) + return res_map, err +} +var DbToYang_acl_forwarding_action_xfmr FieldXfmrDbtoYang = func(inParams XfmrParams) (map[string]interface{}, error) { + var err error + result := make(map[string]interface{}) + data := (*inParams.dbDataMap)[inParams.curDb] + log.Info("DbToYang_acl_forwarding_action_xfmr", data, inParams.ygRoot) + oc_action := findInMap(ACL_FORWARDING_ACTION_MAP, data[RULE_TABLE][inParams.key].Field["PACKET_ACTION"]) + n, err := strconv.ParseInt(oc_action, 10, 64) + result["forwarding-action"] = ocbinds.E_OpenconfigAcl_FORWARDING_ACTION(n).ΛMap()["E_OpenconfigAcl_FORWARDING_ACTION"][n].Name + return result, err +} var YangToDb_acl_type_field_xfmr FieldXfmrYangToDb = func(inParams XfmrParams) (map[string]string, error) { res_map := make(map[string]string) From b7f3b3389716e1ea2642fe020b4df8b1133de9f7 Mon Sep 17 00:00:00 2001 From: amrutasali Date: Fri, 13 Sep 2019 19:59:56 +0000 Subject: [PATCH 124/214] Set case - leaf-list support in transformer core for OC yang --- src/translib/transformer/xlate_to_db.go | 28 ++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index 7bc9752abd..84b0fc8f1a 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -100,9 +100,31 @@ func mapFillData(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, dbKey st return errors.New("Invalid field name") } fieldName := xpathInfo.fieldName - valueStr := fmt.Sprintf("%v", value) - if strings.Contains(valueStr, ":") { - valueStr = strings.Split(valueStr, ":")[1] + valueStr := "" + if xpathInfo.yangEntry.IsLeafList() { + /* Both yang side and Db side('@' suffix field) the data type is leaf-list */ + log.Info("Yang type iand Db type is Leaflist for field = ", xpath) + fieldName += "@" + if reflect.ValueOf(value).Kind() != reflect.Slice { + logStr := fmt.Sprintf("Value for yang xpath %v which is a leaf-list should be a slice", xpath) + log.Error(logStr) + err := errors.New(logStr) + return err + } + valData := reflect.ValueOf(value) + for fidx := 0; fidx < valData.Len(); fidx++ { + if fidx > 0 { + valueStr += "," + } + fVal := fmt.Sprintf("%v", valData.Index(fidx).Interface()) + valueStr = valueStr + fVal + } + + } else { // xpath is a leaf + valueStr := fmt.Sprintf("%v", value) + if strings.Contains(valueStr, ":") { + valueStr = strings.Split(valueStr, ":")[1] + } } dataToDBMapAdd(*xpathInfo.tableName, dbKey, result, fieldName, valueStr) From a3c4bbe829c0c8db4c6fd499850547b9bfc70420 Mon Sep 17 00:00:00 2001 From: s-mari Date: Fri, 13 Sep 2019 16:44:38 -0700 Subject: [PATCH 125/214] provision to get data for sibling container from the module level --- src/translib/transformer/xlate_from_db.go | 69 +++++++++++++++++------ 1 file changed, 51 insertions(+), 18 deletions(-) diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index f95545004d..f4d8193913 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -20,18 +20,20 @@ const ( Yuint8 = 5 ) -func xfmrHandlerFunc(inParams XfmrParams) (string, error) { +func xfmrHandlerFunc(inParams XfmrParams) (map[string]interface{}, error) { + result := make(map[string]interface{}) xpath, _ := RemoveXPATHPredicates(inParams.uri) + log.Info("Subtree transformer function(\"%v\") invoked for yang path(\"%v\").", xSpecMap[xpath].xfmrFunc, xpath) _, err := XlateFuncCall(dbToYangXfmrFunc(xSpecMap[xpath].xfmrFunc), inParams) if err != nil { - return "", err + log.Info("Failed to retrieve data for xpath(\"%v\") err(%v).", inParams.uri, err) + return result, err } ocbSch, _ := ocbinds.Schema() schRoot := ocbSch.RootSchema() device := (*inParams.ygRoot).(*ocbinds.Device) - log.Info("Subtree transformer function(\"%v\") invoked for yang path(\"%v\").", xSpecMap[xpath].xfmrFunc, xpath) path, _ := ygot.StringToPath(inParams.uri, ygot.StructuredPath, ygot.StringSlicePath) for _, p := range path.Elem { pathSlice := strings.Split(p.Name, ":") @@ -46,7 +48,8 @@ func xfmrHandlerFunc(inParams XfmrParams) (string, error) { nodeList, nErr := ytypes.GetNode(schRoot, device, path) if nErr != nil { - return "", nErr + log.Info("Failed to get node for xpath(\"%v\") err(%v).", inParams.uri, err) + return result, err } node := nodeList[0].Data nodeYgot, _:= (node).(ygot.ValidatedGoStruct) @@ -54,7 +57,8 @@ func xfmrHandlerFunc(inParams XfmrParams) (string, error) { Indent: " ", SkipValidation: true, RFC7951Config: &ygot.RFC7951JSONConfig{ AppendModuleName: false, }, }) - return payload, err + err = json.Unmarshal([]byte(payload), result) + return result, err } func leafXfmrHandlerFunc(inParams XfmrParams) (map[string]interface{}, string, error) { @@ -123,8 +127,12 @@ func yangListDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, x curKeyMap, curUri, _, _ := dbKeyToYangDataConvert(uri, xpath, dbKey) if len(xSpecMap[xpath].xfmrFunc) > 0 { inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, curUri, GET, "", dbDataMap, nil) - jsonStr, _ := xfmrHandlerFunc(inParams) - fmt.Printf("From leaf-xfmr(%v)\r\n", jsonStr) + cmap, _ := xfmrHandlerFunc(inParams) + if len(cmap) > 0 { + mapSlice = append(mapSlice, curMap) + } else { + log.Info("Empty container returned from overloaded transformer for(\"%v\")", curUri) + } } else { _, keyFromCurUri, _ := xpathKeyExtract(dbs[cdb], ygRoot, GET, curUri) if dbKey == keyFromCurUri { @@ -140,7 +148,7 @@ func yangListDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, x if len(mapSlice) > 0 { resultMap[xSpecMap[xpath].yangEntry.Name] = mapSlice } else { - fmt.Printf("Map slice is empty.\r\n ") + log.Info("Empty slice for (\"%v\").\r\n", uri) } } return nil @@ -171,7 +179,7 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, chldUri, GET, key, dbDataMap, nil) fldValMap, _, err := leafXfmrHandlerFunc(inParams) if err != nil { - return err + log.Info("Failed to get data(\"%v\").\r\n", chldUri) } for lf, val := range fldValMap { resultMap[lf] = val @@ -194,26 +202,34 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath } } } else if chldYangType == "container" { + cname := xSpecMap[chldXpath].yangEntry.Name if len(xSpecMap[chldXpath].xfmrFunc) > 0 { inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, chldUri, GET, "", dbDataMap, nil) - jsonStr, _ := xfmrHandlerFunc(inParams) - fmt.Printf("From container-xfmr(%v)\r\n", jsonStr) + cmap, _ := xfmrHandlerFunc(inParams) + if len(cmap) > 0 { + resultMap[cname] = cmap + } else { + log.Info("Empty container(\"%v\").\r\n", chldUri) + } } else { - cname := xSpecMap[chldXpath].yangEntry.Name cmap := make(map[string]interface{}) err = yangDataFill(dbs, ygRoot, chldUri, chldXpath, dbDataMap, cmap, tbl, tblKey, cdb) if len(cmap) > 0 { resultMap[cname] = cmap } else { - fmt.Printf("container : empty(%v) \r\n", cname) + log.Info("Empty container(\"%v\").\r\n", chldUri) } } } else if chldYangType == "list" { - cdb = xSpecMap[chldXpath].dbIndex + cdb = xSpecMap[chldXpath].dbIndex if len(xSpecMap[chldXpath].xfmrFunc) > 0 { - inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, chldUri, GET, "", dbDataMap, nil) - jsonStr , _ := xfmrHandlerFunc(inParams) - fmt.Printf("From list-xfmr(%v)\r\n", jsonStr) + inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, chldUri, GET, "", dbDataMap, nil) + cmap, _ := xfmrHandlerFunc(inParams) + if len(cmap) > 0 { + resultMap = cmap + } else { + log.Info("Empty list(\"%v\").\r\n", chldUri) + } } else { ynode, ok := xSpecMap[chldXpath] if ok && ynode.tableName != nil { @@ -250,7 +266,24 @@ func dbDataToYangJsonCreate(uri string, ygRoot *ygot.GoStruct, dbs [db.MaxDB]*db tbl, key, _ := tableNameAndKeyFromDbMapGet((*dbDataMap)[cdb]) jsonData = fmt.Sprintf("{\r\n \"%v\" : \"%v\" \r\n }\r\n", xSpecMap[reqXpath].yangEntry.Name, (*dbDataMap)[cdb][tbl][key].Field[fldName]) - return jsonData, nil + resultMap[fldName] = (*dbDataMap)[cdb][tbl][key].Field[fldName] + } else if yangType == "container" { + cname := xSpecMap[reqXpath].yangEntry.Name + cmap := make(map[string]interface{}) + if len(xSpecMap[reqXpath].xfmrFunc) > 0 { + inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, uri, GET, "", dbDataMap, nil) + cmap, _ = xfmrHandlerFunc(inParams) + if len(cmap) > 0 { + resultMap[cname] = cmap + } else { + log.Info("Empty container(\"%v\").\r\n", uri) + } + } else { + err := yangDataFill(dbs, ygRoot, uri, reqXpath, dbDataMap, resultMap, tableName, keyName, cdb) + if err != nil { + log.Info("Empty container(\"%v\").\r\n", uri) + } + } } else { yangDataFill(dbs, ygRoot, uri, reqXpath, dbDataMap, resultMap, tableName, keyName, cdb) } From fd1ca1a5cb906c3d00835dbcdbc6a092b65321cd Mon Sep 17 00:00:00 2001 From: amrutasali Date: Sat, 14 Sep 2019 06:33:39 +0000 Subject: [PATCH 126/214] Fixed variable scope issue while processing leaf data to redis DB format --- src/translib/transformer/xlate_to_db.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index 84b0fc8f1a..f2dd96ad95 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -103,7 +103,7 @@ func mapFillData(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, dbKey st valueStr := "" if xpathInfo.yangEntry.IsLeafList() { /* Both yang side and Db side('@' suffix field) the data type is leaf-list */ - log.Info("Yang type iand Db type is Leaflist for field = ", xpath) + log.Info("Yang type and Db type is Leaflist for field = ", xpath) fieldName += "@" if reflect.ValueOf(value).Kind() != reflect.Slice { logStr := fmt.Sprintf("Value for yang xpath %v which is a leaf-list should be a slice", xpath) @@ -119,9 +119,10 @@ func mapFillData(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, dbKey st fVal := fmt.Sprintf("%v", valData.Index(fidx).Interface()) valueStr = valueStr + fVal } + log.Infof("leaf-list value after conversion to DB format %v : %v", fieldName, valueStr) } else { // xpath is a leaf - valueStr := fmt.Sprintf("%v", value) + valueStr = fmt.Sprintf("%v", value) if strings.Contains(valueStr, ":") { valueStr = strings.Split(valueStr, ":")[1] } From 97ffbddee07b96e5778b93d74b73244b617cccc0 Mon Sep 17 00:00:00 2001 From: Prabhu Sreenivasan Date: Tue, 17 Sep 2019 05:29:50 -0700 Subject: [PATCH 127/214] fix license header --- Makefile | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index d2f9b1fe07..d7b93967ea 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,21 @@ -####################################################################### -# -# Copyright 2019 Broadcom. All rights reserved. -# The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. -# -####################################################################### +################################################################################ +# # +# Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or # +# its subsidiaries. # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); # +# you may not use this file except in compliance with the License. # +# You may obtain a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +# # +################################################################################ .PHONY: all clean cleanall codegen rest-server rest-clean yamlGen cli From e1721a3045b7575570d6488f5188a168078e2758 Mon Sep 17 00:00:00 2001 From: Sachin Holla Date: Tue, 17 Sep 2019 06:18:13 -0700 Subject: [PATCH 128/214] Updated license statement for REST server sources --- models/Makefile | 24 ++++++++++++++----- models/yang/Makefile | 24 ++++++++++++++----- src/rest/Makefile | 24 ++++++++++++++----- src/rest/main/main.go | 24 ++++++++++++++----- src/rest/main/main_test.go | 19 +++++++++++++++ src/rest/server/context.go | 24 ++++++++++++++----- src/rest/server/context_test.go | 24 ++++++++++++++----- src/rest/server/error.go | 24 ++++++++++++++----- src/rest/server/error_test.go | 24 ++++++++++++++----- src/rest/server/handler.go | 24 ++++++++++++++----- src/rest/server/handler_test.go | 24 ++++++++++++++----- src/rest/server/pamAuth.go | 19 +++++++++++++++ src/rest/server/pamAuth_test.go | 23 ++++++++++++++---- src/rest/server/req_validate.go | 24 ++++++++++++++----- src/rest/server/router.go | 24 ++++++++++++++----- .../go-server/src/swagger/routes.go | 23 ++++++++++++++---- 16 files changed, 290 insertions(+), 82 deletions(-) diff --git a/models/Makefile b/models/Makefile index fa432ca938..8f542e905d 100644 --- a/models/Makefile +++ b/models/Makefile @@ -1,9 +1,21 @@ -####################################################################### -# -# Copyright 2019 Broadcom. All rights reserved. -# The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. -# -####################################################################### +################################################################################ +# # +# Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or # +# its subsidiaries. # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); # +# you may not use this file except in compliance with the License. # +# You may obtain a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +# # +################################################################################ TOPDIR := .. ABS_TOPDIR := $(abspath $(TOPDIR)) diff --git a/models/yang/Makefile b/models/yang/Makefile index 721feecb21..228fa75751 100644 --- a/models/yang/Makefile +++ b/models/yang/Makefile @@ -1,9 +1,21 @@ -####################################################################### -# -# Copyright 2019 Broadcom. All rights reserved. -# The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. -# -####################################################################### +################################################################################ +# # +# Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or # +# its subsidiaries. # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); # +# you may not use this file except in compliance with the License. # +# You may obtain a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +# # +################################################################################ TOPDIR := ../.. BUILD_DIR := $(TOPDIR)/build diff --git a/src/rest/Makefile b/src/rest/Makefile index 1eb352a88d..9f1e4c6ff1 100644 --- a/src/rest/Makefile +++ b/src/rest/Makefile @@ -1,9 +1,21 @@ -####################################################################### -# -# Copyright 2019 Broadcom. All rights reserved. -# The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. -# -####################################################################### +################################################################################ +# # +# Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or # +# its subsidiaries. # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); # +# you may not use this file except in compliance with the License. # +# You may obtain a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +# # +################################################################################ TOPDIR ?= ../.. ABS_TOPDIR ?= $(abspath $(TOPDIR)) diff --git a/src/rest/main/main.go b/src/rest/main/main.go index 1c69290d38..e44056c733 100644 --- a/src/rest/main/main.go +++ b/src/rest/main/main.go @@ -1,9 +1,21 @@ -/////////////////////////////////////////////////////////////////////// -// -// Copyright 2019 Broadcom. All rights reserved. -// The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. -// -/////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// package main diff --git a/src/rest/main/main_test.go b/src/rest/main/main_test.go index 2ab6a40702..50ee1010da 100644 --- a/src/rest/main/main_test.go +++ b/src/rest/main/main_test.go @@ -1,3 +1,22 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// + package main import ( diff --git a/src/rest/server/context.go b/src/rest/server/context.go index 2a7b4eb292..883679e343 100644 --- a/src/rest/server/context.go +++ b/src/rest/server/context.go @@ -1,9 +1,21 @@ -/////////////////////////////////////////////////////////////////////// -// -// Copyright 2019 Broadcom. All rights reserved. -// The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. -// -/////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// package server diff --git a/src/rest/server/context_test.go b/src/rest/server/context_test.go index d4635e9668..1df7fc3857 100644 --- a/src/rest/server/context_test.go +++ b/src/rest/server/context_test.go @@ -1,9 +1,21 @@ -/////////////////////////////////////////////////////////////////////// -// -// Copyright 2019 Broadcom. All rights reserved. -// The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. -// -/////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// package server diff --git a/src/rest/server/error.go b/src/rest/server/error.go index 3b05140975..0335e70eac 100644 --- a/src/rest/server/error.go +++ b/src/rest/server/error.go @@ -1,9 +1,21 @@ -/////////////////////////////////////////////////////////////////////// -// -// Copyright 2019 Broadcom. All rights reserved. -// The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. -// -/////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// package server diff --git a/src/rest/server/error_test.go b/src/rest/server/error_test.go index 9ae5857dc8..7dfdfce3df 100644 --- a/src/rest/server/error_test.go +++ b/src/rest/server/error_test.go @@ -1,9 +1,21 @@ -/////////////////////////////////////////////////////////////////////// -// -// Copyright 2019 Broadcom. All rights reserved. -// The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. -// -/////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// package server diff --git a/src/rest/server/handler.go b/src/rest/server/handler.go index 7b8c1eb036..5596c310f9 100644 --- a/src/rest/server/handler.go +++ b/src/rest/server/handler.go @@ -1,9 +1,21 @@ -/////////////////////////////////////////////////////////////////////// -// -// Copyright 2019 Broadcom. All rights reserved. -// The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. -// -/////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// package server diff --git a/src/rest/server/handler_test.go b/src/rest/server/handler_test.go index eac69616c4..16e1ca21f5 100644 --- a/src/rest/server/handler_test.go +++ b/src/rest/server/handler_test.go @@ -1,9 +1,21 @@ -/////////////////////////////////////////////////////////////////////// -// -// Copyright 2019 Broadcom. All rights reserved. -// The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. -// -/////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// package server diff --git a/src/rest/server/pamAuth.go b/src/rest/server/pamAuth.go index d726d35229..4ad9f0180e 100644 --- a/src/rest/server/pamAuth.go +++ b/src/rest/server/pamAuth.go @@ -1,3 +1,22 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// + package server import ( diff --git a/src/rest/server/pamAuth_test.go b/src/rest/server/pamAuth_test.go index 3726d895ce..d3015ea09d 100644 --- a/src/rest/server/pamAuth_test.go +++ b/src/rest/server/pamAuth_test.go @@ -1,8 +1,21 @@ -/////////////////////////////////////////////////////////////////////// -// -// Copyright 2019 Broadcom. All rights reserved. -// The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. -// +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// // // Test cases for REST Server PAM Authentication module. // diff --git a/src/rest/server/req_validate.go b/src/rest/server/req_validate.go index d5a394f867..4571d8a100 100644 --- a/src/rest/server/req_validate.go +++ b/src/rest/server/req_validate.go @@ -1,9 +1,21 @@ -/////////////////////////////////////////////////////////////////////// -// -// Copyright 2019 Broadcom. All rights reserved. -// The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. -// -/////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// package server diff --git a/src/rest/server/router.go b/src/rest/server/router.go index 6442213965..aa01d193e5 100644 --- a/src/rest/server/router.go +++ b/src/rest/server/router.go @@ -1,9 +1,21 @@ -/////////////////////////////////////////////////////////////////////// -// -// Copyright 2019 Broadcom. All rights reserved. -// The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. -// -/////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// package server diff --git a/tools/swagger_codegen/go-server/src/swagger/routes.go b/tools/swagger_codegen/go-server/src/swagger/routes.go index f21baa80f2..ce305b72aa 100644 --- a/tools/swagger_codegen/go-server/src/swagger/routes.go +++ b/tools/swagger_codegen/go-server/src/swagger/routes.go @@ -1,8 +1,21 @@ -/////////////////////////////////////////////////// -// -// Copyright 2019 Broadcom Inc. -// -/////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// package swagger From 6f63b84d020a54a9acfbf2b71bcabb5f49a2cd27 Mon Sep 17 00:00:00 2001 From: Partha Dutta Date: Tue, 17 Sep 2019 19:40:36 +0530 Subject: [PATCH 129/214] Update license header --- src/cvl/Makefile | 19 +++++++++++++++++++ src/cvl/cvl.go | 19 +++++++++++++++++++ src/cvl/cvl_api.go | 19 +++++++++++++++++++ src/cvl/cvl_luascript.go | 19 +++++++++++++++++++ src/cvl/cvl_test.go | 19 +++++++++++++++++++ src/cvl/internal/util/util.go | 19 +++++++++++++++++++ src/cvl/internal/yparser/yparser.go | 19 +++++++++++++++++++ src/cvl/jsondata_test.go | 19 +++++++++++++++++++ src/cvl/schema/Makefile | 19 +++++++++++++++++++ src/cvl/tests/Makefile | 19 +++++++++++++++++++ src/cvl/tests/cfg_validator.go | 19 +++++++++++++++++++ src/cvl/tests/cv_acl.go | 19 +++++++++++++++++++ src/cvl/tests/cv_edit_op.go | 19 +++++++++++++++++++ src/cvl/tests/cv_vlan.go | 19 +++++++++++++++++++ 14 files changed, 266 insertions(+) diff --git a/src/cvl/Makefile b/src/cvl/Makefile index 4f85259fc4..658ca0cf06 100644 --- a/src/cvl/Makefile +++ b/src/cvl/Makefile @@ -1,3 +1,22 @@ +################################################################################ +# # +# Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or # +# its subsidiaries. # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); # +# you may not use this file except in compliance with the License. # +# You may obtain a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +# # +################################################################################ + all: precheck deps schema tests GO?=/usr/local/go/bin/go SRC_FILES=$(shell find . -name '*.go' | grep -v '_test.go' | grep -v '/tests/') diff --git a/src/cvl/cvl.go b/src/cvl/cvl.go index f90486ecd9..7701372c7f 100644 --- a/src/cvl/cvl.go +++ b/src/cvl/cvl.go @@ -1,3 +1,22 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// + package cvl import ( "fmt" diff --git a/src/cvl/cvl_api.go b/src/cvl/cvl_api.go index 26bc6ea7f7..83b6842519 100644 --- a/src/cvl/cvl_api.go +++ b/src/cvl/cvl_api.go @@ -1,3 +1,22 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// + package cvl import ( diff --git a/src/cvl/cvl_luascript.go b/src/cvl/cvl_luascript.go index ac94c04db5..fd4c863ad1 100644 --- a/src/cvl/cvl_luascript.go +++ b/src/cvl/cvl_luascript.go @@ -1,3 +1,22 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// + package cvl import ( "github.com/go-redis/redis" diff --git a/src/cvl/cvl_test.go b/src/cvl/cvl_test.go index 74d51df3d0..3f5b0b3904 100644 --- a/src/cvl/cvl_test.go +++ b/src/cvl/cvl_test.go @@ -1,3 +1,22 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// + package cvl_test import ( diff --git a/src/cvl/internal/util/util.go b/src/cvl/internal/util/util.go index b57f8f1141..7404500d04 100644 --- a/src/cvl/internal/util/util.go +++ b/src/cvl/internal/util/util.go @@ -1,3 +1,22 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// + package util import ( diff --git a/src/cvl/internal/yparser/yparser.go b/src/cvl/internal/yparser/yparser.go index d08f66c702..2bc208fedf 100644 --- a/src/cvl/internal/yparser/yparser.go +++ b/src/cvl/internal/yparser/yparser.go @@ -1,3 +1,22 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// + package yparser /* Yang parser using libyang library */ diff --git a/src/cvl/jsondata_test.go b/src/cvl/jsondata_test.go index 65adaa8200..592ef71268 100644 --- a/src/cvl/jsondata_test.go +++ b/src/cvl/jsondata_test.go @@ -1,3 +1,22 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// + package cvl_test var json_edit_config_create_acl_table_dependent_data = []string{`{ diff --git a/src/cvl/schema/Makefile b/src/cvl/schema/Makefile index 1408bb1f58..8cd6016f0b 100644 --- a/src/cvl/schema/Makefile +++ b/src/cvl/schema/Makefile @@ -1,3 +1,22 @@ +################################################################################ +# # +# Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or # +# its subsidiaries. # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); # +# you may not use this file except in compliance with the License. # +# You may obtain a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +# # +################################################################################ + src_files=$(wildcard *.yang) out=$(patsubst %.yang, %.yin, $(src_files)) out_ext=$(patsubst %.yang, %.tree, $(src_files)) diff --git a/src/cvl/tests/Makefile b/src/cvl/tests/Makefile index 36ddbc1a33..3dda07a255 100644 --- a/src/cvl/tests/Makefile +++ b/src/cvl/tests/Makefile @@ -1,3 +1,22 @@ +################################################################################ +# # +# Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or # +# its subsidiaries. # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); # +# you may not use this file except in compliance with the License. # +# You may obtain a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +# # +################################################################################ + SRC_FILES=$(wildcard *.go) OUT=$(patsubst %.go, %, $(SRC_FILES)) TOPDIR := $(abspath ../../..) diff --git a/src/cvl/tests/cfg_validator.go b/src/cvl/tests/cfg_validator.go index b7be94fe89..f5a532da95 100644 --- a/src/cvl/tests/cfg_validator.go +++ b/src/cvl/tests/cfg_validator.go @@ -1,3 +1,22 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// + package main import ( diff --git a/src/cvl/tests/cv_acl.go b/src/cvl/tests/cv_acl.go index 0bb61e0478..cb12c0109b 100644 --- a/src/cvl/tests/cv_acl.go +++ b/src/cvl/tests/cv_acl.go @@ -1,3 +1,22 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// + package main import ( diff --git a/src/cvl/tests/cv_edit_op.go b/src/cvl/tests/cv_edit_op.go index 6eb65fa67f..a9035bcf51 100644 --- a/src/cvl/tests/cv_edit_op.go +++ b/src/cvl/tests/cv_edit_op.go @@ -1,3 +1,22 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// + package main import ( diff --git a/src/cvl/tests/cv_vlan.go b/src/cvl/tests/cv_vlan.go index d3e13c42dc..b230e86b5a 100644 --- a/src/cvl/tests/cv_vlan.go +++ b/src/cvl/tests/cv_vlan.go @@ -1,3 +1,22 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// + package main From 31b70f2ad7aad4f032dbcfd763c1e573c3a5952a Mon Sep 17 00:00:00 2001 From: Faraaz Mohammed Date: Tue, 17 Sep 2019 19:56:05 +0530 Subject: [PATCH 130/214] update broadcom license for pyang plugin for openAPI --- tools/pyang/pyang_plugins/openapi.py | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/tools/pyang/pyang_plugins/openapi.py b/tools/pyang/pyang_plugins/openapi.py index 649cb7e975..45a407d88d 100644 --- a/tools/pyang/pyang_plugins/openapi.py +++ b/tools/pyang/pyang_plugins/openapi.py @@ -1,6 +1,21 @@ -## Open Api Spec output plugin(swagger 2.0) -## Author: Mohammed Faraaz C -## Company: Broadcom Inc. +################################################################################ +# # +# Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or # +# its subsidiaries. # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); # +# you may not use this file except in compliance with the License. # +# You may obtain a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +# # +################################################################################ import optparse import sys From ae3ddf517ded00edfaca6b7d99f2486901d6fd6e Mon Sep 17 00:00:00 2001 From: Mayank Maheshwari Date: Tue, 17 Sep 2019 22:12:05 +0530 Subject: [PATCH 131/214] Updated License statement --- src/translib/acl_app.go | 24 ++++++++++++++++++------ src/translib/acl_app_test.go | 19 +++++++++++++++++++ src/translib/app_utils.go | 24 ++++++++++++++++++------ src/translib/nonyang_app.go.demo | 24 ++++++++++++++++++------ src/translib/path_utils.go | 24 ++++++++++++++++++------ src/translib/path_utils_test.go | 19 +++++++++++++++++++ src/translib/translib_test.go | 23 +++++++++++++++++++++-- 7 files changed, 131 insertions(+), 26 deletions(-) diff --git a/src/translib/acl_app.go b/src/translib/acl_app.go index f7e94af58f..0678cde7aa 100644 --- a/src/translib/acl_app.go +++ b/src/translib/acl_app.go @@ -1,9 +1,21 @@ -/////////////////////////////////////////////////////////////////////// -// -// Copyright 2019 Broadcom. All rights reserved. -// The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. -// -/////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// package translib diff --git a/src/translib/acl_app_test.go b/src/translib/acl_app_test.go index 88065982b8..d1773866ac 100644 --- a/src/translib/acl_app_test.go +++ b/src/translib/acl_app_test.go @@ -1,3 +1,22 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// + package translib import ( diff --git a/src/translib/app_utils.go b/src/translib/app_utils.go index 90875968f7..0fa8b66fd3 100644 --- a/src/translib/app_utils.go +++ b/src/translib/app_utils.go @@ -1,9 +1,21 @@ -/////////////////////////////////////////////////////////////////////// -// -// Copyright 2019 Broadcom. All rights reserved. -// The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. -// -/////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// package translib diff --git a/src/translib/nonyang_app.go.demo b/src/translib/nonyang_app.go.demo index 3e3a5f686e..17553ce328 100644 --- a/src/translib/nonyang_app.go.demo +++ b/src/translib/nonyang_app.go.demo @@ -1,9 +1,21 @@ -/////////////////////////////////////////////////////////////////////// -// -// Copyright 2019 Broadcom. All rights reserved. -// The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. -// -/////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// package translib diff --git a/src/translib/path_utils.go b/src/translib/path_utils.go index 8d12ecdfcd..bf7a35dcab 100644 --- a/src/translib/path_utils.go +++ b/src/translib/path_utils.go @@ -1,9 +1,21 @@ -/////////////////////////////////////////////////////////////////////// -// -// Copyright 2019 Broadcom. All rights reserved. -// The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. -// -/////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// package translib diff --git a/src/translib/path_utils_test.go b/src/translib/path_utils_test.go index 5379c00afa..e8d9c19b63 100644 --- a/src/translib/path_utils_test.go +++ b/src/translib/path_utils_test.go @@ -1,3 +1,22 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// + package translib import ( diff --git a/src/translib/translib_test.go b/src/translib/translib_test.go index 7d391757b2..9ceb1e1a80 100644 --- a/src/translib/translib_test.go +++ b/src/translib/translib_test.go @@ -1,10 +1,29 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// + package translib_test import ( "fmt" "path/filepath" - "runtime" "reflect" + "runtime" "testing" ) @@ -36,5 +55,5 @@ func equals(tb testing.TB, exp, act interface{}) { } func Test_Create(t *testing.T) { - + } From cafc7342009e291fb7079020558b555f1b90442d Mon Sep 17 00:00:00 2001 From: Anand Kumar Subramanian Date: Tue, 17 Sep 2019 12:20:38 -0700 Subject: [PATCH 132/214] Update broadcom license --- src/translib/app_interface.go | 24 ++++++++++++++++++------ src/translib/subscribe.go | 23 ++++++++++++++++++----- src/translib/test/translibtest.go | 19 +++++++++++++++++++ src/translib/translib.go | 26 ++++++++++++++++++-------- 4 files changed, 73 insertions(+), 19 deletions(-) diff --git a/src/translib/app_interface.go b/src/translib/app_interface.go index a64d568065..0a8b477403 100644 --- a/src/translib/app_interface.go +++ b/src/translib/app_interface.go @@ -1,8 +1,21 @@ -/////////////////////////////////////////////////// -// -// Copyright 2019 Broadcom Inc. -// -/////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// /* Package translib defines the interface for all the app modules @@ -12,7 +25,6 @@ It exposes register function for all the app modules to register It stores all the app module information in a map and presents it to the tranlib infra when it asks for the same. - */ package translib diff --git a/src/translib/subscribe.go b/src/translib/subscribe.go index d48c9ac12d..a22e04c6e1 100644 --- a/src/translib/subscribe.go +++ b/src/translib/subscribe.go @@ -1,8 +1,21 @@ -/////////////////////////////////////////////////// -// -// Copyright 2019 Broadcom Inc. -// -/////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// /* Package translib defines the functions to be used by the subscribe diff --git a/src/translib/test/translibtest.go b/src/translib/test/translibtest.go index 0d87d472d4..24450736b3 100644 --- a/src/translib/test/translibtest.go +++ b/src/translib/test/translibtest.go @@ -1,3 +1,22 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// + package main import ( diff --git a/src/translib/translib.go b/src/translib/translib.go index c482dc7567..3170128a21 100644 --- a/src/translib/translib.go +++ b/src/translib/translib.go @@ -1,8 +1,21 @@ -/////////////////////////////////////////////////// -// -// Copyright 2019 Broadcom Inc. -// -/////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// /* Package translib implements APIs like Create, Get, Subscribe etc. @@ -16,9 +29,6 @@ Redis ABNF format and persisting them in the Redis DB. It can also translate the ABNF format to YANG specific JSON IETF format This package can also talk to non-DB clients. - -Example: TBD - */ package translib From 16a13061d2b74c4e64b857b9a9b1b508b8ca7de4 Mon Sep 17 00:00:00 2001 From: Arun Barboza <29963827+a-barboza@users.noreply.github.com> Date: Tue, 17 Sep 2019 11:58:58 -0700 Subject: [PATCH 133/214] DB Access Layer: Update Broadcom License --- src/translib/db/db.go | 22 ++++++++++++++++++---- src/translib/db/db_test.go | 22 ++++++++++++++++++---- src/translib/db/map.go | 22 ++++++++++++++++++---- src/translib/db/subscribe.go | 22 ++++++++++++++++++---- src/translib/db/test/arloIssue29.go | 19 +++++++++++++++++++ src/translib/db/test/testdb.go | 19 +++++++++++++++++++ src/translib/db/test/testmap.go | 19 +++++++++++++++++++ src/translib/db/test/testsubscribe.go | 19 +++++++++++++++++++ 8 files changed, 148 insertions(+), 16 deletions(-) diff --git a/src/translib/db/db.go b/src/translib/db/db.go index 804718dc8d..451bc92383 100644 --- a/src/translib/db/db.go +++ b/src/translib/db/db.go @@ -1,7 +1,21 @@ -/* -Copyright 2019 Broadcom. All rights reserved. -The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. -*/ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// /* Package db implements a wrapper over the go-redis/redis. diff --git a/src/translib/db/db_test.go b/src/translib/db/db_test.go index 7f0030537b..edf05b281c 100644 --- a/src/translib/db/db_test.go +++ b/src/translib/db/db_test.go @@ -1,7 +1,21 @@ -/* -Copyright 2019 Broadcom. All rights reserved. -The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. -*/ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// package db diff --git a/src/translib/db/map.go b/src/translib/db/map.go index 63551b31c2..9010cfb15f 100644 --- a/src/translib/db/map.go +++ b/src/translib/db/map.go @@ -1,7 +1,21 @@ -/* -Copyright 2019 Broadcom. All rights reserved. -The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. -*/ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// /* Package db implements a wrapper over the go-redis/redis. diff --git a/src/translib/db/subscribe.go b/src/translib/db/subscribe.go index 145f6fee12..65ea09811e 100644 --- a/src/translib/db/subscribe.go +++ b/src/translib/db/subscribe.go @@ -1,7 +1,21 @@ -/* -Copyright 2019 Broadcom. All rights reserved. -The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. -*/ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// /* Package db implements a wrapper over the go-redis/redis. diff --git a/src/translib/db/test/arloIssue29.go b/src/translib/db/test/arloIssue29.go index 5299f4bf82..d42613d664 100644 --- a/src/translib/db/test/arloIssue29.go +++ b/src/translib/db/test/arloIssue29.go @@ -1,3 +1,22 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// + /* UT for https://github.com/project-arlo/sonic-mgmt-framework/issues/29 diff --git a/src/translib/db/test/testdb.go b/src/translib/db/test/testdb.go index 0756bac16e..c28b368e3a 100644 --- a/src/translib/db/test/testdb.go +++ b/src/translib/db/test/testdb.go @@ -1,3 +1,22 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// + package main import ( diff --git a/src/translib/db/test/testmap.go b/src/translib/db/test/testmap.go index 7a8c76f303..728b8842ac 100644 --- a/src/translib/db/test/testmap.go +++ b/src/translib/db/test/testmap.go @@ -1,3 +1,22 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// + package main import ( diff --git a/src/translib/db/test/testsubscribe.go b/src/translib/db/test/testsubscribe.go index 751fb3c75c..298bf3443a 100644 --- a/src/translib/db/test/testsubscribe.go +++ b/src/translib/db/test/testsubscribe.go @@ -1,3 +1,22 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// + package main import ( From 2a6f71864f5d835c77f10316398284211d0016e9 Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Tue, 17 Sep 2019 17:32:40 -0700 Subject: [PATCH 134/214] Add validate callback function support for acl. Children will inherit parent validate handler --- src/translib/transformer/xfmr_acl.go | 14 +++++--- src/translib/transformer/xlate_from_db.go | 44 +++++++++++++++-------- src/translib/transformer/xspec.go | 5 +++ 3 files changed, 44 insertions(+), 19 deletions(-) diff --git a/src/translib/transformer/xfmr_acl.go b/src/translib/transformer/xfmr_acl.go index 03f6e8b662..2c7216f1eb 100644 --- a/src/translib/transformer/xfmr_acl.go +++ b/src/translib/transformer/xfmr_acl.go @@ -181,12 +181,18 @@ func getL2EtherType(etherType uint64) interface{} { // Validate callpoints //////////////////////////////////////////// var validate_ipv4 ValidateCallpoint = func(inParams XfmrParams) (bool) { - var res bool = true - return res + if strings.Contains(inParams.key, "ACL_IPV4") { + return true + } else { + return false + } } var validate_ipv6 ValidateCallpoint = func(inParams XfmrParams) (bool) { - var res bool = false - return res + if strings.Contains(inParams.key, "ACL_IPV6") { + return true + } else { + return false + } } //////////////////////////////////////////// diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index 79a9af74f9..48ea3dda96 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -167,6 +167,7 @@ func processLfLstDbToYang(fieldXpath string, dbFldVal string) []interface{} { /* Traverse db map and create json for cvl yang */ func directDbToYangJsonCreate(dbDataMap map[string]map[string]db.Value, jsonData string) string { + jsonData += fmt.Sprintf("{") for tblName, tblData := range dbDataMap { dataInst := "" for keyStr, dbFldValData := range tblData { @@ -200,6 +201,7 @@ func directDbToYangJsonCreate(dbDataMap map[string]map[string]db.Value, jsonData jsonData += fmt.Sprintf("\"%v\" : [\r\n %v\r\n ],", tblName, dataInst) } jsonData = strings.TrimRight(jsonData, ",") + jsonData += fmt.Sprintf("}") return jsonData } @@ -215,7 +217,7 @@ func tableNameAndKeyFromDbMapGet(dbDataMap map[string]map[string]db.Value) (stri return tableName, tableKey, nil } -func yangListDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath string, dbDataMap *map[db.DBNum]map[string]map[string]db.Value, resultMap map[string]interface{}, tbl string, tblKey string, cdb db.DBNum) error { +func yangListDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath string, dbDataMap *map[db.DBNum]map[string]map[string]db.Value, resultMap map[string]interface{}, tbl string, tblKey string, cdb db.DBNum, validate bool) error { tblData, ok := (*dbDataMap)[cdb][tbl] if ok { @@ -238,7 +240,7 @@ func yangListDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, x curMap[k] = kv } curXpath, _ := RemoveXPATHPredicates(curUri) - yangDataFill(dbs, ygRoot, curUri, curXpath, dbDataMap, curMap, tbl, dbKey, cdb) + yangDataFill(dbs, ygRoot, curUri, curXpath, dbDataMap, curMap, tbl, dbKey, cdb, validate) mapSlice = append(mapSlice, curMap) } } @@ -252,8 +254,9 @@ func yangListDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, x return nil } -func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath string, dbDataMap *map[db.DBNum]map[string]map[string]db.Value, resultMap map[string]interface{}, tbl string, tblKey string, cdb db.DBNum) error { +func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath string, dbDataMap *map[db.DBNum]map[string]map[string]db.Value, resultMap map[string]interface{}, tbl string, tblKey string, cdb db.DBNum, validate bool) error { var err error + isValid := validate yangNode, ok := xSpecMap[xpath] if ok && yangNode.yangEntry != nil { @@ -261,19 +264,21 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath chldXpath := xpath+"/"+yangChldName chldUri := uri+"/"+yangChldName if xSpecMap[chldXpath] != nil && xSpecMap[chldXpath].yangEntry != nil { - if len(xSpecMap[chldXpath].validateFunc) > 0 { + _, key, _ := xpathKeyExtract(dbs[cdb], ygRoot, GET, chldUri) + if len(xSpecMap[chldXpath].validateFunc) > 0 && !validate { // TODO - handle non CONFIG-DB - inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, chldUri, GET, "", dbDataMap, nil) - res := validateHandlerFunc(inParams) + inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, chldUri, GET, key, dbDataMap, nil) + res := validateHandlerFunc(inParams) if res != true { continue - } + } else { + isValid = res + } } chldYangType := yangTypeGet(xSpecMap[chldXpath].yangEntry) cdb = xSpecMap[chldXpath].dbIndex if xSpecMap[chldXpath].yangEntry.IsLeaf() || xSpecMap[chldXpath].yangEntry.IsLeafList() { if len(xSpecMap[chldXpath].xfmrFunc) > 0 { - _, key, _ := xpathKeyExtract(dbs[cdb], ygRoot, GET, chldUri) inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, chldUri, GET, key, dbDataMap, nil) fldValMap, _, err := leafXfmrHandlerFunc(inParams) if err != nil { @@ -320,7 +325,7 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath } } else { cmap := make(map[string]interface{}) - err = yangDataFill(dbs, ygRoot, chldUri, chldXpath, dbDataMap, cmap, tbl, tblKey, cdb) + err = yangDataFill(dbs, ygRoot, chldUri, chldXpath, dbDataMap, cmap, tbl, tblKey, cdb, isValid) if len(cmap) > 0 { resultMap[cname] = cmap } else { @@ -341,7 +346,7 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath ynode, ok := xSpecMap[chldXpath] if ok && ynode.tableName != nil { lTblName := *ynode.tableName - yangListDataFill(dbs, ygRoot, chldUri, chldXpath, dbDataMap, resultMap, lTblName, "", cdb) + yangListDataFill(dbs, ygRoot, chldUri, chldXpath, dbDataMap, resultMap, lTblName, "", cdb, isValid) } } } else { @@ -370,10 +375,19 @@ func dbDataToYangJsonCreate(uri string, ygRoot *ygot.GoStruct, dbs [db.MaxDB]*db yangType := yangTypeGet(yangNode.yangEntry) if yangType == "leaf" { fldName := xSpecMap[reqXpath].fieldName + yangName := xSpecMap[reqXpath].yangEntry.Name tbl, key, _ := tableNameAndKeyFromDbMapGet((*dbDataMap)[cdb]) - jsonData = fmt.Sprintf("{\r\n \"%v\" : \"%v\" \r\n }\r\n", xSpecMap[reqXpath].yangEntry.Name, - (*dbDataMap)[cdb][tbl][key].Field[fldName]) - resultMap[fldName] = (*dbDataMap)[cdb][tbl][key].Field[fldName] + if len(xSpecMap[reqXpath].validateFunc) > 0 { + // TODO - handle non CONFIG-DB + inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, uri, GET, key, dbDataMap, nil) + res := validateHandlerFunc(inParams) + if res == true { + resultMap[yangName] = (*dbDataMap)[cdb][tbl][key].Field[fldName] + } else { + resultMap[yangName] = "" + } + } + } else if yangType == "container" { cname := xSpecMap[reqXpath].yangEntry.Name cmap := make(map[string]interface{}) @@ -386,13 +400,13 @@ func dbDataToYangJsonCreate(uri string, ygRoot *ygot.GoStruct, dbs [db.MaxDB]*db log.Info("Empty container(\"%v\").\r\n", uri) } } else { - err := yangDataFill(dbs, ygRoot, uri, reqXpath, dbDataMap, resultMap, tableName, keyName, cdb) + err := yangDataFill(dbs, ygRoot, uri, reqXpath, dbDataMap, resultMap, tableName, keyName, cdb, false) if err != nil { log.Info("Empty container(\"%v\").\r\n", uri) } } } else { - yangDataFill(dbs, ygRoot, uri, reqXpath, dbDataMap, resultMap, tableName, keyName, cdb) + yangDataFill(dbs, ygRoot, uri, reqXpath, dbDataMap, resultMap, tableName, keyName, cdb, false) } } diff --git a/src/translib/transformer/xspec.go b/src/translib/transformer/xspec.go index 7af7321dd7..b3d9db57e6 100644 --- a/src/translib/transformer/xspec.go +++ b/src/translib/transformer/xspec.go @@ -82,6 +82,10 @@ func yangToDbMapFill (keyLevel int, xSpecMap map[string]*yangXpathInfo, entry *y xpathData.dbIndex = parentXpathData.dbIndex } + if ok && len(parentXpathData.validateFunc) > 0 { + xpathData.validateFunc = parentXpathData.validateFunc + } + if xpathData.yangDataType == "leaf" && len(xpathData.fieldName) == 0 { if xpathData.tableName != nil && xDbSpecMap[*xpathData.tableName] != nil { if xDbSpecMap[*xpathData.tableName].dbEntry.Dir[entry.Name] != nil { @@ -359,6 +363,7 @@ func mapPrint(inMap map[string]*yangXpathInfo, fileName string) { fmt.Fprintf(fp, "\r\n xfmrKeyFn: %v", d.xfmrKey) fmt.Fprintf(fp, "\r\n xfmrFunc : %v", d.xfmrFunc) fmt.Fprintf(fp, "\r\n dbIndex : %v", d.dbIndex) + fmt.Fprintf(fp, "\r\n validateFunc : %v", d.validateFunc) fmt.Fprintf(fp, "\r\n yangEntry: ") if d.yangEntry != nil { fmt.Fprintf(fp, "%v", *d.yangEntry) From dfcf679844facb188c03e4418115bfedaf59a080 Mon Sep 17 00:00:00 2001 From: Tejaswi Goel Date: Tue, 17 Sep 2019 17:33:56 -0700 Subject: [PATCH 135/214] Add copyright/license headers (#123) Signed-off-by: Tejaswi Goel --- src/CLI/Makefile | 18 ++++++++++++++++++ src/CLI/actioner/sonic-cli-if.py | 18 ++++++++++++++++++ src/CLI/actioner/sonic-cli-lldp.py | 18 ++++++++++++++++++ src/CLI/actioner/sonic-cli-pfm.py | 18 ++++++++++++++++++ src/CLI/actioner/sonic-cli-sys.py | 18 ++++++++++++++++++ src/CLI/actioner/sonic-cli.py | 18 ++++++++++++++++++ src/CLI/clicfg/mgmt_clish_entities.xsl | 17 ++++++++++++++++- src/CLI/clicfg/mgmt_clish_entities_macro.xsl | 16 ++++++++++++++++ src/CLI/clicfg/mgmt_clish_feature_master.xsd | 15 +++++++++++++++ src/CLI/clicfg/mgmt_clish_features.xsl | 16 ++++++++++++++++ src/CLI/clicfg/mgmt_clish_platform.xml | 15 +++++++++++++++ src/CLI/clitree/Makefile | 18 ++++++++++++++++++ src/CLI/clitree/cli-xml/acl.xml | 16 ++++++++++++++++ src/CLI/clitree/cli-xml/configure_mode.xml | 16 ++++++++++++++++ src/CLI/clitree/cli-xml/enable_mode.xml | 16 ++++++++++++++++ src/CLI/clitree/cli-xml/include/pipe.xml | 16 ++++++++++++++++ .../include/pipe_without_display_xml.xml | 16 ++++++++++++++++ src/CLI/clitree/cli-xml/interface.xml | 16 ++++++++++++++++ src/CLI/clitree/cli-xml/ip.xml | 16 ++++++++++++++++ src/CLI/clitree/cli-xml/ipv4.xml | 16 ++++++++++++++++ src/CLI/clitree/cli-xml/ipv6.xml | 16 ++++++++++++++++ src/CLI/clitree/cli-xml/lldp.xml | 17 +++++++++++++++++ src/CLI/clitree/cli-xml/platform.xml | 16 ++++++++++++++++ src/CLI/clitree/cli-xml/sonic_types.xml | 16 ++++++++++++++++ src/CLI/clitree/cli-xml/startup.xml | 16 ++++++++++++++++ src/CLI/clitree/cli-xml/system.xml | 16 ++++++++++++++++ src/CLI/clitree/macro/acl_macro.xml | 16 ++++++++++++++++ src/CLI/clitree/scripts/klish_ins_def_cmd.py | 18 ++++++++++++++++++ src/CLI/clitree/scripts/klish_insert_pipe.py | 18 ++++++++++++++++++ .../scripts/klish_platform_features_process.sh | 18 ++++++++++++++++++ .../clitree/scripts/klish_preproc_cmdtree.py | 18 ++++++++++++++++++ src/CLI/clitree/scripts/klish_replace_macro.py | 18 ++++++++++++++++++ src/CLI/clitree/scripts/platform_dummy.xml | 15 +++++++++++++++ src/CLI/clitree/scripts/sonic-clish.xsd | 15 +++++++++++++++ src/translib/intf_app.go | 18 ++++++++++++++++++ src/translib/lldp_app.go | 18 ++++++++++++++++++ src/translib/pfm_app.go | 18 ++++++++++++++++++ src/translib/sys_app.go | 18 ++++++++++++++++++ 38 files changed, 637 insertions(+), 1 deletion(-) diff --git a/src/CLI/Makefile b/src/CLI/Makefile index b920361a6a..a12bdaad28 100644 --- a/src/CLI/Makefile +++ b/src/CLI/Makefile @@ -1,4 +1,22 @@ SHELL = /bin/bash +########################################################################### +# +# Copyright 2019 Dell, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +########################################################################### + .ONESHELL: .SHELLFLAGS += -e diff --git a/src/CLI/actioner/sonic-cli-if.py b/src/CLI/actioner/sonic-cli-if.py index 5faf8b53b0..9ed5f27006 100755 --- a/src/CLI/actioner/sonic-cli-if.py +++ b/src/CLI/actioner/sonic-cli-if.py @@ -1,4 +1,22 @@ #!/usr/bin/python +########################################################################### +# +# Copyright 2019 Dell, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +########################################################################### + import sys import time import json diff --git a/src/CLI/actioner/sonic-cli-lldp.py b/src/CLI/actioner/sonic-cli-lldp.py index 7c8e98668d..11d71479b2 100644 --- a/src/CLI/actioner/sonic-cli-lldp.py +++ b/src/CLI/actioner/sonic-cli-lldp.py @@ -1,4 +1,22 @@ #!/usr/bin/python +########################################################################### +# +# Copyright 2019 Dell, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +########################################################################### + import sys import time import json diff --git a/src/CLI/actioner/sonic-cli-pfm.py b/src/CLI/actioner/sonic-cli-pfm.py index 3007c2111c..155e404961 100644 --- a/src/CLI/actioner/sonic-cli-pfm.py +++ b/src/CLI/actioner/sonic-cli-pfm.py @@ -1,4 +1,22 @@ #!/usr/bin/python +########################################################################### +# +# Copyright 2019 Dell, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +########################################################################### + import sys import time import json diff --git a/src/CLI/actioner/sonic-cli-sys.py b/src/CLI/actioner/sonic-cli-sys.py index cfa8cfe74f..1fbbb7317d 100644 --- a/src/CLI/actioner/sonic-cli-sys.py +++ b/src/CLI/actioner/sonic-cli-sys.py @@ -1,4 +1,22 @@ #:!/usr/bin/python +########################################################################### +# +# Copyright 2019 Dell, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +########################################################################### + import sys import time import json diff --git a/src/CLI/actioner/sonic-cli.py b/src/CLI/actioner/sonic-cli.py index ced1c44db1..f694c29db9 100755 --- a/src/CLI/actioner/sonic-cli.py +++ b/src/CLI/actioner/sonic-cli.py @@ -1,4 +1,22 @@ #!/usr/bin/python +########################################################################### +# +# Copyright 2019 Dell, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +########################################################################### + import sys import time import json diff --git a/src/CLI/clicfg/mgmt_clish_entities.xsl b/src/CLI/clicfg/mgmt_clish_entities.xsl index aac740d8d5..a21cca8d99 100644 --- a/src/CLI/clicfg/mgmt_clish_entities.xsl +++ b/src/CLI/clicfg/mgmt_clish_entities.xsl @@ -1,7 +1,22 @@ + + - diff --git a/src/CLI/clicfg/mgmt_clish_entities_macro.xsl b/src/CLI/clicfg/mgmt_clish_entities_macro.xsl index fb6fd4d92b..f20fd62e6f 100644 --- a/src/CLI/clicfg/mgmt_clish_entities_macro.xsl +++ b/src/CLI/clicfg/mgmt_clish_entities_macro.xsl @@ -1,4 +1,20 @@ + + diff --git a/src/CLI/clicfg/mgmt_clish_feature_master.xsd b/src/CLI/clicfg/mgmt_clish_feature_master.xsd index 5748b93f42..fd7c330370 100644 --- a/src/CLI/clicfg/mgmt_clish_feature_master.xsd +++ b/src/CLI/clicfg/mgmt_clish_feature_master.xsd @@ -1,4 +1,19 @@ + diff --git a/src/CLI/clicfg/mgmt_clish_features.xsl b/src/CLI/clicfg/mgmt_clish_features.xsl index ba9362e0e9..2c9ebad834 100644 --- a/src/CLI/clicfg/mgmt_clish_features.xsl +++ b/src/CLI/clicfg/mgmt_clish_features.xsl @@ -1,4 +1,20 @@ + + diff --git a/src/CLI/clicfg/mgmt_clish_platform.xml b/src/CLI/clicfg/mgmt_clish_platform.xml index 469b542576..f421e8ce26 100644 --- a/src/CLI/clicfg/mgmt_clish_platform.xml +++ b/src/CLI/clicfg/mgmt_clish_platform.xml @@ -1,4 +1,19 @@ + + + + + + + + + + + + + + + + diff --git a/src/CLI/clitree/cli-xml/ipv6.xml b/src/CLI/clitree/cli-xml/ipv6.xml index 07eb940e47..bad92d0215 100644 --- a/src/CLI/clitree/cli-xml/ipv6.xml +++ b/src/CLI/clitree/cli-xml/ipv6.xml @@ -1,4 +1,20 @@ + + diff --git a/src/CLI/clitree/cli-xml/lldp.xml b/src/CLI/clitree/cli-xml/lldp.xml index eda05c8d36..d03352e24b 100644 --- a/src/CLI/clitree/cli-xml/lldp.xml +++ b/src/CLI/clitree/cli-xml/lldp.xml @@ -1,4 +1,21 @@ + + + + + + + diff --git a/src/CLI/clitree/cli-xml/startup.xml b/src/CLI/clitree/cli-xml/startup.xml index b32edffd95..825fceb4a4 100644 --- a/src/CLI/clitree/cli-xml/startup.xml +++ b/src/CLI/clitree/cli-xml/startup.xml @@ -1,4 +1,20 @@ + + + + diff --git a/src/CLI/clitree/macro/acl_macro.xml b/src/CLI/clitree/macro/acl_macro.xml index 90fcbd57a8..329717c992 100644 --- a/src/CLI/clitree/macro/acl_macro.xml +++ b/src/CLI/clitree/macro/acl_macro.xml @@ -1,4 +1,20 @@ + + diff --git a/src/CLI/clitree/scripts/klish_ins_def_cmd.py b/src/CLI/clitree/scripts/klish_ins_def_cmd.py index 2f873c07c1..01032c07b6 100755 --- a/src/CLI/clitree/scripts/klish_ins_def_cmd.py +++ b/src/CLI/clitree/scripts/klish_ins_def_cmd.py @@ -1,4 +1,22 @@ #!/usr/bin/env python +########################################################################### +# +# Copyright 2019 Dell, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +########################################################################### + """ The script klish_Ins_Def_Cmd.py is used to append the "exit" and "end"commands to the views of the klish XML models except for the views diff --git a/src/CLI/clitree/scripts/klish_insert_pipe.py b/src/CLI/clitree/scripts/klish_insert_pipe.py index 169f87daf3..27c074cad3 100755 --- a/src/CLI/clitree/scripts/klish_insert_pipe.py +++ b/src/CLI/clitree/scripts/klish_insert_pipe.py @@ -1,4 +1,22 @@ #!/usr/bin/python +########################################################################### +# +# Copyright 2019 Dell, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +########################################################################### + ''' This script extends every show and get COMMAND with pipe option ----------------------------------------------------------------''' diff --git a/src/CLI/clitree/scripts/klish_platform_features_process.sh b/src/CLI/clitree/scripts/klish_platform_features_process.sh index 0fed0d6ea2..976d55e8e9 100755 --- a/src/CLI/clitree/scripts/klish_platform_features_process.sh +++ b/src/CLI/clitree/scripts/klish_platform_features_process.sh @@ -1,4 +1,22 @@ #!/bin/bash +########################################################################### +# +# Copyright 2019 Dell, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +########################################################################### + #set -x # Validate all platform xml files # For all platform_*.xml, run xmllint feature_master.xsd $i.xml diff --git a/src/CLI/clitree/scripts/klish_preproc_cmdtree.py b/src/CLI/clitree/scripts/klish_preproc_cmdtree.py index 28123baf77..140c859f07 100755 --- a/src/CLI/clitree/scripts/klish_preproc_cmdtree.py +++ b/src/CLI/clitree/scripts/klish_preproc_cmdtree.py @@ -1,4 +1,22 @@ #!/usr/bin/python2.7 +########################################################################### +# +# Copyright 2019 Dell, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +########################################################################### + ''' CLI parser tree preprocessing script before the parser xml-s are copied to sysroot. These are the steps performed: a. Macro replacement diff --git a/src/CLI/clitree/scripts/klish_replace_macro.py b/src/CLI/clitree/scripts/klish_replace_macro.py index 93d8e087bb..436b1dea82 100755 --- a/src/CLI/clitree/scripts/klish_replace_macro.py +++ b/src/CLI/clitree/scripts/klish_replace_macro.py @@ -1,4 +1,22 @@ #!/usr/bin/python2.7 +########################################################################### +# +# Copyright 2019 Dell, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +########################################################################### + ''' This script does macro replacement on the xml files which are used by klish to defind CLI strucuture. diff --git a/src/CLI/clitree/scripts/platform_dummy.xml b/src/CLI/clitree/scripts/platform_dummy.xml index 191f0c51cc..8cf798a09f 100644 --- a/src/CLI/clitree/scripts/platform_dummy.xml +++ b/src/CLI/clitree/scripts/platform_dummy.xml @@ -1,4 +1,19 @@ + Date: Tue, 17 Sep 2019 19:05:18 -0700 Subject: [PATCH 136/214] move json creation for sonic-yang to map --- src/translib/transformer/xlate_from_db.go | 75 ++++++++++++----------- src/translib/transformer/xlate_utils.go | 3 +- 2 files changed, 41 insertions(+), 37 deletions(-) diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index 79a9af74f9..7b33d0cc9f 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -18,10 +18,6 @@ import ( type typeMapOfInterface map[string]interface{} -const ( - Yuint8 = 5 -) - func xfmrHandlerFunc(inParams XfmrParams) (map[string]interface{}, error) { result := make(map[string]interface{}) xpath, _ := RemoveXPATHPredicates(inParams.uri) @@ -166,10 +162,12 @@ func processLfLstDbToYang(fieldXpath string, dbFldVal string) []interface{} { } /* Traverse db map and create json for cvl yang */ -func directDbToYangJsonCreate(dbDataMap map[string]map[string]db.Value, jsonData string) string { +func directDbToYangJsonCreate(dbDataMap map[string]map[string]db.Value, jsonData string, resultMap map[string]interface{}) string { for tblName, tblData := range dbDataMap { dataInst := "" + var mapSlice []typeMapOfInterface for keyStr, dbFldValData := range tblData { + curMap := make(map[string]interface{}) fldValPair := "" for field, value := range dbFldValData.Field { if strings.HasSuffix(field, "@") { @@ -179,6 +177,7 @@ func directDbToYangJsonCreate(dbDataMap map[string]map[string]db.Value, jsonData if xDbSpecMap[fieldXpath].dbEntry.IsLeafList() { resLst := processLfLstDbToYang(fieldXpath, value) fldValPair += fmt.Sprintf("\"%v\" : \"%v\",\r\n", field, resLst) + curMap[field] = resLst continue } } else { @@ -189,15 +188,20 @@ func directDbToYangJsonCreate(dbDataMap map[string]map[string]db.Value, jsonData log.Warning("Failure in converting Db value type to yang type for field", field) } else { fldValPair += fmt.Sprintf("\"%v\" : \"%v\",\r\n", field, resVal) + curMap[field] = resVal } } } yangKeys := yangKeyFromEntryGet(xDbSpecMap[tblName].dbEntry) - fldValPair = keyJsonDataAdd(yangKeys, keyStr, fldValPair) + fldValPair = keyJsonDataAdd(yangKeys, keyStr, fldValPair, curMap) dataInst += fmt.Sprintf("{ \r\n %v \r\n },", fldValPair) + if curMap != nil { + mapSlice = append(mapSlice, curMap) + } } dataInst = strings.TrimRight(dataInst, ",") jsonData += fmt.Sprintf("\"%v\" : [\r\n %v\r\n ],", tblName, dataInst) + resultMap[tblName] = mapSlice } jsonData = strings.TrimRight(jsonData, ",") return jsonData @@ -356,43 +360,42 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath /* Traverse linear db-map data and add to nested json data */ func dbDataToYangJsonCreate(uri string, ygRoot *ygot.GoStruct, dbs [db.MaxDB]*db.DB, dbDataMap *map[db.DBNum]map[string]map[string]db.Value, cdb db.DBNum) (string, error) { jsonData := "" + resultMap := make(map[string]interface{}) if isCvlYang(uri) { - jsonData := directDbToYangJsonCreate((*dbDataMap)[cdb], jsonData) + jsonData := directDbToYangJsonCreate((*dbDataMap)[cdb], jsonData, resultMap) jsonDataPrint(jsonData) - return jsonData, nil - } - - var d *db.DB - resultMap := make(map[string]interface{}) - reqXpath, keyName, tableName := xpathKeyExtract(d, ygRoot, GET, uri) - yangNode, ok := xSpecMap[reqXpath] - if ok { - yangType := yangTypeGet(yangNode.yangEntry) - if yangType == "leaf" { - fldName := xSpecMap[reqXpath].fieldName - tbl, key, _ := tableNameAndKeyFromDbMapGet((*dbDataMap)[cdb]) - jsonData = fmt.Sprintf("{\r\n \"%v\" : \"%v\" \r\n }\r\n", xSpecMap[reqXpath].yangEntry.Name, + } else { + var d *db.DB + reqXpath, keyName, tableName := xpathKeyExtract(d, ygRoot, GET, uri) + yangNode, ok := xSpecMap[reqXpath] + if ok { + yangType := yangTypeGet(yangNode.yangEntry) + if yangType == "leaf" { + fldName := xSpecMap[reqXpath].fieldName + tbl, key, _ := tableNameAndKeyFromDbMapGet((*dbDataMap)[cdb]) + jsonData = fmt.Sprintf("{\r\n \"%v\" : \"%v\" \r\n }\r\n", xSpecMap[reqXpath].yangEntry.Name, (*dbDataMap)[cdb][tbl][key].Field[fldName]) - resultMap[fldName] = (*dbDataMap)[cdb][tbl][key].Field[fldName] - } else if yangType == "container" { - cname := xSpecMap[reqXpath].yangEntry.Name - cmap := make(map[string]interface{}) - if len(xSpecMap[reqXpath].xfmrFunc) > 0 { - inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, uri, GET, "", dbDataMap, nil) - cmap, _ = xfmrHandlerFunc(inParams) - if len(cmap) > 0 { - resultMap[cname] = cmap + resultMap[xSpecMap[reqXpath].yangEntry.Name] = (*dbDataMap)[cdb][tbl][key].Field[fldName] + } else if yangType == "container" { + cname := xSpecMap[reqXpath].yangEntry.Name + cmap := make(map[string]interface{}) + if len(xSpecMap[reqXpath].xfmrFunc) > 0 { + inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, uri, GET, "", dbDataMap, nil) + cmap, _ = xfmrHandlerFunc(inParams) + if len(cmap) > 0 { + resultMap[cname] = cmap + } else { + log.Info("Empty container(\"%v\").\r\n", uri) + } } else { - log.Info("Empty container(\"%v\").\r\n", uri) + err := yangDataFill(dbs, ygRoot, uri, reqXpath, dbDataMap, resultMap, tableName, keyName, cdb) + if err != nil { + log.Info("Empty container(\"%v\").\r\n", uri) + } } } else { - err := yangDataFill(dbs, ygRoot, uri, reqXpath, dbDataMap, resultMap, tableName, keyName, cdb) - if err != nil { - log.Info("Empty container(\"%v\").\r\n", uri) - } + yangDataFill(dbs, ygRoot, uri, reqXpath, dbDataMap, resultMap, tableName, keyName, cdb) } - } else { - yangDataFill(dbs, ygRoot, uri, reqXpath, dbDataMap, resultMap, tableName, keyName, cdb) } } diff --git a/src/translib/transformer/xlate_utils.go b/src/translib/transformer/xlate_utils.go index 85407ed0fe..73a371cef0 100644 --- a/src/translib/transformer/xlate_utils.go +++ b/src/translib/transformer/xlate_utils.go @@ -191,7 +191,7 @@ func isCvlYang(path string) bool { return false } -func keyJsonDataAdd(keyNameList []string, keyStr string, jsonData string) string { +func keyJsonDataAdd(keyNameList []string, keyStr string, jsonData string, resultMap map[string]interface{}) string { keyValList := strings.Split(keyStr, "|") if len(keyNameList) != len(keyValList) { return "" @@ -199,6 +199,7 @@ func keyJsonDataAdd(keyNameList []string, keyStr string, jsonData string) string for i, keyName := range keyNameList { jsonData += fmt.Sprintf("\"%v\" : \"%v\",", keyName, keyValList[i]) + resultMap[keyName] = keyValList[i] } jsonData = strings.TrimRight(jsonData, ",") return jsonData From 99720f5d5ccdad86529a4617032b49cf508c9d3f Mon Sep 17 00:00:00 2001 From: Partha Dutta Date: Wed, 18 Sep 2019 09:37:06 +0530 Subject: [PATCH 137/214] Moving unwanted CVL YANG to testdata --- src/cvl/Makefile | 6 ++- src/cvl/cvl_test.go | 8 +-- src/cvl/internal/yparser/yparser.go | 11 +++- src/cvl/schema/sonic-acl.yang | 51 +++++-------------- src/cvl/schema/sonic-common.yang | 28 +++++----- src/cvl/schema/sonic-interface.yang | 16 +++--- src/cvl/schema/sonic-mirror-session.yang | 4 +- src/cvl/schema/sonic-port.yang | 10 ++-- src/cvl/testdata/schema/Makefile | 26 ++++++++++ .../{ => testdata}/schema/sonic-acl-dev.yang | 4 +- .../schema/sonic-bgp-neighbor.yang | 4 +- .../schema/sonic-buffer-pg.yang | 4 +- .../schema/sonic-buffer-pool.yang | 4 +- .../schema/sonic-buffer-profile.yang | 4 +- .../schema/sonic-cablelength.yang | 4 +- .../schema/sonic-device-metadata.yang | 4 +- .../schema/sonic-device-neighbor.yang | 4 +- .../schema/sonic-dscp-tc-map.yang | 4 +- .../schema/sonic-pf-limits.yang | 4 +- .../schema/sonic-pfc-priority-queue-map.yang | 4 +- .../schema/sonic-port-qos-map.yang | 4 +- .../schema/sonic-portchannel-interface.yang | 4 +- .../schema/sonic-portchannel.yang | 4 +- .../{ => testdata}/schema/sonic-queue.yang | 4 +- .../schema/sonic-scheduler.yang | 4 +- .../schema/sonic-tc-priority-group-map.yang | 4 +- .../schema/sonic-tc-queue-map.yang | 4 +- .../{ => testdata}/schema/sonic-vlan-dev.yang | 4 +- .../testdata/schema/sonic-vlan-dev.yin.tmp | 30 +++++++++++ .../schema/sonic-vlan-interface.yang | 4 +- src/cvl/{ => testdata}/schema/sonic-vlan.yang | 4 +- .../schema/sonic-wred-profile.yang | 4 +- src/cvl/tests/Makefile | 1 + 33 files changed, 162 insertions(+), 117 deletions(-) create mode 100644 src/cvl/testdata/schema/Makefile rename src/cvl/{ => testdata}/schema/sonic-acl-dev.yang (97%) rename src/cvl/{ => testdata}/schema/sonic-bgp-neighbor.yang (97%) rename src/cvl/{ => testdata}/schema/sonic-buffer-pg.yang (98%) rename src/cvl/{ => testdata}/schema/sonic-buffer-pool.yang (96%) rename src/cvl/{ => testdata}/schema/sonic-buffer-profile.yang (97%) rename src/cvl/{ => testdata}/schema/sonic-cablelength.yang (97%) rename src/cvl/{ => testdata}/schema/sonic-device-metadata.yang (98%) rename src/cvl/{ => testdata}/schema/sonic-device-neighbor.yang (98%) rename src/cvl/{ => testdata}/schema/sonic-dscp-tc-map.yang (97%) rename src/cvl/{ => testdata}/schema/sonic-pf-limits.yang (96%) rename src/cvl/{ => testdata}/schema/sonic-pfc-priority-queue-map.yang (97%) rename src/cvl/{ => testdata}/schema/sonic-port-qos-map.yang (98%) rename src/cvl/{ => testdata}/schema/sonic-portchannel-interface.yang (97%) rename src/cvl/{ => testdata}/schema/sonic-portchannel.yang (97%) rename src/cvl/{ => testdata}/schema/sonic-queue.yang (98%) rename src/cvl/{ => testdata}/schema/sonic-scheduler.yang (96%) rename src/cvl/{ => testdata}/schema/sonic-tc-priority-group-map.yang (97%) rename src/cvl/{ => testdata}/schema/sonic-tc-queue-map.yang (97%) rename src/cvl/{ => testdata}/schema/sonic-vlan-dev.yang (96%) create mode 100644 src/cvl/testdata/schema/sonic-vlan-dev.yin.tmp rename src/cvl/{ => testdata}/schema/sonic-vlan-interface.yang (97%) rename src/cvl/{ => testdata}/schema/sonic-vlan.yang (98%) rename src/cvl/{ => testdata}/schema/sonic-wred-profile.yang (98%) diff --git a/src/cvl/Makefile b/src/cvl/Makefile index 4f85259fc4..198a541290 100644 --- a/src/cvl/Makefile +++ b/src/cvl/Makefile @@ -50,7 +50,11 @@ tests: make -C tests gotest: - CVL_CFG_FILE=$(abspath .)/conf/cvl_cfg.json CVL_SCHEMA_PATH=$(abspath .)/schema GOPATH=$(GOPATH) tests/run_test.sh + make -C schema + make -C testdata/schema + cp schema/*.yin testdata/schema + #CVL_CFG_FILE=$(abspath .)/conf/cvl_cfg.json CVL_SCHEMA_PATH=$(abspath .)/schema:$(abspath .)/testdata/schema GOPATH=$(GOPATH) tests/run_test.sh + CVL_CFG_FILE=$(abspath .)/conf/cvl_cfg.json CVL_SCHEMA_PATH=$(abspath .)/schema GOPATH=$(GOPATH) tests/run_test.sh clean: make -C tests clean diff --git a/src/cvl/cvl_test.go b/src/cvl/cvl_test.go index 74d51df3d0..1ac35ed30f 100644 --- a/src/cvl/cvl_test.go +++ b/src/cvl/cvl_test.go @@ -2806,16 +2806,16 @@ func TestBadSchema(t *testing.T) { if _, err := os.Stat("/usr/sbin/schema"); os.IsNotExist(err) { //Corrupt some schema file - exec.Command("/bin/sh", "-c", "/bin/cp schema/sonic-port.yin schema/sonic-port.yin.bad" + - " && /bin/sed -i '1 a ' schema/sonic-port.yin.bad").Output() + exec.Command("/bin/sh", "-c", "/bin/cp testdata/schema/sonic-port.yin testdata/schema/sonic-port.yin.bad" + + " && /bin/sed -i '1 a ' testdata/schema/sonic-port.yin.bad").Output() //Parse bad schema file - if module, _ := yparser.ParseSchemaFile("schema/sonic-port.yin.bad.1"); module != nil { //should fail + if module, _ := yparser.ParseSchemaFile("testdata/schema/sonic-port.yin.bad"); module != nil { //should fail t.Errorf("Bad schema parsing should fail.") } //Revert to - exec.Command("/bin/sh", "-c", "/bin/rm schema/sonic-port.yin.bad").Output() + exec.Command("/bin/sh", "-c", "/bin/rm testdata/schema/sonic-port.yin.bad").Output() } else { //Corrupt some schema file exec.Command("/bin/sh", "-c", "/bin/cp /usr/sbin/schema/sonic-port.yin /usr/sbin/schema/sonic-port.yin.bad" + diff --git a/src/cvl/internal/yparser/yparser.go b/src/cvl/internal/yparser/yparser.go index d08f66c702..a654d34fc2 100644 --- a/src/cvl/internal/yparser/yparser.go +++ b/src/cvl/internal/yparser/yparser.go @@ -7,6 +7,7 @@ import ( "strings" log "github.com/golang/glog" . "cvl/internal/util" + "fmt" ) /* @@ -235,7 +236,10 @@ func ParseSchemaFile(modelFile string) (*YParserModule, YParserError) { module := C.lys_parse_path((*C.struct_ly_ctx)(ypCtx), C.CString(modelFile), C.LYS_IN_YIN) if module == nil { + fmt.Printf("\n\nFailed Parsed file .... %s\n\n", modelFile) return nil, getErrorDetails() + } else { + fmt.Printf("\n\nParsed file .... %s\n\n", modelFile) } if (strings.Contains(modelFile, "sonic-common.yin") == true) { @@ -250,7 +254,12 @@ func ParseSchemaFile(modelFile string) (*YParserModule, YParserError) { //Add child node to a parent node func(yp *YParser) AddChildNode(module *YParserModule, parent *YParserNode, name string) *YParserNode { - return (*YParserNode)(C.lyd_new((*C.struct_lyd_node)(parent), (*C.struct_lys_module)(module), C.CString(name))) + //return (*YParserNode)(C.lyd_new((*C.struct_lyd_node)(parent), (*C.struct_lys_module)(module), C.CString(name))) + ret := (*YParserNode)(C.lyd_new((*C.struct_lyd_node)(parent), (*C.struct_lys_module)(module), C.CString(name))) + if (ret == nil) { + fmt.Printf("\n\nFailed parsing .... %s\n\n", name) + } + return ret } //Add child node to a parent node diff --git a/src/cvl/schema/sonic-acl.yang b/src/cvl/schema/sonic-acl.yang index 61ed679d8d..c2a96aaccb 100644 --- a/src/cvl/schema/sonic-acl.yang +++ b/src/cvl/schema/sonic-acl.yang @@ -19,23 +19,15 @@ module sonic-acl { prefix prt; } - import sonic-portchannel { - prefix spc; - } - import sonic-mirror-session { prefix sms; } - import sonic-pf-limits { - prefix spf; - } - organization - "BRCM"; + "SONiC"; contact - "BRCM"; + "SONiC"; description "SONIC ACL"; @@ -50,13 +42,12 @@ module sonic-acl { list ACL_TABLE { key "aclname"; - /* must "count(/prt:sonic-port/prt:PORT) > 0"; */ leaf aclname { - type string { - pattern '[a-zA-Z0-9]{1}([-a-zA-Z0-9_]{0,71})'; - length 1..72; - } + type string { + pattern '[a-zA-Z0-9]{1}([-a-zA-Z0-9_]{0,71})'; + length 1..72; + } } leaf policy_desc { @@ -84,30 +75,14 @@ module sonic-acl { } leaf-list ports { - type union { - type leafref { - path "/prt:sonic-port/prt:PORT/prt:ifname"; - } - type leafref { - path "/spc:sonic-portchannel/spc:PORTCHANNEL/spc:name"; - } + type leafref { + path "/prt:sonic-port/prt:PORT/prt:ifname"; } } } list ACL_RULE { key "aclname rulename"; - scommon:pf-check "ACL_CheckAclLimits"; - - /* Limit for number of dynamic ACL rules */ - /*must "count(../ACL_RULE) > /spf:sonic-pf-limits/acl/MAX_ACL_RULES" { - error-message "Number of ACL rules reached max platform limit."; - } - must "PRIORITY > /spf:sonic-pf-limits/acl/MAX_PRIORITY" { - error-message "Invalid ACL rule priority."; - } - must "count(../ACL_TABLE) > 0 and count(/prt:sonic-port/prt:PORT) > 0"; //Temporary work-around - */ leaf aclname { type leafref { @@ -116,7 +91,7 @@ module sonic-acl { must "(/scommon:operation/scommon:operation != 'DELETE') or " + "count(current()/../../ACL_TABLE[aclname=current()]/ports) = 0" { error-message "Ports are already bound to this rule."; - } + } } leaf rulename { @@ -127,7 +102,7 @@ module sonic-acl { type uint16 { range "1..65535"{ error-message "Invalid ACL rule priority."; - } + } } } @@ -160,7 +135,7 @@ module sonic-acl { enum NON_IPV6; } } - + leaf IP_PROTOCOL { type uint8 { range "1|2|6|17|46|47|51|103|115"; @@ -171,8 +146,8 @@ module sonic-acl { type string{ pattern "(0x88CC)|(0x8100)|(0x8915)|(0x0806)|(0x0800)|(0x86DD)|(0x8847)"{ error-message "Invalid ACL Rule Ether Type"; - error-app-tag ether-type-invalid; - } + error-app-tag ether-type-invalid; + } } } diff --git a/src/cvl/schema/sonic-common.yang b/src/cvl/schema/sonic-common.yang index be94f4645a..329d40c537 100644 --- a/src/cvl/schema/sonic-common.yang +++ b/src/cvl/schema/sonic-common.yang @@ -8,10 +8,10 @@ module sonic-common { } organization - "BRCM"; + "SONiC"; contact - "BRCM"; + "SONiC"; description "SONIC VLAN"; @@ -22,18 +22,18 @@ module sonic-common { } typedef tagging_mode { - type enumeration { - enum untagged; - enum tagged; - enum priority_tagged; - } + type enumeration { + enum untagged; + enum tagged; + enum priority_tagged; + } } typedef admin-status { - type enumeration { - enum up; - enum down; - } + type enumeration { + enum up; + enum down; + } } extension custom-handler { @@ -63,19 +63,19 @@ module sonic-common { extension map-list { description "If it is a map list"; - argument "value"; // + argument "value"; } extension map-leaf { description "Map leaf names"; - argument "value"; // + argument "value"; } extension pf-check { description "Platform specific validation"; - argument "handler"; // + argument "handler"; } container operation { diff --git a/src/cvl/schema/sonic-interface.yang b/src/cvl/schema/sonic-interface.yang index 1ddf94c115..540b3a16b8 100644 --- a/src/cvl/schema/sonic-interface.yang +++ b/src/cvl/schema/sonic-interface.yang @@ -7,8 +7,8 @@ module sonic-interface { } import ietf-inet-types { - prefix inet; - } + prefix inet; + } import sonic-common { prefix scommon; @@ -19,10 +19,10 @@ module sonic-interface { } organization - "BRCM"; + "SONiC"; contact - "BRCM"; + "SONiC"; description "SONIC INTERFACE"; @@ -38,13 +38,13 @@ module sonic-interface { leaf portname{ type leafref { - path "/prt:sonic-port/prt:PORT/prt:ifname"; - } + path "/prt:sonic-port/prt:PORT/prt:ifname"; + } } leaf ip_prefix { - mandatory true; - type inet:ip-prefix; + mandatory true; + type inet:ip-prefix; } } diff --git a/src/cvl/schema/sonic-mirror-session.yang b/src/cvl/schema/sonic-mirror-session.yang index 36bb32cc81..1a2591cc0c 100644 --- a/src/cvl/schema/sonic-mirror-session.yang +++ b/src/cvl/schema/sonic-mirror-session.yang @@ -15,10 +15,10 @@ module sonic-mirror-session { } organization - "BRCM"; + "SONiC"; contact - "BRCM"; + "SONiC"; description "SONIC MIRROR SESSION"; diff --git a/src/cvl/schema/sonic-port.yang b/src/cvl/schema/sonic-port.yang index 5e9e893a39..3d99d0534f 100644 --- a/src/cvl/schema/sonic-port.yang +++ b/src/cvl/schema/sonic-port.yang @@ -11,10 +11,10 @@ module sonic-port { } organization - "BRCM"; + "SONiC"; contact - "BRCM"; + "SONiC"; description "SONIC VLAN"; @@ -33,11 +33,11 @@ module sonic-port { type string { pattern "Ethernet([1-3][0-9]{3}|[1-9][0-9]{2}|[1-9][0-9]|[0-9])"{ error-message "Invalid interface name"; - error-app-tag interface-name-invalid; - } + error-app-tag interface-name-invalid; + } } } - + leaf index { type uint16; } diff --git a/src/cvl/testdata/schema/Makefile b/src/cvl/testdata/schema/Makefile new file mode 100644 index 0000000000..daf398bd65 --- /dev/null +++ b/src/cvl/testdata/schema/Makefile @@ -0,0 +1,26 @@ +src_files=$(wildcard *.yang) +out=$(patsubst %.yang, %.yin, $(src_files)) +out_ext=$(patsubst %.yang, %.tree, $(src_files)) + +all:schema + +schema: $(out) + +%.yin:%.yang + @echo "Generating $@ ..." + @devFile="`echo $< | cut -d . -f1`-dev.yang"; \ + if [ -f $$devFile ] ; then devOpt="--deviation-module $$devFile"; fi; \ + pyang -p /home/pd945169/mgmt_framework_pr/sonic-mgmt-framework/src/cvl/schema:../../schema/:../../schema/ietf/ -f yin $$devOpt $< -o $@.tmp + @xmllint --noblanks $@.tmp > $@ + @rm -rf $@.tmp + +%.tree:%.yang + @echo "Generating $@ ..." + @devFile="`echo $< | cut -d . -f1`-dev.yang"; \ + if [ -f $$devFile ] ; then devOpt="--deviation-module $$devFile"; fi; \ + pyang -p ../../schema/:../../schema/ietf/ -f tree $$devOpt $< -o $@ + +clean: + @echo "Removing files ..." + rm -rf $(out) + rm -rf $(out_ext) diff --git a/src/cvl/schema/sonic-acl-dev.yang b/src/cvl/testdata/schema/sonic-acl-dev.yang similarity index 97% rename from src/cvl/schema/sonic-acl-dev.yang rename to src/cvl/testdata/schema/sonic-acl-dev.yang index 963a88303c..9c47e0fd0b 100644 --- a/src/cvl/schema/sonic-acl-dev.yang +++ b/src/cvl/testdata/schema/sonic-acl-dev.yang @@ -21,10 +21,10 @@ module sonic-acl-dev { organization - "BRCM"; + "SONiC"; contact - "BRCM"; + "SONiC"; description "SONIC ACLi Deviations"; diff --git a/src/cvl/schema/sonic-bgp-neighbor.yang b/src/cvl/testdata/schema/sonic-bgp-neighbor.yang similarity index 97% rename from src/cvl/schema/sonic-bgp-neighbor.yang rename to src/cvl/testdata/schema/sonic-bgp-neighbor.yang index f1cf321615..2264e5238e 100644 --- a/src/cvl/schema/sonic-bgp-neighbor.yang +++ b/src/cvl/testdata/schema/sonic-bgp-neighbor.yang @@ -19,10 +19,10 @@ module sonic-bgp-neighbor { } organization - "BRCM"; + "SONiC"; contact - "BRCM"; + "SONiC"; description "SONIC BGP NEIGHBOR"; diff --git a/src/cvl/schema/sonic-buffer-pg.yang b/src/cvl/testdata/schema/sonic-buffer-pg.yang similarity index 98% rename from src/cvl/schema/sonic-buffer-pg.yang rename to src/cvl/testdata/schema/sonic-buffer-pg.yang index 96af02e24c..61b5013fed 100644 --- a/src/cvl/schema/sonic-buffer-pg.yang +++ b/src/cvl/testdata/schema/sonic-buffer-pg.yang @@ -23,10 +23,10 @@ module sonic-buffer-pg { } organization - "BRCM"; + "SONiC"; contact - "BRCM"; + "SONiC"; description "SONIC BUFFER PG"; diff --git a/src/cvl/schema/sonic-buffer-pool.yang b/src/cvl/testdata/schema/sonic-buffer-pool.yang similarity index 96% rename from src/cvl/schema/sonic-buffer-pool.yang rename to src/cvl/testdata/schema/sonic-buffer-pool.yang index 2c6b6b3689..130c28287f 100644 --- a/src/cvl/schema/sonic-buffer-pool.yang +++ b/src/cvl/testdata/schema/sonic-buffer-pool.yang @@ -15,10 +15,10 @@ module sonic-buffer-pool { } organization - "BRCM"; + "SONiC"; contact - "BRCM"; + "SONiC"; description "SONIC BUFFER POOL"; diff --git a/src/cvl/schema/sonic-buffer-profile.yang b/src/cvl/testdata/schema/sonic-buffer-profile.yang similarity index 97% rename from src/cvl/schema/sonic-buffer-profile.yang rename to src/cvl/testdata/schema/sonic-buffer-profile.yang index 7d4c1c3dc5..895def38c4 100644 --- a/src/cvl/schema/sonic-buffer-profile.yang +++ b/src/cvl/testdata/schema/sonic-buffer-profile.yang @@ -19,10 +19,10 @@ module sonic-buffer-profile { } organization - "BRCM"; + "SONiC"; contact - "BRCM"; + "SONiC"; description "SONIC BUFFER PROFILE"; diff --git a/src/cvl/schema/sonic-cablelength.yang b/src/cvl/testdata/schema/sonic-cablelength.yang similarity index 97% rename from src/cvl/schema/sonic-cablelength.yang rename to src/cvl/testdata/schema/sonic-cablelength.yang index 3109294732..e4eeed031c 100644 --- a/src/cvl/schema/sonic-cablelength.yang +++ b/src/cvl/testdata/schema/sonic-cablelength.yang @@ -19,10 +19,10 @@ module sonic-cablelength { } organization - "BRCM"; + "SONiC"; contact - "BRCM"; + "SONiC"; description "SONIC CABLELENGTH"; diff --git a/src/cvl/schema/sonic-device-metadata.yang b/src/cvl/testdata/schema/sonic-device-metadata.yang similarity index 98% rename from src/cvl/schema/sonic-device-metadata.yang rename to src/cvl/testdata/schema/sonic-device-metadata.yang index 77ef8a1731..0bd953836b 100644 --- a/src/cvl/schema/sonic-device-metadata.yang +++ b/src/cvl/testdata/schema/sonic-device-metadata.yang @@ -15,10 +15,10 @@ module sonic-device-metadata { } organization - "BRCM"; + "SONiC"; contact - "BRCM"; + "SONiC"; description "SONIC DEVICE METADATA"; diff --git a/src/cvl/schema/sonic-device-neighbor.yang b/src/cvl/testdata/schema/sonic-device-neighbor.yang similarity index 98% rename from src/cvl/schema/sonic-device-neighbor.yang rename to src/cvl/testdata/schema/sonic-device-neighbor.yang index cba3eed0fc..9dc28187ef 100644 --- a/src/cvl/schema/sonic-device-neighbor.yang +++ b/src/cvl/testdata/schema/sonic-device-neighbor.yang @@ -20,10 +20,10 @@ module sonic-device-neighbor { organization - "BRCM"; + "SONiC"; contact - "BRCM"; + "SONiC"; description "SONIC DEVICE NEIGHBOR"; diff --git a/src/cvl/schema/sonic-dscp-tc-map.yang b/src/cvl/testdata/schema/sonic-dscp-tc-map.yang similarity index 97% rename from src/cvl/schema/sonic-dscp-tc-map.yang rename to src/cvl/testdata/schema/sonic-dscp-tc-map.yang index 449310367a..481cfbece0 100644 --- a/src/cvl/schema/sonic-dscp-tc-map.yang +++ b/src/cvl/testdata/schema/sonic-dscp-tc-map.yang @@ -15,10 +15,10 @@ module sonic-dscp-tc-map { } organization - "BRCM"; + "SONiC"; contact - "BRCM"; + "SONiC"; description "SONIC DSCP_TO_TC_MAP"; diff --git a/src/cvl/schema/sonic-pf-limits.yang b/src/cvl/testdata/schema/sonic-pf-limits.yang similarity index 96% rename from src/cvl/schema/sonic-pf-limits.yang rename to src/cvl/testdata/schema/sonic-pf-limits.yang index 984e649888..6b92e97dba 100644 --- a/src/cvl/schema/sonic-pf-limits.yang +++ b/src/cvl/testdata/schema/sonic-pf-limits.yang @@ -16,10 +16,10 @@ module sonic-pf-limits { } organization - "BRCM"; + "SONiC"; contact - "BRCM"; + "SONiC"; description "SONIC Platform constrainst"; diff --git a/src/cvl/schema/sonic-pfc-priority-queue-map.yang b/src/cvl/testdata/schema/sonic-pfc-priority-queue-map.yang similarity index 97% rename from src/cvl/schema/sonic-pfc-priority-queue-map.yang rename to src/cvl/testdata/schema/sonic-pfc-priority-queue-map.yang index e1a08c07cb..b5c8952e6b 100644 --- a/src/cvl/schema/sonic-pfc-priority-queue-map.yang +++ b/src/cvl/testdata/schema/sonic-pfc-priority-queue-map.yang @@ -11,10 +11,10 @@ module sonic-pfc-priority-queue-map { } organization - "BRCM"; + "SONiC"; contact - "BRCM"; + "SONiC"; description "SONIC MAP_PFC_PRIORITY_TO_QUEUE"; diff --git a/src/cvl/schema/sonic-port-qos-map.yang b/src/cvl/testdata/schema/sonic-port-qos-map.yang similarity index 98% rename from src/cvl/schema/sonic-port-qos-map.yang rename to src/cvl/testdata/schema/sonic-port-qos-map.yang index 04838ae775..eeb5ca0bbc 100644 --- a/src/cvl/schema/sonic-port-qos-map.yang +++ b/src/cvl/testdata/schema/sonic-port-qos-map.yang @@ -31,10 +31,10 @@ module sonic-port-qos-map { } organization - "BRCM"; + "SONiC"; contact - "BRCM"; + "SONiC"; description "SONIC PORT_QOS_MAP"; diff --git a/src/cvl/schema/sonic-portchannel-interface.yang b/src/cvl/testdata/schema/sonic-portchannel-interface.yang similarity index 97% rename from src/cvl/schema/sonic-portchannel-interface.yang rename to src/cvl/testdata/schema/sonic-portchannel-interface.yang index 2bfc4cc006..305fd6ae76 100644 --- a/src/cvl/schema/sonic-portchannel-interface.yang +++ b/src/cvl/testdata/schema/sonic-portchannel-interface.yang @@ -19,10 +19,10 @@ module sonic-portchannel-interface { } organization - "BRCM"; + "SONiC"; contact - "BRCM"; + "SONiC"; description "SONIC PORTCHANNEL INTERFACE"; diff --git a/src/cvl/schema/sonic-portchannel.yang b/src/cvl/testdata/schema/sonic-portchannel.yang similarity index 97% rename from src/cvl/schema/sonic-portchannel.yang rename to src/cvl/testdata/schema/sonic-portchannel.yang index 25b08d5785..4ecd3a33d6 100644 --- a/src/cvl/schema/sonic-portchannel.yang +++ b/src/cvl/testdata/schema/sonic-portchannel.yang @@ -15,10 +15,10 @@ module sonic-portchannel { } organization - "BRCM"; + "SONiC"; contact - "BRCM"; + "SONiC"; description "SONIC PORTCHANNEL"; diff --git a/src/cvl/schema/sonic-queue.yang b/src/cvl/testdata/schema/sonic-queue.yang similarity index 98% rename from src/cvl/schema/sonic-queue.yang rename to src/cvl/testdata/schema/sonic-queue.yang index e3be11691b..fb55793443 100644 --- a/src/cvl/schema/sonic-queue.yang +++ b/src/cvl/testdata/schema/sonic-queue.yang @@ -23,10 +23,10 @@ module sonic-queue { } organization - "BRCM"; + "SONiC"; contact - "BRCM"; + "SONiC"; description "SONIC QUEUE"; diff --git a/src/cvl/schema/sonic-scheduler.yang b/src/cvl/testdata/schema/sonic-scheduler.yang similarity index 96% rename from src/cvl/schema/sonic-scheduler.yang rename to src/cvl/testdata/schema/sonic-scheduler.yang index 0b0745185b..d1e26ab359 100644 --- a/src/cvl/schema/sonic-scheduler.yang +++ b/src/cvl/testdata/schema/sonic-scheduler.yang @@ -11,10 +11,10 @@ module sonic-scheduler { } organization - "BRCM"; + "SONiC"; contact - "BRCM"; + "SONiC"; description "SONIC SCHEDULER"; diff --git a/src/cvl/schema/sonic-tc-priority-group-map.yang b/src/cvl/testdata/schema/sonic-tc-priority-group-map.yang similarity index 97% rename from src/cvl/schema/sonic-tc-priority-group-map.yang rename to src/cvl/testdata/schema/sonic-tc-priority-group-map.yang index 6f7ec329d7..253ed0f47b 100644 --- a/src/cvl/schema/sonic-tc-priority-group-map.yang +++ b/src/cvl/testdata/schema/sonic-tc-priority-group-map.yang @@ -11,10 +11,10 @@ module sonic-tc-priority-group-map { } organization - "BRCM"; + "SONiC"; contact - "BRCM"; + "SONiC"; description "SONIC TC_TO_PRIORITY_GROUP_MAP"; diff --git a/src/cvl/schema/sonic-tc-queue-map.yang b/src/cvl/testdata/schema/sonic-tc-queue-map.yang similarity index 97% rename from src/cvl/schema/sonic-tc-queue-map.yang rename to src/cvl/testdata/schema/sonic-tc-queue-map.yang index a2473d3985..385b9edfac 100644 --- a/src/cvl/schema/sonic-tc-queue-map.yang +++ b/src/cvl/testdata/schema/sonic-tc-queue-map.yang @@ -11,10 +11,10 @@ module sonic-tc-queue-map { } organization - "BRCM"; + "SONiC"; contact - "BRCM"; + "SONiC"; description "SONIC TC_TO_QUEUE_MAP"; diff --git a/src/cvl/schema/sonic-vlan-dev.yang b/src/cvl/testdata/schema/sonic-vlan-dev.yang similarity index 96% rename from src/cvl/schema/sonic-vlan-dev.yang rename to src/cvl/testdata/schema/sonic-vlan-dev.yang index 9ee9e6eede..dcb6531126 100644 --- a/src/cvl/schema/sonic-vlan-dev.yang +++ b/src/cvl/testdata/schema/sonic-vlan-dev.yang @@ -12,10 +12,10 @@ module sonic-vlan-dev { } organization - "BRCM"; + "SONiC"; contact - "BRCM"; + "SONiC"; description "SONIC VLAN deviation file"; diff --git a/src/cvl/testdata/schema/sonic-vlan-dev.yin.tmp b/src/cvl/testdata/schema/sonic-vlan-dev.yin.tmp new file mode 100644 index 0000000000..1ccfd03006 --- /dev/null +++ b/src/cvl/testdata/schema/sonic-vlan-dev.yin.tmp @@ -0,0 +1,30 @@ + + + + + + + + + + + + + SONiC + + + SONiC + + + SONIC VLAN deviation file + + + + Initial revision. + + + diff --git a/src/cvl/schema/sonic-vlan-interface.yang b/src/cvl/testdata/schema/sonic-vlan-interface.yang similarity index 97% rename from src/cvl/schema/sonic-vlan-interface.yang rename to src/cvl/testdata/schema/sonic-vlan-interface.yang index 7f186b9ff0..86b9f8c0f3 100644 --- a/src/cvl/schema/sonic-vlan-interface.yang +++ b/src/cvl/testdata/schema/sonic-vlan-interface.yang @@ -19,10 +19,10 @@ module sonic-vlan-interface { } organization - "BRCM"; + "SONiC"; contact - "BRCM"; + "SONiC"; description "SONIC VLAN INTERFACE"; diff --git a/src/cvl/schema/sonic-vlan.yang b/src/cvl/testdata/schema/sonic-vlan.yang similarity index 98% rename from src/cvl/schema/sonic-vlan.yang rename to src/cvl/testdata/schema/sonic-vlan.yang index f8c0bc1b48..5a043b5f22 100644 --- a/src/cvl/schema/sonic-vlan.yang +++ b/src/cvl/testdata/schema/sonic-vlan.yang @@ -20,10 +20,10 @@ module sonic-vlan { } organization - "BRCM"; + "SONiC"; contact - "BRCM"; + "SONiC"; description "SONIC VLAN"; diff --git a/src/cvl/schema/sonic-wred-profile.yang b/src/cvl/testdata/schema/sonic-wred-profile.yang similarity index 98% rename from src/cvl/schema/sonic-wred-profile.yang rename to src/cvl/testdata/schema/sonic-wred-profile.yang index 96ddd89d64..89b9c90ef5 100644 --- a/src/cvl/schema/sonic-wred-profile.yang +++ b/src/cvl/testdata/schema/sonic-wred-profile.yang @@ -11,10 +11,10 @@ module sonic-wred-profile { } organization - "BRCM"; + "SONiC"; contact - "BRCM"; + "SONiC"; description "SONIC WRED_PROFILE"; diff --git a/src/cvl/tests/Makefile b/src/cvl/tests/Makefile index 36ddbc1a33..64b8eb1c6c 100644 --- a/src/cvl/tests/Makefile +++ b/src/cvl/tests/Makefile @@ -9,6 +9,7 @@ all:tests tests: $(OUT) %:%.go + make -C ../testdata/schema @echo "Building $@ ..." GOPATH=$(GOPATH) $(GO) build -gcflags="all=-N -l" $< From 4dd512a15fe6df14ece91a1d701d2ab228147990 Mon Sep 17 00:00:00 2001 From: Partha Dutta Date: Wed, 18 Sep 2019 10:33:20 +0530 Subject: [PATCH 138/214] Updated Makefiles --- src/cvl/Makefile | 3 +-- src/cvl/internal/yparser/yparser.go | 8 ++------ src/cvl/testdata/schema/Makefile | 5 ++--- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/src/cvl/Makefile b/src/cvl/Makefile index 198a541290..54c3980818 100644 --- a/src/cvl/Makefile +++ b/src/cvl/Makefile @@ -53,8 +53,7 @@ gotest: make -C schema make -C testdata/schema cp schema/*.yin testdata/schema - #CVL_CFG_FILE=$(abspath .)/conf/cvl_cfg.json CVL_SCHEMA_PATH=$(abspath .)/schema:$(abspath .)/testdata/schema GOPATH=$(GOPATH) tests/run_test.sh - CVL_CFG_FILE=$(abspath .)/conf/cvl_cfg.json CVL_SCHEMA_PATH=$(abspath .)/schema GOPATH=$(GOPATH) tests/run_test.sh + CVL_CFG_FILE=$(abspath .)/conf/cvl_cfg.json CVL_SCHEMA_PATH=$(abspath .)/testdata/schema GOPATH=$(GOPATH) tests/run_test.sh clean: make -C tests clean diff --git a/src/cvl/internal/yparser/yparser.go b/src/cvl/internal/yparser/yparser.go index a654d34fc2..a41a058507 100644 --- a/src/cvl/internal/yparser/yparser.go +++ b/src/cvl/internal/yparser/yparser.go @@ -7,7 +7,6 @@ import ( "strings" log "github.com/golang/glog" . "cvl/internal/util" - "fmt" ) /* @@ -236,10 +235,7 @@ func ParseSchemaFile(modelFile string) (*YParserModule, YParserError) { module := C.lys_parse_path((*C.struct_ly_ctx)(ypCtx), C.CString(modelFile), C.LYS_IN_YIN) if module == nil { - fmt.Printf("\n\nFailed Parsed file .... %s\n\n", modelFile) return nil, getErrorDetails() - } else { - fmt.Printf("\n\nParsed file .... %s\n\n", modelFile) } if (strings.Contains(modelFile, "sonic-common.yin") == true) { @@ -254,11 +250,11 @@ func ParseSchemaFile(modelFile string) (*YParserModule, YParserError) { //Add child node to a parent node func(yp *YParser) AddChildNode(module *YParserModule, parent *YParserNode, name string) *YParserNode { - //return (*YParserNode)(C.lyd_new((*C.struct_lyd_node)(parent), (*C.struct_lys_module)(module), C.CString(name))) ret := (*YParserNode)(C.lyd_new((*C.struct_lyd_node)(parent), (*C.struct_lys_module)(module), C.CString(name))) if (ret == nil) { - fmt.Printf("\n\nFailed parsing .... %s\n\n", name) + TRACE_LOG(INFO_DEBUG, TRACE_YPARSER, "Failed parsing node %s\n", name) } + return ret } diff --git a/src/cvl/testdata/schema/Makefile b/src/cvl/testdata/schema/Makefile index daf398bd65..8fabd881ed 100644 --- a/src/cvl/testdata/schema/Makefile +++ b/src/cvl/testdata/schema/Makefile @@ -10,7 +10,7 @@ schema: $(out) @echo "Generating $@ ..." @devFile="`echo $< | cut -d . -f1`-dev.yang"; \ if [ -f $$devFile ] ; then devOpt="--deviation-module $$devFile"; fi; \ - pyang -p /home/pd945169/mgmt_framework_pr/sonic-mgmt-framework/src/cvl/schema:../../schema/:../../schema/ietf/ -f yin $$devOpt $< -o $@.tmp + pyang -p ../../schema/:../../schema/ietf/ -f yin $$devOpt $< -o $@.tmp @xmllint --noblanks $@.tmp > $@ @rm -rf $@.tmp @@ -22,5 +22,4 @@ schema: $(out) clean: @echo "Removing files ..." - rm -rf $(out) - rm -rf $(out_ext) + rm -rf *.yin From a2714372ad7373ac826997c2d68b849eda1aa08e Mon Sep 17 00:00:00 2001 From: Partha Dutta Date: Wed, 18 Sep 2019 10:45:49 +0530 Subject: [PATCH 139/214] Delete file checked in mistakenly. --- .../testdata/schema/sonic-vlan-dev.yin.tmp | 30 ------------------- 1 file changed, 30 deletions(-) delete mode 100644 src/cvl/testdata/schema/sonic-vlan-dev.yin.tmp diff --git a/src/cvl/testdata/schema/sonic-vlan-dev.yin.tmp b/src/cvl/testdata/schema/sonic-vlan-dev.yin.tmp deleted file mode 100644 index 1ccfd03006..0000000000 --- a/src/cvl/testdata/schema/sonic-vlan-dev.yin.tmp +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - SONiC - - - SONiC - - - SONIC VLAN deviation file - - - - Initial revision. - - - From 692beca2ab2d5f4850ecb9ddab7c6fdeb377c5cb Mon Sep 17 00:00:00 2001 From: Partha Dutta Date: Wed, 18 Sep 2019 11:30:44 +0530 Subject: [PATCH 140/214] Updated new Makefile with license, copy schema from testdata/schema also. --- Makefile | 1 + src/cvl/schema/sonic-acl.yang | 8 ++++---- src/cvl/testdata/schema/Makefile | 19 +++++++++++++++++++ src/cvl/testdata/schema/sonic-acl-dev.yang | 2 +- 4 files changed, 25 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index d2f9b1fe07..01d0a951db 100644 --- a/Makefile +++ b/Makefile @@ -101,6 +101,7 @@ install: $(INSTALL) -d $(DESTDIR)/usr/sbin/schema/ $(INSTALL) -d $(DESTDIR)/usr/sbin/lib/ $(INSTALL) -D $(TOPDIR)/src/cvl/schema/*.yin $(DESTDIR)/usr/sbin/schema/ + $(INSTALL) -D $(TOPDIR)/src/cvl/testdata/schema/*.yin $(DESTDIR)/usr/sbin/schema/ cp -rf $(TOPDIR)/build/rest_server/dist/ui/ $(DESTDIR)/rest_ui/ cp -rf $(TOPDIR)/build/cli $(DESTDIR)/usr/sbin/ cp -rf $(TOPDIR)/build/swagger_client_py/ $(DESTDIR)/usr/sbin/lib/ diff --git a/src/cvl/schema/sonic-acl.yang b/src/cvl/schema/sonic-acl.yang index c2a96aaccb..fc65e5ac4a 100644 --- a/src/cvl/schema/sonic-acl.yang +++ b/src/cvl/schema/sonic-acl.yang @@ -143,11 +143,11 @@ module sonic-acl { } leaf ETHER_TYPE { - type string{ - pattern "(0x88CC)|(0x8100)|(0x8915)|(0x0806)|(0x0800)|(0x86DD)|(0x8847)"{ + type string { + pattern "(0x88CC)|(0x8100)|(0x8915)|(0x0806)|(0x0800)|(0x86DD)|(0x8847)" { error-message "Invalid ACL Rule Ether Type"; - error-app-tag ether-type-invalid; - } + error-app-tag ether-type-invalid; + } } } diff --git a/src/cvl/testdata/schema/Makefile b/src/cvl/testdata/schema/Makefile index 8fabd881ed..308b3eaf6b 100644 --- a/src/cvl/testdata/schema/Makefile +++ b/src/cvl/testdata/schema/Makefile @@ -1,3 +1,22 @@ +################################################################################ +# # +# Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or # +# its subsidiaries. # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); # +# you may not use this file except in compliance with the License. # +# You may obtain a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +# # +################################################################################ + src_files=$(wildcard *.yang) out=$(patsubst %.yang, %.yin, $(src_files)) out_ext=$(patsubst %.yang, %.tree, $(src_files)) diff --git a/src/cvl/testdata/schema/sonic-acl-dev.yang b/src/cvl/testdata/schema/sonic-acl-dev.yang index 9c47e0fd0b..7fcf99f931 100644 --- a/src/cvl/testdata/schema/sonic-acl-dev.yang +++ b/src/cvl/testdata/schema/sonic-acl-dev.yang @@ -27,7 +27,7 @@ module sonic-acl-dev { "SONiC"; description - "SONIC ACLi Deviations"; + "SONIC ACL Deviations"; revision 2019-05-15 { description From 1b9a60f8ddb99b631f1c8229150cc340329daf35 Mon Sep 17 00:00:00 2001 From: Mayank Maheshwari Date: Wed, 18 Sep 2019 16:19:23 +0530 Subject: [PATCH 141/214] Updated License statement --- src/translib/ocbinds/oc.go | 19 +++++++++++++ src/translib/tlerr/app_errors.go | 24 ++++++++++++----- src/translib/tlerr/tlerr.go | 46 +++++++++++++++++++++----------- 3 files changed, 67 insertions(+), 22 deletions(-) diff --git a/src/translib/ocbinds/oc.go b/src/translib/ocbinds/oc.go index 91b532c907..2e3b833ece 100644 --- a/src/translib/ocbinds/oc.go +++ b/src/translib/ocbinds/oc.go @@ -1,3 +1,22 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// + package ocbinds //go:generate sh -c "/usr/local/go/bin/go run $BUILD_GOPATH/src/github.com/openconfig/ygot/generator/generator.go -generate_fakeroot -output_file ocbinds.go -package_name ocbinds -generate_fakeroot -fakeroot_name=device -compress_paths=false -exclude_modules ietf-interfaces -path . $(find ../../../models/yang -name '*.yang' | sort)" diff --git a/src/translib/tlerr/app_errors.go b/src/translib/tlerr/app_errors.go index dec7b03184..d695954326 100644 --- a/src/translib/tlerr/app_errors.go +++ b/src/translib/tlerr/app_errors.go @@ -1,9 +1,21 @@ -/////////////////////////////////////////////////////////////////////// -// -// Copyright 2019 Broadcom. All rights reserved. -// The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. -// -/////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// package tlerr diff --git a/src/translib/tlerr/tlerr.go b/src/translib/tlerr/tlerr.go index a0c799b386..8ff1254301 100644 --- a/src/translib/tlerr/tlerr.go +++ b/src/translib/tlerr/tlerr.go @@ -1,7 +1,21 @@ -/* -Copyright 2019 Broadcom. All rights reserved. -The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. -*/ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or // +// its subsidiaries. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// /* Package tlerr defines the errors of the translib library. @@ -17,15 +31,15 @@ Hence, it cannot occur here. package tlerr import ( -// "fmt" - "golang.org/x/text/message" - "golang.org/x/text/language" + // "fmt" "cvl" -// "errors" -// "strings" + "golang.org/x/text/language" + "golang.org/x/text/message" + // "errors" + // "strings" ) -var p * message.Printer +var p *message.Printer func init() { p = message.NewPrinter(language.English) @@ -48,7 +62,7 @@ func (e TranslibDBNotInit) Error() string { } type TranslibRedisClientEntryNotExist struct { - Entry string + Entry string } func (e TranslibRedisClientEntryNotExist) Error() string { @@ -56,8 +70,8 @@ func (e TranslibRedisClientEntryNotExist) Error() string { } type TranslibCVLFailure struct { - Code int - CVLErrorInfo cvl.CVLErrorInfo + Code int + CVLErrorInfo cvl.CVLErrorInfo } func (e TranslibCVLFailure) Error() string { @@ -80,10 +94,10 @@ func (e TranslibDBSubscribeFail) Error() string { } type TranslibSyntaxValidationError struct { - StatusCode int // status code - ErrorStr error // error message + StatusCode int // status code + ErrorStr error // error message } func (e TranslibSyntaxValidationError) Error() string { - return p.Sprintf("%s", e.ErrorStr) + return p.Sprintf("%s", e.ErrorStr) } From 009158010bb2a67f407e824bbac97780703c9f33 Mon Sep 17 00:00:00 2001 From: Mayank Maheshwari Date: Wed, 18 Sep 2019 16:38:03 +0530 Subject: [PATCH 142/214] Update License statement --- go_server.sh | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/go_server.sh b/go_server.sh index de3be2c253..4c13c1aa2f 100755 --- a/go_server.sh +++ b/go_server.sh @@ -1,5 +1,24 @@ #!/usr/bin/env bash +################################################################################ +# # +# Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or # +# its subsidiaries. # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); # +# you may not use this file except in compliance with the License. # +# You may obtain a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +# # +################################################################################ + set -e TOPDIR=$PWD From d50801c740cea50925f99628cd8d3b1350663c3b Mon Sep 17 00:00:00 2001 From: s-mari Date: Wed, 18 Sep 2019 15:55:00 -0700 Subject: [PATCH 143/214] error handling and code clean-up --- src/translib/transformer/transformer.go | 5 +- src/translib/transformer/xfmr_path_utils.go | 102 -------------------- 2 files changed, 4 insertions(+), 103 deletions(-) diff --git a/src/translib/transformer/transformer.go b/src/translib/transformer/transformer.go index f10c007c17..e6649cff2c 100644 --- a/src/translib/transformer/transformer.go +++ b/src/translib/transformer/transformer.go @@ -72,7 +72,10 @@ func init() { yangFiles = getDefaultModelsList() yangFiles = append(yangFiles, ocList...) fmt.Println("Yang model List:", yangFiles) - loadYangModules(yangFiles...) + err := loadYangModules(yangFiles...) + if err != nil { + fmt.Fprintln(os.Stderr, err) + } } func loadYangModules(files ...string) error { diff --git a/src/translib/transformer/xfmr_path_utils.go b/src/translib/transformer/xfmr_path_utils.go index 494cf02759..8a052cd24c 100644 --- a/src/translib/transformer/xfmr_path_utils.go +++ b/src/translib/transformer/xfmr_path_utils.go @@ -10,7 +10,6 @@ package transformer import ( "bytes" "fmt" - "strconv" "strings" ) @@ -27,18 +26,6 @@ func (p *PathInfo) Var(name string) string { return p.Vars[name] } -// IntVar returns the value for a path variable as an int. -// Returns 0 if no such variable exists. Returns an error -// if the value is not an integer. -func (p *PathInfo) IntVar(name string) (int, error) { - val := p.Vars[name] - if len(val) == 0 { - return 0, nil - } - - return strconv.Atoi(val) -} - // NewPathInfo parses given path string into a PathInfo structure. func NewPathInfo(path string) *PathInfo { var info PathInfo @@ -110,92 +97,3 @@ func RemoveXPATHPredicates(s string) (string, error) { return b.String(), nil } - -// stripPrefix removes the prefix from a YANG path element. For example, removing -// foo from "foo:bar". Such qualified paths are used in YANG modules where remote -// paths are referenced. -func stripPrefix(name string) (string, error) { - ps := strings.Split(name, ":") - switch len(ps) { - case 1: - return name, nil - case 2: - return ps[1], nil - } - return "", fmt.Errorf("path element did not form a valid name (name, prefix:name): %v", name) -} -/* -func getParentNode(targetUri *string, deviceObj *ocbinds.Device) (*interface{}, *yang.Entry, error) { - path, err := ygot.StringToPath(*targetUri, ygot.StructuredPath, ygot.StringSlicePath) - if err != nil { - return nil, nil, err - } - - var pathList []*gnmi.PathElem = path.Elem - - parentPath := &gnmi.Path{} - - for i := 0; i < (len(pathList) - 1); i++ { - pathSlice := strings.Split(pathList[i].Name, ":") - pathList[i].Name = pathSlice[len(pathSlice)-1] - parentPath.Elem = append(parentPath.Elem, pathList[i]) - } - - treeNodeList, err2 := ytypes.GetNode(ygSchema.RootSchema(), deviceObj, parentPath) - if err2 != nil { - return nil, nil, err2 - } - - if len(treeNodeList) == 0 { - return nil, nil, errors.New("Invalid URI") - } - - return &(treeNodeList[0].Data), treeNodeList[0].Schema, nil -} - -func getNodeName(targetUri *string, deviceObj *ocbinds.Device) (string, error) { - path, err := ygot.StringToPath(*targetUri, ygot.StructuredPath, ygot.StringSlicePath) - if err != nil { - log.Error("Error in uri to path conversion: ", err) - return "", err - } - - pathList := path.Elem - for i := 0; i < len(pathList); i++ { - pathSlice := strings.Split(pathList[i].Name, ":") - pathList[i].Name = pathSlice[len(pathSlice)-1] - } - - treeNodeList, err := ytypes.GetNode(ygSchema.RootSchema(), deviceObj, path) - if err != nil { - log.Error("Error in uri to path conversion: ", err) - return "", err - } - - if len(treeNodeList) == 0 { - return "", errors.New("Invalid URI") - } - - return treeNodeList[0].Schema.Name, nil -} - -func getObjectFieldName(targetUri *string, deviceObj *ocbinds.Device, ygotTarget *interface{}) (string, error) { - parentObjIntf, _, err := getParentNode(targetUri, deviceObj) - if err != nil { - return "", err - } - valObj := reflect.ValueOf(*parentObjIntf).Elem() - parentObjType := reflect.TypeOf(*parentObjIntf).Elem() - - for i := 0; i < parentObjType.NumField(); i++ { - if reflect.ValueOf(*ygotTarget).Kind() == reflect.Ptr && valObj.Field(i).Kind() == reflect.Ptr { - if valObj.Field(i).Pointer() == reflect.ValueOf(*ygotTarget).Pointer() { - return parentObjType.Field(i).Name, nil - } - } else if valObj.Field(i).String() == reflect.ValueOf(*ygotTarget).String() { - return parentObjType.Field(i).Name, nil - } - } - return "", errors.New("Target object not found") -} -*/ From b4ca046c12ce7a24e4ffa038745220f7a828d912 Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Wed, 18 Sep 2019 18:52:53 -0700 Subject: [PATCH 144/214] Add error handling in xlate_utils.go --- src/translib/transformer/xlate_to_db.go | 2 +- src/translib/transformer/xlate_utils.go | 97 +++++++++++++++++-------- 2 files changed, 68 insertions(+), 31 deletions(-) diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index f2dd96ad95..3bc0361946 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -304,7 +304,7 @@ func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, } for _, data := range dataMap { curKey := "" - curUri := uriWithKeyCreate(uri, xpathPrefix, data) + curUri, _ := uriWithKeyCreate(uri, xpathPrefix, data) if len(xSpecMap[xpathPrefix].xfmrKey) > 0 { /* key transformer present */ inParams := formXfmrInputRequest(d, dbs, db.MaxDB, ygRoot, curUri, oper, "", nil, nil) diff --git a/src/translib/transformer/xlate_utils.go b/src/translib/transformer/xlate_utils.go index 73a371cef0..38addb96df 100644 --- a/src/translib/transformer/xlate_utils.go +++ b/src/translib/transformer/xlate_utils.go @@ -26,20 +26,24 @@ func keyFromXpathCreate(keyList []string) string { /* Create db key from data xpath(request) */ func keyCreate(keyPrefix string, xpath string, data interface{}) string { - yangEntry := xSpecMap[xpath].yangEntry - if len(keyPrefix) > 0 { keyPrefix += "|" } - - keyVal := "" - for i, k := range (strings.Split(yangEntry.Key, " ")) { - if i > 0 { keyVal = keyVal + "_" } - val := fmt.Sprint(data.(map[string]interface{})[k]) - if strings.Contains(val, ":") { - val = strings.Split(val, ":")[1] - } - keyVal += val - } - keyPrefix += string(keyVal) - return keyPrefix + _, ok := xSpecMap[xpath] + if ok { + if xSpecMap[xpath].yangEntry != nil { + yangEntry := xSpecMap[xpath].yangEntry + if len(keyPrefix) > 0 { keyPrefix += "|" } + keyVal := "" + for i, k := range (strings.Split(yangEntry.Key, " ")) { + if i > 0 { keyVal = keyVal + "_" } + val := fmt.Sprint(data.(map[string]interface{})[k]) + if strings.Contains(val, ":") { + val = strings.Split(val, ":")[1] + } + keyVal += val + } + keyPrefix += string(keyVal) + } + } + return keyPrefix } /* Copy redis-db source to destn map */ @@ -85,6 +89,19 @@ func yangTypeGet(entry *yang.Entry) string { } func dbKeyToYangDataConvert(uri string, xpath string, dbKey string) (map[string]interface{}, string, string, error) { + var err error + if len(uri) == 0 && len(xpath) == 0 && len(dbKey) == 0 { + err = fmt.Errorf("Insufficient input") + return nil, "", "", err + } + + if _, ok := xSpecMap[xpath]; ok { + if xSpecMap[xpath].yangEntry == nil { + err = fmt.Errorf("Yang Entry not available for xpath ", xpath) + return nil, "", "", nil + } + } + var kLvlValList []string keyDataList := strings.Split(dbKey, "|") keyNameList := yangKeyFromEntryGet(xSpecMap[xpath].yangEntry) @@ -104,7 +121,7 @@ func dbKeyToYangDataConvert(uri string, xpath string, dbKey string) (map[string] if err != nil { return nil, "","",err } - rmap := ret[0].Interface().(map[string]interface{}) + rmap := ret[0].Interface().(map[string]interface{}) for k, v := range rmap { jsonData += fmt.Sprintf("\"%v\" : \"%v\",\r\n", k, v) uriWithKey += fmt.Sprintf("[%v=%v]", k, v) @@ -140,8 +157,7 @@ func dbKeyToYangDataConvert(uri string, xpath string, dbKey string) (map[string] } return rmap, uriWithKey, jsonData, nil - } - +} func contains(sl []string, str string) bool { for _, v := range sl { @@ -152,9 +168,11 @@ func contains(sl []string, str string) bool { return false } - func isSubtreeRequest(targetUriPath string, nodePath string) bool { - return strings.HasPrefix(targetUriPath, nodePath) + if len(targetUriPath) > 0 && len(nodePath) > 0 { + return strings.HasPrefix(targetUriPath, nodePath) + } + return false } func getYangPathFromUri(uri string) (string, error) { @@ -209,17 +227,29 @@ func yangToDbXfmrFunc(funcName string) string { return ("YangToDb_" + funcName) } -func uriWithKeyCreate (uri string, xpathTmplt string, data interface{}) string { - yangEntry := xSpecMap[xpathTmplt].yangEntry - for _, k := range (strings.Split(yangEntry.Key, " ")) { - uri += fmt.Sprintf("[%v=%v]", k, data.(map[string]interface{})[k]) +func uriWithKeyCreate (uri string, xpathTmplt string, data interface{}) (string, error) { + var err error + if _, ok := xSpecMap[xpathTmplt]; ok { + yangEntry := xSpecMap[xpathTmplt].yangEntry + if yangEntry != nil { + for _, k := range (strings.Split(yangEntry.Key, " ")) { + uri += fmt.Sprintf("[%v=%v]", k, data.(map[string]interface{})[k]) + } + } else { + err = fmt.Errorf("Yang Entry not available for xpath ", xpathTmplt) + } + } else { + err = fmt.Errorf("No entry in xSpecMap for xpath ", xpathTmplt) } - return uri + return uri, err } func xpathRootNameGet(path string) string { - pathl := strings.Split(path, "/") - return ("/" + pathl[1]) + if len(path) > 0 { + pathl := strings.Split(path, "/") + return ("/" + pathl[1]) + } + return "" } func getDbNum(xpath string ) db.DBNum { @@ -241,11 +271,13 @@ func uriModuleNameGet(uri string) (string, error) { result := "" if len(uri) == 0 { log.Error("Empty uri string supplied") + err = fmt.Errorf("Empty uri string supplied") return result, err } urislice := strings.Split(uri, ":") if len(urislice) == 1 { log.Errorf("uri string %s does not have module name", uri) + err = fmt.Errorf("uri string does not have module name: ", uri) return result, err } moduleNm := strings.Split(urislice[0], "/") @@ -259,7 +291,7 @@ func uriModuleNameGet(uri string) (string, error) { } func recMap(rMap interface{}, name []string, id int, max int) { - if id == max { + if id == max || id < 0 { return } val := name[id] @@ -279,13 +311,18 @@ func recMap(rMap interface{}, name []string, id int, max int) { func mapCreate(xpath string) map[string]interface{} { retMap := make(map[string]interface{}) - attrList := strings.Split(xpath, "/") - alLen := len(attrList) - recMap(retMap, attrList, 1, alLen) + if len(xpath) > 0 { + attrList := strings.Split(xpath, "/") + alLen := len(attrList) + recMap(retMap, attrList, 1, alLen) + } return retMap } func mapInstGet(name []string, id int, max int, inMap interface{}) map[string]interface{} { + if inMap == nil { + return nil + } result := reflect.ValueOf(inMap).Interface().(map[string]interface{}) if id == max { return result From fdcdfc4c431aa4e809a5ecbbee8ecbbedfa69322 Mon Sep 17 00:00:00 2001 From: Kwan Kim Date: Thu, 19 Sep 2019 00:31:35 -0700 Subject: [PATCH 145/214] fix the uint64 encoding, fix the ygot bug in handling the union type of leafref --- src/translib/transformer/xlate_from_db.go | 8 ++------ ygot-modified-files/leaf.go | 14 +++++++++++--- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index 35c4b227b7..3637f2c99b 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -108,22 +108,18 @@ func DbToYangType(yngTerminalNdDtType yang.TypeKind, fldXpath string, dbFldVal s res, err = DbValToInt(dbFldVal, INTBASE, 16, false) case yang.Yint32: res, err = DbValToInt(dbFldVal, INTBASE, 32, false) - case yang.Yint64: - res, err = DbValToInt(dbFldVal, INTBASE, 64, false) case yang.Yuint8: res, err = DbValToInt(dbFldVal, INTBASE, 8, true) case yang.Yuint16: res, err = DbValToInt(dbFldVal, INTBASE, 16, true) case yang.Yuint32: res, err = DbValToInt(dbFldVal, INTBASE, 32, true) - case yang.Yuint64: - res, err = DbValToInt(dbFldVal, INTBASE, 64, true) case yang.Ybool: if res, err = strconv.ParseBool(dbFldVal); err != nil { log.Warning("Non Bool type for yang leaf-list item %v", dbFldVal) } - //TODO enhance Yunion using yangEntry way - case yang.Yenum, yang.Ystring, yang.Yidentityref, yang.Yunion: + case yang.Ybinary, yang.Ydecimal64, yang.Yenum, yang.Yidentityref, yang.Yint64, yang.Yuint64, yang.Ystring: + // Make sure to encode as string, expected by util_types.go: ytypes.yangToJSONType log.Info("Yenum/Ystring/Yunion(having all members as strings) type for yangXpath ", fldXpath) res = dbFldVal case yang.Yempty: diff --git a/ygot-modified-files/leaf.go b/ygot-modified-files/leaf.go index 7440e551e8..605029bef4 100644 --- a/ygot-modified-files/leaf.go +++ b/ygot-modified-files/leaf.go @@ -252,7 +252,7 @@ func validateUnion(schema *yang.Entry, value interface{}) util.Errors { // during validation against each matching schema otherwise. func validateMatchingSchemas(schema *yang.Entry, value interface{}) util.Errors { var errors []error - ss := findMatchingSchemasInUnion(schema.Type, value) + ss := findMatchingSchemasInUnion(schema, schema.Type, value) var kk []yang.TypeKind for _, s := range ss { kk = append(kk, s.Type.Kind) @@ -283,17 +283,25 @@ func validateMatchingSchemas(schema *yang.Entry, value interface{}) util.Errors // findMatchingSchemasInUnion returns all schemas in the given union type, // including those within nested unions, that match the Go type of value. // value must not be nil. -func findMatchingSchemasInUnion(ytype *yang.YangType, value interface{}) []*yang.Entry { +func findMatchingSchemasInUnion(schema *yang.Entry, ytype *yang.YangType, value interface{}) []*yang.Entry { var matches []*yang.Entry util.DbgPrint("findMatchingSchemasInUnion for type %T, kind %s", value, reflect.TypeOf(value).Kind()) for _, t := range ytype.Type { if t.Kind == yang.Yunion { // Recursively check all union types within this union. - matches = append(matches, findMatchingSchemasInUnion(t, value)...) + matches = append(matches, findMatchingSchemasInUnion(schema, t, value)...) continue } + if t.Kind == yang.Yleafref { + ns, err := findLeafRefSchema(schema, t.Path) + if err != nil { + log.Warningf("not found base Go type for type %v in union value %s", t.Kind, util.ValueStr(value)) + continue + } + t = ns.Type + } ybt := yangBuiltinTypeToGoType(t.Kind) if reflect.ValueOf(value).Kind() == reflect.Ptr { ybt = ygot.ToPtr(yangBuiltinTypeToGoType(t.Kind)) From 9659b8490271101b16df12cbd458f2104ee129fb Mon Sep 17 00:00:00 2001 From: amrutasali Date: Thu, 19 Sep 2019 21:13:07 +0000 Subject: [PATCH 146/214] For a Get req on individual terminal node- Fix overloaded function processing, data-type conversion and leaf-list check handling --- src/translib/transformer/xlate_from_db.go | 190 ++++++++++++++-------- 1 file changed, 123 insertions(+), 67 deletions(-) diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index 35c4b227b7..31c283f10f 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -86,8 +86,14 @@ func validateHandlerFunc(inParams XfmrParams) (bool) { func DbValToInt(dbFldVal string, base int, size int, isUint bool) (interface{}, error) { var res interface{} var err error - if res, err = strconv.ParseInt(dbFldVal, base, size); err != nil { - log.Warning("Non Yint%v type for yang leaf-list item %v", size, dbFldVal) + if isUint { + if res, err = strconv.ParseUint(dbFldVal, base, size); err != nil { + log.Warningf("Non Yint%v type for yang leaf-list item %v", size, dbFldVal) + } + } else { + if res, err = strconv.ParseInt(dbFldVal, base, size); err != nil { + log.Warningf("Non Yint %v type for yang leaf-list item %v", size, dbFldVal) + } } return res, err } @@ -120,7 +126,7 @@ func DbToYangType(yngTerminalNdDtType yang.TypeKind, fldXpath string, dbFldVal s res, err = DbValToInt(dbFldVal, INTBASE, 64, true) case yang.Ybool: if res, err = strconv.ParseBool(dbFldVal); err != nil { - log.Warning("Non Bool type for yang leaf-list item %v", dbFldVal) + log.Warningf("Non Bool type for yang leaf-list item %v", dbFldVal) } //TODO enhance Yunion using yangEntry way case yang.Yenum, yang.Ystring, yang.Yidentityref, yang.Yunion: @@ -166,32 +172,47 @@ func directDbToYangJsonCreate(dbDataMap map[string]map[string]db.Value, jsonData for tblName, tblData := range dbDataMap { dataInst := "" var mapSlice []typeMapOfInterface + //var resVal interface{} for keyStr, dbFldValData := range tblData { curMap := make(map[string]interface{}) fldValPair := "" for field, value := range dbFldValData.Field { - if strings.HasSuffix(field, "@") { - fldVals := strings.Split(field, "@") - field = fldVals[0] - fieldXpath := tblName + "/" + field - if xDbSpecMap[fieldXpath].dbEntry.IsLeafList() { - resLst := processLfLstDbToYang(fieldXpath, value) - fldValPair += fmt.Sprintf("\"%v\" : \"%v\",\r\n", field, resLst) - curMap[field] = resLst - continue - } - } else { - fieldXpath := tblName + "/" + field - yngTerminalNdDtType := xDbSpecMap[fieldXpath].dbEntry.Type.Kind - resVal, err := DbToYangType(yngTerminalNdDtType, fieldXpath, value) - if err != nil { - log.Warning("Failure in converting Db value type to yang type for field", field) - } else { - fldValPair += fmt.Sprintf("\"%v\" : \"%v\",\r\n", field, resVal) - curMap[field] = resVal - } - } - } + resField := field + if strings.HasSuffix(field, "@") { + fldVals := strings.Split(field, "@") + resField = fldVals[0] + } + fieldXpath := tblName + "/" + resField + xDbSpecMapEntry, ok := xDbSpecMap[fieldXpath] + if !ok { + log.Warningf("No entry found in xDbSpecMap for xpath %v", fieldXpath) + continue + } + if xDbSpecMapEntry.dbEntry == nil { + log.Warningf("Yang entry is nil in xDbSpecMap for xpath %v", fieldXpath) + continue + } + yangType := yangTypeGet(xDbSpecMapEntry.dbEntry) + if yangType == "leaf-list" { + /* this should never happen but just adding for safetty */ + if !strings.HasSuffix(field, "@") { + log.Warningf("Leaf-list in Sonic yang should also be a leaf-list in DB, its not for xpath %v", fieldXpath) + continue + } + resLst := processLfLstDbToYang(fieldXpath, value) + fldValPair += fmt.Sprintf("\"%v\" : \"%v\",\r\n", field, resLst) + curMap[field] = resLst + } else { /* yangType is leaf - there are only 2 types of yang terminal node leaf and leaf-list */ + yngTerminalNdDtType := xDbSpecMapEntry.dbEntry.Type.Kind + resVal, err := DbToYangType(yngTerminalNdDtType, fieldXpath, value) + if err != nil { + log.Warningf("Failure in converting Db value type to yang type for xpath", fieldXpath) + } else { + fldValPair += fmt.Sprintf("\"%v\" : \"%v\",\r\n", field, resVal) + curMap[field] = resVal + } + } + } //end of for yangKeys := yangKeyFromEntryGet(xDbSpecMap[tblName].dbEntry) fldValPair = keyJsonDataAdd(yangKeys, keyStr, fldValPair, curMap) dataInst += fmt.Sprintf("{ \r\n %v \r\n },", fldValPair) @@ -257,6 +278,59 @@ func yangListDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, x return nil } +func terminalNodeProcess(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath string, dbDataMap *map[db.DBNum]map[string]map[string]db.Value, tbl string, tblKey string) (map[string]interface{}, error) { + log.Info("Received xpath - %v, uri - %v, dbDataMap - %v, table - %v, table key - %v", xpath, uri, (*dbDataMap), tbl, tblKey) + var err error + resFldValMap := make(map[string]interface{}) + if xSpecMap[xpath].yangEntry == nil { + logStr := fmt.Sprintf("No yang entry found for xpath %v.", xpath) + err = fmt.Errorf("%v", logStr) + return resFldValMap, err + } + + cdb := xSpecMap[xpath].dbIndex + if len(xSpecMap[xpath].xfmrFunc) > 0 { + _, key, _ := xpathKeyExtract(dbs[cdb], ygRoot, GET, uri) + inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, uri, GET, key, dbDataMap, nil) + fldValMap, _, err := leafXfmrHandlerFunc(inParams) + if err != nil { + logStr := fmt.Sprintf("%Failed to get data from overloaded function for %v -v.", uri, err) + err = fmt.Errorf("%v", logStr) + return resFldValMap, err + } + for lf, val := range fldValMap { + resFldValMap[lf] = val + } + } else { + dbFldName := xSpecMap[xpath].fieldName + /* if there is no transformer extension/annotation then it means leaf-list in yang is also leaflist in db */ + if len(dbFldName) > 0 && !xSpecMap[xpath].isKey { + yangType := yangTypeGet(xSpecMap[xpath].yangEntry) + if yangType == "leaf-list" { + dbFldName += "@" + val, ok := (*dbDataMap)[cdb][tbl][tblKey].Field[dbFldName] + if ok { + resLst := processLfLstDbToYang(xpath, val) + resFldValMap[xSpecMap[xpath].yangEntry.Name] = resLst + } + } else { + val, ok := (*dbDataMap)[cdb][tbl][tblKey].Field[dbFldName] + if ok { + yngTerminalNdDtType := xSpecMap[xpath].yangEntry.Type.Kind + resVal, err := DbToYangType(yngTerminalNdDtType, xpath, val) + if err != nil { + log.Error("Failure in converting Db value type to yang type for field", xpath) + } else { + resFldValMap[xSpecMap[xpath].yangEntry.Name] = resVal + } + } + } + } + } + return resFldValMap, err +} + + func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath string, dbDataMap *map[db.DBNum]map[string]map[string]db.Value, resultMap map[string]interface{}, tbl string, tblKey string, cdb db.DBNum, validate bool) error { var err error isValid := validate @@ -280,42 +354,15 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath } chldYangType := yangTypeGet(xSpecMap[chldXpath].yangEntry) cdb = xSpecMap[chldXpath].dbIndex - if xSpecMap[chldXpath].yangEntry.IsLeaf() || xSpecMap[chldXpath].yangEntry.IsLeafList() { - if len(xSpecMap[chldXpath].xfmrFunc) > 0 { - inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, chldUri, GET, key, dbDataMap, nil) - fldValMap, _, err := leafXfmrHandlerFunc(inParams) - if err != nil { - log.Info("Failed to get data(\"%v\").\r\n", chldUri) - } - for lf, val := range fldValMap { - resultMap[lf] = val - } - } else { - dbFldName := xSpecMap[chldXpath].fieldName - /* if there is no transformer extension/annotation then it means leaf-list in yang is also leaflist in db */ - if len(dbFldName) > 0 && !xSpecMap[chldXpath].isKey { - if xSpecMap[chldXpath].yangEntry.IsLeafList() { - dbFldName += "@" - val, ok := (*dbDataMap)[cdb][tbl][tblKey].Field[dbFldName] - if ok { - resLst := processLfLstDbToYang(chldXpath, val) - resultMap[xSpecMap[chldXpath].yangEntry.Name] = resLst - } - } else { - val, ok := (*dbDataMap)[cdb][tbl][tblKey].Field[dbFldName] - if ok { - /* this will be enhanced to support all yang data types */ - yngTerminalNdDtType := xSpecMap[chldXpath].yangEntry.Type.Kind - resVal, err := DbToYangType(yngTerminalNdDtType, chldXpath, val) - if err != nil { - log.Warning("Failure in converting Db value type to yang type for field", chldXpath) - } else { - resultMap[xSpecMap[chldXpath].yangEntry.Name] = resVal - } - } - } - } + if chldYangType == "leaf" || chldYangType == "leaf-list" { + fldValMap, err := terminalNodeProcess(dbs, ygRoot, chldUri, chldXpath, dbDataMap, tbl, tblKey) + if err != nil { + log.Info("Failed to get data(\"%v\").", chldUri) + } + for lf, val := range fldValMap { + resultMap[lf] = val } + } else if chldYangType == "container" { cname := xSpecMap[chldXpath].yangEntry.Name if len(xSpecMap[chldXpath].xfmrFunc) > 0 { @@ -375,20 +422,29 @@ func dbDataToYangJsonCreate(uri string, ygRoot *ygot.GoStruct, dbs [db.MaxDB]*db if ok { yangType := yangTypeGet(yangNode.yangEntry) - if yangType == "leaf" { - fldName := xSpecMap[reqXpath].fieldName + if yangType == "leaf" || yangType == "leaf-list" { + //fldName := xSpecMap[reqXpath].fieldName yangName := xSpecMap[reqXpath].yangEntry.Name tbl, key, _ := tableNameAndKeyFromDbMapGet((*dbDataMap)[cdb]) + validateHandlerFlag := false if len(xSpecMap[reqXpath].validateFunc) > 0 { // TODO - handle non CONFIG-DB inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, uri, GET, key, dbDataMap, nil) res := validateHandlerFunc(inParams) - if res == true { - resultMap[yangName] = (*dbDataMap)[cdb][tbl][key].Field[fldName] - } else { - resultMap[yangName] = "" - } + if !res { + validateHandlerFlag = true + resultMap[yangName] = "" + } } + if !validateHandlerFlag { + fldValMap, err := terminalNodeProcess(dbs, ygRoot, uri, reqXpath, dbDataMap, tbl, key) + //err := terminalNodeProcess(dbs, ygRoot, uri, reqXpath, dbDataMap, tbl, key) + if err != nil { + log.Infof("Empty terminal node (\"%v\").", uri) + } + resultMap = fldValMap + } + } else if yangType == "container" { cname := xSpecMap[reqXpath].yangEntry.Name cmap := make(map[string]interface{}) From b6ebc29735c75817b48f9beef5da2814c7e1cd45 Mon Sep 17 00:00:00 2001 From: s-mari Date: Thu, 19 Sep 2019 14:53:15 -0700 Subject: [PATCH 147/214] table transformer support --- src/translib/transformer/xspec.go | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/translib/transformer/xspec.go b/src/translib/transformer/xspec.go index b3d9db57e6..1dee5c705a 100644 --- a/src/translib/transformer/xspec.go +++ b/src/translib/transformer/xspec.go @@ -14,6 +14,7 @@ import ( type yangXpathInfo struct { yangDataType string tableName *string + xfmrTbl *string childTable []string dbEntry *yang.Entry yangEntry *yang.Entry @@ -74,8 +75,12 @@ func yangToDbMapFill (keyLevel int, xSpecMap map[string]*yangXpathInfo, entry *y parentXpathData, ok := xSpecMap[xpathPrefix] /* init current xpath table data with its parent data, change only if needed. */ - if ok && xpathData.tableName == nil && parentXpathData.tableName != nil { - xpathData.tableName = parentXpathData.tableName + if ok { + if xpathData.tableName == nil && parentXpathData.tableName != nil && xpathData.xfmrTbl == nil { + xpathData.tableName = parentXpathData.tableName + } else if xpathData.xfmrTbl == nil && parentXpathData.xfmrTbl != nil { + xpathData.xfmrTbl = parentXpathData.xfmrTbl + } } if ok && parentXpathData.dbIndex != db.ConfigDB { @@ -93,7 +98,10 @@ func yangToDbMapFill (keyLevel int, xSpecMap map[string]*yangXpathInfo, entry *y } else if xDbSpecMap[*xpathData.tableName].dbEntry.Dir[strings.ToUpper(entry.Name)] != nil { xpathData.fieldName = strings.ToUpper(entry.Name) } - } + } else if xpathData.xfmrTbl != nil { + /* table transformer present */ + xpathData.fieldName = entry.Name + } } if xpathData.yangDataType == "leaf" && len(xpathData.fieldName) > 0 && xpathData.tableName != nil { @@ -265,6 +273,11 @@ func annotEntryFill(xSpecMap map[string]*yangXpathInfo, xpath string, entry *yan *xpathData.tableName = ext.NName() updateDbTableData(xpath, xpathData, *xpathData.tableName) //childToUpdateParent(xpath, *xpathData.tableName) + case "table-transformer" : + if xpathData.xfmrTbl == nil { + xpathData.xfmrTbl = new(string) + } + *xpathData.xfmrTbl = ext.NName() case "field-name" : xpathData.fieldName = ext.NName() case "subtree-transformer" : @@ -298,7 +311,7 @@ func annotEntryFill(xSpecMap map[string]*yangXpathInfo, xpath string, entry *yan xpathData.dbIndex = db.StateDB } else { xpathData.dbIndex = db.ConfigDB - } + } } } } @@ -357,6 +370,10 @@ func mapPrint(inMap map[string]*yangXpathInfo, fileName string) { if d.tableName != nil { fmt.Fprintf(fp, "%v", *d.tableName) } + fmt.Fprintf(fp, "\r\n xfmrTbl : ") + if d.xfmrTbl != nil { + fmt.Fprintf(fp, "%v", *d.xfmrTbl) + } fmt.Fprintf(fp, "\r\n childTbl : %v", d.childTable) fmt.Fprintf(fp, "\r\n FieldName: %v", d.fieldName) fmt.Fprintf(fp, "\r\n keyLevel : %v", d.keyLevel) From 2fdee4b8337e66869634571f98f8743ea1d1cef4 Mon Sep 17 00:00:00 2001 From: justinejose91 Date: Thu, 19 Sep 2019 15:23:13 -0700 Subject: [PATCH 148/214] CLI skeletion for VLAN feature: config, show and its templates --- src/CLI/clitree/cli-xml/interface.xml | 285 ++++++++++++++++++++---- src/CLI/renderer/templates/show_vlan.j2 | 23 ++ 2 files changed, 259 insertions(+), 49 deletions(-) create mode 100644 src/CLI/renderer/templates/show_vlan.j2 diff --git a/src/CLI/clitree/cli-xml/interface.xml b/src/CLI/clitree/cli-xml/interface.xml index 3341170d76..7a65823dba 100644 --- a/src/CLI/clitree/cli-xml/interface.xml +++ b/src/CLI/clitree/cli-xml/interface.xml @@ -35,31 +35,31 @@ limitations under the License. ptype="SUBCOMMAND" > - + name="counters" + help="Counters for Physical Interfaces" + ptype="SUBCOMMAND" + mode="subcommand" + > + - + - + @@ -77,33 +77,90 @@ limitations under the License. fi + + + + + + + + + - - - - - + > + + + + + + + + + + + + + + + + + + + - - python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_interfaces_interfaces_interface_config_enabled ${iface} False - - - python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_interfaces_interfaces_interface_config_enabled ${iface} True - - python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_interfaces_interfaces_interface_config_mtu ${iface} ${mtu} - python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_interfaces_interfaces_interface_config_mtu ${iface} 9100 - + + python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_interfaces_interfaces_interface_config_enabled ${iface} False + + + python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_interfaces_interfaces_interface_config_enabled ${iface} True + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/CLI/renderer/templates/show_vlan.j2 b/src/CLI/renderer/templates/show_vlan.j2 new file mode 100644 index 0000000000..aabb216869 --- /dev/null +++ b/src/CLI/renderer/templates/show_vlan.j2 @@ -0,0 +1,23 @@ +{% set vars = {'vlanName': ""} %} +{% set vars = {'ifName': ""} %} +{% set vars = {'tagMode': ""} %} +{% set vars = {'tagLetter': ""} %} +{% if json_output -%} +Q: A - Access (Untagged), T - Tagged +{{'%-11s'|format("NUM")}}{{'%-2s'|format("Q Ports")}} +{% for vlanKey, memberEntries in json_output.items() %} +{% if vars.update({'vlanName':vlanKey}) %}{% endif %} +{% for ifKey, ifMode in memberEntries.items() %} +{% if vars.update({'ifName':ifKey}) %}{% endif %} +{% if vars.update({'tagMode':ifMode}) %}{% endif %} +{% if ifMode == "untagged" %} +{% if vars.update({'tagLetter':" U "}) %}{% endif %} +{% else %} +{% if vars.update({'tagLetter':" T "}) %}{% endif %} +{% endif %} +{{'%-10s'|format(vars.vlanName)}}{{'%-2s'|format(vars.tagLetter)}}{{'%-10s'|format(vars.ifName)}} +{% if vars.update({'vlanName':''}) %}{% endif %} +{% endfor %} +{% endfor %} +{% endif %} + From b769aa90db84e9118f5c1f7b0cea9ec7677127b7 Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Thu, 19 Sep 2019 15:49:29 -0700 Subject: [PATCH 149/214] Cleanup of unused code --- src/translib/common_app.go | 4 +- src/translib/transformer/xlate_from_db.go | 112 +++++----------------- src/translib/transformer/xlate_to_db.go | 26 ++--- src/translib/transformer/xlate_utils.go | 22 ++--- 4 files changed, 47 insertions(+), 117 deletions(-) diff --git a/src/translib/common_app.go b/src/translib/common_app.go index 38231615ad..2ec8cf10bd 100644 --- a/src/translib/common_app.go +++ b/src/translib/common_app.go @@ -159,7 +159,7 @@ func (app *CommonApp) processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error) { payload, err = transformer.GetAndXlateFromDB(app.pathInfo.Path, app.ygotRoot, dbs) if err != nil { - log.Error("transformer.XlateFromDb() failure") + log.Error("transformer.transformer.GetAndXlateFromDB failure. error:", err) return GetResponse{Payload: payload, ErrSrc: AppErr}, err } @@ -167,7 +167,7 @@ func (app *CommonApp) processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error) { if targetObj != nil { err = ocbinds.Unmarshal(payload, targetObj) if err != nil { - log.Error("ocbinds.Unmarshal() failed") + log.Error("ocbinds.Unmarshal() failed. error:", err) return GetResponse{Payload: payload, ErrSrc: AppErr}, err } } diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index 68779c62f8..18803da0f4 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -21,10 +21,10 @@ type typeMapOfInterface map[string]interface{} func xfmrHandlerFunc(inParams XfmrParams) (map[string]interface{}, error) { result := make(map[string]interface{}) xpath, _ := RemoveXPATHPredicates(inParams.uri) - log.Info("Subtree transformer function(\"%v\") invoked for yang path(\"%v\").", xSpecMap[xpath].xfmrFunc, xpath) + log.Infof("Subtree transformer function(\"%v\") invoked for yang path(\"%v\").", xSpecMap[xpath].xfmrFunc, xpath) _, err := XlateFuncCall(dbToYangXfmrFunc(xSpecMap[xpath].xfmrFunc), inParams) if err != nil { - log.Info("Failed to retrieve data for xpath(\"%v\") err(%v).", inParams.uri, err) + log.Infof("Failed to retrieve data for xpath(\"%v\") err(%v).", inParams.uri, err) return result, err } @@ -46,7 +46,7 @@ func xfmrHandlerFunc(inParams XfmrParams) (map[string]interface{}, error) { nodeList, nErr := ytypes.GetNode(schRoot, device, path) if nErr != nil { - log.Info("Failed to get node for xpath(\"%v\") err(%v).", inParams.uri, err) + log.Infof("Failed to get node for xpath(\"%v\") err(%v).", inParams.uri, err) return result, err } node := nodeList[0].Data @@ -59,19 +59,14 @@ func xfmrHandlerFunc(inParams XfmrParams) (map[string]interface{}, error) { return result, err } -func leafXfmrHandlerFunc(inParams XfmrParams) (map[string]interface{}, string, error) { +func leafXfmrHandlerFunc(inParams XfmrParams) (map[string]interface{}, error) { xpath, _ := RemoveXPATHPredicates(inParams.uri) ret, err := XlateFuncCall(dbToYangXfmrFunc(xSpecMap[xpath].xfmrFunc), inParams) if err != nil { - return nil, "", err + return nil, err } fldValMap := ret[0].Interface().(map[string]interface{}) - data := "" - for f, v := range fldValMap { - value := fmt.Sprintf("%v", v) - data += fmt.Sprintf("\"%v\" : \"%v\",", f, value) - } - return fldValMap, data, nil + return fldValMap, nil } func validateHandlerFunc(inParams XfmrParams) (bool) { @@ -164,14 +159,12 @@ func processLfLstDbToYang(fieldXpath string, dbFldVal string) []interface{} { } /* Traverse db map and create json for cvl yang */ -func directDbToYangJsonCreate(dbDataMap map[string]map[string]db.Value, jsonData string, resultMap map[string]interface{}) string { +func directDbToYangJsonCreate(dbDataMap map[string]map[string]db.Value, jsonData string, resultMap map[string]interface{}) error { + var err error for tblName, tblData := range dbDataMap { - dataInst := "" var mapSlice []typeMapOfInterface - //var resVal interface{} for keyStr, dbFldValData := range tblData { curMap := make(map[string]interface{}) - fldValPair := "" for field, value := range dbFldValData.Field { resField := field if strings.HasSuffix(field, "@") { @@ -196,33 +189,26 @@ func directDbToYangJsonCreate(dbDataMap map[string]map[string]db.Value, jsonData continue } resLst := processLfLstDbToYang(fieldXpath, value) - fldValPair += fmt.Sprintf("\"%v\" : \"%v\",\r\n", field, resLst) - curMap[field] = resLst + curMap[resField] = resLst } else { /* yangType is leaf - there are only 2 types of yang terminal node leaf and leaf-list */ yngTerminalNdDtType := xDbSpecMapEntry.dbEntry.Type.Kind resVal, err := DbToYangType(yngTerminalNdDtType, fieldXpath, value) if err != nil { log.Warningf("Failure in converting Db value type to yang type for xpath", fieldXpath) } else { - fldValPair += fmt.Sprintf("\"%v\" : \"%v\",\r\n", field, resVal) - curMap[field] = resVal + curMap[resField] = resVal } } } //end of for yangKeys := yangKeyFromEntryGet(xDbSpecMap[tblName].dbEntry) - fldValPair = keyJsonDataAdd(yangKeys, keyStr, fldValPair, curMap) - dataInst += fmt.Sprintf("{ \r\n %v \r\n },", fldValPair) + sonicKeyDataAdd(yangKeys, keyStr, curMap) if curMap != nil { mapSlice = append(mapSlice, curMap) } } - dataInst = strings.TrimRight(dataInst, ",") - jsonData += fmt.Sprintf("\"%v\" : [\r\n %v\r\n ],", tblName, dataInst) resultMap[tblName] = mapSlice } - jsonData = strings.TrimRight(jsonData, ",") - jsonData += fmt.Sprintf("}") - return jsonData + return err } func tableNameAndKeyFromDbMapGet(dbDataMap map[string]map[string]db.Value) (string, string, error) { @@ -244,14 +230,14 @@ func yangListDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, x var mapSlice []typeMapOfInterface for dbKey, _ := range tblData { curMap := make(map[string]interface{}) - curKeyMap, curUri, _, _ := dbKeyToYangDataConvert(uri, xpath, dbKey) + curKeyMap, curUri, _ := dbKeyToYangDataConvert(uri, xpath, dbKey) if len(xSpecMap[xpath].xfmrFunc) > 0 { inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, curUri, GET, "", dbDataMap, nil) cmap, _ := xfmrHandlerFunc(inParams) if len(cmap) > 0 { mapSlice = append(mapSlice, curMap) } else { - log.Info("Empty container returned from overloaded transformer for(\"%v\")", curUri) + log.Infof("Empty container returned from overloaded transformer for(\"%v\")", curUri) } } else { _, keyFromCurUri, _ := xpathKeyExtract(dbs[cdb], ygRoot, GET, curUri) @@ -268,14 +254,14 @@ func yangListDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, x if len(mapSlice) > 0 { resultMap[xSpecMap[xpath].yangEntry.Name] = mapSlice } else { - log.Info("Empty slice for (\"%v\").\r\n", uri) + log.Infof("Empty slice for (\"%v\").\r\n", uri) } } return nil } func terminalNodeProcess(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath string, dbDataMap *map[db.DBNum]map[string]map[string]db.Value, tbl string, tblKey string) (map[string]interface{}, error) { - log.Info("Received xpath - %v, uri - %v, dbDataMap - %v, table - %v, table key - %v", xpath, uri, (*dbDataMap), tbl, tblKey) + log.Infof("Received xpath - %v, uri - %v, dbDataMap - %v, table - %v, table key - %v", xpath, uri, (*dbDataMap), tbl, tblKey) var err error resFldValMap := make(map[string]interface{}) if xSpecMap[xpath].yangEntry == nil { @@ -288,7 +274,7 @@ func terminalNodeProcess(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string if len(xSpecMap[xpath].xfmrFunc) > 0 { _, key, _ := xpathKeyExtract(dbs[cdb], ygRoot, GET, uri) inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, uri, GET, key, dbDataMap, nil) - fldValMap, _, err := leafXfmrHandlerFunc(inParams) + fldValMap, err := leafXfmrHandlerFunc(inParams) if err != nil { logStr := fmt.Sprintf("%Failed to get data from overloaded function for %v -v.", uri, err) err = fmt.Errorf("%v", logStr) @@ -353,7 +339,7 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath if chldYangType == "leaf" || chldYangType == "leaf-list" { fldValMap, err := terminalNodeProcess(dbs, ygRoot, chldUri, chldXpath, dbDataMap, tbl, tblKey) if err != nil { - log.Info("Failed to get data(\"%v\").", chldUri) + log.Infof("Failed to get data(\"%v\").", chldUri) } for lf, val := range fldValMap { resultMap[lf] = val @@ -367,7 +353,7 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath if len(cmap) > 0 { resultMap[cname] = cmap } else { - log.Info("Empty container(\"%v\").\r\n", chldUri) + log.Infof("Empty container(\"%v\").\r\n", chldUri) } } else { cmap := make(map[string]interface{}) @@ -375,7 +361,7 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath if len(cmap) > 0 { resultMap[cname] = cmap } else { - log.Info("Empty container(\"%v\").\r\n", chldUri) + log.Infof("Empty container(\"%v\").\r\n", chldUri) } } } else if chldYangType == "list" { @@ -386,7 +372,7 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath if len(cmap) > 0 { resultMap = cmap } else { - log.Info("Empty list(\"%v\").\r\n", chldUri) + log.Infof("Empty list(\"%v\").\r\n", chldUri) } } else { ynode, ok := xSpecMap[chldXpath] @@ -409,8 +395,7 @@ func dbDataToYangJsonCreate(uri string, ygRoot *ygot.GoStruct, dbs [db.MaxDB]*db jsonData := "" resultMap := make(map[string]interface{}) if isCvlYang(uri) { - jsonData := directDbToYangJsonCreate((*dbDataMap)[cdb], jsonData, resultMap) - jsonDataPrint(jsonData) + directDbToYangJsonCreate((*dbDataMap)[cdb], jsonData, resultMap) } else { var d *db.DB reqXpath, keyName, tableName := xpathKeyExtract(d, ygRoot, GET, uri) @@ -452,13 +437,13 @@ func dbDataToYangJsonCreate(uri string, ygRoot *ygot.GoStruct, dbs [db.MaxDB]*db } else { err := yangDataFill(dbs, ygRoot, uri, reqXpath, dbDataMap, resultMap, tableName, keyName, cdb, false) if err != nil { - log.Info("Empty container(\"%v\").\r\n", uri) + log.Infof("Empty container(\"%v\").\r\n", uri) } } } else { err := yangDataFill(dbs, ygRoot, uri, reqXpath, dbDataMap, resultMap, tableName, keyName, cdb, false) if err != nil { - log.Info("Empty container(\"%v\").\r\n", uri) + log.Infof("Empty container(\"%v\").\r\n", uri) } } } else { @@ -473,55 +458,6 @@ func dbDataToYangJsonCreate(uri string, ygRoot *ygot.GoStruct, dbs [db.MaxDB]*db return jsonData, nil } -func xpathLastAttrGet(xpath string) string { - attrList := strings.Split(xpath, "/") - return attrList[len(attrList)-1] -} - -func jsonPayloadComplete(reqXpath string, data string) string { - entry := xSpecMap[reqXpath].yangEntry - entryType := entry.Node.Statement().Keyword - name := xpathLastAttrGet(reqXpath) - switch entryType { - case "container": - data = fmt.Sprintf("\"%v\" : { \r\n %v \r\n }\r\n", name, data) - case "list": - data = fmt.Sprintf("\"%v\" : [\r\n %v\r\n ]\r\n", name, data) - } - data = fmt.Sprintf("{\r\n %v }\r\n", data) - return data -} - -func parentJsonDataUpdate(reqXpath string, xpath string, data string) string { - curXpath := parentXpathGet(xpath) - if reqXpath == xpath { - data = fmt.Sprintf("{\r\n %v }\r\n", data) - return data - } - if reqXpath == curXpath { - data = jsonPayloadComplete(reqXpath, data) - return data - } - if xSpecMap[curXpath] != nil { - entry := xSpecMap[curXpath].yangEntry - entryType := entry.Node.Statement().Keyword - switch entryType { - case "container": - data = fmt.Sprintf("\"%v\" : { \r\n %v \r\n }", xSpecMap[curXpath].yangEntry.Name, data) - return parentJsonDataUpdate(reqXpath, curXpath, data) - case "list": - data = fmt.Sprintf("\"%v\" : [\r\n %v\r\n ]\r\n", xSpecMap[curXpath].yangEntry.Name, data) - return parentJsonDataUpdate(reqXpath, curXpath, data) - case "module": - data = fmt.Sprintf("\"%v\" : { \r\n %v \r\n }", xSpecMap[curXpath].yangEntry.Name, data) - return data - default: - return "" - } - } - return "" -} - func jsonDataPrint(data string) { fp, err := os.Create("/tmp/dbToYangJson.txt") if err != nil { diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index 3bc0361946..c84f54d73c 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -38,7 +38,7 @@ func dataToDBMapAdd(tableName string, dbKey string, result map[string]map[string func mapFillData(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, dbKey string, result map[string]map[string]db.Value, xpathPrefix string, name string, value interface{}) error { xpath := xpathPrefix + "/" + name xpathInfo := xSpecMap[xpath] - log.Info("name: \"%v\", xpathPrefix(\"%v\").", name, xpathPrefix) + log.Infof("name: \"%v\", xpathPrefix(\"%v\").", name, xpathPrefix) if xpathInfo == nil { log.Errorf("Yang path(\"%v\") not found.", xpath) @@ -62,7 +62,7 @@ func mapFillData(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, dbKey st uri = uri + "/" + name /* field transformer present */ - log.Info("Transformer function(\"%v\") invoked for yang path(\"%v\").", xpathInfo.xfmrFunc, xpath) + log.Infof("Transformer function(\"%v\") invoked for yang path(\"%v\").", xpathInfo.xfmrFunc, xpath) path, _ := ygot.StringToPath(uri, ygot.StructuredPath, ygot.StringSlicePath) for _, p := range path.Elem { pathSlice := strings.Split(p.Name, ":") @@ -96,7 +96,7 @@ func mapFillData(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, dbKey st } if len(xpathInfo.fieldName) == 0 { - log.Info("Field for yang-path(\"%v\") not found in DB.", xpath) + log.Infof("Field for yang-path(\"%v\") not found in DB.", xpath) return errors.New("Invalid field name") } fieldName := xpathInfo.fieldName @@ -129,7 +129,7 @@ func mapFillData(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, dbKey st } dataToDBMapAdd(*xpathInfo.tableName, dbKey, result, fieldName, valueStr) - log.Info("TblName: \"%v\", key: \"%v\", field: \"%v\", valueStr: \"%v\".", + log.Infof("TblName: \"%v\", key: \"%v\", field: \"%v\", valueStr: \"%v\".", *xpathInfo.tableName, dbKey, fieldName, valueStr) return nil } @@ -206,11 +206,11 @@ func dbMapDelete(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string, jsonDat var err error if isCvlYang(path) { xpathPrefix, keyName, tableName := sonicXpathKeyExtract(path) - log.Info("Delete req: path(\"%v\"), key(\"%v\"), xpathPrefix(\"%v\"), tableName(\"%v\").", path, keyName, xpathPrefix, tableName) + log.Infof("Delete req: path(\"%v\"), key(\"%v\"), xpathPrefix(\"%v\"), tableName(\"%v\").", path, keyName, xpathPrefix, tableName) err = cvlYangReqToDbMapDelete(xpathPrefix, tableName, keyName, result) } else { xpathPrefix, keyName, tableName := xpathKeyExtract(d, ygRoot, oper, path) - log.Info("Delete req: path(\"%v\"), key(\"%v\"), xpathPrefix(\"%v\"), tableName(\"%v\").", path, keyName, xpathPrefix, tableName) + log.Infof("Delete req: path(\"%v\"), key(\"%v\"), xpathPrefix(\"%v\"), tableName(\"%v\").", path, keyName, xpathPrefix, tableName) spec, ok := xSpecMap[xpathPrefix] if ok { if spec.tableName != nil { @@ -228,7 +228,7 @@ func dbMapDelete(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string, jsonDat } } } - log.Info("Delete req: path(\"%v\") result(\"%v\").", path, result) + log.Infof("Delete req: path(\"%v\") result(\"%v\").", path, result) return err } @@ -271,9 +271,9 @@ func cvlYangReqToDbMapDelete(xpathPrefix string, tableName string, keyName strin /* Get the data from incoming update/replace request, create map and fill with dbValue(ie. field:value to write into redis-db */ func dbMapUpdate(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string, jsonData interface{}, result map[string]map[string]db.Value) error { - log.Info("Update/replace req: path(\"%v\").", path) + log.Infof("Update/replace req: path(\"%v\").", path) dbMapCreate(d, ygRoot, oper, path, jsonData, result) - log.Info("Update/replace req: path(\"%v\") result(\"%v\").", path, result) + log.Infof("Update/replace req: path(\"%v\") result(\"%v\").", path, result) printDbData(result, "/tmp/yangToDbDataUpRe.txt") return nil } @@ -292,11 +292,11 @@ func dbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string, jsonDat } func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, xpathPrefix string, keyName string, jsonData interface{}, result map[string]map[string]db.Value) error { - log.Info("key(\"%v\"), xpathPrefix(\"%v\").", keyName, xpathPrefix) + log.Infof("key(\"%v\"), xpathPrefix(\"%v\").", keyName, xpathPrefix) var dbs [db.MaxDB]*db.DB if reflect.ValueOf(jsonData).Kind() == reflect.Slice { - log.Info("slice data: key(\"%v\"), xpathPrefix(\"%v\").", keyName, xpathPrefix) + log.Infof("slice data: key(\"%v\"), xpathPrefix(\"%v\").", keyName, xpathPrefix) jData := reflect.ValueOf(jsonData) dataMap := make([]interface{}, jData.Len()) for idx := 0; idx < jData.Len(); idx++ { @@ -324,7 +324,7 @@ func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, for _, key := range jData.MapKeys() { typeOfValue := reflect.TypeOf(jData.MapIndex(key).Interface()).Kind() - log.Info("slice/map data: key(\"%v\"), xpathPrefix(\"%v\").", keyName, xpathPrefix) + log.Infof("slice/map data: key(\"%v\"), xpathPrefix(\"%v\").", keyName, xpathPrefix) xpath := uri curUri := uri pathAttr := key.String() @@ -354,7 +354,7 @@ func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, pathAttr = strings.Split(pathAttr, ":")[1] } value := jData.MapIndex(key).Interface() - log.Info("data field: key(\"%v\"), value(\"%v\").", key, value) + log.Infof("data field: key(\"%v\"), value(\"%v\").", key, value) err := mapFillData(d, ygRoot, oper, uri, keyName, result, xpathPrefix, pathAttr, value) if err != nil { diff --git a/src/translib/transformer/xlate_utils.go b/src/translib/transformer/xlate_utils.go index 38addb96df..849f34e5f0 100644 --- a/src/translib/transformer/xlate_utils.go +++ b/src/translib/transformer/xlate_utils.go @@ -88,17 +88,17 @@ func yangTypeGet(entry *yang.Entry) string { return "" } -func dbKeyToYangDataConvert(uri string, xpath string, dbKey string) (map[string]interface{}, string, string, error) { +func dbKeyToYangDataConvert(uri string, xpath string, dbKey string) (map[string]interface{}, string, error) { var err error if len(uri) == 0 && len(xpath) == 0 && len(dbKey) == 0 { err = fmt.Errorf("Insufficient input") - return nil, "", "", err + return nil, "", err } if _, ok := xSpecMap[xpath]; ok { if xSpecMap[xpath].yangEntry == nil { err = fmt.Errorf("Yang Entry not available for xpath ", xpath) - return nil, "", "", nil + return nil, "", nil } } @@ -106,7 +106,6 @@ func dbKeyToYangDataConvert(uri string, xpath string, dbKey string) (map[string] keyDataList := strings.Split(dbKey, "|") keyNameList := yangKeyFromEntryGet(xSpecMap[xpath].yangEntry) id := xSpecMap[xpath].keyLevel - jsonData := "" uriWithKey := fmt.Sprintf("%v", xpath) /* if uri contins key, use it else use xpath */ @@ -119,14 +118,13 @@ func dbKeyToYangDataConvert(uri string, xpath string, dbKey string) (map[string] inParams := formXfmrInputRequest(nil, dbs, db.MaxDB, nil, uri, GET, dbKey, nil, nil) ret, err := XlateFuncCall(dbToYangXfmrFunc(xSpecMap[xpath].xfmrKey), inParams) if err != nil { - return nil, "","",err + return nil, "", err } rmap := ret[0].Interface().(map[string]interface{}) for k, v := range rmap { - jsonData += fmt.Sprintf("\"%v\" : \"%v\",\r\n", k, v) uriWithKey += fmt.Sprintf("[%v=%v]", k, v) } - return rmap, uriWithKey, jsonData, nil + return rmap, uriWithKey, nil } kLvlValList = append(kLvlValList, keyDataList[id]) @@ -151,12 +149,11 @@ func dbKeyToYangDataConvert(uri string, xpath string, dbKey string) (map[string] kval = strings.Join(kLvlValList[chgId:], "_") } - jsonData += fmt.Sprintf("\"%v\" : \"%v\",", kname, kval) uriWithKey += fmt.Sprintf("[%v=%v]", kname, kval) rmap[kname] = kval } - return rmap, uriWithKey, jsonData, nil + return rmap, uriWithKey, nil } func contains(sl []string, str string) bool { @@ -209,18 +206,15 @@ func isCvlYang(path string) bool { return false } -func keyJsonDataAdd(keyNameList []string, keyStr string, jsonData string, resultMap map[string]interface{}) string { +func sonicKeyDataAdd(keyNameList []string, keyStr string, resultMap map[string]interface{}) { keyValList := strings.Split(keyStr, "|") if len(keyNameList) != len(keyValList) { - return "" + return } for i, keyName := range keyNameList { - jsonData += fmt.Sprintf("\"%v\" : \"%v\",", keyName, keyValList[i]) resultMap[keyName] = keyValList[i] } - jsonData = strings.TrimRight(jsonData, ",") - return jsonData } func yangToDbXfmrFunc(funcName string) string { From 77a8dfffa21976334f9ccce945c76e154848520a Mon Sep 17 00:00:00 2001 From: jjose Date: Fri, 20 Sep 2019 00:00:50 +0000 Subject: [PATCH 150/214] Changes for supporting show command with dummy data --- src/CLI/actioner/sonic-cli-if.py | 6 ++++++ src/CLI/clitree/cli-xml/interface.xml | 4 +++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/CLI/actioner/sonic-cli-if.py b/src/CLI/actioner/sonic-cli-if.py index 9ed5f27006..e858fbb071 100755 --- a/src/CLI/actioner/sonic-cli-if.py +++ b/src/CLI/actioner/sonic-cli-if.py @@ -44,6 +44,7 @@ def call_method(name, args): def generate_body(func, args): body = None + keypath = [] # Get the rules of all ACL table entries. if func.__name__ == 'patch_openconfig_interfaces_interfaces_interface_config_description': keypath = [ args[0] ] @@ -98,6 +99,11 @@ def run(func, args): keypath, body = generate_body(func, args) try: + # Temporary code for #show vlan command with dummy data + if func.__name__ == "get_openconfig_vlan_interfaces_interface_ethernet_switched_vlan_state": + api_response = {'Vlan100': {'Ethernet20': 'tagged', 'Ethernet40': 'untagged'}} + show_cli_output(args[0], api_response) + return if body is not None: api_response = getattr(aa,func.__name__)(*keypath, body=body) else : diff --git a/src/CLI/clitree/cli-xml/interface.xml b/src/CLI/clitree/cli-xml/interface.xml index 7a65823dba..4e92612d2f 100644 --- a/src/CLI/clitree/cli-xml/interface.xml +++ b/src/CLI/clitree/cli-xml/interface.xml @@ -90,7 +90,9 @@ limitations under the License. optional="true" > - + + python $SONIC_CLI_ROOT/sonic-cli-if.py get_openconfig_vlan_interfaces_interface_ethernet_switched_vlan_state show_vlan.j2 + From 2a6f01fe0c1b7b09c46ab7b9c84ba7c0029c4f1e Mon Sep 17 00:00:00 2001 From: Kwan Kim Date: Thu, 19 Sep 2019 23:37:26 -0700 Subject: [PATCH 151/214] add the union type --- src/translib/transformer/xlate_from_db.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index 18803da0f4..f763990231 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -119,7 +119,8 @@ func DbToYangType(yngTerminalNdDtType yang.TypeKind, fldXpath string, dbFldVal s if res, err = strconv.ParseBool(dbFldVal); err != nil { log.Warningf("Non Bool type for yang leaf-list item %v", dbFldVal) } - case yang.Ybinary, yang.Ydecimal64, yang.Yenum, yang.Yidentityref, yang.Yint64, yang.Yuint64, yang.Ystring: + case yang.Ybinary, yang.Ydecimal64, yang.Yenum, yang.Yidentityref, yang.Yint64, yang.Yuint64, yang.Ystring, yang.Yunion: + // TODO - handle the union type // Make sure to encode as string, expected by util_types.go: ytypes.yangToJSONType log.Info("Yenum/Ystring/Yunion(having all members as strings) type for yangXpath ", fldXpath) res = dbFldVal From 936661658273c40c51a1b08e721ce4a8c4e09bab Mon Sep 17 00:00:00 2001 From: Partha Dutta <51353699+dutta-partha@users.noreply.github.com> Date: Fri, 20 Sep 2019 16:04:13 +0530 Subject: [PATCH 152/214] Update Makefile Add rule to compile test YANG schema --- Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Makefile b/Makefile index 01d0a951db..8d3c41d53e 100644 --- a/Makefile +++ b/Makefile @@ -63,6 +63,8 @@ cli: rest-server cvl: go-deps $(MAKE) -C src/cvl $(MAKE) -C src/cvl/schema + $(MAKE) -C src/cvl/testdata/schema + cvl-test: $(MAKE) -C src/cvl gotest From fffeffc2ebf173cd5d131cb4867f752db13961fc Mon Sep 17 00:00:00 2001 From: Tejaswi Goel Date: Fri, 20 Sep 2019 03:31:46 -0700 Subject: [PATCH 153/214] CLI skeleton for Port channel Signed-off-by: Tejaswi Goel --- src/CLI/actioner/port_channel_dummy_data.json | 48 ++ src/CLI/actioner/sonic-cli-if.py | 93 +++- src/CLI/clitree/cli-xml/interface.xml | 433 ++++++++++++++++-- .../renderer/templates/show_portchannel.j2 | 9 + .../renderer/templates/show_portchannel_id.j2 | 8 + 5 files changed, 553 insertions(+), 38 deletions(-) create mode 100644 src/CLI/actioner/port_channel_dummy_data.json create mode 100644 src/CLI/renderer/templates/show_portchannel.j2 create mode 100644 src/CLI/renderer/templates/show_portchannel_id.j2 diff --git a/src/CLI/actioner/port_channel_dummy_data.json b/src/CLI/actioner/port_channel_dummy_data.json new file mode 100644 index 0000000000..20149bb2d5 --- /dev/null +++ b/src/CLI/actioner/port_channel_dummy_data.json @@ -0,0 +1,48 @@ +{ + "openconfig-interfaces:interface": [ + { + "members": [ + "Ethernet56", + "Ethernet60" + ], + "min-links": 2, + "mtu": 9100, + "admin-status": "up", + "name": "Portchannel0" + }, + { + "members": [ + "Ethernet64", + "Ethernet68" + ], + "min-links": 1, + "mtu": 9100, + "admin-status": "up", + "name": "Portchannel1" + }, + { + "members": [ + "Ethernet24", + "Ethernet12" + ], + "min-links": 1, + "mtu": 9100, + "admin-status": "up", + "name": "Portchannel2" + }, + { + "members": [], + "min-links": 1, + "mtu": 9100, + "admin-status": "up", + "name": "Portchannel3" + }, + { + "members": [], + "min-links": 1, + "mtu": 9100, + "admin-status": "up", + "name": "Portchannel4" + } + ] +} diff --git a/src/CLI/actioner/sonic-cli-if.py b/src/CLI/actioner/sonic-cli-if.py index 9ed5f27006..2b20d9cfcd 100755 --- a/src/CLI/actioner/sonic-cli-if.py +++ b/src/CLI/actioner/sonic-cli-if.py @@ -21,6 +21,7 @@ import time import json import ast +import yaml import openconfig_interfaces_client from rpipe_utils import pipestr from openconfig_interfaces_client.rest import ApiException @@ -44,7 +45,6 @@ def call_method(name, args): def generate_body(func, args): body = None - # Get the rules of all ACL table entries. if func.__name__ == 'patch_openconfig_interfaces_interfaces_interface_config_description': keypath = [ args[0] ] body = { "openconfig-interfaces:description": args[1] } @@ -94,6 +94,97 @@ def run(func, args): c.verify_ssl = False aa = openconfig_interfaces_client.OpenconfigInterfacesApi(api_client=openconfig_interfaces_client.ApiClient(configuration=c)) +# Code for Portchannel cli skeleton, reading and writing data to port_channel_dummy_data json file + #create a port-channel + if "Portchannel" in args[0] and func.__name__ == 'patch_openconfig_interfaces_interfaces_interface': + with open('port_channel_dummy_data.json', 'r') as f: + data= yaml.safe_load(f) + for dict in data['openconfig-interfaces:interface']: + if dict["name"] == args[0]: + return + body = { + "name": args[0], + "min-links": 1, + "mtu": 9100, + "admin-status": "up", + "members": [] + } + data['openconfig-interfaces:interface'].append(body) + with open('port_channel_dummy_data.json', 'w') as f: + json.dump(data, f, sort_keys=True, indent=4) + print ("Success") + return + + #show given port-channel details + if "Portchannel" in args[0] and func.__name__ == 'get_openconfig_if_aggregate_interfaces_interface_aggregation_state': + with open('port_channel_dummy_data.json', 'r') as f: + data= yaml.safe_load(f) + for dict in data['openconfig-interfaces:interface']: + if dict["name"] == args[0]: + show_cli_output("show_portchannel_id.j2", dict) + return + print("%Error: Entry not found") + return + + #show port-channels summary + if "Portchannel" in args[0] and func.__name__ == 'get_openconfig_interfaces_interfaces': + with open('port_channel_dummy_data.json', 'r') as f: + data= yaml.safe_load(f) + show_cli_output("show_portchannel.j2", data) + return + + #add members to port-channel + if func.__name__ == 'patch_openconfig_if_aggregate_interfaces_interface_ethernet_config_aggregate_id': + port_c = 'Portchannel' + args[1] + with open('port_channel_dummy_data.json', 'r') as readf: + data= yaml.safe_load(readf) + for dict in data['openconfig-interfaces:interface']: + if dict["name"] == port_c: + dict["members"].append(args[0]) + with open('port_channel_dummy_data.json', 'w') as writef: + json.dump(data, writef, sort_keys=True, indent=4) + print ("Success") + return + print ("Failed-entry not found") + return + + #remove members from port-channel + if func.__name__ == 'delete_openconfig_if_aggregate_interfaces_interface_ethernet_config_aggregate_id': + return("Success") + + #config mtu for port-channel + if "po" in args[0] and func.__name__ == 'patch_openconfig_interfaces_interfaces_interface_config_mtu': + return("Success") + + #delete port-channel + if "Portchannel" in args[0] and func.__name__ == 'delete_openconfig_interfaces_interfaces_interface': + with open('port_channel_dummy_data.json', 'r') as f: + data= yaml.safe_load(f) + for dict in data['openconfig-interfaces:interface']: + if dict["name"] == args[0]: + data['openconfig-interfaces:interface'].remove(dict) + with open('port_channel_dummy_data.json', 'w') as writef: + json.dump(data, writef, sort_keys=True, indent=4) + print ("Success") + return + print ("Failed-entry not found") + return + + #config min-links in port-channel + if func.__name__ == 'patch_openconfig_if_aggregate_interfaces_interface_aggregation_config_min_links': + with open('port_channel_dummy_data.json', 'r') as f: + data= yaml.safe_load(f) + port_c = 'Portchannel'+args[0][2:] + for dict in data['openconfig-interfaces:interface']: + if dict["name"] == port_c: + dict["min-links"]=args[1] + with open('port_channel_dummy_data.json', 'w') as f: + json.dump(data, f, sort_keys=True, indent=4) + print ("Success") + return + print ("Failed-entry not found") + return + # create a body block keypath, body = generate_body(func, args) diff --git a/src/CLI/clitree/cli-xml/interface.xml b/src/CLI/clitree/cli-xml/interface.xml index 3341170d76..5c0a3aa344 100644 --- a/src/CLI/clitree/cli-xml/interface.xml +++ b/src/CLI/clitree/cli-xml/interface.xml @@ -53,7 +53,21 @@ limitations under the License. ptype="UINT" optional="true" > - + + + + + - - - - - + name="interface" + help="Select an interface" + /> + + + + + + + + + + python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_interfaces_interfaces_interface Vlan${vlan-id} + + + + + python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_interfaces_interfaces_interface Portchannel${lag-id} + + + + + + + + + + + + + + if test "${if-subcommands}" = "vlan"; then + python $SONIC_CLI_ROOT/sonic-cli-if.py delete_openconfig_interfaces_interfaces_interface Vlan${vlan-id} + fi + if test "${if-subcommands}" = "port-channel"; then + python $SONIC_CLI_ROOT/sonic-cli-if.py delete_openconfig_interfaces_interfaces_interface Portchannel${lag-id} + fi + + - - python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_interfaces_interfaces_interface_config_enabled ${iface} False - - - python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_interfaces_interfaces_interface_config_enabled ${iface} True - - - python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_interfaces_interfaces_interface_config_description ${iface} ${desc} + python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_interfaces_interfaces_interface_config_description ${iface} ${desc} + @@ -147,8 +233,8 @@ limitations under the License. - python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_interfaces_interfaces_interface_config_mtu ${iface} ${mtu} @@ -158,6 +244,279 @@ limitations under the License. help="Remove MTU"> python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_interfaces_interfaces_interface_config_mtu ${iface} 9100 + + + python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_if_aggregate_interfaces_interface_ethernet_config_aggregate_id ${iface} ${lag-id} + + + python $SONIC_CLI_ROOT/sonic-cli-if.py delete_openconfig_if_aggregate_interfaces_interface_ethernet_config_aggregate_id ${iface} + + + python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_interfaces_interfaces_interface_config_enabled ${iface} False + + + python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_interfaces_interfaces_interface_config_enabled ${iface} True + + + + + + + + + + + + + + + + + + + + + + + if test "${switchport-subcommands}" = "access"; then + python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_vlan_interfaces_interface_ethernet_switched_vlan_config ${iface} ACCESS ${vlan-id} + else + python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_vlan_interfaces_interface_ethernet_switched_vlan_config ${iface} TRUNK ${vlan-id} + fi + + + + + + + + + + + + + + + + + + + + + + if test "${switchport-subcommands}" = "access"; then + python $SONIC_CLI_ROOT/sonic-cli-if.py delete_openconfig_vlan_interfaces_interface_ethernet_switched_vlan_config_access_vlan ${iface} ACCESS + else + python $SONIC_CLI_ROOT/sonic-cli-if.py delete_openconfig_vlan_interfaces_interface_ethernet_switched_vlan_config_trunk_vlans ${iface} TRUNK ${vlan-id} + fi + + + + + + + + + + + + + + + + python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_if_aggregate_interfaces_interface_aggregation_config_min_links ${po_id} ${min-links} + + + python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_if_aggregate_interfaces_interface_aggregation_config_min_links ${po_id} 1 + + + + python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_interfaces_interfaces_interface_config_mtu ${po_id} ${mtu} + + + python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_interfaces_interfaces_interface_config_mtu ${po_id} 9100 + + + + + + + + + + + + + + + + + diff --git a/src/CLI/renderer/templates/show_portchannel.j2 b/src/CLI/renderer/templates/show_portchannel.j2 new file mode 100644 index 0000000000..be5f282ad5 --- /dev/null +++ b/src/CLI/renderer/templates/show_portchannel.j2 @@ -0,0 +1,9 @@ +{% set just_var = 2 %} + +Flags: A - Active, Dw - Oper status down +{{'----------------------------------------------------------------------------------------------------------------------------'}} +{{'%-20s'|format("Port-Channel")}}{{'%-20s'|format("min-links")}}{{'%-20s'|format("Protocol")}}{{'%-15s'|format("MTU")}}{{'%-15s'|format("Admin")}}{{'%-15s'|format("port-members")}} +{{'----------------------------------------------------------------------------------------------------------------------------'}} +{% for dict in json_output['openconfig-interfaces:interface'] %} +{{'%-20s'|format(dict['name']|string)}}{{'%-20s'|format(dict['min-links'])}}{{'%-20s'|format("LACP(A)(Dw)")}}{{'%-15s'|format(dict['mtu'])}}{{'%-15s'|format(dict['admin-status'])}}{{'%-15s'|format(dict['members']|string|replace("[", "")|replace("]", ""))}} +{% endfor %} diff --git a/src/CLI/renderer/templates/show_portchannel_id.j2 b/src/CLI/renderer/templates/show_portchannel_id.j2 new file mode 100644 index 0000000000..b45173aaa9 --- /dev/null +++ b/src/CLI/renderer/templates/show_portchannel_id.j2 @@ -0,0 +1,8 @@ +{% set just_var = 2 %} + +Flags: A - Active, Dw - Oper status down +{{'----------------------------------------------------------------------------------------------------------------------------'}} +{{'%-20s'|format("Port-Channel")}}{{'%-20s'|format("min-links")}}{{'%-20s'|format("Protocol")}}{{'%-15s'|format("MTU")}}{{'%-15s'|format("Admin")}}{{'%-15s'|format("port-members")}} +{{'----------------------------------------------------------------------------------------------------------------------------'}} +{% set dict = json_output %} +{{'%-20s'|format(dict['name']|string)}}{{'%-20s'|format(dict['min-links'])}}{{'%-20s'|format("LACP(A)")}}{{'%-15s'|format(dict['mtu'])}}{{'%-15s'|format(dict['admin-status'])}}{{'%-15s'|format(dict['members']|string|replace("[", "")|replace("]", ""))}} From feddf921d37c5dcc91ca4442f149bf96424263b0 Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Fri, 20 Sep 2019 14:45:43 -0700 Subject: [PATCH 154/214] Add post transformer infra --- .../annotations/openconfig-acl-annot.yang | 6 +++ src/translib/transformer/xfmr_acl.go | 18 +++++-- src/translib/transformer/xfmr_interface.go | 21 +++++--- src/translib/transformer/xlate.go | 6 +-- src/translib/transformer/xlate_to_db.go | 49 ++++++++++++++++--- src/translib/transformer/xspec.go | 3 +- 6 files changed, 80 insertions(+), 23 deletions(-) diff --git a/models/yang/annotations/openconfig-acl-annot.yang b/models/yang/annotations/openconfig-acl-annot.yang index 877629b319..28b98e9b4e 100644 --- a/models/yang/annotations/openconfig-acl-annot.yang +++ b/models/yang/annotations/openconfig-acl-annot.yang @@ -9,6 +9,12 @@ module openconfig-acl-annot { import openconfig-acl { prefix oc-acl; } import openconfig-packet-match { prefix oc-pkt-match; } + deviation /oc-acl:acl { + deviate add { + sonic-ext:post-transformer "acl_post_xfmr"; + } + } + deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set { deviate add { sonic-ext:table-name "ACL_TABLE"; diff --git a/src/translib/transformer/xfmr_acl.go b/src/translib/transformer/xfmr_acl.go index 2c7216f1eb..3f07baa4a0 100644 --- a/src/translib/transformer/xfmr_acl.go +++ b/src/translib/transformer/xfmr_acl.go @@ -39,6 +39,7 @@ func init() { XlateFuncBind("DbToYang_acl_forwarding_action_xfmr", DbToYang_acl_forwarding_action_xfmr) XlateFuncBind("validate_ipv4", validate_ipv4) XlateFuncBind("validate_ipv6", validate_ipv6) + XlateFuncBind("acl_post_xfmr", acl_post_xfmr) } const ( @@ -51,7 +52,6 @@ const ( OPENCONFIG_ACL_TYPE_IPV6 = "ACL_IPV6" OPENCONFIG_ACL_TYPE_L2 = "ACL_L2" ACL_TYPE = "type" - MIN_PRIORITY = 1 MAX_PRIORITY = 65535 ) @@ -183,16 +183,24 @@ func getL2EtherType(etherType uint64) interface{} { var validate_ipv4 ValidateCallpoint = func(inParams XfmrParams) (bool) { if strings.Contains(inParams.key, "ACL_IPV4") { return true - } else { - return false } + return false } var validate_ipv6 ValidateCallpoint = func(inParams XfmrParams) (bool) { if strings.Contains(inParams.key, "ACL_IPV6") { return true - } else { - return false } + return false +} + +//////////////////////////////////////////// +// Post Transformer +//////////////////////////////////////////// +var acl_post_xfmr PostXfmrFunc = func(inParams XfmrParams) (map[string]map[string]db.Value, error) { + log.Info("In Post transformer") + //TODO: check if a default ACL Rule exists, else create one and update the resultMap with default rule + // Return will be the updated result map + return (*inParams.dbDataMap)[inParams.curDb], nil } //////////////////////////////////////////// diff --git a/src/translib/transformer/xfmr_interface.go b/src/translib/transformer/xfmr_interface.go index 472fbc3dff..7109cf4de8 100644 --- a/src/translib/transformer/xfmr_interface.go +++ b/src/translib/transformer/xfmr_interface.go @@ -21,14 +21,14 @@ type XfmrParams struct { /** * KeyXfmrYangToDb type is defined to use for conversion of Yang key to DB Key * Transformer function definition. - * Param: Database info, YgotRoot, operation, Xpath + * Param: XfmrParams structure having Database info, YgotRoot, operation, Xpath * Return: Database keys to access db entry, error **/ type KeyXfmrYangToDb func (inParams XfmrParams) (string, error) /** * KeyXfmrDbToYang type is defined to use for conversion of DB key to Yang key * Transformer function definition. - * Param: Database info, operation, Database keys to access db entry + * Param: XfmrParams structure having Database info, operation, Database keys to access db entry * Return: multi dimensional map to hold the yang key attributes of complete xpath, error **/ type KeyXfmrDbToYang func (inParams XfmrParams) (map[string]interface{}, error) @@ -43,7 +43,7 @@ type FieldXfmrYangToDb func (inParams XfmrParams) (map[string]string, error) /** * FieldXfmrDbtoYang type is defined to use for conversion of DB field to Yang field * Transformer function definition. - * Param: Database info, operation, DB data in multidimensional map, output param YgotRoot + * Param: XfmrParams structure having Database info, operation, DB data in multidimensional map, output param YgotRoot * Return: error **/ type FieldXfmrDbtoYang func (inParams XfmrParams) (map[string]interface{}, error) @@ -51,24 +51,33 @@ type FieldXfmrDbtoYang func (inParams XfmrParams) (map[string]interface{}, erro /** * SubTreeXfmrYangToDb type is defined to use for handling the yang subtree to DB * Transformer function definition. - * Param: Database info, YgotRoot, operation, Xpath + * Param: XfmrParams structure having Database info, YgotRoot, operation, Xpath * Return: multi dimensional map to hold the DB data, error **/ type SubTreeXfmrYangToDb func (inParams XfmrParams) (map[string]map[string]db.Value, error) /** * SubTreeXfmrDbToYang type is defined to use for handling the DB to Yang subtree * Transformer function definition. - * Param : Database pointers, current db, operation, DB data in multidimensional map, output param YgotRoot, uri + * Param : XfmrParams structure having Database pointers, current db, operation, DB data in multidimensional map, output param YgotRoot, uri * Return : error **/ type SubTreeXfmrDbToYang func (inParams XfmrParams) (error) /** * ValidateCallpoint is used to validate a YANG node during data translation back to YANG as a response to GET - * Param : Database pointers, current db, operation, DB data in multidimensional map, output param YgotRoot, uri + * Param : XfmrParams structure having Database pointers, current db, operation, DB data in multidimensional map, output param YgotRoot, uri * Return : bool **/ type ValidateCallpoint func (inParams XfmrParams) (bool) +/** + * PostXfmrFunc type is defined to use for handling any default handling operations required as part of the CREATE + * Transformer function definition. + * Param: XfmrParams structure having database pointers, current db, operation, DB data in multidimensional map, YgotRoot, uri + * Return: multi dimensional map to hold the DB data, error + **/ +type PostXfmrFunc func (inParams XfmrParams) (map[string]map[string]db.Value, error) + + /** * Xfmr validation interface for validating the callback registration of app modules * transformer methods. diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index 6aefb42a7b..f5489096f5 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -53,18 +53,18 @@ func XlateFuncBind(name string, fn interface{}) (err error) { func XlateFuncCall(name string, params ...interface{}) (result []reflect.Value, err error) { if _, ok := XlateFuncs[name]; !ok { err = errors.New(name + " Xfmr function does not exist.") - return + return nil, nil } if len(params) != XlateFuncs[name].Type().NumIn() { err = ErrParamsNotAdapted - return + return nil, nil } in := make([]reflect.Value, len(params)) for k, param := range params { in[k] = reflect.ValueOf(param) } result = XlateFuncs[name].Call(in) - return + return result, nil } func TraverseDb(dbs [db.MaxDB]*db.DB, spec KeySpec, result *map[db.DBNum]map[string]map[string]db.Value, parentKey *db.Key) error { diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index c84f54d73c..f839e96ddd 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -18,6 +18,18 @@ import ( const SONIC_TABLE_INDEX = 2 const SONIC_FIELD_INDEX = 3 +/* Invoke the post tansformer */ +func postXfmrHandlerFunc(inParams XfmrParams) (map[string]map[string]db.Value, error) { + xpath, _ := RemoveXPATHPredicates(inParams.uri) + ret, err := XlateFuncCall(xSpecMap[xpath].xfmrPost, inParams) + if err != nil { + return nil, err + } + retData := ret[0].Interface().(map[string]map[string]db.Value) + log.Info("Post Transformer function :", xSpecMap[xpath].xfmrPost, " Xpath: ", xpath, " retData: ", retData) + return retData, err +} + /* Fill redis-db map with field & value info */ func dataToDBMapAdd(tableName string, dbKey string, result map[string]map[string]db.Value, field string, value string) { _, ok := result[tableName] @@ -281,14 +293,35 @@ func dbMapUpdate(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string, jsonDat /* Get the data from incoming create request, create map and fill with dbValue(ie. field:value to write into redis-db */ func dbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string, jsonData interface{}, result map[string]map[string]db.Value) error { - root := xpathRootNameGet(path) - if isCvlYang(path) { - cvlYangReqToDbMapCreate(jsonData, result) - } else { - yangReqToDbMapCreate(d, ygRoot, oper, root, "", "", jsonData, result) - } - printDbData(result, "/tmp/yangToDbDataCreate.txt") - return nil + var err error + root := xpathRootNameGet(path) + if isCvlYang(path) { + err = cvlYangReqToDbMapCreate(jsonData, result) + } else { + err = yangReqToDbMapCreate(d, ygRoot, oper, root, "", "", jsonData, result) + } + if err == nil { + if oper == CREATE { + moduleNm := "/" + strings.Split(path, "/")[1] + log.Infof("Module name for path %s is %s", path, moduleNm) + if _, ok := xSpecMap[moduleNm]; ok { + if xSpecMap[moduleNm].yangDataType == "container" { + log.Info("Invoke post transformer: ", xSpecMap[moduleNm].xfmrPost) + dbDataMap := make(map[db.DBNum]map[string]map[string]db.Value) + dbDataMap[db.ConfigDB] = result + var dbs [db.MaxDB]*db.DB + inParams := formXfmrInputRequest(d, dbs, db.ConfigDB, ygRoot, path, oper, "", &dbDataMap, nil) + result, err = postXfmrHandlerFunc(inParams) + } + } else { + log.Errorf("No Entry exists for module %s in XSpecMap. Unable to process post xfmr (\"%v\") path(\"%v\") error (\"%v\").", oper, path, err) + } + } + printDbData(result, "/tmp/yangToDbDataCreate.txt") + } else { + log.Errorf("DBMapCreate req failed for oper (\"%v\") path(\"%v\") error (\"%v\").", oper, path, err) + } + return err } func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, xpathPrefix string, keyName string, jsonData interface{}, result map[string]map[string]db.Value) error { diff --git a/src/translib/transformer/xspec.go b/src/translib/transformer/xspec.go index 1dee5c705a..80774588e4 100644 --- a/src/translib/transformer/xspec.go +++ b/src/translib/transformer/xspec.go @@ -22,6 +22,7 @@ type yangXpathInfo struct { delim string fieldName string xfmrFunc string + xfmrPost string validateFunc string xfmrKey string dbIndex db.DBNum @@ -289,7 +290,7 @@ func annotEntryFill(xSpecMap map[string]*yangXpathInfo, xpath string, entry *yan case "field-transformer" : xpathData.xfmrFunc = ext.NName() case "post-transformer" : - xpathData.xfmrFunc = ext.NName() + xpathData.xfmrPost = ext.NName() case "get-validate" : xpathData.validateFunc = ext.NName() case "use-self-key" : From 51801599e6b3727cf41f4a1376398dc9d8e21e7b Mon Sep 17 00:00:00 2001 From: Partha Dutta Date: Sat, 21 Sep 2019 12:02:19 +0530 Subject: [PATCH 155/214] CVL changes for SONiC YANG --- Makefile | 1 + src/cvl/cvl.go | 30 +- src/cvl/internal/yparser/yparser.go | 8 +- src/cvl/schema/sonic-acl.yang | 257 +++++++++--------- src/cvl/schema/sonic-common.yang | 47 +--- src/cvl/schema/sonic-extension.yang | 61 +++++ src/cvl/schema/sonic-interface.yang | 22 +- src/cvl/schema/sonic-mirror-session.yang | 47 ++-- src/cvl/schema/sonic-port.yang | 80 +++--- src/cvl/testdata/schema/sonic-acl-dev.yang | 13 - .../testdata/schema/sonic-bgp-neighbor.yang | 86 +++--- src/cvl/testdata/schema/sonic-buffer-pg.yang | 53 ++-- .../testdata/schema/sonic-buffer-pool.yang | 51 ++-- .../testdata/schema/sonic-buffer-profile.yang | 67 ++--- .../testdata/schema/sonic-cablelength.yang | 52 ++-- .../schema/sonic-device-metadata.yang | 94 ++++--- .../schema/sonic-device-neighbor.yang | 84 +++--- .../testdata/schema/sonic-dscp-tc-map.yang | 50 ++-- src/cvl/testdata/schema/sonic-pf-limits.yang | 14 +- .../schema/sonic-pfc-priority-queue-map.yang | 46 ++-- .../testdata/schema/sonic-port-qos-map.yang | 20 +- .../schema/sonic-portchannel-interface.yang | 34 +-- .../testdata/schema/sonic-portchannel.yang | 66 ++--- src/cvl/testdata/schema/sonic-queue.yang | 56 ++-- src/cvl/testdata/schema/sonic-scheduler.yang | 48 ++-- .../schema/sonic-tc-priority-group-map.yang | 45 ++- .../testdata/schema/sonic-tc-queue-map.yang | 46 ++-- src/cvl/testdata/schema/sonic-vlan-dev.yang | 6 +- .../testdata/schema/sonic-vlan-interface.yang | 34 +-- src/cvl/testdata/schema/sonic-vlan.yang | 100 +++---- .../testdata/schema/sonic-wred-profile.yang | 96 ++++--- 31 files changed, 841 insertions(+), 873 deletions(-) create mode 100644 src/cvl/schema/sonic-extension.yang diff --git a/Makefile b/Makefile index 01d0a951db..39dc969576 100644 --- a/Makefile +++ b/Makefile @@ -63,6 +63,7 @@ cli: rest-server cvl: go-deps $(MAKE) -C src/cvl $(MAKE) -C src/cvl/schema + $(MAKE) -C src/cvl/testdata/schema cvl-test: $(MAKE) -C src/cvl gotest diff --git a/src/cvl/cvl.go b/src/cvl/cvl.go index f90486ecd9..859d78043f 100644 --- a/src/cvl/cvl.go +++ b/src/cvl/cvl.go @@ -227,14 +227,17 @@ func storeModelInfo(modelFile string, module *yparser.YParserModule) { //such mo modelInfo.modelNs[modelName] = modelNs //Store metadata present in each list - nodes = xmlquery.Find(root, "//module/container/list") + nodes = xmlquery.Find(root, "//module/container/container/list") if (nodes == nil) { return } for _, node := range nodes { - //for each list + //for each list, remove "_LIST" suffix tableName := node.Attr[0].Value + if (strings.HasSuffix(tableName, "_LIST")) { + tableName = tableName[0:len(tableName) - len("_LIST")] + } tableInfo := modelTableInfo{modelName: modelName} //Store the reference for list node to be used later listNode := node @@ -244,6 +247,7 @@ func storeModelInfo(modelFile string, module *yparser.YParserModule) { //such mo tableInfo.dbNum = CONFIG_DB //default delim '|' tableInfo.redisKeyDelim = "|" + modelInfo.allKeyDelims[tableInfo.redisKeyDelim] = true fieldCount := 0 @@ -510,9 +514,9 @@ func (c *CVL) checkPathForTableEntry(tableName string, currentValue string, cfgD //Table name should appear like "../VLAN_MEMBER/tagging_mode' or ' // "/prt:PORT/prt:ifname" //re := regexp.MustCompile(fmt.Sprintf(".*[/]([a-zA-Z]*:)?%s[\\[/]", tblNameSrch)) - tblSrchIdx := strings.Index(xpath, fmt.Sprintf("/%s", tblNameSrch)) //no preifx + tblSrchIdx := strings.Index(xpath, fmt.Sprintf("/%s_LIST", tblNameSrch)) //no preifx if (tblSrchIdx < 0) { - tblSrchIdx = strings.Index(xpath, fmt.Sprintf(":%s", tblNameSrch)) //with prefix + tblSrchIdx = strings.Index(xpath, fmt.Sprintf(":%s_LIST", tblNameSrch)) //with prefix } if (tblSrchIdx < 0) { continue @@ -986,14 +990,16 @@ func (c *CVL) addLeafRef(config bool, tableName string, name string, value strin //only key is there, value wil be fetched and stored here, //if value can't fetched this entry will be deleted that time - if (c.tmpDbCache[refTableName] == nil) { - c.tmpDbCache[refTableName] = map[string]interface{}{redisKey: nil} + //Strip "_LIST" suffix + refRedisTableName := refTableName[0:len(refTableName) - len("_LIST")] + if (c.tmpDbCache[refRedisTableName] == nil) { + c.tmpDbCache[refRedisTableName] = map[string]interface{}{redisKey: nil} } else { - tblMap := c.tmpDbCache[refTableName] + tblMap := c.tmpDbCache[refRedisTableName] _, exist := tblMap.(map[string]interface{})[redisKey] if (exist == false) { tblMap.(map[string]interface{})[redisKey] = nil - c.tmpDbCache[refTableName] = tblMap + c.tmpDbCache[refRedisTableName] = tblMap } } } @@ -1307,10 +1313,16 @@ func (c *CVL) generateTableData(config bool, jsonNode *jsonquery.Node)(*yparser. tableName := fmt.Sprintf("%s",jsonNode.Data) c.batchLeaf = "" + //Every Redis table is mapped as list within a container, + //E.g. ACL_RULE is mapped as + // container ACL_RULE { list ACL_RULE_LIST {} } var topNode *yparser.YParserNode + topNode = c.yp.AddChildNode(modelInfo.tableInfo[tableName].module, nil, modelInfo.tableInfo[tableName].modelName) + listConatinerNode := c.yp.AddChildNode(modelInfo.tableInfo[tableName].module, + topNode, tableName) //Traverse each key instance for jsonNode = jsonNode.FirstChild; jsonNode != nil; jsonNode = jsonNode.NextSibling { @@ -1334,7 +1346,7 @@ func (c *CVL) generateTableData(config bool, jsonNode *jsonquery.Node)(*yparser. for ; totalKeyComb > 0 ; totalKeyComb-- { //Add table i.e. create list element - listNode := c.addChildNode(tableName, topNode, tableName) //Add the list to the top node + listNode := c.addChildNode(tableName, listConatinerNode, tableName + "_LIST") //Add the list to the top node //For each key combination //Add keys as leaf to the list diff --git a/src/cvl/internal/yparser/yparser.go b/src/cvl/internal/yparser/yparser.go index a41a058507..dff83d01c7 100644 --- a/src/cvl/internal/yparser/yparser.go +++ b/src/cvl/internal/yparser/yparser.go @@ -76,15 +76,15 @@ int lyd_data_validate_all(const char *data, const char *depData, const char *oth int lyd_multi_new_leaf(struct lyd_node *parent, const struct lys_module *module, const char *leafVal) { char s[4048]; - char *name, *val; + char *name, *val, *saveptr; strcpy(s, leafVal); - name = strtok(s, "#"); + name = strtok_r(s, "#", &saveptr); while (name != NULL) { - val = strtok(NULL, "#"); + val = strtok_r(NULL, "#", &saveptr); if (val != NULL) { if (NULL == lyd_new_leaf(parent, module, name, val)) @@ -93,7 +93,7 @@ int lyd_multi_new_leaf(struct lyd_node *parent, const struct lys_module *module, } } - name = strtok(NULL, "#"); + name = strtok_r(NULL, "#", &saveptr); } return 0; diff --git a/src/cvl/schema/sonic-acl.yang b/src/cvl/schema/sonic-acl.yang index fc65e5ac4a..d778e8da5f 100644 --- a/src/cvl/schema/sonic-acl.yang +++ b/src/cvl/schema/sonic-acl.yang @@ -12,7 +12,7 @@ module sonic-acl { } import sonic-common { - prefix scommon; + prefix cmn; } import sonic-port { @@ -39,181 +39,186 @@ module sonic-acl { container sonic-acl { - list ACL_TABLE { - key "aclname"; + container ACL_TABLE { + list ACL_TABLE_LIST { + key "aclname"; - leaf aclname { - type string { - pattern '[a-zA-Z0-9]{1}([-a-zA-Z0-9_]{0,71})'; - length 1..72; + leaf aclname { + type string { + pattern '[a-zA-Z0-9]{1}([-a-zA-Z0-9_]{0,71})'; + length 1..72; + } } - } - leaf policy_desc { - type string { - length 1..255 { - error-app-tag policy-desc-invalid-length; + leaf policy_desc { + type string { + length 1..255 { + error-app-tag policy-desc-invalid-length; + } } } - } - leaf stage { - type enumeration { - enum INGRESS; - enum EGRESS; + leaf stage { + type enumeration { + enum INGRESS; + enum EGRESS; + } } - } - leaf type { - type enumeration { - enum MIRROR; - enum L2; - enum L3; - enum L3V6; + leaf type { + type enumeration { + enum MIRROR; + enum L2; + enum L3; + enum L3V6; + } } - } - leaf-list ports { - type leafref { - path "/prt:sonic-port/prt:PORT/prt:ifname"; + leaf-list ports { + type leafref { + path "/prt:sonic-port/prt:PORT/prt:PORT_LIST/prt:ifname"; + } } } } - list ACL_RULE { - key "aclname rulename"; + container ACL_RULE { - leaf aclname { - type leafref { - path "../../ACL_TABLE/aclname"; - } - must "(/scommon:operation/scommon:operation != 'DELETE') or " + - "count(current()/../../ACL_TABLE[aclname=current()]/ports) = 0" { - error-message "Ports are already bound to this rule."; - } - } + list ACL_RULE_LIST { + key "aclname rulename"; - leaf rulename { - type string; - } + leaf aclname { + type leafref { + path "../../../ACL_TABLE/ACL_TABLE_LIST/aclname"; + } + must "(/cmn:operation/cmn:operation != 'DELETE') or " + + "count(current()/../../../ACL_TABLE/ACL_TABLE_LIST[aclname=current()]/ports) = 0" { + error-message "Ports are already bound to this rule."; + } + } - leaf PRIORITY { - type uint16 { - range "1..65535"{ - error-message "Invalid ACL rule priority."; - } + leaf rulename { + type string; } - } - - leaf RULE_DESCRIPTION { - type string; - } - leaf PACKET_ACTION { - type enumeration { - enum FORWARD; - enum DROP; - enum REDIRECT; + leaf PRIORITY { + type uint16 { + range "1..65535"{ + error-message "Invalid ACL rule priority."; + } + } } - } - leaf MIRROR_ACTION { - type leafref { - path "/sms:sonic-mirror-session/sms:MIRROR_SESSION/sms:name"; + leaf RULE_DESCRIPTION { + type string; } - } - leaf IP_TYPE { - type enumeration { - enum ANY; - enum IP; - enum IPV4; - enum IPV4ANY; - enum NON_IPV4; - enum IPV6ANY; - enum NON_IPV6; + leaf PACKET_ACTION { + type enumeration { + enum FORWARD; + enum DROP; + enum REDIRECT; + } } - } - leaf IP_PROTOCOL { - type uint8 { - range "1|2|6|17|46|47|51|103|115"; + leaf MIRROR_ACTION { + type leafref { + path "/sms:sonic-mirror-session/sms:MIRROR_SESSION/sms:MIRROR_SESSION_LIST/sms:name"; + } } - } - leaf ETHER_TYPE { - type string { - pattern "(0x88CC)|(0x8100)|(0x8915)|(0x0806)|(0x0800)|(0x86DD)|(0x8847)" { - error-message "Invalid ACL Rule Ether Type"; - error-app-tag ether-type-invalid; + leaf IP_TYPE { + type enumeration { + enum ANY; + enum IP; + enum IPV4; + enum IPV4ANY; + enum NON_IPV4; + enum IPV6ANY; + enum NON_IPV6; } } - } - choice ip_src_dst { - case ipv4_src_dst { - //when "boolean(IP_TYPE[.='ANY' or .='IP' or .='IPV4' or .='IPV4ANY'])"; - leaf SRC_IP { - mandatory true; - type inet:ipv4-prefix; + leaf IP_PROTOCOL { + type uint8 { + range "1|2|6|17|46|47|51|103|115"; } - leaf DST_IP { - mandatory true; - type inet:ipv4-prefix; + } + + leaf ETHER_TYPE { + type string { + pattern "(0x88CC)|(0x8100)|(0x8915)|(0x0806)|(0x0800)|(0x86DD)|(0x8847)" { + error-message "Invalid ACL Rule Ether Type"; + error-app-tag ether-type-invalid; + } } } - case ipv6_src_dst { - //when "boolean(IP_TYPE[.='ANY' or .='IP' or .='IPV6' or .='IPV6ANY'])"; - leaf SRC_IPV6 { - mandatory true; - type inet:ipv6-prefix; + + choice ip_src_dst { + case ipv4_src_dst { + //when "boolean(IP_TYPE[.='ANY' or .='IP' or .='IPV4' or .='IPV4ANY'])"; + leaf SRC_IP { + mandatory true; + type inet:ipv4-prefix; + } + leaf DST_IP { + mandatory true; + type inet:ipv4-prefix; + } } - leaf DST_IPV6 { - mandatory true; - type inet:ipv6-prefix; + case ipv6_src_dst { + //when "boolean(IP_TYPE[.='ANY' or .='IP' or .='IPV6' or .='IPV6ANY'])"; + leaf SRC_IPV6 { + mandatory true; + type inet:ipv6-prefix; + } + leaf DST_IPV6 { + mandatory true; + type inet:ipv6-prefix; + } } } - } - choice src_port { - case l4_src_port { - leaf L4_SRC_PORT { - type uint16; + choice src_port { + case l4_src_port { + leaf L4_SRC_PORT { + type uint16; + } } - } - case l4_src_port_range { - leaf L4_SRC_PORT_RANGE { - type string { - pattern "[0-9]{1,5}(-)[0-9]{1,5}"; + case l4_src_port_range { + leaf L4_SRC_PORT_RANGE { + type string { + pattern "[0-9]{1,5}(-)[0-9]{1,5}"; + } } } } - } - choice dst_port { - case l4_dst_port { - leaf L4_DST_PORT { - type uint16; + choice dst_port { + case l4_dst_port { + leaf L4_DST_PORT { + type uint16; + } } - } - case l4_dst_port_range { - leaf L4_DST_PORT_RANGE { - type string { - pattern "[0-9]{1,5}(-)[0-9]{1,5}"; + case l4_dst_port_range { + leaf L4_DST_PORT_RANGE { + type string { + pattern "[0-9]{1,5}(-)[0-9]{1,5}"; + } } } } - } - leaf TCP_FLAGS { - type string { - pattern "0[xX][0-9a-fA-F]{2}[/]0[xX][0-9a-fA-F]{2}"; + leaf TCP_FLAGS { + type string { + pattern "0[xX][0-9a-fA-F]{2}[/]0[xX][0-9a-fA-F]{2}"; + } } - } - leaf DSCP { - type uint8; + leaf DSCP { + type uint8; + } } } } diff --git a/src/cvl/schema/sonic-common.yang b/src/cvl/schema/sonic-common.yang index 329d40c537..77a81c5f84 100644 --- a/src/cvl/schema/sonic-common.yang +++ b/src/cvl/schema/sonic-common.yang @@ -1,11 +1,7 @@ module sonic-common { namespace "http://github.com/Azure/sonic-common"; - prefix sv; - - import ietf-yang-types { - prefix yang; - } + prefix scommon; organization "SONiC"; @@ -36,47 +32,6 @@ module sonic-common { } } - extension custom-handler { - description - "Node should be handled by custom handler"; - argument "name"; - } - - extension db-name { - description - "DB name, e.g. APPL_DB, CONFIG_DB"; - argument "value"; - } - - extension key-delim { - description - "Key delimeter, e.g. - |, :"; - argument "value"; - } - - extension key-pattern { - description - "Key pattern, e.g. - ACL_RULE|{aclname}|{rulename}"; - argument "value"; - } - - extension map-list { - description - "If it is a map list"; - argument "value"; - } - - extension map-leaf { - description - "Map leaf names"; - argument "value"; - } - - extension pf-check { - description - "Platform specific validation"; - argument "handler"; - } container operation { leaf operation { diff --git a/src/cvl/schema/sonic-extension.yang b/src/cvl/schema/sonic-extension.yang new file mode 100644 index 0000000000..f488809586 --- /dev/null +++ b/src/cvl/schema/sonic-extension.yang @@ -0,0 +1,61 @@ + +module sonic-extension { + namespace "http://github.com/Azure/sonic-extension"; + prefix sonic-ext; + + organization + "SONiC"; + + contact + "SONiC"; + + description + "SONIC Extension"; + + revision 2019-09-18 { + description + "Initial revision."; + } + + extension custom-handler { + description + "Node should be handled by custom handler"; + argument "name"; + } + + extension db-name { + description + "DB name, e.g. APPL_DB, CONFIG_DB"; + argument "value"; + } + + extension key-delim { + description + "Key delimeter, e.g. - |, :"; + argument "value"; + } + + extension key-pattern { + description + "Key pattern, e.g. - ACL_RULE|{aclname}|{rulename}"; + argument "value"; + } + + extension map-list { + description + "If it is a map list"; + argument "value"; + } + + extension map-leaf { + description + "Map leaf names"; + argument "value"; + } + + extension pf-check { + description + "Platform specific validation"; + argument "handler"; + } +} diff --git a/src/cvl/schema/sonic-interface.yang b/src/cvl/schema/sonic-interface.yang index 540b3a16b8..79ca4832e8 100644 --- a/src/cvl/schema/sonic-interface.yang +++ b/src/cvl/schema/sonic-interface.yang @@ -33,19 +33,23 @@ module sonic-interface { } container sonic-interface { - list INTERFACE { - key "portname ip_prefix"; - leaf portname{ - type leafref { - path "/prt:sonic-port/prt:PORT/prt:ifname"; + container INTERFACE { + + list INTERFACE_LIST { + key "portname ip_prefix"; + + leaf portname{ + type leafref { + path "/prt:sonic-port/prt:PORT/prt:PORT_LIST/prt:ifname"; + } } - } - leaf ip_prefix { - mandatory true; - type inet:ip-prefix; + leaf ip_prefix { + mandatory true; + type inet:ip-prefix; + } } } } diff --git a/src/cvl/schema/sonic-mirror-session.yang b/src/cvl/schema/sonic-mirror-session.yang index 1a2591cc0c..9805a121fa 100644 --- a/src/cvl/schema/sonic-mirror-session.yang +++ b/src/cvl/schema/sonic-mirror-session.yang @@ -30,35 +30,38 @@ module sonic-mirror-session { container sonic-mirror-session { - list MIRROR_SESSION { - key "name"; + container MIRROR_SESSION { - leaf name { - type string; - } + list MIRROR_SESSION_LIST { + key "name"; - leaf src_ip { - type inet:ipv4-address; - } + leaf name { + type string; + } - leaf dst_ip { - type inet:ipv4-address; - } + leaf src_ip { + type inet:ipv4-address; + } - leaf gre_type { - type string; - } + leaf dst_ip { + type inet:ipv4-address; + } - leaf dscp { - type uint8; - } + leaf gre_type { + type string; + } - leaf ttl { - type uint8; - } + leaf dscp { + type uint8; + } + + leaf ttl { + type uint8; + } - leaf queue { - type uint8; + leaf queue { + type uint8; + } } } } diff --git a/src/cvl/schema/sonic-port.yang b/src/cvl/schema/sonic-port.yang index 3d99d0534f..ba0959f3b6 100644 --- a/src/cvl/schema/sonic-port.yang +++ b/src/cvl/schema/sonic-port.yang @@ -2,10 +2,6 @@ module sonic-port { namespace "http://github.com/Azure/sonic-port"; prefix prt; - import ietf-yang-types { - prefix yang; - } - import sonic-common { prefix scommon; } @@ -26,53 +22,57 @@ module sonic-port { container sonic-port { - list PORT { - key "ifname"; - - leaf ifname { - type string { - pattern "Ethernet([1-3][0-9]{3}|[1-9][0-9]{2}|[1-9][0-9]|[0-9])"{ - error-message "Invalid interface name"; - error-app-tag interface-name-invalid; - } + + container PORT { + + list PORT_LIST { + key "ifname"; + + leaf ifname { + type string { + pattern "Ethernet([1-3][0-9]{3}|[1-9][0-9]{2}|[1-9][0-9]|[0-9])" { + error-message "Invalid interface name"; + error-app-tag interface-name-invalid; + } + } } - } - leaf index { - type uint16; - } + leaf index { + type uint16; + } - leaf speed { - type uint64; - } + leaf speed { + type uint64; + } - leaf valid_speeds { - type string; - } + leaf valid_speeds { + type string; + } - leaf alias { - type string; - } + leaf alias { + type string; + } - leaf description { - type string; - } + leaf description { + type string; + } - leaf mtu{ - type uint32 { - range "1312..9216" { - error-message "Invalid MTU value"; - error-app-tag mtu-invalid; + leaf mtu{ + type uint32 { + range "1312..9216" { + error-message "Invalid MTU value"; + error-app-tag mtu-invalid; + } } } - } - leaf lanes { - type string; - } + leaf lanes { + type string; + } - leaf admin_status { - type scommon:admin-status; + leaf admin_status { + type scommon:admin-status; + } } } } diff --git a/src/cvl/testdata/schema/sonic-acl-dev.yang b/src/cvl/testdata/schema/sonic-acl-dev.yang index 7fcf99f931..d11b40a95c 100644 --- a/src/cvl/testdata/schema/sonic-acl-dev.yang +++ b/src/cvl/testdata/schema/sonic-acl-dev.yang @@ -3,23 +3,10 @@ module sonic-acl-dev { prefix acld; yang-version 1.1; - import ietf-yang-types { - prefix yang; - } - - import ietf-inet-types { - prefix inet; - } - import sonic-acl { prefix sacl; } - import sonic-common { - prefix scommon; - } - - organization "SONiC"; diff --git a/src/cvl/testdata/schema/sonic-bgp-neighbor.yang b/src/cvl/testdata/schema/sonic-bgp-neighbor.yang index 2264e5238e..14504d6f9b 100644 --- a/src/cvl/testdata/schema/sonic-bgp-neighbor.yang +++ b/src/cvl/testdata/schema/sonic-bgp-neighbor.yang @@ -2,22 +2,14 @@ module sonic-bgp-neighbor { namespace "http://github.com/Azure/sonic-bgp-neighbor"; prefix sbn; - import ietf-yang-types { - prefix yang; - } - import ietf-inet-types { - prefix inet; - } + prefix inet; + } import sonic-common { prefix scommon; } - import sonic-port { - prefix prt; - } - organization "SONiC"; @@ -33,54 +25,58 @@ module sonic-bgp-neighbor { } container sonic-bgp-neighbor { - list BGP_NEIGHBOR { - key "ipaddress"; - leaf ipaddress{ - type inet:ip-address; - } + container BGP_NEIGHBOR { - leaf rrclient { - type uint8 { - range "0..255"; + list BGP_NEIGHBOR_LIST { + key "ipaddress"; + + leaf ipaddress{ + type inet:ip-address; } - } - leaf admin_status{ - type scommon:admin-status; - } + leaf rrclient { + type uint8 { + range "0..255"; + } + } - leaf peer_addr{ - type inet:ip-address; - } + leaf admin_status{ + type scommon:admin-status; + } - leaf name { - type string; - } + leaf peer_addr{ + type inet:ip-address; + } - leaf local_addr { - type inet:ipv4-address; - } + leaf name { + type string; + } - leaf nhopself { - type uint8 { - range "0..255"; + leaf local_addr { + type inet:ipv4-address; } - } - leaf holdtime { - type uint8 { - range "0..255"; + leaf nhopself { + type uint8 { + range "0..255"; + } } - } - leaf asn { - type uint64; - } + leaf holdtime { + type uint8 { + range "0..255"; + } + } + + leaf asn { + type uint64; + } - leaf keepalive { - type uint8 { - range "0..255"; + leaf keepalive { + type uint8 { + range "0..255"; + } } } } diff --git a/src/cvl/testdata/schema/sonic-buffer-pg.yang b/src/cvl/testdata/schema/sonic-buffer-pg.yang index 61b5013fed..27918081e8 100644 --- a/src/cvl/testdata/schema/sonic-buffer-pg.yang +++ b/src/cvl/testdata/schema/sonic-buffer-pg.yang @@ -2,16 +2,8 @@ module sonic-buffer-pg { namespace "http://github.com/Azure/sonic-buffer-pg"; prefix bpg; - import ietf-yang-types { - prefix yang; - } - - import ietf-inet-types { - prefix inet; - } - - import sonic-common { - prefix scommon; + import sonic-extension { + prefix sonic-ext; } import sonic-port { @@ -38,32 +30,37 @@ module sonic-buffer-pg { container sonic-buffer-pg { - list BUFFER_PG { - key "ifname pg_num"; - scommon:key-pattern "BUFFER_PG|({ifname},)*|{pg_num}"; //special pattern used for extracting keys from redis-key and fill populate the yang instance - // Total list instance = number(key1) * number(key2) * number(key3) - leaf ifname { - type leafref { - path "/prt:sonic-port/prt:PORT/prt:ifname"; + container BUFFER_PG { + + list BUFFER_PG_LIST { + key "ifname pg_num"; + sonic-ext:key-pattern "BUFFER_PG|({ifname},)*|{pg_num}"; //special pattern used for extracting keys from + //redis-key and fill populate the yang instance + // Total list instance = number(key1) * number(key2) * number(key3) + + leaf ifname { + type leafref { + path "/prt:sonic-port/prt:PORT/prt:PORT_LIST/prt:ifname"; + } } - } - leaf pg_num { - type string { - pattern "[0-7]((-)[0-7])?"{ - error-message "Invalid Buffer PG number"; - error-app-tag pg-num-invalid; + leaf pg_num { + type string { + pattern "[0-7]((-)[0-7])?" { + error-message "Invalid Buffer PG number"; + error-app-tag pg-num-invalid; + } } } - } - leaf profile { //Hash reference key - type leafref { - path "/bpf:sonic-buffer-profile/bpf:BUFFER_PROFILE/bpf:name"; + leaf profile { //Hash reference key + type leafref { + path "/bpf:sonic-buffer-profile/bpf:BUFFER_PROFILE/bpf:BUFFER_PROFILE_LIST/bpf:name"; + } } - } + } } } } diff --git a/src/cvl/testdata/schema/sonic-buffer-pool.yang b/src/cvl/testdata/schema/sonic-buffer-pool.yang index 130c28287f..5f935b3f94 100644 --- a/src/cvl/testdata/schema/sonic-buffer-pool.yang +++ b/src/cvl/testdata/schema/sonic-buffer-pool.yang @@ -2,18 +2,6 @@ module sonic-buffer-pool { namespace "http://github.com/Azure/sonic-buffer-pool"; prefix bpl; - import ietf-yang-types { - prefix yang; - } - - import ietf-inet-types { - prefix inet; - } - - import sonic-common { - prefix scommon; - } - organization "SONiC"; @@ -30,31 +18,34 @@ module sonic-buffer-pool { container sonic-buffer-pool { - list BUFFER_POOL { - key "name"; + container BUFFER_POOL { - leaf name { - type string; - } + list BUFFER_POOL_LIST { + key "name"; - leaf type { - type enumeration { - enum ingress; - enum egress; + leaf name { + type string; } - } - leaf mode { - type enumeration { - enum static; - enum dynamic; + leaf type { + type enumeration { + enum ingress; + enum egress; + } } - } - leaf size { - type uint64; - } + leaf mode { + type enumeration { + enum static; + enum dynamic; + } + } + leaf size { + type uint64; + } + + } } } } diff --git a/src/cvl/testdata/schema/sonic-buffer-profile.yang b/src/cvl/testdata/schema/sonic-buffer-profile.yang index 895def38c4..71f077654d 100644 --- a/src/cvl/testdata/schema/sonic-buffer-profile.yang +++ b/src/cvl/testdata/schema/sonic-buffer-profile.yang @@ -2,18 +2,6 @@ module sonic-buffer-profile { namespace "http://github.com/Azure/sonic-buffer-profile"; prefix bpf; - import ietf-yang-types { - prefix yang; - } - - import ietf-inet-types { - prefix inet; - } - - import sonic-common { - prefix scommon; - } - import sonic-buffer-pool { prefix bpl; } @@ -35,41 +23,44 @@ module sonic-buffer-profile { container sonic-buffer-profile { - list BUFFER_PROFILE { - key "name"; + container BUFFER_PROFILE { - leaf name { - type string; - } + list BUFFER_PROFILE_LIST { + key "name"; - leaf static_th { - type uint64; - } + leaf name { + type string; + } - leaf dynamic_th { - type int64; - } + leaf static_th { + type uint64; + } - leaf size { - type uint64; - } + leaf dynamic_th { + type int64; + } - leaf pool { - type leafref { - path "/bpl:sonic-buffer-pool/bpl:BUFFER_POOL/bpl:name"; + leaf size { + type uint64; } - } - leaf xon_offset { - type uint64; - } + leaf pool { + type leafref { + path "/bpl:sonic-buffer-pool/bpl:BUFFER_POOL/bpl:BUFFER_POOL_LIST/bpl:name"; + } + } - leaf xon { - type uint64; - } + leaf xon_offset { + type uint64; + } - leaf xoff { - type uint64; + leaf xon { + type uint64; + } + + leaf xoff { + type uint64; + } } } } diff --git a/src/cvl/testdata/schema/sonic-cablelength.yang b/src/cvl/testdata/schema/sonic-cablelength.yang index e4eeed031c..af4746211b 100644 --- a/src/cvl/testdata/schema/sonic-cablelength.yang +++ b/src/cvl/testdata/schema/sonic-cablelength.yang @@ -2,16 +2,8 @@ module sonic-cablelength { namespace "http://github.com/Azure/sonic-cablelength"; prefix scl; - import ietf-yang-types { - prefix yang; - } - - import ietf-inet-types { - prefix inet; - } - - import sonic-common { - prefix scommon; + import sonic-extension { + prefix sonic-ext; } import sonic-port { @@ -33,32 +25,36 @@ module sonic-cablelength { } container sonic-cablelength { - list CABLE_LENGTH { - key "name"; - scommon:map-list true; //special conversion for map tables - scommon:map-leaf "port length"; //every key:value pair is mapped to list keys, e.g. "1":"7" ==> tc_num=1, dscp=7 - leaf name { - type string; - } - - list CABLE_LENGTH { //this is list inside list for storing mapping between two fields - key "port length"; + container CABLE_LENGTH { - leaf port { - type leafref { - path "/prt:sonic-port/prt:PORT/prt:ifname"; - } + list CABLE_LENGTH_LIST { + key "name"; + sonic-ext:map-list true; //special conversion for map tables + sonic-ext:map-leaf "port length"; //every key:value pair is mapped to list keys, e.g. "1":"7" ==> tc_num=1, dscp=7 + leaf name { + type string; } - leaf length { - type string { - pattern "[0-9]?[0-9]m"; + list CABLE_LENGTH { //this is list inside list for storing mapping between two fields + key "port length"; + + leaf port { + type leafref { + path "/prt:sonic-port/prt:PORT/prt:PORT_LIST/prt:ifname"; + } + + } + + leaf length { + type string { + pattern "[0-9]?[0-9]m"; + } } } - } + } } } } diff --git a/src/cvl/testdata/schema/sonic-device-metadata.yang b/src/cvl/testdata/schema/sonic-device-metadata.yang index 0bd953836b..014f88cd47 100644 --- a/src/cvl/testdata/schema/sonic-device-metadata.yang +++ b/src/cvl/testdata/schema/sonic-device-metadata.yang @@ -29,64 +29,68 @@ module sonic-device-metadata { } container sonic-device-metadata { - list DEVICE_METADATA { - key "name"; - leaf name{ - type string; - } + container DEVICE_METADATA { - leaf hwsku { - type string; - } + list DEVICE_METADATA_LIST { + key "name"; - leaf hostname { - type string; - } + leaf name{ + type string; + } - leaf platform { - type string; - } + leaf hwsku { + type string; + } - leaf mac { - type yang:mac-address; - } + leaf hostname { + type string; + } - leaf bgp_asn { - type leafref { - path "/sbn:sonic-bgp-neighbor/sbn:BGP_NEIGHBOR/sbn:asn"; + leaf platform { + type string; } - } - leaf default_pfcwd_status { - type enumeration { - enum enable; - enum disable; - } - } + leaf mac { + type yang:mac-address; + } - leaf default_bgp_status { - type scommon:admin-status; - } + leaf bgp_asn { + type leafref { + path "/sbn:sonic-bgp-neighbor/sbn:BGP_NEIGHBOR/sbn:BGP_NEIGHBOR_LIST/sbn:asn"; + } + } - leaf docker_routing_config_mode { - type enumeration { - enum unified; - enum separated; - } - } + leaf default_pfcwd_status { + type enumeration { + enum enable; + enum disable; + } + } - leaf deployment_id { - type uint8 { - range "0..255"; + leaf default_bgp_status { + type scommon:admin-status; } - } - leaf type { - type enumeration { - enum ToRRouter; - enum LeafRouter; - } + leaf docker_routing_config_mode { + type enumeration { + enum unified; + enum separated; + } + } + + leaf deployment_id { + type uint8 { + range "0..255"; + } + } + + leaf type { + type enumeration { + enum ToRRouter; + enum LeafRouter; + } + } } } } diff --git a/src/cvl/testdata/schema/sonic-device-neighbor.yang b/src/cvl/testdata/schema/sonic-device-neighbor.yang index 9dc28187ef..a91302ac24 100644 --- a/src/cvl/testdata/schema/sonic-device-neighbor.yang +++ b/src/cvl/testdata/schema/sonic-device-neighbor.yang @@ -2,16 +2,8 @@ module sonic-device-neighbor { namespace "http://github.com/Azure/sonic-device-neighbor"; prefix sdn; - import ietf-yang-types { - prefix yang; - } - import ietf-inet-types { - prefix inet; - } - - import sonic-common { - prefix scommon; + prefix inet; } import sonic-port { @@ -34,42 +26,46 @@ module sonic-device-neighbor { } container sonic-device-neighbor { - list DEVICE_NEIGHBOR { - key "name"; - - leaf name{ - type string; - } - - leaf mgmt_addr{ - type inet:ip-address; - } - - leaf hwsku { - type string; - } - - leaf lo_addr { - type inet:ip-address; - } - - leaf local_port { - type leafref { - path "/prt:sonic-port/prt:PORT/prt:ifname"; - } - } - - leaf type { - type enumeration { - enum ToRRouter; - enum LeafRouter; - } - } - leaf port { - type leafref { - path "/prt:sonic-port/prt:PORT/prt:ifname"; - } + container DEVICE_NEIGHBOR { + + list DEVICE_NEIGHBOR_LIST { + key "name"; + + leaf name{ + type string; + } + + leaf mgmt_addr{ + type inet:ip-address; + } + + leaf hwsku { + type string; + } + + leaf lo_addr { + type inet:ip-address; + } + + leaf local_port { + type leafref { + path "/prt:sonic-port/prt:PORT/prt:PORT_LIST/prt:ifname"; + } + } + + leaf type { + type enumeration { + enum ToRRouter; + enum LeafRouter; + } + } + + leaf port { + type leafref { + path "/prt:sonic-port/prt:PORT/prt:PORT_LIST/prt:ifname"; + } + } } } } diff --git a/src/cvl/testdata/schema/sonic-dscp-tc-map.yang b/src/cvl/testdata/schema/sonic-dscp-tc-map.yang index 481cfbece0..9ec41b4f15 100644 --- a/src/cvl/testdata/schema/sonic-dscp-tc-map.yang +++ b/src/cvl/testdata/schema/sonic-dscp-tc-map.yang @@ -2,12 +2,8 @@ module sonic-dscp-tc-map { namespace "http://github.com/Azure/sonic-dscp-tc-map"; prefix dtm; - import ietf-yang-types { - prefix yang; - } - - import sonic-common { - prefix scommon; + import sonic-extension { + prefix sonic-ext; } import sonic-port { @@ -29,34 +25,38 @@ module sonic-dscp-tc-map { } container sonic-dscp-tc-map { - list DSCP_TO_TC_MAP { - key "name"; - scommon:map-list true; //special conversion for map tables - scommon:map-leaf "dscp tc_num"; //every key:value pair is mapped to list keys, e.g. "1":"7" ==> tc_num=1, dscp=7 - leaf name { - type string; - } + container DSCP_TO_TC_MAP { + + list DSCP_TO_TC_MAP_LIST { + key "name"; + sonic-ext:map-list true; //special conversion for map tables + sonic-ext:map-leaf "dscp tc_num"; //every key:value pair is mapped to list keys, e.g. "1":"7" ==> tc_num=1, dscp=7 + + leaf name { + type string; + } - list DSCP_TO_TC_MAP { //this is list inside list for storing mapping between two fields - key "dscp tc_num"; + list DSCP_TO_TC_MAP { //this is list inside list for storing mapping between two fields + key "dscp tc_num"; - leaf tc_num { - type string { - pattern "[0-9]?"{ - error-message "Invalid Traffic Class number"; - error-app-tag tc-num-invalid; + leaf tc_num { + type string { + pattern "[0-9]?"{ + error-message "Invalid Traffic Class number"; + error-app-tag tc-num-invalid; + } } } - } - leaf dscp { - type string { - pattern "[1-9][0-9]?|[0-9]?"; + leaf dscp { + type string { + pattern "[1-9][0-9]?|[0-9]?"; + } } } - } + } } } } diff --git a/src/cvl/testdata/schema/sonic-pf-limits.yang b/src/cvl/testdata/schema/sonic-pf-limits.yang index 6b92e97dba..658a6e9a8d 100644 --- a/src/cvl/testdata/schema/sonic-pf-limits.yang +++ b/src/cvl/testdata/schema/sonic-pf-limits.yang @@ -3,16 +3,8 @@ module sonic-pf-limits { prefix spf; yang-version 1.1; - import ietf-yang-types { - prefix yang; - } - - import ietf-inet-types { - prefix inet; - } - - import sonic-common { - prefix scommon; + import sonic-extension { + prefix sonic-ext; } organization @@ -30,7 +22,7 @@ module sonic-pf-limits { } container sonic-pf-limits { - scommon:db-name "APPL_DB"; + sonic-ext:db-name "APPL_DB"; container acl { leaf MAX_ACL_RULES { diff --git a/src/cvl/testdata/schema/sonic-pfc-priority-queue-map.yang b/src/cvl/testdata/schema/sonic-pfc-priority-queue-map.yang index b5c8952e6b..ad51874d69 100644 --- a/src/cvl/testdata/schema/sonic-pfc-priority-queue-map.yang +++ b/src/cvl/testdata/schema/sonic-pfc-priority-queue-map.yang @@ -2,12 +2,8 @@ module sonic-pfc-priority-queue-map { namespace "http://github.com/Azure/sonic-pfc-priority-queue-map"; prefix ppq; - import ietf-yang-types { - prefix yang; - } - - import sonic-common { - prefix scommon; + import sonic-extension { + prefix sonic-ext; } organization @@ -25,31 +21,35 @@ module sonic-pfc-priority-queue-map { } container sonic-pfc-priority-queue-map { - list MAP_PFC_PRIORITY_TO_QUEUE { - key "name"; - scommon:map-list true; //special conversion for map tables - scommon:map-leaf "pfc_priority qindex"; //every key:value pair is mapped to list keys, e.g. "1":"7" ==> tc_num=1, dscp=7 - leaf name { - type string; - } + container MAP_PFC_PRIORITY_TO_QUEUE { - list MAP_PFC_PRIORITY_TO_QUEUE { //this is list inside list for storing mapping between two fields - key "pfc_priority qindex"; + list MAP_PFC_PRIORITY_TO_QUEUE_LIST { + key "name"; + sonic-ext:map-list true; //special conversion for map tables + sonic-ext:map-leaf "pfc_priority qindex"; //every key:value pair is mapped to list keys, e.g. "1":"7" ==> tc_num=1, dscp=7 - leaf pfc_priority { - type string { - pattern "[0-9]?"; - } + leaf name { + type string; } - leaf qindex { - type string { - pattern "[0-9]?"; + list MAP_PFC_PRIORITY_TO_QUEUE { //this is list inside list for storing mapping between two fields + key "pfc_priority qindex"; + + leaf pfc_priority { + type string { + pattern "[0-9]?"; + } + } + + leaf qindex { + type string { + pattern "[0-9]?"; + } } } - } + } } } } diff --git a/src/cvl/testdata/schema/sonic-port-qos-map.yang b/src/cvl/testdata/schema/sonic-port-qos-map.yang index eeb5ca0bbc..f9785cb46a 100644 --- a/src/cvl/testdata/schema/sonic-port-qos-map.yang +++ b/src/cvl/testdata/schema/sonic-port-qos-map.yang @@ -2,12 +2,8 @@ module sonic-port-qos-map { namespace "http://github.com/Azure/sonic-port-qos-map"; prefix pqm; - import ietf-yang-types { - prefix yang; - } - - import sonic-common { - prefix scommon; + import sonic-extension { + prefix sonic-ext; } import sonic-port { @@ -48,24 +44,24 @@ module sonic-port-qos-map { list PORT_QOS_MAP { key "ifname"; - scommon:key-pattern "PORT_QOS_MAP|({ifname},)*"; //special pattern used for extracting keys from redis-key and fill populate the yang instance + sonic-ext:key-pattern "PORT_QOS_MAP|({ifname},)*"; //special pattern used for extracting keys from redis-key and fill populate the yang instance // Total list instance = number(key1) * number(key2) * number(key3) leaf ifname { type leafref { - path "/prt:sonic-port/prt:PORT/prt:ifname"; + path "/prt:sonic-port/prt:PORT/prt:PORT_LIST/prt:ifname"; } } leaf tc_to_pg_map { type leafref { - path "/tpg:sonic-tc-priority-group-map/tpg:TC_TO_PRIORITY_GROUP_MAP/tpg:name"; + path "/tpg:sonic-tc-priority-group-map/tpg:TC_TO_PRIORITY_GROUP_MAP/tpg:TC_TO_PRIORITY_GROUP_MAP_LIST/tpg:name"; } } leaf tc_to_queue_map { type leafref { - path "/tqm:sonic-tc-queue-map/tqm:TC_TO_QUEUE_MAP/tqm:name"; + path "/tqm:sonic-tc-queue-map/tqm:TC_TO_QUEUE_MAP/tqm:TC_TO_QUEUE_MAP_LIST/tqm:name"; } } @@ -77,13 +73,13 @@ module sonic-port-qos-map { leaf pfc_to_queue_map { type leafref { - path "/ppq:sonic-pfc-priority-queue-map/ppq:MAP_PFC_PRIORITY_TO_QUEUE/ppq:name"; + path "/ppq:sonic-pfc-priority-queue-map/ppq:MAP_PFC_PRIORITY_TO_QUEUE/ppq:MAP_PFC_PRIORITY_TO_QUEUE_LIST/ppq:name"; } } leaf dscp_to_tc_map { type leafref { - path "/dtm:sonic-dscp-tc-map/dtm:DSCP_TO_TC_MAP/dtm:name"; + path "/dtm:sonic-dscp-tc-map/dtm:DSCP_TO_TC_MAP/dtm:DSCP_TO_TC_MAP_LIST/dtm:name"; } } } diff --git a/src/cvl/testdata/schema/sonic-portchannel-interface.yang b/src/cvl/testdata/schema/sonic-portchannel-interface.yang index 305fd6ae76..45d92787d2 100644 --- a/src/cvl/testdata/schema/sonic-portchannel-interface.yang +++ b/src/cvl/testdata/schema/sonic-portchannel-interface.yang @@ -2,16 +2,8 @@ module sonic-portchannel-interface { namespace "http://github.com/Azure/sonic-portchannel-interface"; prefix spchint; - import ietf-yang-types { - prefix yang; - } - import ietf-inet-types { - prefix inet; - } - - import sonic-common { - prefix scommon; + prefix inet; } import sonic-portchannel { @@ -33,19 +25,23 @@ module sonic-portchannel-interface { } container sonic-portchannel-interface { - list PORTCHANNEL_INTERFACE { - key "pch_name ip_prefix"; - leaf pch_name{ - type leafref { - path "/spc:sonic-portchannel/spc:PORTCHANNEL/spc:name"; - } - } + container PORTCHANNEL_INTERFACE { + + list PORTCHANNEL_INTERFACE_LIST { + key "pch_name ip_prefix"; + + leaf pch_name{ + type leafref { + path "/spc:sonic-portchannel/spc:PORTCHANNEL/spc:PORTCHANNEL_LIST/spc:name"; + } + } - leaf ip_prefix { - mandatory true; - type inet:ip-prefix; + leaf ip_prefix { + mandatory true; + type inet:ip-prefix; + } } } } diff --git a/src/cvl/testdata/schema/sonic-portchannel.yang b/src/cvl/testdata/schema/sonic-portchannel.yang index 4ecd3a33d6..afe308f4e5 100644 --- a/src/cvl/testdata/schema/sonic-portchannel.yang +++ b/src/cvl/testdata/schema/sonic-portchannel.yang @@ -2,10 +2,6 @@ module sonic-portchannel { namespace "http://github.com/Azure/sonic-portchannel"; prefix spc; - import ietf-yang-types { - prefix yang; - } - import sonic-common { prefix scommon; } @@ -30,48 +26,52 @@ module sonic-portchannel { container sonic-portchannel { - list PORTCHANNEL { - key "name"; + container PORTCHANNEL { - max-elements 3; + list PORTCHANNEL_LIST { + key "name"; - leaf name { - type string; - } + max-elements 3; - leaf admin_status { - type scommon:admin-status; - } + leaf name { + type string; + } - leaf mtu { - type uint16; - } + leaf admin_status { + type scommon:admin-status; + } - leaf min_links { - type uint8; - } + leaf mtu { + type uint16; + } + + leaf min_links { + type uint8; + } - leaf fallback { - type boolean; + leaf fallback { + type boolean; + } } } - list PORTCHANNEL_MEMBER { - key "name ifname"; - scommon:key-delim "|"; - scommon:key-pattern "PORTCHANNEL|{name}|{ifname}"; + container PORTCHANNEL_MEMBER { - leaf name { - type leafref { - path "../../PORTCHANNEL/name"; + list PORTCHANNEL_MEMBER_LIST { + key "name ifname"; + + leaf name { + type leafref { + path "../../../PORTCHANNEL/PORTCHANNEL_LIST/name"; + } } - } - leaf ifname { - type leafref { - path "/prt:sonic-port/prt:PORT/prt:ifname"; + leaf ifname { + type leafref { + path "/prt:sonic-port/prt:PORT/prt:PORT_LIST/prt:ifname"; + } } } } - } + } } diff --git a/src/cvl/testdata/schema/sonic-queue.yang b/src/cvl/testdata/schema/sonic-queue.yang index fb55793443..92a7f4c96f 100644 --- a/src/cvl/testdata/schema/sonic-queue.yang +++ b/src/cvl/testdata/schema/sonic-queue.yang @@ -2,12 +2,8 @@ module sonic-queue { namespace "http://github.com/Azure/sonic-queue"; prefix squeue; - import ietf-yang-types { - prefix yang; - } - - import sonic-common { - prefix scommon; + import sonic-extension { + prefix sonic-ext; } import sonic-port { @@ -38,35 +34,39 @@ module sonic-queue { container sonic-queue { - list QUEUE { - key "ifname qindex"; - scommon:key-pattern "QUEUE|({ifname},)*|{qindex}"; //special pattern used for extracting keys from redis-key and populate the yang instance - // Total list instances = number(key1) * number(key2) * number(key3) - - leaf ifname { - type leafref { - path "/prt:sonic-port/prt:PORT/prt:ifname"; + + container QUEUE { + + list QUEUE_LIST { + key "ifname qindex"; + sonic-ext:key-pattern "QUEUE|({ifname},)*|{qindex}"; //special pattern used for extracting keys from redis-key and populate the yang instance + // Total list instances = number(key1) * number(key2) * number(key3) + + leaf ifname { + type leafref { + path "/prt:sonic-port/prt:PORT/prt:PORT_LIST/prt:ifname"; + } } - } - leaf qindex { - type string { - pattern "[0-8]((-)[0-8])?"{ - error-message "Invalid Q-index"; - error-app-tag qindex-invalid; + leaf qindex { + type string { + pattern "[0-8]((-)[0-8])?"{ + error-message "Invalid Q-index"; + error-app-tag qindex-invalid; + } } } - } - leaf scheduler { - type leafref { - path "/sch:sonic-scheduler/sch:SCHEDULER/sch:name"; + leaf scheduler { + type leafref { + path "/sch:sonic-scheduler/sch:SCHEDULER/sch:SCHEDULER_LIST/sch:name"; + } } - } - leaf wred_profile { - type leafref { - path "/wrd:sonic-wred-profile/wrd:WRED_PROFILE/wrd:name"; + leaf wred_profile { + type leafref { + path "/wrd:sonic-wred-profile/wrd:WRED_PROFILE/wrd:WRED_PROFILE_LIST/wrd:name"; + } } } } diff --git a/src/cvl/testdata/schema/sonic-scheduler.yang b/src/cvl/testdata/schema/sonic-scheduler.yang index d1e26ab359..2fc7997f71 100644 --- a/src/cvl/testdata/schema/sonic-scheduler.yang +++ b/src/cvl/testdata/schema/sonic-scheduler.yang @@ -2,14 +2,6 @@ module sonic-scheduler { namespace "http://github.com/Azure/sonic-scheduler"; prefix sch; - import ietf-yang-types { - prefix yang; - } - - import sonic-common { - prefix scommon; - } - organization "SONiC"; @@ -25,30 +17,34 @@ module sonic-scheduler { } container sonic-scheduler { - list SCHEDULER { - key "name"; - leaf name{ - type string; - } + container SCHEDULER { - leaf type { - type enumeration { - enum DWRR; - enum WRR; - enum PRIORITY; + list SCHEDULER_LIST { + key "name"; + + leaf name{ + type string; } - } - leaf weight { - type uint8 { - range "0..255"; + leaf type { + type enumeration { + enum DWRR; + enum WRR; + enum PRIORITY; + } + } + + leaf weight { + type uint8 { + range "0..255"; + } } - } - leaf priority { - type uint8 { - range "0..9"; + leaf priority { + type uint8 { + range "0..9"; + } } } } diff --git a/src/cvl/testdata/schema/sonic-tc-priority-group-map.yang b/src/cvl/testdata/schema/sonic-tc-priority-group-map.yang index 253ed0f47b..ed89a281ec 100644 --- a/src/cvl/testdata/schema/sonic-tc-priority-group-map.yang +++ b/src/cvl/testdata/schema/sonic-tc-priority-group-map.yang @@ -2,12 +2,8 @@ module sonic-tc-priority-group-map { namespace "http://github.com/Azure/sonic-tc-priority-group-map"; prefix tpg; - import ietf-yang-types { - prefix yang; - } - - import sonic-common { - prefix scommon; + import sonic-extension { + prefix sonic-ext; } organization @@ -25,31 +21,34 @@ module sonic-tc-priority-group-map { } container sonic-tc-priority-group-map { - list TC_TO_PRIORITY_GROUP_MAP { - key "name"; - scommon:map-list "true"; //special conversion for map tables - scommon:map-leaf "tc_num pg_num"; //every key:value pair is mapped to list keys, e.g. "1":"7" ==> tc_num=1, dscp=7 - leaf name { - type string; - } + container TC_TO_PRIORITY_GROUP_MAP { - list TC_TO_PRIORITY_GROUP_MAP { //this is list inside list for storing mapping between two fields - key "tc_num pg_num"; + list TC_TO_PRIORITY_GROUP_MAP_LIST { + key "name"; + sonic-ext:map-list "true"; //special conversion for map tables + sonic-ext:map-leaf "tc_num pg_num"; //every key:value pair is mapped to list keys, e.g. "1":"7" ==> tc_num=1, dscp=7 - leaf tc_num { - type string { - pattern "[0-9]?"; - } + leaf name { + type string; } - leaf pg_num { - type string { - pattern "[0-7]?"; + list TC_TO_PRIORITY_GROUP_MAP { //this is list inside list for storing mapping between two fields + key "tc_num pg_num"; + + leaf tc_num { + type string { + pattern "[0-9]?"; + } + } + + leaf pg_num { + type string { + pattern "[0-7]?"; + } } } } - } } } diff --git a/src/cvl/testdata/schema/sonic-tc-queue-map.yang b/src/cvl/testdata/schema/sonic-tc-queue-map.yang index 385b9edfac..37ab1c8113 100644 --- a/src/cvl/testdata/schema/sonic-tc-queue-map.yang +++ b/src/cvl/testdata/schema/sonic-tc-queue-map.yang @@ -2,12 +2,8 @@ module sonic-tc-queue-map { namespace "http://github.com/Azure/sonic-tc-queue-map"; prefix tqm; - import ietf-yang-types { - prefix yang; - } - - import sonic-common { - prefix scommon; + import sonic-extension { + prefix sonic-ext; } organization @@ -25,31 +21,35 @@ module sonic-tc-queue-map { } container sonic-tc-queue-map { - list TC_TO_QUEUE_MAP { - key "name"; - scommon:map-list "true"; //special conversion for map tables - scommon:map-leaf "tc_num qindex"; //every key:value pair is mapped to list keys, e.g. "1":"7" ==> tc_num=1, qindex=7 - leaf name { - type string; - } + container TC_TO_QUEUE_MAP { - list TC_TO_QUEUE_MAP { //this is list inside list for storing mapping between two fields - key "tc_num qindex"; + list TC_TO_QUEUE_MAP_LIST { + key "name"; + sonic-ext:map-list "true"; //special conversion for map tables + sonic-ext:map-leaf "tc_num qindex"; //every key:value pair is mapped to list keys, e.g. "1":"7" ==> tc_num=1, qindex=7 - leaf tc_num { - type string { - pattern "[0-9]?"; - } + leaf name { + type string; } - leaf qindex { - type string { - pattern "[0-9]?"; + list TC_TO_QUEUE_MAP { //this is list inside list for storing mapping between two fields + key "tc_num qindex"; + + leaf tc_num { + type string { + pattern "[0-9]?"; + } + } + + leaf qindex { + type string { + pattern "[0-9]?"; + } } } - } + } } } } diff --git a/src/cvl/testdata/schema/sonic-vlan-dev.yang b/src/cvl/testdata/schema/sonic-vlan-dev.yang index dcb6531126..7cc5784851 100644 --- a/src/cvl/testdata/schema/sonic-vlan-dev.yang +++ b/src/cvl/testdata/schema/sonic-vlan-dev.yang @@ -3,13 +3,11 @@ module sonic-vlan-dev { prefix svd; yang-version 1.1; - import ietf-yang-types { - prefix yang; - } - + /* import sonic-vlan { prefix svlan; } + */ organization "SONiC"; diff --git a/src/cvl/testdata/schema/sonic-vlan-interface.yang b/src/cvl/testdata/schema/sonic-vlan-interface.yang index 86b9f8c0f3..554feb1f58 100644 --- a/src/cvl/testdata/schema/sonic-vlan-interface.yang +++ b/src/cvl/testdata/schema/sonic-vlan-interface.yang @@ -2,16 +2,8 @@ module sonic-vlan-interface { namespace "http://github.com/Azure/sonic-vlan-interface"; prefix svint; - import ietf-yang-types { - prefix yang; - } - import ietf-inet-types { - prefix inet; - } - - import sonic-common { - prefix scommon; + prefix inet; } import sonic-vlan { @@ -33,19 +25,23 @@ module sonic-vlan-interface { } container sonic-vlan-interface { - list VLAN_INTERFACE { - key "portname ip_prefix"; - leaf portname{ - type leafref { - path "/svlan:sonic-vlan/svlan:VLAN/svlan:name"; - } - } + container VLAN_INTERFACE { + + list VLAN_INTERFACE_LIST { + key "portname ip_prefix"; + + leaf portname{ + type leafref { + path "/svlan:sonic-vlan/svlan:VLAN/svlan:VLAN_LIST/svlan:name"; + } + } - leaf ip_prefix { - mandatory true; - type inet:ip-prefix; + leaf ip_prefix { + mandatory true; + type inet:ip-prefix; + } } } } diff --git a/src/cvl/testdata/schema/sonic-vlan.yang b/src/cvl/testdata/schema/sonic-vlan.yang index 5a043b5f22..1170960df1 100644 --- a/src/cvl/testdata/schema/sonic-vlan.yang +++ b/src/cvl/testdata/schema/sonic-vlan.yang @@ -3,10 +3,6 @@ module sonic-vlan { prefix svlan; yang-version 1.1; - import ietf-yang-types { - prefix yang; - } - import sonic-common { prefix scommon; } @@ -36,72 +32,76 @@ module sonic-vlan { container sonic-vlan { - list VLAN { - key "name"; - must "./name = concat('Vlan', string(./vlanid))"{ - error-app-tag vlan-invalid; - } + container VLAN { - leaf name { - type string { - pattern "Vlan(409[0-5]|40[0-8][0-9]|[1-3][0-9]{3}|[1-9][0-9]{2}|[1-9][0-9]|[1-9])" { - error-message "Invalid Vlan name pattern"; - error-app-tag vlan-name-invalid; + list VLAN_LIST { + key "name"; + must "./name = concat('Vlan', string(./vlanid))"{ + error-app-tag vlan-invalid; + } + + leaf name { + type string { + pattern "Vlan(409[0-5]|40[0-8][0-9]|[1-3][0-9]{3}|[1-9][0-9]{2}|[1-9][0-9]|[1-9])" { + error-message "Invalid Vlan name pattern"; + error-app-tag vlan-name-invalid; + } } } - } - leaf vlanid { - mandatory true; - type uint16 { - range "1..4095" { - error-message "Vlan ID out of range"; - error-app-tag vlanid-invalid; + leaf vlanid { + mandatory true; + type uint16 { + range "1..4095" { + error-message "Vlan ID out of range"; + error-app-tag vlanid-invalid; + } } } - } - leaf-list members { - must "count(../members[text()=/spc:sonic-portchannel/" + - "spc:PORTCHANNEL_MEMBER[spc:ifname=current()]/spc:name]) = 0 and " + - "count(../members[text()=/spc:sonic-portchannel/" + - "spc:PORTCHANNEL_MEMBER[spc:name=current()]/spc:ifname]) = 0 " { - error-message "A vlan interface member cannot be part of portchannel which is already a vlan member"; - } + leaf-list members { + must "count(../members[text()=/spc:sonic-portchannel/spc:PORTCHANNEL_MEMBER/" + + "spc:PORTCHANNEL_MEMBER_LIST[spc:ifname=current()]/spc:name]) = 0 and " + + "count(../members[text()=/spc:sonic-portchannel/spc:PORTCHANNEL_MEMBER/" + + "spc:PORTCHANNEL_MEMBER_LIST[spc:name=current()]/spc:ifname]) = 0 " { + error-message "A vlan interface member cannot be part of portchannel which is already a vlan member"; + } - type union { - type leafref { - path "/prt:sonic-port/prt:PORT/prt:ifname"; - } - type leafref { - path "/spc:sonic-portchannel/spc:PORTCHANNEL/spc:name"; + type union { + type leafref { + path "/prt:sonic-port/prt:PORT/prt:PORT_LIST/prt:ifname"; + } + type leafref { + path "/spc:sonic-portchannel/spc:PORTCHANNEL/spc:PORTCHANNEL_LIST/spc:name"; + } } } } } - list VLAN_MEMBER { - key "name ifname"; + container VLAN_MEMBER { - leaf name { - type leafref { - path "../../VLAN/name"; + list VLAN_MEMBER_LIST { + key "name ifname"; + + leaf name { + type leafref { + path "../../../VLAN/VLAN_LIST/name"; + } } - } - leaf ifname { - type leafref { - path "/prt:sonic-port/prt:PORT/prt:ifname"; + leaf ifname { + type leafref { + path "/prt:sonic-port/prt:PORT/prt:PORT_LIST/prt:ifname"; + } } - } - leaf tagging_mode { - type scommon:tagging_mode; - default tagged; + leaf tagging_mode { + type scommon:tagging_mode; + default tagged; + } } } - } - } diff --git a/src/cvl/testdata/schema/sonic-wred-profile.yang b/src/cvl/testdata/schema/sonic-wred-profile.yang index 89b9c90ef5..e3c5abe363 100644 --- a/src/cvl/testdata/schema/sonic-wred-profile.yang +++ b/src/cvl/testdata/schema/sonic-wred-profile.yang @@ -2,14 +2,6 @@ module sonic-wred-profile { namespace "http://github.com/Azure/sonic-wred-profile"; prefix wrd; - import ietf-yang-types { - prefix yang; - } - - import sonic-common { - prefix scommon; - } - organization "SONiC"; @@ -25,59 +17,63 @@ module sonic-wred-profile { } container sonic-wred-profile { - list WRED_PROFILE { - key "name"; - leaf name{ - type string; - } + container WRED_PROFILE { - leaf yellow_min_threshold { - type uint64; - } + list WRED_PROFILE_LIST { + key "name"; - leaf green_min_threshold { - type uint64; - } + leaf name{ + type string; + } - leaf red_min_threshold { - type uint64; - } - leaf yellow_max_threshold { - type uint64; - } + leaf yellow_min_threshold { + type uint64; + } - leaf green_max_threshold { - type uint64; - } + leaf green_min_threshold { + type uint64; + } - leaf red_max_threshold { - type uint64; - } + leaf red_min_threshold { + type uint64; + } + leaf yellow_max_threshold { + type uint64; + } - leaf ecn { - type enumeration { - enum ecn_none; - enum ecn_green; - enum ecn_yellow; - enum ecn_red; - enum ecn_green_yellow; - enum ecn_green_red; - enum ecn_yellow_red; - enum ecn_all; + leaf green_max_threshold { + type uint64; } - } - leaf wred_green_enable { - type boolean; - } + leaf red_max_threshold { + type uint64; + } - leaf wred_yellow_enable { - type boolean; - } + leaf ecn { + type enumeration { + enum ecn_none; + enum ecn_green; + enum ecn_yellow; + enum ecn_red; + enum ecn_green_yellow; + enum ecn_green_red; + enum ecn_yellow_red; + enum ecn_all; + } + } + + leaf wred_green_enable { + type boolean; + } - leaf wred_red_enable { - type boolean; + leaf wred_yellow_enable { + type boolean; + } + + leaf wred_red_enable { + type boolean; + } } } } From 58da2b578f8f735eddf037b5b13c6cc04a928ec7 Mon Sep 17 00:00:00 2001 From: Partha Dutta Date: Sat, 21 Sep 2019 12:02:19 +0530 Subject: [PATCH 156/214] CVL changes for SONiC YANG --- src/cvl/schema/Makefile | 4 +- src/cvl/schema/sonic-interface.yang | 8 - src/cvl/schema/sonic-mirror-session.yang | 8 - tools/pyang/pyang_plugins/yin_cvl.py | 179 +++++++++++++++++++++++ 4 files changed, 180 insertions(+), 19 deletions(-) create mode 100644 tools/pyang/pyang_plugins/yin_cvl.py diff --git a/src/cvl/schema/Makefile b/src/cvl/schema/Makefile index 1408bb1f58..fe23d1ce71 100644 --- a/src/cvl/schema/Makefile +++ b/src/cvl/schema/Makefile @@ -10,9 +10,7 @@ schema: $(out) @echo "Generating $@ ..." @devFile="`echo $< | cut -d . -f1`-dev.yang"; \ if [ -f $$devFile ] ; then devOpt="--deviation-module $$devFile"; fi; \ - pyang -p ./ietf/ -f yin $$devOpt $< -o $@.tmp - @xmllint --noblanks $@.tmp > $@ - @rm -rf $@.tmp + pyang -p ./ietf/ --plugindir ../../../tools/pyang/pyang_plugins/ -f yin-cvl $$devOpt $< -o $@ %.tree:%.yang @echo "Generating $@ ..." diff --git a/src/cvl/schema/sonic-interface.yang b/src/cvl/schema/sonic-interface.yang index 79ca4832e8..f51a37f43a 100644 --- a/src/cvl/schema/sonic-interface.yang +++ b/src/cvl/schema/sonic-interface.yang @@ -2,18 +2,10 @@ module sonic-interface { namespace "http://github.com/Azure/sonic-interface"; prefix sint; - import ietf-yang-types { - prefix yang; - } - import ietf-inet-types { prefix inet; } - import sonic-common { - prefix scommon; - } - import sonic-port { prefix prt; } diff --git a/src/cvl/schema/sonic-mirror-session.yang b/src/cvl/schema/sonic-mirror-session.yang index 9805a121fa..ff18b5a14a 100644 --- a/src/cvl/schema/sonic-mirror-session.yang +++ b/src/cvl/schema/sonic-mirror-session.yang @@ -2,18 +2,10 @@ module sonic-mirror-session { namespace "http://github.com/Azure/sonic-mirror-session"; prefix sms; - import ietf-yang-types { - prefix yang; - } - import ietf-inet-types { prefix inet; } - import sonic-common { - prefix scommon; - } - organization "SONiC"; diff --git a/tools/pyang/pyang_plugins/yin_cvl.py b/tools/pyang/pyang_plugins/yin_cvl.py new file mode 100644 index 0000000000..7e03b3a0c0 --- /dev/null +++ b/tools/pyang/pyang_plugins/yin_cvl.py @@ -0,0 +1,179 @@ +################################################################################ +# # +# Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or # +# its subsidiaries. # +# # +# Licensed under the Apache License, Version 2.0 (the "License"); # +# you may not use this file except in compliance with the License. # +# You may obtain a copy of the License at # +# # +# http://www.apache.org/licenses/LICENSE-2.0 # +# # +# Unless required by applicable law or agreed to in writing, software # +# distributed under the License is distributed on an "AS IS" BASIS, # +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # +# See the License for the specific language governing permissions and # +# limitations under the License. # +# # +################################################################################ +"""CVL YIN output plugin""" + +from xml.sax.saxutils import quoteattr +from xml.sax.saxutils import escape + +import optparse +import re + +from pyang import plugin +from pyang import util +from pyang import grammar +from pyang import syntax +from pyang import statements + +new_line='' #replace with '\n' for adding new line +indent_space= '' #replace with ' ' for indentation +ns_indent_space= '' #replace with ' ' for indentation +yin_namespace = "urn:ietf:params:xml:ns:yang:yin:1" +revision_added = False + +def pyang_plugin_init(): + plugin.register_plugin(YINPluginCVL()) + +class YINPluginCVL(plugin.PyangPlugin): + def add_output_format(self, fmts): + fmts['yin-cvl'] = self + def emit(self, ctx, modules, fd): + module = modules[0] + emit_yin(ctx, module, fd) + +def emit_yin(ctx, module, fd): + fd.write('' + new_line) + fd.write(('<%s name="%s"' + new_line) % (module.keyword, module.arg)) + fd.write(ns_indent_space * len(module.keyword) + ns_indent_space + ' xmlns="%s"' % yin_namespace) + + prefix = module.search_one('prefix') + if prefix is not None: + namespace = module.search_one('namespace') + fd.write('' + new_line) + fd.write(ns_indent_space * len(module.keyword)) + fd.write(ns_indent_space + ' xmlns:' + prefix.arg + '=' + + quoteattr(namespace.arg)) + else: + belongs_to = module.search_one('belongs-to') + if belongs_to is not None: + prefix = belongs_to.search_one('prefix') + if prefix is not None: + # read the parent module in order to find the namespace uri + res = ctx.read_module(belongs_to.arg, extra={'no_include':True}) + if res is not None: + namespace = res.search_one('namespace') + if namespace is None or namespace.arg is None: + pass + else: + # success - namespace found + fd.write('' + new_line) + fd.write(sonic-acl.yin * len(module.keyword)) + fd.write(sonic-acl.yin + ' xmlns:' + prefix.arg + '=' + + quoteattr(namespace.arg)) + + for imp in module.search('import'): + prefix = imp.search_one('prefix') + if prefix is not None: + rev = None + r = imp.search_one('revision-date') + if r is not None: + rev = r.arg + mod = statements.modulename_to_module(module, imp.arg, rev) + if mod is not None: + ns = mod.search_one('namespace') + if ns is not None: + fd.write('' + new_line) + fd.write(ns_indent_space * len(module.keyword)) + fd.write(ns_indent_space + ' xmlns:' + prefix.arg + '=' + + quoteattr(ns.arg)) + fd.write('>' + new_line) + + substmts = module.substmts + for s in substmts: + emit_stmt(ctx, module, s, fd, indent_space, indent_space) + fd.write(('' + new_line) % module.keyword) + +def emit_stmt(ctx, module, stmt, fd, indent, indentstep): + global revision_added + + if stmt.raw_keyword == "revision" and revision_added == False: + revision_added = True + elif stmt.raw_keyword == "revision" and revision_added == True: + #Only add the latest revision + return + + #Don't keep the following keywords as they are not used in CVL + # stmt.raw_keyword == "revision" or + if ((stmt.raw_keyword == "organization" or + stmt.raw_keyword == "contact" or + stmt.raw_keyword == "rpc" or + stmt.raw_keyword == "notification" or + stmt.raw_keyword == "description") or + (len(stmt.substmts) > 0 and stmt.substmts[0].raw_keyword == "config" and + stmt.substmts[0].arg == "false")): + return + + if util.is_prefixed(stmt.raw_keyword): + # this is an extension. need to find its definition + (prefix, identifier) = stmt.raw_keyword + tag = prefix + ':' + identifier + if stmt.i_extension is not None: + ext_arg = stmt.i_extension.search_one('argument') + if ext_arg is not None: + yin_element = ext_arg.search_one('yin-element') + if yin_element is not None and yin_element.arg == 'true': + argname = prefix + ':' + ext_arg.arg + argiselem = True + else: + # explicit false or no yin-element given + argname = ext_arg.arg + argiselem = False + else: + argiselem = False + argname = None + else: + argiselem = False + argname = None + else: + (argname, argiselem) = syntax.yin_map[stmt.raw_keyword] + tag = stmt.raw_keyword + if argiselem == False or argname is None: + if argname is None: + attr = '' + else: + attr = ' ' + argname + '=' + quoteattr(stmt.arg) + if len(stmt.substmts) == 0: + fd.write(indent + '<' + tag + attr + '/>' + new_line) + else: + fd.write(indent + '<' + tag + attr + '>' + new_line) + for s in stmt.substmts: + emit_stmt(ctx, module, s, fd, indent + indentstep, + indentstep) + fd.write(indent + '' + new_line) + else: + fd.write(indent + '<' + tag + '>' + new_line) + fd.write(indent + indentstep + '<' + argname + '>' + \ + escape(stmt.arg) + \ + '' + new_line) + substmts = stmt.substmts + + for s in substmts: + emit_stmt(ctx, module, s, fd, indent + indentstep, indentstep) + + fd.write(indent + '' + new_line) + +def fmt_text(indent, data): + res = [] + for line in re.split("(\n)", escape(data)): + if line == '': + continue + if line == '' + new_line: + res.extend(line) + else: + res.extend(indent + line) + return ''.join(res) From 5363ce0a886eaa14a926fc9b7842e8e706ca42be Mon Sep 17 00:00:00 2001 From: amrutasali Date: Mon, 23 Sep 2019 18:50:33 +0000 Subject: [PATCH 157/214] Initial support for table transformer --- src/translib/transformer/xlate_from_db.go | 110 +++++++++++++++++++++- 1 file changed, 109 insertions(+), 1 deletion(-) diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index f763990231..a861c2fd06 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -78,6 +78,17 @@ func validateHandlerFunc(inParams XfmrParams) (bool) { return ret[0].Interface().(bool) } +func xfmrTblHandlerFunc(xfmrTblNm string, inParams XfmrParams) []string { + //xpath, _ := RemoveXPATHPredicates(inParams.uri) + ret, err := XlateFuncCall(xfmrTblNm, inParams) + if err != nil { + return []string{} + } + return ret[0].Interface().([]string) + +} + + func DbValToInt(dbFldVal string, base int, size int, isUint bool) (interface{}, error) { var res interface{} var err error @@ -224,7 +235,71 @@ func tableNameAndKeyFromDbMapGet(dbDataMap map[string]map[string]db.Value) (stri return tableName, tableKey, nil } +/*db num ??, key ??*/ +func fillDbDataMapForTbl(uri string, xpath string, tblName string, tblKey string, cdb db.DBNum, dbs [db.MaxDB]*db.DB, resDbDataMap *map[string]map[string]db.Value) error { + var err error + var dbresult = make(map[db.DBNum]map[string]map[string]db.Value) + dbresult[cdb] = make(map[string]map[string]db.Value) + dbFormat := KeySpec{} + dbFormat.Ts.Name = tblName + dbFormat.dbNum = cdb + /* TODO - handle key + dbFormat.Key.Comp = append(dbFormat.Key.Comp, tblKey) */ + err = TraverseDb(dbs, dbFormat, &dbresult, nil) + if err != nil { + log.Errorf("TraverseDb() failure for tbl(DB num) %v(%v) for xpath %v", tblName, cdb, xpath) + return err + } + if _, ok := dbresult[cdb]; !ok { + logStr := fmt.Sprintf("TraverseDb() did not populate Db data for tbl(DB num) %v(%v) for xpath %v", tblName, cdb, xpath) + err = fmt.Errorf("%v", logStr) + return err + } + for tblNm := range(dbresult[cdb]) { + for tblky := range(dbresult[cdb][tblNm]) { + for fld, val := range(dbresult[cdb][tblNm]) { + (*resDbDataMap)[tblNm][tblky].Field[fld] = val + } + } + } + return err + +} + func yangListDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath string, dbDataMap *map[db.DBNum]map[string]map[string]db.Value, resultMap map[string]interface{}, tbl string, tblKey string, cdb db.DBNum, validate bool) error { + + tblXfmr := false + var tblList []string + if tbl == "" && xSpecMap[xpath].xfmrTbl != nil { + lxfmrTblName := *xSpecMap[xpath].xfmrTbl + if len(lxfmrTblName) > 0 { + inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, chldUri, GET, "", dbDataMap, nil) + // call table transformer + tblList = xfmrTblHandlerFunc(inParams) + if len(tblList) == 0 { + log.Warningf("Table transformer did not return any table for xpath %v", xpath) + return nil + } + for _, tbl := range(tblList) { + var resDbDataMap = make(map[string]map[string]db.Value) + err := fillDbDataMapForTbl(uri, xpath, tbl, dbs, cdb, &resDbDataMap) + if err != nil { + log.Wraningf("Could not retrieve DB data for table %v for xpath %v", tbl, xpath) + continue + } + mapCopy((*dbDataMap), resDbDataMap) + } + tblXfmr = true + } else { + log.Warningf("Empty table transformer name for xpath %v", xpath) + return nil + } + } + if tbl != "" && !tblXfmr { + tblList[0] = tbl + } + + for _, tbl = range(tblList) { tblData, ok := (*dbDataMap)[cdb][tbl] if ok { @@ -258,6 +333,7 @@ func yangListDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, x log.Infof("Empty slice for (\"%v\").\r\n", uri) } } + }// end of tblList for return nil } @@ -356,6 +432,37 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath } else { log.Infof("Empty container(\"%v\").\r\n", chldUri) } + } else if xSpecMap[chldXpath].xfmrTbl != nil { + lxfmrTblName := *xSpecMap[chldXpath].tableName + if len(lxfmrTblName) > 0 { + inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, chldUri, GET, "", dbDataMap, nil) + tblList = xfmrTblHandlerFunc(inParams) // should be a list containing a single table ??? + if len(tblList) == 0 { + log.Warningf("Table transformer did not return any table for xpath %v", chldXpath) + continue + } + // TODO - add check of single tbale in list ??? + if len(tblList) > 1 { + log.Warningf("Table transformer returned returned more than one table for container %v", chldXpath) + continue + } + for _, tbl := range(tblList) { + var resDbDataMap = make(map[string]map[string]db.Value) + //err := fillDbDataMapForTbl(chldUri, chldXpath, tbl, parentTblKey, dbs, cdb, &resDbDataMap) + err := fillDbDataMapForTbl(chldUri, chldXpath, tbl, tblKey, cdb, &resDbDataMap) + if err != nil { + log.Wraningf("Could not retrieve DB data for table %v for xpath %v", tbl, xpath) + continue + } + mapCopy((*dbDataMap), resDbDataMap) + } + tblXfmr = true + + } else { + log.Warningf("Table transformer name is empty for xpath %v", chldXpath) + } + + } else { cmap := make(map[string]interface{}) err = yangDataFill(dbs, ygRoot, chldUri, chldXpath, dbDataMap, cmap, tbl, tblKey, cdb, isValid) @@ -377,10 +484,11 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath } } else { ynode, ok := xSpecMap[chldXpath] + lTblName := "" if ok && ynode.tableName != nil { lTblName := *ynode.tableName - yangListDataFill(dbs, ygRoot, chldUri, chldXpath, dbDataMap, resultMap, lTblName, "", cdb, isValid) } + yangListDataFill(dbs, ygRoot, chldUri, chldXpath, dbDataMap, resultMap, lTblName, "", cdb, isValid) } } else { return err From 4c5a210751d2b1d5105cc5bb3941221e41cbb9c5 Mon Sep 17 00:00:00 2001 From: amrutasali Date: Mon, 23 Sep 2019 23:32:36 +0000 Subject: [PATCH 158/214] Fix issues in initial commit for table transformer --- src/translib/transformer/xlate_from_db.go | 54 ++++++++++++----------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index a861c2fd06..4dc7c7fcfa 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -244,7 +244,9 @@ func fillDbDataMapForTbl(uri string, xpath string, tblName string, tblKey string dbFormat.Ts.Name = tblName dbFormat.dbNum = cdb /* TODO - handle key - dbFormat.Key.Comp = append(dbFormat.Key.Comp, tblKey) */ + if tblKey != "" { + dbFormat.Key.Comp = append(dbFormat.Key.Comp, tblKey) + } */ err = TraverseDb(dbs, dbFormat, &dbresult, nil) if err != nil { log.Errorf("TraverseDb() failure for tbl(DB num) %v(%v) for xpath %v", tblName, cdb, xpath) @@ -257,7 +259,7 @@ func fillDbDataMapForTbl(uri string, xpath string, tblName string, tblKey string } for tblNm := range(dbresult[cdb]) { for tblky := range(dbresult[cdb][tblNm]) { - for fld, val := range(dbresult[cdb][tblNm]) { + for fld, val := range(dbresult[cdb][tblNm][tblky].Field) { (*resDbDataMap)[tblNm][tblky].Field[fld] = val } } @@ -273,21 +275,21 @@ func yangListDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, x if tbl == "" && xSpecMap[xpath].xfmrTbl != nil { lxfmrTblName := *xSpecMap[xpath].xfmrTbl if len(lxfmrTblName) > 0 { - inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, chldUri, GET, "", dbDataMap, nil) + inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, uri, GET, "", dbDataMap, nil) // call table transformer - tblList = xfmrTblHandlerFunc(inParams) + tblList = xfmrTblHandlerFunc(lxfmrTblName, inParams) if len(tblList) == 0 { log.Warningf("Table transformer did not return any table for xpath %v", xpath) return nil } for _, tbl := range(tblList) { var resDbDataMap = make(map[string]map[string]db.Value) - err := fillDbDataMapForTbl(uri, xpath, tbl, dbs, cdb, &resDbDataMap) + err := fillDbDataMapForTbl(uri, xpath, tbl, "", cdb, dbs, &resDbDataMap) if err != nil { - log.Wraningf("Could not retrieve DB data for table %v for xpath %v", tbl, xpath) + log.Warningf("Could not retrieve DB data for table %v for xpath %v", tbl, xpath) continue } - mapCopy((*dbDataMap), resDbDataMap) + mapCopy((*dbDataMap)[cdb], resDbDataMap) } tblXfmr = true } else { @@ -436,42 +438,42 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath lxfmrTblName := *xSpecMap[chldXpath].tableName if len(lxfmrTblName) > 0 { inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, chldUri, GET, "", dbDataMap, nil) - tblList = xfmrTblHandlerFunc(inParams) // should be a list containing a single table ??? + tblList := xfmrTblHandlerFunc(lxfmrTblName, inParams) // should be a list containing a single table ??? if len(tblList) == 0 { log.Warningf("Table transformer did not return any table for xpath %v", chldXpath) continue } - // TODO - add check of single tbale in list ??? + // TODO - add check of single table in list ??? if len(tblList) > 1 { log.Warningf("Table transformer returned returned more than one table for container %v", chldXpath) continue } for _, tbl := range(tblList) { var resDbDataMap = make(map[string]map[string]db.Value) - //err := fillDbDataMapForTbl(chldUri, chldXpath, tbl, parentTblKey, dbs, cdb, &resDbDataMap) - err := fillDbDataMapForTbl(chldUri, chldXpath, tbl, tblKey, cdb, &resDbDataMap) + /*TODO - check if there is a key transformer, if yes then get the key and supply else use incoming tblKey(key of parent)*/ + //err := fillDbDataMapForTbl(chldUri, chldXpath, tbl, parentTblKey, cdb, dbs, &resDbDataMap) + err := fillDbDataMapForTbl(chldUri, chldXpath, tbl, tblKey, cdb, dbs, &resDbDataMap) if err != nil { - log.Wraningf("Could not retrieve DB data for table %v for xpath %v", tbl, xpath) + log.Warningf("Could not retrieve DB data for table %v for xpath %v", tbl, xpath) continue } - mapCopy((*dbDataMap), resDbDataMap) + mapCopy((*dbDataMap)[cdb], resDbDataMap) } - tblXfmr = true + //tblXfmr = true } else { log.Warningf("Table transformer name is empty for xpath %v", chldXpath) + continue } - - - } else { - cmap := make(map[string]interface{}) - err = yangDataFill(dbs, ygRoot, chldUri, chldXpath, dbDataMap, cmap, tbl, tblKey, cdb, isValid) - if len(cmap) > 0 { - resultMap[cname] = cmap - } else { - log.Infof("Empty container(\"%v\").\r\n", chldUri) - } - } + } //else { + cmap := make(map[string]interface{}) + err = yangDataFill(dbs, ygRoot, chldUri, chldXpath, dbDataMap, cmap, tbl, tblKey, cdb, isValid) + if len(cmap) > 0 { + resultMap[cname] = cmap + } else { + log.Infof("Empty container(\"%v\").\r\n", chldUri) + } + //} } else if chldYangType == "list" { cdb = xSpecMap[chldXpath].dbIndex if len(xSpecMap[chldXpath].xfmrFunc) > 0 { @@ -486,7 +488,7 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath ynode, ok := xSpecMap[chldXpath] lTblName := "" if ok && ynode.tableName != nil { - lTblName := *ynode.tableName + lTblName = *ynode.tableName } yangListDataFill(dbs, ygRoot, chldUri, chldXpath, dbDataMap, resultMap, lTblName, "", cdb, isValid) } From 5d8ded46e6d626477cff4643361708f02491ee36 Mon Sep 17 00:00:00 2001 From: Kwan Kim Date: Mon, 23 Sep 2019 16:54:37 -0700 Subject: [PATCH 159/214] copy the misisng lines from transformer-phase1 --- src/cvl/schema/Makefile | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/cvl/schema/Makefile b/src/cvl/schema/Makefile index b2c30c00ac..ef5d13a4e0 100644 --- a/src/cvl/schema/Makefile +++ b/src/cvl/schema/Makefile @@ -17,6 +17,18 @@ # # ################################################################################ +TOPDIR := ../../.. +CVL_YANGAPI_DIR := $(TOPDIR)/build/yaml +CVL_YANGDIR := $(TOPDIR)/src/cvl/schema +CVL_YANGDIR_COMMON := $(TOPDIR)/src/cvl/schema/ietf +CVL_YANG_MOD_FILES := $(shell find $(CVL_YANGDIR) -maxdepth 1 -name '*.yang' | sort) +CVL_YANG_COMMON_FILES := $(shell find $(CVL_YANGDIR_COMMON) -name '*.yang' | sort) + +CVL_TOOLS_DIR := $(TOPDIR)/tools +CVL_PYANG_DIR := $(CVL_TOOLS_DIR)/pyang +CVL_PYANG_PLUGIN_DIR := $(CVL_PYANG_DIR)/pyang_plugins +CVL_PYANG_BIN := pyang + src_files=$(wildcard *.yang) out=$(patsubst %.yang, %.yin, $(src_files)) out_ext=$(patsubst %.yang, %.tree, $(src_files)) From 78c96d96afe60ad86883a728bb24a6ee5573016d Mon Sep 17 00:00:00 2001 From: Kwan Kim Date: Mon, 23 Sep 2019 23:25:16 -0700 Subject: [PATCH 160/214] add missing lines from transforer-phase1 --- src/cvl/schema/Makefile | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/src/cvl/schema/Makefile b/src/cvl/schema/Makefile index ef5d13a4e0..f5f970c264 100644 --- a/src/cvl/schema/Makefile +++ b/src/cvl/schema/Makefile @@ -33,10 +33,12 @@ src_files=$(wildcard *.yang) out=$(patsubst %.yang, %.yin, $(src_files)) out_ext=$(patsubst %.yang, %.tree, $(src_files)) -all:schema +all: yamlGen allyangs.tree allyangs_tree.html schema schema: $(out) +#yamlGen: $(CVL_YANGAPI_DIR)/.done + %.yin:%.yang @echo "Generating $@ ..." @devFile="`echo $< | cut -d . -f1`-dev.yang"; \ @@ -45,6 +47,38 @@ schema: $(out) @xmllint --noblanks $@.tmp > $@ @rm -rf $@.tmp +allyangs.tree: $(CVL_YANG_MOD_FILES) $(CVL_YANG_COMMON_FILES) + $(CVL_PYANG_BIN) \ + -f tree \ + -o $(CVL_YANGDIR)/$@ \ + -p $(CVL_YANGDIR_COMMON):$(CVL_YANGDIR) \ + $(CVL_YANG_MOD_FILES) + @echo "+++++ Generation of YANG tree for Sonic Yang modules completed +++++" + +allyangs_tree.html: $(CVL_YANG_MOD_FILES) $(CVL_YANG_COMMON_FILES) + $(CVL_PYANG_BIN) \ + -f jstree \ + -o $(CVL_YANGDIR)/$@ \ + -p $(CVL_YANGDIR_COMMON):$(CVL_YANGDIR) \ + $(CVL_YANG_MOD_FILES) + @echo "+++++ Generation of HTML tree for Sonic Yang modules completed +++++" + +#====================================================================== +# Generate YAML files for Sonic Yang modules +#====================================================================== +yamlGen: + @echo "+++++ Generating YAML files for Sonic Yang modules +++++" + mkdir -p $(CVL_YANGAPI_DIR) + $(CVL_PYANG_BIN) \ + -f swaggerapi \ + --outdir $(CVL_YANGAPI_DIR) \ + --plugindir $(CVL_PYANG_PLUGIN_DIR) \ + -p $(CVL_YANGDIR_COMMON):$(CVL_YANGDIR) \ + $(CVL_YANG_MOD_FILES) + @echo "+++++ Generation of YAML files for Sonic Yang modules completed +++++" + # touch $@ + + %.tree:%.yang @echo "Generating $@ ..." @devFile="`echo $< | cut -d . -f1`-dev.yang"; \ @@ -55,3 +89,5 @@ clean: @echo "Removing files ..." rm -rf $(out) rm -rf $(out_ext) + rm -rf $(CVL_YANGAPI_DIR) + rm -rf allyangs.tree allyangs_tree.html From b7f5146c0f888d3703f82c1fc7797042ef34e720 Mon Sep 17 00:00:00 2001 From: s-mari Date: Tue, 24 Sep 2019 17:11:47 -0700 Subject: [PATCH 161/214] support for table transformer for crud and get operation --- src/translib/transformer/xlate_from_db.go | 660 ++++++++++------------ src/translib/transformer/xlate_to_db.go | 53 +- src/translib/transformer/xlate_utils.go | 113 ++-- src/translib/transformer/xspec.go | 349 ++++++------ 4 files changed, 586 insertions(+), 589 deletions(-) diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index 4dc7c7fcfa..7125c1caea 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -78,14 +78,12 @@ func validateHandlerFunc(inParams XfmrParams) (bool) { return ret[0].Interface().(bool) } -func xfmrTblHandlerFunc(xfmrTblNm string, inParams XfmrParams) []string { - //xpath, _ := RemoveXPATHPredicates(inParams.uri) - ret, err := XlateFuncCall(xfmrTblNm, inParams) +func xfmrTblHandlerFunc(xfmrTblFunc string, inParams XfmrParams) []string { + ret, err := XlateFuncCall(xfmrTblFunc, inParams) if err != nil { return []string{} } return ret[0].Interface().([]string) - } @@ -173,54 +171,54 @@ func processLfLstDbToYang(fieldXpath string, dbFldVal string) []interface{} { /* Traverse db map and create json for cvl yang */ func directDbToYangJsonCreate(dbDataMap map[string]map[string]db.Value, jsonData string, resultMap map[string]interface{}) error { var err error - for tblName, tblData := range dbDataMap { - var mapSlice []typeMapOfInterface - for keyStr, dbFldValData := range tblData { - curMap := make(map[string]interface{}) - for field, value := range dbFldValData.Field { - resField := field - if strings.HasSuffix(field, "@") { - fldVals := strings.Split(field, "@") - resField = fldVals[0] - } - fieldXpath := tblName + "/" + resField - xDbSpecMapEntry, ok := xDbSpecMap[fieldXpath] - if !ok { - log.Warningf("No entry found in xDbSpecMap for xpath %v", fieldXpath) - continue - } - if xDbSpecMapEntry.dbEntry == nil { - log.Warningf("Yang entry is nil in xDbSpecMap for xpath %v", fieldXpath) - continue - } - yangType := yangTypeGet(xDbSpecMapEntry.dbEntry) - if yangType == "leaf-list" { - /* this should never happen but just adding for safetty */ - if !strings.HasSuffix(field, "@") { - log.Warningf("Leaf-list in Sonic yang should also be a leaf-list in DB, its not for xpath %v", fieldXpath) - continue - } - resLst := processLfLstDbToYang(fieldXpath, value) - curMap[resField] = resLst - } else { /* yangType is leaf - there are only 2 types of yang terminal node leaf and leaf-list */ - yngTerminalNdDtType := xDbSpecMapEntry.dbEntry.Type.Kind - resVal, err := DbToYangType(yngTerminalNdDtType, fieldXpath, value) - if err != nil { - log.Warningf("Failure in converting Db value type to yang type for xpath", fieldXpath) - } else { - curMap[resField] = resVal - } - } - } //end of for - yangKeys := yangKeyFromEntryGet(xDbSpecMap[tblName].dbEntry) - sonicKeyDataAdd(yangKeys, keyStr, curMap) - if curMap != nil { - mapSlice = append(mapSlice, curMap) - } - } - resultMap[tblName] = mapSlice - } - return err + for tblName, tblData := range dbDataMap { + var mapSlice []typeMapOfInterface + for keyStr, dbFldValData := range tblData { + curMap := make(map[string]interface{}) + for field, value := range dbFldValData.Field { + resField := field + if strings.HasSuffix(field, "@") { + fldVals := strings.Split(field, "@") + resField = fldVals[0] + } + fieldXpath := tblName + "/" + resField + xDbSpecMapEntry, ok := xDbSpecMap[fieldXpath] + if !ok { + log.Warningf("No entry found in xDbSpecMap for xpath %v", fieldXpath) + continue + } + if xDbSpecMapEntry.dbEntry == nil { + log.Warningf("Yang entry is nil in xDbSpecMap for xpath %v", fieldXpath) + continue + } + yangType := yangTypeGet(xDbSpecMapEntry.dbEntry) + if yangType == "leaf-list" { + /* this should never happen but just adding for safetty */ + if !strings.HasSuffix(field, "@") { + log.Warningf("Leaf-list in Sonic yang should also be a leaf-list in DB, its not for xpath %v", fieldXpath) + continue + } + resLst := processLfLstDbToYang(fieldXpath, value) + curMap[resField] = resLst + } else { /* yangType is leaf - there are only 2 types of yang terminal node leaf and leaf-list */ + yngTerminalNdDtType := xDbSpecMapEntry.dbEntry.Type.Kind + resVal, err := DbToYangType(yngTerminalNdDtType, fieldXpath, value) + if err != nil { + log.Warningf("Failure in converting Db value type to yang type for xpath", fieldXpath) + } else { + curMap[resField] = resVal + } + } + } //end of for + yangKeys := yangKeyFromEntryGet(xDbSpecMap[tblName].dbEntry) + sonicKeyDataAdd(yangKeys, keyStr, curMap) + if curMap != nil { + mapSlice = append(mapSlice, curMap) + } + } + resultMap[tblName] = mapSlice + } + return err } func tableNameAndKeyFromDbMapGet(dbDataMap map[string]map[string]db.Value) (string, string, error) { @@ -235,338 +233,302 @@ func tableNameAndKeyFromDbMapGet(dbDataMap map[string]map[string]db.Value) (stri return tableName, tableKey, nil } -/*db num ??, key ??*/ -func fillDbDataMapForTbl(uri string, xpath string, tblName string, tblKey string, cdb db.DBNum, dbs [db.MaxDB]*db.DB, resDbDataMap *map[string]map[string]db.Value) error { - var err error - var dbresult = make(map[db.DBNum]map[string]map[string]db.Value) - dbresult[cdb] = make(map[string]map[string]db.Value) - dbFormat := KeySpec{} - dbFormat.Ts.Name = tblName - dbFormat.dbNum = cdb - /* TODO - handle key - if tblKey != "" { - dbFormat.Key.Comp = append(dbFormat.Key.Comp, tblKey) - } */ - err = TraverseDb(dbs, dbFormat, &dbresult, nil) - if err != nil { - log.Errorf("TraverseDb() failure for tbl(DB num) %v(%v) for xpath %v", tblName, cdb, xpath) - return err - } - if _, ok := dbresult[cdb]; !ok { - logStr := fmt.Sprintf("TraverseDb() did not populate Db data for tbl(DB num) %v(%v) for xpath %v", tblName, cdb, xpath) - err = fmt.Errorf("%v", logStr) - return err - } - for tblNm := range(dbresult[cdb]) { - for tblky := range(dbresult[cdb][tblNm]) { - for fld, val := range(dbresult[cdb][tblNm][tblky].Field) { - (*resDbDataMap)[tblNm][tblky].Field[fld] = val - } +func fillDbDataMapForTbl(uri string, xpath string, tblName string, tblKey string, cdb db.DBNum, dbs [db.MaxDB]*db.DB) (map[db.DBNum]map[string]map[string]db.Value, error) { + var err error + dbresult := make(map[db.DBNum]map[string]map[string]db.Value) + dbresult[cdb] = make(map[string]map[string]db.Value) + dbFormat := KeySpec{} + dbFormat.Ts.Name = tblName + dbFormat.dbNum = cdb + /* TODO - handle key + if tblKey != "" { + dbFormat.Key.Comp = append(dbFormat.Key.Comp, tblKey) + } */ + err = TraverseDb(dbs, dbFormat, &dbresult, nil) + if err != nil { + log.Errorf("TraverseDb() failure for tbl(DB num) %v(%v) for xpath %v", tblName, cdb, xpath) + return nil, err } - } - return err + if _, ok := dbresult[cdb]; !ok { + logStr := fmt.Sprintf("TraverseDb() did not populate Db data for tbl(DB num) %v(%v) for xpath %v", tblName, cdb, xpath) + err = fmt.Errorf("%v", logStr) + return nil, err + } + return dbresult, err } -func yangListDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath string, dbDataMap *map[db.DBNum]map[string]map[string]db.Value, resultMap map[string]interface{}, tbl string, tblKey string, cdb db.DBNum, validate bool) error { +// Assumption: All tables are from the same DB +func dbDataFromTblXfmrGet(tbl string, inParams XfmrParams, dbDataMap *map[db.DBNum]map[string]map[string]db.Value) error { + xpath, _ := RemoveXPATHPredicates(inParams.uri) + curDbDataMap, err := fillDbDataMapForTbl(inParams.uri, xpath, tbl, "", inParams.curDb, inParams.dbs) + if err == nil { + mapCopy((*dbDataMap)[inParams.curDb], curDbDataMap[inParams.curDb]) + } + return nil +} - tblXfmr := false - var tblList []string - if tbl == "" && xSpecMap[xpath].xfmrTbl != nil { - lxfmrTblName := *xSpecMap[xpath].xfmrTbl - if len(lxfmrTblName) > 0 { - inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, uri, GET, "", dbDataMap, nil) - // call table transformer - tblList = xfmrTblHandlerFunc(lxfmrTblName, inParams) - if len(tblList) == 0 { - log.Warningf("Table transformer did not return any table for xpath %v", xpath) - return nil - } - for _, tbl := range(tblList) { - var resDbDataMap = make(map[string]map[string]db.Value) - err := fillDbDataMapForTbl(uri, xpath, tbl, "", cdb, dbs, &resDbDataMap) - if err != nil { - log.Warningf("Could not retrieve DB data for table %v for xpath %v", tbl, xpath) - continue +func yangListDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath string, dbDataMap *map[db.DBNum]map[string]map[string]db.Value, resultMap map[string]interface{}, tbl string, tblKey string, cdb db.DBNum, validate bool) error { + var tblList []string + tblXfmr := false + + if tbl == "" && xSpecMap[xpath].xfmrTbl != nil { + xfmrTblFunc := *xSpecMap[xpath].xfmrTbl + if len(xfmrTblFunc) > 0 { + tblXfmr = true + inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, uri, GET, "", dbDataMap, nil) + tblList = xfmrTblHandlerFunc(xfmrTblFunc, inParams) + if len(tblList) != 0 { + for _, curTbl := range tblList { + dbDataFromTblXfmrGet(curTbl, inParams, dbDataMap) + } + } } - mapCopy((*dbDataMap)[cdb], resDbDataMap) - } - tblXfmr = true - } else { - log.Warningf("Empty table transformer name for xpath %v", xpath) - return nil + } else if tbl != "" && !tblXfmr { + tblList = append(tblList, tbl) } - } - if tbl != "" && !tblXfmr { - tblList[0] = tbl - } - for _, tbl = range(tblList) { - tblData, ok := (*dbDataMap)[cdb][tbl] - - if ok { - var mapSlice []typeMapOfInterface - for dbKey, _ := range tblData { - curMap := make(map[string]interface{}) - curKeyMap, curUri, _ := dbKeyToYangDataConvert(uri, xpath, dbKey) - if len(xSpecMap[xpath].xfmrFunc) > 0 { - inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, curUri, GET, "", dbDataMap, nil) - cmap, _ := xfmrHandlerFunc(inParams) - if len(cmap) > 0 { - mapSlice = append(mapSlice, curMap) - } else { - log.Infof("Empty container returned from overloaded transformer for(\"%v\")", curUri) - } - } else { - _, keyFromCurUri, _ := xpathKeyExtract(dbs[cdb], ygRoot, GET, curUri) - if dbKey == keyFromCurUri { - for k, kv := range curKeyMap { - curMap[k] = kv - } - curXpath, _ := RemoveXPATHPredicates(curUri) - yangDataFill(dbs, ygRoot, curUri, curXpath, dbDataMap, curMap, tbl, dbKey, cdb, validate) - mapSlice = append(mapSlice, curMap) - } - } - } - if len(mapSlice) > 0 { - resultMap[xSpecMap[xpath].yangEntry.Name] = mapSlice - } else { - log.Infof("Empty slice for (\"%v\").\r\n", uri) - } - } - }// end of tblList for - return nil + for _, tbl = range(tblList) { + tblData, ok := (*dbDataMap)[cdb][tbl] + + if ok { + var mapSlice []typeMapOfInterface + for dbKey, _ := range tblData { + curMap := make(map[string]interface{}) + curKeyMap, curUri, _ := dbKeyToYangDataConvert(uri, xpath, dbKey) + if len(xSpecMap[xpath].xfmrFunc) > 0 { + inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, curUri, GET, "", dbDataMap, nil) + cmap, _ := xfmrHandlerFunc(inParams) + if len(cmap) > 0 { + mapSlice = append(mapSlice, curMap) + } else { + log.Infof("Empty container returned from overloaded transformer for(\"%v\")", curUri) + } + } else { + _, keyFromCurUri, _ := xpathKeyExtract(dbs[cdb], ygRoot, GET, curUri) + if dbKey == keyFromCurUri { + for k, kv := range curKeyMap { + curMap[k] = kv + } + curXpath, _ := RemoveXPATHPredicates(curUri) + yangDataFill(dbs, ygRoot, curUri, curXpath, dbDataMap, curMap, tbl, dbKey, cdb, validate) + mapSlice = append(mapSlice, curMap) + } + } + } + if len(mapSlice) > 0 { + resultMap[xSpecMap[xpath].yangEntry.Name] = mapSlice + } else { + log.Infof("Empty slice for (\"%v\").\r\n", uri) + } + } + }// end of tblList for + return nil } func terminalNodeProcess(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath string, dbDataMap *map[db.DBNum]map[string]map[string]db.Value, tbl string, tblKey string) (map[string]interface{}, error) { - log.Infof("Received xpath - %v, uri - %v, dbDataMap - %v, table - %v, table key - %v", xpath, uri, (*dbDataMap), tbl, tblKey) - var err error + log.Infof("Received xpath - %v, uri - %v, dbDataMap - %v, table - %v, table key - %v", xpath, uri, (*dbDataMap), tbl, tblKey) + var err error resFldValMap := make(map[string]interface{}) - if xSpecMap[xpath].yangEntry == nil { + if xSpecMap[xpath].yangEntry == nil { logStr := fmt.Sprintf("No yang entry found for xpath %v.", xpath) - err = fmt.Errorf("%v", logStr) - return resFldValMap, err - } + err = fmt.Errorf("%v", logStr) + return resFldValMap, err + } - cdb := xSpecMap[xpath].dbIndex - if len(xSpecMap[xpath].xfmrFunc) > 0 { - _, key, _ := xpathKeyExtract(dbs[cdb], ygRoot, GET, uri) - inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, uri, GET, key, dbDataMap, nil) + cdb := xSpecMap[xpath].dbIndex + if len(xSpecMap[xpath].xfmrFunc) > 0 { + _, key, _ := xpathKeyExtract(dbs[cdb], ygRoot, GET, uri) + inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, uri, GET, key, dbDataMap, nil) fldValMap, err := leafXfmrHandlerFunc(inParams) - if err != nil { + if err != nil { logStr := fmt.Sprintf("%Failed to get data from overloaded function for %v -v.", uri, err) err = fmt.Errorf("%v", logStr) return resFldValMap, err - } - for lf, val := range fldValMap { - resFldValMap[lf] = val - } - } else { - dbFldName := xSpecMap[xpath].fieldName - /* if there is no transformer extension/annotation then it means leaf-list in yang is also leaflist in db */ - if len(dbFldName) > 0 && !xSpecMap[xpath].isKey { - yangType := yangTypeGet(xSpecMap[xpath].yangEntry) - if yangType == "leaf-list" { - dbFldName += "@" - val, ok := (*dbDataMap)[cdb][tbl][tblKey].Field[dbFldName] - if ok { - resLst := processLfLstDbToYang(xpath, val) - resFldValMap[xSpecMap[xpath].yangEntry.Name] = resLst - } - } else { - val, ok := (*dbDataMap)[cdb][tbl][tblKey].Field[dbFldName] - if ok { - yngTerminalNdDtType := xSpecMap[xpath].yangEntry.Type.Kind - resVal, err := DbToYangType(yngTerminalNdDtType, xpath, val) - if err != nil { - log.Error("Failure in converting Db value type to yang type for field", xpath) - } else { - resFldValMap[xSpecMap[xpath].yangEntry.Name] = resVal - } - } - } - } - } + } + for lf, val := range fldValMap { + resFldValMap[lf] = val + } + } else { + dbFldName := xSpecMap[xpath].fieldName + /* if there is no transformer extension/annotation then it means leaf-list in yang is also leaflist in db */ + if len(dbFldName) > 0 && !xSpecMap[xpath].isKey { + yangType := yangTypeGet(xSpecMap[xpath].yangEntry) + if yangType == "leaf-list" { + dbFldName += "@" + val, ok := (*dbDataMap)[cdb][tbl][tblKey].Field[dbFldName] + if ok { + resLst := processLfLstDbToYang(xpath, val) + resFldValMap[xSpecMap[xpath].yangEntry.Name] = resLst + } + } else { + val, ok := (*dbDataMap)[cdb][tbl][tblKey].Field[dbFldName] + if ok { + yngTerminalNdDtType := xSpecMap[xpath].yangEntry.Type.Kind + resVal, err := DbToYangType(yngTerminalNdDtType, xpath, val) + if err != nil { + log.Error("Failure in converting Db value type to yang type for field", xpath) + } else { + resFldValMap[xSpecMap[xpath].yangEntry.Name] = resVal + } + } + } + } + } return resFldValMap, err } func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath string, dbDataMap *map[db.DBNum]map[string]map[string]db.Value, resultMap map[string]interface{}, tbl string, tblKey string, cdb db.DBNum, validate bool) error { - var err error - isValid := validate - yangNode, ok := xSpecMap[xpath] - - if ok && yangNode.yangEntry != nil { - for yangChldName := range yangNode.yangEntry.Dir { - chldXpath := xpath+"/"+yangChldName - chldUri := uri+"/"+yangChldName - if xSpecMap[chldXpath] != nil && xSpecMap[chldXpath].yangEntry != nil { - _, key, _ := xpathKeyExtract(dbs[cdb], ygRoot, GET, chldUri) - if len(xSpecMap[chldXpath].validateFunc) > 0 && !validate { - // TODO - handle non CONFIG-DB - inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, chldUri, GET, key, dbDataMap, nil) - res := validateHandlerFunc(inParams) - if res != true { - continue - } else { - isValid = res - } - } - chldYangType := yangTypeGet(xSpecMap[chldXpath].yangEntry) - cdb = xSpecMap[chldXpath].dbIndex - if chldYangType == "leaf" || chldYangType == "leaf-list" { - fldValMap, err := terminalNodeProcess(dbs, ygRoot, chldUri, chldXpath, dbDataMap, tbl, tblKey) - if err != nil { - log.Infof("Failed to get data(\"%v\").", chldUri) - } - for lf, val := range fldValMap { - resultMap[lf] = val - } - - } else if chldYangType == "container" { - cname := xSpecMap[chldXpath].yangEntry.Name - if len(xSpecMap[chldXpath].xfmrFunc) > 0 { - inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, chldUri, GET, "", dbDataMap, nil) - cmap, _ := xfmrHandlerFunc(inParams) - if len(cmap) > 0 { - resultMap[cname] = cmap - } else { - log.Infof("Empty container(\"%v\").\r\n", chldUri) - } - } else if xSpecMap[chldXpath].xfmrTbl != nil { - lxfmrTblName := *xSpecMap[chldXpath].tableName - if len(lxfmrTblName) > 0 { - inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, chldUri, GET, "", dbDataMap, nil) - tblList := xfmrTblHandlerFunc(lxfmrTblName, inParams) // should be a list containing a single table ??? - if len(tblList) == 0 { - log.Warningf("Table transformer did not return any table for xpath %v", chldXpath) - continue - } - // TODO - add check of single table in list ??? - if len(tblList) > 1 { - log.Warningf("Table transformer returned returned more than one table for container %v", chldXpath) - continue - } - for _, tbl := range(tblList) { - var resDbDataMap = make(map[string]map[string]db.Value) - /*TODO - check if there is a key transformer, if yes then get the key and supply else use incoming tblKey(key of parent)*/ - //err := fillDbDataMapForTbl(chldUri, chldXpath, tbl, parentTblKey, cdb, dbs, &resDbDataMap) - err := fillDbDataMapForTbl(chldUri, chldXpath, tbl, tblKey, cdb, dbs, &resDbDataMap) - if err != nil { - log.Warningf("Could not retrieve DB data for table %v for xpath %v", tbl, xpath) - continue + var err error + isValid := validate + yangNode, ok := xSpecMap[xpath] + + if ok && yangNode.yangEntry != nil { + for yangChldName := range yangNode.yangEntry.Dir { + chldXpath := xpath+"/"+yangChldName + chldUri := uri+"/"+yangChldName + if xSpecMap[chldXpath] != nil && xSpecMap[chldXpath].yangEntry != nil { + _, key, _ := xpathKeyExtract(dbs[cdb], ygRoot, GET, chldUri) + if len(xSpecMap[chldXpath].validateFunc) > 0 && !validate { + // TODO - handle non CONFIG-DB + inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, chldUri, GET, key, dbDataMap, nil) + res := validateHandlerFunc(inParams) + if res != true { + continue + } else { + isValid = res + } + } + chldYangType := yangTypeGet(xSpecMap[chldXpath].yangEntry) + cdb = xSpecMap[chldXpath].dbIndex + if chldYangType == "leaf" || chldYangType == "leaf-list" { + fldValMap, err := terminalNodeProcess(dbs, ygRoot, chldUri, chldXpath, dbDataMap, tbl, tblKey) + if err != nil { + log.Infof("Failed to get data(\"%v\").", chldUri) + } + for lf, val := range fldValMap { + resultMap[lf] = val + } + } else if chldYangType == "container" { + cname := xSpecMap[chldXpath].yangEntry.Name + if len(xSpecMap[chldXpath].xfmrFunc) > 0 { + inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, chldUri, GET, "", dbDataMap, nil) + cmap, _ := xfmrHandlerFunc(inParams) + if len(cmap) > 0 { + resultMap[cname] = cmap + } else { + log.Infof("Empty container(\"%v\").\r\n", chldUri) + } + } else if xSpecMap[chldXpath].xfmrTbl != nil { + xfmrTblFunc := *xSpecMap[chldXpath].xfmrTbl + if len(xfmrTblFunc) > 0 { + inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, chldUri, GET, "", dbDataMap, nil) + tblList := xfmrTblHandlerFunc(xfmrTblFunc, inParams) + if len(tblList) > 1 { + log.Warningf("Table transformer returned more than one table for container %v", chldXpath) + } + dbDataFromTblXfmrGet(tblList[0], inParams, dbDataMap) + } + } + cmap := make(map[string]interface{}) + err = yangDataFill(dbs, ygRoot, chldUri, chldXpath, dbDataMap, cmap, tbl, tblKey, cdb, isValid) + if len(cmap) > 0 { + resultMap[cname] = cmap + } else { + log.Infof("Empty container(\"%v\").\r\n", chldUri) + } + } else if chldYangType == "list" { + cdb = xSpecMap[chldXpath].dbIndex + if len(xSpecMap[chldXpath].xfmrFunc) > 0 { + inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, chldUri, GET, "", dbDataMap, nil) + cmap, _ := xfmrHandlerFunc(inParams) + if len(cmap) > 0 { + resultMap = cmap + } else { + log.Infof("Empty list(\"%v\").\r\n", chldUri) + } + } else { + ynode, ok := xSpecMap[chldXpath] + lTblName := "" + if ok && ynode.tableName != nil { + lTblName = *ynode.tableName + } + yangListDataFill(dbs, ygRoot, chldUri, chldXpath, dbDataMap, resultMap, lTblName, "", cdb, isValid) + } + } else { + return err } - mapCopy((*dbDataMap)[cdb], resDbDataMap) - } - //tblXfmr = true - - } else { - log.Warningf("Table transformer name is empty for xpath %v", chldXpath) - continue } - } //else { - cmap := make(map[string]interface{}) - err = yangDataFill(dbs, ygRoot, chldUri, chldXpath, dbDataMap, cmap, tbl, tblKey, cdb, isValid) - if len(cmap) > 0 { - resultMap[cname] = cmap - } else { - log.Infof("Empty container(\"%v\").\r\n", chldUri) } - //} - } else if chldYangType == "list" { - cdb = xSpecMap[chldXpath].dbIndex - if len(xSpecMap[chldXpath].xfmrFunc) > 0 { - inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, chldUri, GET, "", dbDataMap, nil) - cmap, _ := xfmrHandlerFunc(inParams) - if len(cmap) > 0 { - resultMap = cmap - } else { - log.Infof("Empty list(\"%v\").\r\n", chldUri) - } - } else { - ynode, ok := xSpecMap[chldXpath] - lTblName := "" - if ok && ynode.tableName != nil { - lTblName = *ynode.tableName - } - yangListDataFill(dbs, ygRoot, chldUri, chldXpath, dbDataMap, resultMap, lTblName, "", cdb, isValid) - } - } else { - return err - } - } - } - } - return err + } + return err } /* Traverse linear db-map data and add to nested json data */ func dbDataToYangJsonCreate(uri string, ygRoot *ygot.GoStruct, dbs [db.MaxDB]*db.DB, dbDataMap *map[db.DBNum]map[string]map[string]db.Value, cdb db.DBNum) (string, error) { - jsonData := "" - resultMap := make(map[string]interface{}) + jsonData := "" + resultMap := make(map[string]interface{}) if isCvlYang(uri) { directDbToYangJsonCreate((*dbDataMap)[cdb], jsonData, resultMap) } else { - var d *db.DB - reqXpath, keyName, tableName := xpathKeyExtract(d, ygRoot, GET, uri) - yangNode, ok := xSpecMap[reqXpath] - - if ok { - yangType := yangTypeGet(yangNode.yangEntry) - if yangType == "leaf" || yangType == "leaf-list" { - //fldName := xSpecMap[reqXpath].fieldName - yangName := xSpecMap[reqXpath].yangEntry.Name - tbl, key, _ := tableNameAndKeyFromDbMapGet((*dbDataMap)[cdb]) - validateHandlerFlag := false - if len(xSpecMap[reqXpath].validateFunc) > 0 { - // TODO - handle non CONFIG-DB - inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, uri, GET, key, dbDataMap, nil) - res := validateHandlerFunc(inParams) - if !res { - validateHandlerFlag = true - resultMap[yangName] = "" - } - } - if !validateHandlerFlag { - fldValMap, err := terminalNodeProcess(dbs, ygRoot, uri, reqXpath, dbDataMap, tbl, key) - //err := terminalNodeProcess(dbs, ygRoot, uri, reqXpath, dbDataMap, tbl, key) - if err != nil { - log.Infof("Empty terminal node (\"%v\").", uri) - } - resultMap = fldValMap + var d *db.DB + reqXpath, keyName, tableName := xpathKeyExtract(d, ygRoot, GET, uri) + yangNode, ok := xSpecMap[reqXpath] + if ok { + yangType := yangTypeGet(yangNode.yangEntry) + if yangType == "leaf" || yangType == "leaf-list" { + //fldName := xSpecMap[reqXpath].fieldName + yangName := xSpecMap[reqXpath].yangEntry.Name + tbl, key, _ := tableNameAndKeyFromDbMapGet((*dbDataMap)[cdb]) + validateHandlerFlag := false + if len(xSpecMap[reqXpath].validateFunc) > 0 { + // TODO - handle non CONFIG-DB + inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, uri, GET, key, dbDataMap, nil) + res := validateHandlerFunc(inParams) + if !res { + validateHandlerFlag = true + resultMap[yangName] = "" + } + } + if !validateHandlerFlag { + fldValMap, err := terminalNodeProcess(dbs, ygRoot, uri, reqXpath, dbDataMap, tbl, key) + //err := terminalNodeProcess(dbs, ygRoot, uri, reqXpath, dbDataMap, tbl, key) + if err != nil { + log.Infof("Empty terminal node (\"%v\").", uri) + } + resultMap = fldValMap + } + } else if yangType == "container" { + cname := xSpecMap[reqXpath].yangEntry.Name + cmap := make(map[string]interface{}) + if len(xSpecMap[reqXpath].xfmrFunc) > 0 { + inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, uri, GET, "", dbDataMap, nil) + cmap, _ = xfmrHandlerFunc(inParams) + if len(cmap) > 0 { + resultMap[cname] = cmap + } else { + err := yangDataFill(dbs, ygRoot, uri, reqXpath, dbDataMap, resultMap, tableName, keyName, cdb, false) + if err != nil { + log.Infof("Empty container(\"%v\").\r\n", uri) + } + } + } else { + err := yangDataFill(dbs, ygRoot, uri, reqXpath, dbDataMap, resultMap, tableName, keyName, cdb, false) + if err != nil { + log.Infof("Empty container(\"%v\").\r\n", uri) + } + } + } else { + yangDataFill(dbs, ygRoot, uri, reqXpath, dbDataMap, resultMap, tableName, keyName, cdb, false) + } } + } - } else if yangType == "container" { - cname := xSpecMap[reqXpath].yangEntry.Name - cmap := make(map[string]interface{}) - if len(xSpecMap[reqXpath].xfmrFunc) > 0 { - inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, uri, GET, "", dbDataMap, nil) - cmap, _ = xfmrHandlerFunc(inParams) - if len(cmap) > 0 { - resultMap[cname] = cmap - } else { - err := yangDataFill(dbs, ygRoot, uri, reqXpath, dbDataMap, resultMap, tableName, keyName, cdb, false) - if err != nil { - log.Infof("Empty container(\"%v\").\r\n", uri) - } - } - } else { - err := yangDataFill(dbs, ygRoot, uri, reqXpath, dbDataMap, resultMap, tableName, keyName, cdb, false) - if err != nil { - log.Infof("Empty container(\"%v\").\r\n", uri) - } - } - } else { - yangDataFill(dbs, ygRoot, uri, reqXpath, dbDataMap, resultMap, tableName, keyName, cdb, false) - } - } - } - - jsonMapData, _ := json.Marshal(resultMap) - jsonData = fmt.Sprintf("%v", string(jsonMapData)) - jsonDataPrint(jsonData) - return jsonData, nil + jsonMapData, _ := json.Marshal(resultMap) + jsonData = fmt.Sprintf("%v", string(jsonMapData)) + jsonDataPrint(jsonData) + return jsonData, nil } func jsonDataPrint(data string) { diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index f839e96ddd..4afa6cf0e1 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -46,8 +46,21 @@ func dataToDBMapAdd(tableName string, dbKey string, result map[string]map[string return } +func tblNameFromTblXfmrGet(xfmrTblFunc string, inParams XfmrParams) (string, error){ + tblList := xfmrTblHandlerFunc(xfmrTblFunc, inParams) + if len(tblList) != 1 { + logStr := fmt.Sprintf("Invalid return value(%v) from table transformer for (%v)", tblList, inParams.uri) + log.Error(logStr) + err := errors.New(logStr) + return "", err + } + return tblList[0], nil +} + /* Fill the redis-db map with data */ func mapFillData(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, dbKey string, result map[string]map[string]db.Value, xpathPrefix string, name string, value interface{}) error { + var dbs [db.MaxDB]*db.DB + var err error xpath := xpathPrefix + "/" + name xpathInfo := xSpecMap[xpath] log.Infof("name: \"%v\", xpathPrefix(\"%v\").", name, xpathPrefix) @@ -57,7 +70,7 @@ func mapFillData(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, dbKey st return errors.New("Invalid URI") } - if xpathInfo.tableName == nil { + if xpathInfo.tableName == nil && xpathInfo.xfmrTbl == nil{ log.Errorf("Table for yang-path(\"%v\") not found.", xpath) return errors.New("Invalid table name") } @@ -93,7 +106,6 @@ func mapFillData(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, dbKey st if nErr != nil { return nErr } - var dbs [db.MaxDB]*db.DB inParams := formXfmrInputRequest(d, dbs, db.MaxDB, ygRoot, uri, oper, "", nil, node[0].Data) ret, err := XlateFuncCall(yangToDbXfmrFunc(xSpecMap[xpath].xfmrFunc), inParams) if err != nil { @@ -134,15 +146,27 @@ func mapFillData(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, dbKey st log.Infof("leaf-list value after conversion to DB format %v : %v", fieldName, valueStr) } else { // xpath is a leaf - valueStr = fmt.Sprintf("%v", value) - if strings.Contains(valueStr, ":") { - valueStr = strings.Split(valueStr, ":")[1] - } + valueStr = fmt.Sprintf("%v", value) + if strings.Contains(valueStr, ":") { + valueStr = strings.Split(valueStr, ":")[1] + } } - dataToDBMapAdd(*xpathInfo.tableName, dbKey, result, fieldName, valueStr) - log.Infof("TblName: \"%v\", key: \"%v\", field: \"%v\", valueStr: \"%v\".", - *xpathInfo.tableName, dbKey, fieldName, valueStr) + tableName := "" + if xpathInfo.xfmrTbl != nil { + inParams := formXfmrInputRequest(d, dbs, db.MaxDB, ygRoot, uri, oper, "", nil, "") + // expecting only one table name from tbl-xfmr + tableName, err = tblNameFromTblXfmrGet(*xSpecMap[xpath].xfmrTbl, inParams) + if err != nil { + return err + } + } else { + tableName = *xpathInfo.tableName + } + + dataToDBMapAdd(tableName, dbKey, result, fieldName, valueStr) + log.Infof("TblName: \"%v\", key: \"%v\", field: \"%v\", valueStr: \"%v\".", tableName, dbKey, + fieldName, valueStr) return nil } @@ -305,7 +329,7 @@ func dbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string, jsonDat moduleNm := "/" + strings.Split(path, "/")[1] log.Infof("Module name for path %s is %s", path, moduleNm) if _, ok := xSpecMap[moduleNm]; ok { - if xSpecMap[moduleNm].yangDataType == "container" { + if xSpecMap[moduleNm].yangDataType == "container" && len(xSpecMap[moduleNm].xfmrPost) > 0 { log.Info("Invoke post transformer: ", xSpecMap[moduleNm].xfmrPost) dbDataMap := make(map[db.DBNum]map[string]map[string]db.Value) dbDataMap[db.ConfigDB] = result @@ -372,7 +396,7 @@ func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, if (typeOfValue == reflect.Map || typeOfValue == reflect.Slice) && xSpecMap[xpath].yangDataType != "leaf-list" { if xSpecMap[xpath] != nil && len(xSpecMap[xpath].xfmrFunc) > 0 { /* subtree transformer present */ - inParams := formXfmrInputRequest(d, dbs, db.MaxDB, ygRoot, curUri, oper, "", nil, nil) + inParams := formXfmrInputRequest(d, dbs, db.MaxDB, ygRoot, curUri, oper, "", nil, nil) ret, err := XlateFuncCall(yangToDbXfmrFunc(xSpecMap[xpath].xfmrFunc), inParams) if err != nil { return nil @@ -440,7 +464,7 @@ func xpathKeyExtract(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string) (st if ok { if len(xSpecMap[yangXpath].xfmrKey) > 0 { xfmrFuncName := yangToDbXfmrFunc(xSpecMap[yangXpath].xfmrKey) - inParams := formXfmrInputRequest(d, dbs, db.MaxDB, ygRoot, curPathWithKey, oper, "", nil, nil) + inParams := formXfmrInputRequest(d, dbs, db.MaxDB, ygRoot, curPathWithKey, oper, "", nil, nil) ret, err := XlateFuncCall(xfmrFuncName, inParams) if err != nil { return "", "", "" @@ -461,7 +485,10 @@ func xpathKeyExtract(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string) (st tblPtr := xSpecMap[pfxPath].tableName if tblPtr != nil { tableName = *tblPtr - } + } else if xSpecMap[pfxPath].xfmrTbl != nil { + inParams := formXfmrInputRequest(d, dbs, db.MaxDB, ygRoot, curPathWithKey, oper, "", nil, nil) + tableName, _ = tblNameFromTblXfmrGet(*xSpecMap[pfxPath].xfmrTbl, inParams) + } return pfxPath, keyStr, tableName } diff --git a/src/translib/transformer/xlate_utils.go b/src/translib/transformer/xlate_utils.go index 849f34e5f0..42e280ab5b 100644 --- a/src/translib/transformer/xlate_utils.go +++ b/src/translib/transformer/xlate_utils.go @@ -89,71 +89,76 @@ func yangTypeGet(entry *yang.Entry) string { } func dbKeyToYangDataConvert(uri string, xpath string, dbKey string) (map[string]interface{}, string, error) { - var err error - if len(uri) == 0 && len(xpath) == 0 && len(dbKey) == 0 { - err = fmt.Errorf("Insufficient input") - return nil, "", err - } + var err error + if len(uri) == 0 && len(xpath) == 0 && len(dbKey) == 0 { + err = fmt.Errorf("Insufficient input") + return nil, "", err + } - if _, ok := xSpecMap[xpath]; ok { - if xSpecMap[xpath].yangEntry == nil { - err = fmt.Errorf("Yang Entry not available for xpath ", xpath) - return nil, "", nil + if _, ok := xSpecMap[xpath]; ok { + if xSpecMap[xpath].yangEntry == nil { + err = fmt.Errorf("Yang Entry not available for xpath ", xpath) + return nil, "", nil + } } - } - var kLvlValList []string - keyDataList := strings.Split(dbKey, "|") - keyNameList := yangKeyFromEntryGet(xSpecMap[xpath].yangEntry) - id := xSpecMap[xpath].keyLevel - uriWithKey := fmt.Sprintf("%v", xpath) + var kLvlValList []string + keyDataList := strings.Split(dbKey, "|") + keyNameList := yangKeyFromEntryGet(xSpecMap[xpath].yangEntry) + id := xSpecMap[xpath].keyLevel + uriWithKey := fmt.Sprintf("%v", xpath) - /* if uri contins key, use it else use xpath */ - if strings.Contains(uri, "[") { - uriWithKey = fmt.Sprintf("%v", uri) - } + /* if uri contins key, use it else use xpath */ + if strings.Contains(uri, "[") { + uriWithKey = fmt.Sprintf("%v", uri) + } - if len(xSpecMap[xpath].xfmrKey) > 0 { - var dbs [db.MaxDB]*db.DB - inParams := formXfmrInputRequest(nil, dbs, db.MaxDB, nil, uri, GET, dbKey, nil, nil) - ret, err := XlateFuncCall(dbToYangXfmrFunc(xSpecMap[xpath].xfmrKey), inParams) - if err != nil { - return nil, "", err - } - rmap := ret[0].Interface().(map[string]interface{}) - for k, v := range rmap { - uriWithKey += fmt.Sprintf("[%v=%v]", k, v) - } - return rmap, uriWithKey, nil - } - kLvlValList = append(kLvlValList, keyDataList[id]) + if len(xSpecMap[xpath].xfmrKey) > 0 { + var dbs [db.MaxDB]*db.DB + inParams := formXfmrInputRequest(nil, dbs, db.MaxDB, nil, uri, GET, dbKey, nil, nil) + ret, err := XlateFuncCall(dbToYangXfmrFunc(xSpecMap[xpath].xfmrKey), inParams) + if err != nil { + return nil, "", err + } + rmap := ret[0].Interface().(map[string]interface{}) + for k, v := range rmap { + uriWithKey += fmt.Sprintf("[%v=%v]", k, v) + } + return rmap, uriWithKey, nil + } - if len(keyNameList) > 1 { - kLvlValList = strings.Split(keyDataList[id], "_") - } + if len(keyDataList) == 0 || len(keyNameList) == 0 { + return nil, "", nil + } - /* TODO: Need to add leaf-ref related code in here and remove this code*/ - kvalExceedFlag := false - chgId := -1 - if len(keyNameList) < len(kLvlValList) { - kvalExceedFlag = true - chgId = len(keyNameList) - 1 - } + kLvlValList = append(kLvlValList, keyDataList[id]) - rmap := make(map[string]interface{}) - for i, kname := range keyNameList { - kval := kLvlValList[i] + if len(keyNameList) > 1 { + kLvlValList = strings.Split(keyDataList[id], "_") + } - /* TODO: Need to add leaf-ref related code in here and remove this code*/ - if kvalExceedFlag && (i == chgId) { - kval = strings.Join(kLvlValList[chgId:], "_") - } + /* TODO: Need to add leaf-ref related code in here and remove this code*/ + kvalExceedFlag := false + chgId := -1 + if len(keyNameList) < len(kLvlValList) { + kvalExceedFlag = true + chgId = len(keyNameList) - 1 + } - uriWithKey += fmt.Sprintf("[%v=%v]", kname, kval) - rmap[kname] = kval - } + rmap := make(map[string]interface{}) + for i, kname := range keyNameList { + kval := kLvlValList[i] + + /* TODO: Need to add leaf-ref related code in here and remove this code*/ + if kvalExceedFlag && (i == chgId) { + kval = strings.Join(kLvlValList[chgId:], "_") + } + + uriWithKey += fmt.Sprintf("[%v=%v]", kname, kval) + rmap[kname] = kval + } - return rmap, uriWithKey, nil + return rmap, uriWithKey, nil } func contains(sl []string, str string) bool { diff --git a/src/translib/transformer/xspec.go b/src/translib/transformer/xspec.go index 80774588e4..2ec8c2f52d 100644 --- a/src/translib/transformer/xspec.go +++ b/src/translib/transformer/xspec.go @@ -42,68 +42,72 @@ var xDbSpecOrdTblMap map[string][]string //map of module-name to ordered list of /* update transformer spec with db-node */ func updateDbTableData (xpath string, xpathData *yangXpathInfo, tableName string) { - _, ok := xDbSpecMap[tableName] - if ok { + _, ok := xDbSpecMap[tableName] + if ok { xDbSpecMap[tableName].yangXpath = append(xDbSpecMap[tableName].yangXpath, xpath) - xpathData.dbEntry = xDbSpecMap[tableName].dbEntry - } + xpathData.dbEntry = xDbSpecMap[tableName].dbEntry + } } /* Recursive api to fill the map with yang details */ func yangToDbMapFill (keyLevel int, xSpecMap map[string]*yangXpathInfo, entry *yang.Entry, xpathPrefix string) { - xpath := "" - /* create the yang xpath */ - if xSpecMap[xpathPrefix] != nil && xSpecMap[xpathPrefix].yangDataType == "module" { - /* module name is separated from the rest of xpath with ":" */ - xpath = xpathPrefix + ":" + entry.Name - } else { - xpath = xpathPrefix + "/" + entry.Name - } + xpath := "" + /* create the yang xpath */ + if xSpecMap[xpathPrefix] != nil && xSpecMap[xpathPrefix].yangDataType == "module" { + /* module name is separated from the rest of xpath with ":" */ + xpath = xpathPrefix + ":" + entry.Name + } else { + xpath = xpathPrefix + "/" + entry.Name + } - xpathData, ok := xSpecMap[xpath] - if !ok { - xpathData = new(yangXpathInfo) - xSpecMap[xpath] = xpathData - xpathData.dbIndex = db.ConfigDB // default value - } else { - xpathData = xSpecMap[xpath] - } + xpathData, ok := xSpecMap[xpath] + if !ok { + xpathData = new(yangXpathInfo) + xSpecMap[xpath] = xpathData + xpathData.dbIndex = db.ConfigDB // default value + } else { + xpathData = xSpecMap[xpath] + } - xpathData.yangDataType = entry.Node.Statement().Keyword - if entry.Node.Statement().Keyword == "list" && xpathData.tableName != nil { - childToUpdateParent(xpath, *xpathData.tableName) - } + xpathData.yangDataType = entry.Node.Statement().Keyword + if entry.Node.Statement().Keyword == "list" && xpathData.tableName != nil { + childToUpdateParent(xpath, *xpathData.tableName) + } - parentXpathData, ok := xSpecMap[xpathPrefix] - /* init current xpath table data with its parent data, change only if needed. */ - if ok { - if xpathData.tableName == nil && parentXpathData.tableName != nil && xpathData.xfmrTbl == nil { - xpathData.tableName = parentXpathData.tableName - } else if xpathData.xfmrTbl == nil && parentXpathData.xfmrTbl != nil { - xpathData.xfmrTbl = parentXpathData.xfmrTbl - } - } + parentXpathData, ok := xSpecMap[xpathPrefix] + /* init current xpath table data with its parent data, change only if needed. */ + if ok { + if xpathData.tableName == nil && parentXpathData.tableName != nil && xpathData.xfmrTbl == nil { + xpathData.tableName = parentXpathData.tableName + } else if xpathData.xfmrTbl == nil && parentXpathData.xfmrTbl != nil { + xpathData.xfmrTbl = parentXpathData.xfmrTbl + } + } - if ok && parentXpathData.dbIndex != db.ConfigDB { - xpathData.dbIndex = parentXpathData.dbIndex - } + if ok && parentXpathData.dbIndex != db.ConfigDB { + xpathData.dbIndex = parentXpathData.dbIndex + } - if ok && len(parentXpathData.validateFunc) > 0 { - xpathData.validateFunc = parentXpathData.validateFunc - } + if ok && len(parentXpathData.validateFunc) > 0 { + xpathData.validateFunc = parentXpathData.validateFunc + } - if xpathData.yangDataType == "leaf" && len(xpathData.fieldName) == 0 { - if xpathData.tableName != nil && xDbSpecMap[*xpathData.tableName] != nil { + if ok && len(parentXpathData.xfmrFunc) > 0 && len(xpathData.xfmrFunc) == 0 { + xpathData.xfmrFunc = parentXpathData.xfmrFunc + } + + if xpathData.yangDataType == "leaf" && len(xpathData.fieldName) == 0 { + if xpathData.tableName != nil && xDbSpecMap[*xpathData.tableName] != nil { if xDbSpecMap[*xpathData.tableName].dbEntry.Dir[entry.Name] != nil { xpathData.fieldName = entry.Name } else if xDbSpecMap[*xpathData.tableName].dbEntry.Dir[strings.ToUpper(entry.Name)] != nil { xpathData.fieldName = strings.ToUpper(entry.Name) } } else if xpathData.xfmrTbl != nil { - /* table transformer present */ - xpathData.fieldName = entry.Name - } - } + /* table transformer present */ + xpathData.fieldName = entry.Name + } + } if xpathData.yangDataType == "leaf" && len(xpathData.fieldName) > 0 && xpathData.tableName != nil { dbPath := *xpathData.tableName + "/" + xpathData.fieldName @@ -112,44 +116,44 @@ func yangToDbMapFill (keyLevel int, xSpecMap map[string]*yangXpathInfo, entry *y } } - /* fill table with key data. */ - curKeyLevel := keyLevel - if len(entry.Key) != 0 { - parentKeyLen := 0 - - /* create list with current keys */ - keyXpath := make([]string, len(strings.Split(entry.Key, " "))) - for id, keyName := range(strings.Split(entry.Key, " ")) { - keyXpath[id] = xpath + "/" + keyName - keyXpathData := new(yangXpathInfo) - xSpecMap[xpath + "/" + keyName] = keyXpathData - xSpecMap[xpath + "/" + keyName].isKey = true - } + /* fill table with key data. */ + curKeyLevel := keyLevel + if len(entry.Key) != 0 { + parentKeyLen := 0 + + /* create list with current keys */ + keyXpath := make([]string, len(strings.Split(entry.Key, " "))) + for id, keyName := range(strings.Split(entry.Key, " ")) { + keyXpath[id] = xpath + "/" + keyName + keyXpathData := new(yangXpathInfo) + xSpecMap[xpath + "/" + keyName] = keyXpathData + xSpecMap[xpath + "/" + keyName].isKey = true + } - xpathData.keyXpath = make(map[int]*[]string, (parentKeyLen + 1)) - k := 0 - for ; k < parentKeyLen; k++ { - /* copy parent key-list to child key-list*/ - xpathData.keyXpath[k] = parentXpathData.keyXpath[k] - } - xpathData.keyXpath[k] = &keyXpath - xpathData.keyLevel = curKeyLevel - curKeyLevel++ - } else if parentXpathData != nil && parentXpathData.keyXpath != nil { - xpathData.keyXpath = parentXpathData.keyXpath - } + xpathData.keyXpath = make(map[int]*[]string, (parentKeyLen + 1)) + k := 0 + for ; k < parentKeyLen; k++ { + /* copy parent key-list to child key-list*/ + xpathData.keyXpath[k] = parentXpathData.keyXpath[k] + } + xpathData.keyXpath[k] = &keyXpath + xpathData.keyLevel = curKeyLevel + curKeyLevel++ + } else if parentXpathData != nil && parentXpathData.keyXpath != nil { + xpathData.keyXpath = parentXpathData.keyXpath + } - /* get current obj's children */ - var childList []string - for k := range entry.Dir { - childList = append(childList, k) - } + /* get current obj's children */ + var childList []string + for k := range entry.Dir { + childList = append(childList, k) + } - xpathData.yangEntry = entry - /* now recurse, filling the map with current node's children info */ - for _, child := range childList { - yangToDbMapFill(curKeyLevel, xSpecMap, entry.Dir[child], xpath) - } + xpathData.yangEntry = entry + /* now recurse, filling the map with current node's children info */ + for _, child := range childList { + yangToDbMapFill(curKeyLevel, xSpecMap, entry.Dir[child], xpath) + } } /* Build lookup table based of yang xpath */ @@ -195,7 +199,6 @@ func dbMapFill(prefixPath string, curPath string, moduleNm string, trkTpCnt bool xDbSpecMap[dbXpath].fieldType = entryType } - var childList []string for _, k := range entry.DirOKeys { childList = append(childList, k) @@ -215,108 +218,108 @@ func dbMapFill(prefixPath string, curPath string, moduleNm string, trkTpCnt bool /* Build redis db lookup map */ func dbMapBuild(entries []*yang.Entry) { - if entries == nil { - return - } - xDbSpecMap = make(map[string]*dbInfo) - xDbSpecOrdTblMap = make(map[string][]string) + if entries == nil { + return + } + xDbSpecMap = make(map[string]*dbInfo) + xDbSpecOrdTblMap = make(map[string][]string) - for _, e := range entries { - if e == nil || len(e.Dir) == 0 { - continue - } - moduleNm := e.Name - log.Info("Module name", moduleNm) - xDbSpecOrdTblMap[moduleNm] = []string{} - trkTpCnt := true - dbMapFill("", "", moduleNm, trkTpCnt, xDbSpecMap, e) - } + for _, e := range entries { + if e == nil || len(e.Dir) == 0 { + continue + } + moduleNm := e.Name + log.Info("Module name", moduleNm) + xDbSpecOrdTblMap[moduleNm] = []string{} + trkTpCnt := true + dbMapFill("", "", moduleNm, trkTpCnt, xDbSpecMap, e) + } } func childToUpdateParent( xpath string, tableName string) { - var xpathData *yangXpathInfo - parent := parentXpathGet(xpath) - if len(parent) == 0 || parent == "/" { - return - } + var xpathData *yangXpathInfo + parent := parentXpathGet(xpath) + if len(parent) == 0 || parent == "/" { + return + } - _, ok := xSpecMap[parent] - if !ok { - xpathData = new(yangXpathInfo) - xSpecMap[parent] = xpathData - } - xSpecMap[parent].childTable = append(xSpecMap[parent].childTable, tableName) - if xSpecMap[parent].yangEntry != nil && xSpecMap[parent].yangEntry.Node.Statement().Keyword == "list" { - return - } - childToUpdateParent(parent, tableName) + _, ok := xSpecMap[parent] + if !ok { + xpathData = new(yangXpathInfo) + xSpecMap[parent] = xpathData + } + xSpecMap[parent].childTable = append(xSpecMap[parent].childTable, tableName) + if xSpecMap[parent].yangEntry != nil && xSpecMap[parent].yangEntry.Node.Statement().Keyword == "list" { + return + } + childToUpdateParent(parent, tableName) } /* Build lookup map based on yang xpath */ func annotEntryFill(xSpecMap map[string]*yangXpathInfo, xpath string, entry *yang.Entry) { - xpathData := new(yangXpathInfo) - _, ok := xSpecMap[xpath] - if !ok { - fmt.Printf("Xpath not found(%v) \r\n", xpath) - } + xpathData := new(yangXpathInfo) + _, ok := xSpecMap[xpath] + if !ok { + fmt.Printf("Xpath not found(%v) \r\n", xpath) + } - xpathData.dbIndex = db.ConfigDB // default value - /* fill table with yang extension data. */ - if entry != nil && len(entry.Exts) > 0 { - for _, ext := range entry.Exts { - dataTagArr := strings.Split(ext.Keyword, ":") - tagType := dataTagArr[len(dataTagArr)-1] - switch tagType { - case "table-name" : - if xpathData.tableName == nil { - xpathData.tableName = new(string) - } - *xpathData.tableName = ext.NName() - updateDbTableData(xpath, xpathData, *xpathData.tableName) - //childToUpdateParent(xpath, *xpathData.tableName) - case "table-transformer" : - if xpathData.xfmrTbl == nil { - xpathData.xfmrTbl = new(string) - } - *xpathData.xfmrTbl = ext.NName() - case "field-name" : - xpathData.fieldName = ext.NName() - case "subtree-transformer" : - xpathData.xfmrFunc = ext.NName() - case "key-transformer" : - xpathData.xfmrKey = ext.NName() - case "key-delimiter" : - xpathData.delim = ext.NName() - case "field-transformer" : - xpathData.xfmrFunc = ext.NName() - case "post-transformer" : - xpathData.xfmrPost = ext.NName() - case "get-validate" : - xpathData.validateFunc = ext.NName() - case "use-self-key" : - xpathData.keyXpath = nil - case "redis-db-name" : - if ext.NName() == "APPL_DB" { - xpathData.dbIndex = db.ApplDB - } else if ext.NName() == "ASIC_DB" { - xpathData.dbIndex = db.AsicDB - } else if ext.NName() == "COUNTERS_DB" { - xpathData.dbIndex = db.CountersDB - } else if ext.NName() == "LOGLEVEL_DB" { - xpathData.dbIndex = db.LogLevelDB - } else if ext.NName() == "CONFIG_DB" { - xpathData.dbIndex = db.ConfigDB - } else if ext.NName() == "FLEX_COUNTER_DB" { - xpathData.dbIndex = db.FlexCounterDB - } else if ext.NName() == "STATE_DB" { - xpathData.dbIndex = db.StateDB - } else { - xpathData.dbIndex = db.ConfigDB - } - } - } - } - xSpecMap[xpath] = xpathData + xpathData.dbIndex = db.ConfigDB // default value + /* fill table with yang extension data. */ + if entry != nil && len(entry.Exts) > 0 { + for _, ext := range entry.Exts { + dataTagArr := strings.Split(ext.Keyword, ":") + tagType := dataTagArr[len(dataTagArr)-1] + switch tagType { + case "table-name" : + if xpathData.tableName == nil { + xpathData.tableName = new(string) + } + *xpathData.tableName = ext.NName() + updateDbTableData(xpath, xpathData, *xpathData.tableName) + //childToUpdateParent(xpath, *xpathData.tableName) + case "table-transformer" : + if xpathData.xfmrTbl == nil { + xpathData.xfmrTbl = new(string) + } + *xpathData.xfmrTbl = ext.NName() + case "field-name" : + xpathData.fieldName = ext.NName() + case "subtree-transformer" : + xpathData.xfmrFunc = ext.NName() + case "key-transformer" : + xpathData.xfmrKey = ext.NName() + case "key-delimiter" : + xpathData.delim = ext.NName() + case "field-transformer" : + xpathData.xfmrFunc = ext.NName() + case "post-transformer" : + xpathData.xfmrPost = ext.NName() + case "get-validate" : + xpathData.validateFunc = ext.NName() + case "use-self-key" : + xpathData.keyXpath = nil + case "redis-db-name" : + if ext.NName() == "APPL_DB" { + xpathData.dbIndex = db.ApplDB + } else if ext.NName() == "ASIC_DB" { + xpathData.dbIndex = db.AsicDB + } else if ext.NName() == "COUNTERS_DB" { + xpathData.dbIndex = db.CountersDB + } else if ext.NName() == "LOGLEVEL_DB" { + xpathData.dbIndex = db.LogLevelDB + } else if ext.NName() == "CONFIG_DB" { + xpathData.dbIndex = db.ConfigDB + } else if ext.NName() == "FLEX_COUNTER_DB" { + xpathData.dbIndex = db.FlexCounterDB + } else if ext.NName() == "STATE_DB" { + xpathData.dbIndex = db.StateDB + } else { + xpathData.dbIndex = db.ConfigDB + } + } + } + } + xSpecMap[xpath] = xpathData } /* Build xpath from yang-annotation */ From 6cced54f489ae754ac90ffe553728b4a32fdfbac Mon Sep 17 00:00:00 2001 From: ranjinidn Date: Wed, 25 Sep 2019 00:20:33 +0000 Subject: [PATCH 162/214] Extend annotations for augmentations in oc-yang --- goyang-modified-files/annotate.go | 241 ++++++++++++++++++++++++++++-- 1 file changed, 231 insertions(+), 10 deletions(-) diff --git a/goyang-modified-files/annotate.go b/goyang-modified-files/annotate.go index 47237b4e15..e1f820c3b6 100644 --- a/goyang-modified-files/annotate.go +++ b/goyang-modified-files/annotate.go @@ -38,12 +38,10 @@ func init() { func getFile(files []string, mods map[string]*yang.Module) { for _, name := range files { slash := strings.Split(name, "/") - if strings.HasSuffix(name, ".yang") { modname := slash[len(slash)-1] modname = strings.TrimSuffix(modname, ".yang"); /* Save the yang.Module entries we are interested in */ modules[modname] = mods[modname] - } } } @@ -67,11 +65,11 @@ func generate(w io.Writer, e *yang.Entry, path string) { if e.Name != "" { fmt.Fprintf(w, "module %s-annot {\n", e.Name) //} fmt.Fprintln(w) - fmt.Fprintf(w, " yang-version \"%s\"\n", getYangVersion(e.Name, modules)) + fmt.Fprintf(w, " yang-version \"%s\";\n", getYangVersion(e.Name, modules)) fmt.Fprintln(w) fmt.Fprintf(w, " namespace \"http://openconfig.net/yang/annotation\";\n") if e.Prefix != nil { - fmt.Fprintf(w, " prefix \"%s-annot\" \n", e.Prefix.Name) + fmt.Fprintf(w, " prefix \"%s-annot\";\n", e.Prefix.Name) } fmt.Fprintln(w) @@ -79,7 +77,7 @@ func generate(w io.Writer, e *yang.Entry, path string) { imports = getImportModules(e.Name, modules) for k := range imports { if e.Name != k { - fmt.Fprintf(w, " import %s { prefix %s }\n", k, allimports[k]) + fmt.Fprintf(w, " import %s { prefix %s; }\n", k, allimports[k]) } } @@ -98,23 +96,37 @@ func generate(w io.Writer, e *yang.Entry, path string) { } path = path + delim + name - fmt.Fprintf(w, " deviation %s {\n", path) - fmt.Fprintf(w, " deviate add {\n") - fmt.Fprintf(w, " }\n") - fmt.Fprintf(w, " }\n") - fmt.Fprintln(w) + printDeviation(w, path) var names []string for k := range e.Dir { names = append(names, k) } + if (e.Node.Kind() == "module") { + if len(e.Node.(*yang.Module).Augment) > 0 { + for _,a := range e.Node.(*yang.Module).Augment { + path = a.Name + handleAugments(w, a, e.Node.(*yang.Module).Grouping, e.Prefix.Name, path) + } + } + } + for _, k := range names { generate(w, e.Dir[k], path) } } +func printDeviation(w io.Writer, path string){ + fmt.Fprintf(w, " deviation %s {\n", path) + fmt.Fprintf(w, " deviate add {\n") + fmt.Fprintf(w, " }\n") + fmt.Fprintf(w, " }\n") + fmt.Fprintln(w) +} + + // Save to map all imported modules func GetAllImports(entries []*yang.Entry) { for _, e := range entries { @@ -141,3 +153,212 @@ func getImportModules(modname string, mods map[string]*yang.Module) map[string]s } return imports } + +func handleAugments(w io.Writer, a *yang.Augment, grp []*yang.Grouping, prefix string, path string) { + for _, u := range a.Uses { + grpN := u.Name + for _, g := range grp { + if grpN == g.Name { + if len(g.Container) > 0 { + handleContainer(w, g.Container, grp, prefix, path) + } + if len(g.List) > 0 { + handleList(w, g.List, grp, prefix, path) + } + if len(g.LeafList) > 0 { + handleLeafList(w, g.LeafList, prefix, path) + } + if len(g.Leaf) > 0 { + handleLeaf(w, g.Leaf, prefix, path) + } + if len(g.Choice) > 0 { + handleChoice(w, g.Choice, grp, prefix, path) + } + if len(g.Uses) > 0 { + handleUses(w, g.Uses, grp, prefix, path) + } + } + } + } + +} + +func handleUses(w io.Writer, u []*yang.Uses, grp []*yang.Grouping, prefix string, path string) { + for _, u := range u { + grpN := u.Name + for _, g := range grp { + if grpN == g.Name { + if len(g.Container) > 0 { + handleContainer(w, g.Container, grp, prefix, path) + } + if len(g.List) > 0 { + handleList(w, g.List, grp, prefix, path) + } + if len(g.LeafList) > 0 { + handleLeafList(w, g.LeafList, prefix, path) + } + if len(g.Leaf) > 0 { + handleLeaf(w, g.Leaf, prefix, path) + } + if len(g.Choice) > 0 { + handleChoice(w, g.Choice, grp, prefix, path) + } + } + } + } + +} + +func handleContainer(w io.Writer, ctr []*yang.Container, grp []*yang.Grouping, prefix string, path string) { + for _, c := range ctr { + npath := path + "/" + prefix + ":" + c.Name + printDeviation(w, npath) + if len(c.Container) > 0 { + handleContainer(w, c.Container, grp, prefix, npath) + } + if len(c.List) > 0 { + handleList(w, c.List, grp, prefix, npath) + } + if len(c.LeafList) > 0 { + handleLeafList(w, c.LeafList, prefix, npath) + } + if len(c.Leaf) > 0 { + handleLeaf(w, c.Leaf, prefix, npath) + } + if len(c.Choice) > 0 { + handleChoice(w, c.Choice, grp, prefix, npath) + } + if len(c.Grouping) > 0 { + handleGrouping(w, c.Grouping, grp, prefix, npath) + } + if len(c.Uses) > 0 { + handleUses(w, c.Uses, grp, prefix, npath) + } + } +} + +func handleList(w io.Writer, lst []*yang.List, grp []*yang.Grouping, prefix string, path string) { + for _, l := range lst { + npath := path + "/" + prefix + ":" + l.Name + printDeviation(w, npath) + if len(l.Container) > 0 { + handleContainer(w, l.Container, grp, prefix, npath) + } + if len(l.List) > 0 { + handleList(w, l.List, grp, prefix, npath) + } + if len(l.LeafList) > 0 { + handleLeafList(w, l.LeafList, prefix, npath) + } + if len(l.Leaf) > 0 { + handleLeaf(w, l.Leaf, prefix, npath) + } + if len(l.Choice) > 0 { + handleChoice(w, l.Choice, grp, prefix, npath) + } + if len(l.Grouping) > 0 { + handleGrouping(w, l.Grouping, grp, prefix, npath) + } + if len(l.Uses) > 0 { + handleUses(w, l.Uses, grp, prefix, npath) + } + + } +} + +func handleGrouping(w io.Writer, grp []*yang.Grouping, grptop []*yang.Grouping, prefix string, path string) { + for _, g := range grp { + npath := path + "/" + prefix + ":" + g.Name + printDeviation(w, npath) + if len(g.Container) > 0 { + handleContainer(w, g.Container, grptop, prefix, npath) + } + if len(g.List) > 0 { + handleList(w, g.List, grptop, prefix, npath) + } + if len(g.LeafList) > 0 { + handleLeafList(w, g.LeafList, prefix, npath) + } + if len(g.Leaf) > 0 { + handleLeaf(w, g.Leaf, prefix, npath) + } + if len(g.Choice) > 0 { + handleChoice(w, g.Choice, grptop, prefix, npath) + } + if len(g.Grouping) > 0 { + handleGrouping(w, g.Grouping, grptop, prefix, npath) + } + if len(g.Uses) > 0 { + handleUses(w, g.Uses, grptop, prefix, npath) + } + + } +} + +func handleLeaf (w io.Writer, lf []*yang.Leaf, prefix string, path string) { + if len(lf) > 0 { + for _, l := range lf { + npath := path + "/" + prefix + ":" + l.Name + printDeviation(w, npath) + } + } + +} + +func handleLeafList (w io.Writer, llst []*yang.LeafList, prefix string, path string) { + if len(llst) > 0 { + for _, l := range llst { + npath := path + "/" + prefix + ":" + l.Name + printDeviation(w, npath) + } + } +} + +func handleChoice (w io.Writer, ch []*yang.Choice, grp []*yang.Grouping, prefix string, path string) { + for _, c := range ch { + npath := path + "/" + prefix + ":" + c.Name + printDeviation(w, npath) + if len(c.Container) > 0 { + handleContainer(w, c.Container, grp, prefix, npath) + } + if len(c.List) > 0 { + handleList(w, c.List, grp, prefix, npath) + } + if len(c.LeafList) > 0 { + handleLeafList(w, c.LeafList, prefix, npath) + } + if len(c.Leaf) > 0 { + handleLeaf(w, c.Leaf, prefix, npath) + } + if len(c.Case) > 0 { + handleCase(w, c.Case, grp, prefix, npath) + } + } +} + +func handleCase (w io.Writer, ch []*yang.Case, grp []*yang.Grouping, prefix string, path string) { + for _, c := range ch { + npath := path + "/" + prefix + ":" + c.Name + printDeviation(w, npath) + if len(c.Container) > 0 { + handleContainer(w, c.Container, grp, prefix, npath) + } + if len(c.List) > 0 { + handleList(w, c.List, grp, prefix, npath) + } + if len(c.LeafList) > 0 { + handleLeafList(w, c.LeafList, prefix, npath) + } + if len(c.Leaf) > 0 { + handleLeaf(w, c.Leaf, prefix, npath) + } + if len(c.Choice) > 0 { + handleChoice(w, c.Choice, grp, prefix, npath) + } + if len(c.Uses) > 0 { + handleUses(w, c.Uses, grp, prefix, npath) + } + + } +} + From da35b700eee235fa86a5a97c6c5e08cbfee9bdf0 Mon Sep 17 00:00:00 2001 From: justinejose91 Date: Tue, 24 Sep 2019 22:10:02 -0700 Subject: [PATCH 163/214] Addressing the comments mentioned --- src/CLI/clitree/cli-xml/interface.xml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/CLI/clitree/cli-xml/interface.xml b/src/CLI/clitree/cli-xml/interface.xml index 4e92612d2f..32d2e9df1a 100644 --- a/src/CLI/clitree/cli-xml/interface.xml +++ b/src/CLI/clitree/cli-xml/interface.xml @@ -131,7 +131,7 @@ limitations under the License. @@ -157,7 +157,7 @@ limitations under the License. @@ -242,7 +242,7 @@ limitations under the License. @@ -268,8 +268,8 @@ limitations under the License. > @@ -301,7 +301,7 @@ limitations under the License. ptype="SUBCOMMAND" mode="subcommand" > - + @@ -348,5 +348,5 @@ limitations under the License. completion="false" /> - + From 4cdb8c5edb5c22322037494d82f1dce69f1983ae Mon Sep 17 00:00:00 2001 From: justinejose91 Date: Tue, 24 Sep 2019 23:03:01 -0700 Subject: [PATCH 164/214] Fixed alignment of XML files --- src/CLI/clitree/cli-xml/interface.xml | 534 +++++++++++++------------- 1 file changed, 268 insertions(+), 266 deletions(-) diff --git a/src/CLI/clitree/cli-xml/interface.xml b/src/CLI/clitree/cli-xml/interface.xml index 32d2e9df1a..bd35a4df2d 100644 --- a/src/CLI/clitree/cli-xml/interface.xml +++ b/src/CLI/clitree/cli-xml/interface.xml @@ -23,148 +23,150 @@ limitations under the License. http://www.dellemc.com/sonic/XMLSchema/clish.xsd" > - + - - + > + + + + + + + + + - - - - - - - - - if test "${if-subcommands}" = "status"; then - python $SONIC_CLI_ROOT/sonic-cli-if.py get_openconfig_interfaces_interfaces show_interface_status.j2 ${__full_line} - elif test "${if-subcommands}" = "counters"; then - python $SONIC_CLI_ROOT/sonic-cli-if.py get_openconfig_interfaces_interfaces show_interface_counters.j2 ${__full_line} - else - if test "${phy-if-id}" = ""; then - python $SONIC_CLI_ROOT/sonic-cli-if.py get_openconfig_interfaces_interfaces show_interface.j2 ${__full_line} - else - python $SONIC_CLI_ROOT/sonic-cli-if.py get_openconfig_interfaces_interfaces_interface Ethernet${phy-if-id} show_interface_id.j2 ${__full_line} - fi - fi - - - - - - - python $SONIC_CLI_ROOT/sonic-cli-if.py get_openconfig_vlan_interfaces_interface_ethernet_switched_vlan_state show_vlan.j2 - - + + if test "${if-subcommands}" = "status"; then + python $SONIC_CLI_ROOT/sonic-cli-if.py get_openconfig_interfaces_interfaces show_interface_status.j2 ${__full_line} + elif test "${if-subcommands}" = "counters"; then + python $SONIC_CLI_ROOT/sonic-cli-if.py get_openconfig_interfaces_interfaces show_interface_counters.j2 ${__full_line} + else + if test "${phy-if-id}" = ""; then + python $SONIC_CLI_ROOT/sonic-cli-if.py get_openconfig_interfaces_interfaces show_interface.j2 ${__full_line} + else + python $SONIC_CLI_ROOT/sonic-cli-if.py get_openconfig_interfaces_interfaces_interface Ethernet${phy-if-id} show_interface_id.j2 ${__full_line} + fi + fi + + - + + + + + python $SONIC_CLI_ROOT/sonic-cli-if.py get_openconfig_vlan_interfaces_interface_ethernet_switched_vlan_state show_vlan.j2 + + + + - - + + - - - - - - - - - - + + + + + - - - - - - - - - - - + + + + + + + + + + + + + + + + - - python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_interfaces_interfaces_interface_config_description ${iface} ${desc} + python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_interfaces_interfaces_interface_config_description ${iface} ${desc} - python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_interfaces_interfaces_interface_config_description ${iface} "" + python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_interfaces_interfaces_interface_config_description ${iface} "" - - python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_interfaces_interfaces_interface_config_mtu ${iface} ${mtu} + python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_interfaces_interfaces_interface_config_mtu ${iface} ${mtu} - python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_interfaces_interfaces_interface_config_mtu ${iface} 9100 @@ -210,143 +212,143 @@ limitations under the License. - python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_interfaces_interfaces_interface_config_enabled ${iface} False + python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_interfaces_interfaces_interface_config_enabled ${iface} False - python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_interfaces_interfaces_interface_config_enabled ${iface} True + python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_interfaces_interfaces_interface_config_enabled ${iface} True - - - - - - - - - - - - - - - - - - - + + + + + + + + - - - - - - + + + + + + + + + + + - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - - + + From d5d6b80df91282e503e5e4e825cdf5004db3c1fa Mon Sep 17 00:00:00 2001 From: justinejose91 Date: Tue, 24 Sep 2019 23:29:17 -0700 Subject: [PATCH 165/214] Cleanup of the xml files --- src/CLI/clitree/cli-xml/interface.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CLI/clitree/cli-xml/interface.xml b/src/CLI/clitree/cli-xml/interface.xml index bd35a4df2d..0ded9aabfd 100644 --- a/src/CLI/clitree/cli-xml/interface.xml +++ b/src/CLI/clitree/cli-xml/interface.xml @@ -80,13 +80,13 @@ limitations under the License. From de22d29062551e0d54833ef2ba44139748fdc0cd Mon Sep 17 00:00:00 2001 From: ranjinidn Date: Wed, 25 Sep 2019 06:30:30 +0000 Subject: [PATCH 166/214] Handle nested groupings for augmentation --- goyang-modified-files/annotate.go | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/goyang-modified-files/annotate.go b/goyang-modified-files/annotate.go index e1f820c3b6..e86d441fad 100644 --- a/goyang-modified-files/annotate.go +++ b/goyang-modified-files/annotate.go @@ -24,6 +24,7 @@ import ( var allimports = make(map[string]string) var modules = make(map[string]*yang.Module) +var allmodules = make(map[string]*yang.Module) func init() { register(&formatter{ @@ -36,6 +37,7 @@ func init() { // Get the modules for which annotation file needs to be generated func getFile(files []string, mods map[string]*yang.Module) { + allmodules = mods for _, name := range files { slash := strings.Split(name, "/") modname := slash[len(slash)-1] @@ -134,6 +136,15 @@ func GetAllImports(entries []*yang.Entry) { } } +func GetModuleFromPrefix(prefix string) string { + for m, p := range allimports { + if prefix == p { + return m + } + } + return "" +} + //Get Yang version from the yang.Modules func getYangVersion(modname string, mods map[string]*yang.Module) string { if (mods[modname].YangVersion != nil) { @@ -186,6 +197,14 @@ func handleAugments(w io.Writer, a *yang.Augment, grp []*yang.Grouping, prefix s func handleUses(w io.Writer, u []*yang.Uses, grp []*yang.Grouping, prefix string, path string) { for _, u := range u { grpN := u.Name + if strings.Contains(grpN, ":") { + tokens := strings.Split(grpN, ":") + nprefix := tokens[0] + grpN = tokens[1] + mod := GetModuleFromPrefix(nprefix) + grp = allmodules[mod].Grouping + prefix = nprefix + } for _, g := range grp { if grpN == g.Name { if len(g.Container) > 0 { @@ -203,6 +222,10 @@ func handleUses(w io.Writer, u []*yang.Uses, grp []*yang.Grouping, prefix string if len(g.Choice) > 0 { handleChoice(w, g.Choice, grp, prefix, path) } + if len(g.Uses) > 0 { + handleUses(w, g.Uses, grp, prefix, path) + } + } } } From 045cbf90c92fbc20aa0a2dd3332c159e2ac26d1b Mon Sep 17 00:00:00 2001 From: s-mari Date: Wed, 25 Sep 2019 10:13:24 -0700 Subject: [PATCH 167/214] changed the xSpecMap to xYangSpecMap for code clarity and added new file with transformer-constants --- src/translib/transformer/xconst.go | 31 ++++++++++ src/translib/transformer/xlate.go | 8 +-- src/translib/transformer/xlate_from_db.go | 70 +++++++++++------------ src/translib/transformer/xlate_to_db.go | 42 +++++++------- src/translib/transformer/xlate_utils.go | 28 ++++----- src/translib/transformer/xspec.go | 55 +++++++++--------- 6 files changed, 133 insertions(+), 101 deletions(-) create mode 100644 src/translib/transformer/xconst.go diff --git a/src/translib/transformer/xconst.go b/src/translib/transformer/xconst.go new file mode 100644 index 0000000000..a20d297934 --- /dev/null +++ b/src/translib/transformer/xconst.go @@ -0,0 +1,31 @@ +package transformer + +const ( + YANG_MODULE = "module" + YANG_LIST = "list" + YANG_CONTAINER = "container" + YANG_LEAF = "leaf" + YANG_LEAF_LIST = "leaflist" + + YANG_ANNOT_DB_NAME = "redis-db-name" + YANG_ANNOT_TABLE_NAME = "table-name" + YANG_ANNOT_FIELD_NAME = "field-name" + YANG_ANNOT_KEY_DELIM = "key-delimiter" + YANG_ANNOT_TABLE_XFMR = "table-transformer" + YANG_ANNOT_FIELD_XFMR = "field-transformer" + YANG_ANNOT_KEY_XFMR = "key-transformer" + YANG_ANNOT_POST_XFMR = "post-transformer" + YANG_ANNOT_SUBTREE_XFMR = "subtree-transformer" + YANG_ANNOT_VALIDATE_FUNC = "get-validate" + + REDIS_DB_TYPE_APPLN = "APPL_DB" + REDIS_DB_TYPE_ASIC = "ASIC_DB" + REDIS_DB_TYPE_CONFIG = "CONFIG_DB" + REDIS_DB_TYPE_COUNTER = "COUNTERS_DB" + REDIS_DB_TYPE_LOG_LVL = "LOGLEVEL_DB" + REDIS_DB_TYPE_STATE = "STATE_DB" + REDIS_DB_TYPE_FLX_COUNTER = "FLEX_COUNTER_DB" + + XPATH_SEP_FWD_SLASH = "/" + XFMR_EMPTY_STRING = "" +) diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index f5489096f5..77007c30fc 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -128,12 +128,12 @@ func XlateUriToKeySpec(uri string, ygRoot *ygot.GoStruct, t *interface{}) (*[]Ke } func FillKeySpecs(yangXpath string , keyStr string, retdbFormat *[]KeySpec) ([]KeySpec){ - if xSpecMap == nil { + if xYangSpecMap == nil { return *retdbFormat } - _, ok := xSpecMap[yangXpath] + _, ok := xYangSpecMap[yangXpath] if ok { - xpathInfo := xSpecMap[yangXpath] + xpathInfo := xYangSpecMap[yangXpath] if xpathInfo.tableName != nil { dbFormat := KeySpec{} dbFormat.Ts.Name = *xpathInfo.tableName @@ -303,7 +303,7 @@ func XlateFromDb(uri string, ygRoot *ygot.GoStruct, dbs [db.MaxDB]*db.DB, data m } } else { xpath, _ := RemoveXPATHPredicates(uri) - cdb = xSpecMap[xpath].dbIndex + cdb = xYangSpecMap[xpath].dbIndex } payload, err := dbDataToYangJsonCreate(uri, ygRoot, dbs, &dbData, cdb) log.Info("Payload generated:", payload) diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index 7125c1caea..fc8824222a 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -21,8 +21,8 @@ type typeMapOfInterface map[string]interface{} func xfmrHandlerFunc(inParams XfmrParams) (map[string]interface{}, error) { result := make(map[string]interface{}) xpath, _ := RemoveXPATHPredicates(inParams.uri) - log.Infof("Subtree transformer function(\"%v\") invoked for yang path(\"%v\").", xSpecMap[xpath].xfmrFunc, xpath) - _, err := XlateFuncCall(dbToYangXfmrFunc(xSpecMap[xpath].xfmrFunc), inParams) + log.Infof("Subtree transformer function(\"%v\") invoked for yang path(\"%v\").", xYangSpecMap[xpath].xfmrFunc, xpath) + _, err := XlateFuncCall(dbToYangXfmrFunc(xYangSpecMap[xpath].xfmrFunc), inParams) if err != nil { log.Infof("Failed to retrieve data for xpath(\"%v\") err(%v).", inParams.uri, err) return result, err @@ -61,7 +61,7 @@ func xfmrHandlerFunc(inParams XfmrParams) (map[string]interface{}, error) { func leafXfmrHandlerFunc(inParams XfmrParams) (map[string]interface{}, error) { xpath, _ := RemoveXPATHPredicates(inParams.uri) - ret, err := XlateFuncCall(dbToYangXfmrFunc(xSpecMap[xpath].xfmrFunc), inParams) + ret, err := XlateFuncCall(dbToYangXfmrFunc(xYangSpecMap[xpath].xfmrFunc), inParams) if err != nil { return nil, err } @@ -71,7 +71,7 @@ func leafXfmrHandlerFunc(inParams XfmrParams) (map[string]interface{}, error) { func validateHandlerFunc(inParams XfmrParams) (bool) { xpath, _ := RemoveXPATHPredicates(inParams.uri) - ret, err := XlateFuncCall(xSpecMap[xpath].validateFunc, inParams) + ret, err := XlateFuncCall(xYangSpecMap[xpath].validateFunc, inParams) if err != nil { return false } @@ -272,8 +272,8 @@ func yangListDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, x var tblList []string tblXfmr := false - if tbl == "" && xSpecMap[xpath].xfmrTbl != nil { - xfmrTblFunc := *xSpecMap[xpath].xfmrTbl + if tbl == "" && xYangSpecMap[xpath].xfmrTbl != nil { + xfmrTblFunc := *xYangSpecMap[xpath].xfmrTbl if len(xfmrTblFunc) > 0 { tblXfmr = true inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, uri, GET, "", dbDataMap, nil) @@ -296,7 +296,7 @@ func yangListDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, x for dbKey, _ := range tblData { curMap := make(map[string]interface{}) curKeyMap, curUri, _ := dbKeyToYangDataConvert(uri, xpath, dbKey) - if len(xSpecMap[xpath].xfmrFunc) > 0 { + if len(xYangSpecMap[xpath].xfmrFunc) > 0 { inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, curUri, GET, "", dbDataMap, nil) cmap, _ := xfmrHandlerFunc(inParams) if len(cmap) > 0 { @@ -317,7 +317,7 @@ func yangListDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, x } } if len(mapSlice) > 0 { - resultMap[xSpecMap[xpath].yangEntry.Name] = mapSlice + resultMap[xYangSpecMap[xpath].yangEntry.Name] = mapSlice } else { log.Infof("Empty slice for (\"%v\").\r\n", uri) } @@ -330,14 +330,14 @@ func terminalNodeProcess(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string log.Infof("Received xpath - %v, uri - %v, dbDataMap - %v, table - %v, table key - %v", xpath, uri, (*dbDataMap), tbl, tblKey) var err error resFldValMap := make(map[string]interface{}) - if xSpecMap[xpath].yangEntry == nil { + if xYangSpecMap[xpath].yangEntry == nil { logStr := fmt.Sprintf("No yang entry found for xpath %v.", xpath) err = fmt.Errorf("%v", logStr) return resFldValMap, err } - cdb := xSpecMap[xpath].dbIndex - if len(xSpecMap[xpath].xfmrFunc) > 0 { + cdb := xYangSpecMap[xpath].dbIndex + if len(xYangSpecMap[xpath].xfmrFunc) > 0 { _, key, _ := xpathKeyExtract(dbs[cdb], ygRoot, GET, uri) inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, uri, GET, key, dbDataMap, nil) fldValMap, err := leafXfmrHandlerFunc(inParams) @@ -350,26 +350,26 @@ func terminalNodeProcess(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string resFldValMap[lf] = val } } else { - dbFldName := xSpecMap[xpath].fieldName + dbFldName := xYangSpecMap[xpath].fieldName /* if there is no transformer extension/annotation then it means leaf-list in yang is also leaflist in db */ - if len(dbFldName) > 0 && !xSpecMap[xpath].isKey { - yangType := yangTypeGet(xSpecMap[xpath].yangEntry) + if len(dbFldName) > 0 && !xYangSpecMap[xpath].isKey { + yangType := yangTypeGet(xYangSpecMap[xpath].yangEntry) if yangType == "leaf-list" { dbFldName += "@" val, ok := (*dbDataMap)[cdb][tbl][tblKey].Field[dbFldName] if ok { resLst := processLfLstDbToYang(xpath, val) - resFldValMap[xSpecMap[xpath].yangEntry.Name] = resLst + resFldValMap[xYangSpecMap[xpath].yangEntry.Name] = resLst } } else { val, ok := (*dbDataMap)[cdb][tbl][tblKey].Field[dbFldName] if ok { - yngTerminalNdDtType := xSpecMap[xpath].yangEntry.Type.Kind + yngTerminalNdDtType := xYangSpecMap[xpath].yangEntry.Type.Kind resVal, err := DbToYangType(yngTerminalNdDtType, xpath, val) if err != nil { log.Error("Failure in converting Db value type to yang type for field", xpath) } else { - resFldValMap[xSpecMap[xpath].yangEntry.Name] = resVal + resFldValMap[xYangSpecMap[xpath].yangEntry.Name] = resVal } } } @@ -382,15 +382,15 @@ func terminalNodeProcess(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath string, dbDataMap *map[db.DBNum]map[string]map[string]db.Value, resultMap map[string]interface{}, tbl string, tblKey string, cdb db.DBNum, validate bool) error { var err error isValid := validate - yangNode, ok := xSpecMap[xpath] + yangNode, ok := xYangSpecMap[xpath] if ok && yangNode.yangEntry != nil { for yangChldName := range yangNode.yangEntry.Dir { chldXpath := xpath+"/"+yangChldName chldUri := uri+"/"+yangChldName - if xSpecMap[chldXpath] != nil && xSpecMap[chldXpath].yangEntry != nil { + if xYangSpecMap[chldXpath] != nil && xYangSpecMap[chldXpath].yangEntry != nil { _, key, _ := xpathKeyExtract(dbs[cdb], ygRoot, GET, chldUri) - if len(xSpecMap[chldXpath].validateFunc) > 0 && !validate { + if len(xYangSpecMap[chldXpath].validateFunc) > 0 && !validate { // TODO - handle non CONFIG-DB inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, chldUri, GET, key, dbDataMap, nil) res := validateHandlerFunc(inParams) @@ -400,8 +400,8 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath isValid = res } } - chldYangType := yangTypeGet(xSpecMap[chldXpath].yangEntry) - cdb = xSpecMap[chldXpath].dbIndex + chldYangType := yangTypeGet(xYangSpecMap[chldXpath].yangEntry) + cdb = xYangSpecMap[chldXpath].dbIndex if chldYangType == "leaf" || chldYangType == "leaf-list" { fldValMap, err := terminalNodeProcess(dbs, ygRoot, chldUri, chldXpath, dbDataMap, tbl, tblKey) if err != nil { @@ -411,8 +411,8 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath resultMap[lf] = val } } else if chldYangType == "container" { - cname := xSpecMap[chldXpath].yangEntry.Name - if len(xSpecMap[chldXpath].xfmrFunc) > 0 { + cname := xYangSpecMap[chldXpath].yangEntry.Name + if len(xYangSpecMap[chldXpath].xfmrFunc) > 0 { inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, chldUri, GET, "", dbDataMap, nil) cmap, _ := xfmrHandlerFunc(inParams) if len(cmap) > 0 { @@ -420,8 +420,8 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath } else { log.Infof("Empty container(\"%v\").\r\n", chldUri) } - } else if xSpecMap[chldXpath].xfmrTbl != nil { - xfmrTblFunc := *xSpecMap[chldXpath].xfmrTbl + } else if xYangSpecMap[chldXpath].xfmrTbl != nil { + xfmrTblFunc := *xYangSpecMap[chldXpath].xfmrTbl if len(xfmrTblFunc) > 0 { inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, chldUri, GET, "", dbDataMap, nil) tblList := xfmrTblHandlerFunc(xfmrTblFunc, inParams) @@ -439,8 +439,8 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath log.Infof("Empty container(\"%v\").\r\n", chldUri) } } else if chldYangType == "list" { - cdb = xSpecMap[chldXpath].dbIndex - if len(xSpecMap[chldXpath].xfmrFunc) > 0 { + cdb = xYangSpecMap[chldXpath].dbIndex + if len(xYangSpecMap[chldXpath].xfmrFunc) > 0 { inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, chldUri, GET, "", dbDataMap, nil) cmap, _ := xfmrHandlerFunc(inParams) if len(cmap) > 0 { @@ -449,7 +449,7 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath log.Infof("Empty list(\"%v\").\r\n", chldUri) } } else { - ynode, ok := xSpecMap[chldXpath] + ynode, ok := xYangSpecMap[chldXpath] lTblName := "" if ok && ynode.tableName != nil { lTblName = *ynode.tableName @@ -474,15 +474,15 @@ func dbDataToYangJsonCreate(uri string, ygRoot *ygot.GoStruct, dbs [db.MaxDB]*db } else { var d *db.DB reqXpath, keyName, tableName := xpathKeyExtract(d, ygRoot, GET, uri) - yangNode, ok := xSpecMap[reqXpath] + yangNode, ok := xYangSpecMap[reqXpath] if ok { yangType := yangTypeGet(yangNode.yangEntry) if yangType == "leaf" || yangType == "leaf-list" { - //fldName := xSpecMap[reqXpath].fieldName - yangName := xSpecMap[reqXpath].yangEntry.Name + //fldName := xYangSpecMap[reqXpath].fieldName + yangName := xYangSpecMap[reqXpath].yangEntry.Name tbl, key, _ := tableNameAndKeyFromDbMapGet((*dbDataMap)[cdb]) validateHandlerFlag := false - if len(xSpecMap[reqXpath].validateFunc) > 0 { + if len(xYangSpecMap[reqXpath].validateFunc) > 0 { // TODO - handle non CONFIG-DB inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, uri, GET, key, dbDataMap, nil) res := validateHandlerFunc(inParams) @@ -500,9 +500,9 @@ func dbDataToYangJsonCreate(uri string, ygRoot *ygot.GoStruct, dbs [db.MaxDB]*db resultMap = fldValMap } } else if yangType == "container" { - cname := xSpecMap[reqXpath].yangEntry.Name + cname := xYangSpecMap[reqXpath].yangEntry.Name cmap := make(map[string]interface{}) - if len(xSpecMap[reqXpath].xfmrFunc) > 0 { + if len(xYangSpecMap[reqXpath].xfmrFunc) > 0 { inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, uri, GET, "", dbDataMap, nil) cmap, _ = xfmrHandlerFunc(inParams) if len(cmap) > 0 { diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index 4afa6cf0e1..2b98dd25e7 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -21,12 +21,12 @@ const SONIC_FIELD_INDEX = 3 /* Invoke the post tansformer */ func postXfmrHandlerFunc(inParams XfmrParams) (map[string]map[string]db.Value, error) { xpath, _ := RemoveXPATHPredicates(inParams.uri) - ret, err := XlateFuncCall(xSpecMap[xpath].xfmrPost, inParams) + ret, err := XlateFuncCall(xYangSpecMap[xpath].xfmrPost, inParams) if err != nil { return nil, err } retData := ret[0].Interface().(map[string]map[string]db.Value) - log.Info("Post Transformer function :", xSpecMap[xpath].xfmrPost, " Xpath: ", xpath, " retData: ", retData) + log.Info("Post Transformer function :", xYangSpecMap[xpath].xfmrPost, " Xpath: ", xpath, " retData: ", retData) return retData, err } @@ -62,7 +62,7 @@ func mapFillData(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, dbKey st var dbs [db.MaxDB]*db.DB var err error xpath := xpathPrefix + "/" + name - xpathInfo := xSpecMap[xpath] + xpathInfo := xYangSpecMap[xpath] log.Infof("name: \"%v\", xpathPrefix(\"%v\").", name, xpathPrefix) if xpathInfo == nil { @@ -107,7 +107,7 @@ func mapFillData(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, dbKey st return nErr } inParams := formXfmrInputRequest(d, dbs, db.MaxDB, ygRoot, uri, oper, "", nil, node[0].Data) - ret, err := XlateFuncCall(yangToDbXfmrFunc(xSpecMap[xpath].xfmrFunc), inParams) + ret, err := XlateFuncCall(yangToDbXfmrFunc(xYangSpecMap[xpath].xfmrFunc), inParams) if err != nil { return err } @@ -156,7 +156,7 @@ func mapFillData(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, dbKey st if xpathInfo.xfmrTbl != nil { inParams := formXfmrInputRequest(d, dbs, db.MaxDB, ygRoot, uri, oper, "", nil, "") // expecting only one table name from tbl-xfmr - tableName, err = tblNameFromTblXfmrGet(*xSpecMap[xpath].xfmrTbl, inParams) + tableName, err = tblNameFromTblXfmrGet(*xYangSpecMap[xpath].xfmrTbl, inParams) if err != nil { return err } @@ -247,7 +247,7 @@ func dbMapDelete(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string, jsonDat } else { xpathPrefix, keyName, tableName := xpathKeyExtract(d, ygRoot, oper, path) log.Infof("Delete req: path(\"%v\"), key(\"%v\"), xpathPrefix(\"%v\"), tableName(\"%v\").", path, keyName, xpathPrefix, tableName) - spec, ok := xSpecMap[xpathPrefix] + spec, ok := xYangSpecMap[xpathPrefix] if ok { if spec.tableName != nil { result[*spec.tableName] = make(map[string]db.Value) @@ -328,9 +328,9 @@ func dbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string, jsonDat if oper == CREATE { moduleNm := "/" + strings.Split(path, "/")[1] log.Infof("Module name for path %s is %s", path, moduleNm) - if _, ok := xSpecMap[moduleNm]; ok { - if xSpecMap[moduleNm].yangDataType == "container" && len(xSpecMap[moduleNm].xfmrPost) > 0 { - log.Info("Invoke post transformer: ", xSpecMap[moduleNm].xfmrPost) + if _, ok := xYangSpecMap[moduleNm]; ok { + if xYangSpecMap[moduleNm].yangDataType == "container" && len(xYangSpecMap[moduleNm].xfmrPost) > 0 { + log.Info("Invoke post transformer: ", xYangSpecMap[moduleNm].xfmrPost) dbDataMap := make(map[db.DBNum]map[string]map[string]db.Value) dbDataMap[db.ConfigDB] = result var dbs [db.MaxDB]*db.DB @@ -338,7 +338,7 @@ func dbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string, jsonDat result, err = postXfmrHandlerFunc(inParams) } } else { - log.Errorf("No Entry exists for module %s in XSpecMap. Unable to process post xfmr (\"%v\") path(\"%v\") error (\"%v\").", oper, path, err) + log.Errorf("No Entry exists for module %s in xYangSpecMap. Unable to process post xfmr (\"%v\") path(\"%v\") error (\"%v\").", oper, path, err) } } printDbData(result, "/tmp/yangToDbDataCreate.txt") @@ -362,10 +362,10 @@ func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, for _, data := range dataMap { curKey := "" curUri, _ := uriWithKeyCreate(uri, xpathPrefix, data) - if len(xSpecMap[xpathPrefix].xfmrKey) > 0 { + if len(xYangSpecMap[xpathPrefix].xfmrKey) > 0 { /* key transformer present */ inParams := formXfmrInputRequest(d, dbs, db.MaxDB, ygRoot, curUri, oper, "", nil, nil) - ret, err := XlateFuncCall(yangToDbXfmrFunc(xSpecMap[xpathPrefix].xfmrKey), inParams) + ret, err := XlateFuncCall(yangToDbXfmrFunc(xYangSpecMap[xpathPrefix].xfmrKey), inParams) if err != nil { return err } @@ -393,11 +393,11 @@ func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, curUri = uri + "/" + pathAttr } - if (typeOfValue == reflect.Map || typeOfValue == reflect.Slice) && xSpecMap[xpath].yangDataType != "leaf-list" { - if xSpecMap[xpath] != nil && len(xSpecMap[xpath].xfmrFunc) > 0 { + if (typeOfValue == reflect.Map || typeOfValue == reflect.Slice) && xYangSpecMap[xpath].yangDataType != "leaf-list" { + if xYangSpecMap[xpath] != nil && len(xYangSpecMap[xpath].xfmrFunc) > 0 { /* subtree transformer present */ inParams := formXfmrInputRequest(d, dbs, db.MaxDB, ygRoot, curUri, oper, "", nil, nil) - ret, err := XlateFuncCall(yangToDbXfmrFunc(xSpecMap[xpath].xfmrFunc), inParams) + ret, err := XlateFuncCall(yangToDbXfmrFunc(xYangSpecMap[xpath].xfmrFunc), inParams) if err != nil { return nil } @@ -460,10 +460,10 @@ func xpathKeyExtract(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string) (st keyStr += "|" } yangXpath, _ := RemoveXPATHPredicates(curPathWithKey) - _, ok := xSpecMap[yangXpath] + _, ok := xYangSpecMap[yangXpath] if ok { - if len(xSpecMap[yangXpath].xfmrKey) > 0 { - xfmrFuncName := yangToDbXfmrFunc(xSpecMap[yangXpath].xfmrKey) + if len(xYangSpecMap[yangXpath].xfmrKey) > 0 { + xfmrFuncName := yangToDbXfmrFunc(xYangSpecMap[yangXpath].xfmrKey) inParams := formXfmrInputRequest(d, dbs, db.MaxDB, ygRoot, curPathWithKey, oper, "", nil, nil) ret, err := XlateFuncCall(xfmrFuncName, inParams) if err != nil { @@ -482,12 +482,12 @@ func xpathKeyExtract(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string) (st curPathWithKey += "/" } pfxPath, _ := RemoveXPATHPredicates(path) - tblPtr := xSpecMap[pfxPath].tableName + tblPtr := xYangSpecMap[pfxPath].tableName if tblPtr != nil { tableName = *tblPtr - } else if xSpecMap[pfxPath].xfmrTbl != nil { + } else if xYangSpecMap[pfxPath].xfmrTbl != nil { inParams := formXfmrInputRequest(d, dbs, db.MaxDB, ygRoot, curPathWithKey, oper, "", nil, nil) - tableName, _ = tblNameFromTblXfmrGet(*xSpecMap[pfxPath].xfmrTbl, inParams) + tableName, _ = tblNameFromTblXfmrGet(*xYangSpecMap[pfxPath].xfmrTbl, inParams) } return pfxPath, keyStr, tableName diff --git a/src/translib/transformer/xlate_utils.go b/src/translib/transformer/xlate_utils.go index 42e280ab5b..87a1f67312 100644 --- a/src/translib/transformer/xlate_utils.go +++ b/src/translib/transformer/xlate_utils.go @@ -26,10 +26,10 @@ func keyFromXpathCreate(keyList []string) string { /* Create db key from data xpath(request) */ func keyCreate(keyPrefix string, xpath string, data interface{}) string { - _, ok := xSpecMap[xpath] + _, ok := xYangSpecMap[xpath] if ok { - if xSpecMap[xpath].yangEntry != nil { - yangEntry := xSpecMap[xpath].yangEntry + if xYangSpecMap[xpath].yangEntry != nil { + yangEntry := xYangSpecMap[xpath].yangEntry if len(keyPrefix) > 0 { keyPrefix += "|" } keyVal := "" for i, k := range (strings.Split(yangEntry.Key, " ")) { @@ -95,8 +95,8 @@ func dbKeyToYangDataConvert(uri string, xpath string, dbKey string) (map[string] return nil, "", err } - if _, ok := xSpecMap[xpath]; ok { - if xSpecMap[xpath].yangEntry == nil { + if _, ok := xYangSpecMap[xpath]; ok { + if xYangSpecMap[xpath].yangEntry == nil { err = fmt.Errorf("Yang Entry not available for xpath ", xpath) return nil, "", nil } @@ -104,8 +104,8 @@ func dbKeyToYangDataConvert(uri string, xpath string, dbKey string) (map[string] var kLvlValList []string keyDataList := strings.Split(dbKey, "|") - keyNameList := yangKeyFromEntryGet(xSpecMap[xpath].yangEntry) - id := xSpecMap[xpath].keyLevel + keyNameList := yangKeyFromEntryGet(xYangSpecMap[xpath].yangEntry) + id := xYangSpecMap[xpath].keyLevel uriWithKey := fmt.Sprintf("%v", xpath) /* if uri contins key, use it else use xpath */ @@ -113,10 +113,10 @@ func dbKeyToYangDataConvert(uri string, xpath string, dbKey string) (map[string] uriWithKey = fmt.Sprintf("%v", uri) } - if len(xSpecMap[xpath].xfmrKey) > 0 { + if len(xYangSpecMap[xpath].xfmrKey) > 0 { var dbs [db.MaxDB]*db.DB inParams := formXfmrInputRequest(nil, dbs, db.MaxDB, nil, uri, GET, dbKey, nil, nil) - ret, err := XlateFuncCall(dbToYangXfmrFunc(xSpecMap[xpath].xfmrKey), inParams) + ret, err := XlateFuncCall(dbToYangXfmrFunc(xYangSpecMap[xpath].xfmrKey), inParams) if err != nil { return nil, "", err } @@ -228,8 +228,8 @@ func yangToDbXfmrFunc(funcName string) string { func uriWithKeyCreate (uri string, xpathTmplt string, data interface{}) (string, error) { var err error - if _, ok := xSpecMap[xpathTmplt]; ok { - yangEntry := xSpecMap[xpathTmplt].yangEntry + if _, ok := xYangSpecMap[xpathTmplt]; ok { + yangEntry := xYangSpecMap[xpathTmplt].yangEntry if yangEntry != nil { for _, k := range (strings.Split(yangEntry.Key, " ")) { uri += fmt.Sprintf("[%v=%v]", k, data.(map[string]interface{})[k]) @@ -238,7 +238,7 @@ func uriWithKeyCreate (uri string, xpathTmplt string, data interface{}) (string, err = fmt.Errorf("Yang Entry not available for xpath ", xpathTmplt) } } else { - err = fmt.Errorf("No entry in xSpecMap for xpath ", xpathTmplt) + err = fmt.Errorf("No entry in xYangSpecMap for xpath ", xpathTmplt) } return uri, err } @@ -252,9 +252,9 @@ func xpathRootNameGet(path string) string { } func getDbNum(xpath string ) db.DBNum { - _, ok := xSpecMap[xpath] + _, ok := xYangSpecMap[xpath] if ok { - xpathInfo := xSpecMap[xpath] + xpathInfo := xYangSpecMap[xpath] return xpathInfo.dbIndex } // Default is ConfigDB diff --git a/src/translib/transformer/xspec.go b/src/translib/transformer/xspec.go index 2ec8c2f52d..2a42f87bf1 100644 --- a/src/translib/transformer/xspec.go +++ b/src/translib/transformer/xspec.go @@ -36,7 +36,7 @@ type dbInfo struct { yangXpath []string } -var xSpecMap map[string]*yangXpathInfo +var xYangSpecMap map[string]*yangXpathInfo var xDbSpecMap map[string]*dbInfo var xDbSpecOrdTblMap map[string][]string //map of module-name to ordered list of db tables { "sonic-acl" : ["ACL_TABLE", "ACL_RULE"] } @@ -50,23 +50,23 @@ func updateDbTableData (xpath string, xpathData *yangXpathInfo, tableName string } /* Recursive api to fill the map with yang details */ -func yangToDbMapFill (keyLevel int, xSpecMap map[string]*yangXpathInfo, entry *yang.Entry, xpathPrefix string) { +func yangToDbMapFill (keyLevel int, xYangSpecMap map[string]*yangXpathInfo, entry *yang.Entry, xpathPrefix string) { xpath := "" /* create the yang xpath */ - if xSpecMap[xpathPrefix] != nil && xSpecMap[xpathPrefix].yangDataType == "module" { + if xYangSpecMap[xpathPrefix] != nil && xYangSpecMap[xpathPrefix].yangDataType == "module" { /* module name is separated from the rest of xpath with ":" */ xpath = xpathPrefix + ":" + entry.Name } else { xpath = xpathPrefix + "/" + entry.Name } - xpathData, ok := xSpecMap[xpath] + xpathData, ok := xYangSpecMap[xpath] if !ok { xpathData = new(yangXpathInfo) - xSpecMap[xpath] = xpathData + xYangSpecMap[xpath] = xpathData xpathData.dbIndex = db.ConfigDB // default value } else { - xpathData = xSpecMap[xpath] + xpathData = xYangSpecMap[xpath] } xpathData.yangDataType = entry.Node.Statement().Keyword @@ -74,7 +74,7 @@ func yangToDbMapFill (keyLevel int, xSpecMap map[string]*yangXpathInfo, entry *y childToUpdateParent(xpath, *xpathData.tableName) } - parentXpathData, ok := xSpecMap[xpathPrefix] + parentXpathData, ok := xYangSpecMap[xpathPrefix] /* init current xpath table data with its parent data, change only if needed. */ if ok { if xpathData.tableName == nil && parentXpathData.tableName != nil && xpathData.xfmrTbl == nil { @@ -126,8 +126,8 @@ func yangToDbMapFill (keyLevel int, xSpecMap map[string]*yangXpathInfo, entry *y for id, keyName := range(strings.Split(entry.Key, " ")) { keyXpath[id] = xpath + "/" + keyName keyXpathData := new(yangXpathInfo) - xSpecMap[xpath + "/" + keyName] = keyXpathData - xSpecMap[xpath + "/" + keyName].isKey = true + xYangSpecMap[xpath + "/" + keyName] = keyXpathData + xYangSpecMap[xpath + "/" + keyName].isKey = true } xpathData.keyXpath = make(map[int]*[]string, (parentKeyLen + 1)) @@ -152,7 +152,7 @@ func yangToDbMapFill (keyLevel int, xSpecMap map[string]*yangXpathInfo, entry *y xpathData.yangEntry = entry /* now recurse, filling the map with current node's children info */ for _, child := range childList { - yangToDbMapFill(curKeyLevel, xSpecMap, entry.Dir[child], xpath) + yangToDbMapFill(curKeyLevel, xYangSpecMap, entry.Dir[child], xpath) } } @@ -162,8 +162,8 @@ func yangToDbMapBuild(entries map[string]*yang.Entry) { return } - if xSpecMap == nil { - xSpecMap = make(map[string]*yangXpathInfo) + if xYangSpecMap == nil { + xYangSpecMap = make(map[string]*yangXpathInfo) } for module, e := range entries { @@ -173,12 +173,12 @@ func yangToDbMapBuild(entries map[string]*yang.Entry) { /* Start to fill xpath based map with yang data */ keyLevel := 0 - yangToDbMapFill(keyLevel, xSpecMap, e, "") + yangToDbMapFill(keyLevel, xYangSpecMap, e, "") // Fill the ordered map of child tables list for oc yangs updateSchemaOrderedMap(module, e) } - mapPrint(xSpecMap, "/tmp/fullSpec.txt") + mapPrint(xYangSpecMap, "/tmp/fullSpec.txt") dbMapPrint() } @@ -243,22 +243,23 @@ func childToUpdateParent( xpath string, tableName string) { return } - _, ok := xSpecMap[parent] + _, ok := xYangSpecMap[parent] if !ok { xpathData = new(yangXpathInfo) - xSpecMap[parent] = xpathData + xYangSpecMap[parent] = xpathData } - xSpecMap[parent].childTable = append(xSpecMap[parent].childTable, tableName) - if xSpecMap[parent].yangEntry != nil && xSpecMap[parent].yangEntry.Node.Statement().Keyword == "list" { + xYangSpecMap[parent].childTable = append(xYangSpecMap[parent].childTable, tableName) + if xYangSpecMap[parent].yangEntry != nil && + xYangSpecMap[parent].yangEntry.Node.Statement().Keyword == "list" { return } childToUpdateParent(parent, tableName) } /* Build lookup map based on yang xpath */ -func annotEntryFill(xSpecMap map[string]*yangXpathInfo, xpath string, entry *yang.Entry) { +func annotEntryFill(xYangSpecMap map[string]*yangXpathInfo, xpath string, entry *yang.Entry) { xpathData := new(yangXpathInfo) - _, ok := xSpecMap[xpath] + _, ok := xYangSpecMap[xpath] if !ok { fmt.Printf("Xpath not found(%v) \r\n", xpath) } @@ -319,7 +320,7 @@ func annotEntryFill(xSpecMap map[string]*yangXpathInfo, xpath string, entry *yan } } } - xSpecMap[xpath] = xpathData + xYangSpecMap[xpath] = xpathData } /* Build xpath from yang-annotation */ @@ -336,8 +337,8 @@ func annotToDbMapBuild(annotEntries []*yang.Entry) { if annotEntries == nil { return } - if xSpecMap == nil { - xSpecMap = make(map[string]*yangXpathInfo) + if xYangSpecMap == nil { + xYangSpecMap = make(map[string]*yangXpathInfo) } for _, e := range annotEntries { @@ -348,14 +349,14 @@ func annotToDbMapBuild(annotEntries []*yang.Entry) { for i, deviate := range d.Deviate { if i == 2 { for _, ye := range deviate { - annotEntryFill(xSpecMap, xpath, ye) + annotEntryFill(xYangSpecMap, xpath, ye) } } } } } } - mapPrint(xSpecMap, "/tmp/annotSpec.txt") + mapPrint(xYangSpecMap, "/tmp/annotSpec.txt") } /* Debug function to print the yang xpath lookup map */ @@ -427,9 +428,9 @@ func updateSchemaOrderedMap(module string, entry *yang.Entry) { for _, dir := range entry.DirOKeys { // Gives the yang xpath for the top level container xpath := "/" + module + ":" + dir - _, ok := xSpecMap[xpath] + _, ok := xYangSpecMap[xpath] if ok { - yentry := xSpecMap[xpath].yangEntry + yentry := xYangSpecMap[xpath].yangEntry if yentry.Node.Statement().Keyword == "container" { var keyspec = make([]KeySpec, 0) keyspec = FillKeySpecs(xpath, "" , &keyspec) From 006737e7ed71ae11dd0416d7e7311b4c6993b2e6 Mon Sep 17 00:00:00 2001 From: Tejaswi Goel Date: Wed, 25 Sep 2019 12:04:36 -0700 Subject: [PATCH 168/214] Changes to remove dummy json file Signed-off-by: Tejaswi Goel --- src/CLI/actioner/port_channel_dummy_data.json | 48 -------- src/CLI/actioner/sonic-cli-if.py | 106 +++++++----------- src/CLI/clitree/cli-xml/interface.xml | 10 +- .../renderer/templates/show_portchannel.j2 | 2 +- .../renderer/templates/show_portchannel_id.j2 | 2 +- 5 files changed, 50 insertions(+), 118 deletions(-) delete mode 100644 src/CLI/actioner/port_channel_dummy_data.json diff --git a/src/CLI/actioner/port_channel_dummy_data.json b/src/CLI/actioner/port_channel_dummy_data.json deleted file mode 100644 index 20149bb2d5..0000000000 --- a/src/CLI/actioner/port_channel_dummy_data.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "openconfig-interfaces:interface": [ - { - "members": [ - "Ethernet56", - "Ethernet60" - ], - "min-links": 2, - "mtu": 9100, - "admin-status": "up", - "name": "Portchannel0" - }, - { - "members": [ - "Ethernet64", - "Ethernet68" - ], - "min-links": 1, - "mtu": 9100, - "admin-status": "up", - "name": "Portchannel1" - }, - { - "members": [ - "Ethernet24", - "Ethernet12" - ], - "min-links": 1, - "mtu": 9100, - "admin-status": "up", - "name": "Portchannel2" - }, - { - "members": [], - "min-links": 1, - "mtu": 9100, - "admin-status": "up", - "name": "Portchannel3" - }, - { - "members": [], - "min-links": 1, - "mtu": 9100, - "admin-status": "up", - "name": "Portchannel4" - } - ] -} diff --git a/src/CLI/actioner/sonic-cli-if.py b/src/CLI/actioner/sonic-cli-if.py index 2b20d9cfcd..770a644d28 100755 --- a/src/CLI/actioner/sonic-cli-if.py +++ b/src/CLI/actioner/sonic-cli-if.py @@ -21,7 +21,6 @@ import time import json import ast -import yaml import openconfig_interfaces_client from rpipe_utils import pipestr from openconfig_interfaces_client.rest import ApiException @@ -94,95 +93,76 @@ def run(func, args): c.verify_ssl = False aa = openconfig_interfaces_client.OpenconfigInterfacesApi(api_client=openconfig_interfaces_client.ApiClient(configuration=c)) -# Code for Portchannel cli skeleton, reading and writing data to port_channel_dummy_data json file +# Code for PortChannel cli skeleton + #create a port-channel - if "Portchannel" in args[0] and func.__name__ == 'patch_openconfig_interfaces_interfaces_interface': - with open('port_channel_dummy_data.json', 'r') as f: - data= yaml.safe_load(f) - for dict in data['openconfig-interfaces:interface']: - if dict["name"] == args[0]: - return - body = { - "name": args[0], - "min-links": 1, - "mtu": 9100, - "admin-status": "up", - "members": [] - } - data['openconfig-interfaces:interface'].append(body) - with open('port_channel_dummy_data.json', 'w') as f: - json.dump(data, f, sort_keys=True, indent=4) - print ("Success") + if "PortChannel" in args[0] and func.__name__ == 'patch_openconfig_interfaces_interfaces_interface': return + dummy_data= { + "openconfig-interfaces:interface": [ + { + "members": [ + "Ethernet56", + "Ethernet60" + ], + "min-links": 2, + "mtu": 9100, + "admin_status": "up", + "oper_status": "down", + "name": "PortChannel1" + }, + { + "members": [], + "min-links": 1, + "mtu": 9100, + "admin_status": "up", + "oper_status": "down", + "name": "PortChannel2" + }, + { + "members": [], + "min-links": 1, + "mtu": 9100, + "admin_status": "up", + "oper_status": "down", + "name": "PortChannel3" + } + ] +} + #show given port-channel details - if "Portchannel" in args[0] and func.__name__ == 'get_openconfig_if_aggregate_interfaces_interface_aggregation_state': - with open('port_channel_dummy_data.json', 'r') as f: - data= yaml.safe_load(f) - for dict in data['openconfig-interfaces:interface']: - if dict["name"] == args[0]: + if "PortChannel" in args[0] and func.__name__ == 'get_openconfig_if_aggregate_interfaces_interface_aggregation_state': + for dict in dummy_data['openconfig-interfaces:interface']: + if dict["name"] == "PortChannel3": show_cli_output("show_portchannel_id.j2", dict) return print("%Error: Entry not found") return #show port-channels summary - if "Portchannel" in args[0] and func.__name__ == 'get_openconfig_interfaces_interfaces': - with open('port_channel_dummy_data.json', 'r') as f: - data= yaml.safe_load(f) - show_cli_output("show_portchannel.j2", data) + if "PortChannel" in args[0] and func.__name__ == 'get_openconfig_interfaces_interfaces': + show_cli_output("show_portchannel.j2", dummy_data) return #add members to port-channel if func.__name__ == 'patch_openconfig_if_aggregate_interfaces_interface_ethernet_config_aggregate_id': - port_c = 'Portchannel' + args[1] - with open('port_channel_dummy_data.json', 'r') as readf: - data= yaml.safe_load(readf) - for dict in data['openconfig-interfaces:interface']: - if dict["name"] == port_c: - dict["members"].append(args[0]) - with open('port_channel_dummy_data.json', 'w') as writef: - json.dump(data, writef, sort_keys=True, indent=4) - print ("Success") - return - print ("Failed-entry not found") return #remove members from port-channel if func.__name__ == 'delete_openconfig_if_aggregate_interfaces_interface_ethernet_config_aggregate_id': - return("Success") + return #config mtu for port-channel if "po" in args[0] and func.__name__ == 'patch_openconfig_interfaces_interfaces_interface_config_mtu': - return("Success") + return #delete port-channel - if "Portchannel" in args[0] and func.__name__ == 'delete_openconfig_interfaces_interfaces_interface': - with open('port_channel_dummy_data.json', 'r') as f: - data= yaml.safe_load(f) - for dict in data['openconfig-interfaces:interface']: - if dict["name"] == args[0]: - data['openconfig-interfaces:interface'].remove(dict) - with open('port_channel_dummy_data.json', 'w') as writef: - json.dump(data, writef, sort_keys=True, indent=4) - print ("Success") - return - print ("Failed-entry not found") + if "PortChannel" in args[0] and func.__name__ == 'delete_openconfig_interfaces_interfaces_interface': return #config min-links in port-channel if func.__name__ == 'patch_openconfig_if_aggregate_interfaces_interface_aggregation_config_min_links': - with open('port_channel_dummy_data.json', 'r') as f: - data= yaml.safe_load(f) - port_c = 'Portchannel'+args[0][2:] - for dict in data['openconfig-interfaces:interface']: - if dict["name"] == port_c: - dict["min-links"]=args[1] - with open('port_channel_dummy_data.json', 'w') as f: - json.dump(data, f, sort_keys=True, indent=4) - print ("Success") - return - print ("Failed-entry not found") return # create a body block diff --git a/src/CLI/clitree/cli-xml/interface.xml b/src/CLI/clitree/cli-xml/interface.xml index 5c0a3aa344..f46c082ddc 100644 --- a/src/CLI/clitree/cli-xml/interface.xml +++ b/src/CLI/clitree/cli-xml/interface.xml @@ -63,7 +63,7 @@ limitations under the License. > @@ -84,9 +84,9 @@ limitations under the License. python $SONIC_CLI_ROOT/sonic-cli-if.py get_openconfig_interfaces_interfaces show_interface_counters.j2 elif test "${if-subcommands}" = "port-channel"; then if test "${lag-id}" = ""; then - python $SONIC_CLI_ROOT/sonic-cli-if.py get_openconfig_interfaces_interfaces Portchannel show_portchannel.j2 + python $SONIC_CLI_ROOT/sonic-cli-if.py get_openconfig_interfaces_interfaces PortChannel show_portchannel.j2 else - python $SONIC_CLI_ROOT/sonic-cli-if.py get_openconfig_if_aggregate_interfaces_interface_aggregation_state Portchannel${lag-id} show_portchannel_id.j2#xA; + python $SONIC_CLI_ROOT/sonic-cli-if.py get_openconfig_if_aggregate_interfaces_interface_aggregation_state PortChannel${lag-id} show_portchannel_id.j2#xA; fi else if test "${phy-if-id}" = ""; then @@ -151,7 +151,7 @@ limitations under the License. ptype="UINT" > - python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_interfaces_interfaces_interface Portchannel${lag-id} + python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_interfaces_interfaces_interface PortChannel${lag-id} @@ -195,7 +195,7 @@ limitations under the License. python $SONIC_CLI_ROOT/sonic-cli-if.py delete_openconfig_interfaces_interfaces_interface Vlan${vlan-id} fi if test "${if-subcommands}" = "port-channel"; then - python $SONIC_CLI_ROOT/sonic-cli-if.py delete_openconfig_interfaces_interfaces_interface Portchannel${lag-id} + python $SONIC_CLI_ROOT/sonic-cli-if.py delete_openconfig_interfaces_interfaces_interface PortChannel${lag-id} fi diff --git a/src/CLI/renderer/templates/show_portchannel.j2 b/src/CLI/renderer/templates/show_portchannel.j2 index be5f282ad5..a0f45a4e56 100644 --- a/src/CLI/renderer/templates/show_portchannel.j2 +++ b/src/CLI/renderer/templates/show_portchannel.j2 @@ -5,5 +5,5 @@ Flags: A - Active, Dw - Oper status down {{'%-20s'|format("Port-Channel")}}{{'%-20s'|format("min-links")}}{{'%-20s'|format("Protocol")}}{{'%-15s'|format("MTU")}}{{'%-15s'|format("Admin")}}{{'%-15s'|format("port-members")}} {{'----------------------------------------------------------------------------------------------------------------------------'}} {% for dict in json_output['openconfig-interfaces:interface'] %} -{{'%-20s'|format(dict['name']|string)}}{{'%-20s'|format(dict['min-links'])}}{{'%-20s'|format("LACP(A)(Dw)")}}{{'%-15s'|format(dict['mtu'])}}{{'%-15s'|format(dict['admin-status'])}}{{'%-15s'|format(dict['members']|string|replace("[", "")|replace("]", ""))}} +{{'%-20s'|format(dict['name']|string)}}{{'%-20s'|format(dict['min-links'])}}{{'%-20s'|format("LACP(A)(Dw)")}}{{'%-15s'|format(dict['mtu'])}}{{'%-15s'|format(dict['admin_status'])}}{{'%-15s'|format(dict['members']|string|replace("[", "")|replace("]", ""))}} {% endfor %} diff --git a/src/CLI/renderer/templates/show_portchannel_id.j2 b/src/CLI/renderer/templates/show_portchannel_id.j2 index b45173aaa9..20ccd97758 100644 --- a/src/CLI/renderer/templates/show_portchannel_id.j2 +++ b/src/CLI/renderer/templates/show_portchannel_id.j2 @@ -5,4 +5,4 @@ Flags: A - Active, Dw - Oper status down {{'%-20s'|format("Port-Channel")}}{{'%-20s'|format("min-links")}}{{'%-20s'|format("Protocol")}}{{'%-15s'|format("MTU")}}{{'%-15s'|format("Admin")}}{{'%-15s'|format("port-members")}} {{'----------------------------------------------------------------------------------------------------------------------------'}} {% set dict = json_output %} -{{'%-20s'|format(dict['name']|string)}}{{'%-20s'|format(dict['min-links'])}}{{'%-20s'|format("LACP(A)")}}{{'%-15s'|format(dict['mtu'])}}{{'%-15s'|format(dict['admin-status'])}}{{'%-15s'|format(dict['members']|string|replace("[", "")|replace("]", ""))}} +{{'%-20s'|format(dict['name']|string)}}{{'%-20s'|format(dict['min-links'])}}{{'%-20s'|format("LACP(A)")}}{{'%-15s'|format(dict['mtu'])}}{{'%-15s'|format(dict['admin_status'])}}{{'%-15s'|format(dict['members']|string|replace("[", "")|replace("]", ""))}} From ce598cfcd82a55116d8aca7c56d15f42f03f17f2 Mon Sep 17 00:00:00 2001 From: amrutasali Date: Wed, 25 Sep 2019 22:02:06 +0000 Subject: [PATCH 169/214] Enhanced transformer core to support user-defined key-delimiter/concatenater --- src/translib/transformer/xlate_from_db.go | 2 +- src/translib/transformer/xlate_to_db.go | 2 +- src/translib/transformer/xlate_utils.go | 25 ++++++++++++++++------- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index fc8824222a..26f1ae7174 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -295,7 +295,7 @@ func yangListDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, x var mapSlice []typeMapOfInterface for dbKey, _ := range tblData { curMap := make(map[string]interface{}) - curKeyMap, curUri, _ := dbKeyToYangDataConvert(uri, xpath, dbKey) + curKeyMap, curUri, _ := dbKeyToYangDataConvert(uri, xpath, dbKey, dbs[cdb].Opts.KeySeparator) if len(xYangSpecMap[xpath].xfmrFunc) > 0 { inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, curUri, GET, "", dbDataMap, nil) cmap, _ := xfmrHandlerFunc(inParams) diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index 2b98dd25e7..00c5f0d495 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -371,7 +371,7 @@ func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, } curKey = ret[0].Interface().(string) } else { - curKey = keyCreate(keyName, xpathPrefix, data) + curKey = keyCreate(keyName, xpathPrefix, data, d.Opts.KeySeparator) } yangReqToDbMapCreate(d, ygRoot, oper, curUri, xpathPrefix, curKey, data, result) } diff --git a/src/translib/transformer/xlate_utils.go b/src/translib/transformer/xlate_utils.go index 87a1f67312..6820a56377 100644 --- a/src/translib/transformer/xlate_utils.go +++ b/src/translib/transformer/xlate_utils.go @@ -25,15 +25,21 @@ func keyFromXpathCreate(keyList []string) string { } /* Create db key from data xpath(request) */ -func keyCreate(keyPrefix string, xpath string, data interface{}) string { +func keyCreate(keyPrefix string, xpath string, data interface{}, dbKeySep string) string { _, ok := xYangSpecMap[xpath] if ok { if xYangSpecMap[xpath].yangEntry != nil { yangEntry := xYangSpecMap[xpath].yangEntry - if len(keyPrefix) > 0 { keyPrefix += "|" } + keyConcat := dbKeySep + if len(xYangSpecMap[xpath].delim) > 0 { + keyConcat = xYangSpecMap[xpath].delim + log.Infof("key concatenater(\"%v\") found for xpath %v ", keyConcat, xpath) + } + + if len(keyPrefix) > 0 { keyPrefix += dbKeySep } keyVal := "" for i, k := range (strings.Split(yangEntry.Key, " ")) { - if i > 0 { keyVal = keyVal + "_" } + if i > 0 { keyVal = keyVal + keyConcat } val := fmt.Sprint(data.(map[string]interface{})[k]) if strings.Contains(val, ":") { val = strings.Split(val, ":")[1] @@ -88,7 +94,7 @@ func yangTypeGet(entry *yang.Entry) string { return "" } -func dbKeyToYangDataConvert(uri string, xpath string, dbKey string) (map[string]interface{}, string, error) { +func dbKeyToYangDataConvert(uri string, xpath string, dbKey string, dbKeySep string) (map[string]interface{}, string, error) { var err error if len(uri) == 0 && len(xpath) == 0 && len(dbKey) == 0 { err = fmt.Errorf("Insufficient input") @@ -103,7 +109,7 @@ func dbKeyToYangDataConvert(uri string, xpath string, dbKey string) (map[string] } var kLvlValList []string - keyDataList := strings.Split(dbKey, "|") + keyDataList := strings.Split(dbKey, dbKeySep) keyNameList := yangKeyFromEntryGet(xYangSpecMap[xpath].yangEntry) id := xYangSpecMap[xpath].keyLevel uriWithKey := fmt.Sprintf("%v", xpath) @@ -112,6 +118,11 @@ func dbKeyToYangDataConvert(uri string, xpath string, dbKey string) (map[string] if strings.Contains(uri, "[") { uriWithKey = fmt.Sprintf("%v", uri) } + keyConcat := dbKeySep + if len(xYangSpecMap[xpath].delim) > 0 { + keyConcat = xYangSpecMap[xpath].delim + log.Infof("Found key concatenater(\"%v\") for xpath %v", keyConcat, xpath) + } if len(xYangSpecMap[xpath].xfmrKey) > 0 { var dbs [db.MaxDB]*db.DB @@ -134,7 +145,7 @@ func dbKeyToYangDataConvert(uri string, xpath string, dbKey string) (map[string] kLvlValList = append(kLvlValList, keyDataList[id]) if len(keyNameList) > 1 { - kLvlValList = strings.Split(keyDataList[id], "_") + kLvlValList = strings.Split(keyDataList[id], keyConcat) } /* TODO: Need to add leaf-ref related code in here and remove this code*/ @@ -151,7 +162,7 @@ func dbKeyToYangDataConvert(uri string, xpath string, dbKey string) (map[string] /* TODO: Need to add leaf-ref related code in here and remove this code*/ if kvalExceedFlag && (i == chgId) { - kval = strings.Join(kLvlValList[chgId:], "_") + kval = strings.Join(kLvlValList[chgId:], keyConcat) } uriWithKey += fmt.Sprintf("[%v=%v]", kname, kval) From 20d14e1543b02f780c6945691a0ee55b52b993f6 Mon Sep 17 00:00:00 2001 From: s-mari Date: Wed, 25 Sep 2019 17:12:28 -0700 Subject: [PATCH 170/214] basic support for sonic-yang annotation --- src/translib/transformer/transformer.go | 16 ++- src/translib/transformer/xspec.go | 154 +++++++++++++++++++----- 2 files changed, 131 insertions(+), 39 deletions(-) diff --git a/src/translib/transformer/transformer.go b/src/translib/transformer/transformer.go index e6649cff2c..c69ecabda6 100644 --- a/src/translib/transformer/transformer.go +++ b/src/translib/transformer/transformer.go @@ -117,13 +117,16 @@ func loadYangModules(files ...string) error { } } - sonic_entries := make([]*yang.Entry, len(names)) - oc_entries := make(map[string]*yang.Entry) - annot_entries := make([]*yang.Entry, len(names)) + sonic_entries := make([]*yang.Entry, len(names)) + oc_entries := make(map[string]*yang.Entry) + oc_annot_entries := make([]*yang.Entry, len(names)) + sonic_annot_entries := make([]*yang.Entry, len(names)) for _, n := range names { - if strings.Contains(n, "annot") { - annot_entries = append(annot_entries, yang.ToEntry(mods[n])) + if strings.Contains(n, "annot") && strings.Contains(n, "sonic") { + sonic_annot_entries = append(sonic_annot_entries, yang.ToEntry(mods[n])) + } else if strings.Contains(n, "annot") { + oc_annot_entries = append(oc_annot_entries, yang.ToEntry(mods[n])) } else if strings.Contains(n, "sonic") { sonic_entries = append(sonic_entries, yang.ToEntry(mods[n])) } else if oc_entries[n] == nil { @@ -132,7 +135,8 @@ func loadYangModules(files ...string) error { } dbMapBuild(sonic_entries) - annotToDbMapBuild(annot_entries) + annotDbSpecMap(sonic_annot_entries) + annotToDbMapBuild(oc_annot_entries) yangToDbMapBuild(oc_entries) return err diff --git a/src/translib/transformer/xspec.go b/src/translib/transformer/xspec.go index 2a42f87bf1..dde3804918 100644 --- a/src/translib/transformer/xspec.go +++ b/src/translib/transformer/xspec.go @@ -31,9 +31,11 @@ type yangXpathInfo struct { } type dbInfo struct { + dbIndex db.DBNum + keyName *string fieldType string dbEntry *yang.Entry - yangXpath []string + yangXpath []string } var xYangSpecMap map[string]*yangXpathInfo @@ -179,41 +181,44 @@ func yangToDbMapBuild(entries map[string]*yang.Entry) { updateSchemaOrderedMap(module, e) } mapPrint(xYangSpecMap, "/tmp/fullSpec.txt") - dbMapPrint() + dbMapPrint("/tmp/dbSpecMap.txt") } /* Fill the map with db details */ func dbMapFill(prefixPath string, curPath string, moduleNm string, trkTpCnt bool, xDbSpecMap map[string]*dbInfo, entry *yang.Entry) { - entryType := entry.Node.Statement().Keyword - if entryType == "list" { - prefixPath = entry.Name - } + entryType := entry.Node.Statement().Keyword + if entryType == "list" { + prefixPath = entry.Name + } - if !isYangResType(entryType) { - dbXpath := prefixPath - if entryType != "list" { - dbXpath = prefixPath + "/" + entry.Name - } - xDbSpecMap[dbXpath] = new(dbInfo) - xDbSpecMap[dbXpath].dbEntry = entry - xDbSpecMap[dbXpath].fieldType = entryType - } + if !isYangResType(entryType) { + dbXpath := prefixPath + if entryType != "list" { + dbXpath = prefixPath + "/" + entry.Name + } + xDbSpecMap[dbXpath] = new(dbInfo) + xDbSpecMap[dbXpath].dbEntry = entry + xDbSpecMap[dbXpath].fieldType = entryType + if entryType == "list" { + xDbSpecMap[dbXpath].dbIndex = db.ConfigDB + } + } - var childList []string - for _, k := range entry.DirOKeys { - childList = append(childList, k) - } + var childList []string + for _, k := range entry.DirOKeys { + childList = append(childList, k) + } - if entryType == "container" && trkTpCnt { - xDbSpecOrdTblMap[moduleNm] = childList - log.Info("xDbSpecOrdTblMap after appending ", xDbSpecOrdTblMap) - trkTpCnt = false - } + if entryType == "container" && trkTpCnt { + xDbSpecOrdTblMap[moduleNm] = childList + log.Info("xDbSpecOrdTblMap after appending ", xDbSpecOrdTblMap) + trkTpCnt = false + } - for _, child := range childList { - childPath := prefixPath + "/" + entry.Dir[child].Name - dbMapFill(prefixPath, childPath, moduleNm, trkTpCnt, xDbSpecMap, entry.Dir[child]) - } + for _, child := range childList { + childPath := prefixPath + "/" + entry.Dir[child].Name + dbMapFill(prefixPath, childPath, moduleNm, trkTpCnt, xDbSpecMap, entry.Dir[child]) + } } /* Build redis db lookup map */ @@ -359,6 +364,84 @@ func annotToDbMapBuild(annotEntries []*yang.Entry) { mapPrint(xYangSpecMap, "/tmp/annotSpec.txt") } +func annotDbSpecMapFill(xDbSpecMap map[string]*dbInfo, dbXpath string, entry *yang.Entry) error { + var err error + var dbXpathData *dbInfo + var ok bool + + //Currently sonic-yang annotation is supported for "list" type only. + listName := strings.Split(dbXpath, "/") + if len(listName) < 2 { + log.Errorf("Invalid list xpath length(%v) \r\n", dbXpath) + return err + } + dbXpathData, ok = xDbSpecMap[listName[2]] + if !ok { + log.Errorf("DB spec-map data not found(%v) \r\n", dbXpath) + return err + } + log.Infof("Annotate dbSpecMap for (%v)(listName:%v)\r\n", dbXpath, listName[2]) + dbXpathData.dbIndex = db.ConfigDB // default value + + /* fill table with cvl yang extension data. */ + if entry != nil && len(entry.Exts) > 0 { + for _, ext := range entry.Exts { + dataTagArr := strings.Split(ext.Keyword, ":") + tagType := dataTagArr[len(dataTagArr)-1] + switch tagType { + case "key-name" : + if dbXpathData.keyName == nil { + dbXpathData.keyName = new(string) + } + *dbXpathData.keyName = ext.NName() + case "db-name" : + if ext.NName() == "APPL_DB" { + dbXpathData.dbIndex = db.ApplDB + } else if ext.NName() == "ASIC_DB" { + dbXpathData.dbIndex = db.AsicDB + } else if ext.NName() == "COUNTERS_DB" { + dbXpathData.dbIndex = db.CountersDB + } else if ext.NName() == "LOGLEVEL_DB" { + dbXpathData.dbIndex = db.LogLevelDB + } else if ext.NName() == "CONFIG_DB" { + dbXpathData.dbIndex = db.ConfigDB + } else if ext.NName() == "FLEX_COUNTER_DB" { + dbXpathData.dbIndex = db.FlexCounterDB + } else if ext.NName() == "STATE_DB" { + dbXpathData.dbIndex = db.StateDB + } else { + dbXpathData.dbIndex = db.ConfigDB + } + default : + } + } + } + + dbMapPrint("/tmp/dbSpecMapFull.txt") + return err +} + +func annotDbSpecMap(annotEntries []*yang.Entry) { + if annotEntries == nil || xDbSpecMap == nil { + return + } + for _, e := range annotEntries { + if e != nil && len(e.Deviations) > 0 { + for _, d := range e.Deviations { + xpath := xpathFromDevCreate(d.Name) + xpath = "/" + strings.Replace(e.Name, "-annot", "", -1) + ":" + xpath + for i, deviate := range d.Deviate { + if i == 2 { + for _, ye := range deviate { + annotDbSpecMapFill(xDbSpecMap, xpath, ye) + } + } + } + } + } + } +} + /* Debug function to print the yang xpath lookup map */ func mapPrint(inMap map[string]*yangXpathInfo, fileName string) { fp, err := os.Create(fileName) @@ -405,8 +488,8 @@ func mapPrint(inMap map[string]*yangXpathInfo, fileName string) { } /* Debug function to print redis db lookup map */ -func dbMapPrint() { - fp, err := os.Create("/tmp/dbTmplt.txt") +func dbMapPrint( fname string) { + fp, err := os.Create(fname) if err != nil { return } @@ -414,9 +497,14 @@ func dbMapPrint() { fmt.Fprintf (fp, "-----------------------------------------------------------------\r\n") for k, v := range xDbSpecMap { fmt.Fprintf(fp, " field:%v \r\n", k) - fmt.Fprintf(fp, " type :%v \r\n", v.fieldType) - fmt.Fprintf(fp, " Yang :%v \r\n", v.yangXpath) - fmt.Fprintf(fp, " DB :%v \r\n", v.dbEntry) + fmt.Fprintf(fp, " type :%v \r\n", v.fieldType) + fmt.Fprintf(fp, " db-type :%v \r\n", v.dbIndex) + fmt.Fprintf(fp, " KeyName: ") + if v.keyName != nil { + fmt.Fprintf(fp, "%v", *v.keyName) + } + fmt.Fprintf(fp, "\r\n oc-yang :%v \r\n", v.yangXpath) + fmt.Fprintf(fp, " cvl-yang :%v \r\n", v.dbEntry) fmt.Fprintf (fp, "-----------------------------------------------------------------\r\n") } From 021209a571b95d4129d9c4cca9e74ab6698b6399 Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Wed, 25 Sep 2019 18:19:55 -0700 Subject: [PATCH 171/214] Fill cvl KeySpec with DbName read from annotation --- src/translib/transformer/xlate.go | 18 +++++++++-------- src/translib/transformer/xlate_to_db.go | 27 +++++++++++++------------ src/translib/transformer/xspec.go | 2 +- 3 files changed, 25 insertions(+), 22 deletions(-) diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index 77007c30fc..844fb9b7a8 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -116,12 +116,12 @@ func XlateUriToKeySpec(uri string, ygRoot *ygot.GoStruct, t *interface{}) (*[]Ke // In case of CVL yang, the tablename and key info is available in the xpath if isCvlYang(uri) { /* Extract the xpath and key from input xpath */ - yangXpath, keyStr, tableName := sonicXpathKeyExtract(uri) - retdbFormat = fillCvlKeySpec(yangXpath, tableName, keyStr) + xpath, keyStr, tableName := sonicXpathKeyExtract(uri) + retdbFormat = fillCvlKeySpec(xpath, tableName, keyStr) } else { /* Extract the xpath and key from input xpath */ - yangXpath, keyStr, _ := xpathKeyExtract(nil, ygRoot, 0, uri) - retdbFormat = FillKeySpecs(yangXpath, keyStr, &retdbFormat) + xpath, keyStr, _ := xpathKeyExtract(nil, ygRoot, 0, uri) + retdbFormat = FillKeySpecs(xpath, keyStr, &retdbFormat) } return &retdbFormat, err @@ -170,29 +170,31 @@ func FillKeySpecs(yangXpath string , keyStr string, retdbFormat *[]KeySpec) ([]K return *retdbFormat } -func fillCvlKeySpec(yangXpath string , tableName string, keyStr string) ( []KeySpec ) { +func fillCvlKeySpec(xpath string , tableName string, keyStr string) ( []KeySpec ) { var retdbFormat = make([]KeySpec, 0) if tableName != "" { dbFormat := KeySpec{} dbFormat.Ts.Name = tableName - dbFormat.dbNum = db.ConfigDB + cdb := xDbSpecMap[xpath].dbIndex + dbFormat.dbNum = cdb if keyStr != "" { dbFormat.Key.Comp = append(dbFormat.Key.Comp, keyStr) } retdbFormat = append(retdbFormat, dbFormat) } else { // If table name not available in xpath get top container name - tokens:= strings.Split(yangXpath, ":") + tokens:= strings.Split(xpath, ":") container := "/" + tokens[len(tokens)-1] if xDbSpecMap[container] != nil { dbInfo := xDbSpecMap[container] if dbInfo.fieldType == "container" { for dir, _ := range dbInfo.dbEntry.Dir { + cdb := xDbSpecMap[dir].dbIndex dbFormat := KeySpec{} dbFormat.Ts.Name = dir - dbFormat.dbNum = db.ConfigDB + dbFormat.dbNum = cdb retdbFormat = append(retdbFormat, dbFormat) } } diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index 00c5f0d495..6b21d71f74 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -83,6 +83,19 @@ func mapFillData(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, dbKey st if xpathInfo.isKey { return nil } + + tableName := "" + if xpathInfo.xfmrTbl != nil { + inParams := formXfmrInputRequest(d, dbs, db.MaxDB, ygRoot, uri, oper, "", nil, "") + // expecting only one table name from tbl-xfmr + tableName, err = tblNameFromTblXfmrGet(*xYangSpecMap[xpath].xfmrTbl, inParams) + if err != nil { + return err + } + } else { + tableName = *xpathInfo.tableName + } + if len(xpathInfo.xfmrFunc) > 0 { uri = uri + "/" + name @@ -114,7 +127,7 @@ func mapFillData(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, dbKey st retData := ret[0].Interface().(map[string]string) log.Info("Transformer function :", xpathInfo.xfmrFunc, " Xpath: ", xpath, " retData: ", retData) for f, v := range retData { - dataToDBMapAdd(*xpathInfo.tableName, dbKey, result, f, v) + dataToDBMapAdd(tableName, dbKey, result, f, v) } return nil } @@ -152,18 +165,6 @@ func mapFillData(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, dbKey st } } - tableName := "" - if xpathInfo.xfmrTbl != nil { - inParams := formXfmrInputRequest(d, dbs, db.MaxDB, ygRoot, uri, oper, "", nil, "") - // expecting only one table name from tbl-xfmr - tableName, err = tblNameFromTblXfmrGet(*xYangSpecMap[xpath].xfmrTbl, inParams) - if err != nil { - return err - } - } else { - tableName = *xpathInfo.tableName - } - dataToDBMapAdd(tableName, dbKey, result, fieldName, valueStr) log.Infof("TblName: \"%v\", key: \"%v\", field: \"%v\", valueStr: \"%v\".", tableName, dbKey, fieldName, valueStr) diff --git a/src/translib/transformer/xspec.go b/src/translib/transformer/xspec.go index dde3804918..3327805223 100644 --- a/src/translib/transformer/xspec.go +++ b/src/translib/transformer/xspec.go @@ -371,7 +371,7 @@ func annotDbSpecMapFill(xDbSpecMap map[string]*dbInfo, dbXpath string, entry *ya //Currently sonic-yang annotation is supported for "list" type only. listName := strings.Split(dbXpath, "/") - if len(listName) < 2 { + if len(listName) < 3 { log.Errorf("Invalid list xpath length(%v) \r\n", dbXpath) return err } From e1d4cf7378fafcdc625cf5a8203e466215ef51bc Mon Sep 17 00:00:00 2001 From: Partha Dutta Date: Thu, 26 Sep 2019 23:27:43 +0530 Subject: [PATCH 172/214] More changes for CVL YANG --- models/yang/sonic/Makefile | 53 ++ .../sonic/common/ietf/ietf-inet-types.yang | 457 +++++++++++++++++ .../sonic/common/ietf/ietf-yang-types.yang | 474 ++++++++++++++++++ .../yang/sonic/common}/sonic-common.yang | 0 .../yang/sonic/common}/sonic-extension.yang | 0 .../yang/sonic}/sonic-acl.yang | 4 - .../yang/sonic}/sonic-interface.yang | 15 + .../yang/sonic}/sonic-mirror-session.yang | 0 .../yang/sonic}/sonic-port.yang | 0 src/cvl/cvl.go | 89 +++- src/cvl/cvl_api.go | 3 +- src/cvl/schema/Makefile | 40 +- src/cvl/testdata/schema/Makefile | 18 +- ...-acl-dev.yang => sonic-acl-deviation.yang} | 4 +- .../testdata/schema/sonic-dscp-tc-map.yang | 4 - ...lan-dev.yang => sonic-vlan-deviation.yang} | 4 +- tools/pyang/pyang_plugins/yin_cvl.py | 6 +- 17 files changed, 1129 insertions(+), 42 deletions(-) create mode 100644 models/yang/sonic/Makefile create mode 100644 models/yang/sonic/common/ietf/ietf-inet-types.yang create mode 100644 models/yang/sonic/common/ietf/ietf-yang-types.yang rename {src/cvl/schema => models/yang/sonic/common}/sonic-common.yang (100%) rename {src/cvl/schema => models/yang/sonic/common}/sonic-extension.yang (100%) rename {src/cvl/schema => models/yang/sonic}/sonic-acl.yang (98%) rename {src/cvl/schema => models/yang/sonic}/sonic-interface.yang (74%) rename {src/cvl/schema => models/yang/sonic}/sonic-mirror-session.yang (100%) rename {src/cvl/schema => models/yang/sonic}/sonic-port.yang (100%) rename src/cvl/testdata/schema/{sonic-acl-dev.yang => sonic-acl-deviation.yang} (85%) rename src/cvl/testdata/schema/{sonic-vlan-dev.yang => sonic-vlan-deviation.yang} (83%) diff --git a/models/yang/sonic/Makefile b/models/yang/sonic/Makefile new file mode 100644 index 0000000000..9141ff952a --- /dev/null +++ b/models/yang/sonic/Makefile @@ -0,0 +1,53 @@ +TOPDIR := ../../../ +SONIC_YANGAPI_DIR := $(TOPDIR)/build/yaml +SONIC_YANGDIR := $(TOPDIR)/models/yang/sonic +SONIC_YANGDIR_DEVIATION := $(TOPDIR)/models/yang/sonic/deviation +SONIC_YANGDIR_COMMON := $(TOPDIR)/models/yang/sonic/common +SONIC_YANGDIR_COMMON_IETF := $(TOPDIR)/models/yang/sonic/common/ietf +SONIC_YANG_MOD_FILES := $(shell find $(SONIC_YANGDIR) -maxdepth 1 -name '*.yang' | sort) +SONIC_YANG_COMMON_FILES := $(shell find $(SONIC_YANGDIR_COMMON) -name '*.yang' | sort) +SONIC_YANG_COMMON_FILES += $(shell find $(SONIC_YANGDIR_COMMON_IETF) -name '*.yang' | sort) + +SONIC_TOOLS_DIR := $(TOPDIR)/tools +SONIC_PYANG_DIR := $(SONIC_TOOLS_DIR)/pyang +SONIC_PYANG_PLUGIN_DIR := $(SONIC_PYANG_DIR)/pyang_plugins +SONIC_PYANG_BIN := pyang + +all: yamlGen allyangs.tree allyangs_tree.html + +#yamlGen: $(SONIC_YANGAPI_DIR)/.done + +allyangs.tree: $(SONIC_YANG_MOD_FILES) $(SONIC_YANG_COMMON_FILES) + $(SONIC_PYANG_BIN) \ + -f tree \ + -o $(SONIC_YANGDIR)/$@ \ + -p $(SONIC_YANGDIR_COMMON):$(SONIC_YANGDIR) \ + $(SONIC_YANG_MOD_FILES) + @echo "+++++ Generation of YANG tree for Sonic Yang modules completed +++++" + +allyangs_tree.html: $(SONIC_YANG_MOD_FILES) $(SONIC_YANG_COMMON_FILES) + $(SONIC_PYANG_BIN) \ + -f jstree \ + -o $(SONIC_YANGDIR)/$@ \ + -p $(SONIC_YANGDIR_COMMON):$(SONIC_YANGDIR) \ + $(SONIC_YANG_MOD_FILES) + @echo "+++++ Generation of HTML tree for Sonic Yang modules completed +++++" + +#====================================================================== +# Generate YAML files for SONiC YANG modules +#====================================================================== +yamlGen: + @echo "+++++ Generating YAML files for Sonic Yang modules +++++" + mkdir -p $(SONIC_YANGAPI_DIR) + $(SONIC_PYANG_BIN) \ + -f swaggerapi \ + --outdir $(SONIC_YANGAPI_DIR) \ + --plugindir $(SONIC_PYANG_PLUGIN_DIR) \ + -p $(SONIC_YANGDIR_COMMON):$(SONIC_YANGDIR) \ + $(SONIC_YANG_MOD_FILES) + @echo "+++++ Generation of YAML files for Sonic Yang modules completed +++++" + +clean: + @echo "Removing files ..." + rm -rf $(SONIC_YANGAPI_DIR) + rm -rf allyangs.tree allyangs_tree.html diff --git a/models/yang/sonic/common/ietf/ietf-inet-types.yang b/models/yang/sonic/common/ietf/ietf-inet-types.yang new file mode 100644 index 0000000000..2f14270dec --- /dev/null +++ b/models/yang/sonic/common/ietf/ietf-inet-types.yang @@ -0,0 +1,457 @@ +module ietf-inet-types { + + namespace "urn:ietf:params:xml:ns:yang:ietf-inet-types"; + prefix "inet"; + + organization + "IETF NETMOD (NETCONF Data Modeling Language) Working Group"; + + contact + "WG Web: + WG List: + + WG Chair: David Kessens + + + WG Chair: Juergen Schoenwaelder + + + Editor: Juergen Schoenwaelder + "; + + description + "This module contains a collection of generally useful derived + YANG data types for Internet addresses and related things. + + Copyright (c) 2013 IETF Trust and the persons identified as + authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Simplified BSD License + set forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (http://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC 6991; see + the RFC itself for full legal notices."; + + revision 2013-07-15 { + description + "This revision adds the following new data types: + - ip-address-no-zone + - ipv4-address-no-zone + - ipv6-address-no-zone"; + reference + "RFC 6991: Common YANG Data Types"; + } + + revision 2010-09-24 { + description + "Initial revision."; + reference + "RFC 6021: Common YANG Data Types"; + } + + /*** collection of types related to protocol fields ***/ + + typedef ip-version { + type enumeration { + enum unknown { + value "0"; + description + "An unknown or unspecified version of the Internet + protocol."; + } + enum ipv4 { + value "1"; + description + "The IPv4 protocol as defined in RFC 791."; + } + enum ipv6 { + value "2"; + description + "The IPv6 protocol as defined in RFC 2460."; + } + } + description + "This value represents the version of the IP protocol. + + In the value set and its semantics, this type is equivalent + to the InetVersion textual convention of the SMIv2."; + reference + "RFC 791: Internet Protocol + RFC 2460: Internet Protocol, Version 6 (IPv6) Specification + RFC 4001: Textual Conventions for Internet Network Addresses"; + } + + typedef dscp { + type uint8 { + range "0..63"; + } + description + "The dscp type represents a Differentiated Services Code Point + that may be used for marking packets in a traffic stream. + In the value set and its semantics, this type is equivalent + to the Dscp textual convention of the SMIv2."; + reference + "RFC 3289: Management Information Base for the Differentiated + Services Architecture + RFC 2474: Definition of the Differentiated Services Field + (DS Field) in the IPv4 and IPv6 Headers + RFC 2780: IANA Allocation Guidelines For Values In + the Internet Protocol and Related Headers"; + } + + typedef ipv6-flow-label { + type uint32 { + range "0..1048575"; + } + description + "The ipv6-flow-label type represents the flow identifier or Flow + Label in an IPv6 packet header that may be used to + discriminate traffic flows. + + In the value set and its semantics, this type is equivalent + to the IPv6FlowLabel textual convention of the SMIv2."; + reference + "RFC 3595: Textual Conventions for IPv6 Flow Label + RFC 2460: Internet Protocol, Version 6 (IPv6) Specification"; + } + + typedef port-number { + type uint16 { + range "0..65535"; + } + description + "The port-number type represents a 16-bit port number of an + Internet transport-layer protocol such as UDP, TCP, DCCP, or + SCTP. Port numbers are assigned by IANA. A current list of + all assignments is available from . + + Note that the port number value zero is reserved by IANA. In + situations where the value zero does not make sense, it can + be excluded by subtyping the port-number type. + In the value set and its semantics, this type is equivalent + to the InetPortNumber textual convention of the SMIv2."; + reference + "RFC 768: User Datagram Protocol + RFC 793: Transmission Control Protocol + RFC 4960: Stream Control Transmission Protocol + RFC 4340: Datagram Congestion Control Protocol (DCCP) + RFC 4001: Textual Conventions for Internet Network Addresses"; + } + + /*** collection of types related to autonomous systems ***/ + + typedef as-number { + type uint32; + description + "The as-number type represents autonomous system numbers + which identify an Autonomous System (AS). An AS is a set + of routers under a single technical administration, using + an interior gateway protocol and common metrics to route + packets within the AS, and using an exterior gateway + protocol to route packets to other ASes. IANA maintains + the AS number space and has delegated large parts to the + regional registries. + + Autonomous system numbers were originally limited to 16 + bits. BGP extensions have enlarged the autonomous system + number space to 32 bits. This type therefore uses an uint32 + base type without a range restriction in order to support + a larger autonomous system number space. + + In the value set and its semantics, this type is equivalent + to the InetAutonomousSystemNumber textual convention of + the SMIv2."; + reference + "RFC 1930: Guidelines for creation, selection, and registration + of an Autonomous System (AS) + RFC 4271: A Border Gateway Protocol 4 (BGP-4) + RFC 4001: Textual Conventions for Internet Network Addresses + RFC 6793: BGP Support for Four-Octet Autonomous System (AS) + Number Space"; + } + + /*** collection of types related to IP addresses and hostnames ***/ + + typedef ip-address { + type union { + type inet:ipv4-address; + type inet:ipv6-address; + } + description + "The ip-address type represents an IP address and is IP + version neutral. The format of the textual representation + implies the IP version. This type supports scoped addresses + by allowing zone identifiers in the address format."; + reference + "RFC 4007: IPv6 Scoped Address Architecture"; + } + + typedef ipv4-address { + type string { + pattern + '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}' + + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])' + + '(%[\p{N}\p{L}]+)?'; + } + description + "The ipv4-address type represents an IPv4 address in + dotted-quad notation. The IPv4 address may include a zone + index, separated by a % sign. + + The zone index is used to disambiguate identical address + values. For link-local addresses, the zone index will + typically be the interface index number or the name of an + interface. If the zone index is not present, the default + zone of the device will be used. + + The canonical format for the zone index is the numerical + format"; + } + + typedef ipv6-address { + type string { + pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}' + + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|' + + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}' + + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))' + + '(%[\p{N}\p{L}]+)?'; + pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|' + + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)' + + '(%.+)?'; + } + description + "The ipv6-address type represents an IPv6 address in full, + mixed, shortened, and shortened-mixed notation. The IPv6 + address may include a zone index, separated by a % sign. + + The zone index is used to disambiguate identical address + values. For link-local addresses, the zone index will + typically be the interface index number or the name of an + interface. If the zone index is not present, the default + zone of the device will be used. + + The canonical format of IPv6 addresses uses the textual + representation defined in Section 4 of RFC 5952. The + canonical format for the zone index is the numerical + format as described in Section 11.2 of RFC 4007."; + reference + "RFC 4291: IP Version 6 Addressing Architecture + RFC 4007: IPv6 Scoped Address Architecture + RFC 5952: A Recommendation for IPv6 Address Text + Representation"; + } + + typedef ip-address-no-zone { + type union { + type inet:ipv4-address-no-zone; + type inet:ipv6-address-no-zone; + } + description + "The ip-address-no-zone type represents an IP address and is + IP version neutral. The format of the textual representation + implies the IP version. This type does not support scoped + addresses since it does not allow zone identifiers in the + address format."; + reference + "RFC 4007: IPv6 Scoped Address Architecture"; + } + + typedef ipv4-address-no-zone { + type inet:ipv4-address { + pattern '[0-9\.]*'; + } + description + "An IPv4 address without a zone index. This type, derived from + ipv4-address, may be used in situations where the zone is + known from the context and hence no zone index is needed."; + } + + typedef ipv6-address-no-zone { + type inet:ipv6-address { + pattern '[0-9a-fA-F:\.]*'; + } + description + "An IPv6 address without a zone index. This type, derived from + ipv6-address, may be used in situations where the zone is + known from the context and hence no zone index is needed."; + reference + "RFC 4291: IP Version 6 Addressing Architecture + RFC 4007: IPv6 Scoped Address Architecture + RFC 5952: A Recommendation for IPv6 Address Text + Representation"; + } + + typedef ip-prefix { + type union { + type inet:ipv4-prefix; + type inet:ipv6-prefix; + } + description + "The ip-prefix type represents an IP prefix and is IP + version neutral. The format of the textual representations + implies the IP version."; + } + + typedef ipv4-prefix { + type string { + pattern + '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}' + + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])' + + '/(([0-9])|([1-2][0-9])|(3[0-2]))'; + } + description + "The ipv4-prefix type represents an IPv4 address prefix. + The prefix length is given by the number following the + slash character and must be less than or equal to 32. + + A prefix length value of n corresponds to an IP address + mask that has n contiguous 1-bits from the most + significant bit (MSB) and all other bits set to 0. + + The canonical format of an IPv4 prefix has all bits of + the IPv4 address set to zero that are not part of the + IPv4 prefix."; + } + + typedef ipv6-prefix { + type string { + pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}' + + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|' + + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}' + + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))' + + '(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))'; + pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|' + + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)' + + '(/.+)'; + } + description + "The ipv6-prefix type represents an IPv6 address prefix. + The prefix length is given by the number following the + slash character and must be less than or equal to 128. + + A prefix length value of n corresponds to an IP address + mask that has n contiguous 1-bits from the most + significant bit (MSB) and all other bits set to 0. + + The IPv6 address should have all bits that do not belong + to the prefix set to zero. + + The canonical format of an IPv6 prefix has all bits of + the IPv6 address set to zero that are not part of the + IPv6 prefix. Furthermore, the IPv6 address is represented + as defined in Section 4 of RFC 5952."; + reference + "RFC 5952: A Recommendation for IPv6 Address Text + Representation"; + } + + /*** collection of domain name and URI types ***/ + + typedef domain-name { + type string { + length "1..253"; + pattern + '((([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.)*' + + '([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.?)' + + '|\.'; + } + description + "The domain-name type represents a DNS domain name. The + name SHOULD be fully qualified whenever possible. + + Internet domain names are only loosely specified. Section + 3.5 of RFC 1034 recommends a syntax (modified in Section + 2.1 of RFC 1123). The pattern above is intended to allow + for current practice in domain name use, and some possible + future expansion. It is designed to hold various types of + domain names, including names used for A or AAAA records + (host names) and other records, such as SRV records. Note + that Internet host names have a stricter syntax (described + in RFC 952) than the DNS recommendations in RFCs 1034 and + 1123, and that systems that want to store host names in + schema nodes using the domain-name type are recommended to + adhere to this stricter standard to ensure interoperability. + + The encoding of DNS names in the DNS protocol is limited + to 255 characters. Since the encoding consists of labels + prefixed by a length bytes and there is a trailing NULL + byte, only 253 characters can appear in the textual dotted + notation. + + The description clause of schema nodes using the domain-name + type MUST describe when and how these names are resolved to + IP addresses. Note that the resolution of a domain-name value + may require to query multiple DNS records (e.g., A for IPv4 + and AAAA for IPv6). The order of the resolution process and + which DNS record takes precedence can either be defined + explicitly or may depend on the configuration of the + resolver. + + Domain-name values use the US-ASCII encoding. Their canonical + format uses lowercase US-ASCII characters. Internationalized + domain names MUST be A-labels as per RFC 5890."; + reference + "RFC 952: DoD Internet Host Table Specification + RFC 1034: Domain Names - Concepts and Facilities + RFC 1123: Requirements for Internet Hosts -- Application + and Support + RFC 2782: A DNS RR for specifying the location of services + (DNS SRV) + RFC 5890: Internationalized Domain Names in Applications + (IDNA): Definitions and Document Framework"; + } + + typedef host { + type union { + type inet:ip-address; + type inet:domain-name; + } + description + "The host type represents either an IP address or a DNS + domain name."; + } + + typedef uri { + type string; + description + "The uri type represents a Uniform Resource Identifier + (URI) as defined by STD 66. + + Objects using the uri type MUST be in US-ASCII encoding, + and MUST be normalized as described by RFC 3986 Sections + 6.2.1, 6.2.2.1, and 6.2.2.2. All unnecessary + percent-encoding is removed, and all case-insensitive + characters are set to lowercase except for hexadecimal + digits, which are normalized to uppercase as described in + Section 6.2.2.1. + + The purpose of this normalization is to help provide + unique URIs. Note that this normalization is not + sufficient to provide uniqueness. Two URIs that are + textually distinct after this normalization may still be + equivalent. + + Objects using the uri type may restrict the schemes that + they permit. For example, 'data:' and 'urn:' schemes + might not be appropriate. + + A zero-length URI is not a valid URI. This can be used to + express 'URI absent' where required. + + In the value set and its semantics, this type is equivalent + to the Uri SMIv2 textual convention defined in RFC 5017."; + reference + "RFC 3986: Uniform Resource Identifier (URI): Generic Syntax + RFC 3305: Report from the Joint W3C/IETF URI Planning Interest + Group: Uniform Resource Identifiers (URIs), URLs, + and Uniform Resource Names (URNs): Clarifications + and Recommendations + RFC 5017: MIB Textual Conventions for Uniform Resource + Identifiers (URIs)"; + } + +} diff --git a/models/yang/sonic/common/ietf/ietf-yang-types.yang b/models/yang/sonic/common/ietf/ietf-yang-types.yang new file mode 100644 index 0000000000..ee58fa3ab0 --- /dev/null +++ b/models/yang/sonic/common/ietf/ietf-yang-types.yang @@ -0,0 +1,474 @@ +module ietf-yang-types { + + namespace "urn:ietf:params:xml:ns:yang:ietf-yang-types"; + prefix "yang"; + + organization + "IETF NETMOD (NETCONF Data Modeling Language) Working Group"; + + contact + "WG Web: + WG List: + + WG Chair: David Kessens + + + WG Chair: Juergen Schoenwaelder + + + Editor: Juergen Schoenwaelder + "; + + description + "This module contains a collection of generally useful derived + YANG data types. + + Copyright (c) 2013 IETF Trust and the persons identified as + authors of the code. All rights reserved. + + Redistribution and use in source and binary forms, with or + without modification, is permitted pursuant to, and subject + to the license terms contained in, the Simplified BSD License + set forth in Section 4.c of the IETF Trust's Legal Provisions + Relating to IETF Documents + (http://trustee.ietf.org/license-info). + + This version of this YANG module is part of RFC 6991; see + the RFC itself for full legal notices."; + + revision 2013-07-15 { + description + "This revision adds the following new data types: + - yang-identifier + - hex-string + - uuid + - dotted-quad"; + reference + "RFC 6991: Common YANG Data Types"; + } + + revision 2010-09-24 { + description + "Initial revision."; + reference + "RFC 6021: Common YANG Data Types"; + } + + /*** collection of counter and gauge types ***/ + + typedef counter32 { + type uint32; + description + "The counter32 type represents a non-negative integer + that monotonically increases until it reaches a + maximum value of 2^32-1 (4294967295 decimal), when it + wraps around and starts increasing again from zero. + + Counters have no defined 'initial' value, and thus, a + single value of a counter has (in general) no information + content. Discontinuities in the monotonically increasing + value normally occur at re-initialization of the + management system, and at other times as specified in the + description of a schema node using this type. If such + other times can occur, for example, the creation of + a schema node of type counter32 at times other than + re-initialization, then a corresponding schema node + should be defined, with an appropriate type, to indicate + the last discontinuity. + + The counter32 type should not be used for configuration + schema nodes. A default statement SHOULD NOT be used in + combination with the type counter32. + + In the value set and its semantics, this type is equivalent + to the Counter32 type of the SMIv2."; + reference + "RFC 2578: Structure of Management Information Version 2 + (SMIv2)"; + } + + typedef zero-based-counter32 { + type yang:counter32; + default "0"; + description + "The zero-based-counter32 type represents a counter32 + that has the defined 'initial' value zero. + + A schema node of this type will be set to zero (0) on creation + and will thereafter increase monotonically until it reaches + a maximum value of 2^32-1 (4294967295 decimal), when it + wraps around and starts increasing again from zero. + + Provided that an application discovers a new schema node + of this type within the minimum time to wrap, it can use the + 'initial' value as a delta. It is important for a management + station to be aware of this minimum time and the actual time + between polls, and to discard data if the actual time is too + long or there is no defined minimum time. + + In the value set and its semantics, this type is equivalent + to the ZeroBasedCounter32 textual convention of the SMIv2."; + reference + "RFC 4502: Remote Network Monitoring Management Information + Base Version 2"; + } + + typedef counter64 { + type uint64; + description + "The counter64 type represents a non-negative integer + that monotonically increases until it reaches a + maximum value of 2^64-1 (18446744073709551615 decimal), + when it wraps around and starts increasing again from zero. + + Counters have no defined 'initial' value, and thus, a + single value of a counter has (in general) no information + content. Discontinuities in the monotonically increasing + value normally occur at re-initialization of the + management system, and at other times as specified in the + description of a schema node using this type. If such + other times can occur, for example, the creation of + a schema node of type counter64 at times other than + re-initialization, then a corresponding schema node + should be defined, with an appropriate type, to indicate + the last discontinuity. + + The counter64 type should not be used for configuration + schema nodes. A default statement SHOULD NOT be used in + combination with the type counter64. + + In the value set and its semantics, this type is equivalent + to the Counter64 type of the SMIv2."; + reference + "RFC 2578: Structure of Management Information Version 2 + (SMIv2)"; + } + + typedef zero-based-counter64 { + type yang:counter64; + default "0"; + description + "The zero-based-counter64 type represents a counter64 that + has the defined 'initial' value zero. + + A schema node of this type will be set to zero (0) on creation + and will thereafter increase monotonically until it reaches + a maximum value of 2^64-1 (18446744073709551615 decimal), + when it wraps around and starts increasing again from zero. + + Provided that an application discovers a new schema node + of this type within the minimum time to wrap, it can use the + 'initial' value as a delta. It is important for a management + station to be aware of this minimum time and the actual time + between polls, and to discard data if the actual time is too + long or there is no defined minimum time. + + In the value set and its semantics, this type is equivalent + to the ZeroBasedCounter64 textual convention of the SMIv2."; + reference + "RFC 2856: Textual Conventions for Additional High Capacity + Data Types"; + } + + typedef gauge32 { + type uint32; + description + "The gauge32 type represents a non-negative integer, which + may increase or decrease, but shall never exceed a maximum + value, nor fall below a minimum value. The maximum value + cannot be greater than 2^32-1 (4294967295 decimal), and + the minimum value cannot be smaller than 0. The value of + a gauge32 has its maximum value whenever the information + being modeled is greater than or equal to its maximum + value, and has its minimum value whenever the information + being modeled is smaller than or equal to its minimum value. + If the information being modeled subsequently decreases + below (increases above) the maximum (minimum) value, the + gauge32 also decreases (increases). + + In the value set and its semantics, this type is equivalent + to the Gauge32 type of the SMIv2."; + reference + "RFC 2578: Structure of Management Information Version 2 + (SMIv2)"; + } + + typedef gauge64 { + type uint64; + description + "The gauge64 type represents a non-negative integer, which + may increase or decrease, but shall never exceed a maximum + value, nor fall below a minimum value. The maximum value + cannot be greater than 2^64-1 (18446744073709551615), and + the minimum value cannot be smaller than 0. The value of + a gauge64 has its maximum value whenever the information + being modeled is greater than or equal to its maximum + value, and has its minimum value whenever the information + being modeled is smaller than or equal to its minimum value. + If the information being modeled subsequently decreases + below (increases above) the maximum (minimum) value, the + gauge64 also decreases (increases). + + In the value set and its semantics, this type is equivalent + to the CounterBasedGauge64 SMIv2 textual convention defined + in RFC 2856"; + reference + "RFC 2856: Textual Conventions for Additional High Capacity + Data Types"; + } + + /*** collection of identifier-related types ***/ + + typedef object-identifier { + type string { + pattern '(([0-1](\.[1-3]?[0-9]))|(2\.(0|([1-9]\d*))))' + + '(\.(0|([1-9]\d*)))*'; + } + description + "The object-identifier type represents administratively + assigned names in a registration-hierarchical-name tree. + + Values of this type are denoted as a sequence of numerical + non-negative sub-identifier values. Each sub-identifier + value MUST NOT exceed 2^32-1 (4294967295). Sub-identifiers + are separated by single dots and without any intermediate + whitespace. + + The ASN.1 standard restricts the value space of the first + sub-identifier to 0, 1, or 2. Furthermore, the value space + of the second sub-identifier is restricted to the range + 0 to 39 if the first sub-identifier is 0 or 1. Finally, + the ASN.1 standard requires that an object identifier + has always at least two sub-identifiers. The pattern + captures these restrictions. + + Although the number of sub-identifiers is not limited, + module designers should realize that there may be + implementations that stick with the SMIv2 limit of 128 + sub-identifiers. + + This type is a superset of the SMIv2 OBJECT IDENTIFIER type + since it is not restricted to 128 sub-identifiers. Hence, + this type SHOULD NOT be used to represent the SMIv2 OBJECT + IDENTIFIER type; the object-identifier-128 type SHOULD be + used instead."; + reference + "ISO9834-1: Information technology -- Open Systems + Interconnection -- Procedures for the operation of OSI + Registration Authorities: General procedures and top + arcs of the ASN.1 Object Identifier tree"; + } + + typedef object-identifier-128 { + type object-identifier { + pattern '\d*(\.\d*){1,127}'; + } + description + "This type represents object-identifiers restricted to 128 + sub-identifiers. + + In the value set and its semantics, this type is equivalent + to the OBJECT IDENTIFIER type of the SMIv2."; + reference + "RFC 2578: Structure of Management Information Version 2 + (SMIv2)"; + } + + typedef yang-identifier { + type string { + length "1..max"; + pattern '[a-zA-Z_][a-zA-Z0-9\-_.]*'; + pattern '.|..|[^xX].*|.[^mM].*|..[^lL].*'; + } + description + "A YANG identifier string as defined by the 'identifier' + rule in Section 12 of RFC 6020. An identifier must + start with an alphabetic character or an underscore + followed by an arbitrary sequence of alphabetic or + numeric characters, underscores, hyphens, or dots. + + A YANG identifier MUST NOT start with any possible + combination of the lowercase or uppercase character + sequence 'xml'."; + reference + "RFC 6020: YANG - A Data Modeling Language for the Network + Configuration Protocol (NETCONF)"; + } + + /*** collection of types related to date and time***/ + + typedef date-and-time { + type string { + pattern '\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?' + + '(Z|[\+\-]\d{2}:\d{2})'; + } + description + "The date-and-time type is a profile of the ISO 8601 + standard for representation of dates and times using the + Gregorian calendar. The profile is defined by the + date-time production in Section 5.6 of RFC 3339. + + The date-and-time type is compatible with the dateTime XML + schema type with the following notable exceptions: + + (a) The date-and-time type does not allow negative years. + + (b) The date-and-time time-offset -00:00 indicates an unknown + time zone (see RFC 3339) while -00:00 and +00:00 and Z + all represent the same time zone in dateTime. + + (c) The canonical format (see below) of data-and-time values + differs from the canonical format used by the dateTime XML + schema type, which requires all times to be in UTC using + the time-offset 'Z'. + + This type is not equivalent to the DateAndTime textual + convention of the SMIv2 since RFC 3339 uses a different + separator between full-date and full-time and provides + higher resolution of time-secfrac. + + The canonical format for date-and-time values with a known time + zone uses a numeric time zone offset that is calculated using + the device's configured known offset to UTC time. A change of + the device's offset to UTC time will cause date-and-time values + to change accordingly. Such changes might happen periodically + in case a server follows automatically daylight saving time + (DST) time zone offset changes. The canonical format for + date-and-time values with an unknown time zone (usually + referring to the notion of local time) uses the time-offset + -00:00."; + reference + "RFC 3339: Date and Time on the Internet: Timestamps + RFC 2579: Textual Conventions for SMIv2 + XSD-TYPES: XML Schema Part 2: Datatypes Second Edition"; + } + + typedef timeticks { + type uint32; + description + "The timeticks type represents a non-negative integer that + represents the time, modulo 2^32 (4294967296 decimal), in + hundredths of a second between two epochs. When a schema + node is defined that uses this type, the description of + the schema node identifies both of the reference epochs. + + In the value set and its semantics, this type is equivalent + to the TimeTicks type of the SMIv2."; + reference + "RFC 2578: Structure of Management Information Version 2 + (SMIv2)"; + } + + typedef timestamp { + type yang:timeticks; + description + "The timestamp type represents the value of an associated + timeticks schema node at which a specific occurrence + happened. The specific occurrence must be defined in the + description of any schema node defined using this type. When + the specific occurrence occurred prior to the last time the + associated timeticks attribute was zero, then the timestamp + value is zero. Note that this requires all timestamp values + to be reset to zero when the value of the associated timeticks + attribute reaches 497+ days and wraps around to zero. + + The associated timeticks schema node must be specified + in the description of any schema node using this type. + + In the value set and its semantics, this type is equivalent + to the TimeStamp textual convention of the SMIv2."; + reference + "RFC 2579: Textual Conventions for SMIv2"; + } + + /*** collection of generic address types ***/ + + typedef phys-address { + type string { + pattern '([0-9a-fA-F]{2}(:[0-9a-fA-F]{2})*)?'; + } + + description + "Represents media- or physical-level addresses represented + as a sequence octets, each octet represented by two hexadecimal + numbers. Octets are separated by colons. The canonical + representation uses lowercase characters. + + In the value set and its semantics, this type is equivalent + to the PhysAddress textual convention of the SMIv2."; + reference + "RFC 2579: Textual Conventions for SMIv2"; + } + + typedef mac-address { + type string { + pattern '[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}'; + } + description + "The mac-address type represents an IEEE 802 MAC address. + The canonical representation uses lowercase characters. + + In the value set and its semantics, this type is equivalent + to the MacAddress textual convention of the SMIv2."; + reference + "IEEE 802: IEEE Standard for Local and Metropolitan Area + Networks: Overview and Architecture + RFC 2579: Textual Conventions for SMIv2"; + } + + /*** collection of XML-specific types ***/ + + typedef xpath1.0 { + type string; + description + "This type represents an XPATH 1.0 expression. + + When a schema node is defined that uses this type, the + description of the schema node MUST specify the XPath + context in which the XPath expression is evaluated."; + reference + "XPATH: XML Path Language (XPath) Version 1.0"; + } + + /*** collection of string types ***/ + + typedef hex-string { + type string { + pattern '([0-9a-fA-F]{2}(:[0-9a-fA-F]{2})*)?'; + } + description + "A hexadecimal string with octets represented as hex digits + separated by colons. The canonical representation uses + lowercase characters."; + } + + typedef uuid { + type string { + pattern '[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-' + + '[0-9a-fA-F]{4}-[0-9a-fA-F]{12}'; + } + description + "A Universally Unique IDentifier in the string representation + defined in RFC 4122. The canonical representation uses + lowercase characters. + + The following is an example of a UUID in string representation: + f81d4fae-7dec-11d0-a765-00a0c91e6bf6 + "; + reference + "RFC 4122: A Universally Unique IDentifier (UUID) URN + Namespace"; + } + + typedef dotted-quad { + type string { + pattern + '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}' + + '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'; + } + description + "An unsigned 32-bit number expressed in the dotted-quad + notation, i.e., four octets written as decimal numbers + and separated with the '.' (full stop) character."; + } +} diff --git a/src/cvl/schema/sonic-common.yang b/models/yang/sonic/common/sonic-common.yang similarity index 100% rename from src/cvl/schema/sonic-common.yang rename to models/yang/sonic/common/sonic-common.yang diff --git a/src/cvl/schema/sonic-extension.yang b/models/yang/sonic/common/sonic-extension.yang similarity index 100% rename from src/cvl/schema/sonic-extension.yang rename to models/yang/sonic/common/sonic-extension.yang diff --git a/src/cvl/schema/sonic-acl.yang b/models/yang/sonic/sonic-acl.yang similarity index 98% rename from src/cvl/schema/sonic-acl.yang rename to models/yang/sonic/sonic-acl.yang index d778e8da5f..6c57edcbba 100644 --- a/src/cvl/schema/sonic-acl.yang +++ b/models/yang/sonic/sonic-acl.yang @@ -3,10 +3,6 @@ module sonic-acl { prefix sacl; yang-version 1.1; - import ietf-yang-types { - prefix yang; - } - import ietf-inet-types { prefix inet; } diff --git a/src/cvl/schema/sonic-interface.yang b/models/yang/sonic/sonic-interface.yang similarity index 74% rename from src/cvl/schema/sonic-interface.yang rename to models/yang/sonic/sonic-interface.yang index f51a37f43a..30f1f02c42 100644 --- a/src/cvl/schema/sonic-interface.yang +++ b/models/yang/sonic/sonic-interface.yang @@ -29,6 +29,21 @@ module sonic-interface { container INTERFACE { list INTERFACE_LIST { + key "portname"; + + leaf portname{ + type leafref { + path "/prt:sonic-port/prt:PORT/prt:PORT_LIST/prt:ifname"; + } + } + + leaf vrf-name { + type string; + } + + } + + list INTERFACE_IPADDR_LIST { key "portname ip_prefix"; leaf portname{ diff --git a/src/cvl/schema/sonic-mirror-session.yang b/models/yang/sonic/sonic-mirror-session.yang similarity index 100% rename from src/cvl/schema/sonic-mirror-session.yang rename to models/yang/sonic/sonic-mirror-session.yang diff --git a/src/cvl/schema/sonic-port.yang b/models/yang/sonic/sonic-port.yang similarity index 100% rename from src/cvl/schema/sonic-port.yang rename to models/yang/sonic/sonic-port.yang diff --git a/src/cvl/cvl.go b/src/cvl/cvl.go index 859d78043f..4d44b35b7a 100644 --- a/src/cvl/cvl.go +++ b/src/cvl/cvl.go @@ -51,6 +51,7 @@ var luaScripts map[string]*redis.Script type modelTableInfo struct { dbNum uint8 modelName string + redisTableName string //To which Redis table it belongs to, used for 1 Redis to N Yang List module *yparser.YParserModule keys []string redisKeyDelim string @@ -92,8 +93,9 @@ type modelNamespace struct { } type modelDataInfo struct { - modelNs map[string]modelNamespace//model namespace - tableInfo map[string]modelTableInfo //redis table to model name and keys + modelNs map[string]modelNamespace //model namespace + tableInfo map[string]*modelTableInfo //redis table to model name and keys + redisTableToYangList map[string][]string //Redis table to all YANG lists when it is not 1:1 mapping allKeyDelims map[string]bool } @@ -226,12 +228,17 @@ func storeModelInfo(modelFile string, module *yparser.YParserModule) { //such mo modelInfo.modelNs[modelName] = modelNs - //Store metadata present in each list + //Store metadata present in each list. + //Each list represent one Redis table in general. + //However when one Redis table is mapped to multiple + //YANG lists need to store the information in redisTableToYangList map nodes = xmlquery.Find(root, "//module/container/container/list") if (nodes == nil) { return } + //number list under one table container i.e. ACL_TABLE container + //has only one ACL_TABLE_LIST list for _, node := range nodes { //for each list, remove "_LIST" suffix tableName := node.Attr[0].Value @@ -239,6 +246,8 @@ func storeModelInfo(modelFile string, module *yparser.YParserModule) { //such mo tableName = tableName[0:len(tableName) - len("_LIST")] } tableInfo := modelTableInfo{modelName: modelName} + //Store Redis table name + tableInfo.redisTableName = node.Parent.Attr[0].Value //Store the reference for list node to be used later listNode := node node = node.FirstChild @@ -294,10 +303,20 @@ func storeModelInfo(modelFile string, module *yparser.YParserModule) { //such mo } */ + //If container has more than one list, it means one Redis table is mapped to + //multiple lists, store the info in redisTableToYangList + allLists := xmlquery.Find(listNode.Parent, "/list") + if len(allLists) > 1 { + yangList := modelInfo.redisTableToYangList[tableInfo.redisTableName] + yangList = append(yangList, tableName) + //Update the map + modelInfo.redisTableToYangList[tableInfo.redisTableName] = yangList + } + leafRefNodes := xmlquery.Find(listNode, "//type[@name='leafref']") if (leafRefNodes == nil) { //Store the tableInfo in global data - modelInfo.tableInfo[tableName] = tableInfo + modelInfo.tableInfo[tableName] = &tableInfo continue } @@ -325,11 +344,11 @@ func storeModelInfo(modelFile string, module *yparser.YParserModule) { //such mo } } - //Find all 'must' expression and store the agains its parent node + //Find all 'must' expression and store the against its parent node mustExps := xmlquery.Find(listNode, "//must") if (mustExps == nil) { //Update the tableInfo in global data - modelInfo.tableInfo[tableName] = tableInfo + modelInfo.tableInfo[tableName] = &tableInfo continue } @@ -353,7 +372,8 @@ func storeModelInfo(modelFile string, module *yparser.YParserModule) { //such mo } //Update the tableInfo in global data - modelInfo.tableInfo[tableName] = tableInfo + modelInfo.tableInfo[tableName] = &tableInfo + } } @@ -438,6 +458,48 @@ func splitRedisKey(key string) (string, string) { return tblName, key[prefixLen:] } +//Get the YANG list name from Redis key +//This just returns same YANG list name as Redis table name +//when 1:1 mapping is there. For one Redis table to +//multiple YANG list, it returns appropriate YANG list name +//INTERFACE:Ethernet12 returns ==> INTERFACE +//INTERFACE:Ethernet12:1.1.1.0/32 ==> INTERFACE_IPADDR +func getRedisKeyToYangList(tableName, key string) string { + mapArr, exists := modelInfo.redisTableToYangList[tableName] + + if exists == false { + //1:1 mapping case + return tableName + } + + //As of now determine the mapping based on number of keys + var foundIdx int = -1 + numOfKeys := 1 //Assume only one key initially + for keyDelim, _ := range modelInfo.allKeyDelims { + foundIdx = strings.Index(key, keyDelim) + if (foundIdx >= 0) { + //Matched with key delim + keyComps := strings.Split(key, keyDelim) + numOfKeys = len(keyComps) + break + } + } + + //Check which list has number of keys as 'numOfKeys' + for i := 0; i < len(mapArr); i++ { + tblInfo, exists := modelInfo.tableInfo[mapArr[i]] + if exists == true { + if (len(tblInfo.keys) == numOfKeys) { + //Found the YANG list matching the number of keys + return mapArr[i] + } + } + } + + //No matches + return tableName +} + //Convert Redis key to Yang keys, if multiple key components are there, //they are separated based on Yang schema func getRedisToYangKeys(tableName string, redisKey string)[]keyValuePairStruct{ @@ -1310,6 +1372,7 @@ parent *yparser.YParserNode) CVLRetCode { func (c *CVL) generateTableData(config bool, jsonNode *jsonquery.Node)(*yparser.YParserNode, CVLErrorInfo) { var cvlErrObj CVLErrorInfo + tableName := fmt.Sprintf("%s",jsonNode.Data) c.batchLeaf = "" @@ -1318,9 +1381,15 @@ func (c *CVL) generateTableData(config bool, jsonNode *jsonquery.Node)(*yparser. // container ACL_RULE { list ACL_RULE_LIST {} } var topNode *yparser.YParserNode + // Add top most conatiner e.g. 'container sonic-acl {...}' + if _, exists := modelInfo.tableInfo[tableName]; exists == false { + return nil, cvlErrObj + } topNode = c.yp.AddChildNode(modelInfo.tableInfo[tableName].module, nil, modelInfo.tableInfo[tableName].modelName) + //Add the container node for each list + //e.g. 'container ACL_TABLE { list ACL_TABLE_LIST ...} listConatinerNode := c.yp.AddChildNode(modelInfo.tableInfo[tableName].module, topNode, tableName) @@ -1330,6 +1399,9 @@ func (c *CVL) generateTableData(config bool, jsonNode *jsonquery.Node)(*yparser. //For each field check if is key //If it is key, create list as child of top container // Get all key name/value pairs + if yangListName := getRedisKeyToYangList(tableName, jsonNode.Data); yangListName!= "" { + tableName = yangListName + } keyValuePair := getRedisToYangKeys(tableName, jsonNode.Data) keyCompCount := len(keyValuePair) totalKeyComb := 1 @@ -1344,6 +1416,9 @@ func (c *CVL) generateTableData(config bool, jsonNode *jsonquery.Node)(*yparser. } for ; totalKeyComb > 0 ; totalKeyComb-- { + //Get the YANG list name from Redis table name + //Ideally they are same except when one Redis table is split + //into multiple YANG lists //Add table i.e. create list element listNode := c.addChildNode(tableName, listConatinerNode, tableName + "_LIST") //Add the list to the top node diff --git a/src/cvl/cvl_api.go b/src/cvl/cvl_api.go index 26bc6ea7f7..d4bfe7ee2b 100644 --- a/src/cvl/cvl_api.go +++ b/src/cvl/cvl_api.go @@ -104,8 +104,9 @@ func Initialize() CVLRetCode { yparser.Initialize() modelInfo.modelNs = make(map[string]modelNamespace) //redis table to model name - modelInfo.tableInfo = make(map[string]modelTableInfo) //model namespace + modelInfo.tableInfo = make(map[string]*modelTableInfo) //model namespace modelInfo.allKeyDelims = make(map[string]bool) //all key delimiter + modelInfo.redisTableToYangList = make(map[string][]string) //Redis table to Yang list map dbNameToDbNum = map[string]uint8{"APPL_DB": APPL_DB, "CONFIG_DB": CONFIG_DB} /* schema */ diff --git a/src/cvl/schema/Makefile b/src/cvl/schema/Makefile index fe23d1ce71..911ab84184 100644 --- a/src/cvl/schema/Makefile +++ b/src/cvl/schema/Makefile @@ -1,24 +1,40 @@ -src_files=$(wildcard *.yang) -out=$(patsubst %.yang, %.yin, $(src_files)) -out_ext=$(patsubst %.yang, %.tree, $(src_files)) +sonic_yang=../../../models/yang/sonic +sonic_yang_common=../../../models/yang/sonic/common +pyang_plugin_dir=../../../tools/pyang/pyang_plugins + +src_files=$(wildcard $(sonic_yang)/*.yang) +src_files += $(wildcard $(sonic_yang_common)/*.yang) +out=$(patsubst %.yang, %.yin, $(shell ls -1 $(sonic_yang)/*.yang | cut -d'/' -f7)) +out_common=$(patsubst %.yang, %.yin, $(shell ls -1 $(sonic_yang_common)/*.yang | cut -d'/' -f8)) +out_tree=$(patsubst %.yang, %.tree, $(src_files)) +search_path=$(sonic_yang):$(sonic_yang_common):$(sonic_yang_common)/ietf + all:schema -schema: $(out) +schema: $(out) $(out_common) -%.yin:%.yang - @echo "Generating $@ ..." - @devFile="`echo $< | cut -d . -f1`-dev.yang"; \ +schema-tree: $(out_tree) + +%.yin:$(sonic_yang)/%.yang + @echo "Generating `basename $@` ..." + @devFile="`echo $@ | cut -d . -f1`-deviation.yang"; \ if [ -f $$devFile ] ; then devOpt="--deviation-module $$devFile"; fi; \ - pyang -p ./ietf/ --plugindir ../../../tools/pyang/pyang_plugins/ -f yin-cvl $$devOpt $< -o $@ + pyang -p $(search_path) --plugindir $(pyang_plugin_dir) \ + -f yin-cvl $$devOpt $< -o `basename $@` +%.yin:$(sonic_yang_common)/%.yang + @echo "Generating `basename $@` ..." + @devFile="`echo $@ | cut -d . -f1`-deviation.yang"; \ + if [ -f $$devFile ] ; then devOpt="--deviation-module $$devFile"; fi; \ + pyang -p $(search_path) --plugindir $(pyang_plugin_dir) \ + -f yin-cvl $$devOpt $< -o `basename $@` %.tree:%.yang - @echo "Generating $@ ..." + @echo "Generating `basename $@` ..." @devFile="`echo $< | cut -d . -f1`-dev.yang"; \ if [ -f $$devFile ] ; then devOpt="--deviation-module $$devFile"; fi; \ - pyang -p ./ietf/ -f tree $$devOpt $< -o $@ + pyang -p $(search_path) -f tree $$devOpt $< -o `basename $@` clean: @echo "Removing files ..." - rm -rf $(out) - rm -rf $(out_ext) + rm -rf *.yin *.tree diff --git a/src/cvl/testdata/schema/Makefile b/src/cvl/testdata/schema/Makefile index 308b3eaf6b..43fee356bf 100644 --- a/src/cvl/testdata/schema/Makefile +++ b/src/cvl/testdata/schema/Makefile @@ -17,6 +17,8 @@ # # ################################################################################ +sonic_yang=../../../../models/yang/sonic +pyang_plugin_dir=../../../../tools/pyang/pyang_plugins src_files=$(wildcard *.yang) out=$(patsubst %.yang, %.yin, $(src_files)) out_ext=$(patsubst %.yang, %.tree, $(src_files)) @@ -25,20 +27,22 @@ all:schema schema: $(out) +schema-tree: $(out_ext) + %.yin:%.yang - @echo "Generating $@ ..." + @echo "Generating `basename $@` ..." @devFile="`echo $< | cut -d . -f1`-dev.yang"; \ if [ -f $$devFile ] ; then devOpt="--deviation-module $$devFile"; fi; \ - pyang -p ../../schema/:../../schema/ietf/ -f yin $$devOpt $< -o $@.tmp - @xmllint --noblanks $@.tmp > $@ - @rm -rf $@.tmp + pyang -p $(sonic_yang):$(sonic_yang)/common:$(sonic_yang)/common/ietf \ + --plugindir $(pyang_plugin_dir) -f yin-cvl $$devOpt $< -o `basename $@` %.tree:%.yang - @echo "Generating $@ ..." + @echo "Generating `basename $@` ..." @devFile="`echo $< | cut -d . -f1`-dev.yang"; \ if [ -f $$devFile ] ; then devOpt="--deviation-module $$devFile"; fi; \ - pyang -p ../../schema/:../../schema/ietf/ -f tree $$devOpt $< -o $@ + pyang -p $(sonic_yang):$(sonic_yang)/common:$(sonic_yang)/common/ietf \ + -f tree $$devOpt $< -o `basename $@` clean: @echo "Removing files ..." - rm -rf *.yin + rm -rf *.yin *.tree diff --git a/src/cvl/testdata/schema/sonic-acl-dev.yang b/src/cvl/testdata/schema/sonic-acl-deviation.yang similarity index 85% rename from src/cvl/testdata/schema/sonic-acl-dev.yang rename to src/cvl/testdata/schema/sonic-acl-deviation.yang index d11b40a95c..c1d701c29d 100644 --- a/src/cvl/testdata/schema/sonic-acl-dev.yang +++ b/src/cvl/testdata/schema/sonic-acl-deviation.yang @@ -1,5 +1,5 @@ -module sonic-acl-dev { - namespace "http://github.com/Azure/sonic-acl-dev"; +module sonic-acl-deviation { + namespace "http://github.com/Azure/sonic-acl-deviation"; prefix acld; yang-version 1.1; diff --git a/src/cvl/testdata/schema/sonic-dscp-tc-map.yang b/src/cvl/testdata/schema/sonic-dscp-tc-map.yang index 9ec41b4f15..14dccddd3d 100644 --- a/src/cvl/testdata/schema/sonic-dscp-tc-map.yang +++ b/src/cvl/testdata/schema/sonic-dscp-tc-map.yang @@ -6,10 +6,6 @@ module sonic-dscp-tc-map { prefix sonic-ext; } - import sonic-port { - prefix sif; - } - organization "SONiC"; diff --git a/src/cvl/testdata/schema/sonic-vlan-dev.yang b/src/cvl/testdata/schema/sonic-vlan-deviation.yang similarity index 83% rename from src/cvl/testdata/schema/sonic-vlan-dev.yang rename to src/cvl/testdata/schema/sonic-vlan-deviation.yang index 7cc5784851..ff426fb30c 100644 --- a/src/cvl/testdata/schema/sonic-vlan-dev.yang +++ b/src/cvl/testdata/schema/sonic-vlan-deviation.yang @@ -1,5 +1,5 @@ -module sonic-vlan-dev { - namespace "http://github.com/Azure/sonic-vlan-dev"; +module sonic-vlan-deviation { + namespace "http://github.com/Azure/sonic-vlan-deviation"; prefix svd; yang-version 1.1; diff --git a/tools/pyang/pyang_plugins/yin_cvl.py b/tools/pyang/pyang_plugins/yin_cvl.py index 7e03b3a0c0..71689003b0 100644 --- a/tools/pyang/pyang_plugins/yin_cvl.py +++ b/tools/pyang/pyang_plugins/yin_cvl.py @@ -30,9 +30,9 @@ from pyang import syntax from pyang import statements -new_line='' #replace with '\n' for adding new line -indent_space= '' #replace with ' ' for indentation -ns_indent_space= '' #replace with ' ' for indentation +new_line ='' #replace with '\n' for adding new line +indent_space = '' #replace with ' ' for indentation +ns_indent_space = '' #replace with ' ' for indentation yin_namespace = "urn:ietf:params:xml:ns:yang:yin:1" revision_added = False From 483030f8aeebe1f913750ade03c26be30cca9648 Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Thu, 26 Sep 2019 17:15:35 -0700 Subject: [PATCH 173/214] Fix table get in Traverse for App DB with ":" separator --- src/translib/transformer/xlate.go | 15 +++++++++++---- src/translib/transformer/xlate_to_db.go | 6 +++++- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index 844fb9b7a8..3563b93858 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -69,6 +69,10 @@ func XlateFuncCall(name string, params ...interface{}) (result []reflect.Value, func TraverseDb(dbs [db.MaxDB]*db.DB, spec KeySpec, result *map[db.DBNum]map[string]map[string]db.Value, parentKey *db.Key) error { var err error + separator := ":" + if spec.dbNum == db.ConfigDB { + separator = "|" + } if spec.Key.Len() > 0 { // get an entry with a specific key @@ -78,9 +82,9 @@ func TraverseDb(dbs [db.MaxDB]*db.DB, spec KeySpec, result *map[db.DBNum]map[str } if (*result)[spec.dbNum][spec.Ts.Name] == nil { - (*result)[spec.dbNum][spec.Ts.Name] = map[string]db.Value{strings.Join(spec.Key.Comp, "|"): data} + (*result)[spec.dbNum][spec.Ts.Name] = map[string]db.Value{strings.Join(spec.Key.Comp, separator): data} } else { - (*result)[spec.dbNum][spec.Ts.Name][strings.Join(spec.Key.Comp, "|")] = data + (*result)[spec.dbNum][spec.Ts.Name][strings.Join(spec.Key.Comp, separator)] = data } if len(spec.Child) > 0 { @@ -97,7 +101,7 @@ func TraverseDb(dbs [db.MaxDB]*db.DB, spec KeySpec, result *map[db.DBNum]map[str for i, _ := range keys { if parentKey != nil { // TODO - multi-depth with a custom delimiter - if strings.Index(strings.Join(keys[i].Comp, "|"), strings.Join((*parentKey).Comp, "|")) == -1 { + if strings.Index(strings.Join(keys[i].Comp, separator), strings.Join((*parentKey).Comp, "|")) == -1 { continue } } @@ -177,7 +181,10 @@ func fillCvlKeySpec(xpath string , tableName string, keyStr string) ( []KeySpec if tableName != "" { dbFormat := KeySpec{} dbFormat.Ts.Name = tableName - cdb := xDbSpecMap[xpath].dbIndex + cdb := db.ConfigDB + if _, ok := xDbSpecMap[xpath]; ok { + cdb = xDbSpecMap[xpath].dbIndex + } dbFormat.dbNum = cdb if keyStr != "" { dbFormat.Key.Comp = append(dbFormat.Key.Comp, keyStr) diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index 6b21d71f74..b34c87d5ec 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -436,7 +436,11 @@ func sonicXpathKeyExtract(path string) (string, string, string) { rgp := regexp.MustCompile(`\[([^\[\]]*)\]`) pathsubStr := strings.Split(path , "/") if len(pathsubStr) > SONIC_TABLE_INDEX { - tableName = strings.Split(pathsubStr[SONIC_TABLE_INDEX], "[")[0] + if strings.Contains(pathsubStr[2], ":") { + tableName = strings.Split(pathsubStr[SONIC_TABLE_INDEX], "[")[0] + } else { + tableName = pathsubStr[SONIC_TABLE_INDEX] + } for i, kname := range rgp.FindAllString(path, -1) { if i > 0 { keyStr += "|" } val := strings.Split(kname, "=")[1] From 60da3901fe5d172f4d5769d71d8f527d822b328b Mon Sep 17 00:00:00 2001 From: s-mari Date: Thu, 26 Sep 2019 18:16:22 -0700 Subject: [PATCH 174/214] added support to invoke container level key transformer --- src/translib/transformer/xlate_to_db.go | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index b34c87d5ec..e47971dfc9 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -385,6 +385,7 @@ func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, log.Infof("slice/map data: key(\"%v\"), xpathPrefix(\"%v\").", keyName, xpathPrefix) xpath := uri curUri := uri + curKey := keyName pathAttr := key.String() if len(xpathPrefix) > 0 { if strings.Contains(pathAttr, ":") { @@ -393,7 +394,17 @@ func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, xpath = xpathPrefix + "/" + pathAttr curUri = uri + "/" + pathAttr } - + log.Infof("slice/map data: curKey(\"%v\"), xpath(\"%v\"), curUri(\"%v\").", + curKey, xpath, curUri) + if len(xYangSpecMap[xpath].xfmrKey) > 0 { + /* key transformer present */ + inParams := formXfmrInputRequest(d, dbs, db.MaxDB, ygRoot, curUri, oper, "", nil, nil) + ret, err := XlateFuncCall(yangToDbXfmrFunc(xYangSpecMap[xpath].xfmrKey), inParams) + if err != nil { + return err + } + curKey = ret[0].Interface().(string) + } if (typeOfValue == reflect.Map || typeOfValue == reflect.Slice) && xYangSpecMap[xpath].yangDataType != "leaf-list" { if xYangSpecMap[xpath] != nil && len(xYangSpecMap[xpath].xfmrFunc) > 0 { /* subtree transformer present */ @@ -404,7 +415,7 @@ func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, } mapCopy(result, ret[0].Interface().(map[string]map[string]db.Value)) } else { - yangReqToDbMapCreate(d, ygRoot, oper, curUri, xpath, keyName, jData.MapIndex(key).Interface(), result) + yangReqToDbMapCreate(d, ygRoot, oper, curUri, xpath, curKey, jData.MapIndex(key).Interface(), result) } } else { pathAttr := key.String() @@ -413,7 +424,7 @@ func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, } value := jData.MapIndex(key).Interface() log.Infof("data field: key(\"%v\"), value(\"%v\").", key, value) - err := mapFillData(d, ygRoot, oper, uri, keyName, result, xpathPrefix, + err := mapFillData(d, ygRoot, oper, uri, curKey, result, xpathPrefix, pathAttr, value) if err != nil { log.Errorf("Failed constructing data for db write: key(\"%v\"), value(\"%v\"), path(\"%v\").", From 73b1ecf2d06760da27af3b58e29b2d9901732adb Mon Sep 17 00:00:00 2001 From: s-mari Date: Thu, 26 Sep 2019 22:52:14 -0700 Subject: [PATCH 175/214] added code to pass the current ygot node to the key xfmr function --- src/translib/transformer/xlate_to_db.go | 42 ++++++++++++++++++++++--- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index e47971dfc9..7e4cb108b4 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -349,6 +349,28 @@ func dbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string, jsonDat return err } +func yangNodeForUriGet(uri string, ygRoot *ygot.GoStruct) (interface{}, error) { + path, _ := ygot.StringToPath(uri, ygot.StructuredPath, ygot.StringSlicePath) + for _, p := range path.Elem { + pathSlice := strings.Split(p.Name, ":") + p.Name = pathSlice[len(pathSlice)-1] + if len(p.Key) > 0 { + for ekey, ent := range p.Key { + eslice := strings.Split(ent, ":") + p.Key[ekey] = eslice[len(eslice)-1] + } + } + } + ocbSch, _ := ocbinds.Schema() + schRoot := ocbSch.RootSchema() + node, nErr := ytypes.GetNode(schRoot, (*ygRoot).(*ocbinds.Device), path) + log.Info("GetNode data: ", node[0].Data, " nErr :", nErr) + if nErr != nil { + return nil, nErr + } + return node[0].Data, nil +} + func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, xpathPrefix string, keyName string, jsonData interface{}, result map[string]map[string]db.Value) error { log.Infof("key(\"%v\"), xpathPrefix(\"%v\").", keyName, xpathPrefix) var dbs [db.MaxDB]*db.DB @@ -365,10 +387,14 @@ func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, curUri, _ := uriWithKeyCreate(uri, xpathPrefix, data) if len(xYangSpecMap[xpathPrefix].xfmrKey) > 0 { /* key transformer present */ - inParams := formXfmrInputRequest(d, dbs, db.MaxDB, ygRoot, curUri, oper, "", nil, nil) + curYgotNode, nodeErr := yangNodeForUriGet(curUri, ygRoot) + if nodeErr != nil { + curYgotNode = nil + } + inParams := formXfmrInputRequest(d, dbs, db.MaxDB, ygRoot, curUri, oper, "", nil, curYgotNode) ret, err := XlateFuncCall(yangToDbXfmrFunc(xYangSpecMap[xpathPrefix].xfmrKey), inParams) if err != nil { - return err + return err } curKey = ret[0].Interface().(string) } else { @@ -398,7 +424,11 @@ func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, curKey, xpath, curUri) if len(xYangSpecMap[xpath].xfmrKey) > 0 { /* key transformer present */ - inParams := formXfmrInputRequest(d, dbs, db.MaxDB, ygRoot, curUri, oper, "", nil, nil) + curYgotNode, nodeErr := yangNodeForUriGet(curUri, ygRoot) + if nodeErr != nil { + curYgotNode = nil + } + inParams := formXfmrInputRequest(d, dbs, db.MaxDB, ygRoot, curUri, oper, "", nil, curYgotNode) ret, err := XlateFuncCall(yangToDbXfmrFunc(xYangSpecMap[xpath].xfmrKey), inParams) if err != nil { return err @@ -408,7 +438,11 @@ func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, if (typeOfValue == reflect.Map || typeOfValue == reflect.Slice) && xYangSpecMap[xpath].yangDataType != "leaf-list" { if xYangSpecMap[xpath] != nil && len(xYangSpecMap[xpath].xfmrFunc) > 0 { /* subtree transformer present */ - inParams := formXfmrInputRequest(d, dbs, db.MaxDB, ygRoot, curUri, oper, "", nil, nil) + curYgotNode, nodeErr := yangNodeForUriGet(curUri, ygRoot) + if nodeErr != nil { + curYgotNode = nil + } + inParams := formXfmrInputRequest(d, dbs, db.MaxDB, ygRoot, curUri, oper, "", nil, curYgotNode) ret, err := XlateFuncCall(yangToDbXfmrFunc(xYangSpecMap[xpath].xfmrFunc), inParams) if err != nil { return nil From 98822f9fccee72dc4723ab6624557e1f59cd1f50 Mon Sep 17 00:00:00 2001 From: s-mari Date: Fri, 27 Sep 2019 12:46:57 -0700 Subject: [PATCH 176/214] added support for sonic yang non-config db get request --- src/translib/transformer/xlate_from_db.go | 70 +++++++++++++---------- src/translib/transformer/xlate_utils.go | 8 ++- 2 files changed, 45 insertions(+), 33 deletions(-) diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index 26f1ae7174..ac25687f64 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -169,38 +169,40 @@ func processLfLstDbToYang(fieldXpath string, dbFldVal string) []interface{} { } /* Traverse db map and create json for cvl yang */ -func directDbToYangJsonCreate(dbDataMap map[string]map[string]db.Value, jsonData string, resultMap map[string]interface{}) error { +func directDbToYangJsonCreate(dbDataMap *map[db.DBNum]map[string]map[string]db.Value, jsonData string, resultMap map[string]interface{}) error { var err error - for tblName, tblData := range dbDataMap { - var mapSlice []typeMapOfInterface - for keyStr, dbFldValData := range tblData { - curMap := make(map[string]interface{}) - for field, value := range dbFldValData.Field { - resField := field - if strings.HasSuffix(field, "@") { - fldVals := strings.Split(field, "@") - resField = fldVals[0] - } - fieldXpath := tblName + "/" + resField - xDbSpecMapEntry, ok := xDbSpecMap[fieldXpath] - if !ok { - log.Warningf("No entry found in xDbSpecMap for xpath %v", fieldXpath) - continue - } - if xDbSpecMapEntry.dbEntry == nil { - log.Warningf("Yang entry is nil in xDbSpecMap for xpath %v", fieldXpath) - continue - } - yangType := yangTypeGet(xDbSpecMapEntry.dbEntry) - if yangType == "leaf-list" { - /* this should never happen but just adding for safetty */ - if !strings.HasSuffix(field, "@") { - log.Warningf("Leaf-list in Sonic yang should also be a leaf-list in DB, its not for xpath %v", fieldXpath) + for curDbIdx := db.ApplDB; curDbIdx < db.MaxDB; curDbIdx++ { + dbTblData := (*dbDataMap)[curDbIdx] + for tblName, tblData := range dbTblData { + var mapSlice []typeMapOfInterface + for keyStr, dbFldValData := range tblData { + curMap := make(map[string]interface{}) + for field, value := range dbFldValData.Field { + resField := field + if strings.HasSuffix(field, "@") { + fldVals := strings.Split(field, "@") + resField = fldVals[0] + } + fieldXpath := tblName + "/" + resField + xDbSpecMapEntry, ok := xDbSpecMap[fieldXpath] + if !ok { + log.Warningf("No entry found in xDbSpecMap for xpath %v", fieldXpath) continue } - resLst := processLfLstDbToYang(fieldXpath, value) - curMap[resField] = resLst - } else { /* yangType is leaf - there are only 2 types of yang terminal node leaf and leaf-list */ + if xDbSpecMapEntry.dbEntry == nil { + log.Warningf("Yang entry is nil in xDbSpecMap for xpath %v", fieldXpath) + continue + } + yangType := yangTypeGet(xDbSpecMapEntry.dbEntry) + if yangType == "leaf-list" { + /* this should never happen but just adding for safetty */ + if !strings.HasSuffix(field, "@") { + log.Warningf("Leaf-list in Sonic yang should also be a leaf-list in DB, its not for xpath %v", fieldXpath) + continue + } + resLst := processLfLstDbToYang(fieldXpath, value) + curMap[resField] = resLst + } else { /* yangType is leaf - there are only 2 types of yang terminal node leaf and leaf-list */ yngTerminalNdDtType := xDbSpecMapEntry.dbEntry.Type.Kind resVal, err := DbToYangType(yngTerminalNdDtType, fieldXpath, value) if err != nil { @@ -210,14 +212,20 @@ func directDbToYangJsonCreate(dbDataMap map[string]map[string]db.Value, jsonData } } } //end of for + dbSpecData, ok := xDbSpecMap[tblName] + dbIndex := db.ConfigDB + if ok { + dbIndex = dbSpecData.dbIndex + } yangKeys := yangKeyFromEntryGet(xDbSpecMap[tblName].dbEntry) - sonicKeyDataAdd(yangKeys, keyStr, curMap) + sonicKeyDataAdd(dbIndex, yangKeys, keyStr, curMap) if curMap != nil { mapSlice = append(mapSlice, curMap) } } resultMap[tblName] = mapSlice } +} return err } @@ -470,7 +478,7 @@ func dbDataToYangJsonCreate(uri string, ygRoot *ygot.GoStruct, dbs [db.MaxDB]*db jsonData := "" resultMap := make(map[string]interface{}) if isCvlYang(uri) { - directDbToYangJsonCreate((*dbDataMap)[cdb], jsonData, resultMap) + directDbToYangJsonCreate(dbDataMap, jsonData, resultMap) } else { var d *db.DB reqXpath, keyName, tableName := xpathKeyExtract(d, ygRoot, GET, uri) diff --git a/src/translib/transformer/xlate_utils.go b/src/translib/transformer/xlate_utils.go index 6820a56377..f4dc44340d 100644 --- a/src/translib/transformer/xlate_utils.go +++ b/src/translib/transformer/xlate_utils.go @@ -222,8 +222,12 @@ func isCvlYang(path string) bool { return false } -func sonicKeyDataAdd(keyNameList []string, keyStr string, resultMap map[string]interface{}) { - keyValList := strings.Split(keyStr, "|") +func sonicKeyDataAdd(dbIndex db.DBNum, keyNameList []string, keyStr string, resultMap map[string]interface{}) { + keyValList := strings.Split(keyStr, ":") + if dbIndex == db.ConfigDB { + keyValList = strings.Split(keyStr, "|") + } + if len(keyNameList) != len(keyValList) { return } From 2a17ea20a094ce07f1bdb70e683507555fe70a25 Mon Sep 17 00:00:00 2001 From: amrutasali Date: Fri, 27 Sep 2019 23:54:25 +0000 Subject: [PATCH 177/214] Data base specific key-delimiter support in transformer core - Sonic Get case --- src/translib/transformer/xlate.go | 28 ++++++++++++++-------- src/translib/transformer/xlate_to_db.go | 14 ++++++++--- src/translib/transformer/xlate_utils.go | 32 +++++++++++++++++++++---- 3 files changed, 57 insertions(+), 17 deletions(-) diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index 3563b93858..7453631df9 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -69,10 +69,11 @@ func XlateFuncCall(name string, params ...interface{}) (result []reflect.Value, func TraverseDb(dbs [db.MaxDB]*db.DB, spec KeySpec, result *map[db.DBNum]map[string]map[string]db.Value, parentKey *db.Key) error { var err error - separator := ":" - if spec.dbNum == db.ConfigDB { - separator = "|" - } + var dbOpts db.Options + + dbOpts = getDBOptions(spec.dbNum) + separator := dbOpts.KeySeparator + log.Infof("key separator for table %v in Db %v is %v", spec.Ts.Name, spec.dbNum, separator) if spec.Key.Len() > 0 { // get an entry with a specific key @@ -101,7 +102,7 @@ func TraverseDb(dbs [db.MaxDB]*db.DB, spec KeySpec, result *map[db.DBNum]map[str for i, _ := range keys { if parentKey != nil { // TODO - multi-depth with a custom delimiter - if strings.Index(strings.Join(keys[i].Comp, separator), strings.Join((*parentKey).Comp, "|")) == -1 { + if strings.Index(strings.Join(keys[i].Comp, separator), strings.Join((*parentKey).Comp, separator)) == -1 { continue } } @@ -182,8 +183,8 @@ func fillCvlKeySpec(xpath string , tableName string, keyStr string) ( []KeySpec dbFormat := KeySpec{} dbFormat.Ts.Name = tableName cdb := db.ConfigDB - if _, ok := xDbSpecMap[xpath]; ok { - cdb = xDbSpecMap[xpath].dbIndex + if _, ok := xDbSpecMap[tableName]; ok { + cdb = xDbSpecMap[tableName].dbIndex } dbFormat.dbNum = cdb if keyStr != "" { @@ -296,14 +297,21 @@ func GetAndXlateFromDB(uri string, ygRoot *ygot.GoStruct, dbs [db.MaxDB]*db.DB) func XlateFromDb(uri string, ygRoot *ygot.GoStruct, dbs [db.MaxDB]*db.DB, data map[db.DBNum]map[string]map[string]db.Value) ([]byte, error) { var err error + var result []byte var dbData = make(map[db.DBNum]map[string]map[string]db.Value) var cdb db.DBNum = db.ConfigDB dbData = data if isCvlYang(uri) { - yangXpath, keyStr, tableName := sonicXpathKeyExtract(uri) + xpath, keyStr, tableName := sonicXpathKeyExtract(uri) if (tableName != "") { - tokens:= strings.Split(yangXpath, "/") + dbInfo, ok := xDbSpecMap[tableName] + if !ok { + log.Warningf("No entry in xDbSpecMap for xpath %v", tableName) + } else { + cdb = dbInfo.dbIndex + } + tokens:= strings.Split(xpath, "/") // Format /module:container/tableName[key]/fieldName if tokens[len(tokens)-2] == tableName { fieldName := tokens[len(tokens)-1] @@ -322,7 +330,7 @@ func XlateFromDb(uri string, ygRoot *ygot.GoStruct, dbs [db.MaxDB]*db.DB, data m return nil, err } - result := []byte(payload) + result = []byte(payload) return result, err } diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index 7e4cb108b4..1cbe833915 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -364,7 +364,7 @@ func yangNodeForUriGet(uri string, ygRoot *ygot.GoStruct) (interface{}, error) { ocbSch, _ := ocbinds.Schema() schRoot := ocbSch.RootSchema() node, nErr := ytypes.GetNode(schRoot, (*ygRoot).(*ocbinds.Device), path) - log.Info("GetNode data: ", node[0].Data, " nErr :", nErr) + //log.Info("GetNode data: ", node[0].Data, " nErr :", nErr) if nErr != nil { return nil, nErr } @@ -481,13 +481,21 @@ func sonicXpathKeyExtract(path string) (string, string, string) { rgp := regexp.MustCompile(`\[([^\[\]]*)\]`) pathsubStr := strings.Split(path , "/") if len(pathsubStr) > SONIC_TABLE_INDEX { - if strings.Contains(pathsubStr[2], ":") { + if strings.Contains(pathsubStr[2], "[") { tableName = strings.Split(pathsubStr[SONIC_TABLE_INDEX], "[")[0] } else { tableName = pathsubStr[SONIC_TABLE_INDEX] } + dbInfo, ok := xDbSpecMap[tableName] + cdb := db.ConfigDB + if !ok { + log.Errorf("No entry in xDbSpecMap for xpath %v in order to fetch DB index.", tableName) + } else { + cdb = dbInfo.dbIndex + } + dbOpts := getDBOptions(cdb) for i, kname := range rgp.FindAllString(path, -1) { - if i > 0 { keyStr += "|" } + if i > 0 { keyStr += dbOpts.KeySeparator } val := strings.Split(kname, "=")[1] keyStr += strings.TrimRight(val, "]") } diff --git a/src/translib/transformer/xlate_utils.go b/src/translib/transformer/xlate_utils.go index f4dc44340d..bb21f339a5 100644 --- a/src/translib/transformer/xlate_utils.go +++ b/src/translib/transformer/xlate_utils.go @@ -223,10 +223,10 @@ func isCvlYang(path string) bool { } func sonicKeyDataAdd(dbIndex db.DBNum, keyNameList []string, keyStr string, resultMap map[string]interface{}) { - keyValList := strings.Split(keyStr, ":") - if dbIndex == db.ConfigDB { - keyValList = strings.Split(keyStr, "|") - } + var dbOpts db.Options + dbOpts = getDBOptions(dbIndex) + keySeparator := dbOpts.KeySeparator + keyValList := strings.Split(keyStr, keySeparator) if len(keyNameList) != len(keyValList) { return @@ -406,3 +406,27 @@ func findInMap(m map[string]string, str string) string { // str doesn't exist in map m. return "" } + +func getDBOptions(dbNo db.DBNum) db.Options { + var opt db.Options + + switch dbNo { + case db.ApplDB, db.CountersDB: + opt = getDBOptionsWithSeparator(dbNo, "", ":", ":") + break + case db.FlexCounterDB, db.AsicDB, db.LogLevelDB, db.ConfigDB, db.StateDB: + opt = getDBOptionsWithSeparator(dbNo, "", "|", "|") + break + } + + return opt +} + +func getDBOptionsWithSeparator(dbNo db.DBNum, initIndicator string, tableSeparator string, keySeparator string) db.Options { + return(db.Options { + DBNo : dbNo, + InitIndicator : initIndicator, + TableNameSeparator: tableSeparator, + KeySeparator : keySeparator, + }) +} From 7a257f7b4731ec4df26498b83673c2d712b75728 Mon Sep 17 00:00:00 2001 From: Tejaswi Goel Date: Wed, 25 Sep 2019 17:17:32 -0700 Subject: [PATCH 178/214] Changes in show port-channel command Signed-off-by: Tejaswi Goel --- src/CLI/actioner/sonic-cli-if.py | 78 +++++++++--------- src/CLI/clitree/cli-xml/interface.xml | 81 ++++++++++++------- src/CLI/clitree/cli-xml/sonic_types.xml | 14 ++++ .../renderer/templates/show_portchannel.j2 | 9 ++- .../renderer/templates/show_portchannel_id.j2 | 8 -- 5 files changed, 106 insertions(+), 84 deletions(-) delete mode 100644 src/CLI/renderer/templates/show_portchannel_id.j2 diff --git a/src/CLI/actioner/sonic-cli-if.py b/src/CLI/actioner/sonic-cli-if.py index af02afcec8..5fe245442d 100755 --- a/src/CLI/actioner/sonic-cli-if.py +++ b/src/CLI/actioner/sonic-cli-if.py @@ -101,50 +101,44 @@ def run(func, args): if "PortChannel" in args[0] and func.__name__ == 'patch_openconfig_interfaces_interfaces_interface': return - dummy_data= { - "openconfig-interfaces:interface": [ - { - "members": [ - "Ethernet56", - "Ethernet60" - ], - "min-links": 2, - "mtu": 9100, - "admin_status": "up", - "oper_status": "down", - "name": "PortChannel1" - }, - { - "members": [], - "min-links": 1, - "mtu": 9100, - "admin_status": "up", - "oper_status": "down", - "name": "PortChannel2" - }, - { - "members": [], - "min-links": 1, - "mtu": 9100, - "admin_status": "up", - "oper_status": "down", - "name": "PortChannel3" - } - ] -} - - #show given port-channel details - if "PortChannel" in args[0] and func.__name__ == 'get_openconfig_if_aggregate_interfaces_interface_aggregation_state': - for dict in dummy_data['openconfig-interfaces:interface']: - if dict["name"] == "PortChannel3": - show_cli_output("show_portchannel_id.j2", dict) - return - print("%Error: Entry not found") - return - #show port-channels summary if "PortChannel" in args[0] and func.__name__ == 'get_openconfig_interfaces_interfaces': - show_cli_output("show_portchannel.j2", dummy_data) + + dummy_resp= { + "PORTCHANNEL": [ + { + "members": [ + "Ethernet56", + "Ethernet60" + ], + "min-links": 2, + "mtu": 9100, + "admin_status": "up", + "oper_status": "down", + "name": "PortChannel1", + "id": "1" + }, + { + "members": [], + "min-links": 1, + "mtu": 9100, + "admin_status": "up", + "oper_status": "down", + "name": "PortChannel12", + "id": "12" + }, + { + "members": [], + "min-links": 1, + "mtu": 9100, + "admin_status": "up", + "oper_status": "down", + "name": "PortChannel3", + "id": "3" + } + ] + } + show_cli_output(args[1], dummy_resp) return #add members to port-channel diff --git a/src/CLI/clitree/cli-xml/interface.xml b/src/CLI/clitree/cli-xml/interface.xml index a72827413e..5ef58c8650 100644 --- a/src/CLI/clitree/cli-xml/interface.xml +++ b/src/CLI/clitree/cli-xml/interface.xml @@ -98,23 +98,15 @@ limitations under the License. - - - - if test "${lag-id}" = ""; then - python $SONIC_CLI_ROOT/sonic-cli-if.py get_openconfig_interfaces_interfaces PortChannel show_portchannel.j2 - else - python $SONIC_CLI_ROOT/sonic-cli-if.py get_openconfig_if_aggregate_interfaces_interface_aggregation_state PortChannel${lag-id} show_portchannel_id.j2#xA; - fi + mode="subcommand" /> + + + python $SONIC_CLI_ROOT/sonic-cli-if.py get_openconfig_interfaces_interfaces PortChannel show_portchannel.j2 @@ -163,7 +155,7 @@ limitations under the License. python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_interfaces_interfaces_interface PortChannel${lag-id} @@ -209,8 +201,8 @@ limitations under the License. > @@ -263,19 +255,45 @@ limitations under the License. - + + - python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_if_aggregate_interfaces_interface_ethernet_config_aggregate_id ${iface} ${lag-id} + ptype="LAG_ID" + > + + + + + + + + python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_if_aggregate_interfaces_interface_ethernet_config_aggregate_id ${iface} ${lag-id} + - python $SONIC_CLI_ROOT/sonic-cli-if.py delete_openconfig_if_aggregate_interfaces_interface_ethernet_config_aggregate_id ${iface} + python $SONIC_CLI_ROOT/sonic-cli-if.py delete_openconfig_if_aggregate_interfaces_interface_ethernet_config_aggregate_id ${iface} - python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_interfaces_interfaces_interface_config_enabled ${iface} False @@ -438,7 +456,7 @@ limitations under the License. + ptype="MIN_LINK" /> python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_if_aggregate_interfaces_interface_aggregation_config_min_links ${po_id} ${min-links} + + - @@ -485,6 +504,7 @@ limitations under the License. name="addr" help="IP address with mask" ptype="IP_ADDR_MASK" /> + + diff --git a/src/CLI/clitree/cli-xml/sonic_types.xml b/src/CLI/clitree/cli-xml/sonic_types.xml index 6b33089605..09a23fe5ef 100644 --- a/src/CLI/clitree/cli-xml/sonic_types.xml +++ b/src/CLI/clitree/cli-xml/sonic_types.xml @@ -41,6 +41,20 @@ limitations under the License. help="" /> + + + + Date: Mon, 30 Sep 2019 14:26:07 -0700 Subject: [PATCH 179/214] Add checks for xpath entry in xYangSpecMap and xDbSpecMap --- src/translib/transformer/xlate.go | 108 +++++++++++++----------- src/translib/transformer/xlate_to_db.go | 28 +++--- 2 files changed, 75 insertions(+), 61 deletions(-) diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index 7453631df9..17dd5bf44a 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -133,46 +133,50 @@ func XlateUriToKeySpec(uri string, ygRoot *ygot.GoStruct, t *interface{}) (*[]Ke } func FillKeySpecs(yangXpath string , keyStr string, retdbFormat *[]KeySpec) ([]KeySpec){ - if xYangSpecMap == nil { - return *retdbFormat - } - _, ok := xYangSpecMap[yangXpath] - if ok { - xpathInfo := xYangSpecMap[yangXpath] - if xpathInfo.tableName != nil { - dbFormat := KeySpec{} - dbFormat.Ts.Name = *xpathInfo.tableName - dbFormat.dbNum = xpathInfo.dbIndex - if keyStr != "" { - dbFormat.Key.Comp = append(dbFormat.Key.Comp, keyStr) - } - for _, child := range xpathInfo.childTable { - if xDbSpecMap != nil { - chlen := len(xDbSpecMap[child].yangXpath) - if chlen > 0 { - children := make([]KeySpec, 0) - for _, childXpath := range xDbSpecMap[child].yangXpath { - children = FillKeySpecs(childXpath, "", &children) - dbFormat.Child = append(dbFormat.Child, children...) + if xYangSpecMap == nil { + return *retdbFormat + } + _, ok := xYangSpecMap[yangXpath] + if ok { + xpathInfo := xYangSpecMap[yangXpath] + if xpathInfo.tableName != nil { + dbFormat := KeySpec{} + dbFormat.Ts.Name = *xpathInfo.tableName + dbFormat.dbNum = xpathInfo.dbIndex + if keyStr != "" { + dbFormat.Key.Comp = append(dbFormat.Key.Comp, keyStr) } - } - } - } - *retdbFormat = append(*retdbFormat, dbFormat) - } else { - for _, child := range xpathInfo.childTable { - if xDbSpecMap != nil { - chlen := len(xDbSpecMap[child].yangXpath) - if chlen > 0 { - for _, childXpath := range xDbSpecMap[child].yangXpath { - *retdbFormat = FillKeySpecs(childXpath, "", retdbFormat) - } - } - } - } - } - } - return *retdbFormat + for _, child := range xpathInfo.childTable { + if xDbSpecMap != nil { + if _, ok := xDbSpecMap[child]; ok { + chlen := len(xDbSpecMap[child].yangXpath) + if chlen > 0 { + children := make([]KeySpec, 0) + for _, childXpath := range xDbSpecMap[child].yangXpath { + children = FillKeySpecs(childXpath, "", &children) + dbFormat.Child = append(dbFormat.Child, children...) + } + } + } + } + } + *retdbFormat = append(*retdbFormat, dbFormat) + } else { + for _, child := range xpathInfo.childTable { + if xDbSpecMap != nil { + if _, ok := xDbSpecMap[child]; ok { + chlen := len(xDbSpecMap[child].yangXpath) + if chlen > 0 { + for _, childXpath := range xDbSpecMap[child].yangXpath { + *retdbFormat = FillKeySpecs(childXpath, "", retdbFormat) + } + } + } + } + } + } + } + return *retdbFormat } func fillCvlKeySpec(xpath string , tableName string, keyStr string) ( []KeySpec ) { @@ -195,15 +199,19 @@ func fillCvlKeySpec(xpath string , tableName string, keyStr string) ( []KeySpec // If table name not available in xpath get top container name tokens:= strings.Split(xpath, ":") container := "/" + tokens[len(tokens)-1] - if xDbSpecMap[container] != nil { - dbInfo := xDbSpecMap[container] - if dbInfo.fieldType == "container" { - for dir, _ := range dbInfo.dbEntry.Dir { - cdb := xDbSpecMap[dir].dbIndex - dbFormat := KeySpec{} - dbFormat.Ts.Name = dir - dbFormat.dbNum = cdb - retdbFormat = append(retdbFormat, dbFormat) + if xDbSpecMap != nil { + if _, ok := xDbSpecMap[container]; ok { + dbInfo := xDbSpecMap[container] + if dbInfo.fieldType == "container" { + for dir, _ := range dbInfo.dbEntry.Dir { + if _, ok := xDbSpecMap[dir]; ok { + cdb := xDbSpecMap[dir].dbIndex + dbFormat := KeySpec{} + dbFormat.Ts.Name = dir + dbFormat.dbNum = cdb + retdbFormat = append(retdbFormat, dbFormat) + } + } } } } @@ -320,7 +328,9 @@ func XlateFromDb(uri string, ygRoot *ygot.GoStruct, dbs [db.MaxDB]*db.DB, data m } } else { xpath, _ := RemoveXPATHPredicates(uri) - cdb = xYangSpecMap[xpath].dbIndex + if _, ok := xYangSpecMap[xpath]; ok { + cdb = xYangSpecMap[xpath].dbIndex + } } payload, err := dbDataToYangJsonCreate(uri, ygRoot, dbs, &dbData, cdb) log.Info("Payload generated:", payload) diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index 1cbe833915..1f51ce5d2d 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -62,10 +62,10 @@ func mapFillData(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, dbKey st var dbs [db.MaxDB]*db.DB var err error xpath := xpathPrefix + "/" + name - xpathInfo := xYangSpecMap[xpath] + xpathInfo, ok := xYangSpecMap[xpath] log.Infof("name: \"%v\", xpathPrefix(\"%v\").", name, xpathPrefix) - if xpathInfo == nil { + if !ok || xpathInfo == nil { log.Errorf("Yang path(\"%v\") not found.", xpath) return errors.New("Invalid URI") } @@ -293,7 +293,8 @@ func cvlYangReqToDbMapDelete(xpathPrefix string, tableName string, keyName strin // If table name not available in xpath get top container name tokens:= strings.Split(xpathPrefix, ":") container := "/" + tokens[len(tokens)-1] - if xDbSpecMap[container] != nil { + _, ok := xDbSpecMap[container] + if ok && xDbSpecMap[container] != nil { dbInfo := xDbSpecMap[container] if dbInfo.fieldType == "container" { for dir, _ := range dbInfo.dbEntry.Dir { @@ -385,7 +386,8 @@ func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, for _, data := range dataMap { curKey := "" curUri, _ := uriWithKeyCreate(uri, xpathPrefix, data) - if len(xYangSpecMap[xpathPrefix].xfmrKey) > 0 { + _, ok := xYangSpecMap[xpathPrefix] + if ok && len(xYangSpecMap[xpathPrefix].xfmrKey) > 0 { /* key transformer present */ curYgotNode, nodeErr := yangNodeForUriGet(curUri, ygRoot) if nodeErr != nil { @@ -420,9 +422,10 @@ func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, xpath = xpathPrefix + "/" + pathAttr curUri = uri + "/" + pathAttr } - log.Infof("slice/map data: curKey(\"%v\"), xpath(\"%v\"), curUri(\"%v\").", + _, ok := xYangSpecMap[xpath] + log.Infof("slice/map data: curKey(\"%v\"), xpath(\"%v\"), curUri(\"%v\").", curKey, xpath, curUri) - if len(xYangSpecMap[xpath].xfmrKey) > 0 { + if ok && xYangSpecMap[xpath] != nil && len(xYangSpecMap[xpath].xfmrKey) > 0 { /* key transformer present */ curYgotNode, nodeErr := yangNodeForUriGet(curUri, ygRoot) if nodeErr != nil { @@ -436,7 +439,7 @@ func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, curKey = ret[0].Interface().(string) } if (typeOfValue == reflect.Map || typeOfValue == reflect.Slice) && xYangSpecMap[xpath].yangDataType != "leaf-list" { - if xYangSpecMap[xpath] != nil && len(xYangSpecMap[xpath].xfmrFunc) > 0 { + if ok && xYangSpecMap[xpath] != nil && len(xYangSpecMap[xpath].xfmrFunc) > 0 { /* subtree transformer present */ curYgotNode, nodeErr := yangNodeForUriGet(curUri, ygRoot) if nodeErr != nil { @@ -540,14 +543,15 @@ func xpathKeyExtract(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string) (st curPathWithKey += "/" } pfxPath, _ := RemoveXPATHPredicates(path) - tblPtr := xYangSpecMap[pfxPath].tableName - if tblPtr != nil { - tableName = *tblPtr - } else if xYangSpecMap[pfxPath].xfmrTbl != nil { + if _, ok := xYangSpecMap[pfxPath]; ok { + tblPtr := xYangSpecMap[pfxPath].tableName + if tblPtr != nil { + tableName = *tblPtr + } else if xYangSpecMap[pfxPath].xfmrTbl != nil { inParams := formXfmrInputRequest(d, dbs, db.MaxDB, ygRoot, curPathWithKey, oper, "", nil, nil) tableName, _ = tblNameFromTblXfmrGet(*xYangSpecMap[pfxPath].xfmrTbl, inParams) } - + } return pfxPath, keyStr, tableName } From 7753aad4444ac9c0fc194f2beffd9ed156809203 Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Mon, 30 Sep 2019 16:34:15 -0700 Subject: [PATCH 180/214] Chk for list type to create keySpec --- src/translib/transformer/xlate.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index 17dd5bf44a..5baec6c5cb 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -204,7 +204,8 @@ func fillCvlKeySpec(xpath string , tableName string, keyStr string) ( []KeySpec dbInfo := xDbSpecMap[container] if dbInfo.fieldType == "container" { for dir, _ := range dbInfo.dbEntry.Dir { - if _, ok := xDbSpecMap[dir]; ok { + _, ok := xDbSpecMap[dir] + if ok && xDbSpecMap[dir].dbEntry.Node.Statement().Keyword == "list" { cdb := xDbSpecMap[dir].dbIndex dbFormat := KeySpec{} dbFormat.Ts.Name = dir From 2f5eb5bb8888d4c83b7711d1753f9fe877b4c654 Mon Sep 17 00:00:00 2001 From: amrutasali Date: Mon, 30 Sep 2019 23:58:24 +0000 Subject: [PATCH 181/214] workaround for VLAN_MEMBER_TABLE list level get due to translib.generateGetResponsePayload() failure --- src/translib/common_app.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/translib/common_app.go b/src/translib/common_app.go index 2ec8cf10bd..8ab5fac646 100644 --- a/src/translib/common_app.go +++ b/src/translib/common_app.go @@ -172,15 +172,15 @@ func (app *CommonApp) processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error) { } } - payload, err = generateGetResponsePayload(app.pathInfo.Path, (*app.ygotRoot).(*ocbinds.Device), app.ygotTarget) + resPayload, err := generateGetResponsePayload(app.pathInfo.Path, (*app.ygotRoot).(*ocbinds.Device), app.ygotTarget) if err != nil { log.Error("generateGetResponsePayload() failed") return GetResponse{Payload: payload, ErrSrc: AppErr}, err } var dat map[string]interface{} - err = json.Unmarshal(payload, &dat) + err = json.Unmarshal(resPayload, &dat) - return GetResponse{Payload: payload}, err + return GetResponse{Payload: resPayload}, err } func (app *CommonApp) translateCRUDCommon(d *db.DB, opcode int) ([]db.WatchKeys, error) { From 6ca2b16a7996a6a03988a96063a935afe6e0b38b Mon Sep 17 00:00:00 2001 From: s-mari Date: Mon, 30 Sep 2019 18:05:25 -0700 Subject: [PATCH 182/214] added key-name support for oc yang and support to create and push table with just the keys and no field-value data in to redis. --- src/translib/transformer/xlate_from_db.go | 13 ++++++++----- src/translib/transformer/xlate_to_db.go | 13 ++++++++++++- src/translib/transformer/xspec.go | 10 ++++++++++ 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index ac25687f64..ae8518b132 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -44,13 +44,13 @@ func xfmrHandlerFunc(inParams XfmrParams) (map[string]interface{}, error) { } } - nodeList, nErr := ytypes.GetNode(schRoot, device, path) - if nErr != nil { + nodeList, nodeErr := ytypes.GetNode(schRoot, device, path) + if nodeErr != nil { log.Infof("Failed to get node for xpath(\"%v\") err(%v).", inParams.uri, err) return result, err } node := nodeList[0].Data - nodeYgot, _:= (node).(ygot.ValidatedGoStruct) + nodeYgot, _ := (node).(ygot.ValidatedGoStruct) payload, err := ygot.EmitJSON(nodeYgot, &ygot.EmitJSONConfig{ Format: ygot.RFC7951, Indent: " ", SkipValidation: true, RFC7951Config: &ygot.RFC7951JSONConfig{ AppendModuleName: false, }, @@ -216,9 +216,9 @@ func directDbToYangJsonCreate(dbDataMap *map[db.DBNum]map[string]map[string]db.V dbIndex := db.ConfigDB if ok { dbIndex = dbSpecData.dbIndex + yangKeys := yangKeyFromEntryGet(xDbSpecMap[tblName].dbEntry) + sonicKeyDataAdd(dbIndex, yangKeys, keyStr, curMap) } - yangKeys := yangKeyFromEntryGet(xDbSpecMap[tblName].dbEntry) - sonicKeyDataAdd(dbIndex, yangKeys, keyStr, curMap) if curMap != nil { mapSlice = append(mapSlice, curMap) } @@ -359,6 +359,9 @@ func terminalNodeProcess(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string } } else { dbFldName := xYangSpecMap[xpath].fieldName + if dbFldName == "NONE" { + return resFldValMap, err + } /* if there is no transformer extension/annotation then it means leaf-list in yang is also leaflist in db */ if len(dbFldName) > 0 && !xYangSpecMap[xpath].isKey { yangType := yangTypeGet(xYangSpecMap[xpath].yangEntry) diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index 7e4cb108b4..089ebd8c96 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -42,6 +42,10 @@ func dataToDBMapAdd(tableName string, dbKey string, result map[string]map[string result[tableName][dbKey] = db.Value{Field: make(map[string]string)} } + if field == "NONE" { + result[tableName][dbKey].Field["NULL"] = "NULL" + } + result[tableName][dbKey].Field[field] = value return } @@ -397,6 +401,8 @@ func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, return err } curKey = ret[0].Interface().(string) + } else if xYangSpecMap[xpathPrefix].keyName != nil { + curKey = *xYangSpecMap[xpathPrefix].keyName } else { curKey = keyCreate(keyName, xpathPrefix, data, d.Opts.KeySeparator) } @@ -434,7 +440,10 @@ func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, return err } curKey = ret[0].Interface().(string) + } else if xYangSpecMap[xpath].keyName != nil { + curKey = *xYangSpecMap[xpath].keyName } + if (typeOfValue == reflect.Map || typeOfValue == reflect.Slice) && xYangSpecMap[xpath].yangDataType != "leaf-list" { if xYangSpecMap[xpath] != nil && len(xYangSpecMap[xpath].xfmrFunc) > 0 { /* subtree transformer present */ @@ -520,7 +529,9 @@ func xpathKeyExtract(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string) (st return "", "", "" } keyStr = ret[0].Interface().(string) - } else { + } else if xYangSpecMap[yangXpath].keyName != nil { + keyStr += *xYangSpecMap[yangXpath].keyName + } else { var keyl []string for _, kname := range rgp.FindAllString(k, -1) { keyl = append(keyl, strings.TrimRight(strings.TrimLeft(kname, "["), "]")) diff --git a/src/translib/transformer/xspec.go b/src/translib/transformer/xspec.go index 3327805223..ed16d03405 100644 --- a/src/translib/transformer/xspec.go +++ b/src/translib/transformer/xspec.go @@ -25,6 +25,7 @@ type yangXpathInfo struct { xfmrPost string validateFunc string xfmrKey string + keyName *string dbIndex db.DBNum keyLevel int isKey bool @@ -283,6 +284,11 @@ func annotEntryFill(xYangSpecMap map[string]*yangXpathInfo, xpath string, entry *xpathData.tableName = ext.NName() updateDbTableData(xpath, xpathData, *xpathData.tableName) //childToUpdateParent(xpath, *xpathData.tableName) + case "key-name" : + if xpathData.keyName == nil { + xpathData.keyName = new(string) + } + *xpathData.keyName = ext.NName() case "table-transformer" : if xpathData.xfmrTbl == nil { xpathData.xfmrTbl = new(string) @@ -462,6 +468,10 @@ func mapPrint(inMap map[string]*yangXpathInfo, fileName string) { if d.xfmrTbl != nil { fmt.Fprintf(fp, "%v", *d.xfmrTbl) } + fmt.Fprintf(fp, "\r\n keyName : ") + if d.keyName != nil { + fmt.Fprintf(fp, "%v", *d.keyName) + } fmt.Fprintf(fp, "\r\n childTbl : %v", d.childTable) fmt.Fprintf(fp, "\r\n FieldName: %v", d.fieldName) fmt.Fprintf(fp, "\r\n keyLevel : %v", d.keyLevel) From 3fba930e7d9f8765b518c7d5e96447427c8d0333 Mon Sep 17 00:00:00 2001 From: Partha Dutta Date: Tue, 1 Oct 2019 11:03:54 +0530 Subject: [PATCH 183/214] Updated Makefile --- src/cvl/schema/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/cvl/schema/Makefile b/src/cvl/schema/Makefile index 911ab84184..1844920d34 100644 --- a/src/cvl/schema/Makefile +++ b/src/cvl/schema/Makefile @@ -16,6 +16,7 @@ schema: $(out) $(out_common) schema-tree: $(out_tree) +#Build YANG models %.yin:$(sonic_yang)/%.yang @echo "Generating `basename $@` ..." @devFile="`echo $@ | cut -d . -f1`-deviation.yang"; \ @@ -23,6 +24,7 @@ schema-tree: $(out_tree) pyang -p $(search_path) --plugindir $(pyang_plugin_dir) \ -f yin-cvl $$devOpt $< -o `basename $@` +#Build common YANG models %.yin:$(sonic_yang_common)/%.yang @echo "Generating `basename $@` ..." @devFile="`echo $@ | cut -d . -f1`-deviation.yang"; \ From ae33c02f6846c60cd10a0c13a2d14cf623c8d255 Mon Sep 17 00:00:00 2001 From: amrutasali Date: Tue, 1 Oct 2019 08:27:15 +0000 Subject: [PATCH 184/214] OC Yang Get case - DB type based key-delimiter support in transformer core --- .../annotations/openconfig-acl-annot.yang | 1 - src/translib/transformer/xlate_to_db.go | 50 +++++++++++++------ src/translib/transformer/xlate_utils.go | 23 ++------- 3 files changed, 40 insertions(+), 34 deletions(-) diff --git a/models/yang/annotations/openconfig-acl-annot.yang b/models/yang/annotations/openconfig-acl-annot.yang index 28b98e9b4e..0c9d7edd42 100644 --- a/models/yang/annotations/openconfig-acl-annot.yang +++ b/models/yang/annotations/openconfig-acl-annot.yang @@ -18,7 +18,6 @@ module openconfig-acl-annot { deviation /oc-acl:acl/oc-acl:acl-sets/oc-acl:acl-set { deviate add { sonic-ext:table-name "ACL_TABLE"; - sonic-ext:key-delimiter "_"; } } diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index 6e2e189325..18ea1d905a 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -519,15 +519,30 @@ func sonicXpathKeyExtract(path string) (string, string, string) { func xpathKeyExtract(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string) (string, string, string) { keyStr := "" tableName := "" + pfxPath := "" rgp := regexp.MustCompile(`\[([^\[\]]*)\]`) curPathWithKey := "" + cdb := db.ConfigDB var dbs [db.MaxDB]*db.DB + pfxPath, _ = RemoveXPATHPredicates(path) + xpathInfo, ok := xYangSpecMap[pfxPath] + if !ok { + log.Errorf("No entry found in xYangSpecMap for xpath %v.", pfxPath) + return pfxPath, keyStr, tableName + } + cdb = xpathInfo.dbIndex + dbOpts := getDBOptions(cdb) + keySeparator := dbOpts.KeySeparator + if len(xpathInfo.delim) > 0 { + keySeparator = xpathInfo.delim + } + for _, k := range strings.Split(path, "/") { curPathWithKey += k if strings.Contains(k, "[") { if len(keyStr) > 0 { - keyStr += "|" + keyStr += keySeparator } yangXpath, _ := RemoveXPATHPredicates(curPathWithKey) _, ok := xYangSpecMap[yangXpath] @@ -541,27 +556,32 @@ func xpathKeyExtract(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string) (st } keyStr = ret[0].Interface().(string) } else if xYangSpecMap[yangXpath].keyName != nil { - keyStr += *xYangSpecMap[yangXpath].keyName - } else { - var keyl []string - for _, kname := range rgp.FindAllString(k, -1) { - keyl = append(keyl, strings.TrimRight(strings.TrimLeft(kname, "["), "]")) + keyStr += *xYangSpecMap[yangXpath].keyName + } else { + /* multi-leaf yang key together forms a single key-string in redis. + There should be key-transformer, if not then the yang key leaves + will be concatenated with respective default DB type key-delimiter + */ + for idx, kname := range rgp.FindAllString(k, -1) { + if idx > 0 { keyStr += keySeparator } + keyl := strings.TrimRight(strings.TrimLeft(kname, "["), "]") + if strings.Contains(keyl, ":") { + keyl = strings.Split(keyl, ":")[1] + } + keyStr += strings.Split(keyl, "=")[1] } - keyStr += keyFromXpathCreate(keyl) } } } curPathWithKey += "/" } - pfxPath, _ := RemoveXPATHPredicates(path) - if _, ok := xYangSpecMap[pfxPath]; ok { - tblPtr := xYangSpecMap[pfxPath].tableName - if tblPtr != nil { - tableName = *tblPtr - } else if xYangSpecMap[pfxPath].xfmrTbl != nil { + //pfxPath, _ := RemoveXPATHPredicates(path) + tblPtr := xpathInfo.tableName + if tblPtr != nil { + tableName = *tblPtr + } else if xpathInfo.xfmrTbl != nil { inParams := formXfmrInputRequest(d, dbs, db.MaxDB, ygRoot, curPathWithKey, oper, "", nil, nil) - tableName, _ = tblNameFromTblXfmrGet(*xYangSpecMap[pfxPath].xfmrTbl, inParams) - } + tableName, _ = tblNameFromTblXfmrGet(*xpathInfo.xfmrTbl, inParams) } return pfxPath, keyStr, tableName } diff --git a/src/translib/transformer/xlate_utils.go b/src/translib/transformer/xlate_utils.go index bb21f339a5..81e94f89b8 100644 --- a/src/translib/transformer/xlate_utils.go +++ b/src/translib/transformer/xlate_utils.go @@ -11,35 +11,22 @@ import ( log "github.com/golang/glog" ) -/* Create db key from datd xpath(request) */ -func keyFromXpathCreate(keyList []string) string { - keyOut := "" - for i, k := range keyList { - if i > 0 { keyOut += "_" } - if strings.Contains(k, ":") { - k = strings.Split(k, ":")[1] - } - keyOut += strings.Split(k, "=")[1] - } - return keyOut -} - /* Create db key from data xpath(request) */ func keyCreate(keyPrefix string, xpath string, data interface{}, dbKeySep string) string { _, ok := xYangSpecMap[xpath] if ok { if xYangSpecMap[xpath].yangEntry != nil { yangEntry := xYangSpecMap[xpath].yangEntry - keyConcat := dbKeySep + delim := dbKeySep if len(xYangSpecMap[xpath].delim) > 0 { - keyConcat = xYangSpecMap[xpath].delim - log.Infof("key concatenater(\"%v\") found for xpath %v ", keyConcat, xpath) + delim = xYangSpecMap[xpath].delim + log.Infof("key concatenater(\"%v\") found for xpath %v ", delim, xpath) } - if len(keyPrefix) > 0 { keyPrefix += dbKeySep } + if len(keyPrefix) > 0 { keyPrefix += delim } keyVal := "" for i, k := range (strings.Split(yangEntry.Key, " ")) { - if i > 0 { keyVal = keyVal + keyConcat } + if i > 0 { keyVal = keyVal + delim } val := fmt.Sprint(data.(map[string]interface{})[k]) if strings.Contains(val, ":") { val = strings.Split(val, ":")[1] From 57eaddede74d2cc2cd1f2b543af054341978af6a Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Tue, 1 Oct 2019 12:35:00 -0700 Subject: [PATCH 185/214] Add check for no xfmrFunc defined case --- src/translib/transformer/xlate_from_db.go | 22 ++++++++++++------- src/translib/transformer/xlate_to_db.go | 26 ++++++++++++++++------- 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index ae8518b132..72e8c1aa43 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -65,8 +65,12 @@ func leafXfmrHandlerFunc(inParams XfmrParams) (map[string]interface{}, error) { if err != nil { return nil, err } - fldValMap := ret[0].Interface().(map[string]interface{}) - return fldValMap, nil + if ret != nil { + fldValMap := ret[0].Interface().(map[string]interface{}) + return fldValMap, nil + } else { + return nil, nil + } } func validateHandlerFunc(inParams XfmrParams) (bool) { @@ -307,7 +311,7 @@ func yangListDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, x if len(xYangSpecMap[xpath].xfmrFunc) > 0 { inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, curUri, GET, "", dbDataMap, nil) cmap, _ := xfmrHandlerFunc(inParams) - if len(cmap) > 0 { + if cmap != nil && len(cmap) > 0 { mapSlice = append(mapSlice, curMap) } else { log.Infof("Empty container returned from overloaded transformer for(\"%v\")", curUri) @@ -354,9 +358,11 @@ func terminalNodeProcess(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string err = fmt.Errorf("%v", logStr) return resFldValMap, err } - for lf, val := range fldValMap { + if fldValMap != nil { + for lf, val := range fldValMap { resFldValMap[lf] = val - } + } + } } else { dbFldName := xYangSpecMap[xpath].fieldName if dbFldName == "NONE" { @@ -426,7 +432,7 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath if len(xYangSpecMap[chldXpath].xfmrFunc) > 0 { inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, chldUri, GET, "", dbDataMap, nil) cmap, _ := xfmrHandlerFunc(inParams) - if len(cmap) > 0 { + if cmap != nil && len(cmap) > 0 { resultMap[cname] = cmap } else { log.Infof("Empty container(\"%v\").\r\n", chldUri) @@ -454,7 +460,7 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath if len(xYangSpecMap[chldXpath].xfmrFunc) > 0 { inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, chldUri, GET, "", dbDataMap, nil) cmap, _ := xfmrHandlerFunc(inParams) - if len(cmap) > 0 { + if cmap != nil && len(cmap) > 0 { resultMap = cmap } else { log.Infof("Empty list(\"%v\").\r\n", chldUri) @@ -516,7 +522,7 @@ func dbDataToYangJsonCreate(uri string, ygRoot *ygot.GoStruct, dbs [db.MaxDB]*db if len(xYangSpecMap[reqXpath].xfmrFunc) > 0 { inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, uri, GET, "", dbDataMap, nil) cmap, _ = xfmrHandlerFunc(inParams) - if len(cmap) > 0 { + if cmap != nil && len(cmap) > 0 { resultMap[cname] = cmap } else { err := yangDataFill(dbs, ygRoot, uri, reqXpath, dbDataMap, resultMap, tableName, keyName, cdb, false) diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index 18ea1d905a..39cddcf57f 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -128,10 +128,12 @@ func mapFillData(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, dbKey st if err != nil { return err } - retData := ret[0].Interface().(map[string]string) - log.Info("Transformer function :", xpathInfo.xfmrFunc, " Xpath: ", xpath, " retData: ", retData) - for f, v := range retData { - dataToDBMapAdd(tableName, dbKey, result, f, v) + if ret != nil { + retData := ret[0].Interface().(map[string]string) + log.Info("Transformer function :", xpathInfo.xfmrFunc, " Xpath: ", xpath, " retData: ", retData) + for f, v := range retData { + dataToDBMapAdd(tableName, dbKey, result, f, v) + } } return nil } @@ -402,7 +404,9 @@ func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, if err != nil { return err } - curKey = ret[0].Interface().(string) + if ret != nil { + curKey = ret[0].Interface().(string) + } } else if xYangSpecMap[xpathPrefix].keyName != nil { curKey = *xYangSpecMap[xpathPrefix].keyName } else { @@ -442,7 +446,9 @@ func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, if err != nil { return err } - curKey = ret[0].Interface().(string) + if ret != nil { + curKey = ret[0].Interface().(string) + } } else if xYangSpecMap[xpath].keyName != nil { curKey = *xYangSpecMap[xpath].keyName } @@ -459,7 +465,9 @@ func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, if err != nil { return nil } - mapCopy(result, ret[0].Interface().(map[string]map[string]db.Value)) + if ret != nil { + mapCopy(result, ret[0].Interface().(map[string]map[string]db.Value)) + } } else { yangReqToDbMapCreate(d, ygRoot, oper, curUri, xpath, curKey, jData.MapIndex(key).Interface(), result) } @@ -554,7 +562,9 @@ func xpathKeyExtract(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string) (st if err != nil { return "", "", "" } - keyStr = ret[0].Interface().(string) + if ret != nil { + keyStr = ret[0].Interface().(string) + } } else if xYangSpecMap[yangXpath].keyName != nil { keyStr += *xYangSpecMap[yangXpath].keyName } else { From 44741499ae9a153612d7cd54024f6e9b72369adc Mon Sep 17 00:00:00 2001 From: Tejaswi Goel Date: Wed, 2 Oct 2019 07:22:19 -0700 Subject: [PATCH 186/214] Correct naming convention for Interface commands Signed-off-by: Tejaswi Goel --- src/CLI/clitree/cli-xml/interface.xml | 16 ++++++++-------- src/CLI/renderer/templates/show_portchannel.j2 | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/CLI/clitree/cli-xml/interface.xml b/src/CLI/clitree/cli-xml/interface.xml index 5ef58c8650..b555b5a58b 100644 --- a/src/CLI/clitree/cli-xml/interface.xml +++ b/src/CLI/clitree/cli-xml/interface.xml @@ -97,12 +97,12 @@ limitations under the License. @@ -154,7 +154,7 @@ limitations under the License. @@ -452,10 +452,10 @@ limitations under the License. /> + help="Configure the minimum number of links in a PortChannel"> python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_if_aggregate_interfaces_interface_aggregation_config_min_links ${po_id} ${min-links} diff --git a/src/CLI/renderer/templates/show_portchannel.j2 b/src/CLI/renderer/templates/show_portchannel.j2 index d1dba6e31e..da5986b640 100644 --- a/src/CLI/renderer/templates/show_portchannel.j2 +++ b/src/CLI/renderer/templates/show_portchannel.j2 @@ -1,6 +1,6 @@ {% set just_var = 2 %} Flags: D - Down - U - Up (port-channel) + U - Up (PortChannel) {{'----------------------------------------------------------------------------------------------------------------------------'}} {{'%-20s'|format("Group")}}{{'%-30s'|format("Port-Channel")}}{{'%-20s'|format("Type")}}{{'%-15s'|format("Protocol")}}{{'%-15s'|format("Member Ports")}} From 2fc250f495cf698e06484132111241ad5dd3eb76 Mon Sep 17 00:00:00 2001 From: amrutasali Date: Wed, 2 Oct 2019 15:20:26 +0000 Subject: [PATCH 187/214] Changed processLeafList() function name to checkAndProcessLeafList() , added comments and removed unnecessary logs in common app --- src/translib/common_app.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/translib/common_app.go b/src/translib/common_app.go index 8ab5fac646..5648acd798 100644 --- a/src/translib/common_app.go +++ b/src/translib/common_app.go @@ -8,7 +8,7 @@ import ( "github.com/openconfig/ygot/ygot" "reflect" "translib/db" - "translib/ocbinds" + "translib/ocbinds" "translib/tlerr" "translib/transformer" "encoding/json" @@ -291,11 +291,11 @@ func (app *CommonApp) cmnAppCRUCommonDbOpn(d *db.DB, opcode int) error { case UPDATE: if existingEntry.IsPopulated() { log.Info("Entry already exists hence modifying it.") - /* Handle leaf-list merge + /* Handle leaf-list merge if any leaf-list exists A leaf-list field in redis has "@" suffix as per swsssdk convention. */ resTblRw := db.Value{Field: map[string]string{}} - resTblRw = processLeafList(existingEntry, tblRw, UPDATE, d, tblNm, tblKey) + resTblRw = checkAndProcessLeafList(existingEntry, tblRw, UPDATE, d, tblNm, tblKey) err = d.ModEntry(cmnAppTs, db.Key{Comp: []string{tblKey}}, resTblRw) if err != nil { log.Error("UPDATE case - d.ModEntry() failure") @@ -395,8 +395,8 @@ func (app *CommonApp) cmnAppDelDbOpn(d *db.DB, opcode int) error { log.Info("Table Entry from which the fields are to be deleted does not exist") return err } - /*handle leaf-list merge*/ - resTblRw := processLeafList(existingEntry, tblRw, DELETE, d, tblNm, tblKey) + /* handle leaf-list merge if any leaf-list exists */ + resTblRw := checkAndProcessLeafList(existingEntry, tblRw, DELETE, d, tblNm, tblKey) err := d.DeleteEntryFields(cmnAppTs, db.Key{Comp: []string{tblKey}}, resTblRw) if err != nil { log.Error("DELETE case - d.DeleteEntryFields() failure") @@ -417,8 +417,8 @@ func (app *CommonApp) generateDbWatchKeys(d *db.DB, isDeleteOp bool) ([]db.Watch return keys, err } -func processLeafList(existingEntry db.Value, tblRw db.Value, opcode int, d *db.DB, tblNm string, tblKey string) db.Value { - log.Info("process leaf-list Fields in table row.") +/*check if any field is leaf-list , if yes perform merge*/ +func checkAndProcessLeafList(existingEntry db.Value, tblRw db.Value, opcode int, d *db.DB, tblNm string, tblKey string) db.Value { dbTblSpec := &db.TableSpec{Name: tblNm} mergeTblRw := db.Value{Field: map[string]string{}} for field, value := range tblRw.Field { From f793f74a6bcfb6bb8743ed978e1ce181d872a050 Mon Sep 17 00:00:00 2001 From: s-mari Date: Wed, 2 Oct 2019 11:15:02 -0700 Subject: [PATCH 188/214] fix for vlan get-req crash --- src/translib/transformer/xlate_from_db.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index 72e8c1aa43..62716c71e6 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -437,6 +437,7 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath } else { log.Infof("Empty container(\"%v\").\r\n", chldUri) } + continue } else if xYangSpecMap[chldXpath].xfmrTbl != nil { xfmrTblFunc := *xYangSpecMap[chldXpath].xfmrTbl if len(xfmrTblFunc) > 0 { @@ -445,6 +446,9 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath if len(tblList) > 1 { log.Warningf("Table transformer returned more than one table for container %v", chldXpath) } + if len(tblList) == 0 { + continue + } dbDataFromTblXfmrGet(tblList[0], inParams, dbDataMap) } } From 3e79fc5fd296500b0961bc7c10a624a20c94264e Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Wed, 2 Oct 2019 13:19:55 -0700 Subject: [PATCH 189/214] sonic yang get case handling for table instance level --- src/translib/common_app.go | 20 +++++++++------- src/translib/transformer/xlate_from_db.go | 29 +++++++++++++++++++---- 2 files changed, 36 insertions(+), 13 deletions(-) diff --git a/src/translib/common_app.go b/src/translib/common_app.go index 5648acd798..d6229b0a30 100644 --- a/src/translib/common_app.go +++ b/src/translib/common_app.go @@ -155,6 +155,7 @@ func (app *CommonApp) processDelete(d *db.DB) (SetResponse, error) { func (app *CommonApp) processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error) { var err error var payload []byte + var resPayload []byte log.Info("processGet:path =", app.pathInfo.Path) payload, err = transformer.GetAndXlateFromDB(app.pathInfo.Path, app.ygotRoot, dbs) @@ -170,17 +171,20 @@ func (app *CommonApp) processGet(dbs [db.MaxDB]*db.DB) (GetResponse, error) { log.Error("ocbinds.Unmarshal() failed. error:", err) return GetResponse{Payload: payload, ErrSrc: AppErr}, err } - } - resPayload, err := generateGetResponsePayload(app.pathInfo.Path, (*app.ygotRoot).(*ocbinds.Device), app.ygotTarget) - if err != nil { - log.Error("generateGetResponsePayload() failed") - return GetResponse{Payload: payload, ErrSrc: AppErr}, err + resPayload, err = generateGetResponsePayload(app.pathInfo.Path, (*app.ygotRoot).(*ocbinds.Device), app.ygotTarget) + if err != nil { + log.Error("generateGetResponsePayload() failed") + return GetResponse{Payload: payload, ErrSrc: AppErr}, err + } + var dat map[string]interface{} + err = json.Unmarshal(resPayload, &dat) + } else { + log.Warning("processGet. targetObj is null. Unable to Unmarshal payload") + resPayload = payload } - var dat map[string]interface{} - err = json.Unmarshal(resPayload, &dat) - return GetResponse{Payload: resPayload}, err + return GetResponse{Payload: resPayload}, err } func (app *CommonApp) translateCRUDCommon(d *db.DB, opcode int) ([]db.WatchKeys, error) { diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index 62716c71e6..81ff39e81c 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -173,8 +173,13 @@ func processLfLstDbToYang(fieldXpath string, dbFldVal string) []interface{} { } /* Traverse db map and create json for cvl yang */ -func directDbToYangJsonCreate(dbDataMap *map[db.DBNum]map[string]map[string]db.Value, jsonData string, resultMap map[string]interface{}) error { +func directDbToYangJsonCreate(uri string, dbDataMap *map[db.DBNum]map[string]map[string]db.Value) (string, error) { var err error + resultMap := make(map[string]interface{}) + instanceMap := make(map[string]interface{}) + terminalNode := false + _, key, table := sonicXpathKeyExtract(uri) + for curDbIdx := db.ApplDB; curDbIdx < db.MaxDB; curDbIdx++ { dbTblData := (*dbDataMap)[curDbIdx] for tblName, tblData := range dbTblData { @@ -213,12 +218,18 @@ func directDbToYangJsonCreate(dbDataMap *map[db.DBNum]map[string]map[string]db.V log.Warningf("Failure in converting Db value type to yang type for xpath", fieldXpath) } else { curMap[resField] = resVal + if table != "" && key != "" && table == tblName && key == keyStr { + instanceMap = curMap + if strings.Contains(uri, resField) { + terminalNode = true + } + } } } } //end of for dbSpecData, ok := xDbSpecMap[tblName] dbIndex := db.ConfigDB - if ok { + if ok && !terminalNode { dbIndex = dbSpecData.dbIndex yangKeys := yangKeyFromEntryGet(xDbSpecMap[tblName].dbEntry) sonicKeyDataAdd(dbIndex, yangKeys, keyStr, curMap) @@ -229,8 +240,16 @@ func directDbToYangJsonCreate(dbDataMap *map[db.DBNum]map[string]map[string]db.V } resultMap[tblName] = mapSlice } -} - return err + } + jsonMapData, _ := json.Marshal(resultMap) + if table != "" && key != "" && len(instanceMap) > 0 { + jsonMapData, _ = json.Marshal(instanceMap) + } + + jsonData := fmt.Sprintf("%v", string(jsonMapData)) + jsonDataPrint(jsonData) + return jsonData, err + } func tableNameAndKeyFromDbMapGet(dbDataMap map[string]map[string]db.Value) (string, string, error) { @@ -491,7 +510,7 @@ func dbDataToYangJsonCreate(uri string, ygRoot *ygot.GoStruct, dbs [db.MaxDB]*db jsonData := "" resultMap := make(map[string]interface{}) if isCvlYang(uri) { - directDbToYangJsonCreate(dbDataMap, jsonData, resultMap) + return directDbToYangJsonCreate(uri, dbDataMap) } else { var d *db.DB reqXpath, keyName, tableName := xpathKeyExtract(d, ygRoot, GET, uri) From a79ee264264ea0f10263bd2f1493320961d726a2 Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Wed, 2 Oct 2019 15:45:22 -0700 Subject: [PATCH 190/214] Handle nested db-name annotations for oc --- src/translib/transformer/xspec.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/translib/transformer/xspec.go b/src/translib/transformer/xspec.go index ed16d03405..8587a575ef 100644 --- a/src/translib/transformer/xspec.go +++ b/src/translib/transformer/xspec.go @@ -87,7 +87,8 @@ func yangToDbMapFill (keyLevel int, xYangSpecMap map[string]*yangXpathInfo, entr } } - if ok && parentXpathData.dbIndex != db.ConfigDB { + // If DB Index is not annotated and parent DB index is annotated inherit the DB Index of the parent + if ok && xpathData.dbIndex == db.ConfigDB && parentXpathData.dbIndex != db.ConfigDB { xpathData.dbIndex = parentXpathData.dbIndex } From 8d567e02960e79e6887ec5d2da05754421a04faf Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Wed, 2 Oct 2019 17:50:17 -0700 Subject: [PATCH 191/214] Import module name of the annotated module in annotate template file --- goyang-modified-files/annotate.go | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/goyang-modified-files/annotate.go b/goyang-modified-files/annotate.go index e86d441fad..a98ec7cbee 100644 --- a/goyang-modified-files/annotate.go +++ b/goyang-modified-files/annotate.go @@ -82,6 +82,8 @@ func generate(w io.Writer, e *yang.Entry, path string) { fmt.Fprintf(w, " import %s { prefix %s; }\n", k, allimports[k]) } } + // Include the module for which annotation is being generated + fmt.Fprintf(w, " import %s { prefix %s; }\n", e.Name, e.Prefix.Name) fmt.Fprintln(w) } @@ -92,13 +94,10 @@ func generate(w io.Writer, e *yang.Entry, path string) { name = e.Prefix.Name + ":" + name } - delim := "" - if path != "" { - delim = "/" + if (e.Node.Kind() != "module") { + path = path + "/" + name + printDeviation(w, path) } - path = path + delim + name - - printDeviation(w, path) var names []string for k := range e.Dir { From 8148935e6a1911d343728a7f35212352e0bd26ff Mon Sep 17 00:00:00 2001 From: Ravi Vasanthm Date: Wed, 2 Oct 2019 18:04:43 -0700 Subject: [PATCH 192/214] Added table transformer method prototype. --- src/translib/transformer/xfmr_interface.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/translib/transformer/xfmr_interface.go b/src/translib/transformer/xfmr_interface.go index 7109cf4de8..f9c8c6d3a3 100644 --- a/src/translib/transformer/xfmr_interface.go +++ b/src/translib/transformer/xfmr_interface.go @@ -78,6 +78,14 @@ type ValidateCallpoint func (inParams XfmrParams) (bool) type PostXfmrFunc func (inParams XfmrParams) (map[string]map[string]db.Value, error) +/** + * TableXfmrFunc type is defined to use for table transformer function for dynamic derviation of redis table. + * Param: XfmrParams structure having database pointers, current db, operation, DB data in multidimensional map, YgotRoot, uri + * Return: List of table names, error + **/ +type TableXfmrFunc func (inParams XfmrParams) ([]string, error) + + /** * Xfmr validation interface for validating the callback registration of app modules * transformer methods. @@ -104,3 +112,6 @@ func (SubTreeXfmrYangToDb) xfmrInterfaceValiidate () { func (SubTreeXfmrDbToYang) xfmrInterfaceValiidate () { log.Info("xfmrInterfaceValiidate for SubTreeXfmrDbToYang") } +func (TableXfmrFunc) xfmrInterfaceValiidate () { + log.Info("xfmrInterfaceValiidate for TableXfmrFunc") +} From ff13d87510a8b94c801117026696d6be7a0d980b Mon Sep 17 00:00:00 2001 From: Ravi Vasanthm Date: Wed, 2 Oct 2019 18:08:10 -0700 Subject: [PATCH 193/214] Added table transformer extension --- models/yang/common/sonic-extensions.yang | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/models/yang/common/sonic-extensions.yang b/models/yang/common/sonic-extensions.yang index ff3c315b3d..ced7029938 100644 --- a/models/yang/common/sonic-extensions.yang +++ b/models/yang/common/sonic-extensions.yang @@ -75,4 +75,9 @@ module sonic-extensions { argument "db-name"; description "DB name that will indicate where data is stored. Eg: Config DB, App DB etc"; } + extension table-transformer { + argument "table-transformer-name"; + description "Db table transformer name.This can be applied to either transform yang value to some different format + or choose a specific DB table based on the type."; + } } From c584abd875570e3c0a0f605c8b8414e61a6c4edd Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Thu, 3 Oct 2019 11:56:54 -0700 Subject: [PATCH 194/214] Include the prefix for the module where the grouping is used in annotation template --- goyang-modified-files/annotate.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/goyang-modified-files/annotate.go b/goyang-modified-files/annotate.go index a98ec7cbee..52af66307b 100644 --- a/goyang-modified-files/annotate.go +++ b/goyang-modified-files/annotate.go @@ -107,7 +107,15 @@ func generate(w io.Writer, e *yang.Entry, path string) { if (e.Node.Kind() == "module") { if len(e.Node.(*yang.Module).Augment) > 0 { for _,a := range e.Node.(*yang.Module).Augment { - path = a.Name + pathList := strings.Split(a.Name, "/") + pathList = pathList[1:] + for i, pvar := range pathList { + if len(pvar) > 0 && !strings.Contains(pvar, ":") { + pvar = e.Prefix.Name + ":" + pvar + pathList[i] = pvar + } + } + path = "/" + strings.Join(pathList, "/") handleAugments(w, a, e.Node.(*yang.Module).Grouping, e.Prefix.Name, path) } } @@ -202,7 +210,6 @@ func handleUses(w io.Writer, u []*yang.Uses, grp []*yang.Grouping, prefix string grpN = tokens[1] mod := GetModuleFromPrefix(nprefix) grp = allmodules[mod].Grouping - prefix = nprefix } for _, g := range grp { if grpN == g.Name { From 99d2ae8bbaa7f1d6a5c731736476e9ffbaaa3a50 Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Thu, 3 Oct 2019 13:19:07 -0700 Subject: [PATCH 195/214] Include unique namespace, Use the prefix of the including module --- goyang-modified-files/annotate.go | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/goyang-modified-files/annotate.go b/goyang-modified-files/annotate.go index 52af66307b..243c4168cd 100644 --- a/goyang-modified-files/annotate.go +++ b/goyang-modified-files/annotate.go @@ -53,7 +53,8 @@ func genAnnotate(w io.Writer, entries []*yang.Entry) { for _, e := range entries { if _, ok := modules[e.Name]; ok { var path string = "" - generate(w, e, path) + var prefix string = "" + generate(w, e, path, prefix) // { Add closing brace for each module fmt.Fprintln(w, "}") fmt.Fprintln(w) @@ -62,14 +63,14 @@ func genAnnotate(w io.Writer, entries []*yang.Entry) { } // generate writes to stdoutput a template annotation file entry for the selected modules. -func generate(w io.Writer, e *yang.Entry, path string) { +func generate(w io.Writer, e *yang.Entry, path string, prefix string) { if e.Parent == nil { if e.Name != "" { fmt.Fprintf(w, "module %s-annot {\n", e.Name) //} fmt.Fprintln(w) fmt.Fprintf(w, " yang-version \"%s\";\n", getYangVersion(e.Name, modules)) fmt.Fprintln(w) - fmt.Fprintf(w, " namespace \"http://openconfig.net/yang/annotation\";\n") + fmt.Fprintf(w, " namespace \"http://openconfig.net/yang/annotation/%s-annot\";\n", e.Prefix.Name) if e.Prefix != nil { fmt.Fprintf(w, " prefix \"%s-annot\";\n", e.Prefix.Name) } @@ -90,9 +91,10 @@ func generate(w io.Writer, e *yang.Entry, path string) { } name := e.Name - if e.Prefix != nil { - name = e.Prefix.Name + ":" + name + if prefix == "" && e.Prefix != nil { + prefix = e.Prefix.Name } + name = prefix + ":" + name if (e.Node.Kind() != "module") { path = path + "/" + name @@ -122,7 +124,7 @@ func generate(w io.Writer, e *yang.Entry, path string) { } for _, k := range names { - generate(w, e.Dir[k], path) + generate(w, e.Dir[k], path, prefix) } } From 16b1085d9ce9db1d959631b6d57d948ef30c1a2b Mon Sep 17 00:00:00 2001 From: s-mari Date: Thu, 3 Oct 2019 14:46:43 -0700 Subject: [PATCH 196/214] xspec map and cru support in transformer infra per revised sonic-yang and changed the api-names from cvl to sonic --- src/translib/transformer/xlate.go | 10 +- src/translib/transformer/xlate_from_db.go | 2 +- src/translib/transformer/xlate_to_db.go | 190 +++++++++++++--------- src/translib/transformer/xlate_utils.go | 2 +- src/translib/transformer/xspec.go | 93 ++++++----- 5 files changed, 173 insertions(+), 124 deletions(-) diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index 5baec6c5cb..dded8136bd 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -118,11 +118,11 @@ func XlateUriToKeySpec(uri string, ygRoot *ygot.GoStruct, t *interface{}) (*[]Ke var err error var retdbFormat = make([]KeySpec, 0) - // In case of CVL yang, the tablename and key info is available in the xpath - if isCvlYang(uri) { + // In case of SONIC yang, the tablename and key info is available in the xpath + if isSonicYang(uri) { /* Extract the xpath and key from input xpath */ xpath, keyStr, tableName := sonicXpathKeyExtract(uri) - retdbFormat = fillCvlKeySpec(xpath, tableName, keyStr) + retdbFormat = fillSonicKeySpec(xpath, tableName, keyStr) } else { /* Extract the xpath and key from input xpath */ xpath, keyStr, _ := xpathKeyExtract(nil, ygRoot, 0, uri) @@ -179,7 +179,7 @@ func FillKeySpecs(yangXpath string , keyStr string, retdbFormat *[]KeySpec) ([]K return *retdbFormat } -func fillCvlKeySpec(xpath string , tableName string, keyStr string) ( []KeySpec ) { +func fillSonicKeySpec(xpath string , tableName string, keyStr string) ( []KeySpec ) { var retdbFormat = make([]KeySpec, 0) @@ -311,7 +311,7 @@ func XlateFromDb(uri string, ygRoot *ygot.GoStruct, dbs [db.MaxDB]*db.DB, data m var cdb db.DBNum = db.ConfigDB dbData = data - if isCvlYang(uri) { + if isSonicYang(uri) { xpath, keyStr, tableName := sonicXpathKeyExtract(uri) if (tableName != "") { dbInfo, ok := xDbSpecMap[tableName] diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index 81ff39e81c..03d0e3a241 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -509,7 +509,7 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath func dbDataToYangJsonCreate(uri string, ygRoot *ygot.GoStruct, dbs [db.MaxDB]*db.DB, dbDataMap *map[db.DBNum]map[string]map[string]db.Value, cdb db.DBNum) (string, error) { jsonData := "" resultMap := make(map[string]interface{}) - if isCvlYang(uri) { + if isSonicYang(uri) { return directDbToYangJsonCreate(uri, dbDataMap) } else { var d *db.DB diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index 39cddcf57f..962fe91905 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -11,6 +11,7 @@ import ( "translib/db" "translib/ocbinds" "github.com/openconfig/ygot/ytypes" + "github.com/openconfig/goyang/pkg/yang" log "github.com/golang/glog" ) @@ -177,80 +178,109 @@ func mapFillData(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, dbKey st return nil } -func cvlYangReqToDbMapCreate(jsonData interface{}, result map[string]map[string]db.Value) error { +func sonicYangReqToDbMapCreate(jsonData interface{}, result map[string]map[string]db.Value) error { if reflect.ValueOf(jsonData).Kind() == reflect.Map { data := reflect.ValueOf(jsonData) for _, key := range data.MapKeys() { _, ok := xDbSpecMap[key.String()] if ok { - directDbMapData(key.String(), data.MapIndex(key).Interface(), result) + directDbMapData("", key.String(), data.MapIndex(key).Interface(), result) } else { - cvlYangReqToDbMapCreate(data.MapIndex(key).Interface(), result) + sonicYangReqToDbMapCreate(data.MapIndex(key).Interface(), result) } } } return nil } -func directDbMapData(tableName string, jsonData interface{}, result map[string]map[string]db.Value) bool { - _, ok := xDbSpecMap[tableName] +func dbMapDataFill(uri string, tableName string, keyName string, d map[string]interface{}, result map[string]map[string]db.Value) { + result[tableName][keyName] = db.Value{Field: make(map[string]string)} + for field, value := range d { + fieldXpath := tableName + "/" + field + if _, fieldOk := xDbSpecMap[fieldXpath]; (fieldOk && (xDbSpecMap[fieldXpath].dbEntry != nil)) { + log.Info("Found non-nil yang entry in xDbSpecMap for field xpath = ", fieldXpath) + if xDbSpecMap[fieldXpath].dbEntry.IsLeafList() { + log.Info("Yang type is Leaflist for field = ", field) + field += "@" + fieldDt := reflect.ValueOf(value) + fieldValue := "" + for fidx := 0; fidx < fieldDt.Len(); fidx++ { + if fidx > 0 { + fieldValue += "," + } + fVal := fmt.Sprintf("%v", fieldDt.Index(fidx).Interface()) + fieldValue = fieldValue + fVal + } + result[tableName][keyName].Field[field] = fieldValue + continue + } + } else { + // should ideally never happen , just adding for safety + log.Info("Did not find entry in xDbSpecMap for field xpath = ", fieldXpath) + } + result[tableName][keyName].Field[field] = fmt.Sprintf("%v", value) + } + return +} - if ok && xDbSpecMap[tableName].dbEntry != nil { - dbSpecData := xDbSpecMap[tableName].dbEntry - tblKeyName := strings.Split(dbSpecData.Key, " ") - data := reflect.ValueOf(jsonData) - result[tableName] = make(map[string]db.Value) +func dbMapListDataFill(uri string, tableName string, dbEntry *yang.Entry, jsonData interface{}, result map[string]map[string]db.Value) { + data := reflect.ValueOf(jsonData) + tblKeyName := strings.Split(dbEntry.Key, " ") + for idx := 0; idx < data.Len(); idx++ { + keyName := "" + d := data.Index(idx).Interface().(map[string]interface{}) + for i, k := range tblKeyName { + if i > 0 { + keyName += "|" + } + keyName += fmt.Sprintf("%v", d[k]) + delete(d, k) + } + dbMapDataFill(uri, tableName, keyName, d, result) + } + return +} - for idx := 0; idx < data.Len(); idx++ { - keyName := "" - d := data.Index(idx).Interface().(map[string]interface{}) - for i, k := range tblKeyName { - if i > 0 { - keyName += "|" - } - keyName += fmt.Sprintf("%v", d[k]) - delete(d, k) - } +func directDbMapData(uri string, tableName string, jsonData interface{}, result map[string]map[string]db.Value) bool { + _, ok := xDbSpecMap[tableName] + if ok && xDbSpecMap[tableName].dbEntry != nil { + data := reflect.ValueOf(jsonData).Interface().(map[string]interface{}) + key := "" + dbSpecData := xDbSpecMap[tableName] + result[tableName] = make(map[string]db.Value) + + if dbSpecData.keyName != nil { + key = *dbSpecData.keyName + log.Infof("Fill data for container uri(%v), key(%v)", uri, key) + dbMapDataFill(uri, tableName, key, data, result) + return true + } - result[tableName][keyName] = db.Value{Field: make(map[string]string)} - for field, value := range d { - fieldXpath := tableName + "/" + field - if _, fieldOk := xDbSpecMap[fieldXpath]; (fieldOk && (xDbSpecMap[fieldXpath].dbEntry != nil)) { - log.Info("Found non-nil yang entry in xDbSpecMap for field xpath = ", fieldXpath) - if xDbSpecMap[fieldXpath].dbEntry.IsLeafList() { - log.Info("Yang type is Leaflist for field = ", field) - field += "@" - fieldDt := reflect.ValueOf(value) - fieldValue := "" - for fidx := 0; fidx < fieldDt.Len(); fidx++ { - if fidx > 0 { - fieldValue += "," - } - fVal := fmt.Sprintf("%v", fieldDt.Index(fidx).Interface()) - fieldValue = fieldValue + fVal - } - result[tableName][keyName].Field[field] = fieldValue - continue - } - } else { - // should ideally never happen , just adding for safety - log.Info("Did not find entry in xDbSpecMap for field xpath = ", fieldXpath) - } - result[tableName][keyName].Field[field] = fmt.Sprintf("%v", value) - } - } - return true - } - return false + for k, v := range data { + xpath := tableName + "/" + k + curDbSpecData, ok := xDbSpecMap[xpath] + if ok && curDbSpecData.dbEntry != nil { + eType := yangTypeGet(curDbSpecData.dbEntry) + switch eType { + case "list": + log.Infof("Fill data for list uri(%v)", uri) + dbMapListDataFill(uri, tableName, curDbSpecData.dbEntry, v, result) + default: + log.Infof("Invalid node type for uri(%v)", uri) + } + } + } + } + return true } /* Get the db table, key and field name for the incoming delete request */ func dbMapDelete(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string, jsonData interface{}, result map[string]map[string]db.Value) error { var err error - if isCvlYang(path) { + if isSonicYang(path) { xpathPrefix, keyName, tableName := sonicXpathKeyExtract(path) log.Infof("Delete req: path(\"%v\"), key(\"%v\"), xpathPrefix(\"%v\"), tableName(\"%v\").", path, keyName, xpathPrefix, tableName) - err = cvlYangReqToDbMapDelete(xpathPrefix, tableName, keyName, result) + err = sonicYangReqToDbMapDelete(xpathPrefix, tableName, keyName, result) } else { xpathPrefix, keyName, tableName := xpathKeyExtract(d, ygRoot, oper, path) log.Infof("Delete req: path(\"%v\"), key(\"%v\"), xpathPrefix(\"%v\"), tableName(\"%v\").", path, keyName, xpathPrefix, tableName) @@ -275,7 +305,7 @@ func dbMapDelete(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string, jsonDat return err } -func cvlYangReqToDbMapDelete(xpathPrefix string, tableName string, keyName string, result map[string]map[string]db.Value) error { +func sonicYangReqToDbMapDelete(xpathPrefix string, tableName string, keyName string, result map[string]map[string]db.Value) error { if (tableName != "") { // Specific table entry case result[tableName] = make(map[string]db.Value) @@ -327,8 +357,8 @@ to write into redis-db */ func dbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string, jsonData interface{}, result map[string]map[string]db.Value) error { var err error root := xpathRootNameGet(path) - if isCvlYang(path) { - err = cvlYangReqToDbMapCreate(jsonData, result) + if isSonicYang(path) { + err = sonicYangReqToDbMapCreate(jsonData, result) } else { err = yangReqToDbMapCreate(d, ygRoot, oper, root, "", "", jsonData, result) } @@ -492,35 +522,35 @@ func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, } func sonicXpathKeyExtract(path string) (string, string, string) { - xpath, keyStr, tableName := "", "", "" - var err error - xpath, err = RemoveXPATHPredicates(path) - if err != nil { - return xpath, keyStr, tableName - } - rgp := regexp.MustCompile(`\[([^\[\]]*)\]`) - pathsubStr := strings.Split(path , "/") - if len(pathsubStr) > SONIC_TABLE_INDEX { - if strings.Contains(pathsubStr[2], "[") { - tableName = strings.Split(pathsubStr[SONIC_TABLE_INDEX], "[")[0] - } else { - tableName = pathsubStr[SONIC_TABLE_INDEX] + xpath, keyStr, tableName := "", "", "" + var err error + xpath, err = RemoveXPATHPredicates(path) + if err != nil { + return xpath, keyStr, tableName } + rgp := regexp.MustCompile(`\[([^\[\]]*)\]`) + pathsubStr := strings.Split(path , "/") + if len(pathsubStr) > SONIC_TABLE_INDEX { + if strings.Contains(pathsubStr[2], "[") { + tableName = strings.Split(pathsubStr[SONIC_TABLE_INDEX], "[")[0] + } else { + tableName = pathsubStr[SONIC_TABLE_INDEX] + } dbInfo, ok := xDbSpecMap[tableName] - cdb := db.ConfigDB - if !ok { - log.Errorf("No entry in xDbSpecMap for xpath %v in order to fetch DB index.", tableName) - } else { + cdb := db.ConfigDB + if !ok { + log.Errorf("No entry in xDbSpecMap for xpath %v in order to fetch DB index.", tableName) + } else { cdb = dbInfo.dbIndex } dbOpts := getDBOptions(cdb) - for i, kname := range rgp.FindAllString(path, -1) { - if i > 0 { keyStr += dbOpts.KeySeparator } - val := strings.Split(kname, "=")[1] - keyStr += strings.TrimRight(val, "]") - } - } - return xpath, keyStr, tableName + for i, kname := range rgp.FindAllString(path, -1) { + if i > 0 { keyStr += dbOpts.KeySeparator } + val := strings.Split(kname, "=")[1] + keyStr += strings.TrimRight(val, "]") + } + } + return xpath, keyStr, tableName } /* Extract key vars, create db key and xpath */ @@ -550,7 +580,7 @@ func xpathKeyExtract(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string) (st curPathWithKey += k if strings.Contains(k, "[") { if len(keyStr) > 0 { - keyStr += keySeparator + keyStr += keySeparator } yangXpath, _ := RemoveXPATHPredicates(curPathWithKey) _, ok := xYangSpecMap[yangXpath] diff --git a/src/translib/transformer/xlate_utils.go b/src/translib/transformer/xlate_utils.go index 81e94f89b8..16afa18db1 100644 --- a/src/translib/transformer/xlate_utils.go +++ b/src/translib/transformer/xlate_utils.go @@ -202,7 +202,7 @@ func yangKeyFromEntryGet(entry *yang.Entry) []string { return keyList } -func isCvlYang(path string) bool { +func isSonicYang(path string) bool { if strings.HasPrefix(path, "/sonic") { return true } diff --git a/src/translib/transformer/xspec.go b/src/translib/transformer/xspec.go index 8587a575ef..3444b51fc7 100644 --- a/src/translib/transformer/xspec.go +++ b/src/translib/transformer/xspec.go @@ -39,8 +39,8 @@ type dbInfo struct { yangXpath []string } -var xYangSpecMap map[string]*yangXpathInfo -var xDbSpecMap map[string]*dbInfo +var xYangSpecMap map[string]*yangXpathInfo +var xDbSpecMap map[string]*dbInfo var xDbSpecOrdTblMap map[string][]string //map of module-name to ordered list of db tables { "sonic-acl" : ["ACL_TABLE", "ACL_RULE"] } /* update transformer spec with db-node */ @@ -87,8 +87,8 @@ func yangToDbMapFill (keyLevel int, xYangSpecMap map[string]*yangXpathInfo, entr } } - // If DB Index is not annotated and parent DB index is annotated inherit the DB Index of the parent - if ok && xpathData.dbIndex == db.ConfigDB && parentXpathData.dbIndex != db.ConfigDB { + if ok && xpathData.dbIndex == db.ConfigDB && parentXpathData.dbIndex != db.ConfigDB { + // If DB Index is not annotated and parent DB index is annotated inherit the DB Index of the parent xpathData.dbIndex = parentXpathData.dbIndex } @@ -187,22 +187,41 @@ func yangToDbMapBuild(entries map[string]*yang.Entry) { } /* Fill the map with db details */ -func dbMapFill(prefixPath string, curPath string, moduleNm string, trkTpCnt bool, xDbSpecMap map[string]*dbInfo, entry *yang.Entry) { +func dbMapFill(tableName string, curPath string, moduleNm string, trkTpCnt bool, xDbSpecMap map[string]*dbInfo, entry *yang.Entry) { entryType := entry.Node.Statement().Keyword - if entryType == "list" { - prefixPath = entry.Name - } - if !isYangResType(entryType) { - dbXpath := prefixPath - if entryType != "list" { - dbXpath = prefixPath + "/" + entry.Name + if entry.Name != moduleNm { + if entryType == "container" { + tableName = entry.Name } - xDbSpecMap[dbXpath] = new(dbInfo) - xDbSpecMap[dbXpath].dbEntry = entry - xDbSpecMap[dbXpath].fieldType = entryType - if entryType == "list" { - xDbSpecMap[dbXpath].dbIndex = db.ConfigDB + + if !isYangResType(entryType) { + dbXpath := tableName + if entryType != "container" { + dbXpath = tableName + "/" + entry.Name + } + xDbSpecMap[dbXpath] = new(dbInfo) + xDbSpecMap[dbXpath].dbIndex = db.MaxDB + xDbSpecMap[dbXpath].dbEntry = entry + xDbSpecMap[dbXpath].fieldType = entryType + if entryType == "container" { + xDbSpecMap[dbXpath].dbIndex = db.ConfigDB + if entry.Exts != nil && len(entry.Exts) > 0 { + for _, ext := range entry.Exts { + dataTagArr := strings.Split(ext.Keyword, ":") + tagType := dataTagArr[len(dataTagArr)-1] + switch tagType { + case "key-name" : + if xDbSpecMap[dbXpath].keyName == nil { + xDbSpecMap[dbXpath].keyName = new(string) + } + *xDbSpecMap[dbXpath].keyName = ext.NName() + default : + log.Infof("Unsupported ext type(%v) for xpath(%v).", tagType, dbXpath) + } + } + } + } } } @@ -218,8 +237,8 @@ func dbMapFill(prefixPath string, curPath string, moduleNm string, trkTpCnt bool } for _, child := range childList { - childPath := prefixPath + "/" + entry.Dir[child].Name - dbMapFill(prefixPath, childPath, moduleNm, trkTpCnt, xDbSpecMap, entry.Dir[child]) + childPath := tableName + "/" + entry.Dir[child].Name + dbMapFill(tableName, childPath, moduleNm, trkTpCnt, xDbSpecMap, entry.Dir[child]) } } @@ -236,7 +255,7 @@ func dbMapBuild(entries []*yang.Entry) { continue } moduleNm := e.Name - log.Info("Module name", moduleNm) + log.Infof("Module name(%v)", moduleNm) xDbSpecOrdTblMap[moduleNm] = []string{} trkTpCnt := true dbMapFill("", "", moduleNm, trkTpCnt, xDbSpecMap, e) @@ -522,23 +541,23 @@ func dbMapPrint( fname string) { } func updateSchemaOrderedMap(module string, entry *yang.Entry) { - var children []string - if entry.Node.Statement().Keyword == "module" { - for _, dir := range entry.DirOKeys { - // Gives the yang xpath for the top level container - xpath := "/" + module + ":" + dir - _, ok := xYangSpecMap[xpath] - if ok { - yentry := xYangSpecMap[xpath].yangEntry - if yentry.Node.Statement().Keyword == "container" { - var keyspec = make([]KeySpec, 0) - keyspec = FillKeySpecs(xpath, "" , &keyspec) - children = updateChildTable(keyspec, &children) - } - } + var children []string + if entry.Node.Statement().Keyword == "module" { + for _, dir := range entry.DirOKeys { + // Gives the yang xpath for the top level container + xpath := "/" + module + ":" + dir + _, ok := xYangSpecMap[xpath] + if ok { + yentry := xYangSpecMap[xpath].yangEntry + if yentry.Node.Statement().Keyword == "container" { + var keyspec = make([]KeySpec, 0) + keyspec = FillKeySpecs(xpath, "" , &keyspec) + children = updateChildTable(keyspec, &children) + } + } + } } - } - xDbSpecOrdTblMap[module] = children + xDbSpecOrdTblMap[module] = children } func updateChildTable(keyspec []KeySpec, chlist *[]string) ([]string) { @@ -548,7 +567,7 @@ func updateChildTable(keyspec []KeySpec, chlist *[]string) ([]string) { *chlist = append(*chlist, ks.Ts.Name) } } - *chlist = updateChildTable(ks.Child, chlist) + *chlist = updateChildTable(ks.Child, chlist) } return *chlist } From 1043f562488c000dee2a80b53b5562509eec158f Mon Sep 17 00:00:00 2001 From: rvasanthm <51932293+rvasanthm@users.noreply.github.com> Date: Thu, 3 Oct 2019 14:51:12 -0700 Subject: [PATCH 197/214] Management interface cli tree, actioner implementation and sonic yang for management port and interface config handling. (#153) --- src/CLI/actioner/sonic-cli-if.py | 16 +++ src/CLI/clitree/cli-xml/interface.xml | 118 +++++++++++++++++++++++ src/CLI/clitree/cli-xml/ipv4.xml | 38 +++++++- src/CLI/clitree/cli-xml/ipv6.xml | 30 ++++++ src/CLI/clitree/cli-xml/sonic_types.xml | 7 ++ src/cvl/schema/sonic-mgmt-interface.yang | 55 +++++++++++ src/cvl/schema/sonic-mgmt-port.yang | 66 +++++++++++++ 7 files changed, 329 insertions(+), 1 deletion(-) create mode 100644 src/cvl/schema/sonic-mgmt-interface.yang create mode 100644 src/cvl/schema/sonic-mgmt-port.yang diff --git a/src/CLI/actioner/sonic-cli-if.py b/src/CLI/actioner/sonic-cli-if.py index 5fe245442d..261cb32d7f 100755 --- a/src/CLI/actioner/sonic-cli-if.py +++ b/src/CLI/actioner/sonic-cli-if.py @@ -58,6 +58,22 @@ def generate_body(func, args): elif func.__name__ == 'patch_openconfig_interfaces_interfaces_interface_config_mtu': keypath = [ args[0] ] body = { "openconfig-interfaces:mtu": int(args[1]) } + elif func.__name__ == 'patch_openconfig_if_ethernet_interfaces_interface_ethernet_config_auto_negotiate': + keypath = [ args[0] ] + if args[1] == "true": + body = { "openconfig-if-ethernet:auto-negotiate": True } + else : + body = { "openconfig-if-ethernet:auto-negotiate": False } + elif func.__name__ == 'patch_openconfig_if_ethernet_interfaces_interface_ethernet_config_port_speed': + keypath = [ args[0] ] + speed_map = {"10MBPS":"SPEED_10MB", "100MBPS":"SPEED_100MB", "1GIGE":"SPEED_1GB", "auto":"SPEED_1GB" } + if args[1] not in speed_map.keys(): + print("%Error: Invalid port speed config") + exit(1) + else: + speed = speed_map.get(args[1]) + + body = { "openconfig-if-ethernet:port-speed": speed } elif func.__name__ == 'patch_openconfig_if_ip_interfaces_interface_subinterfaces_subinterface_ipv4_addresses_address_config': sp = args[1].split('/') keypath = [ args[0], 0, sp[0] ] diff --git a/src/CLI/clitree/cli-xml/interface.xml b/src/CLI/clitree/cli-xml/interface.xml index b555b5a58b..cb13fab5ec 100644 --- a/src/CLI/clitree/cli-xml/interface.xml +++ b/src/CLI/clitree/cli-xml/interface.xml @@ -55,6 +55,20 @@ limitations under the License. > + + + + + + + + + + + + + + + python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_interfaces_interfaces_interface_config_enabled ${iface} False + + + python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_interfaces_interfaces_interface_config_enabled ${iface} True + + + + python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_interfaces_interfaces_interface_config_description ${iface} ${desc} + + + python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_interfaces_interfaces_interface_config_description ${iface} "" + + + + python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_interfaces_interfaces_interface_config_mtu ${iface} ${mtu} + + + python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_interfaces_interfaces_interface_config_mtu ${iface} 9100 + + + + python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_if_ethernet_interfaces_interface_ethernet_config_auto_negotiate ${iface} ${autoneg} + + + python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_if_ethernet_interfaces_interface_ethernet_config_auto_negotiate ${iface} false + + + + python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_if_ethernet_interfaces_interface_ethernet_config_port_speed ${iface} ${speed} + + + python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_if_ethernet_interfaces_interface_ethernet_config_port_speed ${iface} 1000 + + diff --git a/src/CLI/clitree/cli-xml/ipv4.xml b/src/CLI/clitree/cli-xml/ipv4.xml index 80ba50ac79..e66f3c56a7 100644 --- a/src/CLI/clitree/cli-xml/ipv4.xml +++ b/src/CLI/clitree/cli-xml/ipv4.xml @@ -79,6 +79,42 @@ limitations under the License. python $SONIC_CLI_ROOT/sonic-cli-if.py delete_openconfig_if_ip_interfaces_interface_subinterfaces_subinterface_ipv4_addresses_address_config_prefix_length ${iface} ${addr} - + + + + + + + + + + + python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_if_ip_interfaces_interface_subinterfaces_subinterface_ipv4_addresses_address_config ${iface} ${addr} + + + + + + python $SONIC_CLI_ROOT/sonic-cli-if.py delete_openconfig_if_ip_interfaces_interface_subinterfaces_subinterface_ipv4_addresses_address_config_prefix_length ${iface} ${addr} + + + diff --git a/src/CLI/clitree/cli-xml/ipv6.xml b/src/CLI/clitree/cli-xml/ipv6.xml index bad92d0215..4449535a7f 100644 --- a/src/CLI/clitree/cli-xml/ipv6.xml +++ b/src/CLI/clitree/cli-xml/ipv6.xml @@ -58,4 +58,34 @@ limitations under the License. + + + + + + python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_if_ip_interfaces_interface_subinterfaces_subinterface_ipv6_addresses_address_config ${iface} ${addr} + + + + + python $SONIC_CLI_ROOT/sonic-cli-if.py delete_openconfig_if_ip_interfaces_interface_subinterfaces_subinterface_ipv6_addresses_address_config_prefix_length ${iface} ${addr} + + + diff --git a/src/CLI/clitree/cli-xml/sonic_types.xml b/src/CLI/clitree/cli-xml/sonic_types.xml index 09a23fe5ef..e7d10c81a8 100644 --- a/src/CLI/clitree/cli-xml/sonic_types.xml +++ b/src/CLI/clitree/cli-xml/sonic_types.xml @@ -48,6 +48,13 @@ limitations under the License. help="" /> + + Date: Thu, 3 Oct 2019 15:45:50 -0700 Subject: [PATCH 198/214] sFlow CLI Template (#147) * sFlow CLI template * Add XML skeleton for the sFlow CLI * Add actioner script * Add renderer template Signed-off-by: Garrick He --- src/CLI/actioner/sonic-cli-sflow.py | 45 +++++++++++ src/CLI/clitree/cli-xml/interface.xml | 41 ++++++---- src/CLI/clitree/cli-xml/sflow.xml | 75 +++++++++++++++++++ src/CLI/renderer/templates/show_sflow.j2 | 9 +++ src/CLI/renderer/templates/show_sflow_intf.j2 | 10 +++ 5 files changed, 167 insertions(+), 13 deletions(-) create mode 100755 src/CLI/actioner/sonic-cli-sflow.py create mode 100644 src/CLI/clitree/cli-xml/sflow.xml create mode 100755 src/CLI/renderer/templates/show_sflow.j2 create mode 100755 src/CLI/renderer/templates/show_sflow_intf.j2 diff --git a/src/CLI/actioner/sonic-cli-sflow.py b/src/CLI/actioner/sonic-cli-sflow.py new file mode 100755 index 0000000000..7ac8ac4d5d --- /dev/null +++ b/src/CLI/actioner/sonic-cli-sflow.py @@ -0,0 +1,45 @@ +#!/usr/bin/python +import sys +import time +import json +import ast +from collections import OrderedDict +from scripts.render_cli import show_cli_output + + +import urllib3 +urllib3.disable_warnings() +plugins = dict() + + +def register(func): + """Register sdk client method as a plug-in""" + plugins[func.__name__] = func + return func + +def call_method(name, args): + method = plugins[name] + return method(args) + +def get_sflow(): + pass + +def get_sflow_interface(): + pass + +def run(func, args): + + # create a body block + if (func.__name__ == 'get_sflow'): + sflow_info = {'sflow' : {'admin_state' : 'enabled', 'polling-interval' : 20, 'agent-id' : 'default'}} + else: + sflow_info = {} + sflow_info['sflow'] = OrderedDict() + for i in range(30): + sflow_info['sflow']['Ethernet'+str(i)] = {'admin_state' : 'enabled', 'sampling_rate' : 4000} + show_cli_output(sys.argv[2], sflow_info) + return + +if __name__ == '__main__': + func = eval(sys.argv[1], globals(), {}) + run(func, sys.argv[2:]) diff --git a/src/CLI/clitree/cli-xml/interface.xml b/src/CLI/clitree/cli-xml/interface.xml index cb13fab5ec..f913ac6808 100644 --- a/src/CLI/clitree/cli-xml/interface.xml +++ b/src/CLI/clitree/cli-xml/interface.xml @@ -1,6 +1,6 @@ +--> - - + python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_if_aggregate_interfaces_interface_ethernet_config_aggregate_id ${iface} ${lag-id} @@ -334,7 +334,7 @@ limitations under the License. help="Disable the interface"> python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_interfaces_interfaces_interface_config_enabled ${iface} False - python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_interfaces_interfaces_interface_config_enabled ${iface} True @@ -401,8 +401,23 @@ limitations under the License. - - + + + + + + + + + + + + + + + + @@ -486,10 +501,10 @@ limitations under the License. name="no" help="Negate a command or set its defaults" /> - - @@ -503,8 +518,8 @@ limitations under the License. - python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_interfaces_interfaces_interface_config_mtu ${po_id} ${mtu} @@ -514,12 +529,12 @@ limitations under the License. help="Remove MTU"> python $SONIC_CLI_ROOT/sonic-cli-if.py patch_openconfig_interfaces_interfaces_interface_config_mtu ${po_id} 9100 - - diff --git a/src/CLI/clitree/cli-xml/sflow.xml b/src/CLI/clitree/cli-xml/sflow.xml new file mode 100644 index 0000000000..167badea2f --- /dev/null +++ b/src/CLI/clitree/cli-xml/sflow.xml @@ -0,0 +1,75 @@ + + + + + + + + python $SONIC_CLI_ROOT/sonic-cli-sflow.py get_sflow show_sflow.j2 + + + + python $SONIC_CLI_ROOT/sonic-cli-sflow.py get_sflow_interface show_sflow_intf.j2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/CLI/renderer/templates/show_sflow.j2 b/src/CLI/renderer/templates/show_sflow.j2 new file mode 100755 index 0000000000..7bd2e9b378 --- /dev/null +++ b/src/CLI/renderer/templates/show_sflow.j2 @@ -0,0 +1,9 @@ +{{'---------------------------------------------------------'}} +{{'Global sFlow Information'.ljust(20)}} +{{'---------------------------------------------------------'}} +{% if json_output and 'sflow' in json_output -%} +{% set sflow_info = json_output['sflow'] %} +{{' admin state: '}}{{sflow_info['admin_state']}} +{{' polling-interval: '}}{{sflow_info['polling-interval']}} +{{' agent-id: '}} {{sflow_info['agent-id']}} +{% endif %} diff --git a/src/CLI/renderer/templates/show_sflow_intf.j2 b/src/CLI/renderer/templates/show_sflow_intf.j2 new file mode 100755 index 0000000000..1499d30e78 --- /dev/null +++ b/src/CLI/renderer/templates/show_sflow_intf.j2 @@ -0,0 +1,10 @@ +{{'-----------------------------------------------------------'}} +{{'sFlow interface configurations'.ljust(20)}} +{{'%40s'|format('Interface Admin State Sampling Rate')}} +{% if json_output and 'sflow' in json_output -%} +{% set sflow_info = json_output['sflow'] %} +{% for intf, values in sflow_info.items() %} +{{'%13s'|format(intf.ljust(10))}} {{sflow_info[intf]['admin_state']}} {{sflow_info[intf]['sampling_rate']}} +{% endfor %} +{% endif %} + From 727d0fe0bf90cbd1b15259e6c46f26b4cefc614e Mon Sep 17 00:00:00 2001 From: s-mari Date: Thu, 3 Oct 2019 16:19:22 -0700 Subject: [PATCH 199/214] added code to support reading db data for get req per revised sonic-yang --- src/translib/transformer/xlate.go | 2 +- src/translib/transformer/xlate_from_db.go | 12 ++++++------ src/translib/transformer/xspec.go | 5 +++++ 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index dded8136bd..05b5fbb425 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -205,7 +205,7 @@ func fillSonicKeySpec(xpath string , tableName string, keyStr string) ( []KeySpe if dbInfo.fieldType == "container" { for dir, _ := range dbInfo.dbEntry.Dir { _, ok := xDbSpecMap[dir] - if ok && xDbSpecMap[dir].dbEntry.Node.Statement().Keyword == "list" { + if ok && xDbSpecMap[dir].dbEntry.Node.Statement().Keyword == "container" { cdb := xDbSpecMap[dir].dbIndex dbFormat := KeySpec{} dbFormat.Ts.Name = dir diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index 03d0e3a241..3bebb56f65 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -218,12 +218,12 @@ func directDbToYangJsonCreate(uri string, dbDataMap *map[db.DBNum]map[string]map log.Warningf("Failure in converting Db value type to yang type for xpath", fieldXpath) } else { curMap[resField] = resVal - if table != "" && key != "" && table == tblName && key == keyStr { - instanceMap = curMap - if strings.Contains(uri, resField) { - terminalNode = true - } - } + if table != "" && key != "" && table == tblName && key == keyStr { + instanceMap = curMap + if strings.Contains(uri, resField) { + terminalNode = true + } + } } } } //end of for diff --git a/src/translib/transformer/xspec.go b/src/translib/transformer/xspec.go index 3444b51fc7..eaad4cff73 100644 --- a/src/translib/transformer/xspec.go +++ b/src/translib/transformer/xspec.go @@ -223,6 +223,11 @@ func dbMapFill(tableName string, curPath string, moduleNm string, trkTpCnt bool, } } } + } else { + moduleXpath := "/" + entry.Name + xDbSpecMap[moduleXpath] = new(dbInfo) + xDbSpecMap[moduleXpath].dbEntry = entry + xDbSpecMap[moduleXpath].fieldType = entryType } var childList []string From 1de0b3557a0fe5884dfb04a55eb666e17c78e3c3 Mon Sep 17 00:00:00 2001 From: s-mari Date: Thu, 3 Oct 2019 17:07:17 -0700 Subject: [PATCH 200/214] rearranged the code to call the table transformer and collect data before calling the subtree-transformer overloaded method. --- src/translib/transformer/xlate_from_db.go | 33 ++++++++++++----------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index 3bebb56f65..b630f9891c 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -448,16 +448,7 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath } } else if chldYangType == "container" { cname := xYangSpecMap[chldXpath].yangEntry.Name - if len(xYangSpecMap[chldXpath].xfmrFunc) > 0 { - inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, chldUri, GET, "", dbDataMap, nil) - cmap, _ := xfmrHandlerFunc(inParams) - if cmap != nil && len(cmap) > 0 { - resultMap[cname] = cmap - } else { - log.Infof("Empty container(\"%v\").\r\n", chldUri) - } - continue - } else if xYangSpecMap[chldXpath].xfmrTbl != nil { + if xYangSpecMap[chldXpath].xfmrTbl != nil { xfmrTblFunc := *xYangSpecMap[chldXpath].xfmrTbl if len(xfmrTblFunc) > 0 { inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, chldUri, GET, "", dbDataMap, nil) @@ -469,14 +460,26 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath continue } dbDataFromTblXfmrGet(tblList[0], inParams, dbDataMap) + tbl = tblList[0] } } - cmap := make(map[string]interface{}) - err = yangDataFill(dbs, ygRoot, chldUri, chldXpath, dbDataMap, cmap, tbl, tblKey, cdb, isValid) - if len(cmap) > 0 { - resultMap[cname] = cmap + if len(xYangSpecMap[chldXpath].xfmrFunc) > 0 { + inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, chldUri, GET, "", dbDataMap, nil) + cmap, _ := xfmrHandlerFunc(inParams) + if cmap != nil && len(cmap) > 0 { + resultMap[cname] = cmap + } else { + log.Infof("Empty container(\"%v\").\r\n", chldUri) + } + continue } else { - log.Infof("Empty container(\"%v\").\r\n", chldUri) + cmap := make(map[string]interface{}) + err = yangDataFill(dbs, ygRoot, chldUri, chldXpath, dbDataMap, cmap, tbl, tblKey, cdb, isValid) + if len(cmap) > 0 { + resultMap[cname] = cmap + } else { + log.Infof("Empty container(\"%v\").\r\n", chldUri) + } } } else if chldYangType == "list" { cdb = xYangSpecMap[chldXpath].dbIndex From 857355a1ea456a3c537f8711615251b163674452 Mon Sep 17 00:00:00 2001 From: amrutasali Date: Fri, 4 Oct 2019 01:36:42 +0000 Subject: [PATCH 201/214] Fixed table transformer GET case issues : 1.) calling table-transformer for each leaf when doing a get on parent conatiner(OC-interface) 2.) dbMapData not getting filled for container query in dbDataToYangJsonCreate --- src/translib/transformer/xlate.go | 2 +- src/translib/transformer/xlate_from_db.go | 38 +++++++++++++++++------ src/translib/transformer/xlate_to_db.go | 3 +- 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index 5baec6c5cb..7c426e6770 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -53,7 +53,7 @@ func XlateFuncBind(name string, fn interface{}) (err error) { func XlateFuncCall(name string, params ...interface{}) (result []reflect.Value, err error) { if _, ok := XlateFuncs[name]; !ok { err = errors.New(name + " Xfmr function does not exist.") - return nil, nil + return nil, err } if len(params) != XlateFuncs[name].Type().NumIn() { err = ErrParamsNotAdapted diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index 81ff39e81c..508bb42435 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -369,8 +369,7 @@ func terminalNodeProcess(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string cdb := xYangSpecMap[xpath].dbIndex if len(xYangSpecMap[xpath].xfmrFunc) > 0 { - _, key, _ := xpathKeyExtract(dbs[cdb], ygRoot, GET, uri) - inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, uri, GET, key, dbDataMap, nil) + inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, uri, GET, tblKey, dbDataMap, nil) fldValMap, err := leafXfmrHandlerFunc(inParams) if err != nil { logStr := fmt.Sprintf("%Failed to get data from overloaded function for %v -v.", uri, err) @@ -414,7 +413,6 @@ func terminalNodeProcess(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string return resFldValMap, err } - func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath string, dbDataMap *map[db.DBNum]map[string]map[string]db.Value, resultMap map[string]interface{}, tbl string, tblKey string, cdb db.DBNum, validate bool) error { var err error isValid := validate @@ -425,8 +423,9 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath chldXpath := xpath+"/"+yangChldName chldUri := uri+"/"+yangChldName if xYangSpecMap[chldXpath] != nil && xYangSpecMap[chldXpath].yangEntry != nil { - _, key, _ := xpathKeyExtract(dbs[cdb], ygRoot, GET, chldUri) + cdb = xYangSpecMap[chldXpath].dbIndex if len(xYangSpecMap[chldXpath].validateFunc) > 0 && !validate { + _, key, _ := xpathKeyExtract(dbs[cdb], ygRoot, GET, chldUri) // TODO - handle non CONFIG-DB inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, chldUri, GET, key, dbDataMap, nil) res := validateHandlerFunc(inParams) @@ -437,7 +436,6 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath } } chldYangType := yangTypeGet(xYangSpecMap[chldXpath].yangEntry) - cdb = xYangSpecMap[chldXpath].dbIndex if chldYangType == "leaf" || chldYangType == "leaf-list" { fldValMap, err := terminalNodeProcess(dbs, ygRoot, chldUri, chldXpath, dbDataMap, tbl, tblKey) if err != nil { @@ -542,18 +540,38 @@ func dbDataToYangJsonCreate(uri string, ygRoot *ygot.GoStruct, dbs [db.MaxDB]*db } else if yangType == "container" { cname := xYangSpecMap[reqXpath].yangEntry.Name cmap := make(map[string]interface{}) + IsYangDataFill := true if len(xYangSpecMap[reqXpath].xfmrFunc) > 0 { inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, uri, GET, "", dbDataMap, nil) cmap, _ = xfmrHandlerFunc(inParams) if cmap != nil && len(cmap) > 0 { resultMap[cname] = cmap - } else { - err := yangDataFill(dbs, ygRoot, uri, reqXpath, dbDataMap, resultMap, tableName, keyName, cdb, false) - if err != nil { - log.Infof("Empty container(\"%v\").\r\n", uri) + IsYangDataFill = false + } + } else if xYangSpecMap[reqXpath].xfmrTbl != nil { + xfmrTblFunc := *xYangSpecMap[reqXpath].xfmrTbl + if len(xfmrTblFunc) > 0 { + inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, reqXpath, GET, "", dbDataMap, nil) + tblList := xfmrTblHandlerFunc(xfmrTblFunc, inParams) + if len(tblList) > 1 { + log.Warningf("Table transformer returned more than one table for container %v", reqXpath) + IsYangDataFill = false } + if len(tblList) != 0 { + dbDataFromTblXfmrGet(tblList[0], inParams, dbDataMap) + err := yangDataFill(dbs, ygRoot, uri, reqXpath, dbDataMap, resultMap, tableName, keyName, cdb, false) + if err != nil { + log.Infof("Empty container(\"%v\").\r\n", uri) + } + + } + + } else { + log.Warningf("empty table transformer function name for xpath - %v", reqXpath) + IsYangDataFill = false } - } else { + } + if IsYangDataFill { err := yangDataFill(dbs, ygRoot, uri, reqXpath, dbDataMap, resultMap, tableName, keyName, cdb, false) if err != nil { log.Infof("Empty container(\"%v\").\r\n", uri) diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index 39cddcf57f..29240cad2f 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -585,12 +585,11 @@ func xpathKeyExtract(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string) (st } curPathWithKey += "/" } - //pfxPath, _ := RemoveXPATHPredicates(path) tblPtr := xpathInfo.tableName if tblPtr != nil { tableName = *tblPtr } else if xpathInfo.xfmrTbl != nil { - inParams := formXfmrInputRequest(d, dbs, db.MaxDB, ygRoot, curPathWithKey, oper, "", nil, nil) + inParams := formXfmrInputRequest(d, dbs, cdb, ygRoot, curPathWithKey, oper, "", nil, nil) tableName, _ = tblNameFromTblXfmrGet(*xpathInfo.xfmrTbl, inParams) } return pfxPath, keyStr, tableName From f726b7596586ee5c60c1d0903d353db17925689f Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Thu, 3 Oct 2019 18:59:47 -0700 Subject: [PATCH 202/214] Handle delete for restructured sonic yang --- src/translib/common_app.go | 2 +- src/translib/transformer/xlate_to_db.go | 19 +++++++++++-------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/translib/common_app.go b/src/translib/common_app.go index d6229b0a30..e48c71cdcc 100644 --- a/src/translib/common_app.go +++ b/src/translib/common_app.go @@ -453,7 +453,7 @@ func checkAndProcessLeafList(existingEntry db.Value, tblRw db.Value, opcode int, } /* delete specific item from leaf-list */ if opcode == DELETE { - if mergeTblRw.Field == nil { + if len(mergeTblRw.Field) == 0 { return tblRw } err := d.ModEntry(dbTblSpec, db.Key{Comp: []string{tblKey}}, mergeTblRw) diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index 91e22f10b5..b0ac6a2d26 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -313,13 +313,16 @@ func sonicYangReqToDbMapDelete(xpathPrefix string, tableName string, keyName str // Specific key case var dbVal db.Value tokens:= strings.Split(xpathPrefix, "/") - // Format /module:container/tableName[key]/fieldName - if tokens[len(tokens)-2] == tableName { - // Specific leaf case - fieldName := tokens[len(tokens)-1] - dbVal.Field = make(map[string]string) - dbVal.Field[fieldName] = "" - } + if tokens[SONIC_TABLE_INDEX] == tableName { + fieldName := tokens[len(tokens)-1] + dbSpecField := "/" + fieldName + _, ok := xDbSpecMap[dbSpecField] + if ok && xDbSpecMap[dbSpecField].fieldType == "leaf" { + // Specific leaf case + dbVal.Field = make(map[string]string) + dbVal.Field[fieldName] = "" + } + } result[tableName][keyName] = dbVal } else { // Get all keys @@ -539,7 +542,7 @@ func sonicXpathKeyExtract(path string) (string, string, string) { dbInfo, ok := xDbSpecMap[tableName] cdb := db.ConfigDB if !ok { - log.Errorf("No entry in xDbSpecMap for xpath %v in order to fetch DB index.", tableName) + log.Infof("No entry in xDbSpecMap for xpath %v in order to fetch DB index.", tableName) } else { cdb = dbInfo.dbIndex } From b36c2d0b54d00ebb94e57fde85005cfd290623cc Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Fri, 4 Oct 2019 12:53:00 -0700 Subject: [PATCH 203/214] Strip augmented module names in xpath to reference xYangSpecMap --- src/translib/transformer/xlate_to_db.go | 3 +++ src/translib/transformer/xlate_utils.go | 14 ++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index b0ac6a2d26..441eee127c 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -567,6 +567,9 @@ func xpathKeyExtract(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string) (st var dbs [db.MaxDB]*db.DB pfxPath, _ = RemoveXPATHPredicates(path) + if strings.Count(path, ":") > 1 { + pfxPath = stripAugmentedModuleNames(pfxPath) + } xpathInfo, ok := xYangSpecMap[pfxPath] if !ok { log.Errorf("No entry found in xYangSpecMap for xpath %v.", pfxPath) diff --git a/src/translib/transformer/xlate_utils.go b/src/translib/transformer/xlate_utils.go index 16afa18db1..6afbeeaa74 100644 --- a/src/translib/transformer/xlate_utils.go +++ b/src/translib/transformer/xlate_utils.go @@ -417,3 +417,17 @@ func getDBOptionsWithSeparator(dbNo db.DBNum, initIndicator string, tableSeparat KeySeparator : keySeparator, }) } + +func stripAugmentedModuleNames(xpath string) string { + pathList := strings.Split(xpath, "/") + pathList = pathList[1:] + for i, pvar := range pathList { + if (i > 0) && strings.Contains(pvar, ":") { + pvar = strings.Split(pvar,":")[1] + pathList[i] = pvar + } + } + path := "/" + strings.Join(pathList, "/") + return path +} + From a8746cc262c794bacb5f0ded0b6d9ffcab2306cd Mon Sep 17 00:00:00 2001 From: s-mari Date: Mon, 7 Oct 2019 01:59:30 -0700 Subject: [PATCH 204/214] transformer infra support for revised sonic-yang GET req --- src/translib/transformer/xlate.go | 3 +- src/translib/transformer/xlate_from_db.go | 209 ++++++++++++++-------- src/translib/transformer/xspec.go | 2 +- 3 files changed, 141 insertions(+), 73 deletions(-) diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index 05b5fbb425..471327d5d4 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -197,8 +197,7 @@ func fillSonicKeySpec(xpath string , tableName string, keyStr string) ( []KeySpe retdbFormat = append(retdbFormat, dbFormat) } else { // If table name not available in xpath get top container name - tokens:= strings.Split(xpath, ":") - container := "/" + tokens[len(tokens)-1] + container := xpath if xDbSpecMap != nil { if _, ok := xDbSpecMap[container]; ok { dbInfo := xDbSpecMap[container] diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index b630f9891c..50be238120 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -172,84 +172,153 @@ func processLfLstDbToYang(fieldXpath string, dbFldVal string) []interface{} { return resLst } -/* Traverse db map and create json for cvl yang */ -func directDbToYangJsonCreate(uri string, dbDataMap *map[db.DBNum]map[string]map[string]db.Value) (string, error) { - var err error - resultMap := make(map[string]interface{}) - instanceMap := make(map[string]interface{}) - terminalNode := false - _, key, table := sonicXpathKeyExtract(uri) - - for curDbIdx := db.ApplDB; curDbIdx < db.MaxDB; curDbIdx++ { - dbTblData := (*dbDataMap)[curDbIdx] - for tblName, tblData := range dbTblData { - var mapSlice []typeMapOfInterface - for keyStr, dbFldValData := range tblData { - curMap := make(map[string]interface{}) - for field, value := range dbFldValData.Field { - resField := field - if strings.HasSuffix(field, "@") { - fldVals := strings.Split(field, "@") - resField = fldVals[0] - } - fieldXpath := tblName + "/" + resField - xDbSpecMapEntry, ok := xDbSpecMap[fieldXpath] - if !ok { - log.Warningf("No entry found in xDbSpecMap for xpath %v", fieldXpath) - continue - } - if xDbSpecMapEntry.dbEntry == nil { - log.Warningf("Yang entry is nil in xDbSpecMap for xpath %v", fieldXpath) - continue +func sonicDbToYangTerminalNodeFill(tblName string, field string, value string, resultMap map[string]interface{}) { + resField := field + if len(value) == 0 { + return + } + if strings.HasSuffix(field, "@") { + fldVals := strings.Split(field, "@") + resField = fldVals[0] + } + fieldXpath := tblName + "/" + resField + xDbSpecMapEntry, ok := xDbSpecMap[fieldXpath] + if !ok { + log.Warningf("No entry found in xDbSpecMap for xpath %v", fieldXpath) + return + } + if xDbSpecMapEntry.dbEntry == nil { + log.Warningf("Yang entry is nil in xDbSpecMap for xpath %v", fieldXpath) + return + } + + yangType := yangTypeGet(xDbSpecMapEntry.dbEntry) + if yangType == "leaf-list" { + /* this should never happen but just adding for safetty */ + if !strings.HasSuffix(field, "@") { + log.Warningf("Leaf-list in Sonic yang should also be a leaf-list in DB, its not for xpath %v", fieldXpath) + return + } + resLst := processLfLstDbToYang(fieldXpath, value) + resultMap[resField] = resLst + } else { /* yangType is leaf - there are only 2 types of yang terminal node leaf and leaf-list */ + yngTerminalNdDtType := xDbSpecMapEntry.dbEntry.Type.Kind + resVal, err := DbToYangType(yngTerminalNdDtType, fieldXpath, value) + if err != nil { + log.Warningf("Failure in converting Db value type to yang type for xpath", fieldXpath) + } else { + resultMap[resField] = resVal + } + } + return +} + +func sonicDbToYangListFill(uri string, xpath string, dbIdx db.DBNum, table string, key string, dbDataMap *map[db.DBNum]map[string]map[string]db.Value) []typeMapOfInterface { + var mapSlice []typeMapOfInterface + dbTblData := (*dbDataMap)[dbIdx][table] + + for keyStr, _ := range dbTblData { + curMap := make(map[string]interface{}) + sonicDbToYangDataFill(uri, xpath, dbIdx, table, keyStr, dbDataMap, curMap) + dbSpecData, ok := xDbSpecMap[table] + if ok && dbSpecData.keyName == nil { + yangKeys := yangKeyFromEntryGet(xDbSpecMap[xpath].dbEntry) + sonicKeyDataAdd(dbIdx, yangKeys, keyStr, curMap) + } + if curMap != nil { + mapSlice = append(mapSlice, curMap) + } + } + return mapSlice +} + +func sonicDbToYangDataFill(uri string, xpath string, dbIdx db.DBNum, table string, key string, dbDataMap *map[db.DBNum]map[string]map[string]db.Value, resultMap map[string]interface{}) { + yangNode, ok := xDbSpecMap[xpath] + + if ok && yangNode.dbEntry != nil { + xpathPrefix := table + if len(table) > 0 { xpathPrefix += "/" } + + for yangChldName := range yangNode.dbEntry.Dir { + chldXpath := xpathPrefix+yangChldName + if xDbSpecMap[chldXpath] != nil && xDbSpecMap[chldXpath].dbEntry != nil { + chldYangType := yangTypeGet(xDbSpecMap[chldXpath].dbEntry) + + if chldYangType == YANG_LEAF || chldYangType == YANG_LEAF_LIST { + log.Infof("tbl(%v), k(%v), yc(%v)", table, key, yangChldName) + sonicDbToYangTerminalNodeFill(table, yangChldName, (*dbDataMap)[dbIdx][table][key].Field[yangChldName], resultMap) + } else if chldYangType == YANG_CONTAINER { + curMap := make(map[string]interface{}) + curUri := xpath + "/" + yangChldName + // container can have a static key, so extract key for current container + _, curKey, curTable := sonicXpathKeyExtract(curUri) + // use table-name as xpath from now on + sonicDbToYangDataFill(curUri, curTable, xDbSpecMap[curTable].dbIndex, curTable, curKey, dbDataMap, curMap) + if len(curMap) > 0 { + resultMap[yangChldName] = curMap + } else { + log.Infof("Empty container for xpath(%v)", curUri) } - yangType := yangTypeGet(xDbSpecMapEntry.dbEntry) - if yangType == "leaf-list" { - /* this should never happen but just adding for safetty */ - if !strings.HasSuffix(field, "@") { - log.Warningf("Leaf-list in Sonic yang should also be a leaf-list in DB, its not for xpath %v", fieldXpath) - continue - } - resLst := processLfLstDbToYang(fieldXpath, value) - curMap[resField] = resLst - } else { /* yangType is leaf - there are only 2 types of yang terminal node leaf and leaf-list */ - yngTerminalNdDtType := xDbSpecMapEntry.dbEntry.Type.Kind - resVal, err := DbToYangType(yngTerminalNdDtType, fieldXpath, value) - if err != nil { - log.Warningf("Failure in converting Db value type to yang type for xpath", fieldXpath) + } else if chldYangType == YANG_LIST { + var mapSlice []typeMapOfInterface + curUri := xpath + "/" + yangChldName + mapSlice = sonicDbToYangListFill(curUri, curUri, dbIdx, table, key, dbDataMap) + if len(mapSlice) > 0 { + resultMap[yangChldName] = mapSlice } else { - curMap[resField] = resVal - if table != "" && key != "" && table == tblName && key == keyStr { - instanceMap = curMap - if strings.Contains(uri, resField) { - terminalNode = true - } - } + log.Infof("Empty list for xpath(%v)", curUri) } } - } //end of for - dbSpecData, ok := xDbSpecMap[tblName] - dbIndex := db.ConfigDB - if ok && !terminalNode { - dbIndex = dbSpecData.dbIndex - yangKeys := yangKeyFromEntryGet(xDbSpecMap[tblName].dbEntry) - sonicKeyDataAdd(dbIndex, yangKeys, keyStr, curMap) - } - if curMap != nil { - mapSlice = append(mapSlice, curMap) } } - resultMap[tblName] = mapSlice - } } - jsonMapData, _ := json.Marshal(resultMap) - if table != "" && key != "" && len(instanceMap) > 0 { - jsonMapData, _ = json.Marshal(instanceMap) - } + return +} + +/* Traverse db map and create json for cvl yang */ +func directDbToYangJsonCreate(uri string, dbDataMap *map[db.DBNum]map[string]map[string]db.Value, resultMap map[string]interface{}) (string, error) { + xpath, _ := RemoveXPATHPredicates(uri) + + if len(xpath) > 0 { + var dbNode *dbInfo - jsonData := fmt.Sprintf("%v", string(jsonMapData)) - jsonDataPrint(jsonData) - return jsonData, err + xpath, key, table := sonicXpathKeyExtract(xpath) + if len(table) > 0 { + dbNode = xDbSpecMap[table] + } else { + dbNode, _ = xDbSpecMap[xpath] + } + if dbNode != nil && dbNode.dbEntry != nil { + cdb := db.ConfigDB + yangType := yangTypeGet(dbNode.dbEntry) + if len(table) > 0 { + cdb = xDbSpecMap[table].dbIndex + } + + if yangType == YANG_LEAF || yangType == YANG_LEAF_LIST { + fldName := xDbSpecMap[xpath].dbEntry.Name + sonicDbToYangTerminalNodeFill(table, fldName, (*dbDataMap)[cdb][table][key].Field[fldName], resultMap) + } else if yangType == YANG_CONTAINER { + if len(table) > 0 { + xpath = table + } + sonicDbToYangDataFill(uri, xpath, cdb, table, key, dbDataMap, resultMap) + } else if yangType == YANG_LIST { + mapSlice := sonicDbToYangListFill(uri, xpath, cdb, table, key, dbDataMap) + if len(mapSlice) > 0 { + pathl := strings.Split(xpath, "/") + lname := pathl[len(pathl) - 1] + resultMap[lname] = mapSlice + } + } + } + } + + jsonMapData, _ := json.Marshal(resultMap) + jsonData := fmt.Sprintf("%v", string(jsonMapData)) + jsonDataPrint(jsonData) + return jsonData, nil } func tableNameAndKeyFromDbMapGet(dbDataMap map[string]map[string]db.Value) (string, string, error) { @@ -513,7 +582,7 @@ func dbDataToYangJsonCreate(uri string, ygRoot *ygot.GoStruct, dbs [db.MaxDB]*db jsonData := "" resultMap := make(map[string]interface{}) if isSonicYang(uri) { - return directDbToYangJsonCreate(uri, dbDataMap) + return directDbToYangJsonCreate(uri, dbDataMap, resultMap) } else { var d *db.DB reqXpath, keyName, tableName := xpathKeyExtract(d, ygRoot, GET, uri) diff --git a/src/translib/transformer/xspec.go b/src/translib/transformer/xspec.go index eaad4cff73..11198a645f 100644 --- a/src/translib/transformer/xspec.go +++ b/src/translib/transformer/xspec.go @@ -224,7 +224,7 @@ func dbMapFill(tableName string, curPath string, moduleNm string, trkTpCnt bool, } } } else { - moduleXpath := "/" + entry.Name + moduleXpath := "/" + moduleNm + ":" + entry.Name xDbSpecMap[moduleXpath] = new(dbInfo) xDbSpecMap[moduleXpath].dbEntry = entry xDbSpecMap[moduleXpath].fieldType = entryType From 24016ffd075da2ae93e7aecb0c837756321b149c Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Mon, 7 Oct 2019 13:56:47 -0700 Subject: [PATCH 205/214] Handle delete for restructured sonic acl --- src/translib/transformer/xlate_from_db.go | 5 ++++- src/translib/transformer/xlate_to_db.go | 10 ++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index d64e7816e7..d17d8829fb 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -61,6 +61,9 @@ func xfmrHandlerFunc(inParams XfmrParams) (map[string]interface{}, error) { func leafXfmrHandlerFunc(inParams XfmrParams) (map[string]interface{}, error) { xpath, _ := RemoveXPATHPredicates(inParams.uri) + if strings.Count(xpath, ":") > 1 { + xpath = stripAugmentedModuleNames(xpath) + } ret, err := XlateFuncCall(dbToYangXfmrFunc(xYangSpecMap[xpath].xfmrFunc), inParams) if err != nil { return nil, err @@ -623,7 +626,7 @@ func dbDataToYangJsonCreate(uri string, ygRoot *ygot.GoStruct, dbs [db.MaxDB]*db } else if xYangSpecMap[reqXpath].xfmrTbl != nil { xfmrTblFunc := *xYangSpecMap[reqXpath].xfmrTbl if len(xfmrTblFunc) > 0 { - inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, reqXpath, GET, "", dbDataMap, nil) + inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, uri, GET, "", dbDataMap, nil) tblList := xfmrTblHandlerFunc(xfmrTblFunc, inParams) if len(tblList) > 1 { log.Warningf("Table transformer returned more than one table for container %v", reqXpath) diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index 441eee127c..a1c9faf14b 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -315,7 +315,7 @@ func sonicYangReqToDbMapDelete(xpathPrefix string, tableName string, keyName str tokens:= strings.Split(xpathPrefix, "/") if tokens[SONIC_TABLE_INDEX] == tableName { fieldName := tokens[len(tokens)-1] - dbSpecField := "/" + fieldName + dbSpecField := tableName + "/" + fieldName _, ok := xDbSpecMap[dbSpecField] if ok && xDbSpecMap[dbSpecField].fieldType == "leaf" { // Specific leaf case @@ -330,11 +330,9 @@ func sonicYangReqToDbMapDelete(xpathPrefix string, tableName string, keyName str } else { // Get all table entries // If table name not available in xpath get top container name - tokens:= strings.Split(xpathPrefix, ":") - container := "/" + tokens[len(tokens)-1] - _, ok := xDbSpecMap[container] - if ok && xDbSpecMap[container] != nil { - dbInfo := xDbSpecMap[container] + _, ok := xDbSpecMap[xpathPrefix] + if ok && xDbSpecMap[xpathPrefix] != nil { + dbInfo := xDbSpecMap[xpathPrefix] if dbInfo.fieldType == "container" { for dir, _ := range dbInfo.dbEntry.Dir { result[dir] = make(map[string]db.Value) From e3331fbd3f62a7aa33c0d2ff9f5c70a8ebe63750 Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Mon, 7 Oct 2019 16:04:49 -0700 Subject: [PATCH 206/214] Fix the leaf level get for restructured sonic yang --- src/translib/transformer/xconst.go | 2 ++ src/translib/transformer/xlate.go | 10 +++++++--- src/translib/transformer/xlate_from_db.go | 16 +++++++++++++--- src/translib/transformer/xlate_to_db.go | 3 --- 4 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/translib/transformer/xconst.go b/src/translib/transformer/xconst.go index a20d297934..bcc2d0ffb3 100644 --- a/src/translib/transformer/xconst.go +++ b/src/translib/transformer/xconst.go @@ -28,4 +28,6 @@ const ( XPATH_SEP_FWD_SLASH = "/" XFMR_EMPTY_STRING = "" + SONIC_TABLE_INDEX = 2 + ) diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index 584c2d4593..3c675c63c9 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -320,10 +320,14 @@ func XlateFromDb(uri string, ygRoot *ygot.GoStruct, dbs [db.MaxDB]*db.DB, data m cdb = dbInfo.dbIndex } tokens:= strings.Split(xpath, "/") - // Format /module:container/tableName[key]/fieldName - if tokens[len(tokens)-2] == tableName { + // Format /module:container/tableName/listname[key]/fieldName + if tokens[SONIC_TABLE_INDEX] == tableName { fieldName := tokens[len(tokens)-1] - dbData[cdb] = extractFieldFromDb(tableName, keyStr, fieldName, data[cdb]) + dbSpecField := tableName + "/" + fieldName + _, ok := xDbSpecMap[dbSpecField] + if ok && xDbSpecMap[dbSpecField].fieldType == "leaf" { + dbData[cdb] = extractFieldFromDb(tableName, keyStr, fieldName, data[cdb]) + } } } } else { diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index d17d8829fb..78e6b19bca 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -280,14 +280,24 @@ func sonicDbToYangDataFill(uri string, xpath string, dbIdx db.DBNum, table strin /* Traverse db map and create json for cvl yang */ func directDbToYangJsonCreate(uri string, dbDataMap *map[db.DBNum]map[string]map[string]db.Value, resultMap map[string]interface{}) (string, error) { - xpath, _ := RemoveXPATHPredicates(uri) + xpath, key, table := sonicXpathKeyExtract(uri) if len(xpath) > 0 { var dbNode *dbInfo - xpath, key, table := sonicXpathKeyExtract(xpath) if len(table) > 0 { - dbNode = xDbSpecMap[table] + tokens:= strings.Split(xpath, "/") + if tokens[SONIC_TABLE_INDEX] == table { + fieldName := tokens[len(tokens)-1] + dbSpecField := table + "/" + fieldName + _, ok := xDbSpecMap[dbSpecField] + if ok && xDbSpecMap[dbSpecField].fieldType == "leaf" { + dbNode = xDbSpecMap[dbSpecField] + xpath = dbSpecField + } else { + dbNode = xDbSpecMap[table] + } + } } else { dbNode, _ = xDbSpecMap[xpath] } diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index a1c9faf14b..b6fe747d84 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -16,9 +16,6 @@ import ( log "github.com/golang/glog" ) -const SONIC_TABLE_INDEX = 2 -const SONIC_FIELD_INDEX = 3 - /* Invoke the post tansformer */ func postXfmrHandlerFunc(inParams XfmrParams) (map[string]map[string]db.Value, error) { xpath, _ := RemoveXPATHPredicates(inParams.uri) From 891cad58d56da230aa48a702cbd181bf2435b421 Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Mon, 7 Oct 2019 19:15:04 -0700 Subject: [PATCH 207/214] Make file changes to generate sonic yaml files --- Makefile | 3 +++ src/cvl/schema/Makefile | 3 ++- src/rest/Makefile | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 29d8c73b7c..f78cee25bb 100644 --- a/Makefile +++ b/Makefile @@ -94,6 +94,7 @@ codegen: yamlGen: $(MAKE) -C models/yang + $(MAKE) -C models/yang/sonic go-patch: go-deps cd $(BUILD_GOPATH)/src/github.com/openconfig/ygot/; git reset --hard HEAD; git checkout 724a6b18a9224343ef04fe49199dfb6020ce132a 2>/dev/null ; true; \ @@ -120,6 +121,8 @@ install: $(INSTALL) -d $(DESTDIR)/usr/sbin/schema/ $(INSTALL) -d $(DESTDIR)/usr/sbin/lib/ $(INSTALL) -d $(DESTDIR)/usr/models/yang/ + $(INSTALL) -D $(TOPDIR)/models/yang/sonic/*.yang $(DESTDIR)/usr/models/yang/ + $(INSTALL) -D $(TOPDIR)/models/yang/sonic/common/*.yang $(DESTDIR)/usr/models/yang/ $(INSTALL) -D $(TOPDIR)/src/cvl/schema/*.yin $(DESTDIR)/usr/sbin/schema/ $(INSTALL) -D $(TOPDIR)/src/cvl/testdata/schema/*.yin $(DESTDIR)/usr/sbin/schema/ $(INSTALL) -D $(TOPDIR)/src/cvl/schema/*.yang $(DESTDIR)/usr/models/yang/ diff --git a/src/cvl/schema/Makefile b/src/cvl/schema/Makefile index 8f1276b68b..3af437be35 100644 --- a/src/cvl/schema/Makefile +++ b/src/cvl/schema/Makefile @@ -28,7 +28,8 @@ out_common=$(patsubst %.yang, %.yin, $(shell ls -1 $(sonic_yang_common)/*.yang | out_tree=$(patsubst %.yang, %.tree, $(src_files)) search_path=$(sonic_yang):$(sonic_yang_common):$(sonic_yang_common)/ietf -all: yamlGen allyangs.tree allyangs_tree.html schema +#all: yamlGen allyangs.tree allyangs_tree.html schema +all: schema schema: $(out) $(out_common) diff --git a/src/rest/Makefile b/src/rest/Makefile index 4b3d0055ec..0eb6901f44 100644 --- a/src/rest/Makefile +++ b/src/rest/Makefile @@ -56,6 +56,7 @@ $(REST_BUILD_DIR)/: # Invokes yang and model make to generate swagger artifcats. $(REST_BIN): $(REST_SRCS) | $(REST_BUILD_DIR)/ $(MAKE) -C $(TOPDIR)/models/yang + $(MAKE) -C $(TOPDIR)/models/yang/sonic $(MAKE) -C $(TOPDIR)/models ifeq ($(SONIC_COVERAGE_ON),y) GOPATH=$(REST_GOPATH) $(GO) test -coverpkg=".././..." -c -o $@ main/main.go main/main_test.go From 0f131b567413e40a357e8bd4a6c5d29f95182252 Mon Sep 17 00:00:00 2001 From: amrutasali Date: Tue, 8 Oct 2019 23:48:53 +0000 Subject: [PATCH 208/214] support table transformer - GET case on leaf or nested container --- src/translib/transformer/xlate_from_db.go | 160 ++++++++++++++-------- 1 file changed, 101 insertions(+), 59 deletions(-) diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index 78e6b19bca..992f17b10e 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -353,10 +353,9 @@ func fillDbDataMapForTbl(uri string, xpath string, tblName string, tblKey string dbFormat := KeySpec{} dbFormat.Ts.Name = tblName dbFormat.dbNum = cdb - /* TODO - handle key if tblKey != "" { dbFormat.Key.Comp = append(dbFormat.Key.Comp, tblKey) - } */ + } err = TraverseDb(dbs, dbFormat, &dbresult, nil) if err != nil { log.Errorf("TraverseDb() failure for tbl(DB num) %v(%v) for xpath %v", tblName, cdb, xpath) @@ -374,7 +373,7 @@ func fillDbDataMapForTbl(uri string, xpath string, tblName string, tblKey string // Assumption: All tables are from the same DB func dbDataFromTblXfmrGet(tbl string, inParams XfmrParams, dbDataMap *map[db.DBNum]map[string]map[string]db.Value) error { xpath, _ := RemoveXPATHPredicates(inParams.uri) - curDbDataMap, err := fillDbDataMapForTbl(inParams.uri, xpath, tbl, "", inParams.curDb, inParams.dbs) + curDbDataMap, err := fillDbDataMapForTbl(inParams.uri, xpath, tbl, inParams.key, inParams.curDb, inParams.dbs) if err == nil { mapCopy((*dbDataMap)[inParams.curDb], curDbDataMap[inParams.curDb]) } @@ -389,7 +388,7 @@ func yangListDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, x xfmrTblFunc := *xYangSpecMap[xpath].xfmrTbl if len(xfmrTblFunc) > 0 { tblXfmr = true - inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, uri, GET, "", dbDataMap, nil) + inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, uri, GET, tblKey, dbDataMap, nil) tblList = xfmrTblHandlerFunc(xfmrTblFunc, inParams) if len(tblList) != 0 { for _, curTbl := range tblList { @@ -518,7 +517,7 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath } } chldYangType := yangTypeGet(xYangSpecMap[chldXpath].yangEntry) - if chldYangType == "leaf" || chldYangType == "leaf-list" { + if chldYangType == YANG_LEAF || chldYangType == YANG_LEAF_LIST { fldValMap, err := terminalNodeProcess(dbs, ygRoot, chldUri, chldXpath, dbDataMap, tbl, tblKey) if err != nil { log.Infof("Failed to get data(\"%v\").", chldUri) @@ -526,12 +525,13 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath for lf, val := range fldValMap { resultMap[lf] = val } - } else if chldYangType == "container" { + } else if chldYangType == YANG_CONTAINER { cname := xYangSpecMap[chldXpath].yangEntry.Name if xYangSpecMap[chldXpath].xfmrTbl != nil { xfmrTblFunc := *xYangSpecMap[chldXpath].xfmrTbl if len(xfmrTblFunc) > 0 { - inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, chldUri, GET, "", dbDataMap, nil) + //inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, chldUri, GET, "", dbDataMap, nil) + inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, chldUri, GET, tblKey, dbDataMap, nil) tblList := xfmrTblHandlerFunc(xfmrTblFunc, inParams) if len(tblList) > 1 { log.Warningf("Table transformer returned more than one table for container %v", chldXpath) @@ -561,7 +561,7 @@ func yangDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, xpath log.Infof("Empty container(\"%v\").\r\n", chldUri) } } - } else if chldYangType == "list" { + } else if chldYangType == YANG_LIST { cdb = xYangSpecMap[chldXpath].dbIndex if len(xYangSpecMap[chldXpath].xfmrFunc) > 0 { inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, chldUri, GET, "", dbDataMap, nil) @@ -600,71 +600,113 @@ func dbDataToYangJsonCreate(uri string, ygRoot *ygot.GoStruct, dbs [db.MaxDB]*db yangNode, ok := xYangSpecMap[reqXpath] if ok { yangType := yangTypeGet(yangNode.yangEntry) - if yangType == "leaf" || yangType == "leaf-list" { - //fldName := xYangSpecMap[reqXpath].fieldName + validateHandlerFlag := false + tableXfmrFlag := false + IsValidate := false + if len(xYangSpecMap[reqXpath].validateFunc) > 0 { + inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, uri, GET, keyName, dbDataMap, nil) + res := validateHandlerFunc(inParams) + if !res { + validateHandlerFlag = true + /* cannot immediately return from her since reXpath yangtype decides the return type */ + } else { + IsValidate = res + } + } + isList := false + switch yangType { + case YANG_LIST: + isList = true + case YANG_LEAF, YANG_LEAF_LIST, YANG_CONTAINER: + isList = false + default: + log.Infof("Unknown yang object type for path %v", reqXpath) + isList = true //do not want non-list processing to happen + } + /*If yangtype is a list separate code path is to be taken in case of table transformer + since that code path already handles the calling of table transformer and subsequent processing + */ + if (!validateHandlerFlag) && (!isList) { + if xYangSpecMap[reqXpath].xfmrTbl != nil { + xfmrTblFunc := *xYangSpecMap[reqXpath].xfmrTbl + if len(xfmrTblFunc) > 0 { + inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, uri, GET, keyName, dbDataMap, nil) + tblList := xfmrTblHandlerFunc(xfmrTblFunc, inParams) + if len(tblList) > 1 { + log.Warningf("Table transformer returned more than one table for container %v", reqXpath) + tableXfmrFlag = true + } + if len(tblList) == 0 { + log.Warningf("Table transformer returned no table for conatiner %v", reqXpath) + tableXfmrFlag = true + } + if !tableXfmrFlag { + dbDataFromTblXfmrGet(tblList[0], inParams, dbDataMap) + } + } else { + log.Warningf("empty table transformer function name for xpath - %v", reqXpath) + tableXfmrFlag = true + } + } + } + for { + if yangType == YANG_LEAF || yangType == YANG_LEAF_LIST { yangName := xYangSpecMap[reqXpath].yangEntry.Name + if validateHandlerFlag || tableXfmrFlag { + resultMap[yangName] = "" + break + } tbl, key, _ := tableNameAndKeyFromDbMapGet((*dbDataMap)[cdb]) - validateHandlerFlag := false - if len(xYangSpecMap[reqXpath].validateFunc) > 0 { - // TODO - handle non CONFIG-DB - inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, uri, GET, key, dbDataMap, nil) - res := validateHandlerFunc(inParams) - if !res { - validateHandlerFlag = true - resultMap[yangName] = "" - } - } - if !validateHandlerFlag { - fldValMap, err := terminalNodeProcess(dbs, ygRoot, uri, reqXpath, dbDataMap, tbl, key) - //err := terminalNodeProcess(dbs, ygRoot, uri, reqXpath, dbDataMap, tbl, key) - if err != nil { - log.Infof("Empty terminal node (\"%v\").", uri) - } - resultMap = fldValMap - } - } else if yangType == "container" { + fldValMap, err := terminalNodeProcess(dbs, ygRoot, uri, reqXpath, dbDataMap, tbl, key) + if err != nil { + log.Infof("Empty terminal node (\"%v\").", uri) + } + resultMap = fldValMap + break + + } else if yangType == YANG_CONTAINER { cname := xYangSpecMap[reqXpath].yangEntry.Name cmap := make(map[string]interface{}) - IsYangDataFill := true + if validateHandlerFlag || tableXfmrFlag { + resultMap[cname] = cmap + break + } if len(xYangSpecMap[reqXpath].xfmrFunc) > 0 { inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, uri, GET, "", dbDataMap, nil) cmap, _ = xfmrHandlerFunc(inParams) if cmap != nil && len(cmap) > 0 { resultMap[cname] = cmap - IsYangDataFill = false - } - } else if xYangSpecMap[reqXpath].xfmrTbl != nil { - xfmrTblFunc := *xYangSpecMap[reqXpath].xfmrTbl - if len(xfmrTblFunc) > 0 { - inParams := formXfmrInputRequest(dbs[cdb], dbs, cdb, ygRoot, uri, GET, "", dbDataMap, nil) - tblList := xfmrTblHandlerFunc(xfmrTblFunc, inParams) - if len(tblList) > 1 { - log.Warningf("Table transformer returned more than one table for container %v", reqXpath) - IsYangDataFill = false - } - if len(tblList) != 0 { - dbDataFromTblXfmrGet(tblList[0], inParams, dbDataMap) - err := yangDataFill(dbs, ygRoot, uri, reqXpath, dbDataMap, resultMap, tableName, keyName, cdb, false) - if err != nil { - log.Infof("Empty container(\"%v\").\r\n", uri) - } - - } - - } else { - log.Warningf("empty table transformer function name for xpath - %v", reqXpath) - IsYangDataFill = false + break } } - if IsYangDataFill { - err := yangDataFill(dbs, ygRoot, uri, reqXpath, dbDataMap, resultMap, tableName, keyName, cdb, false) - if err != nil { - log.Infof("Empty container(\"%v\").\r\n", uri) - } + err := yangDataFill(dbs, ygRoot, uri, reqXpath, dbDataMap, resultMap, tableName, keyName, cdb, IsValidate) + if err != nil { + log.Infof("Empty container(\"%v\").\r\n", uri) + } + break + } else if yangType == YANG_LIST { + var err error + var logStr string + if xYangSpecMap[reqXpath].xfmrTbl != nil { + /* pass empty table string since in case of list table transformer can have multiple tables returned, + which are already being fetched and handled in yangListDataFill + */ + err = yangListDataFill(dbs, ygRoot, uri, reqXpath, dbDataMap, resultMap, "", keyName, cdb, IsValidate) + logStr = fmt.Sprintf("yangListDataFill failed for list case(\"%v\").\r\n", uri) + } else { + err = yangDataFill(dbs, ygRoot, uri, reqXpath, dbDataMap, resultMap, tableName, keyName, cdb, IsValidate) + logStr = fmt.Sprintf("yangDataFill failed for list(\"%v\").\r\n", uri) + } + if err != nil { + log.Infof("%v", logStr) + } + break } else { - yangDataFill(dbs, ygRoot, uri, reqXpath, dbDataMap, resultMap, tableName, keyName, cdb, false) + log.Warningf("Unknown yang object type for path %v", reqXpath) + break } + } //end of for } } From 7a2353bb8ab46e43e721065f9d117f5f61c59a1b Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Tue, 8 Oct 2019 22:59:12 -0700 Subject: [PATCH 209/214] Get for sonic yang at instance level to return single instance data --- src/translib/transformer/xlate_from_db.go | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index 992f17b10e..702909ce75 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -266,7 +266,12 @@ func sonicDbToYangDataFill(uri string, xpath string, dbIdx db.DBNum, table strin var mapSlice []typeMapOfInterface curUri := xpath + "/" + yangChldName mapSlice = sonicDbToYangListFill(curUri, curUri, dbIdx, table, key, dbDataMap) - if len(mapSlice) > 0 { + if len(key) > 0 && len(mapSlice) == 1 {// Single instance query. Don't return array of maps + for k, val := range mapSlice[0] { + resultMap[k] = val + } + + } else if len(mapSlice) > 0 { resultMap[yangChldName] = mapSlice } else { log.Infof("Empty list for xpath(%v)", curUri) @@ -319,7 +324,12 @@ func directDbToYangJsonCreate(uri string, dbDataMap *map[db.DBNum]map[string]map sonicDbToYangDataFill(uri, xpath, cdb, table, key, dbDataMap, resultMap) } else if yangType == YANG_LIST { mapSlice := sonicDbToYangListFill(uri, xpath, cdb, table, key, dbDataMap) - if len(mapSlice) > 0 { + if len(key) > 0 && len(mapSlice) == 1 {// Single instance query. Don't return array of maps + for k, val := range mapSlice[0] { + resultMap[k] = val + } + + } else if len(mapSlice) > 0 { pathl := strings.Split(xpath, "/") lname := pathl[len(pathl) - 1] resultMap[lname] = mapSlice From e97303128e14f6256953134a3fcbb067641468b3 Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Wed, 9 Oct 2019 14:24:58 -0700 Subject: [PATCH 210/214] Use new xpathPredicate function that removes augmented module name in the uri --- src/translib/transformer/xlate.go | 2 +- src/translib/transformer/xlate_from_db.go | 13 ++++------- src/translib/transformer/xlate_to_db.go | 11 ++++----- src/translib/transformer/xlate_utils.go | 28 +++++++++++++++++++++++ 4 files changed, 38 insertions(+), 16 deletions(-) diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index 3c675c63c9..42657e95eb 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -331,7 +331,7 @@ func XlateFromDb(uri string, ygRoot *ygot.GoStruct, dbs [db.MaxDB]*db.DB, data m } } } else { - xpath, _ := RemoveXPATHPredicates(uri) + xpath, _ := XfmrRemoveXPATHPredicates(uri) if _, ok := xYangSpecMap[xpath]; ok { cdb = xYangSpecMap[xpath].dbIndex } diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index 702909ce75..0577e22251 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -20,7 +20,7 @@ type typeMapOfInterface map[string]interface{} func xfmrHandlerFunc(inParams XfmrParams) (map[string]interface{}, error) { result := make(map[string]interface{}) - xpath, _ := RemoveXPATHPredicates(inParams.uri) + xpath, _ := XfmrRemoveXPATHPredicates(inParams.uri) log.Infof("Subtree transformer function(\"%v\") invoked for yang path(\"%v\").", xYangSpecMap[xpath].xfmrFunc, xpath) _, err := XlateFuncCall(dbToYangXfmrFunc(xYangSpecMap[xpath].xfmrFunc), inParams) if err != nil { @@ -60,10 +60,7 @@ func xfmrHandlerFunc(inParams XfmrParams) (map[string]interface{}, error) { } func leafXfmrHandlerFunc(inParams XfmrParams) (map[string]interface{}, error) { - xpath, _ := RemoveXPATHPredicates(inParams.uri) - if strings.Count(xpath, ":") > 1 { - xpath = stripAugmentedModuleNames(xpath) - } + xpath, _ := XfmrRemoveXPATHPredicates(inParams.uri) ret, err := XlateFuncCall(dbToYangXfmrFunc(xYangSpecMap[xpath].xfmrFunc), inParams) if err != nil { return nil, err @@ -77,7 +74,7 @@ func leafXfmrHandlerFunc(inParams XfmrParams) (map[string]interface{}, error) { } func validateHandlerFunc(inParams XfmrParams) (bool) { - xpath, _ := RemoveXPATHPredicates(inParams.uri) + xpath, _ := XfmrRemoveXPATHPredicates(inParams.uri) ret, err := XlateFuncCall(xYangSpecMap[xpath].validateFunc, inParams) if err != nil { return false @@ -382,7 +379,7 @@ func fillDbDataMapForTbl(uri string, xpath string, tblName string, tblKey string // Assumption: All tables are from the same DB func dbDataFromTblXfmrGet(tbl string, inParams XfmrParams, dbDataMap *map[db.DBNum]map[string]map[string]db.Value) error { - xpath, _ := RemoveXPATHPredicates(inParams.uri) + xpath, _ := XfmrRemoveXPATHPredicates(inParams.uri) curDbDataMap, err := fillDbDataMapForTbl(inParams.uri, xpath, tbl, inParams.key, inParams.curDb, inParams.dbs) if err == nil { mapCopy((*dbDataMap)[inParams.curDb], curDbDataMap[inParams.curDb]) @@ -432,7 +429,7 @@ func yangListDataFill(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string, x for k, kv := range curKeyMap { curMap[k] = kv } - curXpath, _ := RemoveXPATHPredicates(curUri) + curXpath, _ := XfmrRemoveXPATHPredicates(curUri) yangDataFill(dbs, ygRoot, curUri, curXpath, dbDataMap, curMap, tbl, dbKey, cdb, validate) mapSlice = append(mapSlice, curMap) } diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index b6fe747d84..5601340966 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -18,7 +18,7 @@ import ( /* Invoke the post tansformer */ func postXfmrHandlerFunc(inParams XfmrParams) (map[string]map[string]db.Value, error) { - xpath, _ := RemoveXPATHPredicates(inParams.uri) + xpath, _ := XfmrRemoveXPATHPredicates(inParams.uri) ret, err := XlateFuncCall(xYangSpecMap[xpath].xfmrPost, inParams) if err != nil { return nil, err @@ -522,7 +522,7 @@ func yangReqToDbMapCreate(d *db.DB, ygRoot *ygot.GoStruct, oper int, uri string, func sonicXpathKeyExtract(path string) (string, string, string) { xpath, keyStr, tableName := "", "", "" var err error - xpath, err = RemoveXPATHPredicates(path) + xpath, err = XfmrRemoveXPATHPredicates(path) if err != nil { return xpath, keyStr, tableName } @@ -561,10 +561,7 @@ func xpathKeyExtract(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string) (st cdb := db.ConfigDB var dbs [db.MaxDB]*db.DB - pfxPath, _ = RemoveXPATHPredicates(path) - if strings.Count(path, ":") > 1 { - pfxPath = stripAugmentedModuleNames(pfxPath) - } + pfxPath, _ = XfmrRemoveXPATHPredicates(path) xpathInfo, ok := xYangSpecMap[pfxPath] if !ok { log.Errorf("No entry found in xYangSpecMap for xpath %v.", pfxPath) @@ -583,7 +580,7 @@ func xpathKeyExtract(d *db.DB, ygRoot *ygot.GoStruct, oper int, path string) (st if len(keyStr) > 0 { keyStr += keySeparator } - yangXpath, _ := RemoveXPATHPredicates(curPathWithKey) + yangXpath, _ := XfmrRemoveXPATHPredicates(curPathWithKey) _, ok := xYangSpecMap[yangXpath] if ok { if len(xYangSpecMap[yangXpath].xfmrKey) > 0 { diff --git a/src/translib/transformer/xlate_utils.go b/src/translib/transformer/xlate_utils.go index 6afbeeaa74..84ccd39406 100644 --- a/src/translib/transformer/xlate_utils.go +++ b/src/translib/transformer/xlate_utils.go @@ -431,3 +431,31 @@ func stripAugmentedModuleNames(xpath string) string { return path } +func XfmrRemoveXPATHPredicates(xpath string) (string, error) { + pathList := strings.Split(xpath, "/") + pathList = pathList[1:] + for i, pvar := range pathList { + if strings.Contains(pvar, "[") && strings.Contains(pvar, "]") { + si, ei := strings.Index(pvar, "["), strings.Index(pvar, "]") + // substring contains [] entries + if (si < ei) { + pvar = strings.Split(pvar, "[")[0] + pathList[i] = pvar + + } else { + // This substring contained a ] before a [. + return "", fmt.Errorf("Incorrect ordering of [] within substring %s of %s, [ pos: %d, ] pos: %d", pvar, xpath, si, ei) + } + } else if strings.Contains(pvar, "[") || strings.Contains(pvar, "]") { + // This substring contained a mismatched pair of []s. + return "", fmt.Errorf("Mismatched brackets within substring %s of %s", pvar, xpath) + } + if (i > 0) && strings.Contains(pvar, ":") { + pvar = strings.Split(pvar,":")[1] + pathList[i] = pvar + } + } + path := "/" + strings.Join(pathList, "/") + return path,nil +} + From 7d836d716a298b866153409bb921613ec7f66d48 Mon Sep 17 00:00:00 2001 From: justinejose91 Date: Wed, 9 Oct 2019 17:39:51 -0700 Subject: [PATCH 211/214] Bug fixed for not showing GB instead of Gx --- src/CLI/renderer/templates/show_interface_status.j2 | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/CLI/renderer/templates/show_interface_status.j2 b/src/CLI/renderer/templates/show_interface_status.j2 index c706bd53cd..caf9fde229 100644 --- a/src/CLI/renderer/templates/show_interface_status.j2 +++ b/src/CLI/renderer/templates/show_interface_status.j2 @@ -4,6 +4,7 @@ {% set vars = {'description': ""} %} {% set vars = {'mtu': ""} %} {% set vars = {'speed': ""} %} +{% set vars = {'parsedSpeed': ""} %} {% if json_output -%} ------------------------------------------------------------------------------------------ {{'%-20s'|format("Name")}}{{'%-20s'|format("Description")}}{{'%-15s'|format("Admin")}}{{'%-15s'|format("Oper")}}{{'%-15s'|format("Speed")}}{{'%-15s'|format("MTU")}} @@ -13,7 +14,8 @@ {% for interface in interface_list %} {% for key in interface %} {% if "ethernet" in key %} - {% if vars.update({'speed':interface[key]["state"]["port-speed"]|replace("openconfig-if-ethernet:SPEED_", "")}) %}{% endif %} + {% if vars.update({'speed':interface[key]["state"]["port-speed"]|replace("openconfig-if-ethernet:SPEED_", "")}) %} {% endif %} + {% if vars.update({'parsedSpeed':vars.speed|replace("B", "")}) %} {% endif %} {% endif %} {% if "state" in key %} {% if vars.update({'name':interface[key]["name"]}) %}{% endif %} @@ -28,7 +30,7 @@ {% endif %} {% endfor %} {% if 'Ethernet' in vars.name %} -{{'%-20s'|format(vars.name)}}{{'%-20s'|format(vars.description)}}{{'%-15s'|format(vars.admin_state|lower())}}{{'%-15s'|format(vars.oper_state|lower())}}{{'%-15s'|format(vars.speed)}}{{'%-15s'|format(vars.mtu)}} +{{'%-20s'|format(vars.name)}}{{'%-20s'|format(vars.description)}}{{'%-15s'|format(vars.admin_state|lower())}}{{'%-15s'|format(vars.oper_state|lower())}}{{'%-15s'|format(vars.parsedSpeed)}}{{'%-15s'|format(vars.mtu)}} {% endif %} {% endfor %} {% endfor %} From 9df719d37a379815f3e10fd2111f9d8503f64c76 Mon Sep 17 00:00:00 2001 From: Ranjini Nagaraj Date: Wed, 9 Oct 2019 18:07:34 -0700 Subject: [PATCH 212/214] Add Copyright info --- models/yang/common/sonic-extensions.yang | 2 +- src/translib/common_app.go | 18 ++++++++++++++++ src/translib/transformer/transformer.go | 24 +++++++++++++++++++--- src/translib/transformer/xconst.go | 20 +++++++++++++++++- src/translib/transformer/xfmr_acl.go | 18 ++++++++++++++++ src/translib/transformer/xfmr_interface.go | 18 ++++++++++++++++ src/translib/transformer/xlate.go | 18 ++++++++++++++++ src/translib/transformer/xlate_from_db.go | 18 ++++++++++++++++ src/translib/transformer/xlate_to_db.go | 20 +++++++++++++++++- src/translib/transformer/xlate_utils.go | 18 ++++++++++++++++ src/translib/transformer/xspec.go | 20 +++++++++++++++++- 11 files changed, 187 insertions(+), 7 deletions(-) diff --git a/models/yang/common/sonic-extensions.yang b/models/yang/common/sonic-extensions.yang index ced7029938..263cf9274d 100644 --- a/models/yang/common/sonic-extensions.yang +++ b/models/yang/common/sonic-extensions.yang @@ -71,7 +71,7 @@ module sonic-extensions { description "Validation callpoint used to validate a YANG node during data translation back to YANG as a response to GET."; } - extension redis-db-name { + extension db-name { argument "db-name"; description "DB name that will indicate where data is stored. Eg: Config DB, App DB etc"; } diff --git a/src/translib/common_app.go b/src/translib/common_app.go index e48c71cdcc..7571bb025c 100644 --- a/src/translib/common_app.go +++ b/src/translib/common_app.go @@ -1,3 +1,21 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Dell, Inc. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// + package translib import ( diff --git a/src/translib/transformer/transformer.go b/src/translib/transformer/transformer.go index c69ecabda6..05eb21a292 100644 --- a/src/translib/transformer/transformer.go +++ b/src/translib/transformer/transformer.go @@ -1,3 +1,21 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Dell, Inc. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// + package transformer import ( @@ -30,8 +48,8 @@ func reportIfError(errs []error) { } } -func getOcModelsList () ([] string) { - var fileList [] string +func getOcModelsList () ([]string) { + var fileList []string file, err := os.Open(YangPath + "models_list") if err != nil { return fileList @@ -51,7 +69,7 @@ func getOcModelsList () ([] string) { return fileList } -func getDefaultModelsList () ([] string) { +func getDefaultModelsList () ([]string) { var files []string fileInfo, err := ioutil.ReadDir(YangPath) if err != nil { diff --git a/src/translib/transformer/xconst.go b/src/translib/transformer/xconst.go index bcc2d0ffb3..a1fb5f9f46 100644 --- a/src/translib/transformer/xconst.go +++ b/src/translib/transformer/xconst.go @@ -1,3 +1,21 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Dell, Inc. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// + package transformer const ( @@ -7,7 +25,7 @@ const ( YANG_LEAF = "leaf" YANG_LEAF_LIST = "leaflist" - YANG_ANNOT_DB_NAME = "redis-db-name" + YANG_ANNOT_DB_NAME = "db-name" YANG_ANNOT_TABLE_NAME = "table-name" YANG_ANNOT_FIELD_NAME = "field-name" YANG_ANNOT_KEY_DELIM = "key-delimiter" diff --git a/src/translib/transformer/xfmr_acl.go b/src/translib/transformer/xfmr_acl.go index 3f07baa4a0..fd8b694366 100644 --- a/src/translib/transformer/xfmr_acl.go +++ b/src/translib/transformer/xfmr_acl.go @@ -1,3 +1,21 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Dell, Inc. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// + package transformer import ( diff --git a/src/translib/transformer/xfmr_interface.go b/src/translib/transformer/xfmr_interface.go index f9c8c6d3a3..35e17ed004 100644 --- a/src/translib/transformer/xfmr_interface.go +++ b/src/translib/transformer/xfmr_interface.go @@ -1,3 +1,21 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Dell, Inc. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// + package transformer import ( diff --git a/src/translib/transformer/xlate.go b/src/translib/transformer/xlate.go index 42657e95eb..692353e675 100644 --- a/src/translib/transformer/xlate.go +++ b/src/translib/transformer/xlate.go @@ -1,3 +1,21 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Dell, Inc. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// + package transformer import ( diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index 0577e22251..bf6145e3a3 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -1,3 +1,21 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Dell, Inc. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// + package transformer import ( diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index 5601340966..77a53b7ded 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -1,3 +1,21 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Dell, Inc. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// + package transformer import ( @@ -314,7 +332,7 @@ func sonicYangReqToDbMapDelete(xpathPrefix string, tableName string, keyName str fieldName := tokens[len(tokens)-1] dbSpecField := tableName + "/" + fieldName _, ok := xDbSpecMap[dbSpecField] - if ok && xDbSpecMap[dbSpecField].fieldType == "leaf" { + if ok && xDbSpecMap[dbSpecField].fieldType == "leaf" || xDbSpecMap[dbSpecField].fieldType == "leaf-list" { // Specific leaf case dbVal.Field = make(map[string]string) dbVal.Field[fieldName] = "" diff --git a/src/translib/transformer/xlate_utils.go b/src/translib/transformer/xlate_utils.go index 84ccd39406..05d2bc1715 100644 --- a/src/translib/transformer/xlate_utils.go +++ b/src/translib/transformer/xlate_utils.go @@ -1,3 +1,21 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Dell, Inc. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// + package transformer import ( diff --git a/src/translib/transformer/xspec.go b/src/translib/transformer/xspec.go index 11198a645f..017dcb1130 100644 --- a/src/translib/transformer/xspec.go +++ b/src/translib/transformer/xspec.go @@ -1,3 +1,21 @@ +//////////////////////////////////////////////////////////////////////////////// +// // +// Copyright 2019 Dell, Inc. // +// // +// Licensed under the Apache License, Version 2.0 (the "License"); // +// you may not use this file except in compliance with the License. // +// You may obtain a copy of the License at // +// // +// http://www.apache.org/licenses/LICENSE-2.0 // +// // +// Unless required by applicable law or agreed to in writing, software // +// distributed under the License is distributed on an "AS IS" BASIS, // +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // +// See the License for the specific language governing permissions and // +// limitations under the License. // +// // +//////////////////////////////////////////////////////////////////////////////// + package transformer import ( @@ -335,7 +353,7 @@ func annotEntryFill(xYangSpecMap map[string]*yangXpathInfo, xpath string, entry xpathData.validateFunc = ext.NName() case "use-self-key" : xpathData.keyXpath = nil - case "redis-db-name" : + case "db-name" : if ext.NName() == "APPL_DB" { xpathData.dbIndex = db.ApplDB } else if ext.NName() == "ASIC_DB" { From 30e941a8a2506ddd5e093b621ce856db2d421167 Mon Sep 17 00:00:00 2001 From: amrutasali Date: Thu, 10 Oct 2019 01:42:47 +0000 Subject: [PATCH 213/214] Sonic yang restructuring fix terminal node leaf/leaf-list cases --- src/translib/transformer/xlate_from_db.go | 18 +++++++++++++----- src/translib/transformer/xlate_to_db.go | 19 ++++++++++++++----- src/translib/transformer/xspec.go | 14 ++++++++++---- 3 files changed, 37 insertions(+), 14 deletions(-) diff --git a/src/translib/transformer/xlate_from_db.go b/src/translib/transformer/xlate_from_db.go index 992f17b10e..7268ed4a2b 100644 --- a/src/translib/transformer/xlate_from_db.go +++ b/src/translib/transformer/xlate_from_db.go @@ -159,7 +159,8 @@ func processLfLstDbToYang(fieldXpath string, dbFldVal string) []interface{} { const INTBASE = 10 yngTerminalNdDtType := xDbSpecMap[fieldXpath].dbEntry.Type.Kind switch yngTerminalNdDtType { - case yang.Yenum, yang.Ystring, yang.Yunion: + case yang.Yenum, yang.Ystring, yang.Yunion, yang.Yleafref: + // TODO handle leaf-ref base type log.Info("DB leaf-list and Yang leaf-list are of same data-type") for _, fldVal := range valLst { resLst = append(resLst, fldVal) @@ -196,7 +197,7 @@ func sonicDbToYangTerminalNodeFill(tblName string, field string, value string, r } yangType := yangTypeGet(xDbSpecMapEntry.dbEntry) - if yangType == "leaf-list" { + if yangType == YANG_LEAF_LIST { /* this should never happen but just adding for safetty */ if !strings.HasSuffix(field, "@") { log.Warningf("Leaf-list in Sonic yang should also be a leaf-list in DB, its not for xpath %v", fieldXpath) @@ -249,7 +250,11 @@ func sonicDbToYangDataFill(uri string, xpath string, dbIdx db.DBNum, table strin if chldYangType == YANG_LEAF || chldYangType == YANG_LEAF_LIST { log.Infof("tbl(%v), k(%v), yc(%v)", table, key, yangChldName) - sonicDbToYangTerminalNodeFill(table, yangChldName, (*dbDataMap)[dbIdx][table][key].Field[yangChldName], resultMap) + fldName := yangChldName + if chldYangType == YANG_LEAF_LIST { + fldName = fldName + "@" + } + sonicDbToYangTerminalNodeFill(table, fldName, (*dbDataMap)[dbIdx][table][key].Field[fldName], resultMap) } else if chldYangType == YANG_CONTAINER { curMap := make(map[string]interface{}) curUri := xpath + "/" + yangChldName @@ -291,7 +296,7 @@ func directDbToYangJsonCreate(uri string, dbDataMap *map[db.DBNum]map[string]map fieldName := tokens[len(tokens)-1] dbSpecField := table + "/" + fieldName _, ok := xDbSpecMap[dbSpecField] - if ok && xDbSpecMap[dbSpecField].fieldType == "leaf" { + if ok && (xDbSpecMap[dbSpecField].fieldType == YANG_LEAF || xDbSpecMap[dbSpecField].fieldType == YANG_LEAF_LIST) { dbNode = xDbSpecMap[dbSpecField] xpath = dbSpecField } else { @@ -311,6 +316,9 @@ func directDbToYangJsonCreate(uri string, dbDataMap *map[db.DBNum]map[string]map if yangType == YANG_LEAF || yangType == YANG_LEAF_LIST { fldName := xDbSpecMap[xpath].dbEntry.Name + if yangType == YANG_LEAF_LIST { + fldName = fldName + "@" + } sonicDbToYangTerminalNodeFill(table, fldName, (*dbDataMap)[cdb][table][key].Field[fldName], resultMap) } else if yangType == YANG_CONTAINER { if len(table) > 0 { @@ -470,7 +478,7 @@ func terminalNodeProcess(dbs [db.MaxDB]*db.DB, ygRoot *ygot.GoStruct, uri string /* if there is no transformer extension/annotation then it means leaf-list in yang is also leaflist in db */ if len(dbFldName) > 0 && !xYangSpecMap[xpath].isKey { yangType := yangTypeGet(xYangSpecMap[xpath].yangEntry) - if yangType == "leaf-list" { + if yangType == YANG_LEAF_LIST { dbFldName += "@" val, ok := (*dbDataMap)[cdb][tbl][tblKey].Field[dbFldName] if ok { diff --git a/src/translib/transformer/xlate_to_db.go b/src/translib/transformer/xlate_to_db.go index b6fe747d84..eea19d1851 100644 --- a/src/translib/transformer/xlate_to_db.go +++ b/src/translib/transformer/xlate_to_db.go @@ -314,11 +314,20 @@ func sonicYangReqToDbMapDelete(xpathPrefix string, tableName string, keyName str fieldName := tokens[len(tokens)-1] dbSpecField := tableName + "/" + fieldName _, ok := xDbSpecMap[dbSpecField] - if ok && xDbSpecMap[dbSpecField].fieldType == "leaf" { - // Specific leaf case - dbVal.Field = make(map[string]string) - dbVal.Field[fieldName] = "" - } + if ok { + yangType := xDbSpecMap[dbSpecField].fieldType + // terminal node case + if yangType == YANG_LEAF_LIST { + fieldName = fieldName + "@" + dbVal.Field = make(map[string]string) + dbVal.Field[fieldName] = "" + } + if yangType == YANG_LEAF { + dbVal.Field = make(map[string]string) + dbVal.Field[fieldName] = "" + } + + } } result[tableName][keyName] = dbVal } else { diff --git a/src/translib/transformer/xspec.go b/src/translib/transformer/xspec.go index 11198a645f..b2a02eba39 100644 --- a/src/translib/transformer/xspec.go +++ b/src/translib/transformer/xspec.go @@ -41,7 +41,9 @@ type dbInfo struct { var xYangSpecMap map[string]*yangXpathInfo var xDbSpecMap map[string]*dbInfo -var xDbSpecOrdTblMap map[string][]string //map of module-name to ordered list of db tables { "sonic-acl" : ["ACL_TABLE", "ACL_RULE"] } +//var xDbSpecOrdTblMap map[string][]string //map of module-name to ordered list of db tables { "sonic-acl" : ["ACL_TABLE", "ACL_RULE"] } +//map of module-name to ordered list of db tables { "sonic-acl" : {"ACL_TABLE", "ACL_RULE"} } +var xDbSpecOrdTblMap = map[string][]string { "openconfig-interfaces" : {"PORT", "INTERFACE", "MGMT_PORT", "MGMT_INTERFACE", "PORT_TABLE", "INTF_TABLE", "MGMT_PORT_TABLE", "MGMT_INTF_TABLE"}} /* update transformer spec with db-node */ func updateDbTableData (xpath string, xpathData *yangXpathInfo, tableName string) { @@ -253,7 +255,7 @@ func dbMapBuild(entries []*yang.Entry) { return } xDbSpecMap = make(map[string]*dbInfo) - xDbSpecOrdTblMap = make(map[string][]string) + //xDbSpecOrdTblMap = make(map[string][]string) for _, e := range entries { if e == nil || len(e.Dir) == 0 { @@ -261,7 +263,9 @@ func dbMapBuild(entries []*yang.Entry) { } moduleNm := e.Name log.Infof("Module name(%v)", moduleNm) - xDbSpecOrdTblMap[moduleNm] = []string{} + /*if _, ok := xDbSpecOrdTblMap[moduleNm]; !ok { + xDbSpecOrdTblMap[moduleNm] = []string{} + }*/ trkTpCnt := true dbMapFill("", "", moduleNm, trkTpCnt, xDbSpecMap, e) } @@ -562,7 +566,9 @@ func updateSchemaOrderedMap(module string, entry *yang.Entry) { } } } - xDbSpecOrdTblMap[module] = children + if _, ok := xDbSpecOrdTblMap[module]; !ok { + xDbSpecOrdTblMap[module] = children + } } func updateChildTable(keyspec []KeySpec, chlist *[]string) ([]string) { From 5226709dc5902e8e2b5bb375f8b8a43c5d97e246 Mon Sep 17 00:00:00 2001 From: amrutasali Date: Thu, 10 Oct 2019 01:53:20 +0000 Subject: [PATCH 214/214] revert accidently added local changes in xspec.go --- src/translib/transformer/xspec.go | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/translib/transformer/xspec.go b/src/translib/transformer/xspec.go index c12a5595d6..85cff79cd3 100644 --- a/src/translib/transformer/xspec.go +++ b/src/translib/transformer/xspec.go @@ -59,9 +59,7 @@ type dbInfo struct { var xYangSpecMap map[string]*yangXpathInfo var xDbSpecMap map[string]*dbInfo -//var xDbSpecOrdTblMap map[string][]string //map of module-name to ordered list of db tables { "sonic-acl" : ["ACL_TABLE", "ACL_RULE"] } -//map of module-name to ordered list of db tables { "sonic-acl" : {"ACL_TABLE", "ACL_RULE"} } -var xDbSpecOrdTblMap = map[string][]string { "openconfig-interfaces" : {"PORT", "INTERFACE", "MGMT_PORT", "MGMT_INTERFACE", "PORT_TABLE", "INTF_TABLE", "MGMT_PORT_TABLE", "MGMT_INTF_TABLE"}} +var xDbSpecOrdTblMap map[string][]string //map of module-name to ordered list of db tables { "sonic-acl" : ["ACL_TABLE", "ACL_RULE"] } /* update transformer spec with db-node */ func updateDbTableData (xpath string, xpathData *yangXpathInfo, tableName string) { @@ -273,7 +271,7 @@ func dbMapBuild(entries []*yang.Entry) { return } xDbSpecMap = make(map[string]*dbInfo) - //xDbSpecOrdTblMap = make(map[string][]string) + xDbSpecOrdTblMap = make(map[string][]string) for _, e := range entries { if e == nil || len(e.Dir) == 0 { @@ -281,9 +279,6 @@ func dbMapBuild(entries []*yang.Entry) { } moduleNm := e.Name log.Infof("Module name(%v)", moduleNm) - /*if _, ok := xDbSpecOrdTblMap[moduleNm]; !ok { - xDbSpecOrdTblMap[moduleNm] = []string{} - }*/ trkTpCnt := true dbMapFill("", "", moduleNm, trkTpCnt, xDbSpecMap, e) } @@ -584,9 +579,6 @@ func updateSchemaOrderedMap(module string, entry *yang.Entry) { } } } - if _, ok := xDbSpecOrdTblMap[module]; !ok { - xDbSpecOrdTblMap[module] = children - } } func updateChildTable(keyspec []KeySpec, chlist *[]string) ([]string) {