summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilipp Maier <pmaier@sysmocom.de>2017-06-08 17:22:07 +0200
committerNeels Hofmeyr <nhofmeyr@sysmocom.de>2017-06-18 17:50:09 +0200
commit41c0e21364974d4dca2a28c3c70dec76a1c9269e (patch)
treec79e6d3a6a45c5e8736a62bb1732303bf9dcbdf5
parent456d3c44d1adf0ffe0f9684f57bddf7575479e5c (diff)
a_iface_bssap: clear lingering subscriber connections on reset
When the BSC is vanishing, the subscriber connections will stay active until the MSC is instructed via tha A interface to clear the connections. Unfortunately, this will most likely not be the case because the BSC will most likeley have lost all its state and does not know about the old connections anymore. This patch fixes the problem by looping through the list with the active gsm subscriber connections and clearing them manually when the reset from the BSC is received. Only connections by the bsc who actually executes the reset are affected. Connections from other BSCs will not be touched.
-rw-r--r--openbsc/include/openbsc/gsm_data.h3
-rw-r--r--openbsc/src/libmsc/a_iface_bssap.c28
2 files changed, 29 insertions, 2 deletions
diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h
index 6d82702..b07cac4 100644
--- a/openbsc/include/openbsc/gsm_data.h
+++ b/openbsc/include/openbsc/gsm_data.h
@@ -12,12 +12,14 @@
#include <osmocom/core/stats.h>
#include <osmocom/crypt/auth.h>
+#include <osmocom/sigtran/sccp_sap.h>
#include <openbsc/common.h>
#include <openbsc/rest_octets.h>
#include <openbsc/common_cs.h>
#include <openbsc/mgcpgw_client.h>
+
/** annotations for msgb ownership */
#define __uses
@@ -205,6 +207,7 @@ struct gsm_subscriber_connection {
struct {
struct osmo_sccp_user *scu;
+ struct osmo_sccp_addr bsc_addr;
int conn_id;
} a;
};
diff --git a/openbsc/src/libmsc/a_iface_bssap.c b/openbsc/src/libmsc/a_iface_bssap.c
index bd38ba5..2e2ed23 100644
--- a/openbsc/src/libmsc/a_iface_bssap.c
+++ b/openbsc/src/libmsc/a_iface_bssap.c
@@ -42,7 +42,8 @@ static LLIST_HEAD(bsc_addr_list);
*/
/* Allocate a new subscriber connection */
-static struct gsm_subscriber_connection *subscr_conn_allocate_a(struct gsm_network *network, struct ue_conn_ctx *ue,
+static struct gsm_subscriber_connection *subscr_conn_allocate_a(struct a_conn_info *a_conn_info,
+ struct gsm_network *network, struct ue_conn_ctx *ue,
uint16_t lac, struct osmo_sccp_user *scu, int conn_id)
{
struct gsm_subscriber_connection *conn;
@@ -62,6 +63,10 @@ static struct gsm_subscriber_connection *subscr_conn_allocate_a(struct gsm_netwo
conn->a.conn_id = conn_id;
conn->a.scu = scu;
+ /* Also backup the calling address of the BSC, this allows us to
+ * identify later which BSC is responsible for this subscriber connection */
+ memcpy(&conn->a.bsc_addr, a_conn_info->calling_addr, sizeof(conn->a.bsc_addr));
+
llist_add_tail(&conn->entry, &network->subscr_conns);
LOGP(DMSC, LOGL_NOTICE, "A-Interface subscriber connection successfully allocated!\n");
return conn;
@@ -89,6 +94,22 @@ struct gsm_subscriber_connection *subscr_conn_lookup_a(struct gsm_network *netwo
return NULL;
}
+/* Clear oprphand subscriber connections (called by bssmap_handle_reset()) */
+static void subscr_conn_clear_all(struct a_conn_info *a_conn_info)
+{
+ struct gsm_subscriber_connection *conn;
+ struct gsm_subscriber_connection *conn_temp;
+ struct gsm_network *network = a_conn_info->network;
+
+ llist_for_each_entry_safe(conn, conn_temp, &network->subscr_conns, entry) {
+ if (conn->via_ran == RAN_GERAN_A
+ && memcmp(a_conn_info->calling_addr, &conn->a.bsc_addr, sizeof(conn->a.bsc_addr)) == 0) {
+ LOGP(DMSC, LOGL_NOTICE, "Dropping old subscriber connection (conn_id %i)\n", conn->a.conn_id);
+ msc_clear_request(conn, GSM48_CC_CAUSE_SWITCH_CONG);
+ }
+ }
+}
+
/*
* BSSMAP handling for UNITDATA
*/
@@ -103,6 +124,9 @@ static void bssmap_handle_reset(struct osmo_sccp_user *scu, struct a_conn_info *
LOGP(DMSC, LOGL_NOTICE, "Rx RESET from BSC %s\n", osmo_sccp_addr_dump(a_conn_info->calling_addr));
osmo_sccp_tx_unitdata_msg(scu, a_conn_info->called_addr, a_conn_info->calling_addr, gsm0808_create_reset_ack());
+ /* Make sure all orphand subscriber connections will be cleard */
+ subscr_conn_clear_all(a_conn_info);
+
/* Check if we know this BSC already, if yes, refresh its item */
llist_for_each_entry(known_addr, &bsc_addr_list, list) {
if (memcmp(&known_addr->calling_addr, a_conn_info->calling_addr, sizeof(*a_conn_info->calling_addr)) ==
@@ -300,7 +324,7 @@ static int bssmap_handle_l3_compl(struct osmo_sccp_user *scu, struct a_conn_info
/* Create new subscriber context */
ue = ue_conn_ctx_alloc(a_conn_info->calling_addr, a_conn_info->conn_id);
- conn = subscr_conn_allocate_a(network, ue, lac, scu, a_conn_info->conn_id);
+ conn = subscr_conn_allocate_a(a_conn_info, network, ue, lac, scu, a_conn_info->conn_id);
/* Handover location update to the MSC code */
/* msc_compl_l3() takes ownership of dtap_msg