aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPau Espin Pedrol <pespin@sysmocom.de>2021-04-27 14:53:23 +0200
committerPau Espin Pedrol <pespin@sysmocom.de>2021-04-29 18:44:36 +0200
commit9ff25a3674a470fce19f0f4175aa50f63bf05881 (patch)
tree68a6058363e987bf5e50efc23a0a5ca1f2800f26
parentd8e55223ec6b3c1161716ae0884c8006c90c388d (diff)
ACC: Support ACC ramping based on CPU Loadpespin/acc
* Rearrange acc_ramp struct and API to allow other variables * Move ACC ramp chan-load VTY cmds to an own node Since we'll be adding more parameters and naming is already quite long, let's move everything to an own node instead, to keep names smaller as well as being able to identify them when we add CPU load checks. Old commands can still be used but are marked as deprecated in favour of new commands in the created node. * Add new VTY nodes to configure ACC ramping based on CPU load. Related: SYS#4939 Change-Id: I1930f5c3af34e648021ffdcd455e2c72821edbd8 WIP: cpuload Change-Id: I2a74f5f695237d731db467924c1b6609eadce9a9
-rw-r--r--include/osmocom/bsc/acc.h91
-rw-r--r--include/osmocom/bsc/vty.h1
-rw-r--r--src/osmo-bsc/acc.c269
-rw-r--r--src/osmo-bsc/bsc_vty.c351
-rw-r--r--src/osmo-bsc/osmo_bsc_main.c9
-rw-r--r--tests/acc.vty159
-rw-r--r--tests/acc/acc_test.c72
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;