Change in osmo-bts[master]: osmo-bts-trx/scheduler: refactor Uplink measurement processing

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

fixeria gerrit-no-reply at lists.osmocom.org
Fri Oct 18 20:49:05 UTC 2019


fixeria has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-bts/+/15807 )


Change subject: osmo-bts-trx/scheduler: refactor Uplink measurement processing
......................................................................

osmo-bts-trx/scheduler: refactor Uplink measurement processing

So far we used to store the sums of ToA, RSSI, and C/I measurements
in the logical channel state, and after decoding of a block, we did
calculate the average. This approach works fine for xCCH and PDTCH,
but when it comes to block-diagonal interleaving (which is used on
TCH/F and TCH/H channels), the results are incorrect.

Instead of calculating the sum of measurements on the fly, let's
push them onto a stack (the measurement history), and optionally
keep the last N measurements in there after decoding of a block.

The proposed approach will allow us to reduce the code duplication
and get much more accurate Uplink measurement reports. However,
there is a spoon of tar: records of the measurement history are
getting allocated on heap every time we receive an Uplink burst.

These frequent allocations may introduce a negative impact on the
overall performance level, but we can use a talloc pool to reduce
possible delays and potential fragmentation.

Change-Id: I6bc511223069f66b49109d3267bee7bd89585713
---
M include/osmo-bts/scheduler.h
M src/osmo-bts-trx/scheduler_trx.c
2 files changed, 145 insertions(+), 78 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/osmo-bts refs/changes/07/15807/1

diff --git a/include/osmo-bts/scheduler.h b/include/osmo-bts/scheduler.h
index 3100a1d..e6ec37d 100644
--- a/include/osmo-bts/scheduler.h
+++ b/include/osmo-bts/scheduler.h
@@ -69,6 +69,15 @@
 	TRX_BURST_8PSK,
 };
 
