diff options
-rw-r--r-- | src/bts.cpp | 130 | ||||
-rw-r--r-- | src/bts.h | 10 | ||||
-rw-r--r-- | src/gprs_rlcmac_ts_alloc.cpp | 2 | ||||
-rw-r--r-- | src/tbf.cpp | 17 | ||||
-rw-r--r-- | tests/alloc/AllocTest.cpp | 14 | ||||
-rw-r--r-- | tests/tbf/TbfTest.cpp | 4 | ||||
-rw-r--r-- | tests/tbf/TbfTest.err | 14 |
7 files changed, 98 insertions, 93 deletions
diff --git a/src/bts.cpp b/src/bts.cpp index 712954ea..412e0c03 100644 --- a/src/bts.cpp +++ b/src/bts.cpp @@ -257,48 +257,35 @@ gprs_rlcmac_ul_tbf *BTS::ul_tbf_by_poll_fn(uint32_t fn, uint8_t trx, uint8_t ts) } /* lookup downlink TBF Entity (by TFI) */ -gprs_rlcmac_dl_tbf *BTS::dl_tbf_by_tfi(uint8_t tfi, uint8_t trx) +gprs_rlcmac_dl_tbf *BTS::dl_tbf_by_tfi(uint8_t tfi, uint8_t trx, uint8_t ts) { - return static_cast<gprs_rlcmac_dl_tbf *>(tbf_by_tfi(tfi, trx, GPRS_RLCMAC_DL_TBF)); -} + if (trx >= 8 || ts >= 8) + return NULL; -/* lookup uplink TBF Entity (by TFI) */ -gprs_rlcmac_ul_tbf *BTS::ul_tbf_by_tfi(uint8_t tfi, uint8_t trx) -{ - return static_cast<gprs_rlcmac_ul_tbf *>(tbf_by_tfi(tfi, trx, GPRS_RLCMAC_UL_TBF)); + return m_bts.trx[trx].pdch[ts].dl_tbf_by_tfi(tfi); } -/* lookup TBF Entity (by TFI) */ -gprs_rlcmac_tbf *BTS::tbf_by_tfi(uint8_t tfi, uint8_t trx, - enum gprs_rlcmac_tbf_direction dir) +/* lookup uplink TBF Entity (by TFI) */ +gprs_rlcmac_ul_tbf *BTS::ul_tbf_by_tfi(uint8_t tfi, uint8_t trx, uint8_t ts) { - struct gprs_rlcmac_tbf *tbf; - - if (tfi >= 32 || trx >= 8) - return NULL; - - if (dir == GPRS_RLCMAC_UL_TBF) - tbf = m_bts.trx[trx].ul_tbf[tfi]; - else - tbf = m_bts.trx[trx].dl_tbf[tfi]; - if (!tbf) + if (trx >= 8 || ts >= 8) return NULL; - if (tbf->state_is_not(GPRS_RLCMAC_RELEASING)) { - return tbf; - } - - return NULL; + return m_bts.trx[trx].pdch[ts].ul_tbf_by_tfi(tfi); } -/* FIXME: spread resources over multiple TRX. Also add option to use same - * TRX in case of existing TBF for TLLI in the other direction. */ -/* search for free TFI and return TFI, TRX */ +/* + * Search for free TFI and return TFI, TRX. + * This method returns the first TFI that is currently not used in any PDCH of + * a TRX. The first TRX that contains such an TFI is returned. Negative values + * indicate errors. + */ int BTS::tfi_find_free(enum gprs_rlcmac_tbf_direction dir, uint8_t *_trx, int8_t use_trx) { struct gprs_rlcmac_pdch *pdch; - struct gprs_rlcmac_tbf **tbfp; + uint32_t free_tfis; + bool has_pdch = false; uint8_t trx_from, trx_to, trx, ts, tfi; if (use_trx >= 0 && use_trx < 8) @@ -308,42 +295,50 @@ int BTS::tfi_find_free(enum gprs_rlcmac_tbf_direction dir, trx_to = 7; } - /* on TRX find first enabled TS */ + /* find a TFI that is unused on all PDCH */ for (trx = trx_from; trx <= trx_to; trx++) { + bool trx_has_pdch = false; + + free_tfis = 0xffffffff; + for (ts = 0; ts < 8; ts++) { pdch = &m_bts.trx[trx].pdch[ts]; if (!pdch->is_enabled()) continue; - break; + free_tfis &= ~pdch->assigned_tfi(dir); + trx_has_pdch = true; + has_pdch = true; } - if (ts < 8) + if (trx_has_pdch && free_tfis) break; + + free_tfis = 0; } - if (trx > trx_to) { + if (!has_pdch) { LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH available.\n"); return -EINVAL; } + if (!free_tfis) { + LOGP(DRLCMAC, LOGL_NOTICE, "No TFI available.\n"); + return -EBUSY; + } - LOGP(DRLCMAC, LOGL_DEBUG, "Searching for first unallocated TFI: " - "TRX=%d first TS=%d\n", trx, ts); - if (dir == GPRS_RLCMAC_UL_TBF) - tbfp = m_bts.trx[trx].ul_tbf; - else - tbfp = m_bts.trx[trx].dl_tbf; + + LOGP(DRLCMAC, LOGL_DEBUG, + "Searching for first unallocated TFI: TRX=%d\n", trx); + + /* find the first */ for (tfi = 0; tfi < 32; tfi++) { - if (!tbfp[tfi]) + if (free_tfis & 1 << tfi) break; } - if (tfi < 32) { - LOGP(DRLCMAC, LOGL_DEBUG, " Found TFI=%d.\n", tfi); - *_trx = trx; - return tfi; - } - LOGP(DRLCMAC, LOGL_NOTICE, "No TFI available.\n"); + OSMO_ASSERT(tfi < 32); - return -1; + LOGP(DRLCMAC, LOGL_DEBUG, " Found TFI=%d.\n", tfi); + *_trx = trx; + return tfi; } int BTS::rcv_imm_ass_cnf(const uint8_t *data, uint32_t fn) @@ -693,7 +688,7 @@ int gprs_rlcmac_pdch::rcv_data_block_acknowledged(uint8_t *data, uint8_t len, } /* find TBF inst from given TFI */ - tbf = bts()->ul_tbf_by_tfi(rh->tfi, trx_no()); + tbf = ul_tbf_by_tfi(rh->tfi); if (!tbf) { LOGP(DRLCMACUL, LOGL_NOTICE, "UL DATA unknown TFI=%d\n", rh->tfi); @@ -990,7 +985,7 @@ void gprs_rlcmac_pdch::rcv_resource_request(Packet_Resource_Request_t *request, if (request->ID.u.Global_TFI.UnionType) { struct gprs_rlcmac_dl_tbf *dl_tbf; int8_t tfi = request->ID.u.Global_TFI.u.DOWNLINK_TFI; - dl_tbf = bts()->dl_tbf_by_tfi(tfi, trx_no()); + dl_tbf = bts()->dl_tbf_by_tfi(tfi, trx_no(), ts_no); if (!dl_tbf) { LOGP(DRLCMAC, LOGL_NOTICE, "PACKET RESSOURCE REQ unknown downlink TFI=%d\n", tfi); return; @@ -1001,7 +996,7 @@ void gprs_rlcmac_pdch::rcv_resource_request(Packet_Resource_Request_t *request, } else { struct gprs_rlcmac_ul_tbf *ul_tbf; int8_t tfi = request->ID.u.Global_TFI.u.UPLINK_TFI; - ul_tbf = bts()->ul_tbf_by_tfi(tfi, trx_no()); + ul_tbf = bts()->ul_tbf_by_tfi(tfi, trx_no(), ts_no); if (!ul_tbf) { LOGP(DRLCMAC, LOGL_NOTICE, "PACKET RESSOURCE REQ unknown uplink TFI=%d\n", tfi); return; @@ -1120,24 +1115,54 @@ gprs_rlcmac_tbf *gprs_rlcmac_pdch::tbf_from_list_by_tfi(struct llist_head *tbf_l gprs_rlcmac_ul_tbf *gprs_rlcmac_pdch::ul_tbf_by_tfi(uint8_t tfi) { - return static_cast<gprs_rlcmac_ul_tbf *>(tbf_from_list_by_tfi(&bts_data()->ul_tbfs, tfi, GPRS_RLCMAC_UL_TBF)); + return static_cast<gprs_rlcmac_ul_tbf *>( + tbf_by_tfi(tfi, GPRS_RLCMAC_UL_TBF)); } gprs_rlcmac_dl_tbf *gprs_rlcmac_pdch::dl_tbf_by_tfi(uint8_t tfi) { - return static_cast<gprs_rlcmac_dl_tbf *>(tbf_from_list_by_tfi(&bts_data()->dl_tbfs, tfi, GPRS_RLCMAC_DL_TBF)); + return static_cast<gprs_rlcmac_dl_tbf *>( + tbf_by_tfi(tfi, GPRS_RLCMAC_DL_TBF)); +} + +/* lookup TBF Entity (by TFI) */ +gprs_rlcmac_tbf *gprs_rlcmac_pdch::tbf_by_tfi(uint8_t tfi, + enum gprs_rlcmac_tbf_direction dir) +{ + struct gprs_rlcmac_tbf *tbf; + + if (tfi >= 32) + return NULL; + + tbf = m_tbfs[dir][tfi]; + + if (!tbf) + return NULL; + + if (tbf->state_is_not(GPRS_RLCMAC_RELEASING)) { + return tbf; + } + + return NULL; } void gprs_rlcmac_pdch::attach_tbf(gprs_rlcmac_tbf *tbf) { gprs_rlcmac_ul_tbf *ul_tbf; + if (m_tbfs[tbf->direction][tbf->tfi()]) + LOGP(DRLCMAC, LOGL_ERROR, "PDCH(TS %d, TRX %d): " + "%s has not been detached, overwriting it\n", + ts_no, trx_no(), + m_tbfs[tbf->direction][tbf->tfi()]->name()); + m_num_tbfs[tbf->direction] += 1; if (tbf->direction == GPRS_RLCMAC_UL_TBF) { ul_tbf = static_cast<gprs_rlcmac_ul_tbf *>(tbf); m_assigned_usf |= 1 << ul_tbf->m_usf[ts_no]; } m_assigned_tfi[tbf->direction] |= 1UL << tbf->tfi(); + m_tbfs[tbf->direction][tbf->tfi()] = tbf; LOGP(DRLCMAC, LOGL_INFO, "PDCH(TS %d, TRX %d): Attaching %s, %d TBFs, " "USFs = %02x, TFIs = %08x.\n", @@ -1157,6 +1182,7 @@ void gprs_rlcmac_pdch::detach_tbf(gprs_rlcmac_tbf *tbf) m_assigned_usf &= ~(1 << ul_tbf->m_usf[ts_no]); } m_assigned_tfi[tbf->direction] &= ~(1UL << tbf->tfi()); + m_tbfs[tbf->direction][tbf->tfi()] = NULL; LOGP(DRLCMAC, LOGL_INFO, "PDCH(TS %d, TRX %d): Detaching %s, %d TBFs, " "USFs = %02x, TFIs = %08x.\n", @@ -104,20 +104,21 @@ private: void rcv_measurement_report(Packet_Measurement_Report_t *t, uint32_t fn); gprs_rlcmac_tbf *tbf_from_list_by_tfi(struct llist_head *tbf_list, uint8_t tfi, enum gprs_rlcmac_tbf_direction dir); + gprs_rlcmac_tbf *tbf_by_tfi(uint8_t tfi, + enum gprs_rlcmac_tbf_direction dir); #endif uint8_t m_num_tbfs[2]; uint8_t m_num_reserved[2]; uint8_t m_assigned_usf; /* bit set */ uint32_t m_assigned_tfi[2]; /* bit set */ + struct gprs_rlcmac_tbf *m_tbfs[2][32]; }; struct gprs_rlcmac_trx { void *fl1h; uint16_t arfcn; struct gprs_rlcmac_pdch pdch[8]; - struct gprs_rlcmac_tbf *ul_tbf[32]; /* array of UL TBF, by UL TFI */ - struct gprs_rlcmac_tbf *dl_tbf[32]; /* array of DL TBF, by DL TFI */ /* back pointers */ struct BTS *bts; @@ -242,8 +243,8 @@ public: gprs_rlcmac_dl_tbf *dl_tbf_by_poll_fn(uint32_t fn, uint8_t trx, uint8_t ts); gprs_rlcmac_ul_tbf *ul_tbf_by_poll_fn(uint32_t fn, uint8_t trx, uint8_t ts); - gprs_rlcmac_dl_tbf *dl_tbf_by_tfi(uint8_t tfi, uint8_t trx); - gprs_rlcmac_ul_tbf *ul_tbf_by_tfi(uint8_t tfi, uint8_t trx); + gprs_rlcmac_dl_tbf *dl_tbf_by_tfi(uint8_t tfi, uint8_t trx, uint8_t ts); + gprs_rlcmac_ul_tbf *ul_tbf_by_tfi(uint8_t tfi, uint8_t trx, uint8_t ts); int tfi_find_free(enum gprs_rlcmac_tbf_direction dir, uint8_t *_trx, int8_t use_trx); @@ -293,7 +294,6 @@ private: PollController m_pollController; SBAController m_sba; struct rate_ctr_group *m_ratectrs; - gprs_rlcmac_tbf *tbf_by_tfi(uint8_t tfi, uint8_t trx, enum gprs_rlcmac_tbf_direction dir); GprsMsStorage m_ms_store; diff --git a/src/gprs_rlcmac_ts_alloc.cpp b/src/gprs_rlcmac_ts_alloc.cpp index 55c3ea68..b6f58861 100644 --- a/src/gprs_rlcmac_ts_alloc.cpp +++ b/src/gprs_rlcmac_ts_alloc.cpp @@ -300,7 +300,6 @@ static void assign_uplink_tbf_usf( int tfi, int8_t usf) { tbf->m_tfi = tfi; - tbf->trx->ul_tbf[tbf->tfi()] = tbf; tbf->m_usf[pdch->ts_no] = usf; attach_tbf_to_pdch(pdch, tbf); } @@ -311,7 +310,6 @@ static void assign_dlink_tbf( int tfi) { tbf->m_tfi = tfi; - tbf->trx->dl_tbf[tbf->tfi()] = tbf; attach_tbf_to_pdch(pdch, tbf); } diff --git a/src/tbf.cpp b/src/tbf.cpp index 70483e35..e3a441a7 100644 --- a/src/tbf.cpp +++ b/src/tbf.cpp @@ -201,11 +201,6 @@ static void tbf_unlink_pdch(struct gprs_rlcmac_tbf *tbf) { int ts; - if (tbf->direction == GPRS_RLCMAC_UL_TBF) - tbf->trx->ul_tbf[tbf->tfi()] = NULL; - else - tbf->trx->dl_tbf[tbf->tfi()] = NULL; - for (ts = 0; ts < 8; ts++) { if (!tbf->pdch[ts]) continue; @@ -800,16 +795,8 @@ struct msgb *gprs_rlcmac_tbf::create_ul_ass(uint32_t fn) void gprs_rlcmac_tbf::free_all(struct gprs_rlcmac_trx *trx) { - for (uint8_t tfi = 0; tfi < 32; tfi++) { - struct gprs_rlcmac_tbf *tbf; - - tbf = trx->ul_tbf[tfi]; - if (tbf) - tbf_free(tbf); - tbf = trx->dl_tbf[tfi]; - if (tbf) - tbf_free(tbf); - } + for (uint8_t ts = 0; ts < 8; ts++) + free_all(&trx->pdch[ts]); } void gprs_rlcmac_tbf::free_all(struct gprs_rlcmac_pdch *pdch) diff --git a/tests/alloc/AllocTest.cpp b/tests/alloc/AllocTest.cpp index e419cd25..7bc865d2 100644 --- a/tests/alloc/AllocTest.cpp +++ b/tests/alloc/AllocTest.cpp @@ -82,23 +82,17 @@ static void check_tfi_usage(BTS *the_bts) if (tbf->direction == GPRS_RLCMAC_DL_TBF) { OSMO_ASSERT(pdch->dl_tbf_by_tfi( tbf->tfi()) == tbf); - /* This assertion cannot hold with the - * current API and shared TFI */ -#if 0 OSMO_ASSERT(the_bts->dl_tbf_by_tfi( tbf->tfi(), - tbf->trx->trx_no) == tbf); -#endif + tbf->trx->trx_no, + pdch_no) == tbf); } else { OSMO_ASSERT(pdch->ul_tbf_by_tfi( tbf->tfi()) == tbf); - /* This assertion cannot hold with the - * current API and shared TFI */ -#if 0 OSMO_ASSERT(the_bts->ul_tbf_by_tfi( tbf->tfi(), - tbf->trx->trx_no) == tbf); -#endif + tbf->trx->trx_no, + pdch_no) == tbf); } *tbf_var = tbf; OSMO_ASSERT(pdch->assigned_tfi(tbf->direction) & diff --git a/tests/tbf/TbfTest.cpp b/tests/tbf/TbfTest.cpp index 159c8596..39f57ad8 100644 --- a/tests/tbf/TbfTest.cpp +++ b/tests/tbf/TbfTest.cpp @@ -526,7 +526,7 @@ static void test_tbf_single_phase() the_bts.rcv_rach(0x03, fn, qta); - ul_tbf = the_bts.ul_tbf_by_tfi(tfi, trx_no); + ul_tbf = the_bts.ul_tbf_by_tfi(tfi, trx_no, ts_no); OSMO_ASSERT(ul_tbf != NULL); fprintf(stderr, "Got '%s', TA=%d\n", @@ -605,7 +605,7 @@ static void test_tbf_two_phase() pdch->rcv_block(&buf[0], num_bytes, 2654270, &meas); /* check the TBF */ - ul_tbf = the_bts.ul_tbf_by_tfi(tfi, trx_no); + ul_tbf = the_bts.ul_tbf_by_tfi(tfi, trx_no, ts_no); OSMO_ASSERT(ul_tbf != NULL); fprintf(stderr, "Got '%s', TA=%d, CS=%d\n", diff --git a/tests/tbf/TbfTest.err b/tests/tbf/TbfTest.err index 72c3851f..ee57d638 100644 --- a/tests/tbf/TbfTest.err +++ b/tests/tbf/TbfTest.err @@ -35,7 +35,7 @@ Modifying MS object, TLLI: 0x00000000 -> 0x00002342, already confirmed partly The MS object cannot fully confirm an unexpected TLLI: 0x00004232, partly confirmed Modifying MS object, TLLI: 0x00002342 -> 0x00004232, already confirmed partly Modifying MS object, TLLI = 0x00004232, TA 4 -> 6 -Searching for first unallocated TFI: TRX=0 first TS=4 +Searching for first unallocated TFI: TRX=0 Found TFI=0. ********** TBF starts here ********** Allocating DL TBF: MS_CLASS=45 @@ -110,7 +110,7 @@ PDCH(TS 4, TRX 0): Detaching TBF(TFI=1 TLLI=0xffeeddcc DIR=DL STATE=ASSIGN), 0 T Detaching TBF from MS object, TLLI = 0xffeeddcc, TBF = TBF(TFI=1 TLLI=0xffeeddcc DIR=DL STATE=ASSIGN) ********** TBF ends here ********** Destroying MS object, TLLI = 0xffeeddcc -Searching for first unallocated TFI: TRX=0 first TS=4 +Searching for first unallocated TFI: TRX=0 Found TFI=0. ********** TBF starts here ********** Allocating DL TBF: MS_CLASS=45 @@ -185,7 +185,7 @@ TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=WAIT RELEASE) free PDCH(TS 4, TRX 0): Detaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=WAIT RELEASE), 0 TBFs, USFs = 00, TFIs = 00000000. ********** TBF ends here ********** Destroying MS object, TLLI = 0xffeeddcc -Searching for first unallocated TFI: TRX=0 first TS=4 +Searching for first unallocated TFI: TRX=0 Found TFI=0. ********** TBF starts here ********** Allocating DL TBF: MS_CLASS=45 @@ -414,7 +414,7 @@ PDCH(TS 4, TRX 0): Detaching TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE Detaching TBF from MS object, TLLI = 0xffeeddcc, TBF = TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE) Destroying MS object, TLLI = 0xffeeddcc ********** TBF ends here ********** -Searching for first unallocated TFI: TRX=0 first TS=4 +Searching for first unallocated TFI: TRX=0 Found TFI=0. ********** TBF starts here ********** Allocating DL TBF: MS_CLASS=45 @@ -434,7 +434,7 @@ PDCH(TS 4, TRX 0): Attaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL), 1 TBF Attaching TBF to MS object, TLLI = 0x00000000, TBF = TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL) Allocated TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL): trx = 0, ul_slots = 10, dl_slots = 10 TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL) changes state from NULL to FLOW -Searching for first unallocated TFI: TRX=0 first TS=4 +Searching for first unallocated TFI: TRX=0 Found TFI=1. ********** TBF starts here ********** Allocating DL TBF: MS_CLASS=45 @@ -1359,7 +1359,7 @@ data block: 07 01 04 4d 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 - Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent). Polling cannot be sheduled in this TS 7, waiting for TS 4 MSG = 07 01 04 4d 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 03 -Searching for first unallocated TFI: TRX=0 first TS=7 +Searching for first unallocated TFI: TRX=0 Found TFI=0. MS requests UL TBF on RACH, so we provide one: ********** TBF starts here ********** @@ -1412,7 +1412,7 @@ MS requests single block allocation RX: [PCU <- BTS] RACH qbit-ta=31 ra=0x73, Fn=2654167 (17,25,9), SBFn=2654270 TX: Immediate Assignment Uplink (AGCH) Sending data request: trx=0 ts=0 sapi=2 arfcn=0 fn=0 block=0 data=2d 06 3f 10 0f 00 00 73 8b 29 07 00 c0 0c 5a 43 2b 2b 2b 2b 2b 2b 2b -Searching for first unallocated TFI: TRX=0 first TS=7 +Searching for first unallocated TFI: TRX=0 Found TFI=0. +++++++++++++++++++++++++ RX : Uplink Control Block +++++++++++++++++++++++++ ------------------------- RX : Uplink Control Block ------------------------- |