diff --git a/proto/context.proto b/proto/context.proto
index 4d61572df1db6c95b64e9ce1cbfdd9e0db111078..c527078d67c906b8a725b3e1563677f48dd9fb37 100644
--- a/proto/context.proto
+++ b/proto/context.proto
@@ -223,6 +223,7 @@ enum DeviceDriverEnum {
   DEVICEDRIVER_IETF_ACTN = 10;
   DEVICEDRIVER_OC = 11;
   DEVICEDRIVER_QKD = 12;
+  DEVICEDRIVER_IETF_L3VPN = 13;
 }
 
 enum DeviceOperationalStatusEnum {
diff --git a/proto/kpi_sample_types.proto b/proto/kpi_sample_types.proto
index 0a9800d9e5839205e1e45f84e4c8bdafbe93f32f..d4efc084e5f1ea2376e71ef6a15bc9b972c5ac1d 100644
--- a/proto/kpi_sample_types.proto
+++ b/proto/kpi_sample_types.proto
@@ -39,4 +39,14 @@ enum KpiSampleType {
     KPISAMPLETYPE_L3_SECURITY_STATUS_CRYPTO     = 605;
 
     KPISAMPLETYPE_SERVICE_LATENCY_MS            = 701;
+
+// output KPIs
+    KPISAMPLETYPE_PACKETS_TRANSMITTED_AGG_OUTPUT           = 1101;
+    KPISAMPLETYPE_PACKETS_RECEIVED_AGG_OUTPUT              = 1102;
+    KPISAMPLETYPE_PACKETS_DROPPED_AGG_OUTPUT               = 1103;
+    KPISAMPLETYPE_BYTES_TRANSMITTED_AGG_OUTPUT             = 1201;
+    KPISAMPLETYPE_BYTES_RECEIVED_AGG_OUTPUT                = 1202;
+    KPISAMPLETYPE_BYTES_DROPPED_AGG_OUTPUT                 = 1203;
+
+    KPISAMPLETYPE_SERVICE_LATENCY_MS_AGG_OUTPUT            = 1701;
 }
diff --git a/scripts/run_tests_locally-analytics-backend.sh b/scripts/run_tests_locally-analytics-backend.sh
index 1c3386c62084bb42d6ffa2e1349b6f4286820a52..700155a42714bd05069c7c62db9ada09b4125355 100755
--- a/scripts/run_tests_locally-analytics-backend.sh
+++ b/scripts/run_tests_locally-analytics-backend.sh
@@ -18,8 +18,11 @@ PROJECTDIR=`pwd`
 
 cd $PROJECTDIR/src
 RCFILE=$PROJECTDIR/coverage/.coveragerc
+
 export KFK_SERVER_ADDRESS='127.0.0.1:9092'
+
 CRDB_SQL_ADDRESS=$(kubectl get service cockroachdb-public --namespace crdb -o jsonpath='{.spec.clusterIP}')
 export CRDB_URI="cockroachdb://tfs:tfs123@${CRDB_SQL_ADDRESS}:26257/tfs_analytics?sslmode=require"
-python3 -m pytest --log-level=DEBUG --log-cli-level=DEBUG --verbose \
+
+python3 -m pytest --log-level=DEBUG --log-cli-level=INFO --verbose \
     analytics/backend/tests/test_backend.py
diff --git a/scripts/run_tests_locally-analytics-frontend.sh b/scripts/run_tests_locally-analytics-frontend.sh
index 6e945406f0ff7b2670a35d5315d0ef428f701988..2c18296cf86ae4a00904fb684e2de5c56da9a2ea 100755
--- a/scripts/run_tests_locally-analytics-frontend.sh
+++ b/scripts/run_tests_locally-analytics-frontend.sh
@@ -18,8 +18,10 @@ PROJECTDIR=`pwd`
 
 cd $PROJECTDIR/src
 RCFILE=$PROJECTDIR/coverage/.coveragerc
+
 export KFK_SERVER_ADDRESS='127.0.0.1:9092'
 CRDB_SQL_ADDRESS=$(kubectl get service cockroachdb-public --namespace crdb -o jsonpath='{.spec.clusterIP}')
 export CRDB_URI="cockroachdb://tfs:tfs123@${CRDB_SQL_ADDRESS}:26257/tfs_analytics?sslmode=require"
-python3 -m pytest --log-level=DEBUG --log-cli-level=DEBUG --verbose \
+
+python3 -m pytest --log-level=DEBUG --log-cli-level=INFO --verbose \
     analytics/frontend/tests/test_frontend.py
diff --git a/scripts/run_tests_locally-nbi-ietf-slice.sh b/scripts/run_tests_locally-nbi-ietf-slice.sh
new file mode 100755
index 0000000000000000000000000000000000000000..bf53f18b9a37f9248b072ae2c699b5874fa2c869
--- /dev/null
+++ b/scripts/run_tests_locally-nbi-ietf-slice.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 --verbose \
+    nbi/tests/test_slice_2.py
diff --git a/scripts/run_tests_locally-telemetry-backend.sh b/scripts/run_tests_locally-telemetry-backend.sh
index 3ad4a2d0e05dbb11573eb146b4f0a4959894ace0..f648a62520f2f7b23f30edb19bf54735f5d13e12 100755
--- a/scripts/run_tests_locally-telemetry-backend.sh
+++ b/scripts/run_tests_locally-telemetry-backend.sh
@@ -18,15 +18,12 @@ PROJECTDIR=`pwd`
 
 cd $PROJECTDIR/src
 # RCFILE=$PROJECTDIR/coverage/.coveragerc
-# coverage run --rcfile=$RCFILE --append -m pytest --log-level=INFO --verbose \
-#     kpi_manager/tests/test_unitary.py
 
-# python3 kpi_manager/tests/test_unitary.py
 export KFK_SERVER_ADDRESS='127.0.0.1:9092'
 CRDB_SQL_ADDRESS=$(kubectl get service cockroachdb-public --namespace crdb -o jsonpath='{.spec.clusterIP}')
 export CRDB_URI="cockroachdb://tfs:tfs123@${CRDB_SQL_ADDRESS}:26257/tfs_telemetry?sslmode=require"
 RCFILE=$PROJECTDIR/coverage/.coveragerc
 
 
-python3 -m pytest --log-level=INFO --log-cli-level=debug --verbose \
-    telemetry/backend/tests/test_TelemetryBackend.py
+python3 -m pytest --log-level=debug --log-cli-level=debug --verbose \
+    telemetry/backend/tests/test_backend.py
diff --git a/scripts/run_tests_locally-telemetry-emulated.sh b/scripts/run_tests_locally-telemetry-emulated.sh
new file mode 100755
index 0000000000000000000000000000000000000000..879b878c7281a17dcc89a36ff146939151540ec4
--- /dev/null
+++ b/scripts/run_tests_locally-telemetry-emulated.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+# Copyright 2022-2024 ETSI 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
+
+# export KFK_SERVER_ADDRESS='127.0.0.1:9092'
+# CRDB_SQL_ADDRESS=$(kubectl get service cockroachdb-public --namespace crdb -o jsonpath='{.spec.clusterIP}')
+# export CRDB_URI="cockroachdb://tfs:tfs123@${CRDB_SQL_ADDRESS}:26257/tfs_telemetry?sslmode=require"
+RCFILE=$PROJECTDIR/coverage/.coveragerc
+
+
+python3 -m pytest --log-level=debug --log-cli-level=info --verbose \
+    telemetry/backend/tests/test_emulated.py
diff --git a/src/analytics/backend/service/AnalyticsBackendService.py b/src/analytics/backend/service/AnalyticsBackendService.py
index f3a58feaab8667b266052803dddd1641b8a690f3..1abdd62c0f7162fe7a50f1c08e698f71c5fc93ad 100755
--- a/src/analytics/backend/service/AnalyticsBackendService.py
+++ b/src/analytics/backend/service/AnalyticsBackendService.py
@@ -16,109 +16,164 @@ import time
 import json
 import logging
 import threading
+
 from common.tools.service.GenericGrpcService import GenericGrpcService
 from common.tools.kafka.Variables import KafkaConfig, KafkaTopic
-from confluent_kafka import Consumer as KafkaConsumer
-from confluent_kafka import KafkaError
+from confluent_kafka import Consumer
+from confluent_kafka import KafkaError, KafkaException
 from common.Constants import ServiceNameEnum
 from common.Settings import get_service_port_grpc
-from threading import Thread, Event
-from .DaskStreaming import DaskStreamer
+from analytics.backend.service.Streamer import DaskStreamer
+from analytics.backend.service.AnalyzerHelper import AnalyzerHelper
+
 
 LOGGER = logging.getLogger(__name__)
 
 class AnalyticsBackendService(GenericGrpcService):
     """
-    Class listens for ...
+    AnalyticsBackendService class is responsible for handling the requests from the AnalyticsFrontendService.
+    It listens to the Kafka topic for the requests to start and stop the Streamer accordingly.
+    It also initializes the Kafka producer and Dask cluster for the streamer.
     """
-    def __init__(self, cls_name : str = __name__) -> None:
+    def __init__(self, cls_name : str = __name__, n_workers=1, threads_per_worker=1
+                 ) -> None:
         LOGGER.info('Init AnalyticsBackendService')
         port = get_service_port_grpc(ServiceNameEnum.ANALYTICSBACKEND)
         super().__init__(port, cls_name=cls_name)
-        self.running_threads = {}       # To keep track of all running analyzers 
-        self.kafka_consumer = KafkaConsumer({'bootstrap.servers' : KafkaConfig.get_kafka_address(),
-                                            'group.id'           : 'analytics-frontend',
-                                            'auto.offset.reset'  : 'latest'})
+        self.active_streamers = {}
+        self.central_producer = AnalyzerHelper.initialize_kafka_producer()  # Multi-threaded producer
+        self.cluster          = AnalyzerHelper.initialize_dask_cluster(
+                                        n_workers, threads_per_worker) # Local cluster
+        self.request_consumer = Consumer({
+            'bootstrap.servers' : KafkaConfig.get_kafka_address(),
+            'group.id'          : 'analytics-backend',
+            'auto.offset.reset' : 'latest',
+            })
+
 
     def install_servicers(self):
-        threading.Thread(target=self.RequestListener, args=()).start()
+        threading.Thread(
+            target=self.RequestListener,
+            args=()
+        ).start()
 
     def RequestListener(self):
         """
         listener for requests on Kafka topic.
         """
         LOGGER.info("Request Listener is initiated ...")
-        # print      ("Request Listener is initiated ...")
-        consumer = self.kafka_consumer
+        consumer = self.request_consumer
         consumer.subscribe([KafkaTopic.ANALYTICS_REQUEST.value])
         while True:
-            receive_msg = consumer.poll(2.0)
-            if receive_msg is None:
+            message = consumer.poll(2.0)
+            if message is None:
                 continue
-            elif receive_msg.error():
-                if receive_msg.error().code() == KafkaError._PARTITION_EOF:
-                    continue
-                else:
-                    LOGGER.error("Consumer error: {:}".format(receive_msg.error()))
-                    # print       ("Consumer error: {:}".format(receive_msg.error()))
-                    break
+            elif message.error():
+                    if message.error().code() == KafkaError._PARTITION_EOF:
+                        LOGGER.warning(f"Consumer reached end of topic {message.topic()}/{message.partition()}")
+                        break
+                    elif message.error().code() == KafkaError.UNKNOWN_TOPIC_OR_PART:
+                        LOGGER.error(f"Subscribed topic {message.topic()} does not exist. May be topic does not have any messages.")
+                        continue
+                    elif message.error():
+                        raise KafkaException(message.error())
             try:
-                analyzer      = json.loads(receive_msg.value().decode('utf-8'))
-                analyzer_uuid = receive_msg.key().decode('utf-8')
-                LOGGER.debug('Recevied Analyzer: {:} - {:}'.format(analyzer_uuid, analyzer))
-                # print       ('Recevied Analyzer: {:} - {:}'.format(analyzer_uuid, analyzer))
+                analyzer      = json.loads(message.value().decode('utf-8'))
+                analyzer_uuid = message.key().decode('utf-8')
+                LOGGER.info('Recevied Analyzer: {:} - {:}'.format(analyzer_uuid, analyzer))
 
                 if analyzer["algo_name"] is None and analyzer["oper_mode"] is None:
-                    self.StopDaskListener(analyzer_uuid)
+                    if self.StopStreamer(analyzer_uuid):
+                        LOGGER.info("Dask Streamer stopped.")
+                    else:
+                        LOGGER.warning("Failed to stop Dask Streamer. May be already terminated...")
                 else:
-                    self.StartDaskListener(analyzer_uuid, analyzer)
+                    if self.StartStreamer(analyzer_uuid, analyzer):
+                        LOGGER.info("Dask Streamer started.")
+                    else:
+                        LOGGER.warning("Failed to start Dask Streamer.")
             except Exception as e:
                 LOGGER.warning("Unable to consume message from topic: {:}. ERROR: {:}".format(KafkaTopic.ANALYTICS_REQUEST.value, e))
-                # print         ("Unable to consume message from topic: {:}. ERROR: {:}".format(KafkaTopic.ANALYTICS_REQUEST.value, e))
-
-    def StartDaskListener(self, analyzer_uuid, analyzer):
-        kpi_list      = analyzer[ 'input_kpis'   ] 
-        thresholds    = analyzer[ 'thresholds'   ]
-        window_size   = analyzer[ 'window_size'  ]
-        window_slider = analyzer[ 'window_slider']
-
-        LOGGER.debug ("Received parameters: {:} - {:} - {:} - {:}".format(
-            kpi_list, thresholds, window_size, window_slider))
-        # print        ("Received parameters: {:} - {:} - {:} - {:}".format(
-        #     kpi_list, thresholds, window_size, window_slider))
+
+
+    def StartStreamer(self, analyzer_uuid : str, analyzer : dict):
+        """
+        Start the DaskStreamer with the given parameters.
+        """
+        if analyzer_uuid in self.active_streamers:
+            LOGGER.warning("Dask Streamer already running with the given analyzer_uuid: {:}".format(analyzer_uuid))
+            return False
         try:
-            stop_event = Event()
-            thread     = Thread(
-                target=DaskStreamer,
-                # args=(analyzer_uuid, kpi_list, oper_list, thresholds, stop_event),
-                args=(analyzer['output_kpis'][0] , kpi_list, thresholds, stop_event),
-                kwargs={
-                    "window_size"       : window_size,
-                }
+            streamer = DaskStreamer(
+                key               = analyzer_uuid,
+                input_kpis        = analyzer['input_kpis'        ],
+                output_kpis       = analyzer['output_kpis'       ],
+                thresholds        = analyzer['thresholds'        ],
+                batch_size        = analyzer['batch_size_min'    ],
+                batch_duration    = analyzer['batch_duration_min'],
+                window_size       = analyzer['window_size'       ],
+                cluster_instance  = self.cluster,
+                producer_instance = self.central_producer,
             )
-            thread.start()
-            self.running_threads[analyzer_uuid] = (thread, stop_event)
-            # print      ("Initiated Analyzer backend: {:}".format(analyzer_uuid))
-            LOGGER.info("Initiated Analyzer backend: {:}".format(analyzer_uuid))
+            streamer.start()
+            LOGGER.info(f"Streamer started with analyzer Id: {analyzer_uuid}")
+
+            # Stop the streamer after the given duration
+            duration = analyzer['duration']
+            if duration > 0:
+                def stop_after_duration():
+                    time.sleep(duration)
+                    LOGGER.warning(f"Execution duration ({duration}) completed of Analyzer: {analyzer_uuid}")
+                    if not self.StopStreamer(analyzer_uuid):
+                        LOGGER.warning("Failed to stop Dask Streamer. Streamer may be already terminated.")
+
+                duration_thread = threading.Thread(
+                    target=stop_after_duration, daemon=True, name=f"stop_after_duration_{analyzer_uuid}"
+                    )
+                duration_thread.start()
+
+            self.active_streamers[analyzer_uuid] = streamer
             return True
         except Exception as e:
-            # print       ("Failed to initiate Analyzer backend: {:}".format(e))
-            LOGGER.error("Failed to initiate Analyzer backend: {:}".format(e))
+            LOGGER.error("Failed to start Dask Streamer. ERROR: {:}".format(e))
             return False
 
-    def StopDaskListener(self, analyzer_uuid):
-        if analyzer_uuid in self.running_threads:
-            try:
-                thread, stop_event = self.running_threads[analyzer_uuid]
-                stop_event.set()
-                thread.join()
-                del self.running_threads[analyzer_uuid]
-                # print      ("Terminating backend (by TerminateBackend): Analyzer Id: {:}".format(analyzer_uuid))
-                LOGGER.info("Terminating backend (by TerminateBackend): Analyzer Id: {:}".format(analyzer_uuid))
+    def StopStreamer(self, analyzer_uuid : str):
+        """
+        Stop the DaskStreamer with the given analyzer_uuid.
+        """
+        try:
+            if analyzer_uuid not in self.active_streamers:
+                LOGGER.warning("Dask Streamer not found with the given analyzer_uuid: {:}".format(analyzer_uuid))
                 return True
-            except Exception as e:
-                LOGGER.error("Failed to terminate. Analyzer Id: {:} - ERROR: {:}".format(analyzer_uuid, e))
-                return False
-        else:
-            # print         ("Analyzer not found in active collectors. Analyzer Id: {:}".format(analyzer_uuid))
-            LOGGER.warning("Analyzer not found in active collectors: Analyzer Id: {:}".format(analyzer_uuid))
+            LOGGER.info(f"Terminating streamer with Analyzer Id: {analyzer_uuid}")
+            streamer = self.active_streamers[analyzer_uuid]
+            streamer.stop()
+            streamer.join()
+            del self.active_streamers[analyzer_uuid]
+            LOGGER.info(f"Streamer with analyzer_uuid '{analyzer_uuid}' has been trerminated sucessfully.")
+            return True
+        except:
+            LOGGER.exception("Failed to stop Dask Streamer.")
+            return False
+
+    def close(self):
+        """
+        Close the producer and cluster cleanly.
+        """
+        if self.central_producer:
+            try:
+                self.central_producer.flush()
+                LOGGER.info("Kafka producer flushed and closed.")
+            except:
+                LOGGER.exception("Error closing Kafka producer")
+        if self.cluster:
+            try:
+                self.cluster.close()
+                LOGGER.info("Dask cluster closed.")
+            except:
+                LOGGER.exception("Error closing Dask cluster")
+
+    def stop(self):
+        self.close()
+        return super().stop()
diff --git a/src/analytics/backend/service/AnalyzerHandlers.py b/src/analytics/backend/service/AnalyzerHandlers.py
new file mode 100644
index 0000000000000000000000000000000000000000..256530ba78329f09327b551f0238f4dd8a1258b5
--- /dev/null
+++ b/src/analytics/backend/service/AnalyzerHandlers.py
@@ -0,0 +1,136 @@
+# Copyright 2022-2024 ETSI 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 logging
+from enum import Enum
+import pandas as pd
+
+logger = logging.getLogger(__name__)
+
+
+class Handlers(Enum):
+    AGGREGATION_HANDLER = "AggregationHandler"
+    UNSUPPORTED_HANDLER = "UnsupportedHandler"
+
+    @classmethod
+    def is_valid_handler(cls, handler_name):
+        return handler_name in cls._value2member_map_
+
+# This method is top-level and should not be part of the class due to serialization issues.
+def threshold_handler(key, aggregated_df, thresholds):
+    """
+    Apply thresholds (TH-Fall and TH-Raise) based on the thresholds dictionary
+    on the aggregated DataFrame.
+
+    Args:
+        key (str): Key for the aggregated DataFrame.
+        aggregated_df (pd.DataFrame): DataFrame with aggregated metrics.
+        thresholds (dict): Thresholds dictionary with keys in the format '<metricName>' and values as (fail_th, raise_th).
+
+    Returns:
+        pd.DataFrame: DataFrame with additional threshold columns.
+    """
+    for metric_name, threshold_values in thresholds.items():
+        # Ensure the metric column exists in the DataFrame
+        if metric_name not in aggregated_df.columns:
+            logger.warning(f"Metric '{metric_name}' does not exist in the DataFrame for key: {key}. Skipping threshold application.")
+            continue
+        
+        # Ensure the threshold values are valid (check for tuple specifically)
+        if isinstance(threshold_values, list) and len(threshold_values) == 2:
+            fail_th, raise_th = threshold_values
+            
+            # Add threshold columns with updated naming
+            aggregated_df[f"{metric_name}_TH_RAISE"] = aggregated_df[metric_name] > raise_th
+            aggregated_df[f"{metric_name}_TH_FALL"]  = aggregated_df[metric_name] < fail_th
+        else:
+            logger.warning(f"Threshold values for '{metric_name}' ({threshold_values}) are not a list of length 2. Skipping threshold application.")
+    return aggregated_df
+
+def aggregation_handler(
+        batch_type_name, key, batch, input_kpi_list, output_kpi_list, thresholds
+    ):
+    """
+      Process a batch of data and calculate aggregated values for each input KPI
+      and maps them to the output KPIs. """
+
+    logger.info(f"({batch_type_name}) Processing batch for key: {key}")
+    if not batch:
+        logger.info("Empty batch received. Skipping processing.")
+        return []
+    else:
+        logger.info(f" >>>>> Processing {len(batch)} records for key: {key}")
+        
+        # Convert data into a DataFrame
+        df = pd.DataFrame(batch)
+
+        # Filter the DataFrame to retain rows where kpi_id is in the input list (subscribed endpoints only)
+        df = df[df['kpi_id'].isin(input_kpi_list)].copy()
+
+        if df.empty:
+            logger.warning(f"No data available for KPIs: {input_kpi_list}. Skipping processing.")
+            return []
+
+        # Define all possible aggregation methods
+        aggregation_methods = {
+            "min"     : ('kpi_value', 'min'),
+            "max"     : ('kpi_value', 'max'),
+            "avg"     : ('kpi_value', 'mean'),
+            "first"   : ('kpi_value', lambda x: x.iloc[0]),
+            "last"    : ('kpi_value', lambda x: x.iloc[-1]),
+            "variance": ('kpi_value', 'var'),
+            "count"   : ('kpi_value', 'count'),
+            "range"   : ('kpi_value', lambda x: x.max() - x.min()),
+            "sum"     : ('kpi_value', 'sum'),
+        }
+
+        results = []
+        
+        # Process each KPI-specific task parameter
+        for kpi_index, kpi_id in enumerate(input_kpi_list):
+
+            # logger.info(f"1.Processing KPI: {kpi_id}")
+            kpi_task_parameters = thresholds["task_parameter"][kpi_index]
+            
+            # Get valid task parameters for this KPI
+            valid_task_parameters = [
+                method for method in kpi_task_parameters.keys() 
+                if method in aggregation_methods
+            ]
+
+            # Select the aggregation methods based on valid task parameters
+            selected_methods = {method: aggregation_methods[method] for method in valid_task_parameters}
+
+            # logger.info(f"2. Processing KPI: {kpi_id} with task parameters: {kpi_task_parameters}")
+            kpi_df = df[df['kpi_id'] == kpi_id]
+
+            # Check if kpi_df is not empty before applying the aggregation methods
+            if not kpi_df.empty:
+                agg_df = kpi_df.groupby('kpi_id').agg(**selected_methods).reset_index()
+
+                # logger.info(f"3. Aggregated DataFrame for KPI: {kpi_id}: {agg_df}")
+
+                agg_df['kpi_id'] = output_kpi_list[kpi_index]
+
+                # logger.info(f"4. Applying thresholds for df: {agg_df['kpi_id']}")
+                record = threshold_handler(key, agg_df, kpi_task_parameters)
+
+                results.extend(record.to_dict(orient='records'))
+            else:
+                logger.warning(f"No data available for KPIs: {kpi_id}. Skipping aggregation.")
+                continue
+        if results:
+            return results
+        else:
+            return []
diff --git a/src/analytics/backend/service/AnalyzerHelper.py b/src/analytics/backend/service/AnalyzerHelper.py
new file mode 100644
index 0000000000000000000000000000000000000000..15a45aee68341c599905983efd79737a9d4929ab
--- /dev/null
+++ b/src/analytics/backend/service/AnalyzerHelper.py
@@ -0,0 +1,67 @@
+# Copyright 2022-2024 ETSI 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 dask.distributed import Client, LocalCluster
+from common.tools.kafka.Variables import KafkaConfig, KafkaTopic
+from confluent_kafka import Consumer, Producer
+
+import logging
+logger = logging.getLogger(__name__)
+
+
+class AnalyzerHelper:
+    def __init__(self):
+        pass
+
+    @staticmethod
+    def initialize_dask_client(cluster_instance):
+        """Initialize a local Dask client."""
+        if cluster_instance is None:
+            logger.error("Dask Cluster is not initialized. Exiting.")
+            return None
+        client = Client(cluster_instance)
+        logger.info(f"Dask Client Initialized: {client}")
+        return client
+
+    @staticmethod
+    def initialize_dask_cluster(n_workers=1, threads_per_worker=2):
+        """Initialize a local Dask cluster"""
+        cluster = LocalCluster(n_workers=n_workers, threads_per_worker=threads_per_worker)
+        logger.info(f"Dask Cluster Initialized: {cluster}")
+        return cluster
+
+    @staticmethod
+    def initialize_kafka_consumer():    # TODO: update to receive topic and group_id as parameters
+        """Initialize the Kafka consumer."""
+        consumer_conf = {
+            'bootstrap.servers': KafkaConfig.get_kafka_address(),
+            'group.id': 'analytics-backend',
+            'auto.offset.reset': 'latest'
+        }
+        consumer = Consumer(consumer_conf)
+        consumer.subscribe([KafkaTopic.VALUE.value])
+        return consumer
+
+    @staticmethod
+    def initialize_kafka_producer():
+        """Initialize the Kafka producer."""
+        return Producer({'bootstrap.servers': KafkaConfig.get_kafka_address()})
+
+    @staticmethod
+    def delivery_report(err, msg):
+        if err is not None:
+            logger.error(f"Message delivery failed: {err}")
+        else:
+            logger.debug(f"Message delivered to {msg.topic()} [{msg.partition()}] at offset {msg.offset()}")
diff --git a/src/analytics/backend/service/DaskStreaming.py b/src/analytics/backend/service/DaskStreaming.py
deleted file mode 100644
index 79dee7ef972a8b5546e3b38289c4fdb5b4bcc0d1..0000000000000000000000000000000000000000
--- a/src/analytics/backend/service/DaskStreaming.py
+++ /dev/null
@@ -1,268 +0,0 @@
-# Copyright 2022-2024 ETSI 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 logging
-import time
-import json
-from confluent_kafka import Consumer, Producer, KafkaException, KafkaError
-import pandas as pd
-from dask.distributed import Client, LocalCluster
-from common.tools.kafka.Variables import KafkaConfig, KafkaTopic
-
-logging.basicConfig(level=logging.INFO)
-LOGGER = logging.getLogger(__name__)
-
-def SettingKafkaConsumerParams():
-    return {'bootstrap.servers'  : KafkaConfig.get_kafka_address(),
-            'group.id'           : 'analytics-backend',
-            'auto.offset.reset'  : 'latest'}
-
-def GetAggregationMappings(thresholds):
-    agg_dict = {}
-    for threshold_key in thresholds.keys():
-        parts = threshold_key.split('_', 1)
-        if len(parts) != 2:
-            LOGGER.warning(f"Threshold key '{threshold_key}' does not follow the '<aggregation>_<metricName>' format. Skipping.")
-            continue
-        aggregation, metric_name = parts
-        # Ensure that the aggregation function is valid in pandas
-        if aggregation not in ['mean', 'min', 'max', 'first', 'last', 'std']:
-            LOGGER.warning(f"Unsupported aggregation '{aggregation}' in threshold key '{threshold_key}'. Skipping.")
-            continue
-        agg_dict[threshold_key] = ('kpi_value', aggregation)
-    return agg_dict
-
-
-def ApplyThresholds(aggregated_df, thresholds):
-    """
-    Apply thresholds (TH-Fall and TH-Raise) based on the thresholds dictionary
-    on the aggregated DataFrame.
-    Args:       aggregated_df (pd.DataFrame): DataFrame with aggregated metrics.
-                thresholds (dict): Thresholds dictionary with keys in the format '<aggregation>_<metricName>'.
-    Returns:    pd.DataFrame: DataFrame with additional threshold columns.
-    """
-    for threshold_key, threshold_values in thresholds.items():
-        if threshold_key not in aggregated_df.columns:
-
-            LOGGER.warning(f"Threshold key '{threshold_key}' does not correspond to any aggregation result. Skipping threshold application.")
-            continue
-        if isinstance(threshold_values, (list, tuple)) and len(threshold_values) == 2:
-            fail_th, raise_th = threshold_values
-            aggregated_df["THRESHOLD_FALL"] = aggregated_df[threshold_key] < fail_th
-            aggregated_df["THRESHOLD_RAISE"] = aggregated_df[threshold_key] > raise_th
-            aggregated_df["value"] = aggregated_df[threshold_key]
-        else:
-            LOGGER.warning(f"Threshold values for '{threshold_key}' are not a list or tuple of length 2. Skipping threshold application.")
-    return aggregated_df
-
-def initialize_dask_client():
-    """
-    Initialize a local Dask cluster and client.
-    """
-    cluster = LocalCluster(n_workers=2, threads_per_worker=2)
-    client = Client(cluster)
-    LOGGER.info(f"Dask Client Initialized: {client}")
-    return client, cluster
-
-def initialize_kafka_producer():
-    return Producer({'bootstrap.servers': KafkaConfig.get_kafka_address()})
-
-def delivery_report(err, msg):
-    if err is not None:
-        LOGGER.error(f"Message delivery failed: {err}")
-    else:
-        LOGGER.info(f"Message delivered to {msg.topic()} [{msg.partition()}] at offset {msg.offset()}")
-
-def process_batch(batch, agg_mappings, thresholds, key):
-    """
-    Process a batch of data and apply thresholds.
-    Args:       batch (list of dict): List of messages from Kafka.
-                agg_mappings (dict): Mapping from threshold key to aggregation function.
-                thresholds (dict): Thresholds dictionary.
-    Returns:    list of dict: Processed records ready to be sent to Kafka.
-    """
-    if not batch:
-        LOGGER.info("Empty batch received. Skipping processing.")
-        return []
-
-
-    df = pd.DataFrame(batch)
-    LOGGER.info(f"df {df} ")
-    df['time_stamp'] = pd.to_datetime(df['time_stamp'], errors='coerce')
-    df.dropna(subset=['time_stamp'], inplace=True)
-    LOGGER.info(f"df {df} ")
-    required_columns = {'time_stamp', 'kpi_id', 'kpi_value'}
-    if not required_columns.issubset(df.columns):
-        LOGGER.warning(f"Batch contains missing required columns. Required columns: {required_columns}. Skipping batch.")
-        return []
-    if df.empty:
-        LOGGER.info("No data after filtering by KPI IDs. Skipping processing.")
-        return []
-
-    # Perform aggregations using named aggregation
-    try:
-        agg_dict = {key: value for key, value in agg_mappings.items()}
-
-        df_agg_ = df.groupby(['window_start']).agg(**agg_dict).reset_index()
-
-        #example: agg_dict = {'min_latency_E2E': ('kpi_value', 'min')
-
-        #given that threshold has 1 value
-        second_value_tuple = next(iter(agg_dict.values()))[1]
-        #in case we have multiple thresholds!
-        #second_values_tuples = [value[1] for value in agg_dict.values()]
-        if second_value_tuple=="min":
-            df_agg = df_agg_.min(numeric_only=True).to_frame().T
-        elif second_value_tuple == "max":
-            df_agg = df_agg_.max(numeric_only=True).to_frame().T
-        elif second_value_tuple == "std":
-            df_agg = df_agg_.sted(numeric_only=True).to_frame().T
-        else:
-            df_agg = df_agg_.mean(numeric_only=True).to_frame().T
-
-        # Assign the first value of window_start from the original aggregated data
-        df_agg['window_start'] = df_agg_['window_start'].iloc[0]
-
-        # Reorder columns to place 'window_start' first if needed
-        cols = ['window_start'] + [col for col in df_agg.columns if col != 'window_start']
-        df_agg = df_agg[cols]
-
-    except Exception as e:
-        LOGGER.error(f"Aggregation error: {e}")
-        return []
-
-    # Apply thresholds
-
-
-    df_thresholded = ApplyThresholds(df_agg, thresholds)
-    df_thresholded['kpi_id'] = key
-    df_thresholded['window_start'] = df_thresholded['window_start'].dt.strftime('%Y-%m-%dT%H:%M:%SZ')
-    # Convert aggregated DataFrame to list of dicts
-    result = df_thresholded.to_dict(orient='records')
-    LOGGER.info(f"Processed batch with {len(result)} records after aggregation and thresholding.")
-    return result
-
-def produce_result(result, producer, destination_topic):
-    for record in result:
-        try:
-            producer.produce(
-                destination_topic,
-                key=str(record.get('kpi_id', '')),
-                value=json.dumps(record),
-                callback=delivery_report
-            )
-        except KafkaException as e:
-            LOGGER.error(f"Failed to produce message: {e}")
-    producer.flush()
-    LOGGER.info(f"Produced {len(result)} aggregated records to '{destination_topic}'.")
-
-def DaskStreamer(key, kpi_list, thresholds, stop_event,
-                window_size="30s", time_stamp_col="time_stamp"):
-    client, cluster = initialize_dask_client()
-    consumer_conf   = SettingKafkaConsumerParams()
-    consumer        = Consumer(consumer_conf)
-    consumer.subscribe([KafkaTopic.VALUE.value])
-    producer        = initialize_kafka_producer()
-
-    # Parse window_size to seconds
-    try:
-        window_size_td = pd.to_timedelta(window_size)
-        window_size_seconds = window_size_td.total_seconds()
-    except Exception as e:
-        LOGGER.error(f"Invalid window_size format: {window_size}. Error: {e}")
-        window_size_seconds = 30 
-    LOGGER.info(f"Batch processing interval set to {window_size_seconds} seconds.")
-
-    # Extract aggregation mappings from thresholds
-    agg_mappings = GetAggregationMappings(thresholds)
-    if not agg_mappings:
-        LOGGER.error("No valid aggregation mappings extracted from thresholds. Exiting streamer.")
-        consumer.close()
-        producer.flush()
-        client.close()
-        cluster.close()
-        return
-    try:
-        batch = []
-        last_batch_time = time.time()
-        LOGGER.info("Starting to consume messages...")
-
-        while not stop_event.is_set():
-            msg = consumer.poll(1.0)
-
-            if msg is None:
-                current_time = time.time()
-                if (current_time - last_batch_time) >= window_size_seconds and batch:
-                    LOGGER.info("Time-based batch threshold reached. Processing batch.")
-                    future = client.submit(process_batch, batch, agg_mappings, thresholds)
-                    future.add_done_callback(lambda fut: produce_result(fut.result(), producer, KafkaTopic.ALARMS.value))
-                    batch = []
-                    last_batch_time = current_time
-                continue
-
-            if msg.error():
-                if msg.error().code() == KafkaError._PARTITION_EOF:
-                    LOGGER.warning(f"End of partition reached {msg.topic()} [{msg.partition()}] at offset {msg.offset()}")
-                else:
-                    LOGGER.error(f"Kafka error: {msg.error()}")
-                continue
-
-            try:
-                message_value = json.loads(msg.value().decode('utf-8'))
-            except json.JSONDecodeError as e:
-                LOGGER.error(f"JSON decode error: {e}")
-                continue
-
-            try:
-                message_timestamp = pd.to_datetime(message_value[time_stamp_col], errors='coerce')
-                LOGGER.warning(f"message_timestamp: {message_timestamp}. Skipping message.")
-
-                if pd.isna(message_timestamp):
-                    LOGGER.warning(f"Invalid timestamp in message: {message_value}. Skipping message.")
-                    continue
-                window_start = message_timestamp.floor(window_size)
-                LOGGER.warning(f"window_start: {window_start}. Skipping message.")
-                message_value['window_start'] = window_start
-            except Exception as e:
-                LOGGER.error(f"Error processing timestamp: {e}. Skipping message.")
-                continue
-
-            if message_value['kpi_id'] not in kpi_list:
-                LOGGER.debug(f"KPI ID '{message_value['kpi_id']}' not in kpi_list. Skipping message.")
-                continue
-
-            batch.append(message_value)
-
-            current_time = time.time()
-            if (current_time - last_batch_time) >= window_size_seconds and batch:
-                LOGGER.info("Time-based batch threshold reached. Processing batch.")
-                future = client.submit(process_batch, batch, agg_mappings, thresholds, key)
-                future.add_done_callback(lambda fut: produce_result(fut.result(), producer, KafkaTopic.ALARMS.value))
-                batch = []
-                last_batch_time = current_time
-
-    except Exception as e:
-        LOGGER.exception(f"Error in Dask streaming process: {e}")
-    finally:
-        # Process any remaining messages in the batch
-        if batch:
-            LOGGER.info("Processing remaining messages in the batch.")
-            future = client.submit(process_batch, batch, agg_mappings, thresholds)
-            future.add_done_callback(lambda fut: produce_result(fut.result(), producer, KafkaTopic.ALARMS.value))
-        consumer.close()
-        producer.flush()
-        LOGGER.info("Kafka consumer and producer closed.")
-        client.close()
-        cluster.close()
-        LOGGER.info("Dask client and cluster closed.")
diff --git a/src/analytics/backend/service/Streamer.py b/src/analytics/backend/service/Streamer.py
new file mode 100644
index 0000000000000000000000000000000000000000..10917f002ed306ea408a20b92e94aed597ef1ea3
--- /dev/null
+++ b/src/analytics/backend/service/Streamer.py
@@ -0,0 +1,167 @@
+# Copyright 2022-2024 ETSI 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 time
+import json
+import threading
+import logging
+
+from confluent_kafka                            import KafkaException, KafkaError
+from common.tools.kafka.Variables               import KafkaTopic
+from analytics.backend.service.AnalyzerHandlers import Handlers, aggregation_handler
+from analytics.backend.service.AnalyzerHelper   import AnalyzerHelper
+
+
+logger = logging.getLogger(__name__)
+
+
+class DaskStreamer(threading.Thread):
+    def __init__(self, key, input_kpis, output_kpis, thresholds, 
+                 batch_size        = 5, 
+                 batch_duration    = None,
+                 window_size       = None,
+                 cluster_instance  = None,
+                 producer_instance = AnalyzerHelper.initialize_kafka_producer()
+                 ):
+        super().__init__()
+        self.key            = key
+        self.input_kpis     = input_kpis
+        self.output_kpis    = output_kpis
+        self.thresholds     = thresholds
+        self.window_size    = window_size      # TODO: Not implemented
+        self.batch_size     = batch_size
+        self.batch_duration = batch_duration
+        self.running        = True
+        self.batch          = []
+
+        # Initialize Kafka and Dask components
+        self.client   = AnalyzerHelper.initialize_dask_client(cluster_instance)
+        self.consumer = AnalyzerHelper.initialize_kafka_consumer()      # Single-threaded consumer
+        self.producer = producer_instance
+
+        logger.info("Dask Streamer initialized.")
+
+    def run(self):
+        """Main method to start the DaskStreamer."""
+        try:
+            logger.info("Starting Dask Streamer")
+            last_batch_time = time.time()
+            while True:
+                if not self.consumer:
+                    logger.warning("Kafka consumer is not initialized or stopped. Exiting loop.")
+                    break
+                if not self.running:
+                    logger.warning("Dask Streamer instance has been terminated. Exiting loop.")
+                    break
+                if not self.client:
+                    logger.warning("Dask client is not running. Exiting loop.")
+                    break
+                message = self.consumer.poll(timeout=1.0)
+                if message is None:
+                    # logger.info("No new messages received.")
+                    continue
+                if message.error():
+                    if message.error().code() == KafkaError._PARTITION_EOF:
+                        logger.warning(f"Consumer reached end of topic {message.topic()}/{message.partition()}")
+                    elif message.error().code() == KafkaError.UNKNOWN_TOPIC_OR_PART:
+                        logger.error(f"Subscribed topic {message.topic()} does not exist. May be topic does not have any messages.")
+                        continue
+                    elif message.error():
+                        raise KafkaException(message.error())
+                else:
+                    try:
+                        value = json.loads(message.value())
+                    except json.JSONDecodeError:
+                        logger.error(f"Failed to decode message: {message.value()}")
+                        continue
+                    self.batch.append(value)
+
+                # Window size has a precedence over batch size
+                if self.batch_duration is None:
+                    if len(self.batch) >= self.batch_size:  # If batch size is not provided, process continue with the default batch size
+                        logger.info(f"Processing based on batch size {self.batch_size}.")
+                        self.task_handler_selector()
+                        self.batch = []
+                else:
+                    # Process based on window size
+                    current_time = time.time()
+                    if (current_time - last_batch_time) >= self.batch_duration and self.batch:
+                        logger.info(f"Processing based on window size {self.batch_duration}.")
+                        self.task_handler_selector()
+                        self.batch = []
+                        last_batch_time = current_time
+
+        except Exception as e:
+            logger.exception(f"Error in Dask streaming process: {e}")
+        finally:
+            self.stop()
+            logger.info(">>> Exiting Dask Streamer...")
+
+    def task_handler_selector(self):
+        """Select the task handler based on the task type."""
+        logger.info(f"Batch to be processed: {self.batch}")
+        if Handlers.is_valid_handler(self.thresholds["task_type"]):
+            if self.client is not None and self.client.status == 'running':
+                try:
+                    future = self.client.submit(aggregation_handler, "batch size", self.key,
+                                                    self.batch, self.input_kpis, self.output_kpis, self.thresholds)
+                    future.add_done_callback(lambda fut: self.produce_result(fut.result(), KafkaTopic.ALARMS.value))
+                except Exception as e:
+                    logger.error(f"Failed to submit task to Dask client or unable to process future. See error for detail: {e}")
+            else:
+                logger.warning("Dask client is not running. Skipping processing.")
+        else:
+            logger.warning(f"Unknown task type: {self.thresholds['task_type']}. Skipping processing.")
+
+    def produce_result(self, result, destination_topic):
+        """Produce results to the Kafka topic."""
+        if not result:
+            logger.warning("Nothing to produce. Skipping.")
+            return
+        for record in result:
+            try:
+                self.producer.produce(
+                    destination_topic,
+                    key=str(record.get('kpi_id', '')),
+                    value=json.dumps(record),
+                    callback=AnalyzerHelper.delivery_report
+                )
+            except KafkaException as e:
+                logger.error(f"Failed to produce message: {e}")
+        self.producer.flush()
+        logger.info(f"Produced {len(result)} aggregated records to '{destination_topic}'.")
+
+    def stop(self):
+        """Clean up Kafka and Dask thread resources."""
+        if not self.running:
+            logger.info("Dask Streamer is already stopped.")
+            return
+        self.running = False
+        logger.info("Streamer running status is set to False. Waiting 5 seconds before stopping...")
+        time.sleep(5)       # Waiting time for running tasks to complete
+        if self.consumer:
+            try:
+                self.consumer.close()
+                logger.info("Kafka consumer closed.")
+            except Exception as e:
+                logger.error(f"Error closing Kafka consumer: {e}")
+
+        if self.client is not None and hasattr(self.client, 'status') and self.client.status == 'running':
+            try:
+                self.client.close()
+                logger.info("Dask client closed.")
+            except Exception as e:
+                logger.error(f"Error closing Dask client: {e}")
+
+# TODO: May be Single streamer for all analyzers ... ?
diff --git a/src/analytics/backend/tests/messages.py b/src/analytics/backend/tests/messages.py
index 55d966dfbbae2318a5f774049b02f5b340070113..2ff1e93536e94863ba9eaaf76d35f7453ba95727 100644
--- a/src/analytics/backend/tests/messages.py
+++ b/src/analytics/backend/tests/messages.py
@@ -53,8 +53,8 @@ def create_analyzer():
     _create_analyzer.algorithm_name               = "Test_Aggergate_and_Threshold"
     _create_analyzer.operation_mode               = AnalyzerOperationMode.ANALYZEROPERATIONMODE_STREAMING
     
-    _kpi_id = KpiId()
     # input IDs to analyze
+    _kpi_id = KpiId()
     _kpi_id.kpi_id.uuid              = str(uuid.uuid4())
     _kpi_id.kpi_id.uuid              = "5716c369-932b-4a02-b4c7-6a2e808b92d7"
     _create_analyzer.input_kpi_ids.append(_kpi_id)
@@ -63,11 +63,14 @@ def create_analyzer():
     _create_analyzer.input_kpi_ids.append(_kpi_id)
     _kpi_id.kpi_id.uuid              = str(uuid.uuid4())
     _create_analyzer.input_kpi_ids.append(_kpi_id)
+
     # output IDs after analysis
+    _kpi_id = KpiId()
     _kpi_id.kpi_id.uuid              = str(uuid.uuid4())
     _create_analyzer.output_kpi_ids.append(_kpi_id)
     _kpi_id.kpi_id.uuid              = str(uuid.uuid4())
     _create_analyzer.output_kpi_ids.append(_kpi_id)
+    
     # parameter
     _threshold_dict = {
         # 'avg_value'   :(20, 30), 'min_value'   :(00, 10), 'max_value'   :(45, 50),
diff --git a/src/analytics/backend/tests/messages_analyzer.py b/src/analytics/backend/tests/messages_analyzer.py
new file mode 100644
index 0000000000000000000000000000000000000000..813b4f06cdbaf1dd1c00c4d0f0dfa4b78339e09c
--- /dev/null
+++ b/src/analytics/backend/tests/messages_analyzer.py
@@ -0,0 +1,67 @@
+# Copyright 2022-2024 ETSI 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 pandas as pd
+from analytics.backend.service.AnalyzerHandlers import Handlers
+
+def get_input_kpi_list():
+    return ["1e22f180-ba28-4641-b190-2287bf446666", "6e22f180-ba28-4641-b190-2287bf448888", 'kpi_3']
+
+def get_output_kpi_list():
+    return ["1e22f180-ba28-4641-b190-2287bf441616", "6e22f180-ba28-4641-b190-2287bf181818", 'kpi_4']
+
+def get_thresholds():
+    return {
+        "task_type": Handlers.AGGREGATION_HANDLER.value,
+        "task_parameter": [
+            {"last":  [40, 80], "variance": [300, 500]},
+            {"count": [2,  4],  "max":      [70,  100]},
+            {"min":   [10, 20], "avg":      [50,  70]},
+        ],
+    }
+
+def get_duration():
+    return 90
+
+def get_batch_duration():
+    return 30
+
+def get_windows_size():
+    return None
+
+def get_batch_size():
+    return 5
+
+def get_interval():
+    return 5
+
+def get_batch():
+    return [
+        {"time_stamp": "2025-01-13T08:44:10Z", "kpi_id": "6e22f180-ba28-4641-b190-2287bf448888", "kpi_value": 46.72},
+        {"time_stamp": "2025-01-13T08:44:12Z", "kpi_id": "6e22f180-ba28-4641-b190-2287bf448888", "kpi_value": 65.22},
+        {"time_stamp": "2025-01-13T08:44:14Z", "kpi_id": "1e22f180-ba28-4641-b190-2287bf446666", "kpi_value": 54.24},
+        {"time_stamp": "2025-01-13T08:44:16Z", "kpi_id": "1e22f180-ba28-4641-b190-2287bf446666", "kpi_value": 57.67},
+        {"time_stamp": "2025-01-13T08:44:18Z", "kpi_id": "1e22f180-ba28-4641-b190-2287bf446666", "kpi_value": 38.6},
+        {"time_stamp": "2025-01-13T08:44:20Z", "kpi_id": "6e22f180-ba28-4641-b190-2287bf448888", "kpi_value": 38.9},
+        {"time_stamp": "2025-01-13T08:44:22Z", "kpi_id": "6e22f180-ba28-4641-b190-2287bf448888", "kpi_value": 52.44},
+        {"time_stamp": "2025-01-13T08:44:24Z", "kpi_id": "6e22f180-ba28-4641-b190-2287bf448888", "kpi_value": 47.76},
+        {"time_stamp": "2025-01-13T08:44:26Z", "kpi_id": "efef4d95-1cf1-43c4-9742-95c283ddd7a6", "kpi_value": 33.71},
+        {"time_stamp": "2025-01-13T08:44:28Z", "kpi_id": "efef4d95-1cf1-43c4-9742-95c283ddd7a6", "kpi_value": 64.44},
+    ]
+
+def get_agg_df():
+    data = [ 
+        {"kpi_id": "1e22f180-ba28-4641-b190-2287bf441616", "last": 47.76, "variance": 970.41},
+    ]
+    return pd.DataFrame(data)
diff --git a/src/analytics/backend/tests/test_backend.py b/src/analytics/backend/tests/test_backend.py
index 4aa9df5fae9849ee429361603a35b2fb8eaa4d23..1bbfaee136942bb7f14e77438683e8460f0a4f0b 100644
--- a/src/analytics/backend/tests/test_backend.py
+++ b/src/analytics/backend/tests/test_backend.py
@@ -12,148 +12,307 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import time, json
-from typing import Dict
+import time
+import json
+import pytest
 import logging
-from threading import Event, Thread
-from common.tools.kafka.Variables import KafkaTopic
+import pandas as pd
+
+from unittest.mock      import MagicMock, patch
+from .messages_analyzer import get_batch, get_input_kpi_list, get_output_kpi_list, get_thresholds, \
+                               get_windows_size, get_batch_size, get_agg_df, get_duration
+
+from common.tools.kafka.Variables                      import KafkaTopic
+from analytics.backend.service.Streamer                import DaskStreamer
+from analytics.backend.service.AnalyzerHandlers        import aggregation_handler, threshold_handler
 from analytics.backend.service.AnalyticsBackendService import AnalyticsBackendService
-from analytics.backend.tests.messages import get_kpi_id_list, get_operation_list, get_threshold_dict
-from .messages import create_analyzer, create_analyzer_dask
-from threading import Thread, Event
-from ..service.DaskStreaming import DaskStreamer
 
-LOGGER = logging.getLogger(__name__)
 
+logger = logging.getLogger(__name__)
+logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(funcName)s -  %(levelname)s - %(message)s')
+
+
+# ----
+# Test fixtures and helper functions
+# ----
+
+@pytest.fixture(autouse=True)
+def log_all_methods(request):
+    '''
+    This fixture logs messages before and after each test function runs, indicating the start and end of the test.
+    The autouse=True parameter ensures that this logging happens automatically for all tests in the module.
+    '''
+    logger.info(f" >>>>> Starting test: {request.node.name} ")
+    yield
+    logger.info(f" <<<<< Finished test: {request.node.name} ")
+
+@pytest.fixture
+def mock_kafka_producer():
+    mock_producer         = MagicMock()
+    mock_producer.produce = MagicMock()
+    mock_producer.flush   = MagicMock()
+    return mock_producer
+
+@pytest.fixture
+def mock_dask_cluster():
+    mock_cluster       = MagicMock()
+    mock_cluster.close = MagicMock()
+    return mock_cluster
+
+@pytest.fixture
+def mock_dask_client():
+    mock_client        = MagicMock()
+    mock_client.status = 'running'
+    mock_client.submit = MagicMock()
+    return mock_client
+
+@pytest.fixture()
+def mock_kafka_consumer():
+    mock_consumer           = MagicMock()
+    mock_consumer.subscribe = MagicMock()
+    return mock_consumer
+
+@pytest.fixture()
+def mock_streamer_start():
+    mock_streamer = MagicMock()
+    mock_streamer.start = MagicMock()
+    return mock_streamer
 
 ###########################
-# Tests Implementation of Telemetry Backend
+# funtionality pytest cases with specific fixtures for AnalyticsBackendService class sub-methods
 ###########################
 
-# --- "test_validate_kafka_topics" should be run before the functionality tests ---
-def test_validate_kafka_topics():
-    LOGGER.debug(" >>> test_validate_kafka_topics: START <<< ")
-    response = KafkaTopic.create_all_topics()
-    assert isinstance(response, bool)
-
-
-# --- To test Dask Streamer functionality ---
-# def test_StartDaskStreamer():   # Directly from the Streamer class
-#     LOGGER.debug(" >>> test_StartSparkStreamer: START <<< ")
-#     stop_event = Event()
-#     kpi_list = ["1e22f180-ba28-4641-b190-2287bf446666", "6e22f180-ba28-4641-b190-2287bf448888", 'kpi_3']
-#     oper_list = ['avg', 'min', 'max',]
-#     thresholds = {
-#         'avg_value': (10.0, 90.0),
-#         'min_value': (5.0, 95.0),
-#         'max_value': (15.0, 85.0),
-#         'latency'  : (2.0, 10.0)
-#     }
-
-#     # Start the DaskStreamer in a separate thread
-#     streamer_thread = Thread(
-#         target=DaskStreamer,
-#         args=("analytics_stream", kpi_list, oper_list, thresholds, stop_event),
-#         kwargs={
-#             "window_size": "60s",
-#             "win_slide_duration": "30s",
-#             "time_stamp_col": "time_stamp"
-#         }
-#     )
-#     streamer_thread.start()
-#     try:
-#         while True:
-#             time.sleep(10)
-#     except KeyboardInterrupt:
-#         LOGGER.info("KeyboardInterrupt received. Stopping streamer...")
-#         stop_event.set()
-#         streamer_thread.join()
-#         LOGGER.info("Streamer stopped gracefully.")
-
-# --- To test Start Streamer functionality ---
-# def test_StartDaskStreamer():
-#     LOGGER.debug(" >>> test_StartBaskStreamer: START <<< ")
-#     analyzer_obj = create_analyzer_dask()
-#     # LOGGER.info("Created Analyzer Object: {:}".format(analyzer_obj))
-#     analyzer_uuid = analyzer_obj.analyzer_id.analyzer_id.uuid
-#     analyzer_to_generate : Dict = {
-#         "algo_name"       : analyzer_obj.algorithm_name,
-#         "input_kpis"      : [k.kpi_id.uuid for k in analyzer_obj.input_kpi_ids],
-#         "output_kpis"     : [k.kpi_id.uuid for k in analyzer_obj.output_kpi_ids],
-#         "oper_mode"       : analyzer_obj.operation_mode,
-#         "thresholds"      : json.loads(analyzer_obj.parameters["thresholds"]),
-#         "oper_list"       : json.loads(analyzer_obj.parameters["oper_list"]),
-#         # "oper_list"       : analyzer_obj.parameters["oper_list"],
-#         "window_size"     : analyzer_obj.parameters["window_size"],
-#         "window_slider"   : analyzer_obj.parameters["window_slider"],
-#         # "store_aggregate" : analyzer_obj.parameters["store_aggregate"] 
-#     }
-#     AnalyticsBackendServiceObj = AnalyticsBackendService()
-#     LOGGER.info("Analyzer to be generated: {:}".format((analyzer_to_generate)))
-#     response = AnalyticsBackendServiceObj.StartDaskListener(analyzer_uuid, analyzer_to_generate)
-#     assert isinstance(response, bool)
-#     time.sleep(100)
-#     LOGGER.info('Initiating StopRequestListener...')
-#     # AnalyticsBackendServiceObj = AnalyticsBackendService()
-#     response = AnalyticsBackendServiceObj.StopDaskListener(analyzer_uuid)
-#     LOGGER.debug(str(response)) 
-#     assert isinstance(response, bool)
+@pytest.fixture
+def analytics_service(mock_kafka_producer, mock_dask_cluster, mock_dask_client, mock_kafka_consumer, mock_streamer_start):
+    with patch('analytics.backend.service.AnalyzerHelper.AnalyzerHelper.initialize_kafka_producer', return_value = mock_kafka_producer), \
+         patch('analytics.backend.service.AnalyzerHelper.AnalyzerHelper.initialize_dask_cluster',   return_value = mock_dask_cluster  ), \
+         patch('analytics.backend.service.AnalyzerHelper.AnalyzerHelper.initialize_dask_client',    return_value = mock_dask_client   ), \
+         patch('analytics.backend.service.AnalyzerHelper.AnalyzerHelper.initialize_kafka_consumer', return_value = mock_kafka_consumer), \
+         patch('analytics.backend.service.Streamer.DaskStreamer.run',                               return_value = mock_streamer_start):
+         
+        service = AnalyticsBackendService()
+        yield service
+        service.close()
 
-# --- To test Start Streamer functionality ---
-# def test_StartSparkStreamer():
-#     LOGGER.debug(" >>> test_StartSparkStreamer: START <<< ")
-#     analyzer_obj = create_analyzer()
-#     analyzer_uuid = analyzer_obj.analyzer_id.analyzer_id.uuid
-#     analyzer_to_generate : Dict = {
-#         "algo_name"       : analyzer_obj.algorithm_name,
-#         "input_kpis"      : [k.kpi_id.uuid for k in analyzer_obj.input_kpi_ids],
-#         "output_kpis"     : [k.kpi_id.uuid for k in analyzer_obj.output_kpi_ids],
-#         "oper_mode"       : analyzer_obj.operation_mode,
-#         "thresholds"      : json.loads(analyzer_obj.parameters["thresholds"]),
-#         "window_size"     : analyzer_obj.parameters["window_size"],
-#         "window_slider"   : analyzer_obj.parameters["window_slider"],
-#         # "store_aggregate" : analyzer_obj.parameters["store_aggregate"] 
-#     }
-#     AnalyticsBackendServiceObj = AnalyticsBackendService()
-#     response = AnalyticsBackendServiceObj.StartSparkStreamer(analyzer_uuid, analyzer_to_generate)
-#     assert isinstance(response, bool)
+@pytest.fixture
+def analyzer_data():
+    return {
+        'algo_name'          : 'test_algorithm',
+        'oper_mode'          : 'test_mode',
+        'input_kpis'         : get_input_kpi_list(),
+        'output_kpis'        : get_output_kpi_list(),
+        'thresholds'         : get_thresholds(),
+        'duration'           : get_duration(),
+        'batch_size_min'     : get_batch_size(),
+        'window_size'        : get_windows_size(),
+        'batch_duration_min' : get_duration(),
+    }
 
-# --- To TEST StartRequestListenerFunctionality
-# def test_StartRequestListener():
-#     LOGGER.info('test_RunRequestListener')
-#     AnalyticsBackendServiceObj = AnalyticsBackendService()
-#     AnalyticsBackendServiceObj.stop_event = Event()
-#     listener_thread = Thread(target=AnalyticsBackendServiceObj.RequestListener, args=())
-#     listener_thread.start()
-
-#     time.sleep(100)
-
-    # AnalyticsBackendServiceObj.stop_event.set()
-    # LOGGER.info('Backend termination initiated. waiting for termination... 10 seconds')
-    # listener_thread.join(timeout=10)
-    # assert not listener_thread.is_alive(), "RequestListener thread did not terminate as expected."
-    # LOGGER.info('Completed test_RunRequestListener')
-
-# To test START and STOP communication together
-# def test_StopRequestListener():
-#     LOGGER.info('test_RunRequestListener')
-#     LOGGER.info('Initiating StartRequestListener...')
-#     AnalyticsBackendServiceObj = AnalyticsBackendService()
-#     response_thread = AnalyticsBackendServiceObj.StartRequestListener() # response is Tuple (thread, stop_event)
-#     # LOGGER.debug(str(response_thread))
-#     time.sleep(10)
-#     LOGGER.info('Initiating StopRequestListener...')
-#     AnalyticsBackendServiceObj = AnalyticsBackendService()
-#     response = AnalyticsBackendServiceObj.StopRequestListener(response_thread)
-#     LOGGER.debug(str(response)) 
-#     assert isinstance(response, bool)
+def test_start_streamer(analytics_service, analyzer_data):
+    analyzer_uuid = "test-analyzer-uuid"
+    # Start streamer
+    result = analytics_service.StartStreamer(analyzer_uuid, analyzer_data)
+    assert result is True
+    assert analyzer_uuid in analytics_service.active_streamers
+
+def test_stop_streamer(analytics_service, analyzer_data):
+    analyzer_uuid = "test-analyzer-uuid"
+
+    # Start streamer for stopping it later
+    analytics_service.StartStreamer(analyzer_uuid, analyzer_data)
+    assert analyzer_uuid in analytics_service.active_streamers
+
+    # Stop streamer
+    with patch('time.sleep', return_value=None):
+        result = analytics_service.StopStreamer(analyzer_uuid)
+    assert result is True
+    assert analyzer_uuid not in analytics_service.active_streamers
+
+    # Verify that the streamer was stopped
+    assert analyzer_uuid not in analytics_service.active_streamers
+
+def test_close(analytics_service, mock_kafka_producer, mock_dask_cluster):
+    analytics_service.close()
+
+    mock_kafka_producer.flush.assert_called_once()
+    mock_dask_cluster.close.assert_called_once()
+
+###########################
+# funtionality pytest with specific fixtures for streamer class sub methods
+###########################
+
+@pytest.fixture
+def dask_streamer(mock_kafka_producer, mock_dask_cluster, mock_dask_client, mock_kafka_consumer):
+    with patch('analytics.backend.service.AnalyzerHelper.AnalyzerHelper.initialize_kafka_producer', return_value = mock_kafka_producer), \
+         patch('analytics.backend.service.AnalyzerHelper.AnalyzerHelper.initialize_dask_cluster',   return_value = mock_dask_cluster  ), \
+         patch('analytics.backend.service.AnalyzerHelper.AnalyzerHelper.initialize_dask_client',    return_value = mock_dask_client   ), \
+         patch('analytics.backend.service.AnalyzerHelper.AnalyzerHelper.initialize_kafka_consumer', return_value = mock_kafka_consumer):
+        
+        return DaskStreamer(
+            key               = "test_key",
+            input_kpis        = get_input_kpi_list(),
+            output_kpis       = get_output_kpi_list(),
+            thresholds        = get_thresholds(),
+            batch_size        = get_batch_size(),
+            window_size       = get_windows_size(),
+            cluster_instance  = mock_dask_cluster(),
+            producer_instance = mock_kafka_producer(),
+        )
+
+def test_dask_streamer_initialization(dask_streamer):
+    """Test if the DaskStreamer initializes correctly."""
+    assert dask_streamer.key         == "test_key"
+    assert dask_streamer.batch_size  == get_batch_size()
+    assert dask_streamer.window_size is None
+    assert dask_streamer.consumer    is not None
+    assert dask_streamer.producer    is not None
+    assert dask_streamer.client      is not None
+
+def test_run_stops_on_no_consumer(dask_streamer):
+    """Test if the run method exits when the consumer is not initialized."""
+    dask_streamer.consumer = None
+    with patch('time.sleep', return_value=None):
+        dask_streamer.run()
 
-# To independently tests the SparkListener functionality
-# def test_SparkListener():
-#     LOGGER.info('test_RunRequestListener')
-#     AnalyticsBackendServiceObj = AnalyticsBackendService()
-#     response = AnalyticsBackendServiceObj.RunSparkStreamer(
-#         get_kpi_id_list(), get_operation_list(), get_threshold_dict()
-#         )
-#     LOGGER.debug(str(response))
+    assert not dask_streamer.running
+
+def test_task_handler_selector_valid_handler(dask_streamer, mock_dask_client):
+    """Test task handler selection with a valid handler."""
+    with patch('analytics.backend.service.AnalyzerHelper.AnalyzerHelper.initialize_dask_client', return_value = mock_dask_client):
+
+        dask_streamer.task_handler_selector()
+        assert dask_streamer.client.status == 'running'
+
+def test_task_handler_selector_invalid_handler(dask_streamer):
+    """Test task handler selection with an invalid handler."""
+    with patch('analytics.backend.service.AnalyzerHandlers.Handlers.is_valid_handler', return_value=False):
+        dask_streamer.task_handler_selector()
+        assert dask_streamer.batch == []
+
+def test_produce_result(dask_streamer):
+    """Test if produce_result sends records to Kafka."""
+    result = [{"kpi_id": "kpi1", "value": 100}]
+    with patch('analytics.backend.service.AnalyzerHelper.AnalyzerHelper.delivery_report', return_value=None) as mock_delivery_report, \
+         patch.object(dask_streamer.producer, 'produce') as mock_produce:
+        dask_streamer.produce_result(result, "test_topic")
+        mock_produce.assert_called_once_with(
+            "test_topic",
+            key="kpi1",
+            value=json.dumps({"kpi_id": "kpi1", "value": 100}),
+            callback=mock_delivery_report
+        )
+
+def test_stop(dask_streamer):
+    """Test the cleanup method."""
+    with patch.object(dask_streamer.consumer, 'close') as mock_consumer_close, \
+         patch.object(dask_streamer.client,   'close') as mock_client_close, \
+         patch('time.sleep', return_value=0):
+        
+        # Mock the conditions required for the close calls
+        dask_streamer.client.status = 'running'
+        
+        dask_streamer.stop()
+
+        mock_consumer_close.assert_called_once()
+        mock_client_close.assert_called_once()
+
+def test_run_with_valid_consumer(dask_streamer):
+    """Test the run method with a valid Kafka consumer."""
+    with patch.object(dask_streamer.consumer, 'poll')         as mock_poll, \
+         patch.object(dask_streamer, 'task_handler_selector') as mock_task_handler_selector:
+        
+        # Simulate valid messages without errors
+        mock_message_1 = MagicMock()
+        mock_message_1.value.return_value = b'{"kpi_id": "kpi1", "value": 100}'
+        mock_message_1.error.return_value = None  # No error
+
+        mock_message_2 = MagicMock()
+        mock_message_2.value.return_value = b'{"kpi_id": "kpi2", "value": 200}'
+        mock_message_2.error.return_value = None  # No error
+
+        # Mock `poll` to return valid messages
+        mock_poll.side_effect = [mock_message_1, mock_message_2]
+        
+        # Run the `run` method in a limited loop
+        with patch('time.sleep', return_value=None):  # Mock `sleep` to avoid delays
+            dask_streamer.running = True            
+            dask_streamer.batch_size = 2            
+            
+            # Limit the loop by breaking it after one full processing cycle
+            def stop_running_after_task_handler():
+                logger.info("Stopping the streamer after processing the first batch.")
+                dask_streamer.running = False
+            
+            mock_task_handler_selector.side_effect = stop_running_after_task_handler
+            dask_streamer.run()
+        
+        assert len(dask_streamer.batch) == 0  # Batch should be cleared after processing
+        mock_task_handler_selector.assert_called_once()  # Task handler should be called once
+        mock_poll.assert_any_call(timeout=1.0)  # Poll should have been called at least once
+
+# # add a test to check the working of aggregation_handler function and threshold_handler from AnalyzerHandlers.py
+def test_aggregation_handler():
+
+    # Create a sample batch
+    batch           = get_batch()
+    input_kpi_list  = get_input_kpi_list()
+    output_kpi_list = get_output_kpi_list()
+    thresholds      = get_thresholds() 
+
+    # Test aggregation_handler
+    aggregated_df = aggregation_handler(
+        "test_batch", "test_key", batch, input_kpi_list, output_kpi_list, thresholds
+    )
+    assert isinstance(aggregated_df, list)
+    assert all(isinstance(item, dict) for item in aggregated_df)
+
+# # Test threshold_handler
+def test_threshold_handler():
+    # Create a sample aggregated DataFrame
+    agg_df     = get_agg_df()
+    thresholds = get_thresholds()
+
+    # Test threshold_handler
+    result = threshold_handler("test_key", agg_df, thresholds["task_parameter"][0])
+
+    assert isinstance(result, pd.DataFrame)
+    assert result.shape == (1, 7)
+
+
+###########################
+# integration test of Streamer with backend service (Shouldn't be run in the CI/CD pipeline)
+###########################
+# This is a local machine test to check the integration of the backend service with the Streamer
+
+# @pytest.fixture(scope='session')
+# def analyticBackend_service():
+#     logger.info('Initializing AnalyticsBackendService...')
+
+#     _service = AnalyticsBackendService()
+#     _service.start()
+
+#     logger.info('Yielding AnalyticsBackendService...')
+#     yield _service
+
+#     logger.info('Terminating AnalyticsBackendService...')
+#     _service.stop()
+#     logger.info('Terminated AnalyticsBackendService...')
+
+
+# # --- "test_validate_kafka_topics" should be run before the functionality tests ---
+# def test_validate_kafka_topics():
+#     logger.debug(" >>> test_validate_kafka_topics: START <<< ")
+#     response = KafkaTopic.create_all_topics()
 #     assert isinstance(response, bool)
+
+# def test_backend_integration_with_frontend(analyticBackend_service: AnalyticsBackendService):
+#     # backendServiceObject = AnalyticsBackendService()
+#     # backendServiceObject.install_servicers()
+#     logger.info(" waiting for 2 minutes for the backend service before termination  ... ")
+#     time.sleep(300)
+#     logger.info(" Initiating stop collector ... ")
+#     status = analyticBackend_service.StopStreamer("efef4d95-1cf1-43c4-9742-95c283ddd666")
+#     analyticBackend_service.close()
+#     assert isinstance(status, bool)
+#     assert status == True
+#     logger.info(" Backend service terminated successfully ... ")
diff --git a/src/analytics/frontend/service/AnalyticsFrontendServiceServicerImpl.py b/src/analytics/frontend/service/AnalyticsFrontendServiceServicerImpl.py
index fd5bcd185b1f9945eccf583c33af2a243fe729be..cd20503e7dbe1059b2209e4b0ccd29a229e7916e 100644
--- a/src/analytics/frontend/service/AnalyticsFrontendServiceServicerImpl.py
+++ b/src/analytics/frontend/service/AnalyticsFrontendServiceServicerImpl.py
@@ -46,7 +46,7 @@ class AnalyticsFrontendServiceServicerImpl(AnalyticsFrontendServiceServicer):
 
     @safe_and_metered_rpc_method(METRICS_POOL, LOGGER)
     def StartAnalyzer(self, 
-                       request : Analyzer, grpc_context: grpc.ServicerContext # type: ignore
+                       request : Analyzer, context: grpc.ServicerContext # type: ignore
                       ) -> AnalyzerId: # type: ignore
         LOGGER.info ("At Service gRPC message: {:}".format(request))
         response = AnalyzerId()
@@ -65,14 +65,18 @@ class AnalyticsFrontendServiceServicerImpl(AnalyticsFrontendServiceServicer):
         """
         analyzer_uuid = analyzer_obj.analyzer_id.analyzer_id.uuid
         analyzer_to_generate : Dict = {
-            "algo_name"       : analyzer_obj.algorithm_name,
-            "input_kpis"      : [k.kpi_id.uuid for k in analyzer_obj.input_kpi_ids],
-            "output_kpis"     : [k.kpi_id.uuid for k in analyzer_obj.output_kpi_ids],
-            "oper_mode"       : analyzer_obj.operation_mode,
-            "thresholds"      : json.loads(analyzer_obj.parameters["thresholds"]),
-            "window_size"     : analyzer_obj.parameters["window_size"],
-            "window_slider"   : analyzer_obj.parameters["window_slider"],
-            # "store_aggregate" : analyzer_obj.parameters["store_aggregate"] 
+            "algo_name"           : analyzer_obj.algorithm_name,
+            "input_kpis"          : [k.kpi_id.uuid for k in analyzer_obj.input_kpi_ids],
+            "output_kpis"         : [k.kpi_id.uuid for k in analyzer_obj.output_kpi_ids],
+            "oper_mode"           : analyzer_obj.operation_mode,
+            "duration"            : analyzer_obj.duration_s,
+            "thresholds"          : json.loads(analyzer_obj.parameters["thresholds"]),
+            "window_size"         : analyzer_obj.parameters["window_size"],     # slider window size in seconds (single batch execution time)
+            "window_slider"       : analyzer_obj.parameters["window_slider"],   # slider shift in seconds
+            "batch_size_min"      : analyzer_obj.batch_min_size,                # currently implemented
+            "batch_size_max"      : analyzer_obj.batch_max_size,
+            "batch_duration_min"  : analyzer_obj.batch_min_duration_s,          # currently implemented
+            "batch_interval_max"  : analyzer_obj.batch_max_duration_s
         }
         self.kafka_producer.produce(
             KafkaTopic.ANALYTICS_REQUEST.value,
@@ -137,7 +141,7 @@ class AnalyticsFrontendServiceServicerImpl(AnalyticsFrontendServiceServicer):
 
     @safe_and_metered_rpc_method(METRICS_POOL, LOGGER)
     def StopAnalyzer(self, 
-                      request : AnalyzerId, grpc_context: grpc.ServicerContext # type: ignore
+                      request : AnalyzerId, context: grpc.ServicerContext # type: ignore
                      ) -> Empty:  # type: ignore
         LOGGER.info ("At Service gRPC message: {:}".format(request))
         try:
@@ -181,7 +185,7 @@ class AnalyticsFrontendServiceServicerImpl(AnalyticsFrontendServiceServicer):
 
     @safe_and_metered_rpc_method(METRICS_POOL, LOGGER)
     def SelectAnalyzers(self, 
-                         filter : AnalyzerFilter, contextgrpc_context: grpc.ServicerContext # type: ignore
+                         filter : AnalyzerFilter, context: grpc.ServicerContext # type: ignore
                         ) -> AnalyzerList:  # type: ignore
         LOGGER.info("At Service gRPC message: {:}".format(filter))
         response = AnalyzerList()
@@ -202,7 +206,5 @@ class AnalyticsFrontendServiceServicerImpl(AnalyticsFrontendServiceServicer):
     def delivery_callback(self, err, msg):
         if err:
             LOGGER.debug('Message delivery failed: {:}'.format(err))
-            # print       ('Message delivery failed: {:}'.format(err))
         else:
             LOGGER.debug('Message delivered to topic {:}'.format(msg.topic()))
-            # print('Message delivered to topic {:}'.format(msg.topic()))
diff --git a/src/analytics/frontend/tests/messages.py b/src/analytics/frontend/tests/messages.py
index 4df6070bedffd91402953bbbbbec16ce0118008c..326bc0be22c0d0e01ccdd79b439b82a88d06e0ad 100644
--- a/src/analytics/frontend/tests/messages.py
+++ b/src/analytics/frontend/tests/messages.py
@@ -20,43 +20,77 @@ from common.proto.analytics_frontend_pb2 import ( AnalyzerOperationMode, Analyze
 
 def create_analyzer_id():
     _create_analyzer_id                  = AnalyzerId()
-    # _create_analyzer_id.analyzer_id.uuid = str(uuid.uuid4())
+    _create_analyzer_id.analyzer_id.uuid = str(uuid.uuid4())
     # _create_analyzer_id.analyzer_id.uuid = "efef4d95-1cf1-43c4-9742-95c283ddd7a6"
-    _create_analyzer_id.analyzer_id.uuid = "1e22f180-ba28-4641-b190-2287bf446666"
+    # _create_analyzer_id.analyzer_id.uuid = "1e22f180-ba28-4641-b190-2287bf446666"
     return _create_analyzer_id
 
 def create_analyzer():
     _create_analyzer                              = Analyzer()
-    # _create_analyzer.analyzer_id.analyzer_id.uuid = str(uuid.uuid4())
-    _create_analyzer.analyzer_id.analyzer_id.uuid = "1e22f180-ba28-4641-b190-2287bf446666"
-    _create_analyzer.algorithm_name               = "Test_Aggergate_and_Threshold"
+
+    _create_analyzer.analyzer_id.analyzer_id.uuid = str(uuid.uuid4())
+    # _create_analyzer.analyzer_id.analyzer_id.uuid = "1e22f180-ba28-4641-b190-2287bf446666"
+    _create_analyzer.algorithm_name               = "Test_new_Threshold"
     _create_analyzer.operation_mode               = AnalyzerOperationMode.ANALYZEROPERATIONMODE_STREAMING
     
-    _kpi_id = KpiId()
     # input IDs to analyze
-    _kpi_id.kpi_id.uuid              = str(uuid.uuid4())
+    _kpi_id = KpiId()
+
+    # _kpi_id.kpi_id.uuid              = str(uuid.uuid4())
     _kpi_id.kpi_id.uuid              = "6e22f180-ba28-4641-b190-2287bf448888"
     _create_analyzer.input_kpi_ids.append(_kpi_id)
-    _kpi_id.kpi_id.uuid              = str(uuid.uuid4())
+
+    # _kpi_id.kpi_id.uuid              = str(uuid.uuid4())
     _kpi_id.kpi_id.uuid              = "1e22f180-ba28-4641-b190-2287bf446666"
     _create_analyzer.input_kpi_ids.append(_kpi_id)
+
     _kpi_id.kpi_id.uuid              = str(uuid.uuid4())
     _create_analyzer.input_kpi_ids.append(_kpi_id)
+    
     # output IDs after analysis
-    _kpi_id.kpi_id.uuid              = str(uuid.uuid4())
+    _kpi_id = KpiId()
+
+    # _kpi_id.kpi_id.uuid              = str(uuid.uuid4())
+    _kpi_id.kpi_id.uuid              = "6e22f180-ba28-4641-b190-2287bf181818"
+    _create_analyzer.output_kpi_ids.append(_kpi_id)
+
+    # _kpi_id.kpi_id.uuid              = str(uuid.uuid4())
+    _kpi_id.kpi_id.uuid              = "1e22f180-ba28-4641-b190-2287bf441616"
     _create_analyzer.output_kpi_ids.append(_kpi_id)
+
     _kpi_id.kpi_id.uuid              = str(uuid.uuid4())
     _create_analyzer.output_kpi_ids.append(_kpi_id)
+
     # parameter
+    # _threshold_dict = {
+    #     'mean_value'  :[20, 30], 'min_value'   :[00, 10], 'max_value' :[45, 50],
+    #     'first_value' :[00, 10], 'last_value'  :[40, 50], 'std_value' :[00, 10]
+    #     }
     _threshold_dict = {
-        'mean_value'   :(20, 30), 'min_value'   :(00, 10), 'max_value'   :(45, 50),
-        'first_value' :(00, 10), 'last_value'  :(40, 50), 'std_value':(00, 10)
-        }
+        "task_type": Handlers.AGGREGATION_HANDLER.value,
+        "task_parameter": [
+            {"last":  [40, 80], "variance": [300, 500]},
+            {"count": [2,  4],  "max":      [70,  100]},
+            {"min":   [10, 20], "avg":      [50,  70]},
+        ],
+    }
+
     _create_analyzer.parameters['thresholds']      = json.dumps(_threshold_dict)
-    _create_analyzer.parameters['window_size']     = "10s"            # Such as "10 seconds", "2 minutes", "3 hours", "4 days" or "5 weeks" 
-    _create_analyzer.parameters['window_slider']   = "5s"             # should be less than window size
-    _create_analyzer.parameters['store_aggregate'] = str(False)       # TRUE to store. No implemented yet
+    _create_analyzer.parameters['window_size']     = "0"   #   slider window size in seconds (Total time for aggeration processing) 
+    _create_analyzer.parameters['window_slider']   = "0"    #   should be less than window size
+    _create_analyzer.parameters['store_aggregate'] = str(False)  #   TRUE to store. No implemented yet
 
+    # duration of the analyzer
+    _create_analyzer.duration_s = 90
+
+    # batch window size
+    _create_analyzer.batch_min_duration_s = 20
+    _create_analyzer.batch_max_duration_s = 50
+
+    # batch size
+    _create_analyzer.batch_min_size       = 5
+    _create_analyzer.batch_max_size       = 10
+    
     return _create_analyzer
 
 def create_analyzer_filter():
@@ -84,3 +118,10 @@ def create_analyzer_filter():
     # _create_analyzer_filter.input_kpi_ids.append(_output_kpi_id_obj)
 
     return _create_analyzer_filter
+
+
+# Added for testing to remove the dependency on the backend service
+from enum import Enum
+class Handlers(Enum):
+    AGGREGATION_HANDLER = "AggregationHandler"
+    UNSUPPORTED_HANDLER = "UnsupportedHandler"
diff --git a/src/analytics/frontend/tests/test_frontend.py b/src/analytics/frontend/tests/test_frontend.py
index 134871fb77719e4747b6fc3ae6cfd21dd317a31f..7d8a08d3ad2d82758b088a8f83342c2b3929eadd 100644
--- a/src/analytics/frontend/tests/test_frontend.py
+++ b/src/analytics/frontend/tests/test_frontend.py
@@ -78,6 +78,15 @@ def analyticsFrontend_client(analyticsFrontend_service : AnalyticsFrontendServic
 
     LOGGER.info('Closed AnalyticsFrontendClient...')
 
+@pytest.fixture(autouse=True)
+def log_all_methods(request):
+    '''
+    This fixture logs messages before and after each test function runs, indicating the start and end of the test.
+    The autouse=True parameter ensures that this logging happens automatically for all tests in the module.
+    '''
+    LOGGER.info(f" >>>>> Starting test: {request.node.name} ")
+    yield
+    LOGGER.info(f" <<<<< Finished test: {request.node.name} ")
 
 ###########################
 # Tests Implementation of Analytics Frontend
@@ -89,24 +98,17 @@ def test_validate_kafka_topics():
     response = KafkaTopic.create_all_topics()
     assert isinstance(response, bool)
 
-# ----- core funtionality test -----
-# def test_StartAnalytics(analyticsFrontend_client):
-#     LOGGER.info(' >>> test_StartAnalytic START: <<< ')
-#     response = analyticsFrontend_client.StartAnalyzer(create_analyzer())
-#     LOGGER.debug(str(response))
-#     assert isinstance(response, AnalyzerId)
-
 # To test start and stop listener together
 def test_StartAnalyzers(analyticsFrontend_client):
     LOGGER.info(' >>> test_StartAnalyzers START: <<< ')
     added_analyzer_id = analyticsFrontend_client.StartAnalyzer(create_analyzer())
     LOGGER.debug(str(added_analyzer_id))
-    LOGGER.info(' --> Calling StartResponseListener... ')
-    class_obj = AnalyticsFrontendServiceServicerImpl()
-    response =  class_obj.StartResponseListener(added_analyzer_id.analyzer_id.uuid)
-    LOGGER.debug(response)
-    LOGGER.info("waiting for timer to comlete ...")
-    time.sleep(3)
+    # LOGGER.info(' --> Calling StartResponseListener... ')
+    # class_obj = AnalyticsFrontendServiceServicerImpl()
+    # response  =  class_obj.StartResponseListener(added_analyzer_id.analyzer_id.uuid)
+    # LOGGER.debug(response)
+    LOGGER.info("waiting for timer to complete ...")
+    time.sleep(15)
     LOGGER.info('--> StopAnalyzer')
     response = analyticsFrontend_client.StopAnalyzer(added_analyzer_id)
     LOGGER.debug(str(response))
diff --git a/src/common/tools/context_queries/Slice.py b/src/common/tools/context_queries/Slice.py
index c826c59ce79adbe1e399d674ffd46a421ddd9b5e..686f08a845df5c99fdd0cace393290419d92922c 100644
--- a/src/common/tools/context_queries/Slice.py
+++ b/src/common/tools/context_queries/Slice.py
@@ -12,12 +12,20 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import grpc, logging
-from typing import Optional
+import logging
+from typing import Optional, Tuple, Union
+from uuid import UUID, uuid5
+
+import grpc
+
 from common.Constants import DEFAULT_CONTEXT_NAME
-from common.proto.context_pb2 import Slice, SliceFilter, SliceId
+from common.method_wrappers.ServiceExceptions import InvalidArgumentsException
+from common.proto.context_pb2 import ContextId, Slice, SliceFilter, SliceId
 from context.client.ContextClient import ContextClient
 
+
+NAMESPACE_TFS = UUID("200e3a1f-2223-534f-a100-758e29c37f40")
+
 LOGGER = logging.getLogger(__name__)
 
 def get_slice_by_id(
@@ -59,3 +67,96 @@ def get_slice_by_uuid(
         context_client, slice_id, rw_copy=rw_copy, include_endpoint_ids=include_endpoint_ids,
         include_constraints=include_constraints, include_service_ids=include_service_ids,
         include_subslice_ids=include_subslice_ids, include_config_rules=include_config_rules)
+
+
+def get_uuid_from_string(
+    str_uuid_or_name: Union[str, UUID], prefix_for_name: Optional[str] = None
+) -> str:
+    # if UUID given, assume it is already a valid UUID
+    if isinstance(str_uuid_or_name, UUID):
+        return str_uuid_or_name
+    if not isinstance(str_uuid_or_name, str):
+        MSG = "Parameter({:s}) cannot be used to produce a UUID"
+        raise Exception(MSG.format(str(repr(str_uuid_or_name))))
+    try:
+        # try to parse as UUID
+        return str(UUID(str_uuid_or_name))
+    except:  # pylint: disable=bare-except
+        # produce a UUID within TFS namespace from parameter
+        if prefix_for_name is not None:
+            str_uuid_or_name = "{:s}/{:s}".format(prefix_for_name, str_uuid_or_name)
+        return str(uuid5(NAMESPACE_TFS, str_uuid_or_name))
+
+
+def context_get_uuid(
+    context_id: ContextId,
+    context_name: str = "",
+    allow_random: bool = False,
+    allow_default: bool = False,
+) -> str:
+    context_uuid = context_id.context_uuid.uuid
+
+    if len(context_uuid) > 0:
+        return get_uuid_from_string(context_uuid)
+    if len(context_name) > 0:
+        return get_uuid_from_string(context_name)
+    if allow_default:
+        return get_uuid_from_string(DEFAULT_CONTEXT_NAME)
+
+    raise InvalidArgumentsException(
+        [
+            ("context_id.context_uuid.uuid", context_uuid),
+            ("name", context_name),
+        ],
+        extra_details=["At least one is required to produce a Context UUID"],
+    )
+
+
+def slice_get_uuid(slice_id: SliceId) -> Tuple[str, str]:
+    context_uuid = context_get_uuid(slice_id.context_id, allow_random=False)
+    raw_slice_uuid = slice_id.slice_uuid.uuid
+
+    if len(raw_slice_uuid) > 0:
+        return context_uuid, get_uuid_from_string(
+            raw_slice_uuid, prefix_for_name=context_uuid
+        )
+
+    raise InvalidArgumentsException(
+        [
+            ("slice_id.slice_uuid.uuid", raw_slice_uuid),
+        ],
+        extra_details=["At least one is required to produce a Slice UUID"],
+    )
+
+def get_slice_by_defualt_id(
+    context_client : ContextClient, default_slice_id : SliceId, context_uuid : str = DEFAULT_CONTEXT_NAME,
+    rw_copy : bool = False, include_endpoint_ids : bool = True, include_constraints : bool = True,
+    include_service_ids : bool = True, include_subslice_ids : bool = True, include_config_rules : bool = True
+) -> Optional[Slice]:
+    context_uuid, slice_uuid = slice_get_uuid(default_slice_id)
+    LOGGER.debug(f'P60: {context_uuid} {slice_uuid}')
+    slice_id = SliceId()
+    slice_id.context_id.context_uuid.uuid = context_uuid    # pylint: disable=no-member
+    slice_id.slice_uuid.uuid = slice_uuid                   # pylint: disable=no-member
+    return get_slice_by_id(
+        context_client, slice_id, rw_copy=rw_copy, include_endpoint_ids=include_endpoint_ids,
+        include_constraints=include_constraints, include_service_ids=include_service_ids,
+        include_subslice_ids=include_subslice_ids, include_config_rules=include_config_rules)
+
+
+def get_slice_by_defualt_name(
+    context_client : ContextClient, slice_name : str, context_uuid : str = DEFAULT_CONTEXT_NAME,
+    rw_copy : bool = False, include_endpoint_ids : bool = True, include_constraints : bool = True,
+    include_service_ids : bool = True, include_subslice_ids : bool = True, include_config_rules : bool = True
+) -> Optional[Slice]:
+    default_slice_id = SliceId()
+    default_slice_id.context_id.context_uuid.uuid = context_uuid    # pylint: disable=no-member
+    default_slice_id.slice_uuid.uuid = slice_name                   # pylint: disable=no-member
+    context_uuid, slice_uuid = slice_get_uuid(default_slice_id)
+    slice_id = SliceId()
+    slice_id.context_id.context_uuid.uuid = context_uuid    # pylint: disable=no-member
+    slice_id.slice_uuid.uuid = slice_uuid                   # pylint: disable=no-member
+    return get_slice_by_id(
+        context_client, slice_id, rw_copy=rw_copy, include_endpoint_ids=include_endpoint_ids,
+        include_constraints=include_constraints, include_service_ids=include_service_ids,
+        include_subslice_ids=include_subslice_ids, include_config_rules=include_config_rules)
diff --git a/src/common/tools/kafka/Variables.py b/src/common/tools/kafka/Variables.py
index 21e66af137302553663d6e0a6701368bda638017..5c7501b6c07e6aaa26569e2817fca374e6b0c12e 100644
--- a/src/common/tools/kafka/Variables.py
+++ b/src/common/tools/kafka/Variables.py
@@ -41,14 +41,14 @@ class KafkaConfig(Enum):
 
 class KafkaTopic(Enum):
     # TODO: Later to be populated from ENV variable.
-    REQUEST            = 'topic_request' 
-    RESPONSE           = 'topic_response'
+    TELEMETRY_REQUEST  = 'topic_telemetry_request' 
+    TELEMETRY_RESPONSE = 'topic_telemetry_response'
     RAW                = 'topic_raw' 
     LABELED            = 'topic_labeled'
     VALUE              = 'topic_value'
     ALARMS             = 'topic_alarms'
-    ANALYTICS_REQUEST  = 'topic_request_analytics'
-    ANALYTICS_RESPONSE = 'topic_response_analytics'
+    ANALYTICS_REQUEST  = 'topic_analytics_request'
+    ANALYTICS_RESPONSE = 'topic_analytics_response'
 
     @staticmethod
     def create_all_topics() -> bool:
diff --git a/src/device/service/drivers/__init__.py b/src/device/service/drivers/__init__.py
index b99ee50ca8319ab96f9062a3c58c356fa2ae7ec7..2e53cfa03ed4d3c5b4883edb939f6add79416f3f 100644
--- a/src/device/service/drivers/__init__.py
+++ b/src/device/service/drivers/__init__.py
@@ -81,6 +81,16 @@ DRIVERS.append(
         }
     ]))
 
+
+from .ietf_l3vpn.driver import IetfL3VpnDriver # pylint: disable=wrong-import-position
+DRIVERS.append(
+    (IetfL3VpnDriver, [
+        {
+            FilterFieldEnum.DEVICE_TYPE: DeviceTypeEnum.TERAFLOWSDN_CONTROLLER,
+            FilterFieldEnum.DRIVER: DeviceDriverEnum.DEVICEDRIVER_IETF_L3VPN,
+        }
+    ]))
+
 from .ietf_actn.IetfActnDriver import IetfActnDriver # pylint: disable=wrong-import-position
 DRIVERS.append(
     (IetfActnDriver, [
diff --git a/src/device/service/drivers/emulated/Tools.py b/src/device/service/drivers/emulated/Tools.py
index 9f2a105c0d9735f486f41fab5bc3069ec9327f65..2a6f9c95d351f447f7368584d0ad07889eaecd7c 100644
--- a/src/device/service/drivers/emulated/Tools.py
+++ b/src/device/service/drivers/emulated/Tools.py
@@ -82,6 +82,26 @@ def compose_resource_endpoint(endpoint_data : Dict[str, Any]) -> Optional[Tuple[
     
         if 'location' in endpoint_data:
             endpoint_resource_value['location'] = endpoint_data['location']
+
+        if "site_location" in endpoint_data:
+            endpoint_resource_value["site_location"] = endpoint_data["site_location"]
+
+        if "ce-ip" in endpoint_data:
+            endpoint_resource_value["ce-ip"] = endpoint_data["ce-ip"]
+
+        if "address_ip" in endpoint_data:
+            endpoint_resource_value["address_ip"] = endpoint_data["address_ip"]
+
+        if "address_prefix" in endpoint_data:
+            endpoint_resource_value["address_prefix"] = endpoint_data["address_prefix"]
+
+        if "mtu" in endpoint_data:
+            endpoint_resource_value["mtu"] = endpoint_data["mtu"]
+
+        if "ipv4_lan_prefixes" in endpoint_data:
+            endpoint_resource_value["ipv4_lan_prefixes"] = endpoint_data[
+                "ipv4_lan_prefixes"
+            ]
             
         return endpoint_resource_key, endpoint_resource_value
     except: # pylint: disable=bare-except
diff --git a/src/device/service/drivers/ietf_l3vpn/Constants.py b/src/device/service/drivers/ietf_l3vpn/Constants.py
new file mode 100644
index 0000000000000000000000000000000000000000..df66eb16b3d78c1b388a086011ed6f6b75b8099f
--- /dev/null
+++ b/src/device/service/drivers/ietf_l3vpn/Constants.py
@@ -0,0 +1,25 @@
+# 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 device.service.driver_api._Driver import (
+    RESOURCE_ENDPOINTS,
+    RESOURCE_INTERFACES,
+    RESOURCE_NETWORK_INSTANCES,
+)
+
+SPECIAL_RESOURCE_MAPPINGS = {
+    RESOURCE_ENDPOINTS: "/endpoints",
+    RESOURCE_INTERFACES: "/interfaces",
+    RESOURCE_NETWORK_INSTANCES: "/net-instances",
+}
diff --git a/src/device/service/drivers/ietf_l3vpn/TfsApiClient.py b/src/device/service/drivers/ietf_l3vpn/TfsApiClient.py
new file mode 100644
index 0000000000000000000000000000000000000000..1ca965f8777aa23287ad379c8ac2cd0d92d9c28f
--- /dev/null
+++ b/src/device/service/drivers/ietf_l3vpn/TfsApiClient.py
@@ -0,0 +1,187 @@
+# 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 logging
+from typing import Dict, List, Optional
+
+import requests
+from requests.auth import HTTPBasicAuth
+
+from device.service.driver_api.ImportTopologyEnum import ImportTopologyEnum
+
+GET_DEVICES_URL = "{:s}://{:s}:{:d}/tfs-api/devices"
+GET_LINKS_URL = "{:s}://{:s}:{:d}/tfs-api/links"
+L3VPN_URL = "{:s}://{:s}:{:d}/restconf/data/ietf-l3vpn-svc:l3vpn-svc/vpn-services"
+TIMEOUT = 30
+
+HTTP_OK_CODES = {
+    200,  # OK
+    201,  # Created
+    202,  # Accepted
+    204,  # No Content
+}
+
+MAPPING_STATUS = {
+    "DEVICEOPERATIONALSTATUS_UNDEFINED": 0,
+    "DEVICEOPERATIONALSTATUS_DISABLED": 1,
+    "DEVICEOPERATIONALSTATUS_ENABLED": 2,
+}
+
+MAPPING_DRIVER = {
+    "DEVICEDRIVER_UNDEFINED": 0,
+    "DEVICEDRIVER_OPENCONFIG": 1,
+    "DEVICEDRIVER_TRANSPORT_API": 2,
+    "DEVICEDRIVER_P4": 3,
+    "DEVICEDRIVER_IETF_NETWORK_TOPOLOGY": 4,
+    "DEVICEDRIVER_ONF_TR_532": 5,
+    "DEVICEDRIVER_XR": 6,
+    "DEVICEDRIVER_IETF_L2VPN": 7,
+    "DEVICEDRIVER_GNMI_OPENCONFIG": 8,
+    "DEVICEDRIVER_OPTICAL_TFS": 9,
+    "DEVICEDRIVER_IETF_ACTN": 10,
+    "DEVICEDRIVER_OC": 11,
+}
+
+MSG_ERROR = "Could not retrieve devices in remote TeraFlowSDN instance({:s}). status_code={:s} reply={:s}"
+
+LOGGER = logging.getLogger(__name__)
+
+
+class TfsApiClient:
+    def __init__(
+        self,
+        address: str,
+        port: int,
+        scheme: str = "http",
+        username: Optional[str] = None,
+        password: Optional[str] = None,
+    ) -> None:
+        self._devices_url = GET_DEVICES_URL.format(scheme, address, port)
+        self._links_url = GET_LINKS_URL.format(scheme, address, port)
+        self._l3vpn_url = L3VPN_URL.format(scheme, address, port)
+        self._auth = None
+        # (
+        #     HTTPBasicAuth(username, password)
+        #     if username is not None and password is not None
+        #     else None
+        # )
+
+    def get_devices_endpoints(
+        self, import_topology: ImportTopologyEnum = ImportTopologyEnum.DEVICES
+    ) -> List[Dict]:
+        LOGGER.debug("[get_devices_endpoints] begin")
+        LOGGER.debug(
+            "[get_devices_endpoints] import_topology={:s}".format(str(import_topology))
+        )
+
+        reply = requests.get(self._devices_url, timeout=TIMEOUT, auth=self._auth)
+        if reply.status_code not in HTTP_OK_CODES:
+            msg = MSG_ERROR.format(
+                str(self._devices_url), str(reply.status_code), str(reply)
+            )
+            LOGGER.error(msg)
+            raise Exception(msg)
+
+        if import_topology == ImportTopologyEnum.DISABLED:
+            raise Exception(
+                "Unsupported import_topology mode: {:s}".format(str(import_topology))
+            )
+
+        result = list()
+        for json_device in reply.json()["devices"]:
+            device_uuid: str = json_device["device_id"]["device_uuid"]["uuid"]
+            device_type: str = json_device["device_type"]
+            device_status = json_device["device_operational_status"]
+            device_url = "/devices/device[{:s}]".format(device_uuid)
+            device_data = {
+                "uuid": json_device["device_id"]["device_uuid"]["uuid"],
+                "name": json_device["name"],
+                "type": device_type,
+                "status": MAPPING_STATUS[device_status],
+                "drivers": [
+                    MAPPING_DRIVER[driver] for driver in json_device["device_drivers"]
+                ],
+            }
+            result.append((device_url, device_data))
+
+            for json_endpoint in json_device["device_endpoints"]:
+                endpoint_uuid = json_endpoint["endpoint_id"]["endpoint_uuid"]["uuid"]
+                endpoint_url = "/endpoints/endpoint[{:s}]".format(endpoint_uuid)
+                endpoint_data = {
+                    "device_uuid": device_uuid,
+                    "uuid": endpoint_uuid,
+                    "name": json_endpoint["name"],
+                    "type": json_endpoint["endpoint_type"],
+                }
+                result.append((endpoint_url, endpoint_data))
+
+        if import_topology == ImportTopologyEnum.DEVICES:
+            LOGGER.debug("[get_devices_endpoints] devices only; returning")
+            return result
+
+        reply = requests.get(self._links_url, timeout=TIMEOUT, auth=self._auth)
+        if reply.status_code not in HTTP_OK_CODES:
+            msg = MSG_ERROR.format(
+                str(self._links_url), str(reply.status_code), str(reply)
+            )
+            LOGGER.error(msg)
+            raise Exception(msg)
+
+        for json_link in reply.json()["links"]:
+            link_uuid: str = json_link["link_id"]["link_uuid"]["uuid"]
+            link_url = "/links/link[{:s}]".format(link_uuid)
+            link_endpoint_ids = [
+                (
+                    json_endpoint_id["device_id"]["device_uuid"]["uuid"],
+                    json_endpoint_id["endpoint_uuid"]["uuid"],
+                )
+                for json_endpoint_id in json_link["link_endpoint_ids"]
+            ]
+            link_data = {
+                "uuid": json_link["link_id"]["link_uuid"]["uuid"],
+                "name": json_link["name"],
+                "endpoints": link_endpoint_ids,
+            }
+            result.append((link_url, link_data))
+
+        LOGGER.debug("[get_devices_endpoints] topology; returning")
+        return result
+
+    def create_connectivity_service(self, l3vpn_data: dict) -> None:
+        try:
+            requests.post(self._l3vpn_url, json=l3vpn_data)
+            LOGGER.debug(
+                "[create_connectivity_service] l3vpn_data={:s}".format(str(l3vpn_data))
+            )
+        except requests.exceptions.ConnectionError:
+            raise Exception("faild to send post request to TFS L3VPN NBI")
+
+    def update_connectivity_service(self, l3vpn_data: dict) -> None:
+        vpn_id = l3vpn_data['ietf-l3vpn-svc:l3vpn-svc']["vpn-services"]["vpn-service"][0]["vpn-id"]
+        url = self._l3vpn_url + f"/vpn-service={vpn_id}"
+        try:
+            requests.put(url, json=l3vpn_data)
+            LOGGER.debug(
+                "[update_connectivity_service] l3vpn_data={:s}".format(str(l3vpn_data))
+            )
+        except requests.exceptions.ConnectionError:
+            raise Exception("faild to send post request to TFS L3VPN NBI")
+
+    def delete_connectivity_service(self, service_uuid: str) -> None:
+        url = self._l3vpn_url + f"/vpn-service={service_uuid}"
+        try:
+            requests.delete(url, auth=self._auth)
+            LOGGER.debug("[delete_connectivity_service] url={:s}".format(str(url)))
+        except requests.exceptions.ConnectionError:
+            raise Exception("faild to send delete request to TFS L3VPN NBI")
diff --git a/src/device/service/drivers/ietf_l3vpn/Tools.py b/src/device/service/drivers/ietf_l3vpn/Tools.py
new file mode 100644
index 0000000000000000000000000000000000000000..7caaa27a52cacf03d9822e933f0a6b74fd0e4db8
--- /dev/null
+++ b/src/device/service/drivers/ietf_l3vpn/Tools.py
@@ -0,0 +1,198 @@
+# 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 logging
+from typing import Any, Dict, Optional, Tuple, TypedDict
+
+import requests
+
+from common.proto.kpi_sample_types_pb2 import KpiSampleType
+from common.type_checkers.Checkers import chk_attribute, chk_string, chk_type
+from device.service.driver_api._Driver import RESOURCE_ENDPOINTS
+
+from .Constants import SPECIAL_RESOURCE_MAPPINGS
+
+
+class LANPrefixesDict(TypedDict):
+    lan: str
+    lan_tag: str
+
+
+LOGGER = logging.getLogger(__name__)
+
+SITE_NETWORK_ACCESS_TYPE = "ietf-l3vpn-svc:multipoint"
+
+
+def service_exists(wim_url: str, auth, service_uuid: str) -> bool:
+    try:
+        get_connectivity_service(wim_url, auth, service_uuid)
+        return True
+    except:  # pylint: disable=bare-except
+        return False
+
+
+def get_all_active_connectivity_services(wim_url: str, auth):
+    try:
+        LOGGER.info("Sending get all connectivity services")
+        servicepoint = f"{wim_url}/restconf/data/ietf-l3vpn-svc:l3vpn-svc/vpn-services"
+        response = requests.get(servicepoint, auth=auth)
+
+        if response.status_code != requests.codes.ok:
+            raise Exception(
+                "Unable to get all connectivity services",
+                http_code=response.status_code,
+            )
+
+        return response
+    except requests.exceptions.ConnectionError:
+        raise Exception("Request Timeout", http_code=408)
+
+
+def get_connectivity_service(wim_url, auth, service_uuid):
+    try:
+        LOGGER.info("Sending get connectivity service")
+        servicepoint = f"{wim_url}/restconf/data/ietf-l3vpn-svc:l3vpn-svc/vpn-services/vpn-service={service_uuid}"
+
+        response = requests.get(servicepoint)
+
+        if response.status_code != requests.codes.ok:
+            raise Exception(
+                "Unable to get connectivity service{:s}".format(str(service_uuid)),
+                http_code=response.status_code,
+            )
+
+        return response
+    except requests.exceptions.ConnectionError:
+        raise Exception("Request Timeout", http_code=408)
+
+
+def process_optional_string_field(
+    endpoint_data: Dict[str, Any],
+    field_name: str,
+    endpoint_resource_value: Dict[str, Any],
+) -> None:
+    field_value = chk_attribute(
+        field_name, endpoint_data, "endpoint_data", default=None
+    )
+    if field_value is None:
+        return
+    chk_string("endpoint_data.{:s}".format(field_name), field_value)
+    if len(field_value) > 0:
+        endpoint_resource_value[field_name] = field_value
+
+
+def compose_resource_endpoint(
+    endpoint_data: Dict[str, Any],
+) -> Optional[Tuple[str, Dict]]:
+    try:
+        # Check type of endpoint_data
+        chk_type("endpoint_data", endpoint_data, dict)
+
+        # Check endpoint UUID (mandatory)
+        endpoint_uuid = chk_attribute("uuid", endpoint_data, "endpoint_data")
+        chk_string("endpoint_data.uuid", endpoint_uuid, min_length=1)
+        endpoint_resource_path = SPECIAL_RESOURCE_MAPPINGS.get(RESOURCE_ENDPOINTS)
+        endpoint_resource_key = "{:s}/endpoint[{:s}]".format(
+            endpoint_resource_path, endpoint_uuid
+        )
+        endpoint_resource_value = {"uuid": endpoint_uuid}
+
+        # Check endpoint optional string fields
+        process_optional_string_field(endpoint_data, "name", endpoint_resource_value)
+        process_optional_string_field(
+            endpoint_data, "site_location", endpoint_resource_value
+        )
+        process_optional_string_field(endpoint_data, "ce-ip", endpoint_resource_value)
+        process_optional_string_field(
+            endpoint_data, "address_ip", endpoint_resource_value
+        )
+        process_optional_string_field(
+            endpoint_data, "address_prefix", endpoint_resource_value
+        )
+        process_optional_string_field(endpoint_data, "mtu", endpoint_resource_value)
+        process_optional_string_field(
+            endpoint_data, "ipv4_lan_prefixes", endpoint_resource_value
+        )
+        process_optional_string_field(endpoint_data, "type", endpoint_resource_value)
+        process_optional_string_field(
+            endpoint_data, "context_uuid", endpoint_resource_value
+        )
+        process_optional_string_field(
+            endpoint_data, "topology_uuid", endpoint_resource_value
+        )
+
+        # Check endpoint sample types (optional)
+        endpoint_sample_types = chk_attribute(
+            "sample_types", endpoint_data, "endpoint_data", default=[]
+        )
+        chk_type("endpoint_data.sample_types", endpoint_sample_types, list)
+        sample_types = {}
+        sample_type_errors = []
+        for i, endpoint_sample_type in enumerate(endpoint_sample_types):
+            field_name = "endpoint_data.sample_types[{:d}]".format(i)
+            try:
+                chk_type(field_name, endpoint_sample_type, (int, str))
+                if isinstance(endpoint_sample_type, int):
+                    metric_name = KpiSampleType.Name(endpoint_sample_type)
+                    metric_id = endpoint_sample_type
+                elif isinstance(endpoint_sample_type, str):
+                    metric_id = KpiSampleType.Value(endpoint_sample_type)
+                    metric_name = endpoint_sample_type
+                else:
+                    str_type = str(type(endpoint_sample_type))
+                    raise Exception("Bad format: {:s}".format(str_type))  # pylint: disable=broad-exception-raised
+            except Exception as e:  # pylint: disable=broad-exception-caught
+                MSG = "Unsupported {:s}({:s}) : {:s}"
+                sample_type_errors.append(
+                    MSG.format(field_name, str(endpoint_sample_type), str(e))
+                )
+
+            metric_name = metric_name.lower().replace("kpisampletype_", "")
+            monitoring_resource_key = "{:s}/state/{:s}".format(
+                endpoint_resource_key, metric_name
+            )
+            sample_types[metric_id] = monitoring_resource_key
+
+        if len(sample_type_errors) > 0:
+            # pylint: disable=broad-exception-raised
+            raise Exception(
+                "Malformed Sample Types:\n{:s}".format("\n".join(sample_type_errors))
+            )
+
+        if len(sample_types) > 0:
+            endpoint_resource_value["sample_types"] = sample_types
+
+        if "site_location" in endpoint_data:
+            endpoint_resource_value["site_location"] = endpoint_data["site_location"]
+
+        if "ce-ip" in endpoint_data:
+            endpoint_resource_value["ce-ip"] = endpoint_data["ce-ip"]
+
+        if "address_ip" in endpoint_data:
+            endpoint_resource_value["address_ip"] = endpoint_data["address_ip"]
+
+        if "address_prefix" in endpoint_data:
+            endpoint_resource_value["address_prefix"] = endpoint_data["address_prefix"]
+
+        if "mtu" in endpoint_data:
+            endpoint_resource_value["mtu"] = endpoint_data["mtu"]
+
+        if "ipv4_lan_prefixes" in endpoint_data:
+            endpoint_resource_value["ipv4_lan_prefixes"] = endpoint_data[
+                "ipv4_lan_prefixes"
+            ]
+
+        return endpoint_resource_key, endpoint_resource_value
+    except:  # pylint: disable=bare-except
+        LOGGER.exception("Problem composing endpoint({:s})".format(str(endpoint_data)))
+        return None
diff --git a/src/device/service/drivers/ietf_l3vpn/__init__.py b/src/device/service/drivers/ietf_l3vpn/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..bbfc943b68af13a11e562abbc8680ade71db8f02
--- /dev/null
+++ b/src/device/service/drivers/ietf_l3vpn/__init__.py
@@ -0,0 +1,13 @@
+# 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.
diff --git a/src/device/service/drivers/ietf_l3vpn/driver.py b/src/device/service/drivers/ietf_l3vpn/driver.py
new file mode 100644
index 0000000000000000000000000000000000000000..2aca83b6a645bf2e793b08841949813f0413a531
--- /dev/null
+++ b/src/device/service/drivers/ietf_l3vpn/driver.py
@@ -0,0 +1,309 @@
+# 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
+import logging
+import re
+import threading
+from typing import Any, Iterator, List, Optional, Tuple, Union
+
+import anytree
+import requests
+from requests.auth import HTTPBasicAuth
+
+from common.method_wrappers.Decorator import MetricsPool, metered_subclass_method
+from common.type_checkers.Checkers import chk_length, chk_string, chk_type
+from device.service.driver_api._Driver import (
+    RESOURCE_ENDPOINTS,
+    RESOURCE_SERVICES,
+    _Driver,
+)
+from device.service.driver_api.AnyTreeTools import (
+    TreeNode,
+    dump_subtree,
+    get_subnode,
+    set_subnode_value,
+)
+from device.service.driver_api.ImportTopologyEnum import (
+    ImportTopologyEnum,
+    get_import_topology,
+)
+
+from .Constants import SPECIAL_RESOURCE_MAPPINGS
+from .TfsApiClient import TfsApiClient
+from .Tools import compose_resource_endpoint
+
+LOGGER = logging.getLogger(__name__)
+
+
+ALL_RESOURCE_KEYS = [
+    RESOURCE_ENDPOINTS,
+    RESOURCE_SERVICES,
+]
+
+RE_GET_ENDPOINT_FROM_INTERFACE = re.compile(r"^\/interface\[([^\]]+)\].*")
+
+RE_IETF_L3VPN_DATA = re.compile(r"^\/service\[[^\]]+\]\/IETFL3VPN$")
+RE_IETF_L3VPN_OPERATION = re.compile(r"^\/service\[[^\]]+\]\/IETFL3VPN\/operation$")
+
+DRIVER_NAME = "ietf_l3vpn"
+METRICS_POOL = MetricsPool("Device", "Driver", labels={"driver": DRIVER_NAME})
+
+
+class IetfL3VpnDriver(_Driver):
+    def __init__(self, address: str, port: str, **settings) -> None:
+        super().__init__(DRIVER_NAME, address, int(port), **settings)
+        self.__lock = threading.Lock()
+        self.__started = threading.Event()
+        self.__terminate = threading.Event()
+        self.__running = TreeNode(".")
+        scheme = self.settings.get("scheme", "http")
+        username = self.settings.get("username")
+        password = self.settings.get("password")
+        self.tac = TfsApiClient(
+            self.address,
+            self.port,
+            scheme=scheme,
+            username=username,
+            password=password,
+        )
+        self.__auth = None
+        # (
+        #     HTTPBasicAuth(username, password)
+        #     if username is not None and password is not None
+        #     else None
+        # )
+        self.__tfs_nbi_root = "{:s}://{:s}:{:d}".format(
+            scheme, self.address, int(self.port)
+        )
+        self.__timeout = int(self.settings.get("timeout", 120))
+        self.__import_topology = get_import_topology(
+            self.settings, default=ImportTopologyEnum.DEVICES
+        )
+        endpoints = self.settings.get("endpoints", [])
+        endpoint_resources = []
+        for endpoint in endpoints:
+            endpoint_resource = compose_resource_endpoint(endpoint)
+            if endpoint_resource is None:
+                continue
+            endpoint_resources.append(endpoint_resource)
+        self._set_initial_config(endpoint_resources)
+
+    def _set_initial_config(
+        self, resources: List[Tuple[str, Any]]
+    ) -> List[Union[bool, Exception]]:
+        chk_type("resources", resources, list)
+        if len(resources) == 0:
+            return []
+        results = []
+        resolver = anytree.Resolver(pathattr="name")
+        with self.__lock:
+            for i, resource in enumerate(resources):
+                str_resource_name = "resources[#{:d}]".format(i)
+                try:
+                    chk_type(str_resource_name, resource, (list, tuple))
+                    chk_length(str_resource_name, resource, min_length=2, max_length=2)
+                    resource_key, resource_value = resource
+                    chk_string(str_resource_name, resource_key, allow_empty=False)
+                    resource_path = resource_key.split("/")
+                except Exception as e:  # pylint: disable=broad-except
+                    LOGGER.exception(
+                        "Exception validating {:s}: {:s}".format(
+                            str_resource_name, str(resource_key)
+                        )
+                    )
+                    results.append(e)  # if validation fails, store the exception
+                    continue
+
+                try:
+                    resource_value = json.loads(resource_value)
+                except:  # pylint: disable=bare-except
+                    pass
+
+                set_subnode_value(
+                    resolver, self.__running, resource_path, resource_value
+                )
+
+                results.append(True)
+        return results
+
+    def Connect(self) -> bool:
+        url = (
+            self.__tfs_nbi_root + "/restconf/data/ietf-l3vpn-svc:l3vpn-svc/vpn-services"
+        )
+        with self.__lock:
+            if self.__started.is_set():
+                return True
+            try:
+                # requests.get(url, timeout=self.__timeout, auth=self.__auth)
+                ...
+            except requests.exceptions.Timeout:
+                LOGGER.exception("Timeout connecting {:s}".format(url))
+                return False
+            except Exception:  # pylint: disable=broad-except
+                LOGGER.exception("Exception connecting {:s}".format(url))
+                return False
+            else:
+                self.__started.set()
+                return True
+
+    def Disconnect(self) -> bool:
+        with self.__lock:
+            self.__terminate.set()
+            return True
+
+    @metered_subclass_method(METRICS_POOL)
+    def GetInitialConfig(self) -> List[Tuple[str, Any]]:
+        with self.__lock:
+            return []
+
+    @metered_subclass_method(METRICS_POOL)
+    def GetConfig(
+        self, resource_keys: List[str] = []
+    ) -> List[Tuple[str, Union[Any, None, Exception]]]:
+        chk_type("resources", resource_keys, list)
+        with self.__lock:
+            if len(resource_keys) == 0:
+                return dump_subtree(self.__running)
+            results = []
+            resolver = anytree.Resolver(pathattr="name")
+            for i, resource_key in enumerate(resource_keys):
+                str_resource_name = "resource_key[#{:d}]".format(i)
+                try:
+                    chk_string(str_resource_name, resource_key, allow_empty=False)
+                    resource_key = SPECIAL_RESOURCE_MAPPINGS.get(
+                        resource_key, resource_key
+                    )
+                    resource_path = resource_key.split("/")
+                except Exception as e:  # pylint: disable=broad-except
+                    LOGGER.exception(
+                        "Exception validating {:s}: {:s}".format(
+                            str_resource_name, str(resource_key)
+                        )
+                    )
+                    results.append(
+                        (resource_key, e)
+                    )  # if validation fails, store the exception
+                    continue
+
+                resource_node = get_subnode(
+                    resolver, self.__running, resource_path, default=None
+                )
+                # if not found, resource_node is None
+                if resource_node is None:
+                    continue
+                results.extend(dump_subtree(resource_node))
+            return results
+        return results
+
+    @metered_subclass_method(METRICS_POOL)
+    def SetConfig(
+        self, resources: List[Tuple[str, Any]]
+    ) -> List[Union[bool, Exception]]:
+        results = []
+        if len(resources) == 0:
+            return results
+        with self.__lock:
+            for resource in resources:
+                resource_key, resource_value = resource
+                if RE_IETF_L3VPN_OPERATION.match(resource_key):
+                    operation_type = json.loads(resource_value)["type"]
+                    results.append((resource_key, True))
+                    break
+            else:
+                raise Exception("operation type not found in resources")
+            for resource in resources:
+                LOGGER.info("resource = {:s}".format(str(resource)))
+                resource_key, resource_value = resource
+                if not RE_IETF_L3VPN_DATA.match(resource_key):
+                    continue
+                try:
+                    resource_value = json.loads(resource_value)
+
+                    # if service_exists(self.__tfs_nbi_root, self.__auth, service_uuid):
+                    #     exc = NotImplementedError(
+                    #         "IETF L3VPN Service Update is still not supported"
+                    #     )
+                    #     results.append((resource[0], exc))
+                    #     continue
+                    if operation_type == "create":
+                        service_id = resource_value["ietf-l3vpn-svc:l3vpn-svc"][
+                            "vpn-services"
+                        ]["vpn-service"][0]["vpn-id"]
+                        self.tac.create_connectivity_service(resource_value)
+                    elif operation_type == "update":
+                        service_id = resource_value["ietf-l3vpn-svc:l3vpn-svc"][
+                            "vpn-services"
+                        ]["vpn-service"][0]["vpn-id"]
+                        self.tac.update_connectivity_service(resource_value)
+                    else:
+                        raise Exception("operation type not supported")
+                    results.append((resource_key, True))
+                except Exception as e:  # pylint: disable=broad-except
+                    LOGGER.exception(
+                        "Unhandled error processing resource_key({:s})".format(
+                            str(resource_key)
+                        )
+                    )
+                    results.append((resource_key, e))
+        return results
+
+    @metered_subclass_method(METRICS_POOL)
+    def DeleteConfig(
+        self, resources: List[Tuple[str, Any]]
+    ) -> List[Union[bool, Exception]]:
+        results = []
+        if len(resources) == 0:
+            return results
+        with self.__lock:
+            for resource in resources:
+                LOGGER.info("resource = {:s}".format(str(resource)))
+                resource_key, resource_value = resource
+                if not RE_IETF_L3VPN_DATA.match(resource_key):
+                    continue
+                try:
+                    resource_value = json.loads(resource_value)
+                    service_id = resource_value["id"]
+
+                    # if service_exists(self.__tfs_nbi_root, self.__auth, service_uuid):
+                    self.tac.delete_connectivity_service(service_id)
+                    results.append((resource_key, True))
+                except Exception as e:  # pylint: disable=broad-except
+                    LOGGER.exception(
+                        "Unhandled error processing resource_key({:s})".format(
+                            str(resource_key)
+                        )
+                    )
+                    results.append((resource_key, e))
+        return results
+
+    @metered_subclass_method(METRICS_POOL)
+    def SubscribeState(
+        self, subscriptions: List[Tuple[str, float, float]]
+    ) -> List[Union[bool, Exception]]:
+        # TODO: IETF L3VPN does not support monitoring by now
+        return [False for _ in subscriptions]
+
+    @metered_subclass_method(METRICS_POOL)
+    def UnsubscribeState(
+        self, subscriptions: List[Tuple[str, float, float]]
+    ) -> List[Union[bool, Exception]]:
+        # TODO: IETF L3VPN does not support monitoring by now
+        return [False for _ in subscriptions]
+
+    def GetState(
+        self, blocking=False, terminate: Optional[threading.Event] = None
+    ) -> Iterator[Tuple[float, str, Any]]:
+        # TODO: IETF L3VPN does not support monitoring by now
+        return []
diff --git a/src/device/service/drivers/ietf_slice/Constants.py b/src/device/service/drivers/ietf_slice/Constants.py
new file mode 100644
index 0000000000000000000000000000000000000000..172c328aeaa5a2beafe4ced1b273cb3e7577e241
--- /dev/null
+++ b/src/device/service/drivers/ietf_slice/Constants.py
@@ -0,0 +1,25 @@
+# Copyright 2022-2025 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 device.service.driver_api._Driver import (
+    RESOURCE_ENDPOINTS,
+    RESOURCE_INTERFACES,
+    RESOURCE_NETWORK_INSTANCES,
+)
+
+SPECIAL_RESOURCE_MAPPINGS = {
+    RESOURCE_ENDPOINTS: "/endpoints",
+    RESOURCE_INTERFACES: "/interfaces",
+    RESOURCE_NETWORK_INSTANCES: "/net-instances",
+}
diff --git a/src/device/service/drivers/ietf_slice/Tools.py b/src/device/service/drivers/ietf_slice/Tools.py
new file mode 100644
index 0000000000000000000000000000000000000000..bd976927e4b17c74264b3372ed1caeeb1bc96c61
--- /dev/null
+++ b/src/device/service/drivers/ietf_slice/Tools.py
@@ -0,0 +1,147 @@
+# Copyright 2022-2025 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 logging
+from typing import Any, Dict, Optional, Tuple
+
+import requests
+
+from common.proto.kpi_sample_types_pb2 import KpiSampleType
+from common.type_checkers.Checkers import chk_attribute, chk_string, chk_type
+from device.service.driver_api._Driver import RESOURCE_ENDPOINTS
+
+from .Constants import SPECIAL_RESOURCE_MAPPINGS
+
+LOGGER = logging.getLogger(__name__)
+
+
+def process_optional_string_field(
+    endpoint_data: Dict[str, Any],
+    field_name: str,
+    endpoint_resource_value: Dict[str, Any],
+) -> None:
+    field_value = chk_attribute(
+        field_name, endpoint_data, "endpoint_data", default=None
+    )
+    if field_value is None:
+        return
+    chk_string("endpoint_data.{:s}".format(field_name), field_value)
+    if len(field_value) > 0:
+        endpoint_resource_value[field_name] = field_value
+
+
+def compose_resource_endpoint(
+    endpoint_data: Dict[str, Any],
+) -> Optional[Tuple[str, Dict]]:
+    try:
+        # Check type of endpoint_data
+        chk_type("endpoint_data", endpoint_data, dict)
+
+        # Check endpoint UUID (mandatory)
+        endpoint_uuid = chk_attribute("uuid", endpoint_data, "endpoint_data")
+        chk_string("endpoint_data.uuid", endpoint_uuid, min_length=1)
+        endpoint_resource_path = SPECIAL_RESOURCE_MAPPINGS.get(RESOURCE_ENDPOINTS)
+        endpoint_resource_key = "{:s}/endpoint[{:s}]".format(
+            endpoint_resource_path, endpoint_uuid
+        )
+        endpoint_resource_value = {"uuid": endpoint_uuid}
+
+        # Check endpoint optional string fields
+        process_optional_string_field(endpoint_data, "name", endpoint_resource_value)
+        process_optional_string_field(
+            endpoint_data, "site_location", endpoint_resource_value
+        )
+        process_optional_string_field(endpoint_data, "ce-ip", endpoint_resource_value)
+        process_optional_string_field(
+            endpoint_data, "address_ip", endpoint_resource_value
+        )
+        process_optional_string_field(
+            endpoint_data, "address_prefix", endpoint_resource_value
+        )
+        process_optional_string_field(endpoint_data, "mtu", endpoint_resource_value)
+        process_optional_string_field(
+            endpoint_data, "ipv4_lan_prefixes", endpoint_resource_value
+        )
+        process_optional_string_field(endpoint_data, "type", endpoint_resource_value)
+        process_optional_string_field(
+            endpoint_data, "context_uuid", endpoint_resource_value
+        )
+        process_optional_string_field(
+            endpoint_data, "topology_uuid", endpoint_resource_value
+        )
+
+        # Check endpoint sample types (optional)
+        endpoint_sample_types = chk_attribute(
+            "sample_types", endpoint_data, "endpoint_data", default=[]
+        )
+        chk_type("endpoint_data.sample_types", endpoint_sample_types, list)
+        sample_types = {}
+        sample_type_errors = []
+        for i, endpoint_sample_type in enumerate(endpoint_sample_types):
+            field_name = "endpoint_data.sample_types[{:d}]".format(i)
+            try:
+                chk_type(field_name, endpoint_sample_type, (int, str))
+                if isinstance(endpoint_sample_type, int):
+                    metric_name = KpiSampleType.Name(endpoint_sample_type)
+                    metric_id = endpoint_sample_type
+                elif isinstance(endpoint_sample_type, str):
+                    metric_id = KpiSampleType.Value(endpoint_sample_type)
+                    metric_name = endpoint_sample_type
+                else:
+                    str_type = str(type(endpoint_sample_type))
+                    raise Exception("Bad format: {:s}".format(str_type))  # pylint: disable=broad-exception-raised
+            except Exception as e:  # pylint: disable=broad-exception-caught
+                MSG = "Unsupported {:s}({:s}) : {:s}"
+                sample_type_errors.append(
+                    MSG.format(field_name, str(endpoint_sample_type), str(e))
+                )
+
+            metric_name = metric_name.lower().replace("kpisampletype_", "")
+            monitoring_resource_key = "{:s}/state/{:s}".format(
+                endpoint_resource_key, metric_name
+            )
+            sample_types[metric_id] = monitoring_resource_key
+
+        if len(sample_type_errors) > 0:
+            # pylint: disable=broad-exception-raised
+            raise Exception(
+                "Malformed Sample Types:\n{:s}".format("\n".join(sample_type_errors))
+            )
+
+        if len(sample_types) > 0:
+            endpoint_resource_value["sample_types"] = sample_types
+
+        if "site_location" in endpoint_data:
+            endpoint_resource_value["site_location"] = endpoint_data["site_location"]
+
+        if "ce-ip" in endpoint_data:
+            endpoint_resource_value["ce-ip"] = endpoint_data["ce-ip"]
+
+        if "address_ip" in endpoint_data:
+            endpoint_resource_value["address_ip"] = endpoint_data["address_ip"]
+
+        if "address_prefix" in endpoint_data:
+            endpoint_resource_value["address_prefix"] = endpoint_data["address_prefix"]
+
+        if "mtu" in endpoint_data:
+            endpoint_resource_value["mtu"] = endpoint_data["mtu"]
+
+        if "ipv4_lan_prefixes" in endpoint_data:
+            endpoint_resource_value["ipv4_lan_prefixes"] = endpoint_data[
+                "ipv4_lan_prefixes"
+            ]
+
+        return endpoint_resource_key, endpoint_resource_value
+    except:  # pylint: disable=bare-except
+        LOGGER.exception("Problem composing endpoint({:s})".format(str(endpoint_data)))
+        return None
diff --git a/src/device/service/drivers/ietf_slice/__init__.py b/src/device/service/drivers/ietf_slice/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..6242c89c7fa17bc5b6cc44328d8ce58438721d45
--- /dev/null
+++ b/src/device/service/drivers/ietf_slice/__init__.py
@@ -0,0 +1,13 @@
+# Copyright 2022-2025 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.
diff --git a/src/device/service/drivers/ietf_slice/driver.py b/src/device/service/drivers/ietf_slice/driver.py
new file mode 100644
index 0000000000000000000000000000000000000000..e8b6e7d0effac1f7a3eb05c7aabd2d0a39125b65
--- /dev/null
+++ b/src/device/service/drivers/ietf_slice/driver.py
@@ -0,0 +1,306 @@
+# Copyright 2022-2025 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
+import logging
+import re
+import threading
+from typing import Any, Iterator, List, Optional, Tuple, Union
+
+import anytree
+import requests
+from requests.auth import HTTPBasicAuth
+
+from common.method_wrappers.Decorator import MetricsPool, metered_subclass_method
+from common.type_checkers.Checkers import chk_length, chk_string, chk_type
+from device.service.driver_api._Driver import (
+    RESOURCE_ENDPOINTS,
+    RESOURCE_SERVICES,
+    _Driver,
+)
+from device.service.driver_api.AnyTreeTools import (
+    TreeNode,
+    dump_subtree,
+    get_subnode,
+    set_subnode_value,
+)
+from device.service.driver_api.ImportTopologyEnum import (
+    ImportTopologyEnum,
+    get_import_topology,
+)
+
+from .Constants import SPECIAL_RESOURCE_MAPPINGS
+from .tfs_slice_nbi_client import TfsApiClient
+from .Tools import compose_resource_endpoint
+
+LOGGER = logging.getLogger(__name__)
+
+
+ALL_RESOURCE_KEYS = [
+    RESOURCE_ENDPOINTS,
+    RESOURCE_SERVICES,
+]
+
+RE_IETF_SLICE_DATA = re.compile(r"^\/service\[[^\]]+\]\/IETFSlice$")
+RE_IETF_SLICE_OPERATION = re.compile(r"^\/service\[[^\]]+\]\/IETFSlice\/operation$")
+
+DRIVER_NAME = "ietf_slice"
+METRICS_POOL = MetricsPool("Device", "Driver", labels={"driver": DRIVER_NAME})
+
+
+class IetfSliceDriver(_Driver):
+    def __init__(self, address: str, port: str, **settings) -> None:
+        super().__init__(DRIVER_NAME, address, int(port), **settings)
+        self.__lock = threading.Lock()
+        self.__started = threading.Event()
+        self.__terminate = threading.Event()
+        self.__running = TreeNode(".")
+        scheme = self.settings.get("scheme", "http")
+        username = self.settings.get("username")
+        password = self.settings.get("password")
+        self.tac = TfsApiClient(
+            self.address,
+            self.port,
+            scheme=scheme,
+            username=username,
+            password=password,
+        )
+        self.__auth = None
+        # (
+        #     HTTPBasicAuth(username, password)
+        #     if username is not None and password is not None
+        #     else None
+        # )
+        self.__tfs_nbi_root = "{:s}://{:s}:{:d}".format(
+            scheme, self.address, int(self.port)
+        )
+        self.__timeout = int(self.settings.get("timeout", 120))
+        self.__import_topology = get_import_topology(
+            self.settings, default=ImportTopologyEnum.DEVICES
+        )
+        endpoints = self.settings.get("endpoints", [])
+        endpoint_resources = []
+        for endpoint in endpoints:
+            endpoint_resource = compose_resource_endpoint(endpoint)
+            if endpoint_resource is None:
+                continue
+            endpoint_resources.append(endpoint_resource)
+        self._set_initial_config(endpoint_resources)
+
+    def _set_initial_config(
+        self, resources: List[Tuple[str, Any]]
+    ) -> List[Union[bool, Exception]]:
+        chk_type("resources", resources, list)
+        if len(resources) == 0:
+            return []
+        results = []
+        resolver = anytree.Resolver(pathattr="name")
+        with self.__lock:
+            for i, resource in enumerate(resources):
+                str_resource_name = "resources[#{:d}]".format(i)
+                try:
+                    chk_type(str_resource_name, resource, (list, tuple))
+                    chk_length(str_resource_name, resource, min_length=2, max_length=2)
+                    resource_key, resource_value = resource
+                    chk_string(str_resource_name, resource_key, allow_empty=False)
+                    resource_path = resource_key.split("/")
+                except Exception as e:  # pylint: disable=broad-except
+                    LOGGER.exception(
+                        "Exception validating {:s}: {:s}".format(
+                            str_resource_name, str(resource_key)
+                        )
+                    )
+                    results.append(e)  # if validation fails, store the exception
+                    continue
+
+                try:
+                    resource_value = json.loads(resource_value)
+                except:  # pylint: disable=bare-except
+                    pass
+
+                set_subnode_value(
+                    resolver, self.__running, resource_path, resource_value
+                )
+
+                results.append(True)
+        return results
+
+    def Connect(self) -> bool:
+        url = self.__tfs_nbi_root + "/restconf/data/ietf-network-slice-service:ietf-nss"
+        with self.__lock:
+            if self.__started.is_set():
+                return True
+            try:
+                # requests.get(url, timeout=self.__timeout)
+                ...
+            except requests.exceptions.Timeout:
+                LOGGER.exception("Timeout connecting {:s}".format(url))
+                return False
+            except Exception:  # pylint: disable=broad-except
+                LOGGER.exception("Exception connecting {:s}".format(url))
+                return False
+            else:
+                self.__started.set()
+                return True
+
+    def Disconnect(self) -> bool:
+        with self.__lock:
+            self.__terminate.set()
+            return True
+
+    @metered_subclass_method(METRICS_POOL)
+    def GetInitialConfig(self) -> List[Tuple[str, Any]]:
+        with self.__lock:
+            return []
+
+    @metered_subclass_method(METRICS_POOL)
+    def GetConfig(
+        self, resource_keys: List[str] = []
+    ) -> List[Tuple[str, Union[Any, None, Exception]]]:
+        chk_type("resources", resource_keys, list)
+        with self.__lock:
+            if len(resource_keys) == 0:
+                return dump_subtree(self.__running)
+            results = []
+            resolver = anytree.Resolver(pathattr="name")
+            for i, resource_key in enumerate(resource_keys):
+                str_resource_name = "resource_key[#{:d}]".format(i)
+                try:
+                    chk_string(str_resource_name, resource_key, allow_empty=False)
+                    resource_key = SPECIAL_RESOURCE_MAPPINGS.get(
+                        resource_key, resource_key
+                    )
+                    resource_path = resource_key.split("/")
+                except Exception as e:  # pylint: disable=broad-except
+                    LOGGER.exception(
+                        "Exception validating {:s}: {:s}".format(
+                            str_resource_name, str(resource_key)
+                        )
+                    )
+                    results.append(
+                        (resource_key, e)
+                    )  # if validation fails, store the exception
+                    continue
+                resource_node = get_subnode(
+                    resolver, self.__running, resource_path, default=None
+                )
+                # if not found, resource_node is None
+                if resource_node is None:
+                    continue
+                results.extend(dump_subtree(resource_node))
+            return results
+
+    @metered_subclass_method(METRICS_POOL)
+    def SetConfig(
+        self, resources: List[Tuple[str, Any]]
+    ) -> List[Union[bool, Exception]]:
+        results = []
+
+        if len(resources) == 0:
+            return results
+
+        with self.__lock:
+            for resource in resources:
+                resource_key, resource_value = resource
+                if RE_IETF_SLICE_OPERATION.match(resource_key):
+                    operation_type = json.loads(resource_value)["type"]
+                    results.append((resource_key, True))
+                    break
+            else:
+                raise Exception("operation type not found in resources")
+            for resource in resources:
+                LOGGER.info("resource = {:s}".format(str(resource)))
+                resource_key, resource_value = resource
+                if not RE_IETF_SLICE_DATA.match(resource_key):
+                    continue
+                try:
+                    resource_value = json.loads(resource_value)
+
+                    slice_name = resource_value["network-slice-services"][
+                        "slice-service"
+                    ][0]["id"]
+
+                    if operation_type == "create":
+                        self.tac.create_slice(resource_value)
+
+                    elif operation_type == "update":
+                        connection_groups = resource_value["network-slice-services"][
+                            "slice-service"
+                        ][0]["connection-groups"]["connection-group"]
+
+                        if len(connection_groups) != 1:
+                            raise Exception("only one connection group is supported")
+
+                        connection_group = connection_groups[0]
+
+                        self.tac.update_slice(
+                            slice_name, connection_group["id"], connection_group
+                        )
+
+                    elif operation_type == "delete":
+                        self.tac.delete_slice(slice_name)
+
+                    results.append((resource_key, True))
+                except Exception as e:  # pylint: disable=broad-except
+                    LOGGER.exception(
+                        "Unhandled error processing resource_key({:s})".format(
+                            str(resource_key)
+                        )
+                    )
+                    results.append((resource_key, e))
+        return results
+
+    @metered_subclass_method(METRICS_POOL)
+    def DeleteConfig(
+        self, resources: List[Tuple[str, Any]]
+    ) -> List[Union[bool, Exception]]:
+        results = []
+
+        if len(resources) == 0:
+            return results
+
+        with self.__lock:
+            for resource in resources:
+                LOGGER.info("resource = {:s}".format(str(resource)))
+                resource_key, resource_value = resource
+                try:
+                    results.append((resource_key, True))
+                except Exception as e:  # pylint: disable=broad-except
+                    LOGGER.exception(
+                        "Unhandled error processing resource_key({:s})".format(
+                            str(resource_key)
+                        )
+                    )
+                    results.append((resource_key, e))
+        return results
+
+    @metered_subclass_method(METRICS_POOL)
+    def SubscribeState(
+        self, subscriptions: List[Tuple[str, float, float]]
+    ) -> List[Union[bool, Exception]]:
+        # TODO: IETF Slice does not support monitoring by now
+        return [False for _ in subscriptions]
+
+    @metered_subclass_method(METRICS_POOL)
+    def UnsubscribeState(
+        self, subscriptions: List[Tuple[str, float, float]]
+    ) -> List[Union[bool, Exception]]:
+        # TODO: IETF Slice does not support monitoring by now
+        return [False for _ in subscriptions]
+
+    def GetState(
+        self, blocking=False, terminate: Optional[threading.Event] = None
+    ) -> Iterator[Tuple[float, str, Any]]:
+        # TODO: IETF Slice does not support monitoring by now
+        return []
diff --git a/src/device/service/drivers/ietf_slice/tfs_slice_nbi_client.py b/src/device/service/drivers/ietf_slice/tfs_slice_nbi_client.py
new file mode 100644
index 0000000000000000000000000000000000000000..596e3d903d6e17dda96be42d776aae2f9068f7bd
--- /dev/null
+++ b/src/device/service/drivers/ietf_slice/tfs_slice_nbi_client.py
@@ -0,0 +1,76 @@
+# Copyright 2022-2025 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 logging
+from typing import Optional
+
+import requests
+from requests.auth import HTTPBasicAuth
+
+IETF_SLICE_URL = "{:s}://{:s}:{:d}/restconf/data/ietf-network-slice-service"
+TIMEOUT = 30
+
+LOGGER = logging.getLogger(__name__)
+
+HEADERS = {"Content-Type": "application/json"}
+
+
+class TfsApiClient:
+    def __init__(
+        self,
+        address: str,
+        port: int,
+        scheme: str = "http",
+        username: Optional[str] = None,
+        password: Optional[str] = None,
+    ) -> None:
+        self._slice_url = IETF_SLICE_URL.format(scheme, address, port)
+        self._auth = None
+        # (
+        #     HTTPBasicAuth(username, password)
+        #     if username is not None and password is not None
+        #     else None
+        # )
+
+    def create_slice(self, slice_data: dict) -> None:
+        url = self._slice_url + ":network-slice-services"
+        try:
+            requests.post(url, json=slice_data, headers=HEADERS)
+            LOGGER.info(f"IETF Slice Post to {url}: {slice_data}")
+        except requests.exceptions.ConnectionError:
+            raise Exception("faild to send post request to TFS IETF Slice NBI")
+
+    def update_slice(
+        self,
+        slice_name: str,
+        connection_group_id: str,
+        updated_connection_group_data: dict,
+    ) -> None:
+        url = (
+            self._slice_url
+            + f":network-slice-services/slice-service={slice_name}/connection-groups/connection-group={connection_group_id}"
+        )
+        try:
+            requests.put(url, json=updated_connection_group_data, headers=HEADERS)
+            LOGGER.info(f"IETF Slice Put to {url}: {updated_connection_group_data}")
+        except requests.exceptions.ConnectionError:
+            raise Exception("faild to send update request to TFS IETF Slice NBI")
+
+    def delete_slice(self, slice_name: str) -> None:
+        url = self._slice_url + f":network-slice-services/slice-service={slice_name}"
+        try:
+            requests.delete(url)
+            LOGGER.info(f"IETF Slice Delete to {url}")
+        except requests.exceptions.ConnectionError:
+            raise Exception("faild to send delete request to TFS IETF Slice NBI")
diff --git a/src/device/service/drivers/nce/Constants.py b/src/device/service/drivers/nce/Constants.py
new file mode 100644
index 0000000000000000000000000000000000000000..172c328aeaa5a2beafe4ced1b273cb3e7577e241
--- /dev/null
+++ b/src/device/service/drivers/nce/Constants.py
@@ -0,0 +1,25 @@
+# Copyright 2022-2025 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 device.service.driver_api._Driver import (
+    RESOURCE_ENDPOINTS,
+    RESOURCE_INTERFACES,
+    RESOURCE_NETWORK_INSTANCES,
+)
+
+SPECIAL_RESOURCE_MAPPINGS = {
+    RESOURCE_ENDPOINTS: "/endpoints",
+    RESOURCE_INTERFACES: "/interfaces",
+    RESOURCE_NETWORK_INSTANCES: "/net-instances",
+}
diff --git a/src/device/service/drivers/nce/Tools.py b/src/device/service/drivers/nce/Tools.py
new file mode 100644
index 0000000000000000000000000000000000000000..f9b2f24a8df494d04d749624ea6b2e5b986944fc
--- /dev/null
+++ b/src/device/service/drivers/nce/Tools.py
@@ -0,0 +1,145 @@
+# Copyright 2022-2025 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 logging
+from typing import Any, Dict, Optional, Tuple
+
+from common.proto.kpi_sample_types_pb2 import KpiSampleType
+from common.type_checkers.Checkers import chk_attribute, chk_string, chk_type
+from device.service.driver_api._Driver import RESOURCE_ENDPOINTS
+
+from .Constants import SPECIAL_RESOURCE_MAPPINGS
+
+LOGGER = logging.getLogger(__name__)
+
+
+def process_optional_string_field(
+    endpoint_data: Dict[str, Any],
+    field_name: str,
+    endpoint_resource_value: Dict[str, Any],
+) -> None:
+    field_value = chk_attribute(
+        field_name, endpoint_data, "endpoint_data", default=None
+    )
+    if field_value is None:
+        return
+    chk_string("endpoint_data.{:s}".format(field_name), field_value)
+    if len(field_value) > 0:
+        endpoint_resource_value[field_name] = field_value
+
+
+def compose_resource_endpoint(
+    endpoint_data: Dict[str, Any],
+) -> Optional[Tuple[str, Dict]]:
+    try:
+        # Check type of endpoint_data
+        chk_type("endpoint_data", endpoint_data, dict)
+
+        # Check endpoint UUID (mandatory)
+        endpoint_uuid = chk_attribute("uuid", endpoint_data, "endpoint_data")
+        chk_string("endpoint_data.uuid", endpoint_uuid, min_length=1)
+        endpoint_resource_path = SPECIAL_RESOURCE_MAPPINGS.get(RESOURCE_ENDPOINTS)
+        endpoint_resource_key = "{:s}/endpoint[{:s}]".format(
+            endpoint_resource_path, endpoint_uuid
+        )
+        endpoint_resource_value = {"uuid": endpoint_uuid}
+
+        # Check endpoint optional string fields
+        process_optional_string_field(endpoint_data, "name", endpoint_resource_value)
+        process_optional_string_field(
+            endpoint_data, "site_location", endpoint_resource_value
+        )
+        process_optional_string_field(endpoint_data, "ce-ip", endpoint_resource_value)
+        process_optional_string_field(
+            endpoint_data, "address_ip", endpoint_resource_value
+        )
+        process_optional_string_field(
+            endpoint_data, "address_prefix", endpoint_resource_value
+        )
+        process_optional_string_field(endpoint_data, "mtu", endpoint_resource_value)
+        process_optional_string_field(
+            endpoint_data, "ipv4_lan_prefixes", endpoint_resource_value
+        )
+        process_optional_string_field(endpoint_data, "type", endpoint_resource_value)
+        process_optional_string_field(
+            endpoint_data, "context_uuid", endpoint_resource_value
+        )
+        process_optional_string_field(
+            endpoint_data, "topology_uuid", endpoint_resource_value
+        )
+
+        # Check endpoint sample types (optional)
+        endpoint_sample_types = chk_attribute(
+            "sample_types", endpoint_data, "endpoint_data", default=[]
+        )
+        chk_type("endpoint_data.sample_types", endpoint_sample_types, list)
+        sample_types = {}
+        sample_type_errors = []
+        for i, endpoint_sample_type in enumerate(endpoint_sample_types):
+            field_name = "endpoint_data.sample_types[{:d}]".format(i)
+            try:
+                chk_type(field_name, endpoint_sample_type, (int, str))
+                if isinstance(endpoint_sample_type, int):
+                    metric_name = KpiSampleType.Name(endpoint_sample_type)
+                    metric_id = endpoint_sample_type
+                elif isinstance(endpoint_sample_type, str):
+                    metric_id = KpiSampleType.Value(endpoint_sample_type)
+                    metric_name = endpoint_sample_type
+                else:
+                    str_type = str(type(endpoint_sample_type))
+                    raise Exception("Bad format: {:s}".format(str_type))  # pylint: disable=broad-exception-raised
+            except Exception as e:  # pylint: disable=broad-exception-caught
+                MSG = "Unsupported {:s}({:s}) : {:s}"
+                sample_type_errors.append(
+                    MSG.format(field_name, str(endpoint_sample_type), str(e))
+                )
+
+            metric_name = metric_name.lower().replace("kpisampletype_", "")
+            monitoring_resource_key = "{:s}/state/{:s}".format(
+                endpoint_resource_key, metric_name
+            )
+            sample_types[metric_id] = monitoring_resource_key
+
+        if len(sample_type_errors) > 0:
+            # pylint: disable=broad-exception-raised
+            raise Exception(
+                "Malformed Sample Types:\n{:s}".format("\n".join(sample_type_errors))
+            )
+
+        if len(sample_types) > 0:
+            endpoint_resource_value["sample_types"] = sample_types
+
+        if "site_location" in endpoint_data:
+            endpoint_resource_value["site_location"] = endpoint_data["site_location"]
+
+        if "ce-ip" in endpoint_data:
+            endpoint_resource_value["ce-ip"] = endpoint_data["ce-ip"]
+
+        if "address_ip" in endpoint_data:
+            endpoint_resource_value["address_ip"] = endpoint_data["address_ip"]
+
+        if "address_prefix" in endpoint_data:
+            endpoint_resource_value["address_prefix"] = endpoint_data["address_prefix"]
+
+        if "mtu" in endpoint_data:
+            endpoint_resource_value["mtu"] = endpoint_data["mtu"]
+
+        if "ipv4_lan_prefixes" in endpoint_data:
+            endpoint_resource_value["ipv4_lan_prefixes"] = endpoint_data[
+                "ipv4_lan_prefixes"
+            ]
+
+        return endpoint_resource_key, endpoint_resource_value
+    except:  # pylint: disable=bare-except
+        LOGGER.exception("Problem composing endpoint({:s})".format(str(endpoint_data)))
+        return None
diff --git a/src/device/service/drivers/nce/__init__.py b/src/device/service/drivers/nce/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..6242c89c7fa17bc5b6cc44328d8ce58438721d45
--- /dev/null
+++ b/src/device/service/drivers/nce/__init__.py
@@ -0,0 +1,13 @@
+# Copyright 2022-2025 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.
diff --git a/src/device/service/drivers/nce/driver.py b/src/device/service/drivers/nce/driver.py
new file mode 100644
index 0000000000000000000000000000000000000000..4ac1a2b1c604a6ebe5028688dc39f545e0e1cee6
--- /dev/null
+++ b/src/device/service/drivers/nce/driver.py
@@ -0,0 +1,278 @@
+# Copyright 2022-2025 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
+import logging
+import re
+import threading
+from typing import Any, Iterator, List, Optional, Tuple, Union
+
+import anytree
+import requests
+from requests.auth import HTTPBasicAuth
+
+from common.method_wrappers.Decorator import MetricsPool, metered_subclass_method
+from common.type_checkers.Checkers import chk_length, chk_string, chk_type
+from device.service.driver_api._Driver import _Driver
+from device.service.driver_api.AnyTreeTools import (
+    TreeNode,
+    dump_subtree,
+    get_subnode,
+    set_subnode_value,
+)
+from device.service.driver_api.ImportTopologyEnum import (
+    ImportTopologyEnum,
+    get_import_topology,
+)
+
+from .Constants import SPECIAL_RESOURCE_MAPPINGS
+from .nce_fan_client import NCEClient
+from .Tools import compose_resource_endpoint
+
+LOGGER = logging.getLogger(__name__)
+
+
+RE_NCE_APP_FLOW_DATA = re.compile(r"^\/service\[[^\]]+\]\/AppFlow$")
+RE_NCE_APP_FLOW_OPERATION = re.compile(r"^\/service\[[^\]]+\]\/AppFlow\/operation$")
+
+DRIVER_NAME = "nce"
+METRICS_POOL = MetricsPool("Device", "Driver", labels={"driver": DRIVER_NAME})
+
+
+class NCEDriver(_Driver):
+    def __init__(self, address: str, port: str, **settings) -> None:
+        super().__init__(DRIVER_NAME, address, int(port), **settings)
+        self.__lock = threading.Lock()
+        self.__started = threading.Event()
+        self.__terminate = threading.Event()
+        self.__running = TreeNode(".")
+        scheme = self.settings.get("scheme", "http")
+        username = self.settings.get("username")
+        password = self.settings.get("password")
+        self.nce = NCEClient(
+            self.address,
+            self.port,
+            scheme=scheme,
+            username=username,
+            password=password,
+        )
+        self.__auth = None
+        # (
+        #     HTTPBasicAuth(username, password)
+        #     if username is not None and password is not None
+        #     else None
+        # )
+        self.__tfs_nbi_root = "{:s}://{:s}:{:d}".format(
+            scheme, self.address, int(self.port)
+        )
+        self.__timeout = int(self.settings.get("timeout", 120))
+        self.__import_topology = get_import_topology(
+            self.settings, default=ImportTopologyEnum.DEVICES
+        )
+        endpoints = self.settings.get("endpoints", [])
+        endpoint_resources = []
+        for endpoint in endpoints:
+            endpoint_resource = compose_resource_endpoint(endpoint)
+            if endpoint_resource is None:
+                continue
+            endpoint_resources.append(endpoint_resource)
+        self._set_initial_config(endpoint_resources)
+
+    def _set_initial_config(
+        self, resources: List[Tuple[str, Any]]
+    ) -> List[Union[bool, Exception]]:
+        chk_type("resources", resources, list)
+        if len(resources) == 0:
+            return []
+        results = []
+        resolver = anytree.Resolver(pathattr="name")
+        with self.__lock:
+            for i, resource in enumerate(resources):
+                str_resource_name = "resources[#{:d}]".format(i)
+                try:
+                    chk_type(str_resource_name, resource, (list, tuple))
+                    chk_length(str_resource_name, resource, min_length=2, max_length=2)
+                    resource_key, resource_value = resource
+                    chk_string(str_resource_name, resource_key, allow_empty=False)
+                    resource_path = resource_key.split("/")
+                except Exception as e:  # pylint: disable=broad-except
+                    LOGGER.exception(
+                        "Exception validating {:s}: {:s}".format(
+                            str_resource_name, str(resource_key)
+                        )
+                    )
+                    results.append(e)  # if validation fails, store the exception
+                    continue
+
+                try:
+                    resource_value = json.loads(resource_value)
+                except:  # pylint: disable=bare-except
+                    pass
+
+                set_subnode_value(
+                    resolver, self.__running, resource_path, resource_value
+                )
+
+                results.append(True)
+        return results
+
+    def Connect(self) -> bool:
+        with self.__lock:
+            if self.__started.is_set():
+                return True
+            try:
+                ...
+            except requests.exceptions.Timeout:
+                return False
+            except Exception:  # pylint: disable=broad-except
+                return False
+            else:
+                self.__started.set()
+                return True
+
+    def Disconnect(self) -> bool:
+        with self.__lock:
+            self.__terminate.set()
+            return True
+
+    @metered_subclass_method(METRICS_POOL)
+    def GetInitialConfig(self) -> List[Tuple[str, Any]]:
+        with self.__lock:
+            return []
+
+    @metered_subclass_method(METRICS_POOL)
+    def GetConfig(
+        self, resource_keys: List[str] = []
+    ) -> List[Tuple[str, Union[Any, None, Exception]]]:
+        chk_type("resources", resource_keys, list)
+        with self.__lock:
+            if len(resource_keys) == 0:
+                return dump_subtree(self.__running)
+            results = []
+            resolver = anytree.Resolver(pathattr="name")
+            for i, resource_key in enumerate(resource_keys):
+                str_resource_name = "resource_key[#{:d}]".format(i)
+                try:
+                    chk_string(str_resource_name, resource_key, allow_empty=False)
+                    resource_key = SPECIAL_RESOURCE_MAPPINGS.get(
+                        resource_key, resource_key
+                    )
+                    resource_path = resource_key.split("/")
+                except Exception as e:  # pylint: disable=broad-except
+                    LOGGER.exception(
+                        "Exception validating {:s}: {:s}".format(
+                            str_resource_name, str(resource_key)
+                        )
+                    )
+                    results.append(
+                        (resource_key, e)
+                    )  # if validation fails, store the exception
+                    continue
+
+                resource_node = get_subnode(
+                    resolver, self.__running, resource_path, default=None
+                )
+                # if not found, resource_node is None
+                if resource_node is None:
+                    continue
+                results.extend(dump_subtree(resource_node))
+            return results
+        return results
+
+    @metered_subclass_method(METRICS_POOL)
+    def SetConfig(
+        self, resources: List[Tuple[str, Any]]
+    ) -> List[Union[bool, Exception]]:
+        results = []
+
+        if len(resources) == 0:
+            return results
+
+        with self.__lock:
+            for resource in resources:
+                resource_key, resource_value = resource
+                LOGGER.debug("resource = {:s}".format(str(resource)))
+                if RE_NCE_APP_FLOW_OPERATION.match(resource_key):
+                    operation_type = json.loads(resource_value)["type"]
+                    results.append((resource_key, True))
+                    break
+            else:
+                raise Exception("operation type not found in resources")
+            for resource in resources:
+                LOGGER.info("resource = {:s}".format(str(resource)))
+                resource_key, resource_value = resource
+                if not RE_NCE_APP_FLOW_DATA.match(resource_key):
+                    continue
+                try:
+                    resource_value = json.loads(resource_value)
+                    if operation_type == "create":
+
+                        self.nce.create_app_flow(resource_value)
+                    elif operation_type == "delete":
+
+                        app_flow_name = resource_value["huawei-nce-app-flow:app-flows"][
+                            "app-flow"
+                        ][0]["app-name"]
+                        self.nce.delete_app_flow(app_flow_name)
+                    results.append((resource_key, True))
+                except Exception as e:  # pylint: disable=broad-except
+                    LOGGER.exception(
+                        "Unhandled error processing resource_key({:s})".format(
+                            str(resource_key)
+                        )
+                    )
+                    results.append((resource_key, e))
+        return results
+
+    @metered_subclass_method(METRICS_POOL)
+    def DeleteConfig(
+        self, resources: List[Tuple[str, Any]]
+    ) -> List[Union[bool, Exception]]:
+        results = []
+        if len(resources) == 0:
+            return results
+        with self.__lock:
+            for resource in resources:
+                LOGGER.info("resource = {:s}".format(str(resource)))
+                resource_key, resource_value = resource
+                try:
+                    results.append((resource_key, True))
+                except Exception as e:  # pylint: disable=broad-except
+                    LOGGER.exception(
+                        "Unhandled error processing resource_key({:s})".format(
+                            str(resource_key)
+                        )
+                    )
+                    results.append((resource_key, e))
+        return results
+
+    @metered_subclass_method(METRICS_POOL)
+    def SubscribeState(
+        self, subscriptions: List[Tuple[str, float, float]]
+    ) -> List[Union[bool, Exception]]:
+        # TODO: IETF L3VPN does not support monitoring by now
+        return [False for _ in subscriptions]
+
+    @metered_subclass_method(METRICS_POOL)
+    def UnsubscribeState(
+        self, subscriptions: List[Tuple[str, float, float]]
+    ) -> List[Union[bool, Exception]]:
+        # TODO: IETF L3VPN does not support monitoring by now
+        return [False for _ in subscriptions]
+
+    def GetState(
+        self, blocking=False, terminate: Optional[threading.Event] = None
+    ) -> Iterator[Tuple[float, str, Any]]:
+        # TODO: IETF L3VPN does not support monitoring by now
+        return []
diff --git a/src/device/service/drivers/nce/nce_fan_client.py b/src/device/service/drivers/nce/nce_fan_client.py
new file mode 100644
index 0000000000000000000000000000000000000000..1c3523427ab5818b650a5eeecafc098b1c55662e
--- /dev/null
+++ b/src/device/service/drivers/nce/nce_fan_client.py
@@ -0,0 +1,94 @@
+# Copyright 2022-2025 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 logging
+from typing import Optional
+
+import requests
+from requests.auth import HTTPBasicAuth
+
+LOGGER = logging.getLogger(__name__)
+
+NCE_FAN_URL = "{:s}://{:s}:{:d}/restconf/v1/data"
+TIMEOUT = 30
+
+HTTP_OK_CODES = {
+    200,  # OK
+    201,  # Created
+    202,  # Accepted
+    204,  # No Content
+}
+
+MAPPING_STATUS = {
+    "DEVICEOPERATIONALSTATUS_UNDEFINED": 0,
+    "DEVICEOPERATIONALSTATUS_DISABLED": 1,
+    "DEVICEOPERATIONALSTATUS_ENABLED": 2,
+}
+
+MAPPING_DRIVER = {
+    "DEVICEDRIVER_UNDEFINED": 0,
+    "DEVICEDRIVER_OPENCONFIG": 1,
+    "DEVICEDRIVER_TRANSPORT_API": 2,
+    "DEVICEDRIVER_P4": 3,
+    "DEVICEDRIVER_IETF_NETWORK_TOPOLOGY": 4,
+    "DEVICEDRIVER_ONF_TR_532": 5,
+    "DEVICEDRIVER_XR": 6,
+    "DEVICEDRIVER_IETF_L2VPN": 7,
+    "DEVICEDRIVER_GNMI_OPENCONFIG": 8,
+    "DEVICEDRIVER_OPTICAL_TFS": 9,
+    "DEVICEDRIVER_IETF_ACTN": 10,
+    "DEVICEDRIVER_OC": 11,
+}
+
+HEADERS = {'Content-Type': 'application/json'}
+
+class NCEClient:
+    def __init__(
+        self,
+        address: str,
+        port: int,
+        scheme: str = "http",
+        username: Optional[str] = None,
+        password: Optional[str] = None,
+    ) -> None:
+        self._nce_fan_url = NCE_FAN_URL.format(scheme, address, port)
+        self._auth = None
+
+    def create_app_flow(self, app_flow_data: dict) -> None:
+        try:
+            app_data = app_flow_data["huawei-nce-app-flow:app-flows"]["applications"]
+            app_url = self._nce_fan_url + "/app-flows/apps"
+            LOGGER.info(f'Creating app: {app_data} URL: {app_url}')
+            requests.post(app_url, json=app_data, headers=HEADERS)
+
+            app_flow_data = {
+                "app-flow": app_flow_data["huawei-nce-app-flow:app-flows"]["app-flow"]
+            }
+            app_flow_url = self._nce_fan_url + "/app-flows"
+            LOGGER.info(f'Creating app flow: {app_flow_data} URL: {app_flow_url}')
+            requests.post(app_flow_url, json=app_flow_data, headers=HEADERS)
+        except requests.exceptions.ConnectionError:
+            raise Exception("faild to send post requests to NCE FAN")
+
+    def delete_app_flow(self, app_flow_name: str) -> None:
+        try:
+            app_url = self._nce_fan_url + f"/app-flows/apps/application={app_flow_name}"
+            LOGGER.info(f'Deleting app: {app_flow_name} URL: {app_url}')
+            requests.delete(app_url)
+
+            app_flow_url = self._nce_fan_url + f"/app-flows/app-flow={app_flow_name}"
+            LOGGER.info(f'Deleting app flow: {app_flow_name} URL: {app_flow_url}')
+            requests.delete(app_flow_url)
+        except requests.exceptions.ConnectionError:
+            raise Exception("faild to send delete request to NCE FAN")
diff --git a/src/device/tests/test_unitary_ietf_l3vpn.py b/src/device/tests/test_unitary_ietf_l3vpn.py
new file mode 100644
index 0000000000000000000000000000000000000000..728ca691332c8abee7b5d6f5ad6c151240e540ed
--- /dev/null
+++ b/src/device/tests/test_unitary_ietf_l3vpn.py
@@ -0,0 +1,345 @@
+import json
+from json import dumps
+
+import requests
+
+from device.service.drivers.ietf_l3vpn.driver import IetfL3VpnDriver
+from device.service.Tools import RESOURCE_ENDPOINTS
+
+settings = {
+    "endpoints": [
+        {
+            "uuid": "access-pe",
+            "name": "access-pe",
+            "type": "copper",
+            "ce-ip": "1.1.1.1",
+            "address_ip": "3.3.2.1",
+            "address_prefix": 24,
+            "location": "access",
+            "mtu": 1500,
+            "ipv4_lan_prefixes": [
+                {"lan": "128.32.10.0/24", "lan_tag": 10},
+                {"lan": "128.32.20.0/24", "lan_tag": 20},
+            ],
+        },
+        {
+            "uuid": "cloud-pe",
+            "name": "cloud-pe",
+            "type": "copper",
+            "ce-ip": "1.1.1.1",
+            "address_ip": "3.3.2.1",
+            "address_prefix": 24,
+            "location": "cloud",
+            "mtu": 1500,
+            "ipv4_lan_prefixes": [{"lan": "172.1.101.0/24", "lan_tag": 101}],
+        },
+    ],
+    "scheme": "http",
+    "username": "admin",
+    "password": "admin",
+    "base_url": "/restconf/v2/data",
+    "timeout": 120,
+    "verify": False,
+}
+
+post_request_data = []
+get_request_data = []
+
+
+def mock_post(*args, **kwargs):
+    post_request_data.append((args, kwargs))
+
+
+def mock_get(*args, **kwargs):
+    get_request_data.append((args, kwargs))
+
+
+driver = IetfL3VpnDriver(address="1.2.3.4", port=0, **settings)
+
+
+def test_connect(monkeypatch):
+    global post_request_data
+    global get_request_data
+    post_request_data = []
+    get_request_data = []
+    monkeypatch.setattr(requests, "post", mock_post)
+    monkeypatch.setattr(requests, "get", mock_get)
+
+    driver.Connect()
+    assert not post_request_data
+    assert len(get_request_data) == 1
+    assert get_request_data[0][0] == (
+        "http://1.2.3.4:0/restconf/data/ietf-l3vpn-svc:l3vpn-svc/vpn-services",
+    )
+    assert list(get_request_data[0][1].keys()) == ["timeout", "verify", "auth"]
+
+
+def test_GetConfig(monkeypatch):
+    global post_request_data
+    global get_request_data
+    post_request_data = []
+    get_request_data = []
+    monkeypatch.setattr(requests, "post", mock_post)
+    monkeypatch.setattr(requests, "get", mock_get)
+
+    resources_to_get = [RESOURCE_ENDPOINTS]
+    result_GetConfig = driver.GetConfig(resources_to_get)
+    assert result_GetConfig == [
+        (
+            "/endpoints/endpoint[access-pe]",
+            {
+                "uuid": "access-pe",
+                "name": "access-pe",
+                "type": "copper",
+                "location": "access",
+                "ce-ip": "1.1.1.1",
+                "address_ip": "3.3.2.1",
+                "address_prefix": 24,
+                "mtu": 1500,
+                "ipv4_lan_prefixes": [
+                    {"lan": "128.32.10.0/24", "lan_tag": 10},
+                    {"lan": "128.32.20.0/24", "lan_tag": 20},
+                ],
+            },
+        ),
+        (
+            "/endpoints/endpoint[cloud-pe]",
+            {
+                "uuid": "cloud-pe",
+                "name": "cloud-pe",
+                "type": "copper",
+                "location": "cloud",
+                "ce-ip": "1.1.1.1",
+                "address_ip": "3.3.2.1",
+                "address_prefix": 24,
+                "mtu": 1500,
+                "ipv4_lan_prefixes": [{"lan": "172.1.101.0/24", "lan_tag": 101}],
+            },
+        ),
+    ]
+
+
+def test_SetConfig(monkeypatch):
+    global post_request_data
+    global get_request_data
+    post_request_data = []
+    get_request_data = []
+    monkeypatch.setattr(requests, "post", mock_post)
+    monkeypatch.setattr(requests, "get", mock_get)
+
+    resources = [
+        (
+            "/services/service[vpn_A]",
+            json.dumps(
+                {
+                    "uuid": "vpn_A",
+                    "src_device_name": "ip-net-controller",
+                    "src_endpoint_name": settings["endpoints"][0]["name"],
+                    "src_site_location": settings["endpoints"][0]["location"],
+                    "src_ipv4_lan_prefixes": settings["endpoints"][0][
+                        "ipv4_lan_prefixes"
+                    ],
+                    "src_ce_address": settings["endpoints"][0]["ce-ip"],
+                    "src_pe_address": settings["endpoints"][0]["address_ip"],
+                    "src_ce_pe_network_prefix": settings["endpoints"][0][
+                        "address_prefix"
+                    ],
+                    "src_mtu": settings["endpoints"][0]["mtu"],
+                    "dst_device_name": "ip-net-controller",
+                    "dst_endpoint_name": settings["endpoints"][1]["name"],
+                    "dst_site_location": settings["endpoints"][1]["location"],
+                    "dst_ipv4_lan_prefixes": settings["endpoints"][1][
+                        "ipv4_lan_prefixes"
+                    ],
+                    "dst_ce_address": settings["endpoints"][1]["ce-ip"],
+                    "dst_pe_address": settings["endpoints"][1]["address_ip"],
+                    "dst_ce_pe_network_prefix": settings["endpoints"][1][
+                        "address_prefix"
+                    ],
+                    "dst_mtu": settings["endpoints"][1]["mtu"],
+                }
+            ),
+        )
+    ]
+    result_SetConfig = driver.SetConfig(resources)
+    assert result_SetConfig == [("/services/service[vpn_A]", True)]
+    assert len(get_request_data) == 1
+    assert get_request_data[0][0] == (
+        "http://1.2.3.4:0/restconf/data/ietf-l3vpn-svc:l3vpn-svc/vpn-services/vpn-service=vpn_A",
+    )
+    assert len(post_request_data) == 1
+    assert post_request_data[0][0] == (
+        "http://1.2.3.4:0/restconf/data/ietf-l3vpn-svc:l3vpn-svc/vpn-services/vpn-services",
+    )
+    assert post_request_data[0][1]["json"] == {
+        "ietf-l3vpn-svc:l3vpn-svc": {
+            "vpn-services": {"vpn-service": [{"vpn-id": "vpn_A"}]},
+            "sites": {
+                "site": [
+                    {
+                        "site-id": "site_access",
+                        "management": {"type": "ietf-l3vpn-svc:customer-managed"},
+                        "locations": {"location": [{"location-id": "access"}]},
+                        "devices": {
+                            "device": [
+                                {
+                                    "device-id": "ip-net-controller",
+                                    "location": "access",
+                                }
+                            ]
+                        },
+                        "routing-protocols": {
+                            "routing-protocol": [
+                                {
+                                    "type": "ietf-l3vpn-svc:static",
+                                    "static": {
+                                        "cascaded-lan-prefixes": {
+                                            "ipv4-lan-prefixes": [
+                                                {
+                                                    "lan": "128.32.10.0/24",
+                                                    "lan-tag": 10,
+                                                    "next-hop": "3.3.2.1",
+                                                },
+                                                {
+                                                    "lan": "128.32.20.0/24",
+                                                    "lan-tag": 20,
+                                                    "next-hop": "3.3.2.1",
+                                                },
+                                            ]
+                                        }
+                                    },
+                                }
+                            ]
+                        },
+                        "site-network-accesses": {
+                            "site-network-access": [
+                                {
+                                    "site-network-access-id": "access-pe",
+                                    "site-network-access-type": "ietf-l3vpn-svc:multipoint",
+                                    "device-reference": "ip-net-controller",
+                                    "vpn-attachment": {
+                                        "vpn-id": "vpn_A",
+                                        "site-role": "ietf-l3vpn-svc:hub-role",
+                                    },
+                                    "ip-connection": {
+                                        "ipv4": {
+                                            "address-allocation-type": "ietf-l3vpn-svc:static-address",
+                                            "addresses": {
+                                                "provider-address": "3.3.2.1",
+                                                "customer-address": "1.1.1.1",
+                                                "prefix-length": 24,
+                                            },
+                                        }
+                                    },
+                                    "service": {
+                                        "svc-mtu": 1500,
+                                        "svc-input-bandwidth": 1000000000,
+                                        "svc-output-bandwidth": 1000000000,
+                                        "qos": {
+                                            "qos-profile": {
+                                                "classes": {
+                                                    "class": [
+                                                        {
+                                                            "class-id": "src_qos_profile",
+                                                            "direction": (
+                                                                "ietf-l3vpn-svc:both",
+                                                            ),
+                                                            "latency": {
+                                                                "latency-boundary": 10
+                                                            },
+                                                            "bandwidth": {
+                                                                "guaranteed-bw-percent": 100
+                                                            },
+                                                        }
+                                                    ]
+                                                }
+                                            }
+                                        },
+                                    },
+                                }
+                            ]
+                        },
+                    },
+                    {
+                        "site-id": "site_cloud",
+                        "management": {"type": "ietf-l3vpn-svc:customer-managed"},
+                        "locations": {"location": [{"location-id": "cloud"}]},
+                        "devices": {
+                            "device": [
+                                {
+                                    "device-id": "ip-net-controller",
+                                    "location": "cloud",
+                                }
+                            ]
+                        },
+                        "routing-protocols": {
+                            "routing-protocol": [
+                                {
+                                    "type": "ietf-l3vpn-svc:static",
+                                    "static": {
+                                        "cascaded-lan-prefixes": {
+                                            "ipv4-lan-prefixes": [
+                                                {
+                                                    "lan": "172.1.101.0/24",
+                                                    "lan-tag": 101,
+                                                    "next-hop": "3.3.2.1",
+                                                }
+                                            ]
+                                        }
+                                    },
+                                }
+                            ]
+                        },
+                        "site-network-accesses": {
+                            "site-network-access": [
+                                {
+                                    "site-network-access-id": "cloud-pe",
+                                    "site-network-access-type": "ietf-l3vpn-svc:multipoint",
+                                    "device-reference": "ip-net-controller",
+                                    "vpn-attachment": {
+                                        "vpn-id": "vpn_A",
+                                        "site-role": "ietf-l3vpn-svc:spoke-role",
+                                    },
+                                    "ip-connection": {
+                                        "ipv4": {
+                                            "address-allocation-type": "ietf-l3vpn-svc:static-address",
+                                            "addresses": {
+                                                "provider-address": "3.3.2.1",
+                                                "customer-address": "1.1.1.1",
+                                                "prefix-length": 24,
+                                            },
+                                        }
+                                    },
+                                    "service": {
+                                        "svc-mtu": 1500,
+                                        "svc-input-bandwidth": 1000000000,
+                                        "svc-output-bandwidth": 1000000000,
+                                        "qos": {
+                                            "qos-profile": {
+                                                "classes": {
+                                                    "class": [
+                                                        {
+                                                            "class-id": "dst_qos_profile",
+                                                            "direction": (
+                                                                "ietf-l3vpn-svc:both",
+                                                            ),
+                                                            "latency": {
+                                                                "latency-boundary": 10
+                                                            },
+                                                            "bandwidth": {
+                                                                "guaranteed-bw-percent": 100
+                                                            },
+                                                        }
+                                                    ]
+                                                }
+                                            }
+                                        },
+                                    },
+                                }
+                            ]
+                        },
+                    },
+                ]
+            },
+        }
+    }
diff --git a/src/nbi/service/__main__.py b/src/nbi/service/__main__.py
index 71df0517aa688c106d8d0fe544f5f6b1af5a58f3..1d470f4eac30795e2272c9145baf947f3c982ba5 100644
--- a/src/nbi/service/__main__.py
+++ b/src/nbi/service/__main__.py
@@ -31,6 +31,7 @@ from .rest_server.nbi_plugins.ietf_network_slice import register_ietf_nss
 from .rest_server.nbi_plugins.ietf_acl import register_ietf_acl
 from .rest_server.nbi_plugins.qkd_app import register_qkd_app
 from .rest_server.nbi_plugins.tfs_api import register_tfs_api
+from .rest_server.nbi_plugins import register_restconf
 from .context_subscription import register_context_subscription
 
 terminate = threading.Event()
@@ -79,6 +80,7 @@ def main():
     register_ietf_acl(rest_server)
     register_qkd_app(rest_server)
     register_tfs_api(rest_server)
+    register_restconf(rest_server)
     rest_server.start()
 
     register_context_subscription()
diff --git a/src/nbi/service/rest_server/nbi_plugins/__init__.py b/src/nbi/service/rest_server/nbi_plugins/__init__.py
index 53d5157f750bfb085125cbd33faff1cec5924e14..9b5d7920db49bab6d456aba186e6500142aad5b2 100644
--- a/src/nbi/service/rest_server/nbi_plugins/__init__.py
+++ b/src/nbi/service/rest_server/nbi_plugins/__init__.py
@@ -12,3 +12,27 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+from flask.json import jsonify
+from flask_restful import Resource
+
+from nbi.service.rest_server.RestServer import RestServer
+
+from .tools.HttpStatusCodes import HTTP_CREATED
+
+URL_PREFIX = "/restconf/data"
+
+
+class BaseServer(Resource):
+    def post(self):
+        response = jsonify({})
+        response.status_code = HTTP_CREATED
+        return response
+
+
+def _add_resource(rest_server: RestServer, resource: Resource, *urls, **kwargs):
+    urls = [(URL_PREFIX + url) for url in urls]
+    rest_server.add_resource(resource, *urls, **kwargs)
+
+
+def register_restconf(rest_server: RestServer):
+    _add_resource(rest_server, BaseServer, "")
diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/L3VPN_Service.py b/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/L3VPN_Service.py
index 97364dff8606f1af48bab362b94b968561792411..bf3f8aabca1c04260d32a4163ec2686931f520fc 100644
--- a/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/L3VPN_Service.py
+++ b/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/L3VPN_Service.py
@@ -26,7 +26,7 @@ from ..tools.HttpStatusCodes import HTTP_GATEWAYTIMEOUT, HTTP_NOCONTENT, HTTP_OK
 LOGGER = logging.getLogger(__name__)
 
 class L3VPN_Service(Resource):
-    @HTTP_AUTH.login_required
+    # @HTTP_AUTH.login_required
     def get(self, vpn_id : str):
         LOGGER.debug('VPN_Id: {:s}'.format(str(vpn_id)))
         LOGGER.debug('Request: {:s}'.format(str(request)))
@@ -52,7 +52,7 @@ class L3VPN_Service(Resource):
             response.status_code = HTTP_SERVERERROR
         return response
 
-    @HTTP_AUTH.login_required
+    # @HTTP_AUTH.login_required
     def delete(self, vpn_id : str):
         LOGGER.debug('VPN_Id: {:s}'.format(str(vpn_id)))
         LOGGER.debug('Request: {:s}'.format(str(request)))
diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/L3VPN_Services.py b/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/L3VPN_Services.py
index 98d950952702d5cf1df8aa29edc50683e56a296e..47f6d5726225350976a67eeaacda64ceb32f0d7f 100644
--- a/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/L3VPN_Services.py
+++ b/src/nbi/service/rest_server/nbi_plugins/ietf_l3vpn/L3VPN_Services.py
@@ -26,11 +26,11 @@ from .YangValidator import YangValidator
 LOGGER = logging.getLogger(__name__)
 
 class L3VPN_Services(Resource):
-    @HTTP_AUTH.login_required
+    # @HTTP_AUTH.login_required
     def get(self):
         return {}
 
-    @HTTP_AUTH.login_required
+    # @HTTP_AUTH.login_required
     def post(self):
         if not request.is_json: raise UnsupportedMediaType('JSON payload is required')
         request_data : Dict = request.json
diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/NSS_Service.py b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/NSS_Service.py
index e25270d3601ffa1cfdffa68a98305e3646602001..8f6dc86609f8c0e4d51fa02c64ab7c59a377395a 100644
--- a/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/NSS_Service.py
+++ b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/NSS_Service.py
@@ -1,4 +1,4 @@
-# Copyright 2022-2024 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/)
+# 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.
@@ -13,47 +13,61 @@
 # limitations under the License.
 
 import logging
+
 from flask.json import jsonify
 from flask_restful import Resource
+
 from common.proto.context_pb2 import SliceStatusEnum
 from common.tools.context_queries.Slice import get_slice_by_uuid
 from common.tools.grpc.Tools import grpc_message_to_json
 from context.client.ContextClient import ContextClient
 from slice.client.SliceClient import SliceClient
+
 from ..tools.Authentication import HTTP_AUTH
-from ..tools.HttpStatusCodes import HTTP_GATEWAYTIMEOUT, HTTP_NOCONTENT, HTTP_OK, HTTP_SERVERERROR
+from ..tools.HttpStatusCodes import (
+    HTTP_GATEWAYTIMEOUT,
+    HTTP_NOCONTENT,
+    HTTP_OK,
+    HTTP_SERVERERROR,
+)
 
 LOGGER = logging.getLogger(__name__)
 
+
 class NSS_Service(Resource):
-    @HTTP_AUTH.login_required
-    def get(self, slice_id : str):
-        LOGGER.debug('GET Slice ID: {:s}'.format(str(slice_id)))
+    # @HTTP_AUTH.login_required
+    def get(self, slice_id: str):
+        LOGGER.debug("GET Slice ID: {:s}".format(str(slice_id)))
         try:
             context_client = ContextClient()
 
             target = get_slice_by_uuid(context_client, slice_id, rw_copy=True)
             if target is None:
-                raise Exception('Slice({:s}) not found in database'.format(str(slice_id)))
+                raise Exception(
+                    "Slice({:s}) not found in database".format(str(slice_id))
+                )
 
-            if target.slice_id.slice_uuid.uuid != slice_id: # pylint: disable=no-member
-                raise Exception('Slice retrieval failed. Wrong Slice Id was returned')
+            if target.slice_id.slice_uuid.uuid != slice_id:  # pylint: disable=no-member
+                raise Exception("Slice retrieval failed. Wrong Slice Id was returned")
 
             slice_ready_status = SliceStatusEnum.SLICESTATUS_ACTIVE
-            slice_status = target.slice_status.slice_status # pylint: disable=no-member
+            slice_status = target.slice_status.slice_status  # pylint: disable=no-member
             response = jsonify(grpc_message_to_json(target))
-            response.status_code = HTTP_OK if slice_status == slice_ready_status else HTTP_GATEWAYTIMEOUT
+            response.status_code = (
+                HTTP_OK if slice_status == slice_ready_status else HTTP_GATEWAYTIMEOUT
+            )
 
-        except Exception as e: # pylint: disable=broad-except
-            LOGGER.exception('Something went wrong Retrieving Slice({:s})'.format(str(slice_id)))
-            response = jsonify({'error': str(e)})
+        except Exception as e:  # pylint: disable=broad-except
+            LOGGER.exception(
+                "Something went wrong Retrieving Slice({:s})".format(str(slice_id))
+            )
+            response = jsonify({"error": str(e)})
             response.status_code = HTTP_SERVERERROR
         return response
 
-
-    @HTTP_AUTH.login_required
-    def delete(self, slice_id : str):
-        LOGGER.debug('DELETE Slice ID: {:s}'.format(str(slice_id)))
+    # @HTTP_AUTH.login_required
+    def delete(self, slice_id: str):
+        LOGGER.debug("DELETE Slice ID: {:s}".format(str(slice_id)))
         try:
             context_client = ContextClient()
             target = get_slice_by_uuid(context_client, slice_id)
@@ -62,17 +76,25 @@ class NSS_Service(Resource):
             response.status_code = HTTP_OK
 
             if target is None:
-                LOGGER.warning('Slice({:s}) not found in database. Nothing done.'.format(str(slice_id)))
+                LOGGER.warning(
+                    "Slice({:s}) not found in database. Nothing done.".format(
+                        str(slice_id)
+                    )
+                )
                 response.status_code = HTTP_NOCONTENT
             else:
-                if target.slice_id.slice_uuid.uuid != slice_id:  # pylint: disable=no-member
-                    raise Exception('Slice retrieval failed. Wrong Slice Id was returned')
+                if target.slice_id.slice_uuid.uuid != slice_id and target.name != slice_id:  # pylint: disable=no-member
+                    raise Exception(
+                        "Slice retrieval failed. Wrong Slice Id was returned"
+                    )
                 slice_client = SliceClient()
                 slice_client.DeleteSlice(target.slice_id)
                 LOGGER.debug(f"Slice({slice_id}) successfully deleted")
 
         except Exception as e:  # pylint: disable=broad-except
-            LOGGER.exception('Something went wrong Deleting Slice({:s})'.format(str(slice_id)))
-            response = jsonify({'error': str(e)})
+            LOGGER.exception(
+                "Something went wrong Deleting Slice({:s})".format(str(slice_id))
+            )
+            response = jsonify({"error": str(e)})
             response.status_code = HTTP_SERVERERROR
-        return response
\ No newline at end of file
+        return response
diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/NSS_Service_Match_Criteria.py b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/NSS_Service_Match_Criteria.py
new file mode 100644
index 0000000000000000000000000000000000000000..3e1c9f73f97f0df8a2b271cb34a4852e983e77a1
--- /dev/null
+++ b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/NSS_Service_Match_Criteria.py
@@ -0,0 +1,59 @@
+# 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 logging
+from typing import Dict
+
+from flask import request
+from flask.json import jsonify
+from flask_restful import Resource
+from werkzeug.exceptions import UnsupportedMediaType
+
+from context.client.ContextClient import ContextClient
+from slice.client.SliceClient import SliceClient
+
+from ..tools.Authentication import HTTP_AUTH
+from ..tools.HttpStatusCodes import (
+    HTTP_CREATED,
+)
+from .ietf_slice_handler import IETFSliceHandler
+
+LOGGER = logging.getLogger(__name__)
+
+
+class NSS_Service_Match_Criteria(Resource):
+    # @HTTP_AUTH.login_required
+    def get(self):
+        response = jsonify({"message": "All went well!"})
+        # TODO Return list of current network-slice-services
+        return response
+
+    # @HTTP_AUTH.login_required
+    def post(self, slice_id: str, sdp_id: str):
+        if not request.is_json:
+            raise UnsupportedMediaType("JSON payload is required")
+        request_data: Dict = request.json
+        context_client = ContextClient()
+        slice_request = IETFSliceHandler.create_match_criteria(
+            request_data, slice_id, sdp_id, context_client
+        )
+        slice_client = SliceClient()
+        slice_client.UpdateSlice(slice_request)
+        slice_request = IETFSliceHandler.copy_candidate_ietf_slice_data_to_running(
+            slice_id, context_client
+        )
+        _ = context_client.SetSlice(slice_request)
+
+        response = jsonify({})
+        response.status_code = HTTP_CREATED
+        return response
diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/NSS_Service_Match_Criterion.py b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/NSS_Service_Match_Criterion.py
new file mode 100644
index 0000000000000000000000000000000000000000..8fb8adfd98e461a43f2dc24121b84a59aaabbd6b
--- /dev/null
+++ b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/NSS_Service_Match_Criterion.py
@@ -0,0 +1,48 @@
+# 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 logging
+
+from flask.json import jsonify
+from flask_restful import Resource
+
+from context.client.ContextClient import ContextClient
+
+from ..tools.Authentication import HTTP_AUTH
+from ..tools.HttpStatusCodes import (
+    HTTP_CREATED,
+)
+from .ietf_slice_handler import IETFSliceHandler
+
+LOGGER = logging.getLogger(__name__)
+
+
+class NSS_Service_Match_Criterion(Resource):
+    # @HTTP_AUTH.login_required
+    def get(self):
+        response = jsonify({"message": "All went well!"})
+        # TODO Return list of current network-slice-services
+        return response
+
+    # @HTTP_AUTH.login_required
+    def delete(self, slice_id: str, sdp_id: str, match_criterion_id: str):
+        context_client = ContextClient()
+        slice_request = IETFSliceHandler.delete_match_criteria(
+            slice_id, sdp_id, int(match_criterion_id), context_client
+        )
+        context_client = ContextClient()
+        _ = context_client.SetSlice(slice_request)
+
+        response = jsonify({})
+        response.status_code = HTTP_CREATED
+        return response
diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/NSS_Services.py b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/NSS_Services.py
index 11a73141d6bd05db851d3019903e5a6db2f5c2d6..8398917a2c5d8c553efe59551962271d91759e9e 100644
--- a/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/NSS_Services.py
+++ b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/NSS_Services.py
@@ -1,4 +1,4 @@
-# Copyright 2022-2024 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/)
+# 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.
@@ -11,112 +11,44 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
-import json
 import logging
-import ssl
-import uuid
 from typing import Dict
+
+from flask import request
 from flask.json import jsonify
 from flask_restful import Resource
-from flask import request
-
-from common.Constants import DEFAULT_CONTEXT_NAME
-from common.proto.context_pb2 import Slice, SliceStatusEnum, EndPointId, Constraint
-from common.tools.grpc.Tools import grpc_message_to_json
-from ..tools.Authentication import HTTP_AUTH
-from ..tools.HttpStatusCodes import HTTP_BADREQUEST, HTTP_OK, HTTP_CREATED, HTTP_SERVERERROR
 from werkzeug.exceptions import UnsupportedMediaType
 
+from context.client.ContextClient import ContextClient
 from slice.client.SliceClient import SliceClient
-from .bindings import load_json_data
-from .bindings.network_slice_services import NetworkSliceServices
+
+from ..tools.HttpStatusCodes import HTTP_CREATED, HTTP_OK
+from .ietf_slice_handler import IETFSliceHandler
 
 LOGGER = logging.getLogger(__name__)
 
+
 class NSS_Services(Resource):
-    @HTTP_AUTH.login_required
-    def get(self):    
-        response = jsonify({"message": "All went well!"})
-        # TODO Return list of current network-slice-services
+    # @HTTP_AUTH.login_required
+    def get(self):
+        context_client = ContextClient()
+        ietf_slices = IETFSliceHandler.get_all_ietf_slices(context_client)
+        response = jsonify(ietf_slices)
+        response.status_code = HTTP_OK
         return response
 
-    @HTTP_AUTH.login_required
+    # @HTTP_AUTH.login_required
     def post(self):
         if not request.is_json:
-            raise UnsupportedMediaType('JSON payload is required')
-        request_data = json.dumps(request.json)
+            raise UnsupportedMediaType("JSON payload is required")
+        request_data: Dict = request.json
+        context_client = ContextClient()
+        slice_request = IETFSliceHandler.create_slice_service(
+            request_data, context_client
+        )
+        slice_client = SliceClient()
+        slice_client.CreateSlice(slice_request)
+
         response = jsonify({})
         response.status_code = HTTP_CREATED
-
-        slices: NetworkSliceServices = load_json_data(request_data, NetworkSliceServices)[0]
-        for ietf_slice in slices.slice_service:
-            slice_request: Slice = Slice()
-            # Meta information
-            # TODO implement name and owner based on "tags"
-            slice_request.slice_id.context_id.context_uuid.uuid = DEFAULT_CONTEXT_NAME
-            slice_request.slice_id.slice_uuid.uuid = ietf_slice.service_id()
-            # TODO map with admin status of IETF Slice
-            slice_request.slice_status.slice_status = SliceStatusEnum.SLICESTATUS_PLANNED
-
-            list_endpoints = []
-            for sdp in ietf_slice.sdps().sdp:
-                endpoint = EndPointId()
-                endpoint.topology_id.context_id.context_uuid.uuid = DEFAULT_CONTEXT_NAME
-                endpoint.device_id.device_uuid.uuid = sdp.node_id()
-                endpoint.endpoint_uuid.uuid = sdp.sdp_id()
-                list_endpoints.append(endpoint)
-            slice_request.slice_endpoint_ids.extend(list_endpoints)
-
-            # TODO Map connectivity_groups and connectivity constructs to real connections
-            LOGGER.debug(f"Connection groups detected: {len(ietf_slice.connection_groups().connection_group())}")
-            list_constraints = []
-            for cg in ietf_slice.connection_groups().connection_group:
-                for cc in cg.connectivity_construct:
-                    if cc.slo_sle_policy.custom:
-                        with cc.slo_sle_policy.custom as slo:
-                            for metric_bound in slo.service_slo_sle_policy().metric_bounds().metric_bound:
-                                metric_type = str(metric_bound.metric_type()).casefold()
-                                if metric_type == "service-slo-two-way-bandwidth":  # TODO fix to two way!
-                                    constraint = Constraint()
-                                    metric_unit = metric_bound.metric_unit().casefold()
-                                    capacity = float(metric_bound.bound())  # Assuming capacity already in Gbps
-                                    if metric_unit == "mbps":
-                                        capacity /= 1E3
-                                    elif metric_unit != "gbps":
-                                        LOGGER.warning(f"Invalided metric unit ({metric_bound.metric_unit()}), must be Mbps or Gbps")
-                                        response.status_code = HTTP_SERVERERROR
-                                        return response
-                                    constraint.sla_capacity.capacity_gbps = capacity
-                                    list_constraints.append(constraint)
-
-                                elif metric_type == "service-slo-one-way-delay":
-                                    if metric_bound.metric_unit().casefold() == "ms":
-                                        latency = int(metric_bound.bound())
-                                    else:
-                                        LOGGER.warning(f"Invalided metric unit ({metric_bound.metric_unit()}), must be \"ms\" ")
-                                        response.status_code = HTTP_SERVERERROR
-                                        return response
-                                    constraint = Constraint()
-                                    constraint.sla_latency.e2e_latency_ms = latency
-                                    list_constraints.append(constraint)
-
-                                elif metric_type == "service-slo-availability":
-                                    availability = float(metric_bound.bound())
-                                    if availability > 100.0 or availability < 0.0:
-                                        raise Exception(f'Slice SLO availability ({availability}) must be constrained [0,100]')
-                                    constraint = Constraint()
-                                    constraint.sla_availability.availability = availability
-                                    # TODO not really necessary, remove after OFC2023
-                                    constraint.sla_availability.num_disjoint_paths = 0
-                                    constraint.sla_availability.all_active = False
-                                    list_constraints.append(constraint)
-
-            slice_request.slice_constraints.extend(list_constraints)
-            LOGGER.debug(grpc_message_to_json(slice_request))  # TODO remove
-            # TODO adding owner, needs to be recoded after updating the bindings
-            owner = request.json["data"]["ietf-network-slice-service:network-slice-services"]["slice-service"][0]["service-tags"][0]["value"]
-            slice_request.slice_owner.owner_string = owner
-            slice_request.slice_owner.owner_uuid.uuid = str(uuid.uuid5(uuid.NAMESPACE_DNS, owner))
-            slice_client = SliceClient()
-            slice_client.CreateSlice(slice_request)
         return response
diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/NSS_Services_Connection_Group.py b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/NSS_Services_Connection_Group.py
new file mode 100644
index 0000000000000000000000000000000000000000..0309c6ac475dec59d3219be79792fdef81e3d330
--- /dev/null
+++ b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/NSS_Services_Connection_Group.py
@@ -0,0 +1,75 @@
+# 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 logging
+from typing import Dict
+
+from flask import request
+from flask.json import jsonify
+from flask_restful import Resource
+from werkzeug.exceptions import UnsupportedMediaType
+
+from context.client.ContextClient import ContextClient
+from slice.client.SliceClient import SliceClient
+
+from ..tools.Authentication import HTTP_AUTH
+from ..tools.HttpStatusCodes import HTTP_CREATED
+from .ietf_slice_handler import IETFSliceHandler
+
+LOGGER = logging.getLogger(__name__)
+
+
+class NSS_Service_Connection_Group(Resource):
+    # @HTTP_AUTH.login_required
+    def get(self):
+        response = jsonify({"message": "All went well!"})
+        # TODO Return list of current network-slice-services
+        return response
+
+    # @HTTP_AUTH.login_required
+    def put(self, slice_id: str, connection_group_id: str):
+        if not request.is_json:
+            raise UnsupportedMediaType("JSON payload is required")
+        request_data: Dict = request.json
+
+        context_client = ContextClient()
+        slice_request = IETFSliceHandler.update_connection_group(
+            slice_id, request_data, context_client
+        )
+        slice_client = SliceClient()
+        slice_client.UpdateSlice(slice_request)
+        slice_request = IETFSliceHandler.copy_candidate_ietf_slice_data_to_running(
+            slice_id, context_client
+        )
+        _ = context_client.SetSlice(slice_request)
+
+        response = jsonify({})
+        response.status_code = HTTP_CREATED
+        return response
+
+    # @HTTP_AUTH.login_required
+    def delete(self, slice_id: str, connection_group_id: str):
+        context_client = ContextClient()
+        slice_request = IETFSliceHandler.delete_connection_group(
+            slice_id, connection_group_id, context_client
+        )
+        slice_client = SliceClient()
+        slice_client.UpdateSlice(slice_request)
+        slice_request = IETFSliceHandler.copy_candidate_ietf_slice_data_to_running(
+            slice_id, context_client
+        )
+        _ = context_client.SetSlice(slice_request)
+
+        response = jsonify({})
+        response.status_code = HTTP_CREATED
+        return response
diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/NSS_Services_Connection_Groups.py b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/NSS_Services_Connection_Groups.py
new file mode 100644
index 0000000000000000000000000000000000000000..bee8349ef1949f0eb7f633ca4cbe6de6de1abbd6
--- /dev/null
+++ b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/NSS_Services_Connection_Groups.py
@@ -0,0 +1,52 @@
+# 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 logging
+from typing import Dict
+
+from flask import request
+from flask.json import jsonify
+from flask_restful import Resource
+from werkzeug.exceptions import UnsupportedMediaType
+
+from context.client.ContextClient import ContextClient
+
+from ..tools.Authentication import HTTP_AUTH
+from ..tools.HttpStatusCodes import HTTP_CREATED
+from .ietf_slice_handler import IETFSliceHandler
+
+LOGGER = logging.getLogger(__name__)
+
+
+class NSS_Service_Connection_Groups(Resource):
+    # @HTTP_AUTH.login_required
+    def get(self):
+        response = jsonify({"message": "All went well!"})
+        # TODO Return list of current network-slice-services
+        return response
+
+    # @HTTP_AUTH.login_required
+    def post(self, slice_id: str):
+        if not request.is_json:
+            raise UnsupportedMediaType("JSON payload is required")
+        request_data: Dict = request.json
+
+        context_client = ContextClient()
+        slice_request = IETFSliceHandler.create_connection_group(
+            request_data, slice_id, context_client
+        )
+        _ = context_client.SetSlice(slice_request)
+
+        response = jsonify({})
+        response.status_code = HTTP_CREATED
+        return response
diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/NSS_Services_SDP.py b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/NSS_Services_SDP.py
new file mode 100644
index 0000000000000000000000000000000000000000..f1d04a858907d016dc39a5a15a0d2771e25310af
--- /dev/null
+++ b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/NSS_Services_SDP.py
@@ -0,0 +1,45 @@
+# 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 logging
+from typing import Dict
+
+from flask import request
+from flask.json import jsonify
+from flask_restful import Resource
+from werkzeug.exceptions import UnsupportedMediaType
+
+from context.client.ContextClient import ContextClient
+
+from ..tools.HttpStatusCodes import HTTP_OK
+from .ietf_slice_handler import IETFSliceHandler
+
+LOGGER = logging.getLogger(__name__)
+
+
+class NSS_Service_SDP(Resource):
+    # @HTTP_AUTH.login_required
+    def get(self):
+        response = jsonify({"message": "All went well!"})
+        # TODO Return list of current network-slice-services
+        return response
+
+    # @HTTP_AUTH.login_required
+    def delete(self, slice_id: str, sdp_id: str):
+        context_client = ContextClient()
+        slice_request = IETFSliceHandler.delete_sdp(slice_id, sdp_id, context_client)
+        _ = context_client.SetSlice(slice_request)
+
+        response = jsonify({})
+        response.status_code = HTTP_OK
+        return response
diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/NSS_Services_SDPs.py b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/NSS_Services_SDPs.py
new file mode 100644
index 0000000000000000000000000000000000000000..8a3fb8c4210b790dd25f9c0f8467b79ef5a86bc9
--- /dev/null
+++ b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/NSS_Services_SDPs.py
@@ -0,0 +1,51 @@
+# 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 logging
+from typing import Dict
+
+from flask import request
+from flask.json import jsonify
+from flask_restful import Resource
+from werkzeug.exceptions import UnsupportedMediaType
+
+from context.client.ContextClient import ContextClient
+
+from ..tools.HttpStatusCodes import HTTP_CREATED
+from .ietf_slice_handler import IETFSliceHandler
+
+LOGGER = logging.getLogger(__name__)
+
+
+class NSS_Service_SDPs(Resource):
+    # @HTTP_AUTH.login_required
+    def get(self):
+        response = jsonify({"message": "All went well!"})
+        # TODO Return list of current network-slice-services
+        return response
+
+    # @HTTP_AUTH.login_required
+    def post(self, slice_id: str):
+        if not request.is_json:
+            raise UnsupportedMediaType("JSON payload is required")
+        request_data: Dict = request.json
+
+        context_client = ContextClient()
+        slice_request = IETFSliceHandler.create_sdp(
+            request_data, slice_id, context_client
+        )
+        _ = context_client.SetSlice(slice_request)
+
+        response = jsonify({})
+        response.status_code = HTTP_CREATED
+        return response
diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/YangValidator.py b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/YangValidator.py
new file mode 100644
index 0000000000000000000000000000000000000000..77071f7f7a72ad7d46e34f118a87dc2280a2a24c
--- /dev/null
+++ b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/YangValidator.py
@@ -0,0 +1,36 @@
+# 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 libyang, os
+from typing import Dict, Optional
+
+YANG_DIR = os.path.join(os.path.dirname(__file__), 'yang')
+
+class YangValidator:
+    def __init__(self, module_name : str) -> None:
+        self._yang_context = libyang.Context(YANG_DIR)
+        self._yang_module  = self._yang_context.load_module(module_name)
+        self._yang_module.feature_enable_all()
+
+    def parse_to_dict(self, message : Dict) -> Dict:
+        dnode : Optional[libyang.DNode] = self._yang_module.parse_data_dict(
+            message, validate_present=True, validate=True, strict=True
+        )
+        if dnode is None: raise Exception('Unable to parse Message({:s})'.format(str(message)))
+        message = dnode.print_dict()
+        dnode.free()
+        return message
+
+    def destroy(self) -> None:
+        self._yang_context.destroy()
diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/__init__.py b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/__init__.py
index e900c27e96aafc248e5db1bec303cb25b5a0f2d7..db76b3b911c971df8ab81b1710f4ac80e4ccb3ad 100644
--- a/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/__init__.py
+++ b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/__init__.py
@@ -1,4 +1,4 @@
-# Copyright 2022-2024 ETSI SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/)
+# 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.
@@ -16,16 +16,60 @@
 # Ref: https://datatracker.ietf.org/doc/draft-ietf-teas-ietf-network-slice-nbi-yang/
 
 from flask_restful import Resource
+
 from nbi.service.rest_server.RestServer import RestServer
-from .NSS_Services import NSS_Services
+
 from .NSS_Service import NSS_Service
+from .NSS_Service_Match_Criteria import NSS_Service_Match_Criteria
+from .NSS_Service_Match_Criterion import NSS_Service_Match_Criterion
+from .NSS_Services import NSS_Services
+from .NSS_Services_Connection_Group import NSS_Service_Connection_Group
+from .NSS_Services_Connection_Groups import NSS_Service_Connection_Groups
+from .NSS_Services_SDP import NSS_Service_SDP
+from .NSS_Services_SDPs import NSS_Service_SDPs
+
+URL_PREFIX = "/restconf/data/ietf-network-slice-service"
 
-URL_PREFIX = '/restconf/data/ietf-network-slice-service:ietf-nss'
 
-def _add_resource(rest_server : RestServer, resource : Resource, *urls, **kwargs):
+def _add_resource(rest_server: RestServer, resource: Resource, *urls, **kwargs):
     urls = [(URL_PREFIX + url) for url in urls]
     rest_server.add_resource(resource, *urls, **kwargs)
 
-def register_ietf_nss(rest_server : RestServer):
-    _add_resource(rest_server, NSS_Services, '/network-slice-services')
-    _add_resource(rest_server, NSS_Service, '/network-slice-services/slice-service=<string:slice_id>')
+
+def register_ietf_nss(rest_server: RestServer):
+    _add_resource(rest_server, NSS_Services, ":network-slice-services")
+    _add_resource(
+        rest_server,
+        NSS_Service,
+        ":network-slice-services/slice-service=<string:slice_id>",
+    )
+    _add_resource(
+        rest_server,
+        NSS_Service_SDPs,
+        ":network-slice-services/slice-service=<string:slice_id>/sdps",
+    )
+    _add_resource(
+        rest_server,
+        NSS_Service_SDP,
+        ":network-slice-services/slice-service=<string:slice_id>/sdps/sdp=<string:sdp_id>",
+    )
+    _add_resource(
+        rest_server,
+        NSS_Service_Connection_Groups,
+        ":network-slice-services/slice-service=<string:slice_id>/connection-groups",
+    )
+    _add_resource(
+        rest_server,
+        NSS_Service_Connection_Group,
+        ":network-slice-services/slice-service=<string:slice_id>/connection-groups/connection-group=<string:connection_group_id>",
+    )
+    _add_resource(
+        rest_server,
+        NSS_Service_Match_Criteria,
+        ":network-slice-services/slice-service=<string:slice_id>/sdps/sdp=<string:sdp_id>/service-match-criteria",
+    )
+    _add_resource(
+        rest_server,
+        NSS_Service_Match_Criterion,
+        ":network-slice-services/slice-service=<string:slice_id>/sdps/sdp=<string:sdp_id>/service-match-criteria/match-criterion=<string:match_criterion_id>",
+    )
diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/ietf_slice_handler.py b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/ietf_slice_handler.py
new file mode 100644
index 0000000000000000000000000000000000000000..80ce4c6b78d446ff1e08a750f236e0c143e1ba57
--- /dev/null
+++ b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/ietf_slice_handler.py
@@ -0,0 +1,640 @@
+# 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
+import logging
+import uuid
+from typing import Dict, List, Optional
+
+from common.Constants import DEFAULT_CONTEXT_NAME
+from common.proto.context_pb2 import (
+    ConfigRule,
+    Constraint,
+    DeviceId,
+    Device,
+    Empty,
+    EndPointId,
+    ServiceConfig,
+    Slice,
+    SliceStatusEnum,
+)
+from common.tools.context_queries.Slice import get_slice_by_defualt_name
+from common.tools.grpc.ConfigRules import update_config_rule_custom
+from common.tools.object_factory.Device import json_device_id
+from common.DeviceTypes import DeviceTypeEnum
+from context.client import ContextClient
+
+from .YangValidator import YangValidator
+
+LOGGER = logging.getLogger(__name__)
+
+
+RUNNING_RESOURCE_KEY = "running_ietf_slice"
+CANDIDATE_RESOURCE_KEY = "candidate_ietf_slice"
+ADDRESS_PREFIX = 24
+RAISE_IF_DIFFERS = False
+
+
+def validate_ietf_slice_data(request_data: Dict) -> None:
+    """
+    Validate the provided IETF slice data against the YANG model.
+    """
+    yang_validator = YangValidator("ietf-network-slice-service")
+    _ = yang_validator.parse_to_dict(request_data)
+    yang_validator.destroy()
+
+
+def get_custom_config_rule(
+    service_config: ServiceConfig, resource_key: str
+) -> Optional[ConfigRule]:
+    """
+    Retrieve the custom config rule with the given resource_key from a ServiceConfig.
+    """
+    for cr in service_config.config_rules:
+        if (
+            cr.WhichOneof("config_rule") == "custom"
+            and cr.custom.resource_key == resource_key
+        ):
+            return cr
+    return None
+
+
+def get_ietf_data_from_config(slice_request: Slice, resource_key: str) -> Dict:
+    """
+    Retrieve the IETF data (as a Python dict) from a slice's config rule for the specified resource_key.
+    Raises an exception if not found.
+    """
+    config_rule = get_custom_config_rule(slice_request.slice_config, resource_key)
+    if not config_rule:
+        raise Exception(f"IETF data not found for resource_key: {resource_key}")
+    return json.loads(config_rule.custom.resource_value)
+
+
+def update_ietf_data_in_config(
+    slice_request: Slice, resource_key: str, ietf_data: Dict
+) -> None:
+    """
+    Update the slice config rule (identified by resource_key) with the provided IETF data.
+    """
+    fields = {name: (value, RAISE_IF_DIFFERS) for name, value in ietf_data.items()}
+    update_config_rule_custom(
+        slice_request.slice_config.config_rules, resource_key, fields
+    )
+
+
+def build_constraints_from_connection_group(connection_group: dict) -> List[Constraint]:
+    """
+    Build a list of Constraints from the 'metric-bound' data in a connection group.
+    """
+    constraints = []
+    metric_bounds = connection_group["connectivity-construct"][0][
+        "service-slo-sle-policy"
+    ]["slo-policy"]["metric-bound"]
+
+    for metric in metric_bounds:
+        metric_type = metric["metric-type"]
+        if metric_type == "ietf-nss:one-way-delay-maximum":
+            bound_value = float(metric["bound"])
+            constraint = Constraint()
+            constraint.sla_latency.e2e_latency_ms = bound_value
+            constraints.append(constraint)
+        elif metric_type == "ietf-nss:one-way-bandwidth":
+            bound_value = float(metric["bound"])
+            constraint = Constraint()
+            # Convert from Mbps to Gbps if needed
+            constraint.sla_capacity.capacity_gbps = bound_value / 1.0e3
+            constraints.append(constraint)
+
+    return constraints
+
+
+def get_endpoint_controller_type(
+    endpoint: EndPointId, context_client: ContextClient
+) -> str:
+    """
+    Retrieve the device type of an endpoint's controller device, if any; otherwise returns an empty string.
+    """
+    endpoint_device: Device = context_client.GetDevice(endpoint.device_id)
+    if endpoint_device.controller_id == DeviceId():
+        return ""
+    controller = context_client.GetDevice(endpoint_device.controller_id)
+    if controller is None:
+        controller_uuid = endpoint_device.controller_id.device_uuid.uuid
+        raise Exception(f"Controller device {controller_uuid} not found")
+    return controller.device_type
+
+
+def sort_endpoints(
+    endpoints_list: List[EndPointId],
+    sdps: List,
+    connection_group: Dict,
+    context_client: ContextClient,
+) -> List[EndPointId]:
+    """
+    Sort the endpoints_list based on controller type:
+      - If the first endpoint is an NCE, keep order.
+      - If the last endpoint is an NCE, reverse order.
+      - Otherwise, use the 'p2p-sender-sdp' from the connection group to decide.
+    """
+    if not endpoints_list:
+        return endpoints_list
+
+    first_ep = endpoints_list[0]
+    last_ep = endpoints_list[-1]
+    first_controller_type = get_endpoint_controller_type(first_ep, context_client)
+    last_controller_type = get_endpoint_controller_type(last_ep, context_client)
+
+    if first_controller_type == DeviceTypeEnum.NCE.value:
+        return endpoints_list
+    elif last_controller_type == DeviceTypeEnum.NCE.value:
+        return endpoints_list[::-1]
+
+    src_sdp_id = connection_group["connectivity-construct"][0]["p2p-sender-sdp"]
+    sdp_id_name_mapping = {sdp["id"]: sdp["node-id"] for sdp in sdps}
+    if endpoints_list[0].device_id.device_uuid.uuid == sdp_id_name_mapping[src_sdp_id]:
+        return endpoints_list
+    return endpoints_list[::-1]
+
+
+def replace_ont_endpoint_with_emu_dc(
+    endpoint_list: List[EndPointId], context_client: ContextClient
+) -> List[EndPointId]:
+    """
+    Replace an ONT endpoint in endpoint_list with an 'emu-datacenter' endpoint if found.
+    One endpoint must be managed (controller_id != empty), the other must be unmanaged.
+    """
+    if len(endpoint_list) != 2:
+        raise Exception(
+            "Expecting exactly two endpoints to handle ONT -> emu-dc replacement"
+        )
+
+    link_list = context_client.ListLinks(Empty())
+    links = list(link_list.links)
+    devices_list = context_client.ListDevices(Empty())
+    devices = devices_list.devices
+
+    uuid_name_map = {d.device_id.device_uuid.uuid: d.name for d in devices}
+    uuid_device_map = {d.device_id.device_uuid.uuid: d for d in devices}
+    name_device_map = {d.name: d for d in devices}
+
+    endpoint_id_1, endpoint_id_2 = endpoint_list
+    device_uuid_1 = endpoint_id_1.device_id.device_uuid.uuid
+    device_uuid_2 = endpoint_id_2.device_id.device_uuid.uuid
+
+    device_1 = name_device_map.get(device_uuid_1)
+    device_2 = name_device_map.get(device_uuid_2)
+
+    if not device_1 or not device_2:
+        raise Exception("One or both devices not found in name_device_map")
+
+    # Check if the first endpoint is managed
+    if device_1.controller_id != DeviceId():
+        for link in links:
+            link_endpoints = list(link.link_endpoint_ids)
+            link_ep_1, link_ep_2 = link_endpoints
+            if (
+                device_uuid_1 == uuid_name_map.get(link_ep_1.device_id.device_uuid.uuid)
+                and uuid_device_map[link_ep_2.device_id.device_uuid.uuid].device_type
+                == "emu-datacenter"
+            ):
+                endpoint_list[0] = link_ep_2
+                break
+    # Otherwise, check if the second endpoint is managed
+    elif device_2.controller_id != DeviceId():
+        for link in links:
+            link_endpoints = list(link.link_endpoint_ids)
+            link_ep_1, link_ep_2 = link_endpoints
+            if (
+                device_uuid_2 == uuid_name_map.get(link_ep_1.device_id.device_uuid.uuid)
+                and uuid_device_map[link_ep_2.device_id.device_uuid.uuid].device_type
+                == "emu-datacenter"
+            ):
+                endpoint_list[1] = link_ep_2
+                break
+    else:
+        raise Exception(
+            "One endpoint should be managed by a controller and the other should not be"
+        )
+
+    return endpoint_list
+
+
+class IETFSliceHandler:
+    @staticmethod
+    def get_all_ietf_slices(context_client: ContextClient) -> Dict:
+        """
+        Retrieve all IETF slices from the (single) context. Expects exactly one context in the system.
+        """
+        existing_context_ids = context_client.ListContextIds(Empty())
+        context_ids = list(existing_context_ids.context_ids)
+        if len(context_ids) != 1:
+            raise Exception("Number of contexts should be exactly 1")
+
+        slices_list = context_client.ListSlices(context_ids[0])
+        slices = slices_list.slices
+
+        ietf_slices = {"network-slice-services": {"slice-service": []}}
+        for slc in slices:
+            candidate_cr = get_custom_config_rule(
+                slc.slice_config, CANDIDATE_RESOURCE_KEY
+            )
+            if not candidate_cr:
+                # Skip slices that don't have the candidate_ietf_slice data
+                continue
+            candidate_ietf_data = json.loads(candidate_cr.custom.resource_value)
+            ietf_slices["network-slice-services"]["slice-service"].append(
+                candidate_ietf_data["network-slice-services"]["slice-service"][0]
+            )
+        return ietf_slices
+
+    @staticmethod
+    def create_slice_service(
+        request_data: dict, context_client: ContextClient
+    ) -> Slice:
+        """
+        Create a new slice service from the provided IETF data, applying validations and constructing a Slice object.
+        """
+        # Ensure the top-level key is "network-slice-services"
+        if "network-slice-services" not in request_data:
+            request_data = {"network-slice-services": request_data}
+
+        validate_ietf_slice_data(request_data)
+        slice_service = request_data["network-slice-services"]["slice-service"][0]
+
+        slice_id = slice_service["id"]
+        sdps = slice_service["sdps"]["sdp"]
+        if len(sdps) != 2:
+            raise Exception("Number of SDPs should be exactly 2")
+
+        connection_groups = slice_service["connection-groups"]["connection-group"]
+        slice_request = Slice()
+        slice_request.slice_id.context_id.context_uuid.uuid = DEFAULT_CONTEXT_NAME
+        slice_request.slice_id.slice_uuid.uuid = slice_id
+        slice_request.slice_status.slice_status = SliceStatusEnum.SLICESTATUS_PLANNED
+
+        list_endpoints = []
+        endpoint_config_rules = []
+        connection_group_ids = set()
+
+        # Build endpoints from SDPs
+        for sdp in sdps:
+            attachment_circuits = sdp["attachment-circuits"]["attachment-circuit"]
+            if len(attachment_circuits) != 1:
+                raise Exception("Each SDP must have exactly 1 attachment-circuit")
+
+            endpoint = EndPointId()
+            endpoint.topology_id.context_id.context_uuid.uuid = DEFAULT_CONTEXT_NAME
+            device_uuid = sdp["node-id"]
+            endpoint.device_id.device_uuid.uuid = device_uuid
+            endpoint_uuid = attachment_circuits[0]["ac-tp-id"]
+            endpoint.endpoint_uuid.uuid = endpoint_uuid
+            list_endpoints.append(endpoint)
+
+            # Keep track of connection-group-id from each SDP
+            connection_group_ids.add(
+                sdp["service-match-criteria"]["match-criterion"][0][
+                    "target-connection-group-id"
+                ]
+            )
+
+            # Endpoint-specific config rule fields
+            endpoint_config_rule_fields = {
+                "address_ip": (endpoint_uuid, RAISE_IF_DIFFERS),
+                "address_prefix": (ADDRESS_PREFIX, RAISE_IF_DIFFERS),
+            }
+            endpoint_config_rules.append(
+                (
+                    f"/device[{device_uuid}]/endpoint[{endpoint_uuid}]/settings",
+                    endpoint_config_rule_fields,
+                )
+            )
+
+        if len(connection_group_ids) != 1:
+            raise Exception("SDPs do not share a common connection-group-id")
+
+        # Build constraints from the matching connection group
+        unique_cg_id = connection_group_ids.pop()
+        found_cg = next(
+            (cg for cg in connection_groups if cg["id"] == unique_cg_id), None
+        )
+        if not found_cg:
+            raise Exception("The connection group referenced by the SDPs was not found")
+
+        list_constraints = build_constraints_from_connection_group(found_cg)
+
+        # Sort endpoints and optionally replace the ONT endpoint
+        list_endpoints = sort_endpoints(list_endpoints, sdps, found_cg, context_client)
+        list_endpoints = replace_ont_endpoint_with_emu_dc(
+            list_endpoints, context_client
+        )
+
+        slice_request.slice_endpoint_ids.extend(list_endpoints)
+        slice_request.slice_constraints.extend(list_constraints)
+
+        # Set slice owner
+        slice_request.slice_owner.owner_string = slice_id
+        slice_request.slice_owner.owner_uuid.uuid = str(
+            uuid.uuid5(uuid.NAMESPACE_DNS, slice_id)
+        )
+
+        # Update slice config with IETF data (both running and candidate)
+        ietf_slice_fields = {
+            name: (value, RAISE_IF_DIFFERS) for name, value in request_data.items()
+        }
+        update_config_rule_custom(
+            slice_request.slice_config.config_rules,
+            RUNNING_RESOURCE_KEY,
+            ietf_slice_fields,
+        )
+        update_config_rule_custom(
+            slice_request.slice_config.config_rules,
+            CANDIDATE_RESOURCE_KEY,
+            ietf_slice_fields,
+        )
+
+        # Update endpoint config rules
+        for ep_cr_key, ep_cr_fields in endpoint_config_rules:
+            update_config_rule_custom(
+                slice_request.slice_config.config_rules, ep_cr_key, ep_cr_fields
+            )
+
+        return slice_request
+
+    @staticmethod
+    def create_sdp(
+        request_data: dict, slice_uuid: str, context_client: ContextClient
+    ) -> Slice:
+        """
+        Add a new SDP to an existing slice, updating the candidate IETF data.
+        """
+        sdps = request_data["sdp"]
+        if len(sdps) != 1:
+            raise Exception("Number of SDPs to create must be exactly 1")
+
+        new_sdp = sdps[0]
+        slice_request = get_slice_by_defualt_name(
+            context_client, slice_uuid, rw_copy=False
+        )
+        ietf_data = get_ietf_data_from_config(slice_request, CANDIDATE_RESOURCE_KEY)
+
+        slice_service = ietf_data["network-slice-services"]["slice-service"][0]
+        slice_sdps = slice_service["sdps"]["sdp"]
+        slice_sdps.append(new_sdp)
+
+        # Save updated IETF data
+        update_ietf_data_in_config(slice_request, CANDIDATE_RESOURCE_KEY, ietf_data)
+        return slice_request
+
+    @staticmethod
+    def delete_sdp(
+        slice_uuid: str, sdp_id: str, context_client: ContextClient
+    ) -> Slice:
+        """
+        Delete the specified SDP from an existing slice's candidate IETF data.
+        """
+        slice_request = get_slice_by_defualt_name(
+            context_client, slice_uuid, rw_copy=False
+        )
+        ietf_data = get_ietf_data_from_config(slice_request, CANDIDATE_RESOURCE_KEY)
+
+        slice_service = ietf_data["network-slice-services"]["slice-service"][0]
+        slice_sdps = slice_service["sdps"]["sdp"]
+
+        # Find and remove the matching SDP
+        sdp_idx = next(
+            (i for i, sdp in enumerate(slice_sdps) if sdp["id"] == sdp_id), None
+        )
+        if sdp_idx is None:
+            raise Exception(f"SDP with id '{sdp_id}' not found in slice '{slice_uuid}'")
+        slice_sdps.pop(sdp_idx)
+
+        update_ietf_data_in_config(slice_request, CANDIDATE_RESOURCE_KEY, ietf_data)
+        return slice_request
+
+    @staticmethod
+    def create_connection_group(
+        request_data: dict, slice_id: str, context_client: ContextClient
+    ) -> Slice:
+        """
+        Add a new connection group to an existing slice's candidate IETF data.
+        """
+        connection_groups = request_data["connection-group"]
+        if len(connection_groups) != 1:
+            raise Exception("Number of connection groups to create must be exactly 1")
+
+        new_connection_group = connection_groups[0]
+        slice_request = get_slice_by_defualt_name(
+            context_client, slice_id, rw_copy=False
+        )
+        ietf_data = get_ietf_data_from_config(slice_request, CANDIDATE_RESOURCE_KEY)
+
+        slice_service = ietf_data["network-slice-services"]["slice-service"][0]
+        slice_connection_groups = slice_service["connection-groups"]["connection-group"]
+        slice_connection_groups.append(new_connection_group)
+
+        # Validate the updated data, then save
+        validate_ietf_slice_data(ietf_data)
+        update_ietf_data_in_config(slice_request, CANDIDATE_RESOURCE_KEY, ietf_data)
+        return slice_request
+
+    @staticmethod
+    def update_connection_group(
+        slice_name: str,
+        updated_connection_group: dict,
+        context_client: ContextClient,
+    ) -> Slice:
+        """
+        Update an existing connection group in the candidate IETF data.
+        """
+        slice_request = get_slice_by_defualt_name(
+            context_client, slice_name, rw_copy=False
+        )
+        candidate_ietf_data = get_ietf_data_from_config(
+            slice_request, CANDIDATE_RESOURCE_KEY
+        )
+
+        slice_service = candidate_ietf_data["network-slice-services"]["slice-service"][
+            0
+        ]
+        slice_connection_groups = slice_service["connection-groups"]["connection-group"]
+
+        cg_id = updated_connection_group["id"]
+        cg_idx = next(
+            (i for i, cg in enumerate(slice_connection_groups) if cg["id"] == cg_id),
+            None,
+        )
+        if cg_idx is None:
+            raise Exception(f"Connection group with id '{cg_id}' not found")
+
+        slice_connection_groups[cg_idx] = updated_connection_group
+        update_ietf_data_in_config(
+            slice_request, CANDIDATE_RESOURCE_KEY, candidate_ietf_data
+        )
+
+        slice_request.slice_status.slice_status = SliceStatusEnum.SLICESTATUS_PLANNED
+        return slice_request
+
+    @staticmethod
+    def delete_connection_group(
+        slice_uuid: str, connection_group_id: str, context_client: ContextClient
+    ) -> Slice:
+        """
+        Remove an existing connection group from the candidate IETF data of a slice.
+        """
+        slice_request = get_slice_by_defualt_name(
+            context_client, slice_uuid, rw_copy=False
+        )
+        candidate_ietf_data = get_ietf_data_from_config(
+            slice_request, CANDIDATE_RESOURCE_KEY
+        )
+
+        slice_service = candidate_ietf_data["network-slice-services"]["slice-service"][
+            0
+        ]
+        slice_connection_groups = slice_service["connection-groups"]["connection-group"]
+
+        cg_idx = next(
+            (
+                i
+                for i, cg in enumerate(slice_connection_groups)
+                if cg["id"] == connection_group_id
+            ),
+            None,
+        )
+        if cg_idx is None:
+            raise Exception(
+                f"Connection group with id '{connection_group_id}' not found"
+            )
+
+        slice_connection_groups.pop(cg_idx)
+        update_ietf_data_in_config(
+            slice_request, CANDIDATE_RESOURCE_KEY, candidate_ietf_data
+        )
+
+        slice_request.slice_status.slice_status = SliceStatusEnum.SLICESTATUS_PLANNED
+        return slice_request
+
+    @staticmethod
+    def create_match_criteria(
+        request_data: dict, slice_name: str, sdp_id: str, context_client: ContextClient
+    ) -> Slice:
+        """
+        Create a new match-criterion for the specified SDP in a slice's candidate IETF data.
+        """
+        match_criteria = request_data["match-criterion"]
+        if len(match_criteria) != 1:
+            raise Exception(
+                "Number of match-criterion entries to create must be exactly 1"
+            )
+
+        new_match_criterion = match_criteria[0]
+        target_connection_group_id = new_match_criterion["target-connection-group-id"]
+
+        slice_request = get_slice_by_defualt_name(
+            context_client, slice_name, rw_copy=False
+        )
+        ietf_data = get_ietf_data_from_config(slice_request, CANDIDATE_RESOURCE_KEY)
+
+        slice_service = ietf_data["network-slice-services"]["slice-service"][0]
+        connection_groups = slice_service["connection-groups"]["connection-group"]
+        sdps = slice_service["sdps"]["sdp"]
+
+        # Find the referenced connection group
+        found_cg = next(
+            (cg for cg in connection_groups if cg["id"] == target_connection_group_id),
+            None,
+        )
+        if not found_cg:
+            raise Exception(
+                f"Connection group '{target_connection_group_id}' not found"
+            )
+
+        # Build constraints from that connection group
+        list_constraints = build_constraints_from_connection_group(found_cg)
+
+        # Add match-criterion to the relevant SDP
+        sdp_to_update = next((s for s in sdps if s["id"] == sdp_id), None)
+        if not sdp_to_update:
+            raise Exception(f"SDP '{sdp_id}' not found")
+
+        sdp_to_update["service-match-criteria"]["match-criterion"].append(
+            new_match_criterion
+        )
+
+        # Update constraints at the slice level as needed
+        del slice_request.slice_constraints[:]
+        slice_request.slice_constraints.extend(list_constraints)
+        slice_request.slice_status.slice_status = SliceStatusEnum.SLICESTATUS_PLANNED
+
+        update_ietf_data_in_config(slice_request, CANDIDATE_RESOURCE_KEY, ietf_data)
+        return slice_request
+
+    @staticmethod
+    def delete_match_criteria(
+        slice_uuid: str,
+        sdp_id: str,
+        match_criterion_id: int,
+        context_client: ContextClient,
+    ) -> Slice:
+        """
+        Delete the specified match-criterion from an SDP in the slice's candidate IETF data.
+        """
+        slice_request = get_slice_by_defualt_name(
+            context_client, slice_uuid, rw_copy=False
+        )
+        ietf_data = get_ietf_data_from_config(slice_request, CANDIDATE_RESOURCE_KEY)
+
+        slice_service = ietf_data["network-slice-services"]["slice-service"][0]
+        sdps = slice_service["sdps"]["sdp"]
+
+        # Find and modify the specified SDP
+        sdp_to_update = next((s for s in sdps if s["id"] == sdp_id), None)
+        if not sdp_to_update:
+            raise Exception(f"SDP '{sdp_id}' not found in slice '{slice_uuid}'")
+
+        match_criteria = sdp_to_update["service-match-criteria"]["match-criterion"]
+        mc_index = next(
+            (
+                i
+                for i, m in enumerate(match_criteria)
+                if m["index"] == match_criterion_id
+            ),
+            None,
+        )
+        if mc_index is None:
+            raise Exception(
+                f"No match-criterion with index '{match_criterion_id}' found in SDP '{sdp_id}'"
+            )
+
+        match_criteria.pop(mc_index)
+        update_ietf_data_in_config(slice_request, CANDIDATE_RESOURCE_KEY, ietf_data)
+        return slice_request
+
+    @staticmethod
+    def copy_candidate_ietf_slice_data_to_running(
+        slice_uuid: str, context_client: ContextClient
+    ) -> Slice:
+        """
+        Copy candidate IETF slice data to the running IETF slice data for a given slice.
+        """
+        slice_request = get_slice_by_defualt_name(
+            context_client, slice_uuid, rw_copy=False
+        )
+        candidate_ietf_data = get_ietf_data_from_config(
+            slice_request, CANDIDATE_RESOURCE_KEY
+        )
+        update_ietf_data_in_config(
+            slice_request, RUNNING_RESOURCE_KEY, candidate_ietf_data
+        )
+        return slice_request
diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-ac-common@2023-11-13.yang b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-ac-common@2023-11-13.yang
new file mode 100644
index 0000000000000000000000000000000000000000..170e70fff67242b380fc984d815e3d83557eca06
--- /dev/null
+++ b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-ac-common@2023-11-13.yang
@@ -0,0 +1,1651 @@
+module ietf-ac-common {
+  yang-version 1.1;
+  namespace "urn:ietf:params:xml:ns:yang:ietf-ac-common";
+  prefix ac-common;
+
+  import ietf-vpn-common {
+    prefix vpn-common;
+    reference
+      "RFC 9181: A Common YANG Data Model for Layer 2 and Layer 3
+                 VPNs";
+  }
+  import ietf-netconf-acm {
+    prefix nacm;
+    reference
+      "RFC 8341: Network Configuration Access Control Model";
+  }
+  import ietf-inet-types {
+    prefix inet;
+    reference
+      "RFC 6991: Common YANG Data Types, Section 4";
+  }
+  import ietf-yang-types {
+    prefix yang;
+    reference
+      "RFC 6991: Common YANG Data Types, Section 3";
+  }
+  import ietf-key-chain {
+    prefix key-chain;
+    reference
+      "RFC 8177: YANG Data Model for Key Chains";
+  }
+
+  organization
+    "IETF OPSAWG (Operations and Management Area Working Group)";
+  contact
+    "WG Web:   <https://datatracker.ietf.org/wg/opsawg/>
+     WG List:  <mailto:opsawg@ietf.org>
+
+     Editor:   Mohamed Boucadair
+               <mailto:mohamed.boucadair@orange.com>
+     Author:   Richard Roberts
+               <mailto:rroberts@juniper.net>
+     Author:   Oscar Gonzalez de Dios
+               <mailto:oscar.gonzalezdedios@telefonica.com>
+     Author:   Samier Barguil
+               <mailto:ssamier.barguil_giraldo@nokia.com>
+     Author:   Bo Wu
+               <mailto:lana.wubo@huawei.com>";
+  description
+    "This YANG module defines a common attachment circuit (AC)
+     YANG model.
+
+     Copyright (c) 2024 IETF Trust and the persons identified as
+     authors of the code.  All rights reserved.
+
+     Redistribution and use in source and binary forms, with or
+     without modification, is permitted pursuant to, and subject
+     to the license terms contained in, the Revised BSD License
+     set forth in Section 4.c of the IETF Trust's Legal Provisions
+     Relating to IETF Documents
+     (https://trustee.ietf.org/license-info).
+
+     This version of this YANG module is part of RFC XXXX; see the
+     RFC itself for full legal notices.";
+
+  revision 2023-11-13 {
+    description
+      "Initial revision.";
+    reference
+      "RFC XXXX: A Common YANG Data Model for Attachment Circuits";
+  }
+
+  /****************************Features************************/
+
+  feature layer2-ac {
+    description
+      "Indicates support of Layer 2 ACs.";
+  }
+
+  feature layer3-ac {
+    description
+      "Indicates support of Layer 3 ACs.";
+  }
+
+  feature server-assigned-reference {
+    description
+      "This feature indicates support for server-generated references
+       and use of such references to access related resources.";
+  }
+
+  /****************************Identities************************/
+  // IP address allocation types
+
+  identity address-allocation-type {
+    description
+      "Base identity for address allocation type in the AC.";
+  }
+
+  identity provider-dhcp {
+    base address-allocation-type;
+    description
+      "The provider's network provides a DHCP service to the
+       customer.";
+  }
+
+  identity provider-dhcp-relay {
+    base address-allocation-type;
+    description
+      "The provider's network provides a DHCP relay service to the
+       customer.";
+  }
+
+  identity provider-dhcp-slaac {
+    if-feature "vpn-common:ipv6";
+    base address-allocation-type;
+    description
+      "The provider's network provides a DHCP service to the customer
+       as well as IPv6 Stateless Address Autoconfiguration (SLAAC).";
+    reference
+      "RFC 4862: IPv6 Stateless Address Autoconfiguration";
+  }
+
+  identity static-address {
+    base address-allocation-type;
+    description
+      "The provider's network provides static IP addressing to the
+       customer.";
+  }
+
+  identity slaac {
+    if-feature "vpn-common:ipv6";
+    base address-allocation-type;
+    description
+      "The provider's network uses IPv6 SLAAC to provide addressing
+       to the customer.";
+    reference
+      "RFC 4862: IPv6 Stateless Address Autoconfiguration";
+  }
+
+  identity dynamic-infra {
+    base address-allocation-type;
+    description
+      "The IP address is dynamically allocated by the hosting
+       infrastrcture.";
+  }
+
+  // next-hop actions
+
+  identity local-defined-next-hop {
+    description
+      "Base identity of local defined next hops.";
+  }
+
+  identity discard {
+    base local-defined-next-hop;
+    description
+      "Indicates an action to discard traffic for the corresponding
+       destination. For example, this can be used to black-hole
+       traffic.";
+  }
+
+  identity local-link {
+    base local-defined-next-hop;
+    description
+      "Treat traffic towards addresses within the specified next-hop
+       prefix as though they are connected to a local link.";
+  }
+
+  // Layer 2 tunnel types
+
+  identity l2-tunnel-type {
+    description
+      "Base identity for Layer 2 tunnel selection for an AC.";
+  }
+
+  identity pseudowire {
+    base l2-tunnel-type;
+    description
+      "Pseudowire tunnel termination for the AC.";
+  }
+
+  identity vpls {
+    base l2-tunnel-type;
+    description
+      "Virtual Private LAN Service (VPLS) tunnel termination for
+       the AC.";
+  }
+
+  identity vxlan {
+    base l2-tunnel-type;
+    description
+      "Virtual eXtensible Local Area Network (VXLAN) tunnel
+       termination for the AC.";
+  }
+
+  // Layer 3 tunnel types
+
+  identity l3-tunnel-type {
+    description
+      "Base identity for Layer 3 tunnel selection for an AC.";
+  }
+
+  identity ip-in-ip {
+    base l3-tunnel-type;
+    description
+      "IP in IP Tunneling.";
+  }
+
+  identity ipsec {
+    base l3-tunnel-type;
+    description
+      "IP Security (IPsec).";
+  }
+
+  identity gre {
+    base l3-tunnel-type;
+    description
+      "Generic Routing Encapsulation (GRE).";
+  }
+
+  // Tagging precedence
+
+  identity precedence-type {
+    description
+      "Redundancy type. The service can be created with primary and
+       secondary tagging.";
+  }
+
+  identity primary {
+    base precedence-type;
+    description
+      "Identifies the main attachment circuit.";
+  }
+
+  identity secondary {
+    base precedence-type;
+    description
+      "Identifies the secondary attachment circuit.";
+  }
+  // AC Type
+
+  identity role {
+    description
+      "Base identity for the network role of an AC.";
+  }
+
+  identity uni {
+    base role;
+      description
+        "User-to-Network Interface (UNI).";
+  }
+
+  identity nni {
+    base role;
+    description
+      "Network-to-Network Interface (NNI).";
+  }
+
+  identity public-nni {
+    base role;
+    description
+      "Public peering.";
+  }
+
+  // More Admin status types
+
+  identity awaiting-validation {
+    base vpn-common:administrative-status;
+    description
+      "This administrative status reflects that a request is
+       pending an adiministrator approval.";
+  }
+
+  identity awaiting-processing {
+    base vpn-common:administrative-status;
+    description
+      "This administrative status reflects that a request was
+       approved and validated, but is awaiting more processing
+       before activation.";
+  }
+
+  identity admin-prohibited {
+    base vpn-common:administrative-status;
+    description
+      "This administrative status reflects that a request cannot
+       be handled because of administrative policies.";
+  }
+  identity rejected {
+    base vpn-common:administrative-status;
+    description
+      "This administrative status reflects that a request was
+       rejected because, e.g., there are no sufficient resources
+       or other reasons not covered by the other status types.";
+  }
+
+  identity bgp-role {
+    description
+      "Used to indicate BGP role when establishing a BGP session.";
+    reference
+      "RFC 9234: Route Leak Prevention and Detection Using
+                 Roles in UPDATE and OPEN Messages, Section 4";
+  }
+
+  identity provider {
+    base bgp-role;
+    description
+      "The local AS is a transit provider of the remote AS.";
+  }
+
+  identity client {
+    base bgp-role;
+    description
+      "The local AS is a transit provider of the remote AS.";
+  }
+
+  identity rs {
+    base bgp-role;
+    description
+      "The local AS is a Route Server (RS).";
+  }
+
+  identity rs-client {
+    base bgp-role;
+    description
+      "The local AS is a client of an RS and the RS is the
+       remote AS.";
+  }
+
+  identity peer {
+    base bgp-role;
+    description
+      "The local and remote ASes have a peering relationship.";
+  }
+
+  /****************************Typedefs************************/
+  typedef predefined-next-hop {
+    type identityref {
+      base local-defined-next-hop;
+    }
+    description
+      "Predefined next-hop designation for locally generated
+       routes.";
+  }
+
+  typedef area-address {
+    type string {
+      pattern '[0-9A-Fa-f]{2}(\.[0-9A-Fa-f]{4}){0,6}';
+    }
+    description
+      "This type defines the area address format.";
+  }
+
+  /************************Reusable groupings********************/
+  /**** Service Status ****/
+
+  grouping service-status {
+    description
+      "Service status grouping.";
+    container status {
+      description
+        "Service status.";
+      container admin-status {
+        description
+          "Administrative service status.";
+        leaf status {
+          type identityref {
+            base vpn-common:administrative-status;
+          }
+          description
+            "Administrative service status.";
+        }
+        leaf last-change {
+          type yang:date-and-time;
+          config false;
+          description
+            "Indicates the actual date and time of the service
+             status change.";
+        }
+      }
+      container oper-status {
+        config false;
+        description
+          "Operational service status.";
+        uses vpn-common:oper-status-timestamp;
+      }
+    }
+  }
+
+  /**** A set of profiles ****/
+
+  grouping ac-profile-cfg {
+    description
+      "Grouping for AC profile configuration.";
+    container valid-provider-identifiers {
+      description
+        "Container for valid provider profile identifiers.
+         The profiles only have significance within the service
+         provider's administrative domain.";
+      list encryption-profile-identifier {
+        key "id";
+        description
+          "List of encryption profile identifiers.";
+        leaf id {
+          type string;
+          description
+            "Identification of the encryption profile to be used.";
+        }
+      }
+      list qos-profile-identifier {
+        key "id";
+        description
+          "List of QoS profile identifiers.";
+        leaf id {
+          type string;
+          description
+            "Identification of the QoS profile to be used.";
+        }
+      }
+      list failure-detection-profile-identifier {
+        key "id";
+        description
+          "List of BFD profile identifiers.";
+        leaf id {
+          type string;
+          description
+            "Identification of the a failure detection (e.g., BFD)
+             profile to be used.";
+        }
+      }
+      list forwarding-profile-identifier {
+        key "id";
+        description
+          "List of forwarding profile identifiers.";
+        leaf id {
+          type string;
+          description
+            "Identification of the forwarding profile to be used.";
+        }
+      }
+      list routing-profile-identifier {
+        key "id";
+        description
+          "List of routing profile identifiers.";
+        leaf id {
+          type string;
+          description
+            "Identification of the routing profile to be used by
+             the routing protocols over an AC.";
+        }
+      }
+      nacm:default-deny-write;
+    }
+  }
+
+  /**** Operational instructions ****/
+
+  grouping op-instructions {
+    description
+      "Scheduling instructions.";
+    leaf requested-start {
+      type yang:date-and-time;
+      description
+        "Indicates the requested date and time when the service is
+         expected to be active.";
+    }
+    leaf requested-stop {
+      type yang:date-and-time;
+      description
+        "Indicates the requested date and time when the service is
+         expected to be disabled.";
+    }
+    leaf actual-start {
+      type yang:date-and-time;
+      config false;
+      description
+        "Indicates the actual date and time when the service
+         actually was enabled.";
+    }
+    leaf actual-stop {
+      type yang:date-and-time;
+      config false;
+      description
+        "Indicates the actual date and time when the service
+         actually was disabled.";
+    }
+  }
+
+  /**** Layer 2 encapsulations ****/
+  // Dot1q
+
+  grouping dot1q {
+    description
+      "Defines a grouping for tagged interfaces.";
+    leaf tag-type {
+      type identityref {
+        base vpn-common:tag-type;
+      }
+      description
+        "Tag type.";
+    }
+    leaf cvlan-id {
+      type uint16 {
+        range "1..4094";
+      }
+      description
+        "VLAN identifier.";
+    }
+  }
+
+  // priority-tagged
+
+  grouping priority-tagged {
+    description
+      "Priority tagged.";
+    leaf tag-type {
+      type identityref {
+        base vpn-common:tag-type;
+      }
+      description
+        "Tag type.";
+    }
+  }
+
+  // QinQ
+
+  grouping qinq {
+    description
+      "Includes QinQ parameters.";
+    leaf tag-type {
+      type identityref {
+        base vpn-common:tag-type;
+      }
+      description
+        "Tag type.";
+    }
+    leaf svlan-id {
+      type uint16 {
+        range "1..4094";
+      }
+      description
+        "Service VLAN (S-VLAN) identifier.";
+    }
+    leaf cvlan-id {
+      type uint16 {
+        range "1..4094";
+      }
+      description
+        "Customer VLAN (C-VLAN) identifier.";
+    }
+  }
+
+  /**** Layer 2 tunnel services ****/
+  // pseudowire (PW)
+
+  grouping pseudowire {
+    description
+      "Includes pseudowire termination parameters.";
+    leaf vcid {
+      type uint32;
+      description
+        "Indicates a PW or virtual circuit (VC) identifier.";
+    }
+    leaf far-end {
+      type union {
+        type uint32;
+        type inet:ip-address;
+      }
+      description
+        "Neighbor reference.";
+      reference
+        "RFC 8077: Pseudowire Setup and Maintenance Using the Label
+                   Distribution Protocol (LDP), Section 6.1";
+    }
+  }
+  // VPLS
+
+  grouping vpls {
+    description
+      "VPLS termination parameters.";
+    leaf vcid {
+      type uint32;
+      description
+        "VC identifier.";
+    }
+    leaf-list far-end {
+      type union {
+        type uint32;
+        type inet:ip-address;
+      }
+      description
+        "Neighbor reference.";
+    }
+  }
+
+  // VXLAN
+
+  grouping vxlan {
+    description
+      "VXLAN termination parameters.";
+    leaf vni-id {
+      type uint32;
+      description
+        "VXLAN Network Identifier (VNI).";
+    }
+    leaf peer-mode {
+      type identityref {
+        base vpn-common:vxlan-peer-mode;
+      }
+      description
+        "Specifies the VXLAN access mode. By default,
+         the peer mode is set to 'static-mode'.";
+    }
+    leaf-list peer-ip-address {
+      type inet:ip-address;
+      description
+        "List of a peer's IP addresses.";
+    }
+  }
+
+  // Layer 2 Tunnel service
+
+  grouping l2-tunnel-service {
+    description
+      "Defines a Layer 2 tunnel termination.";
+    leaf type {
+      type identityref {
+        base l2-tunnel-type;
+      }
+      description
+        "Selects the tunnel termination type for an AC.";
+    }
+    container pseudowire {
+      when "derived-from-or-self(../type, 'ac-common:pseudowire')" {
+        description
+          "Only applies when the Layer 2 service type is
+           'pseudowire'.";
+      }
+      description
+        "Includes pseudowire termination parameters.";
+      uses pseudowire;
+    }
+    container vpls {
+      when "derived-from-or-self(../type, 'ac-common:vpls')" {
+        description
+          "Only applies when the Layer 2 service type is 'vpls'.";
+      }
+      description
+        "VPLS termination parameters.";
+      uses vpls;
+    }
+    container vxlan {
+      when "derived-from-or-self(../type, 'ac-common:vxlan')" {
+        description
+          "Only applies when the Layer 2 service type is 'vxlan'.";
+      }
+      description
+        "VXLAN termination parameters.";
+      uses vxlan;
+    }
+  }
+
+  /**** Layer 3 connection *****/
+  // IPv4 allocation type
+
+  grouping ipv4-allocation-type {
+    description
+      "IPv4-specific parameters.";
+    leaf prefix-length {
+      type uint8 {
+        range "0..32";
+      }
+      description
+        "Subnet prefix length expressed in bits. It is applied to
+         both local and customer addresses.";
+    }
+    leaf address-allocation-type {
+      type identityref {
+        base address-allocation-type;
+      }
+      must "not(derived-from-or-self(current(), 'ac-common:slaac') "
+         + "or derived-from-or-self(current(), "
+         + "'ac-common:provider-dhcp-slaac'))" {
+        error-message "SLAAC is only applicable to IPv6.";
+      }
+      description
+        "Defines how IPv4 addresses are allocated to the peer site.";
+    }
+  }
+
+  // IPv6 allocation type
+
+  grouping ipv6-allocation-type {
+    description
+      "IPv6-specific parameters.";
+    leaf prefix-length {
+      type uint8 {
+        range "0..128";
+      }
+      description
+        "Subnet prefix length expressed in bits. It is applied to
+          both local and customer addresses.";
+    }
+    leaf address-allocation-type {
+      type identityref {
+        base address-allocation-type;
+      }
+      description
+        "Defines how IPv6 addresses are allocated to the peer site.";
+    }
+  }
+
+  // Basic parameters for IPv4 connection
+
+  grouping ipv4-connection-basic {
+    description
+      "Basic set fof IPv4-specific parameters for the connection.";
+    uses ipv4-allocation-type;
+    choice allocation-type {
+      description
+        "Choice of the IPv4 address allocation.";
+      case dynamic {
+        description
+          "When the addresses are allocated by DHCP or other dynamic
+           means local to the infrastructure.";
+        choice provider-dhcp {
+          description
+            "Parameters related to DHCP-allocated addresses. IP
+             addresses are allocated by DHCP, that is provided by
+             the operator.";
+          leaf dhcp-service-type {
+            type enumeration {
+              enum server {
+                description
+                  "Local DHCP server.";
+              }
+              enum relay {
+                description
+                  "Local DHCP relay.  DHCP requests are relayed to
+                   a provider's server.";
+              }
+            }
+            description
+              "Indicates the type of DHCP service to be enabled on
+               an AC.";
+          }
+        }
+        choice dhcp-relay {
+          description
+            "The DHCP relay is provided by the operator.";
+          container customer-dhcp-servers {
+            description
+              "Container for a list of the customer's DHCP servers.";
+            leaf-list server-ip-address {
+              type inet:ipv4-address;
+              description
+                "IPv4 addresses of the customer's DHCP server.";
+            }
+          }
+        }
+      }
+    }
+  }
+
+  // Basic parameters for IPv6 connection
+
+  grouping ipv6-connection-basic {
+    description
+      "Basic set fof IPv6-specific parameters for the connection.";
+    uses ipv6-allocation-type;
+    choice allocation-type {
+      description
+        "Choice of the IPv6 address allocation.";
+      case dynamic {
+        description
+          "When the addresses are allocated by DHCP or other dynamic
+           means local to the infrastructure.";
+        choice provider-dhcp {
+          description
+            "Parameters related to DHCP-allocated addresses.
+             IP addresses are allocated by DHCP, that is provided
+             by the operator.";
+          leaf dhcp-service-type {
+            type enumeration {
+              enum server {
+                description
+                  "Local DHCP server.";
+              }
+              enum relay {
+                description
+                  "Local DHCP relay.  DHCP requests are relayed to a
+                   provider's server.";
+              }
+            }
+            description
+              "Indicates the type of DHCP service to be enabled on
+               the AC.";
+          }
+        }
+        choice dhcp-relay {
+          description
+            "The DHCP relay is provided by the operator.";
+          container customer-dhcp-servers {
+            description
+              "Container for a list of the customer's DHCP servers.";
+            leaf-list server-ip-address {
+              type inet:ipv6-address;
+              description
+                "IPv6 addresses of the customer's DHCP server.";
+            }
+          }
+        }
+      }
+    }
+  }
+  // Full parameters for the IPv4 connection
+
+  grouping ipv4-connection {
+    description
+      "IPv4-specific parameters.";
+    leaf local-address {
+      type inet:ipv4-address;
+      description
+        "The IP address used at the provider's interface.";
+    }
+    leaf virtual-address {
+      type inet:ipv4-address;
+      description
+        "This addresss may be used for redundancy purposes.";
+    }
+    uses ipv4-allocation-type;
+    choice allocation-type {
+      description
+        "Choice of the IPv4 address allocation.";
+      case dynamic {
+        description
+          "When the addresses are allocated by DHCP or other
+           dynamic means local to the infrastructure.";
+        choice address-assign {
+          description
+            "A choice for how IPv4 addresses are assigned.";
+          case number {
+            leaf number-of-dynamic-address {
+              type uint16;
+              description
+                "Specifies the number of IP addresses to be assigned
+                 to the customer on the AC.";
+            }
+          }
+          case explicit {
+            container customer-addresses {
+              description
+                "Container for customer addresses to be allocated
+                 using DHCP.";
+              list address-pool {
+                key "pool-id";
+                description
+                  "Describes IP addresses to be dyncamically
+                   allocated.
+
+                   When only 'start-address' is present, it
+                   represents a single address.
+
+                   When both 'start-address' and 'end-address' are
+                   specified, it implies a range inclusive of both
+                   addresses.";
+                leaf pool-id {
+                  type string;
+                  description
+                    "A pool identifier for the address range from
+                     'start-address' to 'end-address'.";
+                }
+                leaf start-address {
+                  type inet:ipv4-address;
+                  mandatory true;
+                  description
+                    "Indicates the first address in the pool.";
+                }
+                leaf end-address {
+                  type inet:ipv4-address;
+                  description
+                    "Indicates the last address in the pool.";
+                }
+              }
+            }
+          }
+        }
+        choice provider-dhcp {
+          description
+            "Parameters related to DHCP-allocated addresses. IP
+             addresses are allocated by DHCP, which is provided by
+             the operator.";
+          leaf dhcp-service-type {
+            type enumeration {
+              enum server {
+                description
+                  "Local DHCP server.";
+              }
+              enum relay {
+                description
+                  "Local DHCP relay.  DHCP requests are relayed to
+                   a provider's server.";
+              }
+            }
+            description
+              "Indicates the type of DHCP service to be enabled on
+               this AC.";
+          }
+        }
+        choice dhcp-relay {
+          description
+            "The DHCP relay is provided by the operator.";
+          container customer-dhcp-servers {
+            description
+              "Container for a list of the customer's DHCP servers.";
+            leaf-list server-ip-address {
+              type inet:ipv4-address;
+              description
+                "IPv4 addresses of the customer's DHCP server.";
+            }
+          }
+        }
+      }
+      case static-addresses {
+        description
+          "Lists the IPv4 addresses that are used.";
+        list address {
+          key "address-id";
+          ordered-by user;
+          description
+            "Lists the IPv4 addresses that are used. The first
+             address of the list is the primary address of the
+             connection.";
+          leaf address-id {
+            type string;
+            description
+              "An identifier of the static IPv4 address.";
+          }
+          leaf customer-address {
+            type inet:ipv4-address;
+            description
+              "An IPv4 address of the customer side.";
+          }
+        }
+      }
+    }
+  }
+
+  // Full parameters for the IPv6 connection
+
+  grouping ipv6-connection {
+    description
+      "IPv6-specific parameters.";
+    leaf local-address {
+      type inet:ipv6-address;
+      description
+        "IPv6 address of the provider side.";
+    }
+    leaf virtual-address {
+      type inet:ipv6-address;
+      description
+        "This addresss may be used for redundancy purposes.";
+    }
+    uses ipv6-allocation-type;
+    choice allocation-type {
+      description
+        "Choice of the IPv6 address allocation.";
+      case dynamic {
+        description
+          "When the addresses are allocated by DHCP or other
+           dynamic means local to the infrastructure.";
+        choice address-assign {
+          description
+            "A choice for how IPv6 addresses are assigned.";
+          case number {
+            leaf number-of-dynamic-address {
+              type uint16;
+              description
+                "Specifies the number of IP addresses to be
+                 assigned to the customer on this access.";
+            }
+          }
+          case explicit {
+            container customer-addresses {
+              description
+                "Container for customer addresses to be allocated
+                 using DHCP.";
+              list address-pool {
+                key "pool-id";
+                description
+                  "Describes IP addresses to be dyncamically
+                   allocated.
+
+                   When only 'start-address' is present, it
+                   represents a single address.
+
+                   When both 'start-address' and 'end-address' are
+                   specified, it implies a range inclusive of both
+                   addresses.";
+                leaf pool-id {
+                  type string;
+                  description
+                    "A pool identifier for the address range from
+                     'start-address' to 'end-address'.";
+                }
+                leaf start-address {
+                  type inet:ipv6-address;
+                  mandatory true;
+                  description
+                    "Indicates the first address in the pool.";
+                }
+                leaf end-address {
+                  type inet:ipv6-address;
+                  description
+                    "Indicates the last address in the pool.";
+                }
+              }
+            }
+          }
+        }
+        choice provider-dhcp {
+          description
+            "Parameters related to DHCP-allocated addresses.
+             IP addresses are allocated by DHCP, which is provided
+             by the operator.";
+          leaf dhcp-service-type {
+            type enumeration {
+              enum server {
+                description
+                  "Local DHCP server.";
+              }
+              enum relay {
+                description
+                  "Local DHCP relay.  DHCP requests are relayed
+                   to a provider's server.";
+              }
+            }
+            description
+              "Indicates the type of DHCP service to
+               be enabled on this access.";
+          }
+        }
+        choice dhcp-relay {
+          description
+            "The DHCP relay is provided by the operator.";
+          container customer-dhcp-servers {
+            description
+              "Container for a list of the customer's DHCP servers.";
+            leaf-list server-ip-address {
+              type inet:ipv6-address;
+              description
+                "IPv6 addresses of the customer's DHCP server.";
+            }
+          }
+        }
+      }
+      case static-addresses {
+        description
+          "Lists the IPv6 addresses that are used.";
+        list address {
+          key "address-id";
+          ordered-by user;
+          description
+            "Lists the IPv6 addresses that are used. The first
+             address of the list is the primary IP address of
+             the connection.";
+          leaf address-id {
+            type string;
+            description
+              "An identifier of the static IPv6 address.";
+          }
+          leaf customer-address {
+            type inet:ipv6-address;
+            description
+              "An IPv6 address of the customer side.";
+          }
+        }
+      }
+    }
+  }
+
+  /**** Routing ****/
+  // Routing authentication
+
+  grouping bgp-authentication {
+    description
+      "Grouping for BGP authentication parameters.";
+    container authentication {
+      description
+        "Container for BGP authentication  parameters.";
+      leaf enabled {
+        type boolean;
+        description
+          "Enables or disables authentication.";
+      }
+      container keying-material {
+        when "../enabled = 'true'";
+        description
+          "Container for describing how a BGP routing session is to
+           be secured on an AC.";
+        choice option {
+          description
+            "Choice of authentication options.";
+          case ao {
+            description
+              "Uses the TCP Authentication Option (TCP-AO).";
+            reference
+              "RFC 5925: The TCP Authentication Option";
+            leaf enable-ao {
+              type boolean;
+              description
+                "Enables the TCP-AO.";
+            }
+            leaf ao-keychain {
+              type key-chain:key-chain-ref;
+              description
+                "Reference to the TCP-AO key chain.";
+              reference
+                "RFC 8177: YANG Data Model for Key Chains";
+            }
+          }
+          case md5 {
+            description
+              "Uses MD5 to secure the session.";
+            reference
+              "RFC 4364: BGP/MPLS IP Virtual Private Networks
+                         (VPNs), Section 13.2";
+            leaf md5-keychain {
+              type key-chain:key-chain-ref;
+              description
+                "Reference to the MD5 key chain.";
+              reference
+                "RFC 8177: YANG Data Model for Key Chains";
+            }
+          }
+          case explicit {
+            leaf key-id {
+              type uint32;
+              description
+                "Key identifier.";
+            }
+            leaf key {
+              type string;
+              description
+                "BGP authentication key.
+
+                 This model only supports the subset of keys that
+                 are representable as ASCII strings.";
+            }
+            leaf crypto-algorithm {
+              type identityref {
+                base key-chain:crypto-algorithm;
+              }
+              description
+                "Indicates the cryptographic algorithm associated
+                 with the key.";
+            }
+          }
+        }
+      }
+    }
+  }
+
+  grouping ospf-authentication {
+    description
+      "Authentication configuration.";
+    container authentication {
+      description
+        "Container for OSPF authentication  parameters.";
+      leaf enabled {
+        type boolean;
+        description
+          "Enables or disables authentication.";
+      }
+      container keying-material {
+        when "../enabled = 'true'";
+        description
+          "Container for describing how an OSPF session is to be
+           secured for this AC.";
+        choice option {
+          description
+            "Options for OSPF authentication.";
+          case auth-key-chain {
+            leaf key-chain {
+              type key-chain:key-chain-ref;
+              description
+                "Name of the key chain.";
+            }
+          }
+          case auth-key-explicit {
+            leaf key-id {
+              type uint32;
+              description
+                "Key identifier.";
+            }
+            leaf key {
+              type string;
+              description
+                "OSPF authentication key.
+                 This model only supports the subset of keys that
+                 are representable as ASCII strings.";
+            }
+            leaf crypto-algorithm {
+              type identityref {
+                base key-chain:crypto-algorithm;
+              }
+              description
+                "Indicates the cryptographic algorithm associated
+                 with the key.";
+            }
+          }
+        }
+      }
+    }
+  }
+
+  grouping isis-authentication {
+    description
+      "IS-IS authentication configuration.";
+    container authentication {
+      description
+        "Container for IS-IS authentication  parameters.";
+      leaf enabled {
+        type boolean;
+        description
+          "Enables or disables authentication.";
+      }
+      container keying-material {
+        when "../enabled = 'true'";
+        description
+          "Container for describing how an IS-IS session is secured
+           over an AC.";
+        choice option {
+          description
+            "Options for IS-IS authentication.";
+          case auth-key-chain {
+            leaf key-chain {
+              type key-chain:key-chain-ref;
+              description
+                "Name of the key chain.";
+            }
+          }
+          case auth-key-explicit {
+            leaf key-id {
+              type uint32;
+              description
+                "Key identifier.";
+            }
+            leaf key {
+              type string;
+              description
+                "IS-IS authentication key.
+
+                 This model only supports the subset of keys that
+                 are representable as ASCII strings.";
+            }
+            leaf crypto-algorithm {
+              type identityref {
+                base key-chain:crypto-algorithm;
+              }
+              description
+                "Indicates the cryptographic algorithm associated
+                 with the key.";
+            }
+          }
+        }
+      }
+    }
+  }
+
+  grouping rip-authentication {
+    description
+      "RIP authentication configuration.";
+    container authentication {
+      description
+        "Container for RIP authentication  parameters.";
+      leaf enabled {
+        type boolean;
+        description
+          "Enables or disables authentication.";
+      }
+      container keying-material {
+        when "../enabled = 'true'";
+        description
+          "Container for describing how a RIP session is to be
+           secured on this AC.";
+        choice option {
+          description
+            "Specifies the authentication
+             scheme.";
+          case auth-key-chain {
+            leaf key-chain {
+              type key-chain:key-chain-ref;
+              description
+                "Name of the key chain.";
+            }
+          }
+          case auth-key-explicit {
+            leaf key {
+              type string;
+              description
+                "RIP authentication key.
+
+                 This model only supports the subset of keys that
+                 are representable as ASCII strings.";
+            }
+            leaf crypto-algorithm {
+              type identityref {
+                base key-chain:crypto-algorithm;
+              }
+              description
+                "Indicates the cryptographic algorithm associated
+                 with the key.";
+            }
+          }
+        }
+      }
+    }
+  }
+
+  // Basic routing parameters
+
+  grouping bgp-peer-group-without-name {
+    description
+      "Identifies a BGP peer-group configured on the local system.";
+    leaf local-as {
+      type inet:as-number;
+      description
+        "Indicates a local AS Number (ASN). This ASN is exposed
+         to a customer so that it knows which ASN to use
+         to set up a BGP session.";
+    }
+    leaf peer-as {
+      type inet:as-number;
+      description
+        "Indicates the customer's ASN when the customer
+         requests BGP routing.";
+    }
+    leaf address-family {
+      type identityref {
+        base vpn-common:address-family;
+      }
+      description
+        "This node contains the address families to be activated.
+         'dual-stack' means that both IPv4 and IPv6 will be
+         activated.";
+    }
+    leaf role {
+      type identityref {
+        base ac-common:bgp-role;
+      }
+      description
+        "Specifies the BGP role (provider, customer, peer, etc.).";
+      reference
+        "RFC 9234: Route Leak Prevention and Detection Using
+                   Roles in UPDATE and OPEN Messages, Section 4";
+    }
+  }
+
+  grouping bgp-peer-group-with-name {
+    description
+      "Identifies a BGP peer-group configured on the local system -
+       identified by a peer-group name.";
+    leaf name {
+      type string;
+      description
+        "Name of the BGP peer-group.";
+    }
+    uses bgp-peer-group-without-name;
+  }
+
+  grouping ospf-basic {
+    description
+      "Configuration specific to OSPF.";
+    leaf address-family {
+      type identityref {
+        base vpn-common:address-family;
+      }
+      description
+        "Indicates whether IPv4, IPv6, or both are to be activated.";
+    }
+    leaf area-id {
+      type yang:dotted-quad;
+      mandatory true;
+      description
+        "Area ID.";
+      reference
+        "RFC 4577: OSPF as the Provider/Customer Edge Protocol
+                   for BGP/MPLS IP Virtual Private Networks
+                   (VPNs), Section 4.2.3
+         RFC 6565: OSPFv3 as a Provider Edge to Customer Edge
+                   (PE-CE) Routing Protocol, Section 4.2";
+    }
+    leaf metric {
+      type uint16;
+      description
+        "Metric of the AC.  It is used in the routing state
+         calculation and path selection.";
+    }
+  }
+
+  grouping isis-basic {
+    description
+      "Basic configuration specific to IS-IS.";
+    leaf address-family {
+      type identityref {
+        base vpn-common:address-family;
+      }
+      description
+        "Indicates whether IPv4, IPv6, or both are to be activated.";
+    }
+    leaf area-address {
+      type area-address;
+      mandatory true;
+      description
+        "Area address.";
+    }
+  }
+
+  // Static routing
+
+  grouping ipv4-static-rtg-entry {
+    description
+      "Paramters to configure a specific IPv4 static routing entry.";
+    leaf lan {
+      type inet:ipv4-prefix;
+      description
+        "LAN prefix.";
+    }
+    leaf lan-tag {
+      type string;
+      description
+        "Internal tag to be used in service policies.";
+    }
+    leaf next-hop {
+      type union {
+        type inet:ip-address;
+        type predefined-next-hop;
+      }
+      description
+        "The next hop that is to be used for the static route.
+         This may be specified as an IP address or a
+         predefined next-hop type (e.g., 'discard' or
+         'local-link').";
+    }
+    leaf metric {
+      type uint32;
+      description
+        "Indicates the metric associated with the static route.";
+    }
+  }
+
+  grouping ipv4-static-rtg {
+    description
+      "Configuration specific to IPv4 static routing.";
+    list ipv4-lan-prefixes {
+      if-feature "vpn-common:ipv4";
+      key "lan next-hop";
+      description
+        "List of LAN prefixes for the site.";
+      uses ipv4-static-rtg-entry;
+      uses ac-common:service-status;
+    }
+  }
+
+  grouping ipv6-static-rtg-entry {
+    description
+      "Paramters to configure a specific IPv6 static routing entry.";
+    leaf lan {
+      type inet:ipv6-prefix;
+      description
+        "LAN prefixes.";
+    }
+    leaf lan-tag {
+      type string;
+      description
+        "Internal tag to be used in service (e.g., VPN) policies.";
+    }
+    leaf next-hop {
+      type union {
+        type inet:ip-address;
+        type predefined-next-hop;
+      }
+      description
+        "The next hop that is to be used for the static route.
+         This may be specified as an IP address or a predefined
+         next-hop type (e.g., 'discard' or 'local-link').";
+    }
+    leaf metric {
+      type uint32;
+      description
+        "Indicates the metric associated with the static route.";
+    }
+  }
+
+  grouping ipv6-static-rtg {
+    description
+      "Configuration specific to IPv6 static routing.";
+    list ipv6-lan-prefixes {
+      if-feature "vpn-common:ipv6";
+      key "lan next-hop";
+      description
+        "List of LAN prefixes for the site.";
+      uses ipv6-static-rtg-entry;
+      uses ac-common:service-status;
+    }
+  }
+
+  // OAM
+
+  grouping bfd {
+    description
+      "A grouping for basic BFD.";
+    leaf holdtime {
+      type uint32;
+      units "milliseconds";
+      description
+        "Expected BFD holdtime.
+         The customer may impose some fixed values
+         for the holdtime period if the provider allows
+         the customer to use this function.
+         If the provider doesn't allow the customer to
+         use this function, fixed values will not be set.";
+      reference
+        "RFC 5880: Bidirectional Forwarding Detection (BFD),
+                   Section 6.8.18";
+    }
+  }
+
+  // redundancy
+
+  grouping redundancy-group {
+    description
+      "A grouping for redundancy group.";
+    list group {
+       key "group-id";
+       description
+         "List of group-ids.";
+       leaf group-id {
+         type string;
+         description
+           "Indicates the group-id to which the AC belongs.";
+       }
+       leaf precedence {
+         type identityref {
+           base ac-common:precedence-type;
+         }
+         description
+           "Defines redundancy of an AC.";
+       }
+     }
+   }
+
+  // QoS
+
+  grouping bandwidth-parameters {
+    description
+      "A grouping for bandwidth parameters.";
+    leaf cir {
+      type uint64;
+      units "bps";
+      description
+        "Committed Information Rate (CIR). The maximum number of bits
+         that a port can receive or send during one second over
+         an interface.";
+    }
+    leaf cbs {
+      type uint64;
+      units "bytes";
+      description
+        "Committed Burst Size (CBS). CBS controls the bursty nature
+         of the traffic.  Traffic that does not use the configured
+         CIR accumulates credits until the credits reach the
+         configured CBS.";
+    }
+    leaf eir {
+      type uint64;
+      units "bps";
+      description
+        "Excess Information Rate (EIR), i.e., excess frame delivery
+         allowed not subject to a Service Level Agreement (SLA).
+         The traffic rate can be limited by EIR.";
+    }
+    leaf ebs {
+      type uint64;
+      units "bytes";
+      description
+        "Excess Burst Size (EBS).  The bandwidth available for burst
+         traffic from the EBS is subject to the amount of bandwidth
+         that is accumulated during periods when traffic allocated
+         by the EIR policy is not used.";
+    }
+    leaf pir {
+      type uint64;
+      units "bps";
+      description
+        "Peak Information Rate (PIR), i.e., maximum frame delivery
+         allowed. It is equal to or less than sum of CIR and EIR.";
+    }
+    leaf pbs {
+      type uint64;
+      units "bytes";
+      description
+        "Peak Burst Size (PBS).";
+    }
+  }
+
+  grouping bandwidth-per-type {
+    description
+      "Grouping for bandwidth per type.";
+    list bandwidth {
+      key "bw-type";
+      description
+        "List for bandwidth per type data nodes.";
+      leaf bw-type {
+        type identityref {
+          base vpn-common:bw-type;
+        }
+        description
+          "Indicates the bandwidth type.";
+      }
+      choice type {
+        description
+          "Choice based upon bandwidth type.";
+        case per-cos {
+          description
+            "Bandwidth per CoS.";
+          list cos {
+            key "cos-id";
+            description
+              "List of Class of Services.";
+            leaf cos-id {
+              type uint8;
+              description
+                "Identifier of the CoS, indicated by a Differentiated
+                 Services Code Point (DSCP) or a CE-CLAN CoS (802.1p)
+                 value in the service frame.";
+              reference
+                "IEEE Std 802.1Q: Bridges and Bridged Networks";
+            }
+            uses bandwidth-parameters;
+          }
+        }
+        case other {
+          description
+            "Other bandwidth types.";
+          uses bandwidth-parameters;
+        }
+      }
+    }
+  }
+}
diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-ac-svc@2024-08-06.yang b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-ac-svc@2024-08-06.yang
new file mode 100644
index 0000000000000000000000000000000000000000..a5790644f1f7600cfad42663f2e7c7ed13134ac1
--- /dev/null
+++ b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-ac-svc@2024-08-06.yang
@@ -0,0 +1,1252 @@
+module ietf-ac-svc {
+  yang-version 1.1;
+  namespace "urn:ietf:params:xml:ns:yang:ietf-ac-svc";
+  prefix ac-svc;
+
+  import ietf-ac-common {
+    prefix ac-common;
+    reference
+      "RFC CCCC: A Common YANG Data Model for Attachment Circuits";
+  }
+  import ietf-vpn-common {
+    prefix vpn-common;
+    reference
+      "RFC 9181: A Common YANG Data Model for Layer 2 and Layer 3
+                 VPNs";
+  }
+  import ietf-netconf-acm {
+    prefix nacm;
+    reference
+      "RFC 8341: Network Configuration Access Control Model";
+  }
+  import ietf-inet-types {
+    prefix inet;
+    reference
+      "RFC 6991: Common YANG Data Types, Section 4";
+  }
+  import ietf-key-chain {
+    prefix key-chain;
+    reference
+      "RFC 8177: YANG Data Model for Key Chains";
+  }
+
+  organization
+    "IETF OPSAWG (Operations and Management Area Working Group)";
+  contact
+    "WG Web:   <https://datatracker.ietf.org/wg/opsawg/>
+     WG List:  <mailto:opsawg@ietf.org>
+
+     Editor:   Mohamed Boucadair
+               <mailto:mohamed.boucadair@orange.com>
+     Author:   Richard Roberts
+               <mailto:rroberts@juniper.net>
+     Author:   Oscar Gonzalez de Dios
+               <mailto:oscar.gonzalezdedios@telefonica.com>
+     Author:   Samier Barguil
+               <mailto:ssamier.barguil_giraldo@nokia.com>
+     Author:   Bo Wu
+               <mailto:lana.wubo@huawei.com>";
+  description
+    "This YANG module defines a YANG model for exposing
+     attachment circuits as a service (ACaaS).
+
+     Copyright (c) 2024 IETF Trust and the persons identified as
+     authors of the code.  All rights reserved.
+
+     Redistribution and use in source and binary forms, with or
+     without modification, is permitted pursuant to, and subject
+     to the license terms contained in, the Revised BSD License
+     set forth in Section 4.c of the IETF Trust's Legal Provisions
+     Relating to IETF Documents
+     (https://trustee.ietf.org/license-info).
+
+     This version of this YANG module is part of RFC XXXX; see the
+     RFC itself for full legal notices.";
+
+  revision 2024-08-06 {
+    description
+      "Initial revision.";
+    reference
+      "RFC XXXX: YANG Data Models for Bearers and 'Attachment
+                 Circuits'-as-a-Service (ACaaS)";
+  }
+
+  /* A set of typedefs to ease referencing cross-modules */
+
+  typedef attachment-circuit-reference {
+    type leafref {
+      path "/ac-svc:attachment-circuits/ac-svc:ac/ac-svc:name";
+    }
+    description
+      "Defines a reference to an attachment circuit that can be used
+       by other modules.";
+  }
+
+  typedef ac-group-reference {
+    type leafref {
+      path "/ac-svc:attachment-circuits/ac-svc:ac-group-profile"
+         + "/ac-svc:name";
+    }
+    description
+      "Defines a reference to an attachment circuit profile.";
+  }
+
+  typedef encryption-profile-reference {
+    type leafref {
+      path
+        "/ac-svc:specific-provisioning-profiles"
+      + "/ac-svc:valid-provider-identifiers"
+      + "/ac-svc:encryption-profile-identifier/ac-svc:id";
+    }
+    description
+      "Defines a reference to an encryption profile.";
+  }
+
+  typedef qos-profile-reference {
+    type leafref {
+      path
+        "/ac-svc:specific-provisioning-profiles"
+      + "/ac-svc:valid-provider-identifiers"
+      + "/ac-svc:qos-profile-identifier/ac-svc:id";
+    }
+    description
+      "Defines a reference to a QoS profile.";
+  }
+
+  typedef failure-detection-profile-reference {
+    type leafref {
+      path
+        "/ac-svc:specific-provisioning-profiles"
+      + "/ac-svc:valid-provider-identifiers"
+      + "/ac-svc:failure-detection-profile-identifier"
+      + "/ac-svc:id";
+    }
+    description
+      "Defines a reference to a BFD profile.";
+  }
+
+  typedef forwarding-profile-reference {
+    type leafref {
+      path
+        "/ac-svc:specific-provisioning-profiles"
+      + "/ac-svc:valid-provider-identifiers"
+      + "/ac-svc:forwarding-profile-identifier/ac-svc:id";
+    }
+    description
+      "Defines a reference to a forwarding profile.";
+  }
+
+  typedef routing-profile-reference {
+    type leafref {
+      path
+        "/ac-svc:specific-provisioning-profiles"
+      + "/ac-svc:valid-provider-identifiers"
+      + "/ac-svc:routing-profile-identifier/ac-svc:id";
+    }
+    description
+      "Defines a reference to a routing profile.";
+  }
+
+  typedef service-profile-reference {
+    type leafref {
+      path
+        "/ac-svc:service-provisioning-profiles"
+      + "/ac-svc:service-profile-identifier"
+      + "/ac-svc:id";
+    }
+    description
+      "Defines a reference to a service profile.";
+  }
+
+  /******************** Reusable groupings ********************/
+  // Basic Layer 2 connection
+
+  grouping l2-connection-basic {
+    description
+      "Defines Layer 2 protocols and parameters that can be
+       factorized when provisioning Layer 2 connectivity
+       among multiple ACs.";
+    container encapsulation {
+      description
+        "Container for Layer 2 encapsulation.";
+      leaf type {
+        type identityref {
+          base vpn-common:encapsulation-type;
+        }
+        description
+          "Encapsulation type.";
+      }
+      container dot1q {
+        when "derived-from-or-self(../type, 'vpn-common:dot1q')" {
+          description
+            "Only applies when the type of the tagged interface
+             is 'dot1q'.";
+        }
+        description
+          "Tagged interface.";
+        uses ac-common:dot1q;
+      }
+      container qinq {
+        when "derived-from-or-self(../type, 'vpn-common:qinq')" {
+          description
+            "Only applies when the type of the tagged interface
+             is 'qinq'.";
+        }
+        description
+          "Includes QinQ parameters.";
+        uses ac-common:qinq;
+      }
+    }
+  }
+
+  // Full Layer 2 connection
+
+  grouping l2-connection {
+    description
+      "Defines Layer 2 protocols and parameters that are used to
+       enable AC connectivity.";
+    container encapsulation {
+      description
+        "Container for Layer 2 encapsulation.";
+      leaf type {
+        type identityref {
+          base vpn-common:encapsulation-type;
+        }
+        description
+          "Indicates the encapsulation type.";
+      }
+      container dot1q {
+        when "derived-from-or-self(../type, 'vpn-common:dot1q')" {
+          description
+            "Only applies when the type of the tagged interface
+             is 'dot1q'.";
+        }
+        description
+          "Tagged interface.";
+        uses ac-common:dot1q;
+      }
+      container priority-tagged {
+        when "derived-from-or-self(../type, "
+           + "'vpn-common:priority-tagged')" {
+          description
+            "Only applies when the type of the tagged interface is
+             'priority-tagged'.";
+        }
+        description
+          "Priority-tagged interface.";
+        uses ac-common:priority-tagged;
+      }
+      container qinq {
+        when "derived-from-or-self(../type, 'vpn-common:qinq')" {
+          description
+            "Only applies when the type of the tagged interface
+             is 'qinq'.";
+        }
+        description
+          "Includes QinQ parameters.";
+        uses ac-common:qinq;
+      }
+    }
+    choice l2-service {
+      description
+        "The Layer 2 connectivity service can be provided by
+         indicating a pointer to an L2VPN or by specifying a
+         Layer 2 tunnel service.";
+      container l2-tunnel-service {
+        description
+          "Defines a Layer 2 tunnel termination.
+           It is only applicable when a tunnel is required.";
+        uses ac-common:l2-tunnel-service;
+      }
+      case l2vpn {
+        leaf l2vpn-id {
+          type vpn-common:vpn-id;
+          description
+            "Indicates the L2VPN service associated with an
+             Integrated Routing and Bridging (IRB) interface.";
+        }
+      }
+    }
+    leaf bearer-reference {
+      if-feature "ac-common:server-assigned-reference";
+      type string;
+      description
+        "This is an internal reference for the service provider
+         to identify the bearer associated with this AC.";
+    }
+  }
+
+  // Basic IP connection
+
+  grouping ip-connection-basic {
+    description
+      "Defines basic IP connection parameters.";
+    container ipv4 {
+      if-feature "vpn-common:ipv4";
+      description
+        "IPv4-specific parameters.";
+      uses ac-common:ipv4-connection-basic;
+    }
+    container ipv6 {
+      if-feature "vpn-common:ipv6";
+      description
+        "IPv6-specific parameters.";
+      uses ac-common:ipv6-connection-basic;
+    }
+  }
+
+  // Full IP connection
+
+  grouping ip-connection {
+    description
+      "Defines IP connection parameters.";
+    container ipv4 {
+      if-feature "vpn-common:ipv4";
+      description
+        "IPv4-specific parameters.";
+      uses ac-common:ipv4-connection {
+        augment ac-svc:allocation-type/static-addresses/address {
+          leaf failure-detection-profile {
+            if-feature "vpn-common:bfd";
+            type failure-detection-profile-reference;
+            description
+              "Points to a failure detection profile.";
+          }
+          description
+            "Adds a failure detection profile.";
+        }
+      }
+    }
+    container ipv6 {
+      if-feature "vpn-common:ipv6";
+      description
+        "IPv6-specific parameters.";
+      uses ac-common:ipv6-connection {
+        augment ac-svc:allocation-type/static-addresses/address {
+          leaf failure-detection-profile {
+            if-feature "vpn-common:bfd";
+            type failure-detection-profile-reference;
+            description
+              "Points to a failure detection profile.";
+          }
+          description
+            "Adds a failure detection profile.";
+        }
+      }
+    }
+    choice l3-service {
+      description
+        "The Layer 3 connectivity service can be provided by
+         specifying a Layer 3 tunnel service.";
+      container l3-tunnel-service {
+        description
+          "Defines a Layer 3 tunnel termination.
+           It is only applicable when a tunnel is required.";
+        leaf type {
+          type identityref {
+            base ac-common:l3-tunnel-type;
+          }
+          description
+            "Selects the tunnel termination type for an AC.";
+        }
+      }
+    }
+  }
+
+  // Routing protocol list
+
+  grouping routing-protocol-list {
+    description
+      "List of routing protocols used on the AC.";
+    leaf type {
+      type identityref {
+        base vpn-common:routing-protocol-type;
+      }
+      description
+        "Type of routing protocol.";
+    }
+    list routing-profiles {
+      key "id";
+      description
+        "Routing profiles.";
+      leaf id {
+        type routing-profile-reference;
+        description
+          "Reference to the routing profile to be used.";
+      }
+      leaf type {
+        type identityref {
+          base vpn-common:ie-type;
+        }
+        description
+          "Import, export, or both.";
+      }
+    }
+  }
+
+  // Static routing with BFD
+
+  grouping ipv4-static-rtg-with-bfd {
+    description
+      "Configuration specific to IPv4 static routing with
+       failure protection (e.g., BFD).";
+    list ipv4-lan-prefix {
+      if-feature "vpn-common:ipv4";
+      key "lan next-hop";
+      description
+        "List of LAN prefixes for the site.";
+      uses ac-common:ipv4-static-rtg-entry;
+      leaf failure-detection-profile {
+        if-feature "vpn-common:bfd";
+        type failure-detection-profile-reference;
+        description
+          "Points to a failure detection profile.";
+      }
+      uses ac-common:service-status;
+    }
+  }
+
+  grouping ipv6-static-rtg-with-bfd {
+    description
+      "Configuration specific to IPv6 static routing with
+       failure protection (e.g., BFD).";
+    list ipv6-lan-prefix {
+      if-feature "vpn-common:ipv6";
+      key "lan next-hop";
+      description
+        "List of LAN prefixes for the site.";
+      uses ac-common:ipv6-static-rtg-entry;
+      leaf failure-detection-profile {
+        if-feature "vpn-common:bfd";
+        type failure-detection-profile-reference;
+        description
+          "Points to a failure detection profile.";
+      }
+      uses ac-common:service-status;
+    }
+  }
+
+  //  BGP Service 
+
+  grouping bgp-neighbor-without-name {
+    description
+      "A grouping with generic parameters for configuring a BGP 
+       neighbor.";
+    leaf remote-address {
+      type inet:ip-address;
+      description
+        "The remote IP address of this entry's BGP peer. This is
+         a customer IP address.
+
+         If this leaf is not present, this means that the primary
+         customer IP address is used as remote IP address.";
+    }
+    leaf local-address {
+      type inet:ip-address;
+      description
+        "The provider's IP address that will be used to establish
+         the BGP session.";
+    }
+    uses ac-common:bgp-peer-group-without-name;
+    container bgp-max-prefix {
+      description
+        "A container for the maximum number of BGP prefixes
+         allowed in the BGP session.";
+      leaf max-prefix {
+        type uint32;
+        description
+          "Indicates the maximum number of BGP prefixes allowed
+           in the BGP session.
+
+           It allows control of how many prefixes can be received
+           from a neighbor.";
+        reference
+          "RFC 4271: A Border Gateway Protocol 4 (BGP-4),
+                     Section 8.2.2";
+      }
+    }
+    uses ac-common:bgp-authentication;
+    uses ac-common:op-instructions;
+    uses ac-common:service-status;
+  }
+
+  grouping bgp-neighbor-with-name {
+    description
+      "A grouping with generic parameters for configuring a BGP 
+       neighbor with an identifier.";
+    leaf id {
+      type string;
+      description
+        "An identifier that uniquely identifies a neighbor.";
+    }
+    uses ac-svc:bgp-neighbor-without-name;
+  }
+
+  grouping bgp-neighbor-with-server-reference {
+    description
+      "A grouping with generic parameters for configuring a BGP 
+       neighbor with a reference generated by the provider.";
+    leaf server-reference {
+      if-feature "ac-common:server-assigned-reference";
+      type string;
+      config false;
+      description
+        "This is an internal reference for the service provider
+         to identify the BGP session.";
+    }
+    uses ac-svc:bgp-neighbor-without-name;
+  }
+
+  grouping bgp-neighbor-with-name-server-reference {
+    description
+      "A grouping with generic parameters for configuring a BGP 
+       neighbor with an identifier and a reference generated by 
+       the provider.";
+    leaf id {
+      type string;
+      description
+        "An identifier that uniquely identifiers a neighbor.";
+    }
+    uses ac-svc:bgp-neighbor-with-server-reference;
+  }
+
+  grouping bgp-svc {
+    description
+      "Configuration specific to BGP.";
+    container peer-groups {
+      description
+        "Configuration for BGP peer-groups";
+      list peer-group {
+        key "name";
+        description
+          "List of BGP peer-groups configured on the local 
+           system - uniquely identified by peer-group
+           name.";
+        uses ac-common:bgp-peer-group-with-name;
+        leaf local-address {
+          type inet:ip-address;
+          description
+            "The provider's local IP address that will be used to
+             establish the BGP session.";
+        }
+        container bgp-max-prefix {
+          description
+            "A container for the maximum number of BGP prefixes
+             allowed in the BGP session.";
+          leaf max-prefix {
+            type uint32;
+            description
+              "Indicates the maximum number of BGP prefixes allowed
+               in the BGP session.
+
+               It allows control of how many prefixes can be received
+               from a neighbor.";
+            reference
+              "RFC 4271: A Border Gateway Protocol 4 (BGP-4),
+                         Section 8.2.2";
+          }
+        }
+        uses ac-common:bgp-authentication;
+      }
+    }
+    list neighbor {
+      key "id";
+      description
+        "List of BGP neighbors.";
+      uses ac-svc:bgp-neighbor-with-name-server-reference;
+      leaf peer-group {
+        type leafref {
+          path "../../peer-groups/peer-group/name";
+        }
+        description
+          "The peer-group with which this neighbor is associated.";
+      }
+      leaf failure-detection-profile {
+        if-feature "vpn-common:bfd";
+        type failure-detection-profile-reference;
+        description
+          "Points to a failure detection profile.";
+      }
+    }
+  }
+
+  //  OSPF Service 
+
+  grouping ospf-svc {
+    description
+      "Service configuration specific to OSPF.";
+    uses ac-common:ospf-basic;
+    uses ac-common:ospf-authentication;
+    uses ac-common:service-status;
+  }
+
+  //  IS-IS Service 
+
+  grouping isis-svc {
+    description
+      "Service configuration specific to IS-IS.";
+    uses ac-common:isis-basic;
+    uses ac-common:isis-authentication;
+    uses ac-common:service-status;
+  }
+
+  //  RIP Service 
+
+  grouping rip-svc {
+    description
+      "Service configuration specific to RIP routing.";
+    leaf address-family {
+      type identityref {
+        base vpn-common:address-family;
+      }
+      description
+        "Indicates whether IPv4, IPv6, or both address families
+         are to be activated.";
+    }
+    uses ac-common:rip-authentication;
+    uses ac-common:service-status;
+  }
+
+  //  VRRP Service 
+
+  grouping vrrp-svc {
+    description
+      "Service configuration specific to VRRP.";
+    reference
+      "RFC 9568: Virtual Router Redundancy Protocol (VRRP)
+                 Version 3 for IPv4 and IPv6";
+    leaf address-family {
+      type identityref {
+        base vpn-common:address-family;
+      }
+      description
+        "Indicates whether IPv4, IPv6, or both
+         address families are to be enabled.";
+    }
+    uses ac-common:service-status;
+  }
+
+  // Basic routing parameters
+
+  grouping routing-basic {
+    description
+      "Defines basic parameters for routing protocols.";
+    list routing-protocol {
+      key "id";
+      description
+        "List of routing protocols used on the AC.";
+      leaf id {
+        type string;
+        description
+          "Unique identifier for the routing protocol.";
+      }
+      uses routing-protocol-list;
+      container bgp {
+        when
+          "derived-from-or-self(../type, 'vpn-common:bgp-routing')" {
+          description
+            "Only applies when the protocol is BGP.";
+        }
+        if-feature "vpn-common:rtg-bgp";
+        description
+          "Configuration specific to BGP.";
+        container peer-groups {
+          description
+            "Configuration for BGP peer-groups";
+          list peer-group {
+            key "name";
+            description
+              "List of BGP peer-groups configured on the local
+               system - uniquely identified by peer-group
+               name.";
+            uses ac-common:bgp-peer-group-with-name;
+          }
+        }
+      }
+      container ospf {
+        when "derived-from-or-self(../type, "
+           + "'vpn-common:ospf-routing')" {
+          description
+            "Only applies when the protocol is OSPF.";
+        }
+        if-feature "vpn-common:rtg-ospf";
+        description
+          "Configuration specific to OSPF.";
+        uses ac-common:ospf-basic;
+      }
+      container isis {
+        when "derived-from-or-self(../type, "
+           + "'vpn-common:isis-routing')" {
+          description
+            "Only applies when the protocol is IS-IS.";
+        }
+       if-feature "vpn-common:rtg-isis";
+        description
+          "Configuration specific to IS-IS.";
+        uses ac-common:isis-basic;
+      }
+      container rip {
+        when "derived-from-or-self(../type, "
+           + "'vpn-common:rip-routing')" {
+          description
+            "Only applies when the protocol is RIP.
+             For IPv4, the model assumes that RIP
+             version 2 is used.";
+        }
+        if-feature "vpn-common:rtg-rip";
+        description
+          "Configuration specific to RIP routing.";
+        leaf address-family {
+          type identityref {
+            base vpn-common:address-family;
+          }
+          description
+            "Indicates whether IPv4, IPv6, or both
+             address families are to be activated.";
+        }
+      }
+      container vrrp {
+        when "derived-from-or-self(../type, "
+           + "'vpn-common:vrrp-routing')" {
+          description
+            "Only applies when the protocol is the
+             Virtual Router Redundancy Protocol (VRRP).";
+        }
+        if-feature "vpn-common:rtg-vrrp";
+        description
+          "Configuration specific to VRRP.";
+        leaf address-family {
+          type identityref {
+            base vpn-common:address-family;
+          }
+          description
+            "Indicates whether IPv4, IPv6, or both address families
+             are to be enabled.";
+        }
+      }
+    }
+  }
+
+  // Full routing parameters
+
+  grouping routing {
+    description
+      "Defines routing protocols.";
+    list routing-protocol {
+      key "id";
+      description
+        "List of routing protocols used on the AC.";
+      leaf id {
+        type string;
+        description
+          "Unique identifier for the routing protocol.";
+      }
+      uses routing-protocol-list;
+      container static {
+        when "derived-from-or-self(../type, "
+           + "'vpn-common:static-routing')" {
+          description
+            "Only applies when the protocol is static routing
+             protocol.";
+        }
+        description
+          "Configuration specific to static routing.";
+        container cascaded-lan-prefixes {
+          description
+            "LAN prefixes from the customer.";
+          uses ipv4-static-rtg-with-bfd;
+          uses ipv6-static-rtg-with-bfd;
+        }
+      }
+      container bgp {
+        when "derived-from-or-self(../type, "
+           + "'vpn-common:bgp-routing')" {
+          description
+            "Only applies when the protocol is BGP.";
+        }
+        if-feature "vpn-common:rtg-bgp";
+        description
+          "Configuration specific to BGP.";
+        uses bgp-svc;
+      }
+      container ospf {
+        when "derived-from-or-self(../type, "
+           + "'vpn-common:ospf-routing')" {
+          description
+            "Only applies when the protocol is OSPF.";
+        }
+        if-feature "vpn-common:rtg-ospf";
+        description
+          "Configuration specific to OSPF.";
+        uses ospf-svc;
+      }
+      container isis {
+        when "derived-from-or-self(../type, "
+           + "'vpn-common:isis-routing')" {
+          description
+            "Only applies when the protocol is IS-IS.";
+        }
+        if-feature "vpn-common:rtg-isis";
+        description
+          "Configuration specific to IS-IS.";
+        uses isis-svc;
+      }
+      container rip {
+        when "derived-from-or-self(../type, "
+           + "'vpn-common:rip-routing')" {
+          description
+            "Only applies when the protocol is RIP.
+             For IPv4, the model assumes that RIP version 2 is
+             used.";
+        }
+        if-feature "vpn-common:rtg-rip";
+        description
+          "Configuration specific to RIP routing.";
+        uses rip-svc;
+      }
+      container vrrp {
+        when "derived-from-or-self(../type, "
+           + "'vpn-common:vrrp-routing')" {
+          description
+            "Only applies when the protocol is the Virtual Router
+             Redundancy Protocol (VRRP).";
+        }
+        if-feature "vpn-common:rtg-vrrp";
+        description
+          "Configuration specific to VRRP.";
+        uses vrrp-svc;
+      }
+    }
+  }
+
+  // Encryption choice
+
+  grouping encryption-choice {
+    description
+      "Container for the encryption profile.";
+    choice profile {
+      description
+        "Choice for the encryption profile.";
+      case provider-profile {
+        leaf provider-profile {
+          type encryption-profile-reference;
+          description
+            "Reference to a provider encryption profile.";
+        }
+      }
+      case customer-profile {
+        leaf customer-key-chain {
+          type key-chain:key-chain-ref;
+          description
+            "Customer-supplied key chain.";
+        }
+      }
+    }
+  }
+
+  // Basic security parameters
+
+  grouping ac-security-basic {
+    description
+      "AC-specific security parameters.";
+    container encryption {
+      if-feature "vpn-common:encryption";
+      description
+        "Container for AC security encryption.";
+      leaf enabled {
+        type boolean;
+        description
+          "If set to 'true', traffic encryption on the connection
+           is required.  Otherwise, it is disabled.";
+      }
+      leaf layer {
+        when "../enabled = 'true'" {
+          description
+            "Included only when encryption is enabled.";
+        }
+        type enumeration {
+          enum layer2 {
+            description
+              "Encryption occurs at Layer 2.";
+          }
+          enum layer3 {
+            description
+              "Encryption occurs at Layer 3.
+               For example, IPsec may be used when a customer 
+               requests Layer 3 encryption.";
+          }
+        }
+        description
+          "Indicates the layer on which encryption is applied.";
+      }
+    }
+    container encryption-profile {
+      when "../encryption/enabled = 'true'" {
+        description
+          "Indicates the layer on which encryption is enabled.";
+      }
+      description
+        "Container for the encryption profile.";
+      uses encryption-choice;
+    }
+  }
+
+  // Bandwith parameters
+
+  grouping bandwidth {
+    description
+      "Container for bandwidth.";
+    container svc-pe-to-ce-bandwidth {
+      if-feature "vpn-common:inbound-bw";
+      description
+        "From the customer site's perspective, the inbound
+         bandwidth of the AC or download bandwidth from the
+         service provider to the site.";
+      uses ac-common:bandwidth-per-type;
+    }
+    container svc-ce-to-pe-bandwidth {
+      if-feature "vpn-common:outbound-bw";
+      description
+        "From the customer site's perspective, the outbound
+         bandwidth of the AC or upload bandwidth from
+         the CE to the PE.";
+      uses ac-common:bandwidth-per-type;
+    }
+  }
+
+  // Basic AC parameters
+
+  grouping ac-basic {
+    description
+      "Grouping for basic parameters for an attachment circuit.";
+    leaf name {
+      type string;
+      description
+        "A name that uniquely identifies the AC.";
+    }
+    container l2-connection {
+      if-feature "ac-common:layer2-ac";
+      description
+        "Defines Layer 2 protocols and parameters that are required 
+         to enable AC connectivity.";
+      uses l2-connection-basic;
+    }
+    container ip-connection {
+      if-feature "ac-common:layer3-ac";
+      description
+        "Defines IP connection parameters.";
+      uses ip-connection-basic;
+    }
+    container routing-protocols {
+      description
+        "Defines routing protocols.";
+      uses routing-basic;
+    }
+    container oam {
+      description
+        "Defines the Operations, Administration, and Maintenance
+         (OAM) mechanisms used.";
+      container bfd {
+        if-feature "vpn-common:bfd";
+        description
+          "Container for BFD.";
+        uses ac-common:bfd;
+      }
+    }
+    container security {
+      description
+        "AC-specific security parameters.";
+      uses ac-security-basic;
+    }
+    container service {
+      description
+        "AC-specific bandwith parameters.";
+      leaf mtu {
+        type uint32;
+        units "bytes";
+        description
+          "Layer 2 MTU.";
+      }
+      uses bandwidth;
+    }
+  }
+
+  // Full AC parameters
+
+  grouping ac {
+    description
+      "Grouping for an attachment circuit.";
+    leaf name {
+      type string;
+      description
+        "A name of the AC. Data models that need to reference  
+         an attachment circuit should use 
+         attachment-circuit-reference.";
+    }
+    leaf-list service-profile {
+      type service-profile-reference;
+      description
+        "A reference to a service profile.";
+    }
+    container l2-connection {
+      if-feature "ac-common:layer2-ac";
+      description
+        "Defines Layer 2 protocols and parameters that are required 
+         to enable AC connectivity.";
+      uses l2-connection;
+    }
+    container ip-connection {
+      if-feature "ac-common:layer3-ac";
+      description
+        "Defines IP connection parameters.";
+      uses ip-connection;
+    }
+    container routing-protocols {
+      description
+        "Defines routing protocols.";
+      uses routing;
+    }
+    container oam {
+      description
+        "Defines the OAM mechanisms used.";
+      container bfd {
+        if-feature "vpn-common:bfd";
+        description
+          "Container for BFD.";
+        list session {
+          key "id";
+          description
+            "List of BFD sessions.";
+          leaf id {
+             type string;
+             description
+               "A unique identifer for the BFD session.";
+          }
+          leaf local-address {
+            type inet:ip-address;
+            description
+              "Provider's IP address of the BFD session.";
+          }
+          leaf remote-address {
+            type inet:ip-address;
+            description
+              "Customer's IP address of the BFD session.";
+          }
+          leaf profile {
+            type failure-detection-profile-reference;
+            description
+              "Points to a BFD profile.";
+          }
+          uses ac-common:bfd;
+          uses ac-common:service-status;
+        } 
+      }
+    }
+    container security {
+      description
+        "AC-specific security parameters.";
+      uses ac-security-basic;
+    }
+    container service {
+      description
+        "AC-specific bandwith parameters.";
+      leaf mtu {
+        type uint32;
+        units "bytes";
+        description
+          "Layer 2 MTU.";
+      }
+      uses bandwidth;
+      container qos {
+        if-feature "vpn-common:qos";
+        description
+          "QoS configuration.";
+        container qos-profiles {
+          description
+            "QoS profile configuration.";
+          list qos-profile {
+            key "profile";
+            description
+              "Points to a QoS profile.";
+            leaf profile {
+              type qos-profile-reference;
+              description
+                "QoS profile to be used.";
+            }
+            leaf direction {
+              type identityref {
+                base vpn-common:qos-profile-direction;
+              }
+              description
+                "The direction to which the QoS profile
+                 is applied.";
+            }
+          }
+        }
+      }
+      container access-control-list {
+        description
+          "Container for the Access Control List (ACL).";
+        container acl-profiles {
+          description
+            "ACL profile configuration.";
+          list acl-profile {
+            key "profile";
+            description
+              "Points to an ACL profile.";
+            leaf profile {
+              type forwarding-profile-reference;
+              description
+                "Forwarding profile to be used.";
+            }
+          }
+        }
+      }
+    }
+  }
+
+  // Parent and Child ACs
+
+  grouping ac-hierarchy {
+    description
+      "Container for parent and child AC references.";
+    leaf-list parent-ref {
+      type ac-svc:attachment-circuit-reference;
+      description
+        "Specifies a parent AC that is inherited by an AC.
+         In contexts where dynamic terminating points are 
+         bound to the same AC, a parent AC with stable
+         information is created with a set of child ACs
+         to track dynamic AC information.";
+    }
+    leaf-list child-ref {
+      type ac-svc:attachment-circuit-reference;
+      config false;
+      description
+        "Specifies a child AC that relies upon a parent AC.";
+    }
+  }
+
+  /******************** Main AC containers ********************/
+
+  container specific-provisioning-profiles {
+    description
+      "Contains a set of valid profiles to reference for an AC.";
+    uses ac-common:ac-profile-cfg;
+  }
+  container service-provisioning-profiles {
+    description
+      "Contains a set of valid profiles to reference for an AC.";
+    list service-profile-identifier {
+      key "id";
+      description
+        "List of generic service profile identifiers.";
+      leaf id {
+        type string;
+        description
+          "Identification of the service profile to be used.
+           The profile only has significance within the service
+           provider's administrative domain.";
+      }
+    }
+    nacm:default-deny-write;
+  }
+  container attachment-circuits {
+    description
+      "Main container for the attachment circuits.";
+    list ac-group-profile {
+      key "name";
+      description
+        "Maintains a list of profiles that are shared among
+         a set of ACs.";
+      uses ac;
+    }
+    container placement-constraints {
+      description
+        "Diversity constraint type.";
+      uses vpn-common:placement-constraints;
+    }
+    leaf customer-name {
+      type string;
+      description
+        "Indicates the name of the customer that requested these
+         ACs.";
+    }
+    uses ac-common:op-instructions;
+    list ac {
+      key "name";
+      description
+        "Global provisioning of attachment circuits.";
+      leaf customer-name {
+        type string;
+        description
+          "Indicates the name of the customer that requested this
+           AC.";
+      }
+      leaf description {
+        type string;
+        description
+          "Associates a description with an AC.";
+      }
+      leaf test-only {
+        type empty;
+        description
+         "When present, this indicates that this is a feasibility
+          check request. No resources are commited for such AC 
+          requests.";
+      }
+      uses ac-common:op-instructions;
+      leaf role {
+        type identityref {
+          base ac-common:role;
+        }
+        description
+          "Indicates whether this AC is used as UNI, NNI, etc.";
+      }
+      leaf-list peer-sap-id {
+        type string;
+        description
+          "One or more peer SAPs can be indicated.";
+      }
+      leaf-list group-profile-ref {
+        type ac-group-reference;
+        description
+          "A reference to an AC profile.";
+      }
+      uses ac-hierarchy;
+      uses ac-common:redundancy-group;
+      list service-ref {
+        key "service-type service-id";
+        config false;
+        description
+          "Reports the set of services that are bound to the AC.";
+        leaf service-type {
+          type identityref {
+            base vpn-common:service-type;
+          }
+          description
+            "Indicates the service type (e.g., L3VPN or Network Slice
+             Service).";
+          reference
+            "RFC 9408: A YANG Network Data Model for Service 
+                       Attachment Points (SAPs), Section 5";
+        }
+        leaf service-id {
+          type string;
+          description
+            "Indicates an identifier of a service instance
+             of a given type that uses the AC.";
+        }
+      }
+      leaf server-reference {
+        if-feature "ac-common:server-assigned-reference";
+        type string;
+        config false;
+        description
+          "Reports an internal reference for the service provider
+           to identify the AC.";
+      }
+      uses ac;
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-ethertypes@2019-03-04.yang b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-ethertypes@2019-03-04.yang
new file mode 100644
index 0000000000000000000000000000000000000000..fd055074aeba5c277bbefdce0b81ebd24d0d3551
--- /dev/null
+++ b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-ethertypes@2019-03-04.yang
@@ -0,0 +1,381 @@
+module ietf-ethertypes {
+  namespace "urn:ietf:params:xml:ns:yang:ietf-ethertypes";
+  prefix ethertypes;
+
+  organization
+    "IETF NETMOD (Network Modeling) Working Group.";
+
+  contact
+    "WG Web:   <https://datatracker.ietf.org/wg/netmod/>
+     WG List:  <mailto:netmod@ietf.org>
+
+     Editor:   Mahesh Jethanandani
+               <mjethanandani@gmail.com>";
+
+  description
+    "This module contains common definitions for the
+     Ethertype used by different modules.  It is a
+     placeholder module, till such time that IEEE
+     starts a project to define these Ethertypes
+     and publishes a standard.
+
+     At that time, this module can be deprecated.
+
+     Copyright (c) 2019 IETF Trust and the persons identified as
+     the document authors.  All rights reserved.
+
+     Redistribution and use in source and binary forms, with or
+     without modification, is permitted pursuant to, and subject
+     to the license terms contained in, the Simplified BSD
+     License set forth in Section 4.c of the IETF Trust's Legal
+     Provisions Relating to IETF Documents
+     (http://trustee.ietf.org/license-info).
+
+     This version of this YANG module is part of RFC 8519; see
+     the RFC itself for full legal notices.";
+
+  revision 2019-03-04 {
+    description
+      "Initial revision.";
+    reference
+      "RFC 8519: YANG Data Model for Network Access Control
+                 Lists (ACLs).";
+  }
+
+  typedef ethertype {
+    type union {
+      type uint16;
+      type enumeration {
+        enum ipv4 {
+          value 2048;
+          description
+            "Internet Protocol version 4 (IPv4) with a
+             hex value of 0x0800.";
+          reference
+            "RFC 791: Internet Protocol.";
+        }
+        enum arp {
+          value 2054;
+          description
+            "Address Resolution Protocol (ARP) with a
+             hex value of 0x0806.";
+          reference
+            "RFC 826: An Ethernet Address Resolution Protocol: Or
+                      Converting Network Protocol Addresses to 48.bit
+                      Ethernet Address for Transmission on Ethernet
+                      Hardware.";
+        }
+        enum wlan {
+          value 2114;
+          description
+            "Wake-on-LAN.  Hex value of 0x0842.";
+        }
+        enum trill {
+          value 8947;
+          description
+            "Transparent Interconnection of Lots of Links.
+             Hex value of 0x22F3.";
+          reference
+            "RFC 6325: Routing Bridges (RBridges): Base Protocol
+                       Specification.";
+        }
+        enum srp {
+          value 8938;
+          description
+            "Stream Reservation Protocol.  Hex value of
+             0x22EA.";
+          reference
+            "IEEE 801.1Q-2011.";
+        }
+        enum decnet {
+          value 24579;
+          description
+            "DECnet Phase IV.  Hex value of 0x6003.";
+        }
+        enum rarp {
+          value 32821;
+          description
+            "Reverse Address Resolution Protocol.
+             Hex value 0x8035.";
+          reference
+            "RFC 903: A Reverse Address Resolution Protocol.";
+        }
+        enum appletalk {
+          value 32923;
+          description
+            "Appletalk (Ethertalk).  Hex value of 0x809B.";
+        }
+        enum aarp {
+          value 33011;
+          description
+            "Appletalk Address Resolution Protocol.  Hex value
+             of 0x80F3.";
+        }
+        enum vlan {
+          value 33024;
+          description
+            "VLAN-tagged frame (IEEE 802.1Q) and Shortest Path
+             Bridging IEEE 802.1aq with Network-Network
+             Interface (NNI) compatibility.  Hex value of
+             0x8100.";
+          reference
+            "IEEE 802.1Q.";
+        }
+        enum ipx {
+          value 33079;
+          description
+            "Internetwork Packet Exchange (IPX).  Hex value
+             of 0x8137.";
+        }
+        enum qnx {
+          value 33284;
+          description
+            "QNX Qnet.  Hex value of 0x8204.";
+        }
+        enum ipv6 {
+          value 34525;
+          description
+            "Internet Protocol Version 6 (IPv6).  Hex value
+             of 0x86DD.";
+          reference
+            "RFC 8200: Internet Protocol, Version 6 (IPv6)
+                       Specification
+             RFC 8201: Path MTU Discovery for IP version 6.";
+        }
+        enum efc {
+          value 34824;
+          description
+            "Ethernet flow control using pause frames.
+             Hex value of 0x8808.";
+          reference
+            "IEEE 802.1Qbb.";
+        }
+        enum esp {
+          value 34825;
+          description
+            "Ethernet Slow Protocol.  Hex value of 0x8809.";
+          reference
+            "IEEE 802.3-2015.";
+        }
+        enum cobranet {
+          value 34841;
+          description
+            "CobraNet.  Hex value of 0x8819.";
+        }
+        enum mpls-unicast {
+          value 34887;
+          description
+            "Multiprotocol Label Switching (MPLS) unicast traffic.
+             Hex value of 0x8847.";
+          reference
+            "RFC 3031: Multiprotocol Label Switching Architecture.";
+        }
+        enum mpls-multicast {
+          value 34888;
+          description
+            "MPLS multicast traffic.  Hex value of 0x8848.";
+          reference
+            "RFC 3031: Multiprotocol Label Switching Architecture.";
+        }
+        enum pppoe-discovery {
+          value 34915;
+          description
+            "Point-to-Point Protocol over Ethernet.  Used during
+             the discovery process.  Hex value of 0x8863.";
+          reference
+            "RFC 2516: A Method for Transmitting PPP Over Ethernet
+                       (PPPoE).";
+        }
+        enum pppoe-session {
+          value 34916;
+          description
+            "Point-to-Point Protocol over Ethernet.  Used during
+             session stage.  Hex value of 0x8864.";
+          reference
+            "RFC 2516: A Method for Transmitting PPP Over Ethernet
+                       (PPPoE).";
+        }
+        enum intel-ans {
+          value 34925;
+          description
+            "Intel Advanced Networking Services.  Hex value of
+             0x886D.";
+        }
+        enum jumbo-frames {
+          value 34928;
+          description
+            "Jumbo frames or Ethernet frames with more than
+             1500 bytes of payload, up to 9000 bytes.";
+        }
+        enum homeplug {
+          value 34939;
+          description
+            "Family name for the various power line
+             communications.  Hex value of 0x887B.";
+        }
+        enum eap {
+          value 34958;
+          description
+            "Ethernet Access Protocol (EAP) over LAN.  Hex value
+             of 0x888E.";
+          reference
+            "IEEE 802.1X.";
+        }
+        enum profinet {
+          value 34962;
+          description
+            "PROcess FIeld Net (PROFINET).  Hex value of 0x8892.";
+        }
+        enum hyperscsi {
+          value 34970;
+          description
+            "Small Computer System Interface (SCSI) over Ethernet.
+             Hex value of 0x889A.";
+        }
+        enum aoe {
+          value 34978;
+          description
+            "Advanced Technology Advancement (ATA) over Ethernet.
+             Hex value of 0x88A2.";
+        }
+        enum ethercat {
+          value 34980;
+          description
+            "Ethernet for Control Automation Technology (EtherCAT).
+             Hex value of 0x88A4.";
+        }
+        enum provider-bridging {
+          value 34984;
+          description
+            "Provider Bridging (802.1ad) and Shortest Path Bridging
+             (801.1aq).  Hex value of 0x88A8.";
+          reference
+            "IEEE 802.1ad and IEEE 802.1aq).";
+        }
+        enum ethernet-powerlink {
+          value 34987;
+          description
+            "Ethernet Powerlink.  Hex value of 0x88AB.";
+        }
+        enum goose {
+          value 35000;
+          description
+            "Generic Object Oriented Substation Event (GOOSE).
+             Hex value of 0x88B8.";
+          reference
+            "IEC/ISO 8802-2 and 8802-3.";
+        }
+        enum gse {
+          value 35001;
+          description
+            "Generic Substation Events.  Hex value of 88B9.";
+          reference
+            "IEC 61850.";
+        }
+        enum sv {
+          value 35002;
+          description
+            "Sampled Value Transmission.  Hex value of 0x88BA.";
+          reference
+            "IEC 61850.";
+        }
+        enum lldp {
+          value 35020;
+          description
+            "Link Layer Discovery Protocol (LLDP).  Hex value of
+             0x88CC.";
+          reference
+            "IEEE 802.1AB.";
+        }
+        enum sercos {
+          value 35021;
+          description
+            "Sercos Interface.  Hex value of 0x88CD.";
+        }
+        enum wsmp {
+          value 35036;
+          description
+            "WAVE Short Message Protocol (WSMP).  Hex value of
+             0x88DC.";
+        }
+        enum homeplug-av-mme {
+          value 35041;
+          description
+            "HomePlug AV Mobile Management Entity (MME).  Hex value
+             of 88E1.";
+        }
+        enum mrp {
+          value 35043;
+          description
+            "Media Redundancy Protocol (MRP).  Hex value of
+             0x88E3.";
+          reference
+            "IEC 62439-2.";
+        }
+        enum macsec {
+          value 35045;
+          description
+            "MAC Security.  Hex value of 0x88E5.";
+          reference
+            "IEEE 802.1AE.";
+        }
+        enum pbb {
+          value 35047;
+          description
+            "Provider Backbone Bridges (PBB).  Hex value of
+             0x88E7.";
+          reference
+            "IEEE 802.1ah.";
+        }
+        enum cfm {
+          value 35074;
+          description
+            "Connectivity Fault Management (CFM).  Hex value of
+             0x8902.";
+          reference
+            "IEEE 802.1ag.";
+        }
+        enum fcoe {
+          value 35078;
+          description
+            "Fiber Channel over Ethernet (FCoE).  Hex value of
+             0x8906.";
+          reference
+            "T11 FC-BB-5.";
+        }
+        enum fcoe-ip {
+          value 35092;
+          description
+            "FCoE Initialization Protocol.  Hex value of 0x8914.";
+        }
+        enum roce {
+          value 35093;
+          description
+            "RDMA over Converged Ethernet (RoCE).  Hex value of
+             0x8915.";
+        }
+        enum tte {
+          value 35101;
+          description
+            "TTEthernet Protocol Control Frame (TTE).  Hex value
+             of 0x891D.";
+          reference
+            "SAE AS6802.";
+        }
+        enum hsr {
+          value 35119;
+          description
+            "High-availability Seamless Redundancy (HSR).  Hex
+             value of 0x892F.";
+          reference
+            "IEC 62439-3:2016.";
+        }
+      }
+    }
+    description
+      "The uint16 type placeholder is defined to enable
+       users to manage their own ethertypes not
+       covered by the module.  Otherwise, the module contains
+       enum definitions for the more commonly used ethertypes.";
+  }
+}
diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-geo-location@2022-02-11.yang b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-geo-location@2022-02-11.yang
new file mode 100644
index 0000000000000000000000000000000000000000..b815446f819ac2dcba50e63e5781e8a1be9b59c6
--- /dev/null
+++ b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-geo-location@2022-02-11.yang
@@ -0,0 +1,278 @@
+module ietf-geo-location {
+  yang-version 1.1;
+  namespace "urn:ietf:params:xml:ns:yang:ietf-geo-location";
+  prefix geo;
+  import ietf-yang-types {
+    prefix yang;
+    reference "RFC 6991: Common YANG Data Types";
+  }
+
+  organization
+    "IETF NETMOD Working Group (NETMOD)";
+  contact
+   "WG Web:   <https://datatracker.ietf.org/wg/netmod/>
+    WG List:  <mailto:netmod@ietf.org>
+
+    Editor:   Christian Hopps
+              <mailto:chopps@chopps.org>";
+
+  description
+    "This module defines a grouping of a container object for
+     specifying a location on or around an astronomical object (e.g.,
+     'earth').
+
+     The key words 'MUST', 'MUST NOT', 'REQUIRED', 'SHALL', 'SHALL
+     NOT', 'SHOULD', 'SHOULD NOT', 'RECOMMENDED', 'NOT RECOMMENDED',
+     'MAY', and 'OPTIONAL' in this document are to be interpreted as
+     described in BCP 14 (RFC 2119) (RFC 8174) when, and only when,
+     they appear in all capitals, as shown here.
+
+     Copyright (c) 2022 IETF Trust and the persons identified as
+     authors of the code.  All rights reserved.
+
+     Redistribution and use in source and binary forms,
+     with or without modification, is permitted pursuant to,
+     and subject to the license terms contained in, the
+     Revised BSD License set forth in Section 4.c of the
+     IETF Trust's Legal Provisions Relating to IETF Documents
+     (https://trustee.ietf.org/license-info).
+
+     This version of this YANG module is part of RFC 9179
+     (https://www.rfc-editor.org/info/rfc9179); see the RFC itself
+     for full legal notices.";
+
+  revision 2022-02-11 {
+    description
+      "Initial Revision";
+    reference
+      "RFC 9179: A YANG Grouping for Geographic Locations";
+  }
+
+  feature alternate-systems {
+    description
+      "This feature means the device supports specifying locations
+       using alternate systems for reference frames.";
+  }
+
+  grouping geo-location {
+    description
+      "Grouping to identify a location on an astronomical object.";
+
+    container geo-location {
+      description
+        "A location on an astronomical body (e.g., 'earth')
+         somewhere in a universe.";
+
+      container reference-frame {
+        description
+          "The Frame of Reference for the location values.";
+
+        leaf alternate-system {
+          if-feature "alternate-systems";
+          type string;
+          description
+            "The system in which the astronomical body and
+             geodetic-datum is defined.  Normally, this value is not
+             present and the system is the natural universe; however,
+             when present, this value allows for specifying alternate
+             systems (e.g., virtual realities).  An alternate-system
+             modifies the definition (but not the type) of the other
+             values in the reference frame.";
+        }
+        leaf astronomical-body {
+          type string {
+            pattern '[ -@\[-\^_-~]*';
+          }
+          default "earth";
+          description
+            "An astronomical body as named by the International
+             Astronomical Union (IAU) or according to the alternate
+             system if specified.  Examples include 'sun' (our star),
+             'earth' (our planet), 'moon' (our moon), 'enceladus' (a
+             moon of Saturn), 'ceres' (an asteroid), and
+             '67p/churyumov-gerasimenko (a comet).  The ASCII value
+             SHOULD have uppercase converted to lowercase and not
+             include control characters (i.e., values 32..64, and
+             91..126).  Any preceding 'the' in the name SHOULD NOT be
+             included.";
+          reference
+            "https://www.iau.org/";
+        }
+        container geodetic-system {
+          description
+            "The geodetic system of the location data.";
+          leaf geodetic-datum {
+            type string {
+              pattern '[ -@\[-\^_-~]*';
+            }
+            description
+              "A geodetic-datum defining the meaning of latitude,
+               longitude, and height.  The default when the
+               astronomical body is 'earth' is 'wgs-84', which is
+               used by the Global Positioning System (GPS).  The
+               ASCII value SHOULD have uppercase converted to
+               lowercase and not include control characters
+               (i.e., values 32..64, and 91..126).  The IANA registry
+               further restricts the value by converting all spaces
+               (' ') to dashes ('-').
+               The specification for the geodetic-datum indicates
+               how accurately it models the astronomical body in
+               question, both for the 'horizontal'
+               latitude/longitude coordinates and for height
+               coordinates.";
+            reference
+              "RFC 9179: A YANG Grouping for Geographic Locations,
+               Section 6.1";
+          }
+          leaf coord-accuracy {
+            type decimal64 {
+              fraction-digits 6;
+            }
+            description
+              "The accuracy of the latitude/longitude pair for
+               ellipsoidal coordinates, or the X, Y, and Z components
+               for Cartesian coordinates.  When coord-accuracy is
+               specified, it indicates how precisely the coordinates
+               in the associated list of locations have been
+               determined with respect to the coordinate system
+               defined by the geodetic-datum.  For example, there
+               might be uncertainty due to measurement error if an
+               experimental measurement was made to determine each
+               location.";
+          }
+          leaf height-accuracy {
+            type decimal64 {
+              fraction-digits 6;
+            }
+            units "meters";
+            description
+              "The accuracy of the height value for ellipsoidal
+               coordinates; this value is not used with Cartesian
+               coordinates.  When height-accuracy is specified, it
+               indicates how precisely the heights in the
+               associated list of locations have been determined
+               with respect to the coordinate system defined by the
+               geodetic-datum.  For example, there might be
+               uncertainty due to measurement error if an
+               experimental measurement was made to determine each
+               location.";
+          }
+        }
+      }
+      choice location {
+        description
+          "The location data either in latitude/longitude or
+           Cartesian values";
+        case ellipsoid {
+          leaf latitude {
+            type decimal64 {
+              fraction-digits 16;
+            }
+            units "decimal degrees";
+            description
+              "The latitude value on the astronomical body.  The
+               definition and precision of this measurement is
+               indicated by the reference-frame.";
+          }
+          leaf longitude {
+            type decimal64 {
+              fraction-digits 16;
+            }
+            units "decimal degrees";
+            description
+              "The longitude value on the astronomical body.  The
+               definition and precision of this measurement is
+               indicated by the reference-frame.";
+          }
+          leaf height {
+            type decimal64 {
+              fraction-digits 6;
+            }
+            units "meters";
+            description
+              "Height from a reference 0 value.  The precision and
+               '0' value is defined by the reference-frame.";
+          }
+        }
+        case cartesian {
+          leaf x {
+            type decimal64 {
+              fraction-digits 6;
+            }
+            units "meters";
+            description
+              "The X value as defined by the reference-frame.";
+          }
+          leaf y {
+            type decimal64 {
+              fraction-digits 6;
+            }
+            units "meters";
+            description
+              "The Y value as defined by the reference-frame.";
+          }
+          leaf z {
+            type decimal64 {
+              fraction-digits 6;
+            }
+            units "meters";
+            description
+              "The Z value as defined by the reference-frame.";
+          }
+        }
+      }
+      container velocity {
+        description
+          "If the object is in motion, the velocity vector describes
+           this motion at the time given by the timestamp.  For a
+           formula to convert these values to speed and heading, see
+           RFC 9179.";
+        reference
+          "RFC 9179: A YANG Grouping for Geographic Locations";
+
+        leaf v-north {
+          type decimal64 {
+            fraction-digits 12;
+          }
+          units "meters per second";
+          description
+            "v-north is the rate of change (i.e., speed) towards
+             true north as defined by the geodetic-system.";
+        }
+
+        leaf v-east {
+          type decimal64 {
+            fraction-digits 12;
+          }
+          units "meters per second";
+          description
+            "v-east is the rate of change (i.e., speed) perpendicular
+             to the right of true north as defined by
+             the geodetic-system.";
+        }
+
+        leaf v-up {
+          type decimal64 {
+            fraction-digits 12;
+          }
+          units "meters per second";
+          description
+            "v-up is the rate of change (i.e., speed) away from the
+             center of mass.";
+        }
+      }
+      leaf timestamp {
+        type yang:date-and-time;
+        description
+          "Reference time when location was recorded.";
+      }
+      leaf valid-until {
+        type yang:date-and-time;
+        description
+          "The timestamp for which this geo-location is valid until.
+           If unspecified, the geo-location has no specific
+           expiration time.";
+      }
+    }
+  }
+}
diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-inet-types@2024-10-21.yang b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-inet-types@2024-10-21.yang
new file mode 100644
index 0000000000000000000000000000000000000000..78c5201baf73f339d3ac409083b1f8ea13682faf
--- /dev/null
+++ b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-inet-types@2024-10-21.yang
@@ -0,0 +1,657 @@
+module ietf-inet-types {
+
+  namespace "urn:ietf:params:xml:ns:yang:ietf-inet-types";
+  prefix "inet";
+
+  organization
+   "IETF Network Modeling (NETMOD) Working Group";
+
+  contact
+   "WG Web:   <https://datatracker.ietf.org/wg/netmod/>
+    WG List:  <mailto:netmod@ietf.org>
+
+    Editor:   Juergen Schoenwaelder
+              <mailto:jschoenwaelder@constructor.university>";
+
+  description
+   "This module contains a collection of generally useful derived
+    YANG data types for Internet addresses and related things.
+
+    The key words 'MUST', 'MUST NOT', 'REQUIRED', 'SHALL', 'SHALL
+    NOT', 'SHOULD', 'SHOULD NOT', 'RECOMMENDED', 'NOT RECOMMENDED',
+    'MAY', and 'OPTIONAL' in this document are to be interpreted as
+    described in BCP 14 (RFC 2119) (RFC 8174) when, and only when,
+    they appear in all capitals, as shown here.
+
+    Copyright (c) 2024 IETF Trust and the persons identified as
+    authors of the code.  All rights reserved.
+
+    Redistribution and use in source and binary forms, with or
+    without modification, is permitted pursuant to, and subject
+    to the license terms contained in, the Revised BSD License
+    set forth in Section 4.c of the IETF Trust's Legal Provisions
+    Relating to IETF Documents
+    (https://trustee.ietf.org/license-info).
+
+    This version of this YANG module is part of RFC XXXX;
+    see the RFC itself for full legal notices.";
+
+  revision 2024-10-21 {
+    description
+     "This revision adds the following new data types:
+      - inet:ip-address-and-prefix
+      - inet:ipv4-address-and-prefix
+      - inet:ipv6-address-and-prefix
+      - inet:protocol-number
+      - inet:host-name
+      - inet:email-address
+      - inet:ip-address-link-local
+      - inet:ipv4-address-link-local
+      - inet:ipv6-address-link-local
+      The inet:host union was changed to use inet:host-name instead
+      of inet:domain-name. Several pattern statements have been
+      improved.";
+    reference 
+     "RFC XXXX: Common YANG Data Types";
+  }
+
+  revision 2013-07-15 {
+    description
+     "This revision adds the following new data types:
+      - inet:ip-address-no-zone
+      - inet:ipv4-address-no-zone
+      - inet:ipv6-address-no-zone";
+    reference 
+     "RFC 6991: Common YANG Data Types";
+  }
+
+  revision 2010-09-24 {
+    description
+     "Initial revision.";
+    reference 
+     "RFC 6021: Common YANG Data Types";
+  }
+
+  /*** collection of types related to protocol fields ***/
+
+  typedef ip-version {
+    type enumeration {
+      enum unknown {
+        value "0"; 
+        description
+         "An unknown or unspecified version of the Internet
+          protocol.";
+      }
+      enum ipv4 {
+        value "1";
+        description
+         "The IPv4 protocol as defined in RFC 791.";
+      }
+      enum ipv6 {
+        value "2";
+        description
+         "The IPv6 protocol as defined in RFC 8200.";
+      }
+    }
+    description
+     "This value represents the version of the IP protocol.
+
+      In the value set and its semantics, this type is equivalent
+      to the InetVersion textual convention of the SMIv2.";
+    reference
+     "RFC  791: Internet Protocol
+      RFC 8200: Internet Protocol, Version 6 (IPv6) Specification
+      RFC 4001: Textual Conventions for Internet Network Addresses";
+  }
+
+  typedef dscp {
+    type uint8 {
+      range "0..63";
+    }
+    description
+     "The dscp type represents a Differentiated Services Code Point
+      that may be used for marking packets in a traffic stream.
+
+      In the value set and its semantics, this type is equivalent
+      to the Dscp textual convention of the SMIv2.";
+    reference 
+     "RFC 3289: Management Information Base for the Differentiated
+                Services Architecture
+      RFC 2474: Definition of the Differentiated Services Field
+                (DS Field) in the IPv4 and IPv6 Headers
+      RFC 2780: IANA Allocation Guidelines For Values In
+                the Internet Protocol and Related Headers";
+  }
+
+  typedef ipv6-flow-label {
+    type uint32 {
+      range "0..1048575";
+    }
+    description
+     "The ipv6-flow-label type represents the flow identifier or 
+      Flow Label in an IPv6 packet header that may be used to
+      discriminate traffic flows.
+
+      In the value set and its semantics, this type is equivalent
+      to the IPv6FlowLabel textual convention of the SMIv2.";
+    reference
+     "RFC 3595: Textual Conventions for IPv6 Flow Label
+      RFC 8200: Internet Protocol, Version 6 (IPv6) Specification";
+  }
+
+  typedef port-number {
+    type uint16 {
+      range "0..65535";
+    }
+    description
+     "The port-number type represents a 16-bit port number of an 
+      Internet transport-layer protocol such as UDP, TCP, DCCP, or 
+      SCTP.
+
+      Port numbers are assigned by IANA.  The current list of
+      all assignments is available from <https://www.iana.org/>.
+
+      Note that the port number value zero is reserved by IANA.  In
+      situations where the value zero does not make sense, it can
+      be excluded by subtyping the port-number type.
+
+      In the value set and its semantics, this type is equivalent
+      to the InetPortNumber textual convention of the SMIv2.";
+    reference
+     "RFC  768: User Datagram Protocol
+      RFC 9293: Transmission Control Protocol (TCP)
+      RFC 9260: Stream Control Transmission Protocol
+      RFC 4340: Datagram Congestion Control Protocol (DCCP)
+      RFC 4001: Textual Conventions for Internet Network Addresses";
+  }
+
+  typedef protocol-number {
+    type uint8;
+    description
+     "The protocol-number type represents an 8-bit Internet
+      protocol number, carried in the 'protocol' field of the
+      IPv4 header or in the 'next header' field of the IPv6
+      header. If IPv6 extension headers are present, then the
+      protocol number type represents the upper layer protocol 
+      number, i.e., the number of the last 'next header' field 
+      of the IPv6 extension headers.
+
+      Protocol numbers are assigned by IANA. The current list of
+      all assignments is available from <https://www.iana.org/>.";
+    reference
+     "RFC  791: Internet Protocol
+      RFC 8200: Internet Protocol, Version 6 (IPv6) Specification";
+  }
+
+  /*** collection of types related to autonomous systems ***/
+
+  typedef as-number {
+    type uint32;
+    description
+     "The as-number type represents autonomous system numbers
+      which identify an Autonomous System (AS).  An AS is a set
+      of routers under a single technical administration, using
+      an interior gateway protocol and common metrics to route
+      packets within the AS, and using an exterior gateway
+      protocol to route packets to other ASes.  IANA maintains
+      the AS number space and has delegated large parts to the
+      regional registries.
+
+      Autonomous system numbers were originally limited to 16 
+      bits.  BGP extensions have enlarged the autonomous system
+      number space to 32 bits.  This type therefore uses an uint32
+      base type without a range restriction in order to support
+      a larger autonomous system number space.
+
+      In the value set and its semantics, this type is equivalent
+      to the InetAutonomousSystemNumber textual convention of 
+      the SMIv2.";
+    reference
+     "RFC 1930: Guidelines for creation, selection, and registration
+                of an Autonomous System (AS)
+      RFC 4271: A Border Gateway Protocol 4 (BGP-4)
+      RFC 4001: Textual Conventions for Internet Network Addresses
+      RFC 6793: BGP Support for Four-Octet Autonomous System (AS)
+                Number Space";
+  }
+
+  /*** collection of types related to IP addresses and hostnames ***/
+
+  typedef ip-address {
+    type union {
+      type ipv4-address;
+      type ipv6-address;
+    }
+    description
+     "The ip-address type represents an IP address and is IP 
+      version neutral.  The format of the textual representation
+      implies the IP version.  This type supports scoped addresses
+      by allowing zone identifiers in the address format.";
+    reference
+     "RFC 4007: IPv6 Scoped Address Architecture";
+  }
+
+  typedef ipv4-address {
+    type string {
+      pattern 
+        '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
+      +  '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
+      + '(%.+)?';
+    }
+    description
+      "The ipv4-address type represents an IPv4 address in 
+       dotted-quad notation.  The IPv4 address may include a zone
+       index, separated by a % sign. If a system uses zone names
+       that are not represented in UTF-8, then an implementation
+       needs to use some mechanism to transform the local name
+       into UTF-8. The definition of such a mechanism is outside
+       the scope of this document.
+
+       The zone index is used to disambiguate identical address
+       values.  For link-local addresses, the zone index will
+       typically be the interface index number or the name of an
+       interface.  If the zone index is not present, the default
+       zone of the device will be used.
+
+       The canonical format for the zone index is the numerical
+       format";
+  }
+
+  typedef ipv6-address {
+    type string {
+      pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}'
+            + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|'
+            + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}'
+            + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))'
+            + '(%[A-Za-z0-9][A-Za-z0-9\-\._~/]*)?';
+      pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|'
+            + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)'
+            + '(%.+)?';
+    }
+    description
+     "The ipv6-address type represents an IPv6 address in full,
+      mixed, shortened, and shortened-mixed notation.  The IPv6
+      address may include a zone index, separated by a % sign.
+      If a system uses zone names that are not represented in
+      UTF-8, then an implementation needs to use some mechanism
+      to transform the local name into UTF-8. The definition of
+      such a mechanism is outside the scope of this document.
+
+      The zone index is used to disambiguate identical address
+      values.  For link-local addresses, the zone index will
+      typically be the interface index number or the name of an
+      interface.  If the zone index is not present, the default
+      zone of the device will be used.
+
+      The canonical format of IPv6 addresses uses the textual
+      representation defined in Section 4 of RFC 5952.  The
+      canonical format for the zone index is the numerical
+      format as described in Section 11.2 of RFC 4007.";
+    reference
+     "RFC 4291: IP Version 6 Addressing Architecture
+      RFC 4007: IPv6 Scoped Address Architecture
+      RFC 5952: A Recommendation for IPv6 Address Text
+                Representation";
+  }
+
+  typedef ip-address-no-zone {
+    type union {
+      type ipv4-address-no-zone;
+      type ipv6-address-no-zone;
+    }
+    description
+     "The ip-address-no-zone type represents an IP address and is 
+      IP version neutral.  The format of the textual representation
+      implies the IP version.  This type does not support scoped
+      addresses since it does not allow zone identifiers in the
+      address format.";
+    reference
+     "RFC 4007: IPv6 Scoped Address Architecture";
+  }
+
+  typedef ipv4-address-no-zone {
+    type ipv4-address {
+      pattern '[0-9\.]*';
+    }
+    description
+      "An IPv4 address without a zone index.  This type, derived
+       from the type ipv4-address, may be used in situations where
+       the zone is known from the context and no zone index is
+       needed.";
+  }
+
+  typedef ipv6-address-no-zone {
+    type ipv6-address {
+      pattern '[0-9a-fA-F:\.]*';
+    }
+    description
+      "An IPv6 address without a zone index.  This type, derived
+       from the type ipv6-address, may be used in situations where
+       the zone is known from the context and no zone index is
+       needed.";
+    reference
+     "RFC 4291: IP Version 6 Addressing Architecture
+      RFC 4007: IPv6 Scoped Address Architecture
+      RFC 5952: A Recommendation for IPv6 Address Text
+                Representation";
+  }
+
+  typedef ip-address-link-local {
+    type union {
+      type ipv4-address-link-local;
+      type ipv6-address-link-local;
+    }
+    description
+     "The ip-address-link-local type represents a link-local IP
+      address and is IP version neutral. The format of the textual
+      representation implies the IP version.";
+  }
+
+  typedef ipv4-address-link-local {
+    type ipv4-address {
+      pattern '169\.254\..*';
+    }
+    description
+      "A link-local IPv4 address in the prefix 169.254.0.0/16 as
+       defined in section 2.1. of RFC 3927.";
+    reference
+      "RFC 3927: Dynamic Configuration of IPv4 Link-Local Addresses";
+  }
+
+  typedef ipv6-address-link-local {
+    type ipv6-address {
+      pattern '[fF][eE]80:.*';
+    }
+    description
+      "A link-local IPv6 address in the prefix fe80::/10 as defined
+       in section 2.5.6. of RFC 4291.";
+    reference
+      "RFC 4291: IP Version 6 Addressing Architecture";
+  }
+
+  typedef ip-prefix {
+    type union {
+      type ipv4-prefix;
+      type ipv6-prefix;
+    }
+    description
+     "The ip-prefix type represents an IP prefix and is IP
+      version neutral.  The format of the textual representations
+      implies the IP version.";
+  }
+
+  typedef ipv4-prefix {
+    type string {
+      pattern
+         '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
+       +  '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
+       + '/(([0-9])|([1-2][0-9])|(3[0-2]))';
+    }
+    description
+     "The ipv4-prefix type represents an IPv4 prefix.
+      The prefix length is given by the number following the
+      slash character and must be less than or equal to 32. 
+
+      A prefix length value of n corresponds to an IP address
+      mask that has n contiguous 1-bits from the most
+      significant bit (MSB) and all other bits set to 0.
+
+      The canonical format of an IPv4 prefix has all bits of
+      the IPv4 address set to zero that are not part of the
+      IPv4 prefix.
+
+      The definition of ipv4-prefix does not require that bits,
+      which are not part of the prefix, are set to zero. However,
+      implementations have to return values in canonical format,
+      which requires non-prefix bits to be set to zero. This means
+      that 192.0.2.1/24 must be accepted as a valid value but it
+      will be converted into the canonical format 192.0.2.0/24.";
+  }
+
+  typedef ipv6-prefix {
+    type string {
+      pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}'
+            + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|'
+            + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}'
+            + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))'
+            + '(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))';
+      pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|'
+            + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)'
+            + '(/.+)';
+    }
+    description
+     "The ipv6-prefix type represents an IPv6 prefix.
+      The prefix length is given by the number following the
+      slash character and must be less than or equal to 128. 
+
+      A prefix length value of n corresponds to an IP address
+      mask that has n contiguous 1-bits from the most
+      significant bit (MSB) and all other bits set to 0.
+
+      The canonical format of an IPv6 prefix has all bits of
+      the IPv6 address set to zero that are not part of the
+      IPv6 prefix.  Furthermore, the IPv6 address is represented
+      as defined in Section 4 of RFC 5952.
+
+      The definition of ipv6-prefix does not require that bits,
+      which are not part of the prefix, are set to zero. However,
+      implementations have to return values in canonical format,
+      which requires non-prefix bits to be set to zero. This means
+      that 2001:db8::1/64 must be accepted as a valid value but it
+      will be converted into the canonical format 2001:db8::/64.";
+    reference
+     "RFC 5952: A Recommendation for IPv6 Address Text
+                Representation";
+  }
+
+  typedef ip-address-and-prefix {
+    type union {
+      type ipv4-address-and-prefix;
+      type ipv6-address-and-prefix;
+    }
+    description
+     "The ip-address-and-prefix type represents an IP address and 
+      prefix and is IP version neutral.  The format of the textual
+      representations implies the IP version.";
+  }
+
+  typedef ipv4-address-and-prefix {
+    type string {
+      pattern
+         '(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}'
+       +  '([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
+       + '/(([0-9])|([1-2][0-9])|(3[0-2]))';
+    }
+    description
+     "The ipv4-address-and-prefix type represents an IPv4 
+      address and an associated IPv4 prefix.
+      The prefix length is given by the number following the
+      slash character and must be less than or equal to 32. 
+
+      A prefix length value of n corresponds to an IP address
+      mask that has n contiguous 1-bits from the most
+      significant bit (MSB) and all other bits set to 0.";
+  }
+
+  typedef ipv6-address-and-prefix {
+    type string {
+      pattern '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}'
+            + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|'
+            + '(((25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])\.){3}'
+            + '(25[0-5]|2[0-4][0-9]|[01]?[0-9]?[0-9])))'
+            + '(/(([0-9])|([0-9]{2})|(1[0-1][0-9])|(12[0-8])))';
+      pattern '(([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|'
+            + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?)'
+            + '(/.+)';
+    }
+    description
+     "The ipv6-address-and-prefix type represents an IPv6
+      address and an associated IPv6 prefix.
+      The prefix length is given by the number following the
+      slash character and must be less than or equal to 128. 
+
+      A prefix length value of n corresponds to an IP address
+      mask that has n contiguous 1-bits from the most
+      significant bit (MSB) and all other bits set to 0.
+
+      The canonical format requires that the IPv6 address is
+      represented as defined in Section 4 of RFC 5952.";
+    reference
+     "RFC 5952: A Recommendation for IPv6 Address Text
+                Representation";
+  }
+
+  /*** collection of domain name and URI types ***/
+
+  typedef domain-name {
+    type string {
+      length "1..253";
+      pattern 
+        '((([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.)*'
+      + '([a-zA-Z0-9_]([a-zA-Z0-9\-_]){0,61})?[a-zA-Z0-9]\.?)'
+      + '|\.';
+    }
+    description
+     "The domain-name type represents a DNS domain name.  The 
+      name SHOULD be fully qualified whenever possible. This
+      type does not support wildcards (see RFC 4592) or
+      classless in-addr.arpa delegations (see RFC 2317).
+
+      Internet domain names are only loosely specified.  Section
+      3.5 of RFC 1034 recommends a syntax (modified in Section 
+      2.1 of RFC 1123).  The pattern above is intended to allow
+      for current practice in domain name use, and some possible
+      future expansion.  Note that Internet host names have a
+      stricter syntax (described in RFC 952) than the DNS 
+      recommendations in RFCs 1034 and 1123. Schema nodes
+      representing host names should use the host-name type
+      instead of the domain-type.
+
+      The encoding of DNS names in the DNS protocol is limited
+      to 255 characters.  Since the encoding consists of labels
+      prefixed by a length bytes and there is a trailing NULL
+      byte, only 253 characters can appear in the textual dotted
+      notation.
+
+      The description clause of schema nodes using the domain-name
+      type MUST describe when and how these names are resolved to
+      IP addresses.  Note that the resolution of a domain-name value
+      may require to query multiple DNS records (e.g., A for IPv4
+      and AAAA for IPv6).  The order of the resolution process and
+      which DNS record takes precedence can either be defined
+      explicitly or may depend on the configuration of the
+      resolver.
+
+      Domain-name values use the US-ASCII encoding.  Their canonical
+      format uses lowercase US-ASCII characters.  Internationalized
+      domain names MUST be A-labels as per RFC 5890.";
+    reference
+     "RFC  952: DoD Internet Host Table Specification
+      RFC 1034: Domain Names - Concepts and Facilities
+      RFC 1123: Requirements for Internet Hosts -- Application 
+                and Support
+      RFC 2317: Classless IN-ADDR.ARPA delegation
+      RFC 2782: A DNS RR for specifying the location of services
+                (DNS SRV)
+      RFC 4592: The Role of Wildcards in the Domain Name System
+      RFC 5890: Internationalized Domain Names in Applications
+                (IDNA): Definitions and Document Framework
+      RFC 9499: DNS Terminology";
+  }
+
+  typedef host-name {
+    type domain-name {
+      length "2..max";
+      pattern '[a-zA-Z0-9\-\.]+';
+    }
+    description
+     "The host-name type represents (fully qualified) host names.
+      Host names must be at least two characters long (see RFC 952)
+      and they are restricted to labels consisting of letters, digits
+      and hyphens separated by dots (see RFC1123 and RFC 952).";
+    reference
+     "RFC  952: DoD Internet Host Table Specification
+      RFC 1123: Requirements for Internet Hosts -- Application
+                and Support";
+  }
+
+  typedef host {
+    type union {
+      type ip-address;
+      type host-name;
+    }
+    description
+     "The host type represents either an IP address or a (fully
+      qualified) host name.";
+  }
+
+  typedef uri {
+    type string {
+      pattern '[a-z][a-z0-9+.-]*:.*';
+    }
+    description
+     "The uri type represents a Uniform Resource Identifier
+      (URI) as defined by the rule 'URI' in RFC 3986.
+
+      Objects using the uri type MUST be in US-ASCII encoding,
+      and MUST be normalized as described by RFC 3986 Sections
+      6.2.1, 6.2.2.1, and 6.2.2.2.  All unnecessary
+      percent-encoding is removed, and all case-insensitive
+      characters are set to lowercase except for hexadecimal
+      digits within a percent-encoded triplet, which are
+      normalized to uppercase as described in Section 6.2.2.1
+      of RFC 3986.
+
+      The purpose of this normalization is to help provide
+      unique URIs.  Note that this normalization is not
+      sufficient to provide uniqueness.  Two URIs that are
+      textually distinct after this normalization may still be
+      equivalent.
+
+      Objects using the uri type may restrict the schemes that
+      they permit.  For example, 'data:' and 'urn:' schemes
+      might not be appropriate.
+
+      A zero-length URI is not a valid URI.  This can be used to
+      express 'URI absent' where required.
+
+      In the value set and its semantics, this type is equivalent
+      to the Uri SMIv2 textual convention defined in RFC 5017.";
+    reference
+     "RFC 3986: Uniform Resource Identifier (URI): Generic Syntax
+      RFC 3305: Report from the Joint W3C/IETF URI Planning Interest
+                Group: Uniform Resource Identifiers (URIs), URLs, 
+                and Uniform Resource Names (URNs): Clarifications
+                and Recommendations
+      RFC 5017: MIB Textual Conventions for Uniform Resource 
+                Identifiers (URIs)";
+  }
+
+  typedef email-address {
+    type string {
+      pattern '.+@.+';
+    }
+    description
+     "The email-address type represents an internationalized
+      email address.
+
+      The email address format is defined by the addr-spec
+      ABNF rule in RFC 5322 section 3.4.1. This format has
+      been extended by RFC 6532 to support internationalized
+      email addresses. Implementations MUST support the
+      internationalization extensions of RFC 6532. Support
+      of the obsolete obs-local-part, obs-domain, and
+      obs-qtext parts of RFC 5322 is not required.
+
+      The domain part may use both A-labels and U-labels
+      (see RFC 5890). The canonical format of the domain part
+      uses lowercase characters and U-labels (RFC 5890) where
+      applicable.";
+    reference
+     "RFC 5322: Internet Message Format
+      RFC 5890: Internationalized Domain Names in Applications
+                (IDNA): Definitions and Document Framework
+      RFC 6531: SMTP Extension for Internationalized Email";
+  }
+
+}
\ No newline at end of file
diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-key-chain@2017-06-15.yang b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-key-chain@2017-06-15.yang
new file mode 100644
index 0000000000000000000000000000000000000000..445d1994a5ac57366078b198200a9e143d4ccda8
--- /dev/null
+++ b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-key-chain@2017-06-15.yang
@@ -0,0 +1,382 @@
+module ietf-key-chain {
+  yang-version 1.1;
+  namespace "urn:ietf:params:xml:ns:yang:ietf-key-chain";
+  prefix key-chain;
+
+  import ietf-yang-types {
+    prefix yang;
+  }
+  import ietf-netconf-acm {
+    prefix nacm;
+  }
+
+  organization
+    "IETF RTGWG - Routing Area Working Group";
+  contact
+    "WG Web:   <https://datatracker.ietf.org/group/rtgwg>
+     WG List:  <mailto:rtgwg@ietf.org>
+
+     Editor: Acee Lindem
+             <mailto:acee@cisco.com>
+             Yingzhen Qu
+             <mailto:yingzhen.qu@huawei.com>
+             Derek Yeung
+             <mailto:derek@arrcus.com>
+             Ing-Wher Chen
+             <mailto:Ing-Wher_Chen@jabail.com>
+             Jeffrey Zhang
+             <mailto:zzhang@juniper.net>";
+
+  description
+    "This YANG module defines the generic configuration
+     data for key chains.  It is intended that the module
+     will be extended by vendors to define vendor-specific
+     key chain configuration parameters.
+
+     Copyright (c) 2017 IETF Trust and the persons identified as
+     authors of the code.  All rights reserved.
+
+     Redistribution and use in source and binary forms, with or
+     without modification, is permitted pursuant to, and subject
+     to the license terms contained in, the Simplified BSD License
+     set forth in Section 4.c of the IETF Trust's Legal Provisions
+     Relating to IETF Documents
+     (http://trustee.ietf.org/license-info).
+
+     This version of this YANG module is part of RFC 8177;
+     see the RFC itself for full legal notices.";
+
+  reference "RFC 8177";
+
+  revision 2017-06-15 {
+    description
+      "Initial RFC Revision";
+    reference "RFC 8177: YANG Data Model for Key Chains";
+  }
+
+  feature hex-key-string {
+    description
+      "Support hexadecimal key string.";
+  }
+
+  feature accept-tolerance {
+    description
+      "Support the tolerance or acceptance limit.";
+  }
+
+  feature independent-send-accept-lifetime {
+    description
+      "Support for independent send and accept key lifetimes.";
+  }
+
+  feature crypto-hmac-sha-1-12 {
+    description
+      "Support for TCP HMAC-SHA-1 12-byte digest hack.";
+  }
+
+  feature cleartext {
+    description
+      "Support for cleartext algorithm.  Usage is
+       NOT RECOMMENDED.";
+  }
+
+  feature aes-cmac-prf-128 {
+    description
+      "Support for AES Cipher-based Message Authentication
+       Code Pseudorandom Function.";
+  }
+
+  feature aes-key-wrap {
+    description
+      "Support for Advanced Encryption Standard (AES) Key Wrap.";
+  }
+
+  feature replay-protection-only {
+    description
+      "Provide replay protection without any authentication
+       as required by protocols such as Bidirectional
+       Forwarding Detection (BFD).";
+  }
+  identity crypto-algorithm {
+    description
+      "Base identity of cryptographic algorithm options.";
+  }
+
+  identity hmac-sha-1-12 {
+    base crypto-algorithm;
+    if-feature "crypto-hmac-sha-1-12";
+    description
+      "The HMAC-SHA1-12 algorithm.";
+  }
+
+  identity aes-cmac-prf-128 {
+    base crypto-algorithm;
+    if-feature "aes-cmac-prf-128";
+    description
+      "The AES-CMAC-PRF-128 algorithm - required by
+       RFC 5926 for TCP-AO key derivation functions.";
+  }
+
+  identity md5 {
+    base crypto-algorithm;
+    description
+      "The MD5 algorithm.";
+  }
+
+  identity sha-1 {
+    base crypto-algorithm;
+    description
+      "The SHA-1 algorithm.";
+  }
+
+  identity hmac-sha-1 {
+    base crypto-algorithm;
+    description
+      "HMAC-SHA-1 authentication algorithm.";
+  }
+
+  identity hmac-sha-256 {
+    base crypto-algorithm;
+    description
+      "HMAC-SHA-256 authentication algorithm.";
+  }
+
+  identity hmac-sha-384 {
+    base crypto-algorithm;
+    description
+      "HMAC-SHA-384 authentication algorithm.";
+  }
+
+  identity hmac-sha-512 {
+    base crypto-algorithm;
+    description
+      "HMAC-SHA-512 authentication algorithm.";
+  }
+
+  identity cleartext {
+    base crypto-algorithm;
+    if-feature "cleartext";
+    description
+      "cleartext.";
+  }
+
+  identity replay-protection-only {
+    base crypto-algorithm;
+    if-feature "replay-protection-only";
+    description
+      "Provide replay protection without any authentication as
+       required by protocols such as Bidirectional Forwarding
+       Detection (BFD).";
+  }
+
+  typedef key-chain-ref {
+    type leafref {
+      path
+      "/key-chain:key-chains/key-chain:key-chain/key-chain:name";
+    }
+    description
+      "This type is used by data models that need to reference
+       configured key chains.";
+  }
+
+  grouping lifetime {
+    description
+      "Key lifetime specification.";
+    choice lifetime {
+      default "always";
+      description
+        "Options for specifying key accept or send lifetimes";
+      case always {
+        leaf always {
+          type empty;
+          description
+            "Indicates key lifetime is always valid.";
+        }
+      }
+      case start-end-time {
+        leaf start-date-time {
+          type yang:date-and-time;
+          description
+            "Start time.";
+        }
+        choice end-time {
+          default "infinite";
+          description
+            "End-time setting.";
+          case infinite {
+            leaf no-end-time {
+              type empty;
+              description
+                "Indicates key lifetime end-time is infinite.";
+            }
+          }
+          case duration {
+            leaf duration {
+              type uint32 {
+                range "1..2147483646";
+              }
+              units "seconds";
+              description
+                "Key lifetime duration, in seconds";
+            }
+          }
+          case end-date-time {
+            leaf end-date-time {
+              type yang:date-and-time;
+              description
+                "End time.";
+            }
+          }
+        }
+      }
+    }
+  }
+
+  container key-chains {
+    description
+      "All configured key-chains on the device.";
+    list key-chain {
+      key "name";
+      description
+        "List of key-chains.";
+      leaf name {
+        type string;
+        description
+          "Name of the key-chain.";
+      }
+      leaf description {
+        type string;
+        description
+          "A description of the key-chain";
+      }
+      container accept-tolerance {
+        if-feature "accept-tolerance";
+        description
+          "Tolerance for key lifetime acceptance (seconds).";
+        leaf duration {
+          type uint32;
+          units "seconds";
+          default "0";
+          description
+            "Tolerance range, in seconds.";
+        }
+      }
+      leaf last-modified-timestamp {
+        type yang:date-and-time;
+        config false;
+        description
+          "Timestamp of the most recent update to the key-chain";
+      }
+      list key {
+        key "key-id";
+        description
+          "Single key in key chain.";
+        leaf key-id {
+          type uint64;
+          description
+            "Numeric value uniquely identifying the key";
+        }
+        container lifetime {
+          description
+            "Specify a key's lifetime.";
+          choice lifetime {
+            description
+              "Options for specification of send and accept
+               lifetimes.";
+            case send-and-accept-lifetime {
+              description
+                "Send and accept key have the same lifetime.";
+              container send-accept-lifetime {
+                description
+                  "Single lifetime specification for both
+                   send and accept lifetimes.";
+                uses lifetime;
+              }
+            }
+            case independent-send-accept-lifetime {
+              if-feature "independent-send-accept-lifetime";
+              description
+                "Independent send and accept key lifetimes.";
+              container send-lifetime {
+                description
+                  "Separate lifetime specification for send
+                   lifetime.";
+                uses lifetime;
+              }
+              container accept-lifetime {
+                description
+                  "Separate lifetime specification for accept
+                   lifetime.";
+                uses lifetime;
+              }
+            }
+          }
+        }
+        leaf crypto-algorithm {
+          type identityref {
+            base crypto-algorithm;
+          }
+          mandatory true;
+          description
+            "Cryptographic algorithm associated with key.";
+        }
+        container key-string {
+          description
+            "The key string.";
+          nacm:default-deny-all;
+          choice key-string-style {
+            description
+              "Key string styles";
+             case keystring {
+               leaf keystring {
+                type string;
+                description
+                  "Key string in ASCII format.";
+              }
+            }
+            case hexadecimal {
+              if-feature "hex-key-string";
+              leaf hexadecimal-string {
+                type yang:hex-string;
+                description
+                  "Key in hexadecimal string format.  When compared
+                   to ASCII, specification in hexadecimal affords
+                   greater key entropy with the same number of
+                   internal key-string octets.  Additionally, it
+                   discourages usage of well-known words or
+                   numbers.";
+              }
+            }
+          }
+        }
+        leaf send-lifetime-active {
+          type boolean;
+          config false;
+          description
+            "Indicates if the send lifetime of the
+             key-chain key is currently active.";
+           }
+        leaf accept-lifetime-active {
+          type boolean;
+          config false;
+          description
+            "Indicates if the accept lifetime of the
+             key-chain key is currently active.";
+        }
+      }
+    }
+    container aes-key-wrap {
+      if-feature "aes-key-wrap";
+      description
+        "AES Key Wrap encryption for key-chain key-strings.  The
+         encrypted key-strings are encoded as hexadecimal key
+         strings using the hex-key-string leaf.";
+      leaf enable {
+        type boolean;
+        default "false";
+        description
+          "Enable AES Key Wrap encryption.";
+      }
+    }
+  }
+}
diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-netconf-acm@2018-02-14.yang b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-netconf-acm@2018-02-14.yang
new file mode 100644
index 0000000000000000000000000000000000000000..bf4855faf0508a152471f6c6c8f756581b8ebb96
--- /dev/null
+++ b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-netconf-acm@2018-02-14.yang
@@ -0,0 +1,464 @@
+module ietf-netconf-acm {
+
+  namespace "urn:ietf:params:xml:ns:yang:ietf-netconf-acm";
+
+  prefix nacm;
+
+  import ietf-yang-types {
+    prefix yang;
+  }
+
+  organization
+    "IETF NETCONF (Network Configuration) Working Group";
+
+  contact
+    "WG Web:   <https://datatracker.ietf.org/wg/netconf/>
+     WG List:  <mailto:netconf@ietf.org>
+
+     Author:   Andy Bierman
+               <mailto:andy@yumaworks.com>
+
+     Author:   Martin Bjorklund
+               <mailto:mbj@tail-f.com>";
+
+  description
+    "Network Configuration Access Control Model.
+
+     Copyright (c) 2012 - 2018 IETF Trust and the persons
+     identified as authors of the code.  All rights reserved.
+
+     Redistribution and use in source and binary forms, with or
+     without modification, is permitted pursuant to, and subject
+     to the license terms contained in, the Simplified BSD
+     License set forth in Section 4.c of the IETF Trust's
+     Legal Provisions Relating to IETF Documents
+     (https://trustee.ietf.org/license-info).
+
+     This version of this YANG module is part of RFC 8341; see
+     the RFC itself for full legal notices.";
+
+  revision "2018-02-14" {
+    description
+      "Added support for YANG 1.1 actions and notifications tied to
+       data nodes.  Clarified how NACM extensions can be used by
+       other data models.";
+    reference
+      "RFC 8341: Network Configuration Access Control Model";
+  }
+
+  revision "2012-02-22" {
+    description
+      "Initial version.";
+    reference
+      "RFC 6536: Network Configuration Protocol (NETCONF)
+                 Access Control Model";
+  }
+
+  /*
+   * Extension statements
+   */
+
+  extension default-deny-write {
+    description
+      "Used to indicate that the data model node
+       represents a sensitive security system parameter.
+
+       If present, the NETCONF server will only allow the designated
+       'recovery session' to have write access to the node.  An
+       explicit access control rule is required for all other users.
+
+       If the NACM module is used, then it must be enabled (i.e.,
+       /nacm/enable-nacm object equals 'true'), or this extension
+       is ignored.
+
+       The 'default-deny-write' extension MAY appear within a data
+       definition statement.  It is ignored otherwise.";
+  }
+
+  extension default-deny-all {
+    description
+      "Used to indicate that the data model node
+       controls a very sensitive security system parameter.
+
+       If present, the NETCONF server will only allow the designated
+       'recovery session' to have read, write, or execute access to
+       the node.  An explicit access control rule is required for all
+       other users.
+
+       If the NACM module is used, then it must be enabled (i.e.,
+       /nacm/enable-nacm object equals 'true'), or this extension
+       is ignored.
+
+       The 'default-deny-all' extension MAY appear within a data
+       definition statement, 'rpc' statement, or 'notification'
+       statement.  It is ignored otherwise.";
+  }
+
+  /*
+   * Derived types
+   */
+
+  typedef user-name-type {
+    type string {
+      length "1..max";
+    }
+    description
+      "General-purpose username string.";
+  }
+
+  typedef matchall-string-type {
+    type string {
+      pattern '\*';
+    }
+    description
+      "The string containing a single asterisk '*' is used
+       to conceptually represent all possible values
+       for the particular leaf using this data type.";
+  }
+
+  typedef access-operations-type {
+    type bits {
+      bit create {
+        description
+          "Any protocol operation that creates a
+           new data node.";
+      }
+      bit read {
+        description
+          "Any protocol operation or notification that
+           returns the value of a data node.";
+      }
+      bit update {
+        description
+          "Any protocol operation that alters an existing
+           data node.";
+      }
+      bit delete {
+        description
+          "Any protocol operation that removes a data node.";
+      }
+      bit exec {
+        description
+          "Execution access to the specified protocol operation.";
+      }
+    }
+    description
+      "Access operation.";
+  }
+
+  typedef group-name-type {
+    type string {
+      length "1..max";
+      pattern '[^\*].*';
+    }
+    description
+      "Name of administrative group to which
+       users can be assigned.";
+  }
+
+  typedef action-type {
+    type enumeration {
+      enum permit {
+        description
+          "Requested action is permitted.";
+      }
+      enum deny {
+        description
+          "Requested action is denied.";
+      }
+    }
+    description
+      "Action taken by the server when a particular
+       rule matches.";
+  }
+
+  typedef node-instance-identifier {
+    type yang:xpath1.0;
+    description
+      "Path expression used to represent a special
+       data node, action, or notification instance-identifier
+       string.
+
+       A node-instance-identifier value is an
+       unrestricted YANG instance-identifier expression.
+       All the same rules as an instance-identifier apply,
+       except that predicates for keys are optional.  If a key
+       predicate is missing, then the node-instance-identifier
+       represents all possible server instances for that key.
+
+       This XML Path Language (XPath) expression is evaluated in the
+       following context:
+
+          o  The set of namespace declarations are those in scope on
+             the leaf element where this type is used.
+
+          o  The set of variable bindings contains one variable,
+             'USER', which contains the name of the user of the
+             current session.
+
+          o  The function library is the core function library, but
+             note that due to the syntax restrictions of an
+             instance-identifier, no functions are allowed.
+
+          o  The context node is the root node in the data tree.
+
+       The accessible tree includes actions and notifications tied
+       to data nodes.";
+  }
+
+  /*
+   * Data definition statements
+   */
+
+  container nacm {
+    nacm:default-deny-all;
+
+    description
+      "Parameters for NETCONF access control model.";
+
+    leaf enable-nacm {
+      type boolean;
+      default "true";
+      description
+        "Enables or disables all NETCONF access control
+         enforcement.  If 'true', then enforcement
+         is enabled.  If 'false', then enforcement
+         is disabled.";
+    }
+
+    leaf read-default {
+      type action-type;
+      default "permit";
+      description
+        "Controls whether read access is granted if
+         no appropriate rule is found for a
+         particular read request.";
+    }
+
+    leaf write-default {
+      type action-type;
+      default "deny";
+      description
+        "Controls whether create, update, or delete access
+         is granted if no appropriate rule is found for a
+         particular write request.";
+    }
+
+    leaf exec-default {
+      type action-type;
+      default "permit";
+      description
+        "Controls whether exec access is granted if no appropriate
+         rule is found for a particular protocol operation request.";
+    }
+
+    leaf enable-external-groups {
+      type boolean;
+      default "true";
+      description
+        "Controls whether the server uses the groups reported by the
+         NETCONF transport layer when it assigns the user to a set of
+         NACM groups.  If this leaf has the value 'false', any group
+         names reported by the transport layer are ignored by the
+         server.";
+    }
+
+    leaf denied-operations {
+      type yang:zero-based-counter32;
+      config false;
+      mandatory true;
+      description
+        "Number of times since the server last restarted that a
+         protocol operation request was denied.";
+    }
+
+    leaf denied-data-writes {
+      type yang:zero-based-counter32;
+      config false;
+      mandatory true;
+      description
+        "Number of times since the server last restarted that a
+         protocol operation request to alter
+         a configuration datastore was denied.";
+    }
+
+    leaf denied-notifications {
+      type yang:zero-based-counter32;
+      config false;
+      mandatory true;
+      description
+        "Number of times since the server last restarted that
+         a notification was dropped for a subscription because
+         access to the event type was denied.";
+    }
+
+    container groups {
+      description
+        "NETCONF access control groups.";
+
+      list group {
+        key name;
+
+        description
+          "One NACM group entry.  This list will only contain
+           configured entries, not any entries learned from
+           any transport protocols.";
+
+        leaf name {
+          type group-name-type;
+          description
+            "Group name associated with this entry.";
+        }
+
+        leaf-list user-name {
+          type user-name-type;
+          description
+            "Each entry identifies the username of
+             a member of the group associated with
+             this entry.";
+        }
+      }
+    }
+
+    list rule-list {
+      key name;
+      ordered-by user;
+      description
+        "An ordered collection of access control rules.";
+
+      leaf name {
+        type string {
+          length "1..max";
+        }
+        description
+          "Arbitrary name assigned to the rule-list.";
+      }
+      leaf-list group {
+        type union {
+          type matchall-string-type;
+          type group-name-type;
+        }
+        description
+          "List of administrative groups that will be
+           assigned the associated access rights
+           defined by the 'rule' list.
+
+           The string '*' indicates that all groups apply to the
+           entry.";
+      }
+
+      list rule {
+        key name;
+        ordered-by user;
+        description
+          "One access control rule.
+
+           Rules are processed in user-defined order until a match is
+           found.  A rule matches if 'module-name', 'rule-type', and
+           'access-operations' match the request.  If a rule
+           matches, the 'action' leaf determines whether or not
+           access is granted.";
+
+        leaf name {
+          type string {
+            length "1..max";
+          }
+          description
+            "Arbitrary name assigned to the rule.";
+        }
+
+        leaf module-name {
+          type union {
+            type matchall-string-type;
+            type string;
+          }
+          default "*";
+          description
+            "Name of the module associated with this rule.
+
+             This leaf matches if it has the value '*' or if the
+             object being accessed is defined in the module with the
+             specified module name.";
+        }
+        choice rule-type {
+          description
+            "This choice matches if all leafs present in the rule
+             match the request.  If no leafs are present, the
+             choice matches all requests.";
+          case protocol-operation {
+            leaf rpc-name {
+              type union {
+                type matchall-string-type;
+                type string;
+              }
+              description
+                "This leaf matches if it has the value '*' or if
+                 its value equals the requested protocol operation
+                 name.";
+            }
+          }
+          case notification {
+            leaf notification-name {
+              type union {
+                type matchall-string-type;
+                type string;
+              }
+              description
+                "This leaf matches if it has the value '*' or if its
+                 value equals the requested notification name.";
+            }
+          }
+
+          case data-node {
+            leaf path {
+              type node-instance-identifier;
+              mandatory true;
+              description
+                "Data node instance-identifier associated with the
+                 data node, action, or notification controlled by
+                 this rule.
+
+                 Configuration data or state data
+                 instance-identifiers start with a top-level
+                 data node.  A complete instance-identifier is
+                 required for this type of path value.
+
+                 The special value '/' refers to all possible
+                 datastore contents.";
+            }
+          }
+        }
+
+        leaf access-operations {
+          type union {
+            type matchall-string-type;
+            type access-operations-type;
+          }
+          default "*";
+          description
+            "Access operations associated with this rule.
+
+             This leaf matches if it has the value '*' or if the
+             bit corresponding to the requested operation is set.";
+        }
+
+        leaf action {
+          type action-type;
+          mandatory true;
+          description
+            "The access control action associated with the
+             rule.  If a rule has been determined to match a
+             particular request, then this object is used
+             to determine whether to permit or deny the
+             request.";
+        }
+
+        leaf comment {
+          type string;
+          description
+            "A textual description of the access rule.";
+        }
+      }
+    }
+  }
+}
diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/ietf-network-slice-service.txt b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-network-slice-service.txt
similarity index 100%
rename from src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/ietf-network-slice-service.txt
rename to src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-network-slice-service.txt
diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-network-slice-service@2024-08-28.yang b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-network-slice-service@2024-08-28.yang
new file mode 100644
index 0000000000000000000000000000000000000000..d72dd1ed38c6b098c70ab824f98e8029aef7d137
--- /dev/null
+++ b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-network-slice-service@2024-08-28.yang
@@ -0,0 +1,1375 @@
+module ietf-network-slice-service {
+  yang-version 1.1;
+  namespace
+    "urn:ietf:params:xml:ns:yang:ietf-network-slice-service";
+  prefix ietf-nss;
+
+  import ietf-inet-types {
+    prefix inet;
+    reference
+      "RFC 6991: Common YANG Types";
+  }
+  import ietf-yang-types {
+    prefix yang;
+    reference
+      "RFC 6991: Common YANG Data Types";
+  }
+  import ietf-geo-location {
+    prefix geo;
+    reference
+      "RFC 9179: A YANG Grouping for Geographic Locations";
+  }
+  import ietf-vpn-common {
+    prefix vpn-common;
+    reference
+      "RFC 9181: A Common YANG Data Model for Layer 2 and Layer 3
+                 VPNs";
+  }
+  import ietf-network {
+    prefix nw;
+    reference
+      "RFC 8345: A YANG Data Model for Network Topologies";
+  }
+  import ietf-network-topology {
+    prefix nt;
+    reference
+      "RFC 8345: A YANG Data Model for Network
+                 Topologies, Section 6.2";
+  }
+  import ietf-ac-common {
+    prefix ac-common;
+    reference
+      "RFC BBBB: A Common YANG Data Model for Attachment Circuits";
+  }
+  import ietf-ac-svc {
+    prefix ac-svc;
+    reference
+      "RFC CCCC: YANG Data Models for Bearers and 'Attachment
+                 Circuits'-as-a-Service (ACaaS)";
+  }
+  import ietf-te-types {
+    prefix te-types;
+    reference
+      "RFC DDDD: Common YANG Types for Traffic Engineering";
+  }
+  import ietf-te-packet-types {
+    prefix te-packet-types;
+    reference
+      "RFC DDDD: Common YANG Data Types for Traffic Engineering";
+  }
+
+  organization
+    "IETF Traffic Engineering Architecture and Signaling (TEAS)
+     Working Group";
+  contact
+    "WG Web:  <https://datatracker.ietf.org/wg/teas/>
+     WG List:  <mailto:teas@ietf.org>
+
+     Editor: Bo Wu
+             <lana.wubo@huawei.com>
+     Editor: Dhruv Dhody
+             <dhruv.ietf@gmail.com>
+     Editor: Reza Rokui
+             <rrokui@ciena.com>
+     Editor: Tarek Saad
+             <tsaad@cisco.com>
+     Editor: John Mullooly
+             <jmullool@cisco.com>";
+  description
+    "This YANG module defines a service model for the RFC 9543
+     Network Slice Service.
+
+     Copyright (c) 2024 IETF Trust and the persons identified as
+     authors of the code.  All rights reserved.
+
+     Redistribution and use in source and binary forms, with or
+     without modification, is permitted pursuant to, and subject to
+     the license terms contained in, the Revised BSD License set
+     forth in Section 4.c of the IETF Trust's Legal Provisions
+     Relating to IETF Documents
+     (https://trustee.ietf.org/license-info).
+
+     This version of this YANG module is part of RFC AAAA; see the
+     RFC itself for full legal notices.";
+
+  revision 2024-08-28 {
+    description
+      "Initial revision.";
+    reference
+      "RFC AAAA: A YANG Data Model for the RFC 9543 Network Slice
+       Service";
+  }
+
+  /* Identities */
+
+  identity service-tag-type {
+    description
+      "Base identity of Network Slice Service tag type, which is
+       used for management purposes, such as classification
+       (e.g., customer names) and policy constraints
+       (e.g., Layer 2 or Layer 3 technology realization).";
+  }
+
+  identity customer {
+    base service-tag-type;
+    description
+      "The Network Slice Service customer name tag type,
+       e.g., adding tags with 'customer name' when multiple actual
+       customers use the same Network Slice Service.";
+  }
+
+  identity service {
+    base service-tag-type;
+    description
+      "The Network Slice Service tag type, which can indicate the
+       technical constraints used during service realization,
+       for example, Layer 2 or Layer 3 technologies.";
+  }
+
+  identity opaque {
+    base service-tag-type;
+    description
+      "An opaque type, which can be used for future use,
+       such as filtering of services.";
+  }
+
+  identity attachment-circuit-tag-type {
+    description
+      "Base identity for the attachment circuit tag type.";
+  }
+
+  identity vlan-id {
+    base attachment-circuit-tag-type;
+    description
+      "Identity for VLAN ID tag type, 802.1Q dot1Q.";
+    reference
+      "IEEE Std 802.1Q: IEEE Standard for Local and Metropolitan
+                        Area Networks--Bridges and Bridged
+                        Networks";
+  }
+
+  identity cvlan-id {
+    base attachment-circuit-tag-type;
+    description
+      "Identity for C-VLAN ID tag type, 802.1ad QinQ VLAN IDs.";
+    reference
+      "IEEE Std 802.1ad: IEEE Standard for Local and Metropolitan
+                         Area Networks---Virtual Bridged Local
+                         Area Networks---Amendment 4: Provider
+                         Bridges";
+  }
+
+  identity svlan-id {
+    base attachment-circuit-tag-type;
+    description
+      "Identity for S-VLAN ID tag type, 802.1ad QinQ VLAN IDs.";
+    reference
+      "IEEE Std 802.1ad: IEEE Standard for Local and Metropolitan
+                         Area Networks---Virtual Bridged Local
+                         Area Networks---Amendment 4: Provider
+                         Bridges";
+  }
+
+  identity ip-address-mask {
+    base attachment-circuit-tag-type;
+    description
+      "Identity for IP address mask tag type.";
+  }
+
+  identity service-isolation-type {
+    description
+      "Base identity for Network Slice Service isolation type.";
+  }
+
+  identity traffic-isolation {
+    base service-isolation-type;
+    description
+      "Specify the requirement for separating the traffic of the
+       customer's Network Slice Service from other services,
+       which may be provided by the service provider using VPN
+       technologies, such as L3VPN, L2VPN, EVPN, etc.";
+  }
+
+  identity service-security-type {
+    description
+      "Base identity for Network Slice Service security type.";
+  }
+
+  identity authentication {
+    base service-security-type;
+    description
+      "Indicates that the Slice Service requires authentication.";
+  }
+
+  identity integrity {
+    base service-security-type;
+    description
+      "Indicates that the Slice Service requires data integrity.";
+  }
+
+  identity encryption {
+    base service-security-type;
+    description
+      "Indicates that the Slice Service requires data encryption.";
+  }
+
+  identity point-to-point {
+    base vpn-common:vpn-topology;
+    description
+      "Identity for point-to-point Network Slice
+       Service connectivity.";
+  }
+
+  identity point-to-multipoint {
+    base vpn-common:vpn-topology;
+    description
+      "Identity for point-to-multipoint Network Slice
+       Service connectivity.";
+  }
+
+  identity multipoint-to-multipoint {
+    base vpn-common:vpn-topology;
+    description
+      "Identity for multipoint-to-multipoint Network Slice
+       Service connectivity.";
+  }
+
+  identity multipoint-to-point {
+    base vpn-common:vpn-topology;
+    description
+      "Identity for multipoint-to-point Network Slice
+       Service connectivity.";
+  }
+
+  identity sender-role {
+    base vpn-common:role;
+    description
+      "Indicates that an SDP is acting as a sender.";
+  }
+
+  identity receiver-role {
+    base vpn-common:role;
+    description
+      "Indicates that an SDP is acting as a receiver.";
+  }
+
+  identity service-slo-metric-type {
+    description
+      "Base identity for Network Slice Service SLO metric type.";
+  }
+
+  identity one-way-bandwidth {
+    base service-slo-metric-type;
+    description
+      "SLO bandwidth metric. Minimum guaranteed bandwidth between
+       two SDPs at any time and is measured unidirectionally.";
+  }
+
+  identity two-way-bandwidth {
+    base service-slo-metric-type;
+    description
+      "SLO bandwidth metric. Minimum guaranteed bandwidth between
+       two SDPs at any time.";
+  }
+
+  identity shared-bandwidth {
+    base service-slo-metric-type;
+    description
+      "The shared SLO bandwidth bound. It is the limit on the
+       bandwidth that can be shared amongst a group of
+       connectivity constructs of a Slice Service.";
+  }
+
+  identity one-way-delay-maximum {
+    base service-slo-metric-type;
+    description
+      "The SLO objective of this metric is the upper bound of network
+       delay when transmitting between two SDPs.";
+    reference
+      "RFC 7679: A One-Way Delay Metric for IP Performance
+                 Metrics (IPPM)";
+  }
+
+  identity one-way-delay-percentile {
+    base service-slo-metric-type;
+    description
+      "The SLO objective of this metric is percentile objective of
+       network delay when transmitting between two SDPs.
+       The metric is defined in RFC7679.";
+    reference
+      "RFC 7679: A One-Way Delay Metric for IP Performance
+                 Metrics (IPPM)";
+  }
+
+  identity two-way-delay-maximum {
+    base service-slo-metric-type;
+    description
+      "SLO two-way delay is the upper bound of network delay when
+       transmitting between two SDPs";
+    reference
+      "RFC 2681: A Round-trip Delay Metric for IPPM";
+  }
+
+  identity two-way-delay-percentile {
+    base service-slo-metric-type;
+    description
+      "The SLO objective of this metric is the percentile
+       objective of network delay when the traffic transmitting
+       between two SDPs.";
+    reference
+      "RFC 2681: A Round-trip Delay Metric for IPPM";
+  }
+
+  identity one-way-delay-variation-maximum {
+    base service-slo-metric-type;
+    description
+      "The SLO objective of this metric is maximum bound of the
+       difference in the one-way delay between sequential packets
+       between two SDPs.";
+    reference
+      "RFC 3393: IP Packet Delay Variation Metric for IP Performance
+                 Metrics (IPPM)";
+  }
+
+  identity one-way-delay-variation-percentile {
+    base service-slo-metric-type;
+    description
+      "The SLO objective of this metric is the percentile objective
+       in the one-way delay between sequential packets between two
+       SDPs.";
+    reference
+      "RFC 3393: IP Packet Delay Variation Metric for IP Performance
+                 Metrics (IPPM)";
+  }
+
+  identity two-way-delay-variation-maximum {
+    base service-slo-metric-type;
+    description
+      "SLO two-way delay variation is the difference in the
+       round-trip delay between sequential packets between two
+       SDPs.";
+    reference
+      "RFC 5481: Packet Delay Variation Applicability Statement";
+  }
+
+  identity two-way-delay-variation-percentile {
+    base service-slo-metric-type;
+    description
+      "The SLO objective of this metric is the percentile objective
+       in the round-trip delay between sequential packets between
+       two SDPs.";
+    reference
+      "RFC 5481: Packet Delay Variation Applicability Statement";
+  }
+
+  identity one-way-packet-loss {
+    base service-slo-metric-type;
+    description
+      "This metric type refers to the ratio of packets dropped
+       to packets transmitted between two SDPs in one-way.";
+    reference
+      "RFC 7680: A One-Way Loss Metric for IP Performance
+                 Metrics (IPPM)";
+  }
+
+  identity two-way-packet-loss {
+    base service-slo-metric-type;
+    description
+      "This metric type refers to the ratio of packets dropped
+       to packets transmitted between two SDPs in two-way.";
+    reference
+      "RFC 7680: A One-Way Loss Metric for IP Performance
+                 Metrics (IPPM)";
+  }
+
+  identity availability-type {
+    description
+      "Base identity for availability.";
+  }
+
+  identity six-nines {
+    base availability-type;
+    description
+      "Specifies the availability level: 99.9999%";
+  }
+
+  identity five-nines {
+    base availability-type;
+    description
+      "Specifies the availability level: 99.999%";
+  }
+
+  identity four-nines {
+    base availability-type;
+    description
+      "Specifies the availability level: 99.99%";
+  }
+
+  identity three-nines {
+    base availability-type;
+    description
+      "Specifies the availability level: 99.9%";
+  }
+
+  identity two-nines {
+    base availability-type;
+    description
+      "Specifies the availability level: 99%";
+  }
+
+  identity service-match-type {
+    description
+      "Base identity for Network Slice Service traffic
+       match type.";
+  }
+  identity phy-interface {
+    base service-match-type;
+    description
+      "Uses the physical interface as match criteria for
+       Slice Service traffic.";
+  }
+
+  identity vlan {
+    base service-match-type;
+    description
+      "Uses the VLAN ID as match criteria for the Slice Service
+       traffic.";
+  }
+
+  identity label {
+    base service-match-type;
+    description
+      "Uses the MPLS label as match criteria for the Slice Service
+       traffic.";
+  }
+
+  identity source-ip-prefix {
+    base service-match-type;
+    description
+      "Uses source IP prefix as match criteria for the Slice Service
+       traffic. Examples of 'value' of this match type are
+       '192.0.2.0/24' and '2001:db8::1/64'.";
+  }
+
+  identity destination-ip-prefix {
+    base service-match-type;
+    description
+      "Uses destination IP prefix as match criteria for the Slice
+       Service traffic. Examples of 'value' of this match type are
+       '203.0.113.1/32' and '2001:db8::2/128'.";
+  }
+
+  identity dscp {
+    base service-match-type;
+    description
+      "Uses DSCP field in the IP packet header as match criteria
+       for the Slice Service traffic.";
+  }
+
+  identity acl {
+    base service-match-type;
+    description
+      "Uses Access Control List (ACL) as match criteria
+       for the Slice Service traffic.";
+    reference
+      "RFC 8519: YANG Data Model for Network Access Control
+                 Lists (ACLs)";
+  }
+
+  identity any {
+    base service-match-type;
+    description
+      "Matches any Slice Service traffic.";
+  }
+
+  identity source-tcp-port {
+    base service-match-type;
+    description
+      "Uses source TCP port as match criteria for the Slice Service
+      traffic. Examples of 'value' of this match type are
+      '8080' and '22'.";
+  }
+  
+  identity destination-tcp-port {
+    base service-match-type;
+    description
+      "Uses destination TCP port as match criteria for the Slice
+      Service traffic. Examples of 'value' of this match type are
+      '8080' and '22'.";
+  }
+  
+  identity source-udp-port {
+    base service-match-type;
+    description
+      "Uses source UDP port as match criteria for the Slice Service
+      traffic. Examples of 'value' of this match type are
+      '53', '67' and '68'.";
+  }
+ 
+identity destination-udp-port {
+  base service-match-type;
+  description
+    "Uses destination UDP port as match criteria for the Slice
+    Service traffic. Examples of 'value' of this match type are
+    '53', '67' and '68'.";
+}
+
+  identity slo-sle-policy-override {
+    description
+      "Base identity for SLO/SLE policy override options.";
+  }
+
+  identity full-override {
+    base slo-sle-policy-override;
+    description
+      "The SLO/SLE policy defined at the child level overrides a
+       parent SLO/SLE policy, which means that no SLO/SLEs are
+       inherited from parent if a child SLO/SLE policy exists.";
+  }
+
+  identity partial-override {
+    base slo-sle-policy-override;
+    description
+      "The SLO/SLE policy defined at the child level updates the
+       parent SLO/SLE policy. For example, if a specific SLO is
+       defined at the child level, that specific SLO overrides
+       the one inherited from a parent SLO/SLE policy, while all
+       other SLOs in the parent SLO-SLE policy still apply.";
+  }
+
+  /* Typedef */
+
+  typedef percentage {
+    type decimal64 {
+      fraction-digits 5;
+      range "0..100";
+    }
+    description
+      "Percentage to 5 decimal places.";
+  }
+
+  typedef percentile {
+    type decimal64 {
+      fraction-digits 3;
+      range "0..100";
+    }
+    description
+      "The percentile is a value between 0 and 100
+       to 3 decimal places, e.g., 10.000, 99.900,99.990, etc.
+       For example, for a given one-way delay measurement,
+       if the percentile is set to 95.000 and the 95th percentile
+       one-way delay is 2 milliseconds, then the 95 percent of
+       the sample value is less than or equal to 2 milliseconds.";
+  }
+
+  typedef slice-template-ref {
+    type leafref {
+      path "/ietf-nss:network-slice-services"
+         + "/ietf-nss:slo-sle-templates"
+         + "/ietf-nss:slo-sle-template"
+         + "/ietf-nss:id";
+    }
+    description
+      "This type is used by data models that need to reference
+       Network Slice templates.";
+  }
+
+  typedef slice-service-ref {
+    type leafref {
+      path
+        "/ietf-nss:network-slice-services/ietf-nss:slice-service"
+      + "/ietf-nss:id";
+    }
+    description
+      "Defines a reference to a slice service that can be used
+       by other modules.";
+  }
+
+  /* Groupings */
+
+  grouping service-slos {
+    description
+      "A reusable grouping for directly measurable objectives of
+       a Slice Service.";
+    container slo-policy {
+      description
+        "Contains the SLO policy.";
+      list metric-bound {
+        key "metric-type";
+        description
+          "List of Slice Service metric bounds.";
+        leaf metric-type {
+          type identityref {
+            base service-slo-metric-type;
+          }
+          description
+            "Identifies SLO metric type of the Slice Service.";
+        }
+        leaf metric-unit {
+          type string;
+          mandatory true;
+          description
+            "The metric unit of the parameter. For example,
+             for time units, where the options are hours, minutes,
+             seconds, milliseconds, microseconds, and nanoseconds;
+             for bandwidth units, where the options are bps, Kbps,
+             Mbps, Gbps; for the packet loss rate unit,
+             the options can be a percentage.";
+        }
+        leaf value-description {
+          type string;
+          description
+            "The description of the provided value.";
+        }
+        leaf percentile-value {
+          type percentile;
+          description
+            "The percentile value of the metric type.";
+        }
+        leaf bound {
+          type uint64;
+          description
+            "The bound on the Slice Service connection metric.
+             When set to zero, this indicates an unbounded
+             upper limit for the specific metric-type.";
+        }
+      }
+      leaf availability {
+        type identityref {
+          base availability-type;
+        }
+        description
+          "Service availability level";
+      }
+      leaf mtu {
+        type uint32;
+        units "bytes";
+        description
+          "Specifies the maximum length of Layer 2 data
+           packets of the Slice Service.
+           If the customer sends packets that are longer than the
+           requested service MTU, the network may discard them
+           (or for IPv4, fragment them).
+           This service MTU takes precedence over the MTUs of
+           all attachment circuits (ACs). The value needs to be
+           less than or equal to the minimum MTU value of
+           all ACs in the SDPs.";
+      }
+    }
+  }
+
+  grouping service-sles {
+    description
+      "A reusable grouping for indirectly measurable objectives of
+       a Slice Service.";
+    container sle-policy {
+      description
+        "Contains the SLE policy.";
+      leaf-list security {
+        type identityref {
+          base service-security-type;
+        }
+        description
+          "The security functions that the customer requests
+           the operator to apply to traffic between the two SDPs.";
+      }
+      leaf-list isolation {
+        type identityref {
+          base service-isolation-type;
+        }
+        description
+          "The Slice Service isolation requirement.";
+      }
+      leaf max-occupancy-level {
+        type uint8 {
+          range "1..100";
+        }
+        description
+          "The maximal occupancy level specifies the number of flows
+           to be admitted and optionally a maximum number of
+           countable resource units (e.g., IP or MAC addresses)
+           a Network Slice Service can consume.";
+      }
+      container path-constraints {
+        description
+          "Container for the policy of path constraints
+           applicable to the Slice Service.";
+        container service-functions {
+          description
+            "Container for the policy of service function
+             applicable to the Slice Service.";
+        }
+        container diversity {
+          description
+            "Container for the policy of disjointness
+             applicable to the Slice Service.";
+          leaf diversity-type {
+            type te-types:te-path-disjointness;
+            description
+              "The type of disjointness on Slice Service, i.e.,
+               across all connectivity constructs.";
+          }
+        }
+      }
+    }
+  }
+
+  grouping slice-service-template {
+    description
+      "A reusable grouping for Slice Service templates.";
+    container slo-sle-templates {
+      description
+        "Contains a set of Slice Service templates.";
+      list slo-sle-template {
+        key "id";
+        description
+          "List for SLO and SLE template identifiers.";
+        leaf id {
+          type string;
+          description
+            "Identification of the Service Level Objective (SLO)
+             and Service Level Expectation (SLE) template to be used.
+             Local administration meaning.";
+        }
+        leaf description {
+          type string;
+          description
+            "Describes the SLO and SLE policy template.";
+        }
+        leaf template-ref {
+          type slice-template-ref;
+          description
+            "The reference to a standard template. When set it
+              indicates the base template over which further
+              SLO/SLE policy changes are made.";
+        }
+        uses service-slos;
+        uses service-sles;
+      }
+    }
+  }
+
+  grouping service-slo-sle-policy {
+    description
+      "Slice service policy grouping.";
+    choice slo-sle-policy {
+      description
+        "Choice for SLO and SLE policy template.
+         Can be standard template or customized template.";
+      case standard {
+        description
+          "Standard SLO template.";
+        leaf slo-sle-template {
+          type slice-template-ref;
+          description
+            "Standard SLO and SLE template to be used.";
+        }
+      }
+      case custom {
+        description
+          "Customized SLO and SLE template.";
+        container service-slo-sle-policy {
+          description
+            "Contains the SLO and SLE policy.";
+          leaf description {
+            type string;
+            description
+              "Describes the SLO and SLE policy.";
+          }
+          uses service-slos;
+          uses service-sles;
+        }
+      }
+    }
+  }
+
+  grouping service-qos {
+    description
+      "Grouping for the Slice Service QoS policy.";
+    container incoming-qos-policy {
+      description
+        "The QoS policy imposed on ingress direction of the traffic,
+         from the customer network or from another provider's
+         network.";
+      leaf qos-policy-name {
+        type string;
+        description
+          "The name of the QoS policy that is applied to the
+           attachment circuit. The name can reference a QoS
+           profile that is pre-provisioned on the device.";
+      }
+      container rate-limits {
+        description
+          "Container for the asymmetric traffic control.";
+        uses ac-common:bandwidth-parameters;
+        container classes {
+          description
+            "Container for service class bandwidth control.";
+          list cos {
+            key "cos-id";
+            description
+              "List of Class of Services.";
+            leaf cos-id {
+              type uint8;
+              description
+                "Identifier of the CoS, indicated by
+                 a Differentiated Services Code Point
+                 (DSCP) or a CE-CLAN CoS (802.1p)
+                 value in the service frame.";
+              reference
+                "IEEE Std 802.1Q: Bridges and Bridged
+                                  Networks";
+            }
+            uses ac-common:bandwidth-parameters;
+          }
+        }
+      }
+    }
+    container outgoing-qos-policy {
+      description
+        "The QoS policy imposed on egress direction of the traffic,
+         towards the customer network or towards another
+         provider's network.";
+      leaf qos-policy-name {
+        type string;
+        description
+          "The name of the QoS policy that is applied to the
+           attachment circuit. The name can reference a QoS
+           profile that is pre-provisioned on the device.";
+      }
+      container rate-limits {
+        description
+          "The rate-limit imposed on outgoing traffic.";
+        uses ac-common:bandwidth-parameters;
+        container classes {
+          description
+            "Container for classes.";
+          list cos {
+            key "cos-id";
+            description
+              "List of Class of Services.";
+            leaf cos-id {
+              type uint8;
+              description
+                "Identifier of the CoS, indicated by
+                 a Differentiated Services Code Point
+                 (DSCP) or a CE-CLAN CoS (802.1p)
+                 value in the service frame.";
+              reference
+                "IEEE Std 802.1Q: Bridges and Bridged
+                                  Networks";
+            }
+            uses ac-common:bandwidth-parameters;
+          }
+        }
+      }
+    }
+  }
+
+  grouping service-slo-sle-policy-override {
+    description
+      "Slice Service policy override grouping.";
+    leaf service-slo-sle-policy-override {
+      type identityref {
+        base slo-sle-policy-override;
+      }
+      description
+        "SLO/SLE policy override option.";
+    }
+  }
+
+  grouping connectivity-construct-monitoring-metrics {
+    description
+      "Grouping for connectivity construct monitoring metrics.";
+    uses
+      te-packet-types:one-way-performance-metrics-gauge-packet;
+    uses
+      te-packet-types:two-way-performance-metrics-gauge-packet;
+  }
+  /* Main Network Slice Services Container */
+
+  container network-slice-services {
+    description
+      "Contains a list of Network Slice Services";
+    uses slice-service-template;
+    list slice-service {
+      key "id";
+      description
+        "A Slice Service is identified by a service id.";
+      leaf id {
+        type string;
+        description
+          "A unique Slice Service identifier within an NSC.";
+      }
+      leaf description {
+        type string;
+        description
+          "Textual description of the Slice Service.";
+      }
+      container service-tags {
+        description
+          "Container for a list of service tags for management
+           purposes, such as policy constraints
+           (e.g., Layer 2 or Layer 3 technology realization),
+           classification (e.g., customer names, opaque values).";
+        list tag-type {
+          key "tag-type";
+          description
+            "The service tag list.";
+          leaf tag-type {
+            type identityref {
+              base service-tag-type;
+            }
+            description
+              "Slice Service tag type, e.g., realization technology
+               constraints, customer name, or other customer-defined
+               opaque types.";
+          }
+          leaf-list value {
+            type string;
+            description
+              "The tag values, e.g., 5G customer names when multiple
+               customers share the same Slice Service in 5G scenario,
+               or Slice realization technology (such as Layer 2 or
+               Layer 3).";
+          }
+        }
+      }
+      uses service-slo-sle-policy;
+      leaf compute-only {
+        type empty;
+        description
+          "When present, this is a feasibility check. That is, no
+           resources are reserved in the network.";
+      }
+      uses ac-common:service-status;
+      container sdps {
+        description
+          "Slice Service SDPs.";
+        list sdp {
+          key "id";
+          min-elements 2;
+          description
+            "List of SDPs in this Slice Service.";
+          leaf id {
+            type string;
+            description
+              "The unique identifier of the SDP within the scope of
+               an NSC.";
+          }
+          leaf description {
+            type string;
+            description
+              "Provides a description of the SDP.";
+          }
+          uses geo:geo-location;
+          leaf node-id {
+            type string;
+            description
+              "A unique identifier of an edge node of the SDP
+               within the scope of the NSC.";
+          }
+          leaf-list sdp-ip-address {
+            type inet:ip-address;
+            description
+              "IPv4 or IPv6 address of the SDP.";
+          }
+          leaf tp-ref {
+            type leafref {
+              path
+                "/nw:networks/nw:network[nw:network-id="
+              + "current()/../../../custom-topology/network-ref]/"
+              + "nw:node/nt:termination-point/nt:tp-id";
+            }
+            description
+              "A reference to Termination Point (TP) in the custom
+               topology";
+            reference
+              "RFC 8345: A YANG Data Model for Network Topologies";
+          }
+          container service-match-criteria {
+            description
+              "Describes the Slice Service match criteria.";
+            list match-criterion {
+              key "index";
+              description
+                "List of the Slice Service traffic match criteria.";
+              leaf index {
+                type uint32;
+                description
+                  "The identifier of a match criteria.";
+              }
+              list match-type {
+                key "type";
+                description
+                  "List of the Slice Service traffic match types.";
+                leaf type {
+                  type identityref {
+                    base service-match-type;
+                  }
+                  mandatory true;
+                  description
+                    "Indicates the match type of the entry in the
+                     list of the Slice Service match criteria.";
+                }
+                leaf-list value {
+                  type string;
+                  description
+                    "Provides a value for the Slice Service match
+                     criteria, e.g., IP prefix, VLAN ID, or
+                     ACL name.";
+                }
+              }
+              leaf target-connection-group-id {
+                type leafref {
+                  path
+                    "../../../../../ietf-nss:connection-groups"
+                  + "/ietf-nss:connection-group"
+                  + "/ietf-nss:id";
+                }
+                mandatory true;
+                description
+                  "Reference to the Slice Service connection group.";
+              }
+              leaf connection-group-sdp-role {
+                type identityref {
+                  base vpn-common:role;
+                }
+                description
+                  "Specifies the role of SDP in the connection group
+                   When the service connection type is MP2MP,
+                   such as hub and spoke service connection type.
+                   In addition, this helps to create connectivity
+                   construct automatically, rather than explicitly
+                   specifying each one.";
+              }
+              leaf target-connectivity-construct-id {
+                type leafref {
+                  path
+                    "../../../../../ietf-nss:connection-groups"
+                  + "/ietf-nss:connection-group[ietf-nss:id="
+                  + "current()/../target-connection-group-id]"
+                  + "/ietf-nss:connectivity-construct/ietf-nss:id";
+                }
+                description
+                  "Reference to a Network Slice connection
+                   construct.";
+              }
+            }
+          }
+          uses service-qos;
+          container sdp-peering {
+            description
+              "Describes SDP peering attributes.";
+            leaf-list peer-sap-id {
+              type string;
+              description
+                "Indicates the reference to the remote endpoints of
+                 the attachment circuits. This information can be
+                 used for correlation purposes, such as identifying
+                 SAPs of provider equipments when requesting
+                 a service with CE based SDP attributes.";
+              reference
+                "RFC 9408: A YANG Network Data Model for Service
+                 Attachment Points (SAPs)";
+            }
+            container protocols {
+              description
+                "Serves as an augmentation target.
+                 Protocols can be augmented into this container,
+                 e.g., BGP, static routing.";
+            }
+          }
+          leaf-list ac-svc-ref {
+            type ac-svc:attachment-circuit-reference;
+            description
+              "A reference to the ACs that have been created before
+               the slice creation.";
+            reference
+              "RFC CCCC: YANG Data Models for Bearers and
+                'Attachment Circuits'-as-a-Service (ACaaS)";
+          }
+          leaf ce-mode {
+            type boolean;
+            description
+              "Indicates that SDP is on the CE.";
+          }
+          container attachment-circuits {
+            description
+              "List of attachment circuits.";
+            list attachment-circuit {
+              key "id";
+              description
+                "The Network Slice Service SDP attachment circuit
+                 related parameters.";
+              leaf id {
+                type string;
+                description
+                  "The identifier of attachment circuit.";
+              }
+              leaf description {
+                type string;
+                description
+                  "The attachment circuit's description.";
+              }
+              leaf ac-svc-ref {
+                type ac-svc:attachment-circuit-reference;
+                description
+                  "A reference to the AC service that has been
+                   created before the slice creation.";
+                reference
+                  "RFC CCCC: YANG Data Models for Bearers and
+                    'Attachment Circuits'-as-a-Service (ACaaS)";
+              }
+              leaf ac-node-id {
+                type string;
+                description
+                  "The attachment circuit node ID in the case of
+                   multi-homing.";
+              }
+              leaf ac-tp-id {
+                type string;
+                description
+                  "The termination port ID of the
+                   attachment circuit.";
+              }
+              leaf ac-ipv4-address {
+                type inet:ipv4-address;
+                description
+                  "The IPv4 address of the AC.";
+              }
+              leaf ac-ipv4-prefix-length {
+                type uint8;
+                description
+                  "The IPv4 subnet prefix length expressed in bits.";
+              }
+              leaf ac-ipv6-address {
+                type inet:ipv6-address;
+                description
+                  "The IPv6 address of the AC.";
+              }
+              leaf ac-ipv6-prefix-length {
+                type uint8;
+                description
+                  "The IPv6 subnet prefix length expressed in bits.";
+              }
+              leaf mtu {
+                type uint32;
+                units "bytes";
+                description
+                  "Maximum size of the Slice Service Layer 2 data
+                   packet that can traverse an SDP.";
+              }
+              container ac-tags {
+                description
+                  "Container for the attachment circuit tags.";
+                list ac-tag {
+                  key "tag-type";
+                  description
+                    "The attachment circuit tag list.";
+                  leaf tag-type {
+                    type identityref {
+                      base attachment-circuit-tag-type;
+                    }
+                    description
+                      "The attachment circuit tag type.";
+                  }
+                  leaf-list value {
+                    type string;
+                    description
+                      "The attachment circuit tag values.
+                       For example, the tag may indicate
+                       multiple VLAN identifiers.";
+                  }
+                }
+              }
+              uses service-qos;
+              container sdp-peering {
+                description
+                  "Describes SDP peering attributes.";
+                leaf peer-sap-id {
+                  type string;
+                  description
+                    "Indicates a reference to the remote endpoints
+                     of an attachment circuit. This information can
+                     be used for correlation purposes, such as
+                     identifying a service attachment point (SAP)
+                     of a provider equipment when requesting a
+                     service with CE based SDP attributes.";
+                  reference
+                    "RFC 9408: A YANG Network Data Model for
+                               Service Attachment Points (SAPs)";
+                }
+                container protocols {
+                  description
+                    "Serves as an augmentation target.
+                     Protocols can be augmented into this container,
+                     e.g., BGP or static routing.";
+                }
+              }
+              uses ac-common:service-status;
+            }
+          }
+          uses ac-common:service-status;
+          container sdp-monitoring {
+            config false;
+            description
+              "Container for SDP monitoring metrics.";
+            leaf incoming-bw-value {
+              type yang:gauge64;
+              units "bps";
+              description
+                "Indicates the absolute value of the incoming
+                 bandwidth at an SDP from the customer network or
+                 from another provider's network.";
+            }
+            leaf incoming-bw-percent {
+              type percentage;
+              units "percent";
+              description
+                "Indicates a percentage of the incoming bandwidth
+                 at an SDP from the customer network or
+                 from another provider's network.";
+            }
+            leaf outgoing-bw-value {
+              type yang:gauge64;
+              units "bps";
+              description
+                "Indicates the absolute value of the outgoing
+                 bandwidth at an SDP towards the customer network or
+                 towards another provider's network.";
+            }
+            leaf outgoing-bw-percent {
+              type percentage;
+              units "percent";
+              description
+                "Indicates a percentage of the outgoing bandwidth
+                 at an SDP towards the customer network or towards
+                 another provider's network.";
+            }
+          }
+        }
+      }
+      container connection-groups {
+        description
+          "Contains connection groups.";
+        list connection-group {
+          key "id";
+          description
+            "List of connection groups.";
+          leaf id {
+            type string;
+            description
+              "The connection group identifier.";
+          }
+          leaf connectivity-type {
+            type identityref {
+              base vpn-common:vpn-topology;
+            }
+            description
+              "Connection group connectivity type.";
+          }
+          uses service-slo-sle-policy;
+          /* Per connection group SLO/SLE policy
+           * overrides the per Slice SLO/SLE policy.
+           */
+          uses service-slo-sle-policy-override;
+          list connectivity-construct {
+            key "id";
+            description
+              "List of connectivity constructs.";
+            leaf id {
+              type string;
+              description
+                "The connectivity construct identifier.";
+            }
+            choice type {
+              default "p2p";
+              description
+                "Choice for connectivity construct type.";
+              case p2p {
+                description
+                  "P2P connectivity construct.";
+                leaf p2p-sender-sdp {
+                  type leafref {
+                    path "../../../../sdps/sdp/id";
+                  }
+                  description
+                    "Reference to a sender SDP.";
+                }
+                leaf p2p-receiver-sdp {
+                  type leafref {
+                    path "../../../../sdps/sdp/id";
+                  }
+                  description
+                    "Reference to a receiver SDP.";
+                }
+              }
+              case p2mp {
+                description
+                  "P2MP connectivity construct.";
+                leaf p2mp-sender-sdp {
+                  type leafref {
+                    path "../../../../sdps/sdp/id";
+                  }
+                  description
+                    "Reference to a sender SDP.";
+                }
+                leaf-list p2mp-receiver-sdp {
+                  type leafref {
+                    path "../../../../sdps/sdp/id";
+                  }
+                  description
+                    "Reference to a receiver SDP.";
+                }
+              }
+              case a2a {
+                description
+                  "A2A connectivity construct.";
+                list a2a-sdp {
+                  key "sdp-id";
+                  description
+                    "List of included A2A SDPs.";
+                  leaf sdp-id {
+                    type leafref {
+                      path "../../../../../sdps/sdp/id";
+                    }
+                    description
+                      "Reference to an SDP.";
+                  }
+                  uses service-slo-sle-policy;
+                }
+              }
+            }
+            uses service-slo-sle-policy;
+            /* Per connectivity construct SLO/SLE policy
+             * overrides the per slice SLO/SLE policy.
+             */
+            uses service-slo-sle-policy-override;
+            uses ac-common:service-status;
+            container connectivity-construct-monitoring {
+              config false;
+              description
+                "SLO status per connectivity construct.";
+              uses connectivity-construct-monitoring-metrics;
+            }
+          }
+          container connection-group-monitoring {
+            config false;
+            description
+              "SLO status per connection group.";
+            uses connectivity-construct-monitoring-metrics;
+          }
+        }
+      }
+      container custom-topology {
+        description
+          "Serves as an augmentation target.
+           Container for custom topology, which is indicated by the
+           referenced topology predefined, e.g., an abstract RFC8345
+           topology.";
+        uses nw:network-ref;
+      }
+    }
+  }
+}
diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-network-slice@2022-03-04.yang b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-network-slice@2022-03-04.yang
new file mode 100644
index 0000000000000000000000000000000000000000..b1ead4bf025c59065d01172f309af188c0ee2f75
--- /dev/null
+++ b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-network-slice@2022-03-04.yang
@@ -0,0 +1,1130 @@
+module ietf-network-slice {
+  yang-version 1.1;
+  namespace "urn:ietf:params:xml:ns:yang:ietf-network-slice";
+  prefix ietf-ns;
+
+  import ietf-inet-types {
+    prefix inet;
+    reference
+      "RFC 6991: Common YANG Types.";
+  }
+  import ietf-te-types {
+    prefix te-types;
+    reference
+      "RFC 8776: Common YANG Data Types for Traffic Engineering.";
+  }
+  import ietf-te-packet-types {
+    prefix te-packet-types;
+    reference
+      "RFC 8776: Common YANG Data Types for Traffic Engineering.";
+  }
+
+  organization
+    "IETF Traffic Engineering Architecture and Signaling (TEAS)
+     Working Group";
+  contact
+    "WG Web:  <https://tools.ietf.org/wg/teas/>
+     WG List:  <mailto:teas@ietf.org>
+
+     Editor: Bo Wu
+          <lana.wubo@huawei.com>
+     Editor: Dhruv Dhody
+          <dhruv.ietf@gmail.com>
+     Editor: Reza Rokui
+          <reza.rokui@nokia.com>
+     Editor: Tarek Saad
+          <tsaad@juniper.net>
+     Author: Liuyan Han
+          <hanliuyan@chinamobile.com>";
+  description
+    "This module contains a YANG module for the IETF Network Slice.
+
+        Copyright (c) 2022 IETF Trust and the persons identified as
+        authors of the code.  All rights reserved.
+
+        Redistribution and use in source and binary forms, with or
+        without modification, is permitted pursuant to, and subject
+        to the license terms contained in, the Revised BSD License
+        set forth in Section 4.c of the IETF Trust's Legal Provisions
+        Relating to IETF Documents
+        (https://trustee.ietf.org/license-info).
+
+     This version of this YANG module is part of RFC XXXX; see the
+     RFC itself for full legal notices.";
+
+  revision 2022-03-04 {
+    description
+      "initial version.";
+    reference
+      "RFC XXXX: A Yang Data Model for IETF Network Slice Operation";
+  }
+
+  /* Features */
+  /* Identities */
+
+  identity ns-tag-type {
+    description
+      "Base identity for IETF Network Slice tag type.";
+  }
+
+  identity ns-tag-customer {
+    base ns-tag-type;
+    description
+      "The IETF Network Slice customer ID tag type.";
+  }
+
+  identity ns-tag-service {
+    base ns-tag-type;
+    description
+      "The IETF Network Slice service tag type.";
+  }
+
+  identity ns-tag-opaque {
+    base ns-tag-type;
+    description
+      "The IETF Network Slice opaque tag type.";
+  }
+
+  identity network-access-tag-type {
+    description
+      "Base identity for the network access tag type.";
+  }
+
+  identity network-access-tag-vlan-id {
+    base network-access-tag-type;
+    description
+      "The network access interface VLAN ID tag type.";
+  }
+
+  identity network-access-tag-ip-mask {
+    base network-access-tag-type;
+    description
+      "The network access tag IP mask.";
+  }
+
+  identity network-access-tag-opaque {
+    base network-access-tag-type;
+    description
+      "The network access opaque tag type.";
+  }
+
+  identity ns-isolation-type {
+    description
+      "Base identity for IETF Network slice isolation level.";
+  }
+
+  identity ns-isolation-shared {
+    base ns-isolation-type;
+    description
+      "Shared resources (e.g. queues) are associated with the Network
+       Slice traffic. Hence, the IETF network slice traffic can be
+       impacted by effects of other services traffic sharing
+       the same resources.";
+  }
+
+  identity ns-isolation-dedicated {
+    base ns-isolation-type;
+    description
+      "Dedicated resources (e.g. queues) are associated with the
+       Network Slice traffic. Hence, the IETF network slice traffic
+       is isolated from other servceis traffic sharing the same
+       resources.";
+  }
+
+  identity ns-security-type {
+    description
+      "Base identity for for IETF Network security level.";
+  }
+
+  identity ns-security-authenticate {
+    base ns-security-type;
+    description
+      "IETF Network Slice requires authentication.";
+  }
+
+  identity ns-security-integrity {
+    base ns-security-type;
+    description
+      "IETF Network Slice requires data integrity.";
+  }
+
+  identity ns-security-encryption {
+    base ns-security-type;
+    description
+      "IETF Network Slice requires data encryption.";
+  }
+
+  identity ns-connectivity-type {
+    description
+      "Base identity for IETF Network Slice connectivity.";
+  }
+
+  identity point-to-point {
+    base ns-connectivity-type;
+    description
+      "Identity for point-to-point IETF Network Slice connectivity.";
+  }
+
+  identity point-to-multipoint {
+    base ns-connectivity-type;
+    description
+      "Identity for point-to-multipoint IETF Network Slice
+       connectivity.";
+  }
+
+  identity multipoint-to-multipoint {
+    base ns-connectivity-type;
+    description
+      "Identity for multipoint-to-multipoint IETF Network Slice
+       connectivity.";
+  }
+
+  identity any-to-any {
+    base ns-connectivity-type;
+    description
+      "Identity for any-to-any IETF Network Slice connectivity.";
+  }
+
+  identity hub-spoke {
+    base ns-connectivity-type;
+    description
+      "Identity for Hub-and-Spoke IETF Network Slice connectivity.";
+  }
+
+  identity custom {
+    base ns-connectivity-type;
+    description
+      "Identity of a custom NS topology where Hubs can act as
+       Spoke for certain parts of the network or Spokes as Hubs.";
+  }
+
+  identity endpoint-role {
+    description
+      "Base identity of a NSE role in an IETF Network Slice topology.";
+  }
+
+  identity any-to-any-role {
+    base endpoint-role;
+    description
+      "Identity of any-to-any NS.";
+  }
+
+  identity spoke-role {
+    base endpoint-role;
+    description
+      "A NSE is acting as a Spoke.";
+  }
+
+  identity hub-role {
+    base endpoint-role;
+    description
+      "A NSE is acting as a Hub.";
+  }
+
+  identity ns-slo-metric-type {
+    description
+      "Base identity for IETF Network Slice SLO metric type.";
+  }
+
+  identity ns-slo-one-way-bandwidth {
+    base ns-slo-metric-type;
+    description
+      "SLO bandwidth metric. Minimum guaranteed bandwidth between
+       two endpoints at any time and is measured unidirectionally.";
+  }
+
+  identity ns-slo-two-way-bandwidth {
+    base ns-slo-metric-type;
+    description
+      "SLO bandwidth metric. Minimum guaranteed bandwidth between
+       two endpoints at any time.";
+  }
+
+  identity ns-slo-shared-bandwidth {
+    base ns-slo-metric-type;
+    description
+      "The shared SLO bandwidth bound. It is the limit on the
+       bandwidth that can be shared amongst a group of connections
+       of an IETF Network Slice.";
+  }
+
+  identity ns-slo-one-way-delay {
+    base ns-slo-metric-type;
+    description
+      "SLO one-way-delay is the upper bound of network delay when
+       transmitting between two endpoints. The metric is defined in
+       RFC7679.";
+  }
+
+  identity ns-slo-two-way-delay {
+    base ns-slo-metric-type;
+    description
+      "SLO two-way delay is the upper bound of network delay when
+       transmitting between two endpoints. The metric is defined in
+       RFC2681.";
+  }
+  identity ns-slo-one-way-delay-variation {
+    base ns-slo-metric-type;
+    description
+      "SLO one-way delay variation is defined by RFC3393, is the
+       difference in the one-way delay between sequential packets
+       between two endpoints.";
+  }
+
+  identity ns-slo-two-way-delay-variation {
+    base ns-slo-metric-type;
+    description
+      "SLO two-way delay variation is defined by RFC5481, is the
+       difference in the round-trip delay between sequential packets
+       between two endpoints.";
+  }
+
+  identity ns-slo-one-way-packet-loss {
+    base ns-slo-metric-type;
+    description
+      "SLO loss metric. The ratio of packets dropped to packets
+       transmitted between two endpoints in one-way
+       over a period of time as specified in RFC7680.";
+  }
+
+  identity ns-slo-two-way-packet-loss {
+    base ns-slo-metric-type;
+    description
+      "SLO loss metric. The ratio of packets dropped to packets
+       transmitted between two endpoints in two-way
+       over a period of time as specified in RFC7680.";
+  }
+
+  identity ns-slo-availability {
+    base ns-slo-metric-type;
+    description
+      "SLO availability level.";
+  }
+
+  identity ns-match-type {
+    description
+      "Base identity for IETF Network Slice traffic match type.";
+  }
+
+  identity ns-phy-interface-match {
+    base ns-match-type;
+    description
+      "Use the physical interface as match criteria for the IETF
+       Network Slice traffic.";
+  }
+
+  identity ns-vlan-match {
+    base ns-match-type;
+    description
+      "Use the VLAN ID as match criteria for the IETF Network Slice
+       traffic.";
+  }
+
+  identity ns-label-match {
+    base ns-match-type;
+    description
+      "Use the MPLS label as match criteria for the IETF Network
+       Slice traffic.";
+  }
+
+  identity peering-protocol-type {
+    description
+      "Base identity for NSE peering protocol type.";
+  }
+
+  identity peering-protocol-bgp {
+    base peering-protocol-type;
+    description
+      "Use BGP as protocol for NSE peering with customer device.";
+  }
+
+  identity peering-static-routing {
+    base peering-protocol-type;
+    description
+      "Use static routing for NSE peering with customer device.";
+  }
+
+  /*
+   * Identity for availability-type
+   */
+
+  identity availability-type {
+    description
+      "Base identity from which specific availability types are
+       derived.";
+  }
+
+  identity level-1 {
+    base availability-type;
+    description
+      "level 1: 99.9999%";
+  }
+  identity level-2 {
+    base availability-type;
+    description
+      "level 2: 99.999%";
+  }
+
+  identity level-3 {
+    base availability-type;
+    description
+      "level 3: 99.99%";
+  }
+
+  identity level-4 {
+    base availability-type;
+    description
+      "level 4: 99.9%";
+  }
+
+  identity level-5 {
+    base availability-type;
+    description
+      "level 5: 99%";
+  }
+
+  /* typedef */
+
+  typedef operational-type {
+    type enumeration {
+      enum up {
+        value 0;
+        description
+          "Operational status UP.";
+      }
+      enum down {
+        value 1;
+        description
+          "Operational status DOWN.";
+      }
+      enum unknown {
+        value 2;
+        description
+          "Operational status UNKNOWN.";
+      }
+    }
+    description
+      "This is a read-only attribute used to determine the
+       status of a particular element.";
+  }
+  typedef ns-monitoring-type {
+    type enumeration {
+      enum one-way {
+        description
+          "Represents one-way measurments monitoring type.";
+      }
+      enum two-way {
+        description
+          "represents two-way measurements monitoring type.";
+      }
+    }
+    description
+      "An enumerated type for monitoring on a IETF Network Slice
+       connection.";
+  }
+
+  /* Groupings */
+
+  grouping status-params {
+    description
+      "A grouping used to join operational and administrative status.";
+    container status {
+      description
+        "A container for the administrative and operational state.";
+      leaf admin-enabled {
+        type boolean;
+        description
+          "The administrative status.";
+      }
+      leaf oper-status {
+        type operational-type;
+        config false;
+        description
+          "The operational status.";
+      }
+    }
+  }
+
+  grouping ns-match-criteria {
+    description
+      "A grouping for the IETF Network Slice match definition.";
+    container ns-match-criteria {
+      description
+        "Describes the IETF Network Slice match criteria.";
+      list ns-match-criterion {
+        key "index";
+        description
+          "List of the IETF Network Slice traffic match criteria.";
+        leaf index {
+          type uint32;
+          description
+            "The entry index.";
+        }
+        leaf match-type {
+          type identityref {
+            base ns-match-type;
+          }
+          description
+            "Identifies an entry in the list of the IETF Network Slice
+             match criteria.";
+        }
+        list values {
+          key "index";
+          description
+            "List of match criteria values.";
+          leaf index {
+            type uint8;
+            description
+              "Index of an entry in the list.";
+          }
+          leaf value {
+            type string;
+            description
+              "Describes the IETF Network Slice match criteria, e.g.
+               IP address, VLAN, etc.";
+          }
+        }
+        leaf target-ns-connection-group-id {
+          type leafref {
+            path "/network-slices/network-slice"
+               + "/ns-connection-groups/ns-connection-group"
+               + "/ns-connection-group-id";
+          }
+          description
+            "reference to a Network Slice connection group.";
+        }
+      }
+    }
+  }
+
+  grouping ns-sles {
+    description
+      "Indirectly Measurable Objectives of a IETF Network
+       Slice.";
+    leaf-list security {
+      type identityref {
+        base ns-security-type;
+      }
+      description
+        "The IETF Network Slice security SLE(s)";
+    }
+    leaf isolation {
+      type identityref {
+        base ns-isolation-type;
+      }
+      default "ns-isolation-shared";
+      description
+        "The IETF Network Slice isolation SLE requirement.";
+    }
+    leaf max-occupancy-level {
+      type uint8 {
+        range "1..100";
+      }
+      description
+        "The maximal occupancy level specifies the number of flows to
+         be admitted.";
+    }
+    leaf mtu {
+      type uint16;
+      units "bytes";
+      mandatory true;
+      description
+        "The MTU specifies the maximum length in octets of data
+         packets that can be transmitted by the NS. The value needs
+         to be less than or equal to the minimum MTU value of
+         all 'ep-network-access-points' in the NSEs of the NS.";
+    }
+    container steering-constraints {
+      description
+        "Container for the policy of steering constraints
+         applicable to IETF Network Slice.";
+      container path-constraints {
+        description
+          "Container for the policy of path constraints
+           applicable to IETF Network Slice.";
+      }
+      container service-function {
+        description
+          "Container for the policy of service function
+           applicable to IETF Network Slice.";
+      }
+    }
+  }
+
+  grouping ns-metric-bounds {
+    description
+      "IETF Network Slice metric bounds grouping.";
+    container ns-metric-bounds {
+      description
+        "IETF Network Slice metric bounds container.";
+      list ns-metric-bound {
+        key "metric-type";
+        description
+          "List of IETF Network Slice metric bounds.";
+        leaf metric-type {
+          type identityref {
+            base ns-slo-metric-type;
+          }
+          description
+            "Identifies an entry in the list of metric type
+             bounds for the IETF Network Slice.";
+        }
+        leaf metric-unit {
+          type string;
+          mandatory true;
+          description
+            "The metric unit of the parameter. For example,
+             s, ms, ns, and so on.";
+        }
+        leaf value-description {
+          type string;
+          description
+            "The description of previous value.";
+        }
+        leaf bound {
+          type uint64;
+          default "0";
+          description
+            "The Bound on the Network Slice connection metric. A
+             zero indicate an unbounded upper limit for the
+             specific metric-type.";
+        }
+      }
+    }
+  }
+
+  grouping ep-peering {
+    description
+      "A grouping for the IETF Network Slice Endpoint peering.";
+    container ep-peering {
+      description
+        "Describes NSE peering attributes.";
+      list protocol {
+        key "protocol-type";
+        description
+          "List of the NSE peering protocol.";
+        leaf protocol-type {
+          type identityref {
+            base peering-protocol-type;
+          }
+          description
+            "Identifies an entry in the list of NSE peering
+             protocol type.";
+        }
+        list attribute {
+          key "index";
+          description
+            "List of protocol attribute.";
+          leaf index {
+            type uint8;
+            description
+              "Index of an entry in the list.";
+          }
+          leaf attribute-description {
+            type string;
+            description
+              "The description of the attribute.";
+          }
+          leaf value {
+            type string;
+            description
+              "Describes the value of protocol attribute, e.g.
+               nexthop address, peer address, etc.";
+          }
+        }
+      }
+    }
+  }
+
+  grouping ep-network-access-points {
+    description
+      "Grouping for the endpoint network access definition.";
+    container ep-network-access-points {
+      description
+        "List of network access points.";
+      list ep-network-access-point {
+        key "network-access-id";
+        description
+          "The IETF Network Slice network access points
+           related parameters.";
+        leaf network-access-id {
+          type string;
+          description
+            "Uniquely identifier a network access point.";
+        }
+        leaf network-access-description {
+          type string;
+          description
+            "The network access point description.";
+        }
+        leaf network-access-node-id {
+          type string;
+          description
+            "The network access point node ID in the case of
+             multi-homing.";
+        }
+        leaf network-access-tp-id {
+          type string;
+          description
+            "The termination port ID of the EP network access
+             point.";
+        }
+        leaf network-access-tp-ip-address {
+          type inet:ip-address;
+          description
+            "The IP address of the EP network access point.";
+        }
+        leaf network-access-tp-ip-prefix-length {
+          type uint8;
+          description
+            "The subnet prefix length expressed in bits.";
+        }
+        leaf network-access-qos-policy-name {
+          type string;
+          description
+            "The name of the QoS policy that is applied to the
+             network access point. The name can reference a QoS
+             profile that is pre-provisioned on the device.";
+        }
+        leaf mtu {
+          type uint16;
+          units "bytes";
+          mandatory true;
+          description
+            "Maximum size in octets of a data packet that
+             can traverse a NSE network access point.";
+        }
+        container network-access-tags {
+          description
+            "Container for the network access tags.";
+          list network-access-tag {
+            key "index";
+            description
+              "The network access point tags list.";
+            leaf index {
+              type uint32;
+              description
+                "The entry index.";
+            }
+            leaf network-access-tag-type {
+              type identityref {
+                base network-access-tag-type;
+              }
+              description
+                "The network access point tag type.";
+            }
+            leaf network-access-tag-value {
+              type string;
+              description
+                "The network access point tag value.";
+            }
+          }
+        }
+        /* Per ep-network-access-point rate limits */
+        uses ns-match-criteria;
+        uses ep-peering;
+        uses ns-rate-limit;
+      }
+    }
+  }
+
+  grouping ep-monitoring-metrics {
+    description
+      "Grouping for the NS endpoint monitoring metrics.";
+    container ep-monitoring {
+      config false;
+      description
+        "Container for NS endpoint monitoring metrics.";
+      leaf incoming-utilized-bandwidth {
+        type te-types:te-bandwidth;
+        description
+          "Incoming bandwidth utilization at an endpoint.";
+      }
+      leaf incoming-bw-utilization {
+        type decimal64 {
+          fraction-digits 5;
+          range "0..100";
+        }
+        units "percent";
+        mandatory true;
+        description
+          "To be used to define the bandwidth utilization
+           as a percentage of the available bandwidth.";
+      }
+      leaf outgoing-utilized-bandwidth {
+        type te-types:te-bandwidth;
+        description
+          "Outoing bandwidth utilization at an endpoint.";
+      }
+      leaf outgoing-bw-utilization {
+        type decimal64 {
+          fraction-digits 5;
+          range "0..100";
+        }
+        units "percent";
+        mandatory true;
+        description
+          "To be used to define the bandwidth utilization
+           as a percentage of the available bandwidth.";
+      }
+    }
+  }
+
+  grouping ns-connection-monitoring-metrics {
+    description
+      "Grouping for NS connection monitoring metrics.";
+    uses te-packet-types:one-way-performance-metrics-packet;
+    uses te-packet-types:two-way-performance-metrics-packet;
+  }
+
+  grouping geolocation-container {
+    description
+      "A grouping containing a GPS location.";
+    container location {
+      description
+        "A container containing a GPS location.";
+      leaf altitude {
+        type int64;
+        units "millimeter";
+        description
+          "Distance above the sea level.";
+      }
+      leaf latitude {
+        type decimal64 {
+          fraction-digits 8;
+          range "-90..90";
+        }
+        description
+          "Relative position north or south on the Earth's surface.";
+      }
+      leaf longitude {
+        type decimal64 {
+          fraction-digits 8;
+          range "-180..180";
+        }
+        description
+          "Angular distance east or west on the Earth's surface.";
+      }
+    }
+    // gps-location
+  }
+
+  // geolocation-container
+
+  grouping bw-rate-limits {
+    description
+      "Bandwidth rate limits grouping.";
+    reference
+      "RFC 7640: Traffic Management Benchmarking";
+    leaf cir {
+      type uint64;
+      units "bps";
+      description
+        "Committed Information Rate. The maximum number of bits
+         that a port can receive or send during one-second over an
+         interface.";
+    }
+    leaf cbs {
+      type uint64;
+      units "bytes";
+      description
+        "Committed Burst Size. CBS controls the bursty nature
+         of the traffic. Traffic that does not use the configured
+         CIR accumulates credits until the credits reach the
+         configured CBS.";
+    }
+    leaf eir {
+      type uint64;
+      units "bps";
+      description
+        "Excess Information Rate, i.e., excess frame delivery
+         allowed not subject to SLA. The traffic rate can be
+         limited by EIR.";
+    }
+    leaf ebs {
+      type uint64;
+      units "bytes";
+      description
+        "Excess Burst Size. The bandwidth available for burst
+         traffic from the EBS is subject to the amount of
+         bandwidth that is accumulated during periods when
+         traffic allocated by the EIR policy is not used.";
+    }
+    leaf pir {
+      type uint64;
+      units "bps";
+      description
+        "Peak Information Rate, i.e., maximum frame delivery
+         allowed. It is equal to or less than sum of CIR and EIR.";
+    }
+    leaf pbs {
+      type uint64;
+      units "bytes";
+      description
+        "Peak Burst Size.";
+    }
+  }
+
+  grouping ns-rate-limit {
+    description
+      "The rate limits grouping.";
+    container incoming-rate-limits {
+      description
+        "Container for the asymmetric traffic control.";
+      uses bw-rate-limits;
+    }
+    container outgoing-rate-limits {
+      description
+        "The rate-limit imposed on outgoing traffic.";
+      uses bw-rate-limits;
+    }
+  }
+
+  grouping endpoint {
+    description
+      "IETF Network Slice endpoint related information";
+    leaf ep-id {
+      type string;
+      description
+        "Unique identifier for the referred IETF Network
+         Slice endpoint.";
+    }
+    leaf ep-description {
+      type string;
+      description
+        "Give more description of the Network Slice endpoint.";
+    }
+    uses geolocation-container;
+    leaf node-id {
+      type string;
+      description
+        "Uniquely identifies an edge node within the IETF slice
+         network.";
+    }
+    leaf ep-ip {
+      type inet:ip-address;
+      description
+        "The IP address of the endpoint.";
+    }
+    uses ns-match-criteria;
+    uses ep-peering;
+    uses ep-network-access-points;
+    uses ns-rate-limit;
+    /* Per NSE rate limits */
+    uses status-params;
+    uses ep-monitoring-metrics;
+  }
+
+  //ns-endpoint
+
+  grouping ns-connection {
+    description
+      "The network slice connection grouping.";
+    list ns-connection {
+      key "ns-connection-id";
+      description
+        "List of Network Slice connections.";
+      leaf ns-connection-id {
+        type uint32;
+        description
+          "The Network Slice connection identifier.";
+      }
+      leaf ns-connectivity-type {
+        type identityref {
+          base ns-connectivity-type;
+        }
+        default "point-to-point";
+        description
+          "Network Slice connection construct type.";
+      }
+      leaf-list src-nse {
+        type leafref {
+          path "/network-slices/network-slice"
+             + "/ns-endpoints/ns-endpoint/ep-id";
+        }
+        description
+          "reference to source Network Slice endpoint.";
+      }
+      leaf-list dest-nse {
+        type leafref {
+          path "/network-slices/network-slice"
+             + "/ns-endpoints/ns-endpoint/ep-id";
+        }
+        description
+          "reference to source Network Slice endpoint.";
+      }
+      uses ns-slo-sle-policy;
+      /* Per connection ns-slo-sle-policy overrides
+       * the per network slice ns-slo-sle-policy.
+       */
+      container ns-connection-monitoring {
+        config false;
+        description
+          "SLO status Per NS connection.";
+        uses ns-connection-monitoring-metrics;
+      }
+    }
+  }
+
+  //ns-connection
+
+  grouping ns-connection-group {
+    description
+      "The Network Slice connection group is described in this
+       container.";
+    leaf ns-connection-group-id {
+      type string;
+      description
+        "The Network Slice connection group identifier.";
+    }
+    uses ns-slo-sle-policy;
+    uses ns-connection;
+    /* Per connection ns-slo-sle-policy overrides
+     * the per network slice ns-slo-sle-policy.
+     */
+    container ns-connection-group-monitoring {
+      config false;
+      description
+        "SLO status Per NS connection.";
+      uses ns-connection-monitoring-metrics;
+    }
+  }
+
+  //ns-connection-group
+
+  grouping slice-template {
+    description
+      "Grouping for slice-templates.";
+    container ns-slo-sle-templates {
+      description
+        "Contains a set of network slice templates to
+         reference in the IETF network slice.";
+      list ns-slo-sle-template {
+        key "id";
+        leaf id {
+          type string;
+          description
+            "Identification of the Service Level Objective (SLO)
+             and Service Level Expectation (SLE) template to be used.
+             Local administration meaning.";
+        }
+        leaf template-description {
+          type string;
+          description
+            "Description of the SLO &amp; SLE policy template.";
+        }
+        description
+          "List for SLO and SLE template identifiers.";
+      }
+    }
+  }
+
+  /* Configuration data nodes */
+
+  grouping ns-slo-sle-policy {
+    description
+      "Network Slice policy grouping.";
+    choice ns-slo-sle-policy {
+      description
+        "Choice for SLO and SLE policy template.
+         Can be standard template or customized template.";
+      case standard {
+        description
+          "Standard SLO template.";
+        leaf slo-sle-template {
+          type leafref {
+            path "/network-slices"
+               + "/ns-slo-sle-templates/ns-slo-sle-template/id";
+          }
+          description
+            "Standard SLO and SLE template to be used.";
+        }
+      }
+      case custom {
+        description
+          "Customized SLO template.";
+        container slo-sle-policy {
+          description
+            "Contains the SLO policy.";
+          leaf policy-description {
+            type string;
+            description
+              "Description of the SLO policy.";
+          }
+          uses ns-metric-bounds;
+          uses ns-sles;
+        }
+      }
+    }
+  }
+
+  container network-slices {
+    description
+      "Containes a list of IETF network slice";
+    uses slice-template;
+    list network-slice {
+      key "ns-id";
+      description
+        "A network-slice is identified by a ns-id.";
+      leaf ns-id {
+        type string;
+        description
+          "A unique network-slice identifier across an IETF NSC.";
+      }
+      leaf ns-description {
+        type string;
+        description
+          "Give more description of the network slice.";
+      }
+      container ns-tags {
+        description
+          "Container for the list of IETF Network Slice tags.";
+        list ns-tag {
+          key "index";
+          description
+            "IETF Network Slice tag list.";
+          leaf index {
+            type uint32;
+            description
+              "The entry index.";
+          }
+          leaf ns-tag-type {
+            type identityref {
+              base ns-tag-type;
+            }
+            description
+              "The IETF Network Slice tag type.";
+          }
+          leaf ns-tag-value {
+            type string;
+            description
+              "The IETF Network Slice tag value.";
+          }
+        }
+      }
+      uses ns-slo-sle-policy;
+      uses status-params;
+      container ns-endpoints {
+        description
+          "NS Endpoints.";
+        list ns-endpoint {
+          key "ep-id";
+          uses endpoint;
+          description
+            "List of endpoints in this slice.";
+        }
+      }
+      container ns-connection-groups {
+        description
+          "Contains NS connections group.";
+        list ns-connection-group {
+          key "ns-connection-group-id";
+          description
+            "List of Network Slice connections.";
+          uses ns-connection-group;
+        }
+      }
+    }
+    //ietf-network-slice list
+  }
+}
diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-network-topology@2018-02-26.yang b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-network-topology@2018-02-26.yang
new file mode 100644
index 0000000000000000000000000000000000000000..1ec944d791db1da1b8236c6069f10d65b1b6f97f
--- /dev/null
+++ b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-network-topology@2018-02-26.yang
@@ -0,0 +1,294 @@
+module ietf-network-topology {
+  yang-version 1.1;
+  namespace "urn:ietf:params:xml:ns:yang:ietf-network-topology";
+  prefix nt;
+
+  import ietf-inet-types {
+    prefix inet;
+    reference
+      "RFC 6991: Common YANG Data Types";
+  }
+  import ietf-network {
+    prefix nw;
+    reference
+      "RFC 8345: A YANG Data Model for Network Topologies";
+  }
+
+  organization
+    "IETF I2RS (Interface to the Routing System) Working Group";
+
+  contact
+    "WG Web:    <https://datatracker.ietf.org/wg/i2rs/>
+     WG List:   <mailto:i2rs@ietf.org>
+
+     Editor:    Alexander Clemm
+                <mailto:ludwig@clemm.org>
+
+     Editor:    Jan Medved
+                <mailto:jmedved@cisco.com>
+
+     Editor:    Robert Varga
+                <mailto:robert.varga@pantheon.tech>
+
+     Editor:    Nitin Bahadur
+                <mailto:nitin_bahadur@yahoo.com>
+
+     Editor:    Hariharan Ananthakrishnan
+                <mailto:hari@packetdesign.com>
+
+     Editor:    Xufeng Liu
+                <mailto:xufeng.liu.ietf@gmail.com>";
+
+  description
+    "This module defines a common base model for a network topology,
+     augmenting the base network data model with links to connect
+     nodes, as well as termination points to terminate links
+     on nodes.
+
+     Copyright (c) 2018 IETF Trust and the persons identified as
+     authors of the code.  All rights reserved.
+
+     Redistribution and use in source and binary forms, with or
+     without modification, is permitted pursuant to, and subject
+     to the license terms contained in, the Simplified BSD License
+     set forth in Section 4.c of the IETF Trust's Legal Provisions
+     Relating to IETF Documents
+     (https://trustee.ietf.org/license-info).
+
+     This version of this YANG module is part of RFC 8345;
+     see the RFC itself for full legal notices.";
+
+  revision 2018-02-26 {
+    description
+      "Initial revision.";
+    reference
+      "RFC 8345: A YANG Data Model for Network Topologies";
+  }
+
+  typedef link-id {
+    type inet:uri;
+    description
+      "An identifier for a link in a topology.  The precise
+       structure of the link-id will be up to the implementation.
+       The identifier SHOULD be chosen such that the same link in a
+       real network topology will always be identified through the
+       same identifier, even if the data model is instantiated in
+       separate datastores.  An implementation MAY choose to capture
+       semantics in the identifier -- for example, to indicate the
+       type of link and/or the type of topology of which the link is
+       a part.";
+  }
+
+  typedef tp-id {
+    type inet:uri;
+    description
+      "An identifier for termination points on a node.  The precise
+       structure of the tp-id will be up to the implementation.
+       The identifier SHOULD be chosen such that the same termination
+       point in a real network topology will always be identified
+       through the same identifier, even if the data model is
+       instantiated in separate datastores.  An implementation MAY
+       choose to capture semantics in the identifier -- for example,
+       to indicate the type of termination point and/or the type of
+       node that contains the termination point.";
+  }
+
+  grouping link-ref {
+    description
+      "This grouping can be used to reference a link in a specific
+       network.  Although it is not used in this module, it is
+       defined here for the convenience of augmenting modules.";
+    leaf link-ref {
+      type leafref {
+        path "/nw:networks/nw:network[nw:network-id=current()/../"+
+          "network-ref]/nt:link/nt:link-id";
+        require-instance false;
+      }
+      description
+        "A type for an absolute reference to a link instance.
+         (This type should not be used for relative references.
+         In such a case, a relative path should be used instead.)";
+    }
+    uses nw:network-ref;
+  }
+
+  grouping tp-ref {
+    description
+      "This grouping can be used to reference a termination point
+       in a specific node.  Although it is not used in this module,
+       it is defined here for the convenience of augmenting
+       modules.";
+    leaf tp-ref {
+      type leafref {
+        path "/nw:networks/nw:network[nw:network-id=current()/../"+
+          "network-ref]/nw:node[nw:node-id=current()/../"+
+          "node-ref]/nt:termination-point/nt:tp-id";
+        require-instance false;
+      }
+      description
+        "A type for an absolute reference to a termination point.
+         (This type should not be used for relative references.
+         In such a case, a relative path should be used instead.)";
+    }
+    uses nw:node-ref;
+  }
+
+  augment "/nw:networks/nw:network" {
+    description
+      "Add links to the network data model.";
+    list link {
+      key "link-id";
+      description
+        "A network link connects a local (source) node and
+         a remote (destination) node via a set of the respective
+         node's termination points.  It is possible to have several
+         links between the same source and destination nodes.
+         Likewise, a link could potentially be re-homed between
+         termination points.  Therefore, in order to ensure that we
+         would always know to distinguish between links, every link
+         is identified by a dedicated link identifier.  Note that a
+         link models a point-to-point link, not a multipoint link.";
+      leaf link-id {
+        type link-id;
+        description
+          "The identifier of a link in the topology.
+           A link is specific to a topology to which it belongs.";
+      }
+      container source {
+        description
+          "This container holds the logical source of a particular
+           link.";
+        leaf source-node {
+          type leafref {
+            path "../../../nw:node/nw:node-id";
+            require-instance false;
+          }
+          description
+            "Source node identifier.  Must be in the same topology.";
+        }
+        leaf source-tp {
+          type leafref {
+            path "../../../nw:node[nw:node-id=current()/../"+
+              "source-node]/termination-point/tp-id";
+            require-instance false;
+          }
+          description
+            "This termination point is located within the source node
+             and terminates the link.";
+        }
+      }
+
+      container destination {
+        description
+          "This container holds the logical destination of a
+           particular link.";
+        leaf dest-node {
+          type leafref {
+            path "../../../nw:node/nw:node-id";
+          require-instance false;
+          }
+          description
+            "Destination node identifier.  Must be in the same
+             network.";
+        }
+        leaf dest-tp {
+          type leafref {
+            path "../../../nw:node[nw:node-id=current()/../"+
+              "dest-node]/termination-point/tp-id";
+            require-instance false;
+          }
+          description
+            "This termination point is located within the
+             destination node and terminates the link.";
+        }
+      }
+      list supporting-link {
+        key "network-ref link-ref";
+        description
+          "Identifies the link or links on which this link depends.";
+        leaf network-ref {
+          type leafref {
+            path "../../../nw:supporting-network/nw:network-ref";
+          require-instance false;
+          }
+          description
+            "This leaf identifies in which underlay topology
+             the supporting link is present.";
+        }
+
+        leaf link-ref {
+          type leafref {
+            path "/nw:networks/nw:network[nw:network-id=current()/"+
+              "../network-ref]/link/link-id";
+            require-instance false;
+          }
+          description
+            "This leaf identifies a link that is a part
+             of this link's underlay.  Reference loops in which
+             a link identifies itself as its underlay, either
+             directly or transitively, are not allowed.";
+        }
+      }
+    }
+  }
+  augment "/nw:networks/nw:network/nw:node" {
+    description
+      "Augments termination points that terminate links.
+       Termination points can ultimately be mapped to interfaces.";
+    list termination-point {
+      key "tp-id";
+      description
+        "A termination point can terminate a link.
+         Depending on the type of topology, a termination point
+         could, for example, refer to a port or an interface.";
+      leaf tp-id {
+        type tp-id;
+        description
+          "Termination point identifier.";
+      }
+      list supporting-termination-point {
+        key "network-ref node-ref tp-ref";
+        description
+          "This list identifies any termination points on which a
+           given termination point depends or onto which it maps.
+           Those termination points will themselves be contained
+           in a supporting node.  This dependency information can be
+           inferred from the dependencies between links.  Therefore,
+           this item is not separately configurable.  Hence, no
+           corresponding constraint needs to be articulated.
+           The corresponding information is simply provided by the
+           implementing system.";
+
+        leaf network-ref {
+          type leafref {
+            path "../../../nw:supporting-node/nw:network-ref";
+          require-instance false;
+          }
+          description
+            "This leaf identifies in which topology the
+             supporting termination point is present.";
+        }
+        leaf node-ref {
+          type leafref {
+            path "../../../nw:supporting-node/nw:node-ref";
+          require-instance false;
+          }
+          description
+            "This leaf identifies in which node the supporting
+             termination point is present.";
+        }
+        leaf tp-ref {
+          type leafref {
+            path "/nw:networks/nw:network[nw:network-id=current()/"+
+              "../network-ref]/nw:node[nw:node-id=current()/../"+
+              "node-ref]/termination-point/tp-id";
+            require-instance false;
+          }
+          description
+            "Reference to the underlay node (the underlay node must
+             be in a different topology).";
+        }
+      }
+    }
+  }
+}
diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-network@2018-02-26.yang b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-network@2018-02-26.yang
new file mode 100644
index 0000000000000000000000000000000000000000..6a03d7e41614cc8dc017cfb4d5aacfb4ca60bc2c
--- /dev/null
+++ b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-network@2018-02-26.yang
@@ -0,0 +1,192 @@
+module ietf-network {
+  yang-version 1.1;
+  namespace "urn:ietf:params:xml:ns:yang:ietf-network";
+  prefix nw;
+
+  import ietf-inet-types {
+    prefix inet;
+    reference
+      "RFC 6991: Common YANG Data Types";
+  }
+
+  organization
+    "IETF I2RS (Interface to the Routing System) Working Group";
+
+  contact
+    "WG Web:    <https://datatracker.ietf.org/wg/i2rs/>
+     WG List:   <mailto:i2rs@ietf.org>
+
+     Editor:    Alexander Clemm
+                <mailto:ludwig@clemm.org>
+
+     Editor:    Jan Medved
+                <mailto:jmedved@cisco.com>
+
+     Editor:    Robert Varga
+                <mailto:robert.varga@pantheon.tech>
+
+     Editor:    Nitin Bahadur
+                <mailto:nitin_bahadur@yahoo.com>
+
+     Editor:    Hariharan Ananthakrishnan
+                <mailto:hari@packetdesign.com>
+
+     Editor:    Xufeng Liu
+                <mailto:xufeng.liu.ietf@gmail.com>";
+  description
+    "This module defines a common base data model for a collection
+     of nodes in a network.  Node definitions are further used
+     in network topologies and inventories.
+
+     Copyright (c) 2018 IETF Trust and the persons identified as
+     authors of the code.  All rights reserved.
+
+     Redistribution and use in source and binary forms, with or
+     without modification, is permitted pursuant to, and subject
+     to the license terms contained in, the Simplified BSD License
+     set forth in Section 4.c of the IETF Trust's Legal Provisions
+     Relating to IETF Documents
+     (https://trustee.ietf.org/license-info).
+
+     This version of this YANG module is part of RFC 8345;
+     see the RFC itself for full legal notices.";
+
+  revision 2018-02-26 {
+    description
+      "Initial revision.";
+    reference
+      "RFC 8345: A YANG Data Model for Network Topologies";
+  }
+
+  typedef node-id {
+    type inet:uri;
+    description
+      "Identifier for a node.  The precise structure of the node-id
+       will be up to the implementation.  For example, some
+       implementations MAY pick a URI that includes the network-id
+       as part of the path.  The identifier SHOULD be chosen
+       such that the same node in a real network topology will
+       always be identified through the same identifier, even if
+       the data model is instantiated in separate datastores.  An
+       implementation MAY choose to capture semantics in the
+       identifier -- for example, to indicate the type of node.";
+  }
+
+  typedef network-id {
+    type inet:uri;
+    description
+      "Identifier for a network.  The precise structure of the
+       network-id will be up to the implementation.  The identifier
+       SHOULD be chosen such that the same network will always be
+       identified through the same identifier, even if the data model
+       is instantiated in separate datastores.  An implementation MAY
+       choose to capture semantics in the identifier -- for example,
+       to indicate the type of network.";
+  }
+
+  grouping network-ref {
+    description
+      "Contains the information necessary to reference a network --
+       for example, an underlay network.";
+    leaf network-ref {
+      type leafref {
+        path "/nw:networks/nw:network/nw:network-id";
+      require-instance false;
+      }
+      description
+        "Used to reference a network -- for example, an underlay
+         network.";
+    }
+  }
+
+  grouping node-ref {
+    description
+      "Contains the information necessary to reference a node.";
+    leaf node-ref {
+      type leafref {
+        path "/nw:networks/nw:network[nw:network-id=current()/../"+
+          "network-ref]/nw:node/nw:node-id";
+        require-instance false;
+      }
+      description
+        "Used to reference a node.
+         Nodes are identified relative to the network that
+         contains them.";
+    }
+    uses network-ref;
+  }
+
+  container networks {
+    description
+      "Serves as a top-level container for a list of networks.";
+    list network {
+      key "network-id";
+      description
+        "Describes a network.
+         A network typically contains an inventory of nodes,
+         topological information (augmented through the
+         network-topology data model), and layering information.";
+      leaf network-id {
+        type network-id;
+        description
+          "Identifies a network.";
+      }
+      container network-types {
+        description
+          "Serves as an augmentation target.
+           The network type is indicated through corresponding
+           presence containers augmented into this container.";
+      }
+      list supporting-network {
+        key "network-ref";
+        description
+          "An underlay network, used to represent layered network
+           topologies.";
+        leaf network-ref {
+          type leafref {
+            path "/nw:networks/nw:network/nw:network-id";
+          require-instance false;
+          }
+          description
+            "References the underlay network.";
+        }
+      }
+
+      list node {
+        key "node-id";
+        description
+          "The inventory of nodes of this network.";
+        leaf node-id {
+          type node-id;
+          description
+            "Uniquely identifies a node within the containing
+             network.";
+        }
+        list supporting-node {
+          key "network-ref node-ref";
+          description
+            "Represents another node that is in an underlay network
+             and that supports this node.  Used to represent layering
+             structure.";
+          leaf network-ref {
+            type leafref {
+              path "../../../nw:supporting-network/nw:network-ref";
+            require-instance false;
+            }
+            description
+              "References the underlay network of which the
+               underlay node is a part.";
+          }
+          leaf node-ref {
+            type leafref {
+              path "/nw:networks/nw:network/nw:node/nw:node-id";
+            require-instance false;
+            }
+            description
+              "References the underlay node itself.";
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-packet-fields@2019-03-04.yang b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-packet-fields@2019-03-04.yang
new file mode 100644
index 0000000000000000000000000000000000000000..2fb797bd87bf4ed825f83ec788df707b94c5f68b
--- /dev/null
+++ b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-packet-fields@2019-03-04.yang
@@ -0,0 +1,576 @@
+module ietf-packet-fields {
+  yang-version 1.1;
+  namespace "urn:ietf:params:xml:ns:yang:ietf-packet-fields";
+  prefix packet-fields;
+
+  import ietf-inet-types {
+    prefix inet;
+    reference
+      "RFC 6991 - Common YANG Data Types.";
+  }
+
+  import ietf-yang-types {
+    prefix yang;
+    reference
+      "RFC 6991 - Common YANG Data Types.";
+  }
+
+  import ietf-ethertypes {
+    prefix eth;
+    reference
+      "RFC 8519 - YANG Data Model for Network Access Control
+                  Lists (ACLs).";
+  }
+
+  organization
+    "IETF NETMOD (Network Modeling) Working Group.";
+
+  contact
+    "WG Web:  <https://datatracker.ietf.org/wg/netmod/>
+     WG List: netmod@ietf.org
+
+     Editor: Mahesh Jethanandani
+             mjethanandani@gmail.com
+     Editor: Lisa Huang
+             huangyi_99@yahoo.com
+     Editor: Sonal Agarwal
+             sagarwal12@gmail.com
+     Editor: Dana Blair
+             dana@blairhome.com";
+
+  description
+    "This YANG module defines groupings that are used by
+     the ietf-access-control-list YANG module.  Their usage
+     is not limited to ietf-access-control-list and can be
+     used anywhere as applicable.
+
+     Copyright (c) 2019 IETF Trust and the persons identified as
+     the document authors.  All rights reserved.
+
+     Redistribution and use in source and binary forms, with or
+     without modification, is permitted pursuant to, and subject
+     to the license terms contained in, the Simplified BSD
+     License set forth in Section 4.c of the IETF Trust's Legal
+     Provisions Relating to IETF Documents
+     (http://trustee.ietf.org/license-info).
+
+     This version of this YANG module is part of RFC 8519; see
+     the RFC itself for full legal notices.";
+
+  revision 2019-03-04 {
+    description
+      "Initial version.";
+    reference
+      "RFC 8519: YANG Data Model for Network Access Control
+                 Lists (ACLs).";
+  }
+
+  /*
+   * Typedefs
+   */
+  typedef operator {
+    type enumeration {
+      enum lte {
+        description
+          "Less than or equal to.";
+      }
+      enum gte {
+        description
+          "Greater than or equal to.";
+      }
+      enum eq {
+        description
+          "Equal to.";
+      }
+      enum neq {
+        description
+          "Not equal to.";
+      }
+    }
+    description
+      "The source and destination port range definitions
+       can be further qualified using an operator.  An
+       operator is needed only if the lower-port is specified
+       and the upper-port is not specified.  The operator
+       therefore further qualifies the lower-port only.";
+  }
+
+  /*
+   * Groupings
+   */
+  grouping port-range-or-operator {
+    choice port-range-or-operator {
+      case range {
+        leaf lower-port {
+          type inet:port-number;
+          must '. <= ../upper-port' {
+            error-message
+              "The lower-port must be less than or equal to
+               the upper-port.";
+          }
+          mandatory true;
+          description
+            "Lower boundary for a port.";
+        }
+        leaf upper-port {
+          type inet:port-number;
+          mandatory true;
+          description
+            "Upper boundary for a port.";
+        }
+      }
+      case operator {
+        leaf operator {
+          type operator;
+          default "eq";
+          description
+            "Operator to be applied on the port below.";
+        }
+        leaf port {
+          type inet:port-number;
+          mandatory true;
+          description
+            "Port number along with the operator on which to
+             match.";
+        }
+      }
+      description
+        "Choice of specifying a port range or a single
+         port along with an operator.";
+    }
+    description
+      "Grouping for port definitions in the form of a
+       choice statement.";
+  }
+
+  grouping acl-ip-header-fields {
+    description
+      "IP header fields common to IPv4 and IPv6";
+    reference
+      "RFC 791: Internet Protocol.";
+
+    leaf dscp {
+      type inet:dscp;
+      description
+        "Differentiated Services Code Point.";
+      reference
+        "RFC 2474: Definition of the Differentiated Services
+                   Field (DS Field) in the IPv4 and IPv6
+                   Headers.";
+    }
+
+    leaf ecn {
+      type uint8 {
+        range "0..3";
+      }
+      description
+        "Explicit Congestion Notification.";
+      reference
+        "RFC 3168: The Addition of Explicit Congestion
+                   Notification (ECN) to IP.";
+    }
+
+    leaf length {
+      type uint16;
+      description
+        "In the IPv4 header field, this field is known as the Total
+         Length.  Total Length is the length of the datagram, measured
+         in octets, including internet header and data.
+
+         In the IPv6 header field, this field is known as the Payload
+         Length, which is the length of the IPv6 payload, i.e., the rest
+         of the packet following the IPv6 header, in octets.";
+      reference
+        "RFC 791: Internet Protocol
+         RFC 8200: Internet Protocol, Version 6 (IPv6) Specification.";
+    }
+    leaf ttl {
+      type uint8;
+      description
+        "This field indicates the maximum time the datagram is allowed
+         to remain in the internet system.  If this field contains the
+         value zero, then the datagram must be dropped.
+
+         In IPv6, this field is known as the Hop Limit.";
+      reference
+        "RFC 791: Internet Protocol
+         RFC 8200: Internet Protocol, Version 6 (IPv6) Specification.";
+    }
+    leaf protocol {
+      type uint8;
+      description
+        "Internet Protocol number.  Refers to the protocol of the
+         payload.  In IPv6, this field is known as 'next-header',
+         and if extension headers are present, the protocol is
+         present in the 'upper-layer' header.";
+      reference
+        "RFC 791: Internet Protocol
+         RFC 8200: Internet Protocol, Version 6 (IPv6) Specification.";
+    }
+  }
+
+  grouping acl-ipv4-header-fields {
+    description
+      "Fields in the IPv4 header.";
+    leaf ihl {
+      type uint8 {
+        range "5..60";
+      }
+      description
+        "In an IPv4 header field, the Internet Header Length (IHL) is
+         the length of the internet header in 32-bit words and
+         thus points to the beginning of the data.  Note that the
+         minimum value for a correct header is 5.";
+    }
+    leaf flags {
+      type bits {
+        bit reserved {
+          position 0;
+          description
+            "Reserved.  Must be zero.";
+        }
+        bit fragment {
+          position 1;
+          description
+            "Setting the value to 0 indicates may fragment, while
+             setting the value to 1 indicates do not fragment.";
+        }
+        bit more {
+          position 2;
+          description
+            "Setting the value to 0 indicates this is the last fragment,
+             and setting the value to 1 indicates more fragments are
+             coming.";
+        }
+      }
+      description
+        "Bit definitions for the Flags field in the IPv4 header.";
+    }
+    leaf offset {
+      type uint16 {
+        range "20..65535";
+      }
+      description
+        "The fragment offset is measured in units of 8 octets (64 bits).
+         The first fragment has offset zero.  The length is 13 bits";
+    }
+    leaf identification {
+      type uint16;
+      description
+        "An identifying value assigned by the sender to aid in
+         assembling the fragments of a datagram.";
+    }
+
+    choice destination-network {
+      case destination-ipv4-network {
+        leaf destination-ipv4-network {
+          type inet:ipv4-prefix;
+          description
+            "Destination IPv4 address prefix.";
+        }
+      }
+      description
+        "Choice of specifying a destination IPv4 address or
+         referring to a group of IPv4 destination addresses.";
+    }
+
+    choice source-network {
+      case source-ipv4-network {
+        leaf source-ipv4-network {
+          type inet:ipv4-prefix;
+          description
+            "Source IPv4 address prefix.";
+        }
+      }
+      description
+        "Choice of specifying a source IPv4 address or
+         referring to a group of IPv4 source addresses.";
+    }
+  }
+
+  grouping acl-ipv6-header-fields {
+    description
+      "Fields in the IPv6 header.";
+
+    choice destination-network {
+      case destination-ipv6-network {
+        leaf destination-ipv6-network {
+          type inet:ipv6-prefix;
+          description
+            "Destination IPv6 address prefix.";
+        }
+      }
+      description
+        "Choice of specifying a destination IPv6 address
+         or referring to a group of IPv6 destination
+         addresses.";
+    }
+
+    choice source-network {
+      case source-ipv6-network {
+        leaf source-ipv6-network {
+          type inet:ipv6-prefix;
+          description
+            "Source IPv6 address prefix.";
+        }
+      }
+      description
+        "Choice of specifying a source IPv6 address or
+         referring to a group of IPv6 source addresses.";
+    }
+
+    leaf flow-label {
+      type inet:ipv6-flow-label;
+      description
+        "IPv6 Flow label.";
+    }
+    reference
+      "RFC 4291: IP Version 6 Addressing Architecture
+       RFC 4007: IPv6 Scoped Address Architecture
+       RFC 5952: A Recommendation for IPv6 Address Text
+                 Representation.";
+  }
+
+  grouping acl-eth-header-fields {
+    description
+      "Fields in the Ethernet header.";
+    leaf destination-mac-address {
+      type yang:mac-address;
+      description
+        "Destination IEEE 802 Media Access Control (MAC)
+         address.";
+    }
+    leaf destination-mac-address-mask {
+      type yang:mac-address;
+      description
+        "Destination IEEE 802 MAC address mask.";
+    }
+    leaf source-mac-address {
+      type yang:mac-address;
+      description
+        "Source IEEE 802 MAC address.";
+    }
+    leaf source-mac-address-mask {
+      type yang:mac-address;
+      description
+        "Source IEEE 802 MAC address mask.";
+    }
+    leaf ethertype {
+      type eth:ethertype;
+      description
+        "The Ethernet Type (or Length) value represented
+         in the canonical order defined by IEEE 802.
+         The canonical representation uses lowercase
+         characters.";
+      reference
+        "IEEE 802-2014, Clause 9.2.";
+    }
+    reference
+      "IEEE 802: IEEE Standard for Local and Metropolitan
+       Area Networks: Overview and Architecture.";
+  }
+
+  grouping acl-tcp-header-fields {
+    description
+      "Collection of TCP header fields that can be used to
+       set up a match filter.";
+    leaf sequence-number {
+      type uint32;
+      description
+        "Sequence number that appears in the packet.";
+    }
+    leaf acknowledgement-number {
+      type uint32;
+      description
+        "The acknowledgement number that appears in the
+         packet.";
+    }
+    leaf data-offset {
+      type uint8 {
+        range "5..15";
+      }
+      description
+        "Specifies the size of the TCP header in 32-bit
+         words.  The minimum size header is 5 words and
+         the maximum is 15 words; thus, this gives a
+         minimum size of 20 bytes and a maximum of 60
+         bytes, allowing for up to 40 bytes of options
+         in the header.";
+    }
+    leaf reserved {
+      type uint8;
+      description
+        "Reserved for future use.";
+    }
+    leaf flags {
+      type bits {
+        bit cwr {
+          position 1;
+          description
+            "The Congestion Window Reduced (CWR) flag is set
+             by the sending host to indicate that it received
+             a TCP segment with the ECN-Echo (ECE) flag set
+             and had responded in the congestion control
+             mechanism.";
+          reference
+            "RFC 3168: The Addition of Explicit Congestion
+                       Notification (ECN) to IP.";
+        }
+        bit ece {
+          position 2;
+          description
+            "ECN-Echo has a dual role, depending on the value
+             of the SYN flag.  It indicates the following: if
+             the SYN flag is set (1), the TCP peer is ECN
+             capable, and if the SYN flag is clear (0), a packet
+             with the Congestion Experienced flag set (ECN=11)
+             in the IP header was received during normal
+             transmission (added to the header by RFC 3168).
+             This serves as an indication of network congestion
+             (or impending congestion) to the TCP sender.";
+          reference
+            "RFC 3168: The Addition of Explicit Congestion
+                       Notification (ECN) to IP.";
+        }
+        bit urg {
+          position 3;
+          description
+            "Indicates that the Urgent Pointer field is significant.";
+        }
+        bit ack {
+          position 4;
+          description
+            "Indicates that the Acknowledgement field is significant.
+             All packets after the initial SYN packet sent by the
+             client should have this flag set.";
+        }
+        bit psh {
+          position 5;
+          description
+            "Push function.  Asks to push the buffered data to the
+             receiving application.";
+        }
+        bit rst {
+          position 6;
+          description
+            "Reset the connection.";
+        }
+        bit syn {
+          position 7;
+          description
+            "Synchronize sequence numbers.  Only the first packet
+             sent from each end should have this flag set.  Some
+             other flags and fields change meaning based on this
+             flag, and some are only valid for when it is set,
+             and others when it is clear.";
+        }
+        bit fin {
+          position 8;
+          description
+            "Last package from the sender.";
+        }
+      }
+      description
+        "Also known as Control Bits.  Contains nine 1-bit flags.";
+      reference
+        "RFC 793: Transmission Control Protocol.";
+    }
+    leaf window-size {
+      type uint16;
+      units "bytes";
+      description
+        "The size of the receive window, which specifies
+         the number of window size units beyond the segment
+         identified by the sequence number in the Acknowledgement
+         field that the sender of this segment is currently
+         willing to receive.";
+    }
+    leaf urgent-pointer {
+      type uint16;
+      description
+        "This field is an offset from the sequence number
+         indicating the last urgent data byte.";
+    }
+    leaf options {
+      type binary {
+        length "1..40";
+      }
+      description
+        "The length of this field is determined by the
+         Data Offset field.  Options have up to three
+         fields: Option-Kind (1 byte), Option-Length
+         (1 byte), and Option-Data (variable).  The Option-Kind
+         field indicates the type of option and is the
+         only field that is not optional.  Depending on
+         what kind of option we are dealing with,
+         the next two fields may be set: the Option-Length
+         field indicates the total length of the option,
+         and the Option-Data field contains the value of
+         the option, if applicable.";
+    }
+  }
+
+  grouping acl-udp-header-fields {
+    description
+      "Collection of UDP header fields that can be used
+       to set up a match filter.";
+    leaf length {
+      type uint16;
+      description
+        "A field that specifies the length in bytes of
+         the UDP header and UDP data.  The minimum
+         length is 8 bytes because that is the length of
+         the header.  The field size sets a theoretical
+         limit of 65,535 bytes (8-byte header plus 65,527
+         bytes of data) for a UDP datagram.  However, the
+         actual limit for the data length, which is
+         imposed by the underlying IPv4 protocol, is
+         65,507 bytes (65,535 minus 8-byte UDP header
+         minus 20-byte IP header).
+
+         In IPv6 jumbograms, it is possible to have
+         UDP packets of a size greater than 65,535 bytes.
+         RFC 2675 specifies that the Length field is set
+         to zero if the length of the UDP header plus
+         UDP data is greater than 65,535.";
+    }
+  }
+
+  grouping acl-icmp-header-fields {
+    description
+      "Collection of ICMP header fields that can be
+       used to set up a match filter.";
+    leaf type {
+      type uint8;
+      description
+        "Also known as control messages.";
+      reference
+        "RFC 792: Internet Control Message Protocol
+         RFC 4443: Internet Control Message Protocol (ICMPv6)
+                   for Internet Protocol Version 6 (IPv6)
+                   Specification.";
+    }
+    leaf code {
+      type uint8;
+      description
+        "ICMP subtype.  Also known as control messages.";
+      reference
+        "RFC 792: Internet Control Message Protocol
+         RFC 4443: Internet Control Message Protocol (ICMPv6)
+                   for Internet Protocol Version 6 (IPv6)
+                   Specification.";
+    }
+    leaf rest-of-header {
+      type binary;
+      description
+        "Unbounded in length, the contents vary based on the
+         ICMP type and code.  Also referred to as 'Message Body'
+         in ICMPv6.";
+      reference
+        "RFC 792: Internet Control Message Protocol
+         RFC 4443: Internet Control Message Protocol (ICMPv6)
+                   for Internet Protocol Version 6 (IPv6)
+                   Specification.";
+    }
+  }
+}
diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-routing-types@2017-12-04.yang b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-routing-types@2017-12-04.yang
new file mode 100644
index 0000000000000000000000000000000000000000..24319c155fb104e20bee79e5b257317b01323197
--- /dev/null
+++ b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-routing-types@2017-12-04.yang
@@ -0,0 +1,771 @@
+module ietf-routing-types {
+  namespace "urn:ietf:params:xml:ns:yang:ietf-routing-types";
+  prefix rt-types;
+
+  import ietf-yang-types {
+    prefix yang;
+  }
+  import ietf-inet-types {
+    prefix inet;
+  }
+
+  organization
+    "IETF RTGWG - Routing Area Working Group";
+  contact
+    "WG Web:   <https://datatracker.ietf.org/wg/rtgwg/>
+     WG List:  <mailto:rtgwg@ietf.org>
+
+     Editors:  Xufeng Liu
+               <mailto:Xufeng_Liu@jabail.com>
+               Yingzhen Qu
+               <mailto:yingzhen.qu@huawei.com>
+               Acee Lindem
+               <mailto:acee@cisco.com>
+               Christian Hopps
+               <mailto:chopps@chopps.org>
+               Lou Berger
+               <mailto:lberger@labn.com>";
+
+  description
+    "This module contains a collection of YANG data types
+     considered generally useful for routing protocols.
+
+     Copyright (c) 2017 IETF Trust and the persons
+     identified as authors of the code.  All rights reserved.
+
+     Redistribution and use in source and binary forms, with or
+     without modification, is permitted pursuant to, and subject
+     to the license terms contained in, the Simplified BSD License
+     set forth in Section 4.c of the IETF Trust's Legal Provisions
+     Relating to IETF Documents
+     (https://trustee.ietf.org/license-info).
+
+     This version of this YANG module is part of RFC 8294; see
+     the RFC itself for full legal notices.";
+   revision 2017-12-04 {
+     description "Initial revision.";
+     reference
+       "RFC 8294: Common YANG Data Types for the Routing Area.
+        Section 3.";
+  }
+
+  /*** Identities related to MPLS/GMPLS ***/
+
+  identity mpls-label-special-purpose-value {
+    description
+      "Base identity for deriving identities describing
+       special-purpose Multiprotocol Label Switching (MPLS) label
+       values.";
+    reference
+      "RFC 7274: Allocating and Retiring Special-Purpose MPLS
+       Labels.";
+  }
+
+  identity ipv4-explicit-null-label {
+    base mpls-label-special-purpose-value;
+    description
+      "This identity represents the IPv4 Explicit NULL Label.";
+    reference
+      "RFC 3032: MPLS Label Stack Encoding.  Section 2.1.";
+  }
+
+  identity router-alert-label {
+    base mpls-label-special-purpose-value;
+    description
+      "This identity represents the Router Alert Label.";
+    reference
+      "RFC 3032: MPLS Label Stack Encoding.  Section 2.1.";
+  }
+
+  identity ipv6-explicit-null-label {
+    base mpls-label-special-purpose-value;
+    description
+      "This identity represents the IPv6 Explicit NULL Label.";
+    reference
+      "RFC 3032: MPLS Label Stack Encoding.  Section 2.1.";
+  }
+
+  identity implicit-null-label {
+    base mpls-label-special-purpose-value;
+    description
+      "This identity represents the Implicit NULL Label.";
+    reference
+      "RFC 3032: MPLS Label Stack Encoding.  Section 2.1.";
+  }
+
+  identity entropy-label-indicator {
+    base mpls-label-special-purpose-value;
+    description
+      "This identity represents the Entropy Label Indicator.";
+    reference
+      "RFC 6790: The Use of Entropy Labels in MPLS Forwarding.
+       Sections 3 and 10.1.";
+  }
+
+  identity gal-label {
+    base mpls-label-special-purpose-value;
+    description
+      "This identity represents the Generic Associated Channel
+       (G-ACh) Label (GAL).";
+    reference
+      "RFC 5586: MPLS Generic Associated Channel.
+       Sections 4 and 10.";
+  }
+
+  identity oam-alert-label {
+    base mpls-label-special-purpose-value;
+    description
+      "This identity represents the OAM Alert Label.";
+    reference
+      "RFC 3429: Assignment of the 'OAM Alert Label' for
+       Multiprotocol Label Switching Architecture (MPLS)
+       Operation and Maintenance (OAM) Functions.
+       Sections 3 and 6.";
+  }
+
+  identity extension-label {
+    base mpls-label-special-purpose-value;
+    description
+      "This identity represents the Extension Label.";
+    reference
+      "RFC 7274: Allocating and Retiring Special-Purpose MPLS
+       Labels.  Sections 3.1 and 5.";
+  }
+
+  /*** Collection of types related to routing ***/
+
+  typedef router-id {
+    type yang:dotted-quad;
+    description
+      "A 32-bit number in the dotted-quad format assigned to each
+       router.  This number uniquely identifies the router within
+       an Autonomous System.";
+  }
+
+  /*** Collection of types related to VPNs ***/
+
+  typedef route-target {
+    type string {
+      pattern
+        '(0:(6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|'
+      +     '6[0-4][0-9]{3}|'
+      +     '[1-5][0-9]{4}|[1-9][0-9]{0,3}|0):(429496729[0-5]|'
+      +     '42949672[0-8][0-9]|'
+      +     '4294967[01][0-9]{2}|429496[0-6][0-9]{3}|'
+      +     '42949[0-5][0-9]{4}|'
+      +     '4294[0-8][0-9]{5}|429[0-3][0-9]{6}|'
+      +     '42[0-8][0-9]{7}|4[01][0-9]{8}|'
+      +     '[1-3][0-9]{9}|[1-9][0-9]{0,8}|0))|'
+      + '(1:((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|'
+      +     '25[0-5])\.){3}([0-9]|[1-9][0-9]|'
+      +     '1[0-9]{2}|2[0-4][0-9]|25[0-5])):(6553[0-5]|'
+      +     '655[0-2][0-9]|'
+      +     '65[0-4][0-9]{2}|6[0-4][0-9]{3}|'
+      +     '[1-5][0-9]{4}|[1-9][0-9]{0,3}|0))|'
+      + '(2:(429496729[0-5]|42949672[0-8][0-9]|'
+      +     '4294967[01][0-9]{2}|'
+      +     '429496[0-6][0-9]{3}|42949[0-5][0-9]{4}|'
+      +     '4294[0-8][0-9]{5}|'
+      +     '429[0-3][0-9]{6}|42[0-8][0-9]{7}|4[01][0-9]{8}|'
+      +     '[1-3][0-9]{9}|[1-9][0-9]{0,8}|0):'
+      +     '(6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|'
+      +     '6[0-4][0-9]{3}|'
+      +     '[1-5][0-9]{4}|[1-9][0-9]{0,3}|0))|'
+      + '(6(:[a-fA-F0-9]{2}){6})|'
+      + '(([3-57-9a-fA-F]|[1-9a-fA-F][0-9a-fA-F]{1,3}):'
+      +     '[0-9a-fA-F]{1,12})';
+    }
+
+    description
+      "A Route Target is an 8-octet BGP extended community
+       initially identifying a set of sites in a BGP VPN
+       (RFC 4364).  However, it has since taken on a more general
+       role in BGP route filtering.  A Route Target consists of two
+       or three fields: a 2-octet Type field, an administrator
+       field, and, optionally, an assigned number field.
+
+       According to the data formats for types 0, 1, 2, and 6 as
+       defined in RFC 4360, RFC 5668, and RFC 7432, the encoding
+       pattern is defined as:
+
+       0:2-octet-asn:4-octet-number
+       1:4-octet-ipv4addr:2-octet-number
+       2:4-octet-asn:2-octet-number
+       6:6-octet-mac-address
+
+       Additionally, a generic pattern is defined for future
+       Route Target types:
+
+       2-octet-other-hex-number:6-octet-hex-number
+
+       Some valid examples are 0:100:100, 1:1.1.1.1:100,
+       2:1234567890:203, and 6:26:00:08:92:78:00.";
+    reference
+      "RFC 4360: BGP Extended Communities Attribute.
+       RFC 4364: BGP/MPLS IP Virtual Private Networks (VPNs).
+       RFC 5668: 4-Octet AS Specific BGP Extended Community.
+       RFC 7432: BGP MPLS-Based Ethernet VPN.";
+  }
+
+  typedef ipv6-route-target {
+    type string {
+      pattern
+          '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}'
+          + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|'
+          + '(((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.){3}'
+          + '(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])))'
+          + ':'
+          + '(6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|'
+          + '6[0-4][0-9]{3}|'
+          + '[1-5][0-9]{4}|[1-9][0-9]{0,3}|0)';
+      pattern '((([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|'
+          + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?))'
+          + ':'
+          + '(6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|'
+          + '6[0-4][0-9]{3}|'
+          + '[1-5][0-9]{4}|[1-9][0-9]{0,3}|0)';
+    }
+    description
+      "An IPv6 Route Target is a 20-octet BGP IPv6 Address
+       Specific Extended Community serving the same function
+       as a standard 8-octet Route Target, except that it only
+       allows an IPv6 address as the global administrator.
+       The format is <ipv6-address:2-octet-number>.
+
+       Two valid examples are 2001:db8::1:6544 and
+       2001:db8::5eb1:791:6b37:17958.";
+    reference
+      "RFC 5701: IPv6 Address Specific BGP Extended Community
+       Attribute.";
+  }
+
+  typedef route-target-type {
+    type enumeration {
+      enum import {
+        value 0;
+        description
+          "The Route Target applies to route import.";
+      }
+      enum export {
+        value 1;
+        description
+          "The Route Target applies to route export.";
+      }
+
+      enum both {
+        value 2;
+        description
+          "The Route Target applies to both route import and
+           route export.";
+      }
+    }
+    description
+      "Indicates the role a Route Target takes in route filtering.";
+    reference
+      "RFC 4364: BGP/MPLS IP Virtual Private Networks (VPNs).";
+  }
+
+  typedef route-distinguisher {
+    type string {
+      pattern
+        '(0:(6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|'
+      +     '6[0-4][0-9]{3}|'
+      +     '[1-5][0-9]{4}|[1-9][0-9]{0,3}|0):(429496729[0-5]|'
+      +     '42949672[0-8][0-9]|'
+      +     '4294967[01][0-9]{2}|429496[0-6][0-9]{3}|'
+      +     '42949[0-5][0-9]{4}|'
+      +     '4294[0-8][0-9]{5}|429[0-3][0-9]{6}|'
+      +     '42[0-8][0-9]{7}|4[01][0-9]{8}|'
+      +     '[1-3][0-9]{9}|[1-9][0-9]{0,8}|0))|'
+      + '(1:((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|'
+      +     '25[0-5])\.){3}([0-9]|[1-9][0-9]|'
+      +     '1[0-9]{2}|2[0-4][0-9]|25[0-5])):(6553[0-5]|'
+      +     '655[0-2][0-9]|'
+      +     '65[0-4][0-9]{2}|6[0-4][0-9]{3}|'
+      +     '[1-5][0-9]{4}|[1-9][0-9]{0,3}|0))|'
+      + '(2:(429496729[0-5]|42949672[0-8][0-9]|'
+      +     '4294967[01][0-9]{2}|'
+      +     '429496[0-6][0-9]{3}|42949[0-5][0-9]{4}|'
+      +     '4294[0-8][0-9]{5}|'
+      +     '429[0-3][0-9]{6}|42[0-8][0-9]{7}|4[01][0-9]{8}|'
+      +     '[1-3][0-9]{9}|[1-9][0-9]{0,8}|0):'
+      +     '(6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|'
+      +     '6[0-4][0-9]{3}|'
+      +     '[1-5][0-9]{4}|[1-9][0-9]{0,3}|0))|'
+      + '(6(:[a-fA-F0-9]{2}){6})|'
+      + '(([3-57-9a-fA-F]|[1-9a-fA-F][0-9a-fA-F]{1,3}):'
+      +     '[0-9a-fA-F]{1,12})';
+    }
+
+    description
+      "A Route Distinguisher is an 8-octet value used to
+       distinguish routes from different BGP VPNs (RFC 4364).
+       A Route Distinguisher will have the same format as a
+       Route Target as per RFC 4360 and will consist of
+       two or three fields: a 2-octet Type field, an administrator
+       field, and, optionally, an assigned number field.
+
+       According to the data formats for types 0, 1, 2, and 6 as
+       defined in RFC 4360, RFC 5668, and RFC 7432, the encoding
+       pattern is defined as:
+
+       0:2-octet-asn:4-octet-number
+       1:4-octet-ipv4addr:2-octet-number
+       2:4-octet-asn:2-octet-number
+       6:6-octet-mac-address
+
+       Additionally, a generic pattern is defined for future
+       route discriminator types:
+
+       2-octet-other-hex-number:6-octet-hex-number
+
+       Some valid examples are 0:100:100, 1:1.1.1.1:100,
+       2:1234567890:203, and 6:26:00:08:92:78:00.";
+    reference
+      "RFC 4360: BGP Extended Communities Attribute.
+       RFC 4364: BGP/MPLS IP Virtual Private Networks (VPNs).
+       RFC 5668: 4-Octet AS Specific BGP Extended Community.
+       RFC 7432: BGP MPLS-Based Ethernet VPN.";
+  }
+
+  typedef route-origin {
+    type string {
+      pattern
+        '(0:(6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|'
+      +     '6[0-4][0-9]{3}|'
+      +     '[1-5][0-9]{4}|[1-9][0-9]{0,3}|0):(429496729[0-5]|'
+      +     '42949672[0-8][0-9]|'
+      +     '4294967[01][0-9]{2}|429496[0-6][0-9]{3}|'
+      +     '42949[0-5][0-9]{4}|'
+      +     '4294[0-8][0-9]{5}|429[0-3][0-9]{6}|'
+      +     '42[0-8][0-9]{7}|4[01][0-9]{8}|'
+      +     '[1-3][0-9]{9}|[1-9][0-9]{0,8}|0))|'
+      + '(1:((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|'
+      +     '25[0-5])\.){3}([0-9]|[1-9][0-9]|'
+      +     '1[0-9]{2}|2[0-4][0-9]|25[0-5])):(6553[0-5]|'
+      +     '655[0-2][0-9]|'
+      +     '65[0-4][0-9]{2}|6[0-4][0-9]{3}|'
+      +     '[1-5][0-9]{4}|[1-9][0-9]{0,3}|0))|'
+      + '(2:(429496729[0-5]|42949672[0-8][0-9]|'
+      +     '4294967[01][0-9]{2}|'
+      +     '429496[0-6][0-9]{3}|42949[0-5][0-9]{4}|'
+      +     '4294[0-8][0-9]{5}|'
+      +     '429[0-3][0-9]{6}|42[0-8][0-9]{7}|4[01][0-9]{8}|'
+      +     '[1-3][0-9]{9}|[1-9][0-9]{0,8}|0):'
+      +     '(6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|'
+      +     '6[0-4][0-9]{3}|'
+      +     '[1-5][0-9]{4}|[1-9][0-9]{0,3}|0))|'
+      + '(6(:[a-fA-F0-9]{2}){6})|'
+      + '(([3-57-9a-fA-F]|[1-9a-fA-F][0-9a-fA-F]{1,3}):'
+      +    '[0-9a-fA-F]{1,12})';
+    }
+    description
+      "A Route Origin is an 8-octet BGP extended community
+       identifying the set of sites where the BGP route
+       originated (RFC 4364).  A Route Origin will have the same
+       format as a Route Target as per RFC 4360 and will consist
+       of two or three fields: a 2-octet Type field, an
+       administrator field, and, optionally, an assigned number
+       field.
+
+       According to the data formats for types 0, 1, 2, and 6 as
+       defined in RFC 4360, RFC 5668, and RFC 7432, the encoding
+       pattern is defined as:
+
+       0:2-octet-asn:4-octet-number
+       1:4-octet-ipv4addr:2-octet-number
+       2:4-octet-asn:2-octet-number
+       6:6-octet-mac-address
+       Additionally, a generic pattern is defined for future
+       Route Origin types:
+
+       2-octet-other-hex-number:6-octet-hex-number
+
+       Some valid examples are 0:100:100, 1:1.1.1.1:100,
+       2:1234567890:203, and 6:26:00:08:92:78:00.";
+    reference
+      "RFC 4360: BGP Extended Communities Attribute.
+       RFC 4364: BGP/MPLS IP Virtual Private Networks (VPNs).
+       RFC 5668: 4-Octet AS Specific BGP Extended Community.
+       RFC 7432: BGP MPLS-Based Ethernet VPN.";
+  }
+
+  typedef ipv6-route-origin {
+    type string {
+      pattern
+          '((:|[0-9a-fA-F]{0,4}):)([0-9a-fA-F]{0,4}:){0,5}'
+          + '((([0-9a-fA-F]{0,4}:)?(:|[0-9a-fA-F]{0,4}))|'
+          + '(((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.){3}'
+          + '(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])))'
+          + ':'
+          + '(6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|'
+          + '6[0-4][0-9]{3}|'
+          + '[1-5][0-9]{4}|[1-9][0-9]{0,3}|0)';
+      pattern '((([^:]+:){6}(([^:]+:[^:]+)|(.*\..*)))|'
+          + '((([^:]+:)*[^:]+)?::(([^:]+:)*[^:]+)?))'
+          + ':'
+          + '(6553[0-5]|655[0-2][0-9]|65[0-4][0-9]{2}|'
+          + '6[0-4][0-9]{3}|'
+          + '[1-5][0-9]{4}|[1-9][0-9]{0,3}|0)';
+    }
+    description
+      "An IPv6 Route Origin is a 20-octet BGP IPv6 Address
+       Specific Extended Community serving the same function
+       as a standard 8-octet route, except that it only allows
+       an IPv6 address as the global administrator.  The format
+       is <ipv6-address:2-octet-number>.
+
+       Two valid examples are 2001:db8::1:6544 and
+       2001:db8::5eb1:791:6b37:17958.";
+    reference
+      "RFC 5701: IPv6 Address Specific BGP Extended Community
+       Attribute.";
+  }
+
+  /*** Collection of types common to multicast ***/
+
+  typedef ipv4-multicast-group-address {
+    type inet:ipv4-address {
+      pattern '(2((2[4-9])|(3[0-9]))\.).*';
+    }
+    description
+      "This type represents an IPv4 multicast group address,
+       which is in the range of 224.0.0.0 to 239.255.255.255.";
+    reference
+      "RFC 1112: Host Extensions for IP Multicasting.";
+  }
+
+  typedef ipv6-multicast-group-address {
+    type inet:ipv6-address {
+      pattern '(([fF]{2}[0-9a-fA-F]{2}):).*';
+    }
+    description
+      "This type represents an IPv6 multicast group address,
+       which is in the range of ff00::/8.";
+    reference
+      "RFC 4291: IP Version 6 Addressing Architecture.  Section 2.7.
+       RFC 7346: IPv6 Multicast Address Scopes.";
+  }
+
+  typedef ip-multicast-group-address {
+    type union {
+      type ipv4-multicast-group-address;
+      type ipv6-multicast-group-address;
+    }
+    description
+      "This type represents a version-neutral IP multicast group
+       address.  The format of the textual representation implies
+       the IP version.";
+  }
+
+  typedef ipv4-multicast-source-address {
+    type union {
+      type enumeration {
+        enum * {
+          description
+            "Any source address.";
+        }
+      }
+      type inet:ipv4-address;
+    }
+    description
+      "Multicast source IPv4 address type.";
+  }
+
+  typedef ipv6-multicast-source-address {
+    type union {
+      type enumeration {
+        enum * {
+          description
+            "Any source address.";
+        }
+      }
+      type inet:ipv6-address;
+    }
+    description
+      "Multicast source IPv6 address type.";
+  }
+
+  /*** Collection of types common to protocols ***/
+
+  typedef bandwidth-ieee-float32 {
+    type string {
+      pattern
+        '0[xX](0((\.0?)?[pP](\+)?0?|(\.0?))|'
+      + '1(\.([0-9a-fA-F]{0,5}[02468aAcCeE]?)?)?[pP](\+)?(12[0-7]|'
+      + '1[01][0-9]|0?[0-9]?[0-9])?)';
+    }
+    description
+      "Bandwidth in IEEE 754 floating-point 32-bit binary format:
+       (-1)**(S) * 2**(Exponent-127) * (1 + Fraction),
+       where Exponent uses 8 bits and Fraction uses 23 bits.
+       The units are octets per second.
+       The encoding format is the external hexadecimal-significant
+       character sequences specified in IEEE 754 and ISO/IEC C99.
+       The format is restricted to be normalized, non-negative, and
+       non-fraction: 0x1.hhhhhhp{+}d, 0X1.HHHHHHP{+}D, or 0x0p0,
+       where 'h' and 'H' are hexadecimal digits and 'd' and 'D' are
+       integers in the range of [0..127].
+       When six hexadecimal digits are used for 'hhhhhh' or
+       'HHHHHH', the least significant digit must be an even
+       number.  'x' and 'X' indicate hexadecimal; 'p' and 'P'
+       indicate a power of two.  Some examples are 0x0p0, 0x1p10,
+       and 0x1.abcde2p+20.";
+    reference
+      "IEEE Std 754-2008: IEEE Standard for Floating-Point
+       Arithmetic.
+       ISO/IEC C99: Information technology - Programming
+       Languages - C.";
+  }
+
+  typedef link-access-type {
+    type enumeration {
+      enum broadcast {
+        description
+          "Specify broadcast multi-access network.";
+      }
+      enum non-broadcast-multiaccess {
+        description
+          "Specify Non-Broadcast Multi-Access (NBMA) network.";
+      }
+      enum point-to-multipoint {
+        description
+          "Specify point-to-multipoint network.";
+      }
+      enum point-to-point {
+        description
+          "Specify point-to-point network.";
+      }
+    }
+    description
+      "Link access type.";
+  }
+
+  typedef timer-multiplier {
+    type uint8;
+    description
+      "The number of timer value intervals that should be
+       interpreted as a failure.";
+  }
+
+  typedef timer-value-seconds16 {
+    type union {
+      type uint16 {
+        range "1..65535";
+      }
+      type enumeration {
+        enum infinity {
+          description
+            "The timer is set to infinity.";
+        }
+        enum not-set {
+          description
+            "The timer is not set.";
+        }
+      }
+    }
+    units "seconds";
+    description
+      "Timer value type, in seconds (16-bit range).";
+  }
+
+  typedef timer-value-seconds32 {
+    type union {
+      type uint32 {
+        range "1..4294967295";
+      }
+      type enumeration {
+        enum infinity {
+          description
+            "The timer is set to infinity.";
+        }
+        enum not-set {
+          description
+            "The timer is not set.";
+        }
+      }
+    }
+    units "seconds";
+    description
+      "Timer value type, in seconds (32-bit range).";
+  }
+
+  typedef timer-value-milliseconds {
+    type union {
+      type uint32 {
+        range "1..4294967295";
+      }
+      type enumeration {
+        enum infinity {
+          description
+            "The timer is set to infinity.";
+        }
+        enum not-set {
+          description
+            "The timer is not set.";
+        }
+      }
+    }
+    units "milliseconds";
+    description
+      "Timer value type, in milliseconds.";
+  }
+
+  typedef percentage {
+    type uint8 {
+      range "0..100";
+    }
+    description
+      "Integer indicating a percentage value.";
+  }
+
+  typedef timeticks64 {
+    type uint64;
+    description
+      "This type is based on the timeticks type defined in
+       RFC 6991, but with 64-bit width.  It represents the time,
+       modulo 2^64, in hundredths of a second between two epochs.";
+    reference
+      "RFC 6991: Common YANG Data Types.";
+  }
+
+  typedef uint24 {
+    type uint32 {
+      range "0..16777215";
+    }
+    description
+      "24-bit unsigned integer.";
+  }
+
+  /*** Collection of types related to MPLS/GMPLS ***/
+
+  typedef generalized-label {
+    type binary;
+    description
+      "Generalized Label.  Nodes sending and receiving the
+       Generalized Label are aware of the link-specific
+       label context and type.";
+    reference
+      "RFC 3471: Generalized Multi-Protocol Label Switching (GMPLS)
+       Signaling Functional Description.  Section 3.2.";
+  }
+
+  typedef mpls-label-special-purpose {
+    type identityref {
+      base mpls-label-special-purpose-value;
+    }
+    description
+      "This type represents the special-purpose MPLS label values.";
+    reference
+      "RFC 3032: MPLS Label Stack Encoding.
+       RFC 7274: Allocating and Retiring Special-Purpose MPLS
+       Labels.";
+  }
+
+  typedef mpls-label-general-use {
+    type uint32 {
+      range "16..1048575";
+    }
+    description
+      "The 20-bit label value in an MPLS label stack as specified
+       in RFC 3032.  This label value does not include the
+       encodings of Traffic Class and TTL (Time to Live).
+       The label range specified by this type is for general use,
+       with special-purpose MPLS label values excluded.";
+    reference
+      "RFC 3032: MPLS Label Stack Encoding.";
+  }
+
+  typedef mpls-label {
+    type union {
+      type mpls-label-special-purpose;
+      type mpls-label-general-use;
+    }
+    description
+      "The 20-bit label value in an MPLS label stack as specified
+       in RFC 3032.  This label value does not include the
+       encodings of Traffic Class and TTL.";
+    reference
+      "RFC 3032: MPLS Label Stack Encoding.";
+  }
+
+  /*** Groupings **/
+
+  grouping mpls-label-stack {
+    description
+      "This grouping specifies an MPLS label stack.  The label
+       stack is encoded as a list of label stack entries.  The
+       list key is an identifier that indicates the relative
+       ordering of each entry, with the lowest-value identifier
+       corresponding to the top of the label stack.";
+    container mpls-label-stack {
+      description
+        "Container for a list of MPLS label stack entries.";
+      list entry {
+        key "id";
+        description
+          "List of MPLS label stack entries.";
+        leaf id {
+          type uint8;
+          description
+            "Identifies the entry in a sequence of MPLS label
+             stack entries.  An entry with a smaller identifier
+             value precedes an entry with a larger identifier
+             value in the label stack.  The value of this ID has
+             no semantic meaning other than relative ordering
+             and referencing the entry.";
+        }
+        leaf label {
+          type rt-types:mpls-label;
+          description
+            "Label value.";
+        }
+
+        leaf ttl {
+          type uint8;
+          description
+            "Time to Live (TTL).";
+          reference
+            "RFC 3032: MPLS Label Stack Encoding.";
+        }
+        leaf traffic-class {
+          type uint8 {
+            range "0..7";
+          }
+          description
+            "Traffic Class (TC).";
+          reference
+            "RFC 5462: Multiprotocol Label Switching (MPLS) Label
+             Stack Entry: 'EXP' Field Renamed to 'Traffic Class'
+             Field.";
+        }
+      }
+    }
+  }
+
+  grouping vpn-route-targets {
+    description
+      "A grouping that specifies Route Target import-export rules
+       used in BGP-enabled VPNs.";
+    reference
+      "RFC 4364: BGP/MPLS IP Virtual Private Networks (VPNs).
+       RFC 4664: Framework for Layer 2 Virtual Private Networks
+       (L2VPNs).";
+    list vpn-target {
+      key "route-target";
+      description
+        "List of Route Targets.";
+      leaf route-target {
+        type rt-types:route-target;
+        description
+          "Route Target value.";
+      }
+      leaf route-target-type {
+        type rt-types:route-target-type;
+        mandatory true;
+        description
+          "Import/export type of the Route Target.";
+      }
+    }
+  }
+}
diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-te-packet-types@2024-10-30.yang b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-te-packet-types@2024-10-30.yang
new file mode 100644
index 0000000000000000000000000000000000000000..70bead463820694c7f88c977f8ef28df0bb3db7a
--- /dev/null
+++ b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-te-packet-types@2024-10-30.yang
@@ -0,0 +1,806 @@
+module ietf-te-packet-types {
+  yang-version 1.1;
+  namespace "urn:ietf:params:xml:ns:yang:ietf-te-packet-types";
+  prefix te-packet-types;
+
+  import ietf-yang-types {
+    prefix yang;
+    reference
+      "RFC 6991: Common YANG Data Types";
+  }
+
+  import ietf-te-types {
+    prefix te-types;
+    reference
+      "RFC XXXX: Common YANG Data Types for Traffic Engineering";
+  }
+  // RFC Editor: replace XXXX with actual RFC number
+  // and remove this note
+
+  organization
+    "IETF Traffic Engineering Architecture and Signaling (TEAS)
+     Working Group";
+  contact
+    "WG Web:   <https://datatracker.ietf.org/wg/teas/>
+     WG List:  <mailto:teas@ietf.org>
+
+     Editor:   Tarek Saad
+               <mailto:tsaad.net@gmail.com>
+
+     Editor:   Rakesh Gandhi
+               <mailto:rgandhi@cisco.com>
+
+     Editor:   Vishnu Pavan Beeram
+               <mailto:vbeeram@juniper.net>
+
+     Editor:   Xufeng Liu
+               <mailto:xufeng.liu.ietf@gmail.com>
+
+     Editor:   Igor Bryskin
+               <mailto:i_bryskin@yahoo.com>";
+  description
+    "This YANG module contains a collection of generally useful YANG
+     data type definitions specific to Packet Traffic Enginnering
+     (TE).
+
+     The model fully conforms to the Network Management Datastore
+     Architecture (NMDA).
+
+     The key words 'MUST', 'MUST NOT', 'REQUIRED', 'SHALL', 'SHALL
+     NOT', 'SHOULD', 'SHOULD NOT', 'RECOMMENDED', 'NOT RECOMMENDED',
+     'MAY', and 'OPTIONAL' in this document are to be interpreted as
+     described in BCP 14 (RFC 2119) (RFC 8174) when, and only when,
+     they appear in all capitals, as shown here.
+
+     Copyright (c) 2024 IETF Trust and the persons identified as
+     authors of the code.  All rights reserved.
+
+     Redistribution and use in source and binary forms, with or
+     without modification, is permitted pursuant to, and subject to
+     the license terms contained in, the Revised BSD License set
+     forth in Section 4.c of the IETF Trust's Legal Provisions
+     Relating to IETF Documents
+     (https://trustee.ietf.org/license-info).
+
+     This version of this YANG module is part of RFC XXXX
+     (https://www.rfc-editor.org/info/rfcXXXX); see the RFC itself
+     for full legal notices.";
+  revision 2024-10-30 {
+    description
+      "This revision adds the following new identities:
+       - bandwidth-profile-type;
+       - link-metric-delay-variation;
+       - link-metric-loss;
+       - path-metric-delay-variation;
+       - path-metric-loss.
+
+      This revision adds the following new groupings:
+       - bandwidth-profile-parameters;
+       - te-packet-path-bandwidth;
+       - te-packet-link-bandwidth.
+
+      This revision provides also few editorial changes.";
+    reference
+      "RFC XXXX: Common YANG Data Types for Traffic Engineering";
+  }
+  // RFC Editor: replace XXXX with actual RFC number, update date
+  // information and remove this note
+
+  revision 2020-06-10 {
+    description
+      "Latest revision of TE MPLS types.";
+    reference
+      "RFC 8776: Common YANG Data Types for Traffic Engineering";
+  }
+
+  /*
+   * Identities
+   */
+
+  identity bandwidth-profile-type {
+    description
+      "Bandwidth Profile Types";
+  }
+
+    identity mef-10 {
+      base bandwidth-profile-type;
+      description
+        "MEF 10 Bandwidth Profile";
+      reference
+        "MEF 10.3: Ethernet Services Attributes Phase 3";
+    }
+
+    identity rfc-2697 {
+      base bandwidth-profile-type;
+      description
+        "RFC 2697 Bandwidth Profile";
+      reference
+        "RFC 2697: A Single Rate Three Color Marker";
+    }
+
+    identity rfc-2698 {
+      base bandwidth-profile-type;
+      description
+        "RFC 2698 Bandwidth Profile";
+      reference
+        "RFC 2698: A Two Rate Three Color Marker";
+    }
+
+  // Derived identities from te-types:link-metric-type
+
+    identity link-metric-delay-variation {
+      base te-types:link-metric-type;
+      description
+        "The Unidirectional Delay Variation Metric,
+         measured in units of microseconds.";
+      reference
+        "RFC 7471: OSPF Traffic Engineering (TE) Metric Extensions,
+                   Section 4.3
+         RFC 8570: IS-IS Traffic Engineering (TE) Metric Extensions,
+                   Section 4.3";
+    }
+
+    identity link-metric-loss {
+      base te-types:link-metric-type;
+      description
+        "The Unidirectional Link Loss Metric,
+         measured in units of 0.000003%.";
+      reference
+        "RFC 7471: OSPF Traffic Engineering (TE) Metric Extensions,
+                   Section 4.4
+         RFC 8570: IS-IS Traffic Engineering (TE) Metric Extensions,
+                   Section 4.4";
+    }
+
+  // Derived identities from te-types:link-metric-type
+
+    identity path-metric-delay-variation {
+      base te-types:path-metric-type;
+      description
+        "The Path Delay Variation Metric,
+         measured in units of microseconds.";
+      reference
+        "RFC 8233: Extensions to the Path Computation Element
+                   Communication Protocol (PCEP) to Compute
+                   Service-Aware Label Switched Paths (LSPs),
+                   Section 3.1.2";
+    }
+
+    identity path-metric-loss {
+      base te-types:path-metric-type;
+      description
+        "The Path Loss Metric, measured in units of 0.000003%.";
+      reference
+        "RFC 8233: Extensions to the Path Computation Element
+                   Communication Protocol (PCEP) to Compute
+                   Service-Aware Label Switched Paths (LSPs),
+                   Section 3.1.3";
+    }
+
+  /*
+   * Typedefs
+   */
+
+  typedef te-bandwidth-requested-type {
+    type enumeration {
+      enum specified-value {
+        description
+          "Bandwidth value is explicitly specified.";
+      }
+      enum specified-profile {
+        description
+          "Bandwidth profile is explicitly specified.";
+      }
+      enum auto {
+        description
+          "Bandwidth is automatically computed.";
+      }
+    }
+    description
+      "Enumerated type for specifying whether bandwidth is
+       explicitly specified or automatically computed.";
+  }
+
+  typedef te-class-type {
+    type uint8;
+    description
+      "Diffserv-TE Class-Type.  Defines a set of Traffic Trunks
+       crossing a link that is governed by a specific set of
+       bandwidth constraints.  Class-Type is used for the purposes
+       of link bandwidth allocation, constraint-based routing, and
+       admission control.";
+    reference
+      "RFC 4124: Protocol Extensions for Support of Diffserv-aware
+                 MPLS Traffic Engineering";
+  }
+
+  typedef bc-type {
+    type uint8 {
+      range "0..7";
+    }
+    description
+      "Diffserv-TE bandwidth constraints as defined in RFC 4124.";
+    reference
+      "RFC 4124: Protocol Extensions for Support of Diffserv-aware
+                 MPLS Traffic Engineering";
+  }
+
+  typedef bandwidth-kbps {
+    type uint64;
+    units "Kbps";
+    description
+      "Bandwidth values, expressed in kilobits per second.";
+  }
+
+  typedef bandwidth-mbps {
+    type uint64;
+    units "Mbps";
+    description
+      "Bandwidth values, expressed in megabits per second.";
+  }
+
+  typedef bandwidth-gbps {
+    type uint64;
+    units "Gbps";
+    description
+      "Bandwidth values, expressed in gigabits per second.";
+  }
+
+  identity backup-protection-type {
+    description
+      "Base identity for the backup protection type.";
+  }
+
+  identity backup-protection-link {
+    base backup-protection-type;
+    description
+      "Backup provides link protection only.";
+  }
+
+  identity backup-protection-node-link {
+    base backup-protection-type;
+    description
+      "Backup offers node (preferred) or link protection.";
+  }
+
+  identity bc-model-type {
+    description
+      "Base identity for the Diffserv-TE Bandwidth Constraints
+       Model type.";
+    reference
+      "RFC 4124: Protocol Extensions for Support of Diffserv-aware
+                 MPLS Traffic Engineering";
+  }
+
+  identity bc-model-rdm {
+    base bc-model-type;
+    description
+      "Russian Dolls Bandwidth Constraints Model type.";
+    reference
+      "RFC 4127: Russian Dolls Bandwidth Constraints Model for
+                 Diffserv-aware MPLS Traffic Engineering";
+  }
+
+  identity bc-model-mam {
+    base bc-model-type;
+    description
+      "Maximum Allocation Bandwidth Constraints Model type.";
+    reference
+      "RFC 4125: Maximum Allocation Bandwidth Constraints Model for
+                 Diffserv-aware MPLS Traffic Engineering";
+  }
+
+  identity bc-model-mar {
+    base bc-model-type;
+    description
+      "Maximum Allocation with Reservation Bandwidth Constraints
+       Model type.";
+    reference
+      "RFC 4126: Max Allocation with Reservation Bandwidth
+                 Constraints Model for Diffserv-aware MPLS Traffic
+                 Engineering & Performance Comparisons";
+  }
+
+  /*
+   * Groupings
+   */
+
+  grouping performance-metrics-attributes-packet {
+    description
+      "Contains PM attributes.";
+    uses te-types:performance-metrics-attributes {
+      augment "performance-metrics-one-way" {
+        leaf one-way-min-delay {
+          type uint32 {
+            range "0..16777215";
+          }
+          description
+            "One-way minimum delay or latency in microseconds.";
+        }
+        leaf one-way-min-delay-normality {
+          type te-types:performance-metrics-normality;
+          default "normal";
+          description
+            "One-way minimum delay or latency normality.";
+        }
+        leaf one-way-max-delay {
+          type uint32 {
+            range "0..16777215";
+          }
+          description
+            "One-way maximum delay or latency in microseconds.";
+        }
+        leaf one-way-max-delay-normality {
+          type te-types:performance-metrics-normality;
+          default "normal";
+          description
+            "One-way maximum delay or latency normality.";
+        }
+        leaf one-way-delay-variation {
+          type uint32 {
+            range "0..16777215";
+          }
+          description
+            "One-way delay variation in microseconds.";
+          reference
+            "RFC 5481: Packet Delay Variation Applicability
+                       Statement, Section 4.2";
+        }
+        leaf one-way-delay-variation-normality {
+          type te-types:performance-metrics-normality;
+          default "normal";
+          description
+            "One-way delay variation normality.";
+          reference
+            "RFC 7471: OSPF Traffic Engineering (TE) Metric
+                       Extensions
+             RFC 8570: IS-IS Traffic Engineering (TE) Metric
+                       Extensions
+             RFC 7823: Performance-Based Path Selection for
+                       Explicitly Routed Label Switched Paths (LSPs)
+                       Using TE Metric Extensions";
+        }
+        leaf one-way-packet-loss {
+          type decimal64 {
+            fraction-digits 6;
+            range "0..50.331642";
+          }
+          description
+            "One-way packet loss as a percentage of the total traffic
+             sent over a configurable interval.  The finest precision
+             is 0.000003%, where the maximum is 50.331642%.";
+          reference
+            "RFC 8570: IS-IS Traffic Engineering (TE) Metric
+                       Extensions, Section 4.4";
+        }
+        leaf one-way-packet-loss-normality {
+          type te-types:performance-metrics-normality;
+          default "normal";
+          description
+            "Packet loss normality.";
+          reference
+            "RFC 7471: OSPF Traffic Engineering (TE) Metric
+                       Extensions
+             RFC 8570: IS-IS Traffic Engineering (TE) Metric
+                       Extensions
+             RFC 7823: Performance-Based Path Selection for
+                       Explicitly Routed Label Switched Paths (LSPs)
+                       Using TE Metric Extensions";
+        }
+        description
+          "PM one-way packet-specific augmentation for a generic PM
+           grouping.";
+      }
+      augment "performance-metrics-two-way" {
+        leaf two-way-min-delay {
+          type uint32 {
+            range "0..16777215";
+          }
+          default "0";
+          description
+            "Two-way minimum delay or latency in microseconds.";
+        }
+        leaf two-way-min-delay-normality {
+          type te-types:performance-metrics-normality;
+          default "normal";
+          description
+            "Two-way minimum delay or latency normality.";
+          reference
+            "RFC 7471: OSPF Traffic Engineering (TE) Metric
+                       Extensions
+             RFC 8570: IS-IS Traffic Engineering (TE) Metric
+                       Extensions
+             RFC 7823: Performance-Based Path Selection for
+                       Explicitly Routed Label Switched Paths (LSPs)
+                       Using TE Metric Extensions";
+        }
+        leaf two-way-max-delay {
+          type uint32 {
+            range "0..16777215";
+          }
+          default "0";
+          description
+            "Two-way maximum delay or latency in microseconds.";
+        }
+        leaf two-way-max-delay-normality {
+          type te-types:performance-metrics-normality;
+          default "normal";
+          description
+            "Two-way maximum delay or latency normality.";
+          reference
+            "RFC 7471: OSPF Traffic Engineering (TE) Metric
+                       Extensions
+             RFC 8570: IS-IS Traffic Engineering (TE) Metric
+                       Extensions
+             RFC 7823: Performance-Based Path Selection for
+                       Explicitly Routed Label Switched Paths (LSPs)
+                       Using TE Metric Extensions";
+        }
+        leaf two-way-delay-variation {
+          type uint32 {
+            range "0..16777215";
+          }
+          default "0";
+          description
+            "Two-way delay variation in microseconds.";
+          reference
+            "RFC 5481: Packet Delay Variation Applicability
+                       Statement, Section 4.2";
+        }
+        leaf two-way-delay-variation-normality {
+          type te-types:performance-metrics-normality;
+          default "normal";
+          description
+            "Two-way delay variation normality.";
+          reference
+            "RFC 7471: OSPF Traffic Engineering (TE) Metric
+                       Extensions
+             RFC 8570: IS-IS Traffic Engineering (TE) Metric
+                       Extensions
+             RFC 7823: Performance-Based Path Selection for
+                       Explicitly Routed Label Switched Paths (LSPs)
+                       Using TE Metric Extensions";
+        }
+        leaf two-way-packet-loss {
+          type decimal64 {
+            fraction-digits 6;
+            range "0..50.331642";
+          }
+          default "0";
+          description
+            "Two-way packet loss as a percentage of the total traffic
+             sent over a configurable interval.  The finest precision
+             is 0.000003%.";
+        }
+        leaf two-way-packet-loss-normality {
+          type te-types:performance-metrics-normality;
+          default "normal";
+          description
+            "Two-way packet loss normality.";
+        }
+        description
+          "PM two-way packet-specific augmentation for a generic PM
+           grouping.";
+        reference
+          "RFC 7471: OSPF Traffic Engineering (TE) Metric Extensions
+           RFC 8570: IS-IS Traffic Engineering (TE) Metric Extensions
+           RFC 7823: Performance-Based Path Selection for Explicitly
+                     Routed Label Switched Paths (LSPs) Using TE
+                     Metric Extensions";
+      }
+    }
+  }
+
+  grouping one-way-performance-metrics-packet {
+    description
+      "One-way packet PM throttle grouping.";
+    leaf one-way-min-delay {
+      type uint32 {
+        range "0..16777215";
+      }
+      default "0";
+      description
+        "One-way minimum delay or latency in microseconds.";
+    }
+    leaf one-way-max-delay {
+      type uint32 {
+        range "0..16777215";
+      }
+      default "0";
+      description
+        "One-way maximum delay or latency in microseconds.";
+    }
+    leaf one-way-delay-variation {
+      type uint32 {
+        range "0..16777215";
+      }
+      default "0";
+      description
+        "One-way delay variation in microseconds.";
+    }
+    leaf one-way-packet-loss {
+      type decimal64 {
+        fraction-digits 6;
+        range "0..50.331642";
+      }
+      default "0";
+      description
+        "One-way packet loss as a percentage of the total traffic
+         sent over a configurable interval.  The finest precision is
+         0.000003%.";
+    }
+  }
+
+  grouping one-way-performance-metrics-gauge-packet {
+    description
+      "One-way packet PM throttle grouping.
+
+       This grouping is used to report the same metrics defined in
+       the one-way-performance-metrics-packet grouping, using gauges
+       instead of uint32 data types and referencing IPPM RFCs
+       instead of IGP-TE RFCs.";
+    leaf one-way-min-delay {
+      type yang:gauge64;
+      description
+        "One-way minimum delay or latency in microseconds.";
+    }
+    leaf one-way-max-delay {
+      type yang:gauge64;
+      description
+        "One-way maximum delay or latency in microseconds.";
+      reference
+        "RFC 7679: A One-Way Delay Metric for IP Performance
+                   Metrics (IPPM)";
+    }
+    leaf one-way-delay-variation {
+      type yang:gauge64;
+      description
+        "One-way delay variation in microseconds.";
+      reference
+        "RFC 3393: IP Packet Delay Variation Metric for IP
+                   Performance Metrics (IPPM)";
+    }
+    leaf one-way-packet-loss {
+      type decimal64 {
+        fraction-digits 5;
+        range "0..100";
+      }
+      description
+        "The ratio of packets dropped to packets transmitted between
+         two endpoints.";
+      reference
+        "RFC 7680: A One-Way Loss Metric for IP Performance
+                   Metrics (IPPM)";
+    }
+  }
+
+  grouping two-way-performance-metrics-packet {
+    description
+      "Two-way packet PM throttle grouping.";
+    leaf two-way-min-delay {
+      type uint32 {
+        range "0..16777215";
+      }
+      default "0";
+      description
+        "Two-way minimum delay or latency in microseconds.";
+    }
+    leaf two-way-max-delay {
+      type uint32 {
+        range "0..16777215";
+      }
+      default "0";
+      description
+        "Two-way maximum delay or latency in microseconds.";
+    }
+    leaf two-way-delay-variation {
+      type uint32 {
+        range "0..16777215";
+      }
+      default "0";
+      description
+        "Two-way delay variation in microseconds.";
+    }
+    leaf two-way-packet-loss {
+      type decimal64 {
+        fraction-digits 6;
+        range "0..50.331642";
+      }
+      default "0";
+      description
+        "Two-way packet loss as a percentage of the total traffic
+         sent over a configurable interval.  The finest precision is
+         0.000003%.";
+    }
+  }
+
+  grouping two-way-performance-metrics-gauge-packet {
+    description
+      "Two-way packet PM throttle grouping.
+
+       This grouping is used to report the same metrics defined in
+       the two-way-performance-metrics-packet grouping, using gauges
+       instead of uint32 data types and referencing IPPM RFCs
+       instead of IGP-TE RFCs.";
+    leaf two-way-min-delay {
+      type yang:gauge64;
+      description
+        "Two-way minimum delay or latency in microseconds.";
+      reference
+        "RFC 2681: A Round-trip Delay Metric for IPPM";
+    }
+    leaf two-way-max-delay {
+      type yang:gauge64;
+      description
+        "Two-way maximum delay or latency in microseconds.";
+      reference
+        "RFC 2681: A Round-trip Delay Metric for IPPM";
+    }
+    leaf two-way-delay-variation {
+      type yang:gauge64;
+      description
+        "Two-way delay variation in microseconds.";
+      reference
+        "RFC 5481: Packet Delay Variation Applicability Statement";
+    }
+    leaf two-way-packet-loss {
+      type decimal64 {
+        fraction-digits 5;
+        range "0..100";
+      }
+      description
+        "The ratio of packets dropped to packets transmitted between
+         two endpoints.";
+    }
+  }
+
+  grouping performance-metrics-throttle-container-packet {
+    description
+      "Packet PM threshold grouping.";
+    uses te-types:performance-metrics-throttle-container {
+      augment "throttle/threshold-out" {
+        uses one-way-performance-metrics-packet;
+        uses two-way-performance-metrics-packet;
+        description
+          "PM threshold-out packet augmentation for a
+           generic grouping.";
+      }
+      augment "throttle/threshold-in" {
+        uses one-way-performance-metrics-packet;
+        uses two-way-performance-metrics-packet;
+        description
+          "PM threshold-in packet augmentation for a
+           generic grouping.";
+      }
+      augment "throttle/threshold-accelerated-advertisement" {
+        uses one-way-performance-metrics-packet;
+        uses two-way-performance-metrics-packet;
+        description
+          "PM accelerated advertisement packet augmentation for a
+           generic grouping.";
+      }
+    }
+  }
+
+  grouping bandwidth-profile-parameters {
+    description
+      "Common parameters to define bandwidth profiles in packet
+       networks.";
+    leaf cir {
+      type uint64;
+      units "bits/second";
+      description
+        "Committed Information Rate (CIR).";
+    }
+    leaf cbs {
+      type uint64;
+      units "bytes";
+      description
+        "Committed Burst Size (CBS).";
+    }
+    leaf eir {
+      type uint64;
+      units "bits/second";
+      description
+        "Excess Information Rate (EIR).";
+    }
+    leaf ebs {
+      type uint64;
+      units "bytes";
+      description
+        "Excess Burst Size (EBS).";
+    }
+    leaf pir {
+      type uint64;
+      units "bits/second";
+      description
+        "Peak Information Rate (PIR).";
+    }
+    leaf pbs {
+      type uint64;
+      units "bytes";
+      description
+        "Peak Burst Size (PBS).";
+    }
+  }
+
+  grouping te-packet-path-bandwidth {
+    description
+      "Bandwidth attributes for TE Packet paths.";
+    container packet-bandwidth {
+      description
+        "Bandwidth attributes for TE Packet paths.";
+      leaf specification-type {
+        type te-bandwidth-requested-type;
+        description
+          "The bandwidth specification type, either explicitly
+           specified or automatically computed.";
+      }
+      leaf set-bandwidth {
+        when "../specification-type = 'specified-value'" {
+          description
+            "When the bandwidth value is explicitly specified.";
+        }
+        type bandwidth-kbps;
+        description
+          "Set the bandwidth value explicitly, e.g., using offline
+           calculation.";
+      }
+      container bandwidth-profile {
+        when "../specification-type = 'specified-profile'" {
+          description
+            "When the bandwidth profile is explicitly specified.";
+        }
+        description
+          "Set the bandwidth profile attributes explicitly.";
+        leaf bandwidth-profile-name {
+          type string;
+          description
+            "Name of Bandwidth Profile.";
+        }
+        leaf bandwidth-profile-type {
+          type identityref {
+            base bandwidth-profile-type;
+          }
+          description
+            "Type of Bandwidth Profile.";
+        }
+        uses bandwidth-profile-parameters;
+      }
+      leaf class-type {
+        type te-types:te-ds-class;
+        description
+          "The Class-Type of traffic transported by the LSP.";
+        reference
+          "RFC 4124: Protocol Extensions for Support of
+                     Diffserv-aware MPLS Traffic Engineering,
+                     Section 4.3.1";
+      }
+      leaf signaled-bandwidth {
+        type te-packet-types:bandwidth-kbps;
+        config false;
+        description
+          "The currently signaled bandwidth of the LSP.
+
+           In the case where the bandwidth is specified
+           explicitly, then this will match the value of the
+           set-bandwidth leaf.
+
+           In the cases where the bandwidth is dynamically
+           computed by the system, the current value of the
+           bandwidth should be reflected.";
+      }
+    }
+  }
+
+  grouping te-packet-link-bandwidth {
+    description
+      "Bandwidth attributes for Packet TE links.";
+    leaf packet-bandwidth {
+      type uint64;
+      units "bits/second";
+      description
+        "Bandwidth value for Packet TE links.";
+    }
+  }
+}
diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-te-types@2024-10-30.yang b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-te-types@2024-10-30.yang
new file mode 100644
index 0000000000000000000000000000000000000000..5d9ae16f4bb43b5389217771a9b3f83d177449ca
--- /dev/null
+++ b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-te-types@2024-10-30.yang
@@ -0,0 +1,4399 @@
+module ietf-te-types {
+  yang-version 1.1;
+  namespace "urn:ietf:params:xml:ns:yang:ietf-te-types";
+  prefix te-types;
+
+  import ietf-inet-types {
+    prefix inet;
+    reference
+      "RFC 6991: Common YANG Data Types";
+  }
+  import ietf-yang-types {
+    prefix yang;
+    reference
+      "RFC 6991: Common YANG Data Types";
+  }
+  import ietf-routing-types {
+    prefix rt-types;
+    reference
+      "RFC 8294: Common YANG Data Types for the Routing Area";
+  }
+
+  import ietf-network {
+    prefix "nw";
+    reference
+      "RFC 8345: A YANG Data Model for Network Topologies";
+  }
+
+  import ietf-network-topology {
+    prefix "nt";
+    reference
+      "RFC 8345: A YANG Data Model for Network Topologies";
+  }
+
+  organization
+    "IETF Traffic Engineering Architecture and Signaling (TEAS)
+     Working Group";
+  contact
+    "WG Web:   <https://datatracker.ietf.org/wg/teas/>
+     WG List:  <mailto:teas@ietf.org>
+
+     Editor:   Tarek Saad
+               <mailto:tsaad.net@gmail.com>
+
+     Editor:   Rakesh Gandhi
+               <mailto:rgandhi@cisco.com>
+
+     Editor:   Vishnu Pavan Beeram
+               <mailto:vbeeram@juniper.net>
+
+     Editor:   Xufeng Liu
+               <mailto:xufeng.liu.ietf@gmail.com>
+
+     Editor:   Igor Bryskin
+               <mailto:i_bryskin@yahoo.com>";
+  description
+    "This YANG module contains a collection of generally useful
+     YANG data type definitions specific to TE.  The model fully
+     conforms to the Network Management Datastore Architecture
+     (NMDA).
+
+     The key words 'MUST', 'MUST NOT', 'REQUIRED', 'SHALL', 'SHALL
+     NOT', 'SHOULD', 'SHOULD NOT', 'RECOMMENDED', 'NOT RECOMMENDED',
+     'MAY', and 'OPTIONAL' in this document are to be interpreted as
+     described in BCP 14 (RFC 2119) (RFC 8174) when, and only when,
+     they appear in all capitals, as shown here.
+
+     Copyright (c) 2024 IETF Trust and the persons identified as
+     authors of the code.  All rights reserved.
+
+     Redistribution and use in source and binary forms, with or
+     without modification, is permitted pursuant to, and subject to
+     the license terms contained in, the Revised BSD License set
+     forth in Section 4.c of the IETF Trust's Legal Provisions
+     Relating to IETF Documents
+     (https://trustee.ietf.org/license-info).
+
+     This version of this YANG module is part of RFC XXXX
+     (https://www.rfc-editor.org/info/rfcXXXX); see the RFC itself
+     for full legal notices.";
+  revision 2024-10-30 {
+    description
+      "This revision adds the following new identities:
+      - lsp-provisioning-error-reason;
+      - association-type-diversity;
+      - tunnel-admin-state-auto;
+      - lsp-restoration-restore-none;
+      - restoration-scheme-rerouting;
+      - path-metric-optimization-type;
+      - link-path-metric-type;
+      - link-metric-type and its derived identities;
+      - path-computation-error-reason and its derived identities;
+      - protocol-origin-type and its derived identities;
+      - svec-objective-function-type and its derived identities;
+      - svec-metric-type and its derived identities.
+
+      This revision adds the following new data types:
+      - path-type.
+
+      This revision adds the following new groupings:
+      - encoding-and-switching-type;
+      - te-generic-node-id.
+
+      This revision updates the following identities:
+      - objective-function-type;
+      - action-exercise;
+      - path-metric-type;
+      - path-metric-te;
+      - path-metric-igp;
+      - path-metric-hop;
+      - path-metric-delay-average;
+      - path-metric-delay-minimum;
+      - path-metric-residual-bandwidth;
+      - path-metric-optimize-includes;
+      - path-metric-optimize-excludes;
+      - te-optimization-criterion.
+
+      This revision updates the following data types:
+      - te-node-id.
+
+      This revision updates the following groupings:
+      - explicit-route-hop:
+        - adds the following leaves:
+          - node-id-uri;
+          - link-tp-id-uri;
+        - updates the following leaves:
+          - node-id;
+          - link-tp-id;
+      - record-route-state:
+        - adds the following leaves:
+          - node-id-uri;
+          - link-tp-id-uri;
+        - updates the following leaves:
+          - node-id;
+          - link-tp-id;
+      - optimization-metric-entry:
+        - updates the following leaves:
+          - metric-type;
+      - tunnel-constraints;
+        - adds the following leaves:
+          - network-id;
+      - path-constraints-route-objects:
+        - updates the following containers:
+          - explicit-route-objects-always;
+      - generic-path-metric-bounds:
+        - updates the following leaves:
+          - metric-type;
+      - generic-path-optimization
+        - adds the following leaves:
+          - tiebreaker;
+        - deprecate the following containers:
+          - tiebreakers.
+
+      This revision obsoletes the following identities:
+      - of-minimize-agg-bandwidth-consumption;
+      - of-minimize-load-most-loaded-link;
+      - of-minimize-cost-path-set;
+      - lsp-protection-reroute-extra;
+      - lsp-protection-reroute.
+
+      This revision provides also few editorial changes.";
+    reference
+      "RFC XXXX: Common YANG Data Types for Traffic Engineering";
+  }
+  // RFC Editor: replace XXXX with actual RFC number, update date
+  // information and remove this note
+
+  revision 2020-06-10 {
+    description
+      "Initial Version of TE types.";
+    reference
+      "RFC 8776: Common YANG Data Types for Traffic Engineering";
+  }
+
+  /**
+   * Typedefs
+   */
+
+  typedef admin-group {
+    type yang:hex-string {
+      /* 01:02:03:04 */
+      length "1..11";
+    }
+    description
+      "Administrative group / resource class / color representation
+       in 'hex-string' type.
+
+       The most significant byte in the hex-string is the farthest
+       to the left in the byte sequence.  Leading zero bytes in the
+       configured value may be omitted for brevity.";
+    reference
+      "RFC 3630: Traffic Engineering (TE) Extensions to OSPF
+                 Version 2
+       RFC 5305: IS-IS Extensions for Traffic Engineering
+       RFC 7308: Extended Administrative Groups in MPLS Traffic
+                 Engineering (MPLS-TE)";
+  }
+
+  typedef admin-groups {
+    type union {
+      type admin-group;
+      type extended-admin-group;
+    }
+    description
+      "Derived types for TE administrative groups.";
+  }
+
+  typedef extended-admin-group {
+    type yang:hex-string;
+    description
+      "Extended administrative group / resource class / color
+       representation in 'hex-string' type.
+
+       The most significant byte in the hex-string is the farthest
+       to the left in the byte sequence.  Leading zero bytes in the
+       configured value may be omitted for brevity.";
+    reference
+      "RFC 7308: Extended Administrative Groups in MPLS Traffic
+                 Engineering (MPLS-TE)";
+  }
+
+  typedef path-attribute-flags {
+    type union {
+      type identityref {
+        base session-attributes-flags;
+      }
+      type identityref {
+        base lsp-attributes-flags;
+      }
+    }
+    description
+      "Path attributes flags type.";
+  }
+
+  typedef performance-metrics-normality {
+    type enumeration {
+      enum unknown {
+        value 0;
+        description
+          "Unknown.";
+      }
+      enum normal {
+        value 1;
+        description
+          "Normal.  Indicates that the anomalous bit is not set.";
+      }
+      enum abnormal {
+        value 2;
+        description
+          "Abnormal.  Indicates that the anomalous bit is set.";
+      }
+    }
+    description
+      "Indicates whether a performance metric is normal (anomalous
+       bit not set), abnormal (anomalous bit set), or unknown.";
+    reference
+      "RFC 7471: OSPF Traffic Engineering (TE) Metric Extensions
+       RFC 7823: Performance-Based Path Selection for Explicitly
+                 Routed Label Switched Paths (LSPs) Using TE Metric
+                 Extensions
+       RFC 8570: IS-IS Traffic Engineering (TE) Metric Extensions";
+  }
+
+  typedef srlg {
+    type uint32;
+    description
+      "SRLG type.";
+    reference
+      "RFC 4203: OSPF Extensions in Support of Generalized
+                 Multi-Protocol Label Switching (GMPLS)
+       RFC 5307: IS-IS Extensions in Support of Generalized
+                 Multi-Protocol Label Switching (GMPLS)";
+  }
+
+  typedef te-common-status {
+    type enumeration {
+      enum up {
+        description
+          "Enabled.";
+      }
+      enum down {
+        description
+          "Disabled.";
+      }
+      enum testing {
+        description
+          "In some test mode.";
+      }
+      enum preparing-maintenance {
+        description
+          "The resource is disabled in the control plane to prepare
+           for a graceful shutdown for maintenance purposes.";
+        reference
+          "RFC 5817: Graceful Shutdown in MPLS and Generalized MPLS
+                     Traffic Engineering Networks";
+      }
+      enum maintenance {
+        description
+          "The resource is disabled in the data plane for maintenance
+           purposes.";
+      }
+      enum unknown {
+        description
+          "Status is unknown.";
+      }
+    }
+    description
+      "Defines a type representing the common states of a TE
+       resource.";
+  }
+
+  typedef te-bandwidth {
+    type string {
+      pattern '0[xX](0((\.0?)?[pP](\+)?0?|(\.0?))|'
+            + '1(\.([\da-fA-F]{0,5}[02468aAcCeE]?)?)?'
+            + '[pP](\+)?(12[0-7]|'
+            + '1[01]\d|0?\d?\d)?)|0[xX][\da-fA-F]{1,8}|\d+'
+            + '(,(0[xX](0((\.0?)?[pP](\+)?0?|(\.0?))|'
+            + '1(\.([\da-fA-F]{0,5}[02468aAcCeE]?)?)?'
+            + '[pP](\+)?(12[0-7]|'
+            + '1[01]\d|0?\d?\d)?)|0[xX][\da-fA-F]{1,8}|\d+))*';
+    }
+    description
+      "This is the generic bandwidth type.  It is a string containing
+       a list of numbers separated by commas, where each of these
+       numbers can be non-negative decimal, hex integer, or
+       hex float:
+
+       (dec | hex | float)[*(','(dec | hex | float))]
+
+       For the packet-switching type, the string encoding follows
+       the type 'bandwidth-ieee-float32' as defined in RFC 8294
+       (e.g., 0x1p10), where the units are in bytes per second.
+
+       For the Optical Transport Network (OTN) switching type,
+       a list of integers can be used, such as '0,2,3,1', indicating
+       two ODU0s and one ODU3.  ('ODU' stands for 'Optical Data
+       Unit'.)  For Dense Wavelength Division Multiplexing (DWDM),
+       a list of pairs of slot numbers and widths can be used,
+       such as '0,2,3,3', indicating a frequency slot 0 with
+       slot width 2 and a frequency slot 3 with slot width 3.
+       Canonically, the string is represented as all lowercase and in
+       hex, where the prefix '0x' precedes the hex number.";
+    reference
+      "RFC 8294: Common YANG Data Types for the Routing Area
+       ITU-T G.709: Interfaces for the optical transport network -
+                    Edition 6.0 (06/2020)";
+  }
+
+  typedef te-ds-class {
+    type uint8 {
+      range "0..7";
+    }
+    description
+      "The Differentiated Services Class-Type of traffic.";
+    reference
+      "RFC 4124: Protocol Extensions for Support of Diffserv-aware
+                 MPLS Traffic Engineering, Section 4.3.1";
+  }
+
+  typedef te-global-id {
+    type uint32;
+    description
+      "An identifier to uniquely identify an operator, which can be
+       either a provider or a client.
+
+       The definition of this type is taken from RFCs 6370 and 5003.
+
+       This attribute type is used solely to provide a globally
+       unique context for TE topologies.";
+    reference
+      "RFC 5003: Attachment Individual Identifier (AII) Types for
+                 Aggregation
+       RFC 6370: MPLS Transport Profile (MPLS-TP) Identifiers";
+  }
+
+  typedef te-hop-type {
+    type enumeration {
+      enum loose {
+        description
+          "A loose hop in an explicit path.";
+      }
+      enum strict {
+        description
+          "A strict hop in an explicit path.";
+      }
+    }
+    description
+      "Enumerated type for specifying loose or strict paths.";
+    reference
+      "RFC 3209: RSVP-TE: Extensions to RSVP for LSP Tunnels,
+                 Section 4.3.3";
+  }
+
+  typedef te-link-access-type {
+    type enumeration {
+      enum point-to-point {
+        description
+          "The link is point-to-point.";
+      }
+      enum multi-access {
+        description
+          "The link is multi-access, including broadcast and NBMA.";
+      }
+    }
+    description
+      "Defines a type representing the access type of a TE link.";
+    reference
+      "RFC 3630: Traffic Engineering (TE) Extensions to OSPF
+                 Version 2";
+  }
+
+  typedef te-label-direction {
+    type enumeration {
+      enum forward {
+        description
+          "Label allocated for the forward LSP direction.";
+      }
+      enum reverse {
+        description
+          "Label allocated for the reverse LSP direction.";
+      }
+    }
+    description
+      "Enumerated type for specifying the forward or reverse
+       label.";
+  }
+
+  typedef te-link-direction {
+    type enumeration {
+      enum incoming {
+        description
+          "The explicit route represents an incoming link on
+           a node.";
+      }
+      enum outgoing {
+        description
+          "The explicit route represents an outgoing link on
+           a node.";
+      }
+    }
+    description
+      "Enumerated type for specifying the direction of a link on
+       a node.";
+  }
+
+  typedef te-metric {
+    type uint32;
+    description
+      "TE metric.";
+    reference
+      "RFC 3785: Use of Interior Gateway Protocol (IGP) Metric as a
+                 second MPLS Traffic Engineering (TE) Metric";
+  }
+
+  typedef te-node-id {
+    type union {
+      type yang:dotted-quad;
+      type inet:ipv6-address-no-zone;
+    }
+    description
+      "A type representing the identifier for a node in a TE
+       topology.
+
+       The identifier is represented either as 4 octets in
+       dotted-quad notation, or as 16 octets in full, mixed,
+       shortened, or shortened-mixed IPv6 address notation.
+
+       This attribute MAY be mapped to the Router Address TLV
+       described in Section 2.4.1 of RFC 3630, the TE Router ID
+       described in Section 3 of RFC 6827, the Traffic Engineering
+       Router ID TLV described in Section 4.3 of RFC 5305, the TE
+       Router ID TLV described in Section 3.2.1 of RFC 6119, or the
+       IPv6 TE Router ID TLV described in Section 4.1 of RFC 6119.
+
+       The reachability of such a TE node MAY be achieved by a
+       mechanism such as that described in Section 6.2 of RFC 6827.";
+    reference
+      "RFC 3630: Traffic Engineering (TE) Extensions to OSPF
+                 Version 2, Section 2.4.1
+       RFC 5305: IS-IS Extensions for Traffic Engineering,
+                 Section 4.3
+       RFC 6119: IPv6 Traffic Engineering in IS-IS, Section 3.2.1
+       RFC 6827: Automatically Switched Optical Network (ASON)
+                 Routing for OSPFv2 Protocols, Section 3";
+  }
+
+  typedef te-oper-status {
+    type te-common-status;
+    description
+      "Defines a type representing the operational status of
+       a TE resource.";
+  }
+
+  typedef te-admin-status {
+    type te-common-status;
+    description
+      "Defines a type representing the administrative status of
+       a TE resource.";
+  }
+
+  typedef te-path-disjointness {
+    type bits {
+      bit node {
+        position 0;
+        description
+          "Node disjoint.";
+      }
+      bit link {
+        position 1;
+        description
+          "Link disjoint.";
+      }
+      bit srlg {
+        position 2;
+        description
+          "SRLG (Shared Risk Link Group) disjoint.";
+      }
+    }
+    description
+      "Type of the resource disjointness for a TE tunnel path.";
+    reference
+      "RFC 4872: RSVP-TE Extensions in Support of End-to-End
+                 Generalized Multi-Protocol Label Switching (GMPLS)
+                 Recovery";
+  }
+
+  typedef te-recovery-status {
+    type enumeration {
+      enum normal {
+        description
+          "Both the recovery span and the working span are fully
+           allocated and active, data traffic is being
+           transported over (or selected from) the working
+           span, and no trigger events are reported.";
+      }
+      enum recovery-started {
+        description
+          "The recovery action has been started but not completed.";
+      }
+      enum recovery-succeeded {
+        description
+          "The recovery action has succeeded.  The working span has
+           reported a failure/degrade condition, and the user traffic
+           is being transported (or selected) on the recovery span.";
+      }
+      enum recovery-failed {
+        description
+          "The recovery action has failed.";
+      }
+      enum reversion-started {
+        description
+          "The reversion has started.";
+      }
+      enum reversion-succeeded {
+        description
+          "The reversion action has succeeded.";
+      }
+      enum reversion-failed {
+        description
+          "The reversion has failed.";
+      }
+      enum recovery-unavailable {
+        description
+          "The recovery is unavailable, as a result of either an
+           operator's lockout command or a failure condition
+           detected on the recovery span.";
+      }
+      enum recovery-admin {
+        description
+          "The operator has issued a command to switch the user
+           traffic to the recovery span.";
+      }
+      enum wait-to-restore {
+        description
+          "The recovery domain is recovering from a failure/degrade
+           condition on the working span that is being controlled by
+           the Wait-to-Restore (WTR) timer.";
+      }
+    }
+    description
+      "Defines the status of a recovery action.";
+    reference
+      "RFC 6378: MPLS Transport Profile (MPLS-TP) Linear Protection
+       RFC 4427: Recovery (Protection and Restoration) Terminology
+                 for Generalized Multi-Protocol Label Switching
+                 (GMPLS)";
+  }
+
+  typedef te-template-name {
+    type string {
+      pattern '/?([a-zA-Z0-9\-_.]+)(/[a-zA-Z0-9\-_.]+)*';
+    }
+    description
+      "A type for the name of a TE node template or TE link
+       template.";
+  }
+
+  typedef te-topology-event-type {
+    type enumeration {
+      enum add {
+        value 0;
+        description
+          "A TE node or TE link has been added.";
+      }
+      enum remove {
+        value 1;
+        description
+          "A TE node or TE link has been removed.";
+      }
+      enum update {
+        value 2;
+        description
+          "A TE node or TE link has been updated.";
+      }
+    }
+    description
+      "TE event type for notifications.";
+  }
+
+  typedef te-topology-id {
+    type union {
+      type string {
+        length "0";
+        // empty string
+      }
+      type string {
+        pattern '([a-zA-Z0-9\-_.]+:)*'
+              + '/?([a-zA-Z0-9\-_.]+)(/[a-zA-Z0-9\-_.]+)*';
+      }
+    }
+    description
+      "An identifier for a topology.
+
+       It is optional to have one or more prefixes at the beginning,
+       separated by colons.  The prefixes can be 'network-types' as
+       defined in the 'ietf-network' module in RFC 8345, to help the
+       user better understand the topology before further inquiry
+       is made.";
+    reference
+      "RFC 8345: A YANG Data Model for Network Topologies";
+  }
+
+  typedef te-tp-id {
+    type union {
+      type uint32;
+      // Unnumbered
+      type inet:ip-address;
+      // IPv4 or IPv6 address
+    }
+    description
+      "An identifier for a TE link endpoint on a node.
+
+       This attribute is mapped to a local or remote link identifier
+       as defined in RFCs 3630 and 5305.";
+    reference
+      "RFC 3630: Traffic Engineering (TE) Extensions to OSPF
+                 Version 2
+       RFC 5305: IS-IS Extensions for Traffic Engineering";
+  }
+
+  typedef path-type {
+    type enumeration {
+      enum primary-path {
+        description
+          "Indicates that the TE path is a primary path.";
+      }
+      enum secondary-path {
+        description
+          "Indicates that the TE path is a secondary path.";
+      }
+      enum primary-reverse-path {
+        description
+          "Indicates that the TE path is a primary reverse path.";
+      }
+      enum secondary-reverse-path {
+        description
+          "Indicates that the TE path is a secondary reverse path.";
+      }
+    }
+    description
+      "The type of TE path, indicating whether a path is a primary, 
+       or a reverse primary, or a secondary, or a reverse secondary 
+       path.";
+  }
+
+  /* TE features */
+
+  feature p2mp-te {
+    description
+      "Indicates support for Point-to-Multipoint TE (P2MP-TE).";
+    reference
+      "RFC 4875: Extensions to Resource Reservation Protocol -
+                 Traffic Engineering (RSVP-TE) for
+                 Point-to-Multipoint TE Label Switched Paths (LSPs)";
+  }
+
+  feature frr-te {
+    description
+      "Indicates support for TE Fast Reroute (FRR).";
+    reference
+      "RFC 4090: Fast Reroute Extensions to RSVP-TE for LSP Tunnels";
+  }
+
+  feature extended-admin-groups {
+    description
+      "Indicates support for TE link extended administrative
+       groups.";
+    reference
+      "RFC 7308: Extended Administrative Groups in MPLS Traffic
+                 Engineering (MPLS-TE)";
+  }
+
+  feature named-path-affinities {
+    description
+      "Indicates support for named path affinities.";
+  }
+
+  feature named-extended-admin-groups {
+    description
+      "Indicates support for named extended administrative groups.";
+  }
+
+  feature named-srlg-groups {
+    description
+      "Indicates support for named SRLG groups.";
+  }
+
+  feature named-path-constraints {
+    description
+      "Indicates support for named path constraints.";
+  }
+
+  feature path-optimization-metric {
+    description
+      "Indicates support for path optimization metrics.";
+  }
+
+  feature path-optimization-objective-function {
+    description
+      "Indicates support for path optimization objective functions.";
+  }
+
+  /*
+   * Identities
+   */
+
+  identity lsp-provisioning-error-reason {
+    description
+      "Base identity for LSP provisioning errors.";
+  }
+
+  identity session-attributes-flags {
+    description
+      "Base identity for the RSVP-TE session attributes flags.";
+  }
+
+    identity local-protection-desired {
+      base session-attributes-flags;
+      description
+        "Local protection is desired.";
+      reference
+        "RFC 3209: RSVP-TE: Extensions to RSVP for LSP Tunnels,
+                  Section 4.7.1";
+    }
+
+    identity se-style-desired {
+      base session-attributes-flags;
+      description
+        "Shared explicit style, to allow the LSP to be established
+         and share resources with the old LSP.";
+      reference
+        "RFC 3209: RSVP-TE: Extensions to RSVP for LSP Tunnels";
+    }
+
+    identity local-recording-desired {
+      base session-attributes-flags;
+      description
+        "Label recording is desired.";
+      reference
+        "RFC 3209: RSVP-TE: Extensions to RSVP for LSP Tunnels,
+                  Section 4.7.1";
+    }
+
+    identity bandwidth-protection-desired {
+      base session-attributes-flags;
+      description
+        "Requests FRR bandwidth protection on LSRs, if present.";
+      reference
+        "RFC 4090: Fast Reroute Extensions to RSVP-TE for LSP
+                   Tunnels";
+    }
+
+    identity node-protection-desired {
+      base session-attributes-flags;
+      description
+        "Requests FRR node protection on LSRs, if present.";
+      reference
+        "RFC 4090: Fast Reroute Extensions to RSVP-TE for LSP
+                   Tunnels";
+    }
+
+    identity path-reevaluation-request {
+      base session-attributes-flags;
+      description
+        "This flag indicates that a path re-evaluation (of the
+         current path in use) is requested.  Note that this does
+         not trigger any LSP reroutes but instead just signals a
+         request to evaluate whether a preferable path exists.";
+      reference
+        "RFC 4736: Reoptimization of Multiprotocol Label Switching
+                  (MPLS) Traffic Engineering (TE) Loosely Routed
+                  Label Switched Path (LSP)";
+    }
+
+    identity soft-preemption-desired {
+      base session-attributes-flags;
+      description
+        "Soft preemption of LSP resources is desired.";
+      reference
+        "RFC 5712: MPLS Traffic Engineering Soft Preemption";
+    }
+
+  identity lsp-attributes-flags {
+    description
+      "Base identity for LSP attributes flags.";
+  }
+
+    identity end-to-end-rerouting-desired {
+      base lsp-attributes-flags;
+      description
+        "Indicates end-to-end rerouting behavior for an LSP
+         undergoing establishment.  This MAY also be used to
+         specify the behavior of end-to-end LSP recovery for
+         established LSPs.";
+      reference
+        "RFC 4920: Crankback Signaling Extensions for MPLS and GMPLS
+                   RSVP-TE
+         RFC 5420: Encoding of Attributes for MPLS LSP Establishment
+                   Using Resource Reservation Protocol Traffic
+                   Engineering (RSVP-TE)
+         RFC 7570: Label Switched Path (LSP) Attribute in the
+                   Explicit Route Object (ERO)";
+    }
+
+    identity boundary-rerouting-desired {
+      base lsp-attributes-flags;
+      description
+        "Indicates boundary rerouting behavior for an LSP undergoing
+         establishment.  This MAY also be used to specify
+         segment-based LSP recovery through nested crankback for
+         established LSPs.  The boundary Area Border Router (ABR) /
+         Autonomous System Border Router (ASBR) can decide to forward
+         the PathErr message upstream to either an upstream boundary
+         ABR/ASBR or the ingress LSR.  Alternatively, it can try to
+         select another egress boundary LSR.";
+      reference
+        "RFC 4920: Crankback Signaling Extensions for MPLS and GMPLS
+                   RSVP-TE
+         RFC 5420: Encoding of Attributes for MPLS LSP Establishment
+                   Using Resource Reservation Protocol Traffic
+                   Engineering (RSVP-TE)
+         RFC 7570: Label Switched Path (LSP) Attribute in the
+                   Explicit Route Object (ERO)";
+    }
+
+    identity segment-based-rerouting-desired {
+      base lsp-attributes-flags;
+      description
+        "Indicates segment-based rerouting behavior for an LSP
+         undergoing establishment.  This MAY also be used to specify
+         segment-based LSP recovery for established LSPs.";
+      reference
+        "RFC 4920: Crankback Signaling Extensions for MPLS and GMPLS
+                   RSVP-TE
+         RFC 5420: Encoding of Attributes for MPLS LSP Establishment
+                   Using Resource Reservation Protocol
+                   Traffic Engineering (RSVP-TE)
+         RFC 7570: Label Switched Path (LSP) Attribute in the
+                   Explicit Route Object (ERO)";
+    }
+
+    identity lsp-integrity-required {
+      base lsp-attributes-flags;
+      description
+        "Indicates that LSP integrity is required.";
+      reference
+        "RFC 4875: Extensions to Resource Reservation Protocol -
+                   Traffic Engineering (RSVP-TE) for
+                   Point-to-Multipoint TE Label Switched Paths (LSPs)
+         RFC 7570: Label Switched Path (LSP) Attribute in the
+                   Explicit Route Object (ERO)";
+    }
+
+    identity contiguous-lsp-desired {
+      base lsp-attributes-flags;
+      description
+        "Indicates that a contiguous LSP is desired.";
+      reference
+        "RFC 5151: Inter-Domain MPLS and GMPLS Traffic Engineering --
+                   Resource Reservation Protocol-Traffic Engineering
+                   (RSVP-TE) Extensions
+         RFC 7570: Label Switched Path (LSP) Attribute in the
+                   Explicit Route Object (ERO)";
+    }
+
+    identity lsp-stitching-desired {
+      base lsp-attributes-flags;
+      description
+        "Indicates that LSP stitching is desired.";
+      reference
+        "RFC 5150: Label Switched Path Stitching with Generalized
+                   Multiprotocol Label Switching Traffic Engineering
+                   (GMPLS TE)
+         RFC 7570: Label Switched Path (LSP) Attribute in the
+                   Explicit Route Object (ERO)";
+    }
+
+    identity pre-planned-lsp-flag {
+      base lsp-attributes-flags;
+      description
+        "Indicates that the LSP MUST be provisioned in the
+         control plane only.";
+      reference
+        "RFC 6001: Generalized MPLS (GMPLS) Protocol Extensions for
+                   Multi-Layer and Multi-Region Networks (MLN/MRN)
+         RFC 7570: Label Switched Path (LSP) Attribute in the
+                   Explicit Route Object (ERO)";
+    }
+
+    identity non-php-behavior-flag {
+      base lsp-attributes-flags;
+      description
+        "Indicates that non-PHP (non-Penultimate Hop Popping)
+         behavior for the LSP is desired.";
+      reference
+        "RFC 6511: Non-Penultimate Hop Popping Behavior and
+                   Out-of-Band Mapping for RSVP-TE Label Switched
+                   Paths
+         RFC 7570: Label Switched Path (LSP) Attribute in the
+                   Explicit Route Object (ERO)";
+    }
+
+    identity oob-mapping-flag {
+      base lsp-attributes-flags;
+      description
+        "Indicates that signaling of the egress binding information
+         is out of band (e.g., via the Border Gateway Protocol
+         (BGP)).";
+      reference
+        "RFC 6511: Non-Penultimate Hop Popping Behavior and
+                   Out-of-Band Mapping for RSVP-TE Label Switched
+                   Paths
+         RFC 7570: Label Switched Path (LSP) Attribute in the
+                   Explicit Route Object (ERO)";
+    }
+
+    identity entropy-label-capability {
+      base lsp-attributes-flags;
+      description
+        "Indicates entropy label capability.";
+      reference
+        "RFC 6790: The Use of Entropy Labels in MPLS Forwarding
+         RFC 7570: Label Switched Path (LSP) Attribute in the
+                   Explicit Route Object (ERO)";
+    }
+
+    identity oam-mep-entity-desired {
+      base lsp-attributes-flags;
+      description
+        "OAM Maintenance Entity Group End Point (MEP) entities
+         desired.";
+      reference
+        "RFC 7260: GMPLS RSVP-TE Extensions for Operations,
+                   Administration, and Maintenance (OAM)
+                   Configuration";
+    }
+
+    identity oam-mip-entity-desired {
+      base lsp-attributes-flags;
+      description
+        "OAM Maintenance Entity Group Intermediate Points (MIP)
+         entities desired.";
+      reference
+        "RFC 7260: GMPLS RSVP-TE Extensions for Operations,
+                   Administration, and Maintenance (OAM)
+                   Configuration";
+    }
+
+    identity srlg-collection-desired {
+      base lsp-attributes-flags;
+      description
+        "SRLG collection desired.";
+      reference
+        "RFC 7570: Label Switched Path (LSP) Attribute in the
+                   Explicit Route Object (ERO)
+         RFC 8001: RSVP-TE Extensions for Collecting Shared Risk
+                   Link Group (SRLG) Information";
+    }
+
+    identity loopback-desired {
+      base lsp-attributes-flags;
+      description
+        "This flag indicates that a particular node on the LSP is
+         required to enter loopback mode.  This can also be
+         used to specify the loopback state of the node.";
+      reference
+        "RFC 7571: GMPLS RSVP-TE Extensions for Lock Instruct and
+                   Loopback";
+    }
+
+    identity p2mp-te-tree-eval-request {
+      base lsp-attributes-flags;
+      description
+        "P2MP-TE tree re-evaluation request.";
+      reference
+        "RFC 8149: RSVP Extensions for Reoptimization of Loosely
+                   Routed Point-to-Multipoint Traffic Engineering
+                   Label Switched Paths (LSPs)";
+    }
+
+    identity rtm-set-desired {
+      base lsp-attributes-flags;
+      description
+        "Residence Time Measurement (RTM) attribute flag requested.";
+      reference
+        "RFC 8169: Residence Time Measurement in MPLS Networks";
+    }
+
+  identity link-protection-type {
+    description
+      "Base identity for the link protection type.";
+  }
+
+    identity link-protection-unprotected {
+      base link-protection-type;
+      description
+        "Unprotected link type.";
+      reference
+        "RFC 4872: RSVP-TE Extensions in Support of End-to-End
+                   Generalized Multi-Protocol Label Switching (GMPLS)
+                   Recovery";
+    }
+
+    identity link-protection-extra-traffic {
+      base link-protection-type;
+      description
+        "Extra-Traffic protected link type.";
+      reference
+        "RFC 4872: RSVP-TE Extensions in Support of End-to-End
+                   Generalized Multi-Protocol Label Switching (GMPLS)
+                   Recovery";
+    }
+
+    identity link-protection-shared {
+      base link-protection-type;
+      description
+        "Shared protected link type.";
+      reference
+        "RFC 4872: RSVP-TE Extensions in Support of End-to-End
+                   Generalized Multi-Protocol Label Switching (GMPLS)
+                   Recovery";
+    }
+
+    identity link-protection-1-for-1 {
+      base link-protection-type;
+      description
+        "One-for-one (1:1) protected link type.";
+      reference
+        "RFC 4872: RSVP-TE Extensions in Support of End-to-End
+                   Generalized Multi-Protocol Label Switching (GMPLS)
+                   Recovery";
+    }
+
+    identity link-protection-1-plus-1 {
+      base link-protection-type;
+      description
+        "One-plus-one (1+1) protected link type.";
+      reference
+        "RFC 4872: RSVP-TE Extensions in Support of End-to-End
+                   Generalized Multi-Protocol Label Switching (GMPLS)
+                   Recovery";
+    }
+
+    identity link-protection-enhanced {
+      base link-protection-type;
+      description
+        "A compound link protection type derived from the underlay
+         TE tunnel protection configuration supporting the TE link.";
+    }
+
+  identity association-type {
+    description
+      "Base identity for the tunnel association.";
+  }
+
+    identity association-type-recovery {
+      base association-type;
+      description
+        "Association type for recovery, used to associate LSPs of the
+         same tunnel for recovery.";
+      reference
+        "RFC 4872: RSVP-TE Extensions in Support of End-to-End
+                   Generalized Multi-Protocol Label Switching (GMPLS)
+                   Recovery
+         RFC 6780: RSVP ASSOCIATION Object Extensions";
+    }
+
+    identity association-type-resource-sharing {
+      base association-type;
+      description
+        "Association type for resource sharing, used to enable
+         resource sharing during make-before-break.";
+      reference
+        "RFC 4873: GMPLS Segment Recovery
+         RFC 6780: RSVP ASSOCIATION Object Extensions";
+    }
+
+    identity association-type-double-sided-bidir {
+      base association-type;
+      description
+        "Association type for double-sided bidirectional LSPs,
+         used to associate two LSPs of two tunnels that are
+         independently configured on either endpoint.";
+      reference
+        "RFC 7551: RSVP-TE Extensions for Associated Bidirectional
+                   Label Switched Paths (LSPs)";
+    }
+
+    identity association-type-single-sided-bidir {
+      base association-type;
+      description
+        "Association type for single-sided bidirectional LSPs,
+         used to associate two LSPs of two tunnels, where one
+         tunnel is configured on one side/endpoint and the other
+         tunnel is dynamically created on the other endpoint.";
+      reference
+        "RFC 6780: RSVP ASSOCIATION Object Extensions
+         RFC 7551: RSVP-TE Extensions for Associated Bidirectional
+                   Label Switched Paths (LSPs)";
+    }
+
+    identity association-type-diversity {
+      base association-type;
+      description
+        "Association Type diversity used to associate LSPs whose
+         paths are to be diverse from each other.";
+      reference
+        "RFC 8800: Path Computation Element Communication Protocol
+                   (PCEP) Extension for Label Switched Path (LSP)
+                   Diversity Constraint Signaling";
+    }
+
+  identity objective-function-type {
+    description
+      "Base identity for path objective function types.";
+  }
+
+    identity of-minimize-cost-path {
+      base objective-function-type;
+      description
+        "Objective function for minimizing path cost.";
+      reference
+        "RFC 5541: Encoding of Objective Functions in the Path
+                   Computation Element Communication Protocol
+                   (PCEP)";
+    }
+
+    identity of-minimize-load-path {
+      base objective-function-type;
+      description
+        "Objective function for minimizing the load on one or more
+         paths.";
+      reference
+        "RFC 5541: Encoding of Objective Functions in the Path
+                   Computation Element Communication Protocol
+                   (PCEP)";
+    }
+
+    identity of-maximize-residual-bandwidth {
+      base objective-function-type;
+      description
+        "Objective function for maximizing residual bandwidth.";
+      reference
+        "RFC 5541: Encoding of Objective Functions in the Path
+                   Computation Element Communication Protocol
+                   (PCEP)";
+    }
+
+    identity of-minimize-agg-bandwidth-consumption {
+      base objective-function-type;
+      status obsolete;
+      description
+        "Objective function for minimizing aggregate bandwidth
+         consumption.
+
+         This identity has been obsoleted: the
+         'svec-of-minimize-agg-bandwidth-consumption' identity SHOULD
+         be used instead.";
+      reference
+        "RFC 5541: Encoding of Objective Functions in the Path
+                   Computation Element Communication Protocol
+                   (PCEP)";
+    }
+
+    identity of-minimize-load-most-loaded-link {
+      base objective-function-type;
+      status obsolete;
+      description
+        "Objective function for minimizing the load on the link that
+         is carrying the highest load.
+
+         This identity has been obsoleted: the
+         'svec-of-minimize-load-most-loaded-link' identity SHOULD
+         be used instead.";
+      reference
+        "RFC 5541: Encoding of Objective Functions in the Path
+                   Computation Element Communication Protocol
+                   (PCEP)";
+    }
+
+    identity of-minimize-cost-path-set {
+      base objective-function-type;
+      status obsolete;
+      description
+        "Objective function for minimizing the cost on a path set.
+
+         This identity has been obsoleted: the
+         'svec-of-minimize-cost-path-set' identity SHOULD
+         be used instead.";
+      reference
+        "RFC 5541: Encoding of Objective Functions in the Path
+                   Computation Element Communication Protocol
+                   (PCEP)";
+    }
+
+  identity path-computation-method {
+    description
+      "Base identity for supported path computation mechanisms.";
+  }
+
+    identity path-locally-computed {
+      base path-computation-method;
+      description
+        "Indicates a constrained-path LSP in which the
+         path is computed by the local LER.";
+      reference
+        "RFC 9522: Overview and Principles of Internet Traffic
+                   Engineering, Section 4.4";
+    }
+
+    identity path-externally-queried {
+      base path-computation-method;
+      description
+        "Constrained-path LSP in which the path is obtained by
+         querying an external source, such as a PCE server.
+         In the case that an LSP is defined to be externally queried,
+         it may also have associated explicit definitions (provided
+         to the external source to aid computation).  The path that
+         is returned by the external source may require further local
+         computation on the device.";
+      reference
+        "RFC 9522: Overview and Principles of Internet Traffic
+                   Engineering
+         RFC 4657: Path Computation Element (PCE) Communication
+                   Protocol Generic Requirements";
+    }
+
+    identity path-explicitly-defined {
+      base path-computation-method;
+      description
+        "Constrained-path LSP in which the path is
+         explicitly specified as a collection of strict and/or loose
+         hops.";
+      reference
+        "RFC 3209: RSVP-TE: Extensions to RSVP for LSP Tunnels
+         RFC 9522: Overview and Principles of Internet Traffic
+                   Engineering";
+    }
+
+  identity lsp-metric-type {
+    description
+      "Base identity for the LSP metric specification types.";
+  }
+
+    identity lsp-metric-relative {
+      base lsp-metric-type;
+      description
+        "The metric specified for the LSPs to which this identity
+         refers is specified as a value relative to the IGP metric
+         cost to the LSP's tail end.";
+      reference
+        "RFC 4657: Path Computation Element (PCE) Communication
+                   Protocol Generic Requirements";
+    }
+
+    identity lsp-metric-absolute {
+      base lsp-metric-type;
+      description
+        "The metric specified for the LSPs to which this identity
+         refers is specified as an absolute value.";
+      reference
+        "RFC 4657: Path Computation Element (PCE) Communication
+                   Protocol Generic Requirements";
+    }
+
+    identity lsp-metric-inherited {
+      base lsp-metric-type;
+      description
+        "The metric for the LSPs to which this identity refers is
+         not specified explicitly; rather, it is directly inherited
+         from the IGP cost.";
+      reference
+        "RFC 4657: Path Computation Element (PCE) Communication
+                   Protocol Generic Requirements";
+    }
+
+  identity te-tunnel-type {
+    description
+      "Base identity from which specific tunnel types are derived.";
+  }
+
+    identity te-tunnel-p2p {
+      base te-tunnel-type;
+      description
+        "TE Point-to-Point (P2P) tunnel type.";
+      reference
+        "RFC 3209: RSVP-TE: Extensions to RSVP for LSP Tunnels";
+    }
+
+    identity te-tunnel-p2mp {
+      base te-tunnel-type;
+      description
+        "TE P2MP tunnel type.";
+      reference
+        "RFC 4875: Extensions to Resource Reservation Protocol -
+                   Traffic Engineering (RSVP-TE) for
+                   Point-to-Multipoint TE Label Switched Paths
+                   (LSPs)";
+    }
+
+  identity tunnel-action-type {
+    description
+      "Base identity from which specific tunnel action types
+       are derived.";
+  }
+
+    identity tunnel-action-resetup {
+      base tunnel-action-type;
+      description
+        "TE tunnel action that tears down the tunnel's current LSP
+         (if any) and attempts to re-establish a new LSP.";
+    }
+
+    identity tunnel-action-reoptimize {
+      base tunnel-action-type;
+      description
+        "TE tunnel action that reoptimizes the placement of the
+         tunnel LSP(s).";
+    }
+
+    identity tunnel-action-switchpath {
+      base tunnel-action-type;
+      description
+        "TE tunnel action that switches the tunnel's LSP to use the
+         specified path.";
+    }
+
+  identity te-action-result {
+    description
+      "Base identity from which specific TE action results
+       are derived.";
+  }
+
+    identity te-action-success {
+      base te-action-result;
+      description
+        "TE action was successful.";
+    }
+
+    identity te-action-fail {
+      base te-action-result;
+      description
+        "TE action failed.";
+    }
+
+    identity tunnel-action-inprogress {
+      base te-action-result;
+      description
+        "TE action is in progress.";
+    }
+
+  identity tunnel-admin-state-type {
+    description
+      "Base identity for TE tunnel administrative states.";
+  }
+
+    identity tunnel-admin-state-up {
+      base tunnel-admin-state-type;
+      description
+        "Tunnel's administrative state is up.";
+    }
+
+    identity tunnel-admin-state-down {
+      base tunnel-admin-state-type;
+      description
+        "Tunnel's administrative state is down.";
+    }
+
+    identity tunnel-admin-state-auto {
+      base tunnel-admin-state-type;
+      description
+        "Tunnel administrative auto state. The administrative status
+         in state datastore transitions to 'tunnel-admin-up' when the
+         tunnel used by the client layer, and to 'tunnel-admin-down'
+         when it is not used by the client layer.";
+    }
+
+  identity tunnel-state-type {
+    description
+      "Base identity for TE tunnel states.";
+  }
+
+    identity tunnel-state-up {
+      base tunnel-state-type;
+      description
+        "Tunnel's state is up.";
+    }
+
+    identity tunnel-state-down {
+      base tunnel-state-type;
+      description
+        "Tunnel's state is down.";
+    }
+
+  identity lsp-state-type {
+    description
+      "Base identity for TE LSP states.";
+  }
+
+    identity lsp-path-computing {
+      base lsp-state-type;
+      description
+        "State path computation is in progress.";
+    }
+
+    identity lsp-path-computation-ok {
+      base lsp-state-type;
+      description
+        "State path computation was successful.";
+    }
+
+    identity lsp-path-computation-failed {
+      base lsp-state-type;
+      description
+        "State path computation failed.";
+    }
+
+    identity lsp-state-setting-up {
+      base lsp-state-type;
+      description
+        "State is being set up.";
+    }
+
+    identity lsp-state-setup-ok {
+      base lsp-state-type;
+      description
+        "State setup was successful.";
+    }
+
+    identity lsp-state-setup-failed {
+      base lsp-state-type;
+      description
+        "State setup failed.";
+    }
+
+    identity lsp-state-up {
+      base lsp-state-type;
+      description
+        "State is up.";
+    }
+
+    identity lsp-state-tearing-down {
+      base lsp-state-type;
+      description
+        "State is being torn down.";
+    }
+
+    identity lsp-state-down {
+      base lsp-state-type;
+      description
+        "State is down.";
+    }
+
+  identity path-invalidation-action-type {
+    description
+      "Base identity for TE path invalidation action types.";
+  }
+
+    identity path-invalidation-action-drop {
+      base path-invalidation-action-type;
+      description
+        "Upon invalidation of the TE tunnel path, the tunnel remains
+         valid, but any packet mapped over the tunnel is dropped.";
+      reference
+        "RFC 3209: RSVP-TE: Extensions to RSVP for LSP Tunnels,
+                   Section 2.5";
+    }
+
+    identity path-invalidation-action-teardown {
+      base path-invalidation-action-type;
+      description
+        "TE path invalidation action teardown.";
+      reference
+        "RFC 3209: RSVP-TE: Extensions to RSVP for LSP Tunnels,
+                   Section 2.5";
+    }
+
+  identity lsp-restoration-type {
+    description
+      "Base identity from which LSP restoration types are derived.";
+  }
+
+    identity lsp-restoration-restore-none {
+      base lsp-restoration-type;
+      description
+        "No LSP affected by a failure is restored.";
+    }
+
+    identity lsp-restoration-restore-any {
+      base lsp-restoration-type;
+      description
+        "Any LSP affected by a failure is restored.";
+    }
+
+    identity lsp-restoration-restore-all {
+      base lsp-restoration-type;
+      description
+        "Affected LSPs are restored after all LSPs of the tunnel are
+         broken.";
+    }
+
+  identity restoration-scheme-type {
+    description
+      "Base identity for LSP restoration schemes.";
+  }
+
+    identity restoration-scheme-rerouting {
+      base restoration-scheme-type;
+      description
+        "Restoration LSP is computed after the failure detection.
+
+         This restoration scheme is also known as
+         'Full LSP Re-routing.'";
+      reference
+        "RFC 4872: RSVP-TE Extensions in Support of End-to-End
+                   Generalized Multi-Protocol Label Switching (GMPLS)
+                   Recovery";
+    }
+
+    identity restoration-scheme-preconfigured {
+      base restoration-scheme-type;
+      description
+        "Restoration LSP is preconfigured prior to the failure.";
+      reference
+        "RFC 4872: RSVP-TE Extensions in Support of End-to-End
+                  Generalized Multi-Protocol Label Switching (GMPLS)
+                  Recovery";
+    }
+
+    identity restoration-scheme-precomputed {
+      base restoration-scheme-type;
+      description
+        "Restoration LSP is precomputed prior to the failure.";
+      reference
+        "RFC 4872: RSVP-TE Extensions in Support of End-to-End
+                  Generalized Multi-Protocol Label Switching (GMPLS)
+                  Recovery";
+    }
+
+    identity restoration-scheme-presignaled {
+      base restoration-scheme-type;
+      description
+        "Restoration LSP is presignaled prior to the failure.";
+      reference
+        "RFC 4872: RSVP-TE Extensions in Support of End-to-End
+                  Generalized Multi-Protocol Label Switching (GMPLS)
+                  Recovery";
+    }
+
+  identity lsp-protection-type {
+    description
+      "Base identity from which LSP protection types are derived.";
+    reference
+      "RFC 4872: RSVP-TE Extensions in Support of End-to-End
+                 Generalized Multi-Protocol Label Switching (GMPLS)
+                 Recovery";
+  }
+
+    identity lsp-protection-unprotected {
+      base lsp-protection-type;
+      description
+        "'Unprotected' LSP protection type.";
+      reference
+        "RFC 4872: RSVP-TE Extensions in Support of End-to-End
+                   Generalized Multi-Protocol Label Switching (GMPLS)
+                   Recovery";
+    }
+
+    identity lsp-protection-reroute-extra {
+      base lsp-protection-type;
+      status obsolete;
+      description
+        "'(Full) Rerouting' LSP protection type.
+
+         This identity has been obsoleted: the
+         'restoration-scheme-rerouting' identity SHOULD be used
+         instead.";
+      reference
+        "RFC 4872: RSVP-TE Extensions in Support of End-to-End
+                   Generalized Multi-Protocol Label Switching (GMPLS)
+                   Recovery";
+    }
+
+    identity lsp-protection-reroute {
+      base lsp-protection-type;
+      status obsolete;
+      description
+        "'Rerouting without Extra-Traffic' LSP protection type.
+
+         This identity has been obsoleted: the
+         'restoration-scheme-rerouting' identity SHOULD be used
+         instead.";
+      reference
+        "RFC 4872: RSVP-TE Extensions in Support of End-to-End
+                   Generalized Multi-Protocol Label Switching (GMPLS)
+                   Recovery";
+    }
+
+    identity lsp-protection-1-for-n {
+      base lsp-protection-type;
+      description
+        "'1:N Protection with Extra-Traffic' LSP protection type.";
+      reference
+        "RFC 4872: RSVP-TE Extensions in Support of End-to-End
+                   Generalized Multi-Protocol Label Switching (GMPLS)
+                   Recovery";
+    }
+
+    identity lsp-protection-1-for-1 {
+      base lsp-protection-type;
+      description
+        "LSP protection '1:1 Protection Type'.";
+      reference
+        "RFC 4872: RSVP-TE Extensions in Support of End-to-End
+                   Generalized Multi-Protocol Label Switching (GMPLS)
+                   Recovery";
+    }
+
+    identity lsp-protection-unidir-1-plus-1 {
+      base lsp-protection-type;
+      description
+        "'1+1 Unidirectional Protection' LSP protection type.";
+      reference
+        "RFC 4872: RSVP-TE Extensions in Support of End-to-End
+                   Generalized Multi-Protocol Label Switching (GMPLS)
+                   Recovery";
+    }
+
+    identity lsp-protection-bidir-1-plus-1 {
+      base lsp-protection-type;
+      description
+        "'1+1 Bidirectional Protection' LSP protection type.";
+      reference
+        "RFC 4872: RSVP-TE Extensions in Support of End-to-End
+                   Generalized Multi-Protocol Label Switching (GMPLS)
+                   Recovery";
+    }
+
+    identity lsp-protection-extra-traffic {
+      base lsp-protection-type;
+      description
+        "Extra-Traffic LSP protection type.";
+      reference
+        "RFC 4872: RSVP-TE Extensions in Support of End-to-End
+                   Generalized Multi-Protocol Label Switching (GMPLS)
+                   Recovery";
+    }
+
+  identity lsp-protection-state {
+    description
+      "Base identity of protection states for reporting purposes.";
+  }
+
+    identity normal {
+      base lsp-protection-state;
+      description
+        "Normal state.";
+      reference
+        "RFC 6378: MPLS Transport Profile (MPLS-TP) Linear Protection
+         RFC 4427: Recovery (Protection and Restoration) Terminology
+                   for Generalized Multi-Protocol Label Switching
+                   (GMPLS)";
+    }
+
+    identity signal-fail-of-protection {
+      base lsp-protection-state;
+      description
+        "The protection transport entity has a signal fail condition
+         that is of higher priority than the forced switchover
+         command.";
+      reference
+        "RFC 6378: MPLS Transport Profile (MPLS-TP) Linear Protection
+         RFC 4427: Recovery (Protection and Restoration) Terminology
+                   for Generalized Multi-Protocol Label Switching
+                   (GMPLS)";
+    }
+
+    identity lockout-of-protection {
+      base lsp-protection-state;
+      description
+        "A Loss of Protection (LoP) command is active.";
+      reference
+        "RFC 6378: MPLS Transport Profile (MPLS-TP) Linear Protection
+         RFC 4427: Recovery (Protection and Restoration) Terminology
+                   for Generalized Multi-Protocol Label Switching
+                   (GMPLS)";
+    }
+
+    identity forced-switch {
+      base lsp-protection-state;
+      description
+        "A forced switchover command is active.";
+      reference
+        "RFC 6378: MPLS Transport Profile (MPLS-TP) Linear Protection
+         RFC 4427: Recovery (Protection and Restoration) Terminology
+                   for Generalized Multi-Protocol Label Switching
+                   (GMPLS)";
+    }
+
+    identity signal-fail {
+      base lsp-protection-state;
+      description
+        "There is a signal fail condition on either the working path
+         or the protection path.";
+      reference
+        "RFC 6378: MPLS Transport Profile (MPLS-TP) Linear Protection
+         RFC 4427: Recovery (Protection and Restoration) Terminology
+                   for Generalized Multi-Protocol Label Switching
+                   (GMPLS)";
+    }
+
+    identity signal-degrade {
+      base lsp-protection-state;
+      description
+        "There is a signal degrade condition on either the working
+         path or the protection path.";
+      reference
+        "RFC 6378: MPLS Transport Profile (MPLS-TP) Linear Protection
+         RFC 4427: Recovery (Protection and Restoration) Terminology
+                   for Generalized Multi-Protocol Label Switching
+                   (GMPLS)";
+    }
+
+    identity manual-switch {
+      base lsp-protection-state;
+      description
+        "A manual switchover command is active.";
+      reference
+        "RFC 6378: MPLS Transport Profile (MPLS-TP) Linear Protection
+         RFC 4427: Recovery (Protection and Restoration) Terminology
+                   for Generalized Multi-Protocol Label Switching
+                   (GMPLS)";
+    }
+
+    identity wait-to-restore {
+      base lsp-protection-state;
+      description
+        "A Wait-to-Restore (WTR) timer is running.";
+      reference
+        "RFC 6378: MPLS Transport Profile (MPLS-TP) Linear Protection
+         RFC 4427: Recovery (Protection and Restoration) Terminology
+                   for Generalized Multi-Protocol Label Switching
+                   (GMPLS)";
+    }
+
+    identity do-not-revert {
+      base lsp-protection-state;
+      description
+        "A Do Not Revert (DNR) condition is active because of
+         non-revertive behavior.";
+      reference
+        "RFC 6378: MPLS Transport Profile (MPLS-TP) Linear Protection
+         RFC 4427: Recovery (Protection and Restoration) Terminology
+                   for Generalized Multi-Protocol Label Switching
+                   (GMPLS)";
+    }
+
+    identity failure-of-protocol {
+      base lsp-protection-state;
+      description
+        "LSP protection is not working because of a protocol failure
+         condition.";
+      reference
+        "RFC 7271: MPLS Transport Profile (MPLS-TP) Linear Protection
+                   to Match the Operational Expectations of
+                   Synchronous Digital Hierarchy, Optical Transport
+                   Network, and Ethernet Transport Network Operators
+         RFC 4427: Recovery (Protection and Restoration) Terminology
+                   for Generalized Multi-Protocol Label Switching
+                   (GMPLS)";
+    }
+
+  identity protection-external-commands {
+    description
+      "Base identity from which protection-related external commands
+       used for troubleshooting purposes are derived.";
+  }
+
+    identity action-freeze {
+      base protection-external-commands;
+      description
+        "A temporary configuration action initiated by an operator
+         command that prevents any switchover action from being taken
+         and, as such, freezes the current state.";
+      reference
+        "RFC 7271: MPLS Transport Profile (MPLS-TP) Linear Protection
+                   to Match the Operational Expectations of
+                   Synchronous Digital Hierarchy, Optical Transport
+                   Network, and Ethernet Transport Network Operators
+         RFC 4427: Recovery (Protection and Restoration) Terminology
+                   for Generalized Multi-Protocol Label Switching
+                   (GMPLS)";
+    }
+
+    identity clear-freeze {
+      base protection-external-commands;
+      description
+        "An action that clears the active freeze state.";
+      reference
+        "RFC 7271: MPLS Transport Profile (MPLS-TP) Linear Protection
+                   to Match the Operational Expectations of
+                   Synchronous Digital Hierarchy, Optical Transport
+                   Network, and Ethernet Transport Network Operators
+         RFC 4427: Recovery (Protection and Restoration) Terminology
+                   for Generalized Multi-Protocol Label Switching
+                   (GMPLS)";
+    }
+
+    identity action-lockout-of-normal {
+      base protection-external-commands;
+      description
+        "A temporary configuration action initiated by an operator
+         command to ensure that the normal traffic is not allowed
+         to use the protection transport entity.";
+      reference
+        "RFC 4872: RSVP-TE Extensions in Support of End-to-End
+                   Generalized Multi-Protocol Label Switching (GMPLS)
+                   Recovery
+         RFC 4427: Recovery (Protection and Restoration) Terminology
+                  for Generalized Multi-Protocol Label Switching
+                  (GMPLS)";
+    }
+
+    identity clear-lockout-of-normal {
+      base protection-external-commands;
+      description
+        "An action that clears the active lockout of the
+         normal state.";
+      reference
+        "RFC 4872: RSVP-TE Extensions in Support of End-to-End
+                   Generalized Multi-Protocol Label Switching (GMPLS)
+                   Recovery
+         RFC 4427: Recovery (Protection and Restoration) Terminology
+                  for Generalized Multi-Protocol Label Switching
+                  (GMPLS)";
+    }
+
+    identity action-lockout-of-protection {
+      base protection-external-commands;
+      description
+        "A temporary configuration action initiated by an operator
+         command to ensure that the protection transport entity is
+         temporarily not available to transport a traffic signal
+         (either normal or Extra-Traffic).";
+      reference
+        "RFC 4872: RSVP-TE Extensions in Support of End-to-End
+                   Generalized Multi-Protocol Label Switching (GMPLS)
+                   Recovery
+         RFC 4427: Recovery (Protection and Restoration) Terminology
+                  for Generalized Multi-Protocol Label Switching
+                  (GMPLS)";
+    }
+
+    identity action-forced-switch {
+      base protection-external-commands;
+      description
+        "A switchover action initiated by an operator command to
+         switch the Extra-Traffic signal, the normal traffic signal,
+         or the null signal to the protection transport entity,
+         unless a switchover command of equal or higher priority is
+         in effect.";
+      reference
+        "RFC 4872: RSVP-TE Extensions in Support of End-to-End
+                   Generalized Multi-Protocol Label Switching (GMPLS)
+                   Recovery
+         RFC 4427: Recovery (Protection and Restoration) Terminology
+                  for Generalized Multi-Protocol Label Switching
+                  (GMPLS)";
+    }
+
+    identity action-manual-switch {
+      base protection-external-commands;
+      description
+        "A switchover action initiated by an operator command to
+         switch the Extra-Traffic signal, the normal traffic signal,
+         or the null signal to the protection transport entity,
+         unless a fault condition exists on other transport entities
+         or a switchover command of equal or higher priority is in
+         effect.";
+      reference
+        "RFC 4872: RSVP-TE Extensions in Support of End-to-End
+                   Generalized Multi-Protocol Label Switching (GMPLS)
+                   Recovery
+         RFC 4427: Recovery (Protection and Restoration) Terminology
+                  for Generalized Multi-Protocol Label Switching
+                  (GMPLS)";
+    }
+
+    identity action-exercise {
+      base protection-external-commands;
+      description
+        "An action that starts testing whether or not Automatic 
+        Protection Switching (APS) communication is operating 
+        correctly.  It is of lower priority than any
+        other state or command.";
+      reference
+        "RFC 7271: MPLS Transport Profile (MPLS-TP) Linear Protection
+                   to Match the Operational Expectations of
+                   Synchronous Digital Hierarchy, Optical Transport
+                   Network, and Ethernet Transport Network Operators
+         RFC 4427: Recovery (Protection and Restoration) Terminology
+                   for Generalized Multi-Protocol Label Switching
+                   (GMPLS)";
+    }
+
+    identity clear {
+      base protection-external-commands;
+      description
+        "An action that clears the active near-end lockout of a
+         protection, forced switchover, manual switchover,
+         Wait-to-Restore (WTR) state, or exercise command.";
+      reference
+        "RFC 6378: MPLS Transport Profile (MPLS-TP) Linear Protection
+         RFC 4427: Recovery (Protection and Restoration) Terminology
+                   for Generalized Multi-Protocol Label Switching
+                   (GMPLS)";
+    }
+
+  identity switching-capabilities {
+    description
+      "Base identity for interface switching capabilities.";
+    reference
+      "RFC 3471: Generalized Multi-Protocol Label Switching (GMPLS)
+                 Signaling Functional Description";
+  }
+
+    identity switching-psc1 {
+      base switching-capabilities;
+      description
+        "Packet-Switch Capable-1 (PSC-1).";
+      reference
+        "RFC 3471: Generalized Multi-Protocol Label Switching (GMPLS)
+                   Signaling Functional Description";
+    }
+
+    identity switching-evpl {
+      base switching-capabilities;
+      description
+        "Ethernet Virtual Private Line (EVPL).";
+      reference
+        "RFC 6004: Generalized MPLS (GMPLS) Support for Metro
+                   Ethernet Forum and G.8011 Ethernet Service
+                   Switching";
+    }
+
+    identity switching-l2sc {
+      base switching-capabilities;
+      description
+        "Layer-2 Switch Capable (L2SC).";
+      reference
+        "RFC 3471: Generalized Multi-Protocol Label Switching (GMPLS)
+                   Signaling Functional Description";
+    }
+
+    identity switching-tdm {
+      base switching-capabilities;
+      description
+        "Time-Division-Multiplex Capable (TDM).";
+      reference
+        "RFC 3471: Generalized Multi-Protocol Label Switching (GMPLS)
+                   Signaling Functional Description";
+    }
+
+    identity switching-otn {
+      base switching-capabilities;
+      description
+        "OTN-TDM capable.";
+      reference
+        "RFC 7138: Traffic Engineering Extensions to OSPF for GMPLS
+                  Control of Evolving G.709 Optical Transport
+                  Networks";
+    }
+
+    identity switching-dcsc {
+      base switching-capabilities;
+      description
+        "Data Channel Switching Capable (DCSC).";
+      reference
+        "RFC 6002: Generalized MPLS (GMPLS) Data Channel
+                   Switching Capable (DCSC) and Channel Set Label
+                   Extensions";
+    }
+
+    identity switching-lsc {
+      base switching-capabilities;
+      description
+        "Lambda-Switch Capable (LSC).";
+      reference
+        "RFC 3471: Generalized Multi-Protocol Label Switching (GMPLS)
+                   Signaling Functional Description";
+    }
+
+    identity switching-fsc {
+      base switching-capabilities;
+      description
+        "Fiber-Switch Capable (FSC).";
+      reference
+        "RFC 3471: Generalized Multi-Protocol Label Switching (GMPLS)
+                   Signaling Functional Description";
+    }
+
+  identity lsp-encoding-types {
+    description
+      "Base identity for encoding types.";
+    reference
+      "RFC 3471: Generalized Multi-Protocol Label Switching (GMPLS)
+                 Signaling Functional Description";
+  }
+
+    identity lsp-encoding-packet {
+      base lsp-encoding-types;
+      description
+        "Packet LSP encoding.";
+      reference
+        "RFC 3471: Generalized Multi-Protocol Label Switching (GMPLS)
+                   Signaling Functional Description";
+    }
+
+    identity lsp-encoding-ethernet {
+      base lsp-encoding-types;
+      description
+        "Ethernet LSP encoding.";
+      reference
+        "RFC 3471: Generalized Multi-Protocol Label Switching (GMPLS)
+                   Signaling Functional Description";
+    }
+
+    identity lsp-encoding-pdh {
+      base lsp-encoding-types;
+      description
+        "ANSI/ETSI PDH LSP encoding.";
+      reference
+        "RFC 3471: Generalized Multi-Protocol Label Switching (GMPLS)
+                   Signaling Functional Description";
+    }
+
+    identity lsp-encoding-sdh {
+      base lsp-encoding-types;
+      description
+        "SDH ITU-T G.707 / SONET ANSI T1.105 LSP encoding.";
+      reference
+        "RFC 3471: Generalized Multi-Protocol Label Switching (GMPLS)
+                   Signaling Functional Description";
+    }
+
+    identity lsp-encoding-digital-wrapper {
+      base lsp-encoding-types;
+      description
+        "Digital Wrapper LSP encoding.";
+      reference
+        "RFC 3471: Generalized Multi-Protocol Label Switching (GMPLS)
+                   Signaling Functional Description";
+    }
+
+    identity lsp-encoding-lambda {
+      base lsp-encoding-types;
+      description
+        "Lambda (photonic) LSP encoding.";
+      reference
+        "RFC 3471: Generalized Multi-Protocol Label Switching (GMPLS)
+                   Signaling Functional Description";
+    }
+
+    identity lsp-encoding-fiber {
+      base lsp-encoding-types;
+      description
+        "Fiber LSP encoding.";
+      reference
+        "RFC 3471: Generalized Multi-Protocol Label Switching (GMPLS)
+                   Signaling Functional Description";
+    }
+
+    identity lsp-encoding-fiber-channel {
+      base lsp-encoding-types;
+      description
+        "FiberChannel LSP encoding.";
+      reference
+        "RFC 3471: Generalized Multi-Protocol Label Switching (GMPLS)
+                   Signaling Functional Description";
+    }
+
+    identity lsp-encoding-oduk {
+      base lsp-encoding-types;
+      description
+        "G.709 ODUk (Digital Path) LSP encoding.";
+      reference
+        "RFC 4328: Generalized Multi-Protocol Label Switching (GMPLS)
+                   Signaling Extensions for G.709 Optical Transport
+                   Networks Control";
+    }
+
+    identity lsp-encoding-optical-channel {
+      base lsp-encoding-types;
+      description
+        "G.709 Optical Channel LSP encoding.";
+      reference
+        "RFC 4328: Generalized Multi-Protocol Label Switching (GMPLS)
+                   Signaling Extensions for G.709 Optical Transport
+                   Networks Control";
+    }
+
+    identity lsp-encoding-line {
+      base lsp-encoding-types;
+      description
+        "Line (e.g., 8B/10B) LSP encoding.";
+      reference
+        "RFC 6004: Generalized MPLS (GMPLS) Support for Metro
+                   Ethernet Forum and G.8011 Ethernet Service
+                   Switching";
+    }
+
+  identity path-signaling-type {
+    description
+      "Base identity from which specific LSP path setup types
+       are derived.";
+  }
+
+    identity path-setup-static {
+      base path-signaling-type;
+      description
+        "Static LSP provisioning path setup.";
+    }
+
+    identity path-setup-rsvp {
+      base path-signaling-type;
+      description
+        "RSVP-TE signaling path setup.";
+      reference
+        "RFC 3209: RSVP-TE: Extensions to RSVP for LSP Tunnels";
+    }
+
+    identity path-setup-sr {
+      base path-signaling-type;
+      description
+        "Segment-routing path setup.";
+    }
+
+  identity path-scope-type {
+    description
+      "Base identity from which specific path scope types are
+       derived.";
+  }
+
+    identity path-scope-segment {
+      base path-scope-type;
+      description
+        "Path scope segment.";
+      reference
+        "RFC 4873: GMPLS Segment Recovery";
+    }
+
+    identity path-scope-end-to-end {
+      base path-scope-type;
+      description
+        "Path scope end to end.";
+      reference
+        "RFC 4873: GMPLS Segment Recovery";
+    }
+
+  identity route-usage-type {
+    description
+      "Base identity for route usage.";
+  }
+
+    identity route-include-object {
+      base route-usage-type;
+      description
+        "'Include route' object.";
+    }
+
+    identity route-exclude-object {
+      base route-usage-type;
+      description
+        "'Exclude route' object.";
+      reference
+        "RFC 4874: Exclude Routes - Extension to Resource ReserVation
+                   Protocol-Traffic Engineering (RSVP-TE)";
+    }
+
+    identity route-exclude-srlg {
+      base route-usage-type;
+      description
+        "Excludes SRLGs.";
+      reference
+        "RFC 4874: Exclude Routes - Extension to Resource ReserVation
+                   Protocol-Traffic Engineering (RSVP-TE)";
+    }
+
+  identity path-metric-optimization-type {
+    description
+      "Base identity used to define the path metric optimization
+       types.";
+  }
+
+  identity link-path-metric-type {
+    description
+      "Base identity used to define the link and the path metric
+       types.
+
+       The unit of the path metric value is interpreted in the
+       context of the path metric type and the derived identities
+       SHOULD describe the unit of the path metric types they
+       define.";
+  }
+
+    identity link-metric-type {
+      base link-path-metric-type;
+      description
+        "Base identity for the link metric types.";
+    }
+
+      identity link-metric-te {
+        base link-metric-type;
+        description
+          "Traffic Engineering (TE) Link Metric.";
+        reference
+          "RFC 3630: Traffic Engineering (TE) Extensions to OSPF
+                     Version 2, Section 2.5.5
+           RFC 5305: IS-IS Extensions for Traffic Engineering,
+                     Section 3.7";
+      }
+
+      identity link-metric-igp {
+        base link-metric-type;
+        description
+          "Interior Gateway Protocol (IGP) Link Metric.";
+        reference
+          "RFC 3785: Use of Interior Gateway Protocol (IGP) Metric
+                     as a second MPLS Traffic Engineering (TE)
+                     Metric";
+      }
+
+      identity link-metric-delay-average {
+        base link-metric-type;
+        description
+          "Unidirectional Link Delay, measured in units of
+           microseconds.";
+        reference
+          "RFC 7471: OSPF Traffic Engineering (TE) Metric
+                     Extensions, Section 4.1        
+           RFC 8570: IS-IS Traffic Engineering (TE) Metric
+                     Extensions, Section 4.1";
+      }
+
+      identity link-metric-delay-minimum {
+        base link-metric-type;
+        description
+          "Minimum unidirectional Link Delay, measured in units of
+           microseconds.";
+        reference
+          "RFC 7471: OSPF Traffic Engineering (TE) Metric
+                     Extensions, Section 4.2
+           RFC 8570: IS-IS Traffic Engineering (TE) Metric
+                     Extensions, Section 4.2";
+      }
+
+      identity link-metric-delay-maximum {
+        base link-metric-type;
+        description
+          "Maximum unidirectional Link Delay, measured in units of
+           microseconds.";
+        reference
+          "RFC 7471: OSPF Traffic Engineering (TE) Metric
+                     Extensions, Section 4.2
+           RFC 8570: IS-IS Traffic Engineering (TE) Metric
+                     Extensions, Section 4.2";
+      }
+
+      identity link-metric-residual-bandwidth {
+        base link-metric-type;
+        description
+          "Unidirectional Residual Bandwidth, measured in units of
+           bytes per second.
+
+           It is defined to be Maximum Bandwidth minus the bandwidth
+           currently allocated to LSPs.";
+        reference
+          "RFC 7471: OSPF Traffic Engineering (TE) Metric
+                     Extensions, Section 4.5
+           RFC 8570: IS-IS Traffic Engineering (TE) Metric
+                     Extensions, Section 4.5";
+      }
+
+    identity path-metric-type {
+      base link-path-metric-type;
+      base path-metric-optimization-type;
+      description
+        "Base identity for the path metric types.";
+    }
+
+      identity path-metric-te {
+        base path-metric-type;
+        description
+          "Traffic Engineering (TE) Path Metric.";
+        reference
+          "RFC 5440: Path Computation Element (PCE) Communication
+                     Protocol (PCEP), Section 7.8";
+      }
+
+      identity path-metric-igp {
+        base path-metric-type;
+        description
+          "Interior Gateway Protocol (IGP) Path Metric.";
+        reference
+          "RFC 5440: Path Computation Element (PCE) Communication
+                     Protocol (PCEP), section 7.8";
+      }
+
+      identity path-metric-hop {
+        base path-metric-type;
+        description
+          "Hop Count Path Metric.";
+        reference
+          "RFC 5440: Path Computation Element (PCE) Communication
+                     Protocol (PCEP), Section 7.8";
+      }
+
+      identity path-metric-delay-average {
+        base path-metric-type;
+        description
+          "The Path Delay Metric, measured in units of
+           microseconds.";
+        reference
+          "RFC8233: Extensions to the Path Computation Element
+                    Communication Protocol (PCEP) to Compute
+                    Service-Aware Label Switched Paths (LSPs),
+                    Section 3.1.1";
+      }
+
+      identity path-metric-delay-minimum {
+        base path-metric-type;
+        description
+          "The Path Min Delay Metric, measured in units of
+           microseconds.";
+        reference
+          "I-D.ietf-pce-sid-algo: Carrying SR-Algorithm information
+                                  in PCE-based Networks,
+                                  draft-ietf-pce-sid-algo-14,
+                                  Sections 3.5.1 and 3.5.2";
+      }
+
+      identity path-metric-residual-bandwidth {
+        base path-metric-type;
+        description
+          "The Path Residual Bandwidth, defined as the minimum Link
+           Residual Bandwidth all the links along the path.
+
+           The Path Residual Bandwidth can be seen as the path
+           metric associated with the Maximum residual Bandwidth Path
+           (MBP) objective function.";
+        reference
+          "RFC 5541: Encoding of Objective Functions in the Path
+                     Computation Element Communication Protocol
+                     (PCEP)";
+      }
+
+    identity path-metric-optimize-includes {
+      base path-metric-optimization-type;
+      description
+        "A metric that optimizes the number of included resources
+         specified in a set.";
+    }
+
+    identity path-metric-optimize-excludes {
+      base path-metric-optimization-type;
+      description
+        "A metric that optimizes to a maximum the number of excluded
+         resources specified in a set.";
+    }
+
+  identity path-tiebreaker-type {
+    description
+      "Base identity for the path tiebreaker type.";
+  }
+
+    identity path-tiebreaker-minfill {
+      base path-tiebreaker-type;
+      description
+        "Min-Fill LSP path placement: selects the path with the most
+         available bandwidth (load balance LSPs over more links).";
+    }
+
+    identity path-tiebreaker-maxfill {
+      base path-tiebreaker-type;
+      description
+        "Max-Fill LSP path placement: selects the path with the least
+         available bandwidth (packing more LSPs over few links).";
+    }
+
+    identity path-tiebreaker-random {
+      base path-tiebreaker-type;
+      description
+        "Random LSP path placement.";
+    }
+
+  identity resource-affinities-type {
+    description
+      "Base identity for resource class affinities.";
+    reference
+      "RFC 3209: RSVP-TE: Extensions to RSVP for LSP Tunnels
+       RFC 2702: Requirements for Traffic Engineering Over MPLS";
+  }
+
+    identity resource-aff-include-all {
+      base resource-affinities-type;
+      description
+        "The set of attribute filters associated with a
+         tunnel, all of which must be present for a link
+         to be acceptable.";
+      reference
+        "RFC 3209: RSVP-TE: Extensions to RSVP for LSP Tunnels
+         RFC 2702: Requirements for Traffic Engineering Over MPLS";
+    }
+
+    identity resource-aff-include-any {
+      base resource-affinities-type;
+      description
+        "The set of attribute filters associated with a
+         tunnel, any of which must be present for a link
+         to be acceptable.";
+      reference
+        "RFC 3209: RSVP-TE: Extensions to RSVP for LSP Tunnels
+         RFC 2702: Requirements for Traffic Engineering Over MPLS";
+    }
+
+    identity resource-aff-exclude-any {
+      base resource-affinities-type;
+      description
+        "The set of attribute filters associated with a
+         tunnel, any of which renders a link unacceptable.";
+      reference
+        "RFC 3209: RSVP-TE: Extensions to RSVP for LSP Tunnels
+         RFC 2702: Requirements for Traffic Engineering Over MPLS";
+    }
+
+  identity te-optimization-criterion {
+    description
+      "Base identity for the TE optimization criteria.";
+    reference
+      "RFC 9522: Overview and Principles of Internet Traffic
+                 Engineering";
+  }
+
+    identity not-optimized {
+      base te-optimization-criterion;
+      description
+        "Optimization is not applied.";
+    }
+
+    identity cost {
+      base te-optimization-criterion;
+      description
+        "Optimized on cost.";
+      reference
+        "RFC 5541: Encoding of Objective Functions in the Path
+                    Computation Element Communication Protocol
+                    (PCEP)";
+    }
+
+    identity delay {
+      base te-optimization-criterion;
+      description
+        "Optimized on delay.";
+      reference
+        "RFC 5541: Encoding of Objective Functions in the Path
+                    Computation Element Communication Protocol
+                    (PCEP)";
+    }
+
+  identity path-computation-srlg-type {
+    description
+      "Base identity for SRLG path computation.";
+  }
+
+    identity srlg-ignore {
+      base path-computation-srlg-type;
+      description
+        "Ignores SRLGs in the path computation.";
+    }
+
+    identity srlg-strict {
+      base path-computation-srlg-type;
+      description
+        "Includes a strict SRLG check in the path computation.";
+    }
+
+    identity srlg-preferred {
+      base path-computation-srlg-type;
+      description
+        "Includes a preferred SRLG check in the path computation.";
+    }
+
+    identity srlg-weighted {
+      base path-computation-srlg-type;
+      description
+        "Includes a weighted SRLG check in the path computation.";
+    }
+
+  identity path-computation-error-reason {
+    description
+      "Base identity for path computation error reasons.";
+  }
+
+    identity path-computation-error-path-not-found {
+      base path-computation-error-reason;
+      description
+        "Path computation has failed because of an unspecified 
+         reason.";
+      reference
+        "RFC 5440: Path Computation Element (PCE) Communication
+                   Protocol (PCEP), Section 7.5";
+    }
+
+    identity path-computation-error-no-topology {
+      base path-computation-error-reason;
+      description
+        "Path computation has failed because there is no topology
+         with the provided topology-identifier.";
+    }
+
+    identity path-computation-error-no-dependent-server {
+      base path-computation-error-reason;
+      description
+        "Path computation has failed because one or more dependent
+         path computation servers are unavailable.
+
+         The dependent path computation server could be
+         a Backward-Recursive Path Computation (BRPC) downstream
+         PCE or a child PCE.";
+      reference
+        "RFC 5441: A Backward-Recursive PCE-Based Computation (BRPC)
+                   Procedure to Compute Shortest Constrained
+                   Inter-Domain Traffic Engineering Label Switched
+                   Paths
+         RFC 8685: Path Computation Element Communication Protocol
+                   (PCEP) Extensions for the Hierarchical Path
+                   Computation Element (H-PCE) Architecture";
+    }
+
+    identity path-computation-error-pce-unavailable {
+      base path-computation-error-reason;
+      description
+        "Path computation has failed because PCE is not available.
+
+         It corresponds to bit 31 of the Flags field of the 
+         NO-PATH-VECTOR TLV.";
+      reference
+        "RFC 5440: Path Computation Element (PCE) Communication
+                   Protocol (PCEP)
+
+         https://www.iana.org/assignments/pcep
+         /pcep.xhtml#no-path-vector-tlv";
+    }
+
+    identity path-computation-error-no-inclusion-hop {
+      base path-computation-error-reason;
+      description
+        "Path computation has failed because there is no
+         node or link provided by one or more inclusion hops.";
+    }
+
+    identity path-computation-error-destination-unknown-in-domain {
+      base path-computation-error-reason;
+      description
+        "Path computation has failed because the destination node is
+         unknown in indicated destination domain.
+
+         It corresponds to bit 19 of the Flags field of the 
+         NO-PATH-VECTOR TLV.";
+      reference
+        "RFC 8685: Path Computation Element Communication Protocol
+                   (PCEP) Extensions for the Hierarchical Path
+                   Computation Element (H-PCE) Architecture
+
+         https://www.iana.org/assignments/pcep
+         /pcep.xhtml#no-path-vector-tlv";
+    }
+
+    identity path-computation-error-no-resource {
+      base path-computation-error-reason;
+      description
+        "Path computation has failed because there is no
+         available resource in one or more domains.
+
+         It corresponds to bit 20 of the Flags field of the 
+         NO-PATH-VECTOR TLV.";
+      reference
+        "RFC 8685: Path Computation Element Communication Protocol
+                   (PCEP) Extensions for the Hierarchical Path
+                   Computation Element (H-PCE) Architecture
+
+         https://www.iana.org/assignments/pcep
+         /pcep.xhtml#no-path-vector-tlv";
+    }
+
+    identity path-computation-error-child-pce-unresponsive {
+      base path-computation-error-no-dependent-server;
+      description
+        "Path computation has failed because child PCE is not
+         responsive.
+
+         It corresponds to bit 21 of the Flags field of the 
+         NO-PATH-VECTOR TLV.";
+      reference
+        "RFC 8685: Path Computation Element Communication Protocol
+                   (PCEP) Extensions for the Hierarchical Path
+                   Computation Element (H-PCE) Architecture
+
+         https://www.iana.org/assignments/pcep
+         /pcep.xhtml#no-path-vector-tlv";
+    }
+
+    identity path-computation-error-destination-domain-unknown {
+      base path-computation-error-reason;
+      description
+        "Path computation has failed because the destination domain
+         was unknown.
+
+         It corresponds to bit 22 of the Flags field of the 
+         NO-PATH-VECTOR TLV.";
+      reference
+        "RFC 8685: Path Computation Element Communication Protocol
+                   (PCEP) Extensions for the Hierarchical Path
+                   Computation Element (H-PCE) Architecture
+
+         https://www.iana.org/assignments/pcep
+         /pcep.xhtml#no-path-vector-tlv";
+    }
+
+    identity path-computation-error-p2mp {
+      base path-computation-error-reason;
+      description
+        "Path computation has failed because of P2MP reachability
+         problem.
+
+         It corresponds to bit 24 of the Flags field of the 
+         NO-PATH-VECTOR TLV.";
+      reference
+        "RFC 8306: Extensions to the Path Computation Element
+                   Communication Protocol (PCEP) for
+                   Point-to-Multipoint Traffic Engineering Label
+                   Switched Paths
+
+         https://www.iana.org/assignments/pcep
+         /pcep.xhtml#no-path-vector-tlv";
+    }
+
+    identity path-computation-error-no-gco-migration {
+      base path-computation-error-reason;
+      description
+        "Path computation has failed because of no Global Concurrent
+         Optimization (GCO) migration path found.
+
+         It corresponds to bit 26 of the Flags field of the 
+         NO-PATH-VECTOR TLV.";
+      reference
+        "RFC 5557: Path Computation Element Communication Protocol
+                   (PCEP) Requirements and Protocol Extensions in
+                   Support of Global Concurrent Optimization
+
+         https://www.iana.org/assignments/pcep
+         /pcep.xhtml#no-path-vector-tlv";
+    }
+
+    identity path-computation-error-no-gco-solution {
+      base path-computation-error-reason;
+      description
+        "Path computation has failed because of no GCO solution
+         found.
+
+         It corresponds to bit 25 of the Flags field of the 
+         NO-PATH-VECTOR TLV.";
+      reference
+        "RFC 5557: Path Computation Element Communication Protocol
+                   (PCEP) Requirements and Protocol Extensions in
+                   Support of Global Concurrent Optimization
+
+         https://www.iana.org/assignments/pcep
+         /pcep.xhtml#no-path-vector-tlv";
+    }
+
+    identity path-computation-error-pks-expansion {
+      base path-computation-error-reason;
+      description
+        "Path computation has failed because of Path-Key Subobject
+         (PKS)  expansion failure.
+
+         It corresponds to bit 27 of the Flags field of the 
+         NO-PATH-VECTOR TLV.";
+      reference
+        "RFC 5520: Preserving Topology Confidentiality in
+                   Inter-Domain Path Computation Using a
+                   Path-Key-Based Mechanism
+
+         https://www.iana.org/assignments/pcep
+         /pcep.xhtml#no-path-vector-tlv";
+    }
+
+    identity path-computation-error-brpc-chain-unavailable {
+      base path-computation-error-no-dependent-server;
+      description
+        "Path computation has failed because PCE BRPC chain
+         unavailable.
+
+         It corresponds to bit 28 of the Flags field of the 
+         NO-PATH-VECTOR TLV.";
+      reference
+        "RFC 5441: A Backward-Recursive PCE-Based Computation (BRPC)
+                   Procedure to Compute Shortest Constrained
+                   Inter-Domain Traffic Engineering Label Switched
+                   Paths
+
+         https://www.iana.org/assignments/pcep
+         /pcep.xhtml#no-path-vector-tlv";
+    }
+
+    identity path-computation-error-source-unknown {
+      base path-computation-error-reason;
+      description
+        "Path computation has failed because source node is 
+         unknown.
+
+         It corresponds to bit 29 of the Flags field of the 
+         NO-PATH-VECTOR TLV.";
+      reference
+        "RFC 5440: Path Computation Element (PCE) Communication
+                   Protocol (PCEP);
+
+         https://www.iana.org/assignments/pcep
+         /pcep.xhtml#no-path-vector-tlv";
+    }
+
+    identity path-computation-error-destination-unknown {
+      base path-computation-error-reason;
+      description
+        "Path computation has failed because destination node is
+         unknown.
+
+         It corresponds to bit 30 of the Flags field of the 
+         NO-PATH-VECTOR TLV.";
+      reference
+        "RFC 5440: Path Computation Element (PCE) Communication
+        Protocol (PCEP);
+
+         https://www.iana.org/assignments/pcep
+         /pcep.xhtml#no-path-vector-tlv";
+    }
+
+    identity path-computation-error-no-server {
+      base path-computation-error-reason;
+      description
+        "Path computation has failed because path computation
+         server is unavailable.";
+      reference
+        "RFC 5440: Path Computation Element (PCE) Communication
+                   Protocol (PCEP);
+
+         https://www.iana.org/assignments/pcep
+         /pcep.xhtml#no-path-vector-tlv";
+    }
+
+  identity protocol-origin-type {
+    description
+      "Base identity for protocol origin type.";
+  }
+
+    identity protocol-origin-api {
+      base protocol-origin-type;
+      description
+        "Protocol origin is via Application Programming Interface
+         (API).";
+    }
+
+    identity protocol-origin-pcep {
+      base protocol-origin-type;
+      description
+        "Protocol origin is Path Computation Engine Protocol 
+         (PCEP).";
+      reference
+        "RFC 5440: Path Computation Element (PCE) Communication
+                   Protocol (PCEP)";
+    }
+
+    identity protocol-origin-bgp {
+      base protocol-origin-type;
+      description
+        "Protocol origin is Border Gateway Protocol (BGP).";
+      reference
+        "RFC 9012: The BGP Tunnel Encapsulation Attribute";
+    }
+
+  identity svec-objective-function-type {
+    description
+      "Base identity for SVEC objective function type.";
+    reference
+      "RFC 5541: Encoding of Objective Functions in the Path
+                 Computation Element Communication Protocol (PCEP)";
+  }
+
+    identity svec-of-minimize-agg-bandwidth-consumption {
+      base svec-objective-function-type;
+      description
+        "Objective function for minimizing aggregate bandwidth 
+         consumption (MBC).";
+      reference
+        "RFC 5541: Encoding of Objective Functions in the Path
+                   Computation Element Communication Protocol
+                   (PCEP)";
+    }
+
+    identity svec-of-minimize-load-most-loaded-link {
+      base svec-objective-function-type;
+      description
+        "Objective function for minimizing the load on the link that 
+         is carrying the highest load (MLL).";
+      reference
+        "RFC 5541: Encoding of Objective Functions in the Path
+                   Computation Element Communication Protocol
+                   (PCEP)";
+    }
+
+    identity svec-of-minimize-cost-path-set {
+      base svec-objective-function-type;
+      description
+        "Objective function for minimizing the cost on a path set 
+         (MCC).";
+      reference
+        "RFC 5541: Encoding of Objective Functions in the Path
+                   Computation Element Communication Protocol
+                   (PCEP)";
+    }
+
+    identity svec-of-minimize-common-transit-domain {
+      base svec-objective-function-type;
+      description
+        "Objective function for minimizing the number of common 
+         transit domains (MCTD).";
+      reference
+        "RFC 8685: Path Computation Element Communication Protocol 
+                   (PCEP) Extensions for the Hierarchical Path
+                   Computation Element (H-PCE) Architecture.";
+    }
+
+    identity svec-of-minimize-shared-link {
+      base svec-objective-function-type;
+      description
+        "Objective function for minimizing the number of shared 
+         links (MSL).";
+      reference
+        "RFC 8685: Path Computation Element Communication Protocol 
+                   (PCEP) Extensions for the Hierarchical Path
+                   Computation Element (H-PCE) Architecture.";
+    }
+
+    identity svec-of-minimize-shared-srlg {
+      base svec-objective-function-type;
+      description
+        "Objective function for minimizing the number of shared 
+         Shared Risk Link Groups (SRLG) (MSS).";
+      reference
+        "RFC 8685: Path Computation Element Communication Protocol 
+                   (PCEP) Extensions for the Hierarchical Path
+                   Computation Element (H-PCE) Architecture.";
+    }
+
+    identity svec-of-minimize-shared-nodes {
+      base svec-objective-function-type;
+      description
+        "Objective function for minimizing the number of shared 
+         nodes (MSN).";
+      reference
+        "RFC 8685: Path Computation Element Communication Protocol
+                   (PCEP) Extensions for the Hierarchical Path
+                   Computation Element (H-PCE) Architecture.";
+    }
+
+  identity svec-metric-type {
+    description
+      "Base identity for SVEC metric type.";
+    reference
+      "RFC 5541: Encoding of Objective Functions in the Path
+                 Computation Element Communication Protocol (PCEP)";
+  }
+
+    identity svec-metric-cumulative-te {
+      base svec-metric-type;
+      description
+        "Cumulative TE cost.";
+      reference
+        "RFC 5541: Encoding of Objective Functions in the Path
+                   Computation Element Communication Protocol
+                   (PCEP)";
+    }
+
+    identity svec-metric-cumulative-igp {
+      base svec-metric-type;
+      description
+        "Cumulative IGP cost.";
+      reference
+        "RFC 5541: Encoding of Objective Functions in the Path
+                   Computation Element Communication Protocol
+                   (PCEP)";
+    }
+
+    identity svec-metric-cumulative-hop {
+      base svec-metric-type;
+      description
+        "Cumulative Hop path metric.";
+      reference
+        "RFC 5541: Encoding of Objective Functions in the Path
+                   Computation Element Communication Protocol
+                   (PCEP)";
+    }
+
+    identity svec-metric-aggregate-bandwidth-consumption {
+      base svec-metric-type;
+      description
+        "Aggregate bandwidth consumption.";
+      reference
+        "RFC 5541: Encoding of Objective Functions in the Path
+                   Computation Element Communication Protocol
+                   (PCEP)";
+    }
+
+    identity svec-metric-load-of-the-most-loaded-link {
+      base svec-metric-type;
+      description
+        "Load of the most loaded link.";
+      reference
+        "RFC 5541: Encoding of Objective Functions in the Path
+                   Computation Element Communication Protocol
+                   (PCEP)";
+    }
+
+  /**
+   * TE bandwidth groupings
+   **/
+
+  grouping te-bandwidth {
+    description
+      "This grouping defines the generic TE bandwidth.
+       For some known data-plane technologies, specific modeling
+       structures are specified.  The string-encoded 'te-bandwidth'
+       type is used for unspecified technologies.
+       The modeling structure can be augmented later for other
+       technologies.";
+    container te-bandwidth {
+      description
+        "Container that specifies TE bandwidth.  The choices
+         can be augmented for specific data-plane technologies.";
+      choice technology {
+        default "generic";
+        description
+          "Data-plane technology type.";
+        case generic {
+          leaf generic {
+            type te-bandwidth;
+            description
+              "Bandwidth specified in a generic format.";
+          }
+        }
+      }
+    }
+  }
+
+  /**
+   * TE label groupings
+   **/
+
+  grouping te-label {
+    description
+      "This grouping defines the generic TE label.
+       The modeling structure can be augmented for each technology.
+       For unspecified technologies, 'rt-types:generalized-label'
+       is used.";
+    container te-label {
+      description
+        "Container that specifies the TE label.  The choices can
+         be augmented for specific data-plane technologies.";
+      choice technology {
+        default "generic";
+        description
+          "Data-plane technology type.";
+        case generic {
+          leaf generic {
+            type rt-types:generalized-label;
+            description
+              "TE label specified in a generic format.";
+          }
+        }
+      }
+      leaf direction {
+        type te-label-direction;
+        default "forward";
+        description
+          "Label direction.";
+      }
+    }
+  }
+
+  grouping te-topology-identifier {
+    description
+      "Augmentation for a TE topology.";
+    container te-topology-identifier {
+      description
+        "TE topology identifier container.";
+      leaf provider-id {
+        type te-global-id;
+        default "0";
+        description
+          "An identifier to uniquely identify a provider.
+           If omitted, it assumes that the topology provider ID
+           value = 0 (the default).";
+      }
+      leaf client-id {
+        type te-global-id;
+        default "0";
+        description
+          "An identifier to uniquely identify a client.
+           If omitted, it assumes that the topology client ID
+           value = 0 (the default).";
+      }
+      leaf topology-id {
+        type te-topology-id;
+        default "";
+        description
+          "When the datastore contains several topologies,
+           'topology-id' distinguishes between them.  If omitted,
+           the default (empty) string for this leaf is assumed.";
+      }
+    }
+  }
+
+  /**
+   * TE performance metrics groupings
+   **/
+
+  grouping performance-metrics-one-way-delay-loss {
+    description
+      "Performance Metrics (PM) information in real time that can
+       be applicable to links or connections.  PM defined in this
+       grouping are applicable to generic TE PM as well as packet TE
+       PM.";
+    reference
+      "RFC 7471: OSPF Traffic Engineering (TE) Metric Extensions
+       RFC 8570: IS-IS Traffic Engineering (TE) Metric Extensions
+       RFC 7823: Performance-Based Path Selection for Explicitly
+                 Routed Label Switched Paths (LSPs) Using TE Metric
+                 Extensions";
+    leaf one-way-delay {
+      type uint32 {
+        range "0..16777215";
+      }
+      description
+        "One-way delay or latency in microseconds.";
+    }
+    leaf one-way-delay-normality {
+      type te-types:performance-metrics-normality;
+      description
+        "One-way delay normality.";
+    }
+  }
+
+  grouping performance-metrics-two-way-delay-loss {
+    description
+      "PM information in real time that can be applicable to links or
+       connections.  PM defined in this grouping are applicable to
+       generic TE PM as well as packet TE PM.";
+    reference
+      "RFC 7471: OSPF Traffic Engineering (TE) Metric Extensions
+       RFC 8570: IS-IS Traffic Engineering (TE) Metric Extensions
+       RFC 7823: Performance-Based Path Selection for Explicitly
+                 Routed Label Switched Paths (LSPs) Using TE Metric
+                 Extensions";
+    leaf two-way-delay {
+      type uint32 {
+        range "0..16777215";
+      }
+      description
+        "Two-way delay or latency in microseconds.";
+    }
+    leaf two-way-delay-normality {
+      type te-types:performance-metrics-normality;
+      description
+        "Two-way delay normality.";
+    }
+  }
+
+  grouping performance-metrics-one-way-bandwidth {
+    description
+      "PM information in real time that can be applicable to links.
+       PM defined in this grouping are applicable to generic TE PM
+       as well as packet TE PM.";
+    reference
+      "RFC 7471: OSPF Traffic Engineering (TE) Metric Extensions
+       RFC 8570: IS-IS Traffic Engineering (TE) Metric Extensions
+       RFC 7823: Performance-Based Path Selection for Explicitly
+                 Routed Label Switched Paths (LSPs) Using TE Metric
+                 Extensions";
+    leaf one-way-residual-bandwidth {
+      type rt-types:bandwidth-ieee-float32;
+      units "bytes per second";
+      default "0x0p0";
+      description
+        "Residual bandwidth that subtracts tunnel reservations from
+         Maximum Bandwidth (or link capacity) (RFC 3630) and
+         provides an aggregated remainder across QoS classes.";
+      reference
+        "RFC 3630: Traffic Engineering (TE) Extensions to OSPF
+                   Version 2";
+    }
+    leaf one-way-residual-bandwidth-normality {
+      type te-types:performance-metrics-normality;
+      default "normal";
+      description
+        "Residual bandwidth normality.";
+    }
+    leaf one-way-available-bandwidth {
+      type rt-types:bandwidth-ieee-float32;
+      units "bytes per second";
+      default "0x0p0";
+      description
+        "Available bandwidth that is defined to be residual
+         bandwidth minus the measured bandwidth used for the
+         actual forwarding of non-RSVP-TE LSP packets.  For a
+         bundled link, available bandwidth is defined to be the
+         sum of the component link available bandwidths.";
+    }
+    leaf one-way-available-bandwidth-normality {
+      type te-types:performance-metrics-normality;
+      default "normal";
+      description
+        "Available bandwidth normality.";
+    }
+    leaf one-way-utilized-bandwidth {
+      type rt-types:bandwidth-ieee-float32;
+      units "bytes per second";
+      default "0x0p0";
+      description
+        "Bandwidth utilization that represents the actual
+         utilization of the link (i.e., as measured in the router).
+         For a bundled link, bandwidth utilization is defined to
+         be the sum of the component link bandwidth utilizations.";
+    }
+    leaf one-way-utilized-bandwidth-normality {
+      type te-types:performance-metrics-normality;
+      default "normal";
+      description
+        "Bandwidth utilization normality.";
+    }
+  }
+
+  grouping one-way-performance-metrics {
+    description
+      "One-way PM throttle grouping.";
+    leaf one-way-delay {
+      type uint32 {
+        range "0..16777215";
+      }
+      default "0";
+      description
+        "One-way delay or latency in microseconds.";
+    }
+    leaf one-way-residual-bandwidth {
+      type rt-types:bandwidth-ieee-float32;
+      units "bytes per second";
+      default "0x0p0";
+      description
+        "Residual bandwidth that subtracts tunnel reservations from
+         Maximum Bandwidth (or link capacity) (RFC 3630) and
+         provides an aggregated remainder across QoS classes.";
+      reference
+        "RFC 3630: Traffic Engineering (TE) Extensions to OSPF
+                   Version 2";
+    }
+    leaf one-way-available-bandwidth {
+      type rt-types:bandwidth-ieee-float32;
+      units "bytes per second";
+      default "0x0p0";
+      description
+        "Available bandwidth that is defined to be residual
+         bandwidth minus the measured bandwidth used for the
+         actual forwarding of non-RSVP-TE LSP packets.  For a
+         bundled link, available bandwidth is defined to be the
+         sum of the component link available bandwidths.";
+    }
+    leaf one-way-utilized-bandwidth {
+      type rt-types:bandwidth-ieee-float32;
+      units "bytes per second";
+      default "0x0p0";
+      description
+        "Bandwidth utilization that represents the actual
+         utilization of the link (i.e., as measured in the router).
+         For a bundled link, bandwidth utilization is defined to
+         be the sum of the component link bandwidth utilizations.";
+    }
+  }
+
+  grouping two-way-performance-metrics {
+    description
+      "Two-way PM throttle grouping.";
+    leaf two-way-delay {
+      type uint32 {
+        range "0..16777215";
+      }
+      default "0";
+      description
+        "Two-way delay or latency in microseconds.";
+    }
+  }
+
+  grouping performance-metrics-thresholds {
+    description
+      "Grouping for configurable thresholds for measured
+       attributes.";
+    uses one-way-performance-metrics;
+    uses two-way-performance-metrics;
+  }
+
+  grouping performance-metrics-attributes {
+    description
+      "Contains PM attributes.";
+    container performance-metrics-one-way {
+      description
+        "One-way link performance information in real time.";
+      reference
+        "RFC 7471: OSPF Traffic Engineering (TE) Metric Extensions
+         RFC 8570: IS-IS Traffic Engineering (TE) Metric Extensions
+         RFC 7823: Performance-Based Path Selection for Explicitly
+                   Routed Label Switched Paths (LSPs) Using TE Metric
+                   Extensions";
+      uses performance-metrics-one-way-delay-loss;
+      uses performance-metrics-one-way-bandwidth;
+    }
+    container performance-metrics-two-way {
+      description
+        "Two-way link performance information in real time.";
+      reference
+        "RFC 6374: Packet Loss and Delay Measurement for MPLS
+                   Networks";
+      uses performance-metrics-two-way-delay-loss;
+    }
+  }
+
+  grouping performance-metrics-throttle-container {
+    description
+      "Controls PM throttling.";
+    container throttle {
+      must 'suppression-interval >= measure-interval' {
+        error-message "'suppression-interval' cannot be less than "
+                    + "'measure-interval'.";
+        description
+          "Constraint on 'suppression-interval' and
+           'measure-interval'.";
+      }
+      description
+        "Link performance information in real time.";
+      reference
+        "RFC 7471: OSPF Traffic Engineering (TE) Metric Extensions
+         RFC 8570: IS-IS Traffic Engineering (TE) Metric Extensions
+         RFC 7823: Performance-Based Path Selection for Explicitly
+                   Routed Label Switched Paths (LSPs) Using TE Metric
+                   Extensions";
+      leaf one-way-delay-offset {
+        type uint32 {
+          range "0..16777215";
+        }
+        default "0";
+        description
+          "Offset value to be added to the measured delay value.";
+      }
+      leaf measure-interval {
+        type uint32;
+        default "30";
+        description
+          "Interval, in seconds, to measure the extended metric
+           values.";
+      }
+      leaf advertisement-interval {
+        type uint32;
+        default "0";
+        description
+          "Interval, in seconds, to advertise the extended metric
+           values.";
+      }
+      leaf suppression-interval {
+        type uint32 {
+          range "1..max";
+        }
+        default "120";
+        description
+          "Interval, in seconds, to suppress advertisement of the
+           extended metric values.";
+        reference
+          "RFC 8570: IS-IS Traffic Engineering (TE) Metric
+                     Extensions, Section 6";
+      }
+      container threshold-out {
+        uses performance-metrics-thresholds;
+        description
+          "If the measured parameter falls outside an upper bound
+           for all but the minimum-delay metric (or a lower bound
+           for the minimum-delay metric only) and the advertised
+           value is not already outside that bound, an 'anomalous'
+           announcement (anomalous bit set) will be triggered.";
+      }
+      container threshold-in {
+        uses performance-metrics-thresholds;
+        description
+          "If the measured parameter falls inside an upper bound
+           for all but the minimum-delay metric (or a lower bound
+           for the minimum-delay metric only) and the advertised
+           value is not already inside that bound, a 'normal'
+           announcement (anomalous bit cleared) will be triggered.";
+      }
+      container threshold-accelerated-advertisement {
+        description
+          "When the difference between the last advertised value and
+           the current measured value exceeds this threshold, an
+           'anomalous' announcement (anomalous bit set) will be
+           triggered.";
+        uses performance-metrics-thresholds;
+      }
+    }
+  }
+
+  /**
+   * TE tunnel generic groupings
+   **/
+
+  grouping explicit-route-hop {
+    description
+      "The explicit route entry grouping.";
+    choice type {
+      description
+        "The explicit route entry type.";
+      case numbered-node-hop {
+        container numbered-node-hop {
+          must "node-id-uri or node-id" {
+            description
+              "At least one node identifier MUST be present.";
+          }
+          leaf node-id-uri {
+            type nw:node-id;
+            description
+              "The identifier of a node in the topology.";
+          }
+          leaf node-id {
+            type te-node-id;
+            description
+              "The identifier of a node in the TE topology.";
+          }
+          leaf hop-type {
+            type te-hop-type;
+            default "strict";
+            description
+              "Strict or loose hop.";
+          }
+          description
+            "Numbered node route hop.";
+          reference
+            "RFC 3209: RSVP-TE: Extensions to RSVP for LSP Tunnels,
+                       Section 4.3, EXPLICIT_ROUTE in RSVP-TE
+             RFC 3477: Signalling Unnumbered Links in Resource
+                       ReSerVation Protocol - Traffic Engineering
+                       (RSVP-TE)";
+        }
+      }
+      case numbered-link-hop {
+        container numbered-link-hop {
+          leaf link-tp-id {
+            type te-tp-id;
+            mandatory true;
+            description
+              "TE Link Termination Point (LTP) identifier.";
+          }
+          leaf hop-type {
+            type te-hop-type;
+            default "strict";
+            description
+              "Strict or loose hop.";
+          }
+          leaf direction {
+            type te-link-direction;
+            default "outgoing";
+            description
+              "Link route object direction.";
+          }
+          description
+            "Numbered link explicit route hop.";
+          reference
+            "RFC 3209: RSVP-TE: Extensions to RSVP for LSP Tunnels,
+                       Section 4.3, EXPLICIT_ROUTE in RSVP-TE
+             RFC 3477: Signalling Unnumbered Links in Resource
+                       ReSerVation Protocol - Traffic Engineering
+                       (RSVP-TE)";
+        }
+      }
+      case unnumbered-link-hop {
+        container unnumbered-link-hop {
+          must "(link-tp-id-uri or link-tp-id) and " +
+                "(node-id-uri or node-id)" {
+            description
+              "At least one node identifier and at least one Link 
+              Termination Point (LTP) identifier MUST be present.";
+          }
+          leaf link-tp-id-uri {
+            type nt:tp-id;
+            description
+              "Link Termination Point (LTP) identifier.";
+          }
+          leaf link-tp-id {
+            type te-tp-id;
+            description
+              "TE LTP identifier.  The combination of the TE link ID
+               and the TE node ID is used to identify an unnumbered
+               TE link.";
+          }
+          leaf node-id-uri {
+            type nw:node-id;
+            description
+              "The identifier of a node in the topology.";
+          }
+          leaf node-id {
+            type te-node-id;
+            description
+              "The identifier of a node in the TE topology.";
+          }
+          leaf hop-type {
+            type te-hop-type;
+            default "strict";
+            description
+              "Strict or loose hop.";
+          }
+          leaf direction {
+            type te-link-direction;
+            default "outgoing";
+            description
+              "Link route object direction.";
+          }
+          description
+            "Unnumbered link explicit route hop.";
+          reference
+            "RFC 3209: RSVP-TE: Extensions to RSVP for LSP Tunnels,
+                       Section 4.3, EXPLICIT_ROUTE in RSVP-TE
+             RFC 3477: Signalling Unnumbered Links in Resource
+                       ReSerVation Protocol - Traffic Engineering
+                       (RSVP-TE)";
+        }
+      }
+      case as-number {
+        container as-number-hop {
+          leaf as-number {
+            type inet:as-number;
+            mandatory true;
+            description
+              "The Autonomous System (AS) number.";
+          }
+          leaf hop-type {
+            type te-hop-type;
+            default "strict";
+            description
+              "Strict or loose hop.";
+          }
+          description
+            "AS explicit route hop.";
+        }
+      }
+      case label {
+        container label-hop {
+          description
+            "Label hop type.";
+          uses te-label;
+        }
+        description
+          "The label explicit route hop type.";
+      }
+    }
+  }
+
+  grouping record-route-state {
+    description
+      "The Record Route grouping.";
+    leaf index {
+      type uint32;
+      description
+        "Record Route hop index.  The index is used to
+         identify an entry in the list.  The order of entries
+         is defined by the user without relying on key values.";
+    }
+    choice type {
+      description
+        "The Record Route entry type.";
+      case numbered-node-hop {
+        container numbered-node-hop {
+          must "node-id-uri or node-id" {
+            description
+              "At least one node identifier MUST be present.";
+          }
+          description
+            "Numbered node route hop container.";
+          leaf node-id-uri {
+            type nw:node-id;
+            description
+              "The identifier of a node in the topology.";
+          }
+          leaf node-id {
+            type te-node-id;
+            description
+              "The identifier of a node in the TE topology.";
+          }
+          leaf-list flags {
+            type path-attribute-flags;
+            description
+              "Path attributes flags.";
+            reference
+              "RFC 3209: RSVP-TE: Extensions to RSVP for LSP Tunnels
+               RFC 4090: Fast Reroute Extensions to RSVP-TE for LSP
+                         Tunnels
+               RFC 4561: Definition of a Record Route Object (RRO)
+                         Node-Id Sub-Object";
+          }
+        }
+        description
+          "Numbered node route hop.";
+      }
+      case numbered-link-hop {
+        container numbered-link-hop {
+          description
+            "Numbered link route hop container.";
+          leaf link-tp-id {
+            type te-tp-id;
+            mandatory true;
+            description
+              "Numbered TE LTP identifier.";
+          }
+          leaf-list flags {
+            type path-attribute-flags;
+            description
+              "Path attributes flags.";
+            reference
+              "RFC 3209: RSVP-TE: Extensions to RSVP for LSP Tunnels
+               RFC 4090: Fast Reroute Extensions to RSVP-TE for LSP
+                         Tunnels
+               RFC 4561: Definition of a Record Route Object (RRO)
+                         Node-Id Sub-Object";
+          }
+        }
+        description
+          "Numbered link route hop.";
+      }
+      case unnumbered-link-hop {
+        container unnumbered-link-hop {
+          must "(link-tp-id-uri or link-tp-id) and " +
+              "(node-id-uri or node-id)" {
+            description
+              "At least one node identifier and at least one Link 
+              Termination Point (LTP) identifier MUST be present.";
+          }
+          leaf link-tp-id-uri {
+            type nt:tp-id;
+            description
+              "Link Termination Point (LTP) identifier.";
+          }
+          leaf link-tp-id {
+            type te-tp-id;
+            description
+              "TE LTP identifier.  The combination of the TE link ID
+               and the TE node ID is used to identify an unnumbered
+               TE link.";
+          }
+          leaf node-id-uri {
+            type nw:node-id;
+            description
+              "The identifier of a node in the topology.";
+          }
+          leaf node-id {
+            type te-node-id;
+            description
+              "The identifier of a node in the TE topology.";
+          }
+          leaf-list flags {
+            type path-attribute-flags;
+            description
+              "Path attributes flags.";
+            reference
+              "RFC 3209: RSVP-TE: Extensions to RSVP for LSP Tunnels
+               RFC 4090: Fast Reroute Extensions to RSVP-TE for LSP
+                         Tunnels
+               RFC 4561: Definition of a Record Route Object (RRO)
+                         Node-Id Sub-Object";
+          }
+          description
+            "Unnumbered link Record Route hop.";
+          reference
+            "RFC 3477: Signalling Unnumbered Links in Resource
+                       ReSerVation Protocol - Traffic Engineering
+                       (RSVP-TE)";
+        }
+        description
+          "Unnumbered link route hop.";
+      }
+      case label {
+        container label-hop {
+          description
+            "Label route hop type.";
+          uses te-label;
+          leaf-list flags {
+            type path-attribute-flags;
+            description
+              "Path attributes flags.";
+            reference
+              "RFC 3209: RSVP-TE: Extensions to RSVP for LSP Tunnels
+               RFC 4090: Fast Reroute Extensions to RSVP-TE for LSP
+                         Tunnels
+               RFC 4561: Definition of a Record Route Object (RRO)
+                         Node-Id Sub-Object";
+          }
+        }
+        description
+          "The label Record Route entry types.";
+      }
+    }
+  }
+
+  grouping label-restriction-info {
+    description
+      "Label set item information.";
+    leaf restriction {
+      type enumeration {
+        enum inclusive {
+          description
+            "The label or label range is inclusive.";
+        }
+        enum exclusive {
+          description
+            "The label or label range is exclusive.";
+        }
+      }
+      default "inclusive";
+      description
+        "Indicates whether the list item is inclusive or exclusive.";
+    }
+    leaf index {
+      type uint32;
+      description
+        "The index of the label restriction list entry.";
+    }
+    container label-start {
+      must "(not(../label-end/te-label/direction) and"
+         + " not(te-label/direction))"
+         + " or "
+         + "(../label-end/te-label/direction = te-label/direction)"
+         + " or "
+         + "(not(te-label/direction) and"
+         + " (../label-end/te-label/direction = 'forward'))"
+         + " or "
+         + "(not(../label-end/te-label/direction) and"
+         + " (te-label/direction = 'forward'))" {
+        error-message "'label-start' and 'label-end' must have the "
+                    + "same direction.";
+      }
+      description
+        "This is the starting label if a label range is specified.
+         This is the label value if a single label is specified,
+         in which case the 'label-end' attribute is not set.";
+      uses te-label;
+    }
+    container label-end {
+      must "(not(../label-start/te-label/direction) and"
+         + " not(te-label/direction))"
+         + " or "
+         + "(../label-start/te-label/direction = te-label/direction)"
+         + " or "
+         + "(not(te-label/direction) and"
+         + " (../label-start/te-label/direction = 'forward'))"
+         + " or "
+         + "(not(../label-start/te-label/direction) and"
+         + " (te-label/direction = 'forward'))" {
+        error-message "'label-start' and 'label-end' must have the "
+                    + "same direction.";
+      }
+      description
+        "This is the ending label if a label range is specified.
+         This attribute is not set if a single label is specified.";
+      uses te-label;
+    }
+    container label-step {
+      description
+        "The step increment between labels in the label range.
+         The label start/end values will have to be consistent
+         with the sign of label step.  For example,
+         'label-start' < 'label-end' enforces 'label-step' > 0
+         'label-start' > 'label-end' enforces 'label-step' < 0.";
+      choice technology {
+        default "generic";
+        description
+          "Data-plane technology type.";
+        case generic {
+          leaf generic {
+            type int32;
+            default "1";
+            description
+              "Label range step.";
+          }
+        }
+      }
+    }
+    leaf range-bitmap {
+      type yang:hex-string;
+      description
+        "When there are gaps between 'label-start' and 'label-end',
+         this attribute is used to specify the positions
+         of the used labels.  This is represented in big endian as
+         'hex-string'.
+
+         In case the restriction is 'inclusive', the bit-position is
+         set if the corresponding mapped label is available.
+         In this case, if the range-bitmap is not present, all the
+         labels in the range are available.
+
+         In case the restriction is 'exclusive', the bit-position is
+         set if the corresponding mapped label is not available.
+         In this case, if the range-bitmap is not present, all the
+         labels in the range are not available.
+
+         The most significant byte in the hex-string is the farthest
+         to the left in the byte sequence.  Leading zero bytes in the
+         configured value may be omitted for brevity.
+         Each bit position in the 'range-bitmap' 'hex-string' maps
+         to a label in the range derived from 'label-start'.
+
+         For example, assuming that 'label-start' = 16000 and
+         'range-bitmap' = 0x01000001, then:
+
+         - bit position (0) is set, and the corresponding mapped
+           label from the range is 16000 + (0 * 'label-step') or
+           16000 for default 'label-step' = 1.
+         - bit position (24) is set, and the corresponding mapped
+           label from the range is 16000 + (24 * 'label-step') or
+           16024 for default 'label-step' = 1.";
+    }
+  }
+
+  grouping label-set-info {
+    description
+      "Grouping for the list of label restrictions specifying what
+       labels may or may not be used.";
+    container label-restrictions {
+      description
+        "The label restrictions container.";
+      list label-restriction {
+        key "index";
+        description
+          "The absence of the label restrictions container implies
+           that all labels are acceptable; otherwise, only restricted
+           labels are available.";
+        reference
+          "RFC 7579: General Network Element Constraint Encoding
+                     for GMPLS-Controlled Networks";
+        uses label-restriction-info;
+      }
+    }
+  }
+
+  grouping optimization-metric-entry {
+    description
+      "Optimization metrics configuration grouping.";
+    leaf metric-type {
+      type identityref {
+        base path-metric-optimization-type;
+      }
+      description
+        "Identifies the 'metric-type' that the path computation
+         process uses for optimization.";
+    }
+    leaf weight {
+      type uint8;
+      default "1";
+      description
+        "TE path metric normalization weight.";
+    }
+    container explicit-route-exclude-objects {
+      when "../metric-type = "
+         + "'te-types:path-metric-optimize-excludes'";
+      description
+        "Container for the 'exclude route' object list.";
+      uses path-route-exclude-objects;
+    }
+    container explicit-route-include-objects {
+      when "../metric-type = "
+         + "'te-types:path-metric-optimize-includes'";
+      description
+        "Container for the 'include route' object list.";
+      uses path-route-include-objects;
+    }
+  }
+
+  grouping common-constraints {
+    description
+      "Common constraints grouping that can be set on
+       a constraint set or directly on the tunnel.";
+    uses te-bandwidth {
+      description
+        "A requested bandwidth to use for path computation.";
+    }
+    leaf link-protection {
+      type identityref {
+        base link-protection-type;
+      }
+      default "te-types:link-protection-unprotected";
+      description
+        "Link protection type required for the links included
+         in the computed path.";
+      reference
+        "RFC 4202: Routing Extensions in Support of
+                   Generalized Multi-Protocol Label Switching
+                   (GMPLS)";
+    }
+    leaf setup-priority {
+      type uint8 {
+        range "0..7";
+      }
+      default "7";
+      description
+        "TE LSP requested setup priority.";
+      reference
+        "RFC 3209: RSVP-TE: Extensions to RSVP for LSP Tunnels";
+    }
+    leaf hold-priority {
+      type uint8 {
+        range "0..7";
+      }
+      default "7";
+      description
+        "TE LSP requested hold priority.";
+      reference
+        "RFC 3209: RSVP-TE: Extensions to RSVP for LSP Tunnels";
+    }
+    leaf signaling-type {
+      type identityref {
+        base path-signaling-type;
+      }
+      default "te-types:path-setup-rsvp";
+      description
+        "TE tunnel path signaling type.";
+    }
+  }
+
+  grouping tunnel-constraints {
+    description
+      "Tunnel constraints grouping that can be set on
+       a constraint set or directly on the tunnel.";
+    leaf network-id {
+      type nw:network-id;
+      description
+        "The network topology identifier.";
+    }
+    uses te-topology-identifier;
+    uses common-constraints;
+  }
+
+  grouping path-constraints-route-objects {
+    description
+      "List of route entries to be included or excluded when
+       performing the path computation.";
+    container explicit-route-objects {
+      description
+        "Container for the explicit route object lists.";
+      list route-object-exclude-always {
+        key "index";
+        ordered-by user;
+        description
+          "List of route objects to always exclude from the path
+           computation.";
+        leaf index {
+          type uint32;
+          description
+            "Explicit Route Object index.  The index is used to
+             identify an entry in the list.  The order of entries
+             is defined by the user without relying on key values.";
+        }
+        uses explicit-route-hop;
+      }
+      list route-object-include-exclude {
+        key "index";
+        ordered-by user;
+        description
+          "List of route objects to include or exclude in the path
+           computation.";
+        leaf explicit-route-usage {
+          type identityref {
+            base route-usage-type;
+          }
+          default "te-types:route-include-object";
+          description
+            "Indicates whether to include or exclude the
+             route object.  The default is to include it.";
+        }
+        leaf index {
+          type uint32;
+          description
+            "Route object include-exclude index.  The index is used
+             to identify an entry in the list.  The order of entries
+             is defined by the user without relying on key values.";
+        }
+        uses explicit-route-hop {
+          augment "type" {
+            case srlg {
+              container srlg {
+                description
+                  "SRLG container.";
+                leaf srlg {
+                  type uint32;
+                  description
+                    "SRLG value.";
+                }
+              }
+              description
+                "An SRLG value to be included or excluded.";
+            }
+            description
+              "Augmentation for a generic explicit route for SRLG
+               exclusion.";
+          }
+        }
+      }
+    }
+  }
+
+  grouping path-route-include-objects {
+    description
+      "List of route objects to be included when performing
+       the path computation.";
+    list route-object-include-object {
+      key "index";
+      ordered-by user;
+      description
+        "List of Explicit Route Objects to be included in the
+         path computation.";
+      leaf index {
+        type uint32;
+        description
+          "Route object entry index.  The index is used to
+           identify an entry in the list.  The order of entries
+           is defined by the user without relying on key values.";
+      }
+      uses explicit-route-hop;
+    }
+  }
+
+  grouping path-route-exclude-objects {
+    description
+      "List of route objects to be excluded when performing
+       the path computation.";
+    list route-object-exclude-object {
+      key "index";
+      ordered-by user;
+      description
+        "List of Explicit Route Objects to be excluded in the
+         path computation.";
+      leaf index {
+        type uint32;
+        description
+          "Route object entry index.  The index is used to
+           identify an entry in the list.  The order of entries
+           is defined by the user without relying on key values.";
+      }
+      uses explicit-route-hop {
+        augment "type" {
+          case srlg {
+            container srlg {
+              description
+                "SRLG container.";
+              leaf srlg {
+                type uint32;
+                description
+                  "SRLG value.";
+              }
+            }
+            description
+              "An SRLG value to be included or excluded.";
+          }
+          description
+            "Augmentation for a generic explicit route for SRLG
+             exclusion.";
+        }
+      }
+    }
+  }
+
+  grouping generic-path-metric-bounds {
+    description
+      "TE path metric bounds grouping.";
+    container path-metric-bounds {
+      description
+        "Top-level container for the list of path metric bounds.";
+      list path-metric-bound {
+        key "metric-type";
+        description
+          "List of path metric bounds, which can apply to link and
+           path metrics.
+
+           TE paths which have at least one path metric which
+           exceeds the specified bounds MUST NOT be selected.
+
+           TE paths that traverse TE links which have at least one
+           link metric which exceeds the specified bounds MUST NOT
+           be selected.";
+        leaf metric-type {
+          type identityref {
+            base link-path-metric-type;
+          }
+          description
+            "Identifies an entry in the list of 'metric-type' items
+             bound for the TE path.";
+        }
+        leaf upper-bound {
+          type uint64;
+          default "0";
+          description
+            "Upper bound on the specified 'metric-type'.
+
+             A zero indicates an unbounded upper limit for the
+             specificied 'metric-type'.
+
+             The unit of is interpreted in the context of the
+             'metric-type' identity.";
+        }
+      }
+    }
+  }
+
+  grouping generic-path-optimization {
+    description
+      "TE generic path optimization grouping.";
+    container optimizations {
+      description
+        "The objective function container that includes
+         attributes to impose when computing a TE path.";
+      choice algorithm {
+        description
+          "Optimizations algorithm.";
+        case metric {
+          if-feature "path-optimization-metric";
+          /* Optimize by metric */
+          list optimization-metric {
+            key "metric-type";
+            description
+              "TE path metric type.";
+            uses optimization-metric-entry;
+          }
+          /* Tiebreakers */
+          container tiebreakers {
+            status deprecated;
+            description
+              "Container for the list of tiebreakers.
+
+               This container has been deprecated by the tiebreaker
+               leaf.";
+            list tiebreaker {
+              key "tiebreaker-type";
+              status deprecated;
+              description
+                "The list of tiebreaker criteria to apply on an
+                 equally favored set of paths, in order to pick
+                 the best.";
+              leaf tiebreaker-type {
+                type identityref {
+                  base path-metric-type;
+                }
+                status deprecated;
+                description
+                  "Identifies an entry in the list of tiebreakers.";
+              }
+            }
+          }
+        }
+        case objective-function {
+          if-feature "path-optimization-objective-function";
+          /* Objective functions */
+          container objective-function {
+            description
+              "The objective function container that includes
+               attributes to impose when computing a TE path.";
+            leaf objective-function-type {
+              type identityref {
+                base objective-function-type;
+              }
+              default "te-types:of-minimize-cost-path";
+              description
+                "Objective function entry.";
+            }
+          }
+        }
+      }
+    }
+    leaf tiebreaker {
+      type identityref {
+        base path-tiebreaker-type;
+      }
+      default "te-types:path-tiebreaker-random";
+      description
+        "The tiebreaker criteria to apply on an equally favored set
+         of paths, in order to pick the best.";
+    }
+  }
+
+  grouping generic-path-affinities {
+    description
+      "Path affinities grouping.";
+    container path-affinities-values {
+      description
+        "Path affinities represented as values.";
+      list path-affinities-value {
+        key "usage";
+        description
+          "List of named affinity constraints.";
+        leaf usage {
+          type identityref {
+            base resource-affinities-type;
+          }
+          description
+            "Identifies an entry in the list of value affinity
+             constraints.";
+        }
+        leaf value {
+          type admin-groups;
+          default "";
+          description
+            "The affinity value.  The default is empty.";
+        }
+      }
+    }
+    container path-affinity-names {
+      description
+        "Path affinities represented as names.";
+      list path-affinity-name {
+        key "usage";
+        description
+          "List of named affinity constraints.";
+        leaf usage {
+          type identityref {
+            base resource-affinities-type;
+          }
+          description
+            "Identifies an entry in the list of named affinity
+             constraints.";
+        }
+        list affinity-name {
+          key "name";
+          leaf name {
+            type string;
+            description
+              "Identifies a named affinity entry.";
+          }
+          description
+            "List of named affinities.";
+        }
+      }
+    }
+  }
+
+  grouping generic-path-srlgs {
+    description
+      "Path SRLG grouping.";
+    container path-srlgs-lists {
+      description
+        "Path SRLG properties container.";
+      list path-srlgs-list {
+        key "usage";
+        description
+          "List of SRLG values to be included or excluded.";
+        leaf usage {
+          type identityref {
+            base route-usage-type;
+          }
+          description
+            "Identifies an entry in a list of SRLGs to either
+             include or exclude.";
+        }
+        leaf-list values {
+          type srlg;
+          description
+            "List of SRLG values.";
+        }
+      }
+    }
+    container path-srlgs-names {
+      description
+        "Container for the list of named SRLGs.";
+      list path-srlgs-name {
+        key "usage";
+        description
+          "List of named SRLGs to be included or excluded.";
+        leaf usage {
+          type identityref {
+            base route-usage-type;
+          }
+          description
+            "Identifies an entry in a list of named SRLGs to either
+             include or exclude.";
+        }
+        leaf-list names {
+          type string;
+          description
+            "List of named SRLGs.";
+        }
+      }
+    }
+  }
+
+  grouping generic-path-disjointness {
+    description
+      "Path disjointness grouping.";
+    leaf disjointness {
+      type te-path-disjointness;
+      description
+        "The type of resource disjointness.
+         When configured for a primary path, the disjointness level
+         applies to all secondary LSPs.  When configured for a
+         secondary path, the disjointness level overrides the level
+         configured for the primary path.";
+    }
+  }
+
+  grouping common-path-constraints-attributes {
+    description
+      "Common path constraints configuration grouping.";
+    uses common-constraints;
+    uses generic-path-metric-bounds;
+    uses generic-path-affinities;
+    uses generic-path-srlgs;
+  }
+
+  grouping generic-path-constraints {
+    description
+      "Global named path constraints configuration grouping.";
+    container path-constraints {
+      description
+        "TE named path constraints container.";
+      uses common-path-constraints-attributes;
+      uses generic-path-disjointness;
+    }
+  }
+
+  grouping generic-path-properties {
+    description
+      "TE generic path properties grouping.";
+    container path-properties {
+      config false;
+      description
+        "The TE path properties.";
+      list path-metric {
+        key "metric-type";
+        description
+          "TE path metric type.";
+        leaf metric-type {
+          type identityref {
+            base path-metric-type;
+          }
+          description
+            "TE path metric type.";
+        }
+        leaf accumulative-value {
+          type uint64;
+          description
+            "TE path metric accumulative value.";
+        }
+      }
+      uses generic-path-affinities;
+      uses generic-path-srlgs;
+      container path-route-objects {
+        description
+          "Container for the list of route objects either returned by
+           the computation engine or actually used by an LSP.";
+        list path-route-object {
+          key "index";
+          ordered-by user;
+          description
+            "List of route objects either returned by the computation
+             engine or actually used by an LSP.";
+          leaf index {
+            type uint32;
+            description
+              "Route object entry index.  The index is used to
+               identify an entry in the list.  The order of entries
+               is defined by the user without relying on key
+               values.";
+          }
+          uses explicit-route-hop;
+        }
+      }
+    }
+  }
+
+  grouping encoding-and-switching-type {
+    description
+      "Common grouping to define the LSP encoding and
+       switching types";
+    leaf encoding {
+      type identityref {
+        base te-types:lsp-encoding-types;
+      }
+      description
+        "LSP encoding type.";
+      reference
+        "RFC 3945: Generalized Multi-Protocol Label Switching (GMPLS)
+                   Architecture";
+    }
+    leaf switching-type {
+      type identityref {
+        base te-types:switching-capabilities;
+      }
+      description
+        "LSP switching type.";
+      reference
+        "RFC 3945: Generalized Multi-Protocol Label Switching (GMPLS)
+                   Architecture";
+    }
+  }
+
+  grouping te-generic-node-id {
+    description
+      "A reusable grouping for a TE generic node identifier.";
+    leaf id {
+      type union {
+        type te-node-id;
+        type inet:ip-address;
+        type nw:node-id;
+      }
+      description
+        "The identifier of the node.
+
+         It can be represented as IP address or dotted quad address
+         or as an URI.
+
+         The type data node disambiguates the union type.";
+    }
+    leaf type {
+      type enumeration {
+        enum ip {
+          description
+            "IP address representation of the node identifier.";
+        }
+        enum te-id {
+          description
+            "TE identifier of the node";
+        }
+        enum node-id {
+          description
+            "URI representation of the node identifier.";
+        }
+      }
+      description
+        "Type of node identifier representation.";
+    }
+  }
+}
diff --git a/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-vpn-common@2021-09-10.yang b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-vpn-common@2021-09-10.yang
new file mode 100644
index 0000000000000000000000000000000000000000..075437d3a43dd7d81f98f1103fd2e34e2571005b
--- /dev/null
+++ b/src/nbi/service/rest_server/nbi_plugins/ietf_network_slice/yang/ietf-vpn-common@2021-09-10.yang
@@ -0,0 +1,2205 @@
+module ietf-vpn-common {
+  yang-version 1.1;
+  namespace "urn:ietf:params:xml:ns:yang:ietf-vpn-common";
+  prefix vpn-common;
+
+  import ietf-netconf-acm {
+    prefix nacm;
+    reference
+      "RFC 8341: Network Configuration Access Control Model";
+  }
+  import ietf-routing-types {
+    prefix rt-types;
+    reference
+      "RFC 8294: Common YANG Data Types for the Routing Area";
+  }
+  import ietf-yang-types {
+    prefix yang;
+    reference
+      "RFC 6991: Common YANG Data Types, Section 3";
+  }
+  import ietf-packet-fields {
+    prefix packet-fields;
+    reference
+      "RFC 8519: YANG Data Model for Network Access
+                 Control Lists (ACLs)";
+  }
+
+  organization
+    "IETF OPSAWG (Operations and Management Area Working Group)";
+  contact
+    "WG Web:   <https://datatracker.ietf.org/wg/opsawg/>
+     WG List:  <mailto:opsawg@ietf.org>
+
+     Editor:  Mohamed Boucadair
+              <mailto:mohamed.boucadair@orange.com>
+     Author:  Samier Barguil
+              <mailto:samier.barguilgiraldo.ext@telefonica.com>
+     Author:  Oscar Gonzalez de Dios
+              <mailto:oscar.gonzalezdedios@telefonica.com>
+     Author:  Qin Wu
+              <mailto:bill.wu@huawei.com>";
+  description
+    "This YANG module defines a common module that is meant
+     to be reused by various VPN-related modules (e.g.,
+     Layer 3 VPN Service Model (L3SM), Layer 2 VPN Service
+     Model (L2SM), Layer 3 VPN Network Model (L3NM), Layer 2
+     VPN Network Model (L2NM)).
+
+     Copyright (c) 2021 IETF Trust and the persons identified as
+     authors of the code.  All rights reserved.
+
+     Redistribution and use in source and binary forms, with or
+     without modification, is permitted pursuant to, and subject
+     to the license terms contained in, the Simplified BSD License
+     set forth in Section 4.c of the IETF Trust's Legal Provisions
+     Relating to IETF Documents
+     (http://trustee.ietf.org/license-info).
+
+     This version of this YANG module is part of RFC XXXX; see
+     the RFC itself for full legal notices.";
+
+  revision 2021-09-10 {
+    description
+      "Initial revision.";
+    reference
+      "RFC XXXX: A Layer 2/3 VPN Common YANG Model";
+  }
+
+  /******** Collection of VPN-related Features ********/
+  /*
+   * Features related to encapsulation schemes
+   */
+
+  feature dot1q {
+    description
+      "Indicates the support for the Dot1q encapsulation.";
+    reference
+      "IEEE Std 802.1Q: Bridges and Bridged Networks";
+  }
+
+  feature qinq {
+    description
+      "Indicates the support for the QinQ encapsulation.";
+    reference
+      "IEEE Std 802.1ad: Provider Bridges";
+  }
+
+  feature vxlan {
+    description
+      "Indicates the support for the Virtual eXtensible
+       Local Area Network (VXLAN) encapsulation.";
+    reference
+      "RFC 7348: Virtual eXtensible Local Area  Network (VXLAN):
+                 A Framework for Overlaying Virtualized Layer 2
+                 Networks over Layer 3 Networks";
+  }
+
+  feature qinany {
+    description
+      "Indicates the support for the QinAny encapsulation.
+       The outer VLAN tag is set to a specific value but
+       the inner VLAN tag is set to any.";
+  }
+
+  feature lag-interface {
+    description
+      "Indicates the support for Link Aggregation Group (LAG)
+       between VPN network accesses.";
+    reference
+      "IEEE Std. 802.1AX: Link Aggregation";
+  }
+
+  /*
+   * Features related to multicast
+   */
+
+  feature multicast {
+    description
+      "Indicates multicast capabilities support in a VPN.";
+    reference
+      "RFC 6513: Multicast in MPLS/BGP IP VPNs";
+  }
+
+  feature igmp {
+    description
+      "Indicates support for Internet Group Management Protocol
+       (IGMP).";
+    reference
+      "RFC 1112: Host Extensions for IP Multicasting
+       RFC 2236: Internet Group Management Protocol, Version 2
+       RFC 3376: Internet Group Management Protocol, Version 3";
+  }
+
+  feature mld {
+    description
+      "Indicates support for Multicast Listener Discovery (MLD).";
+    reference
+      "RFC 2710: Multicast Listener Discovery (MLD) for IPv6
+       RFC 3810: Multicast Listener Discovery Version 2 (MLDv2)
+                 for IPv6";
+  }
+
+  feature pim {
+    description
+      "Indicates support for Protocol Independent Multicast (PIM).";
+    reference
+      "RFC 7761: Protocol Independent Multicast - Sparse Mode
+                (PIM-SM): Protocol Specification (Revised)";
+  }
+
+  /*
+   * Features related to address family types
+   */
+
+  feature ipv4 {
+    description
+      "Indicates IPv4 support in a VPN. That is, IPv4 traffic
+       can be carried in the VPN, IPv4 addresses/prefixes can
+       be assigned to a VPN network access, IPv4 routes can be
+       installed for the CE/PE link, etc.";
+    reference
+      "RFC 791: Internet Protocol";
+  }
+
+  feature ipv6 {
+    description
+      "Indicates IPv6 support in a VPN. That is, IPv6 traffic
+       can be carried in the VPN, IPv6 addresses/prefixes can
+       be assigned to a VPN network access, IPv6 routes can be
+       installed for the CE/PE link, etc.";
+    reference
+      "RFC 8200: Internet Protocol, Version 6 (IPv6)";
+  }
+
+  /*
+   * Features related to routing protocols
+   */
+
+  feature rtg-ospf {
+    description
+      "Indicates support for the OSPF as the Provider Edge (PE)/
+       Customer Edge (CE) routing protocol.";
+    reference
+      "RFC 4577: OSPF as the Provider/Customer Edge Protocol
+                 for BGP/MPLS IP Virtual Private Networks (VPNs)
+       RFC 6565: OSPFv3 as a Provider Edge to Customer Edge
+                 (PE-CE) Routing Protocol";
+  }
+
+  feature rtg-ospf-sham-link {
+    description
+      "Indicates support for OSPF sham links.";
+    reference
+      "RFC 4577: OSPF as the Provider/Customer Edge Protocol
+                 for BGP/MPLS IP Virtual Private Networks (VPNs),
+                 Section 4.2.7
+       RFC 6565: OSPFv3 as a Provider Edge to Customer Edge
+                 (PE-CE) Routing Protocol, Section 5";
+  }
+
+  feature rtg-bgp {
+    description
+      "Indicates support for BGP as the PE/CE routing protocol.";
+    reference
+      "RFC 4271: A Border Gateway Protocol 4 (BGP-4)";
+  }
+  feature rtg-rip {
+    description
+      "Indicates support for RIP as the PE/CE routing protocol.";
+    reference
+      "RFC 2453: RIP Version 2
+       RFC 2080: RIPng for IPv6";
+  }
+
+  feature rtg-isis {
+    description
+      "Indicates support for IS-IS as the PE/CE routing protocol.";
+    reference
+      "ISO10589: Intermediate System to Intermediate System intra-
+                 domain routeing information exchange protocol for
+                 use in conjunction with the protocol for providing
+                 the connectionless-mode network service
+                 (ISO 8473)";
+  }
+
+  feature rtg-vrrp {
+    description
+      "Indicates support for the Virtual Router Redundancy
+       Protocol (VRRP) in CE/PE link.";
+    reference
+      "RFC 5798: Virtual Router Redundancy Protocol (VRRP) Version 3
+                 for IPv4 and IPv6";
+  }
+
+  feature bfd {
+    description
+      "Indicates support for Bidirectional Forwarding Detection (BFD)
+       between the CE and the PE.";
+    reference
+      "RFC 5880: Bidirectional Forwarding Detection (BFD)";
+  }
+
+  /*
+   * Features related to VPN service constraints
+   */
+
+  feature bearer-reference {
+    description
+      "A bearer refers to properties of the CE-PE attachment that
+       are below Layer 3.
+       This feature indicates support for the bearer reference access
+       constraint. That is, the reuse of a network connection that was
+       already ordered to the service provider apart from the IP VPN
+       site.";
+  }
+
+  feature placement-diversity {
+    description
+      "Indicates support for placement diversity constraints in the
+       customer premises. An example of these constraints may be to
+       avoid connecting a site network access to the same Provider
+       Edge as a target site network access.";
+  }
+
+  /*
+   * Features related to bandwidth and Quality of Service (QoS)
+   */
+
+  feature qos {
+    description
+      "Indicates support for Classes of Service (CoSes) in the VPN.";
+  }
+
+  feature inbound-bw {
+    description
+      "Indicates support for the inbound bandwidth in a VPN. That is,
+       support for specifying the download bandwidth from the service
+       provider network to the VPN site. Note that the L3SM uses
+       'input' to identify the same feature. That terminology should
+       be deprecated in favor of the one defined in this module.";
+  }
+
+  feature outbound-bw {
+    description
+      "Indicates support for the outbound bandwidth in a VPN. That is,
+       support for specifying the upload bandwidth from the VPN site
+       to the service provider network. Note that the L3SM uses
+       'output' to identify the same feature. That terminology should
+       be deprecated in favor of the one defined in this module.";
+  }
+
+  /*
+   * Features related to security and resilience
+   */
+
+  feature encryption {
+    description
+      "Indicates support for encryption in the VPN.";
+  }
+
+  feature fast-reroute {
+    description
+      "Indicates support for Fast Reroute (FRR) capabilities for
+       a VPN site.";
+  }
+
+  /*
+   * Features related to advanced VPN options
+   */
+
+  feature external-connectivity {
+    description
+      "Indicates support for the VPN to provide external
+       connectivity (e.g., Internet, private or public cloud).";
+    reference
+      "RFC 4364: BGP/MPLS IP Virtual Private Networks
+                 (VPNs), Section 11";
+  }
+
+  feature extranet-vpn {
+    description
+      "Indicates support for extranet VPNs. That is, the capability of
+       a VPN to access a list of other VPNs.";
+    reference
+      "RFC 4364: BGP/MPLS IP Virtual Private Networks
+                 (VPNs), Section 1.1";
+  }
+
+  feature carriers-carrier {
+    description
+      "Indicates support for Carrier-of-Carrier VPNs.";
+    reference
+      "RFC 4364: BGP/MPLS IP Virtual Private Networks
+                 (VPNs), Section 9";
+  }
+
+  /*
+   * Address family related identities
+   */
+
+  identity address-family {
+    description
+      "Defines a type for the address family.";
+  }
+
+  identity ipv4 {
+    base address-family;
+    description
+      "Identity for IPv4 address family.";
+  }
+  identity ipv6 {
+    base address-family;
+    description
+      "Identity for IPv6 address family.";
+  }
+
+  identity dual-stack {
+    base address-family;
+    description
+      "Identity for IPv4 and IPv6 address family.";
+  }
+
+  /*
+   * Identities related to VPN topology
+   */
+
+  identity vpn-topology {
+    description
+      "Base identity of the VPN topology.";
+  }
+
+  identity any-to-any {
+    base vpn-topology;
+    description
+      "Identity for any-to-any VPN topology. All VPN sites
+       can communicate with each other without any restrictions.";
+  }
+
+  identity hub-spoke {
+    base vpn-topology;
+    description
+      "Identity for Hub-and-Spoke VPN topology. All Spokes can
+       communicate only with Hubs but not with each other. Hubs
+       can communicate with each other.";
+  }
+
+  identity hub-spoke-disjoint {
+    base vpn-topology;
+    description
+      "Identity for Hub-and-Spoke VPN topology where Hubs cannot
+       communicate with each other.";
+  }
+
+  identity custom {
+    base vpn-topology;
+    description
+      "Identity for custom VPN topologies where the role of the nodes
+       is not strictly Hub or Spoke. The VPN topology is controlled by
+       the import/export policies. The custom topology reflects more
+       complex VPN nodes such as VPN node that acts as Hub for certain
+       nodes and Spoke to others.";
+  }
+
+  /*
+   * Identities related to network access types
+   */
+
+  identity site-network-access-type {
+    description
+      "Base identity for site network access type.";
+  }
+
+  identity point-to-point {
+    base site-network-access-type;
+    description
+      "Point-to-point access type.";
+  }
+
+  identity multipoint {
+    base site-network-access-type;
+    description
+      "Multipoint access type.";
+  }
+
+  identity irb {
+    base site-network-access-type;
+    description
+      "Integrated Routing Bridge (IRB).
+       Identity for pseudowire connections.";
+  }
+
+  identity loopback {
+    base site-network-access-type;
+    description
+      "Loopback access type.";
+  }
+
+  /*
+   * Identities related to operational and administrative status
+   */
+
+  identity operational-status {
+    description
+      "Base identity for the operational status.";
+  }
+
+  identity op-up {
+    base operational-status;
+    description
+      "Operational status is Up/Enabled.";
+  }
+
+  identity op-down {
+    base operational-status;
+    description
+      "Operational status is Down/Disabled.";
+  }
+
+  identity op-unknown {
+    base operational-status;
+    description
+      "Operational status is Unknown.";
+  }
+
+  identity administrative-status {
+    description
+      "Base identity for administrative status.";
+  }
+
+  identity admin-up {
+    base administrative-status;
+    description
+      "Administrative status is Up/Enabled.";
+  }
+
+  identity admin-down {
+    base administrative-status;
+    description
+      "Administrative status is Down/Disabled.";
+  }
+
+  identity admin-testing {
+    base administrative-status;
+    description
+      "Administrative status is up for testing purposes.";
+  }
+
+  identity admin-pre-deployment {
+    base administrative-status;
+    description
+      "Administrative status is pre-deployment phase. That is,
+       prior to the actual deployment of a service.";
+  }
+
+  /*
+   * Identities related to site or node role
+   */
+
+  identity role {
+    description
+      "Base identity of a site or a node role.";
+  }
+
+  identity any-to-any-role {
+    base role;
+    description
+      "Any-to-any role.";
+  }
+
+  identity spoke-role {
+    base role;
+    description
+      "A node or a site is acting as a Spoke.";
+  }
+
+  identity hub-role {
+    base role;
+    description
+      "A node or a site is acting as a Hub.";
+  }
+
+  identity custom-role {
+    base role;
+    description
+      "VPN node with custom or complex role in the VPN. For some
+       sources/destinations it can behave as a Hub, but for others it
+       can act as a Spoke depending on the configured policy.";
+  }
+
+  /*
+   * Identities related to VPN service constraints
+   */
+
+  identity placement-diversity {
+    description
+      "Base identity for access placement constraints.";
+  }
+
+  identity bearer-diverse {
+    base placement-diversity;
+    description
+      "Bearer diversity.
+       The bearers should not use common elements.";
+  }
+
+  identity pe-diverse {
+    base placement-diversity;
+    description
+      "PE diversity.";
+  }
+
+  identity pop-diverse {
+    base placement-diversity;
+    description
+      "Point Of Presence (POP) diversity.";
+  }
+
+  identity linecard-diverse {
+    base placement-diversity;
+    description
+      "Linecard diversity.";
+  }
+
+  identity same-pe {
+    base placement-diversity;
+    description
+      "Having sites connected on the same PE.";
+  }
+
+  identity same-bearer {
+    base placement-diversity;
+    description
+      "Having sites connected using the same bearer.";
+  }
+
+  /*
+   * Identities related to service types
+   */
+
+  identity service-type {
+    description
+      "Base identity for service type.";
+  }
+
+  identity l3vpn {
+    base service-type;
+    description
+      "L3VPN service.";
+    reference
+      "RFC 4364: BGP/MPLS IP Virtual Private Networks (VPNs)";
+  }
+
+  identity vpls {
+    base service-type;
+    description
+      "VPLS service.";
+    reference
+      "RFC 4761: Virtual Private LAN Service (VPLS) Using BGP for
+                 Auto-Discovery and Signaling
+       RFC 4762: Virtual Private LAN Service (VPLS) Using Label
+                 Distribution Protocol (LDP) Signaling";
+  }
+
+  identity vpws {
+    base service-type;
+    description
+      "Virtual Private Wire Service (VPWS) service.";
+    reference
+      "RFC 4664: Framework for Layer 2 Virtual Private Networks
+                 (L2VPNs), Section 3.1.1";
+  }
+
+  identity vpws-evpn {
+    base service-type;
+    description
+      "EVPN used to support VPWS service.";
+    reference
+      "RFC 8214: Virtual Private Wire Service Support in Ethernet VPN";
+  }
+
+  identity pbb-evpn {
+    base service-type;
+    description
+      "Provider Backbone Bridging (PBB) EVPNs service.";
+    reference
+      "RFC 7623: Provider Backbone Bridging Combined with Ethernet VPN
+                (PBB-EVPN)";
+  }
+
+  identity mpls-evpn {
+    base service-type;
+    description
+      "MPLS-based EVPN service.";
+    reference
+      "RFC 7432: BGP MPLS-Based Ethernet VPN";
+  }
+
+  identity vxlan-evpn {
+    base service-type;
+    description
+      "VXLAN-based EVPN service.";
+    reference
+      "RFC 8365: A Network Virtualization Overlay Solution Using
+                 Ethernet VPN (EVPN)";
+  }
+
+  /*
+   * Identities related to VPN signaling type
+   */
+
+  identity vpn-signaling-type {
+    description
+      "Base identity for VPN signaling types";
+  }
+
+  identity bgp-signaling {
+    base vpn-signaling-type;
+    description
+      "Layer 2 VPNs using BGP signaling.";
+    reference
+      "RFC 6624: Layer 2 Virtual Private Networks Using BGP for
+                 Auto-Discovery and Signaling
+       RFC 7432: BGP MPLS-Based Ethernet VPN";
+  }
+
+  identity ldp-signaling {
+    base vpn-signaling-type;
+    description
+      "Targeted Label Distribution Protocol (LDP) signaling.";
+    reference
+      "RFC 5036: LDP Specification";
+  }
+
+  identity l2tp-signaling {
+    base vpn-signaling-type;
+    description
+      "Layer Two Tunneling Protocol (L2TP) signaling.";
+    reference
+      "RFC 3931: Layer Two Tunneling Protocol - Version 3 (L2TPv3)";
+  }
+
+  /*
+   * Identities related to routing protocols
+   */
+
+  identity routing-protocol-type {
+    description
+      "Base identity for routing protocol type.";
+  }
+
+  identity static-routing {
+    base routing-protocol-type;
+    description
+      "Static routing protocol.";
+  }
+
+  identity bgp-routing {
+    if-feature "rtg-bgp";
+    base routing-protocol-type;
+    description
+      "BGP routing protocol.";
+    reference
+      "RFC 4271: A Border Gateway Protocol 4 (BGP-4)";
+  }
+
+  identity ospf-routing {
+    if-feature "rtg-ospf";
+    base routing-protocol-type;
+    description
+      "OSPF routing protocol.";
+    reference
+      "RFC 4577: OSPF as the Provider/Customer Edge Protocol
+                 for BGP/MPLS IP Virtual Private Networks(VPNs)
+       RFC 6565: OSPFv3 as a Provider Edge to Customer Edge
+                 (PE-CE) Routing Protocol";
+  }
+
+  identity rip-routing {
+    if-feature "rtg-rip";
+    base routing-protocol-type;
+    description
+      "RIP routing protocol.";
+    reference
+      "RFC 2453: RIP Version 2
+       RFC 2080: RIPng for IPv6";
+  }
+
+  identity isis-routing {
+    if-feature "rtg-isis";
+    base routing-protocol-type;
+    description
+      "IS-IS routing protocol.";
+    reference
+      "ISO10589: Intermediate System to Intermediate System intra-
+                 domain routeing information exchange protocol for
+                 use in conjunction with the protocol for providing
+                 the connectionless-mode network service
+                 (ISO 8473)";
+  }
+
+  identity vrrp-routing {
+    if-feature "rtg-vrrp";
+    base routing-protocol-type;
+    description
+      "VRRP protocol.
+
+       This is to be used when LANs are directly connected to PEs.";
+    reference
+      "RFC 5798: Virtual Router Redundancy Protocol (VRRP) Version 3
+                 for IPv4 and IPv6";
+  }
+
+  identity direct-routing {
+    base routing-protocol-type;
+    description
+      "Direct routing.
+
+       This is to be used when LANs are directly connected to PEs
+       and must be advertised in the VPN.";
+  }
+
+  identity any-routing {
+    base routing-protocol-type;
+    description
+      "Any routing protocol.
+
+       This can be, e.g., used to set policies that apply to any
+       routing protocol in place.";
+  }
+
+  identity isis-level {
+    if-feature "rtg-isis";
+    description
+      "Base identity for the IS-IS level.";
+    reference
+      "ISO10589: Intermediate System to Intermediate System intra-
+                 domain routeing information exchange protocol for
+                 use in conjunction with the protocol for providing
+                 the connectionless-mode network service
+                 (ISO 8473)";
+  }
+
+  identity level-1 {
+    base isis-level;
+    description
+      "IS-IS level 1.";
+  }
+
+  identity level-2 {
+    base isis-level;
+    description
+      "IS-IS level 2.";
+  }
+
+  identity level-1-2 {
+    base isis-level;
+    description
+      "IS-IS levels 1 and 2.";
+  }
+
+  identity bfd-session-type {
+    if-feature "bfd";
+    description
+      "Base identity for the BFD session type.";
+  }
+
+  identity classic-bfd {
+    base bfd-session-type;
+    description
+      "Classic BFD.";
+    reference
+      "RFC 5880: Bidirectional Forwarding Detection (BFD)";
+  }
+
+  identity s-bfd {
+    base bfd-session-type;
+    description
+      "Seamless BFD.";
+    reference
+      "RFC 7880: Seamless Bidirectional Forwarding Detection (S-BFD)";
+  }
+
+  /*
+   * Identities related to Routes Import and Export
+   */
+
+  identity ie-type {
+    description
+      "Base identity for 'import/export' routing profiles.
+       These profiles can be reused between VPN nodes.";
+  }
+
+  identity import {
+    base ie-type;
+    description
+      "'Import' routing profile.";
+    reference
+      "RFC 4364: BGP/MPLS IP Virtual Private Networks
+                 (VPNs), Section 4.3.1";
+  }
+
+  identity export {
+    base ie-type;
+    description
+      "'Export' routing profile.";
+    reference
+      "RFC 4364: BGP/MPLS IP Virtual Private Networks
+                 (VPNs), Section 4.3.1";
+  }
+
+  identity import-export {
+    base ie-type;
+    description
+      "'Import/export' routing profile.";
+  }
+
+  /*
+   * Identities related to bandwidth and QoS
+   */
+
+  identity bw-direction {
+    description
+      "Base identity for the bandwidth direction.";
+  }
+
+  identity inbound-bw {
+    if-feature "inbound-bw";
+    base bw-direction;
+    description
+      "Inbound bandwidth.";
+  }
+
+  identity outbound-bw {
+    if-feature "outbound-bw";
+    base bw-direction;
+    description
+      "Outbound bandwidth.";
+  }
+  identity bw-type {
+    description
+      "Base identity for the bandwidth type.";
+  }
+
+  identity bw-per-cos {
+    if-feature "qos";
+    base bw-type;
+    description
+      "The bandwidth is per-CoS.";
+  }
+
+  identity bw-per-port {
+    base bw-type;
+    description
+      "The bandwidth is per-site network access.";
+  }
+
+  identity bw-per-site {
+    base bw-type;
+    description
+      "The bandwidth is per-site. It is applicable to all the site
+       network accesses within a site.";
+  }
+
+  identity bw-per-service {
+    base bw-type;
+    description
+      "The bandwidth is per-VPN service.";
+  }
+
+  identity qos-profile-direction {
+    if-feature "qos";
+    description
+      "Base identity for the QoS profile direction.";
+  }
+
+  identity site-to-wan {
+    base qos-profile-direction;
+    description
+      "Customer site to provider's network direction.
+       This is typically the CE-to-PE direction.";
+  }
+
+  identity wan-to-site {
+    base qos-profile-direction;
+    description
+      "Provider's network to customer site direction.
+       This is typically the PE-to-CE direction.";
+  }
+
+  identity both {
+    base qos-profile-direction;
+    description
+      "Both WAN-to-Site and Site-to-WAN directions.";
+  }
+
+  /*
+   *  Identities related to underlay transport instances
+   */
+
+  identity transport-instance-type {
+    description
+      "Base identity for underlay transport instance type.";
+  }
+
+  identity virtual-network {
+    base transport-instance-type;
+    description
+      "Virtual network.";
+    reference
+      "RFC 8453: Framework for Abstraction and Control of TE
+                 Networks (ACTN)";
+  }
+
+  identity enhanced-vpn {
+    base transport-instance-type;
+    description
+      "Enhanced VPN (VPN+). VPN+ is an approach that is
+       based on existing VPN and Traffic Engineering (TE)
+       technologies but adds characteristics that specific
+       services require over and above classical VPNs.";
+    reference
+      "I-D.ietf-teas-enhanced-vpn:
+         A Framework for Enhanced Virtual Private Network
+         (VPN+) Services";
+  }
+
+  identity ietf-network-slice {
+    base transport-instance-type;
+    description
+      "IETF network slice. An IETF network slice
+       is a logical network topology connecting a number of
+       endpoints using a set of shared or dedicated network
+       resources that are used to satisfy specific service
+       objectives.";
+    reference
+      "I-D.ietf-teas-ietf-network-slices:
+         Framework for IETF Network Slices";
+  }
+
+  /*
+   *  Identities related to protocol types. These types are typically
+   *  used to identify the underlay transport.
+   */
+
+  identity protocol-type {
+    description
+      "Base identity for Protocol Type.";
+  }
+
+  identity ip-in-ip {
+    base protocol-type;
+    description
+      "Transport is based on IP-in-IP.";
+    reference
+      "RFC 2003: IP Encapsulation within IP
+       RFC 2473: Generic Packet Tunneling in IPv6 Specification";
+  }
+
+  identity ip-in-ipv4 {
+    base ip-in-ip;
+    description
+      "Transport is based on IP over IPv4.";
+    reference
+      "RFC 2003: IP Encapsulation within IP";
+  }
+
+  identity ip-in-ipv6 {
+    base ip-in-ip;
+    description
+      "Transport is based on IP over IPv6.";
+    reference
+      "RFC 2473: Generic Packet Tunneling in IPv6 Specification";
+  }
+
+  identity gre {
+    base protocol-type;
+    description
+      "Transport is based on Generic Routing Encapsulation (GRE).";
+    reference
+      "RFC 1701: Generic Routing Encapsulation (GRE)
+       RFC 1702: Generic Routing Encapsulation over IPv4 networks
+       RFC 7676: IPv6 Support for Generic Routing Encapsulation (GRE)";
+  }
+
+  identity gre-v4 {
+    base gre;
+    description
+      "Transport is based on GRE over IPv4.";
+    reference
+      "RFC 1702: Generic Routing Encapsulation over IPv4 networks";
+  }
+
+  identity gre-v6 {
+    base gre;
+    description
+      "Transport is based on GRE over IPv6.";
+    reference
+      "RFC 7676: IPv6 Support for Generic Routing Encapsulation (GRE)";
+  }
+
+  identity vxlan-trans {
+    base protocol-type;
+    description
+      "Transport is based on VXLAN.";
+    reference
+      "RFC 7348: Virtual eXtensible Local Area  Network (VXLAN):
+                 A Framework for Overlaying Virtualized Layer 2
+                 Networks over Layer 3 Networks";
+  }
+
+  identity geneve {
+    base protocol-type;
+    description
+      "Transport is based on Generic Network Virtualization
+       Encapsulation (GENEVE).";
+    reference
+      "RFC 8926: Geneve: Generic Network Virtualization Encapsulation";
+  }
+
+  identity ldp {
+    base protocol-type;
+    description
+      "Transport is based on LDP.";
+    reference
+      "RFC 5036: LDP Specification";
+  }
+
+  identity mpls-in-udp {
+    base protocol-type;
+    description
+      "Transport is MPLS in UDP.";
+    reference
+      "RFC 7510: Encapsulating MPLS in UDP";
+  }
+
+  identity sr {
+    base protocol-type;
+    description
+      "Transport is based on Segment Routing (SR).";
+    reference
+      "RFC 8660: Segment Routing with the MPLS Data Plane
+       RFC 8663: MPLS Segment Routing over IP
+       RFC 8754: IPv6 Segment Routing Header (SRH)";
+  }
+
+  identity sr-mpls {
+    base sr;
+    description
+      "Transport is based on SR with MPLS.";
+    reference
+      "RFC 8660: Segment Routing with the MPLS Data Plane";
+  }
+
+  identity srv6 {
+    base sr;
+    description
+      "Transport is based on SR over IPv6.";
+    reference
+      "RFC 8754: IPv6 Segment Routing Header (SRH)";
+  }
+
+  identity sr-mpls-over-ip {
+    base sr;
+    description
+      "Transport is based on SR over MPLS over IP.";
+    reference
+      "RFC 8663: MPLS Segment Routing over IP";
+  }
+
+  identity rsvp-te {
+    base protocol-type;
+    description
+      "Transport setup relies upon RSVP-TE.";
+    reference
+      "RFC 3209: RSVP-TE: Extensions to RSVP for LSP Tunnels";
+  }
+
+  identity bgp-lu {
+    base protocol-type;
+    description
+      "Transport setup relies upon BGP-LU.";
+    reference
+      "RFC 8277: Using BGP to Bind MPLS Labels to Address Prefixes";
+  }
+
+  identity unknown {
+    base protocol-type;
+    description
+      "Not known protocol type.";
+  }
+
+  /*
+   * Identities related to encapsulations
+   */
+
+  identity encapsulation-type {
+    description
+      "Base identity for the encapsulation type.";
+  }
+
+  identity priority-tagged {
+    base encapsulation-type;
+    description
+      "Priority-tagged interface.";
+  }
+
+  identity dot1q {
+    if-feature "dot1q";
+    base encapsulation-type;
+    description
+      "Dot1q encapsulation.";
+  }
+
+  identity qinq {
+    if-feature "qinq";
+    base encapsulation-type;
+    description
+      "QinQ encapsulation.";
+  }
+
+  identity qinany {
+    if-feature "qinany";
+    base encapsulation-type;
+    description
+      "QinAny encapsulation.";
+  }
+  identity vxlan {
+    if-feature "vxlan";
+    base encapsulation-type;
+    description
+      "VxLAN encapsulation.";
+  }
+
+  identity ethernet-type {
+    base encapsulation-type;
+    description
+      "Ethernet encapsulation type.";
+  }
+
+  identity vlan-type {
+    base encapsulation-type;
+    description
+      "VLAN encapsulation type.";
+  }
+
+  identity untagged-int {
+    base encapsulation-type;
+    description
+      "Untagged interface type.";
+  }
+
+  identity tagged-int {
+    base encapsulation-type;
+    description
+      "Tagged interface type.";
+  }
+
+  identity lag-int {
+    if-feature "lag-interface";
+    base encapsulation-type;
+    description
+      "LAG interface type.";
+  }
+
+  /*
+   * Identities related to VLAN Tag
+   */
+
+  identity tag-type {
+    description
+      "Base identity for the tag types.";
+  }
+
+  identity c-vlan {
+    base tag-type;
+    description
+      "Indicates Customer VLAN (C-VLAN) tag, normally using
+       the 0x8100 Ethertype.";
+  }
+
+  identity s-vlan {
+    base tag-type;
+    description
+      "Indicates Service VLAN (S-VLAN) tag.";
+  }
+
+  identity s-c-vlan {
+    base tag-type;
+    description
+      "Uses both an S-VLAN tag and a C-VLAN tag.";
+  }
+
+  /*
+   * Identities related to VXLAN
+   */
+
+  identity vxlan-peer-mode {
+    if-feature "vxlan";
+    description
+      "Base identity for the VXLAN peer mode.";
+  }
+
+  identity static-mode {
+    base vxlan-peer-mode;
+    description
+      "VXLAN access in the static mode.";
+  }
+
+  identity bgp-mode {
+    base vxlan-peer-mode;
+    description
+      "VXLAN access by BGP EVPN learning.";
+  }
+
+  /*
+   * Identities related to multicast
+   */
+
+  identity multicast-gp-address-mapping {
+    if-feature "multicast";
+    description
+      "Base identity for multicast group mapping type.";
+  }
+
+  identity static-mapping {
+    base multicast-gp-address-mapping;
+    description
+      "Static mapping, i.e., attach the interface to the
+       multicast group as a static member.";
+  }
+
+  identity dynamic-mapping {
+    base multicast-gp-address-mapping;
+    description
+      "Dynamic mapping, i.e., an interface is added to the
+       multicast group as a result of snooping.";
+  }
+
+  identity multicast-tree-type {
+    if-feature "multicast";
+    description
+      "Base identity for multicast tree type.";
+  }
+
+  identity ssm-tree-type {
+    base multicast-tree-type;
+    description
+      "Source-Specific Multicast (SSM) tree type.";
+  }
+
+  identity asm-tree-type {
+    base multicast-tree-type;
+    description
+      "Any-Source Multicast (ASM) tree type.";
+  }
+
+  identity bidir-tree-type {
+    base multicast-tree-type;
+    description
+      "Bidirectional tree type.";
+  }
+
+  identity multicast-rp-discovery-type {
+    if-feature "multicast";
+    description
+      "Base identity for Rendezvous Point (RP) discovery type.";
+  }
+
+  identity auto-rp {
+    base multicast-rp-discovery-type;
+    description
+      "Auto-RP discovery type.";
+  }
+
+  identity static-rp {
+    base multicast-rp-discovery-type;
+    description
+      "Static type.";
+  }
+
+  identity bsr-rp {
+    base multicast-rp-discovery-type;
+    description
+      "Bootstrap Router (BSR) discovery type.";
+  }
+
+  identity group-management-protocol {
+    if-feature "multicast";
+    description
+      "Base identity for multicast group management protocol.";
+  }
+
+  identity igmp-proto {
+    base group-management-protocol;
+    description
+      "IGMP.";
+    reference
+      "RFC 1112: Host Extensions for IP Multicasting
+       RFC 2236: Internet Group Management Protocol, Version 2
+       RFC 3376: Internet Group Management Protocol, Version 3";
+  }
+
+  identity mld-proto {
+    base group-management-protocol;
+    description
+      "MLD.";
+    reference
+      "RFC 2710: Multicast Listener Discovery (MLD) for IPv6
+       RFC 3810: Multicast Listener Discovery Version 2 (MLDv2)
+                 for IPv6";
+  }
+
+  identity pim-proto {
+    if-feature "pim";
+    base routing-protocol-type;
+    description
+      "PIM.";
+    reference
+      "RFC 7761: Protocol Independent Multicast - Sparse Mode
+                (PIM-SM): Protocol Specification (Revised)";
+  }
+
+  identity igmp-version {
+    if-feature "igmp";
+    description
+      "Base identity for IGMP version.";
+  }
+
+  identity igmpv1 {
+    base igmp-version;
+    description
+      "IGMPv1.";
+    reference
+      "RFC 1112: Host Extensions for IP Multicasting";
+  }
+
+  identity igmpv2 {
+    base igmp-version;
+    description
+      "IGMPv2.";
+    reference
+      "RFC 2236: Internet Group Management Protocol, Version 2";
+  }
+
+  identity igmpv3 {
+    base igmp-version;
+    description
+      "IGMPv3.";
+    reference
+      "RFC 3376: Internet Group Management Protocol, Version 3";
+  }
+
+  identity mld-version {
+    if-feature "mld";
+    description
+      "Base identity for MLD version.";
+  }
+
+  identity mldv1 {
+    base mld-version;
+    description
+      "MLDv1.";
+    reference
+      "RFC 2710: Multicast Listener Discovery (MLD) for IPv6";
+  }
+
+  identity mldv2 {
+    base mld-version;
+    description
+      "MLDv2.";
+    reference
+      "RFC 3810: Multicast Listener Discovery Version 2 (MLDv2)
+                 for IPv6";
+  }
+
+  /*
+   * Identities related to traffic types
+   */
+
+  identity tf-type {
+    description
+      "Base identity for the traffic type.";
+  }
+
+  identity multicast-traffic {
+    base tf-type;
+    description
+      "Multicast traffic.";
+  }
+
+  identity broadcast-traffic {
+    base tf-type;
+    description
+      "Broadcast traffic.";
+  }
+
+  identity unknown-unicast-traffic {
+    base tf-type;
+    description
+      "Unknown unicast traffic.";
+  }
+
+  /*
+   * Identities related to customer applications
+   */
+
+  identity customer-application {
+    description
+      "Base identity for customer applications.";
+  }
+
+  identity web {
+    base customer-application;
+    description
+      "Web applications (e.g., HTTP, HTTPS).";
+  }
+
+  identity mail {
+    base customer-application;
+    description
+      "Mail application.";
+  }
+
+  identity file-transfer {
+    base customer-application;
+    description
+      "File transfer application (e.g., FTP, SFTP).";
+  }
+
+  identity database {
+    base customer-application;
+    description
+      "Database application.";
+  }
+
+  identity social {
+    base customer-application;
+    description
+      "Social-network application.";
+  }
+
+  identity games {
+    base customer-application;
+    description
+      "Gaming application.";
+  }
+
+  identity p2p {
+    base customer-application;
+    description
+      "Peer-to-peer application.";
+  }
+
+  identity network-management {
+    base customer-application;
+    description
+      "Management application (e.g., Telnet, syslog,
+       SNMP).";
+  }
+
+  identity voice {
+    base customer-application;
+    description
+      "Voice application.";
+  }
+
+  identity video {
+    base customer-application;
+    description
+      "Video conference application.";
+  }
+
+  identity embb {
+    base customer-application;
+    description
+      "Enhanced Mobile Broadband (eMBB) application.
+       Note that an eMBB application demands network performance with a
+       wide variety of characteristics, such as data rate, latency,
+       loss rate, reliability, and many other parameters.";
+  }
+
+  identity urllc {
+    base customer-application;
+    description
+      "Ultra-Reliable and Low Latency Communications
+       (URLLC) application.  Note that an URLLC application demands
+       network performance with a wide variety of characteristics, such
+       as latency, reliability, and many other parameters.";
+  }
+
+  identity mmtc {
+    base customer-application;
+    description
+      "Massive Machine Type Communications (mMTC) application.
+       Note that an mMTC application demands network performance with
+       a wide variety of characteristics, such as data rate, latency,
+       loss rate, reliability, and many other parameters.";
+  }
+
+  /*
+   * Identities related to service bundling
+   */
+
+  identity bundling-type {
+    description
+      "The base identity for the bundling type. It supports a subset or
+       all CE-VLANs associated with an L2VPN service.";
+  }
+
+  identity multi-svc-bundling {
+    base bundling-type;
+    description
+      "Multi-service bundling, i.e., multiple C-VLAN IDs
+       can be associated with an L2VPN service at a site.";
+  }
+
+  identity one2one-bundling {
+    base bundling-type;
+    description
+      "One-to-one service bundling, i.e., each L2VPN can
+       be associated with only one C-VLAN ID at a site.";
+  }
+
+  identity all2one-bundling {
+    base bundling-type;
+    description
+      "All-to-one bundling, i.e., all C-VLAN IDs are mapped
+       to one L2VPN service.";
+  }
+
+  /*
+   * Identities related to Ethernet Services
+   */
+
+  identity control-mode {
+    description
+      "Base Identity for the type of control mode on Layer 2
+       Control Protocol (L2CP).";
+  }
+
+  identity peer {
+    base control-mode;
+    description
+      "'peer' mode, i.e., participate in the protocol towards the CE.
+       Peering is common for Link Aggregation Control Protocol (LACP)
+       and the Ethernet Local Management Interface (E-LMI) and,
+       occasionally, for Link Layer Discovery Protocol (LLDP).
+       For VPLSs and VPWSs, the subscriber can also request that the
+       peer service provider enables spanning tree.";
+  }
+
+  identity tunnel {
+    base control-mode;
+    description
+      "'tunnel' mode, i.e., pass to the egress or destination site. For
+       Ethernet Private Lines (EPLs), the expectation is that L2CP
+       frames are tunnelled.";
+  }
+  identity discard {
+    base control-mode;
+    description
+      "'Discard' mode, i.e., discard the frame.";
+  }
+
+  identity neg-mode {
+    description
+      "Base identity for the negotiation mode.";
+  }
+
+  identity full-duplex {
+    base neg-mode;
+    description
+      "Full-duplex negotiation mode.";
+  }
+
+  identity auto-neg {
+    base neg-mode;
+    description
+      "Auto-negotiation mode.";
+  }
+
+  /******** Collection of VPN-related Types ********/
+
+  typedef vpn-id {
+    type string;
+    description
+      "Defines an identifier that is used with a VPN module.
+       This can be, for example, a service identifier, a node
+       identifier, etc.";
+  }
+
+  /******* VPN-related reusable groupings *******/
+
+  grouping vpn-description {
+    description
+      "Provides common VPN information.";
+    leaf vpn-id {
+      type vpn-common:vpn-id;
+      description
+        "A VPN identifier that uniquely identifies a VPN.
+         This identifier has a local meaning, e.g., within
+         a service provider network.";
+    }
+    leaf vpn-name {
+      type string;
+      description
+        "Used to associate a name with the service
+         in order to facilitate the identification of
+         the service.";
+    }
+    leaf vpn-description {
+      type string;
+      description
+        "Textual description of a VPN.";
+    }
+    leaf customer-name {
+      type string;
+      description
+        "Name of the customer that actually uses the VPN.";
+    }
+  }
+
+  grouping vpn-profile-cfg {
+    description
+      "Grouping for VPN Profile configuration.";
+    container valid-provider-identifiers {
+      description
+        "Container for valid provider profile identifiers.";
+      list external-connectivity-identifier {
+        if-feature "external-connectivity";
+        key "id";
+        description
+          "List for profile identifiers that uniquely identify profiles
+           governing how external connectivity is provided to a VPN.
+           A profile indicates the type of external connectivity
+           (Internet, cloud, etc.), the sites/nodes that are associated
+           with a connectivity profile, etc. A profile can also indicate
+           filtering rules and/or address translation rules. Such
+           features may involve PE, P, or dedicated nodes as a function
+           of the deployment.";
+        leaf id {
+          type string;
+          description
+            "Identification of an external connectivity profile. The
+             profile only has significance within the service provider's
+             administrative domain.";
+        }
+      }
+      list encryption-profile-identifier {
+        key "id";
+        description
+          "List for encryption profile identifiers.";
+        leaf id {
+          type string;
+          description
+            "Identification of the encryption profile to be used. The
+             profile only has significance within the service provider's
+             administrative domain.";
+        }
+      }
+      list qos-profile-identifier {
+        key "id";
+        description
+          "List for QoS Profile Identifiers.";
+        leaf id {
+          type string;
+          description
+            "Identification of the QoS profile to be used. The
+             profile only has significance within the service provider's
+             administrative domain.";
+        }
+      }
+      list bfd-profile-identifier {
+        key "id";
+        description
+          "List for BFD profile identifiers.";
+        leaf id {
+          type string;
+          description
+            "Identification of the BFD profile to be used. The
+             profile only has significance within the service provider's
+             administrative domain.";
+        }
+      }
+      list forwarding-profile-identifier {
+        key "id";
+        description
+          "List for forwarding profile identifiers.";
+        leaf id {
+          type string;
+          description
+            "Identification of the forwarding profile to be used.
+             The profile only has significance within the service
+             provider's administrative domain.";
+        }
+      }
+      list routing-profile-identifier {
+        key "id";
+        description
+          "List for Routing Profile Identifiers.";
+        leaf id {
+          type string;
+          description
+            "Identification of the routing profile to be used by the
+             routing protocols within sites, vpn-network-accesses, or
+             vpn-nodes for refering VRF's import/export policies.
+
+             The profile only has significance within the service
+             provider's administrative domain.";
+        }
+      }
+      nacm:default-deny-write;
+    }
+  }
+
+  grouping oper-status-timestamp {
+    description
+      "This grouping defines some operational parameters for the
+       service.";
+    leaf status {
+      type identityref {
+        base operational-status;
+      }
+      config false;
+      description
+        "Operations status.";
+    }
+    leaf last-change {
+      type yang:date-and-time;
+      config false;
+      description
+        "Indicates the actual date and time of the service status
+         change.";
+    }
+  }
+
+  grouping service-status {
+    description
+      "Service status grouping.";
+    container status {
+      description
+        "Service status.";
+      container admin-status {
+        description
+          "Administrative service status.";
+        leaf status {
+          type identityref {
+            base administrative-status;
+          }
+          description
+            "Administrative service status.";
+        }
+        leaf last-change {
+          type yang:date-and-time;
+          description
+            "Indicates the actual date and time of the service status
+             change.";
+        }
+      }
+      container oper-status {
+        description
+          "Operational service status.";
+        uses oper-status-timestamp;
+      }
+    }
+  }
+
+  grouping underlay-transport {
+    description
+      "This grouping defines the type of underlay transport for the
+       VPN service or how that underlay is set. It can include an
+       identifier to an abstract transport instance to which the VPN
+       is grafted or indicate a technical implementation that is
+       expressed as an ordered list of protocols.";
+    choice type {
+      description
+        "A choice based on the type of underlay transport
+         constraints.";
+      case abstract {
+        description
+          "Indicates that the transport constraint is an abstract
+           concept.";
+        leaf transport-instance-id {
+          type string;
+          description
+            "An optional identifier of the abstract transport instance.";
+        }
+        leaf instance-type {
+          type identityref {
+            base transport-instance-type;
+          }
+          description
+            "Indicates a transport instance type. For example, it can
+             be a VPN+, an IETF network slice, a virtual network, etc.";
+        }
+      }
+      case protocol {
+        description
+          "Indicates a list of protocols.";
+        leaf-list protocol {
+          type identityref {
+            base protocol-type;
+          }
+          ordered-by user;
+          description
+            "A client ordered list of transport protocols.";
+        }
+      }
+    }
+  }
+
+  grouping vpn-route-targets {
+    description
+      "A grouping that specifies Route Target (RT) import-export rules
+       used in a BGP-enabled VPN.";
+    reference
+      "RFC 4364: BGP/MPLS IP Virtual Private Networks (VPNs)
+       RFC 4664: Framework for Layer 2 Virtual Private Networks
+                 (L2VPNs)";
+    list vpn-target {
+      key "id";
+      description
+        "Route targets. AND/OR operations may be defined
+         based on the RTs assigment.";
+      leaf id {
+        type uint8;
+        description
+          "Identifies each VPN Target.";
+      }
+      list route-targets {
+        key "route-target";
+        description
+          "List of RTs.";
+        leaf route-target {
+          type rt-types:route-target;
+          description
+            "Conveys an RT value.";
+        }
+      }
+      leaf route-target-type {
+        type rt-types:route-target-type;
+        mandatory true;
+        description
+          "Import/export type of the RT.";
+      }
+    }
+    container vpn-policies {
+      description
+        "VPN service policies. It contains references to the
+         import and export policies to be associated with the
+         VPN service.";
+      leaf import-policy {
+        type string;
+        description
+          "Identifies the 'import' policy.";
+      }
+      leaf export-policy {
+        type string;
+        description
+          "Identifies the 'export' policy.";
+      }
+    }
+  }
+
+  grouping route-distinguisher {
+    description
+      "Grouping for route distinguisher (RD).";
+    choice rd-choice {
+      description
+        "Route distinguisher choice between several options
+         on providing the route distinguisher value.";
+      case directly-assigned {
+        description
+          "Explicitly assign an RD value.";
+        leaf rd {
+          type rt-types:route-distinguisher;
+          description
+            "Indicates an RD value that is explicitly
+             assigned.";
+        }
+      }
+      case directly-assigned-suffix {
+        description
+          "The value of the Assigned Number subfield of the RD.
+           The Administrator subfield of the RD will be
+           based on other configuration information such as
+           router-id or ASN.";
+        leaf rd-suffix {
+          type uint16;
+          description
+            "Indicates the value of the Assigned Number
+             subfield that is explicitly assigned.";
+        }
+      }
+      case auto-assigned {
+        description
+          "The RD is auto-assigned.";
+        container rd-auto {
+          description
+            "The RD is auto-assigned.";
+          choice auto-mode {
+            description
+              "Indicates the auto-assignment mode. RD can be
+               automatically assigned with or without
+               indicating a pool from which the RD should be
+               taken.
+
+               For both cases, the server will auto-assign an RD
+               value 'auto-assigned-rd' and use that value
+               operationally.";
+            case from-pool {
+              leaf rd-pool-name {
+                type string;
+                description
+                  "The auto-assignment will be made from the pool
+                   identified by the rd-pool-name.";
+              }
+            }
+            case full-auto {
+              leaf auto {
+                type empty;
+                description
+                  "Indicates an RD is fully auto-assigned.";
+              }
+            }
+          }
+          leaf auto-assigned-rd {
+            type rt-types:route-distinguisher;
+            config false;
+            description
+              "The value of the auto-assigned RD.";
+          }
+        }
+      }
+      case auto-assigned-suffix {
+        description
+          "The value of the Assigned Number subfield will
+           be auto-assigned. The Administrator subfield
+           will be based on other configuration information such as
+           router-id or ASN.";
+        container rd-auto-suffix {
+          description
+            "The Assigned Number subfield is auto-assigned.";
+          choice auto-mode {
+            description
+              "Indicates the auto-assignment mode of the Assigned Number
+               subfield. This number can be automatically assigned
+               with or without indicating a pool from which the value
+               should be taken.
+
+               For both cases, the server will auto-assign
+               'auto-assigned-rd-suffix' and use that value to build
+               the RD that will be used operationally.";
+            case from-pool {
+              leaf rd-pool-name {
+                type string;
+                description
+                  "The assignment will be made from the pool identified
+                   by the rd-pool-name.";
+              }
+            }
+            case full-auto {
+              leaf auto {
+                type empty;
+                description
+                  "Indicates that the Assigned Number is fully auto
+                   assigned.";
+              }
+            }
+          }
+          leaf auto-assigned-rd-suffix {
+            type uint16;
+            config false;
+            description
+              "Includes the value of the Assigned Number subfield that
+               is auto-assigned .";
+          }
+        }
+      }
+      case no-rd {
+        description
+          "Use the empty type to indicate RD has no value and is not to
+           be auto-assigned.";
+        leaf no-rd {
+          type empty;
+          description
+            "No RD is assigned.";
+        }
+      }
+    }
+  }
+
+  grouping vpn-components-group {
+    description
+      "Grouping definition to assign group-ids to associate VPN nodes,
+       sites, or network accesses.";
+    container groups {
+      description
+        "Lists the groups to which a VPN node, a site, or a network
+         access belongs to.";
+      list group {
+        key "group-id";
+        description
+          "List of group-ids.";
+        leaf group-id {
+          type string;
+          description
+            "Is the group-id to which a VPN node, a site, or a network
+             access belongs to.";
+        }
+      }
+    }
+  }
+
+  grouping placement-constraints {
+    description
+      "Constraints for placing a network access.";
+    list constraint {
+      key "constraint-type";
+      description
+        "List of constraints.";
+      leaf constraint-type {
+        type identityref {
+          base placement-diversity;
+        }
+        description
+          "Diversity constraint type.";
+      }
+      container target {
+        description
+          "The constraint will apply against this list of groups.";
+        choice target-flavor {
+          description
+            "Choice for the group definition.";
+          case id {
+            list group {
+              key "group-id";
+              description
+                "List of groups.";
+              leaf group-id {
+                type string;
+                description
+                  "The constraint will apply against this particular
+                   group-id.";
+              }
+            }
+          }
+          case all-accesses {
+            leaf all-other-accesses {
+              type empty;
+              description
+                "The constraint will apply against all other network
+                 accesses of a site.";
+            }
+          }
+          case all-groups {
+            leaf all-other-groups {
+              type empty;
+              description
+                "The constraint will apply against all other groups that
+                 the customer is managing.";
+            }
+          }
+        }
+      }
+    }
+  }
+
+  grouping ports {
+    description
+      "Choice of specifying a source or destination port numbers.";
+    choice source-port {
+      description
+        "Choice of specifying the source port or referring to a group
+         of source port numbers.";
+      container source-port-range-or-operator {
+        description
+          "Source port definition.";
+        uses packet-fields:port-range-or-operator;
+      }
+    }
+    choice destination-port {
+      description
+        "Choice of specifying a destination port or referring to a group
+         of destination port numbers.";
+      container destination-port-range-or-operator {
+        description
+          "Destination port definition.";
+        uses packet-fields:port-range-or-operator;
+      }
+    }
+  }
+
+  grouping qos-classification-policy {
+    description
+      "Configuration of the traffic classification policy.";
+    list rule {
+      key "id";
+      ordered-by user;
+      description
+        "List of marking rules.";
+      leaf id {
+        type string;
+        description
+          "An identifier of the QoS classification policy rule.";
+      }
+      choice match-type {
+        default "match-flow";
+        description
+          "Choice for classification.";
+        case match-flow {
+          choice l3 {
+            description
+              "Either IPv4 or IPv6.";
+            container ipv4 {
+              description
+                "Rule set that matches IPv4 header.";
+              uses packet-fields:acl-ip-header-fields;
+              uses packet-fields:acl-ipv4-header-fields;
+            }
+            container ipv6 {
+              description
+                "Rule set that matches IPv6 header.";
+              uses packet-fields:acl-ip-header-fields;
+              uses packet-fields:acl-ipv6-header-fields;
+            }
+          }
+          choice l4 {
+            description
+              "Includes Layer 4 specific information.
+               This version focuses on TCP and UDP.";
+            container tcp {
+              description
+                "Rule set that matches TCP header.";
+              uses packet-fields:acl-tcp-header-fields;
+              uses ports;
+            }
+            container udp {
+              description
+                "Rule set that matches UDP header.";
+              uses packet-fields:acl-udp-header-fields;
+              uses ports;
+            }
+          }
+        }
+        case match-application {
+          leaf match-application {
+            type identityref {
+              base customer-application;
+            }
+            description
+              "Defines the application to match.";
+          }
+        }
+      }
+      leaf target-class-id {
+        if-feature "qos";
+        type string;
+        description
+          "Identification of the class of service. This identifier is
+           internal to the administration.";
+      }
+    }
+  }
+}
diff --git a/src/nbi/tests/data/agg-net-descriptor.json b/src/nbi/tests/data/agg-net-descriptor.json
new file mode 100644
index 0000000000000000000000000000000000000000..bde4db62844084c0674312a60d7c1cbf8357de52
--- /dev/null
+++ b/src/nbi/tests/data/agg-net-descriptor.json
@@ -0,0 +1,628 @@
+{
+    "contexts": [
+        {
+            "context_id": {
+                "context_uuid": {
+                    "uuid": "admin"
+                }
+            }
+        }
+    ],
+    "topologies": [
+        {
+            "topology_id": {
+                "context_id": {
+                    "context_uuid": {
+                        "uuid": "admin"
+                    }
+                },
+                "topology_uuid": {
+                    "uuid": "admin"
+                }
+            }
+        }
+    ],
+    "devices": [
+        {
+            "device_id": {
+                "device_uuid": {
+                    "uuid": "ip-net-controller"
+                }
+            },
+            "name": "ip-net-controller",
+            "device_type": "ip-sdn-controller",
+            "device_operational_status": 1,
+            "device_drivers": [
+                13
+            ],
+            "device_config": {
+                "config_rules": [
+                    {
+                        "action": 1,
+                        "custom": {
+                            "resource_key": "_connect/address",
+                            "resource_value": "10.10.10.10"
+                        }
+                    },
+                    {
+                        "action": 1,
+                        "custom": {
+                            "resource_key": "_connect/port",
+                            "resource_value": "80"
+                        }
+                    },
+                    {
+                        "action": 1,
+                        "custom": {
+                            "resource_key": "_connect/settings",
+                            "resource_value": {
+                                "endpoints": [],
+                                "scheme": "http",
+                                "username": "admin",
+                                "password": "admin",
+                                "base_url": "/restconf/v2/data",
+                                "timeout": 120,
+                                "verify": false
+                            }
+                        }
+                    }
+                ]
+            },
+            "device_endpoints": []
+        },
+        {
+            "device_id": {
+                "device_uuid": {
+                    "uuid": "172.16.182.25"
+                }
+            },
+            "name": "172.16.182.25",
+            "device_type": "emu-packet-router",
+            "controller_id": {
+                "device_uuid": {
+                    "uuid": "ip-net-controller"
+                }
+            },
+            "device_operational_status": 1,
+            "device_drivers": [
+                0
+            ],
+            "device_config": {
+                "config_rules": [
+                    {
+                        "action": 1,
+                        "custom": {
+                            "resource_key": "_connect/address",
+                            "resource_value": "127.0.0.1"
+                        }
+                    },
+                    {
+                        "action": 1,
+                        "custom": {
+                            "resource_key": "_connect/port",
+                            "resource_value": "0"
+                        }
+                    },
+                    {
+                        "action": 1,
+                        "custom": {
+                            "resource_key": "_connect/settings",
+                            "resource_value": {
+                                "endpoints": [
+                                    {
+                                        "uuid": "mgmt",
+                                        "name": "mgmt",
+                                        "type": "mgmt"
+                                    },
+                                    {
+                                        "uuid": "200",
+                                        "name": "200",
+                                        "type": "optical",
+                                        "ce-ip": "128.32.33.2",
+                                        "address_ip": "128.32.33.254",
+                                        "address_prefix": "24",
+                                        "site_location": "access",
+                                        "mtu": "1500",
+                                        "ipv4_lan_prefixes": [
+                                            {
+                                                "lan": "128.32.10.0/24",
+                                                "lan_tag": "10"
+                                            },
+                                            {
+                                                "lan": "128.32.20.0/24",
+                                                "lan_tag": "20"
+                                            }
+                                        ]
+                                    },
+                                    {
+                                        "uuid": "500",
+                                        "name": "500",
+                                        "type": "optical"
+                                    },
+                                    {
+                                        "uuid": "501",
+                                        "name": "501",
+                                        "type": "optical"
+                                    }
+                                ]
+                            }
+                        }
+                    }
+                ]
+            }
+        },
+        {
+            "device_id": {
+                "device_uuid": {
+                    "uuid": "172.16.185.31"
+                }
+            },
+            "name": "172.16.185.31",
+            "device_type": "emu-packet-router",
+            "controller_id": {
+                "device_uuid": {
+                    "uuid": "ip-net-controller"
+                }
+            },
+            "device_operational_status": 1,
+            "device_drivers": [
+                0
+            ],
+            "device_config": {
+                "config_rules": [
+                    {
+                        "action": 1,
+                        "custom": {
+                            "resource_key": "_connect/address",
+                            "resource_value": "127.0.0.1"
+                        }
+                    },
+                    {
+                        "action": 1,
+                        "custom": {
+                            "resource_key": "_connect/port",
+                            "resource_value": "0"
+                        }
+                    },
+                    {
+                        "action": 1,
+                        "custom": {
+                            "resource_key": "_connect/settings",
+                            "resource_value": {
+                                "endpoints": [
+                                    {
+                                        "uuid": "mgmt",
+                                        "name": "mgmt",
+                                        "type": "mgmt"
+                                    },
+                                    {
+                                        "uuid": "500",
+                                        "name": "500",
+                                        "type": "optical"
+                                    },
+                                    {
+                                        "uuid": "501",
+                                        "name": "501",
+                                        "type": "optical"
+                                    }
+                                ]
+                            }
+                        }
+                    }
+                ]
+            }
+        },
+        {
+            "device_id": {
+                "device_uuid": {
+                    "uuid": "172.16.185.33"
+                }
+            },
+            "name": "172.16.185.33",
+            "device_type": "emu-packet-router",
+            "controller_id": {
+                "device_uuid": {
+                    "uuid": "ip-net-controller"
+                }
+            },
+            "device_operational_status": 1,
+            "device_drivers": [
+                0
+            ],
+            "device_config": {
+                "config_rules": [
+                    {
+                        "action": 1,
+                        "custom": {
+                            "resource_key": "_connect/address",
+                            "resource_value": "127.0.0.1"
+                        }
+                    },
+                    {
+                        "action": 1,
+                        "custom": {
+                            "resource_key": "_connect/port",
+                            "resource_value": "0"
+                        }
+                    },
+                    {
+                        "action": 1,
+                        "custom": {
+                            "resource_key": "_connect/settings",
+                            "resource_value": {
+                                "endpoints": [
+                                    {
+                                        "uuid": "mgmt",
+                                        "name": "mgmt",
+                                        "type": "mgmt"
+                                    },
+                                    {
+                                        "uuid": "500",
+                                        "name": "500",
+                                        "type": "optical"
+                                    },
+                                    {
+                                        "uuid": "501",
+                                        "name": "501",
+                                        "type": "optical"
+                                    }
+                                ]
+                            }
+                        }
+                    }
+                ]
+            }
+        },
+        {
+            "device_id": {
+                "device_uuid": {
+                    "uuid": "172.16.185.32"
+                }
+            },
+            "name": "172.16.185.32",
+            "device_type": "emu-packet-router",
+            "controller_id": {
+                "device_uuid": {
+                    "uuid": "ip-net-controller"
+                }
+            },
+            "device_operational_status": 1,
+            "device_drivers": [
+                0
+            ],
+            "device_config": {
+                "config_rules": [
+                    {
+                        "action": 1,
+                        "custom": {
+                            "resource_key": "_connect/address",
+                            "resource_value": "127.0.0.1"
+                        }
+                    },
+                    {
+                        "action": 1,
+                        "custom": {
+                            "resource_key": "_connect/port",
+                            "resource_value": "0"
+                        }
+                    },
+                    {
+                        "action": 1,
+                        "custom": {
+                            "resource_key": "_connect/settings",
+                            "resource_value": {
+                                "endpoints": [
+                                    {
+                                        "uuid": "mgmt",
+                                        "name": "mgmt",
+                                        "type": "mgmt"
+                                    },
+                                    {
+                                        "uuid": "200",
+                                        "name": "200",
+                                        "type": "optical",
+                                        "ce-ip": "172.10.33.2",
+                                        "address_ip": "172.10.33.254",
+                                        "address_prefix": "24",
+                                        "site_location": "cloud",
+                                        "mtu": "1500",
+                                        "ipv4_lan_prefixes": [
+                                            {
+                                                "lan": "172.1.101.0/24",
+                                                "lan_tag": "101"
+                                            }
+                                        ]
+                                    },
+                                    {
+                                        "uuid": "500",
+                                        "name": "500",
+                                        "type": "optical"
+                                    },
+                                    {
+                                        "uuid": "501",
+                                        "name": "501",
+                                        "type": "optical"
+                                    }
+                                ]
+                            }
+                        }
+                    }
+                ]
+            }
+        }
+    ],
+    "links": [
+        {
+            "link_id": {
+                "link_uuid": {
+                    "uuid": "172.16.182.25-500"
+                }
+            },
+            "name": "172.16.182.25-500",
+            "attributes": {
+                "total_capacity_gbps": 10,
+                "used_capacity_gbps": 0
+            },
+            "link_endpoint_ids": [
+                {
+                    "device_id": {
+                        "device_uuid": {
+                            "uuid": "172.16.182.25"
+                        }
+                    },
+                    "endpoint_uuid": {
+                        "uuid": "500"
+                    }
+                },
+                {
+                    "device_id": {
+                        "device_uuid": {
+                            "uuid": "172.16.185.33"
+                        }
+                    },
+                    "endpoint_uuid": {
+                        "uuid": "500"
+                    }
+                }
+            ]
+        },
+        {
+            "link_id": {
+                "link_uuid": {
+                    "uuid": "172.16.185.33-500"
+                }
+            },
+            "name": "172.16.185.33-500",
+            "attributes": {
+                "total_capacity_gbps": 10,
+                "used_capacity_gbps": 0
+            },
+            "link_endpoint_ids": [
+                {
+                    "device_id": {
+                        "device_uuid": {
+                            "uuid": "172.16.185.33"
+                        }
+                    },
+                    "endpoint_uuid": {
+                        "uuid": "500"
+                    }
+                },
+                {
+                    "device_id": {
+                        "device_uuid": {
+                            "uuid": "172.16.182.25"
+                        }
+                    },
+                    "endpoint_uuid": {
+                        "uuid": "500"
+                    }
+                }
+            ]
+        },
+        {
+            "link_id": {
+                "link_uuid": {
+                    "uuid": "172.16.182.25-501"
+                }
+            },
+            "name": "172.16.182.25-501",
+            "attributes": {
+                "total_capacity_gbps": 10,
+                "used_capacity_gbps": 0
+            },
+            "link_endpoint_ids": [
+                {
+                    "device_id": {
+                        "device_uuid": {
+                            "uuid": "172.16.182.25"
+                        }
+                    },
+                    "endpoint_uuid": {
+                        "uuid": "501"
+                    }
+                },
+                {
+                    "device_id": {
+                        "device_uuid": {
+                            "uuid": "172.16.185.31"
+                        }
+                    },
+                    "endpoint_uuid": {
+                        "uuid": "501"
+                    }
+                }
+            ]
+        },
+        {
+            "link_id": {
+                "link_uuid": {
+                    "uuid": "172.16.185.31-501"
+                }
+            },
+            "name": "172.16.185.31-501",
+            "attributes": {
+                "total_capacity_gbps": 10,
+                "used_capacity_gbps": 0
+            },
+            "link_endpoint_ids": [
+                {
+                    "device_id": {
+                        "device_uuid": {
+                            "uuid": "172.16.185.31"
+                        }
+                    },
+                    "endpoint_uuid": {
+                        "uuid": "501"
+                    }
+                },
+                {
+                    "device_id": {
+                        "device_uuid": {
+                            "uuid": "172.16.182.25"
+                        }
+                    },
+                    "endpoint_uuid": {
+                        "uuid": "501"
+                    }
+                }
+            ]
+        },
+        {
+            "link_id": {
+                "link_uuid": {
+                    "uuid": "172.16.185.31-500"
+                }
+            },
+            "name": "172.16.185.31-500",
+            "attributes": {
+                "total_capacity_gbps": 10,
+                "used_capacity_gbps": 0
+            },
+            "link_endpoint_ids": [
+                {
+                    "device_id": {
+                        "device_uuid": {
+                            "uuid": "172.16.185.31"
+                        }
+                    },
+                    "endpoint_uuid": {
+                        "uuid": "500"
+                    }
+                },
+                {
+                    "device_id": {
+                        "device_uuid": {
+                            "uuid": "172.16.185.32"
+                        }
+                    },
+                    "endpoint_uuid": {
+                        "uuid": "500"
+                    }
+                }
+            ]
+        },
+        {
+            "link_id": {
+                "link_uuid": {
+                    "uuid": "172.16.185.32-500"
+                }
+            },
+            "name": "172.16.185.32-500",
+            "attributes": {
+                "total_capacity_gbps": 10,
+                "used_capacity_gbps": 0
+            },
+            "link_endpoint_ids": [
+                {
+                    "device_id": {
+                        "device_uuid": {
+                            "uuid": "172.16.185.32"
+                        }
+                    },
+                    "endpoint_uuid": {
+                        "uuid": "500"
+                    }
+                },
+                {
+                    "device_id": {
+                        "device_uuid": {
+                            "uuid": "172.16.185.31"
+                        }
+                    },
+                    "endpoint_uuid": {
+                        "uuid": "500"
+                    }
+                }
+            ]
+        },
+        {
+            "link_id": {
+                "link_uuid": {
+                    "uuid": "172.16.185.33-501"
+                }
+            },
+            "name": "172.16.185.33-501",
+            "attributes": {
+                "total_capacity_gbps": 10,
+                "used_capacity_gbps": 0
+            },
+            "link_endpoint_ids": [
+                {
+                    "device_id": {
+                        "device_uuid": {
+                            "uuid": "172.16.185.33"
+                        }
+                    },
+                    "endpoint_uuid": {
+                        "uuid": "501"
+                    }
+                },
+                {
+                    "device_id": {
+                        "device_uuid": {
+                            "uuid": "172.16.185.32"
+                        }
+                    },
+                    "endpoint_uuid": {
+                        "uuid": "501"
+                    }
+                }
+            ]
+        },
+        {
+            "link_id": {
+                "link_uuid": {
+                    "uuid": "172.16.185.32-501"
+                }
+            },
+            "name": "172.16.185.32-501",
+            "attributes": {
+                "total_capacity_gbps": 10,
+                "used_capacity_gbps": 0
+            },
+            "link_endpoint_ids": [
+                {
+                    "device_id": {
+                        "device_uuid": {
+                            "uuid": "172.16.185.32"
+                        }
+                    },
+                    "endpoint_uuid": {
+                        "uuid": "501"
+                    }
+                },
+                {
+                    "device_id": {
+                        "device_uuid": {
+                            "uuid": "172.16.185.33"
+                        }
+                    },
+                    "endpoint_uuid": {
+                        "uuid": "501"
+                    }
+                }
+            ]
+        }
+    ]
+}
\ No newline at end of file
diff --git a/src/nbi/tests/data/camara-e2e-topology.json b/src/nbi/tests/data/camara-e2e-topology.json
new file mode 100644
index 0000000000000000000000000000000000000000..0b314e104ef4ae31cfdb7be11f9e3912287cf5ae
--- /dev/null
+++ b/src/nbi/tests/data/camara-e2e-topology.json
@@ -0,0 +1,1642 @@
+{
+  "contexts": [
+    {
+      "context_id": {
+        "context_uuid": {
+          "uuid": "admin"
+        }
+      }
+    }
+  ],
+  "topologies": [
+    {
+      "topology_id": {
+        "context_id": {
+          "context_uuid": {
+            "uuid": "admin"
+          }
+        },
+        "topology_uuid": {
+          "uuid": "admin"
+        }
+      }
+    }
+  ],
+  "devices": [
+    {
+      "device_id": {
+        "device_uuid": {
+          "uuid": "agg-net-controller"
+        }
+      },
+      "name": "agg-net-controller",
+      "device_type": "ietf-slice",
+      "device_operational_status": 1,
+      "device_drivers": [
+        14
+      ],
+      "device_config": {
+        "config_rules": [
+          {
+            "action": 1,
+            "custom": {
+              "resource_key": "_connect/address",
+              "resource_value": "10.0.58.9"
+            }
+          },
+          {
+            "action": 1,
+            "custom": {
+              "resource_key": "_connect/port",
+              "resource_value": "80"
+            }
+          },
+          {
+            "action": 1,
+            "custom": {
+              "resource_key": "_connect/settings",
+              "resource_value": {
+                "endpoints": [
+                  {
+                    "uuid": "mgmt",
+                    "name": "mgmt",
+                    "type": "mgmt"
+                  }
+                ],
+                "scheme": "http",
+                "username": "admin",
+                "password": "admin",
+                "base_url": "/restconf/v2/data",
+                "timeout": 120,
+                "verify": false
+              }
+            }
+          }
+        ]
+      },
+      "device_endpoints": []
+    },
+    {
+      "device_id": {
+        "device_uuid": {
+          "uuid": "nce-controller"
+        }
+      },
+      "name": "nce-controller",
+      "device_type": "nce",
+      "device_operational_status": 1,
+      "device_drivers": [
+        15
+      ],
+      "device_config": {
+        "config_rules": [
+          {
+            "action": 1,
+            "custom": {
+              "resource_key": "_connect/address",
+              "resource_value": "10.10.10.10"
+            }
+          },
+          {
+            "action": 1,
+            "custom": {
+              "resource_key": "_connect/port",
+              "resource_value": "80"
+            }
+          },
+          {
+            "action": 1,
+            "custom": {
+              "resource_key": "_connect/settings",
+              "resource_value": {
+                "endpoints": [
+                  {
+                    "uuid": "mgmt",
+                    "name": "mgmt",
+                    "type": "mgmt"
+                  }
+                ],
+                "scheme": "http",
+                "username": "admin",
+                "password": "admin",
+                "base_url": "/restconf/v2/data",
+                "timeout": 120,
+                "verify": false
+              }
+            }
+          }
+        ]
+      },
+      "device_endpoints": []
+    },
+    {
+      "device_id": {
+        "device_uuid": {
+          "uuid": "172.16.182.25"
+        }
+      },
+      "name": "172.16.182.25",
+      "device_type": "emu-packet-router",
+      "controller_id": {
+        "device_uuid": {
+          "uuid": "agg-net-controller"
+        }
+      },
+      "device_operational_status": 1,
+      "device_drivers": [
+        0,
+        14
+      ],
+      "device_config": {
+        "config_rules": [
+          {
+            "action": 1,
+            "custom": {
+              "resource_key": "_connect/address",
+              "resource_value": "127.0.0.1"
+            }
+          },
+          {
+            "action": 1,
+            "custom": {
+              "resource_key": "_connect/port",
+              "resource_value": "0"
+            }
+          },
+          {
+            "action": 1,
+            "custom": {
+              "resource_key": "_connect/settings",
+              "resource_value": {
+                "endpoints": [
+                  {
+                    "uuid": "mgmt",
+                    "name": "mgmt",
+                    "type": "mgmt"
+                  },
+                  {
+                    "uuid": "200",
+                    "name": "200",
+                    "type": "optical",
+                    "address_ip": "128.32.33.254",
+                    "address_prefix": "24",
+                    "site_location": "access",
+                    "mtu": "1500"
+                  },
+                  {
+                    "uuid": "500",
+                    "name": "500",
+                    "type": "optical"
+                  },
+                  {
+                    "uuid": "501",
+                    "name": "501",
+                    "type": "optical"
+                  }
+                ]
+              }
+            }
+          }
+        ]
+      }
+    },
+    {
+      "device_id": {
+        "device_uuid": {
+          "uuid": "172.16.185.31"
+        }
+      },
+      "name": "172.16.185.31",
+      "device_type": "emu-packet-router",
+      "controller_id": {
+        "device_uuid": {
+          "uuid": "agg-net-controller"
+        }
+      },
+      "device_operational_status": 1,
+      "device_drivers": [
+        0,
+        14
+      ],
+      "device_config": {
+        "config_rules": [
+          {
+            "action": 1,
+            "custom": {
+              "resource_key": "_connect/address",
+              "resource_value": "127.0.0.1"
+            }
+          },
+          {
+            "action": 1,
+            "custom": {
+              "resource_key": "_connect/port",
+              "resource_value": "0"
+            }
+          },
+          {
+            "action": 1,
+            "custom": {
+              "resource_key": "_connect/settings",
+              "resource_value": {
+                "endpoints": [
+                  {
+                    "uuid": "mgmt",
+                    "name": "mgmt",
+                    "type": "mgmt"
+                  },
+                  {
+                    "uuid": "500",
+                    "name": "500",
+                    "type": "optical"
+                  },
+                  {
+                    "uuid": "501",
+                    "name": "501",
+                    "type": "optical"
+                  }
+                ]
+              }
+            }
+          }
+        ]
+      }
+    },
+    {
+      "device_id": {
+        "device_uuid": {
+          "uuid": "172.16.185.33"
+        }
+      },
+      "name": "172.16.185.33",
+      "device_type": "emu-packet-router",
+      "controller_id": {
+        "device_uuid": {
+          "uuid": "agg-net-controller"
+        }
+      },
+      "device_operational_status": 1,
+      "device_drivers": [
+        0,
+        14
+      ],
+      "device_config": {
+        "config_rules": [
+          {
+            "action": 1,
+            "custom": {
+              "resource_key": "_connect/address",
+              "resource_value": "127.0.0.1"
+            }
+          },
+          {
+            "action": 1,
+            "custom": {
+              "resource_key": "_connect/port",
+              "resource_value": "0"
+            }
+          },
+          {
+            "action": 1,
+            "custom": {
+              "resource_key": "_connect/settings",
+              "resource_value": {
+                "endpoints": [
+                  {
+                    "uuid": "mgmt",
+                    "name": "mgmt",
+                    "type": "mgmt"
+                  },
+                  {
+                    "uuid": "500",
+                    "name": "500",
+                    "type": "optical"
+                  },
+                  {
+                    "uuid": "501",
+                    "name": "501",
+                    "type": "optical"
+                  }
+                ]
+              }
+            }
+          }
+        ]
+      }
+    },
+    {
+      "device_id": {
+        "device_uuid": {
+          "uuid": "172.16.185.32"
+        }
+      },
+      "name": "172.16.185.32",
+      "device_type": "emu-packet-router",
+      "controller_id": {
+        "device_uuid": {
+          "uuid": "agg-net-controller"
+        }
+      },
+      "device_operational_status": 1,
+      "device_drivers": [
+        0,
+        14
+      ],
+      "device_config": {
+        "config_rules": [
+          {
+            "action": 1,
+            "custom": {
+              "resource_key": "_connect/address",
+              "resource_value": "127.0.0.1"
+            }
+          },
+          {
+            "action": 1,
+            "custom": {
+              "resource_key": "_connect/port",
+              "resource_value": "0"
+            }
+          },
+          {
+            "action": 1,
+            "custom": {
+              "resource_key": "_connect/settings",
+              "resource_value": {
+                "endpoints": [
+                  {
+                    "uuid": "mgmt",
+                    "name": "mgmt",
+                    "type": "mgmt"
+                  },
+                  {
+                    "uuid": "200",
+                    "name": "200",
+                    "type": "optical",
+                    "ce-ip": "172.10.33.2",
+                    "address_ip": "172.10.33.254",
+                    "address_prefix": "24",
+                    "site_location": "cloud",
+                    "mtu": "1500"
+                  },
+                  {
+                    "uuid": "500",
+                    "name": "500",
+                    "type": "optical"
+                  },
+                  {
+                    "uuid": "501",
+                    "name": "501",
+                    "type": "optical"
+                  }
+                ]
+              }
+            }
+          }
+        ]
+      }
+    },
+    {
+      "device_id": {
+        "device_uuid": {
+          "uuid": "172.16.58.10"
+        }
+      },
+      "name": "172.16.58.10",
+      "device_type": "emu-packet-router",
+      "controller_id": {
+        "device_uuid": {
+          "uuid": "nce-controller"
+        }
+      },
+      "device_operational_status": 1,
+      "device_drivers": [
+        15
+      ],
+      "device_config": {
+        "config_rules": [
+          {
+            "action": 1,
+            "custom": {
+              "resource_key": "_connect/address",
+              "resource_value": "127.0.0.1"
+            }
+          },
+          {
+            "action": 1,
+            "custom": {
+              "resource_key": "_connect/port",
+              "resource_value": "0"
+            }
+          },
+          {
+            "action": 1,
+            "custom": {
+              "resource_key": "_connect/settings",
+              "resource_value": {
+                "endpoints": [
+                  {
+                    "uuid": "mgmt",
+                    "name": "mgmt",
+                    "type": "mgmt"
+                  },
+                  {
+                    "uuid": "200",
+                    "name": "200",
+                    "type": "optical",
+                    "address_ip": "0.0.0.0",
+                    "address_prefix": "24"
+                  },
+                  {
+                    "uuid": "201",
+                    "name": "201",
+                    "type": "optical",
+                    "address_ip": "0.0.0.0",
+                    "address_prefix": "24"
+                  },
+                  {
+                    "uuid": "500",
+                    "name": "500",
+                    "type": "optical",
+                    "address_ip": "128.32.33.2",
+                    "address_prefix": "24"
+                  }
+                ]
+              }
+            }
+          }
+        ]
+      }
+    },
+    {
+      "device_id": {
+        "device_uuid": {
+          "uuid": "172.16.61.10"
+        }
+      },
+      "name": "172.16.61.10",
+      "device_type": "emu-packet-router",
+      "controller_id": {
+        "device_uuid": {
+          "uuid": "nce-controller"
+        }
+      },
+      "device_operational_status": 1,
+      "device_drivers": [
+        15
+      ],
+      "device_config": {
+        "config_rules": [
+          {
+            "action": 1,
+            "custom": {
+              "resource_key": "_connect/address",
+              "resource_value": "127.0.0.1"
+            }
+          },
+          {
+            "action": 1,
+            "custom": {
+              "resource_key": "_connect/port",
+              "resource_value": "0"
+            }
+          },
+          {
+            "action": 1,
+            "custom": {
+              "resource_key": "_connect/settings",
+              "resource_value": {
+                "endpoints": [
+                  {
+                    "uuid": "mgmt",
+                    "name": "mgmt",
+                    "type": "mgmt"
+                  },
+                  {
+                    "uuid": "200",
+                    "name": "200",
+                    "type": "optical",
+                    "address_ip": "0.0.0.0",
+                    "address_prefix": "24"
+                  },
+                  {
+                    "uuid": "500",
+                    "name": "500",
+                    "type": "optical",
+                    "address_ip": "128.32.33.2",
+                    "address_prefix": "24"
+                  }
+                ]
+              }
+            }
+          }
+        ]
+      }
+    },
+    {
+      "device_id": {
+        "device_uuid": {
+          "uuid": "172.16.61.11"
+        }
+      },
+      "name": "172.16.61.11",
+      "device_type": "emu-packet-router",
+      "controller_id": {
+        "device_uuid": {
+          "uuid": "nce-controller"
+        }
+      },
+      "device_operational_status": 1,
+      "device_drivers": [
+        15
+      ],
+      "device_config": {
+        "config_rules": [
+          {
+            "action": 1,
+            "custom": {
+              "resource_key": "_connect/address",
+              "resource_value": "127.0.0.1"
+            }
+          },
+          {
+            "action": 1,
+            "custom": {
+              "resource_key": "_connect/port",
+              "resource_value": "0"
+            }
+          },
+          {
+            "action": 1,
+            "custom": {
+              "resource_key": "_connect/settings",
+              "resource_value": {
+                "endpoints": [
+                  {
+                    "uuid": "mgmt",
+                    "name": "mgmt",
+                    "type": "mgmt"
+                  },
+                  {
+                    "uuid": "200",
+                    "name": "200",
+                    "type": "optical",
+                    "address_ip": "0.0.0.0",
+                    "address_prefix": "24"
+                  },
+                  {
+                    "uuid": "500",
+                    "name": "500",
+                    "type": "optical",
+                    "address_ip": "128.32.33.2",
+                    "address_prefix": "24"
+                  }
+                ]
+              }
+            }
+          }
+        ]
+      }
+    },
+    {
+      "device_id": {
+        "device_uuid": {
+          "uuid": "172.16.104.221"
+        }
+      },
+      "device_type": "emu-datacenter",
+      "device_drivers": [
+        0
+      ],
+      "device_endpoints": [],
+      "device_operational_status": 1,
+      "device_config": {
+        "config_rules": [
+          {
+            "action": 1,
+            "custom": {
+              "resource_key": "_connect/address",
+              "resource_value": "127.0.0.1"
+            }
+          },
+          {
+            "action": 1,
+            "custom": {
+              "resource_key": "_connect/port",
+              "resource_value": "0"
+            }
+          },
+          {
+            "action": 1,
+            "custom": {
+              "resource_key": "_connect/settings",
+              "resource_value": {
+                "endpoints": [
+                  {
+                    "sample_types": [],
+                    "type": "copper",
+                    "uuid": "eth0"
+                  }
+                ]
+              }
+            }
+          }
+        ]
+      }
+    },
+    {
+      "device_id": {
+        "device_uuid": {
+          "uuid": "172.16.104.222"
+        }
+      },
+      "device_type": "emu-datacenter",
+      "device_drivers": [
+        0
+      ],
+      "device_endpoints": [],
+      "device_operational_status": 1,
+      "device_config": {
+        "config_rules": [
+          {
+            "action": 1,
+            "custom": {
+              "resource_key": "_connect/address",
+              "resource_value": "127.0.0.1"
+            }
+          },
+          {
+            "action": 1,
+            "custom": {
+              "resource_key": "_connect/port",
+              "resource_value": "0"
+            }
+          },
+          {
+            "action": 1,
+            "custom": {
+              "resource_key": "_connect/settings",
+              "resource_value": {
+                "endpoints": [
+                  {
+                    "sample_types": [],
+                    "type": "copper",
+                    "uuid": "eth0"
+                  }
+                ]
+              }
+            }
+          }
+        ]
+      }
+    },
+    {
+      "device_id": {
+        "device_uuid": {
+          "uuid": "172.16.204.220"
+        }
+      },
+      "device_type": "emu-datacenter",
+      "device_drivers": [
+        0
+      ],
+      "device_endpoints": [],
+      "device_operational_status": 1,
+      "device_config": {
+        "config_rules": [
+          {
+            "action": 1,
+            "custom": {
+              "resource_key": "_connect/address",
+              "resource_value": "127.0.0.1"
+            }
+          },
+          {
+            "action": 1,
+            "custom": {
+              "resource_key": "_connect/port",
+              "resource_value": "0"
+            }
+          },
+          {
+            "action": 1,
+            "custom": {
+              "resource_key": "_connect/settings",
+              "resource_value": {
+                "endpoints": [
+                  {
+                    "sample_types": [],
+                    "type": "optical",
+                    "uuid": "500"
+                  },
+                  {
+                    "sample_types": [],
+                    "type": "optical",
+                    "uuid": "200"
+                  },
+                  {
+                    "sample_types": [],
+                    "type": "optical",
+                    "uuid": "201"
+                  }
+                ]
+              }
+            }
+          }
+        ]
+      }
+    }
+  ],
+  "links": [
+    {
+      "link_id": {
+        "link_uuid": {
+          "uuid": "nce-controller/mgmt==172.16.61.11/mgmt"
+        }
+      },
+      "name": "nce-controller/mgmt==172.16.61.11/mgmt",
+      "link_endpoint_ids": [
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "nce-controller"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "mgmt"
+          }
+        },
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.61.11"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "mgmt"
+          }
+        }
+      ]
+    },
+    {
+      "link_id": {
+        "link_uuid": {
+          "uuid": "nce-controller/mgmt==172.16.61.10/mgmt"
+        }
+      },
+      "name": "nce-controller/mgmt==172.16.61.10/mgmt",
+      "link_endpoint_ids": [
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "nce-controller"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "mgmt"
+          }
+        },
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.61.10"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "mgmt"
+          }
+        }
+      ]
+    },
+    {
+      "link_id": {
+        "link_uuid": {
+          "uuid": "nce-controller/mgmt==172.16.58.10/mgmt"
+        }
+      },
+      "name": "nce-controller/mgmt==172.16.58.10/mgmt",
+      "link_endpoint_ids": [
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "nce-controller"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "mgmt"
+          }
+        },
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.58.10"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "mgmt"
+          }
+        }
+      ]
+    },
+    {
+      "link_id": {
+        "link_uuid": {
+          "uuid": "agg-net-controller/mgmt==172.16.185.33/mgmt"
+        }
+      },
+      "name": "agg-net-controller/mgmt==172.16.185.33/mgmt",
+      "link_endpoint_ids": [
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "agg-net-controller"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "mgmt"
+          }
+        },
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.185.33"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "mgmt"
+          }
+        }
+      ]
+    },
+    {
+      "link_id": {
+        "link_uuid": {
+          "uuid": "agg-net-controller/mgmt==172.16.185.31/mgmt"
+        }
+      },
+      "name": "agg-net-controller/mgmt==172.16.185.31/mgmt",
+      "link_endpoint_ids": [
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "agg-net-controller"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "mgmt"
+          }
+        },
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.185.31"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "mgmt"
+          }
+        }
+      ]
+    },
+    {
+      "link_id": {
+        "link_uuid": {
+          "uuid": "agg-net-controller/mgmt==172.16.182.25/mgmt"
+        }
+      },
+      "name": "agg-net-controller/mgmt==172.16.182.25/mgmt",
+      "link_endpoint_ids": [
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "agg-net-controller"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "mgmt"
+          }
+        },
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.182.25"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "mgmt"
+          }
+        }
+      ]
+    },
+    {
+      "link_id": {
+        "link_uuid": {
+          "uuid": "agg-net-controller/mgmt==172.16.182.25/mgmt"
+        }
+      },
+      "name": "agg-net-controller/mgmt==172.16.182.25/mgmt",
+      "link_endpoint_ids": [
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "agg-net-controller"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "mgmt"
+          }
+        },
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.182.25"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "mgmt"
+          }
+        }
+      ]
+    },
+    {
+      "link_id": {
+        "link_uuid": {
+          "uuid": "172.16.182.25-500"
+        }
+      },
+      "name": "172.16.182.25-500",
+      "attributes": {
+        "total_capacity_gbps": 10,
+        "used_capacity_gbps": 0
+      },
+      "link_endpoint_ids": [
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.182.25"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "500"
+          }
+        },
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.185.33"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "500"
+          }
+        }
+      ]
+    },
+    {
+      "link_id": {
+        "link_uuid": {
+          "uuid": "172.16.185.33-500"
+        }
+      },
+      "name": "172.16.185.33-500",
+      "attributes": {
+        "total_capacity_gbps": 10,
+        "used_capacity_gbps": 0
+      },
+      "link_endpoint_ids": [
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.185.33"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "500"
+          }
+        },
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.182.25"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "500"
+          }
+        }
+      ]
+    },
+    {
+      "link_id": {
+        "link_uuid": {
+          "uuid": "172.16.182.25-501"
+        }
+      },
+      "name": "172.16.182.25-501",
+      "attributes": {
+        "total_capacity_gbps": 10,
+        "used_capacity_gbps": 0
+      },
+      "link_endpoint_ids": [
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.182.25"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "501"
+          }
+        },
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.185.31"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "501"
+          }
+        }
+      ]
+    },
+    {
+      "link_id": {
+        "link_uuid": {
+          "uuid": "172.16.185.31-501"
+        }
+      },
+      "name": "172.16.185.31-501",
+      "attributes": {
+        "total_capacity_gbps": 10,
+        "used_capacity_gbps": 0
+      },
+      "link_endpoint_ids": [
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.185.31"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "501"
+          }
+        },
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.182.25"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "501"
+          }
+        }
+      ]
+    },
+    {
+      "link_id": {
+        "link_uuid": {
+          "uuid": "172.16.185.31-500"
+        }
+      },
+      "name": "172.16.185.31-500",
+      "attributes": {
+        "total_capacity_gbps": 10,
+        "used_capacity_gbps": 0
+      },
+      "link_endpoint_ids": [
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.185.31"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "500"
+          }
+        },
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.185.32"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "500"
+          }
+        }
+      ]
+    },
+    {
+      "link_id": {
+        "link_uuid": {
+          "uuid": "172.16.185.32-500"
+        }
+      },
+      "name": "172.16.185.32-500",
+      "attributes": {
+        "total_capacity_gbps": 10,
+        "used_capacity_gbps": 0
+      },
+      "link_endpoint_ids": [
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.185.32"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "500"
+          }
+        },
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.185.31"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "500"
+          }
+        }
+      ]
+    },
+    {
+      "link_id": {
+        "link_uuid": {
+          "uuid": "172.16.185.33-501"
+        }
+      },
+      "name": "172.16.185.33-501",
+      "attributes": {
+        "total_capacity_gbps": 10,
+        "used_capacity_gbps": 0
+      },
+      "link_endpoint_ids": [
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.185.33"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "501"
+          }
+        },
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.185.32"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "501"
+          }
+        }
+      ]
+    },
+    {
+      "link_id": {
+        "link_uuid": {
+          "uuid": "172.16.185.32-501"
+        }
+      },
+      "name": "172.16.185.32-501",
+      "attributes": {
+        "total_capacity_gbps": 10,
+        "used_capacity_gbps": 0
+      },
+      "link_endpoint_ids": [
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.185.32"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "501"
+          }
+        },
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.185.33"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "501"
+          }
+        }
+      ]
+    },
+    {
+      "link_id": {
+        "link_uuid": {
+          "uuid": "172.16.185.32-200"
+        }
+      },
+      "name": "172.16.185.32-200",
+      "attributes": {
+        "total_capacity_gbps": 10,
+        "used_capacity_gbps": 0
+      },
+      "link_endpoint_ids": [
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.185.32"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "200"
+          }
+        },
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.204.220"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "500"
+          }
+        }
+      ]
+    },
+    {
+      "link_id": {
+        "link_uuid": {
+          "uuid": "172.16.204.220-500"
+        }
+      },
+      "name": "172.16.204.220-500",
+      "attributes": {
+        "total_capacity_gbps": 10,
+        "used_capacity_gbps": 0
+      },
+      "link_endpoint_ids": [
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.204.220"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "500"
+          }
+        },
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.185.32"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "200"
+          }
+        }
+      ]
+    },
+    {
+      "link_id": {
+        "link_uuid": {
+          "uuid": "172.16.182.25-200"
+        }
+      },
+      "name": "172.16.182.25-200",
+      "attributes": {
+        "total_capacity_gbps": 10,
+        "used_capacity_gbps": 0
+      },
+      "link_endpoint_ids": [
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.182.25"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "200"
+          }
+        },
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.58.10"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "500"
+          }
+        }
+      ]
+    },
+    {
+      "link_id": {
+        "link_uuid": {
+          "uuid": "172.16.58.10-500"
+        }
+      },
+      "name": "172.16.58.10-500",
+      "attributes": {
+        "total_capacity_gbps": 10,
+        "used_capacity_gbps": 0
+      },
+      "link_endpoint_ids": [
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.58.10"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "500"
+          }
+        },
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.182.25"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "200"
+          }
+        }
+      ]
+    },
+    {
+      "link_id": {
+        "link_uuid": {
+          "uuid": "172.16.58.10-200"
+        }
+      },
+      "name": "172.16.58.10-200",
+      "attributes": {
+        "total_capacity_gbps": 10,
+        "used_capacity_gbps": 0
+      },
+      "link_endpoint_ids": [
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.58.10"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "200"
+          }
+        },
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.61.10"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "500"
+          }
+        }
+      ]
+    },
+    {
+      "link_id": {
+        "link_uuid": {
+          "uuid": "172.16.61.10-500"
+        }
+      },
+      "name": "172.16.61.10-500",
+      "attributes": {
+        "total_capacity_gbps": 10,
+        "used_capacity_gbps": 0
+      },
+      "link_endpoint_ids": [
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.61.10"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "500"
+          }
+        },
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.58.10"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "200"
+          }
+        }
+      ]
+    },
+    {
+      "link_id": {
+        "link_uuid": {
+          "uuid": "172.16.58.10-201"
+        }
+      },
+      "name": "172.16.58.10-201",
+      "attributes": {
+        "total_capacity_gbps": 10,
+        "used_capacity_gbps": 0
+      },
+      "link_endpoint_ids": [
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.58.10"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "201"
+          }
+        },
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.61.11"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "500"
+          }
+        }
+      ]
+    },
+    {
+      "link_id": {
+        "link_uuid": {
+          "uuid": "172.16.61.11-500"
+        }
+      },
+      "name": "172.16.61.11-500",
+      "attributes": {
+        "total_capacity_gbps": 10,
+        "used_capacity_gbps": 0
+      },
+      "link_endpoint_ids": [
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.61.11"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "500"
+          }
+        },
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.58.10"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "201"
+          }
+        }
+      ]
+    },
+    {
+      "link_id": {
+        "link_uuid": {
+          "uuid": "172.16.61.10-200"
+        }
+      },
+      "name": "172.16.61.10-200",
+      "attributes": {
+        "total_capacity_gbps": 10,
+        "used_capacity_gbps": 0
+      },
+      "link_endpoint_ids": [
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.61.10"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "200"
+          }
+        },
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.104.221"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "eth0"
+          }
+        }
+      ]
+    },
+    {
+      "link_id": {
+        "link_uuid": {
+          "uuid": "172.16.104.221-eth0"
+        }
+      },
+      "name": "172.16.104.221-eth0",
+      "attributes": {
+        "total_capacity_gbps": 10,
+        "used_capacity_gbps": 0
+      },
+      "link_endpoint_ids": [
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.104.221"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "eth0"
+          }
+        },
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.61.10"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "200"
+          }
+        }
+      ]
+    },
+    {
+      "link_id": {
+        "link_uuid": {
+          "uuid": "172.16.61.11-200"
+        }
+      },
+      "name": "172.16.61.11-200",
+      "attributes": {
+        "total_capacity_gbps": 10,
+        "used_capacity_gbps": 0
+      },
+      "link_endpoint_ids": [
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.61.11"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "200"
+          }
+        },
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.104.222"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "eth0"
+          }
+        }
+      ]
+    },
+    {
+      "link_id": {
+        "link_uuid": {
+          "uuid": "172.16.104.222-eth0"
+        }
+      },
+      "name": "172.16.104.222-eth0",
+      "attributes": {
+        "total_capacity_gbps": 10,
+        "used_capacity_gbps": 0
+      },
+      "link_endpoint_ids": [
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.104.222"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "eth0"
+          }
+        },
+        {
+          "device_id": {
+            "device_uuid": {
+              "uuid": "172.16.61.11"
+            }
+          },
+          "endpoint_uuid": {
+            "uuid": "200"
+          }
+        }
+      ]
+    }
+  ]
+}
diff --git a/src/nbi/tests/data/ip-net-descriptor.json b/src/nbi/tests/data/ip-net-descriptor.json
new file mode 100644
index 0000000000000000000000000000000000000000..dafeeb5bc22dd457fa7b924a30feac660b38f491
--- /dev/null
+++ b/src/nbi/tests/data/ip-net-descriptor.json
@@ -0,0 +1,535 @@
+{
+    "contexts": [
+        {
+            "context_id": {
+                "context_uuid": {
+                    "uuid": "admin"
+                }
+            }
+        }
+    ],
+    "topologies": [
+        {
+            "topology_id": {
+                "context_id": {
+                    "context_uuid": {
+                        "uuid": "admin"
+                    }
+                },
+                "topology_uuid": {
+                    "uuid": "admin"
+                }
+            }
+        }
+    ],
+    "devices": [
+        {
+            "device_id": {
+                "device_uuid": {
+                    "uuid": "172.16.182.25"
+                }
+            },
+            "name": "172.16.182.25",
+            "device_type": "emu-packet-router",
+            "device_operational_status": 1,
+            "device_drivers": [
+                0
+            ],
+            "device_config": {
+                "config_rules": [
+                    {
+                        "action": 1,
+                        "custom": {
+                            "resource_key": "_connect/address",
+                            "resource_value": "127.0.0.1"
+                        }
+                    },
+                    {
+                        "action": 1,
+                        "custom": {
+                            "resource_key": "_connect/port",
+                            "resource_value": "0"
+                        }
+                    },
+                    {
+                        "action": 1,
+                        "custom": {
+                            "resource_key": "_connect/settings",
+                            "resource_value": {
+                                "endpoints": [
+                                    {
+                                        "uuid": "mgmt",
+                                        "name": "mgmt",
+                                        "type": "mgmt"
+                                    },
+                                    {
+                                        "uuid": "200",
+                                        "name": "200",
+                                        "type": "optical"
+                                    },
+                                    {
+                                        "uuid": "500",
+                                        "name": "500",
+                                        "type": "optical"
+                                    },
+                                    {
+                                        "uuid": "501",
+                                        "name": "501",
+                                        "type": "optical"
+                                    }
+                                ]
+                            }
+                        }
+                    }
+                ]
+            }
+        },
+        {
+            "device_id": {
+                "device_uuid": {
+                    "uuid": "172.16.185.31"
+                }
+            },
+            "name": "172.16.185.31",
+            "device_type": "emu-packet-router",
+            "device_operational_status": 1,
+            "device_drivers": [
+                0
+            ],
+            "device_config": {
+                "config_rules": [
+                    {
+                        "action": 1,
+                        "custom": {
+                            "resource_key": "_connect/address",
+                            "resource_value": "127.0.0.1"
+                        }
+                    },
+                    {
+                        "action": 1,
+                        "custom": {
+                            "resource_key": "_connect/port",
+                            "resource_value": "0"
+                        }
+                    },
+                    {
+                        "action": 1,
+                        "custom": {
+                            "resource_key": "_connect/settings",
+                            "resource_value": {
+                                "endpoints": [
+                                    {
+                                        "uuid": "mgmt",
+                                        "name": "mgmt",
+                                        "type": "mgmt"
+                                    },
+                                    {
+                                        "uuid": "500",
+                                        "name": "500",
+                                        "type": "optical"
+                                    },
+                                    {
+                                        "uuid": "501",
+                                        "name": "501",
+                                        "type": "optical"
+                                    }
+                                ]
+                            }
+                        }
+                    }
+                ]
+            }
+        },
+        {
+            "device_id": {
+                "device_uuid": {
+                    "uuid": "172.16.185.33"
+                }
+            },
+            "name": "172.16.185.33",
+            "device_type": "emu-packet-router",
+            "device_operational_status": 1,
+            "device_drivers": [
+                0
+            ],
+            "device_config": {
+                "config_rules": [
+                    {
+                        "action": 1,
+                        "custom": {
+                            "resource_key": "_connect/address",
+                            "resource_value": "127.0.0.1"
+                        }
+                    },
+                    {
+                        "action": 1,
+                        "custom": {
+                            "resource_key": "_connect/port",
+                            "resource_value": "0"
+                        }
+                    },
+                    {
+                        "action": 1,
+                        "custom": {
+                            "resource_key": "_connect/settings",
+                            "resource_value": {
+                                "endpoints": [
+                                    {
+                                        "uuid": "mgmt",
+                                        "name": "mgmt",
+                                        "type": "mgmt"
+                                    },
+                                    {
+                                        "uuid": "500",
+                                        "name": "500",
+                                        "type": "optical"
+                                    },
+                                    {
+                                        "uuid": "501",
+                                        "name": "501",
+                                        "type": "optical"
+                                    }
+                                ]
+                            }
+                        }
+                    }
+                ]
+            }
+        },
+        {
+            "device_id": {
+                "device_uuid": {
+                    "uuid": "172.16.185.32"
+                }
+            },
+            "name": "172.16.185.32",
+            "device_type": "emu-packet-router",
+            "device_operational_status": 1,
+            "device_drivers": [
+                0
+            ],
+            "device_config": {
+                "config_rules": [
+                    {
+                        "action": 1,
+                        "custom": {
+                            "resource_key": "_connect/address",
+                            "resource_value": "127.0.0.1"
+                        }
+                    },
+                    {
+                        "action": 1,
+                        "custom": {
+                            "resource_key": "_connect/port",
+                            "resource_value": "0"
+                        }
+                    },
+                    {
+                        "action": 1,
+                        "custom": {
+                            "resource_key": "_connect/settings",
+                            "resource_value": {
+                                "endpoints": [
+                                    {
+                                        "uuid": "mgmt",
+                                        "name": "mgmt",
+                                        "type": "mgmt"
+                                    },
+                                    {
+                                        "uuid": "200",
+                                        "name": "200",
+                                        "type": "optical"
+                                    },
+                                    {
+                                        "uuid": "500",
+                                        "name": "500",
+                                        "type": "optical"
+                                    },
+                                    {
+                                        "uuid": "501",
+                                        "name": "501",
+                                        "type": "optical"
+                                    }
+                                ]
+                            }
+                        }
+                    }
+                ]
+            }
+        }
+    ],
+    "links": [
+        {
+            "link_id": {
+                "link_uuid": {
+                    "uuid": "172.16.182.25-500"
+                }
+            },
+            "name": "172.16.182.25-500",
+            "attributes": {
+                "total_capacity_gbps": 10,
+                "used_capacity_gbps": 0
+            },
+            "link_endpoint_ids": [
+                {
+                    "device_id": {
+                        "device_uuid": {
+                            "uuid": "172.16.182.25"
+                        }
+                    },
+                    "endpoint_uuid": {
+                        "uuid": "500"
+                    }
+                },
+                {
+                    "device_id": {
+                        "device_uuid": {
+                            "uuid": "172.16.185.33"
+                        }
+                    },
+                    "endpoint_uuid": {
+                        "uuid": "500"
+                    }
+                }
+            ]
+        },
+        {
+            "link_id": {
+                "link_uuid": {
+                    "uuid": "172.16.185.33-500"
+                }
+            },
+            "name": "172.16.185.33-500",
+            "attributes": {
+                "total_capacity_gbps": 10,
+                "used_capacity_gbps": 0
+            },
+            "link_endpoint_ids": [
+                {
+                    "device_id": {
+                        "device_uuid": {
+                            "uuid": "172.16.185.33"
+                        }
+                    },
+                    "endpoint_uuid": {
+                        "uuid": "500"
+                    }
+                },
+                {
+                    "device_id": {
+                        "device_uuid": {
+                            "uuid": "172.16.182.25"
+                        }
+                    },
+                    "endpoint_uuid": {
+                        "uuid": "500"
+                    }
+                }
+            ]
+        },
+        {
+            "link_id": {
+                "link_uuid": {
+                    "uuid": "172.16.182.25-501"
+                }
+            },
+            "name": "172.16.182.25-501",
+            "attributes": {
+                "total_capacity_gbps": 10,
+                "used_capacity_gbps": 0
+            },
+            "link_endpoint_ids": [
+                {
+                    "device_id": {
+                        "device_uuid": {
+                            "uuid": "172.16.182.25"
+                        }
+                    },
+                    "endpoint_uuid": {
+                        "uuid": "501"
+                    }
+                },
+                {
+                    "device_id": {
+                        "device_uuid": {
+                            "uuid": "172.16.185.31"
+                        }
+                    },
+                    "endpoint_uuid": {
+                        "uuid": "501"
+                    }
+                }
+            ]
+        },
+        {
+            "link_id": {
+                "link_uuid": {
+                    "uuid": "172.16.185.31-501"
+                }
+            },
+            "name": "172.16.185.31-501",
+            "attributes": {
+                "total_capacity_gbps": 10,
+                "used_capacity_gbps": 0
+            },
+            "link_endpoint_ids": [
+                {
+                    "device_id": {
+                        "device_uuid": {
+                            "uuid": "172.16.185.31"
+                        }
+                    },
+                    "endpoint_uuid": {
+                        "uuid": "501"
+                    }
+                },
+                {
+                    "device_id": {
+                        "device_uuid": {
+                            "uuid": "172.16.182.25"
+                        }
+                    },
+                    "endpoint_uuid": {
+                        "uuid": "501"
+                    }
+                }
+            ]
+        },
+        {
+            "link_id": {
+                "link_uuid": {
+                    "uuid": "172.16.185.31-500"
+                }
+            },
+            "name": "172.16.185.31-500",
+            "attributes": {
+                "total_capacity_gbps": 10,
+                "used_capacity_gbps": 0
+            },
+            "link_endpoint_ids": [
+                {
+                    "device_id": {
+                        "device_uuid": {
+                            "uuid": "172.16.185.31"
+                        }
+                    },
+                    "endpoint_uuid": {
+                        "uuid": "500"
+                    }
+                },
+                {
+                    "device_id": {
+                        "device_uuid": {
+                            "uuid": "172.16.185.32"
+                        }
+                    },
+                    "endpoint_uuid": {
+                        "uuid": "500"
+                    }
+                }
+            ]
+        },
+        {
+            "link_id": {
+                "link_uuid": {
+                    "uuid": "172.16.185.32-500"
+                }
+            },
+            "name": "172.16.185.32-500",
+            "attributes": {
+                "total_capacity_gbps": 10,
+                "used_capacity_gbps": 0
+            },
+            "link_endpoint_ids": [
+                {
+                    "device_id": {
+                        "device_uuid": {
+                            "uuid": "172.16.185.32"
+                        }
+                    },
+                    "endpoint_uuid": {
+                        "uuid": "500"
+                    }
+                },
+                {
+                    "device_id": {
+                        "device_uuid": {
+                            "uuid": "172.16.185.31"
+                        }
+                    },
+                    "endpoint_uuid": {
+                        "uuid": "500"
+                    }
+                }
+            ]
+        },
+        {
+            "link_id": {
+                "link_uuid": {
+                    "uuid": "172.16.185.33-501"
+                }
+            },
+            "name": "172.16.185.33-501",
+            "attributes": {
+                "total_capacity_gbps": 10,
+                "used_capacity_gbps": 0
+            },
+            "link_endpoint_ids": [
+                {
+                    "device_id": {
+                        "device_uuid": {
+                            "uuid": "172.16.185.33"
+                        }
+                    },
+                    "endpoint_uuid": {
+                        "uuid": "501"
+                    }
+                },
+                {
+                    "device_id": {
+                        "device_uuid": {
+                            "uuid": "172.16.185.32"
+                        }
+                    },
+                    "endpoint_uuid": {
+                        "uuid": "501"
+                    }
+                }
+            ]
+        },
+        {
+            "link_id": {
+                "link_uuid": {
+                    "uuid": "172.16.185.32-501"
+                }
+            },
+            "name": "172.16.185.32-501",
+            "attributes": {
+                "total_capacity_gbps": 10,
+                "used_capacity_gbps": 0
+            },
+            "link_endpoint_ids": [
+                {
+                    "device_id": {
+                        "device_uuid": {
+                            "uuid": "172.16.185.32"
+                        }
+                    },
+                    "endpoint_uuid": {
+                        "uuid": "501"
+                    }
+                },
+                {
+                    "device_id": {
+                        "device_uuid": {
+                            "uuid": "172.16.185.33"
+                        }
+                    },
+                    "endpoint_uuid": {
+                        "uuid": "501"
+                    }
+                }
+            ]
+        }
+    ]
+}
\ No newline at end of file
diff --git a/src/nbi/tests/data/slice/post_connection_group_to_network_slice1.json b/src/nbi/tests/data/slice/post_connection_group_to_network_slice1.json
new file mode 100644
index 0000000000000000000000000000000000000000..d39a837bd8c3719463e8ecfd3fbfc2d25111afef
--- /dev/null
+++ b/src/nbi/tests/data/slice/post_connection_group_to_network_slice1.json
@@ -0,0 +1,62 @@
+{
+    "connection-group": [
+        {
+            "id": "line2",
+            "connectivity-type": "point-to-point",
+            "connectivity-construct": [
+                {
+                    "id": 1,
+                    "p2p-sender-sdp": "1",
+                    "p2p-receiver-sdp": "3",
+                    "service-slo-sle-policy": {
+                        "slo-policy": {
+                            "metric-bound": [
+                                {
+                                    "metric-type": "ietf-network-slice-service:one-way-delay-maximum",
+                                    "metric-unit": "milliseconds",
+                                    "bound": "10"
+                                },
+                                {
+                                    "metric-type": "ietf-network-slice-service:one-way-bandwidth",
+                                    "metric-unit": "Mbps",
+                                    "bound": "5000"
+                                },
+                                {
+                                    "metric-type": "ietf-network-slice-service:two-way-packet-loss",
+                                    "metric-unit": "percentage",
+                                    "percentile-value": "0.001"
+                                }
+                            ]
+                        }
+                    }
+                },
+                {
+                    "id": 2,
+                    "p2p-sender-sdp": "3",
+                    "p2p-receiver-sdp": "1",
+                    "service-slo-sle-policy": {
+                        "slo-policy": {
+                            "metric-bound": [
+                                {
+                                    "metric-type": "ietf-network-slice-service:one-way-delay-maximum",
+                                    "metric-unit": "milliseconds",
+                                    "bound": "20"
+                                },
+                                {
+                                    "metric-type": "ietf-network-slice-service:one-way-bandwidth",
+                                    "metric-unit": "Mbps",
+                                    "bound": "1000"
+                                },
+                                {
+                                    "metric-type": "ietf-network-slice-service:two-way-packet-loss",
+                                    "metric-unit": "percentage",
+                                    "percentile-value": "0.001"
+                                }
+                            ]
+                        }
+                    }
+                }
+            ]
+        }
+    ]
+}
\ No newline at end of file
diff --git a/src/nbi/tests/data/slice/post_connection_group_to_network_slice2.json b/src/nbi/tests/data/slice/post_connection_group_to_network_slice2.json
new file mode 100644
index 0000000000000000000000000000000000000000..d39a837bd8c3719463e8ecfd3fbfc2d25111afef
--- /dev/null
+++ b/src/nbi/tests/data/slice/post_connection_group_to_network_slice2.json
@@ -0,0 +1,62 @@
+{
+    "connection-group": [
+        {
+            "id": "line2",
+            "connectivity-type": "point-to-point",
+            "connectivity-construct": [
+                {
+                    "id": 1,
+                    "p2p-sender-sdp": "1",
+                    "p2p-receiver-sdp": "3",
+                    "service-slo-sle-policy": {
+                        "slo-policy": {
+                            "metric-bound": [
+                                {
+                                    "metric-type": "ietf-network-slice-service:one-way-delay-maximum",
+                                    "metric-unit": "milliseconds",
+                                    "bound": "10"
+                                },
+                                {
+                                    "metric-type": "ietf-network-slice-service:one-way-bandwidth",
+                                    "metric-unit": "Mbps",
+                                    "bound": "5000"
+                                },
+                                {
+                                    "metric-type": "ietf-network-slice-service:two-way-packet-loss",
+                                    "metric-unit": "percentage",
+                                    "percentile-value": "0.001"
+                                }
+                            ]
+                        }
+                    }
+                },
+                {
+                    "id": 2,
+                    "p2p-sender-sdp": "3",
+                    "p2p-receiver-sdp": "1",
+                    "service-slo-sle-policy": {
+                        "slo-policy": {
+                            "metric-bound": [
+                                {
+                                    "metric-type": "ietf-network-slice-service:one-way-delay-maximum",
+                                    "metric-unit": "milliseconds",
+                                    "bound": "20"
+                                },
+                                {
+                                    "metric-type": "ietf-network-slice-service:one-way-bandwidth",
+                                    "metric-unit": "Mbps",
+                                    "bound": "1000"
+                                },
+                                {
+                                    "metric-type": "ietf-network-slice-service:two-way-packet-loss",
+                                    "metric-unit": "percentage",
+                                    "percentile-value": "0.001"
+                                }
+                            ]
+                        }
+                    }
+                }
+            ]
+        }
+    ]
+}
\ No newline at end of file
diff --git a/src/nbi/tests/data/slice/post_match_criteria_to_sdp1_in_slice1.json b/src/nbi/tests/data/slice/post_match_criteria_to_sdp1_in_slice1.json
new file mode 100644
index 0000000000000000000000000000000000000000..16a36d45b86230b27eafa45a612b95c248a7b3ac
--- /dev/null
+++ b/src/nbi/tests/data/slice/post_match_criteria_to_sdp1_in_slice1.json
@@ -0,0 +1,40 @@
+{
+    "match-criterion": [
+        {
+            "index": 2,
+            "match-type": [
+                {
+                    "type": "ietf-network-slice-service:vlan",
+                    "value": [
+                        "101"
+                    ]
+                },
+                {
+                    "type": "ietf-network-slice-service:source-ip-prefix",
+                    "value": [
+                        "172.1.101.22/24"
+                    ]
+                },
+                {
+                    "type": "ietf-network-slice-service:source-tcp-port",
+                    "value": [
+                        "10200"
+                    ]
+                },
+                {
+                    "type": "ietf-network-slice-service:destination-ip-prefix",
+                    "value": [
+                        "172.16.104.222/24"
+                    ]
+                },
+                {
+                    "type": "ietf-network-slice-service:destination-tcp-port",
+                    "value": [
+                        "10500"
+                    ]
+                }
+            ],
+            "target-connection-group-id": "line2"
+        }
+    ]
+}
\ No newline at end of file
diff --git a/src/nbi/tests/data/slice/post_match_criteria_to_sdp1_in_slice2.json b/src/nbi/tests/data/slice/post_match_criteria_to_sdp1_in_slice2.json
new file mode 100644
index 0000000000000000000000000000000000000000..8ceefdc2f2471af225143e5a1def2d7ba71e2ab1
--- /dev/null
+++ b/src/nbi/tests/data/slice/post_match_criteria_to_sdp1_in_slice2.json
@@ -0,0 +1,40 @@
+{
+    "match-criterion": [
+        {
+            "index": 2,
+            "match-type": [
+                {
+                    "type": "ietf-network-slice-service:vlan",
+                    "value": [
+                        "201"
+                    ]
+                },
+                {
+                    "type": "ietf-network-slice-service:source-ip-prefix",
+                    "value": [
+                        "172.1.201.22/24"
+                    ]
+                },
+                {
+                    "type": "ietf-network-slice-service:source-tcp-port",
+                    "value": [
+                        "10200"
+                    ]
+                },
+                {
+                    "type": "ietf-network-slice-service:destination-ip-prefix",
+                    "value": [
+                        "172.16.104.222/24"
+                    ]
+                },
+                {
+                    "type": "ietf-network-slice-service:destination-tcp-port",
+                    "value": [
+                        "10500"
+                    ]
+                }
+            ],
+            "target-connection-group-id": "line2"
+        }
+    ]
+}
\ No newline at end of file
diff --git a/src/nbi/tests/data/slice/post_network_slice1.json b/src/nbi/tests/data/slice/post_network_slice1.json
new file mode 100644
index 0000000000000000000000000000000000000000..e6e0ee90a25ff12f73c8f8896f9c2c74ab6b4019
--- /dev/null
+++ b/src/nbi/tests/data/slice/post_network_slice1.json
@@ -0,0 +1,188 @@
+{
+    "slice-service": [
+        {
+            "id": "slice1",
+            "description": "network slice 1, connect to VM1",
+            "sdps": {
+                "sdp": [
+                    {
+                        "id": "1",
+                        "node-id": "172.16.204.220",
+                        "sdp-ip-address": [
+                            "172.16.204.220"
+                        ],
+                        "service-match-criteria": {
+                            "match-criterion": [
+                                {
+                                    "index": 1,
+                                    "match-type": [
+                                        {
+                                            "type": "ietf-network-slice-service:vlan",
+                                            "value": [
+                                                "101"
+                                            ]
+                                        },
+                                        {
+                                            "type": "ietf-network-slice-service:destination-ip-prefix",
+                                            "value": [
+                                                "172.16.104.221/24"
+                                            ]
+                                        },
+                                        {
+                                            "type": "ietf-network-slice-service:destination-tcp-port",
+                                            "value": [
+                                                "10500"
+                                            ]
+                                        },
+                                        {
+                                            "type": "ietf-network-slice-service:source-ip-prefix",
+                                            "value": [
+                                                "172.1.101.22/24"
+                                            ]
+                                        },
+                                        {
+                                            "type": "ietf-network-slice-service:source-tcp-port",
+                                            "value": [
+                                                "10200"
+                                            ]
+                                        }
+                                    ],
+                                    "target-connection-group-id": "line1"
+                                }
+                            ]
+                        },
+                        "attachment-circuits": {
+                            "attachment-circuit": [
+                                {
+                                    "id": "AC POP to VM1",
+                                    "description": "AC VM1 connected to POP",
+                                    "ac-node-id": "172.16.204.220",
+                                    "ac-tp-id": "200"
+                                }
+                            ]
+                        }
+                    },
+                    {
+                        "id": "2",
+                        "node-id": "172.16.61.10",
+                        "sdp-ip-address": [
+                            "172.16.61.10"
+                        ],
+                        "service-match-criteria": {
+                            "match-criterion": [
+                                {
+                                    "index": 1,
+                                    "match-type": [
+                                        {
+                                            "type": "ietf-network-slice-service:vlan",
+                                            "value": [
+                                                "21"
+                                            ]
+                                        },
+                                        {
+                                            "type": "ietf-network-slice-service:source-ip-prefix",
+                                            "value": [
+                                                "172.16.104.221/24"
+                                            ]
+                                        },
+                                        {
+                                            "type": "ietf-network-slice-service:source-tcp-port",
+                                            "value": [
+                                                "10500"
+                                            ]
+                                        },
+                                        {
+                                            "type": "ietf-network-slice-service:destination-ip-prefix",
+                                            "value": [
+                                                "172.1.101.22/24"
+                                            ]
+                                        },
+                                        {
+                                            "type": "ietf-network-slice-service:destination-tcp-port",
+                                            "value": [
+                                                "10200"
+                                            ]
+                                        }
+                                    ],
+                                    "target-connection-group-id": "line1"
+                                }
+                            ]
+                        },
+                        "attachment-circuits": {
+                            "attachment-circuit": [
+                                {
+                                    "id": "AC ONT",
+                                    "description": "AC connected to PC1",
+                                    "ac-node-id": "172.16.61.10",
+                                    "ac-tp-id": "200"
+                                }
+                            ]
+                        }
+                    }
+                ]
+            },
+            "connection-groups": {
+                "connection-group": [
+                    {
+                        "id": "line1",
+                        "connectivity-type": "point-to-point",
+                        "connectivity-construct": [
+                            {
+                                "id": 1,
+                                "p2p-sender-sdp": "1",
+                                "p2p-receiver-sdp": "2",
+                                "service-slo-sle-policy": {
+                                    "slo-policy": {
+                                        "metric-bound": [
+                                            {
+                                                "metric-type": "ietf-network-slice-service:one-way-delay-maximum",
+                                                "metric-unit": "milliseconds",
+                                                "bound": "10"
+                                            },
+                                            {
+                                                "metric-type": "ietf-network-slice-service:one-way-bandwidth",
+                                                "metric-unit": "Mbps",
+                                                "bound": "5000"
+                                            },
+                                            {
+                                                "metric-type": "ietf-network-slice-service:two-way-packet-loss",
+                                                "metric-unit": "percentage",
+                                                "percentile-value": "0.001"
+                                            }
+                                        ]
+                                    }
+                                }
+                            },
+                            {
+                                "id": 2,
+                                "p2p-sender-sdp": "2",
+                                "p2p-receiver-sdp": "1",
+                                "service-slo-sle-policy": {
+                                    "slo-policy": {
+                                        "metric-bound": [
+                                            {
+                                                "metric-type": "ietf-network-slice-service:one-way-delay-maximum",
+                                                "metric-unit": "milliseconds",
+                                                "bound": "20"
+                                            },
+                                            {
+                                                "metric-type": "ietf-network-slice-service:one-way-bandwidth",
+                                                "metric-unit": "Mbps",
+                                                "bound": "1000"
+                                            },
+                                            {
+                                                "metric-type": "ietf-network-slice-service:two-way-packet-loss",
+                                                "metric-unit": "percentage",
+                                                "percentile-value": "0.001"
+                                            }
+                                        ]
+                                    }
+                                }
+                            }
+                        ]
+                    }
+                ]
+            }
+        }
+    ]
+}
\ No newline at end of file
diff --git a/src/nbi/tests/data/slice/post_network_slice2.json b/src/nbi/tests/data/slice/post_network_slice2.json
new file mode 100644
index 0000000000000000000000000000000000000000..97e6ade27449be0a3816085aa31b707ffbb6f813
--- /dev/null
+++ b/src/nbi/tests/data/slice/post_network_slice2.json
@@ -0,0 +1,189 @@
+{
+    "slice-service": [
+        {
+            "id": "slice2",
+            "description": "network slice 2, connect to VM2",
+            "sdps": {
+                "sdp": [
+                    {
+                        "id": "1",
+                        "node-id": "172.16.204.220",
+                        "sdp-ip-address": [
+                            "172.16.204.220"
+                        ],
+                        "service-match-criteria": {
+                            "match-criterion": [
+                                {
+                                    "index": 1,
+                                    "match-type": [
+                                        {
+                                            "type": "ietf-network-slice-service:vlan",
+                                            "value": [
+                                                "201"
+                                            ]
+                                        },
+                                        {
+                                            "type": "ietf-network-slice-service:destination-ip-prefix",
+                                            "value": [
+                                                "172.16.104.221/24"
+                                            ]
+                                        },
+                                        {
+                                            "type": "ietf-network-slice-service:destination-tcp-port",
+                                            "value": [
+                                                "10500"
+                                            ]
+                                        },
+                                        {
+                                            "type": "ietf-network-slice-service:source-ip-prefix",
+                                            "value": [
+                                                "172.1.201.22/24"
+                                            ]
+                                        },
+                                        {
+                                            "type": "ietf-network-slice-service:source-tcp-port",
+                                            "value": [
+                                                "10200"
+                                            ]
+                                        }
+                                    ],
+                                    "target-connection-group-id": "line1"
+                                }
+                            ]
+                        },
+                        "attachment-circuits": {
+                            "attachment-circuit": [
+                                {
+                                    "id": "AC POP to VM2",
+                                    "description": "AC VM2 connected to POP",
+                                    "ac-node-id": "172.16.204.220",
+                                    "ac-tp-id": "201"
+                                }
+                            ]
+                        }
+                    },
+                    {
+                        "id": "2",
+                        "node-id": "172.16.61.10",
+                        "sdp-ip-address": [
+                            "172.16.61.10"
+                        ],
+                        "service-match-criteria": {
+                            "match-criterion": [
+                                {
+                                    "index": 1,
+                                    "match-type": [
+                                        {
+                                            "type": "ietf-network-slice-service:vlan",
+                                            "value": [
+                                                "31"
+                                            ]
+                                        },
+                                        {
+                                            "type": "ietf-network-slice-service:source-ip-prefix",
+                                            "value": [
+                                                "172.16.104.221/24"
+                                            ]
+                                        },
+                                        {
+                                            "type": "ietf-network-slice-service:source-tcp-port",
+                                            "value": [
+                                                "10500"
+                                            ]
+                                        },
+                                        {
+                                            "type": "ietf-network-slice-service:destination-ip-prefix",
+                                            "value": [
+                                                "172.1.201.22/24"
+                                            ]
+                                        },
+                                        {
+                                            "type": "ietf-network-slice-service:destination-tcp-port",
+                                            "value": [
+                                                "10200"
+                                            ]
+                                        }
+                                    ],
+                                    "target-connection-group-id": "line1"
+                                }
+                            ]
+                        },
+                        "attachment-circuits": {
+                            "attachment-circuit": [
+                                {
+                                    "id": "AC ONT",
+                                    "description": "AC connected to PC",
+                                    "ac-node-id": "172.16.61.10",
+                                    "ac-tp-id": "200",
+                                    "ac-ipv4-address": "172.16.61.10"
+                                }
+                            ]
+                        }
+                    }
+                ]
+            },
+            "connection-groups": {
+                "connection-group": [
+                    {
+                        "id": "line1",
+                        "connectivity-type": "point-to-point",
+                        "connectivity-construct": [
+                            {
+                                "id": 1,
+                                "p2p-sender-sdp": "1",
+                                "p2p-receiver-sdp": "2",
+                                "service-slo-sle-policy": {
+                                    "slo-policy": {
+                                        "metric-bound": [
+                                            {
+                                                "metric-type": "ietf-network-slice-service:one-way-delay-maximum",
+                                                "metric-unit": "milliseconds",
+                                                "bound": "10"
+                                            },
+                                            {
+                                                "metric-type": "ietf-network-slice-service:one-way-bandwidth",
+                                                "metric-unit": "Mbps",
+                                                "bound": "5000"
+                                            },
+                                            {
+                                                "metric-type": "ietf-network-slice-service:two-way-packet-loss",
+                                                "metric-unit": "percentage",
+                                                "percentile-value": "0.001"
+                                            }
+                                        ]
+                                    }
+                                }
+                            },
+                            {
+                                "id": 2,
+                                "p2p-sender-sdp": "2",
+                                "p2p-receiver-sdp": "1",
+                                "service-slo-sle-policy": {
+                                    "slo-policy": {
+                                        "metric-bound": [
+                                            {
+                                                "metric-type": "ietf-network-slice-service:one-way-delay-maximum",
+                                                "metric-unit": "milliseconds",
+                                                "bound": "20"
+                                            },
+                                            {
+                                                "metric-type": "ietf-network-slice-service:one-way-bandwidth",
+                                                "metric-unit": "Mbps",
+                                                "bound": "1000"
+                                            },
+                                            {
+                                                "metric-type": "ietf-network-slice-service:two-way-packet-loss",
+                                                "metric-unit": "percentage",
+                                                "percentile-value": "0.001"
+                                            }
+                                        ]
+                                    }
+                                }
+                            }
+                        ]
+                    }
+                ]
+            }
+        }
+    ]
+}
diff --git a/src/nbi/tests/data/slice/post_sdp_to_network_slice1.json b/src/nbi/tests/data/slice/post_sdp_to_network_slice1.json
new file mode 100644
index 0000000000000000000000000000000000000000..bd3895fc4ae5a9a0b2059be3f6b31a05451abd22
--- /dev/null
+++ b/src/nbi/tests/data/slice/post_sdp_to_network_slice1.json
@@ -0,0 +1,61 @@
+{
+    "sdp": [
+        {
+            "id": "3",
+            "node-id": "172.16.61.11",
+            "sdp-ip-address": [
+                "172.16.61.11"
+            ],
+            "service-match-criteria": {
+                "match-criterion": [
+                    {
+                        "index": 1,
+                        "match-type": [
+                            {
+                                "type": "ietf-network-slice-service:vlan",
+                                "value": [
+                                    "21"
+                                ]
+                            },
+                            {
+                                "type": "ietf-network-slice-service:source-ip-prefix",
+                                "value": [
+                                    "172.16.104.222/24"
+                                ]
+                            },
+                            {
+                                "type": "ietf-network-slice-service:source-tcp-port",
+                                "value": [
+                                    "10500"
+                                ]
+                            },
+                            {
+                                "type": "ietf-network-slice-service:destination-ip-prefix",
+                                "value": [
+                                    "172.1.101.22/24"
+                                ]
+                            },
+                            {
+                                "type": "ietf-network-slice-service:destination-tcp-port",
+                                "value": [
+                                    "10200"
+                                ]
+                            }
+                        ],
+                        "target-connection-group-id": "line2"
+                    }
+                ]
+            },
+            "attachment-circuits": {
+                "attachment-circuit": [
+                    {
+                        "id": "AC ONT",
+                        "description": "AC connected to PC2",
+                        "ac-node-id": "172.16.61.11",
+                        "ac-tp-id": "200"
+                    }
+                ]
+            }
+        }
+    ]
+}
\ No newline at end of file
diff --git a/src/nbi/tests/data/slice/post_sdp_to_network_slice2.json b/src/nbi/tests/data/slice/post_sdp_to_network_slice2.json
new file mode 100644
index 0000000000000000000000000000000000000000..0b147125bd7eb3efc84c87bebab919639782f760
--- /dev/null
+++ b/src/nbi/tests/data/slice/post_sdp_to_network_slice2.json
@@ -0,0 +1,62 @@
+{
+    "sdp": [
+        {
+            "id": "3",
+            "node-id": "172.16.61.11",
+            "sdp-ip-address": [
+                "172.16.61.11"
+            ],
+            "service-match-criteria": {
+                "match-criterion": [
+                    {
+                        "index": 1,
+                        "match-type": [
+                            {
+                                "type": "ietf-network-slice-service:vlan",
+                                "value": [
+                                    "31"
+                                ]
+                            },
+                            {
+                                "type": "ietf-network-slice-service:source-ip-prefix",
+                                "value": [
+                                    "172.16.104.222/24"
+                                ]
+                            },
+                            {
+                                "type": "ietf-network-slice-service:source-tcp-port",
+                                "value": [
+                                    "10500"
+                                ]
+                            },
+                            {
+                                "type": "ietf-network-slice-service:destination-ip-prefix",
+                                "value": [
+                                    "172.1.201.22/24"
+                                ]
+                            },
+                            {
+                                "type": "ietf-network-slice-service:destination-tcp-port",
+                                "value": [
+                                    "10200"
+                                ]
+                            }
+                        ],
+                        "target-connection-group-id": "line2"
+                    }
+                ]
+            },
+            "attachment-circuits": {
+                "attachment-circuit": [
+                    {
+                        "id": "AC ONT",
+                        "description": "AC connected to PC2",
+                        "ac-node-id": "172.16.61.11",
+                        "ac-tp-id": "200",
+                        "ac-ipv4-address": "172.16.61.11"
+                    }
+                ]
+            }
+        }
+    ]
+}
\ No newline at end of file
diff --git a/src/nbi/tests/test_slice_2.py b/src/nbi/tests/test_slice_2.py
new file mode 100644
index 0000000000000000000000000000000000000000..5722e3d922a79bd169fc80a5374c4daab4f5d7d9
--- /dev/null
+++ b/src/nbi/tests/test_slice_2.py
@@ -0,0 +1,205 @@
+# 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
+from typing import Optional
+
+from common.proto.context_pb2 import ConfigRule, ServiceConfig, SliceList
+from context.client.ContextClient import ContextClient
+from nbi.service.rest_server.nbi_plugins.ietf_network_slice.ietf_slice_handler import (
+    IETFSliceHandler,
+)
+
+
+def get_custom_config_rule(
+    service_config: ServiceConfig, resource_key: str
+) -> Optional[ConfigRule]:
+    for cr in service_config.config_rules:
+        if (
+            cr.WhichOneof("config_rule") == "custom"
+            and cr.custom.resource_key == resource_key
+        ):
+            return cr
+
+
+RUNNING_RESOURCE_KEY = "running_ietf_slice"
+CANDIDATE_RESOURCE_KEY = "candidate_ietf_slice"
+
+context_client = ContextClient()
+
+with open("nbi/tests/data/slice/post_network_slice1.json", mode="r") as f:
+    post_slice_request = json.load(f)
+
+with open("nbi/tests/data/slice/post_sdp_to_network_slice1.json", mode="r") as f:
+    post_sdp_request = json.load(f)
+
+with open(
+    "nbi/tests/data/slice/post_connection_group_to_network_slice1.json", mode="r"
+) as f:
+    post_connection_group_request = json.load(f)
+
+with open(
+    "nbi/tests/data/slice/post_match_criteria_to_sdp1_in_slice1.json", mode="r"
+) as f:
+    post_match_criteria_request = json.load(f)
+
+slice_1 = None
+
+
+def select_slice(*args) -> SliceList:
+    slice_list = SliceList()
+    slice_list.slices.extend([slice_1])
+    return slice_list
+
+
+def test_create_slice():
+    global slice_1
+
+    slice_1 = IETFSliceHandler.create_slice_service(post_slice_request)
+    candidate_ietf_data = json.loads(
+        get_custom_config_rule(
+            slice_1.slice_config, CANDIDATE_RESOURCE_KEY
+        ).custom.resource_value
+    )
+    assert candidate_ietf_data["network-slice-services"] == post_slice_request
+    assert slice_1.slice_endpoint_ids[0].device_id.device_uuid.uuid == "172.16.204.220"
+    assert slice_1.slice_endpoint_ids[1].device_id.device_uuid.uuid == "172.16.61.10"
+    assert slice_1.slice_id.slice_uuid.uuid == "slice1"
+
+
+def test_create_sdp(monkeypatch):
+    global slice_1
+
+    monkeypatch.setattr(context_client, "SelectSlice", select_slice)
+
+    slice_1 = IETFSliceHandler.create_sdp(post_sdp_request, "slice1", context_client)
+    candidate_ietf_data = json.loads(
+        get_custom_config_rule(
+            slice_1.slice_config, CANDIDATE_RESOURCE_KEY
+        ).custom.resource_value
+    )
+    slice_services = candidate_ietf_data["network-slice-services"]["slice-service"]
+    slice_service = slice_services[0]
+    slice_sdps = slice_service["sdps"]["sdp"]
+    assert len(slice_sdps) == 3
+
+
+def test_create_connection_group(monkeypatch):
+    global slice_1
+
+    monkeypatch.setattr(context_client, "SelectSlice", select_slice)
+
+    slice_1 = IETFSliceHandler.create_connection_group(
+        post_connection_group_request, "slice1", context_client
+    )
+    candidate_ietf_data = json.loads(
+        get_custom_config_rule(
+            slice_1.slice_config, CANDIDATE_RESOURCE_KEY
+        ).custom.resource_value
+    )
+    slice_services = candidate_ietf_data["network-slice-services"]["slice-service"]
+    slice_service = slice_services[0]
+    slice_connection_groups = slice_service["connection-groups"]["connection-group"]
+
+    assert slice_connection_groups[0]["id"] == "line1"
+    assert slice_connection_groups[1]["id"] == "line2"
+    assert len(slice_connection_groups) == 2
+
+
+def test_create_match_criteria(monkeypatch):
+    global slice_1
+
+    monkeypatch.setattr(context_client, "SelectSlice", select_slice)
+
+    slice_1 = IETFSliceHandler.create_match_criteria(
+        post_match_criteria_request, "slice1", "1", context_client
+    )
+    candidate_ietf_data = json.loads(
+        get_custom_config_rule(
+            slice_1.slice_config, CANDIDATE_RESOURCE_KEY
+        ).custom.resource_value
+    )
+    slice_services = candidate_ietf_data["network-slice-services"]["slice-service"]
+    slice_service = slice_services[0]
+    slice_sdps = slice_service["sdps"]["sdp"]
+    sdp1_match_criteria = slice_sdps[0]["service-match-criteria"]["match-criterion"]
+
+    slice_1 = IETFSliceHandler.copy_candidate_ietf_slice_data_to_running("slice1", context_client)
+    assert len(sdp1_match_criteria) == 2
+    assert sdp1_match_criteria[0]["target-connection-group-id"] == "line1"
+    assert sdp1_match_criteria[1]["target-connection-group-id"] == "line2"
+    assert slice_1.slice_endpoint_ids[0].device_id.device_uuid.uuid == "172.16.204.220"
+    assert slice_1.slice_endpoint_ids[1].device_id.device_uuid.uuid == "172.16.61.11"
+
+
+def test_delete_sdp(monkeypatch):
+    global slice_1
+
+    monkeypatch.setattr(context_client, "SelectSlice", select_slice)
+
+    slice_1 = IETFSliceHandler.delete_sdp("slice1", "3", context_client)
+    candidate_ietf_data = json.loads(
+        get_custom_config_rule(
+            slice_1.slice_config, CANDIDATE_RESOURCE_KEY
+        ).custom.resource_value
+    )
+    slice_services = candidate_ietf_data["network-slice-services"]["slice-service"]
+    slice_service = slice_services[0]
+    slice_sdps = slice_service["sdps"]["sdp"]
+    assert len(slice_sdps) == 2
+    assert "3" not in (sdp["id"] for sdp in slice_sdps)
+
+
+def test_delete_connection_group(monkeypatch):
+    global slice_1
+
+    monkeypatch.setattr(context_client, "SelectSlice", select_slice)
+    running_ietf_data = json.loads(
+        get_custom_config_rule(
+            slice_1.slice_config, RUNNING_RESOURCE_KEY
+        ).custom.resource_value
+    )
+    slice_1 = IETFSliceHandler.delete_connection_group(
+        "slice1", "line2", context_client
+    )
+    
+    candidate_ietf_data = json.loads(
+        get_custom_config_rule(
+            slice_1.slice_config, CANDIDATE_RESOURCE_KEY
+        ).custom.resource_value
+    )
+    slice_services = candidate_ietf_data["network-slice-services"]["slice-service"]
+    slice_service = slice_services[0]
+    slice_connection_groups = slice_service["connection-groups"]["connection-group"]
+    assert len(slice_connection_groups) == 1
+    assert slice_connection_groups[0]["id"] == "line1"
+
+
+def test_delete_match_criteria(monkeypatch):
+    global slice_1
+
+    monkeypatch.setattr(context_client, "SelectSlice", select_slice)
+
+    slice_1 = IETFSliceHandler.delete_match_criteria("slice1", "1", 2, context_client)
+    candidate_ietf_data = json.loads(
+        get_custom_config_rule(
+            slice_1.slice_config, CANDIDATE_RESOURCE_KEY
+        ).custom.resource_value
+    )
+    slice_services = candidate_ietf_data["network-slice-services"]["slice-service"]
+    slice_service = slice_services[0]
+    slice_sdps = slice_service["sdps"]["sdp"]
+    sdp1_match_criteria = slice_sdps[0]["service-match-criteria"]["match-criterion"]
+    assert len(sdp1_match_criteria) == 1
+    assert sdp1_match_criteria[0]["target-connection-group-id"] == "line1"
diff --git a/src/service/requirements.in b/src/service/requirements.in
index 3f8d2a35453691420a9469dfffd0a0d2648c6397..d0dd6dcfe13610fc315a50437fb5f3e094b4ee5e 100644
--- a/src/service/requirements.in
+++ b/src/service/requirements.in
@@ -13,6 +13,7 @@
 # limitations under the License.
 
 
+deepdiff==6.7.*
 anytree==2.8.0
 geopy==2.3.0
 netaddr==0.9.0
diff --git a/src/service/service/service_handler_api/FilterFields.py b/src/service/service/service_handler_api/FilterFields.py
index 78f084605bcd759825975cb7f11abc659506755b..bb96f28351d6c29de43d7dbb8a42db2a095795c3 100644
--- a/src/service/service/service_handler_api/FilterFields.py
+++ b/src/service/service/service_handler_api/FilterFields.py
@@ -44,6 +44,7 @@ DEVICE_DRIVER_VALUES = {
     DeviceDriverEnum.DEVICEDRIVER_IETF_ACTN,
     DeviceDriverEnum.DEVICEDRIVER_OC,
     DeviceDriverEnum.DEVICEDRIVER_QKD,
+    DeviceDriverEnum.DEVICEDRIVER_IETF_L3VPN,
 }
 
 # Map allowed filter fields to allowed values per Filter field. If no restriction (free text) None is specified
diff --git a/src/service/service/service_handlers/__init__.py b/src/service/service/service_handlers/__init__.py
index f93cf011fe02139ae350b91eab52eb71ded0574d..b4d9f39ded994e629eed9847b94b359bbc9b027b 100644
--- a/src/service/service/service_handlers/__init__.py
+++ b/src/service/service/service_handlers/__init__.py
@@ -16,6 +16,7 @@ from common.proto.context_pb2 import DeviceDriverEnum, ServiceTypeEnum
 from ..service_handler_api.FilterFields import FilterFieldEnum
 from .l2nm_emulated.L2NMEmulatedServiceHandler import L2NMEmulatedServiceHandler
 from .l2nm_ietfl2vpn.L2NM_IETFL2VPN_ServiceHandler import L2NM_IETFL2VPN_ServiceHandler
+from .l3nm_ietfl3vpn.L3NM_IETFL3VPN_ServiceHandler import L3NM_IETFL3VPN_ServiceHandler
 from .l2nm_openconfig.L2NMOpenConfigServiceHandler import L2NMOpenConfigServiceHandler
 from .l3nm_emulated.L3NMEmulatedServiceHandler import L3NMEmulatedServiceHandler
 from .l3nm_openconfig.L3NMOpenConfigServiceHandler import L3NMOpenConfigServiceHandler
@@ -66,6 +67,12 @@ SERVICE_HANDLERS = [
             FilterFieldEnum.DEVICE_DRIVER : DeviceDriverEnum.DEVICEDRIVER_IETF_ACTN,
         }
     ]),
+    (L3NM_IETFL3VPN_ServiceHandler, [
+        {
+            FilterFieldEnum.SERVICE_TYPE  : ServiceTypeEnum.SERVICETYPE_L3NM,
+            FilterFieldEnum.DEVICE_DRIVER : DeviceDriverEnum.DEVICEDRIVER_IETF_L3VPN,
+        }
+    ]),
     (TapiServiceHandler, [
         {
             FilterFieldEnum.SERVICE_TYPE  : ServiceTypeEnum.SERVICETYPE_TAPI_CONNECTIVITY_SERVICE,
diff --git a/src/service/service/service_handlers/l3nm_ietfl3vpn/ConfigRules.py b/src/service/service/service_handlers/l3nm_ietfl3vpn/ConfigRules.py
new file mode 100644
index 0000000000000000000000000000000000000000..c5638fc104c253be20ef1bbeb6c69a4392095ad2
--- /dev/null
+++ b/src/service/service/service_handlers/l3nm_ietfl3vpn/ConfigRules.py
@@ -0,0 +1,316 @@
+# Copyright 2022-2025 ETSI 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, TypedDict
+
+from common.proto.context_pb2 import Link
+from common.tools.object_factory.ConfigRule import (
+    json_config_rule_delete,
+    json_config_rule_set,
+)
+from context.client.ContextClient import ContextClient
+
+
+class LANPrefixesDict(TypedDict):
+    lan: str
+    lan_tag: str
+
+
+SITE_NETWORK_ACCESS_TYPE = "ietf-l3vpn-svc:multipoint"
+
+
+def create_site_dict(
+    site_id: str,
+    site_location: str,
+    device_uuid: str,
+    endpoint_uuid: str,
+    service_uuid: str,
+    role: str,
+    management_type: str,
+    ce_address: str,
+    pe_address: str,
+    ce_pe_network_prefix: int,
+    mtu: int,
+    input_bw: int,
+    output_bw: int,
+    qos_profile_id: str,
+    qos_profile_direction: str,
+    qos_profile_latency: int,
+    qos_profile_bw_guarantee: int,
+    lan_prefixes: List[LANPrefixesDict],
+) -> Dict:
+    """
+    Helper function that creates a dictionary representing a single 'site'
+    entry (including management, locations, devices, routing-protocols, and
+    site-network-accesses).
+    """
+    site_lan_prefixes = [
+        {
+            "lan": lp["lan"],
+            "lan-tag": lp["lan_tag"],
+            "next-hop": ce_address,
+        }
+        for lp in lan_prefixes
+    ]
+
+    return {
+        "site-id": site_id,
+        "management": {"type": management_type},
+        "locations": {"location": [{"location-id": site_location}]},
+        "devices": {
+            "device": [
+                {
+                    "device-id": device_uuid,
+                    "location": site_location,
+                }
+            ]
+        },
+        "routing-protocols": {
+            "routing-protocol": [
+                {
+                    "type": "ietf-l3vpn-svc:static",
+                    "static": {
+                        "cascaded-lan-prefixes": {
+                            "ipv4-lan-prefixes": site_lan_prefixes
+                        }
+                    },
+                }
+            ]
+        },
+        "site-network-accesses": {
+            "site-network-access": [
+                {
+                    "site-network-access-id": endpoint_uuid,
+                    "site-network-access-type": SITE_NETWORK_ACCESS_TYPE,
+                    "device-reference": device_uuid,
+                    "vpn-attachment": {
+                        "vpn-id": service_uuid,
+                        "site-role": role,
+                    },
+                    "ip-connection": {
+                        "ipv4": {
+                            "address-allocation-type": "ietf-l3vpn-svc:static-address",
+                            "addresses": {
+                                "provider-address": pe_address,
+                                "customer-address": ce_address,
+                                "prefix-length": ce_pe_network_prefix,
+                            },
+                        }
+                    },
+                    "service": {
+                        "svc-mtu": mtu,
+                        "svc-input-bandwidth": input_bw,
+                        "svc-output-bandwidth": output_bw,
+                        "qos": {
+                            "qos-profile": {
+                                "classes": {
+                                    "class": [
+                                        {
+                                            "class-id": qos_profile_id,
+                                            "direction": qos_profile_direction,
+                                            "latency": {
+                                                "latency-boundary": qos_profile_latency
+                                            },
+                                            "bandwidth": {
+                                                "guaranteed-bw-percent": qos_profile_bw_guarantee
+                                            },
+                                        }
+                                    ]
+                                }
+                            }
+                        },
+                    },
+                }
+            ]
+        },
+    }
+
+
+def setup_config_rules(
+    service_uuid: str, json_settings: Dict, operation_type: str
+) -> List[Dict]:
+    # --- Extract common or required fields for the source site ---
+    src_device_uuid: str = json_settings["src_device_name"]
+    src_endpoint_uuid: str = json_settings["src_endpoint_name"]
+    src_site_location: str = json_settings["src_site_location"]
+    src_ipv4_lan_prefixes: list[LANPrefixesDict] = json_settings.get(
+        "src_ipv4_lan_prefixes"
+    )
+    src_site_id: str = json_settings.get("src_site_id", f"site_{src_site_location}")
+    src_management_type: str = json_settings.get(
+        "src_management_type", "ietf-l3vpn-svc:provider-managed"
+    )
+    if src_management_type != "ietf-l3vpn-svc:provider-managed":
+        raise Exception("management type %s not supported", src_management_type)
+
+    src_role: str = "ietf-l3vpn-svc:hub-role"
+    src_ce_address: str = json_settings["src_ce_address"]
+    src_pe_address: str = json_settings["src_pe_address"]
+    src_ce_pe_network_prefix: int = json_settings["src_ce_pe_network_prefix"]
+    src_mtu: int = json_settings["src_mtu"]
+    src_input_bw: int = json_settings["src_input_bw"]
+    src_output_bw: int = json_settings["src_output_bw"]
+    src_qos_profile_id = "qos-realtime"
+    src_qos_profile_direction = "ietf-l3vpn-svc:both"
+    src_qos_profile_latency: int = json_settings["src_qos_profile_latency"]
+    src_qos_profile_bw_guarantee: int = json_settings.get(
+        "src_qos_profile_bw_guarantee", 100
+    )
+
+    # --- Extract common or required fields for the destination site ---
+    dst_device_uuid = json_settings["dst_device_name"]
+    dst_endpoint_uuid = json_settings["dst_endpoint_name"]
+    dst_site_location: str = json_settings["dst_site_location"]
+    dst_ipv4_lan_prefixes: list[LANPrefixesDict] = json_settings[
+        "dst_ipv4_lan_prefixes"
+    ]
+    dst_site_id: str = json_settings.get("dst_site_id", f"site_{dst_site_location}")
+    dst_management_type: str = json_settings.get(
+        "dst_management_type", "ietf-l3vpn-svc:provider-managed"
+    )
+    if dst_management_type != "ietf-l3vpn-svc:provider-managed":
+        raise Exception("management type %s not supported", dst_management_type)
+
+    dst_role: str = "ietf-l3vpn-svc:spoke-role"
+    dst_ce_address: str = json_settings["dst_ce_address"]
+    dst_pe_address: str = json_settings["dst_pe_address"]
+    dst_ce_pe_network_prefix: int = json_settings["dst_ce_pe_network_prefix"]
+    dst_mtu: int = json_settings["dst_mtu"]
+    dst_input_bw: int = json_settings["dst_input_bw"]
+    dst_output_bw: int = json_settings["dst_output_bw"]
+    dst_qos_profile_id = "qos-realtime"
+    dst_qos_profile_direction = "ietf-l3vpn-svc:both"
+    dst_qos_profile_latency: int = json_settings["dst_qos_profile_latency"]
+    dst_qos_profile_bw_guarantee: int = json_settings.get(
+        "dst_qos_profile_bw_guarantee", 100
+    )
+
+    # --- Build site dictionaries using the helper function ---
+    src_site_dict = create_site_dict(
+        site_id=src_site_id,
+        site_location=src_site_location,
+        device_uuid=src_device_uuid,
+        endpoint_uuid=src_endpoint_uuid,
+        service_uuid=service_uuid,
+        role=src_role,
+        management_type=src_management_type,
+        ce_address=src_ce_address,
+        pe_address=src_pe_address,
+        ce_pe_network_prefix=src_ce_pe_network_prefix,
+        mtu=src_mtu,
+        input_bw=src_input_bw,
+        output_bw=src_output_bw,
+        qos_profile_id=src_qos_profile_id,
+        qos_profile_direction=src_qos_profile_direction,
+        qos_profile_latency=src_qos_profile_latency,
+        qos_profile_bw_guarantee=src_qos_profile_bw_guarantee,
+        lan_prefixes=src_ipv4_lan_prefixes,
+    )
+
+    dst_site_dict = create_site_dict(
+        site_id=dst_site_id,
+        site_location=dst_site_location,
+        device_uuid=dst_device_uuid,
+        endpoint_uuid=dst_endpoint_uuid,
+        service_uuid=service_uuid,
+        role=dst_role,
+        management_type=dst_management_type,
+        ce_address=dst_ce_address,
+        pe_address=dst_pe_address,
+        ce_pe_network_prefix=dst_ce_pe_network_prefix,
+        mtu=dst_mtu,
+        input_bw=dst_input_bw,
+        output_bw=dst_output_bw,
+        qos_profile_id=dst_qos_profile_id,
+        qos_profile_direction=dst_qos_profile_direction,
+        qos_profile_latency=dst_qos_profile_latency,
+        qos_profile_bw_guarantee=dst_qos_profile_bw_guarantee,
+        lan_prefixes=dst_ipv4_lan_prefixes,
+    )
+
+    # --- Combine both sites into one structure ---
+    sites = {
+        "site": [
+            src_site_dict,
+            dst_site_dict,
+        ]
+    }
+
+    l3_vpn_data_model = {
+        "ietf-l3vpn-svc:l3vpn-svc": {
+            "vpn-services": {"vpn-service": [{"vpn-id": service_uuid}]},
+            "sites": sites,
+        }
+    }
+
+    json_config_rules = [
+        json_config_rule_set(
+            "/service[{:s}]/IETFL3VPN".format(service_uuid),
+            l3_vpn_data_model,
+        ),
+        json_config_rule_set(
+            "/service[{:s}]/IETFL3VPN/operation".format(service_uuid),
+            {"type": operation_type},
+        ),
+    ]
+
+    return json_config_rules
+
+
+def teardown_config_rules(service_uuid: str) -> List[Dict]:
+    json_config_rules = [
+        json_config_rule_delete(
+            "/service[{:s}]/IETFL3VPN".format(service_uuid),
+            {"id": service_uuid},
+        ),
+        json_config_rule_delete(
+            "/service[{:s}]/IETFL3VPN/operation".format(service_uuid),
+            {},
+        ),
+    ]
+    return json_config_rules
+
+
+def get_link_ep_device_names(
+    link: Link, context_client: ContextClient
+) -> Tuple[str, str, str, str]:
+    ep_ids = link.link_endpoint_ids
+    ep_device_id_1 = ep_ids[0].device_id
+    ep_uuid_1 = ep_ids[0].endpoint_uuid.uuid
+    device_obj_1 = context_client.GetDevice(ep_device_id_1)
+    for d_ep in device_obj_1.device_endpoints:
+        if d_ep.endpoint_id.endpoint_uuid.uuid == ep_uuid_1:
+            ep_name_1 = d_ep.name
+            break
+    else:
+        raise Exception("endpoint not found")
+    device_obj_name_1 = device_obj_1.name
+    ep_device_id_2 = ep_ids[1].device_id
+    ep_uuid_2 = ep_ids[1].endpoint_uuid.uuid
+    device_obj_2 = context_client.GetDevice(ep_device_id_2)
+    for d_ep in device_obj_2.device_endpoints:
+        if d_ep.endpoint_id.endpoint_uuid.uuid == ep_uuid_2:
+            ep_name_2 = d_ep.name
+            break
+    else:
+        raise Exception("endpoint not found")
+    device_obj_name_2 = device_obj_2.name
+    return (
+        device_obj_name_1,
+        ep_name_1,
+        device_obj_1,
+        device_obj_name_2,
+        ep_name_2,
+        device_obj_2,
+    )
diff --git a/src/service/service/service_handlers/l3nm_ietfl3vpn/L3NM_IETFL3VPN_ServiceHandler.py b/src/service/service/service_handlers/l3nm_ietfl3vpn/L3NM_IETFL3VPN_ServiceHandler.py
new file mode 100644
index 0000000000000000000000000000000000000000..aa650c8096b9443b85114166ad1d0bc5b6f2fc55
--- /dev/null
+++ b/src/service/service/service_handlers/l3nm_ietfl3vpn/L3NM_IETFL3VPN_ServiceHandler.py
@@ -0,0 +1,546 @@
+# Copyright 2022-2025 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
+import logging
+from typing import Any, List, Optional, Tuple, TypedDict, Union
+
+from deepdiff import DeepDiff
+
+from common.DeviceTypes import DeviceTypeEnum
+from common.method_wrappers.Decorator import MetricsPool, metered_subclass_method
+from common.proto.context_pb2 import (
+    ConfigRule,
+    Device,
+    DeviceId,
+    Service,
+    ServiceConfig,
+)
+from common.tools.object_factory.Device import json_device_id
+from common.type_checkers.Checkers import chk_type
+from service.service.service_handler_api._ServiceHandler import _ServiceHandler
+from service.service.service_handler_api.SettingsHandler import SettingsHandler
+from service.service.service_handler_api.Tools import (
+    get_device_endpoint_uuids,
+    get_endpoint_matching,
+)
+from service.service.task_scheduler.TaskExecutor import TaskExecutor
+
+from .ConfigRules import setup_config_rules, teardown_config_rules
+
+RUNNING_RESOURCE_KEY = "running_ietf_slice"
+CANDIDATE_RESOURCE_KEY = "candidate_ietf_slice"
+MTU = 1500
+
+LOGGER = logging.getLogger(__name__)
+
+METRICS_POOL = MetricsPool("Service", "Handler", labels={"handler": "l3nm_ietf_l3vpn"})
+
+
+class LANPrefixesDict(TypedDict):
+    lan: str
+    lan_tag: str
+
+
+class Ipv4Info(TypedDict):
+    src_lan: str
+    dst_lan: str
+    src_port: str
+    dst_port: str
+    vlan: str
+
+
+class QoSInfo(TypedDict):
+    src_qos_profile_latency: int
+    src_input_bw: int
+    src_output_bw: int
+    dst_qos_profile_latency: int
+    dst_input_bw: int
+    dst_output_bw: int
+
+
+def get_custom_config_rule(
+    service_config: ServiceConfig, resource_key: str
+) -> Optional[ConfigRule]:
+    """
+    Return the custom ConfigRule from the ServiceConfig matching the given resource_key,
+    or None if not found.
+    """
+    for cr in service_config.config_rules:
+        if (
+            cr.WhichOneof("config_rule") == "custom"
+            and cr.custom.resource_key == resource_key
+        ):
+            return cr
+    return None
+
+
+def load_json_rule_data(service_config: ServiceConfig) -> Tuple[dict, dict]:
+    """
+    Loads the running/candidate JSON data from the service_config for IETF slice data.
+    Raises an exception if either is missing.
+    """
+    running_cr = get_custom_config_rule(service_config, RUNNING_RESOURCE_KEY)
+    candidate_cr = get_custom_config_rule(service_config, CANDIDATE_RESOURCE_KEY)
+
+    if not running_cr or not candidate_cr:
+        raise ValueError("Missing running/candidate IETF slice config rules.")
+
+    running_data = json.loads(running_cr.custom.resource_value)
+    candidate_data = json.loads(candidate_cr.custom.resource_value)
+    return running_data, candidate_data
+
+
+def extract_match_criterion_ipv4_info(match_criterion: dict) -> Ipv4Info:
+    """
+    Extracts IPv4 match criteria data (src/dst IP, ports, VLAN) from a match_criterion dict.
+    """
+    src_lan = dst_lan = src_port = dst_port = vlan = ""
+    for type_value in match_criterion["match-type"]:
+        value = type_value["value"][0]
+        if type_value["type"] == "ietf-network-slice-service:source-ip-prefix":
+            src_lan = value
+        elif type_value["type"] == "ietf-network-slice-service:destination-ip-prefix":
+            dst_lan = value
+        elif type_value["type"] == "ietf-network-slice-service:source-tcp-port":
+            src_port = value
+        elif type_value["type"] == "ietf-network-slice-service:destination-tcp-port":
+            dst_port = value
+        elif type_value["type"] == "ietf-network-slice-service:vlan":
+            vlan = value
+
+    return Ipv4Info(
+        src_lan=src_lan,
+        dst_lan=dst_lan,
+        src_port=src_port,
+        dst_port=dst_port,
+        vlan=vlan,
+    )
+
+
+def extract_qos_info_from_connection_group(
+    src_sdp_id: str, dst_sdp_id: str, connectivity_constructs: list
+) -> QoSInfo:
+    """
+    Given a pair of SDP ids and a list of connectivity constructs, extract QoS info
+    such as latency and bandwidth (for both directions).
+    """
+
+    def _extract_qos_fields(cc: dict) -> Tuple[int, int]:
+        max_delay = 0
+        bandwidth = 0
+        metric_bounds = cc["service-slo-sle-policy"]["slo-policy"]["metric-bound"]
+        for metric_bound in metric_bounds:
+            if (
+                metric_bound["metric-type"]
+                == "ietf-network-slice-service:one-way-delay-maximum"
+                and metric_bound["metric-unit"] == "milliseconds"
+            ):
+                max_delay = int(metric_bound["bound"])
+            elif (
+                metric_bound["metric-type"]
+                == "ietf-network-slice-service:one-way-bandwidth"
+                and metric_bound["metric-unit"] == "Mbps"
+            ):
+                # Convert from Mbps to bps
+                bandwidth = int(metric_bound["bound"]) * 1000000
+        return max_delay, bandwidth
+
+    src_cc = next(
+        cc
+        for cc in connectivity_constructs
+        if cc["p2p-sender-sdp"] == src_sdp_id and cc["p2p-receiver-sdp"] == dst_sdp_id
+    )
+    dst_cc = next(
+        cc
+        for cc in connectivity_constructs
+        if cc["p2p-sender-sdp"] == dst_sdp_id and cc["p2p-receiver-sdp"] == src_sdp_id
+    )
+    src_max_delay, src_bandwidth = _extract_qos_fields(src_cc)
+    dst_max_delay, dst_bandwidth = _extract_qos_fields(dst_cc)
+
+    return QoSInfo(
+        src_qos_profile_latency=src_max_delay,
+        src_input_bw=src_bandwidth,
+        src_output_bw=dst_bandwidth,
+        dst_qos_profile_latency=dst_max_delay,
+        dst_input_bw=dst_bandwidth,
+        dst_output_bw=src_bandwidth,
+    )
+
+
+def get_endpoint_settings(device_obj: Device, endpoint_name: str) -> dict:
+    """
+    Helper to retrieve endpoint settings from a device's config rules given an endpoint name.
+    Raises an exception if not found.
+    """
+    for rule in device_obj.device_config.config_rules:
+        if (
+            rule.WhichOneof("config_rule") == "custom"
+            and rule.custom.resource_key == f"/endpoints/endpoint[{endpoint_name}]"
+        ):
+            return json.loads(rule.custom.resource_value)
+    raise ValueError(f"Endpoint settings not found for endpoint {endpoint_name}")
+
+
+class L3NM_IETFL3VPN_ServiceHandler(_ServiceHandler):
+    def __init__(  # pylint: disable=super-init-not-called
+        self, service: Service, task_executor: TaskExecutor, **settings
+    ) -> None:
+        self.__service = service
+        self.__task_executor = task_executor
+        self.__settings_handler = SettingsHandler(service.service_config, **settings)
+
+    def __find_IP_transport_edge_endpoints(
+        self, endpoints
+    ) -> Tuple[str, str, str, str, Device]:
+        """
+        Searches for two endpoints whose device controllers are IP_SDN_CONTROLLER.
+        Returns (src_device_uuid, src_endpoint_uuid, dst_device_uuid, dst_endpoint_uuid, controller_device).
+        Raises an exception if not found or if the two IP devices differ.
+        """
+
+        # Find the first IP transport edge endpoint from the head of endpoints
+        for ep in endpoints:
+            device_uuid, endpoint_uuid = get_device_endpoint_uuids(ep)
+            device_obj = self.__task_executor.get_device(
+                DeviceId(**json_device_id(device_uuid))
+            )
+            device_controller = self.__task_executor.get_device_controller(device_obj)
+            if device_controller.device_type == DeviceTypeEnum.IP_SDN_CONTROLLER.value:
+                src_device_uuid, src_endpoint_uuid = device_uuid, endpoint_uuid
+                src_device_controller = device_controller
+                break
+        else:
+            raise Exception("No IP transport edge endpoints found")
+
+        # Find the second IP transport edge endpoint from the tail of endpoints
+        for ep in reversed(endpoints):
+            device_uuid, endpoint_uuid = get_device_endpoint_uuids(ep)
+            device_obj = self.__task_executor.get_device(
+                DeviceId(**json_device_id(device_uuid))
+            )
+            device_controller = self.__task_executor.get_device_controller(device_obj)
+            if device_controller.device_type == DeviceTypeEnum.IP_SDN_CONTROLLER.value:
+                dst_device_uuid, dst_endpoint_uuid = device_uuid, endpoint_uuid
+                dst_device_controller = device_controller
+                break
+        else:
+            raise Exception("No IP transport edge endpoints found")
+
+        if src_device_controller != dst_device_controller:
+            raise Exception("Different Src-Dst devices not supported by now")
+
+        return (
+            src_device_uuid,
+            src_endpoint_uuid,
+            dst_device_uuid,
+            dst_endpoint_uuid,
+            src_device_controller,
+        )
+
+    def __build_resource_value_dict(
+        self,
+        service_id: str,
+        src_device_obj: Device,
+        dst_device_obj: Device,
+        src_endpoint_name: str,
+        dst_endpoint_name: str,
+        qos_info: QoSInfo,
+        src_endpoint_settings: dict,
+        dst_endpoint_settings: dict,
+        src_match_criterion_ipv4_info: Ipv4Info,
+        dst_match_criterion_ipv4_info: Ipv4Info,
+    ) -> dict:
+        """
+        Builds the final resource-value dict to be used when calling setup_config_rules().
+        """
+        # Prepare data for source
+        src_device_name = src_device_obj.name
+        src_ce_ip = src_endpoint_settings["address_ip"]
+        src_ce_prefix = src_endpoint_settings["address_prefix"]
+        src_lan_prefixes = [
+            LANPrefixesDict(
+                lan=src_match_criterion_ipv4_info["dst_lan"],
+                lan_tag=src_match_criterion_ipv4_info["vlan"],
+            )
+        ]
+
+        # Prepare data for destination
+        dst_device_name = dst_device_obj.name
+        dst_ce_ip = dst_endpoint_settings["address_ip"]
+        dst_ce_prefix = dst_endpoint_settings["address_prefix"]
+        dst_lan_prefixes = [
+            LANPrefixesDict(
+                lan=dst_match_criterion_ipv4_info["dst_lan"],
+                lan_tag=dst_match_criterion_ipv4_info["vlan"],
+            )
+        ]
+
+        return {
+            "uuid": service_id,
+            "src_device_name": src_device_name,
+            "src_endpoint_name": src_endpoint_name,
+            "src_site_location": src_endpoint_settings["site_location"],
+            "src_ipv4_lan_prefixes": src_lan_prefixes,
+            "src_ce_address": src_ce_ip,
+            "src_pe_address": src_ce_ip,
+            "src_ce_pe_network_prefix": src_ce_prefix,
+            "src_mtu": MTU,
+            "src_qos_profile_latency": qos_info["src_qos_profile_latency"],
+            "src_input_bw": qos_info["src_input_bw"],
+            "src_output_bw": qos_info["src_output_bw"],
+            "dst_device_name": dst_device_name,
+            "dst_endpoint_name": dst_endpoint_name,
+            "dst_site_location": dst_endpoint_settings["site_location"],
+            "dst_ipv4_lan_prefixes": dst_lan_prefixes,
+            "dst_ce_address": dst_ce_ip,
+            "dst_pe_address": dst_ce_ip,
+            "dst_ce_pe_network_prefix": dst_ce_prefix,
+            "dst_mtu": MTU,
+            "dst_qos_profile_latency": qos_info["dst_qos_profile_latency"],
+            "dst_input_bw": qos_info["dst_input_bw"],
+            "dst_output_bw": qos_info["dst_output_bw"],
+        }
+
+    @metered_subclass_method(METRICS_POOL)
+    def SetEndpoint(
+        self,
+        endpoints: List[Tuple[str, str, Optional[str]]],
+        connection_uuid: Optional[str] = None,
+    ) -> List[Union[bool, Exception]]:
+        chk_type("endpoints", endpoints, list)
+        if len(endpoints) < 2:
+            return []
+
+        results = []
+        service_config = self.__service.service_config
+
+        try:
+            # Identify IP transport edge endpoints
+            (
+                src_device_uuid,
+                src_endpoint_uuid,
+                dst_device_uuid,
+                dst_endpoint_uuid,
+                controller,
+            ) = self.__find_IP_transport_edge_endpoints(endpoints)
+
+            # Retrieve device objects
+            src_device_obj = self.__task_executor.get_device(
+                DeviceId(**json_device_id(src_device_uuid))
+            )
+            src_endpoint_obj = get_endpoint_matching(src_device_obj, src_endpoint_uuid)
+
+            dst_device_obj = self.__task_executor.get_device(
+                DeviceId(**json_device_id(dst_device_uuid))
+            )
+            dst_endpoint_obj = get_endpoint_matching(dst_device_obj, dst_endpoint_uuid)
+
+            # Obtain endpoint settings
+            src_endpoint_settings = get_endpoint_settings(
+                src_device_obj, src_endpoint_obj.name
+            )
+            dst_endpoint_settings = get_endpoint_settings(
+                dst_device_obj, dst_endpoint_obj.name
+            )
+
+            # Load running & candidate data, compute diff
+            running_data, candidate_data = load_json_rule_data(service_config)
+            running_candidate_diff = DeepDiff(running_data, candidate_data)
+
+            # Determine service_id and operation_type
+            slice_service = candidate_data["network-slice-services"]["slice-service"][0]
+            service_id = slice_service["id"]
+            if not running_candidate_diff:
+                operation_type = "create"
+            elif "values_changed" in running_candidate_diff:
+                operation_type = "update"
+
+            # Parse relevant connectivity data
+            sdps = slice_service["sdps"]["sdp"]
+            connection_group = slice_service["connection-groups"]["connection-group"][0]
+            connecitivity_constructs = connection_group["connectivity-construct"]
+
+            # The code below assumes a single connectivity construct or
+            # that the relevant one is the first in the list:
+            connecitivity_construct = connecitivity_constructs[0]
+            src_sdp_idx = connecitivity_construct["p2p-sender-sdp"]
+            dst_sdp_idx = connecitivity_construct["p2p-receiver-sdp"]
+
+            # QoS
+            qos_info = extract_qos_info_from_connection_group(
+                src_sdp_idx, dst_sdp_idx, connecitivity_constructs
+            )
+
+            # Retrieve match-criterion info
+            src_sdp = next(sdp for sdp in sdps if sdp["id"] == src_sdp_idx)
+            dst_sdp = next(sdp for sdp in sdps if sdp["id"] == dst_sdp_idx)
+
+            src_match_criterion = src_sdp["service-match-criteria"]["match-criterion"][
+                0
+            ]
+            dst_match_criterion = dst_sdp["service-match-criteria"]["match-criterion"][
+                0
+            ]
+            src_match_criterion_ipv4_info = extract_match_criterion_ipv4_info(
+                src_match_criterion
+            )
+            dst_match_criterion_ipv4_info = extract_match_criterion_ipv4_info(
+                dst_match_criterion
+            )
+
+            # Build resource dict & config rules
+            resource_value_dict = self.__build_resource_value_dict(
+                service_id=service_id,
+                src_device_obj=src_device_obj,
+                dst_device_obj=dst_device_obj,
+                src_endpoint_name=src_endpoint_obj.name,
+                dst_endpoint_name=dst_endpoint_obj.name,
+                qos_info=qos_info,
+                src_endpoint_settings=src_endpoint_settings,
+                dst_endpoint_settings=dst_endpoint_settings,
+                src_match_criterion_ipv4_info=src_match_criterion_ipv4_info,
+                dst_match_criterion_ipv4_info=dst_match_criterion_ipv4_info,
+            )
+            json_config_rules = setup_config_rules(
+                service_id, resource_value_dict, operation_type
+            )
+
+            # Configure device
+            del controller.device_config.config_rules[:]
+            for jcr in json_config_rules:
+                controller.device_config.config_rules.append(ConfigRule(**jcr))
+            self.__task_executor.configure_device(controller)
+        except Exception as e:  # pylint: disable=broad-except
+            LOGGER.exception(
+                "Unable to SetEndpoint for Service({:s})".format(str(service_id))
+            )
+            results.append(e)
+
+        return results
+
+    @metered_subclass_method(METRICS_POOL)
+    def DeleteEndpoint(
+        self,
+        endpoints: List[Tuple[str, str, Optional[str]]],
+        connection_uuid: Optional[str] = None,
+    ) -> List[Union[bool, Exception]]:
+        chk_type("endpoints", endpoints, list)
+        if len(endpoints) < 2:
+            return []
+        service_config = self.__service.service_config
+        ietf_slice_candidate_cr = get_custom_config_rule(
+            service_config, CANDIDATE_RESOURCE_KEY
+        )
+        candidate_resource_value_dict = json.loads(
+            ietf_slice_candidate_cr.custom.resource_value
+        )
+        service_id = candidate_resource_value_dict["network-slice-services"][
+            "slice-service"
+        ][0]["id"]
+        results = []
+        try:
+            src_device_uuid, _ = get_device_endpoint_uuids(endpoints[0])
+            src_device = self.__task_executor.get_device(
+                DeviceId(**json_device_id(src_device_uuid))
+            )
+            src_controller = self.__task_executor.get_device_controller(src_device)
+
+            dst_device_uuid, _ = get_device_endpoint_uuids(endpoints[1])
+            dst_device = self.__task_executor.get_device(
+                DeviceId(**json_device_id(dst_device_uuid))
+            )
+            dst_controller = self.__task_executor.get_device_controller(dst_device)
+            if (
+                src_controller.device_id.device_uuid.uuid
+                != dst_controller.device_id.device_uuid.uuid
+            ):
+                raise Exception("Different Src-Dst devices not supported by now")
+            controller = src_controller
+            json_config_rules = teardown_config_rules(service_id)
+            del controller.device_config.config_rules[:]
+            for jcr in json_config_rules:
+                controller.device_config.config_rules.append(ConfigRule(**jcr))
+            self.__task_executor.configure_device(controller)
+            results.append(True)
+        except Exception as e:  # pylint: disable=broad-except
+            LOGGER.exception(
+                "Unable to DeleteEndpoint for Service({:s})".format(str(service_id))
+            )
+            results.append(e)
+
+        return results
+
+    @metered_subclass_method(METRICS_POOL)
+    def SetConstraint(
+        self, constraints: List[Tuple[str, Any]]
+    ) -> List[Union[bool, Exception]]:
+        chk_type("constraints", constraints, list)
+        if len(constraints) == 0:
+            return []
+
+        msg = "[SetConstraint] Method not implemented. Constraints({:s}) are being ignored."
+        LOGGER.warning(msg.format(str(constraints)))
+        return [True for _ in range(len(constraints))]
+
+    @metered_subclass_method(METRICS_POOL)
+    def DeleteConstraint(
+        self, constraints: List[Tuple[str, Any]]
+    ) -> List[Union[bool, Exception]]:
+        chk_type("constraints", constraints, list)
+        if len(constraints) == 0:
+            return []
+
+        msg = "[DeleteConstraint] Method not implemented. Constraints({:s}) are being ignored."
+        LOGGER.warning(msg.format(str(constraints)))
+        return [True for _ in range(len(constraints))]
+
+    @metered_subclass_method(METRICS_POOL)
+    def SetConfig(
+        self, resources: List[Tuple[str, Any]]
+    ) -> List[Union[bool, Exception]]:
+        chk_type("resources", resources, list)
+        if len(resources) == 0:
+            return []
+
+        results = []
+        for resource in resources:
+            try:
+                resource_value = json.loads(resource[1])
+                self.__settings_handler.set(resource[0], resource_value)
+                results.append(True)
+            except Exception as e:  # pylint: disable=broad-except
+                LOGGER.exception("Unable to SetConfig({:s})".format(str(resource)))
+                results.append(e)
+
+        return results
+
+    @metered_subclass_method(METRICS_POOL)
+    def DeleteConfig(
+        self, resources: List[Tuple[str, Any]]
+    ) -> List[Union[bool, Exception]]:
+        chk_type("resources", resources, list)
+        if len(resources) == 0:
+            return []
+
+        results = []
+        for resource in resources:
+            try:
+                self.__settings_handler.delete(resource[0])
+            except Exception as e:  # pylint: disable=broad-except
+                LOGGER.exception("Unable to DeleteConfig({:s})".format(str(resource)))
+                results.append(e)
+
+        return results
diff --git a/src/service/service/service_handlers/l3nm_ietfl3vpn/__init__.py b/src/service/service/service_handlers/l3nm_ietfl3vpn/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..906dd19f3c948b03263251f60addb49e2fb522dc
--- /dev/null
+++ b/src/service/service/service_handlers/l3nm_ietfl3vpn/__init__.py
@@ -0,0 +1,14 @@
+# Copyright 2022-2025 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.
+
diff --git a/src/service/service/service_handlers/l3nm_nce/ConfigRules.py b/src/service/service/service_handlers/l3nm_nce/ConfigRules.py
new file mode 100644
index 0000000000000000000000000000000000000000..0544d897606afe950725349bfeb68c365189aa21
--- /dev/null
+++ b/src/service/service/service_handlers/l3nm_nce/ConfigRules.py
@@ -0,0 +1,120 @@
+# Copyright 2022-2025 ETSI 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
+
+from common.tools.object_factory.ConfigRule import (
+    json_config_rule_delete,
+    json_config_rule_set,
+)
+
+
+def setup_config_rules(service_uuid: str, json_settings: Dict) -> List[Dict]:
+    operation_type: str = json_settings["operation_type"]
+    app_flow_id: str = json_settings["app_flow_id"]
+    app_flow_user_id: str = json_settings["app_flow_user_id"]
+    max_latency: int = json_settings["max_latency"]
+    max_jitter: int = json_settings["max_jitter"]
+    max_loss: float = json_settings["max_loss"]
+    upstream_assure_bw: str = json_settings["upstream_assure_bw"]
+    upstream_max_bw: str = json_settings["upstream_max_bw"]
+    downstream_assure_bw: str = json_settings["downstream_assure_bw"]
+    downstream_max_bw: str = json_settings["downstream_max_bw"]
+    src_ip: str = json_settings["src_ip"]
+    src_port: str = json_settings["src_port"]
+    dst_ip: str = json_settings["dst_ip"]
+    dst_port: str = json_settings["dst_port"]
+
+    app_flow_app_name: str = f"App_Flow_{app_flow_id}"
+    app_flow_service_profile: str = f"service_{app_flow_id}"
+    app_id: str = f"app_{app_flow_id}"
+    app_feature_id: str = f"feature_{app_flow_id}"
+    app_flow_name: str = f"App_Flow_{app_flow_id}"
+    app_flow_max_online_users: int = json_settings.get("app_flow_max_online_users", 1)
+    app_flow_stas: str = json_settings.get("stas", "00:3D:E1:18:82:9E")
+    qos_profile_name: str = json_settings.get("app_flow_qos_profile", "AR_VR_Gaming")
+    app_flow_duration: int = json_settings.get("app_flow_duration", 9999)
+    protocol: str = json_settings.get("protocol", "tcp")
+
+    app_flow = {
+        "name": app_flow_name,
+        "user-id": app_flow_user_id,
+        "app-name": app_flow_app_name,
+        "max-online-users": app_flow_max_online_users,
+        "stas": app_flow_stas,
+        "qos-profile": qos_profile_name,
+        "service-profile": app_flow_service_profile,
+        "duration": app_flow_duration,
+    }
+    qos_profile = {
+        "name": qos_profile_name,
+        "max-latency": max_latency,
+        "max-jitter": max_jitter,
+        "max-loss": max_loss,
+        "upstream": {
+            "assure-bandwidth": upstream_assure_bw,
+            "max-bandwidth": upstream_max_bw,
+        },
+        "downstream": {
+            "assure-bandwidth": downstream_assure_bw,
+            "max-bandwidth": downstream_max_bw,
+        },
+    }
+    application = {
+        "name": app_flow_app_name,
+        "app-id": app_id,
+        "app-features": {
+            "app-feature": [
+                {
+                    "id": app_feature_id,
+                    "dest-ip": dst_ip,
+                    "dest-port": dst_port,
+                    "src-ip": src_ip,
+                    "src-port": src_port,
+                    "protocol": protocol,
+                }
+            ]
+        },
+    }
+    app_flow_datamodel = {
+        "huawei-nce-app-flow:app-flows": {
+            "app-flow": [app_flow],
+            "qos-profiles": {"qos-profile": [qos_profile]},
+            "applications": {"application": [application]},
+        }
+    }
+    json_config_rules = [
+        json_config_rule_set(
+            "/service[{:s}]/AppFlow".format(service_uuid), app_flow_datamodel
+        ),
+        json_config_rule_set(
+            "/service[{:s}]/AppFlow/operation".format(service_uuid),
+            {"type": operation_type},
+        ),
+    ]
+    return json_config_rules
+
+
+def teardown_config_rules(service_uuid: str, json_settings: Dict) -> List[Dict]:
+    json_config_rules = [
+        json_config_rule_delete(
+            "/service[{:s}]/AppFlow".format(service_uuid),
+            {},
+        ),
+        json_config_rule_delete(
+            "/service[{:s}]/AppFlow/operation".format(service_uuid),
+            {},
+        ),
+    ]
+    return json_config_rules
diff --git a/src/service/service/service_handlers/l3nm_nce/L3NMNCEServiceHandler.py b/src/service/service/service_handlers/l3nm_nce/L3NMNCEServiceHandler.py
new file mode 100644
index 0000000000000000000000000000000000000000..1317bd0615e4789d7ba76e8c0c6b0923d8f2dec7
--- /dev/null
+++ b/src/service/service/service_handlers/l3nm_nce/L3NMNCEServiceHandler.py
@@ -0,0 +1,564 @@
+# Copyright 2022-2025 ETSI 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
+import logging
+import re
+from typing import Any, List, Optional, Tuple, Union, TypedDict, Dict
+from uuid import uuid4
+
+from deepdiff import DeepDiff
+
+from common.method_wrappers.Decorator import MetricsPool, metered_subclass_method
+from common.proto.context_pb2 import ConfigRule, DeviceId, Empty, Service, ServiceConfig
+from common.tools.object_factory.Device import json_device_id
+from common.type_checkers.Checkers import chk_type
+from context.client.ContextClient import ContextClient
+from service.service.service_handler_api._ServiceHandler import _ServiceHandler
+from service.service.service_handler_api.SettingsHandler import SettingsHandler
+from service.service.service_handler_api.Tools import (
+    get_device_endpoint_uuids,
+)
+from service.service.task_scheduler.TaskExecutor import TaskExecutor
+
+from .ConfigRules import setup_config_rules, teardown_config_rules
+
+RUNNING_RESOURCE_KEY = "running_ietf_slice"
+CANDIDATE_RESOURCE_KEY = "candidate_ietf_slice"
+
+LOGGER = logging.getLogger(__name__)
+
+METRICS_POOL = MetricsPool("Service", "Handler", labels={"handler": "l3nm_nce"})
+
+SDP_DIFF_RE = re.compile(
+    r"^root\[\'network-slice-services\'\]\[\'slice-service\'\]\[0\]\[\'sdps\'\]\[\'sdp\'\]\[(\d)\]$"
+)
+CONNECTION_GROUP_DIFF_RE = re.compile(
+    r"^root\[\'network-slice-services\'\]\[\'slice-service\'\]\[0\]\[\'connection-groups\'\]\[\'connection-group\'\]\[(\d)\]$"
+)
+MATCH_CRITERION_DIFF_RE = re.compile(
+    r"^root\[\'network-slice-services\'\]\[\'slice-service\'\]\[0\]\[\'sdps\'\]\[\'sdp\'\]\[(\d)\]\[\'service-match-criteria\'\]\[\'match-criterion\'\]\[(\d)\]$"
+)
+
+
+class Ipv4Info(TypedDict):
+    src_ip: str
+    dst_ip: str
+    src_port: str
+    dst_port: str
+
+
+def get_removed_items(
+    candidate_ietf_slice_dict: dict, running_ietf_slice_dict: dict
+) -> dict:
+    """
+    For the 'iterable_item_removed' scenario, returns dict with removed sdp / connection_group / match_criterion info.
+    Raises an exception if there's inconsistent data or multiple items removed (which is not supported).
+    """
+    removed_items = {
+        "sdp": {"sdp_idx": None, "value": {}},
+        "connection_group": {"connection_group_idx": None, "value": {}},
+        "match_criterion": {
+            "sdp_idx": None,
+            "match_criterion_idx": None,
+            "value": {},
+        },
+    }
+
+    running_slice_services = running_ietf_slice_dict["network-slice-services"][
+        "slice-service"
+    ][0]
+    candidate_slice_services = candidate_ietf_slice_dict["network-slice-services"][
+        "slice-service"
+    ][0]
+
+    running_slice_sdps = [sdp["id"] for sdp in running_slice_services["sdps"]["sdp"]]
+    candidiate_slice_sdps = [
+        sdp["id"] for sdp in candidate_slice_services["sdps"]["sdp"]
+    ]
+    removed_sdps = set(running_slice_sdps) - set(candidiate_slice_sdps)
+
+    if len(removed_sdps) > 1:
+        raise Exception("Multiple SDPs removed - not supported.")
+    removed_sdp_id = removed_sdps.pop()
+
+    removed_items["sdp"]["sdp_idx"] = running_slice_sdps.index(removed_sdp_id)
+    removed_items["sdp"]["value"] = next(
+        sdp
+        for sdp in running_slice_services["sdps"]["sdp"]
+        if sdp["id"] == removed_sdp_id
+    )
+
+    match_criteria = removed_items["sdp"]["value"]["service-match-criteria"][
+        "match-criterion"
+    ]
+    if len(match_criteria) > 1:
+        raise Exception("Multiple match criteria found - not supported")
+    match_criterion = match_criteria[0]
+    connection_grp_id = match_criterion["target-connection-group-id"]
+    connection_groups = running_slice_services["connection-groups"]["connection-group"]
+    connection_group = next(
+        (idx, cg)
+        for idx, cg in enumerate(connection_groups)
+        if cg["id"] == connection_grp_id
+    )
+    removed_items["connection_group"]["connection_group_idx"] = connection_group[0]
+    removed_items["connection_group"]["value"] = connection_group[1]
+
+    for sdp in running_slice_services["sdps"]["sdp"]:
+        if sdp["id"] == removed_sdp_id:
+            continue
+        for mc in sdp["service-match-criteria"]["match-criterion"]:
+            if mc["target-connection-group-id"] == connection_grp_id:
+                removed_items["match_criterion"]["sdp_idx"] = running_slice_sdps.index(
+                    sdp["id"]
+                )
+                removed_items["match_criterion"]["match_criterion_idx"] = sdp[
+                    "service-match-criteria"
+                ]["match-criterion"].index(mc)
+                removed_items["match_criterion"]["value"] = mc
+                break
+
+    if (
+        removed_items["match_criterion"]["sdp_idx"] is None
+        or removed_items["sdp"]["sdp_idx"] is None
+        or removed_items["connection_group"]["connection_group_idx"] is None
+    ):
+        raise Exception("sdp, connection group or match criterion not found")
+
+    return removed_items
+
+
+def get_custom_config_rule(
+    service_config: ServiceConfig, resource_key: str
+) -> Optional[ConfigRule]:
+    """
+    Returns the ConfigRule from service_config matching the provided resource_key
+    if found, otherwise returns None.
+    """
+    for cr in service_config.config_rules:
+        if (
+            cr.WhichOneof("config_rule") == "custom"
+            and cr.custom.resource_key == resource_key
+        ):
+            return cr
+    return None
+
+
+def get_running_candidate_ietf_slice_data_diff(service_config: ServiceConfig) -> Dict:
+    """
+    Loads the JSON from the running/candidate resource ConfigRules and returns
+    their DeepDiff comparison.
+    """
+    running_cr = get_custom_config_rule(service_config, RUNNING_RESOURCE_KEY)
+    candidate_cr = get_custom_config_rule(service_config, CANDIDATE_RESOURCE_KEY)
+
+    running_value_dict = json.loads(running_cr.custom.resource_value)
+    candidate_value_dict = json.loads(candidate_cr.custom.resource_value)
+
+    return DeepDiff(running_value_dict, candidate_value_dict)
+
+
+def extract_qos_info(
+    connection_groups: List, connection_grp_id: str, src_sdp_idx: str, dst_sdp_idx: str
+) -> Dict:
+    """
+    Extract QoS information from connection groups based on the connection group ID.
+    """
+    qos_info = {
+        "upstream": {"max_delay": "0", "bw": "0", "packet_loss": "0"},
+        "downstream": {"max_delay": "0", "bw": "0", "packet_loss": "0"},
+    }
+    connection_group = next(
+        (cg for cg in connection_groups if cg["id"] == connection_grp_id), None
+    )
+
+    if not connection_group:
+        return qos_info
+
+    for cc in connection_group["connectivity-construct"]:
+        if (
+            cc["p2p-sender-sdp"] == src_sdp_idx
+            and cc["p2p-receiver-sdp"] == dst_sdp_idx
+        ):
+            direction = "upstream"
+        elif (
+            cc["p2p-sender-sdp"] == dst_sdp_idx
+            and cc["p2p-receiver-sdp"] == src_sdp_idx
+        ):
+            direction = "downstream"
+        else:
+            raise Exception("invalid sender and receiver sdp ids")
+        for metric_bound in cc["service-slo-sle-policy"]["slo-policy"]["metric-bound"]:
+            if (
+                metric_bound["metric-type"]
+                == "ietf-network-slice-service:one-way-delay-maximum"
+                and metric_bound["metric-unit"] == "milliseconds"
+            ):
+                qos_info[direction]["max_delay"] = metric_bound["bound"]
+            elif (
+                metric_bound["metric-type"]
+                == "ietf-network-slice-service:one-way-bandwidth"
+                and metric_bound["metric-unit"] == "Mbps"
+            ):
+                qos_info[direction]["bw"] = metric_bound["bound"]
+            elif (
+                metric_bound["metric-type"]
+                == "ietf-network-slice-service:two-way-packet-loss"
+                and metric_bound["metric-unit"] == "percentage"
+            ):
+                qos_info[direction]["packet_loss"] = metric_bound["percentile-value"]
+
+    return qos_info
+
+
+def extract_match_criterion_ipv4_info(match_criterion: Dict) -> Ipv4Info:
+    """
+    Extracts IPv4 info from the match criterion dictionary.
+    """
+    src_ip = dst_ip = src_port = dst_port = ""
+
+    for type_value in match_criterion["match-type"]:
+        m_type = type_value["type"]
+        val = type_value["value"][0]
+        if m_type == "ietf-network-slice-service:source-ip-prefix":
+            src_ip = val.split("/")[0]
+        elif m_type == "ietf-network-slice-service:destination-ip-prefix":
+            dst_ip = val.split("/")[0]
+        elif m_type == "ietf-network-slice-service:source-tcp-port":
+            src_port = val
+        elif m_type == "ietf-network-slice-service:destination-tcp-port":
+            dst_port = val
+
+    return Ipv4Info(
+        src_ip=src_ip,
+        dst_ip=dst_ip,
+        src_port=src_port,
+        dst_port=dst_port,
+    )
+
+
+class L3NMNCEServiceHandler(_ServiceHandler):
+    def __init__(  # pylint: disable=super-init-not-called
+        self, service: Service, task_executor: TaskExecutor, **settings
+    ) -> None:
+        self.__service = service
+        self.__task_executor = task_executor
+        self.__settings_handler = SettingsHandler(service.service_config, **settings)
+
+    @metered_subclass_method(METRICS_POOL)
+    def SetEndpoint(
+        self,
+        endpoints: List[Tuple[str, str, Optional[str]]],
+        connection_uuid: Optional[str] = None,
+    ) -> List[Union[bool, Exception]]:
+        chk_type("endpoints", endpoints, list)
+        if len(endpoints) == 0:
+            return []
+
+        results = []
+        try:
+            context_client = ContextClient()
+            service_config = self.__service.service_config
+            settings = self.__settings_handler.get("/settings")
+
+            src_device_uuid, src_endpoint_uuid = get_device_endpoint_uuids(endpoints[0])
+            src_device_obj = self.__task_executor.get_device(
+                DeviceId(**json_device_id(src_device_uuid))
+            )
+            controller = self.__task_executor.get_device_controller(src_device_obj)
+
+            list_devices = context_client.ListDevices(Empty())
+            devices = list_devices.devices
+            device_name_map = {d.name: d for d in devices}
+
+            running_candidate_diff = get_running_candidate_ietf_slice_data_diff(
+                service_config
+            )
+            candidate_ietf_slice_cr = get_custom_config_rule(
+                service_config, CANDIDATE_RESOURCE_KEY
+            )
+            candidate_resource_value_dict = json.loads(
+                candidate_ietf_slice_cr.custom.resource_value
+            )
+            running_ietf_slice_cr = get_custom_config_rule(
+                service_config, RUNNING_RESOURCE_KEY
+            )
+            running_resource_value_dict = json.loads(
+                running_ietf_slice_cr.custom.resource_value
+            )
+
+            service_name = running_resource_value_dict["network-slice-services"][
+                "slice-service"
+            ][0]["id"]
+
+            if not running_candidate_diff:  # Slice Creation
+                operation_type = "create"
+
+                slice_service = candidate_resource_value_dict["network-slice-services"][
+                    "slice-service"
+                ][0]
+                sdps = slice_service["sdps"]["sdp"]
+                connection_groups = slice_service["connection-groups"][
+                    "connection-group"
+                ]
+                sdp_ids = [sdp["id"] for sdp in sdps]
+                for sdp in sdps:
+                    node_id = sdp["node-id"]
+                    device_obj = device_name_map[node_id]
+                    device_controller = self.__task_executor.get_device_controller(
+                        device_obj
+                    )
+                    if (
+                        device_controller is None
+                        or controller.name != device_controller.name
+                    ):
+                        continue
+                    src_sdp_idx = sdp_ids.pop(sdp_ids.index(sdp["id"]))
+                    dst_sdp_idx = sdp_ids[0]
+                    match_criteria = sdp["service-match-criteria"]["match-criterion"]
+                    match_criterion = match_criteria[0]
+                    connection_grp_id = match_criterion["target-connection-group-id"]
+                    break
+                else:
+                    raise Exception("connection group id not found")
+            elif "iterable_item_added" in running_candidate_diff:  # new SDP added
+                operation_type = "create"
+
+                slice_service = candidate_resource_value_dict["network-slice-services"][
+                    "slice-service"
+                ][0]
+                sdps = slice_service["sdps"]["sdp"]
+                connection_groups = slice_service["connection-groups"][
+                    "connection-group"
+                ]
+                added_items = {
+                    "sdp": {"sdp_idx": None, "value": {}},
+                    "connection_group": {"connection_group_idx": None, "value": {}},
+                    "match_criterion": {
+                        "sdp_idx": None,
+                        "match_criterion_idx": None,
+                        "value": {},
+                    },
+                }
+                for added_key, added_value in running_candidate_diff[
+                    "iterable_item_added"
+                ].items():
+                    sdp_match = SDP_DIFF_RE.match(added_key)
+                    connection_group_match = CONNECTION_GROUP_DIFF_RE.match(added_key)
+                    match_criterion_match = MATCH_CRITERION_DIFF_RE.match(added_key)
+                    if sdp_match:
+                        added_items["sdp"] = {
+                            "sdp_idx": int(sdp_match.groups()[0]),
+                            "value": added_value,
+                        }
+                    elif connection_group_match:
+                        added_items["connection_group"] = {
+                            "connection_group_idx": int(
+                                connection_group_match.groups()[0]
+                            ),
+                            "value": added_value,
+                        }
+                    elif match_criterion_match:
+                        added_items["match_criterion"] = {
+                            "sdp_idx": int(match_criterion_match.groups()[0]),
+                            "match_criterion_idx": int(
+                                match_criterion_match.groups()[1]
+                            ),
+                            "value": added_value,
+                        }
+                new_sdp = sdps[added_items["sdp"]["sdp_idx"]]
+                src_sdp_idx = new_sdp["id"]
+                dst_sdp_idx = sdps[added_items["match_criterion"]["sdp_idx"]]["id"]
+                connection_grp_id = connection_groups[
+                    added_items["connection_group"]["connection_group_idx"]
+                ]["id"]
+
+                if (
+                    connection_grp_id
+                    != added_items["match_criterion"]["value"][
+                        "target-connection-group-id"
+                    ]
+                ):
+                    raise Exception(
+                        "connection group missmatch in destination sdp and added connection group"
+                    )
+                match_criteria = new_sdp["service-match-criteria"]["match-criterion"]
+                match_criterion = match_criteria[0]
+            elif "iterable_item_removed" in running_candidate_diff:  # new SDP added
+                operation_type = "delete"
+
+                slice_service = running_resource_value_dict["network-slice-services"][
+                    "slice-service"
+                ][0]
+                sdps = slice_service["sdps"]["sdp"]
+                connection_groups = slice_service["connection-groups"][
+                    "connection-group"
+                ]
+                removed_items = get_removed_items(
+                    candidate_resource_value_dict, running_resource_value_dict
+                )
+                removed_sdp = sdps[removed_items["sdp"]["sdp_idx"]]
+                src_sdp_idx = removed_sdp["id"]
+                dst_sdp_idx = sdps[removed_items["match_criterion"]["sdp_idx"]]["id"]
+                connection_grp_id = connection_groups[
+                    removed_items["connection_group"]["connection_group_idx"]
+                ]["id"]
+
+                if (
+                    connection_grp_id
+                    != removed_items["match_criterion"]["value"][
+                        "target-connection-group-id"
+                    ]
+                ):
+                    raise Exception(
+                        "connection group missmatch in destination sdp and added connection group"
+                    )
+                match_criteria = removed_sdp["service-match-criteria"][
+                    "match-criterion"
+                ]
+                match_criterion = match_criteria[0]
+            else:
+                raise Exception(
+                    "transition from candidate to running info not supported"
+                )
+
+            ip_info = extract_match_criterion_ipv4_info(match_criterion)
+
+            qos_info = extract_qos_info(
+                connection_groups, connection_grp_id, src_sdp_idx, dst_sdp_idx
+            )
+
+            resource_value_dict = {
+                "uuid": service_name,
+                "operation_type": operation_type,
+                "app_flow_id": f"{src_sdp_idx}_{dst_sdp_idx}_{service_name}",
+                "app_flow_user_id": str(uuid4()),
+                "max_latency": int(qos_info["upstream"]["max_delay"]),
+                "max_jitter": 10,
+                "max_loss": float(qos_info["upstream"]["packet_loss"]),
+                "upstream_assure_bw": int(qos_info["upstream"]["bw"]) * 1e6,
+                "upstream_max_bw": 2 * int(qos_info["upstream"]["bw"]) * 1e6,
+                "downstream_assure_bw": int(qos_info["downstream"]["bw"]) * 1e6,
+                "downstream_max_bw": 2 * int(qos_info["downstream"]["bw"]) * 1e6,
+                "src_ip": ip_info["src_ip"],
+                "src_port": ip_info["src_port"],
+                "dst_ip": ip_info["dst_ip"],
+                "dst_port": ip_info["dst_port"],
+            }
+            json_config_rules = setup_config_rules(service_name, resource_value_dict)
+
+            del controller.device_config.config_rules[:]
+            for jcr in json_config_rules:
+                controller.device_config.config_rules.append(ConfigRule(**jcr))
+
+            self.__task_executor.configure_device(controller)
+            LOGGER.debug('Configured device "{:s}"'.format(controller.name))
+
+        except Exception as e:  # pylint: disable=broad-except
+            results.append(e)
+
+        return results
+
+    @metered_subclass_method(METRICS_POOL)
+    def DeleteEndpoint(
+        self,
+        endpoints: List[Tuple[str, str, Optional[str]]],
+        connection_uuid: Optional[str] = None,
+    ) -> List[Union[bool, Exception]]:
+        chk_type("endpoints", endpoints, list)
+        if len(endpoints) == 0:
+            return []
+        service_uuid = self.__service.service_id.service_uuid.uuid
+        results = []
+        try:
+            src_device_uuid, src_endpoint_uuid = get_device_endpoint_uuids(endpoints[0])
+            src_device_obj = self.__task_executor.get_device(
+                DeviceId(**json_device_id(src_device_uuid))
+            )
+            controller = self.__task_executor.get_device_controller(src_device_obj)
+            json_config_rules = teardown_config_rules(service_uuid, {})
+            if len(json_config_rules) > 0:
+                del controller.device_config.config_rules[:]
+                for json_config_rule in json_config_rules:
+                    controller.device_config.config_rules.append(
+                        ConfigRule(**json_config_rule)
+                    )
+                self.__task_executor.configure_device(controller)
+            results.append(True)
+        except Exception as e:  # pylint: disable=broad-except
+            results.append(e)
+        return results
+
+    @metered_subclass_method(METRICS_POOL)
+    def SetConstraint(
+        self, constraints: List[Tuple[str, Any]]
+    ) -> List[Union[bool, Exception]]:
+        chk_type("constraints", constraints, list)
+        if len(constraints) == 0:
+            return []
+
+        msg = "[SetConstraint] Method not implemented. Constraints({:s}) are being ignored."
+        LOGGER.warning(msg.format(str(constraints)))
+        return [True for _ in range(len(constraints))]
+
+    @metered_subclass_method(METRICS_POOL)
+    def DeleteConstraint(
+        self, constraints: List[Tuple[str, Any]]
+    ) -> List[Union[bool, Exception]]:
+        chk_type("constraints", constraints, list)
+        if len(constraints) == 0:
+            return []
+
+        msg = "[DeleteConstraint] Method not implemented. Constraints({:s}) are being ignored."
+        LOGGER.warning(msg.format(str(constraints)))
+        return [True for _ in range(len(constraints))]
+
+    @metered_subclass_method(METRICS_POOL)
+    def SetConfig(
+        self, resources: List[Tuple[str, Any]]
+    ) -> List[Union[bool, Exception]]:
+        chk_type("resources", resources, list)
+        if len(resources) == 0:
+            return []
+
+        results = []
+        for resource in resources:
+            try:
+                resource_value = json.loads(resource[1])
+                self.__settings_handler.set(resource[0], resource_value)
+                results.append(True)
+            except Exception as e:  # pylint: disable=broad-except
+                LOGGER.exception("Unable to SetConfig({:s})".format(str(resource)))
+                results.append(e)
+
+        return results
+
+    @metered_subclass_method(METRICS_POOL)
+    def DeleteConfig(
+        self, resources: List[Tuple[str, Any]]
+    ) -> List[Union[bool, Exception]]:
+        chk_type("resources", resources, list)
+        if len(resources) == 0:
+            return []
+
+        results = []
+        for resource in resources:
+            try:
+                self.__settings_handler.delete(resource[0])
+            except Exception as e:  # pylint: disable=broad-except
+                LOGGER.exception("Unable to DeleteConfig({:s})".format(str(resource)))
+                results.append(e)
+
+        return results
diff --git a/src/service/service/service_handlers/l3nm_nce/__init__.py b/src/service/service/service_handlers/l3nm_nce/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..3ccc21c7db78aac26daa1f8c5ff8e1ffd3f35460
--- /dev/null
+++ b/src/service/service/service_handlers/l3nm_nce/__init__.py
@@ -0,0 +1,14 @@
+# Copyright 2022-2025 ETSI 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.
+
diff --git a/src/telemetry/backend/collector_api/_Collector.py b/src/telemetry/backend/collector_api/_Collector.py
new file mode 100644
index 0000000000000000000000000000000000000000..ec4ba943c90de8a8d683d1e7a9dd9d48865b5edf
--- /dev/null
+++ b/src/telemetry/backend/collector_api/_Collector.py
@@ -0,0 +1,236 @@
+# Copyright 2022-2024 ETSI 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 threading
+from typing import Any, Iterator, List, Optional, Tuple, Union
+
+# Special resource names to request to the collector to retrieve the specified
+# configuration/structural resources.
+# These resource names should be used with GetConfig() method.
+RESOURCE_ENDPOINTS = '__endpoints__'
+RESOURCE_INTERFACES = '__interfaces__'
+RESOURCE_NETWORK_INSTANCES = '__network_instances__'
+RESOURCE_ROUTING_POLICIES = '__routing_policies__'
+RESOURCE_SERVICES = '__services__'
+RESOURCE_ACL = '__acl__'
+RESOURCE_INVENTORY = '__inventory__'
+
+
+class _Collector:
+    def __init__(self, name : str, address: str, port: int, **settings) -> None:
+        """ Initialize Collector.
+            Parameters:
+                address : str
+                    The address of the device
+                port : int
+                    The port of the device
+                **settings
+                    Extra settings required by the collector.
+        """
+        self._name = name
+        self._address = address
+        self._port = port
+        self._settings = settings
+
+    @property
+    def name(self): return self._name
+
+    @property
+    def address(self): return self._address
+
+    @property
+    def port(self): return self._port
+
+    @property
+    def settings(self): return self._settings
+
+    def Connect(self) -> bool:
+        """ Connect to the Device.
+            Returns:
+                succeeded : bool
+                    Boolean variable indicating if connection succeeded.
+        """
+        raise NotImplementedError()
+
+    def Disconnect(self) -> bool:
+        """ Disconnect from the Device.
+            Returns:
+                succeeded : bool
+                    Boolean variable indicating if disconnection succeeded.
+        """
+        raise NotImplementedError()
+
+    def GetInitialConfig(self) -> List[Tuple[str, Any]]:
+        """ Retrieve initial configuration of entire device.
+            Returns:
+                values : List[Tuple[str, Any]]
+                    List of tuples (resource key, resource value) for
+                    resource keys.
+        """
+        raise NotImplementedError()
+
+    def GetConfig(self, resource_keys: List[str] = []) -> \
+            List[Tuple[str, Union[Any, None, Exception]]]:
+        """ Retrieve running configuration of entire device or
+        selected resource keys.
+            Parameters:
+                resource_keys : List[str]
+                    List of keys pointing to the resources to be retrieved.
+            Returns:
+                values : List[Tuple[str, Union[Any, None, Exception]]]
+                    List of tuples (resource key, resource value) for
+                    resource keys requested. If a resource is found,
+                    the appropriate value type must be retrieved.
+                    If a resource is not found, None must be retrieved as
+                    value for that resource. In case of Exception,
+                    the Exception must be retrieved as value.
+        """
+        raise NotImplementedError()
+
+    def SetConfig(self, resources: List[Tuple[str, Any]]) -> \
+            List[Union[bool, Exception]]:
+        """ Create/Update configuration for a list of resources.
+            Parameters:
+                resources : List[Tuple[str, Any]]
+                    List of tuples, each containing a resource_key pointing the
+                    resource to be modified, and a resource_value containing
+                    the new value to be set.
+            Returns:
+                results : List[Union[bool, Exception]]
+                    List of results for resource key changes requested.
+                    Return values must be in the same order as the
+                    resource keys requested. If a resource is properly set,
+                    True must be retrieved; otherwise, the Exception that is
+                    raised during the processing must be retrieved.
+        """
+        raise NotImplementedError()
+
+    def DeleteConfig(self, resources: List[Tuple[str, Any]]) -> \
+            List[Union[bool, Exception]]:
+        """ Delete configuration for a list of resources.
+            Parameters:
+                resources : List[Tuple[str, Any]]
+                    List of tuples, each containing a resource_key pointing the
+                    resource to be modified, and a resource_value containing
+                    possible additionally required values to locate
+                    the value to be removed.
+            Returns:
+                results : List[Union[bool, Exception]]
+                    List of results for resource key deletions requested.
+                    Return values must be in the same order as the resource keys
+                    requested. If a resource is properly deleted, True must be
+                    retrieved; otherwise, the Exception that is raised during
+                    the processing must be retrieved.
+        """
+        raise NotImplementedError()
+
+    def SubscribeState(self, subscriptions: List[Tuple[str, float, float]]) -> \
+            List[Union[bool, Exception]]:
+        """ Subscribe to state information of entire device or
+        selected resources. Subscriptions are incremental.
+            Collector should keep track of requested resources.
+            Parameters:
+                subscriptions : List[Tuple[str, float, float]]
+                    List of tuples, each containing a resource_key pointing the
+                    resource to be subscribed, a sampling_duration, and a
+                    sampling_interval (both in seconds with float
+                    representation) defining, respectively, for how long
+                    monitoring should last, and the desired monitoring interval
+                    for the resource specified.
+            Returns:
+                results : List[Union[bool, Exception]]
+                    List of results for resource key subscriptions requested.
+                    Return values must be in the same order as the resource keys
+                    requested. If a resource is properly subscribed,
+                    True must be retrieved; otherwise, the Exception that is
+                    raised during the processing must be retrieved.
+        """
+        raise NotImplementedError()
+
+    def UnsubscribeState(self, subscriptions: List[Tuple[str, float, float]]) \
+            -> List[Union[bool, Exception]]:
+        """ Unsubscribe from state information of entire device
+        or selected resources. Subscriptions are incremental.
+            Collector should keep track of requested resources.
+            Parameters:
+                subscriptions : List[str]
+                    List of tuples, each containing a resource_key pointing the
+                    resource to be subscribed, a sampling_duration, and a
+                    sampling_interval (both in seconds with float
+                    representation) defining, respectively, for how long
+                    monitoring should last, and the desired monitoring interval
+                    for the resource specified.
+            Returns:
+                results : List[Union[bool, Exception]]
+                    List of results for resource key un-subscriptions requested.
+                    Return values must be in the same order as the resource keys
+                    requested. If a resource is properly unsubscribed,
+                    True must be retrieved; otherwise, the Exception that is
+                    raised during the processing must be retrieved.
+        """
+        raise NotImplementedError()
+
+    def GetState(
+        self, blocking=False, terminate : Optional[threading.Event] = None
+    ) -> Iterator[Tuple[float, str, Any]]:
+        """ Retrieve last collected values for subscribed resources.
+        Operates as a generator, so this method should be called once and will
+        block until values are available. When values are available,
+        it should yield each of them and block again until new values are
+        available. When the collector is destroyed, GetState() can return instead
+        of yield to terminate the loop.
+        Terminate enables to request interruption of the generation.
+            Examples:
+                # keep looping waiting for extra samples (generator loop)
+                terminate = threading.Event()
+                i = 0
+                for timestamp,resource_key,resource_value in my_collector.GetState(blocking=True, terminate=terminate):
+                    process(timestamp, resource_key, resource_value)
+                    i += 1
+                    if i == 10: terminate.set()
+
+                # just retrieve accumulated samples
+                samples = my_collector.GetState(blocking=False, terminate=terminate)
+                # or (as classical loop)
+                i = 0
+                for timestamp,resource_key,resource_value in my_collector.GetState(blocking=False, terminate=terminate):
+                    process(timestamp, resource_key, resource_value)
+                    i += 1
+                    if i == 10: terminate.set()
+            Parameters:
+                blocking : bool
+                    Select the collector behaviour. In both cases, the collector will
+                    first retrieve the samples accumulated and available in the
+                    internal queue. Then, if blocking, the collector does not
+                    terminate the loop and waits for additional samples to come,
+                    thus behaving as a generator. If non-blocking, the collector
+                    terminates the loop and returns. Non-blocking behaviour can
+                    be used for periodically polling the collector, while blocking
+                    can be used when a separate thread is in charge of
+                    collecting the samples produced by the collector.
+                terminate : threading.Event
+                    Signals the interruption of the GetState method as soon as
+                    possible.
+            Returns:
+                results : Iterator[Tuple[float, str, Any]]
+                    Sequences of state sample. Each State sample contains a
+                    float Unix-like timestamps of the samples in seconds with up
+                    to microsecond resolution, the resource_key of the sample,
+                    and its resource_value.
+                    Only resources with an active subscription must be
+                    retrieved. Interval and duration of the sampling process are
+                    specified when creating the subscription using method
+                    SubscribeState(). Order of values yielded is arbitrary.
+        """
+        raise NotImplementedError()
diff --git a/src/telemetry/backend/collector_api/__init__.py b/src/telemetry/backend/collector_api/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..023830645e0fcb60e3f8583674a954810af222f2
--- /dev/null
+++ b/src/telemetry/backend/collector_api/__init__.py
@@ -0,0 +1,13 @@
+# Copyright 2022-2024 ETSI 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.
diff --git a/src/telemetry/backend/collectors/__init__.py b/src/telemetry/backend/collectors/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..023830645e0fcb60e3f8583674a954810af222f2
--- /dev/null
+++ b/src/telemetry/backend/collectors/__init__.py
@@ -0,0 +1,13 @@
+# Copyright 2022-2024 ETSI 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.
diff --git a/src/telemetry/backend/collectors/emulated/EmulatedCollector.py b/src/telemetry/backend/collectors/emulated/EmulatedCollector.py
new file mode 100644
index 0000000000000000000000000000000000000000..90be013368c5aa80dcb52c2394e8b74f9d74b6f4
--- /dev/null
+++ b/src/telemetry/backend/collectors/emulated/EmulatedCollector.py
@@ -0,0 +1,450 @@
+# Copyright 2022-2024 ETSI 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 pytz
+import queue
+import logging
+import uuid
+import json
+from anytree import Node, Resolver
+from apscheduler.events import EVENT_JOB_ADDED, EVENT_JOB_REMOVED
+from apscheduler.schedulers.background import BackgroundScheduler
+from apscheduler.jobstores.memory import MemoryJobStore
+from apscheduler.executors.pool import ThreadPoolExecutor
+from datetime import datetime, timedelta
+from typing import Any, Iterator, List, Tuple, Union, Optional
+from telemetry.backend.collector_api._Collector import _Collector
+from .EmulatedHelper import EmulatedCollectorHelper
+from .SyntheticMetricsGenerator import SyntheticMetricsGenerator
+
+
+class EmulatedCollector(_Collector):
+    """
+    EmulatedCollector is a class that simulates a network collector for testing purposes.
+    It provides functionalities to manage configurations, state subscriptions, and synthetic data generation.
+    """
+    def __init__(self, address: str, port: int, **settings):
+        super().__init__('emulated_collector', address, port, **settings)
+        self._initial_config = Node('root')                 # Tree structure for initial config
+        self._running_config = Node('root')                 # Tree structure for running config
+        self._subscriptions  = Node('subscriptions')        # Tree for state subscriptions
+        self._resolver       = Resolver()                   # For path resolution in tree structures
+        self._out_samples    = queue.Queue()                # Queue to hold synthetic state samples
+        self._synthetic_data = SyntheticMetricsGenerator(metric_queue=self._out_samples)  # Placeholder for synthetic data generator
+        self._scheduler      = BackgroundScheduler(daemon=True)
+        self._scheduler.configure(
+            jobstores = {'default': MemoryJobStore()},
+            executors = {'default': ThreadPoolExecutor(max_workers=1)},
+            timezone  = pytz.utc
+        )
+        self._scheduler.add_listener(self._listener_job_added_to_subscription_tree,     EVENT_JOB_ADDED)
+        self._scheduler.add_listener(self._listener_job_removed_from_subscription_tree, EVENT_JOB_REMOVED)
+        self._helper_methods = EmulatedCollectorHelper()
+
+        self.logger    = logging.getLogger(__name__)
+        self.connected = False          # To track connection state
+        self.logger.info("EmulatedCollector initialized")
+
+    def Connect(self) -> bool:
+        self.logger.info(f"Connecting to {self.address}:{self.port}")
+        self.connected = True
+        self._scheduler.start()
+        self.logger.info(f"Successfully connected to {self.address}:{self.port}")
+        return True
+
+    def Disconnect(self) -> bool:
+        self.logger.info(f"Disconnecting from {self.address}:{self.port}")
+        if not self.connected:
+            self.logger.warning("Collector is not connected. Nothing to disconnect.")
+            return False
+        self._scheduler.shutdown()
+        self.connected = False
+        self.logger.info(f"Successfully disconnected from {self.address}:{self.port}")
+        return True
+
+    def _require_connection(self):
+        if not self.connected:
+            raise RuntimeError("Collector is not connected. Please connect before performing operations.")
+
+    def SubscribeState(self, subscriptions: List[Tuple[str, float, float]]) -> List[Union[bool, Exception]]:
+        self._require_connection()
+        results = []
+        for resource_key, duration, interval in subscriptions:
+            resource_key = self._helper_methods.validate_resource_key(resource_key)    # Validate the endpoint name
+            self.logger.info(f"1. Subscribing to {resource_key} with duration {duration}s and interval {interval}s")
+            try:
+                self._resolver.get(self._running_config, resource_key)   # Verify if the resource key exists in the running configuration
+                self.logger.info(f"Resource key {resource_key} exists in the configuration.")
+                resource_value = json.loads(self._resolver.get(self._running_config, resource_key).value) 
+                if resource_value is not None:
+                    sample_type_ids = resource_value['sample_types']
+                    self.logger.info(f"Sample type IDs for {resource_key}: {sample_type_ids}")
+                    if len(sample_type_ids) == 0:
+                        self.logger.warning(f"No sample types found for {resource_key}. Skipping subscription.")
+                        results.append(False)
+                        continue
+                else:
+                    self.logger.warning(f"No sample types found for {resource_key}. Skipping subscription.")
+                    results.append(False)
+                    continue
+                # Add the job to the scheduler
+                job_id = f"{resource_key}-{uuid.uuid4()}"
+                self._scheduler.add_job(
+                    self._generate_sample,
+                    'interval',
+                    seconds=interval,
+                    args=[resource_key, sample_type_ids],
+                    id=job_id,
+                    replace_existing=True,
+                    end_date=datetime.now(pytz.utc) + timedelta(seconds=duration)
+                )
+                self.logger.info(f"Job added to scheduler for resource key {resource_key} with duration {duration}s and interval {interval}s")
+                results.append(True)
+            except Exception as e:
+                self.logger.error(f"Failed to verify resource key or add job: {e}")
+                results.append(e)
+        return results
+
+    def UnsubscribeState(self, subscriptions: List[Tuple[str, float, float]]) -> List[Union[bool, Exception]]:
+        self._require_connection()
+        results = []
+        for resource_key, _, _ in subscriptions:
+            resource_key = self._helper_methods.validate_resource_key(resource_key)
+            try:
+                # Check if job exists
+                job_ids = [job.id for job in self._scheduler.get_jobs() if resource_key in job.id]
+                if not job_ids:
+                    self.logger.warning(f"No active jobs found for {resource_key}. It might have already terminated.")
+                    results.append(False)
+                    continue
+                # Remove jobs
+                for job_id in job_ids:
+                    self._scheduler.remove_job(job_id)
+                
+                self.logger.info(f"Unsubscribed from {resource_key} with job IDs: {job_ids}")
+                results.append(True)
+            except Exception as e:
+                self.logger.exception(f"Failed to unsubscribe from {resource_key}")
+                results.append(e)
+        return results
+
+    def GetState(self, blocking: bool = False, terminate: Optional[queue.Queue] = None) -> Iterator[Tuple[float, str, Any]]:
+        self._require_connection()
+        start_time = datetime.now(pytz.utc)
+        duration = 10  # Duration of the subscription in seconds (as an example)
+
+        while True:
+            try:
+                if terminate and not terminate.empty():
+                    self.logger.info("Termination signal received, stopping GetState")
+                    break
+
+                elapsed_time = (datetime.now(pytz.utc) - start_time).total_seconds()
+                if elapsed_time >= duration:
+                    self.logger.info("Duration expired, stopping GetState")
+                    break
+
+                sample = self._out_samples.get(block=blocking, timeout=1 if blocking else 0.1)
+                self.logger.info(f"Retrieved state sample: {sample}")
+                yield sample
+            except queue.Empty:
+                if not blocking:
+                    self.logger.info("No more samples in queue, exiting GetState")
+                    return None
+
+    def _generate_sample(self, resource_key: str, sample_type_ids : List[int]):
+        # Simulate generating a sample for the resource key
+        self.logger.debug(f"Executing _generate_sample for resource: {resource_key}")
+        sample = self._synthetic_data.generate_synthetic_data_point(resource_key, sample_type_ids)
+        self._out_samples.put(sample)
+
+# ------------- Event Listeners (START)-----------------
+
+    def _listener_job_removed_from_subscription_tree(self, event):
+        if event.job_id:
+            # Extract the resource key from the job ID
+            resource_key = event.job_id.split('-')[0]
+            resource_key = self._helper_methods.validate_resource_key(resource_key)
+            
+            # Remove the subscription from the tree
+            try:
+                subscription_path = resource_key.split('/')
+                parent = self._subscriptions
+                for part in subscription_path:
+                    parent = next((child for child in parent.children if child.name == part), None)
+                    if not parent:
+                        raise ValueError(f"Subscription path '{resource_key}' not found in tree.")
+                if parent:
+                    parent.parent.children = tuple(child for child in parent.parent.children if child != parent)
+                    self.logger.warning(f"Automatically removed subscription from subscription_tree for {resource_key} after job termination by listener. Maybe due to timeout.")
+            except Exception as e:
+                self.logger.warning(f"Failed to remove subscription for {resource_key}: {e}")
+
+    def _listener_job_added_to_subscription_tree(self, event):
+        try:
+            job_id = event.job_id
+            if job_id:
+                resource_key = job_id.split('-')[0]  # Extract resource key from job ID
+                resource_key = self._helper_methods.validate_resource_key(resource_key)
+                subscription_path = resource_key.split('/')
+                parent = self._subscriptions
+                for part in subscription_path:
+                    node = next((child for child in parent.children if child.name == part), None)
+                    if not node:
+                        node = Node(part, parent=parent)
+                    parent = node
+                parent.value = {
+                    "job_id": job_id
+                }
+                self.logger.info(f"Automatically added subscription for {resource_key} to the subscription_tree by listener.")
+        except Exception as e:
+            self.logger.exception("Failed to add subscription to the tree")
+
+# ------------- Event Listeners (END)-----------------
+
+#-------------------------------------------------------------------------------------
+# ------- The below methods are kept for debugging purposes (test-case) only ---------
+#-------------------------------------------------------------------------------------
+
+#  This method can be commented but this will arise an error in the test-case (@pytest.fixture --> connected_configured_collector()).
+    def SetConfig(self, resources: dict) -> List[Union[bool, Exception]]:  # For debugging purposes.
+        self._require_connection()
+        results = []
+
+        # if not isinstance(resources, dict):
+        #     self.logger.error("Invalid configuration format: resources must be a dictionary.")
+        #     raise ValueError("Invalid configuration format. Must be a dictionary.")
+        if 'config_rules' not in resources or not isinstance(resources['config_rules'], list):
+            self.logger.error("Invalid configuration format: 'config_rules' key missing or not a list.")
+            raise ValueError("Invalid configuration format. Must contain a 'config_rules' key with a list of rules.")
+
+        for rule in resources['config_rules']:
+            try:
+                if 'action' not in rule or 'custom' not in rule:
+                    raise ValueError(f"Invalid rule format: {rule}")
+
+                action = rule['action']
+                custom = rule['custom']
+                resource_key = custom.get('resource_key')
+                resource_value = custom.get('resource_value')
+
+                if not resource_key:
+                    raise ValueError(f"Resource key is missing in rule: {rule}")
+
+                if resource_value is None:
+                    raise ValueError(f"Resource value is None for key: {resource_key}")
+                if not resource_key:
+                    raise ValueError(f"Resource key is missing in rule: {rule}")
+
+                if action == 1:  # Set action
+                    resource_path = self._helper_methods._parse_resource_key(resource_key)
+                    # self.logger.info(f"1. Setting configuration for resource key {resource_key} and resource_path: {resource_path}")
+                    parent = self._running_config
+
+                    for part in resource_path[:-1]:
+                        if '[' in part and ']' in part:
+                            base, index = part.split('[', 1)
+                            index = index.rstrip(']')
+                            parent = self._helper_methods._find_or_create_node(index, self._helper_methods._find_or_create_node(base, parent))
+                            # self.logger.info(f"2a. Creating node: {base}, {index}, {parent}")
+                        elif resource_path[-1] != 'settings':
+                            # self.logger.info(f"2b. Creating node: {part}")
+                            parent = self._helper_methods._find_or_create_node(part, parent)
+
+                    final_part = resource_path[-1]
+                    if final_part in ['address', 'port']: 
+                        self._helper_methods._create_or_update_node(final_part, parent, resource_value)
+                        self.logger.info(f"Configured: {resource_key} = {resource_value}")
+
+                    if resource_key.startswith("_connect/settings"):
+                        parent = self._helper_methods._find_or_create_node("_connect", self._running_config)
+                        settings_node = self._helper_methods._find_or_create_node("settings", parent)
+                        settings_node.value = None  # Ensure settings node has None value
+                        endpoints_node = self._helper_methods._find_or_create_node("endpoints", settings_node)
+
+                        for endpoint in resource_value.get("endpoints", []):
+                            uuid = endpoint.get("uuid")
+                            uuid = uuid.replace('/', '_') if uuid else None
+                            if uuid:
+                                # self.logger.info(f"3. Creating endpoint: {uuid}, {endpoint}, {endpoints_node}")
+                                self._helper_methods._create_or_update_node(uuid, endpoints_node, endpoint)
+                                self.logger.info(f"Configured endpoint: {uuid} : {endpoint}")
+
+                    elif resource_key.startswith("/interface"):
+                        interface_parent = self._helper_methods._find_or_create_node("interface", self._running_config)
+                        name = resource_value.get("name")
+                        name = name.replace('/', '_') if name else None
+                        if name:
+                            self._helper_methods._create_or_update_node(name, interface_parent, resource_value)
+                            self.logger.info(f"Configured interface: {name} : {resource_value}")
+                            # self.logger.info(f"4. Configured interface: {name}")
+
+                    results.append(True)
+                else:
+                    raise ValueError(f"Unsupported action '{action}' in rule: {rule}")
+
+                if resource_value is None:
+                    raise ValueError(f"Resource value is None for key: {resource_key}")
+
+            except Exception as e:
+                self.logger.exception(f"Failed to apply rule: {rule}")
+                results.append(e)
+
+        return results
+
+#-----------------------------------
+# ------- EXTRA Methods ------------
+#-----------------------------------
+
+    # def log_active_jobs(self):              # For debugging purposes.
+    #     """
+    #     Logs the IDs of all active jobs.
+    #     This method retrieves the list of active jobs from the scheduler and logs their IDs using the logger.
+    #     """
+    #     self._require_connection()
+    #     jobs = self._scheduler.get_jobs()
+    #     self.logger.info(f"Active jobs: {[job.id for job in jobs]}")
+
+    # def print_config_tree(self):            # For debugging purposes.
+    #     """
+    #     Reads the configuration using GetConfig and prints it as a hierarchical tree structure.
+    #     """
+    #     self._require_connection()
+
+    #     def print_tree(node, indent=""):
+    #         """
+    #         Recursively prints the configuration tree.
+
+    #         Args:
+    #             node (Node): The current node to print.
+    #             indent (str): The current indentation level.
+    #         """
+    #         if node.name != "root":  # Skip the root node's name
+    #             value = getattr(node, "value", None)
+    #             print(f"{indent}- {node.name}: {json.loads(value) if value else ''}")
+            
+    #         for child in node.children:
+    #             print_tree(child, indent + "  ")
+
+    #     print("Configuration Tree:")
+    #     print_tree(self._running_config)
+
+
+    # def GetInitialConfig(self) -> List[Tuple[str, Any]]:    # comment
+    #     self._require_connection()
+    #     results = []
+    #     for node in self._initial_config.descendants:
+    #         value = getattr(node, "value", None)
+    #         results.append((node.name, json.loads(value) if value else None))
+    #     self.logger.info("Retrieved initial configurations")
+    #     return results
+
+    # def GetConfig(self, resource_keys: List[str] = []) -> List[Tuple[str, Union[Any, dict, Exception]]]:    # comment
+    #     """
+    #     Retrieves the configuration for the specified resource keys.
+    #     If no keys are provided, returns the full configuration tree.
+
+    #     Args:
+    #         resource_keys (List[str]): A list of keys specifying the configuration to retrieve.
+            
+    #     Returns:
+    #         List[Tuple[str, Union[Any, dict, Exception]]]: A list of tuples with the resource key and its value, 
+    #                                                     subtree, or an exception.
+    #     """
+    #     self._require_connection()
+    #     results = []
+
+    #     try:
+    #         if not resource_keys:
+    #             # If no specific keys are provided, return the full configuration tree
+
+    #             full_tree = self._helper_methods._generate_subtree(self._running_config)
+    #             # full_tree = self._generate_subtree(self._running_config)
+    #             return [("full_configuration", full_tree)]
+
+    #         for key in resource_keys:
+    #             try:
+    #                 # Parse the resource key
+    #                 resource_path = self._helper_methods.(key)
+    #                 self.logger.info(f"1. Retrieving configuration for resource path : {resource_path}")
+
+    #                 # Navigate to the node corresponding to the key
+    #                 parent = self._running_config
+    #                 for part in resource_path:
+    #                     parent = self._find_or_raise_node(part, parent)
+
+    #                 # Check if the node has a value
+    #                 value = getattr(parent, "value", None)
+    #                 if value:
+    #                     # If a value exists, return it
+    #                     results.append((key, json.loads(value)))
+    #                 else:
+    #                     # If no value, return the subtree of this node
+    #                     subtree = self._helper_methods._generate_subtree(parent)
+    #                     # subtree = self._generate_subtree(parent)
+    #                     results.append((key, subtree))
+
+    #             except Exception as e:
+    #                 self.logger.exception(f"Failed to retrieve configuration for key: {key}")
+    #                 results.append((key, e))
+
+    #     except Exception as e:
+    #         self.logger.exception("Failed to retrieve configurations")
+    #         results.append(("Error", e))
+
+    #     return results
+
+    # def DeleteConfig(self, resources: List[Tuple[str, Any]]) -> List[Union[bool, Exception]]: # comment
+    #     self._require_connection()
+    #     results = []
+
+    #     for key in resources:
+    #         try:
+    #             # Parse resource key into parts, handling brackets correctly
+    #             resource_path = self._helper_methods.(key)
+
+    #             parent = self._running_config
+    #             for part in resource_path:
+    #                 parent = self._find_or_raise_node(part, parent)
+
+    #             # Delete the final node
+    #             node_to_delete = parent
+    #             parent = node_to_delete.parent
+    #             parent.children = tuple(child for child in parent.children if child != node_to_delete)
+    #             self.logger.info(f"Deleted configuration for key: {key}")
+
+    #             # Handle endpoints structure
+    #             if "interface" in key and "settings" in key:
+    #                 interface_name = key.split('[')[-1].split(']')[0]
+    #                 endpoints_parent = self._find_or_raise_node("_connect", self._running_config)
+    #                 endpoints_node = self._find_or_raise_node("endpoints", endpoints_parent)
+    #                 endpoint_to_delete = next((child for child in endpoints_node.children if child.name == interface_name), None)
+    #                 if endpoint_to_delete:
+    #                     endpoints_node.children = tuple(child for child in endpoints_node.children if child != endpoint_to_delete)
+    #                     self.logger.info(f"Removed endpoint entry for interface '{interface_name}'")
+
+    #             # Check if parent has no more children and is not the root
+    #             while parent and parent.name != "root" and not parent.children:
+    #                 node_to_delete = parent
+    #                 parent = node_to_delete.parent
+    #                 parent.children = tuple(child for child in parent.children if child != node_to_delete)
+    #                 self.logger.info(f"Deleted empty parent node: {node_to_delete.name}")
+
+    #             results.append(True)
+    #         except Exception as e:
+    #             self.logger.exception(f"Failed to delete configuration for key: {key}")
+    #             results.append(e)
+
+    #     return results
+
diff --git a/src/telemetry/backend/collectors/emulated/EmulatedHelper.py b/src/telemetry/backend/collectors/emulated/EmulatedHelper.py
new file mode 100644
index 0000000000000000000000000000000000000000..ebfb7d49fdb7ceafa00986e763e56dd59e445609
--- /dev/null
+++ b/src/telemetry/backend/collectors/emulated/EmulatedHelper.py
@@ -0,0 +1,166 @@
+# Copyright 2022-2024 ETSI 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 anytree import Node
+import json
+from typing import Any, List
+
+
+class EmulatedCollectorHelper:
+    """
+    Helper class for the emulated collector.
+    """
+    def __init__(self):
+        pass
+
+    def validate_resource_key(self, key: str) -> str:
+        """
+        Splits the input string into two parts: 
+        - The first part is '_connect/settings/endpoints/'.
+        - The second part is the remaining string after the first part, with '/' replaced by '_'.
+        
+        Args:
+            key (str): The input string to process.
+            
+        Returns:
+            str: A single string with the processed result.
+        """
+        prefix = '_connect/settings/endpoints/'
+        if not key.startswith(prefix):
+            raise ValueError(f"The input path '{key}' does not start with the expected prefix: {prefix}")
+        second_part = key[len(prefix):]
+        second_part_processed = second_part.replace('/', '_')
+        validated_key = prefix + second_part_processed
+        return validated_key
+
+#--------------------------------------------------------------------------------------
+# ------- Below function is kept for debugging purposes (test-cases) only -------------
+#--------------------------------------------------------------------------------------
+
+#  This below methods can be commented but are called by the SetConfig method in EmulatedCollector.py
+
+    def _find_or_create_node(self, name: str, parent: Node) -> Node:
+        """
+        Finds or creates a node with the given name under the specified parent.
+
+        Args:
+            name (str): The name of the node to find or create.
+            parent (Node): The parent node.
+
+        Returns:
+            Node: The found or created node.
+        """
+        node = next((child for child in parent.children if child.name == name), None)
+        if not node:
+            node = Node(name, parent=parent)
+        return node
+
+
+    def _create_or_update_node(self, name: str, parent: Node, value: Any):
+        """
+        Creates or updates a node with the given name and value under the specified parent.
+
+        Args:
+            name (str): The name of the node.
+            parent (Node): The parent node.
+            value (Any): The value to set on the node.
+        """
+        node = next((child for child in parent.children if child.name == name), None)
+        if node:
+            node.value = json.dumps(value)
+        else:
+            Node(name, parent=parent, value=json.dumps(value))
+
+
+    def _parse_resource_key(self, resource_key: str) -> List[str]:
+        """
+        Parses the resource key into parts, correctly handling brackets.
+
+        Args:
+            resource_key (str): The resource key to parse.
+
+        Returns:
+            List[str]: A list of parts from the resource key.
+        """
+        resource_path = []
+        current_part = ""
+        in_brackets = False
+
+        if not resource_key.startswith('/interface'):
+            for char in resource_key.strip('/'):
+                if char == '[':
+                    in_brackets = True
+                    current_part += char
+                elif char == ']':
+                    in_brackets = False
+                    current_part += char
+                elif char == '/' and not in_brackets:
+                    resource_path.append(current_part)
+                    current_part = ""
+                else:
+                    current_part += char
+            if current_part:
+                resource_path.append(current_part)
+            return resource_path
+        else:
+            resource_path = resource_key.strip('/').split('/', 1)
+            if resource_path[1] == 'settings':
+                return resource_path
+            else:
+                resource_path = [resource_key.strip('/').split('[')[0].strip('/'), resource_key.strip('/').split('[')[1].split(']')[0].replace('/', '_')]
+                return resource_path
+
+
+#-----------------------------------
+# ------- EXTRA Methods ------------
+#-----------------------------------
+
+    # def _generate_subtree(self, node: Node) -> dict:
+    #     """
+    #     Generates a subtree of the configuration tree starting from the specified node.
+
+    #     Args:
+    #         node (Node): The node from which to generate the subtree.
+
+    #     Returns:
+    #         dict: The subtree as a dictionary.
+    #     """
+    #     subtree = {}
+    #     for child in node.children:
+    #         if child.children:
+    #             subtree[child.name] = self._generate_subtree(child)
+    #         else:
+    #             value = getattr(child, "value", None)
+    #             subtree[child.name] = json.loads(value) if value else None
+    #     return subtree
+
+
+    # def _find_or_raise_node(self, name: str, parent: Node) -> Node:
+    #     """
+    #     Finds a node with the given name under the specified parent or raises an exception if not found.
+
+    #     Args:
+    #         name (str): The name of the node to find.
+    #         parent (Node): The parent node.
+
+    #     Returns:
+    #         Node: The found node.
+
+    #     Raises:
+    #         ValueError: If the node is not found.
+    #     """
+    #     node = next((child for child in parent.children if child.name == name), None)
+    #     if not node:
+    #         raise ValueError(f"Node '{name}' not found under parent '{parent.name}'.")
+    #     return node
diff --git a/src/telemetry/backend/collectors/emulated/SyntheticMetricsGenerator.py b/src/telemetry/backend/collectors/emulated/SyntheticMetricsGenerator.py
new file mode 100644
index 0000000000000000000000000000000000000000..a01e2c0e659f1eea6383030daeafef11c83d7a45
--- /dev/null
+++ b/src/telemetry/backend/collectors/emulated/SyntheticMetricsGenerator.py
@@ -0,0 +1,129 @@
+# Copyright 2022-2024 ETSI 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 numpy as np
+import random
+import logging
+import queue
+import time
+
+LOGGER = logging.getLogger(__name__)
+
+class SyntheticMetricsGenerator():
+    """
+    This collector class generates synthetic network metrics based on the current network state.
+    The metrics include packet_in, packet_out, bytes_in, bytes_out, packet_loss (percentage), packet_drop_count, byte_drop_count, and latency.
+    The network state can be 'good', 'moderate', or 'poor', and it affects the generated metrics accordingly.
+    """
+    def __init__(self, metric_queue=None, network_state="good"):
+        LOGGER.info("Initiaitng Emulator")
+        super().__init__()
+        self.metric_queue        = metric_queue if metric_queue is not None else queue.Queue()
+        self.network_state       = network_state
+        self.running             = True
+        self.set_initial_parameter_values()  # update this method to set the initial values for the parameters
+
+    def set_initial_parameter_values(self):
+        self.bytes_per_pkt       = random.uniform(65, 150)
+        self.states              = ["good", "moderate", "poor"]
+        self.state_probabilities = {
+            "good"    : [0.9, 0.1, 0.0],
+            "moderate": [0.2, 0.7, 0.1],
+            "poor"    : [0.0, 0.3, 0.7]
+        }
+        if self.network_state   == "good":
+            self.packet_in = random.uniform(700, 900)
+        elif self.network_state == "moderate":
+            self.packet_in = random.uniform(300, 700)
+        else:
+            self.packet_in = random.uniform(100, 300)
+
+    def generate_synthetic_data_point(self, resource_key, sample_type_ids):
+        """
+        Generates a synthetic data point based on the current network state.
+
+        Parameters:
+        resource_key (str): The key associated with the resource for which the data point is generated.
+
+        Returns:
+        tuple: A tuple containing the timestamp, resource key, and a dictionary of generated metrics.
+        """
+        if self.network_state   == "good":
+            packet_loss  = random.uniform(0.01, 0.1)  
+            random_noise = random.uniform(1,10)
+            latency      = random.uniform(5, 25)
+        elif self.network_state == "moderate":
+            packet_loss  = random.uniform(0.1, 1)
+            random_noise = random.uniform(10, 40)
+            latency      = random.uniform(25, 100)
+        elif self.network_state == "poor":
+            packet_loss  = random.uniform(1, 3)
+            random_noise = random.uniform(40, 100)
+            latency      = random.uniform(100, 300)
+        else:
+            raise ValueError("Invalid network state. Must be 'good', 'moderate', or 'poor'.")
+
+        period            = 60 * 60 * random.uniform(10, 100)
+        amplitude         = random.uniform(50, 100) 
+        sin_wave          = amplitude  * np.sin(2 * np.pi   * 100 / period) + self.packet_in
+        packet_in         = sin_wave   + ((sin_wave/100)    * random_noise)
+        packet_out        = packet_in  - ((packet_in / 100) * packet_loss)
+        bytes_in          = packet_in  * self.bytes_per_pkt
+        bytes_out         = packet_out * self.bytes_per_pkt
+        packet_drop_count = packet_in  * (packet_loss / 100)
+        byte_drop_count   = packet_drop_count * self.bytes_per_pkt
+
+        state_prob = self.state_probabilities[self.network_state]
+        self.network_state = random.choices(self.states, state_prob)[0]
+        print (self.network_state)
+
+        generated_samples = {
+            "packet_in" : int(packet_in),   "packet_out" : int(packet_out),    "bytes_in"          : float(bytes_in),
+            "bytes_out" : float(bytes_out), "packet_loss": float(packet_loss), "packet_drop_count" : int(packet_drop_count),
+            "latency"   : float(latency),   "byte_drop_count": float(byte_drop_count)
+        }
+        requested_metrics = self.metric_id_mapper(sample_type_ids, generated_samples)
+        # generated_samples = {metric: generated_samples[metric] for metric in requested_metrics}
+
+        return (time.time(), resource_key, requested_metrics)
+
+    def metric_id_mapper(self, sample_type_ids, metric_dict):
+        """
+        Maps the sample type IDs to the corresponding metric names.
+
+        Parameters:
+        sample_type_ids (list): A list of sample type IDs.
+
+        Returns:
+        list: A list of metric names.
+        """
+        metric_names = []
+        for sample_type_id in sample_type_ids:
+            if sample_type_id == 102:
+                metric_names.append(metric_dict["packet_in"])
+            elif sample_type_id == 101:
+                metric_names.append(metric_dict["packet_out"])
+            elif sample_type_id == 103:
+                metric_names.append(metric_dict["packet_drop_count"])
+            elif sample_type_id == 202:
+                metric_names.append(metric_dict["bytes_in"])
+            elif sample_type_id == 201:
+                metric_names.append(metric_dict["bytes_out"])
+            elif sample_type_id == 203:
+                metric_names.append(metric_dict["byte_drop_count"])
+            elif sample_type_id == 701:
+                metric_names.append(metric_dict["latency"])
+            else:
+                raise ValueError(f"Invalid sample type ID: {sample_type_id}")
+        return metric_names
diff --git a/src/telemetry/backend/collectors/emulated/__init__.py b/src/telemetry/backend/collectors/emulated/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..023830645e0fcb60e3f8583674a954810af222f2
--- /dev/null
+++ b/src/telemetry/backend/collectors/emulated/__init__.py
@@ -0,0 +1,13 @@
+# Copyright 2022-2024 ETSI 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.
diff --git a/src/telemetry/backend/requirements.in b/src/telemetry/backend/requirements.in
index effd1752af0d1a2d00312ff4935676c24964c784..2843bdbf68defcc1a972b49bfa12a8107b696aaa 100644
--- a/src/telemetry/backend/requirements.in
+++ b/src/telemetry/backend/requirements.in
@@ -12,4 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+anytree==2.8.0
 confluent-kafka==2.3.*
+numpy==2.0.1
+APScheduler==3.10.1
diff --git a/src/telemetry/backend/service/TelemetryBackendService.py b/src/telemetry/backend/service/TelemetryBackendService.py
index fe5792a023a926d41a71b0dc7614d7e2b093507b..a1f17df3cb65a6bd13ffb8e96a6a07b536200825 100755
--- a/src/telemetry/backend/service/TelemetryBackendService.py
+++ b/src/telemetry/backend/service/TelemetryBackendService.py
@@ -12,21 +12,20 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import queue
 import json
 import time
-import random
 import logging
 import threading
-from typing   import Any, Dict
-from datetime import datetime, timezone
-# from common.proto.context_pb2 import Empty
-from confluent_kafka import Producer as KafkaProducer
-from confluent_kafka import Consumer as KafkaConsumer
-from confluent_kafka import KafkaError
+from typing           import Any, Dict
+from datetime         import datetime, timezone
+from confluent_kafka  import Producer as KafkaProducer
+from confluent_kafka  import Consumer as KafkaConsumer
+from confluent_kafka  import KafkaError
 from common.Constants import ServiceNameEnum
-from common.Settings import get_service_port_grpc
-from common.tools.kafka.Variables import KafkaConfig, KafkaTopic
-from common.method_wrappers.Decorator import MetricsPool
+from common.Settings  import get_service_port_grpc
+from common.method_wrappers.Decorator        import MetricsPool
+from common.tools.kafka.Variables            import KafkaConfig, KafkaTopic
 from common.tools.service.GenericGrpcService import GenericGrpcService
 
 LOGGER             = logging.getLogger(__name__)
@@ -35,7 +34,7 @@ METRICS_POOL       = MetricsPool('TelemetryBackend', 'backendService')
 class TelemetryBackendService(GenericGrpcService):
     """
     Class listens for request on Kafka topic, fetches requested metrics from device.
-    Produces metrics on both RESPONSE and VALUE kafka topics.
+    Produces metrics on both TELEMETRY_RESPONSE and VALUE kafka topics.
     """
     def __init__(self, cls_name : str = __name__) -> None:
         LOGGER.info('Init TelemetryBackendService')
@@ -45,7 +44,9 @@ class TelemetryBackendService(GenericGrpcService):
         self.kafka_consumer = KafkaConsumer({'bootstrap.servers' : KafkaConfig.get_kafka_address(),
                                             'group.id'           : 'backend',
                                             'auto.offset.reset'  : 'latest'})
-        self.running_threads = {}
+        self.running_threads   = {}
+        self.emulatorCollector = None
+        self.metric_queue      = queue.Queue()
 
     def install_servicers(self):
         threading.Thread(target=self.RequestListener).start()
@@ -57,7 +58,7 @@ class TelemetryBackendService(GenericGrpcService):
         LOGGER.info('Telemetry backend request listener is running ...')
         # print      ('Telemetry backend request listener is running ...')
         consumer = self.kafka_consumer
-        consumer.subscribe([KafkaTopic.REQUEST.value])
+        consumer.subscribe([KafkaTopic.TELEMETRY_REQUEST.value])
         while True:
             receive_msg = consumer.poll(2.0)
             if receive_msg is None:
@@ -66,93 +67,83 @@ class TelemetryBackendService(GenericGrpcService):
                 if receive_msg.error().code() == KafkaError._PARTITION_EOF:
                     continue
                 else:
-                    # print("Consumer error: {}".format(receive_msg.error()))
+                    LOGGER.error("Consumer error: {}".format(receive_msg.error()))
                     break
             try: 
                 collector = json.loads(receive_msg.value().decode('utf-8'))
                 collector_id = receive_msg.key().decode('utf-8')
                 LOGGER.debug('Recevied Collector: {:} - {:}'.format(collector_id, collector))
-                # print('Recevied Collector: {:} - {:}'.format(collector_id, collector))
 
                 if collector['duration'] == -1 and collector['interval'] == -1:
                     self.TerminateCollectorBackend(collector_id)
                 else:
-                    self.RunInitiateCollectorBackend(collector_id, collector)
+                    threading.Thread(target=self.InitiateCollectorBackend, 
+                                  args=(collector_id, collector)).start()
             except Exception as e:
-                LOGGER.warning("Unable to consumer message from topic: {:}. ERROR: {:}".format(KafkaTopic.REQUEST.value, e))
-                # print         ("Unable to consumer message from topic: {:}. ERROR: {:}".format(KafkaTopic.REQUEST.value, e))
+                LOGGER.warning("Unable to consumer message from topic: {:}. ERROR: {:}".format(KafkaTopic.TELEMETRY_REQUEST.value, e))
 
-    def TerminateCollectorBackend(self, collector_id):
-        if collector_id in self.running_threads:
-            thread, stop_event = self.running_threads[collector_id]
-            stop_event.set()
-            thread.join()
-            # print ("Terminating backend (by StopCollector): Collector Id: ", collector_id)
-            del self.running_threads[collector_id]
-            self.GenerateCollectorTerminationSignal(collector_id, "-1", -1)          # Termination confirmation to frontend.
-        else:
-            # print ('Backend collector {:} not found'.format(collector_id))
-            LOGGER.warning('Backend collector {:} not found'.format(collector_id))
-
-    def RunInitiateCollectorBackend(self, collector_id: str, collector: str):
-        stop_event = threading.Event()
-        thread = threading.Thread(target=self.InitiateCollectorBackend, 
-                                  args=(collector_id, collector, stop_event))
-        self.running_threads[collector_id] = (thread, stop_event)
-        thread.start()
-
-    def InitiateCollectorBackend(self, collector_id, collector, stop_event):
+    def InitiateCollectorBackend(self, collector_id, collector):
         """
         Method receives collector request and initiates collecter backend.
         """
-        # print("Initiating backend for collector: ", collector_id)
-        LOGGER.info("Initiating backend for collector: {:s}".format(str(collector_id)))
-        start_time = time.time()
-        while not stop_event.is_set():
-            if int(collector['duration']) != -1 and time.time() - start_time >= collector['duration']:            # condition to terminate backend
-                print("Execuation duration completed: Terminating backend: Collector Id: ", collector_id, " - ", time.time() - start_time)
-                self.GenerateCollectorTerminationSignal(collector_id, "-1", -1)       # Termination confirmation to frontend.
-                break
-            self.ExtractKpiValue(collector_id, collector['kpi_id'])
-            time.sleep(collector['interval'])
+        LOGGER.info("Initiating backend for collector: (Not Implemented... In progress ) {:s}".format(str(collector_id)))
+        # start_time = time.time()
+        # self.emulatorCollector = NetworkMetricsEmulator(
+        #     duration           = collector['duration'],
+        #     interval           = collector['interval'],
+        #     metric_queue       = self.metric_queue
+        # )
+        # self.emulatorCollector.start()
+        # self.running_threads[collector_id] = self.emulatorCollector
 
-    def GenerateCollectorTerminationSignal(self, collector_id: str, kpi_id: str, measured_kpi_value: Any):
+        # while self.emulatorCollector.is_alive():
+        #     if not self.metric_queue.empty():
+        #         metric_value = self.metric_queue.get()
+        #         LOGGER.debug("Metric: {:} - Value : {:}".format(collector['kpi_id'], metric_value))
+        #         self.GenerateKpiValue(collector_id, collector['kpi_id'] , metric_value)
+        #     time.sleep(1)
+        # self.TerminateCollectorBackend(collector_id)
+
+    def GenerateKpiValue(self, collector_id: str, kpi_id: str, measured_kpi_value: Any):
         """
-        Method to write kpi Termination signat on RESPONSE Kafka topic
+        Method to write kpi value on VALUE Kafka topic
         """
         producer = self.kafka_producer
         kpi_value : Dict = {
+            "time_stamp": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"),
             "kpi_id"    : kpi_id,
-            "kpi_value" : measured_kpi_value,
+            "kpi_value" : measured_kpi_value
         }
         producer.produce(
-            KafkaTopic.RESPONSE.value, # TODO: to  the topic ...
+            KafkaTopic.VALUE.value,
             key      = collector_id,
             value    = json.dumps(kpi_value),
             callback = self.delivery_callback
         )
         producer.flush()
 
-    def ExtractKpiValue(self, collector_id: str, kpi_id: str):
-        """
-        Method to extract kpi value.
-        """
-        measured_kpi_value = random.randint(1,100)                      # TODO: To be extracted from a device
-        # print ("Measured Kpi value: {:}".format(measured_kpi_value))
-        self.GenerateCollectorResponse(collector_id, kpi_id , measured_kpi_value)
+    def TerminateCollectorBackend(self, collector_id):
+        LOGGER.debug("Terminating collector backend...")
+        if collector_id in self.running_threads:
+            thread = self.running_threads[collector_id]
+            thread.stop()
+            del self.running_threads[collector_id]
+            LOGGER.debug("Collector backend terminated. Collector ID: {:}".format(collector_id))
+            self.GenerateCollectorTerminationSignal(collector_id, "-1", -1)          # Termination confirmation to frontend.
+        else:
+            LOGGER.warning('Backend collector {:} not found'.format(collector_id))
 
-    def GenerateCollectorResponse(self, collector_id: str, kpi_id: str, measured_kpi_value: Any):
+    def GenerateCollectorTerminationSignal(self, collector_id: str, kpi_id: str, measured_kpi_value: Any):
         """
-        Method to write kpi value on RESPONSE Kafka topic
+        Method to write kpi Termination signat on TELEMETRY_RESPONSE Kafka topic
         """
         producer = self.kafka_producer
         kpi_value : Dict = {
-            "time_stamp": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"),
             "kpi_id"    : kpi_id,
-            "kpi_value" : measured_kpi_value
+            "kpi_value" : measured_kpi_value,
         }
         producer.produce(
-            KafkaTopic.VALUE.value, # TODO: to  the topic ...
+            KafkaTopic.TELEMETRY_RESPONSE.value,
             key      = collector_id,
             value    = json.dumps(kpi_value),
             callback = self.delivery_callback
@@ -160,14 +151,9 @@ class TelemetryBackendService(GenericGrpcService):
         producer.flush()
 
     def delivery_callback(self, err, msg):
-        """
-        Callback function to handle message delivery status.
-        Args: err (KafkaError): Kafka error object.
-              msg (Message): Kafka message object.
-        """
-        if err:
-            LOGGER.error('Message delivery failed: {:}'.format(err))
+        if err: 
+            LOGGER.error('Message delivery failed: {:s}'.format(str(err)))
             # print(f'Message delivery failed: {err}')
-        #else:
-        #    LOGGER.debug('Message delivered to topic {:}'.format(msg.topic()))
-        #    # print(f'Message delivered to topic {msg.topic()}')
+        # else:
+        #     LOGGER.info('Message delivered to topic {:}'.format(msg.topic()))
+            # print(f'Message delivered to topic {msg.topic()}')
diff --git a/src/telemetry/backend/tests/messages.py b/src/telemetry/backend/tests/messages.py
index 0dc5506ab42d67d67a88cf8976409472213fe098..f6a2bb247f28d10654746e0c75b6ed1973382e38 100644
--- a/src/telemetry/backend/tests/messages.py
+++ b/src/telemetry/backend/tests/messages.py
@@ -12,4 +12,20 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+import uuid
+import random
+from common.proto import telemetry_frontend_pb2
+# from common.proto.kpi_sample_types_pb2 import KpiSampleType
+# from common.proto.kpi_manager_pb2 import KpiId
+
+def create_collector_request():
+    _create_collector_request                                = telemetry_frontend_pb2.Collector()
+    _create_collector_request.collector_id.collector_id.uuid = str(uuid.uuid4()) 
+    # _create_collector_request.collector_id.collector_id.uuid = "efef4d95-1cf1-43c4-9742-95c283dddddd"
+    _create_collector_request.kpi_id.kpi_id.uuid             = str(uuid.uuid4())
+    # _create_collector_request.kpi_id.kpi_id.uuid             = "6e22f180-ba28-4641-b190-2287bf448888"
+    _create_collector_request.duration_s                     = float(random.randint(8, 16))
+    # _create_collector_request.duration_s                     = -1
+    _create_collector_request.interval_s                     = float(random.randint(2, 4)) 
+    return _create_collector_request
 
diff --git a/src/telemetry/backend/tests/messages_emulated.py b/src/telemetry/backend/tests/messages_emulated.py
new file mode 100644
index 0000000000000000000000000000000000000000..e081fb3febc163d40742d3e690cc0e2b3d4b7d61
--- /dev/null
+++ b/src/telemetry/backend/tests/messages_emulated.py
@@ -0,0 +1,61 @@
+# Copyright 2022-2024 ETSI 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 logging
+# Configure logging to ensure logs appear on the console
+logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
+logger = logging.getLogger(__name__)
+
+
+def create_test_configuration():
+    return {
+            "config_rules": [
+                {"action": 1, "custom": {"resource_key": "_connect/address", "resource_value": "127.0.0.1"}},
+                {"action": 1, "custom": {"resource_key": "_connect/port", "resource_value": 8080}},
+                {"action": 1, "custom": {"resource_key": "_connect/settings", "resource_value": {
+                    "endpoints": [
+                        {"uuid": "eth0",   "type": "ethernet", "sample_types": [101, 102]},
+                        {"uuid": "eth1",   "type": "ethernet", "sample_types": []},
+                        {"uuid": "13/1/2", "type": "copper",   "sample_types": [101, 102, 201, 202]}
+                    ]
+                }}},
+                {"action": 1, "custom": {"resource_key": "/interface[eth0]/settings", "resource_value": {
+                    "name": "eth0", "enabled": True
+                }}},
+                {"action": 1, "custom": {"resource_key": "/interface[eth1]/settings", "resource_value": {
+                    "name": "eth1", "enabled": False
+                }}},
+                {"action": 1, "custom": {"resource_key": "/interface[13/1/2]/settings", "resource_value": {
+                    "name": "13/1/2", "enabled": True
+                }}}
+            ]
+        }
+
+def create_specific_config_keys():
+    keys_to_return = ["_connect/settings/endpoints/eth1", "/interface/[13/1/2]/settings", "_connect/address"]
+    return keys_to_return
+
+def create_config_for_delete():
+    keys_to_delete = ["_connect/settings/endpoints/eth0", "/interface/[eth1]", "_connect/port"]
+    return keys_to_delete
+
+def create_test_subscriptions():
+    return [("_connect/settings/endpoints/eth1",   10, 2),
+            ("_connect/settings/endpoints/13/1/2", 15, 3),
+            ("_connect/settings/endpoints/eth0",   8,  2)]
+
+def create_unscubscribe_subscriptions():
+    return [("_connect/settings/endpoints/eth1",   10, 2),
+            ("_connect/settings/endpoints/13/1/2", 15, 3),
+            ("_connect/settings/endpoints/eth0",   8,  2)]
diff --git a/src/telemetry/backend/tests/test_backend.py b/src/telemetry/backend/tests/test_backend.py
index 5307cd9fe51f3bb15f5dd4915bfc601318db9551..e75b33ca58c6bf27c5d2e1c2012dc31de5274ad3 100644
--- a/src/telemetry/backend/tests/test_backend.py
+++ b/src/telemetry/backend/tests/test_backend.py
@@ -13,10 +13,11 @@
 # limitations under the License.
 
 import logging
-import threading
+import time
+from typing import Dict
 from common.tools.kafka.Variables import KafkaTopic
 from telemetry.backend.service.TelemetryBackendService import TelemetryBackendService
-
+from .messages import create_collector_request
 
 LOGGER = logging.getLogger(__name__)
 
@@ -34,4 +35,19 @@ def test_validate_kafka_topics():
 # def test_RunRequestListener():
 #     LOGGER.info('test_RunRequestListener')
 #     TelemetryBackendServiceObj = TelemetryBackendService()
-#     threading.Thread(target=TelemetryBackendServiceObj.RequestListener).start()
\ No newline at end of file
+#     threading.Thread(target=TelemetryBackendServiceObj.RequestListener).start()
+
+def test_RunInitiateCollectorBackend():
+    LOGGER.debug(">>> RunInitiateCollectorBackend <<<")
+    collector_obj = create_collector_request()
+    collector_id = collector_obj.collector_id.collector_id.uuid
+    collector_dict :  Dict = {
+        "kpi_id"  : collector_obj.kpi_id.kpi_id.uuid,
+        "duration": collector_obj.duration_s,
+        "interval": collector_obj.interval_s
+    }
+    TeleObj = TelemetryBackendService()
+    TeleObj.InitiateCollectorBackend(collector_id, collector_dict)
+    time.sleep(20)
+
+    LOGGER.debug("--- Execution Finished Sucessfully---")
diff --git a/src/telemetry/backend/tests/test_emulated.py b/src/telemetry/backend/tests/test_emulated.py
new file mode 100644
index 0000000000000000000000000000000000000000..feb5b1f7f92de4016f3bcb8eff8e17b843bf0c3e
--- /dev/null
+++ b/src/telemetry/backend/tests/test_emulated.py
@@ -0,0 +1,108 @@
+# Copyright 2022-2024 ETSI 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 logging
+import time
+import pytest
+from telemetry.backend.collectors.emulated.EmulatedCollector import EmulatedCollector
+from telemetry.backend.tests.messages_emulated import (
+    create_test_configuration,
+    create_specific_config_keys,
+    create_config_for_delete,
+    create_test_subscriptions,
+)
+
+logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
+logger = logging.getLogger(__name__)
+
+@pytest.fixture
+def setup_collector():
+    """Sets up an EmulatedCollector instance for testing."""
+    yield EmulatedCollector(address="127.0.0.1", port=8080)
+
+@pytest.fixture
+def connected_configured_collector(setup_collector):
+    collector = setup_collector # EmulatedCollector(address="127.0.0.1", port=8080)
+    collector.Connect()
+    collector.SetConfig(create_test_configuration())
+    yield collector
+    collector.Disconnect()
+
+def test_connect(setup_collector):
+    logger.info(">>> test_connect <<<")
+    collector = setup_collector
+    assert collector.Connect() is True
+    assert collector.connected is True
+
+def test_disconnect(setup_collector):
+    logger.info(">>> test_disconnect <<<")
+    collector = setup_collector
+    collector.Connect()
+    assert collector.Disconnect() is True
+    assert collector.connected is False
+
+# def test_set_config(setup_collector):
+#     logger.info(">>> test_set_config <<<")
+#     collector = setup_collector
+#     collector.Connect()
+
+#     config = create_test_configuration()
+
+#     results = collector.SetConfig(config)
+#     assert all(result is True for result in results)
+
+# def test_get_config(connected_configured_collector):
+#     logger.info(">>> test_get_config <<<")
+#     resource_keys = create_specific_config_keys() 
+#     results = connected_configured_collector.GetConfig(resource_keys)
+
+#     for key, value in results:
+#         assert key in create_specific_config_keys()
+#         assert value is not None
+
+# def test_delete_config(connected_configured_collector):
+#     logger.info(">>> test_delete_config <<<")
+#     resource_keys = create_config_for_delete() 
+
+#     results = connected_configured_collector.DeleteConfig(resource_keys)
+#     assert all(result is True for result in results)
+
+def test_subscribe_state(connected_configured_collector):
+    logger.info(">>> test_subscribe_state <<<")
+    subscriptions = create_test_subscriptions() 
+
+    results = connected_configured_collector.SubscribeState(subscriptions)
+    # logger.info(f"Subscribed result: {results}.")
+    assert results ==  [False, True, True] # all(result is True for result in results)
+
+def test_unsubscribe_state(connected_configured_collector):
+    logger.info(">>> test_unsubscribe_state <<<")
+    subscriptions = create_test_subscriptions()
+
+    connected_configured_collector.SubscribeState(subscriptions)
+    results = connected_configured_collector.UnsubscribeState(subscriptions)
+    assert results ==  [False, True, True] # all(result is True for result in results)
+
+def test_get_state(connected_configured_collector):
+    logger.info(">>> test_get_state <<<")
+    subscriptions = create_test_subscriptions()
+
+    connected_configured_collector.SubscribeState(subscriptions)
+    logger.info(f"Subscribed to state: {subscriptions}. waiting for 12 seconds ...")
+    time.sleep(12)
+
+    state_iterator = connected_configured_collector.GetState(blocking=False)
+    states = list(state_iterator)
+
+    assert len(states) > 0
diff --git a/src/telemetry/frontend/service/TelemetryFrontendServiceServicerImpl.py b/src/telemetry/frontend/service/TelemetryFrontendServiceServicerImpl.py
index ce55f80510b3ff678ead1be82bda9101cc8e7e17..f74e97ffd4998ca0b3255ca4e1ebe496ebc6737b 100644
--- a/src/telemetry/frontend/service/TelemetryFrontendServiceServicerImpl.py
+++ b/src/telemetry/frontend/service/TelemetryFrontendServiceServicerImpl.py
@@ -74,7 +74,7 @@ class TelemetryFrontendServiceServicerImpl(TelemetryFrontendServiceServicer):
             "interval": collector_obj.interval_s
         }
         self.kafka_producer.produce(
-            KafkaTopic.REQUEST.value,
+            KafkaTopic.TELEMETRY_REQUEST.value,
             key      = collector_uuid,
             value    = json.dumps(collector_to_generate),
             callback = self.delivery_callback
@@ -110,7 +110,7 @@ class TelemetryFrontendServiceServicerImpl(TelemetryFrontendServiceServicer):
             "interval": -1
         }
         self.kafka_producer.produce(
-            KafkaTopic.REQUEST.value,
+            KafkaTopic.TELEMETRY_REQUEST.value,
             key      = collector_uuid,
             value    = json.dumps(collector_to_stop),
             callback = self.delivery_callback
@@ -168,7 +168,7 @@ class TelemetryFrontendServiceServicerImpl(TelemetryFrontendServiceServicer):
         """
         listener for response on Kafka topic.
         """
-        self.kafka_consumer.subscribe([KafkaTopic.RESPONSE.value])
+        self.kafka_consumer.subscribe([KafkaTopic.TELEMETRY_RESPONSE.value])
         while True:
             receive_msg = self.kafka_consumer.poll(2.0)
             if receive_msg is None:
@@ -196,7 +196,7 @@ class TelemetryFrontendServiceServicerImpl(TelemetryFrontendServiceServicer):
     def process_response(self, collector_id: str, kpi_id: str, kpi_value: Any):
         if kpi_id == "-1" and kpi_value == -1:
             # print ("Backend termination confirmation for collector id: ", collector_id)
-            LOGGER.info("Backend termination confirmation for collector id: ", collector_id)
+            LOGGER.info("Backend termination confirmation for collector id: {:}".format(collector_id))
         else:
-            LOGGER.info("Backend termination confirmation for collector id: ", collector_id)
+            LOGGER.info("Backend termination confirmation for collector id: {:}".format(collector_id))
             # print ("KPI Value: Collector Id:", collector_id, ", Kpi Id:", kpi_id, ", Value:", kpi_value)