Commit b49bc3b3 authored by Joanne Hugé's avatar Joanne Hugé

simpleran: support handover between 4G and 5G

parent 1468e116
...@@ -24,7 +24,7 @@ md5sum = 307e38207945a9adcfea0263cba9d3a6 ...@@ -24,7 +24,7 @@ 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
...@@ -60,11 +60,11 @@ md5sum = 52da9fe3a569199e35ad89ae1a44c30e ...@@ -60,11 +60,11 @@ md5sum = 52da9fe3a569199e35ad89ae1a44c30e
[template-enb] [template-enb]
_update_hash_filename_ = instance-enb.jinja2.cfg _update_hash_filename_ = instance-enb.jinja2.cfg
md5sum = 5ff63ef0f043a198436a6b05e350a220 md5sum = 248c284cb8612034695e3bcec279e3a2
[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 = f4221fa9088546a40449845dcfb15447
[template-ors-ue] [template-ors-ue]
_update_hash_filename_ = instance-ors-ue.jinja2.cfg _update_hash_filename_ = instance-ors-ue.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 = ac7000a3b6999b51635083619e640e30
[drb_lte.jinja2.cfg] [drb_lte.jinja2.cfg]
filename = config/drb_lte.jinja2.cfg filename = config/drb_lte.jinja2.cfg
......
...@@ -69,6 +69,7 @@ ...@@ -69,6 +69,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 +84,7 @@ ...@@ -83,6 +84,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,
...@@ -465,22 +467,103 @@ ...@@ -465,22 +467,103 @@
], ],
{# 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)) > 0 %}
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 }},
a3_report_type: "rsrp", eutra_handover: {
a3_offset: {{ slapparameter_dict.get('lte_handover_a3_offset', 6) }}, {%- if 'a3_rsrp' in slapparameter_dict.eutra_handover.event %}
a3_hysteresis: 0, a3_report_type: "rsrp",
a3_time_to_trigger: {{ slapparameter_dict.get('lte_handover_a3_time_to_trigger', 480) }}, a3_offset: {{ slapparameter_dict.eutra_handover.event.a3_rsrp }},
{%- elif 'a4_rsrp' in slapparameter_dict.eutra_handover.event %}
a4_threshold_rsrp: {{ slapparameter_dict.eutra_handover.event.a4_rsrp }},
{%- elif 'a5_rsrp' in slapparameter_dict.eutra_handover.event %}
a5_threshold1_rsrp: {{ slapparameter_dict.eutra_handover.event.a5_threshold1_rsrp }},
a5_threshold2_rsrp: {{ slapparameter_dict.eutra_handover.event.a5_threshold2_rsrp }},
{%- endif %}
hysteresis: {{ slapparameter_dict.eutra_handover.hysteresis }},
time_to_trigger: {{ slapparameter_dict.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.nr_handover.event %}
b1_threshold_rsrp: {{ slapparameter_dict.nr_handover.event.b1_rsrp }},
{%- elif 'b2_rsrp' in slapparameter_dict.nr_handover.event %}
b2_threshold1_rsrp: {{ slapparameter_dict.nr_handover.event.b2_threshold1_rsrp }},
b2_threshold2_rsrp: {{ slapparameter_dict.nr_handover.event.b2_threshold2_rsrp }},
{%- endif %}
hysteresis: {{ slapparameter_dict.nr_handover.hysteresis }},
time_to_trigger: {{ slapparameter_dict.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,
},
{%- 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 %}
...@@ -992,6 +1075,130 @@ ...@@ -992,6 +1075,130 @@
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: {
a1_report_type: "rsrp",
a1_rsrp: {{ slapparameter_dict.handover_a1_rsrp }},
a1_hysteresis: {{ slapparameter_dict.handover_a1_hysteresis }},
a1_time_to_trigger: {{ slapparameter_dict.handover_a1_time_to_trigger }},
a2_report_type: "rsrp",
a2_rsrp: {{ slapparameter_dict.handover_a2_rsrp }},
a2_hysteresis: {{ slapparameter_dict.handover_a2_hysteresis }},
a2_time_to_trigger: {{ slapparameter_dict.handover_a2_time_to_trigger }},
nr_handover: {
{%- if 'a3_rsrp' in slapparameter_dict.nr_handover.event %}
a3_report_type: "rsrp",
a3_offset: {{ slapparameter_dict.nr_handover.event.a3_rsrp }},
{%- elif 'a4_rsrp' in slapparameter_dict.nr_handover.event %}
a4_threshold_rsrp: {{ slapparameter_dict.nr_handover.event.a4_rsrp }},
{%- elif 'a5_rsrp' in slapparameter_dict.nr_handover.event %}
a5_threshold1_rsrp: {{ slapparameter_dict.nr_handover.event.a5_threshold1_rsrp }},
a5_threshold2_rsrp: {{ slapparameter_dict.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.eutra_handover.event %}
b1_threshold_rsrp: {{ slapparameter_dict.eutra_handover.event.b1_rsrp }},
{%- elif 'b2_rsrp' in slapparameter_dict.eutra_handover.event %}
b2_threshold1_rsrp: {{ slapparameter_dict.eutra_handover.event.b2_threshold1_rsrp }},
b2_threshold2_rsrp: {{ slapparameter_dict.eutra_handover.event.b2_threshold2_rsrp }},
{%- endif %}
hysteresis: {{ slapparameter_dict.eutra_handover.hysteresis }},
time_to_trigger: {{ slapparameter_dict.eutra_handover.time_to_trigger }}
},
{%- endif %}
ssb_rsrq_filter_coeff: 3,
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: {
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 %}
meas_config_desc: { meas_config_desc: {
a1_report_type: "rsrp", a1_report_type: "rsrp",
a1_rsrp: -60, a1_rsrp: -60,
......
...@@ -7,6 +7,13 @@ ...@@ -7,6 +7,13 @@
'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,
......
...@@ -93,15 +93,21 @@ ...@@ -93,15 +93,21 @@
} }
} }
}, },
"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_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
]
}
}
},
"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": { "ncell_list": {
"title": "Neighbour Cell Info", "title": "Neighbour Cell Info",
"description": "Neighbour Cell Info", "description": "Neighbour Cell Info",
"patternProperties": { "patternProperties": {
".*": { ".*": {
"properties": { "$ref": "peer/cell/input-schema.json"
"dl_earfcn": {
"$ref": "peer/cell/lte/input-schema.json#/properties/dl_earfcn"
},
"pci": {
"$ref": "peer/cell/lte/input-schema.json#/properties/pci"
},
"cell_id": {
"$ref": "peer/cell/lte/input-schema.json#/properties/e_cell_id"
},
"tac": {
"$ref": "peer/cell/lte/input-schema.json#/properties/tac",
"default": "0x0001"
}
},
"type": "object"
} }
}, },
"type": "object", "type": "object",
......
...@@ -123,37 +123,10 @@ ...@@ -123,37 +123,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 %}
......
...@@ -78,15 +78,57 @@ ...@@ -78,15 +78,57 @@
"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",
"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", "type": "number",
"enum": [ "enum": [
0, 0,
...@@ -106,38 +148,201 @@ ...@@ -106,38 +148,201 @@
2560, 2560,
5120 5120
], ],
"default": 100 "default": 640
},
"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
]
}
}
},
"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"
}, },
"ncell_list": { "ncell_list": {
"title": "Neighbour Cell Info", "title": "Neighbour Cell Info",
"description": "Neighbour Cell Info", "description": "Neighbour Cell Info",
"patternProperties": { "patternProperties": {
".*": { ".*": {
"properties": { "$ref": "peer/cell/input-schema.json"
"dl_nr_arfcn": {
"$ref": "peer/cell/nr/input-schema.json#/properties/dl_nr_arfcn"
},
"ssb_nr_arfcn": {
"$ref": "peer/cell/nr/input-schema.json#/properties/ssb_nr_arfcn"
},
"pci": {
"$ref": "peer/cell/nr/input-schema.json#/properties/pci"
},
"nr_cell_id": {
"$ref": "peer/cell/nr/input-schema.json#/properties/nr_cell_id"
},
"gnb_id_bits": {
"$ref": "peer/cell/nr/input-schema.json#/properties/gnb_id_bits"
},
"nr_band": {
"$ref": "peer/cell/nr/input-schema.json#/properties/nr_band"
},
"tac": {
"$ref": "peer/cell/nr/input-schema.json#/properties/tac",
"default": 1
}
},
"type": "object"
} }
}, },
"type": "object", "type": "object",
......
...@@ -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"
} }
} }
} }
...@@ -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',
......
...@@ -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.
...@@ -345,13 +347,13 @@ class ENBTestCase4(RFTestCase4): ...@@ -345,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):
......
...@@ -44,6 +44,7 @@ param_dict = { ...@@ -44,6 +44,7 @@ param_dict = {
'lte_mock': 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',
...@@ -54,26 +55,58 @@ param_dict = { ...@@ -54,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, '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,
'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"
}, },
}, },
} }
...@@ -91,20 +124,6 @@ enb_param_dict = { ...@@ -91,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 = {
...@@ -130,26 +149,6 @@ gnb_param_dict = { ...@@ -130,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 = {
...@@ -206,14 +205,30 @@ class TestENBParameters(ORSTestCase): ...@@ -206,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:
break if p['dl_earfcn'] == param_dict['ncell_list'][k].get('dl_earfcn', 0):
conf_ncell = enb_param_dict['ncell_list'][k] break
self.assertEqual(p['dl_earfcn'], conf_ncell['dl_earfcn']) elif 'dl_nr_arfcn' in p:
self.assertEqual(p['n_id_cell'], conf_ncell['pci']) if p['dl_nr_arfcn'] == param_dict['ncell_list'][k].get('dl_nr_arfcn', 0):
self.assertEqual(p['cell_id'], int(conf_ncell['cell_id'], 16)) break
self.assertEqual(p['tac'], conf_ncell['tac']) 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['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):
...@@ -244,20 +259,35 @@ class TestGNBParameters1(ORSTestCase): ...@@ -244,20 +259,35 @@ 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:
break if p['dl_earfcn'] == param_dict['ncell_list'][k].get('dl_earfcn', 0):
conf_ncell = gnb_param_dict1['ncell_list'][k] break
self.assertEqual(p['dl_nr_arfcn'], conf_ncell['dl_nr_arfcn']) elif 'dl_nr_arfcn' in p:
self.assertEqual(p['ssb_nr_arfcn'], conf_ncell['ssb_nr_arfcn']) if p['dl_nr_arfcn'] == param_dict['ncell_list'][k].get('dl_nr_arfcn', 0):
self.assertEqual(p['ul_nr_arfcn'], conf_ncell['dl_nr_arfcn']) # assumes nr_band is TDD break
self.assertEqual(p['n_id_cell'], conf_ncell['pci']) conf_ncell = param_dict['ncell_list'][k]
self.assertEqual(p['gnb_id_bits'], conf_ncell['gnb_id_bits']) if 'dl_earfcn' in p:
self.assertEqual(p['nr_cell_id'], int(conf_ncell['nr_cell_id'], 16)) self.assertEqual(p['dl_earfcn'], conf_ncell['dl_earfcn'])
self.assertEqual(p['tac'], conf_ncell['tac']) self.assertEqual(p['n_id_cell'], conf_ncell['pci'])
self.assertEqual(p['band'], conf_ncell['nr_band']) 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['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'])
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)
......
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