mscsplit: various preparations to separate MSC from BSC

Disable large parts of the code that depend on BSC presence. The code sections
disabled by #if BEFORE_MSCSPLIT shall be modified or dropped in the course of
adding the A-interface.

Don't set msg->lchan nor msg->dst.
Don't use lchan in libmsc.
Decouple lac from bts.

Prepare entry/exit point for MSC -> BSC and MSC -> RNC communication:
Add msc_ifaces.[hc], a_iface.c, with a general msc_tx_dtap() to redirect to
different interfaces depending on the actual subscriber connection.
While iu_tx() is going to be functional fairly soon, the a_tx() is going to be
just a dummy for some time (see comment).
Add Iu specific fields in gsm_subscriber_connection: the UE connection pointer
and an indicator for the Integrity Protection status on Iu (to be fully
implemented in later commits).
Add lac member to gsm_subscriber_connection, to allow decoupling from
bts->location_area_code. The conn->lac will actually be set in iu.c in an
upcoming commit ("add iucs.[hc]").

move to libcommon-cs: gsm48_extract_mi(), gsm48_paging_extract_mi().

libmsc: duplicate gsm0808 / gsm48 functions (towards BSC).
In osmo-nitb, libmsc would directly call the functions on the BSC level, not
always via the bsc_api. When separating libmsc from libbsc, some functions are
missing from the linkage.
Hence duplicate these functions to libmsc, add an msc_ prefix for clarity, also
add a _tx to gsm0808_cipher_mode():
* add msc_gsm0808_tx_cipher_mode() (dummy/stub)
* add msc_gsm48_tx_mm_serv_ack()
* add msc_gsm48_tx_mm_serv_rej()
Call these from libmsc instead of
* gsm0808_cipher_mode()
* gsm48_tx_mm_serv_ack()
* gsm48_tx_mm_serv_rej()
Also add a comment related to msc_gsm0808_tx_cipher_mode() in two places.

Remove internal RTP streaming code; OsmoNITB supported that, but for OsmoMSC,
this will be done with an external MGCP gateway.

Remove LCHAN_MODIFY from internal MNCC state machine.

Temporarily disable all paging to be able to link libmsc without libbsc.
Skip the paging part of channel_test because the paging is now disabled.
Employ fake paging shims in order for msc_vlr_tests to still work.

msc_compl_l3(): publish in .h, tweak return value.  Use new libmsc enum values
for return val, to avoid dependency on libbsc headers.  Make callable from
other scopes: publish in osmo_msc.h and remove 'static' in osmo_msc.c

add gsm_encr to subscr_conn
move subscr_request to gsm_subscriber.h
subscr_request_channel() -> subscr_request_conn()
move to libmsc: osmo_stats_vty_add_cmds()
gsm_04_08: remove apply_codec_restrictions()
gsm0408_test: use NULL for root ctx
move to libbsc: gsm_bts_neighbor()
move to libbsc: lchan_next_meas_rep()
move vty config for t3212 to network level (periodic lu)
remove unneccessary linking from some tests
remove handle_abisip_signal()
abis_rsl.c: don't use libvlr from libbsc

gsm_subscriber_connection: put the LAC here, so that it is available without
accessing conn->bts. In bsc_api.c, place this lac in conn for the sake of
transition: Iu and A will use this new field to pass the LAC around, but in a
completely separate OsmoBSC this is not actually needed. It can be removed
again from osmo-bsc.git when the time has come.

Siemens MRPCI: completely drop sending the MRPCI messages for now, they shall
be added in osmo-bsc once the A-Interface code has settled. See OS#2389.

Related: OS#1845 OS#2257 OS#2389
Change-Id: Id3705236350d5f69e447046b0a764bbabc3d493c
This commit is contained in:
Neels Hofmeyr 2017-05-08 15:12:20 +02:00 committed by Neels Hofmeyr
parent da76052407
commit ce4d88bd62
39 changed files with 470 additions and 1071 deletions

View File

@ -54,6 +54,7 @@ noinst_HEADERS = \
misdn.h \
mncc.h \
mncc_int.h \
msc_ifaces.h \
nat_rewrite_trie.h \
network_listen.h \
oap_client.h \

View File

@ -65,8 +65,6 @@ 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 bsc_subscr *bsub);
int gsm48_lchan_modify(struct gsm_lchan *lchan, uint8_t lchan_mode);
int gsm48_rx_rr_modif_ack(struct msgb *msg);

View File

