osmo-bsc: Handle RESET/RESET-ACK properly

Improve the way the BSC executes its RESET/RESET-ACK sequence.
Currently only a simple bool variable serves as a state holder.
We set this variable to true when we receive the RESET-ACK
message. Unfortunately no further checking is done. This
patch replaces the old mechanism with a more elaborated
implementation which also detects a loss of the connection
and makes sure to reconnect properly afterwards. Also the
all open connections are closed on connection loss

Change-Id: I876319b15103cc395e74597a52ce4d1a934915f4
This commit is contained in:
Philipp Maier 2017-06-06 14:31:36 +02:00 committed by Neels Hofmeyr
parent 813a230b55
commit 615db796d3
11 changed files with 349 additions and 54 deletions

View File

@ -67,6 +67,7 @@ noinst_HEADERS = \
openbscdefines.h \
osmo_bsc.h \
osmo_bsc_grace.h \
osmo_bsc_reset.h \
osmo_bsc_rf.h \
osmo_msc.h \
osmo_bsc_sigtran.h \

View File

@ -61,7 +61,9 @@ struct bsc_msc_connection {
struct osmo_sccp_addr g_calling_addr;
struct osmo_sccp_addr g_called_addr;
struct osmo_timer_list msc_reset_timer;
bool reset_ack;
struct osmo_fsm_inst *fsm_reset;
unsigned int msc_conn_loss_count;
int conn_id_counter;
};

View File

@ -38,6 +38,7 @@
#include <osmocom/sigtran/sccp_helpers.h>
#include <osmocom/sigtran/protocol/sua.h>
#include <osmocom/sigtran/protocol/m3ua.h>
#include <osmocom/core/fsm.h>
#include <regex.h>

View File

@ -0,0 +1,34 @@
/* (C) 2017 by sysmocom s.f.m.c. GmbH
* All Rights Reserved
*
* Author: Philipp Maier
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/* Create and start state machine which handles the reset/reset-ack procedure */
void start_reset_fsm(struct bsc_msc_data *msc);
/* Confirm that we sucessfully received a reset acknowlege message */
void reset_ack_confirm(struct bsc_msc_data *msc);
/* Report a failed connection */
void report_conn_fail(struct bsc_msc_data *msc);
/* Report a successful connection */
void report_conn_success(struct bsc_msc_data *msc);
/* Check if we have a connection to a specified msc */
bool sccp_conn_ready(struct bsc_msc_data *msc);

View File

@ -20,6 +20,8 @@
#pragma once
#include <openbsc/bsc_msc_data.h>
/* Allocate resources to make a new connection oriented sigtran connection
* (not the connection ittself!) */
enum bsc_con osmo_bsc_sigtran_new_conn(struct gsm_subscriber_connection *conn, struct bsc_msc_data *msc);
@ -35,5 +37,11 @@ int osmo_bsc_sigtran_send(struct osmo_bsc_sccp_con *conn, struct msgb *msg);
* locally, when a connection is closed by the MSC */
int osmo_bsc_sigtran_del_conn(struct osmo_bsc_sccp_con *sccp);
/* Send reset to MSC */
void osmo_bsc_sigtran_tx_reset(struct bsc_msc_data *msc);
/* close all open connections */
void osmo_bsc_sigtran_reset(struct bsc_msc_data *msc);
/* Initalize osmo sigtran backhaul */
int osmo_bsc_sigtran_init(struct llist_head *mscs);

View File

