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/.gitignore | 1 + openbsc/include/openbsc/Makefile.am | 1 + openbsc/include/openbsc/bsc_subscriber.h | 43 ++++++++ openbsc/include/openbsc/debug.h | 3 +- openbsc/include/openbsc/gsm_04_08.h | 4 +- openbsc/include/openbsc/gsm_data.h | 12 +++ openbsc/include/openbsc/osmo_bsc_grace.h | 6 +- openbsc/include/openbsc/paging.h | 17 +-- 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 ++- openbsc/tests/channel/Makefile.am | 2 +- openbsc/tests/channel/channel_test.c | 3 +- openbsc/tests/subscr/Makefile.am | 19 ++++ openbsc/tests/subscr/bsc_subscr_test.c | 130 +++++++++++++++++++++++ openbsc/tests/subscr/bsc_subscr_test.err | 17 +++ openbsc/tests/subscr/bsc_subscr_test.ok | 11 ++ openbsc/tests/testsuite.at | 7 ++ 30 files changed, 615 insertions(+), 115 deletions(-) create mode 100644 openbsc/include/openbsc/bsc_subscriber.h create mode 100644 openbsc/src/libbsc/bsc_subscriber.c create mode 100644 openbsc/tests/subscr/bsc_subscr_test.c create mode 100644 openbsc/tests/subscr/bsc_subscr_test.err create mode 100644 openbsc/tests/subscr/bsc_subscr_test.ok diff --git a/openbsc/.gitignore b/openbsc/.gitignore index e3f25cb20..4f8e7e6d6 100644 --- a/openbsc/.gitignore +++ b/openbsc/.gitignore @@ -79,6 +79,7 @@ tests/trau/trau_test tests/mgcp/mgcp_transcoding_test tests/sgsn/sgsn_test tests/subscr/subscr_test +tests/subscr/bsc_subscr_test tests/oap/oap_test tests/gtphub/gtphub_test tests/mm_auth/mm_auth_test diff --git a/openbsc/include/openbsc/Makefile.am b/openbsc/include/openbsc/Makefile.am index 30c1191d7..7ddf323cd 100644 --- a/openbsc/include/openbsc/Makefile.am +++ b/openbsc/include/openbsc/Makefile.am @@ -10,6 +10,7 @@ noinst_HEADERS = \ bsc_nat_callstats.h \ bsc_nat_sccp.h \ bsc_rll.h \ + bsc_subscriber.h \ bss.h \ bts_ipaccess_nanobts_omlattr.h \ chan_alloc.h \ diff --git a/openbsc/include/openbsc/bsc_subscriber.h b/openbsc/include/openbsc/bsc_subscriber.h new file mode 100644 index 000000000..324734f9a --- /dev/null +++ b/openbsc/include/openbsc/bsc_subscriber.h @@ -0,0 +1,43 @@ +/* GSM subscriber details for use in BSC land */ + +#pragma once + +#include + +#include +#include + +struct log_target; + +struct bsc_subscr { + struct llist_head entry; + int use_count; + + char imsi[GSM23003_IMSI_MAX_DIGITS+1]; + uint32_t tmsi; + uint16_t lac; +}; + +const char *bsc_subscr_name(struct bsc_subscr *bsub); + +struct bsc_subscr *bsc_subscr_find_or_create_by_imsi(struct llist_head *list, + const char *imsi); +struct bsc_subscr *bsc_subscr_find_or_create_by_tmsi(struct llist_head *list, + uint32_t tmsi); + +struct bsc_subscr *bsc_subscr_find_by_imsi(struct llist_head *list, + const char *imsi); +struct bsc_subscr *bsc_subscr_find_by_tmsi(struct llist_head *list, + uint32_t tmsi); + +void bsc_subscr_set_imsi(struct bsc_subscr *bsub, const char *imsi); + +struct bsc_subscr *_bsc_subscr_get(struct bsc_subscr *bsub, + const char *file, int line); +struct bsc_subscr *_bsc_subscr_put(struct bsc_subscr *bsub, + const char *file, int line); +#define bsc_subscr_get(bsub) _bsc_subscr_get(bsub, __BASE_FILE__, __LINE__) +#define bsc_subscr_put(bsub) _bsc_subscr_put(bsub, __BASE_FILE__, __LINE__) + +void log_set_filter_bsc_subscr(struct log_target *target, + struct bsc_subscr *bsub); diff --git a/openbsc/include/openbsc/debug.h b/openbsc/include/openbsc/debug.h index 63000201d..74db72397 100644 --- a/openbsc/include/openbsc/debug.h +++ b/openbsc/include/openbsc/debug.h @@ -42,6 +42,7 @@ enum { struct gsm_subscriber; -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); extern const struct log_info log_info; diff --git a/openbsc/include/openbsc/gsm_04_08.h b/openbsc/include/openbsc/gsm_04_08.h index cb632f632..bdf4ed2a6 100644 --- a/openbsc/include/openbsc/gsm_04_08.h +++ b/openbsc/include/openbsc/gsm_04_08.h @@ -15,6 +15,7 @@ struct gsm_trans; struct gsm_subscriber_connection; struct amr_multirate_conf; struct amr_mode; +struct bsc_subscr; #define GSM48_ALLOC_SIZE 2048 #define GSM48_ALLOC_HEADROOM 256 @@ -78,7 +79,8 @@ int decode_bcd_number(char *output, int output_len, const uint8_t *bcd_lv, int send_siemens_mrpci(struct gsm_lchan *lchan, uint8_t *classmark2_lv); int gsm48_extract_mi(uint8_t *classmark2, int length, char *mi_string, uint8_t *mi_type); int gsm48_paging_extract_mi(struct gsm48_pag_resp *pag, int length, char *mi_string, uint8_t *mi_type); -int gsm48_handle_paging_resp(struct gsm_subscriber_connection *conn, struct msgb *msg, struct gsm_subscriber *subscr); +int gsm48_handle_paging_resp(struct gsm_subscriber_connection *conn, + struct msgb *msg, struct bsc_subscr *bsub); int gsm48_lchan_modify(struct gsm_lchan *lchan, uint8_t lchan_mode); int gsm48_rx_rr_modif_ack(struct msgb *msg); diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h index 620b6e4e0..a36083ada 100644 --- a/openbsc/include/openbsc/gsm_data.h +++ b/openbsc/include/openbsc/gsm_data.h @@ -23,6 +23,7 @@ struct mncc_sock_state; struct gsm_subscriber_group; +struct bsc_subscr; #define OBSC_LINKID_CB(__msgb) (__msgb)->cb[3] @@ -119,6 +120,9 @@ struct gsm_subscriber_connection { /* To whom we are allocated at the moment */ struct gsm_subscriber *subscr; + /* libbsc subscriber information */ + struct bsc_subscr *bsub; + /* LU expiration handling */ uint8_t expire_timer_stopped; /* SMS helpers for libmsc */ @@ -391,6 +395,14 @@ struct gsm_network { * BTS|RNC specific timezone overrides for multi-tz networks in * OsmoMSC, this should be tied to the location area code (LAC). */ struct gsm_tz tz; + + /* List of all struct bsc_subscr used in libbsc. This llist_head is + * allocated so that the llist_head pointer itself can serve as a + * talloc context (useful to not have to pass the entire gsm_network + * struct to the bsc_subscr_* API, and for bsc_susbscr unit tests to + * not require gsm_data.h). In an MSC-without-BSC environment, this + * pointer is NULL to indicate absence of a bsc_subscribers list. */ + struct llist_head *bsc_subscribers; }; struct osmo_esme; diff --git a/openbsc/include/openbsc/osmo_bsc_grace.h b/openbsc/include/openbsc/osmo_bsc_grace.h index ea5e4e2ab..5a81cd137 100644 --- a/openbsc/include/openbsc/osmo_bsc_grace.h +++ b/openbsc/include/openbsc/osmo_bsc_grace.h @@ -22,10 +22,14 @@ #define OSMO_BSC_GRACE_H #include +#include struct bsc_msc_data; int bsc_grace_allow_new_connection(struct gsm_network *net, struct gsm_bts *bts); -int bsc_grace_paging_request(struct gsm_subscriber *sub, int type, 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); #endif diff --git a/openbsc/include/openbsc/paging.h b/openbsc/include/openbsc/paging.h index 689ff5173..7dd8500ac 100644 --- a/openbsc/include/openbsc/paging.h +++ b/openbsc/include/openbsc/paging.h @@ -27,7 +27,7 @@ #include #include -#include +#include /** * A pending paging request @@ -36,8 +36,8 @@ struct gsm_paging_request { /* list_head for list of all paging requests */ struct llist_head entry; /* the subscriber which we're paging. Later gsm_paging_request - * should probably become a part of the gsm_subscriber struct? */ - struct gsm_subscriber *subscr; + * should probably become a part of the bsc_subsrc struct? */ + struct bsc_subscr *bsub; /* back-pointer to the BTS on which we are paging */ struct gsm_bts *bts; /* what kind of channel type do we ask the MS to establish */ @@ -55,13 +55,14 @@ struct gsm_paging_request { }; /* schedule paging request */ -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); -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); /* stop paging requests */ -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); @@ -71,6 +72,6 @@ void paging_update_buffer_space(struct gsm_bts *bts, uint16_t); /* pending paging requests */ unsigned int paging_pending_requests_nr(struct gsm_bts *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); #endif 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; } diff --git a/openbsc/tests/channel/Makefile.am b/openbsc/tests/channel/Makefile.am index 5e9583fbf..ca470ace4 100644 --- a/openbsc/tests/channel/Makefile.am +++ b/openbsc/tests/channel/Makefile.am @@ -24,8 +24,8 @@ channel_test_SOURCES = \ $(NULL) channel_test_LDADD = \ - $(top_builddir)/src/libbsc/libbsc.a \ $(top_builddir)/src/libmsc/libmsc.a \ + $(top_builddir)/src/libbsc/libbsc.a \ $(top_builddir)/src/libcommon-cs/libcommon-cs.a \ $(top_builddir)/src/libcommon/libcommon.a \ $(LIBOSMOCORE_LIBS) \ diff --git a/openbsc/tests/channel/channel_test.c b/openbsc/tests/channel/channel_test.c index c69c70139..88293d0a8 100644 --- a/openbsc/tests/channel/channel_test.c +++ b/openbsc/tests/channel/channel_test.c @@ -49,7 +49,7 @@ static int subscr_cb(unsigned int hook, unsigned int event, struct msgb *msg, vo } /* mock object for testing, directly invoke the cb... maybe later through the timer */ -int paging_request(struct gsm_bts *bts, struct gsm_subscriber *subscriber, int type, gsm_cbfn *cbfn, void *data) +int paging_request(struct gsm_bts *bts, struct bsc_subscr *bsub, int type, gsm_cbfn *cbfn, void *data) { s_data = data; s_cbfn = cbfn; @@ -72,6 +72,7 @@ void test_request_chan(void) exit(1); bts = gsm_bts_alloc(network); bts->location_area_code = 23; + s_conn.network = network; /* Create a dummy subscriber */ struct gsm_subscriber *subscr = subscr_alloc(); diff --git a/openbsc/tests/subscr/Makefile.am b/openbsc/tests/subscr/Makefile.am index ad8b20c0c..6342444ff 100644 --- a/openbsc/tests/subscr/Makefile.am +++ b/openbsc/tests/subscr/Makefile.am @@ -19,10 +19,13 @@ AM_LDFLAGS = \ EXTRA_DIST = \ subscr_test.ok \ + bsc_subscr_test.ok \ + bsc_subscr_test.err \ $(NULL) noinst_PROGRAMS = \ subscr_test \ + bsc_subscr_test \ $(NULL) subscr_test_SOURCES = \ @@ -40,3 +43,19 @@ subscr_test_LDADD = \ $(LIBSMPP34_LIBS) \ $(LIBOSMOVTY_LIBS) \ $(NULL) + +bsc_subscr_test_SOURCES = \ + bsc_subscr_test.c \ + $(NULL) + +bsc_subscr_test_LDADD = \ + $(top_builddir)/src/libbsc/libbsc.a \ + $(top_builddir)/src/libcommon-cs/libcommon-cs.a \ + $(top_builddir)/src/libtrau/libtrau.a \ + $(top_builddir)/src/libcommon/libcommon.a \ + $(LIBOSMOCORE_LIBS) \ + $(LIBOSMOABIS_LIBS) \ + $(LIBOSMOGSM_LIBS) \ + $(LIBSMPP34_LIBS) \ + $(LIBOSMOVTY_LIBS) \ + $(NULL) diff --git a/openbsc/tests/subscr/bsc_subscr_test.c b/openbsc/tests/subscr/bsc_subscr_test.c new file mode 100644 index 000000000..60d687d58 --- /dev/null +++ b/openbsc/tests/subscr/bsc_subscr_test.c @@ -0,0 +1,130 @@ +/* (C) 2008 by Jan Luebbe + * (C) 2009 by Holger Hans Peter Freyther + * (C) 2014 by Alexander Chemeris + * 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 . + * + */ + +#include +#include + +#include +#include + +#include +#include +#include +#include + +struct llist_head *bsc_subscribers; + +#define VERBOSE_ASSERT(val, expect_op, fmt) \ + do { \ + printf(#val " == " fmt "\n", (val)); \ + OSMO_ASSERT((val) expect_op); \ + } while (0); + +static void assert_bsc_subscr(const struct bsc_subscr *bsub, const char *imsi) +{ + struct bsc_subscr *sfound; + OSMO_ASSERT(bsub); + OSMO_ASSERT(strcmp(bsub->imsi, imsi) == 0); + + sfound = bsc_subscr_find_by_imsi(bsc_subscribers, imsi); + OSMO_ASSERT(sfound == bsub); + + bsc_subscr_put(sfound); +} + +static void test_bsc_subscr(void) +{ + struct bsc_subscr *s1, *s2, *s3; + const char *imsi1 = "1234567890"; + const char *imsi2 = "9876543210"; + const char *imsi3 = "5656565656"; + + printf("Test BSC subscriber allocation and deletion\n"); + + /* Check for emptiness */ + VERBOSE_ASSERT(llist_count(bsc_subscribers), == 0, "%d"); + OSMO_ASSERT(bsc_subscr_find_by_imsi(bsc_subscribers, imsi1) == NULL); + OSMO_ASSERT(bsc_subscr_find_by_imsi(bsc_subscribers, imsi2) == NULL); + OSMO_ASSERT(bsc_subscr_find_by_imsi(bsc_subscribers, imsi3) == NULL); + + /* Allocate entry 1 */ + s1 = bsc_subscr_find_or_create_by_imsi(bsc_subscribers, imsi1); + VERBOSE_ASSERT(llist_count(bsc_subscribers), == 1, "%d"); + assert_bsc_subscr(s1, imsi1); + VERBOSE_ASSERT(llist_count(bsc_subscribers), == 1, "%d"); + OSMO_ASSERT(bsc_subscr_find_by_imsi(bsc_subscribers, imsi2) == NULL); + + /* Allocate entry 2 */ + s2 = bsc_subscr_find_or_create_by_imsi(bsc_subscribers, imsi2); + VERBOSE_ASSERT(llist_count(bsc_subscribers), == 2, "%d"); + + /* Allocate entry 3 */ + s3 = bsc_subscr_find_or_create_by_imsi(bsc_subscribers, imsi3); + VERBOSE_ASSERT(llist_count(bsc_subscribers), == 3, "%d"); + + /* Check entries */ + assert_bsc_subscr(s1, imsi1); + assert_bsc_subscr(s2, imsi2); + assert_bsc_subscr(s3, imsi3); + + /* Free entry 1 */ + bsc_subscr_put(s1); + s1 = NULL; + VERBOSE_ASSERT(llist_count(bsc_subscribers), == 2, "%d"); + OSMO_ASSERT(bsc_subscr_find_by_imsi(bsc_subscribers, imsi1) == NULL); + + assert_bsc_subscr(s2, imsi2); + assert_bsc_subscr(s3, imsi3); + + /* Free entry 2 */ + bsc_subscr_put(s2); + s2 = NULL; + VERBOSE_ASSERT(llist_count(bsc_subscribers), == 1, "%d"); + OSMO_ASSERT(bsc_subscr_find_by_imsi(bsc_subscribers, imsi1) == NULL); + OSMO_ASSERT(bsc_subscr_find_by_imsi(bsc_subscribers, imsi2) == NULL); + assert_bsc_subscr(s3, imsi3); + + /* Free entry 3 */ + bsc_subscr_put(s3); + s3 = NULL; + VERBOSE_ASSERT(llist_count(bsc_subscribers), == 0, "%d"); + OSMO_ASSERT(bsc_subscr_find_by_imsi(bsc_subscribers, imsi3) == NULL); + + OSMO_ASSERT(llist_empty(bsc_subscribers)); +} + +int main() +{ + printf("Testing BSC subscriber core code.\n"); + osmo_init_logging(&log_info); + log_set_print_filename(osmo_stderr_target, 0); + log_set_print_timestamp(osmo_stderr_target, 0); + log_set_use_color(osmo_stderr_target, 0); + log_set_print_category(osmo_stderr_target, 1); + log_set_category_filter(osmo_stderr_target, DREF, 1, LOGL_DEBUG); + + bsc_subscribers = talloc_zero(NULL, struct llist_head); + INIT_LLIST_HEAD(bsc_subscribers); + + test_bsc_subscr(); + + printf("Done\n"); + return 0; +} diff --git a/openbsc/tests/subscr/bsc_subscr_test.err b/openbsc/tests/subscr/bsc_subscr_test.err new file mode 100644 index 000000000..a66317a36 --- /dev/null +++ b/openbsc/tests/subscr/bsc_subscr_test.err @@ -0,0 +1,17 @@ +DREF BSC subscr IMSI:1234567890 usage increases to: 2 +DREF BSC subscr IMSI:1234567890 usage decreases to: 1 +DREF BSC subscr IMSI:1234567890 usage increases to: 2 +DREF BSC subscr IMSI:1234567890 usage decreases to: 1 +DREF BSC subscr IMSI:9876543210 usage increases to: 2 +DREF BSC subscr IMSI:9876543210 usage decreases to: 1 +DREF BSC subscr IMSI:5656565656 usage increases to: 2 +DREF BSC subscr IMSI:5656565656 usage decreases to: 1 +DREF BSC subscr IMSI:1234567890 usage decreases to: 0 +DREF BSC subscr IMSI:9876543210 usage increases to: 2 +DREF BSC subscr IMSI:9876543210 usage decreases to: 1 +DREF BSC subscr IMSI:5656565656 usage increases to: 2 +DREF BSC subscr IMSI:5656565656 usage decreases to: 1 +DREF BSC subscr IMSI:9876543210 usage decreases to: 0 +DREF BSC subscr IMSI:5656565656 usage increases to: 2 +DREF BSC subscr IMSI:5656565656 usage decreases to: 1 +DREF BSC subscr IMSI:5656565656 usage decreases to: 0 diff --git a/openbsc/tests/subscr/bsc_subscr_test.ok b/openbsc/tests/subscr/bsc_subscr_test.ok new file mode 100644 index 000000000..0f6a8be01 --- /dev/null +++ b/openbsc/tests/subscr/bsc_subscr_test.ok @@ -0,0 +1,11 @@ +Testing BSC subscriber core code. +Test BSC subscriber allocation and deletion +llist_count(bsc_subscribers) == 0 +llist_count(bsc_subscribers) == 1 +llist_count(bsc_subscribers) == 1 +llist_count(bsc_subscribers) == 2 +llist_count(bsc_subscribers) == 3 +llist_count(bsc_subscribers) == 2 +llist_count(bsc_subscribers) == 1 +llist_count(bsc_subscribers) == 0 +Done diff --git a/openbsc/tests/testsuite.at b/openbsc/tests/testsuite.at index 01737a3e7..280aeb2ed 100644 --- a/openbsc/tests/testsuite.at +++ b/openbsc/tests/testsuite.at @@ -13,6 +13,13 @@ cat $abs_srcdir/subscr/subscr_test.ok > expout AT_CHECK([$abs_top_builddir/tests/subscr/subscr_test], [], [expout], [ignore]) AT_CLEANUP +AT_SETUP([bsc_subscr]) +AT_KEYWORDS([bsc_subscr]) +cat $abs_srcdir/subscr/bsc_subscr_test.ok > expout +cat $abs_srcdir/subscr/bsc_subscr_test.err > experr +AT_CHECK([$abs_top_builddir/tests/subscr/bsc_subscr_test], [], [expout], [experr]) +AT_CLEANUP + AT_SETUP([db]) AT_KEYWORDS([db]) cat $abs_srcdir/db/db_test.ok > expout -- cgit v1.2.3