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
This commit is contained in:
Jacob Erlbeck 2016-02-02 15:32:10 +01:00
parent 14e26cbca3
commit be314d9a54
3 changed files with 338 additions and 83 deletions

View File

@ -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();

View File

@ -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;
/* get data and header from current block */
block_data = m_rlc.block(index)->block;
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;
gprs_rlc_data_info_init_dl(&rlc, cs, false);
if (index2 >= 0) {
bsns[num_bsns] = index2;
num_bsns += 1;
}
if (num_bsns == 1)
cs.decToSingleBlock(&need_padding);
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 */

File diff suppressed because it is too large Load Diff