Change in osmo-bts[master]: Add min/max/std-dev measurement reporting for TOA256

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

Harald Welte gerrit-no-reply at lists.osmocom.org
Fri Jun 29 17:53:20 UTC 2018


Harald Welte has submitted this change and it was merged. ( https://gerrit.osmocom.org/9777 )

Change subject: Add min/max/std-dev measurement reporting for TOA256
......................................................................

Add min/max/std-dev measurement reporting for TOA256

This patch adds extended processing of the high-resolution TOA256
measurement values.  It adds reporting of the following values
for each RSL MEAS REP for uplink measurements:
* minimum TOA256 value during reporting period
* maximum TOA256 value during reporting period
* standard deviation of  TOA256 value during reporting period

Change-Id: Iea4a4781481f77c6163d82dcd71a844a5be87bf2
---
M include/osmo-bts/gsm_data_shared.h
M src/common/measurement.c
M src/common/rsl.c
M tests/meas/meas_test.c
M tests/meas/meas_test.ok
5 files changed, 348 insertions(+), 9 deletions(-)

Approvals:
  Harald Welte: Looks good to me, approved
  Jenkins Builder: Verified



diff --git a/include/osmo-bts/gsm_data_shared.h b/include/osmo-bts/gsm_data_shared.h
index f4fb766..e15abfe 100644
--- a/include/osmo-bts/gsm_data_shared.h
+++ b/include/osmo-bts/gsm_data_shared.h
@@ -127,6 +127,7 @@
 #define MAX_NUM_UL_MEAS	104
 #define LC_UL_M_F_L1_VALID	(1 << 0)
 #define LC_UL_M_F_RES_VALID	(1 << 1)
+#define LC_UL_M_F_OSMO_EXT_VALID (1 << 2)
 
 struct bts_ul_meas {
 	/* BER in units of 0.01%: 10.000 == 100% ber, 0 == 0% ber */
@@ -257,6 +258,15 @@
 		uint8_t l1_info[2];
 		struct gsm_meas_rep_unidir ul_res;
 		int16_t ms_toa256;
+		/* Osmocom extended measurement results, see LC_UL_M_F_EXTD_VALID */
+		struct {
+			/* minimum value of toa256 during measurement period */
+			int16_t toa256_min;
+			/* maximum value of toa256 during measurement period */
+			int16_t toa256_max;
+			/* standard deviation of toa256 value during measurement period */
+			uint16_t toa256_std_dev;
+		} ext;
 	} meas;
 	struct {
 		struct amr_multirate_conf amr_mr;
@@ -317,6 +327,11 @@
 	} ecu_state;
 };
 
+static inline uint8_t lchan_get_ta(const struct gsm_lchan *lchan)
+{
+	return lchan->meas.l1_info[1];
+}
+
 extern const struct value_string lchan_ciph_state_names[];
 static inline const char *lchan_ciph_state_name(uint8_t state) {
 	return get_value_string(lchan_ciph_state_names, state);
diff --git a/src/common/measurement.c b/src/common/measurement.c
index ba7494a..01f1e5d 100644
--- a/src/common/measurement.c
+++ b/src/common/measurement.c
@@ -3,6 +3,7 @@
 #include <errno.h>
 
 #include <osmocom/gsm/gsm_utils.h>
+#include <osmocom/core/utils.h>
 
 #include <osmo-bts/gsm_data.h>
 #include <osmo-bts/logging.h>
@@ -335,6 +336,64 @@
 	return 7;
 }
 
