Skip to content

Commit

Permalink
Change rq.N and rq.M from scalar to list
Browse files Browse the repository at this point in the history
Prepare for the next step, to be able to handle lists of candidate assignment

Signed-off-by: EstherLerouzic <[email protected]>
Change-Id: I2bd78606ce4502f68efb60f85892df5f76d52bb5
  • Loading branch information
EstherLerouzic committed Nov 17, 2023
1 parent 064d3af commit 4ba77d0
Show file tree
Hide file tree
Showing 8 changed files with 490 additions and 326 deletions.
51 changes: 40 additions & 11 deletions gnpy/tools/json_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from gnpy.core.utils import automatic_nch, automatic_fmax, merge_amplifier_restrictions
from gnpy.core.parameters import DEFAULT_RAMAN_COEFFICIENT
from gnpy.topology.request import PathRequest, Disjunction, compute_spectrum_slot_vs_bandwidth
from gnpy.topology.spectrum_assignment import mvalue_to_slots
from gnpy.tools.convert import xls_to_json_data
from gnpy.tools.service_sheet import read_service_sheet

Expand Down Expand Up @@ -627,7 +628,8 @@ def requests_from_json(json_data, equipment):
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'])
params['effective_freq_slot'] = req['path-constraints']['te-bandwidth'].get('effective-freq-slot', [None])[0]
params['effective_freq_slot'] = \
req['path-constraints']['te-bandwidth'].get('effective-freq-slot', [{'N': None, 'M': None}])
try:
params['path_bandwidth'] = req['path-constraints']['te-bandwidth']['path_bandwidth']
except KeyError:
Expand Down Expand Up @@ -656,19 +658,46 @@ def _check_one_request(params, f_max_from_si):
+ f' Max recommanded nb of channels is {max_recommanded_nb_channels}.'
raise ServiceError(msg)
# Transponder mode already selected; will it fit to the requested bandwidth?
if params['trx_mode'] is not None and params['effective_freq_slot'] is not None \
and params['effective_freq_slot']['M'] is not None:
_, requested_m = compute_spectrum_slot_vs_bandwidth(params['path_bandwidth'],
params['spacing'],
params['bit_rate'])
# params['effective_freq_slot']['M'] value should be bigger than the computed requested_m (simple estimate)
if params['trx_mode'] is not None and params['effective_freq_slot'] is not None:
required_nb_of_channels, requested_m = compute_spectrum_slot_vs_bandwidth(params['path_bandwidth'],
params['spacing'],
params['bit_rate'])
_, per_channel_m = compute_spectrum_slot_vs_bandwidth(params['bit_rate'],
params['spacing'],
params['bit_rate'])
# each M should fit one or more channels if it is not None
# spectrum slots should not overlap
# resulting nb of channels should be bigger than the nb computed with path_bandwidth
# without being splitted
# TODO: elaborate a more accurate estimate with nb_wl * tx_osnr + possibly guardbands in case of
# superchannel closed packing.
if requested_m > params['effective_freq_slot']['M']:
msg = f'Requested M {params["effective_freq_slot"]["M"]} number of slots for request ' +\
f'{params["request_id"]} should be greater than {requested_m} to support request ' +\
f'{params["path_bandwidth"] * 1e-9} Gbit/s with {params["trx_type"]} {params["trx_mode"]}'
nb_of_channels = 0
# order slots
slots = sorted(params['effective_freq_slot'], key=lambda x: float('inf') if x['N'] is None else x['N'])
for slot in slots:
nb_of_channels = nb_of_channels + slot['M'] // per_channel_m if slot['M'] is not None \
and nb_of_channels is not None else None
if slot['M'] is not None and slot['M'] < per_channel_m:
msg = f'Requested M {slot} number of slots for request' +\
f' {params["request_id"]} should be greater than {per_channel_m} to support request' +\
f'with {params["trx_type"]} {params["trx_mode"]}'
_logger.critical(msg)
if nb_of_channels is not None and nb_of_channels < required_nb_of_channels:
msg = f'Requested M {slots} number of slots for request {params["request_id"]} support {nb_of_channels}' +\
f' nb of channels while {required_nb_of_channels} are required to support request' +\
f' {params["path_bandwidth"] * 1e-9} Gbit/s with {params["trx_type"]} {params["trx_mode"]}'
raise ServiceError(msg)
if nb_of_channels is not None:
_, stop0n = mvalue_to_slots(slots[0]['N'], slots[0]['M'])
i = 1
while i < len(slots):
slot = slots[i]
startn, stopn = mvalue_to_slots(slot['N'], slot['M'])
if startn <= stop0n:
msg = f'Requested M {slots} for request {params["request_id"]} overlap'
raise ServiceError(msg)
_, stop0n = startn, stopn
i += 1


