diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/bts.cpp | 11 | ||||
-rw-r--r-- | src/bts.h | 1 | ||||
-rw-r--r-- | src/gprs_rlcmac_sched.cpp | 18 | ||||
-rw-r--r-- | src/tbf_dl.cpp | 36 | ||||
-rw-r--r-- | src/tbf_dl.h | 6 |
5 files changed, 52 insertions, 20 deletions
diff --git a/src/bts.cpp b/src/bts.cpp index 4097f942..13766865 100644 --- a/src/bts.cpp +++ b/src/bts.cpp @@ -1123,6 +1123,17 @@ void BTS::set_max_mcs_ul(uint8_t mcs_ul) m_max_mcs_ul = mcs_ul; } +bool BTS::cs_dl_is_supported(CodingScheme cs) +{ + OSMO_ASSERT(mcs_is_valid(cs)); + uint8_t num = mcs_chan_code(cs); + if (mcs_is_gprs(cs)) { + return (max_cs_dl() >= num) && (m_bts.cs_mask & (1U << num)); + } else { + return (max_mcs_dl() >= num) && (m_bts.mcs_mask & (1U << num)); + } +} + GprsMs *BTS::ms_alloc(uint8_t ms_class, uint8_t egprs_ms_class) { GprsMs *ms; @@ -339,6 +339,7 @@ public: void set_max_cs_ul(uint8_t cs_ul); void set_max_mcs_dl(uint8_t mcs_dl); void set_max_mcs_ul(uint8_t mcs_ul); + bool cs_dl_is_supported(CodingScheme cs); GprsMsStorage &ms_store(); GprsMs *ms_by_tlli(uint32_t tlli, uint32_t old_tlli = GSM_RESERVED_TMSI); diff --git a/src/gprs_rlcmac_sched.cpp b/src/gprs_rlcmac_sched.cpp index 537929bb..84a5970b 100644 --- a/src/gprs_rlcmac_sched.cpp +++ b/src/gprs_rlcmac_sched.cpp @@ -305,9 +305,6 @@ static struct msgb *sched_select_downlink(struct gprs_rlcmac_bts *bts, /* If a GPRS (CS1-4) Dl block is required, skip EGPRS(_GSMK) tbfs: */ if (req_mcs_kind == GPRS && tbf->is_egprs_enabled()) continue; - /* TODO: If a GPRS (CS1-4/MCS1-4) Dl block is required, downgrade MCS below instead of skipping */ - if (req_mcs_kind == EGPRS_GMSK && (tbf->is_egprs_enabled() || tbf->ms()->mode() != GPRS)) - continue; age = tbf->frames_since_last_poll(fn); @@ -316,6 +313,15 @@ static struct msgb *sched_select_downlink(struct gprs_rlcmac_bts *bts, if (prio == DL_PRIO_NONE) continue; + /* If a GPRS (CS1-4/MCS1-4) Dl block is required, downgrade MCS + * below instead of skipping. However, downgrade can only be + * done on new data BSNs (not yet sent) and control blocks. */ + if (req_mcs_kind == EGPRS_GMSK && tbf->is_egprs_enabled() && + (prio !=DL_PRIO_CONTROL && prio != DL_PRIO_NEW_DATA)) { + LOGP(DRLCMACSCHED, LOGL_DEBUG, "Cannot downgrade EGPRS TBF with prio %d\n", prio); + continue; + } + /* get the TBF with the highest priority */ if (prio > max_prio) { prio_tfi = tfi; @@ -326,12 +332,12 @@ static struct msgb *sched_select_downlink(struct gprs_rlcmac_bts *bts, if (prio_tbf) { LOGP(DRLCMACSCHED, LOGL_DEBUG, "Scheduling data message at " - "RTS for DL TFI=%d (TRX=%d, TS=%d) prio=%d\n", - prio_tfi, trx, ts, max_prio); + "RTS for DL TFI=%d (TRX=%d, TS=%d) prio=%d mcs_mode_restrict=%s\n", + prio_tfi, trx, ts, max_prio, mode_name(req_mcs_kind)); /* next TBF to handle resource is the next one */ pdch->next_dl_tfi = (prio_tfi + 1) & 31; /* generate DL data block */ - msg = prio_tbf->create_dl_acked_block(fn, ts); + msg = prio_tbf->create_dl_acked_block(fn, ts, req_mcs_kind); *is_egprs = prio_tbf->ms()->mode() != GPRS; } diff --git a/src/tbf_dl.cpp b/src/tbf_dl.cpp index 4b184b83..ad98510c 100644 --- a/src/tbf_dl.cpp +++ b/src/tbf_dl.cpp @@ -442,7 +442,7 @@ bool gprs_rlcmac_dl_tbf::restart_bsn_cycle() } int gprs_rlcmac_dl_tbf::take_next_bsn(uint32_t fn, - int previous_bsn, bool *may_combine) + int previous_bsn, enum mcs_kind req_mcs_kind, bool *may_combine) { int bsn; int data_len2, force_data_len = -1; @@ -456,6 +456,19 @@ int gprs_rlcmac_dl_tbf::take_next_bsn(uint32_t fn, if (!mcs_is_edge(force_cs)) return -1; force_data_len = m_rlc.block(previous_bsn)->len; + } else if (bsn < 0 && is_egprs_enabled() && req_mcs_kind == EGPRS_GMSK) { + /* New data to be sent for EGPRS TBF but we are required to downgrade to + * MCS1-4, because USF for GPRS-only MS will be sent */ + force_cs = m_ms->current_cs_dl(); + if (force_cs > MCS4) { + force_cs = bts->cs_dl_is_supported(MCS4) ? MCS4 : + bts->cs_dl_is_supported(MCS3) ? MCS3 : + bts->cs_dl_is_supported(MCS2) ? MCS2 : + MCS1; + LOGPTBFDL(this, LOGL_DEBUG, + "Force downgrading DL %s -> %s due to USF for GPRS-only MS\n", + mcs_name(m_ms->current_cs_dl()), mcs_name(force_cs)); + } } if (bsn >= 0) { @@ -510,7 +523,7 @@ int gprs_rlcmac_dl_tbf::take_next_bsn(uint32_t fn, m_window.v_a()); bts->do_rate_ctr_inc(CTR_RLC_RESTARTED); if (restart_bsn_cycle()) - return take_next_bsn(fn, previous_bsn, may_combine); + return take_next_bsn(fn, previous_bsn, req_mcs_kind, may_combine); } else if (dl_window_stalled()) { /* There are no more packages to send, but the window is stalled. * Restart the bsn_cycle to resend all unacked messages */ @@ -519,14 +532,15 @@ int gprs_rlcmac_dl_tbf::take_next_bsn(uint32_t fn, m_window.v_a()); bts->do_rate_ctr_inc(CTR_RLC_STALLED); if (restart_bsn_cycle()) - return take_next_bsn(fn, previous_bsn, may_combine); + return take_next_bsn(fn, previous_bsn, req_mcs_kind, may_combine); } else if (have_data()) { /* The window has space left, generate new bsn */ enum CodingScheme new_cs; new_cs = force_cs ? force_cs : current_cs(); LOGPTBFDL(this, LOGL_DEBUG, - "Sending new block at BSN %d, CS=%s\n", - m_window.v_s(), mcs_name(new_cs)); + "Sending new block at BSN %d, CS=%s%s\n", + m_window.v_s(), mcs_name(new_cs), + force_cs ? " (forced)" : ""); bsn = create_new_bsn(fn, new_cs); } else if (bts->bts_data()->dl_tbf_preemptive_retransmission && !m_window.window_empty()) { @@ -537,7 +551,7 @@ int gprs_rlcmac_dl_tbf::take_next_bsn(uint32_t fn, m_window.v_a()); bts->do_rate_ctr_inc(CTR_RLC_RESTARTED); if (restart_bsn_cycle()) - return take_next_bsn(fn, previous_bsn, may_combine); + return take_next_bsn(fn, previous_bsn, req_mcs_kind, may_combine); } else { /* Nothing left to send, create dummy LLC commands */ LOGPTBFDL(this, LOGL_DEBUG, @@ -565,20 +579,20 @@ int gprs_rlcmac_dl_tbf::take_next_bsn(uint32_t fn, * Create DL data block * The messages are fragmented and forwarded as data blocks. */ -struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block(uint32_t fn, uint8_t ts) +struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block(uint32_t fn, uint8_t ts, enum mcs_kind req_mcs_kind) { int bsn, bsn2 = -1; bool may_combine; - LOGPTBFDL(this, LOGL_DEBUG, "downlink (V(A)==%d .. V(S)==%d)\n", - m_window.v_a(), m_window.v_s()); + LOGPTBFDL(this, LOGL_DEBUG, "downlink (V(A)==%d .. V(S)==%d) mcs_mode_restrict=%s\n", + m_window.v_a(), m_window.v_s(), mode_name(req_mcs_kind)); - bsn = take_next_bsn(fn, -1, &may_combine); + bsn = take_next_bsn(fn, -1, req_mcs_kind, &may_combine); if (bsn < 0) return NULL; if (may_combine) - bsn2 = take_next_bsn(fn, bsn, &may_combine); + bsn2 = take_next_bsn(fn, bsn, req_mcs_kind, &may_combine); return create_dl_acked_block(fn, ts, bsn, bsn2); } diff --git a/src/tbf_dl.h b/src/tbf_dl.h index 685e855a..ffb370c3 100644 --- a/src/tbf_dl.h +++ b/src/tbf_dl.h @@ -54,7 +54,7 @@ struct gprs_rlcmac_dl_tbf : public gprs_rlcmac_tbf { int rcvd_dl_ack(bool final, uint8_t ssn, uint8_t *rbb); int rcvd_dl_ack(bool final_ack, unsigned first_bsn, struct bitvec *rbb); - struct msgb *create_dl_acked_block(uint32_t fn, uint8_t ts); + struct msgb *create_dl_acked_block(uint32_t fn, uint8_t ts, enum mcs_kind req_mcs_kind = EGPRS); void trigger_ass(struct gprs_rlcmac_tbf *old_tbf); bool handle_ack_nack(); @@ -106,8 +106,8 @@ protected: unsigned lost_bytes; }; - int take_next_bsn(uint32_t fn, int previous_bsn, - bool *may_combine); + int take_next_bsn(uint32_t fn, int previous_bsn, enum mcs_kind req_mcs_kind, + bool *may_combine); bool restart_bsn_cycle(); int create_new_bsn(const uint32_t fn, enum CodingScheme cs); struct msgb *create_dl_acked_block(const uint32_t fn, const uint8_t ts, |