diff --git a/.gitignore b/.gitignore
index 0a116f850780386a9fe1010b22164f4c7dbf8228..8b8419968a620ed2329dacb166d5e8ae4ae4b0c1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -156,6 +156,7 @@ cython_debug/
 
 # Other
 /tmp
+/netphony-network-protocols
 
 # Sqlite
 *.db
diff --git a/manifests/bgpls_speakerservice.yaml b/manifests/bgpls_speakerservice.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..5488566bc02bf6edeaff3a1536e9641334c07fad
--- /dev/null
+++ b/manifests/bgpls_speakerservice.yaml
@@ -0,0 +1,72 @@
+# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (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.
+
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: bgpls-speakerservice
+spec:
+  selector:
+    matchLabels:
+      app: bgpls-speakerservice
+  replicas: 1
+  template:
+    metadata:
+      labels:
+        app: bgpls-speakerservice
+    spec:
+      terminationGracePeriodSeconds: 5
+      containers:
+      - name: server
+        image: localhost:32000/tfs/bgpls_speaker:dev
+        imagePullPolicy: Always
+        ports:
+        - containerPort: 10030
+        - containerPort: 9192
+        env:
+        - name: LOG_LEVEL
+          value: "DEBUG"
+        readinessProbe:
+          exec:
+            command: ["/bin/grpc_health_probe", "-addr=:10030"]
+        livenessProbe:
+          exec:
+            command: ["/bin/grpc_health_probe", "-addr=:10030"]
+        resources:
+          requests:
+            cpu: 50m
+            memory: 64Mi
+          limits:
+            cpu: 500m
+            memory: 512Mi
+---
+apiVersion: v1
+kind: Service
+metadata:
+  name: bgpls-speakerservice
+  labels:
+    app: bgpls-speakerservice
+spec:
+  type: ClusterIP
+  selector:
+    app: bgpls-speakerservice
+  ports:
+  - name: grpc
+    protocol: TCP
+    port: 10030
+    targetPort: 10030
+  - name: metrics
+    protocol: TCP
+    port: 9192
+    targetPort: 9192
diff --git a/src/common/Constants.py b/src/common/Constants.py
index a7bf198a7204677ed3669fc28a2c3528a5936425..a44758a7954e85a56fd8ae3c5321b2fa5e6551ca 100644
--- a/src/common/Constants.py
+++ b/src/common/Constants.py
@@ -16,7 +16,7 @@ import logging
 from enum import Enum
 
 # Default logging level
-DEFAULT_LOG_LEVEL = logging.WARNING
+DEFAULT_LOG_LEVEL = logging.DEBUG
 
 # Default gRPC server settings
 DEFAULT_GRPC_BIND_ADDRESS = '0.0.0.0'
@@ -49,6 +49,7 @@ class ServiceNameEnum(Enum):
     INTERDOMAIN   = 'interdomain'
     PATHCOMP      = 'pathcomp'
     WEBUI         = 'webui'
+    BGPLS         = 'bgpls-speaker'
 
     # Used for test and debugging only
     DLT_GATEWAY    = 'dltgateway'
