[PATCH] osmo-bsc[master]: Make "waiting indicator" of IMMEDIATE ASSIGN REJECT dynamic.

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/.

Stefan Sperling gerrit-no-reply at lists.osmocom.org
Tue Jan 30 17:36:04 UTC 2018


Review at  https://gerrit.osmocom.org/6211

Make "waiting indicator" of IMMEDIATE ASSIGN REJECT dynamic.

The IMMEDIATE ASSIGN REJECT message contains a wait indicator which
tells an MS requesting a channel to wait for a specified amount of
time before trying to request a channel again, i.e. the wait indicator
controls the T3122 timeout value in the MS.

Previously, the wait indicator was fixed to 10 seconds.
This is not sufficient if there are a lot of MS requesting channels
because the MS will retry too soon. Instead of using a fixed value,
maintain a dynamic wait indicator value based on average channel load.

The load (used vs. available channels on a BTS) is sampled once per
second, and once 8 samples have been collected we update a BTS-specific
T3122 wait indicator based on the measured load.

While the wait indicator could go up to 255 seconds, this initial
implementation keeps it in the range from 10 to 128 seconds.

Further experimentation and testing will show whether higher wait
indicator values are desirable, if the sampling rate needs to change,
or if the function mapping the load measurement to a wait indicator
value should change (currently we map the load average linearly into
the range [10, 128] inclusive).

Change-Id: I57e38f6d6ba3b23cc6e1f9520b90261dbb1f1cec
Related: OS#2592
---
M include/osmocom/bsc/chan_alloc.h
M include/osmocom/bsc/gsm_data.h
M include/osmocom/bsc/gsm_data_shared.h
M src/libbsc/abis_rsl.c
M src/libbsc/bsc_init.c
M src/libbsc/bsc_vty.c
M src/libbsc/chan_alloc.c
M src/libbsc/net_init.c
M src/libcommon/gsm_data_shared.c
M tests/channel/Makefile.am
M tests/channel/channel_test.c
11 files changed, 134 insertions(+), 30 deletions(-)


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

diff --git a/include/osmocom/bsc/chan_alloc.h b/include/osmocom/bsc/chan_alloc.h
index 748e9cd..98568a5 100644
--- a/include/osmocom/bsc/chan_alloc.h
+++ b/include/osmocom/bsc/chan_alloc.h
@@ -37,17 +37,13 @@
 /* Release the given lchan */
 int lchan_release(struct gsm_lchan *lchan, int sacch_deact, enum rsl_rel_mode release_mode);
 
-struct load_counter {
-	unsigned int total;
-	unsigned int used;
-};
-
 struct pchan_load {
 	struct load_counter pchan[_GSM_PCHAN_MAX];
 };
 
 void bts_chan_load(struct pchan_load *cl, const struct gsm_bts *bts);
 void network_chan_load(struct pchan_load *pl, struct gsm_network *net);
+void bts_update_t3122_chan_load(struct gsm_bts *bts);
 
 bool trx_is_usable(const struct gsm_bts_trx *trx);
 bool ts_is_usable(const struct gsm_bts_trx_ts *ts);
diff --git a/include/osmocom/bsc/gsm_data.h b/include/osmocom/bsc/gsm_data.h
index bdf7cfb..25dee78 100644
--- a/include/osmocom/bsc/gsm_data.h
+++ b/include/osmocom/bsc/gsm_data.h
@@ -308,6 +308,9 @@
 	/* Periodic location update default value */
 	uint8_t t3212;
 
+	/* Timer for periodic channel load measurements to maintain each BTS's T3122. */
+	struct osmo_timer_list t3122_chan_load_timer;
+
 	struct {
 		struct mgcp_client_conf *conf;
 		struct mgcp_client *client;
diff --git a/include/osmocom/bsc/gsm_data_shared.h b/include/osmocom/bsc/gsm_data_shared.h
index 86c5ca9..504b42a 100644
--- a/include/osmocom/bsc/gsm_data_shared.h
+++ b/include/osmocom/bsc/gsm_data_shared.h
@@ -573,6 +573,12 @@
 	double height;
 };
 
