This series of patches supports Incremental redundency for EGPRS DL case. These patches have been integration tested on Nuran 1.0 for EGPRS MCS 9 support in DL. And in UL only MCS4 has been tested. The EGPRS testing has been done with Browsing and Ping in DL with larger packet sizes(1500).
Aravind Sirsikar (4): Add data structure for MCS change in Retx Add Accessor functions for MCS change in Retx Modify DL tbf flow for MCS change in Retx Add test cases to support MCS change during Retx
src/gprs_coding_scheme.cpp | 36 ++++ src/gprs_coding_scheme.h | 27 ++- src/gprs_ms.cpp | 5 + src/gprs_ms.h | 1 + src/rlc.h | 10 ++ src/tbf_dl.cpp | 41 +++-- tests/tbf/TbfTest.cpp | 224 +++++++++++++++++++++++++ tests/tbf/TbfTest.err | 397 ++++++++++++++++++++++++++++++++++++++++++++ tests/tbf/TbfTest.ok | 9 + 9 files changed, 737 insertions(+), 13 deletions(-)
From: Aravind Sirsikar Arvind.sirsikar@radisys.com
Modify the existing data structure to support MCS change during Retx case in EGPRS DL. --- src/gprs_coding_scheme.cpp | 36 ++++++++++++++++++++++++++++++++++++ src/gprs_coding_scheme.h | 8 ++++++++ src/rlc.h | 10 ++++++++++ 3 files changed, 54 insertions(+)
diff --git a/src/gprs_coding_scheme.cpp b/src/gprs_coding_scheme.cpp index 8601d4f..4b47c0b 100644 --- a/src/gprs_coding_scheme.cpp +++ b/src/gprs_coding_scheme.cpp @@ -21,6 +21,42 @@
#include "gprs_coding_scheme.h"
+/* + * 44.060 Table 8.1.1.1 and Table 8.1.1.2 + * In has 3 level indexing. 0th level is ARQ type + * 1st level is Original MCS( index 0 corresponds to MCS1 and so on) + * 2nd level is MS MCS (index 0 corresponds to MCS1 and so on) + * in 0th level indexing only ARQ type 2 is supported i.e index 1 for + * incremental redundancy + */ + +/* TODO: Need to support ARQ type 1 */ +enum GprsCodingScheme::Scheme GprsCodingScheme::egprs_mcs_retx_tbl[MAX_NUM_ARQ] + [MAX_NUM_MCS][MAX_NUM_MCS] = { + { + {MCS1, MCS1, MCS1, MCS1, MCS1, MCS1, MCS1, MCS1, MCS1}, + {MCS2, MCS2, MCS2, MCS2, MCS2, MCS2, MCS2, MCS2, MCS2}, + {MCS3, MCS3, MCS3, MCS3, MCS3, MCS3, MCS3, MCS3, MCS3}, + {MCS1, MCS1, MCS1, MCS4, MCS4, MCS4, MCS4, MCS4, MCS4}, + {MCS2, MCS2, MCS2, MCS2, MCS5, MCS5, MCS7, MCS7, MCS7}, + {MCS3, MCS3, MCS3, MCS3, MCS3, MCS6, MCS6, MCS6, MCS9}, + {MCS2, MCS2, MCS2, MCS2, MCS5, MCS5, MCS7, MCS7, MCS7}, + {MCS3, MCS3, MCS3, MCS3, MCS3, MCS6, MCS6, MCS8, MCS8}, + {MCS3, MCS3, MCS3, MCS3, MCS3, MCS6, MCS6, MCS6, MCS9} + }, + { + {MCS1, MCS1, MCS1, MCS1, MCS1, MCS1, MCS1, MCS1, MCS1}, + {MCS2, MCS2, MCS2, MCS2, MCS2, MCS2, MCS2, MCS2, MCS2}, + {MCS3, MCS3, MCS3, MCS3, MCS3, MCS3, MCS3, MCS3, MCS3}, + {MCS4, MCS4, MCS4, MCS4, MCS4, MCS4, MCS4, MCS4, MCS4}, + {MCS5, MCS5, MCS5, MCS5, MCS5, MCS5, MCS7, MCS7, MCS7}, + {MCS6, MCS6, MCS6, MCS6, MCS6, MCS6, MCS6, MCS6, MCS9}, + {MCS5, MCS5, MCS5, MCS5, MCS5, MCS5, MCS7, MCS7, MCS7}, + {MCS6, MCS6, MCS6, MCS6, MCS6, MCS6, MCS6, MCS8, MCS8}, + {MCS6, MCS6, MCS6, MCS6, MCS6, MCS6, MCS6, MCS6, MCS9} + } + }; + static struct { struct { unsigned int bytes; diff --git a/src/gprs_coding_scheme.h b/src/gprs_coding_scheme.h index aec3762..bb0bad4 100644 --- a/src/gprs_coding_scheme.h +++ b/src/gprs_coding_scheme.h @@ -26,6 +26,12 @@
class GprsCodingScheme { public: + +#define MAX_NUM_ARQ 2 /* max. number of ARQ */ +#define MAX_NUM_MCS 9 /* max. number of MCS */ +#define EGPRS_ARQ1 0x0 +#define EGPRS_ARQ2 0x1 + enum Scheme { UNKNOWN, CS1, CS2, CS3, CS4, @@ -105,6 +111,8 @@ public: static GprsCodingScheme getEgprsByNum(unsigned num);
static const char *modeName(Mode mode); + static enum Scheme egprs_mcs_retx_tbl[MAX_NUM_ARQ] + [MAX_NUM_MCS][MAX_NUM_MCS]; private: GprsCodingScheme(int s); /* fail on use */ GprsCodingScheme& operator =(int s); /* fail on use */ diff --git a/src/rlc.h b/src/rlc.h index 8f75588..3b0b04c 100644 --- a/src/rlc.h +++ b/src/rlc.h @@ -120,6 +120,16 @@ struct gprs_rlc_data { uint8_t len;
struct gprs_rlc_data_block_info block_info; +/* + * cs_current_trans is variable to hold the cs value for + * current transmission. cs_current_trans is same as cs during + * transmission case. during retransmission cs_current_trans is + * fetched from egprs_mcs_retx_tbl table based on + * cs and demanded cs.reference is 44.060 Table + * 8.1.1.1 and Table 8.1.1.2 + */ + GprsCodingScheme cs_current_trans; + GprsCodingScheme cs;
/* puncturing scheme value to be used for next transmission*/
Add accessor function in existing classes to support MCS change during the retransmission in EGPRS DL --- src/gprs_coding_scheme.h | 19 ++++++++++++++++++- src/gprs_ms.cpp | 5 +++++ src/gprs_ms.h | 1 + 3 files changed, 24 insertions(+), 1 deletion(-)
diff --git a/src/gprs_coding_scheme.h b/src/gprs_coding_scheme.h index bb0bad4..fb3a191 100644 --- a/src/gprs_coding_scheme.h +++ b/src/gprs_coding_scheme.h @@ -70,6 +70,7 @@ public: unsigned int to_num() const;
GprsCodingScheme& operator =(Scheme s); + bool operator == (Scheme s); GprsCodingScheme& operator =(GprsCodingScheme o);
bool isValid() const {return UNKNOWN <= m_scheme && m_scheme <= MCS9;} @@ -111,6 +112,9 @@ public: static GprsCodingScheme getEgprsByNum(unsigned num);
static const char *modeName(Mode mode); + static Scheme get_retx_mcs(const GprsCodingScheme &mcs, + const GprsCodingScheme &retx_mcs); + static enum Scheme egprs_mcs_retx_tbl[MAX_NUM_ARQ] [MAX_NUM_MCS][MAX_NUM_MCS]; private: @@ -196,6 +200,13 @@ inline bool operator ==(GprsCodingScheme a, GprsCodingScheme b) return GprsCodingScheme::Scheme(a) == GprsCodingScheme::Scheme(b); }
+inline bool GprsCodingScheme::operator == (Scheme scheme) +{ + if (this->m_scheme == scheme) + return true; + return false; +} + inline bool operator !=(GprsCodingScheme a, GprsCodingScheme b) { return !(a == b); @@ -221,4 +232,10 @@ inline bool operator >=(GprsCodingScheme a, GprsCodingScheme b) { return a == b || a > b; } - +inline GprsCodingScheme::Scheme GprsCodingScheme::get_retx_mcs( + const GprsCodingScheme &mcs, + const GprsCodingScheme &demanded_mcs) +{ + return egprs_mcs_retx_tbl[EGPRS_ARQ2][mcs.to_num() - 1] + [demanded_mcs.to_num() - 1]; +} diff --git a/src/gprs_ms.cpp b/src/gprs_ms.cpp index 4296fd3..b9a04fb 100644 --- a/src/gprs_ms.cpp +++ b/src/gprs_ms.cpp @@ -574,6 +574,11 @@ GprsCodingScheme GprsMs::max_cs_ul() const return GprsCodingScheme(GprsCodingScheme::MCS4); }
+void GprsMs::set_current_cs_dl(GprsCodingScheme::Scheme scheme) +{ + m_current_cs_dl = scheme; +} + GprsCodingScheme GprsMs::max_cs_dl() const { struct gprs_rlcmac_bts *bts_data; diff --git a/src/gprs_ms.h b/src/gprs_ms.h index b07f175..bcc4fb3 100644 --- a/src/gprs_ms.h +++ b/src/gprs_ms.h @@ -86,6 +86,7 @@ public: uint8_t egprs_ms_class() const; void set_ms_class(uint8_t ms_class); void set_egprs_ms_class(uint8_t ms_class); + void set_current_cs_dl(GprsCodingScheme::Scheme scheme);
GprsCodingScheme current_cs_ul() const; GprsCodingScheme current_cs_dl() const;
Modify the DL TBF flow to support MCS change during the EGPRS retransmission --- src/tbf_dl.cpp | 41 +++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-)
diff --git a/src/tbf_dl.cpp b/src/tbf_dl.cpp index 9e4d078..17e3603 100644 --- a/src/tbf_dl.cpp +++ b/src/tbf_dl.cpp @@ -365,7 +365,7 @@ int gprs_rlcmac_dl_tbf::take_next_bsn(uint32_t fn, bsn = m_window.resend_needed();
if (previous_bsn >= 0) { - force_cs = m_rlc.block(previous_bsn)->cs; + force_cs = m_rlc.block(previous_bsn)->cs_current_trans; if (!force_cs.isEgprs()) return -1; force_data_len = m_rlc.block(previous_bsn)->len; @@ -379,7 +379,21 @@ int gprs_rlcmac_dl_tbf::take_next_bsn(uint32_t fn, m_window.mod_sns(bsn - previous_bsn) > RLC_EGPRS_MAX_BSN_DELTA) return -1;
- cs2 = m_rlc.block(bsn)->cs; + if (is_egprs_enabled()) { + m_rlc.block(bsn)->cs_current_trans = + GprsCodingScheme::get_retx_mcs(m_rlc.block(bsn)->cs, + ms()->current_cs_dl()); + + /* TODO: Need to remove this check when MCS-8 -> MCS-6 + * transistion is handled + */ + if (m_rlc.block(bsn)->cs == GprsCodingScheme::MCS8) + m_rlc.block(bsn)->cs_current_trans = + GprsCodingScheme::MCS8; + } else + m_rlc.block(bsn)->cs_current_trans = + m_rlc.block(bsn)->cs; + data_len2 = m_rlc.block(bsn)->len; if (force_data_len > 0 && force_data_len != data_len2) return -1; @@ -422,7 +436,7 @@ int gprs_rlcmac_dl_tbf::take_next_bsn(uint32_t fn, "- 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, so don't set cs2 */ + /* Don't send a second block, so don't set cs_current_trans*/ }
if (bsn < 0) { @@ -433,7 +447,7 @@ int gprs_rlcmac_dl_tbf::take_next_bsn(uint32_t fn, bts->rlc_resent(); }
- *may_combine = cs2.numDataBlocks() > 1; + *may_combine = m_rlc.block(bsn)->cs_current_trans.numDataBlocks() > 1;
return bsn; } @@ -505,6 +519,7 @@ int gprs_rlcmac_dl_tbf::create_new_bsn(const uint32_t fn, GprsCodingScheme cs) rlc_data = m_rlc.block(bsn); data = rlc_data->prepare(block_data_len); rlc_data->cs = cs; + rlc_data->cs_current_trans = cs; rlc_data->len = block_data_len;
rdbi = &(rlc_data->block_info); @@ -587,7 +602,6 @@ struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block( bool is_final = false; gprs_rlc_data_info rlc; GprsCodingScheme cs; - GprsCodingScheme cs_current_trans; int bsns[ARRAY_SIZE(rlc.block_info)]; unsigned num_bsns; enum egprs_puncturing_values punct[ARRAY_SIZE(rlc.block_info)]; @@ -601,7 +615,7 @@ struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block( * be put into the data area, even if the resulting CS is higher than * the current limit. */ - cs = m_rlc.block(index)->cs; + cs = m_rlc.block(index)->cs_current_trans; bsns[0] = index; num_bsns = 1;
@@ -613,6 +627,9 @@ struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block( if (num_bsns == 1) { /* TODO: remove the conditional when MCS-6 padding isn't * failing to be decoded by MEs anymore */ + /* TODO: support of MCS-8 -> MCS-6 transition should be + * handled + */ if (cs != GprsCodingScheme(GprsCodingScheme::MCS8)) cs.decToSingleBlock(&need_padding); } @@ -647,18 +664,16 @@ struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block( else bsn = bsns[0];
- cs_enc = m_rlc.block(bsn)->cs; + cs_enc = m_rlc.block(bsn)->cs_current_trans; +
/* get data and header from current block */ block_data = m_rlc.block(bsn)->block;
- /* TODO: Need to support MCS change during retx */ - cs_current_trans = cs; - /* Get current puncturing scheme from block */ punct_scheme = gprs_get_punct_scheme( m_rlc.block(bsn)->next_ps, - cs, cs_current_trans); + m_rlc.block(bsn)->cs, cs);
if (cs.isEgprs()) { OSMO_ASSERT(punct_scheme >= EGPRS_PS_1); @@ -682,7 +697,9 @@ struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block( * in header type 1 */ gprs_update_punct_scheme(&m_rlc.block(bsn)->next_ps, - cs_current_trans); + cs); + + m_rlc.block(bsn)->cs = m_rlc.block(bsn)->cs_current_trans;
rdbi->e = block_info->e; rdbi->cv = block_info->cv;
During MCS upgradation such as MCS6->MCS9, 2 blocks which were sent separately as MCS6, will be clubbed into one MCS9 block during retransmission. Same holds good for MCS5->MCS7 transistion. During MCS reduction such as MCS9->MCS6,2 blocks which were sent together will be sent separately during the retransmission case. Same is verified through the generated log file. Currently MCS8->MCS6 transition is not supported. The retransmission MCS is being calculated from Table 8.1.1.2 of TS 44.060. --- tests/tbf/TbfTest.cpp | 224 ++++++++++++++++++++++++++++ tests/tbf/TbfTest.err | 397 +++++++++++++++++++++++++++++++++++++++++++++++++ tests/tbf/TbfTest.ok | 9 ++ 3 files changed, 630 insertions(+)
diff --git a/tests/tbf/TbfTest.cpp b/tests/tbf/TbfTest.cpp index e1be844..23c8dd5 100644 --- a/tests/tbf/TbfTest.cpp +++ b/tests/tbf/TbfTest.cpp @@ -1272,6 +1272,229 @@ static void establish_and_use_egprs_dl_tbf(BTS *the_bts, int mcs) tbf_free(dl_tbf); }
+static gprs_rlcmac_dl_tbf *tbf_init(BTS *the_bts, + int mcs) +{ + unsigned i; + uint8_t ms_class = 11; + uint8_t egprs_ms_class = 11; + uint32_t fn = 0; + uint8_t trx_no; + uint32_t tlli = 0xffeeddcc; + uint8_t test_data[512]; + + uint8_t rbb[64/8]; + + gprs_rlcmac_dl_tbf *dl_tbf; + + memset(test_data, 1, sizeof(test_data)); + the_bts->bts_data()->initial_mcs_dl = mcs; + + dl_tbf = create_dl_tbf(the_bts, ms_class, egprs_ms_class, &trx_no); + dl_tbf->update_ms(tlli, GPRS_RLCMAC_DL_TBF); + + for (i = 0; i < sizeof(test_data); i++) + test_data[i] = i%256; + + OSMO_ASSERT(dl_tbf->state_is(GPRS_RLCMAC_FLOW)); + + /* Schedule a LLC frame + * passing only 100 bytes, since it is enough to construct + * 2 RLC data blocks. Which are enough to test Header Type 1 + * cases + */ + dl_tbf->append_data(ms_class, 1000, test_data, 100); + + OSMO_ASSERT(dl_tbf->state_is(GPRS_RLCMAC_FLOW)); + + return dl_tbf; + +} + +static void tbf_cleanup(gprs_rlcmac_dl_tbf *dl_tbf) +{ + uint32_t fn = 0; + uint8_t rbb[64/8]; + + /* Receive a final ACK */ + dl_tbf->rcvd_dl_ack(1, dl_tbf->m_window.v_s(), rbb); + + /* Clean up and ensure tbfs are in the correct state */ + OSMO_ASSERT(dl_tbf->state_is(GPRS_RLCMAC_WAIT_RELEASE)); + dl_tbf->dl_ass_state = GPRS_RLCMAC_DL_ASS_NONE; + check_tbf(dl_tbf); + tbf_free(dl_tbf); + +} + +static void establish_and_use_egprs_dl_tbf_for_retx(BTS *the_bts, + int mcs, int demanded_mcs) +{ + uint32_t fn = 0; + gprs_rlcmac_dl_tbf *dl_tbf; + uint8_t block_nr = 0; + int index1 = 0; + uint8_t bn; + struct msgb *msg; + + printf("Testing retx for MCS %d - %d\n", mcs, demanded_mcs); + + dl_tbf = tbf_init(the_bts, mcs); + + /* For MCS reduction cases like MCS9->MCS6, MCS7->MCS5 + * The MCS transition are referred from table Table 8.1.1.2 + * of TS 44.060 + */ + /* TODO: Need to support of MCS8 -> MCS6 transistion */ + if (((mcs == 9) && (demanded_mcs < 9)) || + ((mcs == 7) && (demanded_mcs < 7))) { + fn = fn_add_blocks(fn, 1); + /* Send 2 RLC data block */ + msg = dl_tbf->create_dl_acked_block(fn, dl_tbf->control_ts); + + OSMO_ASSERT(dl_tbf->m_window.m_v_b.is_unacked(0)); + OSMO_ASSERT(dl_tbf->m_window.m_v_b.is_unacked(1)); + OSMO_ASSERT(dl_tbf->m_rlc.block(0)->cs_current_trans.to_num() + == mcs); + OSMO_ASSERT(dl_tbf->m_rlc.block(1)->cs_current_trans.to_num() + == mcs); + + dl_tbf->m_window.m_v_b.mark_nacked(0); + dl_tbf->m_window.m_v_b.mark_nacked(1); + OSMO_ASSERT(dl_tbf->m_window.m_v_b.is_nacked(0)); + OSMO_ASSERT(dl_tbf->m_window.m_v_b.is_nacked(1)); + + /* Set the demanded MCS to demanded_mcs */ + dl_tbf->ms()->set_current_cs_dl + ((GprsCodingScheme::Scheme)(GprsCodingScheme::CS4 + + demanded_mcs)); + + fn = fn_add_blocks(fn, 1); + /* Retransmit the first RLC data block with demanded_mcs */ + msg = dl_tbf->create_dl_acked_block(fn, dl_tbf->control_ts); + OSMO_ASSERT(dl_tbf->m_window.m_v_b.is_unacked(0)); + OSMO_ASSERT(dl_tbf->m_window.m_v_b.is_nacked(1)); + OSMO_ASSERT(dl_tbf->m_rlc.block(0)->cs_current_trans.to_num() + == demanded_mcs); + + fn = fn_add_blocks(fn, 1); + /* Retransmit the second RLC data block with demanded_mcs */ + msg = dl_tbf->create_dl_acked_block(fn, dl_tbf->control_ts); + OSMO_ASSERT(dl_tbf->m_window.m_v_b.is_unacked(0)); + OSMO_ASSERT(dl_tbf->m_window.m_v_b.is_unacked(1)); + OSMO_ASSERT(dl_tbf->m_rlc.block(1)->cs_current_trans.to_num() + == demanded_mcs); + } else if (((mcs == 5) && (demanded_mcs > 6)) || + ((mcs == 6) && (demanded_mcs > 8))) { + fn = fn_add_blocks(fn, 1); + /* Send first RLC data block BSN 0 */ + msg = dl_tbf->create_dl_acked_block(fn, dl_tbf->control_ts); + OSMO_ASSERT(dl_tbf->m_window.m_v_b.is_unacked(0)); + OSMO_ASSERT(dl_tbf->m_rlc.block(0)->cs_current_trans.to_num() + == mcs); + + fn = fn_add_blocks(fn, 1); + /* Send second RLC data block BSN 1 */ + msg = dl_tbf->create_dl_acked_block(fn, dl_tbf->control_ts); + OSMO_ASSERT(dl_tbf->m_window.m_v_b.is_unacked(1)); + OSMO_ASSERT(dl_tbf->m_rlc.block(1)->cs_current_trans.to_num() + == mcs); + + dl_tbf->m_window.m_v_b.mark_nacked(0); + dl_tbf->m_window.m_v_b.mark_nacked(1); + OSMO_ASSERT(dl_tbf->m_window.m_v_b.is_nacked(0)); + OSMO_ASSERT(dl_tbf->m_window.m_v_b.is_nacked(1)); + + dl_tbf->ms()->set_current_cs_dl + ((GprsCodingScheme::Scheme)(GprsCodingScheme::CS4 + + demanded_mcs)); + + fn = fn_add_blocks(fn, 1); + /* Send first, second RLC data blocks with demanded_mcs */ + msg = dl_tbf->create_dl_acked_block(fn, dl_tbf->control_ts); + OSMO_ASSERT(dl_tbf->m_window.m_v_b.is_unacked(0)); + OSMO_ASSERT(dl_tbf->m_window.m_v_b.is_unacked(1)); + OSMO_ASSERT(dl_tbf->m_rlc.block(0)->cs_current_trans.to_num() + == demanded_mcs); + OSMO_ASSERT(dl_tbf->m_rlc.block(1)->cs_current_trans.to_num() + == demanded_mcs); + } else if (mcs > 6) { + /* No Mcs change cases are handled here for mcs > MCS6*/ + fn = fn_add_blocks(fn, 1); + /* Send first,second RLC data blocks */ + msg = dl_tbf->create_dl_acked_block(fn, dl_tbf->control_ts); + OSMO_ASSERT(dl_tbf->m_window.m_v_b.is_unacked(0)); + OSMO_ASSERT(dl_tbf->m_window.m_v_b.is_unacked(1)); + OSMO_ASSERT(dl_tbf->m_rlc.block(0)->cs_current_trans.to_num() + == mcs); + OSMO_ASSERT(dl_tbf->m_rlc.block(1)->cs_current_trans.to_num() + == mcs); + + dl_tbf->m_window.m_v_b.mark_nacked(0); + dl_tbf->m_window.m_v_b.mark_nacked(1); + OSMO_ASSERT(dl_tbf->m_window.m_v_b.is_nacked(0)); + OSMO_ASSERT(dl_tbf->m_window.m_v_b.is_nacked(1)); + + fn = fn_add_blocks(fn, 1); + /* Send first,second RLC data blocks with demanded_mcs*/ + msg = dl_tbf->create_dl_acked_block(fn, dl_tbf->control_ts); + OSMO_ASSERT(dl_tbf->m_window.m_v_b.is_unacked(0)); + OSMO_ASSERT(dl_tbf->m_window.m_v_b.is_unacked(1)); + OSMO_ASSERT(dl_tbf->m_rlc.block(0)->cs_current_trans.to_num() + == mcs); + OSMO_ASSERT(dl_tbf->m_rlc.block(1)->cs_current_trans.to_num() + == mcs); + } else { + + /* No MCS change cases are handled here for mcs <= MCS6*/ + fn = fn_add_blocks(fn, 1); + /* Send first RLC data block */ + msg = dl_tbf->create_dl_acked_block(fn, dl_tbf->control_ts); + OSMO_ASSERT(dl_tbf->m_window.m_v_b.is_unacked(0)); + OSMO_ASSERT(dl_tbf->m_rlc.block(0)->cs_current_trans.to_num() + == mcs); + + dl_tbf->m_window.m_v_b.mark_nacked(0); + OSMO_ASSERT(dl_tbf->m_window.m_v_b.is_nacked(0)); + + fn = fn_add_blocks(fn, 1); + /* Send first RLC data block with demanded_mcs */ + msg = dl_tbf->create_dl_acked_block(fn, dl_tbf->control_ts); + OSMO_ASSERT(dl_tbf->m_window.m_v_b.is_unacked(0)); + OSMO_ASSERT(dl_tbf->m_rlc.block(0)->cs_current_trans.to_num() + == mcs); + } + + tbf_cleanup(dl_tbf); +} + +static void test_tbf_egprs_retx_dl(void) +{ + BTS the_bts; + gprs_rlcmac_bts *bts; + uint8_t ts_no = 4; + int i, j; + + printf("=== start %s ===\n", __func__); + + bts = the_bts.bts_data(); + bts->cs_downgrade_threshold = 0; + setup_bts(&the_bts, ts_no); + bts->dl_tbf_idle_msec = 200; + bts->egprs_enabled = 1; + + /* First parameter is current MCS, second one is demanded_mcs */ + establish_and_use_egprs_dl_tbf_for_retx(&the_bts, 6, 6); + establish_and_use_egprs_dl_tbf_for_retx(&the_bts, 1, 9); + establish_and_use_egprs_dl_tbf_for_retx(&the_bts, 2, 8); + establish_and_use_egprs_dl_tbf_for_retx(&the_bts, 5, 7); + establish_and_use_egprs_dl_tbf_for_retx(&the_bts, 6, 9); + establish_and_use_egprs_dl_tbf_for_retx(&the_bts, 7, 5); + establish_and_use_egprs_dl_tbf_for_retx(&the_bts, 9, 6); + + printf("=== end %s ===\n", __func__); +} + static void test_tbf_egprs_dl() { BTS the_bts; @@ -1356,6 +1579,7 @@ int main(int argc, char **argv) test_tbf_ws(); test_tbf_egprs_two_phase(); test_tbf_egprs_dl(); + test_tbf_egprs_retx_dl();
if (getenv("TALLOC_REPORT_FULL")) talloc_report_full(tall_pcu_ctx, stderr); diff --git a/tests/tbf/TbfTest.err b/tests/tbf/TbfTest.err index 9bea2fd..4b694a7 100644 --- a/tests/tbf/TbfTest.err +++ b/tests/tbf/TbfTest.err @@ -5113,3 +5113,400 @@ PDCH(TS 4, TRX 0): Detaching TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EG Detaching TBF from MS object, TLLI = 0xffeeddcc, TBF = TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS) Destroying MS object, TLLI = 0xffeeddcc ********** TBF ends here ********** +Searching for first unallocated TFI: TRX=0 + Found TFI=0. +********** TBF starts here ********** +Allocating DL TBF: MS_CLASS=11/11 +Creating MS object, TLLI = 0x00000000 +Modifying MS object, TLLI = 0x00000000, MS class 0 -> 11 +Modifying MS object, TLLI = 0x00000000, EGPRS MS class 0 -> 11 +Enabled EGPRS for TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), mode EGPRS +Slot Allocation (Algorithm A) for class 0 +- Skipping TS 0, because not enabled +- Skipping TS 1, because not enabled +- Skipping TS 2, because not enabled +- Skipping TS 3, because not enabled +- Skipping TS 5, because not enabled +- Skipping TS 6, because not enabled +- Skipping TS 7, because not enabled +- Assign downlink TS=4 TFI=0 +PDCH(TS 4, TRX 0): Attaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), 1 TBFs, USFs = 00, TFIs = 00000001. +- Setting Control TS 4 +Attaching TBF to MS object, TLLI = 0x00000000, TBF = TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS) +Allocated TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS): trx = 0, ul_slots = 10, dl_slots = 10 +TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS): Setting EGPRS window size to 64 +TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS) changes state from NULL to FLOW +The MS object cannot fully confirm an unexpected TLLI: 0xffeeddcc, partly confirmed +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) append +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==0) +- Sending new block at BSN 0, CS=MCS-6 +- Dequeue next LLC for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) (len=100) +-- Chunk with length 100 larger than space (74) left in block: copy only remaining space, and we are done +data block (BSN 0, MCS-6): 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 40 41 42 43 44 45 46 47 48 49 +- Copying data unit 0 (BSN 0) +msg block (BSN 0, MCS-6): 07 00 00 10 40 80 c0 00 41 81 c1 01 42 82 c2 02 43 83 c3 03 44 84 c4 04 45 85 c5 05 46 86 c6 06 47 87 c7 07 48 88 c8 08 49 89 c9 09 4a 8a ca 0a 4b 8b cb 0b 4c 8c cc 0c 4d 8d cd 0d 4e 8e ce 0e 4f 8f cf 0f 50 90 d0 10 51 91 d1 11 52 12 +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==1) +- Resending BSN 0 +- Copying data unit 0 (BSN 0) +msg block (BSN 0, MCS-6): 07 00 00 12 40 80 c0 00 41 81 c1 01 42 82 c2 02 43 83 c3 03 44 84 c4 04 45 85 c5 05 46 86 c6 06 47 87 c7 07 48 88 c8 08 49 89 c9 09 4a 8a ca 0a 4b 8b cb 0b 4c 8c cc 0c 4d 8d cd 0d 4e 8e ce 0e 4f 8f cf 0f 50 90 d0 10 51 91 d1 11 52 12 +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink acknowledge +- Final ACK received. +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) changes state from FLOW to WAIT RELEASE +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE EGPRS) starting timer 3193. +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE EGPRS) changes state from WAIT RELEASE to RELEASING +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS) free +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS) stopping timer 3193. +PDCH(TS 4, TRX 0): Detaching TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS), 0 TBFs, USFs = 00, TFIs = 00000000. +Detaching TBF from MS object, TLLI = 0xffeeddcc, TBF = TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS) +Destroying MS object, TLLI = 0xffeeddcc +********** TBF ends here ********** +Searching for first unallocated TFI: TRX=0 + Found TFI=0. +********** TBF starts here ********** +Allocating DL TBF: MS_CLASS=11/11 +Creating MS object, TLLI = 0x00000000 +Modifying MS object, TLLI = 0x00000000, MS class 0 -> 11 +Modifying MS object, TLLI = 0x00000000, EGPRS MS class 0 -> 11 +Enabled EGPRS for TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), mode EGPRS +Slot Allocation (Algorithm A) for class 0 +- Skipping TS 0, because not enabled +- Skipping TS 1, because not enabled +- Skipping TS 2, because not enabled +- Skipping TS 3, because not enabled +- Skipping TS 5, because not enabled +- Skipping TS 6, because not enabled +- Skipping TS 7, because not enabled +- Assign downlink TS=4 TFI=0 +PDCH(TS 4, TRX 0): Attaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), 1 TBFs, USFs = 00, TFIs = 00000001. +- Setting Control TS 4 +Attaching TBF to MS object, TLLI = 0x00000000, TBF = TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS) +Allocated TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS): trx = 0, ul_slots = 10, dl_slots = 10 +TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS): Setting EGPRS window size to 64 +TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS) changes state from NULL to FLOW +The MS object cannot fully confirm an unexpected TLLI: 0xffeeddcc, partly confirmed +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) append +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==0) +- Sending new block at BSN 0, CS=MCS-1 +- Dequeue next LLC for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) (len=100) +-- Chunk with length 100 larger than space (22) left in block: copy only remaining space, and we are done +data block (BSN 0, MCS-1): 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 +- Copying data unit 0 (BSN 0) +msg block (BSN 0, MCS-1): 07 00 00 96 00 02 04 06 08 0a 0c 0e 10 12 14 16 18 1a 1c 1e 20 22 24 26 28 2a 00 +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==1) +- Resending BSN 0 +- Copying data unit 0 (BSN 0) +msg block (BSN 0, MCS-1): 07 00 00 98 00 02 04 06 08 0a 0c 0e 10 12 14 16 18 1a 1c 1e 20 22 24 26 28 2a 00 +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink acknowledge +- Final ACK received. +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) changes state from FLOW to WAIT RELEASE +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE EGPRS) starting timer 3193. +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE EGPRS) changes state from WAIT RELEASE to RELEASING +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS) free +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS) stopping timer 3193. +PDCH(TS 4, TRX 0): Detaching TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS), 0 TBFs, USFs = 00, TFIs = 00000000. +Detaching TBF from MS object, TLLI = 0xffeeddcc, TBF = TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS) +Destroying MS object, TLLI = 0xffeeddcc +********** TBF ends here ********** +Searching for first unallocated TFI: TRX=0 + Found TFI=0. +********** TBF starts here ********** +Allocating DL TBF: MS_CLASS=11/11 +Creating MS object, TLLI = 0x00000000 +Modifying MS object, TLLI = 0x00000000, MS class 0 -> 11 +Modifying MS object, TLLI = 0x00000000, EGPRS MS class 0 -> 11 +Enabled EGPRS for TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), mode EGPRS +Slot Allocation (Algorithm A) for class 0 +- Skipping TS 0, because not enabled +- Skipping TS 1, because not enabled +- Skipping TS 2, because not enabled +- Skipping TS 3, because not enabled +- Skipping TS 5, because not enabled +- Skipping TS 6, because not enabled +- Skipping TS 7, because not enabled +- Assign downlink TS=4 TFI=0 +PDCH(TS 4, TRX 0): Attaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), 1 TBFs, USFs = 00, TFIs = 00000001. +- Setting Control TS 4 +Attaching TBF to MS object, TLLI = 0x00000000, TBF = TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS) +Allocated TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS): trx = 0, ul_slots = 10, dl_slots = 10 +TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS): Setting EGPRS window size to 64 +TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS) changes state from NULL to FLOW +The MS object cannot fully confirm an unexpected TLLI: 0xffeeddcc, partly confirmed +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) append +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==0) +- Sending new block at BSN 0, CS=MCS-2 +- Dequeue next LLC for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) (len=100) +-- Chunk with length 100 larger than space (28) left in block: copy only remaining space, and we are done +data block (BSN 0, MCS-2): 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b +- Copying data unit 0 (BSN 0) +msg block (BSN 0, MCS-2): 07 00 00 92 00 02 04 06 08 0a 0c 0e 10 12 14 16 18 1a 1c 1e 20 22 24 26 28 2a 2c 2e 30 32 34 36 00 +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==1) +- Resending BSN 0 +- Copying data unit 0 (BSN 0) +msg block (BSN 0, MCS-2): 07 00 00 94 00 02 04 06 08 0a 0c 0e 10 12 14 16 18 1a 1c 1e 20 22 24 26 28 2a 2c 2e 30 32 34 36 00 +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink acknowledge +- Final ACK received. +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) changes state from FLOW to WAIT RELEASE +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE EGPRS) starting timer 3193. +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE EGPRS) changes state from WAIT RELEASE to RELEASING +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS) free +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS) stopping timer 3193. +PDCH(TS 4, TRX 0): Detaching TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS), 0 TBFs, USFs = 00, TFIs = 00000000. +Detaching TBF from MS object, TLLI = 0xffeeddcc, TBF = TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS) +Destroying MS object, TLLI = 0xffeeddcc +********** TBF ends here ********** +Searching for first unallocated TFI: TRX=0 + Found TFI=0. +********** TBF starts here ********** +Allocating DL TBF: MS_CLASS=11/11 +Creating MS object, TLLI = 0x00000000 +Modifying MS object, TLLI = 0x00000000, MS class 0 -> 11 +Modifying MS object, TLLI = 0x00000000, EGPRS MS class 0 -> 11 +Enabled EGPRS for TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), mode EGPRS +Slot Allocation (Algorithm A) for class 0 +- Skipping TS 0, because not enabled +- Skipping TS 1, because not enabled +- Skipping TS 2, because not enabled +- Skipping TS 3, because not enabled +- Skipping TS 5, because not enabled +- Skipping TS 6, because not enabled +- Skipping TS 7, because not enabled +- Assign downlink TS=4 TFI=0 +PDCH(TS 4, TRX 0): Attaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), 1 TBFs, USFs = 00, TFIs = 00000001. +- Setting Control TS 4 +Attaching TBF to MS object, TLLI = 0x00000000, TBF = TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS) +Allocated TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS): trx = 0, ul_slots = 10, dl_slots = 10 +TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS): Setting EGPRS window size to 64 +TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS) changes state from NULL to FLOW +The MS object cannot fully confirm an unexpected TLLI: 0xffeeddcc, partly confirmed +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) append +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==0) +- Sending new block at BSN 0, CS=MCS-5 +- Dequeue next LLC for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) (len=100) +-- Chunk with length 100 larger than space (56) left in block: copy only remaining space, and we are done +data block (BSN 0, MCS-5): 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 +- Copying data unit 0 (BSN 0) +msg block (BSN 0, MCS-5): 07 00 00 18 40 80 c0 00 41 81 c1 01 42 82 c2 02 43 83 c3 03 44 84 c4 04 45 85 c5 05 46 86 c6 06 47 87 c7 07 48 88 c8 08 49 89 c9 09 4a 8a ca 0a 4b 8b cb 0b 4c 8c cc 0c 4d 8d cd 0d +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==1) +- Sending new block at BSN 1, CS=MCS-5 +-- Chunk with length 44 is less than remaining space (56): add length header to to delimit LLC frame +Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=100 +-- Empty chunk, added LLC dummy command of size 10, drained_since=0 +-- Chunk with length 10 is less than remaining space (11): add length header to to delimit LLC frame +-- No space left, so we are done. +Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=10 +data block (BSN 1, MCS-5): 58 15 38 39 3a 3b 3c 3d 3e 3f 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 60 61 62 63 43 c0 01 2b 2b 2b 2b 2b 2b 2b +- Copying data unit 0 (BSN 1) +- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent). +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS): Scheduling polling at FN 21 TS 4 +Polling scheduled in this TS 4 +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) Scheduled Ack/Nack polling on FN=21, TS=4 +msg block (BSN 1, MCS-5): 0f 40 00 08 56 05 4e 8e ce 0e 4f 8f cf 0f 50 90 d0 10 51 91 d1 11 52 92 d2 12 53 93 d3 13 54 94 d4 14 55 95 d5 15 56 96 d6 16 57 97 d7 17 58 98 d8 d8 10 70 c0 ca ca ca ca ca ca 0a +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==2) +- Resending BSN 0 +- Resending BSN 1 +- Copying data unit 0 (BSN 0) +- Copying data unit 1 (BSN 1) +msg block (BSN 0, MCS-7): 07 00 00 02 c0 01 04 08 0c 10 14 18 1c 20 24 28 2c 30 34 38 3c 40 44 48 4c 50 54 58 5c 60 64 68 6c 70 74 78 7c 80 84 88 8c 90 94 98 9c a0 a4 a8 ac b0 b4 b8 bc c0 c4 c8 cc d0 d4 d8 dc 80 55 81 93 a3 b3 c3 d3 e3 f3 03 14 24 34 44 54 64 74 84 94 a4 b4 c4 d4 e4 f4 04 15 25 35 45 55 65 75 85 95 a5 b5 c5 d5 e5 f5 05 16 26 36 36 04 1c b0 b2 b2 b2 b2 b2 b2 02 +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink acknowledge +- Final ACK received. +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) changes state from FLOW to WAIT RELEASE +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE EGPRS) starting timer 3193. +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE EGPRS) changes state from WAIT RELEASE to RELEASING +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS) free +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS) stopping timer 3193. +PDCH(TS 4, TRX 0): Detaching TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS), 0 TBFs, USFs = 00, TFIs = 00000000. +Detaching TBF from MS object, TLLI = 0xffeeddcc, TBF = TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS) +Destroying MS object, TLLI = 0xffeeddcc +********** TBF ends here ********** +Searching for first unallocated TFI: TRX=0 + Found TFI=0. +********** TBF starts here ********** +Allocating DL TBF: MS_CLASS=11/11 +Creating MS object, TLLI = 0x00000000 +Modifying MS object, TLLI = 0x00000000, MS class 0 -> 11 +Modifying MS object, TLLI = 0x00000000, EGPRS MS class 0 -> 11 +Enabled EGPRS for TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), mode EGPRS +Slot Allocation (Algorithm A) for class 0 +- Skipping TS 0, because not enabled +- Skipping TS 1, because not enabled +- Skipping TS 2, because not enabled +- Skipping TS 3, because not enabled +- Skipping TS 5, because not enabled +- Skipping TS 6, because not enabled +- Skipping TS 7, because not enabled +- Assign downlink TS=4 TFI=0 +PDCH(TS 4, TRX 0): Attaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), 1 TBFs, USFs = 00, TFIs = 00000001. +- Setting Control TS 4 +Attaching TBF to MS object, TLLI = 0x00000000, TBF = TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS) +Allocated TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS): trx = 0, ul_slots = 10, dl_slots = 10 +TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS): Setting EGPRS window size to 64 +TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS) changes state from NULL to FLOW +The MS object cannot fully confirm an unexpected TLLI: 0xffeeddcc, partly confirmed +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) append +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==0) +- Sending new block at BSN 0, CS=MCS-6 +- Dequeue next LLC for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) (len=100) +-- Chunk with length 100 larger than space (74) left in block: copy only remaining space, and we are done +data block (BSN 0, MCS-6): 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 40 41 42 43 44 45 46 47 48 49 +- Copying data unit 0 (BSN 0) +msg block (BSN 0, MCS-6): 07 00 00 10 40 80 c0 00 41 81 c1 01 42 82 c2 02 43 83 c3 03 44 84 c4 04 45 85 c5 05 46 86 c6 06 47 87 c7 07 48 88 c8 08 49 89 c9 09 4a 8a ca 0a 4b 8b cb 0b 4c 8c cc 0c 4d 8d cd 0d 4e 8e ce 0e 4f 8f cf 0f 50 90 d0 10 51 91 d1 11 52 12 +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==1) +- Sending new block at BSN 1, CS=MCS-6 +-- Chunk with length 26 is less than remaining space (74): add length header to to delimit LLC frame +Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=100 +-- Empty chunk, added LLC dummy command of size 46, drained_since=0 +-- Chunk with length 46 is less than remaining space (47): add length header to to delimit LLC frame +-- No space left, so we are done. +Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=46 +data block (BSN 1, MCS-6): 34 5d 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 60 61 62 63 43 c0 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b +- Copying data unit 0 (BSN 1) +- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent). +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS): Scheduling polling at FN 21 TS 4 +Polling scheduled in this TS 4 +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) Scheduled Ack/Nack polling on FN=21, TS=4 +msg block (BSN 1, MCS-6): 0f 40 00 00 4d 97 d2 12 53 93 d3 13 54 94 d4 14 55 95 d5 15 56 96 d6 16 57 97 d7 17 58 98 d8 d8 10 70 c0 ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca 0a +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==2) +- Resending BSN 0 +- Resending BSN 1 +- Copying data unit 0 (BSN 0) +- Copying data unit 1 (BSN 1) +msg block (BSN 0, MCS-9): 07 00 00 02 28 01 04 08 0c 10 14 18 1c 20 24 28 2c 30 34 38 3c 40 44 48 4c 50 54 58 5c 60 64 68 6c 70 74 78 7c 80 84 88 8c 90 94 98 9c a0 a4 a8 ac b0 b4 b8 bc c0 c4 c8 cc d0 d4 d8 dc e0 e4 e8 ec f0 f4 f8 fc 00 05 09 0d 11 15 19 1d 21 25 41 d3 a5 b4 c4 d4 e4 f4 04 15 25 35 45 55 65 75 85 95 a5 b5 c5 d5 e5 f5 05 16 26 36 36 04 1c b0 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 02 +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink acknowledge +- Final ACK received. +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) changes state from FLOW to WAIT RELEASE +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE EGPRS) starting timer 3193. +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE EGPRS) changes state from WAIT RELEASE to RELEASING +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS) free +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS) stopping timer 3193. +PDCH(TS 4, TRX 0): Detaching TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS), 0 TBFs, USFs = 00, TFIs = 00000000. +Detaching TBF from MS object, TLLI = 0xffeeddcc, TBF = TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS) +Destroying MS object, TLLI = 0xffeeddcc +********** TBF ends here ********** +Searching for first unallocated TFI: TRX=0 + Found TFI=0. +********** TBF starts here ********** +Allocating DL TBF: MS_CLASS=11/11 +Creating MS object, TLLI = 0x00000000 +Modifying MS object, TLLI = 0x00000000, MS class 0 -> 11 +Modifying MS object, TLLI = 0x00000000, EGPRS MS class 0 -> 11 +Enabled EGPRS for TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), mode EGPRS +Slot Allocation (Algorithm A) for class 0 +- Skipping TS 0, because not enabled +- Skipping TS 1, because not enabled +- Skipping TS 2, because not enabled +- Skipping TS 3, because not enabled +- Skipping TS 5, because not enabled +- Skipping TS 6, because not enabled +- Skipping TS 7, because not enabled +- Assign downlink TS=4 TFI=0 +PDCH(TS 4, TRX 0): Attaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), 1 TBFs, USFs = 00, TFIs = 00000001. +- Setting Control TS 4 +Attaching TBF to MS object, TLLI = 0x00000000, TBF = TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS) +Allocated TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS): trx = 0, ul_slots = 10, dl_slots = 10 +TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS): Setting EGPRS window size to 64 +TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS) changes state from NULL to FLOW +The MS object cannot fully confirm an unexpected TLLI: 0xffeeddcc, partly confirmed +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) append +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==0) +- Sending new block at BSN 0, CS=MCS-7 +- Dequeue next LLC for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) (len=100) +-- Chunk with length 100 larger than space (56) left in block: copy only remaining space, and we are done +data block (BSN 0, MCS-7): 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 +- Sending new block at BSN 1, CS=MCS-7 +-- Chunk with length 44 is less than remaining space (56): add length header to to delimit LLC frame +Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=100 +-- Empty chunk, added LLC dummy command of size 10, drained_since=0 +-- Chunk with length 10 is less than remaining space (11): add length header to to delimit LLC frame +-- No space left, so we are done. +Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=10 +data block (BSN 1, MCS-7): 58 15 38 39 3a 3b 3c 3d 3e 3f 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 60 61 62 63 43 c0 01 2b 2b 2b 2b 2b 2b 2b +- Copying data unit 0 (BSN 0) +- Copying data unit 1 (BSN 1) +- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent). +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS): Scheduling polling at FN 17 TS 4 +Polling scheduled in this TS 4 +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) Scheduled Ack/Nack polling on FN=17, TS=4 +msg block (BSN 0, MCS-7): 0f 00 00 02 a0 01 04 08 0c 10 14 18 1c 20 24 28 2c 30 34 38 3c 40 44 48 4c 50 54 58 5c 60 64 68 6c 70 74 78 7c 80 84 88 8c 90 94 98 9c a0 a4 a8 ac b0 b4 b8 bc c0 c4 c8 cc d0 d4 d8 dc 80 55 81 93 a3 b3 c3 d3 e3 f3 03 14 24 34 44 54 64 74 84 94 a4 b4 c4 d4 e4 f4 04 15 25 35 45 55 65 75 85 95 a5 b5 c5 d5 e5 f5 05 16 26 36 36 04 1c b0 b2 b2 b2 b2 b2 b2 02 +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==2) +- Resending BSN 0 +- Copying data unit 0 (BSN 0) +msg block (BSN 0, MCS-5): 07 00 00 18 40 80 c0 00 41 81 c1 01 42 82 c2 02 43 83 c3 03 44 84 c4 04 45 85 c5 05 46 86 c6 06 47 87 c7 07 48 88 c8 08 49 89 c9 09 4a 8a ca 0a 4b 8b cb 0b 4c 8c cc 0c 4d 8d cd 0d +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==2) +- Resending BSN 1 +- Copying data unit 0 (BSN 1) +msg block (BSN 1, MCS-5): 07 40 00 08 56 05 4e 8e ce 0e 4f 8f cf 0f 50 90 d0 10 51 91 d1 11 52 92 d2 12 53 93 d3 13 54 94 d4 14 55 95 d5 15 56 96 d6 16 57 97 d7 17 58 98 d8 d8 10 70 c0 ca ca ca ca ca ca 0a +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink acknowledge +- Final ACK received. +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) changes state from FLOW to WAIT RELEASE +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE EGPRS) starting timer 3193. +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE EGPRS) changes state from WAIT RELEASE to RELEASING +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS) free +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS) stopping timer 3193. +PDCH(TS 4, TRX 0): Detaching TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS), 0 TBFs, USFs = 00, TFIs = 00000000. +Detaching TBF from MS object, TLLI = 0xffeeddcc, TBF = TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS) +Destroying MS object, TLLI = 0xffeeddcc +********** TBF ends here ********** +Searching for first unallocated TFI: TRX=0 + Found TFI=0. +********** TBF starts here ********** +Allocating DL TBF: MS_CLASS=11/11 +Creating MS object, TLLI = 0x00000000 +Modifying MS object, TLLI = 0x00000000, MS class 0 -> 11 +Modifying MS object, TLLI = 0x00000000, EGPRS MS class 0 -> 11 +Enabled EGPRS for TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), mode EGPRS +Slot Allocation (Algorithm A) for class 0 +- Skipping TS 0, because not enabled +- Skipping TS 1, because not enabled +- Skipping TS 2, because not enabled +- Skipping TS 3, because not enabled +- Skipping TS 5, because not enabled +- Skipping TS 6, because not enabled +- Skipping TS 7, because not enabled +- Assign downlink TS=4 TFI=0 +PDCH(TS 4, TRX 0): Attaching TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS), 1 TBFs, USFs = 00, TFIs = 00000001. +- Setting Control TS 4 +Attaching TBF to MS object, TLLI = 0x00000000, TBF = TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS) +Allocated TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS): trx = 0, ul_slots = 10, dl_slots = 10 +TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS): Setting EGPRS window size to 64 +TBF(TFI=0 TLLI=0x00000000 DIR=DL STATE=NULL EGPRS) changes state from NULL to FLOW +The MS object cannot fully confirm an unexpected TLLI: 0xffeeddcc, partly confirmed +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) append +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==0) +- Sending new block at BSN 0, CS=MCS-9 +- Dequeue next LLC for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) (len=100) +-- Chunk with length 100 larger than space (74) left in block: copy only remaining space, and we are done +data block (BSN 0, MCS-9): 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f 40 41 42 43 44 45 46 47 48 49 +- Sending new block at BSN 1, CS=MCS-9 +-- Chunk with length 26 is less than remaining space (74): add length header to to delimit LLC frame +Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=100 +-- Empty chunk, added LLC dummy command of size 46, drained_since=0 +-- Chunk with length 46 is less than remaining space (47): add length header to to delimit LLC frame +-- No space left, so we are done. +Complete DL frame for TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS)len=46 +data block (BSN 1, MCS-9): 34 5d 4a 4b 4c 4d 4e 4f 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f 60 61 62 63 43 c0 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b +- Copying data unit 0 (BSN 0) +- Copying data unit 1 (BSN 1) +- Scheduling Ack/Nack polling, because is was requested explicitly (e.g. first final block sent). +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS): Scheduling polling at FN 17 TS 4 +Polling scheduled in this TS 4 +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) Scheduled Ack/Nack polling on FN=17, TS=4 +msg block (BSN 0, MCS-9): 0f 00 00 02 00 01 04 08 0c 10 14 18 1c 20 24 28 2c 30 34 38 3c 40 44 48 4c 50 54 58 5c 60 64 68 6c 70 74 78 7c 80 84 88 8c 90 94 98 9c a0 a4 a8 ac b0 b4 b8 bc c0 c4 c8 cc d0 d4 d8 dc e0 e4 e8 ec f0 f4 f8 fc 00 05 09 0d 11 15 19 1d 21 25 41 d3 a5 b4 c4 d4 e4 f4 04 15 25 35 45 55 65 75 85 95 a5 b5 c5 d5 e5 f5 05 16 26 36 36 04 1c b0 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 b2 02 +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==2) +- Resending BSN 0 +- Copying data unit 0 (BSN 0) +msg block (BSN 0, MCS-6): 07 00 00 12 40 80 c0 00 41 81 c1 01 42 82 c2 02 43 83 c3 03 44 84 c4 04 45 85 c5 05 46 86 c6 06 47 87 c7 07 48 88 c8 08 49 89 c9 09 4a 8a ca 0a 4b 8b cb 0b 4c 8c cc 0c 4d 8d cd 0d 4e 8e ce 0e 4f 8f cf 0f 50 90 d0 10 51 91 d1 11 52 12 +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink (V(A)==0 .. V(S)==2) +- Resending BSN 1 +- Copying data unit 0 (BSN 1) +msg block (BSN 1, MCS-6): 07 40 00 02 4d 97 d2 12 53 93 d3 13 54 94 d4 14 55 95 d5 15 56 96 d6 16 57 97 d7 17 58 98 d8 d8 10 70 c0 ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca ca 0a +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) downlink acknowledge +- Final ACK received. +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=FLOW EGPRS) changes state from FLOW to WAIT RELEASE +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE EGPRS) starting timer 3193. +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=WAIT RELEASE EGPRS) changes state from WAIT RELEASE to RELEASING +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS) free +TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS) stopping timer 3193. +PDCH(TS 4, TRX 0): Detaching TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS), 0 TBFs, USFs = 00, TFIs = 00000000. +Detaching TBF from MS object, TLLI = 0xffeeddcc, TBF = TBF(TFI=0 TLLI=0xffeeddcc DIR=DL STATE=RELEASING EGPRS) +Destroying MS object, TLLI = 0xffeeddcc +********** TBF ends here ********** diff --git a/tests/tbf/TbfTest.ok b/tests/tbf/TbfTest.ok index 441b444..8a7862f 100644 --- a/tests/tbf/TbfTest.ok +++ b/tests/tbf/TbfTest.ok @@ -43,3 +43,12 @@ Testing MCS-7 Testing MCS-8 Testing MCS-9 === end test_tbf_egprs_dl === +=== start test_tbf_egprs_retx_dl === +Testing retx for MCS 6 - 6 +Testing retx for MCS 1 - 9 +Testing retx for MCS 2 - 8 +Testing retx for MCS 5 - 7 +Testing retx for MCS 6 - 9 +Testing retx for MCS 7 - 5 +Testing retx for MCS 9 - 6 +=== end test_tbf_egprs_retx_dl ===
osmocom-net-gprs@lists.osmocom.org