From 94ac50bb9a97e4dfde345665edf66ec803d38099 Mon Sep 17 00:00:00 2001 From: Ping Mao Date: Tue, 22 Feb 2022 20:05:03 -0500 Subject: [PATCH 1/2] Fix libyang backlinks issue: - remove call of libyang backlinks() call - find data dependencies based on python schema and data tree APIs - Add test of yang model with union of leafrefs --- src/sonic-yang-mgmt/sonic_yang.py | 113 +++++++++++++----- .../libyang-python-tests/config_data.json | 7 +- .../sample-yang-models/test-vlan.yang | 18 ++- .../libyang-python-tests/test_SonicYang.json | 3 +- 4 files changed, 104 insertions(+), 37 deletions(-) diff --git a/src/sonic-yang-mgmt/sonic_yang.py b/src/sonic-yang-mgmt/sonic_yang.py index 16aeb8a9ff8a..4f4207239fb3 100644 --- a/src/sonic-yang-mgmt/sonic_yang.py +++ b/src/sonic-yang-mgmt/sonic_yang.py @@ -348,6 +348,9 @@ def _find_data_node(self, data_xpath): def _find_schema_node(self, schema_xpath): try: schema_set = self.ctx.find_path(schema_xpath) + if schema_set is None: + return None + for schema_node in schema_set.schema(): if (schema_xpath == schema_node.path()): return schema_node @@ -497,21 +500,45 @@ def _find_data_nodes(self, data_xpath): - Exception if schema node not found """ def _find_schema_dependencies(self, schema_xpath): - ref_list = [] - try: - schema_node = self._find_schema_node(schema_xpath) - except Exception as e: - self.sysLog(msg="Cound not find the schema node from xpath: " + str(schema_xpath), debug=syslog.LOG_ERR, doPrint=True) - self.fail(e) - return ref_list - - schema_node = ly.Schema_Node_Leaf(schema_node) - backlinks = schema_node.backlinks() - if backlinks.number() > 0: - for link in backlinks.schema(): - self.sysLog(msg="backlink schema: {}".format(link.path()), doPrint=True) - ref_list.append(link.path()) - return ref_list + backlinks = [] + + modules = self.ctx.get_module_iter() + for module in modules: + instantiables = module.data_instantiables(0) + if len(instantiables) < 1: + continue + + schema = instantiables[0] + # find all backlinks for this schema node + schema_list = schema.tree_dfs() + for elem in schema_list: + if ly.LYS_LEAF == elem.nodetype() or ly.LYS_LEAFLIST == elem.nodetype(): + subtype = elem.subtype() + if subtype is None: + continue + + base_type = subtype.type().base() + #union of leafref + if base_type == ly.LY_TYPE_UNION: + count = subtype.type().info().uni().count() + types = subtype.type().info().uni().types() + for i in range(count): + dertype = types[i] + if dertype.base() == ly.LY_TYPE_LEAFREF: + leafref_path = dertype.info().lref().path() + + if leafref_path == schema_xpath: + backlinks.append(elem.path()) + continue + + if base_type != ly.LY_TYPE_LEAFREF: + continue + + leafref_path = self._get_leafref_path(elem.path()) + + if leafref_path == schema_xpath: + backlinks.append(elem.path()) + return backlinks """ find_data_dependencies(): find the data dependencies from data xpath @@ -530,13 +557,13 @@ def find_data_dependencies(self, data_xpath): try: value = str(self._find_data_node_value(data_xpath)) - schema_node = ly.Schema_Node_Leaf(data_node.schema()) - backlinks = schema_node.backlinks() - if backlinks is not None and backlinks.number() > 0: - for link in backlinks.schema(): - node_set = node.find_path(link.path()) - for data_set in node_set.data(): + #backlinks of this scheme node + backlinks = self._find_schema_dependencies(schema_node.path()) + #data dependencies for this data node + for link in backlinks: + node_set = node.find_path(link) + for data_set in node_set.data(): data_set.schema() casted = data_set.subtype() if value == casted.value_str(): @@ -607,7 +634,8 @@ def _get_data_type(self, schema_xpath): return None if (schema_node is not None): - return schema_node.subtype().type().base() + if schema_node.subtype() != None: + return schema_node.subtype().type().base() return ly.LY_TYPE_UNKNOWN @@ -617,15 +645,15 @@ def _get_data_type(self, schema_xpath): output: type of the node this leafref references to """ def _get_leafref_type(self, data_xpath): - data_node = self._find_data_node(data_xpath) - if (data_node is not None): - subtype = data_node.subtype() - if (subtype is not None): - if data_node.schema().subtype().type().base() != ly.LY_TYPE_LEAFREF: - self.sysLog(msg="get_leafref_type() node type for data xpath: {} is not LEAFREF".format(data_xpath), debug=syslog.LOG_ERR, doPrint=True) - return ly.LY_TYPE_UNKNOWN - else: - return subtype.value_type() + #get leafref's reference schema path + try: + data_node = self._find_data_node(data_xpath) + except Exception as e: + print("_get_leafref_type(): Failed to find data node from xpath: {}".format(data_xapth)) + return ly.LY_TYPE_UNKNOWN + + if data_node != None: + return self._get_leafref_type_schema(data_node.schema().path()) return ly.LY_TYPE_UNKNOWN @@ -639,6 +667,15 @@ def _get_leafref_path(self, schema_xpath): if (schema_node is not None): subtype = schema_node.subtype() if (subtype is not None): + base_type = subtype.type().base() + if base_type == ly.LY_TYPE_UNION: + count = subtype.type().info().uni().count() + types = subtype.type().info().uni().types() + for i in range(count): + dertype = types[i] + if dertype.base() == ly.LY_TYPE_LEAFREF: + return dertype.info().lref().path() + if subtype.type().base() != ly.LY_TYPE_LEAFREF: return None else: @@ -656,10 +693,22 @@ def _get_leafref_type_schema(self, schema_xpath): if (schema_node is not None): subtype = schema_node.subtype() if (subtype is not None): + base_type = subtype.type().base() + #union of leafref + if base_type == ly.LY_TYPE_UNION: + count = subtype.type().info().uni().count() + types = subtype.type().info().uni().types() + for i in range(count): + dertype = types[i] + if dertype.base() == ly.LY_TYPE_LEAFREF: + target = dertype.info().lref().target() + target_path = target.path() + target_type = self._get_data_type(target_path) + return target_type + if subtype.type().base() != ly.LY_TYPE_LEAFREF: return None else: - subtype.type().info().lref().path() target = subtype.type().info().lref().target() target_path = target.path() target_type = self._get_data_type(target_path) diff --git a/src/sonic-yang-mgmt/tests/libyang-python-tests/config_data.json b/src/sonic-yang-mgmt/tests/libyang-python-tests/config_data.json index 8a4eaed176d2..d23a467ec0e4 100644 --- a/src/sonic-yang-mgmt/tests/libyang-python-tests/config_data.json +++ b/src/sonic-yang-mgmt/tests/libyang-python-tests/config_data.json @@ -97,7 +97,12 @@ "vlanid": 111, "port": "Ethernet6", "tagging_mode": "tagged" - } + }, + { + "vlanid": 111, + "port": "Ethernet8", + "tagging_mode": "tagged" + } ] } }, diff --git a/src/sonic-yang-mgmt/tests/libyang-python-tests/sample-yang-models/test-vlan.yang b/src/sonic-yang-mgmt/tests/libyang-python-tests/sample-yang-models/test-vlan.yang index 2ca80607b410..06e853be0501 100644 --- a/src/sonic-yang-mgmt/tests/libyang-python-tests/sample-yang-models/test-vlan.yang +++ b/src/sonic-yang-mgmt/tests/libyang-python-tests/sample-yang-models/test-vlan.yang @@ -1,5 +1,7 @@ module test-vlan { + yang-version 1.1; + namespace "http://github.com/Azure/vlan"; prefix vlan; @@ -21,6 +23,11 @@ module test-vlan { revision-date 2019-07-01; } + import test-portchannel { + prefix lag; + revision-date 2019-07-01; + } + revision 2019-07-01 { description "First Revision"; } @@ -125,9 +132,14 @@ module test-vlan { leaf port { /* key elements are mandatory by default */ mandatory true; - type leafref { - path /port:port/port:PORT/port:PORT_LIST/port:port_name; - } + type union { + type leafref { + path /port:port/port:PORT/port:PORT_LIST/port:port_name; + } + type leafref { + path /lag:portchannel/lag:PORTCHANNEL/lag:PORTCHANNEL_LIST/lag:portchannel_name; + } + } } leaf tagging_mode { diff --git a/src/sonic-yang-mgmt/tests/libyang-python-tests/test_SonicYang.json b/src/sonic-yang-mgmt/tests/libyang-python-tests/test_SonicYang.json index b62322d50bdb..eb86fcd246ca 100644 --- a/src/sonic-yang-mgmt/tests/libyang-python-tests/test_SonicYang.json +++ b/src/sonic-yang-mgmt/tests/libyang-python-tests/test_SonicYang.json @@ -52,7 +52,8 @@ "dependencies" : [ "/test-acl:acl/ACL_TABLE/ACL_TABLE_LIST[ACL_TABLE_NAME='PACL-V6']/ports[.='Ethernet8']", "/test-interface:interface/INTERFACE/INTERFACE_LIST[interface='Ethernet8'][ip-prefix='10.1.1.64/26']/interface", - "/test-interface:interface/INTERFACE/INTERFACE_LIST[interface='Ethernet8'][ip-prefix='2000:f500:40:a749::/126']/interface" + "/test-interface:interface/INTERFACE/INTERFACE_LIST[interface='Ethernet8'][ip-prefix='2000:f500:40:a749::/126']/interface", + "/test-vlan:vlan/VLAN_MEMBER/VLAN_MEMBER_LIST[vlanid='111'][port='Ethernet8']/port" ], "xpath" : "/test-port:port/PORT/PORT_LIST[port_name='Ethernet8']/port_name" }, From 318ab5009f75b7bd1643989fe55ed4e337a1a4fb Mon Sep 17 00:00:00 2001 From: Ping Mao Date: Thu, 24 Feb 2022 00:03:26 -0500 Subject: [PATCH 2/2] Fix identation --- .../libyang-python-tests/config_data.json | 506 +++++++++--------- .../sample-yang-models/test-vlan.yang | 282 +++++----- 2 files changed, 394 insertions(+), 394 deletions(-) diff --git a/src/sonic-yang-mgmt/tests/libyang-python-tests/config_data.json b/src/sonic-yang-mgmt/tests/libyang-python-tests/config_data.json index d23a467ec0e4..66179a2a8913 100644 --- a/src/sonic-yang-mgmt/tests/libyang-python-tests/config_data.json +++ b/src/sonic-yang-mgmt/tests/libyang-python-tests/config_data.json @@ -1,265 +1,265 @@ { - "test-vlan:vlan": { - "test-vlan:VLAN_INTERFACE": { - "VLAN_INTERFACE_LIST": [{ - "vlanid": 111, - "ip-prefix": "2000:f500:45:6709::1/64", - "scope": "global", - "family": "IPv6" - }, - { - "vlanid": 111, - "ip-prefix": "10.1.1.65/26", - "scope": "global", - "family": "IPv4" - }, - { - "vlanid": 111, - "ip-prefix": "fe80::1/10", - "scope": "local", - "family": "IPv6" - }, - { - "vlanid": 555, - "ip-prefix": "2000:f500:41:4e9::1/64", - "scope": "global", - "family": "IPv6" - }, - { - "vlanid": 555, - "ip-prefix": "10.1.5.65/26", - "scope": "global", - "family": "IPv4" - }, - { - "vlanid": 555, - "ip-prefix": "fe80::1/10", - "scope": "local", - "family": "IPv6" - } - ] - }, + "test-vlan:vlan": { + "test-vlan:VLAN_INTERFACE": { + "VLAN_INTERFACE_LIST": [{ + "vlanid": 111, + "ip-prefix": "2000:f500:45:6709::1/64", + "scope": "global", + "family": "IPv6" + }, + { + "vlanid": 111, + "ip-prefix": "10.1.1.65/26", + "scope": "global", + "family": "IPv4" + }, + { + "vlanid": 111, + "ip-prefix": "fe80::1/10", + "scope": "local", + "family": "IPv6" + }, + { + "vlanid": 555, + "ip-prefix": "2000:f500:41:4e9::1/64", + "scope": "global", + "family": "IPv6" + }, + { + "vlanid": 555, + "ip-prefix": "10.1.5.65/26", + "scope": "global", + "family": "IPv4" + }, + { + "vlanid": 555, + "ip-prefix": "fe80::1/10", + "scope": "local", + "family": "IPv6" + } + ] + }, - "test-vlan:VLAN": { - "VLAN_LIST": [{ - "vlanid": 111, - "description": "server_vlan", - "dhcp_servers": [ - "10.1.7.116" - ], - "mtu": "9216", - "admin_status": "up" - }, - { - "vlanid": 555, - "description": "ipmi_vlan", - "dhcp_servers": [ - "10.1.7.116" - ], - "mtu": "9216", - "admin_status": "up" - } - ] - }, + "test-vlan:VLAN": { + "VLAN_LIST": [{ + "vlanid": 111, + "description": "server_vlan", + "dhcp_servers": [ + "10.1.7.116" + ], + "mtu": "9216", + "admin_status": "up" + }, + { + "vlanid": 555, + "description": "ipmi_vlan", + "dhcp_servers": [ + "10.1.7.116" + ], + "mtu": "9216", + "admin_status": "up" + } + ] + }, - "test-vlan:VLAN_MEMBER": { - "VLAN_MEMBER_LIST": [{ - "vlanid": 111, - "port": "Ethernet0", - "tagging_mode": "tagged" - }, - { - "vlanid": 111, - "port": "Ethernet1", - "tagging_mode": "tagged" - }, - { - "vlanid": 111, - "port": "Ethernet2", - "tagging_mode": "tagged" - }, - { - "vlanid": 111, - "port": "Ethernet3", - "tagging_mode": "tagged" - }, - { - "vlanid": 111, - "port": "Ethernet4", - "tagging_mode": "tagged" - }, - { - "vlanid": 111, - "port": "Ethernet5", - "tagging_mode": "tagged" - }, - { - "vlanid": 111, - "port": "Ethernet6", - "tagging_mode": "tagged" - }, + "test-vlan:VLAN_MEMBER": { + "VLAN_MEMBER_LIST": [{ + "vlanid": 111, + "port": "Ethernet0", + "tagging_mode": "tagged" + }, + { + "vlanid": 111, + "port": "Ethernet1", + "tagging_mode": "tagged" + }, + { + "vlanid": 111, + "port": "Ethernet2", + "tagging_mode": "tagged" + }, + { + "vlanid": 111, + "port": "Ethernet3", + "tagging_mode": "tagged" + }, + { + "vlanid": 111, + "port": "Ethernet4", + "tagging_mode": "tagged" + }, + { + "vlanid": 111, + "port": "Ethernet5", + "tagging_mode": "tagged" + }, + { + "vlanid": 111, + "port": "Ethernet6", + "tagging_mode": "tagged" + }, { "vlanid": 111, "port": "Ethernet8", "tagging_mode": "tagged" } - ] - } - }, - "test-port:port": { - "test-port:PORT": { - "PORT_LIST": [{ - "port_name": "Ethernet0", - "alias": "eth0", - "description": "Ethernet0", - "speed": 25000, - "mtu": 9000, - "admin_status": "up" - }, - { - "port_name": "Ethernet1", - "alias": "eth1", - "description": "Ethernet1", - "speed": 25000, - "mtu": 9000, - "admin_status": "up" - }, - { - "port_name": "Ethernet2", - "alias": "eth2", - "description": "Ethernet2", - "speed": 25000, - "mtu": 9000, - "admin_status": "up" - }, - { - "port_name": "Ethernet3", - "alias": "eth2", - "description": "Ethernet3", - "speed": 25000, - "mtu": 9000, - "admin_status": "up" - }, - { - "port_name": "Ethernet4", - "alias": "eth4", - "description": "Ethernet4", - "speed": 25000, - "mtu": 9000, - "admin_status": "up" - }, - { - "port_name": "Ethernet5", - "alias": "eth5", - "description": "Ethernet5", - "speed": 25000, - "mtu": 9000, - "admin_status": "up" - }, - { - "port_name": "Ethernet6", - "alias": "eth6", - "description": "Ethernet6", - "speed": 25000, - "mtu": 9000, - "admin_status": "up" - }, - { - "port_name": "Ethernet7", - "alias": "eth7", - "description": "Ethernet7", - "speed": 25000, - "mtu": 9000, - "admin_status": "up" - }, - { - "port_name": "Ethernet8", - "alias": "eth8", - "description": "Ethernet8", - "speed": 25000, - "mtu": 9000, - "admin_status": "up" - }, - { - "port_name": "Ethernet9", - "alias": "eth9", - "description": "Ethernet9", - "speed": 25000, - "mtu": 9000, - "admin_status": "up" - } - ] - } - }, + ] + } + }, + "test-port:port": { + "test-port:PORT": { + "PORT_LIST": [{ + "port_name": "Ethernet0", + "alias": "eth0", + "description": "Ethernet0", + "speed": 25000, + "mtu": 9000, + "admin_status": "up" + }, + { + "port_name": "Ethernet1", + "alias": "eth1", + "description": "Ethernet1", + "speed": 25000, + "mtu": 9000, + "admin_status": "up" + }, + { + "port_name": "Ethernet2", + "alias": "eth2", + "description": "Ethernet2", + "speed": 25000, + "mtu": 9000, + "admin_status": "up" + }, + { + "port_name": "Ethernet3", + "alias": "eth2", + "description": "Ethernet3", + "speed": 25000, + "mtu": 9000, + "admin_status": "up" + }, + { + "port_name": "Ethernet4", + "alias": "eth4", + "description": "Ethernet4", + "speed": 25000, + "mtu": 9000, + "admin_status": "up" + }, + { + "port_name": "Ethernet5", + "alias": "eth5", + "description": "Ethernet5", + "speed": 25000, + "mtu": 9000, + "admin_status": "up" + }, + { + "port_name": "Ethernet6", + "alias": "eth6", + "description": "Ethernet6", + "speed": 25000, + "mtu": 9000, + "admin_status": "up" + }, + { + "port_name": "Ethernet7", + "alias": "eth7", + "description": "Ethernet7", + "speed": 25000, + "mtu": 9000, + "admin_status": "up" + }, + { + "port_name": "Ethernet8", + "alias": "eth8", + "description": "Ethernet8", + "speed": 25000, + "mtu": 9000, + "admin_status": "up" + }, + { + "port_name": "Ethernet9", + "alias": "eth9", + "description": "Ethernet9", + "speed": 25000, + "mtu": 9000, + "admin_status": "up" + } + ] + } + }, - "test-acl:acl": { - "test-acl:ACL_RULE": { - "ACL_RULE_LIST": [{ - "ACL_TABLE_NAME": "PACL-V4", - "RULE_NAME": "Rule_20", - "PACKET_ACTION": "FORWARD", - "DST_IP": "10.1.72.0/26", - "SRC_IP": "10.1.0.0/15", - "PRIORITY": "999980", - "IP_TYPE": "IPV4ANY" - }, - { - "ACL_TABLE_NAME": "PACL-V4", - "RULE_NAME": "Rule_40", - "PACKET_ACTION": "FORWARD", - "DST_IP": "10.1.72.64/26", - "SRC_IP": "10.1.0.0/15", - "PRIORITY": "999960", - "IP_TYPE": "IPV4ANY", - "INNER_ETHER_TYPE": "0x88CC" - }, - { - "ACL_TABLE_NAME": "PACL-V6", - "RULE_NAME": "Rule_20", - "PACKET_ACTION": "FORWARD", - "IP_TYPE": "IP", - "SRC_IPV6": "2000:f500:41::/48", - "PRIORITY": "999980", - "DST_IPV6": "2000:f500:43:320::/64", - "L4_SRC_PORT_RANGE": "653-1053" - } - ] - }, + "test-acl:acl": { + "test-acl:ACL_RULE": { + "ACL_RULE_LIST": [{ + "ACL_TABLE_NAME": "PACL-V4", + "RULE_NAME": "Rule_20", + "PACKET_ACTION": "FORWARD", + "DST_IP": "10.1.72.0/26", + "SRC_IP": "10.1.0.0/15", + "PRIORITY": "999980", + "IP_TYPE": "IPV4ANY" + }, + { + "ACL_TABLE_NAME": "PACL-V4", + "RULE_NAME": "Rule_40", + "PACKET_ACTION": "FORWARD", + "DST_IP": "10.1.72.64/26", + "SRC_IP": "10.1.0.0/15", + "PRIORITY": "999960", + "IP_TYPE": "IPV4ANY", + "INNER_ETHER_TYPE": "0x88CC" + }, + { + "ACL_TABLE_NAME": "PACL-V6", + "RULE_NAME": "Rule_20", + "PACKET_ACTION": "FORWARD", + "IP_TYPE": "IP", + "SRC_IPV6": "2000:f500:41::/48", + "PRIORITY": "999980", + "DST_IPV6": "2000:f500:43:320::/64", + "L4_SRC_PORT_RANGE": "653-1053" + } + ] + }, - "test-acl:ACL_TABLE": { - "ACL_TABLE_LIST": [{ - "ACL_TABLE_NAME": "PACL-V6", - "policy_desc": "Filter IPv6", - "type": "L3V6", - "stage": "EGRESS", - "ports": ["Ethernet7", "Ethernet9", "Ethernet8"] - }, - { - "ACL_TABLE_NAME": "PACL-V4", - "policy_desc": "Filter IPv6", - "type": "L3", - "stage": "INGRESS", - "ports": ["Ethernet2", "Ethernet0", "Ethernet1"] - } - ] - } - }, + "test-acl:ACL_TABLE": { + "ACL_TABLE_LIST": [{ + "ACL_TABLE_NAME": "PACL-V6", + "policy_desc": "Filter IPv6", + "type": "L3V6", + "stage": "EGRESS", + "ports": ["Ethernet7", "Ethernet9", "Ethernet8"] + }, + { + "ACL_TABLE_NAME": "PACL-V4", + "policy_desc": "Filter IPv6", + "type": "L3", + "stage": "INGRESS", + "ports": ["Ethernet2", "Ethernet0", "Ethernet1"] + } + ] + } + }, - "test-interface:interface": { - "test-interface:INTERFACE": { - "INTERFACE_LIST": [{ - "interface": "Ethernet8", - "ip-prefix": "10.1.1.65/26", - "scope": "global", - "family": "IPv4" - }, - { - "interface": "Ethernet8", - "ip-prefix": "2000:f500:40:a749::2/126", - "scope": "global", - "family": "IPv6" - } - ] - } - } + "test-interface:interface": { + "test-interface:INTERFACE": { + "INTERFACE_LIST": [{ + "interface": "Ethernet8", + "ip-prefix": "10.1.1.65/26", + "scope": "global", + "family": "IPv4" + }, + { + "interface": "Ethernet8", + "ip-prefix": "2000:f500:40:a749::2/126", + "scope": "global", + "family": "IPv6" + } + ] + } + } } diff --git a/src/sonic-yang-mgmt/tests/libyang-python-tests/sample-yang-models/test-vlan.yang b/src/sonic-yang-mgmt/tests/libyang-python-tests/sample-yang-models/test-vlan.yang index 06e853be0501..5b1314e03052 100644 --- a/src/sonic-yang-mgmt/tests/libyang-python-tests/sample-yang-models/test-vlan.yang +++ b/src/sonic-yang-mgmt/tests/libyang-python-tests/sample-yang-models/test-vlan.yang @@ -1,156 +1,156 @@ module test-vlan { - yang-version 1.1; + yang-version 1.1; + + namespace "http://github.com/Azure/vlan"; + prefix vlan; + + import ietf-yang-types { + prefix yang; + } + + import ietf-inet-types { + prefix inet; + } + + import test-head { + prefix head; + revision-date 2019-07-01; + } + + import test-port { + prefix port; + revision-date 2019-07-01; + } + + import test-portchannel { + prefix lag; + revision-date 2019-07-01; + } + + revision 2019-07-01 { + description "First Revision"; + } + + container vlan { + container VLAN_INTERFACE { + + description "VLAN_INTERFACE part of config_db.json"; + + list VLAN_INTERFACE_LIST { + + key "vlanid ip-prefix"; + + leaf vlanid { + type leafref { + path ../../../VLAN/VLAN_LIST/vlanid; + } + } + + leaf ip-prefix { + mandatory true; + type inet:ip-prefix; + } + + leaf scope { + type enumeration { + enum global; + enum local; + } + } + + leaf family { + + /* family leaf needed for backward compatibility + Both ip4 and ip6 address are string in IETF RFC 6021, + so must statement can check based on : or ., family + should be IPv4 or IPv6 according. + */ + + must "(contains(../ip-prefix, ':') and current()='IPv6') or + (contains(../ip-prefix, '.') and current()='IPv4')"; + type head:ip-family; + } + } + /* end of VLAN_INTERFACE_LIST */ + } + /* end of VLAN_INTERFACE container */ - namespace "http://github.com/Azure/vlan"; - prefix vlan; + container VLAN { - import ietf-yang-types { - prefix yang; - } + description "VLAN part of config_db.json"; - import ietf-inet-types { - prefix inet; - } + list VLAN_LIST { - import test-head { - prefix head; - revision-date 2019-07-01; - } + key "vlanid"; - import test-port { - prefix port; - revision-date 2019-07-01; - } + leaf vlanid { + type uint16 { + range 1..4094; + } + } - import test-portchannel { - prefix lag; - revision-date 2019-07-01; - } + leaf description { + type string { + length 1..255; + } + } + + leaf-list dhcp_servers { + type inet:ip-address; + } - revision 2019-07-01 { - description "First Revision"; - } + leaf mtu { + type uint16 { + range 1..9216; + } + } - container vlan { - container VLAN_INTERFACE { - - description "VLAN_INTERFACE part of config_db.json"; - - list VLAN_INTERFACE_LIST { - - key "vlanid ip-prefix"; - - leaf vlanid { - type leafref { - path ../../../VLAN/VLAN_LIST/vlanid; - } - } - - leaf ip-prefix { - mandatory true; - type inet:ip-prefix; - } - - leaf scope { - type enumeration { - enum global; - enum local; - } - } - - leaf family { - - /* family leaf needed for backward compatibility - Both ip4 and ip6 address are string in IETF RFC 6021, - so must statement can check based on : or ., family - should be IPv4 or IPv6 according. - */ - - must "(contains(../ip-prefix, ':') and current()='IPv6') or - (contains(../ip-prefix, '.') and current()='IPv4')"; - type head:ip-family; - } - } - /* end of VLAN_INTERFACE_LIST */ - } - /* end of VLAN_INTERFACE container */ - - container VLAN { - - description "VLAN part of config_db.json"; - - list VLAN_LIST { - - key "vlanid"; - - leaf vlanid { - type uint16 { - range 1..4094; - } - } - - leaf description { - type string { - length 1..255; - } - } - - leaf-list dhcp_servers { - type inet:ip-address; - } - - leaf mtu { - type uint16 { - range 1..9216; - } - } - - leaf admin_status { - mandatory true; - type head:admin_status; - } - } - /* end of VLAN_LIST */ - } - /* end of container VLAN */ - - container VLAN_MEMBER { - - description "VLAN_MEMBER part of config_db.json"; - - list VLAN_MEMBER_LIST { - - key "vlanid port"; - - leaf vlanid { - type leafref { - path ../../../VLAN/VLAN_LIST/vlanid; - } - } - - leaf port { - /* key elements are mandatory by default */ - mandatory true; - type union { - type leafref { - path /port:port/port:PORT/port:PORT_LIST/port:port_name; - } - type leafref { - path /lag:portchannel/lag:PORTCHANNEL/lag:PORTCHANNEL_LIST/lag:portchannel_name; - } - } - } - - leaf tagging_mode { - mandatory true; - type head:vlan_tagging_mode; - } - } + leaf admin_status { + mandatory true; + type head:admin_status; + } + } + /* end of VLAN_LIST */ + } + /* end of container VLAN */ + + container VLAN_MEMBER { + + description "VLAN_MEMBER part of config_db.json"; + + list VLAN_MEMBER_LIST { + + key "vlanid port"; + + leaf vlanid { + type leafref { + path ../../../VLAN/VLAN_LIST/vlanid; + } + } + + leaf port { + /* key elements are mandatory by default */ + mandatory true; + type union { + type leafref { + path /port:port/port:PORT/port:PORT_LIST/port:port_name; + } + type leafref { + path /lag:portchannel/lag:PORTCHANNEL/lag:PORTCHANNEL_LIST/lag:portchannel_name; + } + } + } + + leaf tagging_mode { + mandatory true; + type head:vlan_tagging_mode; + } + } /* end of list VLAN_MEMBER_LIST */ - } + } /* end of container VLAN_MEMBER */ - } + } /* end of container vlan */ } /* end of module vlan */