@@ -68,6 +69,7 @@ DEFAULT_SERVICE_GRPC_PORTS = {
     ServiceNameEnum.CYBERSECURITY.value : 10000,
     ServiceNameEnum.INTERDOMAIN  .value : 10010,
     ServiceNameEnum.PATHCOMP     .value : 10020,
+    ServiceNameEnum.BGPLS        .value : 10030,
 
     # Used for test and debugging only
     ServiceNameEnum.DLT_GATEWAY   .value : 50051,
diff --git a/src/common/DeviceTypes.py b/src/common/DeviceTypes.py
index a47b6be3c6acac5be0ebbe262ba0988f536bf083..99255defdb6b5ee155607536a2e13d23b97b2d3a 100644
--- a/src/common/DeviceTypes.py
+++ b/src/common/DeviceTypes.py
@@ -28,7 +28,6 @@ class DeviceTypeEnum(Enum):
     EMULATED_P4_SWITCH              = 'emu-p4-switch'
     EMULATED_PACKET_ROUTER          = 'emu-packet-router'
     EMULATED_PACKET_SWITCH          = 'emu-packet-switch'
-    EMULATED_BGPLS_ASNUMBER         = 'emu-bgpls-asnumber'
 
     # Real device types
     DATACENTER                      = 'datacenter'
@@ -39,5 +38,4 @@ class DeviceTypeEnum(Enum):
     P4_SWITCH                       = 'p4-switch'
     PACKET_ROUTER                   = 'packet-router'
     PACKET_SWITCH                   = 'packet-switch'
-    XR_CONSTELLATION                = 'xr-constellation'
-    BGPLS_ASNUMBER                  = 'bgpls-asnumber'
\ No newline at end of file
+    XR_CONSTELLATION                = 'xr-constellation'
\ No newline at end of file
diff --git a/src/common/tools/object_factory/Device.py b/src/common/tools/object_factory/Device.py
index d35cb684cb55181b7bc6d665e00f45ebf351c758..0cc4555d455bf28ac2143a5d58b87e084a8360c7 100644
--- a/src/common/tools/object_factory/Device.py
+++ b/src/common/tools/object_factory/Device.py
@@ -43,9 +43,6 @@ DEVICE_MICROWAVE_DRIVERS = [DeviceDriverEnum.DEVICEDRIVER_IETF_NETWORK_TOPOLOGY]
 DEVICE_P4_TYPE      = DeviceTypeEnum.P4_SWITCH.value
 DEVICE_P4_DRIVERS   = [DeviceDriverEnum.DEVICEDRIVER_P4]
 
-DEVICE_BGPLS_TYPE      = DeviceTypeEnum.BGPLS_ASNUMBER.value
-DEVICE_BGPLS_DRIVERS   = [DeviceDriverEnum.DEVICEDRIVER_BGPLS]
-
 def json_device_id(device_uuid : str):
     return {'device_uuid': {'uuid': device_uuid}}
 
diff --git a/src/compute/service/__main__.py b/src/compute/service/__main__.py
index 9705e3187ffff633a4d127855c1c57afcf397e39..8621df44477376b19a2c1400047cfb5dcd85701c 100644
--- a/src/compute/service/__main__.py
+++ b/src/compute/service/__main__.py
@@ -13,6 +13,7 @@
 # limitations under the License.
 
 import logging, signal, sys, threading
+from compute.service.rest_server.nbi_plugins.ietf_topolgy import register_ietf_topology
 from prometheus_client import start_http_server
 from common.Constants import ServiceNameEnum
 from common.Settings import (
@@ -60,6 +61,7 @@ def main():
     rest_server = RestServer()
     register_debug_api(rest_server)
     register_ietf_l2vpn(rest_server)
+    register_ietf_topology(rest_server)
     rest_server.start()
 
     # Wait for Ctrl+C or termination signal
diff --git a/src/compute/service/rest_server/nbi_plugins/ietf_topolgy/Constants.py b/src/compute/service/rest_server/nbi_plugins/ietf_topolgy/Constants.py
new file mode 100644
index 0000000000000000000000000000000000000000..f95b532af4ba01968d17bc3958e1cffbf84a5e7f
--- /dev/null
+++ b/src/compute/service/rest_server/nbi_plugins/ietf_topolgy/Constants.py
@@ -0,0 +1,77 @@
+# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (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.
+
+DEFAULT_MTU              = 1512
+DEFAULT_ADDRESS_FAMILIES = ['IPV4']
+DEFAULT_BGP_AS           = 65000
+DEFAULT_BGP_ROUTE_TARGET = '{:d}:{:d}'.format(DEFAULT_BGP_AS, 333)
+
+# TODO: improve definition of bearer mappings
+
+# Bearer mappings:
+# device_uuid:endpoint_uuid => (
+#   device_uuid, endpoint_uuid, router_id, route_dist, sub_if_index,
+#   address_ip, address_prefix, remote_router, circuit_id)
+
+BEARER_MAPPINGS = {
+    # OFC'22
+    'R1-EMU:13/1/2': ('R1-EMU', '13/1/2', '10.10.10.1', '65000:100', 400, '3.3.2.1', 24, None, None),
+    'R2-EMU:13/1/2': ('R2-EMU', '13/1/2', '12.12.12.1', '65000:120', 450, '3.4.2.1', 24, None, None),
+    'R3-EMU:13/1/2': ('R3-EMU', '13/1/2', '20.20.20.1', '65000:200', 500, '3.3.1.1', 24, None, None),
+    'R4-EMU:13/1/2': ('R4-EMU', '13/1/2', '22.22.22.1', '65000:220', 550, '3.4.1.1', 24, None, None),
+
+    # OECC/PSC'22 - domain 1
+    'R1@D1:3/1'    : ('R1@D1', '3/1', '10.0.1.1', '65001:101', 100, '1.1.3.1', 24, None, None),
+    'R1@D1:3/2'    : ('R1@D1', '3/2', '10.0.1.1', '65001:101', 100, '1.1.3.2', 24, None, None),
+    'R1@D1:3/3'    : ('R1@D1', '3/3', '10.0.1.1', '65001:101', 100, '1.1.3.3', 24, None, None),
+    'R2@D1:3/1'    : ('R2@D1', '3/1', '10.0.1.2', '65001:102', 100, '1.2.3.1', 24, None, None),
+    'R2@D1:3/2'    : ('R2@D1', '3/2', '10.0.1.2', '65001:102', 100, '1.2.3.2', 24, None, None),
+    'R2@D1:3/3'    : ('R2@D1', '3/3', '10.0.1.2', '65001:102', 100, '1.2.3.3', 24, None, None),
+    'R3@D1:3/1'    : ('R3@D1', '3/1', '10.0.1.3', '65001:103', 100, '1.3.3.1', 24, None, None),
+    'R3@D1:3/2'    : ('R3@D1', '3/2', '10.0.1.3', '65001:103', 100, '1.3.3.2', 24, None, None),
+    'R3@D1:3/3'    : ('R3@D1', '3/3', '10.0.1.3', '65001:103', 100, '1.3.3.3', 24, None, None),
+    'R4@D1:3/1'    : ('R4@D1', '3/1', '10.0.1.4', '65001:104', 100, '1.4.3.1', 24, None, None),
+    'R4@D1:3/2'    : ('R4@D1', '3/2', '10.0.1.4', '65001:104', 100, '1.4.3.2', 24, None, None),
+    'R4@D1:3/3'    : ('R4@D1', '3/3', '10.0.1.4', '65001:104', 100, '1.4.3.3', 24, None, None),
+
+    # OECC/PSC'22 - domain 2
+    'R1@D2:3/1'    : ('R1@D2', '3/1', '10.0.2.1', '65002:101', 100, '2.1.3.1', 24, None, None),
+    'R1@D2:3/2'    : ('R1@D2', '3/2', '10.0.2.1', '65002:101', 100, '2.1.3.2', 24, None, None),
+    'R1@D2:3/3'    : ('R1@D2', '3/3', '10.0.2.1', '65002:101', 100, '2.1.3.3', 24, None, None),
+    'R2@D2:3/1'    : ('R2@D2', '3/1', '10.0.2.2', '65002:102', 100, '2.2.3.1', 24, None, None),
+    'R2@D2:3/2'    : ('R2@D2', '3/2', '10.0.2.2', '65002:102', 100, '2.2.3.2', 24, None, None),
+    'R2@D2:3/3'    : ('R2@D2', '3/3', '10.0.2.2', '65002:102', 100, '2.2.3.3', 24, None, None),
+    'R3@D2:3/1'    : ('R3@D2', '3/1', '10.0.2.3', '65002:103', 100, '2.3.3.1', 24, None, None),
+    'R3@D2:3/2'    : ('R3@D2', '3/2', '10.0.2.3', '65002:103', 100, '2.3.3.2', 24, None, None),
+    'R3@D2:3/3'    : ('R3@D2', '3/3', '10.0.2.3', '65002:103', 100, '2.3.3.3', 24, None, None),
+    'R4@D2:3/1'    : ('R4@D2', '3/1', '10.0.2.4', '65002:104', 100, '2.4.3.1', 24, None, None),
+    'R4@D2:3/2'    : ('R4@D2', '3/2', '10.0.2.4', '65002:104', 100, '2.4.3.2', 24, None, None),
+    'R4@D2:3/3'    : ('R4@D2', '3/3', '10.0.2.4', '65002:104', 100, '2.4.3.3', 24, None, None),
+
+    # ECOC'22
+    'DC1-GW:CS1-GW1': ('CS1-GW1', '10/1', '5.5.1.1', None, 0, None, None, '5.5.2.1', 111),
+    'DC1-GW:CS1-GW2': ('CS1-GW2', '10/1', '5.5.1.2', None, 0, None, None, '5.5.2.2', 222),
+    'DC2-GW:CS2-GW1': ('CS2-GW1', '10/1', '5.5.2.1', None, 0, None, None, '5.5.1.1', 111),
+    'DC2-GW:CS2-GW2': ('CS2-GW2', '10/1', '5.5.2.2', None, 0, None, None, '5.5.1.2', 222),
+
+    # NetworkX'22
+    'R1:1/2': ('R1', '1/2', '5.1.1.2', None, 0, None, None, None, None),
+    'R1:1/3': ('R1', '1/3', '5.1.1.3', None, 0, None, None, None, None),
+    'R2:1/2': ('R2', '1/2', '5.2.1.2', None, 0, None, None, None, None),
+    'R2:1/3': ('R2', '1/3', '5.2.1.3', None, 0, None, None, None, None),
+    'R3:1/2': ('R3', '1/2', '5.3.1.2', None, 0, None, None, None, None),
+    'R3:1/3': ('R3', '1/3', '5.3.1.3', None, 0, None, None, None, None),
+    'R4:1/2': ('R4', '1/2', '5.4.1.2', None, 0, None, None, None, None),
+    'R4:1/3': ('R4', '1/3', '5.4.1.3', None, 0, None, None, None, None),
+}
diff --git a/src/compute/service/rest_server/nbi_plugins/ietf_topolgy/Topology_Service.py b/src/compute/service/rest_server/nbi_plugins/ietf_topolgy/Topology_Service.py
new file mode 100644
index 0000000000000000000000000000000000000000..f7ed15fdf39975449fff29ca08deb9667eabffe4
--- /dev/null
+++ b/src/compute/service/rest_server/nbi_plugins/ietf_topolgy/Topology_Service.py
@@ -0,0 +1,76 @@
+# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (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 import request
+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
+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
+
+LOGGER = logging.getLogger(__name__)
+
+class Topology_Service(Resource):
+    @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)))
+
+        try:
+            context_client = ContextClient()
+
+            target = get_slice(context_client, vpn_id, rw_copy=True)
+            if target is None:
+                raise Exception('VPN({:s}) not found in database'.format(str(vpn_id)))
+
+            if target.slice_id.slice_uuid.uuid != vpn_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
+            response = jsonify({})
+            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 VPN({:s})'.format(str(vpn_id)))
+            response = jsonify({'error': str(e)})
+            response.status_code = HTTP_SERVERERROR
+        return response
+
+    @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)))
+
+        try:
+            context_client = ContextClient()
+
+            target = get_slice(context_client, vpn_id)
+            if target is None:
+                LOGGER.warning('VPN({:s}) not found in database. Nothing done.'.format(str(vpn_id)))
+            else:
+                if target.slice_id.slice_uuid.uuid != vpn_id: # pylint: disable=no-member
+                    raise Exception('Slice retrieval failed. Wrong Slice Id was returned')
+                slice_client = SliceClient()
+                slice_client.DeleteSlice(target.slice_id)
+            response = jsonify({})
+            response.status_code = HTTP_NOCONTENT
+        except Exception as e: # pylint: disable=broad-except
+            LOGGER.exception('Something went wrong Deleting VPN({:s})'.format(str(vpn_id)))
+            response = jsonify({'error': str(e)})
+            response.status_code = HTTP_SERVERERROR
+        return response
diff --git a/src/compute/service/rest_server/nbi_plugins/ietf_topolgy/Topology_Services.py b/src/compute/service/rest_server/nbi_plugins/ietf_topolgy/Topology_Services.py
new file mode 100644
index 0000000000000000000000000000000000000000..505e80f868d58810944dd65d9207cdde68b72a68
--- /dev/null
+++ b/src/compute/service/rest_server/nbi_plugins/ietf_topolgy/Topology_Services.py
@@ -0,0 +1,79 @@
+# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (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
+from common.tools.grpc.Tools import grpc_message_list_to_json_string, grpc_message_to_json_string
+from compute.service.rest_server.nbi_plugins.debug_api.Tools import format_grpc_to_json, grpc_topology_id
+from context.client.ContextClient import ContextClient
+from flask import request
+from flask.json import jsonify
+from flask_restful import Resource
+from werkzeug.exceptions import UnsupportedMediaType
+from common.Constants import DEFAULT_CONTEXT_NAME
+from common.proto.context_pb2 import Empty, SliceStatusEnum, Slice
+from slice.client.SliceClient import SliceClient
+from .schemas.vpn_service import SCHEMA_VPN_SERVICE
+from .tools.Authentication import HTTP_AUTH
+from .tools.HttpStatusCodes import HTTP_CREATED, HTTP_SERVERERROR
+from .tools.Validator import validate_message
+
+LOGGER = logging.getLogger(__name__)
+
+class Topology_Services(Resource):
+    @HTTP_AUTH.login_required
+    def get(self):
+
+        context_client=ContextClient()
+        context_client.connect()
+        ctx_ids=context_client.ListContextIds(Empty())
+        topos=[]
+        for ctx in ctx_ids.context_ids:
+            topo_ids=context_client.ListTopologyIds(ctx)
+            context_uuid=ctx
+            for ids in topo_ids.topology_ids:
+                topos.append(context_client.GetTopology(ids))
+                topology_uuid=ids
+        LOGGER.info("nbi topo %s",topos)
+        LOGGER.info("nbi topo JSON %s",grpc_message_list_to_json_string(topos))
+        response=format_grpc_to_json(context_client.GetTopologyDetails(topology_uuid))
+        context_client.close()
+        return response
+
+    @HTTP_AUTH.login_required
+    def post(self):
+        if not request.is_json: raise UnsupportedMediaType('JSON payload is required')
+        request_data : Dict = request.json
+        LOGGER.debug('Request: {:s}'.format(str(request_data)))
+        validate_message(SCHEMA_VPN_SERVICE, request_data)
+
+        vpn_services : List[Dict] = request_data['ietf-l2vpn-svc:vpn-service']
+        for vpn_service in vpn_services:
+            try:
+                # pylint: disable=no-member
+                slice_request = Slice()
+                slice_request.slice_id.context_id.context_uuid.uuid = DEFAULT_CONTEXT_NAME
+                slice_request.slice_id.slice_uuid.uuid = vpn_service['vpn-id']
+                slice_request.slice_status.slice_status = SliceStatusEnum.SLICESTATUS_PLANNED
+
+                slice_client = SliceClient()
+                slice_client.CreateSlice(slice_request)
+
+                response = jsonify({})
+                response.status_code = HTTP_CREATED
+            except Exception as e: # pylint: disable=broad-except
+                LOGGER.exception('Something went wrong Creating Service {:s}'.format(str(request)))
+                response = jsonify({'error': str(e)})
+                response.status_code = HTTP_SERVERERROR
+        return response
diff --git a/src/compute/service/rest_server/nbi_plugins/ietf_topolgy/Topology_SiteNetworkAccesses.py b/src/compute/service/rest_server/nbi_plugins/ietf_topolgy/Topology_SiteNetworkAccesses.py
new file mode 100644
index 0000000000000000000000000000000000000000..93bcb84701f7b06205a7e7dc1513250d0c62c0d1
--- /dev/null
+++ b/src/compute/service/rest_server/nbi_plugins/ietf_topolgy/Topology_SiteNetworkAccesses.py
@@ -0,0 +1,157 @@
+# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (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, Optional
+from flask import request
+from flask.json import jsonify
+from flask.wrappers import Response
+from flask_restful import Resource
+from werkzeug.exceptions import UnsupportedMediaType
+from common.proto.context_pb2 import Slice
+from common.tools.context_queries.Slice import get_slice
+from common.tools.grpc.ConfigRules import update_config_rule_custom
+from common.tools.grpc.Constraints import (
+    update_constraint_custom_dict, update_constraint_endpoint_location, update_constraint_endpoint_priority,
+    update_constraint_sla_availability)
+from common.tools.grpc.EndPointIds import update_endpoint_ids
+from common.tools.grpc.Tools import grpc_message_to_json_string
+from context.client.ContextClient import ContextClient
+from slice.client.SliceClient import SliceClient
+from .schemas.site_network_access import SCHEMA_SITE_NETWORK_ACCESS
+from .tools.Authentication import HTTP_AUTH
+from .tools.HttpStatusCodes import HTTP_NOCONTENT, HTTP_SERVERERROR
+from .tools.Validator import validate_message
+from .Constants import (
+    BEARER_MAPPINGS, DEFAULT_ADDRESS_FAMILIES, DEFAULT_BGP_AS, DEFAULT_BGP_ROUTE_TARGET, DEFAULT_MTU)
+
+LOGGER = logging.getLogger(__name__)
+
+def process_site_network_access(context_client : ContextClient, site_id : str, site_network_access : Dict) -> Slice:
+    vpn_id = site_network_access['vpn-attachment']['vpn-id']
+    encapsulation_type = site_network_access['connection']['encapsulation-type']
+    cvlan_id = site_network_access['connection']['tagged-interface'][encapsulation_type]['cvlan-id']
+
+    bearer_reference = site_network_access['bearer']['bearer-reference']
+
+    access_priority : Optional[int] = site_network_access.get('availability', {}).get('access-priority')
+    single_active   : bool = len(site_network_access.get('availability', {}).get('single-active', [])) > 0
+    all_active      : bool = len(site_network_access.get('availability', {}).get('all-active', [])) > 0
+
+    diversity_constraints = site_network_access.get('access-diversity', {}).get('constraints', {}).get('constraint', [])
+    raise_if_differs = True
+    diversity_constraints = {
+        constraint['constraint-type']:([
+            target[0]
+            for target in constraint['target'].items()
+            if len(target[1]) == 1
+        ][0], raise_if_differs)
+        for constraint in diversity_constraints
+    }
+
+    mapping = BEARER_MAPPINGS.get(bearer_reference)
+    if mapping is None:
+        msg = 'Specified Bearer({:s}) is not configured.'
+        raise Exception(msg.format(str(bearer_reference)))
+    (
+        device_uuid, endpoint_uuid, router_id, route_dist, sub_if_index,
+        address_ip, address_prefix, remote_router, circuit_id
+    ) = mapping
+
+    target = get_slice(context_client, vpn_id, rw_copy=True)
+    if target is None: raise Exception('VPN({:s}) not found in database'.format(str(vpn_id)))
+
+    endpoint_ids = target.slice_endpoint_ids        # pylint: disable=no-member
+    config_rules = target.slice_config.config_rules # pylint: disable=no-member
+    constraints  = target.slice_constraints         # pylint: disable=no-member
+
+    endpoint_id = update_endpoint_ids(endpoint_ids, device_uuid, endpoint_uuid)
+
+    service_settings_key = '/settings'
+    update_config_rule_custom(config_rules, service_settings_key, {
+        'mtu'             : (DEFAULT_MTU,              True),
+        'address_families': (DEFAULT_ADDRESS_FAMILIES, True),
+        'bgp_as'          : (DEFAULT_BGP_AS,           True),
+        'bgp_route_target': (DEFAULT_BGP_ROUTE_TARGET, True),
+    })
+
+    endpoint_settings_key = '/device[{:s}]/endpoint[{:s}]/settings'.format(device_uuid, endpoint_uuid)
+    field_updates = {}
+    if router_id      is not None: field_updates['router_id'          ] = (router_id,      True)
+    if route_dist     is not None: field_updates['route_distinguisher'] = (route_dist,     True)
+    if sub_if_index   is not None: field_updates['sub_interface_index'] = (sub_if_index,   True)
+    if cvlan_id       is not None: field_updates['vlan_id'            ] = (cvlan_id,       True)
+    if address_ip     is not None: field_updates['address_ip'         ] = (address_ip,     True)
+    if address_prefix is not None: field_updates['address_prefix'     ] = (address_prefix, True)
+    if remote_router  is not None: field_updates['remote_router'      ] = (remote_router,  True)
+    if circuit_id     is not None: field_updates['circuit_id'         ] = (circuit_id,     True)
+    update_config_rule_custom(config_rules, endpoint_settings_key, field_updates)
+
+    if len(diversity_constraints) > 0:
+        update_constraint_custom_dict(constraints, 'diversity', diversity_constraints)
+
+    update_constraint_endpoint_location(constraints, endpoint_id, region=site_id)
+    if access_priority is not None: update_constraint_endpoint_priority(constraints, endpoint_id, access_priority)
+    if single_active or all_active:
+        # assume 1 disjoint path per endpoint/location included in service/slice
+        location_endpoints = {}
+        for constraint in constraints:
+            if constraint.WhichOneof('constraint') != 'endpoint_location': continue
+            str_endpoint_id = grpc_message_to_json_string(constraint.endpoint_location.endpoint_id)
+            str_location_id = grpc_message_to_json_string(constraint.endpoint_location.location)
+            location_endpoints.setdefault(str_location_id, set()).add(str_endpoint_id)
+        num_endpoints_per_location = {len(endpoints) for endpoints in location_endpoints.values()}
+        num_disjoint_paths = min(num_endpoints_per_location)
+        update_constraint_sla_availability(constraints, num_disjoint_paths, all_active, 0.0)
+
+    return target
+
+def process_list_site_network_access(
+        context_client : ContextClient, slice_client : SliceClient, site_id : str, request_data : Dict
+    ) -> Response:
+
+    LOGGER.debug('Request: {:s}'.format(str(request_data)))
+    validate_message(SCHEMA_SITE_NETWORK_ACCESS, request_data)
+
+    errors = []
+    for site_network_access in request_data['ietf-l2vpn-svc:site-network-access']:
+        sna_request = process_site_network_access(context_client, site_id, site_network_access)
+        LOGGER.debug('sna_request = {:s}'.format(grpc_message_to_json_string(sna_request)))
+        try:
+            slice_client.UpdateSlice(sna_request)
+        except Exception as e: # pylint: disable=broad-except
+            msg = 'Something went wrong Updating VPN {:s}'
+            LOGGER.exception(msg.format(grpc_message_to_json_string(sna_request)))
+            errors.append({'error': str(e)})
+
+    response = jsonify(errors)
+    response.status_code = HTTP_NOCONTENT if len(errors) == 0 else HTTP_SERVERERROR
+    return response
+
+class Topology_SiteNetworkAccesses(Resource):
+    @HTTP_AUTH.login_required
+    def post(self, site_id : str):
+        if not request.is_json: raise UnsupportedMediaType('JSON payload is required')
+        LOGGER.debug('Site_Id: {:s}'.format(str(site_id)))
+        context_client = ContextClient()
+        slice_client = SliceClient()
+        return process_list_site_network_access(context_client, slice_client, site_id, request.json)
+
+    @HTTP_AUTH.login_required
+    def put(self, site_id : str):
+        if not request.is_json: raise UnsupportedMediaType('JSON payload is required')
+        LOGGER.debug('Site_Id: {:s}'.format(str(site_id)))
+        context_client = ContextClient()
+        slice_client = SliceClient()
+        return process_list_site_network_access(context_client, slice_client, site_id, request.json)
diff --git a/src/compute/service/rest_server/nbi_plugins/ietf_topolgy/__init__.py b/src/compute/service/rest_server/nbi_plugins/ietf_topolgy/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..36ade4b622199f5b2e68795b6943c4c18520014b
--- /dev/null
+++ b/src/compute/service/rest_server/nbi_plugins/ietf_topolgy/__init__.py
@@ -0,0 +1,36 @@
+# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (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.
+
+# RFC 8466 - L2VPN Service Model (L2SM)
+# Ref: https://datatracker.ietf.org/doc/html/rfc8466
+
+from flask_restful import Resource
+from compute.service.rest_server.RestServer import RestServer
+from .Topology_Services import Topology_Services
+from .Topology_Service import Topology_Service
+from .Topology_SiteNetworkAccesses import Topology_SiteNetworkAccesses
+
+URL_PREFIX = '/data/topology'
+
+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_topology(rest_server : RestServer):
+    _add_resource(rest_server, Topology_Services,
+        '/bgpls')
+    _add_resource(rest_server, Topology_Service,
+        '/vpn-services/vpn-service=<vpn_id>', '/vpn-services/vpn-service=<vpn_id>/')
+    _add_resource(rest_server, Topology_SiteNetworkAccesses,
+        '/sites/site=<site_id>/site-network-accesses', '/sites/site=<site_id>/site-network-accesses/')
diff --git a/src/compute/service/rest_server/nbi_plugins/ietf_topolgy/schemas/Common.py b/src/compute/service/rest_server/nbi_plugins/ietf_topolgy/schemas/Common.py
new file mode 100644
index 0000000000000000000000000000000000000000..d708953ec952c68150a22023c5ef304683d4571a
--- /dev/null
+++ b/src/compute/service/rest_server/nbi_plugins/ietf_topolgy/schemas/Common.py
@@ -0,0 +1,16 @@
+# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (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.
+
+# String pattern for UUIDs such as '3fd942ee-2dc3-41d1-aeec-65aa85d117b2'
+REGEX_UUID = r'[a-fA-F0-9]{8}\-[a-fA-F0-9]{4}\-[a-fA-F0-9]{4}\-[a-fA-F0-9]{4}\-[a-fA-F0-9]{12}'
diff --git a/src/device/service/drivers/bgpls/__init__.py b/src/compute/service/rest_server/nbi_plugins/ietf_topolgy/schemas/__init__.py
similarity index 100%
rename from src/device/service/drivers/bgpls/__init__.py
rename to src/compute/service/rest_server/nbi_plugins/ietf_topolgy/schemas/__init__.py
diff --git a/src/compute/service/rest_server/nbi_plugins/ietf_topolgy/schemas/site_network_access.py b/src/compute/service/rest_server/nbi_plugins/ietf_topolgy/schemas/site_network_access.py
new file mode 100644
index 0000000000000000000000000000000000000000..ec39e30ca27b93e76c7959de0f1d7d7a9ceba8c8
--- /dev/null
+++ b/src/compute/service/rest_server/nbi_plugins/ietf_topolgy/schemas/site_network_access.py
@@ -0,0 +1,80 @@
+# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (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.
+
+# Example request:
+# request = {'ietf-l2vpn-svc:site-network-access': [{
+#     'network-access-id': '3fd942ee-2dc3-41d1-aeec-65aa85d117b2',
+#     'vpn-attachment': {'vpn-id': '954b1b53-4a8c-406d-9eff-750ec2c9a258',
+#         'site-role': 'any-to-any-role'},
+#     'connection': {'encapsulation-type': 'dot1q-vlan-tagged', 'tagged-interface': {
+#         'dot1q-vlan-tagged': {'cvlan-id': 1234}}},
+#     'bearer': {'bearer-reference': '1a'}
+# }]}
+
+from .Common import REGEX_UUID
+
+SCHEMA_SITE_NETWORK_ACCESS = {
+    '$schema': 'https://json-schema.org/draft/2020-12/schema',
+    'type': 'object',
+    'required': ['ietf-l2vpn-svc:site-network-access'],
+    'properties': {
+        'ietf-l2vpn-svc:site-network-access': {
+            'type': 'array',
+            'minItems': 1,
+            'maxItems': 1,  # by now we do not support multiple site-network-access in the same message
+            'items': {
+                'type': 'object',
+                'required': ['network-access-id', 'vpn-attachment', 'connection', 'bearer'],
+                'properties': {
+                    'network-access-id': {'type': 'string', 'pattern': REGEX_UUID},
+                    'vpn-attachment': {
+                        'type': 'object',
+                        'required': ['vpn-id', 'site-role'],
+                        'properties': {
+                            'vpn-id': {'type': 'string', 'pattern': REGEX_UUID},
+                            'site-role': {'type': 'string', 'minLength': 1},
+                        },
+                    },
+                    'connection': {
+                        'type': 'object',
+                        'required': ['encapsulation-type', 'tagged-interface'],
+                        'properties': {
+                            'encapsulation-type': {'enum': ['dot1q-vlan-tagged']},
+                            'tagged-interface': {
+                                'type': 'object',
+                                'required': ['dot1q-vlan-tagged'],
+                                'properties': {
+                                    'dot1q-vlan-tagged': {
+                                        'type': 'object',
+                                        'required': ['cvlan-id'],
+                                        'properties': {
+                                            'cvlan-id': {'type': 'integer', 'minimum': 1, 'maximum': 4094},
+                                        },
+                                    },
+                                },
+                            },
+                        },
+                    },
+                    'bearer': {
+                        'type': 'object',
+                        'required': ['bearer-reference'],
+                        'properties': {
+                            'bearer-reference': {'type': 'string', 'minLength': 1},
+                        },
+                    },
+                },
+            },
+        },
+    },
+}
diff --git a/src/compute/service/rest_server/nbi_plugins/ietf_topolgy/schemas/vpn_service.py b/src/compute/service/rest_server/nbi_plugins/ietf_topolgy/schemas/vpn_service.py
new file mode 100644
index 0000000000000000000000000000000000000000..bccc2319bdd0692e3f487c8f879a0fd2dd521b4b
--- /dev/null
+++ b/src/compute/service/rest_server/nbi_plugins/ietf_topolgy/schemas/vpn_service.py
@@ -0,0 +1,46 @@
+# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (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.
+
+# Example request:
+# request = {'ietf-l2vpn-svc:vpn-service': [{
+#   'vpn-id': 'c6270231-f1de-4687-b2ed-7b58f9105775',
+#   'vpn-svc-type': 'vpws',
+#   'svc-topo': 'any-to-any',
+#   'customer-name': 'osm'
+# }]}
+
+from .Common import REGEX_UUID
+
+SCHEMA_VPN_SERVICE = {
+    '$schema': 'https://json-schema.org/draft/2020-12/schema',
+    'type': 'object',
+    'required': ['ietf-l2vpn-svc:vpn-service'],
+    'properties': {
+        'ietf-l2vpn-svc:vpn-service': {
+            'type': 'array',
+            'minItems': 1,
+            'maxItems': 1,  # by now we do not support multiple vpn-service in the same message
+            'items': {
+                'type': 'object',
+                'required': ['vpn-id', 'vpn-svc-type', 'svc-topo', 'customer-name'],
+                'properties': {
+                    'vpn-id': {'type': 'string', 'pattern': REGEX_UUID},
+                    'vpn-svc-type': {'enum': ['vpws', 'vpls']},
+                    'svc-topo': {'enum': ['any-to-any']},
+                    'customer-name': {'const': 'osm'},
+                },
+            }
+        }
+    },
+}
diff --git a/src/compute/service/rest_server/nbi_plugins/ietf_topolgy/tools/Authentication.py b/src/compute/service/rest_server/nbi_plugins/ietf_topolgy/tools/Authentication.py
new file mode 100644
index 0000000000000000000000000000000000000000..4577f4f0ffba31071c1045f22c9a6eb37e6eed39
--- /dev/null
+++ b/src/compute/service/rest_server/nbi_plugins/ietf_topolgy/tools/Authentication.py
@@ -0,0 +1,25 @@
+# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (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 flask_httpauth import HTTPBasicAuth
+from werkzeug.security import check_password_hash
+from compute.Config import RESTAPI_USERS
+
+HTTP_AUTH = HTTPBasicAuth()
+
+@HTTP_AUTH.verify_password
+def verify_password(username, password):
+    if username not in RESTAPI_USERS: return None
+    if not check_password_hash(RESTAPI_USERS[username], password): return None
+    return username
diff --git a/src/compute/service/rest_server/nbi_plugins/ietf_topolgy/tools/HttpStatusCodes.py b/src/compute/service/rest_server/nbi_plugins/ietf_topolgy/tools/HttpStatusCodes.py
new file mode 100644
index 0000000000000000000000000000000000000000..fe22d9ee80970d2bfd3d305f40511f433242df0a
--- /dev/null
+++ b/src/compute/service/rest_server/nbi_plugins/ietf_topolgy/tools/HttpStatusCodes.py
@@ -0,0 +1,20 @@
+# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (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.
+
+HTTP_OK             = 200
+HTTP_CREATED        = 201
+HTTP_NOCONTENT      = 204
+HTTP_BADREQUEST     = 400
+HTTP_SERVERERROR    = 500
+HTTP_GATEWAYTIMEOUT = 504
\ No newline at end of file
diff --git a/src/compute/service/rest_server/nbi_plugins/ietf_topolgy/tools/Validator.py b/src/compute/service/rest_server/nbi_plugins/ietf_topolgy/tools/Validator.py
new file mode 100644
index 0000000000000000000000000000000000000000..942609ed227b24b2e482654c54d2bb3647700e1c
--- /dev/null
+++ b/src/compute/service/rest_server/nbi_plugins/ietf_topolgy/tools/Validator.py
@@ -0,0 +1,35 @@
+# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (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 List
+from flask.json import jsonify
+from jsonschema import _utils
+from jsonschema.validators import validator_for
+from jsonschema.protocols import Validator
+from jsonschema.exceptions import ValidationError
+from werkzeug.exceptions import BadRequest
+from .HttpStatusCodes import HTTP_BADREQUEST
+
+def validate_message(schema, message):
+    validator_class = validator_for(schema)
+    validator : Validator = validator_class(schema)
+    errors : List[ValidationError] = sorted(validator.iter_errors(message), key=str)
+    if len(errors) == 0: return
+    response = jsonify([
+        {'message': str(error.message), 'schema': str(error.schema), 'validator': str(error.validator),
+         'where': str(_utils.format_as_index(container='message', indices=error.relative_path))}
+        for error in errors
+    ])
+    response.status_code = HTTP_BADREQUEST
+    raise BadRequest(response=response)
diff --git a/src/compute/service/rest_server/nbi_plugins/ietf_topolgy/tools/__init__.py b/src/compute/service/rest_server/nbi_plugins/ietf_topolgy/tools/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..1549d9811aa5d1c193a44ad45d0d7773236c0612
--- /dev/null
+++ b/src/compute/service/rest_server/nbi_plugins/ietf_topolgy/tools/__init__.py
@@ -0,0 +1,14 @@
+# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (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/DeviceServiceServicerImpl.py b/src/device/service/DeviceServiceServicerImpl.py
index 76acd203e4a63e0e7e8ad925a8af1a9edd0d56df..9a84d0df2c88293bbbdbb532435d75a91fee0e93 100644
--- a/src/device/service/DeviceServiceServicerImpl.py
+++ b/src/device/service/DeviceServiceServicerImpl.py
@@ -125,12 +125,6 @@ class DeviceServiceServicerImpl(DeviceServiceServicer):
                 device_id = context_client.SetDevice(device)
                 device = context_client.GetDevice(device_id)
 
