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
This commit is contained in:
parent
abf53d87b6
commit
6d804b1a7e
|
@ -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
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/* GSM subscriber details for use in BSC land */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <osmocom/core/linuxlist.h>
|
||||
#include <osmocom/gsm/protocol/gsm_23_003.h>
|
||||
|
||||
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);
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -22,10 +22,14 @@
|
|||
#define OSMO_BSC_GRACE_H
|
||||
|
||||
#include <openbsc/gsm_data.h>
|
||||
#include <openbsc/signal.h>
|
||||
|
||||
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
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#include <osmocom/core/timer.h>
|
||||
|
||||
#include <openbsc/gsm_data.h>
|
||||
#include <openbsc/gsm_subscriber.h>
|
||||
#include <openbsc/bsc_subscriber.h>
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -0,0 +1,168 @@
|
|||
/* GSM subscriber details for use in BSC land */
|
||||
|
||||
/*
|
||||
* (C) 2016 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
|
||||
*
|
||||
* Author: Neels Hofmeyr <nhofmeyr@sysmocom.de>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <talloc.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <osmocom/gsm/gsm48.h>
|
||||
#include <osmocom/core/logging.h>
|
||||
|
||||
#include <openbsc/bsc_subscriber.h>
|
||||
#include <openbsc/debug.h>
|
||||
|
||||
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);
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include <osmocom/gsm/gsm48.h>
|
||||
#include <osmocom/gsm/gsm0502.h>
|
||||
|
||||
#include <openbsc/bsc_subscriber.h>
|
||||
#include <openbsc/paging.h>
|
||||
#include <openbsc/debug.h>
|
||||
#include <openbsc/signal.h>
|
||||
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include <osmocom/core/linuxlist.h>
|
||||
#include <openbsc/gsm_data.h>
|
||||
#include <openbsc/gsm_subscriber.h>
|
||||
#include <openbsc/bsc_subscriber.h>
|
||||
#include <openbsc/silent_call.h>
|
||||
#include <openbsc/gsm_04_11.h>
|
||||
#include <osmocom/abis/e1_input.h>
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,9 +20,10 @@
|
|||
|
||||
#include <openbsc/osmo_bsc.h>
|
||||
#include <openbsc/osmo_bsc_grace.h>
|
||||
#include <openbsc/osmo_bsc_rf.h>
|
||||
#include <openbsc/bsc_msc_data.h>
|
||||
#include <openbsc/debug.h>
|
||||
#include <openbsc/gsm_subscriber.h>
|
||||
#include <openbsc/bsc_subscriber.h>
|
||||
#include <openbsc/mgcp.h>
|
||||
#include <openbsc/paging.h>
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <openbsc/bsc_msc_data.h>
|
||||
#include <openbsc/gsm_04_80.h>
|
||||
#include <openbsc/gsm_subscriber.h>
|
||||
#include <openbsc/bsc_subscriber.h>
|
||||
#include <openbsc/debug.h>
|
||||
#include <openbsc/paging.h>
|
||||
|
||||
|
@ -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)
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include <openbsc/osmo_bsc_rf.h>
|
||||
#include <openbsc/bsc_msc_data.h>
|
||||
#include <openbsc/gsm_04_80.h>
|
||||
#include <openbsc/gsm_subscriber.h>
|
||||
#include <openbsc/bsc_subscriber.h>
|
||||
#include <openbsc/paging.h>
|
||||
#include <openbsc/signal.h>
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
#include <openbsc/osmo_bsc.h>
|
||||
#include <openbsc/bsc_msc_data.h>
|
||||
#include <openbsc/vty.h>
|
||||
#include <openbsc/gsm_subscriber.h>
|
||||
#include <openbsc/bsc_subscriber.h>
|
||||
#include <openbsc/debug.h>
|
||||
#include <openbsc/bsc_msg_filter.h>
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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) \
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
/* (C) 2008 by Jan Luebbe <jluebbe@debian.org>
|
||||
* (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
|
||||
* (C) 2014 by Alexander Chemeris <Alexander.Chemeris@fairwaves.co>
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <openbsc/debug.h>
|
||||
#include <openbsc/bsc_subscriber.h>
|
||||
|
||||
#include <osmocom/core/application.h>
|
||||
#include <osmocom/core/utils.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
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;
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue