diff options
-rw-r--r-- | include/osmocom/bsc/acc.h | 91 | ||||
-rw-r--r-- | include/osmocom/bsc/vty.h | 1 | ||||
-rw-r--r-- | src/osmo-bsc/acc.c | 269 | ||||
-rw-r--r-- | src/osmo-bsc/bsc_vty.c | 351 | ||||
-rw-r--r-- | src/osmo-bsc/osmo_bsc_main.c | 9 | ||||
-rw-r--r-- | tests/acc.vty | 159 | ||||
-rw-r--r-- | tests/acc/acc_test.c | 72 |
7 files changed, 744 insertions, 208 deletions
diff --git a/include/osmocom/bsc/acc.h b/include/osmocom/bsc/acc.h index c7be38cb3..b282605cc 100644 --- a/include/osmocom/bsc/acc.h +++ b/include/osmocom/bsc/acc.h @@ -77,14 +77,21 @@ void acc_mgr_apply_acc(struct acc_mgr *acc_mgr, struct gsm48_rach_control *rach_ #define ACC_RAMP_CHAN_LOAD_THRESHOLD_LOW 71 #define ACC_RAMP_CHAN_LOAD_THRESHOLD_UP 89 +#define ACC_RAMP_CPU_LOAD_THRESHOLD_LOW 71 +#define ACC_RAMP_CPU_LOAD_THRESHOLD_UP 89 + /*! * Data structure used to manage ACC ramping. Please avoid setting or reading fields * in this structure directly. Use the accessor functions below instead. */ -struct acc_ramp { - struct gsm_bts *bts; /*!< backpointer to BTS using this ACC ramp */ - - bool acc_ramping_enabled; /*!< whether ACC ramping is enabled */ +struct acc_ramp_thresh_load; +struct acc_ramp_thresh_load_ops { + bool (*can_increase_len_allowed_ramp)(const struct acc_ramp_thresh_load *ld); + bool (*can_decrease_len_allowed_ramp)(const struct acc_ramp_thresh_load *ld); +}; +struct acc_ramp_thresh_load { + struct acc_ramp *acc_ramp; /* backpointer */ + bool enabled; /*!< whether ACC ramping type is enabled */ /*! * This controls the maximum number of ACCs to allow per ramping step (1 - 10). @@ -103,67 +110,99 @@ struct acc_ramp { struct osmo_timer_list step_timer; /*! - * Channel Load Upper/Lower Thresholds: + * Load Upper/Lower Thresholds: * They control how ramping subset size of allowed ACCs changes in - * relation to current channel load (%, 0-100): Under the lower + * relation to current load (%, 0-100): Under the lower * threshold, subset size may be increased; above the upper threshold, * subset size may be decreased. */ - unsigned int chan_load_lower_threshold; - unsigned int chan_load_upper_threshold; + unsigned int lower_threshold; + unsigned int upper_threshold; + struct acc_ramp_thresh_load_ops ops; +}; +struct acc_ramp { + struct gsm_bts *bts; /*!< backpointer to BTS using this ACC ramp */ + + struct acc_ramp_thresh_load chanld; + struct acc_ramp_thresh_load cpuld; }; +/************* + * CHAN LOAD * + *************/ /*! - * Enable or disable ACC ramping. + * Enable or disable ACC ramping based on Chan Load. * When enabled, ramping begins once acc_ramp_start() is called. * When disabled, an ACC ramping process in progress will continue * unless acc_ramp_abort() is called as well. * \param[in] acc_ramp Pointer to acc_ramp structure. */ -static inline void acc_ramp_set_enabled(struct acc_ramp *acc_ramp, bool enable) +static inline void acc_ramp_thld_set_enabled(struct acc_ramp_thresh_load *thld, bool enable) { - acc_ramp->acc_ramping_enabled = enable; + thld->enabled = enable; } /*! - * Return true if ACC ramping is currently enabled, else false. + * Return true if ACC ramping based on Chan Load is currently enabled, else false. * \param[in] acc_ramp Pointer to acc_ramp structure. */ -static inline bool acc_ramp_is_enabled(struct acc_ramp *acc_ramp) +static inline bool acc_ramp_thld_is_enabled(const struct acc_ramp_thresh_load *thld) { - return acc_ramp->acc_ramping_enabled; + return thld->enabled; } /*! - * Return the current ACC ramp step size. + * Return the current Chan Load ACC ramp step size. * \param[in] acc_ramp Pointer to acc_ramp structure. */ -static inline unsigned int acc_ramp_get_step_size(struct acc_ramp *acc_ramp) +static inline unsigned int acc_ramp_thld_get_step_size(const struct acc_ramp_thresh_load *thld) { - return acc_ramp->step_size; + return thld->step_size; } /*! - * Return the current ACC ramp step interval (in seconds) + * Return the current Chan Load ACC ramp step interval (in seconds) * \param[in] acc_ramp Pointer to acc_ramp structure. */ -static inline unsigned int acc_ramp_get_step_interval(struct acc_ramp *acc_ramp) +static inline unsigned int acc_ramp_thld_get_step_interval(const struct acc_ramp_thresh_load *thld) { - return acc_ramp->step_interval_sec; + return thld->step_interval_sec; } /*! - * Return the current ACC ramp step interval (in seconds) + * Return the current Chan Load ACC ramp step interval (in seconds) * \param[in] acc_ramp Pointer to acc_ramp structure. */ -static inline unsigned int acc_ramp_is_running(struct acc_ramp *acc_ramp) +static inline unsigned int acc_ramp_thld_is_running(struct acc_ramp_thresh_load *thld) +{ + return osmo_timer_pending(&thld->step_timer); +} + +int acc_ramp_thld_set_step_size(struct acc_ramp_thresh_load *thld, unsigned int step_size); +int acc_ramp_thld_set_step_interval(struct acc_ramp_thresh_load *thld, unsigned int step_interval); +int acc_ramp_thld_set_thresholds(struct acc_ramp_thresh_load *thld, unsigned int low_threshold, unsigned int up_threshold); + +/************* + * GENERIC * + *************/ + +static inline bool acc_ramp_is_enabled(const struct acc_ramp *acc_ramp) +{ + return acc_ramp_thld_is_enabled(&acc_ramp->chanld) || + acc_ramp_thld_is_enabled(&acc_ramp->cpuld); +} + +static inline bool acc_ramp_can_increase_len_allowed_ramp(const struct acc_ramp *acc_ramp) { - return acc_ramp->step_interval_sec; + if (acc_ramp_thld_is_enabled(&acc_ramp->chanld) && + !acc_ramp->chanld.ops.can_increase_len_allowed_ramp(&acc_ramp->chanld)) + return false; + if (acc_ramp_thld_is_enabled(&acc_ramp->cpuld) && + !acc_ramp->cpuld.ops.can_increase_len_allowed_ramp(&acc_ramp->cpuld)) + return false; + return true; } void acc_ramp_init(struct acc_ramp *acc_ramp, struct gsm_bts *bts); -int acc_ramp_set_step_size(struct acc_ramp *acc_ramp, unsigned int step_size); -int acc_ramp_set_step_interval(struct acc_ramp *acc_ramp, unsigned int step_interval); -int acc_ramp_set_chan_load_thresholds(struct acc_ramp *acc_ramp, unsigned int low_threshold, unsigned int up_threshold); void acc_ramp_trigger(struct acc_ramp *acc_ramp); void acc_ramp_abort(struct acc_ramp *acc_ramp); diff --git a/include/osmocom/bsc/vty.h b/include/osmocom/bsc/vty.h index 92f7932bb..f85b3e8cf 100644 --- a/include/osmocom/bsc/vty.h +++ b/include/osmocom/bsc/vty.h @@ -17,6 +17,7 @@ enum bsc_vty_node { BTS_NODE, TRX_NODE, TS_NODE, + ACC_RAMP_NODE, OML_NODE, NAT_NODE, NAT_BSC_NODE, diff --git a/src/osmo-bsc/acc.c b/src/osmo-bsc/acc.c index 06f96c625..4ebf85cd0 100644 --- a/src/osmo-bsc/acc.c +++ b/src/osmo-bsc/acc.c @@ -372,9 +372,108 @@ void acc_mgr_apply_acc(struct acc_mgr *acc_mgr, struct gsm48_rach_control *rach_ ////////////////////////// // acc_ramp ////////////////////////// + +/*! + * Change the ramping step size which controls how many ACCs will be allowed per ramping step. + * Returns negative on error (step_size out of range), else zero. + * \param[in] acc_ramp Pointer to acc_ramp structure. + * \param[in] step_size The new step size value. + */ +int acc_ramp_thld_set_step_size(struct acc_ramp_thresh_load *thld, unsigned int step_size) +{ + if (step_size < ACC_RAMP_STEP_SIZE_MIN || step_size > ACC_RAMP_STEP_SIZE_MAX) + return -ERANGE; + + thld->step_size = step_size; + LOG_BTS(thld->acc_ramp->bts, DRSL, LOGL_DEBUG, "ACC RAMP: ramping step size set to %u\n", step_size); + return 0; +} + +/*! + * Change the ramping step interval to a fixed value. Unless this function is called, + * the interval is automatically scaled to the BTS channel load average. + * \param[in] acc_ramp Pointer to acc_ramp structure. + * \param[in] step_interval The new fixed step interval in seconds. + */ +int acc_ramp_thld_set_step_interval(struct acc_ramp_thresh_load *thld, unsigned int step_interval) +{ + if (step_interval < ACC_RAMP_STEP_INTERVAL_MIN || step_interval > ACC_RAMP_STEP_INTERVAL_MAX) + return -ERANGE; + + thld->step_interval_sec = step_interval; + LOG_BTS(thld->acc_ramp->bts, DRSL, LOGL_DEBUG, "ACC RAMP: ramping step interval set to %u seconds\n", + step_interval); + return 0; +} + +/*! + * Change the ramping channel load thresholds. They control how ramping subset + * size of allowed ACCs changes in relation to current load (%, 0-100): + * Under the lower threshold, subset size may be increased; above the upper + * threshold, subset size may be decreased. + * \param[in] acc_ramp Pointer to acc_ramp structure. + * \param[in] low_threshold The new minimum threshold: values under it allow for increasing the ramping subset size. + * \param[in] up_threshold The new maximum threshold: values under it allow for increasing the ramping subset size. + */ +int acc_ramp_thld_set_thresholds(struct acc_ramp_thresh_load *thld, unsigned int low_threshold, unsigned int up_threshold) +{ + /* for instance, high=49 and lower=50 makes sense: + [50-100] -> decrease, [0-49] -> increase */ + if ((int)up_threshold - (int)low_threshold < -1) + return -ERANGE; + + thld->lower_threshold = low_threshold; + thld->upper_threshold = up_threshold; + return 0; +} + + +/*! + * Determine whether Chan Load conditions are good enough to allow increasing + * the ramping size of allowed ACCs. + * \param[in] acc_ramp Pointer to acc_ramp structure. + */ +static bool acc_ramp_chanld_can_increase_len_allowed_ramp(const struct acc_ramp_thresh_load *thld) +{ + return thld->acc_ramp->bts->chan_load_avg > thld->upper_threshold; +} + +/*! + * Determine whether Chan Load conditions are bad enough to allow decreasing + * the ramping size of allowed ACCs. + * \param[in] acc_ramp Pointer to acc_ramp structure. + */ +static bool acc_ramp_chanld_can_decrease_len_allowed_ramp(const struct acc_ramp_thresh_load *thld) +{ + return thld->acc_ramp->bts->chan_load_avg < thld->lower_threshold; +} + +/*! + * Determine whether CPU Load conditions are good enough to allow increasing + * the ramping size of allowed ACCs. + * \param[in] acc_ramp Pointer to acc_ramp structure. + */ +static bool acc_ramp_cpuld_can_increase_len_allowed_ramp(const struct acc_ramp_thresh_load *thld) +{ + /* TODO: implement */ + return true; +} + +/*! + * Determine whether CPU Load conditions are bad enough to allow decreasing + * the ramping size of allowed ACCs. + * \param[in] acc_ramp Pointer to acc_ramp structure. + */ +static bool acc_ramp_cpuld_can_decrease_len_allowed_ramp(const struct acc_ramp_thresh_load *thld) +{ + /* TODO: implement */ + return false; +} + static void do_acc_ramping_step(void *data) { - struct acc_ramp *acc_ramp = data; + struct acc_ramp_thresh_load *thld = data; + struct acc_ramp *acc_ramp = thld->acc_ramp; struct gsm_bts *bts = acc_ramp->bts; struct acc_mgr *acc_mgr = &bts->acc_mgr; @@ -385,29 +484,33 @@ static void do_acc_ramping_step(void *data) * least 1 ACC at ramping lvl to allow subscribers to eventually use the * network. If total barring is desired, it can be controlled by the * adminsitrative subset length through VTY. + * * Remark inc: Never try going over the admin subset size, since it * wouldn't change final subset size anyway and it would create a fake * sense of safe load handling capacity. If then load became high, being * on upper size would mean the BTS requires more time to effectively * drop down the final subset size, hence delaying recovery. + * + * Remark general: We must follow all restrictions for all enabled + * ramping methods in order to increase subset size, but lowering is + * enough based on current ramping method stepping. */ - if (bts->chan_load_avg > acc_ramp->chan_load_upper_threshold) - new_len = (uint8_t)OSMO_MAX(1, (int)(old_len - acc_ramp->step_size)); - else if (bts->chan_load_avg < acc_ramp->chan_load_lower_threshold) + if (acc_ramp_can_increase_len_allowed_ramp(acc_ramp)) + new_len = (uint8_t)OSMO_MAX(1, (int)(old_len - thld->step_size)); + else if (thld->ops.can_decrease_len_allowed_ramp(thld)) new_len = OSMO_MIN(acc_mgr_get_len_allowed_adm(acc_mgr), - old_len + acc_ramp->step_size); + old_len + thld->step_size); else new_len = old_len; if (new_len != old_len) { LOG_BTS(bts, DRSL, LOGL_DEBUG, "ACC RAMP: changing ramping subset size %" PRIu8 - " -> %" PRIu8 ", chan_load_avg=%" PRIu8 "%%\n", - old_len, new_len, bts->chan_load_avg); + " -> %" PRIu8 "\n", old_len, new_len); acc_mgr_set_len_allowed_ramp(acc_mgr, new_len); } - osmo_timer_schedule(&acc_ramp->step_timer, acc_ramp->step_interval_sec, 0); + osmo_timer_schedule(&thld->step_timer, thld->step_interval_sec, 0); } /* Implements osmo_signal_cbfn() -- trigger or abort ACC ramping upon changes RF lock state. */ @@ -530,6 +633,30 @@ static int acc_ramp_nm_sig_cb(unsigned int subsys, unsigned int signal, void *ha return 0; } +static struct acc_ramp_thresh_load chanld_defs = { + .enabled = false, + .step_size = ACC_RAMP_STEP_SIZE_DEFAULT, + .step_interval_sec = ACC_RAMP_STEP_INTERVAL_MIN, + .lower_threshold = ACC_RAMP_CHAN_LOAD_THRESHOLD_LOW, + .upper_threshold = ACC_RAMP_CHAN_LOAD_THRESHOLD_UP, + .ops = { + .can_increase_len_allowed_ramp = acc_ramp_chanld_can_increase_len_allowed_ramp, + .can_decrease_len_allowed_ramp = acc_ramp_chanld_can_decrease_len_allowed_ramp, + }, +}; + +static struct acc_ramp_thresh_load cpuld_defs = { + .enabled = false, + .step_size = ACC_RAMP_STEP_SIZE_DEFAULT, + .step_interval_sec = ACC_RAMP_STEP_INTERVAL_MIN, + .lower_threshold = ACC_RAMP_CPU_LOAD_THRESHOLD_LOW, + .upper_threshold = ACC_RAMP_CPU_LOAD_THRESHOLD_UP, + .ops = { + .can_increase_len_allowed_ramp = acc_ramp_cpuld_can_increase_len_allowed_ramp, + .can_decrease_len_allowed_ramp = acc_ramp_cpuld_can_decrease_len_allowed_ramp, + }, +}; + /*! * Initialize an acc_ramp data structure. * Storage for this structure must be provided by the caller. @@ -542,67 +669,16 @@ static int acc_ramp_nm_sig_cb(unsigned int subsys, unsigned int signal, void *ha void acc_ramp_init(struct acc_ramp *acc_ramp, struct gsm_bts *bts) { acc_ramp->bts = bts; - acc_ramp_set_enabled(acc_ramp, false); - acc_ramp->step_size = ACC_RAMP_STEP_SIZE_DEFAULT; - acc_ramp->step_interval_sec = ACC_RAMP_STEP_INTERVAL_MIN; - acc_ramp->chan_load_lower_threshold = ACC_RAMP_CHAN_LOAD_THRESHOLD_LOW; - acc_ramp->chan_load_upper_threshold = ACC_RAMP_CHAN_LOAD_THRESHOLD_UP; - osmo_timer_setup(&acc_ramp->step_timer, do_acc_ramping_step, acc_ramp); - osmo_signal_register_handler(SS_NM, acc_ramp_nm_sig_cb, acc_ramp); -} -/*! - * Change the ramping step size which controls how many ACCs will be allowed per ramping step. - * Returns negative on error (step_size out of range), else zero. - * \param[in] acc_ramp Pointer to acc_ramp structure. - * \param[in] step_size The new step size value. - */ -int acc_ramp_set_step_size(struct acc_ramp *acc_ramp, unsigned int step_size) -{ - if (step_size < ACC_RAMP_STEP_SIZE_MIN || step_size > ACC_RAMP_STEP_SIZE_MAX) - return -ERANGE; + memcpy(&acc_ramp->chanld, &chanld_defs, sizeof(chanld_defs)); + acc_ramp->chanld.acc_ramp = acc_ramp; + osmo_timer_setup(&acc_ramp->chanld.step_timer, do_acc_ramping_step, &acc_ramp->chanld); - acc_ramp->step_size = step_size; - LOG_BTS(acc_ramp->bts, DRSL, LOGL_DEBUG, "ACC RAMP: ramping step size set to %u\n", step_size); - return 0; -} + memcpy(&acc_ramp->cpuld, &cpuld_defs, sizeof(cpuld_defs)); + acc_ramp->cpuld.acc_ramp = acc_ramp; + osmo_timer_setup(&acc_ramp->cpuld.step_timer, do_acc_ramping_step, &acc_ramp->cpuld); -/*! - * Change the ramping step interval to a fixed value. Unless this function is called, - * the interval is automatically scaled to the BTS channel load average. - * \param[in] acc_ramp Pointer to acc_ramp structure. - * \param[in] step_interval The new fixed step interval in seconds. - */ -int acc_ramp_set_step_interval(struct acc_ramp *acc_ramp, unsigned int step_interval) -{ - if (step_interval < ACC_RAMP_STEP_INTERVAL_MIN || step_interval > ACC_RAMP_STEP_INTERVAL_MAX) - return -ERANGE; - - acc_ramp->step_interval_sec = step_interval; - LOG_BTS(acc_ramp->bts, DRSL, LOGL_DEBUG, "ACC RAMP: ramping step interval set to %u seconds\n", - step_interval); - return 0; -} - -/*! - * Change the ramping channel load thresholds. They control how ramping subset - * size of allowed ACCs changes in relation to current channel load (%, 0-100): - * Under the lower threshold, subset size may be increased; above the upper - * threshold, subset size may be decreased. - * \param[in] acc_ramp Pointer to acc_ramp structure. - * \param[in] low_threshold The new minimum threshold: values under it allow for increasing the ramping subset size. - * \param[in] up_threshold The new maximum threshold: values under it allow for increasing the ramping subset size. - */ -int acc_ramp_set_chan_load_thresholds(struct acc_ramp *acc_ramp, unsigned int low_threshold, unsigned int up_threshold) -{ - /* for instance, high=49 and lower=50 makes sense: - [50-100] -> decrease, [0-49] -> increase */ - if ((int)up_threshold - (int)low_threshold < -1) - return -ERANGE; - - acc_ramp->chan_load_lower_threshold = low_threshold; - acc_ramp->chan_load_upper_threshold = up_threshold; - return 0; + osmo_signal_register_handler(SS_NM, acc_ramp_nm_sig_cb, acc_ramp); } /*! @@ -616,19 +692,49 @@ int acc_ramp_set_chan_load_thresholds(struct acc_ramp *acc_ramp, unsigned int lo void acc_ramp_trigger(struct acc_ramp *acc_ramp) { if (acc_ramp_is_enabled(acc_ramp)) { - if (osmo_timer_pending(&acc_ramp->step_timer)) - return; /* Already started, nothing to do */ - - /* Set all available ACCs to barred and start ramping up. */ - acc_mgr_set_len_allowed_ramp(&acc_ramp->bts->acc_mgr, 0); - if (acc_ramp->chan_load_lower_threshold == 0 && - acc_ramp->chan_load_upper_threshold == 100) { - LOG_BTS(acc_ramp->bts, DRSL, LOGL_ERROR, - "ACC RAMP: starting ramp up with 0 ACCs and " - "no possibility to grow the allowed subset size! " - "Check VTY cmd access-control-class-ramping-chan-load\n"); + /* Some method is enabled, check what changed and whether we need to start/stop them */ + + if (!acc_ramp_thld_is_running(&acc_ramp->chanld) && + !acc_ramp_thld_is_running(&acc_ramp->cpuld)) { + /* Set all available ACCs to barred and start ramping up some blocks below. */ + acc_mgr_set_len_allowed_ramp(&acc_ramp->bts->acc_mgr, 0); + } + /* 2 conditons below: Check if some previously enabled method + * has become disabled, but we know at least one stays enabled, + * so no need to touch current len_allowed_ramp, it will keep + * being controlled by the method still enabled: */ + if (!acc_ramp_thld_is_enabled(&acc_ramp->chanld) && + acc_ramp_thld_is_running(&acc_ramp->chanld)) { + osmo_timer_del(&acc_ramp->chanld.step_timer); + } + if (!acc_ramp_thld_is_enabled(&acc_ramp->cpuld) && + acc_ramp_thld_is_running(&acc_ramp->cpuld)) { + osmo_timer_del(&acc_ramp->cpuld.step_timer); + } + + /* Start enabled threshold load methods which were not yet started */ + if (acc_ramp_thld_is_enabled(&acc_ramp->chanld) && + !acc_ramp_thld_is_running(&acc_ramp->chanld)) { + if (acc_ramp->chanld.lower_threshold == 0 && + acc_ramp->chanld.upper_threshold == 100) { + LOG_BTS(acc_ramp->bts, DRSL, LOGL_ERROR, + "ACC RAMP: starting ramp up with 0 ACCs and " + "no possibility to grow the allowed subset size! " + "Check VTY cmd access-control-class-ramping-chan-load\n"); + } + do_acc_ramping_step(&acc_ramp->chanld); + } + if (acc_ramp_thld_is_enabled(&acc_ramp->cpuld) && + !acc_ramp_thld_is_running(&acc_ramp->cpuld)) { + if (acc_ramp->cpuld.lower_threshold == 0 && + acc_ramp->cpuld.upper_threshold == 100) { + LOG_BTS(acc_ramp->bts, DRSL, LOGL_ERROR, + "ACC RAMP: starting ramp up with 0 ACCs and " + "no possibility to grow the allowed subset size! " + "Check VTY cmd access-control-class-ramping-chan-load\n"); + } + do_acc_ramping_step(&acc_ramp->cpuld); } - do_acc_ramping_step(acc_ramp); } else { /* Abort any previously running ramping process and allow all available ACCs. */ acc_ramp_abort(acc_ramp); @@ -641,8 +747,11 @@ void acc_ramp_trigger(struct acc_ramp *acc_ramp) */ void acc_ramp_abort(struct acc_ramp *acc_ramp) { - if (osmo_timer_pending(&acc_ramp->step_timer)) - osmo_timer_del(&acc_ramp->step_timer); + if (osmo_timer_pending(&acc_ramp->chanld.step_timer)) + osmo_timer_del(&acc_ramp->chanld.step_timer); + + if (osmo_timer_pending(&acc_ramp->cpuld.step_timer)) + osmo_timer_del(&acc_ramp->cpuld.step_timer); acc_mgr_set_len_allowed_ramp(&acc_ramp->bts->acc_mgr, 10); } diff --git a/src/osmo-bsc/bsc_vty.c b/src/osmo-bsc/bsc_vty.c index 3c60f5f42..a7149e5d7 100644 --- a/src/osmo-bsc/bsc_vty.c +++ b/src/osmo-bsc/bsc_vty.c @@ -172,6 +172,12 @@ static struct cmd_node ts_node = { 1, }; +static struct cmd_node acc_ramp_node = { + ACC_RAMP_NODE, + "%s(config-net-bts-acc-ramp)# ", + 1, +}; + static struct gsm_network *vty_global_gsm_network = NULL; struct gsm_network *gsmnet_from_vty(struct vty *v) @@ -359,6 +365,34 @@ static void bts_dump_vty_features(struct vty *vty, struct gsm_bts *bts) vty_out(vty, " (not available)%s", VTY_NEWLINE); } +static void bts_dump_vty_acc_ramp(struct vty *vty, struct gsm_bts *bts) +{ + const struct acc_ramp_thresh_load *methods[] = {&bts->acc_ramp.chanld, + &bts->acc_ramp.cpuld}; + const char *method_names[] = {"Channel Load", "CPU Load"}; + const struct acc_ramp_thresh_load *m; + const char *name; + int i; + + for (i = 0; i < ARRAY_SIZE(methods); i++) { + m = methods[i]; + name = method_names[i]; + vty_out(vty, " Access Control Class ramping (%s): %senabled%s", name, + acc_ramp_thld_is_enabled(m) ? "" : "not ", VTY_NEWLINE); + if (acc_ramp_thld_is_enabled(m)) { + vty_out(vty, " Access Control Class ramping (%s) step interval: %u seconds%s", + name, acc_ramp_thld_get_step_interval(m), VTY_NEWLINE); + vty_out(vty, " Access Control Class (%s) thresholds: (%" PRIu8 ", %" PRIu8 ")%s", + name, bts->acc_ramp.chanld.lower_threshold, + bts->acc_ramp.chanld.upper_threshold, VTY_NEWLINE); + vty_out(vty, " enabling %u Access Control Class%s per %s ramping step%s", + acc_ramp_thld_get_step_size(m), + acc_ramp_thld_get_step_size(m) > 1 ? "es" : "", + name, VTY_NEWLINE); + } + } +} + static void bts_dump_vty(struct vty *vty, struct gsm_bts *bts) { struct pchan_load pl; @@ -417,18 +451,7 @@ static void bts_dump_vty(struct vty *vty, struct gsm_bts *bts) bts->si_common.cell_sel_par.cell_resel_hyst*2, VTY_NEWLINE); vty_out(vty, " Access Control Class rotation allow mask: 0x%" PRIx16 "%s", bts->acc_mgr.allowed_subset_mask, VTY_NEWLINE); - vty_out(vty, " Access Control Class ramping: %senabled%s", - acc_ramp_is_enabled(&bts->acc_ramp) ? "" : "not ", VTY_NEWLINE); - if (acc_ramp_is_enabled(&bts->acc_ramp)) { - vty_out(vty, " Access Control Class ramping step interval: %u seconds%s", - acc_ramp_get_step_interval(&bts->acc_ramp), VTY_NEWLINE); - vty_out(vty, " Access Control Class channel load thresholds: (%" PRIu8 ", %" PRIu8 ")%s", - bts->acc_ramp.chan_load_lower_threshold, - bts->acc_ramp.chan_load_upper_threshold, VTY_NEWLINE); - vty_out(vty, " enabling %u Access Control Class%s per ramping step%s", - acc_ramp_get_step_size(&bts->acc_ramp), - acc_ramp_get_step_size(&bts->acc_ramp) > 1 ? "es" : "", VTY_NEWLINE); - } + bts_dump_vty_acc_ramp(vty, bts); vty_out(vty, " RACH TX-Integer: %u%s", bts->si_common.rach_control.tx_integer, VTY_NEWLINE); vty_out(vty, " RACH Max transmissions: %u%s", @@ -974,6 +997,33 @@ static void config_write_power_ctrl(struct vty *vty, unsigned int indent, #undef cfg_out +static void config_write_bts_acc_ramp(struct vty *vty, struct acc_ramp *acc_ramp, const char* prefix) +{ + vty_out(vty, "%saccess-control-class-ramp%s", prefix, VTY_NEWLINE); + + vty_out(vty, "%s %schan-load-enabled%s", prefix, + acc_ramp_thld_is_enabled(&acc_ramp->chanld) ? "" : "no ", VTY_NEWLINE); + if (acc_ramp_thld_is_enabled(&acc_ramp->chanld)) { + vty_out(vty, "%s chan-load-step-interval %u%s", prefix, + acc_ramp_thld_get_step_interval(&acc_ramp->chanld), VTY_NEWLINE); + vty_out(vty, "%s chan-load-step-size %u%s", prefix, + acc_ramp_thld_get_step_size(&acc_ramp->chanld), VTY_NEWLINE); + vty_out(vty, "%s chan-load-thresholds %u %u%s", prefix, + acc_ramp->chanld.lower_threshold, acc_ramp->chanld.upper_threshold, VTY_NEWLINE); + } + + vty_out(vty, "%s %scpu-load-enabled%s", prefix, + acc_ramp_thld_is_enabled(&acc_ramp->cpuld) ? "" : "no ", VTY_NEWLINE); + if (acc_ramp_thld_is_enabled(&acc_ramp->cpuld)) { + vty_out(vty, "%s cpu-load-step-interval %u%s", prefix, + acc_ramp_thld_get_step_interval(&acc_ramp->cpuld), VTY_NEWLINE); + vty_out(vty, "%s cpu-load-step-size %u%s", prefix, + acc_ramp_thld_get_step_size(&acc_ramp->cpuld), VTY_NEWLINE); + vty_out(vty, "%s cpu-load-thresholds %u %u%s", prefix, + acc_ramp->cpuld.lower_threshold, acc_ramp->cpuld.upper_threshold, VTY_NEWLINE); + } +} + static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts) { int i; @@ -1073,15 +1123,7 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts) vty_out(vty, " access-control-class-rotate %" PRIu8 "%s", bts->acc_mgr.len_allowed_adm, VTY_NEWLINE); if (bts->acc_mgr.rotation_time_sec != ACC_MGR_QUANTUM_DEFAULT) vty_out(vty, " access-control-class-rotate-quantum %" PRIu32 "%s", bts->acc_mgr.rotation_time_sec, VTY_NEWLINE); - vty_out(vty, " %saccess-control-class-ramping%s", acc_ramp_is_enabled(&bts->acc_ramp) ? "" : "no ", VTY_NEWLINE); - if (acc_ramp_is_enabled(&bts->acc_ramp)) { - vty_out(vty, " access-control-class-ramping-step-interval %u%s", - acc_ramp_get_step_interval(&bts->acc_ramp), VTY_NEWLINE); - vty_out(vty, " access-control-class-ramping-step-size %u%s", acc_ramp_get_step_size(&bts->acc_ramp), - VTY_NEWLINE); - vty_out(vty, " access-control-class-ramping-chan-load %u %u%s", - bts->acc_ramp.chan_load_lower_threshold, bts->acc_ramp.chan_load_upper_threshold, VTY_NEWLINE); - } + config_write_bts_acc_ramp(vty, &bts->acc_ramp, " "); if (!bts->si_unused_send_empty) vty_out(vty, " no system-information unused-send-empty%s", VTY_NEWLINE); for (i = SYSINFO_TYPE_1; i < _MAX_SYSINFO_TYPE; i++) { @@ -4109,21 +4151,31 @@ DEFUN_ATTR(cfg_bts_acc_rotate_quantum, return CMD_SUCCESS; } -DEFUN_ATTR(cfg_bts_acc_ramping, - cfg_bts_acc_ramping_cmd, - "access-control-class-ramping", - "Enable Access Control Class ramping\n", +/* per BTS configuration of ACC ramping */ +DEFUN_ATTR(cfg_acc_ramp, + cfg_acc_ramp_cmd, + "access-control-class-ramp", + "Configure Access Control Ramping for current BTS\n", CMD_ATTR_IMMEDIATE) { struct gsm_bts *bts = vty->index; + + vty->index = &bts->acc_ramp; + vty->node = ACC_RAMP_NODE; + + return CMD_SUCCESS; +} + +static int _vty_acc_ramp_thld_enable(struct acc_ramp_thresh_load *thld) +{ struct gsm_bts_trx *trx; - if (!acc_ramp_is_enabled(&bts->acc_ramp)) { - acc_ramp_set_enabled(&bts->acc_ramp, true); + if (!acc_ramp_thld_is_enabled(thld)) { + acc_ramp_thld_set_enabled(thld, true); /* Start ramping if at least one TRX is usable */ - llist_for_each_entry(trx, &bts->trx_list, list) { + llist_for_each_entry(trx, &thld->acc_ramp->bts->trx_list, list) { if (trx_is_usable(trx)) { - acc_ramp_trigger(&bts->acc_ramp); + acc_ramp_trigger(thld->acc_ramp); break; } } @@ -4135,29 +4187,132 @@ DEFUN_ATTR(cfg_bts_acc_ramping, */ return CMD_SUCCESS; } +DEFUN_ATTR(cfg_acc_ramp_chanld_enable, + cfg_acc_ramp_chanld_enable_cmd, + "chan-load-enabled", + "Enable Access Control Class ramping based on Channel Load\n", + CMD_ATTR_IMMEDIATE) +{ + struct acc_ramp *acc_ramp = vty->index; + return _vty_acc_ramp_thld_enable(&acc_ramp->chanld); +} +DEFUN_ATTR(cfg_acc_ramp_cpuld_enable, + cfg_acc_ramp_cpuld_enable_cmd, + "cpu-load-enabled", + "Enable Access Control Class ramping based on CPU Load\n", + CMD_ATTR_IMMEDIATE) +{ + struct acc_ramp *acc_ramp = vty->index; + return _vty_acc_ramp_thld_enable(&acc_ramp->cpuld); +} +DEFUN_ATTR(cfg_bts_acc_ramping, + cfg_bts_acc_ramping_cmd, + "access-control-class-ramping", + "Enable Access Control Class ramping\n", + CMD_ATTR_IMMEDIATE | CMD_ATTR_DEPRECATED) +{ + struct gsm_bts *bts = vty->index; + vty_out(vty, "%% 'bts' / 'access-control-class-ramping' config is deprecated, " + "use 'bts' / 'access-control-class-ramp' / 'chan-load-enabled' instead%s", + VTY_NEWLINE); + return _vty_acc_ramp_thld_enable(&bts->acc_ramp.chanld); +} + + +static int _vty_acc_ramp_thld_disable(struct vty *vty, struct acc_ramp_thresh_load *thld) +{ + struct gsm_bts_trx *trx; + + if (acc_ramp_thld_is_enabled(thld)) { + acc_ramp_thld_set_enabled(thld, false); + /* Stop ramping if at least one TRX is usable (otherwise it + * should already be stopped) */ + llist_for_each_entry(trx, &thld->acc_ramp->bts->trx_list, list) { + if (trx_is_usable(trx)) { + acc_ramp_trigger(thld->acc_ramp); + break; + } + } + //if (gsm_bts_set_system_infos(acc_ramp->bts) != 0) { + // vty_out(vty, "%% Failed to (re)generate System Information " + // "messages, check the logs%s", VTY_NEWLINE); + // return CMD_WARNING; + //} + } + return CMD_SUCCESS; +} +DEFUN_ATTR(cfg_acc_ramp_chanld_no_enable, + cfg_acc_ramp_chanld_no_enable_cmd, + "no chan-load-enabled", + NO_STR + "Enable Access Control Class ramping based on Channel Load\n", + CMD_ATTR_IMMEDIATE) +{ + struct acc_ramp *acc_ramp = vty->index; + return _vty_acc_ramp_thld_disable(vty, &acc_ramp->chanld); +} +DEFUN_ATTR(cfg_acc_ramp_cpuld_no_enable, + cfg_acc_ramp_cpuld_no_enable_cmd, + "no cpu-load-enabled", + NO_STR + "Enable Access Control Class ramping based on CPU Load\n", + CMD_ATTR_IMMEDIATE) +{ + struct acc_ramp *acc_ramp = vty->index; + return _vty_acc_ramp_thld_disable(vty, &acc_ramp->cpuld); +} DEFUN_ATTR(cfg_bts_no_acc_ramping, cfg_bts_no_acc_ramping_cmd, "no access-control-class-ramping", NO_STR "Disable Access Control Class ramping\n", - CMD_ATTR_IMMEDIATE) + CMD_ATTR_IMMEDIATE | CMD_ATTR_DEPRECATED) { struct gsm_bts *bts = vty->index; + vty_out(vty, "%% 'bts' / 'no access-control-class-ramping' config is deprecated, " + "use 'bts' / 'access-control-class-ramp' / 'no chan-load-enabled' instead%s", + VTY_NEWLINE); + return _vty_acc_ramp_thld_disable(vty, &bts->acc_ramp.chanld); +} - if (acc_ramp_is_enabled(&bts->acc_ramp)) { - acc_ramp_abort(&bts->acc_ramp); - acc_ramp_set_enabled(&bts->acc_ramp, false); - if (gsm_bts_set_system_infos(bts) != 0) { - vty_out(vty, "%% Filed to (re)generate System Information " - "messages, check the logs%s", VTY_NEWLINE); - return CMD_WARNING; - } +static int _vty_acc_ramp_thld_step_interval(struct vty *vty, struct acc_ramp_thresh_load *thld, unsigned int step_interval) +{ + int error = acc_ramp_thld_set_step_interval(thld, step_interval); + if (error != 0) { + if (error == -ERANGE) + vty_out(vty, "%% Unable to set ACC ramp step interval: value out of range%s", VTY_NEWLINE); + else + vty_out(vty, "%% Unable to set ACC ramp step interval: unknown error%s", VTY_NEWLINE); + return CMD_WARNING; } return CMD_SUCCESS; } - +DEFUN_ATTR(cfg_acc_ramp_chanld_step_interval, + cfg_acc_ramp_chanld_step_interval_cmd, + "chan-load-step-interval (<" + OSMO_STRINGIFY_VAL(ACC_RAMP_STEP_INTERVAL_MIN) "-" + OSMO_STRINGIFY_VAL(ACC_RAMP_STEP_INTERVAL_MAX) ">)", + "Configure Access Control Class ramping step interval (Chan Load based)\n" + "Set a fixed step interval (in seconds)\n", + CMD_ATTR_IMMEDIATE) +{ + struct acc_ramp *acc_ramp = vty->index; + return _vty_acc_ramp_thld_step_interval(vty, &acc_ramp->chanld, atoi(argv[0])); +} +DEFUN_ATTR(cfg_acc_ramp_cpuld_step_interval, + cfg_acc_ramp_cpuld_step_interval_cmd, + "cpu-load-step-interval (<" + OSMO_STRINGIFY_VAL(ACC_RAMP_STEP_INTERVAL_MIN) "-" + OSMO_STRINGIFY_VAL(ACC_RAMP_STEP_INTERVAL_MAX) ">)", + "Configure Access Control Class ramping step interval (CPU Load based)\n" + "Set a fixed step interval (in seconds)\n", + CMD_ATTR_IMMEDIATE) +{ + struct acc_ramp *acc_ramp = vty->index; + return _vty_acc_ramp_thld_step_interval(vty, &acc_ramp->cpuld, atoi(argv[0])); +} DEFUN_ATTR(cfg_bts_acc_ramping_step_interval, cfg_bts_acc_ramping_step_interval_cmd, "access-control-class-ramping-step-interval (<" @@ -4166,29 +4321,59 @@ DEFUN_ATTR(cfg_bts_acc_ramping_step_interval, "Configure Access Control Class ramping step interval\n" "Set a fixed step interval (in seconds)\n" "Use dynamic step interval based on BTS channel load (deprecated, don't use, ignored)\n", - CMD_ATTR_IMMEDIATE) + CMD_ATTR_IMMEDIATE | CMD_ATTR_DEPRECATED) { struct gsm_bts *bts = vty->index; bool dynamic = (strcmp(argv[0], "dynamic") == 0); - int error; - + vty_out(vty, "%% 'bts' / 'access-control-class-ramping-step-interval' config is deprecated, " + "use 'bts' / 'access-control-class-ramp' / 'chan-load-step-interval' instead%s", + VTY_NEWLINE); if (dynamic) { vty_out(vty, "%% access-control-class-ramping-step-interval 'dynamic' value is deprecated, ignoring it%s", VTY_NEWLINE); return CMD_SUCCESS; } + return _vty_acc_ramp_thld_step_interval(vty, &bts->acc_ramp.chanld, atoi(argv[0])); +} - error = acc_ramp_set_step_interval(&bts->acc_ramp, atoi(argv[0])); + +static int _vty_acc_ramp_thld_step_size(struct vty *vty, struct acc_ramp_thresh_load *thld, unsigned int step_size) +{ + int error; + error = acc_ramp_thld_set_step_size(thld, step_size); if (error != 0) { if (error == -ERANGE) - vty_out(vty, "%% Unable to set ACC ramp step interval: value out of range%s", VTY_NEWLINE); + vty_out(vty, "%% Unable to set ACC ramp step size: value out of range%s", VTY_NEWLINE); else - vty_out(vty, "%% Unable to set ACC ramp step interval: unknown error%s", VTY_NEWLINE); + vty_out(vty, "%% Unable to set ACC ramp step size: unknown error%s", VTY_NEWLINE); return CMD_WARNING; } return CMD_SUCCESS; } - +DEFUN_ATTR(cfg_acc_ramp_chanld_step_size, + cfg_acc_ramp_chanld_step_size_cmd, + "chan-load-step-size (<" + OSMO_STRINGIFY_VAL(ACC_RAMP_STEP_SIZE_MIN) "-" + OSMO_STRINGIFY_VAL(ACC_RAMP_STEP_SIZE_MAX) ">)", + "Configure Access Control Class ramping step size (Chan Load based)\n" + "Set the number of Access Control Classes to enable per ramping step\n", + CMD_ATTR_IMMEDIATE) +{ + struct acc_ramp *acc_ramp = vty->index; + return _vty_acc_ramp_thld_step_size(vty, &acc_ramp->chanld, atoi(argv[0])); +} +DEFUN_ATTR(cfg_acc_ramp_cpuld_step_size, + cfg_acc_ramp_cpuld_step_size_cmd, + "cpu-load-step-size (<" + OSMO_STRINGIFY_VAL(ACC_RAMP_STEP_SIZE_MIN) "-" + OSMO_STRINGIFY_VAL(ACC_RAMP_STEP_SIZE_MAX) ">)", + "Configure Access Control Class ramping step size (CPU Load based)\n" + "Set the number of Access Control Classes to enable per ramping step\n", + CMD_ATTR_IMMEDIATE) +{ + struct acc_ramp *acc_ramp = vty->index; + return _vty_acc_ramp_thld_step_size(vty, &acc_ramp->cpuld, atoi(argv[0])); +} DEFUN_ATTR(cfg_bts_acc_ramping_step_size, cfg_bts_acc_ramping_step_size_cmd, "access-control-class-ramping-step-size (<" @@ -4196,41 +4381,62 @@ DEFUN_ATTR(cfg_bts_acc_ramping_step_size, OSMO_STRINGIFY_VAL(ACC_RAMP_STEP_SIZE_MAX) ">)", "Configure Access Control Class ramping step size\n" "Set the number of Access Control Classes to enable per ramping step\n", - CMD_ATTR_IMMEDIATE) + CMD_ATTR_IMMEDIATE | CMD_ATTR_DEPRECATED) { struct gsm_bts *bts = vty->index; - int error; + vty_out(vty, "%% 'bts' / 'access-control-class-ramping-step-size' config is deprecated, " + "use 'bts' / 'access-control-class-ramp' / 'step-size' instead%s", + VTY_NEWLINE); + return _vty_acc_ramp_thld_step_size(vty, &bts->acc_ramp.chanld, atoi(argv[0])); +} - error = acc_ramp_set_step_size(&bts->acc_ramp, atoi(argv[0])); - if (error != 0) { - if (error == -ERANGE) - vty_out(vty, "%% Unable to set ACC ramp step size: value out of range%s", VTY_NEWLINE); - else - vty_out(vty, "%% Unable to set ACC ramp step size: unknown error%s", VTY_NEWLINE); + +static int _vty_acc_ramp_thld_thresholds(struct vty *vty, struct acc_ramp_thresh_load *thld, + unsigned int low_threshold, unsigned int up_threshold) +{ + int rc; + rc = acc_ramp_thld_set_thresholds(thld, low_threshold, up_threshold); + if (rc < 0) { + vty_out(vty, "%% Unable to set ACC channel load thresholds%s", VTY_NEWLINE); return CMD_WARNING; } - return CMD_SUCCESS; } - +DEFUN_ATTR(cfg_acc_ramp_chanld_thresholds, + cfg_acc_ramp_chanld_thresholds_cmd, + "chan-load-thresholds <0-100> <0-100>", + "Configure Access Control Class ramping channel load thresholds\n" + "Lower Channel load threshold (%) below which subset size of allowed broadcast ACCs can be increased\n" + "Upper channel load threshold (%) above which subset size of allowed broadcast ACCs can be decreased\n", + CMD_ATTR_IMMEDIATE) +{ + struct acc_ramp *acc_ramp = vty->index; + return _vty_acc_ramp_thld_thresholds(vty, &acc_ramp->chanld, atoi(argv[0]), atoi(argv[1])); +} +DEFUN_ATTR(cfg_acc_ramp_cpuld_thresholds, + cfg_acc_ramp_cpuld_thresholds_cmd, + "cpu-load-thresholds <0-100> <0-100>", + "Configure Access Control Class ramping CPU load thresholds\n" + "Lower CPU load threshold (%) below which subset size of allowed broadcast ACCs can be increased\n" + "Upper CPU load threshold (%) above which subset size of allowed broadcast ACCs can be decreased\n", + CMD_ATTR_IMMEDIATE) +{ + struct acc_ramp *acc_ramp = vty->index; + return _vty_acc_ramp_thld_thresholds(vty, &acc_ramp->cpuld, atoi(argv[0]), atoi(argv[1])); +} DEFUN_ATTR(cfg_bts_acc_ramping_chan_load, cfg_bts_acc_ramping_chan_load_cmd, "access-control-class-ramping-chan-load <0-100> <0-100>", "Configure Access Control Class ramping channel load thresholds\n" "Lower Channel load threshold (%) below which subset size of allowed broadcast ACCs can be increased\n" "Upper channel load threshold (%) above which subset size of allowed broadcast ACCs can be decreased\n", - CMD_ATTR_IMMEDIATE) + CMD_ATTR_IMMEDIATE | CMD_ATTR_DEPRECATED) { struct gsm_bts *bts = vty->index; - int rc; - - rc = acc_ramp_set_chan_load_thresholds(&bts->acc_ramp, atoi(argv[0]), atoi(argv[1])); - if (rc < 0) { - vty_out(vty, "%% Unable to set ACC channel load thresholds%s", VTY_NEWLINE); - return CMD_WARNING; - } - - return CMD_SUCCESS; + vty_out(vty, "%% 'bts' / 'access-control-class-ramping-chan-load' config is deprecated, " + "use 'bts' / 'access-control-class-ramp' / 'chan-load-thresholds' instead%s", + VTY_NEWLINE); + return _vty_acc_ramp_thld_thresholds(vty, &bts->acc_ramp.chanld, atoi(argv[0]), atoi(argv[1])); } #define EXCL_RFLOCK_STR "Exclude this BTS from the global RF Lock\n" @@ -7838,6 +8044,19 @@ int bsc_vty_init(struct gsm_network *network) neighbor_ident_vty_init(); /* See also handover commands added on bts level from handover_vty.c */ + install_element(BTS_NODE, &cfg_acc_ramp_cmd); + install_node(&acc_ramp_node, dummy_config_write); + install_element(ACC_RAMP_NODE, &cfg_acc_ramp_chanld_enable_cmd); + install_element(ACC_RAMP_NODE, &cfg_acc_ramp_chanld_no_enable_cmd); + install_element(ACC_RAMP_NODE, &cfg_acc_ramp_chanld_step_interval_cmd); + install_element(ACC_RAMP_NODE, &cfg_acc_ramp_chanld_step_size_cmd); + install_element(ACC_RAMP_NODE, &cfg_acc_ramp_chanld_thresholds_cmd); + install_element(ACC_RAMP_NODE, &cfg_acc_ramp_cpuld_enable_cmd); + install_element(ACC_RAMP_NODE, &cfg_acc_ramp_cpuld_no_enable_cmd); + install_element(ACC_RAMP_NODE, &cfg_acc_ramp_cpuld_step_interval_cmd); + install_element(ACC_RAMP_NODE, &cfg_acc_ramp_cpuld_step_size_cmd); + install_element(ACC_RAMP_NODE, &cfg_acc_ramp_cpuld_thresholds_cmd); + install_element(BTS_NODE, &cfg_bts_power_ctrl_cmd); install_element(BTS_NODE, &cfg_bts_no_power_ctrl_cmd); install_node(&power_ctrl_node, dummy_config_write); diff --git a/src/osmo-bsc/osmo_bsc_main.c b/src/osmo-bsc/osmo_bsc_main.c index 3069cc02f..5e08e2ea2 100644 --- a/src/osmo-bsc/osmo_bsc_main.c +++ b/src/osmo-bsc/osmo_bsc_main.c @@ -609,6 +609,15 @@ static int bsc_vty_go_parent(struct vty *vty) vty->index = ts->trx; } break; + case ACC_RAMP_NODE: + vty->node = BTS_NODE; + { + /* set vty->index correctly ! */ + struct acc_ramp *acc_ramp = vty->index; + vty->index = acc_ramp->bts; + vty->index_sub = &acc_ramp->bts->description; + } + break; case OML_NODE: case OM2K_NODE: vty->node = ENABLE_NODE; diff --git a/tests/acc.vty b/tests/acc.vty new file mode 100644 index 000000000..586f81e73 --- /dev/null +++ b/tests/acc.vty @@ -0,0 +1,159 @@ +OsmoBSC> enable + +OsmoBSC# ### Default configuration +OsmoBSC# show running-config +... + access-control-class-ramp + no chan-load-enabled + no cpu-load-enabled +... + +OsmoBSC# ### Check that 'access-control-class-ramp' node and its commands exist +OsmoBSC# configure terminal +OsmoBSC(config)# network +OsmoBSC(config-net)# bts 0 +OsmoBSC(config-net-bts)# list with-flags +... + ! ... access-control-class-ramp +... + +OsmoBSC(config-net-bts)# ### Check that legacy deprecated cmds still work +OsmoBSC(config-net-bts)# access-control-class-ramping +% 'bts' / 'access-control-class-ramping' config is deprecated, use 'bts' / 'access-control-class-ramp' / 'chan-load-enabled' instead +OsmoBSC(config-net-bts)# show running-config +... + access-control-class-ramp + chan-load-enabled + chan-load-step-interval 5 + chan-load-step-size 1 + chan-load-thresholds 71 89 + no cpu-load-enabled +... +OsmoBSC(config-net-bts)# access-control-class-ramping-step-interval 10 +% 'bts' / 'access-control-class-ramping-step-interval' config is deprecated, use 'bts' / 'access-control-class-ramp' / 'chan-load-step-interval' instead +OsmoBSC(config-net-bts)# access-control-class-ramping-step-size 2 +% 'bts' / 'access-control-class-ramping-step-size' config is deprecated, use 'bts' / 'access-control-class-ramp' / 'step-size' instead +OsmoBSC(config-net-bts)# access-control-class-ramping-chan-load 80 90 +% 'bts' / 'access-control-class-ramping-chan-load' config is deprecated, use 'bts' / 'access-control-class-ramp' / 'chan-load-thresholds' instead +OsmoBSC(config-net-bts)# show running-config +... + access-control-class-ramp + chan-load-enabled + chan-load-step-interval 10 + chan-load-step-size 2 + chan-load-thresholds 80 90 + no cpu-load-enabled +... +OsmoBSC(config-net-bts)# no access-control-class-ramping +% 'bts' / 'no access-control-class-ramping' config is deprecated, use 'bts' / 'access-control-class-ramp' / 'no chan-load-enabled' instead +OsmoBSC(config-net-bts)# show running-config +... + access-control-class-ramp + no chan-load-enabled + no cpu-load-enabled +... + +OsmoBSC(config-net-bts)# ### Now test new cmd set +OsmoBSC(config-net-bts)# access-control-class-ramp +OsmoBSC(config-net-bts-acc-ramp)# list with-flags +... + ! chan-load-enabled + ! no chan-load-enabled + ! chan-load-step-interval (<5-600>) + ! chan-load-step-size (<1-10>) + ! chan-load-thresholds <0-100> <0-100> + ! cpu-load-enabled + ! no cpu-load-enabled + ! cpu-load-step-interval (<5-600>) + ! cpu-load-step-size (<1-10>) + ! cpu-load-thresholds <0-100> <0-100> +... +OsmoBSC(config-net-bts-acc-ramp)# no chan-load-enabled +OsmoBSC(config-net-bts-acc-ramp)# chan-load-enabled +OsmoBSC(config-net-bts-acc-ramp)# show running-config +... + access-control-class-ramp + chan-load-enabled + chan-load-step-interval 10 + chan-load-step-size 2 + chan-load-thresholds 80 90 + no cpu-load-enabled +... +OsmoBSC(config-net-bts-acc-ramp)# chan-load-step-interval 6 +OsmoBSC(config-net-bts-acc-ramp)# chan-load-step-size 2 +OsmoBSC(config-net-bts-acc-ramp)# chan-load-thresholds 10 50 +OsmoBSC(config-net-bts-acc-ramp)# show running-config +... + access-control-class-ramp + chan-load-enabled + chan-load-step-interval 6 + chan-load-step-size 2 + chan-load-thresholds 10 50 + no cpu-load-enabled +... + +OsmoBSC(config-net-bts-acc-ramp)# ### Now same for CPU load +OsmoBSC(config-net-bts-acc-ramp)# no cpu-load-enabled +OsmoBSC(config-net-bts-acc-ramp)# cpu-load-enabled +OsmoBSC(config-net-bts-acc-ramp)# show running-config +... + access-control-class-ramp + chan-load-enabled + chan-load-step-interval 6 + chan-load-step-size 2 + chan-load-thresholds 10 50 + cpu-load-enabled + cpu-load-step-interval 5 + cpu-load-step-size 1 + cpu-load-thresholds 71 89 +... +OsmoBSC(config-net-bts-acc-ramp)# cpu-load-step-interval 7 +OsmoBSC(config-net-bts-acc-ramp)# cpu-load-step-size 3 +OsmoBSC(config-net-bts-acc-ramp)# cpu-load-thresholds 12 60 +OsmoBSC(config-net-bts-acc-ramp)# show running-config +... + access-control-class-ramp + chan-load-enabled + chan-load-step-interval 6 + chan-load-step-size 2 + chan-load-thresholds 10 50 + cpu-load-enabled + cpu-load-step-interval 7 + cpu-load-step-size 3 + cpu-load-thresholds 12 60 +... + + +OsmoBSC(config-net-bts-acc-ramp)# ### Try incorrect use +OsmoBSC(config-net-bts-acc-ramp)# chan-load-step-interval 2 +% Unknown command. +OsmoBSC(config-net-bts-acc-ramp)# chan-load-step-size 0 +% Unknown command. +OsmoBSC(config-net-bts-acc-ramp)# chan-load-thresholds 80 70 +% Unable to set ACC channel load thresholds +OsmoBSC(config-net-bts-acc-ramp)# cpu-load-step-interval 2 +% Unknown command. +OsmoBSC(config-net-bts-acc-ramp)# cpu-load-step-size 0 +% Unknown command. +OsmoBSC(config-net-bts-acc-ramp)# cpu-load-thresholds 80 70 +% Unable to set ACC channel load thresholds + + +OsmoBSC(config-net-bts-acc-ramp)# ### Disable them +OsmoBSC(config-net-bts-acc-ramp)# no chan-load-enabled +OsmoBSC(config-net-bts-acc-ramp)# show running-config +... + access-control-class-ramp + no chan-load-enabled + cpu-load-enabled + cpu-load-step-interval 7 + cpu-load-step-size 3 + cpu-load-thresholds 12 60 +... +OsmoBSC(config-net-bts-acc-ramp)# no cpu-load-enabled +OsmoBSC(config-net-bts-acc-ramp)# show running-config +... + access-control-class-ramp + no chan-load-enabled + no cpu-load-enabled +... diff --git a/tests/acc/acc_test.c b/tests/acc/acc_test.c index 759ff139f..ef4c59790 100644 --- a/tests/acc/acc_test.c +++ b/tests/acc/acc_test.c @@ -64,8 +64,8 @@ static inline void _bts_del(struct gsm_bts *bts, const char *msg) rate_ctr_group_free(bts->bts_ctrs); if (osmo_timer_pending(&bts->acc_mgr.rotate_timer)) osmo_timer_del(&bts->acc_mgr.rotate_timer); - if (osmo_timer_pending(&bts->acc_ramp.step_timer)) - osmo_timer_del(&bts->acc_ramp.step_timer); + if (osmo_timer_pending(&bts->acc_ramp.chanld.step_timer)) + osmo_timer_del(&bts->acc_ramp.chanld.step_timer); /* no need to llist_del(&bts->list), we never registered the bts there. */ talloc_free(bts->site_mgr); fprintf(stderr, "BTS deallocated OK in %s()\n", msg); @@ -254,18 +254,18 @@ static void test_acc_ramp(struct gsm_network *net) struct acc_ramp *acc_ramp = &bts->acc_ramp; /* Validate are all allowed by default after allocation: */ - OSMO_ASSERT(acc_ramp_is_enabled(acc_ramp) == false); - OSMO_ASSERT(acc_ramp_get_step_size(acc_ramp) == ACC_RAMP_STEP_SIZE_DEFAULT); - OSMO_ASSERT(acc_ramp_get_step_interval(acc_ramp) == ACC_RAMP_STEP_INTERVAL_MIN); + OSMO_ASSERT(acc_ramp_thld_is_enabled(&acc_ramp->chanld) == false); + OSMO_ASSERT(acc_ramp_thld_get_step_size(&acc_ramp->chanld) == ACC_RAMP_STEP_SIZE_DEFAULT); + OSMO_ASSERT(acc_ramp_thld_get_step_interval(&acc_ramp->chanld) == ACC_RAMP_STEP_INTERVAL_MIN); /* Set super high rotation time so it doesn't interfer here: */ acc_mgr_set_rotation_time(acc_mgr, 5000); - OSMO_ASSERT(acc_ramp_set_step_interval(acc_ramp, 1) == -ERANGE); - OSMO_ASSERT(acc_ramp_set_step_interval(acc_ramp, 50) == 0); - OSMO_ASSERT(acc_ramp_set_chan_load_thresholds(acc_ramp, 100, 100) == 0); - acc_ramp_set_step_size(acc_ramp, 1); - acc_ramp_set_enabled(acc_ramp, true); + OSMO_ASSERT(acc_ramp_thld_set_step_interval(&acc_ramp->chanld, 1) == -ERANGE); + OSMO_ASSERT(acc_ramp_thld_set_step_interval(&acc_ramp->chanld, 50) == 0); + OSMO_ASSERT(acc_ramp_thld_set_thresholds(&acc_ramp->chanld, 100, 100) == 0); + acc_ramp_thld_set_step_size(&acc_ramp->chanld, 1); + acc_ramp_thld_set_enabled(&acc_ramp->chanld, true); osmo_gettimeofday_override_time = (struct timeval) {0, 0}; acc_ramp_trigger(acc_ramp); @@ -288,17 +288,17 @@ static void test_acc_ramp2(struct gsm_network *net) struct acc_ramp *acc_ramp = &bts->acc_ramp; /* Validate are all allowed by default after allocation: */ - OSMO_ASSERT(acc_ramp_is_enabled(acc_ramp) == false); - OSMO_ASSERT(acc_ramp_get_step_size(acc_ramp) == ACC_RAMP_STEP_SIZE_DEFAULT); - OSMO_ASSERT(acc_ramp_get_step_interval(acc_ramp) == ACC_RAMP_STEP_INTERVAL_MIN); + OSMO_ASSERT(acc_ramp_thld_is_enabled(&acc_ramp->chanld) == false); + OSMO_ASSERT(acc_ramp_thld_get_step_size(&acc_ramp->chanld) == ACC_RAMP_STEP_SIZE_DEFAULT); + OSMO_ASSERT(acc_ramp_thld_get_step_interval(&acc_ramp->chanld) == ACC_RAMP_STEP_INTERVAL_MIN); /* Set super high rotation time so it doesn't interfer here: */ acc_mgr_set_rotation_time(acc_mgr, 5000); /* Set adm len to test that ramping won't go over it */ acc_mgr_set_len_allowed_adm(acc_mgr, 7); - acc_ramp_set_step_size(acc_ramp, 3); - acc_ramp_set_enabled(acc_ramp, true); + acc_ramp_thld_set_step_size(&acc_ramp->chanld, 3); + acc_ramp_thld_set_enabled(&acc_ramp->chanld, true); osmo_gettimeofday_override_time = (struct timeval) {0, 0}; acc_ramp_trigger(acc_ramp); @@ -321,9 +321,9 @@ static void test_acc_ramp3(struct gsm_network *net) struct acc_ramp *acc_ramp = &bts->acc_ramp; /* Validate are all allowed by default after allocation: */ - OSMO_ASSERT(acc_ramp_is_enabled(acc_ramp) == false); - OSMO_ASSERT(acc_ramp_get_step_size(acc_ramp) == ACC_RAMP_STEP_SIZE_DEFAULT); - OSMO_ASSERT(acc_ramp_get_step_interval(acc_ramp) == ACC_RAMP_STEP_INTERVAL_MIN); + OSMO_ASSERT(acc_ramp_thld_is_enabled(&acc_ramp->chanld) == false); + OSMO_ASSERT(acc_ramp_thld_get_step_size(&acc_ramp->chanld) == ACC_RAMP_STEP_SIZE_DEFAULT); + OSMO_ASSERT(acc_ramp_thld_get_step_interval(&acc_ramp->chanld) == ACC_RAMP_STEP_INTERVAL_MIN); /* Set super high rotation time so it doesn't interfer here: */ acc_mgr_set_rotation_time(acc_mgr, 5000); @@ -333,8 +333,8 @@ static void test_acc_ramp3(struct gsm_network *net) bts->si_common.rach_control.t3 |= 0xa5; acc_mgr_perm_subset_changed(acc_mgr, &bts->si_common.rach_control); - acc_ramp_set_step_size(acc_ramp, 1); - acc_ramp_set_enabled(acc_ramp, true); + acc_ramp_thld_set_step_size(&acc_ramp->chanld, 1); + acc_ramp_thld_set_enabled(&acc_ramp->chanld, true); osmo_gettimeofday_override_time = (struct timeval) {0, 0}; acc_ramp_trigger(acc_ramp); @@ -358,20 +358,20 @@ static void test_acc_ramp_up_rotate(struct gsm_network *net, unsigned int chan_l int n; /* Validate are all allowed by default after allocation: */ - OSMO_ASSERT(acc_ramp_is_enabled(acc_ramp) == false); - OSMO_ASSERT(acc_ramp_get_step_size(acc_ramp) == ACC_RAMP_STEP_SIZE_DEFAULT); - OSMO_ASSERT(acc_ramp_get_step_interval(acc_ramp) == ACC_RAMP_STEP_INTERVAL_MIN); + OSMO_ASSERT(acc_ramp_thld_is_enabled(&acc_ramp->chanld) == false); + OSMO_ASSERT(acc_ramp_thld_get_step_size(&acc_ramp->chanld) == ACC_RAMP_STEP_SIZE_DEFAULT); + OSMO_ASSERT(acc_ramp_thld_get_step_interval(&acc_ramp->chanld) == ACC_RAMP_STEP_INTERVAL_MIN); - OSMO_ASSERT(acc_ramp_set_step_interval(acc_ramp, 250) == 0); + OSMO_ASSERT(acc_ramp_thld_set_step_interval(&acc_ramp->chanld, 250) == 0); acc_mgr_set_rotation_time(acc_mgr, 100); /* Test that ramping + rotation won't go over permanently barred ACC*/ fprintf(stderr, "*** Barring one ACC ***\n"); bts->si_common.rach_control.t2 |= 0x02; acc_mgr_perm_subset_changed(acc_mgr, &bts->si_common.rach_control); - OSMO_ASSERT(acc_ramp_set_step_size(acc_ramp, 1) == 0); - OSMO_ASSERT(acc_ramp_set_chan_load_thresholds(acc_ramp, low_threshold, up_threshold) == 0); - acc_ramp_set_enabled(acc_ramp, true); + OSMO_ASSERT(acc_ramp_thld_set_step_size(&acc_ramp->chanld, 1) == 0); + OSMO_ASSERT(acc_ramp_thld_set_thresholds(&acc_ramp->chanld, low_threshold, up_threshold) == 0); + acc_ramp_thld_set_enabled(&acc_ramp->chanld, true); bts->chan_load_avg = chan_load; /*set % channel load */ @@ -380,7 +380,7 @@ static void test_acc_ramp_up_rotate(struct gsm_network *net, unsigned int chan_l n = 5; while (true) { - OSMO_ASSERT(osmo_timer_pending(&acc_ramp->step_timer)); + OSMO_ASSERT(osmo_timer_pending(&acc_ramp->chanld.step_timer)); if (osmo_timer_pending(&acc_mgr->rotate_timer)) { if ((osmo_gettimeofday_override_time.tv_sec + 50) % 250 == 0) osmo_gettimeofday_override_time.tv_sec += 50; @@ -416,20 +416,20 @@ static void test_acc_ramp_updown_rotate(struct gsm_network *net, unsigned int lo bool up = true; /* Validate are all allowed by default after allocation: */ - OSMO_ASSERT(acc_ramp_is_enabled(acc_ramp) == false); - OSMO_ASSERT(acc_ramp_get_step_size(acc_ramp) == ACC_RAMP_STEP_SIZE_DEFAULT); - OSMO_ASSERT(acc_ramp_get_step_interval(acc_ramp) == ACC_RAMP_STEP_INTERVAL_MIN); + OSMO_ASSERT(acc_ramp_thld_is_enabled(&acc_ramp->chanld) == false); + OSMO_ASSERT(acc_ramp_thld_get_step_size(&acc_ramp->chanld) == ACC_RAMP_STEP_SIZE_DEFAULT); + OSMO_ASSERT(acc_ramp_thld_get_step_interval(&acc_ramp->chanld) == ACC_RAMP_STEP_INTERVAL_MIN); - OSMO_ASSERT(acc_ramp_set_step_interval(acc_ramp, 250) == 0); + OSMO_ASSERT(acc_ramp_thld_set_step_interval(&acc_ramp->chanld, 250) == 0); acc_mgr_set_rotation_time(acc_mgr, 100); /* Test that ramping + rotation won't go over permanently barred ACC*/ fprintf(stderr, "*** Barring one ACC ***\n"); bts->si_common.rach_control.t2 |= 0x02; acc_mgr_perm_subset_changed(acc_mgr, &bts->si_common.rach_control); - OSMO_ASSERT(acc_ramp_set_step_size(acc_ramp, 1) == 0); - OSMO_ASSERT(acc_ramp_set_chan_load_thresholds(acc_ramp, low_threshold, up_threshold) == 0); - acc_ramp_set_enabled(acc_ramp, true); + OSMO_ASSERT(acc_ramp_thld_set_step_size(&acc_ramp->chanld, 1) == 0); + OSMO_ASSERT(acc_ramp_thld_set_thresholds(&acc_ramp->chanld, low_threshold, up_threshold) == 0); + acc_ramp_thld_set_enabled(&acc_ramp->chanld, true); bts->chan_load_avg = min_load; /* set % channel load */ @@ -438,7 +438,7 @@ static void test_acc_ramp_updown_rotate(struct gsm_network *net, unsigned int lo /* 50 ev loop iterations */ for (i = 0; i < 50; i++) { - OSMO_ASSERT(osmo_timer_pending(&acc_ramp->step_timer)); + OSMO_ASSERT(osmo_timer_pending(&acc_ramp->chanld.step_timer)); if (osmo_timer_pending(&acc_mgr->rotate_timer)) { if ((osmo_gettimeofday_override_time.tv_sec + 50) % 250 == 0) osmo_gettimeofday_override_time.tv_sec += 50; |