mirror of https://github.com/PentHertz/srsLTE.git
lib,rlc_am_nr: starting to add build_sdu_segment() function.
Also adding write_header function that receives as argument uint8_t* so we can write the header straight to the payload.
This commit is contained in:
parent
72ba7503e5
commit
3e5b064a08
|
@ -85,19 +85,29 @@ public:
|
||||||
bool sdu_queue_is_full() final;
|
bool sdu_queue_is_full() final;
|
||||||
void reestablish() final;
|
void reestablish() final;
|
||||||
|
|
||||||
int write_sdu(unique_byte_buffer_t sdu);
|
int write_sdu(unique_byte_buffer_t sdu);
|
||||||
void empty_queue() final;
|
void empty_queue() final;
|
||||||
|
|
||||||
|
// Data PDU helpers
|
||||||
|
using rlc_amd_tx_pdu_nr = rlc_amd_tx_pdu<rlc_am_nr_pdu_header_t>;
|
||||||
|
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);
|
||||||
|
int build_retx_pdu(unique_byte_buffer_t& tx_pdu, uint32_t nof_bytes);
|
||||||
|
|
||||||
|
// Buffer State
|
||||||
bool has_data() final;
|
bool has_data() final;
|
||||||
uint32_t get_buffer_state() final;
|
uint32_t get_buffer_state() final;
|
||||||
void get_buffer_state(uint32_t& tx_queue, uint32_t& prio_tx_queue) final;
|
void get_buffer_state(uint32_t& tx_queue, uint32_t& prio_tx_queue) final;
|
||||||
|
|
||||||
|
// Status PDU
|
||||||
bool do_status();
|
bool do_status();
|
||||||
uint32_t build_status_pdu(byte_buffer_t* payload, uint32_t nof_bytes);
|
uint32_t build_status_pdu(byte_buffer_t* payload, uint32_t nof_bytes);
|
||||||
|
|
||||||
|
// Polling
|
||||||
uint8_t get_pdu_poll();
|
uint8_t get_pdu_poll();
|
||||||
|
|
||||||
int build_retx_pdu(unique_byte_buffer_t& tx_pdu, uint32_t nof_bytes);
|
|
||||||
|
|
||||||
void stop() final;
|
void stop() final;
|
||||||
|
|
||||||
bool inside_tx_window(uint32_t sn);
|
bool inside_tx_window(uint32_t sn);
|
||||||
|
@ -119,9 +129,7 @@ private:
|
||||||
* Tx state variables
|
* Tx state variables
|
||||||
* Ref: 3GPP TS 38.322 v16.2.0 Section 7.1
|
* Ref: 3GPP TS 38.322 v16.2.0 Section 7.1
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
struct rlc_am_nr_tx_state_t st = {};
|
struct rlc_am_nr_tx_state_t st = {};
|
||||||
|
|
||||||
using rlc_amd_tx_pdu_nr = rlc_amd_tx_pdu<rlc_am_nr_pdu_header_t>;
|
|
||||||
rlc_ringbuffer_t<rlc_amd_tx_pdu_nr, RLC_AM_WINDOW_SIZE> tx_window;
|
rlc_ringbuffer_t<rlc_amd_tx_pdu_nr, RLC_AM_WINDOW_SIZE> tx_window;
|
||||||
pdu_retx_queue<RLC_AM_WINDOW_SIZE> retx_queue;
|
pdu_retx_queue<RLC_AM_WINDOW_SIZE> retx_queue;
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,7 @@ uint32_t rlc_am_nr_read_data_pdu_header(const uint8_t* payload,
|
||||||
const rlc_am_nr_sn_size_t sn_size,
|
const rlc_am_nr_sn_size_t sn_size,
|
||||||
rlc_am_nr_pdu_header_t* header);
|
rlc_am_nr_pdu_header_t* header);
|
||||||
|
|
||||||
|
uint32_t rlc_am_nr_write_data_pdu_header(const rlc_am_nr_pdu_header_t& header, uint8_t* payload);
|
||||||
uint32_t rlc_am_nr_write_data_pdu_header(const rlc_am_nr_pdu_header_t& header, byte_buffer_t* pdu);
|
uint32_t rlc_am_nr_write_data_pdu_header(const rlc_am_nr_pdu_header_t& header, byte_buffer_t* pdu);
|
||||||
|
|
||||||
uint32_t rlc_am_nr_packed_length(const rlc_am_nr_pdu_header_t& header);
|
uint32_t rlc_am_nr_packed_length(const rlc_am_nr_pdu_header_t& header);
|
||||||
|
|
|
@ -105,12 +105,13 @@ uint32_t rlc_am_nr_tx::read_pdu(uint8_t* payload, uint32_t nof_bytes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read new SDU from TX queue
|
// Check wether there is something to TX
|
||||||
if (tx_sdu_queue.is_empty()) {
|
if (tx_sdu_queue.is_empty()) {
|
||||||
logger->info("No data available to be sent");
|
logger->info("No data available to be sent");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read new SDU from TX queue
|
||||||
unique_byte_buffer_t tx_sdu;
|
unique_byte_buffer_t tx_sdu;
|
||||||
logger->debug("Reading from RLC SDU queue. Queue size %d", tx_sdu_queue.size());
|
logger->debug("Reading from RLC SDU queue. Queue size %d", tx_sdu_queue.size());
|
||||||
do {
|
do {
|
||||||
|
@ -119,11 +120,8 @@ uint32_t rlc_am_nr_tx::read_pdu(uint8_t* payload, uint32_t nof_bytes)
|
||||||
|
|
||||||
if (tx_sdu != nullptr) {
|
if (tx_sdu != nullptr) {
|
||||||
logger->debug("Read RLC SDU - %d bytes", tx_sdu->N_bytes);
|
logger->debug("Read RLC SDU - %d bytes", tx_sdu->N_bytes);
|
||||||
}
|
} else {
|
||||||
|
logger->info("No SDUs left in the tx queue.");
|
||||||
uint16_t hdr_size = 2;
|
|
||||||
if (tx_sdu->N_bytes + hdr_size > nof_bytes) {
|
|
||||||
logger->warning("Segmentation not supported yet");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -136,6 +134,16 @@ uint32_t rlc_am_nr_tx::read_pdu(uint8_t* payload, uint32_t nof_bytes)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Segment new SDU if necessary
|
||||||
|
uint16_t hdr_size = 2;
|
||||||
|
if (tx_sdu->N_bytes + hdr_size > nof_bytes) {
|
||||||
|
logger->info("Trying to build PDU segment from SDU.");
|
||||||
|
if (build_new_sdu_segment(tx_sdu, tx_pdu, payload, nof_bytes) != SRSRAN_SUCCESS) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return tx_pdu.buf->N_bytes;
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(tx_pdu.buf->msg, tx_sdu->msg, tx_sdu->N_bytes);
|
memcpy(tx_pdu.buf->msg, tx_sdu->msg, tx_sdu->N_bytes);
|
||||||
tx_pdu.buf->N_bytes = tx_sdu->N_bytes;
|
tx_pdu.buf->N_bytes = tx_sdu->N_bytes;
|
||||||
|
|
||||||
|
@ -164,6 +172,43 @@ uint32_t rlc_am_nr_tx::read_pdu(uint8_t* payload, uint32_t nof_bytes)
|
||||||
return tx_sdu->N_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)
|
||||||
|
{
|
||||||
|
// Sanity check: can this SDU be sent this in a single PDU?
|
||||||
|
if (tx_sdu->N_bytes + 2 >= nof_bytes) {
|
||||||
|
logger->error("Calling build_new_sdu_segment(), but there are enough bytes to tx in a single PDU.");
|
||||||
|
return SRSRAN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sanity check: can this SDU be sent considering header overhead?
|
||||||
|
if (1 + 2 >= nof_bytes) { // Only two bytes, as SO is 0
|
||||||
|
logger->error("Cannot build new sdu_segment, but there are not enough bytes to tx header plus data.");
|
||||||
|
return SRSRAN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare header
|
||||||
|
rlc_am_nr_pdu_header_t hdr = {};
|
||||||
|
hdr.dc = RLC_DC_FIELD_DATA_PDU;
|
||||||
|
hdr.p = get_pdu_poll();
|
||||||
|
hdr.si = rlc_nr_si_field_t::first_segment;
|
||||||
|
hdr.sn_size = rlc_am_nr_sn_size_t::size12bits;
|
||||||
|
hdr.sn = st.tx_next;
|
||||||
|
hdr.so = 0;
|
||||||
|
tx_pdu.header = hdr;
|
||||||
|
log_rlc_am_nr_pdu_header_to_string(logger->info, hdr);
|
||||||
|
|
||||||
|
// Write header
|
||||||
|
uint32_t len = rlc_am_nr_write_data_pdu_header(hdr, payload);
|
||||||
|
if (len > nof_bytes) {
|
||||||
|
logger->error("Error writing AMD PDU header");
|
||||||
|
}
|
||||||
|
|
||||||
|
return SRSRAN_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
int rlc_am_nr_tx::build_retx_pdu(unique_byte_buffer_t& tx_pdu, uint32_t nof_bytes)
|
int rlc_am_nr_tx::build_retx_pdu(unique_byte_buffer_t& tx_pdu, uint32_t nof_bytes)
|
||||||
{
|
{
|
||||||
// Check there is at least 1 element before calling front()
|
// Check there is at least 1 element before calling front()
|
||||||
|
|
|
@ -96,12 +96,9 @@ uint32_t rlc_am_nr_packed_length(const rlc_am_nr_pdu_header_t& header)
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t rlc_am_nr_write_data_pdu_header(const rlc_am_nr_pdu_header_t& header, byte_buffer_t* pdu)
|
uint32_t rlc_am_nr_write_data_pdu_header(const rlc_am_nr_pdu_header_t& header, uint8_t* payload)
|
||||||
{
|
{
|
||||||
// Make room for the header
|
uint8_t* ptr = payload;
|
||||||
uint32_t len = rlc_am_nr_packed_length(header);
|
|
||||||
pdu->msg -= len;
|
|
||||||
uint8_t* ptr = pdu->msg;
|
|
||||||
|
|
||||||
// fixed header part
|
// fixed header part
|
||||||
*ptr = (header.dc & 0x01) << 7; ///< 1 bit D/C field
|
*ptr = (header.dc & 0x01) << 7; ///< 1 bit D/C field
|
||||||
|
@ -131,9 +128,15 @@ uint32_t rlc_am_nr_write_data_pdu_header(const rlc_am_nr_pdu_header_t& header, b
|
||||||
*ptr = (header.so & 0xff); // second part of SO
|
*ptr = (header.so & 0xff); // second part of SO
|
||||||
ptr++;
|
ptr++;
|
||||||
}
|
}
|
||||||
|
return rlc_am_nr_packed_length(header);
|
||||||
|
}
|
||||||
|
|
||||||
pdu->N_bytes += ptr - pdu->msg;
|
uint32_t rlc_am_nr_write_data_pdu_header(const rlc_am_nr_pdu_header_t& header, byte_buffer_t* pdu)
|
||||||
|
{
|
||||||
|
// Make room for the header
|
||||||
|
uint32_t len = rlc_am_nr_packed_length(header);
|
||||||
|
pdu->msg -= len;
|
||||||
|
rlc_am_nr_write_data_pdu_header(header, pdu->msg);
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue