RLC AM NR: Added some logging functions to better debug the state and the received headers. Added initial handling of data pdu. Updating rx_next and rx_status_highest now.

This commit is contained in:
Pedro Alvarez 2021-10-04 17:19:22 +01:00
parent 2d29e4005c
commit 8ae4d379aa
3 changed files with 155 additions and 10 deletions

View File

@ -111,6 +111,13 @@ public:
uint32_t get_status_pdu(rlc_am_nr_status_pdu_t* status, uint32_t len); uint32_t get_status_pdu(rlc_am_nr_status_pdu_t* status, uint32_t len);
uint32_t get_status_pdu_length(); uint32_t get_status_pdu_length();
// Data handling methods
void handle_data_pdu_full(uint8_t* payload, uint32_t nof_bytes, rlc_am_nr_pdu_header_t& header);
bool inside_rx_window(uint32_t sn);
// Helpers
void debug_state();
private: private:
rlc_am* parent = nullptr; rlc_am* parent = nullptr;
rlc_am_nr_tx* tx = nullptr; rlc_am_nr_tx* tx = nullptr;

View File

@ -13,6 +13,7 @@
#ifndef SRSRAN_RLC_AM_NR_PACKING_H #ifndef SRSRAN_RLC_AM_NR_PACKING_H
#define SRSRAN_RLC_AM_NR_PACKING_H #define SRSRAN_RLC_AM_NR_PACKING_H
#include "srsran/common/string_helpers.h"
#include "srsran/rlc/rlc_am_base.h" #include "srsran/rlc/rlc_am_base.h"
namespace srsran { namespace srsran {
@ -79,6 +80,55 @@ int32_t rlc_am_nr_write_status_pdu(const rlc_am_nr_status_pdu_t& status_pdu,
const rlc_am_nr_sn_size_t sn_size, const rlc_am_nr_sn_size_t sn_size,
byte_buffer_t* pdu); byte_buffer_t* pdu);
/**
* Logs Status PDU into provided log channel, using fmt_str as format string
*/
template <typename... Args>
void log_rlc_am_nr_status_pdu_to_string(srslog::log_channel& log_ch,
const char* fmt_str,
rlc_am_nr_status_pdu_t* status,
Args&&... args)
{
if (not log_ch.enabled()) {
return;
}
fmt::memory_buffer buffer;
fmt::format_to(buffer, "ACK_SN = {}, N_nack = {}", status->ack_sn, status->N_nack);
if (status->N_nack > 0) {
fmt::format_to(buffer, ", NACK_SN = ");
for (uint32_t i = 0; i < status->N_nack; ++i) {
if (status->nacks[i].has_so) {
fmt::format_to(
buffer, "[{} {}:{}]", status->nacks[i].nack_sn, status->nacks[i].so_start, status->nacks[i].so_end);
} else {
fmt::format_to(buffer, "[{}]", status->nacks[i].nack_sn);
}
}
}
log_ch(fmt_str, std::forward<Args>(args)..., to_c_str(buffer));
}
/*
* Log NR AMD PDUs
*/
inline void log_rlc_am_nr_pdu_header_to_string(srslog::log_channel& log_ch, const rlc_am_nr_pdu_header_t& header)
{
if (not log_ch.enabled()) {
return;
}
fmt::memory_buffer buffer;
fmt::format_to(buffer,
"[{}, P={}, SI={}, SN_SIZE={}, SN={}, SO={}",
rlc_dc_field_text[header.dc],
(header.p ? "1" : "0"),
to_string_short(header.si),
header.sn,
header.sn,
header.so);
fmt::format_to(buffer, "]");
log_ch("%s", to_c_str(buffer));
}
} // namespace srsran } // namespace srsran
#endif // SRSRAN_RLC_AM_NR_PACKING_H #endif // SRSRAN_RLC_AM_NR_PACKING_H

View File

