lynxis lazus submitted this change.

View Change

Approvals: daniel: Looks good to me, approved pespin: Looks good to me, but someone else must approve Jenkins Builder: Verified
Add BTS setup ramping to prevent BSC overloading

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/Makefile.am
M include/osmocom/bsc/bts.h
A include/osmocom/bsc/bts_setup_ramp.h
M include/osmocom/bsc/gsm_data.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
A src/osmo-bsc/bts_setup_ramp.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
M src/osmo-bsc/nm_bts_sm_fsm.c
M src/osmo-bsc/nm_channel_fsm.c
M src/osmo-bsc/nm_common_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
M tests/osmo-bsc.vty
23 files changed, 619 insertions(+), 30 deletions(-)

diff --git a/include/osmocom/bsc/Makefile.am b/include/osmocom/bsc/Makefile.am
index 115c92b..53d45ad 100644
--- a/include/osmocom/bsc/Makefile.am
+++ b/include/osmocom/bsc/Makefile.am
@@ -13,6 +13,7 @@
bss.h \
bts.h \
bts_sm.h \
+ bts_setup_ramp.h \
bts_trx.h \
bts_ipaccess_nanobts_omlattr.h \
chan_alloc.h \
diff --git a/include/osmocom/bsc/bts.h b/include/osmocom/bsc/bts.h
index d71d18f..cc4db5a 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/bts_setup_ramp.h"

enum bts_counter_id {
BTS_CTR_CHREQ_TOTAL,
@@ -666,6 +667,8 @@

struct chan_counts chan_counts;
struct all_allocated all_allocated;
+
+ struct bts_setup_ramp bts_setup_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/bts_setup_ramp.h b/include/osmocom/bsc/bts_setup_ramp.h
new file mode 100644
index 0000000..0278ee0
--- /dev/null
+++ b/include/osmocom/bsc/bts_setup_ramp.h
@@ -0,0 +1,69 @@
+/* (C) 2022 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
+ *
+ * Author: Alexander Couzens <acouzens@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>
+
+#include <osmocom/core/linuxlist.h>
+#include <osmocom/core/timer.h>
+
+struct gsm_bts;
+struct gsm_network;
+
+enum bts_setup_ramp_state {
+ BTS_SETUP_RAMP_INIT, /*!< initial state */
+ BTS_SETUP_RAMP_WAIT, /*!< BTS has to wait, too many BTS configuring */
+ BTS_SETUP_RAMP_READY, /*!< BTS is allowed to configure */
+};
+
+struct bts_setup_ramp {
+ enum bts_setup_ramp_state state;
+ struct llist_head list;
+};
+
+struct bts_setup_ramp_net {
+ unsigned count; /*!< max count */
+ unsigned step_size; /*!< also the maximum concurrent bts to configure */
+
+ struct llist_head head;
+ struct osmo_timer_list timer;
+ unsigned int step_interval; /*!< in seconds */
+ bool enabled; /*!< enabled by vty */
+ bool active; /*!< if currently active */
+};
+
+void bts_setup_ramp_init_bts(struct gsm_bts *bts);
+void bts_setup_ramp_init_network(struct gsm_network *net);
+
+bool bts_setup_ramp_active(struct gsm_network *net);
+bool bts_setup_ramp_wait(struct gsm_bts *bts);
+void bts_setup_ramp_remove(struct gsm_bts *bts);
+int bts_setup_ramp_unblock_bts(struct gsm_bts *bts);
+
+/* vty related functions */
+void bts_setup_ramp_enable(struct gsm_network *net);
+void bts_setup_ramp_disable(struct gsm_network *net);
+void bts_setup_ramp_set_step_interval(struct gsm_network *net, unsigned int step_interval);
+void bts_setup_ramp_set_step_size(struct gsm_network *net, unsigned int step_size);
+
+const char *bts_setup_ramp_get_state_str(struct gsm_bts *bts);
diff --git a/include/osmocom/bsc/gsm_data.h b/include/osmocom/bsc/gsm_data.h
index 481eae4..9300dfa 100644
--- a/include/osmocom/bsc/gsm_data.h
+++ b/include/osmocom/bsc/gsm_data.h
@@ -31,6 +31,7 @@
#include <osmocom/gsm/protocol/gsm_12_21.h>
#include <osmocom/gsm/protocol/gsm_03_41.h>
#include <osmocom/abis/e1_input.h>
+#include <osmocom/bsc/bts_setup_ramp.h>
#include <osmocom/bsc/meas_rep.h>
#include <osmocom/bsc/acc.h>
#include <osmocom/bsc/osmux.h>
@@ -956,6 +957,8 @@
/* Don't refuse to start with mutually exclusive codec settings */
bool allow_unusable_timeslots;

+ struct bts_setup_ramp_net bts_setup_ramp;
+
uint8_t nri_bitlen;
struct osmo_nri_ranges *null_nri_ranges;

diff --git a/include/osmocom/bsc/nm_common_fsm.h b/include/osmocom/bsc/nm_common_fsm.h
index b41d24a..4c34300 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_SETUP_RAMP_READY, /* BTS setup 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 */
@@ -120,3 +121,5 @@
void nm_obj_fsm_becomes_enabled_disabled(struct gsm_bts *bts, void *obj,
enum abis_nm_obj_class obj_class,
bool running);
+
+void nm_fsm_dispatch_all_configuring(struct gsm_bts *bts, uint32_t event, void *data);
diff --git a/src/osmo-bsc/Makefile.am b/src/osmo-bsc/Makefile.am
index 40381fe..60a76fa 100644
--- a/src/osmo-bsc/Makefile.am
+++ b/src/osmo-bsc/Makefile.am
@@ -56,6 +56,7 @@
bts_osmobts.c \
bts_unknown.c \
bts_ctrl.c \
+ bts_setup_ramp.c \
bts_vty.c \
bts_trx_vty.c \
chan_alloc.c \
diff --git a/src/osmo-bsc/bsc_vty.c b/src/osmo-bsc/bsc_vty.c
index a20cdfb..c5b60d1 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/bts_setup_ramp.h>
#include <osmocom/bsc/system_information.h>
#include <osmocom/bsc/debug.h>
#include <osmocom/bsc/paging.h>
@@ -2623,6 +2624,17 @@
vty_out(vty, " bsc-auto-rf-off %d%s",
bsc_gsmnet->auto_off_timeout, VTY_NEWLINE);

