From Ivan.Kluchnikov at fairwaves.ru Fri Aug 2 09:56:47 2013 From: Ivan.Kluchnikov at fairwaves.ru (Ivan Kluchnikov) Date: Fri, 2 Aug 2013 13:56:47 +0400 Subject: [PATCH 8/9] tests: Create tests directory and move the VTY testing into there In-Reply-To: References: <1375212407-2209-1-git-send-email-hfreyther@sysmocom.de> <1375212407-2209-8-git-send-email-hfreyther@sysmocom.de> <20130731061331.GD32743@xiaoyu.lan> Message-ID: Hi Holger, I committed this patchset to master branch. 2013/7/31 Alexander Chemeris > On Wed, Jul 31, 2013 at 10:13 AM, Holger Hans Peter Freyther > wrote: > > On Wed, Jul 31, 2013 at 09:48:36AM +0400, Alexander Chemeris wrote: > > > Hi Holger, > > > > > > I don't see real files being moved (osmotestvty.py and > > > osmotestconfig.py). Probably you forgot to stage them? > > > > I think I didn't miss a file. The osmotestvty/osmotestconfig > > are two installed scripts and they read the app config from > > the abs_topsrcdir. It is mostly there to start using the > > test/ directory for tests. E.g RLCMACTest is moved there, the > > emulator PCU will be there and other tests while I move code > > around. > > Ok, sorry for false alert. Looked through this from a tablet and > assumed that all files are in-tree. > > -- > Regards, > Alexander Chemeris. > CEO, Fairwaves LLC / ??? ??????? > http://fairwaves.ru > > -- Regards, Ivan Kluchnikov. http://fairwaves.ru -------------- next part -------------- An HTML attachment was scrubbed... URL: From hfreyther at sysmocom.de Fri Aug 2 11:12:42 2013 From: hfreyther at sysmocom.de (Holger Hans Peter Freyther) Date: Fri, 2 Aug 2013 13:12:42 +0200 Subject: [PATCH 8/9] tests: Create tests directory and move the VTY testing into there In-Reply-To: References: <1375212407-2209-1-git-send-email-hfreyther@sysmocom.de> <1375212407-2209-8-git-send-email-hfreyther@sysmocom.de> <20130731061331.GD32743@xiaoyu.lan> Message-ID: <20130802111242.GK3997@xiaoyu.lan> On Fri, Aug 02, 2013 at 01:56:47PM +0400, Ivan Kluchnikov wrote: > Hi Holger, > > I committed this patchset to master branch. thanks a lot. I will post my PCU emu code. It is a manual test for our SGSN (but can also be a testbed for moving LLC code from OpenBSC to libosmocore, now I copy and pasted some routines/defines). I plan to extend this to also enable PDCHs.. and deal with csn1 packed bits at the end. Do you think it makes sense to keep it in the PCU? Another thing I will do is to start re-factoring these giant methods into smaller and unit-tested methods. I will also refactor the lookup of a TBF. It should really be based on TLLI and not only on IMSI, but more importantly the decision/logic of finding or creating a new TBF should really really really not be burried inside the Downlink-Data message routine. holger -- - Holger Freyther http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Schivelbeiner Str. 5 * 10439 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Geschaeftsfuehrer / Managing Directors: Holger Freyther, Harald Welte From andreas at eversberg.eu Mon Aug 5 11:11:33 2013 From: andreas at eversberg.eu (Andreas Eversberg) Date: Mon, 05 Aug 2013 13:11:33 +0200 Subject: C++ for the PCU In-Reply-To: References: <20130729113331.GE18752@xiaoyu.lan> <51F6885A.1080208@eversberg.eu> Message-ID: <51FF8865.7030306@eversberg.eu> Ivan Kluchnikov wrote: > Andreas, if you have patches for that and time, I believe that it make > sense to create new branch with these patches. > After that I can try to turn dissecting part from c++ to c. hi ivan, i juts pushed the old patches i made. (see jolly/outdated_c branch.) the last two patches show you what i did. the first patch moves all bitvector stuff to a sepeate file (is missing in this patch, but present in the next one). the second patch renames c++ code to c and changes c++ functions to c functions. it does not make sense to take any of the patches, since there is too many divergence between master and this branch, so just take it as an idea what i did. regards, andreas From hfreyther at sysmocom.de Thu Aug 22 07:16:58 2013 From: hfreyther at sysmocom.de (Holger Freyther) Date: Thu, 22 Aug 2013 09:16:58 +0200 Subject: [PATCH 04/10] bssgp: Return the gprs_bssgp_pcu instance from create/connect In-Reply-To: <1377155824-7598-1-git-send-email-hfreyther@sysmocom.de> References: <1377155824-7598-1-git-send-email-hfreyther@sysmocom.de> Message-ID: <1377155824-7598-4-git-send-email-hfreyther@sysmocom.de> From: Holger Hans Peter Freyther This can be used to install handlers/testcases to register callbacks and other data. --- src/gprs_bssgp_pcu.cpp | 33 +++++++++------------------------ src/gprs_bssgp_pcu.h | 19 ++++++++++++++++++- src/pcu_l1_if.cpp | 5 +++-- 3 files changed, 30 insertions(+), 27 deletions(-) diff --git a/src/gprs_bssgp_pcu.cpp b/src/gprs_bssgp_pcu.cpp index acd30a4..c332786 100644 --- a/src/gprs_bssgp_pcu.cpp +++ b/src/gprs_bssgp_pcu.cpp @@ -21,23 +21,7 @@ #include #include -struct osmo_pcu { - struct gprs_nsvc *nsvc; - struct bssgp_bvc_ctx *bctx; - - struct gprs_rlcmac_bts *bts; - - struct osmo_timer_list bvc_timer; - - int nsvc_unblocked; - - int bvc_sig_reset; - int bvc_reset; - int bvc_unblocked; - int exit_on_destroy; -}; - -static struct osmo_pcu the_pcu = { 0, }; +static struct gprs_bssgp_pcu the_pcu = { 0, }; extern void *tall_pcu_ctx; extern uint16_t spoof_mcc, spoof_mnc; @@ -591,7 +575,7 @@ static void bvc_timeout(void *_priv) } /* create BSSGP/NS layer instances */ -int gprs_bssgp_create_and_connect(struct gprs_rlcmac_bts *bts, +struct gprs_bssgp_pcu *gprs_bssgp_create_and_connect(struct gprs_rlcmac_bts *bts, uint16_t local_port, uint32_t sgsn_ip, uint16_t sgsn_port, uint16_t nsei, uint16_t nsvci, uint16_t bvci, uint16_t mcc, uint16_t mnc, uint16_t lac, uint16_t rac, @@ -604,15 +588,16 @@ int gprs_bssgp_create_and_connect(struct gprs_rlcmac_bts *bts, mnc = ((mnc & 0xf00) >> 8) * 100 + ((mnc & 0x0f0) >> 4) * 10 + (mnc & 0x00f); cell_id = ntohs(cell_id); + /* if already created... return the current address */ if (the_pcu.bctx) - return 0; /* if already created, must return 0: no error */ + return &the_pcu; the_pcu.bts = bts; bssgp_nsi = gprs_ns_instantiate(&sgsn_ns_cb, tall_pcu_ctx); if (!bssgp_nsi) { LOGP(DBSSGP, LOGL_ERROR, "Failed to create NS instance\n"); - return -EINVAL; + return NULL; } gprs_ns_vty_init(bssgp_nsi); bssgp_nsi->nsip.local_port = local_port; @@ -621,7 +606,7 @@ int gprs_bssgp_create_and_connect(struct gprs_rlcmac_bts *bts, LOGP(DBSSGP, LOGL_ERROR, "Failed to create socket\n"); gprs_ns_destroy(bssgp_nsi); bssgp_nsi = NULL; - return -EINVAL; + return NULL; } dest.sin_family = AF_INET; @@ -633,7 +618,7 @@ int gprs_bssgp_create_and_connect(struct gprs_rlcmac_bts *bts, LOGP(DBSSGP, LOGL_ERROR, "Failed to create NSVCt\n"); gprs_ns_destroy(bssgp_nsi); bssgp_nsi = NULL; - return -EINVAL; + return NULL; } the_pcu.bctx = btsctx_alloc(bvci, nsei); @@ -642,7 +627,7 @@ int gprs_bssgp_create_and_connect(struct gprs_rlcmac_bts *bts, the_pcu.nsvc = NULL; gprs_ns_destroy(bssgp_nsi); bssgp_nsi = NULL; - return -EINVAL; + return NULL; } the_pcu.bctx->ra_id.mcc = spoof_mcc ? : mcc; the_pcu.bctx->ra_id.mnc = spoof_mnc ? : mnc; @@ -655,7 +640,7 @@ int gprs_bssgp_create_and_connect(struct gprs_rlcmac_bts *bts, the_pcu.bvc_timer.cb = bvc_timeout; - return 0; + return &the_pcu; } void gprs_bssgp_destroy_or_exit(void) diff --git a/src/gprs_bssgp_pcu.h b/src/gprs_bssgp_pcu.h index 15c8d9f..2d96032 100644 --- a/src/gprs_bssgp_pcu.h +++ b/src/gprs_bssgp_pcu.h @@ -41,7 +41,24 @@ struct bssgp_bvc_ctx *btsctx_alloc(uint16_t bvci, uint16_t nsei); #define NS_HDR_LEN 4 #define IE_LLC_PDU 14 -int gprs_bssgp_create_and_connect(struct gprs_rlcmac_bts *bts, uint16_t local_port, +struct gprs_bssgp_pcu { + struct gprs_nsvc *nsvc; + struct bssgp_bvc_ctx *bctx; + + struct gprs_rlcmac_bts *bts; + + struct osmo_timer_list bvc_timer; + + int nsvc_unblocked; + + int bvc_sig_reset; + int bvc_reset; + int bvc_unblocked; + int exit_on_destroy; +}; + +struct gprs_bssgp_pcu *gprs_bssgp_create_and_connect(struct gprs_rlcmac_bts *bts, + uint16_t local_port, uint32_t sgsn_ip, uint16_t sgsn_port, uint16_t nsei, uint16_t nsvci, uint16_t bvci, uint16_t mcc, uint16_t mnc, uint16_t lac, uint16_t rac, uint16_t cell_id); diff --git a/src/pcu_l1_if.cpp b/src/pcu_l1_if.cpp index e53b683..43bd36e 100644 --- a/src/pcu_l1_if.cpp +++ b/src/pcu_l1_if.cpp @@ -336,6 +336,7 @@ int flush_pdch(struct gprs_rlcmac_pdch *pdch, uint8_t trx, uint8_t ts) static int pcu_rx_info_ind(struct gsm_pcu_if_info_ind *info_ind) { struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts; + struct gprs_bssgp_pcu *pcu; struct gprs_rlcmac_pdch *pdch; struct in_addr ia; int rc = 0; @@ -418,12 +419,12 @@ bssgp_failed: ia.s_addr = htonl(info_ind->remote_ip[0]); LOGP(DL1IF, LOGL_DEBUG, " remote_ip=%s\n", inet_ntoa(ia)); - rc = gprs_bssgp_create_and_connect(bts, info_ind->local_port[0], + pcu = gprs_bssgp_create_and_connect(bts, info_ind->local_port[0], info_ind->remote_ip[0], info_ind->remote_port[0], info_ind->nsei, info_ind->nsvci[0], info_ind->bvci, info_ind->mcc, info_ind->mnc, info_ind->lac, info_ind->rac, info_ind->cell_id); - if (rc < 0) { + if (!pcu) { LOGP(DL1IF, LOGL_NOTICE, "SGSN not available\n"); goto bssgp_failed; } -- 1.8.3.2 From hfreyther at sysmocom.de Thu Aug 22 07:17:02 2013 From: hfreyther at sysmocom.de (Holger Freyther) Date: Thu, 22 Aug 2013 09:17:02 +0200 Subject: [PATCH 08/10] emu: Send a static GPRS ATTACH request and wait for the reply. In-Reply-To: <1377155824-7598-1-git-send-email-hfreyther@sysmocom.de> References: <1377155824-7598-1-git-send-email-hfreyther@sysmocom.de> Message-ID: <1377155824-7598-8-git-send-email-hfreyther@sysmocom.de> From: Holger Hans Peter Freyther This will send a static message. It will trigger the GMM code on the SGSN and might ask us for the IMEI/IMSI or send us an accept. As we are not replying at all the SGSN needs to send new requests and we can observe if the sequence number is increasing like it should. --- tests/Makefile.am | 2 +- tests/emu/pcu_emu.cpp | 5 +++- tests/emu/test_replay_gprs_attach.cpp | 56 +++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 tests/emu/test_replay_gprs_attach.cpp diff --git a/tests/Makefile.am b/tests/Makefile.am index a037618..7216d3b 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -9,7 +9,7 @@ rlcmac_RLCMACTest_LDADD = \ $(LIBOSMOCORE_LIBS) \ $(COMMON_LA) -emu_pcu_emu_SOURCES = emu/pcu_emu.cpp +emu_pcu_emu_SOURCES = emu/pcu_emu.cpp emu/test_replay_gprs_attach.cpp emu_pcu_emu_LDADD = \ $(top_builddir)/src/libgprs.la \ $(LIBOSMOGB_LIBS) \ diff --git a/tests/emu/pcu_emu.cpp b/tests/emu/pcu_emu.cpp index f78285d..337c0c8 100644 --- a/tests/emu/pcu_emu.cpp +++ b/tests/emu/pcu_emu.cpp @@ -36,6 +36,8 @@ void *tall_pcu_ctx; struct gprs_rlcmac_bts *gprs_rlcmac_bts; int16_t spoof_mnc = 0, spoof_mcc = 0; +extern void test_replay_gprs_attach(struct gprs_bssgp_pcu *pcu); + struct gprs_rlcmac_bts *create_bts() { struct gprs_rlcmac_bts *bts; @@ -62,9 +64,10 @@ struct gprs_rlcmac_bts *create_bts() return bts; } -static void bvci_unblocked(struct gprs_bssgp_pcu *pci) +static void bvci_unblocked(struct gprs_bssgp_pcu *pcu) { printf("BVCI unblocked. We can begin with test cases.\n"); + test_replay_gprs_attach(pcu); } void create_and_connect_bssgp(struct gprs_rlcmac_bts *bts, diff --git a/tests/emu/test_replay_gprs_attach.cpp b/tests/emu/test_replay_gprs_attach.cpp new file mode 100644 index 0000000..500b16e --- /dev/null +++ b/tests/emu/test_replay_gprs_attach.cpp @@ -0,0 +1,56 @@ +/* (C) 2013 by Holger Hans Peter Freyther + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +extern "C" { +#include +} + +#include + +#include +#include + +static const uint8_t gprs_attach_llc[] = { + /* LLC-PDU IE */ + 0x0e, 0x00, 0x2e, + + 0x01, 0xc0, 0x01, 0x08, 0x01, 0x02, 0xf5, 0x40, + 0x71, 0x08, 0x00, 0x05, 0xf4, 0x2d, 0xf1, 0x18, + 0x20, 0x62, 0xf2, 0x10, 0x09, 0x67, 0x00, 0x13, + 0x16, 0x73, 0x43, 0x2a, 0x80, 0x42, 0x00, 0x42, + 0x88, 0x0b, 0x04, 0x20, 0x04, 0x2e, 0x82, 0x30, + 0x42, 0x00, 0x40, 0xaa, 0xf3, 0x18 +}; + +struct msgb *create_msg(const uint8_t *data, size_t len) +{ + struct msgb *msg = msgb_alloc_headroom(4096, 128, "create msg"); + msg->l3h = msgb_put(msg, len); + memcpy(msg->l3h, data, len); + return msg; +} + +void test_replay_gprs_attach(struct gprs_bssgp_pcu *pcu) +{ + uint32_t tlli = 0xadf11820; + const uint8_t qos_profile[] = { 0x0, 0x0, 0x04 }; + + struct msgb *msg = create_msg(gprs_attach_llc, ARRAY_SIZE(gprs_attach_llc)); + bssgp_tx_ul_ud(pcu->bctx, tlli, qos_profile, msg); +} -- 1.8.3.2 From hfreyther at sysmocom.de Thu Aug 22 07:16:59 2013 From: hfreyther at sysmocom.de (Holger Freyther) Date: Thu, 22 Aug 2013 09:16:59 +0200 Subject: [PATCH 05/10] bssgp: Add callbacks for certain BSSGP events In-Reply-To: <1377155824-7598-1-git-send-email-hfreyther@sysmocom.de> References: <1377155824-7598-1-git-send-email-hfreyther@sysmocom.de> Message-ID: <1377155824-7598-5-git-send-email-hfreyther@sysmocom.de> From: Holger Hans Peter Freyther Add a callback called when Unblock Ack is received. This can be used by a supervisor or the emulation test. --- src/gprs_bssgp_pcu.cpp | 2 ++ src/gprs_bssgp_pcu.h | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/src/gprs_bssgp_pcu.cpp b/src/gprs_bssgp_pcu.cpp index c332786..cc66290 100644 --- a/src/gprs_bssgp_pcu.cpp +++ b/src/gprs_bssgp_pcu.cpp @@ -386,6 +386,8 @@ static int gprs_bssgp_pcu_rx_sign(struct msgb *msg, struct tlv_parsed *tp, struc case BSSGP_PDUT_BVC_UNBLOCK_ACK: LOGP(DBSSGP, LOGL_DEBUG, "rx BSSGP_PDUT_BVC_UNBLOCK_ACK\n"); the_pcu.bvc_unblocked = 1; + if (the_pcu.on_unblock_ack) + the_pcu.on_unblock_ack(&the_pcu); bvc_timeout(NULL); break; case BSSGP_PDUT_SGSN_INVOKE_TRACE: diff --git a/src/gprs_bssgp_pcu.h b/src/gprs_bssgp_pcu.h index 2d96032..413c056 100644 --- a/src/gprs_bssgp_pcu.h +++ b/src/gprs_bssgp_pcu.h @@ -1,6 +1,7 @@ /* gprs_bssgp_pcu.h * * Copyright (C) 2012 Ivan Klyuchnikov + * Copyright (C) 2013 by Holger Hans Peter Freyther * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -55,6 +56,11 @@ struct gprs_bssgp_pcu { int bvc_reset; int bvc_unblocked; int exit_on_destroy; + + /** callbacks below */ + + /* The BSSGP has been unblocked */ + void (*on_unblock_ack)(struct gprs_bssgp_pcu *pcu); }; struct gprs_bssgp_pcu *gprs_bssgp_create_and_connect(struct gprs_rlcmac_bts *bts, -- 1.8.3.2 From hfreyther at sysmocom.de Thu Aug 22 07:17:04 2013 From: hfreyther at sysmocom.de (Holger Freyther) Date: Thu, 22 Aug 2013 09:17:04 +0200 Subject: [PATCH 10/10] emu: Add a crash re-producer for the SGSN (and the concept of tests) In-Reply-To: <1377155824-7598-1-git-send-email-hfreyther@sysmocom.de> References: <1377155824-7598-1-git-send-email-hfreyther@sysmocom.de> Message-ID: <1377155824-7598-10-git-send-email-hfreyther@sysmocom.de> From: Holger Hans Peter Freyther Introduce the concept of tests that will be ran one after the other. This new test will send static message that will lead to the opening of a PDP context. At this point one should use ping with a large packet size and suspend/stop the emulator. Once the NS connection is considered dead the SGSN will crash with a double free. Reproduce: 0.) Add IMSI 901700000003094 to the ACL 1.) Stop/Suspend the emulation process so the NS Alive times out 2.) Use ping IP -s 2048 This will create a double free... #4 0xb7bb2646 in talloc_abort_double_free () at talloc.c:175 #5 0xb7bbd41a in talloc_chunk_from_ptr (ptr=0x8091208) at talloc.c:190 #6 _talloc_free (ptr=0x8091208) at talloc.c:517 #7 talloc_free (ptr=ptr at entry=0x8091208) at talloc.c:990 #8 0xb7bb319b in msgb_free (m=m at entry=0x8091208) at msgb.c:72 #9 0x0804db54 in sndcp_send_ud_frag (fs=0xbfffcc6c) at gprs_sndcp.c:423 #10 sndcp_unitdata_req (msg=msg at entry=0x808eed8, lle=0x808fbc8, nsapi=5 '\005', mmcontext=mmcontext at entry=0x80903e8) at gprs_sndcp.c:471 --- tests/Makefile.am | 3 +- tests/emu/gprs_tests.h | 56 +++++++++++ tests/emu/openbsc_clone.c | 19 ++++ tests/emu/openbsc_clone.h | 32 +++++++ tests/emu/pcu_emu.cpp | 47 +++++++++- tests/emu/test_pdp_activation.cpp | 172 ++++++++++++++++++++++++++++++++++ tests/emu/test_replay_gprs_attach.cpp | 15 +-- 7 files changed, 330 insertions(+), 14 deletions(-) create mode 100644 tests/emu/gprs_tests.h create mode 100644 tests/emu/test_pdp_activation.cpp diff --git a/tests/Makefile.am b/tests/Makefile.am index 0131e47..88be652 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -10,7 +10,8 @@ rlcmac_RLCMACTest_LDADD = \ $(COMMON_LA) emu_pcu_emu_SOURCES = emu/pcu_emu.cpp emu/test_replay_gprs_attach.cpp \ - emu/openbsc_clone.c emu/openbsc_clone.h + emu/openbsc_clone.c emu/openbsc_clone.h emu/gprs_tests.h \ + emu/test_pdp_activation.cpp emu_pcu_emu_LDADD = \ $(top_builddir)/src/libgprs.la \ $(LIBOSMOGB_LIBS) \ diff --git a/tests/emu/gprs_tests.h b/tests/emu/gprs_tests.h new file mode 100644 index 0000000..eeb4f82 --- /dev/null +++ b/tests/emu/gprs_tests.h @@ -0,0 +1,56 @@ +/* (C) 2013 by Holger Hans Peter Freyther + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +#ifndef tests_h +#define tests_h + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +struct gprs_bssgp_pcu; +struct tlv_parsed; +struct msgb; + +struct gprs_test { + const char *name; + const char *description; + void (*start)(struct gprs_bssgp_pcu *); + void (*data) (struct gprs_bssgp_pcu *, struct msgb *, struct tlv_parsed *); +}; + +void gprs_test_success(struct gprs_bssgp_pcu *); + +static inline struct msgb *create_msg(const uint8_t *data, size_t len) +{ + struct msgb *msg = msgb_alloc_headroom(4096, 128, "create msg"); + msg->l3h = msgb_put(msg, len); + memcpy(msg->l3h, data, len); + return msg; +} + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/tests/emu/openbsc_clone.c b/tests/emu/openbsc_clone.c index 707819b..b1052ff 100644 --- a/tests/emu/openbsc_clone.c +++ b/tests/emu/openbsc_clone.c @@ -21,6 +21,7 @@ #include #include +#include #include @@ -214,3 +215,21 @@ int gprs_llc_hdr_parse(struct gprs_llc_hdr_parsed *ghp, return 0; } + +const struct tlv_definition gsm48_gmm_att_tlvdef = { + .def = { + [GSM48_IE_GMM_CIPH_CKSN] = { TLV_TYPE_FIXED, 1 }, + [GSM48_IE_GMM_TIMER_READY] = { TLV_TYPE_TV, 1 }, + [GSM48_IE_GMM_ALLOC_PTMSI] = { TLV_TYPE_TLV, 0 }, + [GSM48_IE_GMM_PTMSI_SIG] = { TLV_TYPE_FIXED, 3 }, + [GSM48_IE_GMM_AUTH_RAND] = { TLV_TYPE_FIXED, 16 }, + [GSM48_IE_GMM_AUTH_SRES] = { TLV_TYPE_FIXED, 4 }, + [GSM48_IE_GMM_IMEISV] = { TLV_TYPE_TLV, 0 }, + [GSM48_IE_GMM_DRX_PARAM] = { TLV_TYPE_FIXED, 2 }, + [GSM48_IE_GMM_MS_NET_CAPA] = { TLV_TYPE_TLV, 0 }, + [GSM48_IE_GMM_PDP_CTX_STATUS] = { TLV_TYPE_TLV, 0 }, + [GSM48_IE_GMM_PS_LCS_CAPA] = { TLV_TYPE_TLV, 0 }, + [GSM48_IE_GMM_GMM_MBMS_CTX_ST] = { TLV_TYPE_TLV, 0 }, + }, +}; + diff --git a/tests/emu/openbsc_clone.h b/tests/emu/openbsc_clone.h index d62ff22..b3cc033 100644 --- a/tests/emu/openbsc_clone.h +++ b/tests/emu/openbsc_clone.h @@ -23,6 +23,8 @@ extern "C" { #endif +#include + #include enum gprs_llc_cmd { @@ -57,6 +59,36 @@ struct gprs_llc_hdr_parsed { int gprs_llc_hdr_parse(struct gprs_llc_hdr_parsed *ghp, const uint8_t *llc_hdr, int len); +/* Table 10.4 / 10.4a, GPRS Mobility Management (GMM) */ +#define GSM48_MT_GMM_ATTACH_ACK 0x02 + +/* Chapter 9.4.2 / Table 9.4.2 */ +struct gsm48_attach_ack { + uint8_t att_result:4, /* 10.5.5.7 */ + force_stby:4; /* 10.5.5.1 */ + uint8_t ra_upd_timer; /* 10.5.7.3 */ + uint8_t radio_prio; /* 10.5.7.2 */ + struct gsm48_ra_id ra_id; /* 10.5.5.15 */ + uint8_t data[0]; +} __attribute__((packed)); + +enum gsm48_gprs_ie_mm { + GSM48_IE_GMM_CIPH_CKSN = 0x08, /* 10.5.1.2 */ + GSM48_IE_GMM_TIMER_READY = 0x17, /* 10.5.7.3 */ + GSM48_IE_GMM_ALLOC_PTMSI = 0x18, /* 10.5.1.4 */ + GSM48_IE_GMM_PTMSI_SIG = 0x19, /* 10.5.5.8 */ + GSM48_IE_GMM_AUTH_RAND = 0x21, /* 10.5.3.1 */ + GSM48_IE_GMM_AUTH_SRES = 0x22, /* 10.5.3.2 */ + GSM48_IE_GMM_IMEISV = 0x23, /* 10.5.1.4 */ + GSM48_IE_GMM_DRX_PARAM = 0x27, /* 10.5.5.6 */ + GSM48_IE_GMM_MS_NET_CAPA = 0x31, /* 10.5.5.12 */ + GSM48_IE_GMM_PDP_CTX_STATUS = 0x32, /* 10.5.7.1 */ + GSM48_IE_GMM_PS_LCS_CAPA = 0x33, /* 10.5.5.22 */ + GSM48_IE_GMM_GMM_MBMS_CTX_ST = 0x35, /* 10.5.7.6 */ +}; + +extern const struct tlv_definition gsm48_gmm_att_tlvdef; + #ifdef __cplusplus } #endif diff --git a/tests/emu/pcu_emu.cpp b/tests/emu/pcu_emu.cpp index f4d38cd..4731a60 100644 --- a/tests/emu/pcu_emu.cpp +++ b/tests/emu/pcu_emu.cpp @@ -24,6 +24,9 @@ extern "C" { #include } +#include "gprs_tests.h" + + #include #include @@ -31,6 +34,8 @@ extern "C" { #include #include +static int current_test; + /* Extern data to please the underlying code */ void *tall_pcu_ctx; struct gprs_rlcmac_bts *gprs_rlcmac_bts; @@ -39,6 +44,29 @@ int16_t spoof_mnc = 0, spoof_mcc = 0; extern void test_replay_gprs_attach(struct gprs_bssgp_pcu *pcu); extern void test_replay_gprs_data(struct gprs_bssgp_pcu *, struct msgb *, struct tlv_parsed *); +extern void test_pdp_activation_start(struct gprs_bssgp_pcu *pcu); +extern void test_pdp_activation_data(struct gprs_bssgp_pcu *, struct msgb *, struct tlv_parsed*); + + +struct gprs_test all_tests[] = { + { + .name = "gprs_attach_with_tmsi", + .description = "A simple test that verifies that N(U) is " + "increasing across various messages. This makes " + "sure that no new LLE/LLME is created on the fly.", + .start = test_replay_gprs_attach, + .data = test_replay_gprs_data, + }, + { + .name = "gprs_full_attach_pdp_activation", + .description = "A simple test to do a GPRS attach and open a PDP " + "context. Then goes to sleep and waits for you to ping " + "the connection and hopefully re-produce a crash.", + .start = test_pdp_activation_start, + .data = test_pdp_activation_data, + }, +}; + struct gprs_rlcmac_bts *create_bts() { struct gprs_rlcmac_bts *bts; @@ -68,12 +96,12 @@ struct gprs_rlcmac_bts *create_bts() static void bvci_unblocked(struct gprs_bssgp_pcu *pcu) { printf("BVCI unblocked. We can begin with test cases.\n"); - test_replay_gprs_attach(pcu); + all_tests[current_test].start(pcu); } static void bssgp_data(struct gprs_bssgp_pcu *pcu, struct msgb *msg, struct tlv_parsed *tp) { - test_replay_gprs_data(pcu, msg, tp); + all_tests[current_test].data(pcu, msg, tp); } void create_and_connect_bssgp(struct gprs_rlcmac_bts *bts, @@ -112,6 +140,21 @@ int main(int argc, char **argv) return EXIT_SUCCESS; } + +/* + * Test handling.. + */ +void gprs_test_success(struct gprs_bssgp_pcu *pcu) +{ + current_test += 1; + if (current_test >= ARRAY_SIZE(all_tests)) { + printf("All tests executed.\n"); + exit(EXIT_SUCCESS); + } + + all_tests[current_test].start(pcu); +} + /* * stubs that should not be reached */ diff --git a/tests/emu/test_pdp_activation.cpp b/tests/emu/test_pdp_activation.cpp new file mode 100644 index 0000000..909b308 --- /dev/null +++ b/tests/emu/test_pdp_activation.cpp @@ -0,0 +1,172 @@ +/* (C) 2013 by Holger Hans Peter Freyther + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +extern "C" { +#include +#include +#include +} + +#include "openbsc_clone.h" +#include "gprs_tests.h" + +#include + +#include +#include + +static const uint8_t attach[] = { + 0x0e, 0x00, 0x26, + 0x01, 0xc0, 0x01, 0x08, 0x01, 0x02, 0xe5, 0x80, + 0x71, 0x0d, 0x01, 0x05, 0xf4, 0x02, 0x30, 0xef, + 0x0e, 0x09, 0xf1, 0x07, 0x00, 0x01, 0x00, 0x0b, + 0x34, 0xc7, 0x03, 0x2a, 0xa0, 0x42, 0x7c, 0xad, + 0xe1, 0x18, 0x0b, 0xf8, 0xef, 0xfc +}; + +static const uint8_t id_resp_imei[] = { + 0x0e, 0x00, 0x11, + 0x01, 0xc0, 0x05, 0x08, 0x16, 0x08, 0x3a, 0x49, + 0x50, 0x13, 0x28, 0x15, 0x80, 0x01, 0x21, 0x6c, + 0x22 +}; + +static const uint8_t id_resp_imsi[] = { + 0x0e, 0x00, 0x11, + 0x01, 0xc0, 0x09, 0x08, 0x16, 0x08, 0x99, 0x10, + 0x07, 0x00, 0x00, 0x00, 0x03, 0x49, 0xc7, 0x5b, + 0xb6 +}; + +static const uint8_t attach_complete[] = { + 0x0e, 0x00, 0x08, + 0x01, 0xc0, 0x0d, 0x08, 0x03, 0x55, 0x1c, 0xea +}; + +static const uint8_t pdp_context[] = { + 0x0e, 0x00, 0x5a, + 0x01, 0xc0, 0x11, 0x0a, 0x41, 0x05, 0x03, 0x0c, + 0x00, 0x00, 0x1f, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x21, 0x28, + 0x12, 0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, + 0x65, 0x74, 0x05, 0x65, 0x70, 0x6c, 0x75, 0x73, + 0x02, 0x64, 0x65, 0x27, 0x2a, 0x80, 0xc0, 0x23, + 0x13, 0x01, 0x00, 0x00, 0x13, 0x05, 0x65, 0x70, + 0x6c, 0x75, 0x73, 0x08, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x65, 0x74, 0x80, 0x21, 0x10, 0x01, + 0x00, 0x00, 0x10, 0x81, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x83, 0x06, 0x00, 0x00, 0x00, 0x00, 0xcf, + 0x90, 0xcc +}; + +static const uint8_t qos_profile[] = { 0x0, 0x0, 0x04 }; +static uint32_t tlli = 0xadf11821; + +enum state { + Test_Start, + Test_IdRespIMEI, + Test_IdRespIMSI, + Test_AttachCompl, + Test_PDPAct, + Test_Done, +}; + +static enum state current_state = Test_Start; + +static void extract_tmsi_and_generate_tlli(struct msgb *msg, struct tlv_parsed *tp) +{ + uint32_t tmsi; + struct bssgp_ud_hdr *budh; + struct gprs_llc_hdr_parsed hp; + struct tlv_parsed ack_tp; + int rc; + + gprs_llc_hdr_parse(&hp, TLVP_VAL(tp, BSSGP_IE_LLC_PDU), + TLVP_LEN(tp, BSSGP_IE_LLC_PDU)); + msgb_gmmh(msg) = (unsigned char *) hp.data; + + struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg); + + OSMO_ASSERT(gh->msg_type == GSM48_MT_GMM_ATTACH_ACK); + struct gsm48_attach_ack *ack = (struct gsm48_attach_ack *) gh->data; + rc = tlv_parse(&ack_tp, &gsm48_gmm_att_tlvdef, ack->data, + (msg->data + msg->len) - ack->data, 0, 0); + + + OSMO_ASSERT(TLVP_PRESENT(&ack_tp, GSM48_IE_GMM_ALLOC_PTMSI)); + memcpy(&tmsi, TLVP_VAL(&ack_tp, GSM48_IE_GMM_ALLOC_PTMSI) + 1, 4); + tmsi = ntohl(tmsi); + tlli = gprs_tmsi2tlli(tmsi, TLLI_LOCAL); + printf("New TLLI(0x%08x) based on tmsi(0x%x)\n", tlli, tmsi); +} + +void test_pdp_activation_start(struct gprs_bssgp_pcu *pcu) +{ + struct msgb *msg = create_msg(attach, ARRAY_SIZE(attach)); + bssgp_tx_ul_ud(pcu->bctx, tlli, qos_profile, msg); + current_state = Test_IdRespIMEI; +} + + +void test_pdp_activation_data(struct gprs_bssgp_pcu *pcu, struct msgb *msg, struct tlv_parsed *tp) +{ + const uint8_t *data; + size_t len; + + switch (current_state) { + case Test_IdRespIMEI: + data = id_resp_imei; + len = ARRAY_SIZE(id_resp_imei); + current_state = Test_IdRespIMSI; + break; + case Test_IdRespIMSI: + data = id_resp_imsi; + len = ARRAY_SIZE(id_resp_imsi); + current_state = Test_AttachCompl; + break; + case Test_AttachCompl: + data = attach_complete; + len = ARRAY_SIZE(attach_complete); + extract_tmsi_and_generate_tlli(msg, tp); + current_state = Test_PDPAct; + break; + case Test_PDPAct: + printf("PDP context is active or not...\n"); + return; + break; + case Test_Done: + case Test_Start: /* fall through */ + return; + break; + default: + printf("Unknown state. %d\n", current_state); + return; + break; + }; + + struct msgb *out = create_msg(data, len); + bssgp_tx_ul_ud(pcu->bctx, tlli, qos_profile, out); + + /* send it after the PDP... */ + if (current_state == Test_PDPAct) { + out = create_msg(pdp_context, ARRAY_SIZE(pdp_context)); + bssgp_tx_ul_ud(pcu->bctx, tlli, qos_profile, out); + } +} + diff --git a/tests/emu/test_replay_gprs_attach.cpp b/tests/emu/test_replay_gprs_attach.cpp index fb1e77f..9bcab57 100644 --- a/tests/emu/test_replay_gprs_attach.cpp +++ b/tests/emu/test_replay_gprs_attach.cpp @@ -24,6 +24,7 @@ extern "C" { } #include "openbsc_clone.h" +#include "gprs_tests.h" #include @@ -45,14 +46,6 @@ static const uint8_t gprs_attach_llc[] = { static int next_wanted_nu; -struct msgb *create_msg(const uint8_t *data, size_t len) -{ - struct msgb *msg = msgb_alloc_headroom(4096, 128, "create msg"); - msg->l3h = msgb_put(msg, len); - memcpy(msg->l3h, data, len); - return msg; -} - void test_replay_gprs_attach(struct gprs_bssgp_pcu *pcu) { uint32_t tlli = 0xadf11820; @@ -88,8 +81,8 @@ void test_replay_gprs_data(struct gprs_bssgp_pcu *pcu, struct msgb *msg, struct OSMO_ASSERT(ph.seq_tx == next_wanted_nu++); /* this test just wants to see messages... no further data is sent */ - if (next_wanted_nu == 4) { - printf("Test done.\n"); - exit(EXIT_SUCCESS); + if (next_wanted_nu == 6) { + printf("GPRS attach with increasing N(U) done.\n"); + gprs_test_success(pcu); } } -- 1.8.3.2 From hfreyther at sysmocom.de Thu Aug 22 07:17:00 2013 From: hfreyther at sysmocom.de (Holger Freyther) Date: Thu, 22 Aug 2013 09:17:00 +0200 Subject: [PATCH 06/10] bssgp: Add callback UNITDATA.DL messaes with the data In-Reply-To: <1377155824-7598-1-git-send-email-hfreyther@sysmocom.de> References: <1377155824-7598-1-git-send-email-hfreyther@sysmocom.de> Message-ID: <1377155824-7598-6-git-send-email-hfreyther@sysmocom.de> From: Holger Hans Peter Freyther --- src/gprs_bssgp_pcu.cpp | 3 +++ src/gprs_bssgp_pcu.h | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/src/gprs_bssgp_pcu.cpp b/src/gprs_bssgp_pcu.cpp index cc66290..6f67f52 100644 --- a/src/gprs_bssgp_pcu.cpp +++ b/src/gprs_bssgp_pcu.cpp @@ -1,6 +1,7 @@ /* gprs_bssgp_pcu.cpp * * Copyright (C) 2012 Ivan Klyuchnikov + * Copyright (C) 2013 by Holger Hans Peter Freyther * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -314,6 +315,8 @@ static int gprs_bssgp_pcu_rx_ptp(struct msgb *msg, struct tlv_parsed *tp, struct switch (pdu_type) { case BSSGP_PDUT_DL_UNITDATA: LOGP(DBSSGP, LOGL_DEBUG, "RX: [SGSN->PCU] BSSGP_PDUT_DL_UNITDATA\n"); + if (the_pcu.on_dl_unit_data) + the_pcu.on_dl_unit_data(&the_pcu, msg, tp); gprs_bssgp_pcu_rx_dl_ud(msg, tp); break; case BSSGP_PDUT_PAGING_PS: diff --git a/src/gprs_bssgp_pcu.h b/src/gprs_bssgp_pcu.h index 413c056..7156bf0 100644 --- a/src/gprs_bssgp_pcu.h +++ b/src/gprs_bssgp_pcu.h @@ -61,6 +61,10 @@ struct gprs_bssgp_pcu { /* The BSSGP has been unblocked */ void (*on_unblock_ack)(struct gprs_bssgp_pcu *pcu); + + /* When BSSGP data arrives. The msgb is not only for reference */ + void (*on_dl_unit_data)(struct gprs_bssgp_pcu *pcu, struct msgb *msg, + struct tlv_parsed *tp); }; struct gprs_bssgp_pcu *gprs_bssgp_create_and_connect(struct gprs_rlcmac_bts *bts, -- 1.8.3.2 From hfreyther at sysmocom.de Thu Aug 22 07:16:56 2013 From: hfreyther at sysmocom.de (Holger Freyther) Date: Thu, 22 Aug 2013 09:16:56 +0200 Subject: [PATCH 02/10] bssgp: These routines are not public API.. make them static for now In-Reply-To: <1377155824-7598-1-git-send-email-hfreyther@sysmocom.de> References: <1377155824-7598-1-git-send-email-hfreyther@sysmocom.de> Message-ID: <1377155824-7598-2-git-send-email-hfreyther@sysmocom.de> From: Holger Hans Peter Freyther --- src/gprs_bssgp_pcu.cpp | 8 ++++---- src/gprs_bssgp_pcu.h | 8 -------- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/src/gprs_bssgp_pcu.cpp b/src/gprs_bssgp_pcu.cpp index 4326303..a0ef206 100644 --- a/src/gprs_bssgp_pcu.cpp +++ b/src/gprs_bssgp_pcu.cpp @@ -112,7 +112,7 @@ static int parse_ra_cap_ms_class(struct tlv_parsed *tp) return ms_class; } -int gprs_bssgp_pcu_rx_dl_ud(struct msgb *msg, struct tlv_parsed *tp) +static int gprs_bssgp_pcu_rx_dl_ud(struct msgb *msg, struct tlv_parsed *tp) { struct bssgp_ud_hdr *budh; @@ -307,7 +307,7 @@ int gprs_bssgp_pcu_rx_paging_ps(struct msgb *msg, struct tlv_parsed *tp) } /* Receive a BSSGP PDU from a BSS on a PTP BVCI */ -int gprs_bssgp_pcu_rx_ptp(struct msgb *msg, struct tlv_parsed *tp, struct bssgp_bvc_ctx *bctx) +static int gprs_bssgp_pcu_rx_ptp(struct msgb *msg, struct tlv_parsed *tp, struct bssgp_bvc_ctx *bctx) { struct bssgp_normal_hdr *bgph = (struct bssgp_normal_hdr *) msgb_bssgph(msg); uint8_t pdu_type = bgph->pdu_type; @@ -355,7 +355,7 @@ int gprs_bssgp_pcu_rx_ptp(struct msgb *msg, struct tlv_parsed *tp, struct bssgp_ } /* Receive a BSSGP PDU from a SGSN on a SIGNALLING BVCI */ -int gprs_bssgp_pcu_rx_sign(struct msgb *msg, struct tlv_parsed *tp, struct bssgp_bvc_ctx *bctx) +static int gprs_bssgp_pcu_rx_sign(struct msgb *msg, struct tlv_parsed *tp, struct bssgp_bvc_ctx *bctx) { struct bssgp_normal_hdr *bgph = (struct bssgp_normal_hdr *) msgb_bssgph(msg); int rc = 0; @@ -414,7 +414,7 @@ int gprs_bssgp_pcu_rx_sign(struct msgb *msg, struct tlv_parsed *tp, struct bssgp return rc; } -int gprs_bssgp_pcu_rcvmsg(struct msgb *msg) +static int gprs_bssgp_pcu_rcvmsg(struct msgb *msg) { struct bssgp_normal_hdr *bgph = (struct bssgp_normal_hdr *) msgb_bssgph(msg); struct bssgp_ud_hdr *budh = (struct bssgp_ud_hdr *) msgb_bssgph(msg); diff --git a/src/gprs_bssgp_pcu.h b/src/gprs_bssgp_pcu.h index b611a19..9f0adc9 100644 --- a/src/gprs_bssgp_pcu.h +++ b/src/gprs_bssgp_pcu.h @@ -41,14 +41,6 @@ struct bssgp_bvc_ctx *btsctx_alloc(uint16_t bvci, uint16_t nsei); #define NS_HDR_LEN 4 #define IE_LLC_PDU 14 -int gprs_bssgp_pcu_rx_dl_ud(struct msgb *msg, struct tlv_parsed *tp); - -int gprs_bssgp_pcu_rx_ptp(struct msgb *msg, struct tlv_parsed *tp, struct bssgp_bvc_ctx *bctx); - -int gprs_bssgp_pcu_rx_sign(struct msgb *msg, struct tlv_parsed *tp, struct bssgp_bvc_ctx *bctx); - -int gprs_bssgp_pcu_rcvmsg(struct msgb *msg); - int gprs_bssgp_create_and_connect(uint16_t local_port, uint32_t sgsn_ip, uint16_t sgsn_port, uint16_t nsei, uint16_t nsvci, uint16_t bvci, uint16_t mcc, uint16_t mnc, uint16_t lac, uint16_t rac, -- 1.8.3.2 From hfreyther at sysmocom.de Thu Aug 22 07:16:57 2013 From: hfreyther at sysmocom.de (Holger Freyther) Date: Thu, 22 Aug 2013 09:16:57 +0200 Subject: [PATCH 03/10] rlcmac: Reduce the depedency on the global gprs_rlcmac_bts variable In-Reply-To: <1377155824-7598-1-git-send-email-hfreyther@sysmocom.de> References: <1377155824-7598-1-git-send-email-hfreyther@sysmocom.de> Message-ID: <1377155824-7598-3-git-send-email-hfreyther@sysmocom.de> From: Holger Hans Peter Freyther For mocking/unit-testing/emulation (and a dual trx-systems) having global state is quite bad. Cut back on the usage of the global struct gprs_rlcmac_bts. It also makes the complexity of certain routines more clear. --- src/gprs_bssgp_pcu.cpp | 20 +++++++++++--------- src/gprs_bssgp_pcu.h | 8 ++++---- src/gprs_rlcmac.cpp | 27 +++++++++++++-------------- src/gprs_rlcmac.h | 19 ++++++++++++------- src/gprs_rlcmac_data.cpp | 15 ++++++++------- src/pcu_l1_if.cpp | 2 +- 6 files changed, 49 insertions(+), 42 deletions(-) diff --git a/src/gprs_bssgp_pcu.cpp b/src/gprs_bssgp_pcu.cpp index a0ef206..acd30a4 100644 --- a/src/gprs_bssgp_pcu.cpp +++ b/src/gprs_bssgp_pcu.cpp @@ -25,6 +25,8 @@ struct osmo_pcu { struct gprs_nsvc *nsvc; struct bssgp_bvc_ctx *bctx; + struct gprs_rlcmac_bts *bts; + struct osmo_timer_list bvc_timer; int nsvc_unblocked; @@ -187,15 +189,14 @@ static int gprs_bssgp_pcu_rx_dl_ud(struct msgb *msg, struct tlv_parsed *tp) } else { /* the TBF exists, so we must write it in the queue * we prepend lifetime in front of PDU */ - struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts; struct timeval *tv; struct msgb *llc_msg = msgb_alloc(len + sizeof(*tv), "llc_pdu_queue"); if (!llc_msg) return -ENOMEM; tv = (struct timeval *)msgb_put(llc_msg, sizeof(*tv)); - if (bts->force_llc_lifetime) - delay_csec = bts->force_llc_lifetime; + if (the_pcu.bts->force_llc_lifetime) + delay_csec = the_pcu.bts->force_llc_lifetime; /* keep timestap at 0 for infinite delay */ if (delay_csec != 0xffff) { /* calculate timestamp of timeout */ @@ -247,14 +248,14 @@ static int gprs_bssgp_pcu_rx_dl_ud(struct msgb *msg, struct tlv_parsed *tp) } // Create new TBF (any TRX) - tfi = tfi_alloc(GPRS_RLCMAC_DL_TBF, &trx, use_trx); + tfi = tfi_alloc(the_pcu.bts, GPRS_RLCMAC_DL_TBF, &trx, use_trx); if (tfi < 0) { LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH resource\n"); /* FIXME: send reject */ return -EBUSY; } /* set number of downlink slots according to multislot class */ - tbf = tbf_alloc(tbf, GPRS_RLCMAC_DL_TBF, tfi, trx, ms_class, + tbf = tbf_alloc(the_pcu.bts, tbf, GPRS_RLCMAC_DL_TBF, tfi, trx, ms_class, ss); if (!tbf) { LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH ressource\n"); @@ -560,8 +561,6 @@ int gprs_bssgp_tx_fc_bvc(void) static void bvc_timeout(void *_priv) { - struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts; - if (!the_pcu.bvc_sig_reset) { LOGP(DBSSGP, LOGL_INFO, "Sending reset on BVCI 0\n"); bssgp_tx_bvc_reset(the_pcu.bctx, 0, BSSGP_CAUSE_OML_INTERV); @@ -588,11 +587,12 @@ static void bvc_timeout(void *_priv) LOGP(DBSSGP, LOGL_DEBUG, "Sending flow control info on BVCI %d\n", the_pcu.bctx->bvci); gprs_bssgp_tx_fc_bvc(); - osmo_timer_schedule(&the_pcu.bvc_timer, bts->fc_interval, 0); + osmo_timer_schedule(&the_pcu.bvc_timer, the_pcu.bts->fc_interval, 0); } /* create BSSGP/NS layer instances */ -int gprs_bssgp_create_and_connect(uint16_t local_port, uint32_t sgsn_ip, +int gprs_bssgp_create_and_connect(struct gprs_rlcmac_bts *bts, + uint16_t local_port, uint32_t sgsn_ip, uint16_t sgsn_port, uint16_t nsei, uint16_t nsvci, uint16_t bvci, uint16_t mcc, uint16_t mnc, uint16_t lac, uint16_t rac, uint16_t cell_id) @@ -607,6 +607,8 @@ int gprs_bssgp_create_and_connect(uint16_t local_port, uint32_t sgsn_ip, if (the_pcu.bctx) return 0; /* if already created, must return 0: no error */ + the_pcu.bts = bts; + bssgp_nsi = gprs_ns_instantiate(&sgsn_ns_cb, tall_pcu_ctx); if (!bssgp_nsi) { LOGP(DBSSGP, LOGL_ERROR, "Failed to create NS instance\n"); diff --git a/src/gprs_bssgp_pcu.h b/src/gprs_bssgp_pcu.h index 9f0adc9..15c8d9f 100644 --- a/src/gprs_bssgp_pcu.h +++ b/src/gprs_bssgp_pcu.h @@ -41,10 +41,10 @@ struct bssgp_bvc_ctx *btsctx_alloc(uint16_t bvci, uint16_t nsei); #define NS_HDR_LEN 4 #define IE_LLC_PDU 14 -int gprs_bssgp_create_and_connect(uint16_t local_port, uint32_t sgsn_ip, uint16_t - sgsn_port, uint16_t nsei, uint16_t nsvci, uint16_t bvci, - uint16_t mcc, uint16_t mnc, uint16_t lac, uint16_t rac, - uint16_t cell_id); +int gprs_bssgp_create_and_connect(struct gprs_rlcmac_bts *bts, uint16_t local_port, + uint32_t sgsn_ip, uint16_t sgsn_port, uint16_t nsei, + uint16_t nsvci, uint16_t bvci, uint16_t mcc, uint16_t mnc, + uint16_t lac, uint16_t rac, uint16_t cell_id); void gprs_bssgp_exit_on_destroy(void); void gprs_bssgp_destroy_or_exit(void); diff --git a/src/gprs_rlcmac.cpp b/src/gprs_rlcmac.cpp index f3a24f7..8874983 100644 --- a/src/gprs_rlcmac.cpp +++ b/src/gprs_rlcmac.cpp @@ -176,9 +176,9 @@ void debug_diagram(int diag, const char *format, ...) /* FIXME: spread ressources over multiple TRX. Also add option to use same * TRX in case of existing TBF for TLLI in the other direction. */ /* search for free TFI and return TFI, TRX */ -int tfi_alloc(enum gprs_rlcmac_tbf_direction dir, uint8_t *_trx, int8_t use_trx) +int tfi_alloc(struct gprs_rlcmac_bts *bts, enum gprs_rlcmac_tbf_direction dir, + uint8_t *_trx, int8_t use_trx) { - struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts; struct gprs_rlcmac_pdch *pdch; struct gprs_rlcmac_tbf **tbfp; uint8_t trx_from, trx_to, trx, ts, tfi; @@ -252,11 +252,10 @@ static inline int8_t find_free_usf(struct gprs_rlcmac_pdch *pdch, uint8_t ts) } /* lookup TBF Entity (by TFI) */ -struct gprs_rlcmac_tbf *tbf_by_tfi(uint8_t tfi, uint8_t trx, - enum gprs_rlcmac_tbf_direction dir) +struct gprs_rlcmac_tbf *tbf_by_tfi(struct gprs_rlcmac_bts *bts, + uint8_t tfi, uint8_t trx, enum gprs_rlcmac_tbf_direction dir) { struct gprs_rlcmac_tbf *tbf; - struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts; if (tfi >= 32 || trx >= 8) return NULL; @@ -318,11 +317,11 @@ struct gprs_rlcmac_tbf *tbf_by_poll_fn(uint32_t fn, uint8_t trx, uint8_t ts) return NULL; } -struct gprs_rlcmac_tbf *tbf_alloc(struct gprs_rlcmac_tbf *old_tbf, - enum gprs_rlcmac_tbf_direction dir, uint8_t tfi, uint8_t trx, +struct gprs_rlcmac_tbf *tbf_alloc(struct gprs_rlcmac_bts *bts, + struct gprs_rlcmac_tbf *old_tbf, enum gprs_rlcmac_tbf_direction dir, + uint8_t tfi, uint8_t trx, uint8_t ms_class, uint8_t single_slot) { - struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts; struct gprs_rlcmac_tbf *tbf; int rc; @@ -367,7 +366,7 @@ next_diagram: tbf->ws = 64; tbf->sns = 128; /* select algorithm */ - rc = bts->alloc_algorithm(old_tbf, tbf, bts->alloc_algorithm_curst, + rc = bts->alloc_algorithm(bts, old_tbf, tbf, bts->alloc_algorithm_curst, single_slot); /* if no ressource */ if (rc < 0) { @@ -406,10 +405,10 @@ next_diagram: * * Assign single slot for uplink and downlink */ -int alloc_algorithm_a(struct gprs_rlcmac_tbf *old_tbf, +int alloc_algorithm_a(struct gprs_rlcmac_bts *bts, + struct gprs_rlcmac_tbf *old_tbf, struct gprs_rlcmac_tbf *tbf, uint32_t cust, uint8_t single) { - struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts; struct gprs_rlcmac_pdch *pdch; uint8_t ts; int8_t usf; /* must be signed */ @@ -462,10 +461,10 @@ int alloc_algorithm_a(struct gprs_rlcmac_tbf *old_tbf, * Assign one uplink slot. (With free USF) * */ -int alloc_algorithm_b(struct gprs_rlcmac_tbf *old_tbf, +int alloc_algorithm_b(struct gprs_rlcmac_bts *bts, + struct gprs_rlcmac_tbf *old_tbf, struct gprs_rlcmac_tbf *tbf, uint32_t cust, uint8_t single) { - struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts; struct gprs_rlcmac_pdch *pdch; struct gprs_ms_multislot_class *ms_class; uint8_t Rx, Tx, Sum; /* Maximum Number of Slots: RX, Tx, Sum Rx+Tx */ @@ -964,7 +963,7 @@ int tbf_update(struct gprs_rlcmac_tbf *tbf) ul_tbf = tbf_by_tlli(tbf->tlli, GPRS_RLCMAC_UL_TBF); tbf_unlink_pdch(tbf); - rc = bts->alloc_algorithm(ul_tbf, tbf, bts->alloc_algorithm_curst, 0); + rc = bts->alloc_algorithm(bts, ul_tbf, tbf, bts->alloc_algorithm_curst, 0); /* if no ressource */ if (rc < 0) { LOGP(DRLCMAC, LOGL_ERROR, "No ressource after update???\n"); diff --git a/src/gprs_rlcmac.h b/src/gprs_rlcmac.h index c5af602..ac437f5 100644 --- a/src/gprs_rlcmac.h +++ b/src/gprs_rlcmac.h @@ -84,7 +84,8 @@ struct gprs_rlcmac_bts { uint8_t n3103; uint8_t n3105; struct gprs_rlcmac_trx trx[8]; - int (*alloc_algorithm)(struct gprs_rlcmac_tbf *old_tbf, + int (*alloc_algorithm)(struct gprs_rlcmac_bts *bts, + struct gprs_rlcmac_tbf *old_tbf, struct gprs_rlcmac_tbf *tbf, uint32_t cust, uint8_t single); uint32_t alloc_algorithm_curst; /* options to customize algorithm */ uint8_t force_two_phase; @@ -308,14 +309,16 @@ int sba_alloc(uint8_t *_trx, uint8_t *_ts, uint32_t *_fn, uint8_t ta); struct gprs_rlcmac_sba *sba_find(uint8_t trx, uint8_t ts, uint32_t fn); -int tfi_alloc(enum gprs_rlcmac_tbf_direction dir, uint8_t *_trx, - int8_t use_trx); +int tfi_alloc(struct gprs_rlcmac_bts *bts, enum gprs_rlcmac_tbf_direction dir, + uint8_t *_trx, int8_t use_trx); -struct gprs_rlcmac_tbf *tbf_alloc(struct gprs_rlcmac_tbf *old_tbf, +struct gprs_rlcmac_tbf *tbf_alloc(struct gprs_rlcmac_bts *bts, + struct gprs_rlcmac_tbf *old_tbf, enum gprs_rlcmac_tbf_direction dir, uint8_t tfi, uint8_t trx, uint8_t ms_class, uint8_t single_slot); -struct gprs_rlcmac_tbf *tbf_by_tfi(uint8_t tfi, uint8_t trx, +struct gprs_rlcmac_tbf *tbf_by_tfi(struct gprs_rlcmac_bts *bts, + uint8_t tfi, uint8_t trx, enum gprs_rlcmac_tbf_direction dir); struct gprs_rlcmac_tbf *tbf_by_tlli(uint32_t tlli, @@ -431,10 +434,12 @@ int flush_timing_advance(void); extern "C" { #endif -int alloc_algorithm_a(struct gprs_rlcmac_tbf *old_tbf, +int alloc_algorithm_a(struct gprs_rlcmac_bts *bts, + struct gprs_rlcmac_tbf *old_tbf, struct gprs_rlcmac_tbf *tbf, uint32_t cust, uint8_t single); -int alloc_algorithm_b(struct gprs_rlcmac_tbf *old_tbf, +int alloc_algorithm_b(struct gprs_rlcmac_bts *bts, + struct gprs_rlcmac_tbf *old_tbf, struct gprs_rlcmac_tbf *tbf, uint32_t cust, uint8_t single); #ifdef __cplusplus } diff --git a/src/gprs_rlcmac_data.cpp b/src/gprs_rlcmac_data.cpp index 99fac1b..4d5acb9 100644 --- a/src/gprs_rlcmac_data.cpp +++ b/src/gprs_rlcmac_data.cpp @@ -239,14 +239,14 @@ static struct gprs_rlcmac_tbf *alloc_ul_tbf(int8_t use_trx, uint8_t ms_class, uint8_t tfi; /* create new TBF, use sme TRX as DL TBF */ - tfi = tfi_alloc(GPRS_RLCMAC_UL_TBF, &trx, use_trx); + tfi = tfi_alloc(bts, GPRS_RLCMAC_UL_TBF, &trx, use_trx); if (tfi < 0) { LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH ressource\n"); /* FIXME: send reject */ return NULL; } /* use multislot class of downlink TBF */ - tbf = tbf_alloc(dl_tbf, GPRS_RLCMAC_UL_TBF, tfi, trx, ms_class, 0); + tbf = tbf_alloc(bts, dl_tbf, GPRS_RLCMAC_UL_TBF, tfi, trx, ms_class, 0); if (!tbf) { LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH ressource\n"); /* FIXME: send reject */ @@ -273,6 +273,7 @@ int gprs_rlcmac_rcv_control_block(bitvec *rlc_block, uint8_t trx, uint8_t ts, uint32_t tlli = 0; struct gprs_rlcmac_tbf *tbf; struct gprs_rlcmac_sba *sba; + struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts; int rc; RlcMacUplink_t * ul_control_block = (RlcMacUplink_t *)talloc_zero(tall_pcu_ctx, RlcMacUplink_t); @@ -478,14 +479,14 @@ int gprs_rlcmac_rcv_control_block(bitvec *rlc_block, uint8_t trx, uint8_t ts, } else { if (ul_control_block->u.Packet_Resource_Request.ID.u.Global_TFI.UnionType) { tfi = ul_control_block->u.Packet_Resource_Request.ID.u.Global_TFI.u.DOWNLINK_TFI; - tbf = tbf_by_tfi(tfi, trx, GPRS_RLCMAC_DL_TBF); + tbf = tbf_by_tfi(bts, tfi, trx, GPRS_RLCMAC_DL_TBF); if (!tbf) { LOGP(DRLCMAC, LOGL_NOTICE, "PACKET RESSOURCE REQ unknown downlink TBF=%d\n", tlli); break; } } else { tfi = ul_control_block->u.Packet_Resource_Request.ID.u.Global_TFI.u.UPLINK_TFI; - tbf = tbf_by_tfi(tfi, trx, GPRS_RLCMAC_UL_TBF); + tbf = tbf_by_tfi(bts, tfi, trx, GPRS_RLCMAC_UL_TBF); if (!tbf) { LOGP(DRLCMAC, LOGL_NOTICE, "PACKET RESSOURCE REQ unknown uplink TBF=%d\n", tlli); break; @@ -876,7 +877,7 @@ int gprs_rlcmac_rcv_data_block_acknowledged(uint8_t trx, uint8_t ts, } /* find TBF inst from given TFI */ - tbf = tbf_by_tfi(rh->tfi, trx, GPRS_RLCMAC_UL_TBF); + tbf = tbf_by_tfi(bts, rh->tfi, trx, GPRS_RLCMAC_UL_TBF); if (!tbf) { LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA unknown TBF=%d\n", rh->tfi); @@ -1173,14 +1174,14 @@ int gprs_rlcmac_rcv_rach(uint8_t ra, uint32_t Fn, int16_t qta) "(AGCH)\n"); } else { // Create new TBF - tfi = tfi_alloc(GPRS_RLCMAC_UL_TBF, &trx, -1); + tfi = tfi_alloc(bts, GPRS_RLCMAC_UL_TBF, &trx, -1); if (tfi < 0) { LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH ressource\n"); /* FIXME: send reject */ return -EBUSY; } /* set class to 0, since we don't know the multislot class yet */ - tbf = tbf_alloc(NULL, GPRS_RLCMAC_UL_TBF, tfi, trx, 0, 1); + tbf = tbf_alloc(bts, NULL, GPRS_RLCMAC_UL_TBF, tfi, trx, 0, 1); if (!tbf) { LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH ressource\n"); /* FIXME: send reject */ diff --git a/src/pcu_l1_if.cpp b/src/pcu_l1_if.cpp index b7b0269..e53b683 100644 --- a/src/pcu_l1_if.cpp +++ b/src/pcu_l1_if.cpp @@ -418,7 +418,7 @@ bssgp_failed: ia.s_addr = htonl(info_ind->remote_ip[0]); LOGP(DL1IF, LOGL_DEBUG, " remote_ip=%s\n", inet_ntoa(ia)); - rc = gprs_bssgp_create_and_connect(info_ind->local_port[0], + rc = gprs_bssgp_create_and_connect(bts, info_ind->local_port[0], info_ind->remote_ip[0], info_ind->remote_port[0], info_ind->nsei, info_ind->nsvci[0], info_ind->bvci, info_ind->mcc, info_ind->mnc, info_ind->lac, info_ind->rac, -- 1.8.3.2 From hfreyther at sysmocom.de Thu Aug 22 07:16:55 2013 From: hfreyther at sysmocom.de (Holger Freyther) Date: Thu, 22 Aug 2013 09:16:55 +0200 Subject: [PATCH 01/10] bssgp: Re-indent the switch/case statement Message-ID: <1377155824-7598-1-git-send-email-hfreyther@sysmocom.de> From: Holger Hans Peter Freyther --- src/gprs_bssgp_pcu.cpp | 90 +++++++++++++++++++++++++------------------------- 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/src/gprs_bssgp_pcu.cpp b/src/gprs_bssgp_pcu.cpp index ae47fb2..4326303 100644 --- a/src/gprs_bssgp_pcu.cpp +++ b/src/gprs_bssgp_pcu.cpp @@ -365,51 +365,51 @@ int gprs_bssgp_pcu_rx_sign(struct msgb *msg, struct tlv_parsed *tp, struct bssgp DEBUGP(DBSSGP, "BSSGP BVCI=%u Rx BVC STATUS\n", bctx->bvci); /* FIXME: send NM_STATUS.ind to NM */ break; - case BSSGP_PDUT_SUSPEND_ACK: - LOGP(DBSSGP, LOGL_DEBUG, "rx BSSGP_PDUT_SUSPEND_ACK\n"); - break; - case BSSGP_PDUT_SUSPEND_NACK: - LOGP(DBSSGP, LOGL_DEBUG, "rx BSSGP_PDUT_SUSPEND_NACK\n"); - break; - case BSSGP_PDUT_BVC_RESET_ACK: - LOGP(DBSSGP, LOGL_DEBUG, "rx BSSGP_PDUT_BVC_RESET_ACK\n"); - if (!the_pcu.bvc_sig_reset) - the_pcu.bvc_sig_reset = 1; - else - the_pcu.bvc_reset = 1; - bvc_timeout(NULL); - break; - case BSSGP_PDUT_PAGING_PS: - LOGP(DBSSGP, LOGL_NOTICE, "RX: [SGSN->PCU] BSSGP_PDUT_PAGING_PS\n"); - gprs_bssgp_pcu_rx_paging_ps(msg, tp); - break; - case BSSGP_PDUT_PAGING_CS: - LOGP(DBSSGP, LOGL_DEBUG, "rx BSSGP_PDUT_PAGING_CS\n"); - break; - case BSSGP_PDUT_RESUME_ACK: - LOGP(DBSSGP, LOGL_DEBUG, "rx BSSGP_PDUT_RESUME_ACK\n"); - break; - case BSSGP_PDUT_RESUME_NACK: - LOGP(DBSSGP, LOGL_DEBUG, "rx BSSGP_PDUT_RESUME_NACK\n"); - break; - case BSSGP_PDUT_FLUSH_LL: - LOGP(DBSSGP, LOGL_DEBUG, "rx BSSGP_PDUT_FLUSH_LL\n"); - break; - case BSSGP_PDUT_BVC_BLOCK_ACK: - LOGP(DBSSGP, LOGL_DEBUG, "rx BSSGP_PDUT_SUSPEND_ACK\n"); - break; - case BSSGP_PDUT_BVC_UNBLOCK_ACK: - LOGP(DBSSGP, LOGL_DEBUG, "rx BSSGP_PDUT_BVC_UNBLOCK_ACK\n"); - the_pcu.bvc_unblocked = 1; - bvc_timeout(NULL); - break; - case BSSGP_PDUT_SGSN_INVOKE_TRACE: - LOGP(DBSSGP, LOGL_DEBUG, "rx BSSGP_PDUT_SGSN_INVOKE_TRACE\n"); - break; - default: - LOGP(DBSSGP, LOGL_NOTICE, "BSSGP BVCI=%u Rx PDU type 0x%02x unknown\n", bctx->bvci, bgph->pdu_type); - rc = bssgp_tx_status(BSSGP_CAUSE_PROTO_ERR_UNSPEC, NULL, msg); - break; + case BSSGP_PDUT_SUSPEND_ACK: + LOGP(DBSSGP, LOGL_DEBUG, "rx BSSGP_PDUT_SUSPEND_ACK\n"); + break; + case BSSGP_PDUT_SUSPEND_NACK: + LOGP(DBSSGP, LOGL_DEBUG, "rx BSSGP_PDUT_SUSPEND_NACK\n"); + break; + case BSSGP_PDUT_BVC_RESET_ACK: + LOGP(DBSSGP, LOGL_DEBUG, "rx BSSGP_PDUT_BVC_RESET_ACK\n"); + if (!the_pcu.bvc_sig_reset) + the_pcu.bvc_sig_reset = 1; + else + the_pcu.bvc_reset = 1; + bvc_timeout(NULL); + break; + case BSSGP_PDUT_PAGING_PS: + LOGP(DBSSGP, LOGL_NOTICE, "RX: [SGSN->PCU] BSSGP_PDUT_PAGING_PS\n"); + gprs_bssgp_pcu_rx_paging_ps(msg, tp); + break; + case BSSGP_PDUT_PAGING_CS: + LOGP(DBSSGP, LOGL_DEBUG, "rx BSSGP_PDUT_PAGING_CS\n"); + break; + case BSSGP_PDUT_RESUME_ACK: + LOGP(DBSSGP, LOGL_DEBUG, "rx BSSGP_PDUT_RESUME_ACK\n"); + break; + case BSSGP_PDUT_RESUME_NACK: + LOGP(DBSSGP, LOGL_DEBUG, "rx BSSGP_PDUT_RESUME_NACK\n"); + break; + case BSSGP_PDUT_FLUSH_LL: + LOGP(DBSSGP, LOGL_DEBUG, "rx BSSGP_PDUT_FLUSH_LL\n"); + break; + case BSSGP_PDUT_BVC_BLOCK_ACK: + LOGP(DBSSGP, LOGL_DEBUG, "rx BSSGP_PDUT_SUSPEND_ACK\n"); + break; + case BSSGP_PDUT_BVC_UNBLOCK_ACK: + LOGP(DBSSGP, LOGL_DEBUG, "rx BSSGP_PDUT_BVC_UNBLOCK_ACK\n"); + the_pcu.bvc_unblocked = 1; + bvc_timeout(NULL); + break; + case BSSGP_PDUT_SGSN_INVOKE_TRACE: + LOGP(DBSSGP, LOGL_DEBUG, "rx BSSGP_PDUT_SGSN_INVOKE_TRACE\n"); + break; + default: + LOGP(DBSSGP, LOGL_NOTICE, "BSSGP BVCI=%u Rx PDU type 0x%02x unknown\n", bctx->bvci, bgph->pdu_type); + rc = bssgp_tx_status(BSSGP_CAUSE_PROTO_ERR_UNSPEC, NULL, msg); + break; } return rc; } -- 1.8.3.2 From hfreyther at sysmocom.de Thu Aug 22 07:17:01 2013 From: hfreyther at sysmocom.de (Holger Freyther) Date: Thu, 22 Aug 2013 09:17:01 +0200 Subject: [PATCH 07/10] emu: Create an app that allows to communicate with a SGSN In-Reply-To: <1377155824-7598-1-git-send-email-hfreyther@sysmocom.de> References: <1377155824-7598-1-git-send-email-hfreyther@sysmocom.de> Message-ID: <1377155824-7598-7-git-send-email-hfreyther@sysmocom.de> From: Holger Hans Peter Freyther This code can open a BSSGP connection toward a SGSN and will inititate the unblocking. It does not send any user data. --- .gitignore | 3 +- tests/Makefile.am | 10 +++++ tests/emu/pcu_emu.cpp | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 tests/emu/pcu_emu.cpp diff --git a/.gitignore b/.gitignore index fec1b98..07fde56 100644 --- a/.gitignore +++ b/.gitignore @@ -29,9 +29,10 @@ src/osmo-pcu src/osmo-pcu-remote # tests +.dirstamp tests/atconfig tests/package.m4 -tests/rlcmac/.dirstamp tests/rlcmac/RLCMACTest +tests/emu/pcu_emu tests/testsuite tests/testsuite.log diff --git a/tests/Makefile.am b/tests/Makefile.am index 1faa5f4..a037618 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,6 +1,7 @@ AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) $(LIBOSMOCORE_CFLAGS) $(LIBOSMOGB_CFLAGS) $(LIBOSMOGSM_CFLAGS) -I$(top_srcdir)/src/ check_PROGRAMS = rlcmac/RLCMACTest +noinst_PROGRAMS = emu/pcu_emu rlcmac_RLCMACTest_SOURCES = rlcmac/RLCMACTest.cpp rlcmac_RLCMACTest_LDADD = \ @@ -8,6 +9,15 @@ rlcmac_RLCMACTest_LDADD = \ $(LIBOSMOCORE_LIBS) \ $(COMMON_LA) +emu_pcu_emu_SOURCES = emu/pcu_emu.cpp +emu_pcu_emu_LDADD = \ + $(top_builddir)/src/libgprs.la \ + $(LIBOSMOGB_LIBS) \ + $(LIBOSMOGSM_LIBS) \ + $(LIBOSMOCORE_LIBS) \ + $(COMMON_LA) + + # The `:;' works around a Bash 3.2 bug when the output is not writeable. $(srcdir)/package.m4: $(top_srcdir)/configure.ac :;{ \ diff --git a/tests/emu/pcu_emu.cpp b/tests/emu/pcu_emu.cpp new file mode 100644 index 0000000..f78285d --- /dev/null +++ b/tests/emu/pcu_emu.cpp @@ -0,0 +1,113 @@ +/* Code for a software PCU to test a SGSN.. */ + +/* (C) 2013 by Holger Hans Peter Freyther + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +extern "C" { +#include +#include +} + +#include +#include + +#include +#include +#include + +/* Extern data to please the underlying code */ +void *tall_pcu_ctx; +struct gprs_rlcmac_bts *gprs_rlcmac_bts; +int16_t spoof_mnc = 0, spoof_mcc = 0; + +struct gprs_rlcmac_bts *create_bts() +{ + struct gprs_rlcmac_bts *bts; + + bts = talloc_zero(tall_pcu_ctx, struct gprs_rlcmac_bts); + if (!bts) + return NULL; + bts->fc_interval = 100; + bts->initial_cs_dl = bts->initial_cs_ul = 1; + bts->cs1 = 1; + bts->t3142 = 20; + bts->t3169 = 5; + bts->t3191 = 5; + bts->t3193_msec = 100; + bts->t3195 = 5; + bts->n3101 = 10; + bts->n3103 = 4; + bts->n3105 = 8; + bts->alpha = 0; /* a = 0.0 */ + + if (!bts->alloc_algorithm) + bts->alloc_algorithm = alloc_algorithm_b; + + return bts; +} + +static void bvci_unblocked(struct gprs_bssgp_pcu *pci) +{ + printf("BVCI unblocked. We can begin with test cases.\n"); +} + +void create_and_connect_bssgp(struct gprs_rlcmac_bts *bts, + uint32_t sgsn_ip, uint16_t sgsn_port) +{ + struct gprs_bssgp_pcu *pcu; + + pcu = gprs_bssgp_create_and_connect(bts, 0, sgsn_ip, sgsn_port, + 20, 20, 20, 0x901, 0x99, 1, 0, 0); + pcu->on_unblock_ack = bvci_unblocked; +} + +int main(int argc, char **argv) +{ + struct gprs_rlcmac_bts *bts; + + tall_pcu_ctx = talloc_named_const(NULL, 1, "moiji-mobile Emu-PCU context"); + if (!tall_pcu_ctx) + abort(); + + msgb_set_talloc_ctx(tall_pcu_ctx); + osmo_init_logging(&gprs_log_info); + vty_init(&pcu_vty_info); + pcu_vty_init(&gprs_log_info); + + gprs_rlcmac_bts = create_bts(); + if (!gprs_rlcmac_bts) + abort(); + + create_and_connect_bssgp(gprs_rlcmac_bts, INADDR_LOOPBACK, 23000); + + for (;;) + osmo_select_main(0); + + return EXIT_SUCCESS; +} + +/* + * stubs that should not be reached + */ +extern "C" { +void l1if_pdch_req() { abort(); } +void l1if_connect_pdch() { abort(); } +void l1if_close_pdch() { abort(); } +void l1if_open_pdch() { abort(); } +} -- 1.8.3.2 From hfreyther at sysmocom.de Thu Aug 22 07:17:03 2013 From: hfreyther at sysmocom.de (Holger Freyther) Date: Thu, 22 Aug 2013 09:17:03 +0200 Subject: [PATCH 09/10] emu: Use OpenBSC code to decode the LLC and add assertions In-Reply-To: <1377155824-7598-1-git-send-email-hfreyther@sysmocom.de> References: <1377155824-7598-1-git-send-email-hfreyther@sysmocom.de> Message-ID: <1377155824-7598-9-git-send-email-hfreyther@sysmocom.de> From: Holger Hans Peter Freyther Use the OpenBSC SGSN code to parse the LLC data and look into the data we receive. Add assertions to verify the the sequence number is increasing. --- tests/Makefile.am | 3 +- tests/emu/openbsc_clone.c | 216 ++++++++++++++++++++++++++++++++++ tests/emu/openbsc_clone.h | 64 ++++++++++ tests/emu/pcu_emu.cpp | 7 ++ tests/emu/test_replay_gprs_attach.cpp | 39 ++++++ 5 files changed, 328 insertions(+), 1 deletion(-) create mode 100644 tests/emu/openbsc_clone.c create mode 100644 tests/emu/openbsc_clone.h diff --git a/tests/Makefile.am b/tests/Makefile.am index 7216d3b..0131e47 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -9,7 +9,8 @@ rlcmac_RLCMACTest_LDADD = \ $(LIBOSMOCORE_LIBS) \ $(COMMON_LA) -emu_pcu_emu_SOURCES = emu/pcu_emu.cpp emu/test_replay_gprs_attach.cpp +emu_pcu_emu_SOURCES = emu/pcu_emu.cpp emu/test_replay_gprs_attach.cpp \ + emu/openbsc_clone.c emu/openbsc_clone.h emu_pcu_emu_LDADD = \ $(top_builddir)/src/libgprs.la \ $(LIBOSMOGB_LIBS) \ diff --git a/tests/emu/openbsc_clone.c b/tests/emu/openbsc_clone.c new file mode 100644 index 0000000..707819b --- /dev/null +++ b/tests/emu/openbsc_clone.c @@ -0,0 +1,216 @@ +/* (C) 2009-2010 by Harald Welte + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ +#include "openbsc_clone.h" + +#include + +#include + +#include + +/* Section 6.4 Commands and Responses */ +enum gprs_llc_u_cmd { + GPRS_LLC_U_DM_RESP = 0x01, + GPRS_LLC_U_DISC_CMD = 0x04, + GPRS_LLC_U_UA_RESP = 0x06, + GPRS_LLC_U_SABM_CMD = 0x07, + GPRS_LLC_U_FRMR_RESP = 0x08, + GPRS_LLC_U_XID = 0x0b, + GPRS_LLC_U_NULL_CMD = 0x00, +}; + +#define LLC_ALLOC_SIZE 16384 +#define UI_HDR_LEN 3 +#define N202 4 +#define CRC24_LENGTH 3 + +static const struct value_string llc_cmd_strs[] = { + { GPRS_LLC_NULL, "NULL" }, + { GPRS_LLC_RR, "RR" }, + { GPRS_LLC_ACK, "ACK" }, + { GPRS_LLC_RNR, "RNR" }, + { GPRS_LLC_SACK, "SACK" }, + { GPRS_LLC_DM, "DM" }, + { GPRS_LLC_DISC, "DISC" }, + { GPRS_LLC_UA, "UA" }, + { GPRS_LLC_SABM, "SABM" }, + { GPRS_LLC_FRMR, "FRMR" }, + { GPRS_LLC_XID, "XID" }, + { GPRS_LLC_UI, "UI" }, + { 0, NULL } +}; + +int gprs_llc_hdr_parse(struct gprs_llc_hdr_parsed *ghp, + const uint8_t *llc_hdr, int len) +{ + const uint8_t *ctrl = llc_hdr+1; + + if (len <= CRC24_LENGTH) + return -EIO; + + ghp->crc_length = len - CRC24_LENGTH; + + ghp->ack_req = 0; + + /* Section 5.5: FCS */ + ghp->fcs = *(llc_hdr + len - 3); + ghp->fcs |= *(llc_hdr + len - 2) << 8; + ghp->fcs |= *(llc_hdr + len - 1) << 16; + + /* Section 6.2.1: invalid PD field */ + if (llc_hdr[0] & 0x80) + return -EIO; + + /* This only works for the MS->SGSN direction */ + if (llc_hdr[0] & 0x40) + ghp->is_cmd = 0; + else + ghp->is_cmd = 1; + + ghp->sapi = llc_hdr[0] & 0xf; + + /* Section 6.2.3: check for reserved SAPI */ + switch (ghp->sapi) { + case 0: + case 4: + case 6: + case 0xa: + case 0xc: + case 0xd: + case 0xf: + return -EINVAL; + } + + if ((ctrl[0] & 0x80) == 0) { + /* I (Information transfer + Supervisory) format */ + uint8_t k; + + ghp->data = ctrl + 3; + + if (ctrl[0] & 0x40) + ghp->ack_req = 1; + + ghp->seq_tx = (ctrl[0] & 0x1f) << 4; + ghp->seq_tx |= (ctrl[1] >> 4); + + ghp->seq_rx = (ctrl[1] & 0x7) << 6; + ghp->seq_rx |= (ctrl[2] >> 2); + + switch (ctrl[2] & 0x03) { + case 0: + ghp->cmd = GPRS_LLC_RR; + break; + case 1: + ghp->cmd = GPRS_LLC_ACK; + break; + case 2: + ghp->cmd = GPRS_LLC_RNR; + break; + case 3: + ghp->cmd = GPRS_LLC_SACK; + k = ctrl[3] & 0x1f; + ghp->data += 1 + k; + break; + } + ghp->data_len = (llc_hdr + len - 3) - ghp->data; + } else if ((ctrl[0] & 0xc0) == 0x80) { + /* S (Supervisory) format */ + ghp->data = NULL; + ghp->data_len = 0; + + if (ctrl[0] & 0x20) + ghp->ack_req = 1; + ghp->seq_rx = (ctrl[0] & 0x7) << 6; + ghp->seq_rx |= (ctrl[1] >> 2); + + switch (ctrl[1] & 0x03) { + case 0: + ghp->cmd = GPRS_LLC_RR; + break; + case 1: + ghp->cmd = GPRS_LLC_ACK; + break; + case 2: + ghp->cmd = GPRS_LLC_RNR; + break; + case 3: + ghp->cmd = GPRS_LLC_SACK; + break; + } + } else if ((ctrl[0] & 0xe0) == 0xc0) { + /* UI (Unconfirmed Inforamtion) format */ + ghp->cmd = GPRS_LLC_UI; + ghp->data = ctrl + 2; + ghp->data_len = (llc_hdr + len - 3) - ghp->data; + + ghp->seq_tx = (ctrl[0] & 0x7) << 6; + ghp->seq_tx |= (ctrl[1] >> 2); + if (ctrl[1] & 0x02) { + ghp->is_encrypted = 1; + /* FIXME: encryption */ + } + if (ctrl[1] & 0x01) { + /* FCS over hdr + all inf fields */ + } else { + /* FCS over hdr + N202 octets (4) */ + if (ghp->crc_length > UI_HDR_LEN + N202) + ghp->crc_length = UI_HDR_LEN + N202; + } + } else { + /* U (Unnumbered) format: 1 1 1 P/F M4 M3 M2 M1 */ + ghp->data = NULL; + ghp->data_len = 0; + + switch (ctrl[0] & 0xf) { + case GPRS_LLC_U_NULL_CMD: + ghp->cmd = GPRS_LLC_NULL; + break; + case GPRS_LLC_U_DM_RESP: + ghp->cmd = GPRS_LLC_DM; + break; + case GPRS_LLC_U_DISC_CMD: + ghp->cmd = GPRS_LLC_DISC; + break; + case GPRS_LLC_U_UA_RESP: + ghp->cmd = GPRS_LLC_UA; + break; + case GPRS_LLC_U_SABM_CMD: + ghp->cmd = GPRS_LLC_SABM; + break; + case GPRS_LLC_U_FRMR_RESP: + ghp->cmd = GPRS_LLC_FRMR; + break; + case GPRS_LLC_U_XID: + ghp->cmd = GPRS_LLC_XID; + ghp->data = ctrl + 1; + ghp->data_len = (llc_hdr + len - 3) - ghp->data; + break; + default: + return -EIO; + } + } + + /* FIXME: parse sack frame */ + if (ghp->cmd == GPRS_LLC_SACK) { + LOGP(DPCU, LOGL_NOTICE, "Unsupported SACK frame\n"); + return -EIO; + } + + return 0; +} diff --git a/tests/emu/openbsc_clone.h b/tests/emu/openbsc_clone.h new file mode 100644 index 0000000..d62ff22 --- /dev/null +++ b/tests/emu/openbsc_clone.h @@ -0,0 +1,64 @@ +/* (C) 2009-2010 by Harald Welte + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ +#ifndef OPENBSC_CLONE_H +#define OPENBSC_CLONE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +enum gprs_llc_cmd { + GPRS_LLC_NULL, + GPRS_LLC_RR, + GPRS_LLC_ACK, + GPRS_LLC_RNR, + GPRS_LLC_SACK, + GPRS_LLC_DM, + GPRS_LLC_DISC, + GPRS_LLC_UA, + GPRS_LLC_SABM, + GPRS_LLC_FRMR, + GPRS_LLC_XID, + GPRS_LLC_UI, +}; + +struct gprs_llc_hdr_parsed { + uint8_t sapi; + uint8_t is_cmd:1, + ack_req:1, + is_encrypted:1; + uint32_t seq_rx; + uint32_t seq_tx; + uint32_t fcs; + uint32_t fcs_calc; + const uint8_t *data; + uint16_t data_len; + uint16_t crc_length; + enum gprs_llc_cmd cmd; +}; + +int gprs_llc_hdr_parse(struct gprs_llc_hdr_parsed *ghp, const uint8_t *llc_hdr, int len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/tests/emu/pcu_emu.cpp b/tests/emu/pcu_emu.cpp index 337c0c8..f4d38cd 100644 --- a/tests/emu/pcu_emu.cpp +++ b/tests/emu/pcu_emu.cpp @@ -37,6 +37,7 @@ struct gprs_rlcmac_bts *gprs_rlcmac_bts; int16_t spoof_mnc = 0, spoof_mcc = 0; extern void test_replay_gprs_attach(struct gprs_bssgp_pcu *pcu); +extern void test_replay_gprs_data(struct gprs_bssgp_pcu *, struct msgb *, struct tlv_parsed *); struct gprs_rlcmac_bts *create_bts() { @@ -70,6 +71,11 @@ static void bvci_unblocked(struct gprs_bssgp_pcu *pcu) test_replay_gprs_attach(pcu); } +static void bssgp_data(struct gprs_bssgp_pcu *pcu, struct msgb *msg, struct tlv_parsed *tp) +{ + test_replay_gprs_data(pcu, msg, tp); +} + void create_and_connect_bssgp(struct gprs_rlcmac_bts *bts, uint32_t sgsn_ip, uint16_t sgsn_port) { @@ -78,6 +84,7 @@ void create_and_connect_bssgp(struct gprs_rlcmac_bts *bts, pcu = gprs_bssgp_create_and_connect(bts, 0, sgsn_ip, sgsn_port, 20, 20, 20, 0x901, 0x99, 1, 0, 0); pcu->on_unblock_ack = bvci_unblocked; + pcu->on_dl_unit_data = bssgp_data; } int main(int argc, char **argv) diff --git a/tests/emu/test_replay_gprs_attach.cpp b/tests/emu/test_replay_gprs_attach.cpp index 500b16e..fb1e77f 100644 --- a/tests/emu/test_replay_gprs_attach.cpp +++ b/tests/emu/test_replay_gprs_attach.cpp @@ -19,13 +19,18 @@ extern "C" { #include +#include +#include } +#include "openbsc_clone.h" + #include #include #include +/* GPRS attach with a foreign TLLI */ static const uint8_t gprs_attach_llc[] = { /* LLC-PDU IE */ 0x0e, 0x00, 0x2e, @@ -38,6 +43,8 @@ static const uint8_t gprs_attach_llc[] = { 0x42, 0x00, 0x40, 0xaa, 0xf3, 0x18 }; +static int next_wanted_nu; + struct msgb *create_msg(const uint8_t *data, size_t len) { struct msgb *msg = msgb_alloc_headroom(4096, 128, "create msg"); @@ -51,6 +58,38 @@ void test_replay_gprs_attach(struct gprs_bssgp_pcu *pcu) uint32_t tlli = 0xadf11820; const uint8_t qos_profile[] = { 0x0, 0x0, 0x04 }; + next_wanted_nu = 0; struct msgb *msg = create_msg(gprs_attach_llc, ARRAY_SIZE(gprs_attach_llc)); bssgp_tx_ul_ud(pcu->bctx, tlli, qos_profile, msg); } + +void test_replay_gprs_data(struct gprs_bssgp_pcu *pcu, struct msgb *msg, struct tlv_parsed *tp) +{ + struct bssgp_ud_hdr *budh; + struct gprs_llc_hdr_parsed ph; + uint32_t tlli; + + if (!TLVP_PRESENT(tp, BSSGP_IE_LLC_PDU)) + return; + + + gprs_llc_hdr_parse(&ph, TLVP_VAL(tp, BSSGP_IE_LLC_PDU), + TLVP_LEN(tp, BSSGP_IE_LLC_PDU)); + + budh = (struct bssgp_ud_hdr *)msgb_bssgph(msg); + tlli = ntohl(budh->tlli); + + /* all messages we should get, should be for a foreign tlli */ + OSMO_ASSERT(gprs_tlli_type(tlli) == TLLI_FOREIGN); + printf("TLLI(0x%08x) is foreign!\n", tlli); + + OSMO_ASSERT(ph.cmd == GPRS_LLC_UI); + OSMO_ASSERT(ph.sapi == 1); + OSMO_ASSERT(ph.seq_tx == next_wanted_nu++); + + /* this test just wants to see messages... no further data is sent */ + if (next_wanted_nu == 4) { + printf("Test done.\n"); + exit(EXIT_SUCCESS); + } +} -- 1.8.3.2 From andreas at eversberg.eu Fri Aug 23 09:35:55 2013 From: andreas at eversberg.eu (Andreas Eversberg) Date: Fri, 23 Aug 2013 11:35:55 +0200 Subject: [PATCH 10/10] emu: Add a crash re-producer for the SGSN (and the concept of tests) In-Reply-To: <1377155824-7598-10-git-send-email-hfreyther@sysmocom.de> References: <1377155824-7598-1-git-send-email-hfreyther@sysmocom.de> <1377155824-7598-10-git-send-email-hfreyther@sysmocom.de> Message-ID: <52172CFB.6070509@eversberg.eu> Holger Freyther wrote: > + .name = "gprs_attach_with_tmsi", > hi holger, i tested your patches with my test environment. surfing via gprs works fine, except for some compiling error at pcu_emu.cpp: emu/pcu_emu.cpp:53:3: error: expected primary-expression before '.' token by now, i have no idea how to solve this. regards, andreas From hfreyther at sysmocom.de Fri Aug 23 10:12:04 2013 From: hfreyther at sysmocom.de (Holger Hans Peter Freyther) Date: Fri, 23 Aug 2013 12:12:04 +0200 Subject: [PATCH 10/10] emu: Add a crash re-producer for the SGSN (and the concept of tests) In-Reply-To: <52172CFB.6070509@eversberg.eu> References: <1377155824-7598-1-git-send-email-hfreyther@sysmocom.de> <1377155824-7598-10-git-send-email-hfreyther@sysmocom.de> <52172CFB.6070509@eversberg.eu> Message-ID: <20130823101204.GB27820@xiaoyu.lan> On Fri, Aug 23, 2013 at 11:35:55AM +0200, Andreas Eversberg wrote: Dear Andreas, > emu/pcu_emu.cpp:53:3: error: expected primary-expression before '.' token which version of g++ are you using? which C++ standard is it using by default? holger -- - Holger Freyther http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Schivelbeiner Str. 5 * 10439 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Geschaeftsfuehrer / Managing Directors: Holger Freyther, Harald Welte From andreas at eversberg.eu Fri Aug 23 11:02:11 2013 From: andreas at eversberg.eu (Andreas Eversberg) Date: Fri, 23 Aug 2013 13:02:11 +0200 Subject: [PATCH 10/10] emu: Add a crash re-producer for the SGSN (and the concept of tests) In-Reply-To: <20130823101204.GB27820@xiaoyu.lan> References: <1377155824-7598-1-git-send-email-hfreyther@sysmocom.de> <1377155824-7598-10-git-send-email-hfreyther@sysmocom.de> <52172CFB.6070509@eversberg.eu> <20130823101204.GB27820@xiaoyu.lan> Message-ID: <52174133.6040908@eversberg.eu> Holger Hans Peter Freyther wrote: > which version of g++ are you using? which C++ standard is it using > by default? > openbsc ~ # g++ -v Using built-in specs. COLLECT_GCC=/usr/i686-pc-linux-gnu/gcc-bin/4.5.4/g++ COLLECT_LTO_WRAPPER=/usr/libexec/gcc/i686-pc-linux-gnu/4.5.4/lto-wrapper Target: i686-pc-linux-gnu Configured with: /var/tmp/portage/sys-devel/gcc-4.5.4/work/gcc-4.5.4/configure --prefix=/usr --bindir=/usr/i686-pc-linux-gnu/gcc-bin/4.5.4 --includedir=/usr/lib/gcc/i686-pc-linux-gnu/4.5.4/include --datadir=/usr/share/gcc-data/i686-pc-linux-gnu/4.5.4 --mandir=/usr/share/gcc-data/i686-pc-linux-gnu/4.5.4/man --infodir=/usr/share/gcc-data/i686-pc-linux-gnu/4.5.4/info --with-gxx-include-dir=/usr/lib/gcc/i686-pc-linux-gnu/4.5.4/include/g++-v4 --host=i686-pc-linux-gnu --build=i686-pc-linux-gnu --disable-altivec --disable-fixed-point --without-ppl --without-cloog --disable-lto --enable-nls --without-included-gettext --with-system-zlib --enable-obsolete --disable-werror --enable-secureplt --disable-multilib --enable-libmudflap --disable-libssp --enable-libgomp --with-python-dir=/share/gcc-data/i686-pc-linux-gnu/4.5.4/python --enable-checking=release --disable-libgcj --with-arch=i686 --enable-languages=c,c++,fortran --enable-shared --enable-threads=posix --enable-__cxa_atexit --enable-clocale=gnu --enable-targets=all --with-bugurl=http://bugs.gentoo.org/ --with-pkgversion='Gentoo 4.5.4 p1.0, pie-0.4.7' Thread model: posix gcc version 4.5.4 (Gentoo 4.5.4 p1.0, pie-0.4.7) how do i query the default C++ standard? From hfreyther at sysmocom.de Sat Aug 24 07:24:40 2013 From: hfreyther at sysmocom.de (Holger Hans Peter Freyther) Date: Sat, 24 Aug 2013 09:24:40 +0200 Subject: [PATCH] emu: Add a crash re-producer for the SGSN (and the concept of tests) In-Reply-To: <1377155824-7598-10-git-send-email-hfreyther@sysmocom.de> References: <1377155824-7598-10-git-send-email-hfreyther@sysmocom.de> Message-ID: <1377329080-24332-1-git-send-email-hfreyther@sysmocom.de> From: Holger Hans Peter Freyther Introduce the concept of tests that will be ran one after the other. This new test will send static message that will lead to the opening of a PDP context. At this point one should use ping with a large packet size and suspend/stop the emulator. Once the NS connection is considered dead the SGSN will crash with a double free. Reproduce: 0.) Add IMSI 901700000003094 to the ACL 1.) Stop/Suspend the emulation process so the NS Alive times out 2.) Use ping IP -s 2048 This will create a double free... #4 0xb7bb2646 in talloc_abort_double_free () at talloc.c:175 #5 0xb7bbd41a in talloc_chunk_from_ptr (ptr=0x8091208) at talloc.c:190 #6 _talloc_free (ptr=0x8091208) at talloc.c:517 #7 talloc_free (ptr=ptr at entry=0x8091208) at talloc.c:990 #8 0xb7bb319b in msgb_free (m=m at entry=0x8091208) at msgb.c:72 #9 0x0804db54 in sndcp_send_ud_frag (fs=0xbfffcc6c) at gprs_sndcp.c:423 #10 sndcp_unitdata_req (msg=msg at entry=0x808eed8, lle=0x808fbc8, nsapi=5 '\005', mmcontext=mmcontext at entry=0x80903e8) at gprs_sndcp.c:471 --- tests/Makefile.am | 3 +- tests/emu/gprs_tests.h | 65 +++++++++++++ tests/emu/openbsc_clone.c | 18 ++++ tests/emu/openbsc_clone.h | 32 +++++++ tests/emu/pcu_emu.cpp | 42 ++++++++- tests/emu/test_pdp_activation.cpp | 171 ++++++++++++++++++++++++++++++++++ tests/emu/test_replay_gprs_attach.cpp | 15 +-- 7 files changed, 332 insertions(+), 14 deletions(-) create mode 100644 tests/emu/gprs_tests.h create mode 100644 tests/emu/test_pdp_activation.cpp diff --git a/tests/Makefile.am b/tests/Makefile.am index 0131e47..88be652 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -10,7 +10,8 @@ rlcmac_RLCMACTest_LDADD = \ $(COMMON_LA) emu_pcu_emu_SOURCES = emu/pcu_emu.cpp emu/test_replay_gprs_attach.cpp \ - emu/openbsc_clone.c emu/openbsc_clone.h + emu/openbsc_clone.c emu/openbsc_clone.h emu/gprs_tests.h \ + emu/test_pdp_activation.cpp emu_pcu_emu_LDADD = \ $(top_builddir)/src/libgprs.la \ $(LIBOSMOGB_LIBS) \ diff --git a/tests/emu/gprs_tests.h b/tests/emu/gprs_tests.h new file mode 100644 index 0000000..1f2c3fb --- /dev/null +++ b/tests/emu/gprs_tests.h @@ -0,0 +1,65 @@ +/* (C) 2013 by Holger Hans Peter Freyther + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +#ifndef tests_h +#define tests_h + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +struct gprs_bssgp_pcu; +struct tlv_parsed; +struct msgb; + +struct gprs_test { + gprs_test(const char *name, const char *description, + void (*start)(struct gprs_bssgp_pcu *), + void (*data) (struct gprs_bssgp_pcu *, struct msgb *, struct tlv_parsed *parsed)) + : name(name) + , description(description) + , start(start) + , data(data) + {} + + const char *name; + const char *description; + void (*start)(struct gprs_bssgp_pcu *); + void (*data) (struct gprs_bssgp_pcu *, struct msgb *, struct tlv_parsed *); +}; + +void gprs_test_success(struct gprs_bssgp_pcu *); + +static inline struct msgb *create_msg(const uint8_t *data, size_t len) +{ + struct msgb *msg = msgb_alloc_headroom(4096, 128, "create msg"); + msg->l3h = msgb_put(msg, len); + memcpy(msg->l3h, data, len); + return msg; +} + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/tests/emu/openbsc_clone.c b/tests/emu/openbsc_clone.c index 707819b..575f4e1 100644 --- a/tests/emu/openbsc_clone.c +++ b/tests/emu/openbsc_clone.c @@ -21,6 +21,7 @@ #include #include +#include #include @@ -214,3 +215,20 @@ int gprs_llc_hdr_parse(struct gprs_llc_hdr_parsed *ghp, return 0; } + +const struct tlv_definition gsm48_gmm_att_tlvdef = { + .def = { + [GSM48_IE_GMM_CIPH_CKSN] = { TLV_TYPE_FIXED, 1 }, + [GSM48_IE_GMM_TIMER_READY] = { TLV_TYPE_TV, 1 }, + [GSM48_IE_GMM_ALLOC_PTMSI] = { TLV_TYPE_TLV, 0 }, + [GSM48_IE_GMM_PTMSI_SIG] = { TLV_TYPE_FIXED, 3 }, + [GSM48_IE_GMM_AUTH_RAND] = { TLV_TYPE_FIXED, 16 }, + [GSM48_IE_GMM_AUTH_SRES] = { TLV_TYPE_FIXED, 4 }, + [GSM48_IE_GMM_IMEISV] = { TLV_TYPE_TLV, 0 }, + [GSM48_IE_GMM_DRX_PARAM] = { TLV_TYPE_FIXED, 2 }, + [GSM48_IE_GMM_MS_NET_CAPA] = { TLV_TYPE_TLV, 0 }, + [GSM48_IE_GMM_PDP_CTX_STATUS] = { TLV_TYPE_TLV, 0 }, + [GSM48_IE_GMM_PS_LCS_CAPA] = { TLV_TYPE_TLV, 0 }, + [GSM48_IE_GMM_GMM_MBMS_CTX_ST] = { TLV_TYPE_TLV, 0 }, + }, +}; diff --git a/tests/emu/openbsc_clone.h b/tests/emu/openbsc_clone.h index d62ff22..b3cc033 100644 --- a/tests/emu/openbsc_clone.h +++ b/tests/emu/openbsc_clone.h @@ -23,6 +23,8 @@ extern "C" { #endif +#include + #include enum gprs_llc_cmd { @@ -57,6 +59,36 @@ struct gprs_llc_hdr_parsed { int gprs_llc_hdr_parse(struct gprs_llc_hdr_parsed *ghp, const uint8_t *llc_hdr, int len); +/* Table 10.4 / 10.4a, GPRS Mobility Management (GMM) */ +#define GSM48_MT_GMM_ATTACH_ACK 0x02 + +/* Chapter 9.4.2 / Table 9.4.2 */ +struct gsm48_attach_ack { + uint8_t att_result:4, /* 10.5.5.7 */ + force_stby:4; /* 10.5.5.1 */ + uint8_t ra_upd_timer; /* 10.5.7.3 */ + uint8_t radio_prio; /* 10.5.7.2 */ + struct gsm48_ra_id ra_id; /* 10.5.5.15 */ + uint8_t data[0]; +} __attribute__((packed)); + +enum gsm48_gprs_ie_mm { + GSM48_IE_GMM_CIPH_CKSN = 0x08, /* 10.5.1.2 */ + GSM48_IE_GMM_TIMER_READY = 0x17, /* 10.5.7.3 */ + GSM48_IE_GMM_ALLOC_PTMSI = 0x18, /* 10.5.1.4 */ + GSM48_IE_GMM_PTMSI_SIG = 0x19, /* 10.5.5.8 */ + GSM48_IE_GMM_AUTH_RAND = 0x21, /* 10.5.3.1 */ + GSM48_IE_GMM_AUTH_SRES = 0x22, /* 10.5.3.2 */ + GSM48_IE_GMM_IMEISV = 0x23, /* 10.5.1.4 */ + GSM48_IE_GMM_DRX_PARAM = 0x27, /* 10.5.5.6 */ + GSM48_IE_GMM_MS_NET_CAPA = 0x31, /* 10.5.5.12 */ + GSM48_IE_GMM_PDP_CTX_STATUS = 0x32, /* 10.5.7.1 */ + GSM48_IE_GMM_PS_LCS_CAPA = 0x33, /* 10.5.5.22 */ + GSM48_IE_GMM_GMM_MBMS_CTX_ST = 0x35, /* 10.5.7.6 */ +}; + +extern const struct tlv_definition gsm48_gmm_att_tlvdef; + #ifdef __cplusplus } #endif diff --git a/tests/emu/pcu_emu.cpp b/tests/emu/pcu_emu.cpp index f4d38cd..b68b856 100644 --- a/tests/emu/pcu_emu.cpp +++ b/tests/emu/pcu_emu.cpp @@ -24,6 +24,9 @@ extern "C" { #include } +#include "gprs_tests.h" + + #include #include @@ -31,6 +34,8 @@ extern "C" { #include #include +static int current_test; + /* Extern data to please the underlying code */ void *tall_pcu_ctx; struct gprs_rlcmac_bts *gprs_rlcmac_bts; @@ -39,6 +44,24 @@ int16_t spoof_mnc = 0, spoof_mcc = 0; extern void test_replay_gprs_attach(struct gprs_bssgp_pcu *pcu); extern void test_replay_gprs_data(struct gprs_bssgp_pcu *, struct msgb *, struct tlv_parsed *); +extern void test_pdp_activation_start(struct gprs_bssgp_pcu *pcu); +extern void test_pdp_activation_data(struct gprs_bssgp_pcu *, struct msgb *, struct tlv_parsed*); + +struct gprs_test all_tests[] = { + gprs_test("gprs_attach_with_tmsi", + "A simple test that verifies that N(U) is " + "increasing across various messages. This makes " + "sure that no new LLE/LLME is created on the fly.", + test_replay_gprs_attach, + test_replay_gprs_data), + gprs_test("gprs_full_attach_pdp_activation", + "A simple test to do a GPRS attach and open a PDP " + "context. Then goes to sleep and waits for you to ping " + "the connection and hopefully re-produce a crash.", + test_pdp_activation_start, + test_pdp_activation_data), +}; + struct gprs_rlcmac_bts *create_bts() { struct gprs_rlcmac_bts *bts; @@ -68,12 +91,12 @@ struct gprs_rlcmac_bts *create_bts() static void bvci_unblocked(struct gprs_bssgp_pcu *pcu) { printf("BVCI unblocked. We can begin with test cases.\n"); - test_replay_gprs_attach(pcu); + all_tests[current_test].start(pcu); } static void bssgp_data(struct gprs_bssgp_pcu *pcu, struct msgb *msg, struct tlv_parsed *tp) { - test_replay_gprs_data(pcu, msg, tp); + all_tests[current_test].data(pcu, msg, tp); } void create_and_connect_bssgp(struct gprs_rlcmac_bts *bts, @@ -112,6 +135,21 @@ int main(int argc, char **argv) return EXIT_SUCCESS; } + +/* + * Test handling.. + */ +void gprs_test_success(struct gprs_bssgp_pcu *pcu) +{ + current_test += 1; + if (current_test >= ARRAY_SIZE(all_tests)) { + printf("All tests executed.\n"); + exit(EXIT_SUCCESS); + } + + all_tests[current_test].start(pcu); +} + /* * stubs that should not be reached */ diff --git a/tests/emu/test_pdp_activation.cpp b/tests/emu/test_pdp_activation.cpp new file mode 100644 index 0000000..673874f --- /dev/null +++ b/tests/emu/test_pdp_activation.cpp @@ -0,0 +1,171 @@ +/* (C) 2013 by Holger Hans Peter Freyther + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + * + */ + +extern "C" { +#include +#include +#include +} + +#include "openbsc_clone.h" +#include "gprs_tests.h" + +#include + +#include +#include + +static const uint8_t attach[] = { + 0x0e, 0x00, 0x26, + 0x01, 0xc0, 0x01, 0x08, 0x01, 0x02, 0xe5, 0x80, + 0x71, 0x0d, 0x01, 0x05, 0xf4, 0x02, 0x30, 0xef, + 0x0e, 0x09, 0xf1, 0x07, 0x00, 0x01, 0x00, 0x0b, + 0x34, 0xc7, 0x03, 0x2a, 0xa0, 0x42, 0x7c, 0xad, + 0xe1, 0x18, 0x0b, 0xf8, 0xef, 0xfc +}; + +static const uint8_t id_resp_imei[] = { + 0x0e, 0x00, 0x11, + 0x01, 0xc0, 0x05, 0x08, 0x16, 0x08, 0x3a, 0x49, + 0x50, 0x13, 0x28, 0x15, 0x80, 0x01, 0x21, 0x6c, + 0x22 +}; + +static const uint8_t id_resp_imsi[] = { + 0x0e, 0x00, 0x11, + 0x01, 0xc0, 0x09, 0x08, 0x16, 0x08, 0x99, 0x10, + 0x07, 0x00, 0x00, 0x00, 0x03, 0x49, 0xc7, 0x5b, + 0xb6 +}; + +static const uint8_t attach_complete[] = { + 0x0e, 0x00, 0x08, + 0x01, 0xc0, 0x0d, 0x08, 0x03, 0x55, 0x1c, 0xea +}; + +static const uint8_t pdp_context[] = { + 0x0e, 0x00, 0x5a, + 0x01, 0xc0, 0x11, 0x0a, 0x41, 0x05, 0x03, 0x0c, + 0x00, 0x00, 0x1f, 0x10, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x21, 0x28, + 0x12, 0x08, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, + 0x65, 0x74, 0x05, 0x65, 0x70, 0x6c, 0x75, 0x73, + 0x02, 0x64, 0x65, 0x27, 0x2a, 0x80, 0xc0, 0x23, + 0x13, 0x01, 0x00, 0x00, 0x13, 0x05, 0x65, 0x70, + 0x6c, 0x75, 0x73, 0x08, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x65, 0x74, 0x80, 0x21, 0x10, 0x01, + 0x00, 0x00, 0x10, 0x81, 0x06, 0x00, 0x00, 0x00, + 0x00, 0x83, 0x06, 0x00, 0x00, 0x00, 0x00, 0xcf, + 0x90, 0xcc +}; + +static const uint8_t qos_profile[] = { 0x0, 0x0, 0x04 }; +static uint32_t tlli = 0xadf11821; + +enum state { + Test_Start, + Test_IdRespIMEI, + Test_IdRespIMSI, + Test_AttachCompl, + Test_PDPAct, + Test_Done, +}; + +static enum state current_state = Test_Start; + +static void extract_tmsi_and_generate_tlli(struct msgb *msg, struct tlv_parsed *tp) +{ + uint32_t tmsi; + struct bssgp_ud_hdr *budh; + struct gprs_llc_hdr_parsed hp; + struct tlv_parsed ack_tp; + int rc; + + gprs_llc_hdr_parse(&hp, TLVP_VAL(tp, BSSGP_IE_LLC_PDU), + TLVP_LEN(tp, BSSGP_IE_LLC_PDU)); + msgb_gmmh(msg) = (unsigned char *) hp.data; + + struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_gmmh(msg); + + OSMO_ASSERT(gh->msg_type == GSM48_MT_GMM_ATTACH_ACK); + struct gsm48_attach_ack *ack = (struct gsm48_attach_ack *) gh->data; + rc = tlv_parse(&ack_tp, &gsm48_gmm_att_tlvdef, ack->data, + (msg->data + msg->len) - ack->data, 0, 0); + + + OSMO_ASSERT(TLVP_PRESENT(&ack_tp, GSM48_IE_GMM_ALLOC_PTMSI)); + memcpy(&tmsi, TLVP_VAL(&ack_tp, GSM48_IE_GMM_ALLOC_PTMSI) + 1, 4); + tmsi = ntohl(tmsi); + tlli = gprs_tmsi2tlli(tmsi, TLLI_LOCAL); + printf("New TLLI(0x%08x) based on tmsi(0x%x)\n", tlli, tmsi); +} + +void test_pdp_activation_start(struct gprs_bssgp_pcu *pcu) +{ + struct msgb *msg = create_msg(attach, ARRAY_SIZE(attach)); + bssgp_tx_ul_ud(pcu->bctx, tlli, qos_profile, msg); + current_state = Test_IdRespIMEI; +} + + +void test_pdp_activation_data(struct gprs_bssgp_pcu *pcu, struct msgb *msg, struct tlv_parsed *tp) +{ + const uint8_t *data; + size_t len; + + switch (current_state) { + case Test_IdRespIMEI: + data = id_resp_imei; + len = ARRAY_SIZE(id_resp_imei); + current_state = Test_IdRespIMSI; + break; + case Test_IdRespIMSI: + data = id_resp_imsi; + len = ARRAY_SIZE(id_resp_imsi); + current_state = Test_AttachCompl; + break; + case Test_AttachCompl: + data = attach_complete; + len = ARRAY_SIZE(attach_complete); + extract_tmsi_and_generate_tlli(msg, tp); + current_state = Test_PDPAct; + break; + case Test_PDPAct: + printf("PDP context is active or not...\n"); + return; + break; + case Test_Done: + case Test_Start: /* fall through */ + return; + break; + default: + printf("Unknown state. %d\n", current_state); + return; + break; + }; + + struct msgb *out = create_msg(data, len); + bssgp_tx_ul_ud(pcu->bctx, tlli, qos_profile, out); + + /* send it after the PDP... */ + if (current_state == Test_PDPAct) { + out = create_msg(pdp_context, ARRAY_SIZE(pdp_context)); + bssgp_tx_ul_ud(pcu->bctx, tlli, qos_profile, out); + } +} diff --git a/tests/emu/test_replay_gprs_attach.cpp b/tests/emu/test_replay_gprs_attach.cpp index fb1e77f..9bcab57 100644 --- a/tests/emu/test_replay_gprs_attach.cpp +++ b/tests/emu/test_replay_gprs_attach.cpp @@ -24,6 +24,7 @@ extern "C" { } #include "openbsc_clone.h" +#include "gprs_tests.h" #include @@ -45,14 +46,6 @@ static const uint8_t gprs_attach_llc[] = { static int next_wanted_nu; -struct msgb *create_msg(const uint8_t *data, size_t len) -{ - struct msgb *msg = msgb_alloc_headroom(4096, 128, "create msg"); - msg->l3h = msgb_put(msg, len); - memcpy(msg->l3h, data, len); - return msg; -} - void test_replay_gprs_attach(struct gprs_bssgp_pcu *pcu) { uint32_t tlli = 0xadf11820; @@ -88,8 +81,8 @@ void test_replay_gprs_data(struct gprs_bssgp_pcu *pcu, struct msgb *msg, struct OSMO_ASSERT(ph.seq_tx == next_wanted_nu++); /* this test just wants to see messages... no further data is sent */ - if (next_wanted_nu == 4) { - printf("Test done.\n"); - exit(EXIT_SUCCESS); + if (next_wanted_nu == 6) { + printf("GPRS attach with increasing N(U) done.\n"); + gprs_test_success(pcu); } } -- 1.8.3.2 From hfreyther at sysmocom.de Sat Aug 24 17:28:39 2013 From: hfreyther at sysmocom.de (Holger Hans Peter Freyther) Date: Sat, 24 Aug 2013 19:28:39 +0200 Subject: TBF and API design.. (boolean/int trap) Message-ID: <20130824172839.GA21648@xiaoyu.lan> Good Evening, I started a branch to add a basic structure to the TBF handling. The reasons why I am doing this is for another lengthy email. I just came across a piece of code and would like to create some awareness: int write_immediate_assignment(bitvec * dest, uint8_t downlink, uint8_t ra, uint32_t ref_fn, uint8_t ta, uint16_t arfcn, uint8_t ts, uint8_t tsc, uint8_t tfi, uint8_t usf, uint32_t tlli, uint8_t polling, uint32_t fn, uint8_t single_block, uint8_t alpha, uint8_t gamma, int8_t ta_idx); and invocations like: if (sb) plen = write_immediate_assignment(immediate_assignment, 0, ra, Fn, qta >> 2, bts->trx[trx].arfcn, ts, bts->trx[trx].pdch[ts].tsc, 0, 0, 0, 0, sb_fn, 1, bts->alpha, bts->gamma, -1); else plen = write_immediate_assignment(immediate_assignment, 0, ra, Fn, tbf->ta, tbf->arfcn, tbf->first_ts, tbf->tsc, tbf->tfi, tbf->dir.ul.usf[tbf->first_ts], 0, 0, 0, 0, bts->alpha, bts->gamma, -1); With the above method and two invocations it is difficult to get all arguments right and it is a strong argument against ever writing code like this. With C++ one could create overloads that take the bts and tbf as parameters. Or if one really only wants to have a single method use a struct to pass the parameters. This has the benefit of naming the parameters and will certainly require the same amount of stack space as the current option. So please, don't write methods like the above as they make maintaining the code more difficult than it needs to be. holger -- - Holger Freyther http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Schivelbeiner Str. 5 * 10439 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Geschaeftsfuehrer / Managing Directors: Holger Freyther, Harald Welte From alexander.chemeris at gmail.com Sat Aug 24 17:36:38 2013 From: alexander.chemeris at gmail.com (Alexander Chemeris) Date: Sat, 24 Aug 2013 21:36:38 +0400 Subject: TBF and API design.. (boolean/int trap) In-Reply-To: <20130824172839.GA21648@xiaoyu.lan> References: <20130824172839.GA21648@xiaoyu.lan> Message-ID: Good catch, Holger, Thank you for bringing this up. PS Looking forward for your other lengthy e-mail. On Sat, Aug 24, 2013 at 9:28 PM, Holger Hans Peter Freyther wrote: > Good Evening, > > I started a branch to add a basic structure to the TBF handling. The > reasons why I am doing this is for another lengthy email. I just came > across a piece of code and would like to create some awareness: > > int write_immediate_assignment(bitvec * dest, uint8_t downlink, uint8_t ra, > uint32_t ref_fn, uint8_t ta, uint16_t arfcn, uint8_t ts, uint8_t tsc, > uint8_t tfi, uint8_t usf, uint32_t tlli, uint8_t polling, > uint32_t fn, uint8_t single_block, uint8_t alpha, uint8_t gamma, > int8_t ta_idx); > > and invocations like: > > if (sb) > plen = write_immediate_assignment(immediate_assignment, 0, ra, > Fn, qta >> 2, bts->trx[trx].arfcn, ts, > bts->trx[trx].pdch[ts].tsc, 0, 0, 0, 0, sb_fn, 1, > bts->alpha, bts->gamma, -1); > else > plen = write_immediate_assignment(immediate_assignment, 0, ra, > Fn, tbf->ta, tbf->arfcn, tbf->first_ts, tbf->tsc, > tbf->tfi, tbf->dir.ul.usf[tbf->first_ts], 0, 0, 0, 0, > bts->alpha, bts->gamma, -1); > > With the above method and two invocations it is difficult to get all > arguments right and it is a strong argument against ever writing code > like this. With C++ one could create overloads that take the bts and > tbf as parameters. Or if one really only wants to have a single method > use a struct to pass the parameters. This has the benefit of naming > the parameters and will certainly require the same amount of stack > space as the current option. > > So please, don't write methods like the above as they make maintaining > the code more difficult than it needs to be. > > holger > > -- > - Holger Freyther http://www.sysmocom.de/ > ======================================================================= > * sysmocom - systems for mobile communications GmbH > * Schivelbeiner Str. 5 > * 10439 Berlin, Germany > * Sitz / Registered office: Berlin, HRB 134158 B > * Geschaeftsfuehrer / Managing Directors: Holger Freyther, Harald Welte > > -- Regards, Alexander Chemeris. CEO, Fairwaves LLC / ??? ??????? http://fairwaves.ru From hfreyther at sysmocom.de Sun Aug 25 11:01:36 2013 From: hfreyther at sysmocom.de (Holger Hans Peter Freyther) Date: Sun, 25 Aug 2013 13:01:36 +0200 Subject: [PATCH 3/3] tbf: constify the IMSI argument for the downlink assignment In-Reply-To: <1377428496-21721-1-git-send-email-hfreyther@sysmocom.de> References: <1377428496-21721-1-git-send-email-hfreyther@sysmocom.de> Message-ID: <1377428496-21721-3-git-send-email-hfreyther@sysmocom.de> From: Holger Hans Peter Freyther --- src/gprs_rlcmac.h | 2 +- src/gprs_rlcmac_data.cpp | 6 +++--- src/pcu_l1_if.cpp | 2 +- src/pcu_l1_if.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/gprs_rlcmac.h b/src/gprs_rlcmac.h index 4329cb8..8de7417 100644 --- a/src/gprs_rlcmac.h +++ b/src/gprs_rlcmac.h @@ -392,7 +392,7 @@ struct msgb *gprs_rlcmac_send_packet_downlink_assignment( struct gprs_rlcmac_tbf *tbf, uint32_t fn); void gprs_rlcmac_trigger_downlink_assignment(struct gprs_rlcmac_tbf *tbf, - struct gprs_rlcmac_tbf *old_tbf, char *imsi); + struct gprs_rlcmac_tbf *old_tbf, const char *imsi); int gprs_rlcmac_downlink_ack(struct gprs_rlcmac_tbf *tbf, uint8_t final, uint8_t ssn, uint8_t *rbb); diff --git a/src/gprs_rlcmac_data.cpp b/src/gprs_rlcmac_data.cpp index ff5274f..294753d 100644 --- a/src/gprs_rlcmac_data.cpp +++ b/src/gprs_rlcmac_data.cpp @@ -74,7 +74,7 @@ struct rlc_li_field { } static void gprs_rlcmac_downlink_assignment(gprs_rlcmac_tbf *tbf, uint8_t poll, - char *imsi); + const char *imsi); static int gprs_rlcmac_diag(struct gprs_rlcmac_tbf *tbf) { @@ -1819,7 +1819,7 @@ struct msgb *gprs_rlcmac_send_packet_downlink_assignment( } static void gprs_rlcmac_downlink_assignment(gprs_rlcmac_tbf *tbf, uint8_t poll, - char *imsi) + const char *imsi) { struct gprs_rlcmac_bts *bts = gprs_rlcmac_bts; int plen; @@ -1840,7 +1840,7 @@ static void gprs_rlcmac_downlink_assignment(gprs_rlcmac_tbf *tbf, uint8_t poll, /* depending on the current TBF, we assign on PACCH or AGCH */ void gprs_rlcmac_trigger_downlink_assignment(struct gprs_rlcmac_tbf *tbf, - struct gprs_rlcmac_tbf *old_tbf, char *imsi) + struct gprs_rlcmac_tbf *old_tbf, const char *imsi) { #ifdef DEBUG_DL_ASS_IDLE strncpy(debug_imsi, imsi); diff --git a/src/pcu_l1_if.cpp b/src/pcu_l1_if.cpp index 43bd36e..218dc23 100644 --- a/src/pcu_l1_if.cpp +++ b/src/pcu_l1_if.cpp @@ -174,7 +174,7 @@ void pcu_l1if_tx_agch(bitvec * block, int plen) pcu_tx_data_req(0, 0, PCU_IF_SAPI_AGCH, 0, 0, 0, data, 23); } -void pcu_l1if_tx_pch(bitvec * block, int plen, char *imsi) +void pcu_l1if_tx_pch(bitvec * block, int plen, const char *imsi) { uint8_t data[23+3]; /* prefix PLEN */ diff --git a/src/pcu_l1_if.h b/src/pcu_l1_if.h index 715f89f..f01b95a 100644 --- a/src/pcu_l1_if.h +++ b/src/pcu_l1_if.h @@ -40,7 +40,7 @@ void pcu_l1if_tx_ptcch(msgb *msg, uint8_t trx, uint8_t ts, uint16_t arfcn, uint32_t fn, uint8_t block_nr); void pcu_l1if_tx_agch(bitvec * block, int len); -void pcu_l1if_tx_pch(bitvec * block, int plen, char *imsi); +void pcu_l1if_tx_pch(bitvec * block, int plen, const char *imsi); int pcu_l1if_open(void); void pcu_l1if_close(void); -- 1.8.3.2 From hfreyther at sysmocom.de Sun Aug 25 11:01:35 2013 From: hfreyther at sysmocom.de (Holger Hans Peter Freyther) Date: Sun, 25 Aug 2013 13:01:35 +0200 Subject: [PATCH 2/3] tbf: Make multislot lookup tables static/const In-Reply-To: <1377428496-21721-1-git-send-email-hfreyther@sysmocom.de> References: <1377428496-21721-1-git-send-email-hfreyther@sysmocom.de> Message-ID: <1377428496-21721-2-git-send-email-hfreyther@sysmocom.de> From: Holger Hans Peter Freyther --- src/gprs_rlcmac.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gprs_rlcmac.cpp b/src/gprs_rlcmac.cpp index 913ae48..1d1a8c6 100644 --- a/src/gprs_rlcmac.cpp +++ b/src/gprs_rlcmac.cpp @@ -36,7 +36,7 @@ struct gprs_ms_multislot_class { uint8_t type; /* Type of Mobile */ }; -struct gprs_ms_multislot_class gprs_ms_multislot_class[32] = { +static const struct gprs_ms_multislot_class gprs_ms_multislot_class[32] = { /* M-S Class Rx Tx Sum Tta Ttb Tra Trb Type */ /* N/A */ { MS_NA,MS_NA, MS_NA, MS_NA, MS_NA, MS_NA, MS_NA, MS_NA }, /* 1 */ { 1, 1, 2, 3, 2, 4, 2, 1 }, @@ -467,14 +467,14 @@ int alloc_algorithm_b(struct gprs_rlcmac_bts *bts, struct gprs_rlcmac_tbf *tbf, uint32_t cust, uint8_t single) { struct gprs_rlcmac_pdch *pdch; - struct gprs_ms_multislot_class *ms_class; + const struct gprs_ms_multislot_class *ms_class; uint8_t Rx, Tx, Sum; /* Maximum Number of Slots: RX, Tx, Sum Rx+Tx */ uint8_t Tta, Ttb, Tra, Trb, Tt, Tr; /* Minimum Number of Slots */ uint8_t Type; /* Type of Mobile */ uint8_t rx_win_min = 0, rx_win_max = 7; uint8_t tx_win_min, tx_win_max, tx_range; uint8_t rx_window = 0, tx_window = 0; - const char *digit[10] = { "0","1","2","3","4","5","6","7","8","9" }; + static const char *digit[10] = { "0","1","2","3","4","5","6","7","8","9" }; int8_t usf[8] = { -1, -1, -1, -1, -1, -1, -1, -1 }; /* must be signed */ int8_t tsc = -1; /* must be signed */ int8_t first_common_ts = -1; -- 1.8.3.2 From hfreyther at sysmocom.de Sun Aug 25 11:01:34 2013 From: hfreyther at sysmocom.de (Holger Hans Peter Freyther) Date: Sun, 25 Aug 2013 13:01:34 +0200 Subject: [PATCH 1/3] tfi: The tfi_alloc doesn't allocate anything, rename the function Message-ID: <1377428496-21721-1-git-send-email-hfreyther@sysmocom.de> From: Holger Hans Peter Freyther Call things by what they do and this function doesn't allocate anything but it is searching for the first unallocated tbf index. --- src/gprs_bssgp_pcu.cpp | 2 +- src/gprs_rlcmac.cpp | 3 ++- src/gprs_rlcmac.h | 3 ++- src/gprs_rlcmac_data.cpp | 4 ++-- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/gprs_bssgp_pcu.cpp b/src/gprs_bssgp_pcu.cpp index 6f67f52..4833af8 100644 --- a/src/gprs_bssgp_pcu.cpp +++ b/src/gprs_bssgp_pcu.cpp @@ -233,7 +233,7 @@ static int gprs_bssgp_pcu_rx_dl_ud(struct msgb *msg, struct tlv_parsed *tp) } // Create new TBF (any TRX) - tfi = tfi_alloc(the_pcu.bts, GPRS_RLCMAC_DL_TBF, &trx, use_trx); + tfi = tfi_find_free(the_pcu.bts, GPRS_RLCMAC_DL_TBF, &trx, use_trx); if (tfi < 0) { LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH resource\n"); /* FIXME: send reject */ diff --git a/src/gprs_rlcmac.cpp b/src/gprs_rlcmac.cpp index 8874983..913ae48 100644 --- a/src/gprs_rlcmac.cpp +++ b/src/gprs_rlcmac.cpp @@ -2,6 +2,7 @@ * * Copyright (C) 2012 Ivan Klyuchnikov * Copyright (C) 2012 Andreas Eversberg + * Copyright (C) 2013 by Holger Hans Peter Freyther * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -176,7 +177,7 @@ void debug_diagram(int diag, const char *format, ...) /* FIXME: spread ressources over multiple TRX. Also add option to use same * TRX in case of existing TBF for TLLI in the other direction. */ /* search for free TFI and return TFI, TRX */ -int tfi_alloc(struct gprs_rlcmac_bts *bts, enum gprs_rlcmac_tbf_direction dir, +int tfi_find_free(struct gprs_rlcmac_bts *bts, enum gprs_rlcmac_tbf_direction dir, uint8_t *_trx, int8_t use_trx) { struct gprs_rlcmac_pdch *pdch; diff --git a/src/gprs_rlcmac.h b/src/gprs_rlcmac.h index ac437f5..4329cb8 100644 --- a/src/gprs_rlcmac.h +++ b/src/gprs_rlcmac.h @@ -1,6 +1,7 @@ /* gprs_rlcmac.h * * Copyright (C) 2012 Ivan Klyuchnikov + * Copyright (C) 2013 by Holger Hans Peter Freyther * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -309,7 +310,7 @@ int sba_alloc(uint8_t *_trx, uint8_t *_ts, uint32_t *_fn, uint8_t ta); struct gprs_rlcmac_sba *sba_find(uint8_t trx, uint8_t ts, uint32_t fn); -int tfi_alloc(struct gprs_rlcmac_bts *bts, enum gprs_rlcmac_tbf_direction dir, +int tfi_find_free(struct gprs_rlcmac_bts *bts, enum gprs_rlcmac_tbf_direction dir, uint8_t *_trx, int8_t use_trx); struct gprs_rlcmac_tbf *tbf_alloc(struct gprs_rlcmac_bts *bts, diff --git a/src/gprs_rlcmac_data.cpp b/src/gprs_rlcmac_data.cpp index 4d5acb9..ff5274f 100644 --- a/src/gprs_rlcmac_data.cpp +++ b/src/gprs_rlcmac_data.cpp @@ -239,7 +239,7 @@ static struct gprs_rlcmac_tbf *alloc_ul_tbf(int8_t use_trx, uint8_t ms_class, uint8_t tfi; /* create new TBF, use sme TRX as DL TBF */ - tfi = tfi_alloc(bts, GPRS_RLCMAC_UL_TBF, &trx, use_trx); + tfi = tfi_find_free(bts, GPRS_RLCMAC_UL_TBF, &trx, use_trx); if (tfi < 0) { LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH ressource\n"); /* FIXME: send reject */ @@ -1174,7 +1174,7 @@ int gprs_rlcmac_rcv_rach(uint8_t ra, uint32_t Fn, int16_t qta) "(AGCH)\n"); } else { // Create new TBF - tfi = tfi_alloc(bts, GPRS_RLCMAC_UL_TBF, &trx, -1); + tfi = tfi_find_free(bts, GPRS_RLCMAC_UL_TBF, &trx, -1); if (tfi < 0) { LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH ressource\n"); /* FIXME: send reject */ -- 1.8.3.2 From hfreyther at sysmocom.de Sun Aug 25 11:55:08 2013 From: hfreyther at sysmocom.de (Holger Hans Peter Freyther) Date: Sun, 25 Aug 2013 13:55:08 +0200 Subject: [PATCH 1/3] tfi: The tfi_alloc doesn't allocate anything, rename the function In-Reply-To: <1377428496-21721-1-git-send-email-hfreyther@sysmocom.de> References: <1377428496-21721-1-git-send-email-hfreyther@sysmocom.de> Message-ID: <20130825115508.GU27820@xiaoyu.lan> On Sun, Aug 25, 2013 at 01:01:34PM +0200, Holger Hans Peter Freyther wrote: Hi, > Call things by what they do and this function doesn't allocate > anything but it is searching for the first unallocated tbf index. as part of cleaning up and adding structure (and on the way to eliminate the various hidden errors) I came across tfi_alloc. There are three places that mostly do (the topic of copy and paste in the pcu code is another topic): tfi = tfi_alloc() if (tfi < 0) return; tbf = tbf_alloc(tfi,...); if (!tbf) return; Now just by the name... we would leak the result of tfi_alloc in the above code. But then again tfi_alloc doesn't allocate anything it is just trying to find an unallocated index. Which brings me to: Name things by what they do (and update the name when the implementation does change). In the above case if the method is called tfi_find_free I will know that there is no side-effect and that I will not need to call a tfi_free. cheers holger -- - Holger Freyther http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Schivelbeiner Str. 5 * 10439 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Geschaeftsfuehrer / Managing Directors: Holger Freyther, Harald Welte From hfreyther at sysmocom.de Fri Aug 30 13:14:07 2013 From: hfreyther at sysmocom.de (Holger Hans Peter Freyther) Date: Fri, 30 Aug 2013 15:14:07 +0200 Subject: [PATCH 3/3] tbf: constify the IMSI argument for the downlink assignment In-Reply-To: <1377428496-21721-3-git-send-email-hfreyther@sysmocom.de> References: <1377428496-21721-1-git-send-email-hfreyther@sysmocom.de> <1377428496-21721-3-git-send-email-hfreyther@sysmocom.de> Message-ID: <20130830131407.GC17238@xiaoyu.lan> On Sun, Aug 25, 2013 at 01:01:36PM +0200, Holger Hans Peter Freyther wrote: > From: Holger Hans Peter Freyther Ivan, ping? -- - Holger Freyther http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Schivelbeiner Str. 5 * 10439 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Geschaeftsfuehrer / Managing Directors: Holger Freyther, Harald Welte From hfreyther at sysmocom.de Fri Aug 30 13:13:44 2013 From: hfreyther at sysmocom.de (Holger Hans Peter Freyther) Date: Fri, 30 Aug 2013 15:13:44 +0200 Subject: [PATCH 01/10] bssgp: Re-indent the switch/case statement In-Reply-To: <1377155824-7598-1-git-send-email-hfreyther@sysmocom.de> References: <1377155824-7598-1-git-send-email-hfreyther@sysmocom.de> Message-ID: <20130830131344.GB17238@xiaoyu.lan> On Thu, Aug 22, 2013 at 09:16:55AM +0200, Holger Freyther wrote: > From: Holger Hans Peter Freyther ping? Ivan, any feedback on these patches? -- - Holger Freyther http://www.sysmocom.de/ ======================================================================= * sysmocom - systems for mobile communications GmbH * Schivelbeiner Str. 5 * 10439 Berlin, Germany * Sitz / Registered office: Berlin, HRB 134158 B * Geschaeftsfuehrer / Managing Directors: Holger Freyther, Harald Welte From Ivan.Kluchnikov at fairwaves.ru Fri Aug 30 14:19:26 2013 From: Ivan.Kluchnikov at fairwaves.ru (Ivan Kluchnikov) Date: Fri, 30 Aug 2013 18:19:26 +0400 Subject: [PATCH 01/10] bssgp: Re-indent the switch/case statement In-Reply-To: <20130830131344.GB17238@xiaoyu.lan> References: <1377155824-7598-1-git-send-email-hfreyther@sysmocom.de> <20130830131344.GB17238@xiaoyu.lan> Message-ID: Hi Holger, Sorry for delay, I plan to test and review all these patches on Monday, after that I will merge them. 2013/8/30 Holger Hans Peter Freyther : > On Thu, Aug 22, 2013 at 09:16:55AM +0200, Holger Freyther wrote: >> From: Holger Hans Peter Freyther > > ping? Ivan, any feedback on these patches? > > > -- > - Holger Freyther http://www.sysmocom.de/ > ======================================================================= > * sysmocom - systems for mobile communications GmbH > * Schivelbeiner Str. 5 > * 10439 Berlin, Germany > * Sitz / Registered office: Berlin, HRB 134158 B > * Geschaeftsfuehrer / Managing Directors: Holger Freyther, Harald Welte > > -- Regards, Ivan Kluchnikov. http://fairwaves.ru