blob: 0a20459482c24a0e842dfc375fedbbe64e8c39f8 [file] [log] [blame]
Harald Welte714ded92017-12-08 14:00:22 +01001module RSL_Emulation {
2
Harald Welte35bb7162018-01-03 21:07:52 +01003/* RSL Emulation, runs on top of IPA_Emulation. It multiplexes/demultiplexes
4 * the individual connections (logical channels), so there can be separate TTCN-3 components
5 * handling each of the connections.
6 *
7 * The RSL_Emulation.main() function processes RSL messages from the IPA demultiplex
8 * stack via the IPA_RSL_PT, and dispatches them to the per-connection components.
9 *
10 * Outbound RSL connections are initiated by sending a RSLDC_ChanRqd primitive
11 * to the component running the RSL_Emulation.main() function.
12 *
Harald Weltead2647b2018-03-22 19:53:55 +010013 * in case we're emulating the BTS-side of RSL: We have no clue as to which particular logical
14 * channel the BSC may decide to activate at which point, so we have to blindly acknowledge all
15 * channel activations. Still, a test case might be interested in the exact assignment message to
16 * determine the type of activation, encryption, codec flags etc. at some later point, when it's
17 * clear for which transaction this activation happened. We keep this in the LastChanAct table.
18 *
19 * (C) 2017-2018 by Harald Welte <laforge@gnumonks.org>
Harald Welte35bb7162018-01-03 21:07:52 +010020 * All rights reserved.
21 *
22 * Released under the terms of GNU General Public License, Version 2 or
23 * (at your option) any later version.
Harald Welte34b5a952019-05-27 11:54:11 +020024 *
25 * SPDX-License-Identifier: GPL-2.0-or-later
Harald Welte35bb7162018-01-03 21:07:52 +010026 */
27
Pau Espin Pedrola07cfd92018-10-22 15:54:41 +020028import from Misc_Helpers all;
Harald Welte714ded92017-12-08 14:00:22 +010029import from General_Types all;
30import from Osmocom_Types all;
31import from GSM_Types all;
32import from GSM_RR_Types all;
33import from RSL_Types all;
34import from IPA_Types all;
35import from IPA_Emulation all;
36
37
Vadim Yanitskiy82af0b52020-06-09 20:21:43 +070038modulepar {
39 /* Work around switch for ttcn3-bts-test-latest, enables patching of IPA
40 * stream ID in the "BSC" mode. See I5927f59a49724170a63e87be604973f7c9d5d8be. */
41 boolean mp_rslem_patch_ipa_cid := false;
42};
43
Harald Welte714ded92017-12-08 14:00:22 +010044/* General "base class" component definition, of which specific implementations
45 * derive themselves by means of the "extends" feature */
46type component RSL_DchanHdlr {
47 /* port facing up towards dedicated channel handler */
48 port RSL_DCHAN_PT RSL;
Harald Weltef70df652018-01-29 22:00:23 +010049 port RSLEM_PROC_PT RSL_PROC;
Harald Welte714ded92017-12-08 14:00:22 +010050 var RslChannelNr g_chan_nr;
Harald Welte421e4d42018-02-12 20:04:50 +010051 /* second BTS / DChan during hand-over */
52 port RSL_DCHAN_PT RSL1;
53 port RSLEM_PROC_PT RSL1_PROC;
Neels Hofmeyr91401012019-07-11 00:42:35 +020054 port RSL_DCHAN_PT RSL2;
55 port RSLEM_PROC_PT RSL2_PROC;
Harald Welte714ded92017-12-08 14:00:22 +010056};
57
58type record RSLDC_ChanRqd {
59 OCT1 ra,
Pau Espin Pedrol6451b042018-10-24 20:36:16 +020060 GsmFrameNumber fn optional
Harald Welte714ded92017-12-08 14:00:22 +010061};
62
Pau Espin Pedrol6451b042018-10-24 20:36:16 +020063template (value) RSLDC_ChanRqd ts_RSLDC_ChanRqd(OCT1 ra, GsmFrameNumber fn) := {
Harald Welte714ded92017-12-08 14:00:22 +010064 ra := ra,
65 fn := fn
66}
67
Pau Espin Pedrol6451b042018-10-24 20:36:16 +020068template (value) RSLDC_ChanRqd ts_RSLDC_ChanRqd_anyFN(OCT1 ra) := {
69 ra := ra,
70 fn := omit
71}
72
Vadim Yanitskiy6de2fcb2020-05-25 19:40:45 +070073type enumerated RSLEm_EventType {
74 RSLEM_EV_TRX_UP,
75 RSLEM_EV_TRX_DOWN
76};
77
78type record RSLEm_Event {
79 RSLEm_EventType ev_type,
80 IpaStreamId sid
81};
82
83template (value) RSLEm_Event ts_RSLEm_EV(RSLEm_EventType ev_type,
84 IpaStreamId sid) := {
85 ev_type := ev_type,
86 sid := sid
87};
88template RSLEm_Event tr_RSLEm_EV(template RSLEm_EventType ev_type,
89 template IpaStreamId sid := ?) := {
90 ev_type := ev_type,
91 sid := sid
92};
93
Harald Welte714ded92017-12-08 14:00:22 +010094type port RSL_DCHAN_PT message {
95 inout RSLDC_ChanRqd, RSL_Message;
96} with { extension "internal" };
97
Harald Welte1c02fd12018-02-19 19:20:47 +010098type port RSL_CCHAN_PT message {
Vadim Yanitskiy6de2fcb2020-05-25 19:40:45 +070099 inout ASP_RSL_Unitdata, RSLEm_Event;
Harald Welte1c02fd12018-02-19 19:20:47 +0100100} with { extension "internal" };
101
102
Harald Weltef70df652018-01-29 22:00:23 +0100103signature RSLEM_register(uint8_t trx_nr, RslChannelNr chan_nr, RSL_DchanHdlr hdlr);
Harald Welte1909f462018-01-29 22:29:29 +0100104signature RSLEM_unregister(uint8_t trx_nr, RslChannelNr chan_nr, RSL_DchanHdlr hdlr);
Harald Welte70b52c92018-02-12 20:47:31 +0100105signature RSLEM_suspend(boolean suspend);
Vadim Yanitskiye9c06352020-06-20 01:30:58 +0700106signature RSLEM_wait_queue(boolean enable);
Harald Weltead2647b2018-03-22 19:53:55 +0100107signature RSLEM_get_last_act(in uint8_t trx_nr, in RslChannelNr chan_nr, out RSL_Message chan_act);
Harald Weltef70df652018-01-29 22:00:23 +0100108
109type port RSLEM_PROC_PT procedure {
Vadim Yanitskiye9c06352020-06-20 01:30:58 +0700110 inout RSLEM_register, RSLEM_unregister,
111 RSLEM_suspend, RSLEM_wait_queue,
112 RSLEM_get_last_act;
Harald Weltef70df652018-01-29 22:00:23 +0100113} with { extension "internal" };
114
Harald Welte714ded92017-12-08 14:00:22 +0100115/***********************************************************************
116 * Client Component for a single dedicated channel
117 ***********************************************************************/
118
119private function f_rx_or_fail(template RSL_Message exp_rx) runs on RSL_DchanHdlr return RSL_Message
120{
121 var RSL_Message rx_rsl;
122 timer T := 10.0;
123
124 /* request a channel to be established */
125 T.start;
126 alt {
127 [] RSL.receive(exp_rx) -> value rx_rsl {
128 T.stop;
129 return rx_rsl;
130 }
131 [] RSL.receive {
132 setverdict(fail, "Unexpected RSL message on DCHAN");
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200133 mtc.stop;
Harald Welte714ded92017-12-08 14:00:22 +0100134 }
135 [] T.timeout {
136 setverdict(fail, "Timeout waiting for RSL on DCHAN");
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200137 mtc.stop;
Harald Welte714ded92017-12-08 14:00:22 +0100138 }
139 }
140 /* never reached */
141 return rx_rsl;
142}
143
144/* establish a dedicated channel using 'ra' */
145function f_chan_est(OCT1 ra, octetstring est_l3, template RslLinkId link_id, GsmFrameNumber fn := 23)
146runs on RSL_DchanHdlr {
147 var RSL_Message rx_rsl;
148 var GsmRrMessage rr;
149
150 /* request a channel to be established */
151 RSL.send(ts_RSLDC_ChanRqd(ra, fn));
152 /* expect immediate assignment */
153 rx_rsl := f_rx_or_fail(tr_RSL_IMM_ASSIGN);
154 rr := dec_GsmRrMessage(rx_rsl.ies[1].body.full_imm_ass_info.payload);
155 g_chan_nr := rr.payload.imm_ass.chan_desc.chan_nr;
156 RSL.send(ts_RSL_EST_IND(g_chan_nr, valueof(link_id), est_l3));
157}
158
159function f_deact_chan(RSL_Cause cause) runs on RSL_DchanHdlr
160{
161 var RSL_Message rx_rsl;
162
163 RSL.send(ts_RSL_CONN_FAIL_IND(g_chan_nr, cause));
164 rx_rsl := f_rx_or_fail(tr_RSL_MsgTypeD(RSL_MT_RF_CHAN_REL));
165 /* FIXME RSL.send(ts_RSL_RF_CHAN_REL_ACK()) */
166}
167
168
169
170/***********************************************************************
171 * Main Component
172 ***********************************************************************/
173
174private type record ConnectionData {
175 /* component reference to the client component */
176 RSL_DchanHdlr comp_ref,
177 /* RSL (dedicated) Channel number we're handling */
178 uint8_t trx_nr optional,
179 IpaStreamId stream_id optional,
180 RslChannelNr chan_nr optional,
181 /* Random Reference */
182 OCT1 ra optional,
183 GsmFrameNumber ra_fn optional
184};
185
186private function f_cid_by_comp_ref(RSL_DchanHdlr comp_ref)
187runs on RSL_Emulation_CT return integer {
188 var integer i;
189 for (i := 0; i < sizeof(ConnectionTable); i := i+1) {
Pau Espin Pedrol70965092020-06-23 14:29:56 +0200190 if (ispresent(ConnectionTable[i].comp_ref) and
Harald Welte714ded92017-12-08 14:00:22 +0100191 ConnectionTable[i].comp_ref == comp_ref) {
192 return i;
193 }
194 }
Vadim Yanitskiyf79d9362020-06-03 04:06:18 +0700195 log("No Dchan handler for comp_ref=", comp_ref);
Harald Welte714ded92017-12-08 14:00:22 +0100196 return -1;
197}
198
199private function f_cid_by_chan_nr(uint8_t trx_nr, RslChannelNr chan_nr)
200runs on RSL_Emulation_CT return integer {
201 var integer i;
202 for (i := 0; i < sizeof(ConnectionTable); i := i+1) {
Pau Espin Pedrol70965092020-06-23 14:29:56 +0200203 if (ispresent(ConnectionTable[i].chan_nr) and
Harald Welte714ded92017-12-08 14:00:22 +0100204 ConnectionTable[i].chan_nr == chan_nr and ConnectionTable[i].trx_nr == trx_nr) {
205 return i;
206 }
207 }
Vadim Yanitskiyf79d9362020-06-03 04:06:18 +0700208 log("No Dchan handler for trx_nr=", trx_nr, " and chan_nr=", chan_nr);
Harald Welte714ded92017-12-08 14:00:22 +0100209 return -1;
210}
211
212private function f_cid_by_ra_fn(OCT1 ra, GsmFrameNumber fn)
213runs on RSL_Emulation_CT return integer {
214 var integer i;
215 for (i := 0; i < sizeof(ConnectionTable); i := i+1) {
216 if (ispresent(ConnectionTable[i].ra) and
217 ConnectionTable[i].ra == ra and ConnectionTable[i].ra_fn == fn) {
218 return i;
219 }
220 }
Vadim Yanitskiyf79d9362020-06-03 04:06:18 +0700221 log("No Dchan handler for ra=", ra, " and fn=", fn);
Harald Welte714ded92017-12-08 14:00:22 +0100222 return -1;
223}
224
Pau Espin Pedrol6451b042018-10-24 20:36:16 +0200225/* Matches by only RA if FN is ommited in one of the connections allocated */
226private function f_cid_by_ra_fn2(OCT1 ra, RSL_IE_FrameNumber fn)
227runs on RSL_Emulation_CT return integer {
228 var integer i;
229 for (i := 0; i < sizeof(ConnectionTable); i := i+1) {
230 if (ispresent(ConnectionTable[i].ra) and
231 ConnectionTable[i].ra == ra) {
232 if (not ispresent(ConnectionTable[i].ra_fn) or
233 fn == valueof(ts_RSL_IE_FrameNumber(ConnectionTable[i].ra_fn))) {
234 return i;
235 }
236 }
237 }
Vadim Yanitskiyf79d9362020-06-03 04:06:18 +0700238 log("No Dchan handler for ra=", ra, " and fn=", fn);
Pau Espin Pedrol6451b042018-10-24 20:36:16 +0200239 return -1;
240}
241
Harald Welte714ded92017-12-08 14:00:22 +0100242/* create an ew client with given RA and FN */
Pau Espin Pedrol6451b042018-10-24 20:36:16 +0200243private function f_cid_create(OCT1 ra, template (omit) GsmFrameNumber fn, RSL_DchanHdlr comp_ref)
Harald Welte930d0a72018-03-22 22:08:40 +0100244runs on RSL_Emulation_CT {
Harald Welte714ded92017-12-08 14:00:22 +0100245 var integer i;
246 for (i := 0; i < sizeof(ConnectionTable); i := i+1) {
Harald Weltef70df652018-01-29 22:00:23 +0100247 if (not ispresent(ConnectionTable[i].ra) and
248 not ispresent(ConnectionTable[i].trx_nr)) {
Harald Welte714ded92017-12-08 14:00:22 +0100249 ConnectionTable[i].ra := ra;
Pau Espin Pedrol6451b042018-10-24 20:36:16 +0200250 if (ispresent(fn)) {
251 ConnectionTable[i].ra_fn := valueof(fn);
252 } else {
253 ConnectionTable[i].ra_fn := omit;
254 }
Harald Welte714ded92017-12-08 14:00:22 +0100255 ConnectionTable[i].comp_ref := comp_ref;
Harald Welte930d0a72018-03-22 22:08:40 +0100256 return;
Harald Welte714ded92017-12-08 14:00:22 +0100257 }
258 }
Daniel Willmann8273fb92018-07-05 17:31:20 +0200259 testcase.stop("No free entry in conn table for ", ra, fn);
Harald Welte714ded92017-12-08 14:00:22 +0100260}
261
Vadim Yanitskiyefc94132020-05-24 04:26:45 +0700262/* create a new client with given RA and FN */
Harald Weltef70df652018-01-29 22:00:23 +0100263private function f_cid_create_cnr(uint8_t trx_nr, RslChannelNr chan_nr, RSL_DchanHdlr comp_ref)
Harald Welte930d0a72018-03-22 22:08:40 +0100264runs on RSL_Emulation_CT {
Harald Weltef70df652018-01-29 22:00:23 +0100265 var integer i;
266 for (i := 0; i < sizeof(ConnectionTable); i := i+1) {
267 if (not ispresent(ConnectionTable[i].ra) and
268 not ispresent(ConnectionTable[i].trx_nr)) {
269 ConnectionTable[i].stream_id := f_streamId_by_trx(trx_nr);
270 ConnectionTable[i].trx_nr := trx_nr;
271 ConnectionTable[i].chan_nr := chan_nr;
272 ConnectionTable[i].comp_ref := comp_ref;
Harald Welte930d0a72018-03-22 22:08:40 +0100273 return;
Harald Weltef70df652018-01-29 22:00:23 +0100274 }
275 }
Daniel Willmann8273fb92018-07-05 17:31:20 +0200276 testcase.stop("No free entry in conn table for ", trx_nr, chan_nr, comp_ref);
Harald Weltef70df652018-01-29 22:00:23 +0100277}
278
279
Vadim Yanitskiyefc94132020-05-24 04:26:45 +0700280/* delete client with given RA and FN */
Harald Weltef70df652018-01-29 22:00:23 +0100281private function f_cid_delete_cnr(IpaStreamId stream_id, RslChannelNr chan_nr, RSL_DchanHdlr comp_ref)
282runs on RSL_Emulation_CT return integer {
283 var integer i;
284 for (i := 0; i < sizeof(ConnectionTable); i := i+1) {
285 if (ConnectionTable[i].comp_ref == null) {
286 continue;
287 }
288 if (ConnectionTable[i].stream_id == stream_id and
289 ConnectionTable[i].chan_nr == chan_nr and
290 ConnectionTable[i].comp_ref == comp_ref) {
291 f_cid_clear(i);
292 }
293 }
294 log("Unable to find entry to delete for ", stream_id, chan_nr, comp_ref);
295 return -1;
296}
297
298
Harald Welte714ded92017-12-08 14:00:22 +0100299private function f_cid_clear(integer cid)
300runs on RSL_Emulation_CT {
301 ConnectionTable[cid].ra := omit;
302 ConnectionTable[cid].ra_fn := omit;
Harald Welte714ded92017-12-08 14:00:22 +0100303 ConnectionTable[cid].trx_nr := omit;
304 ConnectionTable[cid].stream_id := omit;
305 ConnectionTable[cid].chan_nr := omit;
Harald Weltef70df652018-01-29 22:00:23 +0100306 ConnectionTable[cid].comp_ref := null;
Harald Welte714ded92017-12-08 14:00:22 +0100307}
308
Harald Weltead2647b2018-03-22 19:53:55 +0100309/* last activation for a given channel number */
310type record LastActData {
311 uint8_t trx_nr optional,
312 RslChannelNr chan_nr optional,
313 RSL_Message chan_act optional
314}
315
316private function f_store_last_act_data(uint8_t trx_nr, RslChannelNr chan_nr, RSL_Message chan_act)
317runs on RSL_Emulation_CT {
318 for (var integer i := 0; i < sizeof(LastActTable); i := i+1) {
319 if (not ispresent(LastActTable[i].chan_nr) or
320 (LastActTable[i].chan_nr == chan_nr and LastActTable[i].trx_nr == trx_nr)) {
321 LastActTable[i].trx_nr := trx_nr;
322 LastActTable[i].chan_nr := chan_nr;
323 LastActTable[i].chan_act := chan_act;
324 return;
325 }
326 }
Daniel Willmann8273fb92018-07-05 17:31:20 +0200327 testcase.stop("No space left in LastActTable to store chan_act for ", chan_nr);
Harald Weltead2647b2018-03-22 19:53:55 +0100328}
329
330private function f_lookup_last_act(uint8_t trx_nr, RslChannelNr chan_nr)
331runs on RSL_Emulation_CT return RSL_Message {
332 for (var integer i := 0; i < sizeof(LastActTable); i := i+1) {
333 if (ispresent(LastActTable[i].chan_nr) and LastActTable[i].chan_nr == chan_nr
334 and LastActTable[i].trx_nr == trx_nr) {
335 return LastActTable[i].chan_act;
336 }
337 }
Daniel Willmann8273fb92018-07-05 17:31:20 +0200338 testcase.stop("No LastActTable entry found for TRX ", trx_nr, " ", chan_nr);
Harald Weltead2647b2018-03-22 19:53:55 +0100339}
340
341private function f_last_act_table_init() runs on RSL_Emulation_CT {
342 for (var integer i := 0; i < sizeof(LastActTable); i := i+1) {
343 LastActTable[i] := { omit, omit, omit };
344 }
345}
346
Vadim Yanitskiy6de2fcb2020-05-25 19:40:45 +0700347private function f_trx_conn_map_init()
348runs on RSL_Emulation_CT {
349 for (var integer i := 0; i < sizeof(TrxConnMap); i := i + 1) {
350 TrxConnMap[i] := -1;
351 }
352}
353
354private function f_trx_conn_map_register(integer conn_id, in IpaCcmIdResp id_resp)
355runs on RSL_Emulation_CT return IpaStreamId {
356 var template charstring unit_id_fmt := pattern "(\d+)/(\d+)/(\d+)";
357 var charstring unit_id;
358 var integer trx_nr;
359 var integer idx;
360
361 /* Check if we have room for a new connection */
362 if (TrxConnNum >= sizeof(TrxConnMap)) {
363 testcase.stop("We cannot handle more than ", sizeof(TrxConnMap), " transceivers");
364 }
365
366 /* Find IPAC_IDTAG_UNITID in the IPA IDENTITY RESPONSE */
367 idx := f_ipa_id_resp_find_ie(id_resp, IPAC_IDTAG_UNITID);
368 if (idx < 0) {
369 testcase.stop("IPA IDENTITY RESPONSE contains no unit-id");
370 }
371
372 /* Make sure that IPA unit-id is valid */
373 unit_id := oct2char(id_resp[idx].data);
374 if (not match(unit_id, unit_id_fmt)) {
375 testcase.stop("IPA unit-id has unknown/unexpected format");
376 }
377
378 /* Parse transceiver number (site/bts/trx).
379 * TODO: implement and use declaratice types. */
380 unit_id := regexp(unit_id, unit_id_fmt, 2);
381 trx_nr := str2int(unit_id);
382
383 if (trx_nr >= sizeof(TrxConnMap)) {
384 testcase.stop("Transceiver #", trx_nr, " does not fit");
385 } else if (TrxConnMap[trx_nr] != -1) {
386 testcase.stop("Transceiver #", trx_nr, " is already connected?!?");
387 }
388
389 /* Finally, store the connection ID */
390 log("Mapped TRX#", trx_nr, " to TCP/IP conn_id=", conn_id);
391 TrxConnMap[trx_nr] := conn_id;
392 TrxConnNum := TrxConnNum + 1;
393
394 return f_streamId_by_trx(trx_nr);
395}
396
Pau Espin Pedrolabcdf782020-06-23 14:29:24 +0200397private function f_trx_conn_map_unregister(integer conn_id)
398runs on RSL_Emulation_CT return IpaStreamId {
399
400 for (var integer i := 0; i < sizeof(TrxConnMap); i := i + 1) {
401 if (conn_id == TrxConnMap[i]) {
402 TrxConnMap[i] := -1;
403 TrxConnNum := TrxConnNum - 1;
404 return f_streamId_by_trx(i);
405 }
406 }
407
408 testcase.stop("Trying to unregister an unknown conn_id=", conn_id);
409}
410
Vadim Yanitskiy6de2fcb2020-05-25 19:40:45 +0700411private function f_trx_conn_map_resolve(IpaStreamId id)
412runs on RSL_Emulation_CT return integer {
413 var integer trx_nr := f_trx_by_streamId(id);
414
415 if (TrxConnMap[trx_nr] == -1) {
416 testcase.stop("Transceiver #", trx_nr, " is not connected");
417 }
418
419 return TrxConnMap[trx_nr];
420}
421
Vadim Yanitskiy82af0b52020-06-09 20:21:43 +0700422/* Work around for a bug in osmo-bts when all transceivers use IPAC_PROTO_RSL_TRX0 */
423private function f_trx_conn_map_patch_ud(inout ASP_RSL_Unitdata ud)
424runs on RSL_Emulation_CT {
425 for (var integer i := 0; i < sizeof(TrxConnMap); i := i + 1) {
426 if (ud.conn_id == TrxConnMap[i]) {
427 ud.streamId := f_streamId_by_trx(i);
428 return; /* We're done */
429 }
430 }
431
432 testcase.stop("Failed to patch IPA stream ID in ASP RSL UD: ", ud);
433}
434
Vadim Yanitskiye9c06352020-06-20 01:30:58 +0700435private type record of ASP_RSL_Unitdata ASP_RSL_UDList;
436
Harald Welte714ded92017-12-08 14:00:22 +0100437type component RSL_Emulation_CT {
438 /* port facing down towards IPA emulation */
439 port IPA_RSL_PT IPA_PT;
440 /* port facing up towards dedicated channel handler */
441 port RSL_DCHAN_PT CLIENT_PT;
Harald Weltef70df652018-01-29 22:00:23 +0100442 port RSLEM_PROC_PT RSL_PROC;
Harald Welte714ded92017-12-08 14:00:22 +0100443
Harald Welte1c02fd12018-02-19 19:20:47 +0100444 /* port for Common Channel / TRX Management */
445 port RSL_CCHAN_PT CCHAN_PT;
446
Harald Welte714ded92017-12-08 14:00:22 +0100447 /* state of all concurrent connections / dedicated channels */
448 var ConnectionData ConnectionTable[64];
Harald Weltead2647b2018-03-22 19:53:55 +0100449
Vadim Yanitskiye9c06352020-06-20 01:30:58 +0700450 /* RSL messages for which no handler is currently registered */
451 var ASP_RSL_UDList WaitingQueue := { };
452
Harald Weltead2647b2018-03-22 19:53:55 +0100453 /* last RSL CHAN ACT for each chan_nr */
454 var LastActData LastActTable[64];
Vadim Yanitskiy6de2fcb2020-05-25 19:40:45 +0700455
456 /* IPA stream ID -> TCP/IP connection ID mapping for transceivers */
457 var integer TrxConnNum := 0; /* number of connected transceivers */
458 var integer TrxConnMap[4]; /* up to 4 transceivers for now */
Harald Welte714ded92017-12-08 14:00:22 +0100459}
460
461
Harald Welte714ded92017-12-08 14:00:22 +0100462private function f_trx_by_streamId(IpaStreamId id) return integer {
463 return enum2int(id);
464}
465
Harald Weltef70df652018-01-29 22:00:23 +0100466private function f_streamId_by_trx(uint8_t trx_nr) return IpaStreamId {
467 select (trx_nr) {
468 case (0) { return IPAC_PROTO_RSL_TRX0; }
469 case (1) { return IPAC_PROTO_RSL_TRX1; }
470 case (2) { return IPAC_PROTO_RSL_TRX2; }
471 case (3) { return IPAC_PROTO_RSL_TRX3; }
472 }
Daniel Willmanna6ea2ef2018-07-24 09:55:52 +0200473 setverdict(fail, "Unknown stream ID ", trx_nr);
474 mtc.stop;
Harald Weltef70df652018-01-29 22:00:23 +0100475}
476
Harald Welte714ded92017-12-08 14:00:22 +0100477
Harald Welte1c02fd12018-02-19 19:20:47 +0100478function main(boolean bts_role := true) runs on RSL_Emulation_CT {
Harald Weltebb6aed32018-02-21 12:19:18 +0100479 var ASP_IPA_Event evt;
Harald Welte714ded92017-12-08 14:00:22 +0100480 var ASP_RSL_Unitdata rx_rsl;
481 var RSL_Message rx_rsl_msg;
482 var RSLDC_ChanRqd chan_rqd;
483 var RSL_DchanHdlr vc_conn;
Harald Weltef70df652018-01-29 22:00:23 +0100484 var RslChannelNr chan_nr;
485 var uint8_t trx_nr;
Vadim Yanitskiy6de2fcb2020-05-25 19:40:45 +0700486 var integer conn_id;
Harald Welte714ded92017-12-08 14:00:22 +0100487 var integer cid;
488 var integer i;
Harald Welte70b52c92018-02-12 20:47:31 +0100489 /* special synchronization handling during hand-over */
490 var boolean dchan_suspended := false;
Vadim Yanitskiye9c06352020-06-20 01:30:58 +0700491 /* Whether to keep RSL messages, for which no handler is found in ConnectionTable,
492 * in a queue. These messages will remain in the queue until the appropriate
493 * connection handler is registered. */
494 var boolean wait_queue_enabled := false;
Harald Welte714ded92017-12-08 14:00:22 +0100495
Daniel Willmann17f970f2018-01-17 12:03:19 +0100496 f_conn_table_init();
Vadim Yanitskiy6de2fcb2020-05-25 19:40:45 +0700497 f_trx_conn_map_init();
Harald Weltead2647b2018-03-22 19:53:55 +0100498 f_last_act_table_init();
Daniel Willmann17f970f2018-01-17 12:03:19 +0100499
Harald Welte714ded92017-12-08 14:00:22 +0100500 while (true) {
501 alt {
Vadim Yanitskiya2afacc2020-05-18 21:16:19 +0700502 [bts_role] IPA_PT.receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_UP)) {
Harald Weltebb6aed32018-02-21 12:19:18 +0100503 }
Vadim Yanitskiya2afacc2020-05-18 21:16:19 +0700504 [not bts_role] IPA_PT.receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_UP)) -> value evt {
Vadim Yanitskiy6de2fcb2020-05-25 19:40:45 +0700505 log("A new IPA/RSL connection has been established (conn_id=",
506 evt.conn_id, "), waiting for IDENTITY RESPONSE...");
507 }
508 [not bts_role] IPA_PT.receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_ID_RESP)) -> value evt {
509 log("Got IDENTITY RESPONSE (conn_id=", evt.conn_id, "): ", evt.id_resp);
510 /* Update [ IPA stream ID -> TCP/IP connection ID ] mapping */
511 var IpaStreamId sid := f_trx_conn_map_register(evt.conn_id, evt.id_resp);
512 /* Notify the upper layers about a new connection */
513 CCHAN_PT.send(ts_RSLEm_EV(RSLEM_EV_TRX_UP, sid));
Harald Welte624f9632017-12-16 19:26:04 +0100514 }
Pau Espin Pedrolabcdf782020-06-23 14:29:24 +0200515 [bts_role] IPA_PT.receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_DOWN)) -> value evt {
516 log("Lost IPA connection! (conn_id=", evt.conn_id, "): ", evt.id_resp);
517 /* Notify the upper layers about lost connection */
518 var IpaStreamId sid := f_trx_conn_map_unregister(evt.conn_id);
519 CCHAN_PT.send(ts_RSLEm_EV(RSLEM_EV_TRX_DOWN, sid));
Pau Espin Pedrola07cfd92018-10-22 15:54:41 +0200520 }
Pau Espin Pedrolabcdf782020-06-23 14:29:24 +0200521 [not bts_role] IPA_PT.receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_DOWN)) -> value evt {
522 log("Lost IPA connection! (conn_id=", evt.conn_id, ")");
523 /* Notify the upper layers about lost connection */
524 var IpaStreamId sid := f_trx_conn_map_unregister(evt.conn_id);
525 CCHAN_PT.send(ts_RSLEm_EV(RSLEM_EV_TRX_DOWN, sid));
Pau Espin Pedrola07cfd92018-10-22 15:54:41 +0200526 }
Vadim Yanitskiya2afacc2020-05-18 21:16:19 +0700527 [bts_role] IPA_PT.receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_ID_ACK)) {
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +0700528 IPA_PT.send(ts_ASP_RSL_UD(ts_RSL_PAGING_LOAD_IND(23)));
Harald Welte714ded92017-12-08 14:00:22 +0100529 }
Vadim Yanitskiya2afacc2020-05-18 21:16:19 +0700530 [not bts_role] IPA_PT.receive(tr_ASP_IPA_EV(ASP_IPA_EVENT_ID_ACK)) { }
Vadim Yanitskiya60e5cf2020-05-26 01:46:31 +0700531 [bts_role] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_IMM_ASSIGN, sid := ?)) -> value rx_rsl {
Harald Welte714ded92017-12-08 14:00:22 +0100532 var GsmRrMessage rr;
533 var OCT1 ra;
534 var GsmFrameNumber fn;
Harald Welte714ded92017-12-08 14:00:22 +0100535 rr := dec_GsmRrMessage(rx_rsl.rsl.ies[1].body.full_imm_ass_info.payload);
536 if (ischosen(rr.payload.imm_ass)) {
537 ra := bit2oct(rr.payload.imm_ass.req_ref.ra);
538 fn := 23; //FIXME(rr.payload.imm_ass);
539 /* lookup client based on RA+time, deliver to client */
540 cid := f_cid_by_ra_fn(ra, fn);
541 if (cid == -1) {
542 setverdict(fail, "IMM ASS for unknown DChan");
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200543 mtc.stop;
Harald Welte714ded92017-12-08 14:00:22 +0100544 }
545 /* update client with trx_nr */
546 ConnectionTable[cid].trx_nr := f_trx_by_streamId(rx_rsl.streamId);
547 ConnectionTable[cid].stream_id := rx_rsl.streamId;
548 /* update client with chan_nr */
549 ConnectionTable[cid].chan_nr := rr.payload.imm_ass.chan_desc.chan_nr;
550 /* TODO: add timer to time-out ConnectionTable entries which
551 * never get followed-up to */
552 CLIENT_PT.send(rx_rsl.rsl) to ConnectionTable[cid].comp_ref;
553 } else if (ischosen(rr.payload.imm_ass_rej)) {
554 for (i := 0; i < sizeof(rr.payload.imm_ass_rej.payload); i := i + 1) {
555 ra := bit2oct(rr.payload.imm_ass_rej.payload[i].req_ref.ra);
556 fn := 23; //FIXME();
557 /* lookup client based on RA+time, deliver to client */
558 cid := f_cid_by_ra_fn(ra, fn);
559 if (cid != -1) {
560 CLIENT_PT.send(rx_rsl.rsl) to ConnectionTable[cid].comp_ref;
561 /* delete ClientTable entry, as it failed */
562 f_cid_clear(cid);
563 }
564 }
565 }
566 }
Vadim Yanitskiya60e5cf2020-05-26 01:46:31 +0700567 [not bts_role] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_CHAN_RQD(?), sid := ?)) -> value rx_rsl {
Pau Espin Pedrol6451b042018-10-24 20:36:16 +0200568 var RSL_IE_RequestRef req_ref;
569 req_ref := rx_rsl.rsl.ies[1].body.req_ref;
570 cid := f_cid_by_ra_fn2(req_ref.ra, req_ref.frame_nr);
571 if (cid != -1) {
572 CLIENT_PT.send(rx_rsl.rsl) to ConnectionTable[cid].comp_ref;
573 f_cid_clear(cid);
574 } else {
575 CCHAN_PT.send(rx_rsl);
576 }
577 }
Harald Welte714ded92017-12-08 14:00:22 +0100578
Vadim Yanitskiya60e5cf2020-05-26 01:46:31 +0700579 [bts_role] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_PAGING_CMD(?, ?), sid := ?)) -> value rx_rsl {
Harald Welte714ded92017-12-08 14:00:22 +0100580 /* broadcast to all clients? */
581 for (i := 0; i < sizeof(ConnectionTable); i := i + 1) {
Neels Hofmeyrd7eabd62020-06-08 22:30:54 +0200582 if (ispresent(ConnectionTable[i].comp_ref) and ConnectionTable[i].comp_ref != null) {
Harald Welte714ded92017-12-08 14:00:22 +0100583 CLIENT_PT.send(rx_rsl.rsl) to ConnectionTable[i].comp_ref;
584 }
585 }
586 }
587
Harald Welte1c02fd12018-02-19 19:20:47 +0100588 /* Forward common channel management to the special port for it */
Vadim Yanitskiya60e5cf2020-05-26 01:46:31 +0700589 [] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeT(?), sid := ?)) -> value rx_rsl {
Vadim Yanitskiy82af0b52020-06-09 20:21:43 +0700590 if (not bts_role and mp_rslem_patch_ipa_cid) {
591 f_trx_conn_map_patch_ud(rx_rsl);
592 }
Harald Welte1c02fd12018-02-19 19:20:47 +0100593 CCHAN_PT.send(rx_rsl);
Harald Welte714ded92017-12-08 14:00:22 +0100594 }
595
Harald Welte1c02fd12018-02-19 19:20:47 +0100596 /* Forward common channel management to the special port for it */
Vadim Yanitskiya60e5cf2020-05-26 01:46:31 +0700597 [] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeC(?), sid := ?)) -> value rx_rsl {
Vadim Yanitskiy82af0b52020-06-09 20:21:43 +0700598 if (not bts_role and mp_rslem_patch_ipa_cid) {
599 f_trx_conn_map_patch_ud(rx_rsl);
600 }
Harald Welte1c02fd12018-02-19 19:20:47 +0100601 CCHAN_PT.send(rx_rsl);
Harald Welte714ded92017-12-08 14:00:22 +0100602 }
603
604 /* blindly acknowledge all channel activations */
Vadim Yanitskiya60e5cf2020-05-26 01:46:31 +0700605 [bts_role] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), sid := ?)) -> value rx_rsl {
Harald Weltef70df652018-01-29 22:00:23 +0100606 chan_nr := rx_rsl.rsl.ies[0].body.chan_nr;
Harald Weltead2647b2018-03-22 19:53:55 +0100607 trx_nr := f_trx_by_streamId(rx_rsl.streamId);
608 f_store_last_act_data(trx_nr, chan_nr, rx_rsl.rsl);
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +0700609 IPA_PT.send(ts_ASP_RSL_UD(ts_RSL_CHAN_ACT_ACK(chan_nr, 23), rx_rsl.streamId));
Harald Welte714ded92017-12-08 14:00:22 +0100610 }
611
Vadim Yanitskiya60e5cf2020-05-26 01:46:31 +0700612 [not dchan_suspended] IPA_PT.receive(tr_ASP_RSL_UD(tr_RSL_MsgTypeDR(?), sid := ?)) -> value rx_rsl {
Harald Welte714ded92017-12-08 14:00:22 +0100613 /* dispatch to channel based on ChanId */
614 cid := f_cid_by_chan_nr(f_trx_by_streamId(rx_rsl.streamId),
615 rx_rsl.rsl.ies[0].body.chan_nr);
616 if (cid != -1) {
617 CLIENT_PT.send(rx_rsl.rsl) to ConnectionTable[cid].comp_ref;
Vadim Yanitskiye9c06352020-06-20 01:30:58 +0700618 } else if (wait_queue_enabled) {
619 log("Storing an RSL message in the waiting queue");
620 WaitingQueue := WaitingQueue & { rx_rsl };
Harald Welte714ded92017-12-08 14:00:22 +0100621 } else {
622 setverdict(fail, "RSL for unknown Dchan");
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200623 mtc.stop;
Harald Welte714ded92017-12-08 14:00:22 +0100624 }
625 }
626
Harald Welte70b52c92018-02-12 20:47:31 +0100627 [not dchan_suspended] IPA_PT.receive {
Harald Welte714ded92017-12-08 14:00:22 +0100628 setverdict(fail, "Received unknown primitive from IPA");
Daniel Willmanne4ff5372018-07-05 17:35:03 +0200629 mtc.stop;
Harald Welte714ded92017-12-08 14:00:22 +0100630 }
631
Harald Welte1c02fd12018-02-19 19:20:47 +0100632 [bts_role] CLIENT_PT.receive(RSLDC_ChanRqd:?) -> value chan_rqd sender vc_conn {
Harald Welte714ded92017-12-08 14:00:22 +0100633 /* Store the knowledge that this sender has requested a certain RQ+time */
634 f_cid_create(chan_rqd.ra, chan_rqd.fn, vc_conn);
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +0700635 IPA_PT.send(ts_ASP_RSL_UD(ts_RSL_CHAN_RQD(chan_rqd.ra, chan_rqd.fn)));
Harald Welte714ded92017-12-08 14:00:22 +0100636 }
637
Pau Espin Pedrol6451b042018-10-24 20:36:16 +0200638 [not bts_role] CLIENT_PT.receive(RSLDC_ChanRqd:?) -> value chan_rqd sender vc_conn {
639 /* Store the knowledge that this sender has requested a certain RQ+time */
640 f_cid_create(chan_rqd.ra, chan_rqd.fn, vc_conn);
641 }
642
Vadim Yanitskiy6de2fcb2020-05-25 19:40:45 +0700643 /* RSL message from a component that runs on RSL_DchanHdlr */
644 [bts_role] CLIENT_PT.receive(tr_RSL_MsgType(?)) -> value rx_rsl_msg sender vc_conn {
Harald Welte714ded92017-12-08 14:00:22 +0100645 cid := f_cid_by_comp_ref(vc_conn);
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +0700646 IPA_PT.send(ts_ASP_RSL_UD(rx_rsl_msg, ConnectionTable[cid].stream_id));
Harald Welte714ded92017-12-08 14:00:22 +0100647 }
Vadim Yanitskiy6de2fcb2020-05-25 19:40:45 +0700648 [not bts_role] CLIENT_PT.receive(tr_RSL_MsgType(?)) -> value rx_rsl_msg sender vc_conn {
649 cid := f_cid_by_comp_ref(vc_conn);
650 conn_id := f_trx_conn_map_resolve(ConnectionTable[cid].stream_id);
651 IPA_PT.send(ts_ASP_RSL_UD(rx_rsl_msg, ConnectionTable[cid].stream_id, conn_id));
652 }
Harald Welte714ded92017-12-08 14:00:22 +0100653
Vadim Yanitskiy6de2fcb2020-05-25 19:40:45 +0700654 /* RSL message from MTC */
655 [bts_role] CCHAN_PT.receive(tr_ASP_RSL_UD(?, sid := ?)) -> value rx_rsl {
Vadim Yanitskiy9b4e3562020-05-25 21:40:52 +0700656 IPA_PT.send(ts_ASP_RSL_UD(rx_rsl.rsl, rx_rsl.streamId));
Harald Welte34252c52018-02-24 04:51:50 +0100657 }
Vadim Yanitskiy6de2fcb2020-05-25 19:40:45 +0700658 [not bts_role] CCHAN_PT.receive(tr_ASP_RSL_UD(?, sid := ?)) -> value rx_rsl {
659 conn_id := f_trx_conn_map_resolve(rx_rsl.streamId);
660 IPA_PT.send(ts_ASP_RSL_UD(rx_rsl.rsl, rx_rsl.streamId, conn_id));
661 }
Harald Welte34252c52018-02-24 04:51:50 +0100662
Harald Weltef70df652018-01-29 22:00:23 +0100663 /* explicit registration, e.g. in (non-immediate) assignment case */
664 [] RSL_PROC.getcall(RSLEM_register:{?,?,?}) -> param(trx_nr, chan_nr, vc_conn) {
665 f_cid_create_cnr(trx_nr, chan_nr, vc_conn);
Harald Weltee32ad992018-05-31 22:17:46 +0200666 RSL_PROC.reply(RSLEM_register:{trx_nr, chan_nr, vc_conn}) to vc_conn;
Harald Weltef70df652018-01-29 22:00:23 +0100667 }
668
Harald Welte1909f462018-01-29 22:29:29 +0100669 [] RSL_PROC.getcall(RSLEM_unregister:{?,?,?}) -> param(trx_nr, chan_nr, vc_conn) {
670 cid := f_cid_by_chan_nr(trx_nr, chan_nr);
671 f_cid_clear(cid);
Harald Weltee32ad992018-05-31 22:17:46 +0200672 RSL_PROC.reply(RSLEM_unregister:{trx_nr, chan_nr, vc_conn}) to vc_conn;
Harald Welte1909f462018-01-29 22:29:29 +0100673 }
674
Harald Weltee32ad992018-05-31 22:17:46 +0200675 [] RSL_PROC.getcall(RSLEM_suspend:{true}) -> sender vc_conn {
Harald Welte70b52c92018-02-12 20:47:31 +0100676 log("Suspending DChan");
677 dchan_suspended := true;
Harald Weltee32ad992018-05-31 22:17:46 +0200678 RSL_PROC.reply(RSLEM_suspend:{true}) to vc_conn;
Harald Welte70b52c92018-02-12 20:47:31 +0100679 }
680
Harald Weltee32ad992018-05-31 22:17:46 +0200681 [] RSL_PROC.getcall(RSLEM_suspend:{false}) -> sender vc_conn {
Harald Welte70b52c92018-02-12 20:47:31 +0100682 log("Resuming DChan");
683 dchan_suspended := false;
Harald Weltee32ad992018-05-31 22:17:46 +0200684 RSL_PROC.reply(RSLEM_suspend:{false}) to vc_conn;
Harald Welte70b52c92018-02-12 20:47:31 +0100685 }
Harald Welte1909f462018-01-29 22:29:29 +0100686
Vadim Yanitskiye9c06352020-06-20 01:30:58 +0700687 [not wait_queue_enabled] RSL_PROC.getcall(RSLEM_wait_queue:{true}) -> sender vc_conn {
688 wait_queue_enabled := true;
689 log("Enabled queueing of DChan messages");
690 RSL_PROC.reply(RSLEM_wait_queue:{wait_queue_enabled}) to vc_conn;
691 }
692
693 [wait_queue_enabled] RSL_PROC.getcall(RSLEM_wait_queue:{false}) -> sender vc_conn {
694 /* Dispatch stalled messages (if any) */
695 f_WaitingQueue_dispatch();
696
697 wait_queue_enabled := false;
698 log("Disabled queueing of DChan messages");
699 RSL_PROC.reply(RSLEM_wait_queue:{wait_queue_enabled}) to vc_conn;
700 }
701
702 [] RSL_PROC.getcall(RSLEM_wait_queue:{?}) -> sender vc_conn {
703 log("Queueing of DChan messages is already enabled/disabled");
704 RSL_PROC.reply(RSLEM_wait_queue:{wait_queue_enabled}) to vc_conn;
705 }
706
Harald Weltee32ad992018-05-31 22:17:46 +0200707 [] RSL_PROC.getcall(RSLEM_get_last_act:{?,?,?}) -> param(trx_nr, chan_nr) sender vc_conn {
Harald Weltead2647b2018-03-22 19:53:55 +0100708 var RSL_Message last_chan_act := f_lookup_last_act(trx_nr, chan_nr);
Harald Weltee32ad992018-05-31 22:17:46 +0200709 RSL_PROC.reply(RSLEM_get_last_act:{trx_nr, chan_nr, last_chan_act}) to vc_conn;
Harald Weltead2647b2018-03-22 19:53:55 +0100710 }
Harald Welte714ded92017-12-08 14:00:22 +0100711 }
712 }
713}
714
Daniel Willmann17f970f2018-01-17 12:03:19 +0100715private function f_conn_table_init()
716runs on RSL_Emulation_CT {
717 var integer i;
718
719 /* Initialize the ConnectionTable */
720 for (i := 0; i < sizeof(ConnectionTable); i := i+1) {
721 f_cid_clear(i);
722 }
723}
Harald Welte714ded92017-12-08 14:00:22 +0100724
Vadim Yanitskiye9c06352020-06-20 01:30:58 +0700725private function f_WaitingQueue_dispatch()
726runs on RSL_Emulation_CT {
727 var integer cid;
728
729 for (var integer i := 0; i < lengthof(WaitingQueue); i := i + 1) {
730 cid := f_cid_by_chan_nr(f_trx_by_streamId(WaitingQueue[i].streamId),
731 WaitingQueue[i].rsl.ies[0].body.chan_nr);
732 if (cid == -1) {
733 setverdict(fail, "No Dchan handler found for: ", WaitingQueue[i]);
734 mtc.stop;
Vadim Yanitskiye9c06352020-06-20 01:30:58 +0700735 }
736
737 /* Dispatch a stalled message to the appropriate handler */
738 CLIENT_PT.send(WaitingQueue[i].rsl) to ConnectionTable[cid].comp_ref;
739 }
740
741 /* All messages dispatched, clear the queue */
742 WaitingQueue := { };
743}
744
Harald Weltef70df652018-01-29 22:00:23 +0100745/* client/conn_hdlr side function to use procedure port to register stream_id/chan_nr */
Harald Welte421e4d42018-02-12 20:04:50 +0100746function f_rslem_register(uint8_t trx_nr, RslChannelNr chan_nr, RSLEM_PROC_PT PT := RSL_PROC)
747runs on RSL_DchanHdlr {
748 PT.call(RSLEM_register:{trx_nr, chan_nr, self}) {
749 [] PT.getreply(RSLEM_register:{?,?,?}) {};
Harald Weltef70df652018-01-29 22:00:23 +0100750 }
751}
752
Harald Welte1909f462018-01-29 22:29:29 +0100753/* client/conn_hdlr side function to use procedure port to unregister stream_id/chan_nr */
Harald Welte421e4d42018-02-12 20:04:50 +0100754function f_rslem_unregister(uint8_t trx_nr, RslChannelNr chan_nr, RSLEM_PROC_PT PT := RSL_PROC)
755runs on RSL_DchanHdlr {
756 PT.call(RSLEM_unregister:{trx_nr, chan_nr, self}) {
757 [] PT.getreply(RSLEM_unregister:{?,?,?}) {};
Harald Welte1909f462018-01-29 22:29:29 +0100758 }
759}
760
Vadim Yanitskiya38c2652020-06-21 19:47:00 +0700761/* suspend handling of RSL DChan messages from IPA until f_rslem_resume() is called */
Harald Welte70b52c92018-02-12 20:47:31 +0100762function f_rslem_suspend(RSLEM_PROC_PT PT)
763runs on RSL_DchanHdlr {
764 PT.call(RSLEM_suspend:{true}) {
765 [] PT.getreply(RSLEM_suspend:{true}) {};
766 }
767}
768
769/* resume handling of RSL DChan messages after f_rslem_suspend() is called */
770function f_rslem_resume(RSLEM_PROC_PT PT)
771runs on RSL_DchanHdlr {
772 PT.call(RSLEM_suspend:{false}) {
773 [] PT.getreply(RSLEM_suspend:{false}) {};
774 }
775}
776
Vadim Yanitskiye9c06352020-06-20 01:30:58 +0700777/* Enable queueing of RSL DChan messages from IPA until f_rslem_dchan_queue_disable() is called. */
778function f_rslem_dchan_queue_enable(RSLEM_PROC_PT PT := RSL_PROC)
779runs on RSL_DchanHdlr {
780 PT.call(RSLEM_wait_queue:{true}) {
781 [] PT.getreply(RSLEM_wait_queue:{true}) {};
782 }
783}
784
785/* Disable queueing of RSL DChan messages after f_rslem_dchan_queue_enable() is called.
786 * Dispatch all stalled messages to the registered handlers. Make sure that no
787 * messages for which there is no handler are left in the queue (mtc.stop if so). */
788function f_rslem_dchan_queue_dispatch(RSLEM_PROC_PT PT := RSL_PROC)
789runs on RSL_DchanHdlr {
790 PT.call(RSLEM_wait_queue:{false}) {
791 [] PT.getreply(RSLEM_wait_queue:{false}) {};
792 }
793}
794
Harald Weltead2647b2018-03-22 19:53:55 +0100795/* obtain the last RSL_CHAN_ACT message for the given chan_nr */
796function f_rslem_get_last_act(RSLEM_PROC_PT PT, uint8_t trx_nr, RslChannelNr chan_nr)
797runs on RSL_DchanHdlr return RSL_Message {
798 var RSL_Message chan_act;
799 PT.call(RSLEM_get_last_act:{trx_nr, chan_nr, -}) {
800 [] PT.getreply(RSLEM_get_last_act:{trx_nr, chan_nr, ?}) -> param(chan_act) {};
801 }
802 return chan_act;
803}
804
805
Harald Welte70b52c92018-02-12 20:47:31 +0100806
Harald Welte1909f462018-01-29 22:29:29 +0100807
Harald Welte714ded92017-12-08 14:00:22 +0100808}