Change in osmo-bsc[master]: fix gscon clear 3/n: separate state for SCCP RLSD

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

neels gerrit-no-reply at lists.osmocom.org
Fri Dec 17 13:55:16 UTC 2021


neels has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-bsc/+/26614 )


Change subject: fix gscon clear 3/n: separate state for SCCP RLSD
......................................................................

fix gscon clear 3/n: separate state for SCCP RLSD

Properly implement the separate conn release stages in separate FSM
states:

x) sent Clear Request, wait for a Clear Command from the MSC.
   Timeout after a configurable 60s.

y) after a Clear Command and sending a Clear Complete, wait for the SCCP
   RLSD. Timeout after a configurable 60s.

z) terminate after the RLSD is received / after timeout.

handover_test.c needs a little tweak to make the MGCP release work with
its fake MGCP client, because cleanup now ensures to invoke
gscon_forget_mgw_endpoint() in all cases.

Related: I680ec4ed866aa5f0b1ff29e7e98322615cfb288d (osmo-ttcn3-hacks)
Related: OS#5337
Change-Id: Ie975117d37f38ba853589dc7f8d3e94f8f9586b2
---
M src/osmo-bsc/bsc_subscr_conn_fsm.c
M tests/handover/handover_test.c
2 files changed, 75 insertions(+), 54 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/osmo-bsc refs/changes/14/26614/1

diff --git a/src/osmo-bsc/bsc_subscr_conn_fsm.c b/src/osmo-bsc/bsc_subscr_conn_fsm.c
index e33fe43..121b154 100644
--- a/src/osmo-bsc/bsc_subscr_conn_fsm.c
+++ b/src/osmo-bsc/bsc_subscr_conn_fsm.c
@@ -67,7 +67,8 @@
 	ST_ASSIGNMENT,
 	ST_HANDOVER,
 	/* BSSMAP CLEAR has been received */
-	ST_CLEARING,
+	ST_WAIT_CLEAR_CMD,
+	ST_WAIT_SCCP_RLSD,
 };
 
 static const struct value_string gscon_fsm_event_names[] = {
@@ -95,7 +96,8 @@
 
 struct osmo_tdef_state_timeout conn_fsm_timeouts[32] = {
 	[ST_WAIT_CC] = { .T = -3210 },
-	[ST_CLEARING] = { .T = -4 },
+	[ST_WAIT_CLEAR_CMD] = { .T = -4 },
+	[ST_WAIT_SCCP_RLSD] = { .T = -4 },
 };
 
 /* Transition to a state, using the T timer defined in conn_fsm_timeouts.
@@ -143,44 +145,71 @@
 {
 	/* already clearing? */
 	switch (conn->fi->state) {
-	case ST_CLEARING:
+	case ST_WAIT_CLEAR_CMD:
+	case ST_WAIT_SCCP_RLSD:
 		return;
 	default:
 		break;
 	}
 
 	conn->clear_cause = cause;
-	conn_fsm_state_chg(ST_CLEARING);
+	conn_fsm_state_chg(ST_WAIT_CLEAR_CMD);
 }
 
-static void gscon_fsm_clearing_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)
+static void gscon_fsm_wait_clear_cmd_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)
 {
 	struct msgb *resp;
 	int rc;
 	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");
-		return;
-	}
-
 	if (!conn->sccp.msc) {
 		LOGPFSML(fi, LOGL_ERROR, "Unable to deliver BSSMAP Clear Request message, no MSC for this conn\n");
-		return;
+		goto nothing_sent;
 	}
 
 	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(fi, LOGL_ERROR, "Unable to compose BSSMAP Clear Request message\n");
-		return;
+		goto nothing_sent;
 	}
 
 	rate_ctr_inc(rate_ctr_group_get_ctr(conn->sccp.msc->msc_ctrs, MSC_CTR_BSSMAP_TX_DT1_CLEAR_RQST));
 	rc = osmo_bsc_sigtran_send(conn, resp);
-	if (rc < 0)
+	if (rc < 0) {
 		LOGPFSML(conn->fi, LOGL_ERROR, "Unable to deliver BSSMAP Clear Request message\n");
+		goto nothing_sent;
+	}
+	return;
+
+nothing_sent:
+	/* Normally, we request a CLEAR from the MSC and terminate as soon as the CLEAR COMMAND has been issued by the
+	 * MSC. But if we are trying to clear without being able to send anything to the MSC, we might as well shut down
+	 * the conn right away now. */
+	conn_fsm_state_chg(ST_WAIT_SCCP_RLSD);
+}
+
+void gscon_fsm_wait_sccp_rlsd_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)
+{
+	struct gsm_subscriber_connection *conn = fi->priv;
+
+	/* According to 3GPP 48.008 3.1.9.1. "The BSS need not wait for the radio channel
+	 * release to be completed or for the guard timer to expire before returning the
+	 * CLEAR COMPLETE message" */
+	if (!gscon_sigtran_send(conn, gsm0808_create_clear_complete()))
+		rate_ctr_inc(rate_ctr_group_get_ctr(conn->sccp.msc->msc_ctrs, MSC_CTR_BSSMAP_TX_DT1_CLEAR_COMPLETE));
+
+	/* Give the handover_fsm a chance to book this as handover success before tearing down everything,
+	 * making it look like a sudden death failure. */
+	if (conn->ho.fi)
+		osmo_fsm_inst_dispatch(conn->ho.fi, HO_EV_CONN_RELEASING, NULL);
+
+	if (conn->lcs.loc_req)
+		osmo_fsm_inst_dispatch(conn->lcs.loc_req->fi, LCS_LOC_REQ_EV_CONN_CLEAR, NULL);
+
+	gscon_release_lchans(conn, true, bsc_gsm48_rr_cause_from_gsm0808_cause(conn->clear_cause));
+	osmo_mgcpc_ep_clear(conn->user_plane.mgw_endpoint);
 }
 
 /* forward MO DTAP from RSL side to BSSAP side */
