lynxis lazus has uploaded this change for review. (
https://gerrit.osmocom.org/c/osmo-bsc/+/29788 )
Change subject: Add BTS ramping to prevent mass configuration of BTS at the same time
......................................................................
Add BTS ramping to prevent mass configuration of BTS at the same time
Prevent BSC overloading in the event of too many BTS try to connect.
E.g. a network outage between the BSC and BTS.
The BSC will accept incoming OML connection, but will delay sending
any BSC originated messages.
Change-Id: Id56dde6d58f3d0d20352f6c306598d2cccc6345d
---
M include/osmocom/bsc/bts.h
M include/osmocom/bsc/gsm_data.h
A include/osmocom/bsc/nm_bts_ramp.h
M include/osmocom/bsc/nm_common_fsm.h
M src/osmo-bsc/Makefile.am
M src/osmo-bsc/bsc_vty.c
M src/osmo-bsc/bts.c
M src/osmo-bsc/bts_ipaccess_nanobts.c
M src/osmo-bsc/bts_vty.c
M src/osmo-bsc/net_init.c
M src/osmo-bsc/nm_bb_transc_fsm.c
M src/osmo-bsc/nm_bts_fsm.c
A src/osmo-bsc/nm_bts_ramp.c
M src/osmo-bsc/nm_bts_sm_fsm.c
M src/osmo-bsc/nm_channel_fsm.c
M src/osmo-bsc/nm_gprs_cell_fsm.c
M src/osmo-bsc/nm_gprs_nse_fsm.c
M src/osmo-bsc/nm_gprs_nsvc_fsm.c
M src/osmo-bsc/nm_rcarrier_fsm.c
M src/osmo-bsc/osmo_bsc_main.c
20 files changed, 449 insertions(+), 14 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-bsc refs/changes/88/29788/1
diff --git a/include/osmocom/bsc/bts.h b/include/osmocom/bsc/bts.h
index b690652..86f73c0 100644
--- a/include/osmocom/bsc/bts.h
+++ b/include/osmocom/bsc/bts.h
@@ -18,6 +18,7 @@
#include "osmocom/bsc/bts_sm.h"
#include "osmocom/bsc/abis_om2000.h"
#include "osmocom/bsc/paging.h"
+#include "osmocom/bsc/nm_bts_ramp.h"
enum bts_counter_id {
BTS_CTR_CHREQ_TOTAL,
@@ -662,6 +663,11 @@
struct chan_counts chan_counts;
struct all_allocated all_allocated;
+
+ struct {
+ enum bts_ramp_state state;
+ struct llist_head list;
+ } bts_ramp;
};
#define GSM_BTS_SI2Q(bts, i) (struct gsm48_system_information_type_2quater
*)((bts)->si_buf[SYSINFO_TYPE_2quater][i])
diff --git a/include/osmocom/bsc/gsm_data.h b/include/osmocom/bsc/gsm_data.h
index 481eae4..2ab0c1d 100644
--- a/include/osmocom/bsc/gsm_data.h
+++ b/include/osmocom/bsc/gsm_data.h
@@ -956,6 +956,15 @@
/* Don't refuse to start with mutually exclusive codec settings */
bool allow_unusable_timeslots;
+ struct {
+ unsigned count;
+ unsigned max_bts;
+
+ struct llist_head head;
+ struct osmo_timer_list timer;
+ unsigned int seconds;
+ } bts_ramp;
+
uint8_t nri_bitlen;
struct osmo_nri_ranges *null_nri_ranges;
diff --git a/include/osmocom/bsc/nm_bts_ramp.h b/include/osmocom/bsc/nm_bts_ramp.h
new file mode 100644
index 0000000..d260afa
--- /dev/null
+++ b/include/osmocom/bsc/nm_bts_ramp.h
@@ -0,0 +1,69 @@
+/* (C) 2022 by sysmocom s.f.m.c. GmbH <info(a)sysmocom.de>
+ *
+ * Author: Alexander Couzens <acouzens(a)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 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/>.
+ *
+ */
+
+#pragma once
+
+#include <stdbool.h>
+#include <stdint.h>
+
+struct gsm_bts;
+struct gsm_network;
+
+enum bts_ramp_state {
+ BTS_RAMP_INIT, /** initial state */
+ BTS_RAMP_WAIT, /** BTS has to wait, too many BTS configuring */
+ BTS_RAMP_GO, /** BTS is allowed to configure */
+};
+
+bool bts_ramp_active(struct gsm_network *net);
+void bts_ramp_init_bts(struct gsm_bts *bts);
+void bts_ramp_init_network(struct gsm_network *net);
+
+/*!
+ * \brief bts_ramp_activate enable the bts ramping feature
+ * \param net a pointer to the gsm network
+ * \param max_bts allow how many bts to provision
+ * \param seconds how long the \param max_bts limits the bts
+ */
+void bts_ramp_activate(struct gsm_network *net, unsigned int max_bts, unsigned int
seconds);
+void bts_ramp_deactivate(struct gsm_network *net);
+
+/*!
+ * \brief bts_ramp_wait called by the bts to check if it should wait
+ * \param bts pointer to the bts
+ * \return true if the bts should wait
+ */
+bool bts_ramp_wait(struct gsm_bts *bts);
+
+const char *bts_ramp_get_state_str(struct gsm_bts *bts);
+
+/*!
+ * \brief bts_ramp_remove a bts from the ramp waiting list
+ * \param bts pointer to the bts
+ */
+void bts_ramp_remove(struct gsm_bts *bts);
+
+/*!
+ * \brief bts_ramp_unblock_bts
+ * \param bts pointer to the bts
+ * \return 0 on success, -EINVAL when the BTS is not waiting.
+ */
+int bts_ramp_unblock_bts(struct gsm_bts *bts);
diff --git a/include/osmocom/bsc/nm_common_fsm.h b/include/osmocom/bsc/nm_common_fsm.h
index b41d24a..20126fc 100644
--- a/include/osmocom/bsc/nm_common_fsm.h
+++ b/include/osmocom/bsc/nm_common_fsm.h
@@ -38,6 +38,7 @@
NM_EV_OPSTART_ACK,
NM_EV_OPSTART_NACK,
NM_EV_OML_DOWN,
+ NM_EV_RAMP_GO, /* BTS ramp allow to continue to configure */
NM_EV_FORCE_LOCK, /* Only supported by RadioCarrier so far */
NM_EV_FEATURE_NEGOTIATED, /* Sent by BTS to NSVC MO */
NM_EV_RSL_CONNECT_ACK, /* Sent by BTS to BBTRANSC MO */
diff --git a/src/osmo-bsc/Makefile.am b/src/osmo-bsc/Makefile.am
index 40381fe..baf4c91 100644
--- a/src/osmo-bsc/Makefile.am
+++ b/src/osmo-bsc/Makefile.am
@@ -88,6 +88,7 @@
nm_bb_transc_fsm.c \
nm_bts_sm_fsm.c \
nm_bts_fsm.c \
+ nm_bts_ramp.c \
nm_gprs_cell_fsm.c \
nm_gprs_nse_fsm.c \
nm_gprs_nsvc_fsm.c \
diff --git a/src/osmo-bsc/bsc_vty.c b/src/osmo-bsc/bsc_vty.c
index 61a1559..755c375 100644
--- a/src/osmo-bsc/bsc_vty.c
+++ b/src/osmo-bsc/bsc_vty.c
@@ -44,6 +44,7 @@
#include <osmocom/bsc/abis_nm.h>
#include <osmocom/bsc/abis_om2000.h>
#include <osmocom/bsc/chan_alloc.h>
+#include <osmocom/bsc/nm_bts_ramp.h>
#include <osmocom/bsc/system_information.h>
#include <osmocom/bsc/debug.h>
#include <osmocom/bsc/paging.h>
@@ -1279,6 +1280,38 @@
return CMD_SUCCESS;
}
+DEFUN(allow_bts_conf, allow_bts_conf_cmd,
+ "allow-bts-configuration <0-65535>",
+ "Unblock and allow to configure a BTS if kept back by BTS ramping\n"
+ BTS_NR_STR)
+{
+ struct gsm_network *gsmnet;
+ struct gsm_bts *bts;
+ unsigned int bts_nr;
+
+ gsmnet = gsmnet_from_vty(vty);
+
+ bts_nr = atoi(argv[0]);
+ if (bts_nr >= gsmnet->num_bts) {
+ vty_out(vty, "%% BTS number must be between 0 and %d. It was %d.%s",
+ gsmnet->num_bts, bts_nr, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ bts = gsm_bts_num(gsmnet, bts_nr);
+ if (!bts) {
+ vty_out(vty, "%% BTS Nr. %d could not be found.%s", bts_nr, VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ if (bts_ramp_unblock_bts(bts)) {
+ vty_out(vty, "%% The BTS is not blocked by BTS ramping.%s", VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+
+ return CMD_SUCCESS;
+}
+
DEFUN(restart_bts, restart_bts_cmd,
"restart-bts <0-65535>",
"Restart ip.access nanoBTS through OML\n"
@@ -2622,6 +2655,10 @@
vty_out(vty, " bsc-auto-rf-off %d%s",
bsc_gsmnet->auto_off_timeout, VTY_NEWLINE);
+ if (bsc_gsmnet->bts_ramp.max_bts > 0)
+ vty_out(vty, " bts ramp limit %d within %d seconds%s",
+ bsc_gsmnet->bts_ramp.max_bts, bsc_gsmnet->bts_ramp.seconds, VTY_NEWLINE);
+
return CMD_SUCCESS;
}
@@ -3045,6 +3082,46 @@
return CMD_SUCCESS;
}
+DEFUN_ATTR(cfg_bsc_bts_ramp,
+ cfg_bsc_bts_ramp_cmd,
+ "bts ramp limit <0-999> within <0-999> seconds",
+ "Set BTS ramping to limit the number of BTS which configure within a time
window.\n"
+ "Set BTS ramping to limit the number of BTS which configure within a time
window.\n"
+ "Set BTS ramping to limit the number of BTS which configure within a time
window.\n"
+ "Number of BTS\n"
+ "Set BTS ramping to limit the number of BTS which configure within a time
window.\n"
+ "Number of seconds\n"
+ "Set BTS ramping to limit the number of BTS which configure within a time
window.\n",
+ CMD_ATTR_IMMEDIATE)
+{
+ struct gsm_network *net = gsmnet_from_vty(vty);
+
+ int max_bts = atoi(argv[0]);
+ int seconds = atoi(argv[1]);
+
+ if (max_bts == 0)
+ bts_ramp_deactivate(net);
+ else
+ bts_ramp_activate(net, max_bts, seconds);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN_ATTR(cfg_bsc_no_bts_ramp,
+ cfg_bsc_no_bts_ramp_cmd,
+ "no bts ramp limit",
+ NO_STR
+ "Disable BTS ramping and configure all waiting BTS.\n"
+ "Disable BTS ramping and configure all waiting BTS.\n"
+ "Disable BTS ramping and configure all waiting BTS.\n",
+ CMD_ATTR_IMMEDIATE)
+{
+ struct gsm_network *net = gsmnet_from_vty(vty);
+
+ bts_ramp_deactivate(net);
+ return CMD_SUCCESS;
+}
+
DEFUN(show_statistics,
show_statistics_cmd,
"show statistics",
@@ -3459,6 +3536,7 @@
install_element(ENABLE_NODE, &drop_bts_cmd);
install_element(ENABLE_NODE, &restart_bts_cmd);
+ install_element(ENABLE_NODE, &allow_bts_conf_cmd);
install_element(ENABLE_NODE, &bts_resend_sysinfo_cmd);
install_element(ENABLE_NODE, &bts_resend_power_ctrl_params_cmd);
install_element(ENABLE_NODE, &bts_c0_power_red_cmd);
@@ -3499,6 +3577,8 @@
install_element(BSC_NODE, &cfg_net_no_rf_off_time_cmd);
install_element(BSC_NODE, &cfg_net_bsc_missing_msc_ussd_cmd);
install_element(BSC_NODE, &cfg_net_bsc_no_missing_msc_text_cmd);
+ install_element(BSC_NODE, &cfg_bsc_bts_ramp_cmd);
+ install_element(BSC_NODE, &cfg_bsc_no_bts_ramp_cmd);
install_node(&msc_node, config_write_msc);
install_element(MSC_NODE, &cfg_net_bsc_ncc_cmd);
diff --git a/src/osmo-bsc/bts.c b/src/osmo-bsc/bts.c
index b7d3c3c..ea0b0d6 100644
--- a/src/osmo-bsc/bts.c
+++ b/src/osmo-bsc/bts.c
@@ -145,6 +145,7 @@
static int gsm_bts_talloc_destructor(struct gsm_bts *bts)
{
paging_destructor(bts);
+ bts_ramp_remove(bts);
osmo_timer_del(&bts->cbch_timer);
diff --git a/src/osmo-bsc/bts_ipaccess_nanobts.c b/src/osmo-bsc/bts_ipaccess_nanobts.c
index 624aabc..3e58c3e 100644
--- a/src/osmo-bsc/bts_ipaccess_nanobts.c
+++ b/src/osmo-bsc/bts_ipaccess_nanobts.c
@@ -619,6 +619,8 @@
e1inp_sign_link_destroy(bts->osmo_link);
bts->osmo_link = NULL;
+ bts_ramp_remove(bts);
+
/* we have issues reconnecting RSL, drop everything. */
llist_for_each_entry(trx, &bts->trx_list, list) {
ipaccess_drop_rsl(trx, "OML link drop");
diff --git a/src/osmo-bsc/bts_vty.c b/src/osmo-bsc/bts_vty.c
index 2348b87..966745a 100644
--- a/src/osmo-bsc/bts_vty.c
+++ b/src/osmo-bsc/bts_vty.c
@@ -3984,6 +3984,8 @@
vty_out(vty, " OML Link: ");
e1isl_dump_vty_tcp(vty, bts->oml_link);
vty_out(vty, " OML Link state: %s", get_model_oml_status(bts));
+ if (bts_ramp_active(bts->network))
+ vty_out(vty, " BTS Ramping: %s", bts_ramp_get_state_str(bts));
sec = bts_uptime(bts);
if (sec)
vty_out(vty, " %llu days %llu hours %llu min. %llu sec.",
diff --git a/src/osmo-bsc/net_init.c b/src/osmo-bsc/net_init.c
index 8a8c0a6..e95e305 100644
--- a/src/osmo-bsc/net_init.c
+++ b/src/osmo-bsc/net_init.c
@@ -25,6 +25,7 @@
#include <osmocom/bsc/handover_cfg.h>
#include <osmocom/bsc/chan_alloc.h>
#include <osmocom/bsc/neighbor_ident.h>
+#include <osmocom/bsc/nm_bts_ramp.h>
static struct osmo_tdef gsm_network_T_defs[] = {
{ .T=4, .default_val=5, .desc="Timeout to receive BSSMAP RESET ACKNOWLEDGE from the
MSC" },
@@ -124,5 +125,7 @@
net->null_nri_ranges = osmo_nri_ranges_alloc(net);
net->nri_bitlen = OSMO_NRI_BITLEN_DEFAULT;
+ bts_ramp_init_network(net);
+
return net;
}
diff --git a/src/osmo-bsc/nm_bb_transc_fsm.c b/src/osmo-bsc/nm_bb_transc_fsm.c
index 3a8786b..a637758 100644
--- a/src/osmo-bsc/nm_bb_transc_fsm.c
+++ b/src/osmo-bsc/nm_bb_transc_fsm.c
@@ -105,6 +105,9 @@
{
struct gsm_bts_trx *trx = gsm_bts_bb_trx_get_trx(bb_transc);
+ if (bts_ramp_wait(trx->bts))
+ return;
+
/* Request TRX-level attributes */
if (!bb_transc->mo.get_attr_sent && !bb_transc->mo.get_attr_rep_received)
{
bb_transc->mo.get_attr_sent = true;
@@ -339,6 +342,10 @@
nm_bb_transc_fsm_state_chg(fi, NM_BB_TRANSC_ST_OP_DISABLED_NOTINSTALLED);
}
break;
+ case NM_EV_RAMP_GO:
+ if (fi->state != NM_BB_TRANSC_ST_OP_ENABLED)
+ configure_loop(bb_transc, &bb_transc->mo.nm_state, fi->state ==
NM_BB_TRANSC_ST_OP_DISABLED_OFFLINE);
+ break;
default:
OSMO_ASSERT(0);
}
@@ -405,7 +412,8 @@
.allstate_event_mask =
X(NM_EV_OPSTART_ACK) |
X(NM_EV_OPSTART_NACK) |
- X(NM_EV_OML_DOWN),
+ X(NM_EV_OML_DOWN) |
+ X(NM_EV_RAMP_GO),
.allstate_action = st_op_allstate,
.event_names = nm_fsm_event_names,
.log_subsys = DNM,
diff --git a/src/osmo-bsc/nm_bts_fsm.c b/src/osmo-bsc/nm_bts_fsm.c
index 1b71323..eb221ff 100644
--- a/src/osmo-bsc/nm_bts_fsm.c
+++ b/src/osmo-bsc/nm_bts_fsm.c
@@ -88,10 +88,16 @@
}
}
-static void configure_loop(struct gsm_bts *bts, const struct gsm_nm_state *state, bool
allow_opstart)
+static void configure_loop(
+ struct gsm_bts *bts,
+ const struct gsm_nm_state *state,
+ bool allow_opstart)
{
struct msgb *msgb;
+ if (bts_ramp_wait(bts))
+ return;
+
/* Request generic BTS-level attributes */
if (!bts->mo.get_attr_sent && !bts->mo.get_attr_rep_received) {
bts->mo.get_attr_sent = true;
@@ -320,6 +326,10 @@
if (fi->state != NM_BTS_ST_OP_DISABLED_NOTINSTALLED)
nm_bts_fsm_state_chg(fi, NM_BTS_ST_OP_DISABLED_NOTINSTALLED);
break;
+ case NM_EV_RAMP_GO:
+ if (fi->state != NM_BTS_ST_OP_ENABLED)
+ configure_loop(bts, &bts->mo.nm_state, fi->state ==
NM_BTS_ST_OP_DISABLED_OFFLINE);
+ break;
default:
OSMO_ASSERT(0);
}
@@ -384,7 +394,8 @@
.allstate_event_mask =
X(NM_EV_OPSTART_ACK) |
X(NM_EV_OPSTART_NACK) |
- X(NM_EV_OML_DOWN),
+ X(NM_EV_OML_DOWN) |
+ X(NM_EV_RAMP_GO),
.allstate_action = st_op_allstate,
.event_names = nm_fsm_event_names,
.log_subsys = DNM,
diff --git a/src/osmo-bsc/nm_bts_ramp.c b/src/osmo-bsc/nm_bts_ramp.c
new file mode 100644
index 0000000..94d0a67
--- /dev/null
+++ b/src/osmo-bsc/nm_bts_ramp.c
@@ -0,0 +1,174 @@
+/* (C) 2022 by sysmocom s.f.m.c. GmbH <info(a)sysmocom.de>
+ *
+ * Author: Alexander Couzens <acouzens(a)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 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 <stdbool.h>
+
+#include <osmocom/core/fsm.h>
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/core/timer.h>
+#include <osmocom/core/utils.h>
+
+#include <osmocom/bsc/bts.h>
+#include <osmocom/bsc/bts_sm.h>
+#include <osmocom/bsc/nm_bts_ramp.h>
+#include <osmocom/bsc/nm_common_fsm.h>
+
+
+static void _bts_ramp_unblock_bts(struct gsm_bts *bts)
+{
+ struct gsm_bts_trx *trx;
+
+ llist_del(&bts->bts_ramp.list);
+ bts->bts_ramp.state = BTS_RAMP_GO;
+
+ /* inform all MOs */
+ osmo_fsm_inst_dispatch(bts->site_mgr->mo.fi, NM_EV_RAMP_GO, NULL);
+ osmo_fsm_inst_dispatch(bts->mo.fi, NM_EV_RAMP_GO, NULL);
+ llist_for_each_entry(trx, &bts->trx_list, list) {
+ osmo_fsm_inst_dispatch(trx->mo.fi, NM_EV_RAMP_GO, NULL);
+ osmo_fsm_inst_dispatch(trx->bb_transc.mo.fi, NM_EV_RAMP_GO, NULL);
+ for (unsigned long i = 0; i < ARRAY_SIZE(trx->ts); i++) {
+ struct gsm_bts_trx_ts *ts = &trx->ts[i];
+ osmo_fsm_inst_dispatch(ts->mo.fi, NM_EV_RAMP_GO, NULL);
+ }
+ }
+
+ /* GPRS MOs */
+ osmo_fsm_inst_dispatch(bts->site_mgr->gprs.nse.mo.fi, NM_EV_RAMP_GO, NULL);
+ for (unsigned long i = 0; i < ARRAY_SIZE(bts->site_mgr->gprs.nsvc); i++)
+ osmo_fsm_inst_dispatch(bts->site_mgr->gprs.nsvc[i].mo.fi, NM_EV_RAMP_GO, NULL);
+ osmo_fsm_inst_dispatch(bts->gprs.cell.mo.fi, NM_EV_RAMP_GO, NULL);
+}
+
+int bts_ramp_unblock_bts(struct gsm_bts *bts)
+{
+ if (llist_entry_empty(&bts->bts_ramp.list))
+ return -EINVAL;
+
+ _bts_ramp_unblock_bts(bts);
+ return 0;
+}
+
+
+/*!
+ * \brief bts_ramp_timer_cb timer callback and called by bts_ramp_deactivate
+ * \param _net pointer to struct gsm_network
+ */
+static void bts_ramp_timer_cb(void *_net)
+{
+ struct gsm_network *net = (struct gsm_network *) _net;
+ struct gsm_bts *bts, *n;
+ net->bts_ramp.count = 0;
+
+ llist_for_each_entry_safe(bts, n, &net->bts_ramp.head, bts_ramp.list) {
+ net->bts_ramp.count++;
+ _bts_ramp_unblock_bts(bts);
+ LOG_BTS(bts, DNM, LOGL_INFO, "Unblock BTS %d from BTS ramping.\n",
bts->nr);
+ if (bts_ramp_active(net) &&
+ net->bts_ramp.count >= net->bts_ramp.max_bts)
+ break;
+ }
+
+ if (net->bts_ramp.max_bts > 0)
+ osmo_timer_schedule(&net->bts_ramp.timer, net->bts_ramp.seconds, 0);
+}
+
+const struct value_string bts_ramp_state_values[] = {
+ { BTS_RAMP_INIT, "Initial" },
+ { BTS_RAMP_WAIT, "Waiting" },
+ { BTS_RAMP_GO, "Go" },
+ { 0, NULL },
+};
+
+const char *bts_ramp_get_state_str(struct gsm_bts *bts)
+{
+ return get_value_string_or_null(bts_ramp_state_values, bts->bts_ramp.state);
+}
+
+void bts_ramp_activate(struct gsm_network *net, unsigned int max_bts, unsigned int
seconds)
+{
+ net->bts_ramp.max_bts = max_bts;
+ net->bts_ramp.seconds = seconds;
+ osmo_timer_schedule(&net->bts_ramp.timer, seconds, 0);
+}
+
+void bts_ramp_deactivate(struct gsm_network *net)
+{
+ net->bts_ramp.max_bts = 0;
+ /* clear bts list */
+ bts_ramp_timer_cb(net);
+ osmo_timer_del(&net->bts_ramp.timer);
+}
+
+bool bts_ramp_active(struct gsm_network *net)
+{
+ return net->bts_ramp.max_bts > 0;
+}
+
+bool bts_ramp_wait(struct gsm_bts *bts)
+{
+ struct gsm_network *net = bts->network;
+
+ if (!bts_ramp_active(net))
+ return false;
+
+ switch (bts->bts_ramp.state) {
+ case BTS_RAMP_INIT:
+ break;
+ case BTS_RAMP_WAIT:
+ return true;
+ case BTS_RAMP_GO:
+ return false;
+ }
+
+ if (net->bts_ramp.count < net->bts_ramp.max_bts) {
+ OSMO_ASSERT(llist_entry_empty(&bts->bts_ramp.list));
+ LOG_BTS(bts, DNM, LOGL_INFO,
+ "BTS %d can configure without waiting for BTS ramping.\n", bts->nr);
+
+ net->bts_ramp.count++;
+ bts->bts_ramp.state = BTS_RAMP_GO;
+ return false;
+ }
+
+ bts->bts_ramp.state = BTS_RAMP_WAIT;
+ llist_add_tail(&bts->bts_ramp.list, &net->bts_ramp.head);
+ LOGP(DNM, LOGL_INFO, "BTS %d will wait for BTS ramping.\n", bts->nr);
+
+ return true;
+}
+
+void bts_ramp_init_network(struct gsm_network *net)
+{
+ INIT_LLIST_HEAD(&net->bts_ramp.head);
+ osmo_timer_setup(&net->bts_ramp.timer, bts_ramp_timer_cb, net);
+}
+
+void bts_ramp_init_bts(struct gsm_bts *bts)
+{
+ bts->bts_ramp.state = BTS_RAMP_INIT;
+}
+
+void bts_ramp_remove(struct gsm_bts *bts)
+{
+ if (!llist_entry_empty(&bts->bts_ramp.list))
+ llist_del(&bts->bts_ramp.list);
+}
diff --git a/src/osmo-bsc/nm_bts_sm_fsm.c b/src/osmo-bsc/nm_bts_sm_fsm.c
index 03bf43c..59f0999 100644
--- a/src/osmo-bsc/nm_bts_sm_fsm.c
+++ b/src/osmo-bsc/nm_bts_sm_fsm.c
@@ -99,6 +99,20 @@
}
}
+static void configure_loop(struct gsm_bts_sm *site_mgr)
+{
+ struct gsm_bts *bts = gsm_bts_sm_get_bts(site_mgr);
+
+ if (bts_ramp_wait(bts))
+ return;
+
+ if (!site_mgr->mo.opstart_sent) {
+ site_mgr->mo.opstart_sent = true;
+ abis_nm_opstart(bts, NM_OC_SITE_MANAGER, 0xff, 0xff, 0xff);
+ }
+}
+
+
static void st_op_disabled_dependency(struct osmo_fsm_inst *fi, uint32_t event, void
*data)
{
struct nm_statechg_signal_data *nsd;
@@ -132,11 +146,8 @@
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;
- struct gsm_bts *bts = gsm_bts_sm_get_bts(site_mgr);
- if (!site_mgr->mo.opstart_sent) {
- site_mgr->mo.opstart_sent = true;
- abis_nm_opstart(bts, NM_OC_SITE_MANAGER, 0xff, 0xff, 0xff);
- }
+
+ configure_loop(site_mgr);
}
static void st_op_disabled_offline(struct osmo_fsm_inst *fi, uint32_t event, void *data)
@@ -144,7 +155,16 @@
struct nm_statechg_signal_data *nsd;
const struct gsm_nm_state *new_state;
+ struct gsm_bts_sm *site_mgr = (struct gsm_bts_sm *)fi->priv;
+ struct gsm_bts *bts = gsm_bts_sm_get_bts(site_mgr);
+
switch (event) {
+ case NM_EV_RAMP_GO:
+ if (!site_mgr->mo.opstart_sent) {
+ site_mgr->mo.opstart_sent = true;
+ abis_nm_opstart(bts, NM_OC_SITE_MANAGER, 0xff, 0xff, 0xff);
+ }
+ break;
case NM_EV_STATE_CHG_REP:
nsd = (struct nm_statechg_signal_data *)data;
new_state = &nsd->new_state;
@@ -170,6 +190,7 @@
OSMO_ASSERT(0);
}
}
+
static void st_op_enabled(struct osmo_fsm_inst *fi, uint32_t event, void *data)
{
struct nm_statechg_signal_data *nsd;
@@ -215,6 +236,10 @@
if (fi->state != NM_BTS_SM_ST_OP_DISABLED_NOTINSTALLED)
nm_bts_sm_fsm_state_chg(fi, NM_BTS_SM_ST_OP_DISABLED_NOTINSTALLED);
break;
+ case NM_EV_RAMP_GO:
+ if (fi->state != NM_BTS_SM_ST_OP_ENABLED)
+ configure_loop(site_mgr);
+ break;
default:
OSMO_ASSERT(0);
}
@@ -273,7 +298,8 @@
.allstate_event_mask =
X(NM_EV_OPSTART_ACK) |
X(NM_EV_OPSTART_NACK) |
- X(NM_EV_OML_DOWN),
+ X(NM_EV_OML_DOWN) |
+ X(NM_EV_RAMP_GO),
.allstate_action = st_op_allstate,
.event_names = nm_fsm_event_names,
.log_subsys = DNM,
diff --git a/src/osmo-bsc/nm_channel_fsm.c b/src/osmo-bsc/nm_channel_fsm.c
index c3146a4..093152e 100644
--- a/src/osmo-bsc/nm_channel_fsm.c
+++ b/src/osmo-bsc/nm_channel_fsm.c
@@ -92,6 +92,9 @@
enum abis_nm_chan_comb ccomb;
struct gsm_bts_trx *trx = ts->trx;
+ if (bts_ramp_wait(ts->trx->bts))
+ return;
+
if (!ts->mo.set_attr_sent && !ts->mo.set_attr_ack_received) {
ts->mo.set_attr_sent = true;
ccomb = abis_nm_chcomb4pchan(ts->pchan_from_config);
@@ -276,6 +279,10 @@
if (fi->state != NM_CHAN_ST_OP_DISABLED_NOTINSTALLED)
nm_chan_fsm_state_chg(fi, NM_CHAN_ST_OP_DISABLED_NOTINSTALLED);
break;
+ case NM_EV_RAMP_GO:
+ if (fi->state != NM_CHAN_ST_OP_ENABLED)
+ configure_loop(ts, &ts->mo.nm_state, fi->state ==
NM_CHAN_ST_OP_DISABLED_OFFLINE);
+ break;
default:
OSMO_ASSERT(0);
}
@@ -338,7 +345,8 @@
.allstate_event_mask =
X(NM_EV_OPSTART_ACK) |
X(NM_EV_OPSTART_NACK) |
- X(NM_EV_OML_DOWN),
+ X(NM_EV_OML_DOWN) |
+ X(NM_EV_RAMP_GO),
.allstate_action = st_op_allstate,
.event_names = nm_fsm_event_names,
.log_subsys = DNM,
diff --git a/src/osmo-bsc/nm_gprs_cell_fsm.c b/src/osmo-bsc/nm_gprs_cell_fsm.c
index aabfc0b..cee537b 100644
--- a/src/osmo-bsc/nm_gprs_cell_fsm.c
+++ b/src/osmo-bsc/nm_gprs_cell_fsm.c
@@ -94,6 +94,9 @@
if (bts->gprs.mode == BTS_GPRS_NONE)
return;
+ if (bts_ramp_wait(bts))
+ return;
+
if (!cell->mo.set_attr_sent && !cell->mo.set_attr_ack_received) {
cell->mo.set_attr_sent = true;
msgb = nanobts_gen_set_cell_attr(bts);
@@ -294,6 +297,10 @@
if (fi->state != NM_GPRS_CELL_ST_OP_DISABLED_NOTINSTALLED)
nm_gprs_cell_fsm_state_chg(fi, NM_GPRS_CELL_ST_OP_DISABLED_NOTINSTALLED);
break;
+ case NM_EV_RAMP_GO:
+ if (fi->state != NM_GPRS_CELL_ST_OP_ENABLED)
+ configure_loop(cell, &cell->mo.nm_state, fi->state ==
NM_GPRS_CELL_ST_OP_DISABLED_OFFLINE);
+ break;
default:
OSMO_ASSERT(0);
}
@@ -357,7 +364,8 @@
X(NM_EV_OPSTART_ACK) |
X(NM_EV_OPSTART_NACK) |
X(NM_EV_FORCE_LOCK) |
- X(NM_EV_OML_DOWN),
+ X(NM_EV_OML_DOWN) |
+ X(NM_EV_RAMP_GO),
.allstate_action = st_op_allstate,
.event_names = nm_fsm_event_names,
.log_subsys = DNM,
diff --git a/src/osmo-bsc/nm_gprs_nse_fsm.c b/src/osmo-bsc/nm_gprs_nse_fsm.c
index 49908ce..ae68a6b 100644
--- a/src/osmo-bsc/nm_gprs_nse_fsm.c
+++ b/src/osmo-bsc/nm_gprs_nse_fsm.c
@@ -93,6 +93,9 @@
struct gsm_bts_sm *bts_sm = container_of(nse, struct gsm_bts_sm, gprs.nse);
struct gsm_bts *bts = gsm_bts_sm_get_bts(bts_sm);
+ if (bts_ramp_wait(bts))
+ return;
+
if (!nse->mo.set_attr_sent && !nse->mo.set_attr_ack_received) {
nse->mo.set_attr_sent = true;
msgb = nanobts_gen_set_nse_attr(bts_sm);
@@ -296,6 +299,10 @@
if (fi->state != NM_GPRS_NSE_ST_OP_DISABLED_NOTINSTALLED)
nm_gprs_nse_fsm_state_chg(fi, NM_GPRS_NSE_ST_OP_DISABLED_NOTINSTALLED);
break;
+ case NM_EV_RAMP_GO:
+ if (fi->state != NM_GPRS_NSE_ST_OP_ENABLED)
+ configure_loop(nse, &nse->mo.nm_state, fi->state ==
NM_GPRS_NSE_ST_OP_DISABLED_OFFLINE);
+ break;
default:
OSMO_ASSERT(0);
}
@@ -359,7 +366,8 @@
X(NM_EV_OPSTART_ACK) |
X(NM_EV_OPSTART_NACK) |
X(NM_EV_FORCE_LOCK) |
- X(NM_EV_OML_DOWN),
+ X(NM_EV_OML_DOWN) |
+ X(NM_EV_RAMP_GO),
.allstate_action = st_op_allstate,
.event_names = nm_fsm_event_names,
.log_subsys = DNM,
diff --git a/src/osmo-bsc/nm_gprs_nsvc_fsm.c b/src/osmo-bsc/nm_gprs_nsvc_fsm.c
index 29eed5c..5e649b4 100644
--- a/src/osmo-bsc/nm_gprs_nsvc_fsm.c
+++ b/src/osmo-bsc/nm_gprs_nsvc_fsm.c
@@ -97,6 +97,9 @@
if (nsvc->bts->gprs.mode == BTS_GPRS_NONE)
return;
+ if (bts_ramp_wait(nsvc->bts))
+ return;
+
/* We need to know BTS features in order to know if we can set IPv6 addresses */
if (gsm_bts_features_negotiated(nsvc->bts) && !nsvc->mo.set_attr_sent
&&
!nsvc->mo.set_attr_ack_received) {
@@ -305,6 +308,10 @@
if (fi->state != NM_GPRS_NSVC_ST_OP_DISABLED_NOTINSTALLED)
nm_gprs_nsvc_fsm_state_chg(fi, NM_GPRS_NSVC_ST_OP_DISABLED_NOTINSTALLED);
break;
+ case NM_EV_RAMP_GO:
+ if (fi->state != NM_GPRS_NSVC_ST_OP_ENABLED)
+ configure_loop(nsvc, &nsvc->mo.nm_state, fi->state ==
NM_GPRS_NSVC_ST_OP_DISABLED_OFFLINE);
+ break;
default:
OSMO_ASSERT(0);
}
@@ -370,7 +377,8 @@
.allstate_event_mask =
X(NM_EV_OPSTART_ACK) |
X(NM_EV_OPSTART_NACK) |
- X(NM_EV_OML_DOWN),
+ X(NM_EV_OML_DOWN) |
+ X(NM_EV_RAMP_GO),
.allstate_action = st_op_allstate,
.event_names = nm_fsm_event_names,
.log_subsys = DNM,
diff --git a/src/osmo-bsc/nm_rcarrier_fsm.c b/src/osmo-bsc/nm_rcarrier_fsm.c
index c8b95ad..04d0c41 100644
--- a/src/osmo-bsc/nm_rcarrier_fsm.c
+++ b/src/osmo-bsc/nm_rcarrier_fsm.c
@@ -100,6 +100,9 @@
{
struct msgb *msgb;
+ if (bts_ramp_wait(trx->bts))
+ return;
+
if (!trx->mo.set_attr_sent && !trx->mo.set_attr_ack_received) {
trx->mo.set_attr_sent = true;
msgb = nanobts_gen_set_radio_attr(trx->bts, trx);
@@ -317,6 +320,10 @@
nm_rcarrier_fsm_state_chg(fi, NM_RCARRIER_ST_OP_DISABLED_NOTINSTALLED);
}
break;
+ case NM_EV_RAMP_GO:
+ if (fi->state != NM_BTS_ST_OP_ENABLED)
+ configure_loop(trx, &trx->mo.nm_state, fi->state ==
NM_RCARRIER_ST_OP_DISABLED_OFFLINE);
+ break;
default:
OSMO_ASSERT(0);
}
@@ -380,7 +387,8 @@
X(NM_EV_OPSTART_ACK) |
X(NM_EV_OPSTART_NACK) |
X(NM_EV_FORCE_LOCK) |
- X(NM_EV_OML_DOWN),
+ X(NM_EV_OML_DOWN) |
+ X(NM_EV_RAMP_GO),
.allstate_action = st_op_allstate,
.event_names = nm_fsm_event_names,
.log_subsys = DNM,
diff --git a/src/osmo-bsc/osmo_bsc_main.c b/src/osmo-bsc/osmo_bsc_main.c
index 920693f..fd630a0 100644
--- a/src/osmo-bsc/osmo_bsc_main.c
+++ b/src/osmo-bsc/osmo_bsc_main.c
@@ -401,6 +401,8 @@
bts->si_common.chan_desc.ccch_conf = (n << 1);
}
+ bts_ramp_init_bts(bts);
+
/* ACC ramping is initialized from vty/config */
/* Initialize the BTS state */
--
To view, visit
https://gerrit.osmocom.org/c/osmo-bsc/+/29788
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings
Gerrit-Project: osmo-bsc
Gerrit-Branch: master
Gerrit-Change-Id: Id56dde6d58f3d0d20352f6c306598d2cccc6345d
Gerrit-Change-Number: 29788
Gerrit-PatchSet: 1
Gerrit-Owner: lynxis lazus <lynxis(a)fe80.eu>
Gerrit-MessageType: newchange