diff --git a/config/transformer/models_list b/config/transformer/models_list
index bc192c902a..c7e34647c0 100644
--- a/config/transformer/models_list
+++ b/config/transformer/models_list
@@ -2,3 +2,4 @@
openconfig-acl.yang
openconfig-acl-annot.yang
+sonic-vxlan.yang
diff --git a/models/yang/openconfig-spanning-tree-ext.yang b/models/yang/openconfig-spanning-tree-ext.yang
index 3546a7c8fa..6e91e7113a 100755
--- a/models/yang/openconfig-spanning-tree-ext.yang
+++ b/models/yang/openconfig-spanning-tree-ext.yang
@@ -85,6 +85,12 @@ module openconfig-spanning-tree-ext {
description
"Instance identifier of STP";
}
+
+ leaf root-port-name {
+ type string;
+ description
+ "Name of root port";
+ }
}
grouping vlan-interface-extra-state-field {
diff --git a/models/yang/sonic/sonic-vxlan.yang b/models/yang/sonic/sonic-vxlan.yang
new file mode 100644
index 0000000000..2c962959d3
--- /dev/null
+++ b/models/yang/sonic/sonic-vxlan.yang
@@ -0,0 +1,105 @@
+module sonic-vxlan {
+ namespace "http://github.com/Azure/sonic-vxlan";
+ prefix svxlan;
+ yang-version 1.1;
+
+ import ietf-yang-types {
+ prefix yang;
+ }
+
+ import ietf-inet-types {
+ prefix inet;
+ }
+
+ organization
+ "SONiC";
+
+ contact
+ "SONiC";
+
+ description
+ "SONIC VXLAN";
+
+ revision 2019-10-01 {
+ description
+ "Initial revision.";
+ }
+
+ container sonic-vxlan {
+
+ container VXLAN_TUNNEL {
+
+ list VXLAN_TUNNEL_LIST {
+ key "name";
+ max-elements 1;
+
+ leaf name {
+ type string;
+ }
+
+ leaf src_ip {
+ mandatory true;
+ type inet:ipv4-address;
+ }
+ }
+ }
+
+ container VXLAN_TUNNEL_MAP {
+
+ list VXLAN_TUNNEL_MAP_LIST {
+ key "name mapname";
+
+ leaf name {
+ type leafref {
+ path "../../../VXLAN_TUNNEL/VXLAN_TUNNEL_LIST/name";
+ }
+ }
+
+ leaf mapname {
+ type string;
+ }
+
+ leaf vlan {
+ mandatory true;
+ type string {
+ pattern "Vlan(409[0-5]|40[0-8][0-9]|[1-3][0-9]{3}|[1-9][0-9]{2}|[1-9][0-9]|[1-9])" {
+ error-message "Invalid Vlan name pattern";
+ error-app-tag vlan-name-invalid;
+ }
+ }
+ }
+
+ leaf vni {
+ mandatory true;
+ type uint32 {
+ range "1..16777215" {
+ error-message "VNI ID out of range";
+ error-app-tag vnid-invalid;
+ }
+ }
+ }
+ }
+ }
+
+ container EVPN_NVO {
+
+ list EVPN_NVO_LIST {
+
+ key "name";
+ max-elements 1;
+
+ leaf name {
+ type string;
+ }
+
+ leaf source_vtep {
+ mandatory true;
+ type leafref {
+ path "../../../VXLAN_TUNNEL/VXLAN_TUNNEL_LIST/name";
+ }
+ }
+ }
+ }
+ }
+
+}
diff --git a/src/CLI/actioner/README_cli_client.md b/src/CLI/actioner/README_cli_client.md
new file mode 100644
index 0000000000..9792310b58
--- /dev/null
+++ b/src/CLI/actioner/README_cli_client.md
@@ -0,0 +1,42 @@
+# Generic RESTful Python client
+
+A generic RESTful Python client for interacting with JSON APIs.
+
+## Usage
+
+To use this client you just need to import ApiClient and initialize it with an URL endpoint
+
+ from cli_client import ApiClient
+ api = ApiClient('#your_api_endpoint') #your_api_endpoint is optional default is https://localhost:443
+
+Now that you have a RESTful API object you can start sending requests.
+
+
+## Making a request
+
+The framework supports GET, PUT, POST, PATCH and DELETE requests:
+
+ from cli_client import ApiClient
+ api = ApiClient()
+ response = api.get('/authors/')
+ response = api.post('/authors/', {'title': 'Broadcom', 'author': 'Faraaz Mohammed'})
+ response = api.put('/author/faraaz/', {'dob': '06/09/2006'})
+ response = api.delete('/author/faraaz/')
+
+## To get the Response Data
+response = api.get('/authors/')
+Use response.content object
+
+For Successful request response.content will contain valid JSON data
+For Non-Successful request response.content will contain errors object returned by REST Server
+
+## Verifying Requests
+
+Two helpers are built in to verify the success of requests made. `ok()` checks for a 20x status code and returns a boolean, `errors()` returns the body content as a dict object if the status code is not 20x:
+
+ response = api.get('/books/')
+ if response.ok():
+ print 'Success!'
+ else:
+ print req.errors()
+
diff --git a/src/CLI/actioner/cli_client.py b/src/CLI/actioner/cli_client.py
new file mode 100644
index 0000000000..e2aea16887
--- /dev/null
+++ b/src/CLI/actioner/cli_client.py
@@ -0,0 +1,119 @@
+################################################################################
+# #
+# Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or #
+# its subsidiaries. #
+# #
+# Licensed under the Apache License, Version 2.0 (the "License"); #
+# you may not use this file except in compliance with the License. #
+# You may obtain a copy of the License at #
+# #
+# http://www.apache.org/licenses/LICENSE-2.0 #
+# #
+# Unless required by applicable law or agreed to in writing, software #
+# distributed under the License is distributed on an "AS IS" BASIS, #
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. #
+# See the License for the specific language governing permissions and #
+# limitations under the License. #
+# #
+################################################################################
+import json
+import urllib3
+
+class ApiClient(object):
+ """
+ A client for accessing a RESTful API
+ """
+ def __init__(self, api_uri=None):
+ """
+ Create a RESTful API client.
+ """
+ api_uri="https://localhost:443"
+ self.api_uri = api_uri
+
+ self.checkCertificate = False
+
+ if not self.checkCertificate:
+ urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
+
+ self.version = "0.0.1"
+
+ def set_headers(self, nonce = None):
+ from base64 import b64encode
+ from hashlib import sha256
+ from platform import platform, python_version
+ from hmac import new
+
+ if not nonce:
+ from time import time
+ nonce = int(time())
+
+ return {
+ 'User-Agent': "PythonClient/{0} ({1}; Python {2})".format(self.version,
+ platform(True),
+ python_version())
+ }
+
+ @staticmethod
+ def merge_dicts(*dict_args):
+ result = {}
+ for dictionary in dict_args:
+ result.update(dictionary)
+
+ return result
+
+ def request(self, method, path, data = {}, headers = {}):
+ from requests import request
+
+ url = '{0}{1}'.format(self.api_uri, path)
+ params = {}
+ headers = self.merge_dicts(self.set_headers(), headers)
+
+ if method == "GET":
+ params.update(data)
+ return request(method, url, headers=headers, params=params, verify=self.checkCertificate)
+ else:
+ return request(method, url, headers=headers, params=params, data=json.dumps(data), verify=self.checkCertificate)
+
+ def post(self, path, data = {}):
+ return Response(self.request("POST", path, data, {'Content-Type': 'application/json'}))
+
+ def get(self, path, data = {}):
+ return Response(self.request("GET", path, data))
+
+ def put(self, path, data = {}):
+ return Response(self.request("PUT", path, data, {'Content-Type': 'application/json'}))
+
+ def patch(self, path, data = {}):
+ return Response(self.request("PATCH", path, data, {'Content-Type': 'application/json'}))
+
+ def delete(self, path, data = {}):
+ return Response(self.request("DELETE", path, data))
+
+class Response(object):
+ def __init__(self, response):
+ self.response = response
+
+ try:
+ self.content = self.response.json()
+ except ValueError:
+ self.content = self.response.text
+
+ def ok(self):
+ import requests
+ return self.response.status_code == requests.codes.ok
+
+ def errors(self):
+ if self.ok():
+ return {}
+
+ errors = self.content
+
+ if(not isinstance(errors, dict)):
+ errors = {"error": errors} # convert to dict for consistency
+ elif('errors' in errors):
+ errors = errors['ietf-restconf:errors']
+
+ return errors
+
+ def __getitem__(self, key):
+ return self.content[key]
diff --git a/src/CLI/actioner/sonic-cli-if.py b/src/CLI/actioner/sonic-cli-if.py
index df36e97c72..d4869cf3b7 100755
--- a/src/CLI/actioner/sonic-cli-if.py
+++ b/src/CLI/actioner/sonic-cli-if.py
@@ -197,6 +197,10 @@ def run(func, args):
try:
# Temporary code for #show vlan command with dummy data
+ if func.__name__ == "get_openconfig_vlan_interfaces_interface_ethernet_switched_vlan_state":
+ api_response = {'Vlan100': {'Ethernet20': 'tagged', 'Ethernet40': 'untagged'}}
+ show_cli_output(args[0], api_response)
+ return
if body is not None:
api_response = getattr(aa,func.__name__)(*keypath, body=body)
else :
diff --git a/src/CLI/actioner/sonic-cli-ptp.py b/src/CLI/actioner/sonic-cli-ptp.py
new file mode 100644
index 0000000000..123306fc6c
--- /dev/null
+++ b/src/CLI/actioner/sonic-cli-ptp.py
@@ -0,0 +1,88 @@
+#!/usr/bin/python
+
+import sys
+import swsssdk
+from rpipe_utils import pipestr
+from scripts.render_cli import show_cli_output
+from swsssdk import ConfigDBConnector
+
+import urllib3
+urllib3.disable_warnings()
+
+PTP_CLOCK = 'PTP_CLOCK'
+PTP_GLOBAL = 'GLOBAL'
+
+if __name__ == '__main__':
+ pipestr().write(sys.argv)
+ db = swsssdk.SonicV2Connector(host='127.0.0.1')
+ db.connect(db.CONFIG_DB)
+ db.connect(db.COUNTERS_DB)
+
+ config_db = ConfigDBConnector()
+ if config_db is None:
+ sys.exit()
+ config_db.connect()
+ if sys.argv[1] == 'get_ietf_ptp_ptp_instance_list_default_ds':
+ raw_data = config_db.get_entry(PTP_CLOCK, PTP_GLOBAL)
+ api_response = {}
+ api_response['ietf-ptp:default-ds'] = raw_data
+ show_cli_output(sys.argv[3], api_response)
+ elif sys.argv[1] == 'get_ietf_ptp_ptp_instance_list_time_properties_ds':
+ print "Nothing"
+ sys.exit()
+ elif sys.argv[1] == 'get_ietf_ptp_ptp_instance_list_parent_ds':
+ print "Nothing"
+ sys.exit()
+ elif sys.argv[1] == 'get_ietf_ptp_ptp_instance_list_port_ds_list':
+ print "Nothing"
+ sys.exit()
+ elif sys.argv[1] == 'get_ietf_ptp_ptp_instance_list':
+ raw_data = config_db.get_keys(PTP_CLOCK)
+ api_response = {}
+ api_response_list = []
+ port_ds_dict = {}
+ port_ds_list = []
+ port_ds_entry = {}
+ for key in raw_data:
+ if "Ethernet" in key:
+ port_ds_entry = {}
+ port_ds_entry["port-number"] = key
+ port_ds_entry["port-state"] = "online"
+ port_ds_list.append(port_ds_entry)
+ port_ds_dict['port-ds-list'] = port_ds_list
+ api_response_list.append(port_ds_dict)
+ api_response['ietf-ptp:instance_list'] = api_response_list
+ show_cli_output(sys.argv[3], api_response)
+ elif sys.argv[1] == 'patch_ietf_ptp_ptp_instance_list_default_ds_domain_number':
+ data = {}
+ data['domain-number'] = sys.argv[3]
+ config_db.mod_entry(PTP_CLOCK, PTP_GLOBAL, data)
+ elif sys.argv[1] == 'patch_ietf_ptp_ptp_instance_list_default_ds_priority1':
+ data = {}
+ data['priority1'] = sys.argv[3]
+ config_db.mod_entry(PTP_CLOCK, PTP_GLOBAL, data)
+ elif sys.argv[1] == 'patch_ietf_ptp_ptp_instance_list_default_ds_priority2':
+ data = {}
+ data['priority2'] = sys.argv[3]
+ config_db.mod_entry(PTP_CLOCK, PTP_GLOBAL, data)
+ elif sys.argv[1] == 'patch_ietf_ptp_ptp_instance_list_default_ds_two_step_flag':
+ data = {}
+ if sys.argv[3] == "enable":
+ data['two-step-flag'] = '1'
+ else:
+ data['two-step-flag'] = '0'
+ config_db.mod_entry(PTP_CLOCK, PTP_GLOBAL, data)
+ elif sys.argv[1] == 'patch_ietf_ptp_ptp_transparent_clock_default_ds_delay_mechanism':
+ data = {}
+ data['tc-delay-mechanism'] = sys.argv[2]
+ config_db.mod_entry(PTP_CLOCK, PTP_GLOBAL, data)
+ elif sys.argv[1] == 'add_port':
+ data = {}
+ data['enable'] = '1'
+ config_db.set_entry(PTP_CLOCK, sys.argv[2], data)
+ elif sys.argv[1] == 'del_port':
+ config_db.set_entry(PTP_CLOCK, sys.argv[2], None)
+ else:
+ data = {}
+ data[sys.argv[1]] = sys.argv[2]
+ config_db.mod_entry(PTP_CLOCK, PTP_GLOBAL, data)
diff --git a/src/CLI/actioner/sonic-cli-vxlan.py b/src/CLI/actioner/sonic-cli-vxlan.py
new file mode 100755
index 0000000000..3bcb1fe2ed
--- /dev/null
+++ b/src/CLI/actioner/sonic-cli-vxlan.py
@@ -0,0 +1,143 @@
+#!/usr/bin/python
+import sys
+import time
+import json
+import ast
+import sonic_vxlan_client
+from rpipe_utils import pipestr
+from sonic_vxlan_client.rest import ApiException
+from scripts.render_cli import show_cli_output
+
+import urllib3
+urllib3.disable_warnings()
+
+
+plugins = dict()
+
+def register(func):
+ """Register sdk client method as a plug-in"""
+ plugins[func.__name__] = func
+ return func
+
+
+def call_method(name, args):
+ method = plugins[name]
+ return method(args)
+
+def generate_body(func, args):
+ body = None
+ # Get the rules of all ACL table entries.
+ if func.__name__ == 'patch_list_sonic_vxlan_sonic_vxlan_vxlan_tunnel_vxlan_tunnel_list':
+ keypath = []
+ body = {
+ "sonic-vxlan:VXLAN_TUNNEL_LIST": [
+ {
+ "name": args[0][5:],
+ "src_ip": args[1]
+ }
+ ]
+ }
+ elif func.__name__ == 'delete_sonic_vxlan_sonic_vxlan_vxlan_tunnel':
+ #keypath = [ args[0][5:] ]
+ keypath = []
+ elif func.__name__ == 'patch_list_sonic_vxlan_sonic_vxlan_evpn_nvo_evpn_nvo_list':
+ keypath = []
+ body = {
+ "sonic-vxlan:EVPN_NVO_LIST": [
+ {
+ "name": args[0][4:],
+ "source_vtep": args[1]
+ }
+ ]
+ }
+ elif func.__name__ == 'delete_sonic_vxlan_sonic_vxlan_evpn_nvo':
+ #keypath = [ args[0][4:] ]
+ keypath = []
+ elif func.__name__ == 'patch_list_sonic_vxlan_sonic_vxlan_vxlan_tunnel_map_vxlan_tunnel_map_list':
+ keypath = []
+ body = {
+ "sonic-vxlan:VXLAN_TUNNEL_MAP_LIST": [
+ {
+ "name": args[0][5:],
+ "mapname": 'map_'+ args[1] + '_' + args[2],
+ "vlan": 'Vlan' + args[2],
+ "vni": int(args[1])
+ }
+ ]
+ }
+ elif func.__name__ == 'delete_sonic_vxlan_sonic_vxlan_vxlan_tunnel_map_vxlan_tunnel_map_list':
+ keypath = [ args[0][5:] , 'map_'+ args[1] + '_' + args[2]]
+ else:
+ body = {}
+
+ return keypath,body
+
+def getId(item):
+ prfx = "Ethernet"
+ state_dict = item['state']
+ ifName = state_dict['name']
+
+ if ifName.startswith(prfx):
+ ifId = int(ifName[len(prfx):])
+ return ifId
+ return ifName
+
+def run(func, args):
+
+ c = sonic_vxlan_client.Configuration()
+ c.verify_ssl = False
+ aa = sonic_vxlan_client.SonicVxlanApi(api_client=sonic_vxlan_client.ApiClient(configuration=c))
+
+ # create a body block
+ keypath, body = generate_body(func, args)
+
+ try:
+ if body is not None:
+ api_response = getattr(aa,func.__name__)(*keypath, body=body)
+ else :
+ api_response = getattr(aa,func.__name__)(*keypath)
+
+ if api_response is None:
+ print ("Success")
+ else:
+ # Get Command Output
+ api_response = aa.api_client.sanitize_for_serialization(api_response)
+# if 'openconfig-interfaces:interfaces' in api_response:
+# value = api_response['openconfig-interfaces:interfaces']
+# if 'interface' in value:
+# tup = value['interface']
+# value['interface'] = sorted(tup, key=getId)
+
+ if api_response is None:
+ print("Failed")
+ else:
+ return
+
+ except ApiException as e:
+ if e.body != "":
+ body = json.loads(e.body)
+ if "ietf-restconf:errors" in body:
+ err = body["ietf-restconf:errors"]
+ if "error" in err:
+ errList = err["error"]
+
+ errDict = {}
+ for dict in errList:
+ for k, v in dict.iteritems():
+ errDict[k] = v
+
+ if "error-message" in errDict:
+ print "%Error: " + errDict["error-message"]
+ return
+ print "%Error: Transaction Failure"
+ return
+ print "%Error: Transaction Failure"
+ else:
+ print "Failed"
+
+if __name__ == '__main__':
+
+ pipestr().write(sys.argv)
+ func = eval(sys.argv[1], globals(), sonic_vxlan_client.SonicVxlanApi.__dict__)
+
+ run(func, sys.argv[2:])
diff --git a/src/CLI/actioner/sonic-cli.py b/src/CLI/actioner/sonic-cli.py
index f694c29db9..9665da747f 100755
--- a/src/CLI/actioner/sonic-cli.py
+++ b/src/CLI/actioner/sonic-cli.py
@@ -59,14 +59,17 @@ def generate_body(func, args):
# Configure ACL table
elif func.__name__ == 'patch_openconfig_acl_acl_acl_sets_acl_set' :
- keypath = [ args[0], args[1] ]
- body = { "openconfig-acl:config": {
- "name": args[0],
- "type": args[1],
- "description": ""
- }
- }
-
+ keypath = [ args[0], args[1] ]
+ body=collections.defaultdict(dict)
+ body["acl-set"]=[{
+ "name": args[0],
+ "type": args[1],
+ "config": {
+ "name": args[0],
+ "type": args[1],
+ "description": ""
+ }
+ }]
# Configure ACL rule specific to an ACL table
elif func.__name__ == 'patch_list_openconfig_acl_acl_acl_sets_acl_set_acl_entries_acl_entry' :
keypath = [ args[0], args[1] ]
diff --git a/src/CLI/clitree/cli-xml/ptp.xml b/src/CLI/clitree/cli-xml/ptp.xml
new file mode 100644
index 0000000000..fcb9905787
--- /dev/null
+++ b/src/CLI/clitree/cli-xml/ptp.xml
@@ -0,0 +1,124 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ if test "${ptp-subcommands}" = "time-property"; then
+ python $SONIC_CLI_ROOT/sonic-cli-ptp.py get_ietf_ptp_ptp_instance_list_time_properties_ds 0 ptp_tp_show.j2
+ elif test "${ptp-subcommands}" = "clock"; then
+ python $SONIC_CLI_ROOT/sonic-cli-ptp.py get_ietf_ptp_ptp_instance_list_default_ds 0 ptp_clock_show.j2
+ elif test "${ptp-subcommands}" = "parent"; then
+ python $SONIC_CLI_ROOT/sonic-cli-ptp.py get_ietf_ptp_ptp_instance_list_parent_ds 0 ptp_parent_show.j2
+ elif test "${ptp-subcommands}" = "foreign-masters-record"; then
+ echo "nothing"
+ elif test "${ptp-subcommands}" = "port"; then
+ python $SONIC_CLI_ROOT/sonic-cli-ptp.py get_ietf_ptp_ptp_instance_list_port_ds_list 0 ${ptp_port_number} ptp_port_show.j2
+ elif test "${ptp-subcommands}" = ""; then
+ python $SONIC_CLI_ROOT/sonic-cli-ptp.py get_ietf_ptp_ptp_instance_list 0 ptp_show.j2
+ else
+ python $SONIC_CLI_ROOT/sonic-cli-ptp.py get_ietf_ptp_ptp_instance_list 0 ptp_port_show.j2
+ fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ if test "${cfg-ptp-subcommands}" = "mode"; then
+ python $SONIC_CLI_ROOT/sonic-cli-ptp.py "clock-type" ${mode_type}
+ elif test "${cfg-ptp-subcommands}" = "delay-mechanism"; then
+ python $SONIC_CLI_ROOT/sonic-cli-ptp.py patch_ietf_ptp_ptp_transparent_clock_default_ds_delay_mechanism ${ptp_delay_mechanism_type}
+ elif test "${cfg-ptp-subcommands}" = "network-transport"; then
+ python $SONIC_CLI_ROOT/sonic-cli-ptp.py "network-transport" ${ptp_network_transport_type}
+ elif test "${cfg-ptp-subcommands}" = "source-ip"; then
+ python $SONIC_CLI_ROOT/sonic-cli-ptp.py "source-ip" ${ptp_source_ip}
+ elif test "${cfg-ptp-subcommands}" = "domain"; then
+ python $SONIC_CLI_ROOT/sonic-cli-ptp.py patch_ietf_ptp_ptp_instance_list_default_ds_domain_number 0 ${ptp_domain}
+ elif test "${cfg-ptp-subcommands}" = "domain-profile"; then
+ python $SONIC_CLI_ROOT/sonic-cli-ptp.py "domain-profile" ${ptp_domain_profile}
+ elif test "${cfg-ptp-subcommands}" = "two-step"; then
+ python $SONIC_CLI_ROOT/sonic-cli-ptp.py patch_ietf_ptp_ptp_instance_list_default_ds_two_step_flag 0 ${ptp_two_step}
+ elif test "${cfg-ptp-subcommands}" = "priority1"; then
+ python $SONIC_CLI_ROOT/sonic-cli-ptp.py patch_ietf_ptp_ptp_instance_list_default_ds_priority1 0 ${ptp_priority1}
+ elif test "${cfg-ptp-subcommands}" = "priority2"; then
+ python $SONIC_CLI_ROOT/sonic-cli-ptp.py patch_ietf_ptp_ptp_instance_list_default_ds_priority2 0 ${ptp_priority2}
+ elif test "${cfg-ptp-subcommands}" = "log-announce-interval"; then
+ python $SONIC_CLI_ROOT/sonic-cli-ptp.py "log-announce-interval" ${ptp_announce_interval}
+ elif test "${cfg-ptp-subcommands}" = "announce-timeout"; then
+ python $SONIC_CLI_ROOT/sonic-cli-ptp.py "announce-receipt-timeout" ${ptp_announce_timeout}
+ elif test "${cfg-ptp-subcommands}" = "log-sync-interval"; then
+ python $SONIC_CLI_ROOT/sonic-cli-ptp.py "log-sync-interval" ${ptp_sync_interval}
+ elif test "${cfg-ptp-subcommands}" = "log-min-delay-req-interval"; then
+ python $SONIC_CLI_ROOT/sonic-cli-ptp.py "log-min-delay-req-interval" ${ptp_delay_request_interval}
+ elif test "${cfg-ptp-subcommands}" = "port"; then
+ if test "${add}" = "add"; then
+ python $SONIC_CLI_ROOT/sonic-cli-ptp.py "add_port" ${Ethernet}${ptp_port_number}
+ elif test "${del}" = "del"; then
+ python $SONIC_CLI_ROOT/sonic-cli-ptp.py "del_port" ${Ethernet}${ptp_port_number}
+ fi
+ fi
+
+
+
+
diff --git a/src/CLI/clitree/cli-xml/sonic_types.xml b/src/CLI/clitree/cli-xml/sonic_types.xml
index 6d4f8fef01..1c011d47a4 100644
--- a/src/CLI/clitree/cli-xml/sonic_types.xml
+++ b/src/CLI/clitree/cli-xml/sonic_types.xml
@@ -76,6 +76,13 @@ limitations under the License.
help="on|off"
/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/CLI/clitree/cli-xml/vxlan.xml b/src/CLI/clitree/cli-xml/vxlan.xml
new file mode 100644
index 0000000000..fe44328284
--- /dev/null
+++ b/src/CLI/clitree/cli-xml/vxlan.xml
@@ -0,0 +1,102 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ python $SONIC_CLI_ROOT/sonic-cli-vxlan.py delete_sonic_vxlan_sonic_vxlan_evpn_nvo ${iface}
+
+
+
+ python $SONIC_CLI_ROOT/sonic-cli-vxlan.py patch_list_sonic_vxlan_sonic_vxlan_evpn_nvo_evpn_nvo_list ${iface} ${vxlan_name}
+
+
+
+
+
+
+
+
+ python $SONIC_CLI_ROOT/sonic-cli-vxlan.py delete_sonic_vxlan_sonic_vxlan_vxlan_tunnel ${iface}
+
+
+
+
+
+
+
+
+
+
+
+ python $SONIC_CLI_ROOT/sonic-cli-vxlan.py delete_sonic_vxlan_sonic_vxlan_vxlan_tunnel_map_vxlan_tunnel_map_list ${iface} ${vnid} ${vid}
+
+
+
+
+ python $SONIC_CLI_ROOT/sonic-cli-vxlan.py patch_list_sonic_vxlan_sonic_vxlan_vxlan_tunnel_vxlan_tunnel_list ${iface} ${SIP}
+
+
+
+
+
+
+
+
+
+
+
+
+ python $SONIC_CLI_ROOT/sonic-cli-vxlan.py patch_list_sonic_vxlan_sonic_vxlan_vxlan_tunnel_map_vxlan_tunnel_map_list ${iface} ${vnid} ${vid}
+
+
+
+
+
diff --git a/src/CLI/klish/clish_start b/src/CLI/klish/clish_start
index ddf43a7676..410b85345e 100755
--- a/src/CLI/klish/clish_start
+++ b/src/CLI/klish/clish_start
@@ -2,7 +2,10 @@
export SONIC_MGMT_ROOT=/usr/sbin
export SONIC_CLI_ROOT=$SONIC_MGMT_ROOT/cli
-export SYSTEM_NAME="${HOSTNAME%%.*}"
+if [ -z $SYSTEM_NAME ]
+then
+ export SYSTEM_NAME="${HOSTNAME%%.*}"
+fi
export PYTHONPATH=$SONIC_MGMT_ROOT:$SONIC_MGMT_ROOT/lib/swagger_client_py:$SONIC_CLI_ROOT:$SONIC_CLI_ROOT/scripts:$PYTHONPATH
export CLISH_PATH=$SONIC_CLI_ROOT/command-tree
export LD_LIBRARY_PATH=/usr/local/lib:$SONIC_CLI_ROOT/.libs:$LD_LIBRARY_PATH
diff --git a/src/CLI/renderer/templates/ptp_clock_show.j2 b/src/CLI/renderer/templates/ptp_clock_show.j2
new file mode 100755
index 0000000000..2371fee3bd
--- /dev/null
+++ b/src/CLI/renderer/templates/ptp_clock_show.j2
@@ -0,0 +1,35 @@
+{{'-----------------------------------------------------------'}}
+{{'Attribute'.ljust(21)}} {{'Value/State'}}
+{{'-----------------------------------------------------------'}}
+{% for key,value in json_output.items() %}
+{% if 'domain-number' in value.keys() %}
+{{ 'Domain Number'.ljust(21)}} {{ value['domain-number']}}
+{% endif %}
+{% if 'priority1' in value.keys() %}
+{{ 'Priority1'.ljust(21)}} {{ value['priority1']}}
+{% endif %}
+{% if 'priority2' in value.keys() %}
+{{ 'Priority2'.ljust(21)}} {{ value['priority2']}}
+{% endif %}
+{% if 'two-step-flag' in value.keys() %}
+{{ 'Two Step'.ljust(21)}} {{ value['two-step-flag']}}
+{% endif %}
+{% if 'slave-only' in value.keys() %}
+{{ 'Slave Only'.ljust(21)}} {{ value['slave-only']}}
+{% endif %}
+{% if 'number-ports' in value.keys() %}
+{{ 'Number Ports'.ljust(21)}} {{ value['number-ports']}}
+{% endif %}
+{% if 'clock-quality' in value.keys() %}
+{{ 'Clock Quality:'.ljust(21)}}
+{% if 'clock-class' in value['clock-quality'].keys() %}
+{{ ' Clock Class'.ljust(21)}} {{ value['clock-quality']['clock-class']}}
+{% endif %}
+{% if 'clock-accuracy' in value['clock-quality'].keys() %}
+{{ ' Clock Accuracy'.ljust(21)}} {{ value['clock-quality']['clock-accuracy']}}
+{% endif %}
+{% if 'offset-scaled-log-variance' in value['clock-quality'].keys() %}
+{{ ' Ofst Scaled Log Var'.ljust(21)}} {{ value['clock-quality']['offset-scaled-log-variance']}}
+{% endif %}
+{% endif %}
+{% endfor %}
diff --git a/src/CLI/renderer/templates/ptp_parent_show.j2 b/src/CLI/renderer/templates/ptp_parent_show.j2
new file mode 100755
index 0000000000..228eec87fb
--- /dev/null
+++ b/src/CLI/renderer/templates/ptp_parent_show.j2
@@ -0,0 +1,24 @@
+{{'-----------------------------------------------------------'}}
+{{'Attribute'.ljust(30)}} {{'Value/State'}}
+{{'-----------------------------------------------------------'}}
+{% for key,value in json_output.items() %}
+{% if 'grandmaster-identity' in value.keys() %}
+{{ 'Grandmaster Identity'.ljust(30)}} {{ value['grandmaster-identity']}}
+{% endif %}
+{% if 'grandmaster-priority1' in value.keys() %}
+{{ 'Grandmaster Priority1'.ljust(30)}} {{ value['grandmaster-priority1']}}
+{% endif %}
+{% if 'grandmaster-priority2' in value.keys() %}
+{{ 'Grandmaster Priority2'.ljust(30)}} {{ value['grandmaster-priority2']}}
+{% endif %}
+{% if 'parent-stats' in value.keys() %}
+{{ 'Stats Valid'.ljust(30)}} {{ value['parent-stats']}}
+{% endif %}
+{% if 'observed-parent-offset-scaled-log-variance' in value.keys() %}
+{{ 'Observed Off Scaled Log Var'.ljust(30)}} {{ value['observed-parent-offset-scaled-log-variance']}}
+{% endif %}
+{% if 'observed-parent-clock-phase-change-rate' in value.keys() %}
+{{ 'Observed Clock Phase Chg Rate'.ljust(30)}} {{ value['observed-parent-clock-phase-change-rate']}}
+{% endif %}
+{% endfor %}
+
diff --git a/src/CLI/renderer/templates/ptp_port_show.j2 b/src/CLI/renderer/templates/ptp_port_show.j2
new file mode 100755
index 0000000000..c19afaadf9
--- /dev/null
+++ b/src/CLI/renderer/templates/ptp_port_show.j2
@@ -0,0 +1,23 @@
+{{'-----------------------------------------------------------'}}
+{{'Attribute'.ljust(30)}} {{'Value/State'}}
+{{'-----------------------------------------------------------'}}
+{% for key,value in json_output.items() %}
+{% for key2,value2 in value.items() %}
+{% if 'port-number' in value2.keys() %}
+{{ 'Port Number'.ljust(30)}} {{ value2['port-number']}}
+{% endif %}
+{% if 'port-state' in value2.keys() %}
+{{ 'Port State'.ljust(30)}} {{ value2['port-state']}}
+{% endif %}
+{% if 'log-min-pdelay-req-interval' in value2.keys() %}
+{{ 'Log Min Pdelay Req Intvl'.ljust(30)}} {{ value2['log-min-pdelay-req-interval']}}
+{% endif %}
+{% if 'log-min-delay-req-interval' in value2.keys() %}
+{{ 'Log Min delay Req Intvl'.ljust(30)}} {{ value2['log-min-delay-req-interval']}}
+{% endif %}
+{% if 'peer-mean-path-delay' in value2.keys() %}
+{{ 'Peer Mean Path delay'.ljust(30)}} {{ value2['peer-mean-path-delay']}}
+{% endif %}
+{% endfor %}
+{% endfor %}
+
diff --git a/src/CLI/renderer/templates/ptp_show.j2 b/src/CLI/renderer/templates/ptp_show.j2
new file mode 100755
index 0000000000..5fb4d8803b
--- /dev/null
+++ b/src/CLI/renderer/templates/ptp_show.j2
@@ -0,0 +1,19 @@
+{{'-----------------------------------------------------------'}}
+{{'Interface'.ljust(20)}} {{'State'}}
+{{'-----------------------------------------------------------'}}
+{% for key,value in json_output.items() %}
+{% for i in value %}
+
+{% for key2,value2 in i.items() %}
+{% for i2 in value2 %}
+
+{% if 'port-number' in i2.keys() and 'port-state' in i2.keys() %}
+{{ i2['port-number'].ljust(20)}}{{ i2['port-state']}}
+{% endif %}
+
+{% endfor %}
+{% endfor %}
+
+{% endfor %}
+{% endfor %}
+
diff --git a/src/CLI/renderer/templates/ptp_tp_show.j2 b/src/CLI/renderer/templates/ptp_tp_show.j2
new file mode 100755
index 0000000000..12013673b5
--- /dev/null
+++ b/src/CLI/renderer/templates/ptp_tp_show.j2
@@ -0,0 +1,30 @@
+{{'-----------------------------------------------------------'}}
+{{'Attribute'.ljust(20)}} {{'Value/State'}}
+{{'-----------------------------------------------------------'}}
+{% for key,value in json_output.items() %}
+{% if 'current-utc-offset-valid' in value.keys() %}
+{{ 'Curr UTC Offset Vld'.ljust(20)}} {{ value['current-utc-offset-valid']}}
+{% endif %}
+{% if 'current-utc-offset' in value.keys() %}
+{{ 'Curr UTC Offset'.ljust(20)}} {{ value['current-utc-offset']}}
+{% endif %}
+{% if 'leap59' in value.keys() %}
+{{ 'Leap59'.ljust(20)}} {{ value['leap59']}}
+{% endif %}
+{% if 'leap61' in value.keys() %}
+{{ 'Leap61'.ljust(20)}} {{ value['leap61']}}
+{% endif %}
+{% if 'time-traceable' in value.keys() %}
+{{ 'Time Traceable'.ljust(20)}} {{ value['time-traceable']}}
+{% endif %}
+{% if 'frequency-traceable' in value.keys() %}
+{{ 'Freq Traceable'.ljust(20)}} {{ value['frequency-traceable']}}
+{% endif %}
+{% if 'ptp-timescale' in value.keys() %}
+{{ 'PTP Timescale'.ljust(20)}} {{ value['ptp-timescale']}}
+{% endif %}
+{% if 'time-source' in value.keys() %}
+{{ 'Time Source'.ljust(20)}} {{ value['time-source']}}
+{% endif %}
+{% endfor %}
+
diff --git a/src/cvl/schema/sonic-mgmt-interface.yang b/src/cvl/schema/sonic-mgmt-interface.yang
new file mode 100644
index 0000000000..0095b9f6b4
--- /dev/null
+++ b/src/cvl/schema/sonic-mgmt-interface.yang
@@ -0,0 +1,55 @@
+module sonic-mgmt-interface {
+ namespace "http://github.com/Azure/sonic-mgmt-interface";
+ prefix sint;
+
+ import ietf-yang-types {
+ prefix yang;
+ }
+
+ import ietf-inet-types {
+ prefix inet;
+ }
+
+ import sonic-common {
+ prefix scommon;
+ }
+
+ import sonic-mgmt-port {
+ prefix mgmtprt;
+ }
+
+ organization
+ "DELL";
+
+ contact
+ "DELL";
+
+ description
+ "SONIC MANAGEMENT INTERFACE";
+
+ revision 2019-07-02 {
+ description
+ "Initial revision.";
+ }
+
+ container sonic-mgmt-interface {
+ list MGMT_INTERFACE {
+ key "portname ip_prefix";
+
+ leaf portname{
+ type leafref {
+ path "/mgmtprt:sonic-mgmt-port/mgmtprt:MGMT_PORT/mgmtprt:ifname";
+ }
+ }
+
+ leaf ip_prefix {
+ mandatory true;
+ type inet:ip-prefix;
+
+ }
+ leaf gwaddr {
+ type inet:ip-prefix;
+ }
+ }
+ }
+}
diff --git a/src/cvl/schema/sonic-mgmt-port.yang b/src/cvl/schema/sonic-mgmt-port.yang
new file mode 100644
index 0000000000..dec56e1e78
--- /dev/null
+++ b/src/cvl/schema/sonic-mgmt-port.yang
@@ -0,0 +1,66 @@
+module sonic-mgmt-port {
+ namespace "http://github.com/Azure/sonic-mgmt-port";
+ prefix prt;
+
+ import ietf-yang-types {
+ prefix yang;
+ }
+
+ import sonic-common {
+ prefix scommon;
+ }
+
+ organization
+ "DELL";
+
+ contact
+ "DELL";
+
+ description
+ "SONIC Management Interface";
+
+ revision 2019-09-17 {
+ description
+ "Initial revision.";
+ }
+
+
+ container sonic-mgmt-port {
+ list MGMT_PORT {
+ key "ifname";
+
+ leaf ifname {
+ type string {
+ pattern "eth([1-3][0-9]{3}|[1-9][0-9]{2}|[1-9][0-9]|[0-9])"{
+ error-message "Invalid interface name";
+ error-app-tag interface-name-invalid;
+ }
+ }
+ }
+
+ leaf speed {
+ type uint64;
+ }
+
+ leaf autoneg {
+ type boolean;
+ }
+
+ leaf alias {
+ type string;
+ }
+
+ leaf description {
+ type string;
+ }
+
+ leaf mtu{
+ type uint32;
+ }
+
+ leaf admin_status {
+ type scommon:admin-status;
+ }
+ }
+ }
+}
diff --git a/src/cvl/testdata/schema/sonic-spanning-tree.yang b/src/cvl/testdata/schema/sonic-spanning-tree.yang
index 2ff9f5e8c6..b8633a4991 100755
--- a/src/cvl/testdata/schema/sonic-spanning-tree.yang
+++ b/src/cvl/testdata/schema/sonic-spanning-tree.yang
@@ -15,8 +15,8 @@ module sonic-spanning-tree {
prefix spc;
}
- import sonic-pf-limits {
- prefix spf;
+ import sonic-vlan {
+ prefix svlan;
}
organization
@@ -33,17 +33,6 @@ module sonic-spanning-tree {
"Initial revision.";
}
- typedef interface-type {
- type union {
- type leafref {
- path "/prt:sonic-port/prt:PORT/prt:ifname";
- }
- type leafref {
- path "/spc:sonic-portchannel/spc:PORTCHANNEL/spc:name";
- }
- }
- }
-
grouping vlanModeAttr {
leaf forward_delay {
type uint8 {
@@ -108,7 +97,6 @@ module sonic-spanning-tree {
container sonic-spanning-tree {
- /*
container STP {
list STP_LIST {
key "keyleaf";
@@ -150,11 +138,8 @@ module sonic-spanning-tree {
}
leaf name {
- type string {
- pattern "Vlan(409[0-5]|40[0-8][0-9]|[1-3][0-9]{3}|[1-9][0-9]{2}|[1-9][0-9]|[1-9])" {
- error-message "Invalid Vlan name pattern";
- error-app-tag vlan-name-invalid;
- }
+ type leafref {
+ path "/svlan:sonic-vlan/svlan:VLAN/svlan:VLAN_LIST/svlan:name";
}
}
@@ -187,7 +172,9 @@ module sonic-spanning-tree {
}
leaf ifname {
- type interface-type;
+ type leafref {
+ path "../../../STP_INTF/STP_INTF_LIST/ifname";
+ }
}
uses interfaceAttr;
@@ -199,7 +186,14 @@ module sonic-spanning-tree {
key "ifname";
leaf ifname {
- type interface-type;
+ type union {
+ type leafref {
+ path "/prt:sonic-port/prt:PORT/prt:PORT_LIST/prt:ifname";
+ }
+ type leafref {
+ path "/spc:sonic-portchannel/spc:PORTCHANNEL/spc:PORTCHANNEL_LIST/spc:name";
+ }
+ }
}
leaf enabled {
@@ -214,6 +208,10 @@ module sonic-spanning-tree {
type boolean;
}
+ leaf bpdu_filter {
+ type boolean;
+ }
+
leaf bpdu_guard_do_disable {
type boolean;
}
@@ -240,142 +238,5 @@ module sonic-spanning-tree {
}
}
}
- */
-
- list STP {
- key "keyleaf";
-
- leaf keyleaf {
- type enumeration {
- enum GLOBAL;
- }
- }
-
- leaf mode {
- type enumeration {
- enum pvst;
- enum rpvst;
- enum mstp;
- enum rstp;
- }
- }
-
- leaf rootguard_timeout {
- type uint16 {
- range "5..600" {
- error-message "Invalid Root-guard Timeout value.";
- }
- }
- units seconds;
- default 30;
- }
-
- uses vlanModeAttr;
- }
-
- list STP_VLAN {
- key "name";
- /*must "./name = concat('Vlan', string(./vlanid))" {
- error-app-tag vlan-invalid;
- }*/
-
- leaf name {
- type string {
- pattern "Vlan(409[0-5]|40[0-8][0-9]|[1-3][0-9]{3}|[1-9][0-9]{2}|[1-9][0-9]|[1-9])" {
- error-message "Invalid Vlan name pattern";
- error-app-tag vlan-name-invalid;
- }
- }
- }
-
- leaf vlanid {
- mandatory true;
- type uint16 {
- range "1..4095" {
- error-message "Vlan ID out of range";
- error-app-tag vlanid-invalid;
- }
- }
- }
-
- leaf enabled {
- type boolean;
- }
-
- uses vlanModeAttr;
- }
-
- list STP_INTF {
- key "ifname";
-
- leaf ifname {
- type string;
- //type interface-type;
- }
-
- leaf enabled {
- type boolean;
- }
-
- leaf root_guard {
- type boolean;
- }
-
- leaf bpdu_guard {
- type boolean;
- }
-
- leaf bpdu_filter {
- type boolean;
- }
-
- leaf bpdu_guard_do_disable {
- type boolean;
- }
-
- leaf uplink_fast {
- type boolean;
- }
-
- leaf portfast {
- type boolean;
- }
-
- uses interfaceAttr;
-
- // For RPVST+
- leaf edge_port {
- //when ("../../STP/mode='rpvst'");
- type boolean;
- }
-
- leaf pt2pt_mac {
- //when ("../../STP/mode='rpvst'");
- type boolean;
- }
- }
-
- list STP_VLAN_INTF {
- key "vlan-name ifname";
-
- leaf vlan-name {
- /*type leafref {
- path "../../STP_VLAN/name";
- }*/
- type string {
- pattern "Vlan(409[0-5]|40[0-8][0-9]|[1-3][0-9]{3}|[1-9][0-9]{2}|[1-9][0-9]|[1-9])" {
- error-message "Invalid Vlan name pattern";
- error-app-tag vlan-name-invalid;
- }
- }
- }
-
- leaf ifname {
- type string;
- //type interface-type;
- }
-
- uses interfaceAttr;
- }
}
}
diff --git a/src/rest/Makefile b/src/rest/Makefile
index f4f4d335d7..0eb6901f44 100644
--- a/src/rest/Makefile
+++ b/src/rest/Makefile
@@ -36,6 +36,7 @@ REST_TEST_SRCS = $(shell find . -name '*_test.go')
# Source files affecting REST server
REST_SRCS := $(ALL_GO_SRCS) \
$(shell find $(TOPDIR)/models/yang -name '*.yang' | sort) \
+ $(shell find $(TOPDIR)/src/cvl/schema '*.yang' | sort) \
$(shell find $(TOPDIR)/models/openapi -name '*.yaml' | sort)
REST_GOPATH := $(GOPATH):$(abspath $(REST_BUILD_DIR)/dist)
diff --git a/src/translib/acl_app_test.go b/src/translib/acl_app_test.go
index d1773866ac..ee81023070 100644
--- a/src/translib/acl_app_test.go
+++ b/src/translib/acl_app_test.go
@@ -501,7 +501,7 @@ var bulkAclCreateJsonRequest string = "{\"acl-sets\":{\"acl-set\":[{\"name\":\"M
var bulkAclCreateJsonResponse string = "{\"openconfig-acl:acl\":{\"acl-sets\":{\"acl-set\":[{\"acl-entries\":{\"acl-entry\":[{\"actions\":{\"config\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"},\"state\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"}},\"config\":{\"sequence-id\":1},\"ipv4\":{\"config\":{\"destination-address\":\"21.1.1.1/32\",\"dscp\":1,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"11.1.1.1/32\"},\"state\":{\"destination-address\":\"21.1.1.1/32\",\"dscp\":1,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"11.1.1.1/32\"}},\"sequence-id\":1,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":1},\"transport\":{\"config\":{\"destination-port\":201,\"source-port\":101},\"state\":{\"destination-port\":201,\"source-port\":101}}},{\"actions\":{\"config\":{\"forwarding-action\":\"openconfig-acl:DROP\"},\"state\":{\"forwarding-action\":\"openconfig-acl:DROP\"}},\"config\":{\"sequence-id\":2},\"ipv4\":{\"config\":{\"destination-address\":\"21.1.1.2/32\",\"dscp\":2,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"11.1.1.2/32\"},\"state\":{\"destination-address\":\"21.1.1.2/32\",\"dscp\":2,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"11.1.1.2/32\"}},\"sequence-id\":2,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":2},\"transport\":{\"config\":{\"destination-port\":202,\"source-port\":102},\"state\":{\"destination-port\":202,\"source-port\":102}}},{\"actions\":{\"config\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"},\"state\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"}},\"config\":{\"sequence-id\":3},\"ipv4\":{\"config\":{\"destination-address\":\"21.1.1.3/32\",\"dscp\":3,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"11.1.1.3/32\"},\"state\":{\"destination-address\":\"21.1.1.3/32\",\"dscp\":3,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"11.1.1.3/32\"}},\"sequence-id\":3,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":3},\"transport\":{\"config\":{\"destination-port\":203,\"source-port\":103},\"state\":{\"destination-port\":203,\"source-port\":103}}},{\"actions\":{\"config\":{\"forwarding-action\":\"openconfig-acl:DROP\"},\"state\":{\"forwarding-action\":\"openconfig-acl:DROP\"}},\"config\":{\"sequence-id\":4},\"ipv4\":{\"config\":{\"destination-address\":\"21.1.1.4/32\",\"dscp\":4,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"11.1.1.4/32\"},\"state\":{\"destination-address\":\"21.1.1.4/32\",\"dscp\":4,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"11.1.1.4/32\"}},\"sequence-id\":4,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":4},\"transport\":{\"config\":{\"destination-port\":204,\"source-port\":104},\"state\":{\"destination-port\":204,\"source-port\":104}}},{\"actions\":{\"config\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"},\"state\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"}},\"config\":{\"sequence-id\":5},\"ipv4\":{\"config\":{\"destination-address\":\"21.1.1.5/32\",\"dscp\":5,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"11.1.1.5/32\"},\"state\":{\"destination-address\":\"21.1.1.5/32\",\"dscp\":5,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"11.1.1.5/32\"}},\"sequence-id\":5,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":5},\"transport\":{\"config\":{\"destination-port\":205,\"source-port\":105},\"state\":{\"destination-port\":205,\"source-port\":105}}}]},\"config\":{\"description\":\"Description for MyACL1\",\"name\":\"MyACL1\",\"type\":\"openconfig-acl:ACL_IPV4\"},\"name\":\"MyACL1\",\"state\":{\"description\":\"Description for MyACL1\",\"name\":\"MyACL1\",\"type\":\"openconfig-acl:ACL_IPV4\"},\"type\":\"openconfig-acl:ACL_IPV4\"},{\"acl-entries\":{\"acl-entry\":[{\"actions\":{\"config\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"},\"state\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"}},\"config\":{\"sequence-id\":1},\"ipv4\":{\"config\":{\"destination-address\":\"22.1.1.1/32\",\"dscp\":1,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"12.1.1.1/32\"},\"state\":{\"destination-address\":\"22.1.1.1/32\",\"dscp\":1,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"12.1.1.1/32\"}},\"sequence-id\":1,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":1},\"transport\":{\"config\":{\"destination-port\":201,\"source-port\":101},\"state\":{\"destination-port\":201,\"source-port\":101}}},{\"actions\":{\"config\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"},\"state\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"}},\"config\":{\"sequence-id\":2},\"ipv4\":{\"config\":{\"destination-address\":\"22.1.1.2/32\",\"dscp\":2,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"12.1.1.2/32\"},\"state\":{\"destination-address\":\"22.1.1.2/32\",\"dscp\":2,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"12.1.1.2/32\"}},\"sequence-id\":2,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":2},\"transport\":{\"config\":{\"destination-port\":202,\"source-port\":102},\"state\":{\"destination-port\":202,\"source-port\":102}}},{\"actions\":{\"config\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"},\"state\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"}},\"config\":{\"sequence-id\":3},\"ipv4\":{\"config\":{\"destination-address\":\"22.1.1.3/32\",\"dscp\":3,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"12.1.1.3/32\"},\"state\":{\"destination-address\":\"22.1.1.3/32\",\"dscp\":3,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"12.1.1.3/32\"}},\"sequence-id\":3,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":3},\"transport\":{\"config\":{\"destination-port\":203,\"source-port\":103},\"state\":{\"destination-port\":203,\"source-port\":103}}},{\"actions\":{\"config\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"},\"state\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"}},\"config\":{\"sequence-id\":4},\"ipv4\":{\"config\":{\"destination-address\":\"22.1.1.4/32\",\"dscp\":4,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"12.1.1.4/32\"},\"state\":{\"destination-address\":\"22.1.1.4/32\",\"dscp\":4,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"12.1.1.4/32\"}},\"sequence-id\":4,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":4},\"transport\":{\"config\":{\"destination-port\":204,\"source-port\":104},\"state\":{\"destination-port\":204,\"source-port\":104}}},{\"actions\":{\"config\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"},\"state\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"}},\"config\":{\"sequence-id\":5},\"ipv4\":{\"config\":{\"destination-address\":\"22.1.1.5/32\",\"dscp\":5,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"12.1.1.5/32\"},\"state\":{\"destination-address\":\"22.1.1.5/32\",\"dscp\":5,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"12.1.1.5/32\"}},\"sequence-id\":5,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":5},\"transport\":{\"config\":{\"destination-port\":205,\"source-port\":105},\"state\":{\"destination-port\":205,\"source-port\":105}}}]},\"config\":{\"description\":\"Description for MyACL2\",\"name\":\"MyACL2\",\"type\":\"openconfig-acl:ACL_IPV4\"},\"name\":\"MyACL2\",\"state\":{\"description\":\"Description for MyACL2\",\"name\":\"MyACL2\",\"type\":\"openconfig-acl:ACL_IPV4\"},\"type\":\"openconfig-acl:ACL_IPV4\"}]},\"interfaces\":{\"interface\":[{\"config\":{\"id\":\"Ethernet0\"},\"id\":\"Ethernet0\",\"ingress-acl-sets\":{\"ingress-acl-set\":[{\"acl-entries\":{\"acl-entry\":[{\"sequence-id\":1,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":1}},{\"sequence-id\":2,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":2}},{\"sequence-id\":3,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":3}},{\"sequence-id\":4,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":4}},{\"sequence-id\":5,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":5}}]},\"config\":{\"set-name\":\"MyACL1\",\"type\":\"openconfig-acl:ACL_IPV4\"},\"set-name\":\"MyACL1\",\"state\":{\"set-name\":\"MyACL1\",\"type\":\"openconfig-acl:ACL_IPV4\"},\"type\":\"openconfig-acl:ACL_IPV4\"}]},\"state\":{\"id\":\"Ethernet0\"}},{\"config\":{\"id\":\"Ethernet4\"},\"id\":\"Ethernet4\",\"ingress-acl-sets\":{\"ingress-acl-set\":[{\"acl-entries\":{\"acl-entry\":[{\"sequence-id\":1,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":1}},{\"sequence-id\":2,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":2}},{\"sequence-id\":3,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":3}},{\"sequence-id\":4,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":4}},{\"sequence-id\":5,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":5}}]},\"config\":{\"set-name\":\"MyACL2\",\"type\":\"openconfig-acl:ACL_IPV4\"},\"set-name\":\"MyACL2\",\"state\":{\"set-name\":\"MyACL2\",\"type\":\"openconfig-acl:ACL_IPV4\"},\"type\":\"openconfig-acl:ACL_IPV4\"}]},\"state\":{\"id\":\"Ethernet4\"}}]}}}"
-var oneAclCreateWithRulesJsonRequest string = "{ \"name\": \"MyACL3\", \"type\": \"ACL_IPV4\", \"config\": { \"name\": \"MyACL3\", \"type\": \"ACL_IPV4\", \"description\": \"Description for MyACL3\" }, \"acl-entries\": { \"acl-entry\": [ { \"sequence-id\": 1, \"config\": { \"sequence-id\": 1, \"description\": \"Description for MyACL3 Rule Seq 1\" }, \"ipv4\": { \"config\": { \"source-address\": \"11.1.1.1/32\", \"destination-address\": \"21.1.1.1/32\", \"dscp\": 1, \"protocol\": \"IP_TCP\" } }, \"transport\": { \"config\": { \"source-port\": 101, \"destination-port\": 201 } }, \"actions\": { \"config\": { \"forwarding-action\": \"ACCEPT\" } } }, { \"sequence-id\": 2, \"config\": { \"sequence-id\": 2, \"description\": \"Description for MyACL3 Rule Seq 2\" }, \"ipv4\": { \"config\": { \"source-address\": \"11.1.1.2/32\", \"destination-address\": \"21.1.1.2/32\", \"dscp\": 2, \"protocol\": \"IP_UDP\" } }, \"transport\": { \"config\": { \"source-port\": 102, \"destination-port\": 202 } }, \"actions\": { \"config\": { \"forwarding-action\": \"DROP\" } } }, { \"sequence-id\": 3, \"config\": { \"sequence-id\": 3, \"description\": \"Description for MyACL3 Rule Seq 3\" }, \"ipv4\": { \"config\": { \"source-address\": \"11.1.1.3/32\", \"destination-address\": \"21.1.1.3/32\", \"dscp\": 3, \"protocol\": \"IP_TCP\" } }, \"transport\": { \"config\": { \"source-port\": 103, \"destination-port\": 203 } }, \"actions\": { \"config\": { \"forwarding-action\": \"ACCEPT\" } } }, { \"sequence-id\": 4, \"config\": { \"sequence-id\": 4, \"description\": \"Description for MyACL3 Rule Seq 4\" }, \"ipv4\": { \"config\": { \"source-address\": \"11.1.1.4/32\", \"destination-address\": \"21.1.1.4/32\", \"dscp\": 4, \"protocol\": \"IP_TCP\" } }, \"transport\": { \"config\": { \"source-port\": 104, \"destination-port\": 204 } }, \"actions\": { \"config\": { \"forwarding-action\": \"DROP\" } } }, { \"sequence-id\": 5, \"config\": { \"sequence-id\": 5, \"description\": \"Description for MyACL3 Rule Seq 5\" }, \"ipv4\": { \"config\": { \"source-address\": \"11.1.1.5/32\", \"destination-address\": \"21.1.1.5/32\", \"dscp\": 5, \"protocol\": \"IP_TCP\" } }, \"transport\": { \"config\": { \"source-port\": 105, \"destination-port\": 205 } }, \"actions\": { \"config\": { \"forwarding-action\": \"ACCEPT\" } } } ] }}"
+var oneAclCreateWithRulesJsonRequest string = "{ \"openconfig-acl:acl-set\": [ { \"name\": \"MyACL3\", \"type\": \"ACL_IPV4\", \"config\": { \"name\": \"MyACL3\", \"type\": \"ACL_IPV4\", \"description\": \"Description for MyACL3\" }, \"acl-entries\": { \"acl-entry\": [ { \"sequence-id\": 1, \"config\": { \"sequence-id\": 1, \"description\": \"Description for MyACL3 Rule Seq 1\" }, \"ipv4\": { \"config\": { \"source-address\": \"11.1.1.1/32\", \"destination-address\": \"21.1.1.1/32\", \"dscp\": 1, \"protocol\": \"IP_TCP\" } }, \"transport\": { \"config\": { \"source-port\": 101, \"destination-port\": 201 } }, \"actions\": { \"config\": { \"forwarding-action\": \"ACCEPT\" } } }, { \"sequence-id\": 2, \"config\": { \"sequence-id\": 2, \"description\": \"Description for MyACL3 Rule Seq 2\" }, \"ipv4\": { \"config\": { \"source-address\": \"11.1.1.2/32\", \"destination-address\": \"21.1.1.2/32\", \"dscp\": 2, \"protocol\": \"IP_UDP\" } }, \"transport\": { \"config\": { \"source-port\": 102, \"destination-port\": 202 } }, \"actions\": { \"config\": { \"forwarding-action\": \"DROP\" } } }, { \"sequence-id\": 3, \"config\": { \"sequence-id\": 3, \"description\": \"Description for MyACL3 Rule Seq 3\" }, \"ipv4\": { \"config\": { \"source-address\": \"11.1.1.3/32\", \"destination-address\": \"21.1.1.3/32\", \"dscp\": 3, \"protocol\": \"IP_TCP\" } }, \"transport\": { \"config\": { \"source-port\": 103, \"destination-port\": 203 } }, \"actions\": { \"config\": { \"forwarding-action\": \"ACCEPT\" } } }, { \"sequence-id\": 4, \"config\": { \"sequence-id\": 4, \"description\": \"Description for MyACL3 Rule Seq 4\" }, \"ipv4\": { \"config\": { \"source-address\": \"11.1.1.4/32\", \"destination-address\": \"21.1.1.4/32\", \"dscp\": 4, \"protocol\": \"IP_TCP\" } }, \"transport\": { \"config\": { \"source-port\": 104, \"destination-port\": 204 } }, \"actions\": { \"config\": { \"forwarding-action\": \"DROP\" } } }, { \"sequence-id\": 5, \"config\": { \"sequence-id\": 5, \"description\": \"Description for MyACL3 Rule Seq 5\" }, \"ipv4\": { \"config\": { \"source-address\": \"11.1.1.5/32\", \"destination-address\": \"21.1.1.5/32\", \"dscp\": 5, \"protocol\": \"IP_TCP\" } }, \"transport\": { \"config\": { \"source-port\": 105, \"destination-port\": 205 } }, \"actions\": { \"config\": { \"forwarding-action\": \"ACCEPT\" } } } ] }} ] }"
var oneAclCreateWithRulesJsonResponse string = "{\"openconfig-acl:acl-set\":[{\"acl-entries\":{\"acl-entry\":[{\"actions\":{\"config\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"},\"state\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"}},\"config\":{\"sequence-id\":1},\"ipv4\":{\"config\":{\"destination-address\":\"21.1.1.1/32\",\"dscp\":1,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"11.1.1.1/32\"},\"state\":{\"destination-address\":\"21.1.1.1/32\",\"dscp\":1,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"11.1.1.1/32\"}},\"sequence-id\":1,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":1},\"transport\":{\"config\":{\"destination-port\":201,\"source-port\":101},\"state\":{\"destination-port\":201,\"source-port\":101}}},{\"actions\":{\"config\":{\"forwarding-action\":\"openconfig-acl:DROP\"},\"state\":{\"forwarding-action\":\"openconfig-acl:DROP\"}},\"config\":{\"sequence-id\":2},\"ipv4\":{\"config\":{\"destination-address\":\"21.1.1.2/32\",\"dscp\":2,\"protocol\":\"openconfig-packet-match-types:IP_UDP\",\"source-address\":\"11.1.1.2/32\"},\"state\":{\"destination-address\":\"21.1.1.2/32\",\"dscp\":2,\"protocol\":\"openconfig-packet-match-types:IP_UDP\",\"source-address\":\"11.1.1.2/32\"}},\"sequence-id\":2,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":2},\"transport\":{\"config\":{\"destination-port\":202,\"source-port\":102},\"state\":{\"destination-port\":202,\"source-port\":102}}},{\"actions\":{\"config\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"},\"state\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"}},\"config\":{\"sequence-id\":3},\"ipv4\":{\"config\":{\"destination-address\":\"21.1.1.3/32\",\"dscp\":3,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"11.1.1.3/32\"},\"state\":{\"destination-address\":\"21.1.1.3/32\",\"dscp\":3,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"11.1.1.3/32\"}},\"sequence-id\":3,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":3},\"transport\":{\"config\":{\"destination-port\":203,\"source-port\":103},\"state\":{\"destination-port\":203,\"source-port\":103}}},{\"actions\":{\"config\":{\"forwarding-action\":\"openconfig-acl:DROP\"},\"state\":{\"forwarding-action\":\"openconfig-acl:DROP\"}},\"config\":{\"sequence-id\":4},\"ipv4\":{\"config\":{\"destination-address\":\"21.1.1.4/32\",\"dscp\":4,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"11.1.1.4/32\"},\"state\":{\"destination-address\":\"21.1.1.4/32\",\"dscp\":4,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"11.1.1.4/32\"}},\"sequence-id\":4,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":4},\"transport\":{\"config\":{\"destination-port\":204,\"source-port\":104},\"state\":{\"destination-port\":204,\"source-port\":104}}},{\"actions\":{\"config\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"},\"state\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"}},\"config\":{\"sequence-id\":5},\"ipv4\":{\"config\":{\"destination-address\":\"21.1.1.5/32\",\"dscp\":5,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"11.1.1.5/32\"},\"state\":{\"destination-address\":\"21.1.1.5/32\",\"dscp\":5,\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"11.1.1.5/32\"}},\"sequence-id\":5,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":5},\"transport\":{\"config\":{\"destination-port\":205,\"source-port\":105},\"state\":{\"destination-port\":205,\"source-port\":105}}}]},\"config\":{\"description\":\"Description for MyACL3\",\"name\":\"MyACL3\",\"type\":\"openconfig-acl:ACL_IPV4\"},\"name\":\"MyACL3\",\"state\":{\"description\":\"Description for MyACL3\",\"name\":\"MyACL3\",\"type\":\"openconfig-acl:ACL_IPV4\"},\"type\":\"openconfig-acl:ACL_IPV4\"}]}"
@@ -512,7 +512,7 @@ var aclDescrUpdateJson string = "{\"openconfig-acl:description\":\"Verifying ACL
var requestOneRulePostJson string = "{\"sequence-id\": 8,\"config\": {\"sequence-id\": 8,\"description\": \"Description for MyACL5 Rule Seq 8\"},\"ipv4\": {\"config\": {\"source-address\": \"4.4.4.4/24\",\"destination-address\": \"5.5.5.5/24\",\"protocol\": \"IP_TCP\"}},\"transport\": {\"config\": {\"source-port\": 101,\"destination-port\": 100,\"tcp-flags\": [\"TCP_FIN\",\"TCP_ACK\"]}},\"actions\": {\"config\": {\"forwarding-action\": \"ACCEPT\"}}}"
-var requestOneRulePatchJson string = "{\"sequence-id\": 8,\"config\": {\"sequence-id\": 8,\"description\": \"Description for MyACL5 Rule Seq 8\"},\"ipv4\": {\"config\": {\"source-address\": \"4.8.4.8/24\",\"destination-address\": \"15.5.15.5/24\",\"protocol\": \"IP_L2TP\"}},\"transport\": {\"config\": {\"source-port\": 101,\"destination-port\": 100,\"tcp-flags\": [\"TCP_FIN\",\"TCP_ACK\",\"TCP_RST\",\"TCP_ECE\"]}},\"actions\": {\"config\": {\"forwarding-action\": \"ACCEPT\"}}}"
+var requestOneRulePatchJson string = "{ \"openconfig-acl:acl-entry\": [ {\"sequence-id\": 8,\"config\": {\"sequence-id\": 8,\"description\": \"Description for MyACL5 Rule Seq 8\"},\"ipv4\": {\"config\": {\"source-address\": \"4.8.4.8/24\",\"destination-address\": \"15.5.15.5/24\",\"protocol\": \"IP_L2TP\"}},\"transport\": {\"config\": {\"source-port\": 101,\"destination-port\": 100,\"tcp-flags\": [\"TCP_FIN\",\"TCP_ACK\",\"TCP_RST\",\"TCP_ECE\"]}},\"actions\": {\"config\": {\"forwarding-action\": \"ACCEPT\"}}} ] }"
var responseOneRuleJson string = "{\"openconfig-acl:acl-entry\":[{\"actions\":{\"config\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"},\"state\":{\"forwarding-action\":\"openconfig-acl:ACCEPT\"}},\"config\":{\"sequence-id\":8},\"ipv4\":{\"config\":{\"destination-address\":\"5.5.5.5/24\",\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"4.4.4.4/24\"},\"state\":{\"destination-address\":\"5.5.5.5/24\",\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"4.4.4.4/24\"}},\"sequence-id\":8,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":8},\"transport\":{\"config\":{\"destination-port\":100,\"source-port\":101,\"tcp-flags\":[\"openconfig-packet-match-types:TCP_FIN\",\"openconfig-packet-match-types:TCP_ACK\"]},\"state\":{\"destination-port\":100,\"source-port\":101,\"tcp-flags\":[\"openconfig-packet-match-types:TCP_FIN\",\"openconfig-packet-match-types:TCP_ACK\"]}}}]}"
@@ -526,7 +526,7 @@ var ingressAclSetCreateJsonResponse string = "{\"openconfig-acl:ingress-acl-set\
var egressAclSetCreateJsonResponse string = "{\"openconfig-acl:egress-acl-set\":[{\"acl-entries\":{\"acl-entry\":[{\"sequence-id\":8,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":8}}]},\"config\":{\"set-name\":\"MyACL5\",\"type\":\"openconfig-acl:ACL_IPV4\"},\"set-name\":\"MyACL5\",\"state\":{\"set-name\":\"MyACL5\",\"type\":\"openconfig-acl:ACL_IPV4\"},\"type\":\"openconfig-acl:ACL_IPV4\"}]}"
-var replaceMultiRulesWithOneRuleJsonRequest string = "{\"name\": \"MyACL3\",\"type\": \"ACL_IPV4\",\"config\": {\"name\": \"MyACL3\",\"type\": \"ACL_IPV4\",\"description\": \"Description for MyACL3\"},\"acl-entries\": {\"acl-entry\": [{\"sequence-id\": 8,\"config\": {\"sequence-id\": 8,\"description\": \"Description for MyACL3 Rule Seq 8\"},\"ipv4\": {\"config\": {\"source-address\": \"81.1.1.1/32\",\"destination-address\": \"91.1.1.1/32\",\"protocol\": \"IP_TCP\"}},\"transport\": {\"config\": {\"source-port\": \"801..811\",\"destination-port\": \"901..921\"}},\"actions\": {\"config\": {\"forwarding-action\": \"REJECT\"}}}]}}"
+var replaceMultiRulesWithOneRuleJsonRequest string = "{ \"openconfig-acl:acl-set\": [ {\"name\": \"MyACL3\",\"type\": \"ACL_IPV4\",\"config\": {\"name\": \"MyACL3\",\"type\": \"ACL_IPV4\",\"description\": \"Description for MyACL3\"},\"acl-entries\": {\"acl-entry\": [{\"sequence-id\": 8,\"config\": {\"sequence-id\": 8,\"description\": \"Description for MyACL3 Rule Seq 8\"},\"ipv4\": {\"config\": {\"source-address\": \"81.1.1.1/32\",\"destination-address\": \"91.1.1.1/32\",\"protocol\": \"IP_TCP\"}},\"transport\": {\"config\": {\"source-port\": \"801..811\",\"destination-port\": \"901..921\"}},\"actions\": {\"config\": {\"forwarding-action\": \"REJECT\"}}}]}} ] }"
var replaceMultiRulesWithOneRuleJsonResponse string = "{\"openconfig-acl:acl-set\":[{\"acl-entries\":{\"acl-entry\":[{\"actions\":{\"config\":{\"forwarding-action\":\"openconfig-acl:DROP\"},\"state\":{\"forwarding-action\":\"openconfig-acl:DROP\"}},\"config\":{\"sequence-id\":8},\"ipv4\":{\"config\":{\"destination-address\":\"91.1.1.1/32\",\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"81.1.1.1/32\"},\"state\":{\"destination-address\":\"91.1.1.1/32\",\"protocol\":\"openconfig-packet-match-types:IP_TCP\",\"source-address\":\"81.1.1.1/32\"}},\"sequence-id\":8,\"state\":{\"matched-octets\":\"0\",\"matched-packets\":\"0\",\"sequence-id\":8},\"transport\":{\"config\":{\"destination-port\":\"901-921\",\"source-port\":\"801-811\"},\"state\":{\"destination-port\":\"901-921\",\"source-port\":\"801-811\"}}}]},\"config\":{\"description\":\"Description for MyACL3\",\"name\":\"MyACL3\",\"type\":\"openconfig-acl:ACL_IPV4\"},\"name\":\"MyACL3\",\"state\":{\"description\":\"Description for MyACL3\",\"name\":\"MyACL3\",\"type\":\"openconfig-acl:ACL_IPV4\"},\"type\":\"openconfig-acl:ACL_IPV4\"}]}"
diff --git a/src/translib/stp_app.go b/src/translib/stp_app.go
index e1a6976b78..a28739ebc8 100644
--- a/src/translib/stp_app.go
+++ b/src/translib/stp_app.go
@@ -1,9 +1,21 @@
-///////////////////////////////////////////////////////////////////////
-//
-// Copyright 2019 Broadcom. All rights reserved.
-// The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
-//
-///////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
+// //
+// Copyright 2019 Broadcom. The term Broadcom refers to Broadcom Inc. and/or //
+// its subsidiaries. //
+// //
+// Licensed under the Apache License, Version 2.0 (the "License"); //
+// you may not use this file except in compliance with the License. //
+// You may obtain a copy of the License at //
+// //
+// http://www.apache.org/licenses/LICENSE-2.0 //
+// //
+// Unless required by applicable law or agreed to in writing, software //
+// distributed under the License is distributed on an "AS IS" BASIS, //
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
+// See the License for the specific language governing permissions and //
+// limitations under the License. //
+// //
+////////////////////////////////////////////////////////////////////////////////
package translib
@@ -23,17 +35,17 @@ import (
)
const (
- GLOBAL_TABLE = "STP"
- VLAN_TABLE = "STP_VLAN"
- VLAN_INTF_TABLE = "STP_VLAN_INTF"
- INTF_TABLE = "STP_INTF"
- VLAN_OPER_TABLE = "_STP_VLAN_TABLE"
- VLAN_INTF_OPER_TABLE = "_STP_VLAN_INTF_TABLE"
- INTF_OPER_TABLE = "_STP_INTF_TABLE"
- STP_MODE = "mode"
- OC_STP_APP_MODULE_NAME = "/openconfig-spanning-tree:stp"
- OC_STP_YANG_PATH_PREFIX = "/device/stp"
- PVST_MAX_INSTANCES = 255
+ STP_GLOBAL_TABLE = "STP"
+ STP_VLAN_TABLE = "STP_VLAN"
+ STP_VLAN_INTF_TABLE = "STP_VLAN_INTF"
+ STP_INTF_TABLE = "STP_INTF"
+ STP_VLAN_OPER_TABLE = "_STP_VLAN_TABLE"
+ STP_VLAN_INTF_OPER_TABLE = "_STP_VLAN_INTF_TABLE"
+ STP_INTF_OPER_TABLE = "_STP_INTF_TABLE"
+ STP_MODE = "mode"
+ OC_STP_APP_MODULE_NAME = "/openconfig-spanning-tree:stp"
+ OC_STP_YANG_PATH_PREFIX = "/device/stp"
+ PVST_MAX_INSTANCES = 255
STP_DEFAULT_ROOT_GUARD_TIMEOUT = "30"
STP_DEFAULT_FORWARD_DELAY = "15"
@@ -73,7 +85,7 @@ func init() {
&appInfo{appType: reflect.TypeOf(StpApp{}),
ygotRootType: reflect.TypeOf(ocbinds.OpenconfigSpanningTree_Stp{}),
isNative: false,
- tablesToWatch: []*db.TableSpec{&db.TableSpec{Name: GLOBAL_TABLE}, &db.TableSpec{Name: VLAN_TABLE}, &db.TableSpec{Name: VLAN_INTF_TABLE}, &db.TableSpec{Name: INTF_TABLE}}})
+ tablesToWatch: []*db.TableSpec{&db.TableSpec{Name: STP_GLOBAL_TABLE}, &db.TableSpec{Name: STP_VLAN_TABLE}, &db.TableSpec{Name: STP_VLAN_INTF_TABLE}, &db.TableSpec{Name: STP_INTF_TABLE}}})
if err != nil {
log.Fatal("Register STP app module with App Interface failed with error=", err)
@@ -91,14 +103,14 @@ func (app *StpApp) initialize(data appData) {
app.ygotRoot = data.ygotRoot
app.ygotTarget = data.ygotTarget
- app.globalTable = &db.TableSpec{Name: GLOBAL_TABLE}
- app.vlanTable = &db.TableSpec{Name: VLAN_TABLE}
- app.vlanIntfTable = &db.TableSpec{Name: VLAN_INTF_TABLE}
- app.interfaceTable = &db.TableSpec{Name: INTF_TABLE}
+ app.globalTable = &db.TableSpec{Name: STP_GLOBAL_TABLE}
+ app.vlanTable = &db.TableSpec{Name: STP_VLAN_TABLE}
+ app.vlanIntfTable = &db.TableSpec{Name: STP_VLAN_INTF_TABLE}
+ app.interfaceTable = &db.TableSpec{Name: STP_INTF_TABLE}
- app.vlanOperTable = &db.TableSpec{Name: VLAN_OPER_TABLE}
- app.vlanIntfOperTable = &db.TableSpec{Name: VLAN_INTF_OPER_TABLE}
- app.intfOperTable = &db.TableSpec{Name: INTF_OPER_TABLE}
+ app.vlanOperTable = &db.TableSpec{Name: STP_VLAN_OPER_TABLE}
+ app.vlanIntfOperTable = &db.TableSpec{Name: STP_VLAN_INTF_OPER_TABLE}
+ app.intfOperTable = &db.TableSpec{Name: STP_INTF_OPER_TABLE}
app.globalInfo = db.Value{Field: map[string]string{}}
app.vlanTableMap = make(map[string]db.Value)
@@ -129,6 +141,7 @@ func (app *StpApp) translateUpdate(d *db.DB) ([]db.WatchKeys, error) {
var keys []db.WatchKeys
log.Info("translateUpdate:stp:path =", app.pathInfo.Template)
+ keys, err = app.translateCRUCommon(d, UPDATE)
return keys, err
}
@@ -137,6 +150,7 @@ func (app *StpApp) translateReplace(d *db.DB) ([]db.WatchKeys, error) {
var keys []db.WatchKeys
log.Info("translateReplace:stp:path =", app.pathInfo.Template)
+ keys, err = app.translateCRUCommon(d, REPLACE)
return keys, err
}
@@ -179,7 +193,10 @@ func (app *StpApp) processUpdate(d *db.DB) (SetResponse, error) {
var err error
var resp SetResponse
- err = errors.New("Not Implemented")
+ if err = app.processCommon(d, UPDATE); err != nil {
+ log.Error(err)
+ resp = SetResponse{ErrSrc: AppErr}
+ }
return resp, err
}
@@ -187,7 +204,10 @@ func (app *StpApp) processReplace(d *db.DB) (SetResponse, error) {
var err error
var resp SetResponse
- err = errors.New("Not Implemented")
+ if err = app.processCommon(d, REPLACE); err != nil {
+ log.Error(err)
+ resp = SetResponse{ErrSrc: AppErr}
+ }
return resp, err
}
@@ -234,9 +254,9 @@ func (app *StpApp) translateCRUCommon(d *db.DB, opcode int) ([]db.WatchKeys, err
var keys []db.WatchKeys
log.Info("translateCRUCommon:STP:path =", app.pathInfo.Template)
- app.convertOCStpGlobalConfToInternal()
- app.convertOCPvstToInternal()
- app.convertOCRpvstConfToInternal()
+ app.convertOCStpGlobalConfToInternal(opcode)
+ app.convertOCPvstToInternal(opcode)
+ app.convertOCRpvstConfToInternal(opcode)
app.convertOCStpInterfacesToInternal()
return keys, err
@@ -261,17 +281,22 @@ func (app *StpApp) processCommon(d *db.DB, opcode int) error {
if isSubtreeRequest(app.pathInfo.Template, "/openconfig-spanning-tree:stp/global") {
switch opcode {
case CREATE:
- err = app.setStpGlobalConfigInDB(d)
- if err != nil {
- return err
- }
- err = app.enableStpForInterfaces(d)
- if err != nil {
- return err
+ err = app.enableStpMode(d)
+ case REPLACE, UPDATE:
+ mode, _ := app.getStpModeFromConfigDB(d)
+ if *app.ygotTarget == stp.Global || *app.ygotTarget == stp.Global.Config || targetUriPath == "/openconfig-spanning-tree:stp/global/config/enabled-protocol" {
+ if len(mode) == 0 {
+ err = app.enableStpMode(d)
+ } else {
+ if mode != app.convertOCStpModeToInternal(stp.Global.Config.EnabledProtocol[0]) {
+ return tlerr.InvalidArgs("STP mode is configured as %s", mode)
+ } else {
+ app.handleStpGlobalFieldsUpdation(d, opcode)
+ }
+ }
+ } else {
+ app.handleStpGlobalFieldsUpdation(d, opcode)
}
- err = app.enableStpForVlans(d)
- case REPLACE:
- case UPDATE:
case DELETE:
if *app.ygotTarget == stp.Global || *app.ygotTarget == stp.Global.Config || targetUriPath == "/openconfig-spanning-tree:stp/global/config/enabled-protocol" {
if app.pathInfo.Template == "/openconfig-spanning-tree:stp/global/config/enabled-protocol{}" {
@@ -306,19 +331,10 @@ func (app *StpApp) processCommon(d *db.DB, opcode int) error {
for intfId, _ := range pvstVlan.Interfaces.Interface {
pvstVlanIntf := pvstVlan.Interfaces.Interface[intfId]
switch opcode {
- case CREATE:
- if *app.ygotTarget == pvstVlanIntf {
- err = app.setRpvstVlanInterfaceDataInDB(d, true)
- } else {
- err = app.setRpvstVlanInterfaceDataInDB(d, false)
- }
- case REPLACE:
- case UPDATE:
- case DELETE:
- if *app.ygotTarget == pvstVlanIntf {
- err = d.DeleteEntry(app.vlanIntfTable, asKey(vlanName, intfId))
- } else {
- err = app.handleVlanInterfaceFieldsDeletion(d, vlanName, intfId)
+ case CREATE, REPLACE, UPDATE, DELETE:
+ err = app.handleRpvstCRUDOperationsAtVlanInterfaceLevel(d, opcode, vlanName, intfId, pvstVlan, pvstVlanIntf)
+ if err != nil {
+ return err
}
case GET:
err = app.convertDBRpvstVlanInterfaceToInternal(d, vlanName, intfId, asKey(vlanName, intfId), true)
@@ -334,32 +350,10 @@ func (app *StpApp) processCommon(d *db.DB, opcode int) error {
} else {
isInterfacesSubtree := isSubtreeRequest(app.pathInfo.Template, "/openconfig-spanning-tree:stp/openconfig-spanning-tree-ext:pvst/vlan{}/interfaces")
switch opcode {
- case CREATE:
- if *app.ygotTarget == pvstVlan {
- log.Info("ygotTarget is pvstVlan")
- err = app.setRpvstVlanDataInDB(d, true)
- if err != nil {
- return err
- }
- err = app.setRpvstVlanInterfaceDataInDB(d, true)
- } else if isInterfacesSubtree {
- err = app.setRpvstVlanInterfaceDataInDB(d, true)
- } else {
- err = d.SetEntry(app.vlanTable, asKey(vlanName), app.vlanTableMap[vlanName])
- }
- case REPLACE:
- case UPDATE:
- case DELETE:
- if *app.ygotTarget == pvstVlan {
- err = d.DeleteKeys(app.vlanIntfTable, asKey(vlanName+TABLE_SEPARATOR+"*"))
- if err != nil {
- return err
- }
- err = d.DeleteEntry(app.vlanTable, asKey(vlanName))
- } else if isInterfacesSubtree {
- err = d.DeleteKeys(app.vlanIntfTable, asKey(vlanName+TABLE_SEPARATOR+"*"))
- } else {
- err = app.handleVlanFieldsDeletion(d, vlanName)
+ case CREATE, REPLACE, UPDATE, DELETE:
+ err = app.handleRpvstCRUDOperationsAtVlanLevel(d, opcode, vlanName, isInterfacesSubtree, stp.Pvst, pvstVlan)
+ if err != nil {
+ return err
}
case GET:
err = app.convertDBRpvstVlanConfigToInternal(d, asKey(vlanName))
@@ -373,6 +367,18 @@ func (app *StpApp) processCommon(d *db.DB, opcode int) error {
}
} else {
// Handle top PVST
+ switch opcode {
+ case CREATE, REPLACE, UPDATE, DELETE:
+ log.Infof("Implementation in progress for URL: %s", app.pathInfo.Template)
+ return tlerr.NotSupported("Implementation in progress")
+ case GET:
+ ygot.BuildEmptyTree(stp.Pvst)
+ err = app.convertDBRpvstVlanConfigToInternal(d, db.Key{})
+ if err != nil {
+ return err
+ }
+ app.convertInternalToOCPvstVlan("", stp.Pvst, nil)
+ }
}
} else if isSubtreeRequest(app.pathInfo.Template, "/openconfig-spanning-tree:stp/rapid-pvst") {
mode, _ := app.getStpModeFromConfigDB(d)
@@ -388,19 +394,10 @@ func (app *StpApp) processCommon(d *db.DB, opcode int) error {
for intfId, _ := range rpvstVlanConf.Interfaces.Interface {
rpvstVlanIntfConf := rpvstVlanConf.Interfaces.Interface[intfId]
switch opcode {
- case CREATE:
- if *app.ygotTarget == rpvstVlanIntfConf {
- err = app.setRpvstVlanInterfaceDataInDB(d, true)
- } else {
- err = app.setRpvstVlanInterfaceDataInDB(d, false)
- }
- case REPLACE:
- case UPDATE:
- case DELETE:
- if *app.ygotTarget == rpvstVlanIntfConf {
- err = d.DeleteEntry(app.vlanIntfTable, asKey(vlanName, intfId))
- } else {
- err = app.handleVlanInterfaceFieldsDeletion(d, vlanName, intfId)
+ case CREATE, REPLACE, UPDATE, DELETE:
+ err = app.handleRpvstCRUDOperationsAtVlanInterfaceLevel(d, opcode, vlanName, intfId, rpvstVlanConf, rpvstVlanIntfConf)
+ if err != nil {
+ return err
}
case GET:
err = app.convertDBRpvstVlanInterfaceToInternal(d, vlanName, intfId, asKey(vlanName, intfId), true)
@@ -416,31 +413,10 @@ func (app *StpApp) processCommon(d *db.DB, opcode int) error {
} else {
isInterfacesSubtree := isSubtreeRequest(app.pathInfo.Template, "/openconfig-spanning-tree:stp/rapid-pvst/vlan{}/interfaces")
switch opcode {
- case CREATE:
- if *app.ygotTarget == rpvstVlanConf {
- err = app.setRpvstVlanDataInDB(d, true)
- if err != nil {
- return err
- }
- err = app.setRpvstVlanInterfaceDataInDB(d, true)
- } else if isInterfacesSubtree {
- err = app.setRpvstVlanInterfaceDataInDB(d, true)
- } else {
- err = d.SetEntry(app.vlanTable, asKey(vlanName), app.vlanTableMap[vlanName])
- }
- case REPLACE:
- case UPDATE:
- case DELETE:
- if *app.ygotTarget == rpvstVlanConf {
- err = d.DeleteKeys(app.vlanIntfTable, asKey(vlanName+TABLE_SEPARATOR+"*"))
- if err != nil {
- return err
- }
- err = d.DeleteEntry(app.vlanTable, asKey(vlanName))
- } else if isInterfacesSubtree {
- err = d.DeleteKeys(app.vlanIntfTable, asKey(vlanName+TABLE_SEPARATOR+"*"))
- } else {
- err = app.handleVlanFieldsDeletion(d, vlanName)
+ case CREATE, REPLACE, UPDATE, DELETE:
+ err = app.handleRpvstCRUDOperationsAtVlanLevel(d, opcode, vlanName, isInterfacesSubtree, stp.RapidPvst, rpvstVlanConf)
+ if err != nil {
+ return err
}
case GET:
err = app.convertDBRpvstVlanConfigToInternal(d, asKey(vlanName))
@@ -454,7 +430,18 @@ func (app *StpApp) processCommon(d *db.DB, opcode int) error {
}
} else {
// Handle both rapid-pvst and rapid-pvst/vlan
- err = app.processCommonRpvstVlanToplevelPath(d, stp, opcode)
+ switch opcode {
+ case CREATE, REPLACE, UPDATE, DELETE:
+ log.Infof("Implementation in progress for URL: %s", app.pathInfo.Template)
+ return tlerr.NotSupported("Implementation in progress")
+ case GET:
+ ygot.BuildEmptyTree(stp.RapidPvst)
+ err = app.convertDBRpvstVlanConfigToInternal(d, db.Key{})
+ if err != nil {
+ return err
+ }
+ app.convertInternalToOCRpvstVlanConfig("", stp.RapidPvst, nil)
+ }
}
} else if isSubtreeRequest(app.pathInfo.Template, "/openconfig-spanning-tree:stp/mstp") {
mode, _ := app.getStpModeFromConfigDB(d)
@@ -467,13 +454,19 @@ func (app *StpApp) processCommon(d *db.DB, opcode int) error {
intfData := stp.Interfaces.Interface[intfId]
switch opcode {
case CREATE:
+ err = app.setStpInterfacesDataInDB(d, true)
+ case REPLACE:
if *app.ygotTarget == intfData {
+ err = d.DeleteEntry(app.interfaceTable, asKey(intfId))
+ if err != nil {
+ return err
+ }
err = app.setStpInterfacesDataInDB(d, true)
} else {
err = app.setStpInterfacesDataInDB(d, false)
}
- case REPLACE:
case UPDATE:
+ err = app.setStpInterfacesDataInDB(d, false)
case DELETE:
if *app.ygotTarget == intfData {
err = d.DeleteEntry(app.interfaceTable, asKey(intfId))
@@ -490,37 +483,76 @@ func (app *StpApp) processCommon(d *db.DB, opcode int) error {
}
}
} else {
+ switch opcode {
+ case CREATE, REPLACE, UPDATE, DELETE:
+ log.Infof("Implementation in progress for URL: %s", app.pathInfo.Template)
+ return tlerr.NotSupported("Implementation in progress")
+ case GET:
+ ygot.BuildEmptyTree(stp.Interfaces)
+ err = app.convertDBStpInterfacesToInternal(d, db.Key{})
+ if err != nil {
+ return err
+ }
+ app.convertInternalToOCStpInterfaces("", stp.Interfaces, nil)
+ }
}
} else if topmostPath {
switch opcode {
case CREATE:
+ err = app.enableStpMode(d)
+ if err != nil {
+ return err
+ }
+ err = app.setRpvstVlanDataInDB(d, true)
+ if err != nil {
+ return err
+ }
+ err = app.setRpvstVlanInterfaceDataInDB(d, true)
+ if err != nil {
+ return err
+ }
+ err = app.setStpInterfacesDataInDB(d, true)
+ case REPLACE:
+ err = app.disableStpMode(d)
+ if err != nil {
+ return err
+ }
+ err = app.enableStpMode(d)
+ if err != nil {
+ return err
+ }
+ err = app.setRpvstVlanDataInDB(d, true)
+ if err != nil {
+ return err
+ }
+ err = app.setRpvstVlanInterfaceDataInDB(d, true)
+ if err != nil {
+ return err
+ }
+ err = app.setStpInterfacesDataInDB(d, true)
case DELETE:
err = app.disableStpMode(d)
case GET:
ygot.BuildEmptyTree(stp)
//////////////////////
- ygot.BuildEmptyTree(stp.Global)
err = app.convertDBStpGlobalConfigToInternal(d)
if err != nil {
return err
}
app.convertInternalToOCStpGlobalConfig(stp.Global)
+ //////////////////////
+ err = app.convertDBRpvstVlanConfigToInternal(d, db.Key{})
+ if err != nil {
+ return err
+ }
stpMode := (&app.globalInfo).Get(STP_MODE)
switch stpMode {
case "pvst":
ygot.BuildEmptyTree(stp.Pvst)
- err = app.convertDBRpvstVlanConfigToInternal(d, db.Key{})
- if err != nil {
- return err
- }
app.convertInternalToOCPvstVlan("", stp.Pvst, nil)
case "rpvst":
ygot.BuildEmptyTree(stp.RapidPvst)
- err = app.convertDBRpvstVlanConfigToInternal(d, db.Key{})
- if err != nil {
- return err
- }
app.convertInternalToOCRpvstVlanConfig("", stp.RapidPvst, nil)
case "mstp":
}
@@ -551,6 +583,114 @@ func (app *StpApp) processCommonRpvstVlanToplevelPath(d *db.DB, stp *ocbinds.Ope
return err
}
+func (app *StpApp) handleRpvstCRUDOperationsAtVlanLevel(d *db.DB, opcode int, vlanName string, isInterfacesSubtree bool, mode interface{}, vlan interface{}) error {
+ var err error
+
+ log.Infof("handleRpvstCRUDOperationsAtVlanLevel --> Perform CRUD for %s", reflect.TypeOf(vlan).Elem().Name())
+ switch opcode {
+ case CREATE:
+ if *app.ygotTarget == vlan {
+ err = app.setRpvstVlanDataInDB(d, true)
+ if err != nil {
+ return err
+ }
+ err = app.setRpvstVlanInterfaceDataInDB(d, true)
+ } else if isInterfacesSubtree {
+ err = app.setRpvstVlanInterfaceDataInDB(d, true)
+ } else {
+ err = d.SetEntry(app.vlanTable, asKey(vlanName), app.vlanTableMap[vlanName])
+ }
+ case REPLACE:
+ if *app.ygotTarget == vlan {
+ err = d.DeleteKeys(app.vlanIntfTable, asKey(vlanName+TABLE_SEPARATOR+"*"))
+ if err != nil {
+ return err
+ }
+ err = d.DeleteEntry(app.vlanTable, asKey(vlanName))
+ if err != nil {
+ return err
+ }
+ err = app.setRpvstVlanDataInDB(d, true)
+ if err != nil {
+ return err
+ }
+ err = app.setRpvstVlanInterfaceDataInDB(d, true)
+ } else if isInterfacesSubtree {
+ err = d.DeleteKeys(app.vlanIntfTable, asKey(vlanName+TABLE_SEPARATOR+"*"))
+ if err != nil {
+ return err
+ }
+ err = app.setRpvstVlanInterfaceDataInDB(d, true)
+ } else {
+ err = d.SetEntry(app.vlanTable, asKey(vlanName), app.vlanTableMap[vlanName])
+ }
+ case UPDATE:
+ if *app.ygotTarget == vlan {
+ err = app.setRpvstVlanDataInDB(d, false)
+ if err != nil {
+ return err
+ }
+ err = app.setRpvstVlanInterfaceDataInDB(d, false)
+ } else if isInterfacesSubtree {
+ err = app.setRpvstVlanInterfaceDataInDB(d, false)
+ } else {
+ err = d.ModEntry(app.vlanTable, asKey(vlanName), app.vlanTableMap[vlanName])
+ }
+ case DELETE:
+ if *app.ygotTarget == vlan {
+ err = d.DeleteKeys(app.vlanIntfTable, asKey(vlanName+TABLE_SEPARATOR+"*"))
+ if err != nil {
+ return err
+ }
+ err = d.DeleteEntry(app.vlanTable, asKey(vlanName))
+ } else if isInterfacesSubtree {
+ err = d.DeleteKeys(app.vlanIntfTable, asKey(vlanName+TABLE_SEPARATOR+"*"))
+ } else {
+ err = app.handleVlanFieldsDeletion(d, vlanName)
+ }
+ }
+
+ return err
+}
+
+func (app *StpApp) handleRpvstCRUDOperationsAtVlanInterfaceLevel(d *db.DB, opcode int, vlanName string, intfId string, vlan interface{}, vlanIntf interface{}) error {
+ var err error
+
+ log.Infof("handleRpvstCRUDOperationsAtVlanInterfaceLevel --> Perform CRUD for %s", reflect.TypeOf(vlanIntf).Elem().Name())
+ switch opcode {
+ case CREATE:
+ if *app.ygotTarget == vlanIntf {
+ err = app.setRpvstVlanInterfaceDataInDB(d, true)
+ } else {
+ err = app.setRpvstVlanInterfaceDataInDB(d, false)
+ }
+ case REPLACE:
+ if *app.ygotTarget == vlanIntf {
+ err = d.DeleteEntry(app.vlanIntfTable, asKey(vlanName, intfId))
+ if err != nil {
+ return err
+ }
+ err = app.setRpvstVlanInterfaceDataInDB(d, true)
+ } else {
+ err = app.handleVlanInterfaceFieldsDeletion(d, vlanName, intfId)
+ if err != nil {
+ return err
+ }
+ err = app.setRpvstVlanInterfaceDataInDB(d, false)
+ }
+ case UPDATE:
+ err = app.setRpvstVlanInterfaceDataInDB(d, false)
+ case DELETE:
+ if *app.ygotTarget == vlanIntf {
+ err = d.DeleteEntry(app.vlanIntfTable, asKey(vlanName, intfId))
+ } else {
+ err = app.handleVlanInterfaceFieldsDeletion(d, vlanName, intfId)
+ }
+ }
+
+ return err
+}
+
///////////////// STP GLOBAL //////////////////////
func (app *StpApp) setStpGlobalConfigInDB(d *db.DB) error {
var err error
@@ -560,39 +700,42 @@ func (app *StpApp) setStpGlobalConfigInDB(d *db.DB) error {
return err
}
-func (app *StpApp) convertOCStpGlobalConfToInternal() {
+func (app *StpApp) convertOCStpGlobalConfToInternal(opcode int) {
stp := app.getAppRootObject()
+ setDefaultFlag := (opcode == CREATE || opcode == REPLACE)
if stp != nil {
if stp.Global != nil && stp.Global.Config != nil {
if stp.Global.Config.BridgePriority != nil {
(&app.globalInfo).Set("priority", strconv.Itoa(int(*stp.Global.Config.BridgePriority)))
- } else {
+ } else if setDefaultFlag {
(&app.globalInfo).Set("priority", STP_DEFAULT_BRIDGE_PRIORITY)
}
if stp.Global.Config.ForwardingDelay != nil {
(&app.globalInfo).Set("forward_delay", strconv.Itoa(int(*stp.Global.Config.ForwardingDelay)))
- } else {
+ } else if setDefaultFlag {
(&app.globalInfo).Set("forward_delay", STP_DEFAULT_FORWARD_DELAY)
}
if stp.Global.Config.HelloTime != nil {
(&app.globalInfo).Set("hello_time", strconv.Itoa(int(*stp.Global.Config.HelloTime)))
- } else {
+ } else if setDefaultFlag {
(&app.globalInfo).Set("hello_time", STP_DEFAULT_HELLO_INTERVAL)
}
if stp.Global.Config.MaxAge != nil {
(&app.globalInfo).Set("max_age", strconv.Itoa(int(*stp.Global.Config.MaxAge)))
- } else {
+ } else if setDefaultFlag {
(&app.globalInfo).Set("max_age", STP_DEFAULT_MAX_AGE)
}
if stp.Global.Config.RootguardTimeout != nil {
(&app.globalInfo).Set("rootguard_timeout", strconv.Itoa(int(*stp.Global.Config.RootguardTimeout)))
- } else {
+ } else if setDefaultFlag {
(&app.globalInfo).Set("rootguard_timeout", STP_DEFAULT_ROOT_GUARD_TIMEOUT)
}
- mode := app.convertOCStpModeToInternal(stp.Global.Config.EnabledProtocol[0])
- if len(mode) > 0 {
- (&app.globalInfo).Set(STP_MODE, mode)
+ if len(stp.Global.Config.EnabledProtocol) > 0 {
+ mode := app.convertOCStpModeToInternal(stp.Global.Config.EnabledProtocol[0])
+ if len(mode) > 0 {
+ (&app.globalInfo).Set(STP_MODE, mode)
+ }
}
log.Infof("convertOCStpGlobalConfToInternal -- Internal Stp global config: %v", app.globalInfo)
@@ -615,6 +758,8 @@ func (app *StpApp) convertInternalToOCStpGlobalConfig(stpGlobal *ocbinds.Opencon
var priority uint32
var forDelay, helloTime, maxAge uint8
var rootGTimeout uint16
+ ygot.BuildEmptyTree(stpGlobal)
+
if stpGlobal.Config != nil {
stpGlobal.Config.EnabledProtocol = app.convertInternalStpModeToOC((&app.globalInfo).Get(STP_MODE))
@@ -651,8 +796,9 @@ func (app *StpApp) convertInternalToOCStpGlobalConfig(stpGlobal *ocbinds.Opencon
}
///////////////// RPVST //////////////////////
-func (app *StpApp) convertOCRpvstConfToInternal() {
+func (app *StpApp) convertOCRpvstConfToInternal(opcode int) {
stp := app.getAppRootObject()
+ setDefaultFlag := (opcode == CREATE || opcode == REPLACE)
if stp != nil && stp.RapidPvst != nil && len(stp.RapidPvst.Vlan) > 0 {
for vlanId, _ := range stp.RapidPvst.Vlan {
vlanName := "Vlan" + strconv.Itoa(int(vlanId))
@@ -663,22 +809,22 @@ func (app *StpApp) convertOCRpvstConfToInternal() {
(&dbVal).Set("vlanid", strconv.Itoa(int(vlanId)))
if rpvstVlanConf.Config.BridgePriority != nil {
(&dbVal).Set("priority", strconv.Itoa(int(*rpvstVlanConf.Config.BridgePriority)))
- } else {
+ } else if setDefaultFlag {
(&dbVal).Set("priority", "32768")
}
if rpvstVlanConf.Config.ForwardingDelay != nil {
(&dbVal).Set("forward_delay", strconv.Itoa(int(*rpvstVlanConf.Config.ForwardingDelay)))
- } else {
+ } else if setDefaultFlag {
(&dbVal).Set("forward_delay", "15")
}
if rpvstVlanConf.Config.HelloTime != nil {
(&dbVal).Set("hello_time", strconv.Itoa(int(*rpvstVlanConf.Config.HelloTime)))
- } else {
+ } else if setDefaultFlag {
(&dbVal).Set("hello_time", "2")
}
if rpvstVlanConf.Config.MaxAge != nil {
(&dbVal).Set("max_age", strconv.Itoa(int(*rpvstVlanConf.Config.MaxAge)))
- } else {
+ } else if setDefaultFlag {
(&dbVal).Set("max_age", "20")
}
if rpvstVlanConf.Config.SpanningTreeEnable != nil {
@@ -687,7 +833,7 @@ func (app *StpApp) convertOCRpvstConfToInternal() {
} else {
(&dbVal).Set("enabled", "false")
}
- } else {
+ } else if setDefaultFlag {
(&dbVal).Set("enabled", "false")
}
}
@@ -698,16 +844,14 @@ func (app *StpApp) convertOCRpvstConfToInternal() {
app.vlanIntfTableMap[vlanName][intfId] = db.Value{Field: map[string]string{}}
if rpvstVlanIntfConf.Config != nil {
dbVal := app.vlanIntfTableMap[vlanName][intfId]
- (&dbVal).Set("vlan-name", vlanName)
- (&dbVal).Set("ifname", intfId)
if rpvstVlanIntfConf.Config.Cost != nil {
(&dbVal).Set("path_cost", strconv.Itoa(int(*rpvstVlanIntfConf.Config.Cost)))
- } else {
+ } else if setDefaultFlag {
(&dbVal).Set("path_cost", "200")
}
if rpvstVlanIntfConf.Config.PortPriority != nil {
(&dbVal).Set("priority", strconv.Itoa(int(*rpvstVlanIntfConf.Config.PortPriority)))
- } else {
+ } else if setDefaultFlag {
(&dbVal).Set("priority", "128")
}
}
@@ -745,7 +889,6 @@ func (app *StpApp) setRpvstVlanInterfaceDataInDB(d *db.DB, createFlag bool) erro
}
if createFlag || (!createFlag && err != nil && !existingEntry.IsPopulated()) {
err = d.CreateEntry(app.vlanIntfTable, asKey(vlanName, intfId), app.vlanIntfTableMap[vlanName][intfId])
- log.Error(err)
} else {
if existingEntry.IsPopulated() {
err = d.ModEntry(app.vlanIntfTable, asKey(vlanName, intfId), app.vlanIntfTableMap[vlanName][intfId])
@@ -880,8 +1023,8 @@ func (app *StpApp) convertInternalToOCRpvstVlanConfig(vlanName string, rpvst *oc
desigRootAddr := (&operDbVal).Get("desig_bridge_id")
rpvstVlanConf.State.DesignatedRootAddress = &desigRootAddr
- //rootPortStr := (&operDbVal).Get("root_port")
- //rpvstVlanConf.State.RootPort = &rootPortStr
+ rootPortStr := (&operDbVal).Get("root_port")
+ rpvstVlanConf.State.RootPortName = &rootPortStr
}
app.convertInternalToOCRpvstVlanInterface(vlanName, "", rpvstVlanConf, nil)
@@ -960,8 +1103,9 @@ func (app *StpApp) convertInternalToOCRpvstVlanInterface(vlanName string, intfId
}
/////////// PVST //////////////////////
-func (app *StpApp) convertOCPvstToInternal() {
+func (app *StpApp) convertOCPvstToInternal(opcode int) {
stp := app.getAppRootObject()
+ setDefaultFlag := (opcode == CREATE || opcode == REPLACE)
if stp != nil && stp.Pvst != nil && len(stp.Pvst.Vlan) > 0 {
for vlanId, _ := range stp.Pvst.Vlan {
vlanName := "Vlan" + strconv.Itoa(int(vlanId))
@@ -972,22 +1116,22 @@ func (app *StpApp) convertOCPvstToInternal() {
(&dbVal).Set("vlanid", strconv.Itoa(int(vlanId)))
if pvstVlan.Config.BridgePriority != nil {
(&dbVal).Set("priority", strconv.Itoa(int(*pvstVlan.Config.BridgePriority)))
- } else {
+ } else if setDefaultFlag {
(&dbVal).Set("priority", "32768")
}
if pvstVlan.Config.ForwardingDelay != nil {
(&dbVal).Set("forward_delay", strconv.Itoa(int(*pvstVlan.Config.ForwardingDelay)))
- } else {
+ } else if setDefaultFlag {
(&dbVal).Set("forward_delay", "15")
}
if pvstVlan.Config.HelloTime != nil {
(&dbVal).Set("hello_time", strconv.Itoa(int(*pvstVlan.Config.HelloTime)))
- } else {
+ } else if setDefaultFlag {
(&dbVal).Set("hello_time", "2")
}
if pvstVlan.Config.MaxAge != nil {
(&dbVal).Set("max_age", strconv.Itoa(int(*pvstVlan.Config.MaxAge)))
- } else {
+ } else if setDefaultFlag {
(&dbVal).Set("max_age", "20")
}
if pvstVlan.Config.SpanningTreeEnable != nil {
@@ -996,7 +1140,7 @@ func (app *StpApp) convertOCPvstToInternal() {
} else {
(&dbVal).Set("enabled", "false")
}
- } else {
+ } else if setDefaultFlag {
(&dbVal).Set("enabled", "false")
}
}
@@ -1007,16 +1151,14 @@ func (app *StpApp) convertOCPvstToInternal() {
app.vlanIntfTableMap[vlanName][intfId] = db.Value{Field: map[string]string{}}
if pvstVlanIntf.Config != nil {
dbVal := app.vlanIntfTableMap[vlanName][intfId]
- (&dbVal).Set("vlan-name", vlanName)
- (&dbVal).Set("ifname", intfId)
if pvstVlanIntf.Config.Cost != nil {
(&dbVal).Set("path_cost", strconv.Itoa(int(*pvstVlanIntf.Config.Cost)))
- } else {
+ } else if setDefaultFlag {
(&dbVal).Set("path_cost", "200")
}
if pvstVlanIntf.Config.PortPriority != nil {
(&dbVal).Set("priority", strconv.Itoa(int(*pvstVlanIntf.Config.PortPriority)))
- } else {
+ } else if setDefaultFlag {
(&dbVal).Set("priority", "128")
}
}
@@ -1112,8 +1254,8 @@ func (app *StpApp) convertInternalToOCPvstVlan(vlanName string, pvst *ocbinds.Op
desigRootAddr := (&operDbVal).Get("desig_bridge_id")
pvstVlan.State.DesignatedRootAddress = &desigRootAddr
- //rootPortStr := (&operDbVal).Get("root_port")
- //pvstVlan.State.RootPort = &rootPortStr
+ rootPortStr := (&operDbVal).Get("root_port")
+ pvstVlan.State.RootPortName = &rootPortStr
}
app.convertInternalToOCPvstVlanInterface(vlanName, "", pvstVlan, nil)
@@ -1172,7 +1314,6 @@ func (app *StpApp) convertOCStpInterfacesToInternal() {
stpIntfConf := stp.Interfaces.Interface[intfId]
if stpIntfConf.Config != nil {
dbVal := app.intfTableMap[intfId]
- (&dbVal).Set("ifname", intfId)
if stpIntfConf.Config.BpduGuard != nil {
if *stpIntfConf.Config.BpduGuard == true {
@@ -1257,7 +1398,21 @@ func (app *StpApp) convertOCStpInterfacesToInternal() {
func (app *StpApp) setStpInterfacesDataInDB(d *db.DB, createFlag bool) error {
var err error
+ // Fetch list of interfaces which are L2 i.e. members of any Vlan
+ l2IntfList, err1 := app.getAllInterfacesFromVlanMemberTable(d)
+ if err1 != nil {
+ return tlerr.InvalidArgs("There are no L2 interfaces configured")
+ }
+ // Fetch list of interfaces which are members of port-channel
+ poMemberIntfList, _ := app.getAllInterfacesFromPortChannelMemberTable(d)
+
for intfName := range app.intfTableMap {
+ if !contains(l2IntfList, intfName) {
+ return tlerr.InvalidArgs("%s has no VLAN configured - It's not a L2 interface", intfName)
+ }
+ if contains(poMemberIntfList, intfName) {
+ return tlerr.InvalidArgs("%s is a portchannel member port - STP can't be configured", intfName)
+ }
existingEntry, err := d.GetEntry(app.interfaceTable, asKey(intfName))
if createFlag && existingEntry.IsPopulated() {
return tlerr.AlreadyExists("Stp Interface %s already configured", intfName)
@@ -1420,7 +1575,10 @@ func (app *StpApp) convertOperInternalToOCVlanInterface(vlanName string, intfId
case "OpenconfigSpanningTree_Stp_Pvst_Vlan":
pvstVlan, _ = vlan.(*ocbinds.OpenconfigSpanningTree_Stp_Pvst_Vlan)
if vlanIntf == nil {
- pvstVlanIntf, _ = pvstVlan.Interfaces.NewInterface(intfId)
+ pvstVlanIntf = pvstVlan.Interfaces.Interface[intfId]
+ if pvstVlanIntf == nil {
+ pvstVlanIntf, _ = pvstVlan.Interfaces.NewInterface(intfId)
+ }
ygot.BuildEmptyTree(pvstVlanIntf)
ygot.BuildEmptyTree(pvstVlanIntf.State)
} else {
@@ -1429,7 +1587,10 @@ func (app *StpApp) convertOperInternalToOCVlanInterface(vlanName string, intfId
case "OpenconfigSpanningTree_Stp_RapidPvst_Vlan":
rpvstVlan, _ = vlan.(*ocbinds.OpenconfigSpanningTree_Stp_RapidPvst_Vlan)
if vlanIntf == nil {
- rpvstVlanIntf, _ = rpvstVlan.Interfaces.NewInterface(intfId)
+ rpvstVlanIntf = rpvstVlan.Interfaces.Interface[intfId]
+ if rpvstVlanIntf == nil {
+ rpvstVlanIntf, _ = rpvstVlan.Interfaces.NewInterface(intfId)
+ }
ygot.BuildEmptyTree(rpvstVlanIntf)
ygot.BuildEmptyTree(rpvstVlanIntf.State)
} else {
@@ -1492,15 +1653,15 @@ func (app *StpApp) convertOperInternalToOCVlanInterface(vlanName string, intfId
pvstVlanIntf.State.DesignatedRootAddress = &desigRootAddr
pvstVlanIntf.State.DesignatedBridgeAddress = &desigBridgeAddr
switch portState {
- case "disabled":
+ case "DISABLED":
pvstVlanIntf.State.PortState = ocbinds.OpenconfigSpanningTreeTypes_STP_PORT_STATE_DISABLED
- case "block":
+ case "BLOCKING":
pvstVlanIntf.State.PortState = ocbinds.OpenconfigSpanningTreeTypes_STP_PORT_STATE_BLOCKING
- case "listen":
+ case "LISTENING":
pvstVlanIntf.State.PortState = ocbinds.OpenconfigSpanningTreeTypes_STP_PORT_STATE_LISTENING
- case "learn":
+ case "LEARNING":
pvstVlanIntf.State.PortState = ocbinds.OpenconfigSpanningTreeTypes_STP_PORT_STATE_LEARNING
- case "forward":
+ case "FORWARDING":
pvstVlanIntf.State.PortState = ocbinds.OpenconfigSpanningTreeTypes_STP_PORT_STATE_FORWARDING
}
if pvstVlanIntf.State.Counters != nil {
@@ -1521,15 +1682,15 @@ func (app *StpApp) convertOperInternalToOCVlanInterface(vlanName string, intfId
rpvstVlanIntf.State.DesignatedRootAddress = &desigRootAddr
rpvstVlanIntf.State.DesignatedBridgeAddress = &desigBridgeAddr
switch portState {
- case "disabled":
+ case "DISABLED":
rpvstVlanIntf.State.PortState = ocbinds.OpenconfigSpanningTreeTypes_STP_PORT_STATE_DISABLED
- case "block":
+ case "BLOCKING":
rpvstVlanIntf.State.PortState = ocbinds.OpenconfigSpanningTreeTypes_STP_PORT_STATE_BLOCKING
- case "listen":
+ case "LISTENING":
rpvstVlanIntf.State.PortState = ocbinds.OpenconfigSpanningTreeTypes_STP_PORT_STATE_LISTENING
- case "learn":
+ case "LEARNING":
rpvstVlanIntf.State.PortState = ocbinds.OpenconfigSpanningTreeTypes_STP_PORT_STATE_LEARNING
- case "forward":
+ case "FORWARDING":
rpvstVlanIntf.State.PortState = ocbinds.OpenconfigSpanningTreeTypes_STP_PORT_STATE_FORWARDING
}
if rpvstVlanIntf.State.Counters != nil {
@@ -1659,6 +1820,22 @@ func (app *StpApp) getAllInterfacesFromVlanMemberTable(d *db.DB) ([]string, erro
return intfList, err
}
+func (app *StpApp) getAllInterfacesFromPortChannelMemberTable(d *db.DB) ([]string, error) {
+ var intfList []string
+
+ keys, err := d.GetKeys(&db.TableSpec{Name: "PORTCHANNEL_MEMBER"})
+ if err != nil {
+ return intfList, err
+ }
+ for i, _ := range keys {
+ key := keys[i]
+ if !contains(intfList, (&key).Get(1)) {
+ intfList = append(intfList, (&key).Get(1))
+ }
+ }
+ return intfList, err
+}
+
func (app *StpApp) enableStpForInterfaces(d *db.DB) error {
defaultDBValues := db.Value{Field: map[string]string{}}
(&defaultDBValues).Set("enabled", "true")
@@ -1737,30 +1914,86 @@ func (app *StpApp) enableStpForVlans(d *db.DB) error {
return err
}
-func (app *StpApp) updateGlobalFieldsToStpVlanTable(d *db.DB, fldName string, valStr string) error {
- stpGlobalDbEntry, err := d.GetEntry(app.globalTable, asKey("GLOBAL"))
- if err != nil {
- return err
+func enableStpOnVlanCreation(d *db.DB, vlanList []string) {
+ if len(vlanList) == 0 {
+ return
}
- globalFldVal := (&stpGlobalDbEntry).Get(fldName)
+ vlanKeys, _ := d.GetKeys(&db.TableSpec{Name: STP_VLAN_TABLE})
+ existingEntriesCount := len(vlanKeys)
+ if existingEntriesCount < PVST_MAX_INSTANCES {
+ stpGlobalDBEntry, err := d.GetEntry(&db.TableSpec{Name: STP_GLOBAL_TABLE}, asKey("GLOBAL"))
+ if err != nil {
+ return
+ }
+ fDelay := (&stpGlobalDBEntry).Get("forward_delay")
+ helloTime := (&stpGlobalDBEntry).Get("hello_time")
+ maxAge := (&stpGlobalDBEntry).Get("max_age")
+ priority := (&stpGlobalDBEntry).Get("priority")
+
+ // Sort vlanList in natural order such that 'Vlan2' < 'Vlan10'
+ natsort.Sort(vlanList)
+
+ for i, _ := range vlanList {
+ if (existingEntriesCount + i) < PVST_MAX_INSTANCES {
+ defaultDBValues := db.Value{Field: map[string]string{}}
+ (&defaultDBValues).Set("enabled", "true")
+ (&defaultDBValues).Set("forward_delay", fDelay)
+ (&defaultDBValues).Set("hello_time", helloTime)
+ (&defaultDBValues).Set("max_age", maxAge)
+ (&defaultDBValues).Set("priority", priority)
+
+ vlanId := strings.Replace(vlanList[i], "Vlan", "", 1)
+ (&defaultDBValues).Set("vlanid", vlanId)
+ d.CreateEntry(&db.TableSpec{Name: STP_VLAN_TABLE}, asKey(vlanList[i]), defaultDBValues)
+ }
+ }
+ }
+}
+// This function accepts map where key is Interface name (i.e. Eth or Portchannel)
+// and value will be slice of VlanIds
+//func enableStpOnInterfaceVlanMembership(d *db.DB, intfVlansMap map[string][]string) {
+//}
+
+func (app *StpApp) updateGlobalFieldsToStpVlanTable(d *db.DB, fldValuePair map[string]string, stpGlobalDbEntry db.Value) error {
vlanKeys, err := d.GetKeys(app.vlanTable)
if err != nil {
return err
}
for i, _ := range vlanKeys {
vlanEntry, _ := d.GetEntry(app.vlanTable, vlanKeys[i])
- if (&vlanEntry).Get(fldName) == globalFldVal {
- (&vlanEntry).Set(fldName, valStr)
- err := d.ModEntry(app.vlanTable, vlanKeys[i], vlanEntry)
- if err != nil {
- return err
+
+ for fldName := range fldValuePair {
+ valStr := fldValuePair[fldName]
+ globalFldVal := (&stpGlobalDbEntry).Get(fldName)
+
+ if (&vlanEntry).Get(fldName) == globalFldVal {
+ (&vlanEntry).Set(fldName, valStr)
+ err := d.ModEntry(app.vlanTable, vlanKeys[i], vlanEntry)
+ if err != nil {
+ return err
+ }
}
}
}
return nil
}
+func (app *StpApp) enableStpMode(d *db.DB) error {
+ var err error
+ err = app.setStpGlobalConfigInDB(d)
+ if err != nil {
+ return err
+ }
+ err = app.enableStpForInterfaces(d)
+ if err != nil {
+ return err
+ }
+ err = app.enableStpForVlans(d)
+
+ return err
+}
+
func (app *StpApp) disableStpMode(d *db.DB) error {
var err error
err = d.DeleteTable(app.vlanIntfTable)
@@ -1780,6 +2013,40 @@ func (app *StpApp) disableStpMode(d *db.DB) error {
return err
}
+func (app *StpApp) handleStpGlobalFieldsUpdation(d *db.DB, opcode int) error {
+ stpGlobalDBEntry, err := d.GetEntry(app.globalTable, asKey("GLOBAL"))
+ if err != nil {
+ return err
+ }
+ // Make a copy of StpGlobalDBEntry to modify fields value.
+ tmpDbEntry := db.Value{Field: map[string]string{}}
+ for field, value := range stpGlobalDBEntry.Field {
+ tmpDbEntry.Field[field] = value
+ }
+ fldValuePair := make(map[string]string)
+
+ for fld := range app.globalInfo.Field {
+ valStr := app.globalInfo.Field[fld]
+ (&tmpDbEntry).Set(fld, valStr)
+
+ if fld != "rootguard_timeout" {
+ fldValuePair[fld] = valStr
+ }
+ }
+
+ err = d.ModEntry(app.globalTable, asKey("GLOBAL"), tmpDbEntry)
+ if err != nil {
+ return err
+ }
+
+ err = app.updateGlobalFieldsToStpVlanTable(d, fldValuePair, stpGlobalDBEntry)
+ if err != nil {
+ return err
+ }
+
+ return nil
+}
+
func (app *StpApp) handleStpGlobalFieldsDeletion(d *db.DB) error {
stpGlobalDBEntry, err := d.GetEntry(app.globalTable, asKey("GLOBAL"))
if err != nil {
@@ -1811,17 +2078,26 @@ func (app *StpApp) handleStpGlobalFieldsDeletion(d *db.DB) error {
valStr = STP_DEFAULT_BRIDGE_PRIORITY
}
- (&stpGlobalDBEntry).Set(fldName, valStr)
- err := d.ModEntry(app.globalTable, asKey("GLOBAL"), stpGlobalDBEntry)
+ // Make a copy of StpGlobalDBEntry to modify fields value.
+ tmpDbEntry := db.Value{Field: map[string]string{}}
+ for field, value := range stpGlobalDBEntry.Field {
+ tmpDbEntry.Field[field] = value
+ }
+ fldValuePair := make(map[string]string)
+
+ (&tmpDbEntry).Set(fldName, valStr)
+ err = d.ModEntry(app.globalTable, asKey("GLOBAL"), tmpDbEntry)
if err != nil {
return err
}
if fldName != "rootguard_timeout" {
- err := app.updateGlobalFieldsToStpVlanTable(d, fldName, valStr)
- if err != nil {
- return err
- }
+ fldValuePair[fldName] = valStr
+ }
+
+ err = app.updateGlobalFieldsToStpVlanTable(d, fldValuePair, stpGlobalDBEntry)
+ if err != nil {
+ return err
}
}
return nil
@@ -1856,6 +2132,15 @@ func (app *StpApp) handleVlanInterfaceFieldsDeletion(d *db.DB, vlanName string,
}
func (app *StpApp) handleVlanFieldsDeletion(d *db.DB, vlanName string) error {
+ stpGlobalDBEntry, err := d.GetEntry(app.globalTable, asKey("GLOBAL"))
+ if err != nil {
+ return err
+ }
+ fDelay := (&stpGlobalDBEntry).Get("forward_delay")
+ helloTime := (&stpGlobalDBEntry).Get("hello_time")
+ maxAge := (&stpGlobalDBEntry).Get("max_age")
+ priority := (&stpGlobalDBEntry).Get("priority")
+
dbEntry, err := d.GetEntry(app.vlanTable, asKey(vlanName))
if err != nil {
return err
@@ -1869,19 +2154,19 @@ func (app *StpApp) handleVlanFieldsDeletion(d *db.DB, vlanName string) error {
if nodeInfo.IsLeaf() {
switch nodeInfo.Name {
case "hello-time":
- (&dbEntry).Remove("hello_time")
+ (&dbEntry).Set("hello_time", helloTime)
case "max-age":
- (&dbEntry).Remove("max_age")
+ (&dbEntry).Set("max_age", maxAge)
case "bridge-priority":
- (&dbEntry).Remove("priority")
+ (&dbEntry).Set("priority", priority)
case "forwarding-delay":
- (&dbEntry).Remove("forward_delay")
+ (&dbEntry).Set("forward_delay", fDelay)
case "spanning-tree-enable":
- (&dbEntry).Remove("enabled")
+ (&dbEntry).Set("enabled", "false")
}
}
- err = d.SetEntry(app.vlanTable, asKey(vlanName), dbEntry)
+ err = d.ModEntry(app.vlanTable, asKey(vlanName), dbEntry)
if err != nil {
return err
}
diff --git a/tools/pyang/pyang_plugins/openapi.py b/tools/pyang/pyang_plugins/openapi.py
index 4a2d62af60..ebc1127d4b 100644
--- a/tools/pyang/pyang_plugins/openapi.py
+++ b/tools/pyang/pyang_plugins/openapi.py
@@ -246,7 +246,7 @@ def add_swagger_tag(module):
else:
return
-def swagger_it(child, defName, pathstr, payload, metadata, verb, operId=False):
+def swagger_it(child, defName, pathstr, payload, metadata, verb, operId=False, xParamsList=[]):
firstEncounter = True
verbPathStr = pathstr
@@ -272,6 +272,18 @@ def swagger_it(child, defName, pathstr, payload, metadata, verb, operId=False):
swaggerDict["paths"][verbPathStr][verb]["responses"] = copy.deepcopy(merge_two_dicts(responses, verb_responses[verb]))
firstEncounter = False
+ haveXParams = False
+ tempParamsList = []
+ for entry in xParamsList:
+ if entry["yangName"] not in tempParamsList:
+ tempParamsList.append(entry["yangName"])
+ else:
+ haveXParams = True
+ break
+
+ if haveXParams:
+ swaggerDict["paths"][verbPathStr][verb]["x-params"] = {"varMapping":copy.deepcopy(xParamsList)}
+
opId = None
if "operationId" not in swaggerDict["paths"][verbPathStr][verb]:
if not operId:
@@ -412,7 +424,8 @@ def walk_child(child):
actXpath = statements.mk_path_str(child, True)
metadata = []
keyNodesInPath = []
- pathstr = mk_path_refine(child, metadata, keyNodesInPath)
+ paramsList = []
+ pathstr = mk_path_refine(child, metadata, keyNodesInPath, False, paramsList)
if actXpath in keysToLeafRefObjSet:
return
@@ -452,7 +465,7 @@ def walk_child(child):
swaggerDict["definitions"][defName_get] = OrderedDict()
swaggerDict["definitions"][defName_get]["type"] = "object"
swaggerDict["definitions"][defName_get]["properties"] = copy.deepcopy(payload_get)
- swagger_it(child, defName_get, pathstr, payload_get, metadata, "get", defName_get)
+ swagger_it(child, defName_get, pathstr, payload_get, metadata, "get", defName_get, paramsList)
else:
swaggerDict["definitions"][defName] = OrderedDict()
swaggerDict["definitions"][defName]["type"] = "object"
@@ -462,7 +475,8 @@ def walk_child(child):
if child.keyword == "leaf-list":
metadata_leaf_list = []
keyNodesInPath_leaf_list = []
- pathstr_leaf_list = mk_path_refine(child, metadata_leaf_list, keyNodesInPath_leaf_list, True)
+ paramsLeafList = []
+ pathstr_leaf_list = mk_path_refine(child, metadata_leaf_list, keyNodesInPath_leaf_list, True, paramsLeafList)
if verb == "get":
payload_get = OrderedDict()
@@ -473,11 +487,11 @@ def walk_child(child):
swaggerDict["definitions"][defName_get] = OrderedDict()
swaggerDict["definitions"][defName_get]["type"] = "object"
swaggerDict["definitions"][defName_get]["properties"] = copy.deepcopy(payload_get)
- swagger_it(child, defName_get, pathstr, payload_get, metadata, verb, defName_get)
+ swagger_it(child, defName_get, pathstr, payload_get, metadata, verb, defName_get, paramsList)
if child.keyword == "leaf-list":
defName_get_leaf_list = "get" + '_llist_' + defName
- swagger_it(child, defName_get, pathstr_leaf_list, payload_get, metadata_leaf_list, verb, defName_get_leaf_list)
+ swagger_it(child, defName_get, pathstr_leaf_list, payload_get, metadata_leaf_list, verb, defName_get_leaf_list, paramsLeafList)
continue
@@ -490,20 +504,21 @@ def walk_child(child):
if isUriKeyInPayload(child,keyNodesInPath):
continue
- swagger_it(child, defName, pathstr, payload, metadata, verb)
+ swagger_it(child, defName, pathstr, payload, metadata, verb, False, paramsList)
if verb == "delete" and child.keyword == "leaf-list":
defName_del_leaf_list = "del" + '_llist_' + defName
- swagger_it(child, defName, pathstr_leaf_list, payload, metadata_leaf_list, verb, defName_del_leaf_list)
+ swagger_it(child, defName, pathstr_leaf_list, payload, metadata_leaf_list, verb, defName_del_leaf_list, paramsLeafList)
if child.keyword == "list":
listMetaData = copy.deepcopy(metadata)
- walk_child_for_list_base(child,actXpath,pathstr, listMetaData, defName)
+ listparamsList = copy.deepcopy(paramsList)
+ walk_child_for_list_base(child,actXpath,pathstr, listMetaData, defName, listparamsList)
if hasattr(child, 'i_children'):
for ch in child.i_children:
walk_child(ch)
-def walk_child_for_list_base(child, actXpath, pathstr, metadata, nonBaseDefName=None):
+def walk_child_for_list_base(child, actXpath, pathstr, metadata, nonBaseDefName=None, paramsList=[]):
payload = OrderedDict()
pathstrList = pathstr.split('/')
@@ -521,6 +536,8 @@ def walk_child_for_list_base(child, actXpath, pathstr, metadata, nonBaseDefName=
for key in child.i_key:
metadata.pop()
+ if len(paramsList) > 0:
+ paramsList.pop()
add_swagger_tag(child.i_module)
build_payload(child, payload, pathstr, False, "", True)
@@ -542,12 +559,12 @@ def walk_child_for_list_base(child, actXpath, pathstr, metadata, nonBaseDefName=
defName_get = "get" + '_' + defName
if nonBaseDefName is not None:
- swagger_it(child, "get" + '_' + nonBaseDefName, pathstr, payload_get, metadata, "get", defName_get)
+ swagger_it(child, "get" + '_' + nonBaseDefName, pathstr, payload_get, metadata, "get", defName_get, paramsList)
else:
swaggerDict["definitions"][defName_get] = OrderedDict()
swaggerDict["definitions"][defName_get]["type"] = "object"
swaggerDict["definitions"][defName_get]["properties"] = copy.deepcopy(payload_get)
- swagger_it(child, defName_get, pathstr, payload_get, metadata, "get", defName_get)
+ swagger_it(child, defName_get, pathstr, payload_get, metadata, "get", defName_get, paramsList)
else:
if nonBaseDefName is None:
swaggerDict["definitions"][defName] = OrderedDict()
@@ -564,18 +581,18 @@ def walk_child_for_list_base(child, actXpath, pathstr, metadata, nonBaseDefName=
defName_get = "get" + '_' + defName
if nonBaseDefName is not None:
- swagger_it(child, "get" + '_' + nonBaseDefName, pathstr, payload_get, metadata, verb, defName_get)
+ swagger_it(child, "get" + '_' + nonBaseDefName, pathstr, payload_get, metadata, verb, defName_get, paramsList)
else:
swaggerDict["definitions"][defName_get] = OrderedDict()
swaggerDict["definitions"][defName_get]["type"] = "object"
swaggerDict["definitions"][defName_get]["properties"] = copy.deepcopy(payload_get)
- swagger_it(child, defName_get, pathstr, payload_get, metadata, verb, defName_get)
+ swagger_it(child, defName_get, pathstr, payload_get, metadata, verb, defName_get, paramsList)
continue
if nonBaseDefName is not None:
- swagger_it(child, nonBaseDefName, pathstr, payload, metadata, verb, verb + '_' + defName)
+ swagger_it(child, nonBaseDefName, pathstr, payload, metadata, verb, verb + '_' + defName, paramsList)
else:
- swagger_it(child, defName, pathstr, payload, metadata, verb, verb + '_' + defName)
+ swagger_it(child, defName, pathstr, payload, metadata, verb, verb + '_' + defName, paramsList)
def build_payload(child, payloadDict, uriPath="", oneInstance=False, Xpath="", firstCall=False, config_false=False, moduleList=[]):
@@ -701,7 +718,36 @@ def build_payload(child, payloadDict, uriPath="", oneInstance=False, Xpath="", f
for ch in child.i_children:
build_payload(ch,childJson,uriPath, False, Xpath, False, config_false, copy.deepcopy(moduleList))
-def mk_path_refine(node, metadata, keyNodes=[], restconf_leaflist=False):
+def handleDuplicateParams(node, paramMeta={}):
+ paramNamesList = paramMeta["paramNamesList"]
+ paramsList = paramMeta["paramsList"]
+ paramName = node.arg
+ paramNamesList.append(paramName)
+ paramNameCount = paramNamesList.count(paramName)
+ paramDictEntry = OrderedDict()
+
+ if paramNameCount > 1:
+ origParamName = paramName
+ paramName = paramName + str(paramNameCount-1)
+ while paramName in paramNamesList:
+ paramNameCount = paramNameCount + 1
+ paramName = origParamName + str(paramNameCount-1)
+ paramNamesList.append(paramName)
+
+ paramDictEntry["uriName"] = paramName
+ paramDictEntry["yangName"] = node.arg
+ if paramName != node.arg:
+ paramMeta["sameParams"] = True
+ paramsList.append(paramDictEntry)
+
+ return paramName
+
+def mk_path_refine(node, metadata, keyNodes=[], restconf_leaflist=False, paramsList=[]):
+ paramMeta={}
+ paramMeta["paramNamesList"] = []
+ paramMeta["paramsList"] = []
+ paramMeta["sameParams"] = False
+
def mk_path(node):
"""Returns the XPath path of the node"""
if node.keyword in ['choice', 'case']:
@@ -709,8 +755,9 @@ def mk_path(node):
def name(node):
extra = ""
if node.keyword == "leaf-list" and restconf_leaflist:
- extraKeys = []
- extraKeys.append('{' + node.arg + '}')
+ extraKeys = []
+ paramName = handleDuplicateParams(node,paramMeta)
+ extraKeys.append('{' + paramName + '}')
desc = node.search_one('description')
if desc is None:
desc = ''
@@ -718,7 +765,7 @@ def name(node):
desc = desc.arg
metaInfo = OrderedDict()
metaInfo["desc"] = desc
- metaInfo["name"] = node.arg
+ metaInfo["name"] = paramName
metaInfo["type"] = "string"
metaInfo["format"] = ""
metadata.append(metaInfo)
@@ -729,8 +776,9 @@ def name(node):
for index, list_key in enumerate(node.i_key):
keyNodes.append(list_key)
if list_key.i_leafref is not None:
- keyNodes.append(list_key.i_leafref_ptr[0])
- extraKeys.append('{' + list_key.arg + '}')
+ keyNodes.append(list_key.i_leafref_ptr[0])
+ paramName = handleDuplicateParams(list_key,paramMeta)
+ extraKeys.append('{' + paramName + '}')
desc = list_key.search_one('description')
if desc is None:
desc = ''
@@ -738,7 +786,7 @@ def name(node):
desc = desc.arg
metaInfo = OrderedDict()
metaInfo["desc"] = desc
- metaInfo["name"] = list_key.arg
+ metaInfo["name"] = paramName
typeInfo = getType(list_key)
if isinstance(typeInfo, tuple):
@@ -786,6 +834,11 @@ def name(node):
xpath = "/".join(final_xpathList)
if not xpath.startswith('/'):
xpath = '/' + xpath
+
+ if paramMeta["sameParams"]:
+ for entry in paramMeta["paramsList"]:
+ paramsList.append(copy.deepcopy(entry))
+
return xpath
def handle_leafref(node,xpath):
diff --git a/tools/swagger_codegen/go-server/templates-yang/controller-api.mustache b/tools/swagger_codegen/go-server/templates-yang/controller-api.mustache
index 790f1ee6b2..15b5c77a3e 100644
--- a/tools/swagger_codegen/go-server/templates-yang/controller-api.mustache
+++ b/tools/swagger_codegen/go-server/templates-yang/controller-api.mustache
@@ -17,5 +17,10 @@ func {{nickname}}(w http.ResponseWriter, r *http.Request) {
{{#produces}}
rc.Produces.Add("{{mediaType}}")
{{/produces}}
+ {{#vendorExtensions}}
+ {{#x-params}}
+ rc.PMap = server.NameMap{ {{#varMapping}}"{{uriName}}":"{{yangName}}", {{/varMapping}} }
+ {{/x-params}}
+ {{/vendorExtensions}}
server.Process(w, r)
}{{/operation}}{{/operations}}