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:
@@ -195,6 +195,15 @@ gNBs =
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
rlc = {
|
||||||
|
srb = {
|
||||||
|
t_poll_retransmit = "ms2000"
|
||||||
|
}
|
||||||
|
drb_am = {
|
||||||
|
t_poll_retransmit = "ms2000"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MACRLCs = (
|
MACRLCs = (
|
||||||
{
|
{
|
||||||
num_cc = 1;
|
num_cc = 1;
|
||||||
|
|||||||
@@ -33,6 +33,11 @@
|
|||||||
000003
|
000003
|
||||||
020001
|
020001
|
||||||
020002
|
020002
|
||||||
|
040001
|
||||||
|
020022
|
||||||
|
040002
|
||||||
|
020001
|
||||||
|
020002
|
||||||
100001
|
100001
|
||||||
222222
|
222222
|
||||||
</TestCaseRequestedList>
|
</TestCaseRequestedList>
|
||||||
@@ -98,6 +103,33 @@
|
|||||||
<ping_packetloss_threshold>5</ping_packetloss_threshold>
|
<ping_packetloss_threshold>5</ping_packetloss_threshold>
|
||||||
</testCase>
|
</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">
|
<testCase id="100001">
|
||||||
<class>Undeploy_Object</class>
|
<class>Undeploy_Object</class>
|
||||||
<always_exec>true</always_exec>
|
<always_exec>true</always_exec>
|
||||||
|
|||||||
@@ -94,7 +94,9 @@ services:
|
|||||||
- ALL
|
- ALL
|
||||||
environment:
|
environment:
|
||||||
USE_ADDITIONAL_OPTIONS: --rfsim --log_config.global_log_options level,nocolor,time
|
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:
|
depends_on:
|
||||||
- oai-ext-dn
|
- oai-ext-dn
|
||||||
networks:
|
networks:
|
||||||
|
|||||||
+21
-16
@@ -825,7 +825,8 @@ void dummyWrite(PHY_VARS_NR_UE *UE,openair0_timestamp timestamp, int writeBlockS
|
|||||||
AssertFatal(writeBlockSize == tmp, "");
|
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;
|
NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
|
||||||
// two frames for initial sync
|
// two frames for initial sync
|
||||||
int num_frames = 2;
|
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, "");
|
AssertFatal(read_block_size == tmp, "");
|
||||||
|
|
||||||
if (IS_SOFTMODEM_RFSIM) {
|
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));
|
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]);
|
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;
|
NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
|
||||||
if (UE->sl_mode == 2)
|
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);
|
const int res = UE->rfdevice.trx_read_func(&UE->rfdevice, timestamp, (void **)UE->common_vars.rxdata, unitTransfer, fp->nb_antennas_rx);
|
||||||
DevAssert(unitTransfer == res);
|
DevAssert(unitTransfer == res);
|
||||||
if (IS_SOFTMODEM_RFSIM) {
|
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);
|
dummyWrite(UE, writeTimestamp, unitTransfer);
|
||||||
}
|
}
|
||||||
slot = (slot + 1) % fp->slots_per_subframe;
|
slot = (slot + 1) % fp->slots_per_subframe;
|
||||||
@@ -965,6 +968,10 @@ void *UE_thread(void *arg)
|
|||||||
notifiedFIFO_t freeBlocks;
|
notifiedFIFO_t freeBlocks;
|
||||||
initNotifiedFIFO_nothreadSafe(&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;
|
int timing_advance = UE->timing_advance;
|
||||||
UE->N_TA_offset = determine_N_TA_offset(UE);
|
UE->N_TA_offset = determine_N_TA_offset(UE);
|
||||||
NR_UE_MAC_INST_t *mac = get_mac_inst(UE->Mod_id);
|
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
|
//warm up the RF board
|
||||||
int64_t tmp;
|
int64_t tmp;
|
||||||
for (int i = 0; i < 50; i++)
|
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) {
|
while (!oai_exit) {
|
||||||
if (syncRunning) {
|
if (syncRunning) {
|
||||||
notifiedFIFO_elt_t *res = pollNotifiedFIFO(&nf);
|
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;
|
const unsigned int sync_in_frames = UE->rfdevice.openair0_cfg->recplay_conf->u_f_sync;
|
||||||
while (trashed_frames != sync_in_frames) {
|
while (trashed_frames != sync_in_frames) {
|
||||||
readFrame(UE, &sync_timestamp, true);
|
readFrame(UE, &sync_timestamp, duration_rx_to_tx, true);
|
||||||
trashed_frames += 2;
|
trashed_frames += 2;
|
||||||
}
|
}
|
||||||
} else {
|
} 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);
|
trashed_frames += ((UE->sl_mode == 2) ? SL_NR_PSBCH_REPETITION_IN_FRAMES : 2);
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
@@ -1048,7 +1051,7 @@ void *UE_thread(void *arg)
|
|||||||
AssertFatal(!syncRunning, "At this point synchronization can't be running\n");
|
AssertFatal(!syncRunning, "At this point synchronization can't be running\n");
|
||||||
|
|
||||||
if (!UE->is_synchronized) {
|
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);
|
notifiedFIFO_elt_t *Msg = newNotifiedFIFO_elt(sizeof(syncData_t), 0, &nf, UE_synch);
|
||||||
syncData_t *syncMsg = (syncData_t *)NotifiedFifoData(Msg);
|
syncData_t *syncMsg = (syncData_t *)NotifiedFifoData(Msg);
|
||||||
*syncMsg = (syncData_t){0};
|
*syncMsg = (syncData_t){0};
|
||||||
@@ -1065,8 +1068,10 @@ void *UE_thread(void *arg)
|
|||||||
syncMsg->UE = UE;
|
syncMsg->UE = UE;
|
||||||
memset(&syncMsg->proc, 0, sizeof(syncMsg->proc));
|
memset(&syncMsg->proc, 0, sizeof(syncMsg->proc));
|
||||||
pushNotifiedFIFO(&UE->sync_actor.fifo, Msg);
|
pushNotifiedFIFO(&UE->sync_actor.fifo, Msg);
|
||||||
timing_advance = 0;
|
if (ntn_koffset == 0) { // reset timing_advance for TN
|
||||||
UE->timing_advance = 0;
|
timing_advance = 0;
|
||||||
|
UE->timing_advance = 0;
|
||||||
|
}
|
||||||
trashed_frames = 0;
|
trashed_frames = 0;
|
||||||
syncRunning = true;
|
syncRunning = true;
|
||||||
continue;
|
continue;
|
||||||
@@ -1074,7 +1079,7 @@ void *UE_thread(void *arg)
|
|||||||
|
|
||||||
if (stream_status == STREAM_STATUS_UNSYNC) {
|
if (stream_status == STREAM_STATUS_UNSYNC) {
|
||||||
stream_status = STREAM_STATUS_SYNCING;
|
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);
|
openair0_write_reorder_clear_context(&UE->rfdevice);
|
||||||
if (get_nrUE_params()->time_sync_I)
|
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
|
// 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 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;
|
int new_timing_advance = UE->timing_advance;
|
||||||
if (new_timing_advance != 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;
|
timing_advance = new_timing_advance;
|
||||||
}
|
}
|
||||||
int new_N_TA_offset = determine_N_TA_offset(UE);
|
int new_N_TA_offset = determine_N_TA_offset(UE);
|
||||||
|
|||||||
@@ -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;
|
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
|
// count number of logical channels with same priority as curr_lcid
|
||||||
uint8_t same_priority_count = 0;
|
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++) {
|
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++;
|
same_priority_count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2520,11 +2520,13 @@ static long get_num_bytes_to_reqlc(NR_UE_MAC_INST_t *mac,
|
|||||||
return num_bytes_requested;
|
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
|
// check whether there is any data in the rlc buffer corresponding to active lcs
|
||||||
for (uint8_t id = 0; id < total_active_lcids; id++) {
|
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)]) {
|
if (data_status_lcbuffers[lcid_buffer_index(lcid)]) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -2532,17 +2534,20 @@ bool get_dataavailability_buffers(uint8_t total_active_lcids, nr_lcordered_info_
|
|||||||
return false;
|
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
|
// (TODO: selection of logical channels for logical channel prioritization procedure as per 5.4.3.1.2 Selection of logical
|
||||||
// channels, TS38.321)
|
// channels, TS38.321)
|
||||||
int nb = 0;
|
int nb = 0;
|
||||||
// selection of logical channels with Bj > 0
|
// selection of logical channels with Bj > 0
|
||||||
for (int i = 0; i < mac->lc_ordered_list.count; i++) {
|
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);
|
NR_LC_SCHEDULING_INFO *sched_info = get_scheduling_info_from_lcid(mac, lcid);
|
||||||
if (sched_info->Bj > 0) {
|
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);
|
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");
|
LOG_E(NR_MAC, "Failed to init lcids_bj_pos: mac->lc_ordered_list.count = 0\n");
|
||||||
return 0;
|
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);
|
int avail_lcids_count = select_logical_channels(mac, lcids_bj_pos);
|
||||||
|
|
||||||
// multiplex in the order of highest priority
|
// 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
|
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
|
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);
|
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
|
// 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
|
// MAC PDU
|
||||||
|
|||||||
@@ -276,7 +276,7 @@ void openair0_write_reorder_clear_context(openair0_device *device)
|
|||||||
re_order_t *ctx = &device->reOrder;
|
re_order_t *ctx = &device->reOrder;
|
||||||
if (!ctx->initDone)
|
if (!ctx->initDone)
|
||||||
return;
|
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");
|
LOG_E(HW, "write_reorder_clear_context call while still writing on the device\n");
|
||||||
pthread_mutex_destroy(&ctx->mutex_write);
|
pthread_mutex_destroy(&ctx->mutex_write);
|
||||||
pthread_mutex_lock(&ctx->mutex_store);
|
pthread_mutex_lock(&ctx->mutex_store);
|
||||||
|
|||||||
Reference in New Issue
Block a user