Commit 8e606c64 authored by Kirill Smelkov's avatar Kirill Smelkov

nrarfcn: Fix behaviour on invalid input parameters

Contrary to earfcn, where band can be automatically deduced from earfcn
number because 4G bands never overlap, most functions in nrarfcn accept
as input parameters both nr_arfcn and band, because 5G bands can and do
overlap. As the result it is possible to invoke e.g. dl2ul with
dl_nr_arfcn being outside of downlink spectrum of specified band.

However in b8065120 I've made a thinko and handled such situation with
simple assert which does not lead to useful error feedback from a user
perspective, for example:

    In [2]: xnrarfcn.dl2ul(10000, 1)
    ---------------------------------------------------------------------------
    AssertionError                            Traceback (most recent call last)
    Cell In[2], line 1
    ----> 1 n.dl2ul(10000, 1)

    File ~/src/wendelin/xlte/nrarfcn.py:85, in dl2ul(dl_nr_arfcn, band)
         83 if dl_lo == 'N/A':
         84     raise AssertionError('band%r does not have downlink spectrum' % band)
    ---> 85 assert dl_lo <= dl_nr_arfcn <= dl_hi
         86 ul_lo, ul_hi = nr.get_nrarfcn_range(band, 'ul')
         87 if ul_lo == 'N/A':

    AssertionError:

The issue here is that asserts can be used to only verify internal
invariants, and that reported error does not provide details about which
nrarfcn and band were used in the query.

-> Fix this by providing details in the error reported to incorrect
module usage, and by consistently raising ValueError for "invalid
parameters" cases.

The reported error for above example now becomes

    ValueError: band1: NR-ARFCN=10000 is outside of downlink spectrum