+/* if we clip the TOA value to 12 bits, i.e. toa256=3200,
+ *  -> the maximum deviation can be 2*3200 = 6400
+ *  -> the maximum squared deviation can be 6400^2 = 40960000
+ *  -> the maximum sum of squared deviations can be 104*40960000 = 4259840000
+ *     and hence fit into uint32_t
+ *  -> once the value is divided by 104, it's again below 40960000
+ *     leaving 6 MSBs of freedom, i.e. we could extend by 64, resulting in 2621440000
+ *  -> as a result, the standard deviation could be communicated with up to six bits
+ *     of fractional fixed-point number.
+ */
+
+/* compute Osmocom extended measurements for the given lchan */
+static void lchan_meas_compute_extended(struct gsm_lchan *lchan)
+{
+	/* we assume that lchan_meas_check_compute() has already computed the mean value
+	 * and we can compute the min/max/variance/stddev from this */
+	int i;
+
+	/* each measurement is an int32_t, so the squared difference value must fit in 32bits */
+	/* the sum of the squared values (each up to 32bit) can very easily exceed 32 bits */
+	u_int64_t sq_diff_sum = 0;
+	/* initialize min/max values with their counterpart */
+	lchan->meas.ext.toa256_min = INT16_MAX;
+	lchan->meas.ext.toa256_max = INT16_MIN;
+
+	OSMO_ASSERT(lchan->meas.num_ul_meas);
+
+	/* all computations are done on the relative arrival time of the burst, relative to the
+	 * beginning of its slot. This is of course excluding the TA value that the MS has already
+	 * compensated/pre-empted its transmission */
+
+	/* step 1: compute the sum of the squared difference of each value to mean */
+	for (i = 0; i < lchan->meas.num_ul_meas; i++) {
+		struct bts_ul_meas *m = &lchan->meas.uplink[i];
+		int32_t diff = (int32_t)m->ta_offs_256bits - (int32_t)lchan->meas.ms_toa256;
+		/* diff can now be any value of +65535 to -65535, so we can safely square it,
+		 * but only in unsigned math.  As squaring looses the sign, we can simply drop
+		 * it before squaring, too. */
+		uint32_t diff_abs = labs(diff);
+		uint32_t diff_squared = diff_abs * diff_abs;
+		sq_diff_sum += diff_squared;
+
+		/* also use this loop iteration to compute min/max values */
+		if (m->ta_offs_256bits > lchan->meas.ext.toa256_max)
+			lchan->meas.ext.toa256_max = m->ta_offs_256bits;
+		if (m->ta_offs_256bits < lchan->meas.ext.toa256_min)
+			lchan->meas.ext.toa256_min = m->ta_offs_256bits;
+	}
+	/* step 2: compute the variance (mean of sum of squared differences) */
+	sq_diff_sum = sq_diff_sum / lchan->meas.num_ul_meas;
+	/* as the individual summed values can each not exceed 2^32, and we're
+	 * dividing by the number of summands, the resulting value can also not exceed 2^32 */
+	OSMO_ASSERT(sq_diff_sum <= UINT32_MAX);
+	/* step 3: compute the standard deviation from the variance */
+	lchan->meas.ext.toa256_std_dev = osmo_isqrt32(sq_diff_sum);
+	lchan->meas.flags |= LC_UL_M_F_OSMO_EXT_VALID;
+}
+
 int lchan_meas_check_compute(struct gsm_lchan *lchan, uint32_t fn)
 {
 	struct gsm_meas_rep_unidir *mru;
@@ -410,8 +469,10 @@
 	       mru->sub.rx_qual, num_meas_sub, lchan->meas.num_ul_meas);
 
 	lchan->meas.flags |= LC_UL_M_F_RES_VALID;
-	lchan->meas.num_ul_meas = 0;
 
+	lchan_meas_compute_extended(lchan);
+
+	lchan->meas.num_ul_meas = 0;
 	/* send a signal indicating computation is complete */
 
 	return 1;
diff --git a/src/common/rsl.c b/src/common/rsl.c
index 5d30ca7..8bbf73c 100644
--- a/src/common/rsl.c
+++ b/src/common/rsl.c
@@ -2536,6 +2536,13 @@
 	return (lchan->ms_t_offs >= 0) || (lchan->p_offs >= 0);
 }
 
