diff --git a/scripts/run_tests_locally-device-openconfig-ocnos.sh b/scripts/run_tests_locally-device-openconfig-ocnos.sh
new file mode 100755
index 0000000000000000000000000000000000000000..60af6768d37199c957d17c6804c8af1072d0b0e1
--- /dev/null
+++ b/scripts/run_tests_locally-device-openconfig-ocnos.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/)
+#
+# 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.
+
+
+PROJECTDIR=`pwd`
+
+cd $PROJECTDIR/src
+RCFILE=$PROJECTDIR/coverage/.coveragerc
+
+# Run unitary tests and analyze coverage of code at same time
+# helpful pytest flags: --log-level=INFO -o log_cli=true --verbose --maxfail=1 --durations=0
+coverage run --rcfile=$RCFILE --append -m pytest --log-level=INFO -o log_cli=true --verbose \
+    device/tests/test_unitary_openconfig_ocnos.py
diff --git a/src/device/service/drivers/openconfig/OpenConfigDriver.py b/src/device/service/drivers/openconfig/OpenConfigDriver.py
index a592b51576acc21e6dc055fe9f41e720f28aae1c..fd36e2dc40e38a125f1812f00eeb304106a40c8a 100644
--- a/src/device/service/drivers/openconfig/OpenConfigDriver.py
+++ b/src/device/service/drivers/openconfig/OpenConfigDriver.py
@@ -12,6 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import time
 import json
 import anytree, copy, logging, pytz, queue, re, threading
 #import lxml.etree as ET
@@ -237,6 +238,8 @@ def edit_config(
                         test_option=test_option, error_option=error_option, format=format)
                     if commit_per_rule:
                         netconf_handler.commit()                                                                               # configuration commit
+                    if 'table_connections' in resource_key:
+                        time.sleep(5) # CPU usage might exceed critical level after route redistribution, BGP daemon needs time to reload
                 
                 #results[i] = True
                 results.append(True)
