1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
{#- Package amari/slap provides helpers for configuring Amarisoft LTE services in SlapOS. XXX ...
XXX overview
XXX see also amari/lte for ...
-#}
{#- defaults provide default values for lte parameters.
it should be kept in sync with "default" in json schemas #}
{#- XXX ssb_pos_bitmap=10000000 is for TDD only; FDD -> "1000" #}
{#- XXX opc='milenage' is not meaningful ? #}
{%- set defaults = {
'enb_id': '0x1A2D0',
'gnb_id': '0x12345',
'gnb_id_bits': 28,
'cell/lte': {
'pci': 1,
'tac': "0x0001",
'tdd_ul_dl_config': '[Configuration 2] 5ms 2UL 6DL (default)',
},
'cell/nr': {
'pci': 500,
'ssb_pos_bitmap': '10000000',
'tdd_ul_dl_config': '5ms 2UL 7DL 4/6 (default)',
},
'cpri_link': {
'mapping': 'hw',
'mult': 16,
'rx_delay': 0,
'tx_delay': 0,
'tx_dbm': 0,
},
'ue': {
'sim_algo': 'milenage',
'opc': 'milenage',
'amf': '0x9001',
'sqn': '000000000000',
'impu': '',
'impi': '',
'imsi': '001010123456789',
'k': '00112233445566778899aabbccddeeff',
}
}
%}
{#- cfg returns value of configuration parameter name #}
{%- macro cfg(name) %}
{{- slapparameter_dict.get(name, defaults.get(name)) }}
{%- endmacro %}
{#- J is used around macro calls to retrieve returned objects.
It is needed to workaround jinja2 limitation that macro can return only
strings - not arbitrary objects: we return objects as JSON-encoded string
and J decodes them.
By convention macros that return JSON-encoded objects start with "j" prefix.
Usage example:
set obj = J(jmymacro(...))
#}
{%- set J = json_module.loads %}
{#- bug indicates an error in template logic.
it should not happen. #}
{%- macro bug(msg) %}
{%- do assert(False, msg) %}
{%- endmacro %}
{#- error reports an error about shared instance #}
{#- XXX -> ierror ? #}
{#- XXX error(ishared, msg) vvv is debug stub -#}
{%- macro error(ishared, msg) %}
{%- set msg = 'E: %s: %s\n' % (J(jref_of_shared(ishared)), msg) %}
{%- do print('\n%s' % msg) %}
{%- do assert(False, msg) %}
{%- endmacro %}
{#- ---- loading ---- #}
{#- qshared_instance_list queues not yet loaded shared instances.
load_* routines process this queue and move loaded instances to i<type>_dict registries. #}
{%- set qshared_instance_list = slap_configuration.get('slave-instance-list', []) %}
{#- check_loaded_everything verifies that all shared instances were handling during the load. #}
{%- macro check_loaded_everything() %}
{%- for ishared in qshared_instance_list %}
{%- do error(ishared, "shared instance of unsupported type") %}
{%- endfor %}
{%- endmacro %}
{#- json-decode _ in all shared instances #}
{%- for ishared in qshared_instance_list %}
{%- do ishared.update({'_': J(ishared['_'])}) %}
{%- endfor %}
{#- load_iru_and_icell initializes RU and cell registries.
icell_dict keeps cell shared instances: reference -> icell
iru_dict keeps RU shared instances + RU whose definition is embedded into a cell: reference -> iRU
in the kept instances _ is automatically json-decoded
icell_kind=enb - load cells definition to serve them from enb
icell_kind=ue - load cells definition to connect to them
XXX defaults ?
#}
{%- macro load_iru_and_icell(iru_dict, icell_dict, icell_kind) %}
{%- set qother = [] %}
{%- for ishared in qshared_instance_list %}
{%- set ref = J(jref_of_shared(ishared)) %}
{%- set _ = ishared['_'] %}
{%- if 'ru_type' in _ %}
{%- set iru = ishared %}
{%- if _.ru_link_type == 'cpri' %}
{%- set link = _.cpri_link %}
{%- for k, v in defaults['cpri_link'].items() %}
{%- do link.setdefault(k, v) %}
{%- endfor %}
{%- endif %}
{%- do iru_dict.update({ref: iru}) %}
{%- elif (icell_kind == 'enb' and 'cell_type' in _) or
(icell_kind == 'ue' and 'ue_cell_type' in _) %}
{%- set icell = ishared %}
{%- if icell_kind == 'enb' %}
{%- for k, v in defaults['cell/' + _.cell_type].items() %}
{%- do _.setdefault(k, v) %}
{%- endfor %}
{%- endif %}
{%- do icell_dict.update({ref: icell}) %}
{%- set ru = _['ru'] %}
{%- if ru.ru_type not in ('ru_ref', 'ruincell_ref') %}
{#- embedded ru definition -> expose it as `_<cell_ref>_ru` #}
{%- do iru_dict.update({'_%s_ru' % ref: {
'_': ru,
'slave_title': '%s. RU' % icell.slave_title,
'slave_reference': icell.slave_reference,
}}) %}
{%- endif %}
{%- else %}
{%- do qother.append(ishared) %}
{%- endif %}
{%- endfor %}
{%- do qshared_instance_list.clear() %}
{%- do qshared_instance_list.extend(qother) %}
{#- do print('\n>>> iru_dict:'), pprint(iru_dict) #}
{#- do print('\n>>> icell_dict:'), pprint(icell_dict) #}
{#- XXX verify cell_type = lte|nr XXX no - this should be verified by json-schema #}
{#- verify that there is no dangling cell->ru references #}
{#- XXX also verify that there is no dangling cell -> cell refs in ruincell_ref #}
{%- for _, icell in icell_dict|dictsort %}
{%- set ru_ref = J(jcell_ru_ref(icell, icell_dict)) %}
{%- if ru_ref not in iru_dict %}
{%- do error(icell, "referred RU %s does not exist" % ru_ref) %}
{%- endif %}
{%- endfor %}
{#- assign RUs rf_port and tx/rx channel indices #}
{%- set rf_chan = namespace(tx=0, rx=0) %}
{%- for rf_port, (ru_ref, iru) in enumerate(iru_dict|dictsort) %}
{%- set ru = iru['_'] %}
{%- do ru.update({'_rf_port': rf_port,
'_rf_chan_tx': rf_chan.tx,
'_rf_chan_rx': rf_chan.rx}) %}
{%- set rf_chan.tx = rf_chan.tx + ru.n_antenna_dl %}
{%- set rf_chan.rx = rf_chan.rx + ru.n_antenna_ul %}
{%- endfor %}
{%- endmacro %}
{#- jcell_ru_ref returns RU reference linked from a cell.
if the cell embeds RU definition, its reference comes as `_<cell_ref>_ru`. #}
{%- macro jcell_ru_ref(icell, icell_dict) %}
{{- _jcell_ru_ref(icell, icell_dict, []) }}
{%- endmacro %}
{%- macro _jcell_ru_ref(icell, icell_dict, seen) %}
{%- set cell_ref = J(jref_of_shared(icell)) %}
{%- if cell_ref in seen %}
{%- for x in seen %}
{%- do error(x, "%s form a cycle via RU references" % seen) %}
{%- endfor %}
{#- XXX what to return ? #}
{%- else %}
{%- do seen.append(cell_ref) %}
{%- set ru = icell['_']['ru'] %}
{%- if ru.ru_type == 'ru_ref' %}
{{- ru.ru_ref | tojson }}
{%- elif ru.ru_type == 'ruincell_ref' %}
{#- XXX first check referred cell exist ? #}
{{- _jcell_ru_ref(icell_dict[ru.ruincell_ref], icell_dict, seen) }}
{%- else %}
{#- ru definition is embedded into cell #}
{{- ('_%s_ru' % J(jref_of_shared(icell))) | tojson }}
{%- endif %}
{%- endif %}
{%- endmacro %}
{#- jref_of_shared returns original reference used to request shared instance.
it is extracted from slave_reference which is composed as <partition_id>_<reference>. #}
{%- macro jref_of_shared(ishared) %}
{#- do print('jref_of_shared %r' % (ishared,)) #}
{%- set ref = ishared['slave_reference'] %}
{%- set partition_id = slap_configuration['slap-computer-partition-id'] %}
{%- if ref.startswith(partition_id) %}
{%- set ref = ref[len(partition_id):] %}
{%- endif %}
{%- if ref.startswith('_') %}
{%- set ref = ref[1:] %}
{%- endif %}
{{- ref | tojson }}
{%- endmacro %}
{#- load_ipeercell initializes peer-cell registry.
ipeercell_dict keeps peer cell shared instances: reference -> ipeercell
#}
{%- macro load_ipeercell(ipeercell_dict) %}
// XXX TODO
{%- endmacro %}
{#- load_iue initializes UE registry.
iue_dict keeps ue shared instance: reference -> iue
#}
{%- set iue_dict = {} %}
{%- macro load_iue(iue_dict) %}
{%- set qother = [] %}
{%- for ishared in qshared_instance_list %}
{%- set ref = J(jref_of_shared(ishared)) %}
{%- set _ = ishared['_'] %}
{%- if 'ue_type' in _ %}
{%- set iue = ishared %}
{#- XXX verify ue.ue_type in lte|nr #}
{%- for k, v in defaults['ue'].items() %}
{%- do _.setdefault(k, v) %}
{%- endfor %}
{%- do iue_dict.update({ref: iue}) %}
{%- else %}
{%- do qother.append(ishared) %}
{%- endif %}
{%- endfor %}
{%- do qshared_instance_list.clear() %}
{%- do qshared_instance_list.extend(qother) %}
{%- endmacro %}