Change in osmo-bsc[master]: BSSMAP RESET: generalize a_reset FSM

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/.

laforge gerrit-no-reply at lists.osmocom.org
Thu Oct 15 05:53:03 UTC 2020


laforge has submitted this change. ( https://gerrit.osmocom.org/c/osmo-bsc/+/20625 )

Change subject: BSSMAP RESET: generalize a_reset FSM
......................................................................

BSSMAP RESET: generalize a_reset FSM

Separate the a_reset FSM implementation from BSSMAP and MSC specifics, so that
it can be re-used on the Lb interface.

Move the FSM implementation to bssmap_reset.c and tweak, to match common practices we
have generally established in our osmo_fsm implementations.

Keep a_reset.h and a_reset.c and redirect to bssmap_reset.c.

A difficulty is setting a proper logging category: the FSM definition allows
only one fixed logging category for FSM state transitions and events. Ideally,
the BSSMAP reset fsm would log on DMSC, and the BSSMAP-LE reset fsm would log
on DLCS. Since that is not possible, introduce a separate DRESET logging
category. This in fact matches an item on my wishlist, because if a given MSC
is configured but currently not connected, the previous RESET FSM would
continuously "spam" log LOGL_NOTICE messages indicating that it is resending
RESET, and I often want to silence those messages without silencing the entire
DMSC category. This is now easily possible by setting DRESET logging to
LOGL_ERROR. There is additional "link up" / "link lost" logging on DMSC, so all
interesting info is still visible on DMSC.

Change-Id: Ib3c3a163186c40a93be0dea666230431172136df
---
M include/osmocom/bsc/Makefile.am
M include/osmocom/bsc/a_reset.h
M include/osmocom/bsc/bsc_msc_data.h
A include/osmocom/bsc/bssmap_reset.h
M include/osmocom/bsc/debug.h
M include/osmocom/bsc/osmo_bsc_sigtran.h
M src/osmo-bsc/Makefile.am
M src/osmo-bsc/a_reset.c
A src/osmo-bsc/bssmap_reset.c
M src/osmo-bsc/osmo_bsc_main.c
M src/osmo-bsc/osmo_bsc_sigtran.c
M tests/handover/handover_test.c
12 files changed, 283 insertions(+), 190 deletions(-)

Approvals:
  Jenkins Builder: Verified
  laforge: Looks good to me, approved



diff --git a/include/osmocom/bsc/Makefile.am b/include/osmocom/bsc/Makefile.am
index 8c42287..05d71bb 100644
--- a/include/osmocom/bsc/Makefile.am
+++ b/include/osmocom/bsc/Makefile.am
@@ -48,6 +48,7 @@
 	paging.h \
 	pcu_if.h \
 	pcuif_proto.h \
+	bssmap_reset.h \
 	rest_octets.h \
 	rs232.h \
 	signal.h \
diff --git a/include/osmocom/bsc/a_reset.h b/include/osmocom/bsc/a_reset.h
index 46a392f..dd44ea5 100644
--- a/include/osmocom/bsc/a_reset.h
+++ b/include/osmocom/bsc/a_reset.h
@@ -23,7 +23,7 @@
 struct bsc_msc_data;
 
 /* 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);
 
 /* Confirm that we successfully received a reset acknowledge message */
 void a_reset_ack_confirm(struct bsc_msc_data *msc);
diff --git a/include/osmocom/bsc/bsc_msc_data.h b/include/osmocom/bsc/bsc_msc_data.h
index 5699b77..5622a42 100644
--- a/include/osmocom/bsc/bsc_msc_data.h
+++ b/include/osmocom/bsc/bsc_msc_data.h
@@ -171,7 +171,7 @@
 
 		/* Pointer to the osmo-fsm that controls the
 		 * BSSMAP RESET procedure */
-		struct osmo_fsm_inst *reset_fsm;
+		struct bssmap_reset *bssmap_reset;
 	} a;
 
 	uint32_t x_osmo_ign;
