aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/bts.cpp130
-rw-r--r--src/bts.h10
-rw-r--r--src/gprs_rlcmac_ts_alloc.cpp2
-rw-r--r--src/tbf.cpp17
-rw-r--r--tests/alloc/AllocTest.cpp14
-rw-r--r--tests/tbf/TbfTest.cpp4
-rw-r--r--tests/tbf/TbfTest.err14
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",
diff --git a/src/bts.h b/src/bts.h
index 8784f4d5..ebfcd5e1 100644
--- a/src/bts.h
+++ b/src/bts.h
@@ -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 -------------------------