Change in osmo-bsc[master]: hodec2: fix congestion balancing on dyn TS

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.

neels gerrit-no-reply at lists.osmocom.org
Sun Jan 17 19:53:04 UTC 2021


neels has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-bsc/+/22269 )


Change subject: hodec2: fix congestion balancing on dyn TS
......................................................................

hodec2: fix congestion balancing on dyn TS

When balancing congestion, not only look at TCH/F or TCH/H separately,
but also to take into account the effects on the other TCH kind from
using/freeing dynamic TS.

Related: OS#5298
Change-Id: I433df6f343650f9056b1bab926bc19ac1d867ad5
---
M src/osmo-bsc/handover_decision_2.c
M tests/handover/test_dyn_ts_balance_congestion.ho_vty
2 files changed, 106 insertions(+), 17 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/osmo-bsc refs/changes/69/22269/1

diff --git a/src/osmo-bsc/handover_decision_2.c b/src/osmo-bsc/handover_decision_2.c
index 379970f..c4144a2 100644
--- a/src/osmo-bsc/handover_decision_2.c
+++ b/src/osmo-bsc/handover_decision_2.c
@@ -106,8 +106,17 @@
 		struct gsm_lchan *lchan;
 		struct gsm_bts *bts;
 		int rxlev;
+		/* free/min-free for the current TCH kind, same as either free_tch_f or free_tch_h below */
 		int free_tch;
 		int min_free_tch;
+		/* free/min-free for the two TCH kinds, to calculate F<->H cross effects for dynamic timeslots */
+		int free_tchf;
+		int min_free_tchf;
+		int free_tchh;
+		int min_free_tchh;
+		/* Effects of freeing a dynamic timeslot: */
+		int lchan_frees_tchf;
+		int lchan_frees_tchh;
 	} current;
 	struct {
 		struct neighbor_ident_key nik;	/* neighbor ARFCN+BSIC */
@@ -155,6 +164,17 @@
 
 static void congestion_check_cb(void *arg);
 
+static unsigned int ts_usage_count(struct gsm_bts_trx_ts *ts)
+{
+	struct gsm_lchan *lchan;
+	unsigned int count = 0;
+	ts_for_each_lchan(lchan, ts) {
+		if (lchan_state_is(lchan, LCHAN_ST_ESTABLISHED))
+			count++;
+	}
+	return count;
+}
+
 /* This function gets called on ho2 init, whenever the congestion check interval is changed, and also
  * when the timer has fired to trigger again after the next congestion check timeout. */
 static void reinit_congestion_timer(struct gsm_network *net)
@@ -659,21 +679,75 @@
 	 * 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) {
+		bool ok;
 		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)
+		ok = target_overbooked < current_overbooked;
+		/* Look at dynamic timeslot effects on TCH/H: */
+		if (ok && c->target.next_tchf_reduces_tchh) {
+			/* Looking at the current TCH type and the target cell's TCH/F alone, congestion balancing
+			 * should happen. However, what if the target TCH/F is a dynamic timeslot -- would that cause
+			 * congestion on TCH/H above the current cell's TCH/H congestion? */
+			int32_t current_tchh_overbooked = load_above_congestion(c->current.free_tchh,
+										c->current.min_free_tchh);
+			int32_t target_tchh_overbooked;
+			int target_free_tchh_after_ho = c->target.free_tchh - c->target.next_tchf_reduces_tchh;
+			/* If this is a re-assignment within the same cell, and if the current candidate would free a
+			 * dynamic timeslot, then the target-overbooking after HO is reduced again by the freed dynamic
+			 * TS. */
+			if (c->current.bts == c->target.bts)
+				target_free_tchh_after_ho += c->current.lchan_frees_tchh;
+			target_tchh_overbooked = load_above_congestion(target_free_tchh_after_ho,
+								       c->target.min_free_tchh);
+			LOGPHOLCHANTOBTS(c->current.lchan, c->target.bts, LOGL_DEBUG,
+					 "dyn TS: current TCH/H overbooked = %s%%, TCH/H target overbooked after HO = %s%%\n",
+					 osmo_int_to_float_str_c(OTC_SELECT, current_tchh_overbooked, LOAD_PRECISION - 2),
+					 osmo_int_to_float_str_c(OTC_SELECT, target_tchh_overbooked, LOAD_PRECISION - 2));
+			/* For the current TCH kind, a handover should only happen if things actually get better
+			 * (condition is '<'). For dynamic timeslot cross effects TCH/F->TCH/H, it is fine to not make
+			 * it worse.  Hence the smaller-or-equal condition. */
+			ok = target_tchh_overbooked <= current_tchh_overbooked;
+		}
+		if (ok)
 			requirement |= REQUIREMENT_C_TCHF;
 	}
 	if (requirement & REQUIREMENT_A_TCHH) {
+		bool ok;
 		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)