diff --git a/include/osmocom/bsc/bssmap_reset.h b/include/osmocom/bsc/bssmap_reset.h
new file mode 100644
index 0000000..ba64257
--- /dev/null
+++ b/include/osmocom/bsc/bssmap_reset.h
@@ -0,0 +1,27 @@
+/* Manage RESET and disconnection detection on BSSMAP and BSSMAP-LE */
+#pragma once
+
+enum bssmap_reset_fsm_event {
+	BSSMAP_RESET_EV_RX_RESET_ACK,
+	BSSMAP_RESET_EV_CONN_CFM_SUCCESS,
+	BSSMAP_RESET_EV_CONN_CFM_FAILURE,
+};
+
+struct bssmap_reset_cfg {
+	int conn_cfm_failure_threshold;
+	struct {
+		void (*tx_reset)(void *data);
+		void (*link_up)(void *data);
+		void (*link_lost)(void *data);
+	} ops;
+	void *data;
+};
+
+struct bssmap_reset {
+	struct osmo_fsm_inst *fi;
+	struct bssmap_reset_cfg cfg;
+	int conn_cfm_failures;
+};
+
+struct bssmap_reset *bssmap_reset_alloc(void *ctx, const char *label, const struct bssmap_reset_cfg *cfg);
+bool bssmap_reset_is_conn_ready(const struct bssmap_reset *bssmap_reset);
diff --git a/include/osmocom/bsc/debug.h b/include/osmocom/bsc/debug.h
index 0380b74..4ad61b4 100644
--- a/include/osmocom/bsc/debug.h
+++ b/include/osmocom/bsc/debug.h
@@ -28,6 +28,7 @@
 	DAS,
 	DCBS,
 	DLCS,
+	DRESET,
 	Debug_LastEntry,
 };
 
diff --git a/include/osmocom/bsc/osmo_bsc_sigtran.h b/include/osmocom/bsc/osmo_bsc_sigtran.h
index faaceb2..79afa6b 100644
--- a/include/osmocom/bsc/osmo_bsc_sigtran.h
+++ b/include/osmocom/bsc/osmo_bsc_sigtran.h
@@ -40,6 +40,8 @@
 /* Close all open sigtran connections and channels */
 void osmo_bsc_sigtran_reset(const struct bsc_msc_data *msc);
 
+void osmo_bsc_sigtran_tx_reset(const struct bsc_msc_data *msc);
+
 /* Send reset-ack to MSC */
 void osmo_bsc_sigtran_tx_reset_ack(const struct bsc_msc_data *msc);
 
diff --git a/src/osmo-bsc/Makefile.am b/src/osmo-bsc/Makefile.am
index 8d109fd..4473fc1 100644
--- a/src/osmo-bsc/Makefile.am
+++ b/src/osmo-bsc/Makefile.am
@@ -89,6 +89,7 @@
 	paging.c \
 	pcu_sock.c \
 	penalty_timers.c \
+	bssmap_reset.c \
 	rest_octets.c \
 	system_information.c \
 	timeslot_fsm.c \
diff --git a/src/osmo-bsc/a_reset.c b/src/osmo-bsc/a_reset.c
index 9446d13..feaf491 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>
+#include <osmocom/bsc/bssmap_reset.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)
+static void a_reset_tx_reset(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);
+	struct bsc_msc_data *msc = data;
+	osmo_bsc_sigtran_tx_reset(msc);
 }
 
-/* Called when entering Disconnected state */
-static void fsm_disc_onenter_cb(struct osmo_fsm_inst *fi, uint32_t prev_state)
+static void a_reset_link_up(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;
+	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);
 }
 
-/* Connected state event handler */
-static void fsm_conn_cb(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+static void a_reset_link_lost(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 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);
 }
 
-/* Called when entering Connected state */
-static void fsm_conn_onenter_cb(struct osmo_fsm_inst *fi, uint32_t prev_state)
-{
-	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);
-	}
-}
-
-/* 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);
+	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;
+	}
 
-	/* 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);
+	msc->a.bssmap_reset = bssmap_reset_alloc(msc, name, &cfg);
 }
 
 /* Confirm that we successfully received a reset acknowledge message */
