lib,rlc_am_nr: changed rlc_amd_nr_tx_sdu to use std::list to store

segment infomation. Segment infomation incluses, SO and payload length.
master
Pedro Alvarez 3 years ago
parent 76c33c78a9
commit aae1d9ad10

@ -70,6 +70,21 @@ struct rlc_am_nr_tx_state_t {
uint32_t byte_without_poll;
};
struct rlc_amd_tx_pdu_nr {
const uint32_t rlc_sn = INVALID_RLC_SN;
const uint32_t pdcp_sn = INVALID_RLC_SN;
rlc_am_nr_pdu_header_t header = {};
unique_byte_buffer_t buf = nullptr;
uint32_t retx_count = 0;
struct pdu_segment {
uint32_t so = 0;
uint32_t retx_count = 0;
uint32_t payload_len = 0;
};
std::list<pdu_segment> segment_list;
explicit rlc_amd_tx_pdu_nr(uint32_t sn) : rlc_sn(sn) {}
};
class rlc_am_nr_tx : public rlc_am::rlc_am_base_tx
{
public:
@ -89,22 +104,12 @@ public:
void empty_queue() final;
// Data PDU helpers
using rlc_amd_tx_pdu_nr = rlc_amd_tx_pdu<rlc_am_nr_pdu_header_t>;
/*
struct rlc_amd_tx_pdu_nr {
const uint32_t rlc_sn = INVALID_RLC_SN;
const uint32_t pdcp_sn = INVALID_RLC_SN;
struct tx_pdu_segment {
rlc_am_nr_pdu_header_t header = {};
uint32_t retx_count = 0;
uint32_t so = 0;
uint32_t len = 0;
};
};*/
int build_new_sdu_segment(const unique_byte_buffer_t& tx_sdu,
rlc_amd_tx_pdu_nr& tx_pdu,
uint8_t* payload,
uint32_t nof_bytes);
// using rlc_amd_tx_pdu_nr_test = rlc_amd_tx_pdu<rlc_am_nr_pdu_header_t>;
int build_new_sdu_segment(unique_byte_buffer_t tx_sdu,
rlc_amd_tx_pdu_nr& tx_pdu,
uint8_t* payload,
uint32_t nof_bytes);
int build_continuation_sdu_segment(rlc_amd_tx_pdu_nr& tx_pdu, uint8_t* payload, uint32_t nof_bytes);
int build_retx_pdu(unique_byte_buffer_t& tx_pdu, uint32_t nof_bytes);

@ -146,7 +146,7 @@ uint32_t rlc_am_nr_tx::read_pdu(uint8_t* payload, uint32_t nof_bytes)
uint16_t hdr_size = 2;
if (tx_sdu->N_bytes + hdr_size > nof_bytes) {
logger->info("Trying to build PDU segment from SDU.");
return build_new_sdu_segment(tx_sdu, tx_pdu, payload, nof_bytes);
return build_new_sdu_segment(std::move(tx_sdu), tx_pdu, payload, nof_bytes);
}
memcpy(tx_pdu.buf->msg, tx_sdu->msg, tx_sdu->N_bytes);
@ -177,10 +177,10 @@ uint32_t rlc_am_nr_tx::read_pdu(uint8_t* payload, uint32_t nof_bytes)
return tx_sdu->N_bytes;
}
int rlc_am_nr_tx::build_new_sdu_segment(const unique_byte_buffer_t& tx_sdu,
rlc_amd_tx_pdu_nr& tx_pdu,
uint8_t* payload,
uint32_t nof_bytes)
int rlc_am_nr_tx::build_new_sdu_segment(unique_byte_buffer_t tx_sdu,
rlc_amd_tx_pdu_nr& tx_pdu,
uint8_t* payload,
uint32_t nof_bytes)
{
logger->info("Creating new SDU segment. Tx SDU (%d B),,nof_bytes=%d B ", tx_sdu->N_bytes, nof_bytes);
@ -218,8 +218,18 @@ int rlc_am_nr_tx::build_new_sdu_segment(const unique_byte_buffer_t& tx_sdu,
logger->error("Error writing AMD PDU header");
}
// Copy PDU to payload
uint32_t segment_payload_len = nof_bytes - hdr_len;
memcpy(&payload[hdr_len], tx_pdu.buf->msg, segment_payload_len);
// Save SDU currently being segmented
current_sdu.rlc_sn = st.tx_next;
current_sdu.buf = std::move(tx_sdu);
// Store Segment Info
rlc_amd_tx_pdu_nr::pdu_segment segment_info;
segment_info.payload_len = segment_payload_len;
tx_pdu.segment_list.push_back(segment_info);
return hdr_len + segment_payload_len;
}
@ -230,12 +240,88 @@ int rlc_am_nr_tx::build_continuation_sdu_segment(rlc_amd_tx_pdu_nr& tx_pdu, uint
current_sdu.buf->N_bytes,
nof_bytes);
// Can the rest of the SDU be sent on a single segment PDU?
// Sanity check: is there an initial SDU segment?
if (tx_pdu.segment_list.empty()) {
logger->error("build_continuation_sdu_segment was called, but there was no initial segment. SN=%d, Tx SDU (%d B), "
"nof_bytes=%d B ",
current_sdu.rlc_sn,
current_sdu.buf->N_bytes,
nof_bytes);
current_sdu.rlc_sn = INVALID_RLC_SN;
current_sdu.buf = nullptr;
return 0;
}
// Sanity check: can this SDU be sent considering header overhead?
if (5 < nof_bytes) { // Four bytes of header, as SO is present
logger->error(
"Cannot build new sdu_segment, there are not enough bytes allocated to tx header plus data. nof_bytes=%d",
nof_bytes);
return 0;
}
// Can the rest of the SDU be sent on a single segment PDU?
std::list<rlc_amd_tx_pdu_nr::pdu_segment>::iterator it = tx_pdu.segment_list.end();
--it;
uint32_t last_byte = it->so + it->payload_len;
logger->debug("Continuing SDU segment. SN=%d, last byte transmited %d", tx_pdu.rlc_sn, last_byte);
// Sanity check: last byte must be smaller than SDU
if (current_sdu.buf->N_bytes < last_byte) {
logger->error(
"Last byte transmited larger than SDU len. SDU len=%d B, last_byte=%d B", tx_pdu.buf->N_bytes, last_byte);
return 0;
}
uint32_t segment_payload_full_len = current_sdu.buf->N_bytes - last_byte + 4; // Four bytes of header
uint32_t segment_payload_len = current_sdu.buf->N_bytes - last_byte;
rlc_nr_si_field_t si = segment_payload_full_len > nof_bytes ? rlc_nr_si_field_t::neither_first_nor_last_segment
: rlc_nr_si_field_t::last_segment;
if (si == rlc_nr_si_field_t::neither_first_nor_last_segment) {
logger->info("Grant is not large enough for full SDU."
"SDU bytes left %d, nof_bytes %d, ",
segment_payload_full_len,
nof_bytes);
segment_payload_len = nof_bytes - 4;
segment_payload_full_len = nof_bytes;
} else {
logger->info("Grant is large enough for full SDU."
"SDU bytes left %d, nof_bytes %d, ",
segment_payload_full_len,
nof_bytes);
}
// Prepare header
return 0;
rlc_am_nr_pdu_header_t hdr = {};
hdr.dc = RLC_DC_FIELD_DATA_PDU;
hdr.p = get_pdu_poll();
hdr.si = si;
hdr.sn_size = rlc_am_nr_sn_size_t::size12bits;
hdr.sn = st.tx_next;
hdr.so = last_byte;
tx_pdu.header = hdr;
log_rlc_am_nr_pdu_header_to_string(logger->info, hdr);
// Write header
uint32_t hdr_len = rlc_am_nr_write_data_pdu_header(hdr, payload);
if (hdr_len > nof_bytes) {
logger->error("Error writing AMD PDU header");
return 0;
}
// Copy PDU to payload
memcpy(&payload[hdr_len], &tx_pdu.buf->msg[last_byte], segment_payload_len);
if (si == rlc_nr_si_field_t::neither_first_nor_last_segment) {
logger->info("Grant is not large enough for full SDU."
"Storing SDU segment info");
} else {
logger->info("Grant is large enough for full SDU."
"Removing current SDU info");
}
return hdr_len + segment_payload_len;
}
int rlc_am_nr_tx::build_retx_pdu(unique_byte_buffer_t& tx_pdu, uint32_t nof_bytes)

Loading…
Cancel
Save