def disjunctions_from_json(json_data):
Expand Down
20 changes: 10 additions & 10 deletions gnpy/topology/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ def __init__(self, *args, **params):
self.cost = params.cost
self.path_bandwidth = params.path_bandwidth
if params.effective_freq_slot is not None:
self.N = params.effective_freq_slot['N']
self.M = params.effective_freq_slot['M']
self.N = [s['N'] for s in params.effective_freq_slot]
self.M = [s['M'] for s in params.effective_freq_slot]
self.initial_spectrum = None
self.offset_db = params.equalization_offset_db

Expand Down Expand Up @@ -172,10 +172,10 @@ def detailed_path_json(self):
temp = {
'path-route-object': {
'index': index,
"label-hop": {
"N": self.path_request.N,
"M": self.path_request.M
},
"label-hop": [{
"N": n,
"M": m
} for n, m in zip(self.path_request.N, self.path_request.M)],
}
}
pro_list.append(temp)
Expand Down Expand Up @@ -459,8 +459,8 @@ def jsontoparams(my_p, tsp, mode, equipment):
temp2 = []
for elem in my_p['path-properties']['path-route-objects']:
if 'label-hop' in elem['path-route-object'].keys():
temp2.append(f'{elem["path-route-object"]["label-hop"]["N"]}, ' +
f'{elem["path-route-object"]["label-hop"]["M"]}')
temp2.append(f'{[e["N"] for e in elem["path-route-object"]["label-hop"]]}, '
+ f'{[e["M"] for e in elem["path-route-object"]["label-hop"]]}')
# OrderedDict.fromkeys returns the unique set of strings.
# TODO: if spectrum changes along the path, we should be able to give the segments
# eg for regeneration case
Expand Down Expand Up @@ -978,8 +978,8 @@ def compare_reqs(req1, req2, disjlist):
req1.OSNR == req2.OSNR and \
req1.roll_off == req2.roll_off and \
same_disj and \
getattr(req1, 'N', None) is None and getattr(req2, 'N', None) is None and \
getattr(req1, 'M', None) is None and getattr(req2, 'M', None) is None:
getattr(req1, 'N', [None]) == [None] and getattr(req2, 'N', [None]) == [None] and \
getattr(req1, 'M', [None]) == [None] and getattr(req2, 'M', [None]) == [None]:
return True
else:
return False
Expand Down
12 changes: 6 additions & 6 deletions gnpy/topology/spectrum_assignment.py
Original file line number Diff line number Diff line change
Expand Up @@ -386,20 +386,20 @@ def pth_assign_spectrum(pths, rqs, oms_list, rpths):
else:
nb_wl, requested_m = compute_spectrum_slot_vs_bandwidth(rq.path_bandwidth,
rq.spacing, rq.bit_rate)
if getattr(rq, 'M', None) is not None:
if getattr(rq, 'M', [None])[0] is not None:
# Consistency check between the requested M and path_bandwidth
# M value should be bigger than the computed requested_m (simple estimate)
# TODO: elaborate a more accurate estimate with nb_wl * tx_osnr + possibly guardbands in case of
# superchannel closed packing.
if requested_m > rq.M:
if requested_m > rq.M[0]:
rq.N = None
rq.M = None
rq.blocking_reason = 'NOT_ENOUGH_RESERVED_SPECTRUM'
# need to stop here for this request and not go though spectrum selection process with requested_m
continue
# use the req.M even if requested_m is smaller
requested_m = rq.M
requested_n = getattr(rq, 'N', None)
requested_m = rq.M[0]
requested_n = getattr(rq, 'N', [None])[0]
(center_n, startn, stopn), path_oms = spectrum_selection(pth + rpth, oms_list, requested_m,
requested_n)
# if requested n and m concern already occupied spectrum the previous function returns a None candidate
Expand All @@ -409,8 +409,8 @@ def pth_assign_spectrum(pths, rqs, oms_list, rpths):
for oms_elem in path_oms:
oms_list[oms_elem].assign_spectrum(center_n, requested_m)
oms_list[oms_elem].add_service(rq.request_id, nb_wl)
rq.N = center_n
rq.M = requested_m
rq.N = [center_n]
rq.M = [requested_m]
else:
rq.N = None
rq.M = None
Expand Down
Loading

0 comments on commit 4ba77d0

Please sign in to comment.