blob: 0c5ab9e5f233dec9d314fb2eebb754d7b2f9ab02 [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
43void *tall_pcu_ctx;
44int16_t spoof_mnc = 0, spoof_mcc = 0;
Neels Hofmeyrbdc55fa2018-02-21 00:39:07 +010045bool spoof_mnc_3_digits = false;
Jacob Erlbecke04e0b02015-05-06 18:30:48 +020046
47static void test_ms_state()
48{
49 uint32_t tlli = 0xffeeddbb;
50 gprs_rlcmac_dl_tbf *dl_tbf;
51 gprs_rlcmac_ul_tbf *ul_tbf;
52 GprsMs *ms;
53
54 printf("=== start %s ===\n", __func__);
55
Jacob Erlbeck17214bb2015-06-02 14:06:12 +020056 ms = new GprsMs(NULL, tlli);
Jacob Erlbecke04e0b02015-05-06 18:30:48 +020057 OSMO_ASSERT(ms->is_idle());
58
59 dl_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_dl_tbf);
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +020060 new (dl_tbf) gprs_rlcmac_dl_tbf(NULL);
Jacob Erlbecke04e0b02015-05-06 18:30:48 +020061 ul_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_ul_tbf);
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +020062 new (ul_tbf) gprs_rlcmac_ul_tbf(NULL);
Jacob Erlbecke04e0b02015-05-06 18:30:48 +020063
64 ms->attach_tbf(ul_tbf);
65 OSMO_ASSERT(!ms->is_idle());
66 OSMO_ASSERT(ms->ul_tbf() == ul_tbf);
67 OSMO_ASSERT(ms->dl_tbf() == NULL);
68
69 ms->attach_tbf(dl_tbf);
70 OSMO_ASSERT(!ms->is_idle());
71 OSMO_ASSERT(ms->ul_tbf() == ul_tbf);
72 OSMO_ASSERT(ms->dl_tbf() == dl_tbf);
73
Jacob Erlbeckac89a552015-06-29 14:18:46 +020074 OSMO_ASSERT(ms->tbf(GPRS_RLCMAC_UL_TBF) == ul_tbf);
75 OSMO_ASSERT(ms->tbf(GPRS_RLCMAC_DL_TBF) == dl_tbf);
76
Jacob Erlbecke04e0b02015-05-06 18:30:48 +020077 ms->detach_tbf(ul_tbf);
78 OSMO_ASSERT(!ms->is_idle());
79 OSMO_ASSERT(ms->ul_tbf() == NULL);
80 OSMO_ASSERT(ms->dl_tbf() == dl_tbf);
81
82 ms->detach_tbf(dl_tbf);
83 /* The ms object is freed now */
84 ms = NULL;
85
86 talloc_free(dl_tbf);
87 talloc_free(ul_tbf);
88
89 printf("=== end %s ===\n", __func__);
90}
91
92static void test_ms_callback()
93{
94 uint32_t tlli = 0xffeeddbb;
95 gprs_rlcmac_dl_tbf *dl_tbf;
96 gprs_rlcmac_ul_tbf *ul_tbf;
97 GprsMs *ms;
98 static enum {UNKNOWN, IS_IDLE, IS_ACTIVE} last_cb = UNKNOWN;
99
100 struct MyCallback: public GprsMs::Callback {
101 virtual void ms_idle(class GprsMs *ms) {
102 OSMO_ASSERT(ms->is_idle());
103 printf(" ms_idle() was called\n");
104 last_cb = IS_IDLE;
105 }
106 virtual void ms_active(class GprsMs *ms) {
107 OSMO_ASSERT(!ms->is_idle());
108 printf(" ms_active() was called\n");
109 last_cb = IS_ACTIVE;
110 }
111 } cb;
112
113 printf("=== start %s ===\n", __func__);
114
Jacob Erlbeck17214bb2015-06-02 14:06:12 +0200115 ms = new GprsMs(NULL, tlli);
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200116 ms->set_callback(&cb);
117
118 OSMO_ASSERT(ms->is_idle());
119
120 dl_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_dl_tbf);
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200121 new (dl_tbf) gprs_rlcmac_dl_tbf(NULL);
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200122 ul_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_ul_tbf);
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200123 new (ul_tbf) gprs_rlcmac_ul_tbf(NULL);
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200124
125 OSMO_ASSERT(last_cb == UNKNOWN);
126
127 ms->attach_tbf(ul_tbf);
128 OSMO_ASSERT(!ms->is_idle());
129 OSMO_ASSERT(ms->ul_tbf() == ul_tbf);
130 OSMO_ASSERT(ms->dl_tbf() == NULL);
131 OSMO_ASSERT(last_cb == IS_ACTIVE);
132
133 last_cb = UNKNOWN;
134
135 ms->attach_tbf(dl_tbf);
136 OSMO_ASSERT(!ms->is_idle());
137 OSMO_ASSERT(ms->ul_tbf() == ul_tbf);
138 OSMO_ASSERT(ms->dl_tbf() == dl_tbf);
139 OSMO_ASSERT(last_cb == UNKNOWN);
140
141 ms->detach_tbf(ul_tbf);
142 OSMO_ASSERT(!ms->is_idle());
143 OSMO_ASSERT(ms->ul_tbf() == NULL);
144 OSMO_ASSERT(ms->dl_tbf() == dl_tbf);
145 OSMO_ASSERT(last_cb == UNKNOWN);
146
147 ms->detach_tbf(dl_tbf);
148 OSMO_ASSERT(ms->is_idle());
149 OSMO_ASSERT(ms->ul_tbf() == NULL);
150 OSMO_ASSERT(ms->dl_tbf() == NULL);
151 OSMO_ASSERT(last_cb == IS_IDLE);
152
153 last_cb = UNKNOWN;
154 delete ms;
155
156 talloc_free(dl_tbf);
157 talloc_free(ul_tbf);
158
159 printf("=== end %s ===\n", __func__);
160}
161
162static void test_ms_replace_tbf()
163{
164 uint32_t tlli = 0xffeeddbb;
165 gprs_rlcmac_dl_tbf *dl_tbf[2];
166 gprs_rlcmac_ul_tbf *ul_tbf;
167 GprsMs *ms;
168 static bool was_idle;
169
170 struct MyCallback: public GprsMs::Callback {
171 virtual void ms_idle(class GprsMs *ms) {
172 OSMO_ASSERT(ms->is_idle());
173 printf(" ms_idle() was called\n");
174 was_idle = true;
175 }
176 virtual void ms_active(class GprsMs *ms) {
177 OSMO_ASSERT(!ms->is_idle());
178 printf(" ms_active() was called\n");
179 }
180 } cb;
181
182 printf("=== start %s ===\n", __func__);
183
Jacob Erlbeck17214bb2015-06-02 14:06:12 +0200184 ms = new GprsMs(NULL, tlli);
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200185 ms->set_callback(&cb);
186
187 OSMO_ASSERT(ms->is_idle());
188 was_idle = false;
189
190 dl_tbf[0] = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_dl_tbf);
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200191 new (dl_tbf[0]) gprs_rlcmac_dl_tbf(NULL);
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200192 dl_tbf[1] = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_dl_tbf);
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200193 new (dl_tbf[1]) gprs_rlcmac_dl_tbf(NULL);
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200194 ul_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_ul_tbf);
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200195 new (ul_tbf) gprs_rlcmac_ul_tbf(NULL);
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200196
197 ms->attach_tbf(dl_tbf[0]);
198 OSMO_ASSERT(!ms->is_idle());
199 OSMO_ASSERT(ms->ul_tbf() == NULL);
200 OSMO_ASSERT(ms->dl_tbf() == dl_tbf[0]);
Jacob Erlbeck6835cea2015-08-21 15:24:02 +0200201 OSMO_ASSERT(llist_empty(&ms->old_tbfs()));
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200202 OSMO_ASSERT(!was_idle);
203
204 ms->attach_tbf(dl_tbf[1]);
205 OSMO_ASSERT(!ms->is_idle());
206 OSMO_ASSERT(ms->ul_tbf() == NULL);
207 OSMO_ASSERT(ms->dl_tbf() == dl_tbf[1]);
Jacob Erlbeck6835cea2015-08-21 15:24:02 +0200208 OSMO_ASSERT(!llist_empty(&ms->old_tbfs()));
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200209 OSMO_ASSERT(!was_idle);
210
211 ms->attach_tbf(ul_tbf);
212 OSMO_ASSERT(!ms->is_idle());
213 OSMO_ASSERT(ms->ul_tbf() == ul_tbf);
214 OSMO_ASSERT(ms->dl_tbf() == dl_tbf[1]);
Jacob Erlbeck6835cea2015-08-21 15:24:02 +0200215 OSMO_ASSERT(!llist_empty(&ms->old_tbfs()));
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200216 OSMO_ASSERT(!was_idle);
217
218 ms->detach_tbf(ul_tbf);
219 OSMO_ASSERT(!ms->is_idle());
220 OSMO_ASSERT(ms->ul_tbf() == NULL);
221 OSMO_ASSERT(ms->dl_tbf() == dl_tbf[1]);
Jacob Erlbeck6835cea2015-08-21 15:24:02 +0200222 OSMO_ASSERT(!llist_empty(&ms->old_tbfs()));
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200223 OSMO_ASSERT(!was_idle);
224
225 ms->detach_tbf(dl_tbf[0]);
226 OSMO_ASSERT(!ms->is_idle());
227 OSMO_ASSERT(ms->ul_tbf() == NULL);
228 OSMO_ASSERT(ms->dl_tbf() == dl_tbf[1]);
Jacob Erlbeck6835cea2015-08-21 15:24:02 +0200229 OSMO_ASSERT(llist_empty(&ms->old_tbfs()));
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200230 OSMO_ASSERT(!was_idle);
231
232 ms->detach_tbf(dl_tbf[1]);
233 OSMO_ASSERT(ms->is_idle());
234 OSMO_ASSERT(ms->ul_tbf() == NULL);
235 OSMO_ASSERT(ms->dl_tbf() == NULL);
Jacob Erlbeck6835cea2015-08-21 15:24:02 +0200236 OSMO_ASSERT(llist_empty(&ms->old_tbfs()));
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200237 OSMO_ASSERT(was_idle);
238
239 delete ms;
240
241 talloc_free(dl_tbf[0]);
242 talloc_free(dl_tbf[1]);
243 talloc_free(ul_tbf);
244
245 printf("=== end %s ===\n", __func__);
246}
247
Jacob Erlbeck93990462015-05-15 15:50:43 +0200248static void test_ms_change_tlli()
249{
250 uint32_t start_tlli = 0xaa000000;
251 uint32_t new_ms_tlli = 0xff001111;
252 uint32_t other_sgsn_tlli = 0xff00eeee;
253 GprsMs *ms;
254
255 printf("=== start %s ===\n", __func__);
256
Jacob Erlbeck17214bb2015-06-02 14:06:12 +0200257 ms = new GprsMs(NULL, start_tlli);
Jacob Erlbeck93990462015-05-15 15:50:43 +0200258
259 OSMO_ASSERT(ms->is_idle());
260
261 /* MS announces TLLI, SGSN uses it immediately */
262 ms->set_tlli(new_ms_tlli);
263 OSMO_ASSERT(ms->tlli() == new_ms_tlli);
264 OSMO_ASSERT(ms->check_tlli(new_ms_tlli));
265 OSMO_ASSERT(ms->check_tlli(start_tlli));
266
267 ms->confirm_tlli(new_ms_tlli);
268 OSMO_ASSERT(ms->tlli() == new_ms_tlli);
269 OSMO_ASSERT(ms->check_tlli(new_ms_tlli));
270 OSMO_ASSERT(!ms->check_tlli(start_tlli));
271
272 /* MS announces TLLI, SGSN uses it later */
273 ms->set_tlli(start_tlli);
274 ms->confirm_tlli(start_tlli);
275
276 ms->set_tlli(new_ms_tlli);
277 OSMO_ASSERT(ms->tlli() == new_ms_tlli);
278 OSMO_ASSERT(ms->check_tlli(new_ms_tlli));
279 OSMO_ASSERT(ms->check_tlli(start_tlli));
280
281 ms->confirm_tlli(start_tlli);
282 OSMO_ASSERT(ms->tlli() == new_ms_tlli);
283 OSMO_ASSERT(ms->check_tlli(new_ms_tlli));
284 OSMO_ASSERT(ms->check_tlli(start_tlli));
285
286 ms->set_tlli(new_ms_tlli);
287 OSMO_ASSERT(ms->tlli() == new_ms_tlli);
288 OSMO_ASSERT(ms->check_tlli(new_ms_tlli));
289 OSMO_ASSERT(ms->check_tlli(start_tlli));
290
291 ms->confirm_tlli(new_ms_tlli);
292 OSMO_ASSERT(ms->tlli() == new_ms_tlli);
293 OSMO_ASSERT(ms->check_tlli(new_ms_tlli));
294 OSMO_ASSERT(!ms->check_tlli(start_tlli));
295
296 /* MS announces TLLI, SGSN uses it later after another new TLLI */
297 ms->set_tlli(start_tlli);
298 ms->confirm_tlli(start_tlli);
299
300 ms->set_tlli(new_ms_tlli);
301 OSMO_ASSERT(ms->tlli() == new_ms_tlli);
302 OSMO_ASSERT(ms->check_tlli(new_ms_tlli));
303 OSMO_ASSERT(ms->check_tlli(start_tlli));
304
305 ms->confirm_tlli(other_sgsn_tlli);
306 OSMO_ASSERT(ms->tlli() == new_ms_tlli);
307 OSMO_ASSERT(ms->check_tlli(new_ms_tlli));
308 OSMO_ASSERT(ms->check_tlli(other_sgsn_tlli));
309
310 ms->set_tlli(new_ms_tlli);
311 OSMO_ASSERT(ms->tlli() == new_ms_tlli);
312 OSMO_ASSERT(ms->check_tlli(new_ms_tlli));
313 OSMO_ASSERT(ms->check_tlli(other_sgsn_tlli));
314
315 ms->confirm_tlli(new_ms_tlli);
316 OSMO_ASSERT(ms->tlli() == new_ms_tlli);
317 OSMO_ASSERT(ms->check_tlli(new_ms_tlli));
318 OSMO_ASSERT(!ms->check_tlli(start_tlli));
319 OSMO_ASSERT(!ms->check_tlli(other_sgsn_tlli));
320
321 /* SGSN uses the new TLLI before it is announced by the MS (shouldn't
322 * happen in normal use) */
323 ms->set_tlli(start_tlli);
324 ms->confirm_tlli(start_tlli);
325
326 ms->confirm_tlli(new_ms_tlli);
327 OSMO_ASSERT(ms->tlli() == start_tlli);
328 OSMO_ASSERT(ms->check_tlli(new_ms_tlli));
329 OSMO_ASSERT(ms->check_tlli(start_tlli));
330
331 ms->set_tlli(new_ms_tlli);
332 OSMO_ASSERT(ms->tlli() == new_ms_tlli);
333 OSMO_ASSERT(ms->check_tlli(new_ms_tlli));
334 OSMO_ASSERT(!ms->check_tlli(start_tlli));
335
336 delete ms;
337
338 printf("=== end %s ===\n", __func__);
339}
340
Maxf4d39732019-03-12 12:53:27 +0100341static GprsMs *prepare_ms(GprsMsStorage *st, uint32_t tlli, enum gprs_rlcmac_tbf_direction dir)
342{
343 GprsMs *ms = st->get_ms(tlli);
344 if (ms)
345 return ms;
346
347 ms = st->create_ms();
348
349 if (dir == GPRS_RLCMAC_UL_TBF)
350 ms->set_tlli(tlli);
351 else
352 ms->confirm_tlli(tlli);
353
354 return ms;
355}
356
Jacob Erlbeck53670862015-05-12 17:54:33 +0200357static void test_ms_storage()
358{
359 uint32_t tlli = 0xffeeddbb;
Jacob Erlbeck7b9f8252015-05-21 11:07:53 +0200360 const char *imsi1 = "001001987654321";
361 const char *imsi2 = "001001987654322";
362
Jacob Erlbeck53670862015-05-12 17:54:33 +0200363 gprs_rlcmac_ul_tbf *ul_tbf;
Jacob Erlbeck0e50ce62015-05-21 16:58:22 +0200364 GprsMs *ms, *ms_tmp;
Jacob Erlbeck17214bb2015-06-02 14:06:12 +0200365 GprsMsStorage store(NULL);
Jacob Erlbeck53670862015-05-12 17:54:33 +0200366
367 printf("=== start %s ===\n", __func__);
368
369 ul_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_ul_tbf);
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200370 new (ul_tbf) gprs_rlcmac_ul_tbf(NULL);
Jacob Erlbeck53670862015-05-12 17:54:33 +0200371
372 ms = store.get_ms(tlli + 0);
373 OSMO_ASSERT(ms == NULL);
374
Maxf4d39732019-03-12 12:53:27 +0100375 ms = prepare_ms(&store, tlli + 0, GPRS_RLCMAC_UL_TBF);
Jacob Erlbeck53670862015-05-12 17:54:33 +0200376 OSMO_ASSERT(ms != NULL);
377 OSMO_ASSERT(ms->tlli() == tlli + 0);
Jacob Erlbeck7b9f8252015-05-21 11:07:53 +0200378 ms->set_imsi(imsi1);
379 OSMO_ASSERT(strcmp(ms->imsi(), imsi1) == 0);
Jacob Erlbeck53670862015-05-12 17:54:33 +0200380
Jacob Erlbeck0e50ce62015-05-21 16:58:22 +0200381 ms_tmp = store.get_ms(tlli + 0);
382 OSMO_ASSERT(ms == ms_tmp);
383 OSMO_ASSERT(ms->tlli() == tlli + 0);
384
Jacob Erlbeck7b9f8252015-05-21 11:07:53 +0200385 ms_tmp = store.get_ms(0, 0, imsi1);
386 OSMO_ASSERT(ms == ms_tmp);
387 OSMO_ASSERT(strcmp(ms->imsi(), imsi1) == 0);
388 ms_tmp = store.get_ms(0, 0, imsi2);
389 OSMO_ASSERT(ms_tmp == NULL);
390
Maxf4d39732019-03-12 12:53:27 +0100391 ms = prepare_ms(&store, tlli + 1, GPRS_RLCMAC_UL_TBF);
Jacob Erlbeck0e50ce62015-05-21 16:58:22 +0200392 OSMO_ASSERT(ms != NULL);
Jacob Erlbeck53670862015-05-12 17:54:33 +0200393 OSMO_ASSERT(ms->tlli() == tlli + 1);
Jacob Erlbeck7b9f8252015-05-21 11:07:53 +0200394 ms->set_imsi(imsi2);
395 OSMO_ASSERT(strcmp(ms->imsi(), imsi2) == 0);
Jacob Erlbeck53670862015-05-12 17:54:33 +0200396
Jacob Erlbeck0e50ce62015-05-21 16:58:22 +0200397 ms_tmp = store.get_ms(tlli + 1);
398 OSMO_ASSERT(ms == ms_tmp);
Jacob Erlbeck53670862015-05-12 17:54:33 +0200399 OSMO_ASSERT(ms->tlli() == tlli + 1);
400
Jacob Erlbeck7b9f8252015-05-21 11:07:53 +0200401 ms_tmp = store.get_ms(0, 0, imsi1);
402 OSMO_ASSERT(ms_tmp != NULL);
403 OSMO_ASSERT(ms_tmp != ms);
404 ms_tmp = store.get_ms(0, 0, imsi2);
405 OSMO_ASSERT(ms == ms_tmp);
406 OSMO_ASSERT(strcmp(ms->imsi(), imsi2) == 0);
407
Jacob Erlbeck53670862015-05-12 17:54:33 +0200408 /* delete ms */
409 ms = store.get_ms(tlli + 0);
410 OSMO_ASSERT(ms != NULL);
411 ms->attach_tbf(ul_tbf);
412 ms->detach_tbf(ul_tbf);
413 ms = store.get_ms(tlli + 0);
414 OSMO_ASSERT(ms == NULL);
415 ms = store.get_ms(tlli + 1);
416 OSMO_ASSERT(ms != NULL);
417
418 /* delete ms */
419 ms = store.get_ms(tlli + 1);
420 OSMO_ASSERT(ms != NULL);
421 ms->attach_tbf(ul_tbf);
422 ms->detach_tbf(ul_tbf);
423 ms = store.get_ms(tlli + 1);
424 OSMO_ASSERT(ms == NULL);
425
426 talloc_free(ul_tbf);
427
428 printf("=== end %s ===\n", __func__);
429}
430
Jacob Erlbeckd9e10242015-05-28 15:43:53 +0200431static void test_ms_timeout()
432{
433 uint32_t tlli = 0xffeeddbb;
434 gprs_rlcmac_dl_tbf *dl_tbf;
435 gprs_rlcmac_ul_tbf *ul_tbf;
436 GprsMs *ms;
437 static enum {UNKNOWN, IS_IDLE, IS_ACTIVE} last_cb = UNKNOWN;
438
439 struct MyCallback: public GprsMs::Callback {
440 virtual void ms_idle(class GprsMs *ms) {
441 OSMO_ASSERT(ms->is_idle());
442 printf(" ms_idle() was called\n");
443 last_cb = IS_IDLE;
444 }
445 virtual void ms_active(class GprsMs *ms) {
446 OSMO_ASSERT(!ms->is_idle());
447 printf(" ms_active() was called\n");
448 last_cb = IS_ACTIVE;
449 }
450 } cb;
451
452 printf("=== start %s ===\n", __func__);
453
Jacob Erlbeck17214bb2015-06-02 14:06:12 +0200454 ms = new GprsMs(NULL, tlli);
Jacob Erlbeckd9e10242015-05-28 15:43:53 +0200455 ms->set_callback(&cb);
456 ms->set_timeout(1);
457
458 OSMO_ASSERT(ms->is_idle());
459
460 dl_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_dl_tbf);
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200461 new (dl_tbf) gprs_rlcmac_dl_tbf(NULL);
Jacob Erlbeckd9e10242015-05-28 15:43:53 +0200462 ul_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_ul_tbf);
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200463 new (ul_tbf) gprs_rlcmac_ul_tbf(NULL);
Jacob Erlbeckd9e10242015-05-28 15:43:53 +0200464
465 OSMO_ASSERT(last_cb == UNKNOWN);
466
467 ms->attach_tbf(ul_tbf);
468 OSMO_ASSERT(!ms->is_idle());
469 OSMO_ASSERT(last_cb == IS_ACTIVE);
470
471 last_cb = UNKNOWN;
472
473 ms->attach_tbf(dl_tbf);
474 OSMO_ASSERT(!ms->is_idle());
475 OSMO_ASSERT(last_cb == UNKNOWN);
476
477 ms->detach_tbf(ul_tbf);
478 OSMO_ASSERT(!ms->is_idle());
479 OSMO_ASSERT(last_cb == UNKNOWN);
480
481 ms->detach_tbf(dl_tbf);
482 OSMO_ASSERT(!ms->is_idle());
483 OSMO_ASSERT(last_cb == UNKNOWN);
484
485 usleep(1100000);
486 osmo_timers_update();
487
488 OSMO_ASSERT(ms->is_idle());
489 OSMO_ASSERT(last_cb == IS_IDLE);
490
491 last_cb = UNKNOWN;
492 delete ms;
493 talloc_free(dl_tbf);
494 talloc_free(ul_tbf);
495
496 printf("=== end %s ===\n", __func__);
497}
498
Jacob Erlbeck70b96aa2015-06-12 10:52:34 +0200499static void test_ms_cs_selection()
500{
501 BTS the_bts;
502 gprs_rlcmac_bts *bts = the_bts.bts_data();
503 uint32_t tlli = 0xffeeddbb;
504
505 gprs_rlcmac_dl_tbf *dl_tbf;
506 GprsMs *ms;
507
508 printf("=== start %s ===\n", __func__);
509
510 bts->initial_cs_dl = 4;
511 bts->initial_cs_ul = 1;
512 bts->cs_downgrade_threshold = 0;
513
514 ms = new GprsMs(&the_bts, tlli);
515
516 OSMO_ASSERT(ms->is_idle());
517
518 dl_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_dl_tbf);
Jacob Erlbeckb6b3c7e2015-08-28 12:07:14 +0200519 new (dl_tbf) gprs_rlcmac_dl_tbf(NULL);
Jacob Erlbeck70b96aa2015-06-12 10:52:34 +0200520
521 dl_tbf->set_ms(ms);
522 OSMO_ASSERT(!ms->is_idle());
523
Max898dddb2019-03-12 15:50:57 +0100524 OSMO_ASSERT(mcs_chan_code(ms->current_cs_dl()) == 3);
Jacob Erlbeck70b96aa2015-06-12 10:52:34 +0200525
526 bts->cs_downgrade_threshold = 200;
527
Max898dddb2019-03-12 15:50:57 +0100528 OSMO_ASSERT(mcs_chan_code(ms->current_cs_dl()) == 2);
Jacob Erlbeck70b96aa2015-06-12 10:52:34 +0200529
530 talloc_free(dl_tbf);
531
532 printf("=== end %s ===\n", __func__);
533}
534
Max41d6b352019-03-06 15:59:09 +0100535static void dump_ms(const GprsMs *ms, const char *pref)
536{
537 printf("%s MS DL %s/%s, UL %s/%s, mode %s, <%s>\n", pref,
538 mcs_name(ms->current_cs_dl()), mcs_name(ms->max_cs_dl()),
539 mcs_name(ms->current_cs_ul()), mcs_name(ms->max_cs_ul()),
540 mode_name(ms->mode()),
541 ms->is_idle() ? "IDLE" : "ACTIVE");
542}
543
544static void test_ms_mcs_mode()
545{
546 BTS the_bts;
547 gprs_rlcmac_bts *bts = the_bts.bts_data();
548 uint32_t tlli = 0xdeadbeef;
549
550 gprs_rlcmac_dl_tbf *dl_tbf;
551 GprsMs *ms1, *ms2;
552
553 printf("=== start %s ===\n", __func__);
554
555 ms1 = new GprsMs(&the_bts, tlli);
556 dump_ms(ms1, "1: no BTS defaults ");
557
558 bts->initial_cs_dl = 4;
559 bts->initial_cs_ul = 1;
560 bts->cs_downgrade_threshold = 0;
561
562 ms2 = new GprsMs(&the_bts, tlli + 1);
563 dump_ms(ms2, "2: with BTS defaults");
564
565 dl_tbf = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_dl_tbf);
566 new (dl_tbf) gprs_rlcmac_dl_tbf(NULL);
567
568 dl_tbf->set_ms(ms2);
569 dump_ms(ms2, "2: after TBF attach ");
570
571 ms1->set_mode(EGPRS);
572 dump_ms(ms1, "1: after mode set ");
573
574 ms2->set_mode(EGPRS);
575 dump_ms(ms2, "2: after mode set ");
576
577 ms1->set_current_cs_dl(MCS7);
578 dump_ms(ms1, "1: after MCS set ");
579
580 ms2->set_current_cs_dl(MCS8);
581 dump_ms(ms2, "2: after MCS set ");
582
583 ms1->set_mode(EGPRS_GMSK);
584 dump_ms(ms1, "1: after mode set ");
585
586 ms2->set_mode(EGPRS_GMSK);
587 dump_ms(ms2, "2: after mode set ");
588
589 // FIXME: following code triggers ASAN failure:
590 // ms2->detach_tbf(dl_tbf);
591 // dump_ms(ms2, "2: after TBF detach ");
592
593 ms1->set_mode(GPRS);
594 dump_ms(ms1, "1: after mode set ");
595
596 ms2->set_mode(GPRS);
597 dump_ms(ms2, "2: after mode set ");
598
599 talloc_free(dl_tbf);
600
601 printf("=== end %s ===\n", __func__);
602}
603
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200604int main(int argc, char **argv)
605{
606 struct vty_app_info pcu_vty_info = {0};
607
608 tall_pcu_ctx = talloc_named_const(NULL, 1, "MsTest context");
609 if (!tall_pcu_ctx)
610 abort();
611
Neels Hofmeyr78ce5912017-02-08 17:07:31 +0100612 msgb_talloc_ctx_init(tall_pcu_ctx, 0);
Neels Hofmeyr42f2d612018-04-01 16:54:40 +0200613 osmo_init_logging2(tall_pcu_ctx, &gprs_log_info);
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200614 log_set_use_color(osmo_stderr_target, 0);
615 log_set_print_filename(osmo_stderr_target, 0);
616 log_set_log_level(osmo_stderr_target, LOGL_INFO);
Harald Welteac0490a2017-10-29 10:39:32 +0100617 log_parse_category_mask(osmo_stderr_target, "DPCU,3:DRLCMAC,3");
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200618
619 vty_init(&pcu_vty_info);
Pau Espin Pedrolcd2ac562019-08-05 14:30:44 +0200620 pcu_vty_init();
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200621
622 test_ms_state();
623 test_ms_callback();
624 test_ms_replace_tbf();
Jacob Erlbeck93990462015-05-15 15:50:43 +0200625 test_ms_change_tlli();
Jacob Erlbeck53670862015-05-12 17:54:33 +0200626 test_ms_storage();
Jacob Erlbeckd9e10242015-05-28 15:43:53 +0200627 test_ms_timeout();
Jacob Erlbeck70b96aa2015-06-12 10:52:34 +0200628 test_ms_cs_selection();
Max41d6b352019-03-06 15:59:09 +0100629 test_ms_mcs_mode();
Jacob Erlbecke04e0b02015-05-06 18:30:48 +0200630
631 if (getenv("TALLOC_REPORT_FULL"))
632 talloc_report_full(tall_pcu_ctx, stderr);
633
634 return EXIT_SUCCESS;
635}
636
637extern "C" {
638void l1if_pdch_req() { abort(); }
639void l1if_connect_pdch() { abort(); }
640void l1if_close_pdch() { abort(); }
641void l1if_open_pdch() { abort(); }
642}