diff --git a/src/device/service/drivers/openconfig/templates/Tools.py b/src/device/service/drivers/openconfig/templates/Tools.py
index b7a5ba9c1a962032fe13b4ec5cb70eae7ff604a1..c4ef22b1e3c11f1e512026bea8e2122ab703a9e5 100644
--- a/src/device/service/drivers/openconfig/templates/Tools.py
+++ b/src/device/service/drivers/openconfig/templates/Tools.py
@@ -61,7 +61,8 @@ def generate_templates(resource_key: str, resource_value: str, delete: bool,vend
         elif "inter_instance_policies" in resource_key:
             result_templates.append(associate_RP_to_NI(data))
         elif "protocols" in resource_key:
-            if vendor == "ADVA": result_templates.append(add_protocol_NI(data, vendor, delete))
+            if vendor is None or vendor == "ADVA":
+                result_templates.append(add_protocol_NI(data, vendor, delete))
         elif "table_connections" in resource_key:
             result_templates.append(create_table_conns(data, delete))
         elif "interface" in resource_key:
diff --git a/src/device/service/drivers/openconfig/templates/VPN/Interfaces_multivendor.py b/src/device/service/drivers/openconfig/templates/VPN/Interfaces_multivendor.py
index 09e3b618a69c738b57b4d2268c0429e6f8119147..ab57ce3bd26e9183f931a1a6e13a44a9a85bef7d 100644
--- a/src/device/service/drivers/openconfig/templates/VPN/Interfaces_multivendor.py
+++ b/src/device/service/drivers/openconfig/templates/VPN/Interfaces_multivendor.py
@@ -54,7 +54,7 @@ def create_If_SubIf(data,vendor, DEL):
                     with tag('enabled'):text('true')    
                 with tag('subinterfaces'):
                     with tag('subinterface'):
-                        if vendor == 'ADVA':
+                        if vendor is None or vendor == 'ADVA':
                             with tag('index'): text('0')
                         with tag('config'):
                             with tag('index'): text('0')
@@ -65,8 +65,10 @@ def create_If_SubIf(data,vendor, DEL):
                                 with tag('single-tagged'):
                                     with tag('config'):
                                         with tag('vlan-id'):text(data['vlan_id'])
-                        if "l3ipvlan" in data['type']: 
+                        if "l3ipvlan" in data['type'] and 'address_ip' in data: 
                             with tag('ipv4',  xmlns="http://openconfig.net/yang/interfaces/ip"):
+                                if 'mtu' in data:
+                                    with tag('mtu'):text(data['mtu'])
                                 with tag('addresses'):
                                     with tag('address'):
                                         with tag('ip'):text(data['address_ip'])
diff --git a/src/device/service/drivers/openconfig/templates/VPN/Network_instance_multivendor.py b/src/device/service/drivers/openconfig/templates/VPN/Network_instance_multivendor.py
index c2d18ef172bccaf46b4e323a1fef6ef048232888..157dd0ab89a0eb625d428dd95109faabc399bcf0 100644
--- a/src/device/service/drivers/openconfig/templates/VPN/Network_instance_multivendor.py
+++ b/src/device/service/drivers/openconfig/templates/VPN/Network_instance_multivendor.py
@@ -64,10 +64,12 @@ def create_NI(parameters,vendor,DEL):
                 elif "L3VRF" in parameters['type']: 
                     with tag('config'):
                         with tag('name'):text(parameters['name'])
-                        if vendor == "ADVA": 
+                        if "router_id" in parameters: 
+                            with tag('router-id'):text(parameters['router_id'])
+                        if vendor is None or vendor == 'ADVA':
                             with tag('type', 'xmlns:oc-ni-types="http://openconfig.net/yang/network-instance-types"'):text('oc-ni-types:',parameters['type'])
                             with tag('route-distinguisher'):text(parameters['route_distinguisher'])
-                    if vendor == "ADVA": 
+                    if vendor is None or vendor == 'ADVA':
                         with tag('encapsulation'):
                             with tag('config'):
                                 with tag('encapsulation-type', 'xmlns:oc-ni-types="http://openconfig.net/yang/network-instance-types"')  :text('oc-ni-types:MPLS')
@@ -123,14 +125,29 @@ def add_protocol_NI(parameters,vendor, DEL):
                         with tag('config'):
                             with tag('identifier', 'xmlns:oc-pol-types="http://openconfig.net/yang/policy-types"'):text('oc-pol-types:',parameters['identifier'])
                             with tag('name')      :text(parameters['protocol_name'])
+                            with tag('enabled'): text('true')
                         if "BGP" in parameters['identifier']:
                             with tag('bgp'):
+                                with tag('name'): text(parameters['as'])
                                 with tag('global'):
                                     with tag('config'):
                                         with tag('as')       :text(parameters['as'])
-                                        if "router-id" in parameters: 
-                                            with tag('router-id'):text(parameters['router-id'])
-                if vendor == "ADVA": 
+                                        if "router_id" in parameters: 
+                                            with tag('router-id'):text(parameters['router_id'])
+                                if 'neighbors' in parameters:
+                                    with tag('neighbors'):
+                                        for neighbor in parameters['neighbors']:
+                                            with tag('neighbor'):
+                                                with tag('neighbor-address'): text(neighbor['ip_address'])
+                                                with tag('afi-safis'):
+                                                    with tag('afi-safi', 'xmlns:oc-bgp-types="http://openconfig.net/yang/bgp-types"'):
+                                                        with tag('afi-safi-name'): text('oc-bgp-types:IPV4_UNICAST')
+                                                        with tag('enabled'): text('true')
+                                                with tag('config'):
+                                                    with tag('neighbor-address'): text(neighbor['ip_address'])
+                                                    with tag('enabled'): text('true')
+                                                    with tag('peer-as'): text(parameters['as'])
+                if vendor is None or vendor == 'ADVA':
                     with tag('tables'):
                       with tag('table'):
                           with tag('protocol', 'xmlns:oc-pol-types="http://openconfig.net/yang/policy-types"'):text('oc-pol-types:',parameters['identifier'])
@@ -177,6 +194,9 @@ def associate_If_to_NI(parameters, DEL):
         else:
             with tag('network-instance'):
                 with tag('name'):text(parameters['name'])
+                with tag('config'):
+                    with tag('name'):text(parameters['name'])
+                    with tag('type', 'xmlns:oc-ni-types="http://openconfig.net/yang/network-instance-types"'):text('oc-ni-types:',parameters['type'])
                 with tag('interfaces'):
                     with tag('interface'):
                         with tag('id'):text(parameters['id'])
@@ -315,7 +335,7 @@ def create_table_conns(parameters,DEL):
                     with tag('table-connection','xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" nc:operation="delete"'):
                       with tag('src-protocol','xmlns:oc-pol-types="http://openconfig.net/yang/policy-types"'):   text('oc-pol-types:',parameters['src_protocol'])
                       with tag('dst-protocol','xmlns:oc-pol-types="http://openconfig.net/yang/policy-types"'):   text('oc-pol-types:',parameters['dst_protocol'])
-                      with tag('address-family', 'xmlns:oc-types="http://openconfig.net/yang/openconfig-types"'):text('oc-types:',parameters['dst_protocol'])     
+                      with tag('address-family', 'xmlns:oc-types="http://openconfig.net/yang/openconfig-types"'):text('oc-types:',parameters['address_family'])     
             else:
                 with tag('table-connections'):
                     with tag('table-connection'):
@@ -326,6 +346,8 @@ def create_table_conns(parameters,DEL):
                         with tag('src-protocol','xmlns:oc-pol-types="http://openconfig.net/yang/policy-types"'):   text('oc-pol-types:',parameters['src_protocol'])
                         with tag('dst-protocol','xmlns:oc-pol-types="http://openconfig.net/yang/policy-types"'):   text('oc-pol-types:',parameters['dst_protocol'])
                         with tag('address-family', 'xmlns:oc-types="http://openconfig.net/yang/openconfig-types"'):text('oc-types:',parameters['address_family'])    
+                        # for OCNOS: check if needed
+                        #with tag('dst-instance', 'xmlns="http://www.ipinfusion.com/yang/ocnos/ipi-oc-ni-augments"'):text('65000')
                         if len(parameters['default_import_policy']) != 0:
                             with tag('default-import-policy'):text(parameters['default_import_policy'])
     result = indent(
diff --git a/src/device/service/drivers/openconfig/templates/VPN/Routing_policy.py b/src/device/service/drivers/openconfig/templates/VPN/Routing_policy.py
index 5cc8cc71de9a952eecc8b3df2d71b6d38c496eb9..69fdd2cc52ec179665b6fc5a766b04b0e6c2a6ae 100644
--- a/src/device/service/drivers/openconfig/templates/VPN/Routing_policy.py
+++ b/src/device/service/drivers/openconfig/templates/VPN/Routing_policy.py
@@ -133,14 +133,14 @@ data_2 =    {'ext_community_member'     : '65001:101',
             'ext_community_set_name'    : 'set_srv_101_a'}
 
 print('\nRouting Policy Statement - CREATE\n')
-print(rp_statement(data_1, False))
+print(create_rp_statement(data_1, False))
 print('\nRouting Policy Statement - DELETE\n')
-print(rp_statement(data_1, True))
+print(create_rp_statement(data_1, True))
 
 print('\nRouting Policy Defined Set - CREATE\n')
-print(rp_defined_set(data_2, False))
+print(create_rp_def(data_2, False))
 print('\nRouting Policy Defined Set - DELETE\n')
-print(rp_defined_set(data_2, True))
+print(create_rp_def(data_2, True))
 '''
 
 '''
diff --git a/src/device/service/drivers/openconfig/templates/__init__.py b/src/device/service/drivers/openconfig/templates/__init__.py
index 0c1a057e7c07bebb0e41e295e8d44082bc3ef236..969ca9f60bd870ca7474f8b06a8b1948a03e84f6 100644
--- a/src/device/service/drivers/openconfig/templates/__init__.py
+++ b/src/device/service/drivers/openconfig/templates/__init__.py
@@ -121,7 +121,8 @@ def compose_config( # template generation
             templates.append(JINJA_ENV.get_template('acl/acl-set/acl-entry/edit_config.xml'))
             templates.append(JINJA_ENV.get_template('acl/interfaces/ingress/edit_config.xml'))
         data : Dict[str, Any] = json.loads(resource_value)
-        operation = 'delete' if delete else 'merge'
+        operation = 'delete' if delete else 'merge' # others
+        #operation = 'delete' if delete else '' # ipinfusion?
 
         return [
             '<config>{:s}</config>'.format(
diff --git a/src/device/service/drivers/openconfig/templates/interface/subinterface/edit_config.xml b/src/device/service/drivers/openconfig/templates/interface/subinterface/edit_config.xml
index e441004006e4cdd445f1d0244a9582b57956af40..2d8d3ee07b3a8df20a4b51be755e18b7aec982de 100644
--- a/src/device/service/drivers/openconfig/templates/interface/subinterface/edit_config.xml
+++ b/src/device/service/drivers/openconfig/templates/interface/subinterface/edit_config.xml
@@ -1,5 +1,4 @@
-<interfaces xmlns="http://openconfig.net/yang/interfaces" 
-            xmlns:oc-ip="http://openconfig.net/yang/interfaces/ip" >
+<interfaces xmlns="http://openconfig.net/yang/interfaces">
     <interface{% if operation is defined %} xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" nc:operation="{{operation}}"{% endif %}>
         <name>{{name}}</name>
         {% if operation is defined and operation != 'delete' %}
@@ -31,17 +30,20 @@
                 </vlan>
                 {% endif %}
                 {% if address_ip is defined %}
-                <oc-ip:ipv4>
-                    <oc-ip:addresses>
-                        <oc-ip:address>
-                            <oc-ip:ip>{{address_ip}}</oc-ip:ip>
-                            <oc-ip:config>
-                                <oc-ip:ip>{{address_ip}}</oc-ip:ip>
-                                <oc-ip:prefix-length>{{address_prefix}}</oc-ip:prefix-length>
-                            </oc-ip:config>
-                        </oc-ip:address>
-                    </oc-ip:addresses>
-                </oc-ip:ipv4>
+                <ipv4 xmlns="http://openconfig.net/yang/interfaces/ip">
+                    <config>
+                        {% if mtu is defined %}<mtu>{{mtu}}</mtu>{% endif%}
+                    </config>
+                    <addresses>
+                        <address>
+                            <ip>{{address_ip}}</ip>
+                            <config>
+                                <ip>{{address_ip}}</ip>
+                                <prefix-length>{{address_prefix}}</prefix-length>
+                            </config>
+                        </address>
+                    </addresses>
+                </ipv4>
                 {% endif %}
             </subinterface>
         </subinterfaces>
diff --git a/src/device/service/drivers/openconfig/templates/network_instance/interface/edit_config.xml b/src/device/service/drivers/openconfig/templates/network_instance/interface/edit_config.xml
index 855f321b4a69ba1e660487c108a05d0ec4b5d475..e926796d039d54e30f6ba13eb5eb66bcec079c08 100644
--- a/src/device/service/drivers/openconfig/templates/network_instance/interface/edit_config.xml
+++ b/src/device/service/drivers/openconfig/templates/network_instance/interface/edit_config.xml
@@ -1,6 +1,10 @@
 <network-instances xmlns="http://openconfig.net/yang/network-instance">
     <network-instance>
         <name>{{name}}</name>
+        <config>
+            <name>{{name}}</name>
+            <type xmlns:oc-ni-types="http://openconfig.net/yang/network-instance-types">oc-ni-types:{{type}}</type>
+        </config>
         <interfaces>
             <interface{% if operation is defined %} xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0" nc:operation="{{operation}}"{% endif %}>
                 <id>{{id}}</id>
diff --git a/src/device/service/drivers/openconfig/templates/network_instance/protocols/edit_config.xml b/src/device/service/drivers/openconfig/templates/network_instance/protocols/edit_config.xml
index c9c068e480c0569cfe5f97b78b28fbe03e2595f8..da66d97f053f509a1a595cdb1abc0bd1791ad0bc 100644
--- a/src/device/service/drivers/openconfig/templates/network_instance/protocols/edit_config.xml
+++ b/src/device/service/drivers/openconfig/templates/network_instance/protocols/edit_config.xml
@@ -9,15 +9,37 @@
                 <config>
                     <identifier xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:{{identifier}}</identifier>
                     <name>{{protocol_name}}</name>
+                    <enabled>true</enabled>
                 </config>
                 {% if identifier=='BGP' %}
                 <bgp>
+                    <name>{{as}}</name>
                     <global>
                         <config>
                             <as>{{as}}</as>
                             <router-id>{{router_id}}</router-id>
                         </config>
                     </global>
+                    {% if neighbors is defined %}
+                    <neighbors>
+                        {% for neighbor in neighbors %}
+                        <neighbor>
+                            <neighbor-address>{{neighbor['ip_address']}}</neighbor-address>
+                            <afi-safis>
+                                <afi-safi xmlns:oc-bgp-types="http://openconfig.net/yang/bgp-types">
+                                    <afi-safi-name>oc-bgp-types:IPV4_UNICAST</afi-safi-name>
+                                    <enabled>true</enabled>
+                                </afi-safi>
+                            </afi-safis>
+                            <config>
+                                <neighbor-address>{{neighbor['ip_address']}}</neighbor-address>
+                                <enabled>true</enabled>
+                                <peer-as>{{as}}</peer-as>
+                            </config>
+                        </neighbor>
+                        {% endfor %}
+                    </neighbors>
+                    {% endif %}
                 </bgp>
                 {% endif %}
                 {% endif %}
diff --git a/src/device/service/drivers/openconfig/templates/network_instance/table_connections/edit_config.xml b/src/device/service/drivers/openconfig/templates/network_instance/table_connections/edit_config.xml
index 46bf5e387789c7efc800ad96ed759748273bed34..35c535c6bd3f78e30fc2177ecc722b1115f54fc5 100644
--- a/src/device/service/drivers/openconfig/templates/network_instance/table_connections/edit_config.xml
+++ b/src/device/service/drivers/openconfig/templates/network_instance/table_connections/edit_config.xml
@@ -11,6 +11,9 @@
                     <src-protocol xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:{{src_protocol}}</src-protocol>
                     <dst-protocol xmlns:oc-pol-types="http://openconfig.net/yang/policy-types">oc-pol-types:{{dst_protocol}}</dst-protocol>
                     <address-family xmlns:oc-types="http://openconfig.net/yang/openconfig-types">oc-types:{{address_family}}</address-family>
+                    {% if False %}
+                        <dst-instance xmlns="http://www.ipinfusion.com/yang/ocnos/ipi-oc-ni-augments">{{as}}</dst-instance>
+                    {% endif %}
                     {% if default_import_policy is defined %}<default-import-policy>{{default_import_policy}}</default-import-policy>{% endif %}
                 </config>
                 {% endif %}
diff --git a/src/device/tests/test_unitary_openconfig_ocnos.py b/src/device/tests/test_unitary_openconfig_ocnos.py
new file mode 100644
index 0000000000000000000000000000000000000000..87d951581ad98147f8dd565af616fe034a346693
--- /dev/null
+++ b/src/device/tests/test_unitary_openconfig_ocnos.py
@@ -0,0 +1,210 @@
+# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/)
+#
+# 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, logging, os, pytest, time
+from typing import Dict, Tuple
+os.environ['DEVICE_EMULATED_ONLY'] = 'YES'
+
+# pylint: disable=wrong-import-position
+from device.service.drivers.openconfig.OpenConfigDriver import OpenConfigDriver
+#from device.service.driver_api._Driver import (
+#    RESOURCE_ENDPOINTS, RESOURCE_INTERFACES, RESOURCE_NETWORK_INSTANCES, RESOURCE_ROUTING_POLICIES, RESOURCE_SERVICES
+#)
+
+logging.basicConfig(level=logging.DEBUG)
+#logging.getLogger('ncclient.operations.rpc').setLevel(logging.INFO)
+#logging.getLogger('ncclient.transport.parser').setLevel(logging.INFO)
+
+LOGGER = logging.getLogger(__name__)
+
+
+##### DRIVERS FIXTURE ##################################################################################################
+
+DEVICES = {
+    'CSGW1': {'address': '10.1.1.86', 'port': 830, 'settings': {
+        'username': 'ocnos', 'password': 'ocnos',
+        'vendor': None, 'force_running': False, 'hostkey_verify': False, 'look_for_keys': False, 'allow_agent': False,
+        'commit_per_rule': True, 'device_params': {'name': 'default'}, 'manager_params': {'timeout' : 120}
+    }},
+    'CSGW2': {'address': '10.1.1.87', 'port': 830, 'settings': {
+        'username': 'ocnos', 'password': 'ocnos',
+        'vendor': None, 'force_running': False, 'hostkey_verify': False, 'look_for_keys': False, 'allow_agent': False,
+        'commit_per_rule': True, 'device_params': {'name': 'default'}, 'manager_params': {'timeout' : 120}
+    }},
+}
+
+@pytest.fixture(scope='session')
+def drivers() -> Dict[str, OpenConfigDriver]:
+    _drivers : Dict[str, OpenConfigDriver] = dict()
+    for device_name, driver_params in DEVICES.items():
+        driver = OpenConfigDriver(driver_params['address'], driver_params['port'], **(driver_params['settings']))
+        driver.Connect()
+        _drivers[device_name] = driver
+    yield _drivers
+    time.sleep(1)
+    for _,driver in _drivers.items():
+        driver.Disconnect()
+
+
+def network_instance(ni_name, ni_type, ni_router_id=None, ni_route_distinguisher=None) -> Tuple[str, Dict]:
+    path = '/network_instance[{:s}]'.format(ni_name)
+    data = {'name': ni_name, 'type': ni_type}
+    if ni_router_id is not None: data['router_id'] = ni_router_id
+    if ni_route_distinguisher is not None: data['route_distinguisher'] = ni_route_distinguisher
+    return path, json.dumps(data)
+
+def network_instance_add_protocol_bgp(ni_name, ni_type, ni_router_id, ni_bgp_as, neighbors=[]) -> Tuple[str, Dict]:
+    path = '/network_instance[{:s}]/protocols[BGP]'.format(ni_name)
+    data = {
+        'name': ni_name, 'type': ni_type, 'router_id': ni_router_id, 'identifier': 'BGP',
+        'protocol_name': ni_bgp_as, 'as': ni_bgp_as
+    }
+    if len(neighbors) > 0:
+        data['neighbors'] = [
+            {'ip_address': neighbor_ip_address, 'remote_as': neighbor_remote_as}
+            for neighbor_ip_address, neighbor_remote_as in neighbors
+        ]
+    return path, json.dumps(data)
+
+def network_instance_add_protocol_direct(ni_name, ni_type) -> Tuple[str, Dict]:
+    path = '/network_instance[{:s}]/protocols[DIRECTLY_CONNECTED]'.format(ni_name)
+    data = {
+        'name': ni_name, 'type': ni_type, 'identifier': 'DIRECTLY_CONNECTED',
+        'protocol_name': 'DIRECTLY_CONNECTED'
+    }
+    return path, json.dumps(data)
+
+def network_instance_add_protocol_static(ni_name, ni_type) -> Tuple[str, Dict]:
+    path = '/network_instance[{:s}]/protocols[STATIC]'.format(ni_name)
+    data = {
+        'name': ni_name, 'type': ni_type, 'identifier': 'STATIC',
+        'protocol_name': 'STATIC'
+    }
+    return path, json.dumps(data)
+
+#def network_instance_static_route(ni_name, prefix, next_hop, next_hop_index=0) -> Tuple[str, Dict]:
+#    path = '/network_instance[{:s}]/static_route[{:s}]'.format(ni_name, prefix)
+#    data = {'name': ni_name, 'prefix': prefix, 'next_hop': next_hop, 'next_hop_index': next_hop_index}
+#    return path, json.dumps(data)
+
+def network_instance_add_table_connection(
+    ni_name, src_protocol, dst_protocol, address_family, default_import_policy, bgp_as=None
+) -> Tuple[str, Dict]:
+    path = '/network_instance[{:s}]/table_connections[{:s}][{:s}][{:s}]'.format(
+        ni_name, src_protocol, dst_protocol, address_family
+    )
+    data = {
+        'name': ni_name, 'src_protocol': src_protocol, 'dst_protocol': dst_protocol,
+        'address_family': address_family, 'default_import_policy': default_import_policy,
+    }
+    if bgp_as is not None: data['as'] = bgp_as
+    return path, json.dumps(data)
+
+def interface(
+    name, index, description=None, if_type=None, vlan_id=None, mtu=None, ipv4_address_prefix=None, enabled=None
+) -> Tuple[str, Dict]:
+    path = '/interface[{:s}]/subinterface[{:d}]'.format(name, index)
+    data = {'name': name, 'index': index}
+    if description is not None: data['description'] = description
+    if if_type     is not None: data['type'       ] = if_type
+    if vlan_id     is not None: data['vlan_id'    ] = vlan_id
+    if mtu         is not None: data['mtu'        ] = mtu
+    if enabled     is not None: data['enabled'    ] = enabled
+    if ipv4_address_prefix is not None:
+        ipv4_address, ipv4_prefix = ipv4_address_prefix
+        data['address_ip'    ] = ipv4_address
+        data['address_prefix'] = ipv4_prefix
+    return path, json.dumps(data)
+
+def network_instance_interface(ni_name, ni_type, if_name, if_index) -> Tuple[str, Dict]:
+    path = '/network_instance[{:s}]/interface[{:s}.{:d}]'.format(ni_name, if_name, if_index)
+    data = {'name': ni_name, 'type': ni_type, 'id': if_name, 'interface': if_name, 'subinterface': if_index}
+    return path, json.dumps(data)
+
+def test_configure(drivers : Dict[str, OpenConfigDriver]):
+    #resources_to_get = []
+    #resources_to_get = [RESOURCE_ENDPOINTS]
+    #resources_to_get = [RESOURCE_INTERFACES]
+    #resources_to_get = [RESOURCE_NETWORK_INSTANCES]
+    #resources_to_get = [RESOURCE_ROUTING_POLICIES]
+    #resources_to_get = [RESOURCE_SERVICES]
+    #LOGGER.info('resources_to_get = {:s}'.format(str(resources_to_get)))
+    #results_getconfig = driver.GetConfig(resources_to_get)
+    #LOGGER.info('results_getconfig = {:s}'.format(str(results_getconfig)))
+
+    csgw1_resources_to_set = [
+        network_instance('ecoc24', 'L3VRF', '192.168.150.1', '65001:1'),
+        network_instance_add_protocol_direct('ecoc24', 'L3VRF'),
+        network_instance_add_protocol_static('ecoc24', 'L3VRF'),
+        network_instance_add_protocol_bgp('ecoc24', 'L3VRF', '192.168.150.1', '65001', neighbors=[
+            ('192.168.150.2', '65001')
+        ]),
+        network_instance_add_table_connection('ecoc24', 'DIRECTLY_CONNECTED', 'BGP', 'IPV4', 'ACCEPT_ROUTE', bgp_as='65001'),
+        network_instance_add_table_connection('ecoc24', 'STATIC', 'BGP', 'IPV4', 'ACCEPT_ROUTE', bgp_as='65001'),
+    
+        interface('ce1', 0, if_type='ethernetCsmacd', mtu=1500),
+        network_instance_interface('ecoc24', 'L3VRF', 'ce1', 0),
+        interface('ce1', 0, if_type='ethernetCsmacd', mtu=1500, ipv4_address_prefix=('192.168.10.1', 24), enabled=True),
+    
+        interface('xe5', 0, if_type='ethernetCsmacd', mtu=1500),
+        network_instance_interface('ecoc24', 'L3VRF', 'xe5', 0),
+        interface('xe5', 0, if_type='ethernetCsmacd', mtu=1500, ipv4_address_prefix=('192.168.150.1', 24), enabled=True),
+    ]
+    LOGGER.info('CSGW1 resources_to_set = {:s}'.format(str(csgw1_resources_to_set)))
+    results_setconfig = drivers['CSGW1'].SetConfig(csgw1_resources_to_set)
+    LOGGER.info('CSGW1 results_setconfig = {:s}'.format(str(results_setconfig)))
+
+    csgw2_resources_to_set = [
+        network_instance('ecoc24', 'L3VRF', '192.168.150.2', '65001:1'),
+        network_instance_add_protocol_direct('ecoc24', 'L3VRF'),
+        network_instance_add_protocol_static('ecoc24', 'L3VRF'),
+        network_instance_add_protocol_bgp('ecoc24', 'L3VRF', '192.168.150.2', '65001', neighbors=[
+            ('192.168.150.1', '65001')
+        ]),
+        network_instance_add_table_connection('ecoc24', 'DIRECTLY_CONNECTED', 'BGP', 'IPV4', 'ACCEPT_ROUTE', bgp_as='65001'),
+        network_instance_add_table_connection('ecoc24', 'STATIC', 'BGP', 'IPV4', 'ACCEPT_ROUTE', bgp_as='65001'),
+    
+        interface('ce1', 0, if_type='ethernetCsmacd', mtu=1500),
+        network_instance_interface('ecoc24', 'L3VRF', 'ce1', 0),
+        interface('ce1', 0, if_type='ethernetCsmacd', mtu=1500, ipv4_address_prefix=('192.168.20.1', 24), enabled=True),
+    
+        interface('xe5', 0, if_type='ethernetCsmacd', mtu=1500),
+        network_instance_interface('ecoc24', 'L3VRF', 'xe5', 0),
+        interface('xe5', 0, if_type='ethernetCsmacd', mtu=1500, ipv4_address_prefix=('192.168.150.2', 24), enabled=True),
+    ]
+    LOGGER.info('CSGW2 resources_to_set = {:s}'.format(str(csgw2_resources_to_set)))
+    results_setconfig = drivers['CSGW2'].SetConfig(csgw2_resources_to_set)
+    LOGGER.info('CSGW2 results_setconfig = {:s}'.format(str(results_setconfig)))
+
+    csgw1_resources_to_delete = [
+        network_instance_interface('ecoc24', 'L3VRF', 'ce1', 0),
+        network_instance_interface('ecoc24', 'L3VRF', 'xe5', 0),
+        #interface('ce1', 0),
+        #interface('xe5', 0),
+        network_instance('ecoc24', 'L3VRF'),
+    ]
+    LOGGER.info('CSGW1 resources_to_delete = {:s}'.format(str(csgw1_resources_to_delete)))
+    results_deleteconfig = drivers['CSGW1'].DeleteConfig(csgw1_resources_to_delete)
+    LOGGER.info('CSGW1 results_deleteconfig = {:s}'.format(str(results_deleteconfig)))
+
+    csgw2_resources_to_delete = [
+        network_instance_interface('ecoc24', 'L3VRF', 'ce1', 0),
+        network_instance_interface('ecoc24', 'L3VRF', 'xe5', 0),
+        #interface('ce1', 0),
+        #interface('xe5', 0),
+        network_instance('ecoc24', 'L3VRF'),
+    ]
+    LOGGER.info('CSGW2 resources_to_delete = {:s}'.format(str(csgw2_resources_to_delete)))
+    results_deleteconfig = drivers['CSGW2'].DeleteConfig(csgw2_resources_to_delete)
+    LOGGER.info('CSGW2 results_deleteconfig = {:s}'.format(str(results_deleteconfig)))
diff --git a/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Resources.py b/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Resources.py
index 4c6ad47bc210316908ed3e3676abbda6757cf615..88754adae376347851c818c596a4d7d9764a3c3b 100644
--- a/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Resources.py
+++ b/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Resources.py
@@ -13,7 +13,9 @@
 # limitations under the License.
 
 import copy, deepmerge, json, logging
+from typing import Dict
 from common.Constants import DEFAULT_CONTEXT_NAME
+from werkzeug.exceptions import UnsupportedMediaType
 from context.client.ContextClient import ContextClient
 from flask_restful import Resource, request
 from service.client.ServiceClient import ServiceClient
@@ -37,15 +39,20 @@ class BwInfo(_Resource):
         return bw_allocations
 
     def post(self):
-        bwinfo = request.get_json()
-        service = bwInfo_2_service(self.client, bwinfo)
+        if not request.is_json:
+            raise UnsupportedMediaType('JSON payload is required')
+        request_data: Dict = request.get_json()
+        service = bwInfo_2_service(self.client, request_data)
         stripped_service = copy.deepcopy(service)
         stripped_service.ClearField('service_endpoint_ids')
         stripped_service.ClearField('service_constraints')
         stripped_service.ClearField('service_config')
 
-        response = format_grpc_to_json(self.service_client.CreateService(stripped_service))
-        response = format_grpc_to_json(self.service_client.UpdateService(service))
+        try:
+            response = format_grpc_to_json(self.service_client.CreateService(stripped_service))
+            response = format_grpc_to_json(self.service_client.UpdateService(service))
+        except Exception as e: # pylint: disable=broad-except
+            return e
 
         return response
 
diff --git a/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Tools.py b/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Tools.py
index 59436708cca2fcf7ff0ff65aa4977e2ccfaeda95..111f6f48482d4f2a0e494b0bd2e49eadee25ee60 100644
--- a/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Tools.py
+++ b/src/nbi/service/rest_server/nbi_plugins/etsi_bwm/Tools.py
@@ -14,22 +14,41 @@
 
 import json
 import logging
+import re
 import time
 from decimal import ROUND_HALF_EVEN, Decimal
 from flask.json import jsonify
 from common.proto.context_pb2 import (
-    ContextId, Empty, EndPointId, ServiceId, ServiceTypeEnum, Service, Constraint, Constraint_SLA_Capacity,
+    ContextId, Empty, EndPointId, ServiceId, ServiceTypeEnum, Service, ServiceStatusEnum, Constraint, Constraint_SLA_Capacity,
     ConfigRule, ConfigRule_Custom, ConfigActionEnum)
 from common.tools.grpc.Tools import grpc_message_to_json
+from common.tools.grpc.ConfigRules import update_config_rule_custom
 from common.tools.object_factory.Context import json_context_id
 from common.tools.object_factory.Service import json_service_id
 
 LOGGER = logging.getLogger(__name__)
 
+ENDPOINT_SETTINGS_KEY = '/device[{:s}]/endpoint[{:s}]/vlan[{:d}]/settings'
+DEVICE_SETTINGS_KEY = '/device[{:s}]/settings'
+RE_CONFIG_RULE_IF_SUBIF = re.compile(r'^\/interface\[([^\]]+)\]\/subinterface\[([^\]]+)\]$')
+MEC_CONSIDERED_FIELDS = ['requestType', 'sessionFilter', 'fixedAllocation', 'allocationDirection', 'fixedBWPriority']
+ALLOCATION_DIRECTION_DESCRIPTIONS = {
+    '00' : 'Downlink (towards the UE)',
+    '01' : 'Uplink (towards the application/session)',
+    '10' : 'Symmetrical'}
+VLAN_TAG = 0
+PREFIX_LENGTH = 24
+BGP_AS = 65000
+POLICY_AZ = 'srv_{:d}_a'.format(VLAN_TAG)
+POLICY_ZA = 'srv_{:d}_b'.format(VLAN_TAG)
+BGP_NEIGHBOR_IP_A = '192.168.150.1'
+BGP_NEIGHBOR_IP_Z = '192.168.150.2'
+ROUTER_ID_A = '200.1.1.1'
+ROUTER_ID_Z = '200.1.1.2'
+ROUTE_DISTINGUISHER = '{:5d}:{:03d}'.format(BGP_AS, VLAN_TAG)
 
 def service_2_bwInfo(service: Service) -> dict:
     response = {}
-    # allocationDirection = '??' # String: 00 = Downlink (towards the UE); 01 = Uplink (towards the application/session); 10 = Symmetrical
     response['appInsId'] = service.service_id.service_uuid.uuid # String: Application instance identifier
     for constraint in service.service_constraints:
         if constraint.WhichOneof('constraint') == 'sla_capacity':
@@ -40,12 +59,19 @@ def service_2_bwInfo(service: Service) -> dict:
             break
 
     for config_rule in service.service_config.config_rules:
+        resource_value_json = json.loads(config_rule.custom.resource_value)
+        if config_rule.custom.resource_key != '/request':
+            continue
         for key in ['allocationDirection', 'fixedBWPriority', 'requestType', 'sourceIp', 'sourcePort', 'dstPort', 'protocol', 'sessionFilter']:
-            if config_rule.custom.resource_key == key:
-                if key != 'sessionFilter':
-                    response[key] = config_rule.custom.resource_value
-                else:
-                    response[key] = json.loads(config_rule.custom.resource_value)
+            if key not in resource_value_json: 
+                continue
+
+            if key == 'sessionFilter':
+                response[key] = [resource_value_json[key]]
+            elif key == 'requestType':
+                response[key] = str(resource_value_json[key])
+            else:
+                response[key] = resource_value_json[key]
 
     unixtime = time.time()
     response['timeStamp'] = { # Time stamp to indicate when the corresponding information elements are sent
@@ -55,47 +81,108 @@ def service_2_bwInfo(service: Service) -> dict:
 
     return response
 
-def bwInfo_2_service(client, bwInfo: dict) -> Service:
+def bwInfo_2_service(client, bw_info: dict) -> Service:
+    # add description to allocationDirection code
+    if 'sessionFilter' in bw_info:
+        bw_info['sessionFilter'] = bw_info['sessionFilter'][0] # Discard other items in sessionFilter field
+
     service = Service()
-    for key in ['allocationDirection', 'fixedBWPriority', 'requestType', 'timeStamp', 'sessionFilter']:
-        if key not in bwInfo:
-            continue
-        config_rule = ConfigRule()
-        config_rule.action = ConfigActionEnum.CONFIGACTION_SET
-        config_rule_custom = ConfigRule_Custom()
-        config_rule_custom.resource_key  = key
-        if key != 'sessionFilter':
-            config_rule_custom.resource_value  = str(bwInfo[key])
-        else:
-            config_rule_custom.resource_value  = json.dumps(bwInfo[key])
-        config_rule.custom.CopyFrom(config_rule_custom)
-        service.service_config.config_rules.append(config_rule)
-
-    if 'sessionFilter' in bwInfo:
-        a_ip = bwInfo['sessionFilter'][0]['sourceIp']
-        z_ip = bwInfo['sessionFilter'][0]['dstAddress']
+    
+    service_config_rules = service.service_config.config_rules
+
+
+    request_cr_key = '/request'
+    request_cr_value = {k:bw_info[k] for k in MEC_CONSIDERED_FIELDS}
+
+    config_rule = ConfigRule()
+    config_rule.action = ConfigActionEnum.CONFIGACTION_SET
+    config_rule_custom = ConfigRule_Custom()
+    config_rule_custom.resource_key  = request_cr_key
+    config_rule_custom.resource_value = json.dumps(request_cr_value)
+    config_rule.custom.CopyFrom(config_rule_custom)
+    service_config_rules.append(config_rule)
+
+    if 'sessionFilter' in bw_info:
+        a_ip = bw_info['sessionFilter']['sourceIp']
+        z_ip = bw_info['sessionFilter']['dstAddress']
 
         devices = client.ListDevices(Empty()).devices
+        ip_interface_name_dict = {}
         for device in devices:
+            device_endpoint_uuids = {ep.name:ep.endpoint_id.endpoint_uuid.uuid for ep in device.device_endpoints}
+            skip_device = True
             for cr in device.device_config.config_rules:
-                if cr.WhichOneof('config_rule') == 'custom' and cr.custom.resource_key == '_connect/settings':
-                    for ep in json.loads(cr.custom.resource_value)['endpoints']:
-                        if 'ip' in ep and (ep['ip'] == a_ip or ep['ip'] == z_ip):
-                            ep_id = EndPointId()
-                            ep_id.endpoint_uuid.uuid = ep['uuid']
-                            ep_id.device_id.device_uuid.uuid = device.device_id.device_uuid.uuid
-                            service.service_endpoint_ids.append(ep_id)
-
+                if cr.WhichOneof('config_rule') != 'custom':
+                    continue
+                match_subif = RE_CONFIG_RULE_IF_SUBIF.match(cr.custom.resource_key)
+                if not match_subif:
+                    continue
+                address_ip = json.loads(cr.custom.resource_value).get('address_ip')
+                short_port_name = match_subif.groups(0)[0]
+                ip_interface_name_dict[address_ip] = short_port_name
+                if address_ip not in [a_ip, z_ip]:
+                    continue
+                port_name = 'PORT-' + short_port_name # `PORT-` added as prefix
+                ep_id = EndPointId()
+                ep_id.endpoint_uuid.uuid = device_endpoint_uuids[port_name]
+                ep_id.device_id.device_uuid.uuid = device.device_id.device_uuid.uuid
+                service.service_endpoint_ids.append(ep_id)
+                # add interface config rules
+                endpoint_settings_key = ENDPOINT_SETTINGS_KEY.format(device.name, port_name, VLAN_TAG)
+                if address_ip in a_ip:
+                    router_id = ROUTER_ID_A
+                    policy_az = POLICY_AZ
+                    policy_za = POLICY_ZA
+                    neighbor_bgp_interface_address_ip = BGP_NEIGHBOR_IP_Z
+                    self_bgp_interface_address_ip = BGP_NEIGHBOR_IP_A
+                else:
+                    router_id = ROUTER_ID_Z
+                    policy_az = POLICY_ZA
+                    policy_za = POLICY_AZ
+                    neighbor_bgp_interface_address_ip= BGP_NEIGHBOR_IP_A
+                    self_bgp_interface_address_ip = BGP_NEIGHBOR_IP_Z
+                endpoint_field_updates = {
+                    'address_ip': (address_ip, True),
+                    'address_prefix'     : (PREFIX_LENGTH, True),
+                    'sub_interface_index': (0, True),
+                        }
+                LOGGER.debug(f'BEFORE UPDATE -> device.device_config.config_rules: {service_config_rules}')
+                update_config_rule_custom(service_config_rules, endpoint_settings_key, endpoint_field_updates)
+                LOGGER.debug(f'AFTER UPDATE -> device.device_config.config_rules: {service_config_rules}')
+                skip_device = False
+            if skip_device:
+                continue
+            device_field_updates = {
+                         'bgp_as':(BGP_AS, True),
+                         'route_distinguisher': (ROUTE_DISTINGUISHER, True),
+                         'router_id': (router_id, True),
+                         'policy_AZ': (policy_az, True),
+                         'policy_ZA': (policy_za, True),
+                         'neighbor_bgp_interface_address_ip': (neighbor_bgp_interface_address_ip, True),
+                         'self_bgp_interface_name': (ip_interface_name_dict[self_bgp_interface_address_ip], True),
+                         'self_bgp_interface_address_ip': (self_bgp_interface_address_ip, True),
+                         'bgp_interface_address_prefix': (PREFIX_LENGTH, True)
+                        }
+            device_settings_key = DEVICE_SETTINGS_KEY.format(device.name)
+            LOGGER.debug(f'BEFORE UPDATE -> device.device_config.config_rules: {service_config_rules}')
+            update_config_rule_custom(service_config_rules, device_settings_key, device_field_updates)
+            LOGGER.debug(f'AFTER UPDATE -> device.device_config.config_rules: {service_config_rules}')
+    
+    settings_cr_key = '/settings'
+    settings_cr_value = {}
+    update_config_rule_custom(service_config_rules, settings_cr_key, settings_cr_value)
+
+    service.service_status.service_status = ServiceStatusEnum.SERVICESTATUS_PLANNED
     service.service_type = ServiceTypeEnum.SERVICETYPE_L3NM
 
-    if 'appInsId' in bwInfo:
-        service.service_id.service_uuid.uuid = bwInfo['appInsId']
+    if 'appInsId' in bw_info:
+        service.service_id.service_uuid.uuid = bw_info['appInsId']
         service.service_id.context_id.context_uuid.uuid = 'admin'
-        service.name = bwInfo['appInsId']
+        service.name = bw_info['appInsId']
 
-    if 'fixedAllocation' in bwInfo:
+    if 'fixedAllocation' in bw_info:
         capacity = Constraint_SLA_Capacity()
-        capacity.capacity_gbps = float(bwInfo['fixedAllocation']) / 1.e9
+        capacity.capacity_gbps = float(bw_info['fixedAllocation']) / 1.e9
         constraint = Constraint()
         constraint.sla_capacity.CopyFrom(capacity)
         service.service_constraints.append(constraint)
diff --git a/src/pathcomp/frontend/service/algorithms/tools/ComposeConfigRules.py b/src/pathcomp/frontend/service/algorithms/tools/ComposeConfigRules.py
index 0c98254729afd0b2089c84499a9c739e985b27f5..f92f9b2fff11ab585813ab59e07c463f361413d2 100644
--- a/src/pathcomp/frontend/service/algorithms/tools/ComposeConfigRules.py
+++ b/src/pathcomp/frontend/service/algorithms/tools/ComposeConfigRules.py
@@ -184,6 +184,10 @@ def compose_device_config_rules(
 
                 device_endpoint_keys = set(itertools.product(device_keys, endpoint_keys))
                 if len(device_endpoint_keys.intersection(endpoints_traversed)) == 0: continue
+
+                # TODO: check if vlan needs to be removed from config_rule
+                #config_rule.custom.resource_key = re.sub('\/vlan\[[^\]]+\]', '', config_rule.custom.resource_key)
+
                 subservice_config_rules.append(config_rule)
         else:
             continue
diff --git a/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py b/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py
index 4e9ceabc3add1bae949f751f36e2a6f8cb237fa6..7527932877f47a092a35f286defb3744e05db109 100644
--- a/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py
+++ b/src/service/service/service_handlers/l3nm_openconfig/ConfigRules.py
@@ -12,24 +12,35 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from typing import Dict, List, Tuple
+from typing import Any, Dict, List, Optional, Tuple
 from common.tools.object_factory.ConfigRule import json_config_rule_delete, json_config_rule_set
 from service.service.service_handler_api.AnyTreeTools import TreeNode
 
+def get_value(field_name : str, *containers, default=None) -> Optional[Any]:
+    if len(containers) == 0: raise Exception('No containers specified')
+    for container in containers:
+        if field_name not in container: continue
+        return container[field_name]
+    return default
+
 def setup_config_rules(
     service_uuid : str, connection_uuid : str, device_uuid : str, endpoint_uuid : str, endpoint_name : str,
-    service_settings : TreeNode, endpoint_settings : TreeNode, endpoint_acls : List [Tuple]
+    service_settings : TreeNode, device_settings : TreeNode, endpoint_settings : TreeNode, endpoint_acls : List [Tuple]
 ) -> List[Dict]:
 
     if service_settings  is None: return []
+    if device_settings   is None: return []
     if endpoint_settings is None: return []
 
     json_settings          : Dict = service_settings.value
+    json_device_settings   : Dict = device_settings.value
     json_endpoint_settings : Dict = endpoint_settings.value
 
-    mtu                       = json_settings.get('mtu',                          1450     )  # 1512
+    settings = (json_settings, json_endpoint_settings, json_device_settings)
+
+    mtu                       = get_value('mtu', *settings, default=1450)   # 1512
     #address_families         = json_settings.get('address_families',             []       )  # ['IPV4']
-    bgp_as                    = json_settings.get('bgp_as',                       65000    )  # 65000
+    bgp_as                    = get_value('bgp_as', *settings, default=65000)   # 65000
 
     router_id                 = json_endpoint_settings.get('router_id',           '0.0.0.0')  # '10.95.0.10'
     route_distinguisher       = json_settings.get('route_distinguisher',          '65000:101'    )  # '60001:801'
@@ -76,6 +87,7 @@ def setup_config_rules(
                 'name': network_instance_name, 
                 'protocol_name': 'BGP', 
                 'identifier': 'BGP', 
+                'type': 'L3VRF',
                 'as': bgp_as,
                 'router_id': router_id, 
         }),
@@ -88,7 +100,6 @@ def setup_config_rules(
                 'protocol_name': 'DIRECTLY_CONNECTED',
         }),
 
-        
         #Add STATIC protocol to network instance
         json_config_rule_set(
             '/network_instance[{:s}]/protocols[STATIC]'.format(network_instance_name), {
@@ -114,6 +125,7 @@ def setup_config_rules(
         json_config_rule_set(
             '/network_instance[{:s}]/interface[{:s}]'.format(network_instance_name, if_subif_name), {
                 'name'        : network_instance_name, 
+                'type'        : 'L3VRF',
                 'id'          : if_subif_name, 
                 'interface'   : if_subif_name,
                 'subinterface': sub_interface_index,
@@ -183,6 +195,7 @@ def setup_config_rules(
         }),
 
     ]
+
     for res_key, res_value in endpoint_acls:
         json_config_rules.append(
                {'action': 1, 'acl': res_value}
@@ -191,23 +204,27 @@ def setup_config_rules(
 
 def teardown_config_rules(
     service_uuid : str, connection_uuid : str, device_uuid : str, endpoint_uuid : str, endpoint_name : str,
-    service_settings : TreeNode, endpoint_settings : TreeNode
+    service_settings : TreeNode, device_settings : TreeNode, endpoint_settings : TreeNode
 ) -> List[Dict]:
 
     if service_settings  is None: return []
+    if device_settings   is None: return []
     if endpoint_settings is None: return []
 
     json_settings          : Dict = service_settings.value
+    json_device_settings   : Dict = device_settings.value
     json_endpoint_settings : Dict = endpoint_settings.value
 
+    settings = (json_settings, json_endpoint_settings, json_device_settings)
+
     service_short_uuid        = service_uuid.split('-')[-1]
     network_instance_name     = '{:s}-NetInst'.format(service_short_uuid)
     #network_interface_desc    = '{:s}-NetIf'.format(service_uuid)
     #network_subinterface_desc = '{:s}-NetSubIf'.format(service_uuid)
 
-    #mtu                 = json_settings.get('mtu',                          1450     )  # 1512
+    #mtu                       = get_value('mtu', *settings, default=1450)   # 1512
     #address_families    = json_settings.get('address_families',             []       )  # ['IPV4']
-    #bgp_as              = json_settings.get('bgp_as',                       65000    )  # 65000
+    #bgp_as                    = get_value('bgp_as', *settings, default=65000)   # 65000
     route_distinguisher = json_settings.get('route_distinguisher',          '0:0'    )  # '60001:801'
     #sub_interface_index = json_endpoint_settings.get('sub_interface_index', 0        )  # 1
     #router_id           = json_endpoint_settings.get('router_id',           '0.0.0.0')  # '10.95.0.10'
diff --git a/src/service/service/service_handlers/l3nm_openconfig/ConfigRules_test_ocnos.py b/src/service/service/service_handlers/l3nm_openconfig/ConfigRules_test_ocnos.py
new file mode 100644
index 0000000000000000000000000000000000000000..5fa1d0b5b6931902b4ac50847c90bf67738032ba
--- /dev/null
+++ b/src/service/service/service_handlers/l3nm_openconfig/ConfigRules_test_ocnos.py
@@ -0,0 +1,337 @@
+# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/)
+#
+# 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.
+
+from typing import Dict, List, Tuple
+from common.tools.object_factory.ConfigRule import json_config_rule_delete, json_config_rule_set
+from service.service.service_handler_api.AnyTreeTools import TreeNode
+
+def setup_config_rules(
+    service_uuid : str, connection_uuid : str, device_uuid : str, endpoint_uuid : str, endpoint_name : str,
+    service_settings : TreeNode, device_settings : TreeNode, endpoint_settings : TreeNode, endpoint_acls : List [Tuple]
+) -> List[Dict]:
+
+    if service_settings  is None: return []
+    if device_settings   is None: return []
+    if endpoint_settings is None: return []
+
+    json_settings          : Dict = service_settings.value
+    json_device_settings   : Dict = device_settings.value
+    json_endpoint_settings : Dict = endpoint_settings.value
+
+    mtu                       = json_settings.get('mtu',                          1450     )  # 1512
+    #address_families         = json_settings.get('address_families',             []       )  # ['IPV4']
+    bgp_as                    = json_device_settings.get('bgp_as',                       65000    )  # 65000
+
+    router_id                 = json_device_settings.get('router_id',           '0.0.0.0')  # '10.95.0.10'
+    route_distinguisher       = json_device_settings.get('route_distinguisher',          '65000:101'    )  # '60001:801'
+    sub_interface_index       = json_endpoint_settings.get('sub_interface_index', 0        )  # 1
+    vlan_id                   = json_endpoint_settings.get('vlan_id',             1        )  # 400
+    address_ip                = json_endpoint_settings.get('address_ip',          '0.0.0.0')  # '2.2.2.1'
+    address_prefix            = json_endpoint_settings.get('address_prefix',      24       )  # 30
+
+    policy_import             = json_device_settings.get('policy_AZ',            '2'     )  # 2
+    policy_export             = json_device_settings.get('policy_ZA',            '7'     )  # 30
+    #network_interface_desc    = '{:s}-NetIf'.format(service_uuid)
+    network_interface_desc    = json_endpoint_settings.get('ni_description','')
+    #network_subinterface_desc = '{:s}-NetSubIf'.format(service_uuid)
+    network_subinterface_desc = json_endpoint_settings.get('subif_description','')
+    #service_short_uuid       = service_uuid.split('-')[-1]
+    #network_instance_name    = '{:s}-NetInst'.format(service_short_uuid)
+    network_instance_name     = json_endpoint_settings.get('ni_name',          service_uuid.split('-')[-1])  #ELAN-AC:1
+
+    self_bgp_if_name          = json_device_settings.get('self_bgp_interface_name', '')
+    self_bgp_address_ip       = json_device_settings.get('self_bgp_interface_address_ip', '')
+    bgp_address_prefix        = json_device_settings.get('bgp_interface_address_prefix', '')
+    bgp_sub_interface_index   = json_device_settings.get('self_bgp_sub_interface_index', 0)
+    neighbor_bgp_if_address_ip= json_device_settings.get('neighbor_bgp_interface_address_ip', '0.0.0.0')  # '2.2.2.1' 
+
+    # if_subif_name       = '{:s}.{:d}'.format(endpoint_name, 0)
+    if_subif_name       = '{:s}'.format(endpoint_name[5:])
+
+    json_config_rules = [
+        # Configure Interface (not used)
+        #json_config_rule_set(
+        #    '/interface[{:s}]'.format(endpoint_name), {
+        #        'name': endpoint_name, 
+        #        'description': network_interface_desc, 
+        #        'mtu': mtu,
+        #}),
+
+        #Create network instance
+        json_config_rule_set(
+            '/network_instance[{:s}]'.format(network_instance_name), {
+                'name': network_instance_name, 
+                'description': network_interface_desc, 
+                'type': 'L3VRF',
+                'route_distinguisher': route_distinguisher,
+                'router_id': router_id,
+                #'address_families': address_families,
+        }),
+
+        #Add BGP protocol to network instance
+        json_config_rule_set(
+            '/network_instance[{:s}]/protocols[BGP]'.format(network_instance_name), {
+                'name': network_instance_name, 
+                'protocol_name': bgp_as, 
+                'identifier': 'BGP', 
+                'type': 'L3VRF',
+                'as': bgp_as,
+                'router_id': router_id, 
+                'neighbors': [{'ip_address': neighbor_bgp_if_address_ip, 'remote_as': bgp_as}]
+        }),
+
+        #Add DIRECTLY CONNECTED protocol to network instance
+        json_config_rule_set(
+            '/network_instance[{:s}]/protocols[DIRECTLY_CONNECTED]'.format(network_instance_name), {
+                'name': network_instance_name, 
+                'identifier': 'DIRECTLY_CONNECTED', 
+                'protocol_name': 'DIRECTLY_CONNECTED',
+        }),
+
+        #Add STATIC protocol to network instance
+        json_config_rule_set(
+            '/network_instance[{:s}]/protocols[STATIC]'.format(network_instance_name), {
+                'name': network_instance_name, 
+                'identifier': 'STATIC', 
+                'protocol_name': 'STATIC',
+        }),
+
+        #Create interface with subinterface (without IP address)
+        json_config_rule_set(
+            '/interface[{:s}]/subinterface[{:d}]'.format(if_subif_name, sub_interface_index), {
+                'name'       : if_subif_name,
+                'type'       :'ethernetCsmacd',
+                'mtu'        : mtu,
+                'index'      : sub_interface_index,
+                'description': network_subinterface_desc, 
+                'vlan_id'    : vlan_id,
+        }),
+
+        #Associate interface to network instance
+        json_config_rule_set(
+            '/network_instance[{:s}]/interface[{:s}]'.format(network_instance_name, if_subif_name), {
+                'name'          : network_instance_name, 
+                'type'          : 'L3VRF',
+                'id'            : if_subif_name, 
+                'interface'     : if_subif_name,
+                'subinterface'  : sub_interface_index,
+                'address_ip'    : address_ip, 
+                'address_prefix': address_prefix,
+        }), 
+
+        #Create interface with subinterface (with IP address)
+        json_config_rule_set(
+            '/interface[{:s}]/subinterface[{:d}]'.format(if_subif_name, sub_interface_index), {
+                'name'          : if_subif_name,
+                'type'          :'ethernetCsmacd',
+                'mtu'           : mtu,
+                'index'         : sub_interface_index,
+                'description'   : network_subinterface_desc, 
+                'vlan_id'       : vlan_id,
+                'address_ip'    : address_ip, 
+                'address_prefix': address_prefix,
+        }),
+
+        json_config_rule_set(
+            '/network_instance[{:s}]/interface[{:s}]'.format(network_instance_name, self_bgp_if_name), {
+                'name'        : network_instance_name, 
+                'type'        : 'L3VRF',
+                'id'          : self_bgp_if_name, 
+                'interface'   : self_bgp_if_name,
+                'subinterface': bgp_sub_interface_index,
+                'address_ip'    : self_bgp_address_ip, 
+                'address_prefix': bgp_address_prefix,
+        }), 
+
+        #Create routing policy
+        json_config_rule_set(
+            '/routing_policy/bgp_defined_set[{:s}_rt_import][{:s}]'.format(policy_import,route_distinguisher), {
+                'ext_community_set_name': 'set_{:s}'.format(policy_import),
+                'ext_community_member'  : route_distinguisher,
+        }),
+        json_config_rule_set(
+            # pylint: disable=duplicate-string-formatting-argument
+            '/routing_policy/policy_definition[{:s}_import]/statement[{:s}]'.format(policy_import, policy_import), {
+                'policy_name'           : policy_import,
+                'statement_name'        : 'stm_{:s}'.format(policy_import), # OCNOS: '10',
+                'ext_community_set_name': 'set_{:s}'.format(policy_import),
+                'policy_result'         : 'ACCEPT_ROUTE',
+        }),
+
+        #Associate routing policy to network instance
+        json_config_rule_set(
+            '/network_instance[{:s}]/inter_instance_policies[{:s}]'.format(network_instance_name, policy_import), {
+                'name'         : network_instance_name,
+                'import_policy': policy_import,
+        }),
+
+        #Create routing policy
+        json_config_rule_set(
+            '/routing_policy/bgp_defined_set[{:s}_rt_export][{:s}]'.format(policy_export, route_distinguisher), {
+                'ext_community_set_name': 'set_{:s}'.format(policy_export),
+                'ext_community_member'  : route_distinguisher,
+        }),
+        json_config_rule_set(
+            # pylint: disable=duplicate-string-formatting-argument
+            '/routing_policy/policy_definition[{:s}_export]/statement[{:s}]'.format(policy_export, policy_export), {
+                'policy_name'           : policy_export,
+                'statement_name'        : 'stm_{:s}'.format(policy_export), # OCNOS: '10',
+                'ext_community_set_name': 'set_{:s}'.format(policy_export),
+                'policy_result'         : 'ACCEPT_ROUTE',
+        }),
+
+        #Associate routing policy to network instance
+        json_config_rule_set(
+            '/network_instance[{:s}]/inter_instance_policies[{:s}]'.format(network_instance_name, policy_export),{
+                'name'         : network_instance_name,
+                'export_policy': policy_export,
+        }),
+
+        #Create table connections
+        json_config_rule_set(
+            '/network_instance[{:s}]/table_connections[DIRECTLY_CONNECTED][BGP][IPV4]'.format(network_instance_name), {
+                'name'                 : network_instance_name,
+                'src_protocol'         : 'DIRECTLY_CONNECTED',
+                'dst_protocol'         : 'BGP',
+                'address_family'       : 'IPV4',
+                'default_import_policy': 'ACCEPT_ROUTE',
+                'as'                   : bgp_as,
+        }),
+
+        json_config_rule_set(
+            '/network_instance[{:s}]/table_connections[STATIC][BGP][IPV4]'.format(network_instance_name), {
+                'name'                 : network_instance_name,
+                'src_protocol'         : 'STATIC',
+                'dst_protocol'         : 'BGP',
+                'address_family'       : 'IPV4',
+                'default_import_policy': 'ACCEPT_ROUTE',
+                'as'                   : bgp_as,
+        }),
+
+    ]
+
+    for res_key, res_value in endpoint_acls:
+        json_config_rules.append(
+               {'action': 1, 'acl': res_value}
+            )
+    return json_config_rules
+
+def teardown_config_rules(
+    service_uuid : str, connection_uuid : str, device_uuid : str, endpoint_uuid : str, endpoint_name : str,
+    service_settings : TreeNode, device_settings : TreeNode, endpoint_settings : TreeNode
+) -> List[Dict]:
+
+    if service_settings  is None: return []
+    if device_settings   is None: return []
+    if endpoint_settings is None: return []
+
+    json_settings          : Dict = service_settings.value
+    json_device_settings   : Dict = device_settings.value
+    json_endpoint_settings : Dict = endpoint_settings.value
+
+    service_short_uuid        = service_uuid.split('-')[-1]
+    # network_instance_name     = '{:s}-NetInst'.format(service_short_uuid)
+    network_instance_name     = json_endpoint_settings.get('ni_name', service_short_uuid)  #ELAN-AC:1
+    #network_interface_desc    = '{:s}-NetIf'.format(service_uuid)
+    # network_subinterface_desc = '{:s}-NetSubIf'.format(service_uuid)
+    network_subinterface_desc = ''
+
+    mtu                 = json_settings.get('mtu',                          1450     )  # 1512
+    #address_families  = json_settings.get('address_families',             []       )  # ['IPV4']
+    #bgp_as              = json_device_settings.get('bgp_as',                       65000    )  # 65000
+    route_distinguisher = json_device_settings.get('route_distinguisher',          '0:0'    )  # '60001:801'
+    sub_interface_index = json_endpoint_settings.get('sub_interface_index', 0        )  # 1
+    #router_id           = json_device_settings.get('router_id',           '0.0.0.0')  # '10.95.0.10'
+    vlan_id             = json_endpoint_settings.get('vlan_id',             1        )  # 400
+    address_ip          = json_endpoint_settings.get('address_ip',          '0.0.0.0')  # '2.2.2.1'
+    address_prefix      = json_endpoint_settings.get('address_prefix',      24       )  # 30
+    policy_import       = json_device_settings.get('policy_AZ',            '2'      )  # 2
+    policy_export       = json_device_settings.get('policy_ZA',            '7'      )  # 30
+
+    self_bgp_if_name          = json_device_settings.get('self_bgp_interface_name', '')
+    self_bgp_address_ip       = json_device_settings.get('self_bgp_interface_address_ip', '')
+    bgp_address_prefix        = json_device_settings.get('bgp_interface_address_prefix', '')
+    bgp_sub_interface_index   = json_device_settings.get('self_bgp_sub_interface_index', 0)
+
+    # if_subif_name             = '{:s}.{:d}'.format(endpoint_name, vlan_id)
+    if_subif_name             = '{:s}'.format(endpoint_name[5:])
+
+    json_config_rules = [
+        #Delete export routing policy 
+        json_config_rule_delete(
+            # pylint: disable=duplicate-string-formatting-argument
+            '/routing_policy/policy_definition[{:s}_export]/statement[{:s}]'.format(policy_export, policy_export), {
+                'policy_name'           : policy_export,
+                'statement_name'        : 'stm_{:s}'.format(policy_export), # OCNOS: '10',
+                'ext_community_set_name': 'set_{:s}'.format(policy_export),
+                'policy_result'         : 'ACCEPT_ROUTE',
+        }),
+        json_config_rule_delete(
+            '/routing_policy/bgp_defined_set[{:s}_rt_export][{:s}]'.format(policy_export, route_distinguisher), {
+                'ext_community_set_name': 'set_{:s}'.format(policy_export),
+                'ext_community_member'  : route_distinguisher,
+        }),
+
+        #Delete import routing policy 
+        json_config_rule_delete(
+            # pylint: disable=duplicate-string-formatting-argument
+            '/routing_policy/policy_definition[{:s}_import]/statement[{:s}]'.format(policy_import, policy_import), {
+                'policy_name'           : policy_import,
+                'statement_name'        : 'stm_{:s}'.format(policy_import), # OCNOS: '10',
+                'ext_community_set_name': 'set_{:s}'.format(policy_import),
+                'policy_result'         : 'ACCEPT_ROUTE',
+        }),
+        json_config_rule_delete(
+            '/routing_policy/bgp_defined_set[{:s}_rt_import][{:s}]'.format(policy_import, route_distinguisher), {
+                'ext_community_set_name': 'set_{:s}'.format(policy_import),
+                'ext_community_member'  : route_distinguisher,
+        }),
+
+        #Delete interface; automatically deletes:
+        # - /interface[]/subinterface[]
+        # json_config_rule_delete('/interface[{:s}]/subinterface[0]'.format(if_subif_name),
+        # {
+        #     'name': if_subif_name,
+        # }),
+
+        #Delete network instance; automatically deletes:
+        # - /network_instance[]/interface[]
+        # - /network_instance[]/protocols[]
+        # - /network_instance[]/inter_instance_policies[]
+
+        #Associate interface to network instance
+        json_config_rule_set(
+            '/network_instance[{:s}]/interface[{:s}]'.format('default', if_subif_name), {
+                'name'        : 'default', 
+                'id'          : if_subif_name, 
+                'interface'   : if_subif_name,
+                'subinterface': sub_interface_index,
+                'address_ip'    : address_ip, 
+                'address_prefix': address_prefix,
+        }), 
+        json_config_rule_set(
+            '/network_instance[{:s}]/interface[{:s}]'.format('default', self_bgp_if_name), {
+                'name'        : 'default', 
+                'id'          : self_bgp_if_name, 
+                'interface'   : self_bgp_if_name,
+                'subinterface': bgp_sub_interface_index,
+                'address_ip'    : self_bgp_address_ip, 
+                'address_prefix': bgp_address_prefix,
+        }), 
+        json_config_rule_delete('/network_instance[{:s}]'.format(network_instance_name),
+        {
+            'name': network_instance_name
+        }),
+    ]
+    return json_config_rules
diff --git a/src/service/service/service_handlers/l3nm_openconfig/L3NMOpenConfigServiceHandler.py b/src/service/service/service_handlers/l3nm_openconfig/L3NMOpenConfigServiceHandler.py
index d714946d128284d60422779bc6286b64ee0244a7..2c944bfe4772b2f55ff16d1a3c726af3ee4c6e8f 100644
--- a/src/service/service/service_handlers/l3nm_openconfig/L3NMOpenConfigServiceHandler.py
+++ b/src/service/service/service_handlers/l3nm_openconfig/L3NMOpenConfigServiceHandler.py
@@ -52,6 +52,7 @@ class L3NMOpenConfigServiceHandler(_ServiceHandler):
                 device_uuid, endpoint_uuid = get_device_endpoint_uuids(endpoint)
 
                 device_obj = self.__task_executor.get_device(DeviceId(**json_device_id(device_uuid)))
+                device_settings = self.__settings_handler.get_device_settings(device_obj)
                 endpoint_obj = get_endpoint_matching(device_obj, endpoint_uuid)
                 endpoint_settings = self.__settings_handler.get_endpoint_settings(device_obj, endpoint_obj)
                 endpoint_acls = self.__settings_handler.get_endpoint_acls(device_obj, endpoint_obj)
@@ -59,7 +60,7 @@ class L3NMOpenConfigServiceHandler(_ServiceHandler):
 
                 json_config_rules = setup_config_rules(
                     service_uuid, connection_uuid, device_uuid, endpoint_uuid, endpoint_name,
-                    settings, endpoint_settings, endpoint_acls)
+                    settings, device_settings, endpoint_settings, endpoint_acls)
 
                 if len(json_config_rules) > 0:
                     del device_obj.device_config.config_rules[:]
@@ -90,13 +91,14 @@ class L3NMOpenConfigServiceHandler(_ServiceHandler):
                 device_uuid, endpoint_uuid = get_device_endpoint_uuids(endpoint)
 
                 device_obj = self.__task_executor.get_device(DeviceId(**json_device_id(device_uuid)))
+                device_settings = self.__settings_handler.get_device_settings(device_obj)
                 endpoint_obj = get_endpoint_matching(device_obj, endpoint_uuid)
                 endpoint_settings = self.__settings_handler.get_endpoint_settings(device_obj, endpoint_obj)
                 endpoint_name = endpoint_obj.name
 
                 json_config_rules = teardown_config_rules(
                     service_uuid, connection_uuid, device_uuid, endpoint_uuid, endpoint_name,
-                    settings, endpoint_settings)
+                    settings, device_settings, endpoint_settings)
 
                 if len(json_config_rules) > 0:
                     del device_obj.device_config.config_rules[:]
diff --git a/src/webui/service/__init__.py b/src/webui/service/__init__.py
index 9b6950aeb0f3fda630db87d5d80ad2bf730fac3d..b864d3549e051b54e888c80547724da14fec5f67 100644
--- a/src/webui/service/__init__.py
+++ b/src/webui/service/__init__.py
@@ -49,7 +49,10 @@ def json_to_list(json_str : str) -> List[Union[str, Tuple[str, str]]]:
     if isinstance(data, dict):
         return [('kv', (key, value)) for key, value in data.items()]
     elif isinstance(data, list):
-        return [('item', ', '.join(data))]
+        if len(data) == 1 and isinstance(data[0], dict):
+            return [('kv', (key, value)) for key, value in data[0].items()]
+        else:
+            return [('item', ', '.join([str(d) for d in data]))]
     else:
         return [('item', str(data))]