From ca8d23f90f679da71c99c2ef15e674b51c2509d9 Mon Sep 17 00:00:00 2001
From: ismaeel <mohammad.ismaael@cnit.it>
Date: Mon, 22 Apr 2024 05:16:33 +0000
Subject: [PATCH] Optical Link Integral

---
 .context.log.swp                              |  Bin 0 -> 8192 bytes
 config.lo                                     |    1 +
 deploy/tfs.sh                                 |    1 +
 my_deploy.sh                                  |    4 +-
 proto/context.proto                           |   54 +-
 src/common/tools/descriptor/Loader.py         |   15 +-
 src/context/client/ContextClient.py           |   30 +-
 .../service/ContextServiceServicerImpl.py     |   23 +-
 src/context/service/database/Device.py        |   37 +-
 src/context/service/database/Link.py          |    2 +
 src/context/service/database/OpticalConfig.py |    9 +-
 src/context/service/database/OpticalLink.py   |  194 ++
 src/context/service/database/Topology.py      |   11 +-
 .../service/database/models/DeviceModel.py    |    3 +
 .../database/models/OpticalEndPointModel.py   |   69 +
 .../database/models/OpticalLinkModel.py       |  149 +-
 .../service/database/models/TopologyModel.py  |   21 +
 .../service/database/uuids/EndPoint.py        |    5 +
 .../service/database/uuids/OpticalEndPoint.py |   45 +
 .../service/database/uuids/OpticalLink.py     |   21 +
 .../service/database/uuids/_Builder.py        |    4 +-
 .../oc_driver/templates/VPN/physical.py       |   28 +-
 src/opticalcontroller/Dockerfile              |   22 +-
 src/opticalcontroller/OpticalController.py    |   93 +-
 src/opticalcontroller/RSA.py                  |  383 ++--
 src/opticalcontroller/__init__.py             |    1 +
 src/opticalcontroller/dijsktra.py             |   20 +-
 src/opticalcontroller/json_files/nodes.json   |   32 +-
 src/opticalcontroller/json_files/tfs.json     | 1790 ++++++++++++-----
 .../json_files/tfs_dict.json                  | 1458 ++++++++++++++
 src/opticalcontroller/requirements.in         |   29 +-
 src/opticalcontroller/requirements_opt.txt    |    7 +
 src/opticalcontroller/test.py                 |   12 +
 src/opticalcontroller/tools.py                |   66 +-
 src/opticalcontroller/variables.py            |   16 +-
 .../service/ServiceServiceServicerImpl.py     |    3 +-
 src/service/service/__main__.py               |    7 +-
 src/service/service/tools/OpticalTools.py     |    8 +-
 src/tests/ofc24/r_t.sh                        |   31 +
 src/tests/ofc24/roadms.sh                     |   26 +
 src/tests/ofc24/tempOC/files/platform_r1.xml  |  121 +-
 src/tests/ofc24/tempOC/files/platform_r2.xml  |  133 +-
 src/tests/ofc24/{copy.sh => transponders.sh}  |    0
 src/webui/service/__init__.py                 |    6 +
 src/webui/service/base_optical/__init__.py    |   14 +
 src/webui/service/base_optical/route.py       |   29 +
 src/webui/service/main/routes.py              |   18 +-
 src/webui/service/optical_link/__init__.py    |   14 +
 src/webui/service/optical_link/routes.py      |   93 +
 src/webui/service/templates/base.html         |    6 +-
 .../service/templates/base_optical/home.html  |   40 +
 src/webui/service/templates/js/topology.js    |   15 +
 src/webui/service/templates/link/detail.html  |    3 +-
 src/webui/service/templates/link/home.html    |    2 +-
 .../templates/optical_link/detail.html        |  126 ++
 .../service/templates/optical_link/home.html  |   98 +
 .../service/templates/opticalconfig/home.html |   28 +-
 test.py                                       |   80 +-
 58 files changed, 4602 insertions(+), 954 deletions(-)
 create mode 100644 .context.log.swp
 create mode 100644 config.lo
 create mode 100644 src/context/service/database/OpticalLink.py
 create mode 100644 src/context/service/database/models/OpticalEndPointModel.py
 create mode 100644 src/context/service/database/uuids/OpticalEndPoint.py
 create mode 100644 src/context/service/database/uuids/OpticalLink.py
 create mode 100644 src/opticalcontroller/json_files/tfs_dict.json
 create mode 100644 src/opticalcontroller/requirements_opt.txt
 create mode 100644 src/opticalcontroller/test.py
 create mode 100644 src/tests/ofc24/r_t.sh
 create mode 100644 src/tests/ofc24/roadms.sh
 rename src/tests/ofc24/{copy.sh => transponders.sh} (100%)
 create mode 100644 src/webui/service/base_optical/__init__.py
 create mode 100644 src/webui/service/base_optical/route.py
 create mode 100644 src/webui/service/optical_link/__init__.py
 create mode 100644 src/webui/service/optical_link/routes.py
 create mode 100644 src/webui/service/templates/base_optical/home.html
 create mode 100644 src/webui/service/templates/optical_link/detail.html
 create mode 100644 src/webui/service/templates/optical_link/home.html

