Merge branch 'sysmocom/allocation-corrections' into sysmocom/master

Merge the refactorings we did at sysmocom and the new test cases that
test the easy success cases of the allocation algorithm. Include the
multislot fixes from Andreas.
This commit is contained in:
Holger Hans Peter Freyther 2014-01-15 10:39:26 +01:00
commit 746b390201
4 changed files with 1620 additions and 264 deletions

View File

@ -178,6 +178,344 @@ int alloc_algorithm_a(struct gprs_rlcmac_bts *bts,
return 0;
}
/*
* Select a window of Rx slots if available.
* The maximum allowed slots depend on RX or the window of available
* slots. This must be done for uplink TBF also, because it is the basis
* for calculating control slot and uplink slot(s).
*/
static uint8_t select_dl_slots(struct gprs_rlcmac_trx *trx,
const int ms_type, const int ms_max_rxslots,
uint8_t *out_rx_win_min, uint8_t *out_rx_win_max)
{
uint8_t rx_window = 0;
int rx_window_size = 0;
int8_t last_tsc = -1; /* must be signed */
uint8_t rx_win_min = 0, rx_win_max = 0;
for (int ts_no = 0; ts_no < 8; ts_no++) {
struct gprs_rlcmac_pdch *pdch;
pdch = &trx->pdch[ts_no];
/* check if enabled */
if (!pdch->is_enabled()) {
LOGP(DRLCMAC, LOGL_DEBUG, "- Skipping TS %d, because "
"not enabled\n", ts_no);
if (ms_type == 1 && rx_window)
goto inc_window;
continue;
}
/* 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_no, trx->trx_no);
if (ms_type == 1 && rx_window)
goto inc_window;
continue;
}
if (!rx_window)
rx_win_min = ts_no;
rx_window |= (1 << ts_no);
LOGP(DRLCMAC, LOGL_DEBUG, "- Selected DL TS %d\n", ts_no);
/* range of window (required for Type 1) */
rx_win_max = ts_no;
inc_window:
if (++rx_window_size == ms_max_rxslots) {
LOGP(DRLCMAC, LOGL_DEBUG, "- Done, because slots / "
"window reached maximum alowed Rx size\n");
break;
}
if (ms_type == 1 && rx_window_size == 5) {
LOGP(DRLCMAC, LOGL_DEBUG, "- Done, because slots / "
"window reached maximum supported Rx size of "
"this algorithm\n");
break;
}
}
LOGP(DRLCMAC, LOGL_DEBUG, "- Selected slots for RX: "
"(TS=0)\"%c%c%c%c%c%c%c%c\"(TS=7)\n",
((rx_window & 0x01)) ? 'D' : '.',
((rx_window & 0x02)) ? 'D' : '.',
((rx_window & 0x04)) ? 'D' : '.',
((rx_window & 0x08)) ? 'D' : '.',
((rx_window & 0x10)) ? 'D' : '.',
((rx_window & 0x20)) ? 'D' : '.',
((rx_window & 0x40)) ? 'D' : '.',
((rx_window & 0x80)) ? 'D' : '.');
*out_rx_win_min = rx_win_min;
*out_rx_win_max = rx_win_max;
return rx_window;
}
static int reduce_rx_window(const int ms_type, const struct gprs_rlcmac_tbf *old_tbf,
const int Tt, const int Tr,
int *rx_window,
uint8_t *rx_win_min, uint8_t *rx_win_max)
{
if (ms_type != 1)
return 0;
if (!old_tbf)
return 0;
if (old_tbf->direction != GPRS_RLCMAC_UL_TBF)
return 0;
uint8_t collide = 0, ul_usage = 0;
/* calculate mask of colliding slots */
for (uint8_t ts_no = 0; ts_no < 8; ts_no++) {
int j;
if (!old_tbf->pdch[ts_no])
continue;
ul_usage |= (1 << ts_no);
/* mark bits from TS-t .. TS+r */
for (j = ts_no - Tt; j != ((ts_no + Tr + 1) & 7); j = (j + 1) & 7)
collide |= (1 << j);
}
LOGP(DRLCMAC, LOGL_DEBUG, "- Not allowed slots due to existing "
"UL allocation: (TS=0)\"%c%c%c%c%c%c%c%c\"(TS=7) "
" D=downlink x=not usable\n",
((ul_usage & 0x01)) ? 'D' : ((collide & 0x01))?'x':'.',
((ul_usage & 0x02)) ? 'D' : ((collide & 0x02))?'x':'.',
((ul_usage & 0x04)) ? 'D' : ((collide & 0x04))?'x':'.',
((ul_usage & 0x08)) ? 'D' : ((collide & 0x08))?'x':'.',
((ul_usage & 0x10)) ? 'D' : ((collide & 0x10))?'x':'.',
((ul_usage & 0x20)) ? 'D' : ((collide & 0x20))?'x':'.',
((ul_usage & 0x40)) ? 'D' : ((collide & 0x40))?'x':'.',
((ul_usage & 0x80)) ? 'D' : ((collide & 0x80))?'x':'.');
/*
* Uplink/Downlink in GSM is shifted by three timeslots. Make
* sure they don't collide.
*/
*rx_window &= ~(collide << 3);
*rx_window &= ~(collide >> 5);
LOGP(DRLCMAC, LOGL_DEBUG, "- Remaining slots for RX: "
"(TS=0)\"%c%c%c%c%c%c%c%c\"(TS=7)\n",
((*rx_window & 0x01)) ? 'D' : '.',
((*rx_window & 0x02)) ? 'D' : '.',
((*rx_window & 0x04)) ? 'D' : '.',
((*rx_window & 0x08)) ? 'D' : '.',
((*rx_window & 0x10)) ? 'D' : '.',
((*rx_window & 0x20)) ? 'D' : '.',
((*rx_window & 0x40)) ? 'D' : '.',
((*rx_window & 0x80)) ? 'D' : '.');
if (!*rx_window) {
LOGP(DRLCMAC, LOGL_NOTICE, "No suitable downlink slots "
"available with current uplink assignment\n");
return -EBUSY;
}
return 0;
}
/* shrink range of rx_win_min and rx_win_max */
static void shrink_rx_window(uint8_t *rx_win_min, uint8_t *rx_win_max, int rx_window)
{
/* calculate new min/max */
for (uint8_t ts_no = *rx_win_min; ts_no <= *rx_win_max; ts_no++) {
if ((rx_window & (1 << ts_no)))
break;
*rx_win_min = ts_no + 1;
LOGP(DRLCMAC, LOGL_DEBUG, "- TS is unused, so "
"raising start of DL window to %d\n",
*rx_win_min);
}
for (uint8_t ts_no = *rx_win_max; ts_no >= *rx_win_min; ts_no--) {
if ((rx_window & (1 << ts_no)))
break;
*rx_win_max = ts_no - 1;
LOGP(DRLCMAC, LOGL_DEBUG, "- TS is unused, so "
"lowering end of DL window to %d\n",
*rx_win_max);
}
}
/*
* reduce window, to allow at least one uplink TX slot
* this is only required for Type 1
*/
static uint8_t update_rx_win_max(const int ms_type, const int Tt,
const int Tr, uint8_t rx_win_min, uint8_t rx_win_max)
{
if (ms_type != 1)
return rx_win_max;
if (rx_win_max - rx_win_min + 1 + Tt + 1 + Tr > 8) {
rx_win_max = rx_win_min + 7 - Tt - 1 - Tr;
LOGP(DRLCMAC, LOGL_DEBUG, "- Reduce RX window due to time "
"contraints to %d slots\n", rx_win_max - rx_win_min + 1);
}
return rx_win_max;
}
static void tx_win_from_rx(const int ms_type,
uint8_t rx_win_min, uint8_t rx_win_max,
int Tt, int Tr,
uint8_t *tx_win_min, uint8_t *tx_win_max,
uint8_t *tx_range)
{
if (ms_type == 1) {
/* calculate TX window (shifted by 3 timeslots)
* it uses the space between tx_win_max and tx_win_min */
*tx_win_min = (rx_win_max - 2 + Tt) & 7;
*tx_win_max = (rx_win_min + 4 - Tr) & 7;
} else {
/* TX and RX simultaniously */
*tx_win_min = rx_win_min;
*tx_win_max = 7;
}
*tx_range = (*tx_win_max - *tx_win_min + 1) & 7;
/* if TX window fills complete range */
if (*tx_range == 0)
*tx_range = 8;
LOGP(DRLCMAC, LOGL_DEBUG, "- TX-Window is: %d..%d\n", *tx_win_min,
*tx_win_max);
}
/*
* Select a window of Tx slots if available.
* The maximum allowed slots depend on TX or the window of available
* slots.
*/
static int select_ul_slots(gprs_rlcmac_trx *trx,
const int ms_type, const 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;
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];
/* 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;
}
if (!tx_window)
*first_common_ts = ts_no;
tx_window |= (1 << ts_no);
LOGP(DRLCMAC, LOGL_DEBUG, "- Selected UL TS %d\n", ts_no);
inc_window:
if (1 && ms_type == 1) { /* FIXME: multislot UL assignment */
LOGP(DRLCMAC, LOGL_DEBUG, "- Done, because "
"1 slot assigned\n");
break;
}
if (++i == ms_max_txslots) {
LOGP(DRLCMAC, LOGL_DEBUG, "- Done, because "
"slots / window reached maximum "
"allowed Tx size\n");
break;
}
}
LOGP(DRLCMAC, LOGL_DEBUG, "- Selected TX window: "
"(TS=0)\"%c%c%c%c%c%c%c%c\"(TS=7)\n",
((tx_window & 0x01)) ? 'U' : '.',
((tx_window & 0x02)) ? 'U' : '.',
((tx_window & 0x04)) ? 'U' : '.',
((tx_window & 0x08)) ? 'U' : '.',
((tx_window & 0x10)) ? 'U' : '.',
((tx_window & 0x20)) ? 'U' : '.',
((tx_window & 0x40)) ? 'U' : '.',
((tx_window & 0x80)) ? 'U' : '.');
if (!tx_window) {
LOGP(DRLCMAC, LOGL_NOTICE, "No suitable uplink slots "
"available\n");
return -EBUSY;
}
return tx_window;
}
/*
* Assign the first common ts, which is used for control or
* single slot.
*/
static int select_first_ts(gprs_rlcmac_trx *trx, uint8_t tx_win_min,
uint8_t tx_range, uint8_t rx_window)
{
uint8_t ts_no;
int i;
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];
/* check if enabled */
if (!pdch->is_enabled()) {
LOGP(DRLCMAC, LOGL_DEBUG, "- Skipping TS %d, "
"because not enabled\n", ts_no);
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);
continue;
}
return ts_no;
}
return -1;
}
/* Slot Allocation: Algorithm B
*
* Assign as many downlink slots as possible.
@ -188,19 +526,15 @@ int alloc_algorithm_b(struct gprs_rlcmac_bts *bts,
struct gprs_rlcmac_tbf *old_tbf,
struct gprs_rlcmac_tbf *tbf, uint32_t cust, uint8_t single)
{
struct gprs_rlcmac_pdch *pdch;
const struct gprs_ms_multislot_class *ms_class;
uint8_t Rx, Tx, Sum; /* Maximum Number of Slots: RX, Tx, Sum Rx+Tx */
uint8_t Tx, Sum; /* Maximum Number of Slots: RX, Tx, Sum Rx+Tx */
uint8_t Tta, Ttb, Tra, Trb, Tt, Tr; /* Minimum Number of Slots */
uint8_t Type; /* Type of Mobile */
uint8_t rx_win_min = 0, rx_win_max = 7;
uint8_t tx_win_min, tx_win_max, tx_range;
uint8_t rx_window = 0, tx_window = 0;
int rx_window;
static const char *digit[10] = { "0","1","2","3","4","5","6","7","8","9" };
int8_t usf[8] = { -1, -1, -1, -1, -1, -1, -1, -1 }; /* must be signed */
int8_t tsc = -1; /* must be signed */
int8_t first_common_ts = -1;
uint8_t i, ts;
uint8_t ts;
uint8_t slotcount = 0;
@ -226,7 +560,6 @@ int alloc_algorithm_b(struct gprs_rlcmac_bts *bts,
return -EINVAL;
}
Rx = ms_class->rx;
Tx = ms_class->tx;
Sum = ms_class->sum;
Tta = ms_class->ta;
@ -236,17 +569,13 @@ int alloc_algorithm_b(struct gprs_rlcmac_bts *bts,
Type = ms_class->type;
/* Tta and Ttb may depend on hopping or frequency change */
if (Ttb == MS_A)
if (Ttb == MS_A || Ttb == MS_B)
Ttb = 0;
if (Trb == MS_A)
Trb = 0;
if (Ttb == MS_B)
Ttb = 0;
if (Trb == MS_C)
if (Trb == MS_A || Trb == MS_C)
Trb = 0;
LOGP(DRLCMAC, LOGL_DEBUG, "- Rx=%d Tx=%d Sum Rx+Tx=%s Tta=%s Ttb=%d "
" Tra=%d Trb=%d Type=%d\n", Rx, Tx,
" Tra=%d Trb=%d Type=%d\n", ms_class->rx, Tx,
(Sum == MS_NA) ? "N/A" : digit[Sum],
(Tta == MS_NA) ? "N/A" : digit[Tta], Ttb, Tra, Trb, Type);
@ -255,251 +584,42 @@ int alloc_algorithm_b(struct gprs_rlcmac_bts *bts,
Tt = Ttb;
Tr = Trb;
/* select a window of Rx slots if available
* The maximum allowed slots depend on RX or the window of available
* slots.
* This must be done for uplink TBF also, because it is the basis
* for calculating control slot and uplink slot(s). */
for (ts = 0, i = 0; ts < 8; ts++) {
pdch = &tbf->trx->pdch[ts];
/* check if enabled */
if (!pdch->is_enabled()) {
LOGP(DRLCMAC, LOGL_DEBUG, "- Skipping TS %d, because "
"not enabled\n", ts);
/* increase window for Type 1 */
if (Type == 1 && rx_window)
i++;
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, tbf->trx->trx_no);
/* increase window for Type 1 */
if (Type == 1 && rx_window)
i++;
continue;
}
uint8_t rx_win_min, rx_win_max;
rx_window = select_dl_slots(tbf->trx, ms_class->type, ms_class->rx,
&rx_win_min, &rx_win_max);
if (!rx_window)
rx_win_min = ts;
rx_window |= (1 << ts);
LOGP(DRLCMAC, LOGL_DEBUG, "- Selected DL TS %d\n", ts);
/* range of window (required for Type 1) */
rx_win_max = ts;
if (++i == Rx) {
LOGP(DRLCMAC, LOGL_DEBUG, "- Done, because slots / "
"window reached maximum alowed Rx size\n");
break;
}
}
LOGP(DRLCMAC, LOGL_DEBUG, "- Selected slots for RX: "
"(TS=0)\"%c%c%c%c%c%c%c%c\"(TS=7)\n",
((rx_window & 0x01)) ? 'D' : '.',
((rx_window & 0x02)) ? 'D' : '.',
((rx_window & 0x04)) ? 'D' : '.',
((rx_window & 0x08)) ? 'D' : '.',
((rx_window & 0x10)) ? 'D' : '.',
((rx_window & 0x20)) ? 'D' : '.',
((rx_window & 0x40)) ? 'D' : '.',
((rx_window & 0x80)) ? 'D' : '.');
/* reduce window, if existing uplink slots collide RX window */
if (Type == 1 && old_tbf && old_tbf->direction == GPRS_RLCMAC_UL_TBF) {
uint8_t collide = 0, ul_usage = 0;
int j;
/* calculate mask of colliding slots */
for (ts = 0; ts < 8; ts++) {
if (old_tbf->pdch[ts]) {
ul_usage |= (1 << ts);
/* mark bits from TS-t .. TS+r */
for (j = ts - Tt; j != ((ts + Tr + 1) & 7);
j = (j + 1) & 7)
collide |= (1 << j);
}
}
LOGP(DRLCMAC, LOGL_DEBUG, "- Not allowed slots due to existing "
"UL allocation: (TS=0)\"%c%c%c%c%c%c%c%c\"(TS=7) "
" D=downlink x=not usable\n",
((ul_usage & 0x01)) ? 'D' : ((collide & 0x01))?'x':'.',
((ul_usage & 0x02)) ? 'D' : ((collide & 0x02))?'x':'.',
((ul_usage & 0x04)) ? 'D' : ((collide & 0x04))?'x':'.',
((ul_usage & 0x08)) ? 'D' : ((collide & 0x08))?'x':'.',
((ul_usage & 0x10)) ? 'D' : ((collide & 0x10))?'x':'.',
((ul_usage & 0x20)) ? 'D' : ((collide & 0x20))?'x':'.',
((ul_usage & 0x40)) ? 'D' : ((collide & 0x40))?'x':'.',
((ul_usage & 0x80)) ? 'D' : ((collide & 0x80))?'x':'.');
/* apply mask to reduce tx_window (shifted by 3 slots) */
rx_window &= ~(collide << 3);
rx_window &= ~(collide >> 5);
LOGP(DRLCMAC, LOGL_DEBUG, "- Remaining slots for RX: "
"(TS=0)\"%c%c%c%c%c%c%c%c\"(TS=7)\n",
((rx_window & 0x01)) ? 'D' : '.',
((rx_window & 0x02)) ? 'D' : '.',
((rx_window & 0x04)) ? 'D' : '.',
((rx_window & 0x08)) ? 'D' : '.',
((rx_window & 0x10)) ? 'D' : '.',
((rx_window & 0x20)) ? 'D' : '.',
((rx_window & 0x40)) ? 'D' : '.',
((rx_window & 0x80)) ? 'D' : '.');
if (!rx_window) {
LOGP(DRLCMAC, LOGL_NOTICE, "No suitable downlink slots "
"available with current uplink assignment\n");
return -EBUSY;
}
/* calculate new min/max */
for (ts = rx_win_min; ts <= rx_win_max; ts++) {
if ((rx_window & (1 << ts)))
break;
rx_win_min = ts + 1;
LOGP(DRLCMAC, LOGL_DEBUG, "- TS has been deleted, so "
"raising start of DL window to %d\n",
rx_win_min);
}
for (ts = rx_win_max; ts >= rx_win_min; ts--) {
if ((rx_window & (1 << ts)))
break;
rx_win_max = ts - 1;
LOGP(DRLCMAC, LOGL_DEBUG, "- TS has been deleted, so "
"lowering end of DL window to %d\n",
rx_win_max);
}
}
/* reduce window, to allow at least one uplink TX slot
* this is only required for Type 1 */
if (Type == 1 && rx_win_max - rx_win_min + 1 + Tt + 1 + Tr > 8) {
rx_win_max = rx_win_min + 7 - Tt - 1 - Tr;
LOGP(DRLCMAC, LOGL_DEBUG, "- Reduce RX window due to time "
"contraints to %d slots\n",
rx_win_max - rx_win_min + 1);
}
int rc = reduce_rx_window(ms_class->type, old_tbf, Tt, Tr,
&rx_window, &rx_win_min, &rx_win_max);
if (rc < 0)
return rc;
shrink_rx_window(&rx_win_min, &rx_win_max, rx_window);
rx_win_max = update_rx_win_max(ms_class->type, Tt, Tr,
rx_win_min, rx_win_max);
shrink_rx_window(&rx_win_min, &rx_win_max, rx_window);
LOGP(DRLCMAC, LOGL_DEBUG, "- RX-Window is: %d..%d\n", rx_win_min,
rx_win_max);
/* calculate TX window */
if (Type == 1) {
/* calculate TX window (shifted by 3 timeslots)
* it uses the space between tx_win_max and tx_win_min */
tx_win_min = (rx_win_max - 2 + Tt) & 7;
tx_win_max = (rx_win_min + 4 - Tr) & 7;
/* calculate the TX window size (might be larger than Tx) */
tx_range = (tx_win_max - tx_win_min + 1) & 7;
} else {
/* TX and RX simultaniously */
tx_win_min = rx_win_min;
tx_win_max = 7;
/* TX window size (might be larger than Tx) */
tx_range = tx_win_max - tx_win_min + 1;
}
uint8_t tx_win_min, tx_win_max, tx_range;
tx_win_from_rx(ms_class->type, rx_win_min, rx_win_max, Tt, Tr,
&tx_win_min, &tx_win_max, &tx_range);
LOGP(DRLCMAC, LOGL_DEBUG, "- TX-Window is: %d..%d\n", tx_win_min,
tx_win_max);
/* select a window of Tx slots if available
* The maximum allowed slots depend on TX or the window of available
* slots.
*
* also assign the first common ts, which is used for control or single
* slot. */
/* select UL slots but in both cases assign first_common_ts */
uint8_t tx_window = 0;
if (tbf->direction == GPRS_RLCMAC_UL_TBF) {
for (ts = tx_win_min, i = 0; i < tx_range; ts = (ts + 1) & 7) {
pdch = &tbf->trx->pdch[ts];
/* check if enabled */
if (!pdch->is_enabled()) {
LOGP(DRLCMAC, LOGL_DEBUG, "- Skipping TS %d, "
"because not enabled\n", ts);
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, tbf->trx->trx_no);
/* increase window for Type 1 */
if (Type == 1)
i++;
continue;
}
/* 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);
/* increase window for Type 1 */
if (Type == 1)
i++;
continue;
}
if (!tx_window)
first_common_ts = ts;
tx_window |= (1 << ts);
LOGP(DRLCMAC, LOGL_DEBUG, "- Selected UL TS %d\n", ts);
if (1 && Type == 1) { /* FIXME: multislot UL assignment */
LOGP(DRLCMAC, LOGL_DEBUG, "- Done, because "
"1 slot assigned\n");
break;
}
if (++i == Tx) {
LOGP(DRLCMAC, LOGL_DEBUG, "- Done, because "
"slots / window reached maximum "
"allowed Tx size\n");
break;
}
}
LOGP(DRLCMAC, LOGL_DEBUG, "- Selected TX window: "
"(TS=0)\"%c%c%c%c%c%c%c%c\"(TS=7)\n",
((tx_window & 0x01)) ? 'U' : '.',
((tx_window & 0x02)) ? 'U' : '.',
((tx_window & 0x04)) ? 'U' : '.',
((tx_window & 0x08)) ? 'U' : '.',
((tx_window & 0x10)) ? 'U' : '.',
((tx_window & 0x20)) ? 'U' : '.',
((tx_window & 0x40)) ? 'U' : '.',
((tx_window & 0x80)) ? 'U' : '.');
if (!tx_window) {
LOGP(DRLCMAC, LOGL_NOTICE, "No suitable uplink slots "
"available\n");
return -EBUSY;
}
rc = select_ul_slots(tbf->trx, ms_class->type, ms_class->tx,
tx_win_min, tx_range, usf,
&first_common_ts, rx_window);
if (rc < 0)
return rc;
tx_window = rc;
} else {
/* assign the first common ts, which is used for control or
* single slot. */
for (ts = tx_win_min, i = 0; i < tx_range; ts = (ts + 1) & 7) {
pdch = &tbf->trx->pdch[ts];
/* check if enabled */
if (!pdch->is_enabled()) {
LOGP(DRLCMAC, LOGL_DEBUG, "- Skipping TS %d, "
"because not enabled\n", ts);
continue;
}
first_common_ts = ts;
break;
}
first_common_ts = select_first_ts(tbf->trx, tx_win_min,
tx_range, rx_window);
}
#warning "first_common_ts might be different if there was no free USF for the new uplink assignment"
if (first_common_ts < 0) {
LOGP(DRLCMAC, LOGL_NOTICE, "No first common slots available\n");
@ -522,8 +642,7 @@ int alloc_algorithm_b(struct gprs_rlcmac_bts *bts,
continue;
LOGP(DRLCMAC, LOGL_DEBUG, "- Assigning DL TS "
"%d\n", ts);
pdch = &tbf->trx->pdch[ts];
assign_dlink_tbf(pdch, tbf);
assign_dlink_tbf(&tbf->trx->pdch[ts], tbf);
slotcount++;
if (slotcount == 1)
tbf->first_ts = ts;
@ -532,18 +651,11 @@ int alloc_algorithm_b(struct gprs_rlcmac_bts *bts,
}
}
} else {
/* assign uplink */
if (tx_window == 0) {
LOGP(DRLCMAC, LOGL_NOTICE, "No uplink slots "
"available\n");
return -EINVAL;
}
for (ts = 0; ts < 8; ts++) {
if ((tx_window & (1 << ts))) {
LOGP(DRLCMAC, LOGL_DEBUG, "- Assigning UL TS "
"%d\n", ts);
pdch = &tbf->trx->pdch[ts];
assign_uplink_tbf_usf(pdch, tbf, usf[ts]);
assign_uplink_tbf_usf(&tbf->trx->pdch[ts], tbf, usf[ts]);
slotcount++;
if (slotcount == 1)
tbf->first_ts = ts;

View File

@ -317,11 +317,6 @@ int gprs_rlcmac_tbf::update()
if (direction != GPRS_RLCMAC_DL_TBF)
return -EINVAL;
if (!ms_class) {
LOGP(DRLCMAC, LOGL_DEBUG, "- Cannot update, no class\n");
return -EINVAL;
}
ul_tbf = bts->tbf_by_tlli(m_tlli, GPRS_RLCMAC_UL_TBF);
tbf_unlink_pdch(this);

View File

@ -97,6 +97,289 @@ static void test_alloc_a()
test_alloc_a(GPRS_RLCMAC_UL_TBF, 7);
}
static void dump_assignment(struct gprs_rlcmac_tbf *tbf, const char *dir)
{
for (int i = 0; i < ARRAY_SIZE(tbf->pdch); ++i)
if (tbf->pdch[i])
printf("PDCH[%d] is used for %s\n", i, dir);
printf("PDCH[%d] is control_ts for %s\n", tbf->control_ts, dir);
printf("PDCH[%d] is first common for %s\n", tbf->first_common_ts, dir);
}
static void test_alloc_b(int ms_class)
{
printf("Going to test multislot assignment MS_CLASS=%d\n", ms_class);
/*
* PDCH is on TS 6,7,8 and we start with a UL allocation and
* then follow two DL allocations (once single, once normal).
*
* Uplink assigned and still available..
*/
{
BTS the_bts;
struct gprs_rlcmac_bts *bts;
struct gprs_rlcmac_trx *trx;
int tfi;
uint8_t ts_no, trx_no;
gprs_rlcmac_tbf *ul_tbf, *dl_tbf;
printf("Testing UL then DL assignment.\n");
bts = the_bts.bts_data();
bts->alloc_algorithm = alloc_algorithm_b;
trx = &bts->trx[0];
trx->pdch[5].enable();
trx->pdch[6].enable();
trx->pdch[7].enable();
tfi = the_bts.tfi_find_free(GPRS_RLCMAC_UL_TBF, &trx_no, -1);
OSMO_ASSERT(tfi >= 0);
ul_tbf = tbf_alloc(bts, NULL, GPRS_RLCMAC_UL_TBF, tfi, trx_no, ms_class, 1);
OSMO_ASSERT(ul_tbf);
dump_assignment(ul_tbf, "UL");
/* assume final ack has not been sent */
tfi = the_bts.tfi_find_free(GPRS_RLCMAC_UL_TBF, &trx_no, -1);
OSMO_ASSERT(tfi >= 0);
dl_tbf = tbf_alloc(bts, ul_tbf, GPRS_RLCMAC_DL_TBF, tfi, trx_no, ms_class, 0);
OSMO_ASSERT(dl_tbf);
dump_assignment(dl_tbf, "DL");
OSMO_ASSERT(dl_tbf->first_common_ts == ul_tbf->first_common_ts);
tbf_free(dl_tbf);
tbf_free(ul_tbf);
}
/**
* Test with the other order.. first DL and then UL
*/
{
BTS the_bts;
struct gprs_rlcmac_bts *bts;
struct gprs_rlcmac_trx *trx;
int tfi;
uint8_t ts_no, trx_no;
gprs_rlcmac_tbf *ul_tbf, *dl_tbf;
printf("Testing DL then UL assignment followed by update\n");
bts = the_bts.bts_data();
bts->alloc_algorithm = alloc_algorithm_b;
trx = &bts->trx[0];
trx->pdch[5].enable();
trx->pdch[6].enable();
trx->pdch[7].enable();
tfi = the_bts.tfi_find_free(GPRS_RLCMAC_UL_TBF, &trx_no, -1);
OSMO_ASSERT(tfi >= 0);
dl_tbf = tbf_alloc(bts, NULL, GPRS_RLCMAC_DL_TBF, tfi, trx_no, ms_class, 1);
dl_tbf->m_tlli = 0x23;
dl_tbf->m_tlli_valid = true;
OSMO_ASSERT(dl_tbf);
dump_assignment(dl_tbf, "DL");
tfi = the_bts.tfi_find_free(GPRS_RLCMAC_UL_TBF, &trx_no, -1);
OSMO_ASSERT(tfi >= 0);
ul_tbf = tbf_alloc(bts, dl_tbf, GPRS_RLCMAC_UL_TBF, tfi, trx_no, ms_class, 0);
ul_tbf->m_tlli = 0x23;
ul_tbf->m_tlli_valid = true;
ul_tbf->dir.ul.contention_resolution_done = 1;
OSMO_ASSERT(ul_tbf);
dump_assignment(ul_tbf, "UL");
OSMO_ASSERT(dl_tbf->first_common_ts == ul_tbf->first_common_ts);
/* now update the dl_tbf */
dl_tbf->update();
dump_assignment(dl_tbf, "DL");
OSMO_ASSERT(dl_tbf->first_common_ts == ul_tbf->first_common_ts);
tbf_free(dl_tbf);
tbf_free(ul_tbf);
}
/* Andreas osmocom-pcu example */
{
BTS the_bts;
struct gprs_rlcmac_bts *bts;
struct gprs_rlcmac_trx *trx;
int tfi;
uint8_t ts_no, trx_no;
gprs_rlcmac_tbf *ul_tbf, *dl_tbf;
printf("Testing jolly example\n");
bts = the_bts.bts_data();
bts->alloc_algorithm = alloc_algorithm_b;
trx = &bts->trx[0];
trx->pdch[1].enable();
trx->pdch[2].enable();
trx->pdch[3].enable();
trx->pdch[4].enable();
tfi = the_bts.tfi_find_free(GPRS_RLCMAC_UL_TBF, &trx_no, -1);
OSMO_ASSERT(tfi >= 0);
ul_tbf = tbf_alloc(bts, NULL, GPRS_RLCMAC_UL_TBF, tfi, trx_no, ms_class, 0);
OSMO_ASSERT(ul_tbf);
dump_assignment(ul_tbf, "UL");
/* assume final ack has not been sent */
tfi = the_bts.tfi_find_free(GPRS_RLCMAC_UL_TBF, &trx_no, -1);
OSMO_ASSERT(tfi >= 0);
dl_tbf = tbf_alloc(bts, ul_tbf, GPRS_RLCMAC_DL_TBF, tfi, trx_no, ms_class, 0);
OSMO_ASSERT(dl_tbf);
dump_assignment(dl_tbf, "DL");
OSMO_ASSERT(dl_tbf->first_common_ts == ul_tbf->first_common_ts);
tbf_free(dl_tbf);
tbf_free(ul_tbf);
}
}
#define ENABLE_PDCH(ts_no, enable_flag, trx) \
if (enable_flag) \
trx->pdch[ts_no].enable();
static void test_alloc_b(bool ts0, bool ts1, bool ts2, bool ts3, bool ts4, bool ts5, bool ts6, bool ts7, int ms_class)
{
/* we can test the allocation failures differently */
if (!ts0 && !ts1 && !ts2 && !ts3 && !ts4 && !ts5 && !ts6 && !ts7)
return;
printf("Mass test: TS0(%c%c%c%c%c%c%c%c)TS7 MS_Class=%d\n",
ts0 ? 'O' : 'x',
ts1 ? 'O' : 'x',
ts2 ? 'O' : 'x',
ts3 ? 'O' : 'x',
ts4 ? 'O' : 'x',
ts5 ? 'O' : 'x',
ts6 ? 'O' : 'x',
ts7 ? 'O' : 'x', ms_class);
fflush(stdout);
{
BTS the_bts;
struct gprs_rlcmac_bts *bts;
struct gprs_rlcmac_trx *trx;
int tfi;
uint8_t ts_no, trx_no;
gprs_rlcmac_tbf *ul_tbf, *dl_tbf;
bts = the_bts.bts_data();
bts->alloc_algorithm = alloc_algorithm_b;
trx = &bts->trx[0];
ENABLE_PDCH(0, ts0, trx);
ENABLE_PDCH(1, ts1, trx);
ENABLE_PDCH(2, ts2, trx);
ENABLE_PDCH(3, ts3, trx);
ENABLE_PDCH(4, ts4, trx);
ENABLE_PDCH(5, ts5, trx);
ENABLE_PDCH(6, ts6, trx);
ENABLE_PDCH(7, ts7, trx);
tfi = the_bts.tfi_find_free(GPRS_RLCMAC_UL_TBF, &trx_no, -1);
OSMO_ASSERT(tfi >= 0);
ul_tbf = tbf_alloc(bts, NULL, GPRS_RLCMAC_UL_TBF, tfi, trx_no, ms_class, 1);
OSMO_ASSERT(ul_tbf);
/* assume final ack has not been sent */
tfi = the_bts.tfi_find_free(GPRS_RLCMAC_UL_TBF, &trx_no, -1);
OSMO_ASSERT(tfi >= 0);
dl_tbf = tbf_alloc(bts, ul_tbf, GPRS_RLCMAC_DL_TBF, tfi, trx_no, ms_class, 0);
OSMO_ASSERT(dl_tbf);
/* verify that both are on the same ts */
OSMO_ASSERT(dl_tbf->first_common_ts == ul_tbf->first_common_ts);
tbf_free(dl_tbf);
tbf_free(ul_tbf);
}
/**
* Test with the other order.. first DL and then UL
*/
{
BTS the_bts;
struct gprs_rlcmac_bts *bts;
struct gprs_rlcmac_trx *trx;
int tfi;
uint8_t ts_no, trx_no;
gprs_rlcmac_tbf *ul_tbf, *dl_tbf;
bts = the_bts.bts_data();
bts->alloc_algorithm = alloc_algorithm_b;
trx = &bts->trx[0];
ENABLE_PDCH(0, ts0, trx);
ENABLE_PDCH(1, ts1, trx);
ENABLE_PDCH(2, ts2, trx);
ENABLE_PDCH(3, ts3, trx);
ENABLE_PDCH(4, ts4, trx);
ENABLE_PDCH(5, ts5, trx);
ENABLE_PDCH(6, ts6, trx);
ENABLE_PDCH(7, ts7, trx);
tfi = the_bts.tfi_find_free(GPRS_RLCMAC_UL_TBF, &trx_no, -1);
OSMO_ASSERT(tfi >= 0);
dl_tbf = tbf_alloc(bts, NULL, GPRS_RLCMAC_DL_TBF, tfi, trx_no, ms_class, 1);
OSMO_ASSERT(dl_tbf);
dl_tbf->m_tlli = 0x23;
dl_tbf->m_tlli_valid = true;
tfi = the_bts.tfi_find_free(GPRS_RLCMAC_UL_TBF, &trx_no, -1);
OSMO_ASSERT(tfi >= 0);
ul_tbf = tbf_alloc(bts, dl_tbf, GPRS_RLCMAC_UL_TBF, tfi, trx_no, ms_class, 0);
OSMO_ASSERT(ul_tbf);
ul_tbf->m_tlli = 0x23;
ul_tbf->m_tlli_valid = true;
ul_tbf->dir.ul.contention_resolution_done = 1;
OSMO_ASSERT(dl_tbf->first_common_ts == ul_tbf->first_common_ts);
/* now update the dl_tbf */
dl_tbf->update();
OSMO_ASSERT(dl_tbf->first_common_ts == ul_tbf->first_common_ts);
tbf_free(dl_tbf);
tbf_free(ul_tbf);
}
}
static void test_all_alloc_b()
{
/* it is a bit crazy... */
for (uint8_t ts0 = 0; ts0 < 2; ++ts0)
for (uint8_t ts1 = 0; ts1 < 2; ++ts1)
for (uint8_t ts2 = 0; ts2 < 2; ++ts2)
for (uint8_t ts3 = 0; ts3 < 2; ++ts3)
for (uint8_t ts4 = 0; ts4 < 2; ++ts4)
for (uint8_t ts5 = 0; ts5 < 2; ++ts5)
for (uint8_t ts6 = 0; ts6 < 2; ++ts6)
for (uint8_t ts7 = 0; ts7 < 2; ++ts7)
for (int ms_class = 0; ms_class < 30; ++ms_class)
test_alloc_b(ts0, ts1, ts2, ts3, ts4, ts5, ts6, ts7, ms_class);
}
static void test_alloc_b()
{
for (int i = 0; i < 30; ++i)
test_alloc_b(i);
test_all_alloc_b();
}
int main(int argc, char **argv)
{
tall_pcu_ctx = talloc_named_const(NULL, 1, "moiji-mobile AllocTest context");
@ -109,6 +392,7 @@ int main(int argc, char **argv)
log_set_print_filename(osmo_stderr_target, 0);
test_alloc_a();
test_alloc_b();
return EXIT_SUCCESS;
}

View File

@ -1,2 +1,967 @@
Testing alloc_a direction(0)
Testing alloc_a direction(1)
Going to test multislot assignment MS_CLASS=0
Testing UL then DL assignment.
PDCH[6] is used for UL
PDCH[6] is control_ts for UL
PDCH[6] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[6] is control_ts for DL
PDCH[6] is first common for DL
Testing DL then UL assignment followed by update
PDCH[6] is used for DL
PDCH[6] is control_ts for DL
PDCH[6] is first common for DL
PDCH[6] is used for UL
PDCH[6] is control_ts for UL
PDCH[6] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[6] is control_ts for DL
PDCH[6] is first common for DL
Testing jolly example
PDCH[3] is used for UL
PDCH[3] is control_ts for UL
PDCH[3] is first common for UL
PDCH[1] is used for DL
PDCH[2] is used for DL
PDCH[3] is used for DL
PDCH[4] is used for DL
PDCH[3] is control_ts for DL
PDCH[3] is first common for DL
Going to test multislot assignment MS_CLASS=1
Testing UL then DL assignment.
PDCH[5] is used for UL
PDCH[5] is control_ts for UL
PDCH[5] is first common for UL
PDCH[5] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
Testing DL then UL assignment followed by update
PDCH[5] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
PDCH[5] is used for UL
PDCH[5] is control_ts for UL
PDCH[5] is first common for UL
PDCH[5] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
Testing jolly example
PDCH[1] is used for UL
PDCH[1] is control_ts for UL
PDCH[1] is first common for UL
PDCH[1] is used for DL
PDCH[1] is control_ts for DL
PDCH[1] is first common for DL
Going to test multislot assignment MS_CLASS=2
Testing UL then DL assignment.
PDCH[6] is used for UL
PDCH[6] is control_ts for UL
PDCH[6] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[6] is control_ts for DL
PDCH[6] is first common for DL
Testing DL then UL assignment followed by update
PDCH[6] is used for DL
PDCH[6] is control_ts for DL
PDCH[6] is first common for DL
PDCH[6] is used for UL
PDCH[6] is control_ts for UL
PDCH[6] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[6] is control_ts for DL
PDCH[6] is first common for DL
Testing jolly example
PDCH[2] is used for UL
PDCH[2] is control_ts for UL
PDCH[2] is first common for UL
PDCH[1] is used for DL
PDCH[2] is used for DL
PDCH[2] is control_ts for DL
PDCH[2] is first common for DL
Going to test multislot assignment MS_CLASS=3
Testing UL then DL assignment.
PDCH[6] is used for UL
PDCH[6] is control_ts for UL
PDCH[6] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[6] is control_ts for DL
PDCH[6] is first common for DL
Testing DL then UL assignment followed by update
PDCH[6] is used for DL
PDCH[6] is control_ts for DL
PDCH[6] is first common for DL
PDCH[6] is used for UL
PDCH[6] is control_ts for UL
PDCH[6] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[6] is control_ts for DL
PDCH[6] is first common for DL
Testing jolly example
PDCH[2] is used for UL
PDCH[2] is control_ts for UL
PDCH[2] is first common for UL
PDCH[1] is used for DL
PDCH[2] is used for DL
PDCH[2] is control_ts for DL
PDCH[2] is first common for DL
Going to test multislot assignment MS_CLASS=4
Testing UL then DL assignment.
PDCH[6] is used for UL
PDCH[6] is control_ts for UL
PDCH[6] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[6] is control_ts for DL
PDCH[6] is first common for DL
Testing DL then UL assignment followed by update
PDCH[6] is used for DL
PDCH[6] is control_ts for DL
PDCH[6] is first common for DL
PDCH[6] is used for UL
PDCH[6] is control_ts for UL
PDCH[6] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[6] is control_ts for DL
PDCH[6] is first common for DL
Testing jolly example
PDCH[2] is used for UL
PDCH[2] is control_ts for UL
PDCH[2] is first common for UL
PDCH[1] is used for DL
PDCH[2] is used for DL
PDCH[3] is used for DL
PDCH[2] is control_ts for DL
PDCH[2] is first common for DL
Going to test multislot assignment MS_CLASS=5
Testing UL then DL assignment.
PDCH[5] is used for UL
PDCH[5] is control_ts for UL
PDCH[5] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
Testing DL then UL assignment followed by update
PDCH[5] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
PDCH[5] is used for UL
PDCH[5] is control_ts for UL
PDCH[5] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
Testing jolly example
PDCH[1] is used for UL
PDCH[1] is control_ts for UL
PDCH[1] is first common for UL
PDCH[1] is used for DL
PDCH[2] is used for DL
PDCH[1] is control_ts for DL
PDCH[1] is first common for DL
Going to test multislot assignment MS_CLASS=6
Testing UL then DL assignment.
PDCH[6] is used for UL
PDCH[6] is control_ts for UL
PDCH[6] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[6] is control_ts for DL
PDCH[6] is first common for DL
Testing DL then UL assignment followed by update
PDCH[6] is used for DL
PDCH[6] is control_ts for DL
PDCH[6] is first common for DL
PDCH[6] is used for UL
PDCH[6] is control_ts for UL
PDCH[6] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[6] is control_ts for DL
PDCH[6] is first common for DL
Testing jolly example
PDCH[2] is used for UL
PDCH[2] is control_ts for UL
PDCH[2] is first common for UL
PDCH[1] is used for DL
PDCH[2] is used for DL
PDCH[3] is used for DL
PDCH[2] is control_ts for DL
PDCH[2] is first common for DL
Going to test multislot assignment MS_CLASS=7
Testing UL then DL assignment.
PDCH[6] is used for UL
PDCH[6] is control_ts for UL
PDCH[6] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[6] is control_ts for DL
PDCH[6] is first common for DL
Testing DL then UL assignment followed by update
PDCH[6] is used for DL
PDCH[6] is control_ts for DL
PDCH[6] is first common for DL
PDCH[6] is used for UL
PDCH[6] is control_ts for UL
PDCH[6] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[6] is control_ts for DL
PDCH[6] is first common for DL
Testing jolly example
PDCH[2] is used for UL
PDCH[2] is control_ts for UL
PDCH[2] is first common for UL
PDCH[1] is used for DL
PDCH[2] is used for DL
PDCH[3] is used for DL
PDCH[2] is control_ts for DL
PDCH[2] is first common for DL
Going to test multislot assignment MS_CLASS=8
Testing UL then DL assignment.
PDCH[6] is used for UL
PDCH[6] is control_ts for UL
PDCH[6] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[6] is control_ts for DL
PDCH[6] is first common for DL
Testing DL then UL assignment followed by update
PDCH[6] is used for DL
PDCH[6] is control_ts for DL
PDCH[6] is first common for DL
PDCH[6] is used for UL
PDCH[6] is control_ts for UL
PDCH[6] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[6] is control_ts for DL
PDCH[6] is first common for DL
Testing jolly example
PDCH[3] is used for UL
PDCH[3] is control_ts for UL
PDCH[3] is first common for UL
PDCH[1] is used for DL
PDCH[2] is used for DL
PDCH[3] is used for DL
PDCH[4] is used for DL
PDCH[3] is control_ts for DL
PDCH[3] is first common for DL
Going to test multislot assignment MS_CLASS=9
Testing UL then DL assignment.
PDCH[6] is used for UL
PDCH[6] is control_ts for UL
PDCH[6] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[6] is control_ts for DL
PDCH[6] is first common for DL
Testing DL then UL assignment followed by update
PDCH[6] is used for DL
PDCH[6] is control_ts for DL
PDCH[6] is first common for DL
PDCH[6] is used for UL
PDCH[6] is control_ts for UL
PDCH[6] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[6] is control_ts for DL
PDCH[6] is first common for DL
Testing jolly example
PDCH[2] is used for UL
PDCH[2] is control_ts for UL
PDCH[2] is first common for UL
PDCH[1] is used for DL
PDCH[2] is used for DL
PDCH[3] is used for DL
PDCH[2] is control_ts for DL
PDCH[2] is first common for DL
Going to test multislot assignment MS_CLASS=10
Testing UL then DL assignment.
PDCH[6] is used for UL
PDCH[6] is control_ts for UL
PDCH[6] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[6] is control_ts for DL
PDCH[6] is first common for DL
Testing DL then UL assignment followed by update
PDCH[6] is used for DL
PDCH[6] is control_ts for DL
PDCH[6] is first common for DL
PDCH[6] is used for UL
PDCH[6] is control_ts for UL
PDCH[6] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[6] is control_ts for DL
PDCH[6] is first common for DL
Testing jolly example
PDCH[3] is used for UL
PDCH[3] is control_ts for UL
PDCH[3] is first common for UL
PDCH[1] is used for DL
PDCH[2] is used for DL
PDCH[3] is used for DL
PDCH[4] is used for DL
PDCH[3] is control_ts for DL
PDCH[3] is first common for DL
Going to test multislot assignment MS_CLASS=11
Testing UL then DL assignment.
PDCH[6] is used for UL
PDCH[6] is control_ts for UL
PDCH[6] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[6] is control_ts for DL
PDCH[6] is first common for DL
Testing DL then UL assignment followed by update
PDCH[6] is used for DL
PDCH[6] is control_ts for DL
PDCH[6] is first common for DL
PDCH[6] is used for UL
PDCH[6] is control_ts for UL
PDCH[6] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[6] is control_ts for DL
PDCH[6] is first common for DL
Testing jolly example
PDCH[3] is used for UL
PDCH[3] is control_ts for UL
PDCH[3] is first common for UL
PDCH[1] is used for DL
PDCH[2] is used for DL
PDCH[3] is used for DL
PDCH[4] is used for DL
PDCH[3] is control_ts for DL
PDCH[3] is first common for DL
Going to test multislot assignment MS_CLASS=12
Testing UL then DL assignment.
PDCH[6] is used for UL
PDCH[6] is control_ts for UL
PDCH[6] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[6] is control_ts for DL
PDCH[6] is first common for DL
Testing DL then UL assignment followed by update
PDCH[6] is used for DL
PDCH[6] is control_ts for DL
PDCH[6] is first common for DL
PDCH[6] is used for UL
PDCH[6] is control_ts for UL
PDCH[6] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[6] is control_ts for DL
PDCH[6] is first common for DL
Testing jolly example
PDCH[3] is used for UL
PDCH[3] is control_ts for UL
PDCH[3] is first common for UL
PDCH[1] is used for DL
PDCH[2] is used for DL
PDCH[3] is used for DL
PDCH[4] is used for DL
PDCH[3] is control_ts for DL
PDCH[3] is first common for DL
Going to test multislot assignment MS_CLASS=13
Testing UL then DL assignment.
PDCH[5] is used for UL
PDCH[5] is control_ts for UL
PDCH[5] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
Testing DL then UL assignment followed by update
PDCH[5] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
PDCH[5] is used for UL
PDCH[6] is used for UL
PDCH[7] is used for UL
PDCH[5] is control_ts for UL
PDCH[5] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
Testing jolly example
PDCH[1] is used for UL
PDCH[2] is used for UL
PDCH[3] is used for UL
PDCH[1] is control_ts for UL
PDCH[1] is first common for UL
PDCH[1] is used for DL
PDCH[2] is used for DL
PDCH[3] is used for DL
PDCH[1] is control_ts for DL
PDCH[1] is first common for DL
Going to test multislot assignment MS_CLASS=14
Testing UL then DL assignment.
PDCH[5] is used for UL
PDCH[5] is control_ts for UL
PDCH[5] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
Testing DL then UL assignment followed by update
PDCH[5] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
PDCH[5] is used for UL
PDCH[6] is used for UL
PDCH[7] is used for UL
PDCH[5] is control_ts for UL
PDCH[5] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
Testing jolly example
PDCH[1] is used for UL
PDCH[2] is used for UL
PDCH[3] is used for UL
PDCH[4] is used for UL
PDCH[1] is control_ts for UL
PDCH[1] is first common for UL
PDCH[1] is used for DL
PDCH[2] is used for DL
PDCH[3] is used for DL
PDCH[4] is used for DL
PDCH[1] is control_ts for DL
PDCH[1] is first common for DL
Going to test multislot assignment MS_CLASS=15
Testing UL then DL assignment.
PDCH[5] is used for UL
PDCH[5] is control_ts for UL
PDCH[5] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
Testing DL then UL assignment followed by update
PDCH[5] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
PDCH[5] is used for UL
PDCH[6] is used for UL
PDCH[7] is used for UL
PDCH[5] is control_ts for UL
PDCH[5] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
Testing jolly example
PDCH[1] is used for UL
PDCH[2] is used for UL
PDCH[3] is used for UL
PDCH[4] is used for UL
PDCH[1] is control_ts for UL
PDCH[1] is first common for UL
PDCH[1] is used for DL
PDCH[2] is used for DL
PDCH[3] is used for DL
PDCH[4] is used for DL
PDCH[1] is control_ts for DL
PDCH[1] is first common for DL
Going to test multislot assignment MS_CLASS=16
Testing UL then DL assignment.
PDCH[5] is used for UL
PDCH[5] is control_ts for UL
PDCH[5] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
Testing DL then UL assignment followed by update
PDCH[5] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
PDCH[5] is used for UL
PDCH[6] is used for UL
PDCH[7] is used for UL
PDCH[5] is control_ts for UL
PDCH[5] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
Testing jolly example
PDCH[1] is used for UL
PDCH[2] is used for UL
PDCH[3] is used for UL
PDCH[4] is used for UL
PDCH[1] is control_ts for UL
PDCH[1] is first common for UL
PDCH[1] is used for DL
PDCH[2] is used for DL
PDCH[3] is used for DL
PDCH[4] is used for DL
PDCH[1] is control_ts for DL
PDCH[1] is first common for DL
Going to test multislot assignment MS_CLASS=17
Testing UL then DL assignment.
PDCH[5] is used for UL
PDCH[5] is control_ts for UL
PDCH[5] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
Testing DL then UL assignment followed by update
PDCH[5] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
PDCH[5] is used for UL
PDCH[6] is used for UL
PDCH[7] is used for UL
PDCH[5] is control_ts for UL
PDCH[5] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
Testing jolly example
PDCH[1] is used for UL
PDCH[2] is used for UL
PDCH[3] is used for UL
PDCH[4] is used for UL
PDCH[1] is control_ts for UL
PDCH[1] is first common for UL
PDCH[1] is used for DL
PDCH[2] is used for DL
PDCH[3] is used for DL
PDCH[4] is used for DL
PDCH[1] is control_ts for DL
PDCH[1] is first common for DL
Going to test multislot assignment MS_CLASS=18
Testing UL then DL assignment.
PDCH[5] is used for UL
PDCH[5] is control_ts for UL
PDCH[5] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
Testing DL then UL assignment followed by update
PDCH[5] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
PDCH[5] is used for UL
PDCH[6] is used for UL
PDCH[7] is used for UL
PDCH[5] is control_ts for UL
PDCH[5] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
Testing jolly example
PDCH[1] is used for UL
PDCH[2] is used for UL
PDCH[3] is used for UL
PDCH[4] is used for UL
PDCH[1] is control_ts for UL
PDCH[1] is first common for UL
PDCH[1] is used for DL
PDCH[2] is used for DL
PDCH[3] is used for DL
PDCH[4] is used for DL
PDCH[1] is control_ts for DL
PDCH[1] is first common for DL
Going to test multislot assignment MS_CLASS=19
Testing UL then DL assignment.
PDCH[5] is used for UL
PDCH[5] is control_ts for UL
PDCH[5] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
Testing DL then UL assignment followed by update
PDCH[5] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
PDCH[5] is used for UL
PDCH[5] is control_ts for UL
PDCH[5] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
Testing jolly example
PDCH[2] is used for UL
PDCH[2] is control_ts for UL
PDCH[2] is first common for UL
PDCH[1] is used for DL
PDCH[2] is used for DL
PDCH[3] is used for DL
PDCH[4] is used for DL
PDCH[2] is control_ts for DL
PDCH[2] is first common for DL
Going to test multislot assignment MS_CLASS=20
Testing UL then DL assignment.
PDCH[5] is used for UL
PDCH[5] is control_ts for UL
PDCH[5] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
Testing DL then UL assignment followed by update
PDCH[5] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
PDCH[5] is used for UL
PDCH[5] is control_ts for UL
PDCH[5] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
Testing jolly example
PDCH[2] is used for UL
PDCH[2] is control_ts for UL
PDCH[2] is first common for UL
PDCH[1] is used for DL
PDCH[2] is used for DL
PDCH[3] is used for DL
PDCH[4] is used for DL
PDCH[2] is control_ts for DL
PDCH[2] is first common for DL
Going to test multislot assignment MS_CLASS=21
Testing UL then DL assignment.
PDCH[5] is used for UL
PDCH[5] is control_ts for UL
PDCH[5] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
Testing DL then UL assignment followed by update
PDCH[5] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
PDCH[5] is used for UL
PDCH[5] is control_ts for UL
PDCH[5] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
Testing jolly example
PDCH[2] is used for UL
PDCH[2] is control_ts for UL
PDCH[2] is first common for UL
PDCH[1] is used for DL
PDCH[2] is used for DL
PDCH[3] is used for DL
PDCH[4] is used for DL
PDCH[2] is control_ts for DL
PDCH[2] is first common for DL
Going to test multislot assignment MS_CLASS=22
Testing UL then DL assignment.
PDCH[5] is used for UL
PDCH[5] is control_ts for UL
PDCH[5] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
Testing DL then UL assignment followed by update
PDCH[5] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
PDCH[5] is used for UL
PDCH[5] is control_ts for UL
PDCH[5] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
Testing jolly example
PDCH[2] is used for UL
PDCH[2] is control_ts for UL
PDCH[2] is first common for UL
PDCH[1] is used for DL
PDCH[2] is used for DL
PDCH[3] is used for DL
PDCH[4] is used for DL
PDCH[2] is control_ts for DL
PDCH[2] is first common for DL
Going to test multislot assignment MS_CLASS=23
Testing UL then DL assignment.
PDCH[5] is used for UL
PDCH[5] is control_ts for UL
PDCH[5] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
Testing DL then UL assignment followed by update
PDCH[5] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
PDCH[5] is used for UL
PDCH[5] is control_ts for UL
PDCH[5] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
Testing jolly example
PDCH[2] is used for UL
PDCH[2] is control_ts for UL
PDCH[2] is first common for UL
PDCH[1] is used for DL
PDCH[2] is used for DL
PDCH[3] is used for DL
PDCH[4] is used for DL
PDCH[2] is control_ts for DL
PDCH[2] is first common for DL
Going to test multislot assignment MS_CLASS=24
Testing UL then DL assignment.
PDCH[5] is used for UL
PDCH[5] is control_ts for UL
PDCH[5] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
Testing DL then UL assignment followed by update
PDCH[5] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
PDCH[5] is used for UL
PDCH[5] is control_ts for UL
PDCH[5] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
Testing jolly example
PDCH[2] is used for UL
PDCH[2] is control_ts for UL
PDCH[2] is first common for UL
PDCH[1] is used for DL
PDCH[2] is used for DL
PDCH[3] is used for DL
PDCH[4] is used for DL
PDCH[2] is control_ts for DL
PDCH[2] is first common for DL
Going to test multislot assignment MS_CLASS=25
Testing UL then DL assignment.
PDCH[5] is used for UL
PDCH[5] is control_ts for UL
PDCH[5] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
Testing DL then UL assignment followed by update
PDCH[5] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
PDCH[5] is used for UL
PDCH[5] is control_ts for UL
PDCH[5] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
Testing jolly example
PDCH[2] is used for UL
PDCH[2] is control_ts for UL
PDCH[2] is first common for UL
PDCH[1] is used for DL
PDCH[2] is used for DL
PDCH[3] is used for DL
PDCH[4] is used for DL
PDCH[2] is control_ts for DL
PDCH[2] is first common for DL
Going to test multislot assignment MS_CLASS=26
Testing UL then DL assignment.
PDCH[5] is used for UL
PDCH[5] is control_ts for UL
PDCH[5] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
Testing DL then UL assignment followed by update
PDCH[5] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
PDCH[5] is used for UL
PDCH[5] is control_ts for UL
PDCH[5] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
Testing jolly example
PDCH[2] is used for UL
PDCH[2] is control_ts for UL
PDCH[2] is first common for UL
PDCH[1] is used for DL
PDCH[2] is used for DL
PDCH[3] is used for DL
PDCH[4] is used for DL
PDCH[2] is control_ts for DL
PDCH[2] is first common for DL
Going to test multislot assignment MS_CLASS=27
Testing UL then DL assignment.
PDCH[5] is used for UL
PDCH[5] is control_ts for UL
PDCH[5] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
Testing DL then UL assignment followed by update
PDCH[5] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
PDCH[5] is used for UL
PDCH[5] is control_ts for UL
PDCH[5] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
Testing jolly example
PDCH[2] is used for UL
PDCH[2] is control_ts for UL
PDCH[2] is first common for UL
PDCH[1] is used for DL
PDCH[2] is used for DL
PDCH[3] is used for DL
PDCH[4] is used for DL
PDCH[2] is control_ts for DL
PDCH[2] is first common for DL
Going to test multislot assignment MS_CLASS=28
Testing UL then DL assignment.
PDCH[5] is used for UL
PDCH[5] is control_ts for UL
PDCH[5] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
Testing DL then UL assignment followed by update
PDCH[5] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
PDCH[5] is used for UL
PDCH[5] is control_ts for UL
PDCH[5] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
Testing jolly example
PDCH[2] is used for UL
PDCH[2] is control_ts for UL
PDCH[2] is first common for UL
PDCH[1] is used for DL
PDCH[2] is used for DL
PDCH[3] is used for DL
PDCH[4] is used for DL
PDCH[2] is control_ts for DL
PDCH[2] is first common for DL
Going to test multislot assignment MS_CLASS=29
Testing UL then DL assignment.
PDCH[5] is used for UL
PDCH[5] is control_ts for UL
PDCH[5] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
Testing DL then UL assignment followed by update
PDCH[5] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
PDCH[5] is used for UL
PDCH[5] is control_ts for UL
PDCH[5] is first common for UL
PDCH[5] is used for DL
PDCH[6] is used for DL
PDCH[7] is used for DL
PDCH[5] is control_ts for DL
PDCH[5] is first common for DL
Testing jolly example
PDCH[2] is used for UL
PDCH[2] is control_ts for UL
PDCH[2] is first common for UL
PDCH[1] is used for DL
PDCH[2] is used for DL
PDCH[3] is used for DL
PDCH[4] is used for DL
PDCH[2] is control_ts for DL
PDCH[2] is first common for DL