Fix NR sidelink SDAP TUN data path

This commit is contained in:
Jérôme Härri
2026-05-08 09:21:26 +02:00
parent acfba637cf
commit 3339aa0fac
11 changed files with 87 additions and 52 deletions

View File

@@ -985,7 +985,7 @@ void *UE_thread(void *arg)
frameslot_t frame_slot_tx;
frame_slot_tx.frame = curMsg.proc.frame_tx;
frame_slot_tx.slot = curMsg.proc.nr_slot_tx;
validate_selected_sl_slot(true , false, mac->SL_MAC_PARAMS->sl_TDD_config, frame_slot_tx);
validate_selected_sl_slot(mac, true, false, mac->SL_MAC_PARAMS->sl_TDD_config, frame_slot_tx);
curMsg.proc.tx_slot_type = NR_SIDELINK_SLOT;
}
@@ -996,7 +996,7 @@ void *UE_thread(void *arg)
frameslot_t frame_slot_rx;
frame_slot_rx.frame = curMsg.proc.frame_rx;
frame_slot_rx.slot = curMsg.proc.nr_slot_rx;
validate_selected_sl_slot(false , true, mac->SL_MAC_PARAMS->sl_TDD_config, frame_slot_rx);
validate_selected_sl_slot(mac, false, true, mac->SL_MAC_PARAMS->sl_TDD_config, frame_slot_rx);
curMsg.proc.rx_slot_type = NR_SIDELINK_SLOT;
}
} else {
@@ -1136,7 +1136,7 @@ void init_NR_UE(int nb_inst, char *uecap_file, char *reconfig_file, char *rbconf
nr_rlc_activate_srb0(mac->crnti, NULL, send_srb0_rrc);
}
//TODO: Move this call to RRC
start_sidelink(instance_id);
start_sidelink(instance_id, ueinfo);
}
}

View File

@@ -455,8 +455,6 @@ int main(int argc, char **argv)
if (UE[CC_id]->sl_mode) {
AssertFatal(UE[CC_id]->sl_mode == 2, "Only Sidelink mode 2 supported. Mode 1 not yet supported\n");
nr_pdcp_entity_security_keys_and_algos_t security_up_parameters = {0};
rrc_ue_process_sidelink_Preconfiguration(0, get_nrUE_params()->sync_ref, &ueinfo, &security_up_parameters);
DevAssert(mac->if_module != NULL && mac->if_module->sl_phy_config_request != NULL);
nr_sl_phy_config_t *phycfg = &mac->SL_MAC_PARAMS->sl_phy_config;
phycfg->sl_config_req.sl_carrier_config.sl_num_rx_ant = get_nrUE_params()->nb_antennas_rx;
@@ -542,4 +540,3 @@ int main(int argc, char **argv)
free(pckg);
return 0;
}

View File

