aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--openbsc/include/openbsc/osmo_bsc.h6
-rw-r--r--openbsc/include/openbsc/vty.h1
-rw-r--r--openbsc/src/libcommon/common_vty.c2
-rw-r--r--openbsc/src/osmo-bsc/osmo_bsc_api.c10
-rw-r--r--openbsc/src/osmo-bsc/osmo_bsc_bssap.c21
-rw-r--r--openbsc/src/osmo-bsc/osmo_bsc_filter.c88
-rw-r--r--openbsc/src/osmo-bsc/osmo_bsc_sccp.c21
-rw-r--r--openbsc/src/osmo-bsc/osmo_bsc_vty.c79
8 files changed, 174 insertions, 54 deletions
diff --git a/openbsc/include/openbsc/osmo_bsc.h b/openbsc/include/openbsc/osmo_bsc.h
index ffa0b5747..0bc39dc1e 100644
--- a/openbsc/include/openbsc/osmo_bsc.h
+++ b/openbsc/include/openbsc/osmo_bsc.h
@@ -32,13 +32,15 @@ struct bsc_api *osmo_bsc_api();
int bsc_queue_for_msc(struct osmo_bsc_sccp_con *conn, struct msgb *msg);
int bsc_open_connection(struct osmo_bsc_sccp_con *sccp, struct msgb *msg);
-int bsc_create_new_connection(struct gsm_subscriber_connection *conn);
+int bsc_create_new_connection(struct gsm_subscriber_connection *conn,
+ struct osmo_msc_data *msc);
int bsc_delete_connection(struct osmo_bsc_sccp_con *sccp);
+struct osmo_msc_data *bsc_find_msc(struct gsm_subscriber_connection *conn, struct msgb *);
int bsc_scan_bts_msg(struct gsm_subscriber_connection *conn, struct msgb *msg);
int bsc_scan_msc_msg(struct gsm_subscriber_connection *conn, struct msgb *msg);
-int bsc_handle_udt(struct gsm_network *net, struct bsc_msc_connection *conn, struct msgb *msg, unsigned int length);
+int bsc_handle_udt(struct osmo_msc_data *msc, struct msgb *msg, unsigned int length);
int bsc_handle_dt1(struct osmo_bsc_sccp_con *conn, struct msgb *msg, unsigned int len);
int bsc_ctrl_cmds_install();
diff --git a/openbsc/include/openbsc/vty.h b/openbsc/include/openbsc/vty.h
index 7d93a16c1..e3f318206 100644
--- a/openbsc/include/openbsc/vty.h
+++ b/openbsc/include/openbsc/vty.h
@@ -34,6 +34,7 @@ enum bsc_vty_node {
TRUNK_NODE,
PGROUP_NODE,
MNCC_INT_NODE,
+ BSC_NODE,
};
extern int bsc_vty_is_config_node(struct vty *vty, int node);
diff --git a/openbsc/src/libcommon/common_vty.c b/openbsc/src/libcommon/common_vty.c
index 5958df287..0fd4f43c1 100644
--- a/openbsc/src/libcommon/common_vty.c
+++ b/openbsc/src/libcommon/common_vty.c
@@ -148,6 +148,7 @@ gDEFUN(ournode_exit,
case GBPROXY_NODE:
case SGSN_NODE:
case NAT_NODE:
+ case BSC_NODE:
vty->node = CONFIG_NODE;
vty->index = NULL;
break;
@@ -195,6 +196,7 @@ gDEFUN(ournode_end,
case PGROUP_NODE:
case MSC_NODE:
case MNCC_INT_NODE:
+ case BSC_NODE:
vty_config_unlock(vty);
vty->node = ENABLE_NODE;
vty->index = NULL;
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_api.c b/openbsc/src/osmo-bsc/osmo_bsc_api.c
index 04305c20f..7acb00afc 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_api.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_api.c
@@ -89,13 +89,21 @@ static int bsc_compl_l3(struct gsm_subscriber_connection *conn, struct msgb *msg
uint16_t chosen_channel)
{
struct msgb *resp;
+ struct osmo_msc_data *msc;
uint16_t network_code;
uint16_t country_code;
LOGP(DMSC, LOGL_INFO, "Tx MSC COMPL L3\n");
+ /* find the MSC link we want to use */
+ msc = bsc_find_msc(conn, msg);
+ if (!msc) {
+ LOGP(DMSC, LOGL_ERROR, "Failed to find a MSC for a connection.\n");
+ return -1;
+ }
+
/* allocate resource for a new connection */
- if (bsc_create_new_connection(conn) != 0)
+ if (bsc_create_new_connection(conn, msc) != 0)
return BSC_API_CONN_POL_REJECT;
network_code = get_network_code_for_msc(conn->sccp_con->msc);
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_bssap.c b/openbsc/src/osmo-bsc/osmo_bsc_bssap.c
index f17db3225..684a6c186 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_bssap.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_bssap.c
@@ -98,7 +98,7 @@ enum gsm48_chan_mode gsm88_to_chan_mode(enum gsm0808_permitted_speech speech)
return GSM48_CMODE_SPEECH_AMR;
}
-static int bssmap_handle_reset_ack(struct gsm_network *net,
+static int bssmap_handle_reset_ack(struct osmo_msc_data *msc,
struct msgb *msg, unsigned int length)
{
LOGP(DMSC, LOGL_NOTICE, "Reset ACK from MSC\n");
@@ -106,7 +106,7 @@ static int bssmap_handle_reset_ack(struct gsm_network *net,
}
/* GSM 08.08 ยง 3.2.1.19 */
-static int bssmap_handle_paging(struct gsm_network *net,
+static int bssmap_handle_paging(struct osmo_msc_data *msc,
struct msgb *msg, unsigned int payload_length)
{
struct gsm_subscriber *subscr;
@@ -167,7 +167,7 @@ static int bssmap_handle_paging(struct gsm_network *net,
LOGP(DMSC, LOGL_ERROR, "eMLPP is not handled\n");
}
- subscr = subscr_get_or_create(net, mi_string);
+ subscr = subscr_get_or_create(msc->network, mi_string);
if (!subscr) {
LOGP(DMSC, LOGL_ERROR, "Failed to allocate a subscriber for %s\n", mi_string);
return -1;
@@ -177,7 +177,7 @@ static int bssmap_handle_paging(struct gsm_network *net,
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);
- paging_request(net, subscr, chan_needed, NULL, NULL);
+ paging_request(msc->network, subscr, chan_needed, NULL, msc);
return 0;
}
@@ -395,7 +395,7 @@ reject:
return -1;
}
-static int bssmap_rcvmsg_udt(struct gsm_network *net,
+static int bssmap_rcvmsg_udt(struct osmo_msc_data *msc,
struct msgb *msg, unsigned int length)
{
int ret = 0;
@@ -410,11 +410,11 @@ static int bssmap_rcvmsg_udt(struct gsm_network *net,
switch (msg->l4h[0]) {
case BSS_MAP_MSG_RESET_ACKNOWLEDGE:
- ret = bssmap_handle_reset_ack(net, msg, length);
+ ret = bssmap_handle_reset_ack(msc, msg, length);
break;
case BSS_MAP_MSG_PAGING:
- if (bsc_grace_allow_new_connection(net))
- ret = bssmap_handle_paging(net, msg, length);
+ if (bsc_grace_allow_new_connection(msc->network))
+ ret = bssmap_handle_paging(msc, msg, length);
break;
}
@@ -499,8 +499,7 @@ static int dtap_rcvmsg(struct osmo_bsc_sccp_con *conn,
return gsm0808_submit_dtap(conn->conn, gsm48, header->link_id, 1);
}
-int bsc_handle_udt(struct gsm_network *network,
- struct bsc_msc_connection *conn,
+int bsc_handle_udt(struct osmo_msc_data *msc,
struct msgb *msgb, unsigned int length)
{
struct bssmap_header *bs;
@@ -520,7 +519,7 @@ int bsc_handle_udt(struct gsm_network *network,
switch (bs->type) {
case BSSAP_MSG_BSS_MANAGEMENT:
msgb->l4h = &msgb->l3h[sizeof(*bs)];
- bssmap_rcvmsg_udt(network, msgb, length - sizeof(*bs));
+ bssmap_rcvmsg_udt(msc, msgb, length - sizeof(*bs));
break;
default:
LOGP(DMSC, LOGL_NOTICE, "Unimplemented msg type: %s\n",
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_filter.c b/openbsc/src/osmo-bsc/osmo_bsc_filter.c
index 9d6909caa..200360ac9 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_filter.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_filter.c
@@ -53,8 +53,9 @@ static void handle_lu_request(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)
+/* extract a subscriber from the paging response */
+static struct gsm_subscriber *extract_sub(struct gsm_subscriber_connection *conn,
+ struct msgb *msg)
{
uint8_t mi_type;
char mi_string[GSM48_MI_SIZE];
@@ -64,7 +65,7 @@ static int handle_page_resp(struct gsm_subscriber_connection *conn, struct msgb
if (msgb_l3len(msg) < sizeof(*gh) + sizeof(*resp)) {
LOGP(DMSC, LOGL_ERROR, "PagingResponse too small: %u\n", msgb_l3len(msg));
- return -1;
+ return NULL;
}
gh = msgb_l3(msg);
@@ -88,6 +89,14 @@ static int handle_page_resp(struct gsm_subscriber_connection *conn, struct msgb
break;
}
+ return subscr;
+}
+
+/* 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);
+
if (!subscr) {
LOGP(DMSC, LOGL_ERROR, "Non active subscriber got paged.\n");
return -1;
@@ -97,6 +106,79 @@ static int handle_page_resp(struct gsm_subscriber_connection *conn, struct msgb
subscr_put(subscr);
return 0;
}
+struct osmo_msc_data *bsc_find_msc(struct gsm_subscriber_connection *conn,
+ struct msgb *msg)
+{
+ struct gsm48_hdr *gh;
+ int8_t pdisc;
+ uint8_t mtype;
+ struct osmo_bsc_data *bsc;
+ struct osmo_msc_data *msc, *pag_msc;
+ struct gsm_subscriber *subscr;
+
+ bsc = conn->bts->network->bsc_data;
+
+ if (msgb_l3len(msg) < sizeof(*gh)) {
+ LOGP(DMSC, LOGL_ERROR, "There is no GSM48 header here.\n");
+ return NULL;
+ }
+
+ gh = msgb_l3(msg);
+ pdisc = gh->proto_discr & 0x0f;
+ mtype = gh->msg_type & 0xbf;
+
+ /*
+ * We are asked to select a MSC here but they are not equal. We
+ * want to respond to a paging request on the MSC where we got the
+ * request from. This is where we need to decide where this connection
+ * will go.
+ */
+ if (pdisc == GSM48_PDISC_RR && mtype == GSM48_MT_RR_PAG_RESP)
+ goto paging;
+ else
+ goto round_robin;
+
+round_robin:
+ llist_for_each_entry(msc, &bsc->mscs, entry) {
+ if (!msc->msc_con->is_authenticated)
+ continue;
+
+ /* force round robin by moving it to the end */
+ llist_move_tail(&msc->entry, &bsc->mscs);
+ return msc;
+ }
+
+ return NULL;
+
+paging:
+ subscr = extract_sub(conn, msg);
+
+ if (!subscr) {
+ LOGP(DMSC, LOGL_ERROR, "Got paged but no subscriber found.\n");
+ return NULL;
+ }
+
+ pag_msc = paging_get_data(conn->bts, subscr);
+ subscr_put(subscr);
+
+ llist_for_each_entry(msc, &bsc->mscs, entry) {
+ if (msc != pag_msc)
+ continue;
+
+ /*
+ * We don't check if the MSC is connected. In case it
+ * is not the connection will be dropped.
+ */
+
+ /* force round robin by moving it to the end */
+ llist_move_tail(&msc->entry, &bsc->mscs);
+ return msc;
+ }
+
+ LOGP(DMSC, LOGL_ERROR, "Got paged but no request found.\n");
+ return NULL;
+}
+
/**
* This is used to scan a message for extra functionality of the BSC. This
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_sccp.c b/openbsc/src/osmo-bsc/osmo_bsc_sccp.c
index cc4eedfb8..37eb1b799 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_sccp.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_sccp.c
@@ -161,7 +161,7 @@ static int msc_sccp_accept(struct sccp_connection *connection, void *data)
static int msc_sccp_read(struct msgb *msgb, unsigned int length, void *data)
{
struct osmo_msc_data *msc = (struct osmo_msc_data *) msgb->cb[0];
- return bsc_handle_udt(msc->network, msc->msc_con, msgb, length);
+ return bsc_handle_udt(msc, msgb, length);
}
int bsc_queue_for_msc(struct osmo_bsc_sccp_con *conn, struct msgb *msg)
@@ -187,22 +187,19 @@ int bsc_queue_for_msc(struct osmo_bsc_sccp_con *conn, struct msgb *msg)
return 0;
}
-int bsc_create_new_connection(struct gsm_subscriber_connection *conn)
+int bsc_create_new_connection(struct gsm_subscriber_connection *conn,
+ struct osmo_msc_data *msc)
{
struct gsm_network *net;
- struct osmo_msc_data *msc;
struct osmo_bsc_sccp_con *bsc_con;
struct sccp_connection *sccp;
net = conn->bts->network;
- msc = osmo_msc_data_find(net, 0);
- if (!msc) {
- LOGP(DMSC, LOGL_ERROR, "Failed to select a MSC.\n");
- return -1;
- }
+ /* This should not trigger */
if (!msc->msc_con->is_authenticated) {
- LOGP(DMSC, LOGL_ERROR, "Not connected to a MSC. Not forwarding data.\n");
+ LOGP(DMSC, LOGL_ERROR,
+ "How did this happen? MSC is not connected. Dropping.\n");
return -1;
}
@@ -272,8 +269,10 @@ static void bsc_close_connections(struct bsc_msc_connection *msc_con)
{
struct osmo_bsc_sccp_con *con, *tmp;
- llist_for_each_entry_safe(con, tmp, &active_connections, entry)
- bsc_sccp_force_free(con);
+ llist_for_each_entry_safe(con, tmp, &active_connections, entry) {
+ if (con->msc->msc_con == msc_con)
+ bsc_sccp_force_free(con);
+ }
}
static int handle_msc_signal(unsigned int subsys, unsigned int signal,
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_vty.c b/openbsc/src/osmo-bsc/osmo_bsc_vty.c
index 26f92292a..04f9bf440 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_vty.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_vty.c
@@ -39,6 +39,12 @@ static struct osmo_msc_data *osmo_msc_data(struct vty *vty)
return osmo_msc_data_find(bsc_gsmnet, (int) vty->index);
}
+static struct cmd_node bsc_node = {
+ BSC_NODE,
+ "%s(bsc)#",
+ 1,
+};
+
static struct cmd_node msc_node = {
MSC_NODE,
"%s(config-msc)# ",
@@ -46,9 +52,9 @@ static struct cmd_node msc_node = {
};
DEFUN(cfg_net_msc, cfg_net_msc_cmd,
- "msc", "Configure MSC details")
+ "msc [<0-1000>]", "Configure MSC details\n" "MSC connection to configure\n")
{
- int index = 0;
+ int index = argc == 1 ? atoi(argv[0]) : 0;
struct osmo_msc_data *msc;
msc = osmo_msc_data_alloc(bsc_gsmnet, index);
@@ -62,11 +68,18 @@ DEFUN(cfg_net_msc, cfg_net_msc_cmd,
return CMD_SUCCESS;
}
+DEFUN(cfg_net_bsc, cfg_net_bsc_cmd,
+ "bsc", "Configure BSC\n")
+{
+ vty->node = BSC_NODE;
+ return CMD_SUCCESS;
+}
+
static void write_msc(struct vty *vty, struct osmo_msc_data *msc)
{
struct bsc_msc_dest *dest;
- vty_out(vty, "msc%s", VTY_NEWLINE);
+ vty_out(vty, "msc %d%s", msc->nr, VTY_NEWLINE);
if (msc->bsc_token)
vty_out(vty, " token %s%s", msc->bsc_token, VTY_NEWLINE);
if (msc->core_ncc != -1)
@@ -111,6 +124,14 @@ static int config_write_msc(struct vty *vty)
llist_for_each_entry(msc, &bsc->mscs, entry)
write_msc(vty, msc);
+ return CMD_SUCCESS;
+}
+
+static int config_write_bsc(struct vty *vty)
+{
+ struct osmo_bsc_data *bsc = osmo_bsc_data(vty);
+
+ vty_out(vty, "bsc%s", VTY_NEWLINE);
if (bsc->mid_call_txt)
vty_out(vty, " mid-call-text %s%s", bsc->mid_call_txt, VTY_NEWLINE);
vty_out(vty, " mid-call-timeout %d%s", bsc->mid_call_timeout, VTY_NEWLINE);
@@ -296,8 +317,23 @@ DEFUN(cfg_net_msc_pong_time,
return CMD_SUCCESS;
}
-DEFUN(cfg_net_msc_mid_call_text,
- cfg_net_msc_mid_call_text_cmd,
+DEFUN(cfg_net_msc_welcome_ussd,
+ cfg_net_msc_welcome_ussd_cmd,
+ "bsc-welcome-text .TEXT",
+ "Set the USSD notification to be sent.\n" "Text to be sent\n")
+{
+ struct osmo_msc_data *data = osmo_msc_data(vty);
+ char *str = argv_concat(argv, argc, 0);
+ if (!str)
+ return CMD_WARNING;
+
+ bsc_replace_string(osmo_bsc_data(vty), &data->ussd_welcome_txt, str);
+ talloc_free(str);
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_net_bsc_mid_call_text,
+ cfg_net_bsc_mid_call_text_cmd,
"mid-call-text .TEXT",
"Set the USSD notifcation to be send.\n" "Text to be sent\n")
{
@@ -311,8 +347,8 @@ DEFUN(cfg_net_msc_mid_call_text,
return CMD_SUCCESS;
}
-DEFUN(cfg_net_msc_mid_call_timeout,
- cfg_net_msc_mid_call_timeout_cmd,
+DEFUN(cfg_net_bsc_mid_call_timeout,
+ cfg_net_bsc_mid_call_timeout_cmd,
"mid-call-timeout NR",
"Switch from Grace to Off in NR seconds.\n" "Timeout in seconds\n")
{
@@ -321,21 +357,6 @@ DEFUN(cfg_net_msc_mid_call_timeout,
return CMD_SUCCESS;
}
-DEFUN(cfg_net_msc_welcome_ussd,
- cfg_net_msc_welcome_ussd_cmd,
- "bsc-welcome-text .TEXT",
- "Set the USSD notification to be sent.\n" "Text to be sent\n")
-{
- struct osmo_msc_data *data = osmo_msc_data(vty);
- char *str = argv_concat(argv, argc, 0);
- if (!str)
- return CMD_WARNING;
-
- bsc_replace_string(osmo_bsc_data(vty), &data->ussd_welcome_txt, str);
- talloc_free(str);
- return CMD_SUCCESS;
-}
-
DEFUN(cfg_net_rf_socket,
cfg_net_rf_socket_cmd,
"bsc-rf-socket PATH",
@@ -376,6 +397,16 @@ DEFUN(show_mscs,
int bsc_vty_init_extra(void)
{
install_element(CONFIG_NODE, &cfg_net_msc_cmd);
+ install_element(CONFIG_NODE, &cfg_net_bsc_cmd);
+
+ install_node(&bsc_node, config_write_bsc);
+ install_default(BSC_NODE);
+ install_element(BSC_NODE, &cfg_net_bsc_mid_call_text_cmd);
+ install_element(BSC_NODE, &cfg_net_bsc_mid_call_timeout_cmd);
+ install_element(BSC_NODE, &cfg_net_rf_socket_cmd);
+
+
+
install_node(&msc_node, config_write_msc);
install_default(MSC_NODE);
install_element(MSC_NODE, &cfg_net_bsc_token_cmd);
@@ -389,10 +420,6 @@ int bsc_vty_init_extra(void)
install_element(MSC_NODE, &cfg_net_msc_pong_time_cmd);
install_element(MSC_NODE, &cfg_net_msc_welcome_ussd_cmd);
- install_element(MSC_NODE, &cfg_net_msc_mid_call_text_cmd);
- install_element(MSC_NODE, &cfg_net_msc_mid_call_timeout_cmd);
- install_element(MSC_NODE, &cfg_net_rf_socket_cmd);
-
install_element_ve(&show_statistics_cmd);
install_element_ve(&show_mscs_cmd);