MCS: add Channel Coding Command encoder

Add function to encode MCS value as proper EDGE or GPRS Channel Coding
value according to 3GPP TS 44.060 and corresponding helpers.

Use it for everything except IA Rest Octet encoding which is done in a
follow-up patches to make sure that we distinguish between
encoding-related changes to test output and unrelated changes.

Change-Id: I127fb29f5aaf77a7f6c4c565dfeb3b711af9845d
This commit is contained in:
Max 2019-03-12 15:50:57 +01:00
parent 48b1e7a86f
commit 898dddb1d1
7 changed files with 31 additions and 20 deletions

View File

@ -64,6 +64,19 @@ bool mcs_is_edge_gmsk(enum CodingScheme cs)
return false;
}
/* Return 3GPP TS 44.060 §12.10d (EDGE) or Table 11.2.28.2 (GPRS) Channel Coding Command value */
uint8_t mcs_chan_code(enum CodingScheme cs)
{
if (mcs_is_gprs(cs))
return cs - CS1;
if (mcs_is_edge(cs))
return cs - MCS1;
/* Defaults to (M)CS1 */
return 0;
}
static struct {
struct {
uint8_t data_header_bits;

View File

@ -37,6 +37,8 @@ bool mcs_is_gprs(enum CodingScheme cs);
bool mcs_is_edge(enum CodingScheme cs);
bool mcs_is_edge_gmsk(enum CodingScheme cs);
uint8_t mcs_chan_code(enum CodingScheme cs);
enum HeaderType {
HEADER_INVALID,
HEADER_GPRS_CONTROL,

View File

@ -67,10 +67,7 @@ CodingScheme GprsCodingScheme::get_retx_mcs(const GprsCodingScheme mcs,
const GprsCodingScheme demanded_mcs,
const unsigned arq_type)
{
OSMO_ASSERT(mcs.to_num() > 0);
OSMO_ASSERT(demanded_mcs.to_num() > 0);
return egprs_mcs_retx_tbl[arq_type][mcs.to_num() - 1][demanded_mcs.to_num() - 1];
return egprs_mcs_retx_tbl[arq_type][mcs_chan_code(mcs)][mcs_chan_code(demanded_mcs)];
}
static struct {

View File

@ -82,6 +82,7 @@ private:
enum CodingScheme m_scheme;
};
// FIXME: remove once < comparison operator below is no longer necessary
inline uint8_t GprsCodingScheme::to_num() const
{
if (mcs_is_gprs(m_scheme))

View File

@ -523,7 +523,7 @@ void GprsMs::update_error_rate(gprs_rlcmac_tbf *tbf, int error_rate)
m_nack_rate_dl = error_rate;
if (error_rate > bts_data->cs_adj_upper_limit) {
if (m_current_cs_dl.to_num() > 1) {
if (mcs_chan_code(m_current_cs_dl) > 0) {
m_current_cs_dl.dec(mode());
LOGP(DRLCMACDL, LOGL_INFO,
"MS (IMSI %s): High error rate %d%%, "
@ -621,7 +621,7 @@ void GprsMs::update_cs_ul(const pcu_l1_meas *meas)
int low;
int high;
GprsCodingScheme new_cs_ul = m_current_cs_ul;
uint8_t current_cs_num = m_current_cs_ul.to_num();
uint8_t current_cs = mcs_chan_code(m_current_cs_ul);
bts_data = m_bts->bts_data();
@ -632,8 +632,6 @@ void GprsMs::update_cs_ul(const pcu_l1_meas *meas)
return;
}
OSMO_ASSERT(current_cs_num > 0);
if (!m_current_cs_ul) {
LOGP(DRLCMACMEAS, LOGL_ERROR,
"Unable to update UL (M)CS because it's not set: %s\n",
@ -651,15 +649,15 @@ void GprsMs::update_cs_ul(const pcu_l1_meas *meas)
old_link_qual = meas->link_qual;
if (mcs_is_gprs(m_current_cs_ul)) {
if (current_cs_num > MAX_GPRS_CS)
current_cs_num = MAX_GPRS_CS;
low = bts_data->cs_lqual_ranges[current_cs_num-1].low;
high = bts_data->cs_lqual_ranges[current_cs_num-1].high;
if (current_cs >= MAX_GPRS_CS)
current_cs = MAX_GPRS_CS - 1;
low = bts_data->cs_lqual_ranges[current_cs].low;
high = bts_data->cs_lqual_ranges[current_cs].high;
} else if (mcs_is_edge(m_current_cs_ul)) {
if (current_cs_num > MAX_EDGE_MCS)
current_cs_num = MAX_EDGE_MCS;
low = bts_data->mcs_lqual_ranges[current_cs_num-1].low;
high = bts_data->mcs_lqual_ranges[current_cs_num-1].high;
if (current_cs >= MAX_EDGE_MCS)
current_cs = MAX_EDGE_MCS - 1;
low = bts_data->mcs_lqual_ranges[current_cs].low;
high = bts_data->mcs_lqual_ranges[current_cs].high;
} else {
LOGP(DRLCMACMEAS, LOGL_ERROR,
"Unable to update UL (M)CS because it's neither GPRS nor EDGE: %s\n",

View File

@ -520,11 +520,11 @@ static void test_ms_cs_selection()
dl_tbf->set_ms(ms);
OSMO_ASSERT(!ms->is_idle());
OSMO_ASSERT(ms->current_cs_dl().to_num() == 4);
OSMO_ASSERT(mcs_chan_code(ms->current_cs_dl()) == 3);
bts->cs_downgrade_threshold = 200;
OSMO_ASSERT(ms->current_cs_dl().to_num() == 3);
OSMO_ASSERT(mcs_chan_code(ms->current_cs_dl()) == 2);
talloc_free(dl_tbf);

View File

@ -2737,12 +2737,12 @@ static void tbf_cleanup(gprs_rlcmac_dl_tbf *dl_tbf)
#define CHECK_UNACKED(tbf, cs, bsn) do { \
OSMO_ASSERT(tbf->window()->m_v_b.is_unacked(bsn)); \
OSMO_ASSERT(tbf->m_rlc.block(bsn)->cs_current_trans.to_num() == cs); \
OSMO_ASSERT(mcs_chan_code(tbf->m_rlc.block(bsn)->cs_current_trans) == cs - 1); \
} while(0)
#define CHECK_NACKED(tbf, cs, bsn) do { \
OSMO_ASSERT(tbf->window()->m_v_b.is_nacked(bsn)); \
OSMO_ASSERT(tbf->m_rlc.block(bsn)->cs_current_trans.to_num() == cs); \
OSMO_ASSERT(mcs_chan_code(tbf->m_rlc.block(bsn)->cs_current_trans) == cs - 1); \
} while(0)
#define MAKE_ACKED(m, tbf, fn, cs, check_unacked) do { \