@ -19,9 +19,10 @@
#include "srsran/srslog/event_trace.h" #include "srsran/srslog/event_trace.h"
#include <iostream> #include <iostream>
#define RLC_AM_NR_WINDOW_SIZE 1024 #define RLC_AM_NR_WINDOW_SIZE 2048
#define RX_MOD_BASE_NR(x) (((x)-rx_next) % RLC_AM_NR_WINDOW_SIZE) #define MOD_NR 4096
//#define TX_MOD_BASE_NR(x) (((x)-vt_a) % RLC_AM_NR_WINDOW_SIZE) #define RX_MOD_BASE_NR(x) (((x)-rx_next) % MOD_NR)
//#define TX_MOD_BASE_NR(x) (((x)-vt_a) % MOD_NR)
namespace srsran { namespace srsran {
@ -232,17 +233,92 @@ void rlc_am_nr_rx::handle_data_pdu(uint8_t* payload, uint32_t nof_bytes)
rlc_am_nr_pdu_header_t header = {}; rlc_am_nr_pdu_header_t header = {};
rlc_am_nr_read_data_pdu_header(payload, nof_bytes, rlc_am_nr_sn_size_t::size12bits, &header); rlc_am_nr_read_data_pdu_header(payload, nof_bytes, rlc_am_nr_sn_size_t::size12bits, &header);
// TODO
// if (header.rf != 0) {
// handle_data_pdu_segment(payload, payload_len, header); TODO
//} else {
handle_data_pdu_full(payload, nof_bytes, header);
//}
}
void rlc_am_nr_rx::handle_data_pdu_full(uint8_t* payload, uint32_t nof_bytes, rlc_am_nr_pdu_header_t& header)
{
std::map<uint32_t, rlc_amd_rx_pdu_nr>::iterator it;
logger->info(payload, nof_bytes, "%s Rx data PDU SN=%d (%d B)", parent->rb_name, header.sn, nof_bytes);
log_rlc_am_nr_pdu_header_to_string(logger->debug, header);
// sanity check for segments not exceeding PDU length
// TODO
if (!inside_rx_window(header.sn)) {
logger->info("%s SN=%d outside rx window [%d:%d] - discarding",
parent->rb_name,
header.sn,
rx_next,
rx_next + RLC_AM_NR_WINDOW_SIZE);
return;
}
// Section 5.2.3.2.2, discard duplicate PDUs
if (rx_window.has_sn(header.sn)) {
logger->info("%s Discarding duplicate SN=%d", parent->rb_name, header.sn);
return;
}
// Write to rx window
rlc_amd_rx_pdu_nr& pdu = rx_window.add_pdu(header.sn);
pdu.buf = srsran::make_byte_buffer();
if (pdu.buf == nullptr) {
logger->error("Fatal Error: Couldn't allocate PDU in handle_data_pdu().");
rx_window.remove_pdu(header.sn);
return;
}
pdu.buf->set_timestamp();
// check available space for payload
if (nof_bytes > pdu.buf->get_tailroom()) {
logger->error("%s Discarding SN=%d of size %d B (available space %d B)",
parent->rb_name,
header.sn,
nof_bytes,
pdu.buf->get_tailroom());
return;
}
memcpy(pdu.buf->msg, payload, nof_bytes);
pdu.buf->N_bytes = nof_bytes;
pdu.header = header;
// Update Rx_Next_Highest
if (RX_MOD_BASE_NR(header.sn) >= RX_MOD_BASE_NR(rx_next_highest)) {
rx_next_highest = (header.sn + 1) % MOD;
}
// Check poll bit // Check poll bit
if (header.p != 0) { if (header.p) {
logger->info("%s Status packet requested through polling bit", parent->rb_name); logger->info("%s Status packet requested through polling bit", parent->rb_name);
do_status = true; do_status = true;
// 36.322 v10 Section 5.2.3
// if (RX_MOD_BASE(header.sn) < RX_MOD_BASE(vr_ms) || RX_MOD_BASE(header.sn) >= RX_MOD_BASE(vr_mr)) {
// do_status = true;
//}
// else delay for reordering timer
} }
// Update RX_Highest_Status
if (RX_MOD_BASE_NR(header.sn) == RX_MOD_BASE_NR(rx_highest_status)) {
rx_highest_status = header.sn % MOD;
}
// Update RX_Next
if (RX_MOD_BASE_NR(header.sn) == RX_MOD_BASE_NR(rx_highest_status)) {
rx_highest_status = header.sn % MOD;
}
// Update reordering variables and timers (36.322 v10.0.0 Section 5.1.3.2.3)
// TODO
debug_state();
}
bool rlc_am_nr_rx::inside_rx_window(uint32_t sn)
{
return (RX_MOD_BASE_NR(sn) >= RX_MOD_BASE_NR(rx_next)) &&
(RX_MOD_BASE_NR(sn) < RX_MOD_BASE_NR(rx_next + RLC_AM_NR_WINDOW_SIZE));
} }
/* /*
@ -303,4 +379,16 @@ uint32_t rlc_am_nr_rx::get_rx_buffered_bytes()
{ {
return 0; return 0;
} }
/*
* Helpers
*/
void rlc_am_nr_rx::debug_state()
{
logger->debug("RX entity state: Rx_Next %d, Rx_Next_Status_Trigger %d, Rx_Highest_Status %d, Rx_Next_Highest",
rx_next,
rx_next_status_trigger,
rx_highest_status,
rx_next_highest);
}
} // namespace srsran } // namespace srsran