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