Hello,
if the network iniates a data transfer it will page the MS to open a TBF and since this paging happens over the CCCH it can only ask the MS to use one PDCH initially.
With this patch (and if there are more PDCH ts available) the PCU will remember that it can upgrade to use multiple timeslots and send a downlink assignment with the new timeslot allocation over the TBF.
Regards, Daniel
This function is called to act upon a received DL ACK packet so this name makes more sense. --- src/bts.cpp | 2 +- src/tbf.cpp | 2 +- src/tbf.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/bts.cpp b/src/bts.cpp index ff16e29..6c02408 100644 --- a/src/bts.cpp +++ b/src/bts.cpp @@ -805,7 +805,7 @@ void gprs_rlcmac_pdch::rcv_control_dl_ack_nack(Packet_Downlink_Ack_Nack_t *ack_n LOGP(DRLCMAC, LOGL_DEBUG, "RX: [PCU <- BTS] %s Packet Downlink Ack/Nack\n", tbf_name(tbf)); tbf->poll_state = GPRS_RLCMAC_POLL_NONE;
- rc = tbf->snd_dl_ack( + rc = tbf->rcvd_dl_ack( ack_nack->Ack_Nack_Description.FINAL_ACK_INDICATION, ack_nack->Ack_Nack_Description.STARTING_SEQUENCE_NUMBER, ack_nack->Ack_Nack_Description.RECEIVED_BLOCK_BITMAP); diff --git a/src/tbf.cpp b/src/tbf.cpp index d6b3802..b20d0fc 100644 --- a/src/tbf.cpp +++ b/src/tbf.cpp @@ -1425,7 +1425,7 @@ int gprs_rlcmac_tbf::maybe_start_new_window() return 0; }
-int gprs_rlcmac_tbf::snd_dl_ack(uint8_t final_ack, uint8_t ssn, uint8_t *rbb) +int gprs_rlcmac_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));
diff --git a/src/tbf.h b/src/tbf.h index c301960..24b98d2 100644 --- a/src/tbf.h +++ b/src/tbf.h @@ -103,7 +103,7 @@ struct gprs_rlcmac_tbf { struct msgb *create_dl_ass(uint32_t fn); struct msgb *create_ul_ass(uint32_t fn); struct msgb *create_ul_ack(uint32_t fn); - int snd_dl_ack(uint8_t final, uint8_t ssn, uint8_t *rbb); + int rcvd_dl_ack(uint8_t final, uint8_t ssn, uint8_t *rbb); int snd_ul_ud();
/* blocks were acked */
The current code does not properly distinguish between DL assignments to reuse a tbf (after it was put in state WAIT_RELEASE) and DL assignments for an active tbf to change the allocation of the PDCH timeslots.
This patch introduces a new variable was_releasing which remembers if trigger_dl_ass() was called with a tbf in state WAIT_RELEASE. In that case we have to set the CONTROL_ACK field in the download assignment.
This should allow us to send DL assignments to change PDCH TS allocation of a tbf before we enter FLOW state. --- src/bts.cpp | 2 ++ src/encoding.cpp | 2 +- src/tbf.cpp | 3 ++- src/tbf.h | 4 ++++ 4 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/src/bts.cpp b/src/bts.cpp index 6c02408..9003099 100644 --- a/src/bts.cpp +++ b/src/bts.cpp @@ -474,6 +474,7 @@ void BTS::trigger_dl_ass( old_tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_SEND_ASS; /* use TA from old TBF */ tbf->ta = old_tbf->ta; + tbf->was_releasing = tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE); /* change state */ tbf_new_state(tbf, GPRS_RLCMAC_ASSIGN); tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_PACCH); @@ -485,6 +486,7 @@ void BTS::trigger_dl_ass( LOGP(DRLCMAC, LOGL_ERROR, "No valid IMSI!\n"); return; } + tbf->was_releasing = tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE); /* change state */ tbf_new_state(tbf, GPRS_RLCMAC_ASSIGN); tbf->state_flags |= (1 << GPRS_RLCMAC_FLAG_CCCH); diff --git a/src/encoding.cpp b/src/encoding.cpp index 51b0fbe..13848aa 100644 --- a/src/encoding.cpp +++ b/src/encoding.cpp @@ -267,7 +267,7 @@ void Encoding::write_packet_downlink_assignment(RlcMacDownlink_t * block, uint8_
block->u.Packet_Downlink_Assignment.MAC_MODE = 0x0; // Dynamic Allocation block->u.Packet_Downlink_Assignment.RLC_MODE = 0x0; // RLC acknowledged mode - block->u.Packet_Downlink_Assignment.CONTROL_ACK = old_downlink; // NW establishes no new DL TBF for the MS with running timer T3192 + block->u.Packet_Downlink_Assignment.CONTROL_ACK = tbf->was_releasing; // NW establishes no new DL TBF for the MS with running timer T3192 block->u.Packet_Downlink_Assignment.TIMESLOT_ALLOCATION = 0; // timeslot(s) for (tn = 0; tn < 8; tn++) { if (tbf->pdch[tn]) diff --git a/src/tbf.cpp b/src/tbf.cpp index b20d0fc..dd1f0fb 100644 --- a/src/tbf.cpp +++ b/src/tbf.cpp @@ -1405,6 +1405,8 @@ int gprs_rlcmac_tbf::maybe_start_new_window() /* report all outstanding packets as received */ gprs_rlcmac_received_lost(this, received, 0);
+ tbf_new_state(this, GPRS_RLCMAC_WAIT_RELEASE); + /* check for LLC PDU in the LLC Queue */ msg = llc_dequeue(gprs_bssgp_pcu_current_bctx()); if (!msg) { @@ -1414,7 +1416,6 @@ int gprs_rlcmac_tbf::maybe_start_new_window() tbf_timer_start(this, 3193, bts_data()->t3193_msec / 1000, (bts_data()->t3193_msec % 1000) * 1000); - tbf_new_state(this, GPRS_RLCMAC_WAIT_RELEASE);
return 0; } diff --git a/src/tbf.h b/src/tbf.h index 24b98d2..0ee9718 100644 --- a/src/tbf.h +++ b/src/tbf.h @@ -217,6 +217,10 @@ struct gprs_rlcmac_tbf { * stops to iterate over all tbf in its current form */ enum gprs_rlcmac_tbf_state state;
+ /* Remember if the tbf was in wait_release state when we want to + * schedule a new dl assignment */ + uint8_t was_releasing; + /* store the BTS this TBF belongs to */ BTS *bts;
The current code would only ever assign one PDCH for the initial assignment (from CCCH). Only if reuse_tbf is called the algorithm would actually use multiple DL PDCHs if possible.
This patch introduced a tbf attribute upgrade_to_multislot that is set if we have multiple PDCH configured, and support multislot assignment, but can only assign a single PDCH (alloc_algorithm_b, parameter single is set). In this case after the assignment completes (and the MS is listening on a PDCH) we resend a DL assignment though the PACCH and this time we can assign multiple timeslots. --- src/gprs_rlcmac_ts_alloc.cpp | 9 +++++++++ src/tbf.cpp | 22 ++++++++++++++++++++-- src/tbf.h | 3 +++ 3 files changed, 32 insertions(+), 2 deletions(-)
diff --git a/src/gprs_rlcmac_ts_alloc.cpp b/src/gprs_rlcmac_ts_alloc.cpp index 366732c..a97cc65 100644 --- a/src/gprs_rlcmac_ts_alloc.cpp +++ b/src/gprs_rlcmac_ts_alloc.cpp @@ -175,6 +175,8 @@ int alloc_algorithm_a(struct gprs_rlcmac_bts *bts, /* the only one TS is the common TS */ tbf->first_ts = tbf->first_common_ts = ts;
+ tbf->upgrade_to_multislot = 0; + return 0; }
@@ -665,10 +667,17 @@ int alloc_algorithm_b(struct gprs_rlcmac_bts *bts, } } if (single && slotcount) { + uint8_t ts_count = 0; + for (ts = 0; ts < 8; ts++) + if ((tx_window & (1 << ts))) + ts_count++; + + tbf->upgrade_to_multislot = (ts_count > 1); LOGP(DRLCMAC, LOGL_INFO, "Using single slot at TS %d for %s\n", tbf->first_ts, (tbf->direction == GPRS_RLCMAC_DL_TBF) ? "DL" : "UL"); } else { + tbf->upgrade_to_multislot = 0; LOGP(DRLCMAC, LOGL_INFO, "Using %d slots for %s\n", slotcount, (tbf->direction == GPRS_RLCMAC_DL_TBF) ? "DL" : "UL"); } diff --git a/src/tbf.cpp b/src/tbf.cpp index dd1f0fb..3a2ad73 100644 --- a/src/tbf.cpp +++ b/src/tbf.cpp @@ -574,11 +574,29 @@ void gprs_rlcmac_tbf::handle_timeout() "in assign state\n", tbf_name(this)); } if ((state_flags & (1 << GPRS_RLCMAC_FLAG_CCCH))) { - /* change state to FLOW, so scheduler will start transmission */ dir.dl.wait_confirm = 0; if (state_is(GPRS_RLCMAC_ASSIGN)) { - tbf_new_state(this, GPRS_RLCMAC_FLOW); tbf_assign_control_ts(this); + + if (!upgrade_to_multislot) { + /* change state to FLOW, so scheduler + * will start transmission */ + tbf_new_state(this, GPRS_RLCMAC_FLOW); + break; + } + + /* This tbf can be upgraded to use multiple DL + * timeslots and now that there is already one + * slot assigned send another DL assignment via + * PDCH. */ + + /* keep to flags */ + state_flags &= GPRS_RLCMAC_FLAG_TO_MASK; + state_flags &= ~(1 << GPRS_RLCMAC_FLAG_CCCH); + + update(); + + bts->trigger_dl_ass(this, this, NULL); } else LOGP(DRLCMAC, LOGL_NOTICE, "%s Continue flow after " "IMM.ASS confirm\n", tbf_name(this)); diff --git a/src/tbf.h b/src/tbf.h index 0ee9718..80e2068 100644 --- a/src/tbf.h +++ b/src/tbf.h @@ -221,6 +221,9 @@ struct gprs_rlcmac_tbf { * schedule a new dl assignment */ uint8_t was_releasing;
+ /* Can/should we upgrade this tbf to use multiple slots? */ + uint8_t upgrade_to_multislot; + /* store the BTS this TBF belongs to */ BTS *bts;