+ if (bsc_gsmnet->bts_setup_ramp.enabled)
+ vty_out(vty, " bts-setup-ramping%s", VTY_NEWLINE);
+
+ if (bsc_gsmnet->bts_setup_ramp.step_size > 0)
+ vty_out(vty, " bts-setup-ramping-step-size %d%s",
+ bsc_gsmnet->bts_setup_ramp.step_size, VTY_NEWLINE);
+
+ if (bsc_gsmnet->bts_setup_ramp.step_interval > 0)
+ vty_out(vty, " bts-setup-ramping-step-interval %d%s",
+ bsc_gsmnet->bts_setup_ramp.step_interval, VTY_NEWLINE);
+
return CMD_SUCCESS;
}

@@ -3046,6 +3058,88 @@
return CMD_SUCCESS;
}

+DEFUN_ATTR(cfg_bsc_bts_setup_ramping,
+ cfg_bsc_bts_setup_ramping_cmd,
+ "bts-setup-ramping",
+ "Enable BTS setup ramping to limit the amount of BTS to configure within a time window.\n",
+ CMD_ATTR_IMMEDIATE)
+{
+ struct gsm_network *net = gsmnet_from_vty(vty);
+ bts_setup_ramp_enable(net);
+ return CMD_SUCCESS;
+}
+
+DEFUN_ATTR(cfg_bsc_no_bts_setup_ramping,
+ cfg_bsc_no_bts_setup_ramping_cmd,
+ "no bts-setup-ramping",
+ NO_STR
+ "Disable BTS ramping and configure all waiting BTS.\n",
+ CMD_ATTR_IMMEDIATE)
+{
+ struct gsm_network *net = gsmnet_from_vty(vty);
+ bts_setup_ramp_disable(net);
+ return CMD_SUCCESS;
+}
+
+DEFUN_ATTR(cfg_bsc_bts_ramping_step_interval,
+ cfg_bsc_bts_setup_ramping_step_interval_cmd,
+ "bts-setup-ramping-step-interval <0-65535>",
+ "Configure the BTS setup ramping step interval. The time between ramping steps.\n"
+ "Set a step interval (in seconds)\n",
+ CMD_ATTR_IMMEDIATE)
+{
+ struct gsm_network *net = gsmnet_from_vty(vty);
+ int interval_size = atoi(argv[0]);
+ bts_setup_ramp_set_step_interval(net, interval_size);
+ return CMD_SUCCESS;
+}
+
+DEFUN_ATTR(cfg_bsc_bts_ramping_step_size,
+ cfg_bsc_bts_setup_ramping_step_size_cmd,
+ "bts-setup-ramping-step-size <0-65535>",
+ "Configure the BTS setup ramping step size. The amount of BTS to allow to configure within a ramping interval\n"
+ "Amount of BTS to setup while a step size\n",
+ CMD_ATTR_IMMEDIATE)
+{
+ struct gsm_network *net = gsmnet_from_vty(vty);
+ int seconds = atoi(argv[0]);
+ bts_setup_ramp_set_step_size(net, seconds);
+ return CMD_SUCCESS;
+}
+
+DEFUN(bts_unblock_setup_ramping,
+ bts_unblock_setup_ramping_cmd,
+ "bts <0-255> unblock-setup-ramping",
+ "BTS Specific Commands\n" BTS_NR_STR
+ "Unblock and allow to configure a BTS if kept back by BTS ramping\n")
+{
+ 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_setup_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(show_statistics,
show_statistics_cmd,
"show statistics",
@@ -3471,6 +3565,7 @@

install_element(ENABLE_NODE, &drop_bts_cmd);
install_element(ENABLE_NODE, &restart_bts_cmd);
+ install_element(ENABLE_NODE, &bts_unblock_setup_ramping_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);
@@ -3511,6 +3606,10 @@
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_setup_ramping_cmd);
+ install_element(BSC_NODE, &cfg_bsc_no_bts_setup_ramping_cmd);
+ install_element(BSC_NODE, &cfg_bsc_bts_setup_ramping_step_size_cmd);
+ install_element(BSC_NODE, &cfg_bsc_bts_setup_ramping_step_interval_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 8d4b8c8..95e3197 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_setup_ramp_remove(bts);

osmo_timer_del(&bts->cbch_timer);

@@ -436,6 +437,7 @@
bts_cbch_init(bts);
bts_etws_init(bts);

+ bts_setup_ramp_init_bts(bts);
acc_mgr_init(&bts->acc_mgr, bts);
acc_ramp_init(&bts->acc_ramp, bts);

diff --git a/src/osmo-bsc/bts_ipaccess_nanobts.c b/src/osmo-bsc/bts_ipaccess_nanobts.c
index 624aabc..338c83f 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_setup_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_setup_ramp.c b/src/osmo-bsc/bts_setup_ramp.c
new file mode 100644
index 0000000..247f776
--- /dev/null
+++ b/src/osmo-bsc/bts_setup_ramp.c
@@ -0,0 +1,249 @@
+/* (C) 2022 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>
+ *
+ * Author: Alexander Couzens <acouzens@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/bts_setup_ramp.h>
+#include <osmocom/bsc/nm_common_fsm.h>
+
+
+static void _bts_setup_ramp_unblock_bts(struct gsm_bts *bts)
+{
+ llist_del_init(&bts->bts_setup_ramp.list);
+ bts->bts_setup_ramp.state = BTS_SETUP_RAMP_READY;
+
+ nm_fsm_dispatch_all_configuring(bts, NM_EV_SETUP_RAMP_READY, NULL);
+}
+
+/*!
+ * Unblock a BTS from BTS setup ramping to continue setup and configure.
+ *
+ * \param bts pointer to the bts
+ * \return 0 on success, -EINVAL when the BTS is not waiting.
+ */
+int bts_setup_ramp_unblock_bts(struct gsm_bts *bts)
+{
+ if (bts->bts_setup_ramp.state != BTS_SETUP_RAMP_WAIT)
+ return -EINVAL;
+
+ if (llist_empty(&bts->bts_setup_ramp.list))
+ return -EINVAL;
+
+ _bts_setup_ramp_unblock_bts(bts);
+ return 0;
+}
+
+/*!
+ * Timer callback and called by bts_setup_ramp_deactivate
+ * \param _net pointer to struct gsm_network
+ */
+static void bts_setup_ramp_timer_cb(void *_net)
+{
+ struct gsm_network *net = (struct gsm_network *) _net;
+ struct gsm_bts *bts, *n;
+ net->bts_setup_ramp.count = 0;
+
+ llist_for_each_entry_safe(bts, n, &net->bts_setup_ramp.head, bts_setup_ramp.list) {
+ net->bts_setup_ramp.count++;
+ _bts_setup_ramp_unblock_bts(bts);
+ LOG_BTS(bts, DNM, LOGL_INFO, "Unblock BTS %d from BTS ramping.\n", bts->nr);
+ if (bts_setup_ramp_active(net) && net->bts_setup_ramp.count >= net->bts_setup_ramp.step_size)
+ break;
+ }
+
+ if (bts_setup_ramp_active(net))
+ osmo_timer_schedule(&net->bts_setup_ramp.timer, net->bts_setup_ramp.step_interval, 0);
+}
+
+const struct value_string bts_setup_ramp_state_values[] = {
+ { BTS_SETUP_RAMP_INIT, "Initial" },
+ { BTS_SETUP_RAMP_WAIT, "Waiting" },
+ { BTS_SETUP_RAMP_READY, "Ready" },
+ { 0, NULL },
+};
+
+const char *bts_setup_ramp_get_state_str(struct gsm_bts *bts)
+{
+ return get_value_string_or_null(bts_setup_ramp_state_values, bts->bts_setup_ramp.state);
+}
+
+/* return true when state has been changed. */
+static bool check_config(struct gsm_network *net)
+{
+ bool new_state = (net->bts_setup_ramp.enabled
+ && net->bts_setup_ramp.step_size > 0
+ && net->bts_setup_ramp.step_interval > 0);
+
+ if (!new_state && bts_setup_ramp_active(net)) {
+ net->bts_setup_ramp.active = false;
+ osmo_timer_del(&net->bts_setup_ramp.timer);
+ /* clear bts list */
+ bts_setup_ramp_timer_cb(net);
+ return true;
+ } else if (new_state && !bts_setup_ramp_active(net)) {
+ net->bts_setup_ramp.active = true;
+ osmo_timer_schedule(&net->bts_setup_ramp.timer, net->bts_setup_ramp.step_interval, 0);
+ return true;
+ }
+
+ return false;
+}
+
+/*!
+ * Enable the bts setup ramping feature
+ *
+ * The BTS setup ramping prevents BSC overload when too many BTS tries to setup and
+ * configure at the same time. E.g. this might happen if there is a major network outage
+ * between all BTS and the BSC.
+ *
+ * \param[in] net a pointer to the gsm network
+ */
+void bts_setup_ramp_enable(struct gsm_network *net)
+{
+ net->bts_setup_ramp.enabled = true;
+ check_config(net);
+}
+
+/*!
+ * Disable the bts setup ramping feature
+ *
+ * \param[in] net a pointer to the gsm network
+ */
+void bts_setup_ramp_disable(struct gsm_network *net)
+{
+ net->bts_setup_ramp.enabled = false;
+ check_config(net);
+}
+
+/*! Checks if the bts setup ramp correct configured and active
+ *
+ * \param[in] net a pointer to the gsm network
+ * \return true if the bts setup ramp is active
+ */
+bool bts_setup_ramp_active(struct gsm_network *net)
+{
+ return net->bts_setup_ramp.active;
+}
+
+/*!
+ * Check if the BTS should wait to setup.
+ *
+ * Can be called multiple times by the same BTS.
+ *
+ * \param bts pointer to the bts
+ * \return true if the bts should wait
+ */
+bool bts_setup_ramp_wait(struct gsm_bts *bts)
+{
+ struct gsm_network *net = bts->network;
+
+ if (!bts_setup_ramp_active(net)) {
+ bts->bts_setup_ramp.state = BTS_SETUP_RAMP_READY;
+ return false;
+ }
+
+ switch (bts->bts_setup_ramp.state) {
+ case BTS_SETUP_RAMP_INIT:
+ break;
+ case BTS_SETUP_RAMP_WAIT:
+ return true;
+ case BTS_SETUP_RAMP_READY:
+ return false;
+ }
+
+ if (net->bts_setup_ramp.count < net->bts_setup_ramp.step_size) {
+ LOG_BTS(bts, DNM, LOGL_INFO,
+ "BTS %d can configure without waiting for BTS ramping.\n", bts->nr);
+
+ net->bts_setup_ramp.count++;
+ bts->bts_setup_ramp.state = BTS_SETUP_RAMP_READY;
+ return false;
+ }
+
+ bts->bts_setup_ramp.state = BTS_SETUP_RAMP_WAIT;
+ llist_add_tail(&bts->bts_setup_ramp.list, &net->bts_setup_ramp.head);
+ LOGP(DNM, LOGL_INFO, "BTS %d will wait for BTS ramping.\n", bts->nr);
+
+ return true;
+}
+
+void bts_setup_ramp_init_network(struct gsm_network *net)
+{
+ INIT_LLIST_HEAD(&net->bts_setup_ramp.head);
+ osmo_timer_setup(&net->bts_setup_ramp.timer, bts_setup_ramp_timer_cb, net);
+}
+
+void bts_setup_ramp_init_bts(struct gsm_bts *bts)
+{
+ /* Initialize bts_setup_ramp.list (llist_entry) to have llist_empty() available */
+ INIT_LLIST_HEAD(&bts->bts_setup_ramp.list);
+ bts->bts_setup_ramp.state = BTS_SETUP_RAMP_INIT;
+}
+
+/*!
+ * Remove the bts from the bts setup ramp waiting list and resets the BTS setup ramping state.
+ * Should be called when removing the BTS
+ *
+ * \param bts pointer to the bts
+ */
+void bts_setup_ramp_remove(struct gsm_bts *bts)
+{
+ if (!llist_empty(&bts->bts_setup_ramp.list))
+ llist_del_init(&bts->bts_setup_ramp.list);
+ bts->bts_setup_ramp.state = BTS_SETUP_RAMP_INIT;
+}
+
+/*!
+ * Set the BTS setup ramping step interval.
+ *
+ * Within the time window of \param step_interval only a limited amount (see step_size)
+ * of BTS will be configured.
+ *
+ * \param[in] net a pointer to the gsm network
+ * \param step_interval in seconds
+ */
+void bts_setup_ramp_set_step_interval(struct gsm_network *net, unsigned int step_interval)
+{
+ net->bts_setup_ramp.step_interval = step_interval;
+ check_config(net);
+}
+
+/*!
+ * Set the BTS setup ramping step_size
+ *
+ * Within the time window of step_interval only a limited amount of BTS (\param step_size)
+ * will be configured.
+ *
+ * \param[in] net a pointer to the gsm network
+ * \param step_size the step size
+ */
+void bts_setup_ramp_set_step_size(struct gsm_network *net, unsigned int step_size)
+{
+ net->bts_setup_ramp.step_size = step_size;
+ check_config(net);
+}
diff --git a/src/osmo-bsc/bts_vty.c b/src/osmo-bsc/bts_vty.c
index 732ed57..e01d9b8 100644
--- a/src/osmo-bsc/bts_vty.c
+++ b/src/osmo-bsc/bts_vty.c
@@ -4012,6 +4012,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_setup_ramp_active(bts->network))
+ vty_out(vty, " BTS Ramping: %s", bts_setup_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..8f2b26c 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/bts_setup_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_setup_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..3302918 100644
--- a/src/osmo-bsc/nm_bb_transc_fsm.c
+++ b/src/osmo-bsc/nm_bb_transc_fsm.c
@@ -76,6 +76,7 @@

switch (event) {
case NM_EV_SW_ACT_REP:
+ case NM_EV_SETUP_RAMP_READY:
break;
case NM_EV_STATE_CHG_REP:
nsd = (struct nm_statechg_signal_data *)data;
@@ -105,6 +106,9 @@
{
struct gsm_bts_trx *trx = gsm_bts_bb_trx_get_trx(bb_transc);

+ if (bts_setup_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;
@@ -202,6 +206,9 @@
default:
return;
}
+ case NM_EV_SETUP_RAMP_READY:
+ configure_loop(bb_transc, &bb_transc->mo.nm_state, false);
+ break;
default:
OSMO_ASSERT(0);
}
@@ -266,6 +273,9 @@
default:
return;
}
+ case NM_EV_SETUP_RAMP_READY:
+ configure_loop(bb_transc, &bb_transc->mo.nm_state, true);
+ break;
default:
OSMO_ASSERT(0);
}
@@ -348,7 +358,8 @@
[NM_BB_TRANSC_ST_OP_DISABLED_NOTINSTALLED] = {
.in_event_mask =
X(NM_EV_SW_ACT_REP) |
- X(NM_EV_STATE_CHG_REP),
+ X(NM_EV_STATE_CHG_REP) |
+ X(NM_EV_SETUP_RAMP_READY),
.out_state_mask =
X(NM_BB_TRANSC_ST_OP_DISABLED_DEPENDENCY) |
X(NM_BB_TRANSC_ST_OP_DISABLED_OFFLINE) |
@@ -362,7 +373,8 @@
X(NM_EV_STATE_CHG_REP) |
X(NM_EV_GET_ATTR_REP) |
X(NM_EV_RSL_CONNECT_ACK) |
- X(NM_EV_RSL_CONNECT_NACK),
+ X(NM_EV_RSL_CONNECT_NACK) |
+ X(NM_EV_SETUP_RAMP_READY),
.out_state_mask =
X(NM_BB_TRANSC_ST_OP_DISABLED_NOTINSTALLED) |
X(NM_BB_TRANSC_ST_OP_DISABLED_OFFLINE) |
@@ -376,7 +388,8 @@
X(NM_EV_STATE_CHG_REP) |
X(NM_EV_GET_ATTR_REP) |
X(NM_EV_RSL_CONNECT_ACK) |
- X(NM_EV_RSL_CONNECT_NACK),
+ X(NM_EV_RSL_CONNECT_NACK) |
+ X(NM_EV_SETUP_RAMP_READY),
.out_state_mask =
X(NM_BB_TRANSC_ST_OP_DISABLED_NOTINSTALLED) |
X(NM_BB_TRANSC_ST_OP_DISABLED_DEPENDENCY) |
diff --git a/src/osmo-bsc/nm_bts_fsm.c b/src/osmo-bsc/nm_bts_fsm.c
index 1b71323..3d95b93 100644
--- a/src/osmo-bsc/nm_bts_fsm.c
+++ b/src/osmo-bsc/nm_bts_fsm.c
@@ -63,6 +63,7 @@

switch (event) {
case NM_EV_SW_ACT_REP:
+ case NM_EV_SETUP_RAMP_READY:
break;
case NM_EV_STATE_CHG_REP:
nsd = (struct nm_statechg_signal_data *)data;
@@ -92,6 +93,9 @@
{
struct msgb *msgb;

+ if (bts_setup_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;
@@ -198,6 +202,9 @@
default:
return;
}
+ case NM_EV_SETUP_RAMP_READY:
+ configure_loop(bts, &bts->mo.nm_state, false);
+ break;
default:
OSMO_ASSERT(0);
}
@@ -256,6 +263,9 @@
default:
return;
}
+ case NM_EV_SETUP_RAMP_READY:
+ configure_loop(bts, &bts->mo.nm_state, true);
+ break;
default:
OSMO_ASSERT(0);
}
@@ -329,7 +339,8 @@
[NM_BTS_ST_OP_DISABLED_NOTINSTALLED] = {
.in_event_mask =
X(NM_EV_SW_ACT_REP) |
- X(NM_EV_STATE_CHG_REP),
+ X(NM_EV_STATE_CHG_REP) |
+ X(NM_EV_SETUP_RAMP_READY),
.out_state_mask =
X(NM_BTS_ST_OP_DISABLED_DEPENDENCY) |
X(NM_BTS_ST_OP_DISABLED_OFFLINE) |
@@ -342,7 +353,8 @@
.in_event_mask =
X(NM_EV_STATE_CHG_REP) |
X(NM_EV_GET_ATTR_REP) |
- X(NM_EV_SET_ATTR_ACK),
+ X(NM_EV_SET_ATTR_ACK) |
+ X(NM_EV_SETUP_RAMP_READY),
.out_state_mask =
X(NM_BTS_ST_OP_DISABLED_NOTINSTALLED) |
X(NM_BTS_ST_OP_DISABLED_OFFLINE) |
@@ -355,7 +367,8 @@
.in_event_mask =
X(NM_EV_STATE_CHG_REP) |
X(NM_EV_GET_ATTR_REP) |
- X(NM_EV_SET_ATTR_ACK),
+ X(NM_EV_SET_ATTR_ACK) |
+ X(NM_EV_SETUP_RAMP_READY),
.out_state_mask =
X(NM_BTS_ST_OP_DISABLED_NOTINSTALLED) |
X(NM_BTS_ST_OP_DISABLED_DEPENDENCY) |
diff --git a/src/osmo-bsc/nm_bts_sm_fsm.c b/src/osmo-bsc/nm_bts_sm_fsm.c
index 03bf43c..fb64a69 100644
--- a/src/osmo-bsc/nm_bts_sm_fsm.c
+++ b/src/osmo-bsc/nm_bts_sm_fsm.c
@@ -61,6 +61,7 @@

switch (event) {
case NM_EV_SW_ACT_REP:
+ case NM_EV_SETUP_RAMP_READY:
break;
case NM_EV_STATE_CHG_REP:
nsd = (struct nm_statechg_signal_data *)data;
@@ -99,12 +100,28 @@
}
}

+static void configure_loop(struct gsm_bts_sm *site_mgr, const struct gsm_nm_state *_state, bool allow_opstart)
+{
+ struct gsm_bts *bts = gsm_bts_sm_get_bts(site_mgr);
+
+ if (bts_setup_ramp_wait(bts))
+ return;
+
+ if (allow_opstart && !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;
const struct gsm_nm_state *new_state;

switch (event) {
+ case NM_EV_SETUP_RAMP_READY:
+ break;
case NM_EV_STATE_CHG_REP:
nsd = (struct nm_statechg_signal_data *)data;
new_state = &nsd->new_state;
@@ -132,17 +149,15 @@
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, &site_mgr->mo.nm_state, true);
}

static void st_op_disabled_offline(struct osmo_fsm_inst *fi, uint32_t event, void *data)
{
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;

switch (event) {
case NM_EV_STATE_CHG_REP:
@@ -166,10 +181,14 @@
default:
return;
}
+ case NM_EV_SETUP_RAMP_READY:
+ configure_loop(site_mgr, &site_mgr->mo.nm_state, true);
+ break;
default:
OSMO_ASSERT(0);
}
}
+
static void st_op_enabled(struct osmo_fsm_inst *fi, uint32_t event, void *data)
{
struct nm_statechg_signal_data *nsd;
@@ -224,7 +243,8 @@
[NM_BTS_SM_ST_OP_DISABLED_NOTINSTALLED] = {
.in_event_mask =
X(NM_EV_SW_ACT_REP) |
- X(NM_EV_STATE_CHG_REP),
+ X(NM_EV_STATE_CHG_REP) |
+ X(NM_EV_SETUP_RAMP_READY),
.out_state_mask =
X(NM_BTS_SM_ST_OP_DISABLED_DEPENDENCY) |
X(NM_BTS_SM_ST_OP_DISABLED_OFFLINE) |
@@ -235,7 +255,8 @@
},
[NM_BTS_SM_ST_OP_DISABLED_DEPENDENCY] = {
.in_event_mask =
- X(NM_EV_STATE_CHG_REP),
+ X(NM_EV_STATE_CHG_REP) |
+ X(NM_EV_SETUP_RAMP_READY),
.out_state_mask =
X(NM_BTS_SM_ST_OP_DISABLED_NOTINSTALLED) |
X(NM_BTS_SM_ST_OP_DISABLED_OFFLINE) |
@@ -245,7 +266,8 @@
},
[NM_BTS_SM_ST_OP_DISABLED_OFFLINE] = {
.in_event_mask =
- X(NM_EV_STATE_CHG_REP),
+ X(NM_EV_STATE_CHG_REP) |
+ X(NM_EV_SETUP_RAMP_READY),
.out_state_mask =
X(NM_BTS_SM_ST_OP_DISABLED_NOTINSTALLED) |
X(NM_BTS_SM_ST_OP_DISABLED_DEPENDENCY) |
diff --git a/src/osmo-bsc/nm_channel_fsm.c b/src/osmo-bsc/nm_channel_fsm.c
index c3146a4..45e455a 100644
--- a/src/osmo-bsc/nm_channel_fsm.c
+++ b/src/osmo-bsc/nm_channel_fsm.c
@@ -62,6 +62,7 @@

switch (event) {
case NM_EV_SW_ACT_REP:
+ case NM_EV_SETUP_RAMP_READY:
break;
case NM_EV_STATE_CHG_REP:
nsd = (struct nm_statechg_signal_data *)data;
@@ -92,6 +93,9 @@
enum abis_nm_chan_comb ccomb;
struct gsm_bts_trx *trx = ts->trx;

+ if (bts_setup_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);
@@ -159,6 +163,9 @@
default:
return;
}
+ case NM_EV_SETUP_RAMP_READY:
+ configure_loop(ts, &ts->mo.nm_state, false);
+ break;
default:
OSMO_ASSERT(0);
}
@@ -214,6 +221,9 @@
default:
return;
}
+ case NM_EV_SETUP_RAMP_READY:
+ configure_loop(ts, &ts->mo.nm_state, true);
+ break;
default:
OSMO_ASSERT(0);
}
@@ -285,7 +295,8 @@
[NM_CHAN_ST_OP_DISABLED_NOTINSTALLED] = {
.in_event_mask =
X(NM_EV_SW_ACT_REP) |
- X(NM_EV_STATE_CHG_REP),
+ X(NM_EV_STATE_CHG_REP) |
+ X(NM_EV_SETUP_RAMP_READY),
.out_state_mask =
X(NM_CHAN_ST_OP_DISABLED_DEPENDENCY) |
X(NM_CHAN_ST_OP_DISABLED_OFFLINE) |
@@ -297,7 +308,8 @@
[NM_CHAN_ST_OP_DISABLED_DEPENDENCY] = {
.in_event_mask =
X(NM_EV_STATE_CHG_REP) |
- X(NM_EV_SET_ATTR_ACK),
+ X(NM_EV_SET_ATTR_ACK) |
+ X(NM_EV_SETUP_RAMP_READY),
.out_state_mask =
X(NM_CHAN_ST_OP_DISABLED_NOTINSTALLED) |
X(NM_CHAN_ST_OP_DISABLED_OFFLINE) |
@@ -309,7 +321,8 @@
[NM_CHAN_ST_OP_DISABLED_OFFLINE] = {
.in_event_mask =
X(NM_EV_STATE_CHG_REP) |
- X(NM_EV_SET_ATTR_ACK),
+ X(NM_EV_SET_ATTR_ACK) |
+ X(NM_EV_SETUP_RAMP_READY),
.out_state_mask =
X(NM_CHAN_ST_OP_DISABLED_NOTINSTALLED) |
X(NM_CHAN_ST_OP_DISABLED_DEPENDENCY) |
diff --git a/src/osmo-bsc/nm_common_fsm.c b/src/osmo-bsc/nm_common_fsm.c
index 2bf38ac..02e2c5e 100644
--- a/src/osmo-bsc/nm_common_fsm.c
+++ b/src/osmo-bsc/nm_common_fsm.c
@@ -20,6 +20,8 @@
*
*/

+#include <osmocom/core/linuxlist.h>
+#include <osmocom/bsc/bts.h>
#include <osmocom/bsc/nm_common_fsm.h>
#include <osmocom/bsc/signal.h>

@@ -51,3 +53,38 @@

osmo_signal_dispatch(SS_NM, S_NM_RUNNING_CHG, &nsd);
}
+
+/* nm_configuring_fsm_inst_dispatch(struct gsm_abis_mo *mo, uint32_t event, void *data) */
+#define nm_configuring_fsm_inst_dispatch(mo, event, data) do { \
+ if ((mo)->nm_state.operational != NM_OPSTATE_ENABLED) \
+ _osmo_fsm_inst_dispatch((mo)->fi, event, data, __FILE__, __LINE__); \
+ } while (0)
+
+/*!
+ * Dispatch an event to all configuring/non-enabled BTS NM fsms
+ *
+ * \param[in] bts a pointer to the BTS instance
+ * \param[in] event the FSM event. See \fn osmo_fsm_inst_dispatch
+ * \param[in] data the private data of the event.
+ */
+void nm_fsm_dispatch_all_configuring(struct gsm_bts *bts, uint32_t event, void *data)
+{
+ struct gsm_bts_trx *trx;
+
+ nm_configuring_fsm_inst_dispatch(&bts->site_mgr->mo, event, data);
+ nm_configuring_fsm_inst_dispatch(&bts->mo, event, data);
+ llist_for_each_entry(trx, &bts->trx_list, list) {
+ nm_configuring_fsm_inst_dispatch(&trx->mo, event, data);
+ nm_configuring_fsm_inst_dispatch(&trx->bb_transc.mo, event, data);
+ for (unsigned long i = 0; i < ARRAY_SIZE(trx->ts); i++) {
+ struct gsm_bts_trx_ts *ts = &trx->ts[i];
+ nm_configuring_fsm_inst_dispatch(&ts->mo, event, data);
+ }
+ }
+
+ /* GPRS MOs */
+ nm_configuring_fsm_inst_dispatch(&bts->site_mgr->gprs.nse.mo, event, data);
+ for (unsigned long i = 0; i < ARRAY_SIZE(bts->site_mgr->gprs.nsvc); i++)
+ nm_configuring_fsm_inst_dispatch(&bts->site_mgr->gprs.nsvc[i].mo, event, data);
+ nm_configuring_fsm_inst_dispatch(&bts->gprs.cell.mo, event, data);
+}
diff --git a/src/osmo-bsc/nm_gprs_cell_fsm.c b/src/osmo-bsc/nm_gprs_cell_fsm.c
index aabfc0b..3e61657 100644
--- a/src/osmo-bsc/nm_gprs_cell_fsm.c
+++ b/src/osmo-bsc/nm_gprs_cell_fsm.c
@@ -61,6 +61,7 @@

switch (event) {
case NM_EV_SW_ACT_REP:
+ case NM_EV_SETUP_RAMP_READY:
break;
case NM_EV_STATE_CHG_REP:
nsd = (struct nm_statechg_signal_data *)data;
@@ -94,6 +95,9 @@
if (bts->gprs.mode == BTS_GPRS_NONE)
return;

+ if (bts_setup_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);
@@ -169,6 +173,9 @@
default:
return;
}
+ case NM_EV_SETUP_RAMP_READY:
+ configure_loop(cell, &cell->mo.nm_state, false);
+ break;
default:
OSMO_ASSERT(0);
}
@@ -225,6 +232,9 @@
default:
return;
}
+ case NM_EV_SETUP_RAMP_READY:
+ configure_loop(cell, &cell->mo.nm_state, true);
+ break;
default:
OSMO_ASSERT(0);
}
@@ -303,7 +313,8 @@
[NM_GPRS_CELL_ST_OP_DISABLED_NOTINSTALLED] = {
.in_event_mask =
X(NM_EV_SW_ACT_REP) |
- X(NM_EV_STATE_CHG_REP),
+ X(NM_EV_STATE_CHG_REP) |
+ X(NM_EV_SETUP_RAMP_READY),
.out_state_mask =
X(NM_GPRS_CELL_ST_OP_DISABLED_DEPENDENCY) |
X(NM_GPRS_CELL_ST_OP_DISABLED_OFFLINE) |
@@ -315,7 +326,8 @@
[NM_GPRS_CELL_ST_OP_DISABLED_DEPENDENCY] = {
.in_event_mask =
X(NM_EV_STATE_CHG_REP) |
- X(NM_EV_SET_ATTR_ACK),
+ X(NM_EV_SET_ATTR_ACK) |
+ X(NM_EV_SETUP_RAMP_READY),
.out_state_mask =
X(NM_GPRS_CELL_ST_OP_DISABLED_NOTINSTALLED) |
X(NM_GPRS_CELL_ST_OP_DISABLED_OFFLINE) |
@@ -327,7 +339,8 @@
[NM_GPRS_CELL_ST_OP_DISABLED_OFFLINE] = {
.in_event_mask =
X(NM_EV_STATE_CHG_REP) |
- X(NM_EV_SET_ATTR_ACK),
+ X(NM_EV_SET_ATTR_ACK) |
+ X(NM_EV_SETUP_RAMP_READY),
.out_state_mask =
X(NM_GPRS_CELL_ST_OP_DISABLED_NOTINSTALLED) |
X(NM_GPRS_CELL_ST_OP_DISABLED_DEPENDENCY) |
diff --git a/src/osmo-bsc/nm_gprs_nse_fsm.c b/src/osmo-bsc/nm_gprs_nse_fsm.c
index 49908ce..1403c5f 100644
--- a/src/osmo-bsc/nm_gprs_nse_fsm.c
+++ b/src/osmo-bsc/nm_gprs_nse_fsm.c
@@ -62,6 +62,7 @@

switch (event) {
case NM_EV_SW_ACT_REP:
+ case NM_EV_SETUP_RAMP_READY:
break;
case NM_EV_STATE_CHG_REP:
nsd = (struct nm_statechg_signal_data *)data;
@@ -93,6 +94,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_setup_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);
@@ -170,6 +174,9 @@
default:
return;
}
+ case NM_EV_SETUP_RAMP_READY:
+ configure_loop(nse, &nse->mo.nm_state, false);
+ break;
default:
OSMO_ASSERT(0);
}
@@ -226,6 +233,9 @@
default:
return;
}
+ case NM_EV_SETUP_RAMP_READY:
+ configure_loop(nse, &nse->mo.nm_state, true);
+ break;
default:
OSMO_ASSERT(0);
}
@@ -305,7 +315,8 @@
[NM_GPRS_NSE_ST_OP_DISABLED_NOTINSTALLED] = {
.in_event_mask =
X(NM_EV_SW_ACT_REP) |
- X(NM_EV_STATE_CHG_REP),
+ X(NM_EV_STATE_CHG_REP) |
+ X(NM_EV_SETUP_RAMP_READY),
.out_state_mask =
X(NM_GPRS_NSE_ST_OP_DISABLED_DEPENDENCY) |
X(NM_GPRS_NSE_ST_OP_DISABLED_OFFLINE) |
@@ -317,7 +328,8 @@
[NM_GPRS_NSE_ST_OP_DISABLED_DEPENDENCY] = {
.in_event_mask =
X(NM_EV_STATE_CHG_REP) |
- X(NM_EV_SET_ATTR_ACK),
+ X(NM_EV_SET_ATTR_ACK) |
+ X(NM_EV_SETUP_RAMP_READY),
.out_state_mask =
X(NM_GPRS_NSE_ST_OP_DISABLED_NOTINSTALLED) |
X(NM_GPRS_NSE_ST_OP_DISABLED_OFFLINE) |
@@ -329,7 +341,8 @@
[NM_GPRS_NSE_ST_OP_DISABLED_OFFLINE] = {
.in_event_mask =
X(NM_EV_STATE_CHG_REP) |
- X(NM_EV_SET_ATTR_ACK),
+ X(NM_EV_SET_ATTR_ACK) |
+ X(NM_EV_SETUP_RAMP_READY),
.out_state_mask =
X(NM_GPRS_NSE_ST_OP_DISABLED_NOTINSTALLED) |
X(NM_GPRS_NSE_ST_OP_DISABLED_DEPENDENCY) |
diff --git a/src/osmo-bsc/nm_gprs_nsvc_fsm.c b/src/osmo-bsc/nm_gprs_nsvc_fsm.c
index 29eed5c..e4a6338 100644
--- a/src/osmo-bsc/nm_gprs_nsvc_fsm.c
+++ b/src/osmo-bsc/nm_gprs_nsvc_fsm.c
@@ -63,8 +63,8 @@

switch (event) {
case NM_EV_FEATURE_NEGOTIATED:
- break;
case NM_EV_SW_ACT_REP:
+ case NM_EV_SETUP_RAMP_READY:
break;
case NM_EV_STATE_CHG_REP:
nsd = (struct nm_statechg_signal_data *)data;
@@ -97,6 +97,9 @@
if (nsvc->bts->gprs.mode == BTS_GPRS_NONE)
return;

+ if (bts_setup_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) {
@@ -185,6 +188,9 @@
default:
return;
}
+ case NM_EV_SETUP_RAMP_READY:
+ configure_loop(nsvc, &nsvc->mo.nm_state, false);
+ break;
default:
OSMO_ASSERT(0);
}
@@ -243,6 +249,9 @@
default:
return;
}
+ case NM_EV_SETUP_RAMP_READY:
+ configure_loop(nsvc, &nsvc->mo.nm_state, true);
+ break;
default:
OSMO_ASSERT(0);
}
@@ -315,7 +324,8 @@
.in_event_mask =
X(NM_EV_SW_ACT_REP) |
X(NM_EV_FEATURE_NEGOTIATED) |
- X(NM_EV_STATE_CHG_REP),
+ X(NM_EV_STATE_CHG_REP) |
+ X(NM_EV_SETUP_RAMP_READY),
.out_state_mask =
X(NM_GPRS_NSVC_ST_OP_DISABLED_DEPENDENCY) |
X(NM_GPRS_NSVC_ST_OP_DISABLED_OFFLINE) |
@@ -328,7 +338,8 @@
.in_event_mask =
X(NM_EV_STATE_CHG_REP) |
X(NM_EV_FEATURE_NEGOTIATED) |
- X(NM_EV_SET_ATTR_ACK),
+ X(NM_EV_SET_ATTR_ACK) |
+ X(NM_EV_SETUP_RAMP_READY),
.out_state_mask =
X(NM_GPRS_NSVC_ST_OP_DISABLED_NOTINSTALLED) |
X(NM_GPRS_NSVC_ST_OP_DISABLED_OFFLINE) |
@@ -341,7 +352,8 @@
.in_event_mask =
X(NM_EV_STATE_CHG_REP) |
X(NM_EV_FEATURE_NEGOTIATED) |
- X(NM_EV_SET_ATTR_ACK),
+ X(NM_EV_SET_ATTR_ACK) |
+ X(NM_EV_SETUP_RAMP_READY),
.out_state_mask =
X(NM_GPRS_NSVC_ST_OP_DISABLED_NOTINSTALLED) |
X(NM_GPRS_NSVC_ST_OP_DISABLED_DEPENDENCY) |
diff --git a/src/osmo-bsc/nm_rcarrier_fsm.c b/src/osmo-bsc/nm_rcarrier_fsm.c
index c8b95ad..00d1d48 100644
--- a/src/osmo-bsc/nm_rcarrier_fsm.c
+++ b/src/osmo-bsc/nm_rcarrier_fsm.c
@@ -71,6 +71,7 @@

switch (event) {
case NM_EV_SW_ACT_REP:
+ case NM_EV_SETUP_RAMP_READY:
break;
case NM_EV_STATE_CHG_REP:
nsd = (struct nm_statechg_signal_data *)data;
@@ -100,6 +101,9 @@
{
struct msgb *msgb;

+ if (bts_setup_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);
@@ -175,6 +179,9 @@
default:
return;
}
+ case NM_EV_SETUP_RAMP_READY:
+ configure_loop(trx, &trx->mo.nm_state, false);
+ break;
default:
OSMO_ASSERT(0);
}
@@ -221,6 +228,9 @@
default:
return;
}
+ case NM_EV_SETUP_RAMP_READY:
+ configure_loop(trx, &trx->mo.nm_state, true);
+ break;
default:
OSMO_ASSERT(0);
}
@@ -326,7 +336,8 @@
[NM_RCARRIER_ST_OP_DISABLED_NOTINSTALLED] = {
.in_event_mask =
X(NM_EV_SW_ACT_REP) |
- X(NM_EV_STATE_CHG_REP),
+ X(NM_EV_STATE_CHG_REP) |
+ X(NM_EV_SETUP_RAMP_READY),
.out_state_mask =
X(NM_RCARRIER_ST_OP_DISABLED_DEPENDENCY) |
X(NM_RCARRIER_ST_OP_DISABLED_OFFLINE) |
@@ -338,7 +349,8 @@
[NM_RCARRIER_ST_OP_DISABLED_DEPENDENCY] = {
.in_event_mask =
X(NM_EV_STATE_CHG_REP) |
- X(NM_EV_SET_ATTR_ACK),
+ X(NM_EV_SET_ATTR_ACK) |
+ X(NM_EV_SETUP_RAMP_READY),
.out_state_mask =
X(NM_RCARRIER_ST_OP_DISABLED_NOTINSTALLED) |
X(NM_RCARRIER_ST_OP_DISABLED_OFFLINE) |
@@ -350,7 +362,8 @@
[NM_RCARRIER_ST_OP_DISABLED_OFFLINE] = {
.in_event_mask =
X(NM_EV_STATE_CHG_REP) |
- X(NM_EV_SET_ATTR_ACK),
+ X(NM_EV_SET_ATTR_ACK) |
+ X(NM_EV_SETUP_RAMP_READY),
.out_state_mask =
X(NM_RCARRIER_ST_OP_DISABLED_NOTINSTALLED) |
X(NM_RCARRIER_ST_OP_DISABLED_DEPENDENCY) |
diff --git a/src/osmo-bsc/osmo_bsc_main.c b/src/osmo-bsc/osmo_bsc_main.c
index 91db7be..2656d23 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_setup_ramp_init_bts(bts);
+
/* ACC ramping is initialized from vty/config */

/* Initialize the BTS state */
diff --git a/tests/osmo-bsc.vty b/tests/osmo-bsc.vty
index 4be3d56..776b5ad 100644
--- a/tests/osmo-bsc.vty
+++ b/tests/osmo-bsc.vty
@@ -46,6 +46,7 @@
<0-255> BTS Number

OsmoBSC# bts 0 ?
+ unblock-setup-ramping Unblock and allow to configure a BTS if kept back by BTS ramping
resend-system-information Re-generate + re-send BCCH SYSTEM INFORMATION
resend-power-control-defaults Re-generate + re-send default MS/BS Power control parameters
c0-power-reduction BCCH carrier power reduction operation

To view, visit change 29788. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: osmo-bsc
Gerrit-Branch: master
Gerrit-Change-Id: Id56dde6d58f3d0d20352f6c306598d2cccc6345d
Gerrit-Change-Number: 29788
Gerrit-PatchSet: 22
Gerrit-Owner: lynxis lazus <lynxis@fe80.eu>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: daniel <dwillmann@sysmocom.de>
Gerrit-Reviewer: fixeria <vyanitskiy@sysmocom.de>
Gerrit-Reviewer: lynxis lazus <lynxis@fe80.eu>
Gerrit-Reviewer: pespin <pespin@sysmocom.de>
Gerrit-CC: laforge <laforge@osmocom.org>
Gerrit-CC: neels <nhofmeyr@sysmocom.de>
Gerrit-MessageType: merged