+/* A set of measurements attached to a burst */
+struct l1sched_meas_set {
+	struct llist_head	list;		/* Link to the measurement history */
+
+	int16_t			toa256;		/* Timing of Arrival (1/256 of a symbol) */
+	int16_t			ci_cb;		/* Carrier-to-Interference (cB) */
+	float			rssi;		/* RSSI (dBm) */
+};
+
 /* States each channel on a multiframe */
 struct l1sched_chan_state {
 	/* scheduler */
@@ -79,14 +88,6 @@
 	uint32_t		ul_first_fn;	/* fn of first burst */
 	uint8_t			ul_mask;	/* mask of received bursts */
 
-	/* measurements */
-	uint8_t			rssi_num;	/* number of RSSI values */
-	float			rssi_sum;	/* sum of RSSI values */
-	uint8_t			toa_num;	/* number of TOA values */
-	int32_t			toa256_sum;	/* sum of TOA values (1/256 symbol) */
-	uint8_t			ci_cb_num;	/* number of C/I values */
-	int32_t			ci_cb_sum;	/* sum of C/I values (in centiBels) */
-
 	/* loss detection */
 	uint8_t			lost_frames;	/* how many L2 frames were lost */
 	uint32_t		last_tdma_fn;	/* last processed TDMA frame number */
@@ -121,6 +122,10 @@
 
 	/* measurements */
 	struct {
+		struct llist_head hist;		/* History of measurements (see l1sched_meas_set) */
+		unsigned int num;		/* Number of measurements in history */
+
+		/* FIXME: keep all measurements in the history (see above) */
 		uint8_t		clock;		/* cyclic clock counter */
 		int8_t		rssi[32];	/* last RSSI values */
 		int		rssi_count;	/* received RSSI values */
diff --git a/src/osmo-bts-trx/scheduler_trx.c b/src/osmo-bts-trx/scheduler_trx.c
index 8662a14..d37dd51 100644
--- a/src/osmo-bts-trx/scheduler_trx.c
+++ b/src/osmo-bts-trx/scheduler_trx.c
@@ -887,6 +887,77 @@
 	return 0;
 }
 
+/* Add a set of measurements to the head of the history. */
+static void l1sched_meas_push(struct l1sched_chan_state *chan_state,
+			      const struct trx_ul_burst_ind *bi)
+{
+	struct l1sched_meas_set *set;
+
+	/* TODO: unfortunately, we cannot use chan_state as the context :/
+	 * TODO: should we use a talloc pool for such allocations? */
+	set = talloc(tall_bts_ctx, struct l1sched_meas_set);
+	OSMO_ASSERT(set != NULL);
+
+	set->toa256 = bi->toa256;
+	set->rssi = bi->rssi;
+
+	/* Optional fields */
+	set->ci_cb = (bi->flags & TRX_BI_F_CI_CB) ? bi->ci_cb : 0;
+
+	llist_add(&set->list, &chan_state->meas.hist);
+	chan_state->meas.num++;
+}
+
+/* Average a given number of measurements from the history,
+ * store the results in a caller-allocated set. */
+static void l1sched_meas_average(const struct l1sched_chan_state *chan_state,
+				 struct l1sched_meas_set *result,
+				 unsigned int num)
+{
+	struct l1sched_meas_set *set;
+	int toa256_sum = 0;
+	int ci_cb_sum = 0;
+	int rssi_sum = 0;
+
+	/* There shall be at least one set */
+	OSMO_ASSERT(chan_state->meas.num > 0);
+	/* Prevent division by zero */
+	OSMO_ASSERT(num > 0);
+
+	/* There can be less records in the history */
+	if (chan_state->meas.num < num)
+		num = chan_state->meas.num;
+
+	/* Calculate the sum of measurements */
+	llist_for_each_entry(set, &chan_state->meas.hist, list) {
+		toa256_sum += set->toa256;
+		ci_cb_sum += set->ci_cb;
+		rssi_sum += set->rssi;
+
+		if (--num == 0)
+			break;
+	}
+
+	/* Calculate the average */
+	result->toa256 = toa256_sum / num;
+	result->ci_cb = ci_cb_sum / num;
+	result->rssi = rssi_sum / num;
+}
+
+/* Reduce amount of measurements in the history to a given number. */
+static void l1sched_meas_squeeze(struct l1sched_chan_state *chan_state,
+				 unsigned int num)
+{
+	struct llist_head *hist = &chan_state->meas.hist;
+	struct l1sched_meas_set *set;
+
+	while (!llist_empty(hist) && chan_state->meas.num-- > num) {
+		set = llist_last_entry(hist, struct l1sched_meas_set, list);
+		llist_del(&set->list);
+		talloc_free(set);
+	}
+}
+
 /*! \brief a single (SDCCH/SACCH) burst was received by the PHY, process it */
 int rx_data_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
 	       uint8_t bid, const struct trx_ul_burst_ind *bi)
@@ -896,15 +967,9 @@
 	sbit_t *burst, **bursts_p = &chan_state->ul_bursts;
 	uint32_t *first_fn = &chan_state->ul_first_fn;
 	uint8_t *mask = &chan_state->ul_mask;
-	float *rssi_sum = &chan_state->rssi_sum;
-	uint8_t *rssi_num = &chan_state->rssi_num;
-	int32_t *toa256_sum = &chan_state->toa256_sum;
-	uint8_t *toa_num = &chan_state->toa_num;
-	int32_t *ci_cb_sum = &chan_state->ci_cb_sum;
-	uint8_t *ci_cb_num = &chan_state->ci_cb_num;
 	uint8_t l2[GSM_MACBLOCK_LEN], l2_len;
+	struct l1sched_meas_set meas_set;
 	int n_errors, n_bits_total;
-	int16_t lqual_cb;
 	uint16_t ber10k;
 	int rc;
 
@@ -920,6 +985,8 @@
 		*bursts_p = talloc_zero_size(tall_bts_ctx, 464);
 		if (!*bursts_p)
 			return -ENOMEM;
+		/* HACK: also initialize the measurement history */
+		INIT_LLIST_HEAD(&chan_state->meas.hist);
 	}
 
 	/* clear burst & store frame number of first burst */
