Implement support for paging based on CI (cell identifier).
This builds upon https://gerrit.osmocom.org/#/c/5698/ which implements support for paging by LAI. The ttcn3 test TC_paging_imsi_nochan_ci passes with this code when run in isolation. It does not pass if another paging test (such as TC_paging_imsi_nochan_lai) is executed beforehand. This problem looks similar to the scenario tested in TC_paging_imsi_a_reset. Change-Id: Ic7772e75c3d7fb0df6e17e118bb33b3248352d4d Depends: Ic3c62ff0fccea586794ea4b3c275a0685cc9326e Related: OS#2753
This commit is contained in:
parent
6b103e14ba
commit
090550f5f8
|
@ -30,6 +30,7 @@ int bsc_grace_allow_new_connection(struct gsm_network *net, struct gsm_bts *bts)
|
|||
int bsc_grace_paging_request(enum signal_rf rf_policy,
|
||||
struct bsc_subscr *subscr,
|
||||
int chan_needed,
|
||||
struct bsc_msc_data *msc);
|
||||
struct bsc_msc_data *msc,
|
||||
struct gsm_bts *bts);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -228,11 +228,12 @@ static int bssmap_handle_reset(struct bsc_msc_data *msc,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Page a subscriber based on TMSI and LAC.
|
||||
/* Page a subscriber based on TMSI and LAC in the specified MSC.
|
||||
* If BTS is not NULL, page the subscriber via this particular BTS.
|
||||
* A non-zero return value indicates a fatal out of memory condition. */
|
||||
static int
|
||||
page_subscriber(struct bsc_msc_data *msc, uint32_t tmsi, uint32_t lac,
|
||||
const char *mi_string, uint8_t chan_needed)
|
||||
page_subscriber(struct bsc_msc_data *msc, struct gsm_bts *bts,
|
||||
uint32_t tmsi, uint32_t lac, const char *mi_string, uint8_t chan_needed)
|
||||
{
|
||||
struct bsc_subscr *subscr;
|
||||
|
||||
|
@ -246,9 +247,14 @@ page_subscriber(struct bsc_msc_data *msc, uint32_t tmsi, uint32_t lac,
|
|||
subscr->lac = lac;
|
||||
subscr->tmsi = tmsi;
|
||||
|
||||
if (bts)
|
||||
LOGP(DMSC, LOGL_INFO, "Paging request from MSC BTS: %d IMSI: '%s' TMSI: '0x%x/%u' LAC: 0x%x\n",
|
||||
bts->nr, mi_string, tmsi, tmsi, lac);
|
||||
else
|
||||
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(msc->network->bsc_data->rf_ctrl->policy,
|
||||
subscr, chan_needed, msc);
|
||||
subscr, chan_needed, msc, bts);
|
||||
|
||||
/* the paging code has grabbed its own references */
|
||||
bsc_subscr_put(subscr);
|
||||
|
@ -343,6 +349,29 @@ static int bssmap_handle_paging(struct bsc_msc_data *msc,
|
|||
LOGP(DMSC, LOGL_NOTICE, "Ignoring no-op paging request for IMSI %s\n", mi_string);
|
||||
return 0; /* nothing to do */
|
||||
|
||||
case CELL_IDENT_CI: {
|
||||
uint16_t *ci_be = (uint16_t *)(&data[1]);
|
||||
while (remain >= sizeof(*ci_be)) {
|
||||
uint16_t ci = osmo_load16be(ci_be);
|
||||
struct gsm_bts *bts;
|
||||
|
||||
llist_for_each_entry(bts, &msc->network->bts_list, list) {
|
||||
if (bts->cell_identity == ci)
|
||||
break;
|
||||
}
|
||||
|
||||
if (bts) {
|
||||
if (page_subscriber(msc, bts, tmsi, lac, mi_string, chan_needed) != 0)
|
||||
break;
|
||||
} else
|
||||
LOGP(DMSC, LOGL_ERROR, "Paging IMSI %s: BTS with cell identifier %d not found\n",
|
||||
mi_string, ci);
|
||||
remain -= sizeof(*ci_be);
|
||||
ci_be++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case CELL_IDENT_LAI_AND_LAC: {
|
||||
struct gsm48_loc_area_id lai;
|
||||
int i = 0;
|
||||
|
@ -358,7 +387,7 @@ static int bssmap_handle_paging(struct bsc_msc_data *msc,
|
|||
break;
|
||||
}
|
||||
if (mcc == msc->network->country_code && mnc == msc->network->network_code) {
|
||||
if (page_subscriber(msc, tmsi, lac, mi_string, chan_needed) != 0)
|
||||
if (page_subscriber(msc, NULL, tmsi, lac, mi_string, chan_needed) != 0)
|
||||
break;
|
||||
} else
|
||||
LOGP(DMSC, LOGL_DEBUG, "Not paging IMSI %s: MCC/MNC in Cell Identifier List "
|
||||
|
@ -375,7 +404,7 @@ static int bssmap_handle_paging(struct bsc_msc_data *msc,
|
|||
lacp_be = (uint16_t *)(&data[1]);
|
||||
while (remain >= sizeof(*lacp_be)) {
|
||||
lac = osmo_load16be(lacp_be);
|
||||
if (page_subscriber(msc, tmsi, lac, mi_string, chan_needed) != 0)
|
||||
if (page_subscriber(msc, NULL, tmsi, lac, mi_string, chan_needed) != 0)
|
||||
break;
|
||||
remain -= sizeof(*lacp_be);
|
||||
lacp_be++;
|
||||
|
@ -388,7 +417,7 @@ static int bssmap_handle_paging(struct bsc_msc_data *msc,
|
|||
" has invalid length: %u, paging entire BSS anyway (%s)\n",
|
||||
mi_string, CELL_IDENT_BSS, data_length, osmo_hexdump(data, data_length));
|
||||
}
|
||||
if (page_subscriber(msc, tmsi, GSM_LAC_RESERVED_ALL_BTS, mi_string, chan_needed) != 0)
|
||||
if (page_subscriber(msc, NULL, tmsi, GSM_LAC_RESERVED_ALL_BTS, mi_string, chan_needed) != 0)
|
||||
break;
|
||||
break;
|
||||
|
||||
|
@ -396,7 +425,7 @@ static int bssmap_handle_paging(struct bsc_msc_data *msc,
|
|||
LOGP(DMSC, LOGL_NOTICE, "Paging IMSI %s: unimplemented Cell Identifier List (0x%x),"
|
||||
" paging entire BSS instead (%s)\n",
|
||||
mi_string, cell_ident, osmo_hexdump(data, data_length));
|
||||
if (page_subscriber(msc, tmsi, GSM_LAC_RESERVED_ALL_BTS, mi_string, chan_needed) != 0)
|
||||
if (page_subscriber(msc, NULL, tmsi, GSM_LAC_RESERVED_ALL_BTS, mi_string, chan_needed) != 0)
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -50,44 +50,62 @@ static int normal_paging(struct bsc_subscr *subscr, int chan_needed,
|
|||
return paging_request(msc->network, subscr, chan_needed, msc);
|
||||
}
|
||||
|
||||
static int locked_paging(struct bsc_subscr *subscr, int chan_needed,
|
||||
struct bsc_msc_data *msc)
|
||||
{
|
||||
struct gsm_bts *bts = NULL;
|
||||
|
||||
/*
|
||||
* Check if there is any BTS that is on for the given lac. Start
|
||||
* with NULL and iterate through all bts.
|
||||
*/
|
||||
llist_for_each_entry(bts, &msc->network->bts_list, list) {
|
||||
/*
|
||||
* continue if the BTS is not excluded from the lock
|
||||
*/
|
||||
if (!bts->excl_from_rf_lock)
|
||||
continue;
|
||||
|
||||
/* in case of no lac patching is in place, check the BTS */
|
||||
if (msc->core_lac == -1 && subscr->lac != bts->location_area_code)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* now page on this bts
|
||||
*/
|
||||
paging_request_bts(bts, subscr, chan_needed, msc);
|
||||
};
|
||||
|
||||
/* All bts are either off or in the grace period */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to not page if everything the cell is not on.
|
||||
*/
|
||||
int bsc_grace_paging_request(enum signal_rf rf_policy,
|
||||
/* Return value is like paging_request_bts():
|
||||
* returns 1 on success (one BTS was paged); 0 in case of error (e.g. TRX down) */
|
||||
static int locked_paging_bts(struct gsm_bts *bts,
|
||||
struct bsc_subscr *subscr,
|
||||
int chan_needed,
|
||||
struct bsc_msc_data *msc)
|
||||
{
|
||||
/* Return error if the BTS is not excluded from the lock. */
|
||||
if (!bts->excl_from_rf_lock)
|
||||
return 0;
|
||||
|
||||
/* in case of no lac patching is in place, check the BTS */
|
||||
if (msc->core_lac == -1 && subscr->lac != bts->location_area_code)
|
||||
return 0;
|
||||
|
||||
return paging_request_bts(bts, subscr, chan_needed, msc);
|
||||
}
|
||||
|
||||
static int locked_paging(struct bsc_subscr *subscr, int chan_needed,
|
||||
struct bsc_msc_data *msc)
|
||||
{
|
||||
struct gsm_bts *bts = NULL;
|
||||
int num_pages = 0;
|
||||
|
||||
/*
|
||||
* Check if there is any BTS that is on for the given lac. Start
|
||||
* with NULL and iterate through all bts.
|
||||
* All other bts are either off or in the grace period.
|
||||
*/
|
||||
llist_for_each_entry(bts, &msc->network->bts_list, list)
|
||||
num_pages += locked_paging_bts(bts, subscr, chan_needed, msc);
|
||||
|
||||
return num_pages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Page a subscriber in an MSC.
|
||||
* \param[in] rf_policy if not S_RF_ON, page only BTSs which are not excluded from the RF lock
|
||||
* \param[in] subscr subscriber we want to page
|
||||
* \param[in] chan_needed value of the GSM0808_IE_CHANNEL_NEEDED IE
|
||||
* \param[in] msc MSC which has issued this paging
|
||||
* \param[in] bts if not NULL, page via this particular BTS
|
||||
* \returns number of BTS on which we issued the paging
|
||||
*/
|
||||
int bsc_grace_paging_request(enum signal_rf rf_policy,
|
||||
struct bsc_subscr *subscr,
|
||||
int chan_needed,
|
||||
struct bsc_msc_data *msc,
|
||||
struct gsm_bts *bts)
|
||||
{
|
||||
if (bts) {
|
||||
if (rf_policy == S_RF_ON)
|
||||
return paging_request_bts(bts, subscr, chan_needed, msc);
|
||||
return locked_paging_bts(bts, subscr, chan_needed, msc);
|
||||
}
|
||||
|
||||
if (rf_policy == S_RF_ON)
|
||||
return normal_paging(subscr, chan_needed, msc);
|
||||
return locked_paging(subscr, chan_needed, msc);
|
||||
|
|
Loading…
Reference in New Issue