summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilipp Maier <pmaier@sysmocom.de>2017-06-12 17:40:01 +0200
committerNeels Hofmeyr <nhofmeyr@sysmocom.de>2017-06-18 17:50:09 +0200
commit738cc1106c0273a918350f495a6a746d06fc2e2a (patch)
tree2d887c4ffd9d6dbca354371875d68236f08d4d16
parent2abf6b020090788b03d0d1d9207acd62d6a6abcb (diff)
libcommon-cs: genralize a interface reset fsm
The AoIP standard also describes an MSC->BSC reset procedure. We currently do not implement it. However, the fsm that is used to issue the reset request from the bsc side is not generalized. This patch generalizes the code in order to be able to use the same code on the MSC side to perform a reset procedure from there.
-rw-r--r--openbsc/include/openbsc/Makefile.am2
-rw-r--r--openbsc/include/openbsc/a_reset.h (renamed from openbsc/include/openbsc/osmo_bsc_reset.h)36
-rw-r--r--openbsc/include/openbsc/bsc_msc.h4
-rw-r--r--openbsc/include/openbsc/osmo_bsc_sigtran.h6
-rw-r--r--openbsc/src/libcommon-cs/Makefile.am1
-rw-r--r--openbsc/src/libcommon-cs/a_reset.c (renamed from openbsc/src/osmo-bsc/osmo_bsc_reset.c)92
-rw-r--r--openbsc/src/osmo-bsc/Makefile.am1
-rw-r--r--openbsc/src/osmo-bsc/osmo_bsc_bssap.c4
-rw-r--r--openbsc/src/osmo-bsc/osmo_bsc_sigtran.c33
9 files changed, 102 insertions, 77 deletions
diff --git a/openbsc/include/openbsc/Makefile.am b/openbsc/include/openbsc/Makefile.am
index e1ae6d2..4a52236 100644
--- a/openbsc/include/openbsc/Makefile.am
+++ b/openbsc/include/openbsc/Makefile.am
@@ -67,7 +67,7 @@ noinst_HEADERS = \
openbscdefines.h \
osmo_bsc.h \
osmo_bsc_grace.h \
- osmo_bsc_reset.h \
+ a_reset.h \
osmo_bsc_rf.h \
osmo_msc.h \
osmo_bsc_sigtran.h \
diff --git a/openbsc/include/openbsc/osmo_bsc_reset.h b/openbsc/include/openbsc/a_reset.h
index 578f763..124cf13 100644
--- a/openbsc/include/openbsc/osmo_bsc_reset.h
+++ b/openbsc/include/openbsc/a_reset.h
@@ -18,17 +18,43 @@
*
*/
+#pragma once
+
+
+
+/* Reset context data (callbacks, state machine etc...) */
+struct a_reset_ctx {
+
+ /* FSM instance, which handles the reset procedure */
+ struct osmo_fsm_inst *fsm;
+
+ /* Connection failure counter. When this counter
+ * reaches a certain threshold, the reset procedure
+ * will be triggered */
+ int conn_loss_counter;
+
+ /* A human readable name to display in the logs */
+ char name[256];
+
+ /* Callback function to be called when a connection
+ * failure is detected and a rest must occur */
+ void (*cb)(void *priv);
+
+ /* Privated data for the callback function */
+ void *priv;
+};
+
/* Create and start state machine which handles the reset/reset-ack procedure */
-void start_reset_fsm(struct bsc_msc_data *msc);
+void a_reset_start(struct a_reset_ctx *reset);
/* Confirm that we sucessfully received a reset acknowlege message */
-void reset_ack_confirm(struct bsc_msc_data *msc);
+void a_reset_ack_confirm(struct a_reset_ctx *reset);
/* Report a failed connection */
-void report_conn_fail(struct bsc_msc_data *msc);
+void a_reset_conn_fail(struct a_reset_ctx *reset);
/* Report a successful connection */
-void report_conn_success(struct bsc_msc_data *msc);
+void a_reset_conn_success(struct a_reset_ctx *reset);
/* Check if we have a connection to a specified msc */
-bool sccp_conn_ready(struct bsc_msc_data *msc);
+bool a_reset_conn_ready(struct a_reset_ctx *reset);
diff --git a/openbsc/include/openbsc/bsc_msc.h b/openbsc/include/openbsc/bsc_msc.h
index b80729c..a7c881b 100644
--- a/openbsc/include/openbsc/bsc_msc.h
+++ b/openbsc/include/openbsc/bsc_msc.h
@@ -25,6 +25,7 @@
#include <osmocom/core/write_queue.h>
#include <osmocom/core/timer.h>
#include <osmocom/sigtran/sccp_sap.h>
+#include <openbsc/a_reset.h>
#include <netinet/in.h>
@@ -60,8 +61,7 @@ struct bsc_msc_connection {
struct osmo_sccp_user *sccp_user;
struct osmo_sccp_addr g_calling_addr;
struct osmo_sccp_addr g_called_addr;
- struct osmo_fsm_inst *fsm_reset;
- unsigned int msc_conn_loss_count;
+ struct a_reset_ctx reset;
int conn_id_counter;
};
diff --git a/openbsc/include/openbsc/osmo_bsc_sigtran.h b/openbsc/include/openbsc/osmo_bsc_sigtran.h
index 92d8ba6..caeea60 100644
--- a/openbsc/include/openbsc/osmo_bsc_sigtran.h
+++ b/openbsc/include/openbsc/osmo_bsc_sigtran.h
@@ -38,11 +38,5 @@ 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);
diff --git a/openbsc/src/libcommon-cs/Makefile.am b/openbsc/src/libcommon-cs/Makefile.am
index f3921ba..21c2745 100644
--- a/openbsc/src/libcommon-cs/Makefile.am
+++ b/openbsc/src/libcommon-cs/Makefile.am
@@ -16,5 +16,6 @@ AM_CFLAGS = \
noinst_LIBRARIES = libcommon-cs.a
libcommon_cs_a_SOURCES = \
+ a_reset.c \
common_cs.c \
common_cs_vty.c
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_reset.c b/openbsc/src/libcommon-cs/a_reset.c
index 0baf080..94d2155 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_reset.c
+++ b/openbsc/src/libcommon-cs/a_reset.c
@@ -34,8 +34,8 @@
#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 */
+ ST_DISC, /* Disconnected from remote end */
+ ST_CONN, /* We have a confirmed connection */
};
static const struct value_string fsm_state_names[] = {
@@ -45,7 +45,7 @@ static const struct value_string fsm_state_names[] = {
};
enum fsm_evt {
- EV_RESET_ACK, /* got reset acknowlegement from the MSC */
+ EV_RESET_ACK, /* got reset acknowlegement from remote end */
EV_N_DISCONNECT, /* lost a connection */
EV_N_CONNECT, /* made a successful connection */
};
@@ -60,34 +60,35 @@ static const struct value_string fsm_evt_names[] = {
/* 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;
+ struct a_reset_ctx *reset = (struct a_reset_ctx *)data;
+ OSMO_ASSERT(reset);
- 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;
+ LOGP(DMSC, LOGL_NOTICE, "(%s) fsm-state (msc-reset): %s, fsm-event: %s\n", reset->name,
+ get_value_string(fsm_state_names, ST_CONN), get_value_string(fsm_evt_names, event));
+
+ reset->conn_loss_counter = 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);
+ struct a_reset_ctx *reset = (struct a_reset_ctx *)data;
+ OSMO_ASSERT(reset);
- OSMO_ASSERT(msc);
+ LOGP(DMSC, LOGL_NOTICE, "(%s) fsm-state (msc-reset): %s, fsm-event: %s\n", reset->name,
+ get_value_string(fsm_state_names, ST_CONN), get_value_string(fsm_evt_names, event));
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);
+ if (reset->conn_loss_counter >= BAD_CONNECTION_THRESOLD) {
+ LOGP(DMSC, LOGL_NOTICE, "(%s) SIGTRAN connection down, reconnecting...\n", reset->name);
osmo_fsm_inst_state_chg(fi, ST_DISC, RESET_RESEND_INTERVAL, RESET_RESEND_TIMER_NO);
} else
- msc->msc_con->msc_conn_loss_count++;
+ reset->conn_loss_counter++;
break;
case EV_N_CONNECT:
- msc->msc_con->msc_conn_loss_count = 0;
+ reset->conn_loss_counter = 0;
break;
}
}
@@ -95,13 +96,12 @@ static void fsm_conn_cb(struct osmo_fsm_inst *fi, uint32_t event, void *data)
/* 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;
+ struct a_reset_ctx *reset = (struct a_reset_ctx *)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);
+ LOGP(DMSC, LOGL_NOTICE, "(%s) reset-ack timeout (T%i) in state %s, resending...\n", reset->name, fi->T,
+ get_value_string(fsm_state_names, fi->state));
- osmo_bsc_sigtran_reset(msc);
- osmo_bsc_sigtran_tx_reset(msc);
+ reset->cb(reset->priv);
osmo_fsm_inst_state_chg(fi, ST_DISC, RESET_RESEND_INTERVAL, RESET_RESEND_TIMER_NO);
return 0;
@@ -132,58 +132,54 @@ static struct osmo_fsm fsm = {
};
/* Create and start state machine which handles the reset/reset-ack procedure */
-void start_reset_fsm(struct bsc_msc_data *msc)
+void a_reset_start(struct a_reset_ctx *reset)
{
- OSMO_ASSERT(msc);
- OSMO_ASSERT(msc->msc_con);
+ OSMO_ASSERT(reset);
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);
+ reset->fsm = osmo_fsm_inst_alloc(&fsm, NULL, NULL, LOGL_DEBUG, "FSM RESET INST");
+ OSMO_ASSERT(reset->fsm);
- msc->msc_con->fsm_reset->priv = msc;
+ reset->fsm->priv = reset;
/* 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);
+ osmo_fsm_inst_state_chg(reset->fsm, 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)
+void a_reset_ack_confirm(struct a_reset_ctx *reset)
{
- OSMO_ASSERT(msc);
- OSMO_ASSERT(msc->msc_con);
- OSMO_ASSERT(msc->msc_con->fsm_reset);
+ OSMO_ASSERT(reset);
+ OSMO_ASSERT(reset->fsm);
- osmo_fsm_inst_dispatch(msc->msc_con->fsm_reset, EV_RESET_ACK, msc);
+ osmo_fsm_inst_dispatch(reset->fsm, EV_RESET_ACK, reset);
}
/* Report a failed connection */
-void report_conn_fail(struct bsc_msc_data *msc)
+void a_reset_conn_fail(struct a_reset_ctx *reset)
{
- OSMO_ASSERT(msc);
- OSMO_ASSERT(msc->msc_con);
- OSMO_ASSERT(msc->msc_con->fsm_reset);
+ OSMO_ASSERT(reset);
+ OSMO_ASSERT(reset->fsm);
- osmo_fsm_inst_dispatch(msc->msc_con->fsm_reset, EV_N_DISCONNECT, msc);
+ osmo_fsm_inst_dispatch(reset->fsm, EV_N_DISCONNECT, reset);
}
/* Report a successful connection */
-void report_conn_success(struct bsc_msc_data *msc)
+void a_reset_conn_success(struct a_reset_ctx *reset)
{
- OSMO_ASSERT(msc);
- OSMO_ASSERT(msc->msc_con);
- OSMO_ASSERT(msc->msc_con->fsm_reset);
+ OSMO_ASSERT(reset);
+ OSMO_ASSERT(reset->fsm);
- osmo_fsm_inst_dispatch(msc->msc_con->fsm_reset, EV_N_CONNECT, msc);
+ osmo_fsm_inst_dispatch(reset->fsm, EV_N_CONNECT, reset);
}
/* Check if we have a connection to a specified msc */
-bool sccp_conn_ready(struct bsc_msc_data *msc)
+bool a_reset_conn_ready(struct a_reset_ctx *reset)
{
- OSMO_ASSERT(msc);
- OSMO_ASSERT(msc->msc_con);
- OSMO_ASSERT(msc->msc_con->fsm_reset);
- if (msc->msc_con->fsm_reset->state == ST_CONN)
+ OSMO_ASSERT(reset);
+ OSMO_ASSERT(reset->fsm);
+
+ if (reset->fsm->state == ST_CONN)
return true;
return false;
diff --git a/openbsc/src/osmo-bsc/Makefile.am b/openbsc/src/osmo-bsc/Makefile.am
index 6aa27d2..a12e174 100644
--- a/openbsc/src/osmo-bsc/Makefile.am
+++ b/openbsc/src/osmo-bsc/Makefile.am
@@ -31,7 +31,6 @@ osmo_bsc_SOURCES = \
osmo_bsc_api.c \
osmo_bsc_grace.c \
osmo_bsc_msc.c \
- osmo_bsc_reset.c \
osmo_bsc_sigtran.c \
osmo_bsc_filter.c \
osmo_bsc_bssap.c \
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_bssap.c b/openbsc/src/osmo-bsc/osmo_bsc_bssap.c
index 739f93c..f088114 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_bssap.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_bssap.c
@@ -31,7 +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 <openbsc/a_reset.h>
#include <osmocom/core/byteswap.h>
#define IP_V4_ADDR_LEN 4
@@ -198,7 +198,7 @@ static int bssmap_handle_reset_ack(struct bsc_msc_data *msc,
/* Inform the FSM that controls the RESET/RESET-ACK procedure
* that we have successfully received the reset-ack message */
- reset_ack_confirm(msc);
+ a_reset_ack_confirm(&msc->msc_con->reset);
return 0;
}
diff --git a/openbsc/src/osmo-bsc/osmo_bsc_sigtran.c b/openbsc/src/osmo-bsc/osmo_bsc_sigtran.c
index 10ae6c8..7afe71e 100644
--- a/openbsc/src/osmo-bsc/osmo_bsc_sigtran.c
+++ b/openbsc/src/osmo-bsc/osmo_bsc_sigtran.c
@@ -31,7 +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>
+#include <openbsc/a_reset.h>
#include <openbsc/gsm_04_80.h>
/* A pointer to a list with all involved MSCs
@@ -76,7 +76,7 @@ static int pick_free_conn_id(struct bsc_msc_data *msc)
}
/* Send reset to MSC */
-void osmo_bsc_sigtran_tx_reset(struct bsc_msc_data *msc)
+static void osmo_bsc_sigtran_tx_reset(struct bsc_msc_data *msc)
{
struct msgb *msg;
LOGP(DMSC, LOGL_NOTICE, "Sending RESET to MSC No.: %i\n", msc->nr);
@@ -169,7 +169,7 @@ static int sccp_sap_up(struct osmo_prim_hdr *oph, void *_scu)
/* 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);
+ a_reset_conn_success(&bsc_con->msc->msc_con->reset);
rc = handle_data_from_msc(scu_prim->u.data.conn_id, oph->msg);
break;
@@ -189,7 +189,7 @@ static int sccp_sap_up(struct osmo_prim_hdr *oph, void *_scu)
/* 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);
+ a_reset_conn_fail(&bsc_con->msc->msc_con->reset);
rc = osmo_bsc_sigtran_del_conn(bsc_con);
}
@@ -216,7 +216,7 @@ 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);
- if (sccp_conn_ready(msc) == false) {
+ if (a_reset_conn_ready(&msc->msc_con->reset) == false) {
LOGP(DMSC, LOGL_ERROR, "MSC is not connected. Dropping.\n");
return BSC_CON_REJECT_NO_LINK;
}
@@ -261,7 +261,7 @@ int osmo_bsc_sigtran_open_conn(struct osmo_bsc_sccp_con *conn, struct msgb *msg)
msc = conn->msc;
- if (sccp_conn_ready(msc) == false) {
+ if (a_reset_conn_ready(&msc->msc_con->reset) == false) {
LOGP(DMSC, LOGL_ERROR, "MSC is not connected. Dropping.\n");
return -EINVAL;
}
@@ -288,7 +288,7 @@ int osmo_bsc_sigtran_send(struct osmo_bsc_sccp_con *conn, struct msgb *msg)
msc = conn->msc;
- if (sccp_conn_ready(msc) == false) {
+ if (a_reset_conn_ready(&msc->msc_con->reset) == false) {
LOGP(DMSC, LOGL_ERROR, "MSC is not connected. Dropping.\n");
return -EINVAL;
}
@@ -319,7 +319,7 @@ int osmo_bsc_sigtran_del_conn(struct osmo_bsc_sccp_con *conn)
/* 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);
+ a_reset_conn_fail(&conn->msc->msc_con->reset);
}
llist_del(&conn->entry);
@@ -348,20 +348,26 @@ static void bsc_notify_msc_lost(struct osmo_bsc_sccp_con *con)
}
-/* close all open connections */
-void osmo_bsc_sigtran_reset(struct bsc_msc_data *msc)
+/* Callback function: Close all open connections */
+static void osmo_bsc_sigtran_reset_cb(void *priv)
{
struct osmo_bsc_sccp_con *conn;
struct osmo_bsc_sccp_con *conn_temp;
+ struct bsc_msc_data *msc = (struct bsc_msc_data*) priv;
+ OSMO_ASSERT(msc);
+
+ /* Close all open connections */
llist_for_each_entry_safe(conn, conn_temp, &active_connections, entry) {
if (conn->conn)
gsm0808_clear(conn->conn);
bsc_notify_msc_lost(conn);
osmo_bsc_sigtran_del_conn(conn);
}
-
msc->msc_con->conn_id_counter = 0;
+
+ /* Send reset to MSC */
+ osmo_bsc_sigtran_tx_reset(msc);
}
/* Initalize osmo sigtran backhaul */
@@ -389,7 +395,10 @@ 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 */
- start_reset_fsm(msc);
+ msc->msc_con->reset.priv = msc;
+ msc->msc_con->reset.cb = osmo_bsc_sigtran_reset_cb;
+ snprintf(msc->msc_con->reset.name,sizeof(msc->msc_con->reset.name),"MSC No. %u",msc->nr);
+ a_reset_start(&msc->msc_con->reset);
}
return 0;