Merge remote-tracking branch 'origin/develop'

This commit is contained in:
Jan Kundrát
2019-11-13 19:59:35 +01:00
17 changed files with 1607 additions and 735 deletions

1
.bandit Normal file
View File

@@ -0,0 +1 @@
skips: ['B101']

View File

@@ -2,8 +2,8 @@
"path-request": [
{
"request-id": "0",
"source": "Lorient_KMA",
"destination": "Vannes_KBE",
"source": "trx Lorient_KMA",
"destination": "trx Vannes_KBE",
"src-tp-id": "trx Lorient_KMA",
"dst-tp-id": "trx Vannes_KBE",
"path-constraints": {
@@ -13,8 +13,8 @@
"trx_mode": null,
"effective-freq-slot": [
{
"n": "null",
"m": "null"
"N": "null",
"M": "null"
}
],
"spacing": 50000000000.0,
@@ -22,15 +22,12 @@
"output-power": 0.0012589254117941673,
"path_bandwidth": 100000000000.0
}
},
"optimizations": {
"explicit-route-include-objects": []
}
},
{
"request-id": "1",
"source": "Brest_KLA",
"destination": "Vannes_KBE",
"source": "trx Brest_KLA",
"destination": "trx Vannes_KBE",
"src-tp-id": "trx Brest_KLA",
"dst-tp-id": "trx Vannes_KBE",
"path-constraints": {
@@ -40,8 +37,8 @@
"trx_mode": "mode 1",
"effective-freq-slot": [
{
"n": "null",
"m": "null"
"N": "null",
"M": "null"
}
],
"spacing": 50000000000.0,
@@ -50,66 +47,42 @@
"path_bandwidth": 200000000000.0
}
},
"optimizations": {
"explicit-route-include-objects": [
"explicit-route-objects": {
"route-object-include-exclude": [
{
"explicit-route-usage": "route-include-ero",
"index": 0,
"unnumbered-hop": {
"num-unnum-hop": {
"node-id": "roadm Brest_KLA",
"link-tp-id": "link-tp-id is not used",
"hop-type": "loose",
"direction": "direction is not used"
},
"label-hop": {
"te-label": {
"generic": "generic is not used",
"direction": "direction is not used"
}
"hop-type": "LOOSE"
}
},
{
"explicit-route-usage": "route-include-ero",
"index": 1,
"unnumbered-hop": {
"num-unnum-hop": {
"node-id": "roadm Lannion_CAS",
"link-tp-id": "link-tp-id is not used",
"hop-type": "loose",
"direction": "direction is not used"
},
"label-hop": {
"te-label": {
"generic": "generic is not used",
"direction": "direction is not used"
}
"hop-type": "LOOSE"
}
},
{
"explicit-route-usage": "route-include-ero",
"index": 2,
"unnumbered-hop": {
"num-unnum-hop": {
"node-id": "roadm Lorient_KMA",
"link-tp-id": "link-tp-id is not used",
"hop-type": "loose",
"direction": "direction is not used"
},
"label-hop": {
"te-label": {
"generic": "generic is not used",
"direction": "direction is not used"
}
"hop-type": "LOOSE"
}
},
{
"explicit-route-usage": "route-include-ero",
"index": 3,
"unnumbered-hop": {
"num-unnum-hop": {
"node-id": "roadm Vannes_KBE",
"link-tp-id": "link-tp-id is not used",
"hop-type": "loose",
"direction": "direction is not used"
},
"label-hop": {
"te-label": {
"generic": "generic is not used",
"direction": "direction is not used"
}
"hop-type": "LOOSE"
}
}
]
@@ -117,8 +90,8 @@
},
{
"request-id": "3",
"source": "Lannion_CAS",
"destination": "Rennes_STA",
"source": "trx Lannion_CAS",
"destination": "trx Rennes_STA",
"src-tp-id": "trx Lannion_CAS",
"dst-tp-id": "trx Rennes_STA",
"path-constraints": {
@@ -128,8 +101,8 @@
"trx_mode": "mode 1",
"effective-freq-slot": [
{
"n": "null",
"m": "null"
"N": "null",
"M": "null"
}
],
"spacing": 50000000000.0,
@@ -137,15 +110,12 @@
"output-power": null,
"path_bandwidth": 60000000000.0
}
},
"optimizations": {
"explicit-route-include-objects": []
}
},
{
"request-id": "4",
"source": "Rennes_STA",
"destination": "Lannion_CAS",
"source": "trx Rennes_STA",
"destination": "trx Lannion_CAS",
"src-tp-id": "trx Rennes_STA",
"dst-tp-id": "trx Lannion_CAS",
"path-constraints": {
@@ -155,8 +125,8 @@
"trx_mode": null,
"effective-freq-slot": [
{
"n": "null",
"m": "null"
"N": "null",
"M": "null"
}
],
"spacing": 75000000000.0,
@@ -164,15 +134,12 @@
"output-power": 0.0019952623149688794,
"path_bandwidth": 150000000000.0
}
},
"optimizations": {
"explicit-route-include-objects": []
}
},
{
"request-id": "5",
"source": "Rennes_STA",
"destination": "Lannion_CAS",
"source": "trx Rennes_STA",
"destination": "trx Lannion_CAS",
"src-tp-id": "trx Rennes_STA",
"dst-tp-id": "trx Lannion_CAS",
"path-constraints": {
@@ -182,8 +149,8 @@
"trx_mode": "mode 2",
"effective-freq-slot": [
{
"n": "null",
"m": "null"
"N": "null",
"M": "null"
}
],
"spacing": 75000000000.0,
@@ -191,15 +158,12 @@
"output-power": 0.0019952623149688794,
"path_bandwidth": 20000000000.0
}
},
"optimizations": {
"explicit-route-include-objects": []
}
},
{
"request-id": "6",
"source": "Lannion_CAS",
"destination": "Lorient_KMA",
"source": "trx Lannion_CAS",
"destination": "trx Lorient_KMA",
"src-tp-id": "trx Lannion_CAS",
"dst-tp-id": "trx Lorient_KMA",
"path-constraints": {
@@ -209,8 +173,8 @@
"trx_mode": "mode 1",
"effective-freq-slot": [
{
"n": "null",
"m": "null"
"N": "null",
"M": "null"
}
],
"spacing": 50000000000.0,
@@ -218,15 +182,12 @@
"output-power": 0.001,
"path_bandwidth": 300000000000.0
}
},
"optimizations": {
"explicit-route-include-objects": []
}
},
{
"request-id": "7",
"source": "Lannion_CAS",
"destination": "Lorient_KMA",
"source": "trx Lannion_CAS",
"destination": "trx Lorient_KMA",
"src-tp-id": "trx Lannion_CAS",
"dst-tp-id": "trx Lorient_KMA",
"path-constraints": {
@@ -236,8 +197,8 @@
"trx_mode": "mode 1",
"effective-freq-slot": [
{
"n": "null",
"m": "null"
"N": "null",
"M": "null"
}
],
"spacing": 50000000000.0,
@@ -245,15 +206,12 @@
"output-power": 0.001,
"path_bandwidth": 400000000000.0
}
},
"optimizations": {
"explicit-route-include-objects": []
}
},
{
"request-id": "7b",
"source": "Lannion_CAS",
"destination": "Lorient_KMA",
"source": "trx Lannion_CAS",
"destination": "trx Lorient_KMA",
"src-tp-id": "trx Lannion_CAS",
"dst-tp-id": "trx Lorient_KMA",
"path-constraints": {
@@ -263,8 +221,8 @@
"trx_mode": "mode 1",
"effective-freq-slot": [
{
"n": "null",
"m": "null"
"N": "null",
"M": "null"
}
],
"spacing": 75000000000.0,
@@ -272,9 +230,6 @@
"output-power": 0.001,
"path_bandwidth": 400000000000.0
}
},
"optimizations": {
"explicit-route-include-objects": []
}
}
],
@@ -282,9 +237,8 @@
{
"synchronization-id": "3",
"svec": {
"relaxable": "False",
"link-diverse": "True",
"node-diverse": "True",
"relaxable": "false",
"disjointness": "node link",
"request-id-number": [
"3",
"1"
@@ -294,9 +248,8 @@
{
"synchronization-id": "4",
"svec": {
"relaxable": "False",
"link-diverse": "True",
"node-diverse": "True",
"relaxable": "false",
"disjointness": "node link",
"request-id-number": [
"4",
"5"

View File

@@ -55,16 +55,18 @@ def requests_from_json(json_data,equipment):
# init all params from request
params = {}
params['request_id'] = req['request-id']
params['source'] = req['src-tp-id']
params['destination'] = req['dst-tp-id']
params['source'] = req['source']
params['destination'] = req['destination']
params['trx_type'] = req['path-constraints']['te-bandwidth']['trx_type']
params['trx_mode'] = req['path-constraints']['te-bandwidth']['trx_mode']
params['format'] = params['trx_mode']
nd_list = req['optimizations']['explicit-route-include-objects']
params['nodes_list'] = [n['unnumbered-hop']['node-id'] for n in nd_list]
params['loose_list'] = [n['unnumbered-hop']['hop-type'] for n in nd_list]
params['spacing'] = req['path-constraints']['te-bandwidth']['spacing']
try :
nd_list = req['explicit-route-objects']['route-object-include-exclude']
except KeyError:
nd_list = []
params['nodes_list'] = [n['num-unnum-hop']['node-id'] for n in nd_list]
params['loose_list'] = [n['num-unnum-hop']['hop-type'] for n in nd_list]
# recover trx physical param (baudrate, ...) from type and mode
# in trx_mode_params optical power is read from equipment['SI']['default'] and
# nb_channel is computed based on min max frequency and spacing
@@ -73,20 +75,24 @@ def requests_from_json(json_data,equipment):
# print(trx_params['min_spacing'])
# optical power might be set differently in the request. if it is indicated then the
# params['power'] is updated
if req['path-constraints']['te-bandwidth']['output-power']:
params['power'] = req['path-constraints']['te-bandwidth']['output-power']
try:
if req['path-constraints']['te-bandwidth']['output-power']:
params['power'] = req['path-constraints']['te-bandwidth']['output-power']
except KeyError:
pass
# same process for nb-channel
f_min = params['f_min']
f_max_from_si = params['f_max']
if req['path-constraints']['te-bandwidth']['max-nb-of-channel'] is not None :
nch = req['path-constraints']['te-bandwidth']['max-nb-of-channel']
params['nb_channel'] = nch
spacing = params['spacing']
params['f_max'] = f_min + nch*spacing
else :
try:
if req['path-constraints']['te-bandwidth']['max-nb-of-channel'] is not None:
nch = req['path-constraints']['te-bandwidth']['max-nb-of-channel']
params['nb_channel'] = nch
spacing = params['spacing']
params['f_max'] = f_min + nch*spacing
else :
params['nb_channel'] = automatic_nch(f_min,f_max_from_si,params['spacing'])
except KeyError:
params['nb_channel'] = automatic_nch(f_min,f_max_from_si,params['spacing'])
consistency_check(params, f_max_from_si)
try :
@@ -122,15 +128,20 @@ def consistency_check(params, f_max_from_si):
def disjunctions_from_json(json_data):
disjunctions_list = []
try:
temp_test = json_data['synchronization']
except KeyError:
temp_test = []
if temp_test:
for snc in json_data['synchronization']:
params = {}
params['disjunction_id'] = snc['synchronization-id']
params['relaxable'] = snc['svec']['relaxable']
params['link_diverse'] = 'link' in snc['svec']['disjointness']
params['node_diverse'] = 'node' in snc['svec']['disjointness']
params['disjunctions_req'] = snc['svec']['request-id-number']
disjunctions_list.append(Disjunction(**params))
for snc in json_data['synchronization']:
params = {}
params['disjunction_id'] = snc['synchronization-id']
params['relaxable'] = snc['svec']['relaxable']
params['link_diverse'] = snc['svec']['link-diverse']
params['node_diverse'] = snc['svec']['node-diverse']
params['disjunctions_req'] = snc['svec']['request-id-number']
disjunctions_list.append(Disjunction(**params))
return disjunctions_list
@@ -205,7 +216,7 @@ def correct_route_list(network, pathreqlist):
# prepares the format of route list of nodes to be consistant
# remove wrong names, remove endpoints
# also correct source and destination
anytype = [n.uid for n in network.nodes() if not isinstance(n, Transceiver) and not isinstance(n, Fiber)]
anytype = [n.uid for n in network.nodes()]
# TODO there is a problem of identification of fibers in case of parallel fibers bitween two adjacent roadms
# so fiber constraint is not supported
transponders = [n.uid for n in network.nodes() if isinstance(n, Transceiver)]
@@ -214,9 +225,11 @@ def correct_route_list(network, pathreqlist):
# replace possibly wrong name with a formated roadm name
# print(n_id)
if n_id not in anytype :
# find nodes name that include constraint among all possible names except
# transponders (not yet supported as constraints).
nodes_suggestion = [uid for uid in anytype \
if n_id.lower() in uid.lower()]
if pathreq.loose_list[i] == 'loose':
if n_id.lower() in uid.lower() and uid not in transponders]
if pathreq.loose_list[i] == 'LOOSE':
if len(nodes_suggestion)>0 :
new_n = nodes_suggestion[0]
print(f'invalid route node specified:\
@@ -257,7 +270,7 @@ def correct_disjn(disjn):
def path_result_json(pathresult):
data = {
'path': [n.json for n in pathresult]
'response': [n.json for n in pathresult]
}
return data

View File

@@ -157,11 +157,13 @@ def main(network, equipment, source, destination, sim_params, req=None):
if len(power_range) == 1:
for elem in path:
print(elem)
if power_mode:
print(f'\nTransmission result for input power = {lin2db(req.power*1e3):.2f} dBm:')
if power_mode:
print(f'\nTransmission result for input power = {lin2db(req.power*1e3):.2f} dBm:')
else:
print(f'\nTransmission results:')
print(f' Final SNR total (0.1 nm): {ansi_escapes.cyan}{mean(destination.snr_01nm):.02f} dB{ansi_escapes.reset}')
else:
print(f'\nTransmission results:')
print(f' Final SNR total (signal bw): {ansi_escapes.cyan}{mean(destination.snr):.02f} dB{ansi_escapes.reset}')
print(path[-1])
#print(f'\n !!!!!!!!!!!!!!!!! TEST POINT !!!!!!!!!!!!!!!!!!!!!')
#print(f'carriers ase output of {path[1]} =\n {list(path[1].carriers("out", "nli"))}')

View File

@@ -25,7 +25,7 @@ from collections import namedtuple
from gnpy.core.node import Node
from gnpy.core.units import UNITS
from gnpy.core.utils import lin2db, db2lin, itufs, itufl, snr_sum
from gnpy.core.utils import lin2db, db2lin, arrange_frequencies, snr_sum
from gnpy.core.science_utils import propagate_raman_fiber, _psi
class Transceiver(Node):
@@ -615,7 +615,7 @@ class Edfa(Node):
self.channel_freq, self.nf, self.interpol_dgt and self.interpol_gain_ripple
"""
# TODO|jla: read amplifier actual frequencies from additional params in json
amplifier_freq = itufl(len(self.params.dgt), self.params.f_min, self.params.f_max) # Hz
amplifier_freq = arrange_frequencies(len(self.params.dgt), self.params.f_min, self.params.f_max) # Hz
self.channel_freq = frequencies
self.interpol_dgt = interp(self.channel_freq, amplifier_freq, self.params.dgt)

View File

@@ -81,9 +81,9 @@ class Path_request:
f'baud_rate:\t{temp} Gbaud',
f'bit_rate:\t{temp2} Gb/s',
f'spacing:\t{self.spacing * 1e-9} GHz',
f'power: \t{round(lin2db(self.power)+30,2)} dBm',
f'power: \t{round(lin2db(self.power)+30, 2)} dBm',
f'nb channels: \t{self.nb_channel}',
f'path_bandwidth: \t{round(self.path_bandwidth * 1e-9,2)} Gbit/s',
f'path_bandwidth: \t{round(self.path_bandwidth * 1e-9, 2)} Gbit/s',
f'nodes-list:\t{self.nodes_list}',
f'loose-list:\t{self.loose_list}'
'\n'])
@@ -97,16 +97,16 @@ class Disjunction:
self.disjunctions_req = params.disjunctions_req
def __str__(self):
return '\n\t'.join([f'relaxable: {self.relaxable}',
f'link-diverse: {self.link_diverse}',
return '\n\t'.join([f'relaxable: {self.relaxable}',
f'link-diverse: {self.link_diverse}',
f'node-diverse: {self.node_diverse}',
f'request-id-numbers: {self.disjunctions_req}']
)
def __repr__(self):
return '\n\t'.join([ f'{type(self).__name__} {self.disjunction_id}',
f'relaxable: {self.relaxable}',
f'link-diverse: {self.link_diverse}',
f'node-diverse: {self.node_diverse}',
f'link-diverse: {self.link_diverse}',
f'node-diverse: {self.node_diverse}',
f'request-id-numbers: {self.disjunctions_req}'
'\n'])
@@ -115,149 +115,77 @@ class Result_element(Element):
self.path_id = path_request.request_id
self.path_request = path_request
self.computed_path = computed_path
hop_type = []
if len(computed_path)>0 :
for e in computed_path :
if isinstance(e, Transceiver) :
hop_type.append(' - '.join([path_request.tsp,path_request.tsp_mode]))
else:
hop_type.append('not recorded')
else:
# TODO differentiate empty path in case not feasible because of tsp or not feasible because
# ther is no path connecting the nodes (whatever the tsp)
mode = 'not feasible with this transponder'
hop_type = ' - '.join([path_request.tsp,mode])
self.hop_type = hop_type
uid = property(lambda self: repr(self))
@property
def pathresult(self):
if not self.computed_path:
return {
'path-id': self.path_id,
'path-properties':{
'path-metric': [
{
'metric-type': 'SNR@bandwidth',
'accumulative-value': 'None'
},
{
'metric-type': 'SNR@0.1nm',
'accumulative-value': 'None'
},
{
'metric-type': 'OSNR@bandwidth',
'accumulative-value': 'None'
},
{
'metric-type': 'OSNR@0.1nm',
'accumulative-value': 'None'
},
{
'metric-type': 'reference_power',
'accumulative-value': self.path_request.power
},
{
'metric-type': 'path_bandwidth',
'accumulative-value': self.path_request.path_bandwidth
}
],
'path-srlgs': {
'usage': 'not used yet',
'values': 'not used yet'
},
'path-route-objects': [
{
'path-route-object': {
'index': 0,
'unnumbered-hop': {
'node-id': self.path_request.source,
'link-tp-id': self.path_request.source,
'hop-type': self.hop_type,
'direction': 'not used'
},
'label-hop': {
'te-label': {
'generic': 'not used yet',
'direction': 'not used yet'
}
}
}
},
{
'path-route-object': {
'index': 1,
'unnumbered-hop': {
'node-id': self.path_request.destination,
'link-tp-id': self.path_request.destination,
'hop-type': self.hop_type,
'direction': 'not used'
},
'label-hop': {
'te-label': {
'generic': 'not used yet',
'direction': 'not used yet'
}
}
'response-id': self.path_id,
'no-path': "Response without path information, due to failure performing the path computation"
}
else:
index = 0
pro_list = []
for element in self.computed_path:
temp = {
'path-route-object': {
'index': index,
'num-unnum-hop': {
'node-id': element.uid,
'link-tp-id': element.uid,
# TODO change index in order to insert transponder attribute
}
}
}
pro_list.append(temp)
index += 1
if isinstance(element, Transceiver):
temp = {
'path-route-object': {
'index': index,
'transponder' : {
'transponder-type' : self.path_request.tsp,
'transponder-mode' : self.path_request.tsp_mode,
}
}
]
}
}
else:
return {
'path-id': self.path_id,
'path-properties':{
'path-metric': [
{
'metric-type': 'SNR@bandwidth',
'accumulative-value': round(mean(self.computed_path[-1].snr),2)
},
{
'metric-type': 'SNR@0.1nm',
'accumulative-value': round(mean(self.computed_path[-1].snr+lin2db(self.path_request.baud_rate/12.5e9)),2)
},
{
'metric-type': 'OSNR@bandwidth',
'accumulative-value': round(mean(self.computed_path[-1].osnr_ase),2)
},
{
'metric-type': 'OSNR@0.1nm',
'accumulative-value': round(mean(self.computed_path[-1].osnr_ase_01nm),2)
},
{
'metric-type': 'reference_power',
'accumulative-value': self.path_request.power
},
{
'metric-type': 'path_bandwidth',
'accumulative-value': self.path_request.path_bandwidth
}
],
'path-srlgs': {
'usage': 'not used yet',
'values': 'not used yet'
}
pro_list.append(temp)
index += 1
response = {
'response-id': self.path_id,
'path-properties':{
'path-metric': [
{
'metric-type': 'SNR-bandwidth',
'accumulative-value': round(mean(self.computed_path[-1].snr), 2)
},
'path-route-objects': [
{
'path-route-object': {
'index': self.computed_path.index(n),
'unnumbered-hop': {
'node-id': n.uid,
'link-tp-id': n.uid,
'hop-type': self.hop_type[self.computed_path.index(n)],
'direction': 'not used'
},
'label-hop': {
'te-label': {
'generic': 'not used yet',
'direction': 'not used yet'
}
}
}
} for n in self.computed_path
]
{
'metric-type': 'SNR-0.1nm',
'accumulative-value': round(mean(self.computed_path[-1]. snr + \
lin2db(self.path_request.baud_rate/12.5e9)), 2)
},
{
'metric-type': 'OSNR-bandwidth',
'accumulative-value': round(mean(self.computed_path[-1].osnr_ase), 2)
},
{
'metric-type': 'OSNR-0.1nm',
'accumulative-value': round(mean(self.computed_path[-1].osnr_ase_01nm), 2)
},
{
'metric-type': 'reference_power',
'accumulative-value': self.path_request.power
},
{
'metric-type': 'path_bandwidth',
'accumulative-value': self.path_request.path_bandwidth
}
],
'path-route-objects': pro_list
}
}
return response
@property
def json(self):
@@ -304,7 +232,7 @@ def compute_constrained_path(network, req):
msg = f'\x1b[1;33;40m'+f'Request {req.request_id} could not find a path from {source.uid} to node : {destination.uid} in network topology'+ '\x1b[0m'
logger.critical(msg)
print(msg)
total_path = []
total_path = []
else :
all_simp_pths = list(all_simple_paths(network,source=source,\
target=destination, cutoff=120))
@@ -319,12 +247,26 @@ def compute_constrained_path(network, req):
candidate.sort(key=lambda x: sum(network.get_edge_data(x[i],x[i+1])['weight'] for i in range(len(x)-2)))
total_path = candidate[0]
else:
if req.loose_list[req.nodes_list.index(n)] == 'loose':
print(f'\x1b[1;33;40m'+f'Request {req.request_id} could not find a path crossing {nodes_list} in network topology'+ '\x1b[0m')
# TODO: better account for individual loose and strict node
# to ease: suppose that one strict makes the whole liste strict (except for the
# last node which is the transceiver)
# if all nodes i n node_list are LOOSE constraint, skip the constraints and find
# a path w/o constraints, else there is no possible path
if nodes_list[:-len("STRICT")]:
print(f'\x1b[1;33;40m'+f'Request {req.request_id} could not find a path crossing ' +\
f'{[el.uid for el in nodes_list[:-len("STRICT")]]} in network topology'+ '\x1b[0m')
else:
print(f'\x1b[1;33;40m'+f'User include_node constraints could not be applied ' +\
f'(invalid names specified)'+ '\x1b[0m')
if 'STRICT' not in req.loose_list[:-len('STRICT')]:
msg = f'\x1b[1;33;40m'+f'Request {req.request_id} could not find a path with user_' +\
f'include node constraints' + '\x1b[0m'
logger.info(msg)
print(f'constraint ignored')
total_path = dijkstra_path(network, source, destination, weight = 'weight')
else:
msg = f'\x1b[1;33;40m'+f'Request {req.request_id} could not find a path crossing {nodes_list}.\nNo path computed'+ '\x1b[0m'
msg = f'\x1b[1;33;40m'+f'Request {req.request_id} could not find a path with user ' +\
f'include node constraints.\nNo path computed'+ '\x1b[0m'
logger.critical(msg)
print(msg)
total_path = []
@@ -418,7 +360,7 @@ def propagate_and_optimize_mode(path, req, equipment):
# if mode is unknown : loops on the modes starting from the highest baudrate fiting in the
# step 1: create an ordered list of modes based on baudrate
baudrate_to_explore = list(set([m['baud_rate'] for m in equipment['Transceiver'][req.tsp].mode
if float(m['min_spacing'])<= req.spacing]))
if float(m['min_spacing'])<= req.spacing]))
# TODO be carefull on limits cases if spacing very close to req spacing eg 50.001 50.000
baudrate_to_explore = sorted(baudrate_to_explore, reverse=True)
if baudrate_to_explore :
@@ -468,65 +410,91 @@ def jsontocsv(json_data,equipment,fileout):
# and write results in an CSV file
mywriter = writer(fileout)
mywriter.writerow(('path-id','source','destination','path_bandwidth','Pass?',\
mywriter.writerow(('response-id','source','destination','path_bandwidth','Pass?',\
'nb of tsp pairs','total cost','transponder-type','transponder-mode',\
'OSNR@0.1nm','SNR@0.1nm','SNR@bandwidth','baud rate (Gbaud)',\
'OSNR-0.1nm','SNR-0.1nm','SNR-bandwidth','baud rate (Gbaud)',\
'input power (dBm)','path'))
tspjsondata = equipment['Transceiver']
#print(tspjsondata)
for p in json_data['path']:
path_id = p['path-id']
source = p['path-properties']['path-route-objects'][0]\
['path-route-object']['unnumbered-hop']['node-id']
destination = p['path-properties']['path-route-objects'][-1]\
['path-route-object']['unnumbered-hop']['node-id']
# selects only roadm nodes
pth = ' | '.join([ e['path-route-object']['unnumbered-hop']['node-id']
for e in p['path-properties']['path-route-objects']
if e['path-route-object']['unnumbered-hop']['node-id'].startswith('roadm') or e['path-route-object']['unnumbered-hop']['node-id'].startswith('Edfa')])
[tsp,mode] = p['path-properties']['path-route-objects'][0]\
['path-route-object']['unnumbered-hop']['hop-type'].split(' - ')
for pth_el in json_data['response']:
path_id = pth_el['response-id']
try:
if pth_el['no-path'] :
source = ''
destination = ''
tsp = ''
mode = ''
isok = False
nb_tsp = 0
pthbdbw = ''
rosnr = ''
rsnr = ''
rsnrb = ''
br = ''
pw = ''
total_cost = ''
pth = ''
except KeyError:
source = pth_el['path-properties']['path-route-objects'][0]\
['path-route-object']['num-unnum-hop']['node-id']
destination = pth_el['path-properties']['path-route-objects'][-2]\
['path-route-object']['num-unnum-hop']['node-id']
# selects only roadm nodes
temp = []
for e in pth_el['path-properties']['path-route-objects']:
try :
temp.append(e['path-route-object']['num-unnum-hop']['node-id'])
except KeyError:
pass
pth = ' | '.join(temp)
temp_tsp = pth_el['path-properties']['path-route-objects'][1]\
['path-route-object']['transponder']
tsp = temp_tsp['transponder-type']
mode = temp_tsp['transponder-mode']
# find the min acceptable OSNR, baud rate from the eqpt library based on tsp (tupe) and mode (format)
# loading equipment already tests the existence of tsp type and mode:
if mode !='not feasible with this transponder' :
[minosnr, baud_rate, bit_rate, cost] = next([m['OSNR'] , m['baud_rate'] , m['bit_rate'], m['cost']]
for m in equipment['Transceiver'][tsp].mode if m['format']==mode)
# else:
# [minosnr, baud_rate, bit_rate] = ['','','','']
output_snr = next(e['accumulative-value']
for e in pth_el['path-properties']['path-metric'] if e['metric-type'] == 'SNR-0.1nm')
output_snrbandwidth = next(e['accumulative-value']
for e in pth_el['path-properties']['path-metric'] if e['metric-type'] == 'SNR-bandwidth')
output_osnr = next(e['accumulative-value']
for e in pth_el['path-properties']['path-metric'] if e['metric-type'] == 'OSNR-0.1nm')
output_osnrbandwidth = next(e['accumulative-value']
for e in pth_el['path-properties']['path-metric'] if e['metric-type'] == 'OSNR-bandwidth')
power = next(e['accumulative-value']
for e in pth_el['path-properties']['path-metric'] if e['metric-type'] == 'reference_power')
path_bandwidth = next(e['accumulative-value']
for e in pth_el['path-properties']['path-metric'] if e['metric-type'] == 'path_bandwidth')
if isinstance(output_snr, str):
isok = False
nb_tsp = 0
pthbdbw = round(path_bandwidth*1e-9,2)
rosnr = ''
rsnr = ''
rsnrb = ''
br = ''
pw = ''
total_cost = ''
else:
isok = output_snr >= minosnr
nb_tsp = ceil(path_bandwidth / bit_rate)
pthbdbw = round(path_bandwidth*1e-9,2)
rosnr = round(output_osnr,2)
rsnr = round(output_snr,2)
rsnrb = round(output_snrbandwidth,2)
br = round(baud_rate*1e-9,2)
pw = round(lin2db(power)+30,2)
total_cost = nb_tsp * cost
# find the min acceptable OSNR, baud rate from the eqpt library based on tsp (tupe) and mode (format)
# loading equipment already tests the existence of tsp type and mode:
if mode !='not feasible with this transponder' :
[minosnr, baud_rate, bit_rate, cost] = next([m['OSNR'] , m['baud_rate'] , m['bit_rate'], m['cost']]
for m in equipment['Transceiver'][tsp].mode if m['format']==mode)
# else:
# [minosnr, baud_rate, bit_rate] = ['','','','']
output_snr = next(e['accumulative-value']
for e in p['path-properties']['path-metric'] if e['metric-type'] == 'SNR@0.1nm')
output_snrbandwidth = next(e['accumulative-value']
for e in p['path-properties']['path-metric'] if e['metric-type'] == 'SNR@bandwidth')
output_osnr = next(e['accumulative-value']
for e in p['path-properties']['path-metric'] if e['metric-type'] == 'OSNR@0.1nm')
output_osnrbandwidth = next(e['accumulative-value']
for e in p['path-properties']['path-metric'] if e['metric-type'] == 'OSNR@bandwidth')
power = next(e['accumulative-value']
for e in p['path-properties']['path-metric'] if e['metric-type'] == 'reference_power')
path_bandwidth = next(e['accumulative-value']
for e in p['path-properties']['path-metric'] if e['metric-type'] == 'path_bandwidth')
if isinstance(output_snr, str):
isok = False
nb_tsp = 0
pthbdbw = round(path_bandwidth*1e-9,2)
rosnr = ''
rsnr = ''
rsnrb = ''
br = ''
pw = ''
total_cost = ''
else:
isok = output_snr >= minosnr
nb_tsp = ceil(path_bandwidth / bit_rate)
pthbdbw = round(path_bandwidth*1e-9,2)
rosnr = round(output_osnr,2)
rsnr = round(output_snr,2)
rsnrb = round(output_snrbandwidth,2)
br = round(baud_rate*1e-9,2)
pw = round(lin2db(power)+30,2)
total_cost = nb_tsp * cost
mywriter.writerow((path_id,
source,
destination,
@@ -617,7 +585,7 @@ def compute_path_dsjctn(network, equipment, pathreqlist, disjunctions_list):
all_simp_pths_reversed = []
for pth in all_simp_pths:
all_simp_pths_reversed.append(find_reversed_path(pth,network))
rqs[pathreq.request_id] = all_simp_pths
rqs[pathreq.request_id] = all_simp_pths
temp =[]
for p in all_simp_pths :
# build a short list representing each roadm+direction with the first item
@@ -759,9 +727,10 @@ def compute_path_dsjctn(network, equipment, pathreqlist, disjunctions_list):
testispartok = False
#break
else:
if 'loose' in allpaths[id(p)].req.loose_list:
if 'LOOSE' in allpaths[id(p)].req.loose_list:
logger.info(f'Could not apply route constraint'+
f'{allpaths[id(p)].req.nodes_list} on request {allpaths[id(p)].req.request_id}')
f'{allpaths[id(p)].req.nodes_list} on request' +\
f' {allpaths[id(p)].req.request_id}')
else :
logger.info(f'removing last solution from candidate paths\n{sol}')
testispartok = False
@@ -798,7 +767,7 @@ def compute_path_dsjctn(network, equipment, pathreqlist, disjunctions_list):
for req in pathreqlist :
req.nodes_list.append(req.destination)
# we assume that the destination is a strict constraint
req.loose_list.append('strict')
req.loose_list.append('STRICT')
if req in pathreqlist_simple:
path_res_list.append(compute_constrained_path(network, req))
else:
@@ -890,19 +859,19 @@ def compare_reqs(req1,req2,disjlist) :
req1.format == req2.format and \
req1.OSNR == req2.OSNR and \
req1.roll_off == req2.roll_off and \
same_disj :
same_disj:
return True
else:
return False
def requests_aggregation(pathreqlist,disjlist) :
def requests_aggregation(pathreqlist,disjlist):
# this function aggregates requests so that if several requests
# exist between same source and destination and with same transponder type
# todo maybe add conditions on mode ??, spacing ...
# currently if undefined takes the default values
local_list = pathreqlist.copy()
for req in pathreqlist:
for r in local_list :
for r in local_list:
if req.request_id != r.request_id and compare_reqs(req, r, disjlist):
# aggregate
r.path_bandwidth += req.path_bandwidth
@@ -912,12 +881,12 @@ def requests_aggregation(pathreqlist,disjlist) :
local_list.remove(req)
# todo change also disjunction req with new demand
for d in disjlist :
if req.request_id in d.disjunctions_req :
for d in disjlist:
if req.request_id in d.disjunctions_req:
d.disjunctions_req.remove(req.request_id)
d.disjunctions_req.append(r.request_id)
for d in disjlist :
if temp_r_id in d.disjunctions_req :
for d in disjlist:
if temp_r_id in d.disjunctions_req:
disjlist.remove(d)
break
return local_list, disjlist

View File

@@ -48,8 +48,8 @@ class Request_element(Element):
# excel has automatic number formatting that adds .0 on integer values
# the next lines recover the pure int value, assuming this .0 is unwanted
self.request_id = correct_xlrd_int_to_str_reading(Request.request_id)
self.source = Request.source
self.destination = Request.destination
self.source = f'trx {Request.source}'
self.destination = f'trx {Request.destination}'
# TODO: the automatic naming generated by excel parser requires that source and dest name
# be a string starting with 'trx' : this is manually added here.
self.srctpid = f'trx {Request.source}'
@@ -120,9 +120,9 @@ class Request_element(Element):
# the excel parser applies the same hop-type to all nodes in the route nodes_list.
# user can change this per node in the generated json
self.loose = 'loose'
self.loose = 'LOOSE'
if Request.is_loose == 'no' :
self.loose = 'strict'
self.loose = 'STRICT'
self.path_bandwidth = None
if Request.path_bandwidth is not None:
self.path_bandwidth = Request.path_bandwidth * 1e9
@@ -132,6 +132,7 @@ class Request_element(Element):
uid = property(lambda self: repr(self))
@property
def pathrequest(self):
req_dictionnary = {
'request-id':self.request_id,
'source': self.source,
@@ -143,35 +144,28 @@ class Request_element(Element):
'technology': 'flexi-grid',
'trx_type' : self.trx_type,
'trx_mode' : self.mode,
'effective-freq-slot':[{'n': 'null','m': 'null'}] ,
'effective-freq-slot':[{'N': 'null', 'M': 'null'}],
'spacing' : self.spacing,
'max-nb-of-channel' : self.nb_channel,
'output-power' : self.power
# 'path_bandwidth' : self.path_bandwidth
}
},
'optimizations': {
'explicit-route-include-objects': [
{
'index': self.nodes_list.index(node),
'unnumbered-hop':{
'node-id': f'{node}',
'link-tp-id': 'link-tp-id is not used',
'hop-type': f'{self.loose}',
'direction': 'direction is not used'
},
'label-hop':{
'te-label': {
'generic': 'generic is not used',
'direction': 'direction is not used'
}
}
}
if self.nodes_list:
req_dictionnary['explicit-route-objects'] = {}
temp = {'route-object-include-exclude' : [
{'explicit-route-usage': 'route-include-ero',
'index': self.nodes_list.index(node),
'num-unnum-hop': {
'node-id': f'{node}',
'link-tp-id': 'link-tp-id is not used',
'hop-type': f'{self.loose}',
}
}
for node in self.nodes_list
]
}
}
for node in self.nodes_list]
}
req_dictionnary['explicit-route-objects'] = temp
if self.path_bandwidth is not None:
req_dictionnary['path-constraints']['te-bandwidth']['path_bandwidth'] = self.path_bandwidth
@@ -181,12 +175,13 @@ class Request_element(Element):
if self.disjoint_from :
return {'synchronization-id':self.request_id,
'svec': {
'relaxable' : 'False',
'link-diverse': 'True',
'node-diverse': 'True',
'relaxable' : 'false',
'disjointness': 'node link',
'request-id-number': [self.request_id]+ [n for n in self.disjoint_from]
}
}
else:
return None
# TO-DO: avoid multiple entries with same synchronisation vectors
@property
def json(self):
@@ -201,11 +196,17 @@ def convert_service_sheet(input_filename, eqpt_filename, output_filename='', fil
output_filename = f'{str(input_filename)[0:len(str(input_filename))-len(str(input_filename.suffixes[0]))]}_services.json'
# for debug
# print(json_filename)
data = {
'path-request': [n.json[0] for n in req],
'synchronization': [n.json[1] for n in req
if n.json[1] is not None]
}
# if there is no sync vector , do not write any synchronization
synchro = [n.json[1] for n in req if n.json[1] is not None]
if synchro:
data = {
'path-request': [n.json[0] for n in req],
'synchronization': synchro
}
else:
data = {
'path-request': [n.json[0] for n in req]
}
with open(output_filename, 'w', encoding='utf-8') as f:
f.write(dumps(data, indent=2, ensure_ascii=False))
return data

View File

@@ -73,35 +73,19 @@ def c():
return constants.c
def itufs(spacing, startf=191.35, stopf=196.10):
"""Creates an array of frequencies whose default range is
191.35-196.10 THz
:param spacing: Frequency spacing in THz
:param starf: Start frequency in THz
:param stopf: Stop frequency in THz
:type spacing: float
:type startf: float
:type stopf: float
:return an array of frequnecies determined by the spacing parameter
:rtype: numpy.ndarray
"""
return np.arange(startf, stopf + spacing / 2, spacing)
def itufl(length, startf=191.35, stopf=196.10):
"""Creates an array of frequencies whose default range is
191.35-196.10 THz
def arrange_frequencies(length, start, stop):
"""Create an array of frequencies
:param length: number of elements
:param starf: Start frequency in THz
:param stopf: Stop frequency in THz
:param star: Start frequency in THz
:param stop: Stop frequency in THz
:type length: integer
:type startf: float
:type stopf: float
:return an array of frequnecies determined by the spacing parameter
:type start: float
:type stop: float
:return an array of frequencies determined by the spacing parameter
:rtype: numpy.ndarray
"""
return np.linspace(startf, stopf, length)
return np.linspace(start, stop, length)
def h():
"""

View File

@@ -1,39 +1,63 @@
{
"paths": [
"response": [
{
"path": {
"path-id": null,
"path-properties": {
"path-metric": [
{
"metric-type": null,
"accumulative-value": null
}
],
"path-srlgs": {
"usage": "not used yet",
"values": ["not used yet"]
"response-id": null,
"path-properties": {
"path-metric": [
{
"metric-type": "SNR@bandwidth",
"accumulative-value": null
},
"path-route-objects": [
{
"path-route-object": {
"index": null,
"unnumbered-hop": {
"node-id": null,
"link-tp-id": null,
"hop-type": null,
"direction": "not used"
},
"label-hop": {
"te-label": {
"generic": "not used yet",
"direction": "not used yet"
}
}
{
"metric-type": "SNR@0.1nm",
"accumulative-value": null
},
{
"metric-type": "OSNR@bandwidth",
"accumulative-value": null
},
{
"metric-type": "OSNR@0.1nm",
"accumulative-value": null
},
{
"metric-type": "reference_power",
"accumulative-value": null
},
{
"metric-type": "path_bandwidth",
"accumulative-value": null
}
],
"path-route-objects": [
{
"path-route-object": {
"index": 0,
"num-unnum-hop": {
"node-id": null,
"link-tp-id": null
}
}
]
}
},
{
"path-route-object": {
"index": 1,
"transponder": {
"transponder-type": null,
"transponder-mode": null
}
}
},
{
"path-route-object": {
"index": 2,
"num-unnum-hop": {
"node-id": null,
"link-tp-id": null
}
}
}
]
}
}
]

View File

@@ -2,6 +2,7 @@ alabaster>=0.7.12,<1
matplotlib>=3.1.0,<4
networkx>=2.3,<3
numpy>=1.16.1,<2
pandas==0.24.2
Pygments>=2.4.2,<3
pytest>=4.0.0,<5
scipy>=1.3.0,<2

View File

@@ -6,6 +6,44 @@
"destination": null,
"src-tp-id": null,
"dst-tp-id": null,
"explicit-route-objects": {
"route-object-include-exclude": [
{
"explicit-route-usage": null,
"index": null,
"num-unnum-hop": {
"node-id": null,
"link-tp-id": null,
"hop-type": null
}
},
{
"explicit-route-usage": null,
"index": null,
"label-hop": {
"N": null,
"M": null
}
},
{
"explicit-route-usage": null,
"index": null,
"transponder": {
"transponder-type": null,
"transponder-mode": null
}
},
{
"explicit-route-usage": null,
"index": null,
"regenerator": {
"regenerator-id": null,
"transponder-type": null,
"transponder-mode": null
}
}
]
},
"path-constraints": {
"te-bandwidth": {
"technology": "flexi-grid",
@@ -22,27 +60,6 @@
"output-power": null,
"path_bandwidth": null
}
},
"optimizations": {
"explicit-route-include-objects": {
"route-object-include-object": [
{
"index": null,
"unnumbered-hop": {
"node-id": null,
"link-tp-id": "link-tp-id is not used",
"hop-type": null,
"direction": "direction is not used"
},
"label-hop": {
"te-label": {
"generic": "generic is not used",
"direction": "direction is not used"
}
}
}
]
}
}
}],
"synchronization": [
@@ -50,10 +67,9 @@
"synchronization-id": null,
"svec": {
"relaxable": "True",
"link-diverse": "False",
"node-diverse": "False",
"disjointness": "node link",
"request-id-number": [
null ]
null, null ]
},
}
]

Binary file not shown.

View File

@@ -0,0 +1,866 @@
{
"response": [
{
"response-id": "0",
"path-properties": {
"path-metric": [
{
"metric-type": "SNR-bandwidth",
"accumulative-value": 26.75
},
{
"metric-type": "SNR-0.1nm",
"accumulative-value": 30.84
},
{
"metric-type": "OSNR-bandwidth",
"accumulative-value": 26.76
},
{
"metric-type": "OSNR-0.1nm",
"accumulative-value": 30.84
},
{
"metric-type": "reference_power",
"accumulative-value": 0.001
},
{
"metric-type": "path_bandwidth",
"accumulative-value": 100000000000.0
}
],
"path-route-objects": [
{
"path-route-object": {
"index": 0,
"num-unnum-hop": {
"node-id": "trx Lorient_KMA",
"link-tp-id": "trx Lorient_KMA"
}
}
},
{
"path-route-object": {
"index": 1,
"transponder": {
"transponder-type": "Voyager",
"transponder-mode": "mode 1"
}
}
},
{
"path-route-object": {
"index": 2,
"num-unnum-hop": {
"node-id": "roadm Lorient_KMA",
"link-tp-id": "roadm Lorient_KMA"
}
}
},
{
"path-route-object": {
"index": 3,
"num-unnum-hop": {
"node-id": "Edfa1_roadm Lorient_KMA",
"link-tp-id": "Edfa1_roadm Lorient_KMA"
}
}
},
{
"path-route-object": {
"index": 4,
"num-unnum-hop": {
"node-id": "fiber (Lorient_KMA → Vannes_KBE)-F055",
"link-tp-id": "fiber (Lorient_KMA → Vannes_KBE)-F055"
}
}
},
{
"path-route-object": {
"index": 5,
"num-unnum-hop": {
"node-id": "Edfa0_fiber (Lorient_KMA → Vannes_KBE)-F055",
"link-tp-id": "Edfa0_fiber (Lorient_KMA → Vannes_KBE)-F055"
}
}
},
{
"path-route-object": {
"index": 6,
"num-unnum-hop": {
"node-id": "roadm Vannes_KBE",
"link-tp-id": "roadm Vannes_KBE"
}
}
},
{
"path-route-object": {
"index": 7,
"num-unnum-hop": {
"node-id": "trx Vannes_KBE",
"link-tp-id": "trx Vannes_KBE"
}
}
},
{
"path-route-object": {
"index": 8,
"transponder": {
"transponder-type": "Voyager",
"transponder-mode": "mode 1"
}
}
}
]
}
},
{
"response-id": "1",
"path-properties": {
"path-metric": [
{
"metric-type": "SNR-bandwidth",
"accumulative-value": 18.03
},
{
"metric-type": "SNR-0.1nm",
"accumulative-value": 22.11
},
{
"metric-type": "OSNR-bandwidth",
"accumulative-value": 18.57
},
{
"metric-type": "OSNR-0.1nm",
"accumulative-value": 22.65
},
{
"metric-type": "reference_power",
"accumulative-value": 0.0012589254117941673
},
{
"metric-type": "path_bandwidth",
"accumulative-value": 0
}
],
"path-route-objects": [
{
"path-route-object": {
"index": 0,
"num-unnum-hop": {
"node-id": "trx Brest_KLA",
"link-tp-id": "trx Brest_KLA"
}
}
},
{
"path-route-object": {
"index": 1,
"transponder": {
"transponder-type": "Voyager",
"transponder-mode": "mode 1"
}
}
},
{
"path-route-object": {
"index": 2,
"num-unnum-hop": {
"node-id": "roadm Brest_KLA",
"link-tp-id": "roadm Brest_KLA"
}
}
},
{
"path-route-object": {
"index": 3,
"num-unnum-hop": {
"node-id": "Edfa0_roadm Brest_KLA",
"link-tp-id": "Edfa0_roadm Brest_KLA"
}
}
},
{
"path-route-object": {
"index": 4,
"num-unnum-hop": {
"node-id": "fiber (Brest_KLA → Morlaix)-F060",
"link-tp-id": "fiber (Brest_KLA → Morlaix)-F060"
}
}
},
{
"path-route-object": {
"index": 5,
"num-unnum-hop": {
"node-id": "east fused spans in Morlaix",
"link-tp-id": "east fused spans in Morlaix"
}
}
},
{
"path-route-object": {
"index": 6,
"num-unnum-hop": {
"node-id": "fiber (Morlaix → Lannion_CAS)-F059",
"link-tp-id": "fiber (Morlaix → Lannion_CAS)-F059"
}
}
},
{
"path-route-object": {
"index": 7,
"num-unnum-hop": {
"node-id": "west edfa in Lannion_CAS to Morlaix",
"link-tp-id": "west edfa in Lannion_CAS to Morlaix"
}
}
},
{
"path-route-object": {
"index": 8,
"num-unnum-hop": {
"node-id": "roadm Lannion_CAS",
"link-tp-id": "roadm Lannion_CAS"
}
}
},
{
"path-route-object": {
"index": 9,
"num-unnum-hop": {
"node-id": "east edfa in Lannion_CAS to Corlay",
"link-tp-id": "east edfa in Lannion_CAS to Corlay"
}
}
},
{
"path-route-object": {
"index": 10,
"num-unnum-hop": {
"node-id": "fiber (Lannion_CAS → Corlay)-F061",
"link-tp-id": "fiber (Lannion_CAS → Corlay)-F061"
}
}
},
{
"path-route-object": {
"index": 11,
"num-unnum-hop": {
"node-id": "west fused spans in Corlay",
"link-tp-id": "west fused spans in Corlay"
}
}
},
{
"path-route-object": {
"index": 12,
"num-unnum-hop": {
"node-id": "fiber (Corlay → Loudeac)-F010",
"link-tp-id": "fiber (Corlay → Loudeac)-F010"
}
}
},
{
"path-route-object": {
"index": 13,
"num-unnum-hop": {
"node-id": "west fused spans in Loudeac",
"link-tp-id": "west fused spans in Loudeac"
}
}
},
{
"path-route-object": {
"index": 14,
"num-unnum-hop": {
"node-id": "fiber (Loudeac → Lorient_KMA)-F054",
"link-tp-id": "fiber (Loudeac → Lorient_KMA)-F054"
}
}
},
{
"path-route-object": {
"index": 15,
"num-unnum-hop": {
"node-id": "Edfa0_fiber (Loudeac → Lorient_KMA)-F054",
"link-tp-id": "Edfa0_fiber (Loudeac → Lorient_KMA)-F054"
}
}
},
{
"path-route-object": {
"index": 16,
"num-unnum-hop": {
"node-id": "roadm Lorient_KMA",
"link-tp-id": "roadm Lorient_KMA"
}
}
},
{
"path-route-object": {
"index": 17,
"num-unnum-hop": {
"node-id": "Edfa1_roadm Lorient_KMA",
"link-tp-id": "Edfa1_roadm Lorient_KMA"
}
}
},
{
"path-route-object": {
"index": 18,
"num-unnum-hop": {
"node-id": "fiber (Lorient_KMA → Vannes_KBE)-F055",
"link-tp-id": "fiber (Lorient_KMA → Vannes_KBE)-F055"
}
}
},
{
"path-route-object": {
"index": 19,
"num-unnum-hop": {
"node-id": "Edfa0_fiber (Lorient_KMA → Vannes_KBE)-F055",
"link-tp-id": "Edfa0_fiber (Lorient_KMA → Vannes_KBE)-F055"
}
}
},
{
"path-route-object": {
"index": 20,
"num-unnum-hop": {
"node-id": "roadm Vannes_KBE",
"link-tp-id": "roadm Vannes_KBE"
}
}
},
{
"path-route-object": {
"index": 21,
"num-unnum-hop": {
"node-id": "trx Vannes_KBE",
"link-tp-id": "trx Vannes_KBE"
}
}
},
{
"path-route-object": {
"index": 22,
"transponder": {
"transponder-type": "Voyager",
"transponder-mode": "mode 1"
}
}
}
]
}
},
{
"response-id": "3",
"path-properties": {
"path-metric": [
{
"metric-type": "SNR-bandwidth",
"accumulative-value": 21.77
},
{
"metric-type": "SNR-0.1nm",
"accumulative-value": 25.85
},
{
"metric-type": "OSNR-bandwidth",
"accumulative-value": 24.2
},
{
"metric-type": "OSNR-0.1nm",
"accumulative-value": 28.29
},
{
"metric-type": "reference_power",
"accumulative-value": 0.0012589254117941673
},
{
"metric-type": "path_bandwidth",
"accumulative-value": 60000000000.0
}
],
"path-route-objects": [
{
"path-route-object": {
"index": 0,
"num-unnum-hop": {
"node-id": "trx Lannion_CAS",
"link-tp-id": "trx Lannion_CAS"
}
}
},
{
"path-route-object": {
"index": 1,
"transponder": {
"transponder-type": "vendorA_trx-type1",
"transponder-mode": "mode 1"
}
}
},
{
"path-route-object": {
"index": 2,
"num-unnum-hop": {
"node-id": "roadm Lannion_CAS",
"link-tp-id": "roadm Lannion_CAS"
}
}
},
{
"path-route-object": {
"index": 3,
"num-unnum-hop": {
"node-id": "east edfa in Lannion_CAS to Stbrieuc",
"link-tp-id": "east edfa in Lannion_CAS to Stbrieuc"
}
}
},
{
"path-route-object": {
"index": 4,
"num-unnum-hop": {
"node-id": "fiber (Lannion_CAS → Stbrieuc)-F056",
"link-tp-id": "fiber (Lannion_CAS → Stbrieuc)-F056"
}
}
},
{
"path-route-object": {
"index": 5,
"num-unnum-hop": {
"node-id": "east edfa in Stbrieuc to Rennes_STA",
"link-tp-id": "east edfa in Stbrieuc to Rennes_STA"
}
}
},
{
"path-route-object": {
"index": 6,
"num-unnum-hop": {
"node-id": "fiber (Stbrieuc → Rennes_STA)-F057",
"link-tp-id": "fiber (Stbrieuc → Rennes_STA)-F057"
}
}
},
{
"path-route-object": {
"index": 7,
"num-unnum-hop": {
"node-id": "Edfa0_fiber (Stbrieuc → Rennes_STA)-F057",
"link-tp-id": "Edfa0_fiber (Stbrieuc → Rennes_STA)-F057"
}
}
},
{
"path-route-object": {
"index": 8,
"num-unnum-hop": {
"node-id": "roadm Rennes_STA",
"link-tp-id": "roadm Rennes_STA"
}
}
},
{
"path-route-object": {
"index": 9,
"num-unnum-hop": {
"node-id": "trx Rennes_STA",
"link-tp-id": "trx Rennes_STA"
}
}
},
{
"path-route-object": {
"index": 10,
"transponder": {
"transponder-type": "vendorA_trx-type1",
"transponder-mode": "mode 1"
}
}
}
]
}
},
{
"response-id": "4",
"path-properties": {
"path-metric": [
{
"metric-type": "SNR-bandwidth",
"accumulative-value": 15.05
},
{
"metric-type": "SNR-0.1nm",
"accumulative-value": 22.15
},
{
"metric-type": "OSNR-bandwidth",
"accumulative-value": 15.18
},
{
"metric-type": "OSNR-0.1nm",
"accumulative-value": 22.27
},
{
"metric-type": "reference_power",
"accumulative-value": 0.001
},
{
"metric-type": "path_bandwidth",
"accumulative-value": 150000000000.0
}
],
"path-route-objects": [
{
"path-route-object": {
"index": 0,
"num-unnum-hop": {
"node-id": "trx Rennes_STA",
"link-tp-id": "trx Rennes_STA"
}
}
},
{
"path-route-object": {
"index": 1,
"transponder": {
"transponder-type": "vendorA_trx-type1",
"transponder-mode": "mode 2"
}
}
},
{
"path-route-object": {
"index": 2,
"num-unnum-hop": {
"node-id": "roadm Rennes_STA",
"link-tp-id": "roadm Rennes_STA"
}
}
},
{
"path-route-object": {
"index": 3,
"num-unnum-hop": {
"node-id": "Edfa1_roadm Rennes_STA",
"link-tp-id": "Edfa1_roadm Rennes_STA"
}
}
},
{
"path-route-object": {
"index": 4,
"num-unnum-hop": {
"node-id": "fiber (Rennes_STA → Ploermel)-",
"link-tp-id": "fiber (Rennes_STA → Ploermel)-"
}
}
},
{
"path-route-object": {
"index": 5,
"num-unnum-hop": {
"node-id": "east edfa in Ploermel to Vannes_KBE",
"link-tp-id": "east edfa in Ploermel to Vannes_KBE"
}
}
},
{
"path-route-object": {
"index": 6,
"num-unnum-hop": {
"node-id": "fiber (Ploermel → Vannes_KBE)-",
"link-tp-id": "fiber (Ploermel → Vannes_KBE)-"
}
}
},
{
"path-route-object": {
"index": 7,
"num-unnum-hop": {
"node-id": "Edfa0_fiber (Ploermel → Vannes_KBE)-",
"link-tp-id": "Edfa0_fiber (Ploermel → Vannes_KBE)-"
}
}
},
{
"path-route-object": {
"index": 8,
"num-unnum-hop": {
"node-id": "roadm Vannes_KBE",
"link-tp-id": "roadm Vannes_KBE"
}
}
},
{
"path-route-object": {
"index": 9,
"num-unnum-hop": {
"node-id": "Edfa0_roadm Vannes_KBE",
"link-tp-id": "Edfa0_roadm Vannes_KBE"
}
}
},
{
"path-route-object": {
"index": 10,
"num-unnum-hop": {
"node-id": "fiber (Vannes_KBE → Lorient_KMA)-F055",
"link-tp-id": "fiber (Vannes_KBE → Lorient_KMA)-F055"
}
}
},
{
"path-route-object": {
"index": 11,
"num-unnum-hop": {
"node-id": "Edfa0_fiber (Vannes_KBE → Lorient_KMA)-F055",
"link-tp-id": "Edfa0_fiber (Vannes_KBE → Lorient_KMA)-F055"
}
}
},
{
"path-route-object": {
"index": 12,
"num-unnum-hop": {
"node-id": "roadm Lorient_KMA",
"link-tp-id": "roadm Lorient_KMA"
}
}
},
{
"path-route-object": {
"index": 13,
"num-unnum-hop": {
"node-id": "Edfa0_roadm Lorient_KMA",
"link-tp-id": "Edfa0_roadm Lorient_KMA"
}
}
},
{
"path-route-object": {
"index": 14,
"num-unnum-hop": {
"node-id": "fiber (Lorient_KMA → Loudeac)-F054",
"link-tp-id": "fiber (Lorient_KMA → Loudeac)-F054"
}
}
},
{
"path-route-object": {
"index": 15,
"num-unnum-hop": {
"node-id": "east fused spans in Loudeac",
"link-tp-id": "east fused spans in Loudeac"
}
}
},
{
"path-route-object": {
"index": 16,
"num-unnum-hop": {
"node-id": "fiber (Loudeac → Corlay)-F010",
"link-tp-id": "fiber (Loudeac → Corlay)-F010"
}
}
},
{
"path-route-object": {
"index": 17,
"num-unnum-hop": {
"node-id": "east fused spans in Corlay",
"link-tp-id": "east fused spans in Corlay"
}
}
},
{
"path-route-object": {
"index": 18,
"num-unnum-hop": {
"node-id": "fiber (Corlay → Lannion_CAS)-F061",
"link-tp-id": "fiber (Corlay → Lannion_CAS)-F061"
}
}
},
{
"path-route-object": {
"index": 19,
"num-unnum-hop": {
"node-id": "west edfa in Lannion_CAS to Corlay",
"link-tp-id": "west edfa in Lannion_CAS to Corlay"
}
}
},
{
"path-route-object": {
"index": 20,
"num-unnum-hop": {
"node-id": "roadm Lannion_CAS",
"link-tp-id": "roadm Lannion_CAS"
}
}
},
{
"path-route-object": {
"index": 21,
"num-unnum-hop": {
"node-id": "trx Lannion_CAS",
"link-tp-id": "trx Lannion_CAS"
}
}
},
{
"path-route-object": {
"index": 22,
"transponder": {
"transponder-type": "vendorA_trx-type1",
"transponder-mode": "mode 2"
}
}
}
]
}
},
{
"response-id": "5",
"path-properties": {
"path-metric": [
{
"metric-type": "SNR-bandwidth",
"accumulative-value": 21.68
},
{
"metric-type": "SNR-0.1nm",
"accumulative-value": 28.77
},
{
"metric-type": "OSNR-bandwidth",
"accumulative-value": 23.7
},
{
"metric-type": "OSNR-0.1nm",
"accumulative-value": 30.79
},
{
"metric-type": "reference_power",
"accumulative-value": 0.0019952623149688794
},
{
"metric-type": "path_bandwidth",
"accumulative-value": 20000000000.0
}
],
"path-route-objects": [
{
"path-route-object": {
"index": 0,
"num-unnum-hop": {
"node-id": "trx Rennes_STA",
"link-tp-id": "trx Rennes_STA"
}
}
},
{
"path-route-object": {
"index": 1,
"transponder": {
"transponder-type": "vendorA_trx-type1",
"transponder-mode": "mode 2"
}
}
},
{
"path-route-object": {
"index": 2,
"num-unnum-hop": {
"node-id": "roadm Rennes_STA",
"link-tp-id": "roadm Rennes_STA"
}
}
},
{
"path-route-object": {
"index": 3,
"num-unnum-hop": {
"node-id": "Edfa0_roadm Rennes_STA",
"link-tp-id": "Edfa0_roadm Rennes_STA"
}
}
},
{
"path-route-object": {
"index": 4,
"num-unnum-hop": {
"node-id": "fiber (Rennes_STA → Stbrieuc)-F057",
"link-tp-id": "fiber (Rennes_STA → Stbrieuc)-F057"
}
}
},
{
"path-route-object": {
"index": 5,
"num-unnum-hop": {
"node-id": "Edfa0_fiber (Rennes_STA → Stbrieuc)-F057",
"link-tp-id": "Edfa0_fiber (Rennes_STA → Stbrieuc)-F057"
}
}
},
{
"path-route-object": {
"index": 6,
"num-unnum-hop": {
"node-id": "fiber (Stbrieuc → Lannion_CAS)-F056",
"link-tp-id": "fiber (Stbrieuc → Lannion_CAS)-F056"
}
}
},
{
"path-route-object": {
"index": 7,
"num-unnum-hop": {
"node-id": "Edfa0_fiber (Stbrieuc → Lannion_CAS)-F056",
"link-tp-id": "Edfa0_fiber (Stbrieuc → Lannion_CAS)-F056"
}
}
},
{
"path-route-object": {
"index": 8,
"num-unnum-hop": {
"node-id": "roadm Lannion_CAS",
"link-tp-id": "roadm Lannion_CAS"
}
}
},
{
"path-route-object": {
"index": 9,
"num-unnum-hop": {
"node-id": "trx Lannion_CAS",
"link-tp-id": "trx Lannion_CAS"
}
}
},
{
"path-route-object": {
"index": 10,
"transponder": {
"transponder-type": "vendorA_trx-type1",
"transponder-mode": "mode 2"
}
}
}
]
}
},
{
"response-id": "6",
"no-path": "Response without path information, due to failure performing the path computation"
}
]
}

View File

@@ -0,0 +1,7 @@
response-id,source,destination,path_bandwidth,Pass?,nb of tsp pairs,total cost,transponder-type,transponder-mode,OSNR-0.1nm,SNR-0.1nm,SNR-bandwidth,baud rate (Gbaud),input power (dBm),path
0,trx Lorient_KMA,trx Vannes_KBE,100.0,True,1,1,Voyager,mode 1,30.84,30.84,26.75,32.0,0.0,trx Lorient_KMA | roadm Lorient_KMA | Edfa1_roadm Lorient_KMA | fiber (Lorient_KMA → Vannes_KBE)-F055 | Edfa0_fiber (Lorient_KMA → Vannes_KBE)-F055 | roadm Vannes_KBE | trx Vannes_KBE
1,trx Brest_KLA,trx Vannes_KBE,0.0,True,0,0,Voyager,mode 1,22.65,22.11,18.03,32.0,1.0,trx Brest_KLA | roadm Brest_KLA | Edfa0_roadm Brest_KLA | fiber (Brest_KLA → Morlaix)-F060 | east fused spans in Morlaix | fiber (Morlaix → Lannion_CAS)-F059 | west edfa in Lannion_CAS to Morlaix | roadm Lannion_CAS | east edfa in Lannion_CAS to Corlay | fiber (Lannion_CAS → Corlay)-F061 | west fused spans in Corlay | fiber (Corlay → Loudeac)-F010 | west fused spans in Loudeac | fiber (Loudeac → Lorient_KMA)-F054 | Edfa0_fiber (Loudeac → Lorient_KMA)-F054 | roadm Lorient_KMA | Edfa1_roadm Lorient_KMA | fiber (Lorient_KMA → Vannes_KBE)-F055 | Edfa0_fiber (Lorient_KMA → Vannes_KBE)-F055 | roadm Vannes_KBE | trx Vannes_KBE
3,trx Lannion_CAS,trx Rennes_STA,60.0,True,1,1,vendorA_trx-type1,mode 1,28.29,25.85,21.77,32.0,1.0,trx Lannion_CAS | roadm Lannion_CAS | east edfa in Lannion_CAS to Stbrieuc | fiber (Lannion_CAS → Stbrieuc)-F056 | east edfa in Stbrieuc to Rennes_STA | fiber (Stbrieuc → Rennes_STA)-F057 | Edfa0_fiber (Stbrieuc → Rennes_STA)-F057 | roadm Rennes_STA | trx Rennes_STA
4,trx Rennes_STA,trx Lannion_CAS,150.0,True,1,1,vendorA_trx-type1,mode 2,22.27,22.15,15.05,64.0,0.0,trx Rennes_STA | roadm Rennes_STA | Edfa1_roadm Rennes_STA | fiber (Rennes_STA → Ploermel)- | east edfa in Ploermel to Vannes_KBE | fiber (Ploermel → Vannes_KBE)- | Edfa0_fiber (Ploermel → Vannes_KBE)- | roadm Vannes_KBE | Edfa0_roadm Vannes_KBE | fiber (Vannes_KBE → Lorient_KMA)-F055 | Edfa0_fiber (Vannes_KBE → Lorient_KMA)-F055 | roadm Lorient_KMA | Edfa0_roadm Lorient_KMA | fiber (Lorient_KMA → Loudeac)-F054 | east fused spans in Loudeac | fiber (Loudeac → Corlay)-F010 | east fused spans in Corlay | fiber (Corlay → Lannion_CAS)-F061 | west edfa in Lannion_CAS to Corlay | roadm Lannion_CAS | trx Lannion_CAS
5,trx Rennes_STA,trx Lannion_CAS,20.0,True,1,1,vendorA_trx-type1,mode 2,30.79,28.77,21.68,64.0,3.0,trx Rennes_STA | roadm Rennes_STA | Edfa0_roadm Rennes_STA | fiber (Rennes_STA → Stbrieuc)-F057 | Edfa0_fiber (Rennes_STA → Stbrieuc)-F057 | fiber (Stbrieuc → Lannion_CAS)-F056 | Edfa0_fiber (Stbrieuc → Lannion_CAS)-F056 | roadm Lannion_CAS | trx Lannion_CAS
6,,,,False,0,,,,,,,,,
1 response-id source destination path_bandwidth Pass? nb of tsp pairs total cost transponder-type transponder-mode OSNR-0.1nm SNR-0.1nm SNR-bandwidth baud rate (Gbaud) input power (dBm) path
2 0 trx Lorient_KMA trx Vannes_KBE 100.0 True 1 1 Voyager mode 1 30.84 30.84 26.75 32.0 0.0 trx Lorient_KMA | roadm Lorient_KMA | Edfa1_roadm Lorient_KMA | fiber (Lorient_KMA → Vannes_KBE)-F055 | Edfa0_fiber (Lorient_KMA → Vannes_KBE)-F055 | roadm Vannes_KBE | trx Vannes_KBE
3 1 trx Brest_KLA trx Vannes_KBE 0.0 True 0 0 Voyager mode 1 22.65 22.11 18.03 32.0 1.0 trx Brest_KLA | roadm Brest_KLA | Edfa0_roadm Brest_KLA | fiber (Brest_KLA → Morlaix)-F060 | east fused spans in Morlaix | fiber (Morlaix → Lannion_CAS)-F059 | west edfa in Lannion_CAS to Morlaix | roadm Lannion_CAS | east edfa in Lannion_CAS to Corlay | fiber (Lannion_CAS → Corlay)-F061 | west fused spans in Corlay | fiber (Corlay → Loudeac)-F010 | west fused spans in Loudeac | fiber (Loudeac → Lorient_KMA)-F054 | Edfa0_fiber (Loudeac → Lorient_KMA)-F054 | roadm Lorient_KMA | Edfa1_roadm Lorient_KMA | fiber (Lorient_KMA → Vannes_KBE)-F055 | Edfa0_fiber (Lorient_KMA → Vannes_KBE)-F055 | roadm Vannes_KBE | trx Vannes_KBE
4 3 trx Lannion_CAS trx Rennes_STA 60.0 True 1 1 vendorA_trx-type1 mode 1 28.29 25.85 21.77 32.0 1.0 trx Lannion_CAS | roadm Lannion_CAS | east edfa in Lannion_CAS to Stbrieuc | fiber (Lannion_CAS → Stbrieuc)-F056 | east edfa in Stbrieuc to Rennes_STA | fiber (Stbrieuc → Rennes_STA)-F057 | Edfa0_fiber (Stbrieuc → Rennes_STA)-F057 | roadm Rennes_STA | trx Rennes_STA
5 4 trx Rennes_STA trx Lannion_CAS 150.0 True 1 1 vendorA_trx-type1 mode 2 22.27 22.15 15.05 64.0 0.0 trx Rennes_STA | roadm Rennes_STA | Edfa1_roadm Rennes_STA | fiber (Rennes_STA → Ploermel)- | east edfa in Ploermel to Vannes_KBE | fiber (Ploermel → Vannes_KBE)- | Edfa0_fiber (Ploermel → Vannes_KBE)- | roadm Vannes_KBE | Edfa0_roadm Vannes_KBE | fiber (Vannes_KBE → Lorient_KMA)-F055 | Edfa0_fiber (Vannes_KBE → Lorient_KMA)-F055 | roadm Lorient_KMA | Edfa0_roadm Lorient_KMA | fiber (Lorient_KMA → Loudeac)-F054 | east fused spans in Loudeac | fiber (Loudeac → Corlay)-F010 | east fused spans in Corlay | fiber (Corlay → Lannion_CAS)-F061 | west edfa in Lannion_CAS to Corlay | roadm Lannion_CAS | trx Lannion_CAS
6 5 trx Rennes_STA trx Lannion_CAS 20.0 True 1 1 vendorA_trx-type1 mode 2 30.79 28.77 21.68 64.0 3.0 trx Rennes_STA | roadm Rennes_STA | Edfa0_roadm Rennes_STA | fiber (Rennes_STA → Stbrieuc)-F057 | Edfa0_fiber (Rennes_STA → Stbrieuc)-F057 | fiber (Stbrieuc → Lannion_CAS)-F056 | Edfa0_fiber (Stbrieuc → Lannion_CAS)-F056 | roadm Lannion_CAS | trx Lannion_CAS
7 6 False 0

View File

@@ -2,8 +2,8 @@
"path-request": [
{
"request-id": "0",
"source": "Lorient_KMA",
"destination": "Vannes_KBE",
"source": "trx Lorient_KMA",
"destination": "trx Vannes_KBE",
"src-tp-id": "trx Lorient_KMA",
"dst-tp-id": "trx Vannes_KBE",
"path-constraints": {
@@ -13,8 +13,8 @@
"trx_mode": "mode 1",
"effective-freq-slot": [
{
"n": "null",
"m": "null"
"N": "null",
"M": "null"
}
],
"spacing": 50000000000.0,
@@ -22,15 +22,12 @@
"output-power": null,
"path_bandwidth": 100000000000.0
}
},
"optimizations": {
"explicit-route-include-objects": []
}
},
{
"request-id": "1",
"source": "Brest_KLA",
"destination": "Vannes_KBE",
"source": "trx Brest_KLA",
"destination": "trx Vannes_KBE",
"src-tp-id": "trx Brest_KLA",
"dst-tp-id": "trx Vannes_KBE",
"path-constraints": {
@@ -40,8 +37,8 @@
"trx_mode": "mode 1",
"effective-freq-slot": [
{
"n": "null",
"m": "null"
"N": "null",
"M": "null"
}
],
"spacing": 50000000000.0,
@@ -50,66 +47,42 @@
"path_bandwidth": 0
}
},
"optimizations": {
"explicit-route-include-objects": [
"explicit-route-objects": {
"route-object-include-exclude": [
{
"explicit-route-usage": "route-include-ero",
"index": 0,
"unnumbered-hop": {
"num-unnum-hop": {
"node-id": "roadm Brest_KLA",
"link-tp-id": "link-tp-id is not used",
"hop-type": "loose",
"direction": "direction is not used"
},
"label-hop": {
"te-label": {
"generic": "generic is not used",
"direction": "direction is not used"
}
"hop-type": "LOOSE"
}
},
{
"explicit-route-usage": "route-include-ero",
"index": 1,
"unnumbered-hop": {
"num-unnum-hop": {
"node-id": "roadm Lannion_CAS",
"link-tp-id": "link-tp-id is not used",
"hop-type": "loose",
"direction": "direction is not used"
},
"label-hop": {
"te-label": {
"generic": "generic is not used",
"direction": "direction is not used"
}
"hop-type": "LOOSE"
}
},
{
"explicit-route-usage": "route-include-ero",
"index": 2,
"unnumbered-hop": {
"num-unnum-hop": {
"node-id": "roadm Lorient_KMA",
"link-tp-id": "link-tp-id is not used",
"hop-type": "loose",
"direction": "direction is not used"
},
"label-hop": {
"te-label": {
"generic": "generic is not used",
"direction": "direction is not used"
}
"hop-type": "LOOSE"
}
},
{
"explicit-route-usage": "route-include-ero",
"index": 3,
"unnumbered-hop": {
"num-unnum-hop": {
"node-id": "roadm Vannes_KBE",
"link-tp-id": "link-tp-id is not used",
"hop-type": "loose",
"direction": "direction is not used"
},
"label-hop": {
"te-label": {
"generic": "generic is not used",
"direction": "direction is not used"
}
"hop-type": "LOOSE"
}
}
]
@@ -117,8 +90,8 @@
},
{
"request-id": "3",
"source": "Lannion_CAS",
"destination": "Rennes_STA",
"source": "trx Lannion_CAS",
"destination": "trx Rennes_STA",
"src-tp-id": "trx Lannion_CAS",
"dst-tp-id": "trx Rennes_STA",
"path-constraints": {
@@ -128,8 +101,8 @@
"trx_mode": "mode 1",
"effective-freq-slot": [
{
"n": "null",
"m": "null"
"N": "null",
"M": "null"
}
],
"spacing": 50000000000.0,
@@ -137,15 +110,12 @@
"output-power": 0.0012589254117941673,
"path_bandwidth": 60000000000.0
}
},
"optimizations": {
"explicit-route-include-objects": []
}
},
{
"request-id": "4",
"source": "Rennes_STA",
"destination": "Lannion_CAS",
"source": "trx Rennes_STA",
"destination": "trx Lannion_CAS",
"src-tp-id": "trx Rennes_STA",
"dst-tp-id": "trx Lannion_CAS",
"path-constraints": {
@@ -155,8 +125,8 @@
"trx_mode": "mode 2",
"effective-freq-slot": [
{
"n": "null",
"m": "null"
"N": "null",
"M": "null"
}
],
"spacing": 75000000000.0,
@@ -164,15 +134,12 @@
"output-power": null,
"path_bandwidth": 150000000000.0
}
},
"optimizations": {
"explicit-route-include-objects": []
}
},
{
"request-id": "5",
"source": "Rennes_STA",
"destination": "Lannion_CAS",
"source": "trx Rennes_STA",
"destination": "trx Lannion_CAS",
"src-tp-id": "trx Rennes_STA",
"dst-tp-id": "trx Lannion_CAS",
"path-constraints": {
@@ -182,8 +149,8 @@
"trx_mode": "mode 2",
"effective-freq-slot": [
{
"n": "null",
"m": "null"
"N": "null",
"M": "null"
}
],
"spacing": 75000000000.0,
@@ -191,9 +158,30 @@
"output-power": 0.0019952623149688794,
"path_bandwidth": 20000000000.0
}
},
"optimizations": {
"explicit-route-include-objects": []
}
},
{
"request-id": "6",
"source": "trx Lannion_CAS",
"destination": "trx a",
"src-tp-id": "trx Lannion_CAS",
"dst-tp-id": "trx a",
"path-constraints": {
"te-bandwidth": {
"technology": "flexi-grid",
"trx_type": "vendorA_trx-type1",
"trx_mode": "mode 2",
"effective-freq-slot": [
{
"N": "null",
"M": "null"
}
],
"spacing": 75000000000.0,
"max-nb-of-channel": null,
"output-power": null,
"path_bandwidth": 100000000000.0
}
}
}
],
@@ -201,9 +189,8 @@
{
"synchronization-id": "3",
"svec": {
"relaxable": "False",
"link-diverse": "True",
"node-diverse": "True",
"relaxable": "false",
"disjointness": "node link",
"request-id-number": [
"3",
"1"
@@ -213,9 +200,8 @@
{
"synchronization-id": "4",
"svec": {
"relaxable": "False",
"link-diverse": "True",
"node-diverse": "True",
"relaxable": "false",
"disjointness": "node link",
"request-id-number": [
"4",
"5"

View File

@@ -2,8 +2,8 @@
"path-request": [
{
"request-id": "1",
"source": "a",
"destination": "g",
"source": "trx a",
"destination": "trx g",
"src-tp-id": "trx a",
"dst-tp-id": "trx g",
"path-constraints": {
@@ -22,15 +22,12 @@
"output-power": 0.001,
"path_bandwidth": 300000000000.0
}
},
"optimizations": {
"explicit-route-include-objects": []
}
},
{
"request-id": "2a",
"source": "a",
"destination": "h",
"source": "trx a",
"destination": "trx h",
"src-tp-id": "trx a",
"dst-tp-id": "trx h",
"path-constraints": {
@@ -49,15 +46,12 @@
"output-power": 0.001,
"path_bandwidth": 300000000000.0
}
},
"optimizations": {
"explicit-route-include-objects": []
}
},
{
"request-id": "3",
"source": "f",
"destination": "b",
"source": "trx f",
"destination": "trx b",
"src-tp-id": "trx f",
"dst-tp-id": "trx b",
"path-constraints": {
@@ -76,15 +70,12 @@
"output-power": 0.001,
"path_bandwidth": 300000000000.0
}
},
"optimizations": {
"explicit-route-include-objects": []
}
},
{
"request-id": "ee",
"source": "c",
"destination": "f",
"source": "trx c",
"destination": "trx f",
"src-tp-id": "trx c",
"dst-tp-id": "trx f",
"path-constraints": {
@@ -104,36 +95,23 @@
"path_bandwidth": 300000000000.0
}
},
"optimizations": {
"explicit-route-include-objects": [
"explicit-route-objects": {
"route-object-include-exclude": [
{
"explicit-route-usage": "route-include-ero",
"index": 0,
"unnumbered-hop": {
"num-unnum-hop": {
"node-id": "roadm e",
"link-tp-id": "link-tp-id is not used",
"hop-type": "loose",
"direction": "direction is not used"
},
"label-hop": {
"te-label": {
"generic": "generic is not used",
"direction": "direction is not used"
}
"hop-type": "LOOSE"
}
},
{
"explicit-route-usage": "route-include-ero",
"index": 1,
"unnumbered-hop": {
"num-unnum-hop": {
"node-id": "roadm g",
"link-tp-id": "link-tp-id is not used",
"hop-type": "loose",
"direction": "direction is not used"
},
"label-hop": {
"te-label": {
"generic": "generic is not used",
"direction": "direction is not used"
}
"hop-type": "LOOSE"
}
}
]
@@ -141,8 +119,8 @@
},
{
"request-id": "ff",
"source": "c",
"destination": "f",
"source": "trx c",
"destination": "trx f",
"src-tp-id": "trx c",
"dst-tp-id": "trx f",
"path-constraints": {
@@ -161,15 +139,12 @@
"output-power": 0.001,
"path_bandwidth": 300000000000.0
}
},
"optimizations": {
"explicit-route-include-objects": []
}
},
{
"request-id": "10",
"source": "a",
"destination": "g",
"source": "trx a",
"destination": "trx g",
"src-tp-id": "trx a",
"dst-tp-id": "trx g",
"path-constraints": {
@@ -188,15 +163,12 @@
"output-power": 0.001,
"path_bandwidth": 300000000000.0
}
},
"optimizations": {
"explicit-route-include-objects": []
}
},
{
"request-id": "11",
"source": "a",
"destination": "h",
"source": "trx a",
"destination": "trx h",
"src-tp-id": "trx a",
"dst-tp-id": "trx h",
"path-constraints": {
@@ -216,21 +188,15 @@
"path_bandwidth": 300000000000.0
}
},
"optimizations": {
"explicit-route-include-objects": [
"explicit-route-objects": {
"route-object-include-exclude": [
{
"explicit-route-usage": "route-include-ero",
"index": 0,
"unnumbered-hop": {
"num-unnum-hop": {
"node-id": "bb",
"link-tp-id": "link-tp-id is not used",
"hop-type": "loose",
"direction": "direction is not used"
},
"label-hop": {
"te-label": {
"generic": "generic is not used",
"direction": "direction is not used"
}
"hop-type": "LOOSE"
}
}
]
@@ -238,8 +204,8 @@
},
{
"request-id": "12",
"source": "f",
"destination": "b",
"source": "trx f",
"destination": "trx b",
"src-tp-id": "trx f",
"dst-tp-id": "trx b",
"path-constraints": {
@@ -259,21 +225,15 @@
"path_bandwidth": 300000000000.0
}
},
"optimizations": {
"explicit-route-include-objects": [
"explicit-route-objects": {
"route-object-include-exclude": [
{
"explicit-route-usage": "route-include-ero",
"index": 0,
"unnumbered-hop": {
"num-unnum-hop": {
"node-id": "trx b",
"link-tp-id": "link-tp-id is not used",
"hop-type": "loose",
"direction": "direction is not used"
},
"label-hop": {
"te-label": {
"generic": "generic is not used",
"direction": "direction is not used"
}
"hop-type": "LOOSE"
}
}
]
@@ -281,8 +241,8 @@
},
{
"request-id": "13",
"source": "c",
"destination": "f",
"source": "trx c",
"destination": "trx f",
"src-tp-id": "trx c",
"dst-tp-id": "trx f",
"path-constraints": {
@@ -301,15 +261,12 @@
"output-power": 0.001,
"path_bandwidth": 300000000000.0
}
},
"optimizations": {
"explicit-route-include-objects": []
}
},
{
"request-id": "14",
"source": "c",
"destination": "f",
"source": "trx c",
"destination": "trx f",
"src-tp-id": "trx c",
"dst-tp-id": "trx f",
"path-constraints": {
@@ -329,36 +286,23 @@
"path_bandwidth": 300000000000.0
}
},
"optimizations": {
"explicit-route-include-objects": [
"explicit-route-objects": {
"route-object-include-exclude": [
{
"explicit-route-usage": "route-include-ero",
"index": 0,
"unnumbered-hop": {
"num-unnum-hop": {
"node-id": "roadm e",
"link-tp-id": "link-tp-id is not used",
"hop-type": "loose",
"direction": "direction is not used"
},
"label-hop": {
"te-label": {
"generic": "generic is not used",
"direction": "direction is not used"
}
"hop-type": "LOOSE"
}
},
{
"explicit-route-usage": "route-include-ero",
"index": 1,
"unnumbered-hop": {
"num-unnum-hop": {
"node-id": "roadm g",
"link-tp-id": "link-tp-id is not used",
"hop-type": "loose",
"direction": "direction is not used"
},
"label-hop": {
"te-label": {
"generic": "generic is not used",
"direction": "direction is not used"
}
"hop-type": "LOOSE"
}
}
]
@@ -366,8 +310,8 @@
},
{
"request-id": "e:1# /",
"source": "a",
"destination": "g",
"source": "trx a",
"destination": "trx g",
"src-tp-id": "trx a",
"dst-tp-id": "trx g",
"path-constraints": {
@@ -386,15 +330,12 @@
"output-power": null,
"path_bandwidth": 300000000000.0
}
},
"optimizations": {
"explicit-route-include-objects": []
}
},
{
"request-id": "b-2a",
"source": "a",
"destination": "h",
"source": "trx a",
"destination": "trx h",
"src-tp-id": "trx a",
"dst-tp-id": "trx h",
"path-constraints": {
@@ -413,15 +354,12 @@
"output-power": 0.001,
"path_bandwidth": 300000000000.0
}
},
"optimizations": {
"explicit-route-include-objects": []
}
},
{
"request-id": "3a;?",
"source": "f",
"destination": "b",
"source": "trx f",
"destination": "trx b",
"src-tp-id": "trx f",
"dst-tp-id": "trx b",
"path-constraints": {
@@ -440,15 +378,12 @@
"output-power": null,
"path_bandwidth": 300000000000.0
}
},
"optimizations": {
"explicit-route-include-objects": []
}
},
{
"request-id": "ee-s",
"source": "c",
"destination": "f",
"source": "trx c",
"destination": "trx f",
"src-tp-id": "trx c",
"dst-tp-id": "trx f",
"path-constraints": {
@@ -468,36 +403,23 @@
"path_bandwidth": 300000000000.0
}
},
"optimizations": {
"explicit-route-include-objects": [
"explicit-route-objects": {
"route-object-include-exclude": [
{
"explicit-route-usage": "route-include-ero",
"index": 0,
"unnumbered-hop": {
"num-unnum-hop": {
"node-id": "roadm e",
"link-tp-id": "link-tp-id is not used",
"hop-type": "loose",
"direction": "direction is not used"
},
"label-hop": {
"te-label": {
"generic": "generic is not used",
"direction": "direction is not used"
}
"hop-type": "LOOSE"
}
},
{
"explicit-route-usage": "route-include-ero",
"index": 1,
"unnumbered-hop": {
"num-unnum-hop": {
"node-id": "roadm g",
"link-tp-id": "link-tp-id is not used",
"hop-type": "loose",
"direction": "direction is not used"
},
"label-hop": {
"te-label": {
"generic": "generic is not used",
"direction": "direction is not used"
}
"hop-type": "LOOSE"
}
}
]
@@ -505,8 +427,8 @@
},
{
"request-id": "ff-b",
"source": "c",
"destination": "f",
"source": "trx c",
"destination": "trx f",
"src-tp-id": "trx c",
"dst-tp-id": "trx f",
"path-constraints": {
@@ -525,15 +447,12 @@
"output-power": 0.001,
"path_bandwidth": 300000000000.0
}
},
"optimizations": {
"explicit-route-include-objects": []
}
},
{
"request-id": "10-z",
"source": "a",
"destination": "g",
"source": "trx a",
"destination": "trx g",
"src-tp-id": "trx a",
"dst-tp-id": "trx g",
"path-constraints": {
@@ -552,15 +471,12 @@
"output-power": null,
"path_bandwidth": 300000000000.0
}
},
"optimizations": {
"explicit-route-include-objects": []
}
},
{
"request-id": "11 g",
"source": "a",
"destination": "h",
"source": "trx a",
"destination": "trx h",
"src-tp-id": "trx a",
"dst-tp-id": "trx h",
"path-constraints": {
@@ -579,15 +495,12 @@
"output-power": null,
"path_bandwidth": 300000000000.0
}
},
"optimizations": {
"explicit-route-include-objects": []
}
},
{
"request-id": "12<",
"source": "f",
"destination": "b",
"source": "trx f",
"destination": "trx b",
"src-tp-id": "trx f",
"dst-tp-id": "trx b",
"path-constraints": {
@@ -606,15 +519,12 @@
"output-power": null,
"path_bandwidth": null
}
},
"optimizations": {
"explicit-route-include-objects": []
}
},
{
"request-id": "12>",
"source": "f",
"destination": "b",
"source": "trx f",
"destination": "trx b",
"src-tp-id": "trx f",
"dst-tp-id": "trx b",
"path-constraints": {
@@ -633,9 +543,6 @@
"output-power": null,
"path_bandwidth": null
}
},
"optimizations": {
"explicit-route-include-objects": []
}
}
],
@@ -644,8 +551,7 @@
"synchronization-id": "1",
"svec": {
"relaxable": "False",
"link-diverse": "True",
"node-diverse": "True",
"disjointness": "node link",
"request-id-number": [
"1",
"2a"
@@ -656,8 +562,7 @@
"synchronization-id": "3",
"svec": {
"relaxable": "False",
"link-diverse": "True",
"node-diverse": "True",
"disjointness": "node link",
"request-id-number": [
"3",
"1"
@@ -668,8 +573,7 @@
"synchronization-id": "ff",
"svec": {
"relaxable": "False",
"link-diverse": "True",
"node-diverse": "True",
"disjointness": "node link",
"request-id-number": [
"ff",
"13"
@@ -680,8 +584,7 @@
"synchronization-id": "13",
"svec": {
"relaxable": "False",
"link-diverse": "True",
"node-diverse": "True",
"disjointness": "node link",
"request-id-number": [
"13",
"14"

View File

@@ -3,38 +3,48 @@
# @Author: Esther Le Rouzic
# @Date: 2018-06-15
from gnpy.core.elements import Edfa
import numpy as np
""" Adding tests to check the parser non regression
convention of naming of test files:
- ..._expected.json for the reference output
tests:
- generation of topology json
- reading of Eqpt sheet w and W/ power mode
- consistency of autodesign
- generation of service list based on service sheet
- writing of results in csv
- writing of results in json (same keys)
"""
from json import load
from pathlib import Path
from os import unlink
from pandas import read_csv
import pytest
from gnpy.core import network_from_json
from gnpy.core.elements import Transceiver, Fiber, Edfa
from gnpy.core.utils import lin2db, db2lin
from gnpy.core.info import SpectralInformation, Channel, Power
from gnpy.core.network import save_network, build_network
from tests.compare import compare_networks, compare_services
from gnpy.core.utils import lin2db
from gnpy.core.network import save_network, build_network
from gnpy.core.convert import convert_file
from gnpy.core.service_sheet import convert_service_sheet
from gnpy.core.equipment import load_equipment, automatic_nch
from gnpy.core.network import load_network
from pathlib import Path
import filecmp
from os import unlink
from gnpy.core.request import (jsontocsv, requests_aggregation,
compute_path_dsjctn, Result_element)
from examples.path_requests_run import (requests_from_json, disjunctions_from_json,
correct_route_list, correct_disjn,
compute_path_with_disjunction)
TEST_DIR = Path(__file__).parent
DATA_DIR = TEST_DIR / 'data'
eqpt_filename = DATA_DIR / 'eqpt_config.json'
# adding tests to check the parser non regression
# convention of naming of test files:
#
# - ..._expected.json for the reference output
@pytest.mark.parametrize('xls_input,expected_json_output', {
DATA_DIR / 'CORONET_Global_Topology.xls': DATA_DIR / 'CORONET_Global_Topology_expected.json',
DATA_DIR / 'testTopology.xls': DATA_DIR / 'testTopology_expected.json',
}.items())
}.items())
def test_excel_json_generation(xls_input, expected_json_output):
""" tests generation of topology json
"""
convert_file(xls_input)
actual_json_output = xls_input.with_suffix('.json')
@@ -55,20 +65,25 @@ def test_excel_json_generation(xls_input, expected_json_output):
# assume xls entries
# test that the build network gives correct results in gain mode
#
@pytest.mark.parametrize('xls_input,expected_json_output', {
DATA_DIR / 'CORONET_Global_Topology.xls': DATA_DIR / 'CORONET_Global_Topology_auto_design_expected.json',
DATA_DIR / 'testTopology.xls': DATA_DIR / 'testTopology_auto_design_expected.json',
}.items())
@pytest.mark.parametrize('xls_input,expected_json_output',
{DATA_DIR / 'CORONET_Global_Topology.xls':\
DATA_DIR / 'CORONET_Global_Topology_auto_design_expected.json',
DATA_DIR / 'testTopology.xls':\
DATA_DIR / 'testTopology_auto_design_expected.json',
}.items())
def test_auto_design_generation_fromxlsgainmode(xls_input, expected_json_output):
""" tests generation of topology json
test that the build network gives correct results in gain mode
"""
equipment = load_equipment(eqpt_filename)
network = load_network(xls_input,equipment)
# in order to test the Eqpt sheet and load gain target, change the power-mode to False (to be in gain mode)
network = load_network(xls_input, equipment)
# in order to test the Eqpt sheet and load gain target,
# change the power-mode to False (to be in gain mode)
equipment['Span']['default'].power_mode = False
# Build the network once using the default power defined in SI in eqpt config
p_db = equipment['SI']['default'].power_dbm
p_total_db = p_db + lin2db(automatic_nch(equipment['SI']['default'].f_min,\
equipment['SI']['default'].f_max, equipment['SI']['default'].spacing))
build_network(network, equipment, p_db, p_total_db)
@@ -92,19 +107,23 @@ def test_auto_design_generation_fromxlsgainmode(xls_input, expected_json_output)
assert not results.connections.different
#test that autodesign creates same file as an input file already autodesigned
@pytest.mark.parametrize('json_input,expected_json_output', {
DATA_DIR / 'CORONET_Global_Topology_auto_design_expected.json': DATA_DIR / 'CORONET_Global_Topology_auto_design_expected.json',
DATA_DIR / 'testTopology_auto_design_expected.json': DATA_DIR / 'testTopology_auto_design_expected.json',
}.items())
@pytest.mark.parametrize('json_input,expected_json_output',
{DATA_DIR / 'CORONET_Global_Topology_auto_design_expected.json':\
DATA_DIR / 'CORONET_Global_Topology_auto_design_expected.json',
DATA_DIR / 'testTopology_auto_design_expected.json':\
DATA_DIR / 'testTopology_auto_design_expected.json',
}.items())
def test_auto_design_generation_fromjson(json_input, expected_json_output):
"""test that autodesign creates same file as an input file already autodesigned
"""
equipment = load_equipment(eqpt_filename)
network = load_network(json_input,equipment)
# in order to test the Eqpt sheet and load gain target, change the power-mode to False (to be in gain mode)
network = load_network(json_input, equipment)
# in order to test the Eqpt sheet and load gain target,
# change the power-mode to False (to be in gain mode)
equipment['Span']['default'].power_mode = False
# Build the network once using the default power defined in SI in eqpt config
p_db = equipment['SI']['default'].power_dbm
p_total_db = p_db + lin2db(automatic_nch(equipment['SI']['default'].f_min,\
equipment['SI']['default'].f_max, equipment['SI']['default'].spacing))
build_network(network, equipment, p_db, p_total_db)
@@ -131,8 +150,10 @@ def test_auto_design_generation_fromjson(json_input, expected_json_output):
@pytest.mark.parametrize('xls_input,expected_json_output', {
DATA_DIR / 'testTopology.xls': DATA_DIR / 'testTopology_services_expected.json',
}.items())
}.items())
def test_excel_service_json_generation(xls_input, expected_json_output):
""" test services creation
"""
convert_service_sheet(xls_input, eqpt_filename)
actual_json_output = f'{str(xls_input)[:-4]}_services.json'
@@ -150,3 +171,128 @@ def test_excel_service_json_generation(xls_input, expected_json_output):
assert not results.synchronizations.missing
assert not results.synchronizations.extra
assert not results.synchronizations.different
# test xls answers creation
@pytest.mark.parametrize('json_input, csv_output', {
DATA_DIR / 'testTopology_response.json': DATA_DIR / 'testTopology_response',
}.items())
def test_csv_response_generation(json_input, csv_output):
""" tests if generated csv is consistant with expected generation
same columns (order not important)
"""
with open(json_input) as jsonfile:
json_data = load(jsonfile)
equipment = load_equipment(eqpt_filename)
csv_filename = str(csv_output)+'.csv'
with open(csv_filename, 'w', encoding='utf-8') as fcsv:
jsontocsv(json_data, equipment, fcsv)
expected_csv_filename = str(csv_output)+'_expected.csv'
# expected header
# csv_header = \
# [
# 'response-id',
# 'source',
# 'destination',
# 'path_bandwidth',
# 'Pass?',
# 'nb of tsp pairs',
# 'total cost',
# 'transponder-type',
# 'transponder-mode',
# 'OSNR-0.1nm',
# 'SNR-0.1nm',
# 'SNR-bandwidth',
# 'baud rate (Gbaud)',
# 'input power (dBm)',
# 'path'
# ]
resp = read_csv(csv_filename)
unlink(csv_filename)
expected_resp = read_csv(expected_csv_filename)
resp_header = list(resp.head(0))
expected_resp_header = list(expected_resp.head(0))
# check that headers are the same
resp_header.sort()
expected_resp_header.sort()
print('headers are differents')
print(resp_header)
print(expected_resp_header)
assert resp_header == expected_resp_header
# for each header checks that the output are as expected
resp.sort_values(by=['response-id'])
expected_resp.sort_values(by=['response-id'])
for column in expected_resp:
assert list(resp[column].fillna('')) == list(expected_resp[column].fillna(''))
print('results are different')
print(list(resp[column]))
print(list(expected_resp[column]))
print(type(list(resp[column])[-1]))
def compare_response(exp_resp, act_resp):
""" False if the keys are different in the nested dicts as well
"""
print(exp_resp)
print(act_resp)
test = True
for key in act_resp.keys():
print(key)
if not key in exp_resp.keys():
print(key)
return False
if isinstance(act_resp[key], dict):
test = compare_response(exp_resp[key], act_resp[key])
if test:
for key in exp_resp.keys():
if not key in act_resp.keys():
print(key)
return False
if isinstance(exp_resp[key], dict):
test = compare_response(exp_resp[key], act_resp[key])
# at this point exp_resp and act_resp have the same keys. Check if their values are the same
for key in act_resp.keys():
if not isinstance(act_resp[key], dict):
if exp_resp[key] != act_resp[key]:
return False
return test
# test json answers creation
@pytest.mark.parametrize('xls_input, expected_response_file', {
DATA_DIR / 'testTopology.xls': DATA_DIR / 'testTopology_response.json',
}.items())
def test_json_response_generation(xls_input, expected_response_file):
""" tests if json response is correctly generated for all combinations of requests
"""
data = convert_service_sheet(xls_input, eqpt_filename)
equipment = load_equipment(eqpt_filename)
network = load_network(xls_input, equipment)
p_db = equipment['SI']['default'].power_dbm
p_total_db = p_db + lin2db(automatic_nch(equipment['SI']['default'].f_min,\
equipment['SI']['default'].f_max, equipment['SI']['default'].spacing))
build_network(network, equipment, p_db, p_total_db)
rqs = requests_from_json(data, equipment)
rqs = correct_route_list(network, rqs)
dsjn = disjunctions_from_json(data)
dsjn = correct_disjn(dsjn)
rqs, dsjn = requests_aggregation(rqs, dsjn)
pths = compute_path_dsjctn(network, equipment, rqs, dsjn)
propagatedpths = compute_path_with_disjunction(network, equipment, rqs, pths)
result = []
for i, pth in enumerate(propagatedpths):
result.append(Result_element(rqs[i], pth))
temp = {
'response': [n.json for n in result]
}
# load expected result and compare keys
# (not values at this stage)
with open(expected_response_file) as jsonfile:
expected = load(jsonfile)
for i, response in enumerate(temp['response']):
assert compare_response(expected['response'][i], response)