@@ -682,13 +711,13 @@
 		.name = "INIT",
 		.in_event_mask = S(GSCON_EV_MO_COMPL_L3) | S(GSCON_EV_A_CONN_IND)
 			| S(GSCON_EV_HANDOVER_END),
-		.out_state_mask = S(ST_WAIT_CC) | S(ST_ACTIVE) | S(ST_CLEARING),
+		.out_state_mask = S(ST_WAIT_CC) | S(ST_ACTIVE) | S(ST_WAIT_CLEAR_CMD) | S(ST_WAIT_SCCP_RLSD),
 		.action = gscon_fsm_init,
 	 },
 	[ST_WAIT_CC] = {
 		.name = "WAIT_CC",
 		.in_event_mask = S(GSCON_EV_A_CONN_CFM),
-		.out_state_mask = S(ST_ACTIVE) | S(ST_CLEARING),
+		.out_state_mask = S(ST_ACTIVE) | S(ST_WAIT_CLEAR_CMD) | S(ST_WAIT_SCCP_RLSD),
 		.action = gscon_fsm_wait_cc,
 	},
 	[ST_ACTIVE] = {
@@ -698,27 +727,32 @@
 				 | S(GSCON_EV_LCS_LOC_REQ_END)
 				 | S(GSCON_EV_MO_COMPL_L3)
 				 ,
-		.out_state_mask = S(ST_CLEARING) | S(ST_ASSIGNMENT) |
+		.out_state_mask = S(ST_WAIT_CLEAR_CMD) | S(ST_WAIT_SCCP_RLSD) | S(ST_ASSIGNMENT) |
 				  S(ST_HANDOVER),
 		.action = gscon_fsm_active,
 	},
 	[ST_ASSIGNMENT] = {
 		.name = "ASSIGNMENT",
 		.in_event_mask = EV_TRANSPARENT_SCCP | S(GSCON_EV_ASSIGNMENT_END),
-		.out_state_mask = S(ST_ACTIVE) | S(ST_CLEARING),
+		.out_state_mask = S(ST_ACTIVE) | S(ST_WAIT_CLEAR_CMD) | S(ST_WAIT_SCCP_RLSD),
 		.action = gscon_fsm_assignment,
 	},
 	[ST_HANDOVER] = {
 		.name = "HANDOVER",
 		.in_event_mask = EV_TRANSPARENT_SCCP | S(GSCON_EV_HANDOVER_END),
-		.out_state_mask = S(ST_ACTIVE) | S(ST_CLEARING),
+		.out_state_mask = S(ST_ACTIVE) | S(ST_WAIT_CLEAR_CMD) | S(ST_WAIT_SCCP_RLSD),
 		.action = gscon_fsm_handover,
 	},
-	[ST_CLEARING] = {
-		.name = "CLEARING",
-		.onenter = gscon_fsm_clearing_onenter,
-		/* dead end state */
-	 },
+	[ST_WAIT_CLEAR_CMD] = {
+		.name = "WAIT_CLEAR_CMD",
+		.onenter = gscon_fsm_wait_clear_cmd_onenter,
+		.out_state_mask = S(ST_WAIT_SCCP_RLSD),
+	},
+	[ST_WAIT_SCCP_RLSD] = {
+		.name = "WAIT_SCCP_RLSD",
+		.onenter = gscon_fsm_wait_sccp_rlsd_onenter,
+		.in_event_mask = S(GSCON_EV_HANDOVER_END),
+	},
 };
 
 void gscon_change_primary_lchan(struct gsm_subscriber_connection *conn, struct gsm_lchan *new_lchan)