-            # Checkear aqui si son dos driver y si uno es bgpls Connect ****tid-bgp-speaker****
-            if DeviceDriverEnum.DEVICEDRIVER_BGPLS in device.device_drivers:
-                LOGGER.info("Es BGPLS (ConfigureDevice)")
-                # config_BGPLSDriver.driverSettings(context_client)
-                # config_BGPLSDriver.driverConnect(self.driver_instance_cache,device,device_uuid)
-
 
             if request.device_operational_status != DeviceOperationalStatusEnum.DEVICEOPERATIONALSTATUS_UNDEFINED:
                 device.device_operational_status = request.device_operational_status
diff --git a/src/device/service/drivers/__init__.py b/src/device/service/drivers/__init__.py
index 17fb8c8f12e7988a89bec8aede92d38b3c31944a..69c82f9f22b2efb8a6d26ba7554bb482c7a70232 100644
--- a/src/device/service/drivers/__init__.py
+++ b/src/device/service/drivers/__init__.py
@@ -36,8 +36,7 @@ DRIVERS.append(
                 DeviceTypeEnum.EMULATED_OPTICAL_TRANSPONDER,
                 DeviceTypeEnum.EMULATED_P4_SWITCH,
                 DeviceTypeEnum.EMULATED_PACKET_ROUTER,
-                DeviceTypeEnum.EMULATED_PACKET_SWITCH,
-                DeviceTypeEnum.EMULATED_BGPLS_ASNUMBER,
+                DeviceTypeEnum.EMULATED_PACKET_SWITCH
 
                 #DeviceTypeEnum.DATACENTER,
                 #DeviceTypeEnum.MICROWAVE_RADIO_SYSTEM,
@@ -127,14 +126,4 @@ if LOAD_ALL_DEVICE_DRIVERS:
                 FilterFieldEnum.DEVICE_TYPE: DeviceTypeEnum.XR_CONSTELLATION,
                 FilterFieldEnum.DRIVER     : DeviceDriverEnum.DEVICEDRIVER_XR,
             }
