aboutsummaryrefslogtreecommitdiffstats
path: root/src/tbf_ul.cpp
diff options
context:
space:
mode:
authorAravind Sirsikar <Arvind.Sirsikar@radisys.com>2016-07-26 18:26:21 +0530
committerHolger Freyther <holger@freyther.de>2016-08-02 06:58:58 +0000
commit505a86d396d4ee6e821e8337056e85362a55848f (patch)
tree8b36c01fc40bd0021bbc4c96ba7327589a84cf68 /src/tbf_ul.cpp
parent36bdc5f7a425426675f7be33fa405501fb45d95a (diff)
Add support for SPB handling for EGPRS UL TBF
This patch will modify the EGPRS UL TBF flow to support Split block handling. This patch also contains test suite modification for SPB UL. Scenarios like MCS6->MCS3, MCS4->MCS1, MCS5->MCS2, MCS9->MCS3 MCS7->MCS2, MCS8->MCS3 have been simulated and Integration tested in NuRAN 1.0 hardware thoroughly. The scope of Unit testing is limited. Change-Id: I39ca53218b6e0982abc2ab9c703c24c8bf0a09c0
Diffstat (limited to 'src/tbf_ul.cpp')
-rw-r--r--src/tbf_ul.cpp164
1 files changed, 142 insertions, 22 deletions
diff --git a/src/tbf_ul.cpp b/src/tbf_ul.cpp
index 9c9154bc..7e0732c8 100644
--- a/src/tbf_ul.cpp
+++ b/src/tbf_ul.cpp
@@ -223,36 +223,28 @@ int gprs_rlcmac_ul_tbf::rcv_data_block_acknowledged(
rdbi->bsn, m_window.v_q(),
m_window.mod_sns(m_window.v_q() + ws - 1));
block = m_rlc.block(rdbi->bsn);
- block->block_info = *rdbi;
- block->cs_last = rlc->cs;
OSMO_ASSERT(rdbi->data_len <= sizeof(block->block));
rlc_data = &(block->block[0]);
- /* TODO: Handle SPB != 0 -> Set length to 2*len, add offset if
- * 2nd part. Note that resegmentation is currently disabled
- * within the UL assignment.
- */
+
if (rdbi->spb) {
- LOGP(DRLCMACUL, LOGL_NOTICE,
- "Got SPB != 0 but resegmentation has been "
- "disabled, skipping %s data block with BSN %d, "
- "TFI=%d.\n", rlc->cs.name(), rdbi->bsn,
- rlc->tfi);
- continue;
- }
+ egprs_rlc_ul_reseg_bsn_state assemble_status;
+
+ assemble_status = handle_egprs_ul_spb(rlc,
+ block, data, block_idx);
- block->len =
- Decoding::rlc_copy_to_aligned_buffer(rlc, block_idx, data,
- rlc_data);
+ if (assemble_status != EGPRS_RESEG_DEFAULT)
+ return 0;
+ } else {
+ block->block_info = *rdbi;
+ block->cs_last = rlc->cs;
+ block->len =
+ Decoding::rlc_copy_to_aligned_buffer(rlc,
+ block_idx, data, rlc_data);
+ }
LOGP(DRLCMACUL, LOGL_DEBUG,
"%s: data_length=%d, data=%s\n",
name(), block->len, osmo_hexdump(rlc_data, block->len));
-
- /* TODO: Handle SPB != 0 -> set state to partly received
- * (upper/lower) and continue with the loop, unless the other
- * part is already present.
- */
-
/* Get/Handle TLLI */
if (rdbi->ti) {
num_chunks = Decoding::rlc_data_from_ul_data(
@@ -393,3 +385,131 @@ int gprs_rlcmac_ul_tbf::snd_ul_ud()
return 0;
}
+egprs_rlc_ul_reseg_bsn_state gprs_rlcmac_ul_tbf::handle_egprs_ul_second_seg(
+ const struct gprs_rlc_data_info *rlc, struct gprs_rlc_data *block,
+ uint8_t *data, const uint8_t block_idx)
+{
+ const gprs_rlc_data_block_info *rdbi = &rlc->block_info[block_idx];
+ union split_block_status *spb_status = &block->spb_status;
+ uint8_t *rlc_data = &block->block[0];
+
+ if (spb_status->block_status_ul &
+ EGPRS_RESEG_FIRST_SEG_RXD) {
+ LOGP(DRLCMACUL, LOGL_DEBUG,
+ "---%s: Second seg is received "
+ "first seg is already present "
+ "set the status to complete\n", name());
+ spb_status->block_status_ul = EGPRS_RESEG_DEFAULT;
+
+ block->len += Decoding::rlc_copy_to_aligned_buffer(rlc,
+ block_idx, data, rlc_data + block->len);
+ block->block_info.data_len += rdbi->data_len;
+ } else if (spb_status->block_status_ul == EGPRS_RESEG_DEFAULT) {
+ LOGP(DRLCMACUL, LOGL_DEBUG,
+ "---%s: Second seg is received "
+ "first seg is not received "
+ "set the status to second seg received\n",
+ name());
+
+ block->len = Decoding::rlc_copy_to_aligned_buffer(rlc,
+ block_idx, data,
+ rlc_data + rlc->block_info[block_idx].data_len);
+
+ spb_status->block_status_ul = EGPRS_RESEG_SECOND_SEG_RXD;
+ block->block_info = *rdbi;
+ }
+ return spb_status->block_status_ul;
+}
+
+egprs_rlc_ul_reseg_bsn_state gprs_rlcmac_ul_tbf::handle_egprs_ul_first_seg(
+ const struct gprs_rlc_data_info *rlc, struct gprs_rlc_data *block,
+ uint8_t *data, const uint8_t block_idx)
+{
+ const gprs_rlc_data_block_info *rdbi = &rlc->block_info[block_idx];
+ uint8_t *rlc_data = &block->block[0];
+ union split_block_status *spb_status = &block->spb_status;
+
+ if (spb_status->block_status_ul & EGPRS_RESEG_SECOND_SEG_RXD) {
+ LOGP(DRLCMACUL, LOGL_DEBUG,
+ "---%s: First seg is received "
+ "second seg is already present "
+ "set the status to complete\n", name());
+
+ block->len += Decoding::rlc_copy_to_aligned_buffer(rlc,
+ block_idx, data, rlc_data);
+
+ block->block_info.data_len = block->len;
+ spb_status->block_status_ul = EGPRS_RESEG_DEFAULT;
+ } else if (spb_status->block_status_ul == EGPRS_RESEG_DEFAULT) {
+ LOGP(DRLCMACUL, LOGL_DEBUG,
+ "---%s: First seg is received "
+ "second seg is not received "
+ "set the status to first seg "
+ "received\n", name());
+
+ spb_status->block_status_ul = EGPRS_RESEG_FIRST_SEG_RXD;
+ block->len = Decoding::rlc_copy_to_aligned_buffer(rlc,
+ block_idx, data, rlc_data);
+ block->block_info = *rdbi;
+ }
+ return spb_status->block_status_ul;
+}
+
+egprs_rlc_ul_reseg_bsn_state gprs_rlcmac_ul_tbf::handle_egprs_ul_spb(
+ const struct gprs_rlc_data_info *rlc, struct gprs_rlc_data *block,
+ uint8_t *data, const uint8_t block_idx)
+{
+ const gprs_rlc_data_block_info *rdbi = &rlc->block_info[block_idx];
+
+ LOGP(DRLCMACUL, LOGL_DEBUG,
+ "--%s: Got SPB(%d) "
+ "cs(%s) data block with BSN (%d), "
+ "TFI(%d).\n", name(), rdbi->spb, rlc->cs.name(), rdbi->bsn,
+ rlc->tfi);
+
+ egprs_rlc_ul_reseg_bsn_state assemble_status = EGPRS_RESEG_INVALID;
+
+ /* Section 10.4.8b of 44.060*/
+ if (rdbi->spb == 2)
+ assemble_status = handle_egprs_ul_first_seg(rlc,
+ block, data, block_idx);
+ else if (rdbi->spb == 3)
+ assemble_status = handle_egprs_ul_second_seg(rlc,
+ block, data, block_idx);
+ else {
+ LOGP(DRLCMACUL, LOGL_ERROR,
+ "--%s: spb(%d) Not supported SPB for this EGPRS "
+ "configuration\n",
+ name(), rdbi->spb);
+ }
+
+ /*
+ * When the block is successfully constructed out of segmented blocks
+ * upgrade the MCS to the type 2
+ */
+ if (assemble_status == EGPRS_RESEG_DEFAULT) {
+ switch (GprsCodingScheme::Scheme(rlc->cs)) {
+ case GprsCodingScheme::MCS3 :
+ block->cs_last = GprsCodingScheme::MCS6;
+ LOGP(DRLCMACUL, LOGL_DEBUG,
+ "--%s: Upgrading to MCS6\n", name());
+ break;
+ case GprsCodingScheme::MCS2 :
+ block->cs_last = GprsCodingScheme::MCS5;
+ LOGP(DRLCMACUL, LOGL_DEBUG,
+ "--%s: Upgrading to MCS5\n", name());
+ break;
+ case GprsCodingScheme::MCS1 :
+ LOGP(DRLCMACUL, LOGL_DEBUG,
+ "--%s: Upgrading to MCS4\n", name());
+ block->cs_last = GprsCodingScheme::MCS4;
+ break;
+ default:
+ LOGP(DRLCMACUL, LOGL_ERROR,
+ "--%s: cs(%s) Error in Upgrading to higher MCS\n",
+ name(), rlc->cs.name());
+ break;
+ }
+ }
+ return assemble_status;
+}