@@ -203,10 +77,10 @@
 	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 @@
 	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 @@
 	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 @@
 	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);
 }
diff --git a/src/osmo-bsc/bssmap_reset.c b/src/osmo-bsc/bssmap_reset.c
new file mode 100644
index 0000000..98f6b65
--- /dev/null
+++ b/src/osmo-bsc/bssmap_reset.c
@@ -0,0 +1,198 @@
+/* (C) 2020 by sysmocom s.f.m.c. GmbH <info at sysmocom.de>
+ * All Rights Reserved
+ *
+ * Authors: Philipp Maier, Neels Hofmeyr
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <osmocom/core/fsm.h>
+#include <osmocom/core/tdef.h>
+#include <osmocom/bsc/debug.h>
+#include <osmocom/bsc/bssmap_reset.h>
+#include <osmocom/bsc/gsm_data.h>
+
+static struct osmo_fsm bssmap_reset_fsm;
+
+enum bssmap_reset_fsm_state {
+	BSSMAP_RESET_ST_DISC,
+	BSSMAP_RESET_ST_CONN,
+};
+
+static const struct value_string bssmap_reset_fsm_event_names[] = {
+	OSMO_VALUE_STRING(BSSMAP_RESET_EV_RX_RESET_ACK),
+	OSMO_VALUE_STRING(BSSMAP_RESET_EV_CONN_CFM_FAILURE),
+	OSMO_VALUE_STRING(BSSMAP_RESET_EV_CONN_CFM_SUCCESS),
+	{}
+};
+
+static const struct osmo_tdef_state_timeout bssmap_reset_timeouts[32] = {
+	[BSSMAP_RESET_ST_DISC] = { .T = 4 },
+};
+
+#define bssmap_reset_fsm_state_chg(FI, STATE) \
+	osmo_tdef_fsm_inst_state_chg(FI, STATE, \
+				     bssmap_reset_timeouts, \
+				     (bsc_gsmnet)->T_defs, \
+				     5)
+
+struct bssmap_reset *bssmap_reset_alloc(void *ctx, const char *label, const struct bssmap_reset_cfg *cfg)
+{
+	struct bssmap_reset *bssmap_reset;
+	struct osmo_fsm_inst *fi;
+
+	fi = osmo_fsm_inst_alloc(&bssmap_reset_fsm, ctx, NULL, LOGL_DEBUG, label);
+	OSMO_ASSERT(fi);
+
+	bssmap_reset = talloc_zero(fi, struct bssmap_reset);
+	OSMO_ASSERT(bssmap_reset);
+	*bssmap_reset = (struct bssmap_reset){
+		.fi = fi,
+		.cfg = *cfg,
+	};
+	fi->priv = bssmap_reset;
+
+	/* Immediately (1ms) kick off reset sending mechanism */
+	osmo_fsm_inst_state_chg_ms(fi, BSSMAP_RESET_ST_DISC, 1, 0);
+	return bssmap_reset;
+}
+
+static void link_up(struct bssmap_reset *bssmap_reset)
+{
+	LOGPFSML(bssmap_reset->fi, LOGL_NOTICE, "link up\n");
+	bssmap_reset->conn_cfm_failures = 0;
+	if (bssmap_reset->cfg.ops.link_up)
+		bssmap_reset->cfg.ops.link_up(bssmap_reset->cfg.data);
+}
+
+static void link_lost(struct bssmap_reset *bssmap_reset)
+{
+	LOGPFSML(bssmap_reset->fi, LOGL_NOTICE, "link lost\n");
+	if (bssmap_reset->cfg.ops.link_lost)
+		bssmap_reset->cfg.ops.link_lost(bssmap_reset->cfg.data);
+}
+
+static void tx_reset(struct bssmap_reset *bssmap_reset)
+{
+	if (bssmap_reset->cfg.ops.tx_reset)
+		bssmap_reset->cfg.ops.tx_reset(bssmap_reset->cfg.data);
+}
+
+static void bssmap_reset_disc_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)
+{
+	struct bssmap_reset *bssmap_reset = (struct bssmap_reset*)fi->priv;
+	if (prev_state == BSSMAP_RESET_ST_CONN)
+		link_lost(bssmap_reset);
+}
+
+static void bssmap_reset_disc_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+	bssmap_reset_fsm_state_chg(fi, BSSMAP_RESET_ST_CONN);
+}
+
+static void bssmap_reset_conn_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)
+{
+	struct bssmap_reset *bssmap_reset = (struct bssmap_reset*)fi->priv;
+	if (prev_state != BSSMAP_RESET_ST_CONN)
+		link_up(bssmap_reset);
+}
+
+static void bssmap_reset_conn_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+	struct bssmap_reset *bssmap_reset = (struct bssmap_reset*)fi->priv;
+
+	switch (event) {
+
+	case BSSMAP_RESET_EV_RX_RESET_ACK:
+		LOGPFSML(fi, LOGL_INFO, "Ignoring duplicate RESET ACK\n");
+		break;
+
+	case BSSMAP_RESET_EV_CONN_CFM_FAILURE:
+		bssmap_reset->conn_cfm_failures++;
+		if (bssmap_reset->conn_cfm_failures > bssmap_reset->cfg.conn_cfm_failure_threshold)
+			bssmap_reset_fsm_state_chg(fi, BSSMAP_RESET_ST_DISC);
+		break;
+
+	case BSSMAP_RESET_EV_CONN_CFM_SUCCESS:
+		bssmap_reset->conn_cfm_failures = 0;
+		break;
+
+	default:
+		OSMO_ASSERT(false);
+	}
+}
+
+static int bssmap_reset_fsm_timer_cb(struct osmo_fsm_inst *fi)
+{
+	struct bssmap_reset *bssmap_reset = (struct bssmap_reset*)fi->priv;
+
+	tx_reset(bssmap_reset);
+
+	/* (re-)enter disconnect state to resend RESET after timeout. */
+	bssmap_reset_fsm_state_chg(fi, BSSMAP_RESET_ST_DISC);
+
+	/* Return 0 to not terminate the fsm */
+	return 0;
+}
+
+#define S(x) (1 << (x))
+
+static struct osmo_fsm_state bssmap_reset_fsm_states[] = {
+	[BSSMAP_RESET_ST_DISC] = {
+		     .name = "DISC",
+		     .in_event_mask = 0
+			     | S(BSSMAP_RESET_EV_RX_RESET_ACK)
+			     ,
+		     .out_state_mask = 0
+			     | S(BSSMAP_RESET_ST_DISC)
+			     | S(BSSMAP_RESET_ST_CONN)
+			     ,
+		     .onenter = bssmap_reset_disc_onenter,
+		     .action = bssmap_reset_disc_action,
+		     },
+	[BSSMAP_RESET_ST_CONN] = {
+		     .name = "CONN",
+		     .in_event_mask = 0
+			     | S(BSSMAP_RESET_EV_RX_RESET_ACK)
+			     | S(BSSMAP_RESET_EV_CONN_CFM_FAILURE)
+			     | S(BSSMAP_RESET_EV_CONN_CFM_SUCCESS)
+			     ,
+		     .out_state_mask = 0
+			     | S(BSSMAP_RESET_ST_DISC)
+			     | S(BSSMAP_RESET_ST_CONN)
+			     ,
+		     .onenter = bssmap_reset_conn_onenter,
+		     .action = bssmap_reset_conn_action,
+		     },
+};
+
+static struct osmo_fsm bssmap_reset_fsm = {
+	.name = "bssmap_reset",
+	.states = bssmap_reset_fsm_states,
+	.num_states = ARRAY_SIZE(bssmap_reset_fsm_states),
+	.log_subsys = DRESET,
+	.timer_cb = bssmap_reset_fsm_timer_cb,
+	.event_names = bssmap_reset_fsm_event_names,
+};
+
+bool bssmap_reset_is_conn_ready(const struct bssmap_reset *bssmap_reset)
+{
+	return bssmap_reset->fi->state == BSSMAP_RESET_ST_CONN;
+}
+
+static __attribute__((constructor)) void bssmap_reset_fsm_init()
+{
+	OSMO_ASSERT(osmo_fsm_register(&bssmap_reset_fsm) == 0);
+}
diff --git a/src/osmo-bsc/osmo_bsc_main.c b/src/osmo-bsc/osmo_bsc_main.c
index 26d32d1..35ddbbf 100644
--- a/src/osmo-bsc/osmo_bsc_main.c
+++ b/src/osmo-bsc/osmo_bsc_main.c
@@ -795,6 +795,11 @@
 		.description = "Location Services",
 		.enabled = 1, .loglevel = LOGL_NOTICE,
 	},
