diff options
author | Holger Hans Peter Freyther <zecke@selfish.org> | 2012-09-11 18:00:59 +0200 |
---|---|---|
committer | Holger Hans Peter Freyther <zecke@selfish.org> | 2012-09-11 18:00:59 +0200 |
commit | c11889f3dd305055dc7c6f4dd6c68d328eb6f2bf (patch) | |
tree | 382d5d0ff51421c424ecbc179402a15f53eecbbe | |
parent | ffd6856249ae3de42d17a2146a3c03e0597b2c53 (diff) | |
parent | f67d9a9bed2dd79c42571599e3713f3f3c6a1fb6 (diff) |
Merge branch 'feature/multiple-msc-connections'
-rw-r--r-- | openbsc/include/openbsc/osmo_bsc.h | 6 | ||||
-rw-r--r-- | openbsc/include/openbsc/vty.h | 1 | ||||
-rw-r--r-- | openbsc/src/libcommon/common_vty.c | 2 | ||||
-rw-r--r-- | openbsc/src/osmo-bsc/osmo_bsc_api.c | 10 | ||||
-rw-r--r-- | openbsc/src/osmo-bsc/osmo_bsc_bssap.c | 21 | ||||
-rw-r--r-- | openbsc/src/osmo-bsc/osmo_bsc_filter.c | 88 | ||||
-rw-r--r-- | openbsc/src/osmo-bsc/osmo_bsc_sccp.c | 21 | ||||
-rw-r--r-- | openbsc/src/osmo-bsc/osmo_bsc_vty.c | 79 |
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); |