diff options
author | Neels Hofmeyr <neels@hofmeyr.de> | 2021-08-02 01:41:49 +0200 |
---|---|---|
committer | Neels Hofmeyr <nhofmeyr@sysmocom.de> | 2022-03-04 00:32:05 +0100 |
commit | 727dd6827167c9c792f770ec6ffee53f3f6816a7 (patch) | |
tree | a5c797e3e85953509d0eb4c5469efba404d8b00b /src/osmo-bsc | |
parent | 0a67e55835ea12bb6f20f03f62f8e6629e8820e4 (diff) |
fix gscon clear 2/n: proper state transition to ST_CLEARING
The way the ST_CLEARING is entered before this patch has various
symptoms of how I / we used osmo_fsm when we were still FSM amateurs in
Osmocom. Patch that up:
- In gscon_bssmap_clear(), ask for a state transition to ST_CLEARING
first. Go ahead only if it is allowed.
- move the Clear Request messaging to ST_CLEARING's onenter function.
- Fix the timeout behavior: by using conn_fsm_state_chg(), use the
actual proper X4 timer value for ST_CLEARING from VTY configuration
instead of hardcoded magic numbers.
Related: OS#5337
Change-Id: I234b2a754d0c98031056981823cdbc187e977741
Diffstat (limited to 'src/osmo-bsc')
-rw-r--r-- | src/osmo-bsc/bsc_subscr_conn_fsm.c | 35 |
1 files changed, 20 insertions, 15 deletions
diff --git a/src/osmo-bsc/bsc_subscr_conn_fsm.c b/src/osmo-bsc/bsc_subscr_conn_fsm.c index ff742a267..e33fe4352 100644 --- a/src/osmo-bsc/bsc_subscr_conn_fsm.c +++ b/src/osmo-bsc/bsc_subscr_conn_fsm.c @@ -141,10 +141,24 @@ int gscon_sigtran_send(struct gsm_subscriber_connection *conn, struct msgb *msg) static void gscon_bssmap_clear(struct gsm_subscriber_connection *conn, enum gsm0808_cause cause) { + /* already clearing? */ + switch (conn->fi->state) { + case ST_CLEARING: + return; + default: + break; + } + + conn->clear_cause = cause; + conn_fsm_state_chg(ST_CLEARING); +} +static void gscon_fsm_clearing_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state) +{ struct msgb *resp; int rc; - conn->clear_cause = cause; + struct gsm_subscriber_connection *conn = fi->priv; + enum gsm0808_cause cause = conn->clear_cause; if (conn->rx_clear_command) { LOGPFSML(conn->fi, LOGL_DEBUG, "Not sending BSSMAP CLEAR REQUEST, already got CLEAR COMMAND from MSC\n"); @@ -152,14 +166,14 @@ static void gscon_bssmap_clear(struct gsm_subscriber_connection *conn, } if (!conn->sccp.msc) { - LOGPFSML(conn->fi, LOGL_ERROR, "Unable to deliver BSSMAP Clear Request message, no MSC for this conn\n"); + LOGPFSML(fi, LOGL_ERROR, "Unable to deliver BSSMAP Clear Request message, no MSC for this conn\n"); return; } - LOGPFSML(conn->fi, LOGL_DEBUG, "Tx BSSMAP CLEAR REQUEST(%s) to MSC\n", gsm0808_cause_name(cause)); + LOGPFSML(fi, LOGL_DEBUG, "Tx BSSMAP CLEAR REQUEST(%s) to MSC\n", gsm0808_cause_name(cause)); resp = gsm0808_create_clear_rqst(cause); if (!resp) { - LOGPFSML(conn->fi, LOGL_ERROR, "Unable to compose BSSMAP Clear Request message\n"); + LOGPFSML(fi, LOGL_ERROR, "Unable to compose BSSMAP Clear Request message\n"); return; } @@ -355,8 +369,6 @@ static void gscon_fsm_init(struct osmo_fsm_inst *fi, uint32_t event, void *data) osmo_fsm_inst_state_name(conn->fi)); } gscon_bssmap_clear(conn, GSM0808_CAUSE_EQUIPMENT_FAILURE); - if (conn->fi->state != ST_CLEARING) - osmo_fsm_inst_state_chg(fi, ST_CLEARING, 60, -4); return; default: OSMO_ASSERT(false); @@ -376,7 +388,6 @@ static void gscon_fsm_wait_cc(struct osmo_fsm_inst *fi, uint32_t event, void *da confirmed connection, then instead simply drop the connection */ LOGPFSML(fi, LOGL_INFO, "Connection confirmed but lchan was dropped previously, clearing conn\n"); - osmo_fsm_inst_state_chg(conn->fi, ST_CLEARING, 60, -4); gscon_bssmap_clear(conn, GSM0808_CAUSE_EQUIPMENT_FAILURE); break; } @@ -705,6 +716,7 @@ static const struct osmo_fsm_state gscon_fsm_states[] = { }, [ST_CLEARING] = { .name = "CLEARING", + .onenter = gscon_fsm_clearing_onenter, /* dead end state */ }, }; @@ -763,11 +775,6 @@ void gscon_lchan_releasing(struct gsm_subscriber_connection *conn, struct gsm_lc yet so we cannot release it. First wait for the CC, and release in gscon_fsm_wait_cc(). */ break; default: - /* Ensure that the FSM is in ST_CLEARING. */ - osmo_fsm_inst_state_chg(conn->fi, ST_CLEARING, 60, -4); - /* fall thru, omit an error log if already in ST_CLEARING */ - case ST_CLEARING: - /* Request a Clear Command from the MSC. */ gscon_bssmap_clear(conn, GSM0808_CAUSE_EQUIPMENT_FAILURE); break; } @@ -806,8 +813,7 @@ void gscon_forget_lchan(struct gsm_subscriber_connection *conn, struct gsm_lchan osmo_fsm_inst_name(conn->fi), detach_label); } - if ((conn->fi && conn->fi->state != ST_CLEARING) - && !conn->lchan + if (!conn->lchan && !conn->ho.new_lchan && !conn->assignment.new_lchan && !conn->lcs.loc_req) @@ -1205,7 +1211,6 @@ static void gsm0808_send_rsl_dtap(struct gsm_subscriber_connection *conn, failed_to_send: LOGPFSML(conn->fi, LOGL_ERROR, "Tx BSSMAP CLEAR REQUEST to MSC\n"); gscon_bssmap_clear(conn, GSM0808_CAUSE_EQUIPMENT_FAILURE); - osmo_fsm_inst_state_chg(conn->fi, ST_ACTIVE, 0, 0); } void gscon_submit_rsl_dtap(struct gsm_subscriber_connection *conn, |