aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeels Hofmeyr <neels@hofmeyr.de>2021-08-02 01:41:49 +0200
committerNeels Hofmeyr <neels@hofmeyr.de>2021-08-09 17:47:44 +0200
commitb4ca0a42fe913cf2de5c56a29f7dbbb964d95c43 (patch)
treeff8d5aed929f6335af989c5e24c9160432c5388d
parent4bf2297b2f29231e3b4cf61f48ac23ec20753d4c (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: - Move all state transitioning into gscon_bssmap_clear(). - In gscon_bssmap_clear(), ask for a state transition to ST_CLEARING first. If the state transition is allowed, do the Clear Request messaging in ST_CLEARING's onenter function. - Fix the timeout behavior: by using conn_fsm_state_chg(), use the proper X4 timer value from VTY configuration instead of hardcoded magic numbers in various places. Change-Id: I234b2a754d0c98031056981823cdbc187e977741
-rw-r--r--src/osmo-bsc/bsc_subscr_conn_fsm.c35
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 1be8ddf9f..004572c60 100644
--- a/src/osmo-bsc/bsc_subscr_conn_fsm.c
+++ b/src/osmo-bsc/bsc_subscr_conn_fsm.c
@@ -140,10 +140,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");
@@ -151,14 +165,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;
}
@@ -354,8 +368,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);
@@ -375,7 +387,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;
}
@@ -691,6 +702,7 @@ static const struct osmo_fsm_state gscon_fsm_states[] = {
},
[ST_CLEARING] = {
.name = "CLEARING",
+ .onenter = gscon_fsm_clearing_onenter,
/* dead end state */
},
};
@@ -749,11 +761,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;
}
@@ -792,8 +799,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)
@@ -1179,7 +1185,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,