diff options
Diffstat (limited to 'src/osmo-bsc/a_reset.c')
-rw-r--r-- | src/osmo-bsc/a_reset.c | 216 |
1 files changed, 41 insertions, 175 deletions
diff --git a/src/osmo-bsc/a_reset.c b/src/osmo-bsc/a_reset.c index 9446d1311..feaf49106 100644 --- a/src/osmo-bsc/a_reset.c +++ b/src/osmo-bsc/a_reset.c @@ -18,183 +18,57 @@ * */ -#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> -/* 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_link_up(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; + LOGP(DMSC, LOGL_NOTICE, "(msc%d) BSSMAP assocation is up\n", msc->nr); + osmo_stat_item_inc(msc->msc_statg->items[MSC_STAT_MSC_LINKS_ACTIVE], 1); + osmo_signal_dispatch(SS_MSC, S_MSC_CONNECTED, 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_lost(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 down\n", msc->nr); + osmo_stat_item_dec(msc->msc_statg->items[MSC_STAT_MSC_LINKS_ACTIVE], 1); + osmo_signal_dispatch(SS_MSC, S_MSC_LOST, msc); + osmo_bsc_sigtran_reset(msc); } -/* Timer callback to retransmit the reset signal */ -static int fsm_reset_ack_timeout_cb(struct osmo_fsm_inst *fi) -{ - 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; -} - -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, + .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); } /* Confirm that we successfully received a reset acknowledge message */ @@ -203,10 +77,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 +89,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 +101,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 +113,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); } |