aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAravind Sirsikar <arvind.sirsikar@radisys.com>2016-05-30 15:43:28 +0530
committerAravind Sirsikar <arvind.sirsikar@radisys.com>2016-05-30 15:45:36 +0530
commit7c7074048483705b865bd515b9129d3d6676f0d6 (patch)
tree29842cc395ed3967cd07831fdc8f346e11f59de4
parentb7cc6a47437d8dc127f75188aa842a723c53b382 (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.h9
-rw-r--r--src/rlc.cpp22
-rw-r--r--src/rlc.h7
-rw-r--r--src/tbf.h3
-rw-r--r--src/tbf_dl.cpp181
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)) {
diff --git a/src/rlc.h b/src/rlc.h
index dfeb262..e4511e2 100644
--- a/src/rlc.h
+++ b/src/rlc.h
@@ -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);
/*
diff --git a/src/tbf.h b/src/tbf.h
index 54c605f..a825b4f 100644
--- a/src/tbf.h
+++ b/src/tbf.h
@@ -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;
+}