diff options
author | Aravind Sirsikar <arvind.sirsikar@radisys.com> | 2016-05-30 15:43:28 +0530 |
---|---|---|
committer | Aravind Sirsikar <arvind.sirsikar@radisys.com> | 2016-05-30 15:45:36 +0530 |
commit | 7c7074048483705b865bd515b9129d3d6676f0d6 (patch) | |
tree | 29842cc395ed3967cd07831fdc8f346e11f59de4 | |
parent | b7cc6a47437d8dc127f75188aa842a723c53b382 (diff) |
Modify EGPRS DL TBF flow to support Split block
Modify the EGPRS DL TBF flow to support Split block during
Retx.
-rw-r--r-- | src/gprs_coding_scheme.h | 9 | ||||
-rw-r--r-- | src/rlc.cpp | 22 | ||||
-rw-r--r-- | src/rlc.h | 7 | ||||
-rw-r--r-- | src/tbf.h | 3 | ||||
-rw-r--r-- | src/tbf_dl.cpp | 181 |
5 files changed, 178 insertions, 44 deletions
diff --git a/src/gprs_coding_scheme.h b/src/gprs_coding_scheme.h index fb3a191..d283c87 100644 --- a/src/gprs_coding_scheme.h +++ b/src/gprs_coding_scheme.h @@ -113,7 +113,8 @@ public: static const char *modeName(Mode mode); static Scheme get_retx_mcs(const GprsCodingScheme &mcs, - const GprsCodingScheme &retx_mcs); + const GprsCodingScheme &retx_mcs, + const unsigned char arq_type); static enum Scheme egprs_mcs_retx_tbl[MAX_NUM_ARQ] [MAX_NUM_MCS][MAX_NUM_MCS]; @@ -232,10 +233,12 @@ 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) + const GprsCodingScheme &demanded_mcs, + const unsigned char arq_type) { - return egprs_mcs_retx_tbl[EGPRS_ARQ2][mcs.to_num() - 1] + return egprs_mcs_retx_tbl[arq_type][mcs.to_num() - 1] [demanded_mcs.to_num() - 1]; } diff --git a/src/rlc.cpp b/src/rlc.cpp index 6770043..dc1db3e 100644 --- a/src/rlc.cpp +++ b/src/rlc.cpp @@ -285,7 +285,8 @@ bool gprs_rlc_ul_window::invalidate_bsn(const uint16_t bsn) } static void gprs_rlc_data_header_init(struct gprs_rlc_data_info *rlc, - GprsCodingScheme cs, bool with_padding, unsigned int header_bits) + GprsCodingScheme cs, bool with_padding, unsigned int header_bits, + unsigned int spb = 0) { unsigned int i; unsigned int padding_bits = with_padding ? cs.optionalPaddingBits() : 0; @@ -300,7 +301,7 @@ static void gprs_rlc_data_header_init(struct gprs_rlc_data_info *rlc, for (i = 0; i < rlc->num_data_blocks; i++) { gprs_rlc_data_block_info_init(&rlc->block_info[i], cs, - with_padding); + with_padding, spb); rlc->data_offs_bits[i] = header_bits + padding_bits + @@ -310,10 +311,10 @@ static void gprs_rlc_data_header_init(struct gprs_rlc_data_info *rlc, } void gprs_rlc_data_info_init_dl(struct gprs_rlc_data_info *rlc, - GprsCodingScheme cs, bool with_padding) + GprsCodingScheme cs, bool with_padding, unsigned int spb) { return gprs_rlc_data_header_init(rlc, cs, with_padding, - cs.numDataHeaderBitsDL()); + cs.numDataHeaderBitsDL(), spb); } void gprs_rlc_data_info_init_ul(struct gprs_rlc_data_info *rlc, @@ -324,7 +325,7 @@ void gprs_rlc_data_info_init_ul(struct gprs_rlc_data_info *rlc, } void gprs_rlc_data_block_info_init(struct gprs_rlc_data_block_info *rdbi, - GprsCodingScheme cs, bool with_padding) + GprsCodingScheme cs, bool with_padding, unsigned int spb) { unsigned int data_len = cs.maxDataBlockBytes(); if (with_padding) @@ -336,7 +337,7 @@ void gprs_rlc_data_block_info_init(struct gprs_rlc_data_block_info *rdbi, rdbi->e = 1; rdbi->cv = 15; rdbi->pi = 0; - rdbi->spb = 0; + rdbi->spb = spb; } unsigned int gprs_rlc_mcs_cps(GprsCodingScheme cs, @@ -411,8 +412,15 @@ void gprs_rlc_mcs_cps_decode(unsigned int cps, enum egprs_puncturing_values gprs_get_punct_scheme( enum egprs_puncturing_values punct, const GprsCodingScheme &cs, - const GprsCodingScheme &cs_current) + const GprsCodingScheme &cs_current, + unsigned int spb) { + /* If it is second segment of the split block + * dont change the puncturing scheme + */ + if (spb == 3) + return punct; + /* TS 44.060 9.3.2.1.1 */ if ((GprsCodingScheme::Scheme(cs) == GprsCodingScheme::MCS9) && (GprsCodingScheme::Scheme(cs_current) == GprsCodingScheme::MCS6)) { @@ -165,18 +165,19 @@ struct gprs_rlc_data { }; void gprs_rlc_data_info_init_dl(struct gprs_rlc_data_info *rlc, - GprsCodingScheme cs, bool with_padding); + GprsCodingScheme cs, bool with_padding, unsigned int spb = 0); void gprs_rlc_data_info_init_ul(struct gprs_rlc_data_info *rlc, GprsCodingScheme cs, bool with_padding); void gprs_rlc_data_block_info_init(struct gprs_rlc_data_block_info *rdbi, - GprsCodingScheme cs, bool with_padding); + GprsCodingScheme cs, bool with_padding, unsigned int spb = 0); unsigned int gprs_rlc_mcs_cps(GprsCodingScheme cs, enum egprs_puncturing_values punct, enum egprs_puncturing_values punct2, int with_padding); void gprs_rlc_mcs_cps_decode(unsigned int cps, GprsCodingScheme cs, int *punct, int *punct2, int *with_padding); enum egprs_puncturing_values gprs_get_punct_scheme(enum egprs_puncturing_values punct, const GprsCodingScheme &cs, - const GprsCodingScheme &cs_current_trans); + const GprsCodingScheme &cs_current_trans, + unsigned int spb); void gprs_update_punct_scheme(enum egprs_puncturing_values *punct, const GprsCodingScheme &cs); /* @@ -420,6 +420,9 @@ protected: void start_llc_timer(); int analyse_errors(char *show_rbb, uint8_t ssn, ana_result *res); void schedule_next_frame(); + void egprs_dl_spb_status_get_data_buffer(int bsn, uint8_t **block_data); + unsigned int get_egprs_dl_spb_status(int bsn); + unsigned int get_egprs_dl_spb_value(int bsn); struct osmo_timer_list m_llc_timer; }; diff --git a/src/tbf_dl.cpp b/src/tbf_dl.cpp index eae6968..f6c48c4 100644 --- a/src/tbf_dl.cpp +++ b/src/tbf_dl.cpp @@ -382,13 +382,8 @@ int gprs_rlcmac_dl_tbf::take_next_bsn(uint32_t fn, if (is_egprs_enabled()) { m_rlc.block(bsn)->cs_current_trans = GprsCodingScheme::get_retx_mcs( - m_rlc.block(bsn)->cs, ms()->current_cs_dl()); - - LOGP(DRLCMACDL, LOGL_DEBUG, - "- current_cs_dl(%d) demanded_mcs(%d) cs_trans(%d)\n", - m_rlc.block(bsn)->cs.to_num(), - ms()->current_cs_dl().to_num(), - m_rlc.block(bsn)->cs_current_trans.to_num()); + m_rlc.block(bsn)->cs, ms()->current_cs_dl(), + bts->bts_data()->arq_type); /* TODO: Need to remove this check when MCS-8 -> MCS-6 * transistion is handled @@ -396,6 +391,14 @@ int gprs_rlcmac_dl_tbf::take_next_bsn(uint32_t fn, if (m_rlc.block(bsn)->cs == GprsCodingScheme::MCS8) m_rlc.block(bsn)->cs_current_trans = GprsCodingScheme::MCS8; + + LOGP(DRLCMACDL, LOGL_DEBUG, + "- current_cs_dl(%d) demanded_mcs(%d)" + "cs_trans(%d) arq_type(%d) bsn(%d)\n", + m_rlc.block(bsn)->cs.to_num(), + ms()->current_cs_dl().to_num(), + m_rlc.block(bsn)->cs_current_trans.to_num(), + bts->bts_data()->arq_type, bsn); } else m_rlc.block(bsn)->cs_current_trans = m_rlc.block(bsn)->cs; @@ -526,6 +529,8 @@ int gprs_rlcmac_dl_tbf::create_new_bsn(const uint32_t fn, GprsCodingScheme cs) data = rlc_data->prepare(block_data_len); rlc_data->cs = cs; rlc_data->cs_current_trans = cs; + rlc_data->block_status_dl = EGPRS_RESEG_DL_DEFAULT; + rlc_data->cs_init = cs; rlc_data->len = block_data_len; rdbi = &(rlc_data->block_info); @@ -612,6 +617,7 @@ struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block( unsigned num_bsns; enum egprs_puncturing_values punct[ARRAY_SIZE(rlc.block_info)]; bool need_padding = false; + unsigned int spb = 0; /* * TODO: This is an experimental work-around to put 2 BSN into @@ -622,6 +628,7 @@ struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block( * the current limit. */ cs = m_rlc.block(index)->cs_current_trans; + GprsCodingScheme &cs_init = m_rlc.block(index)->cs_init; bsns[0] = index; num_bsns = 1; @@ -630,7 +637,15 @@ struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block( num_bsns += 1; } - if (num_bsns == 1) { + if ((GprsCodingScheme::Scheme(cs_init) == GprsCodingScheme::MCS8) && + (GprsCodingScheme::Scheme(cs) == GprsCodingScheme::MCS6 || + GprsCodingScheme::Scheme(cs) == GprsCodingScheme::MCS3)) { + if ((get_egprs_dl_spb_status(index) == + EGPRS_RESEG_DL_DEFAULT) || + (get_egprs_dl_spb_status(index) == + EGPRS_RESEG_SECOND_SEG_SENT)) + need_padding = true; + } else 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 @@ -640,7 +655,14 @@ struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block( cs.decToSingleBlock(&need_padding); } - gprs_rlc_data_info_init_dl(&rlc, cs, need_padding); + spb = get_egprs_dl_spb_value(index); + + LOGP(DRLCMACDL, LOGL_DEBUG, "- need_padding %d spb_status %d spb %d" + "(BSN1 %d BSN2 %d)\n", + need_padding, + get_egprs_dl_spb_status(index), spb, index, index2); + + gprs_rlc_data_info_init_dl(&rlc, cs, need_padding, spb); rlc.usf = 7; /* will be set at scheduler */ rlc.pr = 0; /* FIXME: power reduction */ @@ -659,10 +681,8 @@ struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block( data_block_idx++) { int bsn; - GprsCodingScheme cs_enc; uint8_t *block_data; gprs_rlc_data_block_info *rdbi, *block_info; - enum egprs_puncturing_values punct_scheme; /* Check if there are more blocks than BSNs */ if (data_block_idx < num_bsns) @@ -670,38 +690,34 @@ struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block( else bsn = bsns[0]; - cs_enc = m_rlc.block(bsn)->cs_current_trans; - - /* get data and header from current block */ - block_data = m_rlc.block(bsn)->block; - /* Get current puncturing scheme from block */ - punct_scheme = gprs_get_punct_scheme( - m_rlc.block(bsn)->next_ps, - m_rlc.block(bsn)->cs, cs); + m_rlc.block(bsn)->next_ps = gprs_get_punct_scheme( + m_rlc.block(bsn)->next_ps, + m_rlc.block(bsn)->cs, cs, spb); if (cs.isEgprs()) { - OSMO_ASSERT(punct_scheme >= EGPRS_PS_1); - OSMO_ASSERT(punct_scheme <= EGPRS_PS_3); + OSMO_ASSERT(m_rlc.block(bsn)->next_ps >= EGPRS_PS_1); + OSMO_ASSERT(m_rlc.block(bsn)->next_ps <= EGPRS_PS_3); } - punct[data_block_idx] = punct_scheme; + punct[data_block_idx] = m_rlc.block(bsn)->next_ps; rdbi = &rlc.block_info[data_block_idx]; block_info = &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); - } + egprs_dl_spb_status_get_data_buffer(bsn, &block_data); /* TODO: Need to handle 2 same bsns * in header type 1 */ - gprs_update_punct_scheme(&m_rlc.block(bsn)->next_ps, + /* + * If it is first segment of the split block set the state of + * bsn to nacked. If it is the first segment dont update the + * next ps value of bsn + */ + if (spb == 2) + m_window.m_v_b.mark_nacked(bsn); + else + gprs_update_punct_scheme(&m_rlc.block(bsn)->next_ps, cs); m_rlc.block(bsn)->cs = cs; @@ -1167,3 +1183,106 @@ bool gprs_rlcmac_dl_tbf::keep_open(unsigned fn) const keep_time_frames = msecs_to_frames(bts_data()->dl_tbf_idle_msec); return frames_since_last_drain(fn) <= keep_time_frames; } + +/* + * This function returns the pointer to data which needs + * to be copied. Also updates the status of the block related to + * Split block handling in the RLC/MAC block. + */ +void gprs_rlcmac_dl_tbf::egprs_dl_spb_status_get_data_buffer(int bsn, + uint8_t **block_data) +{ + struct gprs_rlc_data *rlc_data = m_rlc.block(bsn); + + GprsCodingScheme &cs_current_trans = m_rlc.block(bsn)->cs_current_trans; + GprsCodingScheme &cs_init = m_rlc.block(bsn)->cs_init; + + /* + * Table 10.3a.0.1 of 44.060 + * MCS6,9: second segment starts at 74/2 = 37 + * MCS5,7: second segment starts at 56/2 = 28 + * MCS8: second segment starts at 31 + * MCS4: second segment starts at 44/2 = 22 + */ + if (cs_current_trans.headerTypeData() == + GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_3) { + if (rlc_data->block_status_dl == EGPRS_RESEG_FIRST_SEG_SENT) { + switch (GprsCodingScheme::Scheme(cs_init)) { + case GprsCodingScheme::MCS6 : + case GprsCodingScheme::MCS9 : + *block_data = &rlc_data->block[37]; + break; + case GprsCodingScheme::MCS7 : + case GprsCodingScheme::MCS5 : + *block_data = &rlc_data->block[28]; + break; + case GprsCodingScheme::MCS8 : + *block_data = &rlc_data->block[31]; + break; + case GprsCodingScheme::MCS4 : + *block_data = &rlc_data->block[22]; + break; + default: + OSMO_ASSERT(false); + break; + + } + rlc_data->block_status_dl = EGPRS_RESEG_SECOND_SEG_SENT; + return; + } else if ((cs_init.headerTypeData() == + GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_1) || + (cs_init.headerTypeData() == + GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_2)) { + rlc_data->block_status_dl = + EGPRS_RESEG_FIRST_SEG_SENT; + } else if ((GprsCodingScheme::Scheme(cs_init) == + GprsCodingScheme::MCS4) && + (GprsCodingScheme::Scheme(cs_current_trans) == + GprsCodingScheme::MCS1)) { + rlc_data->block_status_dl = EGPRS_RESEG_FIRST_SEG_SENT; + } + } + *block_data = &rlc_data->block[0]; +} + +/* + * This function returns the status of split block + * for RLC/MAC block. + */ +unsigned int gprs_rlcmac_dl_tbf::get_egprs_dl_spb_status(int bsn) +{ + struct gprs_rlc_data *rlc_data = m_rlc.block(bsn); + + return rlc_data->block_status_dl; +} + +/* + * This function returns the spb value to be sent OTA + * for RLC/MAC block. + */ +unsigned int gprs_rlcmac_dl_tbf::get_egprs_dl_spb_value(int bsn) +{ + struct gprs_rlc_data *rlc_data = m_rlc.block(bsn); + + GprsCodingScheme &cs_current_trans = m_rlc.block(bsn)->cs_current_trans; + GprsCodingScheme &cs_init = m_rlc.block(bsn)->cs_init; + + /* Table 10.4.8b.1 of 44.060 */ + if (cs_current_trans.headerTypeData() == + GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_3) { + if (rlc_data->block_status_dl == EGPRS_RESEG_FIRST_SEG_SENT) { + return 3; + } else if ((cs_init.headerTypeData() == + GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_1) || + (cs_init.headerTypeData() == + GprsCodingScheme::HEADER_EGPRS_DATA_TYPE_2)) { + return 2; + } else if ((GprsCodingScheme::Scheme(cs_init) == + GprsCodingScheme::MCS4) && + (GprsCodingScheme::Scheme(cs_current_trans) == + GprsCodingScheme::MCS1)) { + return 2; + } + } + return 0; +} |