From a02255e2f49fabca11fb51a2a8d83cbfa3ac9c1b Mon Sep 17 00:00:00 2001 From: Praveen Chaudhary Date: Tue, 14 Apr 2020 15:36:02 -0700 Subject: [PATCH] [sonic-yang-models]: First version of yang models for Port, VLan, Interface, PortChannel, loopback and ACL. (#3730) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [sonic-yang-models]: First version of yang models for Port, VLan, Interface, PortChannel, loopback and ACL. YANG models as per Guidelines. Guideline doc: https://github.com/Azure/SONiC/blob/master/doc/mgmt/SONiC_YANG_Model_Guidelines.md [sonic-yang-models/tests]: YANG model test code and JSON input for testing. [sonic-yang-models/setup.py]: Build infra for yang models. **- What I did** Created Yang model for Sonic. Tables: PORT, VLAN, VLAN_INTERFACE, VLAN_MEMBER, ACL_RULE, ACL_TABLE, INTERFACE. Created build infra files using which a new package (sonic-yang-models) can be build and can be deployed on sonic switches. Yang models will be part of this new package. **- How I did it** Wrote yang models based on Guideline doc: https://github.com/Azure/SONiC/blob/master/doc/mgmt/SONiC_YANG_Model_Guidelines.md and https://github.com/Azure/SONiC/wiki/Configuration. Wrote python wheel Package infra which runs test for these Yang models using a json files which consists configuration as per yang models. These configs are for negative tests, which means we want to test that most must condition, pattern and when condition works as expected. **- How to verify it** Build Logs and testing: ——————————————————————————————————— ``` /sonic/src/sonic-yang-models /sonic running test running egg_info writing top-level names to sonic_yang_models.egg-info/top_level.txt writing dependency_links to sonic_yang_models.egg-info/dependency_links.txt writing sonic_yang_models.egg-info/PKG-INFO reading manifest file 'sonic_yang_models.egg-info/SOURCES.txt' writing manifest file 'sonic_yang_models.egg-info/SOURCES.txt' running build_ext ---------------------------------------------------------------------- Ran 0 tests in 0.000s OK running bdist_wheel running build running build_py (Reading database ... 155852 files and directories currently installed.) Preparing to unpack .../libyang_1.0.73_amd64.deb ... Unpacking libyang (1.0.73) over (1.0.73) ... Setting up libyang (1.0.73) ... Processing triggers for libc-bin (2.24-11+deb9u4) ... Processing triggers for man-db (2.7.6.1-2) ... (Reading database ... 155852 files and directories currently installed.) Preparing to unpack .../libyang-cpp_1.0.73_amd64.deb ... Unpacking libyang-cpp (1.0.73) over (1.0.73) ... Setting up libyang-cpp (1.0.73) ... Processing triggers for libc-bin (2.24-11+deb9u4) ... (Reading database ... 155852 files and directories currently installed.) Preparing to unpack .../python3-yang_1.0.73_amd64.deb ... Unpacking python3-yang (1.0.73) over (1.0.73) ... Setting up python3-yang (1.0.73) ... INFO:YANG-TEST:module: sonic-vlan is loaded successfully ERROR:YANG-TEST:Could not get module: sonic-head INFO:YANG-TEST:module: sonic-portchannel is loaded successfully INFO:YANG-TEST:module: sonic-acl is loaded successfully INFO:YANG-TEST:module: sonic-loopback-interface is loaded successfully ERROR:YANG-TEST:Could not get module: sonic-port INFO:YANG-TEST:module: sonic-interface is loaded successfully INFO:YANG-TEST: ------------------- Test 1: Configure a member port in VLAN_MEMBER table which does not exist.--------------------- libyang[0]: Leafref "/sonic-port:sonic-port/sonic-port:PORT/sonic-port:PORT_LIST/sonic-port:port_name" of value "Ethernet156" points to a non -existing leaf. (path: /sonic-vlan:sonic-vlan/VLAN_MEMBER/VLAN_MEMBER_LIST[vlan_name='Vlan100'][port='Ethernet156']/port) INFO:YANG-TEST:Configure a member port in VLAN_MEMBER table which does not exist. Passed INFO:YANG-TEST: ------------------- Test 2: Configure non-existing ACL_TABLE in ACL_RULE.--------------------- libyang[0]: Leafref "/sonic-acl:sonic-acl/sonic-acl:ACL_TABLE/sonic-acl:ACL_TABLE_LIST/sonic-acl:ACL_TABLE_NAME" of value "NOT-EXIST" points to a non-existing leaf. (path: /sonic-acl:sonic-acl/ACL_RULE/ACL_RULE_LIST[ACL_TABLE_NAME='NOT-EXIST'][RULE_NAME='Rule_20']/ACL_TABLE_NAME) INFO:YANG-TEST:Configure non-existing ACL_TABLE in ACL_RULE. Passed INFO:YANG-TEST: ------------------- Test 3: Configure IP_TYPE as ARP and ICMPV6_CODE in ACL_RULE.--------------------- libyang[0]: When condition "boolean(IP_TYPE[.='ANY' or .='IP' or .='IPV6' or .='IPv6ANY'])" not satisfied. (path: /sonic-acl:sonic-acl/ACL_RU LE/ACL_RULE_LIST[ACL_TABLE_NAME='NO-NSW-PACL-V4'][RULE_NAME='Rule_40']/ICMPV6_CODE) INFO:YANG-TEST:Configure IP_TYPE as ARP and ICMPV6_CODE in ACL_RULE. Passed INFO:YANG-TEST: INFO:YANG-TEST: ------------------- Test 4: Configure IP_TYPE as ipv4any and SRC_IPV6 in ACL_RULE.--------------------- libyang[0]: When condition "boolean(IP_TYPE[.='ANY' or .='IP' or .='IPV6' or .='IPv6ANY'])" not satisfied. (path: /sonic-acl:sonic-acl/ACL_RU LE/ACL_RULE_LIST[ACL_TABLE_NAME='NO-NSW-PACL-V4'][RULE_NAME='Rule_20']/SRC_IPV6) INFO:YANG-TEST:Configure IP_TYPE as ipv4any and SRC_IPV6 in ACL_RULE. Passed ------------------- Test 5: Configure l4_src_port_range as 99999-99999 in ACL_RULE--------------------- libyang[0]: Value "99999-99999" does not satisfy the constraint "([0-9]{1,4}|[0-5][0-9]{4}|[6][0-4][0-9]{3}|[6][5][0-2][0-9]{2}|[6][5][3][0-5]{2}|[6][5][3][6][0-5])-([0-9]{1,4}|[0-5][0-9]{4}|[6][0-4][0-9]{3}|[6][5][0-2][0-9]{2}|[6][5][3][0-5]{2}|[6][5][3][6][0-5])" (range, length, or pattern). (path: /sonic-acl:sonic-acl/ACL_RULE/ACL_RULE_LIST[ACL_TABLE_NAME='NO-NSW-PACL-V6'][RULE_NAME='Rule_20']/L4_SRC_PORT_RANGE) INFO:YANG-TEST:Configure l4_src_port_range as 99999-99999 in ACL_RULE Passed INFO:YANG-TEST: ------------------- Test 6: Configure empty string as ip-prefix in INTERFACE table.--------------------- libyang[0]: Invalid value "" in "ip-prefix" element. (path: /sonic-interface:sonic-interface/INTERFACE/INTERFACE_LIST[interface='Ethernet8'][ip-prefix='']/ip-prefix) INFO:YANG-TEST:Configure empty string as ip-prefix in INTERFACE table. Passed INFO:YANG-TEST: ------------------- Test 7: Configure Wrong family with ip-prefix for VLAN_Interface Table--------------------- libyang[0]: Must condition "(contains(../ip-prefix, ':') and current()='IPv6') or (contains(../ip-prefix, '.') and current()='IPv4')" not satisfied. (path: /sonic-vlan:sonic-vlan/VLAN_INTERFACE/VLAN_INTERFACE_LIST[vlanid='100'][ip-prefix='2a04:5555:66:7777::1/64']/family) INFO:YANG-TEST:Configure Wrong family with ip-prefix for VLAN_Interface Table Passed INFO:YANG-TEST: ------------------- Test 8: Configure IP_TYPE as ARP and DST_IPV6 in ACL_RULE.--------------------- libyang[0]: When condition "boolean(IP_TYPE[.='ANY' or .='IP' or .='IPV6' or .='IPV6ANY'])" not satisfied. (path: /sonic-acl:sonic-acl/ACL_RULE/ACL_RULE_LIST[ACL_TABLE_NAME='NO-NS W-PACL-V6'][RULE_NAME='Rule_20']/DST_IPV6) INFO:YANG-TEST:Configure IP_TYPE as ARP and DST_IPV6 in ACL_RULE. Passed INFO:YANG-TEST: ------------------- Test 9: Configure INNER_ETHER_TYPE as 0x080C in ACL_RULE.--------------------- libyang[0]: Value "0x080C" does not satisfy the constraint "(0x88CC|0x8100|0x8915|0x0806|0x0800|0x86DD|0x8847)" (range, length, or pattern). (path: /sonic-acl:sonic-acl/ACL_RULE/ACL_RULE_LIST[ACL_TABLE_NAME='NO-NSW-PACL-V4'][RULE_NAME='Rule_40']/INNER_ETHER_TYPE) INFO:YANG-TEST:Configure INNER_ETHER_TYPE as 0x080C in ACL_RULE. Passed INFO:YANG-TEST: ------------------- Test 10: Add dhcp_server which is not in correct ip-prefix format.--------------------- libyang[0]: Invalid value "10.186.72.566" in "dhcp_servers" element. (path: /sonic-vlan:sonic-vlan/VLAN/VLAN_LIST/dhcp_servers[.='10.186.72.566']) INFO:YANG-TEST:Add dhcp_server which is not in correct ip-prefix format. Passed INFO:YANG-TEST: ------------------- Test 11: Configure undefined acl_table_type in ACL_TABLE table.--------------------- libyang[0]: Invalid value "LAYER3V4" in "type" element. (path: /sonic-acl:sonic-acl/ACL_TABLE/ACL_TABLE_LIST[ACL_TABLE_NAME='NO-NSW-PACL-V6']/type) INFO:YANG-TEST:Configure undefined acl_table_type in ACL_TABLE table. Passed INFO:YANG-TEST: ------------------- Test 12: Configure undefined packet_action in ACL_RULE table.--------------------- libyang[0]: Invalid value "SEND" in "PACKET_ACTION" element. (path: /sonic-acl:sonic-acl/ACL_RULE/ACL_RULE_LIST/PACKET_ACTION) INFO:YANG-TEST:Configure undefined packet_action in ACL_RULE table. Passed INFO:YANG-TEST: ------------------- Test 13: Configure wrong value for tagging_mode.--------------------- libyang[0]: Invalid value "non-tagged" in "tagging_mode" element. (path: /sonic-vlan:sonic-vlan/VLAN_MEMBER/VLAN_MEMBER_LIST/tagging_mode) INFO:YANG-TEST:Configure wrong value for tagging_mode. Passed INFO:YANG-TEST: ------------------- Test 14: Configure vlan-id in VLAN_MEMBER table which does not exist in VLAN table.--------------------- libyang[0]: Leafref "../../../VLAN/VLAN_LIST/vlanid" of value "200" points to a non-existing leaf. (path: /sonic-vlan:sonic-vlan/VLAN_MEMBER/VLAN_MEMBER_LIST[vlanid='200'][port='Ethernet0']/vlanid) libyang[0]: Leafref "../../../VLAN/VLAN_LIST/vlanid" of value "200" points to a non-existing leaf. (path: /sonic-vlan:sonic-vlan/VLAN_MEMBER/VLAN_MEMBER_LIST[vlanid='200'][port='Ethernet0']/vlanid) INFO:YANG-TEST:Configure vlan-id in VLAN_MEMBER table which does not exist in VLAN table. Passed INFO:YANG-TEST:All Test Passed ../../target/debs/stretch/libyang0.16_0.16.105-1_amd64.deb installtion failed ../../target/debs/stretch/libyang-cpp0.16_0.16.105-1_amd64.deb installtion failed ../../target/debs/stretch/python2-yang_0.16.105-1_amd64.deb installtion failed YANG Tests passed Passed: pyang -f tree ./yang-models/*.yang > ./yang-models/sonic_yang_tree copying tests/yangModelTesting.py -> build/lib/tests copying tests/test_sonic_yang_models.py -> build/lib/tests copying tests/__init__.py -> build/lib/tests running egg_info writing top-level names to sonic_yang_models.egg-info/top_level.txt writing dependency_links to sonic_yang_models.egg-info/dependency_links.txt writing sonic_yang_models.egg-info/PKG-INFO reading manifest file 'sonic_yang_models.egg-info/SOURCES.txt' writing manifest file 'sonic_yang_models.egg-info/SOURCES.txt' installing to build/bdist.linux-x86_64/wheel running install running install_lib creating build/bdist.linux-x86_64/wheel creating build/bdist.linux-x86_64/wheel/tests copying build/lib/tests/yangModelTesting.py -> build/bdist.linux-x86_64/wheel/tests copying build/lib/tests/test_sonic_yang_models.py -> build/bdist.linux-x86_64/wheel/tests copying build/lib/tests/__init__.py -> build/bdist.linux-x86_64/wheel/tests running install_data creating build/bdist.linux-x86_64/wheel/sonic_yang_models-1.0.data creating build/bdist.linux-x86_64/wheel/sonic_yang_models-1.0.data/data creating build/bdist.linux-x86_64/wheel/sonic_yang_models-1.0.data/data/yang-models copying ./yang-models/sonic-head.yang -> build/bdist.linux-x86_64/wheel/sonic_yang_models-1.0.data/data/yang-models copying ./yang-models/sonic-acl.yang -> build/bdist.linux-x86_64/wheel/sonic_yang_models-1.0.data/data/yang-models copying ./yang-models/sonic-interface.yang -> build/bdist.linux-x86_64/wheel/sonic_yang_models-1.0.data/data/yang-models copying ./yang-models/sonic-loopback-interface.yang -> build/bdist.linux-x86_64/wheel/sonic_yang_models-1.0.data/data/yang-models copying ./yang-models/sonic-port.yang -> build/bdist.linux-x86_64/wheel/sonic_yang_models-1.0.data/data/yang-models copying ./yang-models/sonic-portchannel.yang -> build/bdist.linux-x86_64/wheel/sonic_yang_models-1.0.data/data/yang-models copying ./yang-models/sonic-vlan.yang -> build/bdist.linux-x86_64/wheel/sonic_yang_models-1.0.data/data/yang-models ``` --- .../build_templates/sonic_debian_extension.j2 | 9 + rules/sonic-yang-models-py3.mk | 7 + slave.mk | 9 +- sonic-slave-stretch/Dockerfile.j2 | 7 + src/sonic-yang-models/AUTHORS.rst | 14 + src/sonic-yang-models/LICENSE | 13 + src/sonic-yang-models/README.rst | 4 + src/sonic-yang-models/setup.py | 114 ++ src/sonic-yang-models/tests/__init__.py | 3 + .../tests/test_sonic_yang_models.py | 21 + .../yang_model_tests/yangModelTesting.py | 288 ++++ .../tests/yang_model_tests/yangTest.json | 1284 +++++++++++++++++ .../yang-models/sonic-acl.yang | 283 ++++ .../yang-models/sonic-extension.yang | 23 + .../yang-models/sonic-interface.yang | 122 ++ .../yang-models/sonic-loopback-interface.yang | 98 ++ .../yang-models/sonic-port.yang | 105 ++ .../yang-models/sonic-portchannel.yang | 92 ++ .../yang-models/sonic-types.yang | 92 ++ .../yang-models/sonic-vlan.yang | 209 +++ 20 files changed, 2795 insertions(+), 2 deletions(-) create mode 100644 rules/sonic-yang-models-py3.mk create mode 100644 src/sonic-yang-models/AUTHORS.rst create mode 100644 src/sonic-yang-models/LICENSE create mode 100644 src/sonic-yang-models/README.rst create mode 100644 src/sonic-yang-models/setup.py create mode 100644 src/sonic-yang-models/tests/__init__.py create mode 100644 src/sonic-yang-models/tests/test_sonic_yang_models.py create mode 100644 src/sonic-yang-models/tests/yang_model_tests/yangModelTesting.py create mode 100644 src/sonic-yang-models/tests/yang_model_tests/yangTest.json create mode 100644 src/sonic-yang-models/yang-models/sonic-acl.yang create mode 100644 src/sonic-yang-models/yang-models/sonic-extension.yang create mode 100644 src/sonic-yang-models/yang-models/sonic-interface.yang create mode 100644 src/sonic-yang-models/yang-models/sonic-loopback-interface.yang create mode 100644 src/sonic-yang-models/yang-models/sonic-port.yang create mode 100644 src/sonic-yang-models/yang-models/sonic-portchannel.yang create mode 100644 src/sonic-yang-models/yang-models/sonic-types.yang create mode 100644 src/sonic-yang-models/yang-models/sonic-vlan.yang diff --git a/files/build_templates/sonic_debian_extension.j2 b/files/build_templates/sonic_debian_extension.j2 index 49acd0647ad1..ba9595896022 100644 --- a/files/build_templates/sonic_debian_extension.j2 +++ b/files/build_templates/sonic_debian_extension.j2 @@ -116,6 +116,15 @@ sudo cp {{swsssdk_py2_wheel_path}} $FILESYSTEM_ROOT/$SWSSSDK_PY2_WHEEL_NAME sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip install $SWSSSDK_PY2_WHEEL_NAME sudo rm -rf $FILESYSTEM_ROOT/$SWSSSDK_PY2_WHEEL_NAME +# Install sonic-yang-models py3 package, install dependencies +sudo dpkg --root=$FILESYSTEM_ROOT -i $debs_path/libyang_*.deb +sudo dpkg --root=$FILESYSTEM_ROOT -i $debs_path/libyang-cpp_*.deb +sudo dpkg --root=$FILESYSTEM_ROOT -i $debs_path/python2-yang_*.deb +SONIC_YANG_MODEL_PY3_WHEEL_NAME=$(basename {{sonic_yang_models_py3_wheel_path}}) +sudo cp {{sonic_yang_models_py3_wheel_path}} $FILESYSTEM_ROOT/$SONIC_YANG_MODEL_PY3_WHEEL_NAME +sudo https_proxy=$https_proxy LANG=C chroot $FILESYSTEM_ROOT pip3 install $SONIC_YANG_MODEL_PY3_WHEEL_NAME +sudo rm -rf $FILESYSTEM_ROOT/$SONIC_YANG_MODEL_PY3_WHEEL_NAME + # Install sonic-platform-common Python 2 package PLATFORM_COMMON_PY2_WHEEL_NAME=$(basename {{platform_common_py2_wheel_path}}) sudo cp {{platform_common_py2_wheel_path}} $FILESYSTEM_ROOT/$PLATFORM_COMMON_PY2_WHEEL_NAME diff --git a/rules/sonic-yang-models-py3.mk b/rules/sonic-yang-models-py3.mk new file mode 100644 index 000000000000..d2bd01bb9005 --- /dev/null +++ b/rules/sonic-yang-models-py3.mk @@ -0,0 +1,7 @@ +SONIC_YANG_MODELS_PY3 = sonic_yang_models-1.0-py3-none-any.whl +$(SONIC_YANG_MODELS_PY3)_SRC_PATH = $(SRC_PATH)/sonic-yang-models +$(SONIC_YANG_MODELS_PY3)_PYTHON_VERSION = 3 +$(SONIC_YANG_MODELS_PY3)_DEBS_DEPENDS = $(LIBYANG) + +SONIC_PYTHON_WHEELS += $(SONIC_YANG_MODELS_PY3) +export SONIC_YANG_MODELS_PY3 diff --git a/slave.mk b/slave.mk index 01bb5df7de84..f2f2a8605c8b 100644 --- a/slave.mk +++ b/slave.mk @@ -49,6 +49,8 @@ export BUILD_NUMBER export BUILD_TIMESTAMP export CONFIGURED_PLATFORM export CONFIGURED_ARCH +export STRETCH_DEBS_PATH +export PYTHON_WHEELS_PATH ############################################################################### ## Utility rules @@ -525,7 +527,8 @@ SONIC_TARGET_LIST += $(addprefix $(PYTHON_DEBS_PATH)/, $(SONIC_PYTHON_STDEB_DEBS # $(SOME_NEW_WHL)_DEPENDS = $(SOME_OTHER_WHL1) $(SOME_OTHER_WHL2) ... # SONIC_PYTHON_WHEELS += $(SOME_NEW_WHL) $(addprefix $(PYTHON_WHEELS_PATH)/, $(SONIC_PYTHON_WHEELS)) : $(PYTHON_WHEELS_PATH)/% : .platform $$(addsuffix -install,$$(addprefix $(PYTHON_WHEELS_PATH)/,$$($$*_DEPENDS))) \ - $(call dpkg_depend,$(PYTHON_WHEELS_PATH)/%.dep) + $(call dpkg_depend,$(PYTHON_WHEELS_PATH)/%.dep) \ + $$(addsuffix -install,$$(addprefix $(DEBS_PATH)/,$$($$*_DEBS_DEPENDS))) $(HEADER) @@ -750,7 +753,8 @@ $(addprefix $(TARGET_PATH)/, $(SONIC_INSTALLERS)) : $(TARGET_PATH)/% : \ $(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_CONFIG_ENGINE)) \ $(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_PLATFORM_COMMON_PY2)) \ $(addprefix $(PYTHON_WHEELS_PATH)/,$(REDIS_DUMP_LOAD_PY2)) \ - $(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_PLATFORM_API_PY2)) + $(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_PLATFORM_API_PY2)) \ + $(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_YANG_MODELS_PY3)) $(HEADER) # Pass initramfs and linux kernel explicitly. They are used for all platforms export debs_path="$(STRETCH_DEBS_PATH)" @@ -780,6 +784,7 @@ $(addprefix $(TARGET_PATH)/, $(SONIC_INSTALLERS)) : $(TARGET_PATH)/% : \ export platform_common_py2_wheel_path="$(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_PLATFORM_COMMON_PY2))" export redis_dump_load_py2_wheel_path="$(addprefix $(PYTHON_WHEELS_PATH)/,$(REDIS_DUMP_LOAD_PY2))" export install_debug_image="$(INSTALL_DEBUG_TOOLS)" + export sonic_yang_models_py3_wheel_path="$(addprefix $(PYTHON_WHEELS_PATH)/,$(SONIC_YANG_MODELS_PY3))" export multi_instance="false" $(foreach docker, $($*_DOCKERS),\ diff --git a/sonic-slave-stretch/Dockerfile.j2 b/sonic-slave-stretch/Dockerfile.j2 index f9e96791464d..af5f441c8842 100644 --- a/sonic-slave-stretch/Dockerfile.j2 +++ b/sonic-slave-stretch/Dockerfile.j2 @@ -367,6 +367,13 @@ RUN pip install mockredispy==2.9.3 RUN pip install pytest-runner==4.4 RUN pip install setuptools==40.8.0 +# For sonic_yang_mgmt build +RUN pip install ijson==2.6.1 +RUN pip3 install ijson==2.6.1 +RUN pip install jsondiff==1.2.0 +RUN pip install xmltodict==0.12.0 +RUN pip install pyang==2.1.1 + # For mgmt-framework build RUN pip install mmh3 diff --git a/src/sonic-yang-models/AUTHORS.rst b/src/sonic-yang-models/AUTHORS.rst new file mode 100644 index 000000000000..43adb0900334 --- /dev/null +++ b/src/sonic-yang-models/AUTHORS.rst @@ -0,0 +1,14 @@ +======= +Credits +======= + +Development Lead +---------------- + +LNOS-CODERS +MSFT-LINUX-DEV + +Contributors +------------ + +Praveen Chaudhary diff --git a/src/sonic-yang-models/LICENSE b/src/sonic-yang-models/LICENSE new file mode 100644 index 000000000000..cf593b111eab --- /dev/null +++ b/src/sonic-yang-models/LICENSE @@ -0,0 +1,13 @@ +Copyright 2019 Microsoft, 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. diff --git a/src/sonic-yang-models/README.rst b/src/sonic-yang-models/README.rst new file mode 100644 index 000000000000..6cb6d091367b --- /dev/null +++ b/src/sonic-yang-models/README.rst @@ -0,0 +1,4 @@ +" +This Package contains YANG models for sonic which are written with guidelines mentioned in +https://github.com/Azure/SONiC/blob/master/doc/mgmt/SONiC_YANG_Model_Guidelines.md. +" diff --git a/src/sonic-yang-models/setup.py b/src/sonic-yang-models/setup.py new file mode 100644 index 000000000000..d53d5fb901eb --- /dev/null +++ b/src/sonic-yang-models/setup.py @@ -0,0 +1,114 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +"""The setup script.""" + +from setuptools import setup, find_packages +from setuptools.command.build_py import build_py +from os import system, environ +from sys import exit + +# find path of pkgs from environment vars +prefix = '/sonic'; debs = environ["STRETCH_DEBS_PATH"] +deps_path = '{}/{}'.format(prefix, debs) +# dependencies +libyang = '{}/{}'.format(deps_path, environ["LIBYANG"]) +libyangCpp = '{}/{}'.format(deps_path, environ["LIBYANG_CPP"]) +libyangPy2 = '{}/{}'.format(deps_path, environ["LIBYANG_PY2"]) +libyangPy3 = '{}/{}'.format(deps_path, environ["LIBYANG_PY3"]) + +# important reuirements parameters +build_requirements = [libyang, libyangCpp, libyangPy2, libyangPy3,] + +setup_requirements = ['pytest-runner'] + +test_requirements = ['pytest>=3'] + +# read me +with open('README.rst') as readme_file: + readme = readme_file.read() + +# class for prerequisites to build this package +class pkgBuild(build_py): + """Custom Build PLY""" + + def run (self): + # install libyang + for req in build_requirements: + if '.deb'in req: + pkg_install_cmd = "sudo dpkg -i {}".format(req) + if (system(pkg_install_cmd)): + print("{} installation failed".format(req)) + exit(1) + else: + print("{} installed".format(req)) + + # json file for YANG model test cases. + test_yangJson_file = './tests/yang_model_tests/yangTest.json' + # YANG models are in below dir + yang_model_dir = './yang-models/' + # yang model tester python module + yang_test_py = './tests/yang_model_tests/yangModelTesting.py' + # run tests for yang models + test_yang_cmd = "python {} -f {} -y {}".format(yang_test_py, test_yangJson_file, yang_model_dir) + if (system(test_yang_cmd)): + print("YANG Tests failed\n") + # below line will be uncommented after libyang python support PR # + exit(1) + else: + print("YANG Tests passed\n") + + # Generate YANG Tree + pyang_tree_cmd = "pyang -f tree ./yang-models/*.yang > ./yang-models/sonic_yang_tree" + if (system(pyang_tree_cmd)): + print("Failed: {}".format(pyang_tree_cmd)) + else: + print("Passed: {}".format(pyang_tree_cmd)) + + # Continue usual build steps + build_py.run(self) + +setup( + cmdclass={ + 'build_py': pkgBuild, + }, + author="lnos-coders", + author_email='lnos-coders@linkedin.com', + python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*', + classifiers=[ + 'Development Status :: 2 - Pre-Alpha', + 'Intended Audience :: Developers', + 'License :: OSI Approved :: GNU General Public License v3 (GPLv3)', + 'Natural Language :: English', + "Programming Language :: Python :: 2", + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', + 'Programming Language :: Python :: 3.8', + ], + description="Package contains YANG models for sonic.", + tests_require = test_requirements, + license="GNU General Public License v3", + long_description=readme + '\n\n', + include_package_data=True, + keywords='sonic_yang_models', + name='sonic_yang_models', + py_modules=[], + packages=find_packages(), + setup_requires=setup_requirements, + version='1.0', + data_files=[ + ('yang-models', ['./yang-models/sonic-types.yang', + './yang-models/sonic-extension.yang', + './yang-models/sonic-acl.yang', + './yang-models/sonic-interface.yang', + './yang-models/sonic-loopback-interface.yang', + './yang-models/sonic-port.yang', + './yang-models/sonic-portchannel.yang', + './yang-models/sonic-vlan.yang', + './yang-models/sonic_yang_tree']), + ], + zip_safe=False, +) diff --git a/src/sonic-yang-models/tests/__init__.py b/src/sonic-yang-models/tests/__init__.py new file mode 100644 index 000000000000..c116c5072b34 --- /dev/null +++ b/src/sonic-yang-models/tests/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +"""Unit test package for sonic_yang_models.""" diff --git a/src/sonic-yang-models/tests/test_sonic_yang_models.py b/src/sonic-yang-models/tests/test_sonic_yang_models.py new file mode 100644 index 000000000000..e8acedf9f974 --- /dev/null +++ b/src/sonic-yang-models/tests/test_sonic_yang_models.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +"""Tests for `sonic_yang_models` package.""" + +import pytest + +@pytest.fixture +def response(): + """Sample pytest fixture. + + See more at: http://doc.pytest.org/en/latest/fixture.html + """ + # import requests + # return requests.get('https://github.com/audreyr/cookiecutter-pypackage') + + +def test_content(response): + """Sample pytest test function with the pytest fixture as an argument.""" + # from bs4 import BeautifulSoup + # assert 'GitHub' in BeautifulSoup(response.content).title.string diff --git a/src/sonic-yang-models/tests/yang_model_tests/yangModelTesting.py b/src/sonic-yang-models/tests/yang_model_tests/yangModelTesting.py new file mode 100644 index 000000000000..d36416adcae7 --- /dev/null +++ b/src/sonic-yang-models/tests/yang_model_tests/yangModelTesting.py @@ -0,0 +1,288 @@ +# This script is used to + +import yang as ly +import logging +import argparse +import sys +import ijson +import json +#import sonic_yang as sy +from glob import glob +from os import listdir +from os.path import isfile, join, splitext + +#Globals vars +PASS = 0 +FAIL = 1 +logging.basicConfig(level=logging.DEBUG) +log = logging.getLogger("YANG-TEST") +log.setLevel(logging.INFO) +log.addHandler(logging.NullHandler()) + +# Global functions +def printExceptionDetails(): + try: + excType, excObj, traceBack = sys.exc_info() + fileName = traceBack.tb_frame.f_code.co_filename + lineNumber = traceBack.tb_lineno + log.error(" Exception >{}< in {}:{}".format(excObj, fileName, lineNumber)) + except Exception as e: + log.error(" Exception in printExceptionDetails") + return + +# class for YANG Model YangModelTesting +# Run function will run all the tests +# from a user given list. + +class YangModelTesting: + + def __init__(self, tests, yangDir, jsonFile): + self.defaultYANGFailure = { + 'Must': ['Must condition', 'not satisfied'], + 'InvalidValue': ['Invalid value'], + 'LeafRef': ['Leafref', 'non-existing'], + 'When': ['When condition', 'not satisfied'], + 'Pattern': ['pattern', 'does not satisfy'], + 'None': [''] + } + + self.ExceptionTests = { + 'WRONG_FAMILY_WITH_IP_PREFIX': { + 'desc': 'Configure Wrong family with ip-prefix for VLAN_Interface Table', + 'eStr': self.defaultYANGFailure['Must'] + }, + 'DHCP_SERVER_INCORRECT_FORMAT': { + 'desc': 'Add dhcp_server which is not in correct ip-prefix format.', + 'eStr': self.defaultYANGFailure['InvalidValue'] + ['dhcp_servers'] + }, + 'VLAN_WITH_NON_EXIST_PORT': { + 'desc': 'Configure a member port in VLAN_MEMBER table which does not exist.', + 'eStr': self.defaultYANGFailure['LeafRef'] + }, + 'VLAN_MEMEBER_WITH_NON_EXIST_VLAN': { + 'desc': 'Configure vlan-id in VLAN_MEMBER table which does not exist in VLAN table.', + 'eStr': self.defaultYANGFailure['LeafRef'] + }, + 'TAGGING_MODE_WRONG_VALUE': { + 'desc': 'Configure wrong value for tagging_mode.', + 'eStr': self.defaultYANGFailure['InvalidValue'] + ['tagging_mode'] + }, + 'INTERFACE_IP_PREFIX_EMPTY_STRING': { + 'desc': 'Configure empty string as ip-prefix in INTERFACE table.', + 'eStr': self.defaultYANGFailure['InvalidValue'] + ['ip-prefix'] + }, + 'ACL_RULE_UNDEFINED_PACKET_ACTION': { + 'desc': 'Configure undefined packet_action in ACL_RULE table.', + 'eStr': self.defaultYANGFailure['InvalidValue'] + ['PACKET_ACTION'] + }, + 'ACL_TABLE_UNDEFINED_TABLE_TYPE': { + 'desc': 'Configure undefined acl_table_type in ACL_TABLE table.', + 'eStr': self.defaultYANGFailure['InvalidValue'] + ['type'] + }, + 'ACL_RULE_WITH_NON_EXIST_ACL_TABLE': { + 'desc': 'Configure non-existing ACL_TABLE in ACL_RULE.', + 'eStr': self.defaultYANGFailure['LeafRef'] + }, + 'ACL_RULE_IP_TYPE_SRC_IPV6_MISMATCH': { + 'desc': 'Configure IP_TYPE as ipv4any and SRC_IPV6 in ACL_RULE.', + 'eStr': self.defaultYANGFailure['When'] + ['IP_TYPE'] + }, + 'ACL_RULE_ARP_TYPE_DST_IPV6_MISMATCH': { + 'desc': 'Configure IP_TYPE as ARP and DST_IPV6 in ACL_RULE.', + 'eStr': self.defaultYANGFailure['When'] + ['IP_TYPE'] + }, + 'ACL_RULE_WRONG_L4_SRC_PORT_RANGE': { + 'desc': 'Configure l4_src_port_range as 99999-99999 in ACL_RULE', + 'eStr': self.defaultYANGFailure['Pattern'] + }, + 'ACL_RULE_ARP_TYPE_ICMPV6_CODE_MISMATCH': { + 'desc': 'Configure IP_TYPE as ARP and ICMPV6_CODE in ACL_RULE.', + 'eStr': self.defaultYANGFailure['When'] + ['IP_TYPE'] + }, + 'ACL_RULE_WRONG_INNER_ETHER_TYPE': { + 'desc': 'Configure INNER_ETHER_TYPE as 0x080C in ACL_RULE.', + 'eStr': self.defaultYANGFailure['Pattern'] + }, + 'INTERFACE_IPPREFIX_PORT_MUST_CONDITION_FALSE': { + 'desc': 'Interface Ip-prefix port-name must condition failure.', + 'eStr': self.defaultYANGFailure['Must'] + }, + 'INTERFACE_IPPREFIX_PORT_MUST_CONDITION_TRUE': { + 'desc': 'Interface Ip-prefix port-name must condition pass.', + 'eStr': self.defaultYANGFailure['None'] + }, + 'VLAN_INTERFACE_IPPREFIX_MUST_CONDITION_FALSE': { + 'desc': 'Vlan Interface Ip-prefix must condition failure.', + 'eStr': self.defaultYANGFailure['Must'] + }, + 'LOOPBACK_IPPREFIX_PORT_MUST_CONDITION_FALSE': { + 'desc': 'Loopback Ip-prefix port-name must condition failure.', + 'eStr': self.defaultYANGFailure['Must'] + } + } + + self.tests = tests + if (self.tests == None): + self.tests = self.ExceptionTests.keys() + self.yangDir = yangDir + self.jsonFile = jsonFile + self.testNum = 1 + # other class vars + # self.ctx + return + + """ + load all YANG models before test run + """ + def loadYangModel(self, yangDir): + + try: + # create context + self.ctx = ly.Context(yangDir) + # get all files + yangFiles = glob(yangDir +"/*.yang") + # load yang modules + for file in yangFiles: + log.debug(file) + m = self.ctx.parse_module_path(file, ly.LYS_IN_YANG) + if m is not None: + log.info("module: {} is loaded successfully".format(m.name())) + else: + log.info("Could not load module: {}".format(file)) + + except Exception as e: + printExceptionDetails() + raise e + return + + """ + Run all tests from list self.tests + """ + def run(self): + try: + self.loadYangModel(self.yangDir) + ret = 0 + for test in self.tests: + test = test.strip() + if test in self.ExceptionTests: + ret = ret + self.runExceptionTest(test); + except Exception as e: + printExceptionDetails() + raise e + return ret + + """ + Get the JSON input based on func name + and return jsonInput + """ + def readJsonInput(self, test): + try: + # load test specific Dictionary, using Key = func + # this is to avoid loading very large JSON in memory + log.debug(" Read JSON Section: " + test) + jInput = "" + with open(self.jsonFile, 'rb') as f: + jInst = ijson.items(f, test) + for it in jInst: + jInput = jInput + json.dumps(it) + log.debug(jInput) + except Exception as e: + printExceptionDetails() + return jInput + + """ + Log the start of a test + """ + def logStartTest(self, desc): + log.info("\n------------------- Test "+ str(self.testNum) +\ + ": " + desc + "---------------------") + self.testNum = self.testNum + 1 + return + + """ + Load Config Data and return Exception as String + """ + def loadConfigData(self, jInput): + s = "" + try: + node = self.ctx.parse_data_mem(jInput, ly.LYD_JSON, \ + ly.LYD_OPT_CONFIG | ly.LYD_OPT_STRICT) + except Exception as e: + s = str(e) + log.debug(s) + return s + + """ + Run Exception Test + """ + def runExceptionTest(self, test): + try: + desc = self.ExceptionTests[test]['desc'] + self.logStartTest(desc) + jInput = self.readJsonInput(test) + # load the data, expect a exception with must condition failure + s = self.loadConfigData(jInput) + eStr = self.ExceptionTests[test]['eStr'] + log.debug(eStr) + if (sum(1 for str in eStr if str not in s) == 0): + log.info(desc + " Passed\n") + return PASS + except Exception as e: + printExceptionDetails() + log.info(desc + " Failed\n") + return FAIL + +# End of Class + +""" + Start Here +""" +def main(): + parser = argparse.ArgumentParser(description='Script to run YANG model tests', + formatter_class=argparse.RawTextHelpFormatter, + epilog=""" +Usage: +python yangModelTesting.py -h +""") + parser.add_argument('-t', '--tests', type=str, \ + help='tests to run separated by comma') + parser.add_argument('-f', '--json-file', type=str, \ + help='JSON input for tests ', required=True) + parser.add_argument('-y', '--yang-dir', type=str, \ + help='Path to YANG models', required=True) + parser.add_argument('-v', '--verbose-level', \ + help='Verbose mode', action='store_true') + parser.add_argument('-l', '--list-tests', \ + help='list all tests', action='store_true') + + args = parser.parse_args() + try: + tests = args.tests + jsonFile = args.json_file + yangDir = args.yang_dir + logLevel = args.verbose_level + listTests = args.list_tests + if logLevel: + log.setLevel(logging.DEBUG) + # Make a list + if (tests): + tests = tests.split(",") + + yTest = YangModelTesting(tests, yangDir, jsonFile) + if (listTests): + for key in yTest.ExceptionTests.keys(): + log.info(key) + sys.exit(0) + + ret = yTest.run() + if ret == 0: + log.info("All Test Passed") + sys.exit(ret) + + except Exception as e: + printExceptionDetails() + sys.exit(1) + + return +if __name__ == '__main__': + main() diff --git a/src/sonic-yang-models/tests/yang_model_tests/yangTest.json b/src/sonic-yang-models/tests/yang_model_tests/yangTest.json new file mode 100644 index 000000000000..523eedf3c4b1 --- /dev/null +++ b/src/sonic-yang-models/tests/yang_model_tests/yangTest.json @@ -0,0 +1,1284 @@ +{ + "WRONG_FAMILY_WITH_IP_PREFIX": { + "sonic-vlan:sonic-vlan": { + "sonic-vlan:VLAN_INTERFACE": { + "VLAN_INTERFACE_LIST": [{ + "vlan_name": "Vlan100" + }], + "VLAN_INTERFACE_IPPREFIX_LIST": [{ + "vlan_name": "Vlan100", + "ip-prefix": "2a04:5555:66:7777::1/64", + "scope": "global", + "family": "IPv4" + }] + }, + "sonic-vlan:VLAN": { + "VLAN_LIST": [{ + "vlan_name": "Vlan100", + "description": "server_vlan" + }] + } + } + }, + + "DHCP_SERVER_INCORRECT_FORMAT": { + "sonic-vlan:sonic-vlan": { + "sonic-vlan:VLAN": { + "VLAN_LIST": [{ + "vlan_name": "Vlan100", + "description": "server_vlan", + "dhcp_servers": [ + "10.186.72.566" + ], + "mtu": "9216", + "admin_status": "up" + }] + } + } + }, + + "VLAN_WITH_NON_EXIST_PORT": { + "sonic-vlan:sonic-vlan": { + "sonic-vlan:VLAN_MEMBER": { + "VLAN_MEMBER_LIST": [{ + "vlan_name": "Vlan100", + "port": "Ethernet156", + "tagging_mode": "tagged" + }] + }, + "sonic-vlan:VLAN": { + "VLAN_LIST": [{ + "vlan_name": "Vlan100", + "description": "server_vlan" + }] + } + }, + "sonic-port:sonic-port": { + "sonic-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" + } + ] + } + } + }, + + "VLAN_MEMEBER_WITH_NON_EXIST_VLAN": { + "sonic-vlan:sonic-vlan": { + "sonic-vlan:VLAN_MEMBER": { + "VLAN_MEMBER_LIST": [{ + "vlan_name": "Vlan200", + "port": "Ethernet0", + "tagging_mode": "tagged" + }] + }, + "sonic-vlan:VLAN": { + "VLAN_LIST": [{ + "vlan_name": "Vlan100", + "description": "server_vlan" + }, + { + "vlan_name": "Vlan300", + "description": "ipmi_vlan" + } + ] + } + }, + "sonic-port:sonic-port": { + "sonic-port:PORT": { + "PORT_LIST": [{ + "port_name": "Ethernet0", + "alias": "eth0", + "description": "Ethernet0", + "speed": 25000, + "mtu": 9000, + "admin_status": "up" + }] + } + } + }, + + "TAGGING_MODE_WRONG_VALUE": { + "sonic-vlan:sonic-vlan": { + "sonic-vlan:VLAN_MEMBER": { + "VLAN_MEMBER_LIST": [{ + "vlan_name": 100, + "port": "Ethernet0", + "tagging_mode": "non-tagged" + }] + }, + "sonic-vlan:VLAN": { + "VLAN_LIST": [{ + "vlan_name": "Vlan100", + "description": "server_vlan" + }] + } + }, + "sonic-port:sonic-port": { + "sonic-port:PORT": { + "PORT_LIST": [{ + "port_name": "Ethernet0", + "alias": "eth0", + "description": "Ethernet0", + "speed": 25000, + "mtu": 9000, + "admin_status": "up" + }] + } + } + }, + + "INTERFACE_IP_PREFIX_EMPTY_STRING": { + "sonic-interface:sonic-interface": { + "sonic-interface:INTERFACE": { + "INTERFACE_LIST": [{ + "port_name": "Ethernet8" + }], + "INTERFACE_IPPREFIX_LIST": [{ + "port_name": "Ethernet8", + "ip-prefix": "", + "scope": "global", + "family": "IPv4" + }] + } + }, + "sonic-port:sonic-port": { + "sonic-port:PORT": { + "PORT_LIST": [{ + "port_name": "Ethernet8", + "alias": "eth8", + "description": "Ethernet8", + "speed": 25000, + "mtu": 9000, + "admin_status": "up" + }] + } + } + }, + + "ACL_RULE_UNDEFINED_PACKET_ACTION": { + "sonic-acl:sonic-acl": { + "sonic-acl:ACL_RULE": { + "ACL_RULE_LIST": [{ + "ACL_TABLE_NAME": "NO-NSW-PACL-V4", + "RULE_NAME": "Rule_20", + "PACKET_ACTION": "SEND", + "DST_IP": "10.186.72.0/26", + "SRC_IP": "10.176.0.0/15", + "PRIORITY": 999980, + "IP_TYPE": "IPV4ANY" + }] + }, + "sonic-acl:ACL_TABLE": { + "ACL_TABLE_LIST": [{ + "ACL_TABLE_NAME": "NO-NSW-PACL-V4", + "policy_desc": "Filter IPv4", + "type": "L3", + "stage": "EGRESS", + "ports": ["Ethernet0", "Ethernet1"] + }] + } + }, + "sonic-port:sonic-port": { + "sonic-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" + } + ] + } + } + }, + + "ACL_TABLE_UNDEFINED_TABLE_TYPE": { + "sonic-acl:sonic-acl": { + "sonic-acl:ACL_TABLE": { + "ACL_TABLE_LIST": [{ + "ACL_TABLE_NAME": "NO-NSW-PACL-V6", + "policy_desc": "Filter IPv6", + "type": "LAYER3V4", + "stage": "EGRESS", + "ports": ["Ethernet0", "Ethernet1"] + }] + } + }, + "sonic-port:sonic-port": { + "sonic-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" + } + ] + } + } + }, + + "ACL_RULE_WITH_NON_EXIST_ACL_TABLE": { + "sonic-acl:sonic-acl": { + "sonic-acl:ACL_RULE": { + "ACL_RULE_LIST": [{ + "ACL_TABLE_NAME": "NOT-EXIST", + "RULE_NAME": "Rule_20", + "PACKET_ACTION": "FORWARD", + "DST_IP": "10.186.72.0/26", + "SRC_IP": "10.176.0.0/15", + "PRIORITY": 999980, + "IP_TYPE": "IPv4ANY" + }] + }, + "sonic-acl:ACL_TABLE": { + "ACL_TABLE_LIST": [{ + "ACL_TABLE_NAME": "NO-NSW-PACL-V4", + "policy_desc": "Filter IPv6", + "type": "L3", + "stage": "EGRESS", + "ports": ["Ethernet0", "Ethernet1"] + }] + } + }, + "sonic-port:sonic-port": { + "sonic-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" + } + ] + } + } + }, + + "ACL_RULE_IP_TYPE_SRC_IPV6_MISMATCH": { + "sonic-acl:sonic-acl": { + "sonic-acl:ACL_RULE": { + "ACL_RULE_LIST": [{ + "ACL_TABLE_NAME": "NO-NSW-PACL-V4", + "RULE_NAME": "Rule_20", + "PACKET_ACTION": "FORWARD", + "SRC_IPV6": "2001::1/64", + "PRIORITY": 999980, + "IP_TYPE": "IPv4ANY" + }] + }, + "sonic-acl:ACL_TABLE": { + "ACL_TABLE_LIST": [{ + "ACL_TABLE_NAME": "NO-NSW-PACL-V4", + "policy_desc": "Filter IPv4", + "type": "L3", + "stage": "EGRESS", + "ports": ["Ethernet0", "Ethernet1"] + }] + } + }, + "sonic-port:sonic-port": { + "sonic-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" + } + ] + } + } + }, + + "ACL_RULE_ARP_TYPE_DST_IPV6_MISMATCH": { + "sonic-acl:sonic-acl": { + "sonic-acl:ACL_RULE": { + "ACL_RULE_LIST": [{ + "ACL_TABLE_NAME": "NO-NSW-PACL-V6", + "RULE_NAME": "Rule_20", + "PACKET_ACTION": "FORWARD", + "DST_IPV6": "2001::2/64", + "PRIORITY": 999980, + "IP_TYPE": "ARP" + }] + }, + "sonic-acl:ACL_TABLE": { + "ACL_TABLE_LIST": [{ + "ACL_TABLE_NAME": "NO-NSW-PACL-V6", + "policy_desc": "Filter IPv6", + "type": "L3V6", + "stage": "EGRESS", + "ports": ["Ethernet0", "Ethernet1"] + }] + } + }, + "sonic-port:sonic-port": { + "sonic-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" + } + ] + } + } + }, + + "ACL_RULE_WRONG_L4_SRC_PORT_RANGE": { + "sonic-acl:sonic-acl": { + "sonic-acl:ACL_RULE": { + "ACL_RULE_LIST": [{ + "ACL_TABLE_NAME": "NO-NSW-PACL-V6", + "RULE_NAME": "Rule_20", + "PACKET_ACTION": "FORWARD", + "IP_TYPE": "IP", + "SRC_IPV6": "2a04:f547:41::/48", + "PRIORITY": 999980, + "DST_IPV6": "2a04:f547:43:320::/64", + "L4_SRC_PORT_RANGE": "99999-99999" + }] + }, + "sonic-acl:ACL_TABLE": { + "ACL_TABLE_LIST": [{ + "ACL_TABLE_NAME": "NO-NSW-PACL-V6", + "policy_desc": "Filter IPv6", + "type": "L3V6", + "stage": "EGRESS", + "ports": ["Ethernet0", "Ethernet1"] + }] + } + }, + "sonic-port:sonic-port": { + "sonic-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" + } + ] + } + } + }, + + "VLAN_INTERFACE_IPPREFIX_MUST_CONDITION_FALSE": { + "sonic-vlan:sonic-vlan": { + "sonic-vlan:VLAN_INTERFACE": { + "VLAN_INTERFACE_IPPREFIX_LIST": [{ + "vlan_name": "Vlan100", + "ip-prefix": "2a04:5555:66:7777::1/64", + "scope": "global", + "family": "IPv6" + }] + }, + "sonic-vlan:VLAN": { + "VLAN_LIST": [{ + "vlan_name": "Vlan100", + "description": "server_vlan" + }] + } + } + }, + + "LOOPBACK_IPPREFIX_PORT_MUST_CONDITION_FALSE": { + "sonic-loopback-interface:sonic-loopback-interface": { + "sonic-loopback-interface:LOOPBACK_INTERFACE": { + "LOOPBACK_INTERFACE_IPPREFIX_LIST": [{ + "loopback_interface_name": "lo1", + "ip-prefix": "2a04:5555:66:7777::1/64", + "scope": "global", + "family": "IPv6" + }] + } + } + }, + + "INTERFACE_IPPREFIX_PORT_MUST_CONDITION_FALSE": { + "sonic-interface:sonic-interface": { + "sonic-interface:INTERFACE": { + "INTERFACE_LIST": [{ + "port_name": "Ethernet9" + }], + "INTERFACE_IPPREFIX_LIST": [{ + "port_name": "Ethernet8", + "ip-prefix": "10.0.0.1/30", + "scope": "global", + "family": "IPv4" + }] + } + }, + "sonic-port:sonic-port": { + "sonic-port:PORT": { + "PORT_LIST": [{ + "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" + }] + } + } + }, + + "INTERFACE_IPPREFIX_PORT_MUST_CONDITION_TRUE": { + "sonic-interface:sonic-interface": { + "sonic-interface:INTERFACE": { + "INTERFACE_LIST": [{ + "port_name": "Ethernet8" + }], + "INTERFACE_IPPREFIX_LIST": [{ + "port_name": "Ethernet8", + "ip-prefix": "10.0.0.1/30", + "scope": "global", + "family": "IPv4" + }] + } + }, + "sonic-port:sonic-port": { + "sonic-port:PORT": { + "PORT_LIST": [{ + "port_name": "Ethernet8", + "alias": "eth8", + "description": "Ethernet8", + "speed": 25000, + "mtu": 9000, + "admin_status": "up" + }] + } + } + }, + + "ACL_RULE_ARP_TYPE_ICMPV6_CODE_MISMATCH": { + "sonic-acl:sonic-acl": { + "sonic-acl:ACL_RULE": { + "ACL_RULE_LIST": [{ + "ACL_TABLE_NAME": "NO-NSW-PACL-V4", + "RULE_NAME": "Rule_40", + "PACKET_ACTION": "FORWARD", + "DST_IP": "10.186.72.64/26", + "SRC_IP": "10.176.0.0/15", + "PRIORITY": 999960, + "ICMPV6_CODE": 5, + "IP_TYPE": "ARP", + "INNER_ETHER_TYPE": "0x88CC" + }] + }, + "sonic-acl:ACL_TABLE": { + "ACL_TABLE_LIST": [{ + "ACL_TABLE_NAME": "NO-NSW-PACL-V4", + "policy_desc": "Filter IPv4", + "type": "L3", + "stage": "EGRESS", + "ports": ["Ethernet0", "Ethernet1"] + }] + } + }, + "sonic-port:sonic-port": { + "sonic-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" + } + ] + } + } + }, + + "ACL_RULE_WRONG_INNER_ETHER_TYPE": { + "sonic-acl:sonic-acl": { + "sonic-acl:ACL_RULE": { + "ACL_RULE_LIST": [{ + "ACL_TABLE_NAME": "NO-NSW-PACL-V4", + "RULE_NAME": "Rule_40", + "PACKET_ACTION": "FORWARD", + "DST_IP": "10.186.72.64/26", + "SRC_IP": "10.176.0.0/15", + "PRIORITY": 999960, + "IP_TYPE": "ARP", + "INNER_ETHER_TYPE": "0x080C" + + }] + }, + "sonic-acl:ACL_TABLE": { + "ACL_TABLE_LIST": [{ + "ACL_TABLE_NAME": "NO-NSW-PACL-V4", + "policy_desc": "Filter IPv4", + "type": "L3", + "stage": "EGRESS", + "ports": ["Ethernet0", "Ethernet1"] + }] + } + }, + "sonic-port:sonic-port": { + "sonic-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" + } + ] + } + } + }, + + "SAMPLE_CONFIG_DB_JSON": { + "VLAN_INTERFACE": { + "Vlan111": {}, + "Vlan777": {}, + "Vlan111|2a04:5555:45:6709::1/64": { + "scope": "global", + "family": "IPv6" + }, + "Vlan111|10.222.10.65/26": { + "scope": "global", + "family": "IPv4" + }, + "Vlan111|fe80::1/10": { + "scope": "local", + "family": "IPv6" + }, + "Vlan777|2a04:5555:41:4e9::1/64": { + "scope": "global", + "family": "IPv6" + }, + "Vlan777|10.111.58.65/26": { + "scope": "global", + "family": "IPv4" + }, + "Vlan777|fe80::1/10": { + "scope": "local", + "family": "IPv6" + } + }, + "ACL_RULE": { + "V4-ACL-TABLE|DEFAULT_DENY": { + "PACKET_ACTION": "DROP", + "IP_TYPE": "IPv4ANY", + "PRIORITY": "0" + }, + "V4-ACL-TABLE|Rule_20": { + "PACKET_ACTION": "FORWARD", + "DST_IP": "10.222.72.0/26", + "SRC_IP": "10.222.0.0/15", + "PRIORITY": "777780", + "IP_TYPE": "IPv4ANY" + }, + "V4-ACL-TABLE|Rule_40": { + "PACKET_ACTION": "FORWARD", + "DST_IP": "10.222.72.64/26", + "SRC_IP": "10.222.0.0/15", + "PRIORITY": "777760", + "IP_TYPE": "IPv4ANY" + }, + "V4-ACL-TABLE|Rule_60": { + "PACKET_ACTION": "FORWARD", + "DST_IP": "10.222.80.0/26", + "SRC_IP": "10.222.0.0/15", + "PRIORITY": "777740", + "IP_TYPE": "IPv4ANY" + }, + "V4-ACL-TABLE|Rule_80": { + "PACKET_ACTION": "FORWARD", + "DST_IP": "10.222.80.64/26", + "SRC_IP": "10.222.0.0/15", + "PRIORITY": "777720", + "IP_TYPE": "IPv4ANY" + }, + "V4-ACL-TABLE|Rule_111": { + "PACKET_ACTION": "FORWARD", + "DST_IP": "10.152.17.52/32", + "SRC_IP": "10.222.0.0/15", + "PRIORITY": "777700", + "IP_TYPE": "IPv4ANY" + }, + "V4-ACL-TABLE|Rule_120": { + "PACKET_ACTION": "FORWARD", + "DST_IP": "10.252.208.41/32", + "SRC_IP": "10.222.0.0/15", + "PRIORITY": "777880", + "IP_TYPE": "IPv4ANY" + }, + "V4-ACL-TABLE|Rule_140": { + "PACKET_ACTION": "FORWARD", + "DST_IP": "10.148.128.245/32", + "SRC_IP": "10.222.0.0/15", + "PRIORITY": "777860", + "IP_TYPE": "IPv4ANY" + }, + "V4-ACL-TABLE|Rule_160": { + "PACKET_ACTION": "FORWARD", + "DST_IP": "10.222.1.245/32", + "SRC_IP": "10.222.0.0/15", + "PRIORITY": "777840", + "IP_TYPE": "IPv4ANY" + }, + "V4-ACL-TABLE|Rule_180": { + "PACKET_ACTION": "FORWARD", + "DST_IP": "10.252.222.21/32", + "SRC_IP": "10.222.0.0/15", + "PRIORITY": "777820", + "IP_TYPE": "IPv4ANY" + }, + "V4-ACL-TABLE|Rule_9000": { + "PACKET_ACTION": "DROP", + "DST_IP": "0.0.0.0/0", + "SRC_IP": "10.222.0.0/15", + "PRIORITY": "991110", + "IP_TYPE": "IPv4ANY" + }, + "V4-ACL-TABLE|Rule_11100": { + "PACKET_ACTION": "FORWARD", + "DST_IP": "0.0.0.0/0", + "SRC_IP": "0.0.0.0/0", + "PRIORITY": "990000", + "IP_TYPE": "IPv4ANY" + }, + "V6-ACL-TBLE|DEFAULT_DENY": { + "PACKET_ACTION": "DROP", + "IP_TYPE": "IPv6ANY", + "PRIORITY": "0" + }, + "V6-ACL-TBLE|Rule_20": { + "PACKET_ACTION": "FORWARD", + "IP_TYPE": "IPv6ANY", + "SRC_IPV6": "2a04:5555:41::/48", + "PRIORITY": "777780", + "DST_IPV6": "2a04:5555:43:320::/64" + }, + "V6-ACL-TBLE|Rule_40": { + "PACKET_ACTION": "FORWARD", + "IP_TYPE": "IPv6ANY", + "SRC_IPV6": "2a04:5555:41::/48", + "PRIORITY": "777760", + "DST_IPV6": "2a04:5555:43:321::/64" + }, + "V6-ACL-TBLE|Rule_60": { + "PACKET_ACTION": "FORWARD", + "IP_TYPE": "IPv6ANY", + "SRC_IPV6": "2a04:5555:41::/48", + "PRIORITY": "777740", + "DST_IPV6": "2a04:5555:43:340::/64" + }, + "V6-ACL-TBLE|Rule_80": { + "PACKET_ACTION": "FORWARD", + "IP_TYPE": "IPv6ANY", + "SRC_IPV6": "2a04:5555:41::/48", + "PRIORITY": "777720", + "DST_IPV6": "2a04:5555:43:341::/64" + }, + "V6-ACL-TBLE|Rule_111": { + "PACKET_ACTION": "FORWARD", + "IP_TYPE": "IPv6ANY", + "SRC_IPV6": "2a04:5555:41::/48", + "PRIORITY": "777700", + "DST_IPV6": "2a04:5555:32:12::/64" + }, + "V6-ACL-TBLE|Rule_9000": { + "PACKET_ACTION": "DROP", + "IP_TYPE": "IPv6ANY", + "SRC_IPV6": "2a04:5555:41::/48", + "PRIORITY": "991110", + "DST_IPV6": "::/0" + }, + "V6-ACL-TBLE|Rule_11100": { + "PACKET_ACTION": "FORWARD", + "IP_TYPE": "IPv6ANY", + "SRC_IPV6": "::/0", + "PRIORITY": "990000", + "DST_IPV6": "::/0" + } + }, + "DEVICE_METADATA": { + "localhost": { + "type": "ToR", + "mac": "00:11:22:33:dd:5a", + "hostname": "asw.dc", + "bgp_asn": "64850", + "hwsku": "Stone" + } + }, + "VLAN": { + "Vlan111": { + "description": "svlan", + "dhcp_servers": [ + "10.222.72.116" + ], + "vlanid": "111", + "mtu": "9216", + "admin_status": "up", + "members": [ + "Ethernet8", + "Ethernet3", + "Ethernet0", + "Ethernet1", + "Ethernet6", + "Ethernet4", + "Ethernet5", + "Ethernet9", + "Ethernet2", + "Ethernet7", + "Ethernet32", + "Ethernet30", + "Ethernet31", + "Ethernet36", + "Ethernet34", + "Ethernet33", + "Ethernet35", + "Ethernet29", + "Ethernet21", + "Ethernet20", + "Ethernet23", + "Ethernet22", + "Ethernet27", + "Ethernet26", + "Ethernet18", + "Ethernet19", + "Ethernet14", + "Ethernet15", + "Ethernet16", + "Ethernet17", + "Ethernet10", + "Ethernet11", + "Ethernet12", + "Ethernet13", + "Ethernet28" + ] + }, + "Vlan777": { + "description": "pvlan", + "dhcp_servers": [ + "10.222.72.116" + ], + "vlanid": "777", + "mtu": "9216", + "admin_status": "up", + "members": [ + "Ethernet9", + "Ethernet2", + "Ethernet8", + "Ethernet27", + "Ethernet14", + "Ethernet35" + ] + } + }, + "DEVICE_NEIGHBOR": { + "Ethernet112": { + "name": "dccsw01.nw", + "port": "Eth18" + }, + "Ethernet114": { + "name": "dccsw02.nw", + "port": "Eth18" + }, + "Ethernet116": { + "name": "dccsw03.nw", + "port": "Eth18" + }, + "Ethernet118": { + "name": "dccsw04.nw", + "port": "Eth18" + } + }, + "PORT": { + "Ethernet0": { + "alias": "Eth1/1", + "lanes": "65", + "description": "", + "speed": "11100", + "admin_status": "up" + }, + "Ethernet1": { + "alias": "Eth1/2", + "lanes": "66", + "description": "", + "speed": "11100", + "admin_status": "up" + }, + "Ethernet2": { + "alias": "Eth1/3", + "lanes": "67", + "description": "", + "speed": "11100", + "admin_status": "up" + }, + "Ethernet3": { + "alias": "Eth1/4", + "lanes": "68", + "description": "", + "speed": "11100", + "admin_status": "up" + }, + "Ethernet4": { + "alias": "Eth2/1", + "lanes": "69", + "description": "", + "speed": "11100", + "admin_status": "up" + }, + "Ethernet5": { + "alias": "Eth2/2", + "lanes": "70", + "description": "", + "speed": "11100", + "admin_status": "up" + }, + "Ethernet6": { + "alias": "Eth2/3", + "lanes": "71", + "description": "", + "speed": "11100", + "admin_status": "up" + }, + "Ethernet7": { + "alias": "Eth2/4", + "lanes": "72", + "description": "", + "speed": "11100", + "admin_status": "up" + }, + "Ethernet8": { + "alias": "Eth3/1", + "lanes": "73", + "description": "", + "speed": "11100", + "admin_status": "up" + }, + "Ethernet9": { + "alias": "Eth3/2", + "lanes": "74", + "description": "", + "speed": "11100", + "admin_status": "up" + }, + "Ethernet10": { + "alias": "Eth3/3", + "lanes": "75", + "description": "", + "speed": "11100", + "admin_status": "up" + }, + "Ethernet11": { + "alias": "Eth3/4", + "lanes": "76", + "description": "", + "speed": "11100", + "admin_status": "up" + }, + "Ethernet12": { + "alias": "Eth4/1", + "lanes": "77", + "description": "", + "speed": "11100", + "admin_status": "up" + }, + "Ethernet13": { + "alias": "Eth4/2", + "lanes": "78", + "description": "", + "speed": "11100", + "admin_status": "up" + }, + "Ethernet14": { + "alias": "Eth4/3", + "lanes": "79", + "description": "", + "speed": "11100", + "admin_status": "up" + }, + "Ethernet15": { + "alias": "Eth4/4", + "lanes": "80", + "description": "", + "speed": "11100", + "admin_status": "up" + }, + "Ethernet16": { + "alias": "Eth5/1", + "lanes": "33", + "description": "", + "speed": "11100", + "admin_status": "up" + }, + "Ethernet17": { + "alias": "Eth5/2", + "lanes": "34", + "description": "", + "speed": "11100", + "admin_status": "up" + }, + "Ethernet18": { + "alias": "Eth5/3", + "lanes": "35", + "description": "", + "speed": "11100", + "admin_status": "up" + }, + "Ethernet19": { + "alias": "Eth5/4", + "lanes": "36", + "description": "", + "speed": "11100", + "admin_status": "up" + }, + "Ethernet20": { + "alias": "Eth6/1", + "lanes": "37", + "description": "", + "speed": "11100", + "admin_status": "up" + }, + "Ethernet21": { + "alias": "Eth6/2", + "lanes": "38", + "description": "", + "speed": "11100", + "admin_status": "up" + }, + "Ethernet22": { + "alias": "Eth6/3", + "lanes": "39", + "description": "", + "speed": "11100", + "admin_status": "up" + }, + "Ethernet23": { + "alias": "Eth6/4", + "lanes": "40", + "description": "", + "speed": "11100", + "admin_status": "up" + }, + "Ethernet24": { + "alias": "Eth7/1", + "lanes": "41", + "description": "", + "speed": "11100", + "admin_status": "up" + }, + "Ethernet25": { + "alias": "Eth7/2", + "lanes": "42", + "description": "", + "speed": "11100", + "admin_status": "up" + }, + "Ethernet26": { + "alias": "Eth7/3", + "lanes": "43", + "description": "", + "speed": "11100", + "admin_status": "up" + }, + "Ethernet27": { + "alias": "Eth7/4", + "lanes": "44", + "description": "", + "speed": "11100", + "admin_status": "up" + }, + "Ethernet28": { + "alias": "Eth8/1", + "lanes": "45", + "description": "", + "speed": "11100", + "admin_status": "up" + }, + "Ethernet29": { + "alias": "Eth8/2", + "lanes": "46", + "description": "", + "speed": "11100", + "admin_status": "up" + }, + "Ethernet30": { + "alias": "Eth8/3", + "lanes": "47", + "description": "", + "speed": "11100", + "admin_status": "up" + }, + "Ethernet31": { + "alias": "Eth8/4", + "lanes": "48", + "description": "", + "speed": "11100", + "admin_status": "up" + }, + "Ethernet32": { + "alias": "Eth9/1", + "lanes": "49", + "description": "", + "speed": "11100", + "admin_status": "up" + }, + "Ethernet33": { + "alias": "Eth9/2", + "lanes": "50", + "description": "", + "speed": "11100", + "admin_status": "up" + }, + "Ethernet34": { + "alias": "Eth9/3", + "lanes": "51", + "description": "", + "speed": "11100", + "admin_status": "up" + }, + "Ethernet35": { + "alias": "Eth9/4", + "lanes": "52", + "description": "", + "speed": "11100", + "admin_status": "up" + }, + "Ethernet36": { + "alias": "Eth10/1", + "lanes": "53", + "description": "", + "speed": "11100", + "admin_status": "up" + }, + "Ethernet112": { + "alias": "Eth29/1", + "lanes": "113,114", + "description": "50G|dccsw01.nw|Eth18", + "fec": "fc", + "speed": "11100", + "admin_status": "up" + } + }, + "ACL_TABLE": { + "V4-ACL-TABLE": { + "type": "L3", + "policy_desc": "V4-ACL-TABLE", + "ports": [ + "Ethernet26", + "Ethernet27", + "Ethernet24" + ] + }, + "V6-ACL-TBLE": { + "type": "L3V6", + "policy_desc": "V6-ACL-TBLE", + "ports": [ + "Ethernet14", + "Ethernet15", + "Ethernet23", + "Ethernet30", + "Ethernet31", + "Ethernet18", + "Ethernet19", + "Ethernet25", + "Ethernet24" + ] + } + }, + "INTERFACE": { + "Ethernet112": {}, + "Ethernet14": {}, + "Ethernet16": {}, + "Ethernet18": {}, + "Ethernet112|2a04:5555:40:a709::2/126": { + "scope": "global", + "family": "IPv6" + }, + "Ethernet112|10.184.228.211/31": { + "scope": "global", + "family": "IPv4" + }, + "Ethernet14|2a04:5555:40:a749::2/126": { + "scope": "global", + "family": "IPv6" + }, + "Ethernet14|10.184.229.211/31": { + "scope": "global", + "family": "IPv4" + }, + "Ethernet16|2a04:5555:40:a789::2/126": { + "scope": "global", + "family": "IPv6" + }, + "Ethernet16|10.184.230.211/31": { + "scope": "global", + "family": "IPv4" + }, + "Ethernet18|2a04:5555:40:a7c9::2/126": { + "scope": "global", + "family": "IPv6" + }, + "Ethernet18|10.184.231.211/31": { + "scope": "global", + "family": "IPv4" + } + }, + "VLAN_MEMBER": { + "Vlan111|Ethernet0": { + "tagging_mode": "untagged" + }, + "Vlan111|Ethernet1": { + "tagging_mode": "untagged" + }, + "Vlan111|Ethernet2": { + "tagging_mode": "untagged" + }, + "Vlan111|Ethernet3": { + "tagging_mode": "untagged" + }, + "Vlan111|Ethernet4": { + "tagging_mode": "untagged" + }, + "Vlan111|Ethernet5": { + "tagging_mode": "untagged" + }, + "Vlan111|Ethernet6": { + "tagging_mode": "untagged" + }, + "Vlan111|Ethernet29": { + "tagging_mode": "untagged" + }, + "Vlan111|Ethernet30": { + "tagging_mode": "untagged" + }, + "Vlan111|Ethernet31": { + "tagging_mode": "untagged" + }, + "Vlan111|Ethernet32": { + "tagging_mode": "untagged" + }, + "Vlan111|Ethernet33": { + "tagging_mode": "untagged" + }, + "Vlan111|Ethernet34": { + "tagging_mode": "untagged" + }, + "Vlan111|Ethernet35": { + "tagging_mode": "untagged" + }, + "Vlan111|Ethernet36": { + "tagging_mode": "untagged" + } + }, + "LOOPBACK_INTERFACE": { + "Loopback0": {}, + "Loopback0|2a04:5555:40:4::4e9/128": { + "scope": "global", + "family": "IPv6" + }, + "Loopback0|10.184.8.233/32": { + "scope": "global", + "family": "IPv4" + } + }, + "CRM": { + "Config": { + "polling_interval": "0" + } + } + } +} diff --git a/src/sonic-yang-models/yang-models/sonic-acl.yang b/src/sonic-yang-models/yang-models/sonic-acl.yang new file mode 100644 index 000000000000..ec8a485b4829 --- /dev/null +++ b/src/sonic-yang-models/yang-models/sonic-acl.yang @@ -0,0 +1,283 @@ +module sonic-acl { + + yang-version 1.1; + + namespace "http://github.com/Azure/sonic-acl"; + prefix acl; + + import ietf-yang-types { + prefix yang; + } + + import ietf-inet-types { + prefix inet; + } + + import sonic-types { + prefix stypes; + revision-date 2019-07-01; + } + + import sonic-extension { + prefix ext; + revision-date 2019-07-01; + } + + import sonic-port { + prefix port; + revision-date 2019-07-01; + } + + import sonic-portchannel { + prefix lag; + revision-date 2019-07-01; + } + + description "ACL YANG Module for SONiC OS"; + + revision 2019-07-01 { + description "First Revision"; + } + + container sonic-acl { + + container ACL_RULE { + + description "ACL_RULE part of config_db.json"; + + list ACL_RULE_LIST { + + key "ACL_TABLE_NAME RULE_NAME"; + + ext:key-regex-configdb-to-yang "^([a-zA-Z0-9_-]+)|([a-zA-Z0-9_-]+)$"; + + ext:key-regex-yang-to-configdb "|"; + + leaf ACL_TABLE_NAME { + type leafref { + path "/acl:sonic-acl/acl:ACL_TABLE/acl:ACL_TABLE_LIST/acl:ACL_TABLE_NAME"; + } + } + + leaf RULE_NAME { + type string { + length 1..255; + } + } + + leaf PACKET_ACTION { + type stypes:packet_action; + } + + leaf IP_TYPE { + type stypes:ip_type; + } + + leaf PRIORITY { + type uint32 { + range 0..999999; + } + } + + choice ip_prefix { + + case ip4_prefix { + when "boolean(IP_TYPE[.='ANY' or .='IP' or .='IPV4' or .='IPv4ANY' or .='ARP'])"; + leaf SRC_IP { + type inet:ipv4-prefix; + } + + leaf DST_IP { + type inet:ipv4-prefix; + } + } + + case ip6_prefix { + when "boolean(IP_TYPE[.='ANY' or .='IP' or .='IPV6' or .='IPv6ANY'])"; + leaf SRC_IPV6 { + type inet:ipv6-prefix; + } + + leaf DST_IPV6 { + type inet:ipv6-prefix; + } + } + } + + leaf-list IN_PORTS { + /* Values in leaf list are UNIQUE */ + type uint16; + } + + leaf-list OUT_PORTS { + /* Values in leaf list are UNIQUE */ + 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,4}|[0-5][0-9]{4}|[6][0-4][0-9]{3}|[6][5][0-2][0-9]{2}|[6][5][3][0-5]{2}|[6][5][3][6][0-5])-([0-9]{1,4}|[0-5][0-9]{4}|[6][0-4][0-9]{3}|[6][5][0-2][0-9]{2}|[6][5][3][0-5]{2}|[6][5][3][6][0-5])'; + } + } + } + } + + 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,4}|[0-5][0-9]{4}|[6][0-4][0-9]{3}|[6][5][0-2][0-9]{2}|[6][5][3][0-5]{2}|[6][5][3][6][0-5])-([0-9]{1,4}|[0-5][0-9]{4}|[6][0-4][0-9]{3}|[6][5][0-2][0-9]{2}|[6][5][3][0-5]{2}|[6][5][3][6][0-5])'; + } + } + } + } + + leaf ETHER_TYPE { + type string { + pattern "(0x88CC|0x8100|0x8915|0x0806|0x0800|0x86DD|0x8847)"; + } + } + + leaf IP_PROTOCOL { + type uint8 { + range 1..143; + } + } + + leaf TCP_FLAGS { + type string { + pattern '0[x][0-9a-fA-F]{1,2}|0[X][0-9a-fA-F]{1,2}'; + } + } + + leaf DSCP { + type uint8; + } + + leaf TC { + type uint8; + } + + choice icmp { + + case icmp4 { + when "boolean(IP_TYPE[.='ANY' or .='IP' or .='IPV4' or .='IPv4ANY' or .='ARP'])"; + leaf ICMP_TYPE { + type uint8 { + range 1..44; + } + } + + leaf ICMP_CODE { + type uint8 { + range 1..16; + } + } + } + + case icmp6 { + when "boolean(IP_TYPE[.='ANY' or .='IP' or .='IPV6' or .='IPv6ANY'])"; + leaf ICMPV6_TYPE { + type uint8 { + range 1..44; + } + } + + leaf ICMPV6_CODE { + type uint8 { + range 1..16; + } + } + } + } + + leaf INNER_ETHER_TYPE { + type string { + pattern "(0x88CC|0x8100|0x8915|0x0806|0x0800|0x86DD|0x8847)"; + } + } + + leaf INNER_IP_PROTOCOL { + type uint8 { + range 1..143; + } + } + + leaf INNER_L4_SRC_PORT { + type uint16; + } + + leaf INNER_L4_DST_PORT { + type uint16; + } + } + /* end of ACL_RULE_LIST */ + } + /* end of container ACL_RULE */ + + container ACL_TABLE { + + description "ACL_TABLE part of config_db.json"; + + list ACL_TABLE_LIST { + + key "ACL_TABLE_NAME"; + + ext:key-regex-configdb-to-yang "^([a-zA-Z0-9-_]+)$"; + + ext:key-regex-yang-to-configdb ""; + + leaf ACL_TABLE_NAME { + type string; + } + + leaf policy_desc { + type string { + length 1..255; + } + } + + leaf type { + type stypes:acl_table_type; + } + + leaf stage { + type enumeration { + enum INGRESS; + enum EGRESS; + } + } + + leaf-list ports { + /* union of leafref is allowed in YANG 1.1 */ + type union { + type leafref { + path /port:sonic-port/port:PORT/port:PORT_LIST/port:port_name; + } + type leafref { + path /lag:sonic-portchannel/lag:PORTCHANNEL/lag:PORTCHANNEL_LIST/lag:portchannel_name; + } + } + } + } + /* end of ACL_TABLE_LIST */ + } + /* end of container ACL_TABLE */ + } + /* end of container sonic-acl */ +} +/* end of module sonic-acl */ diff --git a/src/sonic-yang-models/yang-models/sonic-extension.yang b/src/sonic-yang-models/yang-models/sonic-extension.yang new file mode 100644 index 000000000000..5632e893d9ca --- /dev/null +++ b/src/sonic-yang-models/yang-models/sonic-extension.yang @@ -0,0 +1,23 @@ +module sonic-extension { + + yang-version 1.1; + + namespace "http://github.com/Azure/sonic-extension"; + prefix sonic-extension; + + description "Extension yang Module for SONiC OS"; + + revision 2019-07-01 { + description "First Revision"; + } + + extension key-regex-configdb-to-yang { + description "Key regex used to convert config DB keys to YANG Config"; + argument "value"; + } + + extension key-regex-yang-to-configdb { + description "Key regex used to convert config DB keys to YANG Config"; + argument "value"; + } +} diff --git a/src/sonic-yang-models/yang-models/sonic-interface.yang b/src/sonic-yang-models/yang-models/sonic-interface.yang new file mode 100644 index 000000000000..d47268be69f9 --- /dev/null +++ b/src/sonic-yang-models/yang-models/sonic-interface.yang @@ -0,0 +1,122 @@ +module sonic-interface { + + yang-version 1.1; + + namespace "http://github.com/Azure/sonic-interface"; + prefix intf; + + import ietf-yang-types { + prefix yang; + } + + import ietf-inet-types { + prefix inet; + } + + import sonic-types { + prefix stypes; + revision-date 2019-07-01; + } + + import sonic-extension { + prefix ext; + revision-date 2019-07-01; + } + + import sonic-port { + prefix port; + revision-date 2019-07-01; + } + + description "INTERFACE yang Module for SONiC OS"; + + revision 2019-07-01 { + description "First Revision"; + } + + container sonic-interface { + + container INTERFACE { + + description "INTERFACE part of config_db.json"; + + list INTERFACE_LIST { + + description "INTERFACE part of config_db.json with vrf"; + + key "port_name"; + + ext:key-regex-configdb-to-yang "^(Ethernet[0-9]+)$"; + + ext:key-regex-yang-to-configdb ""; + + leaf port_name { + type leafref { + path /port:sonic-port/port:PORT/port:PORT_LIST/port:port_name; + } + } + + leaf vrf_name { + type string { + pattern "Vrf[a-zA-Z0-9_-]+"; + length 3..255; + } + } + } + /* end of INTERFACE_LIST */ + + list INTERFACE_IPPREFIX_LIST { + + description "INTERFACE part of config_db.json with ip-prefix"; + + key "port_name ip-prefix"; + + ext:key-regex-configdb-to-yang "^(Ethernet[0-9]+)|([a-fA-F0-9:./]+)$"; + + ext:key-regex-yang-to-configdb "|"; + + leaf port_name { + /* This node must be present in INTERFACE_LIST */ + must "(current() = ../../INTERFACE_LIST[port_name=current()]/port_name)" + { + error-message "Must condition not satisfied, Try adding PORT: {}, Example: 'Ethernet0': {}"; + } + + type leafref { + path /port:sonic-port/port:PORT/port:PORT_LIST/port:port_name; + } + } + + leaf ip-prefix { + type union { + type stypes:sonic-ip4-prefix; + type stypes:sonic-ip6-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 stypes:ip-family; + } + } + /* end of INTERFACE_IPPREFIX_LIST */ + + } + /* end of INTERFACE container */ + } +} diff --git a/src/sonic-yang-models/yang-models/sonic-loopback-interface.yang b/src/sonic-yang-models/yang-models/sonic-loopback-interface.yang new file mode 100644 index 000000000000..92b059af64ca --- /dev/null +++ b/src/sonic-yang-models/yang-models/sonic-loopback-interface.yang @@ -0,0 +1,98 @@ +module sonic-loopback-interface { + + namespace "http://github.com/Azure/sonic-loopback-interface"; + prefix lointf; + + import ietf-inet-types { + prefix inet; + } + + import sonic-types { + prefix stypes; + revision-date 2019-07-01; + } + + import sonic-extension { + prefix ext; + revision-date 2019-07-01; + } + + description + "SONIC LOOPBACK INTERFACE"; + + revision 2020-02-05 { + description "First Revision"; + } + + container sonic-loopback-interface { + + container LOOPBACK_INTERFACE { + + list LOOPBACK_INTERFACE_LIST { + key "loopback_interface_name"; + + ext:key-regex-configdb-to-yang "^([a-zA-Z0-9-_]+)$"; + + ext:key-regex-yang-to-configdb ""; + + leaf loopback_interface_name{ + type string; + } + + leaf vrf_name { + type string { + pattern "Vrf[a-zA-Z0-9_-]+"; + length 3..255; + } + } + } + /* end of LOOPBACK_INTERFACE_LIST */ + + list LOOPBACK_INTERFACE_IPPREFIX_LIST { + + key "loopback_interface_name ip-prefix"; + + ext:key-regex-configdb-to-yang "^([a-zA-Z0-9-_]+)|([a-fA-F0-9:./]+$)"; + + ext:key-regex-yang-to-configdb "|"; + + leaf loopback_interface_name{ + /* This node must be present in LOOPBACK_INTERFACE_LIST */ + must "(current() = ../../LOOPBACK_INTERFACE_LIST[loopback_interface_name=current()]/loopback_interface_name)" + { + error-message "Must condition not satisfied, Try adding lo<>: {}, Example: 'lo1': {}"; + } + type string; + } + + leaf ip-prefix { + type union { + type stypes:sonic-ip4-prefix; + type stypes:sonic-ip6-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 stypes:ip-family; + } + } + } + /* end of LOOPBACK_INTERFACE_IPPREFIX_LIST */ + } +} diff --git a/src/sonic-yang-models/yang-models/sonic-port.yang b/src/sonic-yang-models/yang-models/sonic-port.yang new file mode 100644 index 000000000000..88fcf72dadbc --- /dev/null +++ b/src/sonic-yang-models/yang-models/sonic-port.yang @@ -0,0 +1,105 @@ +module sonic-port{ + + yang-version 1.1; + + namespace "http://github.com/Azure/sonic-port"; + prefix port; + + import ietf-yang-types { + prefix yang; + } + + import ietf-inet-types { + prefix inet; + } + + import sonic-types { + prefix stypes; + revision-date 2019-07-01; + } + + import sonic-extension { + prefix ext; + revision-date 2019-07-01; + } + + description "PORT yang Module for SONiC OS"; + + revision 2019-07-01 { + description "First Revision"; + } + + container sonic-port{ + + container PORT { + + description "PORT part of config_db.json"; + + list PORT_LIST { + + key "port_name"; + + ext:key-regex-configdb-to-yang "^(Ethernet[0-9]+)$"; + + ext:key-regex-yang-to-configdb ""; + + leaf port_name { + type string { + length 1..128; + } + } + + leaf alias { + type string { + length 1..128; + } + } + + leaf lanes { + mandatory true; + type string { + length 1..128; + } + } + + leaf description { + type string { + length 0..255; + } + } + + leaf speed { + mandatory true; + type uint32 { + range 1..100000; + } + } + + leaf mtu { + type uint16 { + range 1..9216; + } + } + + leaf index { + type uint16 { + range 0..256; + } + } + + leaf admin_status { + type stypes:admin_status; + } + + leaf fec { + type string { + pattern "rc|fc|None"; + } + } + } /* end of list PORT_LIST */ + + } /* end of container PORT */ + + } /* end of container sonic-port */ + +} /* end of module sonic-port */ diff --git a/src/sonic-yang-models/yang-models/sonic-portchannel.yang b/src/sonic-yang-models/yang-models/sonic-portchannel.yang new file mode 100644 index 000000000000..8f758fd51c81 --- /dev/null +++ b/src/sonic-yang-models/yang-models/sonic-portchannel.yang @@ -0,0 +1,92 @@ +module sonic-portchannel { + + yang-version 1.1; + + namespace "http://github.com/Azure/sonic-portchannel"; + prefix lag; + + import ietf-yang-types { + prefix yang; + } + + import ietf-inet-types { + prefix inet; + } + + import sonic-types { + prefix stypes; + revision-date 2019-07-01; + } + + import sonic-extension { + prefix ext; + revision-date 2019-07-01; + } + + import sonic-port { + prefix port; + revision-date 2019-07-01; + } + + description "PORTCHANNEL yang Module for SONiC OS"; + + revision 2019-07-01 { + description "First Revision"; + } + + container sonic-portchannel { + container PORTCHANNEL { + + description "PORTCHANNEL part of config_db.json"; + + list PORTCHANNEL_LIST { + + key "portchannel_name"; + + ext:key-regex-configdb-to-yang "^(Ethernet[0-9]+)$"; + + ext:key-regex-yang-to-configdb ""; + + leaf portchannel_name { + type string { + length 1..128; + pattern 'PortChannel[0-9]{1,4}'; + } + } + + leaf-list members { + /* leaf-list members are unique by default */ + type leafref { + path /port:sonic-port/port:PORT/port:PORT_LIST/port:port_name; + } + } + + leaf min_links { + type uint8 { + range 1..128; + } + } + + leaf description { + type string { + length 1..255; + } + } + + leaf mtu { + type uint16 { + range 1..9216; + } + } + + leaf admin_status { + mandatory true; + type stypes:admin_status; + } + } /* end of list PORTCHANNEL_LIST */ + + } /* end of container PORTCHANNEL */ + + } /* end of container sonic-portchannel */ + +} /* end of module sonic-port */ diff --git a/src/sonic-yang-models/yang-models/sonic-types.yang b/src/sonic-yang-models/yang-models/sonic-types.yang new file mode 100644 index 000000000000..fb651847582e --- /dev/null +++ b/src/sonic-yang-models/yang-models/sonic-types.yang @@ -0,0 +1,92 @@ +module sonic-types { + + yang-version 1.1; + + namespace "http://github.com/Azure/sonic-head"; + prefix sonic-types; + + description "SONiC type for yang Models of SONiC OS"; + + revision 2019-07-01 { + description "First Revision"; + } + + typedef ip-family { + type enumeration { + enum IPv4; + enum IPv6; + } + } + + typedef sonic-ip4-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]))'; + } + } + + typedef sonic-ip6-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}(([^:]+:[^:]+)|(.*\..*)))|' + + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)' + + '(/.+)'; + } + } + + typedef admin_status { + type enumeration { + enum up; + enum down; + } + } + + typedef packet_action{ + type enumeration { + enum DROP; + enum FORWARD; + enum REDIRECT; + } + } + + typedef ip_type { + type enumeration { + enum ANY; + enum IP; + enum NON_IP; + enum IPV4; + enum IPV6; + enum IPv4ANY; + enum NON_IP4; + enum IPv6ANY; + enum NON_IPv6; + enum ARP; + } + } + + typedef acl_table_type { + type enumeration { + enum L2; + enum L3; + enum L3V6; + enum MIRROR; + enum MIRRORV6; + enum MIRROR_DSCP; + enum CTRLPLANE; + } + } + + typedef vlan_tagging_mode { + type enumeration { + enum tagged; + enum untagged; + enum priority_tagged; + } + } +} diff --git a/src/sonic-yang-models/yang-models/sonic-vlan.yang b/src/sonic-yang-models/yang-models/sonic-vlan.yang new file mode 100644 index 000000000000..4c3aecaf8106 --- /dev/null +++ b/src/sonic-yang-models/yang-models/sonic-vlan.yang @@ -0,0 +1,209 @@ +module sonic-vlan { + + namespace "http://github.com/Azure/sonic-vlan"; + prefix vlan; + + import ietf-yang-types { + prefix yang; + } + + import ietf-inet-types { + prefix inet; + } + + import sonic-types { + prefix stypes; + revision-date 2019-07-01; + } + + import sonic-extension { + prefix ext; + revision-date 2019-07-01; + } + + import sonic-port { + prefix port; + revision-date 2019-07-01; + } + + description "VLAN yang Module for SONiC OS"; + + revision 2019-07-01 { + description "First Revision"; + } + + container sonic-vlan { + + container VLAN_INTERFACE { + + description "VLAN_INTERFACE part of config_db.json"; + + list VLAN_INTERFACE_LIST { + + description "VLAN INTERFACE part of config_db.json with vrf"; + + key "vlan_name"; + + ext:key-regex-configdb-to-yang "^(Vlan[a-zA-Z0-9_-]+)$"; + + ext:key-regex-yang-to-configdb ""; + + leaf vlan_name { + type leafref { + path /vlan:sonic-vlan/vlan:VLAN/vlan:VLAN_LIST/vlan:vlan_name; + } + } + + leaf vrf_name { + type string { + pattern "Vrf[a-zA-Z0-9_-]+"; + length 3..255; + } + } + } + /* end of VLAN_INTERFACE_LIST */ + + list VLAN_INTERFACE_IPPREFIX_LIST { + + key "vlan_name ip-prefix"; + + ext:key-regex-configdb-to-yang "^(Vlan[a-zA-Z0-9_-]+)|([a-fA-F0-9:./]+$)"; + + ext:key-regex-yang-to-configdb "|"; + + leaf vlan_name { + /* This node must be present in VLAN_INTERFACE_LIST */ + must "(current() = ../../VLAN_INTERFACE_LIST[vlan_name=current()]/vlan_name)" + { + error-message "Must condition not satisfied, Try adding Vlan: {}, Example: 'Vlan100': {}"; + } + + type leafref { + path "/vlan:sonic-vlan/vlan:VLAN/vlan:VLAN_LIST/vlan:vlan_name"; + } + } + + leaf ip-prefix { + type union { + type stypes:sonic-ip4-prefix; + type stypes:sonic-ip6-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 stypes: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 "vlan_name"; + + ext:key-regex-configdb-to-yang "^(Vlan[a-zA-Z0-9_-]+)$"; + + ext:key-regex-yang-to-configdb ""; + + leaf vlan_name { + type string { + pattern 'Vlan([0-9]{1,3}|[0-3][0-9]{4}|[4][0][0-8][0-9]|[4][0][9][0-4])'; + } + } + + 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 { + type stypes:admin_status; + } + + leaf-list members { + /* leaf-list members are unique by default */ + + type leafref { + path "/port:sonic-port/port:PORT/port:PORT_LIST/port:port_name"; + } + } + } + /* end of VLAN_LIST */ + } + /* end of container VLAN */ + + container VLAN_MEMBER { + + description "VLAN_MEMBER part of config_db.json"; + + list VLAN_MEMBER_LIST { + + key "vlan_name port"; + + ext:key-regex-configdb-to-yang "^(Vlan[a-zA-Z0-9-_]+)|(Ethernet[0-9]+)$"; + + ext:key-regex-yang-to-configdb "|"; + + leaf vlan_name { + type leafref { + path "/vlan:sonic-vlan/vlan:VLAN/vlan:VLAN_LIST/vlan:vlan_name"; + } + } + + leaf port { + /* key elements are mandatory by default */ + type leafref { + path /port:sonic-port/port:PORT/port:PORT_LIST/port:port_name; + } + } + + leaf tagging_mode { + mandatory true; + type stypes:vlan_tagging_mode; + } + } + /* end of list VLAN_MEMBER_LIST */ + } + /* end of container VLAN_MEMBER */ + } + /* end of container sonic-vlan */ +} +/* end of module sonic-vlan */