aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAravind Sirsikar <Arvind.sirsikar@radisys.com>2016-05-19 21:23:34 +0530
committerAravind Sirsikar <Arvind.sirsikar@radisys.com>2016-05-19 21:23:34 +0530
commitdb39e6cb722083787399175e9325f1b6c49f89de (patch)
tree8e1e1f76a769c32aa515ba7e2b5efd22406f00d0
parent2da0dbc7e5891c3046f0ca06e382fcb349e458d5 (diff)
Add support for Split block handling for EGPRS UL TBF
This patch will modify the EGPRS UL TBF flow to support Split block handling.
-rw-r--r--src/encoding.cpp6
-rw-r--r--src/tbf.h12
-rw-r--r--src/tbf_ul.cpp162
3 files changed, 156 insertions, 24 deletions
diff --git a/src/encoding.cpp b/src/encoding.cpp
index 44a0a0d..a078e23 100644
--- a/src/encoding.cpp
+++ b/src/encoding.cpp
@@ -276,7 +276,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
+ /* No RESEGMENT */
+ 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
@@ -613,7 +614,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 (nyi) */
+ 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
diff --git a/src/tbf.h b/src/tbf.h
index ad8ad4c..54c605f 100644
--- a/src/tbf.h
+++ b/src/tbf.h
@@ -439,6 +439,18 @@ 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 e01fa83..90c957b 100644
--- a/src/tbf_ul.cpp
+++ b/src/tbf_ul.cpp
@@ -138,6 +138,134 @@ struct msgb *gprs_rlcmac_ul_tbf::create_ul_ack(uint32_t fn, uint8_t ts)
return msg;
}
+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 struct gprs_rlc_data_block_info *rdbi =
+ &rlc->block_info[block_idx];
+
+ uint8_t *rlc_data = &(block->block[0]);
+
+ if (block->block_status_ul & EGPRS_RESEG_FIRST_SEG_RXD) {
+ LOGP(DRLCMACUL, LOGL_DEBUG,
+ "Second seg is received "
+ "first seg is already present "
+ "set the status to complete\n");
+ block->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;
+ return EGPRS_RESEG_DEFAULT;
+
+ } else if (block->block_status_ul == EGPRS_RESEG_DEFAULT) {
+ LOGP(DRLCMACUL, LOGL_DEBUG,
+ "Second seg is received "
+ "first seg is not received "
+ "set the status to second seg received\n");
+ block->len = Decoding::rlc_copy_to_aligned_buffer(rlc,
+ block_idx, data, rlc_data);
+ block->block_status_ul = EGPRS_RESEG_SECOND_SEG_RXD;
+ block->block_info = *rdbi;
+ return EGPRS_RESEG_SECOND_SEG_RXD;
+ }
+ return EGPRS_RESEG_INVALID;
+}
+
+
+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 struct gprs_rlc_data_block_info *rdbi =
+ &rlc->block_info[block_idx];
+ uint8_t *rlc_data = &(block->block[0]);
+
+ if (block->block_status_ul & EGPRS_RESEG_SECOND_SEG_RXD) {
+ LOGP(DRLCMACUL, LOGL_DEBUG,
+ "First seg is received "
+ "second seg is already present "
+ "set the status to complete");
+ static uint8_t seg_data[RLC_MAX_LEN];
+ uint8_t len = block->len;
+
+ /* Assembling the resegmented split blocks */
+ memcpy(seg_data, block->block, len);
+ block->len = Decoding::rlc_copy_to_aligned_buffer(rlc,
+ block_idx, data, rlc_data);
+ memcpy(block->block + block->len, seg_data, len);
+ block->len += len;
+ block->block_info.data_len += rdbi->data_len;
+ block->block_status_ul = EGPRS_RESEG_DEFAULT;
+ return EGPRS_RESEG_DEFAULT;
+ } else if (block->block_status_ul == EGPRS_RESEG_DEFAULT) {
+ LOGP(DRLCMACUL, LOGL_DEBUG,
+ "First seg is received "
+ "second seg is not received "
+ "set the status to first seg "
+ "received\n");
+
+ block->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 EGPRS_RESEG_FIRST_SEG_RXD;
+ }
+ return EGPRS_RESEG_INVALID;
+}
+
+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 struct gprs_rlc_data_block_info *rdbi =
+ &rlc->block_info[block_idx];
+
+ LOGP(DRLCMACUL, LOGL_NOTICE,
+ "Got SPB(%d) "
+ "cs(%s) data block with BSN (%d), "
+ "TFI(%d).\n", rdbi->spb, rlc->cs.name(), rdbi->bsn,
+ rlc->tfi);
+
+ egprs_rlc_ul_reseg_bsn_state re_assemble_status = EGPRS_RESEG_INVALID;
+
+ /* Section 10.4.8b of 44.060*/
+ if (rdbi->spb == 2)
+ re_assemble_status = handle_egprs_ul_first_seg(rlc,
+ block, data, block_idx);
+ else if (rdbi->spb == 3)
+ re_assemble_status = handle_egprs_ul_second_seg(rlc,
+ block, data, block_idx);
+ else {
+ LOGP(DRLCMACUL, LOGL_ERROR,
+ "Not supported SPB for this EGPRS configuration\n");
+ OSMO_ASSERT(false);
+ }
+
+ /*
+ * When the block is successfully constructed out of segmented blocks
+ * upgrade the MCS to the type 2
+ */
+ if (re_assemble_status == EGPRS_RESEG_DEFAULT) {
+ switch (GprsCodingScheme::Scheme(rlc->cs)) {
+ case GprsCodingScheme::MCS3 :
+ block->cs = GprsCodingScheme::MCS6;
+ break;
+ case GprsCodingScheme::MCS2 :
+ block->cs = GprsCodingScheme::MCS5;
+ break;
+ case GprsCodingScheme::MCS1 :
+ block->cs = GprsCodingScheme::MCS4;
+ break;
+ default:
+ OSMO_ASSERT(false);
+ break;
+ }
+ }
+ return re_assemble_status;
+}
+
int gprs_rlcmac_ul_tbf::rcv_data_block_acknowledged(
const struct gprs_rlc_data_info *rlc,
uint8_t *data, struct pcu_l1_meas *meas)
@@ -219,36 +347,26 @@ 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 = 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 re_assemble_status =
+ handle_egprs_ul_spb(rlc, block,
+ data, block_idx);
+ if (re_assemble_status != EGPRS_RESEG_DEFAULT)
+ return 0;
+ } else {
+ block->block_info = *rdbi;
+ block->cs = rlc->cs;
+ block->len =
+ Decoding::rlc_copy_to_aligned_buffer(rlc,
+ block_idx, data, rlc_data);
}
- 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(