parent b8065120
...@@ -81,8 +81,9 @@ nr = _() ...@@ -81,8 +81,9 @@ nr = _()
def dl2ul(dl_nr_arfcn, band): # -> ul_nr_arfcn def dl2ul(dl_nr_arfcn, band): # -> ul_nr_arfcn
dl_lo, dl_hi = nr.get_nrarfcn_range(band, 'dl') dl_lo, dl_hi = nr.get_nrarfcn_range(band, 'dl')
if dl_lo == 'N/A': if dl_lo == 'N/A':
raise AssertionError('band%r does not have downlink spectrum' % band) raise ValueError('band%r does not have downlink spectrum' % band)
assert dl_lo <= dl_nr_arfcn <= dl_hi if not (dl_lo <= dl_nr_arfcn <= dl_hi):
raise ValueError('band%r: NR-ARFCN=%r is outside of downlink spectrum' % (band, dl_nr_arfcn))
ul_lo, ul_hi = nr.get_nrarfcn_range(band, 'ul') ul_lo, ul_hi = nr.get_nrarfcn_range(band, 'ul')
if ul_lo == 'N/A': if ul_lo == 'N/A':
raise KeyError('band%r, to which DL NR-ARFCN=%r belongs, does not have uplink spectrum' % (band, dl_nr_arfcn)) raise KeyError('band%r, to which DL NR-ARFCN=%r belongs, does not have uplink spectrum' % (band, dl_nr_arfcn))
...@@ -96,8 +97,9 @@ def dl2ul(dl_nr_arfcn, band): # -> ul_nr_arfcn ...@@ -96,8 +97,9 @@ def dl2ul(dl_nr_arfcn, band): # -> ul_nr_arfcn
def ul2dl(ul_nr_arfcn, band): # -> dl_nr_arfcn def ul2dl(ul_nr_arfcn, band): # -> dl_nr_arfcn
ul_lo, ul_hi = nr.get_nrarfcn_range(band, 'ul') ul_lo, ul_hi = nr.get_nrarfcn_range(band, 'ul')
if ul_lo == 'N/A': if ul_lo == 'N/A':
raise AssertionError('band%r does not have uplink spectrum' % band) raise ValueError('band%r does not have uplink spectrum' % band)
assert ul_lo <= ul_nr_arfcn <= ul_hi if not (ul_lo <= ul_nr_arfcn <= ul_hi):
raise ValueError('band%r: NR-ARFCN=%r is outside of uplink spectrum' % (band, ul_nr_arfcn))
dl_lo, dl_hi = nr.get_nrarfcn_range(band, 'dl') dl_lo, dl_hi = nr.get_nrarfcn_range(band, 'dl')
if dl_lo == 'N/A': if dl_lo == 'N/A':
raise KeyError('band%r, to which UL NR-ARFCN=%r belongs, does not have downlink spectrum' % (band, ul_nr_arfcn)) raise KeyError('band%r, to which UL NR-ARFCN=%r belongs, does not have downlink spectrum' % (band, ul_nr_arfcn))
...@@ -114,13 +116,15 @@ def ul2dl(ul_nr_arfcn, band): # -> dl_nr_arfcn ...@@ -114,13 +116,15 @@ def ul2dl(ul_nr_arfcn, band): # -> dl_nr_arfcn
# for return (Fdl - Fssb) is aligned with some SSB SubCarrier Spacing of given band. # for return (Fdl - Fssb) is aligned with some SSB SubCarrier Spacing of given band.
# max_ssb_scs_khz indicates max SSB SubCarrier Spacing for which it was possible to find Fssb constrained with above alignment requirement. # max_ssb_scs_khz indicates max SSB SubCarrier Spacing for which it was possible to find Fssb constrained with above alignment requirement.
# #
# ValueError is raised if Fssb is not possible to find for given Fdl and band. # KeyError is raised if Fssb is not possible to find for given Fdl and band.
# ValueError is raised if input parameters are incorrect.
def dl2ssb(dl_nr_arfcn, band): # -> ssb_nr_arfcn, max_ssb_scs_khz def dl2ssb(dl_nr_arfcn, band): # -> ssb_nr_arfcn, max_ssb_scs_khz
_trace('\ndl2ssb %r %r' % (dl_nr_arfcn, band)) _trace('\ndl2ssb %r %r' % (dl_nr_arfcn, band))
dl_lo, dl_hi = nr.get_nrarfcn_range(band, 'dl') dl_lo, dl_hi = nr.get_nrarfcn_range(band, 'dl')
if dl_lo == 'N/A': if dl_lo == 'N/A':
raise AssertionError('band%r does not have downlink spectrum' % band) raise ValueError('band%r does not have downlink spectrum' % band)
assert dl_lo <= dl_nr_arfcn <= dl_hi if not (dl_lo <= dl_nr_arfcn <= dl_hi):
raise ValueError('band%r: NR-ARFCN=%r is outside of downlink spectrum' % (band, dl_nr_arfcn))
f = frequency(nrarfcn=dl_nr_arfcn) f = frequency(nrarfcn=dl_nr_arfcn)
_trace('f %.16g' % f) _trace('f %.16g' % f)
...@@ -159,7 +163,7 @@ def dl2ssb(dl_nr_arfcn, band): # -> ssb_nr_arfcn, max_ssb_scs_khz ...@@ -159,7 +163,7 @@ def dl2ssb(dl_nr_arfcn, band): # -> ssb_nr_arfcn, max_ssb_scs_khz
return f_sync_arfcn, scs_khz return f_sync_arfcn, scs_khz
gscn += (+1 if δf > 0 else -1) gscn += (+1 if δf > 0 else -1)
raise ValueError('dl2ssb %r %s: cannot find SSB frequency that is both on GSR and aligns from dl modulo SSB SCS of the given band' % (dl_nr_arfcn, band)) raise KeyError('dl2ssb %r %s: cannot find SSB frequency that is both on GSR and aligns from dl modulo SSB SCS of the given band' % (dl_nr_arfcn, band))
# frequency returns frequency corresponding to DL or UL NR-ARFCN. # frequency returns frequency corresponding to DL or UL NR-ARFCN.
......
...@@ -86,5 +86,22 @@ def test_nrarfcn(): ...@@ -86,5 +86,22 @@ def test_nrarfcn():
_(263, 2679991, 2679991, 64049.52, 64049.52, 'TDD', 2679931, 120) # FR2-2 % 480khz ≠ 0 _(263, 2679991, 2679991, 64049.52, 64049.52, 'TDD', 2679931, 120) # FR2-2 % 480khz ≠ 0
# some dl points not on ΔFraster -> ssb cannot be found # some dl points not on ΔFraster -> ssb cannot be found
_( 78, 632629, 632629, 3489.435, 3489.435, 'TDD', ValueError, None) _( 78, 632629, 632629, 3489.435, 3489.435, 'TDD', KeyError, None)
_(257, 2079168, 2079168, 28000.14, 28000.14, 'TDD', ValueError, None) _(257, 2079168, 2079168, 28000.14, 28000.14, 'TDD', KeyError, None)
# error in input parameters -> ValueError
def edl(band, dl_nr_arfcn, estr):
for f in (dl2ul, dl2ssb):
with raises(ValueError, match=estr):
f(dl_nr_arfcn, band)
def eul(band, ul_nr_arfcn, estr):
for f in (ul2dl,):
with raises(ValueError, match=estr):
f(ul_nr_arfcn, band)
# no x spectrum when requesting x2y
edl(80, 10000, 'band80 does not have downlink spectrum') # SUL
eul(29, 10000, 'band29 does not have uplink spectrum') # SDL
# mismatch between x_nr_arfcn and band
edl( 1, 10000, 'band1: NR-ARFCN=10000 is outside of downlink spectrum')
eul( 1, 10000, 'band1: NR-ARFCN=10000 is outside of uplink spectrum')
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment