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.

Change-Id: Ic2b43b937d08a6dea4fe70dbc3eb722323338dc1
This commit is contained in:
Philipp Maier 2017-06-08 17:22:07 +02:00 committed by Neels Hofmeyr
parent d46c75dac9
commit 554488dee8
2 changed files with 29 additions and 2 deletions

View File

@ -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;
};

View File

@ -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