+/* Channel load counter */
+struct load_counter {
+	unsigned int total;
+	unsigned int used;
+};
+
 /* One BTS */
 struct gsm_bts {
 	/* list header in net->bts_list */
@@ -802,6 +808,13 @@
 	struct rate_ctr_group *bts_ctrs;
 
 	struct handover_cfg *ho;
+
+	/* BTS-specific overrides for timer values from struct gsm_network. */
+	uint8_t T3122;	/* ASSIGMENT REJECT wait indication */
+
+	/* Periodic channel load measurements are used to maintain T3122. */
+	struct load_counter chan_load_samples[7];
+	int chan_load_samples_idx;
 };
 
 
diff --git a/src/libbsc/abis_rsl.c b/src/libbsc/abis_rsl.c
index eced0e2..3282591 100644
--- a/src/libbsc/abis_rsl.c
+++ b/src/libbsc/abis_rsl.c
@@ -1776,8 +1776,7 @@
 
 /* Format an IMM ASS REJ according to 04.08 Chapter 9.1.20 */
 static int rsl_send_imm_ass_rej(struct gsm_bts *bts,
-				unsigned int num_req_refs,
-				struct gsm48_req_ref *rqd_refs,
+				struct gsm48_req_ref *rqd_ref,
 				uint8_t wait_ind)
 {
 	uint8_t buf[GSM_MACBLOCK_LEN];
@@ -1789,25 +1788,15 @@
 	iar->msg_type = GSM48_MT_RR_IMM_ASS_REJ;
 	iar->page_mode = GSM48_PM_SAME;
 
-	memcpy(&iar->req_ref1, &rqd_refs[0], sizeof(iar->req_ref1));
+	/* Set all request references and wait indications to the same value.
+	 * The BTS will aggregate up to 4 of our ASS REJ messages if possible. */
+	memcpy(&iar->req_ref1, rqd_ref, sizeof(iar->req_ref1));
 	iar->wait_ind1 = wait_ind;
-
-	if (num_req_refs >= 2)
-		memcpy(&iar->req_ref2, &rqd_refs[1], sizeof(iar->req_ref2));
-	else
-		memcpy(&iar->req_ref2, &rqd_refs[0], sizeof(iar->req_ref2));
+	memcpy(&iar->req_ref2, rqd_ref, sizeof(iar->req_ref2));
 	iar->wait_ind2 = wait_ind;
-
-	if (num_req_refs >= 3)
-		memcpy(&iar->req_ref3, &rqd_refs[2], sizeof(iar->req_ref3));
-	else
-		memcpy(&iar->req_ref3, &rqd_refs[0], sizeof(iar->req_ref3));
+	memcpy(&iar->req_ref3, rqd_ref, sizeof(iar->req_ref3));
 	iar->wait_ind3 = wait_ind;
-
-	if (num_req_refs >= 4)
-		memcpy(&iar->req_ref4, &rqd_refs[3], sizeof(iar->req_ref4));
-	else
-		memcpy(&iar->req_ref4, &rqd_refs[0], sizeof(iar->req_ref4));
+	memcpy(&iar->req_ref4, rqd_ref, sizeof(iar->req_ref4));
 	iar->wait_ind4 = wait_ind;
 
 	/* we need to subtract 1 byte from sizeof(*iar) since ia includes the l2_plen field */
@@ -1913,12 +1902,18 @@
 		lchan = lchan_alloc(bts, lctype, 0);
 	}
 	if (!lchan) {
+		uint8_t wait_ind;
 		LOGP(DRSL, LOGL_NOTICE, "BTS %d CHAN RQD: no resources for %s 0x%x\n",
 		     msg->lchan->ts->trx->bts->nr, gsm_lchant_name(lctype), rqd_ref->ra);
 		rate_ctr_inc(&bts->bts_ctrs->ctr[BTS_CTR_CHREQ_NO_CHANNEL]);
-		/* FIXME gather multiple CHAN RQD and reject up to 4 at the same time */
-		if (bts->network->T3122)
-			rsl_send_imm_ass_rej(bts, 1, rqd_ref, bts->network->T3122 & 0xff);
+		if (bts->T3122)
+			wait_ind = bts->T3122;
+		else if (bts->network->T3122)
+			wait_ind = bts->network->T3122 & 0xff;
+		else
+			wait_ind = GSM_T3122_DEFAULT;
+		/* The BTS will gather multiple CHAN RQD and reject up to 4 MS at the same time. */
+		rsl_send_imm_ass_rej(bts, rqd_ref, wait_ind);
 		return 0;
 	}
 
