aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc
diff options
context:
space:
mode:
Diffstat (limited to 'openbsc')
-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 6d827029e..b07cac4a8 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 bd38ba5f2..2e2ed237b 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