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@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> + +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@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/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 */