diff --git a/src/libbsc/bsc_init.c b/src/libbsc/bsc_init.c
index c5a75aa..2b1d53b 100644
--- a/src/libbsc/bsc_init.c
+++ b/src/libbsc/bsc_init.c
@@ -523,6 +523,8 @@
 
 	bts->si_common.ncc_permitted = 0xff;
 
+	bts->chan_load_samples_idx = 0;
+
 	/* Initialize the BTS state */
 	gsm_bts_mo_reset(bts);
 
diff --git a/src/libbsc/bsc_vty.c b/src/libbsc/bsc_vty.c
index b4a8e2d..2246349 100644
--- a/src/libbsc/bsc_vty.c
+++ b/src/libbsc/bsc_vty.c
@@ -1711,7 +1711,7 @@
 DECLARE_TIMER(3115, "Currently not used")
 DECLARE_TIMER(3117, "Currently not used")
 DECLARE_TIMER(3119, "Currently not used")
-DECLARE_TIMER(3122, "Waiting time (seconds) after IMM ASS REJECT")
+DECLARE_TIMER(3122, "Default waiting time (seconds) after IMM ASS REJECT")
 DECLARE_TIMER(3141, "Currently not used")
 
 DEFUN_DEPRECATED(cfg_net_dtx,
diff --git a/src/libbsc/chan_alloc.c b/src/libbsc/chan_alloc.c
index 21c81aa..5e2c0ee 100644
--- a/src/libbsc/chan_alloc.c
+++ b/src/libbsc/chan_alloc.c
@@ -593,3 +593,78 @@
 		bts_chan_load(pl, bts);
 }
 
+/* Update T3122 wait indicator based on samples of BTS channel load. */
+void
+bts_update_t3122_chan_load(struct gsm_bts *bts)
+{
+	struct pchan_load pl;
+	uint64_t used = 0;
+	uint32_t total = 0;
+	uint64_t load;
+	uint64_t wait_ind;
+	static const uint8_t min_wait_ind = GSM_T3122_DEFAULT;
+	static const uint8_t max_wait_ind = 128; /* max wait ~2 minutes */
+	int i;
+
+	/* Sum up current load across all channels. */
+	memset(&pl, 0, sizeof(pl));
+	bts_chan_load(&pl, bts);
+	for (i = 0; i < ARRAY_SIZE(pl.pchan); i++) {
+		struct load_counter *lc = &pl.pchan[i];
+
+		/* Ignore samples too large for fixed-point calculations (shouldn't happen). */
+		if (lc->used > UINT16_MAX || lc->total > UINT16_MAX) {
+			LOGP(DRLL, LOGL_NOTICE, "(bts=%d) numbers in channel load sample "
+			     "too large (used=%u / total=%u)\n", bts->nr, lc->used, lc->total);
+			continue;
+		}
+
+		used += lc->used;
+		total += lc->total;
+	}
+
+	/* Check for invalid samples (shouldn't happen). */
+	if (total == 0 || used > total) {
+		LOGP(DRLL, LOGL_NOTICE, "(bts=%d) bogus channel load sample (used=%lu / total=%u)\n",
+		     bts->nr, used, total);
+		bts->T3122 = 0; /* disable override of network-wide default value */
+		bts->chan_load_samples_idx = 0; /* invalidate other samples collected so far */
+		return;
+	}
+
+	/* If we haven't got enough samples yet, store measurement for later use. */
+	if (bts->chan_load_samples_idx < ARRAY_SIZE(bts->chan_load_samples)) {
+		struct load_counter *sample = &bts->chan_load_samples[bts->chan_load_samples_idx++];
+		sample->total = (unsigned int)total;
+		sample->used = (unsigned int)used;
+		return;
+	}
+
+	/* We have enough samples and will overwrite our current samples later. */
+	bts->chan_load_samples_idx = 0;
+
+	/* Add all previous samples to the current sample. */
+	for (i = 0; i < ARRAY_SIZE(bts->chan_load_samples); i++) {
+		struct load_counter *sample = &bts->chan_load_samples[i];
+		total += sample->total;
+		used += sample->used;
+	}
+
+	used <<= 8; /* convert to fixed-point */
+
+	/* Log channel load average. */
+	load = ((used / total) * 100);
+	LOGP(DRLL, LOGL_DEBUG, "(bts=%d) channel load average is %lu.%.2lu%%\n",
+	     bts->nr, (load & 0xffffff00) >> 8, (load & 0xff) / 10);
+
+	/* Calculate new T3122 wait indicator. */
+	wait_ind = ((used / total) * max_wait_ind);
+	wait_ind >>= 8; /* convert from fixed-point to integer */
+	if (wait_ind < min_wait_ind)
+		wait_ind = min_wait_ind;
+	else if (wait_ind > max_wait_ind)
+		wait_ind = max_wait_ind;
+
+	LOGP(DRLL, LOGL_DEBUG, "(bts=%d) T3122 wait indicator set to %lu seconds\n", bts->nr, wait_ind);
+	bts->T3122 = (uint8_t)wait_ind;
+}
diff --git a/src/libbsc/net_init.c b/src/libbsc/net_init.c
index 57d8241..ee47ccf 100644
--- a/src/libbsc/net_init.c
+++ b/src/libbsc/net_init.c
@@ -22,6 +22,22 @@
 #include <osmocom/bsc/bsc_msc_data.h>
 #include <osmocom/bsc/gsm_04_08_utils.h>
 #include <osmocom/bsc/handover_cfg.h>
