@ -31,8 +31,8 @@
# include <sstream>
# define MOD 1024
# define RX_MOD_BASE(x) (( x-vr_r)%1024)
# define TX_MOD_BASE(x) (( x-vt_a)%1024)
# define RX_MOD_BASE(x) (( ( x) -vr_r)%1024)
# define TX_MOD_BASE(x) (( ( x) -vt_a)%1024)
# define LCID (parent->lcid)
# define RB_NAME (parent->rb_name.c_str())
@ -198,6 +198,7 @@ rlc_am::rlc_am_tx::rlc_am_tx(rlc_am* parent_, uint32_t queue_len_)
, tx_enabled ( false )
{
pthread_mutex_init ( & mutex , NULL ) ;
ZERO_OBJECT ( tx_status ) ;
}
rlc_am : : rlc_am_tx : : ~ rlc_am_tx ( )
@ -209,7 +210,7 @@ void rlc_am::rlc_am_tx::init()
{
log = parent - > log ;
if ( parent - > mac_timers ) {
if ( parent - > mac_timers ! = NULL ) {
poll_retx_timer_id = parent - > mac_timers - > timer_get_unique_id ( ) ;
poll_retx_timer = parent - > mac_timers - > timer_get ( poll_retx_timer_id ) ;
@ -224,10 +225,19 @@ bool rlc_am::rlc_am_tx::configure(srslte_rlc_am_config_t cfg_)
cfg = cfg_ ;
// check timers
if ( not poll_retx_timer or not status_prohibit_timer ) {
if ( poll_retx_timer = = NULL or status_prohibit_timer = = NULL ) {
return false ;
}
// configure timers
if ( cfg . t_status_prohibit > 0 ) {
status_prohibit_timer - > set ( this , static_cast < uint32_t > ( cfg . t_status_prohibit ) ) ;
}
if ( cfg . t_poll_retx > 0 ) {
poll_retx_timer - > set ( this , static_cast < uint32_t > ( cfg . t_poll_retx ) ) ;
}
tx_enabled = true ;
return true ;
@ -239,13 +249,15 @@ void rlc_am::rlc_am_tx::stop()
pthread_mutex_lock ( & mutex ) ;
if ( parent - > mac_timers & & poll_retx_timer ) {
tx_enabled = false ;
if ( parent - > mac_timers ! = NULL & & poll_retx_timer ! = NULL ) {
poll_retx_timer - > stop ( ) ;
parent - > mac_timers - > timer_release_id ( poll_retx_timer_id ) ;
poll_retx_timer = NULL ;
}
if ( parent - > mac_timers && status_prohibit_timer ) {
if ( parent - > mac_timers != NULL && status_prohibit_timer ! = NULL ) {
status_prohibit_timer - > stop ( ) ;
parent - > mac_timers - > timer_release_id ( status_prohibit_timer_id ) ;
status_prohibit_timer = NULL ;
@ -283,7 +295,7 @@ void rlc_am::rlc_am_tx::empty_queue()
}
// deallocate SDU that is currently processed
if ( tx_sdu ) {
if ( tx_sdu ! = NULL ) {
pool - > deallocate ( tx_sdu ) ;
tx_sdu = NULL ;
}
@ -316,7 +328,7 @@ uint32_t rlc_am::rlc_am_tx::get_buffer_state()
}
// Bytes needed for retx
if ( retx_queue. siz e( ) > 0 ) {
if ( not retx_queue. empty ( ) ) {
rlc_amd_retx_t retx = retx_queue . front ( ) ;
log - > debug ( " Buffer state - retx - SN: %d, Segment: %s, %d:%d \n " , retx . sn , retx . is_segment ? " true " : " false " , retx . so_start , retx . so_end ) ;
if ( tx_window . end ( ) ! = tx_window . find ( retx . sn ) ) {
@ -326,7 +338,7 @@ uint32_t rlc_am::rlc_am_tx::get_buffer_state()
retx_queue . pop_front ( ) ;
goto unlock_and_return ;
}
n_bytes = ( uint32_t ) req_bytes ;
n_bytes = static_cast < uint32_t > ( req_bytes ) ;
log - > debug ( " Buffer state - retx: %d bytes \n " , n_bytes ) ;
goto unlock_and_return ;
}
@ -336,7 +348,7 @@ uint32_t rlc_am::rlc_am_tx::get_buffer_state()
if ( tx_window . size ( ) < 1024 ) {
n_sdus = tx_sdu_queue . size ( ) ;
n_bytes = tx_sdu_queue . size_bytes ( ) ;
if ( tx_sdu ) {
if ( tx_sdu ! = NULL ) {
n_sdus + + ;
n_bytes + = tx_sdu - > N_bytes ;
}
@ -371,7 +383,7 @@ uint32_t rlc_am::rlc_am_tx::get_total_buffer_state()
}
// Bytes needed for retx
if ( retx_queue. siz e( ) > 0 ) {
if ( not retx_queue. empty ( ) ) {
rlc_amd_retx_t retx = retx_queue . front ( ) ;
log - > debug ( " Buffer state - retx - SN: %d, Segment: %s, %d:%d \n " , retx . sn , retx . is_segment ? " true " : " false " , retx . so_start , retx . so_end ) ;
if ( tx_window . end ( ) ! = tx_window . find ( retx . sn ) ) {
@ -390,19 +402,19 @@ uint32_t rlc_am::rlc_am_tx::get_total_buffer_state()
if ( tx_window . size ( ) < 1024 ) {
n_sdus = tx_sdu_queue . size ( ) ;
n_bytes + = tx_sdu_queue . size_bytes ( ) ;
if ( tx_sdu )
{
if ( tx_sdu ! = NULL ) {
n_sdus + + ;
n_bytes + = tx_sdu - > N_bytes ;
}
}
// Room needed for header extensions? (integer rounding)
if ( n_sdus > 1 )
if ( n_sdus > 1 ) {
n_bytes + = ( ( n_sdus - 1 ) * 1.5 ) + 0.5 ;
}
// Room needed for fixed header?
if ( n_bytes > 0 ) {
if ( n_bytes > 0 ) {
n_bytes + = 3 ;
log - > debug ( " Buffer state - tx SDUs: %d bytes \n " , n_bytes ) ;
}
@ -417,7 +429,8 @@ void rlc_am::rlc_am_tx::write_sdu(byte_buffer_t *sdu, bool blocking)
byte_buffer_pool : : get_instance ( ) - > deallocate ( sdu ) ;
return ;
}
if ( sdu ) {
if ( sdu ! = NULL ) {
if ( blocking ) {
// block on write to queue
tx_sdu_queue . write ( sdu ) ;
@ -427,7 +440,7 @@ void rlc_am::rlc_am_tx::write_sdu(byte_buffer_t *sdu, bool blocking)
if ( tx_sdu_queue . try_write ( sdu ) ) {
log - > info_hex ( sdu - > msg , sdu - > N_bytes , " %s Tx SDU (%d B, tx_sdu_queue_len=%d) " , RB_NAME , sdu - > N_bytes , tx_sdu_queue . size ( ) ) ;
} else {
log - > info _hex( sdu - > msg , sdu - > N_bytes , " [Dropped SDU] %s Tx SDU (%d B, tx_sdu_queue_len=%d) " , RB_NAME , sdu - > N_bytes , tx_sdu_queue . size ( ) ) ;
log - > debug _hex( sdu - > msg , sdu - > N_bytes , " [Dropped SDU] %s Tx SDU (%d B, tx_sdu_queue_len=%d) " , RB_NAME , sdu - > N_bytes , tx_sdu_queue . size ( ) ) ;
pool - > deallocate ( sdu ) ;
}
}
@ -439,34 +452,30 @@ void rlc_am::rlc_am_tx::write_sdu(byte_buffer_t *sdu, bool blocking)
int rlc_am : : rlc_am_tx : : read_pdu ( uint8_t * payload , uint32_t nof_bytes )
{
pthread_mutex_lock ( & mutex ) ;
int pdu_size = 0 ;
log - > debug ( " MAC opportunity - %d bytes \n " , nof_bytes ) ;
log - > debug ( " tx_window size - %zu PDUs \n " , tx_window . size ( ) ) ;
if ( not tx_enabled ) {
log - > debug ( " RLC entity not active. Not generating PDU. \n " ) ;
goto unlock_and_exit ;
}
// Tx STATUS if requested
if ( do_status ( ) & & not status_prohibited ) {
pdu_size = build_status_pdu ( payload , nof_bytes ) ;
goto unlock_and_exit ;
}
// if tx_window is full and retx_queue empty, retransmit next PDU to be ack'ed
if ( tx_window . size ( ) > = RLC_AM_WINDOW_SIZE & & retx_queue . size ( ) = = 0 ) {
if ( tx_window [ vt_a ] . buf ! = NULL ) {
log - > warning ( " Full Tx window, ReTx'ing first outstanding PDU \n " ) ;
rlc_amd_retx_t retx ;
retx . is_segment = false ;
retx . so_start = 0 ;
retx . so_end = tx_window [ vt_a ] . buf - > N_bytes ;
retx . sn = vt_a ;
retx_queue . push_back ( retx ) ;
} else {
log - > error ( " Found invalid PDU in tx_window. \n " ) ;
}
// Section 5.2.2.3 in TS 36.311, if tx_window is full and retx_queue empty, retransmit random PDU
if ( tx_window . size ( ) > = RLC_AM_WINDOW_SIZE & & retx_queue . empty ( ) ) {
retransmit_random_pdu ( ) ;
}
// RETX if required
if ( retx_queue . siz e( ) > 0 ) {
if ( not retx_queue . empty ( ) ) {
pdu_size = build_retx_pdu ( payload , nof_bytes ) ;
if ( pdu_size > 0 ) {
goto unlock_and_exit ;
@ -485,31 +494,34 @@ unlock_and_exit:
void rlc_am : : rlc_am_tx : : timer_expired ( uint32_t timeout_id )
{
pthread_mutex_lock ( & mutex ) ;
if ( poll_retx_timer & & poll_retx_timer_id = = timeout_id ) {
// if both tx and retx buffer are empty, retransmit next PDU to be ack'ed (Section 5.2.2.3 in TS 36.322)
log - > debug ( " Poll reTx timer expired (lcid=%d) \n " , parent - > lcid ) ;
if ( ( tx_window . size ( ) > 0 & & retx_queue . size ( ) = = 0 & & tx_sdu_queue . size ( ) = = 0 ) ) {
std : : map < uint32_t , rlc_amd_tx_pdu_t > : : iterator it = tx_window . find ( vt_s - 1 ) ;
if ( it ! = tx_window . end ( ) ) {
log - > info ( " Schedule last PDU (SN=%d) for reTx. \n " , vt_s - 1 ) ;
rlc_amd_retx_t retx ;
retx . is_segment = false ;
retx . so_start = 0 ;
retx . so_end = tx_window [ vt_s - 1 ] . buf - > N_bytes ;
retx . sn = vt_s - 1 ;
retx_queue . push_back ( retx ) ;
} else {
log - > error ( " Found invalid PDU in tx_window. \n " ) ;
}
if ( poll_retx_timer ! = NULL & & poll_retx_timer_id = = timeout_id ) {
log - > debug ( " Poll reTx timer expired for LCID=%d after %d ms \n " , parent - > lcid , poll_retx_timer - > get_timeout ( ) ) ;
// Section 5.2.2.3 in TS 36.311, if tx_window is full and retx_queue empty, retransmit random PDU
if ( ( tx_window . size ( ) > = RLC_AM_WINDOW_SIZE & & retx_queue . empty ( ) & & tx_sdu_queue . size ( ) = = 0 ) ) {
retransmit_random_pdu ( ) ;
}
} else
if ( status_prohibit_timer & & status_prohibit_timer_id = = timeout_id ) {
status_prohibited = true ;
status_prohibit_timer - > reset ( ) ;
if ( status_prohibit_timer ! = NULL & & status_prohibit_timer_id = = timeout_id ) {
status_prohibited = false ;
}
pthread_mutex_unlock ( & mutex ) ;
}
void rlc_am : : rlc_am_tx : : retransmit_random_pdu ( )
{
// randomly select PDU in tx window for retransmission
std : : map < uint32_t , rlc_amd_tx_pdu_t > : : iterator it = tx_window . begin ( ) ;
std : : advance ( it , rand ( ) % tx_window . size ( ) ) ;
log - > info ( " Schedule SN=%d for reTx. \n " , it - > first ) ;
rlc_amd_retx_t retx = { } ;
retx . is_segment = false ;
retx . so_start = 0 ;
retx . so_end = it - > second . buf - > N_bytes ;
retx . sn = it - > first ;
retx_queue . push_back ( retx ) ;
}
uint32_t rlc_am : : rlc_am_tx : : get_num_tx_bytes ( )
{
return num_tx_bytes ;
@ -528,25 +540,28 @@ void rlc_am::rlc_am_tx::reset_metrics()
bool rlc_am : : rlc_am_tx : : poll_required ( )
{
if ( cfg . poll_pdu > 0 & & pdu_without_poll > ( uint32_t ) cfg . poll_pdu ) {
if ( cfg . poll_pdu > 0 & & pdu_without_poll > static_cast < uint32_t > ( cfg . poll_pdu ) ) {
return true ;
}
if ( cfg . poll_byte > 0 & & byte_without_poll > ( uint32_t ) cfg . poll_byte ) {
if ( cfg . poll_byte > 0 & & byte_without_poll > static_cast < uint32_t > ( cfg . poll_byte ) ) {
return true ;
}
if ( poll_retx_timer ) {
if ( poll_retx_timer ! = NULL ) {
if ( poll_retx_timer - > is_expired ( ) ) {
// re-arm timer
// re-arm timer (will be stopped when status PDU is received)
poll_retx_timer - > reset ( ) ;
poll_retx_timer - > set ( this , cfg . t_poll_retx ) ;
poll_retx_timer - > run ( ) ;
return true ;
}
}
if ( tx_sdu_queue . size ( ) = = 0 & & retx_queue . size ( ) = = 0 ) {
if ( tx_window . size ( ) > = RLC_AM_WINDOW_SIZE ) {
return true ;
}
if ( tx_sdu_queue . size ( ) = = 0 & & retx_queue . empty ( ) ) {
return true ;
}
@ -565,25 +580,28 @@ bool rlc_am::rlc_am_tx::poll_required()
int rlc_am : : rlc_am_tx : : build_status_pdu ( uint8_t * payload , uint32_t nof_bytes )
{
int pdu_len = parent - > rx . get_status ( & tx_status ) ;
if ( pdu_len > 0 & & nof_bytes > = ( uint32_t ) pdu_len )
{
if ( pdu_len > 0 & & nof_bytes > = static_cast < uint32_t > ( pdu_len ) ) {
log - > info ( " %s Tx status PDU - %s \n " ,
RB_NAME , rlc_am_to_string ( & tx_status ) . c_str ( ) ) ;
parent - > rx . reset_status ( ) ;
if ( cfg . t_status_prohibit > 0 & & status_prohibit_timer ) {
status_prohibited = false ;
status_prohibit_timer - > set ( this , cfg . t_status_prohibit ) ;
if ( cfg . t_status_prohibit > 0 & & status_prohibit_timer ! = NULL ) {
status_prohibited = true ;
// re-arm timer
status_prohibit_timer - > reset ( ) ;
status_prohibit_timer - > run ( ) ;
}
debug_state ( ) ;
return rlc_am_write_status_pdu( & tx_status , payload ) ;
} else {
pdu_len = rlc_am_write_status_pdu( & tx_status , payload ) ;
} else {
log - > warning ( " %s Cannot tx status PDU - %d bytes available, %d bytes required \n " ,
RB_NAME , nof_bytes , pdu_len ) ;
return 0 ;
pdu_len = 0 ;
}
return pdu_len ;
}
int rlc_am : : rlc_am_tx : : build_retx_pdu ( uint8_t * payload , uint32_t nof_bytes )
@ -614,7 +632,8 @@ int rlc_am::rlc_am_tx::build_retx_pdu(uint8_t *payload, uint32_t nof_bytes)
retx_queue . pop_front ( ) ;
return - 1 ;
}
if ( retx . is_segment | | req_size > ( int ) nof_bytes ) {
if ( retx . is_segment | | req_size > static_cast < int > ( nof_bytes ) ) {
log - > debug ( " %s build_retx_pdu - resegmentation required \n " , RB_NAME ) ;
return build_segment ( payload , nof_bytes , retx ) ;
}
@ -633,8 +652,8 @@ int rlc_am::rlc_am_tx::build_retx_pdu(uint8_t *payload, uint32_t nof_bytes)
poll_sn = vt_s ;
pdu_without_poll = 0 ;
byte_without_poll = 0 ;
if ( poll_retx_timer ) {
poll_retx_timer - > set( this , cfg . t_poll_retx ) ;
if ( poll_retx_timer ! = NULL ) {
poll_retx_timer - > re set( ) ;
poll_retx_timer - > run ( ) ;
}
}
@ -646,6 +665,8 @@ int rlc_am::rlc_am_tx::build_retx_pdu(uint8_t *payload, uint32_t nof_bytes)
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 PDU %d \n " ,
RB_NAME , tx_window [ retx . sn ] . retx_count , retx . sn ) ;
parent - > rrc - > max_retx_attempted ( ) ;
}
@ -656,15 +677,14 @@ int rlc_am::rlc_am_tx::build_retx_pdu(uint8_t *payload, uint32_t nof_bytes)
return ( ptr - payload ) + tx_window [ retx . sn ] . buf - > N_bytes ;
}
int rlc_am : : rlc_am_tx : : build_segment ( uint8_t * payload , uint32_t nof_bytes , rlc_amd_retx_t retx )
{
if ( ! tx_window [ retx . sn ] . buf ) {
int rlc_am : : rlc_am_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 ) ;
return 0 ;
}
if ( ! retx . is_segment ) {
if ( ! retx . is_segment ) {
retx . so_start = 0 ;
retx . so_end = tx_window [ retx . sn ] . buf - > N_bytes ;
retx . so_end = tx_window [ retx . sn ] . buf - > N_bytes ;
}
// Construct new header
@ -676,28 +696,27 @@ int rlc_am::rlc_am_tx::build_segment(uint8_t *payload, uint32_t nof_bytes, rlc_a
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 ) ;
new_header . dc = RLC_DC_FIELD_DATA_PDU ;
new_header . rf = 1 ;
new_header . fi = RLC_FI_FIELD_NOT_START_OR_END_ALIGNED ;
new_header . sn = old_header . sn ;
new_header . lsf = 0 ;
new_header . so = retx . so_start ;
new_header . dc = RLC_DC_FIELD_DATA_PDU ;
new_header . rf = 1 ;
new_header . fi = RLC_FI_FIELD_NOT_START_OR_END_ALIGNED ;
new_header . sn = old_header . sn ;
new_header . lsf = 0 ;
new_header . so = retx . so_start ;
new_header . N_li = 0 ;
new_header . p = 0 ;
if ( poll_required ( ) )
{
new_header . p = 0 ;
if ( poll_required ( ) ) {
log - > debug ( " %s setting poll bit to request status \n " , RB_NAME ) ;
new_header . p = 1 ;
poll_sn = vt_s ;
pdu_without_poll = 0 ;
new_header . p = 1 ;
poll_sn = vt_s ;
pdu_without_poll = 0 ;
byte_without_poll = 0 ;
if ( poll_retx_timer ) {
poll_retx_timer - > set( this , cfg . t_poll_retx ) ;
if ( poll_retx_timer ! = NULL ) {
poll_retx_timer - > re set( ) ;
poll_retx_timer - > run ( ) ;
}
}
uint32_t head_len = 0 ;
uint32_t head_len = 0 ;
uint32_t pdu_space = 0 ;
head_len = rlc_am_packed_length ( & new_header ) ;
@ -706,48 +725,55 @@ int rlc_am::rlc_am_tx::build_segment(uint8_t *payload, uint32_t nof_bytes, rlc_a
head_len + = 2 ;
}
if ( nof_bytes < = head_len )
{
if ( nof_bytes < = head_len ) {
log - > warning ( " %s Cannot build a PDU segment - %d bytes available, %d bytes required for header \n " ,
RB_NAME , nof_bytes , head_len ) ;
return 0 ;
}
pdu_space = nof_bytes - head_len ;
if ( pdu_space < ( retx . so_end - retx . so_start ) )
retx . so_end = retx . so_start + pdu_space ;
pdu_space = nof_bytes - head_len ;
if ( pdu_space < ( retx . so_end - retx . so_start ) ) {
retx . so_end = retx . so_start + pdu_space ;
}
// Need to rebuild the li table & update fi based on so_start and so_end
if ( retx . so_start = = 0 & & rlc_am_start_aligned ( old_header . fi ) )
if ( retx . so_start = = 0 & & rlc_am_start_aligned ( old_header . fi ) ) {
new_header . fi & = RLC_FI_FIELD_NOT_END_ALIGNED ; // segment is start aligned
}
uint32_t lower = 0 ;
uint32_t upper = 0 ;
uint32_t li = 0 ;
for ( uint32_t i = 0 ; i < old_header . N_li ; i + + ) {
if ( lower > = retx . so_end )
if ( lower > = retx . so_end ) {
break ;
}
if ( pdu_space < = 2 )
if ( pdu_space < = 2 ) {
break ;
}
upper + = old_header . li [ i ] ;
head_len = rlc_am_packed_length ( & new_header ) ;
pdu_space = nof_bytes - head_len ;
if ( pdu_space < ( retx . so_end - retx . so_start ) )
retx . so_end = retx . so_start + pdu_space ;
if ( pdu_space < ( retx . so_end - retx . so_start ) ) {
retx . so_end = retx . so_start + pdu_space ;
}
if ( upper > retx . so_start & & lower < retx . so_end ) { // Current SDU is needed
li = upper - lower ;
if ( upper > retx . so_end )
if ( upper > retx . so_end ) {
li - = upper - retx . so_end ;
if ( lower < retx . so_start )
}
if ( lower < retx . so_start ) {
li - = retx . so_start - lower ;
if ( lower > 0 & & lower = = retx . so_start )
}
if ( lower > 0 & & lower = = retx . so_start ) {
new_header . fi & = RLC_FI_FIELD_NOT_END_ALIGNED ; // segment start is aligned with this SDU
if ( upper = = retx . so_end ) {
}
if ( upper = = retx . so_end ) {
new_header . fi & = RLC_FI_FIELD_NOT_START_ALIGNED ; // segment end is aligned with this SDU
}
new_header . li [ new_header . N_li + + ] = li ;
@ -767,15 +793,17 @@ int rlc_am::rlc_am_tx::build_segment(uint8_t *payload, uint32_t nof_bytes, rlc_a
if ( tx_window [ retx . sn ] . buf - > N_bytes = = retx . so_end ) {
retx_queue . pop_front ( ) ;
new_header . lsf = 1 ;
if ( rlc_am_end_aligned ( old_header . fi ) )
if ( rlc_am_end_aligned ( old_header . fi ) ) {
new_header . fi & = RLC_FI_FIELD_NOT_START_ALIGNED ; // segment is end aligned
}
} else if ( retx_queue . front ( ) . so_end = = retx . so_end ) {
retx_queue . pop_front ( ) ;
} else {
retx_queue . front ( ) . is_segment = true ;
retx_queue . front ( ) . so_start = retx . so_end ;
if ( new_header . N_li > 0 )
if ( new_header . N_li > 0 ) {
new_header . N_li - - ;
}
}
// Write header and pdu
@ -790,7 +818,7 @@ int rlc_am::rlc_am_tx::build_segment(uint8_t *payload, uint32_t nof_bytes, rlc_a
debug_state ( ) ;
int pdu_len = ( ptr - payload ) + len ;
if ( pdu_len > ( int ) nof_bytes ) {
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 ) ;
log - > debug ( " %s Retx PDU segment length error. Header len: %ld, Payload len: %d, N_li: %d \n " ,
@ -802,20 +830,20 @@ int rlc_am::rlc_am_tx::build_segment(uint8_t *payload, uint32_t nof_bytes, rlc_a
int rlc_am : : rlc_am_tx : : build_data_pdu ( uint8_t * payload , uint32_t nof_bytes )
{
if ( ! tx_sdu & & tx_sdu_queue . size ( ) = = 0 )
if ( tx_sdu = = NULL & & tx_sdu_queue . size ( ) = = 0 )
{
log - > info ( " No data available to be sent \n " ) ;
return 0 ;
}
// do not build any more PDU if window is already full
if ( ! tx_sdu & & tx_window . size ( ) > = RLC_AM_WINDOW_SIZE ) {
if ( tx_sdu = = NULL & & tx_window . size ( ) > = RLC_AM_WINDOW_SIZE ) {
log - > info ( " Tx window full. \n " ) ;
return 0 ;
}
byte_buffer_t * pdu = pool_allocate_blocking ;
if ( ! pdu ) {
if ( pdu = = NULL ) {
# ifdef RLC_AM_BUFFER_DEBUG
log - > console ( " Fatal Error: Could not allocate PDU in build_data_pdu() \n " ) ;
log - > console ( " tx_window size: %d PDUs \n " , tx_window . size ( ) ) ;
@ -862,8 +890,7 @@ int rlc_am::rlc_am_tx::build_data_pdu(uint8_t *payload, uint32_t nof_bytes)
RB_NAME , pdu_space , head_len ) ;
// Check for SDU segment
if ( tx_sdu )
{
if ( tx_sdu ! = NULL ) {
to_move = ( ( pdu_space - head_len ) > = tx_sdu - > N_bytes ) ? tx_sdu - > N_bytes : pdu_space - head_len ;
memcpy ( pdu_ptr , tx_sdu - > msg , to_move ) ;
last_li = to_move ;
@ -878,10 +905,11 @@ int rlc_am::rlc_am_tx::build_data_pdu(uint8_t *payload, uint32_t nof_bytes)
pool - > deallocate ( tx_sdu ) ;
tx_sdu = NULL ;
}
if ( pdu_space > to_move )
if ( pdu_space > to_move ) {
pdu_space - = to_move ;
else
} else {
pdu_space = 0 ;
}
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 " ,
@ -889,12 +917,12 @@ int rlc_am::rlc_am_tx::build_data_pdu(uint8_t *payload, uint32_t nof_bytes)
}
// Pull SDUs from queue
while ( pdu_space > head_len + 1 & & tx_sdu_queue . size ( ) > 0 )
{
if ( last_li > 0 )
while ( pdu_space > head_len + 1 & & tx_sdu_queue . size ( ) > 0 ) {
if ( last_li > 0 ) {
header . li [ header . N_li + + ] = last_li ;
}
head_len = rlc_am_packed_length ( & header ) ;
if ( head_len > = pdu_space ) {
if ( head_len > = pdu_space ) {
header . N_li - - ;
break ;
}
@ -913,10 +941,11 @@ int rlc_am::rlc_am_tx::build_data_pdu(uint8_t *payload, uint32_t nof_bytes)
pool - > deallocate ( tx_sdu ) ;
tx_sdu = NULL ;
}
if ( pdu_space > to_move )
if ( pdu_space > to_move ) {
pdu_space - = to_move ;
else
} else {
pdu_space = 0 ;
}
log - > debug ( " %s Building PDU - added SDU segment (len:%d) - pdu_space: %d, head_len: %d \n " ,
RB_NAME , to_move , pdu_space , head_len ) ;
@ -928,8 +957,9 @@ int rlc_am::rlc_am_tx::build_data_pdu(uint8_t *payload, uint32_t nof_bytes)
return 0 ;
}
if ( tx_sdu )
if ( tx_sdu ! = NULL ) {
header . fi | = RLC_FI_FIELD_NOT_END_ALIGNED ; // Last byte does not correspond to last byte of SDU
}
// Set Poll bit
pdu_without_poll + + ;
@ -943,8 +973,8 @@ int rlc_am::rlc_am_tx::build_data_pdu(uint8_t *payload, uint32_t nof_bytes)
poll_sn = vt_s ;
pdu_without_poll = 0 ;
byte_without_poll = 0 ;
if ( poll_retx_timer ) {
poll_retx_timer - > set( this , cfg . t_poll_retx ) ;
if ( poll_retx_timer ! = NULL ) {
poll_retx_timer - > re set( ) ;
poll_retx_timer - > run ( ) ;
}
}
@ -979,7 +1009,7 @@ void rlc_am::rlc_am_tx::handle_control_pdu(uint8_t *payload, uint32_t nof_bytes)
log - > info ( " %s Rx Status PDU: %s \n " , RB_NAME , rlc_am_to_string ( & status ) . c_str ( ) ) ;
if ( poll_retx_timer ) {
if ( poll_retx_timer ! = NULL ) {
poll_retx_timer - > reset ( ) ;
}
@ -1005,7 +1035,8 @@ void rlc_am::rlc_am_tx::handle_control_pdu(uint8_t *payload, uint32_t nof_bytes)
if ( tx_window . end ( ) ! = it )
{
if ( ! retx_queue_has_sn ( i ) ) {
rlc_amd_retx_t retx ;
rlc_amd_retx_t retx = { } ;
retx . sn = i ;
retx . is_segment = false ;
retx . so_start = 0 ;
retx . so_end = it - > second . buf - > N_bytes ;
@ -1036,8 +1067,6 @@ void rlc_am::rlc_am_tx::handle_control_pdu(uint8_t *payload, uint32_t nof_bytes)
RB_NAME , i , status . nacks [ j ] . so_start , status . nacks [ j ] . so_end , it - > second . buf - > N_bytes ) ;
}
}
retx . sn = i ;
retx_queue . push_back ( retx ) ;
}
}
@ -1050,7 +1079,7 @@ void rlc_am::rlc_am_tx::handle_control_pdu(uint8_t *payload, uint32_t nof_bytes)
it = tx_window . find ( i ) ;
if ( it ! = tx_window . end ( ) ) {
if ( update_vt_a ) {
if ( it - > second . buf ) {
if ( it - > second . buf ! = NULL ) {
pool - > deallocate ( it - > second . buf ) ;
it - > second . buf = 0 ;
}
@ -1080,7 +1109,7 @@ void rlc_am::rlc_am_tx::debug_state()
int rlc_am : : rlc_am_tx : : required_buffer_size ( rlc_amd_retx_t retx )
{
if ( ! retx . is_segment ) {
if ( tx_window . count ( retx . sn ) ) {
if ( tx_window . count ( retx . sn ) = = 1 ) {
if ( tx_window [ retx . sn ] . buf ) {
return rlc_am_packed_length ( & tx_window [ retx . sn ] . header ) + tx_window [ retx . sn ] . buf - > N_bytes ;
} else {
@ -1106,33 +1135,34 @@ int rlc_am::rlc_am_tx::required_buffer_size(rlc_amd_retx_t retx)
new_header . so = retx . so_start ;
new_header . N_li = 0 ;
uint32_t head_len = 0 ;
// Need to rebuild the li table & update fi based on so_start and so_end
if ( retx . so_start ! = 0 & & rlc_am_start_aligned ( old_header . fi ) )
if ( retx . so_start ! = 0 & & rlc_am_start_aligned ( old_header . fi ) ) {
new_header . fi & = RLC_FI_FIELD_NOT_END_ALIGNED ; // segment is start aligned
}
uint32_t lower = 0 ;
uint32_t upper = 0 ;
uint32_t li = 0 ;
for ( uint32_t i = 0 ; i < old_header . N_li ; i + + ) {
if ( lower > = retx . so_end )
if ( lower > = retx . so_end ) {
break ;
}
upper + = old_header . li [ i ] ;
head_len = rlc_am_packed_length ( & new_header ) ;
if ( upper > retx . so_start & & lower < retx . so_end ) { // Current SDU is needed
if ( upper > retx . so_start & & lower < retx . so_end ) { // Current SDU is needed
li = upper - lower ;
if ( upper > retx . so_end )
if ( upper > retx . so_end ) {
li - = upper - retx . so_end ;
if ( lower < retx . so_start )
}
if ( lower < retx . so_start ) {
li - = retx . so_start - lower ;
if ( lower > 0 & & lower = = retx . so_start )
}
if ( lower > 0 & & lower = = retx . so_start ) {
new_header . fi & = RLC_FI_FIELD_NOT_END_ALIGNED ; // segment start is aligned with this SDU
if ( upper = = retx . so_end ) {
}
if ( upper = = retx . so_end ) {
new_header . fi & = RLC_FI_FIELD_NOT_START_ALIGNED ; // segment end is aligned with this SDU
}
new_header . li [ new_header . N_li + + ] = li ;
@ -1152,9 +1182,10 @@ int rlc_am::rlc_am_tx::required_buffer_size(rlc_amd_retx_t retx)
bool rlc_am : : rlc_am_tx : : retx_queue_has_sn ( uint32_t sn )
{
std : : deque < rlc_amd_retx_t > : : iterator q_it ;
for ( q_it = retx_queue . begin ( ) ; q_it ! = retx_queue . end ( ) ; q_it + + ) {
if ( q_it - > sn = = sn )
for ( q_it = retx_queue . begin ( ) ; q_it ! = retx_queue . end ( ) ; + + q_it ) {
if ( q_it - > sn = = sn ) {
return true ;
}
}
return false ;
}
@ -1192,8 +1223,8 @@ rlc_am::rlc_am_rx::~rlc_am_rx()
void rlc_am : : rlc_am_rx : : init ( )
{
log = parent - > log ;
if ( parent - > mac_timers ) {
log = parent - > log ;
if ( parent - > mac_timers ! = NULL ) {
reordering_timer_id = parent - > mac_timers - > timer_get_unique_id ( ) ;
reordering_timer = parent - > mac_timers - > timer_get ( reordering_timer_id ) ;
}
@ -1205,10 +1236,15 @@ bool rlc_am::rlc_am_rx::configure(srslte_rlc_am_config_t cfg_)
cfg = cfg_ ;
// check timers
if ( not reordering_timer) {
if ( reordering_timer = = NULL ) {
return false ;
}
// configure timer
if ( cfg . t_reordering > 0 ) {
reordering_timer - > set ( this , static_cast < uint32_t > ( cfg . t_reordering ) ) ;
}
return true ;
}
@ -1221,13 +1257,13 @@ void rlc_am::rlc_am_rx::stop()
{
pthread_mutex_lock ( & mutex ) ;
if ( parent - > mac_timers && reordering_timer ) {
if ( parent - > mac_timers != NULL && reordering_timer ! = NULL ) {
reordering_timer - > stop ( ) ;
parent - > mac_timers - > timer_release_id ( reordering_timer_id ) ;
reordering_timer = NULL ;
}
if ( rx_sdu ) {
if ( rx_sdu ! = NULL ) {
pool - > deallocate ( rx_sdu ) ;
rx_sdu = NULL ;
}
@ -1269,7 +1305,10 @@ void rlc_am::rlc_am_rx::handle_data_pdu(uint8_t *payload, uint32_t nof_bytes, rl
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), %s " ,
RB_NAME , header . sn , nof_bytes , rlc_fi_field_text [ header . fi ] ) ;
RB_NAME ,
header . sn ,
nof_bytes ,
rlc_fi_field_text [ header . fi ] ) ;
if ( ! inside_rx_window ( header . sn ) ) {
if ( header . p ) {
@ -1295,7 +1334,7 @@ void rlc_am::rlc_am_rx::handle_data_pdu(uint8_t *payload, uint32_t nof_bytes, rl
// Write to rx window
rlc_amd_rx_pdu_t pdu ;
pdu . buf = pool_allocate_blocking ;
if ( ! pdu . buf ) {
if ( pdu . buf = = NULL ) {
# ifdef RLC_AM_BUFFER_DEBUG
log - > console ( " Fatal Error: Couldn't allocate PDU in handle_data_pdu(). \n " ) ;
exit ( - 1 ) ;
@ -1331,7 +1370,7 @@ void rlc_am::rlc_am_rx::handle_data_pdu(uint8_t *payload, uint32_t nof_bytes, rl
}
// Check poll bit
if ( header . p ) {
if ( header . p ) {
log - > info ( " %s Status packet requested through polling bit \n " , RB_NAME ) ;
poll_received = true ;
@ -1348,7 +1387,7 @@ void rlc_am::rlc_am_rx::handle_data_pdu(uint8_t *payload, uint32_t nof_bytes, rl
reassemble_rx_sdus ( ) ;
// Update reordering variables and timers (36.322 v10.0.0 Section 5.1.3.2.3)
if ( reordering_timer ) {
if ( reordering_timer ! = NULL ) {
if ( reordering_timer - > is_running ( ) ) {
if ( vr_x = = vr_r | | ( ! inside_rx_window ( vr_x ) & & vr_x ! = vr_mr ) ) {
reordering_timer - > reset ( ) ;
@ -1357,7 +1396,7 @@ void rlc_am::rlc_am_rx::handle_data_pdu(uint8_t *payload, uint32_t nof_bytes, rl
if ( not reordering_timer - > is_running ( ) ) {
if ( RX_MOD_BASE ( vr_h ) > RX_MOD_BASE ( vr_r ) ) {
reordering_timer - > set( this , cfg . t_reordering ) ;
reordering_timer - > re set( ) ;
reordering_timer - > run ( ) ;
vr_x = vr_h ;
}
@ -1388,7 +1427,7 @@ void rlc_am::rlc_am_rx::handle_data_pdu_segment(uint8_t *payload, uint32_t nof_b
rlc_amd_rx_pdu_t segment ;
segment . buf = pool_allocate_blocking ;
if ( ! segment . buf ) {
if ( segment . buf = = NULL ) {
# ifdef RLC_AM_BUFFER_DEBUG
log - > console ( " Fatal Error: Couldn't allocate PDU in handle_data_pdu_segment(). \n " ) ;
exit ( - 1 ) ;
@ -1429,14 +1468,13 @@ void rlc_am::rlc_am_rx::handle_data_pdu_segment(uint8_t *payload, uint32_t nof_b
pdu . segments . push_back ( segment ) ;
rx_segments [ header . sn ] = pdu ;
// Update vr_h
if ( RX_MOD_BASE ( header . sn ) > = RX_MOD_BASE ( vr_h ) )
vr_h = ( header . sn + 1 ) % MOD ;
if ( RX_MOD_BASE ( header . sn ) > = RX_MOD_BASE ( vr_h ) ) {
vr_h = ( header . sn + 1 ) % MOD ;
}
// Check poll bit
if ( header . p )
{
if ( header . p ) {
log - > info ( " %s Status packet requested through polling bit \n " , RB_NAME ) ;
poll_received = true ;
@ -1459,9 +1497,9 @@ void rlc_am::rlc_am_rx::handle_data_pdu_segment(uint8_t *payload, uint32_t nof_b
void rlc_am : : rlc_am_rx : : reassemble_rx_sdus ( )
{
uint32_t len = 0 ;
if ( ! rx_sdu ) {
if ( rx_sdu = = NULL ) {
rx_sdu = pool_allocate_blocking ;
if ( ! rx_sdu ) {
if ( rx_sdu = = NULL ) {
# ifdef RLC_AM_BUFFER_DEBUG
log - > console ( " Fatal Error: Could not allocate PDU in reassemble_rx_sdus() (1) \n " ) ;
exit ( - 1 ) ;
@ -1495,7 +1533,7 @@ void rlc_am::rlc_am_rx::reassemble_rx_sdus()
parent - > pdcp - > write_pdu ( parent - > lcid , rx_sdu ) ;
rx_sdu = pool_allocate_blocking ;
if ( ! rx_sdu ) {
if ( rx_sdu = = NULL ) {
# ifdef RLC_AM_BUFFER_DEBUG
log - > console ( " Fatal Error: Could not allocate PDU in reassemble_rx_sdus() (2) \n " ) ;
exit ( - 1 ) ;
@ -1528,12 +1566,12 @@ void rlc_am::rlc_am_rx::reassemble_rx_sdus()
rx_window . erase ( vr_r ) ;
}
if ( rlc_am_end_aligned ( rx_window [ vr_r ] . header . fi ) ) {
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 ) ;
rx_sdu - > set_timestamp ( ) ;
parent - > pdcp - > write_pdu ( parent - > lcid , rx_sdu ) ;
rx_sdu = pool_allocate_blocking ;
if ( ! rx_sdu ) {
if ( rx_sdu = = NULL ) {
# ifdef RLC_AM_BUFFER_DEBUG
log - > console ( " Fatal Error: Could not allocate PDU in reassemble_rx_sdus() (3) \n " ) ;
exit ( - 1 ) ;
@ -1604,7 +1642,7 @@ void rlc_am::rlc_am_rx::write_pdu(uint8_t *payload, uint32_t nof_bytes)
void rlc_am : : rlc_am_rx : : timer_expired ( uint32_t timeout_id )
{
pthread_mutex_lock ( & mutex ) ;
if ( reordering_timer && reordering_timer_id = = timeout_id ) {
if ( reordering_timer != NULL && reordering_timer_id = = timeout_id ) {
reordering_timer - > reset ( ) ;
log - > debug ( " %s reordering timeout expiry - updating vr_ms \n " , RB_NAME ) ;
@ -1621,7 +1659,7 @@ void rlc_am::rlc_am_rx::timer_expired(uint32_t timeout_id)
}
if ( RX_MOD_BASE ( vr_h ) > RX_MOD_BASE ( vr_ms ) ) {
reordering_timer - > set( this , cfg . t_reordering ) ;
reordering_timer - > re set( ) ;
reordering_timer - > run ( ) ;
vr_x = vr_h ;
}
@ -1640,9 +1678,10 @@ int rlc_am::rlc_am_rx::get_status(rlc_status_pdu_t* status)
// We don't use segment NACKs - just NACK the full PDU
uint32_t i = vr_r ;
while ( RX_MOD_BASE ( i ) < RX_MOD_BASE ( vr_ms ) ) {
while ( RX_MOD_BASE ( i ) < RX_MOD_BASE ( vr_ms ) & & status - > N_nack < RLC_AM_WINDOW_SIZE ) {
if ( rx_window . find ( i ) = = rx_window . end ( ) ) {
status - > nacks [ status - > N_nack + + ] . nack_sn = i ;
status - > nacks [ status - > N_nack ] . nack_sn = i ;
status - > N_nack + + ;
}
i = ( i + 1 ) % MOD ;
}
@ -1694,12 +1733,14 @@ bool rlc_am::rlc_am_rx::add_segment_and_check(rlc_amd_rx_pdu_segments_t *pdu, rl
uint32_t so = 0 ;
std : : list < rlc_amd_rx_pdu_t > : : iterator it , tmpit ;
for ( it = pdu - > segments . begin ( ) ; it ! = pdu - > segments . end ( ) ; it + + ) {
if ( so ! = it - > header . so )
if ( so ! = it - > header . so ) {
return false ;
}
so + = it - > buf - > N_bytes ;
}
if ( ! pdu - > segments . back ( ) . header . lsf )
if ( ! pdu - > segments . back ( ) . header . lsf ) {
return false ;
}
// We have all segments of the PDU - reconstruct and handle
rlc_amd_pdu_header_t header ;
@ -1745,7 +1786,7 @@ bool rlc_am::rlc_am_rx::add_segment_and_check(rlc_amd_rx_pdu_segments_t *pdu, rl
// Copy data
byte_buffer_t * full_pdu = pool_allocate_blocking ;
if ( ! full_pdu ) {
if ( full_pdu = = NULL ) {
# ifdef RLC_AM_BUFFER_DEBUG
log - > console ( " Fatal Error: Could not allocate PDU in add_segment_and_check() \n " ) ;
exit ( - 1 ) ;
@ -1801,14 +1842,14 @@ void rlc_am_read_data_pdu_header(uint8_t **payload, uint32_t *nof_bytes, rlc_amd
uint8_t ext ;
uint8_t * ptr = * payload ;
header - > dc = ( rlc_dc_field_t ) ( ( * ptr > > 7 ) & 0x01 ) ;
header - > dc = static_cast < rlc_dc_field_t > ( ( * ptr > > 7 ) & 0x01 ) ;
if ( RLC_DC_FIELD_DATA_PDU = = header - > dc )
{
// Fixed part
header - > rf = ( ( * ptr > > 6 ) & 0x01 ) ;
header - > p = ( ( * ptr > > 5 ) & 0x01 ) ;
header - > fi = ( rlc_fi_field_t ) ( ( * ptr > > 3 ) & 0x03 ) ;
header - > fi = static_cast < rlc_fi_field_t > ( ( * ptr > > 3 ) & 0x03 ) ;
ext = ( ( * ptr > > 2 ) & 0x01 ) ;
header - > sn = ( * ptr & 0x03 ) < < 8 ; // 2 bits SN
ptr + + ;
@ -1848,8 +1889,9 @@ void rlc_am_read_data_pdu_header(uint8_t **payload, uint32_t *nof_bytes, rlc_amd
}
// Account for padding if N_li is odd
if ( header - > N_li % 2 = = 1 )
if ( header - > N_li % 2 = = 1 ) {
ptr + + ;
}
* nof_bytes - = ptr - * payload ;
* payload = ptr ;
@ -1885,7 +1927,7 @@ void rlc_am_write_data_pdu_header(rlc_amd_pdu_header_t *header, uint8_t **payloa
ptr + + ;
// Segment part
if ( header - > rf )
if ( header - > rf )
{
* ptr = ( header - > lsf & 0x01 ) < < 7 ;
* ptr | = ( header - > so & 0x7F00 ) > > 8 ; // 7 bits of SO
@ -1916,8 +1958,9 @@ void rlc_am_write_data_pdu_header(rlc_amd_pdu_header_t *header, uint8_t **payloa
}
}
// Pad if N_li is odd
if ( header - > N_li % 2 = = 1 )
if ( header - > N_li % 2 = = 1 ) {
ptr + + ;
}
* payload = ptr ;
}
@ -1937,7 +1980,7 @@ void rlc_am_read_status_pdu(uint8_t *payload, uint32_t nof_bytes, rlc_status_pdu
srslte_bit_unpack_vector ( payload , tmp . msg , nof_bytes * 8 ) ;
tmp . N_bits = nof_bytes * 8 ;
rlc_dc_field_t dc = ( rlc_dc_field_t ) srslte_bit_pack ( & ptr , 1 ) ;
rlc_dc_field_t dc = static_cast < rlc_dc_field_t > ( srslte_bit_pack ( & ptr , 1 ) ) ;
if ( RLC_DC_FIELD_CONTROL_PDU = = dc )
{
@ -2009,7 +2052,9 @@ int rlc_am_write_status_pdu(rlc_status_pdu_t *status, uint8_t *payload)
uint32_t rlc_am_packed_length ( rlc_amd_pdu_header_t * header )
{
uint32_t len = 2 ; // Fixed part is 2 bytes
if ( header - > rf ) len + = 2 ; // Segment header is 2 bytes
if ( header - > rf ) {
len + = 2 ; // Segment header is 2 bytes
}
len + = header - > N_li * 1.5 + 0.5 ; // Extension part - integer rounding up
return len ;
}
@ -2086,4 +2131,4 @@ bool rlc_am_not_start_aligned(const uint8_t fi)
return ( fi = = RLC_FI_FIELD_NOT_START_ALIGNED | | fi = = RLC_FI_FIELD_NOT_START_OR_END_ALIGNED ) ;
}
} // namespace srs u e
} // namespace srs lt e