aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bts.cpp11
-rw-r--r--src/bts.h1
-rw-r--r--src/gprs_rlcmac_sched.cpp18
-rw-r--r--src/tbf_dl.cpp36
-rw-r--r--src/tbf_dl.h6
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;
diff --git a/src/bts.h b/src/bts.h
index 6f757158..fd520671 100644
--- a/src/bts.h
+++ b/src/bts.h
@@ -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,