aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2012-09-11 18:02:46 +0200
committerHolger Hans Peter Freyther <zecke@selfish.org>2012-09-11 18:02:46 +0200
commitca5d2111131101f7b8df40207b4c597b0e53f2cb (patch)
treeca2cb035b0b5ea736e6e9a0713d267837dd09db1
parentc11889f3dd305055dc7c6f4dd6c68d328eb6f2bf (diff)
parent31b245b91afa21fbf6907c0f08b548a210d7ac70 (diff)
Merge branch 'feature/local-mscs'
-rw-r--r--openbsc/include/openbsc/osmo_msc_data.h8
-rw-r--r--openbsc/src/osmo-bsc/osmo_bsc_filter.c25
-rw-r--r--openbsc/src/osmo-bsc/osmo_bsc_msc.c1
-rw-r--r--openbsc/src/osmo-bsc/osmo_bsc_vty.c34
4 files changed, 67 insertions, 1 deletions
diff --git a/openbsc/include/openbsc/osmo_msc_data.h b/openbsc/include/openbsc/osmo_msc_data.h
index 0f3f92724..0bda66225 100644
--- a/openbsc/include/openbsc/osmo_msc_data.h
+++ b/openbsc/include/openbsc/osmo_msc_data.h
@@ -35,12 +35,20 @@ struct gsm_audio_support {
ver : 7;
};
+enum {
+ MSC_CON_TYPE_NORMAL,
+ MSC_CON_TYPE_LOCAL,
+};
+
struct osmo_msc_data {
struct llist_head entry;
/* Back pointer */
struct gsm_network *network;
+ int allow_emerg;
+ int type;
+
/* Connection data */
char *bsc_token;
int ping_timeout;
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_filter.c b/openbsc/src/osmo-bsc/osmo_bsc_filter.c
index 200360ac9..fa7f2d928 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_filter.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_filter.c
@@ -106,6 +106,21 @@ static int handle_page_resp(struct gsm_subscriber_connection *conn, struct msgb
subscr_put(subscr);
return 0;
}
+
+static int is_cm_service_for_emerg(struct msgb *msg)
+{
+ struct gsm48_service_request *cm;
+ struct gsm48_hdr *gh = msgb_l3(msg);
+
+ if (msgb_l3len(msg) < sizeof(*gh) + sizeof(*cm)) {
+ LOGP(DMSC, LOGL_ERROR, "CM ServiceRequest does not fit.\n");
+ return 0;
+ }
+
+ cm = (struct gsm48_service_request *) &gh->data[0];
+ return cm->cm_service_type == GSM48_CMSERV_EMERGENCY;
+}
+
struct osmo_msc_data *bsc_find_msc(struct gsm_subscriber_connection *conn,
struct msgb *msg)
{
@@ -115,6 +130,7 @@ struct osmo_msc_data *bsc_find_msc(struct gsm_subscriber_connection *conn,
struct osmo_bsc_data *bsc;
struct osmo_msc_data *msc, *pag_msc;
struct gsm_subscriber *subscr;
+ int is_emerg = 0;
bsc = conn->bts->network->bsc_data;
@@ -135,13 +151,20 @@ struct osmo_msc_data *bsc_find_msc(struct gsm_subscriber_connection *conn,
*/
if (pdisc == GSM48_PDISC_RR && mtype == GSM48_MT_RR_PAG_RESP)
goto paging;
- else
+ else if (pdisc == GSM48_PDISC_MM && mtype == GSM48_MT_MM_CM_SERV_REQ) {
+ is_emerg = is_cm_service_for_emerg(msg);
+ goto round_robin;
+ } else
goto round_robin;
round_robin:
llist_for_each_entry(msc, &bsc->mscs, entry) {
if (!msc->msc_con->is_authenticated)
continue;
+ if (!is_emerg && msc->type != MSC_CON_TYPE_NORMAL)
+ continue;
+ if (is_emerg && !msc->allow_emerg)
+ continue;
/* force round robin by moving it to the end */
llist_move_tail(&msc->entry, &bsc->mscs);
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_msc.c b/openbsc/src/osmo-bsc/osmo_bsc_msc.c
index 617a59aee..55532dbd4 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_msc.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_msc.c
@@ -492,6 +492,7 @@ struct osmo_msc_data *osmo_msc_data_alloc(struct gsm_network *net, int nr)
msc_data->rtp_base = 4000;
msc_data->nr = nr;
+ msc_data->allow_emerg = 1;
return msc_data;
}
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_vty.c b/openbsc/src/osmo-bsc/osmo_bsc_vty.c
index 04f9bf440..9f1eb6969 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_vty.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_vty.c
@@ -114,6 +114,11 @@ static void write_msc(struct vty *vty, struct osmo_msc_data *msc)
llist_for_each_entry(dest, &msc->dests, list)
vty_out(vty, " dest %s %d %d%s", dest->ip, dest->port,
dest->dscp, VTY_NEWLINE);
+
+ vty_out(vty, " type %s%s", msc->type == MSC_CON_TYPE_NORMAL ?
+ "normal" : "local", VTY_NEWLINE);
+ vty_out(vty, " allow-emergency %s%s", msc->allow_emerg ?
+ "allow" : "deny", VTY_NEWLINE);
}
static int config_write_msc(struct vty *vty)
@@ -332,6 +337,33 @@ DEFUN(cfg_net_msc_welcome_ussd,
return CMD_SUCCESS;
}
+DEFUN(cfg_net_msc_type,
+ cfg_net_msc_type_cmd,
+ "type (normal|local)",
+ "Select the MSC type\n"
+ "Plain GSM MSC\n" "Special MSC for local call routing\n")
+{
+ struct osmo_msc_data *data = osmo_msc_data(vty);
+
+ if (strcmp(argv[0], "normal") == 0)
+ data->type = MSC_CON_TYPE_NORMAL;
+ else if (strcmp(argv[0], "local") == 0)
+ data->type = MSC_CON_TYPE_LOCAL;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_net_msc_emerg,
+ cfg_net_msc_emerg_cmd,
+ "allow-emergency (allow|deny)",
+ "Allow CM ServiceRequests with type emergency\n"
+ "Allow\n" "Deny\n")
+{
+ struct osmo_msc_data *data = osmo_msc_data(vty);
+ data->allow_emerg = strcmp("allow", argv[0]) == 0;
+ return CMD_SUCCESS;
+}
+
DEFUN(cfg_net_bsc_mid_call_text,
cfg_net_bsc_mid_call_text_cmd,
"mid-call-text .TEXT",
@@ -419,6 +451,8 @@ int bsc_vty_init_extra(void)
install_element(MSC_NODE, &cfg_net_msc_ping_time_cmd);
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_type_cmd);
+ install_element(MSC_NODE, &cfg_net_msc_emerg_cmd);
install_element_ve(&show_statistics_cmd);
install_element_ve(&show_mscs_cmd);