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
This commit is contained in:
Alexander Couzens 2022-10-10 04:54:49 +02:00 committed by lynxis lazus
parent 55c81a9b61
commit af189fb786
23 changed files with 619 additions and 30 deletions

View File

@ -13,6 +13,7 @@ noinst_HEADERS = \
bss.h \
bts.h \
bts_sm.h \
bts_setup_ramp.h \
bts_trx.h \
bts_ipaccess_nanobts_omlattr.h \
chan_alloc.h \

View File

@ -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 gsm_bts {
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])

View File

@ -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);

View File

@ -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 @@ struct gsm_network {
/* 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;

View File

@ -38,6 +38,7 @@ enum nm_fsm_events {
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 @@ extern struct osmo_fsm nm_gprs_nsvc_fsm;
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);

View File

@ -56,6 +56,7 @@ libbsc_la_SOURCES = \
bts_osmobts.c \
bts_unknown.c \
bts_ctrl.c \
bts_setup_ramp.c \
bts_vty.c \
bts_trx_vty.c \
chan_alloc.c \

View File

@ -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 @@ static int config_write_bsc(struct vty *vty)
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 @@ DEFUN_ATTR(cfg_net_no_rf_off_time,
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 @@ int bsc_vty_init(struct gsm_network *network)
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 @@ int bsc_vty_init(struct gsm_network *network)
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);

View File

@ -145,6 +145,7 @@ static const struct gprs_rlc_cfg rlc_cfg_default = {
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 @@ struct gsm_bts *gsm_bts_alloc(struct gsm_network *net, struct gsm_bts_sm *bts_sm
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);

View File

@ -619,6 +619,8 @@ void ipaccess_drop_oml(struct gsm_bts *bts, const char *reason)
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");

View File

@ -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);
}

View File

@ -4012,6 +4012,8 @@ void bts_dump_vty(struct vty *vty, struct gsm_bts *bts)
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.",

View File

@ -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 @@ struct gsm_network *gsm_network_init(void *ctx)
net->null_nri_ranges = osmo_nri_ranges_alloc(net);
net->nri_bitlen = OSMO_NRI_BITLEN_DEFAULT;
bts_setup_ramp_init_network(net);
return net;
}

View File

@ -76,6 +76,7 @@ static void st_op_disabled_notinstalled(struct osmo_fsm_inst *fi, uint32_t event
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 @@ static void configure_loop(struct gsm_bts_bb_trx *bb_transc, const struct gsm_nm
{
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 @@ static void st_op_disabled_dependency(struct osmo_fsm_inst *fi, uint32_t event,
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 @@ static void st_op_disabled_offline(struct osmo_fsm_inst *fi, uint32_t event, voi
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 @@ static struct osmo_fsm_state nm_bb_transc_fsm_states[] = {
[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 @@ static struct osmo_fsm_state nm_bb_transc_fsm_states[] = {
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 @@ static struct osmo_fsm_state nm_bb_transc_fsm_states[] = {
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) |

View File

@ -63,6 +63,7 @@ static void st_op_disabled_notinstalled(struct osmo_fsm_inst *fi, uint32_t event
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 @@ static void configure_loop(struct gsm_bts *bts, const struct gsm_nm_state *state
{
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 @@ static void st_op_disabled_dependency(struct osmo_fsm_inst *fi, uint32_t event,
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 @@ static void st_op_disabled_offline(struct osmo_fsm_inst *fi, uint32_t event, voi
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 @@ static struct osmo_fsm_state nm_bts_fsm_states[] = {
[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 @@ static struct osmo_fsm_state nm_bts_fsm_states[] = {
.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 @@ static struct osmo_fsm_state nm_bts_fsm_states[] = {
.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) |

View File

@ -61,6 +61,7 @@ static void st_op_disabled_notinstalled(struct osmo_fsm_inst *fi, uint32_t event
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 st_op_disabled_notinstalled(struct osmo_fsm_inst *fi, uint32_t event
}
}
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_dependency(struct osmo_fsm_inst *fi, uint32_t event,
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 @@ static void st_op_disabled_offline(struct osmo_fsm_inst *fi, uint32_t event, voi
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 @@ static struct osmo_fsm_state nm_bts_sm_fsm_states[] = {
[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 @@ static struct osmo_fsm_state nm_bts_sm_fsm_states[] = {
},
[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 @@ static struct osmo_fsm_state nm_bts_sm_fsm_states[] = {
},
[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) |

View File

@ -62,6 +62,7 @@ static void st_op_disabled_notinstalled(struct osmo_fsm_inst *fi, uint32_t event
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 @@ static void configure_loop(struct gsm_bts_trx_ts *ts, const struct gsm_nm_state
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 @@ static void st_op_disabled_dependency(struct osmo_fsm_inst *fi, uint32_t event,
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 @@ static void st_op_disabled_offline(struct osmo_fsm_inst *fi, uint32_t event, voi
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 @@ static struct osmo_fsm_state nm_chan_fsm_states[] = {
[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 @@ static struct osmo_fsm_state nm_chan_fsm_states[] = {
[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 @@ static struct osmo_fsm_state nm_chan_fsm_states[] = {
[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) |

View File

@ -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 @@ void nm_obj_fsm_becomes_enabled_disabled(struct gsm_bts *bts, void *obj,
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);
}

View File

@ -61,6 +61,7 @@ static void st_op_disabled_notinstalled(struct osmo_fsm_inst *fi, uint32_t event
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 @@ static void configure_loop(struct gsm_gprs_cell *cell, const struct gsm_nm_state
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 @@ static void st_op_disabled_dependency(struct osmo_fsm_inst *fi, uint32_t event,
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 @@ static void st_op_disabled_offline(struct osmo_fsm_inst *fi, uint32_t event, voi
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 @@ static struct osmo_fsm_state nm_gprs_cell_fsm_states[] = {
[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 @@ static struct osmo_fsm_state nm_gprs_cell_fsm_states[] = {
[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 @@ static struct osmo_fsm_state nm_gprs_cell_fsm_states[] = {
[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) |

View File

@ -62,6 +62,7 @@ static void st_op_disabled_notinstalled(struct osmo_fsm_inst *fi, uint32_t event
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 @@ static void configure_loop(struct gsm_gprs_nse *nse, const struct gsm_nm_state *
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 @@ static void st_op_disabled_dependency(struct osmo_fsm_inst *fi, uint32_t event,
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 @@ static void st_op_disabled_offline(struct osmo_fsm_inst *fi, uint32_t event, voi
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 @@ static struct osmo_fsm_state nm_gprs_nse_fsm_states[] = {
[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 @@ static struct osmo_fsm_state nm_gprs_nse_fsm_states[] = {
[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 @@ static struct osmo_fsm_state nm_gprs_nse_fsm_states[] = {
[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) |

View File

@ -63,8 +63,8 @@ static void st_op_disabled_notinstalled(struct osmo_fsm_inst *fi, uint32_t event
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 @@ static void configure_loop(struct gsm_gprs_nsvc *nsvc, const struct gsm_nm_state
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 @@ static void st_op_disabled_dependency(struct osmo_fsm_inst *fi, uint32_t event,
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 @@ static void st_op_disabled_offline(struct osmo_fsm_inst *fi, uint32_t event, voi
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 @@ static struct osmo_fsm_state nm_gprs_nsvc_fsm_states[] = {
.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 @@ static struct osmo_fsm_state nm_gprs_nsvc_fsm_states[] = {
.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 @@ static struct osmo_fsm_state nm_gprs_nsvc_fsm_states[] = {
.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) |

View File

@ -71,6 +71,7 @@ static void st_op_disabled_notinstalled(struct osmo_fsm_inst *fi, uint32_t event
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 @@ static void configure_loop(struct gsm_bts_trx *trx, const struct gsm_nm_state *s
{
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 @@ static void st_op_disabled_dependency(struct osmo_fsm_inst *fi, uint32_t event,
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 @@ static void st_op_disabled_offline(struct osmo_fsm_inst *fi, uint32_t event, voi
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 @@ static struct osmo_fsm_state nm_rcarrier_fsm_states[] = {
[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 @@ static struct osmo_fsm_state nm_rcarrier_fsm_states[] = {
[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 @@ static struct osmo_fsm_state nm_rcarrier_fsm_states[] = {
[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) |

View File

@ -401,6 +401,8 @@ static void bootstrap_bts(struct gsm_bts *bts)
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 */

View File

@ -46,6 +46,7 @@ OsmoBSC# bts ?
<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