blob: c8bb394d98f8c988eb757e12506817fadc4c755e [file] [log] [blame]
Holger Hans Peter Freyther72bd4eb2011-12-11 20:25:12 +01001/*
2 * (C) 2011 by Holger Hans Peter Freyther
3 * (C) 2011 by On-Waves
Daniel Willmann09129352014-03-20 18:54:57 +01004 * (C) 2014 by Daniel Willmann <dwillmann@sysmocom.de>
Holger Hans Peter Freyther72bd4eb2011-12-11 20:25:12 +01005 * All Rights Reserved
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 */
22
Holger Hans Peter Freytheraf723a42012-12-26 10:51:00 +010023#include <osmocom/core/application.h>
Holger Hans Peter Freyther72bd4eb2011-12-11 20:25:12 +010024#include <osmocom/core/logging.h>
Katerina Barone-Adesi008e53b2013-03-03 10:36:52 +000025#include <osmocom/core/utils.h>
Holger Hans Peter Freyther72bd4eb2011-12-11 20:25:12 +010026#include <osmocom/gsm/lapdm.h>
27#include <osmocom/gsm/rsl.h>
28
29#include <errno.h>
30
31#include <string.h>
32
33#define CHECK_RC(rc) \
34 if (rc != 0) { \
35 printf("Operation failed rc=%d on %s:%d\n", rc, __FILE__, __LINE__); \
36 abort(); \
37 }
38
Holger Hans Peter Freyther72bd4eb2011-12-11 20:25:12 +010039static struct log_info info = {};
Jacob Erlbeckc893c222014-01-28 10:53:59 +010040static int dummy_l1_header_len = 0;
Holger Hans Peter Freyther72bd4eb2011-12-11 20:25:12 +010041
42struct lapdm_polling_state {
43 struct lapdm_channel *bts;
44 int bts_read;
45
46 struct lapdm_channel *ms;
47 int ms_read;
48};
49
50static struct msgb *msgb_from_array(const uint8_t *data, int len)
51{
52 struct msgb *msg = msgb_alloc_headroom(4096, 128, "data");
53 msg->l3h = msgb_put(msg, len);
54 memcpy(msg->l3h, data, len);
55 return msg;
56}
57
Holger Hans Peter Freyther15f740c2011-12-12 00:29:50 +010058/*
59 * Test data is below...
60 */
61static const uint8_t cm[] = {
62 0x05, 0x24, 0x31, 0x03, 0x50, 0x18, 0x93, 0x08,
63 0x29, 0x47, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80,
64};
65
Andreas Eversberg6e182082013-02-06 14:13:21 +010066static const uint8_t ua[] = {
67 0x01, 0x73, 0x41, 0x05, 0x24, 0x31, 0x03, 0x50,
68 0x18, 0x93, 0x08, 0x29, 0x47, 0x80, 0x00, 0x00,
69 0x00, 0x00, 0x80, 0x2b, 0x2b, 0x2b, 0x2b
70};
71
Holger Hans Peter Freyther15f740c2011-12-12 00:29:50 +010072static const uint8_t mm[] = {
Holger Hans Peter Freyther3a5f08c2012-01-12 23:12:28 +010073 0x00, 0x0c, 0x00, 0x03, 0x01, 0x01, 0x20, 0x02,
74 0x00, 0x0b, 0x00, 0x03, 0x05, 0x04, 0x0d
Holger Hans Peter Freyther15f740c2011-12-12 00:29:50 +010075};
76
77static const uint8_t dummy1[] = {
78 0xab, 0x03, 0x30, 0x60, 0x06,
79};
Holger Hans Peter Freyther72bd4eb2011-12-11 20:25:12 +010080
Daniel Willmanne5233922012-12-25 23:15:50 +010081static const uint8_t rel_req[] = {
82 0x02, 0x07, 0x01, 0x0a, 0x02, 0x40, 0x14, 0x01
83};
84
Jacob Erlbeck90937fe2014-01-24 13:48:19 +010085static const uint8_t est_req_sdcch_sapi3[] = {
86 0x02, 0x04, 0x01, 0x20, 0x02, 0x03
87};
88
89static const uint8_t est_req_sacch_sapi3[] = {
90 0x02, 0x04, 0x01, 0x0b, 0x02, 0x43
91};
92
Holger Hans Peter Freyther72bd4eb2011-12-11 20:25:12 +010093static struct msgb *create_cm_serv_req(void)
94{
95 struct msgb *msg;
Holger Hans Peter Freyther72bd4eb2011-12-11 20:25:12 +010096
97 msg = msgb_from_array(cm, sizeof(cm));
98 rsl_rll_push_l3(msg, RSL_MT_EST_REQ, 0, 0, 1);
Jacob Erlbeckc893c222014-01-28 10:53:59 +010099 msgb_push(msg, dummy_l1_header_len);
Holger Hans Peter Freyther72bd4eb2011-12-11 20:25:12 +0100100 return msg;
101}
102
103static struct msgb *create_mm_id_req(void)
104{
105 struct msgb *msg;
Holger Hans Peter Freyther72bd4eb2011-12-11 20:25:12 +0100106
107 msg = msgb_from_array(mm, sizeof(mm));
Holger Hans Peter Freyther3a5f08c2012-01-12 23:12:28 +0100108 msg->l2h = msg->data + 3;
Katerina Barone-Adesi008e53b2013-03-03 10:36:52 +0000109 OSMO_ASSERT(msgb_l2len(msg) == 12);
Holger Hans Peter Freyther3a5f08c2012-01-12 23:12:28 +0100110 msg->l3h = msg->l2h + 6;
Katerina Barone-Adesi008e53b2013-03-03 10:36:52 +0000111 OSMO_ASSERT(msgb_l3len(msg) == 6);
Jacob Erlbeckc893c222014-01-28 10:53:59 +0100112 msgb_push(msg, dummy_l1_header_len);
Holger Hans Peter Freyther3a5f08c2012-01-12 23:12:28 +0100113
Holger Hans Peter Freyther72bd4eb2011-12-11 20:25:12 +0100114 return msg;
115}
116
Holger Hans Peter Freyther90656db2012-01-13 05:49:29 +0800117static struct msgb *create_empty_msg(void)
118{
119 struct msgb *msg;
120
121 msg = msgb_from_array(NULL, 0);
Katerina Barone-Adesi008e53b2013-03-03 10:36:52 +0000122 OSMO_ASSERT(msgb_l3len(msg) == 0);
Holger Hans Peter Freyther90656db2012-01-13 05:49:29 +0800123 rsl_rll_push_l3(msg, RSL_MT_DATA_REQ, 0, 0, 1);
Jacob Erlbeckc893c222014-01-28 10:53:59 +0100124 msgb_push(msg, dummy_l1_header_len);
Holger Hans Peter Freyther90656db2012-01-13 05:49:29 +0800125 return msg;
126}
127
Holger Hans Peter Freyther72bd4eb2011-12-11 20:25:12 +0100128static struct msgb *create_dummy_data_req(void)
129{
130 struct msgb *msg;
Holger Hans Peter Freyther72bd4eb2011-12-11 20:25:12 +0100131
132 msg = msgb_from_array(dummy1, sizeof(dummy1));
133 rsl_rll_push_l3(msg, RSL_MT_DATA_REQ, 0, 0, 1);
Jacob Erlbeckc893c222014-01-28 10:53:59 +0100134 msgb_push(msg, dummy_l1_header_len);
Holger Hans Peter Freyther72bd4eb2011-12-11 20:25:12 +0100135 return msg;
136}
137
Daniel Willmanne5233922012-12-25 23:15:50 +0100138static struct msgb *create_rel_req(void)
139{
140 struct msgb *msg;
141
142 msg = msgb_from_array(rel_req, sizeof(rel_req));
143 msg->l2h = msg->data;
Jacob Erlbeckc893c222014-01-28 10:53:59 +0100144 msgb_push(msg, dummy_l1_header_len);
Daniel Willmanne5233922012-12-25 23:15:50 +0100145 msg->l3h = msg->l2h + sizeof(struct abis_rsl_rll_hdr);
146 return msg;
147}
148
Jacob Erlbeck90937fe2014-01-24 13:48:19 +0100149static struct msgb *create_est_req(const uint8_t *est_req, size_t est_req_size)
150{
151 struct msgb *msg;
152
153 msg = msgb_from_array(est_req, est_req_size);
154 msg->l2h = msg->data;
Jacob Erlbeckc893c222014-01-28 10:53:59 +0100155 msgb_push(msg, dummy_l1_header_len);
Jacob Erlbeck90937fe2014-01-24 13:48:19 +0100156 msg->l3h = msg->l2h + sizeof(struct abis_rsl_rll_hdr);
157 return msg;
158}
159
Holger Hans Peter Freyther72bd4eb2011-12-11 20:25:12 +0100160static int send(struct msgb *in_msg, struct lapdm_channel *chan)
161{
162 struct osmo_phsap_prim pp;
163 struct msgb *msg;
164 int rc;
165
166 msg = msgb_alloc_headroom(128, 64, "PH-DATA.ind");
167 osmo_prim_init(&pp.oph, SAP_GSM_PH, PRIM_PH_DATA,
168 PRIM_OP_INDICATION, msg);
169 /* copy over actual MAC block */
170 msg->l2h = msgb_put(msg, msgb_l2len(in_msg));
171 memcpy(msg->l2h, in_msg->l2h, msgb_l2len(in_msg));
172
173 /* LAPDm requires those... */
174 pp.u.data.chan_nr = 0;
175 pp.u.data.link_id = 0;
176 /* feed into the LAPDm code of libosmogsm */
177 rc = lapdm_phsap_up(&pp.oph, &chan->lapdm_dcch);
Katerina Barone-Adesi008e53b2013-03-03 10:36:52 +0000178 OSMO_ASSERT(rc == 0 || rc == -EBUSY);
Holger Hans Peter Freyther72bd4eb2011-12-11 20:25:12 +0100179 return 0;
180}
181
Daniel Willmann09129352014-03-20 18:54:57 +0100182/* Receive from L1 */
183static int send_buf(const uint8_t *buf, size_t len, struct lapdm_channel *chan)
Andreas Eversberg6e182082013-02-06 14:13:21 +0100184{
185 struct osmo_phsap_prim pp;
186 struct msgb *msg;
187 int rc;
188
Daniel Willmann09129352014-03-20 18:54:57 +0100189 msg = msgb_from_array(buf, len);
190 msg->l2h = msg->l3h;
191 msg->l3h = NULL;
192 osmo_prim_init(&pp.oph, SAP_GSM_PH, PRIM_PH_DATA,
193 PRIM_OP_INDICATION, msg);
194
195 /* LAPDm requires those... */
196 pp.u.data.chan_nr = 0;
197 pp.u.data.link_id = 0;
198 /* feed into the LAPDm code of libosmogsm */
199 rc = lapdm_phsap_up(&pp.oph, &chan->lapdm_dcch);
200 OSMO_ASSERT(rc == 0 || rc == -EBUSY);
201 return 0;
202}
203
204/* Receive from L3 */
205static int enqueue_buf(const uint8_t *buf, size_t len, int sapi, struct lapdm_channel *chan)
206{
207 struct osmo_dlsap_prim dp;
208 struct msgb *msg;
209 int rc;
210 struct lapdm_datalink *dl;
211
212 dl = lapdm_datalink_for_sapi(&chan->lapdm_dcch, sapi);
213 OSMO_ASSERT(dl);
214
215 msg = msgb_from_array(buf, len);
216 osmo_prim_init(&dp.oph, 0, PRIM_DL_DATA, PRIM_OP_REQUEST, msg);
217
218 rc = lapd_recv_dlsap(&dp, &dl->dl.lctx);
219 OSMO_ASSERT(rc == 0 || rc == -EBUSY);
220 return 0;
221}
222
223static int send_sabm(struct lapdm_channel *chan, int sapi, const uint8_t *data, size_t len)
224{
225 struct osmo_phsap_prim pp;
226 struct msgb *msg;
227 int rc;
228
229 OSMO_ASSERT(sapi == 0 || sapi == 3);
230
Andreas Eversberg6e182082013-02-06 14:13:21 +0100231 msg = msgb_alloc_headroom(128, 64, "PH-DATA.ind");
232 osmo_prim_init(&pp.oph, SAP_GSM_PH, PRIM_PH_DATA,
233 PRIM_OP_INDICATION, msg);
234 /* copy over actual MAC block */
Daniel Willmann09129352014-03-20 18:54:57 +0100235 msg->l2h = msgb_put(msg, 3 + len);
236 msg->l2h[0] = 0x01 | (sapi << 2);
Andreas Eversberg6e182082013-02-06 14:13:21 +0100237 msg->l2h[1] = 0x3f;
Daniel Willmann09129352014-03-20 18:54:57 +0100238 msg->l2h[2] = 0x01 | (len << 2);
239
240 if (len > 0)
241 memcpy(msg->l2h + 3, data, len);
Andreas Eversberg6e182082013-02-06 14:13:21 +0100242
243 /* LAPDm requires those... */
244 pp.u.data.chan_nr = 0;
245 pp.u.data.link_id = 0;
246 /* feed into the LAPDm code of libosmogsm */
247 rc = lapdm_phsap_up(&pp.oph, &chan->lapdm_dcch);
248 OSMO_ASSERT(rc == 0 || rc == -EBUSY);
249 return 0;
250}
251
Holger Hans Peter Freyther72bd4eb2011-12-11 20:25:12 +0100252/*
253 * I get called from the LAPDm code when something was sent my way...
254 */
255static int bts_to_ms_tx_cb(struct msgb *in_msg, struct lapdm_entity *le, void *_ctx)
256{
257 struct lapdm_polling_state *state = _ctx;
258
Holger Hans Peter Freyther72bd4eb2011-12-11 20:25:12 +0100259
260 printf("%s: MS->BTS(us) message %d\n", __func__, msgb_length(in_msg));
Holger Hans Peter Freyther15f740c2011-12-12 00:29:50 +0100261
262
263 if (state->bts_read == 0) {
264 printf("BTS: Verifying CM request.\n");
Holger Hans Peter Freytherdd34ed52013-06-19 08:16:56 +0200265 OSMO_ASSERT(msgb_l3len(in_msg) == ARRAY_SIZE(cm));
266 OSMO_ASSERT(memcmp(in_msg->l3h, cm,
267 ARRAY_SIZE(cm)) == 0);
Holger Hans Peter Freyther15f740c2011-12-12 00:29:50 +0100268 } else if (state->bts_read == 1) {
269 printf("BTS: Verifying dummy message.\n");
Katerina Barone-Adesi008e53b2013-03-03 10:36:52 +0000270 OSMO_ASSERT(msgb_l3len(in_msg) == ARRAY_SIZE(dummy1));
271 OSMO_ASSERT(memcmp(in_msg->l3h, dummy1,
272 ARRAY_SIZE(dummy1)) == 0);
Holger Hans Peter Freyther15f740c2011-12-12 00:29:50 +0100273 } else {
274 printf("BTS: Do not know to verify: %d\n", state->bts_read);
275 }
276
277 state->bts_read += 1;
Holger Hans Peter Freyther72bd4eb2011-12-11 20:25:12 +0100278 msgb_free(in_msg);
279
280 return 0;
281}
282
283static int ms_to_bts_l1_cb(struct osmo_prim_hdr *oph, void *_ctx)
284{
285 int rc;
286 struct lapdm_polling_state *state = _ctx;
287 printf("%s: MS(us) -> BTS prim message\n", __func__);
288
289 /* i stuff it into the LAPDm channel of the BTS */
290 rc = send(oph->msg, state->bts);
291 msgb_free(oph->msg);
Holger Hans Peter Freytheraf723a42012-12-26 10:51:00 +0100292 return rc;
Holger Hans Peter Freyther72bd4eb2011-12-11 20:25:12 +0100293}
294
Jacob Erlbeck2462cf62014-02-25 10:49:00 +0100295static int dequeue_prim(struct lapdm_entity *le, struct osmo_phsap_prim *pp,
296 const char *queue_name)
297{
298 int rc;
299 int l2_header_len;
300 int l3_len = 0;
301
302 /* Take message from queue */
303 rc = lapdm_phsap_dequeue_prim(le, pp);
304
305 fprintf(stderr, "dequeue: got rc %d: %s\n", rc,
306 rc <= 0 ? strerror(-rc) : "-");
307
308 if (rc < 0)
309 return rc;
310
311 l2_header_len = msgb_l2len(pp->oph.msg);
312 if (msgb_l3(pp->oph.msg)) {
313 l3_len = msgb_l3len(pp->oph.msg);
314 l2_header_len -= l3_len;
315 } else
316 fprintf(stderr, "MSGB: L3 is undefined\n");
317
318 if (l2_header_len < 0 || l2_header_len > pp->oph.msg->data_len) {
319 fprintf(stderr,
320 "MSGB inconsistent: data = %p, l2 = %p, l3 = %p, tail = %p\n",
321 pp->oph.msg->data,
322 pp->oph.msg->l2h,
323 pp->oph.msg->l3h,
324 pp->oph.msg->tail);
325 l2_header_len = -1;
326 }
327
328 printf("Took message from %s queue: "
329 "L2 header size %d, L3 size %d, "
330 "SAP %#x, %d/%d, Link 0x%02x\n",
331 queue_name,
332 l2_header_len, l3_len,
333 pp->oph.sap, pp->oph.primitive, pp->oph.operation,
334 pp->u.data.link_id);
335 printf("Message: %s\n", msgb_hexdump(pp->oph.msg));
336
337 return rc;
338}
339
Holger Hans Peter Freyther72bd4eb2011-12-11 20:25:12 +0100340static int ms_to_bts_tx_cb(struct msgb *msg, struct lapdm_entity *le, void *_ctx)
341{
342 struct lapdm_polling_state *state = _ctx;
343
344 printf("%s: BTS->MS(us) message %d\n", __func__, msgb_length(msg));
345
346 if (state->ms_read == 0) {
Holger Hans Peter Freyther15f740c2011-12-12 00:29:50 +0100347 struct abis_rsl_rll_hdr hdr;
348
349 printf("MS: Verifying incoming primitive.\n");
Katerina Barone-Adesi008e53b2013-03-03 10:36:52 +0000350 OSMO_ASSERT(msg->len == sizeof(struct abis_rsl_rll_hdr) + 3);
Holger Hans Peter Freyther15f740c2011-12-12 00:29:50 +0100351
352 /* verify the header */
353 memset(&hdr, 0, sizeof(hdr));
354 rsl_init_rll_hdr(&hdr, RSL_MT_EST_CONF);
355 hdr.c.msg_discr |= ABIS_RSL_MDISC_TRANSP;
Katerina Barone-Adesi008e53b2013-03-03 10:36:52 +0000356 OSMO_ASSERT(memcmp(msg->data, &hdr, sizeof(hdr)) == 0);
Holger Hans Peter Freyther15f740c2011-12-12 00:29:50 +0100357
358 /* Verify the added RSL_IE_L3_INFO but we have a bug here */
Katerina Barone-Adesi008e53b2013-03-03 10:36:52 +0000359 OSMO_ASSERT(msg->data[6] == RSL_IE_L3_INFO);
Holger Hans Peter Freyther4a075f82011-12-12 00:41:25 +0100360 #warning "RSL_IE_L3_INFO 16 bit length is wrong"
Holger Hans Peter Freyther3cc268c2013-06-19 08:30:59 +0200361 /* This should be okay but it is actually 0x0, 0x9c on ia-32 */
362 /* OSMO_ASSERT(msg->data[7] == 0x0 && msg->data[8] == 0x0); */
Holger Hans Peter Freyther72bd4eb2011-12-11 20:25:12 +0100363 } else if (state->ms_read == 1) {
Holger Hans Peter Freyther3a5f08c2012-01-12 23:12:28 +0100364 printf("MS: Verifying incoming MM message: %d\n", msgb_l3len(msg));
Katerina Barone-Adesi008e53b2013-03-03 10:36:52 +0000365 OSMO_ASSERT(msgb_l3len(msg) == 3);
366 OSMO_ASSERT(memcmp(msg->l3h, &mm[12], msgb_l3len(msg)) == 0);
Holger Hans Peter Freyther15f740c2011-12-12 00:29:50 +0100367 } else {
368 printf("MS: Do not know to verify: %d\n", state->ms_read);
Holger Hans Peter Freyther72bd4eb2011-12-11 20:25:12 +0100369 }
370
371 state->ms_read += 1;
372 msgb_free(msg);
373 return 0;
374}
375
376static void test_lapdm_polling()
377{
378 printf("I do some very simple LAPDm test.\n");
379
380 int rc;
381 struct lapdm_polling_state test_state;
382 struct osmo_phsap_prim pp;
383
384 /* Configure LAPDm on both sides */
385 struct lapdm_channel bts_to_ms_channel;
386 struct lapdm_channel ms_to_bts_channel;
387 memset(&bts_to_ms_channel, 0, sizeof(bts_to_ms_channel));
388 memset(&ms_to_bts_channel, 0, sizeof(ms_to_bts_channel));
389
390 memset(&test_state, 0, sizeof(test_state));
391 test_state.bts = &bts_to_ms_channel;
392 test_state.ms = &ms_to_bts_channel;
393
394 /* BTS to MS in polling mode */
395 lapdm_channel_init(&bts_to_ms_channel, LAPDM_MODE_BTS);
396 lapdm_channel_set_flags(&bts_to_ms_channel, LAPDM_ENT_F_POLLING_ONLY);
397 lapdm_channel_set_l1(&bts_to_ms_channel, NULL, &test_state);
398 lapdm_channel_set_l3(&bts_to_ms_channel, bts_to_ms_tx_cb, &test_state);
399
400 /* MS to BTS in direct mode */
401 lapdm_channel_init(&ms_to_bts_channel, LAPDM_MODE_MS);
402 lapdm_channel_set_l1(&ms_to_bts_channel, ms_to_bts_l1_cb, &test_state);
403 lapdm_channel_set_l3(&ms_to_bts_channel, ms_to_bts_tx_cb, &test_state);
404
405 /*
406 * We try to send messages from the MS to the BTS to the MS..
407 */
408 /* 1. Start with MS -> BTS, BTS should have a pending message */
409 printf("Establishing link.\n");
410 lapdm_rslms_recvmsg(create_cm_serv_req(), &ms_to_bts_channel);
411
412 /* 2. Poll on the BTS for sending out a confirmation */
413 printf("\nConfirming\n");
Katerina Barone-Adesi008e53b2013-03-03 10:36:52 +0000414 OSMO_ASSERT(test_state.bts_read == 1);
Jacob Erlbeck2462cf62014-02-25 10:49:00 +0100415 rc = dequeue_prim(&bts_to_ms_channel.lapdm_dcch, &pp, "DCCH");
Holger Hans Peter Freyther72bd4eb2011-12-11 20:25:12 +0100416 CHECK_RC(rc);
Katerina Barone-Adesi008e53b2013-03-03 10:36:52 +0000417 OSMO_ASSERT(pp.oph.msg->data == pp.oph.msg->l2h);
Holger Hans Peter Freyther72bd4eb2011-12-11 20:25:12 +0100418 send(pp.oph.msg, &ms_to_bts_channel);
419 msgb_free(pp.oph.msg);
Katerina Barone-Adesi008e53b2013-03-03 10:36:52 +0000420 OSMO_ASSERT(test_state.ms_read == 1);
Holger Hans Peter Freyther72bd4eb2011-12-11 20:25:12 +0100421
422 /* 3. Send some data to the MS */
423 printf("\nSending back to MS\n");
424 lapdm_rslms_recvmsg(create_mm_id_req(), &bts_to_ms_channel);
Jacob Erlbeck2462cf62014-02-25 10:49:00 +0100425 rc = dequeue_prim(&bts_to_ms_channel.lapdm_dcch, &pp, "DCCH");
Holger Hans Peter Freyther72bd4eb2011-12-11 20:25:12 +0100426 CHECK_RC(rc);
427 send(pp.oph.msg, &ms_to_bts_channel);
428 msgb_free(pp.oph.msg);
Katerina Barone-Adesi008e53b2013-03-03 10:36:52 +0000429 OSMO_ASSERT(test_state.ms_read == 2);
Holger Hans Peter Freyther72bd4eb2011-12-11 20:25:12 +0100430
431 /* verify that there is nothing more to poll */
Jacob Erlbeck2462cf62014-02-25 10:49:00 +0100432 rc = dequeue_prim(&bts_to_ms_channel.lapdm_dcch, &pp, "DCCH");
Katerina Barone-Adesi008e53b2013-03-03 10:36:52 +0000433 OSMO_ASSERT(rc < 0);
Holger Hans Peter Freyther72bd4eb2011-12-11 20:25:12 +0100434
435 /* 3. And back to the BTS */
436 printf("\nSending back to BTS\n");
Katerina Barone-Adesi008e53b2013-03-03 10:36:52 +0000437 OSMO_ASSERT(test_state.ms_read == 2);
Holger Hans Peter Freyther72bd4eb2011-12-11 20:25:12 +0100438 lapdm_rslms_recvmsg(create_dummy_data_req(), &ms_to_bts_channel);
439
440
Holger Hans Peter Freyther3a5f08c2012-01-12 23:12:28 +0100441 /* 4. And back to the MS, but let's move data/l2h apart */
Katerina Barone-Adesi008e53b2013-03-03 10:36:52 +0000442 OSMO_ASSERT(test_state.bts_read == 2);
443 OSMO_ASSERT(test_state.ms_read == 2);
Jacob Erlbeck2462cf62014-02-25 10:49:00 +0100444 rc = dequeue_prim(&bts_to_ms_channel.lapdm_dcch, &pp, "DCCH");
Holger Hans Peter Freyther72bd4eb2011-12-11 20:25:12 +0100445 CHECK_RC(rc);
446 send(pp.oph.msg, &ms_to_bts_channel);
Katerina Barone-Adesi008e53b2013-03-03 10:36:52 +0000447 OSMO_ASSERT(test_state.ms_read == 2);
Holger Hans Peter Freyther72bd4eb2011-12-11 20:25:12 +0100448 msgb_free(pp.oph.msg);
449
450 /* verify that there is nothing more to poll */
Jacob Erlbeck2462cf62014-02-25 10:49:00 +0100451 rc = dequeue_prim(&bts_to_ms_channel.lapdm_dcch, &pp, "DCCH");
Katerina Barone-Adesi008e53b2013-03-03 10:36:52 +0000452 OSMO_ASSERT(rc < 0);
Jacob Erlbeck7d5f17a2014-02-28 15:54:03 +0100453 rc = dequeue_prim(&bts_to_ms_channel.lapdm_acch, &pp, "ACCH");
454 OSMO_ASSERT(rc < 0);
Holger Hans Peter Freyther72bd4eb2011-12-11 20:25:12 +0100455
Holger Hans Peter Freyther90656db2012-01-13 05:49:29 +0800456 /* check sending an empty L3 message fails */
457 rc = lapdm_rslms_recvmsg(create_empty_msg(), &bts_to_ms_channel);
Katerina Barone-Adesi008e53b2013-03-03 10:36:52 +0000458 OSMO_ASSERT(rc == -1);
459 OSMO_ASSERT(test_state.ms_read == 2);
Holger Hans Peter Freyther90656db2012-01-13 05:49:29 +0800460
Holger Hans Peter Freyther72bd4eb2011-12-11 20:25:12 +0100461 /* clean up */
462 lapdm_channel_exit(&bts_to_ms_channel);
463 lapdm_channel_exit(&ms_to_bts_channel);
Holger Hans Peter Freytherce397de2013-10-26 13:35:15 +0200464
465 /* Check if exit is idempotent */
466 lapdm_channel_exit(&bts_to_ms_channel);
467 lapdm_channel_exit(&ms_to_bts_channel);
Holger Hans Peter Freyther72bd4eb2011-12-11 20:25:12 +0100468}
469
Andreas Eversberg6e182082013-02-06 14:13:21 +0100470static void test_lapdm_contention_resolution()
471{
472 printf("I test contention resultion by having two mobiles collide and "
473 "first mobile repeating SABM.\n");
474
475 int rc;
476 struct lapdm_polling_state test_state;
477 struct osmo_phsap_prim pp;
Daniel Willmann09129352014-03-20 18:54:57 +0100478 uint8_t *cm2;
Andreas Eversberg6e182082013-02-06 14:13:21 +0100479
480 /* Configure LAPDm on both sides */
481 struct lapdm_channel bts_to_ms_channel;
482 memset(&bts_to_ms_channel, 0, sizeof(bts_to_ms_channel));
483
484 memset(&test_state, 0, sizeof(test_state));
485 test_state.bts = &bts_to_ms_channel;
486
487 /* BTS to MS in polling mode */
488 lapdm_channel_init(&bts_to_ms_channel, LAPDM_MODE_BTS);
489 lapdm_channel_set_flags(&bts_to_ms_channel, LAPDM_ENT_F_POLLING_ONLY);
490 lapdm_channel_set_l1(&bts_to_ms_channel, NULL, &test_state);
491 lapdm_channel_set_l3(&bts_to_ms_channel, bts_to_ms_tx_cb, &test_state);
492
493 /* Send SABM MS 1, we must get UA */
Daniel Willmann09129352014-03-20 18:54:57 +0100494 send_sabm(&bts_to_ms_channel, 0, cm, sizeof(cm));
Jacob Erlbeck2462cf62014-02-25 10:49:00 +0100495 rc = dequeue_prim(&bts_to_ms_channel.lapdm_dcch, &pp, "DCCH");
Andreas Eversberg6e182082013-02-06 14:13:21 +0100496 CHECK_RC(rc);
497 OSMO_ASSERT(memcmp(pp.oph.msg->l2h, ua, ARRAY_SIZE(ua)) == 0);
498
499 /* Send SABM MS 2, we must get nothing, due to collision */
Daniel Willmann09129352014-03-20 18:54:57 +0100500 cm2 = malloc(sizeof(cm));
501 memcpy(cm2, cm, sizeof(cm));
502 cm2[0] += 1;
503 send_sabm(&bts_to_ms_channel, 0, cm2, sizeof(cm2));
504 free(cm2);
Jacob Erlbeck2462cf62014-02-25 10:49:00 +0100505 rc = dequeue_prim(&bts_to_ms_channel.lapdm_dcch, &pp, "DCCH");
Andreas Eversberg6e182082013-02-06 14:13:21 +0100506 OSMO_ASSERT(rc == -ENODEV);
507
508 /* Send SABM MS 1 again, we must get UA gain */
Daniel Willmann09129352014-03-20 18:54:57 +0100509 send_sabm(&bts_to_ms_channel, 0, cm, sizeof(cm));
Jacob Erlbeck2462cf62014-02-25 10:49:00 +0100510 rc = dequeue_prim(&bts_to_ms_channel.lapdm_dcch, &pp, "DCCH");
Andreas Eversberg6e182082013-02-06 14:13:21 +0100511 CHECK_RC(rc);
512 OSMO_ASSERT(memcmp(pp.oph.msg->l2h, ua, ARRAY_SIZE(ua)) == 0);
513
514 /* clean up */
515 lapdm_channel_exit(&bts_to_ms_channel);
Holger Hans Peter Freytherce397de2013-10-26 13:35:15 +0200516
517 /* idempotent */
518 lapdm_channel_exit(&bts_to_ms_channel);
Andreas Eversberg6e182082013-02-06 14:13:21 +0100519}
520
Jacob Erlbeck90937fe2014-01-24 13:48:19 +0100521static void test_lapdm_early_release()
522{
523 printf("I test RF channel release of an unestablished channel.\n");
524
525 int rc;
526 struct lapdm_polling_state test_state;
527
528 /* Configure LAPDm on both sides */
529 struct lapdm_channel bts_to_ms_channel;
530 memset(&bts_to_ms_channel, 0, sizeof(bts_to_ms_channel));
531
532 memset(&test_state, 0, sizeof(test_state));
533 test_state.bts = &bts_to_ms_channel;
534
535 /* BTS to MS in polling mode */
536 lapdm_channel_init(&bts_to_ms_channel, LAPDM_MODE_BTS);
537 lapdm_channel_set_flags(&bts_to_ms_channel, LAPDM_ENT_F_POLLING_ONLY);
538 lapdm_channel_set_l1(&bts_to_ms_channel, NULL, &test_state);
539 lapdm_channel_set_l3(&bts_to_ms_channel, bts_to_ms_tx_cb, &test_state);
540
541 /* Send the release request */
542 rc = lapdm_rslms_recvmsg(create_rel_req(), &bts_to_ms_channel);
543 OSMO_ASSERT(rc == -EINVAL);
544
545 /* clean up */
546 lapdm_channel_exit(&bts_to_ms_channel);
547
548 /* Check if exit is idempotent */
549 lapdm_channel_exit(&bts_to_ms_channel);
550}
551
552static void lapdm_establish(const uint8_t *est_req, size_t est_req_size)
553{
554 int rc;
555 struct lapdm_polling_state test_state;
556 struct osmo_phsap_prim pp;
557 struct msgb *msg;
Jacob Erlbeck90937fe2014-01-24 13:48:19 +0100558
559 /* Configure LAPDm on both sides */
560 struct lapdm_channel bts_to_ms_channel;
561 memset(&bts_to_ms_channel, 0, sizeof(bts_to_ms_channel));
562
563 memset(&test_state, 0, sizeof(test_state));
564 test_state.bts = &bts_to_ms_channel;
565
566 /* BTS to MS in polling mode */
567 lapdm_channel_init(&bts_to_ms_channel, LAPDM_MODE_BTS);
568 lapdm_channel_set_flags(&bts_to_ms_channel, LAPDM_ENT_F_POLLING_ONLY);
569 lapdm_channel_set_l1(&bts_to_ms_channel, NULL, &test_state);
570 lapdm_channel_set_l3(&bts_to_ms_channel, bts_to_ms_tx_cb, &test_state);
571
572 /* Send the release request */
573 msg = create_est_req(est_req, est_req_size);
574 rc = lapdm_rslms_recvmsg(msg, &bts_to_ms_channel);
575 fprintf(stderr, "recvmsg: got rc %d: %s\n", rc, rc <= 0 ? strerror(-rc) : "???");
576 OSMO_ASSERT(rc == 0);
577
578 /* Take message from queue */
Jacob Erlbeck2462cf62014-02-25 10:49:00 +0100579 rc = dequeue_prim(&bts_to_ms_channel.lapdm_dcch, &pp, "DCCH");
580 if (rc < 0)
581 rc = dequeue_prim(&bts_to_ms_channel.lapdm_acch, &pp, "ACCH");
Jacob Erlbeck90937fe2014-01-24 13:48:19 +0100582
Jacob Erlbeck90937fe2014-01-24 13:48:19 +0100583 CHECK_RC(rc);
584
Jacob Erlbeck90937fe2014-01-24 13:48:19 +0100585 OSMO_ASSERT(pp.oph.msg->data == msgb_l2(pp.oph.msg));
586
Jacob Erlbeck2462cf62014-02-25 10:49:00 +0100587 rc = dequeue_prim(&bts_to_ms_channel.lapdm_dcch, &pp, "DCCH");
Jacob Erlbeck90937fe2014-01-24 13:48:19 +0100588 OSMO_ASSERT(rc < 0);
Jacob Erlbeck2462cf62014-02-25 10:49:00 +0100589 rc = dequeue_prim(&bts_to_ms_channel.lapdm_acch, &pp, "ACCH");
Jacob Erlbeck90937fe2014-01-24 13:48:19 +0100590 OSMO_ASSERT(rc < 0);
591
592 /* clean up */
593 lapdm_channel_exit(&bts_to_ms_channel);
594
595 /* idempotent */
596 lapdm_channel_exit(&bts_to_ms_channel);
597}
598
599static void test_lapdm_establishment()
600{
601 printf("I test RF channel establishment.\n");
602 printf("Testing SAPI3/SDCCH\n");
603 lapdm_establish(est_req_sdcch_sapi3, sizeof(est_req_sdcch_sapi3));
604 printf("Testing SAPI3/SACCH\n");
605 lapdm_establish(est_req_sacch_sapi3, sizeof(est_req_sacch_sapi3));
606}
607
Daniel Willmann09129352014-03-20 18:54:57 +0100608
609const uint8_t cm_chg[] = {
610 0x01, 0x00, 0x49, 0x06, 0x16, 0x03, 0x33,
611 0x59, 0xa6, 0x20, 0x0a, 0x20, 0x04, 0x04,
612 0x2f, 0x65, 0x23, 0x02, 0x00, 0x24, 0x04
613};
614
615const uint8_t cm_chg_ack[] = {
616 0x01, 0x21, 0x01
617};
618
619const uint8_t gprs_susp[] = {
620 0x01, 0x02, 0x35, 0x06, 0x34, 0xe3, 0xd4,
621 0xd2, 0x6f, 0x09, 0xf1, 0x07, 0x00, 0x01, 0x00, 0x02
622};
623
624const uint8_t gprs_susp_ack[] = {
625 0x01, 0x41, 0x01
626};
627
628const uint8_t cipher_cmd[] = {
629 0x06, 0x35, 0x01
630};
631
632/* The cipher command we send to the MS */
633const uint8_t cipher_cmd_out[] = {
634 0x03, 0x20, 0x0d, 0x06, 0x35, 0x01
635};
636
637uint8_t cipher_compl[] = {
638 0x01, 0x24, 0x09, 0x06, 0x32
639};
640
641uint8_t cipher_compl_ack[] = {
642 0x01, 0x61, 0x01
643};
644
645static const uint8_t ua_sms[] = {
646 0x0d, 0x73, 0x01
647};
648
649const uint8_t cp_data_1[] = {
650 0x0d, 0x00, 0x53, 0x59, 0x01, 0x5c, 0x00,
651 0x4c, 0x00, 0x06, 0x91, 0x86, 0x77, 0x07,
652 0x00, 0xf9, 0x51, 0x11, 0x76, 0x05, 0x81, 0x29, 0x32
653};
654
655const uint8_t cp_data_1_ack[] = {
656 0x0d, 0x21, 0x01
657};
658
659static int bts_to_ms_dummy_tx_cb(struct msgb *in_msg, struct lapdm_entity *le, void *_ctx)
660{
661 printf("%s: MS->BTS(us) message %d\n", __func__, msgb_length(in_msg));
662 msgb_free(in_msg);
663
664 return 0;
665}
666
667static void dump_queue(struct llist_head *head)
668{
669 struct msgb* msg;
670
671 printf("\nDumping queue:\n");
672 llist_for_each_entry(msg, head, list)
673 printf("%s\n", msgb_hexdump(msg));
674 printf("\n");
675}
676
677static void test_lapdm_desync()
678{
679 printf("I test if desync problems exist in LAPDm\n");
680
681 int rc;
682 struct osmo_phsap_prim pp;
683
684 /* Configure LAPDm on both sides */
685 struct lapdm_channel bts_to_ms_channel;
686 memset(&bts_to_ms_channel, 0, sizeof(bts_to_ms_channel));
687
688 /* BTS to MS in polling mode */
689 lapdm_channel_init(&bts_to_ms_channel, LAPDM_MODE_BTS);
690 lapdm_channel_set_flags(&bts_to_ms_channel, LAPDM_ENT_F_POLLING_ONLY);
691 lapdm_channel_set_l1(&bts_to_ms_channel, NULL, NULL);
692 lapdm_channel_set_l3(&bts_to_ms_channel, bts_to_ms_dummy_tx_cb, NULL);
693 struct lapdm_datalink *dl = lapdm_datalink_for_sapi(&bts_to_ms_channel.lapdm_dcch, 0);
694 dl->mctx.dl = dl;
695 dl->dl.lctx.dl = &dl->dl;
696
697 /* Send SABM MS 1, we must get UA */
698 printf("\nEstablishing SAPI=0\n");
699 send_sabm(&bts_to_ms_channel, 0, cm, sizeof(cm));
700
701 dump_queue(&dl->dl.tx_queue);
702
703 rc = dequeue_prim(&bts_to_ms_channel.lapdm_dcch, &pp, "DCCH");
704 CHECK_RC(rc);
705 OSMO_ASSERT(memcmp(pp.oph.msg->l2h, ua, ARRAY_SIZE(ua)) == 0);
706
707 printf("\nSending Classmark Change\n");
708 send_buf(cm_chg, sizeof(cm_chg), &bts_to_ms_channel);
709 dump_queue(&dl->dl.tx_queue);
710
711 rc = dequeue_prim(&bts_to_ms_channel.lapdm_dcch, &pp, "DCCH");
712 CHECK_RC(rc);
713 OSMO_ASSERT(memcmp(pp.oph.msg->l2h, cm_chg_ack, ARRAY_SIZE(cm_chg_ack)) == 0);
714
715 printf("\nEnqueueing Ciphering Mode Command\n");
716 enqueue_buf(cipher_cmd, sizeof(cipher_cmd), 0, &bts_to_ms_channel);
717 dump_queue(&dl->dl.tx_queue);
718
719 printf("\nSending GPRS Suspend Request\n");
720 send_buf(gprs_susp, sizeof(gprs_susp), &bts_to_ms_channel);
721 dump_queue(&dl->dl.tx_queue);
722
723 rc = dequeue_prim(&bts_to_ms_channel.lapdm_dcch, &pp, "DCCH");
724 CHECK_RC(rc);
725 OSMO_ASSERT(memcmp(pp.oph.msg->l2h, cipher_cmd_out, ARRAY_SIZE(cipher_cmd_out)) == 0);
726
727 printf("\nSending Cipher Mode Complete\n");
728 send_buf(cipher_compl, sizeof(cipher_compl), &bts_to_ms_channel);
729 dump_queue(&dl->dl.tx_queue);
730
731 rc = dequeue_prim(&bts_to_ms_channel.lapdm_dcch, &pp, "DCCH");
732 CHECK_RC(rc);
733 OSMO_ASSERT(memcmp(pp.oph.msg->l2h, gprs_susp_ack, ARRAY_SIZE(gprs_susp_ack)) == 0);
734
735 printf("\nEstablishing SAPI=3\n");
736 send_sabm(&bts_to_ms_channel, 3, NULL, 0);
737 dump_queue(&dl->dl.tx_queue);
738
739 rc = dequeue_prim(&bts_to_ms_channel.lapdm_dcch, &pp, "DCCH");
740 CHECK_RC(rc);
741 OSMO_ASSERT(memcmp(pp.oph.msg->l2h, ua_sms, ARRAY_SIZE(ua_sms)) == 0);
742
743 printf("\nSending CP-DATA\n");
744 send_buf(cp_data_1, sizeof(cp_data_1), &bts_to_ms_channel);
745 dump_queue(&dl->dl.tx_queue);
746
747 rc = dequeue_prim(&bts_to_ms_channel.lapdm_dcch, &pp, "DCCH");
748 CHECK_RC(rc);
749 OSMO_ASSERT(memcmp(pp.oph.msg->l2h, cipher_compl_ack, ARRAY_SIZE(cipher_compl_ack)) == 0);
750
751 /* clean up */
752 lapdm_channel_exit(&bts_to_ms_channel);
753
754 /* Check if exit is idempotent */
755 lapdm_channel_exit(&bts_to_ms_channel);
756}
757
Holger Hans Peter Freyther72bd4eb2011-12-11 20:25:12 +0100758int main(int argc, char **argv)
759{
760 osmo_init_logging(&info);
761
Jacob Erlbeckc893c222014-01-28 10:53:59 +0100762 /* Prevent the test from segfaulting */
763 dummy_l1_header_len = 0;
Holger Hans Peter Freyther72bd4eb2011-12-11 20:25:12 +0100764 test_lapdm_polling();
Jacob Erlbeckc893c222014-01-28 10:53:59 +0100765
766 dummy_l1_header_len = 3;
Daniel Willmanne5233922012-12-25 23:15:50 +0100767 test_lapdm_early_release();
Andreas Eversberg6e182082013-02-06 14:13:21 +0100768 test_lapdm_contention_resolution();
Jacob Erlbeck90937fe2014-01-24 13:48:19 +0100769 test_lapdm_establishment();
Daniel Willmann09129352014-03-20 18:54:57 +0100770 test_lapdm_desync();
Jacob Erlbeckc893c222014-01-28 10:53:59 +0100771
Holger Hans Peter Freyther72bd4eb2011-12-11 20:25:12 +0100772 printf("Success.\n");
773
774 return 0;
775}