<p>laforge <strong>submitted</strong> this change.</p><p><a href="https://gerrit.osmocom.org/c/osmo-bsc/+/20625">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Jenkins Builder: Verified
  laforge: Looks good to me, approved

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">BSSMAP RESET: generalize a_reset FSM<br><br>Separate the a_reset FSM implementation from BSSMAP and MSC specifics, so that<br>it can be re-used on the Lb interface.<br><br>Move the FSM implementation to bssmap_reset.c and tweak, to match common practices we<br>have generally established in our osmo_fsm implementations.<br><br>Keep a_reset.h and a_reset.c and redirect to bssmap_reset.c.<br><br>A difficulty is setting a proper logging category: the FSM definition allows<br>only one fixed logging category for FSM state transitions and events. Ideally,<br>the BSSMAP reset fsm would log on DMSC, and the BSSMAP-LE reset fsm would log<br>on DLCS. Since that is not possible, introduce a separate DRESET logging<br>category. This in fact matches an item on my wishlist, because if a given MSC<br>is configured but currently not connected, the previous RESET FSM would<br>continuously "spam" log LOGL_NOTICE messages indicating that it is resending<br>RESET, and I often want to silence those messages without silencing the entire<br>DMSC category. This is now easily possible by setting DRESET logging to<br>LOGL_ERROR. There is additional "link up" / "link lost" logging on DMSC, so all<br>interesting info is still visible on DMSC.<br><br>Change-Id: Ib3c3a163186c40a93be0dea666230431172136df<br>---<br>M include/osmocom/bsc/Makefile.am<br>M include/osmocom/bsc/a_reset.h<br>M include/osmocom/bsc/bsc_msc_data.h<br>A include/osmocom/bsc/bssmap_reset.h<br>M include/osmocom/bsc/debug.h<br>M include/osmocom/bsc/osmo_bsc_sigtran.h<br>M src/osmo-bsc/Makefile.am<br>M src/osmo-bsc/a_reset.c<br>A src/osmo-bsc/bssmap_reset.c<br>M src/osmo-bsc/osmo_bsc_main.c<br>M src/osmo-bsc/osmo_bsc_sigtran.c<br>M tests/handover/handover_test.c<br>12 files changed, 283 insertions(+), 190 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/osmocom/bsc/Makefile.am b/include/osmocom/bsc/Makefile.am</span><br><span>index 8c42287..05d71bb 100644</span><br><span>--- a/include/osmocom/bsc/Makefile.am</span><br><span>+++ b/include/osmocom/bsc/Makefile.am</span><br><span>@@ -48,6 +48,7 @@</span><br><span>         paging.h \</span><br><span>   pcu_if.h \</span><br><span>   pcuif_proto.h \</span><br><span style="color: hsl(120, 100%, 40%);">+       bssmap_reset.h \</span><br><span>     rest_octets.h \</span><br><span>      rs232.h \</span><br><span>    signal.h \</span><br><span>diff --git a/include/osmocom/bsc/a_reset.h b/include/osmocom/bsc/a_reset.h</span><br><span>index 46a392f..dd44ea5 100644</span><br><span>--- a/include/osmocom/bsc/a_reset.h</span><br><span>+++ b/include/osmocom/bsc/a_reset.h</span><br><span>@@ -23,7 +23,7 @@</span><br><span> struct bsc_msc_data;</span><br><span> </span><br><span> /* Create and start state machine which handles the reset/reset-ack procedure */</span><br><span style="color: hsl(0, 100%, 40%);">-void a_reset_alloc(struct bsc_msc_data *msc, const char *name, void *cb);</span><br><span style="color: hsl(120, 100%, 40%);">+void a_reset_alloc(struct bsc_msc_data *msc, const char *name);</span><br><span> </span><br><span> /* Confirm that we successfully received a reset acknowledge message */</span><br><span> void a_reset_ack_confirm(struct bsc_msc_data *msc);</span><br><span>diff --git a/include/osmocom/bsc/bsc_msc_data.h b/include/osmocom/bsc/bsc_msc_data.h</span><br><span>index 5699b77..5622a42 100644</span><br><span>--- a/include/osmocom/bsc/bsc_msc_data.h</span><br><span>+++ b/include/osmocom/bsc/bsc_msc_data.h</span><br><span>@@ -171,7 +171,7 @@</span><br><span> </span><br><span>               /* Pointer to the osmo-fsm that controls the</span><br><span>                  * BSSMAP RESET procedure */</span><br><span style="color: hsl(0, 100%, 40%);">-            struct osmo_fsm_inst *reset_fsm;</span><br><span style="color: hsl(120, 100%, 40%);">+              struct bssmap_reset *bssmap_reset;</span><br><span>   } a;</span><br><span> </span><br><span>     uint32_t x_osmo_ign;</span><br><span>diff --git a/include/osmocom/bsc/bssmap_reset.h b/include/osmocom/bsc/bssmap_reset.h</span><br><span>new file mode 100644</span><br><span>index 0000000..ba64257</span><br><span>--- /dev/null</span><br><span>+++ b/include/osmocom/bsc/bssmap_reset.h</span><br><span>@@ -0,0 +1,27 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/* Manage RESET and disconnection detection on BSSMAP and BSSMAP-LE */</span><br><span style="color: hsl(120, 100%, 40%);">+#pragma once</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum bssmap_reset_fsm_event {</span><br><span style="color: hsl(120, 100%, 40%);">+      BSSMAP_RESET_EV_RX_RESET_ACK,</span><br><span style="color: hsl(120, 100%, 40%);">+ BSSMAP_RESET_EV_CONN_CFM_SUCCESS,</span><br><span style="color: hsl(120, 100%, 40%);">+     BSSMAP_RESET_EV_CONN_CFM_FAILURE,</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct bssmap_reset_cfg {</span><br><span style="color: hsl(120, 100%, 40%);">+    int conn_cfm_failure_threshold;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct {</span><br><span style="color: hsl(120, 100%, 40%);">+              void (*tx_reset)(void *data);</span><br><span style="color: hsl(120, 100%, 40%);">+         void (*link_up)(void *data);</span><br><span style="color: hsl(120, 100%, 40%);">+          void (*link_lost)(void *data);</span><br><span style="color: hsl(120, 100%, 40%);">+        } ops;</span><br><span style="color: hsl(120, 100%, 40%);">+        void *data;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct bssmap_reset {</span><br><span style="color: hsl(120, 100%, 40%);">+      struct osmo_fsm_inst *fi;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct bssmap_reset_cfg cfg;</span><br><span style="color: hsl(120, 100%, 40%);">+  int conn_cfm_failures;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct bssmap_reset *bssmap_reset_alloc(void *ctx, const char *label, const struct bssmap_reset_cfg *cfg);</span><br><span style="color: hsl(120, 100%, 40%);">+bool bssmap_reset_is_conn_ready(const struct bssmap_reset *bssmap_reset);</span><br><span>diff --git a/include/osmocom/bsc/debug.h b/include/osmocom/bsc/debug.h</span><br><span>index 0380b74..4ad61b4 100644</span><br><span>--- a/include/osmocom/bsc/debug.h</span><br><span>+++ b/include/osmocom/bsc/debug.h</span><br><span>@@ -28,6 +28,7 @@</span><br><span>     DAS,</span><br><span>         DCBS,</span><br><span>        DLCS,</span><br><span style="color: hsl(120, 100%, 40%);">+ DRESET,</span><br><span>      Debug_LastEntry,</span><br><span> };</span><br><span> </span><br><span>diff --git a/include/osmocom/bsc/osmo_bsc_sigtran.h b/include/osmocom/bsc/osmo_bsc_sigtran.h</span><br><span>index faaceb2..79afa6b 100644</span><br><span>--- a/include/osmocom/bsc/osmo_bsc_sigtran.h</span><br><span>+++ b/include/osmocom/bsc/osmo_bsc_sigtran.h</span><br><span>@@ -40,6 +40,8 @@</span><br><span> /* Close all open sigtran connections and channels */</span><br><span> void osmo_bsc_sigtran_reset(const struct bsc_msc_data *msc);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+void osmo_bsc_sigtran_tx_reset(const struct bsc_msc_data *msc);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* Send reset-ack to MSC */</span><br><span> void osmo_bsc_sigtran_tx_reset_ack(const struct bsc_msc_data *msc);</span><br><span> </span><br><span>diff --git a/src/osmo-bsc/Makefile.am b/src/osmo-bsc/Makefile.am</span><br><span>index 8d109fd..4473fc1 100644</span><br><span>--- a/src/osmo-bsc/Makefile.am</span><br><span>+++ b/src/osmo-bsc/Makefile.am</span><br><span>@@ -89,6 +89,7 @@</span><br><span>       paging.c \</span><br><span>   pcu_sock.c \</span><br><span>         penalty_timers.c \</span><br><span style="color: hsl(120, 100%, 40%);">+    bssmap_reset.c \</span><br><span>     rest_octets.c \</span><br><span>      system_information.c \</span><br><span>       timeslot_fsm.c \</span><br><span>diff --git a/src/osmo-bsc/a_reset.c b/src/osmo-bsc/a_reset.c</span><br><span>index 9446d13..feaf491 100644</span><br><span>--- a/src/osmo-bsc/a_reset.c</span><br><span>+++ b/src/osmo-bsc/a_reset.c</span><br><span>@@ -18,183 +18,57 @@</span><br><span>  *</span><br><span>  */</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-#include <osmocom/core/logging.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <osmocom/core/utils.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <osmocom/core/timer.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <osmocom/core/fsm.h></span><br><span> #include <osmocom/core/signal.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <unistd.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <errno.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <string.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/bsc/signal.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #include <osmocom/bsc/debug.h></span><br><span> #include <osmocom/bsc/bsc_msc_data.h></span><br><span> #include <osmocom/bsc/osmo_bsc_sigtran.h></span><br><span style="color: hsl(0, 100%, 40%);">-#include <osmocom/bsc/signal.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/bsc/bssmap_reset.h></span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-#define RESET_RESEND_INTERVAL 2           /* sec */</span><br><span style="color: hsl(0, 100%, 40%);">-#define RESET_RESEND_TIMER_NO 4                /* See also 3GPP TS 48.008 Chapter 3.1.4.1.3.1 */</span><br><span style="color: hsl(0, 100%, 40%);">-#define BAD_CONNECTION_THRESOLD 3      /* connection failures */</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* Reset context data (callbacks, state machine etc...) */</span><br><span style="color: hsl(0, 100%, 40%);">-struct reset_ctx {</span><br><span style="color: hsl(0, 100%, 40%);">-   /* Connection failure counter. When this counter</span><br><span style="color: hsl(0, 100%, 40%);">-         * reaches a certain threshold, the reset procedure</span><br><span style="color: hsl(0, 100%, 40%);">-      * will be triggered */</span><br><span style="color: hsl(0, 100%, 40%);">- int conn_loss_counter;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  /* Callback function to be called when a connection</span><br><span style="color: hsl(0, 100%, 40%);">-      * failure is detected and a rest must occur */</span><br><span style="color: hsl(0, 100%, 40%);">- void (*cb)(void *priv);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* Privated data for the callback function */</span><br><span style="color: hsl(0, 100%, 40%);">-   void *priv;</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-enum reset_fsm_states {</span><br><span style="color: hsl(0, 100%, 40%);">-    ST_DISC,                /* Disconnected from remote end */</span><br><span style="color: hsl(0, 100%, 40%);">-      ST_CONN,                /* We have a confirmed connection */</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-enum reset_fsm_evt {</span><br><span style="color: hsl(0, 100%, 40%);">-      EV_RESET_ACK,           /* got reset acknowlegement from remote end */</span><br><span style="color: hsl(0, 100%, 40%);">-  EV_N_DISCONNECT,        /* lost a connection */</span><br><span style="color: hsl(0, 100%, 40%);">- EV_N_CONNECT,           /* made a successful connection */</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static const struct value_string fsm_event_names[] = {</span><br><span style="color: hsl(0, 100%, 40%);">-      OSMO_VALUE_STRING(EV_RESET_ACK),</span><br><span style="color: hsl(0, 100%, 40%);">-        OSMO_VALUE_STRING(EV_N_DISCONNECT),</span><br><span style="color: hsl(0, 100%, 40%);">-     OSMO_VALUE_STRING(EV_N_CONNECT),</span><br><span style="color: hsl(0, 100%, 40%);">-        {0, NULL}</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* Disconnected state event handler */</span><br><span style="color: hsl(0, 100%, 40%);">-static void fsm_disc_cb(struct osmo_fsm_inst *fi, uint32_t event, void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+static void a_reset_tx_reset(void *data)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-   struct reset_ctx *reset_ctx = (struct reset_ctx *)fi->priv;</span><br><span style="color: hsl(0, 100%, 40%);">-  OSMO_ASSERT(reset_ctx);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- reset_ctx->conn_loss_counter = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-    osmo_fsm_inst_state_chg(fi, ST_CONN, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+   struct bsc_msc_data *msc = data;</span><br><span style="color: hsl(120, 100%, 40%);">+      osmo_bsc_sigtran_tx_reset(msc);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/* Called when entering Disconnected state */</span><br><span style="color: hsl(0, 100%, 40%);">-static void fsm_disc_onenter_cb(struct osmo_fsm_inst *fi, uint32_t prev_state)</span><br><span style="color: hsl(120, 100%, 40%);">+static void a_reset_link_up(void *data)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-       struct reset_ctx *reset_ctx = (struct reset_ctx *)fi->priv;</span><br><span style="color: hsl(0, 100%, 40%);">-  struct bsc_msc_data *msc = reset_ctx->priv;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  LOGPFSML(fi, LOGL_NOTICE, "BSSMAP MSC assocation is down, reconnecting...\n");</span><br><span style="color: hsl(0, 100%, 40%);">-        if (prev_state != ST_DISC) {</span><br><span style="color: hsl(0, 100%, 40%);">-            osmo_stat_item_dec(msc->msc_statg->items[MSC_STAT_MSC_LINKS_ACTIVE], 1);</span><br><span style="color: hsl(0, 100%, 40%);">-          osmo_signal_dispatch(SS_MSC, S_MSC_LOST, msc);</span><br><span style="color: hsl(0, 100%, 40%);">-  }</span><br><span style="color: hsl(120, 100%, 40%);">+     struct bsc_msc_data *msc = data;</span><br><span style="color: hsl(120, 100%, 40%);">+      LOGP(DMSC, LOGL_NOTICE, "(msc%d) BSSMAP assocation is up\n", msc->nr);</span><br><span style="color: hsl(120, 100%, 40%);">+   osmo_stat_item_inc(msc->msc_statg->items[MSC_STAT_MSC_LINKS_ACTIVE], 1);</span><br><span style="color: hsl(120, 100%, 40%);">+        osmo_signal_dispatch(SS_MSC, S_MSC_CONNECTED, msc);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/* Connected state event handler */</span><br><span style="color: hsl(0, 100%, 40%);">-static void fsm_conn_cb(struct osmo_fsm_inst *fi, uint32_t event, void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+static void a_reset_link_lost(void *data)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-    struct reset_ctx *reset_ctx = (struct reset_ctx *)fi->priv;</span><br><span style="color: hsl(0, 100%, 40%);">-  OSMO_ASSERT(reset_ctx);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- switch (event) {</span><br><span style="color: hsl(0, 100%, 40%);">-        case EV_N_DISCONNECT:</span><br><span style="color: hsl(0, 100%, 40%);">-           if (reset_ctx->conn_loss_counter >= BAD_CONNECTION_THRESOLD)</span><br><span style="color: hsl(0, 100%, 40%);">-                      osmo_fsm_inst_state_chg(fi, ST_DISC, RESET_RESEND_INTERVAL, RESET_RESEND_TIMER_NO);</span><br><span style="color: hsl(0, 100%, 40%);">-             else</span><br><span style="color: hsl(0, 100%, 40%);">-                    reset_ctx->conn_loss_counter++;</span><br><span style="color: hsl(0, 100%, 40%);">-              break;</span><br><span style="color: hsl(0, 100%, 40%);">-  case EV_N_CONNECT:</span><br><span style="color: hsl(0, 100%, 40%);">-              reset_ctx->conn_loss_counter = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-            break;</span><br><span style="color: hsl(0, 100%, 40%);">-  case EV_RESET_ACK:</span><br><span style="color: hsl(0, 100%, 40%);">-              LOGPFSML(fi, LOGL_INFO, "Received a duplicated BSSMAP RESET ACK, ignoring\n");</span><br><span style="color: hsl(0, 100%, 40%);">-                break;</span><br><span style="color: hsl(0, 100%, 40%);">-  }</span><br><span style="color: hsl(120, 100%, 40%);">+     struct bsc_msc_data *msc = data;</span><br><span style="color: hsl(120, 100%, 40%);">+      LOGP(DMSC, LOGL_NOTICE, "(msc%d) BSSMAP assocation is down\n", msc->nr);</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_stat_item_dec(msc->msc_statg->items[MSC_STAT_MSC_LINKS_ACTIVE], 1);</span><br><span style="color: hsl(120, 100%, 40%);">+        osmo_signal_dispatch(SS_MSC, S_MSC_LOST, msc);</span><br><span style="color: hsl(120, 100%, 40%);">+        osmo_bsc_sigtran_reset(msc);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/* Called when entering Connected state */</span><br><span style="color: hsl(0, 100%, 40%);">-static void fsm_conn_onenter_cb(struct osmo_fsm_inst *fi, uint32_t prev_state)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-  struct reset_ctx *reset_ctx = (struct reset_ctx *)fi->priv;</span><br><span style="color: hsl(0, 100%, 40%);">-  struct bsc_msc_data *msc = reset_ctx->priv;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  LOGPFSML(fi, LOGL_NOTICE, "BSSMAP MSC assocation is up.\n");</span><br><span style="color: hsl(0, 100%, 40%);">-  if (prev_state != ST_CONN) {</span><br><span style="color: hsl(0, 100%, 40%);">-            osmo_stat_item_inc(msc->msc_statg->items[MSC_STAT_MSC_LINKS_ACTIVE], 1);</span><br><span style="color: hsl(0, 100%, 40%);">-          osmo_signal_dispatch(SS_MSC, S_MSC_CONNECTED, msc);</span><br><span style="color: hsl(0, 100%, 40%);">-     }</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* Timer callback to retransmit the reset signal */</span><br><span style="color: hsl(0, 100%, 40%);">-static int fsm_reset_ack_timeout_cb(struct osmo_fsm_inst *fi)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-     struct reset_ctx *reset_ctx = (struct reset_ctx *)fi->priv;</span><br><span style="color: hsl(0, 100%, 40%);">-  OSMO_ASSERT(reset_ctx);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- LOGPFSML(fi, LOGL_NOTICE, "(re)sending BSSMAP RESET message...\n");</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-   reset_ctx->cb(reset_ctx->priv);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-   osmo_fsm_inst_state_chg(fi, ST_DISC, RESET_RESEND_INTERVAL, RESET_RESEND_TIMER_NO);</span><br><span style="color: hsl(0, 100%, 40%);">-     return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static struct osmo_fsm_state reset_fsm_states[] = {</span><br><span style="color: hsl(0, 100%, 40%);">-   [ST_DISC] = {</span><br><span style="color: hsl(0, 100%, 40%);">-                .in_event_mask = (1 << EV_RESET_ACK),</span><br><span style="color: hsl(0, 100%, 40%);">-                     .out_state_mask = (1 << ST_DISC) | (1 << ST_CONN),</span><br><span style="color: hsl(0, 100%, 40%);">-                  .name = "DISC",</span><br><span style="color: hsl(0, 100%, 40%);">-               .action = fsm_disc_cb,</span><br><span style="color: hsl(0, 100%, 40%);">-                  .onenter = fsm_disc_onenter_cb,</span><br><span style="color: hsl(0, 100%, 40%);">-                 },</span><br><span style="color: hsl(0, 100%, 40%);">- [ST_CONN] = {</span><br><span style="color: hsl(0, 100%, 40%);">-                .in_event_mask = (1 << EV_N_DISCONNECT) | (1 << EV_N_CONNECT) | (1 << EV_RESET_ACK),</span><br><span style="color: hsl(0, 100%, 40%);">-                  .out_state_mask = (1 << ST_DISC) | (1 << ST_CONN),</span><br><span style="color: hsl(0, 100%, 40%);">-                  .name = "CONN",</span><br><span style="color: hsl(0, 100%, 40%);">-               .action = fsm_conn_cb,</span><br><span style="color: hsl(0, 100%, 40%);">-                  .onenter = fsm_conn_onenter_cb,</span><br><span style="color: hsl(0, 100%, 40%);">-                 },</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-/* State machine definition */</span><br><span style="color: hsl(0, 100%, 40%);">-static struct osmo_fsm fsm = {</span><br><span style="color: hsl(0, 100%, 40%);">-   .name = "A-RESET",</span><br><span style="color: hsl(0, 100%, 40%);">-    .states = reset_fsm_states,</span><br><span style="color: hsl(0, 100%, 40%);">-     .num_states = ARRAY_SIZE(reset_fsm_states),</span><br><span style="color: hsl(0, 100%, 40%);">-     .log_subsys = DMSC,</span><br><span style="color: hsl(0, 100%, 40%);">-     .timer_cb = fsm_reset_ack_timeout_cb,</span><br><span style="color: hsl(0, 100%, 40%);">-   .event_names = fsm_event_names,</span><br><span style="color: hsl(0, 100%, 40%);">-};</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> /* Create and start state machine which handles the reset/reset-ack procedure */</span><br><span style="color: hsl(0, 100%, 40%);">-void a_reset_alloc(struct bsc_msc_data *msc, const char *name, void *cb)</span><br><span style="color: hsl(120, 100%, 40%);">+void a_reset_alloc(struct bsc_msc_data *msc, const char *name)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-      struct reset_ctx *reset_ctx;</span><br><span style="color: hsl(0, 100%, 40%);">-    struct osmo_fsm_inst *reset_fsm;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-        OSMO_ASSERT(msc);</span><br><span style="color: hsl(0, 100%, 40%);">-       OSMO_ASSERT(name);</span><br><span style="color: hsl(0, 100%, 40%);">-      OSMO_ASSERT(cb);</span><br><span style="color: hsl(120, 100%, 40%);">+      struct bssmap_reset_cfg cfg = {</span><br><span style="color: hsl(120, 100%, 40%);">+               .conn_cfm_failure_threshold = 3,</span><br><span style="color: hsl(120, 100%, 40%);">+              .ops = {</span><br><span style="color: hsl(120, 100%, 40%);">+                      .tx_reset = a_reset_tx_reset,</span><br><span style="color: hsl(120, 100%, 40%);">+                 .link_up = a_reset_link_up,</span><br><span style="color: hsl(120, 100%, 40%);">+                   .link_lost = a_reset_link_lost,</span><br><span style="color: hsl(120, 100%, 40%);">+               },</span><br><span style="color: hsl(120, 100%, 40%);">+            .data = msc,</span><br><span style="color: hsl(120, 100%, 40%);">+  };</span><br><span> </span><br><span>       /* There must not be any double allocation! */</span><br><span style="color: hsl(0, 100%, 40%);">-  OSMO_ASSERT(msc->a.reset_fsm == NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (msc->a.bssmap_reset) {</span><br><span style="color: hsl(120, 100%, 40%);">+         LOGP(DMSC, LOGL_ERROR, "(msc%d) will not allocate a second reset FSM for this MSC\n", msc->nr);</span><br><span style="color: hsl(120, 100%, 40%);">+          return;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   /* Allocate and configure a new fsm instance */</span><br><span style="color: hsl(0, 100%, 40%);">- reset_ctx = talloc_zero(msc, struct reset_ctx);</span><br><span style="color: hsl(0, 100%, 40%);">- OSMO_ASSERT(reset_ctx);</span><br><span style="color: hsl(0, 100%, 40%);">- reset_ctx->priv = msc;</span><br><span style="color: hsl(0, 100%, 40%);">-       reset_ctx->cb = cb;</span><br><span style="color: hsl(0, 100%, 40%);">-  reset_ctx->conn_loss_counter = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-    reset_fsm = osmo_fsm_inst_alloc(&fsm, msc, reset_ctx, LOGL_DEBUG, name);</span><br><span style="color: hsl(0, 100%, 40%);">-    OSMO_ASSERT(reset_fsm);</span><br><span style="color: hsl(0, 100%, 40%);">- msc->a.reset_fsm = reset_fsm;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-        /* Immediately (1ms) kick off reset sending mechanism */</span><br><span style="color: hsl(0, 100%, 40%);">-        osmo_fsm_inst_state_chg_ms(reset_fsm, ST_DISC, 1, RESET_RESEND_TIMER_NO);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       /* Count the new MSC link */</span><br><span style="color: hsl(0, 100%, 40%);">-    osmo_stat_item_inc(msc->msc_statg->items[MSC_STAT_MSC_LINKS_TOTAL], 1);</span><br><span style="color: hsl(120, 100%, 40%);">+ msc->a.bssmap_reset = bssmap_reset_alloc(msc, name, &cfg);</span><br><span> }</span><br><span> </span><br><span> /* Confirm that we successfully received a reset acknowledge message */</span><br><span>@@ -203,10 +77,10 @@</span><br><span>         if (!msc)</span><br><span>            return;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     if (!msc->a.reset_fsm)</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!msc->a.bssmap_reset)</span><br><span>                 return;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     osmo_fsm_inst_dispatch(msc->a.reset_fsm, EV_RESET_ACK, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+      osmo_fsm_inst_dispatch(msc->a.bssmap_reset->fi, BSSMAP_RESET_EV_RX_RESET_ACK, NULL);</span><br><span> }</span><br><span> </span><br><span> /* Report a failed connection */</span><br><span>@@ -215,10 +89,10 @@</span><br><span>       if (!msc)</span><br><span>            return;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     if (!msc->a.reset_fsm)</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!msc->a.bssmap_reset)</span><br><span>                 return;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     osmo_fsm_inst_dispatch(msc->a.reset_fsm, EV_N_DISCONNECT, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+   osmo_fsm_inst_dispatch(msc->a.bssmap_reset->fi, BSSMAP_RESET_EV_CONN_CFM_FAILURE, NULL);</span><br><span> }</span><br><span> </span><br><span> /* Report a successful connection */</span><br><span>@@ -227,10 +101,10 @@</span><br><span>      if (!msc)</span><br><span>            return;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     if (!msc->a.reset_fsm)</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!msc->a.bssmap_reset)</span><br><span>                 return;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     osmo_fsm_inst_dispatch(msc->a.reset_fsm, EV_N_CONNECT, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+      osmo_fsm_inst_dispatch(msc->a.bssmap_reset->fi, BSSMAP_RESET_EV_CONN_CFM_SUCCESS, NULL);</span><br><span> }</span><br><span> </span><br><span> /* Check if we have a connection to a specified msc */</span><br><span>@@ -239,16 +113,8 @@</span><br><span>     if (!msc)</span><br><span>            return false;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-       if (!msc->a.reset_fsm)</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!msc->a.bssmap_reset)</span><br><span>                 return false;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-       if (msc->a.reset_fsm->state == ST_CONN)</span><br><span style="color: hsl(0, 100%, 40%);">-           return true;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-    return false;</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-static __attribute__((constructor)) void a_reset_fsm_init()</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-      OSMO_ASSERT(osmo_fsm_register(&fsm) == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+        return bssmap_reset_is_conn_ready(msc->a.bssmap_reset);</span><br><span> }</span><br><span>diff --git a/src/osmo-bsc/bssmap_reset.c b/src/osmo-bsc/bssmap_reset.c</span><br><span>new file mode 100644</span><br><span>index 0000000..98f6b65</span><br><span>--- /dev/null</span><br><span>+++ b/src/osmo-bsc/bssmap_reset.c</span><br><span>@@ -0,0 +1,198 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/* (C) 2020 by sysmocom s.f.m.c. GmbH <info@sysmocom.de></span><br><span style="color: hsl(120, 100%, 40%);">+ * All Rights Reserved</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Authors: Philipp Maier, Neels Hofmeyr</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU Affero General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; either version 3 of the License, or</span><br><span style="color: hsl(120, 100%, 40%);">+ * (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU Affero General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * You should have received a copy of the GNU Affero General Public License</span><br><span style="color: hsl(120, 100%, 40%);">+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/fsm.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/core/tdef.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/bsc/debug.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/bsc/bssmap_reset.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmocom/bsc/gsm_data.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct osmo_fsm bssmap_reset_fsm;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum bssmap_reset_fsm_state {</span><br><span style="color: hsl(120, 100%, 40%);">+        BSSMAP_RESET_ST_DISC,</span><br><span style="color: hsl(120, 100%, 40%);">+ BSSMAP_RESET_ST_CONN,</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static const struct value_string bssmap_reset_fsm_event_names[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_VALUE_STRING(BSSMAP_RESET_EV_RX_RESET_ACK),</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_VALUE_STRING(BSSMAP_RESET_EV_CONN_CFM_FAILURE),</span><br><span style="color: hsl(120, 100%, 40%);">+  OSMO_VALUE_STRING(BSSMAP_RESET_EV_CONN_CFM_SUCCESS),</span><br><span style="color: hsl(120, 100%, 40%);">+  {}</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static const struct osmo_tdef_state_timeout bssmap_reset_timeouts[32] = {</span><br><span style="color: hsl(120, 100%, 40%);">+   [BSSMAP_RESET_ST_DISC] = { .T = 4 },</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define bssmap_reset_fsm_state_chg(FI, STATE) \</span><br><span style="color: hsl(120, 100%, 40%);">+   osmo_tdef_fsm_inst_state_chg(FI, STATE, \</span><br><span style="color: hsl(120, 100%, 40%);">+                                  bssmap_reset_timeouts, \</span><br><span style="color: hsl(120, 100%, 40%);">+                              (bsc_gsmnet)->T_defs, \</span><br><span style="color: hsl(120, 100%, 40%);">+                                    5)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct bssmap_reset *bssmap_reset_alloc(void *ctx, const char *label, const struct bssmap_reset_cfg *cfg)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       struct bssmap_reset *bssmap_reset;</span><br><span style="color: hsl(120, 100%, 40%);">+    struct osmo_fsm_inst *fi;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   fi = osmo_fsm_inst_alloc(&bssmap_reset_fsm, ctx, NULL, LOGL_DEBUG, label);</span><br><span style="color: hsl(120, 100%, 40%);">+        OSMO_ASSERT(fi);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    bssmap_reset = talloc_zero(fi, struct bssmap_reset);</span><br><span style="color: hsl(120, 100%, 40%);">+  OSMO_ASSERT(bssmap_reset);</span><br><span style="color: hsl(120, 100%, 40%);">+    *bssmap_reset = (struct bssmap_reset){</span><br><span style="color: hsl(120, 100%, 40%);">+                .fi = fi,</span><br><span style="color: hsl(120, 100%, 40%);">+             .cfg = *cfg,</span><br><span style="color: hsl(120, 100%, 40%);">+  };</span><br><span style="color: hsl(120, 100%, 40%);">+    fi->priv = bssmap_reset;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Immediately (1ms) kick off reset sending mechanism */</span><br><span style="color: hsl(120, 100%, 40%);">+      osmo_fsm_inst_state_chg_ms(fi, BSSMAP_RESET_ST_DISC, 1, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+   return bssmap_reset;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void link_up(struct bssmap_reset *bssmap_reset)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  LOGPFSML(bssmap_reset->fi, LOGL_NOTICE, "link up\n");</span><br><span style="color: hsl(120, 100%, 40%);">+    bssmap_reset->conn_cfm_failures = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+       if (bssmap_reset->cfg.ops.link_up)</span><br><span style="color: hsl(120, 100%, 40%);">+         bssmap_reset->cfg.ops.link_up(bssmap_reset->cfg.data);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void link_lost(struct bssmap_reset *bssmap_reset)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        LOGPFSML(bssmap_reset->fi, LOGL_NOTICE, "link lost\n");</span><br><span style="color: hsl(120, 100%, 40%);">+  if (bssmap_reset->cfg.ops.link_lost)</span><br><span style="color: hsl(120, 100%, 40%);">+               bssmap_reset->cfg.ops.link_lost(bssmap_reset->cfg.data);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void tx_reset(struct bssmap_reset *bssmap_reset)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       if (bssmap_reset->cfg.ops.tx_reset)</span><br><span style="color: hsl(120, 100%, 40%);">+                bssmap_reset->cfg.ops.tx_reset(bssmap_reset->cfg.data);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void bssmap_reset_disc_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   struct bssmap_reset *bssmap_reset = (struct bssmap_reset*)fi->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+        if (prev_state == BSSMAP_RESET_ST_CONN)</span><br><span style="color: hsl(120, 100%, 40%);">+               link_lost(bssmap_reset);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void bssmap_reset_disc_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  bssmap_reset_fsm_state_chg(fi, BSSMAP_RESET_ST_CONN);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void bssmap_reset_conn_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   struct bssmap_reset *bssmap_reset = (struct bssmap_reset*)fi->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+        if (prev_state != BSSMAP_RESET_ST_CONN)</span><br><span style="color: hsl(120, 100%, 40%);">+               link_up(bssmap_reset);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void bssmap_reset_conn_action(struct osmo_fsm_inst *fi, uint32_t event, void *data)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    struct bssmap_reset *bssmap_reset = (struct bssmap_reset*)fi->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      switch (event) {</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    case BSSMAP_RESET_EV_RX_RESET_ACK:</span><br><span style="color: hsl(120, 100%, 40%);">+            LOGPFSML(fi, LOGL_INFO, "Ignoring duplicate RESET ACK\n");</span><br><span style="color: hsl(120, 100%, 40%);">+          break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      case BSSMAP_RESET_EV_CONN_CFM_FAILURE:</span><br><span style="color: hsl(120, 100%, 40%);">+                bssmap_reset->conn_cfm_failures++;</span><br><span style="color: hsl(120, 100%, 40%);">+         if (bssmap_reset->conn_cfm_failures > bssmap_reset->cfg.conn_cfm_failure_threshold)</span><br><span style="color: hsl(120, 100%, 40%);">+                  bssmap_reset_fsm_state_chg(fi, BSSMAP_RESET_ST_DISC);</span><br><span style="color: hsl(120, 100%, 40%);">+         break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      case BSSMAP_RESET_EV_CONN_CFM_SUCCESS:</span><br><span style="color: hsl(120, 100%, 40%);">+                bssmap_reset->conn_cfm_failures = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+               break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      default:</span><br><span style="color: hsl(120, 100%, 40%);">+              OSMO_ASSERT(false);</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int bssmap_reset_fsm_timer_cb(struct osmo_fsm_inst *fi)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     struct bssmap_reset *bssmap_reset = (struct bssmap_reset*)fi->priv;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      tx_reset(bssmap_reset);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /* (re-)enter disconnect state to resend RESET after timeout. */</span><br><span style="color: hsl(120, 100%, 40%);">+      bssmap_reset_fsm_state_chg(fi, BSSMAP_RESET_ST_DISC);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       /* Return 0 to not terminate the fsm */</span><br><span style="color: hsl(120, 100%, 40%);">+       return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define S(x) (1 << (x))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct osmo_fsm_state bssmap_reset_fsm_states[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+   [BSSMAP_RESET_ST_DISC] = {</span><br><span style="color: hsl(120, 100%, 40%);">+                 .name = "DISC",</span><br><span style="color: hsl(120, 100%, 40%);">+                     .in_event_mask = 0</span><br><span style="color: hsl(120, 100%, 40%);">+                            | S(BSSMAP_RESET_EV_RX_RESET_ACK)</span><br><span style="color: hsl(120, 100%, 40%);">+                             ,</span><br><span style="color: hsl(120, 100%, 40%);">+                     .out_state_mask = 0</span><br><span style="color: hsl(120, 100%, 40%);">+                           | S(BSSMAP_RESET_ST_DISC)</span><br><span style="color: hsl(120, 100%, 40%);">+                             | S(BSSMAP_RESET_ST_CONN)</span><br><span style="color: hsl(120, 100%, 40%);">+                             ,</span><br><span style="color: hsl(120, 100%, 40%);">+                     .onenter = bssmap_reset_disc_onenter,</span><br><span style="color: hsl(120, 100%, 40%);">+                 .action = bssmap_reset_disc_action,</span><br><span style="color: hsl(120, 100%, 40%);">+                   },</span><br><span style="color: hsl(120, 100%, 40%);">+       [BSSMAP_RESET_ST_CONN] = {</span><br><span style="color: hsl(120, 100%, 40%);">+                 .name = "CONN",</span><br><span style="color: hsl(120, 100%, 40%);">+                     .in_event_mask = 0</span><br><span style="color: hsl(120, 100%, 40%);">+                            | S(BSSMAP_RESET_EV_RX_RESET_ACK)</span><br><span style="color: hsl(120, 100%, 40%);">+                             | S(BSSMAP_RESET_EV_CONN_CFM_FAILURE)</span><br><span style="color: hsl(120, 100%, 40%);">+                         | S(BSSMAP_RESET_EV_CONN_CFM_SUCCESS)</span><br><span style="color: hsl(120, 100%, 40%);">+                         ,</span><br><span style="color: hsl(120, 100%, 40%);">+                     .out_state_mask = 0</span><br><span style="color: hsl(120, 100%, 40%);">+                           | S(BSSMAP_RESET_ST_DISC)</span><br><span style="color: hsl(120, 100%, 40%);">+                             | S(BSSMAP_RESET_ST_CONN)</span><br><span style="color: hsl(120, 100%, 40%);">+                             ,</span><br><span style="color: hsl(120, 100%, 40%);">+                     .onenter = bssmap_reset_conn_onenter,</span><br><span style="color: hsl(120, 100%, 40%);">+                 .action = bssmap_reset_conn_action,</span><br><span style="color: hsl(120, 100%, 40%);">+                   },</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct osmo_fsm bssmap_reset_fsm = {</span><br><span style="color: hsl(120, 100%, 40%);">+    .name = "bssmap_reset",</span><br><span style="color: hsl(120, 100%, 40%);">+     .states = bssmap_reset_fsm_states,</span><br><span style="color: hsl(120, 100%, 40%);">+    .num_states = ARRAY_SIZE(bssmap_reset_fsm_states),</span><br><span style="color: hsl(120, 100%, 40%);">+    .log_subsys = DRESET,</span><br><span style="color: hsl(120, 100%, 40%);">+ .timer_cb = bssmap_reset_fsm_timer_cb,</span><br><span style="color: hsl(120, 100%, 40%);">+        .event_names = bssmap_reset_fsm_event_names,</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+bool bssmap_reset_is_conn_ready(const struct bssmap_reset *bssmap_reset)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       return bssmap_reset->fi->state == BSSMAP_RESET_ST_CONN;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static __attribute__((constructor)) void bssmap_reset_fsm_init()</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       OSMO_ASSERT(osmo_fsm_register(&bssmap_reset_fsm) == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/src/osmo-bsc/osmo_bsc_main.c b/src/osmo-bsc/osmo_bsc_main.c</span><br><span>index 26d32d1..35ddbbf 100644</span><br><span>--- a/src/osmo-bsc/osmo_bsc_main.c</span><br><span>+++ b/src/osmo-bsc/osmo_bsc_main.c</span><br><span>@@ -795,6 +795,11 @@</span><br><span>           .description = "Location Services",</span><br><span>                .enabled = 1, .loglevel = LOGL_NOTICE,</span><br><span>       },</span><br><span style="color: hsl(120, 100%, 40%);">+    [DRESET] = {</span><br><span style="color: hsl(120, 100%, 40%);">+          .name = "DRESET",</span><br><span style="color: hsl(120, 100%, 40%);">+           .description = "RESET/ACK on A and Lb interfaces",</span><br><span style="color: hsl(120, 100%, 40%);">+          .enabled = 1, .loglevel = LOGL_NOTICE,</span><br><span style="color: hsl(120, 100%, 40%);">+        },</span><br><span> };</span><br><span> </span><br><span> static int filter_fn(const struct log_context *ctx, struct log_target *tar)</span><br><span>diff --git a/src/osmo-bsc/osmo_bsc_sigtran.c b/src/osmo-bsc/osmo_bsc_sigtran.c</span><br><span>index 6853fac..75b3b58 100644</span><br><span>--- a/src/osmo-bsc/osmo_bsc_sigtran.c</span><br><span>+++ b/src/osmo-bsc/osmo_bsc_sigtran.c</span><br><span>@@ -80,7 +80,7 @@</span><br><span> }</span><br><span> </span><br><span> /* Send reset to MSC */</span><br><span style="color: hsl(0, 100%, 40%);">-static void osmo_bsc_sigtran_tx_reset(const struct bsc_msc_data *msc)</span><br><span style="color: hsl(120, 100%, 40%);">+void osmo_bsc_sigtran_tx_reset(const struct bsc_msc_data *msc)</span><br><span> {</span><br><span>       struct osmo_ss7_instance *ss7;</span><br><span>       struct msgb *msg;</span><br><span>@@ -434,18 +434,6 @@</span><br><span>     }</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/* Callback function: Close all open connections */</span><br><span style="color: hsl(0, 100%, 40%);">-static void osmo_bsc_sigtran_reset_cb(const void *priv)</span><br><span style="color: hsl(0, 100%, 40%);">-{</span><br><span style="color: hsl(0, 100%, 40%);">-   struct bsc_msc_data *msc = (struct bsc_msc_data*) priv;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- /* Shut down all ongoing traffic */</span><br><span style="color: hsl(0, 100%, 40%);">-     osmo_bsc_sigtran_reset(msc);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-    /* Send reset to MSC */</span><br><span style="color: hsl(0, 100%, 40%);">- osmo_bsc_sigtran_tx_reset(msc);</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> /* Default point-code to be used as local address (BSC) */</span><br><span> #define BSC_DEFAULT_PC "0.23.3"</span><br><span> </span><br><span>@@ -619,7 +607,7 @@</span><br><span>                                return -EINVAL;</span><br><span> </span><br><span>                  /* Start MSC-Reset procedure */</span><br><span style="color: hsl(0, 100%, 40%);">-                 a_reset_alloc(msc, msc_name, osmo_bsc_sigtran_reset_cb);</span><br><span style="color: hsl(120, 100%, 40%);">+                      a_reset_alloc(msc, msc_name);</span><br><span>                }</span><br><span>    }</span><br><span> </span><br><span>diff --git a/tests/handover/handover_test.c b/tests/handover/handover_test.c</span><br><span>index d3f29e1..230192b 100644</span><br><span>--- a/tests/handover/handover_test.c</span><br><span>+++ b/tests/handover/handover_test.c</span><br><span>@@ -1815,3 +1815,7 @@</span><br><span> enum handover_result bsc_tx_bssmap_ho_complete(struct gsm_subscriber_connection *conn,</span><br><span>                                                struct gsm_lchan *lchan) { return HO_RESULT_OK; }</span><br><span> void bsc_tx_bssmap_ho_failure(struct gsm_subscriber_connection *conn) {}</span><br><span style="color: hsl(120, 100%, 40%);">+void osmo_bsc_sigtran_tx_reset(void) {}</span><br><span style="color: hsl(120, 100%, 40%);">+void osmo_bsc_sigtran_reset(void) {}</span><br><span style="color: hsl(120, 100%, 40%);">+void bssmap_reset_alloc(void) {}</span><br><span style="color: hsl(120, 100%, 40%);">+void bssmap_reset_is_conn_ready(void) {}</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-bsc/+/20625">change 20625</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/osmo-bsc/+/20625"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmo-bsc </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: Ib3c3a163186c40a93be0dea666230431172136df </div>
<div style="display:none"> Gerrit-Change-Number: 20625 </div>
<div style="display:none"> Gerrit-PatchSet: 2 </div>
<div style="display:none"> Gerrit-Owner: neels <nhofmeyr@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>
<div style="display:none"> Gerrit-Reviewer: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-Reviewer: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>