Commit 30179be5 authored by Kirill Smelkov's avatar Kirill Smelkov

software/ors-amarisoft: ue: Generalize UEsim

Rework UEsim to be able to work with multiple cells, multiple radio units(*),
multiple UE all at the same time. RU, CELLs and UEs are now configured,
simiularly to eNB, via shared instances. Add tests.

Contrary to ORS don't care about backward compatibility here because currently
we have just a few UEsim deployments and migrating them should be easy.

Please see added schemas, tests and updates slapos-render-config on how to use
the new system.

(*) contrary to eNB UEsim does not allow to use one RU for two cells,
parent 4abb4101
......@@ -12,7 +12,7 @@
{%- set icell_dict = {} %}
{%- set ipeer_dict = {} %}
{%- set ipeercell_dict = {} %}
{%- do slaplte.load_iru_and_icell(iru_dict, icell_dict) %}
{%- do slaplte.load_iru_and_icell(iru_dict, icell_dict, icell_kind='enb') %}
{%- do slaplte.load_ipeer(ipeer_dict) %}
{%- do slaplte.load_ipeercell(ipeercell_dict) %}
{%- do slaplte.check_loaded_everything() %}
......
{#- ue_type indicates with which mode ue is instantiated with - lte | nr #}
{%- set ue_type = slapparameter_dict.ue_type %}
{%- do assert(ue_type in ('lte', 'nr'), ue_type) %}
{%- import 'slaplte.jinja2' as slaplte with context %}
{%- set B = slaplte.B %}
{%- set J = slaplte.J %}
{%- set jcell_ru_ref = slaplte.jcell_ru_ref %}
{#- for standalone testing via slapos-render-config.py
NOTE: keep in sync with instance-ue.jinja2.cfg and ru/libinstance.jinja2.cfg #}
{%- if _standalone is defined %}
{%- set iru_dict = {} %}
{%- set icell_dict = {} %}
{%- set iue_dict = {} %}
{%- do slaplte.load_iru_and_icell(iru_dict, icell_dict, icell_kind='ue') %}
{%- do slaplte.load_iue(iue_dict) %}
{%- do slaplte.check_loaded_everything() %}
{%- endif %}
{#- start of the config -#}
{
log_options: "all.level=error,all.max_size=0,nas.level=debug,nas.max_size=1,rrc.level=debug,rrc.max_size=1,phy.level=info,file.rotate=1G,file.path=/dev/null",
log_filename: "{{ directory['log'] }}/ue.log",
......@@ -9,70 +23,98 @@
rue_bind_addr: "{{ pub_info['rue_bind_addr'] }}",
com_addr: "{{ pub_info['com_addr'] }}",
rf_driver: {
name: "sdr",
args: "dev0=/dev/sdr0",
rx_antenna:"tx_rx",
},
tx_gain: {{ slapparameter_dict.get('tx_gain', 60) }},
rx_gain: {{ slapparameter_dict.get('rx_gain', 40) }},
cell_groups: [
{%- if ue_type == 'lte' %}
{
// LTE cell
{# instantiate radio units #}
{{ slaplte.ru_config(iru_dict, slapparameter_dict) }}
cell_groups: [{
// LTE cells
group_type: "lte",
multi_ue: true,
cells: [
{
bandwidth: {{ slapparameter_dict.get('bandwidth', '20 MHz') .removesuffix(' MHz') }},
dl_earfcn: {{ slapparameter_dict.get('dl_earfcn', 0) }},
n_antenna_dl: {{ slapparameter_dict.get('n_antenna_dl', 2) }},
n_antenna_ul: {{ slapparameter_dict.get('n_antenna_ul', 2) }},
global_timing_advance: -1,
}
{%- for cell_ref, icell in icell_dict|dictsort %}
{%- set cell = icell['_'] %}
{%- if cell.cell_type == 'lte' %}
{%- set ru_ref = J(jcell_ru_ref(icell)) %}
{%- set iru = iru_dict[ru_ref] %}
{%- set ru = iru['_'] %}
// {{ B(cell_ref) }}
{
rf_port: {{ ru._rf_port }},
n_antenna_dl: {{ ru.n_antenna_dl }},
n_antenna_ul: {{ ru.n_antenna_ul }},
dl_earfcn: {{ cell.dl_earfcn }},
ul_earfcn: {{ cell.ul_earfcn }},
bandwidth: {{ cell.bandwidth }},
global_timing_advance: -1,
},
{%- endif %}
{%- endfor %}
],
pdcch_decode_opt: false,
pdcch_decode_opt_threshold: 0.1,
},
{%- endif %}
{%- if ue_type == 'nr' %}
{
// NR cell
}, {
// NR cells
group_type: "nr",
multi_ue: false,
cells: [{
rf_port: 0,
bandwidth: {{ slapparameter_dict.get('bandwidth', 40) }},
band: {{ slapparameter_dict.get('nr_band', 0) }},
dl_nr_arfcn: {{ slapparameter_dict.get('dl_nr_arfcn', 0) }},
ssb_nr_arfcn: {{ slapparameter_dict.get('ssb_nr_arfcn', 0) }},
subcarrier_spacing: 30,
n_antenna_dl: {{ slapparameter_dict.get('n_antenna_dl', 2) }},
n_antenna_ul: {{ slapparameter_dict.get('n_antenna_ul', 2) }},
}
],
},
{%- endif %}
],
multi_ue: true,
cells: [
{%- for cell_ref, icell in icell_dict|dictsort %}
{%- set cell = icell['_'] %}
{%- if cell.cell_type == 'nr' %}
{%- set ru_ref = J(jcell_ru_ref(icell)) %}
{%- set iru = iru_dict[ru_ref] %}
{%- set ru = iru['_'] %}
// {{ B(cell_ref) }}
{
rf_port: {{ ru._rf_port }},
n_antenna_dl: {{ ru.n_antenna_dl }},
n_antenna_ul: {{ ru.n_antenna_ul }},
band: {{ cell.nr_band }},
dl_nr_arfcn: {{ cell.dl_nr_arfcn }},
ul_nr_arfcn: {{ cell.ul_nr_arfcn }},
ssb_nr_arfcn: {{ cell.ssb_nr_arfcn }},
bandwidth: {{ cell.bandwidth }},
subcarrier_spacing: {{ cell.subcarrier_spacing }},
},
{%- endif %}
{%- endfor %}
]
}],
ue_list: [
{%- for ue_ref, iue in iue_dict|dictsort %}
{%- set ue = iue['_'] %}
// {{ B(ue_ref) }}
{
sim_algo: "{{ slapparameter_dict.get('sim_algo', 'milenage') }}",
opc: "{{ slapparameter_dict.get('opc', '') }}",
amf: {{ slapparameter_dict.get('amf', '0x9001') }},
sqn: "{{ slapparameter_dict.get('sqn', '000000000000') }}",
impu: "{{ slapparameter_dict.get('impu', '') }}",
impi: "{{ slapparameter_dict.get('impi', '') }}",
imsi: "{{ slapparameter_dict.get('imsi', '001010123456789') }}",
K: "{{ slapparameter_dict.get('k', '00112233445566778899aabbccddeeff') }}",
{%- if ue_type == 'lte' %}
ue_category: 12,
{%- endif %}
{%- if ue_type == 'nr' %}
as_release: 15,
ue_category: "nr",
{%- endif %}
rue_addr: "{{ slapparameter_dict.get('rue_addr', '') }}",
tun_setup_script: "ue-ifup",
apn: "internet",
}
sim_algo: "{{ ue.sim_algo }}",
opc: "{{ ue.opc }}",
amf: {{ ue.amf }},
sqn: "{{ ue.sqn }}",
impu: "{{ ue.impu }}",
impi: "{{ ue.impi }}",
imsi: "{{ ue.imsi }}",
K: "{{ ue.k }}",
rue_addr: "{{ ue.rue_addr }}",
{%- if ue.ue_type == 'lte' %}
as_release: 13,
ue_category: 13,
{%- elif ue.ue_type == 'nr' %}
as_release: 15,
ue_category: "nr",
{%- else %}
{%- do bug('unreachable') %}
{%- endif %}
tun_setup_script: "ue-ifup",
apn: "internet",
},
{%- endfor %}
],
}
......@@ -33,6 +33,7 @@ eggs-directory = {{ eggs_directory }}
develop-eggs-directory = {{ develop_eggs_directory }}
offline = true
{%- set icell_kind='enb' %}
{%- import 'slaplte.jinja2' as slaplte with context %}
{%- import 'ru_libinstance.jinja2.cfg' as rulib with context %}
{%- set ipeer_dict = {} %}
......
......@@ -2,39 +2,5 @@
"type": "object",
"$schema": "http://json-schema.org/draft-04/schema",
"title": "Input Parameters",
"properties": {
"ue": {
"title": "UE",
"oneOf": [
{
"$ref": "ue/lte/input-schema.json"
},
{
"$ref": "ue/nr/input-schema.json"
}
]
},
"tx_gain": {
"title": "Tx gain",
"description": "Tx gain (in dB)",
"type": "number"
},
"rx_gain": {
"title": "Rx gain",
"description": "Rx gain (in dB)",
"type": "number"
},
"n_antenna_dl": {
"title": "Number of DL antennas",
"description": "Enumeration: 1, 2, 4 or 8. Number of DL antennas. It must be the same for all NB-IoT and LTE cells sharing the same RF port.",
"type": "number",
"default": 2
},
"n_antenna_ul": {
"title": "Number of UL antennas",
"description": "Enumeration: 1, 2, 4 or 8. Number of UL antennas. It must be the same for all NB-IoT and LTE cells sharing the same RF port.",
"type": "number",
"default": 2
}
}
"properties": {}
}
# instance-ue implements UEsim service.
[buildout]
parts =
directory
lte-ue-config
lte-ue-service
check-sdr-busy.py
monitor-base
publish-connection-information
......@@ -13,6 +14,15 @@ eggs-directory = {{ eggs_directory }}
develop-eggs-directory = {{ develop_eggs_directory }}
offline = true
{%- set icell_kind='ue' %}
{%- import 'slaplte.jinja2' as slaplte with context %}
{%- import 'ru_libinstance.jinja2.cfg' as rulib with context %}
{%- set iue_dict = {} %}
{%- do slaplte.load_iue(iue_dict) %}
{%- do slaplte.check_loaded_everything() %}
{{ rulib.buildout() }}
[myslap]
# see instance-enb.jinja2.cfg about myslap
parameter_dict = {{ dumps(slapparameter_dict) }}
......@@ -88,11 +98,15 @@ environment =
[config-base]
recipe = slapos.recipe.template:jinja2
extensions = jinja2.ext.do
extra-context =
context =
json ors false
section directory directory
section pub_info publish-connection-information
key slap_configuration myslap:configuration
key slapparameter_dict myslap:parameter_dict
import xbuildout xbuildout
${:extra-context}
[lte-ue-config]
<= config-base
......@@ -102,6 +116,17 @@ url = ${ue-config-dl:target}
url = {{ ue_template }}
{% endif %}
output = ${directory:etc}/ue.cfg
import-list =
rawfile slaplte.jinja2 {{ slaplte_template }}
extra-context =
import json_module json
key iru_dict :iru_dict
key icell_dict :icell_dict
key iue_dict :iue_dict
iru_dict = {{ dumps(rulib.iru_dict) }}
icell_dict = {{ dumps(rulib.icell_dict) }}
iue_dict = {{ dumps(iue_dict) }}
[publish-connection-information]
<= monitor-publish
......@@ -117,15 +142,3 @@ monitor-title = {{ slapparameter_dict['name'] | string }}
{% if slapparameter_dict.get("monitor-password", None) %}
password = {{ slapparameter_dict['monitor-password'] | string }}
{% endif %}
[macro.promise]
<= monitor-promise-base
name = ${:_buildout_section_name_}
[check-sdr-busy.py]
<= macro.promise
promise = check_sdr_busy
config-testing = {{ slapparameter_dict.get("testing", False) }}
config-sdr = {{ sdr }}
config-sdr_dev = 0
config-dma_chan = 0
......@@ -207,8 +207,27 @@ extra-context =
key ue amarisoft:ue
key sdr amarisoft:sdr
raw ue_template ${ue.jinja2.cfg:target}
raw slaplte_template ${slaplte.jinja2:target}
raw openssl_location ${openssl:location}
raw ru_amarisoft_stats_template ${ru_amarisoft-stats.jinja2.py:target}
raw ru_amarisoft_rf_info_template ${ru_amarisoft-rf-info.jinja2.py:target}
raw ru_lopcomm_stats_template ${ru_lopcomm_stats.jinja2.py:target}
raw ru_lopcomm_config_template ${ru_lopcomm_config.jinja2.py:target}
raw ru_lopcomm_software_template ${ru_lopcomm_software.jinja2.py:target}
raw ru_lopcomm_reset_info_template ${ru_lopcomm_reset-info.jinja2.py:target}
raw ru_lopcomm_reset_template ${ru_lopcomm_reset.jinja2.py:target}
raw ru_lopcomm_CreateProcessingEle_template ${ru_lopcomm_CreateProcessingEle.jinja2.xml:target}
raw ru_lopcomm_cu_config_template ${ru_lopcomm_cu_config.jinja2.xml:target}
raw ru_lopcomm_firmware_path ${ru_lopcomm_firmware-dl:target}
raw ru_lopcomm_firmware_filename ${ru_lopcomm_firmware-dl:filename}
raw ru_tapsplit ${ru_tapsplit:target}
raw netcapdo ${netcapdo:exe}
raw ru_dnsmasq_template ${ru_dnsmasq.jinja2.cfg:target}
raw dnsmasq_location ${dnsmasq:location}
raw openssh_location ${openssh:location}
raw openssh_output_keygen ${openssh-output:keygen}
[ue-db-config]
recipe = slapos.recipe.template:jinja2
url = ${ue_db.jinja2.cfg:target}
......
{#- Package ru/libinstance provides common instance code for handling Radio Units and cells.
Use buildout() macro to emit instance-level code to
handle configured RUs.
Set global icell_kind=enb|ue before importing to indicate which kind of
cells (server- or client-level) need to be configured. Then, after
importing, use buildout() macro to emit instance-level code to
handle configured RUs and cells.
NOTE: before importing package slaplte.jinja2 needs to already loaded as
......@@ -16,7 +18,7 @@
#}
{%- set iru_dict = {} %}
{%- set icell_dict = {} %}
{%- do slaplte.load_iru_and_icell(iru_dict, icell_dict) %}
{%- do slaplte.load_iru_and_icell(iru_dict, icell_dict, icell_kind) %}
{%- macro buildout() %}
......@@ -260,6 +262,7 @@ txrx_active = {{ dumps(ru.txrx_active) }}
{%- set iru = iru_dict[ru_ref] %}
{%- set ru = iru['_'] %}
{%- if icell_kind == 'enb' %}
{#- generate CELL-drb.cfg and CELL-sib23.asn #}
{{ part('drb-config-%s' % cell_ref) }}
<= config-base
......@@ -288,6 +291,7 @@ cell_ref = {{ dumps(cell_ref) }}
cell = {{ dumps(cell ) }}
ru_ref = {{ dumps(ru_ref ) }}
ru = {{ dumps(ru ) }}
{%- endif %}
{#- publish information about the cell (skipping synthetic) #}
{%- if icell.slave_reference %}
......
......@@ -3,6 +3,7 @@
- load_iru_and_icell initializes RU and cell registries.
- load_ipeercell initializes peer-cell registry.
- load_ipeer initializes peer registry.
- load_iue initializes UE registry.
- ru_config emits RF driver configuration for specified Radio Units.
In the code iX denotes shared instance of type X, while X denotes
......@@ -73,6 +74,17 @@
'ssb_pos_bitmap': '10000000',
'tdd_ul_dl_config': '5ms 2UL 7DL 4/6 (default)',
},
'ue': {
'sim_algo': 'milenage',
'opc': 'milenage',
'amf': '0x9001',
'sqn': '000000000000',
'impu': '',
'impi': '',
'imsi': '001010123456789',
'k': '00112233445566778899aabbccddeeff',
},
}
%}
......@@ -201,8 +213,11 @@
icell_dict keeps cell shared instances: reference -> icell
iru_dict keeps RU shared instances + RU whose definition is embedded into a cell: reference -> iRU
in the kept instances _ is automatically json-decoded
icell_kind=enb - load cells definition to serve them from enb
icell_kind=ue - load cells definition to connect to them
#}
{%- macro load_iru_and_icell(iru_dict, icell_dict) %}
{%- macro load_iru_and_icell(iru_dict, icell_dict, icell_kind) %}
{%- set qother = [] %}
{%- for ishared in qshared_instance_list %}
{%- set ref = J(jref_of_shared(ishared)) %}
......@@ -211,9 +226,9 @@
{%- set iru = ishared %}
{%- do _ru_set_defaults(_) %}
{%- do iru_dict.update({ref: iru}) %}
{%- elif 'cell_type' in _ and _.get('cell_kind') == 'enb' %}
{%- elif 'cell_type' in _ and _.get('cell_kind') == icell_kind %}
{%- set icell = ishared %}
{%- do _cell_set_defaults(_, icell_dict) %}
{%- do _cell_set_defaults(_, icell_kind, icell_dict) %}
{%- do icell_dict.update({ref: icell}) %}
{%- set ru = _['ru'] %}
{%- if ru.ru_type not in ('ru_ref', 'ruincell_ref') %}
......@@ -294,15 +309,17 @@
{%- endif %}
{%- endmacro %}
{%- macro _cell_set_defaults(cell, icell_dict) %}
{%- for k, v in defaults['cell/%s' % cell.cell_type].items() %}
{%- do cell.setdefault(k, v) %}
{%- endfor %}
{%- for k, v in defaults['cell/%s/%s' % (cell.cell_type, cell.rf_mode)].items() %}
{%- do cell.setdefault(k, v) %}
{%- endfor %}
{%- 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) %}
{%- macro _cell_set_defaults(cell, icell_kind, icell_dict) %}
{%- if icell_kind == 'enb' %}
{%- for k, v in defaults['cell/%s' % cell.cell_type].items() %}
{%- do cell.setdefault(k, v) %}
{%- endfor %}
{%- for k, v in defaults['cell/%s/%s' % (cell.cell_type, cell.rf_mode)].items() %}
{%- do cell.setdefault(k, v) %}
{%- endfor %}
{%- 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) %}
{%- endif %}
{%- if cell.cell_type == 'lte' %}
{%- do cell.setdefault('ul_earfcn', J(jdefault_ul_earfcn(cell.dl_earfcn))) %}
{%- elif cell.cell_type == 'nr' %}
......@@ -396,6 +413,30 @@
{%- endmacro %}
{#- load_iue initializes UE registry.
iue_dict keeps ue shared instance: reference -> iue
#}
{%- macro load_iue(iue_dict) %}
{%- set qother = [] %}
{%- for ishared in qshared_instance_list %}
{%- set ref = J(jref_of_shared(ishared)) %}
{%- set _ = ishared['_'] %}
{%- if 'ue_type' in _ %}
{%- set iue = ishared %}
{%- for k, v in defaults['ue'].items() %}
{%- do _.setdefault(k, v) %}
{%- endfor %}
{%- do iue_dict.update({ref: iue}) %}
{%- else %}
{%- do qother.append(ishared) %}
{%- endif %}
{%- endfor %}
{%- do qshared_instance_list.clear() %}
{%- do qshared_instance_list.extend(qother) %}
{%- endmacro %}
{#- ---- building configuration ---- #}
{#- ru_config emits RF driver configuration for specified Radio Units. #}
......
......@@ -560,27 +560,71 @@ def _do_enb_with(iru_icell_func):
# ---- UE ----
def do_ue():
def do(src, out, slapparameter_dict):
jslapparameter_dict = json.dumps(slapparameter_dict)
json_params = """{
"slap_configuration": {
"tap-name": "slaptap9"
},
"directory": {
"log": "log",
"etc": "etc",
"var": "var"
},
"pub_info": {
"rue_bind_addr": "::1",
"com_addr": "[::1]:9002"
},
"slapparameter_dict": %(jslapparameter_dict)s
}"""
j2render(src, out, json_params % locals())
do('ue.jinja2.cfg', 'ue-lte.cfg', {'ue_type': 'lte', 'rue_addr': 'host1'})
do('ue.jinja2.cfg', 'ue-nr.cfg', {'ue_type': 'nr', 'rue_addr': 'host2'})
iue = Instance('ue')
iue.ishared('UCELL1', {
'cell_type': 'lte',
'cell_kind': 'ue',
'rf_mode': 'tdd',
'bandwidth': 5,
'dl_earfcn': 38050, # 2600 MHz
'ru': {
'ru_type': 'sdr',
'ru_link_type': 'sdr',
'sdr_dev_list': [0],
'n_antenna_dl': 2,
'n_antenna_ul': 1,
'tx_gain': 41,
'rx_gain': 42,
}
})
iue.ishared('UCELL2', {
'cell_type': 'nr',
'cell_kind': 'ue',
'rf_mode': 'fdd',
'bandwidth': 5,
'dl_nr_arfcn': 537200, # 2686 MHz
'nr_band': 7,
'ru': { # NOTE contrary to eNB UEsim cannot share one RU in between several cells
'ru_type': 'sdr',
'ru_link_type': 'sdr',
'sdr_dev_list': [2],
'n_antenna_dl': 2,
'n_antenna_ul': 2,
'tx_gain': 31,
'rx_gain': 32,
}
})
iue.ishared('UE1', {
'ue_type': 'lte',
'rue_addr': 'host1'
})
iue.ishared('UE2', {
'ue_type': 'nr',
'rue_addr': 'host2'
})
jshared_instance_list = json.dumps(iue.shared_instance_list)
json_params = """{
"slap_configuration": {
"tap-name": "slaptap9",
"slap-computer-partition-id": "slappart9",
"slave-instance-list": %(jshared_instance_list)s
},
"pub_info": {
"rue_bind_addr": "::1",
"com_addr": "[::1]:9002"
},
"directory": {
"log": "log",
"etc": "etc",
"var": "var"
},
"slapparameter_dict": {
}
}""" % locals()
j2render('ue.jinja2.cfg', 'ue.cfg', json_params)
def main():
......
......@@ -65,12 +65,39 @@
"index": 7
},
"ue": {
"title": "UE",
"description": "UE Configuration",
"title": "UEsim",
"description": "UEsim Configuration",
"software-type": "ue",
"request": "instance-ue-input-schema.json",
"response": "instance-ue-schema.json",
"index": 8
},
"ue/ru": {
"title": "→ UEsim | Radio Unit",
"description": "Configuration of Radio Unit attached to UEsim",
"software-type": "ue",
"shared": true,
"request": "ru/input-schema.json",
"response": "ru/schema.json",
"index": 9
},
"ue/ue": {
"title": "→ UEsim | UE",
"description": "Configuration of UE simulated by UEsim",
"software-type": "ue",
"shared": true,
"request": "ue/input-schema.json",
"response": "ue/schema.json",
"index": 10
},
"ue/cell": {
"title": "→ UEsim | UE Cell",
"description": "Information about Cell to which UEsim attaches",
"software-type": "ue",
"shared": true,
"request": "ue/cell/input-schema.json",
"response": "ue/cell/schema.json",
"index": 11
}
}
}
......@@ -26,6 +26,7 @@
# Here we test:
#
# - enb (see TestENB_*)
# - uesim (see TestUEsim_*)
#
# Currently there is no tests for core-network, because for core-network
# there is no difference in between generic and ORS modes and core-network is
......@@ -57,6 +58,7 @@ setUpModule, _AmariTestCase = makeModuleSetUpAndTestCaseClass(
# - LTE/NR indicate LTE/NR cell with given downlink frequency.
# - BW indicates specified bandwidth.
# - CENB indicates a ENB-kind cell.
# - CUE indicates an UE-kind cell.
# - TAC indicates specified Tracking Area Code.
# - LTE_PEER/NR_PEER indicate an LTE/NR ENB-PEER-kind cell.
# - X2_PEER/XN_PEER indicate an LTE/NR ENB peer.
......@@ -92,6 +94,9 @@ def CENB(cell_id, pci):
'pci': pci,
}
# CUE indicates an UE-kind cell.
CUE = {'cell_kind': 'ue'}
# TAC returns basic parameters to indicate specified Tracking Area Code.
def TAC(tac):
return {
......@@ -659,6 +664,125 @@ class TestENB_Sunwave4 (ENBTestCase4, Sunwave4): pass
class TestENB_RUMultiType4(ENBTestCase4, RUMultiType4): pass
# ---- UEsim ----
# UEsimTestCase4 provides base class for unit-testing UEsim service.
#
# It is similar to ENBTestCase4 but configures UE cells instead of eNB cells.
class UEsimTestCase4(RFTestCase4):
@classmethod
def getInstanceSoftwareType(cls):
return "ue"
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.ue_cfg = cls.rf_cfg = yamlpp_load(cls.ipath('etc/ue.cfg'))
@classmethod
def getInstanceParameterDict(cls):
return {'_': json.dumps({
'testing': True,
})}
@classmethod
def CELLcfg(cls, i):
return CUE
@classmethod
def requestAllShared(cls, imain):
super().requestAllShared(imain)
def UE(i):
ue = {
'ue_type': ('lte', 'nr') [(i-1) % 2],
'rue_addr': 'host%d' % i,
'sim_algo': ('xor', 'milenage', 'tuak') [i-1],
'imsi': '%015d' % i,
'opc': '%032x' % i,
'amf': '0x%04x' % (0x9000+i),
'sqn': '%012x' % i,
'k': 'FFFF%028x' % i,
'impi': 'impi%d@rapid.space' % i,
}
return cls.requestShared(imain, 'UE%d' % i, ue)
UE(1)
UE(2)
UE(3)
# ue parameters
def test_ue_cfg_ue(t):
assertMatch(t, t.ue_cfg['ue_list'], [
dict(
as_release=13, ue_category=13, rue_addr='host1',
sim_algo='xor', amf =0x9001, impi='impi1@rapid.space',
sqn ='000000000001',
imsi='000000000000001',
opc ='00000000000000000000000000000001',
K ='FFFF0000000000000000000000000001',
),
dict(
as_release=15, ue_category='nr', rue_addr='host2',
sim_algo='milenage', amf =0x9002, impi='impi2@rapid.space',
sqn ='000000000002',
imsi='000000000000002',
opc ='00000000000000000000000000000002',
K ='FFFF0000000000000000000000000002',
),
dict(
as_release=13, ue_category=13, rue_addr='host3',
sim_algo='tuak', amf =0x9003, impi='impi3@rapid.space',
sqn ='000000000003',
imsi='000000000000003',
opc ='00000000000000000000000000000003',
K ='FFFF0000000000000000000000000003',
),
])
# cells
def test_ue_cfg_cell(t):
assertMatch(t, t.ue_cfg['cell_groups'], [
dict(
group_type='lte',
cells=[
dict( # CELL1
rf_port=0, n_antenna_dl=4, n_antenna_ul=2,
dl_earfcn=100, ul_earfcn=18100,
bandwidth=5,
),
dict( # CELL2
rf_port=1, n_antenna_dl=4, n_antenna_ul=2,
dl_earfcn=40200, ul_earfcn=40200,
bandwidth=10,
),
]
),
dict(
group_type='nr',
cells=[
dict( # CELL3
rf_port=2, n_antenna_dl=4, n_antenna_ul=2,
dl_nr_arfcn=300300, ul_nr_arfcn=290700, ssb_nr_arfcn=300270, band=74,
bandwidth=15,
),
dict( # CELL4
rf_port=3, n_antenna_dl=4, n_antenna_ul=2,
dl_nr_arfcn=470400, ul_nr_arfcn=470400, ssb_nr_arfcn=470430, band=40,
bandwidth=20,
),
]
)
])
# instantiate UEsim tests
class TestUEsim_SDR4 (UEsimTestCase4, SDR4): pass
class TestUEsim_Lopcomm4 (UEsimTestCase4, Lopcomm4): pass
class TestUEsim_Sunwave4 (UEsimTestCase4, Sunwave4): pass
class TestUEsim_RUMultiType4(UEsimTestCase4, RUMultiType4): pass
# ---- misc ----
# yamlpp_load loads yaml config file after preprocessing it.
......@@ -762,7 +886,7 @@ class TestAssertMatch(unittest.TestCase):
# run only on leaf test classes.
def __dir__():
d = list(sorted(globals().keys()))
abstract = {'AmariTestCase', 'RFTestCase4', 'ENBTestCase4'}
abstract = {'AmariTestCase', 'RFTestCase4', 'ENBTestCase4', 'UEsimTestCase4'}
for _ in abstract:
d.remove(_)
return d
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "UE Cell. Common properties",
"type": "object",
"required": [
"cell_type",
"cell_kind",
"rf_mode",
"ru"
],
"properties": {
"cell_type": {
"type": "string",
"options": { "hidden": true }
},
"cell_kind": {
"type": "string",
"const": "ue",
"template": "ue",
"options": { "hidden": true }
},
"rf_mode": { "$ref": "../../cell/common.json#/properties/rf_mode" },
"ru": { "$ref": "../../cell/common.json#/$defs/ru-of-cell" }
}
}
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "UE Cell",
"type": "object",
"oneOf": [
{ "$ref": "../../ue/cell/lte/input-schema.json" },
{ "$ref": "../../ue/cell/nr/input-schema.json" }
]
}
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "LTE Cell",
"type": "object",
"required": [
"cell_type",
"cell_kind",
"rf_mode",
"ru",
"dl_earfcn",
"bandwidth"
],
"properties": {
"cell_type": {
"$ref": "../../../ue/cell/common.json#/properties/cell_type",
"const": "lte",
"template": "lte"
},
"cell_kind": { "$ref": "../../../ue/cell/common.json#/properties/cell_kind" },
"rf_mode": { "$ref": "../../../ue/cell/common.json#/properties/rf_mode" },
"ru": { "$ref": "../../../ue/cell/common.json#/properties/ru",
"propertyOrder": 9999"
},
"dl_earfcn": { "$ref": "../../../cell/lte/input-schema.json#/properties/dl_earfcn" },
"ul_earfcn": { "$ref": "../../../cell/lte/input-schema.json#/properties/ul_earfcn" },
"bandwidth": {
"$ref": "../../../cell/common.json#/properties/bandwidth",
"enum": [
1.4,
3,
5,
10,
15,
20
]
}
}
}
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "NR Cell",
"type": "object",
"required": [
"cell_type",
"cell_kind",
"rf_mode",
"ru",
"dl_nr_arfcn",
"bandwidth",
"nr_band"
],
"properties": {
"cell_type": {
"$ref": "../../../ue/cell/common.json#/properties/cell_type",
"const": "nr",
"template": "nr"
},
"cell_kind": { "$ref": "../../../ue/cell/common.json#/properties/cell_kind" },
"rf_mode": { "$ref": "../../../ue/cell/common.json#/properties/rf_mode" },
"ru": { "$ref": "../../../ue/cell/common.json#/properties/ru",
"propertyOrder": 9999"
},
"dl_nr_arfcn": { "$ref": "../../../cell/nr/input-schema.json#/properties/dl_nr_arfcn" },
"bandwidth": { "$ref": "../../../cell/common.json#/properties/bandwidth" },
"nr_band": { "$ref": "../../../cell/nr/input-schema.json#/properties/nr_band" },
"ul_nr_arfcn": { "$ref": "../../../cell/nr/input-schema.json#/properties/ul_nr_arfcn" },
"ssb_nr_arfcn": { "$ref": "../../../cell/nr/input-schema.json#/properties/ssb_nr_arfcn" }
}
}
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"description": "Values returned by UE Cell instantiation (stub)",
"type": "object",
"properties": {}
}
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "UE",
"type": "object",
"oneOf": [
{ "$ref": "../ue/lte/input-schema.json" },
{ "$ref": "../ue/nr/input-schema.json" }
]
}
......@@ -11,26 +11,6 @@
"$ref": "#/properties/ue_type",
"const": "lte",
"template": "lte"
},
"dl_earfcn": {
"title": "DL EARFCN",
"description": "Downlink E-UTRA Absolute Radio Frequency Channel Number of the cell",
"type": "number"
},
"bandwidth": {
"title": "Bandwidth",
"description": "Downlink Bandwidth",
"type": "string",
"enum": [
"1.4 MHz",
"3 MHz",
"5 MHz",
"10 MHz",
"15 MHz",
"20 MHz"
],
"default": "20 MHz"
}
}
}
......@@ -9,30 +9,8 @@
"ue_type": {
"$ref": "#/properties/ue_type",
"const": "lte",
"template": "lte"
},
"dl_nr_arfcn": {
"title": "DL NR ARFCN",
"description": "Downlink NR Absolute Radio Frequency Channel Number of the cell",
"type": "number"
},
"band": {
"title": "NR band",
"description": "NR band number",
"type": "number"
},
"bandwidth": {
"title": "Bandwidth",
"description": "Downlink Bandwidth (in MHz)",
"type": "number",
"default": 40
},
"ssb_nr_arfcn": {
"title": "SSB NR ARFCN",
"description": "SSB NR ARFCN, you can retrieve from ENB/GNB side",
"type": "number"
"const": "nr",
"template": "nr"
}
}
}
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"description": "Values returned by UE instantiation (stub)",
"type": "object",
"properties": {}
}
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