@@ -848,44 +882,19 @@
 static void gscon_fsm_allstate(struct osmo_fsm_inst *fi, uint32_t event, void *data)
 {
 	struct gsm_subscriber_connection *conn = fi->priv;
-	const enum gsm0808_cause *cause_0808;
 	const struct tlv_parsed *tp;
 	struct osmo_mobile_identity mi_imsi;
 
 	/* Regular allstate event processing */
 	switch (event) {
 	case GSCON_EV_A_CLEAR_CMD:
-		conn->rx_clear_command = true;
-
-		/* Give the handover_fsm a chance to book this as handover success before tearing down everything,
-		 * making it look like a sudden death failure. */
-		if (conn->ho.fi)
-			osmo_fsm_inst_dispatch(conn->ho.fi, HO_EV_CONN_RELEASING, NULL);
-
-		if (conn->lcs.loc_req)
-			osmo_fsm_inst_dispatch(conn->lcs.loc_req->fi, LCS_LOC_REQ_EV_CONN_CLEAR, NULL);
-
 		OSMO_ASSERT(data);
-		cause_0808 = data;
-		/* MSC tells us to cleanly shut down */
-		if (conn->fi->state != ST_CLEARING)
-			osmo_fsm_inst_state_chg(fi, ST_CLEARING, 60, -4);
-		LOGPFSML(fi, LOGL_DEBUG, "Releasing all lchans (if any) after BSSMAP Clear Command\n");
-		gscon_release_lchans(conn, true, bsc_gsm48_rr_cause_from_gsm0808_cause(*cause_0808));
-		/* FIXME: Release all terestrial resources in ST_CLEARING */
-		/* According to 3GPP 48.008 3.1.9.1. "The BSS need not wait for the radio channel
-		 * release to be completed or for the guard timer to expire before returning the
-		 * CLEAR COMPLETE message" */
-
-		/* Close MGCP connections */
-		osmo_mgcpc_ep_clear(conn->user_plane.mgw_endpoint);
-
-		rate_ctr_inc(rate_ctr_group_get_ctr(conn->sccp.msc->msc_ctrs, MSC_CTR_BSSMAP_TX_DT1_CLEAR_COMPLETE));
-		gscon_sigtran_send(conn, gsm0808_create_clear_complete());
+		conn->clear_cause = *(const enum gsm0808_cause*)data;
+		conn_fsm_state_chg(ST_WAIT_SCCP_RLSD);
 		break;
 	case GSCON_EV_A_DISC_IND:
-		/* MSC or SIGTRAN network has hard-released SCCP connection,
-		 * terminate the FSM now. */
+		/* MSC or SIGTRAN network has hard-released SCCP connection, terminate the FSM now.
+		 * Cleanup is done in gscon_pre_term() and gscon_cleanup(). */
 		osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REGULAR, data);
 		break;
 	case GSCON_EV_FORGET_MGW_ENDPOINT:
@@ -975,6 +984,13 @@
 
 	osmo_mgcpc_ep_clear(conn->user_plane.mgw_endpoint);
 	conn->user_plane.mgw_endpoint = NULL;
+	conn->user_plane.mgw_endpoint = NULL;
+
+	if (conn->ho.fi)
+		osmo_fsm_inst_dispatch(conn->ho.fi, HO_EV_CONN_RELEASING, NULL);
+
+	if (conn->lcs.loc_req)
+		osmo_fsm_inst_dispatch(conn->lcs.loc_req->fi, LCS_LOC_REQ_EV_CONN_CLEAR, NULL);
 
 	if (conn->lcls.fi) {
 		/* request termination of LCLS FSM */
@@ -1013,8 +1029,9 @@
 	case -4:
 		/* The MSC has sent a BSSMAP Clear Command, we acknowledged that, but the conn was never
 		 * disconnected. */
-		LOGPFSML(fi, LOGL_ERROR, "Long after a BSSMAP Clear Command, the conn is still not"
-			 " released. For sanity, discarding this conn now.\n");
+		LOGPFSML(fi, LOGL_ERROR, "Long after expecting %s, the conn is still not"
+			 " released. For sanity, discarding this conn now.\n",
+			 fi->state == ST_WAIT_CLEAR_CMD ? "BSSMAP Clear Command" : "SCCP RLSD");
 		a_reset_conn_fail(conn->sccp.msc);
 		osmo_fsm_inst_term(fi, OSMO_FSM_TERM_ERROR, NULL);
 		break;
diff --git a/tests/handover/handover_test.c b/tests/handover/handover_test.c
index 17bc048..dd2f16a 100644
--- a/tests/handover/handover_test.c
+++ b/tests/handover/handover_test.c
@@ -1710,3 +1710,7 @@
 	};
 	return &ret;
 }
+struct mgcp_client *osmo_mgcpc_ep_client(const struct osmo_mgcpc_ep *ep)
+{
+	return NULL;
+}

-- 
To view, visit https://gerrit.osmocom.org/c/osmo-bsc/+/26614
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-bsc
Gerrit-Branch: master
Gerrit-Change-Id: Ie975117d37f38ba853589dc7f8d3e94f8f9586b2
Gerrit-Change-Number: 26614
Gerrit-PatchSet: 1
Gerrit-Owner: neels <nhofmeyr at sysmocom.de>
Gerrit-Reviewer: laforge <laforge at osmocom.org>
Gerrit-Reviewer: pespin <pespin at sysmocom.de>
Gerrit-MessageType: newchange
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20211217/5ac935a1/attachment.htm>


More information about the gerrit-log mailing list