From 6d804b1a7e375213cb4b3e437c2b9b8c68872164 Mon Sep 17 00:00:00 2001 From: Neels Hofmeyr Date: Sat, 18 Feb 2017 22:20:46 +0100 Subject: add struct bsc_subscr, separating libbsc from gsm_subscriber In a future commit, gsm_subscriber will be replaced by vlr_subscr, and it will not make sense to use vlr_subscr in libbsc. Thus we need a dedicated BSC subscriber: struct bsc_subscr. Add rf_policy arg to bsc_grace_paging_request() because the bsc_subscr will no longer have a backpointer to gsm_network (used to be via subscr->group). Create a separate logging filter for the new BSC subscriber. The implementation of adjusting the filter context is added in libbsc to not introduce bsc_subscr_get/_put() dependencies to libcommon. During Paging Response, fetch a bsc_subscr from the mobile identity, like we do for the gsm_subscriber. It looks like a duplication now, but will make sense for the VLR as well as for future MSC split patches. Naming: it was requested to not name the new struct bsc_sub, because 'sub' is too ambiguous. At the same time it would be fine to have 'bsc_sub_' as function prefix. Instead of struct bsc_subscriber and bsc_sub_ prefix, I decided to match both up as struct bsc_subscr and bsc_subscr_ function prefix. It's fast to type, relatively short, unambiguous, and the naming is consistent. Add bsc_subscr unit test. Related: OS#1592, OS#1594 Change-Id: Ia61cc00e8bb186b976939a4fc8f7cf9ce6aa3d8e --- openbsc/src/libbsc/Makefile.am | 1 + openbsc/src/libbsc/abis_rsl.c | 4 +- openbsc/src/libbsc/bsc_subscriber.c | 168 ++++++++++++++++++++++++++++++ openbsc/src/libbsc/bsc_vty.c | 12 ++- openbsc/src/libbsc/gsm_04_08_utils.c | 20 ++-- openbsc/src/libbsc/paging.c | 88 ++++++++-------- openbsc/src/libcommon-cs/common_cs.c | 3 + openbsc/src/libcommon/debug.c | 12 ++- openbsc/src/libmsc/gsm_04_08.c | 29 +++++- openbsc/src/libmsc/gsm_subscriber.c | 30 +++++- openbsc/src/libmsc/vty_interface_layer3.c | 14 ++- openbsc/src/osmo-bsc/osmo_bsc_bssap.c | 11 +- openbsc/src/osmo-bsc/osmo_bsc_filter.c | 26 ++--- openbsc/src/osmo-bsc/osmo_bsc_grace.c | 21 ++-- openbsc/src/osmo-bsc/osmo_bsc_vty.c | 15 ++- 15 files changed, 352 insertions(+), 102 deletions(-) create mode 100644 openbsc/src/libbsc/bsc_subscriber.c (limited to 'openbsc/src') diff --git a/openbsc/src/libbsc/Makefile.am b/openbsc/src/libbsc/Makefile.am index b8e77e69a..fd8f37a79 100644 --- a/openbsc/src/libbsc/Makefile.am +++ b/openbsc/src/libbsc/Makefile.am @@ -24,6 +24,7 @@ libbsc_a_SOURCES = \ abis_om2000_vty.c \ abis_rsl.c \ bsc_rll.c \ + bsc_subscriber.c \ paging.c \ bts_ericsson_rbs2000.c \ bts_ipaccess_nanobts.c \ diff --git a/openbsc/src/libbsc/abis_rsl.c b/openbsc/src/libbsc/abis_rsl.c index 1cae832a8..5939e75bf 100644 --- a/openbsc/src/libbsc/abis_rsl.c +++ b/openbsc/src/libbsc/abis_rsl.c @@ -1332,10 +1332,10 @@ static void print_meas_rep_uni(struct gsm_meas_rep_unidir *mru, static void print_meas_rep(struct gsm_lchan *lchan, struct gsm_meas_rep *mr) { int i; - char *name = ""; + const char *name = ""; if (lchan && lchan->conn) - name = subscr_name(lchan->conn->subscr); + name = bsc_subscr_name(lchan->conn->bsub); DEBUGP(DMEAS, "[%s] MEASUREMENT RESULT NR=%d ", name, mr->nr); diff --git a/openbsc/src/libbsc/bsc_subscriber.c b/openbsc/src/libbsc/bsc_subscriber.c new file mode 100644 index 000000000..a5e40cdba --- /dev/null +++ b/openbsc/src/libbsc/bsc_subscriber.c @@ -0,0 +1,168 @@ +/* GSM subscriber details for use in BSC land */ + +/* + * (C) 2016 by sysmocom s.f.m.c. GmbH + * + * Author: Neels Hofmeyr + * + * 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 +#include +#include + +#include +#include + +#include +#include + +static struct bsc_subscr *bsc_subscr_alloc(struct llist_head *list) +{ + struct bsc_subscr *bsub; + + bsub = talloc_zero(list, struct bsc_subscr); + if (!bsub) + return NULL; + + llist_add_tail(&bsub->entry, list); + bsub->use_count = 1; + + return bsub; +} + +struct bsc_subscr *bsc_subscr_find_by_imsi(struct llist_head *list, + const char *imsi) +{ + struct bsc_subscr *bsub; + + if (!imsi || !*imsi) + return NULL; + + llist_for_each_entry(bsub, list, entry) { + if (!strcmp(bsub->imsi, imsi)) + return bsc_subscr_get(bsub); + } + return NULL; +} + +struct bsc_subscr *bsc_subscr_find_by_tmsi(struct llist_head *list, + uint32_t tmsi) +{ + struct bsc_subscr *bsub; + + if (tmsi == GSM_RESERVED_TMSI) + return NULL; + + llist_for_each_entry(bsub, list, entry) { + if (bsub->tmsi == tmsi) + return bsc_subscr_get(bsub); + } + return NULL; +} + +void bsc_subscr_set_imsi(struct bsc_subscr *bsub, const char *imsi) +{ + if (!bsub) + return; + strncpy(bsub->imsi, imsi, sizeof(bsub->imsi)); +} + +struct bsc_subscr *bsc_subscr_find_or_create_by_imsi(struct llist_head *list, + const char *imsi) +{ + struct bsc_subscr *bsub; + bsub = bsc_subscr_find_by_imsi(list, imsi); + if (bsub) + return bsub; + bsub = bsc_subscr_alloc(list); + bsc_subscr_set_imsi(bsub, imsi); + return bsub; +} + +struct bsc_subscr *bsc_subscr_find_or_create_by_tmsi(struct llist_head *list, + uint32_t tmsi) +{ + struct bsc_subscr *bsub; + bsub = bsc_subscr_find_by_tmsi(list, tmsi); + if (bsub) + return bsub; + bsub = bsc_subscr_alloc(list); + bsub->tmsi = tmsi; + return bsub; +} + +const char *bsc_subscr_name(struct bsc_subscr *bsub) +{ + static char buf[32]; + if (!bsub) + return "unknown"; + if (bsub->imsi[0]) + snprintf(buf, sizeof(buf), "IMSI:%s", bsub->imsi); + else + snprintf(buf, sizeof(buf), "TMSI:0x%08x", bsub->tmsi); + return buf; +} + +static void bsc_subscr_free(struct bsc_subscr *bsub) +{ + llist_del(&bsub->entry); + talloc_free(bsub); +} + +struct bsc_subscr *_bsc_subscr_get(struct bsc_subscr *bsub, + const char *file, int line) +{ + OSMO_ASSERT(bsub->use_count < INT_MAX); + bsub->use_count++; + LOGPSRC(DREF, LOGL_DEBUG, file, line, + "BSC subscr %s usage increases to: %d\n", + bsc_subscr_name(bsub), bsub->use_count); + return bsub; +} + +struct bsc_subscr *_bsc_subscr_put(struct bsc_subscr *bsub, + const char *file, int line) +{ + bsub->use_count--; + LOGPSRC(DREF, bsub->use_count >= 0? LOGL_DEBUG : LOGL_ERROR, + file, line, + "BSC subscr %s usage decreases to: %d\n", + bsc_subscr_name(bsub), bsub->use_count); + if (bsub->use_count <= 0) + bsc_subscr_free(bsub); + return NULL; +} + +void log_set_filter_bsc_subscr(struct log_target *target, + struct bsc_subscr *bsc_subscr) +{ + struct bsc_subscr **fsub = (void*)&target->filter_data[LOG_FLT_BSC_SUBSCR]; + + /* free the old data */ + if (*fsub) { + bsc_subscr_put(*fsub); + *fsub = NULL; + } + + if (bsc_subscr) { + target->filter_map |= (1 << LOG_FLT_BSC_SUBSCR); + *fsub = bsc_subscr_get(bsc_subscr); + } else + target->filter_map &= ~(1 << LOG_FLT_BSC_SUBSCR); +} diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c index 0a55cf4cf..b1747aa33 100644 --- a/openbsc/src/libbsc/bsc_vty.c +++ b/openbsc/src/libbsc/bsc_vty.c @@ -1023,6 +1023,16 @@ static void subscr_dump_vty(struct vty *vty, struct gsm_subscriber *subscr) vty_out(vty, " Use count: %u%s", subscr->use_count, VTY_NEWLINE); } +static void bsc_subscr_dump_vty(struct vty *vty, struct bsc_subscr *bsub) +{ + if (strlen(bsub->imsi)) + vty_out(vty, " IMSI: %s%s", bsub->imsi, VTY_NEWLINE); + if (bsub->tmsi != GSM_RESERVED_TMSI) + vty_out(vty, " TMSI: 0x%08x%s", bsub->tmsi, + VTY_NEWLINE); + vty_out(vty, " Use count: %d%s", bsub->use_count, VTY_NEWLINE); +} + static void meas_rep_dump_uni_vty(struct vty *vty, struct gsm_meas_rep_unidir *mru, const char *prefix, @@ -1318,7 +1328,7 @@ DEFUN(show_lchan_summary, static void paging_dump_vty(struct vty *vty, struct gsm_paging_request *pag) { vty_out(vty, "Paging on BTS %u%s", pag->bts->nr, VTY_NEWLINE); - subscr_dump_vty(vty, pag->subscr); + bsc_subscr_dump_vty(vty, pag->bsub); } static void bts_paging_dump_vty(struct vty *vty, struct gsm_bts *bts) diff --git a/openbsc/src/libbsc/gsm_04_08_utils.c b/openbsc/src/libbsc/gsm_04_08_utils.c index 98f079078..4a53b31e5 100644 --- a/openbsc/src/libbsc/gsm_04_08_utils.c +++ b/openbsc/src/libbsc/gsm_04_08_utils.c @@ -283,7 +283,7 @@ int gsm48_paging_extract_mi(struct gsm48_pag_resp *resp, int length, } int gsm48_handle_paging_resp(struct gsm_subscriber_connection *conn, - struct msgb *msg, struct gsm_subscriber *subscr) + struct msgb *msg, struct bsc_subscr *bsub) { struct gsm_bts *bts = msg->lchan->ts->trx->bts; struct gsm48_hdr *gh = msgb_l3(msg); @@ -292,22 +292,24 @@ int gsm48_handle_paging_resp(struct gsm_subscriber_connection *conn, if (is_siemens_bts(bts)) send_siemens_mrpci(msg->lchan, classmark2_lv); - if (!conn->subscr) { - conn->subscr = subscr; - } else if (conn->subscr != subscr) { - LOGP(DRR, LOGL_ERROR, "<- Channel already owned by someone else?\n"); - subscr_put(subscr); + if (!conn->bsub) { + conn->bsub = bsub; + } else if (conn->bsub != bsub) { + LOGP(DRR, LOGL_ERROR, + "<- Channel already owned by someone else?\n"); + bsc_subscr_put(bsub); return -EINVAL; } else { DEBUGP(DRR, "<- Channel already owned by us\n"); - subscr_put(subscr); - subscr = conn->subscr; + bsc_subscr_put(bsub); + bsub = conn->bsub; } rate_ctr_inc(&bts->network->bsc_ctrs->ctr[BSC_CTR_PAGING_COMPLETED]); /* Stop paging on the bts we received the paging response */ - paging_request_stop(conn->bts, subscr, conn, msg); + paging_request_stop(&bts->network->bts_list, conn->bts, bsub, conn, + msg); return 0; } diff --git a/openbsc/src/libbsc/paging.c b/openbsc/src/libbsc/paging.c index eb37a33d7..bd23d89de 100644 --- a/openbsc/src/libbsc/paging.c +++ b/openbsc/src/libbsc/paging.c @@ -42,6 +42,7 @@ #include #include +#include #include #include #include @@ -58,11 +59,11 @@ void *tall_paging_ctx; * Kill one paging request update the internal list... */ static void paging_remove_request(struct gsm_bts_paging_state *paging_bts, - struct gsm_paging_request *to_be_deleted) + struct gsm_paging_request *to_be_deleted) { osmo_timer_del(&to_be_deleted->T3113); llist_del(&to_be_deleted->entry); - subscr_put(to_be_deleted->subscr); + bsc_subscr_put(to_be_deleted->bsub); talloc_free(to_be_deleted); } @@ -77,21 +78,21 @@ static void page_ms(struct gsm_paging_request *request) if (!bts->oml_link) return; - log_set_context(LOG_CTX_VLR_SUBSCR, request->subscr); + log_set_context(LOG_CTX_BSC_SUBSCR, request->bsub); LOGP(DPAG, LOGL_INFO, "Going to send paging commands: imsi: %s tmsi: " - "0x%x for ch. type %d (attempt %d)\n", request->subscr->imsi, - request->subscr->tmsi, request->chan_type, request->attempts); + "0x%08x for ch. type %d (attempt %d)\n", request->bsub->imsi, + request->bsub->tmsi, request->chan_type, request->attempts); - if (request->subscr->tmsi == GSM_RESERVED_TMSI) - mi_len = gsm48_generate_mid_from_imsi(mi, request->subscr->imsi); + if (request->bsub->tmsi == GSM_RESERVED_TMSI) + mi_len = gsm48_generate_mid_from_imsi(mi, request->bsub->imsi); else - mi_len = gsm48_generate_mid_from_tmsi(mi, request->subscr->tmsi); + mi_len = gsm48_generate_mid_from_tmsi(mi, request->bsub->tmsi); page_group = gsm0502_calc_paging_group(&bts->si_common.chan_desc, - str_to_imsi(request->subscr->imsi)); + str_to_imsi(request->bsub->imsi)); gsm0808_page(bts, page_group, mi_len, mi, request->chan_type); - log_set_context(LOG_CTX_VLR_SUBSCR, NULL); + log_set_context(LOG_CTX_BSC_SUBSCR, NULL); } static void paging_schedule_if_needed(struct gsm_bts_paging_state *paging_bts) @@ -237,11 +238,12 @@ static void paging_init_if_needed(struct gsm_bts *bts) } static int paging_pending_request(struct gsm_bts_paging_state *bts, - struct gsm_subscriber *subscr) { + struct bsc_subscr *bsub) +{ struct gsm_paging_request *req; llist_for_each_entry(req, &bts->pending_requests, entry) { - if (subscr == req->subscr) + if (bsub == req->bsub) return 1; } @@ -255,10 +257,10 @@ static void paging_T3113_expired(void *data) gsm_cbfn *cbfn; int msg; - log_set_context(LOG_CTX_VLR_SUBSCR, req->subscr); + log_set_context(LOG_CTX_BSC_SUBSCR, req->bsub); LOGP(DPAG, LOGL_INFO, "T3113 expired for request %p (%s)\n", - req, req->subscr->imsi); + req, bsc_subscr_name(req->bsub)); /* must be destroyed before calling cbfn, to prevent double free */ rate_ctr_inc(&req->bts->network->bsc_ctrs->ctr[BSC_CTR_PAGING_EXPIRED]); @@ -277,21 +279,22 @@ static void paging_T3113_expired(void *data) } -static int _paging_request(struct gsm_bts *bts, struct gsm_subscriber *subscr, - int type, gsm_cbfn *cbfn, void *data) +static int _paging_request(struct gsm_bts *bts, struct bsc_subscr *bsub, + int type, gsm_cbfn *cbfn, void *data) { struct gsm_bts_paging_state *bts_entry = &bts->paging; struct gsm_paging_request *req; - if (paging_pending_request(bts_entry, subscr)) { - LOGP(DPAG, LOGL_INFO, "Paging request already pending for %s\n", subscr->imsi); + if (paging_pending_request(bts_entry, bsub)) { + LOGP(DPAG, LOGL_INFO, "Paging request already pending for %s\n", + bsc_subscr_name(bsub)); return -EEXIST; } - LOGP(DPAG, LOGL_DEBUG, "Start paging of subscriber %llu on bts %d.\n", - subscr->id, bts->nr); + LOGP(DPAG, LOGL_DEBUG, "Start paging of subscriber %s on bts %d.\n", + bsc_subscr_name(bsub), bts->nr); req = talloc_zero(tall_paging_ctx, struct gsm_paging_request); - req->subscr = subscr_get(subscr); + req->bsub = bsc_subscr_get(bsub); req->bts = bts; req->chan_type = type; req->cbfn = cbfn; @@ -305,8 +308,8 @@ static int _paging_request(struct gsm_bts *bts, struct gsm_subscriber *subscr, return 0; } -int paging_request_bts(struct gsm_bts *bts, struct gsm_subscriber *subscr, - int type, gsm_cbfn *cbfn, void *data) +int paging_request_bts(struct gsm_bts *bts, struct bsc_subscr *bsub, + int type, gsm_cbfn *cbfn, void *data) { int rc; @@ -317,15 +320,14 @@ int paging_request_bts(struct gsm_bts *bts, struct gsm_subscriber *subscr, /* maybe it is the first time we use it */ paging_init_if_needed(bts); - /* Trigger paging, pass any error to the caller */ - rc = _paging_request(bts, subscr, type, cbfn, data); + rc = _paging_request(bts, bsub, type, cbfn, data); if (rc < 0) return rc; return 1; } -int paging_request(struct gsm_network *network, struct gsm_subscriber *subscr, +int paging_request(struct gsm_network *network, struct bsc_subscr *bsub, int type, gsm_cbfn *cbfn, void *data) { struct gsm_bts *bts = NULL; @@ -337,13 +339,14 @@ int paging_request(struct gsm_network *network, struct gsm_subscriber *subscr, do { int rc; - bts = gsm_bts_by_lac(network, subscr->lac, bts); + bts = gsm_bts_by_lac(network, bsub->lac, bts); if (!bts) break; - rc = paging_request_bts(bts, subscr, type, cbfn, data); + rc = paging_request_bts(bts, bsub, type, cbfn, data); if (rc < 0) { - paging_request_stop(NULL, subscr, NULL, NULL); + paging_request_stop(&network->bts_list, NULL, bsub, + NULL, NULL); return rc; } num_pages += rc; @@ -357,7 +360,7 @@ int paging_request(struct gsm_network *network, struct gsm_subscriber *subscr, /* we consciously ignore the type of the request here */ -static void _paging_request_stop(struct gsm_bts *bts, struct gsm_subscriber *subscr, +static void _paging_request_stop(struct gsm_bts *bts, struct bsc_subscr *bsub, struct gsm_subscriber_connection *conn, struct msgb *msg) { @@ -367,8 +370,8 @@ static void _paging_request_stop(struct gsm_bts *bts, struct gsm_subscriber *sub paging_init_if_needed(bts); llist_for_each_entry_safe(req, req2, &bts_entry->pending_requests, - entry) { - if (req->subscr == subscr) { + entry) { + if (req->bsub == bsub) { gsm_cbfn *cbfn = req->cbfn; void *param = req->cbfn_param; @@ -377,35 +380,36 @@ static void _paging_request_stop(struct gsm_bts *bts, struct gsm_subscriber *sub req = NULL; if (conn && cbfn) { - LOGP(DPAG, LOGL_DEBUG, "Stop paging %s on bts %d, calling cbfn.\n", subscr->imsi, bts->nr); + LOGP(DPAG, LOGL_DEBUG, "Stop paging %s on bts %d, calling cbfn.\n", bsub->imsi, bts->nr); cbfn(GSM_HOOK_RR_PAGING, GSM_PAGING_SUCCEEDED, - msg, conn, param); + msg, conn, param); } else - LOGP(DPAG, LOGL_DEBUG, "Stop paging %s on bts %d silently.\n", subscr->imsi, bts->nr); + LOGP(DPAG, LOGL_DEBUG, "Stop paging %s on bts %d silently.\n", bsub->imsi, bts->nr); break; } } } /* Stop paging on all other bts' */ -void paging_request_stop(struct gsm_bts *_bts, struct gsm_subscriber *subscr, +void paging_request_stop(struct llist_head *bts_list, + struct gsm_bts *_bts, struct bsc_subscr *bsub, struct gsm_subscriber_connection *conn, struct msgb *msg) { struct gsm_bts *bts; - log_set_context(LOG_CTX_VLR_SUBSCR, subscr); + log_set_context(LOG_CTX_BSC_SUBSCR, bsub); /* Stop this first and dispatch the request */ if (_bts) - _paging_request_stop(_bts, subscr, conn, msg); + _paging_request_stop(_bts, bsub, conn, msg); /* Make sure to cancel this everywhere else */ - llist_for_each_entry(bts, &subscr->group->net->bts_list, list) { + llist_for_each_entry(bts, bts_list, list) { /* Sort of an optimization. */ if (bts == _bts) continue; - _paging_request_stop(bts, subscr, NULL, NULL); + _paging_request_stop(bts, bsub, NULL, NULL); } } @@ -434,12 +438,12 @@ unsigned int paging_pending_requests_nr(struct gsm_bts *bts) /** * Find any paging data for the given subscriber at the given BTS. */ -void *paging_get_data(struct gsm_bts *bts, struct gsm_subscriber *subscr) +void *paging_get_data(struct gsm_bts *bts, struct bsc_subscr *bsub) { struct gsm_paging_request *req; llist_for_each_entry(req, &bts->paging.pending_requests, entry) - if (req->subscr == subscr) + if (req->bsub == bsub) return req->cbfn_param; return NULL; diff --git a/openbsc/src/libcommon-cs/common_cs.c b/openbsc/src/libcommon-cs/common_cs.c index 3149580f0..7905802bf 100644 --- a/openbsc/src/libcommon-cs/common_cs.c +++ b/openbsc/src/libcommon-cs/common_cs.c @@ -70,6 +70,9 @@ struct gsm_network *gsm_network_init(void *ctx, INIT_LLIST_HEAD(&net->upqueue); INIT_LLIST_HEAD(&net->subscr_conns); + net->bsc_subscribers = talloc_zero(net, struct llist_head); + INIT_LLIST_HEAD(net->bsc_subscribers); + /* init statistics */ net->msc_ctrs = rate_ctr_group_alloc(net, &msc_ctrg_desc, 0); net->active_calls = osmo_counter_alloc("msc.active_calls"); diff --git a/openbsc/src/libcommon/debug.c b/openbsc/src/libcommon/debug.c index 4d7bfed68..0f8221198 100644 --- a/openbsc/src/libcommon/debug.c +++ b/openbsc/src/libcommon/debug.c @@ -180,6 +180,7 @@ static const struct log_info_cat default_categories[] = { static int filter_fn(const struct log_context *ctx, struct log_target *tar) { const struct gsm_subscriber *subscr = ctx->ctx[LOG_CTX_VLR_SUBSCR]; + const struct bsc_subscr *bsub = ctx->ctx[LOG_CTX_BSC_SUBSCR]; const struct gprs_nsvc *nsvc = ctx->ctx[LOG_CTX_GB_NSVC]; const struct gprs_nsvc *bvc = ctx->ctx[LOG_CTX_GB_BVC]; @@ -187,6 +188,10 @@ static int filter_fn(const struct log_context *ctx, struct log_target *tar) && subscr && subscr == tar->filter_data[LOG_FLT_VLR_SUBSCR]) return 1; + if ((tar->filter_map & (1 << LOG_FLT_BSC_SUBSCR)) != 0 + && bsub && bsub == tar->filter_data[LOG_FLT_BSC_SUBSCR]) + return 1; + /* Filter on the NS Virtual Connection */ if ((tar->filter_map & (1 << LOG_FLT_GB_NSVC)) != 0 && nsvc && (nsvc == tar->filter_data[LOG_FLT_GB_NSVC])) @@ -206,7 +211,8 @@ const struct log_info log_info = { .num_cat = ARRAY_SIZE(default_categories), }; -void log_set_imsi_filter(struct log_target *target, struct gsm_subscriber *subscr) +void log_set_filter_vlr_subscr(struct log_target *target, + struct gsm_subscriber *vlr_subscr) { struct gsm_subscriber **fsub = (void*)&target->filter_data[LOG_FLT_VLR_SUBSCR]; @@ -216,9 +222,9 @@ void log_set_imsi_filter(struct log_target *target, struct gsm_subscriber *subsc *fsub = NULL; } - if (subscr) { + if (vlr_subscr) { target->filter_map |= (1 << LOG_FLT_VLR_SUBSCR); - *fsub = subscr_get(subscr); + *fsub = subscr_get(vlr_subscr); } else target->filter_map &= ~(1 << LOG_FLT_VLR_SUBSCR); } diff --git a/openbsc/src/libmsc/gsm_04_08.c b/openbsc/src/libmsc/gsm_04_08.c index fff902d7a..c910d7192 100644 --- a/openbsc/src/libmsc/gsm_04_08.c +++ b/openbsc/src/libmsc/gsm_04_08.c @@ -1433,6 +1433,8 @@ static int gsm48_rx_rr_pag_resp(struct gsm_subscriber_connection *conn, struct m uint8_t mi_type; char mi_string[GSM48_MI_SIZE]; struct gsm_subscriber *subscr = NULL; + struct bsc_subscr *bsub; + uint32_t tmsi; int rc = 0; resp = (struct gsm48_pag_resp *) &gh->data[0]; @@ -1443,8 +1445,8 @@ static int gsm48_rx_rr_pag_resp(struct gsm_subscriber_connection *conn, struct m switch (mi_type) { case GSM_MI_TYPE_TMSI: - subscr = subscr_get_by_tmsi(conn->network->subscr_group, - tmsi_from_string(mi_string)); + tmsi = tmsi_from_string(mi_string); + subscr = subscr_get_by_tmsi(conn->network->subscr_group, tmsi); break; case GSM_MI_TYPE_IMSI: subscr = subscr_get_by_imsi(conn->network->subscr_group, @@ -1457,6 +1459,19 @@ static int gsm48_rx_rr_pag_resp(struct gsm_subscriber_connection *conn, struct m /* FIXME: request id? close channel? */ return -EINVAL; } + + if (!conn->subscr) { + conn->subscr = subscr; + } else if (conn->subscr != subscr) { + LOGP(DRR, LOGL_ERROR, "<- Channel already owned by someone else?\n"); + subscr_put(subscr); + return -EINVAL; + } else { + DEBUGP(DRR, "<- Channel already owned by us\n"); + subscr_put(subscr); + subscr = conn->subscr; + } + log_set_context(LOG_CTX_VLR_SUBSCR, subscr); DEBUGP(DRR, "<- Channel was requested by %s\n", subscr->name && strlen(subscr->name) ? subscr->name : subscr->imsi); @@ -1465,10 +1480,18 @@ static int gsm48_rx_rr_pag_resp(struct gsm_subscriber_connection *conn, struct m memcpy(subscr->equipment.classmark2, classmark2_lv+1, *classmark2_lv); db_sync_equipment(&subscr->equipment); + /* TODO MSC split -- creating a BSC subscriber directly from MSC data + * structures in RAM. At some point the MSC will send a message to the + * BSC instead. */ + bsub = bsc_subscr_find_or_create_by_imsi(conn->network->bsc_subscribers, + subscr->imsi); + bsub->tmsi = subscr->tmsi; + bsub->lac = subscr->lac; + /* We received a paging */ conn->expire_timer_stopped = 1; - rc = gsm48_handle_paging_resp(conn, msg, subscr); + rc = gsm48_handle_paging_resp(conn, msg, bsub); return rc; } diff --git a/openbsc/src/libmsc/gsm_subscriber.c b/openbsc/src/libmsc/gsm_subscriber.c index 568f1c5d0..1a03cf76e 100644 --- a/openbsc/src/libmsc/gsm_subscriber.c +++ b/openbsc/src/libmsc/gsm_subscriber.c @@ -82,8 +82,11 @@ static int subscr_paging_dispatch(unsigned int hooknum, unsigned int event, struct gsm_subscriber_connection *conn = data; struct gsm_subscriber *subscr = param; struct paging_signal_data sig_data; + struct bsc_subscr *bsub; + struct gsm_network *net; - OSMO_ASSERT(subscr->is_paging); + OSMO_ASSERT(subscr && subscr->is_paging); + net = subscr->group->net; /* * Stop paging on all other BTS. E.g. if this is @@ -91,7 +94,16 @@ static int subscr_paging_dispatch(unsigned int hooknum, unsigned int event, * timeout soon as well. Let's just stop everything * and forget we wanted to page. */ - paging_request_stop(NULL, subscr, NULL, NULL); + + /* TODO MSC split -- creating a BSC subscriber directly from MSC data + * structures in RAM. At some point the MSC will send a message to the + * BSC instead. */ + bsub = bsc_subscr_find_or_create_by_imsi(net->bsc_subscribers, + subscr->imsi); + bsub->tmsi = subscr->tmsi; + bsub->lac = subscr->lac; + paging_request_stop(&net->bts_list, NULL, bsub, NULL, NULL); + bsc_subscr_put(bsub); /* Inform parts of the system we don't know */ sig_data.subscr = subscr; @@ -169,13 +181,23 @@ struct subscr_request *subscr_request_channel(struct gsm_subscriber *subscr, { int rc; struct subscr_request *request; + struct bsc_subscr *bsub; + struct gsm_network *net = subscr->group->net; /* Start paging.. we know it is async so we can do it before */ if (!subscr->is_paging) { LOGP(DMM, LOGL_DEBUG, "Subscriber %s not paged yet.\n", subscr_name(subscr)); - rc = paging_request(subscr->group->net, subscr, channel_type, - subscr_paging_cb, subscr); + /* TODO MSC split -- creating a BSC subscriber directly from + * MSC data structures in RAM. At some point the MSC will send + * a message to the BSC instead. */ + bsub = bsc_subscr_find_or_create_by_imsi(net->bsc_subscribers, + subscr->imsi); + bsub->tmsi = subscr->tmsi; + bsub->lac = subscr->lac; + rc = paging_request(net, bsub, channel_type, subscr_paging_cb, + subscr); + bsc_subscr_put(bsub); if (rc <= 0) { LOGP(DMM, LOGL_ERROR, "Subscriber %s paging failed: %d\n", subscr_name(subscr), rc); diff --git a/openbsc/src/libmsc/vty_interface_layer3.c b/openbsc/src/libmsc/vty_interface_layer3.c index cd5dfb723..1bc9372a6 100644 --- a/openbsc/src/libmsc/vty_interface_layer3.c +++ b/openbsc/src/libmsc/vty_interface_layer3.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -1034,21 +1035,26 @@ DEFUN(logging_fltr_imsi, LOGGING_STR FILTER_STR "Filter log messages by IMSI\n" "IMSI to be used as filter\n") { - struct gsm_subscriber *subscr; + struct gsm_subscriber *vlr_subscr; + struct bsc_subscr *bsc_subscr; struct gsm_network *gsmnet = gsmnet_from_vty(vty); struct log_target *tgt = osmo_log_vty2tgt(vty); + const char *imsi = argv[0]; if (!tgt) return CMD_WARNING; - subscr = subscr_get_by_imsi(gsmnet->subscr_group, argv[0]); - if (!subscr) { + vlr_subscr = subscr_get_by_imsi(gsmnet->subscr_group, imsi); + bsc_subscr = bsc_subscr_find_by_imsi(gsmnet->bsc_subscribers, imsi); + + if (!vlr_subscr && !bsc_subscr) { vty_out(vty, "%%no subscriber with IMSI(%s)%s", argv[0], VTY_NEWLINE); return CMD_WARNING; } - log_set_imsi_filter(tgt, subscr); + log_set_filter_vlr_subscr(tgt, vlr_subscr); + log_set_filter_bsc_subscr(tgt, bsc_subscr); return CMD_SUCCESS; } diff --git a/openbsc/src/osmo-bsc/osmo_bsc_bssap.c b/openbsc/src/osmo-bsc/osmo_bsc_bssap.c index dcfef4079..100f66441 100644 --- a/openbsc/src/osmo-bsc/osmo_bsc_bssap.c +++ b/openbsc/src/osmo-bsc/osmo_bsc_bssap.c @@ -20,9 +20,10 @@ #include #include +#include #include #include -#include +#include #include #include @@ -99,7 +100,7 @@ static int bssmap_handle_reset_ack(struct bsc_msc_data *msc, static int bssmap_handle_paging(struct bsc_msc_data *msc, struct msgb *msg, unsigned int payload_length) { - struct gsm_subscriber *subscr; + struct bsc_subscr *subscr; struct tlv_parsed tp; char mi_string[GSM48_MI_SIZE]; uint32_t tmsi = GSM_RESERVED_TMSI; @@ -157,7 +158,8 @@ static int bssmap_handle_paging(struct bsc_msc_data *msc, LOGP(DMSC, LOGL_ERROR, "eMLPP is not handled\n"); } - subscr = subscr_get_or_create(msc->network->subscr_group, mi_string); + subscr = bsc_subscr_find_or_create_by_imsi(msc->network->bsc_subscribers, + mi_string); if (!subscr) { LOGP(DMSC, LOGL_ERROR, "Failed to allocate a subscriber for %s\n", mi_string); return -1; @@ -167,7 +169,8 @@ static int bssmap_handle_paging(struct bsc_msc_data *msc, subscr->tmsi = tmsi; LOGP(DMSC, LOGL_INFO, "Paging request from MSC IMSI: '%s' TMSI: '0x%x/%u' LAC: 0x%x\n", mi_string, tmsi, tmsi, lac); - bsc_grace_paging_request(subscr, chan_needed, msc); + bsc_grace_paging_request(msc->network->bsc_data->rf_ctrl->policy, + subscr, chan_needed, msc); return 0; } diff --git a/openbsc/src/osmo-bsc/osmo_bsc_filter.c b/openbsc/src/osmo-bsc/osmo_bsc_filter.c index 3443bbed4..2c84b169f 100644 --- a/openbsc/src/osmo-bsc/osmo_bsc_filter.c +++ b/openbsc/src/osmo-bsc/osmo_bsc_filter.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -54,14 +55,14 @@ static void handle_lu_request(struct gsm_subscriber_connection *conn, } /* extract a subscriber from the paging response */ -static struct gsm_subscriber *extract_sub(struct gsm_subscriber_connection *conn, - struct msgb *msg) +static struct bsc_subscr *extract_sub(struct gsm_subscriber_connection *conn, + struct msgb *msg) { uint8_t mi_type; char mi_string[GSM48_MI_SIZE]; struct gsm48_hdr *gh; struct gsm48_pag_resp *resp; - struct gsm_subscriber *subscr; + struct bsc_subscr *subscr; if (msgb_l3len(msg) < sizeof(*gh) + sizeof(*resp)) { LOGP(DMSC, LOGL_ERROR, "PagingResponse too small: %u\n", msgb_l3len(msg)); @@ -78,12 +79,12 @@ static struct gsm_subscriber *extract_sub(struct gsm_subscriber_connection *conn switch (mi_type) { case GSM_MI_TYPE_TMSI: - subscr = subscr_active_by_tmsi(conn->bts->network->subscr_group, - tmsi_from_string(mi_string)); + subscr = bsc_subscr_find_by_tmsi(conn->network->bsc_subscribers, + tmsi_from_string(mi_string)); break; case GSM_MI_TYPE_IMSI: - subscr = subscr_active_by_imsi(conn->bts->network->subscr_group, - mi_string); + subscr = bsc_subscr_find_by_imsi(conn->network->bsc_subscribers, + mi_string); break; default: subscr = NULL; @@ -96,15 +97,16 @@ static struct gsm_subscriber *extract_sub(struct gsm_subscriber_connection *conn /* we will need to stop the paging request */ static int handle_page_resp(struct gsm_subscriber_connection *conn, struct msgb *msg) { - struct gsm_subscriber *subscr = extract_sub(conn, msg); + struct bsc_subscr *subscr = extract_sub(conn, msg); if (!subscr) { LOGP(DMSC, LOGL_ERROR, "Non active subscriber got paged.\n"); return -1; } - paging_request_stop(conn->bts, subscr, conn, msg); - subscr_put(subscr); + paging_request_stop(&conn->network->bts_list, conn->bts, subscr, conn, + msg); + bsc_subscr_put(subscr); return 0; } @@ -130,7 +132,7 @@ struct bsc_msc_data *bsc_find_msc(struct gsm_subscriber_connection *conn, uint8_t mtype; struct osmo_bsc_data *bsc; struct bsc_msc_data *msc, *pag_msc; - struct gsm_subscriber *subscr; + struct bsc_subscr *subscr; int is_emerg = 0; bsc = conn->bts->network->bsc_data; @@ -183,7 +185,7 @@ paging: } pag_msc = paging_get_data(conn->bts, subscr); - subscr_put(subscr); + bsc_subscr_put(subscr); llist_for_each_entry(msc, &bsc->mscs, entry) { if (msc != pag_msc) diff --git a/openbsc/src/osmo-bsc/osmo_bsc_grace.c b/openbsc/src/osmo-bsc/osmo_bsc_grace.c index 5709eeac5..63afa20d0 100644 --- a/openbsc/src/osmo-bsc/osmo_bsc_grace.c +++ b/openbsc/src/osmo-bsc/osmo_bsc_grace.c @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include @@ -34,8 +34,8 @@ int bsc_grace_allow_new_connection(struct gsm_network *network, struct gsm_bts * } -static int normal_paging(struct gsm_subscriber *subscr, int chan_needed, - struct bsc_msc_data *msc) +static int normal_paging(struct bsc_subscr *subscr, int chan_needed, + struct bsc_msc_data *msc) { /* we can't page by lac.. we need to page everything */ if (msc->core_lac != -1) { @@ -47,12 +47,11 @@ static int normal_paging(struct gsm_subscriber *subscr, int chan_needed, return 0; } - return paging_request(subscr->group->net, subscr, chan_needed, NULL, - msc); + return paging_request(msc->network, subscr, chan_needed, NULL, msc); } -static int locked_paging(struct gsm_subscriber *subscr, int chan_needed, - struct bsc_msc_data *msc) +static int locked_paging(struct bsc_subscr *subscr, int chan_needed, + struct bsc_msc_data *msc) { struct gsm_bts *bts = NULL; @@ -84,10 +83,12 @@ static int locked_paging(struct gsm_subscriber *subscr, int chan_needed, /** * Try to not page if everything the cell is not on. */ -int bsc_grace_paging_request(struct gsm_subscriber *subscr, int chan_needed, - struct bsc_msc_data *msc) +int bsc_grace_paging_request(enum signal_rf rf_policy, + struct bsc_subscr *subscr, + int chan_needed, + struct bsc_msc_data *msc) { - if (subscr->group->net->bsc_data->rf_ctrl->policy == S_RF_ON) + if (rf_policy == S_RF_ON) return normal_paging(subscr, chan_needed, msc); return locked_paging(subscr, chan_needed, msc); } diff --git a/openbsc/src/osmo-bsc/osmo_bsc_vty.c b/openbsc/src/osmo-bsc/osmo_bsc_vty.c index d59c51577..2336669e2 100644 --- a/openbsc/src/osmo-bsc/osmo_bsc_vty.c +++ b/openbsc/src/osmo-bsc/osmo_bsc_vty.c @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include @@ -861,20 +861,19 @@ DEFUN(logging_fltr_imsi, LOGGING_STR FILTER_STR "Filter log messages by IMSI\n" "IMSI to be used as filter\n") { - struct gsm_subscriber *subscr; + struct bsc_subscr *bsc_subscr; struct log_target *tgt = osmo_log_vty2tgt(vty); + const char *imsi = argv[0]; - if (!tgt) - return CMD_WARNING; + bsc_subscr = bsc_subscr_find_by_imsi(bsc_gsmnet->bsc_subscribers, imsi); - subscr = subscr_get_or_create(bsc_gsmnet->subscr_group, argv[0]); - if (!subscr) { + if (!bsc_subscr) { vty_out(vty, "%%no subscriber with IMSI(%s)%s", - argv[0], VTY_NEWLINE); + imsi, VTY_NEWLINE); return CMD_WARNING; } - log_set_imsi_filter(tgt, subscr); + log_set_filter_bsc_subscr(tgt, bsc_subscr); return CMD_SUCCESS; } -- cgit v1.2.3