From b7e0f0c6d05d79c0fbe8baa0a7370e90df5faa3c Mon Sep 17 00:00:00 2001 From: Pau Espin Pedrol Date: Wed, 4 Sep 2019 20:40:50 +0200 Subject: bsc_subscr_conn_fsm: Cleanly clear BSSAP conn if associated channel closed during WAIT_CC TTCN3 BSC_Tests.TC_ms_rel_ind_does_not_cause_bssmap_reset seems to sometimes run into a race condition on the order of messages received by osmo-bsc comming from MSC and BTS. Usual (expected) scenario): BTS->BSC EST IND BSC->MSC CL3 Info BSC<-MSC CC BTS->BSC REL IND BTS<-BSC DEACT SACCH BSC->MSC ClearRequest BSC<-MSC ClearCommand BSC->MSC ClearComplete BTS<-BSC RF Chan Release BTS->BSC RF Chan Release ACK Sometimes CC message and REL IND message are received swapped (because they are sent by different components asynchronously in TTCN3). As a result, osmo-bsc was failing to go into CLEARING state and was unable to send the ClearRequest because CC was still not received. So the idea is to stay in WAIT_CC until CC is received, then check if the lchan was dropped and in that case go into clearing state. Change-Id: Id1abf5ee44c60925b478123409f26bd29006202b --- src/osmo-bsc/bsc_subscr_conn_fsm.c | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/osmo-bsc/bsc_subscr_conn_fsm.c b/src/osmo-bsc/bsc_subscr_conn_fsm.c index f8784f9ba..60f035db6 100644 --- a/src/osmo-bsc/bsc_subscr_conn_fsm.c +++ b/src/osmo-bsc/bsc_subscr_conn_fsm.c @@ -332,8 +332,19 @@ static void gscon_fsm_wait_cc(struct osmo_fsm_inst *fi, uint32_t event, void *da struct gsm_subscriber_connection *conn = fi->priv; switch (event) { case GSCON_EV_A_CONN_CFM: - /* MSC has confirmed the connection, we now change into the - * active state and wait there for further operations */ + /* MSC has confirmed the connection */ + + if (!conn->lchan) { + /* If associated lchan was released while we were waiting for the + 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, 999); + gscon_bssmap_clear(conn, GSM0808_CAUSE_EQUIPMENT_FAILURE); + break; + } + + /* We now change into the active state and wait there for further operations. */ conn_fsm_state_chg(ST_ACTIVE); /* if there's user payload, forward it just like EV_MT_DTAP */ /* FIXME: Question: if there's user payload attached to the CC, forward it like EV_MT_DTAP? */ @@ -589,7 +600,7 @@ static const struct osmo_fsm_state gscon_fsm_states[] = { [ST_WAIT_CC] = { .name = "WAIT_CC", .in_event_mask = S(GSCON_EV_A_CONN_CFM), - .out_state_mask = S(ST_ACTIVE), + .out_state_mask = S(ST_ACTIVE) | S(ST_CLEARING), .action = gscon_fsm_wait_cc, }, [ST_ACTIVE] = { @@ -651,10 +662,22 @@ void gscon_lchan_releasing(struct gsm_subscriber_connection *conn, struct gsm_lc lchan_forget_conn(conn->lchan); conn->lchan = NULL; } + /* If the conn has no lchan anymore, it was released by the BTS and needs to Clear towards MSC. */ if (!conn->lchan) { - if (conn->fi->state != ST_CLEARING) + switch (conn->fi->state) { + case ST_WAIT_CC: + /* The SCCP connection was not yet confirmed by a CC, the BSSAP is not fully established + 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, 999); - gscon_bssmap_clear(conn, GSM0808_CAUSE_EQUIPMENT_FAILURE); + /* 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; + } } } -- cgit v1.2.3