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.orgneels has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-bsc/+/21204 )
Change subject: hodec 2: favor moving dyn TS
......................................................................
hodec 2: favor moving dyn TS
Change-Id: Ic221b8d2687cdec0bf94410c84a4da43853f0900
---
M src/osmo-bsc/handover_decision_2.c
M tests/handover/handover_test.c
2 files changed, 105 insertions(+), 65 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-bsc refs/changes/04/21204/1
diff --git a/src/osmo-bsc/handover_decision_2.c b/src/osmo-bsc/handover_decision_2.c
index c818dbb..68ead67 100644
--- a/src/osmo-bsc/handover_decision_2.c
+++ b/src/osmo-bsc/handover_decision_2.c
@@ -1362,6 +1362,100 @@
}
}
+static void collect_candidates_on_ts(struct gsm_bts_trx_ts *ts, struct ho_candidate *clist, unsigned int *candidates,
+ int tchf_congestion, int tchh_congestion,
+ bool only_dyn_ts)
+{
+ int j;
+ struct gsm_lchan *lc;
+
+ if (!ts_is_usable(ts))
+ return;
+
+ switch (ts->pchan_on_init) {
+ case GSM_PCHAN_TCH_F_TCH_H_PDCH:
+ case GSM_PCHAN_TCH_F_PDCH:
+ if (!only_dyn_ts)
+ return;
+ break;
+ default:
+ if (only_dyn_ts)
+ return;
+ break;
+ }
+
+ /* (Do not consider dynamic TS that are in PDCH mode) */
+ switch (ts->pchan_is) {
+ case GSM_PCHAN_TCH_F:
+ /* No need to collect TCH/F candidates if no TCH/F needs to be moved. */
+ if (tchf_congestion == 0)
+ return;
+
+ lc = &ts->lchan[0];
+ /* omit if channel not active */
+ if (lc->type != GSM_LCHAN_TCH_F
+ || !lchan_state_is(lc, LCHAN_ST_ESTABLISHED))
+ break;
+ /* omit if there is an ongoing ho/as */
+ if (!lc->conn || lc->conn->assignment.new_lchan
+ || lc->conn->ho.fi)
+ break;
+ /* We desperately want to resolve congestion, ignore rxlev when
+ * collecting candidates by passing include_weaker_rxlev=true. */
+ collect_candidates_for_lchan(lc, clist, candidates, NULL, true);
+ break;
+
+ case GSM_PCHAN_TCH_H:
+ /* No need to collect TCH/H candidates if no TCH/H needs to be moved. */
+ if (tchh_congestion == 0)
+ return;
+
+ for (j = 0; j < 2; j++) {
+ lc = &ts->lchan[j];
+ /* omit if channel not active */
+ if (lc->type != GSM_LCHAN_TCH_H
+ || !lchan_state_is(lc, LCHAN_ST_ESTABLISHED))
+ return;
+ /* omit of there is an ongoing ho/as */
+ if (!lc->conn
+ || lc->conn->assignment.new_lchan
+ || lc->conn->ho.fi)
+ return;
+ /* We desperately want to resolve congestion, ignore rxlev when
+ * collecting candidates by passing include_weaker_rxlev=true. */
+ collect_candidates_for_lchan(lc, clist, candidates, NULL, true);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+/* loop through all active lchan and collect candidates */
+static void collect_candidates_on_bts(struct gsm_bts *bts, struct ho_candidate *clist, unsigned int *candidates,
+ int tchf_congestion, int tchh_congestion,
+ bool only_dyn_ts)
+{
+ struct gsm_bts_trx *trx;
+ int i;
+
+ llist_for_each_entry(trx, &bts->trx_list, list) {
+ if (!trx_is_usable(trx))
+ continue;
+
+ if (only_dyn_ts) {
+ /* iterate dyn TS in reverse, to favor moving "later" timeslots */
+ for (i = 7; i >= 0; i--)
+ collect_candidates_on_ts(&trx->ts[i], clist, candidates, tchf_congestion,
+ tchh_congestion, only_dyn_ts);
+ } else {
+ for (i = 0; i < 8; i++)
+ collect_candidates_on_ts(&trx->ts[i], clist, candidates, tchf_congestion,
+ tchh_congestion, only_dyn_ts);
+ }
+ }
+}
+
/*
* Handover/assignment check after timer timeout:
*
@@ -1413,10 +1507,7 @@
*/
static int bts_resolve_congestion(struct gsm_bts *bts, int tchf_congestion, int tchh_congestion)
{
- struct gsm_lchan *lc;
- struct gsm_bts_trx *trx;
- struct gsm_bts_trx_ts *ts;
- int i, j;
+ int i;
struct ho_candidate *clist;
unsigned int candidates;
struct ho_candidate *best_cand = NULL, *worst_cand = NULL;
@@ -1437,68 +1528,18 @@
/* allocate array of all bts */
clist = talloc_zero_array(tall_bsc_ctx, struct ho_candidate,
- bts->num_trx * 8 * 2 * (1 + ARRAY_SIZE(lc->neigh_meas)));
+ bts->num_trx * 8 * 2 * (1 + ARRAY_SIZE(((struct gsm_lchan*)0)->neigh_meas)));
if (!clist)
return 0;
candidates = 0;
- /* loop through all active lchan and collect candidates */
- llist_for_each_entry(trx, &bts->trx_list, list) {
- if (!trx_is_usable(trx))
- continue;
+ /* First collect candidates for dyn TS, to favor freeing PDCH. This specifically makes a difference when
+ * rxlev for a target cell are equal, particularly when considering re-assignment within the same cell. */
+ collect_candidates_on_bts(bts, clist, &candidates, tchf_congestion, tchh_congestion, true);
- for (i = 0; i < 8; i++) {
- ts = &trx->ts[i];
- if (!ts_is_usable(ts))
- continue;
-
- /* (Do not consider dynamic TS that are in PDCH mode) */
- switch (ts->pchan_is) {
- case GSM_PCHAN_TCH_F:
- /* No need to collect TCH/F candidates if no TCH/F needs to be moved. */
- if (tchf_congestion == 0)
- continue;
-
- lc = &ts->lchan[0];
- /* omit if channel not active */
- if (lc->type != GSM_LCHAN_TCH_F
- || !lchan_state_is(lc, LCHAN_ST_ESTABLISHED))
- break;
- /* omit if there is an ongoing ho/as */
- if (!lc->conn || lc->conn->assignment.new_lchan
- || lc->conn->ho.fi)
- break;
- /* We desperately want to resolve congestion, ignore rxlev when
- * collecting candidates by passing include_weaker_rxlev=true. */
- collect_candidates_for_lchan(lc, clist, &candidates, NULL, true);
- break;
- case GSM_PCHAN_TCH_H:
- /* No need to collect TCH/H candidates if no TCH/H needs to be moved. */
- if (tchh_congestion == 0)
- continue;
-
- for (j = 0; j < 2; j++) {
- lc = &ts->lchan[j];
- /* omit if channel not active */
- if (lc->type != GSM_LCHAN_TCH_H
- || !lchan_state_is(lc, LCHAN_ST_ESTABLISHED))
- continue;
- /* omit of there is an ongoing ho/as */
- if (!lc->conn
- || lc->conn->assignment.new_lchan
- || lc->conn->ho.fi)
- continue;
- /* We desperately want to resolve congestion, ignore rxlev when
- * collecting candidates by passing include_weaker_rxlev=true. */
- collect_candidates_for_lchan(lc, clist, &candidates, NULL, true);
- }
- break;
- default:
- break;
- }
- }
- }
+ /* Then collect candidates for non-dyn TS */
+ collect_candidates_on_bts(bts, clist, &candidates, tchf_congestion, tchh_congestion, false);
if (!candidates) {
LOGPHOBTS(bts, LOGL_DEBUG, "No neighbor cells qualify to solve congestion\n");
diff --git a/tests/handover/handover_test.c b/tests/handover/handover_test.c
index 6befc5a..804ff4b 100644
--- a/tests/handover/handover_test.c
+++ b/tests/handover/handover_test.c
@@ -1679,16 +1679,15 @@
"congestion-check",
"expect-chan", "0", "6",
"ack-chan",
- /* Not so good: rather than moving static TCH/F, we should favor freeing dyn TS, for more PDCH */
- "expect-ho", "0", "1",
+ "expect-ho", "0", "5",
"ho-complete",
- "expect-ts-use", "0", "0", "*", "-", "TCH/F", "TCH/F", "TCH/F", "TCH/F", "TCH/H-", "PDCH",
+ "expect-ts-use", "0", "0", "*", "TCH/F", "TCH/F", "TCH/F", "TCH/F", "PDCH", "TCH/H-", "PDCH",
"congestion-check",
"expect-chan", "0", "6",
"ack-chan",
- "expect-ho", "0", "2",
+ "expect-ho", "0", "4",
"ho-complete",
- "expect-ts-use", "0", "0", "*", "-", "-", "TCH/F", "TCH/F", "TCH/F", "TCH/HH", "PDCH",
+ "expect-ts-use", "0", "0", "*", "TCH/F", "TCH/F", "TCH/F", "PDCH", "PDCH", "TCH/HH", "PDCH",
"congestion-check",
"expect-no-chan",
NULL
--
To view, visit https://gerrit.osmocom.org/c/osmo-bsc/+/21204
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: osmo-bsc
Gerrit-Branch: master
Gerrit-Change-Id: Ic221b8d2687cdec0bf94410c84a4da43853f0900
Gerrit-Change-Number: 21204
Gerrit-PatchSet: 1
Gerrit-Owner: neels <nhofmeyr at sysmocom.de>
Gerrit-CC: Jenkins Builder
Gerrit-MessageType: newchange
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20201117/6d451e5b/attachment.htm>