blob: 0221a8d6478ad101e05e53a9b0a81dfe324af7b0 [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 Couzensdb7b2ab2021-07-02 16:12:28 +020044static struct osmo_gprs_ns2_prim last_nse_mtu_change = {};
Alexander Couzens1c8785d2020-12-17 06:58:53 +010045
46static int ns_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
47{
Alexander Couzens4f1128f2021-01-20 17:42:48 +010048 struct osmo_gprs_ns2_prim *nsp;
Alexander Couzens8f215c92021-01-25 15:27:56 +010049 OSMO_ASSERT(oph->sap == SAP_NS);
Alexander Couzens4f1128f2021-01-20 17:42:48 +010050 nsp = container_of(oph, struct osmo_gprs_ns2_prim, oph);
Alexander Couzens8f215c92021-01-25 15:27:56 +010051 if (oph->msg) {
Alexander Couzens138b96f2021-01-25 16:23:29 +010052 if (oph->primitive == GPRS_NS2_PRIM_UNIT_DATA) {
Alexander Couzens8f215c92021-01-25 15:27:56 +010053 osmo_wqueue_enqueue(unitdata, oph->msg);
54 } else {
55 msgb_free(oph->msg);
56 }
57 }
Alexander Couzensdb7b2ab2021-07-02 16:12:28 +020058 if (oph->primitive == GPRS_NS2_PRIM_STATUS) {
59 if (nsp->u.status.cause == GPRS_NS2_AFF_CAUSE_RECOVERY) {
60 last_nse_recovery = *nsp;
61 } else if (nsp->u.status.cause == GPRS_NS2_AFF_CAUSE_MTU_CHANGE) {
62 last_nse_mtu_change = *nsp;
63 }
Alexander Couzens4f1128f2021-01-20 17:42:48 +010064 }
Alexander Couzens1c8785d2020-12-17 06:58:53 +010065 return 0;
66}
67
Alexander Couzensd8a8d982021-02-15 01:07:45 +010068static int gp_send_to_ns(struct gprs_ns2_inst *nsi, struct msgb *msg, uint16_t nsei, uint16_t bvci, uint32_t lsp)
69{
70 struct osmo_gprs_ns2_prim nsp = {};
71 nsp.nsei = nsei;
72 nsp.bvci = bvci;
73 nsp.u.unitdata.link_selector = lsp;
74 osmo_prim_init(&nsp.oph, SAP_NS, GPRS_NS2_PRIM_UNIT_DATA,
75 PRIM_OP_REQUEST, msg);
76 return gprs_ns2_recv_prim(nsi, &nsp.oph);
77}
78
79
Alexander Couzens47afc422021-01-17 20:12:46 +010080static struct msgb *get_pdu(struct gprs_ns2_vc_bind *bind, enum ns_pdu_type pdu_type)
81{
82 struct gprs_ns_hdr *nsh;
83 struct osmo_wqueue *queue = bind->priv;
84
85 while (!llist_empty(&queue->msg_queue)) {
86 struct msgb *msg = msgb_dequeue(&queue->msg_queue);
87 nsh = (struct gprs_ns_hdr *) msg->l2h;
88 if (nsh->pdu_type == pdu_type)
89 return msg;
90 msgb_free(msg);
91 }
92
93 return NULL;
94}
95
96static bool find_pdu(struct gprs_ns2_vc_bind *bind, enum ns_pdu_type pdu_type)
97{
98 struct msgb *msg;
99 msg = get_pdu(bind, pdu_type);
100 if (msg) {
101 msgb_free(msg);
102 return true;
103 }
104
105 return false;
106}
107
Alexander Couzensd8a8d982021-02-15 01:07:45 +0100108static unsigned int count_pdus(struct gprs_ns2_vc_bind *bind)
109{
110 struct osmo_wqueue *queue = bind->priv;
111 return llist_count(&queue->msg_queue);
112}
113
Alexander Couzensaf5bfeb2021-01-17 20:12:37 +0100114static void clear_pdus(struct gprs_ns2_vc_bind *bind)
Alexander Couzens1c8785d2020-12-17 06:58:53 +0100115{
Alexander Couzensaf5bfeb2021-01-17 20:12:37 +0100116 struct osmo_wqueue *queue = bind->priv;
117 osmo_wqueue_clear(queue);
Alexander Couzens1c8785d2020-12-17 06:58:53 +0100118}
119
120struct gprs_ns2_vc_driver vc_driver_dummy = {
121 .name = "GB UDP dummy",
Alexander Couzensaf5bfeb2021-01-17 20:12:37 +0100122 .free_bind = clear_pdus,
Alexander Couzens1c8785d2020-12-17 06:58:53 +0100123};
124
125static int vc_sendmsg(struct gprs_ns2_vc *nsvc, struct msgb *msg)
126{
127 struct gprs_ns2_vc_bind *bind = nsvc->bind;
128 struct osmo_wqueue *queue = bind->priv;
129
130 osmo_wqueue_enqueue(queue, msg);
131 return 0;
132}
133
134static struct gprs_ns2_vc_bind *dummy_bind(struct gprs_ns2_inst *nsi, const char *name)
135{
Harald Weltec3aa8f92021-01-31 11:41:34 +0100136 struct gprs_ns2_vc_bind *bind = NULL;
137 OSMO_ASSERT(ns2_bind_alloc(nsi, name, &bind) == 0);
Alexander Couzens1c8785d2020-12-17 06:58:53 +0100138 OSMO_ASSERT(bind);
139
Alexander Couzens1c8785d2020-12-17 06:58:53 +0100140 bind->driver = &vc_driver_dummy;
141 bind->ll = GPRS_NS2_LL_UDP;
142 bind->transfer_capability = 42;
Alexander Couzens1c8785d2020-12-17 06:58:53 +0100143 bind->send_vc = vc_sendmsg;
144 bind->priv = talloc_zero(bind, struct osmo_wqueue);
Alexander Couzens4f1128f2021-01-20 17:42:48 +0100145 bind->mtu = 123;
Alexander Couzens1c8785d2020-12-17 06:58:53 +0100146 struct osmo_wqueue *queue = bind->priv;
147
Alexander Couzens1c8785d2020-12-17 06:58:53 +0100148 osmo_wqueue_init(queue, 100);
149
150 return bind;
151}
152
Alexander Couzens8f215c92021-01-25 15:27:56 +0100153static void free_loopback(struct gprs_ns2_vc_bind *bind) {}
154
155struct gprs_ns2_vc_driver vc_driver_loopback = {
156 .name = "loopback dummy",
157 .free_bind = free_loopback,
158};
159
160/* loopback the msg */
161static int loopback_sendmsg(struct gprs_ns2_vc *nsvc, struct msgb *msg)
162{
163 struct gprs_ns2_vc *target = nsvc->priv;
164 return ns2_recv_vc(target, msg);
165}
166
167/* create a loopback nsvc object which can be used with ns2_tx_* functions. it's not fully registered etc. */
168static struct gprs_ns2_vc *loopback_nsvc(struct gprs_ns2_vc_bind *bind, struct gprs_ns2_vc *target)
169{
170 struct gprs_ns2_vc *nsvc = talloc_zero(bind, struct gprs_ns2_vc);
171 memcpy(nsvc, target, sizeof(struct gprs_ns2_vc));
172 nsvc->bind = bind;
173 nsvc->priv = target;
174 return nsvc;
175}
176
177/* a loop back bind to use the tx_ functions from gprs_ns2_message.c */
178static struct gprs_ns2_vc_bind *loopback_bind(struct gprs_ns2_inst *nsi, const char *name)
179{
Harald Weltec3aa8f92021-01-31 11:41:34 +0100180 struct gprs_ns2_vc_bind *bind = NULL;
181 OSMO_ASSERT(ns2_bind_alloc(nsi, name, &bind) == 0)
Alexander Couzens8f215c92021-01-25 15:27:56 +0100182 OSMO_ASSERT(bind);
Alexander Couzens8f215c92021-01-25 15:27:56 +0100183 bind->driver = &vc_driver_loopback;
184 bind->ll = GPRS_NS2_LL_UDP;
185 bind->transfer_capability = 99;
Alexander Couzens8f215c92021-01-25 15:27:56 +0100186 bind->send_vc = loopback_sendmsg;
Alexander Couzens4f1128f2021-01-20 17:42:48 +0100187 bind->mtu = 123;
Alexander Couzens8f215c92021-01-25 15:27:56 +0100188 return bind;
189}
190
Alexander Couzens1c8785d2020-12-17 06:58:53 +0100191void test_nse_transfer_cap(void *ctx)
192{
193 struct gprs_ns2_inst *nsi;
194 struct gprs_ns2_vc_bind *bind[2];
195 struct gprs_ns2_nse *nse;
196 struct gprs_ns2_vc *nsvc[3];
197
198 /* create a UDP dummy bind[0] with transfer cap 42.
199 * create nse (nsei 1001)
200 * create 2x nsvc with the same bind.
201 * nsvc[0] or nsvc[1] is alive (or both) cap == 42
202 *
203 * create a second bind with transfer cap == 23
204 * create 3rd nsvc with bind[1]
205 * transfer cap should be 42 + 23
206 */
207
208 printf("--- Testing NSE transfer cap\n");
209
210 printf("---- Create NSE + Binds\n");
211 nsi = gprs_ns2_instantiate(ctx, ns_prim_cb, NULL);
212 bind[0] = dummy_bind(nsi, "transfercap1");
213 bind[1] = dummy_bind(nsi, "transfercap2");
214 bind[1]->transfer_capability = 23;
Alexander Couzens138b96f2021-01-25 16:23:29 +0100215 nse = gprs_ns2_create_nse(nsi, 1001, GPRS_NS2_LL_UDP, GPRS_NS2_DIALECT_STATIC_ALIVE);
Alexander Couzens1c8785d2020-12-17 06:58:53 +0100216 OSMO_ASSERT(nse);
217
218 printf("---- Test with NSVC[0]\n");
Alexander Couzens138b96f2021-01-25 16:23:29 +0100219 nsvc[0] = ns2_vc_alloc(bind[0], nse, false, GPRS_NS2_VC_MODE_ALIVE, NULL);
Alexander Couzens1c8785d2020-12-17 06:58:53 +0100220 OSMO_ASSERT(nsvc[0]);
221 OSMO_ASSERT(ns2_count_transfer_cap(nse, 0) == 0);
222 nsvc[0]->fi->state = 3; /* HACK: 3 = GPRS_NS2_ST_UNBLOCKED */
223 ns2_nse_notify_unblocked(nsvc[0], true);
224 OSMO_ASSERT(ns2_count_transfer_cap(nse, 0) == 42);
225
226 printf("---- Test with NSVC[1]\n");
Alexander Couzens138b96f2021-01-25 16:23:29 +0100227 nsvc[1] = ns2_vc_alloc(bind[0], nse, false, GPRS_NS2_VC_MODE_ALIVE, NULL);
Alexander Couzens1c8785d2020-12-17 06:58:53 +0100228 OSMO_ASSERT(nsvc[1]);
229 OSMO_ASSERT(ns2_count_transfer_cap(nse, 0) == 42);
230 nsvc[1]->fi->state = 3; /* HACK: 3 = GPRS_NS2_ST_UNBLOCKED */
231 ns2_nse_notify_unblocked(nsvc[1], true);
232 OSMO_ASSERT(ns2_count_transfer_cap(nse, 0) == 42);
233
234 printf("---- Test with NSVC[2]\n");
Alexander Couzens138b96f2021-01-25 16:23:29 +0100235 nsvc[2] = ns2_vc_alloc(bind[1], nse, false, GPRS_NS2_VC_MODE_ALIVE, NULL);
Alexander Couzens1c8785d2020-12-17 06:58:53 +0100236 OSMO_ASSERT(nsvc[2]);
237 OSMO_ASSERT(ns2_count_transfer_cap(nse, 0) == 42);
238 nsvc[2]->fi->state = 3; /* HACK: 3 = GPRS_NS2_ST_UNBLOCKED */
239 ns2_nse_notify_unblocked(nsvc[2], true);
240 OSMO_ASSERT(ns2_count_transfer_cap(nse, 0) == 42 + 23);
241
242 printf("---- Test with NSVC[1] removed\n");
243 /* reset nsvc[1] to be unconfigured - shouldn't change anything */
244 nsvc[1]->fi->state = 0; /* HACK: 0 = GPRS_NS2_ST_UNCONFIGURED */
245 ns2_nse_notify_unblocked(nsvc[1], false);
246 OSMO_ASSERT(ns2_count_transfer_cap(nse, 0) == 42 + 23);
247
Alexander Couzensaca31b82021-01-17 20:15:20 +0100248 gprs_ns2_free(nsi);
Alexander Couzens1c8785d2020-12-17 06:58:53 +0100249 printf("--- Finish NSE transfer cap\n");
250
251}
252
Alexander Couzens47afc422021-01-17 20:12:46 +0100253/* setup NSE with 2x NSVCs.
254 * block 1x NSVC
255 * unblock 1x NSVC*/
256void test_block_unblock_nsvc(void *ctx)
257{
258 struct gprs_ns2_inst *nsi;
259 struct gprs_ns2_vc_bind *bind[2];
260 struct gprs_ns2_nse *nse;
261 struct gprs_ns2_vc *nsvc[2];
262 struct gprs_ns_hdr *nsh;
263 struct msgb *msg;
264 char idbuf[32];
Harald Welte2846ee22021-01-21 10:22:09 +0100265 int i;
Alexander Couzens47afc422021-01-17 20:12:46 +0100266
267 printf("--- Testing NSE block unblock nsvc\n");
268 printf("---- Create NSE + Binds\n");
269 nsi = gprs_ns2_instantiate(ctx, ns_prim_cb, NULL);
270 bind[0] = dummy_bind(nsi, "bblock1");
271 bind[1] = dummy_bind(nsi, "bblock2");
Alexander Couzens138b96f2021-01-25 16:23:29 +0100272 nse = gprs_ns2_create_nse(nsi, 1001, GPRS_NS2_LL_UDP, GPRS_NS2_DIALECT_STATIC_RESETBLOCK);
Alexander Couzens47afc422021-01-17 20:12:46 +0100273 OSMO_ASSERT(nse);
274
Harald Welte2846ee22021-01-21 10:22:09 +0100275 for (i=0; i<2; i++) {
Alexander Couzens47afc422021-01-17 20:12:46 +0100276 printf("---- Create NSVC[i]\n");
277 snprintf(idbuf, sizeof(idbuf), "NSE%05u-dummy-%i", nse->nsei, i);
Alexander Couzens138b96f2021-01-25 16:23:29 +0100278 nsvc[i] = ns2_vc_alloc(bind[i], nse, false, GPRS_NS2_VC_MODE_BLOCKRESET, idbuf);
Alexander Couzens47afc422021-01-17 20:12:46 +0100279 OSMO_ASSERT(nsvc[i]);
280 nsvc[i]->fi->state = 3; /* HACK: 3 = GPRS_NS2_ST_UNBLOCKED */
281 /* ensure the fi->state works correct */
Alexander Couzens8dfc24c2021-01-25 16:09:23 +0100282 OSMO_ASSERT(ns2_vc_is_unblocked(nsvc[i]));
Alexander Couzens47afc422021-01-17 20:12:46 +0100283 ns2_nse_notify_unblocked(nsvc[i], true);
284 }
285
286 /* both nsvcs are unblocked and alive. Let's block it. */
287 OSMO_ASSERT(!find_pdu(bind[0], NS_PDUT_BLOCK));
288 clear_pdus(bind[0]);
289 ns2_vc_block(nsvc[0]);
290 OSMO_ASSERT(find_pdu(bind[0], NS_PDUT_BLOCK));
291 /* state == BLOCKED */
292 clear_pdus(bind[0]);
293
294 /* now unblocking it */
295 ns2_vc_unblock(nsvc[0]);
296 OSMO_ASSERT(find_pdu(bind[0], NS_PDUT_UNBLOCK));
297 clear_pdus(bind[0]);
298
299 msg = msgb_alloc_headroom(NS_ALLOC_SIZE, NS_ALLOC_HEADROOM, "test_unblock");
300 msg->l2h = msgb_put(msg, sizeof(*nsh));
301 nsh = (struct gprs_ns_hdr *) msg->l2h;
302 nsh->pdu_type = NS_PDUT_UNBLOCK_ACK;
303 ns2_recv_vc(nsvc[0], msg);
304
Alexander Couzens8dfc24c2021-01-25 16:09:23 +0100305 OSMO_ASSERT(ns2_vc_is_unblocked(nsvc[0]));
Alexander Couzens47afc422021-01-17 20:12:46 +0100306 gprs_ns2_free(nsi);
307 printf("--- Finish NSE block unblock nsvc\n");
308}
309
Alexander Couzense09deb62021-06-15 21:35:45 +0200310/* setup NSE with 2x NSVCs.
311 * block 1st NSVC
312 * block 2nd NSVC
313 * unblock 1st NSVC */
314void test_block_unblock_nsvc2(void *ctx)
315{
316 struct gprs_ns2_inst *nsi;
317 struct gprs_ns2_vc_bind *bind[2];
318 struct gprs_ns2_nse *nse;
319 struct gprs_ns2_vc *nsvc[2];
320 struct gprs_ns_hdr *nsh;
321 struct msgb *msg;
322 char idbuf[32];
323 int i;
324
325 printf("--- Testing NSE block unblock nsvc2\n");
326 printf("---- Create NSE + Binds\n");
327 nsi = gprs_ns2_instantiate(ctx, ns_prim_cb, NULL);
328 bind[0] = dummy_bind(nsi, "bblock1");
329 bind[1] = dummy_bind(nsi, "bblock2");
330 nse = gprs_ns2_create_nse(nsi, 1001, GPRS_NS2_LL_UDP, GPRS_NS2_DIALECT_STATIC_RESETBLOCK);
331 OSMO_ASSERT(nse);
332
333 for (i=0; i<2; i++) {
334 printf("---- Create NSVC[i]\n");
335 snprintf(idbuf, sizeof(idbuf), "NSE%05u-dummy-%i", nse->nsei, i);
336 nsvc[i] = ns2_vc_alloc(bind[i], nse, false, GPRS_NS2_VC_MODE_BLOCKRESET, idbuf);
337 OSMO_ASSERT(nsvc[i]);
338 nsvc[i]->fi->state = 3; /* HACK: 3 = GPRS_NS2_ST_UNBLOCKED */
339 /* ensure the fi->state works correct */
340 OSMO_ASSERT(ns2_vc_is_unblocked(nsvc[i]));
341 ns2_nse_notify_unblocked(nsvc[i], true);
342 }
343
344 OSMO_ASSERT(nse->alive);
345 /* both nsvcs are unblocked and alive. Let's block them. */
346 OSMO_ASSERT(!find_pdu(bind[0], NS_PDUT_BLOCK));
347 clear_pdus(bind[0]);
348 ns2_vc_block(nsvc[0]);
349 OSMO_ASSERT(find_pdu(bind[0], NS_PDUT_BLOCK));
350 clear_pdus(bind[0]);
351 OSMO_ASSERT(nse->alive);
352
353 OSMO_ASSERT(!find_pdu(bind[1], NS_PDUT_BLOCK));
354 clear_pdus(bind[1]);
355 ns2_vc_block(nsvc[1]);
356 OSMO_ASSERT(find_pdu(bind[1], NS_PDUT_BLOCK));
357 clear_pdus(bind[1]);
358 OSMO_ASSERT(!nse->alive);
359
360 /* now unblocking the 1st NSVC */
361 ns2_vc_unblock(nsvc[0]);
362 OSMO_ASSERT(find_pdu(bind[0], NS_PDUT_UNBLOCK));
363 clear_pdus(bind[0]);
364 msg = msgb_alloc_headroom(NS_ALLOC_SIZE, NS_ALLOC_HEADROOM, "test_unblock");
365 msg->l2h = msgb_put(msg, sizeof(*nsh));
366 nsh = (struct gprs_ns_hdr *) msg->l2h;
367 nsh->pdu_type = NS_PDUT_UNBLOCK_ACK;
368 ns2_recv_vc(nsvc[0], msg);
369 OSMO_ASSERT(nse->alive);
370
371 OSMO_ASSERT(ns2_vc_is_unblocked(nsvc[0]));
372 gprs_ns2_free(nsi);
373 printf("--- Finish NSE block unblock nsvc2\n");
374}
375
Alexander Couzens8f215c92021-01-25 15:27:56 +0100376static struct msgb *generate_unitdata(const char *msgname)
377{
378 struct gprs_ns_hdr *nsh;
379 struct msgb *msg = msgb_alloc_headroom(NS_ALLOC_SIZE, NS_ALLOC_HEADROOM, msgname);
380 OSMO_ASSERT(msg);
381
382 msg->l2h = msgb_put(msg, sizeof(*nsh) + 6);
383 nsh = (struct gprs_ns_hdr *) msg->l2h;
384 nsh->pdu_type = NS_PDUT_UNITDATA;
385 nsh->data[0] = 0; /* sdu control */
386 nsh->data[1] = 0; /* msb bvci */
387 nsh->data[2] = 12; /* lsb bvci */
388 nsh->data[3] = 0xab; /* first data byte */
389 nsh->data[4] = 0xcd;
390 nsh->data[5] = 0xef;
391
392 return msg;
393}
394
395void test_unitdata(void *ctx)
396{
397 struct gprs_ns2_inst *nsi;
398 struct gprs_ns2_vc_bind *bind[2];
399 struct gprs_ns2_vc_bind *loopbind;
400 struct gprs_ns2_nse *nse;
401 struct gprs_ns2_vc *nsvc[2];
402 struct gprs_ns2_vc *loop[2];
403
404 struct msgb *msg, *other;
405 char idbuf[32];
406 int i;
407
408 printf("--- Testing unitdata test\n");
409 osmo_wqueue_clear(unitdata);
410 printf("---- Create NSE + Binds\n");
411 nsi = gprs_ns2_instantiate(ctx, ns_prim_cb, NULL);
412 bind[0] = dummy_bind(nsi, "bblock1");
413 bind[1] = dummy_bind(nsi, "bblock2");
414 loopbind = loopback_bind(nsi, "loopback");
Alexander Couzens138b96f2021-01-25 16:23:29 +0100415 nse = gprs_ns2_create_nse(nsi, 1004, GPRS_NS2_LL_UDP, GPRS_NS2_DIALECT_STATIC_RESETBLOCK);
Alexander Couzens8f215c92021-01-25 15:27:56 +0100416 OSMO_ASSERT(nse);
417
418 for (i=0; i<2; i++) {
419 printf("---- Create NSVC[%d]\n", i);
420 snprintf(idbuf, sizeof(idbuf), "NSE%05u-dummy-%i", nse->nsei, i);
Alexander Couzens138b96f2021-01-25 16:23:29 +0100421 nsvc[i] = ns2_vc_alloc(bind[i], nse, false, GPRS_NS2_VC_MODE_BLOCKRESET, idbuf);
Alexander Couzens8f215c92021-01-25 15:27:56 +0100422 loop[i] = loopback_nsvc(loopbind, nsvc[i]);
423 OSMO_ASSERT(nsvc[i]);
Alexander Couzens8dfc24c2021-01-25 16:09:23 +0100424 ns2_vc_fsm_start(nsvc[i]);
425 OSMO_ASSERT(!ns2_vc_is_unblocked(nsvc[i]));
Alexander Couzens8f215c92021-01-25 15:27:56 +0100426 ns2_tx_reset(loop[i], NS_CAUSE_OM_INTERVENTION);
427 ns2_tx_unblock(loop[i]);
Alexander Couzens8dfc24c2021-01-25 16:09:23 +0100428 OSMO_ASSERT(ns2_vc_is_unblocked(nsvc[i]));
Alexander Couzens8f215c92021-01-25 15:27:56 +0100429 }
430
431 /* both nsvcs are unblocked and alive */
432 printf("---- Send UNITDATA to NSVC[0]\n");
433 msg = generate_unitdata("test_unitdata");
434 ns2_recv_vc(nsvc[0], msg);
435 other = msgb_dequeue(&unitdata->msg_queue);
436 OSMO_ASSERT(msg == other);
437 other = msgb_dequeue(&unitdata->msg_queue);
438 OSMO_ASSERT(NULL == other);
439
440 printf("---- Send Block NSVC[0]\n");
441 ns2_vc_block(nsvc[0]);
Alexander Couzens67cfc5d2021-09-07 01:10:38 +0200442 ns2_tx_block_ack(loop[0], NULL);
Alexander Couzens8f215c92021-01-25 15:27:56 +0100443
444 /* try to receive a unitdata - this should be dropped & freed by NS */
445 printf("---- Try to receive over blocked NSVC[0]\n");
446 ns2_recv_vc(nsvc[0], msg);
447 other = msgb_dequeue(&unitdata->msg_queue);
448 OSMO_ASSERT(NULL == other);
449
450 /* nsvc[1] should be still good */
451 printf("---- Receive over NSVC[1]\n");
452 msg = generate_unitdata("test_unitdata2");
453 ns2_recv_vc(nsvc[1], msg);
454 other = msgb_dequeue(&unitdata->msg_queue);
455 OSMO_ASSERT(msg == other);
456 msgb_free(msg);
457
458 gprs_ns2_free(nsi);
459 printf("--- Finish unitdata test\n");
460}
461
Alexander Couzensd8a8d982021-02-15 01:07:45 +0100462void test_unitdata_weights(void *ctx)
463{
464 struct gprs_ns2_inst *nsi;
465 struct gprs_ns2_vc_bind *bind[3];
466 struct gprs_ns2_vc_bind *loopbind;
467 struct gprs_ns2_nse *nse;
468 struct gprs_ns2_vc *nsvc[3];
469 struct gprs_ns2_vc *loop[3];
470
471 struct msgb *msg, *other;
472 char idbuf[32];
473 int i;
474
475 printf("--- Testing unitdata weight test\n");
476 osmo_wqueue_clear(unitdata);
477 printf("---- Create NSE + Binds\n");
478 nsi = gprs_ns2_instantiate(ctx, ns_prim_cb, NULL);
479 bind[0] = dummy_bind(nsi, "bblock1");
480 bind[1] = dummy_bind(nsi, "bblock2");
481 bind[2] = dummy_bind(nsi, "bblock3");
482 loopbind = loopback_bind(nsi, "loopback");
483 nse = gprs_ns2_create_nse(nsi, 1004, GPRS_NS2_LL_UDP, GPRS_NS2_DIALECT_STATIC_ALIVE);
484 OSMO_ASSERT(nse);
485
486 /* data weights are
487 * nsvc[0] = 1
488 * nsvc[1] = 2
489 * nsvc[2] = 3
490 */
491 for (i = 0; i < 3; i++) {
492 printf("---- Create NSVC[%d]\n", i);
493 snprintf(idbuf, sizeof(idbuf), "NSE%05u-dummy-%i", nse->nsei, i);
494 nsvc[i] = ns2_vc_alloc(bind[i], nse, false, GPRS_NS2_VC_MODE_ALIVE, idbuf);
495 loop[i] = loopback_nsvc(loopbind, nsvc[i]);
496 OSMO_ASSERT(nsvc[i]);
497 nsvc[i]->data_weight = i + 1;
498 ns2_vc_fsm_start(nsvc[i]);
499 OSMO_ASSERT(!ns2_vc_is_unblocked(nsvc[i]));
500 ns2_tx_alive_ack(loop[i]);
501 OSMO_ASSERT(ns2_vc_is_unblocked(nsvc[i]));
502 }
503
504 /* all nsvcs are alive */
505 printf("---- Send UNITDATA to all NSVCs\n");
506 for (i = 0; i < 3; i++) {
507 msg = generate_unitdata("test_unitdata_weight");
508 ns2_recv_vc(nsvc[i], msg);
509 other = msgb_dequeue(&unitdata->msg_queue);
510 OSMO_ASSERT(msg == other);
511 other = msgb_dequeue(&unitdata->msg_queue);
512 OSMO_ASSERT(NULL == other);
513 msgb_free(msg);
514 }
515
516 /* nsvc[1] should be still good */
517 printf("---- Send BSSGP data to the NSE to test unitdata over NSVC[1]\n");
518 for (i = 0; i < 3; i++)
519 clear_pdus(bind[i]);
520
521 for (i = 0; i < 12; i++) {
522 msg = generate_unitdata("test_unitdata_weight2");
523 gp_send_to_ns(nsi, msg, 1004, 1, i + 1);
524 }
525
526 for (i = 0; i < 3; i++)
527 fprintf(stderr, "count_pdus(bind[%d]) = %d\n", i, count_pdus(bind[i]));
528
529 for (i = 0; i < 3; i++) {
530 OSMO_ASSERT(count_pdus(bind[i]) == nsvc[i]->data_weight * 2);
531 }
532
533 gprs_ns2_free(nsi);
534 printf("--- Finish unitdata weight test\n");
535}
536
Alexander Couzens4f1128f2021-01-20 17:42:48 +0100537void test_mtu(void *ctx)
538{
539 struct gprs_ns2_inst *nsi;
540 struct gprs_ns2_vc_bind *bind[2];
541 struct gprs_ns2_vc_bind *loopbind;
542 struct gprs_ns2_nse *nse;
543 struct gprs_ns2_vc *nsvc[2];
544 struct gprs_ns2_vc *loop[2];
545
546 struct msgb *msg, *other;
547 char idbuf[32];
548 int i;
549
550 printf("--- Testing mtu test\n");
551 osmo_wqueue_clear(unitdata);
552 printf("---- Create NSE + Binds\n");
553 nsi = gprs_ns2_instantiate(ctx, ns_prim_cb, NULL);
554 bind[0] = dummy_bind(nsi, "bblock1");
555 bind[1] = dummy_bind(nsi, "bblock2");
556 loopbind = loopback_bind(nsi, "loopback");
557 nse = gprs_ns2_create_nse(nsi, 1004, GPRS_NS2_LL_UDP, GPRS_NS2_DIALECT_STATIC_RESETBLOCK);
558 OSMO_ASSERT(nse);
559
560 for (i=0; i<2; i++) {
561 printf("---- Create NSVC[%d]\n", i);
562 snprintf(idbuf, sizeof(idbuf), "NSE%05u-dummy-%i", nse->nsei, i);
563 nsvc[i] = ns2_vc_alloc(bind[i], nse, false, GPRS_NS2_VC_MODE_BLOCKRESET, idbuf);
564 loop[i] = loopback_nsvc(loopbind, nsvc[i]);
565 OSMO_ASSERT(nsvc[i]);
566 ns2_vc_fsm_start(nsvc[i]);
567 OSMO_ASSERT(!ns2_vc_is_unblocked(nsvc[i]));
568 ns2_tx_reset(loop[i], NS_CAUSE_OM_INTERVENTION);
569 ns2_tx_unblock(loop[i]);
570 OSMO_ASSERT(ns2_vc_is_unblocked(nsvc[i]));
571 }
572
573 /* both nsvcs are unblocked and alive */
574 printf("---- Send a small UNITDATA to NSVC[0]\n");
575 msg = generate_unitdata("test_unitdata");
576 ns2_recv_vc(nsvc[0], msg);
577 other = msgb_dequeue(&unitdata->msg_queue);
578 OSMO_ASSERT(msg == other);
579 other = msgb_dequeue(&unitdata->msg_queue);
580 OSMO_ASSERT(NULL == other);
581 msgb_free(msg);
582
583 printf("---- Check if got mtu reported\n");
584 /* 1b NS PDU type, 1b NS SDU control, 2b BVCI */
585 OSMO_ASSERT(last_nse_recovery.u.status.mtu == 123 - 4);
586
Alexander Couzensdb7b2ab2021-07-02 16:12:28 +0200587 bind[0]->mtu = 100;
588 ns2_nse_update_mtu(nse);
589 OSMO_ASSERT(last_nse_mtu_change.u.status.mtu == 100 - 4);
590
Alexander Couzens4f1128f2021-01-20 17:42:48 +0100591 gprs_ns2_free(nsi);
592 printf("--- Finish unitdata test\n");
593}
Alexander Couzens8f215c92021-01-25 15:27:56 +0100594
Alexander Couzensa140d442021-07-12 16:42:32 +0200595void test_unconfigured(void *ctx)
596{
597 struct gprs_ns2_inst *nsi;
598 struct gprs_ns2_vc_bind *bind[2];
599 struct gprs_ns2_vc_bind *loopbind;
600 struct gprs_ns2_nse *nse;
601 struct gprs_ns2_vc *nsvc[2];
602 struct gprs_ns2_vc *loop[2];
603
604 char idbuf[32];
605 int i;
606
607 printf("--- Testing force unconfigured\n");
608 osmo_wqueue_clear(unitdata);
609 printf("---- Create NSE + Binds\n");
610 nsi = gprs_ns2_instantiate(ctx, ns_prim_cb, NULL);
611 bind[0] = dummy_bind(nsi, "bblock1");
612 bind[1] = dummy_bind(nsi, "bblock2");
613 loopbind = loopback_bind(nsi, "loopback");
614 nse = gprs_ns2_create_nse(nsi, 1004, GPRS_NS2_LL_UDP, GPRS_NS2_DIALECT_STATIC_RESETBLOCK);
615 OSMO_ASSERT(nse);
616
617 for (i=0; i<2; i++) {
618 printf("---- Create NSVC[%d]\n", i);
619 snprintf(idbuf, sizeof(idbuf), "NSE%05u-dummy-%i", nse->nsei, i);
620 nsvc[i] = ns2_vc_alloc(bind[i], nse, false, GPRS_NS2_VC_MODE_BLOCKRESET, idbuf);
621 loop[i] = loopback_nsvc(loopbind, nsvc[i]);
622 OSMO_ASSERT(nsvc[i]);
623 ns2_vc_fsm_start(nsvc[i]);
624 OSMO_ASSERT(!ns2_vc_is_unblocked(nsvc[i]));
625 ns2_tx_reset(loop[i], NS_CAUSE_OM_INTERVENTION);
626 ns2_tx_unblock(loop[i]);
627 OSMO_ASSERT(ns2_vc_is_unblocked(nsvc[i]));
628 }
629
630 /* both nsvcs are unblocked and alive */
631 printf("---- Check if NSE is alive\n");
632 OSMO_ASSERT(nse->alive);
633
634 ns2_vc_force_unconfigured(nsvc[0]);
635 OSMO_ASSERT(nse->alive);
636
637 ns2_vc_force_unconfigured(nsvc[1]);
638 printf("---- Check if NSE is dead\n");
639 OSMO_ASSERT(!nse->alive);
640
641 gprs_ns2_free(nsi);
642 printf("--- Finish force unconfigured test\n");
643}
644
Alexander Couzens1c8785d2020-12-17 06:58:53 +0100645int main(int argc, char **argv)
646{
647 void *ctx = talloc_named_const(NULL, 0, "gprs_ns2_test");
648 osmo_init_logging2(ctx, &info);
649 log_set_use_color(osmo_stderr_target, 0);
Pau Espin Pedrol01e0d3e2021-02-18 19:25:44 +0100650 log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_NONE);
Pau Espin Pedrol690b6612021-02-18 19:10:28 +0100651 log_set_print_category(osmo_stderr_target, 0);
652 log_set_print_category_hex(osmo_stderr_target, 0);
Alexander Couzens1c8785d2020-12-17 06:58:53 +0100653 log_set_log_level(osmo_stderr_target, LOGL_INFO);
Alexander Couzens8f215c92021-01-25 15:27:56 +0100654 unitdata = talloc_zero(ctx, struct osmo_wqueue);
655 osmo_wqueue_init(unitdata, 100);
Alexander Couzens1c8785d2020-12-17 06:58:53 +0100656 setlinebuf(stdout);
657
658 printf("===== NS2 protocol test START\n");
659 test_nse_transfer_cap(ctx);
Alexander Couzens47afc422021-01-17 20:12:46 +0100660 test_block_unblock_nsvc(ctx);
Alexander Couzense09deb62021-06-15 21:35:45 +0200661 test_block_unblock_nsvc2(ctx);
Alexander Couzens8f215c92021-01-25 15:27:56 +0100662 test_unitdata(ctx);
Alexander Couzensd8a8d982021-02-15 01:07:45 +0100663 test_unitdata_weights(ctx);
Alexander Couzensa140d442021-07-12 16:42:32 +0200664 test_unconfigured(ctx);
Alexander Couzens4f1128f2021-01-20 17:42:48 +0100665 test_mtu(ctx);
Alexander Couzens1c8785d2020-12-17 06:58:53 +0100666 printf("===== NS2 protocol test END\n\n");
667
Alexander Couzense19b7962021-01-17 20:07:54 +0100668 talloc_free(ctx);
Alexander Couzens1c8785d2020-12-17 06:58:53 +0100669 exit(EXIT_SUCCESS);
670}