-        ]))
-if LOAD_ALL_DEVICE_DRIVERS:
-    from .bgpls.BGPLSDriver import BGPLSDriver # pylint: disable=wrong-import-position
-    DRIVERS.append(
-        (BGPLSDriver, [
-            {
-                # Values :TODO ¿
-                FilterFieldEnum.DEVICE_TYPE: DeviceTypeEnum.BGPLS_ASNUMBER,
-                FilterFieldEnum.DRIVER     : DeviceDriverEnum.DEVICEDRIVER_BGPLS,
-            }
         ]))
\ No newline at end of file
diff --git a/src/device/service/drivers/bgpls/BGPLSDriver.py b/src/device/service/drivers/bgpls/BGPLSDriver.py
deleted file mode 100644
index be7b4656e4f2e274c182b0ed9686e4127e81ae97..0000000000000000000000000000000000000000
--- a/src/device/service/drivers/bgpls/BGPLSDriver.py
+++ /dev/null
@@ -1,233 +0,0 @@
-# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/)
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import json, logging,threading, queue,time,signal
-from datetime import datetime, timedelta
-from typing import Any, Iterator, List, Optional, Tuple, Union
-# from apscheduler.executors.pool import ThreadPoolExecutor
-# from apscheduler.job import Job
-# from apscheduler.jobstores.memory import MemoryJobStore
-# from apscheduler.schedulers.background import BackgroundScheduler
-# from common.method_wrappers.Decorator import MetricTypeEnum, MetricsPool, metered_subclass_method, INF
-# from common.type_checkers.Checkers import chk_float, chk_length, chk_string, chk_type
-
-
-import logging,anytree, json, pytz, queue, re, threading
-import grpc
-from .Tools import grpcComms,Link,Node,UpdateInfo
-from .protos import grpcService_pb2_grpc
-from .protos import grpcService_pb2
-
-
-from concurrent import futures
-from lxml import etree
-import os
-import subprocess
-from multiprocessing import Pool
-
-from device.service.driver_api._Driver import _Driver
-from apscheduler.executors.pool import ThreadPoolExecutor
-from apscheduler.job import Job
-from apscheduler.jobstores.memory import MemoryJobStore
-from apscheduler.schedulers.background import BackgroundScheduler
-from common.method_wrappers.Decorator import MetricTypeEnum, MetricsPool, metered_subclass_method, INF
-from common.type_checkers.Checkers import chk_float, 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
-
-SERVER_ADDRESS = 'localhost:2021'
-SERVER_ID = 1
-_ONE_DAY_IN_SECONDS = 60 * 60 * 24
-
-XML_FILE="BGP4Parameters_3.xml"
-XML_CONFIG_FILE="TMConfiguration_guillermo.xml"
-
-LOGGER = logging.getLogger(__name__)
-
-
-# Esto tiene que heredar de _Driver¿
-class BGPLSDriver(_Driver):
-    """
-    This class gets the current topology from a bgps speaker module in java 
-    and updates the posible new devices to add in the context topology.
-    Needs the address, port and as_number from the device giving de information via bgpls
-    to the java module.
-    """
-    def __init__(self, address : str, port : int, asNumber : int,**settings) -> None: # pylint: disable=super-init-not-called
-        self.__lock = threading.Lock()
-        self.__started = threading.Event()
-        self.__terminate = threading.Event()
-        self.__out_samples = queue.Queue()
-        # self.__scheduler = BackgroundScheduler(daemon=True) # scheduler used to emulate sampling events
-        # self.__scheduler.configure(
-        #     jobstores = {'default': MemoryJobStore()},
-        #     executors = {'default': ThreadPoolExecutor(max_workers=1)},
-        #     job_defaults = {'coalesce': False, 'max_instances': 3},
-        #     timezone=pytz.utc)
-        # TODO: atributos necesarios
-        # self.__server=asyncio.run(grpc.aio.server())
-
-        self.__address=address
-        self.__port=port
-        self.__asNumber=asNumber
-        self.__configFile=XML_CONFIG_FILE
-        self.__process=0
-        self.__comms=grpcComms
-
-     
-
-    async def Connect(self) -> bool:
-            # TODO: Metodos necesarios para conectarte al speaker
-            LOGGER.info("CONNECT BGPLSDriver")
-            # If started, assume it is already connected
-            if self.__started.is_set(): return True
-            # self.__scheduler.start()
-            self.__started.set() #notifyAll -->event.is_set()
-            # 10 workers ?
-            with self.__lock:
-                self.__server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
-                grpcService_pb2_grpc.add_updateServiceServicer_to_server(self, self.__server)
-                self.__server.add_insecure_port(SERVER_ADDRESS)
-                # server.add_secure_port(SERVER_ADDRESS)
-                LOGGER.info("Starting server on %s", SERVER_ADDRESS)
-                await self.__server.start()
-                try:
-                    while True:
-                        time.sleep(_ONE_DAY_IN_SECONDS)
-                except KeyboardInterrupt:
-                    LOGGER.info("DISCONNECT")
-                    self.Disconnect()
-                return True
-
-
-    def Disconnect(self) -> bool:
-        # TODO: channel grpc close
-        self.__terminate.set()
-        # If not started, assume it is already disconnected
-        if not self.__started.is_set(): return True
-
-        LOGGER.info("Keyboard interrupt, stop server")
-        self.__server.stop(0)
-        # Disconnect triggers deactivation of sampling events
-        # self.__scheduler.shutdown()
-        exit(0)
-        return True
-
-    # @metered_subclass_method(METRICS_POOL)
-    def update(self,request, context) -> bool:
-        """
-        Processes the messages recived by de grpc server
-        """
-        with self.__lock:
-            #TODO: Get update
-            LOGGER.info("(server)SimpleMethod called by client the message: %s" % (request))
-            response = grpcService_pb2.updateResponse(greeting="OK")
-            link=None
-            node=None # inicializar en otro lado¿
-            for linkIn in request.link:
-                link=Link(linkIn.remoteID,linkIn.localID,linkIn.remoteIP,linkIn.localIP)
-            for nodeIn in request.node:
-                node=Node(nodeIn.nodeName,nodeIn.nodeID)
-            up=UpdateInfo(link,node)
-            return response
-
-    def GetState(self, blocking=False, terminate : Optional[threading.Event] = None) -> Iterator[Tuple[str, Any]]:
-        while True:
-            if self.__terminate.is_set(): break
-            if terminate is not None and terminate.is_set(): break
-            try:
-                sample = self.__out_samples.get(block=blocking, timeout=0.1)
-            except queue.Empty:
-                if blocking: continue
-                return
-            if sample is None: continue
-            yield sample
-
-    def setPeer(self) -> bool:
-        """
-        Sets XML existing config file with peer address and port. TODO: as_number
-        """
-
-        XMLParser = etree.XMLParser(remove_blank_text=False)
-        tree = etree.parse(XML_FILE, parser=XMLParser)
-        root = tree.getroot()
-        peerAddress = root.find(".//peer")
-        peerAddress.text=self.__address
-        peerPort = root.find(".//peerPort")
-        peerPort.text=str(self.__port)
-        tree.write(XML_FILE) #with ... as ..
-        return True
-
-    def execBGPSpeaker(self) -> bool:
-        """
-        Executes java BGPLS speaker
-        """
-        # CHECKEAR muchas cosas
-        LOGGER.debug("Before exec")
-        with subprocess.Popen(['java -jar bgp_ls.jar '+ XML_CONFIG_FILE],
-            shell=True,start_new_session=True) as self.__process:
-        #     # logging.debug(self.__process.stdout.read())
-            return True
-
-    def endBGPSpeaker(self) -> bool:
-        """
-        Starts timer to kill java BGPLS Speaker
-        """
-        LOGGER.debug("end to sleep")
-        time.sleep(15)
-        LOGGER.debug("PID: %d",self.__process.pid)
-        LOGGER.debug("Group PID: %d",os.getpgid(self.__process.pid))
-        os.killpg(os.getpgid(self.__process.pid), signal.SIGKILL)
-        self.__process.kill()
-        return True
-
-    def runThreads(self):
-        # with futures.ThreadPoolExecutor(max_workers=4) as executor:
-        #     executor.submit(bgpDriver.ConnectNotWait)
-        #     executor.submit(bgpDriver.execBGPSpeaker)
-        #     executor.submit(bgpDriver.endBGPSpeaker)
-        t1=threading.Thread(name="t1",target=bgpDriver.Connect)
-        t2=threading.Thread(name="t2",target=bgpDriver.execBGPSpeaker)
-        t3=threading.Thread(name="t3",target=bgpDriver.endBGPSpeaker)
-        t1.start()
-        t2.start()
-        t3.start()
-        return True
-
-    def getCurrentTopo():
-        # import common.tools.Device
-        # get_devices_in_topology(
-            # context_client : ContextClient, context_id : ContextId, topology_uuid : str)
-
-        return True
-
-def quit(signal, _frame):
-    LOGGER.info("Interrupted by %d, shutting down" % signal)
-    bgpDriver.Disconnect()
-
-if __name__ == "__main__":
-
-    logging.basicConfig(level=logging.DEBUG)
-    for sig in ('TERM', 'HUP', 'INT'):
-        signal.signal(getattr(signal, 'SIG'+sig), quit)
-    # TODO: add port connection speaker
-    bgpDriver=BGPLSDriver("10.95.90.76",179,65006)
-    bgpDriver.setPeer()
-    bgpDriver.runThreads()
-
-    
-    
-        
-
-
diff --git a/src/device/service/drivers/bgpls/Tools.py b/src/device/service/drivers/bgpls/Tools.py
deleted file mode 100644
index 61f52ad51c8b6dd0639a63dd2b297e508f642b5e..0000000000000000000000000000000000000000
--- a/src/device/service/drivers/bgpls/Tools.py
+++ /dev/null
@@ -1,111 +0,0 @@
-
-from .protos import grpcService_pb2_grpc
-from .protos import grpcService_pb2
-
-import logging
-LOGGER = logging.getLogger(__name__)
-import os
-
-class UpdateInfo:
-    def __init__(self,link,node):
-        self.link=link
-        self.node=node
-class Link:
-    def __init__(self,rID,lID,rIP,lIP):
-        self.rID=rID
-        self.lID=lID
-        self.rIP=rIP
-        self.lIP=lIP
-class Node:
-    def __init__(self,name,nid):
-        self.Name=name
-        self.ID=nid
-
-class grpcComms(grpcService_pb2_grpc.updateServiceServicer):
-
-    def update(self,request, context) -> bool:
-        """
-        Processes the messages recived by de grpc server
-        """
-        with self.__lock:
-            #TODO: Get update
-            print("(server)SimpleMethod called by client the message: %s" % (request))
-            response = grpcService_pb2.updateResponse(greeting="OK")
-            link=None
-            node=None # inicializar en otro lado¿
-            for linkIn in request.link:
-                link=Link(linkIn.remoteID,linkIn.localID,linkIn.remoteIP,linkIn.localIP)
-            for nodeIn in request.node:
-                node=Node(nodeIn.nodeName,nodeIn.nodeID)
-            up=UpdateInfo(link,node)
-            return response
-
-from common.proto.context_pb2 import Device ,DeviceDriverEnum,ContextId,Empty
-from device.service.driver_api.DriverInstanceCache import DriverInstanceCache
-from device.service.driver_api.FilterFields import FilterFieldEnum, get_device_driver_filter_fields
-from device.service.Tools import get_connect_rules
-from . import BGPLSDriver as bgpls
-from context.client.ContextClient import ContextClient
-from common.Constants import DEFAULT_CONTEXT_NAME
-from common.tools.object_factory.Context import json_context_id
-
-ADMIN_CONTEXT_ID = ContextId(**json_context_id(DEFAULT_CONTEXT_NAME))
-
-class config_BGPLSDriver():
-
-    
-    def driverSettings( context_client : ContextClient):
-
-        list_topo=[]
-        LOGGER.info("Context (driverSettings) **************%s",context_client)
-        # context_uuid = context_id['context_uuid']['uuid']
-        # response = context.GetContext(ADMIN_CONTEXT_ID)
-        contexts : ContextList = context_client.ListContexts(Empty())
-        for context_ in contexts.contexts:
-            context_uuid : str = context_.context_id.context_uuid.uuid
-            context_name : str = context_.name
-            topologies : TopologyList = context_client.ListTopologies(context_.context_id)
-        # topologies : TopologyList=context_client.ListTopologies(context_client)
-            for topology_ in topologies.topologies:
-                #topology_uuid : str = topology_.topology_id.topology_uuid.uuid
-                topology_name : str = topology_.name
-                context_topology_name  = 'Context({:s}):Topology({:s})'.format(context_name, topology_name)
-                # Topos=context.GetTopology(list_topo.topology_id)
-                LOGGER.info("topo (driverSettings) %s",topology_)
-                details=context_client.GetTopologyDetails(topology_.topology_id)
-                LOGGER.info("details (driverSettings) %s",details)
-                devices=context_client.ListDevices(Empty())
-                # LOGGER.info("devices (driverSettings) %s",devices)
-                for device_ in devices.devices:
-                    LOGGER.info("device_ (driverSettings) %s",device_.name)
-                    for config_rule_ in device_.device_config.config_rules:
-                        if config_rule_.custom.resource_key == "_connect/address":
-                            LOGGER.info("device_.resource_value-addr (driverSettings) %s",
-                            config_rule_.custom.resource_value)
-                
-        # LOGGER.info("response getContext (driverSettings) %s",response)
-        # list_topo=context.ListTopologies(response.context_id)
-        # LOGGER.info("list_topo (driverSettings) %s",list_topo)
-        # Topos=context.GetTopology(list_topo.topology_id)
-        # LOGGER.info("topo (driverSettings) %s",Topos)
-        return
-
-    def driverConnect(driver_instance_cache : DriverInstanceCache,device : Device,
-    device_uuid):
-        bgpls_instance=[driver for driver in device.device_drivers if DeviceDriverEnum.DEVICEDRIVER_BGPLS]
-        LOGGER.info(" (driverConnect) class bgpls: %s",bgpls_instance)
-        driver_filter_fields = get_device_driver_filter_fields(device)
-        connect_rules = get_connect_rules(device.device_config)
-        address  = connect_rules.get('address',  '127.0.0.1')
-        port     = connect_rules.get('port',     '0')
-        settings = connect_rules.get('settings', '{}')
-        driver : _Driver = driver_instance_cache.get(
-        device_uuid, filter_fields=driver_filter_fields, address=address, port=port, settings=settings)
-        LOGGER.info(" (driverConnect) driver: %s",driver)
-        bgpDriver=bgpls.BGPLSDriver("10.95.90.76",179,65006)
-        cwd = os.getcwd()
-        LOGGER.info("Current working directory:", cwd)
-        bgpDriver.setPeer()
-        bgpDriver.runThreads()
-        driver.Connect()
-        return
diff --git a/src/device/service/drivers/bgpls/protos/grpcService.proto b/src/device/service/drivers/bgpls/protos/grpcService.proto
deleted file mode 100644
index ef3642c30a301087189db9d1e1a2abba09ba209c..0000000000000000000000000000000000000000
--- a/src/device/service/drivers/bgpls/protos/grpcService.proto
+++ /dev/null
@@ -1,40 +0,0 @@
-syntax = "proto3";
-package src.main.proto;
-
-//el modulo java abre la comunicacion
-//cliente(java) manda la info al servidor(python)
-//el modulo en python responde con ok
-
-message updateRequest {
-
-  repeated nodeInfo node = 1;
-  // repeated : se da la posibilidad de mandar 0 o varios
-  repeated linkInfo link = 2;
-
-  // There are many more basics types, like Enum, Map
-  // See https://developers.google.com/protocol-buffers/docs/proto3
-  // for more information.
-}
-
-message nodeInfo{
-	string nodeName=1;
-	string nodeID=2;
-}
-
-message linkInfo{
-	string remoteID=1;
-	string localID=2;
-
-	string remoteIP=3;
-	string localIP=4;
-}
-
-message updateResponse {
-  string greeting = 1;
-}
-
-// Defining a Service, a Service can have multiple RPC operations
-service updateService {
-  // MODIFY HERE: Update the return to streaming return.
-  rpc update(updateRequest) returns (updateResponse);
-}
\ No newline at end of file
diff --git a/src/device/service/drivers/bgpls/protos/grpcService_pb2.py b/src/device/service/drivers/bgpls/protos/grpcService_pb2.py
deleted file mode 100644
index 47f75875c38186d9e578a96b103a3697a1cfeadf..0000000000000000000000000000000000000000
--- a/src/device/service/drivers/bgpls/protos/grpcService_pb2.py
+++ /dev/null
@@ -1,33 +0,0 @@
-# -*- coding: utf-8 -*-
-# Generated by the protocol buffer compiler.  DO NOT EDIT!
-# source: grpcService.proto
-"""Generated protocol buffer code."""
-from google.protobuf.internal import builder as _builder
-from google.protobuf import descriptor as _descriptor
-from google.protobuf import descriptor_pool as _descriptor_pool
-from google.protobuf import symbol_database as _symbol_database
-# @@protoc_insertion_point(imports)
-
-_sym_db = _symbol_database.Default()
-
-
-
-
-DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x11grpcService.proto\x12\x0esrc.main.proto\"_\n\rupdateRequest\x12&\n\x04node\x18\x01 \x03(\x0b\x32\x18.src.main.proto.nodeInfo\x12&\n\x04link\x18\x02 \x03(\x0b\x32\x18.src.main.proto.linkInfo\",\n\x08nodeInfo\x12\x10\n\x08nodeName\x18\x01 \x01(\t\x12\x0e\n\x06nodeID\x18\x02 \x01(\t\"P\n\x08linkInfo\x12\x10\n\x08remoteID\x18\x01 \x01(\t\x12\x0f\n\x07localID\x18\x02 \x01(\t\x12\x10\n\x08remoteIP\x18\x03 \x01(\t\x12\x0f\n\x07localIP\x18\x04 \x01(\t\"\"\n\x0eupdateResponse\x12\x10\n\x08greeting\x18\x01 \x01(\t2X\n\rupdateService\x12G\n\x06update\x12\x1d.src.main.proto.updateRequest\x1a\x1e.src.main.proto.updateResponseb\x06proto3')
-
-_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
-_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'grpcService_pb2', globals())
-if _descriptor._USE_C_DESCRIPTORS == False:
-
-  DESCRIPTOR._options = None
-  _UPDATEREQUEST._serialized_start=37
-  _UPDATEREQUEST._serialized_end=132
-  _NODEINFO._serialized_start=134
-  _NODEINFO._serialized_end=178
-  _LINKINFO._serialized_start=180
-  _LINKINFO._serialized_end=260
-  _UPDATERESPONSE._serialized_start=262
-  _UPDATERESPONSE._serialized_end=296
-  _UPDATESERVICE._serialized_start=298
-  _UPDATESERVICE._serialized_end=386
-# @@protoc_insertion_point(module_scope)
diff --git a/src/device/service/drivers/bgpls/protos/grpcService_pb2_grpc.py b/src/device/service/drivers/bgpls/protos/grpcService_pb2_grpc.py
deleted file mode 100644
index c8bbda558d60b1108bfcb1ff60fbe755bb2d75c3..0000000000000000000000000000000000000000
--- a/src/device/service/drivers/bgpls/protos/grpcService_pb2_grpc.py
+++ /dev/null
@@ -1,70 +0,0 @@
-# Generated by the gRPC Python protocol compiler plugin. DO NOT EDIT!
-"""Client and server classes corresponding to protobuf-defined services."""
-import grpc
-
-from . import grpcService_pb2 as grpcService__pb2
-
-
-class updateServiceStub(object):
-    """Defining a Service, a Service can have multiple RPC operations
-    """
-
-    def __init__(self, channel):
-        """Constructor.
-
-        Args:
-            channel: A grpc.Channel.
-        """
-        self.update = channel.unary_unary(
-                '/src.main.proto.updateService/update',
-                request_serializer=grpcService__pb2.updateRequest.SerializeToString,
-                response_deserializer=grpcService__pb2.updateResponse.FromString,
-                )
-
-
-class updateServiceServicer(object):
-    """Defining a Service, a Service can have multiple RPC operations
-    """
-
-    def update(self, request, context):
-        """MODIFY HERE: Update the return to streaming return.
-        """
-        context.set_code(grpc.StatusCode.UNIMPLEMENTED)
-        context.set_details('Method not implemented!')
-        raise NotImplementedError('Method not implemented!')
-
-
-def add_updateServiceServicer_to_server(servicer, server):
-    rpc_method_handlers = {
-            'update': grpc.unary_unary_rpc_method_handler(
-                    servicer.update,
-                    request_deserializer=grpcService__pb2.updateRequest.FromString,
-                    response_serializer=grpcService__pb2.updateResponse.SerializeToString,
-            ),
-    }
-    generic_handler = grpc.method_handlers_generic_handler(
-            'src.main.proto.updateService', rpc_method_handlers)
-    server.add_generic_rpc_handlers((generic_handler,))
-
-
- # This class is part of an EXPERIMENTAL API.
-class updateService(object):
-    """Defining a Service, a Service can have multiple RPC operations
-    """
-
-    @staticmethod
-    def update(request,
-            target,
-            options=(),
-            channel_credentials=None,
-            call_credentials=None,
-            insecure=False,
-            compression=None,
-            wait_for_ready=None,
-            timeout=None,
-            metadata=None):
-        return grpc.experimental.unary_unary(request, target, '/src.main.proto.updateService/update',
-            grpcService__pb2.updateRequest.SerializeToString,
-            grpcService__pb2.updateResponse.FromString,
-            options, channel_credentials,
-            insecure, call_credentials, compression, wait_for_ready, timeout, metadata)
diff --git a/src/pathcomp/frontend/service/algorithms/tools/ConstantsMappings.py b/src/pathcomp/frontend/service/algorithms/tools/ConstantsMappings.py
index b38907668fd2faec199b5e2821efb1b8919e55da..8f40fec452a5dd0b4d3eb3e7805746d200e447cc 100644
--- a/src/pathcomp/frontend/service/algorithms/tools/ConstantsMappings.py
+++ b/src/pathcomp/frontend/service/algorithms/tools/ConstantsMappings.py
@@ -102,8 +102,6 @@ DEVICE_TYPE_TO_LAYER = {
     DeviceTypeEnum.EMULATED_OPTICAL_TRANSPONDER.value    : DeviceLayerEnum.OPTICAL_DEVICE,
     DeviceTypeEnum.OPTICAL_TRANSPONDER.value             : DeviceLayerEnum.OPTICAL_DEVICE,
 
-    DeviceTypeEnum.BGPLS_ASNUMBER.value                  : DeviceLayerEnum.APPLICATION_CONTROLLER, #TODO: value
-    DeviceTypeEnum.EMULATED_BGPLS_ASNUMBER.value         : DeviceLayerEnum.APPLICATION_CONTROLLER, #TODO:
 }
 
 DEVICE_LAYER_TO_SERVICE_TYPE = {
diff --git a/src/webui/Dockerfile b/src/webui/Dockerfile
index 7c718890fcf3f07b32f66eca2ecab41f2eb30fbb..795d5d7f7b5a7ba403599c467761f920959f264d 100644
--- a/src/webui/Dockerfile
+++ b/src/webui/Dockerfile
@@ -84,6 +84,8 @@ COPY --chown=webui:webui src/service/client/. service/client/
 COPY --chown=webui:webui src/slice/__init__.py slice/__init__.py
 COPY --chown=webui:webui src/slice/client/. slice/client/
 COPY --chown=webui:webui src/webui/. webui/
+COPY --chown=webui:webui src/bgpls_speaker/__init__.py bgpls_speaker/__init__.py
+COPY --chown=webui:webui src/bgpls_speaker/client/. bgpls_speaker/client/
 
 # Start the service
 ENTRYPOINT ["python", "-m", "webui.service"]
diff --git a/src/webui/service/device/routes.py b/src/webui/service/device/routes.py
index 32fc6babc8990bbb5dfd2868f60b11e35c369119..4c6a2a1189804be157eb96ba48a52bfd2d0c59cb 100644
--- a/src/webui/service/device/routes.py
+++ b/src/webui/service/device/routes.py
@@ -65,8 +65,10 @@ def add():
             (DeviceOperationalStatusEnum.Value(key), key.replace('DEVICEOPERATIONALSTATUS_', '')))
 
     # items for Device Type field