@@ -927,26 +994,13 @@
 		memset(*bursts_p, 0, 464);
 		*mask = 0x0;
 		*first_fn = bi->fn;
-		*rssi_sum = 0;
-		*rssi_num = 0;
-		*toa256_sum = 0;
-		*toa_num = 0;
-		*ci_cb_sum = 0;
-		*ci_cb_num = 0;
 	}
 
-	/* update mask + RSSI */
+	/* store the measurements */
+	l1sched_meas_push(chan_state, bi);
+
+	/* update the mask */
 	*mask |= (1 << bid);
-	*rssi_sum += bi->rssi;
-	(*rssi_num)++;
-	*toa256_sum += bi->toa256;
-	(*toa_num)++;
-
-	/* C/I: Carrier-to-Interference ratio (in centiBels) */
-	if (bi->flags & TRX_BI_F_CI_CB) {
-		*ci_cb_sum += bi->ci_cb;
-		(*ci_cb_num)++;
-	}
 
 	/* copy burst to buffer of 4 bursts */
 	burst = *bursts_p + bid * 116;
@@ -987,19 +1041,21 @@
 	} else
 		l2_len = GSM_MACBLOCK_LEN;
 
+	/* Average measurements of the last 4 bursts */
+	l1sched_meas_average(chan_state, &meas_set, 4);
+	/* Nothing to store for the next block */
+	l1sched_meas_squeeze(chan_state, 0);
+
 	/* Send uplink measurement information to L2 */
 	l1if_process_meas_res(l1t->trx, bi->tn, *first_fn,
 			      trx_chan_desc[chan].chan_nr | bi->tn,
 			      n_errors, n_bits_total,
-			      *rssi_sum / *rssi_num,
-			      *toa256_sum / *toa_num);
-	lqual_cb = *ci_cb_num ? (*ci_cb_sum / *ci_cb_num) : 0;
+			      meas_set.rssi, meas_set.toa256);
 	ber10k = compute_ber10k(n_bits_total, n_errors);
 	return _sched_compose_ph_data_ind(l1t, bi->tn, *first_fn,
 					  chan, l2, l2_len,
-					  *rssi_sum / *rssi_num,
-					  *toa256_sum / *toa_num,
-					  lqual_cb, ber10k,
+					  meas_set.rssi, meas_set.toa256,
+					  meas_set.ci_cb, ber10k,
 					  PRES_INFO_UNKNOWN);
 }
 
@@ -1012,15 +1068,9 @@
 	sbit_t *burst, **bursts_p = &chan_state->ul_bursts;
 	uint32_t *first_fn = &chan_state->ul_first_fn;
 	uint8_t *mask = &chan_state->ul_mask;
-	float *rssi_sum = &chan_state->rssi_sum;
-	uint8_t *rssi_num = &chan_state->rssi_num;
-	int32_t *toa256_sum = &chan_state->toa256_sum;
-	uint8_t *toa_num = &chan_state->toa_num;
-	int32_t *ci_cb_sum = &chan_state->ci_cb_sum;
-	uint8_t *ci_cb_num = &chan_state->ci_cb_num;
 	uint8_t l2[EGPRS_0503_MAX_BYTES];
+	struct l1sched_meas_set meas_set;
 	int n_errors, n_bursts_bits, n_bits_total;
-	int16_t lqual_cb;
 	uint16_t ber10k;
 	int rc;
 
@@ -1033,6 +1083,8 @@
 					     GSM0503_EGPRS_BURSTS_NBITS);
 		if (!*bursts_p)
 			return -ENOMEM;
+		/* HACK: also initialize the measurement history */
+		INIT_LLIST_HEAD(&chan_state->meas.hist);
 	}
 
 	/* clear burst */
@@ -1040,26 +1092,13 @@
 		memset(*bursts_p, 0, GSM0503_EGPRS_BURSTS_NBITS);
 		*mask = 0x0;
 		*first_fn = bi->fn;
-		*rssi_sum = 0;
-		*rssi_num = 0;
-		*toa256_sum = 0;
-		*toa_num = 0;
-		*ci_cb_sum = 0;
-		*ci_cb_num = 0;
 	}
 
