lynxis lazus has submitted this change. ( https://gerrit.osmocom.org/c/osmo-bsc/+/29788 )
Change subject: Add BTS setup ramping to prevent BSC overloading ......................................................................
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(-)
Approvals: daniel: Looks good to me, approved pespin: Looks good to me, but someone else must approve Jenkins Builder: Verified
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