+		ok = target_overbooked < current_overbooked;
+		/* Look at dynamic timeslot effects on TCH/F: */
+		if (ok && c->target.next_tchh_reduces_tchf) {
+			/* Looking at the current TCH type and the target cell's TCH/H alone, congestion balancing
+			 * should happen. However, what if the target TCH/H is a dynamic timeslot -- would that cause
+			 * congestion on TCH/F above the current cell's TCH/F congestion? */
+			int32_t current_tchf_overbooked = load_above_congestion(c->current.free_tchf,
+										c->current.min_free_tchf);
+			int32_t target_tchf_overbooked;
+			int target_free_tchf_after_ho = c->target.free_tchf - c->target.next_tchh_reduces_tchf;
+			/* If this is a re-assignment within the same cell, and if the current candidate would free a
+			 * dynamic timeslot, then the target-overbooking after HO is reduced again by the freed dynamic
+			 * TS. */
+			if (c->current.bts == c->target.bts)
+				target_free_tchf_after_ho += c->current.lchan_frees_tchf;
+			target_tchf_overbooked = load_above_congestion(target_free_tchf_after_ho,
+								       c->target.min_free_tchf);
+			LOGPHOLCHANTOBTS(c->current.lchan, c->target.bts, LOGL_DEBUG,
+					 "dyn TS: current TCH/F overbooked = %s%%, TCH/F target overbooked after HO = %s%%\n",
+					 osmo_int_to_float_str_c(OTC_SELECT, current_tchf_overbooked, LOAD_PRECISION - 2),
+					 osmo_int_to_float_str_c(OTC_SELECT, target_tchf_overbooked, LOAD_PRECISION - 2));
+			/* For the current TCH kind, a handover should only happen if things actually get better
+			 * (condition is '<'). For dynamic timeslot cross effects TCH/H->TCH/F, it is fine to not make
+			 * it worse. Hence the smaller-or-equal condition. */
+			ok = target_tchf_overbooked <= current_tchf_overbooked;
+		}
+		if (ok)
 			requirement |= REQUIREMENT_C_TCHH;
 	}
 
