blob: 6762ef88317e76bdf606177b46ef0a72a12107ae [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
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200103static void test_llme(void)
104{
105 struct gprs_llc_lle *lle, *lle_copy;
106 uint32_t local_tlli;
107 uint32_t foreign_tlli;
108
109 printf("Testing LLME allocations\n");
110 local_tlli = gprs_tmsi2tlli(0x234, TLLI_LOCAL);
111 foreign_tlli = gprs_tmsi2tlli(0x234, TLLI_FOREIGN);
112
113 /* initial state */
114 OSMO_ASSERT(count(gprs_llme_list()) == 0);
115
116 /* Create a new entry */
117 lle = gprs_lle_get_or_create(local_tlli, 3);
118 OSMO_ASSERT(lle);
119 OSMO_ASSERT(count(gprs_llme_list()) == 1);
120
121 /* No new entry is created */
122 lle_copy = gprs_lle_get_or_create(local_tlli, 3);
123 OSMO_ASSERT(lle == lle_copy);
124 OSMO_ASSERT(count(gprs_llme_list()) == 1);
125 lle_copy = gprs_lle_get_or_create(foreign_tlli, 3);
126 OSMO_ASSERT(lle == lle_copy);
127 OSMO_ASSERT(count(gprs_llme_list()) == 1);
128
129 /* unassign which should delete it*/
130 gprs_llgmm_assign(lle->llme, lle->llme->tlli, 0xffffffff, GPRS_ALGO_GEA0, NULL);
131
132 /* Check that everything was cleaned up */
133 OSMO_ASSERT(count(gprs_llme_list()) == 0);
134}
135
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200136/*
137 * Test that a GMM Detach will remove the MMCTX and the
138 * associated LLME.
139 */
140static void test_gmm_detach(void)
141{
142 struct gprs_ra_id raid = { 0, };
143 struct sgsn_mm_ctx *ctx, *ictx;
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200144 uint32_t local_tlli;
145 struct msgb *msg;
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100146 int sgsn_tx_counter_old;
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200147
148 printf("Testing GMM detach\n");
149
150 /* DTAP - Detach Request (MO) */
151 /* normal detach, power_off = 0 */
152 static const unsigned char detach_req[] = {
153 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xef, 0xe2,
154 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
155 };
156
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200157 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200158
Jacob Erlbeckabc16a52014-10-27 13:23:49 +0100159 /* Create a context */
160 OSMO_ASSERT(count(gprs_llme_list()) == 0);
161 ctx = alloc_mm_ctx(local_tlli, &raid);
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200162
163 /* inject the detach */
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100164 sgsn_tx_counter_old = sgsn_tx_counter;
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200165 msg = create_msg(detach_req, ARRAY_SIZE(detach_req));
166 msgb_tlli(msg) = local_tlli;
167 gsm0408_gprs_rcvmsg(msg, ctx->llme);
168 msgb_free(msg);
169
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100170 /* verify that a single message (hopefully the Detach Accept) has been
171 * sent by the SGSN */
172 OSMO_ASSERT(sgsn_tx_counter_old + 1 == sgsn_tx_counter);
173
174 /* verify that things are gone */
175 OSMO_ASSERT(count(gprs_llme_list()) == 0);
176 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
177 OSMO_ASSERT(!ictx);
178}
179
180/*
181 * Test that a GMM Detach will remove the MMCTX and the associated LLME but
182 * will not sent a Detach Accept message (power_off = 1)
183 */
184static void test_gmm_detach_power_off(void)
185{
186 struct gprs_ra_id raid = { 0, };
187 struct sgsn_mm_ctx *ctx, *ictx;
188 uint32_t local_tlli;
189 struct msgb *msg;
190 int sgsn_tx_counter_old;
191
192 printf("Testing GMM detach (power off)\n");
193
194 /* DTAP - Detach Request (MO) */
195 /* normal detach, power_off = 1 */
196 static const unsigned char detach_req[] = {
197 0x08, 0x05, 0x09, 0x18, 0x05, 0xf4, 0xef, 0xe2,
198 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
199 };
200
201 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
202
203 /* Create a context */
204 OSMO_ASSERT(count(gprs_llme_list()) == 0);
205 ctx = alloc_mm_ctx(local_tlli, &raid);
206
207 /* inject the detach */
208 sgsn_tx_counter_old = sgsn_tx_counter;
209 msg = create_msg(detach_req, ARRAY_SIZE(detach_req));
210 msgb_tlli(msg) = local_tlli;
211 gsm0408_gprs_rcvmsg(msg, ctx->llme);
212 msgb_free(msg);
213
214 /* verify that no message (and therefore no Detach Accept) has been
215 * sent by the SGSN */
Jacob Erlbeckb9ab0d42014-10-21 09:52:05 +0200216 OSMO_ASSERT(sgsn_tx_counter_old == sgsn_tx_counter);
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100217
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200218 /* verify that things are gone */
219 OSMO_ASSERT(count(gprs_llme_list()) == 0);
220 ictx = sgsn_mm_ctx_by_tlli(local_tlli, &raid);
Jacob Erlbeck258ce3d2014-09-30 13:51:45 +0200221 OSMO_ASSERT(!ictx);
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200222}
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200223
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200224/*
225 * Test that a GMM Detach will remove the associated LLME if there is no MMCTX.
226 */
227static void test_gmm_detach_no_mmctx(void)
228{
229 struct gprs_llc_lle *lle;
230 uint32_t local_tlli;
231 struct msgb *msg;
232
233 printf("Testing GMM detach (no MMCTX)\n");
234
235 /* DTAP - Detach Request (MO) */
236 /* normal detach, power_off = 0 */
237 static const unsigned char detach_req[] = {
238 0x08, 0x05, 0x01, 0x18, 0x05, 0xf4, 0xef, 0xe2,
239 0xb7, 0x00, 0x19, 0x03, 0xb9, 0x97, 0xcb
240 };
241
242 /* Create an LLME */
243 OSMO_ASSERT(count(gprs_llme_list()) == 0);
244 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
245 lle = gprs_lle_get_or_create(local_tlli, 3);
246
247 OSMO_ASSERT(count(gprs_llme_list()) == 1);
248
249 /* inject the detach */
250 msg = create_msg(detach_req, ARRAY_SIZE(detach_req));
251 msgb_tlli(msg) = local_tlli;
252 gsm0408_gprs_rcvmsg(msg, lle->llme);
253 msgb_free(msg);
254
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;
266 struct msgb *msg;
267 int sgsn_tx_counter_old;
268
269 printf("Testing GMM Status (no MMCTX)\n");
270
271 /* DTAP - GMM Status, protocol error */
272 static const unsigned char gmm_status[] = {
273 0x08, 0x20, 0x6f
274 };
275
276 /* Create an LLME */
277 OSMO_ASSERT(count(gprs_llme_list()) == 0);
278 local_tlli = gprs_tmsi2tlli(0x23, TLLI_LOCAL);
279 lle = gprs_lle_get_or_create(local_tlli, 3);
280
281 OSMO_ASSERT(count(gprs_llme_list()) == 1);
282
283 /* inject the detach */
284 sgsn_tx_counter_old = sgsn_tx_counter;
285 msg = create_msg(gmm_status, ARRAY_SIZE(gmm_status));
286 msgb_tlli(msg) = local_tlli;
287 gsm0408_gprs_rcvmsg(msg, lle->llme);
288 msgb_free(msg);
289
290 /* verify that no message has been sent by the SGSN */
291 OSMO_ASSERT(sgsn_tx_counter_old == sgsn_tx_counter);
292
293 /* verify that the LLME is gone */
294 OSMO_ASSERT(count(gprs_llme_list()) == 0);
295}
296
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200297static struct log_info_cat gprs_categories[] = {
298 [DMM] = {
299 .name = "DMM",
300 .description = "Layer3 Mobility Management (MM)",
301 .color = "\033[1;33m",
302 .enabled = 1, .loglevel = LOGL_NOTICE,
303 },
304 [DPAG] = {
305 .name = "DPAG",
306 .description = "Paging Subsystem",
307 .color = "\033[1;38m",
308 .enabled = 1, .loglevel = LOGL_NOTICE,
309 },
310 [DMEAS] = {
311 .name = "DMEAS",
312 .description = "Radio Measurement Processing",
313 .enabled = 0, .loglevel = LOGL_NOTICE,
314 },
315 [DREF] = {
316 .name = "DREF",
317 .description = "Reference Counting",
318 .enabled = 0, .loglevel = LOGL_NOTICE,
319 },
320 [DGPRS] = {
321 .name = "DGPRS",
322 .description = "GPRS Packet Service",
323 .enabled = 1, .loglevel = LOGL_DEBUG,
324 },
325 [DNS] = {
326 .name = "DNS",
327 .description = "GPRS Network Service (NS)",
328 .enabled = 1, .loglevel = LOGL_INFO,
329 },
330 [DBSSGP] = {
331 .name = "DBSSGP",
332 .description = "GPRS BSS Gateway Protocol (BSSGP)",
333 .enabled = 1, .loglevel = LOGL_DEBUG,
334 },
335 [DLLC] = {
336 .name = "DLLC",
337 .description = "GPRS Logical Link Control Protocol (LLC)",
338 .enabled = 1, .loglevel = LOGL_DEBUG,
339 },
340 [DSNDCP] = {
341 .name = "DSNDCP",
342 .description = "GPRS Sub-Network Dependent Control Protocol (SNDCP)",
343 .enabled = 1, .loglevel = LOGL_DEBUG,
344 },
345};
346
347static struct log_info info = {
348 .cat = gprs_categories,
349 .num_cat = ARRAY_SIZE(gprs_categories),
350};
351
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +0200352int main(int argc, char **argv)
353{
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200354 osmo_init_logging(&info);
355 tall_bsc_ctx = talloc_named_const(NULL, 0, "osmo_sgsn");
356 tall_msgb_ctx = talloc_named_const(tall_bsc_ctx, 0, "msgb");
357
358 test_llme();
Holger Hans Peter Freytherfe921332014-10-02 22:24:47 +0200359 test_gmm_detach();
Jacob Erlbeck189999d2014-10-27 14:34:13 +0100360 test_gmm_detach_power_off();
Jacob Erlbeck5a38f642014-10-21 13:09:55 +0200361 test_gmm_detach_no_mmctx();
Jacob Erlbeck14ae5822014-10-28 09:47:03 +0100362 test_gmm_status_no_mmctx();
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200363 printf("Done\n");
Holger Hans Peter Freyther68c6f882014-09-30 09:10:25 +0200364 return 0;
365}
Holger Hans Peter Freyther4299c052014-10-02 21:27:24 +0200366
367
368/* stubs */
369struct osmo_prim_hdr;
370int bssgp_prim_cb(struct osmo_prim_hdr *oph, void *ctx)
371{
372 abort();
373}