diff --git a/src/tbf.cpp b/src/tbf.cpp index 42d522b..b604c68 100644 --- a/src/tbf.cpp +++ b/src/tbf.cpp @@ -960,6 +960,27 @@ void gprs_rlcmac_tbf::free_all(struct gprs_rlcmac_pdch *pdch) } } +int gprs_rlcmac_tbf::establish_dl_tbf_on_pacch() +{ + struct gprs_rlcmac_dl_tbf *new_tbf = NULL; + + bts->tbf_reused(); + + new_tbf = tbf_alloc_dl_tbf(bts->bts_data(), ms(), + this->trx->trx_no, ms_class(), 0); + + if (!new_tbf) { + LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH resource\n"); + return -1; + } + + LOGP(DRLCMAC, LOGL_DEBUG, "%s Trigger downlink assignment on PACCH\n", + tbf_name(this)); + bts->trigger_dl_ass(new_tbf, this); + + return 0; +} + int gprs_rlcmac_tbf::extract_tlli(const uint8_t *data, const size_t len) { struct gprs_rlcmac_tbf *dl_tbf = NULL; diff --git a/src/tbf.h b/src/tbf.h index b35ea78..3619910 100644 --- a/src/tbf.h +++ b/src/tbf.h @@ -137,6 +137,7 @@ struct gprs_rlcmac_tbf { void handle_timeout(); void stop_timer(); void stop_t3191(); + int establish_dl_tbf_on_pacch(); void poll_timeout(); @@ -337,6 +338,7 @@ struct gprs_rlcmac_dl_tbf : public gprs_rlcmac_tbf { int frames_since_last_poll(unsigned fn) const; int frames_since_last_drain(unsigned fn) const; bool keep_open(unsigned fn) const; + int release(); bool is_control_ts(uint8_t ts) const { return ts == control_ts; diff --git a/src/tbf_dl.cpp b/src/tbf_dl.cpp index b57e10e..aabe8e3 100644 --- a/src/tbf_dl.cpp +++ b/src/tbf_dl.cpp @@ -118,7 +118,7 @@ int gprs_rlcmac_dl_tbf::append_data(const uint8_t ms_class, "%s in WAIT RELEASE state " "(T3193), so reuse TBF\n", tbf_name(this)); tbf_update_ms_class(this, ms_class); - reuse_tbf(); + establish_dl_tbf_on_pacch(); } return 0; @@ -832,10 +832,21 @@ int gprs_rlcmac_dl_tbf::update_window(const uint8_t ssn, const uint8_t *rbb) int gprs_rlcmac_dl_tbf::maybe_start_new_window() +{ + release(); + + /* check for LLC PDU in the LLC Queue */ + if (llc_queue()->size() > 0) + /* we have more data so we will re-use this tbf */ + establish_dl_tbf_on_pacch(); + + return 0; +} + +int gprs_rlcmac_dl_tbf::release() { uint16_t received; - LOGP(DRLCMACDL, LOGL_DEBUG, "- Final ACK received.\n"); /* range V(A)..V(S)-1 */ received = m_window.count_unacked(); @@ -849,37 +860,6 @@ int gprs_rlcmac_dl_tbf::maybe_start_new_window() bts_data()->t3193_msec / 1000, (bts_data()->t3193_msec % 1000) * 1000); - /* check for LLC PDU in the LLC Queue */ - if (have_data()) - /* we have more data so we will re-use this tbf */ - reuse_tbf(); - - return 0; -} - -int gprs_rlcmac_dl_tbf::rcvd_dl_ack(uint8_t final_ack, uint8_t ssn, uint8_t *rbb) -{ - LOGP(DRLCMACDL, LOGL_DEBUG, "%s downlink acknowledge\n", tbf_name(this)); - - if (!final_ack) - return update_window(ssn, rbb); - return maybe_start_new_window(); -} - -void gprs_rlcmac_dl_tbf::reuse_tbf() -{ - struct gprs_rlcmac_dl_tbf *new_tbf = NULL; - - bts->tbf_reused(); - - new_tbf = tbf_alloc_dl_tbf(bts->bts_data(), ms(), - this->trx->trx_no, ms_class(), 0); - - if (!new_tbf) { - LOGP(DRLCMAC, LOGL_NOTICE, "No PDCH resource\n"); - return; - } - /* reset rlc states */ m_tx_counter = 0; m_wait_confirm = 0; @@ -889,10 +869,19 @@ void gprs_rlcmac_dl_tbf::reuse_tbf() state_flags &= GPRS_RLCMAC_FLAG_TO_MASK; state_flags &= ~(1 << GPRS_RLCMAC_FLAG_CCCH); - LOGP(DRLCMAC, LOGL_DEBUG, "%s Trigger dowlink assignment on PACCH, " - "because another LLC PDU has arrived in between\n", - tbf_name(this)); - bts->trigger_dl_ass(new_tbf, this); + return 0; +} + + +int gprs_rlcmac_dl_tbf::rcvd_dl_ack(uint8_t final_ack, uint8_t ssn, uint8_t *rbb) +{ + LOGP(DRLCMACDL, LOGL_DEBUG, "%s downlink acknowledge\n", tbf_name(this)); + + if (!final_ack) + return update_window(ssn, rbb); + + LOGP(DRLCMACDL, LOGL_DEBUG, "- Final ACK received.\n"); + return maybe_start_new_window(); } bool gprs_rlcmac_dl_tbf::dl_window_stalled() const diff --git a/tests/tbf/TbfTest.err b/tests/tbf/TbfTest.err index 6dc532e..024e2d8 100644 --- a/tests/tbf/TbfTest.err +++ b/tests/tbf/TbfTest.err @@ -97,7 +97,7 @@ PDCH(TS 4, TRX 0): Attaching TBF(TFI=1 TLLI=0x00000000 DIR=DL STATE=NULL), 2 TBF - Setting Control TS 4 Attaching TBF to MS object, TLLI = 0xffeeddcc, TBF = TBF(TFI=1 TLLI=0xffeeddcc DIR=DL STATE=NULL) Allocated TBF(TFI=1 TLLI=0xffeeddcc DIR=DL STATE=NULL): trx = 0, ul_slots = 10, dl_slots = 10 -TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE) Trigger dowlink assignment on PACCH, because another LLC PDU has arrived in between +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE) Trigger downlink assignment on PACCH Send dowlink assignment on PACCH, because TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE) exists TBF(TFI=1 TLLI=0xffeeddcc DIR=DL STATE=NULL) changes state from NULL to ASSIGN TBF(TFI=1 TLLI=0xffeeddcc DIR=DL STATE=ASSIGN) starting timer 0. @@ -175,7 +175,7 @@ PDCH(TS 4, TRX 0): Attaching TBF(TFI=1 TLLI=0x00000000 DIR=DL STATE=NULL), 2 TBF - Setting Control TS 4 Attaching TBF to MS object, TLLI = 0xffeeddcc, TBF = TBF(TFI=1 TLLI=0xffeeddcc DIR=DL STATE=NULL) Allocated TBF(TFI=1 TLLI=0xffeeddcc DIR=DL STATE=NULL): trx = 0, ul_slots = 10, dl_slots = 10 -TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE) Trigger dowlink assignment on PACCH, because another LLC PDU has arrived in between +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE) Trigger downlink assignment on PACCH Send dowlink assignment on PACCH, because TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE) exists TBF(TFI=1 TLLI=0xffeeddcc DIR=DL STATE=NULL) changes state from NULL to ASSIGN TBF(TFI=1 TLLI=0xffeeddcc DIR=DL STATE=ASSIGN) starting timer 0. @@ -1951,10 +1951,13 @@ TBF(TFI=0 TLLI=0x00000000 DIR=UL STATE=FLOW) TX: START Immediate Assignment Upli Sending data request: trx=0 ts=0 sapi=2 arfcn=0 fn=0 block=0 data=2d 06 3f 10 0f 00 00 03 8b ed 07 00 c8 00 10 0b 2b 2b 2b 2b 2b 2b 2b UL DATA TFI=0 received (V(Q)=0 .. V(R)=0) Detaching TBF from MS object, TLLI = 0xf1223344, TBF = TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=ASSIGN) -Destroying MS object, TLLI = 0xf1223344 Attaching TBF to MS object, TLLI = 0x00000000, TBF = TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=ASSIGN) +Modifying MS object, TLLI = 0x00000000, IMSI '' -> '0011223344' +Modifying MS object, TLLI = 0x00000000, MS class 0 -> 1 +Clearing MS object, TLLI: 0xf1223344, IMSI: '0011223344' Modifying MS object, UL TLLI: 0x00000000 -> 0xf1223344, not yet confirmed Decoded premier TLLI=0xf1223344 of UL DATA TFI=0. +Destroying MS object, TLLI = 0x00000000 TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW) restarting timer 3169 while old timer 3169 pending - BSN 0 storing in window (0..63) - Raising V(R) to 1 @@ -1971,7 +1974,7 @@ No bctx TBF(TFI=0 TLLI=0xf1223344 DIR=UL STATE=FLOW) changes state from FLOW to FINISHED - Scheduling Ack/Nack, because TLLI is included. - Scheduling Ack/Nack, because last block has CV==0. -New MS: TLLI = 0xf1223344, TA = 7, IMSI = , LLC = 0 +New MS: TLLI = 0xf1223344, TA = 7, IMSI = 0011223344, LLC = 2 Sending data request: trx=0 ts=7 sapi=5 arfcn=0 fn=2654218 block=8 data=47 94 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b MS requests UL TBF on RACH, so we provide one: MS requests single block allocation @@ -2651,7 +2654,7 @@ PDCH(TS 7, TRX 0): Attaching TBF(TFI=1 TLLI=0x00000000 DIR=DL STATE=NULL), 2 TBF - Setting Control TS 7 Attaching TBF to MS object, TLLI = 0xf1223344, TBF = TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=NULL) Allocated TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=NULL): trx = 0, ul_slots = 80, dl_slots = 80 -TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=WAIT RELEASE) Trigger dowlink assignment on PACCH, because another LLC PDU has arrived in between +TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=WAIT RELEASE) Trigger downlink assignment on PACCH Send dowlink assignment on PACCH, because TBF(TFI=0 TLLI=0xf1223344 DIR=DL STATE=WAIT RELEASE) exists TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=NULL) changes state from NULL to ASSIGN TBF(TFI=1 TLLI=0xf1223344 DIR=DL STATE=ASSIGN) starting timer 0.