diff options
author | Aravind Sirsikar <Arvind.Sirsikar@radisys.com> | 2016-07-26 18:26:21 +0530 |
---|---|---|
committer | Holger Freyther <holger@freyther.de> | 2016-08-02 06:58:58 +0000 |
commit | 505a86d396d4ee6e821e8337056e85362a55848f (patch) | |
tree | 8b36c01fc40bd0021bbc4c96ba7327589a84cf68 /src | |
parent | 36bdc5f7a425426675f7be33fa405501fb45d95a (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')
-rw-r--r-- | src/encoding.cpp | 6 | ||||
-rw-r--r-- | src/tbf.h | 15 | ||||
-rw-r--r-- | src/tbf_ul.cpp | 164 |
3 files changed, 161 insertions, 24 deletions
diff --git a/src/encoding.cpp b/src/encoding.cpp index a778ef0b..63049ac3 100644 --- a/src/encoding.cpp +++ b/src/encoding.cpp @@ -283,7 +283,8 @@ void Encoding::write_packet_uplink_assignment( bitvec_write_field(dest, wp,0x0,1); // No CONTENTION_RESOLUTION_TLLI bitvec_write_field(dest, wp,0x0,1); // No COMPACT reduced MA bitvec_write_field(dest, wp,tbf->current_cs().to_num()-1, 4); // EGPRS Modulation and Coding IE - bitvec_write_field(dest, wp,0x0,1); // No RESEGMENT + /* 0: no RESEGMENT, 1: Segmentation*/ + bitvec_write_field(dest, wp, 0x1, 1); bitvec_write_field(dest, wp,ws_enc,5); // EGPRS Window Size bitvec_write_field(dest, wp,0x0,1); // No Access Technologies Request bitvec_write_field(dest, wp,0x0,1); // No ARAC RETRANSMISSION REQUEST @@ -620,7 +621,8 @@ static void write_packet_uplink_ack_egprs( /* CHANNEL_CODING_COMMAND */ bitvec_write_field(dest, wp, tbf->current_cs().to_num() - 1, 4); - bitvec_write_field(dest, wp, 0, 1); // 0: no RESEGMENT (nyi) + /* 0: no RESEGMENT, 1: Segmentation*/ + bitvec_write_field(dest, wp, 1, 1); bitvec_write_field(dest, wp, 1, 1); // PRE_EMPTIVE_TRANSMISSION, TODO: This resembles GPRS, change it? bitvec_write_field(dest, wp, 0, 1); // 0: no PRR_RETRANSMISSION_REQUEST, TODO: clarify bitvec_write_field(dest, wp, 0, 1); // 0: no ARAC_RETRANSMISSION_REQUEST, TODO: clarify @@ -439,6 +439,21 @@ struct gprs_rlcmac_ul_tbf : public gprs_rlcmac_tbf { int assemble_forward_llc(const gprs_rlc_data *data); int snd_ul_ud(); + egprs_rlc_ul_reseg_bsn_state handle_egprs_ul_spb( + const struct gprs_rlc_data_info *rlc, + struct gprs_rlc_data *block, + uint8_t *data, const uint8_t block_idx); + + egprs_rlc_ul_reseg_bsn_state 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); + + egprs_rlc_ul_reseg_bsn_state 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); + /* Please note that all variables here will be reset when changing * from WAIT RELEASE back to FLOW state (re-use of TBF). * All states that need reset must be in this struct, so this is why 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; +} |