|
|
|
@ -23,12 +23,12 @@
|
|
|
|
|
|
|
|
|
|
namespace srslte {
|
|
|
|
|
|
|
|
|
|
rlc_am_lte::rlc_am_lte(srslte::log_ref log_,
|
|
|
|
|
rlc_am_lte::rlc_am_lte(srslog::basic_logger& logger,
|
|
|
|
|
uint32_t lcid_,
|
|
|
|
|
srsue::pdcp_interface_rlc* pdcp_,
|
|
|
|
|
srsue::rrc_interface_rlc* rrc_,
|
|
|
|
|
srslte::timer_handler* timers_) :
|
|
|
|
|
log(log_), rrc(rrc_), pdcp(pdcp_), timers(timers_), lcid(lcid_), tx(this), rx(this)
|
|
|
|
|
logger(logger), rrc(rrc_), pdcp(pdcp_), timers(timers_), lcid(lcid_), tx(this), rx(this)
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
// Applies new configuration. Must be just reestablished or initiated
|
|
|
|
@ -41,17 +41,17 @@ bool rlc_am_lte::configure(const rlc_config_t& cfg_)
|
|
|
|
|
cfg = cfg_;
|
|
|
|
|
|
|
|
|
|
if (not rx.configure(cfg.am)) {
|
|
|
|
|
log->error("Error configuring bearer (RX)\n");
|
|
|
|
|
logger.error("Error configuring bearer (RX)");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (not tx.configure(cfg)) {
|
|
|
|
|
log->error("Error configuring bearer (TX)\n");
|
|
|
|
|
logger.error("Error configuring bearer (TX)");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log->info("%s configured: t_poll_retx=%d, poll_pdu=%d, poll_byte=%d, max_retx_thresh=%d, "
|
|
|
|
|
"t_reordering=%d, t_status_prohibit=%d\n",
|
|
|
|
|
logger.info("%s configured: t_poll_retx=%d, poll_pdu=%d, poll_byte=%d, max_retx_thresh=%d, "
|
|
|
|
|
"t_reordering=%d, t_status_prohibit=%d",
|
|
|
|
|
rb_name.c_str(),
|
|
|
|
|
cfg.am.t_poll_retx,
|
|
|
|
|
cfg.am.poll_pdu,
|
|
|
|
@ -75,14 +75,14 @@ void rlc_am_lte::empty_queue()
|
|
|
|
|
|
|
|
|
|
void rlc_am_lte::reestablish()
|
|
|
|
|
{
|
|
|
|
|
log->debug("Reestablished bearer %s\n", rb_name.c_str());
|
|
|
|
|
logger.debug("Reestablished bearer %s", rb_name.c_str());
|
|
|
|
|
tx.reestablish(); // calls stop and enables tx again
|
|
|
|
|
rx.reestablish(); // calls only stop
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void rlc_am_lte::stop()
|
|
|
|
|
{
|
|
|
|
|
log->debug("Stopped bearer %s\n", rb_name.c_str());
|
|
|
|
|
logger.debug("Stopped bearer %s", rb_name.c_str());
|
|
|
|
|
tx.stop();
|
|
|
|
|
rx.stop();
|
|
|
|
|
}
|
|
|
|
@ -167,7 +167,7 @@ void rlc_am_lte::write_pdu(uint8_t* payload, uint32_t nof_bytes)
|
|
|
|
|
|
|
|
|
|
rlc_am_lte::rlc_am_lte_tx::rlc_am_lte_tx(rlc_am_lte* parent_) :
|
|
|
|
|
parent(parent_),
|
|
|
|
|
log(parent_->log),
|
|
|
|
|
logger(parent_->logger),
|
|
|
|
|
pool(byte_buffer_pool::get_instance()),
|
|
|
|
|
poll_retx_timer(parent_->timers->get_unique_timer()),
|
|
|
|
|
status_prohibit_timer(parent_->timers->get_unique_timer())
|
|
|
|
@ -192,7 +192,7 @@ bool rlc_am_lte::rlc_am_lte_tx::configure(const rlc_config_t& cfg_)
|
|
|
|
|
|
|
|
|
|
// check timers
|
|
|
|
|
if (not poll_retx_timer.is_valid() or not status_prohibit_timer.is_valid()) {
|
|
|
|
|
log->error("Configuring RLC AM TX: timers not configured\n");
|
|
|
|
|
logger.error("Configuring RLC AM TX: timers not configured");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -286,7 +286,7 @@ uint32_t rlc_am_lte::rlc_am_lte_tx::get_buffer_state()
|
|
|
|
|
uint32_t n_bytes = 0;
|
|
|
|
|
uint32_t n_sdus = 0;
|
|
|
|
|
|
|
|
|
|
log->debug("%s Buffer state - do_status=%s, status_prohibit_running=%s (%d/%d)\n",
|
|
|
|
|
logger.debug("%s Buffer state - do_status=%s, status_prohibit_running=%s (%d/%d)",
|
|
|
|
|
RB_NAME,
|
|
|
|
|
do_status() ? "yes" : "no",
|
|
|
|
|
status_prohibit_timer.is_running() ? "yes" : "no",
|
|
|
|
@ -296,13 +296,13 @@ uint32_t rlc_am_lte::rlc_am_lte_tx::get_buffer_state()
|
|
|
|
|
// Bytes needed for status report
|
|
|
|
|
if (do_status() && not status_prohibit_timer.is_running()) {
|
|
|
|
|
n_bytes += parent->rx.get_status_pdu_length();
|
|
|
|
|
log->debug("%s Buffer state - total status report: %d bytes\n", RB_NAME, n_bytes);
|
|
|
|
|
logger.debug("%s Buffer state - total status report: %d bytes", RB_NAME, n_bytes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Bytes needed for retx
|
|
|
|
|
if (not retx_queue.empty()) {
|
|
|
|
|
rlc_amd_retx_t retx = retx_queue.front();
|
|
|
|
|
log->debug("%s Buffer state - retx - SN=%d, Segment: %s, %d:%d\n",
|
|
|
|
|
logger.debug("%s Buffer state - retx - SN=%d, Segment: %s, %d:%d",
|
|
|
|
|
RB_NAME,
|
|
|
|
|
retx.sn,
|
|
|
|
|
retx.is_segment ? "true" : "false",
|
|
|
|
@ -311,11 +311,11 @@ uint32_t rlc_am_lte::rlc_am_lte_tx::get_buffer_state()
|
|
|
|
|
if (tx_window.end() != tx_window.find(retx.sn)) {
|
|
|
|
|
int req_bytes = required_buffer_size(retx);
|
|
|
|
|
if (req_bytes < 0) {
|
|
|
|
|
log->error("In get_buffer_state(): Removing retx.sn=%d from queue\n", retx.sn);
|
|
|
|
|
logger.error("In get_buffer_state(): Removing retx.sn=%d from queue", retx.sn);
|
|
|
|
|
retx_queue.pop_front();
|
|
|
|
|
} else {
|
|
|
|
|
n_bytes += req_bytes;
|
|
|
|
|
log->debug("Buffer state - retx: %d bytes\n", n_bytes);
|
|
|
|
|
logger.debug("Buffer state - retx: %d bytes", n_bytes);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -338,7 +338,7 @@ uint32_t rlc_am_lte::rlc_am_lte_tx::get_buffer_state()
|
|
|
|
|
// Room needed for fixed header of data PDUs
|
|
|
|
|
if (n_bytes > 0 && n_sdus > 0) {
|
|
|
|
|
n_bytes += 2; // Two bytes for fixed header with SN length = 10
|
|
|
|
|
log->debug("%s Total buffer state - %d SDUs (%d B)\n", RB_NAME, n_sdus, n_bytes);
|
|
|
|
|
logger.debug("%s Total buffer state - %d SDUs (%d B)", RB_NAME, n_sdus, n_bytes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pthread_mutex_unlock(&mutex);
|
|
|
|
@ -355,7 +355,7 @@ int rlc_am_lte::rlc_am_lte_tx::write_sdu(unique_byte_buffer_t sdu)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (sdu.get() == nullptr) {
|
|
|
|
|
log->warning("NULL SDU pointer in write_sdu()\n");
|
|
|
|
|
logger.warning("NULL SDU pointer in write_sdu()");
|
|
|
|
|
pthread_mutex_unlock(&mutex);
|
|
|
|
|
return SRSLTE_ERROR;
|
|
|
|
|
}
|
|
|
|
@ -369,13 +369,12 @@ int rlc_am_lte::rlc_am_lte_tx::write_sdu(unique_byte_buffer_t sdu)
|
|
|
|
|
uint32_t nof_bytes = sdu->N_bytes;
|
|
|
|
|
srslte::error_type<unique_byte_buffer_t> ret = tx_sdu_queue.try_write(std::move(sdu));
|
|
|
|
|
if (ret) {
|
|
|
|
|
log->info_hex(
|
|
|
|
|
msg_ptr, nof_bytes, "%s Tx SDU (%d B, tx_sdu_queue_len=%d)\n", RB_NAME, nof_bytes, tx_sdu_queue.size());
|
|
|
|
|
logger.info(msg_ptr, nof_bytes, "%s Tx SDU (%d B, tx_sdu_queue_len=%d)", RB_NAME, nof_bytes, tx_sdu_queue.size());
|
|
|
|
|
} else {
|
|
|
|
|
// in case of fail, the try_write returns back the sdu
|
|
|
|
|
log->warning_hex(ret.error()->msg,
|
|
|
|
|
logger.warning(ret.error()->msg,
|
|
|
|
|
ret.error()->N_bytes,
|
|
|
|
|
"[Dropped SDU] %s Tx SDU (%d B, tx_sdu_queue_len=%d)\n",
|
|
|
|
|
"[Dropped SDU] %s Tx SDU (%d B, tx_sdu_queue_len=%d)",
|
|
|
|
|
RB_NAME,
|
|
|
|
|
ret.error()->N_bytes,
|
|
|
|
|
tx_sdu_queue.size());
|
|
|
|
@ -386,17 +385,17 @@ int rlc_am_lte::rlc_am_lte_tx::write_sdu(unique_byte_buffer_t sdu)
|
|
|
|
|
// Store SDU info
|
|
|
|
|
uint32_t info_count = undelivered_sdu_info_queue.count(info.sn);
|
|
|
|
|
if (info_count != 0) {
|
|
|
|
|
log->error("PDCP SDU info already exists. SN=%d\n", info.sn);
|
|
|
|
|
logger.error("PDCP SDU info already exists. SN=%d", info.sn);
|
|
|
|
|
pthread_mutex_unlock(&mutex);
|
|
|
|
|
return SRSLTE_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (undelivered_sdu_info_queue.size() >= pdcp_info_queue_capacity) {
|
|
|
|
|
log->warning("Undelivered PDCP SDU info queue is growing large. Queue size: %ld\n",
|
|
|
|
|
logger.warning("Undelivered PDCP SDU info queue is growing large. Queue size: %ld",
|
|
|
|
|
undelivered_sdu_info_queue.size());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log->debug("Adding SDU info for PDCP_SN=%d", info.sn);
|
|
|
|
|
logger.debug("Adding SDU info for PDCP_SN=%d", info.sn);
|
|
|
|
|
undelivered_sdu_info_queue[info.sn] = info;
|
|
|
|
|
pthread_mutex_unlock(&mutex);
|
|
|
|
|
return SRSLTE_SUCCESS;
|
|
|
|
@ -407,7 +406,7 @@ void rlc_am_lte::rlc_am_lte_tx::discard_sdu(uint32_t discard_sn)
|
|
|
|
|
if (!tx_enabled) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
log->warning("Discard SDU not implemented yet\n");
|
|
|
|
|
logger.warning("Discard SDU not implemented yet");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool rlc_am_lte::rlc_am_lte_tx::sdu_queue_is_full()
|
|
|
|
@ -425,11 +424,11 @@ int rlc_am_lte::rlc_am_lte_tx::read_pdu(uint8_t* payload, uint32_t nof_bytes)
|
|
|
|
|
goto unlock_and_exit;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log->debug("MAC opportunity - %d bytes\n", nof_bytes);
|
|
|
|
|
log->debug("tx_window size - %zu PDUs\n", tx_window.size());
|
|
|
|
|
logger.debug("MAC opportunity - %d bytes", nof_bytes);
|
|
|
|
|
logger.debug("tx_window size - %zu PDUs", tx_window.size());
|
|
|
|
|
|
|
|
|
|
if (not tx_enabled) {
|
|
|
|
|
log->debug("RLC entity not active. Not generating PDU.\n");
|
|
|
|
|
logger.debug("RLC entity not active. Not generating PDU.");
|
|
|
|
|
goto unlock_and_exit;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -464,7 +463,7 @@ void rlc_am_lte::rlc_am_lte_tx::timer_expired(uint32_t timeout_id)
|
|
|
|
|
{
|
|
|
|
|
pthread_mutex_lock(&mutex);
|
|
|
|
|
if (poll_retx_timer.is_valid() && poll_retx_timer.id() == timeout_id) {
|
|
|
|
|
log->debug("%s Poll reTx timer expired after %dms\n", RB_NAME, poll_retx_timer.duration());
|
|
|
|
|
logger.debug("%s Poll reTx timer expired after %dms", RB_NAME, poll_retx_timer.duration());
|
|
|
|
|
// Section 5.2.2.3 in TS 36.311, schedule PDU for retransmission if
|
|
|
|
|
// (a) both tx and retx buffer are empty, or
|
|
|
|
|
// (b) no new data PDU can be transmitted (tx window is full)
|
|
|
|
@ -484,7 +483,7 @@ void rlc_am_lte::rlc_am_lte_tx::retransmit_pdu()
|
|
|
|
|
if (not tx_window.empty()) {
|
|
|
|
|
// select PDU in tx window for retransmission
|
|
|
|
|
std::map<uint32_t, rlc_amd_tx_pdu_t>::iterator it = tx_window.begin();
|
|
|
|
|
log->info("%s Schedule SN=%d for reTx.\n", RB_NAME, it->first);
|
|
|
|
|
logger.info("%s Schedule SN=%d for reTx.", RB_NAME, it->first);
|
|
|
|
|
rlc_amd_retx_t retx = {};
|
|
|
|
|
retx.is_segment = false;
|
|
|
|
|
retx.so_start = 0;
|
|
|
|
@ -544,9 +543,9 @@ bool rlc_am_lte::rlc_am_lte_tx::poll_required()
|
|
|
|
|
int rlc_am_lte::rlc_am_lte_tx::build_status_pdu(uint8_t* payload, uint32_t nof_bytes)
|
|
|
|
|
{
|
|
|
|
|
int pdu_len = parent->rx.get_status_pdu(&tx_status, nof_bytes);
|
|
|
|
|
log->debug("%s\n", rlc_am_status_pdu_to_string(&tx_status).c_str());
|
|
|
|
|
logger.debug("%s", rlc_am_status_pdu_to_string(&tx_status).c_str());
|
|
|
|
|
if (pdu_len > 0 && nof_bytes >= static_cast<uint32_t>(pdu_len)) {
|
|
|
|
|
log->info("%s Tx status PDU - %s\n", RB_NAME, rlc_am_status_pdu_to_string(&tx_status).c_str());
|
|
|
|
|
logger.info("%s Tx status PDU - %s", RB_NAME, rlc_am_status_pdu_to_string(&tx_status).c_str());
|
|
|
|
|
|
|
|
|
|
parent->rx.reset_status();
|
|
|
|
|
|
|
|
|
@ -557,7 +556,7 @@ int rlc_am_lte::rlc_am_lte_tx::build_status_pdu(uint8_t* payload, uint32_t nof_b
|
|
|
|
|
debug_state();
|
|
|
|
|
pdu_len = rlc_am_write_status_pdu(&tx_status, payload);
|
|
|
|
|
} else {
|
|
|
|
|
log->info("%s Cannot tx status PDU - %d bytes available, %d bytes required\n", RB_NAME, nof_bytes, pdu_len);
|
|
|
|
|
logger.info("%s Cannot tx status PDU - %d bytes available, %d bytes required", RB_NAME, nof_bytes, pdu_len);
|
|
|
|
|
pdu_len = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -568,7 +567,7 @@ int rlc_am_lte::rlc_am_lte_tx::build_retx_pdu(uint8_t* payload, uint32_t nof_byt
|
|
|
|
|
{
|
|
|
|
|
// Check there is at least 1 element before calling front()
|
|
|
|
|
if (retx_queue.empty()) {
|
|
|
|
|
log->error("In build_retx_pdu(): retx_queue is empty\n");
|
|
|
|
|
logger.error("In build_retx_pdu(): retx_queue is empty");
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -580,7 +579,7 @@ int rlc_am_lte::rlc_am_lte_tx::build_retx_pdu(uint8_t* payload, uint32_t nof_byt
|
|
|
|
|
if (!retx_queue.empty()) {
|
|
|
|
|
retx = retx_queue.front();
|
|
|
|
|
} else {
|
|
|
|
|
log->info("In build_retx_pdu(): retx_queue is empty during sanity check, sn=%d\n", retx.sn);
|
|
|
|
|
logger.info("In build_retx_pdu(): retx_queue is empty during sanity check, sn=%d", retx.sn);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -588,13 +587,13 @@ int rlc_am_lte::rlc_am_lte_tx::build_retx_pdu(uint8_t* payload, uint32_t nof_byt
|
|
|
|
|
// Is resegmentation needed?
|
|
|
|
|
int req_size = required_buffer_size(retx);
|
|
|
|
|
if (req_size < 0) {
|
|
|
|
|
log->error("In build_retx_pdu(): Removing retx.sn=%d from queue\n", retx.sn);
|
|
|
|
|
logger.error("In build_retx_pdu(): Removing retx.sn=%d from queue", retx.sn);
|
|
|
|
|
retx_queue.pop_front();
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (retx.is_segment || req_size > static_cast<int>(nof_bytes)) {
|
|
|
|
|
log->debug("%s build_retx_pdu - resegmentation required\n", RB_NAME);
|
|
|
|
|
logger.debug("%s build_retx_pdu - resegmentation required", RB_NAME);
|
|
|
|
|
return build_segment(payload, nof_bytes, retx);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -605,8 +604,8 @@ int rlc_am_lte::rlc_am_lte_tx::build_retx_pdu(uint8_t* payload, uint32_t nof_byt
|
|
|
|
|
// Set poll bit
|
|
|
|
|
pdu_without_poll++;
|
|
|
|
|
byte_without_poll += (tx_window[retx.sn].buf->N_bytes + rlc_am_packed_length(&new_header));
|
|
|
|
|
log->info("%s pdu_without_poll: %d\n", RB_NAME, pdu_without_poll);
|
|
|
|
|
log->info("%s byte_without_poll: %d\n", RB_NAME, byte_without_poll);
|
|
|
|
|
logger.info("%s pdu_without_poll: %d", RB_NAME, pdu_without_poll);
|
|
|
|
|
logger.info("%s byte_without_poll: %d", RB_NAME, byte_without_poll);
|
|
|
|
|
if (poll_required()) {
|
|
|
|
|
new_header.p = 1;
|
|
|
|
|
// vt_s won't change for reTx, so don't update poll_sn
|
|
|
|
@ -625,19 +624,19 @@ int rlc_am_lte::rlc_am_lte_tx::build_retx_pdu(uint8_t* payload, uint32_t nof_byt
|
|
|
|
|
retx_queue.pop_front();
|
|
|
|
|
tx_window[retx.sn].retx_count++;
|
|
|
|
|
if (tx_window[retx.sn].retx_count >= cfg.max_retx_thresh) {
|
|
|
|
|
log->warning("%s Signaling max number of reTx=%d for for SN=%d\n", RB_NAME, tx_window[retx.sn].retx_count, retx.sn);
|
|
|
|
|
logger.warning("%s Signaling max number of reTx=%d for for SN=%d", RB_NAME, tx_window[retx.sn].retx_count, retx.sn);
|
|
|
|
|
parent->rrc->max_retx_attempted();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log->info_hex(payload,
|
|
|
|
|
logger.info(payload,
|
|
|
|
|
tx_window[retx.sn].buf->N_bytes,
|
|
|
|
|
"%s Tx PDU SN=%d (%d B) (attempt %d/%d)\n",
|
|
|
|
|
"%s Tx PDU SN=%d (%d B) (attempt %d/%d)",
|
|
|
|
|
RB_NAME,
|
|
|
|
|
retx.sn,
|
|
|
|
|
tx_window[retx.sn].buf->N_bytes,
|
|
|
|
|
tx_window[retx.sn].retx_count + 1,
|
|
|
|
|
cfg.max_retx_thresh);
|
|
|
|
|
log->debug("%s\n", rlc_amd_pdu_header_to_string(new_header).c_str());
|
|
|
|
|
logger.debug("%s", rlc_amd_pdu_header_to_string(new_header).c_str());
|
|
|
|
|
|
|
|
|
|
debug_state();
|
|
|
|
|
return (ptr - payload) + tx_window[retx.sn].buf->N_bytes;
|
|
|
|
@ -646,7 +645,7 @@ int rlc_am_lte::rlc_am_lte_tx::build_retx_pdu(uint8_t* payload, uint32_t nof_byt
|
|
|
|
|
int rlc_am_lte::rlc_am_lte_tx::build_segment(uint8_t* payload, uint32_t nof_bytes, rlc_amd_retx_t retx)
|
|
|
|
|
{
|
|
|
|
|
if (tx_window[retx.sn].buf == NULL) {
|
|
|
|
|
log->error("In build_segment: retx.sn=%d has null buffer\n", retx.sn);
|
|
|
|
|
logger.error("In build_segment: retx.sn=%d has null buffer", retx.sn);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
if (!retx.is_segment) {
|
|
|
|
@ -660,8 +659,8 @@ int rlc_am_lte::rlc_am_lte_tx::build_segment(uint8_t* payload, uint32_t nof_byte
|
|
|
|
|
|
|
|
|
|
pdu_without_poll++;
|
|
|
|
|
byte_without_poll += (tx_window[retx.sn].buf->N_bytes + rlc_am_packed_length(&new_header));
|
|
|
|
|
log->info("%s pdu_without_poll: %d\n", RB_NAME, pdu_without_poll);
|
|
|
|
|
log->info("%s byte_without_poll: %d\n", RB_NAME, byte_without_poll);
|
|
|
|
|
logger.info("%s pdu_without_poll: %d", RB_NAME, pdu_without_poll);
|
|
|
|
|
logger.info("%s byte_without_poll: %d", RB_NAME, byte_without_poll);
|
|
|
|
|
|
|
|
|
|
new_header.dc = RLC_DC_FIELD_DATA_PDU;
|
|
|
|
|
new_header.rf = 1;
|
|
|
|
@ -672,7 +671,7 @@ int rlc_am_lte::rlc_am_lte_tx::build_segment(uint8_t* payload, uint32_t nof_byte
|
|
|
|
|
new_header.N_li = 0;
|
|
|
|
|
new_header.p = 0;
|
|
|
|
|
if (poll_required()) {
|
|
|
|
|
log->debug("%s setting poll bit to request status\n", RB_NAME);
|
|
|
|
|
logger.debug("%s setting poll bit to request status", RB_NAME);
|
|
|
|
|
new_header.p = 1;
|
|
|
|
|
// vt_s won't change for reTx, so don't update poll_sn
|
|
|
|
|
pdu_without_poll = 0;
|
|
|
|
@ -692,7 +691,7 @@ int rlc_am_lte::rlc_am_lte_tx::build_segment(uint8_t* payload, uint32_t nof_byte
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (nof_bytes <= head_len) {
|
|
|
|
|
log->info("%s Cannot build a PDU segment - %d bytes available, %d bytes required for header\n",
|
|
|
|
|
logger.info("%s Cannot build a PDU segment - %d bytes available, %d bytes required for header",
|
|
|
|
|
RB_NAME,
|
|
|
|
|
nof_bytes,
|
|
|
|
|
head_len);
|
|
|
|
@ -788,18 +787,18 @@ int rlc_am_lte::rlc_am_lte_tx::build_segment(uint8_t* payload, uint32_t nof_byte
|
|
|
|
|
debug_state();
|
|
|
|
|
int pdu_len = (ptr - payload) + len;
|
|
|
|
|
if (pdu_len > static_cast<int>(nof_bytes)) {
|
|
|
|
|
log->error("%s Retx PDU segment length error. Available: %d, Used: %d\n", RB_NAME, nof_bytes, pdu_len);
|
|
|
|
|
logger.error("%s Retx PDU segment length error. Available: %d, Used: %d", RB_NAME, nof_bytes, pdu_len);
|
|
|
|
|
int header_len = (ptr - payload);
|
|
|
|
|
log->debug("%s Retx PDU segment length error. Header len: %d, Payload len: %d, N_li: %d\n",
|
|
|
|
|
logger.debug("%s Retx PDU segment length error. Header len: %d, Payload len: %d, N_li: %d",
|
|
|
|
|
RB_NAME,
|
|
|
|
|
header_len,
|
|
|
|
|
len,
|
|
|
|
|
new_header.N_li);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log->info_hex(payload,
|
|
|
|
|
logger.info(payload,
|
|
|
|
|
pdu_len,
|
|
|
|
|
"%s Retx PDU segment SN=%d [so=%d] (%d B) (attempt %d/%d)\n",
|
|
|
|
|
"%s Retx PDU segment SN=%d [so=%d] (%d B) (attempt %d/%d)",
|
|
|
|
|
RB_NAME,
|
|
|
|
|
retx.sn,
|
|
|
|
|
retx.so_start,
|
|
|
|
@ -813,13 +812,13 @@ int rlc_am_lte::rlc_am_lte_tx::build_segment(uint8_t* payload, uint32_t nof_byte
|
|
|
|
|
int rlc_am_lte::rlc_am_lte_tx::build_data_pdu(uint8_t* payload, uint32_t nof_bytes)
|
|
|
|
|
{
|
|
|
|
|
if (tx_sdu == NULL && tx_sdu_queue.is_empty()) {
|
|
|
|
|
log->info("No data available to be sent\n");
|
|
|
|
|
logger.info("No data available to be sent");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// do not build any more PDU if window is already full
|
|
|
|
|
if (tx_sdu == NULL && tx_window.size() >= RLC_AM_WINDOW_SIZE) {
|
|
|
|
|
log->info("Tx window full.\n");
|
|
|
|
|
logger.info("Tx window full.");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -836,7 +835,7 @@ int rlc_am_lte::rlc_am_lte_tx::build_data_pdu(uint8_t* payload, uint32_t nof_byt
|
|
|
|
|
}
|
|
|
|
|
exit(-1);
|
|
|
|
|
#else
|
|
|
|
|
log->error("Fatal Error: Couldn't allocate PDU in build_data_pdu().\n");
|
|
|
|
|
logger.error("Fatal Error: Couldn't allocate PDU in build_data_pdu().");
|
|
|
|
|
return 0;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
@ -852,12 +851,12 @@ int rlc_am_lte::rlc_am_lte_tx::build_data_pdu(uint8_t* payload, uint32_t nof_byt
|
|
|
|
|
uint8_t* pdu_ptr = pdu->msg;
|
|
|
|
|
|
|
|
|
|
if (pdu_space <= head_len) {
|
|
|
|
|
log->info(
|
|
|
|
|
"%s Cannot build a PDU - %d bytes available, %d bytes required for header\n", RB_NAME, nof_bytes, head_len);
|
|
|
|
|
logger.info(
|
|
|
|
|
"%s Cannot build a PDU - %d bytes available, %d bytes required for header", RB_NAME, nof_bytes, head_len);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log->debug("%s Building PDU - pdu_space: %d, head_len: %d \n", RB_NAME, pdu_space, head_len);
|
|
|
|
|
logger.debug("%s Building PDU - pdu_space: %d, head_len: %d ", RB_NAME, pdu_space, head_len);
|
|
|
|
|
|
|
|
|
|
// Check for SDU segment
|
|
|
|
|
if (tx_sdu != NULL) {
|
|
|
|
@ -870,12 +869,12 @@ int rlc_am_lte::rlc_am_lte_tx::build_data_pdu(uint8_t* payload, uint32_t nof_byt
|
|
|
|
|
tx_sdu->msg += to_move;
|
|
|
|
|
auto info_it = undelivered_sdu_info_queue.find(tx_sdu->md.pdcp_sn);
|
|
|
|
|
if (info_it == undelivered_sdu_info_queue.end()) {
|
|
|
|
|
log->error("Could not find PDCP SN in SDU info queue (segment). PDCP_SN=%d\n", tx_sdu->md.pdcp_sn);
|
|
|
|
|
logger.error("Could not find PDCP SN in SDU info queue (segment). PDCP_SN=%d", tx_sdu->md.pdcp_sn);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
undelivered_sdu_info_queue.at(tx_sdu->md.pdcp_sn).rlc_sn_info_list.push_back({header.sn, false});
|
|
|
|
|
if (tx_sdu->N_bytes == 0) {
|
|
|
|
|
log->debug("%s Complete SDU scheduled for tx.\n", RB_NAME);
|
|
|
|
|
logger.debug("%s Complete SDU scheduled for tx.", RB_NAME);
|
|
|
|
|
undelivered_sdu_info_queue[tx_sdu->md.pdcp_sn].fully_txed = true;
|
|
|
|
|
tx_sdu.reset();
|
|
|
|
|
}
|
|
|
|
@ -886,7 +885,7 @@ int rlc_am_lte::rlc_am_lte_tx::build_data_pdu(uint8_t* payload, uint32_t nof_byt
|
|
|
|
|
}
|
|
|
|
|
header.fi |= RLC_FI_FIELD_NOT_START_ALIGNED; // First byte does not correspond to first byte of SDU
|
|
|
|
|
|
|
|
|
|
log->debug("%s Building PDU - added SDU segment (len:%d) - pdu_space: %d, head_len: %d \n",
|
|
|
|
|
logger.debug("%s Building PDU - added SDU segment (len:%d) - pdu_space: %d, head_len: %d ",
|
|
|
|
|
RB_NAME,
|
|
|
|
|
to_move,
|
|
|
|
|
pdu_space,
|
|
|
|
@ -916,12 +915,12 @@ int rlc_am_lte::rlc_am_lte_tx::build_data_pdu(uint8_t* payload, uint32_t nof_byt
|
|
|
|
|
tx_sdu->msg += to_move;
|
|
|
|
|
auto info_it = undelivered_sdu_info_queue.find(tx_sdu->md.pdcp_sn);
|
|
|
|
|
if (info_it == undelivered_sdu_info_queue.end()) {
|
|
|
|
|
log->error("Could not find PDCP SN in SDU info queue. PDCP_SN=%d\n", tx_sdu->md.pdcp_sn);
|
|
|
|
|
logger.error("Could not find PDCP SN in SDU info queue. PDCP_SN=%d", tx_sdu->md.pdcp_sn);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
info_it->second.rlc_sn_info_list.push_back({header.sn, false});
|
|
|
|
|
if (tx_sdu->N_bytes == 0) {
|
|
|
|
|
log->debug("%s Complete SDU scheduled for tx. PDCP SN=%d\n", RB_NAME, tx_sdu->md.pdcp_sn);
|
|
|
|
|
logger.debug("%s Complete SDU scheduled for tx. PDCP SN=%d", RB_NAME, tx_sdu->md.pdcp_sn);
|
|
|
|
|
undelivered_sdu_info_queue[tx_sdu->md.pdcp_sn].fully_txed = true;
|
|
|
|
|
tx_sdu.reset();
|
|
|
|
|
}
|
|
|
|
@ -931,7 +930,7 @@ int rlc_am_lte::rlc_am_lte_tx::build_data_pdu(uint8_t* payload, uint32_t nof_byt
|
|
|
|
|
pdu_space = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log->debug("%s Building PDU - added SDU segment (len:%d) - pdu_space: %d, head_len: %d \n",
|
|
|
|
|
logger.debug("%s Building PDU - added SDU segment (len:%d) - pdu_space: %d, head_len: %d ",
|
|
|
|
|
RB_NAME,
|
|
|
|
|
to_move,
|
|
|
|
|
pdu_space,
|
|
|
|
@ -940,7 +939,7 @@ int rlc_am_lte::rlc_am_lte_tx::build_data_pdu(uint8_t* payload, uint32_t nof_byt
|
|
|
|
|
|
|
|
|
|
// Make sure, at least one SDU (segment) has been added until this point
|
|
|
|
|
if (pdu->N_bytes == 0) {
|
|
|
|
|
log->error("Generated empty RLC PDU.\n");
|
|
|
|
|
logger.error("Generated empty RLC PDU.");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -951,10 +950,10 @@ int rlc_am_lte::rlc_am_lte_tx::build_data_pdu(uint8_t* payload, uint32_t nof_byt
|
|
|
|
|
// Set Poll bit
|
|
|
|
|
pdu_without_poll++;
|
|
|
|
|
byte_without_poll += (pdu->N_bytes + head_len);
|
|
|
|
|
log->debug("%s pdu_without_poll: %d\n", RB_NAME, pdu_without_poll);
|
|
|
|
|
log->debug("%s byte_without_poll: %d\n", RB_NAME, byte_without_poll);
|
|
|
|
|
logger.debug("%s pdu_without_poll: %d", RB_NAME, pdu_without_poll);
|
|
|
|
|
logger.debug("%s byte_without_poll: %d", RB_NAME, byte_without_poll);
|
|
|
|
|
if (poll_required()) {
|
|
|
|
|
log->debug("%s setting poll bit to request status\n", RB_NAME);
|
|
|
|
|
logger.debug("%s setting poll bit to request status", RB_NAME);
|
|
|
|
|
header.p = 1;
|
|
|
|
|
poll_sn = vt_s;
|
|
|
|
|
pdu_without_poll = 0;
|
|
|
|
@ -979,8 +978,8 @@ int rlc_am_lte::rlc_am_lte_tx::build_data_pdu(uint8_t* payload, uint32_t nof_byt
|
|
|
|
|
rlc_am_write_data_pdu_header(&header, &ptr);
|
|
|
|
|
memcpy(ptr, buffer_ptr->msg, buffer_ptr->N_bytes);
|
|
|
|
|
int total_len = (ptr - payload) + buffer_ptr->N_bytes;
|
|
|
|
|
log->info_hex(payload, total_len, "%s Tx PDU SN=%d (%d B)\n", RB_NAME, header.sn, total_len);
|
|
|
|
|
log->debug("%s\n", rlc_amd_pdu_header_to_string(header).c_str());
|
|
|
|
|
logger.info(payload, total_len, "%s Tx PDU SN=%d (%d B)", RB_NAME, header.sn, total_len);
|
|
|
|
|
logger.debug("%s", rlc_amd_pdu_header_to_string(header).c_str());
|
|
|
|
|
debug_state();
|
|
|
|
|
|
|
|
|
|
return total_len;
|
|
|
|
@ -994,17 +993,17 @@ void rlc_am_lte::rlc_am_lte_tx::handle_control_pdu(uint8_t* payload, uint32_t no
|
|
|
|
|
|
|
|
|
|
pthread_mutex_lock(&mutex);
|
|
|
|
|
|
|
|
|
|
log->info_hex(payload, nof_bytes, "%s Rx control PDU", RB_NAME);
|
|
|
|
|
logger.info(payload, nof_bytes, "%s Rx control PDU", RB_NAME);
|
|
|
|
|
|
|
|
|
|
rlc_status_pdu_t status;
|
|
|
|
|
rlc_am_read_status_pdu(payload, nof_bytes, &status);
|
|
|
|
|
|
|
|
|
|
log->info("%s Rx Status PDU: %s\n", RB_NAME, rlc_am_status_pdu_to_string(&status).c_str());
|
|
|
|
|
logger.info("%s Rx Status PDU: %s", RB_NAME, rlc_am_status_pdu_to_string(&status).c_str());
|
|
|
|
|
|
|
|
|
|
// Sec 5.2.2.2, stop poll reTx timer if status PDU comprises a positive _or_ negative acknowledgement
|
|
|
|
|
// for the RLC data PDU with sequence number poll_sn
|
|
|
|
|
if (poll_retx_timer.is_valid() && (TX_MOD_BASE(poll_sn) < TX_MOD_BASE(status.ack_sn))) {
|
|
|
|
|
log->debug("%s Stopping pollRetx timer\n", RB_NAME);
|
|
|
|
|
logger.debug("%s Stopping pollRetx timer", RB_NAME);
|
|
|
|
|
poll_retx_timer.stop();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1038,7 +1037,7 @@ void rlc_am_lte::rlc_am_lte_tx::handle_control_pdu(uint8_t* payload, uint32_t no
|
|
|
|
|
// sanity check
|
|
|
|
|
if (status.nacks[j].so_start >= it->second.buf->N_bytes) {
|
|
|
|
|
// print error but try to send original PDU again
|
|
|
|
|
log->info("SO_start is larger than original PDU (%d >= %d)\n",
|
|
|
|
|
logger.info("SO_start is larger than original PDU (%d >= %d)",
|
|
|
|
|
status.nacks[j].so_start,
|
|
|
|
|
it->second.buf->N_bytes);
|
|
|
|
|
status.nacks[j].so_start = 0;
|
|
|
|
@ -1056,7 +1055,7 @@ void rlc_am_lte::rlc_am_lte_tx::handle_control_pdu(uint8_t* payload, uint32_t no
|
|
|
|
|
retx.is_segment = true;
|
|
|
|
|
retx.so_start = status.nacks[j].so_start;
|
|
|
|
|
} else {
|
|
|
|
|
log->warning("%s invalid segment NACK received for SN %d. so_start: %d, so_end: %d, N_bytes: %d\n",
|
|
|
|
|
logger.warning("%s invalid segment NACK received for SN %d. so_start: %d, so_end: %d, N_bytes: %d",
|
|
|
|
|
RB_NAME,
|
|
|
|
|
i,
|
|
|
|
|
status.nacks[j].so_start,
|
|
|
|
@ -1092,10 +1091,10 @@ void rlc_am_lte::rlc_am_lte_tx::handle_control_pdu(uint8_t* payload, uint32_t no
|
|
|
|
|
|
|
|
|
|
// Remove all SDUs that were fully acked
|
|
|
|
|
for (uint32_t acked_pdcp_sn : notify_info_vec) {
|
|
|
|
|
log->debug("Erasing SDU info: PDCP_SN=%d\n", acked_pdcp_sn);
|
|
|
|
|
logger.debug("Erasing SDU info: PDCP_SN=%d", acked_pdcp_sn);
|
|
|
|
|
size_t erased = undelivered_sdu_info_queue.erase(acked_pdcp_sn);
|
|
|
|
|
if (erased == 0) {
|
|
|
|
|
log->error("Could not find info to erase: SN=%d\n", acked_pdcp_sn);
|
|
|
|
|
logger.error("Could not find info to erase: SN=%d", acked_pdcp_sn);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -1113,7 +1112,7 @@ void rlc_am_lte::rlc_am_lte_tx::handle_control_pdu(uint8_t* payload, uint32_t no
|
|
|
|
|
void rlc_am_lte::rlc_am_lte_tx::update_notification_ack_info(const rlc_amd_tx_pdu_t& tx_pdu,
|
|
|
|
|
std::vector<uint32_t>& notify_info_vec)
|
|
|
|
|
{
|
|
|
|
|
log->debug("Updating ACK info: RLC SN=%d, number of notified SDU=%ld, number of undelivered SDUs=%ld",
|
|
|
|
|
logger.debug("Updating ACK info: RLC SN=%d, number of notified SDU=%ld, number of undelivered SDUs=%ld",
|
|
|
|
|
tx_pdu.header.sn,
|
|
|
|
|
notify_info_vec.size(),
|
|
|
|
|
undelivered_sdu_info_queue.size());
|
|
|
|
@ -1143,7 +1142,7 @@ void rlc_am_lte::rlc_am_lte_tx::update_notification_ack_info(const rlc_amd_tx_pd
|
|
|
|
|
|
|
|
|
|
void rlc_am_lte::rlc_am_lte_tx::debug_state()
|
|
|
|
|
{
|
|
|
|
|
log->debug("%s vt_a = %d, vt_ms = %d, vt_s = %d, poll_sn = %d\n", RB_NAME, vt_a, vt_ms, vt_s, poll_sn);
|
|
|
|
|
logger.debug("%s vt_a = %d, vt_ms = %d, vt_s = %d, poll_sn = %d", RB_NAME, vt_a, vt_ms, vt_s, poll_sn);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int rlc_am_lte::rlc_am_lte_tx::required_buffer_size(rlc_amd_retx_t retx)
|
|
|
|
@ -1153,11 +1152,11 @@ int rlc_am_lte::rlc_am_lte_tx::required_buffer_size(rlc_amd_retx_t retx)
|
|
|
|
|
if (tx_window[retx.sn].buf) {
|
|
|
|
|
return rlc_am_packed_length(&tx_window[retx.sn].header) + tx_window[retx.sn].buf->N_bytes;
|
|
|
|
|
} else {
|
|
|
|
|
log->warning("retx.sn=%d has null ptr in required_buffer_size()\n", retx.sn);
|
|
|
|
|
logger.warning("retx.sn=%d has null ptr in required_buffer_size()", retx.sn);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
log->warning("retx.sn=%d does not exist in required_buffer_size()\n", retx.sn);
|
|
|
|
|
logger.warning("retx.sn=%d does not exist in required_buffer_size()", retx.sn);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -1237,7 +1236,7 @@ bool rlc_am_lte::rlc_am_lte_tx::retx_queue_has_sn(uint32_t sn)
|
|
|
|
|
rlc_am_lte::rlc_am_lte_rx::rlc_am_lte_rx(rlc_am_lte* parent_) :
|
|
|
|
|
parent(parent_),
|
|
|
|
|
pool(byte_buffer_pool::get_instance()),
|
|
|
|
|
log(parent_->log),
|
|
|
|
|
logger(parent_->logger),
|
|
|
|
|
reordering_timer(parent_->timers->get_unique_timer())
|
|
|
|
|
{
|
|
|
|
|
pthread_mutex_init(&mutex, NULL);
|
|
|
|
@ -1255,7 +1254,7 @@ bool rlc_am_lte::rlc_am_lte_rx::configure(rlc_am_config_t cfg_)
|
|
|
|
|
|
|
|
|
|
// check timers
|
|
|
|
|
if (not reordering_timer.is_valid()) {
|
|
|
|
|
log->error("Configuring RLC AM TX: timers not configured\n");
|
|
|
|
|
logger.error("Configuring RLC AM TX: timers not configured");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1310,8 +1309,8 @@ void rlc_am_lte::rlc_am_lte_rx::handle_data_pdu(uint8_t* payload, uint32_t nof_b
|
|
|
|
|
{
|
|
|
|
|
std::map<uint32_t, rlc_amd_rx_pdu_t>::iterator it;
|
|
|
|
|
|
|
|
|
|
log->info_hex(payload, nof_bytes, "%s Rx data PDU SN=%d (%d B)", RB_NAME, header.sn, nof_bytes);
|
|
|
|
|
log->debug("%s\n", rlc_amd_pdu_header_to_string(header).c_str());
|
|
|
|
|
logger.info(payload, nof_bytes, "%s Rx data PDU SN=%d (%d B)", RB_NAME, header.sn, nof_bytes);
|
|
|
|
|
logger.debug("%s", rlc_amd_pdu_header_to_string(header).c_str());
|
|
|
|
|
|
|
|
|
|
// sanity check for segments not exceeding PDU length
|
|
|
|
|
if (header.N_li > 0) {
|
|
|
|
@ -1319,7 +1318,7 @@ void rlc_am_lte::rlc_am_lte_rx::handle_data_pdu(uint8_t* payload, uint32_t nof_b
|
|
|
|
|
for (uint32_t i = 0; i < header.N_li; i++) {
|
|
|
|
|
segments_len += header.li[i];
|
|
|
|
|
if (segments_len > nof_bytes) {
|
|
|
|
|
log->info("Dropping corrupted PDU (segments_len=%d > pdu_len=%d)\n", segments_len, nof_bytes);
|
|
|
|
|
logger.info("Dropping corrupted PDU (segments_len=%d > pdu_len=%d)", segments_len, nof_bytes);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -1327,20 +1326,20 @@ void rlc_am_lte::rlc_am_lte_rx::handle_data_pdu(uint8_t* payload, uint32_t nof_b
|
|
|
|
|
|
|
|
|
|
if (!inside_rx_window(header.sn)) {
|
|
|
|
|
if (header.p) {
|
|
|
|
|
log->info("%s Status packet requested through polling bit\n", RB_NAME);
|
|
|
|
|
logger.info("%s Status packet requested through polling bit", RB_NAME);
|
|
|
|
|
do_status = true;
|
|
|
|
|
}
|
|
|
|
|
log->info("%s SN=%d outside rx window [%d:%d] - discarding\n", RB_NAME, header.sn, vr_r, vr_mr);
|
|
|
|
|
logger.info("%s SN=%d outside rx window [%d:%d] - discarding", RB_NAME, header.sn, vr_r, vr_mr);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
it = rx_window.find(header.sn);
|
|
|
|
|
if (rx_window.end() != it) {
|
|
|
|
|
if (header.p) {
|
|
|
|
|
log->info("%s Status packet requested through polling bit\n", RB_NAME);
|
|
|
|
|
logger.info("%s Status packet requested through polling bit", RB_NAME);
|
|
|
|
|
do_status = true;
|
|
|
|
|
}
|
|
|
|
|
log->info("%s Discarding duplicate SN=%d\n", RB_NAME, header.sn);
|
|
|
|
|
logger.info("%s Discarding duplicate SN=%d", RB_NAME, header.sn);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1352,7 +1351,7 @@ void rlc_am_lte::rlc_am_lte_rx::handle_data_pdu(uint8_t* payload, uint32_t nof_b
|
|
|
|
|
srslte::console("Fatal Error: Couldn't allocate PDU in handle_data_pdu().\n");
|
|
|
|
|
exit(-1);
|
|
|
|
|
#else
|
|
|
|
|
log->error("Fatal Error: Couldn't allocate PDU in handle_data_pdu().\n");
|
|
|
|
|
logger.error("Fatal Error: Couldn't allocate PDU in handle_data_pdu().");
|
|
|
|
|
return;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
@ -1360,7 +1359,7 @@ void rlc_am_lte::rlc_am_lte_rx::handle_data_pdu(uint8_t* payload, uint32_t nof_b
|
|
|
|
|
|
|
|
|
|
// check available space for payload
|
|
|
|
|
if (nof_bytes > pdu.buf->get_tailroom()) {
|
|
|
|
|
log->error("%s Discarding SN=%d of size %d B (available space %d B)\n",
|
|
|
|
|
logger.error("%s Discarding SN=%d of size %d B (available space %d B)",
|
|
|
|
|
RB_NAME,
|
|
|
|
|
header.sn,
|
|
|
|
|
nof_bytes,
|
|
|
|
@ -1387,7 +1386,7 @@ void rlc_am_lte::rlc_am_lte_rx::handle_data_pdu(uint8_t* payload, uint32_t nof_b
|
|
|
|
|
|
|
|
|
|
// Check poll bit
|
|
|
|
|
if (header.p) {
|
|
|
|
|
log->info("%s Status packet requested through polling bit\n", RB_NAME);
|
|
|
|
|
logger.info("%s Status packet requested through polling bit", RB_NAME);
|
|
|
|
|
poll_received = true;
|
|
|
|
|
|
|
|
|
|
// 36.322 v10 Section 5.2.3
|
|
|
|
@ -1404,21 +1403,21 @@ void rlc_am_lte::rlc_am_lte_rx::handle_data_pdu(uint8_t* payload, uint32_t nof_b
|
|
|
|
|
if (reordering_timer.is_valid()) {
|
|
|
|
|
if (reordering_timer.is_running()) {
|
|
|
|
|
if (vr_x == vr_r || (!inside_rx_window(vr_x) && vr_x != vr_mr)) {
|
|
|
|
|
log->debug("Stopping reordering timer.\n");
|
|
|
|
|
logger.debug("Stopping reordering timer.");
|
|
|
|
|
reordering_timer.stop();
|
|
|
|
|
} else {
|
|
|
|
|
log->debug("Leave reordering timer running.\n");
|
|
|
|
|
logger.debug("Leave reordering timer running.");
|
|
|
|
|
}
|
|
|
|
|
debug_state();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (not reordering_timer.is_running()) {
|
|
|
|
|
if (RX_MOD_BASE(vr_h) > RX_MOD_BASE(vr_r)) {
|
|
|
|
|
log->debug("Starting reordering timer.\n");
|
|
|
|
|
logger.debug("Starting reordering timer.");
|
|
|
|
|
reordering_timer.run();
|
|
|
|
|
vr_x = vr_h;
|
|
|
|
|
} else {
|
|
|
|
|
log->debug("Leave reordering timer stopped.\n");
|
|
|
|
|
logger.debug("Leave reordering timer stopped.");
|
|
|
|
|
}
|
|
|
|
|
debug_state();
|
|
|
|
|
}
|
|
|
|
@ -1433,7 +1432,7 @@ void rlc_am_lte::rlc_am_lte_rx::handle_data_pdu_segment(uint8_t* pa
|
|
|
|
|
{
|
|
|
|
|
std::map<uint32_t, rlc_amd_rx_pdu_segments_t>::iterator it;
|
|
|
|
|
|
|
|
|
|
log->info_hex(payload,
|
|
|
|
|
logger.info(payload,
|
|
|
|
|
nof_bytes,
|
|
|
|
|
"%s Rx data PDU segment of SN=%d (%d B), SO=%d, N_li=%d",
|
|
|
|
|
RB_NAME,
|
|
|
|
@ -1441,15 +1440,15 @@ void rlc_am_lte::rlc_am_lte_rx::handle_data_pdu_segment(uint8_t* pa
|
|
|
|
|
nof_bytes,
|
|
|
|
|
header.so,
|
|
|
|
|
header.N_li);
|
|
|
|
|
log->debug("%s\n", rlc_amd_pdu_header_to_string(header).c_str());
|
|
|
|
|
logger.debug("%s", rlc_amd_pdu_header_to_string(header).c_str());
|
|
|
|
|
|
|
|
|
|
// Check inside rx window
|
|
|
|
|
if (!inside_rx_window(header.sn)) {
|
|
|
|
|
if (header.p) {
|
|
|
|
|
log->info("%s Status packet requested through polling bit\n", RB_NAME);
|
|
|
|
|
logger.info("%s Status packet requested through polling bit", RB_NAME);
|
|
|
|
|
do_status = true;
|
|
|
|
|
}
|
|
|
|
|
log->info("%s SN=%d outside rx window [%d:%d] - discarding\n", RB_NAME, header.sn, vr_r, vr_mr);
|
|
|
|
|
logger.info("%s SN=%d outside rx window [%d:%d] - discarding", RB_NAME, header.sn, vr_r, vr_mr);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1460,13 +1459,13 @@ void rlc_am_lte::rlc_am_lte_rx::handle_data_pdu_segment(uint8_t* pa
|
|
|
|
|
srslte::console("Fatal Error: Couldn't allocate PDU in handle_data_pdu_segment().\n");
|
|
|
|
|
exit(-1);
|
|
|
|
|
#else
|
|
|
|
|
log->error("Fatal Error: Couldn't allocate PDU in handle_data_pdu_segment().\n");
|
|
|
|
|
logger.error("Fatal Error: Couldn't allocate PDU in handle_data_pdu_segment().");
|
|
|
|
|
return;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (segment.buf->get_tailroom() < nof_bytes) {
|
|
|
|
|
log->info("Dropping corrupted segment SN=%d, not enough space to fit %d B\n", header.sn, nof_bytes);
|
|
|
|
|
logger.info("Dropping corrupted segment SN=%d, not enough space to fit %d B", header.sn, nof_bytes);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1478,7 +1477,7 @@ void rlc_am_lte::rlc_am_lte_rx::handle_data_pdu_segment(uint8_t* pa
|
|
|
|
|
it = rx_segments.find(header.sn);
|
|
|
|
|
if (rx_segments.end() != it) {
|
|
|
|
|
if (header.p) {
|
|
|
|
|
log->info("%s Status packet requested through polling bit\n", RB_NAME);
|
|
|
|
|
logger.info("%s Status packet requested through polling bit", RB_NAME);
|
|
|
|
|
do_status = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1501,7 +1500,7 @@ void rlc_am_lte::rlc_am_lte_rx::handle_data_pdu_segment(uint8_t* pa
|
|
|
|
|
|
|
|
|
|
// Check poll bit
|
|
|
|
|
if (header.p) {
|
|
|
|
|
log->info("%s Status packet requested through polling bit\n", RB_NAME);
|
|
|
|
|
logger.info("%s Status packet requested through polling bit", RB_NAME);
|
|
|
|
|
poll_received = true;
|
|
|
|
|
|
|
|
|
|
// 36.322 v10 Section 5.2.3
|
|
|
|
@ -1527,7 +1526,7 @@ void rlc_am_lte::rlc_am_lte_rx::reassemble_rx_sdus()
|
|
|
|
|
srslte::console("Fatal Error: Could not allocate PDU in reassemble_rx_sdus() (1)\n");
|
|
|
|
|
exit(-1);
|
|
|
|
|
#else
|
|
|
|
|
log->error("Fatal Error: Could not allocate PDU in reassemble_rx_sdus() (1)\n");
|
|
|
|
|
logger.error("Fatal Error: Could not allocate PDU in reassemble_rx_sdus() (1)");
|
|
|
|
|
return;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
@ -1539,9 +1538,9 @@ void rlc_am_lte::rlc_am_lte_rx::reassemble_rx_sdus()
|
|
|
|
|
for (uint32_t i = 0; i < rx_window[vr_r].header.N_li; i++) {
|
|
|
|
|
len = rx_window[vr_r].header.li[i];
|
|
|
|
|
|
|
|
|
|
log->debug_hex(rx_window[vr_r].buf->msg,
|
|
|
|
|
logger.debug(rx_window[vr_r].buf->msg,
|
|
|
|
|
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,
|
|
|
|
|
rx_window[vr_r].header.N_li,
|
|
|
|
|
len,
|
|
|
|
@ -1555,7 +1554,7 @@ void rlc_am_lte::rlc_am_lte_rx::reassemble_rx_sdus()
|
|
|
|
|
if (rx_sdu->get_tailroom() >= len) {
|
|
|
|
|
if ((rx_window[vr_r].buf->msg - rx_window[vr_r].buf->buffer) + len < SRSLTE_MAX_BUFFER_SIZE_BYTES) {
|
|
|
|
|
if (rx_window[vr_r].buf->N_bytes < len) {
|
|
|
|
|
log->error("Dropping corrupted SN=%d\n", vr_r);
|
|
|
|
|
logger.error("Dropping corrupted SN=%d", vr_r);
|
|
|
|
|
rx_sdu.reset();
|
|
|
|
|
goto exit;
|
|
|
|
|
}
|
|
|
|
@ -1569,7 +1568,7 @@ void rlc_am_lte::rlc_am_lte_rx::reassemble_rx_sdus()
|
|
|
|
|
rx_window[vr_r].buf->msg += len;
|
|
|
|
|
rx_window[vr_r].buf->N_bytes -= len;
|
|
|
|
|
|
|
|
|
|
log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU (%d B)", RB_NAME, rx_sdu->N_bytes);
|
|
|
|
|
logger.info(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU (%d B)", RB_NAME, rx_sdu->N_bytes);
|
|
|
|
|
sdu_rx_latency_ms.push(std::chrono::duration_cast<std::chrono::milliseconds>(
|
|
|
|
|
std::chrono::high_resolution_clock::now() - rx_sdu->get_timestamp())
|
|
|
|
|
.count());
|
|
|
|
@ -1582,18 +1581,18 @@ void rlc_am_lte::rlc_am_lte_rx::reassemble_rx_sdus()
|
|
|
|
|
srslte::console("Fatal Error: Could not allocate PDU in reassemble_rx_sdus() (2)\n");
|
|
|
|
|
exit(-1);
|
|
|
|
|
#else
|
|
|
|
|
log->error("Fatal Error: Could not allocate PDU in reassemble_rx_sdus() (2)\n");
|
|
|
|
|
logger.error("Fatal Error: Could not allocate PDU in reassemble_rx_sdus() (2)");
|
|
|
|
|
return;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
int buf_len = rx_window[vr_r].buf->msg - rx_window[vr_r].buf->buffer;
|
|
|
|
|
log->error("Cannot read %d bytes from rx_window. vr_r=%d, msg-buffer=%d B\n", len, vr_r, buf_len);
|
|
|
|
|
logger.error("Cannot read %d bytes from rx_window. vr_r=%d, msg-buffer=%d B", len, vr_r, buf_len);
|
|
|
|
|
rx_sdu.reset();
|
|
|
|
|
goto exit;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
log->error("Cannot fit RLC PDU in SDU buffer, dropping both.\n");
|
|
|
|
|
logger.error("Cannot fit RLC PDU in SDU buffer, dropping both.");
|
|
|
|
|
rx_sdu.reset();
|
|
|
|
|
goto exit;
|
|
|
|
|
}
|
|
|
|
@ -1601,7 +1600,7 @@ void rlc_am_lte::rlc_am_lte_rx::reassemble_rx_sdus()
|
|
|
|
|
|
|
|
|
|
// Handle last segment
|
|
|
|
|
len = rx_window[vr_r].buf->N_bytes;
|
|
|
|
|
log->debug_hex(rx_window[vr_r].buf->msg, len, "Handling last segment of length %d B of SN=%d\n", len, vr_r);
|
|
|
|
|
logger.debug(rx_window[vr_r].buf->msg, len, "Handling last segment of length %d B of SN=%d", len, vr_r);
|
|
|
|
|
if (rx_sdu->get_tailroom() >= len) {
|
|
|
|
|
// store timestamp of the first segment when starting to assemble SDUs
|
|
|
|
|
if (rx_sdu->N_bytes == 0) {
|
|
|
|
@ -1619,7 +1618,7 @@ void rlc_am_lte::rlc_am_lte_rx::reassemble_rx_sdus()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (rlc_am_end_aligned(rx_window[vr_r].header.fi)) {
|
|
|
|
|
log->info_hex(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU (%d B)", RB_NAME, rx_sdu->N_bytes);
|
|
|
|
|
logger.info(rx_sdu->msg, rx_sdu->N_bytes, "%s Rx SDU (%d B)", RB_NAME, rx_sdu->N_bytes);
|
|
|
|
|
sdu_rx_latency_ms.push(std::chrono::duration_cast<std::chrono::milliseconds>(
|
|
|
|
|
std::chrono::high_resolution_clock::now() - rx_sdu->get_timestamp())
|
|
|
|
|
.count());
|
|
|
|
@ -1632,7 +1631,7 @@ void rlc_am_lte::rlc_am_lte_rx::reassemble_rx_sdus()
|
|
|
|
|
srslte::console("Fatal Error: Could not allocate PDU in reassemble_rx_sdus() (3)\n");
|
|
|
|
|
exit(-1);
|
|
|
|
|
#else
|
|
|
|
|
log->error("Fatal Error: Could not allocate PDU in reassemble_rx_sdus() (3)\n");
|
|
|
|
|
logger.error("Fatal Error: Could not allocate PDU in reassemble_rx_sdus() (3)");
|
|
|
|
|
return;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
@ -1640,15 +1639,15 @@ void rlc_am_lte::rlc_am_lte_rx::reassemble_rx_sdus()
|
|
|
|
|
|
|
|
|
|
exit:
|
|
|
|
|
// Move the rx_window
|
|
|
|
|
log->debug("Erasing SN=%d.\n", vr_r);
|
|
|
|
|
logger.debug("Erasing SN=%d.", vr_r);
|
|
|
|
|
// also erase any segments of this SN
|
|
|
|
|
std::map<uint32_t, rlc_amd_rx_pdu_segments_t>::iterator it;
|
|
|
|
|
it = rx_segments.find(vr_r);
|
|
|
|
|
if (rx_segments.end() != it) {
|
|
|
|
|
log->debug("Erasing segments of SN=%d\n", vr_r);
|
|
|
|
|
logger.debug("Erasing segments of SN=%d", vr_r);
|
|
|
|
|
std::list<rlc_amd_rx_pdu_t>::iterator segit;
|
|
|
|
|
for (segit = it->second.segments.begin(); segit != it->second.segments.end(); ++segit) {
|
|
|
|
|
log->debug(" Erasing segment of SN=%d SO=%d Len=%d N_li=%d\n",
|
|
|
|
|
logger.debug(" Erasing segment of SN=%d SO=%d Len=%d N_li=%d",
|
|
|
|
|
segit->header.sn,
|
|
|
|
|
segit->header.so,
|
|
|
|
|
segit->buf->N_bytes,
|
|
|
|
@ -1691,7 +1690,7 @@ void rlc_am_lte::rlc_am_lte_rx::write_pdu(uint8_t* payload, const uint32_t nof_b
|
|
|
|
|
uint32_t payload_len = nof_bytes;
|
|
|
|
|
rlc_am_read_data_pdu_header(&payload, &payload_len, &header);
|
|
|
|
|
if (payload_len > nof_bytes) {
|
|
|
|
|
log->info("Dropping corrupted PDU (%d B). Remaining length after header %d B.\n", nof_bytes, payload_len);
|
|
|
|
|
logger.info("Dropping corrupted PDU (%d B). Remaining length after header %d B.", nof_bytes, payload_len);
|
|
|
|
|
pthread_mutex_unlock(&mutex);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
@ -1733,7 +1732,7 @@ void rlc_am_lte::rlc_am_lte_rx::timer_expired(uint32_t timeout_id)
|
|
|
|
|
{
|
|
|
|
|
pthread_mutex_lock(&mutex);
|
|
|
|
|
if (reordering_timer.is_valid() and reordering_timer.id() == timeout_id) {
|
|
|
|
|
log->debug("%s reordering timeout expiry - updating vr_ms (was %d)\n", RB_NAME, vr_ms);
|
|
|
|
|
logger.debug("%s reordering timeout expiry - updating vr_ms (was %d)", RB_NAME, vr_ms);
|
|
|
|
|
|
|
|
|
|
// 36.322 v10 Section 5.1.3.2.4
|
|
|
|
|
vr_ms = vr_x;
|
|
|
|
@ -1777,18 +1776,18 @@ int rlc_am_lte::rlc_am_lte_rx::get_status_pdu(rlc_status_pdu_t* status, const ui
|
|
|
|
|
|
|
|
|
|
// make sure we don't exceed grant size
|
|
|
|
|
if (rlc_am_packed_length(status) > max_pdu_size) {
|
|
|
|
|
log->debug("Status PDU too big (%d > %d)\n", rlc_am_packed_length(status), max_pdu_size);
|
|
|
|
|
logger.debug("Status PDU too big (%d > %d)", rlc_am_packed_length(status), max_pdu_size);
|
|
|
|
|
if (status->N_nack >= 1 && status->N_nack < RLC_AM_WINDOW_SIZE) {
|
|
|
|
|
log->debug("Removing last NACK SN=%d\n", status->nacks[status->N_nack].nack_sn);
|
|
|
|
|
logger.debug("Removing last NACK SN=%d", status->nacks[status->N_nack].nack_sn);
|
|
|
|
|
status->N_nack--;
|
|
|
|
|
// make sure we don't have the current ACK_SN in the NACK list
|
|
|
|
|
if (rlc_am_is_valid_status_pdu(*status) == false) {
|
|
|
|
|
// No space to send any NACKs
|
|
|
|
|
log->debug("Resetting N_nack to zero\n");
|
|
|
|
|
logger.debug("Resetting N_nack to zero");
|
|
|
|
|
status->N_nack = 0;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
log->warning("Failed to generate small enough status PDU (packed_len=%d, max_pdu_size=%d, status->N_nack=%d)\n",
|
|
|
|
|
logger.warning("Failed to generate small enough status PDU (packed_len=%d, max_pdu_size=%d, status->N_nack=%d)",
|
|
|
|
|
rlc_am_packed_length(status),
|
|
|
|
|
max_pdu_size,
|
|
|
|
|
status->N_nack);
|
|
|
|
@ -1831,7 +1830,7 @@ void rlc_am_lte::rlc_am_lte_rx::print_rx_segments()
|
|
|
|
|
<< " N_li: " << segit->header.N_li << std::endl;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
log->debug("%s\n", ss.str().c_str());
|
|
|
|
|
logger.debug("%s", ss.str().c_str());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// NOTE: Preference would be to capture by value, and then move; but header is stack allocated
|
|
|
|
@ -1905,19 +1904,19 @@ bool rlc_am_lte::rlc_am_lte_rx::add_segment_and_check(rlc_amd_rx_pdu_segments_t*
|
|
|
|
|
header.fi |= (pdu->segments.front().header.fi & RLC_FI_FIELD_NOT_START_ALIGNED);
|
|
|
|
|
header.fi |= (pdu->segments.back().header.fi & RLC_FI_FIELD_NOT_END_ALIGNED);
|
|
|
|
|
|
|
|
|
|
log->debug("Starting header reconstruction of %zd segments\n", pdu->segments.size());
|
|
|
|
|
logger.debug("Starting header reconstruction of %zd segments", pdu->segments.size());
|
|
|
|
|
|
|
|
|
|
// Reconstruct li fields
|
|
|
|
|
uint16_t count = 0;
|
|
|
|
|
uint16_t carryover = 0;
|
|
|
|
|
for (it = pdu->segments.begin(); it != pdu->segments.end(); it++) {
|
|
|
|
|
log->debug(" Handling %d PDU segments\n", it->header.N_li);
|
|
|
|
|
logger.debug(" Handling %d PDU segments", it->header.N_li);
|
|
|
|
|
for (uint32_t i = 0; i < it->header.N_li; i++) {
|
|
|
|
|
header.li[header.N_li] = it->header.li[i];
|
|
|
|
|
if (i == 0) {
|
|
|
|
|
header.li[header.N_li] += carryover;
|
|
|
|
|
}
|
|
|
|
|
log->debug(" - adding segment %d/%d (%d B, SO=%d, carryover=%d, count=%d)\n",
|
|
|
|
|
logger.debug(" - adding segment %d/%d (%d B, SO=%d, carryover=%d, count=%d)",
|
|
|
|
|
i + 1,
|
|
|
|
|
it->header.N_li,
|
|
|
|
|
header.li[header.N_li],
|
|
|
|
@ -1931,7 +1930,7 @@ bool rlc_am_lte::rlc_am_lte_rx::add_segment_and_check(rlc_amd_rx_pdu_segments_t*
|
|
|
|
|
|
|
|
|
|
if (count <= it->buf->N_bytes) {
|
|
|
|
|
carryover += it->buf->N_bytes - count;
|
|
|
|
|
log->debug("Incremented carryover (it->buf->N_bytes=%d, count=%d). New carryover=%d\n",
|
|
|
|
|
logger.debug("Incremented carryover (it->buf->N_bytes=%d, count=%d). New carryover=%d",
|
|
|
|
|
it->buf->N_bytes,
|
|
|
|
|
count,
|
|
|
|
|
carryover);
|
|
|
|
@ -1939,7 +1938,7 @@ bool rlc_am_lte::rlc_am_lte_rx::add_segment_and_check(rlc_amd_rx_pdu_segments_t*
|
|
|
|
|
// Next segment would be too long, recalculate carryover
|
|
|
|
|
header.N_li--;
|
|
|
|
|
carryover = it->buf->N_bytes - (count - header.li[header.N_li]);
|
|
|
|
|
log->debug("Recalculated carryover=%d (it->buf->N_bytes=%d, count=%d, header.li[header.N_li]=%d)\n",
|
|
|
|
|
logger.debug("Recalculated carryover=%d (it->buf->N_bytes=%d, count=%d, header.li[header.N_li]=%d)",
|
|
|
|
|
carryover,
|
|
|
|
|
it->buf->N_bytes,
|
|
|
|
|
count,
|
|
|
|
@ -1948,7 +1947,7 @@ bool rlc_am_lte::rlc_am_lte_rx::add_segment_and_check(rlc_amd_rx_pdu_segments_t*
|
|
|
|
|
|
|
|
|
|
tmpit = it;
|
|
|
|
|
if (rlc_am_end_aligned(it->header.fi) && ++tmpit != pdu->segments.end()) {
|
|
|
|
|
log->debug("Header is end-aligned, overwrite header.li[%d]=%d\n", header.N_li, carryover);
|
|
|
|
|
logger.debug("Header is end-aligned, overwrite header.li[%d]=%d", header.N_li, carryover);
|
|
|
|
|
header.li[header.N_li] = carryover;
|
|
|
|
|
header.N_li++;
|
|
|
|
|
carryover = 0;
|
|
|
|
@ -1959,7 +1958,7 @@ bool rlc_am_lte::rlc_am_lte_rx::add_segment_and_check(rlc_amd_rx_pdu_segments_t*
|
|
|
|
|
header.p |= it->header.p;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log->debug("Finished header reconstruction of %zd segments\n", pdu->segments.size());
|
|
|
|
|
logger.debug("Finished header reconstruction of %zd segments", pdu->segments.size());
|
|
|
|
|
|
|
|
|
|
// Copy data
|
|
|
|
|
unique_byte_buffer_t full_pdu = srslte::make_byte_buffer();
|
|
|
|
@ -1968,7 +1967,7 @@ bool rlc_am_lte::rlc_am_lte_rx::add_segment_and_check(rlc_amd_rx_pdu_segments_t*
|
|
|
|
|
srslte::console("Fatal Error: Could not allocate PDU in add_segment_and_check()\n");
|
|
|
|
|
exit(-1);
|
|
|
|
|
#else
|
|
|
|
|
log->error("Fatal Error: Could not allocate PDU in add_segment_and_check()\n");
|
|
|
|
|
logger.error("Fatal Error: Could not allocate PDU in add_segment_and_check()");
|
|
|
|
|
return false;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
@ -2004,7 +2003,7 @@ bool rlc_am_lte::rlc_am_lte_rx::inside_rx_window(const int16_t sn)
|
|
|
|
|
|
|
|
|
|
void rlc_am_lte::rlc_am_lte_rx::debug_state()
|
|
|
|
|
{
|
|
|
|
|
log->debug("%s vr_r = %d, vr_mr = %d, vr_x = %d, vr_ms = %d, vr_h = %d\n", RB_NAME, vr_r, vr_mr, vr_x, vr_ms, vr_h);
|
|
|
|
|
logger.debug("%s vr_r = %d, vr_mr = %d, vr_x = %d, vr_ms = %d, vr_h = %d", RB_NAME, vr_r, vr_mr, vr_x, vr_ms, vr_h);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
|