blob: b5e30fb85cf828229279dbb60e662804dffe6b2f [file] [log] [blame]
Jacob Erlbecke04e0b02015-05-06 18:30:48 +02001/*
2 * MsTest.cpp
3 *
4 * Copyright (C) 2015 by Sysmocom s.f.m.c. GmbH
5 *
6 * All Rights Reserved
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU Affero General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU Affero General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 *
21 */
22
23#include "tbf.h"
Pau Espin Pedrol9d1cdb12019-09-25 17:47:02 +020024#include "tbf_ul.h"
Jacob Erlbecke04e0b02015-05-06 18:30:48 +020025#include "gprs_debug.h"
26#include "gprs_ms.h"
Jacob Erlbeck53670862015-05-12 17:54:33 +020027#include "gprs_ms_storage.h"
Jacob Erlbeck70b96aa2015-06-12 10:52:34 +020028#include "bts.h"
Jacob Erlbecke04e0b02015-05-06 18:30:48 +020029
30extern "C" {
31#include "pcu_vty.h"
32
33#include <osmocom/core/application.h>
34#include <osmocom/core/msgb.h>
35#include <osmocom/core/talloc.h>
36#include <osmocom/core/utils.h>
37#include <osmocom/vty/vty.h>
38}
39
40#include <errno.h>
Jacob Erlbeckd9e10242015-05-28 15:43:53 +020041#include <unistd.h>
Jacob Erlbecke04e0b02015-05-06 18:30:48 +020042
Pau Espin Pedrola0cbde72020-03-26 15:56:15 +010043#include <new>
44
Jacob Erlbecke04e0b02015-05-06 18:30:48 +020045void *tall_pcu_ctx;
46int16_t spoof_mnc = 0, spoof_mcc = 0;
Neels Hofmeyrbdc55fa2018-02-21 00:39:07 +010047bool spoof_mnc_3_digits = false;
Jacob Erlbecke04e0b02015-05-06 18:30:48 +020048
49static void test_ms_state()
50{
51 uint32_t tlli = 0xffeeddbb;
52 gprs_rlcmac_dl_tbf *dl_tbf;
53 gprs_rlcmac_ul_tbf *ul_tbf;
54 GprsMs *ms;
55
56 printf("=== start %s ===\n", __func__);
57
Jacob Erlbeck17214bb2015-06-02 14:06:12 +020058 ms = new GprsMs(NULL, tlli);
Jacob Erlbecke04e0b02015-05-06 18:30:48 +020059 OSMO_ASSERT(ms->is_idle());
60
61 dl_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_dl_tbf);
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +020062 new (dl_tbf) gprs_rlcmac_dl_tbf(NULL);
Jacob Erlbecke04e0b02015-05-06 18:30:48 +020063 ul_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_ul_tbf);
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +020064 new (ul_tbf) gprs_rlcmac_ul_tbf(NULL);
Jacob Erlbecke04e0b02015-05-06 18:30:48 +020065
66 ms->attach_tbf(ul_tbf);
67 OSMO_ASSERT(!ms->is_idle());
68 OSMO_ASSERT(ms->ul_tbf() == ul_tbf);
69 OSMO_ASSERT(ms->dl_tbf() == NULL);
70
71 ms->attach_tbf(dl_tbf);
72 OSMO_ASSERT(!ms->is_idle());
73 OSMO_ASSERT(ms->ul_tbf() == ul_tbf);
74 OSMO_ASSERT(ms->dl_tbf() == dl_tbf);
75
Jacob Erlbeckac89a552015-06-29 14:18:46 +020076 OSMO_ASSERT(ms->tbf(GPRS_RLCMAC_UL_TBF) == ul_tbf);
77 OSMO_ASSERT(ms->tbf(GPRS_RLCMAC_DL_TBF) == dl_tbf);
78
Jacob Erlbecke04e0b02015-05-06 18:30:48 +020079 ms->detach_tbf(ul_tbf);
80 OSMO_ASSERT(!ms->is_idle());
81 OSMO_ASSERT(ms->ul_tbf() == NULL);
82 OSMO_ASSERT(ms->dl_tbf() == dl_tbf);
83
84 ms->detach_tbf(dl_tbf);
85 /* The ms object is freed now */
86 ms = NULL;
87
88 talloc_free(dl_tbf);
89 talloc_free(ul_tbf);
90
91 printf("=== end %s ===\n", __func__);
92}
93
94static void test_ms_callback()
95{
96 uint32_t tlli = 0xffeeddbb;
97 gprs_rlcmac_dl_tbf *dl_tbf;
98 gprs_rlcmac_ul_tbf *ul_tbf;
99 GprsMs *ms;
100 static enum {UNKNOWN, IS_IDLE, IS_ACTIVE} last_cb = UNKNOWN;
101
102 struct MyCallback: public GprsMs::Callback {
103 virtual void ms_idle(class GprsMs *ms) {
104 OSMO_ASSERT(ms->is_idle());
105 printf(" ms_idle() was called\n");
106 last_cb = IS_IDLE;
107 }
108 virtual void ms_active(class GprsMs *ms) {
109 OSMO_ASSERT(!ms->is_idle());
110 printf(" ms_active() was called\n");
111 last_cb = IS_ACTIVE;
112 }
113 } cb;
114
115 printf("=== start %s ===\n", __func__);
116
Jacob Erlbeck17214bb2015-06-02 14:06:12 +0200117 ms = new GprsMs(NULL, tlli);
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200118 ms->set_callback(&cb);
119
120 OSMO_ASSERT(ms->is_idle());
121
122 dl_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_dl_tbf);
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200123 new (dl_tbf) gprs_rlcmac_dl_tbf(NULL);
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200124 ul_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_ul_tbf);
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200125 new (ul_tbf) gprs_rlcmac_ul_tbf(NULL);
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200126
127 OSMO_ASSERT(last_cb == UNKNOWN);
128
129 ms->attach_tbf(ul_tbf);
130 OSMO_ASSERT(!ms->is_idle());
131 OSMO_ASSERT(ms->ul_tbf() == ul_tbf);
132 OSMO_ASSERT(ms->dl_tbf() == NULL);
133 OSMO_ASSERT(last_cb == IS_ACTIVE);
134
135 last_cb = UNKNOWN;
136
137 ms->attach_tbf(dl_tbf);
138 OSMO_ASSERT(!ms->is_idle());
139 OSMO_ASSERT(ms->ul_tbf() == ul_tbf);
140 OSMO_ASSERT(ms->dl_tbf() == dl_tbf);
141 OSMO_ASSERT(last_cb == UNKNOWN);
142
143 ms->detach_tbf(ul_tbf);
144 OSMO_ASSERT(!ms->is_idle());
145 OSMO_ASSERT(ms->ul_tbf() == NULL);
146 OSMO_ASSERT(ms->dl_tbf() == dl_tbf);
147 OSMO_ASSERT(last_cb == UNKNOWN);
148
149 ms->detach_tbf(dl_tbf);
150 OSMO_ASSERT(ms->is_idle());
151 OSMO_ASSERT(ms->ul_tbf() == NULL);
152 OSMO_ASSERT(ms->dl_tbf() == NULL);
153 OSMO_ASSERT(last_cb == IS_IDLE);
154
155 last_cb = UNKNOWN;
156 delete ms;
157
158 talloc_free(dl_tbf);
159 talloc_free(ul_tbf);
160
161 printf("=== end %s ===\n", __func__);
162}
163
164static void test_ms_replace_tbf()
165{
166 uint32_t tlli = 0xffeeddbb;
167 gprs_rlcmac_dl_tbf *dl_tbf[2];
168 gprs_rlcmac_ul_tbf *ul_tbf;
169 GprsMs *ms;
170 static bool was_idle;
171
172 struct MyCallback: public GprsMs::Callback {
173 virtual void ms_idle(class GprsMs *ms) {
174 OSMO_ASSERT(ms->is_idle());
175 printf(" ms_idle() was called\n");
176 was_idle = true;
177 }
178 virtual void ms_active(class GprsMs *ms) {
179 OSMO_ASSERT(!ms->is_idle());
180 printf(" ms_active() was called\n");
181 }
182 } cb;
183
184 printf("=== start %s ===\n", __func__);
185
Jacob Erlbeck17214bb2015-06-02 14:06:12 +0200186 ms = new GprsMs(NULL, tlli);
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200187 ms->set_callback(&cb);
188
189 OSMO_ASSERT(ms->is_idle());
190 was_idle = false;
191
192 dl_tbf[0] = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_dl_tbf);
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200193 new (dl_tbf[0]) gprs_rlcmac_dl_tbf(NULL);
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200194 dl_tbf[1] = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_dl_tbf);
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200195 new (dl_tbf[1]) gprs_rlcmac_dl_tbf(NULL);
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200196 ul_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_ul_tbf);
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200197 new (ul_tbf) gprs_rlcmac_ul_tbf(NULL);
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200198
199 ms->attach_tbf(dl_tbf[0]);
200 OSMO_ASSERT(!ms->is_idle());
201 OSMO_ASSERT(ms->ul_tbf() == NULL);
202 OSMO_ASSERT(ms->dl_tbf() == dl_tbf[0]);
Jacob Erlbeck6835cea2015-08-21 15:24:02 +0200203 OSMO_ASSERT(llist_empty(&ms->old_tbfs()));
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200204 OSMO_ASSERT(!was_idle);
205
206 ms->attach_tbf(dl_tbf[1]);
207 OSMO_ASSERT(!ms->is_idle());
208 OSMO_ASSERT(ms->ul_tbf() == NULL);
209 OSMO_ASSERT(ms->dl_tbf() == dl_tbf[1]);
Jacob Erlbeck6835cea2015-08-21 15:24:02 +0200210 OSMO_ASSERT(!llist_empty(&ms->old_tbfs()));
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200211 OSMO_ASSERT(!was_idle);
212
213 ms->attach_tbf(ul_tbf);
214 OSMO_ASSERT(!ms->is_idle());
215 OSMO_ASSERT(ms->ul_tbf() == ul_tbf);
216 OSMO_ASSERT(ms->dl_tbf() == dl_tbf[1]);
Jacob Erlbeck6835cea2015-08-21 15:24:02 +0200217 OSMO_ASSERT(!llist_empty(&ms->old_tbfs()));
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200218 OSMO_ASSERT(!was_idle);
219
220 ms->detach_tbf(ul_tbf);
221 OSMO_ASSERT(!ms->is_idle());
222 OSMO_ASSERT(ms->ul_tbf() == NULL);
223 OSMO_ASSERT(ms->dl_tbf() == dl_tbf[1]);
Jacob Erlbeck6835cea2015-08-21 15:24:02 +0200224 OSMO_ASSERT(!llist_empty(&ms->old_tbfs()));
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200225 OSMO_ASSERT(!was_idle);
226
227 ms->detach_tbf(dl_tbf[0]);
228 OSMO_ASSERT(!ms->is_idle());
229 OSMO_ASSERT(ms->ul_tbf() == NULL);
230 OSMO_ASSERT(ms->dl_tbf() == dl_tbf[1]);
Jacob Erlbeck6835cea2015-08-21 15:24:02 +0200231 OSMO_ASSERT(llist_empty(&ms->old_tbfs()));
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200232 OSMO_ASSERT(!was_idle);
233
234 ms->detach_tbf(dl_tbf[1]);
235 OSMO_ASSERT(ms->is_idle());
236 OSMO_ASSERT(ms->ul_tbf() == NULL);
237 OSMO_ASSERT(ms->dl_tbf() == NULL);
Jacob Erlbeck6835cea2015-08-21 15:24:02 +0200238 OSMO_ASSERT(llist_empty(&ms->old_tbfs()));
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200239 OSMO_ASSERT(was_idle);
240
241 delete ms;
242
243 talloc_free(dl_tbf[0]);
244 talloc_free(dl_tbf[1]);
245 talloc_free(ul_tbf);
246
247 printf("=== end %s ===\n", __func__);
248}
249
Jacob Erlbeck93990462015-05-15 15:50:43 +0200250static void test_ms_change_tlli()
251{
252 uint32_t start_tlli = 0xaa000000;
253 uint32_t new_ms_tlli = 0xff001111;
254 uint32_t other_sgsn_tlli = 0xff00eeee;
255 GprsMs *ms;
256
257 printf("=== start %s ===\n", __func__);
258
Jacob Erlbeck17214bb2015-06-02 14:06:12 +0200259 ms = new GprsMs(NULL, start_tlli);
Jacob Erlbeck93990462015-05-15 15:50:43 +0200260
261 OSMO_ASSERT(ms->is_idle());
262
263 /* MS announces TLLI, SGSN uses it immediately */
264 ms->set_tlli(new_ms_tlli);
265 OSMO_ASSERT(ms->tlli() == new_ms_tlli);
266 OSMO_ASSERT(ms->check_tlli(new_ms_tlli));
267 OSMO_ASSERT(ms->check_tlli(start_tlli));
268
269 ms->confirm_tlli(new_ms_tlli);
270 OSMO_ASSERT(ms->tlli() == new_ms_tlli);
271 OSMO_ASSERT(ms->check_tlli(new_ms_tlli));
272 OSMO_ASSERT(!ms->check_tlli(start_tlli));
273
274 /* MS announces TLLI, SGSN uses it later */
275 ms->set_tlli(start_tlli);
276 ms->confirm_tlli(start_tlli);
277
278 ms->set_tlli(new_ms_tlli);
279 OSMO_ASSERT(ms->tlli() == new_ms_tlli);
280 OSMO_ASSERT(ms->check_tlli(new_ms_tlli));
281 OSMO_ASSERT(ms->check_tlli(start_tlli));
282
283 ms->confirm_tlli(start_tlli);
284 OSMO_ASSERT(ms->tlli() == new_ms_tlli);
285 OSMO_ASSERT(ms->check_tlli(new_ms_tlli));
286 OSMO_ASSERT(ms->check_tlli(start_tlli));
287
288 ms->set_tlli(new_ms_tlli);
289 OSMO_ASSERT(ms->tlli() == new_ms_tlli);
290 OSMO_ASSERT(ms->check_tlli(new_ms_tlli));
291 OSMO_ASSERT(ms->check_tlli(start_tlli));
292
293 ms->confirm_tlli(new_ms_tlli);
294 OSMO_ASSERT(ms->tlli() == new_ms_tlli);
295 OSMO_ASSERT(ms->check_tlli(new_ms_tlli));
296 OSMO_ASSERT(!ms->check_tlli(start_tlli));
297
298 /* MS announces TLLI, SGSN uses it later after another new TLLI */
299 ms->set_tlli(start_tlli);
300 ms->confirm_tlli(start_tlli);
301
302 ms->set_tlli(new_ms_tlli);
303 OSMO_ASSERT(ms->tlli() == new_ms_tlli);
304 OSMO_ASSERT(ms->check_tlli(new_ms_tlli));
305 OSMO_ASSERT(ms->check_tlli(start_tlli));
306
307 ms->confirm_tlli(other_sgsn_tlli);
308 OSMO_ASSERT(ms->tlli() == new_ms_tlli);
309 OSMO_ASSERT(ms->check_tlli(new_ms_tlli));
310 OSMO_ASSERT(ms->check_tlli(other_sgsn_tlli));
311
312 ms->set_tlli(new_ms_tlli);
313 OSMO_ASSERT(ms->tlli() == new_ms_tlli);
314 OSMO_ASSERT(ms->check_tlli(new_ms_tlli));
315 OSMO_ASSERT(ms->check_tlli(other_sgsn_tlli));
316
317 ms->confirm_tlli(new_ms_tlli);
318 OSMO_ASSERT(ms->tlli() == new_ms_tlli);
319 OSMO_ASSERT(ms->check_tlli(new_ms_tlli));
320 OSMO_ASSERT(!ms->check_tlli(start_tlli));
321 OSMO_ASSERT(!ms->check_tlli(other_sgsn_tlli));
322
323 /* SGSN uses the new TLLI before it is announced by the MS (shouldn't
324 * happen in normal use) */
325 ms->set_tlli(start_tlli);
326 ms->confirm_tlli(start_tlli);
327
328 ms->confirm_tlli(new_ms_tlli);
329 OSMO_ASSERT(ms->tlli() == start_tlli);
330 OSMO_ASSERT(ms->check_tlli(new_ms_tlli));
331 OSMO_ASSERT(ms->check_tlli(start_tlli));
332
333 ms->set_tlli(new_ms_tlli);
334 OSMO_ASSERT(ms->tlli() == new_ms_tlli);
335 OSMO_ASSERT(ms->check_tlli(new_ms_tlli));
336 OSMO_ASSERT(!ms->check_tlli(start_tlli));
337
338 delete ms;
339
340 printf("=== end %s ===\n", __func__);
341}
342
Maxf4d39732019-03-12 12:53:27 +0100343static GprsMs *prepare_ms(GprsMsStorage *st, uint32_t tlli, enum gprs_rlcmac_tbf_direction dir)
344{
345 GprsMs *ms = st->get_ms(tlli);
346 if (ms)
347 return ms;
348
349 ms = st->create_ms();
350
351 if (dir == GPRS_RLCMAC_UL_TBF)
352 ms->set_tlli(tlli);
353 else
354 ms->confirm_tlli(tlli);
355
356 return ms;
357}
358
Jacob Erlbeck53670862015-05-12 17:54:33 +0200359static void test_ms_storage()
360{
361 uint32_t tlli = 0xffeeddbb;
Jacob Erlbeck7b9f8252015-05-21 11:07:53 +0200362 const char *imsi1 = "001001987654321";
363 const char *imsi2 = "001001987654322";
364
Jacob Erlbeck53670862015-05-12 17:54:33 +0200365 gprs_rlcmac_ul_tbf *ul_tbf;
Jacob Erlbeck0e50ce62015-05-21 16:58:22 +0200366 GprsMs *ms, *ms_tmp;
Jacob Erlbeck17214bb2015-06-02 14:06:12 +0200367 GprsMsStorage store(NULL);
Jacob Erlbeck53670862015-05-12 17:54:33 +0200368
369 printf("=== start %s ===\n", __func__);
370
371 ul_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_ul_tbf);
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200372 new (ul_tbf) gprs_rlcmac_ul_tbf(NULL);
Jacob Erlbeck53670862015-05-12 17:54:33 +0200373
374 ms = store.get_ms(tlli + 0);
375 OSMO_ASSERT(ms == NULL);
376
Maxf4d39732019-03-12 12:53:27 +0100377 ms = prepare_ms(&store, tlli + 0, GPRS_RLCMAC_UL_TBF);
Jacob Erlbeck53670862015-05-12 17:54:33 +0200378 OSMO_ASSERT(ms != NULL);
379 OSMO_ASSERT(ms->tlli() == tlli + 0);
Jacob Erlbeck7b9f8252015-05-21 11:07:53 +0200380 ms->set_imsi(imsi1);
381 OSMO_ASSERT(strcmp(ms->imsi(), imsi1) == 0);
Jacob Erlbeck53670862015-05-12 17:54:33 +0200382
Jacob Erlbeck0e50ce62015-05-21 16:58:22 +0200383 ms_tmp = store.get_ms(tlli + 0);
384 OSMO_ASSERT(ms == ms_tmp);
385 OSMO_ASSERT(ms->tlli() == tlli + 0);
386
Jacob Erlbeck7b9f8252015-05-21 11:07:53 +0200387 ms_tmp = store.get_ms(0, 0, imsi1);
388 OSMO_ASSERT(ms == ms_tmp);
389 OSMO_ASSERT(strcmp(ms->imsi(), imsi1) == 0);
390 ms_tmp = store.get_ms(0, 0, imsi2);
391 OSMO_ASSERT(ms_tmp == NULL);
392
Maxf4d39732019-03-12 12:53:27 +0100393 ms = prepare_ms(&store, tlli + 1, GPRS_RLCMAC_UL_TBF);
Jacob Erlbeck0e50ce62015-05-21 16:58:22 +0200394 OSMO_ASSERT(ms != NULL);
Jacob Erlbeck53670862015-05-12 17:54:33 +0200395 OSMO_ASSERT(ms->tlli() == tlli + 1);
Jacob Erlbeck7b9f8252015-05-21 11:07:53 +0200396 ms->set_imsi(imsi2);
397 OSMO_ASSERT(strcmp(ms->imsi(), imsi2) == 0);
Jacob Erlbeck53670862015-05-12 17:54:33 +0200398
Jacob Erlbeck0e50ce62015-05-21 16:58:22 +0200399 ms_tmp = store.get_ms(tlli + 1);
400 OSMO_ASSERT(ms == ms_tmp);
Jacob Erlbeck53670862015-05-12 17:54:33 +0200401 OSMO_ASSERT(ms->tlli() == tlli + 1);
402
Jacob Erlbeck7b9f8252015-05-21 11:07:53 +0200403 ms_tmp = store.get_ms(0, 0, imsi1);
404 OSMO_ASSERT(ms_tmp != NULL);
405 OSMO_ASSERT(ms_tmp != ms);
406 ms_tmp = store.get_ms(0, 0, imsi2);
407 OSMO_ASSERT(ms == ms_tmp);
408 OSMO_ASSERT(strcmp(ms->imsi(), imsi2) == 0);
409
Jacob Erlbeck53670862015-05-12 17:54:33 +0200410 /* delete ms */
411 ms = store.get_ms(tlli + 0);
412 OSMO_ASSERT(ms != NULL);
413 ms->attach_tbf(ul_tbf);
414 ms->detach_tbf(ul_tbf);
415 ms = store.get_ms(tlli + 0);
416 OSMO_ASSERT(ms == NULL);
417 ms = store.get_ms(tlli + 1);
418 OSMO_ASSERT(ms != NULL);
419
420 /* delete ms */
421 ms = store.get_ms(tlli + 1);
422 OSMO_ASSERT(ms != NULL);
423 ms->attach_tbf(ul_tbf);
424 ms->detach_tbf(ul_tbf);
425 ms = store.get_ms(tlli + 1);
426 OSMO_ASSERT(ms == NULL);
427
428 talloc_free(ul_tbf);
429
430 printf("=== end %s ===\n", __func__);
431}
432
Jacob Erlbeckd9e10242015-05-28 15:43:53 +0200433static void test_ms_timeout()
434{
435 uint32_t tlli = 0xffeeddbb;
436 gprs_rlcmac_dl_tbf *dl_tbf;
437 gprs_rlcmac_ul_tbf *ul_tbf;
438 GprsMs *ms;
439 static enum {UNKNOWN, IS_IDLE, IS_ACTIVE} last_cb = UNKNOWN;
440
441 struct MyCallback: public GprsMs::Callback {
442 virtual void ms_idle(class GprsMs *ms) {
443 OSMO_ASSERT(ms->is_idle());
444 printf(" ms_idle() was called\n");
445 last_cb = IS_IDLE;
446 }
447 virtual void ms_active(class GprsMs *ms) {
448 OSMO_ASSERT(!ms->is_idle());
449 printf(" ms_active() was called\n");
450 last_cb = IS_ACTIVE;
451 }
452 } cb;
453
454 printf("=== start %s ===\n", __func__);
455
Jacob Erlbeck17214bb2015-06-02 14:06:12 +0200456 ms = new GprsMs(NULL, tlli);
Jacob Erlbeckd9e10242015-05-28 15:43:53 +0200457 ms->set_callback(&cb);
458 ms->set_timeout(1);
459
460 OSMO_ASSERT(ms->is_idle());
461
462 dl_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_dl_tbf);
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200463 new (dl_tbf) gprs_rlcmac_dl_tbf(NULL);
Jacob Erlbeckd9e10242015-05-28 15:43:53 +0200464 ul_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_ul_tbf);
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200465 new (ul_tbf) gprs_rlcmac_ul_tbf(NULL);
Jacob Erlbeckd9e10242015-05-28 15:43:53 +0200466
467 OSMO_ASSERT(last_cb == UNKNOWN);
468
469 ms->attach_tbf(ul_tbf);
470 OSMO_ASSERT(!ms->is_idle());
471 OSMO_ASSERT(last_cb == IS_ACTIVE);
472
473 last_cb = UNKNOWN;
474
475 ms->attach_tbf(dl_tbf);
476 OSMO_ASSERT(!ms->is_idle());
477 OSMO_ASSERT(last_cb == UNKNOWN);
478
479 ms->detach_tbf(ul_tbf);
480 OSMO_ASSERT(!ms->is_idle());
481 OSMO_ASSERT(last_cb == UNKNOWN);
482
483 ms->detach_tbf(dl_tbf);
484 OSMO_ASSERT(!ms->is_idle());
485 OSMO_ASSERT(last_cb == UNKNOWN);
486
487 usleep(1100000);
488 osmo_timers_update();
489
490 OSMO_ASSERT(ms->is_idle());
491 OSMO_ASSERT(last_cb == IS_IDLE);
492
493 last_cb = UNKNOWN;
494 delete ms;
495 talloc_free(dl_tbf);
496 talloc_free(ul_tbf);
497
498 printf("=== end %s ===\n", __func__);
499}
500
Jacob Erlbeck70b96aa2015-06-12 10:52:34 +0200501static void test_ms_cs_selection()
502{
503 BTS the_bts;
504 gprs_rlcmac_bts *bts = the_bts.bts_data();
505 uint32_t tlli = 0xffeeddbb;
506
507 gprs_rlcmac_dl_tbf *dl_tbf;
508 GprsMs *ms;
509
510 printf("=== start %s ===\n", __func__);
511
512 bts->initial_cs_dl = 4;
513 bts->initial_cs_ul = 1;
514 bts->cs_downgrade_threshold = 0;
515
516 ms = new GprsMs(&the_bts, tlli);
517
518 OSMO_ASSERT(ms->is_idle());
519
520 dl_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_dl_tbf);
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200521 new (dl_tbf) gprs_rlcmac_dl_tbf(NULL);
Jacob Erlbeck70b96aa2015-06-12 10:52:34 +0200522
523 dl_tbf->set_ms(ms);
524 OSMO_ASSERT(!ms->is_idle());
525
Max898dddb2019-03-12 15:50:57 +0100526 OSMO_ASSERT(mcs_chan_code(ms->current_cs_dl()) == 3);
Jacob Erlbeck70b96aa2015-06-12 10:52:34 +0200527
528 bts->cs_downgrade_threshold = 200;
529
Max898dddb2019-03-12 15:50:57 +0100530 OSMO_ASSERT(mcs_chan_code(ms->current_cs_dl()) == 2);
Jacob Erlbeck70b96aa2015-06-12 10:52:34 +0200531
532 talloc_free(dl_tbf);
533
534 printf("=== end %s ===\n", __func__);
535}
536
Max41d6b352019-03-06 15:59:09 +0100537static void dump_ms(const GprsMs *ms, const char *pref)
538{
539 printf("%s MS DL %s/%s, UL %s/%s, mode %s, <%s>\n", pref,
540 mcs_name(ms->current_cs_dl()), mcs_name(ms->max_cs_dl()),
541 mcs_name(ms->current_cs_ul()), mcs_name(ms->max_cs_ul()),
542 mode_name(ms->mode()),
543 ms->is_idle() ? "IDLE" : "ACTIVE");
544}
545
546static void test_ms_mcs_mode()
547{
548 BTS the_bts;
549 gprs_rlcmac_bts *bts = the_bts.bts_data();
550 uint32_t tlli = 0xdeadbeef;
551
552 gprs_rlcmac_dl_tbf *dl_tbf;
553 GprsMs *ms1, *ms2;
554
555 printf("=== start %s ===\n", __func__);
556
557 ms1 = new GprsMs(&the_bts, tlli);
558 dump_ms(ms1, "1: no BTS defaults ");
559
560 bts->initial_cs_dl = 4;
561 bts->initial_cs_ul = 1;
562 bts->cs_downgrade_threshold = 0;
563
564 ms2 = new GprsMs(&the_bts, tlli + 1);
565 dump_ms(ms2, "2: with BTS defaults");
566
567 dl_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_dl_tbf);
568 new (dl_tbf) gprs_rlcmac_dl_tbf(NULL);
569
570 dl_tbf->set_ms(ms2);
571 dump_ms(ms2, "2: after TBF attach ");
572
573 ms1->set_mode(EGPRS);
574 dump_ms(ms1, "1: after mode set ");
575
576 ms2->set_mode(EGPRS);
577 dump_ms(ms2, "2: after mode set ");
578
579 ms1->set_current_cs_dl(MCS7);
580 dump_ms(ms1, "1: after MCS set ");
581
582 ms2->set_current_cs_dl(MCS8);
583 dump_ms(ms2, "2: after MCS set ");
584
585 ms1->set_mode(EGPRS_GMSK);
586 dump_ms(ms1, "1: after mode set ");
587
588 ms2->set_mode(EGPRS_GMSK);
589 dump_ms(ms2, "2: after mode set ");
590
591 // FIXME: following code triggers ASAN failure:
592 // ms2->detach_tbf(dl_tbf);
593 // dump_ms(ms2, "2: after TBF detach ");
594
595 ms1->set_mode(GPRS);
596 dump_ms(ms1, "1: after mode set ");
597
598 ms2->set_mode(GPRS);
599 dump_ms(ms2, "2: after mode set ");
600
601 talloc_free(dl_tbf);
602
603 printf("=== end %s ===\n", __func__);
604}
605
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200606int main(int argc, char **argv)
607{
608 struct vty_app_info pcu_vty_info = {0};
609
610 tall_pcu_ctx = talloc_named_const(NULL, 1, "MsTest context");
611 if (!tall_pcu_ctx)
612 abort();
613
Neels Hofmeyr78ce5912017-02-08 17:07:31 +0100614 msgb_talloc_ctx_init(tall_pcu_ctx, 0);
Neels Hofmeyr42f2d612018-04-01 16:54:40 +0200615 osmo_init_logging2(tall_pcu_ctx, &gprs_log_info);
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200616 log_set_use_color(osmo_stderr_target, 0);
617 log_set_print_filename(osmo_stderr_target, 0);
618 log_set_log_level(osmo_stderr_target, LOGL_INFO);
Harald Welteac0490a2017-10-29 10:39:32 +0100619 log_parse_category_mask(osmo_stderr_target, "DPCU,3:DRLCMAC,3");
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200620
621 vty_init(&pcu_vty_info);
Pau Espin Pedrolcd2ac562019-08-05 14:30:44 +0200622 pcu_vty_init();
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200623
624 test_ms_state();
625 test_ms_callback();
626 test_ms_replace_tbf();
Jacob Erlbeck93990462015-05-15 15:50:43 +0200627 test_ms_change_tlli();
Jacob Erlbeck53670862015-05-12 17:54:33 +0200628 test_ms_storage();
Jacob Erlbeckd9e10242015-05-28 15:43:53 +0200629 test_ms_timeout();
Jacob Erlbeck70b96aa2015-06-12 10:52:34 +0200630 test_ms_cs_selection();
Max41d6b352019-03-06 15:59:09 +0100631 test_ms_mcs_mode();
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200632
633 if (getenv("TALLOC_REPORT_FULL"))
634 talloc_report_full(tall_pcu_ctx, stderr);
635
636 return EXIT_SUCCESS;
637}
638
639extern "C" {
640void l1if_pdch_req() { abort(); }
641void l1if_connect_pdch() { abort(); }
642void l1if_close_pdch() { abort(); }
643void l1if_open_pdch() { abort(); }
644}