aboutsummaryrefslogtreecommitdiffstats
path: root/src/osmo-bsc/a_reset.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/osmo-bsc/a_reset.c')
-rw-r--r--src/osmo-bsc/a_reset.c221
1 files changed, 49 insertions, 172 deletions
diff --git a/src/osmo-bsc/a_reset.c b/src/osmo-bsc/a_reset.c
index 9446d1311..d23ffa799 100644
--- a/src/osmo-bsc/a_reset.c
+++ b/src/osmo-bsc/a_reset.c
@@ -18,183 +18,68 @@
*
*/
-#include <osmocom/core/logging.h>
-#include <osmocom/core/utils.h>
-#include <osmocom/core/timer.h>
-#include <osmocom/core/fsm.h>
#include <osmocom/core/signal.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
+#include <osmocom/bsc/signal.h>
+
#include <osmocom/bsc/debug.h>
#include <osmocom/bsc/bsc_msc_data.h>
#include <osmocom/bsc/osmo_bsc_sigtran.h>
-#include <osmocom/bsc/signal.h>
-
-#define RESET_RESEND_INTERVAL 2 /* sec */
-#define RESET_RESEND_TIMER_NO 4 /* See also 3GPP TS 48.008 Chapter 3.1.4.1.3.1 */
-#define BAD_CONNECTION_THRESOLD 3 /* connection failures */
-
-/* Reset context data (callbacks, state machine etc...) */
-struct reset_ctx {
- /* Connection failure counter. When this counter
- * reaches a certain threshold, the reset procedure
- * will be triggered */
- int conn_loss_counter;
-
- /* 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;
-};
-
-enum reset_fsm_states {
- ST_DISC, /* Disconnected from remote end */
- ST_CONN, /* We have a confirmed connection */
-};
-
-enum reset_fsm_evt {
- EV_RESET_ACK, /* got reset acknowlegement from remote end */
- EV_N_DISCONNECT, /* lost a connection */
- EV_N_CONNECT, /* made a successful connection */
-};
-
-static const struct value_string fsm_event_names[] = {
- OSMO_VALUE_STRING(EV_RESET_ACK),
- OSMO_VALUE_STRING(EV_N_DISCONNECT),
- OSMO_VALUE_STRING(EV_N_CONNECT),
- {0, NULL}
-};
-
-/* Disconnected state event handler */
-static void fsm_disc_cb(struct osmo_fsm_inst *fi, uint32_t event, void *data)
-{
- struct reset_ctx *reset_ctx = (struct reset_ctx *)fi->priv;
- OSMO_ASSERT(reset_ctx);
-
- reset_ctx->conn_loss_counter = 0;
- osmo_fsm_inst_state_chg(fi, ST_CONN, 0, 0);
-}
+#include <osmocom/bsc/bssmap_reset.h>
+#include <osmocom/bsc/bsc_stats.h>
-/* Called when entering Disconnected state */
-static void fsm_disc_onenter_cb(struct osmo_fsm_inst *fi, uint32_t prev_state)
+static void a_reset_tx_reset(void *data)
{
- struct reset_ctx *reset_ctx = (struct reset_ctx *)fi->priv;
- struct bsc_msc_data *msc = reset_ctx->priv;
-
- LOGPFSML(fi, LOGL_NOTICE, "BSSMAP MSC assocation is down, reconnecting...\n");
- if (prev_state != ST_DISC) {
- osmo_stat_item_dec(msc->msc_statg->items[MSC_STAT_MSC_LINKS_ACTIVE], 1);
- osmo_signal_dispatch(SS_MSC, S_MSC_LOST, msc);
- }
+ struct bsc_msc_data *msc = data;
+ osmo_bsc_sigtran_tx_reset(msc);
}
-/* Connected state event handler */
-static void fsm_conn_cb(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+static void a_reset_tx_reset_ack(void *data)
{
- struct reset_ctx *reset_ctx = (struct reset_ctx *)fi->priv;
- OSMO_ASSERT(reset_ctx);
-
- switch (event) {
- case EV_N_DISCONNECT:
- if (reset_ctx->conn_loss_counter >= BAD_CONNECTION_THRESOLD)
- osmo_fsm_inst_state_chg(fi, ST_DISC, RESET_RESEND_INTERVAL, RESET_RESEND_TIMER_NO);
- else
- reset_ctx->conn_loss_counter++;
- break;
- case EV_N_CONNECT:
- reset_ctx->conn_loss_counter = 0;
- break;
- case EV_RESET_ACK:
- LOGPFSML(fi, LOGL_INFO, "Received a duplicated BSSMAP RESET ACK, ignoring\n");
- break;
- }
+ struct bsc_msc_data *msc = data;
+ osmo_bsc_sigtran_tx_reset_ack(msc);
}
-/* Called when entering Connected state */
-static void fsm_conn_onenter_cb(struct osmo_fsm_inst *fi, uint32_t prev_state)
+static void a_reset_link_up(void *data)
{
- struct reset_ctx *reset_ctx = (struct reset_ctx *)fi->priv;
- struct bsc_msc_data *msc = reset_ctx->priv;
-
- LOGPFSML(fi, LOGL_NOTICE, "BSSMAP MSC assocation is up.\n");
- if (prev_state != ST_CONN) {
- osmo_stat_item_inc(msc->msc_statg->items[MSC_STAT_MSC_LINKS_ACTIVE], 1);
- osmo_signal_dispatch(SS_MSC, S_MSC_CONNECTED, msc);
- }
+ struct bsc_msc_data *msc = data;
+ LOGP(DMSC, LOGL_NOTICE, "(msc%d) BSSMAP assocation is up\n", msc->nr);
+ osmo_stat_item_inc(osmo_stat_item_group_get_item(msc->msc_statg, MSC_STAT_MSC_LINKS_ACTIVE), 1);
+ osmo_stat_item_inc(osmo_stat_item_group_get_item(msc->network->bsc_statg, BSC_STAT_NUM_MSC_CONNECTED), 1);
+ osmo_signal_dispatch(SS_MSC, S_MSC_CONNECTED, msc);
}
-/* Timer callback to retransmit the reset signal */
-static int fsm_reset_ack_timeout_cb(struct osmo_fsm_inst *fi)
+static void a_reset_link_lost(void *data)
{
- struct reset_ctx *reset_ctx = (struct reset_ctx *)fi->priv;
- OSMO_ASSERT(reset_ctx);
-
- LOGPFSML(fi, LOGL_NOTICE, "(re)sending BSSMAP RESET message...\n");
-
- reset_ctx->cb(reset_ctx->priv);
-
- osmo_fsm_inst_state_chg(fi, ST_DISC, RESET_RESEND_INTERVAL, RESET_RESEND_TIMER_NO);
- return 0;
+ struct bsc_msc_data *msc = data;
+ LOGP(DMSC, LOGL_NOTICE, "(msc%d) BSSMAP assocation is down\n", msc->nr);
+ osmo_stat_item_dec(osmo_stat_item_group_get_item(msc->msc_statg, MSC_STAT_MSC_LINKS_ACTIVE), 1);
+ osmo_stat_item_dec(osmo_stat_item_group_get_item(msc->network->bsc_statg, BSC_STAT_NUM_MSC_CONNECTED), 1);
+ osmo_signal_dispatch(SS_MSC, S_MSC_LOST, msc);
+ osmo_bsc_sigtran_reset(msc);
}
-static struct osmo_fsm_state reset_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,
- .onenter = fsm_disc_onenter_cb,
- },
- [ST_CONN] = {
- .in_event_mask = (1 << EV_N_DISCONNECT) | (1 << EV_N_CONNECT) | (1 << EV_RESET_ACK),
- .out_state_mask = (1 << ST_DISC) | (1 << ST_CONN),
- .name = "CONN",
- .action = fsm_conn_cb,
- .onenter = fsm_conn_onenter_cb,
- },
-};
-
-/* State machine definition */
-static struct osmo_fsm fsm = {
- .name = "A-RESET",
- .states = reset_fsm_states,
- .num_states = ARRAY_SIZE(reset_fsm_states),
- .log_subsys = DMSC,
- .timer_cb = fsm_reset_ack_timeout_cb,
- .event_names = fsm_event_names,
-};
-
/* Create and start state machine which handles the reset/reset-ack procedure */
-void a_reset_alloc(struct bsc_msc_data *msc, const char *name, void *cb)
+void a_reset_alloc(struct bsc_msc_data *msc, const char *name)
{
- struct reset_ctx *reset_ctx;
- struct osmo_fsm_inst *reset_fsm;
-
- OSMO_ASSERT(msc);
- OSMO_ASSERT(name);
- OSMO_ASSERT(cb);
+ struct bssmap_reset_cfg cfg = {
+ .conn_cfm_failure_threshold = 3,
+ .ops = {
+ .tx_reset = a_reset_tx_reset,
+ .tx_reset_ack = a_reset_tx_reset_ack,
+ .link_up = a_reset_link_up,
+ .link_lost = a_reset_link_lost,
+ },
+ .data = msc,
+ };
/* There must not be any double allocation! */
- OSMO_ASSERT(msc->a.reset_fsm == NULL);
-
- /* Allocate and configure a new fsm instance */
- reset_ctx = talloc_zero(msc, struct reset_ctx);
- OSMO_ASSERT(reset_ctx);
- reset_ctx->priv = msc;
- reset_ctx->cb = cb;
- reset_ctx->conn_loss_counter = 0;
- reset_fsm = osmo_fsm_inst_alloc(&fsm, msc, reset_ctx, LOGL_DEBUG, name);
- OSMO_ASSERT(reset_fsm);
- msc->a.reset_fsm = reset_fsm;
-
- /* Immediately (1ms) kick off reset sending mechanism */
- osmo_fsm_inst_state_chg_ms(reset_fsm, ST_DISC, 1, RESET_RESEND_TIMER_NO);
-
- /* Count the new MSC link */
- osmo_stat_item_inc(msc->msc_statg->items[MSC_STAT_MSC_LINKS_TOTAL], 1);
+ if (msc->a.bssmap_reset) {
+ LOGP(DMSC, LOGL_ERROR, "(msc%d) will not allocate a second reset FSM for this MSC\n", msc->nr);
+ return;
+ }
+
+ msc->a.bssmap_reset = bssmap_reset_alloc(msc, name, &cfg);
+ osmo_stat_item_inc(osmo_stat_item_group_get_item(msc->network->bsc_statg, BSC_STAT_NUM_MSC_TOTAL), 1);
}
/* Confirm that we successfully received a reset acknowledge message */
@@ -203,10 +88,10 @@ void a_reset_ack_confirm(struct bsc_msc_data *msc)
if (!msc)
return;
- if (!msc->a.reset_fsm)
+ if (!msc->a.bssmap_reset)
return;
- osmo_fsm_inst_dispatch(msc->a.reset_fsm, EV_RESET_ACK, NULL);
+ osmo_fsm_inst_dispatch(msc->a.bssmap_reset->fi, BSSMAP_RESET_EV_RX_RESET_ACK, NULL);
}
/* Report a failed connection */
@@ -215,10 +100,10 @@ void a_reset_conn_fail(struct bsc_msc_data *msc)
if (!msc)
return;
- if (!msc->a.reset_fsm)
+ if (!msc->a.bssmap_reset)
return;
- osmo_fsm_inst_dispatch(msc->a.reset_fsm, EV_N_DISCONNECT, NULL);
+ osmo_fsm_inst_dispatch(msc->a.bssmap_reset->fi, BSSMAP_RESET_EV_CONN_CFM_FAILURE, NULL);
}
/* Report a successful connection */
@@ -227,10 +112,10 @@ void a_reset_conn_success(struct bsc_msc_data *msc)
if (!msc)
return;
- if (!msc->a.reset_fsm)
+ if (!msc->a.bssmap_reset)
return;
- osmo_fsm_inst_dispatch(msc->a.reset_fsm, EV_N_CONNECT, NULL);
+ osmo_fsm_inst_dispatch(msc->a.bssmap_reset->fi, BSSMAP_RESET_EV_CONN_CFM_SUCCESS, NULL);
}
/* Check if we have a connection to a specified msc */
@@ -239,16 +124,8 @@ bool a_reset_conn_ready(struct bsc_msc_data *msc)
if (!msc)
return false;
- if (!msc->a.reset_fsm)
+ if (!msc->a.bssmap_reset)
return false;
- if (msc->a.reset_fsm->state == ST_CONN)
- return true;
-
- return false;
-}
-
-static __attribute__((constructor)) void a_reset_fsm_init()
-{
- OSMO_ASSERT(osmo_fsm_register(&fsm) == 0);
+ return bssmap_reset_is_conn_ready(msc->a.bssmap_reset);
}