@@ -904,17 +978,37 @@
 {
 	struct gsm_lchan *next_lchan;
 
-	c->current.free_tch = bts_count_free_ts(c->current.bts, c->current.lchan->ts->pchan_is);
+	c->current.free_tchf = bts_count_free_ts(c->current.bts, GSM_PCHAN_TCH_F);
+	c->current.min_free_tchf = ho_get_hodec2_tchf_min_slots(c->current.bts->ho);
+	c->current.free_tchh = bts_count_free_ts(c->current.bts, GSM_PCHAN_TCH_H);
+	c->current.min_free_tchh = ho_get_hodec2_tchh_min_slots(c->current.bts->ho);
 	switch (c->current.lchan->ts->pchan_is) {
 	case GSM_PCHAN_TCH_F:
-		c->current.min_free_tch = ho_get_hodec2_tchf_min_slots(c->current.bts->ho);
+		c->current.free_tch = c->current.free_tchf;
+		c->current.min_free_tch = c->current.min_free_tchf;
+		c->current.lchan_frees_tchf = 1;
+		if (c->current.lchan->ts->pchan_on_init == GSM_PCHAN_TCH_F_TCH_H_PDCH)
+			c->current.lchan_frees_tchh = 2;
+		else
+			c->current.lchan_frees_tchh = 0;
 		break;
 	case GSM_PCHAN_TCH_H:
-		c->current.min_free_tch = ho_get_hodec2_tchh_min_slots(c->current.bts->ho);
+		c->current.free_tch = c->current.free_tchh;
+		c->current.min_free_tch = c->current.min_free_tchh;
+		c->current.lchan_frees_tchh = 1;
+		/* Freeing one of two TCH/H does not free a dyn TS and would not free a TCH/F. It has to be the last
+		 * TCH/H of a dynamic timeslot that is freed to get a new TCH/F in the current cell from the handover.
+		 * Hence the ts_usage_count() condition. */
+		if (c->current.lchan->ts->pchan_on_init == GSM_PCHAN_TCH_F_TCH_H_PDCH
+		    && ts_usage_count(c->current.lchan->ts) == 1)
+			c->current.lchan_frees_tchf = 1;
+		else
+			c->current.lchan_frees_tchf = 0;
 		break;
 	default:
 		break;
 	}
+
 	c->target.free_tchf = bts_count_free_ts(c->target.bts, GSM_PCHAN_TCH_F);
 	c->target.min_free_tchf = ho_get_hodec2_tchf_min_slots(c->target.bts->ho);
 	c->target.free_tchh = bts_count_free_ts(c->target.bts, GSM_PCHAN_TCH_H);
@@ -1454,17 +1548,6 @@
 		|| lchan->ts->pchan_on_init == GSM_PCHAN_TCH_F_PDCH;
 }
 
-static unsigned int ts_usage_count(struct gsm_bts_trx_ts *ts)
-{
-	struct gsm_lchan *lchan;
-	unsigned int count = 0;
-	ts_for_each_lchan(lchan, ts) {
-		if (lchan_state_is(lchan, LCHAN_ST_ESTABLISHED))
-			count++;
-	}
-	return count;
-}
-
 static bool is_upgrade_to_tchf(const struct ho_candidate *c, uint8_t for_requirement)
 {
 	return c->current.lchan
diff --git a/tests/handover/test_dyn_ts_balance_congestion.ho_vty b/tests/handover/test_dyn_ts_balance_congestion.ho_vty
index ad9d6a5..2fa11b6 100644
--- a/tests/handover/test_dyn_ts_balance_congestion.ho_vty
+++ b/tests/handover/test_dyn_ts_balance_congestion.ho_vty
@@ -27,5 +27,11 @@
 # not congested. No handover is performed because 50% in the target is more congestion for TCH/H than 0% in the source
 # cell.
 congestion-check
-# FAIL: should not increase TCH/H congestion by occupying a dyn TS
+expect-no-chan
+
+# If there is no constraint on TCH/H in the target cell, the handover does take place.
+network
+ bts 1
+  handover2 min-free-slots tch/h 2
+congestion-check
 expect-ho from lchan 0 0 1 0 to lchan 1 0 5 0

-- 
To view, visit https://gerrit.osmocom.org/c/osmo-bsc/+/22269
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-bsc
Gerrit-Branch: master
Gerrit-Change-Id: I433df6f343650f9056b1bab926bc19ac1d867ad5
Gerrit-Change-Number: 22269
Gerrit-PatchSet: 1
Gerrit-Owner: neels <nhofmeyr at sysmocom.de>
Gerrit-MessageType: newchange
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20210117/ae9f5946/attachment.htm>


More information about the gerrit-log mailing list