aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJacob Erlbeck <jerlbeck@sysmocom.de>2016-02-02 15:32:10 +0100
committerJacob Erlbeck <jerlbeck@sysmocom.de>2016-02-08 00:45:40 +0100
commitbe314d9a54578d1eb31ab84f5de9bc16f8e892e9 (patch)
tree756beab87dd7d3e0aa4c10072abf60307e265663 /src
parent14e26cbca3d4fe5b7e7e6729e12708555ddb3a41 (diff)
edge: Refactor create_dl_acked_block for multi-block support
Currently the method is hard-coded to support a single BSN only. MCS-7 to MCS-9 encode 2 data blocks into a single RLC data message. This commit refactors create_dl_acked_block to process any number of blocks internally. Note that this does not extend the parameter list accordingly and just duplicates the BSN if these MCS are being used. Sponsored-by: On-Waves ehf
Diffstat (limited to 'src')
-rw-r--r--src/tbf.h2
-rw-r--r--src/tbf_dl.cpp109
2 files changed, 86 insertions, 25 deletions
diff --git a/src/tbf.h b/src/tbf.h
index 443f85f..2eefbee 100644
--- a/src/tbf.h
+++ b/src/tbf.h
@@ -408,7 +408,7 @@ protected:
struct msgb *create_new_bsn(const uint32_t fn, const uint8_t ts);
struct msgb *create_dl_acked_block(const uint32_t fn, const uint8_t ts,
- const int index);
+ int index, int index2 = -1);
int update_window(const uint8_t ssn, const uint8_t *rbb);
int update_window(unsigned first_bsn, const struct bitvec *rbb);
int maybe_start_new_window();
diff --git a/src/tbf_dl.cpp b/src/tbf_dl.cpp
index 6208b60..21b2ba1 100644
--- a/src/tbf_dl.cpp
+++ b/src/tbf_dl.cpp
@@ -519,9 +519,9 @@ struct msgb *gprs_rlcmac_dl_tbf::create_new_bsn(const uint32_t fn, const uint8_t
struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block(
const uint32_t fn, const uint8_t ts,
- const int index)
+ int index, int index2)
{
- uint8_t *block_data, *msg_data;
+ uint8_t *msg_data;
struct msgb *dl_msg;
unsigned msg_len;
bool need_poll;
@@ -530,26 +530,96 @@ struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block(
unsigned int rrbp;
uint32_t new_poll_fn;
int rc;
-
+ bool is_final = false;
gprs_rlc_data_info rlc;
GprsCodingScheme cs;
- gprs_rlc_data_block_info *rdbi;
+ int bsns[ARRAY_SIZE(rlc.block_info)];
+ unsigned num_bsns;
+ int punct[ARRAY_SIZE(rlc.block_info)];
+ bool need_padding = false;
+
+ /*
+ * TODO: This is an experimental work-around to put 2 BSN into
+ * MSC-7 to MCS-9 encoded messages. It just sends the same BSN
+ * twice in the block. The cs should be derived from the TBF's
+ * current CS such that both BSNs (that must be compatible) can
+ * be put into the data area, even if the resulting CS is higher than
+ * the current limit.
+ */
+ cs = m_rlc.block(index)->cs;
+ bsns[0] = index;
+ num_bsns = 1;
- /* get data and header from current block */
- block_data = m_rlc.block(index)->block;
+ if (index2 >= 0) {
+ bsns[num_bsns] = index2;
+ num_bsns += 1;
+ }
- cs = m_rlc.block(index)->cs;
+ if (num_bsns == 1)
+ cs.decToSingleBlock(&need_padding);
- gprs_rlc_data_info_init_dl(&rlc, cs, false);
+ gprs_rlc_data_info_init_dl(&rlc, cs, need_padding);
rlc.usf = 7; /* will be set at scheduler */
rlc.pr = 0; /* FIXME: power reduction */
rlc.tfi = m_tfi; /* TFI */
- /* TODO: Use real puncturing values */
- rlc.cps = gprs_rlc_mcs_cps(cs, 0, 0, 0);
- rlc.block_info[data_block_idx] = m_rlc.block(index)->block_info;
- rdbi = &rlc.block_info[data_block_idx];
+ /* return data block(s) as message */
+ msg_len = cs.sizeDL();
+ dl_msg = msgb_alloc(msg_len, "rlcmac_dl_data");
+ if (!dl_msg)
+ return NULL;
+
+ msg_data = msgb_put(dl_msg, msg_len);
+
+ /* Copy block(s) to RLC message */
+ for (data_block_idx = 0; data_block_idx < rlc.num_data_blocks;
+ data_block_idx++)
+ {
+ int bsn;
+ GprsCodingScheme cs_enc;
+ uint8_t *block_data;
+ gprs_rlc_data_block_info *rdbi, *block_info;
+
+ /* Check if there are more blocks than BSNs */
+ if (data_block_idx < num_bsns)
+ bsn = bsns[data_block_idx];
+ else
+ bsn = bsns[0];
+
+ cs_enc = m_rlc.block(bsn)->cs;
+
+ /* get data and header from current block */
+ block_data = m_rlc.block(bsn)->block;
+
+ /* TODO: Use real puncturing values */
+ punct[data_block_idx] = data_block_idx;
+
+ 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);
+ }
+ rdbi->e = block_info->e;
+ rdbi->cv = block_info->cv;
+ rdbi->bsn = bsn;
+ is_final = is_final || rdbi->cv == 0;
+
+ LOGP(DRLCMACDL, LOGL_DEBUG, "- Copying data unit %d (BSN %d)\n",
+ data_block_idx, bsn);
+
+ Encoding::rlc_copy_from_aligned_buffer(&rlc, data_block_idx,
+ msg_data, block_data);
+ }
+
+ OSMO_ASSERT(ARRAY_SIZE(punct) >= 2);
+ rlc.cps = gprs_rlc_mcs_cps(cs, punct[0], punct[1], need_padding);
/* If the TBF has just started, relate frames_since_last_poll to the
* current fn */
@@ -583,7 +653,7 @@ struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block(
"TS %d\n", ts);
m_tx_counter = 0;
/* start timer whenever we send the final block */
- if (rdbi->cv == 0)
+ if (is_final)
tbf_timer_start(this, 3191, bts_data()->t3191, 0);
/* Clear poll timeout flag */
@@ -604,20 +674,11 @@ struct msgb *gprs_rlcmac_dl_tbf::create_dl_acked_block(
}
}
- msg_len = cs.sizeDL();
-
- /* return data block as message */
- dl_msg = msgb_alloc(msg_len, "rlcmac_dl_data");
- if (!dl_msg)
- return NULL;
-
- msg_data = msgb_put(dl_msg, msg_len);
Encoding::rlc_write_dl_data_header(&rlc, msg_data);
- Encoding::rlc_copy_from_aligned_buffer(&rlc, data_block_idx, msg_data,
- block_data);
- LOGP(DRLCMACDL, LOGL_DEBUG, "msg block (BSN %d, %s): %s\n",
+ LOGP(DRLCMACDL, LOGL_DEBUG, "msg block (BSN %d, %s%s): %s\n",
index, cs.name(),
+ need_padding ? ", padded" : "",
msgb_hexdump(dl_msg));
/* Increment TX-counter */