diff --git a/src/device/Dockerfile b/src/device/Dockerfile
index 6566625527f8ceaa8de4639d558c92572c4835cb..2bcb5322af358a4892683a1c0d547392dd327c1b 100644
--- a/src/device/Dockerfile
+++ b/src/device/Dockerfile
@@ -53,6 +53,21 @@ RUN python3 -m grpc_tools.protoc -I=. --python_out=. --grpc_python_out=. *.proto
 RUN rm *.proto
 RUN find . -type f -exec sed -i -E 's/(import\ .*)_pb2/from . \1_pb2/g' {} \;
 
+# Download, build and install libyang. Note that APT package is outdated
+# - Ref: https://github.com/CESNET/libyang
+# - Ref: https://github.com/CESNET/libyang-python/
+RUN apt-get --yes --quiet --quiet update && \
+    apt-get --yes --quiet --quiet install build-essential cmake libpcre2-dev python3-dev python3-cffi && \
+    rm -rf /var/lib/apt/lists/*
+RUN mkdir -p /var/libyang
+RUN git clone https://github.com/CESNET/libyang.git /var/libyang
+RUN mkdir -p /var/libyang/build
+WORKDIR /var/libyang/build
+RUN cmake -D CMAKE_BUILD_TYPE:String="Release" ..
+RUN make
+RUN make install
+RUN ldconfig
+
 # Create component sub-folders, get specific Python packages
 RUN mkdir -p /var/teraflow/device
 WORKDIR /var/teraflow/device
@@ -62,9 +77,11 @@ RUN python3 -m pip install -r requirements.txt
 
 # Add component files into working directory
 WORKDIR /var/teraflow
-COPY src/context/. context/
 COPY src/device/. device/
-COPY src/monitoring/. monitoring/
+COPY src/context/__init__.py context/__init__.py
+COPY src/context/client/. context/client/
+COPY src/monitoring/__init__.py monitoring/__init__.py
+COPY src/monitoring/client/. monitoring/client/
 
 # Start the service
 ENTRYPOINT ["python", "-m", "device.service"]
diff --git a/src/device/requirements.in b/src/device/requirements.in
index d8a33455e446b270ae5f1407c0d039fea889574f..20ed1e2dc611b312299ccd33ecf5b5b71a9400b2 100644
--- a/src/device/requirements.in
+++ b/src/device/requirements.in
@@ -12,30 +12,30 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-
 anytree==2.8.0
 APScheduler==3.10.1
 bitarray==2.8.*
 cryptography==36.0.2
 #fastcache==1.1.0
+ipaddress
 Jinja2==3.0.3
+libyang==2.8.0
+macaddress
 ncclient==0.6.13
 p4runtime==1.3.0
 pandas==1.5.*
 paramiko==2.9.2
+pyang==2.6.*
+git+https://github.com/robshakir/pyangbind.git
 python-json-logger==2.0.2
 #pytz==2021.3
 #redis==4.1.2
 requests==2.27.1
 requests-mock==1.9.3
-xmltodict==0.12.0
 tabulate
-ipaddress
-macaddress
-yattag
-pyang==2.6.*
-git+https://github.com/robshakir/pyangbind.git
 websockets==10.4
+xmltodict==0.12.0
+yattag
 
 # pip's dependency resolver does not take into account installed packages.
 # p4runtime does not specify the version of grpcio/protobuf it needs, so it tries to install latest one
diff --git a/src/device/service/drivers/gnmi_openconfig/handlers/Component.py b/src/device/service/drivers/gnmi_openconfig/handlers/Component.py
index 73728192f3089bedffb092d0bea35f9ed6713cf7..9b92c6b83bb313f0042c74c0b2f5d6d3ace4c826 100644
--- a/src/device/service/drivers/gnmi_openconfig/handlers/Component.py
+++ b/src/device/service/drivers/gnmi_openconfig/handlers/Component.py
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import json, logging # libyang
+import json, logging, re # libyang
 from typing import Any, Dict, List, Tuple
 from common.proto.kpi_sample_types_pb2 import KpiSampleType
 from ._Handler import _Handler
@@ -55,7 +55,7 @@ class ComponentHandler(_Handler):
 
             # TODO: improve mapping between interface name and component name
             # By now, computed by time for the sake of saving time for the Hackfest.
-            interface_name = component_name.lower().replace('-port', '')
+            interface_name = re.sub(r'\-[pP][oO][rR][tT]', '', component_name)
 
             endpoint = {'uuid': interface_name, 'type': '-'}
             endpoint['sample_types'] = {
diff --git a/src/device/service/drivers/gnmi_openconfig/handlers/NetworkInstance.py b/src/device/service/drivers/gnmi_openconfig/handlers/NetworkInstance.py
index b9761298704f9e13e75ad7421370a7ce00349e82..d8231b2a6660fdf54b7beb42a269645759bf22a1 100644
--- a/src/device/service/drivers/gnmi_openconfig/handlers/NetworkInstance.py
+++ b/src/device/service/drivers/gnmi_openconfig/handlers/NetworkInstance.py
@@ -134,18 +134,15 @@ class NetworkInstanceHandler(_Handler):
                     for static_route in static_routes:
                         static_route_prefix = static_route['prefix']
 
-                        next_hops = static_route.get('next-hops', {}).get('next-hop', [])
-                        _next_hops = [
-                            {
-                                'index'  : next_hop['index'],
-                                'gateway': next_hop['config']['next-hop'],
-                                'metric' : next_hop['config']['metric'],
+                        next_hops = {
+                            next_hop['index'] : {
+                                'next_hop': next_hop['config']['next-hop'],
+                                'metric'  : next_hop['config']['metric'],
                             }
-                            for next_hop in next_hops
-                        ]
-                        _next_hops = sorted(_next_hops, key=operator.itemgetter('index'))
+                            for next_hop in static_route.get('next-hops', {}).get('next-hop', [])
+                        }
 
-                        _static_route = {'prefix': static_route_prefix, 'next_hops': _next_hops}
+                        _static_route = {'prefix': static_route_prefix, 'next_hops': next_hops}
                         entry_static_route_key = '{:s}/static_routes[{:s}]'.format(
                             entry_protocol_key, static_route_prefix
                         )
diff --git a/src/device/service/drivers/gnmi_openconfig/handlers/NetworkInstanceStaticRoute.py b/src/device/service/drivers/gnmi_openconfig/handlers/NetworkInstanceStaticRoute.py
index 0343e3cbaab3f554f45590c3832bd89b6b552aa8..03c04e316845d6ba7f884755a9449ff7dba42411 100644
--- a/src/device/service/drivers/gnmi_openconfig/handlers/NetworkInstanceStaticRoute.py
+++ b/src/device/service/drivers/gnmi_openconfig/handlers/NetworkInstanceStaticRoute.py
@@ -39,8 +39,8 @@ class NetworkInstanceStaticRouteHandler(_Handler):
             str_data = json.dumps({})
             return str_path, str_data
 
-        next_hop       = get_str(resource_value, 'next_hop'         )   # '172.0.0.1'
-        next_hop_index = get_int(resource_value, 'next_hop_index', 0)   # 0
+        next_hop       = get_str(resource_value, 'next_hop'      )   # '172.0.0.1'
+        next_hop_index = get_str(resource_value, 'next_hop_index')   # AUTO_1_172-0-0-1
 
         PATH_TMPL = '/network-instances/network-instance[name={:s}]/protocols/protocol[identifier={:s}][name={:s}]'
         str_path = PATH_TMPL.format(ni_name, identifier, name)
@@ -74,7 +74,7 @@ class NetworkInstanceStaticRouteHandler(_Handler):
         yang_ni_pr_sr.create_path('config/prefix', prefix)
 
         yang_ni_pr_sr_nhs : libyang.DContainer = yang_ni_pr_sr.create_path('next-hops')
-        yang_ni_pr_sr_nh_path = 'next-hop[index="{:d}"]'.format(next_hop_index)
+        yang_ni_pr_sr_nh_path = 'next-hop[index="{:s}"]'.format(next_hop_index)
         yang_ni_pr_sr_nh : libyang.DContainer = yang_ni_pr_sr_nhs.create_path(yang_ni_pr_sr_nh_path)
         yang_ni_pr_sr_nh.create_path('config/index', next_hop_index)
         yang_ni_pr_sr_nh.create_path('config/next-hop', next_hop)
diff --git a/src/device/tests/gnmi_openconfig/storage/StorageEndpoints.py b/src/device/tests/gnmi_openconfig/storage/StorageEndpoints.py
index 815a1b0adda1a2e7bfae18ad297595403a725f24..d2596b73265c0dfc913de6f5bbc55189bf451333 100644
--- a/src/device/tests/gnmi_openconfig/storage/StorageEndpoints.py
+++ b/src/device/tests/gnmi_openconfig/storage/StorageEndpoints.py
@@ -39,13 +39,16 @@ class Endpoints:
 
         for _, field_names in Endpoints.STRUCT:
             field_names = set(field_names)
-            item.update({k:v for k,v in resource_value if k in field_names})
+            item.update({k:v for k,v in resource_value.items() if k in field_names})
 
         item['sample_types'] = {
             sample_type_id : sample_type_path.format(ep_uuid)
             for sample_type_id, sample_type_path in ENDPOINT_PACKET_SAMPLE_TYPES.items()
         }
 
+    def get(self, ep_uuid : str) -> Dict:
+        return self._items.get(ep_uuid)
+
     def remove(self, ep_uuid : str) -> None:
         self._items.pop(ep_uuid, None)
     
diff --git a/src/device/tests/gnmi_openconfig/storage/StorageInterface.py b/src/device/tests/gnmi_openconfig/storage/StorageInterface.py
index a0391e92f1d0250638e5b14ead1357cc626ebb23..0933433cb406614ad00ab40030d424986ac2cf25 100644
--- a/src/device/tests/gnmi_openconfig/storage/StorageInterface.py
+++ b/src/device/tests/gnmi_openconfig/storage/StorageInterface.py
@@ -37,7 +37,10 @@ class Interfaces:
         item['name'] = if_name
         for _, field_names in Interfaces.STRUCT:
             field_names = set(field_names)
-            item.update({k:v for k,v in resource_value if k in field_names})
+            item.update({k:v for k,v in resource_value.items() if k in field_names})
+
+    def get(self, if_name : str) -> Dict:
+        return self._items.get(if_name)
 
     def remove(self, if_name : str) -> None:
         self._items.pop(if_name, None)
@@ -57,6 +60,9 @@ class SubInterfaces:
         item = self._items.setdefault((if_name, subif_index), dict())
         item['index'] = subif_index
 
+    def get(self, if_name : str, subif_index : int) -> Dict:
+        return self._items.get((if_name, subif_index))
+
     def remove(self, if_name : str, subif_index : int) -> None:
         self._items.pop((if_name, subif_index), None)
     
@@ -77,6 +83,9 @@ class IPv4Addresses:
         item['origin'] = resource_value.get('origin')
         item['prefix'] = resource_value.get('prefix')
 
+    def get(self, if_name : str, subif_index : int, ipv4_address : str) -> Dict:
+        return self._items.get((if_name, subif_index, ipv4_address))
+
     def remove(self, if_name : str, subif_index : int, ipv4_address : str) -> None:
         self._items.pop((if_name, subif_index, ipv4_address), None)
 
diff --git a/src/device/tests/gnmi_openconfig/storage/StorageNetworkInstance.py b/src/device/tests/gnmi_openconfig/storage/StorageNetworkInstance.py
index fa336488317776a10e20b283acfc1dcfbc3d7b8a..ba437ef9d59bbc273a57a0da7bdd8854bfdec58a 100644
--- a/src/device/tests/gnmi_openconfig/storage/StorageNetworkInstance.py
+++ b/src/device/tests/gnmi_openconfig/storage/StorageNetworkInstance.py
@@ -37,6 +37,9 @@ class NetworkInstances:
         item['name'] = ni_name
         item['type'] = resource_value.get('type')
 
+    def get(self, ni_name : str) -> Dict:
+        return self._items.get(ni_name)
+
     def remove(self, ni_name : str) -> None:
         self._items.pop(ni_name, None)
     
@@ -45,17 +48,24 @@ class NetworkInstances:
 
 class Interfaces:
     STRUCT : List[Tuple[str, List[str]]] = [
-        ('/network_instance[{:s}]/interface[{:s}]', []),
+        ('/network_instance[{:s}]/interface[{:s}.{:d}]', ['name', 'id', 'if_name', 'sif_index']),
     ]
 
     def __init__(self) -> None:
         self._items : Dict[Tuple[str, str], Dict] = dict()
 
-    def add(self, ni_name : str, if_name : str) -> None:
-        self._items.setdefault((ni_name, if_name), dict())
+    def add(self, ni_name : str, if_name : str, sif_index : int) -> None:
+        item = self._items.setdefault((ni_name, if_name, sif_index), dict())
+        item['name'     ] = ni_name
+        item['id'       ] = '{:s}.{:d}'.format(if_name, sif_index)
+        item['if_name'  ] = if_name
+        item['sif_index'] = sif_index
+
+    def get(self, ni_name : str, if_name : str, sif_index : int) -> Dict:
+        return self._items.get((ni_name, if_name, sif_index))
 
-    def remove(self, ni_name : str, if_name : str) -> None:
-        self._items.pop((ni_name, if_name), None)
+    def remove(self, ni_name : str, if_name : str, sif_index : int) -> None:
+        self._items.pop((ni_name, if_name, sif_index), None)
 
     def compose_resources(self) -> List[Dict]:
         return compose_resources(self._items, Interfaces.STRUCT)
@@ -73,6 +83,9 @@ class Protocols:
         item['id'  ] = protocol
         item['name'] = protocol
 
+    def get(self, ni_name : str, protocol : str) -> Dict:
+        return self._items.get((ni_name, protocol))
+
     def remove(self, ni_name : str, protocol : str) -> None:
         self._items.pop((ni_name, protocol), None)
 
@@ -84,18 +97,16 @@ class StaticRoutes:
         ('/network_instance[{:s}]/protocol[{:s}]/static_routes[{:s}]', ['prefix', 'next_hops']),
     ]
 
-    #('/network_instance[{:s}]/static_route[{:s}]'.format(ni_name, static_route['prefix']), {
-    #    'name': ni_name, 'prefix': static_route['prefix'], 'next_hop': static_route['gateway'],
-    #    'next_hop_index': 0, 'metric': static_route['metric']
-    #})
-
     def __init__(self) -> None:
         self._items : Dict[Tuple[str, str, str], Dict] = dict()
 
     def add(self, ni_name : str, protocol : str, prefix : str, resource_value : Dict) -> None:
         item = self._items.setdefault((ni_name, protocol, prefix), dict())
         item['prefix'   ] = prefix
-        item['next_hops'] = sorted(resource_value.get('next_hops'))
+        item['next_hops'] = resource_value.get('next_hops')
+
+    def get(self, ni_name : str, protocol : str, prefix : str) -> Dict:
+        return self._items.get((ni_name, protocol, prefix))
 
     def remove(self, ni_name : str, protocol : str, prefix : str) -> None:
         self._items.pop((ni_name, protocol, prefix), None)
@@ -116,6 +127,9 @@ class Tables:
         item['protocol'      ] = protocol
         item['address_family'] = address_family
 
+    def get(self, ni_name : str, protocol : str, address_family : str) -> Dict:
+        return self._items.get((ni_name, protocol, address_family))
+
     def remove(self, ni_name : str, protocol : str, address_family : str) -> None:
         self._items.pop((ni_name, protocol, address_family), None)
 
@@ -136,6 +150,9 @@ class Vlans:
         item['name'   ] = resource_value.get('name')
         item['members'] = sorted(resource_value.get('members'))
 
+    def get(self, ni_name : str, vlan_id : int) -> Dict:
+        return self._items.get((ni_name, vlan_id))
+
     def remove(self, ni_name : str, vlan_id : int) -> None:
         self._items.pop((ni_name, vlan_id), None)
 
@@ -160,7 +177,11 @@ class StorageNetworkInstance:
 
             match = RE_RESKEY_INTERFACE.match(resource_key)
             if match is not None:
-                self.interfaces.add(match.group(1), match.group(2))
+                if_id = match.group(2)
+                if_id_parts = if_id.split('.')
+                if_name = if_id_parts[0]
+                sif_index = 0 if len(if_id_parts) == 1 else int(if_id_parts[1])
+                self.interfaces.add(match.group(1), if_name, sif_index)
                 continue
 
             match = RE_RESKEY_PROTOCOL.match(resource_key)
diff --git a/src/device/tests/gnmi_openconfig/storage/Tools.py b/src/device/tests/gnmi_openconfig/storage/Tools.py
index 4da48af4680a6b608e29d61ae83f027261b16424..c9dab12e6366632154c59962163eb1fe8c3f2c91 100644
--- a/src/device/tests/gnmi_openconfig/storage/Tools.py
+++ b/src/device/tests/gnmi_openconfig/storage/Tools.py
@@ -21,6 +21,7 @@ def compose_resources(
 
     for resource_key_fields, resource_value_data in storage.items():
         for resource_key_template, resource_key_field_names in config_struct:
+            if isinstance(resource_key_fields, (str, int, float, bool)): resource_key_fields = (resource_key_fields,)
             resource_key = resource_key_template.format(*resource_key_fields)
             resource_value = {
                 field_name : resource_value_data[field_name]
diff --git a/src/device/tests/gnmi_openconfig/test_unitary_gnmi_openconfig.py b/src/device/tests/gnmi_openconfig/test_unitary_gnmi_openconfig.py
index 3970e65a63ba5325da37cc3ea20baf42936ad947..a601e1f234b984d5be7fd335ce2718a68276eb7d 100644
--- a/src/device/tests/gnmi_openconfig/test_unitary_gnmi_openconfig.py
+++ b/src/device/tests/gnmi_openconfig/test_unitary_gnmi_openconfig.py
@@ -17,11 +17,15 @@ os.environ['DEVICE_EMULATED_ONLY'] = 'YES'
 
 # pylint: disable=wrong-import-position
 import logging, pytest, time
-from typing import Dict
+from typing import Dict, List
+from device.service.driver_api._Driver import (
+    RESOURCE_ENDPOINTS, RESOURCE_INTERFACES, RESOURCE_NETWORK_INSTANCES,
+    RESOURCE_ROUTING_POLICIES, RESOURCE_SERVICES
+)
 from device.service.drivers.gnmi_openconfig.GnmiOpenConfigDriver import GnmiOpenConfigDriver
 from .storage.Storage import Storage
-from .tools.check_config import (
-    check_config_endpoints, check_config_interfaces, check_config_network_instances
+from .tools.manage_config import (
+    check_config_endpoints, check_config_interfaces, check_config_network_instances, del_config, get_config, set_config
 )
 from .tools.check_updates import check_updates
 from .tools.request_composers import (
@@ -69,26 +73,26 @@ NETWORK_INSTANCES = [
         'name': 'test-l3-svc',
         'type': 'L3VRF',
         'interfaces': [
-            {'name': 'Ethernet1',  'subif_index': 0, 'ipv4_addr': '192.168.1.1',  'ipv4_prefix': 24, 'enabled': True},
-            {'name': 'Ethernet10', 'subif_index': 0, 'ipv4_addr': '192.168.10.1', 'ipv4_prefix': 24, 'enabled': True},
+            {'name': 'Ethernet1',  'index': 0, 'ipv4_addr': '192.168.1.1',  'ipv4_prefix': 24, 'enabled': True},
+            {'name': 'Ethernet10', 'index': 0, 'ipv4_addr': '192.168.10.1', 'ipv4_prefix': 24, 'enabled': True},
         ],
         'static_routes': [
-            {'prefix': '172.0.0.0/24', 'gateway': '172.16.0.2', 'metric': 1},
-            {'prefix': '172.2.0.0/24', 'gateway': '172.16.0.3', 'metric': 1},
+            {'prefix': '172.0.0.0/24', 'next_hop': '172.16.0.2', 'metric': 1},
+            {'prefix': '172.2.0.0/24', 'next_hop': '172.16.0.3', 'metric': 1},
         ]
     },
-    {
-        'name': 'test-l2-svc',
-        'type': 'L2VSI',
-        'interfaces': [
-            {'name': 'Ethernet2',  'subif_index': 0, 'ipv4_addr': '192.168.1.1',  'ipv4_prefix': 24, 'enabled': True},
-            {'name': 'Ethernet4', 'subif_index': 0, 'ipv4_addr': '192.168.10.1', 'ipv4_prefix': 24, 'enabled': True},
-        ],
-        'static_routes': [
-            {'prefix': '172.0.0.0/24', 'gateway': '172.16.0.2', 'metric': 1},
-            {'prefix': '172.2.0.0/24', 'gateway': '172.16.0.3', 'metric': 1},
-        ]
-    }
+    #{
+    #    'name': 'test-l2-svc',
+    #    'type': 'L2VSI',
+    #    'interfaces': [
+    #        {'name': 'Ethernet2', 'index': 0, 'ipv4_addr': '192.168.1.1',  'ipv4_prefix': 24, 'enabled': True},
+    #        {'name': 'Ethernet4', 'index': 0, 'ipv4_addr': '192.168.10.1', 'ipv4_prefix': 24, 'enabled': True},
+    #    ],
+    #    'static_routes': [
+    #        {'prefix': '172.0.0.0/24', 'next_hop': '172.16.0.2', 'metric': 1},
+    #        {'prefix': '172.2.0.0/24', 'next_hop': '172.16.0.3', 'metric': 1},
+    #    ]
+    #}
 ]
 
 
@@ -98,7 +102,7 @@ def test_get_endpoints(
     driver : GnmiOpenConfigDriver,  # pylint: disable=redefined-outer-name
     storage : Storage,              # pylint: disable=redefined-outer-name
 ) -> None:
-    results_getconfig = check_config_endpoints(driver, storage)
+    results_getconfig = get_config(driver, [RESOURCE_ENDPOINTS])
     storage.endpoints.populate(results_getconfig)
     check_config_endpoints(driver, storage)
 
@@ -107,7 +111,7 @@ def test_get_interfaces(
     driver : GnmiOpenConfigDriver,  # pylint: disable=redefined-outer-name
     storage : Storage,              # pylint: disable=redefined-outer-name
 ) -> None:
-    results_getconfig = check_config_interfaces(driver, storage)
+    results_getconfig = get_config(driver, [RESOURCE_INTERFACES])
     storage.interfaces.populate(results_getconfig)
     check_config_interfaces(driver, storage)
 
@@ -116,7 +120,7 @@ def test_get_network_instances(
     driver : GnmiOpenConfigDriver,  # pylint: disable=redefined-outer-name
     storage : Storage,              # pylint: disable=redefined-outer-name
 ) -> None:
-    results_getconfig = check_config_network_instances(driver, storage)
+    results_getconfig = get_config(driver, [RESOURCE_NETWORK_INSTANCES])
     storage.network_instances.populate(results_getconfig)
     check_config_network_instances(driver, storage)
 
@@ -136,17 +140,18 @@ def test_set_network_instances(
         resources_to_set.append(network_instance(ni_name, ni_type))
         ni_names.append(ni_name)
         storage.network_instances.network_instances.add(ni_name, {'type': ni_type})
-    
-    LOGGER.info('resources_to_set = {:s}'.format(str(resources_to_set)))
-    results_setconfig = driver.SetConfig(resources_to_set)
-    LOGGER.info('results_setconfig = {:s}'.format(str(results_setconfig)))
+        storage.network_instances.protocols.add(ni_name, 'DIRECTLY_CONNECTED')
+        storage.network_instances.tables.add(ni_name, 'DIRECTLY_CONNECTED', 'IPV4')
+        storage.network_instances.tables.add(ni_name, 'DIRECTLY_CONNECTED', 'IPV6')
+
+    results_setconfig = set_config(driver, resources_to_set)
     check_updates(results_setconfig, '/network_instance[{:s}]', ni_names)
 
-    check_config_interfaces(driver, storage, max_retries=5)
-    check_config_network_instances(driver, storage, max_retries=5)
+    check_config_interfaces(driver, storage, max_retries=10, retry_delay=2.0)
+    check_config_network_instances(driver, storage, max_retries=10, retry_delay=2.0)
 
 
-def test_set_interfaces(
+def test_add_interfaces_to_network_instance(
     driver : GnmiOpenConfigDriver,  # pylint: disable=redefined-outer-name
     storage : Storage,              # pylint: disable=redefined-outer-name
 ) -> None:
@@ -154,33 +159,24 @@ def test_set_interfaces(
     check_config_network_instances(driver, storage)
 
     resources_to_set = list()
-    if_names = list()
+    ni_if_names = list()
     for ni in NETWORK_INSTANCES:
         ni_name = ni['name']
         for ni_if in ni.get('interfaces', list()):
-            if_name      = ni_if['if_name']
-            subif_index  = ni_if['sif_index']
-            ipv4_address = ni_if['ipv4_addr']
-            ipv4_prefix  = ni_if['ipv4_prefix']
-            enabled      = ni_if['enabled']
-            resources_to_set.append(interface(
-                if_name, subif_index, ipv4_address, ipv4_prefix, enabled
-            ))
-            if_names.append(ni_name)
-            storage.interfaces.ipv4_addresses.add(if_name, subif_index, ipv4_address, {
-                'origin' : 'STATIC', 'prefix': ipv4_prefix
-            })
+            if_name     = ni_if['name' ]
+            subif_index = ni_if['index']
+            resources_to_set.append(network_instance_interface(ni_name, if_name, subif_index))
+            ni_if_names.append((ni_name, '{:s}.{:d}'.format(if_name, subif_index)))
+            storage.network_instances.interfaces.add(ni_name, if_name, subif_index)
 
-    LOGGER.info('resources_to_set = {:s}'.format(str(resources_to_set)))
-    results_setconfig = driver.SetConfig(resources_to_set)
-    LOGGER.info('results_setconfig = {:s}'.format(str(results_setconfig)))
-    check_updates(results_setconfig, '/interface[{:s}]', if_names)
+    results_setconfig = set_config(driver, resources_to_set)
+    check_updates(results_setconfig, '/network_instance[{:s}]/interface[{:s}]', ni_if_names)
 
-    check_config_interfaces(driver, storage, max_retries=5)
-    check_config_network_instances(driver, storage, max_retries=5)
+    check_config_interfaces(driver, storage, max_retries=10, retry_delay=2.0)
+    check_config_network_instances(driver, storage, max_retries=10, retry_delay=2.0)
 
 
-def test_add_interfaces_to_network_instance(
+def test_set_interfaces(
     driver : GnmiOpenConfigDriver,  # pylint: disable=redefined-outer-name
     storage : Storage,              # pylint: disable=redefined-outer-name
 ) -> None:
@@ -188,23 +184,30 @@ def test_add_interfaces_to_network_instance(
     check_config_network_instances(driver, storage)
 
     resources_to_set = list()
-    ni_if_names = list()
+    if_names = list()
     for ni in NETWORK_INSTANCES:
-        ni_name = ni['name']
         for ni_if in ni.get('interfaces', list()):
-            if_name     = ni_if['if_name']
-            subif_index = ni_if['sif_index']
-            resources_to_set.append(network_instance_interface(ni_name, if_name, subif_index))
-            ni_if_names.append((ni_name, '{:s}.{:d}'.format(if_name, subif_index)))
-            storage.network_instances.interfaces.add(ni_name, if_name) # TODO: add subif_index
+            if_name      = ni_if['name'       ]
+            subif_index  = ni_if['index'      ]
+            ipv4_address = ni_if['ipv4_addr'  ]
+            ipv4_prefix  = ni_if['ipv4_prefix']
+            enabled      = ni_if['enabled'    ]
+            resources_to_set.append(interface(
+                if_name, subif_index, ipv4_address, ipv4_prefix, enabled
+            ))
+            if_names.append(if_name)
+            storage.interfaces.ipv4_addresses.add(if_name, subif_index, ipv4_address, {
+                'origin' : 'STATIC', 'prefix': ipv4_prefix
+            })
+            default_vlan = storage.network_instances.vlans.get('default', 1)
+            default_vlan_members : List[str] = default_vlan.setdefault('members', list())
+            if if_name in default_vlan_members: default_vlan_members.remove(if_name)
 
-    LOGGER.info('resources_to_set = {:s}'.format(str(resources_to_set)))
-    results_setconfig = driver.SetConfig(resources_to_set)
-    LOGGER.info('results_setconfig = {:s}'.format(str(results_setconfig)))
-    check_updates(results_setconfig, '/network_instance[{:s}]/interface[{:s}]', ni_if_names)
+    results_setconfig = set_config(driver, resources_to_set)
+    check_updates(results_setconfig, '/interface[{:s}]', if_names)
 
-    check_config_interfaces(driver, storage, max_retries=5)
-    check_config_network_instances(driver, storage, max_retries=5)
+    check_config_interfaces(driver, storage, max_retries=10, retry_delay=2.0)
+    check_config_network_instances(driver, storage, max_retries=10, retry_delay=2.0)
 
 
 def test_set_network_instance_static_routes(
@@ -219,24 +222,28 @@ def test_set_network_instance_static_routes(
     for ni in NETWORK_INSTANCES:
         ni_name = ni['name']
         for ni_sr in ni.get('static_routes', list()):
-            ni_sr_prefix  = ni_sr['prefix' ]
-            ni_sr_gateway = ni_sr['gateway']
-            ni_sr_metric  = ni_sr['metric' ]
-            resources_to_set.append(
-                network_instance_static_route(ni_name, ni_sr_prefix, ni_sr_gateway, metric=ni_sr_metric)
-            )
+            ni_sr_prefix   = ni_sr['prefix'  ]
+            ni_sr_next_hop = ni_sr['next_hop']
+            ni_sr_metric   = ni_sr['metric'  ]
+            ni_sr_next_hop_index = 'AUTO_{:d}_{:s}'.format(ni_sr_metric, '-'.join(ni_sr_next_hop.split('.')))
+            resources_to_set.append(network_instance_static_route(
+                ni_name, ni_sr_prefix, ni_sr_next_hop_index, ni_sr_next_hop, metric=ni_sr_metric
+            ))
             ni_sr_prefixes.append((ni_name, ni_sr_prefix))
+            storage.network_instances.protocols.add(ni_name, 'STATIC')
             storage.network_instances.protocol_static.add(ni_name, 'STATIC', ni_sr_prefix, {
-                'prefix': ni_sr_prefix, 
+                'prefix': ni_sr_prefix, 'next_hops': {
+                    ni_sr_next_hop_index: {'next_hop': ni_sr_next_hop, 'metric': ni_sr_metric}
+                }
             })
+            storage.network_instances.tables.add(ni_name, 'STATIC', 'IPV4')
+            storage.network_instances.tables.add(ni_name, 'STATIC', 'IPV6')
 
-    LOGGER.info('resources_to_set = {:s}'.format(str(resources_to_set)))
-    results_setconfig = driver.SetConfig(resources_to_set)
-    LOGGER.info('results_setconfig = {:s}'.format(str(results_setconfig)))
+    results_setconfig = set_config(driver, resources_to_set)
     check_updates(results_setconfig, '/network_instance[{:s}]/static_route[{:s}]', ni_sr_prefixes)
 
-    check_config_interfaces(driver, storage, max_retries=5)
-    check_config_network_instances(driver, storage, max_retries=5)
+    check_config_interfaces(driver, storage, max_retries=10, retry_delay=2.0)
+    check_config_network_instances(driver, storage, max_retries=10, retry_delay=2.0)
 
 
 def test_del_network_instance_static_routes(
@@ -251,79 +258,80 @@ def test_del_network_instance_static_routes(
     for ni in NETWORK_INSTANCES:
         ni_name = ni['name']
         for ni_sr in ni.get('static_routes', list()):
-            ni_sr_prefix  = ni_sr['prefix' ]
-            ni_sr_gateway = ni_sr['gateway']
-            ni_sr_metric  = ni_sr['metric' ]
-            resources_to_delete.append(
-                network_instance_static_route(ni_name, ni_sr_prefix, ni_sr_gateway, metric=ni_sr_metric)
-            )
+            ni_sr_prefix   = ni_sr['prefix'  ]
+            ni_sr_next_hop = ni_sr['next_hop']
+            ni_sr_metric   = ni_sr['metric'  ]
+            ni_sr_next_hop_index = 'AUTO_{:d}_{:s}'.format(ni_sr_metric, '-'.join(ni_sr_next_hop.split('.')))
+            resources_to_delete.append(network_instance_static_route(
+                ni_name, ni_sr_prefix, ni_sr_next_hop_index, ni_sr_next_hop, metric=ni_sr_metric
+            ))
             ni_sr_prefixes.append((ni_name, ni_sr_prefix))
+
+            storage.network_instances.protocols.remove(ni_name, 'STATIC')
             storage.network_instances.protocol_static.remove(ni_name, 'STATIC', ni_sr_prefix)
+            storage.network_instances.tables.remove(ni_name, 'STATIC', 'IPV4')
+            storage.network_instances.tables.remove(ni_name, 'STATIC', 'IPV6')
 
-    LOGGER.info('resources_to_delete = {:s}'.format(str(resources_to_delete)))
-    results_deleteconfig = driver.DeleteConfig(resources_to_delete)
-    LOGGER.info('results_deleteconfig = {:s}'.format(str(results_deleteconfig)))
+    results_deleteconfig = del_config(driver, resources_to_delete)
     check_updates(results_deleteconfig, '/network_instance[{:s}]/static_route[{:s}]', ni_sr_prefixes)
 
-    check_config_interfaces(driver, storage, max_retries=5)
-    check_config_network_instances(driver, storage, max_retries=5)
+    check_config_interfaces(driver, storage, max_retries=10, retry_delay=2.0)
+    #check_config_network_instances(driver, storage, max_retries=10, retry_delay=2.0)
 
 
-def test_del_interfaces_from_network_instance(
+def test_del_interfaces(
     driver : GnmiOpenConfigDriver,  # pylint: disable=redefined-outer-name
     storage : Storage,              # pylint: disable=redefined-outer-name
 ) -> None:
     check_config_interfaces(driver, storage)
-    check_config_network_instances(driver, storage)
+    #check_config_network_instances(driver, storage)
 
     resources_to_delete = list()
-    ni_if_names = list()
+    if_names = list()
     for ni in NETWORK_INSTANCES:
-        ni_name = ni['name']
         for ni_if in ni.get('interfaces', list()):
-            if_name     = ni_if['if_name']
-            subif_index = ni_if['sif_index']
-            resources_to_delete.append(network_instance_interface(ni_name, if_name, subif_index))
-            ni_if_names.append((ni_name, '{:s}.{:d}'.format(if_name, subif_index)))
-            storage.network_instances.interfaces.remove(ni_name, if_name) # TODO: add subif_index
+            if_name      = ni_if['name'       ]
+            subif_index  = ni_if['index'      ]
+            ipv4_address = ni_if['ipv4_addr'  ]
+            ipv4_prefix  = ni_if['ipv4_prefix']
+            enabled      = ni_if['enabled'    ]
+            resources_to_delete.append(interface(if_name, subif_index, ipv4_address, ipv4_prefix, enabled))
+            if_names.append(if_name)
+            storage.interfaces.ipv4_addresses.remove(if_name, subif_index, ipv4_address)
+            default_vlan = storage.network_instances.vlans.get('default', 1)
+            default_vlan_members : List[str] = default_vlan.setdefault('members', list())
+            if if_name not in default_vlan_members: default_vlan_members.append(if_name)
 
-    LOGGER.info('resources_to_delete = {:s}'.format(str(resources_to_delete)))
-    results_deleteconfig = driver.DeleteConfig(resources_to_delete)
-    LOGGER.info('results_deleteconfig = {:s}'.format(str(results_deleteconfig)))
-    check_updates(results_deleteconfig, '/network_instance[{:s}]/interface[{:s}]', ni_if_names)
-    
-    check_config_interfaces(driver, storage, max_retries=5)
-    check_config_network_instances(driver, storage, max_retries=5)
+    results_deleteconfig = del_config(driver, resources_to_delete)
+    check_updates(results_deleteconfig, '/interface[{:s}]', if_names)
 
+    check_config_interfaces(driver, storage, max_retries=10, retry_delay=2.0)
+    #check_config_network_instances(driver, storage, max_retries=10, retry_delay=2.0)
 
-def test_del_interfaces(
+
+def test_del_interfaces_from_network_instance(
     driver : GnmiOpenConfigDriver,  # pylint: disable=redefined-outer-name
     storage : Storage,              # pylint: disable=redefined-outer-name
 ) -> None:
     check_config_interfaces(driver, storage)
-    check_config_network_instances(driver, storage)
+    #check_config_network_instances(driver, storage)
 
     resources_to_delete = list()
-    if_names = list()
+    ni_if_names = list()
     for ni in NETWORK_INSTANCES:
         ni_name = ni['name']
         for ni_if in ni.get('interfaces', list()):
-            if_name      = ni_if['if_name']
-            subif_index  = ni_if['sif_index']
-            ipv4_address = ni_if['ipv4_addr']
-            ipv4_prefix  = ni_if['ipv4_prefix']
-            enabled      = ni_if['enabled']
-            resources_to_delete.append(interface(if_name, subif_index, ipv4_address, ipv4_prefix, enabled))
-            if_names.append(ni_name)
-            storage.interfaces.ipv4_addresses.remove(if_name, subif_index, ipv4_address)
-
-    LOGGER.info('resources_to_delete = {:s}'.format(str(resources_to_delete)))
-    results_deleteconfig = driver.DeleteConfig(resources_to_delete)
-    LOGGER.info('results_deleteconfig = {:s}'.format(str(results_deleteconfig)))
-    check_updates(results_deleteconfig, '/interface[{:s}]', if_names)
+            if_name     = ni_if['name' ]
+            subif_index = ni_if['index']
+            resources_to_delete.append(network_instance_interface(ni_name, if_name, subif_index))
+            ni_if_names.append((ni_name, '{:s}.{:d}'.format(if_name, subif_index)))
+            storage.network_instances.interfaces.remove(ni_name, if_name, subif_index)
 
-    check_config_interfaces(driver, storage, max_retries=5)
-    check_config_network_instances(driver, storage, max_retries=5)
+    results_deleteconfig = del_config(driver, resources_to_delete)
+    check_updates(results_deleteconfig, '/network_instance[{:s}]/interface[{:s}]', ni_if_names)
+    
+    check_config_interfaces(driver, storage, max_retries=10, retry_delay=2.0)
+    #check_config_network_instances(driver, storage, max_retries=10, retry_delay=2.0)
 
 
 def test_del_network_instances(
@@ -331,7 +339,7 @@ def test_del_network_instances(
     storage : Storage,              # pylint: disable=redefined-outer-name
 ) -> None:
     check_config_interfaces(driver, storage)
-    check_config_network_instances(driver, storage)
+    #check_config_network_instances(driver, storage)
 
     resources_to_delete = list()
     ni_names = list()
@@ -341,11 +349,12 @@ def test_del_network_instances(
         resources_to_delete.append(network_instance(ni_name, ni_type))
         ni_names.append(ni_name)
         storage.network_instances.network_instances.remove(ni_name)
+        storage.network_instances.protocols.remove(ni_name, 'DIRECTLY_CONNECTED')
+        storage.network_instances.tables.remove(ni_name, 'DIRECTLY_CONNECTED', 'IPV4')
+        storage.network_instances.tables.remove(ni_name, 'DIRECTLY_CONNECTED', 'IPV6')
 
-    LOGGER.info('resources_to_delete = {:s}'.format(str(resources_to_delete)))
-    results_deleteconfig = driver.DeleteConfig(resources_to_delete)
-    LOGGER.info('results_deleteconfig = {:s}'.format(str(results_deleteconfig)))
+    results_deleteconfig = del_config(driver, resources_to_delete)
     check_updates(results_deleteconfig, '/network_instance[{:s}]', ni_names)
 
-    check_config_interfaces(driver, storage, max_retries=5)
-    check_config_network_instances(driver, storage, max_retries=5)
+    check_config_interfaces(driver, storage, max_retries=10, retry_delay=2.0)
+    check_config_network_instances(driver, storage, max_retries=10, retry_delay=2.0)
diff --git a/src/device/tests/gnmi_openconfig/tools/check_updates.py b/src/device/tests/gnmi_openconfig/tools/check_updates.py
index 7f31844cffb43e25b81f9bbb97f5c7313497550b..a9e2a1be930baab7fd3a8d4c98ea512b583b5119 100644
--- a/src/device/tests/gnmi_openconfig/tools/check_updates.py
+++ b/src/device/tests/gnmi_openconfig/tools/check_updates.py
@@ -17,5 +17,6 @@ from typing import Iterable, List, Tuple
 def check_updates(results : Iterable[Tuple[str, bool]], format_str : str, item_ids : List[Tuple]) -> None:
     results = set(results)
     assert len(results) == len(item_ids)
-    for item_id in item_ids:
-        assert (format_str.format(*item_id), True) in results
+    for item_id_fields in item_ids:
+        if isinstance(item_id_fields, (str, int, float, bool)): item_id_fields = (item_id_fields,)
+        assert (format_str.format(*item_id_fields), True) in results
diff --git a/src/device/tests/gnmi_openconfig/tools/check_config.py b/src/device/tests/gnmi_openconfig/tools/manage_config.py
similarity index 71%
rename from src/device/tests/gnmi_openconfig/tools/check_config.py
rename to src/device/tests/gnmi_openconfig/tools/manage_config.py
index 5258da80c0e333c0a987d1f1d1543604dbebac92..72d6a09d323368cdf210701dfec8ae2fcd7ef55d 100644
--- a/src/device/tests/gnmi_openconfig/tools/check_config.py
+++ b/src/device/tests/gnmi_openconfig/tools/manage_config.py
@@ -13,7 +13,7 @@
 # limitations under the License.
 
 import copy, deepdiff, logging, time
-from typing import Callable, Dict, List, Tuple
+from typing import Callable, Dict, List, Tuple, Union
 from device.service.driver_api._Driver import (
     RESOURCE_ENDPOINTS, RESOURCE_INTERFACES, RESOURCE_NETWORK_INSTANCES,
     RESOURCE_ROUTING_POLICIES, RESOURCE_SERVICES
@@ -24,6 +24,28 @@ from .result_config_adapters import adapt_endpoint, adapt_interface, adapt_netwo
 
 LOGGER = logging.getLogger(__name__)
 
+def get_config(driver : GnmiOpenConfigDriver, resources_to_get : List[str]) -> List[Tuple[str, Dict]]:
+    LOGGER.info('[get_config] resources_to_get = {:s}'.format(str(resources_to_get)))
+    results_getconfig = driver.GetConfig(resources_to_get)
+    LOGGER.info('[get_config] results_getconfig = {:s}'.format(str(results_getconfig)))
+    return results_getconfig
+
+def set_config(
+    driver : GnmiOpenConfigDriver, resources_to_set : List[Tuple[str, Dict]]
+) -> List[Tuple[str, Union[bool, Exception]]]:
+    LOGGER.info('[set_config] resources_to_set = {:s}'.format(str(resources_to_set)))
+    results_setconfig = driver.SetConfig(resources_to_set)
+    LOGGER.info('[set_config] results_setconfig = {:s}'.format(str(results_setconfig)))
+    return results_setconfig
+
+def del_config(
+    driver : GnmiOpenConfigDriver, resources_to_delete : List[Tuple[str, Dict]]
+) -> List[Tuple[str, Union[bool, Exception]]]:
+    LOGGER.info('resources_to_delete = {:s}'.format(str(resources_to_delete)))
+    results_deleteconfig = driver.DeleteConfig(resources_to_delete)
+    LOGGER.info('results_deleteconfig = {:s}'.format(str(results_deleteconfig)))
+    return results_deleteconfig
+
 def check_expected_config(
     driver : GnmiOpenConfigDriver, resources_to_get : List[str], expected_config : List[Dict],
     func_adapt_returned_config : Callable[[Tuple[str, Dict]], Tuple[str, Dict]] = lambda x: x,
@@ -34,9 +56,7 @@ def check_expected_config(
     num_retry = 0
     return_data = None
     while num_retry < max_retries:
-        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)))
+        results_getconfig = get_config(driver, resources_to_get)
         return_data = copy.deepcopy(results_getconfig)
 
         results_getconfig = [
@@ -49,7 +69,7 @@ def check_expected_config(
         if num_diffs == 0: break
         # let the device take some time to reconfigure
         time.sleep(retry_delay)
-        num_retry -= 1
+        num_retry += 1
 
     if num_diffs > 0: LOGGER.error('Differences[{:d}]:\n{:s}'.format(num_diffs, str(diff_data.pretty())))
     assert num_diffs == 0
diff --git a/src/device/tests/gnmi_openconfig/tools/request_composers.py b/src/device/tests/gnmi_openconfig/tools/request_composers.py
index faa8425c8afa04fe5e1e5fa4a3c641052d865d9c..be058710109580448ceea86e6a09df35b503ded8 100644
--- a/src/device/tests/gnmi_openconfig/tools/request_composers.py
+++ b/src/device/tests/gnmi_openconfig/tools/request_composers.py
@@ -29,10 +29,10 @@ def network_instance(ni_name, ni_type) -> Tuple[str, Dict]:
     }
     return str_path, str_data
 
-def network_instance_static_route(ni_name, prefix, next_hop, next_hop_index=0, metric=1) -> Tuple[str, Dict]:
+def network_instance_static_route(ni_name, prefix, next_hop_index, next_hop, metric=1) -> Tuple[str, Dict]:
     str_path = '/network_instance[{:s}]/static_route[{:s}]'.format(ni_name, prefix)
     str_data = {
-        'name': ni_name, 'prefix': prefix, 'next_hop': next_hop, 'next_hop_index': next_hop_index, 'metric': metric
+        'name': ni_name, 'prefix': prefix, 'next_hop_index': next_hop_index, 'next_hop': next_hop, 'metric': metric
     }
     return str_path, str_data