@ -36,6 +36,7 @@
#include <openbsc/transaction.h>
#include <openbsc/mgcpgw_client.h>
#include <osmocom/core/byteswap.h>
#include <osmocom/sccp/sccp_types.h>
#define SSN_BSSAP 254 /* SCCP_SSN_BSSAP */
#define SENDER_PC 1 /* Our local point code */
@ -292,6 +293,26 @@ int a_assign(struct gsm_trans *trans)
return osmo_sccp_tx_data_msg(conn->a.scu, conn->a.conn_id, msg);
}
/* Check if we already know this BSC from a successfuly executed reset procedure. */
static bool test_bsc_known(struct osmo_sccp_addr *bsc_addr)
{
struct a_bsc_addr *addr;
struct llist_head *bsc_addr_list = get_bsc_addr_list();
/* Check if the given address is */
llist_for_each_entry(addr, bsc_addr_list, list) {
if (memcmp(&addr->calling_addr, bsc_addr, sizeof(*bsc_addr)) == 0) {
LOGP(DMSC, LOGL_ERROR, "The calling BSC (%s) is known by this MSC, proceeding...\n",
osmo_sccp_addr_dump(bsc_addr));
return true;
}
}
LOGP(DMSC, LOGL_ERROR, "The calling BSC (%s) is unknown to this MSC, rejecting...\n",
osmo_sccp_addr_dump(bsc_addr));
return false;
}
/* Callback function, called by the SSCP stack when data arrives */
static int sccp_sap_up(struct osmo_prim_hdr *oph, void *_scu)
{
@ -308,6 +329,13 @@ static int sccp_sap_up(struct osmo_prim_hdr *oph, void *_scu)
a_conn_info.conn_id = scu_prim->u.connect.conn_id;
a_conn_info.called_addr = &scu_prim->u.connect.called_addr;
a_conn_info.calling_addr = &scu_prim->u.connect.calling_addr;
if (test_bsc_known(a_conn_info.calling_addr) == false) {
rc = osmo_sccp_tx_disconn(scu, a_conn_info.conn_id, a_conn_info.called_addr,
SCCP_RETURN_CAUSE_UNQUALIFIED);
break;
}
osmo_sccp_tx_conn_resp(scu, scu_prim->u.connect.conn_id, &scu_prim->u.connect.called_addr, NULL, 0);
if (msgb_l2len(oph->msg) > 0) {
LOGP(DMSC, LOGL_DEBUG, "N-CONNECT.ind(%u, %s)\n",

View File

@ -105,7 +105,8 @@ static void bssmap_handle_reset(struct osmo_sccp_user *scu, struct 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)) == 0) {
if (memcmp(&known_addr->calling_addr, a_conn_info->calling_addr, sizeof(*a_conn_info->calling_addr)) ==
0) {
LOGP(DMSC, LOGL_NOTICE, "This BSC is already known to this MSC, refreshing its list item\n");
llist_del(&known_addr->list);
talloc_free(known_addr);

View File

@ -31,6 +31,7 @@ osmo_bsc_SOURCES = \
osmo_bsc_api.c \
osmo_bsc_grace.c \
osmo_bsc_msc.c \
osmo_bsc_reset.c \
osmo_bsc_sccp.c \
osmo_bsc_sigtran.c \
osmo_bsc_filter.c \

View File

@ -31,6 +31,7 @@
#include <osmocom/gsm/gsm0808.h>
#include <osmocom/gsm/gsm0808_utils.h>
#include <openbsc/osmo_bsc_sigtran.h>
#include <openbsc/osmo_bsc_reset.h>
#include <osmocom/core/byteswap.h>
#define IP_V4_ADDR_LEN 4
@ -194,17 +195,10 @@ static int bssmap_handle_reset_ack(struct bsc_msc_data *msc,
struct msgb *msg, unsigned int length)
{
LOGP(DMSC, LOGL_NOTICE, "Reset ACK from MSC No.: %i\n", msc->nr);
msc->msc_con->reset_ack = true;
#if 0
struct msc_signal_data sig;
struct bsc_msc_data *data;
data = (struct bsc_msc_data *) msc;
sig.data = data;
osmo_signal_dispatch(SS_MSC, S_MSC_CONNECTED, &sig);
osmo_signal_dispatch(SS_MSC, S_MSC_AUTHENTICATED, &sig);
#endif
/* Inform the FSM that controls the RESET/RESET-ACK procedure
* that we have successfully received the reset-ack message */
reset_ack_confirm(msc);
return 0;
}

View File

@ -0,0 +1,190 @@
/* (C) 2017 by sysmocom s.f.m.c. GmbH
* All Rights Reserved
*
* Author: Philipp Maier
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include <osmocom/core/logging.h>
#include <osmocom/core/utils.h>
#include <osmocom/core/timer.h>
#include <osmocom/core/fsm.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <openbsc/debug.h>
#include <openbsc/bsc_msc_data.h>
#include <openbsc/osmo_bsc_sigtran.h>
#define RESET_RESEND_INTERVAL 2 /* sec */
#define RESET_RESEND_TIMER_NO 1234 /* FIXME: dig out the real timer number */
#define BAD_CONNECTION_THRESOLD 3 /* connection failures */
enum fsm_states {
ST_DISC, /* Disconnected from MSC */
ST_CONN, /* We have a confirmed connection to the MSC */
};
static const struct value_string fsm_state_names[] = {
{ST_DISC, "ST_DISC (disconnected)"},
{ST_CONN, "ST_CONN (connected)"},
{0, NULL},
};
enum fsm_evt {
EV_RESET_ACK, /* got reset acknowlegement from the MSC */
EV_N_DISCONNECT, /* lost a connection */
EV_N_CONNECT, /* made a successful connection */
};
static const struct value_string fsm_evt_names[] = {
{EV_RESET_ACK, "EV_RESET_ACK"},
{EV_N_DISCONNECT, "EV_N_DISCONNECT"},
{EV_N_CONNECT, "EV_N_CONNECT"},
{0, NULL},
};
/* Disconnected state */
static void fsm_disc_cb(struct osmo_fsm_inst *fi, uint32_t event, void *data)
{
struct bsc_msc_data *msc = (struct bsc_msc_data *)data;
LOGP(DMSC, LOGL_NOTICE, "fsm-state (msc-reset): %s, fsm-event: %s, MSC No.: %i\n",
get_value_string(fsm_state_names, ST_DISC), get_value_string(fsm_evt_names, event), msc->nr);
msc->msc_con->msc_conn_loss_count = 0;
osmo_fsm_inst_state_chg(fi, ST_CONN, 0, 0);
}
/* Connected state */
static void fsm_conn_cb(struct osmo_fsm_inst *fi, uint32_t event, void *data)
{
struct bsc_msc_data *msc = (struct bsc_msc_data *)data;
LOGP(DMSC, LOGL_NOTICE, "fsm-state (msc-reset): %s, fsm-event: %s, MSC No.: %i\n",
get_value_string(fsm_state_names, ST_CONN), get_value_string(fsm_evt_names, event), msc->nr);
OSMO_ASSERT(msc);
switch (event) {
case EV_N_DISCONNECT:
if (msc->msc_con->msc_conn_loss_count >= BAD_CONNECTION_THRESOLD) {
LOGP(DMSC, LOGL_NOTICE, "SIGTRAN connection to MSC No.: %i down, reconnecting...\n", msc->nr);
osmo_fsm_inst_state_chg(fi, ST_DISC, RESET_RESEND_INTERVAL, RESET_RESEND_TIMER_NO);
} else
msc->msc_con->msc_conn_loss_count++;
break;
case EV_N_CONNECT:
msc->msc_con->msc_conn_loss_count = 0;
break;
}
}
/* Timer callback to retransmit the reset signal */
static int fsm_reset_ack_timeout_cb(struct osmo_fsm_inst *fi)
{
struct bsc_msc_data *msc = (struct bsc_msc_data *)fi->priv;
LOGP(DMSC, LOGL_NOTICE, "reset-ack timeout (T%i) in state %s, MSC No.: %i, resending...\n", fi->T,
get_value_string(fsm_state_names, fi->state), msc->nr);
osmo_bsc_sigtran_reset(msc);
osmo_bsc_sigtran_tx_reset(msc);
osmo_fsm_inst_state_chg(fi, ST_DISC, RESET_RESEND_INTERVAL, RESET_RESEND_TIMER_NO);
return 0;
}
static struct osmo_fsm_state fsm_states[] = {
[ST_DISC] = {
.in_event_mask = (1 << EV_RESET_ACK),
.out_state_mask = (1 << ST_DISC) | (1 << ST_CONN),
.name = "DISC",
.action = fsm_disc_cb,
},
[ST_CONN] = {
.in_event_mask = (1 << EV_N_DISCONNECT) | (1 << EV_N_CONNECT),
.out_state_mask = (1 << ST_DISC) | (1 << ST_CONN),
.name = "CONN",
.action = fsm_conn_cb,
},
};
/* State machine definition */
static struct osmo_fsm fsm = {
.name = "FSM RESET",
.states = fsm_states,
.num_states = ARRAY_SIZE(fsm_states),
.log_subsys = DMSC,
.timer_cb = fsm_reset_ack_timeout_cb,
};
/* Create and start state machine which handles the reset/reset-ack procedure */
void start_reset_fsm(struct bsc_msc_data *msc)
{
OSMO_ASSERT(msc);
OSMO_ASSERT(msc->msc_con);
osmo_fsm_register(&fsm);
msc->msc_con->fsm_reset = osmo_fsm_inst_alloc(&fsm, NULL, NULL, LOGL_DEBUG, "FSM RESET INST");
OSMO_ASSERT(msc->msc_con->fsm_reset);
msc->msc_con->fsm_reset->priv = msc;
/* kick off reset-ack sending mechanism */
osmo_fsm_inst_state_chg(msc->msc_con->fsm_reset, ST_DISC, RESET_RESEND_INTERVAL, RESET_RESEND_TIMER_NO);
}
/* Confirm that we sucessfully received a reset acknowlege message */
void reset_ack_confirm(struct bsc_msc_data *msc)
{
OSMO_ASSERT(msc);
OSMO_ASSERT(msc->msc_con);
OSMO_ASSERT(msc->msc_con->fsm_reset);
osmo_fsm_inst_dispatch(msc->msc_con->fsm_reset, EV_RESET_ACK, msc);
}
/* Report a failed connection */
void report_conn_fail(struct bsc_msc_data *msc)
{
OSMO_ASSERT(msc);
OSMO_ASSERT(msc->msc_con);
OSMO_ASSERT(msc->msc_con->fsm_reset);
osmo_fsm_inst_dispatch(msc->msc_con->fsm_reset, EV_N_DISCONNECT, msc);
}
/* Report a successful connection */
void report_conn_success(struct bsc_msc_data *msc)
{
OSMO_ASSERT(msc);
OSMO_ASSERT(msc->msc_con);
OSMO_ASSERT(msc->msc_con->fsm_reset);
osmo_fsm_inst_dispatch(msc->msc_con->fsm_reset, EV_N_CONNECT, msc);
}
/* Check if we have a connection to a specified msc */
bool sccp_conn_ready(struct bsc_msc_data *msc)
{
OSMO_ASSERT(msc);
OSMO_ASSERT(msc->msc_con);
OSMO_ASSERT(msc->msc_con->fsm_reset);
if (msc->msc_con->fsm_reset->state == ST_CONN)
return true;
return false;
}

View File

@ -1,4 +1,4 @@
/* (C) 2017 by Sysmocom s.f.m.c. GmbH
/* (C) 2017 by sysmocom s.f.m.c. GmbH
* All Rights Reserved
*
* Author: Philipp Maier
@ -31,6 +31,7 @@
#include <openbsc/osmo_bsc.h>
#include <openbsc/osmo_bsc_grace.h>
#include <openbsc/osmo_bsc_sigtran.h>
#include <openbsc/osmo_bsc_reset.h>
/* A pointer to a list with all involved MSCs
* (a copy of the pointer location submitted with osmo_bsc_sigtran_init() */
@ -73,36 +74,14 @@ static int pick_free_conn_id(struct bsc_msc_data *msc)
return -1;
}
/* Timer callback to handle the MSC reset procedure */
static void msc_reset_timer_cb(void *data)
/* Send reset to MSC */
void osmo_bsc_sigtran_tx_reset(struct bsc_msc_data *msc)
{
/* FIXME: Probably the reset procedure should be moved to osmo_bsc_bssap.c,
* since it is clearly in the BSSAP's area of accountability */
struct bsc_msc_data *msc = (struct bsc_msc_data *)data;
struct msgb *msg = NULL;
/* Stop sending RESET messages as soon as the
* connection is marked as connected. */
if (msc->msc_con->reset_ack)
return;
struct msgb *msg;
LOGP(DMSC, LOGL_NOTICE, "Sending RESET to MSC No.: %i\n", msc->nr);
msg = gsm0808_create_reset();
osmo_sccp_tx_unitdata_msg(msc->msc_con->sccp_user, &msc->msc_con->g_calling_addr,
&msc->msc_con->g_called_addr, msg);
osmo_timer_schedule(&msc->msc_con->msc_reset_timer, RESET_INTERVAL, 0);
}
/* Perform MSC reset procedure */
static void msc_reset(struct bsc_msc_data *msc)
{
LOGP(DMSC, LOGL_NOTICE, "Starting RESET for MSC No.: %i\n", msc->nr);
msc->msc_con->msc_reset_timer.cb = msc_reset_timer_cb;
msc->msc_con->msc_reset_timer.data = msc;
msc->msc_con->reset_ack = false;
osmo_timer_schedule(&msc->msc_con->msc_reset_timer, RESET_INTERVAL, 0);
}
/* Find an MSC by its sigtran point code */
@ -154,6 +133,7 @@ static int sccp_sap_up(struct osmo_prim_hdr *oph, void *_scu)
{
struct osmo_scu_prim *scu_prim = (struct osmo_scu_prim *)oph;
struct osmo_sccp_user *scu = _scu;
struct osmo_bsc_sccp_con *bsc_con;
int rc = 0;
switch (OSMO_PRIM_HDR(&scu_prim->oph)) {
@ -184,19 +164,34 @@ static int sccp_sap_up(struct osmo_prim_hdr *oph, void *_scu)
/* Handle incoming connection oriented data */
DEBUGP(DMSC, "N-DATA.ind(%u, %s)\n", scu_prim->u.data.conn_id,
osmo_hexdump(msgb_l2(oph->msg), msgb_l2len(oph->msg)));
/* Incoming data is a sign of a vital connection */
bsc_con = get_bsc_conn_by_conn_id(scu_prim->u.disconnect.conn_id);
if (bsc_con)
report_conn_success(bsc_con->msc);
rc = handle_data_from_msc(scu_prim->u.data.conn_id, oph->msg);
break;
case OSMO_PRIM(OSMO_SCU_PRIM_N_DISCONNECT, PRIM_OP_INDICATION):
/* indication of disconnect */
if (msgb_l2len(oph->msg) > 0) {
DEBUGP(DMSC, "N-DISCONNECT.ind(%u, %s)\n", scu_prim->u.disconnect.conn_id,
osmo_hexdump(msgb_l2(oph->msg), msgb_l2len(oph->msg)));
DEBUGP(DMSC, "N-DISCONNECT.ind(%u, %s, cause=%i)\n", scu_prim->u.disconnect.conn_id,
osmo_hexdump(msgb_l2(oph->msg), msgb_l2len(oph->msg)), scu_prim->u.disconnect.cause);
handle_data_from_msc(scu_prim->u.disconnect.conn_id, oph->msg);
} else
DEBUGP(DRANAP, "N-DISCONNECT.ind(%u)\n", scu_prim->u.disconnect.conn_id);
DEBUGP(DRANAP, "N-DISCONNECT.ind(%u, cause=%i)\n", scu_prim->u.disconnect.conn_id,
scu_prim->u.disconnect.cause);
rc = osmo_bsc_sigtran_del_conn(get_bsc_conn_by_conn_id(scu_prim->u.disconnect.conn_id));
bsc_con = get_bsc_conn_by_conn_id(scu_prim->u.disconnect.conn_id);
if (bsc_con) {
/* We might have a connectivity problem. Maybe we need to go
* through the reset procedure again? */
if (scu_prim->u.disconnect.cause == 0)
report_conn_fail(bsc_con->msc);
rc = osmo_bsc_sigtran_del_conn(bsc_con);
}
break;
default:
@ -220,9 +215,8 @@ enum bsc_con osmo_bsc_sigtran_new_conn(struct gsm_subscriber_connection *conn, s
LOGP(DMSC, LOGL_NOTICE, "Initalizing resources for new SIGTRAN connection to MSC No.: %i...\n", msc->nr);
/* This should not trigger */
if (!msc || !msc->msc_con->is_authenticated) {
LOGP(DMSC, LOGL_ERROR, "How did this happen? MSC is not connected. Dropping.\n");
if (sccp_conn_ready(msc) == false) {
LOGP(DMSC, LOGL_ERROR, "MSC is not connected. Dropping.\n");
return BSC_CON_REJECT_NO_LINK;
}
@ -256,13 +250,22 @@ enum bsc_con osmo_bsc_sigtran_new_conn(struct gsm_subscriber_connection *conn, s
/* Open a new connection oriented sigtran connection */
int osmo_bsc_sigtran_open_conn(struct osmo_bsc_sccp_con *conn, struct msgb *msg)
{
struct bsc_msc_data *msc = conn->msc;
int conn_id = conn->conn_id;
struct bsc_msc_data *msc;
int conn_id;
int rc;
OSMO_ASSERT(conn);
OSMO_ASSERT(msg);
OSMO_ASSERT(conn->msc);
msc = conn->msc;
if (sccp_conn_ready(msc) == false) {
LOGP(DMSC, LOGL_ERROR, "MSC is not connected. Dropping.\n");
return -EINVAL;
}
conn_id = conn->conn_id;
LOGP(DMSC, LOGL_NOTICE, "Opening new SIGTRAN connection (id=%i) to MSC No.: %i...\n", conn_id, msc->nr);
rc = osmo_sccp_tx_conn_req_msg(msc->msc_con->sccp_user, conn_id, &msc->msc_con->g_calling_addr,
@ -280,11 +283,19 @@ int osmo_bsc_sigtran_send(struct osmo_bsc_sccp_con *conn, struct msgb *msg)
OSMO_ASSERT(conn);
OSMO_ASSERT(msg);
OSMO_ASSERT(conn->msc);
msc = conn->msc;
if (sccp_conn_ready(msc) == false) {
LOGP(DMSC, LOGL_ERROR, "MSC is not connected. Dropping.\n");
return -EINVAL;
}
conn_id = conn->conn_id;
LOGP(DMSC, LOGL_DEBUG, "Sending connection (id=%i) oriented data to MSC No.: %i...\n", conn_id, msc->nr);
rc = osmo_sccp_tx_data_msg(msc->msc_con->sccp_user, conn_id, msg);
return rc;
@ -293,20 +304,44 @@ int osmo_bsc_sigtran_send(struct osmo_bsc_sccp_con *conn, struct msgb *msg)
/* Delete a connection from the list with open connections
* (called by osmo_bsc_api.c on failing open connections and
* locally, when a connection is closed by the MSC */
int osmo_bsc_sigtran_del_conn(struct osmo_bsc_sccp_con *sccp)
int osmo_bsc_sigtran_del_conn(struct osmo_bsc_sccp_con *conn)
{
if (!sccp)
if (!conn)
return 0;
if (sccp->conn)
LOGP(DMSC, LOGL_ERROR, "sccp connection not cleared -- forcefully clearing it now!\n");
if (conn->conn) {
LOGP(DMSC, LOGL_ERROR,
"sccp connection (id=%i) not cleared (gsm subscriber connection still active) -- forcefully clearing it now!\n",
conn->conn_id);
bsc_subscr_con_free(conn->conn);
conn->conn = NULL;
llist_del(&sccp->entry);
talloc_free(sccp);
/* This bahaviour might be caused by a bad connection. Maybe we
* will have to go through the reset procedure again */
report_conn_fail(conn->msc);
}
llist_del(&conn->entry);
talloc_free(conn);
return 0;
}
/* close all open connections */
void osmo_bsc_sigtran_reset(struct bsc_msc_data *msc)
{
struct osmo_bsc_sccp_con *conn;
struct osmo_bsc_sccp_con *conn_temp;
llist_for_each_entry_safe(conn, conn_temp, &active_connections, entry) {
if (conn->conn)
gsm0808_clear(conn->conn);
osmo_bsc_sigtran_del_conn(conn);
}
msc->msc_con->conn_id_counter = 0;
}
/* Initalize osmo sigtran backhaul */
int osmo_bsc_sigtran_init(struct llist_head *mscs)
{
@ -332,7 +367,7 @@ int osmo_bsc_sigtran_init(struct llist_head *mscs)
osmo_sccp_user_bind(msc->msc_con->sccp, msc_name, sccp_sap_up, SCCP_SSN_BSSAP);
/* Start MSC reset procedure */
msc_reset(msc);
start_reset_fsm(msc);
}
return 0;