+    form.device_type.choices= []
     for device_type in DeviceTypeEnum:
-        form.device_type.choices.append((device_type.value,device_type.value))    
+        if device_type:
+            form.device_type.choices.append((device_type.value,device_type.value))    
 
     if form.validate_on_submit():
         device_obj = Device()
@@ -120,8 +122,6 @@ def add():
             device_drivers.append(DeviceDriverEnum.DEVICEDRIVER_ONF_TR_352)
         if form.device_drivers_xr.data:
             device_drivers.append(DeviceDriverEnum.DEVICEDRIVER_XR)
-        if form.device_drivers_bgpls.data:
-            device_drivers.append(DeviceDriverEnum.DEVICEDRIVER_BGPLS)
         device_obj.device_drivers.extend(device_drivers) # pylint: disable=no-member
 
         try:
diff --git a/src/webui/service/templates/topology/add.html b/src/webui/service/templates/topology/add.html
new file mode 100644
index 0000000000000000000000000000000000000000..317926383e6c2a7b858e1c87938a2c671c1afa49
--- /dev/null
+++ b/src/webui/service/templates/topology/add.html
@@ -0,0 +1,162 @@
+<!--
+ Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (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.
+-->
+
+{% extends 'base.html' %}
+
+{% block content %}
+<h1>Add New Device</h1>
+<h3>Node name: {{form.device_name}}</h3>
+<br />
+<form id="add_device" method="POST">
+    {{ form.hidden_tag() }}
+    <fieldset>
+        <div class="row mb-3">
+            {{ form.device_id.label(class="col-sm-2 col-form-label") }}
+            <div class="col-sm-10">
+                {% if form.device_id.errors %}
+                {{ form.device_id(class="form-control is-invalid") }}
+                <div class="invalid-feedback">
+                    {% for error in form.device_id.errors %}
+                    <span>{{ error }}</span>
+                    {% endfor %}
+                </div>
+                {% else %}
+                {{ form.device_id(class="form-control") }}
+                {% endif %}
+            </div>
+        </div>
+        <br />
+        <div class="row mb-3">
+            {{ form.device_type.label(class="col-sm-2 col-form-label") }}
+            <div class="col-sm-10">
+                {% if form.device_type.errors %}
+                {{ form.device_type(class="form-control is-invalid") }}
+                <div class="invalid-feedback">
+                    {% for error in form.device_type.errors %}
+                    <span>{{ error }}</span>
+                    {% endfor %}
+                </div>
+                {% else %}
+                {{ form.device_type(class="form-select")}}
+                {% endif %}
+            </div>
+        </div>
+        <br />
+        <div class="row mb-3">
+            {{ form.operational_status.label(class="col-sm-2 col-form-label") }}
+            <div class="col-sm-10">
+                {% if form.operational_status.errors %}
+                {{ form.operational_status(class="form-control is-invalid") }}
+                <div class="invalid-feedback">
+                    {% for error in form.operational_status.errors %}
+                    <span>{{ error }}</span>
+                    {% endfor %}
+                </div>
+                {% else %}
+                {{ form.operational_status(class="form-select") }}
+                {% endif %}
+            </div>
+        </div>
+        <br />
+        <div class="row mb-3">
+            <div class="col-sm-2 col-form-label">Drivers</div>
+            <div class="col-sm-10">
+                {% if form.device_drivers_undefined.errors %}
+                {{ form.device_drivers_undefined(class="form-control is-invalid") }}
+                <div class="invalid-feedback">
+                    {% for error in form.device_drivers_undefined.errors %}
+                    <span>{{ error }}</span>
+                    {% endfor %}
+                </div>
+                {% else %}
+                {{ form.device_drivers_undefined }} {{ form.device_drivers_undefined.label(class="col-sm-3
+                col-form-label") }}
+                {{ form.device_drivers_openconfig }} {{ form.device_drivers_openconfig.label(class="col-sm-3
+                col-form-label") }}
+                {{ form.device_drivers_transport_api }} {{ form.device_drivers_transport_api.label(class="col-sm-3
+                col-form-label") }}
+                <br />{{ form.device_drivers_p4 }} {{ form.device_drivers_p4.label(class="col-sm-3 col-form-label") }}
+                {{ form.device_drivers_ietf_network_topology }} {{
+                form.device_drivers_ietf_network_topology.label(class="col-sm-3
+                col-form-label") }}
+                {{ form.device_drivers_onf_tr_352 }} {{ form.device_drivers_onf_tr_352.label(class="col-sm-3
+                col-form-label") }}<br />
+                {{ form.device_drivers_xr }} {{ form.device_drivers_xr.label(class="col-sm-3
+                col-form-label") }}
+                {% endif %}
+            </div>
+        </div>
+        <br />
+        Configuration Rules <br />
+        <div class="row mb-3">
+            {{ form.device_config_address.label(class="col-sm-2 col-form-label") }}
+            <div class="col-sm-10">
+                {% if form.device_config_address.errors %}
+                {{ form.device_config_address(class="form-control is-invalid", rows=5) }}
+                <div class="invalid-feedback">
+                    {% for error in form.device_config_address.errors %}
+                    <span>{{ error }}</span>
+                    {% endfor %}
+                </div>
+                {% else %}
+                {{ form.device_config_address(class="form-control", rows=5) }}
+                {% endif %}
+            </div>
+        </div>
+        <div class="row mb-3">
+            {{ form.device_config_port.label(class="col-sm-2 col-form-label") }}
+            <div class="col-sm-10">
+                {% if form.device_config_port.errors %}
+                {{ form.device_config_port(class="form-control is-invalid", rows=5) }}
+                <div class="invalid-feedback">
+                    {% for error in form.device_config_port.errors %}
+                    <span>{{ error }}</span>
+                    {% endfor %}
+                </div>
+                {% else %}
+                {{ form.device_config_port(class="form-control", rows=5) }}
+                {% endif %}
+            </div>
+        </div>
+        <div class="row mb-3">
+            {{ form.device_config_settings.label(class="col-sm-2 col-form-label") }}
+            <div class="col-sm-10">
+                {% if form.device_config_settings.errors %}
+                {{ form.device_config_settings(class="form-control is-invalid", rows=5) }}
+                <div class="invalid-feedback">
+                    {% for error in form.device_config_settings.errors %}
+                    <span>{{ error }}</span>
+                    {% endfor %}
+                </div>
+                {% else %}
+                {{ form.device_config_settings(class="form-control", rows=5) }}
+                {% endif %}
+            </div>
+        </div>
+        <br />
+        <div class="d-grid gap-2 d-md-flex justify-content-md-start">
+            <button type="submit" class="btn btn-primary">
+                <i class="bi bi-plus-circle-fill"></i>
+                {{ submit_text }}
+            </button>
+            <button type="button" class="btn btn-block btn-secondary" onclick="javascript: history.back()">
+                <i class="bi bi-box-arrow-in-left"></i>
+                Cancel
+            </button>
+        </div>
+    </fieldset>
+</form>
+{% endblock %}
\ No newline at end of file
diff --git a/src/webui/service/templates/topology/addSpeaker.html b/src/webui/service/templates/topology/addSpeaker.html
new file mode 100644
index 0000000000000000000000000000000000000000..26ec8c94e59b72d5cc153ac70617ece7ab48119e
--- /dev/null
+++ b/src/webui/service/templates/topology/addSpeaker.html
@@ -0,0 +1,88 @@
+<!--
+    Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (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.
+   -->
+
+{% extends 'base.html' %}
+
+{% block content %}
+     <h1>Add Device </h1>
+     <!-- TEST -->
+     <h5>New bglps speaker</h5>
+     
+      <br />
+     <div>
+          <form action='{{ url_for("topology.addSpeaker")}}' method="post">
+               {{ form.hidden_tag() }}
+               <fieldset>
+                    <div class="row mb-3">
+                         {{ form.speaker_address.label(class="col-sm-2 col-form-label") }}
+                         <div class="col-sm-10">
+                         {% if form.speaker_address.errors %}
+                         {{ form.speaker_address(class="form-control is-invalid") }}
+                         <div class="invalid-feedback">
+                              {% for error in form.speaker_address.errors %}
+                              <span>{{ error }}</span>
+                              {% endfor %}
+                         </div>
+                         {% else %}
+                         {{ form.speaker_address(class="form-control") }}
+                         {% endif %}
+                         </div>
+                    </div>
+                    <div class="row mb-3">
+                         {{ form.speaker_port.label(class="col-sm-2 col-form-label") }}
+                         <div class="col-sm-10">
+                         {% if form.speaker_port.errors %}
+                         {{ form.speaker_port(class="form-control is-invalid") }}
+                         <div class="invalid-feedback">
+                              {% for error in form.speaker_port.errors %}
+                              <span>{{ error }}</span>
+                              {% endfor %}
+                         </div>
+                         {% else %}
+                         {{ form.speaker_port(class="form-control") }}
+                         {% endif %}
+                         </div>
+                    </div>
+                    <div class="row mb-3">
+                         {{ form.speaker_as.label(class="col-sm-2 col-form-label") }}
+                         <div class="col-sm-10">
+                         {% if form.speaker_as.errors %}
+                         {{ form.speaker_as(class="form-control is-invalid") }}
+                         <div class="invalid-feedback">
+                              {% for error in form.speaker_as.errors %}
+                              <span>{{ error }}</span>
+                              {% endfor %}
+                         </div>
+                         {% else %}
+                         {{ form.speaker_as(class="form-control") }}
+                         {% endif %}
+                         </div>
+                    </div>
+               </fieldset>
+          <button type="submit" class="btn btn-primary">
+               <i class="bi bi-plus-circle-fill"></i>
+               Add Speaker
+               </button>
+          </form>
+     </div>
+     
+
+     <script src="https://d3js.org/d3.v4.min.js"></script>
+     <div id="topology"></div>
+     <script src="{{ url_for('js.topology_js') }}"></script>
+
+{% endblock %}
+   
\ No newline at end of file
diff --git a/src/webui/service/templates/topology/detail.html b/src/webui/service/templates/topology/detail.html
deleted file mode 100644
index aad221c85e73b98869b90f59117228b77c02fa43..0000000000000000000000000000000000000000
--- a/src/webui/service/templates/topology/detail.html
+++ /dev/null
@@ -1,37 +0,0 @@
-<!--
-    Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (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.
-   -->
-
-{% extends 'base.html' %}
-
-{% block content %}
-     <h1>Device {{ device.name }} ({{ device.device_id.device_uuid.uuid }})</h1>
-     <!-- TEST -->
-     <h5>Type: {{ device.device_type }}</h5>
-     <div>
-          <label for="nombre">Device IP:</label>
-          <input type="text" id="ip" name="ip">
-          <label for="nombre">Device User:</label>
-          <input type="text" id="user" name="user">
-          <label for="nombre">Device Password:</label>
-          <input type="text" id="pass" name="pass">
-     </div>
-
-     <script src="https://d3js.org/d3.v4.min.js"></script>
-     <div id="topology"></div>
-     <script src="{{ url_for('js.topology_js') }}"></script>
-
-{% endblock %}
-   
\ No newline at end of file
diff --git a/src/webui/service/templates/topology/editSpeakers.html b/src/webui/service/templates/topology/editSpeakers.html
new file mode 100644
index 0000000000000000000000000000000000000000..f98c453199d40865c7d8501344808cecf5a4e1a6
--- /dev/null
+++ b/src/webui/service/templates/topology/editSpeakers.html
@@ -0,0 +1,70 @@
+<!--
+ Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (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.
+-->
+
+
+{% extends 'base.html' %}
+{% block content %}
+    <h1>Topology</h1>
+
+    <div class="row">
+       
+        <div class="col">
+            {{ speakers | length }} speakers found in context <i>{{ session['context_uuid'] }}</i>
+        </div>
+    </div>
+    
+    <div class="col">
+        <a href="{{ url_for('topology.addSpeaker') }}" class="btn btn-primary" style="margin-bottom: 10px;">
+            <i class="bi bi-plus"></i>
+            Add BGPLS Speaker
+        </a>
+    </div>
+    
+     <table class="table table-striped table-hover">
+          <thead>
+          <tr>
+          <th scope="col">Speaker IP Address</th>
+          <th scope="col">Speaker As Number</th>
+          <th scope="col"></th>
+          </tr>
+          </thead>
+          <tbody>
+          {% if speakers %}
+               {% for speaker in speakers %}
+               <tr>
+                    <td>{{ speaker.address }}</td>
+                    <td>{{ speaker.asNumber }}</td>
+                    <td>
+                         <a type="button" class="btn btn-danger" href="{{ url_for('topology.disconnectSpeaker',speaker_address=speaker.address)}}">
+                              <i class="bi bi-x-square"></i>
+                         </a>
+                              
+                    </td>
+               </tr>
+               {% endfor %}
+          {% else %}
+               <tr>
+                    <td colspan="3">No devices found</td>
+               </tr>
+          {% endif %}
+          </tbody>
+     </table>
+
+<script src="https://d3js.org/d3.v4.min.js"></script>
+    <div id="topology"></div>
+    <script src="{{ url_for('js.topology_js') }}"></script>
+
+{% endblock %}
\ No newline at end of file
diff --git a/src/webui/service/templates/topology/home.html b/src/webui/service/templates/topology/home.html
index 27b864d3bb6aefb9d1586838a2466238cbe83299..1603699436fb0bdb0e46310c166c8f17c8712110 100644
--- a/src/webui/service/templates/topology/home.html
+++ b/src/webui/service/templates/topology/home.html
@@ -22,34 +22,78 @@
     <div class="row">
        
         <div class="col">
-            {{ devices | length }} devices found in context <i>{{ session['context_uuid'] }}</i>
+            {{ speakers | length }} speakers found in context <i>{{ session['context_uuid'] }}</i>
         </div>
     </div>
-    
-    
+        <div class="row">
+        <div class="col">
+            <a href="{{ url_for('topology.addSpeaker') }}" class="btn btn-primary" style="margin-bottom: 10px;">
+                <i class="bi bi-plus"></i>
+                Add BGPLS Speaker
+            </a>
+        </div>
+
+        <div class="col">
+            <a href="{{ url_for('topology.editSpeakers') }}" class="btn btn-primary" style="margin-bottom: 10px;">
+                <i class="bi bi-pencil-square"></i>
+                Edit BGPLS Speakers
+            </a>
+        </div>
+    </div>  
+
     <table class="table table-striped table-hover">
         <thead>
           <tr>
-            <th scope="col">Name</th>
-            <th scope="col">Config Rules</th>
+            <th scope="col">Node name</th>
+            <th scope="col">Local IGP Id</th>
+            <th scope="col">Remote IGP Id</th>
+            <th scope="col">Learnt from</th>
             <th scope="col"></th>
           </tr>
         </thead>
         <tbody>
-            {% if devices %}
-                {% for device in devices %}
+            {% if disdev %}
+                {% for device in disdev %}
                 <tr>
-                    <td>{{ device.name }}</td>
-                    <td>{{ device.device_config.config_rules | length }}</td>
+                    <td>{{ device.nodeName }}</td>
+                    <td>{{ device.igpID }}</td>
+                    <td></td>
+                    <td>{{ device.learntFrom }}</td>
                     <td>
                         <div class="col">
-                            <a href="{{ url_for('topology.detail', device_uuid=device.device_id.device_uuid.uuid) }}">
+                            <a href='{{ url_for("topology.add",device_name=device.nodeName)}}'>
                                 <i class="bi bi-plus"></i>
                                 Add Device
                             </a>
                         </div>
                             
                     
+                    </td>
+                </tr>
+                {% endfor %}
+            {% else %}
+                <tr>
+                    <td colspan="3">No devices found</td>
+                </tr>
+            {% endif %}
+        </tbody>
+        <tbody>
+            {% if dislink %}
+                {% for link in dislink %}
+                <tr>
+                    <td></td>
+                    <td>{{ link.local.nodeName }}</td>
+                    <td>{{ link.remote.nodeName }}</td>
+                    <td>{{ link.learntFrom }}</td>
+                    <td>
+                        <div class="col">
+                            <a href=''>
+                                <i class="bi bi-plus"></i>
+                                Add Link
+                            </a>
+                        </div>
+                            
+                    
                     </td>
                 </tr>
                 {% endfor %}
diff --git a/src/webui/service/topology/forms.py b/src/webui/service/topology/forms.py
index ca039a9e2edbbd0176f513c150db6b120e3432ae..55c5d34d1de1e6fc715a99b3d7ceadcdd5d5f6c9 100644
--- a/src/webui/service/topology/forms.py
+++ b/src/webui/service/topology/forms.py
@@ -37,7 +37,6 @@ class AddDeviceForm(FlaskForm):
     device_drivers_ietf_network_topology = BooleanField('IETF_NETWORK_TOPOLOGY')
     device_drivers_onf_tr_352 = BooleanField('ONF_TR_352')
     device_drivers_xr = BooleanField('XR')
-    device_drivers_bgpls = BooleanField('BGPLS')
     device_config_address = StringField('connect/address',default='127.0.0.1',validators=[DataRequired(), Length(min=5)])
     device_config_port = StringField('connect/port',default='0',validators=[DataRequired(), Length(min=1)])
     device_config_settings = TextAreaField('connect/settings',default='{}',validators=[DataRequired(), Length(min=2)])
@@ -77,4 +76,11 @@ class DescriptorForm(FlaskForm):
         validators=[
             FileAllowed(['json'], 'JSON Descriptors only!')
         ])
+    submit = SubmitField('Submit')
+
+class SpeakerForm(FlaskForm):
+    
+    speaker_address = StringField('ip',default='127.0.0.1',validators=[DataRequired(), Length(min=5)])
+    speaker_port = StringField('port',default='179',validators=[DataRequired(), Length(min=1)])
+    speaker_as = StringField('as',default='65000',validators=[DataRequired(), Length(min=1)])
     submit = SubmitField('Submit')
\ No newline at end of file
diff --git a/src/webui/service/topology/routes.py b/src/webui/service/topology/routes.py
index 710461b47b5dd500995beacf5f6244be41b04886..498252cfb4665aff1a2cab77d64da5f41ea7bd13 100644
--- a/src/webui/service/topology/routes.py
+++ b/src/webui/service/topology/routes.py
@@ -12,22 +12,28 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import json
-from flask import current_app, render_template, Blueprint, flash, session, redirect, url_for
+import json,logging
+from flask import current_app, render_template, Blueprint, flash, session, redirect, url_for, request
 from common.proto.context_pb2 import (
-    ConfigActionEnum, Device, DeviceDriverEnum, DeviceId, DeviceList, DeviceOperationalStatusEnum, Empty, TopologyId)
+    ConfigActionEnum, ConfigRule, ConfigRule_Custom, Device, DeviceConfig, DeviceDriverEnum, DeviceId, DeviceList, DeviceOperationalStatusEnum, 
+    Empty, EndPoint, EndPointId, TopologyId, Uuid)
 from common.tools.object_factory.Context import json_context_id
 from common.tools.object_factory.Topology import json_topology_id
 from context.client.ContextClient import ContextClient
 from device.client.DeviceClient import DeviceClient
 from webui.service.device.forms import AddDeviceForm
 from common.DeviceTypes import DeviceTypeEnum
-from webui.service.topology.forms import ConfigForm
+from webui.service.topology.forms import ConfigForm, SpeakerForm
 from webui.service.topology.forms import UpdateDeviceForm
 
-topology = Blueprint('topology', __name__, url_prefix='/topoloy')
+from bgpls_speaker.client.BgplsClient import BgplsClient
+from common.proto.bgpls_pb2 import (BgplsSpeaker, DiscoveredDeviceList,DiscoveredDevice,DiscoveredLinkList,DiscoveredLink, NodeDescriptors)
+
+topology = Blueprint('topology', __name__, url_prefix='/topology')
 context_client = ContextClient()
 device_client = DeviceClient()
+bgpls_client = BgplsClient()
+logger = logging.getLogger(__name__)
 
 @topology.get('/')
 def home():
@@ -42,28 +48,57 @@ def home():
     json_topo_id = json_topology_id(topology_uuid, context_id=json_context_id(context_uuid))
     grpc_topology = context_client.GetTopology(TopologyId(**json_topo_id))
     topo_device_uuids = {device_id.device_uuid.uuid for device_id in grpc_topology.device_ids}
-    grpc_devices: DeviceList = context_client.ListDevices(Empty())
-    context_client.close()
+    
+    if grpc_topology is None:
+        flash('Context({:s})/Topology({:s}) not found'.format(str(context_uuid), str(topology_uuid)), 'danger')
+        devices = []
+    else:
+        topo_device_uuids = {device_id.device_uuid.uuid for device_id in grpc_topology.device_ids}
+        grpc_devices: DeviceList = context_client.ListDevices(Empty())
+        devices = [
+            device for device in grpc_devices.devices
+            if device.device_id.device_uuid.uuid in topo_device_uuids
+        ]
+
+    # ListNewDevices discovered from bgpls
+    logger.info('topology/home')
+    bgpls_client.connect()
+    logger.info('bgpls_client.connect %s',bgpls_client)
+    discovered_device_list = bgpls_client.ListDiscoveredDevices(Empty())
+    logger.info('discoveredDeviceList %s',discovered_device_list)
+    # List Links discovered from bgpls
+    discovered_link_list = bgpls_client.ListDiscoveredLinks(Empty())
+    logger.info('discoveredLinkList %s',discovered_link_list)
+    # List current open speaker connections
+    speaker_list=bgpls_client.ListBgplsSpeakers(Empty())
 
-    devices = [
-        device for device in grpc_devices.devices
-        if device.device_id.device_uuid.uuid in topo_device_uuids
-    ]
+
+    context_client.close()
+    bgpls_client.close()
 
     return render_template(
         'topology/home.html', devices=devices, dde=DeviceDriverEnum,
-        dose=DeviceOperationalStatusEnum)
-
-@topology.route('add', methods=['GET', 'POST'])
-def add():
+        dose=DeviceOperationalStatusEnum,disdev=discovered_device_list.discovereddevices,
+        dislink=discovered_link_list.discoveredlinks,speakers=speaker_list.speakers)
+
+@topology.route('add/<path:device_name>', methods=['GET', 'POST'])
+def add(device_name):
+    """"
+    Add a discovered device from bgpls protocol. Populate form from
+    existent info in bgpls. 
+    """
+    # TODO: Conect to device and get necessary info
     form = AddDeviceForm()
 
+    logger.info('topology/add')    
+    
     # listing enum values
     form.operational_status.choices = []
     for key, _ in DeviceOperationalStatusEnum.DESCRIPTOR.values_by_name.items():
         form.operational_status.choices.append(
             (DeviceOperationalStatusEnum.Value(key), key.replace('DEVICEOPERATIONALSTATUS_', '')))
-
+        
+    form.device_type.choices = []
     # items for Device Type field
     for device_type in DeviceTypeEnum:
         form.device_type.choices.append((device_type.value,device_type.value))    
@@ -71,23 +106,23 @@ def add():
     if form.validate_on_submit():
         device_obj = Device()
         # Device UUID: 
-        device_obj.device_id.device_uuid.uuid = form.device_id.data
+        device_obj.device_id.device_uuid.uuid = form.device_id.data # pylint: disable=no-member
 
         # Device type: 
         device_obj.device_type = str(form.device_type.data)
 
         # Device configurations: 
-        config_rule = device_obj.device_config.config_rules.add()
+        config_rule = device_obj.device_config.config_rules.add() # pylint: disable=no-member
         config_rule.action = ConfigActionEnum.CONFIGACTION_SET
         config_rule.custom.resource_key = '_connect/address'
         config_rule.custom.resource_value = form.device_config_address.data
 
-        config_rule = device_obj.device_config.config_rules.add()
+        config_rule = device_obj.device_config.config_rules.add() # pylint: disable=no-member
         config_rule.action = ConfigActionEnum.CONFIGACTION_SET
         config_rule.custom.resource_key = '_connect/port'
         config_rule.custom.resource_value = form.device_config_port.data
 
-        config_rule = device_obj.device_config.config_rules.add()
+        config_rule = device_obj.device_config.config_rules.add() # pylint: disable=no-member
         config_rule.action = ConfigActionEnum.CONFIGACTION_SET
         config_rule.custom.resource_key = '_connect/settings'
 
@@ -95,9 +130,10 @@ def add():
             device_config_settings = json.loads(form.device_config_settings.data)
         except: # pylint: disable=bare-except
             device_config_settings = form.device_config_settings.data
-
+        logger.info('(topology/add) config settings %s', form.device_config_settings.data)    
         if isinstance(device_config_settings, dict):
             config_rule.custom.resource_value = json.dumps(device_config_settings)
+            logger.info('(topology/add) config settings is instance to json')
         else:
             config_rule.custom.resource_value = str(device_config_settings)
 
@@ -119,19 +155,30 @@ def add():
             device_obj.device_drivers.append(DeviceDriverEnum.DEVICEDRIVER_ONF_TR_352)
         if form.device_drivers_xr.data:
             device_obj.device_drivers.append(DeviceDriverEnum.DEVICEDRIVER_XR)
-        if form.device_drivers_bgpls.data:
-            device_obj.device_drivers.append(DeviceDriverEnum.DEVICEDRIVER_BGPLS)
 
         try:
             device_client.connect()
+            logger.info('add device from speaker:%s',device_obj)
             response: DeviceId = device_client.AddDevice(device_obj)
             device_client.close()
             flash(f'New device was created with ID "{response.device_uuid.uuid}".', 'success')
+            bgpls_client.connect()
+            bgpls_client.NotifyAddNodeToContext(NodeDescriptors(nodeName=device_obj.device_id.device_uuid.uuid))
+            bgpls_client.close()
             return redirect(url_for('device.home'))
         except Exception as e:
             flash(f'Problem adding the device. {e.details()}', 'danger')
         
-    return render_template('device/add.html', form=form,
+    # Prefill data with discovered info from speaker
+    # Device Name from bgpls
+    form.device_name=device_name
+    device=device_name
+    form.device_id.data=device_name
+    # Default values (TODO: NOT WORKING)
+    form.device_type.data=DeviceTypeEnum.EMULATED_PACKET_ROUTER
+    form.device_config_settings.data=str('{"username": "admin", "password": "admin"}')
+
+    return render_template('topology/add.html', form=form, device=device,
                         submit_text='Add New Device')
 
 @topology.route('detail/<path:device_uuid>', methods=['GET', 'POST'])
@@ -145,88 +192,54 @@ def detail(device_uuid: str):
                                                  dde=DeviceDriverEnum,
                                                  dose=DeviceOperationalStatusEnum)
 
-@topology.get('<path:device_uuid>/delete')
-def delete(device_uuid):
-    try:
-
-        # first, check if device exists!
-        # request: DeviceId = DeviceId()
-        # request.device_uuid.uuid = device_uuid
-        # response: Device = client.GetDevice(request)
-        # TODO: finalize implementation
-
-        request = DeviceId()
-        request.device_uuid.uuid = device_uuid
-        device_client.connect()
-        response = device_client.DeleteDevice(request)
-        device_client.close()
-
-        flash(f'Device "{device_uuid}" deleted successfully!', 'success')
-    except Exception as e:
-        flash(f'Problem deleting device "{device_uuid}": {e.details()}', 'danger')
-        current_app.logger.exception(e)
-    return redirect(url_for('device.home'))
-
-@topology.route('<path:device_uuid>/addconfig', methods=['GET', 'POST'])
-def addconfig(device_uuid):
-    form = ConfigForm()
-    request = DeviceId()
-    request.device_uuid.uuid = device_uuid
-    context_client.connect()
-    response = context_client.GetDevice(request)
-    context_client.close()
-
+@topology.route('addSpeaker', methods=['GET', 'POST'])
+def addSpeaker():
+    # Conectar con bgpls¿
+    bgpls_client.connect()
+    form = SpeakerForm()
     if form.validate_on_submit():
-        device = Device()
-        device.CopyFrom(response)
-        config_rule = device.device_config.config_rules.add()
-        config_rule.action = ConfigActionEnum.CONFIGACTION_SET
-        config_rule.custom.resource_key = form.device_key_config.data
-        config_rule.custom.resource_value = form.device_value_config.data
-        try:
-            device_client.connect()
-            response: DeviceId = device_client.ConfigureDevice(device)
-            device_client.close()
-            flash(f'New configuration was created with ID "{response.device_uuid.uuid}".', 'success')
-            return redirect(url_for('device.home'))
-        except Exception as e:
-             flash(f'Problem adding the device. {e.details()}', 'danger')
+        logger.info('addSpeaker ip:%s',form.speaker_address.data)
+        bgpls_client.AddBgplsSpeaker(BgplsSpeaker(address=form.speaker_address.data,port=form.speaker_port.data,asNumber=form.speaker_as.data))
+        flash(f'Speaker "{form.speaker_address.data}:{form.speaker_port.data}" added successfully!', 'success')
+    bgpls_client.close()
+    return render_template('topology/addSpeaker.html',form=form)
+
+@topology.route('formSpeaker', methods=['GET','POST'])
+def formSpeaker():
+    # Conectar con bgpls¿
+    form = SpeakerForm()
+    if request.method=="POST":
+        address = form.speaker_address.data
+        port = form.speaker_port.data
+        as_ = form.speaker_as.data
+        logger.info("FORM formSpeaker: %s %s %s", address,port,as_)
+        
+        flash(f'Speaker "{address}:{port}" added successfully!', 'success')
 
-    return render_template('topology/addconfig.html', form=form,  submit_text='Add New Configuration')
+    return redirect(url_for('topology.home'))
+    # return 'Form submitted'
 
-@topology.route('updateconfig', methods=['GET', 'POST'])
-def updateconfig():
 
+@topology.route('editSpeakers', methods=['GET','POST'])
+def editSpeakers():
+
+    speakers=[]
+    bgpls_client.connect()
+    speaker_list=bgpls_client.ListBgplsSpeakers(Empty())
+    speakers_ids=[speaker for speaker in speaker_list.speakers if speaker.id]
+    speakers=[bgpls_client.GetSpeakerInfoFromId(ids) for ids in speakers_ids]
         
-    return render_template('topology/updateconfig.html')
+    bgpls_client.close()
+    return render_template('topology/editSpeakers.html',speakers=speakers)
 
 
-@topology.route('<path:device_uuid>/update', methods=['GET', 'POST'])
-def update(device_uuid):
-    form = UpdateDeviceForm()
-    request = DeviceId()
-    request.device_uuid.uuid = device_uuid
-    context_client.connect()
-    response = context_client.GetDevice(request)
-    context_client.close()
+@topology.route('disconnectSpeaker/<path:speaker_address>', methods=['GET','POST'])
+def disconnectSpeaker(speaker_address):
 
-    # listing enum values
-    form.update_operational_status.choices = []
-    for key, value in DeviceOperationalStatusEnum.DESCRIPTOR.values_by_name.items():
-        form.update_operational_status.choices.append((DeviceOperationalStatusEnum.Value(key), key.replace('DEVICEOPERATIONALSTATUS_', '')))
-
-    form.update_operational_status.default = response.device_operational_status
+    bgpls_client.connect()
+    current_speaker=BgplsSpeaker(address=speaker_address)
+    logger.info('Disconnecting speaker: %s...',speaker_address)
+    bgpls_client.DisconnectFromSpeaker(current_speaker)
+    bgpls_client.close()
 
-    if form.validate_on_submit():
-        device = Device()
-        device.CopyFrom(response)
-        device.device_operational_status = form.update_operational_status.data
-        try:
-            device_client.connect()
-            response: DeviceId = device_client.ConfigureDevice(device)
-            device_client.close()
-            flash(f'Status of device with ID "{response.device_uuid.uuid}" was updated.', 'success')
-            return redirect(url_for('device.home'))
-        except Exception as e:
-             flash(f'Problem updating the device. {e.details()}', 'danger')  
-    return render_template('topology/update.html', device=response, form=form, submit_text='Update Device')
+    return redirect(url_for('topology.editSpeakers'))
\ No newline at end of file