blob: 60e8bf288b4fcc9fbbafb98f992bd665e6f5b1c9 [file] [log] [blame]
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +02001/* Test the SGSN */
2/*
3 * (C) 2014 by Holger Hans Peter Freyther
4 * (C) 2014 by sysmocom s.f.m.c. GmbH
5 * 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 Affero General Public License as published by
9 * the Free Software Foundation; either version 3 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 Affero General Public License for more details.
16 *
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020022#include <openbsc/gprs_llc.h>
23#include <openbsc/sgsn.h>
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +020024#include <openbsc/gprs_gmm.h>
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020025#include <openbsc/debug.h>
26
Jacob Erlbeck189999d2014-10-27 14:34:13 +010027#include <osmocom/gprs/gprs_bssgp.h>
28
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020029#include <osmocom/gsm/gsm_utils.h>
30
31#include <osmocom/core/application.h>
32#include <osmocom/core/msgb.h>
Jacob Erlbeck189999d2014-10-27 14:34:13 +010033#include <osmocom/core/rate_ctr.h>
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020034
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +020035#include <stdio.h>
36
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020037extern void *tall_msgb_ctx;
38
39void *tall_bsc_ctx;
40static struct sgsn_instance sgsn_inst = {
41 .config_file = "osmo_sgsn.cfg",
42 .cfg = {
43 .gtp_statedir = "./",
44 .acl_enabled = 1,
45 },
46};
47struct sgsn_instance *sgsn = &sgsn_inst;
Jacob Erlbeck189999d2014-10-27 14:34:13 +010048unsigned sgsn_tx_counter = 0;
49
50/* override */
51int bssgp_tx_dl_ud(struct msgb *msg, uint16_t pdu_lifetime,
52 struct bssgp_dl_ud_par *dup)
53{
54 sgsn_tx_counter += 1;
55 return 0;
56}
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +020057
58static int count(struct llist_head *head)
59{
60 struct llist_head *cur;
61 int count = 0;
62
63 llist_for_each(cur, head)
64 count += 1;
65
66 return count;
67}
68
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +020069static struct msgb *create_msg(const uint8_t *data, size_t len)
70{
71 struct msgb *msg = msgb_alloc(len + 8, "test message");
72 msg->l1h = msgb_put(msg, 8);
73 msg->l2h = msgb_put(msg, len);
74 memcpy(msg->l2h, data, len);
75
76 msgb_bcid(msg) = msg->l1h;
77 msgb_gmmh(msg) = msg->l2h;
78 return msg;
79}
80
Jacob Erlbeckabc16a52014-10-27 13:23:49 +010081/*
82 * Create a context and search for it
83 */
84static struct sgsn_mm_ctx *alloc_mm_ctx(uint32_t tlli, struct gprs_ra_id *raid)
85{
86 struct sgsn_mm_ctx *ctx, *ictx;
87 struct gprs_llc_lle *lle;
88 int old_count = count(gprs_llme_list());
89
90 lle = gprs_lle_get_or_create(tlli, 3);
91 ctx = sgsn_mm_ctx_alloc(tlli, raid);
92 ctx->mm_state = GMM_REGISTERED_NORMAL;
93 ctx->llme = lle->llme;
94
95 ictx = sgsn_mm_ctx_by_tlli(tlli, raid);
96 OSMO_ASSERT(ictx == ctx);
97
98 OSMO_ASSERT(count(gprs_llme_list()) == old_count + 1);
99
100 return ctx;
101}
102
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100103static void send_0408_message(struct gprs_llc_llme *llme, uint32_t tlli,
104 const uint8_t *data, size_t data_len)
105{
106 struct msgb *msg;
107
108 sgsn_tx_counter = 0;
109
110 msg = create_msg(data, data_len);
111 msgb_tlli(msg) = tlli;
112 gsm0408_gprs_rcvmsg(msg, llme);
113 msgb_free(msg);
114}
115
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200116static void test_llme(void)
117{
118 struct gprs_llc_lle *lle, *lle_copy;
119 uint32_t local_tlli;
120 uint32_t foreign_tlli;
121
122 printf("Testing LLME allocations\n");
123 local_tlli = gprs_tmsi2tlli(0x234, TLLI_LOCAL);
124 foreign_tlli = gprs_tmsi2tlli(0x234, TLLI_FOREIGN);
125
126 /* initial state */
127 OSMO_ASSERT(count(gprs_llme_list()) == 0);
128
129 /* Create a new entry */
130 lle = gprs_lle_get_or_create(local_tlli, 3);
131 OSMO_ASSERT(lle);
132 OSMO_ASSERT(count(gprs_llme_list()) == 1);
133
134 /* No new entry is created */
135 lle_copy = gprs_lle_get_or_create(local_tlli, 3);
136 OSMO_ASSERT(lle == lle_copy);
137 OSMO_ASSERT(count(gprs_llme_list()) == 1);
138 lle_copy = gprs_lle_get_or_create(foreign_tlli, 3);
139 OSMO_ASSERT(lle == lle_copy);
140 OSMO_ASSERT(count(gprs_llme_list()) == 1);
141
142 /* unassign which should delete it*/
143 gprs_llgmm_assign(lle->llme, lle->llme->tlli, 0xffffffff, GPRS_ALGO_GEA0, NULL);
144
145 /* Check that everything was cleaned up */
146 OSMO_ASSERT(count(gprs_llme_list()) == 0);
147}
148
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200149/*
150 * Test that a GMM Detach will remove the MMCTX and the
151 * associated LLME.
152 */
153static void test_gmm_detach(void)
154{
155 struct gprs_ra_id raid = { 0, };
156 struct sgsn_mm_ctx *ctx, *ictx;
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200157 uint32_t local_tlli;
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200158
159 printf("Testing GMM detach\n");
160
161 /* DTAP - Detach Request (MO) */
162 /* normal detach, power_off = 0 */
163 static const unsigned char detach_req[] = {
164 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xef, 0xe2,
165 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
166 };
167
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200168 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200169
Jacob Erlbeckabc16a52014-10-27 13:23:49 +0100170 /* Create a context */
171 OSMO_ASSERT(count(gprs_llme_list()) == 0);
172 ctx = alloc_mm_ctx(local_tlli, &raid);
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200173
174 /* inject the detach */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100175 send_0408_message(ctx->llme, local_tlli,
176 detach_req, ARRAY_SIZE(detach_req));
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200177
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100178 /* verify that a single message (hopefully the Detach Accept) has been
179 * sent by the SGSN */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100180 OSMO_ASSERT(sgsn_tx_counter == 1);
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100181
182 /* verify that things are gone */
183 OSMO_ASSERT(count(gprs_llme_list()) == 0);
184 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
185 OSMO_ASSERT(!ictx);
186}
187
188/*
189 * Test that a GMM Detach will remove the MMCTX and the associated LLME but
190 * will not sent a Detach Accept message (power_off = 1)
191 */
192static void test_gmm_detach_power_off(void)
193{
194 struct gprs_ra_id raid = { 0, };
195 struct sgsn_mm_ctx *ctx, *ictx;
196 uint32_t local_tlli;
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100197
198 printf("Testing GMM detach (power off)\n");
199
200 /* DTAP - Detach Request (MO) */
201 /* normal detach, power_off = 1 */
202 static const unsigned char detach_req[] = {
203 0x08, 0x05, 0x09, 0x18, 0x05, 0xf4, 0xef, 0xe2,
204 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
205 };
206
207 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
208
209 /* Create a context */
210 OSMO_ASSERT(count(gprs_llme_list()) == 0);
211 ctx = alloc_mm_ctx(local_tlli, &raid);
212
213 /* inject the detach */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100214 send_0408_message(ctx->llme, local_tlli,
215 detach_req, ARRAY_SIZE(detach_req));
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100216
217 /* verify that no message (and therefore no Detach Accept) has been
218 * sent by the SGSN */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100219 OSMO_ASSERT(sgsn_tx_counter == 0);
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100220
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200221 /* verify that things are gone */
222 OSMO_ASSERT(count(gprs_llme_list()) == 0);
223 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
Jacob Erlbeck258ce3d2014-09-30 13:51:45 +0200224 OSMO_ASSERT(!ictx);
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200225}
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200226
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200227/*
228 * Test that a GMM Detach will remove the associated LLME if there is no MMCTX.
229 */
230static void test_gmm_detach_no_mmctx(void)
231{
232 struct gprs_llc_lle *lle;
233 uint32_t local_tlli;
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200234
235 printf("Testing GMM detach (no MMCTX)\n");
236
237 /* DTAP - Detach Request (MO) */
238 /* normal detach, power_off = 0 */
239 static const unsigned char detach_req[] = {
240 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xef, 0xe2,
241 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
242 };
243
244 /* Create an LLME */
245 OSMO_ASSERT(count(gprs_llme_list()) == 0);
246 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
247 lle = gprs_lle_get_or_create(local_tlli, 3);
248
249 OSMO_ASSERT(count(gprs_llme_list()) == 1);
250
251 /* inject the detach */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100252 send_0408_message(lle->llme, local_tlli,
253 detach_req, ARRAY_SIZE(detach_req));
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200254
255 /* verify that the LLME is gone */
256 OSMO_ASSERT(count(gprs_llme_list()) == 0);
257}
258
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100259/*
260 * Test that a GMM Status will remove the associated LLME if there is no MMCTX.
261 */
262static void test_gmm_status_no_mmctx(void)
263{
264 struct gprs_llc_lle *lle;
265 uint32_t local_tlli;
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100266
267 printf("Testing GMM Status (no MMCTX)\n");
268
269 /* DTAP - GMM Status, protocol error */
270 static const unsigned char gmm_status[] = {
271 0x08, 0x20, 0x6f
272 };
273
274 /* Create an LLME */
275 OSMO_ASSERT(count(gprs_llme_list()) == 0);
276 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
277 lle = gprs_lle_get_or_create(local_tlli, 3);
278
279 OSMO_ASSERT(count(gprs_llme_list()) == 1);
280
281 /* inject the detach */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100282 send_0408_message(lle->llme, local_tlli,
283 gmm_status, ARRAY_SIZE(gmm_status));
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100284
285 /* verify that no message has been sent by the SGSN */
Jacob Erlbeck94ef1c02014-10-29 10:31:18 +0100286 OSMO_ASSERT(sgsn_tx_counter == 0);
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100287
288 /* verify that the LLME is gone */
289 OSMO_ASSERT(count(gprs_llme_list()) == 0);
290}
291
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200292static struct log_info_cat gprs_categories[] = {
293 [DMM] = {
294 .name = "DMM",
295 .description = "Layer3 Mobility Management (MM)",
296 .color = "\033[1;33m",
297 .enabled = 1, .loglevel = LOGL_NOTICE,
298 },
299 [DPAG] = {
300 .name = "DPAG",
301 .description = "Paging Subsystem",
302 .color = "\033[1;38m",
303 .enabled = 1, .loglevel = LOGL_NOTICE,
304 },
305 [DMEAS] = {
306 .name = "DMEAS",
307 .description = "Radio Measurement Processing",
308 .enabled = 0, .loglevel = LOGL_NOTICE,
309 },
310 [DREF] = {
311 .name = "DREF",
312 .description = "Reference Counting",
313 .enabled = 0, .loglevel = LOGL_NOTICE,
314 },
315 [DGPRS] = {
316 .name = "DGPRS",
317 .description = "GPRS Packet Service",
318 .enabled = 1, .loglevel = LOGL_DEBUG,
319 },
320 [DNS] = {
321 .name = "DNS",
322 .description = "GPRS Network Service (NS)",
323 .enabled = 1, .loglevel = LOGL_INFO,
324 },
325 [DBSSGP] = {
326 .name = "DBSSGP",
327 .description = "GPRS BSS Gateway Protocol (BSSGP)",
328 .enabled = 1, .loglevel = LOGL_DEBUG,
329 },
330 [DLLC] = {
331 .name = "DLLC",
332 .description = "GPRS Logical Link Control Protocol (LLC)",
333 .enabled = 1, .loglevel = LOGL_DEBUG,
334 },
335 [DSNDCP] = {
336 .name = "DSNDCP",
337 .description = "GPRS Sub-Network Dependent Control Protocol (SNDCP)",
338 .enabled = 1, .loglevel = LOGL_DEBUG,
339 },
340};
341
342static struct log_info info = {
343 .cat = gprs_categories,
344 .num_cat = ARRAY_SIZE(gprs_categories),
345};
346
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +0200347int main(int argc, char **argv)
348{
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200349 osmo_init_logging(&info);
350 tall_bsc_ctx = talloc_named_const(NULL, 0, "osmo_sgsn");
351 tall_msgb_ctx = talloc_named_const(tall_bsc_ctx, 0, "msgb");
352
353 test_llme();
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200354 test_gmm_detach();
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100355 test_gmm_detach_power_off();
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200356 test_gmm_detach_no_mmctx();
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100357 test_gmm_status_no_mmctx();
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200358 printf("Done\n");
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +0200359 return 0;
360}
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200361
362
363/* stubs */
364struct osmo_prim_hdr;
365int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
366{
367 abort();
368}