diff --git a/.context.log.swp b/.context.log.swp
new file mode 100644
index 0000000000000000000000000000000000000000..bab7729c124bd1a470885e2307011e49de2ddb1e
GIT binary patch
literal 8192
zcmeIuJqp4=5QgE2g`MEf1!Ao8V{CE-3(MFF24fSA=px$ajXaze&|O$l*ldwT;hko7
zmv4vRStrZ+!q1{qboE89tDp??Odij!sPbf9ouzZ(dFPDDO$TEWF4VD#i+Zm%7Zp|Y
z*8P<P0tmDg=*cXdCT7ee82h7P-g+Vf5I_I{1Q0*~0R#|0;C}?v!IQgQ_hoBfSNCl1
ie06(m+9%gMa6kY71Q0*~0R#|0009ILKmdWC6L<qCxgNv-

literal 0
HcmV?d00001

diff --git a/config.lo b/config.lo
new file mode 100644
index 000000000..f35fe4763
--- /dev/null
+++ b/config.lo
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"><interfaces xmlns="http://openconfig.net/yang/interfaces"><interface><name>eth0</name><config><name>eth0</name><enabled>true</enabled></config><ipv4 xmlns="http://openconfig.net/yang/interfaces/ip"><addresses><address><ip>192.168.1.1</ip><config><ip>192.168.1.1</ip><prefix-length>24</prefix-length></config></address></addresses></ipv4></interface></interfaces><components xmlns="http://openconfig.net/yang/platform"><component><name>channel-1</name><config><name>channel-1</name></config><state><name>channel-1</name><type xmlns:oc-opt-types="http://openconfig.net/yang/transport-types">oc-opt-types:OPTICAL_CHANNEL</type></state><optical-channel xmlns="http://openconfig.net/yang/terminal-device"><config><frequency>191600000</frequency><target-output-power>100.0</target-output-power><operational-mode>0</operational-mode><line-port>transceiver-1</line-port></config><state><frequency>191600000</frequency><target-output-power>0.0</target-output-power><operational-mode>0</operational-mode><line-port>transceiver-1</line-port><group-id>1</group-id><output-power><instant>0.0</instant><avg>0.0</avg><min>0.0</min><max>0.0</max><interval>0</interval></output-power><input-power><instant>0.0</instant><avg>0.0</avg><min>0.0</min><max>0.0</max><interval>0</interval></input-power><laser-bias-current><instant>0.0</instant><avg>0.0</avg><min>0.0</min><max>0.0</max><interval>0</interval></laser-bias-current><chromatic-dispersion><instant>0.0</instant><avg>0.0</avg><min>0.0</min><max>0.0</max></chromatic-dispersion><polarization-mode-dispersion><instant>0.0</instant><avg>0.0</avg><min>0.0</min><max>0.0</max></polarization-mode-dispersion><second-order-polarization-mode-dispersion><instant>0.0</instant><avg>0.0</avg><min>0.0</min><max>0.0</max></second-order-polarization-mode-dispersion><polarization-dependent-loss><instant>0.0</instant><avg>0.0</avg><min>0.0</min><max>0.0</max><interval>0</interval></polarization-dependent-loss></state></optical-channel></component><component><name>device</name><config><name>device</name></config><state><name>MellanoxSwitch</name><type xmlns:oc-platform-types="http://openconfig.net/yang/platform-types">oc-platform-types:OPERATING_SYSTEM</type><mfg-name>SSSA-CNIT</mfg-name><hardware-version>1.0.0</hardware-version><firmware-version>1.0.0</firmware-version><software-version>1.0.0</software-version><serial-no>610610</serial-no></state></component><component><name>port-1</name><config><name>port-1</name></config><state><name>port-1</name><type xmlns:oc-platform-types="http://openconfig.net/yang/platform-types">oc-platform-types:PORT</type></state><properties><property><name>odtn-port-type</name><config><name>odtn-port-type</name><value>line</value></config><state><name>odtn-port-type</name><value>line</value></state></property><property><name>onos-index</name><config><name>onos-index</name><value>4</value></config><state><name>onos-index</name><value>4</value></state></property></properties><subcomponents><subcomponent><name>channel-1</name><config><name>channel-1</name></config><state><name>channel-1</name></state></subcomponent></subcomponents></component><component><name>transceiver-1</name><config><name>transceiver-1</name></config><state><name>transceiver-1</name><type xmlns:oc-platform-types="http://openconfig.net/yang/platform-types">oc-platform-types:TRANSCEIVER</type></state><transceiver xmlns="http://openconfig.net/yang/platform/transceiver"><config><enabled>true</enabled><form-factor-preconf xmlns:oc-opt-types="http://openconfig.net/yang/transport-types">oc-opt-types:QSFP56_DD_TYPE1</form-factor-preconf><ethernet-pmd-preconf xmlns:oc-opt-types="http://openconfig.net/yang/transport-types">oc-opt-types:ETH_400GBASE_ZR</ethernet-pmd-preconf><fec-mode xmlns:oc-platform-types="http://openconfig.net/yang/platform-types">oc-platform-types:FEC_AUTO</fec-mode><module-functional-type xmlns:oc-opt-types="http://openconfig.net/yang/transport-types">oc-opt-types:TYPE_DIGITAL_COHERENT_OPTIC</module-functional-type></config><state><enabled>true</enabled><form-factor-preconf xmlns:oc-opt-types="http://openconfig.net/yang/transport-types">oc-opt-types:QSFP56_DD_TYPE1</form-factor-preconf><ethernet-pmd-preconf xmlns:oc-opt-types="http://openconfig.net/yang/transport-types">oc-opt-types:ETH_400GBASE_ZR</ethernet-pmd-preconf><fec-mode xmlns:oc-platform-types="http://openconfig.net/yang/platform-types">oc-platform-types:FEC_AUTO</fec-mode><module-functional-type xmlns:oc-opt-types="http://openconfig.net/yang/transport-types">oc-opt-types:TYPE_DIGITAL_COHERENT_OPTIC</module-functional-type><vendor>Cisco</vendor><vendor-part>400zr-QSFP-DD</vendor-part><vendor-rev>01</vendor-rev><serial-no>1567321</serial-no></state><physical-channels><channel><index>1</index><config><index>1</index><associated-optical-channel>channel-1</associated-optical-channel></config></channel></physical-channels></transceiver></component></components><bgp-instance xmlns="http://openconfig.net/yang/protocols"><bgp><neighbors><neighbor><neighbor-address>192.168.1.1</neighbor-address><config><neighbor-address>192.168.1.1</neighbor-address><neighbor-port>88</neighbor-port><enabled>true</enabled><peer-as>65432</peer-as></config></neighbor></neighbors></bgp></bgp-instance><terminal-device xmlns="http://openconfig.net/yang/terminal-device"><logical-channels><channel><index>1</index><config><index>1</index><description>Logical channel 1</description><admin-state>DISABLED</admin-state><logical-channel-type xmlns:oc-opt-types="http://openconfig.net/yang/transport-types">oc-opt-types:PROT_OTN</logical-channel-type><loopback-mode>NONE</loopback-mode></config><state><index>1</index><description>Logical channel 1</description><admin-state>DISABLED</admin-state><logical-channel-type xmlns:oc-opt-types="http://openconfig.net/yang/transport-types">oc-opt-types:PROT_OTN</logical-channel-type><loopback-mode>NONE</loopback-mode><link-state>UP</link-state></state><ingress><config><transceiver>transceiver-1</transceiver></config><state><transceiver>transceiver-1</transceiver></state></ingress><logical-channel-assignments><assignment><index>1</index><config><index>1</index><description>Optical channel assigned 100</description><assignment-type>OPTICAL_CHANNEL</assignment-type><optical-channel>channel-1</optical-channel><allocation>100.0</allocation></config><state><index>1</index><description>Optical channel assigned 100</description><assignment-type>OPTICAL_CHANNEL</assignment-type><optical-channel>channel-1</optical-channel><allocation>100.0</allocation></state></assignment></logical-channel-assignments></channel></logical-channels><operational-modes><mode><mode-id>1</mode-id><state><mode-id>1</mode-id><description>FEC1</description><vendor-id>Ericsson</vendor-id></state></mode><mode><mode-id>2</mode-id><state><mode-id>2</mode-id><description>FEC2</description><vendor-id>Ericsson</vendor-id></state></mode></operational-modes></terminal-device><aaa xmlns="http://tail-f.com/ns/aaa/1.1"><authentication><users><user><name>admin</name><uid>9000</uid><gid>100</gid><password>$1$HWfCFyTg$TOxt04aLi5ONWrSB8X94U.</password><ssh_keydir>/var/confd/homes/admin/.ssh</ssh_keydir><homedir>/var/confd/homes/admin</homedir></user><user><name>oper</name><uid>9003</uid><gid>103</gid><password>$1$D8R6MYXb$ah52S1b/zOYSlbVU9MS/21</password><ssh_keydir>/var/confd/homes/oper/.ssh</ssh_keydir><homedir>/var/confd/homes/oper</homedir></user><user><name>optical</name><uid>9001</uid><gid>101</gid><password>$1$qJM5YOJZ$Y1ECCKsRIgMFJBk.hrjkv1</password><ssh_keydir>/var/confd/homes/optical/.ssh</ssh_keydir><homedir>/var/confd/homes/optical</homedir></user><user><name>packet</name><uid>9002</uid><gid>102</gid><password>$1$Fmz.hLNd$8yG5nYZhSPNPjinrCWId8.</password><ssh_keydir>/var/confd/homes/packet/.ssh</ssh_keydir><homedir>/var/confd/homes/packet</homedir></user><user><name>private</name><uid>9005</uid><gid>103</gid><password>$1$4uQVo9HU$xjyOZc8JhotXBtfcFV7MX.</password><ssh_keydir>/var/confd/homes/private/.ssh</ssh_keydir><homedir>/var/confd/homes/private</homedir></user><user><name>public</name><uid>9004</uid><gid>100</gid><password>$1$YhqvvCDs$LAGH/GQUMGMbqTUMWpapD1</password><ssh_keydir>/var/confd/homes/public/.ssh</ssh_keydir><homedir>/var/confd/homes/public</homedir></user></users></authentication><ios><level><nr>0</nr><prompt>\h&gt; </prompt></level><level><nr>15</nr><prompt>\h# </prompt></level><privilege><mode>exec</mode><level><nr>0</nr><command><name>action</name></command><command><name>autowizard</name></command><command><name>enable</name></command><command><name>exit</name></command><command><name>help</name></command><command><name>startup</name></command></level><level><nr>15</nr><command><name>configure</name></command></level></privilege></ios></aaa><nacm xmlns="urn:ietf:params:xml:ns:yang:ietf-netconf-acm"><enable-nacm>true</enable-nacm><read-default>permit</read-default><write-default>permit</write-default><exec-default>permit</exec-default><enable-external-groups>true</enable-external-groups><groups><group><name>admin</name><user-name>admin</user-name><user-name>private</user-name></group><group><name>oper</name><user-name>oper</user-name><user-name>public</user-name></group><group><name>opt</name><user-name>optical</user-name></group><group><name>pck</name><user-name>packet</user-name></group></groups><rule-list><name>any-group</name><group>*</group><rule><name>get</name><module-name>*</module-name><path>/</path><access-operations>read</access-operations><action>permit</action></rule><rule><name>tailf-aaa-authentication</name><module-name>tailf-aaa</module-name><path>/aaa/authentication/users/user[name='$USER']</path><access-operations>read update</access-operations><action>permit</action></rule><rule><name>tailf-aaa-user</name><module-name>tailf-aaa</module-name><path>/user[name='$USER']</path><access-operations>create read update delete</access-operations><action>permit</action></rule><rule><name>tailf-webui-user</name><module-name>tailf-webui</module-name><path>/webui/data-stores/user-profile[username='$USER']</path><access-operations>create read update delete</access-operations><action>permit</action></rule></rule-list><rule-list><name>packet</name><group>pck</group><rule><name>vlan</name><module-name>vlan</module-name><path>/switched-vlans</path><access-operations>create read update delete</access-operations><action>permit</action></rule><rule><name>terminal-device</name><module-name>*</module-name><path>/terminal-device</path><access-operations>create update delete</access-operations><action>deny</action></rule><rule><name>components</name><module-name>*</module-name><path>/components</path><access-operations>create update delete</access-operations><action>deny</action></rule></rule-list><rule-list><name>optical</name><group>opt</group><rule><name>terminal-device</name><module-name>*</module-name><path>/terminal-device</path><access-operations>create read update delete</access-operations><action>permit</action></rule><rule><name>components</name><module-name>*</module-name><path>/components</path><access-operations>create read update delete</access-operations><action>permit</action></rule><rule><name>vlan</name><module-name>vlan</module-name><path>/switched-vlans</path><access-operations>create update delete</access-operations><action>deny</action></rule></rule-list><rule-list><name>admin</name><group>admin</group><rule><name>any-access</name><action>permit</action></rule></rule-list></nacm></data>
diff --git a/deploy/tfs.sh b/deploy/tfs.sh
index fd49c9758..96c1b6186 100755
--- a/deploy/tfs.sh
+++ b/deploy/tfs.sh
@@ -368,6 +368,7 @@ printf "\n"
 for COMPONENT in $TFS_COMPONENTS; do
     echo "Waiting for '$COMPONENT' component..."
     COMPONENT_OBJNAME=$(echo "${COMPONENT}" | sed "s/\_/-/")
+ 
     kubectl wait --namespace $TFS_K8S_NAMESPACE \
         --for='condition=available' --timeout=90s deployment/${COMPONENT_OBJNAME}service
     WAIT_EXIT_CODE=$?
diff --git a/my_deploy.sh b/my_deploy.sh
index 9e4447349..7bb15dd96 100755
--- a/my_deploy.sh
+++ b/my_deploy.sh
@@ -20,7 +20,7 @@
 export TFS_REGISTRY_IMAGES="http://localhost:32000/tfs/"
 
 # Set the list of components, separated by spaces, you want to build images for, and deploy.
-export TFS_COMPONENTS="context device pathcomp opticalcontroller service slice nbi webui "
+export TFS_COMPONENTS="context device pathcomp opticalcontroller service slice  webui "
 
 # Uncomment to activate Monitoring
 #export TFS_COMPONENTS="${TFS_COMPONENTS} monitoring"
@@ -102,7 +102,7 @@ export CRDB_DEPLOY_MODE="single"
 export CRDB_DROP_DATABASE_IF_EXISTS=""
 
 # Disable flag for re-deploying CockroachDB from scratch.
-export CRDB_REDEPLOY=""
+export CRDB_REDEPLOY="YES"
 
 
 # ----- NATS -------------------------------------------------------------------
diff --git a/proto/context.proto b/proto/context.proto
index 55c412119..465e235d4 100644
--- a/proto/context.proto
+++ b/proto/context.proto
@@ -83,9 +83,10 @@ service ContextService {
   rpc DeleteOpticalConfig(OpticalConfigId) returns (Empty         ) {}
 
   rpc SetOpticalLink     (OpticalLink    ) returns (Empty                 ) {}
-  rpc GetOpticalLink     (OpticalLinkId  ) returns (OpticalLink           ) {}
-  rpc GetFiber           (FiberId        ) returns (Fiber                 ) {}
-}
+  rpc GetOpticalLink     (LinkId  ) returns (OpticalLink           ) {}
+  rpc DeleteOpticalLink           (LinkId        ) returns (Empty                 ) {}
+  rpc GetOpticalLinkList (Empty)    returns (OpticalLinkList)                {}
+ }
 
 // ----- Generic -------------------------------------------------------------------------------------------------------
 message Empty {}
@@ -149,6 +150,8 @@ message Topology {
   string name = 2;
   repeated DeviceId device_ids = 3;
   repeated LinkId link_ids = 4;
+
+  repeated LinkId optical_link_ids=5;
 }
 
 message TopologyDetails {
@@ -156,6 +159,8 @@ message TopologyDetails {
   string name = 2;
   repeated Device devices = 3;
   repeated Link links = 4;
+  
+  repeated OpticalLink optical_links =5 ;
 }
 
 message TopologyIdList {
@@ -647,37 +652,34 @@ message OpticalConfigEvent {
 
 // ---- Optical Link ----
 
-message OpticalLinkId {
-  Uuid optical_link_uuid = 1;
+message OpticalEndPointId {
+  
+  DeviceId device_id = 2;
+  Uuid endpoint_uuid = 3;
 }
 
-message FiberId {
-  Uuid fiber_uuid = 1;
-}
 
-message Fiber {
-  string ID = 10;
-  string src_port = 1;
-  string dst_port = 2;
-  string local_peer_port =  3;
-  string remote_peer_port = 4;
-  repeated int32 c_slots = 5;
-  repeated int32 l_slots = 6;
-  repeated int32 s_slots = 7;
-  float length = 8;
-  bool used = 9;
-  FiberId fiber_uuid = 11;
- 
+message OpticalLinkList {
+  repeated OpticalLink optical_links = 1;
 }
+
+
+
 message OpticalLinkDetails {
   float length = 1;
-  string source = 2;
-  string target = 3;
-  repeated Fiber fibers = 4;
+  string src_port = 2;
+  string dst_port = 3;
+  string local_peer_port = 4;
+  string remote_peer_port = 5 ;
+  bool used = 6 ; 
+  map< string ,int32 > c_slots = 7;
+  map< string ,int32 > l_slots = 8;
+  map< string ,int32 > s_slots = 9;
 }
 
 message OpticalLink {
   string name = 1;
-  OpticalLinkDetails details = 2;
-  OpticalLinkId optical_link_uuid = 3;
+  OpticalLinkDetails optical_details = 2;
+  LinkId link_id = 3;
+ repeated EndPointId link_endpoint_ids=4;
 }
diff --git a/src/common/tools/descriptor/Loader.py b/src/common/tools/descriptor/Loader.py
index 4ab33beae..6def79da6 100644
--- a/src/common/tools/descriptor/Loader.py
+++ b/src/common/tools/descriptor/Loader.py
@@ -37,7 +37,7 @@ import concurrent.futures, json, logging, operator
 from typing import Any, Dict, List, Optional, Tuple, Union
 from common.proto.context_pb2 import (
     Connection, Context, ContextId, Device, DeviceId, Empty, Link, LinkId, Service, ServiceId, Slice, SliceId,
-    Topology, TopologyId)
+    Topology, TopologyId , OpticalLink)
 from common.tools.object_factory.Context import json_context_id
 from context.client.ContextClient import ContextClient
 from device.client.DeviceClient import DeviceClient
@@ -107,6 +107,12 @@ class DescriptorLoader:
         self.__services    = self.__descriptors.get('services'   , [])
         self.__slices      = self.__descriptors.get('slices'     , [])
         self.__connections = self.__descriptors.get('connections', [])
+        
+        #--------------- Experimental Optical Link --------------
+        
+        self.__optical_links = self.__descriptors.get("optical_links",[])
+        
+        
 
         self.__contexts_add   = None
         self.__topologies_add = None
@@ -211,6 +217,10 @@ class DescriptorLoader:
 
     @property
     def num_connections(self) -> int: return len(self.__connections)
+    
+    #------------- Experimental ---------------
+    @property
+    def optical_links(self) -> List[Dict]: return self.__optical_links
 
     def process(self) -> TypeResults:
         # Format CustomConfigRules in Devices, Services and Slices provided in JSON format
@@ -282,6 +292,9 @@ class DescriptorLoader:
         self._process_descr('service',    'update', self.__svc_cli.UpdateService,   Service,  self.__services      )
         self._process_descr('slice',      'add',    self.__slc_cli.CreateSlice,     Slice,    self.__slices_add    )
         self._process_descr('slice',      'update', self.__slc_cli.UpdateSlice,     Slice,    self.__slices        )
+        
+        #----------------------------------- Experimental ---------------------------------------
+        self._process_descr('link',       'add',    self.__ctx_cli.SetOpticalLink,         OpticalLink,     self.__optical_links         )
 
         # By default the Context component automatically assigns devices and links to topologies based on their
         # endpoints, and assigns topologies, services, and slices to contexts based on their identifiers.
diff --git a/src/context/client/ContextClient.py b/src/context/client/ContextClient.py
index 3ca4ea16a..b325bece3 100644
--- a/src/context/client/ContextClient.py
+++ b/src/context/client/ContextClient.py
@@ -27,7 +27,7 @@ from common.proto.context_pb2 import (
     Service, ServiceEvent, ServiceFilter, ServiceId, ServiceIdList, ServiceList,
     Slice, SliceEvent, SliceFilter, SliceId, SliceIdList, SliceList,
     Topology, TopologyDetails, TopologyEvent, TopologyId, TopologyIdList, TopologyList,
-    OpticalConfig, OpticalConfigId, OpticalConfigList
+    OpticalConfig, OpticalConfigId, OpticalConfigList , OpticalLink ,OpticalLinkList
 )
 from common.proto.context_pb2_grpc import ContextServiceStub
 from common.proto.context_policy_pb2_grpc import ContextPolicyServiceStub
@@ -467,3 +467,31 @@ class ContextClient:
         response = self.stub.DeleteOpticalConfig(request)
         LOGGER.debug('DeleteOpticalConfig result: {:s}'.format(grpc_message_to_json_string(response)))
         return response
+    
+    #--------------------------- Optical Link ------------------------
+    def GetOpticalLinkList(self, request: Empty) -> OpticalLinkList:
+        LOGGER.debug('ListOpticalLinks request: {:s}'.format(grpc_message_to_json_string(request)))
+        response = self.stub.GetOpticalLinkList(request)
+        LOGGER.debug('ListOpticalLinks result: {:s}'.format(grpc_message_to_json_string(response)))
+        return response
+
+    @RETRY_DECORATOR
+    def GetOpticalLink(self, request: LinkId) -> OpticalLink:
+        LOGGER.debug('GetOpticalLink request: {:s}'.format(grpc_message_to_json_string(request)))
+        response = self.stub.GetOpticalLink(request)
+        LOGGER.debug('GetOpticalLink result: {:s}'.format(grpc_message_to_json_string(response)))
+        return response
+
+    @RETRY_DECORATOR
+    def SetOpticalLink(self, request: OpticalLink) -> LinkId:
+        LOGGER.debug('SetOpticalLink request: {:s}'.format(grpc_message_to_json_string(request)))
+        response = self.stub.SetOpticalLink(request)
+        LOGGER.debug('SetOpticalLink result: {:s}'.format(grpc_message_to_json_string(response)))
+        return response
+
+    @RETRY_DECORATOR
+    def DeleteOpticalLink(self, request: LinkId) -> Empty:
+        LOGGER.debug('RemoveOpticalLink request: {:s}'.format(grpc_message_to_json_string(request)))
+        response = self.stub.DeleteOpticalLink(request)
+        LOGGER.debug('RemoveOpticalLink result: {:s}'.format(grpc_message_to_json_string(response)))
+        return response
\ No newline at end of file
diff --git a/src/context/service/ContextServiceServicerImpl.py b/src/context/service/ContextServiceServicerImpl.py
index 2b6c61ebe..e75f3a5c7 100644
--- a/src/context/service/ContextServiceServicerImpl.py
+++ b/src/context/service/ContextServiceServicerImpl.py
@@ -24,7 +24,7 @@ from common.proto.context_pb2 import (
     Service, ServiceEvent, ServiceFilter, ServiceId, ServiceIdList, ServiceList,
     Slice, SliceEvent, SliceFilter, SliceId, SliceIdList, SliceList,
     Topology, TopologyDetails, TopologyEvent, TopologyId, TopologyIdList, TopologyList,
-    OpticalConfigList, OpticalConfigId, OpticalConfig 
+    OpticalConfigList, OpticalConfigId, OpticalConfig ,OpticalLink , OpticalLinkList, 
 )
 from common.proto.policy_pb2 import PolicyRuleIdList, PolicyRuleId, PolicyRuleList, PolicyRule
 from common.proto.context_pb2_grpc import ContextServiceServicer
@@ -47,6 +47,7 @@ from .database.Topology import (
     topology_delete, topology_get, topology_get_details, topology_list_ids, topology_list_objs, topology_set)
 from .database.OpticalConfig import set_opticalconfig, select_opticalconfig, get_opticalconfig ,delete_opticalconfig
 
+from .database.OpticalLink import optical_link_delete,optical_link_get,optical_link_list_objs,optical_link_set
 LOGGER = logging.getLogger(__name__)
 
 METRICS_POOL = MetricsPool('Context', 'RPC')
@@ -324,3 +325,23 @@ class ContextServiceServicerImpl(ContextServiceServicer, ContextPolicyServiceSer
         delete_opticalconfig(self.db_engine,self.messagebroker, request)
        
         return Empty()
+
+
+    #--------------------- Experimental Optical Link -------------------
+    
+    @safe_and_metered_rpc_method(METRICS_POOL, LOGGER)
+    def GetOpticalLinkList(self, request : Empty, context : grpc.ServicerContext) -> OpticalLinkList:
+        return optical_link_list_objs(self.db_engine)
+
+    @safe_and_metered_rpc_method(METRICS_POOL, LOGGER)
+    def GetOpticalLink(self, request : LinkId, context : grpc.ServicerContext) -> OpticalLink:
+        return optical_link_get(self.db_engine, request)
+
+    @safe_and_metered_rpc_method(METRICS_POOL, LOGGER)
+    def SetOpticalLink(self, request : Link, context : grpc.ServicerContext) -> LinkId:
+        return optical_link_set(self.db_engine, self.messagebroker, request)
+
+    @safe_and_metered_rpc_method(METRICS_POOL, LOGGER)
+    def DeleteOpticalLink(self, request : LinkId, context : grpc.ServicerContext) -> Empty:
+        return optical_link_delete(self.db_engine, self.messagebroker, request)
+
diff --git a/src/context/service/database/Device.py b/src/context/service/database/Device.py
index 6c3bd24e0..942e6f115 100644
--- a/src/context/service/database/Device.py
+++ b/src/context/service/database/Device.py
@@ -39,6 +39,7 @@ from .uuids.EndPoint import endpoint_get_uuid
 from .ConfigRule import compose_config_rules_data, upsert_config_rules
 from .Component import compose_components_data
 from .Events import notify_event_context, notify_event_device, notify_event_topology
+from .models.OpticalEndPointModel import OpticalEndPointModel
 
 LOGGER = logging.getLogger(__name__)
 
@@ -106,7 +107,8 @@ def device_set(db_engine : Engine, messagebroker : MessageBroker, request : Devi
     topology_uuids.add(topology_uuid)
 
     is_oc_driver = DeviceDriverEnum.DEVICEDRIVER_OC in set(request.device_drivers)
-
+    optical_endpoints_data : List[Dict] = list()
+    LOGGER.info(f"is_oc_driver {is_oc_driver}")
     endpoints_data : List[Dict] = list()
     for i, endpoint in enumerate(request.device_endpoints):
         endpoint_device_uuid = endpoint.endpoint_id.device_id.device_uuid.uuid
@@ -136,7 +138,21 @@ def device_set(db_engine : Engine, messagebroker : MessageBroker, request : Devi
             'created_at'       : now,
             'updated_at'       : now,
         })
-        LOGGER.info(f"endpoint data {endpoints_data}")
+        # ------------------- Experimental -----------------------
+       
+        if is_oc_driver:
+            
+            optical_endpoints_data.append({
+                    'endpoint_uuid'    : endpoint_uuid,
+                    'device_uuid'      : endpoint_device_uuid,
+                    'name'             : endpoint_name,
+                    'endpoint_type'    : endpoint.endpoint_type,
+                    'created_at'       : now,
+                    'updated_at'       : now,
+            })
+        
+        
+        
 
         if endpoint_topology_uuid not in topology_uuids:
             related_topologies.append({
@@ -192,6 +208,23 @@ def device_set(db_engine : Engine, messagebroker : MessageBroker, request : Devi
             stmt = stmt.returning(EndPointModel.created_at, EndPointModel.updated_at)
             endpoint_updates = session.execute(stmt).fetchall()
             updated_endpoints = any([(updated_at > created_at) for created_at,updated_at in endpoint_updates])
+        
+        #---------------------- Experimental ---------------------------------
+        
+        if len(optical_endpoints_data) > 0:
+            LOGGER.info(f"Optical endpoint data_ device_model {optical_endpoints_data}")
+            stmt = insert(OpticalEndPointModel).values(optical_endpoints_data)
+            stmt = stmt.on_conflict_do_update(
+                index_elements=[OpticalEndPointModel.endpoint_uuid],
+                set_=dict(
+                    name             = stmt.excluded.name,
+                    endpoint_type    = stmt.excluded.endpoint_type,
+                    updated_at       = stmt.excluded.updated_at,
+                )
+            )
+            stmt = stmt.returning(OpticalEndPointModel.created_at, OpticalEndPointModel.updated_at)
+            optical_endpoint_updates = session.execute(stmt).fetchall()
+            updated_optical_endpoints = any([(updated_at > created_at) for created_at,updated_at in endpoint_updates])    
 
         device_topology_ids = []
         if not updated or len(related_topologies) > 1:
diff --git a/src/context/service/database/Link.py b/src/context/service/database/Link.py
index ccc22a472..119571dd8 100644
--- a/src/context/service/database/Link.py
+++ b/src/context/service/database/Link.py
@@ -63,6 +63,7 @@ def link_get(db_engine : Engine, request : LinkId) -> Link:
     return Link(**obj)
 
 def link_set(db_engine : Engine, messagebroker : MessageBroker, request : Link) -> LinkId:
+    
     raw_link_uuid = request.link_id.link_uuid.uuid
     raw_link_name = request.name
     link_name = raw_link_uuid if len(raw_link_name) == 0 else raw_link_name
@@ -83,6 +84,7 @@ def link_set(db_engine : Engine, messagebroker : MessageBroker, request : Link)
 
     link_endpoints_data : List[Dict] = list()
     for i,endpoint_id in enumerate(request.link_endpoint_ids):
+        logging.info(f"links endpoint_id is {endpoint_id}")
         endpoint_topology_uuid, _, endpoint_uuid = endpoint_get_uuid(
             endpoint_id, allow_random=False)
 
diff --git a/src/context/service/database/OpticalConfig.py b/src/context/service/database/OpticalConfig.py
index 3884e5f57..281634df8 100644
--- a/src/context/service/database/OpticalConfig.py
+++ b/src/context/service/database/OpticalConfig.py
@@ -31,7 +31,7 @@ def get_opticalconfig(db_engine : Engine):
         results = session.query(OpticalConfigModel).all()
         
         for obj in results:
-            LOGGER.info(f"opticaln config obj from context {obj.dump()}")
+           
      
             optical_config = OpticalConfig()
             optical_config.config = json.dumps(obj.dump())
@@ -42,7 +42,7 @@ def get_opticalconfig(db_engine : Engine):
     return obj
 
 def set_opticalconfig(db_engine : Engine, request : OpticalConfig):
-    LOGGER.info(f"request {request} ")
+   
     opticalconfig_id = OpticalConfigId()
     opticalconfig_id.opticalconfig_uuid = request.opticalconfig_id.opticalconfig_uuid
     OpticalConfig_data = []
@@ -79,8 +79,7 @@ def set_opticalconfig(db_engine : Engine, request : OpticalConfig):
         )
             
        
-    LOGGER.info(f"optical config to set {OpticalConfig_data} ")
-    LOGGER.info(f"channels {channels}")
+
     def callback(session:Session)->bool:
         stmt = insert(OpticalConfigModel).values(OpticalConfig_data)
         
@@ -109,7 +108,7 @@ def set_opticalconfig(db_engine : Engine, request : OpticalConfig):
                 )
                 stmt = stmt.returning(OpticalChannelModel.channel_uuid)
                 opticalChannel_id = session.execute(stmt).fetchone()
-                LOGGER.info(f"new optical channel config {opticalChannel_id}")
+                
     opticalconfig_id = run_transaction(sessionmaker(bind=db_engine), callback)
     return {'opticalconfig_uuid': opticalconfig_id}
 
diff --git a/src/context/service/database/OpticalLink.py b/src/context/service/database/OpticalLink.py
new file mode 100644
index 000000000..b6efabbff
--- /dev/null
+++ b/src/context/service/database/OpticalLink.py
@@ -0,0 +1,194 @@
+# 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 datetime, logging
+from sqlalchemy.dialects.postgresql import insert
+from sqlalchemy.engine import Engine
+from sqlalchemy import inspect
+from sqlalchemy.orm import Session, selectinload, sessionmaker
+from sqlalchemy_cockroachdb import run_transaction
+from typing import Dict, List, Optional, Set, Tuple
+from common.proto.context_pb2 import Empty, EventTypeEnum, OpticalLink, LinkId, OpticalLinkList, TopologyId
+from common.message_broker.MessageBroker import MessageBroker
+from common.method_wrappers.ServiceExceptions import NotFoundException
+from common.tools.object_factory.Link import json_link_id
+from context.service.database.uuids.Topology import topology_get_uuid
+from .models.OpticalLinkModel import OpticalLinkModel,OpticalLinkEndPointModel 
+from .models.OpticalEndPointModel import OpticalEndPointModel
+from .models.TopologyModel import TopologyOpticalLinkModel, TopologyModel
+from .uuids.OpticalEndPoint import optical_endpoint_get_uuid
+from .uuids.Link import link_get_uuid
+from .uuids.OpticalLink import opticaldetail_get_uuid
+from .Events import notify_event_context, notify_event_link, notify_event_topology
+from .uuids.EndPoint import endpoint_get_uuid
+
+LOGGER = logging.getLogger(__name__)
+
+
+
+def optical_link_list_objs(db_engine : Engine) -> OpticalLinkList:
+    def callback(session : Session) -> List[Dict]:
+        obj_list : List[OpticalLinkModel] = session.query(OpticalLinkModel)\
+            .options(selectinload(OpticalLinkModel.opticallink_endpoints))\
+            .all()
+        return [obj.dump() for obj in obj_list]
+    links = run_transaction(sessionmaker(bind=db_engine), callback)
+    return OpticalLinkList(optical_links=links)
+
+def optical_link_get(db_engine : Engine, request : LinkId) -> OpticalLink:
+    link_uuid = link_get_uuid(request, allow_random=False)
+    def callback(session : Session) -> Optional[Dict]:
+        obj : Optional[OpticalLinkModel] = session.query(OpticalLinkModel)\
+            .options(selectinload(OpticalLinkModel.opticallink_endpoints))\
+            .filter_by(opticallink_uuid=link_uuid).one_or_none()
+        return None if obj is None else obj.dump()
+    obj = run_transaction(sessionmaker(bind=db_engine), callback)
+    if obj is None:
+        raw_link_uuid = request.link_uuid.uuid
+        raise NotFoundException('Optical Link', raw_link_uuid, extra_details=[
+            'link_uuid generated was: {:s}'.format(link_uuid)
+        ])
+    return OpticalLink(**obj)
+
+def optical_link_set(db_engine : Engine, messagebroker : MessageBroker, request : OpticalLink) -> LinkId:
+    raw_link_uuid = request.link_id.link_uuid.uuid
+    raw_link_name = request.name
+    link_name = raw_link_uuid if len(raw_link_name) == 0 else raw_link_name
+    link_uuid = link_get_uuid(request.link_id, link_name=link_name, allow_random=True)
+
+    now = datetime.datetime.utcnow()
+
+    # By default, always add link to default Context/Topology
+  
+    
+    topology_uuids : Set[str] = set()
+    related_topologies : List[Dict] = list()
+    _,topology_uuid = topology_get_uuid(TopologyId(), allow_random=False, allow_default=True)
+    related_topologies.append({
+        'topology_uuid': topology_uuid,
+        'optical_link_uuid'    : link_uuid,
+    })
+    topology_uuids.add(topology_uuid)
+    
+    link_endpoints_data : List[Dict] = list()
+    
+    for i,endpoint_id in enumerate(request.link_endpoint_ids):
+        endpoint_topology_uuid, endpoint_device_uuid, endpoint_uuid = endpoint_get_uuid(
+              endpoint_id, endpoint_name="", allow_random=True)
+
+        link_endpoints_data.append({
+            'link_uuid'    : link_uuid,
+            'endpoint_uuid': endpoint_uuid,
+           
+        })
+        
+        if endpoint_topology_uuid not in topology_uuids:
+            related_topologies.append({
+                'topology_uuid': endpoint_topology_uuid,
+                'optical_link_uuid'    : link_uuid,
+            })
+            topology_uuids.add(endpoint_topology_uuid)
+
+       
+
+
+    
+    optical_link_data = [{
+        'opticallink_uuid'     : link_uuid,
+        'name'                 : link_name,
+        'created_at'           : now,
+        'updated_at'           : now,
+        'length'               : request.optical_details.length,
+        "src_port"             : request.optical_details.src_port,
+        "dst_port"             : request.optical_details.dst_port,
+        "local_peer_port"      : request.optical_details.local_peer_port,
+        "remote_peer_port"     : request.optical_details.remote_peer_port,
+        "used"                 : request.optical_details.used,
+        "c_slots"              : request.optical_details.c_slots ,
+        "l_slots"              : request.optical_details.l_slots,
+        "s_slots"              : request.optical_details.s_slots,
+       
+    }]
+  
+    LOGGER.info(f"setting Optical link data {optical_link_data}")
+    def callback(session : Session) -> Tuple[bool, List[Dict]]:
+        stmt = insert(OpticalLinkModel).values(optical_link_data)
+        stmt = stmt.on_conflict_do_update(
+            index_elements=[OpticalLinkModel.opticallink_uuid],
+            set_=dict(
+                name           = stmt.excluded.name,
+                updated_at          = stmt.excluded.updated_at,
+            )
+        )
+        stmt = stmt.returning(OpticalLinkModel.created_at, OpticalLinkModel.updated_at)
+        created_at,updated_at = session.execute(stmt).fetchone()
+        updated = updated_at > created_at
+
+        updated_endpoints = False
+        
+   
+            
+        if len(link_endpoints_data) > 0:
+            LOGGER.info(f"from OpticalLink Model endpoint data {link_endpoints_data}")
+            stmt = insert(OpticalLinkEndPointModel).values(link_endpoints_data)
+            stmt = stmt.on_conflict_do_nothing(
+                index_elements=[OpticalLinkEndPointModel.link_uuid, OpticalLinkEndPointModel.endpoint_uuid]
+            )
+            link_endpoint_inserts = session.execute(stmt)
+            updated_endpoints = int(link_endpoint_inserts.rowcount) > 0
+
+        if not updated or len(related_topologies) > 1:
+            # Only update topology-link relations when link is created (not updated) or when endpoint_ids are
+            # modified (len(related_topologies) > 1).
+            stmt = insert(TopologyOpticalLinkModel).values(related_topologies)
+            stmt = stmt.on_conflict_do_nothing(
+                index_elements=[TopologyOpticalLinkModel.topology_uuid, TopologyOpticalLinkModel.optical_link_uuid]
+            )
+            stmt = stmt.returning(TopologyOpticalLinkModel.topology_uuid)
+            topology_uuids = session.execute(stmt).fetchall()
+
+            #LOGGER.warning('RAW topology_uuids={:s}'.format(str(topology_uuids)))
+            if len(topology_uuids) > 0:
+                topology_uuids = [topology_uuid[0] for topology_uuid in topology_uuids]
+                #LOGGER.warning('NEW topology_uuids={:s}'.format(str(topology_uuids)))
+                query = session.query(TopologyModel)
+                query = query.filter(TopologyModel.topology_uuid.in_(topology_uuids))
+                link_topologies : List[TopologyModel] = query.all()
+                link_topology_ids = [obj.dump_id() for obj in link_topologies]
+                #LOGGER.warning('link_topology_ids={:s}'.format(str(link_topology_ids)))
+
+       
+        return updated or updated_endpoints
+
+    updated = run_transaction(sessionmaker(bind=db_engine), callback )
+    link_id = json_link_id(link_uuid)
+    event_type = EventTypeEnum.EVENTTYPE_UPDATE if updated else EventTypeEnum.EVENTTYPE_CREATE
+    notify_event_link(messagebroker, event_type, link_id)
+
+    return LinkId(**link_id)
+
+def optical_link_delete(db_engine : Engine, messagebroker : MessageBroker, request : LinkId) -> Empty:
+    link_uuid = link_get_uuid(request, allow_random=False)
+    def callback(session : Session) -> bool:
+      
+        query = query.filter_by(link_uuid=link_uuid)
+       
+        num_deleted = session.query(OpticalLinkModel).filter_by(opticallink_uuid=link_uuid).delete()
+        return num_deleted > 0
+    deleted = run_transaction(sessionmaker(bind=db_engine), callback)
+    link_id = json_link_id(link_uuid)
+    if deleted:
+        notify_event_link(messagebroker, EventTypeEnum.EVENTTYPE_REMOVE, link_id)
+
+    return Empty()
diff --git a/src/context/service/database/Topology.py b/src/context/service/database/Topology.py
index e8f994155..c94d336a0 100644
--- a/src/context/service/database/Topology.py
+++ b/src/context/service/database/Topology.py
@@ -27,13 +27,15 @@ from common.tools.object_factory.Topology import json_topology_id
 from context.Config import ALLOW_EXPLICIT_ADD_DEVICE_TO_TOPOLOGY, ALLOW_EXPLICIT_ADD_LINK_TO_TOPOLOGY
 from .models.DeviceModel import DeviceModel
 from .models.LinkModel import LinkModel
-from .models.TopologyModel import TopologyDeviceModel, TopologyLinkModel, TopologyModel
+from .models.TopologyModel import TopologyDeviceModel, TopologyLinkModel, TopologyModel , TopologyOpticalLinkModel
 from .uuids.Context import context_get_uuid
 from .uuids.Device import device_get_uuid
 from .uuids.Link import link_get_uuid
 from .uuids.Topology import topology_get_uuid
 from .Events import notify_event_context, notify_event_topology
 
+from .models.OpticalLinkModel import OpticalLinkModel
+
 LOGGER = logging.getLogger(__name__)
 
 def topology_list_ids(db_engine : Engine, request : ContextId) -> TopologyIdList:
@@ -77,9 +79,10 @@ def topology_get_details(db_engine : Engine, request : TopologyId) -> TopologyDe
     _,topology_uuid = topology_get_uuid(request, allow_random=False)
     def callback(session : Session) -> Optional[Dict]:
         obj : Optional[TopologyModel] = session.query(TopologyModel)\
-            .options(selectinload(TopologyModel.topology_devices, TopologyDeviceModel.device, DeviceModel.endpoints))\
-            .options(selectinload(TopologyModel.topology_links, TopologyLinkModel.link, LinkModel.link_endpoints))\
-            .filter_by(topology_uuid=topology_uuid).one_or_none()
+                        .options(selectinload(TopologyModel.topology_devices, TopologyDeviceModel.device, DeviceModel.endpoints))\
+                        .options(selectinload(TopologyModel.topology_links, TopologyLinkModel.link, LinkModel.link_endpoints))\
+                        .options(selectinload(TopologyModel.topology_optical_links, TopologyOpticalLinkModel.optical_link, OpticalLinkModel.opticallink_endpoints))\
+                        .filter_by(topology_uuid=topology_uuid).one_or_none()
             #.options(selectinload(DeviceModel.components))\
         return None if obj is None else obj.dump_details()
     obj = run_transaction(sessionmaker(bind=db_engine), callback)
diff --git a/src/context/service/database/models/DeviceModel.py b/src/context/service/database/models/DeviceModel.py
index 376dc98c4..fb7f80e71 100644
--- a/src/context/service/database/models/DeviceModel.py
+++ b/src/context/service/database/models/DeviceModel.py
@@ -38,6 +38,9 @@ class DeviceModel(_Base):
     endpoints    = relationship('EndPointModel', passive_deletes=True) # lazy='joined', back_populates='device'
     components   = relationship('ComponentModel', passive_deletes=True) # lazy='joined', back_populates='device' 
     controller   = relationship('DeviceModel', remote_side=[device_uuid], passive_deletes=True) # lazy='joined', back_populates='device'
+    
+    # ------------------- Experimental -----------------------------------
+    optical_endpoints= relationship('OpticalEndPointModel',passive_deletes=True)
 
     def dump_id(self) -> Dict:
         return {'device_uuid': {'uuid': self.device_uuid}}
diff --git a/src/context/service/database/models/OpticalEndPointModel.py b/src/context/service/database/models/OpticalEndPointModel.py
new file mode 100644
index 000000000..0500bedf3
--- /dev/null
+++ b/src/context/service/database/models/OpticalEndPointModel.py
@@ -0,0 +1,69 @@
+# 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 operator
+from sqlalchemy import CheckConstraint, Column, DateTime, Float, ForeignKey, Integer, String ,Boolean
+from sqlalchemy.dialects.postgresql import UUID
+from sqlalchemy.types import ARRAY
+from sqlalchemy.orm import relationship
+from typing import Dict
+from ._Base import _Base
+
+
+
+
+class OpticalEndPointModel(_Base):
+    __tablename__ = 'optical_endpoint'
+
+    endpoint_uuid     = Column(UUID(as_uuid=False), primary_key=True)
+    device_uuid       = Column(ForeignKey('device.device_uuid',     ondelete='CASCADE' ), nullable=False, index=True)
+   
+    name              = Column(String, nullable=False)
+    endpoint_type     = Column(String, nullable=False)
+   
+    created_at        = Column(DateTime, nullable=False)
+    updated_at        = Column(DateTime, nullable=False)
+   
+    device            = relationship('DeviceModel',          back_populates='optical_endpoints') # lazy='selectin'
+   
+    #link_endpoints    = relationship('LinkEndPointModel',    back_populates='endpoint' )
+    #service_endpoints = relationship('ServiceEndPointModel', back_populates='endpoint' )
+
+    def dump_id(self) -> Dict:
+        result = {
+         
+            'device_id'    : self.device.dump_id(),
+            'endpoint_uuid': {'uuid': self.endpoint_uuid},
+        }
+        return result
+
+    def dump(self) -> Dict:
+        return {
+            'endpoint_id'      : self.dump_id(),
+            'name'             : self.name,
+            'endpoint_type'    : self.endpoint_type,
+           
+        }
+
+    def dump_name(self) -> Dict:
+        return {
+            'endpoint_id'  : self.dump_id(),
+            'device_name'  : self.device.device_name,
+            'endpoint_name': self.name,
+            'endpoint_type': self.endpoint_type,
+        }    
\ No newline at end of file
diff --git a/src/context/service/database/models/OpticalLinkModel.py b/src/context/service/database/models/OpticalLinkModel.py
index b94eeda93..28c71675e 100644
--- a/src/context/service/database/models/OpticalLinkModel.py
+++ b/src/context/service/database/models/OpticalLinkModel.py
@@ -1,78 +1,117 @@
+# 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 operator
 from sqlalchemy import CheckConstraint, Column, DateTime, Float, ForeignKey, Integer, String ,Boolean
 from sqlalchemy.dialects.postgresql import UUID
-from sqlalchemy.types import ARRAY
+from sqlalchemy.types import  PickleType , TypeDecorator
 from sqlalchemy.orm import relationship
+import json,logging
 from typing import Dict
 from ._Base import _Base
 
+
+
+
+class SlotType(TypeDecorator):
+
+    impl = String
+
+    def process_bind_param(self, value, dialect):
+        if value is not None:
+            slot={}
+            for k,v in value.items():
+                slot[k]=v
+            logging.info(f"dict from slotType {slot}")    
+            value = json.dumps(slot)
+
+        return value
+
+    def process_result_value(self, value, dialect):
+        if value is not None:
+            value = json.loads(value)
+        return value
+    
+    
+
+
+
 class OpticalLinkModel(_Base):
     __tablename__ = 'opticallink'
 
-    optical_link_uuid           = Column(UUID(as_uuid=False), primary_key=True)
-    optical_link_name           = Column(String, nullable=False)
-    length = Column(Integer, nullable=True)
-    source  = Column(String, nullable=True)
-    target  = Column(String, nullable=True)
-    optical_link_fiber= relationship("FiberModel") 
-    created_at          = Column(DateTime, nullable=False)
-    updated_at          = Column(DateTime, nullable=False)
+    opticallink_uuid          = Column(UUID(as_uuid=False), primary_key=True)
+    name                      = Column(String, nullable=False)
+    created_at                = Column(DateTime, nullable=False)
+    updated_at                = Column(DateTime, nullable=False)
+    length                    = Column(Integer, nullable=True)
+    src_port                  = Column(String, nullable=True)
+    dst_port                  = Column(String, nullable=True)
+    local_peer_port           = Column(String, nullable=True)
+    remote_peer_port          = Column(String, nullable=True)
+    used                      = Column(Boolean ,nullable=True)
+    c_slots                   = Column (SlotType,nullable=True)
+    l_slots                   = Column (SlotType,nullable=True)
+    s_slots                   = Column (SlotType,nullable=True)
+    opticallink_endpoints     = relationship("OpticalLinkEndPointModel")
+    topology_optical_links    = relationship('TopologyOpticalLinkModel', back_populates='optical_link')
+   
 
  
    
 
     def dump_id(self) -> Dict:
-        return {'optical_link_uuid': {'uuid': self.link_uuid}}
+        return {'link_uuid': {'uuid': self.opticallink_uuid}}
 
     def dump(self) -> Dict:
+       
         result = {
-            'optical_link_id'   : self.dump_id(),
-            'name'              : self.optical_link_name,
-            'details': {
-                "length"        : self.length,
-                'source'        : self.source,
-                "target"        : self.target,
-                'fibers'        : [ fiber.dump() for fiber in self.optical_link_fiber ]
-            }
-          
+            
+            'link_id'            : self.dump_id(),
+            'name'               : self.name,
+            'optical_details'    :{
+                 
+                                'length'           : self.length,
+                                "src_port"         : self.src_port,
+                                "dst_port"         : self.dst_port,
+                                "local_peer_port"  : self.local_peer_port,
+                                "remote_peer_port" : self.remote_peer_port,
+                                "used"             : self.used,
+                                "c_slots"          : self.c_slots ,
+                                "l_slots"          : self.l_slots,
+                                "s_slots"          : self.s_slots
+                },
+            "link_endpoint_ids" : [optical_endpoint.endpoint.dump_id() for optical_endpoint in self.opticallink_endpoints]
+            
         }
        
         return result
 
-class FiberModel(_Base):
-    __tablename__ = 'fiber'
-    fiber_uuid  = Column(UUID(as_uuid=False), primary_key=True)
-    fiber_length = Column(Integer, nullable=True)
-    source_port  = Column(String, nullable=True)
-    destination_port  = Column(String, nullable=True)
-    local_peer_port = Column(String, nullable=True)
-    remote_peer_port = Column(String, nullable=True)
-    used = Column(Boolean ,nullable=true)
-    c_slots = Column (ARRAY(Integer),nullable=True)
-    l_slots = Column (ARRAY(Integer),nullable=True)
-    s_slots = Column (ARRAY(Integer),nullable=True)
-    optical_link_uuid     = Column(ForeignKey('opticallink.optical_link_uuid',  ondelete='CASCADE' ), primary_key=True)
-	optical_link     = relationship('OpticalLinkModel',     back_populates='optical_link_fibers')
- 
- 
- 	def dump_id(self) -> Dict:
-        return {'fiber_uuid': {'uuid': self.fiber_uuid}}
-    
-    
-    def dump(self) -> Dict:
-        result = {
-        'ID'               : self.dump_id(),
-        'length'           : self.fiber_length,
-        "src_port"         : self.source_port,
-        "dst_port"         : self.destination_port,
-        "local_peer_port"  : self.local_peer_port,
-        "remote_peer_port" : self.remote_peer_port,
-        "used"             : self.used,
-        "c_slots"          : self.c_slots ,
-        "l_slots"          : self.l_slots,
-        "s_slots"          : self.s_slots
-          
-        }
-       
-        return result
\ No newline at end of file
+
+
+
+class OpticalLinkEndPointModel(_Base):
+    __tablename__ = 'opticallink_endpoint'
+
+    link_uuid     = Column(ForeignKey('opticallink.opticallink_uuid',         ondelete='CASCADE' ), primary_key=True)
+    endpoint_uuid = Column(ForeignKey('optical_endpoint.endpoint_uuid', ondelete='RESTRICT'), primary_key=True, index=True)
+
+
+    optical_link     = relationship('OpticalLinkModel',     back_populates='opticallink_endpoints') #, lazy='selectin'
+    endpoint = relationship('OpticalEndPointModel', lazy='selectin') # back_populates='link_endpoints'
+
+
+
diff --git a/src/context/service/database/models/TopologyModel.py b/src/context/service/database/models/TopologyModel.py
index 68d97edf3..f0e3da3aa 100644
--- a/src/context/service/database/models/TopologyModel.py
+++ b/src/context/service/database/models/TopologyModel.py
@@ -30,6 +30,9 @@ class TopologyModel(_Base):
     context          = relationship('ContextModel', back_populates='topologies', lazy='selectin')
     topology_devices = relationship('TopologyDeviceModel') # back_populates='topology'
     topology_links   = relationship('TopologyLinkModel'  ) # back_populates='topology'
+    
+    #-------------------------- Experimental ---------------------------
+    topology_optical_links= relationship("TopologyOpticalLinkModel")
 
     def dump_id(self) -> Dict:
         return {
@@ -43,6 +46,8 @@ class TopologyModel(_Base):
             'name'       : self.topology_name,
             'device_ids' : [{'device_uuid': {'uuid': td.device_uuid}} for td in self.topology_devices],
             'link_ids'   : [{'link_uuid'  : {'uuid': tl.link_uuid  }} for tl in self.topology_links  ],
+            'optical_link_ids'   : [{'link_uuid'  : {'uuid': to.optical_link_uuid  }} for to in self.topology_optical_links  ],
+            
         }
 
     def dump_details(self) -> Dict:
@@ -54,11 +59,16 @@ class TopologyModel(_Base):
             tl.link.dump()
             for tl in self.topology_links
         ]
+        optical_links=[
+            ol.optical_link.dump() 
+            for ol in self.topology_optical_links
+        ]
         return {
             'topology_id': self.dump_id(),
             'name'       : self.topology_name,
             'devices'    : devices,
             'links'      : links,
+            'optical_links':optical_links
         }
 
 class TopologyDeviceModel(_Base):
@@ -78,3 +88,14 @@ class TopologyLinkModel(_Base):
 
     topology = relationship('TopologyModel', lazy='selectin', viewonly=True) # back_populates='topology_links'
     link     = relationship('LinkModel',     lazy='selectin') # back_populates='topology_links'
+
+#---------------------------------------- Experimental ---------------------------------------
+
+class TopologyOpticalLinkModel(_Base):
+    __tablename__ = 'topology_optical_link'
+
+    topology_uuid = Column(ForeignKey('topology.topology_uuid', ondelete='RESTRICT'), primary_key=True, index=True)
+    optical_link_uuid     = Column(ForeignKey('opticallink.opticallink_uuid',         ondelete='CASCADE' ), primary_key=True, index=True)
+
+    topology = relationship('TopologyModel', lazy='selectin', viewonly=True) # back_populates='topology_optical_links'
+    optical_link     = relationship('OpticalLinkModel',     lazy='selectin') # back_populates='topology_optical_links'
diff --git a/src/context/service/database/uuids/EndPoint.py b/src/context/service/database/uuids/EndPoint.py
index bf5f30ec3..aef2c6de4 100644
--- a/src/context/service/database/uuids/EndPoint.py
+++ b/src/context/service/database/uuids/EndPoint.py
@@ -18,21 +18,26 @@ from common.method_wrappers.ServiceExceptions import InvalidArgumentsException
 from ._Builder import get_uuid_from_string, get_uuid_random
 from .Device import device_get_uuid
 from .Topology import topology_get_uuid
+import logging
 
 def endpoint_get_uuid(
     endpoint_id : EndPointId, endpoint_name : str = '', allow_random : bool = False
 ) -> Tuple[str, str, str]:
+    logging.info(f"endpoint_id is {endpoint_id}")
     device_uuid = device_get_uuid(endpoint_id.device_id, allow_random=False)
     _,topology_uuid = topology_get_uuid(endpoint_id.topology_id, allow_random=False, allow_default=True)
     raw_endpoint_uuid = endpoint_id.endpoint_uuid.uuid
 
     if len(raw_endpoint_uuid) > 0:
         prefix_for_name = '{:s}/{:s}'.format(topology_uuid, device_uuid)
+        logging.info(f" e_raw_endpoint_uuid , e  {raw_endpoint_uuid} and endpoint{get_uuid_from_string(raw_endpoint_uuid, prefix_for_name=prefix_for_name)}")
         return topology_uuid, device_uuid, get_uuid_from_string(raw_endpoint_uuid, prefix_for_name=prefix_for_name)
     if len(endpoint_name) > 0:
+      
         prefix_for_name = '{:s}/{:s}'.format(topology_uuid, device_uuid)
         return topology_uuid, device_uuid, get_uuid_from_string(endpoint_name, prefix_for_name=prefix_for_name)
     if allow_random:
+        
         return topology_uuid, device_uuid, get_uuid_random()
 
     raise InvalidArgumentsException([
diff --git a/src/context/service/database/uuids/OpticalEndPoint.py b/src/context/service/database/uuids/OpticalEndPoint.py
new file mode 100644
index 000000000..b31bc7d71
--- /dev/null
+++ b/src/context/service/database/uuids/OpticalEndPoint.py
@@ -0,0 +1,45 @@
+# 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 Tuple
+from common.proto.context_pb2 import EndPointId
+from common.method_wrappers.ServiceExceptions import InvalidArgumentsException
+from ._Builder import get_uuid_from_string, get_uuid_random
+from .Device import device_get_uuid
+from .Topology import topology_get_uuid
+import logging
+
+def optical_endpoint_get_uuid(
+    endpoint_id : EndPointId, endpoint_name : str = '', allow_random : bool = False
+) -> Tuple[str, str, str]:
+    device_uuid = device_get_uuid(endpoint_id.device_id, allow_random=False)
+   
+    raw_endpoint_uuid = endpoint_id.endpoint_uuid.uuid
+
+    if len(raw_endpoint_uuid) > 0:
+        prefix_for_name = '{:s}'.format( device_uuid)
+        logging.info(f"  raw_endpoint uuid {raw_endpoint_uuid} and endpoint {get_uuid_from_string(raw_endpoint_uuid, prefix_for_name=prefix_for_name)}")
+        return  device_uuid, get_uuid_from_string(raw_endpoint_uuid, prefix_for_name=prefix_for_name)
+    if len(endpoint_name) > 0:
+       
+        prefix_for_name = '{:s}'.format( device_uuid)
+        return  device_uuid, get_uuid_from_string(endpoint_name, prefix_for_name=prefix_for_name)
+    if allow_random:
+    
+        return device_uuid, get_uuid_random()
+
+    raise InvalidArgumentsException([
+        ('optical_endpoint_id.endpoint_uuid.uuid', raw_endpoint_uuid),
+        ('name', endpoint_name),
+    ], extra_details=['At least one is required to produce a OpticalEndPoint UUID'])
diff --git a/src/context/service/database/uuids/OpticalLink.py b/src/context/service/database/uuids/OpticalLink.py
new file mode 100644
index 000000000..0caead511
--- /dev/null
+++ b/src/context/service/database/uuids/OpticalLink.py
@@ -0,0 +1,21 @@
+
+from common.proto.context_pb2 import LinkId
+from common.method_wrappers.ServiceExceptions import InvalidArgumentsException
+from ._Builder import get_uuid_from_string, get_uuid_random
+
+optical_detail_sp="Optical_link_detail"
+def opticaldetail_get_uuid(
+    link_id : LinkId,allow_random=False
+) -> str:
+    link_uuid = link_id.link_uuid.uuid
+
+    if len(link_uuid) > 0:
+        str_uuid=f"{link_uuid}{optical_detail_sp}"
+        return get_uuid_from_string(str_uuid)
+  
+    if allow_random: return get_uuid_random()
+
+    raise InvalidArgumentsException([
+        ('link_id.link_uuid.uuid', link_uuid),
+
+    ], extra_details=['At least one is required to produce a Optical Link Detail UUID'])
diff --git a/src/context/service/database/uuids/_Builder.py b/src/context/service/database/uuids/_Builder.py
index 75fe51bc0..338b3ac97 100644
--- a/src/context/service/database/uuids/_Builder.py
+++ b/src/context/service/database/uuids/_Builder.py
@@ -14,7 +14,7 @@
 
 from typing import Optional, Union
 from uuid import UUID, uuid4, uuid5
-
+import logging
 # Generate a UUIDv5-like from the SHA-1 of "TFS" and no namespace to be used as the NAMESPACE for all
 # the context UUIDs generated. For efficiency purposes, the UUID is hardcoded; however, it is produced
 # using the following code:
@@ -32,10 +32,12 @@ def get_uuid_from_string(str_uuid_or_name : Union[str, UUID], prefix_for_name :
         raise Exception(MSG.format(str(repr(str_uuid_or_name))))
     try:
         # try to parse as UUID
+
         return str(UUID(str_uuid_or_name))
     except: # pylint: disable=bare-except
         # produce a UUID within TFS namespace from parameter
         if prefix_for_name is not None:
+            logging.info(f"playing with its suit {prefix_for_name} and {str_uuid_or_name}")
             str_uuid_or_name = '{:s}/{:s}'.format(prefix_for_name, str_uuid_or_name)
         return str(uuid5(NAMESPACE_TFS, str_uuid_or_name))
 
diff --git a/src/device/service/drivers/oc_driver/templates/VPN/physical.py b/src/device/service/drivers/oc_driver/templates/VPN/physical.py
index 7835b4778..f368ca10e 100644
--- a/src/device/service/drivers/oc_driver/templates/VPN/physical.py
+++ b/src/device/service/drivers/oc_driver/templates/VPN/physical.py
@@ -207,4 +207,30 @@ def create_media_channel (resources):
         return results
              
                 
-     
\ No newline at end of file
+
+
+
+def disable_optical_channel (index,state) :
+    
+    results=[]
+    doc, tag, text = Doc().tagtext()
+    #with tag('config'):
+    with tag('config',xmlns="urn:ietf:params:xml:ns:netconf:base:1.0"):
+        with tag('components', xmlns="http://openconfig.net/yang/platform"):
+            with tag('terminal-device',xmlns="http://openconfig.net/yang/terminal-device"):
+                with tag("logical-channels"):
+                    with tag('channel'):
+                        with tag('index'):text("{}".format(index))
+                        with tag('config'):
+                            with tag('admin-state'):text("{}".format(state))
+                       
+    result = indent(
+        doc.getvalue(),
+        indentation = ' '*2,
+        newline = ''
+    )
+    results.append(result)
+
+
+    return results
+
diff --git a/src/opticalcontroller/Dockerfile b/src/opticalcontroller/Dockerfile
index d54566ccb..70bae4223 100644
--- a/src/opticalcontroller/Dockerfile
+++ b/src/opticalcontroller/Dockerfile
@@ -1,4 +1,4 @@
-# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/)
+# Copyright 2022-2024 ETSI OSG/SDG TeraFlowSDN (TFS) (https://tfs.etsi.org/)
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -34,19 +34,20 @@ RUN python3 -m pip install --upgrade pip-tools
 
 # Get common Python packages
 # Note: this step enables sharing the previous Docker build steps among all the Python components
-WORKDIR /var/teraflow
+WORKDIR /var/teraflow/opticalcontroller/
+
 COPY common_requirements.in common_requirements.in
 RUN pip-compile --quiet --output-file=common_requirements.txt common_requirements.in
 RUN python3 -m pip install -r common_requirements.txt
 
 # Add common files into working directory
-WORKDIR /var/teraflow/common
+WORKDIR /var/teraflow/opticalcontroller/common
 COPY src/common/. ./
 RUN rm -rf proto
 
 # Create proto sub-folder, copy .proto files, and generate Python code
-RUN mkdir -p /var/teraflow/common/proto
-WORKDIR /var/teraflow/common/proto
+RUN mkdir -p /var/teraflow/opticalcontroller/common/proto
+WORKDIR /var/teraflow/opticalcontroller/common/proto
 RUN touch __init__.py
 COPY proto/*.proto ./
 RUN python3 -m grpc_tools.protoc -I=. --python_out=. --grpc_python_out=. *.proto
@@ -54,18 +55,19 @@ RUN rm *.proto
 RUN find . -type f -exec sed -i -E 's/(import\ .*)_pb2/from . \1_pb2/g' {} \;
 
 # Create component sub-folders, get specific Python packages
-RUN mkdir -p /var/teraflow/opticalcontroller
-WORKDIR /var/teraflow/opticalcontroller
+
+WORKDIR /var/teraflow/
 COPY src/opticalcontroller/requirements.in requirements.in
 RUN pip-compile --quiet --output-file=requirements.txt requirements.in
 RUN python3 -m pip install -r requirements.txt
 
 # Add component files into working directory
-WORKDIR /var/teraflow
+WORKDIR /var/teraflow/opticalcontroller/
+
 COPY src/context/__init__.py context/__init__.py
 COPY src/context/client/. context/client/
-COPY src/opticalcontroller/. opticalcontroller/
+COPY src/opticalcontroller/. ./
 
 # Start the service
-WORKDIR /var/teraflow/opticalcontroller
+
 ENTRYPOINT ["python", "OpticalController.py"]
diff --git a/src/opticalcontroller/OpticalController.py b/src/opticalcontroller/OpticalController.py
index c2805695a..c91c76e9f 100644
--- a/src/opticalcontroller/OpticalController.py
+++ b/src/opticalcontroller/OpticalController.py
@@ -1,30 +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.
-
 from flask import Flask
 from flask import render_template
 from flask_restplus import Resource, Api
-
 from tools import *
 from variables import *
 from RSA import RSA
-import time
-import logging
+import time , logging
+from common.proto.context_pb2 import TopologyId
+
 
 
 rsa = None
-LOGGER = logging.getLogger(__name__)
+
 
 app = Flask(__name__)
 api = Api(app, version='1.0', title='Optical controller API',
@@ -47,7 +33,7 @@ class AddLightpath(Resource):
     @staticmethod
     def put(src, dst, bitrate, bidir=1):
 
-        LOGGER.info("INFO: New Lightpath request from {} to {} with rate {} ".format(src, dst, bitrate))
+        print("INFO: New Lightpath request from {} to {} with rate {} ".format(src, dst, bitrate))
         t0 = time.time()*1000.0
         if debug:
             rsa.g.printGraph()
@@ -56,9 +42,9 @@ class AddLightpath(Resource):
             flow_id = rsa.rsa_computation(src, dst, bitrate, bidir)
             if rsa.db_flows[flow_id]["op-mode"] == 0:
                 return 'No path found', 404
-            t1 = time.time()*1000.0
+            t1 = time.time() * 1000.0
             elapsed = t1 - t0
-            LOGGER.info("INFO: time elapsed = {} ms".format(elapsed))
+            print("INFO: time elapsed = {} ms".format(elapsed))
             return rsa.db_flows[flow_id], 200
         else:
             return "Error", 404
@@ -74,17 +60,15 @@ class AddLightpath(Resource):
 @optical.response(404, 'Error, not found')
 class AddFlexLightpath(Resource):
     @staticmethod
-    def put(src, dst, bitrate,bidir=1, band=None):
-        
+    def put(src, dst, bitrate, bidir=1, band=None):
+
         print("INFO: New FlexLightpath request from {} to {} with rate {} ".format(src, dst, bitrate))
-        LOGGER.info("INFO: New FlexLightpath request from {} to {} with rate {} ".format(src, dst, bitrate))
         t0 = time.time()*1000.0
         if debug:
             rsa.g.printGraph()
 
         if rsa is not None:
             flow_id, optical_band_id = rsa.rsa_fs_computation(src, dst, bitrate, bidir, band)
-            print (f"flow_id {flow_id} and optical_band_id {optical_band_id} ")
             if flow_id is not None:
                 if rsa.db_flows[flow_id]["op-mode"] == 0:
                     return 'No path found', 404
@@ -99,7 +83,7 @@ class AddFlexLightpath(Resource):
                 else:
                     t1 = time.time() * 1000.0
                     elapsed = t1 - t0
-                    LOGGER.info("INFO: time elapsed = {} ms".format(elapsed))
+                    print("INFO: time elapsed = {} ms".format(elapsed))
 
                     return rsa.optical_bands[optical_band_id], 200
         else:
@@ -108,7 +92,7 @@ class AddFlexLightpath(Resource):
 @optical.route('/DelFlexLightpath/<int:flow_id>/<string:src>/<string:dst>/<int:bitrate>/<int:o_band_id>')
 @optical.response(200, 'Success')
 @optical.response(404, 'Error, not found')
-class DelLightpath(Resource):
+class DelFLightpath(Resource):
     @staticmethod
     def delete(flow_id, src, dst, bitrate, o_band_id):
         if flow_id in rsa.db_flows.keys():
@@ -122,12 +106,12 @@ class DelLightpath(Resource):
                     rsa.del_flow(flow, ob_id)
                     rsa.db_flows[flow_id]["is_active"] = False
                     rsa.optical_bands[ob_id]["served_lightpaths"].remove(flow_id)
-                    if rsa.optical_bands[ob_id]["reverse_optical_band_id"] != 0:
-                        rev_ob_id = rsa.optical_bands[ob_id]["reverse_optical_band_id"]
-                        rsa.optical_bands[rev_ob_id]["served_lightpaths"].remove(flow_id)
+                    #if rsa.optical_bands[ob_id]["reverse_optical_band_id"] != 0:
+                    #    rev_ob_id = rsa.optical_bands[ob_id]["reverse_optical_band_id"]
+                    #    rsa.optical_bands[rev_ob_id]["served_lightpaths"].remove(flow_id)
 
                     if debug:
-                       LOGGER.info(links_dict)
+                        print(links_dict)
                     return "flow {} deleted".format(flow_id), 200
                 else:
                     return "flow {} not matching".format(flow_id), 404
@@ -138,7 +122,7 @@ class DelLightpath(Resource):
                     rsa.db_flows[flow_id]["is_active"] = False
                     rsa.optical_bands[ob_id]["served_lightpaths"].remove(flow_id)
                     if debug:
-                       LOGGER.info(links_dict)
+                        print(links_dict)
                     return "flow {} deleted".format(flow_id), 200
                 else:
                     return "flow {} not matching".format(flow_id), 404
@@ -161,7 +145,7 @@ class DelLightpath(Resource):
                 rsa.del_flow(flow)
                 rsa.db_flows[flow_id]["is_active"] = False
                 if debug:
-                   LOGGER.info(links_dict)
+                    print(links_dict)
                 return "flow {} deleted".format(flow_id), 200
             else:
                 return "flow {} not matching".format(flow_id), 404
@@ -177,7 +161,7 @@ class GetFlows(Resource):
     def get():
         try:
             if debug:
-               LOGGER.info(rsa.db_flows)
+                print(rsa.db_flows)
             return rsa.db_flows, 200
         except:
             return "Error", 404
@@ -188,11 +172,9 @@ class GetFlows(Resource):
 class GetBands(Resource):
     @staticmethod
     def get():
-        print("Getting ")
-        LOGGER.info("Getting")
         try:
             if debug:
-               LOGGER.info(rsa.optical_bands)
+                print(rsa.optical_bands)
             return rsa.optical_bands, 200
         except:
             return "Error", 404
@@ -207,7 +189,7 @@ class GetBand(Resource):
         for ob_idx in rsa.optical_bands.keys():
             if str(ob_idx) == str(ob_id):
                 if debug:
-                   LOGGER.info(rsa.optical_bands[ob_id])
+                    print(rsa.optical_bands[ob_id])
                 return rsa.optical_bands[ob_idx], 200
         return {}, 404
 
@@ -221,25 +203,36 @@ class GetFlows(Resource):
         global links_dict
         try:
             if debug:
-               LOGGER.info(links_dict)
+                print(links_dict)
             return links_dict, 200
         except:
             return "Error", 404
+        
+@optical.route('/GetTopology/<path:topology_id>',methods=(['GET']))
+@optical.response(200, 'Success')
+@optical.response(404, 'Error, not found')
+class GetTopology(Resource):
+    @staticmethod
+    def get(topology_id:TopologyId):
+        
+        try:
+            nodes , links = readTopologyDataFromContext(topology_id)
+            print(f"nodes {nodes} and links {links}")
+            return "Done"
+        except Exception as e:
+            print(f"err {e}")
+            return "Error", 404
+        
 
 
-if __name__ == '__main__':
     
-
-    # Start metrics server
-
-    LOGGER.info('Starting...')
-
-
-
+if __name__ == '__main__':
+   
+   
     nodes_dict, links_dict = readTopologyData(nodes_json, topology_json)
 
-    #topologies, links = getTopology()
-    #print("topologies{} and devices {}".format(topologies,links))
+   
     rsa = RSA(nodes_dict, links_dict)
+    #print(rsa.init_link_slots2(testing))
 
-    app.run(host='0.0.0.0', port=10060, debug=True)
+    app.run(host='0.0.0.0', port=5000,debug=True)
diff --git a/src/opticalcontroller/RSA.py b/src/opticalcontroller/RSA.py
index 9b12b1ac8..b6f9b0cbd 100644
--- a/src/opticalcontroller/RSA.py
+++ b/src/opticalcontroller/RSA.py
@@ -1,17 +1,3 @@
-# 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 dijsktra
 from tools import *
 from variables import *
@@ -26,15 +12,15 @@ class RSA():
         self.flow_id = 0
         self.opt_band_id = 0
         self.db_flows = {}
-        self.initGraph()
+        self.initGraph2()
         self.c_slot_number = 0
         self.l_slot_number = 0
         self.s_slot_number = 0
         self.optical_bands = {}
-
+        print(f"node_ctxt {nodes} links_ctxt {links}")
     def init_link_slots(self, testing):
         if not testing:
-            for l in self.links_dict["links"]:
+            for l in self.links_dict["optical_links"]:
                 for fib in l["optical_link"]["details"]["fibers"]:
                     #fib = self.links_dict[l]["fibers"][f]
                     if len(fib["c_slots"]) > 0:
@@ -45,7 +31,7 @@ class RSA():
                         fib["s_slots"] = list(range(0, Ns))
                     if debug:
                         print(fib)
-        for l1 in self.links_dict["links"]:
+        for l1 in self.links_dict["optical_links"]:
 
             for fib1 in l1["optical_link"]["details"]["fibers"]:
                 #fib1 = self.links_dict[l1]["details"]["fibers"][f1]
@@ -58,11 +44,35 @@ class RSA():
             break
         return "{},{},{}".format(self.c_slot_number, self.l_slot_number, self.s_slot_number)
 
+    def init_link_slots2(self, testing):
+        if not testing:
+            for l in self.links_dict["optical_links"]:
+                fib = l["optical_details"]
+                #fib = self.links_dict[l]["fibers"][f]
+                if len(fib["c_slots"]) > 0:
+                    for c in range(0, Nc):
+                        fib["c_slots"][c] = 1
+                if len(fib["l_slots"]) > 0:
+                    for c in range(0, Nl):
+                        fib["l_slots"][c] = 1
+                if len(fib["s_slots"]) > 0:
+                    for c in range(0, Ns):
+                        fib["s_slots"][c] = 1
+                if debug:
+                    print(fib)
+        for l1 in self.links_dict["optical_links"]:
+            fib1 = l1["optical_details"]
+            self.c_slot_number = len(fib1["c_slots"].keys())
+            self.l_slot_number = len(fib1["l_slots"].keys())
+            self.s_slot_number = len(fib1["s_slots"].keys())
+            break
+        return "{},{},{}".format(self.c_slot_number, self.l_slot_number, self.s_slot_number)
+
     def initGraph(self):
         self.g = dijsktra.Graph()
         for n in self.nodes_dict:
             self.g.add_vertex(n)
-        for l in self.links_dict["links"]:
+        for l in self.links_dict["optical_links"]:
             if debug:
                 print(l)
             [s, d] = l["optical_link"]["name"].split('-')
@@ -74,6 +84,22 @@ class RSA():
         if debug:
             self.g.printGraph()
 
+    def initGraph2(self):
+        self.g = dijsktra.Graph()
+        for n in self.nodes_dict:
+            self.g.add_vertex(n)
+        for l in self.links_dict["optical_links"]:
+            if debug:
+                print(l)
+            [s, d] = l["name"].split('-')
+            ps = l["optical_details"]["src_port"]
+            pd = l["optical_details"]["dst_port"]
+            self.g.add_edge(s, d, ps, pd, 1)
+
+        print("INFO: Graph initiated.2")
+        if debug:
+            self.g.printGraph()
+
     def compute_path(self, src, dst):
         path = dijsktra.shortest_path(self.g, self.g.get_vertex(src), self.g.get_vertex(dst))
         print("INFO: Path from {} to {} with distance: {}".format(src, dst, self.g.get_vertex(dst).get_distance()))
@@ -95,7 +121,7 @@ class RSA():
         self.g.reset_graph()
         return links, path
 
-    def get_slots(self, links, slots, optical_band_id = None):
+    def get_slots(self, links, slots, optical_band_id=None):
 
         if isinstance(slots, int):
             val_c = slots
@@ -120,38 +146,40 @@ class RSA():
             add = links[0]
         if self.nodes_dict[dst_2]["type"] == "OC-TP":
             drop = links[-1]
-
+        found = 0
         for l in links:
             c_slots[l] = []
             l_slots[l] = []
             s_slots[l] = []
-            found = 0
-            for link in self.links_dict["links"]:
-                if link["optical_link"]["name"] == l:
-                    #for f in self.links_dict[l]['fibers'].keys():
-                    for fib in link["optical_link"]["details"]["fibers"]:
-                        if l == add:
-                            if 'used' in fib:
-                                if fib["used"]:
-                                    #if debug:
-                                    print("WARNING!!!: link {}, fiber {} is already in use".format(l, fib["ID"]))
-                                    continue
-                        if l == drop:
-                            if 'used' in fib:
-                                if fib["used"]:
-                                    #if debug:
-                                    print("WARNING!!!: link {}, fiber {} is already in use".format(l, fib["ID"]))
-                                    continue
-                        if len(fib["c_slots"]) > 0:
-                            c_slots[l] = combine(c_slots[l], consecutives(fib["c_slots"], val_c))
-                        if len(fib["l_slots"]) > 0:
-                            l_slots[l] = combine(l_slots[l], consecutives(fib["l_slots"], val_l))
-                        if len(fib["s_slots"]) > 0:
-                            s_slots[l] = combine(s_slots[l], consecutives(fib["s_slots"], val_s))
-                        if debug:
-                            print(l, c_slots[l])
-                        found = 1
-            if found == 0:
+
+            link = self.get_link_by_name(l)
+            fib = link["optical_details"]
+            if l == add:
+                if 'used' in fib:
+                    if fib["used"]:
+                        #if debug:
+                        print("WARNING!!!: link {}, is already in use".format(l))
+                        return [], [], []
+            if l == drop:
+                if 'used' in fib:
+                    if fib["used"]:
+                        #if debug:
+                        print("WARNING!!!: link {} is already in use".format(l))
+                        return [], [], []
+            c_found = l_found = s_found = 0
+            if len(fib["c_slots"].keys()) > 0:
+                #c_slots[l] = combine(c_slots[l], consecutives(fib["c_slots"], val_c))
+                c_slots[l] = combine(c_slots[l], consecutives(fib["c_slots"], val_c))
+                c_found = 1
+            if len(fib["l_slots"].keys()) > 0:
+                l_slots[l] = combine(l_slots[l], consecutives(fib["l_slots"], val_l))
+                l_found = 1
+            if len(fib["s_slots"].keys()) > 0:
+                s_slots[l] = combine(s_slots[l], consecutives(fib["s_slots"], val_s))
+                s_found = 1
+            if debug:
+                print(l, c_slots[l])
+            if c_found == 0 and l_found == 0 and s_found == 0:
                 return [], [], []
 
         keys = list(c_slots.keys())
@@ -185,58 +213,61 @@ class RSA():
                 c_sts = common_slots(a_c, b_c)
                 l_sts = common_slots(a_l, b_l)
                 s_sts = common_slots(a_s, b_s)
+                '''
+             if len(fib["l_slots"]) > 0:
+                l_slots[l] = combine(l_slots[l], consecutives(fib["l_slots"], val_l))
+                l_found = 1'''
         if optical_band_id is not None:
             if "c_slots" in self.optical_bands[optical_band_id].keys():
                 if len(self.optical_bands[optical_band_id]["c_slots"]) > 0:
                     a_c = c_sts
-                    b_c = self.optical_bands[optical_band_id]["c_slots"]
+                    #MOD
+                    b_c = consecutives(self.optical_bands[optical_band_id]["c_slots"], val_c)
+                    #b_c = self.optical_bands[optical_band_id]["c_slots"]
                     c_sts = common_slots(a_c, b_c)
-                else:
-                    c_sts = []
             else:
                 c_sts = []
             if "l_slots" in self.optical_bands[optical_band_id].keys():
                 if len(self.optical_bands[optical_band_id]["l_slots"]) > 0:
                     a_l = l_sts
-                    b_l = self.optical_bands[optical_band_id]["l_slots"]
+                    b_l = consecutives(self.optical_bands[optical_band_id]["l_slots"], val_c)
                     l_sts = common_slots(a_l, b_l)
-                else:
-                    l_sts = []
             else:
                 l_sts = []
             if "s_slots" in self.optical_bands[optical_band_id].keys():
                 if len(self.optical_bands[optical_band_id]["s_slots"]) > 0:
                     a_s = s_sts
-                    b_s = self.optical_bands[optical_band_id]["s_slots"]
+                    b_s = consecutives(str_list_to_int(self.optical_bands[optical_band_id]["s_slots"].keys()), val_c)
                     s_sts = common_slots(a_s, b_s)
-                else:
-                    s_sts = []
             else:
                 s_sts = []
 
         return c_sts, l_sts, s_sts
 
     def update_link(self, fib, slots, band):
+        print(fib)
         for i in slots:
-            fib[band].remove(i)
+            fib[band][str(i)] = 0
         if 'used' in fib:
             fib['used'] = True
+        print(fib)
 
     def update_optical_band(self, optical_band_id, slots, band):
         for i in slots:
-            self.optical_bands[optical_band_id][band].remove(i)
+            self.optical_bands[optical_band_id][band][str(i)] = 0
 
     def restore_link(self, fib, slots, band):
         for i in slots:
-            fib[band].append(int(i))
+            fib[band][str(i)] = 1
         if 'used' in fib:
             fib['used'] = False
         fib[band].sort()
 
     def restore_optical_band(self, optical_band_id, slots, band):
         for i in slots:
-            self.optical_bands[optical_band_id][band].append(int(i))
-        self.optical_bands[optical_band_id][band].sort()
+            self.optical_bands[optical_band_id][band][str(i)] = 1
+            #self.optical_bands[optical_band_id][band].append(int(i))
+        #self.optical_bands[optical_band_id][band].sort()
 
     def del_flow(self, flow, o_b_id = None):
         flows = flow["flows"]
@@ -250,21 +281,35 @@ class RSA():
         links = flow["links"]
         bidir = flow["bidir"]
 
-        for l in fiber_f.keys():
+        for l in links:
             if debug:
                 print(l)
-                print(fiber_f[l])
             #link = self.links_dict[l]
             #f = fiber_f[l]
             #fib = link['fibers'][f]
-            fib = self.get_fiber_details(l, fiber_f[l])
-            if not list_in_list(slots, fib[band]):
+            fib = self.get_link_by_name(l)["optical_details"]
+            if not list_in_list(slots, str_list_to_int(fib[band].keys())):
                 self.restore_link(fib, slots, band)
                 if debug:
                     print(fib[band])
         if o_b_id is not None:
+            if debug:
+                print("restoring OB")
             self.restore_optical_band(o_b_id, slots, band)
         if bidir:
+            for l in links:
+                r_l = reverse_link(l)
+                if debug:
+                    print(r_l)
+                # link = self.links_dict[l]
+                # f = fiber_f[l]
+                # fib = link['fibers'][f]
+                fib = self.get_link_by_name(r_l)["optical_details"]
+                if not list_in_list(slots, str_list_to_int(fib[band].keys())):
+                    self.restore_link(fib, slots, band)
+                    if debug:
+                        print(fib[band])
+            '''
             for rl in fiber_b.keys():
                 if debug:
                     print(rl)
@@ -277,6 +322,7 @@ class RSA():
                     self.restore_link(rfib, slots, band)
                     if debug:
                         print(rfib[band])
+            '''
             #changed according to TFS development
             #if o_b_id is not None:
             #    rev_o_band_id = self.optical_bands[o_b_id]["reverse_optical_band_id"]
@@ -287,7 +333,7 @@ class RSA():
         fiber_list = {}
         add = links[0]
         drop = links[-1]
-        print(links)
+        #print(links)
         '''
         for link in self.links_dict["links"]:
             if link["optical_link"]["name"] == l:
@@ -296,85 +342,98 @@ class RSA():
 
         '''
         for l in links:
-            for link in self.links_dict["links"]:
-                if link["optical_link"]["name"] == l:
-                    for fib in link["optical_link"]["details"]["fibers"]:
-                        #for f in self.links_dict[l]['fibers'].keys():
-                        #for fib in l["optical_link"]["details"]["fibers"]:
-                        #fib = self.links_dict[l]['fibers'][f]
-                        if l == add:
-                            if 'used' in fib:
-                                if fib["used"]:
-                                    if debug:
-                                        print("link {}, fiber {} is already in use".format(l, fib["ID"]))
-                                    continue
-                        if l == drop:
-                            if 'used' in fib:
-                                if fib["used"]:
-                                    if debug:
-                                        print("link {}, fiber {} is already in use".format(l, fib["ID"]))
-                                    continue
-                        if list_in_list(slots, fib[band]):
-                            fiber_list[l] = fib["ID"]
-                            self.update_link(fib, slots, band)
-                            break
+            for link in self.links_dict["optical_links"]:
+                if link["name"] == l:
+                    fib = link["optical_details"]
+                    #for f in self.links_dict[l]['fibers'].keys():
+                    #for fib in l["optical_link"]["details"]["fibers"]:
+                    #fib = self.links_dict[l]['fibers'][f]
+                    if l == add:
+                        if 'used' in fib:
+                            if fib["used"]:
+                                if debug:
+                                    print("link {} is already in use".format(l))
+                                continue
+                    if l == drop:
+                        if 'used' in fib:
+                            if fib["used"]:
+                                if debug:
+                                    print("link {} is already in use".format(l))
+                                continue
+                    if list_in_list(slots, str_list_to_int(fib[band].keys())):
+                        #fiber_list[l] = fib["ID"]
+                        self.update_link(fib, slots, band)
+                        break
         print("INFO: Path forward computation completed")
         return fiber_list
 
     def get_link_by_name (self, key):
-        result = None
-        for link in self.links_dict["links"]:
-            if link["optical_link"]["name"] == key:
+        for link in self.links_dict["optical_links"]:
+            if link["name"] == key:
                 if debug:
                     print(link)
-                result = link
                 break
-        return result
+        return link
 
     def get_fiber_details(self, link_key, fiber_id):
-        for link in self.links_dict["links"]:
-            if link["optical_link"]["name"] == link_key:
+        for link in self.links_dict["optical_links"]:
+            if link["name"] == link_key:
                 if debug:
                     print(link)
-                for fib in link["optical_link"]["details"]["fibers"]:
+                for fib in link["optical_details"]:
                     if fib["ID"] == fiber_id:
                         return fib
         return None
 
-
-    def get_fibers_backward(self, links, fibers, slots, band):
+    def get_fibers_backward(self, links, slots, band):
         fiber_list = {}
         #r_drop = reverse_link(links[0])
         #r_add = reverse_link(links[-1])
-        for l in fibers.keys():
-            fib = self.get_fiber_details(l, fibers[l])
+        for l in links:
+            fib = self.get_link_by_name(l)["optical_details"]
             '''
             link = self.get_link_by_name(l)
             #port = self.links_dict[l]["fibers"][fibers[l]]["src_port"]
             for fib in link["optical_link"]["details"]["fibers"]:
                 if fib["ID"] == fibers[l]:
             '''
-            port = fib["src_port"]
+            s_port = fib["src_port"]
+            d_port = fib["dst_port"]
+
+            if debug:
+                print(l, s_port, d_port)
+
             r_l = reverse_link(l)
             r_link = self.get_link_by_name(r_l)
+            if debug:
+                print(r_l)
+
             #for f in r_link["fibers"].keys():
-            for r_fib in r_link["optical_link"]["details"]["fibers"]:
-                if r_fib["remote_peer_port"] == port:
-                    if list_in_list(slots, r_fib[band]):
-                        fiber_list[r_l] = r_fib["ID"]
-                        self.update_link(r_fib, slots, band)
+            r_fib = r_link["optical_details"]
+            if r_fib["remote_peer_port"] == s_port and r_fib["local_peer_port"] == d_port:
+                if list_in_list(slots, str_list_to_int(r_fib[band].keys())):
+                    #fiber_list[r_l] = r_fib["ID"]
+                    self.update_link(r_fib, slots, band)
         print("INFO: Path backward computation completed")
         return fiber_list
 
+    #function invoked for lightpaths and OB
     def select_slots_and_ports(self, links, n_slots, c, l, s, bidir):
         if debug:
             print(self.links_dict)
         band, slots = slot_selection(c, l, s, n_slots, self.c_slot_number, self.l_slot_number, self.s_slot_number)
+        if debug:
+            print (band, slots)
         if band is None:
             print("No slots available in the three bands")
-            return None, None, None
+            #return None, None, None, {}, {}
+            return None, None, None, {}, {}
         if debug:
             print(band, slots)
+        self.get_fibers_forward(links, slots, band)
+        if bidir:
+            self.get_fibers_backward(links, slots, band)
+        '''
         fibers_f = self.get_fibers_forward(links, slots, band)
 
         fibers_b = []
@@ -385,6 +444,7 @@ class RSA():
             print(fibers_f)
             print("backward")
             print(fibers_b)
+        '''
         add = links[0]
         drop = links[-1]
         inport = "0"
@@ -394,18 +454,22 @@ class RSA():
         t_flows = {}
         #if len(links) == 1:
 
-        for lx in fibers_f:
-            if lx == add:
+        for llx in links:
+            if llx == add:
                 inport = "0"
                 r_outport = "0"
-            if lx == drop:
+            if llx == drop:
                 outport = "0"
                 r_inport = "0"
+            '''
             f = fibers_f[lx]
-            src, dst = lx.split("-")
+            
             fibx = self.get_fiber_details(lx, f)
+            '''
+            src, dst = llx.split("-")
             #outport = self.links_dict[lx]['fibers'][f]["src_port"]
-            outport = fibx["src_port"]
+            lx = self.get_link_by_name(llx)["optical_details"]
+            outport = lx["src_port"]
 
             t_flows[src] = {}
             t_flows[src]["f"] = {}
@@ -414,14 +478,14 @@ class RSA():
 
             if bidir:
                 #r_inport = self.links_dict[lx]['fibers'][f]["local_peer_port"]
-                r_inport = fibx["local_peer_port"]
+                r_inport = lx["local_peer_port"]
                 t_flows[src]["b"] = {"in": r_inport, "out": r_outport}
 
             #inport = self.links_dict[lx]['fibers'][f]["dst_port"]
-            inport = fibx["dst_port"]
+            inport = lx["dst_port"]
             if bidir:
                 #r_outport = self.links_dict[lx]['fibers'][f]["remote_peer_port"]
-                r_outport = fibx["remote_peer_port"]
+                r_outport = lx["remote_peer_port"]
             t_flows[dst] = {}
             t_flows[dst]["f"] = {}
             t_flows[dst]["b"] = {}
@@ -436,8 +500,9 @@ class RSA():
             print(t_flows)
         print("INFO: Flow matrix computed")
 
-        return t_flows, band, slots, fibers_f, fibers_b
+        return t_flows, band, slots, {}, {}
 
+    #function ivoked for fs lightpaths only
     def select_slots_and_ports_fs(self, links, n_slots, c, l, s, bidir, o_band_id):
         if debug:
             print(self.links_dict)
@@ -447,22 +512,20 @@ class RSA():
             return None, None, None, None, None
         if debug:
             print(band, slots)
-        fibers_f = self.get_fibers_forward(links, slots, band)
-        self.update_optical_band(o_band_id, slots, band)
-        fibers_b = []
+        self.get_fibers_forward(links, slots, band)
         if bidir:
-            fibers_b = self.get_fibers_backward(links, fibers_f, slots, band)
+            self.get_fibers_backward(links, slots, band)
+
+        #fibers_f = self.get_fibers_forward(links, slots, band)
+        self.update_optical_band(o_band_id, slots, band)
+        #fibers_b = []
+        #if bidir:
+        #    fibers_b = self.get_fibers_backward(links, fibers_f, slots, band)
         '''
 
             rev_o_band_id = self.optical_bands[o_band_id]["reverse_optical_band_id"]
             self.update_optical_band(rev_o_band_id, slots, band)
         '''
-        if debug:
-            print("forward")
-            print(fibers_f)
-            if bidir:
-                print("backward")
-                print(fibers_b)
         add = links[0]
         drop = links[-1]
         port_0 = "0"
@@ -470,11 +533,10 @@ class RSA():
         t_flows = {}
 
         #flows_add_side
-        f = fibers_f[add]
         src, dst = add.split("-")
-        fibx = self.get_fiber_details(add, f)
+        lx = self.get_link_by_name(add)["optical_details"]
         #outport = self.links_dict[add]['fibers'][f]["src_port"]
-        outport = fibx["src_port"]
+        outport = lx["src_port"]
         #T1 rules
         t_flows[src] = {}
         t_flows[src]["f"] = {}
@@ -482,7 +544,7 @@ class RSA():
         t_flows[src]["f"] = {"in": port_0, "out": outport}
         if bidir:
             #r_inport = self.links_dict[add]['fibers'][f]["local_peer_port"]
-            r_inport = fibx["local_peer_port"]
+            r_inport = lx["local_peer_port"]
             t_flows[src]["b"] = {"in": r_inport, "out": port_0}
 
         #R1 rules
@@ -490,27 +552,26 @@ class RSA():
         t_flows[dst]["f"] = {}
         t_flows[dst]["b"] = {}
         #inport = self.links_dict[add]['fibers'][f]["dst_port"]
-        inport = fibx["dst_port"]
+        inport = lx["dst_port"]
         opt_band_src_port = self.optical_bands[o_band_id]["src_port"]
         t_flows[dst]["f"] = {"in": inport, "out": opt_band_src_port}
         #to modify to peer ports
         if bidir:
             #r_inport = self.links_dict[add]['fibers'][f]["local_peer_port"]
-            r_inport = fibx["local_peer_port"]
+            r_inport = lx["local_peer_port"]
             t_flows[src]["b"] = {"in": r_inport, "out": port_0}
         if bidir:
             rev_opt_band_dst_port = self.optical_bands[o_band_id]["rev_dst_port"]
             #r_outport = self.links_dict[add]['fibers'][f]["remote_peer_port"]
-            r_outport = fibx["remote_peer_port"]
+            r_outport = lx["remote_peer_port"]
             t_flows[dst]["b"] = {"in": rev_opt_band_dst_port, "out": r_outport}
 
         #flows_drop_side
         # R2 rules
-        f = fibers_f[drop]
+        ly = self.get_link_by_name(drop)["optical_details"]
         src, dst = drop.split("-")
-        fiby = self.get_fiber_details(drop, f)
         #outport = self.links_dict[drop]['fibers'][f]["src_port"]
-        outport = fiby["src_port"]
+        outport = ly["src_port"]
 
         t_flows[src] = {}
         t_flows[src]["f"] = {}
@@ -520,17 +581,17 @@ class RSA():
         if bidir:
             rev_opt_band_src_port = self.optical_bands[o_band_id]["rev_src_port"]
             #r_inport = self.links_dict[drop]['fibers'][f]["local_peer_port"]
-            r_inport = fiby["local_peer_port"]
+            r_inport = ly["local_peer_port"]
             t_flows[src]["b"] = {"in": r_inport, "out": rev_opt_band_src_port}
         t_flows[dst] = {}
         t_flows[dst]["f"] = {}
         t_flows[dst]["b"] = {}
         #inport = self.links_dict[drop]['fibers'][f]["dst_port"]
-        inport = fiby["dst_port"]
+        inport = ly["dst_port"]
         t_flows[dst]["f"] = {"in": inport, "out": port_0}
         if bidir:
             #r_inport = self.links_dict[drop]['fibers'][f]["remote_peer_port"]
-            r_inport = fiby["remote_peer_port"]
+            r_inport = ly["remote_peer_port"]
             t_flows[dst]["b"] = {"in": port_0, "out": r_inport}
 
         if debug:
@@ -540,7 +601,7 @@ class RSA():
             print(t_flows)
         print("INFO: Flow matrix computed for Flex Lightpath")
 
-        return t_flows, band, slots, fibers_f, fibers_b
+        return t_flows, band, slots, {}, {}
 
     def rsa_computation(self, src, dst, rate, bidir):
         self.flow_id += 1
@@ -676,7 +737,8 @@ class RSA():
         if len(c_slots) > 0 or len(l_slots) > 0 or len(s_slots) > 0:
             flow_list, band_range, slots, fiber_f, fiber_b = self.select_slots_and_ports(links, num_slots, c_slots, l_slots, s_slots, bidir)
             f0, band = freqency_converter(band_range, slots)
-            print(flow_list, band_range, slots, fiber_f, fiber_b)
+            if debug:
+                print(flow_list, band_range, slots, fiber_f, fiber_b)
             '''
 
             flow_list_b = {}
@@ -696,29 +758,34 @@ class RSA():
             if flow_list is None:
                 self.null_values(self.flow_id)
                 return self.flow_id, []
-            slots_i = []
+            #slots_i = []
+            #for i in slots:
+            #    slots_i.append(int(i))
+            slots_i = {}
             for i in slots:
-                slots_i.append(int(i))
+                slots_i[str(i)] = 1
 
             # return links, path, flow_list, band_range, slots, fiber_f, fiber_b, op, num_slots, f0, band
             #        links, path, flows, bx, slots, fiber_f, fiber_b, op, n_slots, f0, band
+            if debug:
+                print(links)
             if len(flow_list) > 0:
                 src_port = flow_list[path[0]]['f']['out']
                 dst_port = flow_list[path[-1]]['f']['in']
-                print(flow_list)
-            if len(fiber_f.keys()) == 1:
-                link_x = list(fiber_f.keys())[0]
+                if debug:
+                    print(flow_list)
+            if len(links) == 1:
                 #fib_x = fiber_f[link_x]
                 #rev_dst_port = self.links_dict[link_x]['fibers'][fib_x]["local_peer_port"]
                 #rev_src_port = self.links_dict[link_x]['fibers'][fib_x]["remote_peer_port"]
-                fibx = self.get_fiber_details(link_x, fiber_f[link_x])
+                fibx = self.get_link_by_name(links[0])["optical_details"]
                 rev_dst_port = fibx["local_peer_port"]
                 rev_src_port = fibx["remote_peer_port"]
             else:
-                link_in = list(fiber_f.keys())[0]
-                link_out = list(fiber_f.keys())[-1]
-                fib_inx = self.get_fiber_details(link_in, fiber_f[link_in])
-                fib_outx = self.get_fiber_details(link_out, fiber_f[link_out])
+                link_in = links[0]
+                link_out = links[-1]
+                fib_inx = self.get_link_by_name(link_in)["optical_details"]
+                fib_outx = self.get_link_by_name(link_out)["optical_details"]
                 rev_dst_port = fib_inx["local_peer_port"]
                 rev_src_port = fib_outx["remote_peer_port"]
 
@@ -790,6 +857,7 @@ class RSA():
                 return self.flow_id, []
             optical_band_id, temp_links = self.create_optical_band(links, path, bidir, num_slots_ob)
             return None, optical_band_id
+        print("INFO: TP to TP connection")
         self.flow_id += 1
         self.db_flows[self.flow_id] = {}
         self.db_flows[self.flow_id]["flow_id"] = self.flow_id
@@ -797,7 +865,7 @@ class RSA():
         self.db_flows[self.flow_id]["dst"] = dst
         self.db_flows[self.flow_id]["bitrate"] = rate
         self.db_flows[self.flow_id]["bidir"] = bidir
-        print("INFO: TP to TP connection")
+
         if band is None:
             temp_links2 = []
             temp_path = []
@@ -816,7 +884,6 @@ class RSA():
                 temp_path.append(roadm_dst)
                 temp_path.append(t_dst)
                 existing_ob = self.get_optical_bands(roadm_src, roadm_dst)
-               
 
                 if len(existing_ob) > 0:
                     print("INFO: Evaluating existing OB  {}".format(existing_ob))
@@ -879,13 +946,7 @@ class RSA():
         links, path = self.compute_path(src, dst)
         optical_band_id, temp_links = self.create_optical_band(links, path, bidir, num_slots_ob)
         op, num_slots = map_rate_to_slot(rate)
-        # self.flow_id += 1
-        # self.db_flows[self.flow_id] = {}
-        # self.db_flows[self.flow_id]["flow_id"] = self.flow_id
-        # self.db_flows[self.flow_id]["src"] = src
-        # self.db_flows[self.flow_id]["dst"] = dst
-        # self.db_flows[self.flow_id]["bitrate"] = rate
-        # self.db_flows[self.flow_id]["bidir"] = bidir
+
 
         if debug:
             print(temp_links)
diff --git a/src/opticalcontroller/__init__.py b/src/opticalcontroller/__init__.py
index 38d04994f..1549d9811 100644
--- a/src/opticalcontroller/__init__.py
+++ b/src/opticalcontroller/__init__.py
@@ -11,3 +11,4 @@
 # 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/opticalcontroller/dijsktra.py b/src/opticalcontroller/dijsktra.py
index a86d1d93d..5be78c624 100644
--- a/src/opticalcontroller/dijsktra.py
+++ b/src/opticalcontroller/dijsktra.py
@@ -1,21 +1,3 @@
-# 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.
-
-# TODO: migrate to NetworkX:
-# https://networkx.org/documentation/stable/index.html
-# https://networkx.org/documentation/stable/reference/algorithms/shortest_paths.html
-
 import sys
 
 class Vertex:
@@ -237,4 +219,4 @@ if __name__ == '__main__':
     print ('The shortest path : %s' %(path[::-1]))"""
 
     p = shortest_path(g, g.get_vertex('a'), g.get_vertex('e'))
-    print(p)
+    print(p)
\ No newline at end of file
diff --git a/src/opticalcontroller/json_files/nodes.json b/src/opticalcontroller/json_files/nodes.json
index 60f017c19..51f19448e 100644
--- a/src/opticalcontroller/json_files/nodes.json
+++ b/src/opticalcontroller/json_files/nodes.json
@@ -22,14 +22,42 @@
         "type":"OC-ROADM",
         "driver": "OpticalOC"
     },
-    "T1":{
+    "T1.1":{
         "id":3,
         "ip":"10.30.2.210",
         "port":"50001",
         "type":"OC-TP",
         "driver": "OpticalOC"
     },
-    "T2":{
+    "T1.2":{
+        "id":3,
+        "ip":"10.30.2.210",
+        "port":"50001",
+        "type":"OC-TP",
+        "driver": "OpticalOC"
+    },
+    "T1.3":{
+        "id":3,
+        "ip":"10.30.2.210",
+        "port":"50001",
+        "type":"OC-TP",
+        "driver": "OpticalOC"
+    },
+    "T2.1":{
+        "id":4,
+        "ip":"10.30.2.211",
+        "port":"50001",
+        "type":"OC-TP",
+        "driver": "OpticalOC"
+    },
+    "T2.2":{
+        "id":4,
+        "ip":"10.30.2.211",
+        "port":"50001",
+        "type":"OC-TP",
+        "driver": "OpticalOC"
+    },
+    "T2.3":{
         "id":4,
         "ip":"10.30.2.211",
         "port":"50001",
diff --git a/src/opticalcontroller/json_files/tfs.json b/src/opticalcontroller/json_files/tfs.json
index 31803b893..46ee3da95 100644
--- a/src/opticalcontroller/json_files/tfs.json
+++ b/src/opticalcontroller/json_files/tfs.json
@@ -1,16 +1,17 @@
 {
 	"links": [
 		{
+			"name": "T1.1-R1",
 			"link_id": {
 				"link_uuid": {
-					"uuid": "T1->R1"
+					"uuid": "T1.1->R1"
 				}
 			},
 			"link_endpoint_ids": [
 				{
 					"device_id": {
 						"device_uuid": {
-							"uuid": "T1"
+							"uuid": "T1.1"
 						}
 					},
 					"endpoint_uuid": {
@@ -28,96 +29,294 @@
 					}
 				}
 			],
-			"optical_link": {
-				"name": "T1-R1",
-				"details": {
-					"length": 0,
-					"source": "muxT",
-					"target": "srgR",
-					"fibers": [
-						{
-							"ID": "M1",
-							"length": 0,
-							"src_port": "1",
-							"dst_port": "12",
-							"local_peer_port": "1",
-							"remote_peer_port": "2",
-							"used": false,
-							"c_slots": [
-								1,
-								2,
-								3,
-								4,
-								5,
-								6,
-								7,
-								8,
-								9,
-								10,
-								11,
-								12,
-								13,
-								14,
-								15,
-								16,
-								17,
-								18,
-								19,
-								20
-							],
-							"l_slots": [
-								101,
-								102,
-								103,
-								104,
-								105,
-								106,
-								107,
-								108,
-								109,
-								110,
-								111,
-								112,
-								113,
-								114,
-								115,
-								116,
-								117,
-								118,
-								119,
-								120
-							],
-							"s_slots": [
-								501,
-								502,
-								503,
-								504,
-								505,
-								506,
-								507,
-								508,
-								509,
-								510,
-								511,
-								512,
-								513,
-								514,
-								515,
-								516,
-								517,
-								518,
-								519,
-								520
-							]
+			"optical_details": {
+				"length": 0,
+				"src_port": "1",
+				"dst_port": "12",
+				"local_peer_port": "1",
+				"remote_peer_port": "2",
+				"used": false,
+				"c_slots": [
+					1,
+					2,
+					3,
+					4,
+					5,
+					6,
+					7,
+					8,
+					9,
+					10,
+					11,
+					12,
+					13,
+					14,
+					15,
+					16,
+					17,
+					18,
+					19,
+					20
+				],
+				"l_slots": [
+					101,
+					102,
+					103,
+					104,
+					105,
+					106,
+					107,
+					108,
+					109,
+					110,
+					111,
+					112,
+					113,
+					114,
+					115,
+					116,
+					117,
+					118,
+					119,
+					120
+				],
+				"s_slots": [
+					501,
+					502,
+					503,
+					504,
+					505,
+					506,
+					507,
+					508,
+					509,
+					510,
+					511,
+					512,
+					513,
+					514,
+					515,
+					516,
+					517,
+					518,
+					519,
+					520
+				]
+			}
+		},
+		{
+			"name": "T1.2-R1",
+			"link_id": {
+				"link_uuid": {
+					"uuid": "T1.2->R1"
+				}
+			},
+			"link_endpoint_ids": [
+				{
+					"device_id": {
+						"device_uuid": {
+							"uuid": "T1.2"
 						}
-					]
+					},
+					"endpoint_uuid": {
+						"uuid": "1"
+					}
+				},
+				{
+					"device_id": {
+						"device_uuid": {
+							"uuid": "R1"
+						}
+					},
+					"endpoint_uuid": {
+						"uuid": "13"
+					}
 				}
+			],
+			"optical_details": {
+				"length": 0,
+				"src_port": "1",
+				"dst_port": "13",
+				"local_peer_port": "1",
+				"remote_peer_port": "3",
+				"used": false,
+				"c_slots": [
+					1,
+					2,
+					3,
+					4,
+					5,
+					6,
+					7,
+					8,
+					9,
+					10,
+					11,
+					12,
+					13,
+					14,
+					15,
+					16,
+					17,
+					18,
+					19,
+					20
+				],
+				"l_slots": [
+					101,
+					102,
+					103,
+					104,
+					105,
+					106,
+					107,
+					108,
+					109,
+					110,
+					111,
+					112,
+					113,
+					114,
+					115,
+					116,
+					117,
+					118,
+					119,
+					120
+				],
+				"s_slots": [
+					501,
+					502,
+					503,
+					504,
+					505,
+					506,
+					507,
+					508,
+					509,
+					510,
+					511,
+					512,
+					513,
+					514,
+					515,
+					516,
+					517,
+					518,
+					519,
+					520
+				]
 			}
 		},
 		{
+			"name": "T1.3-R1",
 			"link_id": {
 				"link_uuid": {
-					"uuid": "R1->T1"
+					"uuid": "T1.3->R1"
+				}
+			},
+			"link_endpoint_ids": [
+				{
+					"device_id": {
+						"device_uuid": {
+							"uuid": "T1.3"
+						}
+					},
+					"endpoint_uuid": {
+						"uuid": "1"
+					}
+				},
+				{
+					"device_id": {
+						"device_uuid": {
+							"uuid": "R1"
+						}
+					},
+					"endpoint_uuid": {
+						"uuid": "14"
+					}
+				}
+			],
+			"optical_details": {
+				"length": 0,
+				"src_port": "1",
+				"dst_port": "14",
+				"local_peer_port": "1",
+				"remote_peer_port": "4",
+				"used": false,
+				"c_slots": [
+					1,
+					2,
+					3,
+					4,
+					5,
+					6,
+					7,
+					8,
+					9,
+					10,
+					11,
+					12,
+					13,
+					14,
+					15,
+					16,
+					17,
+					18,
+					19,
+					20
+				],
+				"l_slots": [
+					101,
+					102,
+					103,
+					104,
+					105,
+					106,
+					107,
+					108,
+					109,
+					110,
+					111,
+					112,
+					113,
+					114,
+					115,
+					116,
+					117,
+					118,
+					119,
+					120
+				],
+				"s_slots": [
+					501,
+					502,
+					503,
+					504,
+					505,
+					506,
+					507,
+					508,
+					509,
+					510,
+					511,
+					512,
+					513,
+					514,
+					515,
+					516,
+					517,
+					518,
+					519,
+					520
+				]
+			}
+		},
+		{
+			"name": "R1-T1.1",
+			"link_id": {
+				"link_uuid": {
+					"uuid": "R1->T1.1"
 				}
 			},
 			"link_endpoint_ids": [
@@ -134,7 +333,7 @@
 				{
 					"device_id": {
 						"device_uuid": {
-							"uuid": "T1"
+							"uuid": "T1.1"
 						}
 					},
 					"endpoint_uuid": {
@@ -142,96 +341,190 @@
 					}
 				}
 			],
-            "optical_link": {
-				"name": "R1-T1",
-				"details": {
-					"length": 0,
-					"source": "srgT",
-					"target": "muxT",
-					"fibers": [
-						{
-							"ID": "M1",
-							"length": 0,
-							"src_port": "2",
-							"dst_port": "1",
-							"local_peer_port": "12",
-							"remote_peer_port": "1",
-							"used": false,
-							"c_slots": [
-								1,
-								2,
-								3,
-								4,
-								5,
-								6,
-								7,
-								8,
-								9,
-								10,
-								11,
-								12,
-								13,
-								14,
-								15,
-								16,
-								17,
-								18,
-								19,
-								20
-							],
-							"l_slots": [
-								101,
-								102,
-								103,
-								104,
-								105,
-								106,
-								107,
-								108,
-								109,
-								110,
-								111,
-								112,
-								113,
-								114,
-								115,
-								116,
-								117,
-								118,
-								119,
-								120
-							],
-							"s_slots": [
-								501,
-								502,
-								503,
-								504,
-								505,
-								506,
-								507,
-								508,
-								509,
-								510,
-								511,
-								512,
-								513,
-								514,
-								515,
-								516,
-								517,
-								518,
-								519,
-								520
-							]
+			"optical_details": {
+				"length": 0,
+				"src_port": "2",
+				"dst_port": "1",
+				"local_peer_port": "12",
+				"remote_peer_port": "1",
+				"used": false,
+				"c_slots": [
+					1,
+					2,
+					3,
+					4,
+					5,
+					6,
+					7,
+					8,
+					9,
+					10,
+					11,
+					12,
+					13,
+					14,
+					15,
+					16,
+					17,
+					18,
+					19,
+					20
+				],
+				"l_slots": [
+					101,
+					102,
+					103,
+					104,
+					105,
+					106,
+					107,
+					108,
+					109,
+					110,
+					111,
+					112,
+					113,
+					114,
+					115,
+					116,
+					117,
+					118,
+					119,
+					120
+				],
+				"s_slots": [
+					501,
+					502,
+					503,
+					504,
+					505,
+					506,
+					507,
+					508,
+					509,
+					510,
+					511,
+					512,
+					513,
+					514,
+					515,
+					516,
+					517,
+					518,
+					519,
+					520
+				]
+			}
+		},
+		{
+			"name": "R1-T1.2",
+			"link_id": {
+				"link_uuid": {
+					"uuid": "R1->T1.2"
+				}
+			},
+			"link_endpoint_ids": [
+				{
+					"device_id": {
+						"device_uuid": {
+							"uuid": "R1"
+						}
+					},
+					"endpoint_uuid": {
+						"uuid": "3"
+					}
+				},
+				{
+					"device_id": {
+						"device_uuid": {
+							"uuid": "T1.2"
 						}
-					]
+					},
+					"endpoint_uuid": {
+						"uuid": "1"
+					}
 				}
+			],
+			"optical_details": {
+				"length": 0,
+				"src_port": "3",
+				"dst_port": "1",
+				"local_peer_port": "13",
+				"remote_peer_port": "1",
+				"used": false,
+				"c_slots": [
+					1,
+					2,
+					3,
+					4,
+					5,
+					6,
+					7,
+					8,
+					9,
+					10,
+					11,
+					12,
+					13,
+					14,
+					15,
+					16,
+					17,
+					18,
+					19,
+					20
+				],
+				"l_slots": [
+					101,
+					102,
+					103,
+					104,
+					105,
+					106,
+					107,
+					108,
+					109,
+					110,
+					111,
+					112,
+					113,
+					114,
+					115,
+					116,
+					117,
+					118,
+					119,
+					120
+				],
+				"s_slots": [
+					501,
+					502,
+					503,
+					504,
+					505,
+					506,
+					507,
+					508,
+					509,
+					510,
+					511,
+					512,
+					513,
+					514,
+					515,
+					516,
+					517,
+					518,
+					519,
+					520
+				]
 			}
 		},
 		{
+			"name": "R1-T1.3",
 			"link_id": {
 				"link_uuid": {
-					"uuid": "R1->R2"
+					"uuid": "R1->T1.3"
 				}
 			},
 			"link_endpoint_ids": [
@@ -242,107 +535,201 @@
 						}
 					},
 					"endpoint_uuid": {
-						"uuid": "3"
+						"uuid": "4"
 					}
 				},
 				{
 					"device_id": {
 						"device_uuid": {
-							"uuid": "R2"
+							"uuid": "T1.3"
 						}
 					},
 					"endpoint_uuid": {
-						"uuid": "14"
+						"uuid": "1"
 					}
 				}
 			],
-            "optical_link": {
-				"name": "R1-R2",
-				"details": {
-					"length": 0,
-					"source": "D1",
-					"target": "D1",
-					"fibers": [
-						{
-							"ID": "D11",
-							"length": 0,
-							"src_port": "3",
-							"dst_port": "14",
-							"local_peer_port": "13",
-							"remote_peer_port": "4",
-							"c_slots": [
-								1,
-								2,
-								3,
-								4,
-								5,
-								6,
-								7,
-								8,
-								9,
-								10,
-								11,
-								12,
-								13,
-								14,
-								15,
-								16,
-								17,
-								18,
-								19,
-								20
-							],
-							"l_slots": [
-								101,
-								102,
-								103,
-								104,
-								105,
-								106,
-								107,
-								108,
-								109,
-								110,
-								111,
-								112,
-								113,
-								114,
-								115,
-								116,
-								117,
-								118,
-								119,
-								120
-							],
-							"s_slots": [
-								501,
-								502,
-								503,
-								504,
-								505,
-								506,
-								507,
-								508,
-								509,
-								510,
-								511,
-								512,
-								513,
-								514,
-								515,
-								516,
-								517,
-								518,
-								519,
-								520
-							]
+			"optical_details": {
+				"length": 0,
+				"src_port": "4",
+				"dst_port": "1",
+				"local_peer_port": "14",
+				"remote_peer_port": "1",
+				"used": false,
+				"c_slots": [
+					1,
+					2,
+					3,
+					4,
+					5,
+					6,
+					7,
+					8,
+					9,
+					10,
+					11,
+					12,
+					13,
+					14,
+					15,
+					16,
+					17,
+					18,
+					19,
+					20
+				],
+				"l_slots": [
+					101,
+					102,
+					103,
+					104,
+					105,
+					106,
+					107,
+					108,
+					109,
+					110,
+					111,
+					112,
+					113,
+					114,
+					115,
+					116,
+					117,
+					118,
+					119,
+					120
+				],
+				"s_slots": [
+					501,
+					502,
+					503,
+					504,
+					505,
+					506,
+					507,
+					508,
+					509,
+					510,
+					511,
+					512,
+					513,
+					514,
+					515,
+					516,
+					517,
+					518,
+					519,
+					520
+				]
+			}
+		},
+		{
+			"name": "R1-R2",
+			"link_id": {
+				"link_uuid": {
+					"uuid": "R1->R2"
+				}
+			},
+			"link_endpoint_ids": [
+				{
+					"device_id": {
+						"device_uuid": {
+							"uuid": "R1"
 						}
-					]
+					},
+					"endpoint_uuid": {
+						"uuid": "101"
+					}
+				},
+				{
+					"device_id": {
+						"device_uuid": {
+							"uuid": "R2"
+						}
+					},
+					"endpoint_uuid": {
+						"uuid": "201"
+					}
 				}
+			],
+            "optical_details": {
+				"length": 0,
+				"src_port": "101",
+				"dst_port": "201",
+				"local_peer_port": "201",
+				"remote_peer_port": "101",
+				"c_slots": [
+					1,
+					2,
+					3,
+					4,
+					5,
+					6,
+					7,
+					8,
+					9,
+					10,
+					11,
+					12,
+					13,
+					14,
+					15,
+					16,
+					17,
+					18,
+					19,
+					20
+				],
+				"l_slots": [
+					101,
+					102,
+					103,
+					104,
+					105,
+					106,
+					107,
+					108,
+					109,
+					110,
+					111,
+					112,
+					113,
+					114,
+					115,
+					116,
+					117,
+					118,
+					119,
+					120
+				],
+				"s_slots": [
+					501,
+					502,
+					503,
+					504,
+					505,
+					506,
+					507,
+					508,
+					509,
+					510,
+					511,
+					512,
+					513,
+					514,
+					515,
+					516,
+					517,
+					518,
+					519,
+					520
+				]
 			}
 		},
 		{
-		"link_id": {
+			"name": "R2-R1",
+			"link_id": {
 				"link_uuid": {
 					"uuid": "R2->R1"
 				}
@@ -355,7 +742,7 @@
 						}
 					},
 					"endpoint_uuid": {
-						"uuid": "4"
+						"uuid": "101"
 					}
 				},
 				{
@@ -365,110 +752,308 @@
 						}
 					},
 					"endpoint_uuid": {
-						"uuid": "13"
+						"uuid": "201"
+					}
+				}
+			],
+            "optical_details": {
+				"length": 0,
+				"src_port": "101",
+				"dst_port": "201",
+				"local_peer_port": "201",
+				"remote_peer_port": "101",
+				"c_slots": [
+					1,
+					2,
+					3,
+					4,
+					5,
+					6,
+					7,
+					8,
+					9,
+					10,
+					11,
+					12,
+					13,
+					14,
+					15,
+					16,
+					17,
+					18,
+					19,
+					20
+				],
+				"l_slots": [
+					101,
+					102,
+					103,
+					104,
+					105,
+					106,
+					107,
+					108,
+					109,
+					110,
+					111,
+					112,
+					113,
+					114,
+					115,
+					116,
+					117,
+					118,
+					119,
+					120
+				],
+				"s_slots": [
+					501,
+					502,
+					503,
+					504,
+					505,
+					506,
+					507,
+					508,
+					509,
+					510,
+					511,
+					512,
+					513,
+					514,
+					515,
+					516,
+					517,
+					518,
+					519,
+					520
+				]
+			}
+		},
+		{
+			"name": "T2.1-R2",
+			"link_id": {
+				"link_uuid": {
+					"uuid": "T2.1->R2"
+				}
+			},
+			"link_endpoint_ids": [
+				{
+					"device_id": {
+						"device_uuid": {
+							"uuid": "T2.1"
+						}
+					},
+					"endpoint_uuid": {
+						"uuid": "1"
+					}
+				},
+				{
+					"device_id": {
+						"device_uuid": {
+							"uuid": "R2"
+						}
+					},
+					"endpoint_uuid": {
+						"uuid": "12"
 					}
 				}
 			],
-            "optical_link": {
-				"name": "R2-R1",
-				"details": {
-					"length": 0,
-					"source": "D1",
-					"target": "D1",
-					"fibers": [
-						{
-							"ID": "D11",
-							"length": 0,
-							"src_port": "4",
-							"dst_port": "13",
-							"local_peer_port": "14",
-							"remote_peer_port": "3",
-							"c_slots": [
-								1,
-								2,
-								3,
-								4,
-								5,
-								6,
-								7,
-								8,
-								9,
-								10,
-								11,
-								12,
-								13,
-								14,
-								15,
-								16,
-								17,
-								18,
-								19,
-								20
-							],
-							"l_slots": [
-								101,
-								102,
-								103,
-								104,
-								105,
-								106,
-								107,
-								108,
-								109,
-								110,
-								111,
-								112,
-								113,
-								114,
-								115,
-								116,
-								117,
-								118,
-								119,
-								120
-							],
-							"s_slots": [
-								501,
-								502,
-								503,
-								504,
-								505,
-								506,
-								507,
-								508,
-								509,
-								510,
-								511,
-								512,
-								513,
-								514,
-								515,
-								516,
-								517,
-								518,
-								519,
-								520
-							]
+			"optical_details": {
+				"length": 0,
+				"src_port": "1",
+				"dst_port": "12",
+				"local_peer_port": "1",
+				"remote_peer_port": "2",
+				"used": false,
+				"c_slots": [
+					1,
+					2,
+					3,
+					4,
+					5,
+					6,
+					7,
+					8,
+					9,
+					10,
+					11,
+					12,
+					13,
+					14,
+					15,
+					16,
+					17,
+					18,
+					19,
+					20
+				],
+				"l_slots": [
+					101,
+					102,
+					103,
+					104,
+					105,
+					106,
+					107,
+					108,
+					109,
+					110,
+					111,
+					112,
+					113,
+					114,
+					115,
+					116,
+					117,
+					118,
+					119,
+					120
+				],
+				"s_slots": [
+					501,
+					502,
+					503,
+					504,
+					505,
+					506,
+					507,
+					508,
+					509,
+					510,
+					511,
+					512,
+					513,
+					514,
+					515,
+					516,
+					517,
+					518,
+					519,
+					520
+				]
+			}
+		},
+		{
+			"name": "T2.2-R2",
+			"link_id": {
+				"link_uuid": {
+					"uuid": "T2.2->R2"
+				}
+			},
+			"link_endpoint_ids": [
+				{
+					"device_id": {
+						"device_uuid": {
+							"uuid": "T2.2"
+						}
+					},
+					"endpoint_uuid": {
+						"uuid": "1"
+					}
+				},
+				{
+					"device_id": {
+						"device_uuid": {
+							"uuid": "R2"
 						}
-					]
+					},
+					"endpoint_uuid": {
+						"uuid": "13"
+					}
 				}
+			],
+			"optical_details": {
+				"length": 0,
+				"src_port": "1",
+				"dst_port": "13",
+				"local_peer_port": "1",
+				"remote_peer_port": "3",
+				"used": false,
+				"c_slots": [
+					1,
+					2,
+					3,
+					4,
+					5,
+					6,
+					7,
+					8,
+					9,
+					10,
+					11,
+					12,
+					13,
+					14,
+					15,
+					16,
+					17,
+					18,
+					19,
+					20
+				],
+				"l_slots": [
+					101,
+					102,
+					103,
+					104,
+					105,
+					106,
+					107,
+					108,
+					109,
+					110,
+					111,
+					112,
+					113,
+					114,
+					115,
+					116,
+					117,
+					118,
+					119,
+					120
+				],
+				"s_slots": [
+					501,
+					502,
+					503,
+					504,
+					505,
+					506,
+					507,
+					508,
+					509,
+					510,
+					511,
+					512,
+					513,
+					514,
+					515,
+					516,
+					517,
+					518,
+					519,
+					520
+				]
 			}
 		},
 		{
+			"name": "T2.3-R2",
 			"link_id": {
 				"link_uuid": {
-					"uuid": "T2->R2"
+					"uuid": "T2.3->R2"
 				}
 			},
 			"link_endpoint_ids": [
 				{
 					"device_id": {
 						"device_uuid": {
-							"uuid": "T2"
+							"uuid": "T2.3"
 						}
 					},
 					"endpoint_uuid": {
-						"uuid": "6"
+						"uuid": "1"
 					}
 				},
 				{
@@ -478,100 +1063,194 @@
 						}
 					},
 					"endpoint_uuid": {
-						"uuid": "15"
+						"uuid": "14"
 					}
 				}
 			],
-            "optical_link": {
-				"name": "T2-R2",
-				"details": {
-					"length": 0,
-					"source": "srgT",
-					"target": "muxT",
-					"fibers": [
-						{
-							"ID": "M1",
-							"length": 0,
-							"src_port": "6",
-							"dst_port": "15",
-							"local_peer_port": "6",
-							"remote_peer_port": "5",
-							"used": false,
-							"c_slots": [
-								1,
-								2,
-								3,
-								4,
-								5,
-								6,
-								7,
-								8,
-								9,
-								10,
-								11,
-								12,
-								13,
-								14,
-								15,
-								16,
-								17,
-								18,
-								19,
-								20
-							],
-							"l_slots": [
-								101,
-								102,
-								103,
-								104,
-								105,
-								106,
-								107,
-								108,
-								109,
-								110,
-								111,
-								112,
-								113,
-								114,
-								115,
-								116,
-								117,
-								118,
-								119,
-								120
-							],
-							"s_slots": [
-								501,
-								502,
-								503,
-								504,
-								505,
-								506,
-								507,
-								508,
-								509,
-								510,
-								511,
-								512,
-								513,
-								514,
-								515,
-								516,
-								517,
-								518,
-								519,
-								520
-							]
+			"optical_details": {
+				"length": 0,
+				"src_port": "1",
+				"dst_port": "14",
+				"local_peer_port": "1",
+				"remote_peer_port": "4",
+				"used": false,
+				"c_slots": [
+					1,
+					2,
+					3,
+					4,
+					5,
+					6,
+					7,
+					8,
+					9,
+					10,
+					11,
+					12,
+					13,
+					14,
+					15,
+					16,
+					17,
+					18,
+					19,
+					20
+				],
+				"l_slots": [
+					101,
+					102,
+					103,
+					104,
+					105,
+					106,
+					107,
+					108,
+					109,
+					110,
+					111,
+					112,
+					113,
+					114,
+					115,
+					116,
+					117,
+					118,
+					119,
+					120
+				],
+				"s_slots": [
+					501,
+					502,
+					503,
+					504,
+					505,
+					506,
+					507,
+					508,
+					509,
+					510,
+					511,
+					512,
+					513,
+					514,
+					515,
+					516,
+					517,
+					518,
+					519,
+					520
+				]
+			}
+		},
+		{
+			"name": "R2-T2.1",
+			"link_id": {
+				"link_uuid": {
+					"uuid": "R2->T2.1"
+				}
+			},
+			"link_endpoint_ids": [
+				{
+					"device_id": {
+						"device_uuid": {
+							"uuid": "R2"
 						}
-					]
+					},
+					"endpoint_uuid": {
+						"uuid": "2"
+					}
+				},
+				{
+					"device_id": {
+						"device_uuid": {
+							"uuid": "T2.1"
+						}
+					},
+					"endpoint_uuid": {
+						"uuid": "1"
+					}
 				}
+			],
+			"optical_details": {
+				"length": 0,
+				"src_port": "2",
+				"dst_port": "1",
+				"local_peer_port": "12",
+				"remote_peer_port": "1",
+				"used": false,
+				"c_slots": [
+					1,
+					2,
+					3,
+					4,
+					5,
+					6,
+					7,
+					8,
+					9,
+					10,
+					11,
+					12,
+					13,
+					14,
+					15,
+					16,
+					17,
+					18,
+					19,
+					20
+				],
+				"l_slots": [
+					101,
+					102,
+					103,
+					104,
+					105,
+					106,
+					107,
+					108,
+					109,
+					110,
+					111,
+					112,
+					113,
+					114,
+					115,
+					116,
+					117,
+					118,
+					119,
+					120
+				],
+				"s_slots": [
+					501,
+					502,
+					503,
+					504,
+					505,
+					506,
+					507,
+					508,
+					509,
+					510,
+					511,
+					512,
+					513,
+					514,
+					515,
+					516,
+					517,
+					518,
+					519,
+					520
+				]
 			}
 		},
 		{
+			"name": "R2-T2.2",
 			"link_id": {
 				"link_uuid": {
-					"uuid": "R2->T2"
+					"uuid": "R1->T2.2"
 				}
 			},
 			"link_endpoint_ids": [
@@ -582,104 +1261,197 @@
 						}
 					},
 					"endpoint_uuid": {
-						"uuid": "5"
+						"uuid": "3"
 					}
 				},
 				{
 					"device_id": {
 						"device_uuid": {
-							"uuid": "T2"
+							"uuid": "T2.2"
 						}
 					},
 					"endpoint_uuid": {
-						"uuid": "6"
+						"uuid": "1"
 					}
 				}
 			],
-            "optical_link": {
-				"name": "R2-T2",
-				"details": {
-					"length": 0,
-					"source": "srgT",
-					"target": "muxT",
-					"fibers": [
-						{
-							"ID": "M1",
-							"length": 0,
-							"src_port": "5",
-							"dst_port": "6",
-							"local_peer_port": "15",
-							"remote_peer_port": "6",
-							"used": false,
-							"c_slots": [
-								1,
-								2,
-								3,
-								4,
-								5,
-								6,
-								7,
-								8,
-								9,
-								10,
-								11,
-								12,
-								13,
-								14,
-								15,
-								16,
-								17,
-								18,
-								19,
-								20
-							],
-							"l_slots": [
-								101,
-								102,
-								103,
-								104,
-								105,
-								106,
-								107,
-								108,
-								109,
-								110,
-								111,
-								112,
-								113,
-								114,
-								115,
-								116,
-								117,
-								118,
-								119,
-								120
-							],
-							"s_slots": [
-								501,
-								502,
-								503,
-								504,
-								505,
-								506,
-								507,
-								508,
-								509,
-								510,
-								511,
-								512,
-								513,
-								514,
-								515,
-								516,
-								517,
-								518,
-								519,
-								520
-							]
+			"optical_details": {
+				"length": 0,
+				"src_port": "3",
+				"dst_port": "1",
+				"local_peer_port": "13",
+				"remote_peer_port": "1",
+				"used": false,
+				"c_slots": [
+					1,
+					2,
+					3,
+					4,
+					5,
+					6,
+					7,
+					8,
+					9,
+					10,
+					11,
+					12,
+					13,
+					14,
+					15,
+					16,
+					17,
+					18,
+					19,
+					20
+				],
+				"l_slots": [
+					101,
+					102,
+					103,
+					104,
+					105,
+					106,
+					107,
+					108,
+					109,
+					110,
+					111,
+					112,
+					113,
+					114,
+					115,
+					116,
+					117,
+					118,
+					119,
+					120
+				],
+				"s_slots": [
+					501,
+					502,
+					503,
+					504,
+					505,
+					506,
+					507,
+					508,
+					509,
+					510,
+					511,
+					512,
+					513,
+					514,
+					515,
+					516,
+					517,
+					518,
+					519,
+					520
+				]
+			}
+		},
+		{
+			"name": "R2-T2.3",
+			"link_id": {
+				"link_uuid": {
+					"uuid": "R2->T2.3"
+				}
+			},
+			"link_endpoint_ids": [
+				{
+					"device_id": {
+						"device_uuid": {
+							"uuid": "R2"
 						}
-					]
+					},
+					"endpoint_uuid": {
+						"uuid": "4"
+					}
+				},
+				{
+					"device_id": {
+						"device_uuid": {
+							"uuid": "T2.3"
+						}
+					},
+					"endpoint_uuid": {
+						"uuid": "1"
+					}
 				}
+			],
+			"optical_details": {
+				"length": 0,
+				"src_port": "4",
+				"dst_port": "1",
+				"local_peer_port": "14",
+				"remote_peer_port": "1",
+				"used": false,
+				"c_slots": [
+					1,
+					2,
+					3,
+					4,
+					5,
+					6,
+					7,
+					8,
+					9,
+					10,
+					11,
+					12,
+					13,
+					14,
+					15,
+					16,
+					17,
+					18,
+					19,
+					20
+				],
+				"l_slots": [
+					101,
+					102,
+					103,
+					104,
+					105,
+					106,
+					107,
+					108,
+					109,
+					110,
+					111,
+					112,
+					113,
+					114,
+					115,
+					116,
+					117,
+					118,
+					119,
+					120
+				],
+				"s_slots": [
+					501,
+					502,
+					503,
+					504,
+					505,
+					506,
+					507,
+					508,
+					509,
+					510,
+					511,
+					512,
+					513,
+					514,
+					515,
+					516,
+					517,
+					518,
+					519,
+					520
+				]
 			}
 		}
 	]
diff --git a/src/opticalcontroller/json_files/tfs_dict.json b/src/opticalcontroller/json_files/tfs_dict.json
new file mode 100644
index 000000000..de7ec97fb
--- /dev/null
+++ b/src/opticalcontroller/json_files/tfs_dict.json
@@ -0,0 +1,1458 @@
+{
+	"optical_links": [
+		{
+			"name": "T1.1-R1",
+			"link_id": {
+				"link_uuid": {
+					"uuid": "T1.1->R1"
+				}
+			},
+			"link_endpoint_ids": [
+				{
+					"device_id": {
+						"device_uuid": {
+							"uuid": "T1.1"
+						}
+					},
+					"endpoint_uuid": {
+						"uuid": "1"
+					}
+				},
+				{
+					"device_id": {
+						"device_uuid": {
+							"uuid": "R1"
+						}
+					},
+					"endpoint_uuid": {
+						"uuid": "12"
+					}
+				}
+			],
+			"optical_details": {
+				"length": 0,
+				"src_port": "1",
+				"dst_port": "12",
+				"local_peer_port": "1",
+				"remote_peer_port": "2",
+				"used": false,
+				"c_slots": {
+					"1": 1,
+					"2": 1,
+					"3": 1,
+					"4": 1,
+					"5": 1,
+					"6": 1,
+					"7": 1,
+					"8": 1,
+					"9": 1,
+					"10": 1,
+					"11": 1,
+					"12": 1,
+					"13": 1,
+					"14": 1,
+					"15": 1,
+					"16": 1,
+					"17": 1,
+					"18": 1,
+					"19": 1,
+					"20": 1
+				},
+				"l_slots": {
+					"101": 1,
+					"102": 1,
+					"103": 1,
+					"104": 1,
+					"105": 1,
+					"106": 1,
+					"107": 1,
+					"108": 1,
+					"109": 1,
+					"110": 1,
+					"111": 1,
+					"112": 1,
+					"113": 1,
+					"114": 1,
+					"115": 1,
+					"116": 1,
+					"117": 1,
+					"118": 1,
+					"119": 1,
+					"120": 1
+				},
+				"s_slots": {
+					"501": 1,
+					"502": 1,
+					"503": 1,
+					"504": 1,
+					"505": 1,
+					"506": 1,
+					"507": 1,
+					"508": 1,
+					"509": 1,
+					"510": 1,
+					"511": 1,
+					"512": 1,
+					"513": 1,
+					"514": 1,
+					"515": 1,
+					"516": 1,
+					"517": 1,
+					"518": 1,
+					"519": 1,
+					"520": 1
+				}
+			}
+		},
+		{
+			"name": "T1.2-R1",
+			"link_id": {
+				"link_uuid": {
+					"uuid": "T1.2->R1"
+				}
+			},
+			"link_endpoint_ids": [
+				{
+					"device_id": {
+						"device_uuid": {
+							"uuid": "T1.2"
+						}
+					},
+					"endpoint_uuid": {
+						"uuid": "1"
+					}
+				},
+				{
+					"device_id": {
+						"device_uuid": {
+							"uuid": "R1"
+						}
+					},
+					"endpoint_uuid": {
+						"uuid": "13"
+					}
+				}
+			],
+			"optical_details": {
+				"length": 0,
+				"src_port": "1",
+				"dst_port": "13",
+				"local_peer_port": "1",
+				"remote_peer_port": "3",
+				"used": false,
+				"c_slots": {
+					"1": 1,
+					"2": 1,
+					"3": 1,
+					"4": 1,
+					"5": 1,
+					"6": 1,
+					"7": 1,
+					"8": 1,
+					"9": 1,
+					"10": 1,
+					"11": 1,
+					"12": 1,
+					"13": 1,
+					"14": 1,
+					"15": 1,
+					"16": 1,
+					"17": 1,
+					"18": 1,
+					"19": 1,
+					"20": 1
+				},
+				"l_slots": {
+					"101": 1,
+					"102": 1,
+					"103": 1,
+					"104": 1,
+					"105": 1,
+					"106": 1,
+					"107": 1,
+					"108": 1,
+					"109": 1,
+					"110": 1,
+					"111": 1,
+					"112": 1,
+					"113": 1,
+					"114": 1,
+					"115": 1,
+					"116": 1,
+					"117": 1,
+					"118": 1,
+					"119": 1,
+					"120": 1
+				},
+				"s_slots": {
+					"501": 1,
+					"502": 1,
+					"503": 1,
+					"504": 1,
+					"505": 1,
+					"506": 1,
+					"507": 1,
+					"508": 1,
+					"509": 1,
+					"510": 1,
+					"511": 1,
+					"512": 1,
+					"513": 1,
+					"514": 1,
+					"515": 1,
+					"516": 1,
+					"517": 1,
+					"518": 1,
+					"519": 1,
+					"520": 1
+				}
+			}
+		},
+		{
+			"name": "T1.3-R1",
+			"link_id": {
+				"link_uuid": {
+					"uuid": "T1.3->R1"
+				}
+			},
+			"link_endpoint_ids": [
+				{
+					"device_id": {
+						"device_uuid": {
+							"uuid": "T1.3"
+						}
+					},
+					"endpoint_uuid": {
+						"uuid": "1"
+					}
+				},
+				{
+					"device_id": {
+						"device_uuid": {
+							"uuid": "R1"
+						}
+					},
+					"endpoint_uuid": {
+						"uuid": "14"
+					}
+				}
+			],
+			"optical_details": {
+				"length": 0,
+				"src_port": "1",
+				"dst_port": "14",
+				"local_peer_port": "1",
+				"remote_peer_port": "4",
+				"used": false,
+				"c_slots": {
+					"1": 1,
+					"2": 1,
+					"3": 1,
+					"4": 1,
+					"5": 1,
+					"6": 1,
+					"7": 1,
+					"8": 1,
+					"9": 1,
+					"10": 1,
+					"11": 1,
+					"12": 1,
+					"13": 1,
+					"14": 1,
+					"15": 1,
+					"16": 1,
+					"17": 1,
+					"18": 1,
+					"19": 1,
+					"20": 1
+				},
+				"l_slots": {
+					"101": 1,
+					"102": 1,
+					"103": 1,
+					"104": 1,
+					"105": 1,
+					"106": 1,
+					"107": 1,
+					"108": 1,
+					"109": 1,
+					"110": 1,
+					"111": 1,
+					"112": 1,
+					"113": 1,
+					"114": 1,
+					"115": 1,
+					"116": 1,
+					"117": 1,
+					"118": 1,
+					"119": 1,
+					"120": 1
+				},
+				"s_slots": {
+					"501": 1,
+					"502": 1,
+					"503": 1,
+					"504": 1,
+					"505": 1,
+					"506": 1,
+					"507": 1,
+					"508": 1,
+					"509": 1,
+					"510": 1,
+					"511": 1,
+					"512": 1,
+					"513": 1,
+					"514": 1,
+					"515": 1,
+					"516": 1,
+					"517": 1,
+					"518": 1,
+					"519": 1,
+					"520": 1
+				}
+			}
+		},
+		{
+			"name": "R1-T1.1",
+			"link_id": {
+				"link_uuid": {
+					"uuid": "R1->T1.1"
+				}
+			},
+			"link_endpoint_ids": [
+				{
+					"device_id": {
+						"device_uuid": {
+							"uuid": "R1"
+						}
+					},
+					"endpoint_uuid": {
+						"uuid": "2"
+					}
+				},
+				{
+					"device_id": {
+						"device_uuid": {
+							"uuid": "T1.1"
+						}
+					},
+					"endpoint_uuid": {
+						"uuid": "1"
+					}
+				}
+			],
+			"optical_details": {
+				"length": 0,
+				"src_port": "2",
+				"dst_port": "1",
+				"local_peer_port": "12",
+				"remote_peer_port": "1",
+				"used": false,
+				"c_slots": {
+					"1": 1,
+					"2": 1,
+					"3": 1,
+					"4": 1,
+					"5": 1,
+					"6": 1,
+					"7": 1,
+					"8": 1,
+					"9": 1,
+					"10": 1,
+					"11": 1,
+					"12": 1,
+					"13": 1,
+					"14": 1,
+					"15": 1,
+					"16": 1,
+					"17": 1,
+					"18": 1,
+					"19": 1,
+					"20": 1
+				},
+				"l_slots": {
+					"101": 1,
+					"102": 1,
+					"103": 1,
+					"104": 1,
+					"105": 1,
+					"106": 1,
+					"107": 1,
+					"108": 1,
+					"109": 1,
+					"110": 1,
+					"111": 1,
+					"112": 1,
+					"113": 1,
+					"114": 1,
+					"115": 1,
+					"116": 1,
+					"117": 1,
+					"118": 1,
+					"119": 1,
+					"120": 1
+				},
+				"s_slots": {
+					"501": 1,
+					"502": 1,
+					"503": 1,
+					"504": 1,
+					"505": 1,
+					"506": 1,
+					"507": 1,
+					"508": 1,
+					"509": 1,
+					"510": 1,
+					"511": 1,
+					"512": 1,
+					"513": 1,
+					"514": 1,
+					"515": 1,
+					"516": 1,
+					"517": 1,
+					"518": 1,
+					"519": 1,
+					"520": 1
+				}
+			}
+		},
+		{
+			"name": "R1-T1.2",
+			"link_id": {
+				"link_uuid": {
+					"uuid": "R1->T1.2"
+				}
+			},
+			"link_endpoint_ids": [
+				{
+					"device_id": {
+						"device_uuid": {
+							"uuid": "R1"
+						}
+					},
+					"endpoint_uuid": {
+						"uuid": "3"
+					}
+				},
+				{
+					"device_id": {
+						"device_uuid": {
+							"uuid": "T1.2"
+						}
+					},
+					"endpoint_uuid": {
+						"uuid": "1"
+					}
+				}
+			],
+			"optical_details": {
+				"length": 0,
+				"src_port": "3",
+				"dst_port": "1",
+				"local_peer_port": "13",
+				"remote_peer_port": "1",
+				"used": false,
+				"c_slots": {
+					"1": 1,
+					"2": 1,
+					"3": 1,
+					"4": 1,
+					"5": 1,
+					"6": 1,
+					"7": 1,
+					"8": 1,
+					"9": 1,
+					"10": 1,
+					"11": 1,
+					"12": 1,
+					"13": 1,
+					"14": 1,
+					"15": 1,
+					"16": 1,
+					"17": 1,
+					"18": 1,
+					"19": 1,
+					"20": 1
+				},
+				"l_slots": {
+					"101": 1,
+					"102": 1,
+					"103": 1,
+					"104": 1,
+					"105": 1,
+					"106": 1,
+					"107": 1,
+					"108": 1,
+					"109": 1,
+					"110": 1,
+					"111": 1,
+					"112": 1,
+					"113": 1,
+					"114": 1,
+					"115": 1,
+					"116": 1,
+					"117": 1,
+					"118": 1,
+					"119": 1,
+					"120": 1
+				},
+				"s_slots": {
+					"501": 1,
+					"502": 1,
+					"503": 1,
+					"504": 1,
+					"505": 1,
+					"506": 1,
+					"507": 1,
+					"508": 1,
+					"509": 1,
+					"510": 1,
+					"511": 1,
+					"512": 1,
+					"513": 1,
+					"514": 1,
+					"515": 1,
+					"516": 1,
+					"517": 1,
+					"518": 1,
+					"519": 1,
+					"520": 1
+				}
+			}
+		},
+		{
+			"name": "R1-T1.3",
+			"link_id": {
+				"link_uuid": {
+					"uuid": "R1->T1.3"
+				}
+			},
+			"link_endpoint_ids": [
+				{
+					"device_id": {
+						"device_uuid": {
+							"uuid": "R1"
+						}
+					},
+					"endpoint_uuid": {
+						"uuid": "4"
+					}
+				},
+				{
+					"device_id": {
+						"device_uuid": {
+							"uuid": "T1.3"
+						}
+					},
+					"endpoint_uuid": {
+						"uuid": "1"
+					}
+				}
+			],
+			"optical_details": {
+				"length": 0,
+				"src_port": "4",
+				"dst_port": "1",
+				"local_peer_port": "14",
+				"remote_peer_port": "1",
+				"used": false,
+				"c_slots": {
+					"1": 1,
+					"2": 1,
+					"3": 1,
+					"4": 1,
+					"5": 1,
+					"6": 1,
+					"7": 1,
+					"8": 1,
+					"9": 1,
+					"10": 1,
+					"11": 1,
+					"12": 1,
+					"13": 1,
+					"14": 1,
+					"15": 1,
+					"16": 1,
+					"17": 1,
+					"18": 1,
+					"19": 1,
+					"20": 1
+				},
+				"l_slots": {
+					"101": 1,
+					"102": 1,
+					"103": 1,
+					"104": 1,
+					"105": 1,
+					"106": 1,
+					"107": 1,
+					"108": 1,
+					"109": 1,
+					"110": 1,
+					"111": 1,
+					"112": 1,
+					"113": 1,
+					"114": 1,
+					"115": 1,
+					"116": 1,
+					"117": 1,
+					"118": 1,
+					"119": 1,
+					"120": 1
+				},
+				"s_slots": {
+					"501": 1,
+					"502": 1,
+					"503": 1,
+					"504": 1,
+					"505": 1,
+					"506": 1,
+					"507": 1,
+					"508": 1,
+					"509": 1,
+					"510": 1,
+					"511": 1,
+					"512": 1,
+					"513": 1,
+					"514": 1,
+					"515": 1,
+					"516": 1,
+					"517": 1,
+					"518": 1,
+					"519": 1,
+					"520": 1
+				}
+			}
+		},
+		{
+			"name": "R1-R2",
+			"link_id": {
+				"link_uuid": {
+					"uuid": "R1->R2"
+				}
+			},
+			"link_endpoint_ids": [
+				{
+					"device_id": {
+						"device_uuid": {
+							"uuid": "R1"
+						}
+					},
+					"endpoint_uuid": {
+						"uuid": "101"
+					}
+				},
+				{
+					"device_id": {
+						"device_uuid": {
+							"uuid": "R2"
+						}
+					},
+					"endpoint_uuid": {
+						"uuid": "201"
+					}
+				}
+			],
+            "optical_details": {
+				"length": 0,
+				"src_port": "101",
+				"dst_port": "201",
+				"local_peer_port": "201",
+				"remote_peer_port": "101",
+				"c_slots": {
+					"1": 1,
+					"2": 1,
+					"3": 1,
+					"4": 1,
+					"5": 1,
+					"6": 1,
+					"7": 1,
+					"8": 1,
+					"9": 1,
+					"10": 1,
+					"11": 1,
+					"12": 1,
+					"13": 1,
+					"14": 1,
+					"15": 1,
+					"16": 1,
+					"17": 1,
+					"18": 1,
+					"19": 1,
+					"20": 1
+				},
+				"l_slots": {
+					"101": 1,
+					"102": 1,
+					"103": 1,
+					"104": 1,
+					"105": 1,
+					"106": 1,
+					"107": 1,
+					"108": 1,
+					"109": 1,
+					"110": 1,
+					"111": 1,
+					"112": 1,
+					"113": 1,
+					"114": 1,
+					"115": 1,
+					"116": 1,
+					"117": 1,
+					"118": 1,
+					"119": 1,
+					"120": 1
+				},
+				"s_slots": {
+					"501": 1,
+					"502": 1,
+					"503": 1,
+					"504": 1,
+					"505": 1,
+					"506": 1,
+					"507": 1,
+					"508": 1,
+					"509": 1,
+					"510": 1,
+					"511": 1,
+					"512": 1,
+					"513": 1,
+					"514": 1,
+					"515": 1,
+					"516": 1,
+					"517": 1,
+					"518": 1,
+					"519": 1,
+					"520": 1
+				}
+			}
+		},
+		{
+			"name": "R2-R1",
+			"link_id": {
+				"link_uuid": {
+					"uuid": "R2->R1"
+				}
+			},
+			"link_endpoint_ids": [
+				{
+					"device_id": {
+						"device_uuid": {
+							"uuid": "R2"
+						}
+					},
+					"endpoint_uuid": {
+						"uuid": "101"
+					}
+				},
+				{
+					"device_id": {
+						"device_uuid": {
+							"uuid": "R1"
+						}
+					},
+					"endpoint_uuid": {
+						"uuid": "201"
+					}
+				}
+			],
+            "optical_details": {
+				"length": 0,
+				"src_port": "101",
+				"dst_port": "201",
+				"local_peer_port": "201",
+				"remote_peer_port": "101",
+				"c_slots": {
+					"1": 1,
+					"2": 1,
+					"3": 1,
+					"4": 1,
+					"5": 1,
+					"6": 1,
+					"7": 1,
+					"8": 1,
+					"9": 1,
+					"10": 1,
+					"11": 1,
+					"12": 1,
+					"13": 1,
+					"14": 1,
+					"15": 1,
+					"16": 1,
+					"17": 1,
+					"18": 1,
+					"19": 1,
+					"20": 1
+				},
+				"l_slots": {
+					"101": 1,
+					"102": 1,
+					"103": 1,
+					"104": 1,
+					"105": 1,
+					"106": 1,
+					"107": 1,
+					"108": 1,
+					"109": 1,
+					"110": 1,
+					"111": 1,
+					"112": 1,
+					"113": 1,
+					"114": 1,
+					"115": 1,
+					"116": 1,
+					"117": 1,
+					"118": 1,
+					"119": 1,
+					"120": 1
+				},
+				"s_slots": {
+					"501": 1,
+					"502": 1,
+					"503": 1,
+					"504": 1,
+					"505": 1,
+					"506": 1,
+					"507": 1,
+					"508": 1,
+					"509": 1,
+					"510": 1,
+					"511": 1,
+					"512": 1,
+					"513": 1,
+					"514": 1,
+					"515": 1,
+					"516": 1,
+					"517": 1,
+					"518": 1,
+					"519": 1,
+					"520": 1
+				}
+			}
+		},
+		{
+			"name": "T2.1-R2",
+			"link_id": {
+				"link_uuid": {
+					"uuid": "T2.1->R2"
+				}
+			},
+			"link_endpoint_ids": [
+				{
+					"device_id": {
+						"device_uuid": {
+							"uuid": "T2.1"
+						}
+					},
+					"endpoint_uuid": {
+						"uuid": "1"
+					}
+				},
+				{
+					"device_id": {
+						"device_uuid": {
+							"uuid": "R2"
+						}
+					},
+					"endpoint_uuid": {
+						"uuid": "12"
+					}
+				}
+			],
+			"optical_details": {
+				"length": 0,
+				"src_port": "1",
+				"dst_port": "12",
+				"local_peer_port": "1",
+				"remote_peer_port": "2",
+				"used": false,
+				"c_slots": {
+					"1": 1,
+					"2": 1,
+					"3": 1,
+					"4": 1,
+					"5": 1,
+					"6": 1,
+					"7": 1,
+					"8": 1,
+					"9": 1,
+					"10": 1,
+					"11": 1,
+					"12": 1,
+					"13": 1,
+					"14": 1,
+					"15": 1,
+					"16": 1,
+					"17": 1,
+					"18": 1,
+					"19": 1,
+					"20": 1
+				},
+				"l_slots": {
+					"101": 1,
+					"102": 1,
+					"103": 1,
+					"104": 1,
+					"105": 1,
+					"106": 1,
+					"107": 1,
+					"108": 1,
+					"109": 1,
+					"110": 1,
+					"111": 1,
+					"112": 1,
+					"113": 1,
+					"114": 1,
+					"115": 1,
+					"116": 1,
+					"117": 1,
+					"118": 1,
+					"119": 1,
+					"120": 1
+				},
+				"s_slots": {
+					"501": 1,
+					"502": 1,
+					"503": 1,
+					"504": 1,
+					"505": 1,
+					"506": 1,
+					"507": 1,
+					"508": 1,
+					"509": 1,
+					"510": 1,
+					"511": 1,
+					"512": 1,
+					"513": 1,
+					"514": 1,
+					"515": 1,
+					"516": 1,
+					"517": 1,
+					"518": 1,
+					"519": 1,
+					"520": 1
+				}
+			}
+		},
+		{
+			"name": "T2.2-R2",
+			"link_id": {
+				"link_uuid": {
+					"uuid": "T2.2->R2"
+				}
+			},
+			"link_endpoint_ids": [
+				{
+					"device_id": {
+						"device_uuid": {
+							"uuid": "T2.2"
+						}
+					},
+					"endpoint_uuid": {
+						"uuid": "1"
+					}
+				},
+				{
+					"device_id": {
+						"device_uuid": {
+							"uuid": "R2"
+						}
+					},
+					"endpoint_uuid": {
+						"uuid": "13"
+					}
+				}
+			],
+			"optical_details": {
+				"length": 0,
+				"src_port": "1",
+				"dst_port": "13",
+				"local_peer_port": "1",
+				"remote_peer_port": "3",
+				"used": false,
+				"c_slots": {
+					"1": 1,
+					"2": 1,
+					"3": 1,
+					"4": 1,
+					"5": 1,
+					"6": 1,
+					"7": 1,
+					"8": 1,
+					"9": 1,
+					"10": 1,
+					"11": 1,
+					"12": 1,
+					"13": 1,
+					"14": 1,
+					"15": 1,
+					"16": 1,
+					"17": 1,
+					"18": 1,
+					"19": 1,
+					"20": 1
+				},
+				"l_slots": {
+					"101": 1,
+					"102": 1,
+					"103": 1,
+					"104": 1,
+					"105": 1,
+					"106": 1,
+					"107": 1,
+					"108": 1,
+					"109": 1,
+					"110": 1,
+					"111": 1,
+					"112": 1,
+					"113": 1,
+					"114": 1,
+					"115": 1,
+					"116": 1,
+					"117": 1,
+					"118": 1,
+					"119": 1,
+					"120": 1
+				},
+				"s_slots": {
+					"501": 1,
+					"502": 1,
+					"503": 1,
+					"504": 1,
+					"505": 1,
+					"506": 1,
+					"507": 1,
+					"508": 1,
+					"509": 1,
+					"510": 1,
+					"511": 1,
+					"512": 1,
+					"513": 1,
+					"514": 1,
+					"515": 1,
+					"516": 1,
+					"517": 1,
+					"518": 1,
+					"519": 1,
+					"520": 1
+				}
+			}
+		},
+		{
+			"name": "T2.3-R2",
+			"link_id": {
+				"link_uuid": {
+					"uuid": "T2.3->R2"
+				}
+			},
+			"link_endpoint_ids": [
+				{
+					"device_id": {
+						"device_uuid": {
+							"uuid": "T2.3"
+						}
+					},
+					"endpoint_uuid": {
+						"uuid": "1"
+					}
+				},
+				{
+					"device_id": {
+						"device_uuid": {
+							"uuid": "R2"
+						}
+					},
+					"endpoint_uuid": {
+						"uuid": "14"
+					}
+				}
+			],
+			"optical_details": {
+				"length": 0,
+				"src_port": "1",
+				"dst_port": "14",
+				"local_peer_port": "1",
+				"remote_peer_port": "4",
+				"used": false,
+				"c_slots": {
+					"1": 1,
+					"2": 1,
+					"3": 1,
+					"4": 1,
+					"5": 1,
+					"6": 1,
+					"7": 1,
+					"8": 1,
+					"9": 1,
+					"10": 1,
+					"11": 1,
+					"12": 1,
+					"13": 1,
+					"14": 1,
+					"15": 1,
+					"16": 1,
+					"17": 1,
+					"18": 1,
+					"19": 1,
+					"20": 1
+				},
+				"l_slots": {
+					"101": 1,
+					"102": 1,
+					"103": 1,
+					"104": 1,
+					"105": 1,
+					"106": 1,
+					"107": 1,
+					"108": 1,
+					"109": 1,
+					"110": 1,
+					"111": 1,
+					"112": 1,
+					"113": 1,
+					"114": 1,
+					"115": 1,
+					"116": 1,
+					"117": 1,
+					"118": 1,
+					"119": 1,
+					"120": 1
+				},
+				"s_slots": {
+					"501": 1,
+					"502": 1,
+					"503": 1,
+					"504": 1,
+					"505": 1,
+					"506": 1,
+					"507": 1,
+					"508": 1,
+					"509": 1,
+					"510": 1,
+					"511": 1,
+					"512": 1,
+					"513": 1,
+					"514": 1,
+					"515": 1,
+					"516": 1,
+					"517": 1,
+					"518": 1,
+					"519": 1,
+					"520": 1
+				}
+			}
+		},
+		{
+			"name": "R2-T2.1",
+			"link_id": {
+				"link_uuid": {
+					"uuid": "R2->T2.1"
+				}
+			},
+			"link_endpoint_ids": [
+				{
+					"device_id": {
+						"device_uuid": {
+							"uuid": "R2"
+						}
+					},
+					"endpoint_uuid": {
+						"uuid": "2"
+					}
+				},
+				{
+					"device_id": {
+						"device_uuid": {
+							"uuid": "T2.1"
+						}
+					},
+					"endpoint_uuid": {
+						"uuid": "1"
+					}
+				}
+			],
+			"optical_details": {
+				"length": 0,
+				"src_port": "2",
+				"dst_port": "1",
+				"local_peer_port": "12",
+				"remote_peer_port": "1",
+				"used": false,
+				"c_slots": {
+					"1": 1,
+					"2": 1,
+					"3": 1,
+					"4": 1,
+					"5": 1,
+					"6": 1,
+					"7": 1,
+					"8": 1,
+					"9": 1,
+					"10": 1,
+					"11": 1,
+					"12": 1,
+					"13": 1,
+					"14": 1,
+					"15": 1,
+					"16": 1,
+					"17": 1,
+					"18": 1,
+					"19": 1,
+					"20": 1
+				},
+				"l_slots": {
+					"101": 1,
+					"102": 1,
+					"103": 1,
+					"104": 1,
+					"105": 1,
+					"106": 1,
+					"107": 1,
+					"108": 1,
+					"109": 1,
+					"110": 1,
+					"111": 1,
+					"112": 1,
+					"113": 1,
+					"114": 1,
+					"115": 1,
+					"116": 1,
+					"117": 1,
+					"118": 1,
+					"119": 1,
+					"120": 1
+				},
+				"s_slots": {
+					"501": 1,
+					"502": 1,
+					"503": 1,
+					"504": 1,
+					"505": 1,
+					"506": 1,
+					"507": 1,
+					"508": 1,
+					"509": 1,
+					"510": 1,
+					"511": 1,
+					"512": 1,
+					"513": 1,
+					"514": 1,
+					"515": 1,
+					"516": 1,
+					"517": 1,
+					"518": 1,
+					"519": 1,
+					"520": 1
+				}
+			}
+		},
+		{
+			"name": "R2-T2.2",
+			"link_id": {
+				"link_uuid": {
+					"uuid": "R1->T2.2"
+				}
+			},
+			"link_endpoint_ids": [
+				{
+					"device_id": {
+						"device_uuid": {
+							"uuid": "R2"
+						}
+					},
+					"endpoint_uuid": {
+						"uuid": "3"
+					}
+				},
+				{
+					"device_id": {
+						"device_uuid": {
+							"uuid": "T2.2"
+						}
+					},
+					"endpoint_uuid": {
+						"uuid": "1"
+					}
+				}
+			],
+			"optical_details": {
+				"length": 0,
+				"src_port": "3",
+				"dst_port": "1",
+				"local_peer_port": "13",
+				"remote_peer_port": "1",
+				"used": false,
+				"c_slots": {
+					"1": 1,
+					"2": 1,
+					"3": 1,
+					"4": 1,
+					"5": 1,
+					"6": 1,
+					"7": 1,
+					"8": 1,
+					"9": 1,
+					"10": 1,
+					"11": 1,
+					"12": 1,
+					"13": 1,
+					"14": 1,
+					"15": 1,
+					"16": 1,
+					"17": 1,
+					"18": 1,
+					"19": 1,
+					"20": 1
+				},
+				"l_slots": {
+					"101": 1,
+					"102": 1,
+					"103": 1,
+					"104": 1,
+					"105": 1,
+					"106": 1,
+					"107": 1,
+					"108": 1,
+					"109": 1,
+					"110": 1,
+					"111": 1,
+					"112": 1,
+					"113": 1,
+					"114": 1,
+					"115": 1,
+					"116": 1,
+					"117": 1,
+					"118": 1,
+					"119": 1,
+					"120": 1
+				},
+				"s_slots": {
+					"501": 1,
+					"502": 1,
+					"503": 1,
+					"504": 1,
+					"505": 1,
+					"506": 1,
+					"507": 1,
+					"508": 1,
+					"509": 1,
+					"510": 1,
+					"511": 1,
+					"512": 1,
+					"513": 1,
+					"514": 1,
+					"515": 1,
+					"516": 1,
+					"517": 1,
+					"518": 1,
+					"519": 1,
+					"520": 1
+				}
+			}
+		},
+		{
+			"name": "R2-T2.3",
+			"link_id": {
+				"link_uuid": {
+					"uuid": "R2->T2.3"
+				}
+			},
+			"link_endpoint_ids": [
+				{
+					"device_id": {
+						"device_uuid": {
+							"uuid": "R2"
+						}
+					},
+					"endpoint_uuid": {
+						"uuid": "4"
+					}
+				},
+				{
+					"device_id": {
+						"device_uuid": {
+							"uuid": "T2.3"
+						}
+					},
+					"endpoint_uuid": {
+						"uuid": "1"
+					}
+				}
+			],
+			"optical_details": {
+				"length": 0,
+				"src_port": "4",
+				"dst_port": "1",
+				"local_peer_port": "14",
+				"remote_peer_port": "1",
+				"used": false,
+				"c_slots": {
+					"1": 1,
+					"2": 1,
+					"3": 1,
+					"4": 1,
+					"5": 1,
+					"6": 1,
+					"7": 1,
+					"8": 1,
+					"9": 1,
+					"10": 1,
+					"11": 1,
+					"12": 1,
+					"13": 1,
+					"14": 1,
+					"15": 1,
+					"16": 1,
+					"17": 1,
+					"18": 1,
+					"19": 1,
+					"20": 1
+				},
+				"l_slots": {
+					"101": 1,
+					"102": 1,
+					"103": 1,
+					"104": 1,
+					"105": 1,
+					"106": 1,
+					"107": 1,
+					"108": 1,
+					"109": 1,
+					"110": 1,
+					"111": 1,
+					"112": 1,
+					"113": 1,
+					"114": 1,
+					"115": 1,
+					"116": 1,
+					"117": 1,
+					"118": 1,
+					"119": 1,
+					"120": 1
+				},
+				"s_slots": {
+					"501": 1,
+					"502": 1,
+					"503": 1,
+					"504": 1,
+					"505": 1,
+					"506": 1,
+					"507": 1,
+					"508": 1,
+					"509": 1,
+					"510": 1,
+					"511": 1,
+					"512": 1,
+					"513": 1,
+					"514": 1,
+					"515": 1,
+					"516": 1,
+					"517": 1,
+					"518": 1,
+					"519": 1,
+					"520": 1
+				}
+			}
+		}
+	]
+}
\ No newline at end of file
diff --git a/src/opticalcontroller/requirements.in b/src/opticalcontroller/requirements.in
index fefe604bc..4746979fe 100644
--- a/src/opticalcontroller/requirements.in
+++ b/src/opticalcontroller/requirements.in
@@ -1,21 +1,22 @@
-# 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.
-
+aniso8601==9.0.1
+attrs==23.1.0
+blinker==1.6.2
+click==8.1.7
+colorama==0.4.6
 Flask==1.1.2
 flask-restplus==0.13.0
+importlib-metadata==6.8.0
+importlib-resources==6.0.1
 itsdangerous==1.1.0
 Jinja2==2.11.3
+jsonschema==4.19.0
+jsonschema-specifications==2023.7.1
 MarkupSafe==1.1.1
 numpy==1.23.0
+pkgutil-resolve-name==1.3.10
+pytz==2023.3.post1
+referencing==0.30.2
+rpds-py==0.10.3
+six==1.16.0
 Werkzeug==0.16.1
+zipp==3.16.2
diff --git a/src/opticalcontroller/requirements_opt.txt b/src/opticalcontroller/requirements_opt.txt
new file mode 100644
index 000000000..e4b8abe1b
--- /dev/null
+++ b/src/opticalcontroller/requirements_opt.txt
@@ -0,0 +1,7 @@
+Flask==1.1.2
+flask-restplus==0.13.0
+itsdangerous==1.1.0
+Jinja2==2.11.3
+MarkupSafe==1.1.1
+numpy==1.23.0
+Werkzeug==0.16.1
diff --git a/src/opticalcontroller/test.py b/src/opticalcontroller/test.py
new file mode 100644
index 000000000..255ee2de4
--- /dev/null
+++ b/src/opticalcontroller/test.py
@@ -0,0 +1,12 @@
+import json
+
+
+def readTopologyData():
+    topo_file = open("json_files/tfs_dict.json", 'r')
+    topo = json.load(topo_file)
+    # print(topo)
+    topo_file.close()
+    return topo
+
+
+print(readTopologyData())
\ No newline at end of file
diff --git a/src/opticalcontroller/tools.py b/src/opticalcontroller/tools.py
index 3b3223d81..197305255 100644
--- a/src/opticalcontroller/tools.py
+++ b/src/opticalcontroller/tools.py
@@ -1,20 +1,8 @@
-# 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 numpy as np
 from variables import  *
-import json
+import json , logging
+from context.client.ContextClient import ContextClient
+from common.proto.context_pb2 import TopologyId
 
 
 def common_slots(a, b):
@@ -54,20 +42,23 @@ def map_rate_to_slot(rate):
         return 2, 5
 
 
-def consecutives(x, val):
+def consecutives(link, val):
     res = []
     temp = []
+    x1 = list(link.keys())
+    x = str_list_to_int(x1)
     x.sort()
-    temp.append(x[0])
+    temp.append(int(x[0]))
     y = 1
+    #print(link, x)
     for i in range(1, len(x)):
-        if x[i] == x[i - 1] + 1:
+        if (int(x[i]) == int(x[i - 1]) + 1) and link[str(x[i])] == 1:
             y += 1
-            temp.append(x[i])
+            temp.append(int(x[i]))
         else:
             if y >= val:
                 res.extend(temp)
-            temp = [x[i]]
+            temp = [int(x[i])]
             y = 1
         if i == len(x) - 1 and y >= val:
             res.extend(temp)
@@ -83,6 +74,13 @@ def combine(ls1, ls2):
     return temp
 
 
+def str_list_to_int(str_list):
+    int_list = []
+    for i in str_list:
+        int_list.append(int(i))
+    return int_list
+
+
 def list_in_list(a, b):
     # convert list A to numpy array
     a_arr = np.array(a)
@@ -135,15 +133,27 @@ def freqency_converter(b, slots):
 
 
 def readTopologyData(nodes, topology):
+        
+        
         nodes_file = open(nodes, 'r')
         topo_file = open(topology, 'r')
         nodes = json.load(nodes_file)
         topo = json.load(topo_file)
-        print(topo)
+        #print(topo)
         nodes_file.close()
         topo_file.close()
         return nodes, topo
-
+def readTopologyDataFromContext(topology_id:TopologyId):
+   
+   
+    ctx_client = ContextClient()
+    ctx_client.connect()
+    topo_details = ctx_client.GetTopologyDetails(topology_id)
+    topo = topo_details.optical_links
+    nodes = topo_details.devices
+    ctx_client.close()
+    return topo , nodes
+    
 
 def reverse_links(links):
     temp_links = links.copy()
@@ -154,18 +164,20 @@ def reverse_links(links):
         result.append("{}-{}".format(b, a))
     return result
 
+
 def get_links_from_node(topology, node):
     result = {}
     for link in topology["links"]:
-        if "{}-".format(node) in link["optical_link"]["name"]:
-            result[link["optical_link"]["name"]] = link
+        if "{}-".format(node) in link["name"]:
+            result[link["name"]] = link
     return result
 
+
 def get_links_to_node(topology, node):
     result = {}
     for link in topology["links"]:
-        if "-{}".format(node) in link["optical_link"]["name"]:
-            result[link["optical_link"]["name"]] = link
+        if "-{}".format(node) in link["name"]:
+            result[link["name"]] = link
     return result
 
 
@@ -183,7 +195,7 @@ def slot_selection(c, l, s, n_slots, Nc, Nl, Ns):
         return "c_slots", c[0: slot_c]
     elif len(l) >= slot_l:
         return "l_slots", l[0: slot_l]
-    elif len(l) >= slot_s:
+    elif len(s) >= slot_s:
         return "s_slots", s[0: slot_s]
     else:
         return None, None
diff --git a/src/opticalcontroller/variables.py b/src/opticalcontroller/variables.py
index cbb65200f..28ee66208 100644
--- a/src/opticalcontroller/variables.py
+++ b/src/opticalcontroller/variables.py
@@ -1,17 +1,3 @@
-# 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.
-
 debug = 1
 
 Fl = 184800
@@ -24,7 +10,7 @@ Nc = 320
 Ns = 720
 
 nodes_json = 'json_files/nodes.json'
-topology_json = 'json_files/tfs.json' #LAST
+topology_json = 'json_files/tfs_dict.json' #LAST
 #topology_json = 'json_files/optical_TFSworking.json' #LAST
 #topology_json = 'json_files/optical_topoTFS.json'
 #topology_json = 'json_files/topo_2_links.json'
diff --git a/src/service/service/ServiceServiceServicerImpl.py b/src/service/service/ServiceServiceServicerImpl.py
index b5623885f..94f200bbb 100644
--- a/src/service/service/ServiceServiceServicerImpl.py
+++ b/src/service/service/ServiceServiceServicerImpl.py
@@ -39,7 +39,7 @@ from .service_handler_api.ServiceHandlerFactory import ServiceHandlerFactory
 from .task_scheduler.TaskScheduler import TasksScheduler
 from .tools.GeodesicDistance import gps_distance
 from .tools.OpticalTools import (
-    add_lightpath, delete_lightpath, adapt_reply, get_device_name_from_uuid, get_optical_band
+    add_lightpath, delete_lightpath, adapt_reply, get_device_name_from_uuid, get_optical_band,refresh_opticalcontroller
 )
 
 
@@ -254,6 +254,7 @@ class ServiceServiceServicerImpl(ServiceServiceServicer):
                 DEFAULT_TOPOLOGY_NAME, context_id_x)
             topology_details = context_client.GetTopologyDetails(
                 TopologyId(**topology_id_x))
+            #refresh_opticalcontroller(TopologyId(**topology_id_x))
             # devices = get_devices_in_topology(context_client, TopologyId(**topology_id_x), ContextId(**context_id_x))
             devices = topology_details.devices
             context_uuid_x = topology_details.topology_id.context_id.context_uuid.uuid
diff --git a/src/service/service/__main__.py b/src/service/service/__main__.py
index edd4d8f99..5a700b57d 100644
--- a/src/service/service/__main__.py
+++ b/src/service/service/__main__.py
@@ -12,7 +12,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-import logging, signal, sys, threading
+import logging, signal, sys, threading , os
 from prometheus_client import start_http_server
 from common.Constants import ServiceNameEnum
 from common.Settings import (
@@ -44,8 +44,11 @@ def main():
         get_env_var_name(ServiceNameEnum.DEVICE,   ENVVAR_SUFIX_SERVICE_PORT_GRPC),
         get_env_var_name(ServiceNameEnum.PATHCOMP, ENVVAR_SUFIX_SERVICE_HOST     ),
         get_env_var_name(ServiceNameEnum.PATHCOMP, ENVVAR_SUFIX_SERVICE_PORT_GRPC),
+        get_env_var_name(ServiceNameEnum.OPTICALCONTROLLER, ENVVAR_SUFIX_SERVICE_PORT_GRPC),
+        get_env_var_name(ServiceNameEnum.OPTICALCONTROLLER, ENVVAR_SUFIX_SERVICE_HOST     ),
+        
     ])
-
+    LOGGER.info(os.environ)
     signal.signal(signal.SIGINT,  signal_handler)
     signal.signal(signal.SIGTERM, signal_handler)
 
diff --git a/src/service/service/tools/OpticalTools.py b/src/service/service/tools/OpticalTools.py
index 206524371..31bcb7bcf 100644
--- a/src/service/service/tools/OpticalTools.py
+++ b/src/service/service/tools/OpticalTools.py
@@ -41,7 +41,7 @@ opticalcontrollers_url = find_environment_variables([
 ])
 OPTICAL_IP   = opticalcontrollers_url.get(VAR_NAME_OPTICAL_CONTROLLER_HOST)
 OPTICAL_PORT = opticalcontrollers_url.get(VAR_NAME_OPTICAL_CONTROLLER_PORT)
-log.info(str(OPTICAL_IP), str(OPTICAL_PORT))
+log.info(f"OPTICAL_IP:{OPTICAL_IP} OPTICAL_PORT:{OPTICAL_PORT}")
 
 def get_uuids_from_names(devices: List[Device], device_name: str, port_name: str):
     device_uuid = ""
@@ -77,6 +77,11 @@ def get_device_name_from_uuid(devices: List[Device], device_uuid: str):
             return device_name
     return ""
 
+def refresh_opticalcontroller (topology_id:TopologyId):
+     headers = {"Content-Type": "application/json"}
+     urlx = "http://{}:{}/GetTopology/{}".format(OPTICAL_IP, OPTICAL_PORT,topology_id)
+     res = requests.get(urlx, headers=headers)
+     logging.info(f"Refresh opticalcontroller {res}")
 
 def add_lightpath(src, dst, bitrate, bidir, ob_band) -> str:
     if not testing:
@@ -91,6 +96,7 @@ def add_lightpath(src, dst, bitrate, bidir, ob_band) -> str:
                 bidir = 1
             urlx = "http://{}:{}/OpticalTFS/AddFlexLightpath/{}/{}/{}/{}/{}".format(OPTICAL_IP, OPTICAL_PORT, src, dst, bitrate, bidir, ob_band)
         r = requests.put(urlx, headers=headers)
+        print(f"addpathlight {r}")
         reply = r.text 
         return reply
     else:
diff --git a/src/tests/ofc24/r_t.sh b/src/tests/ofc24/r_t.sh
new file mode 100644
index 000000000..f5357fc37
--- /dev/null
+++ b/src/tests/ofc24/r_t.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+# 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
+
+
+docker stop -t 1 t1
+docker stop -t 1 na3
+docker stop -t 1 t2
+docker stop -t 1 na2
+
+docker rm t1
+docker rm na3
+
+docker rm t2
+docker rm na2
+
+screen -dmS t1 -T xterm sh -c "docker run --name t1  -p  10.0.2.4:2023:2022 -v /home/tfs/tfs-ctrl/src/tests/ofc24/tempOC/files:/files  -it asgamb1/oc23bgp.img:latest bash -c 'cp /files/platform_t1.xml demoECOC21.xml ; ./startNetconfAgent.sh'"
+screen -dmS t3 -T xterm sh -c "docker run --name na3  -p  10.0.2.4:2025:2022 -v /home/tfs/tfs-ctrl/src/tests/ofc24/tempOC/files:/files  -it asgamb1/flexscale-node.img:latest bash -c 'cp /files/platform_r1.xml init_openconfig-platform.xml ; ./startNetconfAgent.sh'"
+screen -dmS t2 -T xterm sh -c "docker run --name t2  -p  10.0.2.4:2024:2022 -v /home/tfs/tfs-ctrl/src/tests/ofc24/tempOC/files:/files  -it asgamb1/oc23bgp.img:latest bash -c 'cp /files/platform_t2.xml demoECOC21.xml ; ./startNetconfAgent.sh'"
+screen -dmS t4 -T xterm sh -c "docker run --name na2  -p  10.0.2.4:2026:2022 -v /home/tfs/tfs-ctrl/src/tests/ofc24/tempOC/files:/files  -it asgamb1/flexscale-node.img:latest bash -c 'cp /files/platform_r2.xml init_openconfig-platform.xml ; ./startNetconfAgent.sh'"
\ No newline at end of file
diff --git a/src/tests/ofc24/roadms.sh b/src/tests/ofc24/roadms.sh
new file mode 100644
index 000000000..ac5101376
--- /dev/null
+++ b/src/tests/ofc24/roadms.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+# 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.
+
+         
+docker stop -t 1 na3
+docker stop -t 1 na4
+
+docker rm na3
+docker rm na4
+
+
+
+screen -dmS t3 -T xterm sh -c "docker run --name na3  -p  10.0.2.4:2025:2022 -v /home/tfs/tfs-ctrl/src/tests/ofc24/tempOC/files:/files  -it asgamb1/flexscale-node.img:latest bash -c 'cp /files/platform_r1.xml demoECOC21.xml ; ./startNetconfAgent.sh'"
+screen -dmS t4 -T xterm sh -c "docker run --name na4  -p  10.0.2.4:2026:2022 -v /home/tfs/tfs-ctrl/src/tests/ofc24/tempOC/files:/files  -it asgamb1/flexscale-node.img:latest bash -c 'cp /files/platform_r2.xml demoECOC21.xml ; ./startNetconfAgent.sh'"
\ No newline at end of file
diff --git a/src/tests/ofc24/tempOC/files/platform_r1.xml b/src/tests/ofc24/tempOC/files/platform_r1.xml
index 625d7048a..02ea8feb4 100644
--- a/src/tests/ofc24/tempOC/files/platform_r1.xml
+++ b/src/tests/ofc24/tempOC/files/platform_r1.xml
@@ -116,5 +116,122 @@
                 </property>
             </properties>
         </component>
-    </components>
-</config>
+        <component xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0" ns0:operation="create">
+            <name>4</name>
+            <config>
+                <name>4</name>
+            </config>
+            <properties>
+                <property>
+                    <name>MG_ON_PORT_TYPE</name>
+                    <config>
+                        <name>MG_ON_PORT_TYPE</name>
+                        <value>MG_ON_OPTICAL_PORT_WAVEBAND</value>
+                    </config>
+                </property>
+                <property>
+                    <name>MG_ON_PORT_DIRECTION</name>
+                    <config>
+                        <name>MG_ON_PORT_DIRECTION</name>
+                        <value>OUTPUT</value>
+                    </config>
+                </property>
+                <property>
+                    <name>MG_ON_PORT_DEGREE</name>
+                    <config>
+                        <name>MG_ON_PORT_DEGREE</name>
+                        <value>D2</value>
+                    </config>
+                </property>
+            </properties>
+        </component>
+        <component xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0" ns0:operation="create">
+            <name>14</name>
+            <config>
+                <name>14</name>
+            </config>
+            <properties>
+                <property>
+                    <name>MG_ON_PORT_TYPE</name>
+                    <config>
+                        <name>MG_ON_PORT_TYPE</name>
+                        <value>MG_ON_OPTICAL_PORT_WAVEBAND</value>
+                    </config>
+                </property>
+                <property>
+                    <name>MG_ON_PORT_DIRECTION</name>
+                    <config>
+                        <name>MG_ON_PORT_DIRECTION</name>
+                        <value>INPUT</value>
+                    </config>
+                </property>
+                <property>
+                    <name>MG_ON_PORT_DEGREE</name>
+                    <config>
+                        <name>MG_ON_PORT_DEGREE</name>
+                        <value>D2</value>
+                    </config>
+                </property>
+            </properties>
+        </component>
+   
+        <component xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0" ns0:operation="create">
+            <name>101</name>
+            <config>
+                <name>101</name>
+            </config>
+            <properties>
+                <property>
+                    <name>MG_ON_PORT_TYPE</name>
+                    <config>
+                        <name>MG_ON_PORT_TYPE</name>
+                        <value>MG_ON_OPTICAL_PORT_WAVEBAND</value>
+                    </config>
+                </property>
+                <property>
+                    <name>MG_ON_PORT_DIRECTION</name>
+                    <config>
+                        <name>MG_ON_PORT_DIRECTION</name>
+                        <value>OUTPUT</value>
+                    </config>
+                </property>
+                <property>
+                    <name>MG_ON_PORT_DEGREE</name>
+                    <config>
+                        <name>MG_ON_PORT_DEGREE</name>
+                        <value>D2</value>
+                    </config>
+                </property>
+            </properties>
+        </component>
+        <component xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0" ns0:operation="create">
+            <name>111</name>
+            <config>
+                <name>111</name>
+            </config>
+            <properties>
+                <property>
+                    <name>MG_ON_PORT_TYPE</name>
+                    <config>
+                        <name>MG_ON_PORT_TYPE</name>
+                        <value>MG_ON_OPTICAL_PORT_WAVEBAND</value>
+                    </config>
+                </property>
+                <property>
+                    <name>MG_ON_PORT_DIRECTION</name>
+                    <config>
+                        <name>MG_ON_PORT_DIRECTION</name>
+                        <value>INPUT</value>
+                    </config>
+                </property>
+                <property>
+                    <name>MG_ON_PORT_DEGREE</name>
+                    <config>
+                        <name>MG_ON_PORT_DEGREE</name>
+                        <value>D2</value>
+                    </config>
+                </property>
+            </properties>
+        </component>
+        </components>
+</config>
\ No newline at end of file
diff --git a/src/tests/ofc24/tempOC/files/platform_r2.xml b/src/tests/ofc24/tempOC/files/platform_r2.xml
index 65f7ee458..04d1d8370 100644
--- a/src/tests/ofc24/tempOC/files/platform_r2.xml
+++ b/src/tests/ofc24/tempOC/files/platform_r2.xml
@@ -1,5 +1,121 @@
 <config xmlns="http://tail-f.com/ns/config/1.0">
     <components xmlns="http://openconfig.net/yang/platform">
+        <component xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0" ns0:operation="create">
+            <name>2</name>
+            <config>
+                <name>2</name>
+            </config>
+            <properties>
+                <property>
+                    <name>MG_ON_PORT_TYPE</name>
+                    <config>
+                        <name>MG_ON_PORT_TYPE</name>
+                        <value>MG_ON_OPTICAL_PORT_WAVEBAND</value>
+                    </config>
+                </property>
+                <property>
+                    <name>MG_ON_PORT_DIRECTION</name>
+                    <config>
+                        <name>MG_ON_PORT_DIRECTION</name>
+                        <value>OUTPUT</value>
+                    </config>
+                </property>
+                <property>
+                    <name>MG_ON_PORT_DEGREE</name>
+                    <config>
+                        <name>MG_ON_PORT_DEGREE</name>
+                        <value>D1</value>
+                    </config>
+                </property>
+            </properties>
+        </component>
+        <component xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0" ns0:operation="create">
+            <name>12</name>
+            <config>
+                <name>12</name>
+            </config>
+            <properties>
+                <property>
+                    <name>MG_ON_PORT_TYPE</name>
+                    <config>
+                        <name>MG_ON_PORT_TYPE</name>
+                        <value>MG_ON_OPTICAL_PORT_WAVEBAND</value>
+                    </config>
+                </property>
+                <property>
+                    <name>MG_ON_PORT_DIRECTION</name>
+                    <config>
+                        <name>MG_ON_PORT_DIRECTION</name>
+                        <value>INPUT</value>
+                    </config>
+                </property>
+                <property>
+                    <name>MG_ON_PORT_DEGREE</name>
+                    <config>
+                        <name>MG_ON_PORT_DEGREE</name>
+                        <value>D1</value>
+                    </config>
+                </property>
+            </properties>
+        </component>
+        <component xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0" ns0:operation="create">
+            <name>3</name>
+            <config>
+                <name>3</name>
+            </config>
+            <properties>
+                <property>
+                    <name>MG_ON_PORT_TYPE</name>
+                    <config>
+                        <name>MG_ON_PORT_TYPE</name>
+                        <value>MG_ON_OPTICAL_PORT_WAVEBAND</value>
+                    </config>
+                </property>
+                <property>
+                    <name>MG_ON_PORT_DIRECTION</name>
+                    <config>
+                        <name>MG_ON_PORT_DIRECTION</name>
+                        <value>OUTPUT</value>
+                    </config>
+                </property>
+                <property>
+                    <name>MG_ON_PORT_DEGREE</name>
+                    <config>
+                        <name>MG_ON_PORT_DEGREE</name>
+                        <value>D2</value>
+                    </config>
+                </property>
+            </properties>
+        </component>
+        <component xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0" ns0:operation="create">
+            <name>13</name>
+            <config>
+                <name>13</name>
+            </config>
+            <properties>
+                <property>
+                    <name>MG_ON_PORT_TYPE</name>
+                    <config>
+                        <name>MG_ON_PORT_TYPE</name>
+                        <value>MG_ON_OPTICAL_PORT_WAVEBAND</value>
+                    </config>
+                </property>
+                <property>
+                    <name>MG_ON_PORT_DIRECTION</name>
+                    <config>
+                        <name>MG_ON_PORT_DIRECTION</name>
+                        <value>INPUT</value>
+                    </config>
+                </property>
+                <property>
+                    <name>MG_ON_PORT_DEGREE</name>
+                    <config>
+                        <name>MG_ON_PORT_DEGREE</name>
+                        <value>D2</value>
+                    </config>
+                </property>
+            </properties>
+        </component>
         <component xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0" ns0:operation="create">
             <name>4</name>
             <config>
@@ -24,7 +140,7 @@
                     <name>MG_ON_PORT_DEGREE</name>
                     <config>
                         <name>MG_ON_PORT_DEGREE</name>
-                        <value>D1</value>
+                        <value>D2</value>
                     </config>
                 </property>
             </properties>
@@ -53,15 +169,16 @@
                     <name>MG_ON_PORT_DEGREE</name>
                     <config>
                         <name>MG_ON_PORT_DEGREE</name>
-                        <value>D1</value>
+                        <value>D2</value>
                     </config>
                 </property>
             </properties>
         </component>
+ 
         <component xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0" ns0:operation="create">
-            <name>5</name>
+            <name>101</name>
             <config>
-                <name>5</name>
+                <name>101</name>
             </config>
             <properties>
                 <property>
@@ -88,9 +205,9 @@
             </properties>
         </component>
         <component xmlns:ns0="urn:ietf:params:xml:ns:netconf:base:1.0" ns0:operation="create">
-            <name>15</name>
+            <name>111</name>
             <config>
-                <name>15</name>
+                <name>111</name>
             </config>
             <properties>
                 <property>
@@ -116,5 +233,5 @@
                 </property>
             </properties>
         </component>
-    </components>
-</config>
+        </components>
+</config>
\ No newline at end of file
diff --git a/src/tests/ofc24/copy.sh b/src/tests/ofc24/transponders.sh
similarity index 100%
rename from src/tests/ofc24/copy.sh
rename to src/tests/ofc24/transponders.sh
diff --git a/src/webui/service/__init__.py b/src/webui/service/__init__.py
index 196652d3f..00908079d 100644
--- a/src/webui/service/__init__.py
+++ b/src/webui/service/__init__.py
@@ -84,8 +84,14 @@ def create_app(use_config=None, web_app_root=None):
     from webui.service.load_gen.routes import load_gen      # pylint: disable=import-outside-toplevel
     app.register_blueprint(load_gen)
     
+    from webui.service.base_optical.route import base_optical              # pylint: disable=import-outside-toplevel
+    app.register_blueprint(base_optical)
+    
     from webui.service.opticalconfig.routes import opticalconfig      # pylint: disable=import-outside-toplevel
     app.register_blueprint(opticalconfig)
+    
+    from webui.service.optical_link.routes import optical_link              # pylint: disable=import-outside-toplevel
+    app.register_blueprint(optical_link)
 
     from webui.service.service.routes import service        # pylint: disable=import-outside-toplevel
     app.register_blueprint(service)
diff --git a/src/webui/service/base_optical/__init__.py b/src/webui/service/base_optical/__init__.py
new file mode 100644
index 000000000..1549d9811
--- /dev/null
+++ b/src/webui/service/base_optical/__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/webui/service/base_optical/route.py b/src/webui/service/base_optical/route.py
new file mode 100644
index 000000000..e3f37de51
--- /dev/null
+++ b/src/webui/service/base_optical/route.py
@@ -0,0 +1,29 @@
+# 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 import current_app, render_template, Blueprint, flash, session, redirect, url_for
+from common.proto.context_pb2 import Empty, OpticalLink, LinkId, OpticalLinkList
+from common.tools.context_queries.EndPoint import get_endpoint_names
+from common.tools.context_queries.Link import get_link
+from common.tools.context_queries.Topology import get_topology
+from context.client.ContextClient import ContextClient
+
+
+base_optical = Blueprint('base_optical', __name__, url_prefix='/base_optical')
+
+@base_optical.get('/')
+def home():
+    
+    return render_template("base_optical/home.html")
\ No newline at end of file
diff --git a/src/webui/service/main/routes.py b/src/webui/service/main/routes.py
index 1fd7e006c..9f700283d 100644
--- a/src/webui/service/main/routes.py
+++ b/src/webui/service/main/routes.py
@@ -155,11 +155,23 @@ def topology():
                 'source': link.link_endpoint_ids[0].device_id.device_uuid.uuid,
                 'target': link.link_endpoint_ids[1].device_id.device_uuid.uuid,
             })
-
-        return jsonify({'devices': devices, 'links': links})
+        optical_links = []
+        for link in response.optical_links:
+            if len(link.link_endpoint_ids) != 2:
+                str_link = grpc_message_to_json_string(link)
+                LOGGER.warning('Unexpected link with len(endpoints) != 2: {:s}'.format(str_link))
+                continue
+            optical_links.append({
+                'id': link.link_id.link_uuid.uuid,
+                'name': link.name,
+                'source': link.link_endpoint_ids[0].device_id.device_uuid.uuid,
+                'target': link.link_endpoint_ids[1].device_id.device_uuid.uuid,
+            })    
+        LOGGER.info(f"optical links {optical_links}")
+        return jsonify({'devices': devices, 'links': links ,'optical_links':optical_links})
     except: # pylint: disable=bare-except
         LOGGER.exception('Error retrieving topology')
-        return jsonify({'devices': [], 'links': []})
+        return jsonify({'devices': [], 'links': [],'optical_links':[]})
     finally:
         context_client.close()
 
diff --git a/src/webui/service/optical_link/__init__.py b/src/webui/service/optical_link/__init__.py
new file mode 100644
index 000000000..355dcdb04
--- /dev/null
+++ b/src/webui/service/optical_link/__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/webui/service/optical_link/routes.py b/src/webui/service/optical_link/routes.py
new file mode 100644
index 000000000..7be81410e
--- /dev/null
+++ b/src/webui/service/optical_link/routes.py
@@ -0,0 +1,93 @@
+# 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 import current_app, render_template, Blueprint, flash, session, redirect, url_for
+from common.proto.context_pb2 import Empty, OpticalLink, LinkId, OpticalLinkList
+from common.tools.context_queries.EndPoint import get_endpoint_names
+from common.tools.context_queries.Link import get_link
+from common.tools.context_queries.Topology import get_topology
+from context.client.ContextClient import ContextClient
+
+
+optical_link = Blueprint('optical_link', __name__, url_prefix='/optical_link')
+context_client = ContextClient()
+
+@optical_link.get('/')
+def home():
+    if 'context_uuid' not in session or 'topology_uuid' not in session:
+        flash("Please select a context!", "warning")
+        return redirect(url_for("main.home"))
+
+    context_uuid = session['context_uuid']
+    topology_uuid = session['topology_uuid']
+
+    links, endpoint_ids = list(), list()
+    device_names, endpoints_data = dict(), dict()
+
+    context_client.connect()
+    grpc_topology = get_topology(context_client, topology_uuid, context_uuid=context_uuid, rw_copy=False)
+    if grpc_topology is None:
+        flash('Context({:s})/Topology({:s}) not found'.format(str(context_uuid), str(topology_uuid)), 'danger')
+    else:
+        topo_link_uuids = {link_id.link_uuid.uuid for link_id in grpc_topology.link_ids}
+        grpc_links: OpticalLinkList = context_client.GetOpticalLinkList(Empty())
+        for link_ in grpc_links.optical_links:
+           
+            links.append(link_)
+            endpoint_ids.extend(link_.link_endpoint_ids)
+        device_names, endpoints_data = get_endpoint_names(context_client, endpoint_ids)
+    context_client.close()
+
+    return render_template('optical_link/home.html', links=links, device_names=device_names, endpoints_data=endpoints_data)
+
+
+@optical_link.route('detail/<path:link_uuid>', methods=('GET', 'POST'))
+def detail(link_uuid: str):
+    context_client.connect()
+    # pylint: disable=no-member
+    link_id = LinkId()
+    link_id.link_uuid.uuid = link_uuid
+    link_obj = context_client.GetOpticalLink(link_id)
+
+    if link_obj is None:
+        flash('Optical Link({:s}) not found'.format(str(link_uuid)), 'danger')
+        link_obj = OpticalLink()
+        device_names, endpoints_data = dict(), dict()
+    else:
+        device_names, endpoints_data = get_endpoint_names(context_client, link_obj.link_endpoint_ids)
+    context_client.close()
+    return render_template('optical_link/detail.html',link=link_obj, device_names=device_names, endpoints_data=endpoints_data)
+
+@optical_link.get('<path:link_uuid>/delete')
+def delete(link_uuid):
+    try:
+
+        # first, check if link exists!
+        # request: LinkId = LinkId()
+        # request.link_uuid.uuid = link_uuid
+        # response: Link = client.GetLink(request)
+        # TODO: finalize implementation
+
+        request = LinkId()
+        request.link_uuid.uuid = link_uuid # pylint: disable=no-member
+        context_client.connect()
+        context_client.DeleteOpticalLink(request)
+        context_client.close()
+
+        flash(f'Optical Link "{link_uuid}" deleted successfully!', 'success')
+    except Exception as e: # pylint: disable=broad-except
+        flash(f'Problem deleting link "{link_uuid}": {e.details()}', 'danger')
+        current_app.logger.exception(e)
+    return redirect(url_for('optical_link.home'))
diff --git a/src/webui/service/templates/base.html b/src/webui/service/templates/base.html
index e081b2710..32b658746 100644
--- a/src/webui/service/templates/base.html
+++ b/src/webui/service/templates/base.html
@@ -84,10 +84,10 @@
                   {% endif %}
                 </li>
                 <li class="nav-item">
-                  {% if '/opticalconfig/' in request.path %}
-                  <a class="nav-link active" aria-current="page" href="{{ url_for('opticalconfig.home') }}">Optical Config</a>
+                  {% if '/base_optical/' in request.path %}
+                  <a class="nav-link active" aria-current="page" href="{{ url_for('base_optical.home') }}">Optical Config</a>
                   {% else %}
-                  <a class="nav-link" href="{{ url_for('opticalconfig.home') }}">Optical Config</a>
+                  <a class="nav-link" href="{{ url_for('base_optical.home') }}">Optical Config</a>
                   {% endif %}
                 </li>
                 <li class="nav-item">
diff --git a/src/webui/service/templates/base_optical/home.html b/src/webui/service/templates/base_optical/home.html
new file mode 100644
index 000000000..e6cae4c67
--- /dev/null
+++ b/src/webui/service/templates/base_optical/home.html
@@ -0,0 +1,40 @@
+<!--
+    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>My Configurations</h1>
+   
+       <div class="row">
+          <div class="col">
+            <a href="{{ url_for('opticalconfig.home') }}" class="btn btn-primary" style="margin-bottom: 10px;">
+              
+                  Optical Devices
+            </a>
+          </div>
+          <div class="col">
+            <a href="{{ url_for('optical_link.home') }}" class="btn btn-primary" style="margin-bottom: 10px;">
+              
+                  Optical Links
+            </a>
+          </div>
+       </div>
+       
+   
+   
+   
+   {% endblock %}
\ No newline at end of file
diff --git a/src/webui/service/templates/js/topology.js b/src/webui/service/templates/js/topology.js
index 1b34f2b2c..fa2cfb41b 100644
--- a/src/webui/service/templates/js/topology.js
+++ b/src/webui/service/templates/js/topology.js
@@ -85,6 +85,21 @@ d3.json("{{ url_for('main.topology') }}", function(data) {
         .attr("stroke-dasharray", function(l) {
             return l.name.toLowerCase().includes('mgmt') ? "5,5" : "0";
         });
+     optical_link = svg.append("g").attr("class", "links").style('stroke', '#aaa')
+         .selectAll("line")
+         .data(data.optical_links)
+         .enter()
+         .append("line")
+         .attr("opacity", 1)
+         .attr("stroke", function(l) {
+             return l.name.toLowerCase().includes('mgmt') ? '#AAAAAA' : '#555555';
+         })
+         .attr("stroke-width", function(l) {
+             return l.name.toLowerCase().includes('mgmt') ? 1 : 2;
+         })
+         .attr("stroke-dasharray", function(l) {
+             return l.name.toLowerCase().includes('mgmt') ? "5,5" : "0";
+         });    
     node = svg.append("g").attr("class", "devices").attr('r', 20).style('fill', '#69b3a2')
         .selectAll("circle")
         .data(data.devices)
diff --git a/src/webui/service/templates/link/detail.html b/src/webui/service/templates/link/detail.html
index 864d0cdb2..13c397334 100644
--- a/src/webui/service/templates/link/detail.html
+++ b/src/webui/service/templates/link/detail.html
@@ -20,7 +20,7 @@
 <h1>Link {{ link.name }} ({{ link.link_id.link_uuid.uuid }})</h1>
 <div class="row mb-3">
     <div class="col-sm-3">
-        <button type="button" class="btn btn-success" onclick="window.location.href='{{ url_for('link.home') }}'">
+        <button type="button" class="btn btn-success" onclick="window.location.href='{{ url_for('optical_link.home') }}'">
             <i class="bi bi-box-arrow-in-left"></i>
             Back to link list
         </button>
@@ -102,6 +102,7 @@
 </table>
 
 
+
 <!-- Modal -->
 <div class="modal fade" id="deleteModal" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1"
     aria-labelledby="staticBackdropLabel" aria-hidden="true">
diff --git a/src/webui/service/templates/link/home.html b/src/webui/service/templates/link/home.html
index ca96a59b5..9902702fa 100644
--- a/src/webui/service/templates/link/home.html
+++ b/src/webui/service/templates/link/home.html
@@ -78,7 +78,7 @@
                        </td>
    
                        <td> 
-                            <a href="{{ url_for('link.detail', link_uuid=link.link_id.link_uuid.uuid) }}">
+                            <a href="{{ url_for('optical_link.detail', link_uuid=link.link_id.link_uuid.uuid) }}">
                                <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-eye" viewBox="0 0 16 16">
                                    <path d="M16 8s-3-5.5-8-5.5S0 8 0 8s3 5.5 8 5.5S16 8 16 8zM1.173 8a13.133 13.133 0 0 1 1.66-2.043C4.12 4.668 5.88 3.5 8 3.5c2.12 0 3.879 1.168 5.168 2.457A13.133 13.133 0 0 1 14.828 8c-.058.087-.122.183-.195.288-.335.48-.83 1.12-1.465 1.755C11.879 11.332 10.119 12.5 8 12.5c-2.12 0-3.879-1.168-5.168-2.457A13.134 13.134 0 0 1 1.172 8z"/>
                                    <path d="M8 5.5a2.5 2.5 0 1 0 0 5 2.5 2.5 0 0 0 0-5zM4.5 8a3.5 3.5 0 1 1 7 0 3.5 3.5 0 0 1-7 0z"/>
diff --git a/src/webui/service/templates/optical_link/detail.html b/src/webui/service/templates/optical_link/detail.html
new file mode 100644
index 000000000..537c437a8
--- /dev/null
+++ b/src/webui/service/templates/optical_link/detail.html
@@ -0,0 +1,126 @@
+<!--
+    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>Link {{ link.name }} ({{ link.link_id.link_uuid.uuid }})</h1>
+<div class="row mb-3">
+    <div class="col-sm-3">
+        <button type="button" class="btn btn-success" onclick="window.location.href='{{ url_for('optical_link.home') }}'">
+            <i class="bi bi-box-arrow-in-left"></i>
+            Back to link list
+        </button>
+    </div>
+    <div class="col-sm-3">
+        <!-- <button type="button" class="btn btn-danger"><i class="bi bi-x-square"></i>Delete link</button> -->
+        <button type="button" class="btn btn-danger" data-bs-toggle="modal" data-bs-target="#deleteModal">
+            <i class="bi bi-x-square"></i>
+            Delete link
+        </button>
+    </div>
+</div>
+
+<br>
+<div class="row mb-3">
+    <div class="col-sm-4">
+        <b>UUID: </b>{{ link.link_id.link_uuid.uuid }}<br>
+        <b>Name: </b>{{ link.name }}<br>
+    </div>
+    <div class="col-sm-8">
+        <table class="table table-striped table-hover">
+            <thead>
+                <tr>
+                    <th scope="col">Endpoint UUID</th>
+                    <th scope="col">Name</th>
+                    <th scope="col">Device</th>
+                    <th scope="col">Endpoint Type</th>
+                </tr>
+            </thead>
+            <tbody>
+                {% for endpoint in link.link_endpoint_ids %}
+                <tr>
+                    <td>
+                        {{ endpoint.endpoint_uuid.uuid }}
+                    </td>
+                    <td>
+                        {{ endpoints_data.get(endpoint.endpoint_uuid.uuid, (endpoint.endpoint_uuid.uuid, ''))[0] }}
+                    </td>
+                    <td>
+                        <a href="{{ url_for('device.detail', device_uuid=endpoint.device_id.device_uuid.uuid) }}">
+                            {{ device_names.get(endpoint.device_id.device_uuid.uuid, endpoint.device_id.device_uuid.uuid) }}
+                            <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-eye" viewBox="0 0 16 16">
+                                    <path d="M16 8s-3-5.5-8-5.5S0 8 0 8s3 5.5 8 5.5S16 8 16 8zM1.173 8a13.133 13.133 0 0 1 1.66-2.043C4.12 4.668 5.88 3.5 8 3.5c2.12 0 3.879 1.168 5.168 2.457A13.133 13.133 0 0 1 14.828 8c-.058.087-.122.183-.195.288-.335.48-.83 1.12-1.465 1.755C11.879 11.332 10.119 12.5 8 12.5c-2.12 0-3.879-1.168-5.168-2.457A13.134 13.134 0 0 1 1.172 8z"/>
+                                    <path d="M8 5.5a2.5 2.5 0 1 0 0 5 2.5 2.5 0 0 0 0-5zM4.5 8a3.5 3.5 0 1 1 7 0 3.5 3.5 0 0 1-7 0z"/>
+                            </svg>
+                        </a>
+                    </td>
+                    <td>
+                        {{ endpoints_data.get(endpoint.endpoint_uuid.uuid, ('', '-'))[1] }}
+                    </td>
+                </tr>
+                {% endfor %}
+            </tbody>
+        </table>
+    </div>
+</div>
+
+
+
+<b>Optical Link Detail:</b>
+<table class="table table-striped table-hover">
+    <thead>
+        <tr>
+            <th scope="col">Key</th>
+            <th scope="col">Value</th>
+        </tr>
+    </thead>
+    <tbody>
+        {% for field_descriptor, field_value in link.optical_details.ListFields() %}
+        <tr>
+            <td>
+                {{ field_descriptor.name }}
+            </td>
+            <td>
+                {{ field_value }}
+            </td>
+        </tr>
+        {% endfor %}
+    </tbody>
+</table>
+<!-- Modal -->
+<div class="modal fade" id="deleteModal" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1"
+    aria-labelledby="staticBackdropLabel" aria-hidden="true">
+    <div class="modal-dialog">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title" id="staticBackdropLabel">Delete link?</h5>
+                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
+            </div>
+            <div class="modal-body">
+                Are you sure you want to delete the link "{{ link.link_id.link_uuid.uuid }}"?
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">No</button>
+                <a type="button" class="btn btn-danger"
+                    href="{{ url_for('link.delete', link_uuid=link.link_id.link_uuid.uuid) }}"><i
+                        class="bi bi-exclamation-diamond"></i>Yes</a>
+            </div>
+        </div>
+    </div>
+</div>
+
+{% endblock %}
diff --git a/src/webui/service/templates/optical_link/home.html b/src/webui/service/templates/optical_link/home.html
new file mode 100644
index 000000000..e5aca5695
--- /dev/null
+++ b/src/webui/service/templates/optical_link/home.html
@@ -0,0 +1,98 @@
+<!--
+    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>Optical Links</h1>
+   
+       <div class="row">
+           <div class="col">
+               <!-- <a href="#" class="btn btn-primary" style="margin-bottom: 10px;">
+                   <i class="bi bi-plus"></i>
+                   Add New Link
+               </a> -->
+           </div>
+           <div class="col">
+               {{ links | length }} links found in context <i>{{ session['context_uuid'] }}</i>
+           </div>
+           <!-- <div class="col">
+               <form>
+                   <div class="input-group">
+                       <input type="text" aria-label="Search" placeholder="Search..." class="form-control"/>
+                       <button type="submit" class="btn btn-primary">Search</button>
+                     </div>
+               </form>
+           </div> -->
+       </div>
+   
+       <table class="table table-striped table-hover">
+           <thead>
+             <tr>
+               <th scope="col">UUID</th>
+               <th scope="col">Name</th>
+               <th scope="col">Endpoints</th>
+               <th scope="col"></th>
+             </tr>
+           </thead>
+           <tbody>
+               {% if links %}
+                   {% for link in links %}
+                   <tr>
+                       <td>
+                            {{ link.link_id.link_uuid.uuid }}
+                       </td>
+                       <td>
+                            {{ link.name }}
+                        </td>
+
+                       <td>
+                           <ul>
+                               {% for endpoint in link.link_endpoint_ids %}
+                               <li>
+                                   {{ endpoints_data.get(endpoint.endpoint_uuid.uuid, (endpoint.endpoint_uuid.uuid, ''))[0] }} / 
+                                   Device: 
+                                   <a href="{{ url_for('device.detail', device_uuid=endpoint.device_id.device_uuid.uuid) }}">
+                                       {{ device_names.get(endpoint.device_id.device_uuid.uuid, endpoint.device_id.device_uuid.uuid) }}
+                                       <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-eye" viewBox="0 0 16 16">
+                                           <path d="M16 8s-3-5.5-8-5.5S0 8 0 8s3 5.5 8 5.5S16 8 16 8zM1.173 8a13.133 13.133 0 0 1 1.66-2.043C4.12 4.668 5.88 3.5 8 3.5c2.12 0 3.879 1.168 5.168 2.457A13.133 13.133 0 0 1 14.828 8c-.058.087-.122.183-.195.288-.335.48-.83 1.12-1.465 1.755C11.879 11.332 10.119 12.5 8 12.5c-2.12 0-3.879-1.168-5.168-2.457A13.134 13.134 0 0 1 1.172 8z"/>
+                                           <path d="M8 5.5a2.5 2.5 0 1 0 0 5 2.5 2.5 0 0 0 0-5zM4.5 8a3.5 3.5 0 1 1 7 0 3.5 3.5 0 0 1-7 0z"/>
+                                       </svg>
+                                   </a>
+                               </li>
+                               {% endfor %}
+                           </ul>
+                       </td>
+   
+                       <td> 
+                            <a href="{{ url_for('optical_link.detail', link_uuid=link.link_id.link_uuid.uuid) }}">
+                               <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-eye" viewBox="0 0 16 16">
+                                   <path d="M16 8s-3-5.5-8-5.5S0 8 0 8s3 5.5 8 5.5S16 8 16 8zM1.173 8a13.133 13.133 0 0 1 1.66-2.043C4.12 4.668 5.88 3.5 8 3.5c2.12 0 3.879 1.168 5.168 2.457A13.133 13.133 0 0 1 14.828 8c-.058.087-.122.183-.195.288-.335.48-.83 1.12-1.465 1.755C11.879 11.332 10.119 12.5 8 12.5c-2.12 0-3.879-1.168-5.168-2.457A13.134 13.134 0 0 1 1.172 8z"/>
+                                   <path d="M8 5.5a2.5 2.5 0 1 0 0 5 2.5 2.5 0 0 0 0-5zM4.5 8a3.5 3.5 0 1 1 7 0 3.5 3.5 0 0 1-7 0z"/>
+                               </svg> 
+                           </a>
+                       </td>
+                   </tr>
+                   {% endfor %}
+               {% else %}
+                   <tr>
+                       <td colspan="7">No links found</td>
+                   </tr>
+               {% endif %}
+           </tbody>
+       </table>
+   
+   {% endblock %}
\ No newline at end of file
diff --git a/src/webui/service/templates/opticalconfig/home.html b/src/webui/service/templates/opticalconfig/home.html
index c1253a7b5..349c25e36 100644
--- a/src/webui/service/templates/opticalconfig/home.html
+++ b/src/webui/service/templates/opticalconfig/home.html
@@ -1,18 +1,18 @@
 <!--
- 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.
--->
+    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' %}
 
diff --git a/test.py b/test.py
index d27e15d38..f8e77b70b 100644
--- a/test.py
+++ b/test.py
@@ -1,10 +1,63 @@
 from ncclient import manager
 from ncclient.xml_ import *
 import lxml.etree as ET
+import re
+from typing import Optional, Union
+from uuid import UUID, uuid4, uuid5
+import logging
+
+NAMESPACE_TFS = UUID('200e3a1f-2223-534f-a100-758e29c37f40')
+
+print (uuid5(NAMESPACE_TFS, '1'))
+def extract_roadm_ports (xml_data:str):
+    pattern = r'\bMG_ON_OPTICAL_PORT_WAVEBAND\b'
+    xml_bytes = xml_data.encode("utf-8")
+    root = ET.fromstring(xml_bytes)
+    with open('xml.log', 'w') as f:
+         print(xml_bytes, file=f)
+    
+
+    namespace = {'oc': 'http://openconfig.net/yang/platform'}
+    ports = []
+    components = root.findall('.//oc:component',namespace)
+    print(f"component {components}")
+    
+    
+    for component  in components:
+       
+        properties = component.find(".//oc:properties",namespace)
+       
+        if (properties is not None):
+            for property in properties :
+                value = property.find(".//oc:value",namespace)
+              
+                if (re.search(pattern,value.text)):
+                    name_element= component.find(".//oc:name",namespace)
+                    print (f"name {name_element.text}")
+
+
+ 
+def extract_ports_based_on_type (xml_data:str):
+    pattern = r':\s*PORT\b'
+    
+    xml_bytes = xml_data.encode("utf-8")
+    root = ET.fromstring(xml_bytes)
+    
+    namespace = {'oc': 'http://openconfig.net/yang/platform', 'typex': 'http://openconfig.net/yang/platform-types'}
+    ports = []
+    components = root.findall(".//oc:state[oc:type]",namespace)
+    for component in components:
+         type_ele = component.find(".//oc:type",namespace)
+         match = re.search(pattern, type_ele.text)
+         if match is not None :
+            name= component.find(".//oc:name",namespace)
+            print(name.text)
+            print("/////////////")
+    
 
 device = {
-    'host': '10.0.2.10',        # IP address or hostname of the remote machine
-    'port': 2023,                # SSH port (default: 22)
+    'host': '10.0.2.4',        # IP address or hostname of the remote machine
+    'port': 2025,                # SSH port (default: 22)
     'username': 'admin',    # SSH username
     'password': 'admin',    # SSH password
     'device_params': {'name': 'default'},
@@ -12,6 +65,8 @@ device = {
      "allow_agent":False
      ,"look_for_keys":False
 }
+
+
 def extract_value (xml_data):
     xml_bytes = xml_data.encode("utf-8")
     root = ET.fromstring(xml_bytes)
@@ -28,14 +83,15 @@ def extract_value (xml_data):
       
     else:
        print(" element not found.")
-
-with manager.connect(**device) as m:
-    # Perform operations on the remote machine using the 'm' object
-    # For example, you can retrieve the running configuration:
-    #result =m.edit_config(target='running',config=edit_config)
-    running_config = m.get_config('running').data_xml
-   
-   
-   
-    extract_value(running_config)
+def main () : 
+        with manager.connect(**device) as m:
+            # Perform operations on the remote machine using the 'm' object
+            # For example, you can retrieve the running configuration:
+            #result =m.edit_config(target='running',config=edit_config)
+            running_config = m.get_config('running').data_xml
+        
+            #extract_roadm_ports(running_config)
+        x,y= [1,3]
+        print (x)    
+            
 
-- 
GitLab