+	[DRESET] = {
+		.name = "DRESET",
+		.description = "RESET/ACK on A and Lb interfaces",
+		.enabled = 1, .loglevel = LOGL_NOTICE,
+	},
 };
 
 static int filter_fn(const struct log_context *ctx, struct log_target *tar)
diff --git a/src/osmo-bsc/osmo_bsc_sigtran.c b/src/osmo-bsc/osmo_bsc_sigtran.c
index 6853fac..75b3b58 100644
--- a/src/osmo-bsc/osmo_bsc_sigtran.c
+++ b/src/osmo-bsc/osmo_bsc_sigtran.c
@@ -80,7 +80,7 @@
 }
 
 /* Send reset to MSC */
-static void osmo_bsc_sigtran_tx_reset(const struct bsc_msc_data *msc)
+void osmo_bsc_sigtran_tx_reset(const struct bsc_msc_data *msc)
 {
 	struct osmo_ss7_instance *ss7;
 	struct msgb *msg;
@@ -434,18 +434,6 @@
 	}
 }
 
-/* Callback function: Close all open connections */
-static void osmo_bsc_sigtran_reset_cb(const void *priv)
-{
-	struct bsc_msc_data *msc = (struct bsc_msc_data*) priv;
-
-	/* Shut down all ongoing traffic */
-	osmo_bsc_sigtran_reset(msc);
-
-	/* Send reset to MSC */
-	osmo_bsc_sigtran_tx_reset(msc);
-}
-
 /* Default point-code to be used as local address (BSC) */
 #define BSC_DEFAULT_PC "0.23.3"
 
