Commit 37b1b28d authored by Kirill Smelkov's avatar Kirill Smelkov

software/ors-amarisoft: enb: Take frequencies control into our hands

Currently when setting up cells we allow users to input

- dl_earfcn for LTE, and
- dl_nr_arfcn and nr_band for NR

and from that lteenb automatically computes

- ul_earfcn for LTE, and
- ul_nr_arfcn and ssb_nr_arfcn for NR

everything kind of works out of the box for eNB case when there is simple SDR Radio Unit.

Then there are also the following cases:

1. we also need to set UL frequency when configuring Lopcomm RU, or any other ORAN-based Radio Unit.
2. we also need to specify DL/UL frequencies in MHz when configuring Lopcomm RU.
3. when configuring NR peercell it is required to set ssb_nr_arfcn. It is also
   required to set both dl_nr_arfcn and ul_nr_arfcn, and so far we were setting
   only DL one and using it for both assuming TDD band.
4. when configuring UEsim we need to specify both dl_nr_arfcn and ssb_nr_arfcn for NR cells.

So the problem is that even though lteenb automatically computes UL and SSB
frequencies, there is no way for us to reuse results of that computation for
scenarios outside of "simple enb" case.

As the result we kind of workaround that currently with exposing additional
parameters and asking users to look into enb, probably its `cell phy` output,
with the following:

     ---- 8< ---- (from UEsim)
     "ssb_nr_arfcn": {
       "title": "SSB NR ARFCN",
       "description": "SSB NR ARFCN, you can retrieve from ENB/GNB side",

or use additional parameters just for ul_earfcn and frequency-in-MHz:

     ---- 8< ---- (from ru/lopcomm)
     "txa0cc00_center_frequency": {
       "title": "Lopcomm ORAN DL Center Frequency in MHz (TXA0CC00)",
       "description": "Lopcomm ORAN Center Frequency in MHz (TXA0CC00)",
       "type": "number",
       "default": 2140
     },
     "rxa0cc00_center_frequency_earfcn": {
       "title": "Lopcomm ORAN UL Center Frequency EARFCN (RXA0CC00)",
       "description": "Lopcomm ORAN Center Frequency EARFCN (RXA0CC00)",
       "type": "number",
       "default": 18300
     },
     "rxa0cc00_center_frequency": {
       "title": "Lopcomm ORAN UL Center Frequency in MHz (RXA0CC00)",
       "description": "Lopcomm ORAN Center Frequency in MHz (RXA0CC00)",
       "type": "number",
       "default": 1950
     },

which prevents automation, opens the door for inconsistencies and puts the load
to resolve all that on users.

The root cause of the problem is that there is no way to access at
instantiation time what lteenb would compute internally. But DL<->UL conversion
and DL->SSB conversion is not a difficult task and we can do that on our own.

-> Do that here and solve all the problems listed above in one go.

For frequency computations we use my xlte.earfcn and xlte.nrarfcn modules and
upstream nrarfcn egg. For this xlte is updated(*) to primarily pick up

kirr/xlte@6cb9d37f
kirr/xlte@b8065120

and the rest of the conversion is in slaplte to use corresponding dl2ul and
dl2ssb routines.

For consistency ul_earfcn and ul_nr_arfcn now become input parameters for LTE
and NR cells, but optional. If they are absent - they are computed with
defaults, but a user can now control them explicitly. The same applies for
ssb_nr_arfcn.

This patch does not convert UEsim yet, because UEsim does not use rulib yet and
will be handled all in one go in a follow-up step.

The computation routines are thoroughly tested. First they have unit tests
inside XLTE itself, then we also update our tests in generic test/test.py here
with explicitly checking that correct numbers are emitted for UL and SSB
frequencies, and third I've also verified SSB computation results with respect
to https://tech-academy.amarisoft.com/OutOfBox_UEsim_SA.html#Tips_SSB_Frequency .

All this creates a base to be sure that the computations are correct and we are
indeed safe to switch our frequencies computation modules.

(*) full upgrade brings kirr/xlte@e716ab51...8e606c64 ;
    nrarfcn egg: https://pypi.org/project/nrarfcn/
parent 7a22aaa0
...@@ -54,6 +54,16 @@ ...@@ -54,6 +54,16 @@
"description": "NR band number", "description": "NR band number",
"type": "integer" "type": "integer"
}, },
"ul_nr_arfcn": {
"title": "UL NR ARFCN",
"description": "Uplink NR Absolute Radio Frequency Channel Number of the cell. By default a frequency corresponding to dl_nr_arfcn and nr_band is chosen.",
"type": "integer"
},
"ssb_nr_arfcn": {
"title": "SSB NR ARFCN",
"description": "SSB NR Absolute Radio Frequency Channel Number of the cell. If set it must be an element of global synchronization raster and be at offset from center DL frequency that aligns with SSB subcarrier spacing of selected band. By default a valid frequency nearby dl_nr_arfcn is chosen.",
"type": "integer"
},
"ssb_pos_bitmap": { "ssb_pos_bitmap": {
"title": "SSB Position Bitmap", "title": "SSB Position Bitmap",
"description": "SSB position bitmap in bits (4, 8 or 64 bits depending on the DL frequency).", "description": "SSB position bitmap in bits (4, 8 or 64 bits depending on the DL frequency).",
...@@ -68,11 +78,6 @@ ...@@ -68,11 +78,6 @@
}, },
"$defs": { "$defs": {
"ssb_nr_arfcn": {
"title": "SSB NR ARFCN",
"description": "SSB NR Absolute Radio Frequency Channel Number of the cell",
"type": "number"
},
"tac": { "tac": {
"title": "Tracking Area Code", "title": "Tracking Area Code",
"description": "Integer (range 0 to 16777215)", "description": "Integer (range 0 to 16777215)",
......
...@@ -51,7 +51,7 @@ ...@@ -51,7 +51,7 @@
dl_nr_arfcn: {{ ncell.dl_nr_arfcn }}, dl_nr_arfcn: {{ ncell.dl_nr_arfcn }},
band: {{ ncell.nr_band }}, band: {{ ncell.nr_band }},
ssb_nr_arfcn: {{ ncell.ssb_nr_arfcn }}, ssb_nr_arfcn: {{ ncell.ssb_nr_arfcn }},
ul_nr_arfcn: {{ ncell.dl_nr_arfcn }}, {#- XXX assumes nr_band is TDD #} ul_nr_arfcn: {{ ncell.ul_nr_arfcn }},
tac: {{ ncell.tac }}, tac: {{ ncell.tac }},
ssb_subcarrier_spacing: 30, ssb_subcarrier_spacing: 30,
ssb_period: 20, ssb_period: 20,
...@@ -221,6 +221,7 @@ ...@@ -221,6 +221,7 @@
n_id_cell: {{ cell.pci }}, n_id_cell: {{ cell.pci }},
root_sequence_index: {{ cell.root_sequence_index }}, root_sequence_index: {{ cell.root_sequence_index }},
dl_earfcn: {{ cell.dl_earfcn }}, dl_earfcn: {{ cell.dl_earfcn }},
ul_earfcn: {{ cell.ul_earfcn }},
inactivity_timer: {{ cell.inactivity_timer }}, inactivity_timer: {{ cell.inactivity_timer }},
// Handover // Handover
...@@ -440,9 +441,11 @@ ...@@ -440,9 +441,11 @@
n_id_cell: {{ cell.pci }}, n_id_cell: {{ cell.pci }},
band: {{ cell.nr_band }}, band: {{ cell.nr_band }},
dl_nr_arfcn: {{ cell.dl_nr_arfcn }}, dl_nr_arfcn: {{ cell.dl_nr_arfcn }},
ul_nr_arfcn: {{ cell.ul_nr_arfcn }},
bandwidth: {{ cell.bandwidth }}, bandwidth: {{ cell.bandwidth }},
subcarrier_spacing: 30, subcarrier_spacing: 30,
ssb_nr_arfcn: {{ cell.ssb_nr_arfcn }},
ssb_pos_bitmap: "{{ cell.ssb_pos_bitmap }}", ssb_pos_bitmap: "{{ cell.ssb_pos_bitmap }}",
root_sequence_index: {{ cell.root_sequence_index }}, root_sequence_index: {{ cell.root_sequence_index }},
......
...@@ -29,6 +29,9 @@ context = ...@@ -29,6 +29,9 @@ context =
import xbuildout xbuildout import xbuildout xbuildout
import json_module json import json_module json
import netaddr netaddr import netaddr netaddr
import nrarfcn_module nrarfcn
import xearfcn_module xlte.earfcn
import xnrarfcn_module xlte.nrarfcn
key eggs_directory buildout:eggs-directory key eggs_directory buildout:eggs-directory
key develop_eggs_directory buildout:develop-eggs-directory key develop_eggs_directory buildout:develop-eggs-directory
raw buildout_directory ${buildout:directory} raw buildout_directory ${buildout:directory}
...@@ -50,6 +53,19 @@ import-list = ...@@ -50,6 +53,19 @@ import-list =
[activate-eggs] [activate-eggs]
recipe = slapos.recipe.build recipe = slapos.recipe.build
init = init =
import pkg_resources as rpkg
buildout = self.buildout['buildout']
env = rpkg.Environment([buildout['develop-eggs-directory'],
buildout['eggs-directory']])
env.scan()
def activate(pkgspec):
req = rpkg.Requirement.parse(pkgspec)
for dist in rpkg.working_set.resolve([req], env):
rpkg.working_set.add(dist)
activate('xlte')
activate('nrarfcn')
  • Hello @kirr

    could you explain why you need to explicitly add those 2 eggs in the global working set ?

    For example, we are using netaddr egg in the jinja2 template without any problem.

    /cc @xavier_thompson

  • I had to do similar trick once, this is needed to have the packages available during buildout. netaddr works because it's a dependency of a recipe ( https://lab.nexedi.com/nexedi/slapos/-/blob/37b1b28d710a92fa6026e3dd5e92ffc0a1528152/setup.py#L67 )

  • So when buildout sees a recipe, it does its own magic to import it (see here).

    I think our slapos.recipe.template:jinja2 recipe should do the same when it sees an import in context, instead of just importing normally (see here).

    Moreover, slapos.recipe.build could provide a utility to import locally installed eggs, so that one could do e.g.:

    [import-whatever-and-use-it]
    recipe = slapos.recipe.build
    init =
      # import whatever # might not work
      local_import('whatever')
      whatever.use_it()

    Here local_import plays essentially the same role as the custom activate in this commit.

    In fact, this could actually be a utility of buildout itself; in a way it almost already does with the internal _install_and_load, but that would be a bit clumsy and it's not intended for this usage.

    Then we could even do:

    [import-whatever-and-use-it]
    recipe = slapos.recipe.build
    init =
      self.buildout.local_import('whatever')

    But I think it would be faster for now to not add this to the current work on buildout.

  • Hello, @tomo.

    As Jérome explained (thanks, @jerome) those eggs are indeed added into working set so that importing them in jinja2 templates works. For slapos.recipe.template:jinja2 netaddr is indeed already there on sys.path because netaddr is dependency of slapos.cookbook, but for eggs that are not listed in those dependencies, importing them will fail if we do not add them to the working set ourselves. Please try to comment e.g. activate('xlte') to see such failure. The code of [activate-eggs] has corresponding comments explaining that it is doing "activation of eggs and modules used in jinja2 templates". I thought that is enough, but if the comment is not clear we could try to improve it.

    Xavier, thanks also for sharing your thoughts about how to do the activation more automatically instead of manually at low level. It would be good if there is straightforward way to do without delving into pkg_resources details. It also feels we are picking virtualenv-style semantics in steps more and more, so maybe, at some point, it would be better to just switch to using full virtualenv without needing to do any kind of manual activation and other workarounds at all.

    Kirill

  • Thanks, I also believe that it would be nice to have an API for doing this and that it's not really critical because for now this low level way works. When I used it it was with slapos.recipe.build .

Please register or sign in to reply
# ~ import xbuildout # ~ import xbuildout
import sys, types import sys, types
def readfile(path): def readfile(path):
......
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
"nr_cell_id", "nr_cell_id",
"gnb_id_bits", "gnb_id_bits",
"dl_nr_arfcn", "dl_nr_arfcn",
"ssb_nr_arfcn",
"nr_band" "nr_band"
], ],
...@@ -36,7 +35,8 @@ ...@@ -36,7 +35,8 @@
}, },
"dl_nr_arfcn": { "$ref": "../../../cell/nr/input-schema.json#/properties/dl_nr_arfcn" }, "dl_nr_arfcn": { "$ref": "../../../cell/nr/input-schema.json#/properties/dl_nr_arfcn" },
"nr_band": { "$ref": "../../../cell/nr/input-schema.json#/properties/nr_band" }, "nr_band": { "$ref": "../../../cell/nr/input-schema.json#/properties/nr_band" },
"ssb_nr_arfcn": { "$ref": "../../../cell/nr/input-schema.json#/$defs/ssb_nr_arfcn" }, "ssb_nr_arfcn": { "$ref": "../../../cell/nr/input-schema.json#/properties/ssb_nr_arfcn" },
"ul_nr_arfcn": { "$ref": "../../../cell/nr/input-schema.json#/properties/ul_nr_arfcn" },
"pci": { "$ref": "../../../cell/nr/input-schema.json#/properties/pci" }, "pci": { "$ref": "../../../cell/nr/input-schema.json#/properties/pci" },
"tac": { "$ref": "../../../cell/nr/input-schema.json#/$defs/tac" } "tac": { "$ref": "../../../cell/nr/input-schema.json#/$defs/tac" }
} }
......
...@@ -297,10 +297,14 @@ recipe = slapos.cookbook:publish.serialised ...@@ -297,10 +297,14 @@ recipe = slapos.cookbook:publish.serialised
{{ slap_configuration['slap-software-type'] }} = {{ dumps(root) }} {{ slap_configuration['slap-software-type'] }} = {{ dumps(root) }}
ru = {{ dumps(ru_ref) }} ru = {{ dumps(ru_ref) }}
{%- if cell.cell_type == 'lte' %} {%- if cell.cell_type == 'lte' %}
band = {{ dumps('b%d' % xearfcn_module.band(cell.dl_earfcn)[0].band) }}
dl_earfcn = {{ dumps(cell.dl_earfcn) }} dl_earfcn = {{ dumps(cell.dl_earfcn) }}
ul_earfcn = {{ dumps(cell.ul_earfcn) }}
{%- elif cell.cell_type == 'nr' %} {%- elif cell.cell_type == 'nr' %}
band = {{ dumps('n%d' % cell.nr_band) }} band = {{ dumps('n%d' % cell.nr_band) }}
dl_nr_arfcn = {{ dumps(cell.dl_nr_arfcn) }} dl_nr_arfcn = {{ dumps(cell.dl_nr_arfcn) }}
ul_nr_arfcn = {{ dumps(cell.ul_nr_arfcn) }}
ssb_nr_arfcn= {{ dumps(cell.ssb_nr_arfcn) }}
{%- else %} {%- else %}
{%- do bug('unreachable') %} {%- do bug('unreachable') %}
{%- endif %} {%- endif %}
......
...@@ -91,8 +91,14 @@ ...@@ -91,8 +91,14 @@
<!-- TODO support multiple cells over 1 RU --> <!-- TODO support multiple cells over 1 RU -->
{%- if cell.cell_type == 'lte' %} {%- if cell.cell_type == 'lte' %}
{%- set dl_arfcn = cell.dl_earfcn %} {%- set dl_arfcn = cell.dl_earfcn %}
{%- set ul_arfcn = cell.ul_earfcn %}
{%- set dl_freq = int(xearfcn_module.frequency(dl_arfcn) * 1e6) %}
{%- set ul_freq = int(xearfcn_module.frequency(ul_arfcn) * 1e6) %}
{%- elif cell.cell_type == 'nr' %} {%- elif cell.cell_type == 'nr' %}
{%- set dl_arfcn = cell.dl_nr_arfcn %} {%- set dl_arfcn = cell.dl_nr_arfcn %}
{%- set ul_arfcn = cell.ul_nr_arfcn %}
{%- set dl_freq = int(xnrarfcn_module.frequency(dl_arfcn) * 1e6) %}
{%- set ul_freq = int(xnrarfcn_module.frequency(ul_arfcn) * 1e6) %}
{%- else %} {%- else %}
{%- do bug('unreachable') %} {%- do bug('unreachable') %}
{%- endif %} {%- endif %}
...@@ -100,7 +106,7 @@ ...@@ -100,7 +106,7 @@
<tx-array-carriers> <tx-array-carriers>
<name>{{ TxCarrier }}</name> <name>{{ TxCarrier }}</name>
<absolute-frequency-center>{{ dl_arfcn }}</absolute-frequency-center> <absolute-frequency-center>{{ dl_arfcn }}</absolute-frequency-center>
<center-of-channel-bandwidth>{{ 1000000*ru.get('txa0cc00_center_frequency', 2140) }}</center-of-channel-bandwidth> <center-of-channel-bandwidth>{{ dl_freq }}</center-of-channel-bandwidth>
<channel-bandwidth>{{ bw }}</channel-bandwidth> <channel-bandwidth>{{ bw }}</channel-bandwidth>
<active>{{ ru.txrx_active }}</active> <active>{{ ru.txrx_active }}</active>
<rw-type>{{ cell.cell_type | upper }}</rw-type> <rw-type>{{ cell.cell_type | upper }}</rw-type>
...@@ -111,8 +117,8 @@ ...@@ -111,8 +117,8 @@
</tx-array-carriers> </tx-array-carriers>
<rx-array-carriers> <rx-array-carriers>
<name>{{ RxCarrier }}</name> <name>{{ RxCarrier }}</name>
<absolute-frequency-center>{{ ru.get('rxa0cc00_center_frequency_earfcn', 18300) }}</absolute-frequency-center> <absolute-frequency-center>{{ ul_arfcn }}</absolute-frequency-center>
<center-of-channel-bandwidth>{{ 1000000*ru.get('rxa0cc00_center_frequency', 1950) }}</center-of-channel-bandwidth> <center-of-channel-bandwidth>{{ ul_freq }}</center-of-channel-bandwidth>
<channel-bandwidth>{{ bw }}</channel-bandwidth> <channel-bandwidth>{{ bw }}</channel-bandwidth>
<active>{{ ru.txrx_active }}</active> <active>{{ ru.txrx_active }}</active>
<downlink-radio-frame-offset>0</downlink-radio-frame-offset> <downlink-radio-frame-offset>0</downlink-radio-frame-offset>
......
...@@ -63,25 +63,6 @@ ...@@ -63,25 +63,6 @@
} }
}, },
"txa0cc00_center_frequency": {
"title": "Lopcomm ORAN DL Center Frequency in MHz (TXA0CC00)",
"description": "Lopcomm ORAN Center Frequency in MHz (TXA0CC00)",
"type": "number",
"default": 2140
},
"rxa0cc00_center_frequency_earfcn": {
"title": "Lopcomm ORAN UL Center Frequency EARFCN (RXA0CC00)",
"description": "Lopcomm ORAN Center Frequency EARFCN (RXA0CC00)",
"type": "number",
"default": 18300
},
"rxa0cc00_center_frequency": {
"title": "Lopcomm ORAN UL Center Frequency in MHz (RXA0CC00)",
"description": "Lopcomm ORAN Center Frequency in MHz (RXA0CC00)",
"type": "number",
"default": 1950
},
"reset_schedule": { "reset_schedule": {
"title": "Cron schedule for RRH reset", "title": "Cron schedule for RRH reset",
"description": "Refer https://crontab.guru/ to make a reset schedule for RRH, for example, '0 1 * * *' means the RRH will reset every day at 1 am", "description": "Refer https://crontab.guru/ to make a reset schedule for RRH, for example, '0 1 * * *' means the RRH will reset every day at 1 am",
......
...@@ -73,6 +73,8 @@ url = {{ ru_lopcomm_cu_config_template }} ...@@ -73,6 +73,8 @@ url = {{ ru_lopcomm_cu_config_template }}
{% endif %} {% endif %}
output = ${directory:etc}/{{B('%s-cu_config.xml' % ru_ref)}} output = ${directory:etc}/{{B('%s-cu_config.xml' % ru_ref)}}
extra-context = extra-context =
import xearfcn_module xlte.earfcn
import xnrarfcn_module xlte.nrarfcn
key ru :ru key ru :ru
key cell :cell key cell :cell
ru = {{ dumps(ru) }} ru = {{ dumps(ru) }}
......
...@@ -104,6 +104,24 @@ ...@@ -104,6 +104,24 @@
#} #}
{%- set J = json_module.loads %} {%- set J = json_module.loads %}
{#- jdefault_ul_earfcn returns default UL EARFCN corresponding to DL EARFCN. #}
{%- macro jdefault_ul_earfcn(dl_earfcn) %}
{{- xearfcn_module.dl2ul(dl_earfcn) | tojson }}
{%- endmacro %}
{#- jdefault_ul_nr_arfcn returns default UL NR ARFCN corresponding to DL NR ARFCN and band. #}
{%- macro jdefault_ul_nr_arfcn(dl_nr_arfcn, nr_band) %}
{{- xnrarfcn_module.dl2ul(dl_nr_arfcn, nr_band) | tojson }}
{%- endmacro %}
{#- jdefault_ssb_nr_arfcn returns default SSB NR ARFCN corresponding to DL NR ARFCN
and band. #}
{%- macro jdefault_ssb_nr_arfcn(dl_nr_arfcn, nr_band) %}
{#- NOTE: computations rechecked wrt https://tech-academy.amarisoft.com/OutOfBox_UEsim_SA.html#Tips_SSB_Frequency #}
{%- set ssb_nr_arfcn, max_ssb_scs_khz = xnrarfcn_module.dl2ssb(dl_nr_arfcn, nr_band) %}
{{- ssb_nr_arfcn | tojson }}
{%- endmacro %}
{#- tap indicates tap interface, that slapos told us to use, {#- tap indicates tap interface, that slapos told us to use,
or 'xxx-notap-xxx' if slapos provided us either nothing or empty string. #} or 'xxx-notap-xxx' if slapos provided us either nothing or empty string. #}
...@@ -284,6 +302,14 @@ ...@@ -284,6 +302,14 @@
{%- endfor %} {%- endfor %}
{%- set n = len(list(icell_dict|dictsort | selectattr('1._.cell_type', '==', cell.cell_type))) %} {%- set n = len(list(icell_dict|dictsort | selectattr('1._.cell_type', '==', cell.cell_type))) %}
{%- do cell.setdefault('root_sequence_index', 1 + 203*(cell.cell_type == 'lte') + n) %} {%- do cell.setdefault('root_sequence_index', 1 + 203*(cell.cell_type == 'lte') + n) %}
{%- if cell.cell_type == 'lte' %}
{%- do cell.setdefault('ul_earfcn', J(jdefault_ul_earfcn(cell.dl_earfcn))) %}
{%- elif cell.cell_type == 'nr' %}
{%- do cell.setdefault('ul_nr_arfcn', J(jdefault_ul_nr_arfcn(cell.dl_nr_arfcn, cell.nr_band))) %}
{%- do cell.setdefault('ssb_nr_arfcn', J(jdefault_ssb_nr_arfcn(cell.dl_nr_arfcn, cell.nr_band))) %}
{%- else %}
{%- do bug('unreachable') %}
{%- endif %}
{%- endmacro %} {%- endmacro %}
...@@ -347,6 +373,14 @@ ...@@ -347,6 +373,14 @@
{%- set _ = ishared['_'] %} {%- set _ = ishared['_'] %}
{%- if 'cell_type' in _ and _.get('cell_kind') == 'enb_peer' %} {%- if 'cell_type' in _ and _.get('cell_kind') == 'enb_peer' %}
{%- set ipeercell = ishared %} {%- set ipeercell = ishared %}
{%- if _.cell_type == 'lte' %}
{%- do _.setdefault('ul_earfcn', J(jdefault_ul_earfcn(_.dl_earfcn))) %}
{%- elif _.cell_type == 'nr' %}
{%- do _.setdefault('ul_nr_arfcn', J(jdefault_ul_nr_arfcn(_.dl_nr_arfcn, _.nr_band))) %}
{%- do _.setdefault('ssb_nr_arfcn', J(jdefault_ssb_nr_arfcn(_.dl_nr_arfcn, _.nr_band))) %}
{%- else %}
{%- do bug('unreachable') %}
{%- endif %}
{%- do ipeercell_dict.update({ref: ipeercell}) %} {%- do ipeercell_dict.update({ref: ipeercell}) %}
{%- else %} {%- else %}
{%- do qother.append(ishared) %} {%- do qother.append(ishared) %}
......
...@@ -28,6 +28,9 @@ def j2render(src, out, jcfg): ...@@ -28,6 +28,9 @@ def j2render(src, out, jcfg):
textctx += 'json %s %s\n' % (k, json.dumps(v)) textctx += 'json %s %s\n' % (k, json.dumps(v))
textctx += 'import xbuildout xbuildout\n' textctx += 'import xbuildout xbuildout\n'
textctx += 'import json_module json\n' textctx += 'import json_module json\n'
textctx += 'import nrarfcn_module nrarfcn\n'
textctx += 'import xearfcn_module xlte.earfcn\n'
textctx += 'import xnrarfcn_module xlte.nrarfcn\n'
buildout = None # stub buildout = None # stub
r = jinja2_template.Recipe(buildout, "recipe", { r = jinja2_template.Recipe(buildout, "recipe", {
'extensions': 'jinja2.ext.do', 'extensions': 'jinja2.ext.do',
...@@ -469,7 +472,6 @@ def _do_enb_with(iru_icell_func): ...@@ -469,7 +472,6 @@ def _do_enb_with(iru_icell_func):
'nr_cell_id': '0x77712', 'nr_cell_id': '0x77712',
'gnb_id_bits': 22, 'gnb_id_bits': 22,
'dl_nr_arfcn': 520000, 'dl_nr_arfcn': 520000,
'ssb_nr_arfcn': 520090,
'nr_band': 38, 'nr_band': 38,
'pci': 75, 'pci': 75,
'tac': 321, 'tac': 321,
......
...@@ -156,6 +156,7 @@ eggs = ...@@ -156,6 +156,7 @@ eggs =
xmltodict xmltodict
ncclient ncclient
${lxml-python:egg} ${lxml-python:egg}
nrarfcn
netifaces netifaces
netaddr netaddr
interpreter = pythonwitheggs interpreter = pythonwitheggs
...@@ -163,7 +164,7 @@ interpreter = pythonwitheggs ...@@ -163,7 +164,7 @@ interpreter = pythonwitheggs
[xlte-repository] [xlte-repository]
recipe = slapos.recipe.build:gitclone recipe = slapos.recipe.build:gitclone
repository = https://lab.nexedi.com/kirr/xlte.git repository = https://lab.nexedi.com/kirr/xlte.git
revision = e716ab51 revision = 8e606c64
git-executable = ${git:location}/bin/git git-executable = ${git:location}/bin/git
[xlte] [xlte]
...@@ -192,3 +193,4 @@ exe = ${dnsmasq:location}/sbin/dnsmasq ...@@ -192,3 +193,4 @@ exe = ${dnsmasq:location}/sbin/dnsmasq
websocket-client = 1.4.2 websocket-client = 1.4.2
ncclient = 0.6.13 ncclient = 0.6.13
xmltodict = 0.13.0 xmltodict = 0.13.0
nrarfcn = 2.4.0:whl
...@@ -274,18 +274,18 @@ class RFTestCase4(AmariTestCase): ...@@ -274,18 +274,18 @@ class RFTestCase4(AmariTestCase):
assertMatch(t, q('RU3'), {'tx_gain': 13, 'rx_gain': 23, 'txrx_active': 'ACTIVE'}) assertMatch(t, q('RU3'), {'tx_gain': 13, 'rx_gain': 23, 'txrx_active': 'ACTIVE'})
assertMatch(t, q('RU4'), {'tx_gain': 14, 'rx_gain': 24, 'txrx_active': 'ACTIVE'}) assertMatch(t, q('RU4'), {'tx_gain': 14, 'rx_gain': 24, 'txrx_active': 'ACTIVE'})
assertMatch(t, q('RU1.CELL'), dict( assertMatch(t, q('RU1.CELL'), dict(band='b1',
dl_earfcn= 100, dl_earfcn= 100, ul_earfcn=18100,
dl_nr_arfcn=NO)) dl_nr_arfcn=NO, ul_nr_arfcn=NO, ssb_nr_arfcn=NO))
assertMatch(t, q('RU2.CELL'), dict( assertMatch(t, q('RU2.CELL'), dict(band='b41',
dl_earfcn=40200, dl_earfcn=40200, ul_earfcn=40200,
dl_nr_arfcn=NO)) dl_nr_arfcn=NO, ul_nr_arfcn=NO, ssb_nr_arfcn=NO))
assertMatch(t, q('RU3.CELL'), dict(band='n74', assertMatch(t, q('RU3.CELL'), dict(band='n74',
dl_earfcn=NO, dl_earfcn=NO, ul_earfcn=NO,
dl_nr_arfcn=300300)) dl_nr_arfcn=300300, ul_nr_arfcn=290700, ssb_nr_arfcn=300270))
assertMatch(t, q('RU4.CELL'), dict(band='n40', assertMatch(t, q('RU4.CELL'), dict(band='n40',
dl_earfcn=NO, dl_earfcn=NO, ul_earfcn=NO,
dl_nr_arfcn=470400)) dl_nr_arfcn=470400, ul_nr_arfcn=470400, ssb_nr_arfcn=470430))
# ENBTestCase4 provides base class for unit-testing eNB service. # ENBTestCase4 provides base class for unit-testing eNB service.
...@@ -337,7 +337,7 @@ class ENBTestCase4(RFTestCase4): ...@@ -337,7 +337,7 @@ class ENBTestCase4(RFTestCase4):
_('PEER5', XN_PEER('55.1.1.1')) _('PEER5', XN_PEER('55.1.1.1'))
_('PEERCELL4', LTE(700) | LTE_PEER(0x12345, 35, 0x123)) _('PEERCELL4', LTE(700) | LTE_PEER(0x12345, 35, 0x123))
_('PEERCELL5', NR(520000,38) | NR_PEER(0x77712,22, 75, 0x321) | {'ssb_nr_arfcn': 520090}) _('PEERCELL5', NR(520000,38) | NR_PEER(0x77712,22, 75, 0x321))
def CELLcfg(i): def CELLcfg(i):
return CENB(i, 0x10+i) | TAC(0x100+i) | { return CENB(i, 0x10+i) | TAC(0x100+i) | {
...@@ -370,14 +370,14 @@ class ENBTestCase4(RFTestCase4): ...@@ -370,14 +370,14 @@ class ENBTestCase4(RFTestCase4):
assertMatch(t, t.enb_cfg['cell_list'], [ assertMatch(t, t.enb_cfg['cell_list'], [
dict( # CELL1 dict( # CELL1
uldl_config=NO, rf_port=0, n_antenna_dl=4, n_antenna_ul=2, uldl_config=NO, rf_port=0, n_antenna_dl=4, n_antenna_ul=2,
dl_earfcn=100, dl_earfcn=100, ul_earfcn=18100,
n_rb_dl=25, n_rb_dl=25,
cell_id=0x1, n_id_cell=0x11, tac=0x101, cell_id=0x1, n_id_cell=0x11, tac=0x101,
root_sequence_index=101, inactivity_timer=1001, root_sequence_index=101, inactivity_timer=1001,
), ),
dict( # CELL2 dict( # CELL2
uldl_config=2, rf_port=1, n_antenna_dl=4, n_antenna_ul=2, uldl_config=2, rf_port=1, n_antenna_dl=4, n_antenna_ul=2,
dl_earfcn=40200, dl_earfcn=40200, ul_earfcn=40200,
n_rb_dl=50, n_rb_dl=50,
cell_id=0x2, n_id_cell=0x12, tac=0x102, cell_id=0x2, n_id_cell=0x12, tac=0x102,
root_sequence_index=102, inactivity_timer=1002, root_sequence_index=102, inactivity_timer=1002,
...@@ -387,7 +387,7 @@ class ENBTestCase4(RFTestCase4): ...@@ -387,7 +387,7 @@ class ENBTestCase4(RFTestCase4):
assertMatch(t, t.enb_cfg['nr_cell_list'], [ assertMatch(t, t.enb_cfg['nr_cell_list'], [
dict( # CELL3 dict( # CELL3
tdd_ul_dl_config=NO, rf_port=2, n_antenna_dl=4, n_antenna_ul=2, tdd_ul_dl_config=NO, rf_port=2, n_antenna_dl=4, n_antenna_ul=2,
dl_nr_arfcn=300300, band=74, dl_nr_arfcn=300300, ul_nr_arfcn=290700, ssb_nr_arfcn=300270, band=74,
bandwidth=15, bandwidth=15,
cell_id=0x3, n_id_cell=0x13, tac=NO, cell_id=0x3, n_id_cell=0x13, tac=NO,
root_sequence_index=103, inactivity_timer=1003, root_sequence_index=103, inactivity_timer=1003,
...@@ -398,7 +398,7 @@ class ENBTestCase4(RFTestCase4): ...@@ -398,7 +398,7 @@ class ENBTestCase4(RFTestCase4):
period=5, dl_slots=7, dl_symbols=6, ul_slots=2, ul_symbols=4, period=5, dl_slots=7, dl_symbols=6, ul_slots=2, ul_symbols=4,
)}, )},
rf_port=3, n_antenna_dl=4, n_antenna_ul=2, rf_port=3, n_antenna_dl=4, n_antenna_ul=2,
dl_nr_arfcn=470400, band=40, dl_nr_arfcn=470400, ul_nr_arfcn=470400, ssb_nr_arfcn=470430, band=40,
bandwidth=20, bandwidth=20,
cell_id=0x4, n_id_cell=0x14, tac=NO, cell_id=0x4, n_id_cell=0x14, tac=NO,
root_sequence_index=104, inactivity_timer=1004, root_sequence_index=104, inactivity_timer=1004,
...@@ -465,17 +465,20 @@ class Lopcomm4: ...@@ -465,17 +465,20 @@ class Lopcomm4:
# RU configuration in cu_config.xml # RU configuration in cu_config.xml
def test_ru_cu_config_xml(t): def test_ru_cu_config_xml(t):
def uctx(rf_mode, cell_type, dl_arfcn, bw, tx_gain, rx_gain): def uctx(rf_mode, cell_type, dl_arfcn, ul_arfcn, bw, dl_freq, ul_freq, tx_gain, rx_gain):
return { return {
'tx-array-carriers': { 'tx-array-carriers': {
'rw-duplex-scheme': rf_mode, 'rw-duplex-scheme': rf_mode,
'rw-type': cell_type, 'rw-type': cell_type,
'absolute-frequency-center': '%d' % dl_arfcn, 'absolute-frequency-center': '%d' % dl_arfcn,
'center-of-channel-bandwidth': '%d' % dl_freq,
'channel-bandwidth': '%d' % bw, 'channel-bandwidth': '%d' % bw,
'gain': '%d' % tx_gain, 'gain': '%d' % tx_gain,
'active': 'ACTIVE', 'active': 'ACTIVE',
}, },
'rx-array-carriers': { 'rx-array-carriers': {
'absolute-frequency-center': '%d' % ul_arfcn,
'center-of-channel-bandwidth': '%d' % ul_freq,
'channel-bandwidth': '%d' % bw, 'channel-bandwidth': '%d' % bw,
# XXX no rx_gain # XXX no rx_gain
'active': 'ACTIVE', 'active': 'ACTIVE',
...@@ -484,11 +487,11 @@ class Lopcomm4: ...@@ -484,11 +487,11 @@ class Lopcomm4:
_ = t._test_ru_cu_config_xml _ = t._test_ru_cu_config_xml
# rf_mode ctype dl_arfcn bw txg rxg # rf_mode ctype dl_arfcn ul_arfcn bw dl_freq ul_freq txg rxg
_(1, uctx('FDD', 'LTE', 100, 5000000, 11, 21)) _(1, uctx('FDD', 'LTE', 100, 18100, 5000000, 2120000000, 1930000000, 11, 21))
_(2, uctx('TDD', 'LTE', 40200, 10000000, 12, 22)) _(2, uctx('TDD', 'LTE', 40200, 40200, 10000000, 2551000000, 2551000000, 12, 22))
_(3, uctx('FDD', 'NR', 300300, 15000000, 13, 23)) _(3, uctx('FDD', 'NR', 300300, 290700, 15000000, 1501500000, 1453500000, 13, 23))
_(4, uctx('TDD', 'NR', 470400, 20000000, 14, 24)) _(4, uctx('TDD', 'NR', 470400, 470400, 20000000, 2352000000, 2352000000, 14, 24))
def _test_ru_cu_config_xml(t, i, uctx): def _test_ru_cu_config_xml(t, i, uctx):
cu_xml = t.ipath('etc/%s' % xbuildout.encode('%s-cu_config.xml' % t.ref('RU%d' % i))) cu_xml = t.ipath('etc/%s' % xbuildout.encode('%s-cu_config.xml' % t.ref('RU%d' % i)))
......
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