aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPau Espin Pedrol <pespin@sysmocom.de>2020-06-17 17:23:57 +0200
committerpespin <pespin@sysmocom.de>2020-06-23 12:49:11 +0000
commitfee04adc751747a476ce832be26a488df01f852e (patch)
treeef09fb652ae54806a468bba53a07f247e35b394c
parent580a27e97c3f0e139dfd7b0c10de24463d4b5294 (diff)
Introduce bts_shutdown FSM
Using an FSM here will allow for more complex ordered shutdown procedures, like power ramp down, waiting for TRX deact asyncrhonously, etc. Current commit leaves everything in place already prepared to implement ramp down, which will be implemented in next commit in the series. Related: SYS#4920 Change-Id: I8f48f17e61c3b9b86342eaf5b8a2b1ac9758bde5
-rw-r--r--include/osmo-bts/Makefile.am1
-rw-r--r--include/osmo-bts/bts_shutdown_fsm.h38
-rw-r--r--include/osmo-bts/gsm_data.h3
-rw-r--r--src/common/Makefile.am1
-rw-r--r--src/common/bts.c33
-rw-r--r--src/common/bts_shutdown_fsm.c144
-rw-r--r--src/common/gsm_data.c18
7 files changed, 204 insertions, 34 deletions
diff --git a/include/osmo-bts/Makefile.am b/include/osmo-bts/Makefile.am
index 4999ab46..310fce2a 100644
--- a/include/osmo-bts/Makefile.am
+++ b/include/osmo-bts/Makefile.am
@@ -2,6 +2,7 @@ noinst_HEADERS = \
abis.h \
bts.h \
bts_model.h \
+ bts_shutdown_fsm.h \
gsm_data.h \
logging.h \
measurement.h \
diff --git a/include/osmo-bts/bts_shutdown_fsm.h b/include/osmo-bts/bts_shutdown_fsm.h
new file mode 100644
index 00000000..1268b2b6
--- /dev/null
+++ b/include/osmo-bts/bts_shutdown_fsm.h
@@ -0,0 +1,38 @@
+/* BTS shutdown 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/>.
+ *
+ */
+
+#pragma once
+
+#include <osmocom/core/fsm.h>
+
+/* 3GPP TS 24.008 ยง 4.1.3.3 GMM mobility management states on the network side */
+enum bts_shutdown_fsm_states {
+ BTS_SHUTDOWN_ST_NONE,
+ BTS_SHUTDOWN_ST_WAIT_RAMP_DOWN_COMPL,
+ BTS_SHUTDOWN_ST_EXIT,
+};
+
+enum bts_shutdown_fsm_events {
+ BTS_SHUTDOWN_EV_START,
+};
+
+extern struct osmo_fsm bts_shutdown_fsm;
diff --git a/include/osmo-bts/gsm_data.h b/include/osmo-bts/gsm_data.h
index 9032aeba..416864fb 100644
--- a/include/osmo-bts/gsm_data.h
+++ b/include/osmo-bts/gsm_data.h
@@ -733,6 +733,9 @@ struct gsm_bts {
char *sock_path;
} pcu;
+ struct osmo_fsm_inst *shutdown_fi; /* FSM instance to manage shutdown procedure during process exit */
+ struct osmo_tdef *T_defs; /* Timer defines */
+
void *model_priv; /* Allocated by bts_model, contains model specific data pointer */
};
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index 85b7038c..2fa55144 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -27,6 +27,7 @@ libbts_a_SOURCES = \
tx_power.c \
bts_ctrl_commands.c \
bts_ctrl_lookup.c \
+ bts_shutdown_fsm.c \
l1sap.c \
cbch.c \
power_control.c \
diff --git a/src/common/bts.c b/src/common/bts.c
index d2bca2f7..dccb0986 100644
--- a/src/common/bts.c
+++ b/src/common/bts.c
@@ -269,39 +269,6 @@ int bts_trx_init(struct gsm_bts_trx *trx)
return 0;
}
-static void shutdown_timer_cb(void *data)
-{
- fprintf(stderr, "Shutdown timer expired\n");
- exit(42);
-}
-
-static struct osmo_timer_list shutdown_timer = {
- .cb = &shutdown_timer_cb,
-};
-
-void bts_shutdown(struct gsm_bts *bts, const char *reason)
-{
- struct gsm_bts_trx *trx;
-
- if (osmo_timer_pending(&shutdown_timer)) {
- LOGP(DOML, LOGL_NOTICE,
- "BTS is already being shutdown.\n");
- return;
- }
-
- LOGP(DOML, LOGL_NOTICE, "Shutting down BTS %u, Reason %s\n",
- bts->nr, reason);
-
- llist_for_each_entry_reverse(trx, &bts->trx_list, list) {
- bts_model_trx_deact_rf(trx);
- bts_model_trx_close(trx);
- }
-
- /* schedule a timer to make sure select loop logic can run again
- * to dispatch any pending primitives */
- osmo_timer_schedule(&shutdown_timer, 3, 0);
-}
-
/* main link is established, send status report */
int bts_link_estab(struct gsm_bts *bts)
{
diff --git a/src/common/bts_shutdown_fsm.c b/src/common/bts_shutdown_fsm.c
new file mode 100644
index 00000000..50ef652e
--- /dev/null
+++ b/src/common/bts_shutdown_fsm.c
@@ -0,0 +1,144 @@
+/* BTS shutdown 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 <osmocom/core/fsm.h>
+#include <osmocom/core/tdef.h>
+
+#include <osmo-bts/bts_shutdown_fsm.h>
+#include <osmo-bts/logging.h>
+#include <osmo-bts/gsm_data.h>
+#include <osmo-bts/bts_model.h>
+
+#define X(s) (1 << (s))
+
+static const struct osmo_tdef_state_timeout bts_shutdown_fsm_timeouts[32] = {
+ [BTS_SHUTDOWN_ST_WAIT_RAMP_DOWN_COMPL] = { .T = -1 },
+ [BTS_SHUTDOWN_ST_EXIT] = { .T = -2 },
+};
+
+#define bts_shutdown_fsm_state_chg(fi, NEXT_STATE) \
+ osmo_tdef_fsm_inst_state_chg(fi, NEXT_STATE, bts_shutdown_fsm_timeouts, ((struct gsm_bts *)fi->priv)->T_defs, -1)
+
+static void st_none(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+ switch(event) {
+ case BTS_SHUTDOWN_EV_START:
+ bts_shutdown_fsm_state_chg(fi, BTS_SHUTDOWN_ST_WAIT_RAMP_DOWN_COMPL);
+ break;
+ }
+}
+
+static void st_wait_ramp_down_compl_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state)
+{
+ /* TODO: here power ramp down will be started on all TRX, prior to changing state */
+}
+
+static void st_wait_ramp_down_compl(struct osmo_fsm_inst *fi, uint32_t event, void *data)
+{
+ /* TODO: In here once we have ramp down implemented we'll transit to
+ regular exit. For now we simply wait for state timeout
+ bts_shutdown_fsm_state_chg(fi, BTS_SHUTDOWN_ST_EXIT);
+ */
+}
+
+static void st_exit_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_state)
+{
+ struct gsm_bts *bts = (struct gsm_bts *)fi->priv;
+ struct gsm_bts_trx *trx;
+ llist_for_each_entry_reverse(trx, &bts->trx_list, list) {
+ bts_model_trx_deact_rf(trx);
+ bts_model_trx_close(trx);
+ }
+ /* There's yet no way to get confirmation from lower layers regarding
+ state. Allow a few seconds of select() loop and timeout timer will
+ exit later */
+}
+
+static struct osmo_fsm_state bts_shutdown_fsm_states[] = {
+ [BTS_SHUTDOWN_ST_NONE] = {
+ .in_event_mask =
+ X(BTS_SHUTDOWN_EV_START),
+ .out_state_mask = X(BTS_SHUTDOWN_ST_WAIT_RAMP_DOWN_COMPL),
+ .name = "NONE",
+ .action = st_none,
+ },
+ [BTS_SHUTDOWN_ST_WAIT_RAMP_DOWN_COMPL] = {
+ .in_event_mask = 0,
+ .out_state_mask =
+ X(BTS_SHUTDOWN_ST_EXIT),
+ .name = "WAIT_RAMP_DOWN_COMPL",
+ .onenter = st_wait_ramp_down_compl_on_enter,
+ .action = st_wait_ramp_down_compl,
+ },
+ [BTS_SHUTDOWN_ST_EXIT] = {
+ .name = "EXIT",
+ .onenter = st_exit_on_enter,
+ }
+};
+
+const struct value_string bts_shutdown_fsm_event_names[] = {
+ OSMO_VALUE_STRING(BTS_SHUTDOWN_EV_START),
+ { 0, NULL }
+};
+
+int bts_shutdown_fsm_timer_cb(struct osmo_fsm_inst *fi)
+{
+ switch (fi->state) {
+ case BTS_SHUTDOWN_ST_WAIT_RAMP_DOWN_COMPL:
+ LOGPFSML(fi, LOGL_ERROR, "Timer expired waiting for ramp down complete\n");
+ bts_shutdown_fsm_state_chg(fi, BTS_SHUTDOWN_ST_EXIT);
+ break;
+ case BTS_SHUTDOWN_ST_EXIT:
+ LOGPFSML(fi, LOGL_NOTICE, "Shutdown process completed successfuly, exiting process\n");
+ exit(0);
+ break;
+ default:
+ OSMO_ASSERT(false);
+ }
+ return 0;
+}
+
+struct osmo_fsm bts_shutdown_fsm = {
+ .name = "BTS_SHUTDOWN",
+ .states = bts_shutdown_fsm_states,
+ .num_states = ARRAY_SIZE(bts_shutdown_fsm_states),
+ .event_names = bts_shutdown_fsm_event_names,
+ .log_subsys = DOML,
+ .timer_cb = bts_shutdown_fsm_timer_cb,
+};
+
+static __attribute__((constructor)) void bts_shutdown_fsm_init(void)
+{
+ OSMO_ASSERT(osmo_fsm_register(&bts_shutdown_fsm) == 0);
+}
+
+void bts_shutdown(struct gsm_bts *bts, const char *reason)
+{
+ struct osmo_fsm_inst *fi = bts->shutdown_fi;
+ if (fi->state != BTS_SHUTDOWN_ST_NONE) {
+ LOGPFSML(fi, LOGL_NOTICE, "BTS is already being shutdown.\n");
+ return;
+ }
+
+ LOGPFSML(fi, LOGL_NOTICE, "Shutting down BTS, reason: %s\n", reason);
+ osmo_fsm_inst_dispatch(fi, BTS_SHUTDOWN_EV_START, NULL);
+}
diff --git a/src/common/gsm_data.c b/src/common/gsm_data.c
index c6800016..18d5b663 100644
--- a/src/common/gsm_data.c
+++ b/src/common/gsm_data.c
@@ -28,12 +28,22 @@
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/talloc.h>
+#include <osmocom/core/statistics.h>
+#include <osmocom/core/fsm.h>
+#include <osmocom/core/tdef.h>
+
#include <osmocom/gsm/gsm_utils.h>
#include <osmocom/gsm/abis_nm.h>
-#include <osmocom/core/statistics.h>
#include <osmocom/codec/ecu.h>
#include <osmo-bts/gsm_data.h>
+#include <osmo-bts/bts_shutdown_fsm.h>
+
+static struct osmo_tdef bts_T_defs[] = {
+ { .T=-1, .default_val=1, .desc="Time after which osmo-bts exits if regular ramp down during shut down process does not finish (s)" },
+ { .T=-2, .default_val=3, .desc="Time after which osmo-bts exits if requesting transceivers to stop during shut down process does not finish (s)" },
+ {}
+};
void gsm_abis_mo_reset(struct gsm_abis_mo *mo)
{
@@ -277,6 +287,12 @@ struct gsm_bts *gsm_bts_alloc(void *ctx, uint8_t bts_num)
INIT_LLIST_HEAD(&bts->trx_list);
bts->ms_max_power = 15; /* dBm */
+ bts->T_defs = bts_T_defs;
+ osmo_tdefs_reset(bts->T_defs);
+ bts->shutdown_fi = osmo_fsm_inst_alloc(&bts_shutdown_fsm, bts, bts,
+ LOGL_INFO, NULL);
+ osmo_fsm_inst_update_id_f(bts->shutdown_fi, "bts%d", bts->nr);
+
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,