-	/* update mask + rssi */
+	/* store the measurements */
+	l1sched_meas_push(chan_state, bi);
+
+	/* update the mask */
 	*mask |= (1 << bid);
-	*rssi_sum += bi->rssi;
-	(*rssi_num)++;
-	*toa256_sum += bi->toa256;
-	(*toa_num)++;
-
-	/* C/I: Carrier-to-Interference ratio (in centiBels) */
-	if (bi->flags & TRX_BI_F_CI_CB) {
-		*ci_cb_sum += bi->ci_cb;
-		(*ci_cb_num)++;
-	}
 
 	/* copy burst to buffer of 4 bursts */
 	if (bi->burst_len == EGPRS_BURST_LEN) {
@@ -1100,13 +1139,16 @@
 				  &n_errors, &n_bits_total);
 	}
 
+	/* Average measurements of the last 4 bursts */
+	l1sched_meas_average(chan_state, &meas_set, 4);
+	/* Nothing to store for the next block */
+	l1sched_meas_squeeze(chan_state, 0);
 
 	/* Send uplink measurement information to L2 */
 	l1if_process_meas_res(l1t->trx, bi->tn, *first_fn,
 		trx_chan_desc[chan].chan_nr | bi->tn,
 		n_errors, n_bits_total,
-		*rssi_sum / *rssi_num,
-		*toa256_sum / *toa_num);
+		meas_set.rssi, meas_set.toa256);
 
 	if (rc <= 0) {
 		LOGL1S(DL1P, LOGL_DEBUG, l1t, bi->tn, chan, bi->fn,
@@ -1115,13 +1157,11 @@
 		return 0;
 	}
 
-	lqual_cb = *ci_cb_num ? (*ci_cb_sum / *ci_cb_num) : 0;
 	ber10k = compute_ber10k(n_bits_total, n_errors);
 	return _sched_compose_ph_data_ind(l1t, bi->tn,
 					  *first_fn, chan, l2, rc,
-					  *rssi_sum / *rssi_num,
-					  *toa256_sum / *toa_num,
-					  lqual_cb, ber10k,
+					  meas_set.rssi, meas_set.toa256,
+					  meas_set.ci_cb, ber10k,
 					  PRES_INFO_BOTH);
 }
 
@@ -1137,6 +1177,7 @@
 	uint8_t rsl_cmode = chan_state->rsl_cmode;
 	uint8_t tch_mode = chan_state->tch_mode;
 	uint8_t tch_data[128]; /* just to be safe */
+	struct l1sched_meas_set meas_set;
 	int rc, amr = 0;
 	int n_errors, n_bits_total;
 	bool bfi_flag = false;
@@ -1155,6 +1196,8 @@
 		*bursts_p = talloc_zero_size(tall_bts_ctx, 928);
 		if (!*bursts_p)
 			return -ENOMEM;
+		/* HACK: also initialize the measurement history */
+		INIT_LLIST_HEAD(&chan_state->meas.hist);
 	}
 
 	/* clear burst */
@@ -1164,6 +1207,9 @@
 		*first_fn = bi->fn;
 	}
 
+	/* store the measurements */
+	l1sched_meas_push(chan_state, bi);
+
 	/* update mask */
 	*mask |= (1 << bid);
 
@@ -1225,11 +1271,16 @@
 	}
 	memcpy(*bursts_p, *bursts_p + 464, 464);
 