+#include <osmocom/bsc/chan_alloc.h>
+
+/* XXX hard-coded for now */
+#define T3122_CHAN_LOAD_SAMPLE_INTERVAL 1 /* in seconds */
+
+static void update_t3122_chan_load_timer(void *data)
+{
+	struct gsm_network *net = data;
+	struct gsm_bts *bts;
+
+	llist_for_each_entry(bts, &net->bts_list, list)
+		bts_update_t3122_chan_load(bts);
+
+	/* Keep this timer ticking. */
+	osmo_timer_schedule(&net->t3122_chan_load_timer, T3122_CHAN_LOAD_SAMPLE_INTERVAL, 0);
+}
 
 struct gsm_network *bsc_network_init(void *ctx,
 				     uint16_t country_code,
@@ -60,6 +76,9 @@
 
 	INIT_LLIST_HEAD(&net->bts_list);
 
+	osmo_timer_setup(&net->t3122_chan_load_timer, update_t3122_chan_load_timer, net);
+	osmo_timer_schedule(&net->t3122_chan_load_timer, T3122_CHAN_LOAD_SAMPLE_INTERVAL, 0);
+
 	/* init statistics */
 	net->bsc_ctrs = rate_ctr_group_alloc(net, &bsc_ctrg_desc, 0);
 	if (!net->bsc_ctrs) {
diff --git a/src/libcommon/gsm_data_shared.c b/src/libcommon/gsm_data_shared.c
index e4ec594..3afc67e 100644
--- a/src/libcommon/gsm_data_shared.c
+++ b/src/libcommon/gsm_data_shared.c
@@ -377,6 +377,9 @@
 
 	bts->ho = ho_cfg_init(bts, net->ho);
 
+	/* timer overrides */
+	bts->T3122 = 0; /* not overriden by default */
+
 	return bts;
 }
 
diff --git a/tests/channel/Makefile.am b/tests/channel/Makefile.am
index 12f18f8..aae7a45 100644
--- a/tests/channel/Makefile.am
+++ b/tests/channel/Makefile.am
@@ -29,4 +29,5 @@
 	$(top_builddir)/src/libcommon/libcommon.a \
 	$(LIBOSMOCORE_LIBS) \
 	$(LIBOSMOGSM_LIBS) \
+	$(LIBOSMOABIS_LIBS) \
 	$(NULL)
diff --git a/tests/channel/channel_test.c b/tests/channel/channel_test.c
index 7957b14..933df9c 100644
--- a/tests/channel/channel_test.c
+++ b/tests/channel/channel_test.c
@@ -98,12 +98,9 @@
 	return EXIT_SUCCESS;
 }
 
-void _abis_nm_sendmsg() {}
 void sms_alloc() {}
 void sms_free() {}
-void gsm_net_update_ctype(struct gsm_network *network) {}
 void gsm48_secure_channel() {}
-void paging_request_stop() {}
 void vty_out() {}
 
 void ipa_client_conn_clear_queue() {}

-- 
To view, visit https://gerrit.osmocom.org/6211
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I57e38f6d6ba3b23cc6e1f9520b90261dbb1f1cec
Gerrit-PatchSet: 1
Gerrit-Project: osmo-bsc
Gerrit-Branch: master
Gerrit-Owner: Stefan Sperling <ssperling at sysmocom.de>



More information about the gerrit-log mailing list