Merge remote-tracking branch 'origin/fix_ntn_reestablishment' into integration_2025_wk26 (!3360)

NR UE: fix reestablishment for NTN

With these changes in place we should extend the NTN/GEO rfsim CI test
to include reestablishment, too.
This commit is contained in:
Robert Schmidt
2025-06-30 18:39:40 +02:00
6 changed files with 81 additions and 28 deletions
@@ -195,6 +195,15 @@ gNBs =
}
);
rlc = {
srb = {
t_poll_retransmit = "ms2000"
}
drb_am = {
t_poll_retransmit = "ms2000"
}
}
MACRLCs = (
{
num_cc = 1;
@@ -33,6 +33,11 @@
000003
020001
020002
040001
020022
040002
020001
020002
100001
222222
</TestCaseRequestedList>
@@ -98,6 +103,33 @@
<ping_packetloss_threshold>5</ping_packetloss_threshold>
</testCase>
<testCase id="040001">
<class>Custom_Command</class>
<desc>Trigger Reestablishment</desc>
<node>cacofonix</node>
<command>echo ci force_reestab | nc 192.168.71.140 9090 | grep -E 'Reset RLC counters of UE RNTI [0-9a-f]{4} to trigger reestablishment'</command>
<command_fail>yes</command_fail>
</testCase>
<testCase id="020022">
<class>Ping</class>
<desc>Ping ext-dn from NR-UE</desc>
<id>rfsim5g_ue</id>
<nodes>cacofonix</nodes>
<svr_id>rfsim5g_ext_dn</svr_id>
<svr_node>cacofonix</svr_node>
<ping_args>-c 20 -i0.5 -w25</ping_args>
<ping_packetloss_threshold>80</ping_packetloss_threshold>
</testCase>
<testCase id="040002">
<class>Custom_Command</class>
<desc>Verify Reestablishment</desc>
<node>cacofonix</node>
<command>echo ci get_reestab_count | nc 192.168.71.140 9090 | grep -E 'UE RNTI [0-9a-f]{4} reestab 1'</command>
<command_fail>yes</command_fail>
</testCase>
<testCase id="100001">
<class>Undeploy_Object</class>
<always_exec>true</always_exec>
@@ -94,7 +94,9 @@ services:
- ALL
environment:
USE_ADDITIONAL_OPTIONS: --rfsim --log_config.global_log_options level,nocolor,time
ASAN_OPTIONS: detect_leaks=0
--telnetsrv --telnetsrv.listenaddr 192.168.71.140
--telnetsrv.shrmod ci
ASAN_OPTIONS: detect_leaks=0:detect_odr_violation=0
depends_on:
- oai-ext-dn
networks:
+21 -16
View File
@@ -825,7 +825,8 @@ void dummyWrite(PHY_VARS_NR_UE *UE,openair0_timestamp timestamp, int writeBlockS
AssertFatal(writeBlockSize == tmp, "");
}
void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, bool toTrash) {
void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, int duration_rx_to_tx, bool toTrash)
{
NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
// two frames for initial sync
int num_frames = 2;
@@ -853,7 +854,8 @@ void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, bool toTrash)
AssertFatal(read_block_size == tmp, "");
if (IS_SOFTMODEM_RFSIM) {
const openair0_timestamp writeTimestamp = *timestamp + fp->get_samples_slot_timestamp(slot, fp, NR_UE_CAPABILITY_SLOT_RX_TO_TX) - UE->N_TA_offset;
const openair0_timestamp writeTimestamp =
*timestamp + fp->get_samples_slot_timestamp(slot, fp, duration_rx_to_tx) - UE->N_TA_offset - UE->timing_advance;
dummyWrite(UE, writeTimestamp, fp->get_samples_per_slot(slot, fp));
}
}
@@ -864,7 +866,7 @@ void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, bool toTrash)
free(rxp[i]);
}
static void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, openair0_timestamp rx_offset)
static void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, int duration_rx_to_tx, openair0_timestamp rx_offset)
{
NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
if (UE->sl_mode == 2)
@@ -879,7 +881,8 @@ static void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, opena
const int res = UE->rfdevice.trx_read_func(&UE->rfdevice, timestamp, (void **)UE->common_vars.rxdata, unitTransfer, fp->nb_antennas_rx);
DevAssert(unitTransfer == res);
if (IS_SOFTMODEM_RFSIM) {
const openair0_timestamp writeTimestamp = *timestamp + fp->get_samples_slot_timestamp(slot, fp, NR_UE_CAPABILITY_SLOT_RX_TO_TX) - UE->N_TA_offset;
const openair0_timestamp writeTimestamp =
*timestamp + fp->get_samples_slot_timestamp(slot, fp, duration_rx_to_tx) - UE->N_TA_offset - UE->timing_advance;
dummyWrite(UE, writeTimestamp, unitTransfer);
}
slot = (slot + 1) % fp->slots_per_subframe;
@@ -965,6 +968,10 @@ void *UE_thread(void *arg)
notifiedFIFO_t freeBlocks;
initNotifiedFIFO_nothreadSafe(&freeBlocks);
double ntn_init_time_drift = get_nrUE_params()->ntn_init_time_drift;
int ntn_koffset = 0;
int duration_rx_to_tx = NR_UE_CAPABILITY_SLOT_RX_TO_TX;
int timing_advance = UE->timing_advance;
UE->N_TA_offset = determine_N_TA_offset(UE);
NR_UE_MAC_INST_t *mac = get_mac_inst(UE->Mod_id);
@@ -988,13 +995,9 @@ void *UE_thread(void *arg)
//warm up the RF board
int64_t tmp;
for (int i = 0; i < 50; i++)
readFrame(UE, &tmp, true);
readFrame(UE, &tmp, duration_rx_to_tx, true);
}
double ntn_init_time_drift = get_nrUE_params()->ntn_init_time_drift;
int ntn_koffset = 0;
int duration_rx_to_tx = NR_UE_CAPABILITY_SLOT_RX_TO_TX;
while (!oai_exit) {
if (syncRunning) {
notifiedFIFO_elt_t *res = pollNotifiedFIFO(&nf);
@@ -1034,11 +1037,11 @@ void *UE_thread(void *arg)
*/
const unsigned int sync_in_frames = UE->rfdevice.openair0_cfg->recplay_conf->u_f_sync;
while (trashed_frames != sync_in_frames) {
readFrame(UE, &sync_timestamp, true);
readFrame(UE, &sync_timestamp, duration_rx_to_tx, true);
trashed_frames += 2;
}
} else {
readFrame(UE, &sync_timestamp, true);
readFrame(UE, &sync_timestamp, duration_rx_to_tx, true);
trashed_frames += ((UE->sl_mode == 2) ? SL_NR_PSBCH_REPETITION_IN_FRAMES : 2);
}
continue;
@@ -1048,7 +1051,7 @@ void *UE_thread(void *arg)
AssertFatal(!syncRunning, "At this point synchronization can't be running\n");
if (!UE->is_synchronized) {
readFrame(UE, &sync_timestamp, false);
readFrame(UE, &sync_timestamp, duration_rx_to_tx, false);
notifiedFIFO_elt_t *Msg = newNotifiedFIFO_elt(sizeof(syncData_t), 0, &nf, UE_synch);
syncData_t *syncMsg = (syncData_t *)NotifiedFifoData(Msg);
*syncMsg = (syncData_t){0};
@@ -1065,8 +1068,10 @@ void *UE_thread(void *arg)
syncMsg->UE = UE;
memset(&syncMsg->proc, 0, sizeof(syncMsg->proc));
pushNotifiedFIFO(&UE->sync_actor.fifo, Msg);
timing_advance = 0;
UE->timing_advance = 0;
if (ntn_koffset == 0) { // reset timing_advance for TN
timing_advance = 0;
UE->timing_advance = 0;
}
trashed_frames = 0;
syncRunning = true;
continue;
@@ -1074,7 +1079,7 @@ void *UE_thread(void *arg)
if (stream_status == STREAM_STATUS_UNSYNC) {
stream_status = STREAM_STATUS_SYNCING;
syncInFrame(UE, &sync_timestamp, intialSyncOffset);
syncInFrame(UE, &sync_timestamp, duration_rx_to_tx, intialSyncOffset);
openair0_write_reorder_clear_context(&UE->rfdevice);
if (get_nrUE_params()->time_sync_I)
// ntn_init_time_drift is in µs/s, max_pos_acc * time_sync_I is in samples/frame
@@ -1200,7 +1205,7 @@ void *UE_thread(void *arg)
int writeBlockSize = fp->get_samples_per_slot((slot_nr + duration_rx_to_tx) % nb_slot_frame, fp) - iq_shift_to_apply;
int new_timing_advance = UE->timing_advance;
if (new_timing_advance != timing_advance) {
writeBlockSize -= new_timing_advance- timing_advance;
writeBlockSize -= new_timing_advance - timing_advance;
timing_advance = new_timing_advance;
}
int new_N_TA_offset = determine_N_TA_offset(UE);
+15 -10
View File
@@ -2466,13 +2466,13 @@ static void nr_ue_get_sdu_mac_ce_post(NR_UE_MAC_INST_t *mac,
mac_ce_p->cur_ptr += size;
}
uint32_t get_count_lcids_same_priority(uint8_t start, uint8_t total_active_lcids, nr_lcordered_info_t *lcid_ordered_array)
static uint32_t get_count_lcids_same_priority(uint8_t start, uint8_t total_active_lcids, nr_lcordered_info_t *lcid_ordered_array[])
{
// count number of logical channels with same priority as curr_lcid
uint8_t same_priority_count = 0;
uint8_t curr_lcid = lcid_ordered_array[start].lcid;
uint8_t curr_lcid = lcid_ordered_array[start]->lcid;
for (uint8_t index = start; index < total_active_lcids; index++) {
if (lcid_ordered_array[start].priority == lcid_ordered_array[index].priority) {
if (lcid_ordered_array[start]->priority == lcid_ordered_array[index]->priority) {
same_priority_count++;
}
}
@@ -2520,11 +2520,13 @@ static long get_num_bytes_to_reqlc(NR_UE_MAC_INST_t *mac,
return num_bytes_requested;
}
bool get_dataavailability_buffers(uint8_t total_active_lcids, nr_lcordered_info_t *lcid_ordered_array, bool *data_status_lcbuffers)
static bool get_dataavailability_buffers(uint8_t total_active_lcids,
nr_lcordered_info_t *lcid_ordered_array[],
bool *data_status_lcbuffers)
{
// check whether there is any data in the rlc buffer corresponding to active lcs
for (uint8_t id = 0; id < total_active_lcids; id++) {
int lcid = lcid_ordered_array[id].lcid;
int lcid = lcid_ordered_array[id]->lcid;
if (data_status_lcbuffers[lcid_buffer_index(lcid)]) {
return true;
}
@@ -2532,17 +2534,20 @@ bool get_dataavailability_buffers(uint8_t total_active_lcids, nr_lcordered_info_
return false;
}
static uint select_logical_channels(NR_UE_MAC_INST_t *mac, nr_lcordered_info_t *active_lcids)
static uint select_logical_channels(NR_UE_MAC_INST_t *mac, nr_lcordered_info_t *active_lcids[])
{
// (TODO: selection of logical channels for logical channel prioritization procedure as per 5.4.3.1.2 Selection of logical
// channels, TS38.321)
int nb = 0;
// selection of logical channels with Bj > 0
for (int i = 0; i < mac->lc_ordered_list.count; i++) {
int lcid = mac->lc_ordered_list.array[i]->lcid;
nr_lcordered_info_t *lc_info = mac->lc_ordered_list.array[i];
if (lc_info->rb_suspended)
continue;
int lcid = lc_info->lcid;
NR_LC_SCHEDULING_INFO *sched_info = get_scheduling_info_from_lcid(mac, lcid);
if (sched_info->Bj > 0) {
active_lcids[nb++] = *mac->lc_ordered_list.array[i];
active_lcids[nb++] = lc_info;
LOG_D(NR_MAC, "The available lcid is %d with total active channels count = %d\n", lcid, nb);
}
}
@@ -2731,7 +2736,7 @@ static uint8_t nr_ue_get_sdu(NR_UE_MAC_INST_t *mac,
LOG_E(NR_MAC, "Failed to init lcids_bj_pos: mac->lc_ordered_list.count = 0\n");
return 0;
}
nr_lcordered_info_t lcids_bj_pos[mac->lc_ordered_list.count];
nr_lcordered_info_t *lcids_bj_pos[mac->lc_ordered_list.count];
int avail_lcids_count = select_logical_channels(mac, lcids_bj_pos);
// multiplex in the order of highest priority
@@ -2752,7 +2757,7 @@ static uint8_t nr_ue_get_sdu(NR_UE_MAC_INST_t *mac,
still space availble in the MAC PDU, then from the next run all the remaining data from the higher priority logical channel
is placed in the MAC PDU before going on to next high priority logical channel
*/
int lcid = lcids_bj_pos[id].lcid;
int lcid = lcids_bj_pos[id]->lcid;
int idx = lcid_buffer_index(lcid);
// skip the logical channel if no data in the buffer initially or the data in the buffer was zero because it was written in to
// MAC PDU
+1 -1
View File
@@ -276,7 +276,7 @@ void openair0_write_reorder_clear_context(openair0_device *device)
re_order_t *ctx = &device->reOrder;
if (!ctx->initDone)
return;
if (pthread_mutex_trylock(&ctx->mutex_write) == 0)
if (pthread_mutex_trylock(&ctx->mutex_write) != 0)
LOG_E(HW, "write_reorder_clear_context call while still writing on the device\n");
pthread_mutex_destroy(&ctx->mutex_write);
pthread_mutex_lock(&ctx->mutex_store);