From dee7cde1516480f37e78aeb9d74bd572031ea6bd Mon Sep 17 00:00:00 2001 From: sgambelluri <andrea.sgambelluri@cnit.it> Date: Thu, 15 Feb 2024 10:29:32 +0300 Subject: [PATCH] opticalcontroller component --- src/opticalcontroller/Dockerfile | 79 + src/opticalcontroller/OpticalController.py | 232 +++ src/opticalcontroller/README.md | 17 + src/opticalcontroller/RSA.py | 913 ++++++++ src/opticalcontroller/__init__.py | 0 src/opticalcontroller/dijsktra.py | 222 ++ src/opticalcontroller/images/topo.png | Bin 0 -> 30289 bytes src/opticalcontroller/json_files/nodes.json | 39 + .../json_files/optical_TFSworking.json | 486 +++++ .../json_files/optical_topoTFS.json | 1836 +++++++++++++++++ src/opticalcontroller/json_files/tfs.json | 1286 ++++++++++++ .../json_files/topo_2_links.json | 1530 ++++++++++++++ .../json_files/topology-optical.json | 252 +++ .../json_files/topology-optical2.json | 324 +++ src/opticalcontroller/requirements.in | 7 + src/opticalcontroller/tools.py | 175 ++ src/opticalcontroller/variables.py | 18 + 17 files changed, 7416 insertions(+) create mode 100644 src/opticalcontroller/Dockerfile create mode 100644 src/opticalcontroller/OpticalController.py create mode 100644 src/opticalcontroller/README.md create mode 100644 src/opticalcontroller/RSA.py create mode 100644 src/opticalcontroller/__init__.py create mode 100644 src/opticalcontroller/dijsktra.py create mode 100644 src/opticalcontroller/images/topo.png create mode 100644 src/opticalcontroller/json_files/nodes.json create mode 100644 src/opticalcontroller/json_files/optical_TFSworking.json create mode 100644 src/opticalcontroller/json_files/optical_topoTFS.json create mode 100644 src/opticalcontroller/json_files/tfs.json create mode 100644 src/opticalcontroller/json_files/topo_2_links.json create mode 100644 src/opticalcontroller/json_files/topology-optical.json create mode 100644 src/opticalcontroller/json_files/topology-optical2.json create mode 100644 src/opticalcontroller/requirements.in create mode 100644 src/opticalcontroller/tools.py create mode 100644 src/opticalcontroller/variables.py diff --git a/src/opticalcontroller/Dockerfile b/src/opticalcontroller/Dockerfile new file mode 100644 index 000000000..c3d886ab5 --- /dev/null +++ b/src/opticalcontroller/Dockerfile @@ -0,0 +1,79 @@ +# Copyright 2022-2023 ETSI TeraFlowSDN - TFS OSG (https://tfs.etsi.org/) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +FROM python:3.9-slim + +# Install dependencies +RUN apt-get --yes --quiet --quiet update && \ + apt-get --yes --quiet --quiet install wget g++ && \ + rm -rf /var/lib/apt/lists/* + +# Set Python to show logs as they occur +ENV PYTHONUNBUFFERED=0 + +# Download the gRPC health probe +# RUN GRPC_HEALTH_PROBE_VERSION=v0.2.0 && \ +# wget -qO/bin/grpc_health_probe https://github.com/grpc-ecosystem/grpc-health-probe/releases/download/${GRPC_HEALTH_PROBE_VERSION}/grpc_health_probe-linux-amd64 && \ +# chmod +x /bin/grpc_health_probe + + + + +# Get generic Python packages +RUN python3 -m pip install --upgrade pip +RUN python3 -m pip install --upgrade setuptools wheel +RUN python3 -m pip install --upgrade pip-tools + + + +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 + +RUN mkdir -p /var/teraflow/opticalcontroller + +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/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 +RUN rm *.proto +RUN find . -type f -exec sed -i -E 's/(import\ .*)_pb2/from . \1_pb2/g' {} \; + +# Create component sub-folder, get specific Python packages + + + +WORKDIR /var/teraflow/opticalcontroller +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/ + +COPY src/context/. context/ + +COPY src/opticalcontroller/. opticalcontroller/ +COPY src/context/. opticalcontroller/context/ + +# Start the service +WORKDIR /var/teraflow/opticalcontroller +ENTRYPOINT ["python", "OpticalController.py"] diff --git a/src/opticalcontroller/OpticalController.py b/src/opticalcontroller/OpticalController.py new file mode 100644 index 000000000..1acb67481 --- /dev/null +++ b/src/opticalcontroller/OpticalController.py @@ -0,0 +1,232 @@ +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 + + +rsa = None +LOGGER = logging.getLogger(__name__) + +app = Flask(__name__) +api = Api(app, version='1.0', title='Optical controller API', + description='Rest API to configure OC Optical devices in TFS') +# app.config.from_object('config') +# appbuilder = AppBuilder(app, indexview=MyIndexView) +optical = api.namespace('OpticalTFS', description='TFS Optical APIs') + + +@app.route('/index') +def index(): + return render_template('index.html') + + +#@optical.route('/AddLightpath/<string:src>/<string:dst>/<int:bitrate>/<int:bidir>') +@optical.route('/AddLightpath/<string:src>/<string:dst>/<int:bitrate>') +@optical.response(200, 'Success') +@optical.response(404, 'Error, not found') +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)) + t0 = time.time()*1000.0 + if debug: + rsa.g.printGraph() + + if rsa is not None: + 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 + elapsed = t1 - t0 + LOGGER.info("INFO: time elapsed = {} ms".format(elapsed)) + return rsa.db_flows[flow_id], 200 + else: + return "Error", 404 + + +#@optical.route('/AddFlexLightpath/<string:src>/<string:dst>/<int:bitrate>') +@optical.route('/AddFlexLightpath/<string:src>/<string:dst>/<int:bitrate>', + defaults={"bidir": 1, "band": None}) +@optical.route('/AddFlexLightpath/<string:src>/<string:dst>/<int:bitrate>/<int:bidir>', + defaults={"band": None}) +@optical.route('/AddFlexLightpath/<string:src>/<string:dst>/<int:bitrate>/<int:bidir>/<int:band>',) +@optical.response(200, 'Success') +@optical.response(404, 'Error, not found') +class AddFlexLightpath(Resource): + @staticmethod + 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 + t1 = time.time() * 1000.0 + elapsed = t1 - t0 + print("INFO: time elapsed = {} ms".format(elapsed)) + + return rsa.db_flows[flow_id], 200 + else: + if len(rsa.optical_bands[optical_band_id]["flows"]) == 0: + return 'No path found', 404 + else: + t1 = time.time() * 1000.0 + elapsed = t1 - t0 + LOGGER.info("INFO: time elapsed = {} ms".format(elapsed)) + + return rsa.optical_bands[optical_band_id], 200 + else: + return "Error", 404 + +@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): + @staticmethod + def delete(flow_id, src, dst, bitrate, o_band_id): + if flow_id in rsa.db_flows.keys(): + flow = rsa.db_flows[flow_id] + bidir = flow["bidir"] + match1 = flow["src"] == src and flow["dst"] == dst and flow["bitrate"] == bitrate + if bidir: + match2 = flow["src"] == dst and flow["dst"] == src and flow["bitrate"] == bitrate + if match1 or match2: + ob_id = flow["parent_opt_band"] + 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 debug: + LOGGER.info(links_dict) + return "flow {} deleted".format(flow_id), 200 + else: + return "flow {} not matching".format(flow_id), 404 + else: + if match1: + ob_id = flow["parent_opt_band"] + 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 debug: + LOGGER.info(links_dict) + return "flow {} deleted".format(flow_id), 200 + else: + return "flow {} not matching".format(flow_id), 404 + else: + return "flow id {} does not exist".format(flow_id), 404 + + + +@optical.route('/DelLightpath/<int:flow_id>/<string:src>/<string:dst>/<int:bitrate>') +@optical.response(200, 'Success') +@optical.response(404, 'Error, not found') +class DelLightpath(Resource): + @staticmethod + def delete(flow_id, src, dst, bitrate): + if flow_id in rsa.db_flows.keys(): + flow = rsa.db_flows[flow_id] + match1 = flow["src"] == src and flow["dst"] == dst and flow["bitrate"] == bitrate + match2 = flow["src"] == dst and flow["dst"] == src and flow["bitrate"] == bitrate + if match1 or match2: + rsa.del_flow(flow) + rsa.db_flows[flow_id]["is_active"] = False + if debug: + LOGGER.info(links_dict) + return "flow {} deleted".format(flow_id), 200 + else: + return "flow {} not matching".format(flow_id), 404 + else: + return "flow id {} does not exist".format(flow_id), 404 + + +@optical.route('/GetLightpaths') +@optical.response(200, 'Success') +@optical.response(404, 'Error, not found') +class GetFlows(Resource): + @staticmethod + def get(): + try: + if debug: + LOGGER.info(rsa.db_flows) + return rsa.db_flows, 200 + except: + return "Error", 404 + +@optical.route('/GetOpticalBands') +@optical.response(200, 'Success') +@optical.response(404, 'Error, not found') +class GetBands(Resource): + @staticmethod + def get(): + print("Getting ") + LOGGER.info("Getting") + try: + if debug: + LOGGER.info(rsa.optical_bands) + return rsa.optical_bands, 200 + except: + return "Error", 404 + + +@optical.route('/GetOpticalBand/<string:ob_id>') +@optical.response(200, 'Success') +@optical.response(404, 'Error, not found') +class GetBand(Resource): + @staticmethod + def get(ob_id): + for ob_idx in rsa.optical_bands.keys(): + if str(ob_idx) == str(ob_id): + if debug: + LOGGER.info(rsa.optical_bands[ob_id]) + return rsa.optical_bands[ob_idx], 200 + return {}, 404 + + +@optical.route('/GetLinks') +@optical.response(200, 'Success') +@optical.response(404, 'Error, not found') +class GetFlows(Resource): + @staticmethod + def get(): + global links_dict + try: + if debug: + LOGGER.info(links_dict) + return links_dict, 200 + except: + return "Error", 404 + + +if __name__ == '__main__': + + + # Start metrics server + + LOGGER.info('Starting...') + + + + 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) + LOGGER.info(rsa.init_link_slots(testing)) + + app.run(host='0.0.0.0', port=5022,debug=True) diff --git a/src/opticalcontroller/README.md b/src/opticalcontroller/README.md new file mode 100644 index 000000000..5fd94c59e --- /dev/null +++ b/src/opticalcontroller/README.md @@ -0,0 +1,17 @@ +# optical-controller +This a framework to implement the optical controller for the RMSA algorithm. +#create a venv +python -m venv venv + +in linux +source venv/Scripts/activate + +in windows +venv\Scripts\activate + +pip install -r requirements_opt.txt + +python OpticalController.py + + + diff --git a/src/opticalcontroller/RSA.py b/src/opticalcontroller/RSA.py new file mode 100644 index 000000000..47ddbe71c --- /dev/null +++ b/src/opticalcontroller/RSA.py @@ -0,0 +1,913 @@ +import dijsktra +from tools import * +from variables import * + + +class RSA(): + def __init__(self, nodes, links): + self.nodes_dict = nodes + self.links_dict = links + self.g = None + + self.flow_id = 0 + self.opt_band_id = 0 + self.db_flows = {} + self.initGraph() + self.c_slot_number = 0 + self.l_slot_number = 0 + self.s_slot_number = 0 + self.optical_bands = {} + + def init_link_slots(self, testing): + if not testing: + for l in self.links_dict["links"]: + for fib in l["optical_link"]["details"]["fibers"]: + #fib = self.links_dict[l]["fibers"][f] + if len(fib["c_slots"]) > 0: + fib["c_slots"] = list(range(0, Nc)) + if len(fib["l_slots"]) > 0: + fib["l_slots"] = list(range(0, Nl)) + if len(fib["s_slots"]) > 0: + fib["s_slots"] = list(range(0, Ns)) + if debug: + print(fib) + for l1 in self.links_dict["links"]: + + for fib1 in l1["optical_link"]["details"]["fibers"]: + #fib1 = self.links_dict[l1]["details"]["fibers"][f1] + + self.c_slot_number = len(fib1["c_slots"]) + self.l_slot_number = len(fib1["l_slots"]) + self.s_slot_number = len(fib1["s_slots"]) + + break + 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"]: + if debug: + print(l) + [s, d] = l["optical_link"]["name"].split('-') + ps = l["optical_link"]["details"]["source"] + pd = l["optical_link"]["details"]["target"] + self.g.add_edge(s, d, ps, pd, 1) + + print("INFO: Graph initiated.") + 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())) + if debug: + print(path) + links = [] + for i in range(0, len(path) - 1): + s = path[i] + if debug: + print(s) + if i < len(path) - 1: + d = path[i + 1] + link_id = "{}-{}".format(s, d) + if debug: + #print(link_id, self.links_dict[link_id]) + print(link_id, self.get_link_by_name(link_id)) + + links.append(link_id) + self.g.reset_graph() + return links, path + + def get_slots(self, links, slots, optical_band_id = None): + + if isinstance(slots, int): + val_c = slots + val_s = slots + val_l = slots + else: + val_c = self.c_slot_number + val_l = self.l_slot_number + val_s = self.s_slot_number + + c_sts = [] + l_sts = [] + s_sts = [] + c_slots = {} + l_slots = {} + s_slots = {} + add = "" + drop = "" + src_1, dst_1 = links[0].split('-') + src_2, dst_2 = links[-1].split('-') + if self.nodes_dict[src_1]["type"] == "OC-TP": + add = links[0] + if self.nodes_dict[dst_2]["type"] == "OC-TP": + drop = links[-1] + + 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: + return [], [], [] + + keys = list(c_slots.keys()) + if debug: + print(len(keys)) + if debug: + print(keys[0]) + # intersection among the slots over all links + if len(keys) == 1: + c_sts = c_slots[keys[0]] + l_sts = l_slots[keys[0]] + s_sts = s_slots[keys[0]] + else: + for i in range(1, len(keys)): + if debug: + print(keys[i]) + # set a for the intersection + if i == 1: + a_c = c_slots[keys[i - 1]] + a_l = l_slots[keys[i - 1]] + a_s = s_slots[keys[i - 1]] + else: + a_c = c_sts + a_l = l_sts + a_s = s_sts + # set b for the intersection + b_c = c_slots[keys[i]] + b_l = l_slots[keys[i]] + b_s = s_slots[keys[i]] + + 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 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"] + 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"] + 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"] + 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): + for i in slots: + fib[band].remove(i) + if 'used' in fib: + fib['used'] = True + + def update_optical_band(self, optical_band_id, slots, band): + for i in slots: + self.optical_bands[optical_band_id][band].remove(i) + + def restore_link(self, fib, slots, band): + for i in slots: + fib[band].append(int(i)) + 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() + + def del_flow(self, flow, o_b_id = None): + flows = flow["flows"] + band = flow["band_type"] + slots = flow["slots"] + fiber_f = flow["fiber_forward"] + fiber_b = flow["fiber_backward"] + op = flow["op-mode"] + n_slots = flow["n_slots"] + path = flow["path"] + links = flow["links"] + bidir = flow["bidir"] + + for l in fiber_f.keys(): + 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]): + self.restore_link(fib, slots, band) + if debug: + print(fib[band]) + if o_b_id is not None: + self.restore_optical_band(o_b_id, slots, band) + if bidir: + for rl in fiber_b.keys(): + if debug: + print(rl) + print(fiber_b[rl]) + #rlink = self.links_dict[rl] + #rf = fiber_b[rl] + #rfib = rlink['fibers'][rf] + rfib = self.get_fiber_details(rl, fiber_b[rl]) + if not list_in_list(slots, rfib[band]): + 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"] + # self.restore_optical_band(rev_o_band_id, slots, band) + return True + + def get_fibers_forward(self, links, slots, band): + fiber_list = {} + add = links[0] + drop = links[-1] + print(links) + ''' + 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"]: + + ''' + 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 + print("INFO: Path forward computation completed") + return fiber_list + + def get_link_by_name (self, key): + for link in self.links_dict["links"]: + if link["optical_link"]["name"] == key: + if debug: + print(link) + 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: + if debug: + print(link) + for fib in link["optical_link"]["details"]["fibers"]: + if fib["ID"] == fiber_id: + return fib + return None + + + def get_fibers_backward(self, links, fibers, 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]) + ''' + 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"] + r_l = reverse_link(l) + r_link = self.get_link_by_name(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) + print("INFO: Path backward computation completed") + return fiber_list + + 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 band is None: + print("No slots available in the three bands") + return None, None, None + if debug: + print(band, slots) + fibers_f = self.get_fibers_forward(links, slots, band) + + fibers_b = [] + if bidir: + fibers_b = self.get_fibers_backward(links, fibers_f, slots, band) + if debug: + print("forward") + print(fibers_f) + print("backward") + print(fibers_b) + add = links[0] + drop = links[-1] + inport = "0" + outport = "0" + r_inport = "0" + r_outport = "0" + t_flows = {} + #if len(links) == 1: + + for lx in fibers_f: + if lx == add: + inport = "0" + r_outport = "0" + if lx == drop: + outport = "0" + r_inport = "0" + f = fibers_f[lx] + src, dst = lx.split("-") + fibx = self.get_fiber_details(lx, f) + #outport = self.links_dict[lx]['fibers'][f]["src_port"] + outport = fibx["src_port"] + + t_flows[src] = {} + t_flows[src]["f"] = {} + t_flows[src]["b"] = {} + t_flows[src]["f"] = {"in": inport, "out": outport} + + if bidir: + #r_inport = self.links_dict[lx]['fibers'][f]["local_peer_port"] + r_inport = fibx["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"] + if bidir: + #r_outport = self.links_dict[lx]['fibers'][f]["remote_peer_port"] + r_outport = fibx["remote_peer_port"] + t_flows[dst] = {} + t_flows[dst]["f"] = {} + t_flows[dst]["b"] = {} + t_flows[dst]["f"] = {"in": inport, "out": "0"} + if bidir: + t_flows[dst]["b"] = {"in": "0", "out": r_outport} + + if debug: + print(self.links_dict) + + if debug: + print(t_flows) + print("INFO: Flow matrix computed") + + return t_flows, band, slots, fibers_f, fibers_b + + def select_slots_and_ports_fs(self, links, n_slots, c, l, s, bidir, o_band_id): + 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 band is None: + print("No slots available in the three bands") + 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 = [] + 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" + + t_flows = {} + + #flows_add_side + f = fibers_f[add] + src, dst = add.split("-") + fibx = self.get_fiber_details(add, f) + #outport = self.links_dict[add]['fibers'][f]["src_port"] + outport = fibx["src_port"] + #T1 rules + t_flows[src] = {} + t_flows[src]["f"] = {} + t_flows[src]["b"] = {} + 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"] + t_flows[src]["b"] = {"in": r_inport, "out": port_0} + + #R1 rules + t_flows[dst] = {} + t_flows[dst]["f"] = {} + t_flows[dst]["b"] = {} + #inport = self.links_dict[add]['fibers'][f]["dst_port"] + inport = fibx["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"] + 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"] + t_flows[dst]["b"] = {"in": rev_opt_band_dst_port, "out": r_outport} + + #flows_drop_side + # R2 rules + f = fibers_f[drop] + src, dst = drop.split("-") + fiby = self.get_fiber_details(drop, f) + #outport = self.links_dict[drop]['fibers'][f]["src_port"] + outport = fiby["src_port"] + + t_flows[src] = {} + t_flows[src]["f"] = {} + t_flows[src]["b"] = {} + opt_band_dst_port = self.optical_bands[o_band_id]["dst_port"] + t_flows[src]["f"] = {"in": opt_band_dst_port, "out": outport} + 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"] + 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"] + 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"] + t_flows[dst]["b"] = {"in": port_0, "out": r_inport} + + if debug: + print(self.links_dict) + + if debug: + print(t_flows) + print("INFO: Flow matrix computed for Flex Lightpath") + + return t_flows, band, slots, fibers_f, fibers_b + + def rsa_computation(self, src, dst, rate, bidir): + 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 + + links, path = self.compute_path(src, dst) + + if len(path) < 1: + self.null_values(self.flow_id) + return self.flow_id + op, num_slots = map_rate_to_slot(rate) + c_slots, l_slots, s_slots = self.get_slots(links, num_slots) + if debug: + print(c_slots) + print(l_slots) + print(s_slots) + 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) + if debug: + print(f0, band) + print("INFO: RSA completed for normal wavelenght connection") + if flow_list is None: + self.null_values(self.flow_id) + return self.flow_id + slots_i = [] + for i in slots: + slots_i.append(int(i)) + # 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 + self.db_flows[self.flow_id]["flows"] = flow_list + self.db_flows[self.flow_id]["band_type"] = band_range + self.db_flows[self.flow_id]["slots"] = slots_i + self.db_flows[self.flow_id]["fiber_forward"] = fiber_f + self.db_flows[self.flow_id]["fiber_backward"] = fiber_b + self.db_flows[self.flow_id]["op-mode"] = op + self.db_flows[self.flow_id]["n_slots"] = num_slots + self.db_flows[self.flow_id]["links"] = links + self.db_flows[self.flow_id]["path"] = path + self.db_flows[self.flow_id]["band"] = band + self.db_flows[self.flow_id]["freq"] = f0 + self.db_flows[self.flow_id]["is_active"] = True + return self.flow_id + + def null_values(self, flow_id): + self.db_flows[flow_id]["flows"] = {} + self.db_flows[flow_id]["band_type"] = "" + self.db_flows[flow_id]["slots"] = [] + self.db_flows[flow_id]["fiber_forward"] = [] + self.db_flows[flow_id]["fiber_backward"] = [] + self.db_flows[flow_id]["op-mode"] = 0 + self.db_flows[flow_id]["n_slots"] = 0 + self.db_flows[flow_id]["links"] = {} + self.db_flows[flow_id]["path"] = [] + self.db_flows[flow_id]["band"] = 0 + self.db_flows[flow_id]["freq"] = 0 + self.db_flows[flow_id]["is_active"] = False + + def null_values_ob(self, ob_id): + self.optical_bands[ob_id]["flows"] = {} + self.optical_bands[ob_id]["band_type"] = "" + #self.optical_bands[ob_id]["slots"] = [] + self.optical_bands[ob_id]["fiber_forward"] = [] + self.optical_bands[ob_id]["n_slots"] = 0 + self.optical_bands[ob_id]["links"] = {} + self.optical_bands[ob_id]["path"] = [] + self.optical_bands[ob_id]["band"] = 0 + self.optical_bands[ob_id]["freq"] = 0 + self.optical_bands[ob_id]["is_active"] = False + self.optical_bands[ob_id]["c_slots"] = [] + self.optical_bands[ob_id]["l_slots"] = [] + self.optical_bands[ob_id]["s_slots"] = [] + self.optical_bands[ob_id]["served_lightpaths"] = [] + self.optical_bands[ob_id]["reverse_optical_band_id"] = 0 + self.db_flows[self.flow_id]["parent_opt_band"] = 0 + self.db_flows[self.flow_id]["new_optical_band"] = 0 + + def create_optical_band(self, links, path, bidir, num_slots): + print("INFO: Creating optical-band of {} slots".format(num_slots)) + self.opt_band_id += 1 + forw_opt_band_id = self.opt_band_id + self.optical_bands[forw_opt_band_id] = {} + self.optical_bands[forw_opt_band_id]["optical_band_id"] = forw_opt_band_id + self.optical_bands[forw_opt_band_id]["bidir"] = bidir + ''' + back_opt_band_id = 0 + if bidir: + self.opt_band_id += 1 + back_opt_band_id = self.opt_band_id + self.optical_bands[back_opt_band_id] = {} + self.optical_bands[back_opt_band_id]["optical_band_id"] = back_opt_band_id + self.optical_bands[back_opt_band_id]["bidir"] = bidir + self.optical_bands[back_opt_band_id]["reverse_optical_band_id"] = forw_opt_band_id + self.optical_bands[forw_opt_band_id]["reverse_optical_band_id"] = back_opt_band_id + else: + self.optical_bands[forw_opt_band_id]["reverse_optical_band_id"] = 0 + ''' + op = 0 + temp_links = [] + #num_slots = "all" + if self.nodes_dict[path[0]]["type"] == "OC-TP": + add_link = links[0] + temp_links.append(add_link) + links.remove(add_link) + path.remove(path[0]) + self.optical_bands[forw_opt_band_id]["src"] = path[0] + ''' + if bidir: + self.optical_bands[back_opt_band_id]["dst"] = path[0] + ''' + if self.nodes_dict[path[-1]]["type"] == "OC-TP": + drop_link = links[-1] + temp_links.append(drop_link) + links.remove(drop_link) + path.remove(path[-1]) + self.optical_bands[forw_opt_band_id]["dst"] = path[-1] + ''' + if bidir: + self.optical_bands[back_opt_band_id]["src"] = path[-1] + ''' + + c_slots, l_slots, s_slots = self.get_slots(links, num_slots) + if debug: + print(c_slots) + print(l_slots) + print(s_slots) + 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) + ''' + + flow_list_b = {} + rev_path = path.copy() + rev_path.reverse() + rev_links = reverse_links(links) + if bidir: + for dev_x in flow_list.keys(): + flow_list_b[dev_x] = {} + flow_list_b[dev_x]["f"] = flow_list[dev_x]["b"] + del flow_list[dev_x]["b"] + rev_path = path.copy() + ''' + if debug: + print(f0, band) + print("INFO: RSA completed for optical band") + if flow_list is None: + self.null_values(self.flow_id) + return self.flow_id, [] + slots_i = [] + for i in slots: + slots_i.append(int(i)) + + # 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 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] + #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]) + 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]) + rev_dst_port = fib_inx["local_peer_port"] + rev_src_port = fib_outx["remote_peer_port"] + + #fib_in = fiber_f[link_in] + #fib_out = fiber_f[link_out] + #rev_dst_port = self.links_dict[link_in]['fibers'][fib_in]["local_peer_port"] + #rev_src_port = self.links_dict[link_out]['fibers'][fib_out]["remote_peer_port"] + + self.optical_bands[forw_opt_band_id]["flows"] = flow_list + self.optical_bands[forw_opt_band_id]["band_type"] = band_range + self.optical_bands[forw_opt_band_id]["fiber_forward"] = fiber_f + self.optical_bands[forw_opt_band_id]["fiber_backward"] = fiber_b + self.optical_bands[forw_opt_band_id]["op-mode"] = op + self.optical_bands[forw_opt_band_id]["n_slots"] = num_slots + self.optical_bands[forw_opt_band_id]["links"] = links + self.optical_bands[forw_opt_band_id]["path"] = path + self.optical_bands[forw_opt_band_id]["band"] = band + self.optical_bands[forw_opt_band_id]["freq"] = f0 + self.optical_bands[forw_opt_band_id]["is_active"] = True + self.optical_bands[forw_opt_band_id]["src_port"] = src_port + self.optical_bands[forw_opt_band_id]["dst_port"] = dst_port + self.optical_bands[forw_opt_band_id]["rev_dst_port"] = rev_dst_port + self.optical_bands[forw_opt_band_id]["rev_src_port"] = rev_src_port + self.optical_bands[forw_opt_band_id][band_range] = slots_i + self.optical_bands[forw_opt_band_id]["served_lightpaths"] = [] + ''' + if bidir: + self.optical_bands[back_opt_band_id]["flows"] = flow_list_b + self.optical_bands[back_opt_band_id]["band_type"] = band_range + self.optical_bands[back_opt_band_id]["fiber_forward"] = fiber_b + # self.optical_bands[back_opt_band_id]["fiber_backward"] = fiber_b + self.optical_bands[back_opt_band_id]["op-mode"] = op + self.optical_bands[back_opt_band_id]["n_slots"] = num_slots + self.optical_bands[back_opt_band_id]["links"] = rev_links + self.optical_bands[back_opt_band_id]["path"] = rev_path + self.optical_bands[back_opt_band_id]["band"] = band + self.optical_bands[back_opt_band_id]["freq"] = f0 + self.optical_bands[back_opt_band_id]["is_active"] = True + self.optical_bands[back_opt_band_id]["src_port"] = rev_src_port + self.optical_bands[back_opt_band_id]["dst_port"] = rev_dst_port + self.optical_bands[back_opt_band_id][band_range] = slots_i.copy() + self.optical_bands[back_opt_band_id]["served_lightpaths"] = [] + ''' + + return forw_opt_band_id, temp_links + + def get_optical_bands(self, r_src, r_dst): + result = [] + for ob_id in self.optical_bands: + ob = self.optical_bands[ob_id] + if debug: + print(r_src, ob["src"]) + print(r_dst, ob["dst"]) + print(ob) + if ob["src"] == r_src and ob["dst"] == r_dst: + result.append(ob_id) + return result + + def rsa_fs_computation(self, src, dst, rate, bidir, band): + num_slots_ob = "full_band" + if band is not None: + num_slots_ob = map_band_to_slot(band) + print(band, num_slots_ob) + if self.nodes_dict[src]["type"] == "OC-ROADM" and self.nodes_dict[dst]["type"] == "OC-ROADM": + print("INFO: ROADM to ROADM connection") + links, path = self.compute_path(src, dst) + if len(path) < 1: + self.null_values_ob(self.opt_band_id) + 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") + if band is None: + temp_links2 = [] + temp_path = [] + src_links = get_links_from_node(self.links_dict, src) + dst_links = get_links_to_node(self.links_dict, dst) + if len(src_links.keys()) >= 1: + temp_links2.append(list(src_links.keys())[0]) + if len(dst_links.keys()) >= 1: + temp_links2.append(list(dst_links.keys())[0]) + + if len(temp_links2) == 2: + [t_src, roadm_src] = temp_links2[0].split('-') + [roadm_dst, t_dst] = temp_links2[1].split('-') + temp_path.append(t_src) + temp_path.append(roadm_src) + temp_path.append(roadm_dst) + temp_path.append(t_dst) + existing_ob = self.get_optical_bands(roadm_src, roadm_dst) + 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 len(existing_ob) > 0: + print("INFO: Evaluating existing OB {}".format(existing_ob)) + #first checking in existing OB + ob_found = 0 + for ob_id in existing_ob: + op, num_slots = map_rate_to_slot(rate) + if debug: + print(temp_links2) + c_slots, l_slots, s_slots = self.get_slots(temp_links2, num_slots, ob_id) + if debug: + print(c_slots) + print(l_slots) + print(s_slots) + if len(c_slots) >= num_slots or len(l_slots) >= num_slots or len(s_slots) >= num_slots: + flow_list, band_range, slots, fiber_f, fiber_b = self.select_slots_and_ports_fs(temp_links2, num_slots, + c_slots, + l_slots, s_slots, bidir, + ob_id) + f0, band = freqency_converter(band_range, slots) + if debug: + print(f0, band) + print("INFO: RSA completed for Flex Lightpath with OB already in place") + if flow_list is None: + self.null_values(self.flow_id) + continue + slots_i = [] + for i in slots: + slots_i.append(int(i)) + # 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 + self.db_flows[self.flow_id]["flows"] = flow_list + self.db_flows[self.flow_id]["band_type"] = band_range + self.db_flows[self.flow_id]["slots"] = slots_i + self.db_flows[self.flow_id]["fiber_forward"] = fiber_f + self.db_flows[self.flow_id]["fiber_backward"] = fiber_b + self.db_flows[self.flow_id]["op-mode"] = op + self.db_flows[self.flow_id]["n_slots"] = num_slots + self.db_flows[self.flow_id]["links"] = temp_links2 + self.db_flows[self.flow_id]["path"] = temp_path + self.db_flows[self.flow_id]["band"] = band + self.db_flows[self.flow_id]["freq"] = f0 + self.db_flows[self.flow_id]["is_active"] = True + self.db_flows[self.flow_id]["parent_opt_band"] = ob_id + self.db_flows[self.flow_id]["new_optical_band"] = 0 + self.optical_bands[ob_id]["served_lightpaths"].append(self.flow_id) + ''' + if bidir: + rev_ob_id = self.optical_bands[ob_id]["reverse_optical_band_id"] + self.optical_bands[rev_ob_id]["served_lightpaths"].append(self.flow_id) + ''' + return self.flow_id, ob_id + else: + print("not enough slots") + if band is None: + print("INFO: Not existing optical-band meeting the requirements") + else: + print("INFO: optical-band width specified") + #if no OB I create a new one + 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) + c_slots, l_slots, s_slots = self.get_slots(temp_links, num_slots, optical_band_id) + if debug: + print(c_slots) + print(l_slots) + print(s_slots) + 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_fs(temp_links, num_slots, c_slots, + l_slots, s_slots, bidir, optical_band_id) + f0, band = freqency_converter(band_range, slots) + if debug: + print(f0, band) + print("INFO: RSA completed for FLex Lightpath with new OB") + if flow_list is None: + self.null_values(self.flow_id) + return self.flow_id, optical_band_id + slots_i = [] + for i in slots: + slots_i.append(int(i)) + + self.db_flows[self.flow_id]["flows"] = flow_list + self.db_flows[self.flow_id]["band_type"] = band_range + self.db_flows[self.flow_id]["slots"] = slots_i + self.db_flows[self.flow_id]["fiber_forward"] = fiber_f + self.db_flows[self.flow_id]["fiber_backward"] = fiber_b + self.db_flows[self.flow_id]["op-mode"] = op + self.db_flows[self.flow_id]["n_slots"] = num_slots + self.db_flows[self.flow_id]["links"] = temp_links + self.db_flows[self.flow_id]["path"] = path + self.db_flows[self.flow_id]["band"] = band + self.db_flows[self.flow_id]["freq"] = f0 + self.db_flows[self.flow_id]["is_active"] = True + self.db_flows[self.flow_id]["parent_opt_band"] = optical_band_id + self.db_flows[self.flow_id]["new_optical_band"] = 1 + self.optical_bands[optical_band_id]["served_lightpaths"].append(self.flow_id) + ''' + if bidir: + rev_ob_id = self.optical_bands[optical_band_id]["reverse_optical_band_id"] + self.optical_bands[rev_ob_id]["served_lightpaths"].append(self.flow_id) + ''' + return self.flow_id, optical_band_id diff --git a/src/opticalcontroller/__init__.py b/src/opticalcontroller/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/src/opticalcontroller/dijsktra.py b/src/opticalcontroller/dijsktra.py new file mode 100644 index 000000000..5be78c624 --- /dev/null +++ b/src/opticalcontroller/dijsktra.py @@ -0,0 +1,222 @@ +import sys + +class Vertex: + def __init__(self, node): + self.id = node + self.adjacent = {} + # Set distance to infinity for all nodes + self.distance = float("inf") + # Mark all nodes unvisited + self.visited = False + # Predecessor + self.previous = None + + # heapq compara gli item nella coda usando <= per vedere ci sono duplciati: + # se ho una coda di tuple, + # compara il primo elemento della prima tupla nella coda con il primo elemento della seconda tupla nella coda + # se sono diversi si ferma, se sono uguali continua + # la tupla nel caso in esame è: (v.get_distance(),v) + # se due nodi hanno stessa distanza, heapq procede a comparare v: Vertex(). + # Va quindi definita una politica per confrontare i Vertex + def __lt__(self, other): + if self.id < other.id: + return True + else: + return False + + def __le__(self, other): + if self.id <= other.id: + return True + else: + return False + + def add_neighbor(self, neighbor, port): + self.adjacent[neighbor] = port + + def del_neighbor(self, neighbor): + self.adjacent.pop(neighbor) + + def get_connections(self): + return self.adjacent.keys() + + def get_id(self): + return self.id + + def get_port(self, neighbor): + return self.adjacent[neighbor][0] + + def get_weight(self, neighbor): + return self.adjacent[neighbor][1] + + def set_distance(self, dist): + self.distance = dist + + def get_distance(self): + return self.distance + + def set_previous(self, prev): + self.previous = prev + + def set_visited(self): + self.visited = True + + def reset_vertex(self): + self.visited = False + self.previous = None + self.distance = float("inf") + + def __str__(self): + return str(self.id) + ' adjacent: ' + str([x.id for x in self.adjacent]) + +class Graph: + def __init__(self): + self.vert_dict = {} + self.num_vertices = 0 + + def __iter__(self): + return iter(self.vert_dict.values()) + + def reset_graph(self): + for n in self.vert_dict: + self.get_vertex(n).reset_vertex() + + def printGraph(self): + for v in self: + for w in v.get_connections(): + vid = v.get_id() + wid = w.get_id() + print ('( %s , %s, %s, %s, %s, %s)' % ( vid, wid, v.get_port(w), w.get_port(v), v.get_weight(w), w.get_weight(v))) + + def add_vertex(self, node): + self.num_vertices = self.num_vertices + 1 + new_vertex = Vertex(node) + self.vert_dict[node] = new_vertex + return new_vertex + + def del_Vertex(self, node): + self.vert_dict.pop(node) + + def get_vertex(self, n): + if n in self.vert_dict: + return self.vert_dict[n] + else: + return None + + def add_edge(self, frm, to, port_frm, port_to,w): + if frm not in self.vert_dict: + self.add_vertex(frm) + if to not in self.vert_dict: + self.add_vertex(to) + + self.vert_dict[frm].add_neighbor(self.vert_dict[to], [port_frm, w]) + self.vert_dict[to].add_neighbor(self.vert_dict[frm], [port_to, w]) + + def del_edge(self, frm, to, cost = 0): + self.vert_dict[frm].del_neighbor(self.vert_dict[to]) + self.vert_dict[to].del_neighbor(self.vert_dict[frm]) + + def get_vertices(self): + return self.vert_dict.keys() + + def set_previous(self, current): + self.previous = current + + def get_previous(self, current): + return self.previous + +def shortest(v, path): + if v.previous: + path.append(v.previous.get_id()) + shortest(v.previous, path) + return + +import heapq + +def dijkstra(aGraph, start): + """print ('''Dijkstra's shortest path''')""" + # Set the distance for the start node to zero + start.set_distance(0) + + # Put tuple pair into the priority queue + unvisited_queue = [(v.get_distance(),v) for v in aGraph] + #priority queue->costruisce un albero in cui ogni nodo parent ha ha un valore <= di ogni child + #heappop prende il valore più piccolo, nel caso di dikstra, il nodo più vicino + heapq.heapify(unvisited_queue) + + while len(unvisited_queue): + # Pops a vertex with the smallest distance + uv = heapq.heappop(unvisited_queue) + current = uv[1] + current.set_visited() + + #for next in v.adjacent: + for next in current.adjacent: + # if visited, skip + if next.visited: + continue + new_dist = current.get_distance() + current.get_weight(next) + + if new_dist < next.get_distance(): + next.set_distance(new_dist) + next.set_previous(current) + """print ('updated : current = %s next = %s new_dist = %s' \ + %(current.get_id(), next.get_id(), next.get_distance()))""" + else: + """print ('not updated : current = %s next = %s new_dist = %s' \ + %(current.get_id(), next.get_id(), next.get_distance()))""" + + # Rebuild heap + # 1. Pop every item + while len(unvisited_queue): + heapq.heappop(unvisited_queue) + # 2. Put all vertices not visited into the queue + unvisited_queue = [(v.get_distance(),v) for v in aGraph if not v.visited] + heapq.heapify(unvisited_queue) + +def shortest_path(graph, src, dst): + dijkstra(graph, src) + target = dst + path = [target.get_id()] + shortest(target, path) + return path[::-1] + +if __name__ == '__main__': + + print("Testing Algo") + g = Graph() + + g.add_vertex('a') + g.add_vertex('b') + g.add_vertex('c') + g.add_vertex('d') + g.add_vertex('e') + g.add_vertex('f') + + g.add_edge('a', 'b', 7) + g.add_edge('a', 'c', 9) + g.add_edge('a', 'f', 14) + g.add_edge('b', 'c', 10) + g.add_edge('b', 'd', 15) + g.add_edge('c', 'd', 11) + g.add_edge('c', 'f', 2) + g.add_edge('d', 'e', 6) + g.add_edge('e', 'f', 9) + + + """print ('Graph data:') + for v in g: + for w in v.get_connections(): + vid = v.get_id() + wid = w.get_id() + print ('( %s , %s, %3d)' % ( vid, wid, v.get_weight(w))) + + + dijkstra(g, g.get_vertex('a')) + + target = g.get_vertex('e') + path = [target.get_id()] + shortest(target, path) + print ('The shortest path : %s' %(path[::-1]))""" + + p = shortest_path(g, g.get_vertex('a'), g.get_vertex('e')) + print(p) \ No newline at end of file diff --git a/src/opticalcontroller/images/topo.png b/src/opticalcontroller/images/topo.png new file mode 100644 index 0000000000000000000000000000000000000000..216e1360b3caecd68285ca8b69fd498049dcbf79 GIT binary patch literal 30289 zcmbTebyO5w_dhy{gd#AYbV(_Vf^<p<f`AGVL#ZG&G=ua20@7X53IZbCT}mS@APqxz z_W<_{&+~qN@A}?#*IoDi;hHtWIs5E$&fcG$$AA|q@&vc2Zb2Xrf@cb{uOJXCTL|QO zJRT1Ch3sw`Irz9{|4LpOlHWtK0>0cZd7}IT0x1f^N591e-*4I|Xxl>|BnZsEYg5Mb zP7sL0;xpMN>Q4F_lQ-YoT{yqo;gP$cZj~LOr1IpZtO{uW&N<T;Is9Rg+%ye*#XJr5 zTFZ>#v+o+%V#pNiT+&>PYcKI`T&u!*@`QVV1bdzg8gYp<NnuFrwkl3se^j!EJVy@3 zFU5~`^VS6HjV{G6Wg~>704oqk$~JxphH;1!gn<zADdq#k#eC99`(t4~i5Qx%fe%kV zC<^nnQ3em}76O@J@Daj%ZbPMMFrQ9%|7-fI6&ugd(8S;m=iOvb`oy?UK^-v6vw?-P z*%Fym&vuP8%C>_HGg(1|>ORzZr#h3Rx#<8y{T^v$rkq&IUP7$v|F<>&f3r+(Qde;D zg1rpM@Pp+~Iqg}P7;?Xo=Q$T<XLlKzTeP!&pAO`>rZXumNokjvzADkG<8G2js#k#> zxGCN5op=-DxOvhK!yH)0WBaB>k`SVZSa}2XLb~)2;xWAbg~*%ohbxDbL>fA0#0D{h zxSuyFJ4{Cm1R4ze$QuR?KCX97Maf%<>U}aud~Y69bC&JAJM&#mqi?Y9XxJ}DNqowh zmwS{EbBZkB5a+ko_$`}uE$z+>Q{y8oHzT=<-ABAg2#7TgthuVl%L}iMqknR}$})bv zGFD%o3#(Alz$I&O$m2>GDJ^ZT^2DiJ!%bmNtviRW{5^D1!v}0L8)ziD@UAT22XayU zRyVD~5z4q`y&kpHakQ6Tx~i$%QI>B#^edfQ2i{D?(1T5Oc|_uTQ81aIzhRz<k)Lfs z0!x)I_UMh?<h(K*v5n+U#|&U4<TyrnzTKf>CGoqGt9zTnxfNRhYLlYxKXWx>T?viU z#JR~X3@$$N5jDyA()J(0vdze|>G8ZzM7Z`Yk67~G-}q;GQ?;-Xf~zHU5(M+j%!zsa z{R7{A0bic*93s$*p(^V$tohDAgmq0lsf7>i*Cd3JrSSuvTuJncw<?}%N!kV}XI<Kv zWC2qC_FnyS_2HP?ip?$&ggI1ySpDc{g3;6o;|biHup5=nc#htNR^DK0u4+tH{T(w- zfA$-Ox%HuyvFyYeqoCIqjj2=yH^OW4_dzD}ZjDZ+;uc(jvwY(Gk5~!$&Wrz1hWC4- z2g*0Ue-2hEZ(q!qQ@#nrUAQunEA7d1YD&Ta3Jdc<Q-9G7l;d-@TK!4tj&E^14_Q0{ zm-x9DdLHb{%xS!L*Z4m=lJVZ(9^S4HXP~<#v$uXj%`PmM`ji+bjVA{&3aV;GjhZ0i zO}j~<f3<ag0tUjJyS;E2jsWIX{*P++B^TdCWIY$FR=W;?R0JL*XcTBquqNl5OtOyc zQG*H6x@>s10rHshvwEEZZ9A|)Ih~_hfrf5IV<`Q<qQU>xOlFIe%3YheTB4QayuD^Q zZ)d=>RPiI#q?(7Sx)DA;mAi$=XA{Sn-<~<y%$>YmL4;m|NVx!s!e_`=fcaK_9Ab={ z;3#&9YDdM%6~jK$F39>TiDA&hhNBJ{7(*@dRAlG$gr(Wn36a~rk*>^e?=qEfay(vI zm>4B%%uU*H5mi^`60ER?b68F#_}XX&PYrK*NX}@$FcZphg-YaB=z*lQ(PqV=lLK_) z{qYY0`}N&~HdKrv6#}AAa;lmA+D`+0xz|*@CuhZ6<HdTBJeZ?k4qcL&AU7DFef#HO z4e57%<q|AXfqgd7M!lgn^&9<t==N|Fm%ZUu$#f8Z;&Y6Yc~<VZ`HL<v*YKOR%Vl1- z{W{4if1x>llBg^Poy@9!KL(c{5jb?&v~wi@ga0mXusfWM;X?zKWRl8ju`6&GB=TLp z8!06k{vs<OZmPEK#^_^OS_R%hXrZ;{X#Kc8l-`B<MFveoY+QWcy|KOLN5VmLYuL{Z zLr9W{wzj<vMIvzyet&xM8BFv~4lP8UIxt!*lUA+SsRdN_(HZsprTmKE^b1=g4cYpF z#k5+ak7ws2bT|E|WX11jNK{#lO~8_m8t3RIkg8^@UEPQ+$8iSK)<}Y4v)s3-_f(r; z@(f&`cJ$&jNKW5rTD_8jfv`mgO#dFOQc}zpA{ErNZp}#*^C<Og)ScfL_B;0z?PWDC za!`YYUn>V(;=0*ON4_qh*EwB#%qj#`pr{wmH>>27JA2a7RoH2zp2|ZUB-VTUre|+R znRwm-1frF70w~^!*LSY!9S#|n5I->u<Evn3{;FG=t?ltB$(jw3$Mpf$TZb`b3M{mR zvIR;?@JS2e#e}k4IuolW{xVg|f3Qx2zUpz7b!Ft2HP}|N0bPZ78ugn|?ISCS^OefR zjlLH@ed~xXP18A#D7tO=cF-Vr#wzZ8h%sg)^H}h8*Nxz<FF`#XxnGql4)m)sDGwh- z_=Nu46i6Ym70LQkPux>%o~|dkIF}{@W<V~WV|`zOhP-p1y!<6o@%&7SHiP#wj+A)M zMg^|3M6+2`)>PsGr%K89Ov|j$uUi-;7TVVrCV-1zd&$(iHUH$)h&3qYB+>l7j5WSg zh8$-MLltT<MB%!DsQUBd6p=4c7t_8``2b_;rC@{Hu_~tcnGQ`MlKSyEVOIeC?M2fn z%1}%wsrbVl)<+DMKs@gzl;j>$5D{j%^(tjve|Y5qNZlf+`tB50-^ZdWD0NKzzpVfN z*7yJIJY1Q;=uV6YloV}>?mRr7O3&CVl1zBD!fUl`Qr=01rrNi?vUk=&hv@rrwKz&y z_O~GrG}rLjsL}S^fdy~ID%z!-WwVOyL1NzWysBH>Z|o#Zz;5G)7$u63?$lT8$d&^h za(vQ}q^XB7%{C7-9kPO3UdC`>|9ra7Bc4F^bzQ>yw?+iQ92xqwxCj0a1Av|gDaVFp z6q?Ld**~a7>GD)+isFdAit$L$Zexr4aaqI)HJ#<(ZTl}y2YJtSQSiBWBF)9l*H|uz zW9>o(U>Ui01eC!$&_vVTt;0s=ygLidd90fOK~J8{+6iyW&*k!?Ojec*6wk=oaE3XQ zflfn6e2ef%=0+)cay}KBk_+w_`|Fe|_N>9CVNA$aP8~KA#~<Wc9%klXXgFT*PB_H^ z<s5@91)<(Vt9@!ha?MfaC+qsSpq`$>Vc63aTJ%adr(V&^(}l<2JJ2SncXxAhxZ2dk zE%J!#Y`Bb?l+qKq%UhlL94gPhDsi%(9y{$$h}-flaz;EzrRCa^h-GQ0&y)Hz`B1h; zBE4>un(oLd#&R~2XCd?~H9Rb3gL!GXP>SxNi)*0BeMPw+bLyUqE|zzLj0r*`$`X+e zGm7P0CrLY1N8TbS=bG%fY_WYg=1ZgCTI1EjyzEvT<nV8LN@umJur9DA{}las`5N8R zoRV*FV_G<^mB%tkP@vfG8k)D&`$&4Cm^5;zxVkJ4&XtaeMb?XLdleX4u3b%4xZUcc zaJwORXQl~Sp;4@o{~q&)@0BcF8cH=9{CSpoa7wVkP8$VLz--ndIx$j|fc1$!@^6Jf zf}mI{I~WWL+qIY2-q0DF)f%~N1?*oq1vZ#{Hr%H353?&vUVAQf?%5g#<ioJ8l}<GV z70DUxytVj9<u12vj@FY#dIxouoZL0U<qVLrZ?_D^m_MbqI&EwC>s0Hiz#Wp<MoV)K zSQ}=DYQ3A3G1u+=h>ql!s-c(@dovgJZMPYnQ9U+VnEr3v2I-HI+k`lRK(qhZnq<h% zOkQkdZ-d0Hm*Zc0bb<2C1!A<9<HJe-F;eJ9tupV9ErW4;eJc44JeY=Z&ZT)*U-R<| zaKY;~<=3VEL(E_D>YM<vcxaZrY0_|YJ{xJ)!SAA%5?|?^aJ>@&SIzVo#-{<}D*ha3 z>0%gJ1AWiegKGLB{G<OY==NU=wsdLWNX)b}l-ZcNKY1hhj(ihq>x~V-UeDuq!G6u# z;}k?GH*J;bwdjvM$vq5dU<S~?VSjzk8bv84ZUC<bNioOp2rbm={Qz^t2G7#(ghs*I zUO(b*F{|4gnS<6T{10bD7|!V1oVI2COP=lsSCzB*W}Q(EJrIbH`1iE@=`kCW4BeRt zfmZDAHR9GdmDsaR8oW5JVylvQ^2BR@b5e)>^$#O1y=p|!s<h>Jxw4(TeHhJ1@p~mo zL93)uory`uX)cGg;j+-dve>S!(?<Da#g)Qpb>6F^_PyG<Z7{B?Pi4#4K8+pLcNz)K zUHdnW5SOT*6bWBEF0|Rt_oLXDTV;sEnWG-43a~_+>@9V%#Oc0Ml-sO3(sy3Vt9bs* z=wNk-7qR?8jXkYtvk8|zdSkpo=e-_WSodM@rvoo*eHWqO^D9AoVT)09B+XpY0mJ4@ zQ)({Je!+#9Ja11bvm}453ZWncBZ-z$`r3T6RPyi|Qd}jB=s`{IJ-FGxxAIa`T{T#; zx)MwvhiPfQ3e{fkgimNpNMQPPIG1g7Amf_l;_vuOBb^GX<WY8RA=XyLbzFV>A{-;8 zMIt20&qv@EM;>B?%OMzd#IKV5b!cR_QX9Q?=xGZN^D$w*HCcn6MFSl@yOYNddkog) za$0z?S(8r7;hFEASHsLxQ5t#?lF$v$bsxh?gE3r5(pd@s%<!u#7XepZtwweS&$fjo z@X>3{d<%iwspV9!g@4!;ZNsW^ZD@of)VGlsCZvq?Y3G_Y&|u1uw5}=M*@;OBaYni{ zZ1o+1*CUFDZ#+lY2h!y5OJ09--di-zQAieX_~v@FnP~(c_!cnAp08P;Z=7?T-Pg^P z_)i8e``4uy?ie8J@=jo16?<zGL{ruQIi~(fGq{&MqFd2D$)bsoTH{-_d!cNkRR_a5 zLD&)mF4pxYnQWx}#GG5zYup?&Y<iNr?M#s|G4EqIn5UKwW}cJ)eVws((NTPEC}u;g z^at=Olkw}C@i?{lALwXF+uiFQw#bCJ(J%7e4i)eeJLIt4a63xYTXG!w5kMpK=GL{d zqabyzbDfZPp_2MbiVuAu;%x`3@c@h<p?y3J-mczeZ}2uOHK^*Ip6$r1;q}2Q)58R? zFZ&9|D}QBVG8fy9*6apJmD--hC4U~}SvIDRI0%~JwhemmwC2KCX@2ef*0Y#jlJr$_ z-=8cNut1k`Ef+F%d}_&2=0hZ-WnF;3&AZv!E|P!Wsfaz=CbSUn^|Y?PS?fxfIb+yH z!&GdY%60?2?X7UInhC`g_nSt-Z(VZ<RTXNw3s|)A!O5S|S1S5c*tb?*=ei-%u=i5v z@Iu_SXlk&vPG{D4>dq3%>IWE^viKEXaErX5*zs0MWuF1n&re+YwV6A9bN~-B#2&YL zXC0dc<6im-)mPz#N!|xjI$rj#aZ|DU%rRBcjR_C<tLLVF)7EX-a>oj3j8Ft(x@{V* zaGQSN#+I+pW`NS|E2*)w5l^I$pqguPW#FFb?sc<&yZ3UB4~Uau%b82;8n@1}^ZPe< z$iKF*KDx5l9mHFhMJyz$Q&^gb1uU)%+Whv6!-yX}l9fxRJX$e^U0cb@D&JzfynCJN z)r%MR0FDUTC0W7sSlx3a{Opq?jw)^Eeoxum5>tI-CI;kHMmKj_tPf42Un{wPMQ~fp zNp)f&&VV~dvjBiY#gvN@1{T!V?K)WE+R-O_%Fl8){ODZTqXU->4}@t>CuIBx`7`X& zSbAEdCHG0)?M;#8{UjjP45uNj+f>}8AmTIW!Qe;Ys|bGh@aH_nrYF6`G{ZErbUBhT z9vW4zOJ9Cu!y)l6jG&M(M*>ekfi2(Uj(4mOdC-v{IXFf1BaEdX%&#HwhAzF^LE0~? znEmIdeD!;)-Gco#Cu@{|Rz1&F*jw!G)`%eEf`NswaBe@;k^3pG;qmDr*KV&LC=$Lc zT`lpSJI7D)Fd?m&Q0uR~UP%MaFJ=$V#-}fg73K8Z4_>cKRF$v=?5_?fZPxCo01ONx zAap#PxYDqgJ6yKhPyZ_1?%@DeW#_bAt(1kORc0PTBjNTJh7j>|0Xk79SIS~JRqHGt zn)ui((&+tr@XLPDDNT><=>)m1jn}A-3g+TH7`QvqPn<r5C8UBKzG9ymDbaNtb^F6Q zTL*PqjAt}SVi?FveCi$%O4}XEdcNs+Xtxl<*l<~=V*K{QF%1_cEchR(pql$S@Yb>c zQH4onX^aZ+&{~%V(f}{(@up2STa49tT17_ZONMEyZ`pl&F28&IWG{Va2+`MRzN@3d zlq&aN!8j;Q{YSo#$@*1xH9)zMc&yH*gG3FFl@)3>J#{y&ucDy+^1|fSwXFu8-5i7X zk74|l?7Igenb7SaO~wbwMz>xr(^m?lJZ!pqy%jg#<LrPB+i~Z)e^=^pHJe=Qq{)ls zLR<Yy>iLdDmB`#EczgotR{aFquapaz1m$IJ_A?Js@d8|;3+52fi{a>X=&{;8$m(v1 zkJ}xRLgZ{ihGI;(btqsAohgGG(GsN0@TQ+JVo-(8m({e;=|~SC&dko5LE^`-75_N+ zNP@Jd3hPvEJe%xnh1c3x#Wa8mk4v5Tfn}<Xk=?G7Y+c!wYf(m{36q)Xk(+~tP;mky z?X1VKm*;c0N6{~>wfA;>i>*4bi&xSmG)A=%4RrFJz;nWTgK-;xDAnJz%_=uzN%e4O zj8+_Qce(w}9%ihhU27MIvHJ&@yyFdwae7$z?9^;Lvx-xvuI=A}Q8CUx?&eNdE6%PU z#X*qMSg<b;%ha{699gs^+ws@oqtW_z12=;=H#6o$?}{$g3o@tA;C5&gD)BB_@znDa zF7F^;u21XdB|nxtU^JuBQZaWeGTNusxA2G;d;BKYdNbe**~TrL-U~gkb0bnyo9H;t z>PQMm&#>A^$h?2vGFQv3vlFB1v4+Jv=bN9I`K<)EHzp!%n#oc}ke?qge(|b*EnmN( z?%9RJx336^vhr*;vx_Cs`OSXn_qz?L0{kllX-oVFNb^9elg%K+zuqih&_*NYse^XS z3a*-(>>469^}24Y>BI5u4Z6{)2WTUISi#v%8$f!Yjf*qj>(^Y%930-0Q9h>7oiAtm z6oMgdwi2OPD&kcEZgj>rck%|^S?Os@zs+=Qd#IP{AAy7ag0A#sv8@$?q!mc(jt_HP zx0ddR6~YWm%`MNn?(z8NwDou32x8WV8!Gp`>sIwE`sd)e3(dQ^mTS=SA(D~I_s!6( zvlkND@mUH@KO&c210N0mmDGtXz7opG79yKk*33_Eqdao@jVUet@oty-_$#u4<EiMt zL6=D)0ONtPWU<YKygygBM~W4Xs<=3g*_-*{c4_NVt}n_r(EWe>%kmtmi53RY-|oDh zzDRw)SB~oLgAM=J>}?b{u3NUNe>4b!2&~=_n3H^$X)#K6i3I!(Mq9vo%-8Z0r2rh% z2I^>$w863NopLvqSx)N4=8eJ?$71XXUi$?KbCs0c&E>q1m+Q(Zv$O;j2J#)x>g_X{ z0s_zFhS*AhJfqPu_sqLahS$ffs4ZKAipR<#S{S;|04rduI!#3(bLa?;)c#u~-9eH` zHp)NWP`PidH7)p95@RVB$uN#DIPFKdP0C`AA!(N|)II^M>@`vZ0U%Ci?ZqR?gSE~_ zLpdD@A%}t#)x*WZ;DYW+V5ZaxK+?9Pbz{;)Bg^xs+KY#3a^)(@2ub4{%uAT2Z;wvn z@t2f??Lp}$entxEQ$hM28C1$F-6J{iYuT!o1yD>%4V19=;4arV>xqGL;m?8D7!TN3 z7c>hi-tA)O8vN~xsN;TU#j(=aIR3xE(=Q-aa~a^CM@dHRhZk#Zm6J_Abz2scQqr&} zD|hG?lm;8$!3f_h809{eTx@o)(XxW9qW+P-dQNN6z;bi-?o@C$h@QYee;%;t?SB^4 ztoWcTT<-E3-f!6)rowyDF~K!V_20xeXbB&VKa1<nZy06Qxo95g)-W1%$BEA?eq8_? zg>8x2w8Pqdfi!Bj#%_xpw|C1~?T>##P(_tkiahlcc_3M`eeg2Vf||~1vau@H0))`f zQSoBk-nSFE)b_OO%cXI;7dv7FtF5B+QG6=pSi4C)@OD0;Nn^_z<xZK2MUw}gUl~yf z?gw3T2cS;=q|+yv=lK~NSC!?nx`$*F+V)?J(*_6??2Qb^OiQ?yqt8B34pfaEWeT`t zON4=~1VFb6Z4c!}y7C%CU(#KU2=dO=MPv?ppxpK4>kjiRwD`uytp1>%S8aA0=!{#< zb!|rfu>3_k{PDQcyjTV)^r8b(Rk-))N&t8vX(rN1nM=j7S_pXA5Dd*d;e1=~-OG&K z-rcs#ih+NI7W0m`qj-+A;LTy0KoDge6?wMbId;mPAh-Ho9sQ+OW)nbUfe1`LZRAaV zVEMQ~Y3L8#4l21v`n663WLtoNUsamgYjSD^Wy4nU9Z<o2wup#JQfDLo_HD0BUfHd2 z+55eGzMgA5WX>1HYIu*VezZ3dGuBo6KX>`9-s%q}r^jUFXIT36y;t~E#M&5zoR-N4 zjx&SapATM!C=sy=>UPCy*8Z{;!;yNvU$w99Z~rrv>6Jg+IlfMxzg53im&$4GLY=og zZ<Kl9Cru8T4E6Ey+;4B)fw`&esmNB0-S1D24kaQc?3Ec5|5+*<=)Lupac5lv_v4Jf z9aLGaVzYDJGQ___C@!Vyfr^X|ju64S9AzPVdGD#!#-f5LGxqD%6(!z&<x?wrLOl)q z(C1WtuRR?>raci9YK&djsrdbr!bOF@am6)#=@q&7^eJ-X3@8^wR3W;o85Jhp@L1=9 zY*XwLcac!pEFs*MPxV6<0_OX(49`rk^EGu4Y?ej^u4|U($VGjc&eF3I`s1zEuXwAt zVUndJQA_Q?H)Jk^$xHa|p$c1aX0P1o0PS}#r`EJ9cFdJ@87-z=OUv@-P#{r22M~fy zxmHH^+rve%`vY~hJ9xI)8Y%XaY@XPI4>R{`eMPraICPht-LEp;a=Vvi6`!6mCG07* z1IYoI%%CuYa2UI#^hB^Doj?Yvr+z-P(yvm%OFE{UhmL`Jpn;FF)0MmHmTix_zY6(q z-=6-M>#UeStm|B-NZ4>g6ecaGn^rq3Qy_jo_GO@cJ@kF8mnqH#M~J3Ol6@Uz_g}J} zBK8SqqNy#`ysu1=MoCK3Du*G<6MK=gZi(`hCN_ftu9NdOTxoM(x?@5mNYE!P0u!nk z#(tiT<W^h);%ZZ&LC>#Gm_ElIXc5>TQAz22eXptN@<U`@!&mIhD(!o!LgR_4zD<6F z`uXpNeZ26ha`4Osgrurg%3?loS-u=(Au*Avnwc^jtIo_*Zh9i?9gIUn;F>{zjthN9 z`{jj9g8m4Q92flXl(w1SsxZ2WkyEXTX8`x;mtUyp4c>MQDPEz+J|BMYiUU*6Ov}<^ z;73F|BnIG!6WsmUvtf!$Op8!i;ZKk-sMPTtNG41o@0xL@8rZKEpviLBE50--pmjm= z->cuQ&$fvu#kX}ybC7L*k>PMA^Q=dZu>UYy|0r)1ulQ|HU8WAG;YlGB;Z8RBhRJYF zS^1hm^QZm@y*1r7f$t^--YcIeGaTHNV*nNJv#|#vrTkXE+YUvBJF?ErSEXI^&OMXm za38)rRsIxvpmT5O*Ts-AINMSK;CMr#o1L(BGUBCl1n4V=)qQ4l+di$iFAme0nUSNC zeDcnXXsHB}`dy&3w3BUB*@N0i^}{Z7Wx4L34!rZuOC%Faw(v8Rd#ii%=#hZhH^I7w z7do>8c?@lQ3@U1fZ)6O5A9bd38;KFMd@mhL@BAR#SfxpCQzg7XoJAwDOT<`X67GIc znmsl<A@<`8Q1CRer?S(p8&v;BtlD#D>8XCggPwSKW}3PHfr0KKs%WO}n^_IaRI%P> zU3$5BHoxxxVT*iH@NzDLaWB!gM{`kE&9`PMaG&D!m;>zbJ{9LsXCgjh_tC_efGe#o z{U(jbNb79A-hnWpHbe{OWdMSE&Y3{TKj;pRuaF=UC|!FRv2IZDlP%QY1l?^<dPuez z<gl^wO}zi7Z-|qRP=S8e(_6M<HTj%l-o3&Fvp;RWEpaPX+EZ@9|CT1b0~>&BGqzIu z)0^n}&9uZnP{B%!9kT8z8Y#K8Q6{4!cX0S6=k)U}@_<+&`VLIx@a$=}46Et9U2Q z{qSop^G>_UeS0$ZaYy&ua~X?ywQ_C^8@6&K+!)B>l5<IowXYov;VoUuC~3&`x*Slh z#by1IpF=gDbR<K*@szR)L<-TnuBd?k%`@Vfn@3k$QaBK|wfc2TxDyrZih4zbf=Zq? zDUf5JFx=Fq5`|~GBjb-HjagVq42lY5YHm^Gm8QYW1vlc?M}n*Rl?8am%`##-r~zy) z+npzliuZ0{a`??yBi}b8Ro-e5qdf0n2ttW;(;4IOY`6I_Rk6))BW}oM2ktabAdz0i z?Fz&50dxHH_cFS~mHQPB{6n`1rD;fhp1wKRCgK4EJ&*4-UyEoFZGO~(SzC2u+@sOr z+BOM>n5QcL8t)4`+-atCeGgTQT$r`_wMtqH7maQCVhulXPZ(A6DO?H=H8zD42S@$8 zFQ>$Wowgs?-+)xirU+@(+NmZTiaSzo=3qgbVjSql<?EE6VZx5ciZ`xrMj1+O2`Gi} zsYWD~RNshI87S74u~&DRxPvR(+IU|9kH@zX9Z-<?YW4jQr7WmyI%$~t<Cib_r5cTW z%!{me2wh+Fc+f_pre|0E{#n>&R+q3z%KaD)@~u8Oe=J7BH<&6D^Mq|14U2mT-+VwK ztmC6#Pvnx7CEG!cRk(?K17~;5VrPs8I;fWS5KFselX?#i(s5N7k%}Ly_`xQ)n8G|q z-yQj}Xi1@AvmyMWuk*lG=Xi#E!`D}Pf7yB6Pk6ffAtV79{Pq0&C;z1!GTA;2ZK%be zEtXj$W^2etxu4Uz+x$TM+X>hC{L!UjO6`T2y>`O}1z2gPS=_eJMpgIZw)>Ap3({=$ z>{l}$GRVA-frrTP*}l2!ACJh%g#@-QBaX&@UZ9~d*Dp=zi7zU*CDWJxzB~IRCTGU; zl8EO5y?9ePC2Jneij+DYp?E|4L1_JA#)Nf@e%G4-?op)25*Bn!^}9&^5I1lZ8CWMd zL8r5`#B;*@{@g92&FB1PCND~jLQaxty+kWDBXZsFz=NsbseGR+>4p5~bK(y;(Z`ft zm$}&VdZ%!_OYNc?;?J^GiJ@qkw;lz*QXagg*Exl&FFHJxAQ(ovIv#rmo(D7e-K7P; zvYv^pbV}Su_iD1FGA;jYG@c)MLr-qyv8`Hi7-y@kh89+&)3LaWn3QY7-Xc1R`dQoj z4mb8-@AZyhv~W)@!sA%}$EzuhUt`wdO>a+nyN={*ALQ49SmWjHqIHa!eM4-mZw+($ za9E^$r*Vhbc^N{|IY^jY+(wlqtpy`M(z+);_#jc>)G`p3;_vE@&%d=t8!6~0bMLP^ z2Z!K|>w4pQk%Q*Sn6Ct@>wNOgpev#O-Id@tJ&jX?cUfw_@5Jp*d2n*+n4jdR;@B~5 z6Pk3SV7+p2WY8f)kBAn|S&dJ>ChL7wnNuArSNe8j$rxiN`?SG?{TlrjQ5MeZWtD6X zCyyh+h>ktkrv!H>?IK2B-l}lOx-F=hbk0F)Cn^2n(XnPvJ~z^0-k_t=*6WgIO;cdK zm+0%!`d!+WyMHkkUI{K7{e3_`jZPnZ(tXEAOtoX=1=@4F;8CMU?yJA&O}#HlCFgOe zhcDjMDAJMd@P9T8TPM2v>-?^(N2Pc<s@FOcU!*oSwP62qp=6W#Q@2~`%O*bVWNRhr zulkFsNlzSpd^uuAhdn%FTEES@gN_ND_R<*c)qERv(<Sm%D&xK5o!Lzfe2)}$HpvDG z`xHfq1LErGDcXxK?<D8i8RXhxFQ|TAs%ZaKTmFB(a!IY7C01vPqI3BV<h10qk`t=8 z_DF(gwZJ+pVJ{bjN(Rnn>9ZA`3vR<34sOKEC*fbeq}?-h>?B(9*S&Cz*r?gqWs;Ho zL{wT4<+~Z}Pj=MIzz|7`>OAus!N;IdLE-)7!<okWjt$JaGl`5`RQ?Dnrrlw6X_|=; zSJaI2so&90QQ6gDD5Xt)HgK?0%4|+loM#qz7Sa+k72~?HI&syE6-R<8d2RnPpEw;~ z&ZpGx&57`4fPNevvJ;DFg*J^$l5JvXn#fSeS|C{Cp_8}^leO0Ky{h@qgWQQAp`*`K zaA{pPVK?<yd$0M%NyD@UqjwLCDP-;Z4IQyTkO9Uek8t5v#-8Ex5n`tGaJmNBPGRA2 z?BJWLkG=SX&kUbI#6R3K=~(?MbHDb`f4)xi)rSpn)}_*u9-3q=ZLZ%qGiv{tY11Gs ziDuqfvX0eB(PvA}KUTMLa*MGL@6)oPunWnJ7gf=B-9%Qo%wP}Xb_6UELn3{>l;1pS zS&m-qFJi0+3$=W6r{XOTcu!4VLW^RHZmSNRLh-`&aBb{FmZe~Ufpk~R4&j`rQj6g} z8q$;lUAoFx{|7h%Pf970Np8-@K*?24{o)`vkZry?71sqGTB8KgiTb$oA2eLTlOovC zI`S*F8o1f77Fg|#M)7Q=jDl4_S<JK2c_STb03A)^Ja^L2kxQf>j=M$2xU_@_U~9al zz%5Pl;@a6E{X@`?=F~gpZ1{cxpQzozn>%uti#ibov66RG)LK@dtRu}C?kd#|Vzyq? z?MOTq*5kbfNy!*7v%0f(fH%oDi#>72&*xsV+=uNMRo;z3Dbq8=*ZFSPJxN;hOFNOF z7`o)u_MsylMqqTslnMrSAJkhZX2(sMKp6<l0$fp^%vxn1(rfn@UF}W|juZ#Et9DTw z1<!s_tu3_Fz`7<zsyosJ%OfOAlHY`a%x%ZxQ*qJS6<&w0dRg!+tM2<XgbJGAo|36A zx9LRoOP(iJz1Vbj`etN+NWOjiOK(^1ZT;=#mvS1l_W8BvHm)ag8Oq-*_o%=nLGHcY zbnCZrAAG+nR--baGC8sEfi^rJ&sIT1@O;+&{W`AQ0{tZ;#(I^c8^oTz7Hqe#D38Xr zPGV7=_@j7gY|?Jq_D}@$Ia=+WpE3IFG4fO`C180ymh+bx$k-*?+FxjhKD!)$?IMQe z$aY?T`Ks`t>Z!w}@7-W=`BupU7L4KB&>4Cx58@NZ=C8*4h2PBIM9Jy^!xdjHCbO&Y zII8wNKTF9;f8?OBj9vBP=uk`Z`1DSmIrOvJ79V*xMvtOK15=$OmZseOervcj@0D$g z(ofryZyo*YUb5Ok9@Ptw_JXe?i;KN_V!b*+IBlJYOj~=PjVHUg@xDJ<x*8+H09$i6 zx)^z{G@04iz^HvO*{g53D06?=<<-4fTAl-QTFcPDFhUQJd)@`dG4M;QjVyfXg++XG zh)p6HL0F8V0p%0_9Edbc8rZh9lW?=;n7%mluS$4rOn2UJxkgB7*~X2Il`)0tB-l7j z423woHM|^nlVsAmEuc3m&&dzeE4&|cYdh46?LU#ff_&$&{a7@?QoHjKA`X2iswv@g zC|0%c<F^m4ki&8omNBMLPk|7Idb0ylO8Qi3#*xsD8${h+KKVMAJ4!gSYyPG~PC`1# z)`Xvq;zD}l(cX-5+v~7PysS2j0*i8X?x}*UO7k7pdZ&hRrxZcbqY=&Sx~-f<a7L2$ zo!v{|?|JV>rUytgua!14zz|uo(x5ZUjrVdpIhf+Yb>sqfOqE=KeX4+Gsuvexl|Ety z`m~t9NFawkaWcB!jR-A%E`x?J9;W8kw}Gt-bo8G~5&D+A`M^5D^|U80%<oe5K4BuW z9-nbL1`08dC?}{K^I-Z|myCPb3?t}}T3@JN>2T!~5$|#?|E@>FrR=cSqbF9v)(PuV zVmemNh)+oqTZSilQ5+a(G-})Q#>h0pvxXQo!vSDS<-%@9H~vH0rP0V#Dszq@(G}cL z3F(~@@r0YSx^pRMZ1VmqdcZ~cHYje}KY(0UnVy&NL&mO@kSk67u8I_d7p<SaO`S(v zWXvOS8N@|sdD>|2AU*Ln1Awa-ub)*#0L%mJqr#gcKergT|NJPUX4x9V=2e!NOj;P= z;*bFlK*;HErE;toXP2;Uac{2d#z>Vv4pt)MSs(C5s}6UA<_*&6!V4Bdq9k?QGb|=1 zwJx@2Zmqa1a8h3Uwu?VrsaP}xo4e<18sP04Te+O4Ri>ZW4Ks4AOF9?ER4Hy$7Qu~q zZIXjb`;rF?t?EyVPqu#%DR*d;7%Nw8|HNNNfagcFhEOMtMM@mcV4bWPT$)?<CJOe# z9t0u_(cjY=o&zilUmg09Kmw%m78O<ab049w{x1Udi_fbz%EzCFw6Bkr<cSd2Ti5P< zDm5EyT`$`BTO_mDaCz}=*19E-)VOOJb&e5DbO6-PDDa4%^Qf7nqijUq)yVl|AujJl z1$=~?Qrx9f_-DD>iCxwHfKndBanfNV9tI{s3W-s#<^>y0Ldpm?%(J-=V<dvczbSG! zFx5W@=()^L*cdD8*08N}If!Ia%T&lxNq&xLnhDneCAf&;JRNc!m&0{7p1S?Wp+>0r z`RT##A2n6&HX)GVZT^Uj|C?BWSz0&nd8))D%*5Cj2KOUGkg&~QLZN^!6(^6)2AZoE z+O+=|hKU=8>_BPeA2%LsO&dH7p?V)v<G5uNa_~j`H+RiC??+t{DC(6I)<j;#l)2@! z!-(EhvQmMCz_w{l$aL!=fvK;rFR$4Evwd{?RGn*{;lUxj_|rDmzOq4~oyA0J7@V1q zf&1CV#7tZwI*>YD!A-S_0&LjiJn_cSh7*_((rTY4J5I5Epv@U67o2iRFQXM%#6pEZ z<Cs-S_OZ!z-<ZoHPr3{exWKGN_fXMIp_13-TA^|+P*h~IS?n;ilmlTU=wYCZZ>Po( zPN(EE)>`YcrTIBp>s(Sc%>7w`Q(E`d{Nf_)+}}auniU$jDW2oYQupUtLrQRX`kyG} z*Poh~JSg6o+vv!3XjWt<W8jv%Krcz^tQ}2zOkcG)XMZEO-9tf`m5QuJFYtI2!G<0u z#qhgS6Ha7>jeNRgSt#`mbEml_J;n7y6rvw;`JaP|9wc0`N$vIx$J9S;g^KAT#Xaq7 zmw;{_KS>ZYj`7s8)t6k~)KWD?Y!sHW&=sc>#V!)`i_K%Z3HPeO*gtiK4F|FRj5b_V zXXInSGa0iArH!|ld%wj`=A(w&V-&=|#tt^dM_|1v;^VNKmLT$fNnFm+Up~atUZhaB zsRe$+!sx`S{~Apb<_!ikI?xHzR`!~GkwOupNS;5C)Gd1F3p!)$;mZ=@tzX^!%eV(f z#N<H$1_@^!3$dGN^wQuM2OBpxw`{tm5;iMQIgc^$pm^1_B1|?${k%)X({L<z9+P<h zKPtI~uGHCyv=#C3$Et{b@!n&j{UfV0FHPQRtB|YchxPk|v{C6A58ssY-)PT3;j>6l zqrF$Igg_H#=v=y&<X7yHa|UlMBd#}9oCqP_+@Vc;BA@r?iR$C#m3^!X+fZMwsgXh- zA*Wjy_tbF!Uf<oT0@{V!E5FhMpi!(Xc)Nn}h%nv!N;I6O8=mz2KX4)2CGKZL3J2z| zm9yWO24FF!i?aMz#6Dx<k{oNlm>oG-m$Sb-`~+5EVR6_T3dNOu>WC?aG<U}=X~ysy z%y*E=Y{giS6UNqDNWdgI6CZ#AqfsbiMgWsGfY7hm58vEf4zV=agip=`mqzKzwb9g% z%G9%4*j?L-iJNj$)ySJP4aJ$kxtgLiCQ!iOQCk{-aago>da8K8$djI=Jv6{U&vJLv zFN;(i%|`G#EJ_O_mQ6s2o81WT+i4+1Xv1|=U_ujYjD1a_Jj^BW)k<vc1dB6%xzf~6 z+Txi#u1Nb<w&6O2u!%#ov9ij1iqMz4z>)CTe)UfUHADYH>Jz|%r%4M5>f^>=_lMBs za-8dvbRCJ8d4ICqlPu82iM37+DM^EiqW0>i7@K$7;yO^B=pTCNfoPE>*^{<Hjbf+g zj?So7W8P)Wkc9wM7ll2Y(~hmnEivcw!Np?a_#<GbPyw+*TBZRU^e_~}<8KMi;mgx^ z?!T}67{ojG3-L2UF^Q%EgBCR3;e$h(stxfM0T+V5FSeK#%mX;O%abJ)r_g!4mYXAy z6*h53e@<W8sf=<8=QYFv8~aE;0~dyZa#aKG2G4dOYLkI`I0$#)AShF|0ZF>oJM**b zd506dC!%ye{Q-&&CEb1I<~QFx`Np9}w~7I}JhmB`qyfL)w5enE!X#C=GZD|$pNxU< z<`aL8RF19lRK!}OnPQ9W>@A2*jge2~n`xv+qj^RbUmoJXoF*Dyb(~oo=D}rBI$<2T z3$j3Iq+8H7aa$>D8l8%wySY=8AGGUit$znyv~k7CVQJ?AlVPQn9XSetk^-0JD@(rH zCous{cKX*t(U5OBb3f?cm!~;e9CR9Uh!kA}&;4j|a{G8mu;6lG9w07{bR|;Hl}rcj zic7KR!tV@5LkTiU(8qmd6(PbeYu8H(GQ^;{d+`hN7Z$?)G$7$0p_&pabf^iZrY2wb zXr)bviZdP7H|jc-y|Kpo^gYB?+k~z)_HYn9$=&ZQ>7rWHxai7P!ui+1gQ7aKj<z;q zcX+}cW}qr<upyOtwbBzm7ep6+sW!w^DG4adQVos`yX5VgmS|IroHfyq(x*?~i7(fh zZ-NKGCU0p3?H`v+vJ0AjZVwMyKb8I0agybg(Uq%~s^q%LkTrI7Qlq3FoaO7SX^obi zoJFe~x*sWdy*bKMDBxy{qT`FX`P5&g6h(`o_<Q47hTgs6OJ?5P21c&yUdoq!=HY{O zOAL(TAL6k<;xmU+yGkjA@~CW|UjLppR#ul!yrhyw8y)X#nLP8>WJEE1t0@{=h_pSz z(;A8jS6{>O7{^TlP4&U;wf%>J?}H4=b><%bK7Y_l12W66%zKF>JI+oL7h<zC6|*=b zVyNj1SagUU$5MaNWr8n;MvbJ@806DAc|8VYTW48w_p(v_)bW0Otd(G>-?ssY)wxZM zDNEiQ-}VFY@$oym8vv3O>fggZblF=ML@8})G3N2av(IH-ux1$<cj@p*u<}h&voLK| zs`PA3y=2$?Fv9ZfaK3;1v3f!NA(euOk5J`xy?cO0NI)u*<5#LSw_ZUKi-(hq@0A;6 za}cvTRBO9i@RF##EY5(LE0O=Pe9d6gWx4DAa@^0;g@@sr;0$Bc!&HR#+0N=K<v;n~ zrZ;8()kp0=`N<3PY3hSu59IvVg(qti!>nk(IdruetFGrhdG*SMYxcSDm!mNc0e0s> zeAfR2tP!2iEWLZM^PUSF<*hKKVL{V>qt}1&b|-%8F)2e&JWNXYOnz5q7NcGu64~g( z23^O0{53t5d}pd=UlGrEs;99K#;TV!XH?_M%GDDGELFsTWc)|qbt*p|VQRW&weEiC zR+25H1fmZ|MP^xc=_KlEspiwJ(sx5H@dEIO`R*hR=Mu>*(fg3b!F>@f57b&_v<s-6 z#yE?oRlMD=S2nr`{DUI|Vwciom4MQj7;Y%0KZJgvI|>8m)p|l&nAGc43RWzY3?TZe z*)Xp)90D7Ww)LDl8&c%e%MLi<Js@hV?&F49;oIa4TSa3aox9;e-)xLUQ{QcY-%QJ} zuGUEt9)AWCblz_j7+A`^^SdATv!weX?{;gqyEf^6KaomcY-Y$V#cwVP%d97IEyTFt z*?i=kbwpv&>p}TZ*E}kf>RErsT@(M&9_ZK;Q$cUVgRv5&mioWM00@8UtZY2^HCsCn zx4H4V=^ttn1K962VhtC*cgD<jN?yn%ICjTiQnHxTEG9*ZKP9A;QkfmI-`x{F7b@I| zp#!nO#S!pg(Z))g4~06zf3V4hU-mY;c?*C<EQ__ATE`hGuGoF6KXNFuet*q2Z5|<_ zZ$9$<U1*?w>q!)lB`N83Ok~QgQ`)vU>DX=&!<Dc!Q8ImAV7qm3ERh;`$p7@rjeQIh z7e@Z_oXJum*HXm=3j-1#7T!z)ITHnc^<b5F)3pj(romW~8y|J}I&?JDcoXTlgp>K0 zvy^03{$|Ds|3Kr}uCQd{=ik*^x9!)hMu>z-@$O63cujcpa`{x=y7x~!CR^=O8E-I5 z<WnBSycKkNw3ZJ#CNdmNr>A<$r(!NcKQF!e<&N#{Le6|lmUTtBn)BDVA3=*++_GxU z{WM)`Hz1M>&97-d3<vIpp_U3IU|B$iXYoK`s&i2Tu9Ne0Z0y6wd4wgio=To&sA6zR zSOx!8KIKFY$)<`v{~)c44F#qMQwvaHu<H5Y!fV;`Y_|!8Q*7x-np4J=l`}c^L3(n& zd-|zARyZpNQ;{z+40ALEbTWb#gu`+)4vVspA#EBQXToYHRO!Ngp{A*P#7jj0@JUeY zo=`tiVpKTPr}A&|nT=Am+ubN+7Cw*edd4pQ4@8xz%7Jt6g4VtMeUT8TCelYpHVEp6 zvG(|}otx3gegWuJbV=TZy57Sab-nQWC>>+cBm6T8qyXfYfFb|gzh-ZC2ujW#kCpgP zgay*LhG$DE^AGZVUZ*z8IP1{CWbYQ{W-p@xe%*ftvU<Bs(eVQdyV-XA%4!Q8f)a7Q zU5*Lq7(Z|eR9j*ZW&s=oQSMlf7fG1tk;_&=9ur}MXL8s&H49oD$S-k8jvATs-6zr_ z$uI*ukzv9c)glA+ua)i9S1?a5?)JkaB=wX)G>K9AdxQx?(;SktBAf-{jt!Vx9404s zm74=OIz%-}t!iN<W*2#3Ji3Q<M-HS~8udUGrw&vk7?wV4v0{MLxK>bc%4O$?Fbkhf ztMd6vm;vu=?mEK&v7<u~?Q-J^XAm7g!bK2SJ}uUhY%w3aSaY<`Kqs=%SXL18)}Swl zlD*J~ZTXHBbxjw<4<^m&27k<hFbb>M25!pA9=XThr3r8!f_eg9ue~43mHM72thsCK zp#sV+jp>z7<#;idc-piJd?;Q}8It;;nPU!o%tobu{x$>Oxxl=Tx@hKSk7NU`?v>N^ zk2fpk8+%oqTBv(^FvrEJ+oeeZl5+5WN>-#dZIM*BLvMD^fz-LdRT<C;r0TN77*u*A z=wm*l4BT(tSxghd9P2$gJllRYYyZ8uKd(XOS#8z(!M%CG4)oQ+vi?CJWE1hJeB8?O zWHj<WVJ<mszCn7_I$SH00<iaAFX{gGJC`fJ_W%A!mYEGadPB9HFm?X2wvUMRy?Xv8 z7xN(mMwZ{*+3J9NmXfe8N^;(^GnYucmbg^0r=9|;UXXB3-NcxXHFPs@*}<|icEH2P zjyB|}Ch+(t;@~bfj%rWlNsw;rsWZmnwa;$v%aUC^EW^srFUwuxOul;010i=sbAfcX zTz<n}^~T*<nuvADfZ#;))I|ADH>7n5Fx?(2G=HbcyJ$XtawA7Q&J%qm?&yO_X+v}s zbfO<en<|(kyk&o@eVN>@7Z;R^j%%MTAf=ReVKnqv$`fwsH+4B5k2M&+B|XvIJ7)c3 z?Co&jC3xi-snFFGc&Y<$AL;|npXZ-S4jXrktWWKESkJLTDeNL>r&fm^leT7ft!c&d zOscq(qDr$JE^Z~H$(VT#-e1C<zAM}iG<kQDqY%kqQ(qd8a1TUg;chMjnInddy7vca zy|QKF(Kfwb3Zy5*c>+rD(ARYjFP~#`)*J;OESWH#&7R=6a(@(ENn%z^?^Azp$2PvW z`V~5}`Bi=DU!G&<Y;0z^Od;(<v!BZVVGy~ywyMn7J7LOhBddWgTI!4ZHMoRuRjvSC zoSyRoPekwc-f><gVyVGT^FL&DMda2ke~-@6GbFOwo$_9pbXf_4W-$#e7v_%1ZGYr@ z&eB;LGz$la@CwyxvQB5@GEL4nUaCBQ*ngPDWuvGwD_~JnF&M)mJ<&z~*E@cKuO0A2 z<#xFnSm!>+a)@b-3djPf2BKoze11~@@2;W|znl+?55yyijz*WPX7F75>Jc%A3@V9Q z^mI(TGrDKWPmNU6N|7@<z$w9|;13>F0*o6C*wU2pn@v{8jhIwF*E8K3DT_V0;JMpx zl~v^hM{X!)Bl;w|udlFf$RzOzqrBasUf$1QgGp|?^pr{#g>FXm++hLsva<WgYwckj znSFkDlH68=TJ`X5()$mTE!ct+rjA{R=wSwxs0uz|#$Uy;-DZKq3*LSk)}H%BpnvE$ z1{4)4x2AcJdW)PQ1knR!u~i277W|=)sLk%@fp?8R*$9}Ll=}@O%GWe4OS?o)i2?_? zqeb3jq=+W#sGb>PGRIaCqKs&V+EB#;#2X4)Uvb(D2mirL(~L<h@5Hp^2>5;q4_CuQ zgx*uzu>!57FtxD<n4Czq+S*?f++WwpPa%#$E`)!~d%gO>#wUNr3u8h>88cc`>!fBe zB`gl@F?QzAd5vq$mX+3n6HI)iRHM3D#xcoi*?V5~Jt%unD_wkJU*pG#*9OAUSItba z@Mh<tn?13jyqKNUmyOX;{VOKF)U|#hx*Jc9XQ5)){o@g1?{w0|+}mT`W?@00;rzD+ z=PEj*`-wrZaifFyreExhYc)ltaj<@Y1tFU=pg%=92a(R1ro2n_2PVK-?ePMax4-J3 zbS=B50&|FswCq<caxtJq&I0-2Bio5gE5W(Z-oQ@gUD}4^tlcCg%!LOmm5s(uzRo~~ zV1eK3G=BJN8HkP)^glb~=VagxIA&qJdcaqyEmqLInHtXKv7%|J*xwJ&xT=s_6rbJR zmGd7Q(S6w=q)IwF4qb{7jKkC<XXtjS1;#xJiyzmWFrKVtAAN(x$YhpVxa7@eK{cm_ zJ9kr<VsiJ?iOp<Plj^G$zFJ#3gSr9aOYN@apSZEMQMl|Ox-IWF*~bhy|G92unsbe> zi~t%Sik+9mUf`LM)f@M;>?f?2c{C@_z*|0)7(L3#{tl0>lF?(#u%Cm_qcu8$JpP~Q zWxTw-enL|d%fIy<YRkai?v)9+c?4UGx|hzUO!rlDDRi+040pEIVko3XR*3z=WFNy} zd>Vh^)^n+b%k#^EBTe&yIf2h&Z8a*P<reu5m0eB#sP!J@T+CatmVTJFi0aic7GwH) z<r~@NT-6{M>G`MQGOavm@@vY~Gc_R?htkptv@MZ3xt0gXCY)@p6J!OX;T}JkyPo{& zh=d|l@*9t$d^i_eJg^T#QuWaNoLV^2U87ugxF#YvzVykiWOrPI=6rlz#^CH02k*zU zxcf>p=&>rhDdEYy4b{xvX!86db4&Sj#-$GYD}8L1F6d@Ya~bNi>ldcn-Ot+qsaxeR zo|vOd>sWW(w8Z@y#u4L%h`_ax-!(|CsFbcE>CI2pN6)q-7oW{~Zza@a>~%UI<(x#C zPiDJA+MGq4j|*5XFMG<$OFSfB*SkHgw*SU%mx8gGkQP0cZd%?-Yl0PLmzPAvY^jzJ z<WtjJ)(z;w?11M51RMy<Sf91rKpefHFGzmv;{qBrl9l5cvC-1^4Qw%aX(J~Kvx!j6 zmq;gj4l0x}Qrmzo;g1Za-jU-rOOV>0T$lCiD5^qhq4>(8q6{y+=rhcgbWc{#Q(onn z_tUhU5z$0ux@Wa(?zLgBh6$9-Is=FG4<FCDPPvs9E7PaPg8Ym}A^J>hf~%~8`e!<7 zceLetB6fc|D~^iWy1ZjAo^VjhN3UAcq~^+W!RR-S`&j6Hid$<d6))roJ+l)@eWUo! z5>5;D8p+|&L(;MN=Zlu78tC$!3~O{wsC!YYTGCc$W2(LOR!Lh)S1zNN4aUOpRkO6E zc-Z#!d^fJhvpBVlmtl+U^)lQICSL0k_I>Q&vZfEC<=KC7gJfjd<k2>(aQ&)F)uW1e z^3~qpGgvvDDJSsDdj9ytZF1RWTji<i3#q2u20lr@cEgHj)tecvVuWsac2QYZcN|fh z1VadQwD_y{)t6rZn+maX=bt*G1o@)~^S}cD#vqOL=(nl`F=lsC1o>w(&dNrkSN0Zs zHT6LNWo~UAsOz#sLg{w!dSEZ9C-c6Tr0$ZdUEsBZwDhQ>m9%%@L83-nXQKol%-r@# zS;uJYsOA^=PazJf4Z`+H(4%`Sq8w=90nmP3@Cj($_veWx@$(3wp6Ec+<V_&zQg-tm z<+9a|taaqk;58rm`Q`a2?N3!?{sB@_lF<5U&V2WUuAK<IwW3_9$`L@bd&0)Q6F5e- z+Y(+mVV2>5ailL*U8&JZ2|jbld%bMUocTI0SQhAO$1ny8H3sdYw5##|j<@vxTE;7q zf{!_{4&Z8n8qA}NNJJ_fV92u>R*J}=F{t_RSmbMU_D$8JHCvZj`hFOtc&{%8H=bka zw}{)*3+gNNwc7tY1vNdfCwumRGS7w(yskT9`VT)k<z;L25wxO5ifsb3HA(D~74B_x zYg!nVR4$Stqcr8;DVx&@O<4mx3CY6X31YXDG+(JB8(Vr*jo{&)IOhJB(XA);4Yz$t zsxvbYE=hC+VS9IA9ENk*m>tuuAuAuM;rn#1IME!nfWu*a@$DppX=kmrtyH76)sP`n zu!7T%@SM}xzCJujg(Zs&FQaX_=oE7<%?4(B)bgkb=P<Lp;AE4l^)q|*Ig?fLc*@}F zkN6{29?@d8tr~){P!ExJE?1PtuPFEM0m_0Rhkvg3Uw&Qwnyx;O0kYBeHaiohg-9B@ zU7y3>uh-tWf>2N*n@0o#!C_72v4YJ!0@VBqOcw=1n^pJd24R$<TRz}idGla3FApyY zRYA*>nR#bs+Xd7qSOWCHLw2GhT~ng@8*G`8@kgJ5t=N$THXuZ0Di<5neGjc&_aB{N z&a_$e!X!0L_@8lF)VknMlOO!EsfFH{q|pA5Daz;c>0!W`lX8<4{V#e?0X?q4CU41S zQ=llv6bO!g#Srsa2vGfAsfA&c2*awj1m-=u<%qds&%O9#M3$X<RMG6X`@m8rb}`~~ zEweQinAdq#PJQwq@L>GPx<<QTQYGXD&dO8B%DU`;?hHrH2uuwxDRr>r&tHI(6CXk$ z|5s<<9Z%)|{(l=$p`;`$6iGsnJtHHtNa7d`BYW?4ibQ4aovdVK@2Heb2;mqRaqNu9 z{9U)+@6Y%B`F_5?@8kFQoqy_aoO7Soec!M98qe!_J+J((5gF#BjX`qO;q*Qni_cbX zNK$5>Ab&ypa{o!!?>j@wzgmvQ#{r47`}XI1>tYwW<)~|SU&sc}{%8t6N*;Y=UMDtg zwW|GS!`l9BaTZ_7xsp?%z3XCnT;q8B)UZA~y|YoH&pPg|nT4+q^V;gV&1X^BJp$4T zV{=Liqt<*OcO`dSZp1mz-Bn~ubX%ZM|NZ(62$cN(YBKpnjZ`@+&5>+4EH$`v3Q^58 zFEY{JF0&Xazad9%YGrocd1RX3&f{Z{-8hq%x!LxyG2M~Gu#D+xU^(1Zp}C>IdB+pV z4#=$+B-|7Pp;0>g&qmG_-|wZr7i@o$y-xUwAu$h)-ikjE&_)}1mr5_Q1$BP1T%NiZ zG1q;cse>g(LO;2|T6ctM>N7-bwFftqCP_GN=SFkxx+J%Ht|@D1NC2Y8Wi2Ktjn*K{ zpj3gwMhVqJo0!zhTGbR^e^LI!i;oW-P2g_Olx&W;FX%d4w!BfUnZau36>ZRLSs^R_ z1@}6qw^<InsH#sXG)kt}gjtLfw?-%)w#+5Z9Qs`r!!-!(txFiTik-!@Y#H1xk)&dG zdqu`A^^4ZNn`XO0(D(h&Tr_bQcQao#q=a*-@vLC+CH_hKt)lF7?QFh@%IwWpI%x*9 zgn_EgD2Pkz_MfINQ<sQaPvi)|#SN;vISPZqLFN=!avaxS1baI#W_WyNA%d=aRq{$` z)Q#^!hx8MW%n$Q@Y`4lEBz)ppHf{?~IMNWS{u^&UZI4EIHau!CRB5lD=_>A{+I+V| znx-B72v(Sr8)-IQU7%hQ=UHS~ezL{E>={Y*zphXxm6m|cnBr7`>lkIMU+!q{`!DDZ zNYk*_W!Y@WJQ4k@4TnbRY0%oy|AX#R%zfr-A{63pgyga7mp@@8@wX7K`o_;oL>Z^f z(`%4N1X0oe#4aGsP<<Yk@Dv|3I%V1GVfC+i6w8r!QvRIuEO`#T<$&81LbYC&Zfx7( zY7WguUm<HqUm;n7uj}Ifs8jqyh|0N{(joIA{SZg!#jW+d^F41EEfuL{oE2RHwJJ4c zOxi4`!w!|DiW>D#t7?l#>jE(k$Uq7wDfIjGFiO8-6Ir)bFXF%CZSP$@Q~%z)`o!2j zxj1?9e^v!85u;{4Tc_DEeI23bqZn&qz|wcr`_^aGjcWoH1NVdAA}!HCDPL>W)y<RE zcBqNh@)k|(s<KIwgi&y7%x=mmt&p<YD*c6ZaWTaV<z$|%quUQrUVq3i#7ttToriiR z3x@*@C+2gF@Z}b+%NfRY9zAQzA2{>TEoX=4cW&h4*~OgX(lg!vnpZhHH}QIXB#_HO zF7|p_Fs%uscg;)MC@j->Gu?4g+I?kN=-5DjA6`2lT!qnUlBlV1Sm5^sDjEmwxRyjT z?vlDyjTe@KU}5#M{A^nk97l01sl4mh7*K<op^i{kPc<fOx#5)DdeFCG`*97geW&yC zc(7zMw!1cJ?)IbfwUb%5CqsmJ#gC0u2SfctCi%i84Az-)Oz}*8WDr0-UFr|}T5OLx zMvc=uhtn8ODs;#5gefI2vUMmoMaUZTT}FFgmPmBQq`y#Um42DZX%v)~Vm<rRs0o6( z+Y3?UT?}|PVegurHM^FeWY(<+#;_r~+=L;w=U3ir`3QGaJq%cp&>3rf8YSd%jLVh{ zHuYb3SUUN*g73|bs^LX$2B9I8G&2f)Ex%`3YwwnQ&HtI&GuhRm$8*Sb8160;@N8%( zW_s!^B9Ee2j!-l+TvJNYd_`m6Y%Zh*E-w@Z7P@>|FMJT(xHgp=k+NrP#EfISBwx<N z(!QlmJqCI~71P`(VnUKYzu{TlG3Q@r$r9A`?z_Bi`E**hqXbZ^m&7dt==n^2boc5m zHdQ+mzBpZWLp4wD{9d(3smIz^_vL7>CzFS5#xtIMoj2#fYT>qX7)QSz0rj<VGA>&d zs0j`xc}m7|F&F4K?c}mA1`L)eO$6^zx^hyEF+5#ql?(eqHRYN0Frb^~G)WL;#qRxm zoMvCM$k>FqxSk+OUP;#hh$8v;z_N=Mo9>L6c0Nm7ZjG6=!{>IVnT~KQfB5DhtS=GC zPU>;y$<cS5XY(7wTiUlPKM>^IEosE}^%E@QwWzR-9$T+w?Rxd7(P*#Z7C=70KxXD* z#Gm=yc-S;Lo~OdOJvw*Rq-oU3^)^jY*;CahdiRrxPs2;&<?9<JD$a~7o^0C71Vo5G z5=;8ROU-cYT&RiF6>0?OgIc))*?_EFvk7M6U8i|kgX2nChYA_%-pY*KFJYR-`U17) zc5zapYqcF|CO>}o1_}J$*8x&Wa~IVhaKSneyjzj2+L}0E5~GM<&280m4+0+tcQ#dT zPkk|<n>+0Hb0-C_t9NVeh8sGIYZrD*pSmNW@YLzk;(@nGoCnVCXf_x00dMaP+e%Wo ze8V%G#DLY+ULIx#-{v_<S#Pz3L16c8`?-(33Rms>gc>TLI&o<kT<CAy;a|<IvLj7D z9nBSf;pf@5TH7Cu_UgaU6dz#FreZmwAD%;5W*n|C#p2efbtO>>((0sDdnJVEzP$f) zRS`X!?nEkVwzeLtyr-#S=$z-cN7LR|`B^>IOcfV>Ih<|cs#vCd7QqoI!{AyYHI60b zbsIvg2_!$|17wSfq2u()ENT*$bPt<Uvz%pO<R;omWDlhKDkzVf=dpa!oki@R_~-|P za(ctO<Wg!sA$Aow>Z3XaZS?Grl7--0=B*WR<0LP~im6q5vhI!0OkMmNT48E0Xt64J zh*xy|k-pamQ3{8O=v15zqF?~nWu9g(ogV9>YhCzDUwy0xh~kBwm$q{x+DWzKdmBa% z-T#=u#q0Eeo!4O_HO%!FHSb)Kyy5JoFmL&y?T>?qf;G7X)nh27Ie&SifXfi`QHDxK zGiPk7hM(PF-MIl-UNo^v7B^Uy#GJtp;fvg#8YnvT7T7sGb?ch;o%zvNXP+P$@c!ng zC>$u!p_2Pt{S#;>Sa`|8{jY)+Ajr48j@s@Y>{VUijpZpXj{ZbCVrdLl)4~mmNO7JK z<MAUbN4x;a{p&s;W3TTz{&auNpz4adr9n`BC-A|X<2>Cj5n2Hc>%A|t*6s=eiF^uv zLo2V*V2ETrm&KrFL}S?Nbqy}YT^;Tcvi%s~58Epy+WUw3ofNHnVD!E=*Ie%dli~7f z-vAL&=4cJsI+wsLetI`@)$3ImS}iJ68)846yujKm=NNiSCQhlNdseCBO=Mdtf;?M@ zV3}4uR4!8qLTuEP8g2#`sx;0uzsjFg*o~%O^ESHsd;3(Am4RlVXwv!qMAa7<GR#M^ zjHYMW)-hD0N0U!lfdf3zg|CdEq&YJrld!8!q`y=@V$EK!iGUI7VyQQ!X`<zvQQCcD z9JVKGnPsqb9<GmCp{QWgT=&emv?sY!<CbkFM-6<-mk!!;L(LyET}!(3ES*VwpXZpc z?s^$Lh6jZur&?hz#)*lmUz?vWCHH#3P1fU2C`l>D&Rox&^+5S?2z8;6vu1_2bjCg| z)E#fq94*Rgq+lh_;ZYU+qB=7kP>!4Ggbc_AG@pR!Bf>q3Du0&3*1iR1Fxj5TilfAg z!CVn5>DZE^q@;Ta?~thGPZny$qB=!EP(9r|VxWd{FB8_m0{p(D#t;G+e)`$^Ckkbh zq%PE{8n?;eoKFFF5lF#qVC{oYAxSB92O-lc+_$0|!>2{G-?`0*)8e?)O7oK0KAw(c ziH%l`!ii3`#9XI0{8+ZtdKN*x?>EqNX=d9gxEWhT9ovxzH+9}tJ2%98efgwC<aS54 zQgZxB1vFUqOzmro=qPR6C3@P5-c1x7Q_s6O#FVqv*su_h-fa-g&UA{qL2&LoPjxLO z?pNZO=;4ZMXm$RgPC>T_?5G#$cXTsls&1q4HYW<Dc<_5CkiXl!(C_xLfZW|Jw;0m? zStjkPeM-nXXhC3snxhRV<F|TC_)k+r5K(-DtYldyxnkkHZZN?X0TUhi%%JKNx#{>u z@t0`{Ta^rB#n|uxsG_71kO*)vvT#GskAfQA;T?yo%Kj@7(z>e<e9#_rJaGGUOL7(L z@iYPm$Y5VWeAqVQ<~naZF(1uTSgB7aRhi1hO$?E^o85!;)@#t=I9SZq9{f<2=q233 zKS#z6K1A3;SoCwO;)vN0Zg9nnLmX&4`)?wm*z7=hK~<eHE4}*_zkkFVy?=b*$Llea ztY}_qZvkYk$@FObFh)_Q7`P=%z}`mcdVbCIKgcCL!f?K9$SJ;L`WGtG5v}JGOa1M! z_}W(uUW;#+I4)i+4yswGoXuJK_3c4$6IU7Teh?v2SB2tNYSV*d`MU1&CB4giwY!?1 zU(i12nRR-bDC*q2vp&M3k)d1=)N``p=XirsTO7X;Xyp_FbJ3m^L5BBRh17wB$jZm3 z;WR&>nS)99tHj}SH46EyaCZjEtgS5<hpPI3DL1MKCKPMZlczUm5gEAk9YOG@*;rzw zFd7h7FL~JcK}Y`8dK+HcZon>+%LVA@v=EDr3cDE$^7rXJu$&!bOX0E`s8N?s{VE&W z{YbUad69c>qd~Iu7<?9u+eZ(HP^I%3)qSEdxH#LJTSRiH^SzQZmrijbU7$KmW{E1P z!0&~s#T-kZ)uQ`riP+>Bfu1?D278jrtCAz>@2!Bp*}MF+fe90ApTQa<;aMqs7(uM} zN$c-p?@P%idyEGP=G^44u378lCB4`g%CTlkH}RF|sMy_HXf3#a-VXbLV$%mDjiw=6 z9p1YS%#`|4WJt|(hc3b2q3aB(3r~2YGVC_XWzNWziPAdt!8su=VNT&+kFl2+sbo^x z=z;`F?{s9!u*Zsux##yMG&<(6V)Q9m%Gur7!py>*z?i3}sLJP8!yXA%=KE4)qGo>g zcq01({AQ6bU=)8AJ&UpqE9FJH51yxRaH~yFU6@zqd)Y8ucaEoa+b%$O67~?JYp{nB z@Ps0cGlrnI$s8|eom4WCGIY_AxCJPt46(+eK*KCZdWw)D3Z(nkKnLEnCDXV?U^1Yn z_4aSJF=2u<eL2yp!NlZNm#KS22Y5t)yw@64YoV|6mH#BxTU@{@-Q&uls0LL9e_8tK zjNN07NHr0?spDwuja^M+v05oQuFSDxg!>XqIb{o(&}yvaW(8Y4!42Q?uFga_p+7lU zUCFP-y-o{wZ0bP7b5uvAYN8qS(jC>SOxl2GWdZE5BnW4uMUPt->aX+)BCndd*(A1g zxWa2A74^=jH9(7p*jf<GI0)LGxQ}!%CQ^qX9R`qt_d%yX6VEqJJ{nK<hQ3^u{>-xI zIX+RPU$pb-Iz6dvp=`i$uKvtP6h94_)+vSqOA`Mw9X7#VC~3?f$PBA}D9`-$KrflV zb*H{?qI-D{?&6sl2TFM5Aro7o`){pwT?k}>XuhS*sM8llZ?6^xh$Ii{Vo_I%5#%ne z)Grk^3DNZ)lyRtmm79WgEHl@wY#nX4Bz*$_C%91$8ldJJHm9-P^a9VMnEdEt8j8EV zJCxZH@qxS_9Iz{B6JgiCB=TOHwl^+$ZB&Y|YCQLAfCn6>Zsy#4=Z+o^jmO#FWJE1t zM31oRK89rj=lj{MBaX0J3d*M+1sBW&N+wg)yMm3l>#53zuv#@gJKZWZq8@{XU4{Ga z=T{C*0LRKGX)N|0$%NHzxHl!&>Mzq+hI5H}!OENzoLWlkoMySYUN0Q|p|E(S-j#_3 zNNy6EcS}JMS6bH=y#}K4mHN8{smktInaXb5@`WAEQQK?6U0VUeUE|*kI@e$$lmiJ5 zyT}i)<$iGh+~<jRLrQ)VP7yrLhRw;tVj6M79-%l%7LC%mJTsI;uK*lCzw>uWx-AG4 zO7wT~R27_?Z^-{hj;~c+CUa8Sp_5dEb%hPhn49b6HnTwYOzAw;Z?&XGB_{t?gL{3B zR$O*12sGHw+wlUgd<zn5i9U%Ko<RCu5Fo~nJzJsgPUHp2XRLW7znZQq+j3Glx6IrU z6mu2&1kPj&Jj)q2Ty$rBYrP@mF4}p}b~w6~QV?_ks`zAw59eq;CpqJ@^-R}3MWH6n zNsrZv%oZAdnW@m&A-J=XBbl~Hm%GL>?#jHVtp2HZo`#mp<q51>+R}SxqX}wPyZ%@M zEtebNkdJ*HW=DHa!cUX=mR~;8XJE1DF7%e7ylsdlfSiGa*Slgz_M=`jsYLCgj-T_X zvR><g_LNASCisA^FsD$4{dDa=vYO={jm4%x8TOVyak6oV8mwRG7prjZs?Yl7b@3Hn zhe>eKlF_Mt{mFWk9J^a3kECc0+6=^rxh5&RH?wC(>iE&4KXwXD0F1A~dX)}uJ0ym; z?<Q>8tFBD&Y(KzjI~QJP-*J_;bCC}pTOpj`jvGtKS$HUQLEO6txPi*=9}d?o9LaHV z_x?<QD2Rd+NiuQ_WmqpkA^WQ56I)f28-9$FO{9J;UHJSKG{AVY(;hBIp)T6^p3Yt^ zVP?490^!c|Sp^AWNZ#uBq^lH;K>UERLr4rfBhk2`dT06LexQLqrolE(_ms=}h{A+K z*lrvX`4VvCOX}I|<xfON`O#DjLK`l|#O1(R$FObLK{oH7s{MtYwT8)^s_ha*;fBe> z5*a52%+p#<koV=~+9W>xw$7M)`hl~C5{X>q>N~?A)vR^1_6x;jncT&TPiA{QEtqNd zn%tH&xB3XZA|LKOBY=FI0I%W$48Ptm%O|BdhfCh3U#J(>I5J&#EM=XMjS7OfFxs)x zjOM{|w91$u{$#cyHdV<o;!8-thZ96d2(dvM<bFq+0{eD9JL<8fUPkqH@h6Cy$Ze!@ z9Bws3k^B|cXOSLkJ8kq1d+5=r7#{@5+c&2um{eLVPlRjS8_1;{V53+%JTH-zqUw`S z`IFXt{s4;Mlp@SEV3Dz$rt9)$0j1{g$44D*986pirPd%vpN_EpL|%p(HC4=5MClhc z8P`e;Zk<Z?Wl7GE?S3*=?}fva4+#DJ-N$s%fQpC0_V;lE!St^!3w-C_keM;|SdaSe zGx1g=%6x?qSGTs-Rg50X9v=hHiRz%GQqC8F2kq)v2AOXRlW$`RMZbn}F6c@56Hy*R z`?(d*-?1bWYFOMo*R@qT)-uEsn}}7K9u?i}r<j~*z@1PFOo1E|z$g@yLcu9dk|W`? z-I5UtnRB7nI~<}+Q!AVOXH}z;GBced6cB}T;7VArM;^ZVSp1ZmjBpJbpEJyAH^Bes zt-y!V>FUu?s3wYk_<VVUa4SruN<m^}tah@?d?6$w(SE<UG@hLo&2DXWPN~7DrEw6` zVpKy9(vEN9<-z|zJk6|HsB<E4iN>^(I|>`$%48Y*QpCGLyba4e@I;+d;QH<8QHl|! zvk#1uSsl%9hdND>hoN8`IE9G!p5~2Oi|Y}nvp`$Oz<KZjytL1J8GRr^mmc)8(oDHC znqr0Us;c~J<y%;^GW{QUSbj&Sd!8lNKk_h)9&5H{uEpsCh)r5g-8uHJxn`w^%TVi4 z{V<L_FI<E=&%h%U93-;UJUvA5^@IOwQuZ8Y#JfBBl3s&=xiR-F8K7>R92%@w0Qg`s z|FMTTw==s4OibvQitm$203%WG>fJ=X*}2~aU!yilg2U#Htg%+vKWLK3wUXBP<|Z-R zYe68@5ABc$vZ0g49oBDR)RH!3XE>lFZdA`C+9gYcjA7Btq1m!!;f>v%ud=DzitKWx zV8_052*CxZZ#ePLx~d7vg%V?lmmHj%+eQ{ai@!@Hb0sgTdfnhk`d45Rg|(Rvag?xe z8&s*~i8bk1L)qNWq$dOl-xIK;Fsg~lAx(`+$EGW6$oZjhnVPNj58W(Bq&86r-#>7w zJm86tj?JO^lz)Wk6%4?^A&4y~3LHgkc1t7YGHSyon+TE{e=cWLUlK6*lL?8aB!S64 znfna|K2gp&)Vp*6Q9>>7<a|o_WOn9o`1_${02j1*=R#@2T=9k#yN|Sajk`$tm*yp) z89<5^>?9I$tLF_vSW;{}3LzN|Fz$t4FH;Vi`|P@0r^JauO(^7qLQjSOK^cPE{&5pQ zNYUR*i|Afk-qIsA!msx2o7SHcqRjxklve5gN!0lDcnIq5LNjY#8c}>X1yMY6Y_-JO z>#oyN0uFb>c1XP<wuO~gy?+6)V-aAn<5lLcxTMt7E>c?mIvO&rIv#Kf9#>^jlDYl& zaY-_3Ku>PRv?SL^8MkU*Sev~SIoEBb<n&a;?o$mJ`r$_?m#&VFj{h|eiuZI#itOV* zY7#b83?m!lP(Kn!Q5J82{+131I&~;t(HW}_j4J<T+Sg*H87#o|2gI=vrg%xryVprM zCGYT*7z@ZdQa1@4NA~O|!7quCq|f4z5doLuKPEbWeZjWKx~u6{Quu~8Zz0`yUB4uG z)JZP_T#s#mW{EB%h0R-Px0AT1cyX?*@aFnILRa*t{~RNM?GP8aou(cHoHS+GQ<ZAL zwo$`nv5faxb<LQ%mw7cH#vMareu+un+(G&HX9usm4cyLe1a)<7aXCYv3tv?QP+cu! zR7SN?uc+x(#0Oykb(dbsIfm5devsmvfcxm7`0;i=x6`HP*L;#lN(<IwpJ9Jc%oTz@ z>eJ&htG`!WcdqTt(-ptcyv^J_W!C@pywL3L-nS|tL<riYw-Mpzb3Hg#ni$ZrzKW?o z%IgFD`KuL*WWIPspGcB{ZSQAdy!E%Dq%rs_AqPmu@2cK#-!*p6UEMbDw(ZZ&0D}bX z3^~(P*ZJxZ2XSYw5VcC#dj~;}myG&VWqi~|F56sN34SCG8psw0xnkReoe~m_@*7l2 z`VeIAexWsDBb+!Vsxz7RQm1OsR7uTdHn?l6uoz=dezL0Tm+ATkO?sl1QyRz4CZ>t> zG~08RP^(~CR^Pq<LYYy#mF4uH=e8(?=l6E^wDk|JIi<f$ZC=Qwtuz{rAfuM>fG8ZN z`vr}!>AVjk)^($(#}c+k675gA4d+I6)VWg7d{rEzx&Ef(EC^1aNxu}8kWW3zLPL-n zs_<>8tYTTNgr4{hWdbbK*{2IJL$7L_LE}RKb}QDuxGK%B<Oa-aP~n^7SIqPYop!AT znV$0>wc^|4LR1Fl9K(;#@gsG$`=8F6d64fj<)g6|YnAV9A5<fUH$L&rye3m+(Z~K| z`thvUQj(f3xgFfwPx^vytn&$wT{LUFmiBRU)@DQG!YdgfzazsbdPI0tT1Lk5`q*+& zmz!><9S36poOD~%eXYeluy|ky^etiCOIZqB(v`$z)%b(qbf+N(I~b61R(q!LdHZEL z>Ef-I8cyfl%JnC3N4G0PDPr)e2@*EBATP8*r$LTL#l3DkL1Z<a&Owr3df-Fn^{S65 z??=C2>BT-_KgOyu$MBWuUW~bqAYD+GgkmVRz5nEZN|&}GnT=xbAqpGCsw|O?pZMpH zzgFHPL>S;<m5TFEUsJ$5e05BzWjH6YL8<IE23oPIMf#o3w9l$oJB4NP7~EAXKs8$S zk2<OWAp?(NKo2H4(Xe!z3s*s|f1khL<)gU)txsSh&<!`{`}Uak6MC})?f9E$Um__$ zEzBwpY3lAo^jwG-G70Hd47}x>d6B0q5vpc{Qkx)IgFR}h5OB`o8a<-#GVWQi*r{b$ zzm#pXMD3}PyH~$eJ?yZqQD{CJeMXbMiL(P|X-0r}L3cbN^@I!aPI1#g^r~?O=Dr!_ z(V`#J&Da(C=FF9-Som%91`9D;)Q_|exf|^W4yI$aDj#*-%O(eza9HXEUl1gn74%}a z#Po*8H88Tp=FT(~PMWu!MzA9&LzP<ko5Bn2m8eE-ZMqk-z<}p`(xQbK1h&H8f9zj5 zsWfQZlQVBMZ+6G%&!c~X#W%42yzV>I%2=BmJx!Cgy{-Wg1a*$DDL=?<<2|2LIqfkA zs=c;~EXg)&8xJb2%p*h~l0qWr@14E8`tCz1*KACfN=HEuA%GxYOm0~HIifl*hQUO! z)M|dVaZ_a^h6<_cKu^)`tOe`moQeZoxq2!Zg+>DT+)oU0z(Hb@(UX`2Dbp85oW0iv zPx31_ecti=<7m)hZWJxDZ~t!e^gB{B^7b~xf*|q!nN41UZ+xIOXDgDm)VPp`+1li_ zoiWKEMwU3iHoeq6NFPuz_nf+GBU(OI-8Rr$TbMFP5ZZR@^7mK60;_?mNXR1OA=G=- z&_NQZ8~OVWa`$4k$Qj*g?|px^_Rj<U)GGJL{VMkBHPt$;$lMl1woU^9vi%&cnLjOD z6Nly1bL_YH(w8<J%<BwikWqWo3bdjNvG^U`RqDENcTT88n>toJzYg{xVC+Ol{fqs( zYZcadQ12F_i4k7R!vMWx!RT6IjtNkWcmK|wd{fIE@nVI&iEREfwdtjL9Vh;GSFL6? zA8U?GKEoH<ufMA+>=QeTj0*0fFCY~JeUjF>4f$=+R_<jwgH;!_LcQ7wjkHU2ZfjfW ziws*(J1@u9hU>ZiYU-w^X~fRY=7@N12U3VOrNy!97&QP+u8>Oy%py1Y_SuH)48<S2 ziM^#s(JMMhoU_>s4<a?wR&-i>w4PUQzTqIQUVhf7sRaVe`!{;jMBL4PVlq~`uGsX9 zurNp<KbCW06!E{PZ*iF5`N@C;r#Oyl0rq5wKNdXps0l!o6sb-dt|MpOOpkX{PaQx) zq~N;2>(8_#t83<`5oSWTr||l>!Aa*OE4K-d5C`})mi@$u6AFvNHR<Z<ioIRwN;KKr zUrQ|qSp@~x8*NcdV%zc0u{EEDJlBWR0X&@*(lhVpKiG(155k2WH939w@KN#A5M}76 zjkxxsBbg^!*De4=t=EU$C!v9vmo2m>TdU<uii}E@KS>oSlgEux>k+F+$J|Mq_ml`C zh$>o%u?WQoUwQdNr^q<4|H7;PE*egVjLM<=;dkfcQ3RWYGSElmhz$`b;{ElLpSlFX zL#Cato`6VqwW~ddbgL$cbk(>!15^rK*A~=$*;+hBngo!?NfDxtOp?u1qO;;udm^fY z>^$t+5b+G>Hk<p2Fqx!AaKxh<gpm(MLFafh^-@G0lk3E>rsn3tW&lVuQMGM)*ez{w z0Um3S9K<<#oL$9P9M@7_1*>V%k^5lA9f(`+V8(^Y;QBzl0lo6*WGig4?ILiIl0Yu& z@3-LJKf|sj<(*sWzvBpzGpK$2`&|^hj)D0Z+d1;VV?)0(RG#M!4z~#o20JH>M{0Qt z&hw<|c^9#%uY9>$WHhK*@vOhFE&hrko#1vl2lXMZBh=es?>h=y@h(LNkfpO|%%S}7 z#(9<Ux5rw>cTNcGj<5+fN?KW6h~+YiiwirfwHPKTxfbcM-CmTDAtYY5pF1uAAr}lO zwgV02OxnqO18a9uLLFM(n42kfy|vX~w(y_=vwr+a#K?!wp3p`m$1m78>ct)#7dE{4 zFtv5FFhgu-9iyy*&RUW}n=}xQ49rw%p+(zijl<Tz!WhH)Gb%V(=uDjE&lg3_38XI> zQ!hl8TB<@!i8P~=oFuyESA&-EVR{)S^uNdLbmg{~X81mY4pEMx!|%XgIL$}CMF+xA zlA)*g!Y{D@00u@HX)Bdd3EW3jK?}`0f*(z?YiM-k$i}l4Ir72ijh9fbK}PxL1Xhiw z74FH*_IVd64V1E2)L&ScASqlJWKzx&s_A%Z>r?6b0Gtqd_D^{+f~C^3LUhu+YE}=Q zh}UOeqDy(ro18Q*SoO~g5yR(n!E4k#9Vj(rd1C%6PTdwxD1xubFplc}&4JN#<Yt73 zKT7M^xKWmu*)*5_{i9#6NvWxkqQ9)EPyD6VhY)6cbXhWV0up-Lxg6A5<!(<)m<l*8 zZNk-Pzk=yzhpV{6LP1|*b}M>qWPy)gfPzWXc~9Z_%>%ylxND1&79U=o1CNOAH#L5% z8wSSI9@dHi6!ap~hnjhCf2{#1ZOF#0vb=et9p_I~JJfmo?6H<QF;vZG;S)uN*Y{Uq zg|0-ya<DkU$o#qUR=i$0C#7_uG7N>VvH|1A*%?WNPzs{!;o!8mIAEbz`ax6llt=30 z4-{7Wi*P~rjhgAV*V^MTXMN(o%^G~Ue}eS=UnhzZRYo5SiIhbJ6wT#%i)_dl$DivJ zxNy$J<~RvI0aB0B#65CsQ{@W3SIP7`p?ALgo{Tv?HMBewwhSbdL|jz?W*-`=F_{l$ z$TC;Y7nG9q%|-H66&ID>y!>nQ942R8Pjdfc-tGSyoxou&tD@5AT;m(zE{9IzeD{w4 zU111Q_uHG<pD!=>%G2js>bw|}Cl!npn#Jrd1eJ;N$m^)koBVXhfb{X_fDDqKFZDFm zs%JbrfYhY%#~_59;~iKN!~}#&{&Xy&)`l)`<7{;7R@?2(c%e1Eip>o9e?>f&_*GBN zS=@~4S~v7PMSv^AUP-%m7lrAw9A;}J<tlM~O8Sgq@@{2&pTEjQ*~-+umeE}@|I(1I zv7vD5M$ozXNIxtof=B1*n4XWK%)D~9js7z90++DA=B8k2KiMW6G+F)TVY}tDD@Bym z)G37WGz#Gu*3r(sIzs2K?+Wu@io3uZfq}waIbp7(``u3`tp8yqN2Dso{ng}pRQa8D zb1{(bLv|r-K|kWJL?Y=|ZiuF1l3)I-Xn@+Xe`a3)X1(C5!|OlOJ-DLq+MoY-F#B!^ z^y*x@F!>Flt~y5e3YO|LBPZZMXR-zRCx;}zL4hU&U<}YQ-=B<yHnE@*untz1PH>by z)MN&2jG6x>OBTBt15mFq>DYZxE^>dv%@-Y~DAUp|p;yew`B$M;KEW=mapv+F8E#%` z|Lhg(5{!^cVElzJ0PG;=VrVa-k%cVH7q!$3DO}cV^f82Eii>==*2xR|-Y>XbpMc>~ zm5^W&fVS&M_^E;W0E)mVVTrq~BHWTwNQ!P$s(l>j*UtE0LpYQp4a2mssIHpSV+zkV z==7{^0hpczsS3d7B>Ug%+8T0r8#84sKz;1W8*72b#V^e{5oU6DOp!xZY<wHPZ7HXm zpf8OHWNsJp+?Of=*UjAik`=TYvxpo{D5je;dKO+4uVT2~O%A%JSab**^VQYULMF|K zNvA1sM4nb)fjm)<RXE?_Ik%_Bkt&$=g&+)YRS|Uy8w23?a7iR$OTXe1?7ox85Fq<w zmTc-v^?rF6|JUTG`jMqaXM)KKeB!(3)#Zy4R%3+0Suy_!oTTC!{~ogRO6#r8M6tOt z%j2F5vb#AjXNi3ur&;7&6jn`h5N$w*DS&Ha2<>?_A+DRE<Vpyq>d%CpFdC;oLQywa zJgDzlUXX22`Ev#Yhu9Do)FSA%SFX<_Zf2ZFgt2zzD_*&$_86^x^w?X}SizTF=>CVQ zFC6jzIy&-y8y?j+<JtC9J!_5ZCRb1_nLx{z+V+S_J^i8?2weDQonz4&F>nx(x)Kqi z-e{Ph$EYnr+WbZ~Jnqws<4q=21NQ#t8uoFCJ6wGRPH)8Q2Jz};PMWkZBoL4Derz#V zFaouBgeTiUsLp~2(LE2&ynj20QU6sWOsg!K<Sy71l{V#!_q#%2@-e@Sw?tMhcuTt1 zvq;`gZ%B2fC(qbSwo;e(>JJ*L(3|TfEg?7!Wy?=4YYelq!_^MeQ2nm<hfT+=l|&hx z*L>JERBTiI5pMUJ$z@4yM%14{spSx&;12EsU}t1W0#1cFm-^z!xw8!(+>U0qBS%)v zj3E!(FN8DaPM?n$@KmQ^j9e~$K2ks;=xTk7$8@+n1Fhmh!HEFrYR*{ndb{A=Ei0dX zYv6F%y%l|PXoJc}gS9TjbyZqBmrr-i`#1ZUX}2a^3*CmeX@%yFSHJ+uALpS2i)I1} z7?C!qg(qA&c@Z=3Z$6J%g+R*{_NdfAcdzhMr!r!st_8Iz23fWi)DYER1<_c}^z8Z% zwTX}TS>>$8X<LIkvnN%|6k*0>ufSgg;Iv3GQnfJdXk{VZHYpgE7%{sWW*vCrce|u} zTq>M8TIpxD6kCrjng|_KEh|klCApnD$kumMO!G(ZqCCj-LP=1B;Vwv?b4TpAKmBW} zX#d}r8f_8%|J-Q*gN0Q1E6S9no!^Y-VwTt+1OaD*W<BsanzG-N`R@@uy#Kc$hM56- X1J}fD+0-ZZE%0?&)oXducOU;BO(BFm literal 0 HcmV?d00001 diff --git a/src/opticalcontroller/json_files/nodes.json b/src/opticalcontroller/json_files/nodes.json new file mode 100644 index 000000000..60f017c19 --- /dev/null +++ b/src/opticalcontroller/json_files/nodes.json @@ -0,0 +1,39 @@ +{ + "R1":{ + "id":0, + "ip":"10.30.2.207", + "port":"50001", + "type":"OC-ROADM", + "driver": "OpticalOC" + }, + + "R2":{ + "id":1, + "ip":"10.30.2.208", + "port":"50001", + "type":"OC-ROADM", + "driver": "OpticalOC" + }, + + "R3":{ + "id":2, + "ip":"10.30.2.209", + "port":"50001", + "type":"OC-ROADM", + "driver": "OpticalOC" + }, + "T1":{ + "id":3, + "ip":"10.30.2.210", + "port":"50001", + "type":"OC-TP", + "driver": "OpticalOC" + }, + "T2":{ + "id":4, + "ip":"10.30.2.211", + "port":"50001", + "type":"OC-TP", + "driver": "OpticalOC" + } +} diff --git a/src/opticalcontroller/json_files/optical_TFSworking.json b/src/opticalcontroller/json_files/optical_TFSworking.json new file mode 100644 index 000000000..ff1841eee --- /dev/null +++ b/src/opticalcontroller/json_files/optical_TFSworking.json @@ -0,0 +1,486 @@ +{ + "R1-R2": { + "length": 80, + "source": "d1", + "target": "d1", + "fibers": { + "d1-1": { + "length": 80, + "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 + ] + } + } + }, + "R2-R1": { + "length": 80, + "source": "d1", + "target": "d1", + "fibers": { + "d1-1": { + "length": 80, + "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 + ] + } + } + }, + "T1-R1": { + "length": 0, + "source": "muxT", + "target": "srgR", + "fibers": { + "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 + ] + } + } + }, + "R1-T1": { + "length": 0, + "source": "srgT", + "target": "muxR", + "fibers": { + "S1": { + "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 + ] + } + } + }, + "T2-R2": { + "length": 0, + "source": "muxT", + "target": "srgR", + "fibers": { + "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 + ] + } + } + }, + "R2-T2": { + "length": 0, + "source": "srgT", + "target": "muxR", + "fibers": { + "S1": { + "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 + ] + } + } + } +} diff --git a/src/opticalcontroller/json_files/optical_topoTFS.json b/src/opticalcontroller/json_files/optical_topoTFS.json new file mode 100644 index 000000000..7dea474cd --- /dev/null +++ b/src/opticalcontroller/json_files/optical_topoTFS.json @@ -0,0 +1,1836 @@ +{ + "R1-R2": { + "length": 80, + "source": "d1", + "target": "d1", + "fibers": { + "d1-1": { + "length": 80, + "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 + ] + }, + "d1-2": { + "length": 80, + "src_port": "102", + "dst_port": "202", + "local_peer_port": "202", + "remote_peer_port": "102", + "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 + ] + } + } + }, + "R2-R1": { + "length": 80, + "source": "d1", + "target": "d1", + "fibers": { + "d1-1": { + "length": 80, + "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 + ] + }, + "d1-2": { + "length": 80, + "src_port": "102", + "dst_port": "202", + "local_peer_port": "202", + "remote_peer_port": "102", + "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 + ] + } + } + }, + "R1-R3": { + "length": 80, + "source": "d2", + "target": "d1", + "fibers": { + "d2-1": { + "length": 80, + "src_port": "103", + "dst_port": "201", + "local_peer_port": "203", + "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 + ] + }, + "d2-2": { + "length": 80, + "src_port": "104", + "dst_port": "202", + "local_peer_port": "204", + "remote_peer_port": "102", + "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 + ] + } + } + }, + "R3-R1": { + "length": 80, + "source": "d1", + "target": "d2", + "fibers": { + "d1-1": { + "length": 80, + "src_port": "101", + "dst_port": "203", + "local_peer_port": "201", + "remote_peer_port": "103", + "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 + ] + }, + "d1-2": { + "length": 80, + "src_port": "102", + "dst_port": "204", + "local_peer_port": "202", + "remote_peer_port": "104", + "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 + ] + } + } + }, + "R2-R3": { + "length": 80, + "source": "d2", + "target": "d2", + "fibers": { + "d2-1": { + "length": 80, + "src_port": "103", + "dst_port": "203", + "local_peer_port": "203", + "remote_peer_port": "103", + "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 + ] + }, + "d2-2": { + "length": 80, + "src_port": "104", + "dst_port": "204", + "local_peer_port": "204", + "remote_peer_port": "104", + "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 + ] + } + } + }, + "R3-R2": { + "length": 80, + "source": "d2", + "target": "d2", + "fibers": { + "d2-1": { + "length": 80, + "src_port": "103", + "dst_port": "203", + "local_peer_port": "203", + "remote_peer_port": "103", + "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 + ] + }, + "d2-2": { + "length": 80, + "src_port": "104", + "dst_port": "204", + "local_peer_port": "204", + "remote_peer_port": "104", + "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 + ] + } + } + }, + "T1-R1": { + "length": 0, + "source": "muxT", + "target": "srgR", + "fibers": { + "M1": { + "length": 0, + "src_port": "1", + "dst_port": "2001", + "local_peer_port": "1", + "remote_peer_port": "1001", + "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 + ] + }, + "M2": { + "length": 0, + "src_port": "2", + "dst_port": "2002", + "local_peer_port": "2", + "remote_peer_port": "1002", + "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 + ] + }, + "M3": { + "length": 0, + "src_port": "3", + "dst_port": "2003", + "local_peer_port": "3", + "remote_peer_port": "1003", + "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 + ] + } + } + }, + "R1-T1": { + "length": 0, + "source": "srgT", + "target": "muxR", + "fibers": { + "S1": { + "length": 0, + "src_port": "1001", + "dst_port": "1", + "local_peer_port": "2001", + "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 + ] + }, + "S2": { + "length": 0, + "src_port": "1002", + "dst_port": "2", + "local_peer_port": "2002", + "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 + ] + }, + "S3": { + "length": 0, + "src_port": "1003", + "dst_port": "3", + "local_peer_port": "2003", + "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 + ] + } + } + }, + "T2-R2": { + "length": 0, + "source": "muxT", + "target": "srgR", + "fibers": { + "M1": { + "length": 0, + "src_port": "1", + "dst_port": "2001", + "local_peer_port": "1", + "remote_peer_port": "1001", + "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 + ] + }, + "M2": { + "length": 0, + "src_port": "2", + "dst_port": "2002", + "local_peer_port": "2", + "remote_peer_port": "1002", + "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 + ] + }, + "M3": { + "length": 0, + "src_port": "3", + "dst_port": "2003", + "local_peer_port": "3", + "remote_peer_port": "1003", + "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 + ] + } + } + }, + "R2-T2": { + "length": 0, + "source": "srgT", + "target": "muxR", + "fibers": { + "S1": { + "length": 0, + "src_port": "1001", + "dst_port": "1", + "local_peer_port": "2001", + "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 + ] + }, + "S2": { + "length": 0, + "src_port": "1002", + "dst_port": "2", + "local_peer_port": "2002", + "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 + ] + }, + "S3": { + "length": 0, + "src_port": "1003", + "dst_port": "3", + "local_peer_port": "2003", + "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 + ] + } + } + } +} diff --git a/src/opticalcontroller/json_files/tfs.json b/src/opticalcontroller/json_files/tfs.json new file mode 100644 index 000000000..a108ed13e --- /dev/null +++ b/src/opticalcontroller/json_files/tfs.json @@ -0,0 +1,1286 @@ +{ + "links": [ + { + "link_id": { + "link_uuid": { + "uuid": "T1->R1" + } + }, + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "T1" + } + }, + "endpoint_uuid": { + "uuid": "1" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "R1" + } + }, + "endpoint_uuid": { + "uuid": "12" + } + } + ], + "optical_link": { + "name": "T1-R1", + "details": { + "length": 0, + "source": "muxT", + "target": "srgR", + "fibers": [ + { + "ID": "M1", + "length": 0, + "src_port": "1", + "dst_port": "2001", + "local_peer_port": "1", + "remote_peer_port": "1001", + "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 + ] + }, + { + "ID": "M2", + "length": 0, + "src_port": "2", + "dst_port": "2002", + "local_peer_port": "2", + "remote_peer_port": "1002", + "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 + ] + }, + { + "ID": "M3", + "length": 0, + "src_port": "3", + "dst_port": "2003", + "local_peer_port": "3", + "remote_peer_port": "1003", + "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 + ] + } + ] + } + } + }, + { + "link_id": { + "link_uuid": { + "uuid": "R1->T1" + } + }, + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "R1" + } + }, + "endpoint_uuid": { + "uuid": "2" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "T1" + } + }, + "endpoint_uuid": { + "uuid": "1" + } + } + ], + "optical_link": { + "name": "R1-T1", + "details": { + "length": 0, + "source": "srgT", + "target": "muxT", + "fibers": [ + { + "ID": "M1", + "length": 0, + "src_port": "1001", + "dst_port": "1", + "local_peer_port": "2001", + "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 + ] + }, + { + "ID": "M2", + "length": 0, + "src_port": "1002", + "dst_port": "2", + "local_peer_port": "2002", + "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 + ] + }, + { + "ID": "M3", + "length": 0, + "src_port": "1003", + "dst_port": "3", + "local_peer_port": "2003", + "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 + ] + } + ] + } + } + }, + { + "link_id": { + "link_uuid": { + "uuid": "R1->R2" + } + }, + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "R1" + } + }, + "endpoint_uuid": { + "uuid": "13" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "R2" + } + }, + "endpoint_uuid": { + "uuid": "24" + } + } + ], + "optical_link": { + "name": "R1-R2", + "details": { + "length": 0, + "source": "D1", + "target": "D1", + "fibers": [ + { + "ID": "D11", + "length": 0, + "src_port": "13", + "dst_port": "24", + "local_peer_port": "23", + "remote_peer_port": "14", + "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": { + "link_uuid": { + "uuid": "R2->R1" + } + }, + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "R2" + } + }, + "endpoint_uuid": { + "uuid": "14" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "R1" + } + }, + "endpoint_uuid": { + "uuid": "23" + } + } + ], + "optical_link": { + "name": "R2-R1", + "details": { + "length": 0, + "source": "D1", + "target": "D1", + "fibers": [ + { + "ID": "D11", + "length": 0, + "src_port": "14", + "dst_port": "23", + "local_peer_port": "24", + "remote_peer_port": "13", + "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": { + "link_uuid": { + "uuid": "T2->R2" + } + }, + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "T2" + } + }, + "endpoint_uuid": { + "uuid": "1" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "R2" + } + }, + "endpoint_uuid": { + "uuid": "1001" + } + } + ], + "optical_link": { + "name": "T2-R2", + "details": { + "length": 0, + "source": "srgT", + "target": "muxT", + "fibers": [ + { + "ID": "M1", + "length": 0, + "src_port": "1", + "dst_port": "1001", + "local_peer_port": "1", + "remote_peer_port": "2001", + "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 + ] + }, + { + "ID": "M2", + "length": 0, + "src_port": "2", + "dst_port": "1002", + "local_peer_port": "2", + "remote_peer_port": "2002", + "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 + ] + }, + { + "ID": "M3", + "length": 0, + "src_port": "3", + "dst_port": "1003", + "local_peer_port": "3", + "remote_peer_port": "2003", + "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 + ] + } + ] + } + } + }, + { + "link_id": { + "link_uuid": { + "uuid": "R2->T2" + } + }, + "link_endpoint_ids": [ + { + "device_id": { + "device_uuid": { + "uuid": "R2" + } + }, + "endpoint_uuid": { + "uuid": "5" + } + }, + { + "device_id": { + "device_uuid": { + "uuid": "T2" + } + }, + "endpoint_uuid": { + "uuid": "6" + } + } + ], + "optical_link": { + "name": "R2-T2", + "details": { + "length": 0, + "source": "srgT", + "target": "muxT", + "fibers": [ + { + "ID": "M1", + "length": 0, + "src_port": "1001", + "dst_port": "1", + "local_peer_port": "2001", + "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 + ] + }, + { + "ID": "M2", + "length": 0, + "src_port": "1002", + "dst_port": "2", + "local_peer_port": "2002", + "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 + ] + }, + { + "ID": "M3", + "length": 0, + "src_port": "1003", + "dst_port": "3", + "local_peer_port": "2003", + "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 + ] + } + ] + } + } + } + ] +} \ No newline at end of file diff --git a/src/opticalcontroller/json_files/topo_2_links.json b/src/opticalcontroller/json_files/topo_2_links.json new file mode 100644 index 000000000..02165938c --- /dev/null +++ b/src/opticalcontroller/json_files/topo_2_links.json @@ -0,0 +1,1530 @@ +{ + "R1-R3": { + "length": 80, + "source": "d2", + "target": "d1", + "fibers": { + "d2-1": { + "length": 80, + "src_port": "103", + "dst_port": "201", + "local_peer_port": "203", + "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 + ] + }, + "d2-2": { + "length": 80, + "src_port": "104", + "dst_port": "202", + "local_peer_port": "204", + "remote_peer_port": "102", + "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 + ] + } + } + }, + "R3-R1": { + "length": 80, + "source": "d1", + "target": "d2", + "fibers": { + "d1-1": { + "length": 80, + "src_port": "101", + "dst_port": "203", + "local_peer_port": "201", + "remote_peer_port": "103", + "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 + ] + }, + "d1-2": { + "length": 80, + "src_port": "102", + "dst_port": "204", + "local_peer_port": "202", + "remote_peer_port": "104", + "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 + ] + } + } + }, + "R2-R3": { + "length": 80, + "source": "d2", + "target": "d2", + "fibers": { + "d2-1": { + "length": 80, + "src_port": "103", + "dst_port": "203", + "local_peer_port": "203", + "remote_peer_port": "103", + "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 + ] + }, + "d2-2": { + "length": 80, + "src_port": "104", + "dst_port": "204", + "local_peer_port": "204", + "remote_peer_port": "104", + "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 + ] + } + } + }, + "R3-R2": { + "length": 80, + "source": "d2", + "target": "d2", + "fibers": { + "d2-1": { + "length": 80, + "src_port": "103", + "dst_port": "203", + "local_peer_port": "203", + "remote_peer_port": "103", + "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 + ] + }, + "d2-2": { + "length": 80, + "src_port": "104", + "dst_port": "204", + "local_peer_port": "204", + "remote_peer_port": "104", + "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 + ] + } + } + }, + "T1-R1": { + "length": 0, + "source": "muxT", + "target": "srgR", + "fibers": { + "M1": { + "length": 0, + "src_port": "1", + "dst_port": "2001", + "local_peer_port": "1", + "remote_peer_port": "1001", + "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 + ] + }, + "M2": { + "length": 0, + "src_port": "2", + "dst_port": "2002", + "local_peer_port": "2", + "remote_peer_port": "1002", + "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 + ] + }, + "M3": { + "length": 0, + "src_port": "3", + "dst_port": "2003", + "local_peer_port": "3", + "remote_peer_port": "1003", + "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 + ] + } + } + }, + "R1-T1": { + "length": 0, + "source": "srgT", + "target": "muxR", + "fibers": { + "S1": { + "length": 0, + "src_port": "1001", + "dst_port": "1", + "local_peer_port": "2001", + "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 + ] + }, + "S2": { + "length": 0, + "src_port": "1002", + "dst_port": "2", + "local_peer_port": "2002", + "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 + ] + }, + "S3": { + "length": 0, + "src_port": "1003", + "dst_port": "3", + "local_peer_port": "2003", + "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 + ] + } + } + }, + "T2-R2": { + "length": 0, + "source": "muxT", + "target": "srgR", + "fibers": { + "M1": { + "length": 0, + "src_port": "1", + "dst_port": "2001", + "local_peer_port": "1", + "remote_peer_port": "1001", + "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 + ] + }, + "M2": { + "length": 0, + "src_port": "2", + "dst_port": "2002", + "local_peer_port": "2", + "remote_peer_port": "1002", + "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 + ] + }, + "M3": { + "length": 0, + "src_port": "3", + "dst_port": "2003", + "local_peer_port": "3", + "remote_peer_port": "1003", + "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 + ] + } + } + }, + "R2-T2": { + "length": 0, + "source": "srgT", + "target": "muxR", + "fibers": { + "S1": { + "length": 0, + "src_port": "1001", + "dst_port": "1", + "local_peer_port": "2001", + "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 + ] + }, + "S2": { + "length": 0, + "src_port": "1002", + "dst_port": "2", + "local_peer_port": "2002", + "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 + ] + }, + "S3": { + "length": 0, + "src_port": "1003", + "dst_port": "3", + "local_peer_port": "2003", + "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 + ] + } + } + } +} diff --git a/src/opticalcontroller/json_files/topology-optical.json b/src/opticalcontroller/json_files/topology-optical.json new file mode 100644 index 000000000..e2453b654 --- /dev/null +++ b/src/opticalcontroller/json_files/topology-optical.json @@ -0,0 +1,252 @@ +{ + "r1-r2": { + "length": 80, + "source" : "d1", + "target" : "d1", + "fibers" : { + "d1-1": { + "src_port": "1T", + "dst_port": "1R", + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + }, + "d1-2":{ + "src_port": "2T", + "dst_port": "2R", + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + } + } + }, + "r2-r1": { + "length": 80, + "source" : "d1", + "target" : "d1", + "fibers" : { + "d1-1" : { + "src_port": "1T", + "dst_port": "1R", + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + }, + "d1-2" : { + "src_port": "2T", + "dst_port": "2R", + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + } + } + }, + "r1-r3": { + "length": 80, + "source" : "d2", + "target" : "d1", + "fibers" : { + "d2-1":{ + "src_port": "3T", + "dst_port": "1R", + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + }, + "d2-2":{ + "src_port": "4T", + "dst_port": "2R", + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + } + } + }, + "r3-r1": { + "length": 80, + "source" : "d1", + "target" : "d2", + "fibers" : { + "d1-1": { + "src_port": "1T", + "dst_port": "3R", + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + }, + "d1-2": { + "src_port": "2T", + "dst_port": "4R", + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + } + } + }, + "r2-r3": { + "length": 80, + "source" : "d2", + "target" : "d2", + "fibers" : { + "d2-1": { + "src_port": "3T", + "dst_port": "3R", + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + }, + "d2-2": { + "src_port": "4T", + "dst_port": "4R", + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + } + } + }, + "r3-r2": { + "length": 80, + "source" : "d2", + "target" : "d2", + "fibers" : { + "d2-1": { + "src_port": "3T", + "dst_port": "3R", + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + }, + "d2-2":{ + "src_port": "4T", + "dst_port": "4R", + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + } + } + }, + "t1-r1": { + "length": 0, + "source" : "muxT", + "target" : "srgR", + "fibers" : { + "M1": { + "src_port": "1", + "dst_port": "101R", + "used": false, + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + }, + "M2": { + "src_port": "2", + "dst_port": "102R", + "used": false, + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + }, + "M3": { + "src_port": "3", + "dst_port": "103R", + "used": false, + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + } + } + }, + "r1-t1": { + "length": 0, + "source" : "srgT", + "target" : "muxR", + "fibers" : { + "S1": { + "src_port": "101T", + "dst_port": "1", + "used": false, + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + }, + "S2": { + "src_port": "102T", + "dst_port": "2", + "used": false, + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + }, + "S3": { + "src_port": "103T", + "dst_port": "3", + "used": false, + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + } + } + }, + "t2-r2": { + "length": 0, + "source" : "muxT", + "target" : "srgR", + "fibers" : { + "M1": { + "src_port": "1", + "dst_port": "101R", + "used": false, + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + }, + "M2": { + "src_port": "2", + "dst_port": "102R", + "used": false, + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + }, + "M3": { + "src_port": "3", + "dst_port": "103R", + "used": false, + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + } + } + }, + "r2-t2": { + "length": 0, + "source" : "srgT", + "target" : "muxR", + "fibers" : { + "S1": { + "src_port": "101T", + "dst_port": "1", + "used": false, + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + }, + "S2": { + "src_port": "102T", + "dst_port": "2", + "used": false, + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + }, + "S3": { + "src_port": "103T", + "dst_port": "3", + "used": false, + "c_slots": {"1": 1, "2": 1, "3": 1, "4": 1}, + "l_slots": {"101": 1, "102": 1, "103": 1, "104": 1}, + "s_slots": {"1001": 1, "1002": 1, "1003": 1, "1004": 1} + } + } + } +} diff --git a/src/opticalcontroller/json_files/topology-optical2.json b/src/opticalcontroller/json_files/topology-optical2.json new file mode 100644 index 000000000..fe8e9866b --- /dev/null +++ b/src/opticalcontroller/json_files/topology-optical2.json @@ -0,0 +1,324 @@ +{ + "r1-r2": { + "length": 80, + "source" : "d1", + "target" : "d1", + "fibers" : { + "d1-1": { + "length": 80, + "src_port": "1T", + "dst_port": "1R", + "local_peer_port": "1R", + "remote_peer_port": "1T", + "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] + }, + "d1-2":{ + "length": 80, + "src_port": "2T", + "dst_port": "2R", + "local_peer_port": "2R", + "remote_peer_port": "2T", + "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] + } + } + }, + "r2-r1": { + "length": 80, + "source" : "d1", + "target" : "d1", + "fibers" : { + "d1-1" : { + "length": 80, + "src_port": "1T", + "dst_port": "1R", + "local_peer_port": "1R", + "remote_peer_port": "1T", + "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] + }, + "d1-2" : { + "length": 80, + "src_port": "2T", + "dst_port": "2R", + "local_peer_port": "2R", + "remote_peer_port": "2T", + "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] + } + } + }, + "r1-r3": { + "length": 80, + "source" : "d2", + "target" : "d1", + "fibers" : { + "d2-1":{ + "length": 80, + "src_port": "3T", + "dst_port": "1R", + "local_peer_port": "3R", + "remote_peer_port": "1T", + "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] + }, + "d2-2":{ + "length": 80, + "src_port": "4T", + "dst_port": "2R", + "local_peer_port": "4R", + "remote_peer_port": "2T", + "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] + } + } + }, + "r3-r1": { + "length": 80, + "source" : "d1", + "target" : "d2", + "fibers" : { + "d1-1": { + "length": 80, + "src_port": "1T", + "dst_port": "3R", + "local_peer_port": "1R", + "remote_peer_port": "3T", + "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] + }, + "d1-2": { + "length": 80, + "src_port": "2T", + "dst_port": "4R", + "local_peer_port": "2R", + "remote_peer_port": "4T", + "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] + } + } + }, + "r2-r3": { + "length": 80, + "source" : "d2", + "target" : "d2", + "fibers" : { + "d2-1": { + "length": 80, + "src_port": "3T", + "dst_port": "3R", + "local_peer_port": "3R", + "remote_peer_port": "3T", + "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] + }, + "d2-2": { + "length": 80, + "src_port": "4T", + "dst_port": "4R", + "local_peer_port": "4R", + "remote_peer_port": "4T", + "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] + } + } + }, + "r3-r2": { + "length": 80, + "source" : "d2", + "target" : "d2", + "fibers" : { + "d2-1": { + "length": 80, + "src_port": "3T", + "dst_port": "3R", + "local_peer_port": "3R", + "remote_peer_port": "3T", + "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] + }, + "d2-2":{ + "length": 80, + "src_port": "4T", + "dst_port": "4R", + "local_peer_port": "4R", + "remote_peer_port": "4T", + "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] + } + } + }, + "t1-r1": { + "length": 0, + "source" : "muxT", + "target" : "srgR", + "fibers" : { + "M1": { + "length": 0, + "src_port": "1", + "dst_port": "101R", + "local_peer_port": "1", + "remote_peer_port": "101T", + "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] + }, + "M2": { + "length": 0, + "src_port": "2", + "dst_port": "102R", + "local_peer_port": "2", + "remote_peer_port": "102T", + "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] + }, + "M3": { + "length": 0, + "src_port": "3", + "dst_port": "103R", + "local_peer_port": "3", + "remote_peer_port": "103T", + "used": false, + "c_slots": [], + "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] + } + } + }, + "r1-t1": { + "length": 0, + "source" : "srgT", + "target" : "muxR", + "fibers" : { + "S1": { + "length": 0, + "src_port": "101T", + "dst_port": "1", + "local_peer_port": "101R", + "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] + }, + "S2": { + "length": 0, + "src_port": "102T", + "dst_port": "2", + "local_peer_port": "102T", + "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] + }, + "S3": { + "length": 0, + "src_port": "103T", + "dst_port": "3", + "local_peer_port": "103R", + "remote_peer_port": "3", + "used": false, + "c_slots": [], + "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] + } + } + }, + "t2-r2": { + "length": 0, + "source" : "muxT", + "target" : "srgR", + "fibers" : { + "M1": { + "length": 0, + "src_port": "1", + "dst_port": "101R", + "local_peer_port": "1", + "remote_peer_port": "101T", + "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] + }, + "M2": { + "length": 0, + "src_port": "2", + "dst_port": "102R", + "local_peer_port": "2", + "remote_peer_port": "102T", + "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] + }, + "M3": { + "length": 0, + "src_port": "3", + "dst_port": "103R", + "local_peer_port": "3", + "remote_peer_port": "103T", + "used": false, + "c_slots": [], + "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] + } + } + }, + "r2-t2": { + "length": 0, + "source" : "srgT", + "target" : "muxR", + "fibers" : { + "S1": { + "length": 0, + "src_port": "101T", + "dst_port": "1", + "local_peer_port": "101R", + "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] + }, + "S2": { + "length": 0, + "src_port": "102T", + "dst_port": "2", + "local_peer_port": "102R", + "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] + }, + "S3": { + "length": 0, + "src_port": "103T", + "dst_port": "3", + "local_peer_port": "103R", + "remote_peer_port": "3", + "used": false, + "c_slots": [], + "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/requirements.in b/src/opticalcontroller/requirements.in new file mode 100644 index 000000000..e4b8abe1b --- /dev/null +++ b/src/opticalcontroller/requirements.in @@ -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/tools.py b/src/opticalcontroller/tools.py new file mode 100644 index 000000000..d91240d45 --- /dev/null +++ b/src/opticalcontroller/tools.py @@ -0,0 +1,175 @@ +import numpy as np +from variables import * +import json + + +def common_slots(a, b): + return list(np.intersect1d(a, b)) + + +def map_modulation_to_op(mod): + if mod == "DP-QPSK": + return 1 + if mod == "DP-16QAM": + return 7 + if mod == "DP-64QAM": + return 10 + + +def map_band_to_slot(band): + return int(band/12.5) + + +def map_rate_to_slot(rate): + if rate == 100: + mod = "DP-QPSK" + slots = 4 + op = map_modulation_to_op(mod) + return op, slots + if rate == 400: + mod = "DP-16QAM" + slots = 8 + op = map_modulation_to_op(mod) + return op, slots + if rate == 1000: + mod = "DP-64QAM" + slots = 18 + op = map_modulation_to_op(mod) + return op, slots + else: + return 2, 5 + + +def consecutives(x, val): + res = [] + temp = [] + x.sort() + temp.append(x[0]) + y = 1 + for i in range(1, len(x)): + if x[i] == x[i - 1] + 1: + y += 1 + temp.append(x[i]) + else: + if y >= val: + res.extend(temp) + temp = [x[i]] + y = 1 + if i == len(x) - 1 and y >= val: + res.extend(temp) + return res + + +def combine(ls1, ls2): + temp = ls1 + for i in ls2: + if i not in ls1: + temp.append(i) + temp.sort() + return temp + + +def list_in_list(a, b): + # convert list A to numpy array + a_arr = np.array(a) + # convert list B to numpy array + b_arr = np.array(b) + + for i in range(len(b_arr)): + if np.array_equal(a_arr, b_arr[i:i + len(a_arr)]): + return True + return False + + +def reverse_link(link): + s, d = link.split('-') + r_link = "{}-{}".format(d, s) + return r_link + + +def get_slot_frequency(b, n): + if debug: + print(n) + if b == "c_slots": + return Fc + n * 12.5 + if b == "s_slots": + return Fs + n * 12.5 + if b == "l_slots": + return Fl + n * 12.5 + + +def freqency_converter(b, slots): + l = len(slots) + if debug: + print(slots) + if l % 2 == 0: + if debug: + print("pari {}".format(l)) + fx = get_slot_frequency(b, slots[int(l / 2)-1]) + if debug: + print(fx) + #GHz + # #f0 = fx + 6.25 + #MHz + f0 = int((fx + 6.25) * 1000) + else: + f0 = get_slot_frequency(b, slots[int((l + 1) / 2) - 1]) + #GHz + # #return f0, 12.5 * l + # MHz + return f0, int((12.5 * l) * 1000) + + +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) + nodes_file.close() + topo_file.close() + return nodes, topo + + +def reverse_links(links): + temp_links = links.copy() + temp_links.reverse() + result = [] + for link in temp_links: + [a, b] = link.split("-") + 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 + 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 + return result + + +def slot_selection(c, l, s, n_slots, Nc, Nl, Ns): + # First Fit + if isinstance(n_slots, int): + slot_c = n_slots + slot_l = n_slots + slot_s = n_slots + else: + slot_c = Nc + slot_l = Nl + slot_s = Ns + if len(c) >= slot_c: + return "c_slots", c[0: slot_c] + elif len(l) >= slot_l: + return "l_slots", l[0: slot_l] + elif len(l) >= 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 new file mode 100644 index 000000000..32fe4bd8d --- /dev/null +++ b/src/opticalcontroller/variables.py @@ -0,0 +1,18 @@ +debug = 1 + +Fl = 184800 +Fc = 192000 +Fs = 196200 + +Nl = 550 +Nc = 320 +#Nc = 10 +Ns = 720 + +nodes_json = 'json_files/nodes.json' +topology_json = 'json_files/tfs.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' + +testing = 1 -- GitLab