Hello Jenkins Builder, I'd like you to reexamine a change. Please visit
https://gerrit.osmocom.org/3935 to look at the new patch set (#3). Simplify TS alloc: move slot check into functions Move timeslot applicability check outside of nested for loop into separate functions and document them. This allows us to clarify types used in TS-related computations. Change-Id: Ic39e848da47dc11357782362fdf6206d2c1457c2 Related: OS#2282 --- M src/gprs_rlcmac_ts_alloc.cpp 1 file changed, 96 insertions(+), 73 deletions(-) git pull ssh://gerrit.osmocom.org:29418/osmo-pcu refs/changes/35/3935/3 diff --git a/src/gprs_rlcmac_ts_alloc.cpp b/src/gprs_rlcmac_ts_alloc.cpp index 8311e22..f4c4ef0 100644 --- a/src/gprs_rlcmac_ts_alloc.cpp +++ b/src/gprs_rlcmac_ts_alloc.cpp @@ -139,11 +139,11 @@ return -1; } -static int find_possible_pdchs(const struct gprs_rlcmac_trx *trx, size_t max_slots, uint8_t mask, - const char *mask_reason = NULL) +static uint8_t find_possible_pdchs(const struct gprs_rlcmac_trx *trx, uint8_t max_slots, uint8_t mask, + const char *mask_reason = NULL) { unsigned ts; - int valid_ts_set = 0; + uint8_t valid_ts_set = 0; int8_t last_tsc = -1; /* must be signed */ for (ts = 0; ts < ARRAY_SIZE(trx->pdch); ts++) { @@ -422,7 +422,7 @@ int trx_no; int tfi = -1; int usf = -1; - int mask = 0xff; + uint8_t mask = 0xff; const char *mask_reason = NULL; const GprsMs *ms = ms_; const gprs_rlcmac_tbf *tbf = tbf_; @@ -506,7 +506,7 @@ * \param[in] tx_window Transmit window * \returns non-negative capacity */ -static inline unsigned compute_capacity(const struct gprs_rlcmac_trx *trx, int rx_window, int tx_window) +static inline unsigned compute_capacity(const struct gprs_rlcmac_trx *trx, int16_t rx_window, int16_t tx_window) { const struct gprs_rlcmac_pdch *pdch; unsigned ts, capacity = 0; @@ -526,6 +526,84 @@ return capacity; } +/*! Decide if a given slot should be skipped by multislot allocator + * + * \param[in] ms_class Pointer to MS Class object + * \param[in] check_tr Flag indicating whether we should check for Tra or Tta parameters for a given MS class + * \param[in] rx_window Receive window + * \param[in] rx_slot_count Number of TS in RX + * \param[in] tx_window Transmit window + * \param[in] tx_slot_count Number of TS in TX + * \param[in,out] checked_rx array with already checked RX timeslots + * \returns true if the slot should be skipped, false otherwise + */ +static bool skip_slot(const struct gprs_ms_multislot_class *ms_class, bool check_tr, int16_t rx_window, + uint8_t rx_slot_count, int16_t tx_window, uint8_t tx_slot_count, uint32_t *checked_rx) +{ + uint8_t common_slot_count, req_common_slots; + + /* Check compliance with TS 45.002, table 6.4.2.2.1 */ + /* Whether to skip this round doesn not only depend on the bit + * sets but also on check_tr. Therefore this check must be done + * before doing the test_and_set_bit shortcut. */ + if (ms_class->type == 1) { + uint16_t slot_sum = rx_slot_count + tx_slot_count; + /* Assume down + up / dynamic. + * TODO: For ext-dynamic, down only, up only add more cases. + */ + if (slot_sum <= 6 && tx_slot_count < 3) { + if (!check_tr) + return true; /* Skip Tta */ + } else if (slot_sum > 6 && tx_slot_count < 3) { + if (check_tr) + return true; /* Skip Tra */ + } else + return true; /* No supported row in TS 45.002, table 6.4.2.2.1. */ + } + + /* Avoid repeated RX combination check */ + if (test_and_set_bit(checked_rx, rx_window)) + return true; + + /* Check number of common slots according to TS 45.002, ยง6.4.2.2 */ + common_slot_count = pcu_bitcount(tx_window & rx_window); + req_common_slots = OSMO_MIN(tx_slot_count, rx_slot_count); + if (ms_class->type == 1) + req_common_slots = OSMO_MIN(req_common_slots, 2); + + if (req_common_slots != common_slot_count) + return true; + + return false; +} + +/*! Filter out bad slots + * + * \param[in] mask TS selection mask + * \param[in] ul_slots set of UL timeslots + * \param[in] dl_slots set of DL timeslots + * \param[in] rx_valid_win Mask for valid RX window value + * \returns negative error code or RX window on success + */ +static int16_t filter_bad_slots(uint8_t mask, uint8_t ul_slots, uint8_t dl_slots, uint16_t rx_valid_win) +{ + uint8_t rx_good; + uint16_t rx_bad = (uint16_t)(0xff & ~mask) << ul_slots; + + /* TODO: CHECK this calculation -> separate function for unit testing */ + rx_bad = (rx_bad | (rx_bad >> 8)) & 0xff; + rx_good = dl_slots & ~rx_bad; + if (!rx_good) + return -1; + + return rx_good & rx_valid_win; +} + +static inline uint16_t wrap_window(uint16_t win) +{ + return (win | win >> 8) & 0xFF; +} + /*! Find set of slots available for allocation while taking MS class into account * * \param[in] trx Pointer to TRX object @@ -540,18 +618,14 @@ uint8_t Tx, Sum; /* Maximum Number of Slots: RX, Tx, Sum Rx+Tx */ uint8_t Tta, Ttb, Tra, Trb; /* Minimum Number of Slots */ uint8_t Type; /* Type of Mobile */ - int rx_window, tx_window, pdch_slots; + uint8_t max_slots, num_tx, mask_sel, pdch_slots, ul_ts, dl_ts; + int16_t rx_window, tx_window; static const char *digit[10] = { "0","1","2","3","4","5","6","7","8","9" }; char slot_info[9] = {0}; int max_capacity; uint8_t max_ul_slots; uint8_t max_dl_slots; - unsigned max_slots; - - unsigned ul_ts, dl_ts; - unsigned num_tx; enum {MASK_TT, MASK_TR}; - unsigned mask_sel; if (ms->ms_class() >= 32) { LOGP(DRLCMAC, LOGL_ERROR, "Multislot class %d out of range.\n", @@ -643,13 +717,12 @@ /* Rotate group of TX slots: UUU-----, -UUU----, ..., UU-----U */ for (ul_ts = 0; ul_ts < 8; ul_ts += 1, tx_valid_win <<= 1) { - unsigned tx_slot_count; - int max_rx; + uint8_t tx_slot_count; uint16_t rx_valid_win; uint32_t checked_rx[256/32] = {0}; /* Wrap valid window */ - tx_valid_win = (tx_valid_win | tx_valid_win >> 8) & 0xff; + tx_valid_win = wrap_window(tx_valid_win); tx_window = tx_valid_win; @@ -666,78 +739,28 @@ tx_slot_count = pcu_bitcount(tx_window); - max_rx = OSMO_MIN(ms_class->rx, ms_class->sum - num_tx); - rx_valid_win = (1 << max_rx) - 1; + rx_valid_win = (1 << OSMO_MIN(ms_class->rx, ms_class->sum - num_tx)) - 1; /* Rotate group of RX slots: DDD-----, -DDD----, ..., DD-----D */ for (dl_ts = 0; dl_ts < 8; dl_ts += 1, rx_valid_win <<= 1) { /* Wrap valid window */ - rx_valid_win = (rx_valid_win | rx_valid_win >> 8) & 0xff; + rx_valid_win = wrap_window(rx_valid_win); /* Validate with both Tta/Ttb/Trb and Ttb/Tra/Trb */ for (mask_sel = MASK_TT; mask_sel <= MASK_TR; mask_sel += 1) { - unsigned common_slot_count; - unsigned req_common_slots; - unsigned rx_slot_count; - uint16_t rx_bad; - uint8_t rx_good; + uint8_t rx_slot_count; int capacity; - /* Filter out bad slots */ - rx_bad = (uint16_t)(0xff & ~rx_mask[mask_sel]) << ul_ts; - rx_bad = (rx_bad | (rx_bad >> 8)) & 0xff; - rx_good = *dl_slots & ~rx_bad; + rx_window = filter_bad_slots(rx_mask[mask_sel], ul_ts, *dl_slots, rx_valid_win); + if (rx_window < 0) + continue; - /* TODO: CHECK this calculation -> separate function for unit - * testing */ - - rx_window = rx_good & rx_valid_win; rx_slot_count = pcu_bitcount(rx_window); - /* Check compliance with TS 45.002, table 6.4.2.2.1 */ - /* Whether to skip this round doesn not only depend on the bit - * sets but also on mask_sel. Therefore this check must be done - * before doing the test_and_set_bit shortcut. */ - if (ms_class->type == 1) { - unsigned slot_sum = rx_slot_count + tx_slot_count; - /* Assume down+up/dynamic. - * TODO: For ext-dynamic, down only, up only add more - * cases. - */ - if (slot_sum <= 6 && tx_slot_count < 3) { - if (mask_sel != MASK_TR) - /* Skip Tta */ - continue; - } else if (slot_sum > 6 && tx_slot_count < 3) { - if (mask_sel != MASK_TT) - /* Skip Tra */ - continue; - } else { - /* No supported row in table 6.4.2.2.1. */ - continue; - } - } - - /* Avoid repeated RX combination check */ - if (test_and_set_bit(checked_rx, rx_window)) + if (skip_slot(ms_class, mask_sel != MASK_TT, + rx_window, rx_slot_count, + tx_window, tx_slot_count, checked_rx)) continue; - - if (!rx_good) { - continue; - } - - if (!rx_window) - continue; - - /* Check number of common slots according to TS 54.002, 6.4.2.2 */ - common_slot_count = pcu_bitcount(tx_window & rx_window); - req_common_slots = OSMO_MIN(tx_slot_count, rx_slot_count); - if (ms_class->type == 1) - req_common_slots = OSMO_MIN(req_common_slots, 2); - - if (req_common_slots != common_slot_count) { - continue; - } /* Compute capacity */ capacity = compute_capacity(trx, rx_window, tx_window); -- To view, visit https://gerrit.osmocom.org/3935 To unsubscribe, visit https://gerrit.osmocom.org/settings Gerrit-MessageType: newpatchset Gerrit-Change-Id: Ic39e848da47dc11357782362fdf6206d2c1457c2 Gerrit-PatchSet: 3 Gerrit-Project: osmo-pcu Gerrit-Branch: master Gerrit-Owner: Max <msur...@sysmocom.de> Gerrit-Reviewer: Jenkins Builder