|
|
|
@ -89,11 +89,25 @@ rlc_amd_tx_pdu::~rlc_amd_tx_pdu()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
|
* RLC AM LTE entity
|
|
|
|
|
***************************************************************************/
|
|
|
|
|
rlc_am_lte::rlc_am_lte(srslog::basic_logger& logger,
|
|
|
|
|
uint32_t lcid_,
|
|
|
|
|
srsue::pdcp_interface_rlc* pdcp_,
|
|
|
|
|
srsue::rrc_interface_rlc* rrc_,
|
|
|
|
|
srsran::timer_handler* timers_) :
|
|
|
|
|
rlc_am_base(logger, lcid_, pdcp_, rrc_, timers_, nullptr, nullptr)
|
|
|
|
|
{
|
|
|
|
|
tx = new rlc_am_lte::rlc_am_lte_tx(this);
|
|
|
|
|
rx = new rlc_am_lte::rlc_am_lte_rx(this);
|
|
|
|
|
tx_base = tx;
|
|
|
|
|
rx_base = rx;
|
|
|
|
|
}
|
|
|
|
|
/****************************************************************************
|
|
|
|
|
* Tx subclass implementation
|
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
|
|
rlc_am_lte_tx::rlc_am_lte_tx(rlc_am_lte* parent_) :
|
|
|
|
|
rlc_am_lte::rlc_am_lte_tx::rlc_am_lte_tx(rlc_am_lte* parent_) :
|
|
|
|
|
parent(parent_),
|
|
|
|
|
logger(parent_->logger),
|
|
|
|
|
pool(byte_buffer_pool::get_instance()),
|
|
|
|
@ -101,12 +115,7 @@ rlc_am_lte_tx::rlc_am_lte_tx(rlc_am_lte* parent_) :
|
|
|
|
|
status_prohibit_timer(parent_->timers->get_unique_timer())
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
void rlc_am_lte_tx::set_bsr_callback(bsr_callback_t callback)
|
|
|
|
|
{
|
|
|
|
|
bsr_callback = callback;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool rlc_am_lte_tx::configure(const rlc_config_t& cfg_)
|
|
|
|
|
bool rlc_am_lte::rlc_am_lte_tx::configure(const rlc_config_t& cfg_)
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<std::mutex> lock(mutex);
|
|
|
|
|
if (cfg_.tx_queue_length > MAX_SDUS_PER_RLC_PDU) {
|
|
|
|
@ -144,13 +153,13 @@ bool rlc_am_lte_tx::configure(const rlc_config_t& cfg_)
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void rlc_am_lte_tx::stop()
|
|
|
|
|
void rlc_am_lte::rlc_am_lte_tx::stop()
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<std::mutex> lock(mutex);
|
|
|
|
|
stop_nolock();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void rlc_am_lte_tx::stop_nolock()
|
|
|
|
|
void rlc_am_lte::rlc_am_lte_tx::stop_nolock()
|
|
|
|
|
{
|
|
|
|
|
empty_queue_nolock();
|
|
|
|
|
|
|
|
|
@ -182,13 +191,13 @@ void rlc_am_lte_tx::stop_nolock()
|
|
|
|
|
undelivered_sdu_info_queue.clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void rlc_am_lte_tx::empty_queue()
|
|
|
|
|
void rlc_am_lte::rlc_am_lte_tx::empty_queue()
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<std::mutex> lock(mutex);
|
|
|
|
|
empty_queue_nolock();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void rlc_am_lte_tx::empty_queue_nolock()
|
|
|
|
|
void rlc_am_lte::rlc_am_lte_tx::empty_queue_nolock()
|
|
|
|
|
{
|
|
|
|
|
// deallocate all SDUs in transmit queue
|
|
|
|
|
while (tx_sdu_queue.size() > 0) {
|
|
|
|
@ -202,20 +211,20 @@ void rlc_am_lte_tx::empty_queue_nolock()
|
|
|
|
|
tx_sdu.reset();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void rlc_am_lte_tx::reestablish()
|
|
|
|
|
void rlc_am_lte::rlc_am_lte_tx::reestablish()
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<std::mutex> lock(mutex);
|
|
|
|
|
stop_nolock();
|
|
|
|
|
tx_enabled = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool rlc_am_lte_tx::do_status()
|
|
|
|
|
bool rlc_am_lte::rlc_am_lte_tx::do_status()
|
|
|
|
|
{
|
|
|
|
|
return parent->rx.get_do_status();
|
|
|
|
|
return parent->rx->get_do_status();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Function is supposed to return as fast as possible
|
|
|
|
|
bool rlc_am_lte_tx::has_data()
|
|
|
|
|
bool rlc_am_lte::rlc_am_lte_tx::has_data()
|
|
|
|
|
{
|
|
|
|
|
return (((do_status() && not status_prohibit_timer.is_running())) || // if we have a status PDU to transmit
|
|
|
|
|
(not retx_queue.empty()) || // if we have a retransmission
|
|
|
|
@ -232,7 +241,7 @@ bool rlc_am_lte_tx::has_data()
|
|
|
|
|
*
|
|
|
|
|
* @param sn The SN of the PDU to check
|
|
|
|
|
*/
|
|
|
|
|
void rlc_am_lte_tx::check_sn_reached_max_retx(uint32_t sn)
|
|
|
|
|
void rlc_am_lte::rlc_am_lte_tx::check_sn_reached_max_retx(uint32_t sn)
|
|
|
|
|
{
|
|
|
|
|
if (tx_window[sn].retx_count == cfg.max_retx_thresh) {
|
|
|
|
|
logger.warning("%s Signaling max number of reTx=%d for SN=%d", RB_NAME, tx_window[sn].retx_count, sn);
|
|
|
|
@ -248,20 +257,20 @@ void rlc_am_lte_tx::check_sn_reached_max_retx(uint32_t sn)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t rlc_am_lte_tx::get_buffer_state()
|
|
|
|
|
uint32_t rlc_am_lte::rlc_am_lte_tx::get_buffer_state()
|
|
|
|
|
{
|
|
|
|
|
uint32_t new_tx_queue = 0, prio_tx_queue = 0;
|
|
|
|
|
get_buffer_state(new_tx_queue, prio_tx_queue);
|
|
|
|
|
return new_tx_queue + prio_tx_queue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void rlc_am_lte_tx::get_buffer_state(uint32_t& n_bytes_newtx, uint32_t& n_bytes_prio)
|
|
|
|
|
void rlc_am_lte::rlc_am_lte_tx::get_buffer_state(uint32_t& n_bytes_newtx, uint32_t& n_bytes_prio)
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<std::mutex> lock(mutex);
|
|
|
|
|
get_buffer_state_nolock(n_bytes_newtx, n_bytes_prio);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void rlc_am_lte_tx::get_buffer_state_nolock(uint32_t& n_bytes_newtx, uint32_t& n_bytes_prio)
|
|
|
|
|
void rlc_am_lte::rlc_am_lte_tx::get_buffer_state_nolock(uint32_t& n_bytes_newtx, uint32_t& n_bytes_prio)
|
|
|
|
|
{
|
|
|
|
|
n_bytes_newtx = 0;
|
|
|
|
|
n_bytes_prio = 0;
|
|
|
|
@ -276,7 +285,7 @@ void rlc_am_lte_tx::get_buffer_state_nolock(uint32_t& n_bytes_newtx, uint32_t& n
|
|
|
|
|
|
|
|
|
|
// Bytes needed for status report
|
|
|
|
|
if (do_status() && not status_prohibit_timer.is_running()) {
|
|
|
|
|
n_bytes_prio += parent->rx.get_status_pdu_length();
|
|
|
|
|
n_bytes_prio += parent->rx->get_status_pdu_length();
|
|
|
|
|
logger.debug("%s Buffer state - total status report: %d bytes", RB_NAME, n_bytes_prio);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -323,47 +332,12 @@ void rlc_am_lte_tx::get_buffer_state_nolock(uint32_t& n_bytes_newtx, uint32_t& n
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (bsr_callback) {
|
|
|
|
|
logger.debug("%s Calling BSR callback - %d new_tx, %d prio bytes", RB_NAME, n_bytes_newtx, n_bytes_prio);
|
|
|
|
|
bsr_callback(parent->lcid, n_bytes_newtx, n_bytes_prio);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int rlc_am_lte_tx::write_sdu(unique_byte_buffer_t sdu)
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<std::mutex> lock(mutex);
|
|
|
|
|
|
|
|
|
|
if (!tx_enabled) {
|
|
|
|
|
return SRSRAN_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (sdu.get() == nullptr) {
|
|
|
|
|
logger.warning("NULL SDU pointer in write_sdu()");
|
|
|
|
|
return SRSRAN_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get SDU info
|
|
|
|
|
uint32_t sdu_pdcp_sn = sdu->md.pdcp_sn;
|
|
|
|
|
|
|
|
|
|
// Store SDU
|
|
|
|
|
uint8_t* msg_ptr = sdu->msg;
|
|
|
|
|
uint32_t nof_bytes = sdu->N_bytes;
|
|
|
|
|
srsran::error_type<unique_byte_buffer_t> ret = tx_sdu_queue.try_write(std::move(sdu));
|
|
|
|
|
if (ret) {
|
|
|
|
|
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
|
|
|
|
|
logger.warning(ret.error()->msg,
|
|
|
|
|
ret.error()->N_bytes,
|
|
|
|
|
"[Dropped SDU] %s Tx SDU (%d B, tx_sdu_queue_len=%d)",
|
|
|
|
|
RB_NAME,
|
|
|
|
|
ret.error()->N_bytes,
|
|
|
|
|
tx_sdu_queue.size());
|
|
|
|
|
return SRSRAN_ERROR;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return SRSRAN_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void rlc_am_lte_tx::discard_sdu(uint32_t discard_sn)
|
|
|
|
|
void rlc_am_lte::rlc_am_lte_tx::discard_sdu(uint32_t discard_sn)
|
|
|
|
|
{
|
|
|
|
|
if (!tx_enabled) {
|
|
|
|
|
return;
|
|
|
|
@ -381,12 +355,12 @@ void rlc_am_lte_tx::discard_sdu(uint32_t discard_sn)
|
|
|
|
|
logger.info("%s PDU with PDCP_SN=%d", discarded ? "Discarding" : "Couldn't discard", discard_sn);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool rlc_am_lte_tx::sdu_queue_is_full()
|
|
|
|
|
bool rlc_am_lte::rlc_am_lte_tx::sdu_queue_is_full()
|
|
|
|
|
{
|
|
|
|
|
return tx_sdu_queue.is_full();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t rlc_am_lte_tx::read_pdu(uint8_t* payload, uint32_t nof_bytes)
|
|
|
|
|
uint32_t rlc_am_lte::rlc_am_lte_tx::read_pdu(uint8_t* payload, uint32_t nof_bytes)
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<std::mutex> lock(mutex);
|
|
|
|
|
|
|
|
|
@ -424,7 +398,7 @@ uint32_t rlc_am_lte_tx::read_pdu(uint8_t* payload, uint32_t nof_bytes)
|
|
|
|
|
return build_data_pdu(payload, nof_bytes);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void rlc_am_lte_tx::timer_expired(uint32_t timeout_id)
|
|
|
|
|
void rlc_am_lte::rlc_am_lte_tx::timer_expired(uint32_t timeout_id)
|
|
|
|
|
{
|
|
|
|
|
std::unique_lock<std::mutex> lock(mutex);
|
|
|
|
|
if (poll_retx_timer.is_valid() && poll_retx_timer.id() == timeout_id) {
|
|
|
|
@ -445,7 +419,7 @@ void rlc_am_lte_tx::timer_expired(uint32_t timeout_id)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void rlc_am_lte_tx::retransmit_pdu(uint32_t sn)
|
|
|
|
|
void rlc_am_lte::rlc_am_lte_tx::retransmit_pdu(uint32_t sn)
|
|
|
|
|
{
|
|
|
|
|
if (tx_window.empty()) {
|
|
|
|
|
logger.warning("%s No PDU to retransmit", RB_NAME);
|
|
|
|
@ -484,7 +458,7 @@ void rlc_am_lte_tx::retransmit_pdu(uint32_t sn)
|
|
|
|
|
*
|
|
|
|
|
* @return True if a status PDU needs to be requested, false otherwise.
|
|
|
|
|
*/
|
|
|
|
|
bool rlc_am_lte_tx::poll_required()
|
|
|
|
|
bool rlc_am_lte::rlc_am_lte_tx::poll_required()
|
|
|
|
|
{
|
|
|
|
|
if (cfg.poll_pdu > 0 && pdu_without_poll > static_cast<uint32_t>(cfg.poll_pdu)) {
|
|
|
|
|
return true;
|
|
|
|
@ -519,9 +493,10 @@ bool rlc_am_lte_tx::poll_required()
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int rlc_am_lte_tx::build_status_pdu(uint8_t* payload, uint32_t nof_bytes)
|
|
|
|
|
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);
|
|
|
|
|
logger->debug("%s Generating status PDU. Nof bytes %d", RB_NAME, nof_bytes);
|
|
|
|
|
int pdu_len = parent->rx->get_status_pdu(&tx_status, nof_bytes);
|
|
|
|
|
if (pdu_len == SRSRAN_ERROR) {
|
|
|
|
|
logger.debug("%s Deferred Status PDU. Cause: Failed to acquire Rx lock", RB_NAME);
|
|
|
|
|
pdu_len = 0;
|
|
|
|
@ -541,7 +516,7 @@ int rlc_am_lte_tx::build_status_pdu(uint8_t* payload, uint32_t nof_bytes)
|
|
|
|
|
return pdu_len;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int rlc_am_lte_tx::build_retx_pdu(uint8_t* payload, uint32_t nof_bytes)
|
|
|
|
|
int rlc_am_lte::rlc_am_lte_tx::build_retx_pdu(uint8_t* payload, uint32_t nof_bytes)
|
|
|
|
|
{
|
|
|
|
|
// Check there is at least 1 element before calling front()
|
|
|
|
|
if (retx_queue.empty()) {
|
|
|
|
@ -622,7 +597,7 @@ int rlc_am_lte_tx::build_retx_pdu(uint8_t* payload, uint32_t nof_bytes)
|
|
|
|
|
return (ptr - payload) + tx_window[retx.sn].buf->N_bytes;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int rlc_am_lte_tx::build_segment(uint8_t* payload, uint32_t nof_bytes, rlc_amd_retx_t retx)
|
|
|
|
|
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) {
|
|
|
|
|
logger.error("In build_segment: retx.sn=%d has null buffer", retx.sn);
|
|
|
|
@ -797,7 +772,7 @@ int rlc_am_lte_tx::build_segment(uint8_t* payload, uint32_t nof_bytes, rlc_amd_r
|
|
|
|
|
return pdu_len;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int rlc_am_lte_tx::build_data_pdu(uint8_t* payload, uint32_t nof_bytes)
|
|
|
|
|
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()) {
|
|
|
|
|
logger.info("No data available to be sent");
|
|
|
|
@ -1013,7 +988,7 @@ int rlc_am_lte_tx::build_data_pdu(uint8_t* payload, uint32_t nof_bytes)
|
|
|
|
|
return total_len;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void rlc_am_lte_tx::handle_control_pdu(uint8_t* payload, uint32_t nof_bytes)
|
|
|
|
|
void rlc_am_lte::rlc_am_lte_tx::handle_control_pdu(uint8_t* payload, uint32_t nof_bytes)
|
|
|
|
|
{
|
|
|
|
|
if (not tx_enabled) {
|
|
|
|
|
return;
|
|
|
|
@ -1161,7 +1136,7 @@ void rlc_am_lte_tx::handle_control_pdu(uint8_t* payload, uint32_t nof_bytes)
|
|
|
|
|
* @tx_pdu: RLC PDU that was ack'ed.
|
|
|
|
|
* @notify_info_vec: Vector which will keep track of the PDCP PDU SNs that have been fully ack'ed.
|
|
|
|
|
*/
|
|
|
|
|
void rlc_am_lte_tx::update_notification_ack_info(uint32_t rlc_sn)
|
|
|
|
|
void rlc_am_lte::rlc_am_lte_tx::update_notification_ack_info(uint32_t rlc_sn)
|
|
|
|
|
{
|
|
|
|
|
logger.debug("Updating ACK info: RLC SN=%d, number of notified SDU=%ld, number of undelivered SDUs=%ld",
|
|
|
|
|
rlc_sn,
|
|
|
|
@ -1198,12 +1173,12 @@ void rlc_am_lte_tx::update_notification_ack_info(uint32_t rlc_sn)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void rlc_am_lte_tx::debug_state()
|
|
|
|
|
void rlc_am_lte::rlc_am_lte_tx::debug_state()
|
|
|
|
|
{
|
|
|
|
|
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_tx::required_buffer_size(const rlc_amd_retx_t& retx)
|
|
|
|
|
int rlc_am_lte::rlc_am_lte_tx::required_buffer_size(const rlc_amd_retx_t& retx)
|
|
|
|
|
{
|
|
|
|
|
if (!retx.is_segment) {
|
|
|
|
|
if (tx_window.has_sn(retx.sn)) {
|
|
|
|
@ -1280,16 +1255,16 @@ int rlc_am_lte_tx::required_buffer_size(const rlc_amd_retx_t& retx)
|
|
|
|
|
* Rx subclass implementation
|
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
|
|
rlc_am_lte_rx::rlc_am_lte_rx(rlc_am_lte* parent_) :
|
|
|
|
|
rlc_am_lte::rlc_am_lte_rx::rlc_am_lte_rx(rlc_am_lte* parent_) :
|
|
|
|
|
parent(parent_),
|
|
|
|
|
pool(byte_buffer_pool::get_instance()),
|
|
|
|
|
logger(parent_->logger),
|
|
|
|
|
reordering_timer(parent_->timers->get_unique_timer())
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
rlc_am_lte_rx::~rlc_am_lte_rx() {}
|
|
|
|
|
rlc_am_lte::rlc_am_lte_rx::~rlc_am_lte_rx() {}
|
|
|
|
|
|
|
|
|
|
bool rlc_am_lte_rx::configure(rlc_config_t cfg_)
|
|
|
|
|
bool rlc_am_lte::rlc_am_lte_rx::configure(const rlc_config_t& cfg_)
|
|
|
|
|
{
|
|
|
|
|
// TODO: add config checks
|
|
|
|
|
cfg = cfg_.am;
|
|
|
|
@ -1308,12 +1283,12 @@ bool rlc_am_lte_rx::configure(rlc_config_t cfg_)
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void rlc_am_lte_rx::reestablish()
|
|
|
|
|
void rlc_am_lte::rlc_am_lte_rx::reestablish()
|
|
|
|
|
{
|
|
|
|
|
stop();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void rlc_am_lte_rx::stop()
|
|
|
|
|
void rlc_am_lte::rlc_am_lte_rx::stop()
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<std::mutex> lock(mutex);
|
|
|
|
|
|
|
|
|
@ -1345,7 +1320,7 @@ void rlc_am_lte_rx::stop()
|
|
|
|
|
* @param nof_bytes Payload length
|
|
|
|
|
* @param header Reference to PDU header (unpacked by caller)
|
|
|
|
|
*/
|
|
|
|
|
void rlc_am_lte_rx::handle_data_pdu(uint8_t* payload, uint32_t nof_bytes, rlc_amd_pdu_header_t& header)
|
|
|
|
|
void rlc_am_lte::rlc_am_lte_rx::handle_data_pdu(uint8_t* payload, uint32_t nof_bytes, rlc_amd_pdu_header_t& header)
|
|
|
|
|
{
|
|
|
|
|
std::map<uint32_t, rlc_amd_rx_pdu>::iterator it;
|
|
|
|
|
|
|
|
|
@ -1462,7 +1437,9 @@ void rlc_am_lte_rx::handle_data_pdu(uint8_t* payload, uint32_t nof_bytes, rlc_am
|
|
|
|
|
debug_state();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void rlc_am_lte_rx::handle_data_pdu_segment(uint8_t* payload, uint32_t nof_bytes, rlc_amd_pdu_header_t& header)
|
|
|
|
|
void rlc_am_lte::rlc_am_lte_rx::handle_data_pdu_segment(uint8_t* payload,
|
|
|
|
|
uint32_t nof_bytes,
|
|
|
|
|
rlc_amd_pdu_header_t& header)
|
|
|
|
|
{
|
|
|
|
|
std::map<uint32_t, rlc_amd_rx_pdu_segments_t>::iterator it;
|
|
|
|
|
|
|
|
|
@ -1550,7 +1527,7 @@ void rlc_am_lte_rx::handle_data_pdu_segment(uint8_t* payload, uint32_t nof_bytes
|
|
|
|
|
debug_state();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void rlc_am_lte_rx::reassemble_rx_sdus()
|
|
|
|
|
void rlc_am_lte::rlc_am_lte_rx::reassemble_rx_sdus()
|
|
|
|
|
{
|
|
|
|
|
uint32_t len = 0;
|
|
|
|
|
if (rx_sdu == NULL) {
|
|
|
|
@ -1701,25 +1678,25 @@ void rlc_am_lte_rx::reassemble_rx_sdus()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void rlc_am_lte_rx::reset_status()
|
|
|
|
|
void rlc_am_lte::rlc_am_lte_rx::reset_status()
|
|
|
|
|
{
|
|
|
|
|
do_status = false;
|
|
|
|
|
poll_received = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool rlc_am_lte_rx::get_do_status()
|
|
|
|
|
bool rlc_am_lte::rlc_am_lte_rx::get_do_status()
|
|
|
|
|
{
|
|
|
|
|
return do_status.load(std::memory_order_relaxed);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void rlc_am_lte_rx::write_pdu(uint8_t* payload, const uint32_t nof_bytes)
|
|
|
|
|
void rlc_am_lte::rlc_am_lte_rx::write_pdu(uint8_t* payload, const uint32_t nof_bytes)
|
|
|
|
|
{
|
|
|
|
|
if (nof_bytes < 1) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (rlc_am_is_control_pdu(payload)) {
|
|
|
|
|
parent->tx.handle_control_pdu(payload, nof_bytes);
|
|
|
|
|
parent->tx->handle_control_pdu(payload, nof_bytes);
|
|
|
|
|
} else {
|
|
|
|
|
std::lock_guard<std::mutex> lock(mutex);
|
|
|
|
|
rlc_amd_pdu_header_t header = {};
|
|
|
|
@ -1737,13 +1714,13 @@ void rlc_am_lte_rx::write_pdu(uint8_t* payload, const uint32_t nof_bytes)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t rlc_am_lte_rx::get_rx_buffered_bytes()
|
|
|
|
|
uint32_t rlc_am_lte::rlc_am_lte_rx::get_rx_buffered_bytes()
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<std::mutex> lock(mutex);
|
|
|
|
|
return rx_window.get_buffered_bytes();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32_t rlc_am_lte_rx::get_sdu_rx_latency_ms()
|
|
|
|
|
uint32_t rlc_am_lte::rlc_am_lte_rx::get_sdu_rx_latency_ms()
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<std::mutex> lock(mutex);
|
|
|
|
|
return sdu_rx_latency_ms.value();
|
|
|
|
@ -1754,7 +1731,7 @@ uint32_t rlc_am_lte_rx::get_sdu_rx_latency_ms()
|
|
|
|
|
*
|
|
|
|
|
* @param timeout_id
|
|
|
|
|
*/
|
|
|
|
|
void rlc_am_lte_rx::timer_expired(uint32_t timeout_id)
|
|
|
|
|
void rlc_am_lte::rlc_am_lte_rx::timer_expired(uint32_t timeout_id)
|
|
|
|
|
{
|
|
|
|
|
std::lock_guard<std::mutex> lock(mutex);
|
|
|
|
|
if (reordering_timer.is_valid() and reordering_timer.id() == timeout_id) {
|
|
|
|
@ -1781,7 +1758,7 @@ void rlc_am_lte_rx::timer_expired(uint32_t timeout_id)
|
|
|
|
|
|
|
|
|
|
// Called from Tx object to pack status PDU that doesn't exceed a given size
|
|
|
|
|
// If lock-acquisition fails, return -1. Otherwise it returns the length of the generated PDU.
|
|
|
|
|
int rlc_am_lte_rx::get_status_pdu(rlc_status_pdu_t* status, const uint32_t max_pdu_size)
|
|
|
|
|
int rlc_am_lte::rlc_am_lte_rx::get_status_pdu(rlc_status_pdu_t* status, const uint32_t max_pdu_size)
|
|
|
|
|
{
|
|
|
|
|
std::unique_lock<std::mutex> lock(mutex, std::try_to_lock);
|
|
|
|
|
if (not lock.owns_lock()) {
|
|
|
|
@ -1834,7 +1811,7 @@ int rlc_am_lte_rx::get_status_pdu(rlc_status_pdu_t* status, const uint32_t max_p
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Called from Tx object to obtain length of the full status PDU
|
|
|
|
|
int rlc_am_lte_rx::get_status_pdu_length()
|
|
|
|
|
int rlc_am_lte::rlc_am_lte_rx::get_status_pdu_length()
|
|
|
|
|
{
|
|
|
|
|
std::unique_lock<std::mutex> lock(mutex, std::try_to_lock);
|
|
|
|
|
if (not lock.owns_lock()) {
|
|
|
|
@ -1852,7 +1829,7 @@ int rlc_am_lte_rx::get_status_pdu_length()
|
|
|
|
|
return rlc_am_packed_length(&status);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void rlc_am_lte_rx::print_rx_segments()
|
|
|
|
|
void rlc_am_lte::rlc_am_lte_rx::print_rx_segments()
|
|
|
|
|
{
|
|
|
|
|
std::map<uint32_t, rlc_amd_rx_pdu_segments_t>::iterator it;
|
|
|
|
|
std::stringstream ss;
|
|
|
|
@ -1868,7 +1845,7 @@ void rlc_am_lte_rx::print_rx_segments()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// NOTE: Preference would be to capture by value, and then move; but header is stack allocated
|
|
|
|
|
bool rlc_am_lte_rx::add_segment_and_check(rlc_amd_rx_pdu_segments_t* pdu, rlc_amd_rx_pdu* segment)
|
|
|
|
|
bool rlc_am_lte::rlc_am_lte_rx::add_segment_and_check(rlc_amd_rx_pdu_segments_t* pdu, rlc_amd_rx_pdu* segment)
|
|
|
|
|
{
|
|
|
|
|
// Find segment insertion point in the list of segments
|
|
|
|
|
auto it1 = pdu->segments.begin();
|
|
|
|
@ -2048,7 +2025,7 @@ bool rlc_am_lte_rx::add_segment_and_check(rlc_amd_rx_pdu_segments_t* pdu, rlc_am
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool rlc_am_lte_rx::inside_rx_window(const int16_t sn)
|
|
|
|
|
bool rlc_am_lte::rlc_am_lte_rx::inside_rx_window(const int16_t sn)
|
|
|
|
|
{
|
|
|
|
|
if (RX_MOD_BASE(sn) >= RX_MOD_BASE(static_cast<int16_t>(vr_r)) && RX_MOD_BASE(sn) < RX_MOD_BASE(vr_mr)) {
|
|
|
|
|
return true;
|
|
|
|
@ -2057,7 +2034,7 @@ bool rlc_am_lte_rx::inside_rx_window(const int16_t sn)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void rlc_am_lte_rx::debug_state()
|
|
|
|
|
void rlc_am_lte::rlc_am_lte_rx::debug_state()
|
|
|
|
|
{
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|