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>