aboutsummaryrefslogtreecommitdiffstats
path: root/src/tbf_dl.cpp
diff options
context:
space:
mode:
authorJacob Erlbeck <jerlbeck@sysmocom.de>2015-03-12 12:08:54 +0100
committerJacob Erlbeck <jerlbeck@sysmocom.de>2015-03-12 18:08:18 +0100
commit7c44415d785422b8f7e02059420e7c6feb89f4e9 (patch)
treed738e6cf35a93346b1b0144c820287346c660690 /src/tbf_dl.cpp
parent0eabffdc35bef3bb678014d4c377ab8a2ac5951f (diff)
tbf: Fix scheduling for DL Ack/Nack request
Currently the DL Ack/Nack is not requested, if the last chunk of the final LLC frame in the TBF fits exactly into the remaining space of the RLC block. It is also not requested, if the RRBP flag cannot be set due to scheduling issues (single block allocation, polling already pending for this TBF, ...). So up to POLL_ACK_AFTER_FRAMES (20) RLC data blocks will have to be resent, before requesting the Ack/Nack will be retried. This commit removes the first_fin_ack parameter of create_dl_acked_block entirely and adds a request_dl_ack() method that should be called, when the TBF's state changes to FINISHED. This request will be reset, when the block has been scheduled successfully. Since the first_fin_ack hasn't been set if chunk == space, calling request_dl_ack() on both places in create_new_bsn() when the state is changed to FINISHED will also fix the first issue described above. Note that DL scheduling might not be fair concerning access to first_ts when multiple TS are used for a TBF. In theory, a TBF might never get access to first_ts in the worst case. Sponsored-by: On-Waves ehf
Diffstat (limited to 'src/tbf_dl.cpp')
-rw-r--r--src/tbf_dl.cpp31
1 files changed, 19 insertions, 12 deletions
diff --git a/src/tbf_dl.cpp b/src/tbf_dl.cpp
index 89ca9c2a..dea18bd7 100644
--- a/src/tbf_dl.cpp
+++ b/src/tbf_dl.cpp
@@ -252,7 +252,7 @@ do_resend:
/* re-send block with negative aknowlegement */
m_window.m_v_b.mark_unacked(resend_bsn);
bts->rlc_resent();
- return create_dl_acked_block(fn, ts, resend_bsn, false);
+ return create_dl_acked_block(fn, ts, resend_bsn);
}
/* if the window has stalled, or transfer is complete,
@@ -281,7 +281,7 @@ do_resend:
/* we just send final block again */
int16_t index = m_window.v_s_mod(-1);
bts->rlc_resent();
- return create_dl_acked_block(fn, ts, index, false);
+ return create_dl_acked_block(fn, ts, index);
}
/* cycle through all unacked blocks */
@@ -295,7 +295,7 @@ do_resend:
" != V(S). PLEASE FIX!\n");
/* we just send final block again */
int16_t index = m_window.v_s_mod(-1);
- return create_dl_acked_block(fn, ts, index, false);
+ return create_dl_acked_block(fn, ts, index);
}
goto do_resend;
}
@@ -311,7 +311,6 @@ struct msgb *gprs_rlcmac_dl_tbf::create_new_bsn(const uint32_t fn, const uint8_t
uint8_t *delimiter, *data, *e_pointer;
uint16_t space, chunk;
gprs_rlc_data *rlc_data;
- bool first_fin_ack = false;
const uint16_t bsn = m_window.v_s();
LOGP(DRLCMACDL, LOGL_DEBUG, "- Sending new block at BSN %d\n",
@@ -377,6 +376,7 @@ struct msgb *gprs_rlcmac_dl_tbf::create_new_bsn(const uint32_t fn, const uint8_t
m_llc.reset();
/* final block */
rh->fbi = 1; /* we indicate final block */
+ request_dl_ack();
set_state(GPRS_RLCMAC_FINISHED);
/* return data block as message */
break;
@@ -448,8 +448,7 @@ struct msgb *gprs_rlcmac_dl_tbf::create_new_bsn(const uint32_t fn, const uint8_t
"done.\n");
li->e = 1; /* we cannot extend */
rh->fbi = 1; /* we indicate final block */
- first_fin_ack = true;
- /* + 1 indicates: first final ack */
+ request_dl_ack();
set_state(GPRS_RLCMAC_FINISHED);
break;
}
@@ -467,12 +466,17 @@ struct msgb *gprs_rlcmac_dl_tbf::create_new_bsn(const uint32_t fn, const uint8_t
m_window.m_v_b.mark_unacked(bsn);
m_window.increment_send();
- return create_dl_acked_block(fn, ts, bsn, first_fin_ack);
+ return create_dl_acked_block(fn, ts, bsn);
+}
+
+void gprs_rlcmac_dl_tbf::request_dl_ack()
+{
+ m_dl_ack_requested = true;
}
struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block(
const uint32_t fn, const uint8_t ts,
- const int index, const bool first_fin_ack)
+ const int index)
{
uint8_t *data;
struct rlc_dl_header *rh;
@@ -491,11 +495,12 @@ struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block(
/* poll after POLL_ACK_AFTER_FRAMES frames, or when final block is tx.
*/
- if (m_tx_counter >= POLL_ACK_AFTER_FRAMES || first_fin_ack ||
+ if (m_tx_counter >= POLL_ACK_AFTER_FRAMES || m_dl_ack_requested ||
need_poll) {
- if (first_fin_ack) {
+ if (m_dl_ack_requested) {
LOGP(DRLCMACDL, LOGL_DEBUG, "- Scheduling Ack/Nack "
- "polling, because first final block sent.\n");
+ "polling, because is was requested explicitly "
+ "(e.g. first final block sent).\n");
} else if (need_poll) {
LOGP(DRLCMACDL, LOGL_DEBUG, "- Scheduling Ack/Nack "
"polling, because polling timed out.\n");
@@ -513,7 +518,6 @@ struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block(
LOGP(DRLCMACDL, LOGL_DEBUG, "Polling cannot be "
"sheduled in this TS %d, waiting for "
"TS %d\n", ts, control_ts);
-#warning "What happens to the first_fin_ack in case something is already scheduled?"
else if (bts->sba()->find(trx->trx_no, ts, (fn + 13) % 2715648))
LOGP(DRLCMACDL, LOGL_DEBUG, "Polling cannot be "
"sheduled, because single block alllocation "
@@ -533,6 +537,9 @@ struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block(
/* Clear poll timeout flag */
state_flags &= ~(1 << GPRS_RLCMAC_FLAG_TO_DL_ACK);
+ /* Clear request flag */
+ m_dl_ack_requested = false;
+
/* set polling in header */
rh->rrbp = 0; /* N+13 */
rh->s_p = 1; /* Polling */