implement support for 3-digit MNC with leading zeros
Add 3-digit flags and use the new RAI and LAI API from libosmocore throughout the code base to be able to handle an MNC < 100 that has three digits (leading zeros). The changes to abis_test and gsm0408_test show that this code now handles 3-digit MNC correctly, by not dropping the leading zero as 0xf in the encoded PLMN. Re-implement CTRL commands 'mcc', 'mnc' and 'mcc-mnc-apply' to preserve the presence of the third digit of the MNC. Always reply with all leading zeros. Adjust the expected results in ctrl_test_runner.py, to show that it works. In VTY and CTRL, the parsing of MCC and MNC is inherently made stricter by use of osmo_{mcc,mnc}_from_str() -- they will no longer allow surplus characters and detect errno returned by strtol() (in contrast to atoi()). Depends: Id2240f7f518494c9df6c8bda52c0d5092f90f221 (libosmocore), Ib7176b1d65a03b76f41f94bc9d3293a8a07d24c6 (libosmocore), I020a4f11791c61742a3d795f782805f7b7e8733e (libosmocore) Change-Id: I8e722103344186fde118b26d8353db95a4581daa
This commit is contained in:
parent
56dec0c753
commit
f93970b167
|
@ -39,6 +39,7 @@
|
|||
#include <osmocom/sigtran/protocol/sua.h>
|
||||
#include <osmocom/sigtran/protocol/m3ua.h>
|
||||
#include <osmocom/core/fsm.h>
|
||||
#include <osmocom/gsm/gsm23003.h>
|
||||
|
||||
#include <regex.h>
|
||||
|
||||
|
@ -78,8 +79,7 @@ struct bsc_msc_data {
|
|||
struct osmo_timer_list pong_timer;
|
||||
int advanced_ping;
|
||||
struct bsc_msc_connection *msc_con;
|
||||
int core_mnc;
|
||||
int core_mcc;
|
||||
struct osmo_plmn_id core_plmn;
|
||||
int core_lac;
|
||||
int core_ci;
|
||||
int rtp_base;
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <osmocom/core/stats.h>
|
||||
#include <osmocom/core/stat_item.h>
|
||||
#include <osmocom/gsm/protocol/gsm_08_08.h>
|
||||
#include <osmocom/gsm/gsm48.h>
|
||||
|
||||
#include <osmocom/crypt/auth.h>
|
||||
|
||||
|
@ -1197,9 +1198,8 @@ struct gsm_network {
|
|||
* these have in common, like country and network code, put in yet
|
||||
* separate structs and placed as members in osmo_bsc and osmo_msc. */
|
||||
|
||||
/* global parameters */
|
||||
uint16_t country_code;
|
||||
uint16_t network_code;
|
||||
struct osmo_plmn_id plmn;
|
||||
|
||||
/* bit-mask of permitted encryption algorithms. LSB=A5/0, MSB=A5/7 */
|
||||
uint8_t a5_encryption_mask;
|
||||
int neci;
|
||||
|
@ -1275,6 +1275,16 @@ struct gsm_network {
|
|||
} mgw;
|
||||
};
|
||||
|
||||
static inline const struct osmo_location_area_id *bts_lai(struct gsm_bts *bts)
|
||||
{
|
||||
static struct osmo_location_area_id lai;
|
||||
lai = (struct osmo_location_area_id){
|
||||
.plmn = bts->network->plmn,
|
||||
.lac = bts->location_area_code,
|
||||
};
|
||||
return &lai;
|
||||
}
|
||||
|
||||
extern void talloc_ctx_init(void *ctx_root);
|
||||
|
||||
int gsm_set_bts_type(struct gsm_bts *bts, enum gsm_bts_type type);
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include <time.h>
|
||||
|
||||
#include <osmocom/ctrl/control_cmd.h>
|
||||
#include <osmocom/gsm/gsm48.h>
|
||||
#include <osmocom/bsc/ipaccess.h>
|
||||
#include <osmocom/bsc/gsm_data.h>
|
||||
#include <osmocom/bsc/abis_nm.h>
|
||||
|
@ -30,8 +31,61 @@
|
|||
#include <osmocom/bsc/osmo_bsc_rf.h>
|
||||
#include <osmocom/bsc/bsc_msc_data.h>
|
||||
|
||||
CTRL_CMD_DEFINE_RANGE(net_mnc, "mnc", struct gsm_network, network_code, 0, 999);
|
||||
CTRL_CMD_DEFINE_RANGE(net_mcc, "mcc", struct gsm_network, country_code, 1, 999);
|
||||
CTRL_CMD_DEFINE(net_mcc, "mcc");
|
||||
static int get_net_mcc(struct ctrl_cmd *cmd, void *_data)
|
||||
{
|
||||
struct gsm_network *net = cmd->node;
|
||||
cmd->reply = talloc_asprintf(cmd, "%s", osmo_mcc_name(net->plmn.mcc));
|
||||
if (!cmd->reply) {
|
||||
cmd->reply = "OOM";
|
||||
return CTRL_CMD_ERROR;
|
||||
}
|
||||
return CTRL_CMD_REPLY;
|
||||
}
|
||||
static int set_net_mcc(struct ctrl_cmd *cmd, void *_data)
|
||||
{
|
||||
struct gsm_network *net = cmd->node;
|
||||
uint16_t mcc;
|
||||
if (osmo_mcc_from_str(cmd->value, &mcc))
|
||||
return -1;
|
||||
net->plmn.mcc = mcc;
|
||||
return get_net_mcc(cmd, _data);
|
||||
}
|
||||
static int verify_net_mcc(struct ctrl_cmd *cmd, const char *value, void *_data)
|
||||
{
|
||||
if (osmo_mcc_from_str(value, NULL))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
CTRL_CMD_DEFINE(net_mnc, "mnc");
|
||||
static int get_net_mnc(struct ctrl_cmd *cmd, void *_data)
|
||||
{
|
||||
struct gsm_network *net = cmd->node;
|
||||
cmd->reply = talloc_asprintf(cmd, "%s", osmo_mnc_name(net->plmn.mnc, net->plmn.mnc_3_digits));
|
||||
if (!cmd->reply) {
|
||||
cmd->reply = "OOM";
|
||||
return CTRL_CMD_ERROR;
|
||||
}
|
||||
return CTRL_CMD_REPLY;
|
||||
}
|
||||
static int set_net_mnc(struct ctrl_cmd *cmd, void *_data)
|
||||
{
|
||||
struct gsm_network *net = cmd->node;
|
||||
struct osmo_plmn_id plmn = net->plmn;
|
||||
if (osmo_mnc_from_str(cmd->value, &plmn.mnc, &plmn.mnc_3_digits)) {
|
||||
cmd->reply = "Error while decoding MNC";
|
||||
return CTRL_CMD_ERROR;
|
||||
}
|
||||
net->plmn = plmn;
|
||||
return get_net_mnc(cmd, _data);
|
||||
}
|
||||
static int verify_net_mnc(struct ctrl_cmd *cmd, const char *value, void *_data)
|
||||
{
|
||||
if (osmo_mnc_from_str(value, NULL, NULL))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_net_apply_config(struct ctrl_cmd *cmd, void *data)
|
||||
{
|
||||
|
@ -64,6 +118,7 @@ CTRL_CMD_DEFINE_WO_NOVRF(net_apply_config, "apply-configuration");
|
|||
static int verify_net_mcc_mnc_apply(struct ctrl_cmd *cmd, const char *value, void *d)
|
||||
{
|
||||
char *tmp, *saveptr, *mcc, *mnc;
|
||||
int rc = 0;
|
||||
|
||||
tmp = talloc_strdup(cmd, value);
|
||||
if (!tmp)
|
||||
|
@ -71,39 +126,45 @@ static int verify_net_mcc_mnc_apply(struct ctrl_cmd *cmd, const char *value, voi
|
|||
|
||||
mcc = strtok_r(tmp, ",", &saveptr);
|
||||
mnc = strtok_r(NULL, ",", &saveptr);
|
||||
talloc_free(tmp);
|
||||
|
||||
if (!mcc || !mnc)
|
||||
return 1;
|
||||
return 0;
|
||||
if (osmo_mcc_from_str(mcc, NULL) || osmo_mnc_from_str(mnc, NULL, NULL))
|
||||
rc = -1;
|
||||
|
||||
talloc_free(tmp);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int set_net_mcc_mnc_apply(struct ctrl_cmd *cmd, void *data)
|
||||
{
|
||||
struct gsm_network *net = cmd->node;
|
||||
char *tmp, *saveptr, *mcc_str, *mnc_str;
|
||||
int mcc, mnc;
|
||||
struct osmo_plmn_id plmn;
|
||||
|
||||
tmp = talloc_strdup(cmd, cmd->value);
|
||||
if (!tmp)
|
||||
goto oom;
|
||||
|
||||
|
||||
mcc_str = strtok_r(tmp, ",", &saveptr);
|
||||
mnc_str = strtok_r(NULL, ",", &saveptr);
|
||||
|
||||
mcc = atoi(mcc_str);
|
||||
mnc = atoi(mnc_str);
|
||||
if (osmo_mcc_from_str(mcc_str, &plmn.mcc)) {
|
||||
cmd->reply = "Error while decoding MCC";
|
||||
return CTRL_CMD_ERROR;
|
||||
}
|
||||
|
||||
if (osmo_mnc_from_str(mnc_str, &plmn.mnc, &plmn.mnc_3_digits)) {
|
||||
cmd->reply = "Error while decoding MNC";
|
||||
return CTRL_CMD_ERROR;
|
||||
}
|
||||
|
||||
talloc_free(tmp);
|
||||
|
||||
if (net->network_code == mnc && net->country_code == mcc) {
|
||||
if (!osmo_plmn_cmp(&net->plmn, &plmn)) {
|
||||
cmd->reply = "Nothing changed";
|
||||
return CTRL_CMD_REPLY;
|
||||
}
|
||||
|
||||
net->network_code = mnc;
|
||||
net->country_code = mcc;
|
||||
net->plmn = plmn;
|
||||
|
||||
return set_net_apply_config(cmd, data);
|
||||
|
||||
|
|
|
@ -326,9 +326,10 @@ static void bootstrap_rsl(struct gsm_bts_trx *trx)
|
|||
unsigned int i;
|
||||
|
||||
LOGP(DRSL, LOGL_NOTICE, "bootstrapping RSL for BTS/TRX (%u/%u) "
|
||||
"on ARFCN %u using MCC=%u MNC=%u LAC=%u CID=%u BSIC=%u\n",
|
||||
trx->bts->nr, trx->nr, trx->arfcn, bsc_gsmnet->country_code,
|
||||
bsc_gsmnet->network_code, trx->bts->location_area_code,
|
||||
"on ARFCN %u using MCC-MNC %s LAC=%u CID=%u BSIC=%u\n",
|
||||
trx->bts->nr, trx->nr, trx->arfcn,
|
||||
osmo_plmn_name(&bsc_gsmnet->plmn),
|
||||
trx->bts->location_area_code,
|
||||
trx->bts->cell_identity, trx->bts->bsic);
|
||||
|
||||
/*
|
||||
|
|
|
@ -203,9 +203,8 @@ static void net_dump_vty(struct vty *vty, struct gsm_network *net)
|
|||
struct pchan_load pl;
|
||||
int i;
|
||||
|
||||
vty_out(vty, "BSC is on Country Code %u, Network Code %u "
|
||||
"and has %u BTS%s", net->country_code, net->network_code,
|
||||
net->num_bts, VTY_NEWLINE);
|
||||
vty_out(vty, "BSC is on MCC-MNC %s and has %u BTS%s",
|
||||
osmo_plmn_name(&net->plmn), net->num_bts, VTY_NEWLINE);
|
||||
vty_out(vty, "%s", VTY_NEWLINE);
|
||||
vty_out(vty, " Encryption:");
|
||||
for (i = 0; i < 8; i++) {
|
||||
|
@ -955,8 +954,9 @@ static int config_write_net(struct vty *vty)
|
|||
int i;
|
||||
|
||||
vty_out(vty, "network%s", VTY_NEWLINE);
|
||||
vty_out(vty, " network country code %u%s", gsmnet->country_code, VTY_NEWLINE);
|
||||
vty_out(vty, " mobile network code %u%s", gsmnet->network_code, VTY_NEWLINE);
|
||||
vty_out(vty, " network country code %s%s", osmo_mcc_name(gsmnet->plmn.mcc), VTY_NEWLINE);
|
||||
vty_out(vty, " mobile network code %s%s",
|
||||
osmo_mnc_name(gsmnet->plmn.mnc, gsmnet->plmn.mnc_3_digits), VTY_NEWLINE);
|
||||
vty_out(vty, " encryption a5");
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (gsmnet->a5_encryption_mask & (1 << i))
|
||||
|
@ -4516,8 +4516,14 @@ DEFUN(cfg_net_ncc,
|
|||
"Network Country Code to use\n")
|
||||
{
|
||||
struct gsm_network *gsmnet = gsmnet_from_vty(vty);
|
||||
uint16_t mcc;
|
||||
|
||||
gsmnet->country_code = atoi(argv[0]);
|
||||
if (osmo_mcc_from_str(argv[0], &mcc)) {
|
||||
vty_out(vty, "%% Error decoding MCC: %s%s", argv[0], VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
gsmnet->plmn.mcc = mcc;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
@ -4531,8 +4537,16 @@ DEFUN(cfg_net_mnc,
|
|||
"Mobile Network Code to use\n")
|
||||
{
|
||||
struct gsm_network *gsmnet = gsmnet_from_vty(vty);
|
||||
uint16_t mnc;
|
||||
bool mnc_3_digits;
|
||||
|
||||
gsmnet->network_code = atoi(argv[0]);
|
||||
if (osmo_mnc_from_str(argv[0], &mnc, &mnc_3_digits)) {
|
||||
vty_out(vty, "%% Error decoding MNC: %s%s", argv[0], VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
|
||||
gsmnet->plmn.mnc = mnc;
|
||||
gsmnet->plmn.mnc_3_digits = mnc_3_digits;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -272,8 +272,9 @@ struct gsm_bts *gsm_bts_alloc_register(struct gsm_network *net, enum gsm_bts_typ
|
|||
void gprs_ra_id_by_bts(struct gprs_ra_id *raid, struct gsm_bts *bts)
|
||||
{
|
||||
*raid = (struct gprs_ra_id){
|
||||
.mcc = bts->network->country_code,
|
||||
.mnc = bts->network->network_code,
|
||||
.mcc = bts->network->plmn.mcc,
|
||||
.mnc = bts->network->plmn.mnc,
|
||||
.mnc_3_digits = bts->network->plmn.mnc_3_digits,
|
||||
.lac = bts->location_area_code,
|
||||
.rac = bts->gprs.rac,
|
||||
};
|
||||
|
|
|
@ -47,8 +47,10 @@ struct gsm_network *bsc_network_init(void *ctx)
|
|||
if (!net)
|
||||
return NULL;
|
||||
|
||||
net->country_code = 1;
|
||||
net->network_code = 1;
|
||||
net->plmn = (struct osmo_plmn_id){
|
||||
.mcc = 1,
|
||||
.mnc = 1,
|
||||
};
|
||||
|
||||
/* Permit a compile-time default of A5/3 and A5/1 */
|
||||
net->a5_encryption_mask = (1 << 3) | (1 << 1);
|
||||
|
|
|
@ -152,8 +152,9 @@ static int pcu_tx_info_ind(struct gsm_bts *bts)
|
|||
info_ind->flags |= PCU_IF_FLAG_SYSMO;
|
||||
|
||||
/* RAI */
|
||||
info_ind->mcc = bts->network->country_code;
|
||||
info_ind->mnc = bts->network->network_code;
|
||||
info_ind->mcc = bts->network->plmn.mcc;
|
||||
info_ind->mnc = bts->network->plmn.mnc;
|
||||
/* TODO: plmn.mnc_3_digits */
|
||||
info_ind->lac = bts->location_area_code;
|
||||
info_ind->rac = bts->gprs.rac;
|
||||
|
||||
|
|
|
@ -860,9 +860,7 @@ static int generate_si3(enum osmo_sysinfo_type t, struct gsm_bts *bts)
|
|||
si3->header.system_information = GSM48_MT_RR_SYSINFO_3;
|
||||
|
||||
si3->cell_identity = htons(bts->cell_identity);
|
||||
gsm48_generate_lai(&si3->lai, bts->network->country_code,
|
||||
bts->network->network_code,
|
||||
bts->location_area_code);
|
||||
gsm48_generate_lai2(&si3->lai, bts_lai(bts));
|
||||
si3->control_channel_desc = bts->si_common.chan_desc;
|
||||
si3->cell_options = bts->si_common.cell_options;
|
||||
si3->cell_sel_par = bts->si_common.cell_sel_par;
|
||||
|
@ -914,9 +912,7 @@ static int generate_si4(enum osmo_sysinfo_type t, struct gsm_bts *bts)
|
|||
si4->header.skip_indicator = 0;
|
||||
si4->header.system_information = GSM48_MT_RR_SYSINFO_4;
|
||||
|
||||
gsm48_generate_lai(&si4->lai, bts->network->country_code,
|
||||
bts->network->network_code,
|
||||
bts->location_area_code);
|
||||
gsm48_generate_lai2(&si4->lai, bts_lai(bts));
|
||||
si4->cell_sel_par = bts->si_common.cell_sel_par;
|
||||
si4->rach_control = bts->si_common.rach_control;
|
||||
if (acc_ramp_is_enabled(&bts->acc_ramp))
|
||||
|
@ -1088,9 +1084,7 @@ static int generate_si6(enum osmo_sysinfo_type t, struct gsm_bts *bts)
|
|||
si6->skip_indicator = 0;
|
||||
si6->system_information = GSM48_MT_RR_SYSINFO_6;
|
||||
si6->cell_identity = htons(bts->cell_identity);
|
||||
gsm48_generate_lai(&si6->lai, bts->network->country_code,
|
||||
bts->network->network_code,
|
||||
bts->location_area_code);
|
||||
gsm48_generate_lai2(&si6->lai, bts_lai(bts));
|
||||
si6->cell_options = bts->si_common.cell_options;
|
||||
si6->ncc_permitted = bts->si_common.ncc_permitted;
|
||||
/* allow/disallow DTXu */
|
||||
|
|
|
@ -54,32 +54,20 @@ static int bsc_clear_request(struct gsm_subscriber_connection *conn, uint32_t ca
|
|||
static int complete_layer3(struct gsm_subscriber_connection *conn,
|
||||
struct msgb *msg, struct bsc_msc_data *msc);
|
||||
|
||||
static uint16_t get_network_code_for_msc(struct bsc_msc_data *msc)
|
||||
static struct osmo_cell_global_id *cgi_for_msc(struct bsc_msc_data *msc, struct gsm_bts *bts)
|
||||
{
|
||||
if (msc->core_mnc != -1)
|
||||
return msc->core_mnc;
|
||||
return msc->network->network_code;
|
||||
}
|
||||
static struct osmo_cell_global_id cgi;
|
||||
cgi.lai.plmn = msc->network->plmn;
|
||||
if (msc->core_plmn.mcc != GSM_MCC_MNC_INVALID)
|
||||
cgi.lai.plmn.mcc = msc->core_plmn.mcc;
|
||||
if (msc->core_plmn.mnc != GSM_MCC_MNC_INVALID) {
|
||||
cgi.lai.plmn.mnc = msc->core_plmn.mnc;
|
||||
cgi.lai.plmn.mnc_3_digits = msc->core_plmn.mnc_3_digits;
|
||||
}
|
||||
cgi.lai.lac = (msc->core_lac != -1) ? msc->core_lac : bts->location_area_code;
|
||||
cgi.cell_identity = (msc->core_ci != -1) ? msc->core_ci : bts->cell_identity;
|
||||
|
||||
static uint16_t get_country_code_for_msc(struct bsc_msc_data *msc)
|
||||
{
|
||||
if (msc->core_mcc != -1)
|
||||
return msc->core_mcc;
|
||||
return msc->network->country_code;
|
||||
}
|
||||
|
||||
static uint16_t get_lac_for_msc(struct bsc_msc_data *msc, struct gsm_bts *bts)
|
||||
{
|
||||
if (msc->core_lac != -1)
|
||||
return msc->core_lac;
|
||||
return bts->location_area_code;
|
||||
}
|
||||
|
||||
static uint16_t get_ci_for_msc(struct bsc_msc_data *msc, struct gsm_bts *bts)
|
||||
{
|
||||
if (msc->core_ci != -1)
|
||||
return msc->core_ci;
|
||||
return bts->cell_identity;
|
||||
return &cgi;
|
||||
}
|
||||
|
||||
static void bsc_maybe_lu_reject(struct gsm_subscriber_connection *conn, int con_type, int cause)
|
||||
|
@ -242,10 +230,6 @@ static int complete_layer3(struct gsm_subscriber_connection *conn,
|
|||
char *imsi = NULL;
|
||||
struct timeval tv;
|
||||
struct msgb *resp;
|
||||
uint16_t network_code;
|
||||
uint16_t country_code;
|
||||
uint16_t lac;
|
||||
uint16_t ci;
|
||||
enum bsc_con ret;
|
||||
int send_ping = msc->advanced_ping;
|
||||
|
||||
|
@ -285,14 +269,9 @@ static int complete_layer3(struct gsm_subscriber_connection *conn,
|
|||
|
||||
/* check return value, if failed check msg for and send USSD */
|
||||
|
||||
network_code = get_network_code_for_msc(conn->sccp.msc);
|
||||
country_code = get_country_code_for_msc(conn->sccp.msc);
|
||||
lac = get_lac_for_msc(conn->sccp.msc, conn_get_bts(conn));
|
||||
ci = get_ci_for_msc(conn->sccp.msc, conn_get_bts(conn));
|
||||
|
||||
bsc_scan_bts_msg(conn, msg);
|
||||
|
||||
resp = gsm0808_create_layer3(msg, network_code, country_code, lac, ci);
|
||||
resp = gsm0808_create_layer3_2(msg, cgi_for_msc(conn->sccp.msc, conn_get_bts(conn)), NULL);
|
||||
if (!resp) {
|
||||
LOGP(DMSC, LOGL_DEBUG, "Failed to create layer3 message.\n");
|
||||
osmo_bsc_sigtran_del_conn(conn);
|
||||
|
|
|
@ -262,15 +262,14 @@ page_subscriber(struct bsc_msc_data *msc, struct gsm_bts *bts,
|
|||
|
||||
/* Decode 5-byte LAI list element data (see TS 08.08 3.2.2.27) into MCC/MNC/LAC.
|
||||
* Return 0 if successful, negative on error. */
|
||||
static int
|
||||
decode_lai(const uint8_t *data, uint16_t *mcc, uint16_t *mnc, uint16_t *lac)
|
||||
static void
|
||||
decode_lai(const uint8_t *data, struct osmo_location_area_id *laid)
|
||||
{
|
||||
struct gsm48_loc_area_id lai;
|
||||
|
||||
/* Copy data to stack to prevent unaligned access in gsm48_decode_lai(). */
|
||||
memcpy(&lai, data, sizeof(lai)); /* don't byte swap yet */
|
||||
|
||||
return gsm48_decode_lai(&lai, mcc, mnc, lac) != 0 ? -1 : 0;
|
||||
gsm48_decode_lai2(&lai, laid);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -290,37 +289,33 @@ page_cgi(struct bsc_msc_data *msc, const uint8_t *data, uint8_t data_length, siz
|
|||
uint16_t ci;
|
||||
int i = 0;
|
||||
while (remain >= sizeof(struct gsm48_loc_area_id) + sizeof(ci)) {
|
||||
uint16_t mcc, mnc, lac, *ci_be;
|
||||
struct osmo_location_area_id lai;
|
||||
uint16_t *ci_be;
|
||||
size_t lai_offset = 1 + i * (sizeof(struct gsm48_loc_area_id) + sizeof(ci));
|
||||
if (decode_lai(&data[lai_offset], &mcc, &mnc, &lac) != 0) {
|
||||
LOGP(DMSC, LOGL_ERROR, "Paging IMSI %s: Invalid LAI in Cell Identifier List "
|
||||
"for BSS (0x%x), paging entire BSS anyway (%s)\n",
|
||||
mi_string, CELL_IDENT_BSS, osmo_hexdump(data, data_length));
|
||||
page_all_bts(msc, tmsi, mi_string, chan_needed);
|
||||
return;
|
||||
}
|
||||
decode_lai(&data[lai_offset], &lai);
|
||||
ci_be = (uint16_t *)(&data[lai_offset + sizeof(struct gsm48_loc_area_id)]);
|
||||
ci = osmo_load16be(ci_be);
|
||||
if (mcc == msc->network->country_code && mnc == msc->network->network_code) {
|
||||
if (!osmo_plmn_cmp(&lai.plmn, &msc->network->plmn)) {
|
||||
int paged = 0;
|
||||
struct gsm_bts *bts;
|
||||
llist_for_each_entry(bts, &msc->network->bts_list, list) {
|
||||
if (bts->location_area_code != lac)
|
||||
if (bts->location_area_code != lai.lac)
|
||||
continue;
|
||||
if (bts->cell_identity != ci)
|
||||
continue;
|
||||
/* ignore errors from page_subscriber(); keep trying other BTS */
|
||||
page_subscriber(msc, bts, tmsi, lac, mi_string, chan_needed);
|
||||
page_subscriber(msc, bts, tmsi, lai.lac, mi_string, chan_needed);
|
||||
paged = 1;
|
||||
}
|
||||
if (!paged) {
|
||||
LOGP(DMSC, LOGL_NOTICE, "Paging IMSI %s: BTS with LAC %d and CI %d not found\n",
|
||||
mi_string, lac, ci);
|
||||
mi_string, lai.lac, ci);
|
||||
}
|
||||
} else {
|
||||
LOGP(DMSC, LOGL_DEBUG, "Paging IMSI %s: MCC/MNC in Cell Identifier List "
|
||||
"(%d/%d) do not match our network (%d/%d)\n", mi_string, mcc, mnc,
|
||||
msc->network->country_code, msc->network->network_code);
|
||||
LOGP(DMSC, LOGL_DEBUG, "Paging IMSI %s: MCC-MNC in Cell Identifier List "
|
||||
"(%s) do not match our network (%s)\n",
|
||||
mi_string, osmo_plmn_name(&lai.plmn),
|
||||
osmo_plmn_name2(&msc->network->plmn));
|
||||
}
|
||||
remain -= sizeof(struct gsm48_loc_area_id) + sizeof(ci);
|
||||
i++;
|
||||
|
@ -389,32 +384,27 @@ page_lai_and_lac(struct bsc_msc_data *msc, const uint8_t *data, size_t data_leng
|
|||
{
|
||||
int i = 0;
|
||||
while (remain >= sizeof(struct gsm48_loc_area_id)) {
|
||||
uint16_t mcc, mnc, lac;
|
||||
if (decode_lai(&data[1 + i * sizeof(struct gsm48_loc_area_id)], &mcc, &mnc, &lac) != 0) {
|
||||
LOGP(DMSC, LOGL_ERROR, "Paging IMSI %s: Invalid LAI in Cell Identifier List "
|
||||
"for BSS (0x%x), paging entire BSS anyway (%s)\n",
|
||||
mi_string, CELL_IDENT_BSS, osmo_hexdump(data, data_length));
|
||||
page_all_bts(msc, tmsi, mi_string, chan_needed);
|
||||
return;
|
||||
}
|
||||
if (mcc == msc->network->country_code && mnc == msc->network->network_code) {
|
||||
struct osmo_location_area_id lai;
|
||||
decode_lai(&data[1 + i * sizeof(struct gsm48_loc_area_id)], &lai);
|
||||
if (!osmo_plmn_cmp(&lai.plmn, &msc->network->plmn)) {
|
||||
int paged = 0;
|
||||
struct gsm_bts *bts;
|
||||
llist_for_each_entry(bts, &msc->network->bts_list, list) {
|
||||
if (bts->location_area_code != lac)
|
||||
if (bts->location_area_code != lai.lac)
|
||||
continue;
|
||||
/* ignore errors from page_subscriber(); keep trying other BTS */
|
||||
page_subscriber(msc, bts, tmsi, lac, mi_string, chan_needed);
|
||||
page_subscriber(msc, bts, tmsi, lai.lac, mi_string, chan_needed);
|
||||
paged = 1;
|
||||
}
|
||||
if (!paged) {
|
||||
LOGP(DMSC, LOGL_NOTICE, "Paging IMSI %s: BTS with LAC %d not found\n",
|
||||
mi_string, lac);
|
||||
mi_string, lai.lac);
|
||||
}
|
||||
} else {
|
||||
LOGP(DMSC, LOGL_DEBUG, "Paging IMSI %s: MCC/MNC in Cell Identifier List "
|
||||
"(%d/%d) do not match our network (%d/%d)\n", mi_string, mcc, mnc,
|
||||
msc->network->country_code, msc->network->network_code);
|
||||
LOGP(DMSC, LOGL_DEBUG, "Paging IMSI %s: MCC-MNC in Cell Identifier List "
|
||||
"(%s) do not match our network (%s)\n",
|
||||
mi_string, osmo_plmn_name(&lai.plmn),
|
||||
osmo_plmn_name2(&msc->network->plmn));
|
||||
}
|
||||
remain -= sizeof(struct gsm48_loc_area_id);
|
||||
i++;
|
||||
|
|
|
@ -207,10 +207,11 @@ static void generate_location_state_trap(struct gsm_bts *bts, struct bsc_msc_con
|
|||
policy = osmo_bsc_rf_get_policy_name(osmo_bsc_rf_get_policy_by_bts(bts));
|
||||
|
||||
cmd->reply = talloc_asprintf_append(cmd->reply,
|
||||
",%s,%s,%s,%d,%d",
|
||||
",%s,%s,%s,%s,%s",
|
||||
oper, admin, policy,
|
||||
bts->network->country_code,
|
||||
bts->network->network_code);
|
||||
osmo_mcc_name(bts->network->plmn.mcc),
|
||||
osmo_mnc_name(bts->network->plmn.mnc,
|
||||
bts->network->plmn.mnc_3_digits));
|
||||
|
||||
osmo_bsc_send_trap(cmd, msc_con);
|
||||
talloc_free(cmd);
|
||||
|
|
|
@ -36,21 +36,16 @@ static void handle_lu_request(struct gsm_subscriber_connection *conn,
|
|||
struct gsm48_hdr *gh;
|
||||
struct gsm48_loc_upd_req *lu;
|
||||
struct gsm48_loc_area_id lai;
|
||||
struct gsm_network *net;
|
||||
struct gsm_bts *bts = conn_get_bts(conn);
|
||||
|
||||
if (msgb_l3len(msg) < sizeof(*gh) + sizeof(*lu)) {
|
||||
LOGP(DMSC, LOGL_ERROR, "LU too small to look at: %u\n", msgb_l3len(msg));
|
||||
return;
|
||||
}
|
||||
|
||||
net = bts->network;
|
||||
|
||||
gh = msgb_l3(msg);
|
||||
lu = (struct gsm48_loc_upd_req *) gh->data;
|
||||
|
||||
gsm48_generate_lai(&lai, net->country_code, net->network_code,
|
||||
bts->location_area_code);
|
||||
gsm48_generate_lai2(&lai, bts_lai(conn_get_bts(conn)));
|
||||
|
||||
if (memcmp(&lai, &lu->lai, sizeof(lai)) != 0) {
|
||||
LOGP(DMSC, LOGL_DEBUG, "Marking con for welcome USSD.\n");
|
||||
|
@ -315,9 +310,9 @@ static int bsc_patch_mm_info(struct gsm_subscriber_connection *conn,
|
|||
|
||||
static int has_core_identity(struct bsc_msc_data *msc)
|
||||
{
|
||||
if (msc->core_mnc != -1)
|
||||
if (msc->core_plmn.mnc != GSM_MCC_MNC_INVALID)
|
||||
return 1;
|
||||
if (msc->core_mcc != -1)
|
||||
if (msc->core_plmn.mcc != GSM_MCC_MNC_INVALID)
|
||||
return 1;
|
||||
if (msc->core_lac != -1)
|
||||
return 1;
|
||||
|
@ -332,8 +327,6 @@ static int has_core_identity(struct bsc_msc_data *msc)
|
|||
int bsc_scan_msc_msg(struct gsm_subscriber_connection *conn, struct msgb *msg)
|
||||
{
|
||||
struct bsc_msc_data *msc;
|
||||
struct gsm_bts *bts = conn_get_bts(conn);
|
||||
struct gsm_network *net;
|
||||
struct gsm48_loc_area_id *lai;
|
||||
struct gsm48_hdr *gh;
|
||||
uint8_t pdisc;
|
||||
|
@ -353,7 +346,6 @@ int bsc_scan_msc_msg(struct gsm_subscriber_connection *conn, struct msgb *msg)
|
|||
return 0;
|
||||
|
||||
mtype = gsm48_hdr_msg_type(gh);
|
||||
net = bts->network;
|
||||
msc = conn->sccp.msc;
|
||||
|
||||
if (mtype == GSM48_MT_MM_LOC_UPD_ACCEPT) {
|
||||
|
@ -361,9 +353,7 @@ int bsc_scan_msc_msg(struct gsm_subscriber_connection *conn, struct msgb *msg)
|
|||
if (msgb_l3len(msg) >= sizeof(*gh) + sizeof(*lai)) {
|
||||
/* overwrite LAI in the message */
|
||||
lai = (struct gsm48_loc_area_id *) &gh->data[0];
|
||||
gsm48_generate_lai(lai, net->country_code,
|
||||
net->network_code,
|
||||
bts->location_area_code);
|
||||
gsm48_generate_lai2(lai, bts_lai(conn_get_bts(conn)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -581,8 +581,10 @@ struct bsc_msc_data *osmo_msc_data_alloc(struct gsm_network *net, int nr)
|
|||
INIT_LLIST_HEAD(&msc_data->dests);
|
||||
msc_data->ping_timeout = 20;
|
||||
msc_data->pong_timeout = 5;
|
||||
msc_data->core_mnc = -1;
|
||||
msc_data->core_mcc = -1;
|
||||
msc_data->core_plmn = (struct osmo_plmn_id){
|
||||
.mcc = GSM_MCC_MNC_INVALID,
|
||||
.mnc = GSM_MCC_MNC_INVALID,
|
||||
};
|
||||
msc_data->core_ci = -1;
|
||||
msc_data->core_lac = -1;
|
||||
msc_data->rtp_base = 4000;
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <osmocom/bsc/bsc_msg_filter.h>
|
||||
|
||||
#include <osmocom/core/talloc.h>
|
||||
#include <osmocom/gsm/gsm48.h>
|
||||
#include <osmocom/vty/logging.h>
|
||||
#include <osmocom/mgcp_client/mgcp_client.h>
|
||||
|
||||
|
@ -107,12 +108,12 @@ static void write_msc(struct vty *vty, struct bsc_msc_data *msc)
|
|||
struct bsc_msc_dest *dest;
|
||||
|
||||
vty_out(vty, "msc %d%s", msc->nr, VTY_NEWLINE);
|
||||
if (msc->core_mnc != -1)
|
||||
vty_out(vty, " core-mobile-network-code %d%s",
|
||||
msc->core_mnc, VTY_NEWLINE);
|
||||
if (msc->core_mcc != -1)
|
||||
vty_out(vty, " core-mobile-country-code %d%s",
|
||||
msc->core_mcc, VTY_NEWLINE);
|
||||
if (msc->core_plmn.mnc != GSM_MCC_MNC_INVALID)
|
||||
vty_out(vty, " core-mobile-network-code %s%s",
|
||||
osmo_mnc_name(msc->core_plmn.mnc, msc->core_plmn.mnc_3_digits), VTY_NEWLINE);
|
||||
if (msc->core_plmn.mcc != GSM_MCC_MNC_INVALID)
|
||||
vty_out(vty, " core-mobile-country-code %s%s",
|
||||
osmo_mcc_name(msc->core_plmn.mcc), VTY_NEWLINE);
|
||||
if (msc->core_lac != -1)
|
||||
vty_out(vty, " core-location-area-code %d%s",
|
||||
msc->core_lac, VTY_NEWLINE);
|
||||
|
@ -236,7 +237,15 @@ DEFUN(cfg_net_bsc_ncc,
|
|||
"Use this network code for the core network\n" "MNC value\n")
|
||||
{
|
||||
struct bsc_msc_data *data = bsc_msc_data(vty);
|
||||
data->core_mnc = atoi(argv[0]);
|
||||
uint16_t mnc;
|
||||
bool mnc_3_digits;
|
||||
|
||||
if (osmo_mnc_from_str(argv[0], &mnc, &mnc_3_digits)) {
|
||||
vty_out(vty, "%% Error decoding MNC: %s%s", argv[0], VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
data->core_plmn.mnc = mnc;
|
||||
data->core_plmn.mnc_3_digits = mnc_3_digits;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -245,8 +254,13 @@ DEFUN(cfg_net_bsc_mcc,
|
|||
"core-mobile-country-code <1-999>",
|
||||
"Use this country code for the core network\n" "MCC value\n")
|
||||
{
|
||||
uint16_t mcc;
|
||||
struct bsc_msc_data *data = bsc_msc_data(vty);
|
||||
data->core_mcc = atoi(argv[0]);
|
||||
if (osmo_mcc_from_str(argv[0], &mcc)) {
|
||||
vty_out(vty, "%% Error decoding MCC: %s%s", argv[0], VTY_NEWLINE);
|
||||
return CMD_WARNING;
|
||||
}
|
||||
data->core_plmn.mcc = mcc;
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -101,8 +101,7 @@ static const struct test_abis_nm_ipaccess_cgi test_abis_nm_ipaccess_cgi_data[] =
|
|||
.plmn = { .mcc = 1, .mnc = 2, .mnc_3_digits = true },
|
||||
.lac = 3,
|
||||
.cell_identity = 4,
|
||||
.expect = "00f120" /* FAIL: should be "002100" */
|
||||
"0003" "0004",
|
||||
.expect = "002100" "0003" "0004",
|
||||
},
|
||||
{
|
||||
.plmn = { .mcc = 0, .mnc = 0, .mnc_3_digits = false },
|
||||
|
@ -114,8 +113,7 @@ static const struct test_abis_nm_ipaccess_cgi test_abis_nm_ipaccess_cgi_data[] =
|
|||
.plmn = { .mcc = 0, .mnc = 0, .mnc_3_digits = true },
|
||||
.lac = 0,
|
||||
.cell_identity = 0,
|
||||
.expect = "00f000" /* FAIL: should be "000000" */
|
||||
"0000" "0000",
|
||||
.expect = "000000" "0000" "0000",
|
||||
},
|
||||
{
|
||||
.plmn = { .mcc = 999, .mnc = 999, .mnc_3_digits = false },
|
||||
|
@ -133,8 +131,7 @@ static const struct test_abis_nm_ipaccess_cgi test_abis_nm_ipaccess_cgi_data[] =
|
|||
.plmn = { .mcc = 909, .mnc = 90, .mnc_3_digits = true },
|
||||
.lac = 0xabcd,
|
||||
.cell_identity = 0x2345,
|
||||
.expect = "09f909" /* FAIL: should be "090990" */
|
||||
"abcd" "2345",
|
||||
.expect = "090990" "abcd" "2345",
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -151,8 +148,7 @@ static void test_abis_nm_ipaccess_cgi()
|
|||
char *result;
|
||||
bool ok;
|
||||
|
||||
net.country_code = t->plmn.mcc;
|
||||
net.network_code = t->plmn.mnc;
|
||||
net.plmn = t->plmn;
|
||||
bts.network = &net;
|
||||
bts.location_area_code = t->lac;
|
||||
bts.cell_identity = t->cell_identity;
|
||||
|
|
|
@ -8,9 +8,9 @@ SELECTED: 1
|
|||
SELECTED: 0
|
||||
test_sw_selection(): OK
|
||||
test_abis_nm_ipaccess_cgi[0]: result=00f12000030004 pass
|
||||
test_abis_nm_ipaccess_cgi[1]: result=00f12000030004 pass
|
||||
test_abis_nm_ipaccess_cgi[1]: result=00210000030004 pass
|
||||
test_abis_nm_ipaccess_cgi[2]: result=00f00000000000 pass
|
||||
test_abis_nm_ipaccess_cgi[3]: result=00f00000000000 pass
|
||||
test_abis_nm_ipaccess_cgi[3]: result=00000000000000 pass
|
||||
test_abis_nm_ipaccess_cgi[4]: result=999999ffffffff pass
|
||||
test_abis_nm_ipaccess_cgi[5]: result=09f909abcd2345 pass
|
||||
test_abis_nm_ipaccess_cgi[6]: result=09f909abcd2345 pass
|
||||
test_abis_nm_ipaccess_cgi[6]: result=090990abcd2345 pass
|
||||
|
|
|
@ -16,7 +16,7 @@ bsc_handle_udt() returned 0
|
|||
2:
|
||||
DMSC Rx MSC UDT: 00 19 52 08 08 59 51 20 69 00 07 43 94 09 04 01 08 44 60 1a 06 04 15 f5 49 00 65
|
||||
DMSC Rx MSC UDT BSSMAP PAGING
|
||||
DMSC Paging IMSI 515029600703449: MCC/MNC in Cell Identifier List (515/94) do not match our network (1/1)
|
||||
DMSC Paging IMSI 515029600703449: MCC-MNC in Cell Identifier List (515-94) do not match our network (001-01)
|
||||
bsc_handle_udt() returned 0
|
||||
|
||||
3:
|
||||
|
|
|
@ -371,32 +371,32 @@ class TestCtrlBSC(TestCtrlBase):
|
|||
r = self.do_get('mcc')
|
||||
self.assertEquals(r['mtype'], 'GET_REPLY')
|
||||
self.assertEquals(r['var'], 'mcc')
|
||||
self.assertEquals(r['value'], '23')
|
||||
self.assertEquals(r['value'], '023')
|
||||
|
||||
r = self.do_set('mcc', '023')
|
||||
r = self.do_get('mcc')
|
||||
self.assertEquals(r['mtype'], 'GET_REPLY')
|
||||
self.assertEquals(r['var'], 'mcc')
|
||||
self.assertEquals(r['value'], '23')
|
||||
self.assertEquals(r['value'], '023')
|
||||
|
||||
def testMnc(self):
|
||||
r = self.do_set('mnc', '9')
|
||||
r = self.do_get('mnc')
|
||||
self.assertEquals(r['mtype'], 'GET_REPLY')
|
||||
self.assertEquals(r['var'], 'mnc')
|
||||
self.assertEquals(r['value'], '9')
|
||||
self.assertEquals(r['value'], '09')
|
||||
|
||||
r = self.do_set('mnc', '09')
|
||||
r = self.do_get('mnc')
|
||||
self.assertEquals(r['mtype'], 'GET_REPLY')
|
||||
self.assertEquals(r['var'], 'mnc')
|
||||
self.assertEquals(r['value'], '9')
|
||||
self.assertEquals(r['value'], '09')
|
||||
|
||||
r = self.do_set('mnc', '009')
|
||||
r = self.do_get('mnc')
|
||||
self.assertEquals(r['mtype'], 'GET_REPLY')
|
||||
self.assertEquals(r['var'], 'mnc')
|
||||
self.assertEquals(r['value'], '9') # FAIL: expecting '009'
|
||||
self.assertEquals(r['value'], '009')
|
||||
|
||||
|
||||
def testMccMncApply(self):
|
||||
|
@ -434,7 +434,7 @@ class TestCtrlBSC(TestCtrlBase):
|
|||
r = self.do_get('mnc')
|
||||
self.assertEquals(r['mtype'], 'GET_REPLY')
|
||||
self.assertEquals(r['var'], 'mnc')
|
||||
self.assertEquals(r['value'], '4')
|
||||
self.assertEquals(r['value'], '04')
|
||||
|
||||
r = self.do_get('mcc')
|
||||
self.assertEquals(r['mtype'], 'GET_REPLY')
|
||||
|
@ -450,7 +450,7 @@ class TestCtrlBSC(TestCtrlBase):
|
|||
r = self.do_get('mnc')
|
||||
self.assertEquals(r['mtype'], 'GET_REPLY')
|
||||
self.assertEquals(r['var'], 'mnc')
|
||||
self.assertEquals(r['value'], '3')
|
||||
self.assertEquals(r['value'], '03')
|
||||
|
||||
r = self.do_get('mcc')
|
||||
self.assertEquals(r['mtype'], 'GET_REPLY')
|
||||
|
@ -466,12 +466,12 @@ class TestCtrlBSC(TestCtrlBase):
|
|||
r = self.do_get('mnc')
|
||||
self.assertEquals(r['mtype'], 'GET_REPLY')
|
||||
self.assertEquals(r['var'], 'mnc')
|
||||
self.assertEquals(r['value'], '3') # FAIL: expecting '003'
|
||||
self.assertEquals(r['value'], '003')
|
||||
|
||||
r = self.do_get('mcc')
|
||||
self.assertEquals(r['mtype'], 'GET_REPLY')
|
||||
self.assertEquals(r['var'], 'mcc')
|
||||
self.assertEquals(r['value'], '2')
|
||||
self.assertEquals(r['value'], '002')
|
||||
|
||||
# Set same MNC with 3 digits
|
||||
r = self.do_set('mcc-mnc-apply', '2,003')
|
||||
|
@ -482,12 +482,12 @@ class TestCtrlBSC(TestCtrlBase):
|
|||
r = self.do_get('mnc')
|
||||
self.assertEquals(r['mtype'], 'GET_REPLY')
|
||||
self.assertEquals(r['var'], 'mnc')
|
||||
self.assertEquals(r['value'], '3') # FAIL: expecting '003'
|
||||
self.assertEquals(r['value'], '003')
|
||||
|
||||
r = self.do_get('mcc')
|
||||
self.assertEquals(r['mtype'], 'GET_REPLY')
|
||||
self.assertEquals(r['var'], 'mcc')
|
||||
self.assertEquals(r['value'], '2')
|
||||
self.assertEquals(r['value'], '002')
|
||||
|
||||
class TestCtrlNAT(TestCtrlBase):
|
||||
|
||||
|
|
|
@ -730,7 +730,7 @@ static const struct test_gsm48_ra_id_by_bts test_gsm48_ra_id_by_bts_data[] = {
|
|||
.lac = 3,
|
||||
.rac = 4,
|
||||
.expect = {
|
||||
.digits = { 0x00, 0xf1, 0x20 }, /* FAIL: should be { 0x00, 0x21, 0x00 }, */
|
||||
.digits = { 0x00, 0x21, 0x00 },
|
||||
.lac = 0x0300, /* network byte order of 3 */
|
||||
.rac = 4,
|
||||
},
|
||||
|
@ -748,7 +748,7 @@ static const struct test_gsm48_ra_id_by_bts test_gsm48_ra_id_by_bts_data[] = {
|
|||
.lac = 0,
|
||||
.rac = 0,
|
||||
.expect = {
|
||||
.digits = { 0x00, 0xf0, 0x00 }, /* FAIL: should be { 0, 0, 0 } */
|
||||
.digits = {},
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -776,7 +776,7 @@ static const struct test_gsm48_ra_id_by_bts test_gsm48_ra_id_by_bts_data[] = {
|
|||
.lac = 0xabcd,
|
||||
.rac = 0xab,
|
||||
.expect = {
|
||||
.digits = { 0x09, 0xf9, 0x09 }, /* FAIL: should be { 0x09, 0x09, 0x90 }, */
|
||||
.digits = { 0x09, 0x09, 0x90 },
|
||||
.lac = 0xcdab,
|
||||
.rac = 0xab,
|
||||
},
|
||||
|
@ -795,8 +795,7 @@ static void test_gsm48_ra_id_by_bts()
|
|||
struct gsm48_ra_id result = {};
|
||||
bool ok;
|
||||
|
||||
net.country_code = t->plmn.mcc;
|
||||
net.network_code = t->plmn.mnc;
|
||||
net.plmn = t->plmn;
|
||||
bts.network = &net;
|
||||
bts.location_area_code = t->lac;
|
||||
bts.gprs.rac = t->rac;
|
||||
|
|
|
@ -215,10 +215,10 @@ SI5: 06 1d 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
|||
SI5bis: 06 05 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
SI5ter: 06 06 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
test_gsm48_ra_id_by_bts[0]: digits='00f120' lac=0x0300=htons(3) rac=0x04=4 pass
|
||||
test_gsm48_ra_id_by_bts[1]: digits='00f120' lac=0x0300=htons(3) rac=0x04=4 pass
|
||||
test_gsm48_ra_id_by_bts[1]: digits='002100' lac=0x0300=htons(3) rac=0x04=4 pass
|
||||
test_gsm48_ra_id_by_bts[2]: digits='00f000' lac=0x0000=htons(0) rac=0x00=0 pass
|
||||
test_gsm48_ra_id_by_bts[3]: digits='00f000' lac=0x0000=htons(0) rac=0x00=0 pass
|
||||
test_gsm48_ra_id_by_bts[3]: digits='000000' lac=0x0000=htons(0) rac=0x00=0 pass
|
||||
test_gsm48_ra_id_by_bts[4]: digits='999999' lac=0xffff=htons(65535) rac=0xff=255 pass
|
||||
test_gsm48_ra_id_by_bts[5]: digits='09f909' lac=0xcdab=htons(43981) rac=0xab=171 pass
|
||||
test_gsm48_ra_id_by_bts[6]: digits='09f909' lac=0xcdab=htons(43981) rac=0xab=171 pass
|
||||
test_gsm48_ra_id_by_bts[6]: digits='090990' lac=0xcdab=htons(43981) rac=0xab=171 pass
|
||||
Done.
|
||||
|
|
|
@ -218,8 +218,7 @@ int main(int argc, char **argv)
|
|||
bts->rach_ldavg_slots = -1;
|
||||
bts->c0->arfcn = 866;
|
||||
bts->cell_identity = 1337;
|
||||
bts->network->country_code = 1;
|
||||
bts->network->network_code = 1;
|
||||
bts->network->plmn = (struct osmo_plmn_id){ .mcc=1, .mnc=1 };
|
||||
bts->location_area_code = 1;
|
||||
bts->gprs.rac = 0;
|
||||
uint8_t attr_bts_expected[] =
|
||||
|
|
Loading…
Reference in New Issue