aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJacob Erlbeck <jerlbeck@sysmocom.de>2015-06-22 16:14:23 +0200
committerJacob Erlbeck <jerlbeck@sysmocom.de>2015-06-22 16:14:23 +0200
commit73d8bc51ce70d8c3a26c7a0c3b3c41d02d33a2db (patch)
tree1fc7cd7cc0c1134a8fc9399889113d066423c350
parente56f9a9a22552a762ac8449a81d6ced3339347f7 (diff)
WIP Algorithm B UL (TODO)
Select UL slot based on slot usage (similar to algorithm A)
-rw-r--r--src/gprs_rlcmac_ts_alloc.cpp172
1 files changed, 109 insertions, 63 deletions
diff --git a/src/gprs_rlcmac_ts_alloc.cpp b/src/gprs_rlcmac_ts_alloc.cpp
index 7da07673..1e0f539b 100644
--- a/src/gprs_rlcmac_ts_alloc.cpp
+++ b/src/gprs_rlcmac_ts_alloc.cpp
@@ -101,11 +101,12 @@ static inline int8_t find_free_usf(struct gprs_rlcmac_pdch *pdch)
}
static int find_possible_pdchs(struct gprs_rlcmac_trx *trx,
- enum gprs_rlcmac_tbf_direction dir,
+ enum gprs_rlcmac_tbf_direction dir, size_t max_slots,
uint8_t mask, const char *mask_reason)
{
unsigned ts;
int valid_ts_set = 0;
+ int8_t last_tsc = -1; /* must be signed */
for (ts = 0; ts < ARRAY_SIZE(trx->pdch); ts++) {
struct gprs_rlcmac_pdch *pdch;
@@ -125,12 +126,53 @@ static int find_possible_pdchs(struct gprs_rlcmac_trx *trx,
continue;
}
+ if (max_slots > 1) {
+ /* check if TSC changes */
+ if (last_tsc < 0)
+ last_tsc = pdch->tsc;
+ else if (last_tsc != pdch->tsc) {
+ LOGP(DRLCMAC, LOGL_ERROR,
+ "Skipping TS %d of TRX=%d, because it "
+ "has different TSC than lower TS of TRX. "
+ "In order to allow multislot, all "
+ "slots must be configured with the same "
+ "TSC!\n", ts, trx->trx_no);
+ continue;
+ }
+ }
+
valid_ts_set |= 1 << ts;
}
return valid_ts_set;
}
+static uint8_t filter_ts(uint8_t current, uint8_t mask, const char *mask_reason)
+{
+ unsigned ts;
+ uint8_t result;
+ uint8_t invalid;
+
+ result = current & mask;
+
+ if (result == current || !mask_reason)
+ return result;
+
+ invalid = current & ~result;
+
+ for (ts = 0; ts < 8; ts++) {
+ if (((1 << ts) & invalid) == 0)
+ continue;
+
+ if (mask_reason)
+ LOGP(DRLCMAC, LOGL_DEBUG,
+ "- Skipping TS %d, because %s\n",
+ ts, mask_reason);
+ }
+
+ return result;
+}
+
static int find_least_busy_pdch(struct gprs_rlcmac_trx *trx,
enum gprs_rlcmac_tbf_direction dir,
uint8_t mask,
@@ -326,7 +368,7 @@ int alloc_algorithm_a(struct gprs_rlcmac_bts *bts,
mask_reason = "need to reuse TS";
else if ((ref_tbf = ms->tbf(reverse(tbf->direction))))
mask_reason = ref_tbf->direction == GPRS_RLCMAC_UL_TBF ?
- "not an uplink TBF" : "not a downlink TBF";
+ "not an uplink slot" : "not a downlink slot";
if (ref_tbf)
ts = ref_tbf->first_common_ts;
@@ -334,7 +376,7 @@ int alloc_algorithm_a(struct gprs_rlcmac_bts *bts,
if (ts >= 0)
mask = 1 << ts;
- mask = find_possible_pdchs(tbf->trx, tbf->direction, mask, mask_reason);
+ mask = find_possible_pdchs(tbf->trx, tbf->direction, 1, mask, mask_reason);
if (!mask)
return -EINVAL;
@@ -597,76 +639,80 @@ static void tx_win_from_rx(const int ms_type,
* slots.
*/
static int select_ul_slots(gprs_rlcmac_trx *trx,
- const int ms_type, const int ms_max_txslots,
+ const int ms_type, int ms_max_txslots,
uint8_t tx_win_min, uint8_t tx_range,
int8_t *usf, int8_t *first_common_ts, uint8_t rx_window)
{
- int tsc = -1;
uint8_t tx_window = 0;
- int i;
- uint8_t ts_no;
+ int ts;
+ uint16_t mask;
+ int first_ts;
+ int first_usf;
- for (ts_no = tx_win_min, i = 0; i < tx_range; ts_no = (ts_no + 1) & 7, i++) {
- gprs_rlcmac_pdch *pdch = &trx->pdch[ts_no];
+ mask = ((1 << tx_range) - 1) << tx_win_min;
+ tx_window = mask | (mask >> 8); /* wrap upper byte */
- /* check if enabled */
- if (!pdch->is_enabled()) {
- LOGP(DRLCMAC, LOGL_DEBUG, "- Skipping TS %d, "
- "because not enabled\n", ts_no);
- if (ms_type == 1 && tx_window)
- goto inc_window;
- continue;
- }
- /* check if used as downlink */
- if (!(rx_window & (1 << ts_no))) {
- LOGP(DRLCMAC, LOGL_DEBUG, "- Skipping TS %d, "
- "because not a downlink slot\n", ts_no);
- if (ms_type == 1 && tx_window)
- goto inc_window;
- continue;
- }
- /* check if TSC changes */
- if (tsc < 0)
- tsc = pdch->tsc;
- else if (tsc != pdch->tsc) {
- LOGP(DRLCMAC, LOGL_ERROR, "Skipping TS %d of "
- "TRX=%d, because it has different TSC "
- "than lower TS of TRX. In order to "
- "allow multislot, all slots must be "
- "configured with the same TSC!\n",
- ts_no, trx->trx_no);
- if (ms_type == 1)
- goto inc_window;
- continue;
- }
- /* check for free usf */
- usf[ts_no] = find_free_usf(pdch);
- if (usf[ts_no] < 0) {
- LOGP(DRLCMAC, LOGL_DEBUG, "- Skipping TS %d, "
- "because no USF available\n", ts_no);
- if (ms_type == 1)
- goto inc_window;
- continue;
- }
+ tx_window = find_possible_pdchs(trx, GPRS_RLCMAC_UL_TBF, ms_max_txslots,
+ tx_window, NULL);
- if (!tx_window)
- *first_common_ts = ts_no;
+ tx_window = filter_ts(tx_window, rx_window, "not a downlink slot");
- tx_window |= (1 << ts_no);
- LOGP(DRLCMAC, LOGL_DEBUG, "- Selected UL TS %d\n", ts_no);
+ if (ms_type == 1) {
+ ms_max_txslots = 1;
+ first_ts = find_least_busy_pdch(trx, GPRS_RLCMAC_UL_TBF,
+ tx_window, &first_usf);
-inc_window:
- if (1 && ms_type == 1) { /* FIXME: multislot UL assignment */
- LOGP(DRLCMAC, LOGL_DEBUG, "- Done, because "
- "1 slot assigned\n");
- break;
- }
- if (i+1 == ms_max_txslots) {
- LOGP(DRLCMAC, LOGL_DEBUG, "- Done, because "
- "slots / window reached maximum "
- "allowed Tx size\n");
- break;
+ LOGP(DRLCMAC, LOGL_DEBUG, "- Selected UL TS %d\n", first_ts);
+
+ tx_window = 1 << first_ts;
+ usf[first_ts] = first_usf;
+ *first_common_ts = first_ts;
+
+ /* FIXME: multislot UL assignment */
+ LOGP(DRLCMAC, LOGL_DEBUG, "- Done, because 1 slot assigned\n");
+ } else {
+ bool found = false;
+ mask = 0;
+ for (ts = tx_win_min; ts < tx_win_min + tx_range; ts++) {
+ gprs_rlcmac_pdch *pdch = &trx->pdch[ts];
+ bool ts_valid = tx_window & (1 << (ts % 8));
+
+ usf[ts] = -1;
+
+ if (!found && !ts_valid)
+ continue;
+
+ if (ts_valid) {
+ /* check for free usf */
+ usf[ts] = find_free_usf(pdch);
+ if (usf[ts] < 0) {
+ LOGP(DRLCMAC, LOGL_DEBUG,
+ "- Skipping TS %d, "
+ "because no USF available\n", ts);
+ continue;
+ }
+
+ if (!found)
+ *first_common_ts = ts;
+
+ found = true;
+ LOGP(DRLCMAC, LOGL_DEBUG,
+ "- Selected UL TS %d\n", ts);
+ mask |= 1 << ts;
+ }
+
+ ms_max_txslots -= 1;
+ if (ms_max_txslots == 0) {
+ LOGP(DRLCMAC, LOGL_DEBUG, "- Done, because "
+ "slots / window reached maximum "
+ "allowed Tx size\n");
+ break;
+ }
+
+ /* see 45.002, 6.4.2.2.1, note 0 */
}
+
+ tx_window = mask;
}
LOGP(DRLCMAC, LOGL_DEBUG, "- Selected TX window: "