|
|
@ -17,12 +17,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
namespace srslte {
|
|
|
|
namespace srslte {
|
|
|
|
|
|
|
|
|
|
|
|
rlc_um_lte::rlc_um_lte(srslte::log_ref log_,
|
|
|
|
rlc_um_lte::rlc_um_lte(srslog::basic_logger& logger,
|
|
|
|
uint32_t lcid_,
|
|
|
|
uint32_t lcid_,
|
|
|
|
srsue::pdcp_interface_rlc* pdcp_,
|
|
|
|
srsue::pdcp_interface_rlc* pdcp_,
|
|
|
|
srsue::rrc_interface_rlc* rrc_,
|
|
|
|
srsue::rrc_interface_rlc* rrc_,
|
|
|
|
srslte::timer_handler* timers_) :
|
|
|
|
srslte::timer_handler* timers_) :
|
|
|
|
rlc_um_base(log_, lcid_, pdcp_, rrc_, timers_)
|
|
|
|
rlc_um_base(logger, lcid_, pdcp_, rrc_, timers_)
|
|
|
|
{}
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
|
|
// Warning: must call stop() to properly deallocate all buffers
|
|
|
|
// Warning: must call stop() to properly deallocate all buffers
|
|
|
@ -49,12 +49,12 @@ bool rlc_um_lte::configure(const rlc_config_t& cnfg_)
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
log->info("%s configured in %s: t_reordering=%d ms, rx_sn_field_length=%u bits, tx_sn_field_length=%u bits\n",
|
|
|
|
logger.info("%s configured in %s: t_reordering=%d ms, rx_sn_field_length=%u bits, tx_sn_field_length=%u bits",
|
|
|
|
rb_name.c_str(),
|
|
|
|
rb_name.c_str(),
|
|
|
|
srslte::to_string(cnfg_.rlc_mode).c_str(),
|
|
|
|
srslte::to_string(cnfg_.rlc_mode).c_str(),
|
|
|
|
cfg.um.t_reordering,
|
|
|
|
cfg.um.t_reordering,
|
|
|
|
srslte::to_number(cfg.um.rx_sn_field_length),
|
|
|
|
srslte::to_number(cfg.um.rx_sn_field_length),
|
|
|
|
srslte::to_number(cfg.um.tx_sn_field_length));
|
|
|
|
srslte::to_number(cfg.um.tx_sn_field_length));
|
|
|
|
|
|
|
|
|
|
|
|
rx_enabled = true;
|
|
|
|
rx_enabled = true;
|
|
|
|
tx_enabled = true;
|
|
|
|
tx_enabled = true;
|
|
|
@ -97,7 +97,7 @@ bool rlc_um_lte::rlc_um_lte_tx::configure(const rlc_config_t& cnfg_, std::string
|
|
|
|
cfg = cnfg_;
|
|
|
|
cfg = cnfg_;
|
|
|
|
|
|
|
|
|
|
|
|
if (cfg.um.tx_mod == 0) {
|
|
|
|
if (cfg.um.tx_mod == 0) {
|
|
|
|
log->error("Error configuring %s RLC UM: tx_mod==0\n", rb_name.c_str());
|
|
|
|
logger.error("Error configuring %s RLC UM: tx_mod==0", rb_name.c_str());
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -125,10 +125,10 @@ int rlc_um_lte::rlc_um_lte_tx::build_data_pdu(unique_byte_buffer_t pdu, uint8_t*
|
|
|
|
int pdu_space = SRSLTE_MIN(nof_bytes, pdu->get_tailroom());
|
|
|
|
int pdu_space = SRSLTE_MIN(nof_bytes, pdu->get_tailroom());
|
|
|
|
|
|
|
|
|
|
|
|
if (pdu_space <= head_len + 1) {
|
|
|
|
if (pdu_space <= head_len + 1) {
|
|
|
|
log->info("%s Cannot build a PDU - %d bytes available, %d bytes required for header\n",
|
|
|
|
logger.info("%s Cannot build a PDU - %d bytes available, %d bytes required for header",
|
|
|
|
rb_name.c_str(),
|
|
|
|
rb_name.c_str(),
|
|
|
|
nof_bytes,
|
|
|
|
nof_bytes,
|
|
|
|
head_len);
|
|
|
|
head_len);
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -136,8 +136,8 @@ int rlc_um_lte::rlc_um_lte_tx::build_data_pdu(unique_byte_buffer_t pdu, uint8_t*
|
|
|
|
if (tx_sdu) {
|
|
|
|
if (tx_sdu) {
|
|
|
|
uint32_t space = pdu_space - head_len;
|
|
|
|
uint32_t space = pdu_space - head_len;
|
|
|
|
to_move = space >= tx_sdu->N_bytes ? tx_sdu->N_bytes : space;
|
|
|
|
to_move = space >= tx_sdu->N_bytes ? tx_sdu->N_bytes : space;
|
|
|
|
log->debug(
|
|
|
|
logger.debug(
|
|
|
|
"%s adding remainder of SDU segment - %d bytes of %d remaining\n", rb_name.c_str(), to_move, tx_sdu->N_bytes);
|
|
|
|
"%s adding remainder of SDU segment - %d bytes of %d remaining", rb_name.c_str(), to_move, tx_sdu->N_bytes);
|
|
|
|
memcpy(pdu_ptr, tx_sdu->msg, to_move);
|
|
|
|
memcpy(pdu_ptr, tx_sdu->msg, to_move);
|
|
|
|
last_li = to_move;
|
|
|
|
last_li = to_move;
|
|
|
|
pdu_ptr += to_move;
|
|
|
|
pdu_ptr += to_move;
|
|
|
@ -148,12 +148,12 @@ int rlc_um_lte::rlc_um_lte_tx::build_data_pdu(unique_byte_buffer_t pdu, uint8_t*
|
|
|
|
#ifdef ENABLE_TIMESTAMP
|
|
|
|
#ifdef ENABLE_TIMESTAMP
|
|
|
|
auto latency_us = tx_sdu->get_latency_us().count();
|
|
|
|
auto latency_us = tx_sdu->get_latency_us().count();
|
|
|
|
mean_pdu_latency_us.push(latency_us);
|
|
|
|
mean_pdu_latency_us.push(latency_us);
|
|
|
|
log->debug("%s Complete SDU scheduled for tx. Stack latency (last/average): %" PRIu64 "/%ld us\n",
|
|
|
|
logger.debug("%s Complete SDU scheduled for tx. Stack latency (last/average): %" PRIu64 "/%ld us",
|
|
|
|
rb_name.c_str(),
|
|
|
|
rb_name.c_str(),
|
|
|
|
(uint64_t)latency_us,
|
|
|
|
(uint64_t)latency_us,
|
|
|
|
(long)mean_pdu_latency_us.value());
|
|
|
|
(long)mean_pdu_latency_us.value());
|
|
|
|
#else
|
|
|
|
#else
|
|
|
|
log->debug("%s Complete SDU scheduled for tx.\n", rb_name.c_str());
|
|
|
|
logger.debug("%s Complete SDU scheduled for tx.", rb_name.c_str());
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
tx_sdu.reset();
|
|
|
|
tx_sdu.reset();
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -163,7 +163,7 @@ int rlc_um_lte::rlc_um_lte_tx::build_data_pdu(unique_byte_buffer_t pdu, uint8_t*
|
|
|
|
|
|
|
|
|
|
|
|
// Pull SDUs from queue
|
|
|
|
// Pull SDUs from queue
|
|
|
|
while (pdu_space > head_len + 1 && tx_sdu_queue.size() > 0) {
|
|
|
|
while (pdu_space > head_len + 1 && tx_sdu_queue.size() > 0) {
|
|
|
|
log->debug("pdu_space=%d, head_len=%d\n", pdu_space, head_len);
|
|
|
|
logger.debug("pdu_space=%d, head_len=%d", pdu_space, head_len);
|
|
|
|
if (last_li > 0) {
|
|
|
|
if (last_li > 0) {
|
|
|
|
header.li[header.N_li++] = last_li;
|
|
|
|
header.li[header.N_li++] = last_li;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -176,7 +176,7 @@ int rlc_um_lte::rlc_um_lte_tx::build_data_pdu(unique_byte_buffer_t pdu, uint8_t*
|
|
|
|
}
|
|
|
|
}
|
|
|
|
tx_sdu = tx_sdu_queue.read();
|
|
|
|
tx_sdu = tx_sdu_queue.read();
|
|
|
|
to_move = (space >= tx_sdu->N_bytes) ? tx_sdu->N_bytes : space;
|
|
|
|
to_move = (space >= tx_sdu->N_bytes) ? tx_sdu->N_bytes : space;
|
|
|
|
log->debug("%s adding new SDU segment - %d bytes of %d remaining\n", rb_name.c_str(), to_move, tx_sdu->N_bytes);
|
|
|
|
logger.debug("%s adding new SDU segment - %d bytes of %d remaining", rb_name.c_str(), to_move, tx_sdu->N_bytes);
|
|
|
|
memcpy(pdu_ptr, tx_sdu->msg, to_move);
|
|
|
|
memcpy(pdu_ptr, tx_sdu->msg, to_move);
|
|
|
|
last_li = to_move;
|
|
|
|
last_li = to_move;
|
|
|
|
pdu_ptr += to_move;
|
|
|
|
pdu_ptr += to_move;
|
|
|
@ -187,12 +187,12 @@ int rlc_um_lte::rlc_um_lte_tx::build_data_pdu(unique_byte_buffer_t pdu, uint8_t*
|
|
|
|
#ifdef ENABLE_TIMESTAMP
|
|
|
|
#ifdef ENABLE_TIMESTAMP
|
|
|
|
auto latency_us = tx_sdu->get_latency_us().count();
|
|
|
|
auto latency_us = tx_sdu->get_latency_us().count();
|
|
|
|
mean_pdu_latency_us.push(latency_us);
|
|
|
|
mean_pdu_latency_us.push(latency_us);
|
|
|
|
log->debug("%s Complete SDU scheduled for tx. Stack latency (last/average): %" PRIu64 "/%ld us\n",
|
|
|
|
logger.debug("%s Complete SDU scheduled for tx. Stack latency (last/average): %" PRIu64 "/%ld us",
|
|
|
|
rb_name.c_str(),
|
|
|
|
rb_name.c_str(),
|
|
|
|
(uint64_t)latency_us,
|
|
|
|
(uint64_t)latency_us,
|
|
|
|
(long)mean_pdu_latency_us.value());
|
|
|
|
(long)mean_pdu_latency_us.value());
|
|
|
|
#else
|
|
|
|
#else
|
|
|
|
log->debug("%s Complete SDU scheduled for tx.\n", rb_name.c_str());
|
|
|
|
logger.debug("%s Complete SDU scheduled for tx.", rb_name.c_str());
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
tx_sdu.reset();
|
|
|
|
tx_sdu.reset();
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -211,7 +211,7 @@ int rlc_um_lte::rlc_um_lte_tx::build_data_pdu(unique_byte_buffer_t pdu, uint8_t*
|
|
|
|
rlc_um_write_data_pdu_header(&header, pdu.get());
|
|
|
|
rlc_um_write_data_pdu_header(&header, pdu.get());
|
|
|
|
memcpy(payload, pdu->msg, pdu->N_bytes);
|
|
|
|
memcpy(payload, pdu->msg, pdu->N_bytes);
|
|
|
|
|
|
|
|
|
|
|
|
log->info_hex(payload, pdu->N_bytes, "%s Tx PDU SN=%d (%d B)\n", rb_name.c_str(), header.sn, pdu->N_bytes);
|
|
|
|
logger.info(payload, pdu->N_bytes, "%s Tx PDU SN=%d (%d B)", rb_name.c_str(), header.sn, pdu->N_bytes);
|
|
|
|
|
|
|
|
|
|
|
|
debug_state();
|
|
|
|
debug_state();
|
|
|
|
|
|
|
|
|
|
|
@ -220,7 +220,7 @@ int rlc_um_lte::rlc_um_lte_tx::build_data_pdu(unique_byte_buffer_t pdu, uint8_t*
|
|
|
|
|
|
|
|
|
|
|
|
void rlc_um_lte::rlc_um_lte_tx::debug_state()
|
|
|
|
void rlc_um_lte::rlc_um_lte_tx::debug_state()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
log->debug("%s vt_us = %d\n", rb_name.c_str(), vt_us);
|
|
|
|
logger.debug("%s vt_us = %d", rb_name.c_str(), vt_us);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void rlc_um_lte::rlc_um_lte_tx::reset()
|
|
|
|
void rlc_um_lte::rlc_um_lte_tx::reset()
|
|
|
@ -243,13 +243,13 @@ bool rlc_um_lte::rlc_um_lte_rx::configure(const rlc_config_t& cnfg_, std::string
|
|
|
|
cfg = cnfg_;
|
|
|
|
cfg = cnfg_;
|
|
|
|
|
|
|
|
|
|
|
|
if (cfg.um.rx_mod == 0) {
|
|
|
|
if (cfg.um.rx_mod == 0) {
|
|
|
|
log->error("Error configuring %s RLC UM: rx_mod==0\n", rb_name.c_str());
|
|
|
|
logger.error("Error configuring %s RLC UM: rx_mod==0", rb_name.c_str());
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// check timer
|
|
|
|
// check timer
|
|
|
|
if (not reordering_timer.is_valid()) {
|
|
|
|
if (not reordering_timer.is_valid()) {
|
|
|
|
log->error("Configuring RLC UM RX: timers not configured\n");
|
|
|
|
logger.error("Configuring RLC UM RX: timers not configured");
|
|
|
|
return false;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -298,17 +298,17 @@ void rlc_um_lte::rlc_um_lte_rx::handle_data_pdu(uint8_t* payload, uint32_t nof_b
|
|
|
|
{
|
|
|
|
{
|
|
|
|
rlc_umd_pdu_header_t header;
|
|
|
|
rlc_umd_pdu_header_t header;
|
|
|
|
rlc_um_read_data_pdu_header(payload, nof_bytes, cfg.um.rx_sn_field_length, &header);
|
|
|
|
rlc_um_read_data_pdu_header(payload, nof_bytes, cfg.um.rx_sn_field_length, &header);
|
|
|
|
log->info_hex(payload, nof_bytes, "%s Rx data PDU SN=%d (%d B)", rb_name.c_str(), header.sn, nof_bytes);
|
|
|
|
logger.info(payload, nof_bytes, "%s Rx data PDU SN=%d (%d B)", rb_name.c_str(), header.sn, nof_bytes);
|
|
|
|
|
|
|
|
|
|
|
|
if (RX_MOD_BASE(header.sn) >= RX_MOD_BASE(vr_uh - cfg.um.rx_window_size) &&
|
|
|
|
if (RX_MOD_BASE(header.sn) >= RX_MOD_BASE(vr_uh - cfg.um.rx_window_size) &&
|
|
|
|
RX_MOD_BASE(header.sn) < RX_MOD_BASE(vr_ur)) {
|
|
|
|
RX_MOD_BASE(header.sn) < RX_MOD_BASE(vr_ur)) {
|
|
|
|
log->info("%s SN=%d outside rx window [%d:%d] - discarding\n", rb_name.c_str(), header.sn, vr_ur, vr_uh);
|
|
|
|
logger.info("%s SN=%d outside rx window [%d:%d] - discarding", rb_name.c_str(), header.sn, vr_ur, vr_uh);
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::map<uint32_t, rlc_umd_pdu_t>::iterator it = rx_window.find(header.sn);
|
|
|
|
std::map<uint32_t, rlc_umd_pdu_t>::iterator it = rx_window.find(header.sn);
|
|
|
|
if (rx_window.end() != it) {
|
|
|
|
if (rx_window.end() != it) {
|
|
|
|
log->info("%s Discarding duplicate SN=%d\n", rb_name.c_str(), header.sn);
|
|
|
|
logger.info("%s Discarding duplicate SN=%d", rb_name.c_str(), header.sn);
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -316,7 +316,7 @@ void rlc_um_lte::rlc_um_lte_rx::handle_data_pdu(uint8_t* payload, uint32_t nof_b
|
|
|
|
rlc_umd_pdu_t pdu = {};
|
|
|
|
rlc_umd_pdu_t pdu = {};
|
|
|
|
pdu.buf = make_byte_buffer();
|
|
|
|
pdu.buf = make_byte_buffer();
|
|
|
|
if (!pdu.buf) {
|
|
|
|
if (!pdu.buf) {
|
|
|
|
log->error("Discarting packet: no space in buffer pool\n");
|
|
|
|
logger.error("Discarting packet: no space in buffer pool");
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
memcpy(pdu.buf->msg, payload, nof_bytes);
|
|
|
|
memcpy(pdu.buf->msg, payload, nof_bytes);
|
|
|
@ -334,9 +334,9 @@ void rlc_um_lte::rlc_um_lte_rx::handle_data_pdu(uint8_t* payload, uint32_t nof_b
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Reassemble and deliver SDUs, while updating vr_ur
|
|
|
|
// Reassemble and deliver SDUs, while updating vr_ur
|
|
|
|
log->debug("Entering Reassemble from received PDU\n");
|
|
|
|
logger.debug("Entering Reassemble from received PDU");
|
|
|
|
reassemble_rx_sdus();
|
|
|
|
reassemble_rx_sdus();
|
|
|
|
log->debug("Finished reassemble from received PDU\n");
|
|
|
|
logger.debug("Finished reassemble from received PDU");
|
|
|
|
|
|
|
|
|
|
|
|
// Update reordering variables and timers
|
|
|
|
// Update reordering variables and timers
|
|
|
|
if (reordering_timer.is_running()) {
|
|
|
|
if (reordering_timer.is_running()) {
|
|
|
@ -360,32 +360,32 @@ void rlc_um_lte::rlc_um_lte_rx::reassemble_rx_sdus()
|
|
|
|
if (!rx_sdu) {
|
|
|
|
if (!rx_sdu) {
|
|
|
|
rx_sdu = make_byte_buffer();
|
|
|
|
rx_sdu = make_byte_buffer();
|
|
|
|
if (!rx_sdu) {
|
|
|
|
if (!rx_sdu) {
|
|
|
|
log->error("Fatal Error: Couldn't allocate buffer in rlc_um::reassemble_rx_sdus().\n");
|
|
|
|
logger.error("Fatal Error: Couldn't allocate buffer in rlc_um::reassemble_rx_sdus().");
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// First catch up with lower edge of reordering window
|
|
|
|
// First catch up with lower edge of reordering window
|
|
|
|
while (!inside_reordering_window(vr_ur)) {
|
|
|
|
while (!inside_reordering_window(vr_ur)) {
|
|
|
|
log->debug("SN=%d is not inside reordering windows\n", vr_ur);
|
|
|
|
logger.debug("SN=%d is not inside reordering windows", vr_ur);
|
|
|
|
|
|
|
|
|
|
|
|
if (rx_window.end() == rx_window.find(vr_ur)) {
|
|
|
|
if (rx_window.end() == rx_window.find(vr_ur)) {
|
|
|
|
log->debug("SN=%d not in rx_window. Reset received SDU\n", vr_ur);
|
|
|
|
logger.debug("SN=%d not in rx_window. Reset received SDU", vr_ur);
|
|
|
|
rx_sdu->clear();
|
|
|
|
rx_sdu->clear();
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
// Handle any SDU segments
|
|
|
|
// Handle any SDU segments
|
|
|
|
for (uint32_t i = 0; i < rx_window[vr_ur].header.N_li; i++) {
|
|
|
|
for (uint32_t i = 0; i < rx_window[vr_ur].header.N_li; i++) {
|
|
|
|
int len = rx_window[vr_ur].header.li[i];
|
|
|
|
int len = rx_window[vr_ur].header.li[i];
|
|
|
|
log->debug_hex(rx_window[vr_ur].buf->msg,
|
|
|
|
logger.debug(rx_window[vr_ur].buf->msg,
|
|
|
|
len,
|
|
|
|
len,
|
|
|
|
"Handling segment %d/%d of length %d B of SN=%d\n",
|
|
|
|
"Handling segment %d/%d of length %d B of SN=%d",
|
|
|
|
i + 1,
|
|
|
|
i + 1,
|
|
|
|
rx_window[vr_ur].header.N_li,
|
|
|
|
rx_window[vr_ur].header.N_li,
|
|
|
|
len,
|
|
|
|
len,
|
|
|
|
vr_ur);
|
|
|
|
vr_ur);
|
|
|
|
// Check if we received a middle or end segment
|
|
|
|
// Check if we received a middle or end segment
|
|
|
|
if (rx_sdu->N_bytes == 0 && i == 0 && !rlc_um_start_aligned(rx_window[vr_ur].header.fi)) {
|
|
|
|
if (rx_sdu->N_bytes == 0 && i == 0 && !rlc_um_start_aligned(rx_window[vr_ur].header.fi)) {
|
|
|
|
log->warning("Dropping PDU %d in reassembly due to lost start segment\n", vr_ur);
|
|
|
|
logger.warning("Dropping PDU %d in reassembly due to lost start segment", vr_ur);
|
|
|
|
// Advance data pointers and continue with next segment
|
|
|
|
// Advance data pointers and continue with next segment
|
|
|
|
rx_window[vr_ur].buf->msg += len;
|
|
|
|
rx_window[vr_ur].buf->msg += len;
|
|
|
|
rx_window[vr_ur].buf->N_bytes -= len;
|
|
|
|
rx_window[vr_ur].buf->N_bytes -= len;
|
|
|
@ -400,18 +400,18 @@ void rlc_um_lte::rlc_um_lte_rx::reassemble_rx_sdus()
|
|
|
|
rx_window[vr_ur].buf->N_bytes -= len;
|
|
|
|
rx_window[vr_ur].buf->N_bytes -= len;
|
|
|
|
if ((pdu_lost && !rlc_um_start_aligned(rx_window[vr_ur].header.fi)) ||
|
|
|
|
if ((pdu_lost && !rlc_um_start_aligned(rx_window[vr_ur].header.fi)) ||
|
|
|
|
(vr_ur != ((vr_ur_in_rx_sdu + 1) % cfg.um.rx_mod))) {
|
|
|
|
(vr_ur != ((vr_ur_in_rx_sdu + 1) % cfg.um.rx_mod))) {
|
|
|
|
log->warning("Dropping remainder of lost PDU (lower edge middle segments, vr_ur=%d, vr_ur_in_rx_sdu=%d)\n",
|
|
|
|
logger.warning("Dropping remainder of lost PDU (lower edge middle segments, vr_ur=%d, vr_ur_in_rx_sdu=%d)",
|
|
|
|
vr_ur,
|
|
|
|
vr_ur,
|
|
|
|
vr_ur_in_rx_sdu);
|
|
|
|
vr_ur_in_rx_sdu);
|
|
|
|
rx_sdu->clear();
|
|
|
|
rx_sdu->clear();
|
|
|
|
metrics.num_lost_pdus++;
|
|
|
|
metrics.num_lost_pdus++;
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
log->info_hex(rx_sdu->msg,
|
|
|
|
logger.info(rx_sdu->msg,
|
|
|
|
rx_sdu->N_bytes,
|
|
|
|
rx_sdu->N_bytes,
|
|
|
|
"%s Rx SDU vr_ur=%d, i=%d (lower edge middle segments)",
|
|
|
|
"%s Rx SDU vr_ur=%d, i=%d (lower edge middle segments)",
|
|
|
|
rb_name.c_str(),
|
|
|
|
rb_name.c_str(),
|
|
|
|
vr_ur,
|
|
|
|
vr_ur,
|
|
|
|
i);
|
|
|
|
i);
|
|
|
|
rx_sdu->set_timestamp();
|
|
|
|
rx_sdu->set_timestamp();
|
|
|
|
metrics.num_rx_sdus++;
|
|
|
|
metrics.num_rx_sdus++;
|
|
|
|
metrics.num_rx_sdu_bytes += rx_sdu->N_bytes;
|
|
|
|
metrics.num_rx_sdu_bytes += rx_sdu->N_bytes;
|
|
|
@ -422,7 +422,7 @@ void rlc_um_lte::rlc_um_lte_rx::reassemble_rx_sdus()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
rx_sdu = make_byte_buffer();
|
|
|
|
rx_sdu = make_byte_buffer();
|
|
|
|
if (!rx_sdu) {
|
|
|
|
if (!rx_sdu) {
|
|
|
|
log->error("Fatal Error: Couldn't allocate buffer in rlc_um::reassemble_rx_sdus().\n");
|
|
|
|
logger.error("Fatal Error: Couldn't allocate buffer in rlc_um::reassemble_rx_sdus().");
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -431,21 +431,21 @@ void rlc_um_lte::rlc_um_lte_rx::reassemble_rx_sdus()
|
|
|
|
|
|
|
|
|
|
|
|
// Handle last segment
|
|
|
|
// Handle last segment
|
|
|
|
if (rx_sdu->N_bytes > 0 || rlc_um_start_aligned(rx_window[vr_ur].header.fi)) {
|
|
|
|
if (rx_sdu->N_bytes > 0 || rlc_um_start_aligned(rx_window[vr_ur].header.fi)) {
|
|
|
|
log->info("Writing last segment in SDU buffer. Lower edge vr_ur=%d, Buffer size=%d, segment size=%d\n",
|
|
|
|
logger.info("Writing last segment in SDU buffer. Lower edge vr_ur=%d, Buffer size=%d, segment size=%d",
|
|
|
|
vr_ur,
|
|
|
|
vr_ur,
|
|
|
|
rx_sdu->N_bytes,
|
|
|
|
rx_sdu->N_bytes,
|
|
|
|
rx_window[vr_ur].buf->N_bytes);
|
|
|
|
rx_window[vr_ur].buf->N_bytes);
|
|
|
|
|
|
|
|
|
|
|
|
memcpy(&rx_sdu->msg[rx_sdu->N_bytes], rx_window[vr_ur].buf->msg, rx_window[vr_ur].buf->N_bytes);
|
|
|
|
memcpy(&rx_sdu->msg[rx_sdu->N_bytes], rx_window[vr_ur].buf->msg, rx_window[vr_ur].buf->N_bytes);
|
|
|
|
rx_sdu->N_bytes += rx_window[vr_ur].buf->N_bytes;
|
|
|
|
rx_sdu->N_bytes += rx_window[vr_ur].buf->N_bytes;
|
|
|
|
vr_ur_in_rx_sdu = vr_ur;
|
|
|
|
vr_ur_in_rx_sdu = vr_ur;
|
|
|
|
if (rlc_um_end_aligned(rx_window[vr_ur].header.fi)) {
|
|
|
|
if (rlc_um_end_aligned(rx_window[vr_ur].header.fi)) {
|
|
|
|
if (pdu_lost && !rlc_um_start_aligned(rx_window[vr_ur].header.fi)) {
|
|
|
|
if (pdu_lost && !rlc_um_start_aligned(rx_window[vr_ur].header.fi)) {
|
|
|
|
log->warning("Dropping remainder of lost PDU (lower edge last segments)\n");
|
|
|
|
logger.warning("Dropping remainder of lost PDU (lower edge last segments)");
|
|
|
|
rx_sdu->clear();
|
|
|
|
rx_sdu->clear();
|
|
|
|
metrics.num_lost_pdus++;
|
|
|
|
metrics.num_lost_pdus++;
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
log->info_hex(
|
|
|
|
logger.info(
|
|
|
|
rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU vr_ur=%d (lower edge last segments)", rb_name.c_str(), vr_ur);
|
|
|
|
rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU vr_ur=%d (lower edge last segments)", rb_name.c_str(), vr_ur);
|
|
|
|
rx_sdu->set_timestamp();
|
|
|
|
rx_sdu->set_timestamp();
|
|
|
|
metrics.num_rx_sdus++;
|
|
|
|
metrics.num_rx_sdus++;
|
|
|
@ -457,7 +457,7 @@ void rlc_um_lte::rlc_um_lte_rx::reassemble_rx_sdus()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
rx_sdu = make_byte_buffer();
|
|
|
|
rx_sdu = make_byte_buffer();
|
|
|
|
if (!rx_sdu) {
|
|
|
|
if (!rx_sdu) {
|
|
|
|
log->error("Fatal Error: Couldn't allocate buffer in rlc_um::reassemble_rx_sdus().\n");
|
|
|
|
logger.error("Fatal Error: Couldn't allocate buffer in rlc_um::reassemble_rx_sdus().");
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -474,11 +474,11 @@ void rlc_um_lte::rlc_um_lte_rx::reassemble_rx_sdus()
|
|
|
|
|
|
|
|
|
|
|
|
// Now update vr_ur until we reach an SN we haven't yet received
|
|
|
|
// Now update vr_ur until we reach an SN we haven't yet received
|
|
|
|
while (rx_window.end() != rx_window.find(vr_ur)) {
|
|
|
|
while (rx_window.end() != rx_window.find(vr_ur)) {
|
|
|
|
log->debug("Reassemble loop for vr_ur=%d\n", vr_ur);
|
|
|
|
logger.debug("Reassemble loop for vr_ur=%d", vr_ur);
|
|
|
|
|
|
|
|
|
|
|
|
if (not pdu_belongs_to_rx_sdu()) {
|
|
|
|
if (not pdu_belongs_to_rx_sdu()) {
|
|
|
|
log->warning(
|
|
|
|
logger.warning(
|
|
|
|
"PDU SN=%d lost, stop reassambling SDU (vr_ur_in_rx_sdu=%d)\n", vr_ur_in_rx_sdu + 1, vr_ur_in_rx_sdu);
|
|
|
|
"PDU SN=%d lost, stop reassambling SDU (vr_ur_in_rx_sdu=%d)", vr_ur_in_rx_sdu + 1, vr_ur_in_rx_sdu);
|
|
|
|
pdu_lost = false; // Reset flag to not prevent reassembling of further segments
|
|
|
|
pdu_lost = false; // Reset flag to not prevent reassembling of further segments
|
|
|
|
rx_sdu->clear();
|
|
|
|
rx_sdu->clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -486,22 +486,22 @@ void rlc_um_lte::rlc_um_lte_rx::reassemble_rx_sdus()
|
|
|
|
// Handle any SDU segments
|
|
|
|
// Handle any SDU segments
|
|
|
|
for (uint32_t i = 0; i < rx_window[vr_ur].header.N_li; i++) {
|
|
|
|
for (uint32_t i = 0; i < rx_window[vr_ur].header.N_li; i++) {
|
|
|
|
uint16_t len = rx_window[vr_ur].header.li[i];
|
|
|
|
uint16_t len = rx_window[vr_ur].header.li[i];
|
|
|
|
log->debug("Handling SDU segment i=%d with len=%d of vr_ur=%d N_li=%d [%s]\n",
|
|
|
|
logger.debug("Handling SDU segment i=%d with len=%d of vr_ur=%d N_li=%d [%s]",
|
|
|
|
i,
|
|
|
|
i,
|
|
|
|
len,
|
|
|
|
len,
|
|
|
|
vr_ur,
|
|
|
|
vr_ur,
|
|
|
|
rx_window[vr_ur].header.N_li,
|
|
|
|
rx_window[vr_ur].header.N_li,
|
|
|
|
rlc_fi_field_text[rx_window[vr_ur].header.fi]);
|
|
|
|
rlc_fi_field_text[rx_window[vr_ur].header.fi]);
|
|
|
|
// Check if the first part of the PDU is a middle or end segment
|
|
|
|
// Check if the first part of the PDU is a middle or end segment
|
|
|
|
if (rx_sdu->N_bytes == 0 && i == 0 && !rlc_um_start_aligned(rx_window[vr_ur].header.fi)) {
|
|
|
|
if (rx_sdu->N_bytes == 0 && i == 0 && !rlc_um_start_aligned(rx_window[vr_ur].header.fi)) {
|
|
|
|
log->warning_hex(
|
|
|
|
logger.warning(
|
|
|
|
rx_window[vr_ur].buf->msg, len, "Dropping first %d B of SN=%d due to lost start segment\n", len, vr_ur);
|
|
|
|
rx_window[vr_ur].buf->msg, len, "Dropping first %d B of SN=%d due to lost start segment", len, vr_ur);
|
|
|
|
|
|
|
|
|
|
|
|
if (rx_window[vr_ur].buf->N_bytes < len) {
|
|
|
|
if (rx_window[vr_ur].buf->N_bytes < len) {
|
|
|
|
log->error("Dropping remaining remainder of SN=%d too (N_bytes=%u < len=%d)\n",
|
|
|
|
logger.error("Dropping remaining remainder of SN=%d too (N_bytes=%u < len=%d)",
|
|
|
|
vr_ur,
|
|
|
|
vr_ur,
|
|
|
|
rx_window[vr_ur].buf->N_bytes,
|
|
|
|
rx_window[vr_ur].buf->N_bytes,
|
|
|
|
len);
|
|
|
|
len);
|
|
|
|
goto clean_up_rx_window;
|
|
|
|
goto clean_up_rx_window;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -518,31 +518,31 @@ void rlc_um_lte::rlc_um_lte_rx::reassemble_rx_sdus()
|
|
|
|
|
|
|
|
|
|
|
|
// Check available space in SDU
|
|
|
|
// Check available space in SDU
|
|
|
|
if ((uint32_t)len > rx_sdu->get_tailroom()) {
|
|
|
|
if ((uint32_t)len > rx_sdu->get_tailroom()) {
|
|
|
|
log->error("Dropping PDU %d due to buffer mis-alignment (current segment len %d B, received %d B)\n",
|
|
|
|
logger.error("Dropping PDU %d due to buffer mis-alignment (current segment len %d B, received %d B)",
|
|
|
|
vr_ur,
|
|
|
|
vr_ur,
|
|
|
|
rx_sdu->N_bytes,
|
|
|
|
rx_sdu->N_bytes,
|
|
|
|
len);
|
|
|
|
len);
|
|
|
|
rx_sdu->clear();
|
|
|
|
rx_sdu->clear();
|
|
|
|
metrics.num_lost_pdus++;
|
|
|
|
metrics.num_lost_pdus++;
|
|
|
|
goto clean_up_rx_window;
|
|
|
|
goto clean_up_rx_window;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (not pdu_belongs_to_rx_sdu()) {
|
|
|
|
if (not pdu_belongs_to_rx_sdu()) {
|
|
|
|
log->info_hex(rx_window[vr_ur].buf->msg, len, "Copying first %d bytes of new SDU\n", len);
|
|
|
|
logger.info(rx_window[vr_ur].buf->msg, len, "Copying first %d bytes of new SDU", len);
|
|
|
|
log->info("Updating vr_ur_in_rx_sdu. old=%d, new=%d\n", vr_ur_in_rx_sdu, vr_ur);
|
|
|
|
logger.info("Updating vr_ur_in_rx_sdu. old=%d, new=%d", vr_ur_in_rx_sdu, vr_ur);
|
|
|
|
vr_ur_in_rx_sdu = vr_ur;
|
|
|
|
vr_ur_in_rx_sdu = vr_ur;
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
log->info_hex(rx_window[vr_ur].buf->msg,
|
|
|
|
logger.info(rx_window[vr_ur].buf->msg,
|
|
|
|
len,
|
|
|
|
len,
|
|
|
|
"Concatenating %d bytes in to current length %d. rx_window remaining bytes=%d, "
|
|
|
|
"Concatenating %d bytes in to current length %d. rx_window remaining bytes=%d, "
|
|
|
|
"vr_ur_in_rx_sdu=%d, vr_ur=%d, rx_mod=%d, last_mod=%d\n",
|
|
|
|
"vr_ur_in_rx_sdu=%d, vr_ur=%d, rx_mod=%d, last_mod=%d",
|
|
|
|
len,
|
|
|
|
len,
|
|
|
|
rx_sdu->N_bytes,
|
|
|
|
rx_sdu->N_bytes,
|
|
|
|
rx_window[vr_ur].buf->N_bytes,
|
|
|
|
rx_window[vr_ur].buf->N_bytes,
|
|
|
|
vr_ur_in_rx_sdu,
|
|
|
|
vr_ur_in_rx_sdu,
|
|
|
|
vr_ur,
|
|
|
|
vr_ur,
|
|
|
|
cfg.um.rx_mod,
|
|
|
|
cfg.um.rx_mod,
|
|
|
|
(vr_ur_in_rx_sdu + 1) % cfg.um.rx_mod);
|
|
|
|
(vr_ur_in_rx_sdu + 1) % cfg.um.rx_mod);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
memcpy(&rx_sdu->msg[rx_sdu->N_bytes], rx_window[vr_ur].buf->msg, len);
|
|
|
|
memcpy(&rx_sdu->msg[rx_sdu->N_bytes], rx_window[vr_ur].buf->msg, len);
|
|
|
@ -552,12 +552,12 @@ void rlc_um_lte::rlc_um_lte_rx::reassemble_rx_sdus()
|
|
|
|
vr_ur_in_rx_sdu = vr_ur;
|
|
|
|
vr_ur_in_rx_sdu = vr_ur;
|
|
|
|
|
|
|
|
|
|
|
|
if (pdu_belongs_to_rx_sdu()) {
|
|
|
|
if (pdu_belongs_to_rx_sdu()) {
|
|
|
|
log->info_hex(rx_sdu->msg,
|
|
|
|
logger.info(rx_sdu->msg,
|
|
|
|
rx_sdu->N_bytes,
|
|
|
|
rx_sdu->N_bytes,
|
|
|
|
"%s Rx SDU vr_ur=%d, i=%d, (update vr_ur middle segments)",
|
|
|
|
"%s Rx SDU vr_ur=%d, i=%d, (update vr_ur middle segments)",
|
|
|
|
rb_name.c_str(),
|
|
|
|
rb_name.c_str(),
|
|
|
|
vr_ur,
|
|
|
|
vr_ur,
|
|
|
|
i);
|
|
|
|
i);
|
|
|
|
rx_sdu->set_timestamp();
|
|
|
|
rx_sdu->set_timestamp();
|
|
|
|
metrics.num_rx_sdus++;
|
|
|
|
metrics.num_rx_sdus++;
|
|
|
|
metrics.num_rx_sdu_bytes += rx_sdu->N_bytes;
|
|
|
|
metrics.num_rx_sdu_bytes += rx_sdu->N_bytes;
|
|
|
@ -568,13 +568,13 @@ void rlc_um_lte::rlc_um_lte_rx::reassemble_rx_sdus()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
rx_sdu = make_byte_buffer();
|
|
|
|
rx_sdu = make_byte_buffer();
|
|
|
|
if (!rx_sdu) {
|
|
|
|
if (!rx_sdu) {
|
|
|
|
log->error("Fatal Error: Couldn't allocate buffer in rlc_um::reassemble_rx_sdus().\n");
|
|
|
|
logger.error("Fatal Error: Couldn't allocate buffer in rlc_um::reassemble_rx_sdus().");
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
log->warning("Dropping remainder of lost PDU (update vr_ur middle segments, vr_ur=%d, vr_ur_in_rx_sdu=%d)\n",
|
|
|
|
logger.warning("Dropping remainder of lost PDU (update vr_ur middle segments, vr_ur=%d, vr_ur_in_rx_sdu=%d)",
|
|
|
|
vr_ur,
|
|
|
|
vr_ur,
|
|
|
|
vr_ur_in_rx_sdu);
|
|
|
|
vr_ur_in_rx_sdu);
|
|
|
|
// Advance data pointers and continue with next segment
|
|
|
|
// Advance data pointers and continue with next segment
|
|
|
|
rx_window[vr_ur].buf->msg += len;
|
|
|
|
rx_window[vr_ur].buf->msg += len;
|
|
|
|
rx_window[vr_ur].buf->N_bytes -= len;
|
|
|
|
rx_window[vr_ur].buf->N_bytes -= len;
|
|
|
@ -586,7 +586,7 @@ void rlc_um_lte::rlc_um_lte_rx::reassemble_rx_sdus()
|
|
|
|
// Handle last segment
|
|
|
|
// Handle last segment
|
|
|
|
if (rx_sdu->N_bytes == 0 && rx_window[vr_ur].header.N_li == 0 &&
|
|
|
|
if (rx_sdu->N_bytes == 0 && rx_window[vr_ur].header.N_li == 0 &&
|
|
|
|
!rlc_um_start_aligned(rx_window[vr_ur].header.fi)) {
|
|
|
|
!rlc_um_start_aligned(rx_window[vr_ur].header.fi)) {
|
|
|
|
log->warning("Dropping PDU %d during last segment handling due to lost start segment\n", vr_ur);
|
|
|
|
logger.warning("Dropping PDU %d during last segment handling due to lost start segment", vr_ur);
|
|
|
|
rx_sdu->clear();
|
|
|
|
rx_sdu->clear();
|
|
|
|
metrics.num_lost_pdus++;
|
|
|
|
metrics.num_lost_pdus++;
|
|
|
|
goto clean_up_rx_window;
|
|
|
|
goto clean_up_rx_window;
|
|
|
@ -595,30 +595,30 @@ void rlc_um_lte::rlc_um_lte_rx::reassemble_rx_sdus()
|
|
|
|
if (rx_sdu->N_bytes < SRSLTE_MAX_BUFFER_SIZE_BYTES &&
|
|
|
|
if (rx_sdu->N_bytes < SRSLTE_MAX_BUFFER_SIZE_BYTES &&
|
|
|
|
rx_window[vr_ur].buf->N_bytes < SRSLTE_MAX_BUFFER_SIZE_BYTES &&
|
|
|
|
rx_window[vr_ur].buf->N_bytes < SRSLTE_MAX_BUFFER_SIZE_BYTES &&
|
|
|
|
rx_window[vr_ur].buf->N_bytes + rx_sdu->N_bytes < SRSLTE_MAX_BUFFER_SIZE_BYTES) {
|
|
|
|
rx_window[vr_ur].buf->N_bytes + rx_sdu->N_bytes < SRSLTE_MAX_BUFFER_SIZE_BYTES) {
|
|
|
|
log->info_hex(rx_window[vr_ur].buf->msg,
|
|
|
|
logger.info(rx_window[vr_ur].buf->msg,
|
|
|
|
rx_window[vr_ur].buf->N_bytes,
|
|
|
|
rx_window[vr_ur].buf->N_bytes,
|
|
|
|
"Writing last segment in SDU buffer. Updating vr_ur=%d, vr_ur_in_rx_sdu=%d, Buffer size=%d, "
|
|
|
|
"Writing last segment in SDU buffer. Updating vr_ur=%d, vr_ur_in_rx_sdu=%d, Buffer size=%d, "
|
|
|
|
"segment size=%d\n",
|
|
|
|
"segment size=%d",
|
|
|
|
vr_ur,
|
|
|
|
vr_ur,
|
|
|
|
vr_ur_in_rx_sdu,
|
|
|
|
vr_ur_in_rx_sdu,
|
|
|
|
rx_sdu->N_bytes,
|
|
|
|
rx_sdu->N_bytes,
|
|
|
|
rx_window[vr_ur].buf->N_bytes);
|
|
|
|
rx_window[vr_ur].buf->N_bytes);
|
|
|
|
memcpy(&rx_sdu->msg[rx_sdu->N_bytes], rx_window[vr_ur].buf->msg, rx_window[vr_ur].buf->N_bytes);
|
|
|
|
memcpy(&rx_sdu->msg[rx_sdu->N_bytes], rx_window[vr_ur].buf->msg, rx_window[vr_ur].buf->N_bytes);
|
|
|
|
rx_sdu->N_bytes += rx_window[vr_ur].buf->N_bytes;
|
|
|
|
rx_sdu->N_bytes += rx_window[vr_ur].buf->N_bytes;
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
log->error("Out of bounds while reassembling SDU buffer in UM: sdu_len=%d, window_buffer_len=%d, vr_ur=%d\n",
|
|
|
|
logger.error("Out of bounds while reassembling SDU buffer in UM: sdu_len=%d, window_buffer_len=%d, vr_ur=%d",
|
|
|
|
rx_sdu->N_bytes,
|
|
|
|
rx_sdu->N_bytes,
|
|
|
|
rx_window[vr_ur].buf->N_bytes,
|
|
|
|
rx_window[vr_ur].buf->N_bytes,
|
|
|
|
vr_ur);
|
|
|
|
vr_ur);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
vr_ur_in_rx_sdu = vr_ur;
|
|
|
|
vr_ur_in_rx_sdu = vr_ur;
|
|
|
|
if (rlc_um_end_aligned(rx_window[vr_ur].header.fi)) {
|
|
|
|
if (rlc_um_end_aligned(rx_window[vr_ur].header.fi)) {
|
|
|
|
if (pdu_lost && !rlc_um_start_aligned(rx_window[vr_ur].header.fi)) {
|
|
|
|
if (pdu_lost && !rlc_um_start_aligned(rx_window[vr_ur].header.fi)) {
|
|
|
|
log->warning("Dropping remainder of lost PDU (update vr_ur last segments)\n");
|
|
|
|
logger.warning("Dropping remainder of lost PDU (update vr_ur last segments)");
|
|
|
|
rx_sdu->clear();
|
|
|
|
rx_sdu->clear();
|
|
|
|
metrics.num_lost_pdus++;
|
|
|
|
metrics.num_lost_pdus++;
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
log->info_hex(
|
|
|
|
logger.info(
|
|
|
|
rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU vr_ur=%d (update vr_ur last segments)", rb_name.c_str(), vr_ur);
|
|
|
|
rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU vr_ur=%d (update vr_ur last segments)", rb_name.c_str(), vr_ur);
|
|
|
|
rx_sdu->set_timestamp();
|
|
|
|
rx_sdu->set_timestamp();
|
|
|
|
metrics.num_rx_sdus++;
|
|
|
|
metrics.num_rx_sdus++;
|
|
|
@ -630,7 +630,7 @@ void rlc_um_lte::rlc_um_lte_rx::reassemble_rx_sdus()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
rx_sdu = make_byte_buffer();
|
|
|
|
rx_sdu = make_byte_buffer();
|
|
|
|
if (!rx_sdu) {
|
|
|
|
if (!rx_sdu) {
|
|
|
|
log->error("Fatal Error: Couldn't allocate buffer in rlc_um::reassemble_rx_sdus().\n");
|
|
|
|
logger.error("Fatal Error: Couldn't allocate buffer in rlc_um::reassemble_rx_sdus().");
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -677,9 +677,9 @@ void rlc_um_lte::rlc_um_lte_rx::timer_expired(uint32_t timeout_id)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
if (reordering_timer.id() == timeout_id) {
|
|
|
|
if (reordering_timer.id() == timeout_id) {
|
|
|
|
// 36.322 v10 Section 5.1.2.2.4
|
|
|
|
// 36.322 v10 Section 5.1.2.2.4
|
|
|
|
log->info("%s reordering timeout expiry - updating vr_ur and reassembling\n", rb_name.c_str());
|
|
|
|
logger.info("%s reordering timeout expiry - updating vr_ur and reassembling", rb_name.c_str());
|
|
|
|
|
|
|
|
|
|
|
|
log->warning("Lost PDU SN=%d\n", vr_ur);
|
|
|
|
logger.warning("Lost PDU SN=%d", vr_ur);
|
|
|
|
|
|
|
|
|
|
|
|
pdu_lost = true;
|
|
|
|
pdu_lost = true;
|
|
|
|
if (rx_sdu != NULL) {
|
|
|
|
if (rx_sdu != NULL) {
|
|
|
@ -688,9 +688,9 @@ void rlc_um_lte::rlc_um_lte_rx::timer_expired(uint32_t timeout_id)
|
|
|
|
|
|
|
|
|
|
|
|
while (RX_MOD_BASE(vr_ur) < RX_MOD_BASE(vr_ux)) {
|
|
|
|
while (RX_MOD_BASE(vr_ur) < RX_MOD_BASE(vr_ux)) {
|
|
|
|
vr_ur = (vr_ur + 1) % cfg.um.rx_mod;
|
|
|
|
vr_ur = (vr_ur + 1) % cfg.um.rx_mod;
|
|
|
|
log->debug("Entering Reassemble from timeout id=%d\n", timeout_id);
|
|
|
|
logger.debug("Entering Reassemble from timeout id=%d", timeout_id);
|
|
|
|
reassemble_rx_sdus();
|
|
|
|
reassemble_rx_sdus();
|
|
|
|
log->debug("Finished reassemble from timeout id=%d\n", timeout_id);
|
|
|
|
logger.debug("Finished reassemble from timeout id=%d", timeout_id);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (RX_MOD_BASE(vr_uh) > RX_MOD_BASE(vr_ur)) {
|
|
|
|
if (RX_MOD_BASE(vr_uh) > RX_MOD_BASE(vr_ur)) {
|
|
|
@ -708,7 +708,7 @@ void rlc_um_lte::rlc_um_lte_rx::timer_expired(uint32_t timeout_id)
|
|
|
|
|
|
|
|
|
|
|
|
void rlc_um_lte::rlc_um_lte_rx::debug_state()
|
|
|
|
void rlc_um_lte::rlc_um_lte_rx::debug_state()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
log->debug("%s vr_ur = %d, vr_ux = %d, vr_uh = %d\n", rb_name.c_str(), vr_ur, vr_ux, vr_uh);
|
|
|
|
logger.debug("%s vr_ur = %d, vr_ux = %d, vr_uh = %d", rb_name.c_str(), vr_ur, vr_ux, vr_uh);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
/****************************************************************************
|
|
|
|