+	/* Average measurements of the last 8 bursts */
+	l1sched_meas_average(chan_state, &meas_set, 8);
+	/* Keep measurements of the last 4 bursts */
+	l1sched_meas_squeeze(chan_state, 4);
+
 	/* Send uplink measurement information to L2 */
 	l1if_process_meas_res(l1t->trx, bi->tn, *first_fn,
 			      trx_chan_desc[chan].chan_nr | bi->tn,
 			      n_errors, n_bits_total,
-			      bi->rssi, bi->toa256);
+			      meas_set.rssi, meas_set.toa256);
 
 	/* Check if the frame is bad */
 	if (rc < 0) {
@@ -1257,10 +1308,9 @@
 			/* FIXME: this calculation is wrong */
 			(bi->fn + GSM_HYPERFRAME - 7) % GSM_HYPERFRAME, chan,
 			tch_data + amr, GSM_MACBLOCK_LEN,
-			/* FIXME: AVG RSSI and ToA256 */
-			bi->rssi, bi->toa256,
-			0 /* FIXME: AVG C/I */,
-			ber10k, PRES_INFO_UNKNOWN);
+			meas_set.rssi, meas_set.toa256,
+			meas_set.ci_cb, ber10k,
+			PRES_INFO_UNKNOWN);
 bfi:
 		if (rsl_cmode == RSL_CMOD_SPD_SPEECH) {
 			/* indicate bad frame */
@@ -1332,6 +1382,7 @@
 	uint8_t rsl_cmode = chan_state->rsl_cmode;
 	uint8_t tch_mode = chan_state->tch_mode;
 	uint8_t tch_data[128]; /* just to be safe */
+	struct l1sched_meas_set meas_set;
 	int rc, amr = 0;
 	int n_errors, n_bits_total;
 	bool bfi_flag = false;
@@ -1355,6 +1406,8 @@
 		*bursts_p = talloc_zero_size(tall_bts_ctx, 696);
 		if (!*bursts_p)
 			return -ENOMEM;
+		/* HACK: also initialize the measurement history */
+		INIT_LLIST_HEAD(&chan_state->meas.hist);
 	}
 
 	/* clear burst */
@@ -1364,6 +1417,9 @@
 		*first_fn = bi->fn;
 	}
 
+	/* store the measurements */
+	l1sched_meas_push(chan_state, bi);
+
 	/* update mask */
 	*mask |= (1 << bid);
 
@@ -1436,11 +1492,18 @@
 	memcpy(*bursts_p, *bursts_p + 232, 232);
 	memcpy(*bursts_p + 232, *bursts_p + 464, 232);
 
+	/* Average measurements of either the last 4 bursts (speech),
+	 * or the last 6 bursts (in case if FACCH/H was received). */
+	l1sched_meas_average(chan_state, &meas_set, rc == GSM_MACBLOCK_LEN ? 6 : 4);
+	/* Keep measurements of the last 2 bursts */
+	l1sched_meas_squeeze(chan_state, 2);
+
 	/* Send uplink measurement information to L2 */
 	l1if_process_meas_res(l1t->trx, bi->tn,
 		*first_fn /* FIXME: this is wrong */,
 		trx_chan_desc[chan].chan_nr | bi->tn,
-		n_errors, n_bits_total, bi->rssi, bi->toa256);
+		n_errors, n_bits_total,
+		meas_set.rssi, meas_set.toa256);
 
 	/* Check if the frame is bad */
 	if (rc < 0) {
@@ -1469,10 +1532,9 @@
 			/* FIXME: what the hell is this?!? */
 			(bi->fn + GSM_HYPERFRAME - 10 - ((bi->fn % 26) >= 19)) % GSM_HYPERFRAME, chan,
 			tch_data + amr, GSM_MACBLOCK_LEN,
-			/* FIXME: AVG both RSSI and ToA */
-			bi->rssi, bi->toa256,
-			0 /* FIXME: AVG C/I */,
-			ber10k, PRES_INFO_UNKNOWN);
+			meas_set.rssi, meas_set.toa256,
+			meas_set.ci_cb, ber10k,
+			PRES_INFO_UNKNOWN);
 bfi:
 		/* FIXME: a FACCH/H frame replaces two speech frames,
 		 * so we actually need to send two bad frame indications! */

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

Gerrit-Project: osmo-bts
Gerrit-Branch: master
Gerrit-Change-Id: I6bc511223069f66b49109d3267bee7bd89585713
Gerrit-Change-Number: 15807
Gerrit-PatchSet: 1
Gerrit-Owner: fixeria <axilirator at gmail.com>
Gerrit-MessageType: newchange
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20191018/1f8c6a40/attachment.htm>


More information about the gerrit-log mailing list