aboutsummaryrefslogtreecommitdiffstats
path: root/src/common
diff options
context:
space:
mode:
authorPau Espin Pedrol <pespin@sysmocom.de>2020-10-02 17:06:45 +0200
committerlaforge <laforge@osmocom.org>2020-10-20 13:45:57 +0000
commit88fe4b079d1b10c0cfd35c49cad1484bc91be308 (patch)
tree1aa5aa15bb5083ff30aa915bca3c0db7d853eb4b /src/common
parent6d117891c93da969e0ff8b293bef97c699490f2b (diff)
Introduce NM BTS Site Manager FSM
This fixes old behavior mimicing broken behavior in nanoBTS (according to TS 12.21) where BTS Site Mgr NM object was announced as Enabled despite no OPSTART was sent by the BSC. With this new FSM, BTS SiteManager will be announced as Disabled Offline during OML startup conversation, instead of Enabled. The new osmo-bsc OML management FSMs use this change in behavior to find out whether it should use the old broken management states (without Offline state, as per nanoBTS) or use the new state transitions (which allow fixing several race conditions). Change-Id: Iab2d17c45c9642860cd2d5d523c1baae24502243
Diffstat (limited to 'src/common')
-rw-r--r--src/common/Makefile.am2
-rw-r--r--src/common/bts.c25
-rw-r--r--src/common/nm_bts_sm_fsm.c145
-rw-r--r--src/common/nm_common_fsm.c31
4 files changed, 198 insertions, 5 deletions
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index e3a72dc8..458041e3 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -37,6 +37,8 @@ libbts_a_SOURCES = \
dtx_dl_amr_fsm.c \
scheduler_mframe.c \
ta_control.c \
+ nm_common_fsm.c \
+ nm_bts_sm_fsm.c \
$(NULL)
libl1sched_a_SOURCES = scheduler.c
diff --git a/src/common/bts.c b/src/common/bts.c
index 8a97b8fa..07706400 100644
--- a/src/common/bts.c
+++ b/src/common/bts.c
@@ -52,6 +52,7 @@
#include <osmo-bts/dtx_dl_amr_fsm.h>
#include <osmo-bts/cbch.h>
#include <osmo-bts/bts_shutdown_fsm.h>
+#include <osmo-bts/nm_common_fsm.h>
#define MIN_QUAL_RACH 50 /* minimum link quality (in centiBels) for Access Bursts */
#define MIN_QUAL_NORM -5 /* minimum link quality (in centiBels) for Normal Bursts */
@@ -200,6 +201,15 @@ const struct value_string bts_impl_flag_desc[] = {
{ 0, NULL }
};
+static int gsm_bts_talloc_destructor(struct gsm_bts *bts)
+{
+ if (bts->site_mgr.mo.fi) {
+ osmo_fsm_inst_free(bts->site_mgr.mo.fi);
+ bts->site_mgr.mo.fi = NULL;
+ }
+ return 0;
+}
+
struct gsm_bts *gsm_bts_alloc(void *ctx, uint8_t bts_num)
{
struct gsm_bts *bts = talloc_zero(ctx, struct gsm_bts);
@@ -208,6 +218,8 @@ struct gsm_bts *gsm_bts_alloc(void *ctx, uint8_t bts_num)
if (!bts)
return NULL;
+ talloc_set_destructor(bts, gsm_bts_talloc_destructor);
+
bts->nr = bts_num;
bts->num_trx = 0;
INIT_LLIST_HEAD(&bts->trx_list);
@@ -219,10 +231,13 @@ struct gsm_bts *gsm_bts_alloc(void *ctx, uint8_t bts_num)
LOGL_INFO, NULL);
osmo_fsm_inst_update_id_f(bts->shutdown_fi, "bts%d", bts->nr);
+ bts->site_mgr.mo.fi = osmo_fsm_inst_alloc(&nm_bts_sm_fsm, bts, &bts->site_mgr,
+ LOGL_INFO, "bts_sm");
+ gsm_mo_init(&bts->site_mgr.mo, bts, NM_OC_SITE_MANAGER,
+ 0xff, 0xff, 0xff);
+
gsm_mo_init(&bts->mo, bts, NM_OC_BTS,
bts->nr, 0xff, 0xff);
- gsm_mo_init(&bts->site_mgr.mo, bts, NM_OC_SITE_MANAGER,
- 0xff, 0xff, 0xff);
for (i = 0; i < ARRAY_SIZE(bts->gprs.nsvc); i++) {
bts->gprs.nsvc[i].bts = bts;
@@ -331,7 +346,7 @@ int bts_init(struct gsm_bts *bts)
bts->radio_link_timeout.current = bts->radio_link_timeout.oml;
/* Start with the site manager */
- oml_mo_state_init(&bts->site_mgr.mo, NM_OPSTATE_ENABLED, NM_AVSTATE_OK);
+ oml_mo_state_init(&bts->site_mgr.mo, NM_OPSTATE_DISABLED, NM_AVSTATE_NOT_INSTALLED);
/* set BTS to dependency */
oml_mo_state_init(&bts->mo, -1, NM_AVSTATE_DEPENDENCY);
@@ -395,8 +410,8 @@ int bts_link_estab(struct gsm_bts *bts)
LOGP(DSUM, LOGL_INFO, "Main link established, sending NM Status.\n");
- /* BTS and SITE MGR are EANBLED, BTS is DEPENDENCY */
- oml_tx_state_changed(&bts->site_mgr.mo);
+ /* BTS SITE MGR becomes Offline (tx SW ACT Report), BTS is DEPENDENCY */
+ osmo_fsm_inst_dispatch(bts->site_mgr.mo.fi, NM_EV_SW_ACT, NULL);
oml_tx_state_changed(&bts->mo);
/* those should all be in DEPENDENCY */
diff --git a/src/common/nm_bts_sm_fsm.c b/src/common/nm_bts_sm_fsm.c
new file mode 100644
index 00000000..dedbacbd
--- /dev/null
+++ b/src/common/nm_bts_sm_fsm.c
@@ -0,0 +1,145 @@
+/* NM BTS Site Manager FSM */
+
+/* (C) 2020 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de>
+ * Author: Pau Espin Pedrol <pespin@sysmocom.de>
+ *
+ * All Rights Reserved
+ *
+ * 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 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 <errno.h>
+#include <unistd.h>
+#include <inttypes.h>
+
+#include <osmocom/core/fsm.h>
+#include <osmocom/core/tdef.h>
+#include <osmocom/gsm/protocol/gsm_12_21.h>
+
+#include <osmo-bts/logging.h>
+#include <osmo-bts/gsm_data.h>
+#include <osmo-bts/bts_model.h>
+#include <osmo-bts/bts.h>
+#include <osmo-bts/rsl.h>
+#include <osmo-bts/nm_common_fsm.h>
+#include <osmo-bts/phy_link.h>
+
+#define X(s) (1 << (s))
+
+#define nm_bts_sm_fsm_state_chg(fi, NEXT_STATE) \
+ osmo_fsm_inst_state_chg(fi, NEXT_STATE, 0, 0)
+
+//////////////////////////
+// FSM STATE ACTIONS
+//////////////////////////
+
+static void st_op_disabled_notinstalled_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state)
+{
+ struct gsm_bts_sm *site_mgr = (struct gsm_bts_sm *)fi->priv;
+ site_mgr->mo.opstart_success = false;
+ oml_mo_state_chg(&site_mgr->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_NOT_INSTALLED);
+}
+
+static void st_op_disabled_notinstalled(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+ struct gsm_bts_sm *site_mgr = (struct gsm_bts_sm *)fi->priv;
+
+ switch (event) {
+ case NM_EV_SW_ACT:
+ oml_mo_tx_sw_act_rep(&site_mgr->mo);
+ nm_bts_sm_fsm_state_chg(fi, NM_BTS_SM_ST_OP_DISABLED_OFFLINE);
+ return;
+ default:
+ OSMO_ASSERT(0);
+ }
+}
+
+static void st_op_disabled_offline_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state)
+{
+ struct gsm_bts_sm *site_mgr = (struct gsm_bts_sm *)fi->priv;
+ site_mgr->mo.opstart_success = false;
+ oml_mo_state_chg(&site_mgr->mo, NM_OPSTATE_DISABLED, NM_AVSTATE_OFF_LINE);
+}
+
+static void st_op_disabled_offline(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+ struct gsm_bts_sm *site_mgr = (struct gsm_bts_sm *)fi->priv;
+
+ switch (event) {
+ case NM_EV_OPSTART_ACK:
+ site_mgr->mo.opstart_success = true;
+ oml_mo_opstart_ack(&site_mgr->mo);
+ nm_bts_sm_fsm_state_chg(fi, NM_BTS_SM_ST_OP_ENABLED);
+ break; /* check statechg below */
+ case NM_EV_OPSTART_NACK:
+ site_mgr->mo.opstart_success = false;
+ oml_mo_opstart_nack(&site_mgr->mo, (int)(intptr_t)data);
+ return;
+ default:
+ OSMO_ASSERT(0);
+ }
+}
+
+static void st_op_enabled_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state)
+{
+ struct gsm_bts_sm *site_mgr = (struct gsm_bts_sm *)fi->priv;
+ oml_mo_state_chg(&site_mgr->mo, NM_OPSTATE_ENABLED, NM_AVSTATE_OK);
+}
+
+static void st_op_enabled(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+}
+
+static struct osmo_fsm_state nm_bts_sm_fsm_states[] = {
+ [NM_BTS_SM_ST_OP_DISABLED_NOTINSTALLED] = {
+ .in_event_mask =
+ X(NM_EV_SW_ACT),
+ .out_state_mask =
+ X(NM_BTS_SM_ST_OP_DISABLED_OFFLINE),
+ .name = "DISABLED_NOTINSTALLED",
+ .onenter = st_op_disabled_notinstalled_on_enter,
+ .action = st_op_disabled_notinstalled,
+ },
+ [NM_BTS_SM_ST_OP_DISABLED_OFFLINE] = {
+ .in_event_mask =
+ X(NM_EV_OPSTART_ACK) |
+ X(NM_EV_OPSTART_NACK),
+ .out_state_mask =
+ X(NM_BTS_SM_ST_OP_ENABLED),
+ .name = "DISABLED_OFFLINE",
+ .onenter = st_op_disabled_offline_on_enter,
+ .action = st_op_disabled_offline,
+ },
+ [NM_BTS_SM_ST_OP_ENABLED] = {
+ .in_event_mask = 0,
+ .out_state_mask = 0,
+ .name = "ENABLED",
+ .onenter = st_op_enabled_on_enter,
+ .action = st_op_enabled,
+ },
+};
+
+struct osmo_fsm nm_bts_sm_fsm = {
+ .name = "NM_BTS_SM_OP",
+ .states = nm_bts_sm_fsm_states,
+ .num_states = ARRAY_SIZE(nm_bts_sm_fsm_states),
+ .event_names = nm_fsm_event_names,
+ .log_subsys = DOML,
+};
+
+static __attribute__((constructor)) void nm_bts_sm_fsm_init(void)
+{
+ OSMO_ASSERT(osmo_fsm_register(&nm_bts_sm_fsm) == 0);
+}
diff --git a/src/common/nm_common_fsm.c b/src/common/nm_common_fsm.c
new file mode 100644
index 00000000..662a7602
--- /dev/null
+++ b/src/common/nm_common_fsm.c
@@ -0,0 +1,31 @@
+/* NM FSM, common bits */
+
+/* (C) 2020 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de>
+ * Author: Pau Espin Pedrol <pespin@sysmocom.de>
+ *
+ * All Rights Reserved
+ *
+ * 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 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/utils.h>
+#include <osmo-bts/nm_common_fsm.h>
+
+
+const struct value_string nm_fsm_event_names[] = {
+ { NM_EV_SW_ACT, "SW_ACT" },
+ { NM_EV_OPSTART_ACK, "OPSTART_ACK" },
+ { NM_EV_OPSTART_NACK, "OPSTART_NACK" },
+ { 0, NULL }
+};