@ -26,6 +26,7 @@ struct gsm_subscriber_group;
struct bsc_subscr;
struct vlr_instance;
struct vlr_subscr;
struct ue_conn_ctx;
#define OBSC_LINKID_CB(__msgb) (__msgb)->cb[3]
@ -117,6 +118,12 @@ struct gsm_classmark {
uint8_t classmark3[14]; /* if cm3 gets extended by spec, it will be truncated */
};
enum integrity_protection_state {
INTEGRITY_PROTECTION_NONE = 0,
INTEGRITY_PROTECTION_IK = 1,
INTEGRITY_PROTECTION_IK_CK = 2,
};
/* active radio connection of a mobile subscriber */
struct gsm_subscriber_connection {
/* global linked list of subscriber_connections */
@ -176,6 +183,15 @@ struct gsm_subscriber_connection {
enum ran_type via_ran;
struct gsm_classmark classmark;
uint16_t lac;
struct gsm_encr encr;
/* which Iu-CS connection, if any. */
struct {
struct ue_conn_ctx *ue_ctx;
int integrity_protection;
} iu;
};
@ -311,6 +327,12 @@ struct gsm_tz {
};
struct gsm_network {
/* TODO MSCSPLIT the gsm_network struct is basically a kitchen sink for
* global settings and variables, "madly" mixing BSC and MSC stuff. Split
* this in e.g. struct osmo_bsc and struct osmo_msc, with the things
* 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;
@ -416,6 +438,9 @@ struct gsm_network {
uint16_t gsup_server_port;
struct vlr_instance *vlr;
/* Periodic location update default value */
uint8_t t3212;
};
struct osmo_esme;
@ -471,10 +496,6 @@ extern void talloc_ctx_init(void *ctx_root);
int gsm_set_bts_type(struct gsm_bts *bts, enum gsm_bts_type type);
/* Get reference to a neighbor cell on a given BCCH ARFCN */
struct gsm_bts *gsm_bts_neighbor(const struct gsm_bts *bts,
uint16_t arfcn, uint8_t bsic);
enum gsm_bts_type parse_btstype(const char *arg);
const char *btstype2str(enum gsm_bts_type type);
struct gsm_bts *gsm_bts_by_lac(struct gsm_network *net, unsigned int lac,
@ -557,7 +578,6 @@ int bts_gprs_mode_is_compat(struct gsm_bts *bts, enum bts_gprs_mode mode);
int gsm48_ra_id_by_bts(uint8_t *buf, struct gsm_bts *bts);
void gprs_ra_id_by_bts(struct gprs_ra_id *raid, struct gsm_bts *bts);
struct gsm_meas_rep *lchan_next_meas_rep(struct gsm_lchan *lchan);
int gsm_btsmodel_set_feature(struct gsm_bts_model *model, enum gsm_bts_features feat);
int gsm_bts_model_register(struct gsm_bts_model *model);

View File

@ -19,8 +19,6 @@
#define GSM_SUBSCRIBER_NO_EXPIRATION 0x0
struct subscr_request;
enum gsm_subscriber_field {
GSM_SUBSCRIBER_IMSI,
GSM_SUBSCRIBER_TMSI,
@ -34,17 +32,35 @@ enum gsm_subscriber_update_reason {
GSM_SUBSCRIBER_UPDATE_EQUIPMENT,
};
int subscr_update(struct vlr_subscr *vsub, struct gsm_bts *bts, int reason);
/*
* Struct for pending channel requests. This is managed in the
* llist_head requests of each subscriber. The reference counting
* should work in such a way that a subscriber with a pending request
* remains in memory.
*/
struct subscr_request {
struct llist_head entry;
/* the callback data */
gsm_cbfn *cbfn;
void *param;
};
int subscr_update(struct vlr_subscr *vsub, int reason);
/*
* Paging handling with authentication
*/
struct subscr_request *subscr_request_channel(struct vlr_subscr *vsub,
int channel_type,
gsm_cbfn *cbfn, void *param);
struct subscr_request *subscr_request_conn(struct vlr_subscr *vsub,
int channel_type,
gsm_cbfn *cbfn, void *param);
void subscr_remove_request(struct subscr_request *req);
int subscr_paging_dispatch(unsigned int hooknum, unsigned int event,
struct msgb *msg, void *data, void *param);
int msc_fake_paging_request(struct vlr_subscr *vsub);
void msc_fake_paging_request_stop(struct vlr_subscr *vsub);
#endif /* _GSM_SUBSCR_H */

View File

@ -155,9 +155,6 @@ struct gsm_mncc {
int notify; /* 0..127 */
int emergency;
char imsi[16];
unsigned char lchan_type;
unsigned char lchan_mode;
};
struct gsm_data_frame {
@ -179,7 +176,6 @@ struct gsm_mncc_hello {
uint32_t called_offset;
uint32_t signal_offset;
uint32_t emergency_offset;
uint32_t lchan_type_offset;
};
struct gsm_mncc_rtp {

View File

@ -0,0 +1,47 @@
#pragma once
#include <osmocom/core/msgb.h>
#include <openbsc/gsm_data.h>
/* These are the interfaces of the MSC layer towards (from?) the BSC and RNC,
* i.e. in the direction towards the mobile device (MS aka UE).
*
* 2G will use the A-interface,
* 3G aka UMTS will use the Iu-interface (for the MSC, it's IuCS).
*
* To allow linking parts of the MSC code without having to include entire
* infrastructures of external libraries, the core transmitting and receiving
* functions are left unimplemented. For example, a unit test does not need to
* link against external ASN1 libraries if it is never going to encode actual
* outgoing messages. It is up to each building scope to implement real world
* functions or to plug mere dummy implementations.
*
* For example, msc_tx_dtap(conn, msg), depending on conn->via_iface, will call
* either iu_tx() or a_tx() [note: at time of writing, the A-interface is not
* yet implemented]. When you try to link against libmsc, you will find that
* the compiler complains about an undefined reference to iu_tx(). If you,
* however, link against libiu as well as the osmo-iuh libs (etc.), iu_tx() is
* available. A unit test may instead simply implement a dummy iu_tx() function
* and not link against osmo-iuh.
*/
/* Each main linkage must implement this function (see comment above). */
extern int iu_tx(struct msgb *msg, uint8_t sapi);
/* So far this is a dummy implemented in libmsc/a_iface.c. When A-interface
* gets implemented, it should be in a separate lib (like libiu), this function
* should move there, and the following comment should remain here: "
* Each main linkage must implement this function (see comment above).
* " */
extern int a_tx(struct msgb *msg);
int msc_tx_dtap(struct gsm_subscriber_connection *conn,
struct msgb *msg);
int msc_gsm48_tx_mm_serv_ack(struct gsm_subscriber_connection *conn);
int msc_gsm48_tx_mm_serv_rej(struct gsm_subscriber_connection *conn,
enum gsm48_reject_value value);
/* TODO: specific to A interface, move this away */
int msc_gsm0808_tx_cipher_mode(struct gsm_subscriber_connection *conn, int cipher,
const uint8_t *key, int len, int include_imeisv);

View File

@ -51,6 +51,11 @@ static inline const char *subscr_conn_from_name(enum subscr_conn_from val)
return get_value_string(subscr_conn_from_names, val);
}
enum msc_compl_l3_rc {
MSC_CONN_ACCEPT = 0,
MSC_CONN_REJECT = 1,
};
struct bsc_api *msc_bsc_api();

View File

@ -1423,6 +1423,19 @@ static void print_meas_rep(struct gsm_lchan *lchan, struct gsm_meas_rep *mr)
}
}
static struct gsm_meas_rep *lchan_next_meas_rep(struct gsm_lchan *lchan)
{
struct gsm_meas_rep *meas_rep;
meas_rep = &lchan->meas_rep[lchan->meas_rep_idx];
memset(meas_rep, 0, sizeof(*meas_rep));
meas_rep->lchan = lchan;
lchan->meas_rep_idx = (lchan->meas_rep_idx + 1)
% ARRAY_SIZE(lchan->meas_rep);
return meas_rep;
}
static int rsl_rx_meas_res(struct msgb *msg)
{
struct abis_rsl_dchan_hdr *dh = msgb_l2(msg);

View File

@ -264,6 +264,7 @@ struct gsm_subscriber_connection *bsc_subscr_con_allocate(struct gsm_lchan *lcha
conn->lchan = lchan;
conn->bts = lchan->ts->trx->bts;
conn->via_ran = RAN_GERAN_A;
conn->lac = conn->bts->location_area_code;
lchan->conn = conn;
llist_add_tail(&conn->entry, &net->subscr_conns);
return conn;

View File

@ -593,18 +593,12 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts)
(sp->penalty_time*20)+20, VTY_NEWLINE);
}
/* Is periodic LU enabled or disabled? */
if (bts->si_common.chan_desc.t3212 == 0)
vty_out(vty, " no periodic location update%s", VTY_NEWLINE);
else
vty_out(vty, " periodic location update %u%s",
bts->si_common.chan_desc.t3212 * 6, VTY_NEWLINE);
if (gsm_bts_get_radio_link_timeout(bts) < 0)
vty_out(vty, " radio-link-timeout infinite%s", VTY_NEWLINE);
else
vty_out(vty, " radio-link-timeout %d%s",
gsm_bts_get_radio_link_timeout(bts), VTY_NEWLINE);
vty_out(vty, " channel allocator %s%s",
bts->chan_alloc_reverse ? "descending" : "ascending",
VTY_NEWLINE);
@ -841,6 +835,11 @@ static int config_write_net(struct vty *vty)
vty_out(vty, " timezone %d %d%s",
gsmnet->tz.hr, gsmnet->tz.mn, VTY_NEWLINE);
}
if (gsmnet->t3212 == 0)
vty_out(vty, " no periodic location update%s", VTY_NEWLINE);
else
vty_out(vty, " periodic location update %u%s",
gsmnet->t3212 * 6, VTY_NEWLINE);
return CMD_SUCCESS;
}
@ -2266,34 +2265,6 @@ DEFUN(cfg_bts_penalty_time_rsvd, cfg_bts_penalty_time_rsvd_cmd,
return CMD_SUCCESS;
}
DEFUN(cfg_bts_per_loc_upd, cfg_bts_per_loc_upd_cmd,
"periodic location update <6-1530>",
"Periodic Location Updating Interval\n"
"Periodic Location Updating Interval\n"
"Periodic Location Updating Interval\n"
"Periodic Location Updating Interval in Minutes\n")
{
struct gsm_bts *bts = vty->index;
bts->si_common.chan_desc.t3212 = atoi(argv[0]) / 6;
return CMD_SUCCESS;
}
DEFUN(cfg_bts_no_per_loc_upd, cfg_bts_no_per_loc_upd_cmd,
"no periodic location update",
NO_STR
"Periodic Location Updating Interval\n"
"Periodic Location Updating Interval\n"
"Periodic Location Updating Interval\n")
{
struct gsm_bts *bts = vty->index;
bts->si_common.chan_desc.t3212 = 0;
return CMD_SUCCESS;
}
DEFUN(cfg_bts_radio_link_timeout, cfg_bts_radio_link_timeout_cmd,
"radio-link-timeout <4-64>",
"Radio link timeout criterion (BTS side)\n"
@ -4129,7 +4100,6 @@ int bsc_vty_init(struct gsm_network *network)
install_element_ve(&show_paging_group_cmd);
logging_vty_add_cmds(NULL);
osmo_stats_vty_add_cmds();
install_element(GSMNET_NODE, &cfg_net_neci_cmd);
install_element(GSMNET_NODE, &cfg_net_handover_cmd);
@ -4189,8 +4159,6 @@ int bsc_vty_init(struct gsm_network *network)
install_element(BTS_NODE, &cfg_bts_rach_ec_allowed_cmd);
install_element(BTS_NODE, &cfg_bts_rach_ac_class_cmd);
install_element(BTS_NODE, &cfg_bts_ms_max_power_cmd);
install_element(BTS_NODE, &cfg_bts_per_loc_upd_cmd);
install_element(BTS_NODE, &cfg_bts_no_per_loc_upd_cmd);
install_element(BTS_NODE, &cfg_bts_cell_resel_hyst_cmd);
install_element(BTS_NODE, &cfg_bts_rxlev_acc_min_cmd);
install_element(BTS_NODE, &cfg_bts_cell_bar_qualify_cmd);

View File

@ -270,61 +270,6 @@ int send_siemens_mrpci(struct gsm_lchan *lchan,
return rsl_siemens_mrpci(lchan, &mrpci);
}
int gsm48_extract_mi(uint8_t *classmark2_lv, int length, char *mi_string, uint8_t *mi_type)
{
/* Check the size for the classmark */
if (length < 1 + *classmark2_lv)
return -1;
uint8_t *mi_lv = classmark2_lv + *classmark2_lv + 1;
if (length < 2 + *classmark2_lv + mi_lv[0])
return -2;
*mi_type = mi_lv[1] & GSM_MI_TYPE_MASK;
return gsm48_mi_to_string(mi_string, GSM48_MI_SIZE, mi_lv+1, *mi_lv);
}
int gsm48_paging_extract_mi(struct gsm48_pag_resp *resp, int length,
char *mi_string, uint8_t *mi_type)
{
static const uint32_t classmark_offset =
offsetof(struct gsm48_pag_resp, classmark2);
uint8_t *classmark2_lv = (uint8_t *) &resp->classmark2;
return gsm48_extract_mi(classmark2_lv, length - classmark_offset,
mi_string, mi_type);
}
int gsm48_handle_paging_resp(struct gsm_subscriber_connection *conn,
struct msgb *msg, struct bsc_subscr *bsub)
{
struct gsm_bts *bts = msg->lchan->ts->trx->bts;
struct gsm48_hdr *gh = msgb_l3(msg);
uint8_t *classmark2_lv = gh->data + 1;
if (is_siemens_bts(bts))
send_siemens_mrpci(msg->lchan, classmark2_lv);
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");
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(&bts->network->bts_list, conn->bts, bsub, conn,
msg);
return 0;
}
/* Chapter 9.1.9: Ciphering Mode Command */
int gsm48_send_rr_ciph_mode(struct gsm_lchan *lchan, int want_imeisv)
{

View File

@ -33,6 +33,27 @@
#include <openbsc/handover.h>
#include <osmocom/gsm/gsm_utils.h>
/* Get reference to a neighbor cell on a given BCCH ARFCN */
static struct gsm_bts *gsm_bts_neighbor(const struct gsm_bts *bts,
uint16_t arfcn, uint8_t bsic)
{
struct gsm_bts *neigh;
/* FIXME: use some better heuristics here to determine which cell
* using this ARFCN really is closest to the target cell. For
* now we simply assume that each ARFCN will only be used by one
* cell */
llist_for_each_entry(neigh, &bts->network->bts_list, list) {
/* FIXME: this is probably returning the same bts again!? */
if (neigh->c0->arfcn == arfcn &&
neigh->bsic == bsic)
return neigh;
}
return NULL;
}
/* issue handover to a cell identified by ARFCN and BSIC */
static int handover_to_arfcn_bsic(struct gsm_lchan *lchan,
uint16_t arfcn, uint8_t bsic)

View File

@ -56,6 +56,9 @@ struct gsm_network *gsm_network_init(void *ctx,
net->country_code = country_code;
net->network_code = network_code;
/* Use 30 min periodic update interval as sane default */
net->t3212 = 5;
INIT_LLIST_HEAD(&net->trans_list);
INIT_LLIST_HEAD(&net->upqueue);
INIT_LLIST_HEAD(&net->subscr_conns);
@ -107,6 +110,30 @@ struct msgb *gsm48_create_loc_upd_rej(uint8_t cause)
return msg;
}
int gsm48_extract_mi(uint8_t *classmark2_lv, int length, char *mi_string, uint8_t *mi_type)
{
/* Check the size for the classmark */
if (length < 1 + *classmark2_lv)
return -1;
uint8_t *mi_lv = classmark2_lv + *classmark2_lv + 1;
if (length < 2 + *classmark2_lv + mi_lv[0])
return -2;
*mi_type = mi_lv[1] & GSM_MI_TYPE_MASK;
return gsm48_mi_to_string(mi_string, GSM48_MI_SIZE, mi_lv+1, *mi_lv);
}
int gsm48_paging_extract_mi(struct gsm48_pag_resp *resp, int length,
char *mi_string, uint8_t *mi_type)
{
static const uint32_t classmark_offset =
offsetof(struct gsm48_pag_resp, classmark2);
uint8_t *classmark2_lv = (uint8_t *) &resp->classmark2;
return gsm48_extract_mi(classmark2_lv, length - classmark_offset,
mi_string, mi_type);
}
uint8_t sms_next_rp_msg_ref(uint8_t *next_rp_ref)
{
const uint8_t rp_msg_ref = *next_rp_ref;

View File

@ -284,6 +284,34 @@ DEFUN(cfg_net_no_timezone,
return CMD_SUCCESS;
}
DEFUN(cfg_net_per_loc_upd, cfg_net_per_loc_upd_cmd,
"periodic location update <6-1530>",
"Periodic Location Updating Interval\n"
"Periodic Location Updating Interval\n"
"Periodic Location Updating Interval\n"
"Periodic Location Updating Interval in Minutes\n")
{
struct gsm_network *net = vty->index;
net->t3212 = atoi(argv[0]) / 6;
return CMD_SUCCESS;
}
DEFUN(cfg_net_no_per_loc_upd, cfg_net_no_per_loc_upd_cmd,
"no periodic location update",
NO_STR
"Periodic Location Updating Interval\n"
"Periodic Location Updating Interval\n"
"Periodic Location Updating Interval\n")
{
struct gsm_network *net = vty->index;
net->t3212 = 0;
return CMD_SUCCESS;
}
static struct gsm_network *vty_global_gsm_network = NULL;
/* initialize VTY elements used in both BSC and MSC */
@ -293,6 +321,8 @@ int common_cs_vty_init(struct gsm_network *network,
OSMO_ASSERT(vty_global_gsm_network == NULL);
vty_global_gsm_network = network;
osmo_stats_vty_add_cmds();
install_element(CONFIG_NODE, &cfg_net_cmd);
install_node(&net_node, config_write_net);
vty_install_default(GSMNET_NODE);
@ -310,6 +340,8 @@ int common_cs_vty_init(struct gsm_network *network,
install_element(GSMNET_NODE, &cfg_net_timezone_cmd);
install_element(GSMNET_NODE, &cfg_net_timezone_dst_cmd);
install_element(GSMNET_NODE, &cfg_net_no_timezone_cmd);
install_element(GSMNET_NODE, &cfg_net_per_loc_upd_cmd);
install_element(GSMNET_NODE, &cfg_net_no_per_loc_upd_cmd);
install_element(GSMNET_NODE, &cfg_net_dyn_ts_allow_tch_f_cmd);
return CMD_SUCCESS;

View File

@ -71,25 +71,6 @@ int gsm_bts_model_register(struct gsm_bts_model *model)
return 0;
}
/* Get reference to a neighbor cell on a given BCCH ARFCN */
struct gsm_bts *gsm_bts_neighbor(const struct gsm_bts *bts,
uint16_t arfcn, uint8_t bsic)
{
struct gsm_bts *neigh;
/* FIXME: use some better heuristics here to determine which cell
* using this ARFCN really is closest to the target cell. For
* now we simply assume that each ARFCN will only be used by one
* cell */
llist_for_each_entry(neigh, &bts->network->bts_list, list) {
if (neigh->c0->arfcn == arfcn &&
neigh->bsic == bsic)
return neigh;
}
return NULL;
}
const struct value_string bts_type_descs[_NUM_GSM_BTS_TYPE+1] = {
{ GSM_BTS_TYPE_UNKNOWN, "Unknown BTS Type" },
{ GSM_BTS_TYPE_BS11, "Siemens BTS (BS-11 or compatible)" },
@ -210,19 +191,6 @@ int bts_gprs_mode_is_compat(struct gsm_bts *bts, enum bts_gprs_mode mode)
return 1;
}
struct gsm_meas_rep *lchan_next_meas_rep(struct gsm_lchan *lchan)
{
struct gsm_meas_rep *meas_rep;
meas_rep = &lchan->meas_rep[lchan->meas_rep_idx];
memset(meas_rep, 0, sizeof(*meas_rep));
meas_rep->lchan = lchan;
lchan->meas_rep_idx = (lchan->meas_rep_idx + 1)
% ARRAY_SIZE(lchan->meas_rep);
return meas_rep;
}
int gsm_btsmodel_set_feature(struct gsm_bts_model *model, enum gsm_bts_features feat)
{
OSMO_ASSERT(_NUM_BTS_FEAT < MAX_BTS_FEATURES);
@ -322,7 +290,7 @@ struct gsm_bts *gsm_bts_alloc_register(struct gsm_network *net, enum gsm_bts_typ
bts->si_common.chan_desc.att = 1; /* attachment required */
bts->si_common.chan_desc.bs_pa_mfrms = RSL_BS_PA_MFRMS_5; /* paging frames */
bts->si_common.chan_desc.bs_ag_blks_res = 1; /* reserved AGCH blocks */
bts->si_common.chan_desc.t3212 = 5; /* Use 30 min periodic update interval as sane default */
bts->si_common.chan_desc.t3212 = net->t3212; /* Use network's current value */
gsm_bts_set_radio_link_timeout(bts, 32); /* Use RADIO LINK TIMEOUT of 32 */
llist_add_tail(&bts->list, &net->bts_list);

View File

@ -44,7 +44,6 @@ void talloc_ctx_init(void *ctx_root)
tall_authciphop_ctx = talloc_named_const(ctx_root, 0, "auth_ciph_oper");
tall_gsms_ctx = talloc_named_const(ctx_root, 0, "sms");
tall_subscr_ctx = talloc_named_const(ctx_root, 0, "subscriber");
tall_sub_req_ctx = talloc_named_const(ctx_root, 0, "subscr_request");
tall_call_ctx = talloc_named_const(ctx_root, 0, "gsm_call");
tall_paging_ctx = talloc_named_const(ctx_root, 0, "paging_request");
tall_sigh_ctx = talloc_named_const(ctx_root, 0, "signal_handler");

View File

@ -23,6 +23,7 @@ noinst_LIBRARIES = \
$(NULL)
libmsc_a_SOURCES = \
a_iface.c \
auth.c \
db.c \
gsm_04_08.c \
@ -32,6 +33,7 @@ libmsc_a_SOURCES = \
mncc.c \
mncc_builtin.c \
mncc_sock.c \
msc_ifaces.c \
rrlp.c \
silent_call.c \
sms_queue.c \

45
src/libmsc/a_iface.c Normal file
View File

@ -0,0 +1,45 @@
/* A-interface implementation, from MSC to BSC */
/* (C) 2016 by sysmocom s.m.f.c GmbH <info@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 <osmocom/core/msgb.h>
#include <osmocom/core/logging.h>
#include <openbsc/debug.h>
#include <openbsc/gsm_data.h>
#include <openbsc/msc_ifaces.h>
#include <openbsc/debug.h>
int a_tx(struct msgb *msg)
{
LOGP(DMSC, LOGL_ERROR, "message to be sent to BSC, but A-interface"
" not implemented.\n%s\n", osmo_hexdump(msg->data, msg->len));
return -1;
}
int msc_gsm0808_tx_cipher_mode(struct gsm_subscriber_connection *conn, int cipher,
const uint8_t *key, int len, int include_imeisv)
{
/* TODO generalize for A- and Iu interfaces, don't name after 08.08 */
LOGP(DMSC, LOGL_ERROR, "gsm0808_cipher_mode(): message to be sent to"
" BSC, but A interface not yet implemented.\n");
return -1;
}

File diff suppressed because it is too large Load Diff

View File

@ -878,7 +878,7 @@ int gsm0411_rcv_sms(struct gsm_subscriber_connection *conn,
}
/* Take a SMS in gsm_sms structure and send it through an already
* existing lchan. We also assume that the caller ensured this lchan already
* existing conn. We also assume that the caller ensured this conn already
* has a SAPI3 RLL connection! */
int gsm411_send_sms(struct gsm_subscriber_connection *conn, struct gsm_sms *sms)
{
@ -1004,7 +1004,7 @@ int gsm411_send_sms_subscr(struct vlr_subscr *vsub,
struct gsm_subscriber_connection *conn;
void *res;
/* check if we already have an open lchan to the subscriber.
/* check if we already have an open conn to the subscriber.
* if yes, send the SMS this way */
conn = connection_for_subscr(vsub);
if (conn) {
@ -1016,8 +1016,8 @@ int gsm411_send_sms_subscr(struct vlr_subscr *vsub,
/* if not, we have to start paging */
LOGP(DLSMS, LOGL_DEBUG, "Sending SMS: no connection open, start paging %s\n",
vlr_subscr_name(vsub));
res = subscr_request_channel(vsub, RSL_CHANNEED_SDCCH,
paging_cb_send_sms, sms);
res = subscr_request_conn(vsub, RSL_CHANNEED_SDCCH, paging_cb_send_sms,
sms);
if (!res) {
send_signal(S_SMS_UNKNOWN_ERROR, NULL, sms, GSM_PAGING_BUSY);
sms_free(sms);

View File

@ -41,43 +41,6 @@
#include <openbsc/chan_alloc.h>
#include <openbsc/vlr.h>
void *tall_sub_req_ctx;
int gsm48_secure_channel(struct gsm_subscriber_connection *conn, int key_seq,
gsm_cbfn *cb, void *cb_data);
/*
* Struct for pending channel requests. This is managed in the
* llist_head requests of each subscriber. The reference counting
* should work in such a way that a subscriber with a pending request
* remains in memory.
*/
struct subscr_request {
struct llist_head entry;
/* the callback data */
gsm_cbfn *cbfn;
void *param;
};
static struct bsc_subscr *vlr_subscr_to_bsc_sub(struct llist_head *bsc_subscribers,
struct vlr_subscr *vsub)
{
struct bsc_subscr *sub;
/* 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. */
sub = bsc_subscr_find_or_create_by_imsi(bsc_subscribers, vsub->imsi);
sub->tmsi = vsub->tmsi;
sub->lac = vsub->lac;
return sub;
}
/*
* We got the channel assigned and can now hand this channel
* over to one of our callbacks.
*/
int subscr_paging_dispatch(unsigned int hooknum, unsigned int event,
struct msgb *msg, void *data, void *param)
{
@ -85,22 +48,12 @@ int subscr_paging_dispatch(unsigned int hooknum, unsigned int event,
struct gsm_subscriber_connection *conn = data;
struct vlr_subscr *vsub = param;
struct paging_signal_data sig_data;
struct bsc_subscr *bsub;
struct gsm_network *net;
OSMO_ASSERT(vsub && vsub->cs.is_paging);
net = vsub->vlr->user_ctx;
/*
* Stop paging on all other BTS. E.g. if this is
* the first timeout on a BTS then the others will
* timeout soon as well. Let's just stop everything
* and forget we wanted to page.
*/
bsub = vlr_subscr_to_bsc_sub(conn->network->bsc_subscribers, vsub);
paging_request_stop(&net->bts_list, NULL, bsub, NULL, NULL);
bsc_subscr_put(bsub);
/* FIXME: implement stop paging in libmsc;
* faking it for the unit tests to still work */
msc_fake_paging_request_stop(vsub);
/* Inform parts of the system we don't know */
sig_data.vsub = vsub;
@ -126,22 +79,21 @@ int subscr_paging_dispatch(unsigned int hooknum, unsigned int event,
return 0;
}
struct subscr_request *subscr_request_channel(struct vlr_subscr *vsub,
int channel_type,
gsm_cbfn *cbfn, void *param)
struct subscr_request *subscr_request_conn(struct vlr_subscr *vsub, int channel_type, gsm_cbfn *cbfn,
void *param)
{
int rc;
struct subscr_request *request;
struct bsc_subscr *bsub;
struct gsm_network *net = vsub->vlr->user_ctx;
/* Start paging.. we know it is async so we can do it before */
if (!vsub->cs.is_paging) {
LOGP(DMM, LOGL_DEBUG, "Subscriber %s not paged yet.\n",
vlr_subscr_name(vsub));
bsub = vlr_subscr_to_bsc_sub(net->bsc_subscribers, vsub);
rc = paging_request(net, bsub, channel_type, NULL, NULL);
bsc_subscr_put(bsub);
/* FIXME: implement paging in libmsc;
* faking it for the unit tests to still work */
rc = msc_fake_paging_request(vsub);
if (rc <= 0) {
LOGP(DMM, LOGL_ERROR, "Subscriber %s paging failed: %d\n",
vlr_subscr_name(vsub), rc);

View File

@ -65,21 +65,6 @@ static struct gsm_call *get_call_ref(uint32_t callref)
return NULL;
}
uint8_t mncc_codec_for_mode(int lchan_type)
{
/* FIXME: check codec capabilities of the phone */
if (lchan_type != GSM_LCHAN_TCH_H)
return mncc_int.def_codec[0];
else
return mncc_int.def_codec[1];
}
static uint8_t determine_lchan_mode(struct gsm_mncc *setup)
{
return mncc_codec_for_mode(setup->lchan_type);
}
/* on incoming call, look up database and send setup to remote subscr. */
static int mncc_setup_ind(struct gsm_call *call, int msg_type,
struct gsm_mncc *setup)
@ -137,9 +122,7 @@ static int mncc_setup_ind(struct gsm_call *call, int msg_type,
/* modify mode */
memset(&mncc, 0, sizeof(struct gsm_mncc));
mncc.callref = call->callref;
mncc.lchan_mode = determine_lchan_mode(setup);
DEBUGP(DMNCC, "(call %x) Modify channel mode: %s\n", call->callref,
get_value_string(gsm48_chan_mode_names, mncc.lchan_mode));
DEBUGP(DMNCC, "(call %x) Modify channel mode\n", call->callref);
mncc_tx_to_cc(call->net, MNCC_LCHAN_MODIFY, &mncc);
/* send setup to remote */
@ -207,10 +190,6 @@ static int mncc_setup_cnf(struct gsm_call *call, int msg_type,
bridge.callref[1] = call->remote_ref;
DEBUGP(DMNCC, "(call %x) Bridging with remote.\n", call->callref);
/* in direct mode, we always have to bridge the channels */
if (ipacc_rtp_direct)
return mncc_tx_to_cc(call->net, MNCC_BRIDGE, &bridge);
/* proxy mode */
if (!net->handover.active) {
/* in the no-handover case, we can bridge, i.e. use
@ -279,28 +258,6 @@ static int mncc_rel_cnf(struct gsm_call *call, int msg_type, struct gsm_mncc *re
return 0;
}
/* receiving a (speech) traffic frame from the BSC code */
static int mncc_rcv_data(struct gsm_call *call, int msg_type,
struct gsm_data_frame *dfr)
{
struct gsm_trans *remote_trans;
remote_trans = trans_find_by_callref(call->net, call->remote_ref);
/* this shouldn't really happen */
if (!remote_trans || !remote_trans->conn) {
LOGP(DMNCC, LOGL_ERROR, "No transaction or transaction without lchan?!?\n");
return -EIO;
}
/* RTP socket of remote end has meanwhile died */
if (!remote_trans->conn->lchan->abis_ip.rtp_socket)
return -EIO;
return rtp_send_frame(remote_trans->conn->lchan->abis_ip.rtp_socket, dfr);
}
/* Internal MNCC handler input function (from CC -> MNCC -> here) */
int int_mncc_recv(struct gsm_network *net, struct msgb *msg)
{
@ -346,7 +303,8 @@ int int_mncc_recv(struct gsm_network *net, struct msgb *msg)
}
if (mncc_is_data_frame(msg_type)) {
rc = mncc_rcv_data(call, msg_type, arg);
LOGP(DMNCC, LOGL_ERROR, "(call %x) Received data frame, which is not supported.\n",
call->callref);
goto out_free;
}
@ -364,7 +322,6 @@ int int_mncc_recv(struct gsm_network *net, struct msgb *msg)
break;
case MNCC_CALL_CONF_IND:
/* we now need to MODIFY the channel */
data->lchan_mode = determine_lchan_mode(data);
mncc_tx_to_cc(call->net, MNCC_LCHAN_MODIFY, data);
break;
case MNCC_ALERT_IND:

View File

@ -224,7 +224,6 @@ static void queue_hello(struct mncc_sock_state *mncc)
hello->called_offset = offsetof(struct gsm_mncc, called);
hello->signal_offset = offsetof(struct gsm_mncc, signal);
hello->emergency_offset = offsetof(struct gsm_mncc, emergency);
hello->lchan_type_offset = offsetof(struct gsm_mncc, lchan_type);
msgb_enqueue(&mncc->net->upqueue, msg);
mncc->conn_bfd.when |= BSC_FD_WRITE;

84
src/libmsc/msc_ifaces.c Normal file
View File

@ -0,0 +1,84 @@
/* Implementation for MSC decisions which interface to send messages out on. */
/* (C) 2016 by sysmocom s.m.f.c GmbH <info@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 <osmocom/core/logging.h>
#include <openbsc/debug.h>
#include <openbsc/gsm_data.h>
#include <openbsc/msc_ifaces.h>
static int msc_tx(struct gsm_subscriber_connection *conn, struct msgb *msg)
{
switch (conn->via_ran) {
/* FUTURE
case RAN_GERAN_A:
msg->dst = conn;
return a_tx(msg);
case RAN_UTRAN_IU:
msg->dst = conn->iu.ue_ctx;
return iu_tx(msg, 0);
*/
default:
LOGP(DMSC, LOGL_ERROR,
"msc_tx(): conn->via_ran invalid (%d)\n",
conn->via_ran);
return -1;
}
}
int msc_tx_dtap(struct gsm_subscriber_connection *conn,
struct msgb *msg)
{
return msc_tx(conn, msg);
}
/* 9.2.5 CM service accept */
int msc_gsm48_tx_mm_serv_ack(struct gsm_subscriber_connection *conn)
{
struct msgb *msg = gsm48_msgb_alloc_name("GSM 04.08 SERV ACC");
struct gsm48_hdr *gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh));
gh->proto_discr = GSM48_PDISC_MM;
gh->msg_type = GSM48_MT_MM_CM_SERV_ACC;
DEBUGP(DMM, "-> CM SERVICE ACCEPT\n");
return msc_tx_dtap(conn, msg);
}
/* 9.2.6 CM service reject */
int msc_gsm48_tx_mm_serv_rej(struct gsm_subscriber_connection *conn,
enum gsm48_reject_value value)
{
struct msgb *msg;
msg = gsm48_create_mm_serv_rej(value);
if (!msg) {
LOGP(DMM, LOGL_ERROR, "Failed to allocate CM Service Reject.\n");
return -1;
}
DEBUGP(DMM, "-> CM SERVICE Reject cause: %d\n", value);
return msc_tx_dtap(conn, msg);
}

View File

@ -21,6 +21,7 @@
*
*/
#include <openbsc/osmo_msc.h>
#include <openbsc/bsc_api.h>
#include <openbsc/debug.h>
#include <openbsc/transaction.h>
@ -69,9 +70,10 @@ static void subscr_conn_bump(struct gsm_subscriber_connection *conn)
osmo_fsm_inst_dispatch(conn->conn_fsm, SUBSCR_CONN_E_BUMP, NULL);
}
/* Receive a COMPLETE LAYER3 INFO from BSC */
static int msc_compl_l3(struct gsm_subscriber_connection *conn, struct msgb *msg,
uint16_t chosen_channel)
/* receive a Level 3 Complete message and return MSC_CONN_ACCEPT or
* MSC_CONN_REJECT */
static int msc_compl_l3(struct gsm_subscriber_connection *conn,
struct msgb *msg, uint16_t chosen_channel)
{
/* Ownership of the gsm_subscriber_connection is still a bit mucky
* between libbsc and libmsc. In libmsc, we use ref counting, but not
@ -87,7 +89,7 @@ static int msc_compl_l3(struct gsm_subscriber_connection *conn, struct msgb *msg
/* keep the use_count reserved, libbsc will discard. If we
* released the ref count and discarded here, libbsc would
* double-free. And we will not change bsc_api semantics. */
return BSC_API_CONN_POL_REJECT;
return MSC_CONN_REJECT;
}
DEBUGP(DMM, "compl_l3: Keeping conn\n");
@ -96,7 +98,7 @@ static int msc_compl_l3(struct gsm_subscriber_connection *conn, struct msgb *msg
/* If this should be kept, the conn->conn_fsm has placed a use_count */
msc_subscr_conn_put(conn);
return BSC_API_CONN_POL_ACCEPT;
return MSC_CONN_ACCEPT;
#if 0
/*
@ -105,14 +107,14 @@ static int msc_compl_l3(struct gsm_subscriber_connection *conn, struct msgb *msg
* pending transaction or ongoing operation.
*/
if (conn->silent_call)
return BSC_API_CONN_POL_ACCEPT;
if (conn->sec_operation || conn->anch_operation)
return BSC_API_CONN_POL_ACCEPT;
return MSC_CONN_ACCEPT;
if (conn->loc_operation || conn->sec_operation || conn->anch_operation)
return MSC_CONN_ACCEPT;
if (trans_has_conn(conn))
return BSC_API_CONN_POL_ACCEPT;
return MSC_CONN_ACCEPT;
LOGP(DRR, LOGL_INFO, "MSC Complete L3: Rejecting connection.\n");
return BSC_API_CONN_POL_REJECT;
return MSC_CONN_REJECT;
#endif
}

View File

@ -52,8 +52,12 @@ static int paging_cb_silent(unsigned int hooknum, unsigned int event,
switch (event) {
case GSM_PAGING_SUCCEEDED:
#if BEFORE_MSCSPLIT
/* Re-enable this log output once we can obtain this information via
* A-interface, see OS#2391. */
DEBUGPC(DLSMS, "success, using Timeslot %u on ARFCN %u\n",
conn->lchan->ts->nr, conn->lchan->ts->trx->arfcn);
#endif
conn->silent_call = 1;
msc_subscr_conn_get(conn);
/* increment lchan reference count */
@ -126,7 +130,10 @@ int gsm_silent_call_start(struct vlr_subscr *vsub, void *data, int type)
{
struct subscr_request *req;
req = subscr_request_channel(vsub, type, paging_cb_silent, data);
/* FIXME the VTY command allows selecting a silent call channel type.
* This doesn't apply to the situation after MSCSPLIT with an
* A-interface. */
req = subscr_request_conn(vsub, type, paging_cb_silent, data);
return req != NULL;
}
@ -143,8 +150,12 @@ int gsm_silent_call_stop(struct vlr_subscr *vsub)
if (!conn->silent_call)
return -EINVAL;
#if BEFORE_MSCSPLIT
/* Re-enable this log output once we can obtain this information via
* A-interface, see OS#2391. */
DEBUGPC(DLSMS, "Stopping silent call using Timeslot %u on ARFCN %u\n",
conn->lchan->ts->nr, conn->lchan->ts->trx->arfcn);
#endif
conn->silent_call = 0;
msc_subscr_conn_put(conn);

View File

@ -423,6 +423,8 @@ void append_tlv_u16(tlv_t **req_tlv, uint16_t tag, uint16_t val)
build_tlv(req_tlv, &tlv);
}
#if BEFORE_MSCSPLIT
/* We currently have no lchan information. Re-add after A-interface, see OS#2390. */
/* Append the Osmocom vendor-specific additional TLVs to a SMPP msg */
static void append_osmo_tlvs(tlv_t **req_tlv, const struct gsm_lchan *lchan)
{
@ -461,6 +463,7 @@ static void append_osmo_tlvs(tlv_t **req_tlv, const struct gsm_lchan *lchan)
(uint8_t *)vsub->imei, imei_len+1);
}
}
#endif
struct {
uint32_t smpp_status_code;
@ -680,8 +683,11 @@ static int deliver_to_esme(struct osmo_esme *esme, struct gsm_sms *sms,
memcpy(deliver.short_message, sms->user_data, deliver.sm_length);
}
#if BEFORE_MSCSPLIT
/* We currently have no lchan information. Re-add after A-interface, see OS#2390. */
if (esme->acl && esme->acl->osmocom_ext && conn->lchan)
append_osmo_tlvs(&deliver.tlv, conn->lchan);
#endif
ret = smpp_tx_deliver(esme, &deliver);
if (ret < 0)

View File

@ -553,57 +553,6 @@ DEFUN(ena_subscr_extension,
return CMD_WARNING;
}
DEFUN(ena_subscr_handover,
ena_subscr_handover_cmd,
"subscriber " SUBSCR_TYPES " ID handover BTS_NR",
SUBSCR_HELP "Handover the active connection\n"
"Number of the BTS to handover to\n")
{
int ret;
struct gsm_subscriber_connection *conn;
struct gsm_bts *bts;
struct gsm_network *gsmnet = gsmnet_from_vty(vty);
struct vlr_subscr *vsub =
get_vsub_by_argv(gsmnet, argv[0], argv[1]);
if (!vsub) {
vty_out(vty, "%% No subscriber found for %s %s.%s",
argv[0], argv[1], VTY_NEWLINE);
return CMD_WARNING;
}
conn = connection_for_subscr(vsub);
if (!conn) {
vty_out(vty, "%% No active connection for subscriber %s %s.%s",
argv[0], argv[1], VTY_NEWLINE);
vlr_subscr_put(vsub);
return CMD_WARNING;
}
bts = gsm_bts_num(gsmnet, atoi(argv[2]));
if (!bts) {
vty_out(vty, "%% BTS with number(%d) could not be found.%s",
atoi(argv[2]), VTY_NEWLINE);
vlr_subscr_put(vsub);
return CMD_WARNING;
}
/* now start the handover */
ret = bsc_handover_start(conn->lchan, bts);
if (ret != 0) {
vty_out(vty, "%% Handover failed with errno %d.%s",
ret, VTY_NEWLINE);
} else {
vty_out(vty, "%% Handover started from %s",
gsm_lchan_name(conn->lchan));
vty_out(vty, " to %s.%s", gsm_lchan_name(conn->ho_lchan),
VTY_NEWLINE);
}
vlr_subscr_put(vsub);
return CMD_SUCCESS;
}
#define A3A8_ALG_TYPES "(none|xor|comp128v1)"
#define A3A8_ALG_HELP \
"Use No A3A8 algorithm\n" \
@ -652,9 +601,7 @@ static int scall_cbfn(unsigned int subsys, unsigned int signal,
switch (signal) {
case S_SCALL_SUCCESS:
vty_out(vty, "%% silent call on ARFCN %u timeslot %u%s",
sigdata->conn->lchan->ts->trx->arfcn, sigdata->conn->lchan->ts->nr,
VTY_NEWLINE);
vty_out(vty, "%% silent call success%s", VTY_NEWLINE);
break;
case S_SCALL_EXPIRED:
vty_out(vty, "%% silent call expired paging%s", VTY_NEWLINE);
@ -670,7 +617,6 @@ DEFUN(show_stats,
{
struct gsm_network *net = gsmnet_from_vty(vty);
openbsc_vty_print_statistics(vty, net);
vty_out(vty, "Location Update : %lu attach, %lu normal, %lu periodic%s",
net->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_ATTACH].current,
net->msc_ctrs->ctr[MSC_CTR_LOC_UPDATE_TYPE_NORMAL].current,
@ -1055,7 +1001,6 @@ int bsc_vty_init_extra(void)
install_element(ENABLE_NODE, &ena_subscr_extension_cmd);
install_element(ENABLE_NODE, &ena_subscr_authorized_cmd);
install_element(ENABLE_NODE, &ena_subscr_a3a8_cmd);
install_element(ENABLE_NODE, &ena_subscr_handover_cmd);
install_element(ENABLE_NODE, &subscriber_purge_cmd);
install_element(ENABLE_NODE, &smsqueue_trigger_cmd);
install_element(ENABLE_NODE, &smsqueue_max_cmd);

View File

@ -32,7 +32,6 @@ bsc_test_SOURCES = \
bsc_test_LDADD = \
$(top_builddir)/src/libbsc/libbsc.a \
$(top_builddir)/src/libmsc/libmsc.a \
$(top_builddir)/src/libcommon-cs/libcommon-cs.a \
$(top_builddir)/src/libmgcp/libmgcp.a \
$(top_builddir)/src/libtrau/libtrau.a \

View File

@ -24,7 +24,6 @@ channel_test_SOURCES = \
$(NULL)
channel_test_LDADD = \
$(top_builddir)/src/libmsc/libmsc.a \
$(top_builddir)/src/libbsc/libbsc.a \
$(top_builddir)/src/libvlr/libvlr.a \
$(top_builddir)/src/libcommon-cs/libcommon-cs.a \