Commit 1685efc2 authored by Joanne Hugé's avatar Joanne Hugé

Update Release Candidate

parents be97c578 3ec53860
...@@ -49,16 +49,16 @@ Simpleran SR needs: ...@@ -49,16 +49,16 @@ Simpleran SR needs:
| /opt/amarisoft/v20XX-XX-XX.X | Binaries | | | /opt/amarisoft/v20XX-XX-XX.X | Binaries | |
| /opt/amarisoft/.amarisoft | Licenses | | | /opt/amarisoft/.amarisoft | Licenses | |
| /opt/amarisoft/init-sdr | Init SDR driver | | | /opt/amarisoft/init-sdr | Init SDR driver | |
| /opt/amarisoft/get-sdr-info | Get SDR info | | | /opt/amarisoft/get-amarisoft-info | Get amarisoft info | |
| /opt/amarisoft/get-license-info | Get license info | |
| /opt/amarisoft/rm-tmp-lte | Remove files in /tmp | Configure amarisoft to disable this lock | | /opt/amarisoft/rm-tmp-lte | Remove files in /tmp | Configure amarisoft to disable this lock |
| /opt/amarisoft/init-enb | Set performance governor | Do it in playbook | | /opt/amarisoft/init-enb | Set performance governor | Do it in playbook |
| /opt/amarisoft/init-ue | | Do it in playbook | | /opt/amarisoft/init-ue | | Do it in playbook |
| /opt/amarisoft/init-mme | | Do it in playbook | | /opt/amarisoft/init-mme | | Do it in playbook |
| /opt/amarisoft/format-ims | Format IMS slaptun | Do it in slapformat | | /opt/sdr/get-sdr-info | Get SDR info | |
| /opt/simpleran/format-ims | Format IMS slaptun | Do it in slapformat |
Playbook needs: Playbook needs:
| Path | Use | How to remove (if possible ) | | Path | Use | How to remove (if possible ) |
|------------------------------------|--------------------------|------------------------------------------| |------------------------------------|--------------------------|------------------------------------------|
| /opt/amarisoft/get-license-info | Get license info | | | /opt/amarisoft/get-amarisoft-info | Get amarisoft info | |
...@@ -16,27 +16,27 @@ ...@@ -16,27 +16,27 @@
[template] [template]
filename = instance.cfg filename = instance.cfg
md5sum = bb6cb40fe200d03435c5c5eae27af958 md5sum = 9013df1ac77d35a1fc8df37bb5615dcd
[template-ors] [template-ors]
filename = instance-ors.cfg filename = instance-ors.cfg
md5sum = 8c2abee8eb0a538ad8ae1a84e140af69 md5sum = 307e38207945a9adcfea0263cba9d3a6
[slaplte.jinja2] [slaplte.jinja2]
_update_hash_filename_ = slaplte.jinja2 _update_hash_filename_ = slaplte.jinja2
md5sum = 8d6eb90fc1191c3a1b24200df2ebf4fa md5sum = 80f86d108ce8634f9577356ce074a560
[ru_amarisoft-stats.jinja2.py] [ru_amarisoft-stats.jinja2.py]
_update_hash_filename_ = ru/amarisoft-stats.jinja2.py _update_hash_filename_ = ru/amarisoft-stats.jinja2.py
md5sum = 31b609f80a82b6efed963161c8907878 md5sum = b492c3a520d48b9c45ea583eec435109
[ru_amarisoft-rf-info.jinja2.py] [ru_amarisoft-rf-info.jinja2.py]
_update_hash_filename_ = ru/amarisoft-rf-info.jinja2.py _update_hash_filename_ = ru/amarisoft-rf-info.jinja2.py
md5sum = 93a5e07a763b619747255b4e03b50bbe md5sum = 3b6c08d7685e7c93ab451bec25e4815f
[ru_libinstance.jinja2.cfg] [ru_libinstance.jinja2.cfg]
_update_hash_filename_ = ru/libinstance.jinja2.cfg _update_hash_filename_ = ru/libinstance.jinja2.cfg
md5sum = f0d7d38ef486f5be44020c3d5ce2a94f md5sum = 349b02e6993409361176a865b780b871
[ru_sdr_libinstance.jinja2.cfg] [ru_sdr_libinstance.jinja2.cfg]
_update_hash_filename_ = ru/sdr/libinstance.jinja2.cfg _update_hash_filename_ = ru/sdr/libinstance.jinja2.cfg
...@@ -60,23 +60,23 @@ md5sum = 52da9fe3a569199e35ad89ae1a44c30e ...@@ -60,23 +60,23 @@ md5sum = 52da9fe3a569199e35ad89ae1a44c30e
[template-enb] [template-enb]
_update_hash_filename_ = instance-enb.jinja2.cfg _update_hash_filename_ = instance-enb.jinja2.cfg
md5sum = b116b58365600f12129d458750b57c71 md5sum = 04b723fc2a3d5555243921823b0e087b
[template-ors-enb] [template-ors-enb]
_update_hash_filename_ = instance-ors-enb.jinja2.cfg _update_hash_filename_ = instance-ors-enb.jinja2.cfg
md5sum = 585457493ce5302ba1f1073b8a3b877c md5sum = bdc8ca95cad8374f24af7ab6a276b61c
[template-ors-ue] [template-ors-ue]
_update_hash_filename_ = instance-ors-ue.jinja2.cfg _update_hash_filename_ = instance-ors-ue.jinja2.cfg
md5sum = f4389a92fb111447e7976e452db78607 md5sum = 82449c34a4632191931ce8aa88ce72e6
[template-core-network] [template-core-network]
_update_hash_filename_ = instance-core-network.jinja2.cfg _update_hash_filename_ = instance-core-network.jinja2.cfg
md5sum = dab992c02a363e00cdc86f102a7ae489 md5sum = 92fd8377819ae6e844f77937cecfa605
[template-ue] [template-ue]
_update_hash_filename_ = instance-ue.jinja2.cfg _update_hash_filename_ = instance-ue.jinja2.cfg
md5sum = 0c387a13a57f7270595b74e11be8eb36 md5sum = 763fa11181527bf4c481fd2e6a2f7c59
[template-obsolete] [template-obsolete]
_update_hash_filename_ = instance-obsolete.jinja2.cfg _update_hash_filename_ = instance-obsolete.jinja2.cfg
...@@ -88,7 +88,7 @@ md5sum = dd50b4e4780830ddbde28b84af118f18 ...@@ -88,7 +88,7 @@ md5sum = dd50b4e4780830ddbde28b84af118f18
[enb.jinja2.cfg] [enb.jinja2.cfg]
filename = config/enb.jinja2.cfg filename = config/enb.jinja2.cfg
md5sum = 573cb004c21aa5f9ad8baf7b4dbbeb43 md5sum = d19d631a0181a5449be8859274d4fade
[drb_lte.jinja2.cfg] [drb_lte.jinja2.cfg]
filename = config/drb_lte.jinja2.cfg filename = config/drb_lte.jinja2.cfg
...@@ -108,7 +108,7 @@ md5sum = 9dbd93036c15c87c6de74b88b34062b6 ...@@ -108,7 +108,7 @@ md5sum = 9dbd93036c15c87c6de74b88b34062b6
[mme.jinja2.cfg] [mme.jinja2.cfg]
filename = config/mme.jinja2.cfg filename = config/mme.jinja2.cfg
md5sum = b86f0e7a0d890771d56aee22838d6487 md5sum = eff3bd1b191cfab251a602ad99a8316e
[dnsmasq-core-network.jinja2.cfg] [dnsmasq-core-network.jinja2.cfg]
filename = config/dnsmasq-core-network.jinja2.cfg filename = config/dnsmasq-core-network.jinja2.cfg
...@@ -120,11 +120,11 @@ md5sum = 95f4f8fb85e0480eb3e9059b9db26540 ...@@ -120,11 +120,11 @@ md5sum = 95f4f8fb85e0480eb3e9059b9db26540
[ims.jinja2.cfg] [ims.jinja2.cfg]
filename = config/ims.jinja2.cfg filename = config/ims.jinja2.cfg
md5sum = f07c85916bcb7e4002c8edc3d087c1be md5sum = 8379c4edcccc03db94acceca77e3cd07
[ue.jinja2.cfg] [ue.jinja2.cfg]
filename = config/ue.jinja2.cfg filename = config/ue.jinja2.cfg
md5sum = 1c65b7227d1416a636a3f04fcabddcdf md5sum = 9b095aed884849a712366e6c2e5953c7
[software.cfg.html] [software.cfg.html]
_update_hash_filename_ = gadget/software.cfg.html _update_hash_filename_ = gadget/software.cfg.html
......
Changelog Changelog
========= =========
Version 1.0.383 (2024-12-11)
-------------
* Amarisoft version is now required to be 2024-11-21 for this version of the software release
* Support handover between 4G and 5G
* Generate unique values on ORS for the following parameters:
- eNB ID
- gNB ID
- Cell ID
- Physical Cell ID
- Root Sequence Index
* Add PDN list parameter in core-network
* Allow to configure multiple iperf3 servers
* Publish MAC address
Version 1.0.379 (2024-10-09) Version 1.0.379 (2024-10-09)
------------- -------------
......
...@@ -4,7 +4,9 @@ ...@@ -4,7 +4,9 @@
{%- set jcell_ru_ref = slaplte.jcell_ru_ref %} {%- set jcell_ru_ref = slaplte.jcell_ru_ref %}
{%- set ierror = slaplte.ierror %} {%- set ierror = slaplte.ierror %}
{%- set bug = slaplte.bug %} {%- set bug = slaplte.bug %}
{#-
#}
{#- for standalone testing via slapos-render-config.py {#- for standalone testing via slapos-render-config.py
NOTE: keep in sync with instance-enb.jinja2.cfg and ru/libinstance.jinja2.cfg #} NOTE: keep in sync with instance-enb.jinja2.cfg and ru/libinstance.jinja2.cfg #}
{%- if _standalone is defined %} {%- if _standalone is defined %}
...@@ -17,16 +19,18 @@ ...@@ -17,16 +19,18 @@
{%- do slaplte.load_ipeercell(ipeercell_dict) %} {%- do slaplte.load_ipeercell(ipeercell_dict) %}
{%- do slaplte.check_loaded_everything() %} {%- do slaplte.check_loaded_everything() %}
{%- endif %} {%- endif %}
{#-
#}
{#- do_lte/do_nr indicate whether we have LTE and/or NR cells {#- do_lte/do_nr indicate whether we have LTE and/or NR cells
icell_dict_lte/icell_dict_nr keep LTE/NR parts of icell_dict registry #} icell_dict_lte/icell_dict_nr keep LTE/NR parts of icell_dict registry #}
{%- set icell_dict_lte = dict(icell_dict|dictsort | selectattr('1._.cell_type', '==', 'lte')) %} {%- set icell_dict_lte = dict(icell_dict|dictsort | selectattr('1._.cell_type', '==', 'lte')) %}
{%- set icell_dict_nr = dict(icell_dict|dictsort | selectattr('1._.cell_type', '==', 'nr' )) %} {%- set icell_dict_nr = dict(icell_dict|dictsort | selectattr('1._.cell_type', '==', 'nr' )) %}
{%- set do_lte = len(icell_dict_lte) > 0 %} {%- set do_lte = len(icell_dict_lte) > 0 %}
{%- set do_nr = len(icell_dict_nr) > 0 %} {%- set do_nr = len(icell_dict_nr) > 0 %}
{#-
#}
{#- handover_config emits handover configuration for specified cell #} {#- handover_config emits handover configuration for specified cell #}
{%- macro handover_config(cell_ref) %} {%- macro handover_config(cell_ref) %}
ncell_list: [ ncell_list: [
...@@ -55,7 +59,6 @@ ...@@ -55,7 +59,6 @@
}, },
{%- endif %} {%- endif %}
{%- endfor %} {%- endfor %}
// Inter-ENB HO // Inter-ENB HO
{#- TODO: add info about peers as shared instances - one instance per peer *ENB*. {#- TODO: add info about peers as shared instances - one instance per peer *ENB*.
then query SlapOS Master about cells configured on that peer ENB and then query SlapOS Master about cells configured on that peer ENB and
...@@ -69,6 +72,7 @@ ...@@ -69,6 +72,7 @@
n_id_cell: {{ ncell.pci }}, n_id_cell: {{ ncell.pci }},
dl_earfcn: {{ ncell.dl_earfcn }}, dl_earfcn: {{ ncell.dl_earfcn }},
tac: {{ ncell.tac }}, tac: {{ ncell.tac }},
plmn: "{{ ncell.plmn }}",
{#- TODO: consider extending peer/cell/lte with {#- TODO: consider extending peer/cell/lte with
.allowed_meas_bandwidth and .antenna_port_1 #} .allowed_meas_bandwidth and .antenna_port_1 #}
allowed_meas_bandwidth: {{ jlte_n_rb_dl(1.4) }}, // (minimum possible bw) allowed_meas_bandwidth: {{ jlte_n_rb_dl(1.4) }}, // (minimum possible bw)
...@@ -83,6 +87,7 @@ ...@@ -83,6 +87,7 @@
ssb_nr_arfcn: {{ ncell.ssb_nr_arfcn }}, ssb_nr_arfcn: {{ ncell.ssb_nr_arfcn }},
ul_nr_arfcn: {{ ncell.ul_nr_arfcn }}, ul_nr_arfcn: {{ ncell.ul_nr_arfcn }},
tac: {{ ncell.tac }}, tac: {{ ncell.tac }},
plmn: "{{ ncell.plmn }}",
ssb_subcarrier_spacing: 30, ssb_subcarrier_spacing: 30,
ssb_period: 20, ssb_period: 20,
ssb_offset: 0, ssb_offset: 0,
...@@ -94,7 +99,9 @@ ...@@ -94,7 +99,9 @@
{%- endfor %} {%- endfor %}
], ],
{%- endmacro %} {%- endmacro %}
{#-
#}
{#- jlte_n_rb_dl returns n_rb_dl for an LTE bandwidth. #} {#- jlte_n_rb_dl returns n_rb_dl for an LTE bandwidth. #}
{%- macro jlte_n_rb_dl(bandwidth) %} {%- macro jlte_n_rb_dl(bandwidth) %}
{%- set _ = {1.4: 6, {%- set _ = {1.4: 6,
...@@ -105,7 +112,9 @@ ...@@ -105,7 +112,9 @@
20: 100} %} 20: 100} %}
{{- _[bandwidth] | tojson }} {{- _[bandwidth] | tojson }}
{%- endmacro %} {%- endmacro %}
{#-
#}
{#- jhostport splits address into (host,port) pair. #} {#- jhostport splits address into (host,port) pair. #}
{%- macro jhostport(addr) %} {%- macro jhostport(addr) %}
{%- set _ = namespace() %} {%- set _ = namespace() %}
...@@ -129,8 +138,9 @@ ...@@ -129,8 +138,9 @@
{%- endif %} {%- endif %}
{{- (_.host, _.port) | tojson }} {{- (_.host, _.port) | tojson }}
{%- endmacro -%} {%- endmacro -%}
{#-
#}
{#- start of the config -#} {#- start of the config -#}
{ {
log_options: "all.level=error,all.max_size=0,nas.level=debug,nas.max_size=1,s1ap.level=debug,s1ap.max_size=1,x2ap.level=debug,x2ap.max_size=1,rrc.level=debug,rrc.max_size=1,ngap.level=debug,ngap.max_size=1,xnap.level=debug,xnap.max_size=1, log_options: "all.level=error,all.max_size=0,nas.level=debug,nas.max_size=1,s1ap.level=debug,s1ap.max_size=1,x2ap.level=debug,x2ap.max_size=1,rrc.level=debug,rrc.max_size=1,ngap.level=debug,ngap.max_size=1,xnap.level=debug,xnap.max_size=1,
...@@ -141,21 +151,20 @@ ...@@ -141,21 +151,20 @@
{%- endif -%} {%- endif -%}
,file.rotate=200M", ,file.rotate=200M",
log_filename: "{{ directory['log'] }}/enb.log", log_filename: "{{ directory['log'] }}/enb.log",
{#-
{# instantiate radio units #} #}
{#- instantiate radio units #}
{{ slaplte.ru_config(iru_dict, slapparameter_dict, True) }} {{ slaplte.ru_config(iru_dict, slapparameter_dict, True) }}
com_addr: "{{ slapparameter_dict.com_addr }}:{{ slapparameter_dict.com_ws_port }}", com_addr: "{{ slapparameter_dict.com_addr }}:{{ slapparameter_dict.com_ws_port }}",
com_auth: { com_auth: {
password: "{{ websocket_password }}", password: "{{ websocket_password }}",
unsecure: false, unsecure: false,
}, },
{%- if slapparameter_dict.get('mbmsgw_addr', '') %} {%- if slapparameter_dict.get('mbmsgw_addr', '') %}
mbmsgw_addr: "{{ slapparameter_dict.mbmsgw_addr }}", mbmsgw_addr: "{{ slapparameter_dict.mbmsgw_addr }}",
{%- endif %} {%- endif %}
{%- if do_lte %}
{% if do_lte %}
// LTE core network // LTE core network
mme_list: [ mme_list: [
{%- for _, mme in slapparameter_dict.mme_list |dictsort %} {%- for _, mme in slapparameter_dict.mme_list |dictsort %}
...@@ -168,8 +177,7 @@ ...@@ -168,8 +177,7 @@
{%- endfor %} {%- endfor %}
], ],
{%- endif %} {%- endif %}
{%- if do_nr %}
{% if do_nr %}
// NR core network // NR core network
amf_list: [ amf_list: [
{%- for _, amf in slapparameter_dict.amf_list |dictsort %} {%- for _, amf in slapparameter_dict.amf_list |dictsort %}
...@@ -182,7 +190,6 @@ ...@@ -182,7 +190,6 @@
{%- endfor %} {%- endfor %}
], ],
{%- endif %} {%- endif %}
{#- listen-address for GTP-U - either explicitly given, or autodetect #} {#- listen-address for GTP-U - either explicitly given, or autodetect #}
{%- if slapparameter_dict.get('gtp_addr') %} {%- if slapparameter_dict.get('gtp_addr') %}
gtp_addr: "{{ slapparameter_dict.gtp_addr }}", gtp_addr: "{{ slapparameter_dict.gtp_addr }}",
...@@ -214,7 +221,9 @@ ...@@ -214,7 +221,9 @@
{%- endif %} {%- endif %}
{%- endif %} {%- endif %}
{%- endif %} {%- endif %}
{#-
#}
{#- X2/Xn peers {#- X2/Xn peers
TODO: add info about peers as shared instances - one instance per peer *ENB*. TODO: add info about peers as shared instances - one instance per peer *ENB*.
then query SlapOS Master about cells configured on that peer ENB and then query SlapOS Master about cells configured on that peer ENB and
...@@ -229,8 +238,9 @@ ...@@ -229,8 +238,9 @@
| map(attribute='1._.xn_addr') | map(attribute='1._.xn_addr')
| list | tojson }}, | list | tojson }},
{%- endif %} {%- endif %}
{#-
#}
{%- if do_lte %} {%- if do_lte %}
enb_id: {{ slapparameter_dict.enb_id }}, enb_id: {{ slapparameter_dict.enb_id }},
{%- endif %} {%- endif %}
...@@ -239,7 +249,6 @@ ...@@ -239,7 +249,6 @@
gnb_id: {{ slapparameter_dict.gnb_id }}, gnb_id: {{ slapparameter_dict.gnb_id }},
en_dc_support: true, en_dc_support: true,
{%- endif %} {%- endif %}
// LTE cells // LTE cells
cell_list: [ cell_list: [
{%- if do_lte %} {%- if do_lte %}
...@@ -248,13 +257,11 @@ ...@@ -248,13 +257,11 @@
{%- set ru_ref = J(jcell_ru_ref(icell, icell_dict)) %} {%- set ru_ref = J(jcell_ru_ref(icell, icell_dict)) %}
{%- set iru = iru_dict[ru_ref] %} {%- set iru = iru_dict[ru_ref] %}
{%- set ru = iru['_'] %} {%- set ru = iru['_'] %}
// {{ B(cell_ref) }} ({{ B(ru_ref) }}) // {{ B(cell_ref) }} ({{ B(ru_ref) }})
{ {
rf_port: {{ ru._rf_port }}, rf_port: {{ ru._rf_port }},
n_antenna_dl: {{ ru.n_antenna_dl }}, n_antenna_dl: {{ ru.n_antenna_dl }},
n_antenna_ul: {{ ru.n_antenna_ul }}, n_antenna_ul: {{ ru.n_antenna_ul }},
cell_id: {{ cell.cell_id }}, cell_id: {{ cell.cell_id }},
tac: {{ cell.tac }}, tac: {{ cell.tac }},
n_id_cell: {{ cell.pci }}, n_id_cell: {{ cell.pci }},
...@@ -262,11 +269,8 @@ ...@@ -262,11 +269,8 @@
ul_earfcn: {{ cell.ul_earfcn }}, ul_earfcn: {{ cell.ul_earfcn }},
root_sequence_index: {{ cell.root_sequence_index }}, root_sequence_index: {{ cell.root_sequence_index }},
inactivity_timer: {{ cell.inactivity_timer }}, inactivity_timer: {{ cell.inactivity_timer }},
// Handover // Handover
{{- handover_config(cell_ref) }} {{- handover_config(cell_ref) }}
// Carrier Aggregation: LTE + LTE // Carrier Aggregation: LTE + LTE
scell_list: [ scell_list: [
{%- for cell2_ref, icell2 in icell_dict_lte|dictsort %} {%- for cell2_ref, icell2 in icell_dict_lte|dictsort %}
...@@ -279,7 +283,6 @@ ...@@ -279,7 +283,6 @@
{%- endif %} {%- endif %}
{%- endfor %} {%- endfor %}
], ],
{%- if do_nr %} {%- if do_nr %}
// Dual Connectivity: LTE + NR // Dual Connectivity: LTE + NR
en_dc_scg_cell_list: [ en_dc_scg_cell_list: [
...@@ -293,13 +296,10 @@ ...@@ -293,13 +296,10 @@
{%- endfor %} {%- endfor %}
], ],
{%- endif %} {%- endif %}
// tune LTE parameters for the cell // tune LTE parameters for the cell
{% if ors %} {%- if ors %}
manual_ref_signal_power: true, manual_ref_signal_power: true,
{% endif %} {%- endif %}
{%- set tdd = (cell.rf_mode == 'tdd') %} {%- set tdd = (cell.rf_mode == 'tdd') %}
{%- if tdd %} {%- if tdd %}
uldl_config: {{ uldl_config: {{
...@@ -309,20 +309,16 @@ ...@@ -309,20 +309,16 @@
}}, }},
sp_config: 7, sp_config: 7,
{%- endif %} {%- endif %}
{%- set n_rb_dl = J(jlte_n_rb_dl(cell.bandwidth)) %} {%- set n_rb_dl = J(jlte_n_rb_dl(cell.bandwidth)) %}
n_rb_dl: {{ n_rb_dl }}, n_rb_dl: {{ n_rb_dl }},
si_coderate: {{ 0.60 if n_rb_dl == 6 else 0.20 }}, si_coderate: {{ 0.60 if n_rb_dl == 6 else 0.20 }},
pdsch_dedicated: { pdsch_dedicated: {
p_a: {{ {4: -6, 2: -3}.get(ru.n_antenna_dl, 0) }}, p_a: {{ {4: -6, 2: -3}.get(ru.n_antenna_dl, 0) }},
p_b: -1, p_b: -1,
}, },
pdcch_format: {{ 1 if n_rb_dl == 6 else 2 }}, pdcch_format: {{ 1 if n_rb_dl == 6 else 2 }},
prach_config_index: {{ 0 if n_rb_dl == 6 else 4 }}, prach_config_index: {{ 0 if n_rb_dl == 6 else 4 }},
initial_cqi: {{ 5 if n_rb_dl == 6 else 3 }}, initial_cqi: {{ 5 if n_rb_dl == 6 else 3 }},
pucch_dedicated: { pucch_dedicated: {
n1_pucch_sr_count: 11, n1_pucch_sr_count: 11,
cqi_pucch_n_rb: 1, cqi_pucch_n_rb: 1,
...@@ -339,12 +335,10 @@ ...@@ -339,12 +335,10 @@
tdd_ack_nack_feedback_mode: "multiplexing", /* TDD only */ tdd_ack_nack_feedback_mode: "multiplexing", /* TDD only */
{%- endif %} {%- endif %}
}, },
{%- if ru.n_antenna_dl >= 2 %} {%- if ru.n_antenna_dl >= 2 %}
m_ri: 8, m_ri: 8,
transmission_mode: 3, transmission_mode: 3,
{%- endif %} {%- endif %}
srs_dedicated: { srs_dedicated: {
{%- if n_rb_dl == 6 %} {%- if n_rb_dl == 6 %}
srs_bandwidth_config: 7, srs_bandwidth_config: 7,
...@@ -369,9 +363,7 @@ ...@@ -369,9 +363,7 @@
srs_period: 40, srs_period: 40,
srs_hopping_bandwidth: 0, srs_hopping_bandwidth: 0,
}, },
drb_config: "{{ B('%s-drb.cfg' % cell_ref) }}", drb_config: "{{ B('%s-drb.cfg' % cell_ref) }}",
sib_sched_list: [ sib_sched_list: [
{ {
filename: "{{ B('%s-sib23.asn' % cell_ref) }}", filename: "{{ B('%s-sib23.asn' % cell_ref) }}",
...@@ -382,7 +374,6 @@ ...@@ -382,7 +374,6 @@
{%- endfor %} {%- endfor %}
{%- endif %} {%- endif %}
], ],
{%- if do_lte %} {%- if do_lte %}
cell_default: { cell_default: {
plmn_list: [ plmn_list: [
...@@ -395,37 +386,26 @@ ...@@ -395,37 +386,26 @@
{%- endfor %} {%- endfor %}
], ],
cyclic_prefix: "normal", cyclic_prefix: "normal",
phich_duration: "normal", phich_duration: "normal",
phich_resource: "1", phich_resource: "1",
si_value_tag: 0, si_value_tag: 0,
cell_barred: false, cell_barred: false,
intra_freq_reselection: true, intra_freq_reselection: true,
q_rx_lev_min: -70, q_rx_lev_min: -70,
si_window_length: 40, si_window_length: 40,
si_pdcch_format: 2, si_pdcch_format: 2,
n_symb_cch: 0, n_symb_cch: 0,
prach_freq_offset: -1, prach_freq_offset: -1,
pusch_dedicated: { pusch_dedicated: {
beta_offset_ack_index: 9, beta_offset_ack_index: 9,
beta_offset_ri_index: 6, beta_offset_ri_index: 6,
beta_offset_cqi_index: 6, beta_offset_cqi_index: 6,
}, },
pusch_hopping_offset: -1, pusch_hopping_offset: -1,
pusch_msg3_mcs: 0, pusch_msg3_mcs: 0,
dl_256qam: true, dl_256qam: true,
ul_64qam: true, ul_64qam: true,
sr_period: 20, sr_period: 20,
cqi_period: 40, cqi_period: 40,
{%- if ors %} {%- if ors %}
mac_config: { mac_config: {
...@@ -440,15 +420,11 @@ ...@@ -440,15 +420,11 @@
}, },
dpc_pucch_snr_target: 20, dpc_pucch_snr_target: 20,
{%- endif %} {%- endif %}
pusch_max_its: 6, pusch_max_its: 6,
dpc: true, dpc: true,
dpc_pusch_snr_target: 25, dpc_pusch_snr_target: 25,
cipher_algo_pref: [], cipher_algo_pref: [],
integ_algo_pref: [2, 1], integ_algo_pref: [2, 1],
srb_config: [ srb_config: [
{ {
id: 1, id: 1,
...@@ -463,28 +439,111 @@ ...@@ -463,28 +439,111 @@
t_PollRetransmit: 60, t_PollRetransmit: 60,
} }
], ],
{#- TODO fully expose lte meas_config_desc in generic SR #}
{# TODO fully expose lte meas_config_desc in generic SR #} {%- if (len(icell_dict) + len(ipeercell_dict)) > 1 %}
meas_config_desc: { meas_config_desc: {
a1_report_type: "rsrp", a1_report_type: "rsrp",
a1_rsrp: -70, a1_rsrp: {{ slapparameter_dict.handover_a1_rsrp }},
a1_hysteresis: 0, a1_hysteresis: {{ slapparameter_dict.handover_a1_hysteresis }},
a1_time_to_trigger: 640, a1_time_to_trigger: {{ slapparameter_dict.handover_a1_time_to_trigger }},
a2_report_type: "rsrp", a2_report_type: "rsrp",
a2_rsrp: -80, a2_rsrp: {{ slapparameter_dict.handover_a2_rsrp }},
a2_hysteresis: 0, a2_hysteresis: {{ slapparameter_dict.handover_a2_hysteresis }},
a2_time_to_trigger: 640, a2_time_to_trigger: {{ slapparameter_dict.handover_a2_time_to_trigger }},
eutra_handover: {
{%- if 'a3_rsrp' in slapparameter_dict.eutra_eutra_handover.event %}
a3_report_type: "rsrp", a3_report_type: "rsrp",
a3_offset: {{ slapparameter_dict.get('lte_handover_a3_offset', 6) }}, a3_offset: {{ slapparameter_dict.eutra_eutra_handover.event.a3_rsrp }},
a3_hysteresis: 0, {%- elif 'a4_rsrp' in slapparameter_dict.eutra_eutra_handover.event %}
a3_time_to_trigger: {{ slapparameter_dict.get('lte_handover_a3_time_to_trigger', 480) }}, a4_report_type: "rsrp",
a4_threshold_rsrp: {{ slapparameter_dict.eutra_eutra_handover.event.a4_rsrp }},
{%- elif 'a5_rsrp' in slapparameter_dict.eutra_eutra_handover.event %}
a5_report_type: "rsrp",
a5_threshold1_rsrp: {{ slapparameter_dict.eutra_eutra_handover.event.a5_threshold1_rsrp }},
a5_threshold2_rsrp: {{ slapparameter_dict.eutra_eutra_handover.event.a5_threshold2_rsrp }},
{%- endif %}
hysteresis: {{ slapparameter_dict.eutra_eutra_handover.hysteresis }},
time_to_trigger: {{ slapparameter_dict.eutra_eutra_handover.time_to_trigger }}
{%- if len(list(ipeercell_dict|dictsort | selectattr('1._.cell_type', '==', 'nr'))) > 0 %}
},
nr_handover: {
{%- if 'b1_rsrp' in slapparameter_dict.eutra_nr_handover.event %}
b1_report_type: "rsrp",
b1_threshold_rsrp: {{ slapparameter_dict.eutra_nr_handover.event.b1_rsrp }},
{%- elif 'b2_rsrp' in slapparameter_dict.eutra_nr_handover.event %}
b2_report_type: "rsrp",
b2_threshold1_rsrp: {{ slapparameter_dict.eutra_nr_handover.event.b2_threshold1_rsrp }},
b2_threshold2_rsrp: {{ slapparameter_dict.eutra_nr_handover.event.b2_threshold2_rsrp }},
{%- endif %}
hysteresis: {{ slapparameter_dict.eutra_nr_handover.hysteresis }},
time_to_trigger: {{ slapparameter_dict.eutra_nr_handover.time_to_trigger }}
}, },
{%- else %}
}
{%- endif %}
},
{%- if slapparameter_dict.handover_meas_gap_config == 'Gap Pattern 1' %}
meas_gap_config: "gp1",
{%- elif slapparameter_dict.handover_meas_gap_config == 'Gap Pattern 0' %}
meas_gap_config: "gp0", meas_gap_config: "gp0",
{%- else %}
meas_gap_config: "none",
{%- endif %}
ho_from_meas: true, ho_from_meas: true,
{%- set nr_bands = list(ipeercell_dict | dictsort | selectattr('1._.cell_type', '==', 'nr') | map(attribute='1._.nr_band')) | unique %}
{%- set lte_bands = list(ipeercell_dict | dictsort | selectattr('1._.cell_type', '==', 'lte') | map(attribute='1._.lte_band')) %}
requested_freq_bands_nr_mrdc: [
{%- for band in nr_bands -%}
{
rat: "nr",
band_nr: {{ band }},
max_bandwidth_requested_dl: 100,
max_bandwidth_requested_ul: 100,
max_carriers_requested_dl: 2,
max_carriers_requested_ul: 2,
}, },
{%- endif %} {%- endfor %}
{%- for band in lte_bands -%}
{
rat: "eutra",
band_eutra: {{ band }},
ca_bandwidth_class_dl: "b",
ca_bandwidth_class_ul: "b",
},
{%- endfor %}
],
requested_freq_bands_nr: [
{%- for band in nr_bands -%}
{
rat: "nr",
band_nr: {{ band }},
max_bandwidth_requested_dl: 100,
max_bandwidth_requested_ul: 100,
max_carriers_requested_dl: 2,
max_carriers_requested_ul: 2,
},
{%- endfor %}
{%- for band in lte_bands -%}
{
rat: "eutra",
band_eutra: {{ band }},
ca_bandwidth_class_dl: "b",
ca_bandwidth_class_ul: "b",
},
{%- endfor %}
],
requested_eutra_freq_bands: [
{%- for band in lte_bands -%}
{{ band }},
{%- endfor -%}
],
{% if do_nr %} {%- endif %}
},
{%- endif %}
{%- if do_nr %}
// NR cells // NR cells
nr_cell_list: [ nr_cell_list: [
{%- for cell_ref, icell in icell_dict_nr|dictsort %} {%- for cell_ref, icell in icell_dict_nr|dictsort %}
...@@ -492,30 +551,24 @@ ...@@ -492,30 +551,24 @@
{%- set ru_ref = J(jcell_ru_ref(icell, icell_dict)) %} {%- set ru_ref = J(jcell_ru_ref(icell, icell_dict)) %}
{%- set iru = iru_dict[ru_ref] %} {%- set iru = iru_dict[ru_ref] %}
{%- set ru = iru['_'] %} {%- set ru = iru['_'] %}
// {{ B(cell_ref) }} ({{ B(ru_ref) }}) // {{ B(cell_ref) }} ({{ B(ru_ref) }})
{ {
rf_port: {{ ru._rf_port }}, rf_port: {{ ru._rf_port }},
n_antenna_dl: {{ ru.n_antenna_dl }}, n_antenna_dl: {{ ru.n_antenna_dl }},
n_antenna_ul: {{ ru.n_antenna_ul }}, n_antenna_ul: {{ ru.n_antenna_ul }},
cell_id: {{ cell.cell_id }}, cell_id: {{ cell.cell_id }},
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 }}, ul_nr_arfcn: {{ cell.ul_nr_arfcn }},
bandwidth: {{ cell.bandwidth }}, bandwidth: {{ cell.bandwidth }},
subcarrier_spacing: {{ cell.subcarrier_spacing }}, subcarrier_spacing: {{ cell.subcarrier_spacing }},
ssb_nr_arfcn: {{ cell.ssb_nr_arfcn }}, 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 }},
inactivity_timer: {{ cell.inactivity_timer }}, inactivity_timer: {{ cell.inactivity_timer }},
// Handover // Handover
{{- handover_config(cell_ref) }} {{- handover_config(cell_ref) }}
// Carrier Aggregation: NR + NR // Carrier Aggregation: NR + NR
scell_list: [ scell_list: [
{%- for cell2_ref, icell2 in icell_dict_nr|dictsort %} {%- for cell2_ref, icell2 in icell_dict_nr|dictsort %}
...@@ -527,10 +580,8 @@ ...@@ -527,10 +580,8 @@
{%- endif %} {%- endif %}
{%- endfor %} {%- endfor %}
], ],
{#- NOTE: NR + LTE Dual Connectivity is setup via EN-DC only - via en_dc_scg_cell_list. {#- NOTE: NR + LTE Dual Connectivity is setup via EN-DC only - via en_dc_scg_cell_list.
nr_dc_scg_cell_list sets up NR+NR Dual Connectivity #} nr_dc_scg_cell_list sets up NR+NR Dual Connectivity #}
// tune NR parameters for the cell // tune NR parameters for the cell
{%- if ors %} {%- if ors %}
manual_ref_signal_power: true, manual_ref_signal_power: true,
...@@ -540,7 +591,6 @@ ...@@ -540,7 +591,6 @@
ss_pbch_block_power: {{ ru.tx_gain - 35 }}, ss_pbch_block_power: {{ ru.tx_gain - 35 }},
{%- endif -%} {%- endif -%}
{%- endif %} {%- endif %}
{%- set tdd = (cell.rf_mode == 'tdd') %} {%- set tdd = (cell.rf_mode == 'tdd') %}
{%- set tdd_config = {%- set tdd_config =
{'5ms 2UL 7DL 4/6 (default)': 1, {'5ms 2UL 7DL 4/6 (default)': 1,
...@@ -549,7 +599,7 @@ ...@@ -549,7 +599,7 @@
'5ms 6UL 3DL 10/2 (high uplink)': 4} '5ms 6UL 3DL 10/2 (high uplink)': 4}
[cell.tdd_ul_dl_config] [cell.tdd_ul_dl_config]
if tdd else None %} if tdd else None %}
{% if tdd_config == 1 %} {%- if tdd_config == 1 %}
tdd_ul_dl_config: { tdd_ul_dl_config: {
pattern1: { pattern1: {
period: 5, period: 5,
...@@ -559,7 +609,7 @@ ...@@ -559,7 +609,7 @@
ul_symbols: 4, ul_symbols: 4,
}, },
}, },
{% elif tdd_config == 2 %} {%- elif tdd_config == 2 %}
tdd_ul_dl_config: { tdd_ul_dl_config: {
pattern1: { pattern1: {
period: 2.5, period: 2.5,
...@@ -569,7 +619,7 @@ ...@@ -569,7 +619,7 @@
ul_symbols: 2, ul_symbols: 2,
}, },
}, },
{% elif tdd_config == 3 %} {%- elif tdd_config == 3 %}
tdd_ul_dl_config: { tdd_ul_dl_config: {
pattern1: { pattern1: {
period: 5, /* in ms */ period: 5, /* in ms */
...@@ -579,7 +629,7 @@ ...@@ -579,7 +629,7 @@
ul_symbols: 2, ul_symbols: 2,
}, },
}, },
{% elif tdd_config == 4 %} {%- elif tdd_config == 4 %}
tdd_ul_dl_config: { tdd_ul_dl_config: {
pattern1: { pattern1: {
period: 5, /* in ms */ period: 5, /* in ms */
...@@ -589,15 +639,13 @@ ...@@ -589,15 +639,13 @@
ul_symbols: 10, ul_symbols: 10,
}, },
}, },
{% endif %} {%- endif %}
prach: { prach: {
{%- if ru.ru_type == "sunwave" %} {%- if ru.ru_type == "sunwave" %}
msg1_frequency_start: 0, msg1_frequency_start: 0,
{%- endif %} {%- endif %}
ra_response_window: {{ 20 if tdd else 10 }}, ra_response_window: {{ 20 if tdd else 10 }},
}, },
pdcch: { pdcch: {
{%- if ru.ru_type == "sunwave" %} {%- if ru.ru_type == "sunwave" %}
n_rb_coreset0: 48, n_rb_coreset0: 48,
...@@ -618,7 +666,6 @@ ...@@ -618,7 +666,6 @@
}, },
{%- endif %} {%- endif %}
}, },
pdsch: { pdsch: {
{%- if ru.ru_type == "sunwave" %} {%- if ru.ru_type == "sunwave" %}
k0: 0, k0: 0,
...@@ -627,7 +674,6 @@ ...@@ -627,7 +674,6 @@
k1: [4, 11], k1: [4, 11],
{%- endif %} {%- endif %}
}, },
pusch: { pusch: {
{%- if ru.ru_type == "sunwave" %} {%- if ru.ru_type == "sunwave" %}
k2: 4, k2: 4,
...@@ -637,157 +683,12 @@ ...@@ -637,157 +683,12 @@
msg3_k2: 7, msg3_k2: 7,
{%- endif %} {%- endif %}
}, },
csi_rs: {
nzp_csi_rs_resource: [
{
{%- if ru.n_antenna_dl == 1 %}
n_ports: 1,
frequency_domain_allocation: "row2",
bitmap: "100000000000",
cdm_type: "no_cdm",
{%- elif ru.n_antenna_dl == 2 %}
n_ports: 2,
frequency_domain_allocation: "other",
bitmap: "100000",
cdm_type: "fd_cdm2",
{%- elif ru.n_antenna_dl == 4 %}
n_ports: 4,
frequency_domain_allocation: "row4",
bitmap: "100",
cdm_type: "fd_cdm2",
{%- elif ru.n_antenna_dl == 8 %}
n_ports: 8,
frequency_domain_allocation: "other",
bitmap: "110011",
cdm_type: "fd_cdm2",
{%- else %}
{%- do ierror(iru, 'n_antenna_dl=%d is not supported' % ru.n_antenna_dl) %}
{%- endif %}
},
{%- if tdd_config != 3 %}
{
csi_rs_id: 1,
n_ports: 1,
frequency_domain_allocation: "row1",
bitmap: "0001",
cdm_type: "no_cdm",
density: 3,
first_symb: 4,
rb_start: 0,
l_crb: -1,
power_control_offset: 0,
power_control_offset_ss: 0,
period: 40,
offset: 11,
qcl_info_periodic_csi_rs: 0,
},
{
csi_rs_id: 2,
n_ports: 1,
frequency_domain_allocation: "row1",
bitmap: "0001",
cdm_type: "no_cdm",
density: 3,
first_symb: 8,
rb_start: 0,
l_crb: -1,
power_control_offset: 0,
power_control_offset_ss: 0,
period: 40,
offset: 11,
qcl_info_periodic_csi_rs: 0,
},
{
csi_rs_id: 3,
n_ports: 1,
frequency_domain_allocation: "row1",
bitmap: "0001",
cdm_type: "no_cdm",
density: 3,
first_symb: 4,
rb_start: 0,
l_crb: -1,
power_control_offset: 0,
power_control_offset_ss: 0,
period: 40,
offset: 12,
qcl_info_periodic_csi_rs: 0,
},
{
csi_rs_id: 4,
n_ports: 1,
frequency_domain_allocation: "row1",
bitmap: "0001",
cdm_type: "no_cdm",
density: 3,
first_symb: 8,
rb_start: 0,
l_crb: -1,
power_control_offset: 0,
power_control_offset_ss: 0,
period: 40,
offset: 12,
qcl_info_periodic_csi_rs: 0,
},
{%- endif %}
],
nzp_csi_rs_resource_set: [
{},
{%- if tdd_config != 3 %}
{
csi_rs_set_id: 1,
nzp_csi_rs_resources: [ 1, 2, 3, 4 ],
repetition: false,
trs_info: true,
},
{%- endif %}
],
csi_resource_config: [
{},
{},
{%- if tdd_config != 3 %}
{
csi_rsc_config_id: 2,
nzp_csi_rs_resource_set_list: [ 1 ],
resource_type: "periodic",
},
{%- endif %}
],
csi_report_config: [
{
{%- if ru.n_antenna_dl > 1 %}
codebook_config: {
codebook_type: "type1",
sub_type: "typeI_SinglePanel",
{%- if ru.n_antenna_dl == 2 %}
{%- elif ru.n_antenna_dl == 4 %}
n1: 2,
n2: 1,
codebook_mode: 1,
{%- elif ru.n_antenna_dl == 8 %}
n1: 4,
n2: 1,
codebook_mode: 1,
{%- endif %}
},
{%- endif %}
},
],
},
drb_config: "{{ B('%s-drb.cfg' % cell_ref) }}", drb_config: "{{ B('%s-drb.cfg' % cell_ref) }}",
}, },
{%- endfor %} {%- endfor %}
], ],
nr_cell_default: { nr_cell_default: {
ssb_period: 20, ssb_period: 20,
plmn_list: [ plmn_list: [
{%- for _, plmn in slapparameter_dict.plmn_list_5g |dictsort %} {%- for _, plmn in slapparameter_dict.plmn_list_5g |dictsort %}
{ {
...@@ -810,7 +711,6 @@ ...@@ -810,7 +711,6 @@
}, },
{%- endfor %} {%- endfor %}
], ],
si_window_length: 40, si_window_length: 40,
cell_barred: false, cell_barred: false,
intra_freq_reselection: true, intra_freq_reselection: true,
...@@ -857,86 +757,13 @@ ...@@ -857,86 +757,13 @@
si_mcs: 6, si_mcs: 6,
}, },
csi_rs: { csi_rs: {
nzp_csi_rs_resource: [ resource_auto: {
{ nzp_csi_rs_period: 80,
csi_rs_id: 0,
density: 1,
first_symb: 4,
rb_start: 0,
l_crb: -1,
power_control_offset: 0,
power_control_offset_ss: 0,
period: 80,
offset: 1,
qcl_info_periodic_csi_rs: 0,
}, },
],
nzp_csi_rs_resource_set: [
{
csi_rs_set_id: 0,
nzp_csi_rs_resources: [ 0 ],
repetition: false,
},
],
csi_im_resource: [
{
csi_im_id: 0,
pattern: 1,
subcarrier_location: 8,
symbol_location: 8,
rb_start: 0,
l_crb: -1,
period: 80,
offset: 1,
},
],
csi_im_resource_set: [
{
csi_im_set_id: 0,
csi_im_resources: [ 0 ],
}
],
zp_csi_rs_resource: [
{
csi_rs_id: 0,
frequency_domain_allocation: "row4",
bitmap: "100",
n_ports: 4,
cdm_type: "fd_cdm2",
first_symb: 8,
density: 1,
rb_start: 0,
l_crb: -1,
period: 80,
offset: 1,
},
],
p_zp_csi_rs_resource_set: [
{
zp_csi_rs_resources: [ 0 ],
},
],
csi_resource_config: [
{
csi_rsc_config_id: 0,
nzp_csi_rs_resource_set_list: [ 0 ],
resource_type: "periodic",
},
{
csi_rsc_config_id: 1,
csi_im_resource_set_list: [ 0 ],
resource_type: "periodic",
},
],
csi_report_config: [ csi_report_config: [
{ {
resources_for_channel_measurement: 0,
csi_im_resources_for_interference: 1,
report_config_type: "periodic", report_config_type: "periodic",
period: 80, period: 80,
report_quantity: "CRI_RI_PMI_CQI",
cqi_table: 2,
subband_size: "value1",
}, },
], ],
}, },
...@@ -990,29 +817,105 @@ ...@@ -990,29 +817,105 @@
}, },
cipher_algo_pref: [], cipher_algo_pref: [],
integ_algo_pref: [2, 1], integ_algo_pref: [2, 1],
{#- TODO fully expose nr meas_config_desc in generic SR #}
{# TODO fully expose nr meas_config_desc in generic SR #} {%- if (len(icell_dict) + len(ipeercell_dict)) > 1 %}
meas_config_desc: { meas_config_desc: {
a1_report_type: "rsrp", a1_report_type: "rsrp",
a1_rsrp: -60, a1_rsrp: {{ slapparameter_dict.handover_a1_rsrp }},
a1_hysteresis: 10, a1_hysteresis: {{ slapparameter_dict.handover_a1_hysteresis }},
a1_time_to_trigger: 100, a1_time_to_trigger: {{ slapparameter_dict.handover_a1_time_to_trigger }},
a2_report_type: "rsrp", a2_report_type: "rsrp",
a2_rsrp: -70, a2_rsrp: {{ slapparameter_dict.handover_a2_rsrp }},
a2_hysteresis: 0, a2_hysteresis: {{ slapparameter_dict.handover_a2_hysteresis }},
a2_time_to_trigger: 100, a2_time_to_trigger: {{ slapparameter_dict.handover_a2_time_to_trigger }},
nr_handover: {
{%- if 'a3_rsrp' in slapparameter_dict.nr_nr_handover.event %}
a3_report_type: "rsrp", a3_report_type: "rsrp",
a3_offset: {{ slapparameter_dict.get('nr_handover_a3_offset', 6) }}, a3_offset: {{ slapparameter_dict.nr_nr_handover.event.a3_rsrp }},
a3_hysteresis: 0, {%- elif 'a4_rsrp' in slapparameter_dict.nr_nr_handover.event %}
a3_time_to_trigger: {{ slapparameter_dict.get('nr_handover_time_to_trigger', 100) }}, a4_threshold_rsrp: {{ slapparameter_dict.nr_nr_handover.event.a4_rsrp }},
{%- elif 'a5_rsrp' in slapparameter_dict.nr_nr_handover.event %}
a5_threshold1_rsrp: {{ slapparameter_dict.nr_nr_handover.event.a5_threshold1_rsrp }},
a5_threshold2_rsrp: {{ slapparameter_dict.nr_nr_handover.event.a5_threshold2_rsrp }},
{%- endif %}
hysteresis: {{ slapparameter_dict.nr_nr_handover.hysteresis }},
time_to_trigger: {{ slapparameter_dict.nr_nr_handover.time_to_trigger }}
},
{%- if len(list(ipeercell_dict|dictsort | selectattr('1._.cell_type', '==', 'lte'))) > 0 %}
eutra_handover: {
{%- if 'b1_rsrp' in slapparameter_dict.nr_eutra_handover.event %}
b1_threshold_rsrp: {{ slapparameter_dict.nr_eutra_handover.event.b1_rsrp }},
{%- elif 'b2_rsrp' in slapparameter_dict.nr_eutra_handover.event %}
b2_threshold1_rsrp: {{ slapparameter_dict.nr_eutra_handover.event.b2_threshold1_rsrp }},
b2_threshold2_rsrp: {{ slapparameter_dict.nr_eutra_handover.event.b2_threshold2_rsrp }},
{%- endif %}
hysteresis: {{ slapparameter_dict.nr_eutra_handover.hysteresis }},
time_to_trigger: {{ slapparameter_dict.nr_eutra_handover.time_to_trigger }}
},
{%- endif %}
ssb_rsrq_filter_coeff: 3, ssb_rsrq_filter_coeff: 3,
ssb_sinr_filter_coeff: 5 ssb_sinr_filter_coeff: 5
}, },
{%- if slapparameter_dict.handover_meas_gap_config == 'Gap Pattern 1' %}
meas_gap_config: {
pattern_id: 1
},
{%- elif slapparameter_dict.handover_meas_gap_config == 'Gap Pattern 0' %}
meas_gap_config: { meas_gap_config: {
pattern_id: 0 pattern_id: 0
}, },
{%- endif %}
ho_from_meas: true,
{%- set nr_bands = list(ipeercell_dict | dictsort | selectattr('1._.cell_type', '==', 'nr') | map(attribute='1._.nr_band')) | unique %}
{%- set lte_bands = list(ipeercell_dict | dictsort | selectattr('1._.cell_type', '==', 'lte') | map(attribute='1._.lte_band')) %}
requested_freq_bands_nr_mrdc: [
{%- for band in nr_bands -%}
{
rat: "nr",
band_nr: {{ band }},
max_bandwidth_requested_dl: 100,
max_bandwidth_requested_ul: 100,
max_carriers_requested_dl: 2,
max_carriers_requested_ul: 2,
},
{%- endfor %}
{%- for band in lte_bands -%}
{
rat: "eutra",
band_eutra: {{ band }},
ca_bandwidth_class_dl: "b",
ca_bandwidth_class_ul: "b",
},
{%- endfor %}
],
requested_freq_bands_nr: [
{%- for band in nr_bands -%}
{
rat: "nr",
band_nr: {{ band }},
max_bandwidth_requested_dl: 100,
max_bandwidth_requested_ul: 100,
max_carriers_requested_dl: 2,
max_carriers_requested_ul: 2,
},
{%- endfor %}
{%- for band in lte_bands -%}
{
rat: "eutra",
band_eutra: {{ band }},
ca_bandwidth_class_dl: "b",
ca_bandwidth_class_ul: "b",
},
{%- endfor %}
],
requested_eutra_freq_bands: [
{%- for band in lte_bands -%}
{{ band }},
{%- endfor -%}
],
{%- endif %}
}, },
{%- endif %} {%- endif %}
} }
...@@ -22,11 +22,11 @@ ...@@ -22,11 +22,11 @@
], ],
mms_server_bind_addr: "{{ internet_ipv4 }}:1111", mms_server_bind_addr: "{{ internet_ipv4 }}:1111",
sctp_addr: "{{ slap_configuration['configuration.ims_addr'] }}", sctp_addr: "{{ slapparameter_dict.ims_addr }}",
cx_server_addr: "127.0.1.100", cx_server_addr: "127.0.1.100",
cx_bind_addr: "{{ slap_configuration['configuration.ims_addr'] }}", cx_bind_addr: "{{ slapparameter_dict.ims_addr }}",
rx_server_addr: "127.0.1.100", rx_server_addr: "127.0.1.100",
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
gtp_addr: "{{ gtp_addr_v6 }}", gtp_addr: "{{ gtp_addr_v6 }}",
{%- endif %} {%- endif %}
{%- else %} {%- else %}
gtp_addr: "{{ slap_configuration['configuration.gtp_addr'] }}", gtp_addr: "{{ slapparameter_dict.gtp_addr }}",
{%- endif %} {%- endif %}
plmn: "{{ slapparameter_dict.get('core_network_plmn', "00101") }}", plmn: "{{ slapparameter_dict.get('core_network_plmn', "00101") }}",
...@@ -68,18 +68,20 @@ ...@@ -68,18 +68,20 @@
fifteen_bearers: false, fifteen_bearers: false,
{%- if support_ims == 'True' %}
ims_list: [ ims_list: [
{ {
ims_addr: "{{ slap_configuration['configuration.ims_addr'] }}", ims_addr: "{{ slapparameter_dict.ims_addr }}",
bind_addr: "{{ slap_configuration['configuration.ims_bind'] }}", bind_addr: "{{ slapparameter_dict.ims_bind }}",
} }
], ],
{%- endif %}
pdn_list: [ pdn_list: [
{ {
access_point_name: ["default", "internet", "sos"], access_point_name: [
{%- for _, pdn in slapparameter_dict.pdn_list |dictsort -%}
"{{ pdn.name }}",
{%- endfor -%}
],
pdn_type: "ipv4v6", pdn_type: "ipv4v6",
tun_ifname: "{{ tun_name }}", tun_ifname: "{{ tun_name }}",
first_ip_addr: "{{ internet_ipv4_start }}", first_ip_addr: "{{ internet_ipv4_start }}",
...@@ -91,17 +93,15 @@ ...@@ -91,17 +93,15 @@
{%- else %} {%- else %}
dns_addr: ["8.8.8.8", "2001:4860:4860::8888"], dns_addr: ["8.8.8.8", "2001:4860:4860::8888"],
{%- endif %} {%- endif %}
erabs: [ erabs: [
{ {
qci: 9, qci: {{ slapparameter_dict.qci }},
priority_level: 15, priority_level: 15,
pre_emption_capability: "shall_not_trigger_pre_emption", pre_emption_capability: "shall_not_trigger_pre_emption",
pre_emption_vulnerability: "not_pre_emptable", pre_emption_vulnerability: "not_pre_emptable",
}, },
], ],
}, },
{%- if support_ims == 'True' %}
{ {
access_point_name: "ims", access_point_name: "ims",
pdn_type: "ipv4v6", pdn_type: "ipv4v6",
...@@ -126,7 +126,6 @@ ...@@ -126,7 +126,6 @@
}, },
], ],
}, },
{%- endif %}
], ],
tun_setup_script: "{{ ifup_empty }}", tun_setup_script: "{{ ifup_empty }}",
......
...@@ -22,7 +22,11 @@ ...@@ -22,7 +22,11 @@
{%- if not ors %} {%- if not ors %}
rue_bind_addr: "{{ pub_info['rue_bind_addr'] }}", rue_bind_addr: "{{ pub_info['rue_bind_addr'] }}",
com_addr: "[[ ", com_addr: "{{ slapparameter_dict.com_addr }}:{{ slapparameter_dict.com_ws_port }}",
com_auth: {
password: "{{ websocket_password }}",
unsecure: false,
},
{%- endif %} {%- endif %}
{# instantiate radio units #} {# instantiate radio units #}
......
...@@ -16,10 +16,10 @@ ...@@ -16,10 +16,10 @@
"type": "boolean" "type": "boolean"
}, },
"iperf3": { "iperf3": {
"default": false, "default": 0,
"title": "iperf3 UDP server", "title": "iperf3 UDP server count",
"description": "Activate iperf3 UDP server", "description": "Activate one or multiple iperf3 UDP server",
"type": "boolean" "type": "number"
}, },
"local_domain": { "local_domain": {
"default": "", "default": "",
...@@ -51,6 +51,40 @@ ...@@ -51,6 +51,40 @@
"description": "Set to true to force a static IPv4 for each UE. If true, the number of UE is limited.", "description": "Set to true to force a static IPv4 for each UE. If true, the number of UE is limited.",
"type": "boolean" "type": "boolean"
}, },
"pdn_list": {
"title": "PDN list",
"description": "Configure the available EPS Packet Data Networks and 5GS Data Network Names.",
"default": {
"internet": {
"name": "internet"
},
"default": {
"name": "default"
},
"sos": {
"name": "sos"
}
},
"patternProperties": {
".*": {
"properties": {
"name": {
"title": "APN name",
"description": "APN name",
"type": "string"
}
},
"type": "object"
}
},
"type": "object"
},
"qci": {
"default": 9,
"title": "QCI of default E-RAB",
"description": "QoS Class Identifier of the default E-RAB",
"type": "number"
},
"eps_5gs_interworking": { "eps_5gs_interworking": {
"title": "EPS 5GS Interworking", "title": "EPS 5GS Interworking",
"type": "string", "type": "string",
......
{%- if lte_version|replace("-", "")|int < 20240502 %} {#- defaults for global core network parameters.
{%- set support_ims = false %} TODO automatically load enb defaults from JSON schema #}
{%- else %} {%- set mme_defaults = {
{%- set support_ims = true %} 'gtp_addr': '127.0.1.100',
{%- endif %} 'ims_addr': '127.0.0.1',
'ims_bind': '127.0.0.2',
'qci': 9,
'pdn_list': {
'internet': {'name': 'internet'},
'default': {'name': 'default'},
'sos': {'name': 'sos'}
}
} %}
{%- for k,v in mme_defaults|dictsort %}
{%- do slapparameter_dict.setdefault(k, v) %}
{%- endfor %}
{%- set dns_slave_instance_list = [] %} {%- set dns_slave_instance_list = [] %}
{%- set sim_slave_instance_list = [] %} {%- set sim_slave_instance_list = [] %}
{%- set fixed_ip = slapparameter_dict.get("fixed_ips", False) %} {%- set fixed_ip = slapparameter_dict.get("fixed_ips", False) %}
...@@ -78,16 +88,14 @@ parts = ...@@ -78,16 +88,14 @@ parts =
mme-service mme-service
ims-config ims-config
mt-call-config mt-call-config
{%- if support_ims %}
ims-service ims-service
{%- endif %}
monitor-base monitor-base
check-interface-up.py check-interface-up.py
publish-connection-information publish-connection-information
{% if slapparameter_dict.get("iperf3", None) %} {%- for i in range(slapparameter_dict.get("iperf3", 0)) %}
iperf-service iperf-service-{{ i }}
iperf-listen-promise iperf-{{ i }}-listen-promise
{% endif %} {%- endfor %}
{% if slapparameter_dict.get("local_domain", '') %} {% if slapparameter_dict.get("local_domain", '') %}
dnsmasq-service dnsmasq-service
{% endif %} {% endif %}
...@@ -101,6 +109,12 @@ eggs-directory = {{ eggs_directory }} ...@@ -101,6 +109,12 @@ eggs-directory = {{ eggs_directory }}
develop-eggs-directory = {{ develop_eggs_directory }} develop-eggs-directory = {{ develop_eggs_directory }}
offline = true offline = true
[myslap]
# NOTE we don't query slapos.cookbook:slapconfiguration the second time because
# slapparameter_dict is potentially modified with defaults.
parameter_dict = {{ dumps(slapparameter_dict) }}
configuration = {{ dumps(slap_configuration) }}
[slap-configuration] [slap-configuration]
recipe = slapos.cookbook:slapconfiguration.serialised recipe = slapos.cookbook:slapconfiguration.serialised
computer = {{ slap_connection['computer-id'] }} computer = {{ slap_connection['computer-id'] }}
...@@ -108,9 +122,6 @@ partition = {{ slap_connection['partition-id'] }} ...@@ -108,9 +122,6 @@ partition = {{ slap_connection['partition-id'] }}
url = {{ slap_connection['server-url'] }} url = {{ slap_connection['server-url'] }}
key = {{ slap_connection['key-file'] }} key = {{ slap_connection['key-file'] }}
cert = {{ slap_connection['cert-file'] }} cert = {{ slap_connection['cert-file'] }}
configuration.gtp_addr = 127.0.1.100
configuration.ims_addr = 127.0.0.1
configuration.ims_bind = 127.0.0.2
ue_db_path = ${ue-db-config:output} ue_db_path = ${ue-db-config:output}
{%- if fixed_ip %} {%- if fixed_ip %}
sim_list = ${sim-ip-configuration:sim-with-ip-list} sim_list = ${sim-ip-configuration:sim-with-ip-list}
...@@ -152,12 +163,10 @@ output = ${directory:bin}/${:_buildout_section_name_} ...@@ -152,12 +163,10 @@ output = ${directory:bin}/${:_buildout_section_name_}
ims-log = ${directory:log}/ims-output.log ims-log = ${directory:log}/ims-output.log
inline = inline =
#!/bin/sh #!/bin/sh
{% if not slapparameter_dict.get("testing", False) %}
(echo && echo && date "+[%Y/%m/%d %T.%N %Z] Starting IMS software..." && echo) >> ${:ims-log}; (echo && echo && date "+[%Y/%m/%d %T.%N %Z] Starting IMS software..." && echo) >> ${:ims-log};
tail -c 1M ${:ims-log} > ${:ims-log}.tmp; tail -c 1M ${:ims-log} > ${:ims-log}.tmp;
mv ${:ims-log}.tmp ${:ims-log}; mv ${:ims-log}.tmp ${:ims-log};
{{ ims }}/lteims ${directory:etc}/ims.cfg >> ${:ims-log} 2>> ${:ims-log}; {{ amarisoft['ims_dir'] }}/lteims ${directory:etc}/ims.cfg >> ${:ims-log} 2>> ${:ims-log};
{% endif %}
### IMS ### IMS
[ims-service] [ims-service]
...@@ -173,7 +182,7 @@ hash-files = ...@@ -173,7 +182,7 @@ hash-files =
${ims-sh-wrapper:output} ${ims-sh-wrapper:output}
environment = environment =
LD_LIBRARY_PATH={{ openssl_location }}/lib:{{ nghttp2_location }}/lib LD_LIBRARY_PATH={{ openssl_location }}/lib:{{ nghttp2_location }}/lib
AMARISOFT_PATH=/opt/amarisoft/.amarisoft AMARISOFT_PATH={{ amarisoft['license_dir'] }}
[mme-sh-wrapper] [mme-sh-wrapper]
recipe = slapos.recipe.template recipe = slapos.recipe.template
...@@ -181,14 +190,12 @@ output = ${directory:bin}/${:_buildout_section_name_} ...@@ -181,14 +190,12 @@ output = ${directory:bin}/${:_buildout_section_name_}
mme-log = ${directory:log}/mme-output.log mme-log = ${directory:log}/mme-output.log
inline = inline =
#!/bin/sh #!/bin/sh
{% if not slapparameter_dict.get("testing", False) %} sudo -n {{ amarisoft['dir'] }}/init-mme;
sudo -n /opt/amarisoft/init-mme;
rm -f ${directory:var}/lte_ue.db; rm -f ${directory:var}/lte_ue.db;
(echo && echo && date "+[%Y/%m/%d %T.%N %Z] Starting MME software..." && echo) >> ${:mme-log}; (echo && echo && date "+[%Y/%m/%d %T.%N %Z] Starting MME software..." && echo) >> ${:mme-log};
tail -c 1M ${:mme-log} > ${:mme-log}.tmp; tail -c 1M ${:mme-log} > ${:mme-log}.tmp;
mv ${:mme-log}.tmp ${:mme-log}; mv ${:mme-log}.tmp ${:mme-log};
{{ mme }}/ltemme ${directory:etc}/mme.cfg >> ${:mme-log} 2>> ${:mme-log}; {{ amarisoft['mme_dir'] }}/ltemme ${directory:etc}/mme.cfg >> ${:mme-log} 2>> ${:mme-log};
{% endif %}
### MME ### MME
[mme-service] [mme-service]
...@@ -205,7 +212,7 @@ hash-files = ...@@ -205,7 +212,7 @@ hash-files =
${mme-sh-wrapper:output} ${mme-sh-wrapper:output}
environment = environment =
LD_LIBRARY_PATH={{ openssl_location }}/lib:{{ nghttp2_location }}/lib LD_LIBRARY_PATH={{ openssl_location }}/lib:{{ nghttp2_location }}/lib
AMARISOFT_PATH=/opt/amarisoft/.amarisoft AMARISOFT_PATH={{ amarisoft['license_dir'] }}
### EMPTY mme-ifup script ### EMPTY mme-ifup script
[mme-ifup-empty] [mme-ifup-empty]
...@@ -214,24 +221,23 @@ wrapper-path = ${directory:bin}/mme-ifup-empty ...@@ -214,24 +221,23 @@ wrapper-path = ${directory:bin}/mme-ifup-empty
command-line = echo Using interface command-line = echo Using interface
mode = 775 mode = 775
{% if slapparameter_dict.get("iperf3", None) %} {%- for i in range(slapparameter_dict.get("iperf3", 0)) %}
### iperf3 [iperf-service-{{ i }}]
[iperf-service]
recipe = slapos.cookbook:wrapper recipe = slapos.cookbook:wrapper
port = 5001 port = {{ 5001 + i }}
ip = ${slap-configuration:tun-ipv4-addr} ip = ${slap-configuration:tun-ipv4-addr}
command-line = {{ iperf3_location }}/bin/iperf3 --server --interval 1 --port ${:port} --bind ${:ip} command-line = {{ iperf3_location }}/bin/iperf3 --server --interval 1 --port ${:port} --bind ${:ip}
wrapper-path = ${directory:service}/iperf3 wrapper-path = ${directory:service}/iperf3-{{ i }}
mode = 0775 mode = 0775
pidfile = ${directory:run}/iperf3.pid pidfile = ${directory:run}/iperf3-{{ i }}.pid
[iperf-listen-promise] [iperf-{{ i }}-listen-promise]
<= monitor-promise-base <= monitor-promise-base
promise = check_socket_listening promise = check_socket_listening
name = iperf3-port-listening.py name = iperf-{{ i }}-port-listening.py
config-host = ${iperf-service:ip} config-host = ${iperf-service-{{ i }}:ip}
config-port = ${iperf-service:port} config-port = ${iperf-service-{{ i }}:port}
{% endif %} {% endfor %}
[config-base] [config-base]
recipe = slapos.recipe.template:jinja2 recipe = slapos.recipe.template:jinja2
...@@ -240,7 +246,7 @@ extra-context = ...@@ -240,7 +246,7 @@ extra-context =
context = context =
section directory directory section directory directory
section slap_configuration slap-configuration section slap_configuration slap-configuration
key slapparameter_dict slap-configuration:configuration key slapparameter_dict myslap:parameter_dict
raw gtp_addr_v6 {{ my_ipv6 }} raw gtp_addr_v6 {{ my_ipv6 }}
raw gtp_addr_v4 {{ lan_ipv4 }} raw gtp_addr_v4 {{ lan_ipv4 }}
import netaddr netaddr import netaddr netaddr
...@@ -269,8 +275,6 @@ context = ...@@ -269,8 +275,6 @@ context =
<= config-base <= config-base
url = {{ mme_template }} url = {{ mme_template }}
output = ${directory:etc}/mme.cfg output = ${directory:etc}/mme.cfg
extra-context =
raw support_ims {{ support_ims }}
{% if slapparameter_dict.get("local_domain", '') %} {% if slapparameter_dict.get("local_domain", '') %}
[dnsmasq-config] [dnsmasq-config]
...@@ -321,15 +325,19 @@ password = {{ slapparameter_dict['monitor-password'] | string }} ...@@ -321,15 +325,19 @@ password = {{ slapparameter_dict['monitor-password'] | string }}
[publish-connection-information] [publish-connection-information]
<= monitor-publish <= monitor-publish
recipe = slapos.cookbook:publish.serialised recipe = slapos.cookbook:publish.serialised
{%- if support_ims %}
ims = Enabled
{%- else %}
ims = Unsupported (Amarisoft version >= 2024-05-02 is required), 5G may not work with your UE
{%- endif %}
core-network-ipv6 = {{ my_ipv6 }} core-network-ipv6 = {{ my_ipv6 }}
core-network-ipv4 = {{ lan_ipv4 }} core-network-ipv4 = {{ lan_ipv4 }}
amarisoft-version = {{ lte_version }} core-network-mac = {{ mac }}
license-expiration = {{ lte_expiration }} {%- if slapparameter_dict.get("iperf3", 0) %}
iperf3-server-ipv4 = ${iperf-service-0:ip}
{%- endif %}
{%- for i in range(1, slapparameter_dict.get("iperf3", 0) + 1) %}
iperf3-server-{{ i - 1 }}-port = ${iperf-service-{{ i - 1 }}:port}
{%- endfor %}
amarisoft-version = {{ amarisoft['version']}}
amarisoft-host-id = {{ amarisoft['lteenb_host_id'] }}
amarisoft-available-versions = {{ amarisoft['version_installed'] }}
license-expiration = {{ amarisoft['ltemme_expiration'] }}
monitor-gadget-url = ${:monitor-base-url}/gadget/software.cfg.html monitor-gadget-url = ${:monitor-base-url}/gadget/software.cfg.html
sim-list = {{ imsi_list | join(', ') }} sim-list = {{ imsi_list | join(', ') }}
......
...@@ -165,6 +165,441 @@ ...@@ -165,6 +165,441 @@
"type": "object", "type": "object",
"default": {} "default": {}
}, },
"handover_a1_rsrp": {
"title": "Handover A1 event RSRP threshold",
"description": "Integer, range from -140 to -43. RSRP threshold value in dBm.",
"type": "number",
"default": -70
},
"handover_a1_hysteresis": {
"title": "Handover A1 event hysteresis",
"description": "Integer, range from 0 to 30. A1 hysteresis in 0.5dB steps used for the measurement report triggering condition.",
"type": "number",
"default": 0
},
"handover_a1_time_to_trigger": {
"title": "Handover A1 event time to trigger",
"description": "Time in ms during which the A1 event condition must be met before triggering the measurement report.",
"type": "number",
"enum": [
0,
40,
64,
80,
100,
128,
160,
256,
320,
480,
512,
640,
1024,
1280,
2560,
5120
],
"default": 640
},
"handover_a2_rsrp": {
"title": "Handover A2 event RSRP threshold",
"description": "Integer, range from -140 to -43. RSRP threshold value in dBm.",
"type": "number",
"default": -80
},
"handover_a2_hysteresis": {
"title": "Handover A2 event hysteresis",
"description": "Integer, range from 0 to 30. A2 hysteresis in 0.5dB steps used for the measurement report triggering condition.",
"type": "number",
"default": 0
},
"handover_a2_time_to_trigger": {
"title": "Handover A2 event time to trigger",
"description": "Time in ms during which the A2 event condition must be met before triggering the measurement report.",
"type": "number",
"enum": [
0,
40,
64,
80,
100,
128,
160,
256,
320,
480,
512,
640,
1024,
1280,
2560,
5120
],
"default": 640
},
"eutra_eutra_handover": {
"title": "EUTRA Handover",
"type": "object",
"default": {
"event": {
"a3_rsrp": 6
},
"hysteresis": 0,
"time_to_trigger": 480
},
"properties": {
"event": {
"title": "EUTRA Handover event",
"type": "object",
"oneOf": [
{
"title": "A3 event",
"type": "object",
"required": [
"a3_rsrp"
],
"properties": {
"a3_rsrp": {
"title": "Handover A3 event RSRP offset",
"description": "Integer, range from -140 to -43. RSRP gain offset between eNBs and gNBs which will trigger handover",
"type": "number"
}
}
},
{
"title": "A4 event",
"type": "object",
"required": [
"a4_rsrp"
],
"properties": {
"a4_rsrp": {
"title": "Handover A4 event RSRP threshold",
"description": "Integer, range from -140 to -43. RSRP threshold value in dBm",
"type": "number"
}
}
},
{
"title": "A5 event",
"type": "object",
"required": [
"a5_threshold1_rsrp",
"a5_threshold2_rsrp"
],
"properties": {
"a5_threshold1_rsrp": {
"title": "Handover A5 event RSRP threshold1",
"description": "Integer, range from -140 to -43. RSRP threshold1 value in dBm",
"type": "number"
},
"a5_threshold2_rsrp": {
"title": "Handover A5 event RSRP threshold2",
"description": "Integer, range from -140 to -43. RSRP threshold2 value in dBm",
"type": "number"
}
}
}
]
},
"hysteresis": {
"title": "EUTRA Handover hysteresis",
"description": "Integer, range from 0 to 30. A3/A4/A5 hysteresis in 0.5dB steps used for the measurement report triggering condition.",
"type": "number"
},
"time_to_trigger": {
"title": "EUTRA Handover time to trigger",
"description": "Time in ms during which the A3/A4/A5 event condition must be met before triggering the measurement report.",
"type": "number",
"enum": [
0,
40,
64,
80,
100,
128,
160,
256,
320,
480,
512,
640,
1024,
1280,
2560,
5120
]
}
}
},
"eutra_nr_handover": {
"title": "NR Handover",
"type": "object",
"default": {
"event": {
"b1_rsrp": -80
},
"hysteresis": 0,
"time_to_trigger": 100
},
"properties": {
"event": {
"title": "NR Handover event",
"type": "object",
"oneOf": [
{
"title": "B1 event",
"type": "object",
"required": [
"b1_rsrp"
],
"properties": {
"b1_rsrp": {
"title": "Handover B1 event RSRP threshold",
"description": "Integer, range from -156 to -30. RSRP threshold value in dBm.",
"type": "number"
}
}
},
{
"title": "B2 event",
"type": "object",
"required": [
"b2_threshold1_rsrp",
"b2_threshold2_rsrp"
],
"properties": {
"b2_threshold1_rsrp": {
"title": "Handover B2 event RSRP threshold1",
"description": "Integer, range from -140 to -43. RSRP threshold1 value in dBm",
"type": "number"
},
"b2_threshold2_rsrp": {
"title": "Handover B2 event RSRP threshold2",
"description": "Integer, range from -140 to -43. RSRP threshold2 value in dBm",
"type": "number"
}
}
}
]
},
"hysteresis": {
"title": "NR Handover hysteresis",
"description": "Integer, range from 0 to 30. NR B1 or B2 hysteresis in 0.5dB steps.",
"type": "number"
},
"time_to_trigger": {
"title": "NR Handover time to trigger",
"description": "Time in ms during which the NR B1 or B2 event condition must be met before triggering the measurement report.",
"type": "number",
"enum": [
0,
40,
64,
80,
100,
128,
160,
256,
320,
480,
512,
640,
1024,
1280,
2560,
5120
]
}
}
},
"nr_nr_handover": {
"title": "NR Handover",
"type": "object",
"default": {
"event": {
"a3_rsrp": 6
},
"hysteresis": 0,
"time_to_trigger": 480
},
"properties": {
"event": {
"title": "NR Handover event",
"type": "object",
"oneOf": [
{
"title": "A3 event",
"type": "object",
"required": [
"a3_rsrp"
],
"properties": {
"a3_rsrp": {
"title": "Handover A3 event RSRP offset",
"description": "Integer, range from -140 to -43. RSRP gain offset between eNBs and gNBs which will trigger handover",
"type": "number"
}
}
},
{
"title": "A4 event",
"type": "object",
"required": [
"a4_rsrp"
],
"properties": {
"a4_rsrp": {
"title": "Handover A4 event RSRP threshold",
"description": "Integer, range from -140 to -43. RSRP threshold value in dBm",
"type": "number"
}
}
},
{
"title": "A5 event",
"type": "object",
"required": [
"a5_threshold1_rsrp",
"a5_threshold2_rsrp"
],
"properties": {
"a5_threshold1_rsrp": {
"title": "Handover A5 event RSRP threshold1",
"description": "Integer, range from -140 to -43. RSRP threshold1 value in dBm",
"type": "number"
},
"a5_threshold2_rsrp": {
"title": "Handover A5 event RSRP threshold2",
"description": "Integer, range from -140 to -43. RSRP threshold2 value in dBm",
"type": "number"
}
}
}
]
},
"hysteresis": {
"title": "NR Handover hysteresis",
"description": "Integer, range from 0 to 30. A3/A4/A5 hysteresis in 0.5dB steps used for the measurement report triggering condition.",
"type": "number"
},
"time_to_trigger": {
"title": "NR Handover time to trigger",
"description": "Time in ms during which the A3/A4/A5 event condition must be met before triggering the measurement report.",
"type": "number",
"enum": [
0,
40,
64,
80,
100,
128,
160,
256,
320,
480,
512,
640,
1024,
1280,
2560,
5120
]
}
}
},
"nr_eutra_handover": {
"title": "EUTRA Handover",
"type": "object",
"default": {
"event": {
"b1_rsrp": -80
},
"hysteresis": 0,
"time_to_trigger": 100
},
"properties": {
"event": {
"title": "EUTRA Handover event",
"type": "object",
"oneOf": [
{
"title": "B1 event",
"type": "object",
"required": [
"b1_rsrp"
],
"properties": {
"b1_rsrp": {
"title": "Handover B1 event RSRP threshold",
"description": "Integer, range from -156 to -30. RSRP threshold value in dBm.",
"type": "number"
}
}
},
{
"title": "B2 event",
"type": "object",
"required": [
"b2_threshold1_rsrp",
"b2_threshold2_rsrp"
],
"properties": {
"b2_threshold1_rsrp": {
"title": "Handover B2 event RSRP threshold1",
"description": "Integer, range from -140 to -43. RSRP threshold1 value in dBm",
"type": "number"
},
"b2_threshold2_rsrp": {
"title": "Handover B2 event RSRP threshold2",
"description": "Integer, range from -140 to -43. RSRP threshold2 value in dBm",
"type": "number"
}
}
}
]
},
"hysteresis": {
"title": "EUTRA Handover hysteresis",
"description": "Integer, range from 0 to 30. EUTRA B1 or B2 hysteresis in 0.5dB steps.",
"type": "number"
},
"time_to_trigger": {
"title": "EUTRA Handover time to trigger",
"description": "Time in ms during which the EUTRA B1 or B2 event condition must be met before triggering the measurement report.",
"type": "number",
"enum": [
0,
40,
64,
80,
100,
128,
160,
256,
320,
480,
512,
640,
1024,
1280,
2560,
5120
]
}
}
},
"handover_meas_gap_config": {
"title": "Handover measurement gap configuration",
"description": "Configuration of the measurement gap. Ignored if no neighbour cells are configured.",
"type": "string",
"enum": [
"None",
"Gap Pattern 0",
"Gap Pattern 1"
],
"default": "Gap Pattern 1"
},
"log_phy_debug": { "log_phy_debug": {
"title": "Physical layer log debug", "title": "Physical layer log debug",
"description": "Enable debug mode for physical layer logs", "description": "Enable debug mode for physical layer logs",
......
# instance-enb implements eNB/gNB service. # instance-enb implements eNB/gNB service.
{#- defaults for global eNB/gNB parameters. {#- defaults for global eNB/gNB parameters.
TODO automatically load enb defaults from JSON schema #} TODO automatically load enb defaults from JSON schema #}
{%- set enb_defaults = { {%- set enb_defaults = {
...@@ -8,9 +7,44 @@ ...@@ -8,9 +7,44 @@
'use_ipv4': False, 'use_ipv4': False,
'gnb_id_bits': 28, 'gnb_id_bits': 28,
'nssai': {'1': {'sst': 1}}, 'nssai': {'1': {'sst': 1}},
'handover_a1_rsrp': -70,
'handover_a1_hysteresis': 0,
'handover_a1_time_to_trigger': 640,
'handover_a2_rsrp': -80,
'handover_a2_hysteresis': 0,
'handover_a2_time_to_trigger': 640,
'handover_meas_gap_config': 'Gap Pattern 1',
'xlog_forwarding_enabled': True, 'xlog_forwarding_enabled': True,
'wendelin_telecom_software_release_url': 'wendelin-telecom-enb-shared-instance', 'wendelin_telecom_software_release_url': 'wendelin-telecom-enb-shared-instance',
'xlog_fluentbit_forward_port': 24224, 'xlog_fluentbit_forward_port': 24224,
'nr_nr_handover': {
'event': {
'a3_rsrp': 6
},
'hysteresis': 0,
'time_to_trigger': 480
},
'nr_eutra_handover': {
'event': {
'b1_rsrp': -80
},
'hysteresis': 0,
'time_to_trigger': 100
},
'eutra_eutra_handover': {
'event': {
'a3_rsrp': 6
},
'hysteresis': 0,
'time_to_trigger': 480
},
'eutra_nr_handover': {
'event': {
'b1_rsrp': -80
},
'hysteresis': 0,
'time_to_trigger': 100
}
} %} } %}
{%- set gtp_addr_lo = '127.0.1.1' %} {%- set gtp_addr_lo = '127.0.1.1' %}
{%- for k,v in enb_defaults|dictsort %} {%- for k,v in enb_defaults|dictsort %}
...@@ -102,17 +136,15 @@ enb-radio-log = ${directory:log}/enb.log ...@@ -102,17 +136,15 @@ enb-radio-log = ${directory:log}/enb.log
enb-start-date = ${directory:run}/enb-start.date enb-start-date = ${directory:run}/enb-start.date
inline = inline =
#!/bin/sh #!/bin/sh
{% if not slapparameter_dict.get("testing", False) %}
# Amarisoft init scripts # Amarisoft init scripts
sudo -n /opt/amarisoft/rm-tmp-lte sudo -n {{ amarisoft['dir'] }}/rm-tmp-lte
sudo -n /opt/amarisoft/init-sdr sudo -n {{ amarisoft['dir'] }}/init-sdr {{ amarisoft['dir'] }}/v{{ amarisoft['version'] }};
sudo -n /opt/amarisoft/init-enb sudo -n {{ amarisoft['dir'] }}/init-enb
# Add useful information to enb-info log # Add useful information to enb-info log
(echo && echo && date "+[%Y/%m/%d %T.%N %Z] Starting eNB software...") >> ${:enb-info-log} (echo && echo && date "+[%Y/%m/%d %T.%N %Z] Starting eNB software...") >> ${:enb-info-log}
(echo -n "PCB: " ; for o in t b v s ; do sudo -n /opt/amarisoft/get-sdr-info -$o 2> /dev/null ; echo -n " " ; done ; echo) >> ${:enb-info-log} (echo -n "PCB: " ; for o in t b v s ; do sudo -n {{ sdr['dir'] }}/get-sdr-info -$o 2> /dev/null ; echo -n " " ; done ; echo) >> ${:enb-info-log}
(AMARISOFT_PATH=/dev/null {{ enb }}/lteenb ${directory:etc}/enb.cfg 2>&1 >/dev/null | sed -n 's/^.*\(Host ID.*\)$/\1/gp') >> ${:enb-info-log}
echo "System info: $(uname -a)" >> ${:enb-info-log} echo "System info: $(uname -a)" >> ${:enb-info-log}
({{ sdr }}/sdr_util version && echo) >> ${:enb-info-log} ({{ amarisoft['sdr_dir'] }}/sdr_util version && echo) >> ${:enb-info-log}
# Remove obsolete logs # Remove obsolete logs
rm -f ${directory:log}/enb-2024* rm -f ${directory:log}/enb-2024*
rm -f ${directory:log}/gnb* rm -f ${directory:log}/gnb*
...@@ -129,8 +161,7 @@ inline = ...@@ -129,8 +161,7 @@ inline =
tail -c 100M ${:enb-info-archive-log} > ${:enb-info-archive-log}.tmp tail -c 100M ${:enb-info-archive-log} > ${:enb-info-archive-log}.tmp
mv ${:enb-info-archive-log}.tmp ${:enb-info-archive-log} mv ${:enb-info-archive-log}.tmp ${:enb-info-archive-log}
# Launch lteenb # Launch lteenb
{{ enb }}/lteenb ${directory:etc}/enb.cfg >> ${:enb-info-log} 2>> ${:enb-info-log} {{ amarisoft['enb_dir'] }}/lteenb ${directory:etc}/enb.cfg >> ${:enb-info-log} 2>> ${:enb-info-log}
{% endif %}
[enb-service] [enb-service]
recipe = slapos.cookbook:wrapper recipe = slapos.cookbook:wrapper
...@@ -144,7 +175,7 @@ hash-files = ...@@ -144,7 +175,7 @@ hash-files =
${enb-sh-wrapper:output} ${enb-sh-wrapper:output}
environment = environment =
LD_LIBRARY_PATH={{ openssl_location }}/lib LD_LIBRARY_PATH={{ openssl_location }}/lib
AMARISOFT_PATH=/opt/amarisoft/.amarisoft AMARISOFT_PATH={{ amarisoft['license_dir'] }}
[xamari-xlog-script] [xamari-xlog-script]
recipe = slapos.recipe.template recipe = slapos.recipe.template
...@@ -170,6 +201,19 @@ wrapper-path = ${directory:service}/${:_buildout_section_name_} ...@@ -170,6 +201,19 @@ wrapper-path = ${directory:service}/${:_buildout_section_name_}
command-line = ${xamari-xlog-script:output} command-line = ${xamari-xlog-script:output}
hash-files = ${:command-line} hash-files = ${:command-line}
[request-parameters]
<= slap-connection
recipe = slapos.cookbook:requestoptional
name = Wendelin Telecom Registration
software-url = {{ slapparameter_dict.wendelin_telecom_software_release_url }}
shared = true
{%- if not slapparameter_dict.xlog_forwarding_enabled or slapparameter_dict.get("xlog_fluentbit_forward_host") %}
state = destroyed
{%- else %}
config-fluentbit-tag = ${xlog-fluentbit-tag:xlog-fluentbit-tag}
return = gateway-host
{%- endif %}
[request-wendelin-telecom-shared] [request-wendelin-telecom-shared]
<= slap-connection <= slap-connection
recipe = slapos.cookbook:requestoptional recipe = slapos.cookbook:requestoptional
...@@ -302,13 +346,16 @@ ipeercell_dict = {{ dumps(ipeercell_dict) }} ...@@ -302,13 +346,16 @@ ipeercell_dict = {{ dumps(ipeercell_dict) }}
[publish-connection-information] [publish-connection-information]
<= monitor-publish <= monitor-publish
recipe = slapos.cookbook:publish.serialised recipe = slapos.cookbook:publish.serialised
websocket-address = ${request-slave-frontend:connection-domain}/${nginx-params:websocket-path} websocket-hostname = ${frontend-urlparse:hostname}
websocket-port = 443 websocket-port = ${frontend-urlparse:port}
websocket-password = ${websocket-password:passwd} websocket-password = ${websocket-password:passwd}
enb-ipv6 = {{ my_ipv6 }} enb-ipv6 = {{ my_ipv6 }}
enb-ipv4 = {{ lan_ipv4 }} enb-ipv4 = {{ lan_ipv4 }}
amarisoft-version = {{ lte_version }} enb-mac = {{ mac }}
license-expiration = {{ lte_expiration }} amarisoft-version = {{ amarisoft['version'] }}
amarisoft-host-id = {{ amarisoft['lteenb_host_id'] }}
amarisoft-available-versions = {{ amarisoft['version_installed'] }}
license-expiration = {{ amarisoft['lteenb_expiration'] }}
monitor-gadget-url = ${:monitor-base-url}/gadget/software.cfg.html monitor-gadget-url = ${:monitor-base-url}/gadget/software.cfg.html
ru-list = {{ dumps(rulib.iru_dict.keys() | sort) }} ru-list = {{ dumps(rulib.iru_dict.keys() | sort) }}
cell-list = {{ dumps(rulib.icell_dict.keys() | sort) }} cell-list = {{ dumps(rulib.icell_dict.keys() | sort) }}
...@@ -334,7 +381,6 @@ name = ${:_buildout_section_name_} ...@@ -334,7 +381,6 @@ name = ${:_buildout_section_name_}
[check-baseband-latency.py] [check-baseband-latency.py]
<= macro.promise <= macro.promise
promise = check_baseband_latency promise = check_baseband_latency
config-testing = {{ slapparameter_dict.get("testing", False) }}
config-amarisoft-stats-log = ${ru_amarisoft-stats-template:log-output} config-amarisoft-stats-log = ${ru_amarisoft-stats-template:log-output}
config-stats-period = {{ slapparameter_dict.get("enb_stats_fetch_period", 60) }} config-stats-period = {{ slapparameter_dict.get("enb_stats_fetch_period", 60) }}
config-min-rxtx-delay = {{ slapparameter_dict.get("min_rxtx_delay", 0) }} config-min-rxtx-delay = {{ slapparameter_dict.get("min_rxtx_delay", 0) }}
......
...@@ -79,7 +79,7 @@ ...@@ -79,7 +79,7 @@
"mme_list": { "mme_list": {
"$ref": "instance-enb-input-schema.json#/properties/mme_list", "$ref": "instance-enb-input-schema.json#/properties/mme_list",
"default": { "default": {
"1": { "Local core-network": {
"mme_addr": "127.0.1.100" "mme_addr": "127.0.1.100"
} }
} }
...@@ -88,20 +88,26 @@ ...@@ -88,20 +88,26 @@
"$ref": "instance-enb-input-schema.json#/properties/plmn_list", "$ref": "instance-enb-input-schema.json#/properties/plmn_list",
"description": "List of PLMNs broadcasted by the eNodeB, at most 6 (default: 00101)", "description": "List of PLMNs broadcasted by the eNodeB, at most 6 (default: 00101)",
"default": { "default": {
"1": { "Test PLMN": {
"plmn": "00101" "plmn": "00101"
} }
} }
}, },
"lte_handover_a3_offset": { "handover_a1_rsrp": {
"title": "A3 offset for LTE handover", "title": "Handover A1 event RSRP threshold",
"description": "RSRP gain offset between gNBs which will trigger handover", "description": "Integer, range from -140 to -43. RSRP threshold value in dBm.",
"type": "number", "type": "number",
"default": 6 "default": -70
}, },
"lte_handover_time_to_trigger": { "handover_a1_hysteresis": {
"title": "Time to Trigger for LTE handover", "title": "Handover A1 event hysteresis",
"description": "Time to triger after which LTE handover will be triggered if A3 offset is reached", "description": "Integer, range from 0 to 30. A1 hysteresis in 0.5dB steps used for the measurement report triggering condition.",
"type": "number",
"default": 0
},
"handover_a1_time_to_trigger": {
"title": "Handover A1 event time to trigger",
"description": "Time in ms during which the A1 event condition must be met before triggering the measurement report.",
"type": "number", "type": "number",
"enum": [ "enum": [
0, 0,
...@@ -121,29 +127,237 @@ ...@@ -121,29 +127,237 @@
2560, 2560,
5120 5120
], ],
"default": 480 "default": 640
},
"handover_a2_rsrp": {
"title": "Handover A2 event RSRP threshold",
"description": "Integer, range from -140 to -43. RSRP threshold value in dBm.",
"type": "number",
"default": -80
},
"handover_a2_hysteresis": {
"title": "Handover A2 event hysteresis",
"description": "Integer, range from 0 to 30. A2 hysteresis in 0.5dB steps used for the measurement report triggering condition.",
"type": "number",
"default": 0
},
"handover_a2_time_to_trigger": {
"title": "Handover A2 event time to trigger",
"description": "Time in ms during which the A2 event condition must be met before triggering the measurement report.",
"type": "number",
"enum": [
0,
40,
64,
80,
100,
128,
160,
256,
320,
480,
512,
640,
1024,
1280,
2560,
5120
],
"default": 640
},
"eutra_eutra_handover": {
"title": "EUTRA Handover",
"type": "object",
"default": {
"event": {
"a3_rsrp": 6
},
"hysteresis": 0,
"time_to_trigger": 480
}, },
"ncell_list": {
"title": "Neighbour Cell Info",
"description": "Neighbour Cell Info",
"patternProperties": {
".*": {
"properties": { "properties": {
"dl_earfcn": { "event": {
"$ref": "peer/cell/lte/input-schema.json#/properties/dl_earfcn" "title": "EUTRA Handover event",
"type": "object",
"oneOf": [
{
"title": "A3 event",
"type": "object",
"required": [
"a3_rsrp"
],
"properties": {
"a3_rsrp": {
"title": "Handover A3 event RSRP offset",
"description": "Integer, range from -140 to -43. RSRP gain offset between eNBs and gNBs which will trigger handover",
"type": "number"
}
}
}, },
"pci": { {
"$ref": "peer/cell/lte/input-schema.json#/properties/pci" "title": "A4 event",
"type": "object",
"required": [
"a4_rsrp"
],
"properties": {
"a4_rsrp": {
"title": "Handover A4 event RSRP threshold",
"description": "Integer, range from -140 to -43. RSRP threshold value in dBm",
"type": "number"
}
}
}, },
"cell_id": { {
"$ref": "peer/cell/lte/input-schema.json#/properties/e_cell_id" "title": "A5 event",
"type": "object",
"required": [
"a5_threshold1_rsrp",
"a5_threshold2_rsrp"
],
"properties": {
"a5_threshold1_rsrp": {
"title": "Handover A5 event RSRP threshold1",
"description": "Integer, range from -140 to -43. RSRP threshold1 value in dBm",
"type": "number"
},
"a5_threshold2_rsrp": {
"title": "Handover A5 event RSRP threshold2",
"description": "Integer, range from -140 to -43. RSRP threshold2 value in dBm",
"type": "number"
}
}
}
]
}, },
"tac": { "hysteresis": {
"$ref": "peer/cell/lte/input-schema.json#/properties/tac", "title": "EUTRA Handover hysteresis",
"default": "0x0001" "description": "Integer, range from 0 to 30. A3/A4/A5 hysteresis in 0.5dB steps used for the measurement report triggering condition.",
"type": "number"
},
"time_to_trigger": {
"title": "EUTRA Handover time to trigger",
"description": "Time in ms during which the A3/A4/A5 event condition must be met before triggering the measurement report.",
"type": "number",
"enum": [
0,
40,
64,
80,
100,
128,
160,
256,
320,
480,
512,
640,
1024,
1280,
2560,
5120
]
}
} }
}, },
"type": "object" "eutra_nr_handover": {
"title": "NR Handover",
"type": "object",
"default": {
"event": {
"b1_rsrp": -80
},
"hysteresis": 0,
"time_to_trigger": 100
},
"properties": {
"event": {
"title": "NR Handover event",
"type": "object",
"oneOf": [
{
"title": "B1 event",
"type": "object",
"required": [
"b1_rsrp"
],
"properties": {
"b1_rsrp": {
"title": "Handover B1 event RSRP threshold",
"description": "Integer, range from -156 to -30. RSRP threshold value in dBm.",
"type": "number"
}
}
},
{
"title": "B2 event",
"type": "object",
"required": [
"b2_threshold1_rsrp",
"b2_threshold2_rsrp"
],
"properties": {
"b2_threshold1_rsrp": {
"title": "Handover B2 event RSRP threshold1",
"description": "Integer, range from -140 to -43. RSRP threshold1 value in dBm",
"type": "number"
},
"b2_threshold2_rsrp": {
"title": "Handover B2 event RSRP threshold2",
"description": "Integer, range from -140 to -43. RSRP threshold2 value in dBm",
"type": "number"
}
}
}
]
},
"hysteresis": {
"title": "NR Handover hysteresis",
"description": "Integer, range from 0 to 30. NR B1 or B2 hysteresis in 0.5dB steps.",
"type": "number"
},
"time_to_trigger": {
"title": "NR Handover time to trigger",
"description": "Time in ms during which the NR B1 or B2 event condition must be met before triggering the measurement report.",
"type": "number",
"enum": [
0,
40,
64,
80,
100,
128,
160,
256,
320,
480,
512,
640,
1024,
1280,
2560,
5120
]
}
}
},
"handover_meas_gap_config": {
"title": "Handover measurement gap configuration",
"description": "Configuration of the measurement gap. Ignored if no neighbour cells are configured.",
"type": "string",
"enum": [
"None",
"Gap Pattern 0",
"Gap Pattern 1"
],
"default": "Gap Pattern 1"
},
"ncell_list": {
"title": "Neighbour Cell Info",
"description": "Neighbour Cell Info",
"patternProperties": {
".*": {
"$ref": "peer/cell/input-schema.json"
} }
}, },
"type": "object", "type": "object",
......
...@@ -12,13 +12,22 @@ ...@@ -12,13 +12,22 @@
"n_antenna_ul": 2, "n_antenna_ul": 2,
"rf_mode": "tdd", "rf_mode": "tdd",
"tdd_ul_dl_config": "[Configuration 2] 5ms 2UL 6DL (default)", "tdd_ul_dl_config": "[Configuration 2] 5ms 2UL 6DL (default)",
"pci": 1, "enb_id": ors_id['enb_id'],
"cell_id": "0x01", "cell_id": ors_id['enb_cell_id'],
"pci": ors_id['enb_pci'],
"root_sequence_index": ors_id['root_sequence_index'],
"tac": "0x0001", "tac": "0x0001",
"root_sequence_index": 204, 'mme_list': {
"enb_id": "0x1A2D0", 'Local Core Network': {
"mme_list": {'1': {'mme_addr': '127.0.1.100'}}, 'mme_addr': '127.0.1.100'
"plmn_list": {"1": {'plmn': '00101'}}, }
},
'plmn_list': {
'Test PLNM': {
'plmn': '00101',
'tac': 100
}
},
"ncell_list": {}, "ncell_list": {},
"x2_peers": {}, "x2_peers": {},
"inactivity_timer": 10000, "inactivity_timer": 10000,
...@@ -31,12 +40,22 @@ ...@@ -31,12 +40,22 @@
"rf_mode": "tdd", "rf_mode": "tdd",
"tdd_ul_dl_config": "5ms 2UL 7DL 4/6 (default)", "tdd_ul_dl_config": "5ms 2UL 7DL 4/6 (default)",
"ssb_pos_bitmap": "10000000", "ssb_pos_bitmap": "10000000",
"pci": 500, "gnb_id": ors_id['gnb_id'],
"cell_id": "0x01", "cell_id": ors_id['gnb_cell_id'],
"gnb_id": "0x12345", "pci": ors_id['gnb_pci'],
"root_sequence_index": ors_id['root_sequence_index'],
"gnb_id_bits": 28, "gnb_id_bits": 28,
"amf_list": {'1': {'amf_addr': '127.0.1.100'}}, 'amf_list': {
"plmn_list": {'1': {'plmn': '00101', 'tac': 100}}, 'Local Core Network': {
'amf_addr': '127.0.1.100'
}
},
'plmn_list': {
'Test PLNM': {
'plmn': '00101',
'tac': 100
}
},
"ncell_list": {}, "ncell_list": {},
"xn_peers": {}, "xn_peers": {},
"inactivity_timer": 10000, "inactivity_timer": 10000,
...@@ -95,7 +114,7 @@ ...@@ -95,7 +114,7 @@
'nr_band': ors_version['current-nr-band'], 'nr_band': ors_version['current-nr-band'],
'bandwidth': slapparameter_dict.nr_bandwidth, 'bandwidth': slapparameter_dict.nr_bandwidth,
'ssb_pos_bitmap': slapparameter_dict.ssb_pos_bitmap, 'ssb_pos_bitmap': slapparameter_dict.ssb_pos_bitmap,
'root_sequence_index': 1, 'root_sequence_index': slapparameter_dict.root_sequence_index,
} }
%} %}
{%- endif %} {%- endif %}
...@@ -123,37 +142,10 @@ ...@@ -123,37 +142,10 @@
{#- inject synthesized peer cells #} {#- inject synthesized peer cells #}
{%- for k, ncell in slapparameter_dict.ncell_list|dictsort %} {%- for k, ncell in slapparameter_dict.ncell_list|dictsort %}
{%- set peercell = {'cell_kind': 'enb_peer'} %}
{%- macro _(name, default) %}
{%- if default is defined %}
{%- do peercell.update({name: default}) %}
{%- endif %}
{%- if name in ncell %}
{%- do peercell.update({name: ncell[name]}) %}
{%- endif %}
{%- endmacro %}
{%- if enb_mode == 'enb' %}
{%- do peercell.update({'cell_type': 'lte'}) %}
{%- if 'cell_id' in ncell %}
{%- do peercell.update({'e_cell_id': ncell.cell_id}) %}
{%- endif %}
{%- do _('pci') %}
{%- do _('dl_earfcn') %}
{%- do _('tac', '0x0001') %}
{%- elif enb_mode == 'gnb' %}
{%- do peercell.update({'cell_type': 'nr'}) %}
{%- do _('nr_cell_id') %}
{%- do _('gnb_id_bits') %}
{%- do _('pci') %}
{%- do _('dl_nr_arfcn') %}
{%- do _('ssb_nr_arfcn') %}
{%- do _('tac', 1) %}
{%- do _('nr_band') %}
{%- endif %}
{%- do ishared_list.append({ {%- do ishared_list.append({
'slave_title': '%s%s' % (iref('PEERCELL'), k), 'slave_title': '%s%s' % (iref('PEERCELL'), k),
'slave_reference': False, 'slave_reference': False,
'_': peercell | tojson '_': ncell | tojson
}) })
%} %}
{%- endfor %} {%- endfor %}
...@@ -228,6 +220,16 @@ frequency-range-rating = {{ ors_version['range'] }} ...@@ -228,6 +220,16 @@ frequency-range-rating = {{ ors_version['range'] }}
current-tx-power-estimate = {{ ors_version['power-estimate'] }} current-tx-power-estimate = {{ ors_version['power-estimate'] }}
current-tx-gain = {{ ors_version['current-tx-gain'] }} current-tx-gain = {{ ors_version['current-tx-gain'] }}
current-rx-gain = {{ ors_version['current-rx-gain'] }} current-rx-gain = {{ ors_version['current-rx-gain'] }}
cell-id = {{ slapparameter_dict['cell_id'] }}
physical-cell-id = {{ slapparameter_dict['pci'] }}
root-sequence-index = {{ slapparameter_dict['root_sequence_index'] }}
{%- if enb_mode == "enb" %}
enb-id = {{ slapparameter_dict['enb_id'] }}
eutra-cell-id = {{ ors_id['eutra_cell_id'] }}
{%- else %}
gnb-id = {{ slapparameter_dict['gnb_id'] }}
nr-cell-id = {{ ors_id['nr_cell_id'] }}
{%- endif %}
{%- if enb_mode == 'enb' %} {%- if enb_mode == 'enb' %}
current-frequency = {{ xearfcn_module.frequency(ors_version['current-earfcn']) }} MHz current-frequency = {{ xearfcn_module.frequency(ors_version['current-earfcn']) }} MHz
......
...@@ -60,7 +60,7 @@ ...@@ -60,7 +60,7 @@
"amf_list": { "amf_list": {
"$ref": "instance-enb-input-schema.json#/properties/amf_list", "$ref": "instance-enb-input-schema.json#/properties/amf_list",
"default": { "default": {
"1": { "Local core-network": {
"amf_addr": "127.0.1.100" "amf_addr": "127.0.1.100"
} }
} }
...@@ -69,7 +69,7 @@ ...@@ -69,7 +69,7 @@
"$ref": "instance-enb-input-schema.json#/properties/plmn_list_5g", "$ref": "instance-enb-input-schema.json#/properties/plmn_list_5g",
"description": "List of PLMNs broadcasted by the gNodeB, at most 12 (default: 00101)", "description": "List of PLMNs broadcasted by the gNodeB, at most 12 (default: 00101)",
"default": { "default": {
"1": { "Test PLMN": {
"plmn": "00101", "plmn": "00101",
"tac": 100 "tac": 100
} }
...@@ -78,15 +78,21 @@ ...@@ -78,15 +78,21 @@
"nssai": { "nssai": {
"$ref": "instance-enb-input-schema.json#/properties/nssai" "$ref": "instance-enb-input-schema.json#/properties/nssai"
}, },
"nr_handover_a3_offset": { "handover_a1_rsrp": {
"title": "A3 offset for NR handover", "title": "Handover A1 event RSRP threshold",
"description": "RSRP gain offset between gNBs which will trigger handover", "description": "Integer, range from -140 to -43. RSRP threshold value in dBm.",
"type": "number", "type": "number",
"default": 6 "default": -70
}, },
"nr_handover_time_to_trigger": { "handover_a1_hysteresis": {
"title": "Time to Trigger for NR handover", "title": "Handover A1 event hysteresis",
"description": "Time to triger after which NR handover will be triggerd if A3 offset is reached", "description": "Integer, range from 0 to 30. A1 hysteresis in 0.5dB steps used for the measurement report triggering condition.",
"type": "number",
"default": 0
},
"handover_a1_time_to_trigger": {
"title": "Handover A1 event time to trigger",
"description": "Time in ms during which the A1 event condition must be met before triggering the measurement report.",
"type": "number", "type": "number",
"enum": [ "enum": [
0, 0,
...@@ -106,38 +112,237 @@ ...@@ -106,38 +112,237 @@
2560, 2560,
5120 5120
], ],
"default": 100 "default": 640
},
"handover_a2_rsrp": {
"title": "Handover A2 event RSRP threshold",
"description": "Integer, range from -140 to -43. RSRP threshold value in dBm.",
"type": "number",
"default": -80
},
"handover_a2_hysteresis": {
"title": "Handover A2 event hysteresis",
"description": "Integer, range from 0 to 30. A2 hysteresis in 0.5dB steps used for the measurement report triggering condition.",
"type": "number",
"default": 0
},
"handover_a2_time_to_trigger": {
"title": "Handover A2 event time to trigger",
"description": "Time in ms during which the A2 event condition must be met before triggering the measurement report.",
"type": "number",
"enum": [
0,
40,
64,
80,
100,
128,
160,
256,
320,
480,
512,
640,
1024,
1280,
2560,
5120
],
"default": 640
},
"nr_nr_handover": {
"title": "NR Handover",
"type": "object",
"default": {
"event": {
"a3_rsrp": 6
},
"hysteresis": 0,
"time_to_trigger": 480
}, },
"ncell_list": {
"title": "Neighbour Cell Info",
"description": "Neighbour Cell Info",
"patternProperties": {
".*": {
"properties": { "properties": {
"dl_nr_arfcn": { "event": {
"$ref": "peer/cell/nr/input-schema.json#/properties/dl_nr_arfcn" "title": "NR Handover event",
"type": "object",
"oneOf": [
{
"title": "A3 event",
"type": "object",
"required": [
"a3_rsrp"
],
"properties": {
"a3_rsrp": {
"title": "Handover A3 event RSRP offset",
"description": "Integer, range from -140 to -43. RSRP gain offset between eNBs and gNBs which will trigger handover",
"type": "number"
}
}
}, },
"ssb_nr_arfcn": { {
"$ref": "peer/cell/nr/input-schema.json#/properties/ssb_nr_arfcn" "title": "A4 event",
"type": "object",
"required": [
"a4_rsrp"
],
"properties": {
"a4_rsrp": {
"title": "Handover A4 event RSRP threshold",
"description": "Integer, range from -140 to -43. RSRP threshold value in dBm",
"type": "number"
}
}
}, },
"pci": { {
"$ref": "peer/cell/nr/input-schema.json#/properties/pci" "title": "A5 event",
"type": "object",
"required": [
"a5_threshold1_rsrp",
"a5_threshold2_rsrp"
],
"properties": {
"a5_threshold1_rsrp": {
"title": "Handover A5 event RSRP threshold1",
"description": "Integer, range from -140 to -43. RSRP threshold1 value in dBm",
"type": "number"
},
"a5_threshold2_rsrp": {
"title": "Handover A5 event RSRP threshold2",
"description": "Integer, range from -140 to -43. RSRP threshold2 value in dBm",
"type": "number"
}
}
}
]
}, },
"nr_cell_id": { "hysteresis": {
"$ref": "peer/cell/nr/input-schema.json#/properties/nr_cell_id" "title": "NR Handover hysteresis",
"description": "Integer, range from 0 to 30. A3/A4/A5 hysteresis in 0.5dB steps used for the measurement report triggering condition.",
"type": "number"
}, },
"gnb_id_bits": { "time_to_trigger": {
"$ref": "peer/cell/nr/input-schema.json#/properties/gnb_id_bits" "title": "NR Handover time to trigger",
"description": "Time in ms during which the A3/A4/A5 event condition must be met before triggering the measurement report.",
"type": "number",
"enum": [
0,
40,
64,
80,
100,
128,
160,
256,
320,
480,
512,
640,
1024,
1280,
2560,
5120
]
}
}
}, },
"nr_band": { "nr_eutra_handover": {
"$ref": "peer/cell/nr/input-schema.json#/properties/nr_band" "title": "EUTRA Handover",
"type": "object",
"default": {
"event": {
"b1_rsrp": -80
}, },
"tac": { "hysteresis": 0,
"$ref": "peer/cell/nr/input-schema.json#/properties/tac", "time_to_trigger": 100
"default": 1 },
"properties": {
"event": {
"title": "EUTRA Handover event",
"type": "object",
"oneOf": [
{
"title": "B1 event",
"type": "object",
"required": [
"b1_rsrp"
],
"properties": {
"b1_rsrp": {
"title": "Handover B1 event RSRP threshold",
"description": "Integer, range from -156 to -30. RSRP threshold value in dBm.",
"type": "number"
}
} }
}, },
"type": "object" {
"title": "B2 event",
"type": "object",
"required": [
"b2_threshold1_rsrp",
"b2_threshold2_rsrp"
],
"properties": {
"b2_threshold1_rsrp": {
"title": "Handover B2 event RSRP threshold1",
"description": "Integer, range from -140 to -43. RSRP threshold1 value in dBm",
"type": "number"
},
"b2_threshold2_rsrp": {
"title": "Handover B2 event RSRP threshold2",
"description": "Integer, range from -140 to -43. RSRP threshold2 value in dBm",
"type": "number"
}
}
}
]
},
"hysteresis": {
"title": "EUTRA Handover hysteresis",
"description": "Integer, range from 0 to 30. EUTRA B1 or B2 hysteresis in 0.5dB steps.",
"type": "number"
},
"time_to_trigger": {
"title": "EUTRA Handover time to trigger",
"description": "Time in ms during which the EUTRA B1 or B2 event condition must be met before triggering the measurement report.",
"type": "number",
"enum": [
0,
40,
64,
80,
100,
128,
160,
256,
320,
480,
512,
640,
1024,
1280,
2560,
5120
]
}
}
},
"handover_meas_gap_config": {
"title": "Handover measurement gap configuration",
"description": "Configuration of the measurement gap. Ignored if no neighbour cells are configured.",
"type": "string",
"enum": [
"None",
"Gap Pattern 0",
"Gap Pattern 1"
],
"default": "Gap Pattern 1"
},
"ncell_list": {
"title": "Neighbour Cell Info",
"description": "Neighbour Cell Info",
"patternProperties": {
".*": {
"$ref": "peer/cell/input-schema.json"
} }
}, },
"type": "object", "type": "object",
......
...@@ -4,7 +4,8 @@ ...@@ -4,7 +4,8 @@
"n_antenna_ul": 1, "n_antenna_ul": 1,
"rf_mode": "tdd", "rf_mode": "tdd",
"plmn": "00101", "plmn": "00101",
"disable_sdr": false "disable_sdr": false,
"power_on": true
} %} } %}
{%- for k,v in ors_defaults|dictsort %} {%- for k,v in ors_defaults|dictsort %}
......
...@@ -48,6 +48,7 @@ import-list += ...@@ -48,6 +48,7 @@ import-list +=
[ors-version] [ors-version]
recipe = slapos.recipe.build recipe = slapos.recipe.build
configuration = $${slap-configuration:configuration} configuration = $${slap-configuration:configuration}
sdr-dir = $${sdr:dir}
init = init =
import subprocess import subprocess
range_map = { range_map = {
...@@ -58,8 +59,8 @@ init = ...@@ -58,8 +59,8 @@ init =
"B41": "2496MHz - 2690MHz", "B41": "2496MHz - 2690MHz",
"B42": "3400MHz - 3600MHz", "B42": "3400MHz - 3600MHz",
"B43": "3600MHz - 3800MHz", "B43": "3600MHz - 3800MHz",
"N77": "3300MHz - 4200MHz", "N77": "3800MHz - 4000MHz",
"N79": "4400MHz - 5000MHz", "N79": "4600MHz - 5000MHz",
"UNKNOWN": "Information not available for this band", "UNKNOWN": "Information not available for this band",
} }
default_tx_gain_map = { default_tx_gain_map = {
...@@ -166,14 +167,14 @@ init = ...@@ -166,14 +167,14 @@ init =
} }
def get_sdr_info(cmd): def get_sdr_info(cmd):
if options['configuration'].get('testing', False): if options['configuration'].get('testing', False):
return {'t': 'TDD', 'b': 'B39', 'v': '4.2', 's': 'B53'}[cmd].encode() return {'t': 'TDD', 'b': 'B39', 'v': '4.2', 's': 'B53'}[cmd]
return subprocess.check_output( return subprocess.check_output(
["sudo", "-n", "/opt/amarisoft/get-sdr-info", "-" + cmd] ["sudo", "-n", options['sdr-dir'] + "/get-sdr-info", "-" + cmd]
) ).decode()
version = get_sdr_info('v').decode() version = get_sdr_info('v')
options['version'] = float(version) if version != 'UNKNOWN' else 0 options['version'] = float(version) if version != 'UNKNOWN' else 0
options['band'] = get_sdr_info('b').decode() options['band'] = get_sdr_info('b')
options['tdd'] = get_sdr_info('t').decode() options['tdd'] = get_sdr_info('t')
options['one-watt'] = bool(options['version'] >= 4) options['one-watt'] = bool(options['version'] >= 4)
options['ors-version'] = "{} {} {}".format( options['ors-version'] = "{} {} {}".format(
options['tdd'], options['tdd'],
......
# instance-ue implements UEsim service. # instance-ue implements UEsim service.
#
{#- defaults for global UE parameters. {#- defaults for global UE parameters.
TODO automatically load ue defaults from JSON schema #} TODO automatically load ue defaults from JSON schema #}
{%- set ue_defaults = { {%- set ue_defaults = {
...@@ -15,6 +14,8 @@ parts = ...@@ -15,6 +14,8 @@ parts =
directory directory
lte-ue-config lte-ue-config
lte-ue-service lte-ue-service
nginx-launcher
nginx-graceful
monitor-base monitor-base
publish-connection-information publish-connection-information
...@@ -76,21 +77,19 @@ ue-radio-log = ${directory:log}/ue.log ...@@ -76,21 +77,19 @@ ue-radio-log = ${directory:log}/ue.log
ue-start-date = ${directory:run}/enb-start.date ue-start-date = ${directory:run}/enb-start.date
inline = inline =
#!/bin/sh #!/bin/sh
{% if not slapparameter_dict.get("testing", False) %} sudo {{ amarisoft['dir'] }}/rm-tmp-lte | true;
sudo /opt/amarisoft/rm-tmp-lte | true; sudo -n {{ amarisoft['dir'] }}/init-sdr {{ amarisoft['dir'] }}/v{{ amarisoft['version'] }};
sudo -n /opt/amarisoft/init-sdr; sudo -n {{ amarisoft['dir'] }}/init-ue;
sudo -n /opt/amarisoft/init-ue;
stat ${:ue-start-date} && mv ${:ue-radio-log} ${directory:log}/ue-$(cat ${:ue-start-date}).log stat ${:ue-start-date} && mv ${:ue-radio-log} ${directory:log}/ue-$(cat ${:ue-start-date}).log
rm -f $(ls -1t ${directory:log}/ue-2* | tail -n+50) rm -f $(ls -1t ${directory:log}/ue-2* | tail -n+50)
date +"%Y-%m-%d-%T" > ${:ue-start-date} date +"%Y-%m-%d-%T" > ${:ue-start-date}
(echo && echo && date "+[%Y/%m/%d %T.%N %Z] Starting UE software..." && echo) >> ${:ue-log}; (echo && echo && date "+[%Y/%m/%d %T.%N %Z] Starting UE software..." && echo) >> ${:ue-log};
tail -c 1M ${:ue-log} > ${:ue-log}.tmp; tail -c 1M ${:ue-log} > ${:ue-log}.tmp;
mv ${:ue-log}.tmp ${:ue-log}; mv ${:ue-log}.tmp ${:ue-log};
{%- if ors %} {%- if slapparameter_dict.get('power_on', False) %}
echo "power_on" | sudo -n {{ ue }}/lteue ${directory:etc}/ue.cfg >> ${:ue-log} 2>> ${:ue-log}; echo "power_on" | sudo -n {{ amarisoft['ue_dir'] }}/lteue ${directory:etc}/ue.cfg >> ${:ue-log} 2>> ${:ue-log};
{%- else %} {%- else %}
{{ ue }}/lteue ${directory:etc}/ue.cfg >> ${:ue-log} 2>> ${:ue-log}; {{ amarisoft['ue_dir'] }}/lteue ${directory:etc}/ue.cfg >> ${:ue-log} 2>> ${:ue-log};
{%- endif %}
{%- endif %} {%- endif %}
### User Equipment (UE) ### User Equipment (UE)
...@@ -106,7 +105,7 @@ hash-files = ...@@ -106,7 +105,7 @@ hash-files =
${lte-ue-sh-wrapper:output} ${lte-ue-sh-wrapper:output}
environment = environment =
LD_LIBRARY_PATH={{ openssl_location }}/lib LD_LIBRARY_PATH={{ openssl_location }}/lib
AMARISOFT_PATH=/opt/amarisoft/.amarisoft AMARISOFT_PATH={{ amarisoft['license_dir'] }}
[config-base] [config-base]
recipe = slapos.recipe.template:jinja2 recipe = slapos.recipe.template:jinja2
...@@ -142,9 +141,15 @@ iue_dict = {{ dumps(iue_dict) }} ...@@ -142,9 +141,15 @@ iue_dict = {{ dumps(iue_dict) }}
<= monitor-publish <= monitor-publish
recipe = slapos.cookbook:publish.serialised recipe = slapos.cookbook:publish.serialised
rue_bind_addr = {{my_ipv6}} rue_bind_addr = {{my_ipv6}}
websocket-address = ${request-slave-frontend:connection-domain}/${nginx-params:websocket-path} ue-ipv4 = {{ lan_ipv4 }}
websocket-port = 443 ue-mac = {{ mac }}
websocket-hostname = ${frontend-urlparse:hostname}
websocket-port = ${frontend-urlparse:port}
websocket-password = ${websocket-password:passwd} websocket-password = ${websocket-password:passwd}
amarisoft-version = {{ amarisoft['version'] }}
amarisoft-host-id = {{ amarisoft['lteue_host_id'] }}
amarisoft-available-versions = {{ amarisoft['version_installed'] }}
license-expiration = {{ amarisoft['lteenb_expiration'] }}
monitor-gadget-url = ${:monitor-base-url}/gadget/software.cfg.html monitor-gadget-url = ${:monitor-base-url}/gadget/software.cfg.html
[monitor-instance-parameter] [monitor-instance-parameter]
......
...@@ -39,7 +39,8 @@ context = ...@@ -39,7 +39,8 @@ context =
raw pythonwitheggs ${buildout:bin-directory}/pythonwitheggs raw pythonwitheggs ${buildout:bin-directory}/pythonwitheggs
section slap_connection slap-connection section slap_connection slap-connection
key slapparameter_dict slap-configuration:configuration key slapparameter_dict slap-configuration:configuration
key lan_ipv4 lan-ip:ipv4 key lan_ipv4 lan:ipv4
key mac lan:mac
key my_ipv4 slap-configuration:ipv4-random key my_ipv4 slap-configuration:ipv4-random
key my_ipv6 slap-configuration:ipv6-random key my_ipv6 slap-configuration:ipv6-random
raw nginx_template ${nginx_conf.in:target} raw nginx_template ${nginx_conf.in:target}
...@@ -80,39 +81,73 @@ init = ...@@ -80,39 +81,73 @@ init =
assert 'xbuildout' not in sys.modules assert 'xbuildout' not in sys.modules
sys.modules['xbuildout'] = xbuildout sys.modules['xbuildout'] = xbuildout
[sdr]
recipe = slapos.recipe.build
configuration = $${slap-configuration:configuration}
init =
# Set SDR directory
options['dir'] = options['configuration'].get('sdr_dir', '/opt/sdr')
[amarisoft] [amarisoft]
recipe = slapos.recipe.build recipe = slapos.recipe.build
fixed_version = 2024-11-21.1732633257
configuration = $${slap-configuration:configuration}
init = init =
import os, re import os, re
mock = options['configuration'].get('lte_mock', False)
# Set Amarisoft directory
options['dir'] = options['configuration'].get('amarisoft_dir', '/opt/amarisoft')
# Get Available Amarisoft versions
if mock:
version_installed = [options['fixed_version']]
else:
version_installed = [x[1:] for x in os.listdir(options['dir']) if re.match(r"v[0-9]{4}-[0-9]{2}-[0-9]{2}.[0-9]{10}", x)]
options['version_installed'] = ', '.join(version_installed)
# Set Amarisoft version to use
slapconf_version = options['configuration'].get('amarisoft_version', False)
if slapconf_version and \
slapconf_version in version_installed:
options['version'] = slapconf_version
else:
options['version'] = options['fixed_version']
# Set Binaries and license directories
binary_dir = options['dir'] + "/v" + options['version']
options['license_dir'] = options['dir'] + '/.amarisoft'
options['sdr_dir'] = binary_dir + '/trx_sdr'
options['enb_dir'] = binary_dir + '/enb'
options['mme_dir'] = binary_dir + '/mme'
options['ims_dir'] = binary_dir + '/mme'
options['ue_dir'] = binary_dir + '/ue'
if options['configuration'].get('lte_mock', False):
options['enb_dir'] = '${buildout:directory}/bin'
options['mme_dir'] = '${buildout:directory}/bin'
options['ims_dir'] = '${buildout:directory}/bin'
options['ue_dir'] = '${buildout:directory}/bin'
# Get License expiration and host IDs
if mock:
options.update({'lteenb_expiration': '9999-99-99', 'ltemme_expiration': '9999-99-99', 'lteue_expiration': '9999-99-99'})
options.update({'lteenb_host_id': '00-00-00-00-00-00-00-00', 'ltemme_host_id': '00-00-00-00-00-00-00-00', 'lteue_host_id': '00-00-00-00-00-00-00-00'})
else:
options.update({'lteenb_expiration': 'Unknown', 'ltemme_expiration': 'Unknown', 'lteue_expiration': 'Unknown'})
options.update({'lteenb_host_id': 'Unknown', 'ltemme_host_id': 'Unknown', 'lteue_host_id': 'Unknown'})
try: try:
lte_version = sorted(filter(lambda x: re.match(r"v[0-9]{4}-[0-9]{2}-[0-9]{2}", x), os.listdir('/opt/amarisoft')))[-1][1:] for filename in os.listdir(options['license_dir']):
except FileNotFoundError:
lte_version = 'LTEVERSION'
path = "/opt/amarisoft/v" + lte_version
options['lte-version'] = lte_version
options['path'] = path
options['sdr'] = path + "/trx_sdr"
options['enb'] = path + "/enb"
options['mme'] = path + "/mme"
options['ims'] = path + "/mme"
options['ue'] = path + "/ue"
import os
lte_expiration = "Unknown"
amarisoft_dir = '/opt/amarisoft/.amarisoft'
try:
for filename in os.listdir(amarisoft_dir):
if filename.endswith('.key'): if filename.endswith('.key'):
with open(os.path.join(amarisoft_dir, filename), 'r') as f: with open(os.path.join(options['license_dir'], filename), 'r') as f:
f.seek(260) f.seek(260)
for l in f: for l in f:
if l.startswith('host_id='):
host_id = l.split('=')[1].strip()
if l.startswith('product_id='):
product_id = l.split('=')[1].strip()
if l.startswith('version='): if l.startswith('version='):
lte_expiration = l.split('=')[1].strip() expiration = l.split('=')[1].strip()
options[product_id + '_expiration'] = expiration
options[product_id + '_host_id'] = host_id
except FileNotFoundError: except FileNotFoundError:
pass pass
options['lte-expiration'] = lte_expiration
[lan-ip] [lan]
recipe = slapos.recipe.build recipe = slapos.recipe.build
init = init =
import netifaces import netifaces
...@@ -124,6 +159,45 @@ init = ...@@ -124,6 +159,45 @@ init =
options['ipv4'] = a[netifaces.AF_INET][0]['addr'] options['ipv4'] = a[netifaces.AF_INET][0]['addr']
except: except:
options['ipv4'] = "0.0.0.0" options['ipv4'] = "0.0.0.0"
try:
options['mac'] = a[netifaces.AF_LINK][0]['addr']
except:
options['mac'] = "00:00:00:00:00:00"
[ors-id]
recipe = slapos.recipe.build
configuration = $${slap-configuration:configuration}
init =
import socket
try:
sn = int(socket.gethostname().split('ors')[1])
except (IndexError, ValueError):
sn = 0
options['serial_number'] = sn
options['enb_id'] = "0x{:05X}".format(sn % 2**20)
options['gnb_id'] = "0x{:05X}".format((sn + 2**19) % 2**20)
options['enb_pci'] = sn % 504
options['gnb_pci'] = sn % 1008
options['enb_cell_id'] = "0x{:02X}".format(sn % 2**8)
options['gnb_cell_id'] = "0x{:02X}".format((sn + 2**7) % 2**8)
options['root_sequence_index'] = sn % 834
def to_int(x):
try:
if '0x' in enb_id:
return int(x, 16)
return int(x)
except ValueError:
return 0
enb_id = options['configuration'].get('enb_id', options['enb_id'])
gnb_id = options['configuration'].get('enb_id', options['enb_id'])
cell_id = options['configuration'].get('cell_id', options['enb_cell_id'])
gnb_id_bits = options['configuration'].get('gnb_id_bits', 28)
options['eutra_cell_id'] = \
"0x{:07X}".format(to_int(enb_id) * 2**8 + to_int(cell_id))
options['nr_cell_id'] = \
"0x{:07X}".format(to_int(gnb_id) * 2**(36 - gnb_id_bits) + to_int(cell_id))
[comp-id] [comp-id]
recipe = slapos.recipe.build recipe = slapos.recipe.build
...@@ -151,10 +225,9 @@ extra-context = ...@@ -151,10 +225,9 @@ extra-context =
raw monitor_template ${monitor2-template:output} raw monitor_template ${monitor2-template:output}
section comp_id comp-id section comp_id comp-id
section slap_configuration slap-configuration section slap_configuration slap-configuration
key lte_version amarisoft:lte-version section amarisoft amarisoft
key lte_expiration amarisoft:lte-expiration section ors_id ors-id
key enb amarisoft:enb section sdr sdr
key sdr amarisoft:sdr
raw enb_template ${enb.jinja2.cfg:target} raw enb_template ${enb.jinja2.cfg:target}
raw slaplte_template ${slaplte.jinja2:target} raw slaplte_template ${slaplte.jinja2:target}
raw drb_lte_template ${drb_lte.jinja2.cfg:target} raw drb_lte_template ${drb_lte.jinja2.cfg:target}
...@@ -178,10 +251,8 @@ filename = instance-core-network.cfg ...@@ -178,10 +251,8 @@ filename = instance-core-network.cfg
extensions = jinja2.ext.do extensions = jinja2.ext.do
extra-context = extra-context =
raw monitor_template ${monitor2-template:output} raw monitor_template ${monitor2-template:output}
key lte_version amarisoft:lte-version section amarisoft amarisoft
key lte_expiration amarisoft:lte-expiration section sdr sdr
key mme amarisoft:mme
key ims amarisoft:ims
raw mme_template ${mme.jinja2.cfg:target} raw mme_template ${mme.jinja2.cfg:target}
raw dnsmasq_template ${dnsmasq-core-network.jinja2.cfg:target} raw dnsmasq_template ${dnsmasq-core-network.jinja2.cfg:target}
raw ims_template ${ims.jinja2.cfg:target} raw ims_template ${ims.jinja2.cfg:target}
...@@ -202,13 +273,12 @@ filename = instance-ue.cfg ...@@ -202,13 +273,12 @@ filename = instance-ue.cfg
extensions = jinja2.ext.do extensions = jinja2.ext.do
extra-context = extra-context =
section slap_configuration slap-configuration section slap_configuration slap-configuration
section amarisoft amarisoft
section sdr sdr
raw monitor_template ${monitor2-template:output} raw monitor_template ${monitor2-template:output}
key ue amarisoft:ue
key sdr amarisoft:sdr
raw ue_template ${ue.jinja2.cfg:target} raw ue_template ${ue.jinja2.cfg:target}
raw slaplte_template ${slaplte.jinja2:target} raw slaplte_template ${slaplte.jinja2:target}
raw openssl_location ${openssl:location} raw openssl_location ${openssl:location}
raw ru_amarisoft_stats_template ${ru_amarisoft-stats.jinja2.py:target} 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_amarisoft_rf_info_template ${ru_amarisoft-rf-info.jinja2.py:target}
raw ru_tapsplit ${ru_tapsplit:target} raw ru_tapsplit ${ru_tapsplit:target}
......
...@@ -6,7 +6,8 @@ ...@@ -6,7 +6,8 @@
"cell_type", "cell_type",
"cell_kind", "cell_kind",
"pci", "pci",
"tac" "tac",
"plmn"
], ],
"properties": { "properties": {
"cell_type": { "cell_type": {
......
...@@ -8,13 +8,17 @@ ...@@ -8,13 +8,17 @@
"pci", "pci",
"tac", "tac",
"e_cell_id", "e_cell_id",
"dl_earfcn" "dl_earfcn",
"plmn"
], ],
"properties": { "properties": {
"cell_type": { "cell_type": {
"$ref": "../../../peer/cell/common.json#/properties/cell_type", "$ref": "../../../peer/cell/common.json#/properties/cell_type",
"const": "lte" "const": "lte"
}, },
"cell_kind": {
"$ref": "../../../peer/cell/common.json#/properties/cell_kind"
},
"e_cell_id": { "e_cell_id": {
"title": "E-UTRAN Cell ID", "title": "E-UTRAN Cell ID",
"description": "28 bit E-UTRAN cell identity. Concatenation of enb_id and cell_id of the neighbour cell.", "description": "28 bit E-UTRAN cell identity. Concatenation of enb_id and cell_id of the neighbour cell.",
...@@ -28,6 +32,11 @@ ...@@ -28,6 +32,11 @@
}, },
"tac": { "tac": {
"$ref": "../../../cell/lte/input-schema.json#/properties/tac" "$ref": "../../../cell/lte/input-schema.json#/properties/tac"
},
"plmn": {
"title": "Public Land Mobile Network",
"description": "Public Land Mobile Network",
"type": "string"
} }
} }
} }
...@@ -10,13 +10,17 @@ ...@@ -10,13 +10,17 @@
"nr_cell_id", "nr_cell_id",
"gnb_id_bits", "gnb_id_bits",
"dl_nr_arfcn", "dl_nr_arfcn",
"nr_band" "nr_band",
"plmn"
], ],
"properties": { "properties": {
"cell_type": { "cell_type": {
"$ref": "../../../peer/cell/common.json#/properties/cell_type", "$ref": "../../../peer/cell/common.json#/properties/cell_type",
"const": "nr" "const": "nr"
}, },
"cell_kind": {
"$ref": "../../../peer/cell/common.json#/properties/cell_kind"
},
"nr_cell_id": { "nr_cell_id": {
"title": "NR Cell ID", "title": "NR Cell ID",
"description": "Concatenation of gnb_id and cell_id of the neighbour cell", "description": "Concatenation of gnb_id and cell_id of the neighbour cell",
...@@ -44,6 +48,11 @@ ...@@ -44,6 +48,11 @@
}, },
"tac": { "tac": {
"$ref": "../../../cell/nr/input-schema.json#/$defs/tac" "$ref": "../../../cell/nr/input-schema.json#/$defs/tac"
},
"plmn": {
"title": "Public Land Mobile Network",
"description": "Public Land Mobile Network",
"type": "string"
} }
} }
} }
#!{{ python_path }} #!{{ python_path }}
import json import json
import hashlib
import hmac
import logging import logging
from logging.handlers import RotatingFileHandler from logging.handlers import RotatingFileHandler
import time import time
...@@ -18,14 +20,22 @@ class enbWebSocket: ...@@ -18,14 +20,22 @@ class enbWebSocket:
handler.setFormatter(formatter) handler.setFormatter(formatter)
self.logger.addHandler(handler) self.logger.addHandler(handler)
if {{ testing }}: self.ws_url = "{{ ws_url }}"
return self.ws_password = "{{ ws_password }}"
self.ws = create_connection(self.ws_url)
self.ws = create_connection("{{ ws_url }}") # Password authentication
data = json.loads(self.ws.recv())
res = hmac.new(
"{}:{}:{}".format(data['type'], self.ws_password, data['name']).encode(),
msg=data['challenge'].encode(),
digestmod=hashlib.sha256
).hexdigest()
msg = {"message": "authenticate", "res": res}
self.ws.send(json.dumps(msg))
self.ws.recv()
def close(self): def close(self):
if {{ testing }}:
return
self.ws.close() self.ws.close()
def send(self, msg): def send(self, msg):
...@@ -37,12 +47,6 @@ class enbWebSocket: ...@@ -37,12 +47,6 @@ class enbWebSocket:
return r return r
def stats(self): def stats(self):
if {{ testing }}:
r = {
'message': 'rf',
'rf_info': "CPRI: x16 HW SW\n"
}
else:
self.send({ self.send({
"message": "rf", "message": "rf",
"rf_info": True "rf_info": True
......
...@@ -20,13 +20,11 @@ class enbWebSocket: ...@@ -20,13 +20,11 @@ class enbWebSocket:
handler.setFormatter(formatter) handler.setFormatter(formatter)
self.logger.addHandler(handler) self.logger.addHandler(handler)
if {{ testing }}:
return
self.ws_url = "{{ ws_url }}" self.ws_url = "{{ ws_url }}"
self.ws_password = "{{ ws_password }}" self.ws_password = "{{ ws_password }}"
self.ws = create_connection(self.ws_url) self.ws = create_connection(self.ws_url)
# Password authentication
data = json.loads(self.ws.recv()) data = json.loads(self.ws.recv())
res = hmac.new( res = hmac.new(
"{}:{}:{}".format(data['type'], self.ws_password, data['name']).encode(), "{}:{}:{}".format(data['type'], self.ws_password, data['name']).encode(),
...@@ -38,8 +36,6 @@ class enbWebSocket: ...@@ -38,8 +36,6 @@ class enbWebSocket:
self.ws.recv() self.ws.recv()
def close(self): def close(self):
if {{ testing }}:
return
self.ws.close() self.ws.close()
def send(self, msg): def send(self, msg):
...@@ -51,15 +47,6 @@ class enbWebSocket: ...@@ -51,15 +47,6 @@ class enbWebSocket:
return r return r
def stats(self): def stats(self):
if {{ testing }}:
from random import randint
nrx = {{ iru_dict.values() | sum(attribute='_.n_antenna_ul') }}
rxv = [{'sat': 0, 'max': randint(-500,-100) / 10.0} for _ in range(nrx)]
r = {
'message': 'stats',
'samples': {'rx': rxv}
}
else:
self.send({ self.send({
"message": "stats", "message": "stats",
"samples": True, "samples": True,
......
...@@ -196,7 +196,7 @@ hash-files = ...@@ -196,7 +196,7 @@ hash-files =
{%- for (i, n) in enumerate(ru.sdr_dev_list) %} {%- for (i, n) in enumerate(ru.sdr_dev_list) %}
{{ promise('%s-sdr-busy%s' % (ru_ref, '-%d' % (i+1) if i > 0 else '')) }} {{ promise('%s-sdr-busy%s' % (ru_ref, '-%d' % (i+1) if i > 0 else '')) }}
promise = check_sdr_busy promise = check_sdr_busy
config-sdr = {{ sdr }} config-sdr = {{ amarisoft['sdr_dir'] }}
config-sdr_dev = {{ n }} config-sdr_dev = {{ n }}
config-dma_chan = 0 config-dma_chan = 0
{%- endfor %} {%- endfor %}
...@@ -204,7 +204,7 @@ config-dma_chan = 0 ...@@ -204,7 +204,7 @@ config-dma_chan = 0
{%- elif ru.ru_link_type == 'cpri' %} {%- elif ru.ru_link_type == 'cpri' %}
{{ promise('%s-sdr-busy' % ru_ref) }} {{ promise('%s-sdr-busy' % ru_ref) }}
promise = check_sdr_busy promise = check_sdr_busy
config-sdr = {{ sdr }} config-sdr = {{ amarisoft['sdr_dir'] }}
config-sdr_dev = {{ ru.cpri_link.sdr_dev }} config-sdr_dev = {{ ru.cpri_link.sdr_dev }}
config-dma_chan = {{ ru.cpri_link.sfp_port }} config-dma_chan = {{ ru.cpri_link.sfp_port }}
...@@ -327,7 +327,7 @@ context = ...@@ -327,7 +327,7 @@ context =
key slapparameter_dict myslap:parameter_dict key slapparameter_dict myslap:parameter_dict
key log_file :log-output key log_file :log-output
raw stats_period {{ slapparameter_dict.get("enb_stats_fetch_period", 60) }} raw stats_period {{ slapparameter_dict.get("enb_stats_fetch_period", 60) }}
raw testing {{ testing }} raw ws_password ${websocket-password:passwd}
raw ws_url ws://{{ slapparameter_dict.com_addr }}:{{ slapparameter_dict.com_ws_port }} raw ws_url ws://{{ slapparameter_dict.com_addr }}:{{ slapparameter_dict.com_ws_port }}
raw python_path {{ buildout_directory}}/bin/pythonwitheggs raw python_path {{ buildout_directory}}/bin/pythonwitheggs
mode = 0775 mode = 0775
...@@ -353,7 +353,6 @@ context = ...@@ -353,7 +353,6 @@ context =
raw ws_password ${websocket-password:passwd} raw ws_password ${websocket-password:passwd}
raw ws_url ws://{{ slapparameter_dict.com_addr }}:{{ slapparameter_dict.com_ws_port }} raw ws_url ws://{{ slapparameter_dict.com_addr }}:{{ slapparameter_dict.com_ws_port }}
raw stats_period {{ slapparameter_dict.get("enb_stats_fetch_period", 60) }} raw stats_period {{ slapparameter_dict.get("enb_stats_fetch_period", 60) }}
raw testing {{ testing }}
raw python_path {{ buildout_directory}}/bin/pythonwitheggs raw python_path {{ buildout_directory}}/bin/pythonwitheggs
key iru_dict :iru_dict key iru_dict :iru_dict
iru_dict = {{ dumps(iru_dict) }} iru_dict = {{ dumps(iru_dict) }}
...@@ -460,14 +459,21 @@ cert-file = ${directory:etc}/websocket.crt ...@@ -460,14 +459,21 @@ cert-file = ${directory:etc}/websocket.crt
executable = {{ nginx_executable }} executable = {{ nginx_executable }}
wrapper = ${directory:bin}/nginx-with-ca wrapper = ${directory:bin}/nginx-with-ca
{%- if not slapparameter_dict.get("testing", False) %} [frontend-urlparse]
recipe = slapos.recipe.build
domain = ${request-slave-frontend:connection-domain}
init =
import six.moves.urllib.parse as urlparse
parsed_url = urlparse.urlparse('wss://' + options['domain'])
options['hostname'] = parsed_url.hostname
options['port'] = parsed_url.port if parsed_url.port else 443
{{ part('websocket-promise') }} {{ part('websocket-promise') }}
<= monitor-promise-base <= monitor-promise-base
promise = check_socket_listening promise = check_socket_listening
name = websocket_promise.py name = websocket_promise.py
config-host = ${request-slave-frontend:connection-domain} config-host = ${frontend-urlparse:hostname}
config-port = 443 config-port = ${frontend-urlparse:port}
{%- endif %}
{{ part('amarisoft-stats-service') }} {{ part('amarisoft-stats-service') }}
recipe = slapos.cookbook:wrapper recipe = slapos.cookbook:wrapper
......
...@@ -383,6 +383,7 @@ ...@@ -383,6 +383,7 @@
{%- set ipeercell = ishared %} {%- set ipeercell = ishared %}
{%- if _.cell_type == 'lte' %} {%- if _.cell_type == 'lte' %}
{%- do _.setdefault('ul_earfcn', J(jdefault_ul_earfcn(_.dl_earfcn))) %} {%- do _.setdefault('ul_earfcn', J(jdefault_ul_earfcn(_.dl_earfcn))) %}
{%- do _.setdefault('lte_band', xearfcn_module.band(_.dl_earfcn)[0]["band"]) %}
{%- elif _.cell_type == 'nr' %} {%- elif _.cell_type == 'nr' %}
{%- do _.setdefault('ul_nr_arfcn', J(jdefault_ul_nr_arfcn(_.dl_nr_arfcn, _.nr_band))) %} {%- do _.setdefault('ul_nr_arfcn', J(jdefault_ul_nr_arfcn(_.dl_nr_arfcn, _.nr_band))) %}
{%- do _.setdefault('subcarrier_spacing', {%- do _.setdefault('subcarrier_spacing',
......
...@@ -49,6 +49,7 @@ parts += ...@@ -49,6 +49,7 @@ parts +=
dnsmasq dnsmasq
eggs eggs
xamari xamari
amarisoft-lte-mock-scripts
setcap-dnsmasq setcap-dnsmasq
# unimplemented parts - the http monitor and better log handling using logrotate # unimplemented parts - the http monitor and better log handling using logrotate
# apache-php # apache-php
...@@ -168,6 +169,31 @@ eggs = ...@@ -168,6 +169,31 @@ eggs =
netaddr netaddr
interpreter = pythonwitheggs interpreter = pythonwitheggs
[amarisoft-lte-mock-repository]
recipe = slapos.recipe.build:gitclone
repository = https://lab.nexedi.com/nexedi/amarisoft-lte-mock.git
revision = 1.1
git-executable = ${git:location}/bin/git
[amarisoft-lte-mock]
recipe = zc.recipe.egg:develop
setup = ${amarisoft-lte-mock-repository:location}
egg = amarisoft-lte-mock
depends =
[amarisoft-lte-mock-scripts]
recipe = zc.recipe.egg
eggs =
${amarisoft-lte-mock:egg}
pcpp
PyYAML
websockets
scripts =
lteenb
ltemme
lteims
lteue
[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
...@@ -201,3 +227,4 @@ websocket-client = 1.4.2 ...@@ -201,3 +227,4 @@ 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 nrarfcn = 2.4.0:whl
pcpp = 1.30
...@@ -104,20 +104,22 @@ def TAC(tac): ...@@ -104,20 +104,22 @@ def TAC(tac):
} }
# LTE_PEER/NR_PEER return basic parameters to indicate an LTE/NR ENB-PEER-kind cell. # LTE_PEER/NR_PEER return basic parameters to indicate an LTE/NR ENB-PEER-kind cell.
def LTE_PEER(e_cell_id, pci, tac): def LTE_PEER(e_cell_id, pci, tac, plmn):
return { return {
'cell_kind': 'enb_peer', 'cell_kind': 'enb_peer',
'e_cell_id': '0x%07x' % e_cell_id, 'e_cell_id': '0x%07x' % e_cell_id,
'pci': pci, 'pci': pci,
'tac': '0x%x' % tac, 'tac': '0x%x' % tac,
'plmn': plmn,
} }
def NR_PEER(nr_cell_id, gnb_id_bits, pci, tac): def NR_PEER(nr_cell_id, gnb_id_bits, pci, tac, plmn):
return { return {
'cell_kind': 'enb_peer', 'cell_kind': 'enb_peer',
'nr_cell_id': '0x%09x' % nr_cell_id, 'nr_cell_id': '0x%09x' % nr_cell_id,
'gnb_id_bits': gnb_id_bits, 'gnb_id_bits': gnb_id_bits,
'pci': pci, 'pci': pci,
'tac': tac, 'tac': tac,
'plmn': plmn,
} }
# X2_PEER/XN_PEER return basic parameters to indicate an LTE/NR ENB peer. # X2_PEER/XN_PEER return basic parameters to indicate an LTE/NR ENB peer.
...@@ -311,6 +313,7 @@ class ENBTestCase4(RFTestCase4): ...@@ -311,6 +313,7 @@ class ENBTestCase4(RFTestCase4):
def getInstanceParameterDict(cls): def getInstanceParameterDict(cls):
return {'_': json.dumps({ return {'_': json.dumps({
'testing': True, 'testing': True,
'lte_mock': True,
'enb_id': '0x17', 'enb_id': '0x17',
'gnb_id': '0x23', 'gnb_id': '0x23',
'gnb_id_bits': 30, 'gnb_id_bits': 30,
...@@ -344,13 +347,13 @@ class ENBTestCase4(RFTestCase4): ...@@ -344,13 +347,13 @@ class ENBTestCase4(RFTestCase4):
_('PEER4', X2_PEER('44.1.1.1')) _('PEER4', X2_PEER('44.1.1.1'))
_('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, "00101"))
_('PEERCELL5', NR(520000,38) | NR_PEER(0x77712,22, 75, 0x321)) _('PEERCELL5', NR(520000,38) | NR_PEER(0x77712,22, 75, 0x321, "00101"))
cls.ho_inter = [ cls.ho_inter = [
dict(rat='eutra', cell_id=0x12345, n_id_cell=35, dl_earfcn= 700, tac=0x123), dict(rat='eutra', cell_id=0x12345, n_id_cell=35, dl_earfcn= 700, tac=0x123, plmn="00101"),
dict(rat='nr', nr_cell_id=0x77712, gnb_id_bits=22, n_id_cell=75, dict(rat='nr', nr_cell_id=0x77712, gnb_id_bits=22, n_id_cell=75,
dl_nr_arfcn=520000, ul_nr_arfcn=520000, ssb_nr_arfcn=520090, band=38, dl_nr_arfcn=520000, ul_nr_arfcn=520000, ssb_nr_arfcn=520090, band=38,
tac = 0x321), tac = 0x321, plmn="00101"),
] ]
def CELLcfg(i): def CELLcfg(i):
...@@ -587,6 +590,7 @@ class UEsimTestCase4(RFTestCase4): ...@@ -587,6 +590,7 @@ class UEsimTestCase4(RFTestCase4):
def getInstanceParameterDict(cls): def getInstanceParameterDict(cls):
return {'_': json.dumps({ return {'_': json.dumps({
'testing': True, 'testing': True,
'lte_mock': True,
})} })}
@classmethod @classmethod
......
...@@ -41,8 +41,10 @@ setUpModule, ORSTestCase = makeModuleSetUpAndTestCaseClass( ...@@ -41,8 +41,10 @@ setUpModule, ORSTestCase = makeModuleSetUpAndTestCaseClass(
param_dict = { param_dict = {
'testing': True, 'testing': True,
'lte_mock': True,
'tx_gain': 17, 'tx_gain': 17,
'rx_gain': 17, 'rx_gain': 17,
'cell_id': '0x01',
'pci': 250, 'pci': 250,
'tac': '0x1717', 'tac': '0x1717',
'root_sequence_index': '1', 'root_sequence_index': '1',
...@@ -53,26 +55,58 @@ param_dict = { ...@@ -53,26 +55,58 @@ param_dict = {
'inactivity_timer': 17, 'inactivity_timer': 17,
'ncell_list': { 'ncell_list': {
'ORS1': { 'ORS1': {
'dl_earfcn': 40000, 'cell_type': 'lte',
'dl_nr_arfcn': 403500, 'cell_kind': 'enb_peer',
'ssb_nr_arfcn': 403500, 'rat': 'eutra',
'dl_earfcn': 38450,
'pci': 1, 'pci': 1,
'nr_cell_id': '0x0000001', 'n_id_cell': 1,
'cell_id': '0x0000001', 'cell_id': '0x0000001',
'gnb_id_bits': 28, 'e_cell_id': '0x0000001',
'nr_band': 34, 'tac': 1,
'tac': 1 'plmn': "00101"
}, },
'ORS2': { 'ORS2': {
'dl_earfcn': 50000, 'cell_type': 'lte',
'dl_nr_arfcn': 519000, 'cell_kind': 'enb_peer',
'ssb_nr_arfcn': 519000, 'rat': 'eutra',
'dl_earfcn': 38050,
'pci': 2,
'n_id_cell': 2,
'cell_id': '0x0000002',
'e_cell_id': '0x0000002',
'tac': 1,
'plmn': "00101"
},
'ORS3': {
'cell_type': 'nr',
'cell_kind': 'enb_peer',
'rat': 'nr',
'dl_nr_arfcn': 520000,
'ssb_nr_arfcn': 520000,
'ul_nr_arfcn': 520000,
'pci': 1,
'n_id_cell': 1,
'nr_cell_id': '0x0000001',
'gnb_id_bits': 28,
'nr_band': 41,
'tac': 1,
'plmn': "00101"
},
'ORS4': {
'cell_type': 'nr',
'cell_kind': 'enb_peer',
'rat': 'nr',
'dl_nr_arfcn': 380000,
'ssb_nr_arfcn': 380000,
'ul_nr_arfcn': 380000,
'pci': 2, 'pci': 2,
'n_id_cell': 2,
'nr_cell_id': '0x0000002', 'nr_cell_id': '0x0000002',
'cell_id': '0x0000001',
'gnb_id_bits': 30, 'gnb_id_bits': 30,
'nr_band': 38, 'nr_band': 39,
'tac': 2 'tac': 2,
'plmn': "00101"
}, },
}, },
} }
...@@ -90,20 +124,6 @@ enb_param_dict = { ...@@ -90,20 +124,6 @@ enb_param_dict = {
'10.0.0.1': {'mme_addr': '10.0.0.1'}, '10.0.0.1': {'mme_addr': '10.0.0.1'},
'2001:db8::1': {'mme_addr': '2001:db8::1'}, '2001:db8::1': {'mme_addr': '2001:db8::1'},
}, },
'ncell_list': {
'ORS1': {
'dl_earfcn': 40000,
'pci': 1,
'cell_id': '0x0000001',
'tac': 1
},
'ORS2': {
'dl_earfcn': 50000,
'pci': 2,
'cell_id': '0x0000001',
'tac': 2
},
},
'xlog_forwarding_enabled': False, 'xlog_forwarding_enabled': False,
} }
gnb_param_dict = { gnb_param_dict = {
...@@ -129,26 +149,6 @@ gnb_param_dict = { ...@@ -129,26 +149,6 @@ gnb_param_dict = {
'xn_addr': '2001:db8::2', 'xn_addr': '2001:db8::2',
}, },
}, },
'ncell_list': {
'ORS1': {
'dl_nr_arfcn': 403500,
'ssb_nr_arfcn': 403500,
'pci': 1,
'nr_cell_id': '0x0000001',
'gnb_id_bits': 28,
'nr_band': 34,
'tac': 1
},
'ORS2': {
'dl_nr_arfcn': 519000,
'ssb_nr_arfcn': 519000,
'pci': 2,
'nr_cell_id': '0x0000002',
'gnb_id_bits': 30,
'nr_band': 38,
'tac': 2
},
},
'xlog_forwarding_enabled': False, 'xlog_forwarding_enabled': False,
} }
gnb_param_dict1 = { gnb_param_dict1 = {
...@@ -205,14 +205,30 @@ class TestENBParameters(ORSTestCase): ...@@ -205,14 +205,30 @@ class TestENBParameters(ORSTestCase):
self.assertEqual(p['mme_addr'], enb_param_dict['mme_list'][p['mme_addr']]['mme_addr']) self.assertEqual(p['mme_addr'], enb_param_dict['mme_list'][p['mme_addr']]['mme_addr'])
for p in conf['cell_list'][0]['ncell_list']: for p in conf['cell_list'][0]['ncell_list']:
for k in enb_param_dict['ncell_list']: for k in param_dict['ncell_list']:
if p['dl_earfcn'] == gnb_param_dict1['ncell_list'][k]['dl_earfcn']: if 'dl_earfcn' in p:
if p['dl_earfcn'] == param_dict['ncell_list'][k].get('dl_earfcn', 0):
break break
conf_ncell = enb_param_dict['ncell_list'][k] elif 'dl_nr_arfcn' in p:
if p['dl_nr_arfcn'] == param_dict['ncell_list'][k].get('dl_nr_arfcn', 0):
break
conf_ncell = param_dict['ncell_list'][k]
if 'dl_earfcn' in p:
self.assertEqual(p['dl_earfcn'], conf_ncell['dl_earfcn']) self.assertEqual(p['dl_earfcn'], conf_ncell['dl_earfcn'])
self.assertEqual(p['n_id_cell'], conf_ncell['pci']) self.assertEqual(p['n_id_cell'], conf_ncell['pci'])
self.assertEqual(p['cell_id'], int(conf_ncell['cell_id'], 16)) self.assertEqual(p['cell_id'], int(conf_ncell['cell_id'], 16))
self.assertEqual(p['tac'], conf_ncell['tac']) self.assertEqual(p['tac'], conf_ncell['tac'])
self.assertEqual(p['plmn'], conf_ncell['plmn'])
elif 'dl_nr_arfcn' in p:
self.assertEqual(p['dl_nr_arfcn'], conf_ncell['dl_nr_arfcn'])
self.assertEqual(p['ssb_nr_arfcn'], conf_ncell['ssb_nr_arfcn'])
self.assertEqual(p['ul_nr_arfcn'], conf_ncell['dl_nr_arfcn']) # assumes nr_band is TDD
self.assertEqual(p['n_id_cell'], conf_ncell['pci'])
self.assertEqual(p['gnb_id_bits'], conf_ncell['gnb_id_bits'])
self.assertEqual(p['nr_cell_id'], int(conf_ncell['nr_cell_id'], 16))
self.assertEqual(p['tac'], conf_ncell['tac'])
self.assertEqual(p['band'], conf_ncell['nr_band'])
self.assertEqual(p['plmn'], conf_ncell['plmn'])
class TestGNBParameters1(ORSTestCase): class TestGNBParameters1(ORSTestCase):
...@@ -243,11 +259,23 @@ class TestGNBParameters1(ORSTestCase): ...@@ -243,11 +259,23 @@ class TestGNBParameters1(ORSTestCase):
self.assertEqual(p['amf_addr'], gnb_param_dict1['amf_list'][p['amf_addr']]['amf_addr']) self.assertEqual(p['amf_addr'], gnb_param_dict1['amf_list'][p['amf_addr']]['amf_addr'])
for p in conf['xn_peers']: for p in conf['xn_peers']:
self.assertEqual(p, gnb_param_dict1['xn_peers'][p]['xn_addr']) self.assertEqual(p, gnb_param_dict1['xn_peers'][p]['xn_addr'])
for p in conf['nr_cell_list'][0]['ncell_list']: for p in conf['nr_cell_list'][0]['ncell_list']:
for k in gnb_param_dict1['ncell_list']: for k in param_dict['ncell_list']:
if p['dl_nr_arfcn'] == gnb_param_dict1['ncell_list'][k]['dl_nr_arfcn']: if 'dl_earfcn' in p:
if p['dl_earfcn'] == param_dict['ncell_list'][k].get('dl_earfcn', 0):
break break
conf_ncell = gnb_param_dict1['ncell_list'][k] elif 'dl_nr_arfcn' in p:
if p['dl_nr_arfcn'] == param_dict['ncell_list'][k].get('dl_nr_arfcn', 0):
break
conf_ncell = param_dict['ncell_list'][k]
if 'dl_earfcn' in p:
self.assertEqual(p['dl_earfcn'], conf_ncell['dl_earfcn'])
self.assertEqual(p['n_id_cell'], conf_ncell['pci'])
self.assertEqual(p['cell_id'], int(conf_ncell['cell_id'], 16))
self.assertEqual(p['tac'], conf_ncell['tac'])
self.assertEqual(p['plmn'], conf_ncell['plmn'])
elif 'dl_nr_arfcn' in p:
self.assertEqual(p['dl_nr_arfcn'], conf_ncell['dl_nr_arfcn']) self.assertEqual(p['dl_nr_arfcn'], conf_ncell['dl_nr_arfcn'])
self.assertEqual(p['ssb_nr_arfcn'], conf_ncell['ssb_nr_arfcn']) self.assertEqual(p['ssb_nr_arfcn'], conf_ncell['ssb_nr_arfcn'])
self.assertEqual(p['ul_nr_arfcn'], conf_ncell['dl_nr_arfcn']) # assumes nr_band is TDD self.assertEqual(p['ul_nr_arfcn'], conf_ncell['dl_nr_arfcn']) # assumes nr_band is TDD
...@@ -256,7 +284,10 @@ class TestGNBParameters1(ORSTestCase): ...@@ -256,7 +284,10 @@ class TestGNBParameters1(ORSTestCase):
self.assertEqual(p['nr_cell_id'], int(conf_ncell['nr_cell_id'], 16)) self.assertEqual(p['nr_cell_id'], int(conf_ncell['nr_cell_id'], 16))
self.assertEqual(p['tac'], conf_ncell['tac']) self.assertEqual(p['tac'], conf_ncell['tac'])
self.assertEqual(p['band'], conf_ncell['nr_band']) self.assertEqual(p['band'], conf_ncell['nr_band'])
self.assertEqual(p['plmn'], conf_ncell['plmn'])
tdd_config = conf['nr_cell_list'][0]['tdd_ul_dl_config']['pattern1'] tdd_config = conf['nr_cell_list'][0]['tdd_ul_dl_config']['pattern1']
self.assertEqual(float(tdd_config['period']), 2.5) self.assertEqual(float(tdd_config['period']), 2.5)
self.assertEqual(int(tdd_config['dl_slots']), 3) self.assertEqual(int(tdd_config['dl_slots']), 3)
self.assertEqual(int(tdd_config['dl_symbols']), 10) self.assertEqual(int(tdd_config['dl_symbols']), 10)
...@@ -346,7 +377,11 @@ class TestGNBMonitorGadgetUrl(ORSTestCase): ...@@ -346,7 +377,11 @@ class TestGNBMonitorGadgetUrl(ORSTestCase):
class TestCoreNetworkMonitorGadgetUrl(ORSTestCase): class TestCoreNetworkMonitorGadgetUrl(ORSTestCase):
@classmethod @classmethod
def getInstanceParameterDict(cls): def getInstanceParameterDict(cls):
return {'_': json.dumps({'testing': True, 'slave-list': []})} return {'_': json.dumps({
'testing': True,
'lte_mock': True,
'slave-list': []
})}
@classmethod @classmethod
def getInstanceSoftwareType(cls): def getInstanceSoftwareType(cls):
...@@ -391,7 +426,11 @@ class TestSimCard(ORSTestCase): ...@@ -391,7 +426,11 @@ class TestSimCard(ORSTestCase):
cls.requestSlaveInstanceWithId(i) cls.requestSlaveInstanceWithId(i)
@classmethod @classmethod
def getInstanceParameterDict(cls): def getInstanceParameterDict(cls):
return {'_': json.dumps({'testing': True, 'fixed_ips': cls.fixed_ips})} return {'_': json.dumps({
'testing': True,
'lte_mock': True,
'fixed_ips': cls.fixed_ips
})}
@classmethod @classmethod
def getInstanceSoftwareType(cls): def getInstanceSoftwareType(cls):
return "core-network" return "core-network"
......
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