From cd1f751e4c28d12fe0b6e77bd7448206990417f8 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Wed, 10 Jun 2009 02:52:31 +0200 Subject: Search for BTS's in the Location Area of the subscriber we call Search for the MS at BTS in the location area of the called_subscr. This makes the case work where caller and receiver are not in the same location area. In fact this looks like a breach of a BSC/MSC separation, I have no idea if in true networks a BSC is managing BTS in different location areas. --- openbsc/src/gsm_04_08.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'openbsc') diff --git a/openbsc/src/gsm_04_08.c b/openbsc/src/gsm_04_08.c index 0630764a2..462e67af8 100644 --- a/openbsc/src/gsm_04_08.c +++ b/openbsc/src/gsm_04_08.c @@ -1357,8 +1357,7 @@ static int gsm48_cc_rx_setup(struct msgb *msg) /* Start paging subscriber on all BTS in LAC of subscriber */ bts = NULL; do { - bts = gsm_bts_by_lac(msg->trx->bts->network, - msg->lchan->subscr->lac, bts); + bts = gsm_bts_by_lac(msg->trx->bts->network, called_subscr->lac, bts); if (!bts) break; /* Trigger paging */ -- cgit v1.2.3 From 2c451238070bf9ceec4601c55160db8e0da0d1cc Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Wed, 10 Jun 2009 02:45:42 +0200 Subject: Move the "finding" of the right BTS into paging.c Move the secret of how to find the BTS in a LocationArea into the paging layer. This allows to implement different strategies without changing other parts. E.g. we might want to try the BTS were the device was seen last and then try... There should be no semantic change and things should continue to work. It is sadly not tested though. --- openbsc/src/gsm_04_08.c | 25 ++----------------------- openbsc/src/paging.c | 46 ++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 44 insertions(+), 27 deletions(-) (limited to 'openbsc') diff --git a/openbsc/src/gsm_04_08.c b/openbsc/src/gsm_04_08.c index 462e67af8..5702dca15 100644 --- a/openbsc/src/gsm_04_08.c +++ b/openbsc/src/gsm_04_08.c @@ -1016,7 +1016,6 @@ static int gsm48_rr_rx_pag_resp(struct msgb *msg) u_int8_t mi_type = mi_lv[1] & GSM_MI_TYPE_MASK; char mi_string[MI_SIZE]; struct gsm_subscriber *subscr; - struct gsm_bts *bts; struct paging_signal_data sig_data; int rc = 0; @@ -1064,18 +1063,6 @@ static int gsm48_rr_rx_pag_resp(struct msgb *msg) /* Stop paging on the bts we received the paging response */ paging_request_stop(msg->trx->bts, subscr, msg->lchan); - /* Stop paging on all other bts' */ - bts = NULL; - do { - bts = gsm_bts_by_lac(msg->trx->bts->network, subscr->lac, bts); - if (!bts) - break; - if (bts == msg->trx->bts) - continue; - /* Stop paging */ - paging_request_stop(bts, subscr, NULL); - } while (1); - /* FIXME: somehow signal the completion of the PAGING to * the entity that requested the paging */ @@ -1310,7 +1297,6 @@ static int gsm48_cc_rx_setup(struct msgb *msg) struct gsm48_hdr *gh = msgb_l3(msg); unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh); struct gsm_subscriber *called_subscr; - struct gsm_bts *bts; char called_number[(43-2)*2 + 1] = "\0"; struct tlv_parsed tp; u_int8_t num_type; @@ -1355,15 +1341,8 @@ static int gsm48_cc_rx_setup(struct msgb *msg) call->called_subscr = called_subscr; /* Start paging subscriber on all BTS in LAC of subscriber */ - bts = NULL; - do { - bts = gsm_bts_by_lac(msg->trx->bts->network, called_subscr->lac, bts); - if (!bts) - break; - /* Trigger paging */ - paging_request(bts, called_subscr, RSL_CHANNEED_TCH_F, - setup_trig_pag_evt, call); - } while (1); + paging_request(msg->trx->bts, called_subscr, RSL_CHANNEED_TCH_F, + setup_trig_pag_evt, call); /* send a CALL PROCEEDING message to the MO */ ret = gsm48_tx_simple(msg->lchan, GSM48_PDISC_CC, diff --git a/openbsc/src/paging.c b/openbsc/src/paging.c index f3bdf6973..e647b33be 100644 --- a/openbsc/src/paging.c +++ b/openbsc/src/paging.c @@ -210,8 +210,8 @@ static void paging_T3113_expired(void *data) paging_remove_request(&req->bts->paging, req); } -void paging_request(struct gsm_bts *bts, struct gsm_subscriber *subscr, - int type, gsm_cbfn *cbfn, void *data) +static void _paging_request(struct gsm_bts *bts, struct gsm_subscriber *subscr, + int type, gsm_cbfn *cbfn, void *data) { struct gsm_bts_paging_state *bts_entry = &bts->paging; struct gsm_paging_request *req; @@ -237,9 +237,25 @@ void paging_request(struct gsm_bts *bts, struct gsm_subscriber *subscr, bsc_schedule_timer(&bts_entry->work_timer, 1, 0); } +void paging_request(struct gsm_bts *_bts, struct gsm_subscriber *subscr, + int type, gsm_cbfn *cbfn, void *data) +{ + struct gsm_bts *bts = NULL; + + do { + bts = gsm_bts_by_lac(_bts->network, subscr->lac, bts); + if (!bts) + break; + + /* Trigger paging */ + _paging_request(bts, subscr, RSL_CHANNEED_TCH_F, cbfn, data); + } while (1); +} + + /* we consciously ignore the type of the request here */ -void paging_request_stop(struct gsm_bts *bts, struct gsm_subscriber *subscr, - struct gsm_lchan *lchan) +static void _paging_request_stop(struct gsm_bts *bts, struct gsm_subscriber *subscr, + struct gsm_lchan *lchan) { struct gsm_bts_paging_state *bts_entry = &bts->paging; struct gsm_paging_request *req, *req2; @@ -256,6 +272,28 @@ void paging_request_stop(struct gsm_bts *bts, struct gsm_subscriber *subscr, } } +/* Stop paging on all other bts' */ +void paging_request_stop(struct gsm_bts *_bts, struct gsm_subscriber *subscr, + struct gsm_lchan *lchan) +{ + struct gsm_bts *bts = NULL; + + do { + /* + * FIXME: Don't use the lac of the subscriber... + * as it might have magically changed the lac.. use the + * location area of the _bts as reconfiguration of the + * network is probably happening less often. + */ + bts = gsm_bts_by_lac(_bts->network, subscr->lac, bts); + if (!bts) + break; + + /* Stop paging */ + _paging_request_stop(bts, subscr, NULL); + } while (1); +} + void paging_update_buffer_space(struct gsm_bts *bts, u_int16_t free_slots) { bts->paging.available_slots = free_slots; -- cgit v1.2.3 From 5c85ef92954a77f10710f6f9fcb6d49b147fc476 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Thu, 4 Jun 2009 16:58:39 +0200 Subject: Remove use_lchan and put_lchan from location updating request paths Andreas Eversberg is suspecting that some of these messages are not balanced and we are seeing a leak here. The general location updating request is guarded by the "location updating request" object inside the lchan that will keep the channel open for at least five seconds to get all the information we need. --- openbsc/src/gsm_04_08.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'openbsc') diff --git a/openbsc/src/gsm_04_08.c b/openbsc/src/gsm_04_08.c index 5702dca15..804c15dee 100644 --- a/openbsc/src/gsm_04_08.c +++ b/openbsc/src/gsm_04_08.c @@ -578,11 +578,6 @@ static int mm_rx_id_resp(struct msgb *msg) DEBUGP(DMM, "IDENTITY RESPONSE: mi_type=0x%02x MI(%s)\n", mi_type, mi_string); - /* - * Rogue messages could trick us but so is life - */ - put_lchan(lchan); - switch (mi_type) { case GSM_MI_TYPE_IMSI: if (!lchan->subscr) @@ -672,7 +667,6 @@ static int mm_rx_loc_upd_req(struct msgb *msg) switch (mi_type) { case GSM_MI_TYPE_IMSI: /* we always want the IMEI, too */ - use_lchan(lchan); rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI); lchan->loc_operation->waiting_for_imei = 1; @@ -681,7 +675,6 @@ static int mm_rx_loc_upd_req(struct msgb *msg) break; case GSM_MI_TYPE_TMSI: /* we always want the IMEI, too */ - use_lchan(lchan); rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMEI); lchan->loc_operation->waiting_for_imei = 1; @@ -689,7 +682,6 @@ static int mm_rx_loc_upd_req(struct msgb *msg) subscr = subscr_get_by_tmsi(mi_string); if (!subscr) { /* send IDENTITY REQUEST message to get IMSI */ - use_lchan(lchan); rc = mm_tx_identity_req(lchan, GSM_MI_TYPE_IMSI); lchan->loc_operation->waiting_for_imsi = 1; } -- cgit v1.2.3 From e91f57879d4f6f919c56c28316e6ac7e75b91e13 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Wed, 10 Jun 2009 10:20:16 +0200 Subject: [bsc_hack] Sanity check for the GSM1800 nanoBTS The GSM1800 requires us to use channels between 512-885. When failing to provide such a channel the OML layer will fail and no RSL connection will be opened. Add a sanity check before creating the gsm_network and fail when the channels are not within the allowed range. Assume no one is operating a BS11 in the 1800 spectrum. --- openbsc/src/bsc_hack.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'openbsc') diff --git a/openbsc/src/bsc_hack.c b/openbsc/src/bsc_hack.c index 7aa8b9aef..687be33cf 100644 --- a/openbsc/src/bsc_hack.c +++ b/openbsc/src/bsc_hack.c @@ -960,6 +960,26 @@ static int bootstrap_network(void) { struct gsm_bts *bts; + switch(BTS_TYPE) { + case GSM_BTS_TYPE_NANOBTS_1800: + if (ARFCN < 512 || ARFCN > 885) { + fprintf(stderr, "GSM1800 channel must be between 512-885.\n"); + return -EINVAL; + } + break; + case GSM_BTS_TYPE_BS11: + case GSM_BTS_TYPE_NANOBTS_900: + /* Assume we have a P-GSM900 here */ + if (ARFCN < 1 || ARFCN > 124) { + fprintf(stderr, "GSM900 channel must be between 1-124.\n"); + return -EINVAL; + } + break; + case GSM_BTS_TYPE_UNKNOWN: + fprintf(stderr, "Unknown BTS. Please use the --bts-type switch\n"); + return -EINVAL; + } + /* initialize our data structures */ gsmnet = gsm_network_init(2, BTS_TYPE, MCC, MNC); if (!gsmnet) -- cgit v1.2.3 From 500f3ca19dfe4eba2d20e3a6d68fdb32b93e17a5 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Wed, 10 Jun 2009 10:48:14 +0200 Subject: [o&m] Dispatch a signal for nacked O&M messages When trying to operate a nanoBTS900 on channels for 1800 or the other way around the "SET BTS ATTRIBUTES" message will be nacked. Dispatch all nacked messages from abis_nm via signals. Handle this in bsc_hack.c, print a small hint and exit the application as this is considered a fatal unrecoverable error (the exit is in the app, so a library can be more robust). --- openbsc/include/openbsc/signal.h | 1 + openbsc/src/abis_nm.c | 3 +++ openbsc/src/bsc_hack.c | 14 ++++++++++++++ 3 files changed, 18 insertions(+) (limited to 'openbsc') diff --git a/openbsc/include/openbsc/signal.h b/openbsc/include/openbsc/signal.h index 4a583f689..c065f9003 100644 --- a/openbsc/include/openbsc/signal.h +++ b/openbsc/include/openbsc/signal.h @@ -54,6 +54,7 @@ enum signal_abisip { enum signal_nm { S_NM_SW_ACTIV_REP, /* GSM 12.21 software activated report */ S_NM_FAIL_REP, /* GSM 12.21 failure event report */ + S_NM_NACK, /* GSM 12.21 various NM_MT_*_NACK happened */ }; /* SS_LCHAN signals */ diff --git a/openbsc/src/abis_nm.c b/openbsc/src/abis_nm.c index 74dba2377..83e6bbb48 100644 --- a/openbsc/src/abis_nm.c +++ b/openbsc/src/abis_nm.c @@ -893,6 +893,9 @@ static int abis_nm_rcvmsg_fom(struct msgb *mb) nack_cause_name(*TLVP_VAL(&tp, NM_ATT_NACK_CAUSES))); else DEBUGPC(DNM, "\n"); + + dispatch_signal(SS_NM, S_NM_NACK, (void*) ((long)mt)); + return 0; } #if 0 /* check if last message is to be acked */ diff --git a/openbsc/src/bsc_hack.c b/openbsc/src/bsc_hack.c index 687be33cf..388840793 100644 --- a/openbsc/src/bsc_hack.c +++ b/openbsc/src/bsc_hack.c @@ -454,6 +454,18 @@ static int sw_activ_rep(struct msgb *mb) return 0; } +/* Callback function for NACK on the OML NM */ +static int oml_msg_nack(int mt) +{ + if (mt == NM_MT_SET_BTS_ATTR_NACK) { + fprintf(stderr, "Failed to set BTS attributes. That is fatal. " + "Was the bts type and frequency properly specified?\n"); + exit(-1); + } + + return 0; +} + /* Callback function to be called every time we receive a signal from NM */ static int nm_sig_cb(unsigned int subsys, unsigned int signal, void *handler_data, void *signal_data) @@ -461,6 +473,8 @@ static int nm_sig_cb(unsigned int subsys, unsigned int signal, switch (signal) { case S_NM_SW_ACTIV_REP: return sw_activ_rep(signal_data); + case S_NM_NACK: + return oml_msg_nack((int)signal_data); default: break; } -- cgit v1.2.3 From fdac4cc176892734ad782dccc2dc45a0282298a2 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Wed, 10 Jun 2009 11:46:58 +0200 Subject: [paging] Unbreak breakge when moving things into paging.c By calling _paging_request_stop with NULL for the lchan we have never used the paging complete callback... I didn't spot that when moving the code over and thought it is a great simplification to not call paging_request_stop first and then loop... *sigh* restore the old behaviour. Call the callback first and then free the requests. --- openbsc/src/paging.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'openbsc') diff --git a/openbsc/src/paging.c b/openbsc/src/paging.c index e647b33be..df11da0e6 100644 --- a/openbsc/src/paging.c +++ b/openbsc/src/paging.c @@ -278,6 +278,8 @@ void paging_request_stop(struct gsm_bts *_bts, struct gsm_subscriber *subscr, { struct gsm_bts *bts = NULL; + _paging_request_stop(_bts, subscr, lchan); + do { /* * FIXME: Don't use the lac of the subscriber... @@ -290,7 +292,8 @@ void paging_request_stop(struct gsm_bts *_bts, struct gsm_subscriber *subscr, break; /* Stop paging */ - _paging_request_stop(bts, subscr, NULL); + if (bts != _bts) + _paging_request_stop(bts, subscr, NULL); } while (1); } -- cgit v1.2.3 From 04866d42792f59b334a13e836237947222b41127 Mon Sep 17 00:00:00 2001 From: Holger Freyther Date: Tue, 31 Mar 2009 04:35:19 +0200 Subject: Proposal for a "channel request" interface... Reuqests for a subscriber a stored within the gsm_subscriber datastructure and it will keep track how many channels are allocated for this user and of which type to decide on policy... e.g. attempt to submit SMS during a phone call and not doing paging but a simple (immediate) assignment of the channel... --- openbsc/include/openbsc/gsm_subscriber.h | 6 ++++++ openbsc/include/openbsc/paging.h | 2 +- openbsc/src/gsm_04_08.c | 2 +- openbsc/src/gsm_subscriber.c | 11 +++++++++++ openbsc/src/paging.c | 4 ++-- 5 files changed, 21 insertions(+), 4 deletions(-) (limited to 'openbsc') diff --git a/openbsc/include/openbsc/gsm_subscriber.h b/openbsc/include/openbsc/gsm_subscriber.h index 1ca79e2ae..f787aebd5 100644 --- a/openbsc/include/openbsc/gsm_subscriber.h +++ b/openbsc/include/openbsc/gsm_subscriber.h @@ -31,6 +31,9 @@ struct gsm_subscriber { u_int8_t classmark2[3]; u_int8_t classmark3_len; u_int8_t classmark3[14]; + + /* pending requests */ + struct llist_head requests; }; enum gsm_subscriber_field { @@ -51,6 +54,9 @@ struct gsm_subscriber *subscr_get_by_imsi(const char *imsi); struct gsm_subscriber *subscr_get_by_extension(const char *ext); int subscr_update(struct gsm_subscriber *s, struct gsm_bts *bts, int reason); void subscr_put_channel(struct gsm_lchan *lchan); +void subscr_get_channel(struct gsm_subscriber *subscr, + struct gsm_network *network, int type, + gsm_cbfn *cbfn, void *param); /* internal */ struct gsm_subscriber *subscr_alloc(void); diff --git a/openbsc/include/openbsc/paging.h b/openbsc/include/openbsc/paging.h index de512d1ae..2f17e243e 100644 --- a/openbsc/include/openbsc/paging.h +++ b/openbsc/include/openbsc/paging.h @@ -33,7 +33,7 @@ void paging_init(struct gsm_bts *bts); /* schedule paging request */ -void paging_request(struct gsm_bts *bts, struct gsm_subscriber *subscr, +void paging_request(struct gsm_network *network, struct gsm_subscriber *subscr, int type, gsm_cbfn *cbfn, void *data); /* stop paging requests */ diff --git a/openbsc/src/gsm_04_08.c b/openbsc/src/gsm_04_08.c index 804c15dee..fd4be2fb8 100644 --- a/openbsc/src/gsm_04_08.c +++ b/openbsc/src/gsm_04_08.c @@ -1333,7 +1333,7 @@ static int gsm48_cc_rx_setup(struct msgb *msg) call->called_subscr = called_subscr; /* Start paging subscriber on all BTS in LAC of subscriber */ - paging_request(msg->trx->bts, called_subscr, RSL_CHANNEED_TCH_F, + subscr_get_channel(called_subscr, msg->trx->bts->network, RSL_CHANNEED_TCH_F, setup_trig_pag_evt, call); /* send a CALL PROCEEDING message to the MO */ diff --git a/openbsc/src/gsm_subscriber.c b/openbsc/src/gsm_subscriber.c index 3f608ec30..3a8179335 100644 --- a/openbsc/src/gsm_subscriber.c +++ b/openbsc/src/gsm_subscriber.c @@ -27,6 +27,7 @@ #include #include +#include #include #include @@ -45,6 +46,8 @@ struct gsm_subscriber *subscr_alloc(void) llist_add_tail(&s->entry, &active_subscribers); s->use_count = 1; + INIT_LLIST_HEAD(&s->requests); + return s; } @@ -131,6 +134,13 @@ struct gsm_subscriber *subscr_put(struct gsm_subscriber *subscr) return NULL; } +void subscr_get_channel(struct gsm_subscriber *subscr, + struct gsm_network *network, int type, + gsm_cbfn *cbfn, void *param) +{ + paging_request(network, subscr, type, cbfn, param); +} + void subscr_put_channel(struct gsm_lchan *lchan) { /* @@ -141,3 +151,4 @@ void subscr_put_channel(struct gsm_lchan *lchan) */ put_lchan(lchan); } + diff --git a/openbsc/src/paging.c b/openbsc/src/paging.c index df11da0e6..8f15e1640 100644 --- a/openbsc/src/paging.c +++ b/openbsc/src/paging.c @@ -237,13 +237,13 @@ static void _paging_request(struct gsm_bts *bts, struct gsm_subscriber *subscr, bsc_schedule_timer(&bts_entry->work_timer, 1, 0); } -void paging_request(struct gsm_bts *_bts, struct gsm_subscriber *subscr, +void paging_request(struct gsm_network *network, struct gsm_subscriber *subscr, int type, gsm_cbfn *cbfn, void *data) { struct gsm_bts *bts = NULL; do { - bts = gsm_bts_by_lac(_bts->network, subscr->lac, bts); + bts = gsm_bts_by_lac(network, subscr->lac, bts); if (!bts) break; -- cgit v1.2.3 From 800d29d798af01f3502bb6437e87ed19ce422eb8 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Wed, 10 Jun 2009 12:36:38 +0200 Subject: [channel] Add a test case for the request foo in gsm_subscriber.c This is simulating a successfull request and is causing a segfault. The test is done with a "mock object" in this case a minimalistic paging implementation which is enough to show the crash. Compare that the callback data is supposed to be the same.... --- openbsc/configure.in | 1 + openbsc/tests/Makefile.am | 2 +- openbsc/tests/channel/Makefile.am | 14 +++++++ openbsc/tests/channel/channel_test.c | 72 ++++++++++++++++++++++++++++++++++++ 4 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 openbsc/tests/channel/Makefile.am create mode 100644 openbsc/tests/channel/channel_test.c (limited to 'openbsc') diff --git a/openbsc/configure.in b/openbsc/configure.in index b886e7ac1..94fb15f4d 100644 --- a/openbsc/configure.in +++ b/openbsc/configure.in @@ -45,4 +45,5 @@ AC_OUTPUT( tests/sms/Makefile tests/gsm0408/Makefile tests/db/Makefile + tests/channel/Makefile Makefile) diff --git a/openbsc/tests/Makefile.am b/openbsc/tests/Makefile.am index 2b72c9c11..2d4e81c75 100644 --- a/openbsc/tests/Makefile.am +++ b/openbsc/tests/Makefile.am @@ -1 +1 @@ -SUBDIRS = debug timer sms gsm0408 db +SUBDIRS = debug timer sms gsm0408 db channel diff --git a/openbsc/tests/channel/Makefile.am b/openbsc/tests/channel/Makefile.am new file mode 100644 index 000000000..60defe0a6 --- /dev/null +++ b/openbsc/tests/channel/Makefile.am @@ -0,0 +1,14 @@ +INCLUDES = $(all_includes) -I$(top_srcdir)/include +AM_CFLAGS=-Wall -ggdb3 + +noinst_PROGRAMS = channel_test + +channel_test_SOURCES = channel_test.c \ + $(top_srcdir)/src/db.c \ + $(top_srcdir)/src/gsm_subscriber.c \ + $(top_srcdir)/src/debug.c \ + $(top_srcdir)/src/timer.c \ + $(top_srcdir)/src/select.c \ + $(top_srcdir)/src/gsm_data.c +channel_test_LDADD = -ldl -ldbi + diff --git a/openbsc/tests/channel/channel_test.c b/openbsc/tests/channel/channel_test.c new file mode 100644 index 000000000..1787e358c --- /dev/null +++ b/openbsc/tests/channel/channel_test.c @@ -0,0 +1,72 @@ +/* + * (C) 2009 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 General Public License as published by + * the Free Software Foundation; either version 2 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 General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include + +#include + +#include +#include +#include + +/* our handler */ +static int subscr_cb(unsigned int hook, unsigned int event, struct msgb *msg, void *data, void *param) +{ + assert(hook == 101); + assert(event == 200); + assert(msg == (void*)0x1323L); + assert(data == (void*)0x4242L); + assert(param == (void*)0x2342L); + printf("Reached, didn't crash, test passed\n"); + return 0; +} + +/* mock object for testing, directly invoke the cb... maybe later through the timer */ +void paging_request(struct gsm_bts *bts, struct gsm_subscriber *subscriber, int type, gsm_cbfn *cbfn, void *data) +{ + cbfn(101, 200, (void*)0x1323L, (void*)0x4242L, data); +} + + +int main(int argc, char** argv) +{ + struct gsm_network network; + + printf("Testing the gsm_subscriber chan logic\n"); + + /* Create a dummy network */ + network.bts[0].location_area_code = 23; + network.bts[0].network = &network; + + /* Create a dummy subscriber */ + struct gsm_subscriber *subscr = subscr_alloc(); + subscr->lac = 23; + + /* Ask for a channel... */ + subscr_get_channel(subscr, &network, RSL_CHANNEED_TCH_F, subscr_cb, (void*)0x2342L); + + while (1) { + bsc_select_main(0); + } +} + +void nm_state_event() {} +void input_event() {} + -- cgit v1.2.3 From 85a7b363d97db5c7be45bfb93079e8db46e90a81 Mon Sep 17 00:00:00 2001 From: Holger Freyther Date: Sat, 18 Apr 2009 13:48:55 +0200 Subject: Handle and dispatch paging requests in gsm_subscriber Implement subscr_get_channel and subscr_put_channel to a degree that SMS Submit and phone call scheduled at the same time will deliver both (one after the other). --- openbsc/include/openbsc/gsm_data.h | 1 + openbsc/include/openbsc/gsm_subscriber.h | 1 + openbsc/src/gsm_subscriber.c | 110 ++++++++++++++++++++++++++++++- 3 files changed, 110 insertions(+), 2 deletions(-) (limited to 'openbsc') diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h index e85adf829..1fb80a2f3 100644 --- a/openbsc/include/openbsc/gsm_data.h +++ b/openbsc/include/openbsc/gsm_data.h @@ -25,6 +25,7 @@ enum gsm_hooks { enum gsm_paging_event { GSM_PAGING_SUCCEEDED, GSM_PAGING_EXPIRED, + GSM_PAGING_OOM, }; struct msgb; diff --git a/openbsc/include/openbsc/gsm_subscriber.h b/openbsc/include/openbsc/gsm_subscriber.h index f787aebd5..780d8ede0 100644 --- a/openbsc/include/openbsc/gsm_subscriber.h +++ b/openbsc/include/openbsc/gsm_subscriber.h @@ -33,6 +33,7 @@ struct gsm_subscriber { u_int8_t classmark3[14]; /* pending requests */ + int in_callback; struct llist_head requests; }; diff --git a/openbsc/src/gsm_subscriber.c b/openbsc/src/gsm_subscriber.c index 3a8179335..3062a6bef 100644 --- a/openbsc/src/gsm_subscriber.c +++ b/openbsc/src/gsm_subscriber.c @@ -25,15 +25,77 @@ #include #include #include +#include #include #include #include +#include #include - LLIST_HEAD(active_subscribers); +/* + * Struct for pending channel requests. This is managed in the + * llist_head requests of each subscriber. The reference counting + * should work in such a way that a subscriber with a pending request + * remains in memory. + */ +struct subscr_request { + struct llist_head entry; + + /* back reference */ + struct gsm_subscriber *subscr; + + /* the requested channel type */ + int channel_type; + + /* the bts we have decided to use */ + struct gsm_network *network; + + /* the callback data */ + gsm_cbfn *cbfn; + void *param; +}; + +/* + * We got the channel assigned and can now hand this channel + * over to one of our callbacks. + */ +static int subscr_paging_cb(unsigned int hooknum, unsigned int event, + struct msgb *msg, void *data, void *param) +{ + struct subscr_request *request; + struct gsm_subscriber *subscr = (struct gsm_subscriber *)param; + + assert(!llist_empty(&subscr->requests)); + + /* + * FIXME: What to do with paging requests coming during + * this callback? We must be sure to not start paging when + * we have an active connection to a subscriber and to make + * the subscr_put_channel work as required... + */ + request = (struct subscr_request *)subscr->requests.next; + llist_del(&request->entry); + subscr->in_callback = 1; + request->cbfn(hooknum, event, msg, data, request->param); + subscr->in_callback = 0; + + free(request); + return 0; +} + +static void subscr_send_paging_request(struct gsm_subscriber *subscr) +{ + struct subscr_request *request; + assert(!llist_empty(&subscr->requests)); + + request = (struct subscr_request *)subscr->requests.next; + paging_request(request->network, subscr, request->channel_type, + subscr_paging_cb, subscr); +} + struct gsm_subscriber *subscr_alloc(void) { struct gsm_subscriber *s; @@ -138,7 +200,36 @@ void subscr_get_channel(struct gsm_subscriber *subscr, struct gsm_network *network, int type, gsm_cbfn *cbfn, void *param) { - paging_request(network, subscr, type, cbfn, param); + struct subscr_request *request; + + request = (struct subscr_request *)malloc(sizeof(*request)); + if (!request) { + if (cbfn) + cbfn(GSM_HOOK_RR_PAGING, GSM_PAGING_OOM, + NULL, NULL, param); + return; + } + + memset(request, 0, sizeof(*request)); + request->network = network; + request->subscr = subscr; + request->channel_type = type; + request->cbfn = cbfn; + request->param = param; + + /* + * FIXME: We might be able to assign more than one + * channel, e.g. voice and SMS submit at the same + * time. + */ + if (!subscr->in_callback && llist_empty(&subscr->requests)) { + /* add to the list, send a request */ + llist_add_tail(&request->entry, &subscr->requests); + subscr_send_paging_request(subscr); + } else { + /* this will be picked up later, from subscr_put_channel */ + llist_add_tail(&request->entry, &subscr->requests); + } } void subscr_put_channel(struct gsm_lchan *lchan) @@ -149,6 +240,21 @@ void subscr_put_channel(struct gsm_lchan *lchan) * of the lchan after having asked the next requestee to handle * the channel. */ + /* + * FIXME: is the lchan is of a different type we could still + * issue an immediate assignment for another channel and then + * close this one. + */ + /* + * Currently we will drop the last ref of the lchan which + * will result in a channel release on RSL and we will start + * the paging. This should work most of the time as the MS + * will listen to the paging requests before we timeout + */ + put_lchan(lchan); + + if (lchan->subscr && !llist_empty(&lchan->subscr->requests)) + subscr_send_paging_request(lchan->subscr); } -- cgit v1.2.3 From 20152a35e35e790ae281cd2445b746e338eb669c Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Wed, 10 Jun 2009 14:47:33 +0200 Subject: [pcap] Write incoming packages without the extra mISDN header This patch fixes the PCAP logging. If frames are received from E1 interface, an 8 byte mISDN header (MISDN_HEADER_LEN) is in front of the RSL packet. When frames are transmitted to the E1 interface, the pcap_write_packet function will get a message buffer without the mISDN header in front of the RSL packet. The pcap file was tested and the output is correct. Follow up patches should make use the msgb->l2, make the ipaccess code use the pcap writing too... --- openbsc/src/e1_input.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'openbsc') diff --git a/openbsc/src/e1_input.c b/openbsc/src/e1_input.c index c3c7c7597..034bd9723 100644 --- a/openbsc/src/e1_input.c +++ b/openbsc/src/e1_input.c @@ -140,6 +140,7 @@ static void write_pcap_packet(int direction, int sapi, int tei, int ret; time_t cur_time; struct tm *tm; + int mi_head = (direction==PCAP_INPUT) ? MISDN_HEADER_LEN : 0; struct fake_linux_lapd_header header = { .pkttype = 4, @@ -163,13 +164,15 @@ static void write_pcap_packet(int direction, int sapi, int tei, .ts_usec = 0, .incl_len = msg->len + sizeof(struct fake_linux_lapd_header) + sizeof(struct lapd_header) - - MISDN_HEADER_LEN, + - mi_head, .orig_len = msg->len + sizeof(struct fake_linux_lapd_header) + sizeof(struct lapd_header) - - MISDN_HEADER_LEN, + - mi_head, }; + printf("Packet of: %d\n", direction); + cur_time = time(NULL); tm = localtime(&cur_time); payload_header.ts_sec = mktime(tm); @@ -177,8 +180,8 @@ static void write_pcap_packet(int direction, int sapi, int tei, ret = write(pcap_fd, &payload_header, sizeof(payload_header)); ret = write(pcap_fd, &header, sizeof(header)); ret = write(pcap_fd, &lapd_header, sizeof(lapd_header)); - ret = write(pcap_fd, msg->data + MISDN_HEADER_LEN, - msg->len - MISDN_HEADER_LEN); + ret = write(pcap_fd, msg->data + mi_head, + msg->len - mi_head); } static const char *sign_types[] = { -- cgit v1.2.3