+struct osmo_bts_supp_meas_info {
+	int16_t toa256_mean;
+	int16_t toa256_min;
+	int16_t toa256_max;
+	uint16_t toa256_std_dev;
+} __attribute__((packed));
+
 /* 8.4.8 MEASUREMENT RESult */
 static int rsl_tx_meas_res(struct gsm_lchan *lchan, uint8_t *l3, int l3_len, const struct lapdm_entity *le)
 {
@@ -2573,16 +2580,23 @@
 						meas_res);
 	lchan->tch.dtx.dl_active = false;
 	if (ie_len >= 3) {
-		if (bts->supp_meas_toa256) {
+		if (bts->supp_meas_toa256 && lchan->meas.flags & LC_UL_M_F_OSMO_EXT_VALID) {
+			struct osmo_bts_supp_meas_info *smi;
+			smi = (struct osmo_bts_supp_meas_info *) &meas_res[ie_len];
+			ie_len += sizeof(struct osmo_bts_supp_meas_info);
 			/* append signed 16bit value containing MS timing offset in 1/256th symbols
 			 * in the vendor-specific "Supplementary Measurement Information" part of
-			 * the uplink measurements IE.  This is the current offset *relative* to the
-			 * TA which the MS has already applied.  So if you want to know the total
-			 * propagation time between MS and BTS, you need to add the actual TA value
-			 * used (from L1_INFO below, in full symbols) plus the ms_toa256 value
-			 * in 1/256 symbol periods. */
-			meas_res[ie_len++] = lchan->meas.ms_toa256 >> 8;
-			meas_res[ie_len++] = lchan->meas.ms_toa256 & 0xff;
+			 * the uplink measurements IE.  The lchan->meas.ext members are the current
+			 * offset *relative* to the TA which the MS has already applied.  As we want
+			 * to know the total propagation time between MS and BTS, we need to add
+			 * the actual TA value applied by the MS plus the respective toa256 value in
+			 * 1/256 symbol periods. */
+			int16_t ta256 = lchan_get_ta(lchan) * 256;
+			smi->toa256_mean = htons(ta256 + lchan->meas.ms_toa256);
+			smi->toa256_min = htons(ta256 + lchan->meas.ext.toa256_min);
+			smi->toa256_max = htons(ta256 + lchan->meas.ext.toa256_max);
+			smi->toa256_std_dev = htons(lchan->meas.ext.toa256_std_dev);
+			lchan->meas.flags &= ~LC_UL_M_F_OSMO_EXT_VALID;
 		}
 		msgb_tlv_put(msg, RSL_IE_UPLINK_MEAS, ie_len, meas_res);
 		lchan->meas.flags &= ~LC_UL_M_F_RES_VALID;
diff --git a/tests/meas/meas_test.c b/tests/meas/meas_test.c
index cbc673f..e889345 100644
--- a/tests/meas/meas_test.c
+++ b/tests/meas/meas_test.c
@@ -3,6 +3,7 @@
 
 #include <osmocom/core/talloc.h>
 #include <osmocom/core/application.h>
+#include <osmocom/gsm/gsm_utils.h>
 
 #include <osmo-bts/gsm_data.h>
 #include <osmo-bts/logging.h>
@@ -62,6 +63,214 @@
 	OSMO_ASSERT(tsmap_result == tsmap);
 }
 
+#define ULM(ber, ta, neg_rssi) \
+	{ .ber10k = (ber), .ta_offs_256bits = (ta), .c_i = 1.0, .is_sub = 0, .inv_rssi = (neg_rssi) }
+
+struct meas_testcase {
+	const char *name;
+	/* input data */
+	const struct bts_ul_meas *ulm;
+	unsigned int ulm_count;
+	uint32_t final_fn;
+	/* results */
+	struct {
+		int success;
+		uint8_t rx_lev_full;
+		uint8_t rx_qual_full;
+		int16_t toa256_mean;
+		int16_t toa256_min;
+		int16_t toa256_max;
+		uint16_t toa256_std_dev;
+	} res;
+};
+
+static struct bts_ul_meas ulm1[] = {
+	ULM(0, 0, 90),
+	ULM(0, 256, 90),
+	ULM(0, -256, 90),
+};
+static const struct meas_testcase mtc1 = {
+	.name = "TOA256 Min-Max negative/positive",
+	.ulm = ulm1,
+	.ulm_count = ARRAY_SIZE(ulm1),
+	.final_fn = 25,
+	.res = {
+		.success = 1,
+		.rx_lev_full = 110-90,
+		.rx_qual_full = 0,
+		.toa256_mean = 0,
+		.toa256_max = 256,
+		.toa256_min = -256,
+		.toa256_std_dev = 209,
+	},
+};
+
+
+static struct bts_ul_meas ulm2[] = {
+	ULM(0, 256, 90),
+	ULM(0, 258, 90),
+	ULM(0, 254, 90),
+	ULM(0, 258, 90),
+	ULM(0, 254, 90),
+	ULM(0, 256, 90),
+};
+static const struct meas_testcase mtc2 = {
+	.name = "TOA256 small jitter around 256",
+	.ulm = ulm2,
+	.ulm_count = ARRAY_SIZE(ulm2),
+	.final_fn = 25,
+	.res = {
+		.success = 1,
+		.rx_lev_full = 110-90,
+		.rx_qual_full = 0,
+		.toa256_mean = 256,
+		.toa256_max = 258,
+		.toa256_min = 254,
+		.toa256_std_dev = 1,
+	},
+};
+
+static struct bts_ul_meas ulm3[] = {
+	ULM(0, 0, 90),
+	ULM(0, 0, 80),
+	ULM(0, 0, 80),
+	ULM(0, 0, 100),
+	ULM(0, 0, 100),
+};
+static const struct meas_testcase mtc3 = {
+	.name = "RxLEv averaging",
+	.ulm = ulm3,
+	.ulm_count = ARRAY_SIZE(ulm3),
+	.final_fn = 25,
+	.res = {
+		.success = 1,
+		.rx_lev_full = 110-90,
+		.rx_qual_full = 0,
+		.toa256_mean = 0,
+		.toa256_max = 0,
+		.toa256_min = 0,
+		.toa256_std_dev = 0,
+	},
+};
+
+static struct bts_ul_meas ulm4[] = {
+};
+static const struct meas_testcase mtc4 = {
+	.name = "Empty measurements",
+	.ulm = ulm4,
+	.ulm_count = ARRAY_SIZE(ulm4),
+	.final_fn = 25,
+	.res = {
+		.success = 0,
+		.rx_lev_full = 0,
+		.rx_qual_full = 0,
+		.toa256_mean = 0,
+		.toa256_max = 0,
+		.toa256_min = 0,
+		.toa256_std_dev = 0,
+	},
+};
+
+static struct bts_ul_meas ulm5[] = {
+	/* one 104 multiframe can at max contain 26 blocks (TCH/F),
+	 * each of which can at maximum be 64 bits in advance (TA range) */
+	ULM(0, 64*256, 90),
+	ULM(0, 64*256, 90),
+	ULM(0, 64*256, 90),
+	ULM(0, 64*256, 90),
+	ULM(0, 64*256, 90),
+	ULM(0, 64*256, 90),
+	ULM(0, 64*256, 90),
+	ULM(0, 64*256, 90),
+	ULM(0, 64*256, 90),
+	ULM(0, 64*256, 90),
+	ULM(0, 64*256, 90),
+	ULM(0, 64*256, 90),
+	ULM(0, 64*256, 90),
+	ULM(0, 64*256, 90),
+	ULM(0, 64*256, 90),
+	ULM(0, 64*256, 90),
+	ULM(0, 64*256, 90),
+	ULM(0, 64*256, 90),
+	ULM(0, 64*256, 90),
+	ULM(0, 64*256, 90),
+	ULM(0, 64*256, 90),
+	ULM(0, 64*256, 90),
+	ULM(0, 64*256, 90),
+	ULM(0, 64*256, 90),
+	ULM(0, 64*256, 90),
+	ULM(0, 64*256, 90),
+};
+static const struct meas_testcase mtc5 = {
+	.name = "TOA256 26 blocks with max TOA256",
+	.ulm = ulm5,
+	.ulm_count = ARRAY_SIZE(ulm5),
+	.final_fn = 25,
+	.res = {
+		.success = 1,
+		.rx_lev_full = 110-90,
+		.rx_qual_full = 0,
+		.toa256_mean = 64*256,
+		.toa256_max = 64*256,
+		.toa256_min = 64*256,
+		.toa256_std_dev = 0,
+	},
+};
+
+
+static void reset_lchan_meas(struct gsm_lchan *lchan)
+{
+	lchan->state = LCHAN_S_ACTIVE;
+	memset(&lchan->meas, 0, sizeof(lchan->meas));
+}
+
+static void test_meas_compute(const struct meas_testcase *mtc)
+{
+	struct gsm_lchan *lchan = &trx->ts[1].lchan[0];
+	unsigned int i;
+	unsigned int fn = 0;
+
+	printf("\nMeasurement Compute Test %s\n", mtc->name);
+
+	lchan->ts->pchan = GSM_PCHAN_TCH_F;
+	reset_lchan_meas(lchan);
+
+	/* feed uplink measurements into the code */
+	for (i = 0; i < mtc->ulm_count; i++) {
+		lchan_new_ul_meas(lchan, (struct bts_ul_meas *) &mtc->ulm[i], fn);
+		fn += 1;
+	}
+
+	/* compute the results */
+	OSMO_ASSERT(lchan_meas_check_compute(lchan, mtc->final_fn) == mtc->res.success);
+	if (!mtc->res.success) {
+		OSMO_ASSERT(!(lchan->meas.flags & LC_UL_M_F_RES_VALID));
+	} else {
+		OSMO_ASSERT(lchan->meas.flags & (LC_UL_M_F_RES_VALID|LC_UL_M_F_OSMO_EXT_VALID));
+		printf("meas.ext.toa256_min      | %6d | %6d\n",
+			lchan->meas.ext.toa256_min, mtc->res.toa256_min);
+		printf("meas.ext.toa256_max      | %6d | %6d\n",
+			lchan->meas.ext.toa256_max, mtc->res.toa256_max);
+		printf("meas.ms_toa256           | %6d | %6d\n",
+			lchan->meas.ms_toa256, mtc->res.toa256_mean);
+		printf("meas.ext.toa256_std_dev  | %6u | %6u\n",
+			lchan->meas.ext.toa256_std_dev, mtc->res.toa256_std_dev);
+		printf("meas.ul_res.full.rx_lev  | %6u | %6u\n",
+			lchan->meas.ul_res.full.rx_lev, mtc->res.rx_lev_full);
+		printf("meas.ul_res.full.rx_qual | %6u | %6u\n",
+			lchan->meas.ul_res.full.rx_qual, mtc->res.rx_qual_full);
+
+		if ((lchan->meas.ext.toa256_min != mtc->res.toa256_min) ||
+		    (lchan->meas.ext.toa256_max != mtc->res.toa256_max) ||
+		    (lchan->meas.ms_toa256 != mtc->res.toa256_mean) ||
+		    (lchan->meas.ext.toa256_std_dev != mtc->res.toa256_std_dev) ||
+		    (lchan->meas.ul_res.full.rx_lev != mtc->res.rx_lev_full)) {
+			fprintf(stderr, "%s: Unexpected measurement result!\n", mtc->name);
+		}
+	}
+
+}
+
 int main(int argc, char **argv)
 {
 	void *tall_bts_ctx;
@@ -111,6 +320,12 @@
 	test_fn_sample(test_fn_tch_h_ts_6_ss0_ss1, ARRAY_SIZE(test_fn_tch_h_ts_6_ss0_ss1), GSM_PCHAN_TCH_H, (1 << 6));
 	test_fn_sample(test_fn_tch_h_ts_7_ss0_ss1, ARRAY_SIZE(test_fn_tch_h_ts_7_ss0_ss1), GSM_PCHAN_TCH_H, (1 << 7));
 
+	test_meas_compute(&mtc1);
+	test_meas_compute(&mtc2);
+	test_meas_compute(&mtc3);
+	test_meas_compute(&mtc4);
+	test_meas_compute(&mtc5);
+
 	printf("Success\n");
 
 	return 0;
diff --git a/tests/meas/meas_test.ok b/tests/meas/meas_test.ok
index 6dbda54..026899d 100644
--- a/tests/meas/meas_test.ok
+++ b/tests/meas/meas_test.ok
@@ -539,4 +539,38 @@
 Testing: ts[7]->lchan[1], fn=15079=>015079/11/25/34/23, fn%104=103, rc=1, delta=13
 Testing: ts[7]->lchan[0], fn=15170=>015170/11/12/23/14, fn%104=90, rc=1, delta=91
 Testing: ts[7]->lchan[1], fn=15183=>015183/11/25/36/27, fn%104=103, rc=1, delta=13
+
+Measurement Compute Test TOA256 Min-Max negative/positive
+meas.ext.toa256_min      |   -256 |   -256
+meas.ext.toa256_max      |    256 |    256
+meas.ms_toa256           |      0 |      0
+meas.ext.toa256_std_dev  |    209 |    209
+meas.ul_res.full.rx_lev  |     20 |     20
+meas.ul_res.full.rx_qual |      0 |      0
+
+Measurement Compute Test TOA256 small jitter around 256
+meas.ext.toa256_min      |    254 |    254
+meas.ext.toa256_max      |    258 |    258
+meas.ms_toa256           |    256 |    256
+meas.ext.toa256_std_dev  |      1 |      1
+meas.ul_res.full.rx_lev  |     20 |     20
+meas.ul_res.full.rx_qual |      0 |      0
+
+Measurement Compute Test RxLEv averaging
+meas.ext.toa256_min      |      0 |      0
+meas.ext.toa256_max      |      0 |      0
+meas.ms_toa256           |      0 |      0
+meas.ext.toa256_std_dev  |      0 |      0
+meas.ul_res.full.rx_lev  |     20 |     20
+meas.ul_res.full.rx_qual |      0 |      0
+
+Measurement Compute Test Empty measurements
+
+Measurement Compute Test TOA256 26 blocks with max TOA256
+meas.ext.toa256_min      |  16384 |  16384
+meas.ext.toa256_max      |  16384 |  16384
+meas.ms_toa256           |  16384 |  16384
+meas.ext.toa256_std_dev  |      0 |      0
+meas.ul_res.full.rx_lev  |     20 |     20
+meas.ul_res.full.rx_qual |      0 |      0
 Success

-- 
To view, visit https://gerrit.osmocom.org/9777
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings

Gerrit-Project: osmo-bts
Gerrit-Branch: master
Gerrit-MessageType: merged
Gerrit-Change-Id: Iea4a4781481f77c6163d82dcd71a844a5be87bf2
Gerrit-Change-Number: 9777
Gerrit-PatchSet: 3
Gerrit-Owner: Harald Welte <laforge at gnumonks.org>
Gerrit-Reviewer: Harald Welte <laforge at gnumonks.org>
Gerrit-Reviewer: Jenkins Builder
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20180629/fd3eee27/attachment.htm>


More information about the gerrit-log mailing list