blob: 4f8f3a0017f4971180cf3ece5054986dfa12f2ec [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"
24#include "gprs_debug.h"
25#include "gprs_ms.h"
Jacob Erlbeck53670862015-05-12 17:54:33 +020026#include "gprs_ms_storage.h"
Jacob Erlbeck70b96aa2015-06-12 10:52:34 +020027#include "bts.h"
Jacob Erlbecke04e0b02015-05-06 18:30:48 +020028
29extern "C" {
30#include "pcu_vty.h"
31
32#include <osmocom/core/application.h>
33#include <osmocom/core/msgb.h>
34#include <osmocom/core/talloc.h>
35#include <osmocom/core/utils.h>
36#include <osmocom/vty/vty.h>
37}
38
39#include <errno.h>
Jacob Erlbeckd9e10242015-05-28 15:43:53 +020040#include <unistd.h>
Jacob Erlbecke04e0b02015-05-06 18:30:48 +020041
42void *tall_pcu_ctx;
43int16_t spoof_mnc = 0, spoof_mcc = 0;
Neels Hofmeyrbdc55fa2018-02-21 00:39:07 +010044bool spoof_mnc_3_digits = false;
Jacob Erlbecke04e0b02015-05-06 18:30:48 +020045
46static void test_ms_state()
47{
48 uint32_t tlli = 0xffeeddbb;
49 gprs_rlcmac_dl_tbf *dl_tbf;
50 gprs_rlcmac_ul_tbf *ul_tbf;
51 GprsMs *ms;
52
53 printf("=== start %s ===\n", __func__);
54
Jacob Erlbeck17214bb2015-06-02 14:06:12 +020055 ms = new GprsMs(NULL, tlli);
Jacob Erlbecke04e0b02015-05-06 18:30:48 +020056 OSMO_ASSERT(ms->is_idle());
57
58 dl_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_dl_tbf);
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +020059 new (dl_tbf) gprs_rlcmac_dl_tbf(NULL);
Jacob Erlbecke04e0b02015-05-06 18:30:48 +020060 ul_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_ul_tbf);
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +020061 new (ul_tbf) gprs_rlcmac_ul_tbf(NULL);
Jacob Erlbecke04e0b02015-05-06 18:30:48 +020062
63 ms->attach_tbf(ul_tbf);
64 OSMO_ASSERT(!ms->is_idle());
65 OSMO_ASSERT(ms->ul_tbf() == ul_tbf);
66 OSMO_ASSERT(ms->dl_tbf() == NULL);
67
68 ms->attach_tbf(dl_tbf);
69 OSMO_ASSERT(!ms->is_idle());
70 OSMO_ASSERT(ms->ul_tbf() == ul_tbf);
71 OSMO_ASSERT(ms->dl_tbf() == dl_tbf);
72
Jacob Erlbeckac89a552015-06-29 14:18:46 +020073 OSMO_ASSERT(ms->tbf(GPRS_RLCMAC_UL_TBF) == ul_tbf);
74 OSMO_ASSERT(ms->tbf(GPRS_RLCMAC_DL_TBF) == dl_tbf);
75
Jacob Erlbecke04e0b02015-05-06 18:30:48 +020076 ms->detach_tbf(ul_tbf);
77 OSMO_ASSERT(!ms->is_idle());
78 OSMO_ASSERT(ms->ul_tbf() == NULL);
79 OSMO_ASSERT(ms->dl_tbf() == dl_tbf);
80
81 ms->detach_tbf(dl_tbf);
82 /* The ms object is freed now */
83 ms = NULL;
84
85 talloc_free(dl_tbf);
86 talloc_free(ul_tbf);
87
88 printf("=== end %s ===\n", __func__);
89}
90
91static void test_ms_callback()
92{
93 uint32_t tlli = 0xffeeddbb;
94 gprs_rlcmac_dl_tbf *dl_tbf;
95 gprs_rlcmac_ul_tbf *ul_tbf;
96 GprsMs *ms;
97 static enum {UNKNOWN, IS_IDLE, IS_ACTIVE} last_cb = UNKNOWN;
98
99 struct MyCallback: public GprsMs::Callback {
100 virtual void ms_idle(class GprsMs *ms) {
101 OSMO_ASSERT(ms->is_idle());
102 printf(" ms_idle() was called\n");
103 last_cb = IS_IDLE;
104 }
105 virtual void ms_active(class GprsMs *ms) {
106 OSMO_ASSERT(!ms->is_idle());
107 printf(" ms_active() was called\n");
108 last_cb = IS_ACTIVE;
109 }
110 } cb;
111
112 printf("=== start %s ===\n", __func__);
113
Jacob Erlbeck17214bb2015-06-02 14:06:12 +0200114 ms = new GprsMs(NULL, tlli);
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200115 ms->set_callback(&cb);
116
117 OSMO_ASSERT(ms->is_idle());
118
119 dl_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_dl_tbf);
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200120 new (dl_tbf) gprs_rlcmac_dl_tbf(NULL);
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200121 ul_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_ul_tbf);
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200122 new (ul_tbf) gprs_rlcmac_ul_tbf(NULL);
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200123
124 OSMO_ASSERT(last_cb == UNKNOWN);
125
126 ms->attach_tbf(ul_tbf);
127 OSMO_ASSERT(!ms->is_idle());
128 OSMO_ASSERT(ms->ul_tbf() == ul_tbf);
129 OSMO_ASSERT(ms->dl_tbf() == NULL);
130 OSMO_ASSERT(last_cb == IS_ACTIVE);
131
132 last_cb = UNKNOWN;
133
134 ms->attach_tbf(dl_tbf);
135 OSMO_ASSERT(!ms->is_idle());
136 OSMO_ASSERT(ms->ul_tbf() == ul_tbf);
137 OSMO_ASSERT(ms->dl_tbf() == dl_tbf);
138 OSMO_ASSERT(last_cb == UNKNOWN);
139
140 ms->detach_tbf(ul_tbf);
141 OSMO_ASSERT(!ms->is_idle());
142 OSMO_ASSERT(ms->ul_tbf() == NULL);
143 OSMO_ASSERT(ms->dl_tbf() == dl_tbf);
144 OSMO_ASSERT(last_cb == UNKNOWN);
145
146 ms->detach_tbf(dl_tbf);
147 OSMO_ASSERT(ms->is_idle());
148 OSMO_ASSERT(ms->ul_tbf() == NULL);
149 OSMO_ASSERT(ms->dl_tbf() == NULL);
150 OSMO_ASSERT(last_cb == IS_IDLE);
151
152 last_cb = UNKNOWN;
153 delete ms;
154
155 talloc_free(dl_tbf);
156 talloc_free(ul_tbf);
157
158 printf("=== end %s ===\n", __func__);
159}
160
161static void test_ms_replace_tbf()
162{
163 uint32_t tlli = 0xffeeddbb;
164 gprs_rlcmac_dl_tbf *dl_tbf[2];
165 gprs_rlcmac_ul_tbf *ul_tbf;
166 GprsMs *ms;
167 static bool was_idle;
168
169 struct MyCallback: public GprsMs::Callback {
170 virtual void ms_idle(class GprsMs *ms) {
171 OSMO_ASSERT(ms->is_idle());
172 printf(" ms_idle() was called\n");
173 was_idle = true;
174 }
175 virtual void ms_active(class GprsMs *ms) {
176 OSMO_ASSERT(!ms->is_idle());
177 printf(" ms_active() was called\n");
178 }
179 } cb;
180
181 printf("=== start %s ===\n", __func__);
182
Jacob Erlbeck17214bb2015-06-02 14:06:12 +0200183 ms = new GprsMs(NULL, tlli);
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200184 ms->set_callback(&cb);
185
186 OSMO_ASSERT(ms->is_idle());
187 was_idle = false;
188
189 dl_tbf[0] = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_dl_tbf);
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200190 new (dl_tbf[0]) gprs_rlcmac_dl_tbf(NULL);
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200191 dl_tbf[1] = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_dl_tbf);
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200192 new (dl_tbf[1]) gprs_rlcmac_dl_tbf(NULL);
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200193 ul_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_ul_tbf);
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200194 new (ul_tbf) gprs_rlcmac_ul_tbf(NULL);
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200195
196 ms->attach_tbf(dl_tbf[0]);
197 OSMO_ASSERT(!ms->is_idle());
198 OSMO_ASSERT(ms->ul_tbf() == NULL);
199 OSMO_ASSERT(ms->dl_tbf() == dl_tbf[0]);
Jacob Erlbeck6835cea2015-08-21 15:24:02 +0200200 OSMO_ASSERT(llist_empty(&ms->old_tbfs()));
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200201 OSMO_ASSERT(!was_idle);
202
203 ms->attach_tbf(dl_tbf[1]);
204 OSMO_ASSERT(!ms->is_idle());
205 OSMO_ASSERT(ms->ul_tbf() == NULL);
206 OSMO_ASSERT(ms->dl_tbf() == dl_tbf[1]);
Jacob Erlbeck6835cea2015-08-21 15:24:02 +0200207 OSMO_ASSERT(!llist_empty(&ms->old_tbfs()));
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200208 OSMO_ASSERT(!was_idle);
209
210 ms->attach_tbf(ul_tbf);
211 OSMO_ASSERT(!ms->is_idle());
212 OSMO_ASSERT(ms->ul_tbf() == ul_tbf);
213 OSMO_ASSERT(ms->dl_tbf() == dl_tbf[1]);
Jacob Erlbeck6835cea2015-08-21 15:24:02 +0200214 OSMO_ASSERT(!llist_empty(&ms->old_tbfs()));
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200215 OSMO_ASSERT(!was_idle);
216
217 ms->detach_tbf(ul_tbf);
218 OSMO_ASSERT(!ms->is_idle());
219 OSMO_ASSERT(ms->ul_tbf() == NULL);
220 OSMO_ASSERT(ms->dl_tbf() == dl_tbf[1]);
Jacob Erlbeck6835cea2015-08-21 15:24:02 +0200221 OSMO_ASSERT(!llist_empty(&ms->old_tbfs()));
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200222 OSMO_ASSERT(!was_idle);
223
224 ms->detach_tbf(dl_tbf[0]);
225 OSMO_ASSERT(!ms->is_idle());
226 OSMO_ASSERT(ms->ul_tbf() == NULL);
227 OSMO_ASSERT(ms->dl_tbf() == dl_tbf[1]);
Jacob Erlbeck6835cea2015-08-21 15:24:02 +0200228 OSMO_ASSERT(llist_empty(&ms->old_tbfs()));
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200229 OSMO_ASSERT(!was_idle);
230
231 ms->detach_tbf(dl_tbf[1]);
232 OSMO_ASSERT(ms->is_idle());
233 OSMO_ASSERT(ms->ul_tbf() == NULL);
234 OSMO_ASSERT(ms->dl_tbf() == NULL);
Jacob Erlbeck6835cea2015-08-21 15:24:02 +0200235 OSMO_ASSERT(llist_empty(&ms->old_tbfs()));
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200236 OSMO_ASSERT(was_idle);
237
238 delete ms;
239
240 talloc_free(dl_tbf[0]);
241 talloc_free(dl_tbf[1]);
242 talloc_free(ul_tbf);
243
244 printf("=== end %s ===\n", __func__);
245}
246
Jacob Erlbeck93990462015-05-15 15:50:43 +0200247static void test_ms_change_tlli()
248{
249 uint32_t start_tlli = 0xaa000000;
250 uint32_t new_ms_tlli = 0xff001111;
251 uint32_t other_sgsn_tlli = 0xff00eeee;
252 GprsMs *ms;
253
254 printf("=== start %s ===\n", __func__);
255
Jacob Erlbeck17214bb2015-06-02 14:06:12 +0200256 ms = new GprsMs(NULL, start_tlli);
Jacob Erlbeck93990462015-05-15 15:50:43 +0200257
258 OSMO_ASSERT(ms->is_idle());
259
260 /* MS announces TLLI, SGSN uses it immediately */
261 ms->set_tlli(new_ms_tlli);
262 OSMO_ASSERT(ms->tlli() == new_ms_tlli);
263 OSMO_ASSERT(ms->check_tlli(new_ms_tlli));
264 OSMO_ASSERT(ms->check_tlli(start_tlli));
265
266 ms->confirm_tlli(new_ms_tlli);
267 OSMO_ASSERT(ms->tlli() == new_ms_tlli);
268 OSMO_ASSERT(ms->check_tlli(new_ms_tlli));
269 OSMO_ASSERT(!ms->check_tlli(start_tlli));
270
271 /* MS announces TLLI, SGSN uses it later */
272 ms->set_tlli(start_tlli);
273 ms->confirm_tlli(start_tlli);
274
275 ms->set_tlli(new_ms_tlli);
276 OSMO_ASSERT(ms->tlli() == new_ms_tlli);
277 OSMO_ASSERT(ms->check_tlli(new_ms_tlli));
278 OSMO_ASSERT(ms->check_tlli(start_tlli));
279
280 ms->confirm_tlli(start_tlli);
281 OSMO_ASSERT(ms->tlli() == new_ms_tlli);
282 OSMO_ASSERT(ms->check_tlli(new_ms_tlli));
283 OSMO_ASSERT(ms->check_tlli(start_tlli));
284
285 ms->set_tlli(new_ms_tlli);
286 OSMO_ASSERT(ms->tlli() == new_ms_tlli);
287 OSMO_ASSERT(ms->check_tlli(new_ms_tlli));
288 OSMO_ASSERT(ms->check_tlli(start_tlli));
289
290 ms->confirm_tlli(new_ms_tlli);
291 OSMO_ASSERT(ms->tlli() == new_ms_tlli);
292 OSMO_ASSERT(ms->check_tlli(new_ms_tlli));
293 OSMO_ASSERT(!ms->check_tlli(start_tlli));
294
295 /* MS announces TLLI, SGSN uses it later after another new TLLI */
296 ms->set_tlli(start_tlli);
297 ms->confirm_tlli(start_tlli);
298
299 ms->set_tlli(new_ms_tlli);
300 OSMO_ASSERT(ms->tlli() == new_ms_tlli);
301 OSMO_ASSERT(ms->check_tlli(new_ms_tlli));
302 OSMO_ASSERT(ms->check_tlli(start_tlli));
303
304 ms->confirm_tlli(other_sgsn_tlli);
305 OSMO_ASSERT(ms->tlli() == new_ms_tlli);
306 OSMO_ASSERT(ms->check_tlli(new_ms_tlli));
307 OSMO_ASSERT(ms->check_tlli(other_sgsn_tlli));
308
309 ms->set_tlli(new_ms_tlli);
310 OSMO_ASSERT(ms->tlli() == new_ms_tlli);
311 OSMO_ASSERT(ms->check_tlli(new_ms_tlli));
312 OSMO_ASSERT(ms->check_tlli(other_sgsn_tlli));
313
314 ms->confirm_tlli(new_ms_tlli);
315 OSMO_ASSERT(ms->tlli() == new_ms_tlli);
316 OSMO_ASSERT(ms->check_tlli(new_ms_tlli));
317 OSMO_ASSERT(!ms->check_tlli(start_tlli));
318 OSMO_ASSERT(!ms->check_tlli(other_sgsn_tlli));
319
320 /* SGSN uses the new TLLI before it is announced by the MS (shouldn't
321 * happen in normal use) */
322 ms->set_tlli(start_tlli);
323 ms->confirm_tlli(start_tlli);
324
325 ms->confirm_tlli(new_ms_tlli);
326 OSMO_ASSERT(ms->tlli() == start_tlli);
327 OSMO_ASSERT(ms->check_tlli(new_ms_tlli));
328 OSMO_ASSERT(ms->check_tlli(start_tlli));
329
330 ms->set_tlli(new_ms_tlli);
331 OSMO_ASSERT(ms->tlli() == new_ms_tlli);
332 OSMO_ASSERT(ms->check_tlli(new_ms_tlli));
333 OSMO_ASSERT(!ms->check_tlli(start_tlli));
334
335 delete ms;
336
337 printf("=== end %s ===\n", __func__);
338}
339
Maxf4d39732019-03-12 12:53:27 +0100340static GprsMs *prepare_ms(GprsMsStorage *st, uint32_t tlli, enum gprs_rlcmac_tbf_direction dir)
341{
342 GprsMs *ms = st->get_ms(tlli);
343 if (ms)
344 return ms;
345
346 ms = st->create_ms();
347
348 if (dir == GPRS_RLCMAC_UL_TBF)
349 ms->set_tlli(tlli);
350 else
351 ms->confirm_tlli(tlli);
352
353 return ms;
354}
355
Jacob Erlbeck53670862015-05-12 17:54:33 +0200356static void test_ms_storage()
357{
358 uint32_t tlli = 0xffeeddbb;
Jacob Erlbeck7b9f8252015-05-21 11:07:53 +0200359 const char *imsi1 = "001001987654321";
360 const char *imsi2 = "001001987654322";
361
Jacob Erlbeck53670862015-05-12 17:54:33 +0200362 gprs_rlcmac_ul_tbf *ul_tbf;
Jacob Erlbeck0e50ce62015-05-21 16:58:22 +0200363 GprsMs *ms, *ms_tmp;
Jacob Erlbeck17214bb2015-06-02 14:06:12 +0200364 GprsMsStorage store(NULL);
Jacob Erlbeck53670862015-05-12 17:54:33 +0200365
366 printf("=== start %s ===\n", __func__);
367
368 ul_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_ul_tbf);
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200369 new (ul_tbf) gprs_rlcmac_ul_tbf(NULL);
Jacob Erlbeck53670862015-05-12 17:54:33 +0200370
371 ms = store.get_ms(tlli + 0);
372 OSMO_ASSERT(ms == NULL);
373
Maxf4d39732019-03-12 12:53:27 +0100374 ms = prepare_ms(&store, tlli + 0, GPRS_RLCMAC_UL_TBF);
Jacob Erlbeck53670862015-05-12 17:54:33 +0200375 OSMO_ASSERT(ms != NULL);
376 OSMO_ASSERT(ms->tlli() == tlli + 0);
Jacob Erlbeck7b9f8252015-05-21 11:07:53 +0200377 ms->set_imsi(imsi1);
378 OSMO_ASSERT(strcmp(ms->imsi(), imsi1) == 0);
Jacob Erlbeck53670862015-05-12 17:54:33 +0200379
Jacob Erlbeck0e50ce62015-05-21 16:58:22 +0200380 ms_tmp = store.get_ms(tlli + 0);
381 OSMO_ASSERT(ms == ms_tmp);
382 OSMO_ASSERT(ms->tlli() == tlli + 0);
383
Jacob Erlbeck7b9f8252015-05-21 11:07:53 +0200384 ms_tmp = store.get_ms(0, 0, imsi1);
385 OSMO_ASSERT(ms == ms_tmp);
386 OSMO_ASSERT(strcmp(ms->imsi(), imsi1) == 0);
387 ms_tmp = store.get_ms(0, 0, imsi2);
388 OSMO_ASSERT(ms_tmp == NULL);
389
Maxf4d39732019-03-12 12:53:27 +0100390 ms = prepare_ms(&store, tlli + 1, GPRS_RLCMAC_UL_TBF);
Jacob Erlbeck0e50ce62015-05-21 16:58:22 +0200391 OSMO_ASSERT(ms != NULL);
Jacob Erlbeck53670862015-05-12 17:54:33 +0200392 OSMO_ASSERT(ms->tlli() == tlli + 1);
Jacob Erlbeck7b9f8252015-05-21 11:07:53 +0200393 ms->set_imsi(imsi2);
394 OSMO_ASSERT(strcmp(ms->imsi(), imsi2) == 0);
Jacob Erlbeck53670862015-05-12 17:54:33 +0200395
Jacob Erlbeck0e50ce62015-05-21 16:58:22 +0200396 ms_tmp = store.get_ms(tlli + 1);
397 OSMO_ASSERT(ms == ms_tmp);
Jacob Erlbeck53670862015-05-12 17:54:33 +0200398 OSMO_ASSERT(ms->tlli() == tlli + 1);
399
Jacob Erlbeck7b9f8252015-05-21 11:07:53 +0200400 ms_tmp = store.get_ms(0, 0, imsi1);
401 OSMO_ASSERT(ms_tmp != NULL);
402 OSMO_ASSERT(ms_tmp != ms);
403 ms_tmp = store.get_ms(0, 0, imsi2);
404 OSMO_ASSERT(ms == ms_tmp);
405 OSMO_ASSERT(strcmp(ms->imsi(), imsi2) == 0);
406
Jacob Erlbeck53670862015-05-12 17:54:33 +0200407 /* delete ms */
408 ms = store.get_ms(tlli + 0);
409 OSMO_ASSERT(ms != NULL);
410 ms->attach_tbf(ul_tbf);
411 ms->detach_tbf(ul_tbf);
412 ms = store.get_ms(tlli + 0);
413 OSMO_ASSERT(ms == NULL);
414 ms = store.get_ms(tlli + 1);
415 OSMO_ASSERT(ms != NULL);
416
417 /* delete ms */
418 ms = store.get_ms(tlli + 1);
419 OSMO_ASSERT(ms != NULL);
420 ms->attach_tbf(ul_tbf);
421 ms->detach_tbf(ul_tbf);
422 ms = store.get_ms(tlli + 1);
423 OSMO_ASSERT(ms == NULL);
424
425 talloc_free(ul_tbf);
426
427 printf("=== end %s ===\n", __func__);
428}
429
Jacob Erlbeckd9e10242015-05-28 15:43:53 +0200430static void test_ms_timeout()
431{
432 uint32_t tlli = 0xffeeddbb;
433 gprs_rlcmac_dl_tbf *dl_tbf;
434 gprs_rlcmac_ul_tbf *ul_tbf;
435 GprsMs *ms;
436 static enum {UNKNOWN, IS_IDLE, IS_ACTIVE} last_cb = UNKNOWN;
437
438 struct MyCallback: public GprsMs::Callback {
439 virtual void ms_idle(class GprsMs *ms) {
440 OSMO_ASSERT(ms->is_idle());
441 printf(" ms_idle() was called\n");
442 last_cb = IS_IDLE;
443 }
444 virtual void ms_active(class GprsMs *ms) {
445 OSMO_ASSERT(!ms->is_idle());
446 printf(" ms_active() was called\n");
447 last_cb = IS_ACTIVE;
448 }
449 } cb;
450
451 printf("=== start %s ===\n", __func__);
452
Jacob Erlbeck17214bb2015-06-02 14:06:12 +0200453 ms = new GprsMs(NULL, tlli);
Jacob Erlbeckd9e10242015-05-28 15:43:53 +0200454 ms->set_callback(&cb);
455 ms->set_timeout(1);
456
457 OSMO_ASSERT(ms->is_idle());
458
459 dl_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_dl_tbf);
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200460 new (dl_tbf) gprs_rlcmac_dl_tbf(NULL);
Jacob Erlbeckd9e10242015-05-28 15:43:53 +0200461 ul_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_ul_tbf);
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200462 new (ul_tbf) gprs_rlcmac_ul_tbf(NULL);
Jacob Erlbeckd9e10242015-05-28 15:43:53 +0200463
464 OSMO_ASSERT(last_cb == UNKNOWN);
465
466 ms->attach_tbf(ul_tbf);
467 OSMO_ASSERT(!ms->is_idle());
468 OSMO_ASSERT(last_cb == IS_ACTIVE);
469
470 last_cb = UNKNOWN;
471
472 ms->attach_tbf(dl_tbf);
473 OSMO_ASSERT(!ms->is_idle());
474 OSMO_ASSERT(last_cb == UNKNOWN);
475
476 ms->detach_tbf(ul_tbf);
477 OSMO_ASSERT(!ms->is_idle());
478 OSMO_ASSERT(last_cb == UNKNOWN);
479
480 ms->detach_tbf(dl_tbf);
481 OSMO_ASSERT(!ms->is_idle());
482 OSMO_ASSERT(last_cb == UNKNOWN);
483
484 usleep(1100000);
485 osmo_timers_update();
486
487 OSMO_ASSERT(ms->is_idle());
488 OSMO_ASSERT(last_cb == IS_IDLE);
489
490 last_cb = UNKNOWN;
491 delete ms;
492 talloc_free(dl_tbf);
493 talloc_free(ul_tbf);
494
495 printf("=== end %s ===\n", __func__);
496}
497
Jacob Erlbeck70b96aa2015-06-12 10:52:34 +0200498static void test_ms_cs_selection()
499{
500 BTS the_bts;
501 gprs_rlcmac_bts *bts = the_bts.bts_data();
502 uint32_t tlli = 0xffeeddbb;
503
504 gprs_rlcmac_dl_tbf *dl_tbf;
505 GprsMs *ms;
506
507 printf("=== start %s ===\n", __func__);
508
509 bts->initial_cs_dl = 4;
510 bts->initial_cs_ul = 1;
511 bts->cs_downgrade_threshold = 0;
512
513 ms = new GprsMs(&the_bts, tlli);
514
515 OSMO_ASSERT(ms->is_idle());
516
517 dl_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_dl_tbf);
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200518 new (dl_tbf) gprs_rlcmac_dl_tbf(NULL);
Jacob Erlbeck70b96aa2015-06-12 10:52:34 +0200519
520 dl_tbf->set_ms(ms);
521 OSMO_ASSERT(!ms->is_idle());
522
Max898dddb2019-03-12 15:50:57 +0100523 OSMO_ASSERT(mcs_chan_code(ms->current_cs_dl()) == 3);
Jacob Erlbeck70b96aa2015-06-12 10:52:34 +0200524
525 bts->cs_downgrade_threshold = 200;
526
Max898dddb2019-03-12 15:50:57 +0100527 OSMO_ASSERT(mcs_chan_code(ms->current_cs_dl()) == 2);
Jacob Erlbeck70b96aa2015-06-12 10:52:34 +0200528
529 talloc_free(dl_tbf);
530
531 printf("=== end %s ===\n", __func__);
532}
533
Max41d6b352019-03-06 15:59:09 +0100534static void dump_ms(const GprsMs *ms, const char *pref)
535{
536 printf("%s MS DL %s/%s, UL %s/%s, mode %s, <%s>\n", pref,
537 mcs_name(ms->current_cs_dl()), mcs_name(ms->max_cs_dl()),
538 mcs_name(ms->current_cs_ul()), mcs_name(ms->max_cs_ul()),
539 mode_name(ms->mode()),
540 ms->is_idle() ? "IDLE" : "ACTIVE");
541}
542
543static void test_ms_mcs_mode()
544{
545 BTS the_bts;
546 gprs_rlcmac_bts *bts = the_bts.bts_data();
547 uint32_t tlli = 0xdeadbeef;
548
549 gprs_rlcmac_dl_tbf *dl_tbf;
550 GprsMs *ms1, *ms2;
551
552 printf("=== start %s ===\n", __func__);
553
554 ms1 = new GprsMs(&the_bts, tlli);
555 dump_ms(ms1, "1: no BTS defaults ");
556
557 bts->initial_cs_dl = 4;
558 bts->initial_cs_ul = 1;
559 bts->cs_downgrade_threshold = 0;
560
561 ms2 = new GprsMs(&the_bts, tlli + 1);
562 dump_ms(ms2, "2: with BTS defaults");
563
564 dl_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_dl_tbf);
565 new (dl_tbf) gprs_rlcmac_dl_tbf(NULL);
566
567 dl_tbf->set_ms(ms2);
568 dump_ms(ms2, "2: after TBF attach ");
569
570 ms1->set_mode(EGPRS);
571 dump_ms(ms1, "1: after mode set ");
572
573 ms2->set_mode(EGPRS);
574 dump_ms(ms2, "2: after mode set ");
575
576 ms1->set_current_cs_dl(MCS7);
577 dump_ms(ms1, "1: after MCS set ");
578
579 ms2->set_current_cs_dl(MCS8);
580 dump_ms(ms2, "2: after MCS set ");
581
582 ms1->set_mode(EGPRS_GMSK);
583 dump_ms(ms1, "1: after mode set ");
584
585 ms2->set_mode(EGPRS_GMSK);
586 dump_ms(ms2, "2: after mode set ");
587
588 // FIXME: following code triggers ASAN failure:
589 // ms2->detach_tbf(dl_tbf);
590 // dump_ms(ms2, "2: after TBF detach ");
591
592 ms1->set_mode(GPRS);
593 dump_ms(ms1, "1: after mode set ");
594
595 ms2->set_mode(GPRS);
596 dump_ms(ms2, "2: after mode set ");
597
598 talloc_free(dl_tbf);
599
600 printf("=== end %s ===\n", __func__);
601}
602
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200603int main(int argc, char **argv)
604{
605 struct vty_app_info pcu_vty_info = {0};
606
607 tall_pcu_ctx = talloc_named_const(NULL, 1, "MsTest context");
608 if (!tall_pcu_ctx)
609 abort();
610
Neels Hofmeyr78ce5912017-02-08 17:07:31 +0100611 msgb_talloc_ctx_init(tall_pcu_ctx, 0);
Neels Hofmeyr42f2d612018-04-01 16:54:40 +0200612 osmo_init_logging2(tall_pcu_ctx, &gprs_log_info);
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200613 log_set_use_color(osmo_stderr_target, 0);
614 log_set_print_filename(osmo_stderr_target, 0);
615 log_set_log_level(osmo_stderr_target, LOGL_INFO);
Harald Welteac0490a2017-10-29 10:39:32 +0100616 log_parse_category_mask(osmo_stderr_target, "DPCU,3:DRLCMAC,3");
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200617
618 vty_init(&pcu_vty_info);
Harald Welteac0490a2017-10-29 10:39:32 +0100619 pcu_vty_init(&gprs_log_info);
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200620
621 test_ms_state();
622 test_ms_callback();
623 test_ms_replace_tbf();
Jacob Erlbeck93990462015-05-15 15:50:43 +0200624 test_ms_change_tlli();
Jacob Erlbeck53670862015-05-12 17:54:33 +0200625 test_ms_storage();
Jacob Erlbeckd9e10242015-05-28 15:43:53 +0200626 test_ms_timeout();
Jacob Erlbeck70b96aa2015-06-12 10:52:34 +0200627 test_ms_cs_selection();
Max41d6b352019-03-06 15:59:09 +0100628 test_ms_mcs_mode();
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200629
630 if (getenv("TALLOC_REPORT_FULL"))
631 talloc_report_full(tall_pcu_ctx, stderr);
632
633 return EXIT_SUCCESS;
634}
635
636extern "C" {
637void l1if_pdch_req() { abort(); }
638void l1if_connect_pdch() { abort(); }
639void l1if_close_pdch() { abort(); }
640void l1if_open_pdch() { abort(); }
641}