@@ -472,6 +472,16 @@ int nr_rrc_mac_config_req_sl_preconfig(module_id_t module_id,
sl_mac->sl_TDD_config = sl_preconfig->sl_PreconfigGeneral_r16->sl_TDD_Configuration_r16;
config_frame_structure(get_softmodem_params()->numerology,
sl_mac->sl_TDD_config,
get_tdd_period_idx(sl_mac->sl_TDD_config),
TDD,
&mac->frame_structure);
sl_set_tdd_config_nr_ue(&sl_mac->sl_phy_config.sl_config_req.tdd_table,
get_softmodem_params()->numerology,
&sl_mac->sl_TDD_config->pattern1);
// Sync source is identified, timing needs to be adjusted.
sl_mac->timing_acquired = true;
}
@@ -499,6 +509,7 @@ int nr_rrc_mac_config_req_sl_preconfig(module_id_t module_id,
nr_slots_period /= get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity);
}
memset(mac->ulsch_slot_bitmap, 0, sizeof(mac->ulsch_slot_bitmap));
for (int slot = 0; slot < nr_slots_frame; ++slot) {
mac->ulsch_slot_bitmap[slot / 64] |= (uint64_t)((slot % nr_slots_period) >= nr_ulstart_slot) << (slot % 64);
LOG_D(NR_MAC,
@@ -679,6 +690,12 @@ void nr_rrc_mac_config_req_sl_mib(module_id_t module_id,
NR_NUMBER_OF_SUBFRAMES_PER_FRAME*(1<<cfg->sl_bwp_config.sl_scs);
}
config_frame_structure(get_softmodem_params()->numerology,
sl_mac->sl_TDD_config,
get_tdd_period_idx(sl_mac->sl_TDD_config),
TDD,
&mac->frame_structure);
sl_set_tdd_config_nr_ue(&cfg->tdd_table,
cfg->sl_bwp_config.sl_scs,
&sl_mac->sl_TDD_config->pattern1);
@@ -706,6 +723,7 @@ void nr_rrc_mac_config_req_sl_mib(module_id_t module_id,
nr_slots_period /= get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity);
}
memset(mac->ulsch_slot_bitmap, 0, sizeof(mac->ulsch_slot_bitmap));
for (int slot = 0; slot < nr_slots_frame; ++slot) {
mac->ulsch_slot_bitmap[slot / 64] |= (uint64_t)((slot % nr_slots_period) >= nr_ulstart_slot) << (slot % 64);
LOG_D(NR_MAC,

View File

@@ -644,7 +644,7 @@ List_t get_nr_sl_comm_opportunities(NR_UE_MAC_INST_t *mac,
bool is_sl_slot(NR_UE_MAC_INST_t *mac, BIT_STRING_t *phy_sl_bitmap, uint16_t phy_map_sz, uint64_t abs_slot);
void validate_selected_sl_slot(bool tx, bool rx, NR_TDD_UL_DL_ConfigCommon_t *conf, frameslot_t frame_slot);
void validate_selected_sl_slot(NR_UE_MAC_INST_t *mac, bool tx, bool rx, NR_TDD_UL_DL_ConfigCommon_t *conf, frameslot_t frame_slot);
bool check_t1_within_tproc1(uint8_t mu, uint16_t t1_slots);

View File

@@ -316,7 +316,7 @@ void nr_schedule_slsch(NR_UE_MAC_INST_t *mac, int frameP, int slotP, nr_sci_pdu_
frameslot_t frame_slot;
frame_slot.frame = frameP;
frame_slot.slot = slotP;
validate_selected_sl_slot(true, false, mac->SL_MAC_PARAMS->sl_TDD_config, frame_slot);
validate_selected_sl_slot(mac, true, false, mac->SL_MAC_PARAMS->sl_TDD_config, frame_slot);
break;
}
}

View File

@@ -324,6 +324,12 @@ uint8_t sl_decode_sl_TDD_Config(NR_TDD_UL_DL_ConfigCommon_t *TDD_UL_DL_Config,
//a5,a6..a11 bits from the 7th to 1st LSB of num SL slots
num_SL_slots = ((bits_0_to_7 & 0x07) << 4 ) | ((bits_8_to_11 & 0xF0) >> 4);
const int nr_slots_period = nr_slots_per_frame[mu] / get_nb_periods_per_frame(TDD_UL_DL_Config->pattern1.dl_UL_TransmissionPeriodicity);
AssertFatal(num_SL_slots <= nr_slots_period,
"Decoded sidelink slots %d exceed TDD period slots %d\n",
num_SL_slots,
nr_slots_period);
TDD_UL_DL_Config->pattern1.nrofDownlinkSlots = nr_slots_period - num_SL_slots;
TDD_UL_DL_Config->pattern1.nrofUplinkSlots = num_SL_slots;
TDD_UL_DL_Config->pattern1.nrofUplinkSymbols = mixed_slot_numsym;
@@ -1123,7 +1129,7 @@ void nr_ue_process_mac_sl_pdu(int module_idP,
NULL);
#endif
nr_mac_rlc_data_ind(mac->ue_id, mac->ue_id, false, rx_lcid, (char *)(pduP + mac_subheader_len), mac_len);
nr_mac_rlc_data_ind(mac->ue_id, mac->src_id, false, rx_lcid, (char *)(pduP + mac_subheader_len), mac_len);
break;
case SL_SCH_LCID_SL_CSI_REPORT:

View File

@@ -549,34 +549,28 @@ bool slot_has_psfch(NR_UE_MAC_INST_t *mac, BIT_STRING_t *phy_sl_bitmap, uint64_t
return has_psfch;
}
void validate_selected_sl_slot(bool tx, bool rx, NR_TDD_UL_DL_ConfigCommon_t *conf, frameslot_t frame_slot) {
AssertFatal(conf->pattern1.nrofUplinkSlots == 4 && conf->pattern1.nrofDownlinkSlots == 6,
"Invalid configuration set. Please update the nrofUplinkSlots to 4 and nrofDownlinkSlots to 6.\n");
if (get_nrUE_params()->sync_ref) {
if (tx) {
AssertFatal((frame_slot.slot == 6 || frame_slot.slot == 7 || frame_slot.slot == 8 || frame_slot.slot == 9),
"As a transmitting syncref UE, based on the current configuration of uplink slots = %ld and downlink = %ld, "
"you should be selecting resources with slot 6, 7, 8, or 9 only.\n",
conf->pattern1.nrofUplinkSlots, conf->pattern1.nrofDownlinkSlots);
} else if (rx) {
AssertFatal((frame_slot.slot == 16 || frame_slot.slot == 17 || frame_slot.slot == 18 || frame_slot.slot == 19),
"As a receiving syncref UE, based on the current configuration of uplink slots = %ld and downlink = %ld, "
"you should be selecting resources with slot 16, 17, 18, or 19 only.\n",
conf->pattern1.nrofUplinkSlots, conf->pattern1.nrofDownlinkSlots);
}
} else if (!get_nrUE_params()->sync_ref) {
if (tx) {
AssertFatal((frame_slot.slot == 16 || frame_slot.slot == 17 || frame_slot.slot == 18 || frame_slot.slot == 19),
"As a transmitting nearby UE, based on the current configuration of uplink slots = %ld and downlink = %ld, "
"you should be selecting resources with slot 16, 17,1 8, or 19 only.\n",
conf->pattern1.nrofUplinkSlots, conf->pattern1.nrofDownlinkSlots);
} else if (rx) {
AssertFatal((frame_slot.slot == 6 || frame_slot.slot == 7 || frame_slot.slot == 8 || frame_slot.slot == 9),
"As a receiving nearby UE, based on the current configuration of uplink slots = %ld and downlink = %ld, "
"you should be selecting resources with slot 6, 7, 8, or 9 only.\n",
conf->pattern1.nrofUplinkSlots, conf->pattern1.nrofDownlinkSlots);
}
}
void validate_selected_sl_slot(NR_UE_MAC_INST_t *mac, bool tx, bool rx, NR_TDD_UL_DL_ConfigCommon_t *conf, frameslot_t frame_slot) {
AssertFatal(mac != NULL, "mac cannot be NULL\n");
AssertFatal(conf != NULL, "TDD configuration cannot be NULL\n");
const int scs = get_softmodem_params()->numerology;
const int nr_slots_frame = nr_slots_per_frame[scs];
AssertFatal(frame_slot.slot >= 0 && frame_slot.slot < nr_slots_frame,
"Selected sidelink slot %d.%d is outside the frame slot range 0..%d\n",
frame_slot.frame,
frame_slot.slot,
nr_slots_frame - 1);
const bool is_ul_slot = (mac->ulsch_slot_bitmap[frame_slot.slot / 64] & ((uint64_t)1 << (frame_slot.slot % 64))) != 0;
const char *direction = tx ? "TX" : rx ? "RX" : "unknown";
AssertFatal(is_ul_slot,
"Selected sidelink %s slot %d.%d is not an UL/sidelink slot for current TDD pattern "
"(DL slots %ld, UL slots %ld, periodicity %ld)\n",
direction,
frame_slot.frame,
frame_slot.slot,
conf->pattern1.nrofDownlinkSlots,
conf->pattern1.nrofUplinkSlots,
conf->pattern1.dl_UL_TransmissionPeriodicity);
}
bool is_sl_slot(NR_UE_MAC_INST_t *mac, BIT_STRING_t *phy_sl_bitmap, uint16_t phy_map_sz, uint64_t abs_slot) {
@@ -616,7 +610,7 @@ static void nr_store_slsch_buffer(NR_UE_MAC_INST_t *mac, frame_t frame, sub_fram
sched_ctrl->sl_pdus_total = 0;
const int lcid = 4;
sched_ctrl->rlc_status[lcid] = nr_mac_rlc_status_ind(mac->ue_id, frame, lcid);
sched_ctrl->rlc_status[lcid] = nr_mac_rlc_status_ind(mac->src_id, frame, lcid);
if (sched_ctrl->rlc_status[lcid].bytes_in_buffer == 0)
continue;
@@ -949,7 +943,7 @@ bool nr_ue_sl_pssch_scheduler(NR_UE_MAC_INST_t *mac,
#endif
sdu_length = nr_mac_rlc_data_req(mac->ue_id,
mac->ue_id,
mac->src_id,
false,
lcid,
ndata,
@@ -1819,7 +1813,7 @@ List_t get_nr_sl_comm_opportunities(NR_UE_MAC_INST_t *mac,
.sl_has_psfch = sl_has_psfch};
de_normalize(slot_info.abs_slot_index, mu, &frame_slot);
LOG_D(NR_MAC, "Pushing %4d.%2d\n", frame_slot.frame, frame_slot.slot);
validate_selected_sl_slot(true , false, mac->SL_MAC_PARAMS->sl_TDD_config, frame_slot);
validate_selected_sl_slot(mac, true, false, mac->SL_MAC_PARAMS->sl_TDD_config, frame_slot);
push_back(&slot_info_list, &slot_info);
}
abs_pool_index = (abs_pool_index + 1) % phy_map_sz;

View File

@@ -656,12 +656,10 @@ void add_drb_sl(ue_id_t srcid, NR_SL_RadioBearerConfig_r16_t *s, const nr_pdcp_e
sdap.pdusession_id = 0;
sdap.drb_id = slrb_id;
int is_gnb = 0; // SL is only for UE side, so is_gnb is always false
sdap_role_t role_dl = is_gnb ? SDAP_DL_TX : SDAP_DL_RX;
int role = 0;
if (s->sl_SDAP_Config_r16 && s->sl_SDAP_Config_r16->sl_SDAP_Header_r16 == NR_SL_SDAP_Config_r16__sl_SDAP_Header_r16_present)
{
role |= role_dl;
role |= SDAP_UL_TX | SDAP_DL_RX;
}
sdap.role = role;
sdap.defaultDRB = s->sl_SDAP_Config_r16 && s->sl_SDAP_Config_r16->sl_DefaultRB_r16 == true ? true : false;
@@ -690,7 +688,8 @@ void add_drb_sl(ue_id_t srcid, NR_SL_RadioBearerConfig_r16_t *s, const nr_pdcp_e
LOG_W(PDCP, "%s:%d:%s: warning DRB %d already exist for UE ID/RNTI %ld, do nothing\n", __FILE__, __LINE__, __FUNCTION__, slrb_id, srcid);
} else {
pdcp_drb = new_nr_pdcp_entity(NR_PDCP_DRB_AM, 0, slrb_id, 0,
(sdap.role & (SDAP_UL_RX | SDAP_DL_RX)) != 0,(sdap.role & (SDAP_UL_RX | SDAP_DL_RX)) != 0,
(sdap.role & (SDAP_UL_RX | SDAP_DL_RX)) != 0,
(sdap.role & (SDAP_UL_TX | SDAP_DL_TX)) != 0,
deliver_sdu_drb, ue, deliver_pdu_drb_ue, ue,
sn_size, t_reordering, discard_timer,
security_parameters);

View File

@@ -3057,7 +3057,7 @@ void handle_t430_expiry(NR_UE_RRC_INST_t *rrc)
}
//This calls the sidelink preconf message after RRC, MAC instances are created.
void start_sidelink(int instance)
void start_sidelink(int instance, ueinfo_t *ueinfo)
{
NR_UE_RRC_INST_t *rrc = get_NR_UE_rrc_inst(instance);
@@ -3072,11 +3072,10 @@ void start_sidelink(int instance)
security_up_parameters.integrity_algorithm = has_integrity ? rrc->integrityProtAlgorithm : 0;
if (get_softmodem_params()->sl_mode == 2) {
ueinfo_t ueinfo;
AssertFatal(ueinfo != NULL, "Sidelink UE info not configured\n");
//Process the Sidelink Preconfiguration
rrc_ue_process_sidelink_Preconfiguration(rrc, get_softmodem_params()->sync_ref, &ueinfo, &security_up_parameters);
rrc_ue_process_sidelink_Preconfiguration(rrc, get_softmodem_params()->sync_ref, ueinfo, &security_up_parameters);
}
}

View File

@@ -92,7 +92,7 @@ int configure_NR_SL_Preconfig(NR_UE_RRC_INST_t *rrc,int sync_source);
//void nr_UE_configure_Sidelink(uint8_t id, uint8_t is_sync_source, ueinfo_t *ueinfo);
void init_sidelink(NR_UE_RRC_INST_t *rrc);
void start_sidelink(int instance);
void start_sidelink(int instance, ueinfo_t *ueinfo);
void rrc_ue_process_sidelink_Preconfiguration(NR_UE_RRC_INST_t *rrc_inst, int sync_ref, ueinfo_t *ueinfo, nr_pdcp_entity_security_keys_and_algos_t *security_up_parameters);
@@ -108,4 +108,3 @@ void nr_rrc_set_mac_queue(instance_t instance, notifiedFIFO_t *mac_input_nf);
/** @}*/
#endif

View File

@@ -33,6 +33,8 @@
#include "tun_if.h"
#include "LAYER2/nr_rlc/nr_rlc_oai_api.h"
#include "LAYER2/nr_pdcp/nr_pdcp_oai_api.h"
#include "openair2/SDAP/nr_sdap/nr_sdap.h"
#include "openair2/SDAP/nr_sdap/nr_sdap_entity.h"
#define GNSS_SUPPORT 0
@@ -678,6 +680,23 @@ void nr_rrc_ue_decode_NR_SBCCH_SL_BCH_Message(NR_UE_RRC_INST_t *rrc,
return;
}
static uint8_t get_sl_tun_qfi(NR_SL_PreconfigurationNR_r16_t *sl_preconfig)
{
NR_SL_RadioBearerConfig_r16_t *slrb =
sl_preconfig->sidelinkPreconfigNR_r16.sl_RadioBearerPreConfigList_r16->list.array[0];
DevAssert(slrb != NULL);
struct NR_SL_SDAP_Config_r16 *sdap = slrb->sl_SDAP_Config_r16;
DevAssert(sdap != NULL && sdap->sl_MappedQoS_Flows_r16 != NULL);
struct NR_SL_SDAP_Config_r16__sl_MappedQoS_Flows_r16__sl_MappedQoS_FlowsList_r16 *flows =
sdap->sl_MappedQoS_Flows_r16->choice.sl_MappedQoS_FlowsList_r16;
DevAssert(flows != NULL && flows->list.count > 0);
NR_SL_QoS_Profile_r16_t *profile = flows->list.array[0];
DevAssert(profile != NULL && profile->sl_PQI_r16 != NULL);
const long standardized_PQI = profile->sl_PQI_r16->choice.sl_StandardizedPQI_r16;
DevAssert(standardized_PQI >= 0 && standardized_PQI < SDAP_MAX_QFI);
return standardized_PQI;
}
void rrc_ue_process_sidelink_Preconfiguration(NR_UE_RRC_INST_t *rrc_inst,
sl_sync_source_enum_t sync_source,
ueinfo_t *ueinfo,
@@ -704,8 +723,8 @@ void rrc_ue_process_sidelink_Preconfiguration(NR_UE_RRC_INST_t *rrc_inst,
char ifname[IFNAMSIZ];
tun_generate_ifname(ifname, "oai_sl_tun", ueinfo->srcid);
tun_config(ifname, ip, NULL);
if (ip)
int sl_tun_sock = tun_alloc(ifname);
if (sl_tun_sock >= 0 && tun_config(ifname, ip, NULL))
{
setup_ue_ipv4_route(ifname, ueinfo->srcid, ip);
}
@@ -716,6 +735,10 @@ void rrc_ue_process_sidelink_Preconfiguration(NR_UE_RRC_INST_t *rrc_inst,
for (int i=0; i<sl_preconfig->sidelinkPreconfigNR_r16.sl_RadioBearerPreConfigList_r16->list.count; i++) {
add_drb_sl(ueinfo->srcid, (NR_SL_RadioBearerConfig_r16_t *)sl_preconfig->sidelinkPreconfigNR_r16.sl_RadioBearerPreConfigList_r16->list.array[i], security_up_parameters);
}
if (sl_tun_sock >= 0) {
set_qfi(get_sl_tun_qfi(sl_preconfig), 0, ueinfo->srcid);
start_sdap_tun_ue(ueinfo->srcid, 0, sl_tun_sock);
}
// configure RLC
for (int i=0; i<sl_preconfig->sidelinkPreconfigNR_r16.sl_RLC_BearerPreConfigList_r16->list.count; i++) {
nr_rlc_add_drb_sl(ueinfo->srcid, 1, (NR_SL_RLC_BearerConfig_r16_t *)sl_preconfig->sidelinkPreconfigNR_r16.sl_RLC_BearerPreConfigList_r16->list.array[i]);