diff --git a/src/tbf.h b/src/tbf.h index 5637822d..64edc18a 100644 --- a/src/tbf.h +++ b/src/tbf.h @@ -408,7 +408,7 @@ protected: }; int take_next_bsn(uint32_t fn, int previous_bsn, - GprsCodingScheme *next_cs); + bool *may_combine); bool restart_bsn_cycle(); int create_new_bsn(const uint32_t fn, GprsCodingScheme cs); struct msgb *create_dl_acked_block(const uint32_t fn, const uint8_t ts, diff --git a/src/tbf_dl.cpp b/src/tbf_dl.cpp index 0a23de4a..27b975ee 100644 --- a/src/tbf_dl.cpp +++ b/src/tbf_dl.cpp @@ -355,9 +355,10 @@ bool gprs_rlcmac_dl_tbf::restart_bsn_cycle() } int gprs_rlcmac_dl_tbf::take_next_bsn(uint32_t fn, - int previous_bsn, GprsCodingScheme *next_cs) + int previous_bsn, bool *may_combine) { int bsn; + int data_len2, force_data_len = -1; GprsCodingScheme cs2; GprsCodingScheme force_cs; @@ -367,6 +368,7 @@ int gprs_rlcmac_dl_tbf::take_next_bsn(uint32_t fn, force_cs = m_rlc.block(previous_bsn)->cs; if (!force_cs.isEgprs()) return -1; + force_data_len = m_rlc.block(previous_bsn)->len; } if (bsn >= 0) { @@ -378,7 +380,8 @@ int gprs_rlcmac_dl_tbf::take_next_bsn(uint32_t fn, return -1; cs2 = m_rlc.block(bsn)->cs; - if (force_cs && !cs2.isCombinable(force_cs)) + data_len2 = m_rlc.block(bsn)->len; + if (force_data_len > 0 && force_data_len != data_len2) return -1; LOGP(DRLCMACDL, LOGL_DEBUG, "- Resending BSN %d\n", bsn); /* re-send block with negative aknowlegement */ @@ -390,14 +393,14 @@ int gprs_rlcmac_dl_tbf::take_next_bsn(uint32_t fn, m_window.v_a()); bts->rlc_restarted(); if (restart_bsn_cycle()) - return take_next_bsn(fn, previous_bsn, next_cs); + return take_next_bsn(fn, previous_bsn, may_combine); } else if (dl_window_stalled()) { LOGP(DRLCMACDL, LOGL_NOTICE, "- Restarting at BSN %d, " "because the window is stalled.\n", m_window.v_a()); bts->rlc_stalled(); if (restart_bsn_cycle()) - return take_next_bsn(fn, previous_bsn, next_cs); + return take_next_bsn(fn, previous_bsn, may_combine); } else if (have_data()) { /* New blocks may be send */ cs2 = force_cs ? force_cs : current_cs(); @@ -412,14 +415,14 @@ int gprs_rlcmac_dl_tbf::take_next_bsn(uint32_t fn, m_window.v_a()); bts->rlc_restarted(); if (restart_bsn_cycle()) - return take_next_bsn(fn, previous_bsn, next_cs); + return take_next_bsn(fn, previous_bsn, may_combine); } else { /* Nothing left to send, create dummy LLC commands */ LOGP(DRLCMACDL, LOGL_DEBUG, "- Sending new dummy block at BSN %d, CS=%s\n", m_window.v_s(), current_cs().name()); bsn = create_new_bsn(fn, current_cs()); - /* Don't send a second block */ + /* Don't send a second block, so don't set cs2 */ } if (bsn < 0) { @@ -430,7 +433,7 @@ int gprs_rlcmac_dl_tbf::take_next_bsn(uint32_t fn, bts->rlc_resent(); } - *next_cs = cs2; + *may_combine = cs2.numDataBlocks() > 1; return bsn; } @@ -442,18 +445,18 @@ int gprs_rlcmac_dl_tbf::take_next_bsn(uint32_t fn, struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block(uint32_t fn, uint8_t ts) { int bsn, bsn2 = -1; - GprsCodingScheme cs, next_cs; + bool may_combine; LOGP(DRLCMACDL, LOGL_DEBUG, "%s downlink (V(A)==%d .. " "V(S)==%d)\n", tbf_name(this), m_window.v_a(), m_window.v_s()); - bsn = take_next_bsn(fn, -1, &next_cs); + bsn = take_next_bsn(fn, -1, &may_combine); if (bsn < 0) return NULL; - if (next_cs.numDataBlocks() > 1) - bsn2 = take_next_bsn(fn, bsn, &next_cs); + if (may_combine) + bsn2 = take_next_bsn(fn, bsn, &may_combine); return create_dl_acked_block(fn, ts, bsn, bsn2); } @@ -651,9 +654,14 @@ struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block( rdbi = &rlc.block_info[data_block_idx]; block_info = &m_rlc.block(bsn)->block_info; - OSMO_ASSERT(data_block_idx < ARRAY_SIZE(rlc.block_info)); - OSMO_ASSERT(rdbi->data_len == m_rlc.block(bsn)->block_info.data_len); - OSMO_ASSERT(sizeof(*rdbi) == sizeof(m_rlc.block(bsn)->block_info)); + if(rdbi->data_len != m_rlc.block(bsn)->len) { + LOGP(DRLCMACDL, LOGL_ERROR, + "ERROR: Expected len = %d for %s instead of " + "%d in data unit %d (BSN %d, %s)\n", + rdbi->data_len, cs.name(), m_rlc.block(bsn)->len, + data_block_idx, bsn, cs_enc.name()); + OSMO_ASSERT(rdbi->data_len == m_rlc.block(bsn)->len); + } rdbi->e = block_info->e; rdbi->cv = block_info->cv; rdbi->bsn = bsn;