diff options
author | Jacob Erlbeck <jerlbeck@sysmocom.de> | 2015-06-04 12:12:32 +0200 |
---|---|---|
committer | Jacob Erlbeck <jerlbeck@sysmocom.de> | 2015-06-08 09:40:09 +0200 |
commit | 1751c62c980f8d6ed965e08fcb9ad1af485d8854 (patch) | |
tree | 80b46ca4327c0902778eb3fd62e4c751af866f98 /src/tbf_dl.cpp | |
parent | f47f68a9d8e4421398e2369e4b18de8c52a9d396 (diff) |
tbf: Add adaptive DL CS adjustment
To cope with transmission failures due to bad radio conditions, a
different coding scheme with more redundance can be used.
This commit adds an implemenation that is based on the Ack/Nack
ratio per PACKET DOWNLINK ACK/NACK message received from the MS.
Basically the CS level is decreased, if the block error rate goes
above cs_adj_upper_limit (default 33%), and it is increased, if the
rate drops below cs_adj_lower_limit (default 10%). Only blocks that
have been encoded with the current CS are taken into account.
Note that this approach doesn't measure the MS->BTS conditions and
that the measurement values reported by the MS are not taken into
account.
Ticket: #1739
Sponsored-by: On-Waves ehf
Diffstat (limited to 'src/tbf_dl.cpp')
-rw-r--r-- | src/tbf_dl.cpp | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/src/tbf_dl.cpp b/src/tbf_dl.cpp index 0aa41a26..0726ef79 100644 --- a/src/tbf_dl.cpp +++ b/src/tbf_dl.cpp @@ -412,6 +412,7 @@ struct msgb *gprs_rlcmac_dl_tbf::create_new_bsn(const uint32_t fn, const uint8_t /* now we still have untransmitted LLC data, so we fill mac block */ rlc_data = m_rlc.block(bsn); data = rlc_data->prepare(block_data_len); + rlc_data->cs = cs; rh = (struct rlc_dl_header *)data; rh->pt = 0; /* Data Block */ @@ -669,6 +670,53 @@ struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block( return dl_msg; } +static uint16_t bitnum_to_bsn(int bitnum, uint16_t ssn, uint16_t mod_sns) +{ + return (ssn - 1 - bitnum) & mod_sns; +} + +int gprs_rlcmac_dl_tbf::analyse_errors(char *show_rbb, uint8_t ssn) +{ + gprs_rlc_data *rlc_data; + uint16_t lost = 0, received = 0, skipped = 0; + + /* SSN - 1 is in range V(A)..V(S)-1 */ + for (int bitpos = 0; bitpos < m_window.ws(); bitpos++) { + uint16_t bsn = bitnum_to_bsn(bitpos, ssn, m_window.mod_sns()); + + if (bsn == ((m_window.v_a() - 1) & m_window.mod_sns())) + break; + + rlc_data = m_rlc.block(bsn); + if (!rlc_data) + continue; + + if (rlc_data->cs != current_cs()) { + /* This block has already been encoded with a different + * CS, so it doesn't help us to decide, whether the + * current CS is ok. Ignore it. */ + skipped += 1; + continue; + } + + if (show_rbb[m_window.ws() - 1 - bitpos] == 'R') { + if (!m_window.m_v_b.is_acked(bsn)) + received += 1; + } else { + lost += 1; + } + } + + LOGP(DRLCMACDL, LOGL_DEBUG, "%s DL analysis, range=%d:%d, lost=%d, recv=%d, skipped=%d\n", + name(), m_window.v_a(), m_window.v_s(), lost, received, skipped); + + if (lost + received == 0) + return -1; + + return lost * 100 / (lost + received); +} + + int gprs_rlcmac_dl_tbf::update_window(const uint8_t ssn, const uint8_t *rbb) { int16_t dist; /* must be signed */ @@ -676,6 +724,7 @@ int gprs_rlcmac_dl_tbf::update_window(const uint8_t ssn, const uint8_t *rbb) char show_rbb[65]; char show_v_b[RLC_MAX_SNS + 1]; const uint16_t mod_sns = m_window.mod_sns(); + int error_rate; Decoding::extract_rbb(rbb, show_rbb); /* show received array in debug (bit 64..1) */ @@ -698,6 +747,11 @@ int gprs_rlcmac_dl_tbf::update_window(const uint8_t ssn, const uint8_t *rbb) return 1; /* indicate to free TBF */ } + if (bts_data()->cs_adj_enabled && ms()) { + error_rate = analyse_errors(show_rbb, ssn); + ms()->update_error_rate(this, error_rate); + } + m_window.update(bts, show_rbb, ssn, &lost, &received); |