aboutsummaryrefslogtreecommitdiffstats
path: root/src/osmo-bsc/handover_decision_2.c
diff options
context:
space:
mode:
authorNeels Hofmeyr <neels@hofmeyr.de>2021-01-09 18:25:36 +0100
committerneels <nhofmeyr@sysmocom.de>2021-01-14 06:24:57 +0000
commit8e830dd136877a65ed294bee3693a1b2463c059f (patch)
treef5fd1101f4ed7548f73084e3972e640a627854ef /src/osmo-bsc/handover_decision_2.c
parent55a015dddf7fa1467b2b9b9def0174990a514490 (diff)
hodec2: to balance congestion, use overload percent
For balancing load across congested cells and across congested TCH/* kinds, instead of comparing the number of lchans above the configured congestion threshold, compare the percent of lchans of overload. In short, using a percentage prevents cells with less min-free-slots to fill up 100% while neighbor cells still may have several free lchans available. An obvious example of why this is desirable is illustrated by test_balance_congestion_by_percentage.ho_vty: Cell A has min-free-slots 2, and has all slots occupied. Cell B has min-free-slots 4, and has 2 slots remaining free. If we count congested lchans as in current master: cell A has a congestion count of 2: two more lchans in use than "allowed". If we move one lchan over to cell B, it ends up with a congestion count of 3, which is worse than 2. So when counting lchans, we decide that cell A should remain full. Instead, when comparing percentage of remaining lchans, we would see that cell A is loaded 100% above congestion (2 of 2 remaining lchans in use), but when moving one lchan to cell B, that would only be 75% loaded above its treshold (3 of 4 remaining lchans in use). So a percentage comparison would cause a handover to cell B. Related: SYS#5259 Change-Id: I55234c6c99eb02ceee52be0d7388bea14304930f
Diffstat (limited to 'src/osmo-bsc/handover_decision_2.c')
-rw-r--r--src/osmo-bsc/handover_decision_2.c45
1 files changed, 37 insertions, 8 deletions
diff --git a/src/osmo-bsc/handover_decision_2.c b/src/osmo-bsc/handover_decision_2.c
index c265f5fa3..0362c9b95 100644
--- a/src/osmo-bsc/handover_decision_2.c
+++ b/src/osmo-bsc/handover_decision_2.c
@@ -25,6 +25,7 @@
#include <stdbool.h>
#include <errno.h>
#include <limits.h>
+#include <math.h>
#include <osmocom/bsc/debug.h>
#include <osmocom/bsc/gsm_data.h>
@@ -387,6 +388,26 @@ static bool codec_type_is_supported(struct gsm_subscriber_connection *conn,
return false;
}
+#define LOAD_PRECISION 6
+
+/* Return a number representing overload, i.e. the fraction of lchans used above the congestion threshold.
+ * Think of it as a percentage of used lchans above congestion, just represented in a fixed-point fraction with N
+ * decimal digits of fractional part. If there is no congestion (free_tch >= min_free_tch), return 0.
+ */
+static int32_t load_above_congestion(int free_tch, int min_free_tch)
+{
+ int32_t v;
+ OSMO_ASSERT(free_tch >= 0);
+ /* Avoid division by zero when no congestion threshold is set, and return zero overload when there is no
+ * congestion. */
+ if (free_tch >= min_free_tch)
+ return 0;
+ v = min_free_tch - free_tch;
+ v *= pow(10, LOAD_PRECISION);
+ v /= min_free_tch;
+ return v;
+}
+
/*
* Check what requirements the given cell fulfills.
* A bit mask of fulfilled requirements is returned.
@@ -443,7 +464,7 @@ static void check_requirements(struct ho_candidate *c)
{
uint8_t requirement = 0;
unsigned int penalty_time;
- int current_overbooked;
+ int32_t current_overbooked;
c->requirements = 0;
/* Requirement A */
@@ -626,17 +647,25 @@ static void check_requirements(struct ho_candidate *c)
/* Requirement C */
- /* the nr of lchans surpassing congestion on the target cell must be <= the lchans surpassing congestion on the
- * current cell _after_ handover/assignment */
- current_overbooked = c->current.min_free_tch - c->current.free_tch;
+ /* the load percentage above congestion on the target cell *after* HO must be < the load percentage above
+ * congestion on the current cell, hence the - 1 on the target. */
+ current_overbooked = load_above_congestion(c->current.free_tch, c->current.min_free_tch);
if (requirement & REQUIREMENT_A_TCHF) {
- int target_overbooked = c->target.min_free_tchf - c->target.free_tchf;
- if (target_overbooked + 1 <= current_overbooked - 1)
+ int32_t target_overbooked = load_above_congestion(c->target.free_tchf - 1, c->target.min_free_tchf);
+ LOGPHOLCHANTOBTS(c->current.lchan, c->target.bts, LOGL_DEBUG,
+ "current overbooked = %s%%, TCH/F target overbooked after HO = %s%%\n",
+ osmo_int_to_float_str_c(OTC_SELECT, current_overbooked, LOAD_PRECISION - 2),
+ osmo_int_to_float_str_c(OTC_SELECT, target_overbooked, LOAD_PRECISION - 2));
+ if (target_overbooked < current_overbooked)
requirement |= REQUIREMENT_C_TCHF;
}
if (requirement & REQUIREMENT_A_TCHH) {
- int target_overbooked = c->target.min_free_tchh - c->target.free_tchh;
- if (target_overbooked + 1 <= current_overbooked - 1)
+ int32_t target_overbooked = load_above_congestion(c->target.free_tchh - 1, c->target.min_free_tchh);
+ LOGPHOLCHANTOBTS(c->current.lchan, c->target.bts, LOGL_DEBUG,
+ "current overbooked = %s%%, TCH/H target overbooked after HO = %s%%\n",
+ osmo_int_to_float_str_c(OTC_SELECT, current_overbooked, LOAD_PRECISION - 2),
+ osmo_int_to_float_str_c(OTC_SELECT, target_overbooked, LOAD_PRECISION - 2));
+ if (target_overbooked < current_overbooked)
requirement |= REQUIREMENT_C_TCHH;
}