@@ -619,7 +607,7 @@
 				return -EINVAL;
 
 			/* Start MSC-Reset procedure */
-			a_reset_alloc(msc, msc_name, osmo_bsc_sigtran_reset_cb);
+			a_reset_alloc(msc, msc_name);
 		}
 	}
 
diff --git a/tests/handover/handover_test.c b/tests/handover/handover_test.c
index d3f29e1..230192b 100644
--- a/tests/handover/handover_test.c
+++ b/tests/handover/handover_test.c
@@ -1815,3 +1815,7 @@
 enum handover_result bsc_tx_bssmap_ho_complete(struct gsm_subscriber_connection *conn,
 					       struct gsm_lchan *lchan) { return HO_RESULT_OK; }
 void bsc_tx_bssmap_ho_failure(struct gsm_subscriber_connection *conn) {}
+void osmo_bsc_sigtran_tx_reset(void) {}
+void osmo_bsc_sigtran_reset(void) {}
+void bssmap_reset_alloc(void) {}
+void bssmap_reset_is_conn_ready(void) {}

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

Gerrit-Project: osmo-bsc
Gerrit-Branch: master
Gerrit-Change-Id: Ib3c3a163186c40a93be0dea666230431172136df
Gerrit-Change-Number: 20625
Gerrit-PatchSet: 2
Gerrit-Owner: neels <nhofmeyr at sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <laforge at osmocom.org>
Gerrit-Reviewer: pespin <pespin at sysmocom.de>
Gerrit-MessageType: merged
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20201015/bbf99df5/attachment.htm>


More information about the gerrit-log mailing list