blob: cc1b2f1f84f2c08aa11ac42734ce5ed9f60e5c10 [file] [log] [blame]
Alexander Couzens1c8785d2020-12-17 06:58:53 +01001/* test routines for NS connection handling
2 * (C) 2020 sysmocom - s.f.m.c. GmbH
3 * Author: Alexander Couzens <lynxis@fe80.eu>
4 *
5 * SPDX-License-Identifier: GPL-2.0+
6 */
7
8#undef _GNU_SOURCE
9#define _GNU_SOURCE
10
11#include <stdio.h>
12#include <stdlib.h>
13#include <unistd.h>
14#include <stdint.h>
15#include <string.h>
16#include <getopt.h>
17#include <dlfcn.h>
18#include <sys/types.h>
19#include <sys/socket.h>
20
21#include <osmocom/core/fsm.h>
22#include <osmocom/core/msgb.h>
Alexander Couzens47afc422021-01-17 20:12:46 +010023#include <osmocom/core/utils.h>
Alexander Couzens1c8785d2020-12-17 06:58:53 +010024#include <osmocom/core/application.h>
25#include <osmocom/core/utils.h>
26#include <osmocom/core/logging.h>
27#include <osmocom/core/socket.h>
28#include <osmocom/core/talloc.h>
29#include <osmocom/core/write_queue.h>
30#include <osmocom/gprs/gprs_msgb.h>
31#include <osmocom/gprs/gprs_ns2.h>
32#include <osmocom/gprs/gprs_bssgp.h>
33
34#include "../../src/gb/gprs_ns2_internal.h"
35
36int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
37{
38 return -1;
39}
40
41static struct log_info info = {};
Alexander Couzens8f215c92021-01-25 15:27:56 +010042static struct osmo_wqueue *unitdata = NULL;
Alexander Couzens4f1128f2021-01-20 17:42:48 +010043static struct osmo_gprs_ns2_prim last_nse_recovery = {};
Alexander Couzens1c8785d2020-12-17 06:58:53 +010044
45static int ns_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
46{
Alexander Couzens4f1128f2021-01-20 17:42:48 +010047 struct osmo_gprs_ns2_prim *nsp;
Alexander Couzens8f215c92021-01-25 15:27:56 +010048 OSMO_ASSERT(oph->sap == SAP_NS);
Alexander Couzens4f1128f2021-01-20 17:42:48 +010049 nsp = container_of(oph, struct osmo_gprs_ns2_prim, oph);
Alexander Couzens8f215c92021-01-25 15:27:56 +010050 if (oph->msg) {
Alexander Couzens138b96f2021-01-25 16:23:29 +010051 if (oph->primitive == GPRS_NS2_PRIM_UNIT_DATA) {
Alexander Couzens8f215c92021-01-25 15:27:56 +010052 osmo_wqueue_enqueue(unitdata, oph->msg);
53 } else {
54 msgb_free(oph->msg);
55 }
56 }
Alexander Couzens4f1128f2021-01-20 17:42:48 +010057 if (oph->primitive == GPRS_NS2_PRIM_STATUS && nsp->u.status.cause == GPRS_NS2_AFF_CAUSE_RECOVERY) {
58 last_nse_recovery = *nsp;
59 }
Alexander Couzens1c8785d2020-12-17 06:58:53 +010060 return 0;
61}
62
Alexander Couzensd8a8d982021-02-15 01:07:45 +010063static int gp_send_to_ns(struct gprs_ns2_inst *nsi, struct msgb *msg, uint16_t nsei, uint16_t bvci, uint32_t lsp)
64{
65 struct osmo_gprs_ns2_prim nsp = {};
66 nsp.nsei = nsei;
67 nsp.bvci = bvci;
68 nsp.u.unitdata.link_selector = lsp;
69 osmo_prim_init(&nsp.oph, SAP_NS, GPRS_NS2_PRIM_UNIT_DATA,
70 PRIM_OP_REQUEST, msg);
71 return gprs_ns2_recv_prim(nsi, &nsp.oph);
72}
73
74
Alexander Couzens47afc422021-01-17 20:12:46 +010075static struct msgb *get_pdu(struct gprs_ns2_vc_bind *bind, enum ns_pdu_type pdu_type)
76{
77 struct gprs_ns_hdr *nsh;
78 struct osmo_wqueue *queue = bind->priv;
79
80 while (!llist_empty(&queue->msg_queue)) {
81 struct msgb *msg = msgb_dequeue(&queue->msg_queue);
82 nsh = (struct gprs_ns_hdr *) msg->l2h;
83 if (nsh->pdu_type == pdu_type)
84 return msg;
85 msgb_free(msg);
86 }
87
88 return NULL;
89}
90
91static bool find_pdu(struct gprs_ns2_vc_bind *bind, enum ns_pdu_type pdu_type)
92{
93 struct msgb *msg;
94 msg = get_pdu(bind, pdu_type);
95 if (msg) {
96 msgb_free(msg);
97 return true;
98 }
99
100 return false;
101}
102
Alexander Couzensd8a8d982021-02-15 01:07:45 +0100103static unsigned int count_pdus(struct gprs_ns2_vc_bind *bind)
104{
105 struct osmo_wqueue *queue = bind->priv;
106 return llist_count(&queue->msg_queue);
107}
108
Alexander Couzensaf5bfeb2021-01-17 20:12:37 +0100109static void clear_pdus(struct gprs_ns2_vc_bind *bind)
Alexander Couzens1c8785d2020-12-17 06:58:53 +0100110{
Alexander Couzensaf5bfeb2021-01-17 20:12:37 +0100111 struct osmo_wqueue *queue = bind->priv;
112 osmo_wqueue_clear(queue);
Alexander Couzens1c8785d2020-12-17 06:58:53 +0100113}
114
115struct gprs_ns2_vc_driver vc_driver_dummy = {
116 .name = "GB UDP dummy",
Alexander Couzensaf5bfeb2021-01-17 20:12:37 +0100117 .free_bind = clear_pdus,
Alexander Couzens1c8785d2020-12-17 06:58:53 +0100118};
119
120static int vc_sendmsg(struct gprs_ns2_vc *nsvc, struct msgb *msg)
121{
122 struct gprs_ns2_vc_bind *bind = nsvc->bind;
123 struct osmo_wqueue *queue = bind->priv;
124
125 osmo_wqueue_enqueue(queue, msg);
126 return 0;
127}
128
129static struct gprs_ns2_vc_bind *dummy_bind(struct gprs_ns2_inst *nsi, const char *name)
130{
Harald Weltec3aa8f92021-01-31 11:41:34 +0100131 struct gprs_ns2_vc_bind *bind = NULL;
132 OSMO_ASSERT(ns2_bind_alloc(nsi, name, &bind) == 0);
Alexander Couzens1c8785d2020-12-17 06:58:53 +0100133 OSMO_ASSERT(bind);
134
Alexander Couzens1c8785d2020-12-17 06:58:53 +0100135 bind->driver = &vc_driver_dummy;
136 bind->ll = GPRS_NS2_LL_UDP;
137 bind->transfer_capability = 42;
Alexander Couzens1c8785d2020-12-17 06:58:53 +0100138 bind->send_vc = vc_sendmsg;
139 bind->priv = talloc_zero(bind, struct osmo_wqueue);
Alexander Couzens4f1128f2021-01-20 17:42:48 +0100140 bind->mtu = 123;
Alexander Couzens1c8785d2020-12-17 06:58:53 +0100141 struct osmo_wqueue *queue = bind->priv;
142
Alexander Couzens1c8785d2020-12-17 06:58:53 +0100143 osmo_wqueue_init(queue, 100);
144
145 return bind;
146}
147
Alexander Couzens8f215c92021-01-25 15:27:56 +0100148static void free_loopback(struct gprs_ns2_vc_bind *bind) {}
149
150struct gprs_ns2_vc_driver vc_driver_loopback = {
151 .name = "loopback dummy",
152 .free_bind = free_loopback,
153};
154
155/* loopback the msg */
156static int loopback_sendmsg(struct gprs_ns2_vc *nsvc, struct msgb *msg)
157{
158 struct gprs_ns2_vc *target = nsvc->priv;
159 return ns2_recv_vc(target, msg);
160}
161
162/* create a loopback nsvc object which can be used with ns2_tx_* functions. it's not fully registered etc. */
163static struct gprs_ns2_vc *loopback_nsvc(struct gprs_ns2_vc_bind *bind, struct gprs_ns2_vc *target)
164{
165 struct gprs_ns2_vc *nsvc = talloc_zero(bind, struct gprs_ns2_vc);
166 memcpy(nsvc, target, sizeof(struct gprs_ns2_vc));
167 nsvc->bind = bind;
168 nsvc->priv = target;
169 return nsvc;
170}
171
172/* a loop back bind to use the tx_ functions from gprs_ns2_message.c */
173static struct gprs_ns2_vc_bind *loopback_bind(struct gprs_ns2_inst *nsi, const char *name)
174{
Harald Weltec3aa8f92021-01-31 11:41:34 +0100175 struct gprs_ns2_vc_bind *bind = NULL;
176 OSMO_ASSERT(ns2_bind_alloc(nsi, name, &bind) == 0)
Alexander Couzens8f215c92021-01-25 15:27:56 +0100177 OSMO_ASSERT(bind);
Alexander Couzens8f215c92021-01-25 15:27:56 +0100178 bind->driver = &vc_driver_loopback;
179 bind->ll = GPRS_NS2_LL_UDP;
180 bind->transfer_capability = 99;
Alexander Couzens8f215c92021-01-25 15:27:56 +0100181 bind->send_vc = loopback_sendmsg;
Alexander Couzens4f1128f2021-01-20 17:42:48 +0100182 bind->mtu = 123;
Alexander Couzens8f215c92021-01-25 15:27:56 +0100183 return bind;
184}
185
Alexander Couzens1c8785d2020-12-17 06:58:53 +0100186void test_nse_transfer_cap(void *ctx)
187{
188 struct gprs_ns2_inst *nsi;
189 struct gprs_ns2_vc_bind *bind[2];
190 struct gprs_ns2_nse *nse;
191 struct gprs_ns2_vc *nsvc[3];
192
193 /* create a UDP dummy bind[0] with transfer cap 42.
194 * create nse (nsei 1001)
195 * create 2x nsvc with the same bind.
196 * nsvc[0] or nsvc[1] is alive (or both) cap == 42
197 *
198 * create a second bind with transfer cap == 23
199 * create 3rd nsvc with bind[1]
200 * transfer cap should be 42 + 23
201 */
202
203 printf("--- Testing NSE transfer cap\n");
204
205 printf("---- Create NSE + Binds\n");
206 nsi = gprs_ns2_instantiate(ctx, ns_prim_cb, NULL);
207 bind[0] = dummy_bind(nsi, "transfercap1");
208 bind[1] = dummy_bind(nsi, "transfercap2");
209 bind[1]->transfer_capability = 23;
Alexander Couzens138b96f2021-01-25 16:23:29 +0100210 nse = gprs_ns2_create_nse(nsi, 1001, GPRS_NS2_LL_UDP, GPRS_NS2_DIALECT_STATIC_ALIVE);
Alexander Couzens1c8785d2020-12-17 06:58:53 +0100211 OSMO_ASSERT(nse);
212
213 printf("---- Test with NSVC[0]\n");
Alexander Couzens138b96f2021-01-25 16:23:29 +0100214 nsvc[0] = ns2_vc_alloc(bind[0], nse, false, GPRS_NS2_VC_MODE_ALIVE, NULL);
Alexander Couzens1c8785d2020-12-17 06:58:53 +0100215 OSMO_ASSERT(nsvc[0]);
216 OSMO_ASSERT(ns2_count_transfer_cap(nse, 0) == 0);
217 nsvc[0]->fi->state = 3; /* HACK: 3 = GPRS_NS2_ST_UNBLOCKED */
218 ns2_nse_notify_unblocked(nsvc[0], true);
219 OSMO_ASSERT(ns2_count_transfer_cap(nse, 0) == 42);
220
221 printf("---- Test with NSVC[1]\n");
Alexander Couzens138b96f2021-01-25 16:23:29 +0100222 nsvc[1] = ns2_vc_alloc(bind[0], nse, false, GPRS_NS2_VC_MODE_ALIVE, NULL);
Alexander Couzens1c8785d2020-12-17 06:58:53 +0100223 OSMO_ASSERT(nsvc[1]);
224 OSMO_ASSERT(ns2_count_transfer_cap(nse, 0) == 42);
225 nsvc[1]->fi->state = 3; /* HACK: 3 = GPRS_NS2_ST_UNBLOCKED */
226 ns2_nse_notify_unblocked(nsvc[1], true);
227 OSMO_ASSERT(ns2_count_transfer_cap(nse, 0) == 42);
228
229 printf("---- Test with NSVC[2]\n");
Alexander Couzens138b96f2021-01-25 16:23:29 +0100230 nsvc[2] = ns2_vc_alloc(bind[1], nse, false, GPRS_NS2_VC_MODE_ALIVE, NULL);
Alexander Couzens1c8785d2020-12-17 06:58:53 +0100231 OSMO_ASSERT(nsvc[2]);
232 OSMO_ASSERT(ns2_count_transfer_cap(nse, 0) == 42);
233 nsvc[2]->fi->state = 3; /* HACK: 3 = GPRS_NS2_ST_UNBLOCKED */
234 ns2_nse_notify_unblocked(nsvc[2], true);
235 OSMO_ASSERT(ns2_count_transfer_cap(nse, 0) == 42 + 23);
236
237 printf("---- Test with NSVC[1] removed\n");
238 /* reset nsvc[1] to be unconfigured - shouldn't change anything */
239 nsvc[1]->fi->state = 0; /* HACK: 0 = GPRS_NS2_ST_UNCONFIGURED */
240 ns2_nse_notify_unblocked(nsvc[1], false);
241 OSMO_ASSERT(ns2_count_transfer_cap(nse, 0) == 42 + 23);
242
Alexander Couzensaca31b82021-01-17 20:15:20 +0100243 gprs_ns2_free(nsi);
Alexander Couzens1c8785d2020-12-17 06:58:53 +0100244 printf("--- Finish NSE transfer cap\n");
245
246}
247
Alexander Couzens47afc422021-01-17 20:12:46 +0100248/* setup NSE with 2x NSVCs.
249 * block 1x NSVC
250 * unblock 1x NSVC*/
251void test_block_unblock_nsvc(void *ctx)
252{
253 struct gprs_ns2_inst *nsi;
254 struct gprs_ns2_vc_bind *bind[2];
255 struct gprs_ns2_nse *nse;
256 struct gprs_ns2_vc *nsvc[2];
257 struct gprs_ns_hdr *nsh;
258 struct msgb *msg;
259 char idbuf[32];
Harald Welte2846ee22021-01-21 10:22:09 +0100260 int i;
Alexander Couzens47afc422021-01-17 20:12:46 +0100261
262 printf("--- Testing NSE block unblock nsvc\n");
263 printf("---- Create NSE + Binds\n");
264 nsi = gprs_ns2_instantiate(ctx, ns_prim_cb, NULL);
265 bind[0] = dummy_bind(nsi, "bblock1");
266 bind[1] = dummy_bind(nsi, "bblock2");
Alexander Couzens138b96f2021-01-25 16:23:29 +0100267 nse = gprs_ns2_create_nse(nsi, 1001, GPRS_NS2_LL_UDP, GPRS_NS2_DIALECT_STATIC_RESETBLOCK);
Alexander Couzens47afc422021-01-17 20:12:46 +0100268 OSMO_ASSERT(nse);
269
Harald Welte2846ee22021-01-21 10:22:09 +0100270 for (i=0; i<2; i++) {
Alexander Couzens47afc422021-01-17 20:12:46 +0100271 printf("---- Create NSVC[i]\n");
272 snprintf(idbuf, sizeof(idbuf), "NSE%05u-dummy-%i", nse->nsei, i);
Alexander Couzens138b96f2021-01-25 16:23:29 +0100273 nsvc[i] = ns2_vc_alloc(bind[i], nse, false, GPRS_NS2_VC_MODE_BLOCKRESET, idbuf);
Alexander Couzens47afc422021-01-17 20:12:46 +0100274 OSMO_ASSERT(nsvc[i]);
275 nsvc[i]->fi->state = 3; /* HACK: 3 = GPRS_NS2_ST_UNBLOCKED */
276 /* ensure the fi->state works correct */
Alexander Couzens8dfc24c2021-01-25 16:09:23 +0100277 OSMO_ASSERT(ns2_vc_is_unblocked(nsvc[i]));
Alexander Couzens47afc422021-01-17 20:12:46 +0100278 ns2_nse_notify_unblocked(nsvc[i], true);
279 }
280
281 /* both nsvcs are unblocked and alive. Let's block it. */
282 OSMO_ASSERT(!find_pdu(bind[0], NS_PDUT_BLOCK));
283 clear_pdus(bind[0]);
284 ns2_vc_block(nsvc[0]);
285 OSMO_ASSERT(find_pdu(bind[0], NS_PDUT_BLOCK));
286 /* state == BLOCKED */
287 clear_pdus(bind[0]);
288
289 /* now unblocking it */
290 ns2_vc_unblock(nsvc[0]);
291 OSMO_ASSERT(find_pdu(bind[0], NS_PDUT_UNBLOCK));
292 clear_pdus(bind[0]);
293
294 msg = msgb_alloc_headroom(NS_ALLOC_SIZE, NS_ALLOC_HEADROOM, "test_unblock");
295 msg->l2h = msgb_put(msg, sizeof(*nsh));
296 nsh = (struct gprs_ns_hdr *) msg->l2h;
297 nsh->pdu_type = NS_PDUT_UNBLOCK_ACK;
298 ns2_recv_vc(nsvc[0], msg);
299
Alexander Couzens8dfc24c2021-01-25 16:09:23 +0100300 OSMO_ASSERT(ns2_vc_is_unblocked(nsvc[0]));
Alexander Couzens47afc422021-01-17 20:12:46 +0100301 gprs_ns2_free(nsi);
302 printf("--- Finish NSE block unblock nsvc\n");
303}
304
Alexander Couzens8f215c92021-01-25 15:27:56 +0100305static struct msgb *generate_unitdata(const char *msgname)
306{
307 struct gprs_ns_hdr *nsh;
308 struct msgb *msg = msgb_alloc_headroom(NS_ALLOC_SIZE, NS_ALLOC_HEADROOM, msgname);
309 OSMO_ASSERT(msg);
310
311 msg->l2h = msgb_put(msg, sizeof(*nsh) + 6);
312 nsh = (struct gprs_ns_hdr *) msg->l2h;
313 nsh->pdu_type = NS_PDUT_UNITDATA;
314 nsh->data[0] = 0; /* sdu control */
315 nsh->data[1] = 0; /* msb bvci */
316 nsh->data[2] = 12; /* lsb bvci */
317 nsh->data[3] = 0xab; /* first data byte */
318 nsh->data[4] = 0xcd;
319 nsh->data[5] = 0xef;
320
321 return msg;
322}
323
324void test_unitdata(void *ctx)
325{
326 struct gprs_ns2_inst *nsi;
327 struct gprs_ns2_vc_bind *bind[2];
328 struct gprs_ns2_vc_bind *loopbind;
329 struct gprs_ns2_nse *nse;
330 struct gprs_ns2_vc *nsvc[2];
331 struct gprs_ns2_vc *loop[2];
332
333 struct msgb *msg, *other;
334 char idbuf[32];
335 int i;
336
337 printf("--- Testing unitdata test\n");
338 osmo_wqueue_clear(unitdata);
339 printf("---- Create NSE + Binds\n");
340 nsi = gprs_ns2_instantiate(ctx, ns_prim_cb, NULL);
341 bind[0] = dummy_bind(nsi, "bblock1");
342 bind[1] = dummy_bind(nsi, "bblock2");
343 loopbind = loopback_bind(nsi, "loopback");
Alexander Couzens138b96f2021-01-25 16:23:29 +0100344 nse = gprs_ns2_create_nse(nsi, 1004, GPRS_NS2_LL_UDP, GPRS_NS2_DIALECT_STATIC_RESETBLOCK);
Alexander Couzens8f215c92021-01-25 15:27:56 +0100345 OSMO_ASSERT(nse);
346
347 for (i=0; i<2; i++) {
348 printf("---- Create NSVC[%d]\n", i);
349 snprintf(idbuf, sizeof(idbuf), "NSE%05u-dummy-%i", nse->nsei, i);
Alexander Couzens138b96f2021-01-25 16:23:29 +0100350 nsvc[i] = ns2_vc_alloc(bind[i], nse, false, GPRS_NS2_VC_MODE_BLOCKRESET, idbuf);
Alexander Couzens8f215c92021-01-25 15:27:56 +0100351 loop[i] = loopback_nsvc(loopbind, nsvc[i]);
352 OSMO_ASSERT(nsvc[i]);
Alexander Couzens8dfc24c2021-01-25 16:09:23 +0100353 ns2_vc_fsm_start(nsvc[i]);
354 OSMO_ASSERT(!ns2_vc_is_unblocked(nsvc[i]));
Alexander Couzens8f215c92021-01-25 15:27:56 +0100355 ns2_tx_reset(loop[i], NS_CAUSE_OM_INTERVENTION);
356 ns2_tx_unblock(loop[i]);
Alexander Couzens8dfc24c2021-01-25 16:09:23 +0100357 OSMO_ASSERT(ns2_vc_is_unblocked(nsvc[i]));
Alexander Couzens8f215c92021-01-25 15:27:56 +0100358 }
359
360 /* both nsvcs are unblocked and alive */
361 printf("---- Send UNITDATA to NSVC[0]\n");
362 msg = generate_unitdata("test_unitdata");
363 ns2_recv_vc(nsvc[0], msg);
364 other = msgb_dequeue(&unitdata->msg_queue);
365 OSMO_ASSERT(msg == other);
366 other = msgb_dequeue(&unitdata->msg_queue);
367 OSMO_ASSERT(NULL == other);
368
369 printf("---- Send Block NSVC[0]\n");
370 ns2_vc_block(nsvc[0]);
371 ns2_tx_block_ack(loop[0]);
372
373 /* try to receive a unitdata - this should be dropped & freed by NS */
374 printf("---- Try to receive over blocked NSVC[0]\n");
375 ns2_recv_vc(nsvc[0], msg);
376 other = msgb_dequeue(&unitdata->msg_queue);
377 OSMO_ASSERT(NULL == other);
378
379 /* nsvc[1] should be still good */
380 printf("---- Receive over NSVC[1]\n");
381 msg = generate_unitdata("test_unitdata2");
382 ns2_recv_vc(nsvc[1], msg);
383 other = msgb_dequeue(&unitdata->msg_queue);
384 OSMO_ASSERT(msg == other);
385 msgb_free(msg);
386
387 gprs_ns2_free(nsi);
388 printf("--- Finish unitdata test\n");
389}
390
Alexander Couzensd8a8d982021-02-15 01:07:45 +0100391void test_unitdata_weights(void *ctx)
392{
393 struct gprs_ns2_inst *nsi;
394 struct gprs_ns2_vc_bind *bind[3];
395 struct gprs_ns2_vc_bind *loopbind;
396 struct gprs_ns2_nse *nse;
397 struct gprs_ns2_vc *nsvc[3];
398 struct gprs_ns2_vc *loop[3];
399
400 struct msgb *msg, *other;
401 char idbuf[32];
402 int i;
403
404 printf("--- Testing unitdata weight test\n");
405 osmo_wqueue_clear(unitdata);
406 printf("---- Create NSE + Binds\n");
407 nsi = gprs_ns2_instantiate(ctx, ns_prim_cb, NULL);
408 bind[0] = dummy_bind(nsi, "bblock1");
409 bind[1] = dummy_bind(nsi, "bblock2");
410 bind[2] = dummy_bind(nsi, "bblock3");
411 loopbind = loopback_bind(nsi, "loopback");
412 nse = gprs_ns2_create_nse(nsi, 1004, GPRS_NS2_LL_UDP, GPRS_NS2_DIALECT_STATIC_ALIVE);
413 OSMO_ASSERT(nse);
414
415 /* data weights are
416 * nsvc[0] = 1
417 * nsvc[1] = 2
418 * nsvc[2] = 3
419 */
420 for (i = 0; i < 3; i++) {
421 printf("---- Create NSVC[%d]\n", i);
422 snprintf(idbuf, sizeof(idbuf), "NSE%05u-dummy-%i", nse->nsei, i);
423 nsvc[i] = ns2_vc_alloc(bind[i], nse, false, GPRS_NS2_VC_MODE_ALIVE, idbuf);
424 loop[i] = loopback_nsvc(loopbind, nsvc[i]);
425 OSMO_ASSERT(nsvc[i]);
426 nsvc[i]->data_weight = i + 1;
427 ns2_vc_fsm_start(nsvc[i]);
428 OSMO_ASSERT(!ns2_vc_is_unblocked(nsvc[i]));
429 ns2_tx_alive_ack(loop[i]);
430 OSMO_ASSERT(ns2_vc_is_unblocked(nsvc[i]));
431 }
432
433 /* all nsvcs are alive */
434 printf("---- Send UNITDATA to all NSVCs\n");
435 for (i = 0; i < 3; i++) {
436 msg = generate_unitdata("test_unitdata_weight");
437 ns2_recv_vc(nsvc[i], msg);
438 other = msgb_dequeue(&unitdata->msg_queue);
439 OSMO_ASSERT(msg == other);
440 other = msgb_dequeue(&unitdata->msg_queue);
441 OSMO_ASSERT(NULL == other);
442 msgb_free(msg);
443 }
444
445 /* nsvc[1] should be still good */
446 printf("---- Send BSSGP data to the NSE to test unitdata over NSVC[1]\n");
447 for (i = 0; i < 3; i++)
448 clear_pdus(bind[i]);
449
450 for (i = 0; i < 12; i++) {
451 msg = generate_unitdata("test_unitdata_weight2");
452 gp_send_to_ns(nsi, msg, 1004, 1, i + 1);
453 }
454
455 for (i = 0; i < 3; i++)
456 fprintf(stderr, "count_pdus(bind[%d]) = %d\n", i, count_pdus(bind[i]));
457
458 for (i = 0; i < 3; i++) {
459 OSMO_ASSERT(count_pdus(bind[i]) == nsvc[i]->data_weight * 2);
460 }
461
462 gprs_ns2_free(nsi);
463 printf("--- Finish unitdata weight test\n");
464}
465
Alexander Couzens4f1128f2021-01-20 17:42:48 +0100466void test_mtu(void *ctx)
467{
468 struct gprs_ns2_inst *nsi;
469 struct gprs_ns2_vc_bind *bind[2];
470 struct gprs_ns2_vc_bind *loopbind;
471 struct gprs_ns2_nse *nse;
472 struct gprs_ns2_vc *nsvc[2];
473 struct gprs_ns2_vc *loop[2];
474
475 struct msgb *msg, *other;
476 char idbuf[32];
477 int i;
478
479 printf("--- Testing mtu test\n");
480 osmo_wqueue_clear(unitdata);
481 printf("---- Create NSE + Binds\n");
482 nsi = gprs_ns2_instantiate(ctx, ns_prim_cb, NULL);
483 bind[0] = dummy_bind(nsi, "bblock1");
484 bind[1] = dummy_bind(nsi, "bblock2");
485 loopbind = loopback_bind(nsi, "loopback");
486 nse = gprs_ns2_create_nse(nsi, 1004, GPRS_NS2_LL_UDP, GPRS_NS2_DIALECT_STATIC_RESETBLOCK);
487 OSMO_ASSERT(nse);
488
489 for (i=0; i<2; i++) {
490 printf("---- Create NSVC[%d]\n", i);
491 snprintf(idbuf, sizeof(idbuf), "NSE%05u-dummy-%i", nse->nsei, i);
492 nsvc[i] = ns2_vc_alloc(bind[i], nse, false, GPRS_NS2_VC_MODE_BLOCKRESET, idbuf);
493 loop[i] = loopback_nsvc(loopbind, nsvc[i]);
494 OSMO_ASSERT(nsvc[i]);
495 ns2_vc_fsm_start(nsvc[i]);
496 OSMO_ASSERT(!ns2_vc_is_unblocked(nsvc[i]));
497 ns2_tx_reset(loop[i], NS_CAUSE_OM_INTERVENTION);
498 ns2_tx_unblock(loop[i]);
499 OSMO_ASSERT(ns2_vc_is_unblocked(nsvc[i]));
500 }
501
502 /* both nsvcs are unblocked and alive */
503 printf("---- Send a small UNITDATA to NSVC[0]\n");
504 msg = generate_unitdata("test_unitdata");
505 ns2_recv_vc(nsvc[0], msg);
506 other = msgb_dequeue(&unitdata->msg_queue);
507 OSMO_ASSERT(msg == other);
508 other = msgb_dequeue(&unitdata->msg_queue);
509 OSMO_ASSERT(NULL == other);
510 msgb_free(msg);
511
512 printf("---- Check if got mtu reported\n");
513 /* 1b NS PDU type, 1b NS SDU control, 2b BVCI */
514 OSMO_ASSERT(last_nse_recovery.u.status.mtu == 123 - 4);
515
516 gprs_ns2_free(nsi);
517 printf("--- Finish unitdata test\n");
518}
Alexander Couzens8f215c92021-01-25 15:27:56 +0100519
Alexander Couzens1c8785d2020-12-17 06:58:53 +0100520int main(int argc, char **argv)
521{
522 void *ctx = talloc_named_const(NULL, 0, "gprs_ns2_test");
523 osmo_init_logging2(ctx, &info);
524 log_set_use_color(osmo_stderr_target, 0);
Pau Espin Pedrol01e0d3e2021-02-18 19:25:44 +0100525 log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_NONE);
Pau Espin Pedrol690b6612021-02-18 19:10:28 +0100526 log_set_print_category(osmo_stderr_target, 0);
527 log_set_print_category_hex(osmo_stderr_target, 0);
Alexander Couzens1c8785d2020-12-17 06:58:53 +0100528 log_set_log_level(osmo_stderr_target, LOGL_INFO);
Alexander Couzens8f215c92021-01-25 15:27:56 +0100529 unitdata = talloc_zero(ctx, struct osmo_wqueue);
530 osmo_wqueue_init(unitdata, 100);
Alexander Couzens1c8785d2020-12-17 06:58:53 +0100531 setlinebuf(stdout);
532
533 printf("===== NS2 protocol test START\n");
534 test_nse_transfer_cap(ctx);
Alexander Couzens47afc422021-01-17 20:12:46 +0100535 test_block_unblock_nsvc(ctx);
Alexander Couzens8f215c92021-01-25 15:27:56 +0100536 test_unitdata(ctx);
Alexander Couzensd8a8d982021-02-15 01:07:45 +0100537 test_unitdata_weights(ctx);
Alexander Couzens4f1128f2021-01-20 17:42:48 +0100538 test_mtu(ctx);
Alexander Couzens1c8785d2020-12-17 06:58:53 +0100539 printf("===== NS2 protocol test END\n\n");
540
Alexander Couzense19b7962021-01-17 20:07:54 +0100541 talloc_free(ctx);
Alexander Couzens1c8785d2020-12-17 06:58:53 +0100542 exit(EXIT_SUCCESS);
543}