diff --git a/CMakeLists.txt b/CMakeLists.txt index 8e2457630a..8a55506b59 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -298,6 +298,7 @@ message(STATUS "Selected KPM Version: ${KPM_VERSION}") add_boolean_option(ENABLE_IMSCOPE OFF "Enable phy scope based on imgui" OFF) +add_boolean_option(ENABLE_IMSCOPE_RECORD OFF "Enable recording IQ data for imscope" OFF) ################################################## # ASN.1 grammar C code generation & dependencies # @@ -779,9 +780,6 @@ add_library(dfts MODULE ${OPENAIR1_DIR}/PHY/TOOLS/oai_dfts.c ${OPENAIR1_DIR}/PHY set(PHY_SRC_COMMON ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dci_tools_common.c ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/lte_mcs.c -# ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/slss.c -# ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/sldch.c -# ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/slsch.c ${OPENAIR1_DIR}/PHY/LTE_UE_TRANSPORT/get_pmi.c ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/group_hopping.c ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/phich_common.c @@ -840,13 +838,9 @@ set(PHY_SRC ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/pcfich.c ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/pucch.c ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/pmch.c -# ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/ulsch_demodulation.c ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/ulsch_decoding.c ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/rar_tools.c ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/uci_tools.c -# ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/freq_equalization.c -# ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_adjust_sync_eNB.c -# ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_eNB_measurements.c ${OPENAIR1_DIR}/PHY/INIT/lte_init.c ) @@ -917,7 +911,6 @@ set(PHY_SRC_UE ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_prach_common.c ${OPENAIR1_DIR}/PHY/nr_phy_common/src/nr_phy_common_csirs.c ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_scrambling.c - ${OPENAIR1_DIR}/PHY/NR_REFSIG/scrambling_luts.c ${OPENAIR1_DIR}/PHY/NR_REFSIG/refsig.c ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c ) @@ -1114,7 +1107,6 @@ set(L2_SRC ${PDCP_DIR}/pdcp_util.c ${PDCP_DIR}/pdcp_security.c ${OPENAIR2_DIR}/LAYER2/openair2_proc.c -# ${RRC_DIR}/rrc_UE.c ${RRC_DIR}/rrc_eNB.c ${RRC_DIR}/rrc_eNB_endc.c ${RRC_DIR}/rrc_eNB_S1AP.c @@ -1129,7 +1121,6 @@ set(L2_SRC set(L2_RRC_SRC ${OPENAIR2_DIR}/LAYER2/openair2_proc.c - # ${RRC_DIR}/rrc_UE.c ${RRC_DIR}/rrc_eNB.c ${RRC_DIR}/rrc_eNB_endc.c ${RRC_DIR}/rrc_eNB_S1AP.c @@ -1368,6 +1359,7 @@ target_link_libraries(L2_UE PRIVATE asn1_lte_rrc_hdrs) add_library( NR_L2_UE ${NR_L2_SRC_UE} ${MAC_NR_SRC_UE} ) target_link_libraries(NR_L2_UE PRIVATE f1ap nr_rlc) target_link_libraries(NR_L2_UE PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs nr_common nr_ue_power_procedures nr_ue_ra_procedures) +target_link_libraries(NR_L2_UE PRIVATE nr_nas) add_library(MAC_NR_COMMON ${OPENAIR2_DIR}/LAYER2/NR_MAC_COMMON/nr_mac_common.c @@ -1412,6 +1404,7 @@ add_library(SCTP_CLIENT ${SCTP_SRC}) target_link_libraries(SCTP_CLIENT PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) set(NAS_SRC ${OPENAIR3_DIR}/NAS/) + set(libnas_api_OBJS ${NAS_SRC}COMMON/API/NETWORK/as_message.c ${NAS_SRC}COMMON/API/NETWORK/nas_message.c @@ -1451,10 +1444,6 @@ set(libnas_emm_msg_OBJS ${NAS_SRC}COMMON/EMM/MSG/UplinkNasTransport.c ) -set(libnas_fgs_msg_OBJS - ${NAS_SRC}COMMON/EMM/MSG/fgs_service_request.c -) - set(libnas_esm_msg_OBJS ${NAS_SRC}COMMON/ESM/MSG/ActivateDedicatedEpsBearerContextAccept.c ${NAS_SRC}COMMON/ESM/MSG/ActivateDedicatedEpsBearerContextReject.c @@ -1643,61 +1632,6 @@ set(libnas_ue_esm_sap_OBJS ${NAS_SRC}UE/ESM/SAP/esm_sap.c ) -set(libnrnas_emm_msg_OBJS - ${NAS_SRC}COMMON/EMM/MSG/RegistrationRequest.c - ${NAS_SRC}COMMON/EMM/MSG/RegistrationAccept.c - ${NAS_SRC}COMMON/EMM/MSG/FGSIdentityResponse.c - ${NAS_SRC}COMMON/EMM/MSG/FGSAuthenticationResponse.c - ${NAS_SRC}COMMON/EMM/MSG/FGSNASSecurityModeComplete.c - ${NAS_SRC}COMMON/EMM/MSG/RegistrationComplete.c - ${NAS_SRC}COMMON/EMM/MSG/FGSUplinkNasTransport.c - ${NAS_SRC}COMMON/ESM/MSG/PduSessionEstablishRequest.c - ${NAS_SRC}COMMON/ESM/MSG/PduSessionEstablishmentAccept.c - ${NAS_SRC}COMMON/EMM/MSG/FGSDeregistrationRequestUEOriginating.c - ) - -set(libnrnas_ies_OBJS - ${NAS_SRC}COMMON/IES/ExtendedProtocolDiscriminator.c - ${NAS_SRC}COMMON/IES/FGSMobileIdentity.c - ${NAS_SRC}COMMON/IES/FGSRegistrationType.c - ${NAS_SRC}COMMON/IES/SpareHalfOctet.c - ${NAS_SRC}COMMON/IES/FGSRegistrationResult.c - ${NAS_SRC}COMMON/IES/FGMMCapability.c - ${NAS_SRC}COMMON/IES/NrUESecurityCapability.c - ${NAS_SRC}COMMON/IES/FGCNasMessageContainer.c - ${NAS_SRC}COMMON/IES/SORTransparentContainer.c - ) - -add_library(LIB_NAS_SIMUE - ${NAS_SRC}UE/nas_itti_messaging.c - ${NAS_SRC}UE/nas_network.c - ${NAS_SRC}UE/nas_parser.c - ${NAS_SRC}UE/nas_proc.c - ${NAS_SRC}UE/nas_user.c - ${NAS_SRC}NR_UE/nr_nas_msg.c - ${libnas_api_OBJS} - ${libnas_ue_api_OBJS} - ${libnas_emm_msg_OBJS} - ${libnas_fgs_msg_OBJS} - ${libnas_esm_msg_OBJS} - ${libnas_ies_OBJS} - ${libnas_utils_OBJS} - ${libnas_ue_emm_OBJS} - ${libnas_ue_emm_sap_OBJS} - ${libnas_ue_esm_OBJS} - ${libnas_ue_esm_sap_OBJS} - ${libnrnas_emm_msg_OBJS} - ${libnrnas_ies_OBJS} - $ - ) -target_include_directories(LIB_NAS_SIMUE PRIVATE ${OPENAIR_DIR}/common/utils/ds/) -target_link_libraries(LIB_NAS_SIMUE PRIVATE lte_rrc) - - - -set(NAS_SIM_LIB LIB_NAS_SIMUE) -target_link_libraries(LIB_NAS_SIMUE PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) - add_library(LIB_NAS_UE ${NAS_SRC}UE/nas_itti_messaging.c ${NAS_SRC}UE/nas_network.c @@ -1737,15 +1671,6 @@ set (NBIOT_SOURCES ) add_library(NB_IoT MODULE ${NBIOT_SOURCES} ) -add_library(LIB_5GNAS_GNB - ${NAS_SRC}/COMMON/nr_common.c - ${OPENAIR3_DIR}//UICC/usim_interface.c - ) - -target_include_directories(LIB_5GNAS_GNB PRIVATE ${OPENAIR_DIR}/common/utils/ds/) -target_link_libraries(LIB_5GNAS_GNB PRIVATE SECURITY) -target_link_libraries(LIB_5GNAS_GNB PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) - # Simulation library ########################## set (SIMUSRC @@ -1963,7 +1888,6 @@ add_executable(nr-uesoftmodem ${OPENAIR_DIR}/radio/COMMON/common_lib.c ${OPENAIR_DIR}/radio/COMMON/record_player.c ${OPENAIR2_DIR}/LAYER2/NR_MAC_COMMON/nr_mac_common.c - ${OPENAIR3_DIR}/NAS/UE/nas_ue_task.c ${OPENAIR1_DIR}/PHY/TOOLS/phy_scope_interface.c ) @@ -1972,11 +1896,12 @@ target_link_libraries(nr-uesoftmodem PRIVATE nr_rrc SECURITY UTIL HASHTABLE SCHED_RU_LIB SCHED_NR_UE_LIB PHY_COMMON PHY_NR_COMMON PHY_NR_UE NR_L2_UE L2_UE_LTE_NR MAC_NR_COMMON NFAPI_LIB NFAPI_PNF_LIB NFAPI_USER_LIB MISC_NFAPI_NR_LIB - ITTI LIB_5GNAS_GNB LIB_NAS_SIMUE ${NAS_SIM_LIB} SIMU shlib_loader + ITTI SIMU shlib_loader -Wl,--end-group z dl) target_link_libraries(nr-uesoftmodem PRIVATE pthread m CONFIG_LIB rt nr_ue_phy_meas) target_link_libraries(nr-uesoftmodem PRIVATE ${T_LIB}) +target_link_libraries(nr-uesoftmodem PRIVATE nr_nas lib_uicc usim_lib) target_link_libraries(nr-uesoftmodem PRIVATE asn1_nr_rrc_hdrs asn1_lte_rrc_hdrs) # force the generation of ASN.1 so that we don't need to wait during the build @@ -2169,10 +2094,6 @@ foreach(myExe s1ap ) endforeach(myExe) -# to be added -#../targets/TEST/PDCP/test_pdcp.c -#../targets/TEST/PDCP/with_rlc/test_pdcp_rlc.c - #ensure that the T header files are generated before targets depending on them if (${T_TRACER}) foreach(i diff --git a/ci-scripts/Jenkinsfile-colosseum b/ci-scripts/Jenkinsfile-colosseum index 462f94fe39..a62d4dbc0f 100644 --- a/ci-scripts/Jenkinsfile-colosseum +++ b/ci-scripts/Jenkinsfile-colosseum @@ -20,8 +20,8 @@ * contact@openairinterface.org */ -def node = "porcepix" -def resource = "CI-NEU-CI" +def node = "${params.JenkinsNode}" +def resource = "${params.JenkinsResource}" pipeline { agent { diff --git a/ci-scripts/conf_files/gnb.sa.band78.106prb.usrpb200.sc-fdma.conf b/ci-scripts/conf_files/gnb.sa.band78.106prb.usrpb200.sc-fdma.conf index 824c0a8cc2..c2960b3aa7 100644 --- a/ci-scripts/conf_files/gnb.sa.band78.106prb.usrpb200.sc-fdma.conf +++ b/ci-scripts/conf_files/gnb.sa.band78.106prb.usrpb200.sc-fdma.conf @@ -66,7 +66,7 @@ gNBs = initialULBWPsubcarrierSpacing = 1; #rach-ConfigCommon #rach-ConfigGeneric - prach_ConfigurationIndex = 98; + prach_ConfigurationIndex = 154; #prach_msg1_FDM #0 = one, 1=two, 2=four, 3=eight prach_msg1_FDM = 0; @@ -133,11 +133,21 @@ gNBs = # pattern1 # dl_UL_TransmissionPeriodicity # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 - dl_UL_TransmissionPeriodicity = 6; - nrofDownlinkSlots = 7; - nrofDownlinkSymbols = 6; - nrofUplinkSlots = 2; - nrofUplinkSymbols = 4; + # ext: 8=ms3, 9=ms4 + dl_UL_TransmissionPeriodicity = 8; + nrofDownlinkSlots = 3; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + # pattern2 + pattern2: { + dl_UL_TransmissionPeriodicity2 = 4; + nrofDownlinkSlots2 = 4; + nrofDownlinkSymbols2 = 0; + nrofUplinkSlots2 = 0; + nrofUplinkSymbols2 = 0; + }; ssPBCH_BlockPower = -25; } diff --git a/ci-scripts/xml_files/container_sa_sc_b200_quectel.xml b/ci-scripts/xml_files/container_sa_sc_b200_quectel.xml index a8515f3ec0..0c76a17eb9 100644 --- a/ci-scripts/xml_files/container_sa_sc_b200_quectel.xml +++ b/ci-scripts/xml_files/container_sa_sc_b200_quectel.xml @@ -21,8 +21,8 @@ --> - TEST-SA-FR1-SC-FDMA-B200 - 40 MHz TDD SA with SC-FDMA + TEST-SA-FR1-SC-PATTERN2-FDMA-B200 + 40 MHz TDD (pattern2) SA with SC-FDMA tasks 300000 @@ -101,7 +101,7 @@ Deploy_Object - Deploy gNB (TDD/Band78/40MHz/B200) with SC-FDMA in a container + Deploy gNB (TDD/pattern2/Band78/40MHz/B200) with SC-FDMA in a container ci-scripts/yaml_files/sa_sc_b200_gnb 0 0 diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index d6d3720bca..27bb63ff89 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -46,7 +46,7 @@ BUILD_DOXYGEN=0 DISABLE_HARDWARE_DEPENDENCY="False" CMAKE_BUILD_TYPE="RelWithDebInfo" CMAKE_CMD="$CMAKE" -OPTIONAL_LIBRARIES="telnetsrv enbscope uescope nrscope ldpc_cuda ldpc_t2 ldpc_xdma websrv oai_iqplayer imscope" +OPTIONAL_LIBRARIES="telnetsrv enbscope uescope nrscope ldpc_cuda ldpc_t2 ldpc_xdma websrv oai_iqplayer imscope imscope_record" TARGET_LIST="" BUILD_TOOL_OPT="-j$(nproc)" diff --git a/common/platform_types.h b/common/platform_types.h index cb3d872804..1001a454a9 100644 --- a/common/platform_types.h +++ b/common/platform_types.h @@ -288,6 +288,12 @@ typedef struct protocol_ctxt_s { #define CHECK_CTXT_ARGS(CTXT_Pp) + +static inline int ceil_mod(const unsigned int v, const unsigned int mod) +{ + return ((v + mod - 1) / mod) * mod; +} + #define exit_fun(msg) exit_function(__FILE__, __FUNCTION__, __LINE__, "exit_fun", OAI_EXIT_NORMAL) #ifdef __cplusplus extern "C" { diff --git a/common/utils/nr/nr_common.c b/common/utils/nr/nr_common.c index 516c94cb46..9b029657ad 100644 --- a/common/utils/nr/nr_common.c +++ b/common/utils/nr/nr_common.c @@ -109,8 +109,6 @@ static const unsigned short srs_bandwidth_config[C_SRS_NUMBER][B_SRS_NUMBER][2] /* 63 */ {{272, 1}, {16, 17}, {8, 2}, {4, 2}}, }; -const char *duplex_mode[]={"FDD","TDD"}; - static const uint8_t bit_reverse_table_256[] = { 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, @@ -126,6 +124,36 @@ static const uint8_t bit_reverse_table_256[] = { 0x3B, 0xBB, 0x7B, 0xFB, 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF}; +simde__m128i byte2bit16_lut[256]; +void init_byte2bit16(void) +{ + for (int s = 0; s < 256; s++) { + byte2bit16_lut[s] = simde_mm_insert_epi16(byte2bit16_lut[s], s & 1, 0); + byte2bit16_lut[s] = simde_mm_insert_epi16(byte2bit16_lut[s], (s >> 1) & 1, 1); + byte2bit16_lut[s] = simde_mm_insert_epi16(byte2bit16_lut[s], (s >> 2) & 1, 2); + byte2bit16_lut[s] = simde_mm_insert_epi16(byte2bit16_lut[s], (s >> 3) & 1, 3); + byte2bit16_lut[s] = simde_mm_insert_epi16(byte2bit16_lut[s], (s >> 4) & 1, 4); + byte2bit16_lut[s] = simde_mm_insert_epi16(byte2bit16_lut[s], (s >> 5) & 1, 5); + byte2bit16_lut[s] = simde_mm_insert_epi16(byte2bit16_lut[s], (s >> 6) & 1, 6); + byte2bit16_lut[s] = simde_mm_insert_epi16(byte2bit16_lut[s], (s >> 7) & 1, 7); + } +} + +simde__m128i byte2m128i[256]; +void init_byte2m128i(void) { + + for (int s=0;s<256;s++) { + byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s],(1-2*(s&1)),0); + byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s],(1-2*((s>>1)&1)),1); + byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s],(1-2*((s>>2)&1)),2); + byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s],(1-2*((s>>3)&1)),3); + byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s],(1-2*((s>>4)&1)),4); + byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s],(1-2*((s>>5)&1)),5); + byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s],(1-2*((s>>6)&1)),6); + byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s],(1-2*((s>>7)&1)),7); + } +} + void reverse_bits_u8(uint8_t const* in, size_t sz, uint8_t* out) { DevAssert(in != NULL); @@ -676,9 +704,12 @@ uint64_t from_nrarfcn(int nr_bandP, uint8_t scs_index, uint32_t nrarfcn) return frequency; } -int get_first_ul_slot(int nrofDownlinkSlots, int nrofDownlinkSymbols, int nrofUplinkSymbols) +/** + * @brief Get the slot index within the period + */ +int get_slot_idx_in_period(const int slot, const frame_structure_t *fs) { - return (nrofDownlinkSlots + (nrofDownlinkSymbols != 0 && nrofUplinkSymbols == 0)); + return slot % fs->numb_slots_period; } int get_dmrs_port(int nl, uint16_t dmrs_ports) @@ -704,7 +735,7 @@ frame_type_t get_frame_type(uint16_t current_band, uint8_t scs_index) { int32_t delta_duplex = get_delta_duplex(current_band, scs_index); frame_type_t current_type = delta_duplex == 0 ? TDD : FDD; - LOG_D(NR_MAC, "NR band %d, duplex mode %s, duplex spacing = %d KHz\n", current_band, duplex_mode[current_type], delta_duplex); + LOG_D(NR_MAC, "NR band %d, duplex mode %s, duplex spacing = %d KHz\n", current_band, duplex_mode_txt[current_type], delta_duplex); return current_type; } diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h index 1408f271b0..bdd10e7896 100644 --- a/common/utils/nr/nr_common.h +++ b/common/utils/nr/nr_common.h @@ -122,6 +122,29 @@ typedef enum frequency_range_e { FR2 } frequency_range_t; +#define MAX_NUM_SLOTS_ALLOWED 80 // up to numerology 3 (120 KHz SCS) is supported +enum slot_type { TDD_NR_DOWNLINK_SLOT, TDD_NR_UPLINK_SLOT, TDD_NR_MIXED_SLOT }; + +typedef struct tdd_bitmap { + enum slot_type slot_type; + uint8_t num_dl_symbols; + uint8_t num_ul_symbols; +} tdd_bitmap_t; + +typedef struct tdd_period_config_s { + tdd_bitmap_t tdd_slot_bitmap[MAX_NUM_SLOTS_ALLOWED]; + uint8_t num_dl_slots; + uint8_t num_ul_slots; +} tdd_period_config_t; + +typedef struct frame_structure_s { + tdd_period_config_t period_cfg; + int8_t numb_slots_frame; + int8_t numb_slots_period; + int8_t numb_period_frame; + bool is_tdd; +} frame_structure_t; + typedef struct { /// Time shift in number of samples estimated based on DMRS-PDSCH/PUSCH int est_delay; @@ -183,6 +206,15 @@ uint32_t nr_timer_elapsed_time(const NR_timer_t *timer); int set_default_nta_offset(frequency_range_t freq_range, uint32_t samples_per_subframe); extern const nr_bandentry_t nr_bandtable[]; +extern simde__m128i byte2bit16_lut[256]; +void init_byte2bit16(void); +void init_byte2m128i(void); + +static inline simde__m128i byte2bit16(uint8_t b) +{ + return byte2bit16_lut[b]; +} + static inline int get_num_dmrs(uint16_t dmrs_mask ) { int num_dmrs=0; @@ -210,7 +242,6 @@ void reverse_bits_u8(uint8_t const* in, size_t sz, uint8_t* out); uint64_t from_nrarfcn(int nr_bandP, uint8_t scs_index, uint32_t dl_nrarfcn); uint32_t to_nrarfcn(int nr_bandP, uint64_t dl_CarrierFreq, uint8_t scs_index, uint32_t bw); -int get_first_ul_slot(int nrofDownlinkSlots, int nrofDownlinkSymbols, int nrofUplinkSymbols); int cce_to_reg_interleaving(const int R, int k, int n_shift, const int C, int L, const int N_regs); int get_SLIV(uint8_t S, uint8_t L); void get_coreset_rballoc(uint8_t *FreqDomainResource,int *n_rb,int *rb_offset); @@ -256,11 +287,12 @@ int get_smallest_supported_bandwidth_index(int scs, frequency_range_t frequency_ unsigned short get_m_srs(int c_srs, int b_srs); unsigned short get_N_b_srs(int c_srs, int b_srs); +int get_slot_idx_in_period(const int slot, const frame_structure_t *fs); + #define CEILIDIV(a,b) ((a+b-1)/b) #define ROUNDIDIV(a,b) (((a<<1)+b)/(b<<1)) -// Align up to a multiple of 16 -#define ALIGN_UP_16(a) ((a + 15) & ~15) +static const char *const duplex_mode_txt[] = {"FDD", "TDD"}; #ifdef __cplusplus #ifdef min diff --git a/doc/Doxyfile b/doc/Doxyfile index 023fe84693..59a984e79f 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -1133,7 +1133,7 @@ INPUT = \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/UICC/usim_interface.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/ocp-gtpu/gtp_itf.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/NR_UE/nr_nas_msg.h \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/NR_UE/nr_nas_msgc \ +@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/NR_UE/nr_nas_msg.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/UE/nas_itti_messaging.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/UE/user_defs.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/UE/EMM/emm_proc.h \ @@ -1274,12 +1274,10 @@ INPUT = \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/EMM/MSG/emm_msg.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/EMM/MSG/AttachReject.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/EMM/MSG/SecurityModeReject.h \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/EMM/MSG/FGSDeregistrationRequestUEOriginating.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/EMM/MSG/UplinkNasTransport.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/EMM/MSG/AuthenticationFailure.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/EMM/MSG/AuthenticationResponse.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/EMM/MSG/AttachComplete.h \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/EMM/MSG/FGSNASSecurityModeComplete.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/EMM/MSG/ExtendedServiceRequest.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/EMM/MSG/GutiReallocationComplete.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/EMM/MSG/DownlinkNasTransport.h \ @@ -1289,7 +1287,6 @@ INPUT = \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/EMM/MSG/AttachReject.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/EMM/MSG/AttachAccept.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/EMM/MSG/ServiceReject.h \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/EMM/MSG/FGSIdentityResponse.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/EMM/MSG/AttachComplete.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/EMM/MSG/AttachRequest.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/EMM/MSG/AuthenticationRequest.c \ @@ -1301,17 +1298,14 @@ INPUT = \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/EMM/MSG/AttachAccept.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/EMM/MSG/IdentityResponse.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/EMM/MSG/GutiReallocationComplete.h \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/EMM/MSG/RegistrationComplete.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/EMM/MSG/ServiceRequest.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/EMM/MSG/RegistrationAccept.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/EMM/MSG/IdentityRequest.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/EMM/MSG/RegistrationRequest.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/EMM/MSG/DetachAccept.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/EMM/MSG/AttachRequest.c \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/EMM/MSG/FGSIdentityResponse.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/EMM/MSG/EmmStatus.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/EMM/MSG/AuthenticationFailure.h \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/EMM/MSG/FGSAuthenticationResponse.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/EMM/MSG/AuthenticationReject.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/EMM/MSG/TrackingAreaUpdateAccept.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/EMM/MSG/TrackingAreaUpdateRequest.h \ @@ -1321,13 +1315,14 @@ INPUT = \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/EMM/MSG/FGSNASSecurityModeComplete.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/EMM/MSG/IdentityResponse.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/EMM/MSG/RegistrationComplete.c \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/EMM/MSG/FGSDeregistrationRequestUEOriginating.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/EMM/MSG/emm_cause.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/EMM/MSG/EmmInformation.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/EMM/MSG/IdentityRequest.h \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/EMM/MSG/FGSUplinkNasTransport.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/EMM/MSG/GutiReallocationCommand.h \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/EMM/MSG/RegistrationRequest.h \ +@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/NR_UE/5GS/5GMM/MSG \ +@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/NR_UE/5GS/5GMM/IES \ +@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/NR_UE/5GS/5GSM \ +@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/NR_UE/5GS/5GSM/MSG \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/UTIL/parser.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/UTIL/device.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/UTIL/device.c \ @@ -1353,7 +1348,6 @@ INPUT = \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/AuthenticationParameterRand.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/UeRadioCapabilityInformationUpdateNeeded.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/ProtocolDiscriminator.h \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/ExtendedProtocolDiscriminator.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/CsfbResponse.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/EsmCause.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/ProcedureTransactionIdentity.h \ @@ -1367,7 +1361,6 @@ INPUT = \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/LlcServiceAccessPointIdentifier.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/ProtocolConfigurationOptions.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/TransactionIdentifier.h \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/ExtendedProtocolDiscriminator.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/GutiType.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/SupportedCodecList.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/MobileStationClassmark3.c \ @@ -1391,12 +1384,10 @@ INPUT = \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/UeSecurityCapability.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/ApnAggregateMaximumBitRate.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/ImeisvRequest.c \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/SpareHalfOctet.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/PdnType.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/ShortMac.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/MobileStationClassmark3.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/TrafficFlowTemplate.h \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/SORTransparentContainer.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/NasPagingIdentity.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/NasMessageContainer.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/Cli.h \ @@ -1406,18 +1397,15 @@ INPUT = \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/DetachType.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/EmergencyNumberList.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/EsmMessageContainer.c \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/FGSRegistrationResult.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/GprsTimer.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/TmsiStatus.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/VoiceDomainPreferenceAndUeUsageSetting.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/IdentityType2.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/EpsQualityOfService.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/LocationAreaIdentification.h \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/FGCNasMessageContainer.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/TrackingAreaIdentityList.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/MsNetworkCapability.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/ShortMac.c \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/FGSRegistrationResult.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/AuthenticationFailureParameter.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/TrackingAreaIdentity.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/EmmCause.h \ @@ -1432,12 +1420,10 @@ INPUT = \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/AuthenticationParameterAutn.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/PdnAddress.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/EsmInformationTransferFlag.c \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/SpareHalfOctet.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/KsiAndSequenceNumber.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/LocationAreaIdentification.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/QualityOfService.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/ProcedureTransactionIdentity.c \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/NrUESecurityCapability.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/ProtocolConfigurationOptions.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/SsCode.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/EpsQualityOfService.h \ @@ -1447,12 +1433,10 @@ INPUT = \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/EpsMobileIdentity.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/MobileIdentity.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/SsCode.h \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/FGSRegistrationType.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/TrackingAreaIdentity.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/EpsBearerIdentity.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/NasMessageContainer.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/DetachType.h \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/FGMMCapability.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/TmsiStatus.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/MobileStationClassmark2.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/MessageType.c \ @@ -1466,13 +1450,10 @@ INPUT = \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/AdditionalUpdateType.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/NasRequestType.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/EpsBearerContextStatus.h \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/FGSMobileIdentity.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/LcsClientIdentity.h \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/FGSMobileIdentity.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/ServiceType.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/PagingIdentity.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/UeNetworkCapability.c \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/NrUESecurityCapability.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/AuthenticationParameterAutn.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/PdnAddress.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/EpsUpdateType.h \ @@ -1480,7 +1461,6 @@ INPUT = \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/PTmsiSignature.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/PacketFlowIdentifier.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/UeRadioCapabilityInformationUpdateNeeded.h \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/FGCNasMessageContainer.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/PTmsiSignature.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/EpsMobileIdentity.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/GutiType.h \ @@ -1496,16 +1476,13 @@ INPUT = \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/NasKeySetIdentifier.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/EpsAttachResult.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/AccessPointName.h \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/FGMMCapability.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/AdditionalUpdateResult.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/EpsAttachType.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/UeNetworkCapability.h \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/FGSDeregistrationType.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/EsmMessageContainer.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/SecurityHeaderType.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/EsmCause.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/NasSecurityAlgorithms.c \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/SORTransparentContainer.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/LinkedEpsBearerIdentity.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/AdditionalUpdateType.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/MsNetworkFeatureSupport.c \ @@ -1518,14 +1495,12 @@ INPUT = \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/EpsBearerIdentity.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/EsmInformationTransferFlag.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/TimeZoneAndTime.c \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/FGSRegistrationType.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/EpsUpdateResult.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/EpsUpdateType.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/AuthenticationResponseParameter.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/NetworkName.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/LinkedEpsBearerIdentity.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/IES/SupportedCodecList.c \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/NR_NAS_defs.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/milenage.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/ESM/MSG/EsmStatus.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/ESM/MSG/ModifyEpsBearerContextReject.h \ @@ -1580,7 +1555,6 @@ INPUT = \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/ESM/MSG/EsmInformationResponse.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/ESM/MSG/ActivateDefaultEpsBearerContextAccept.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/userDef.h \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair3/NAS/COMMON/nr_common.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair3/UTILS/conversions.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/X2AP/x2ap_eNB_encoder.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair2/X2AP/x2ap_eNB_management_procedures.c \ @@ -2085,7 +2059,6 @@ INPUT = \ @CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_REFSIG/ul_ref_seq_nr.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_REFSIG/ul_ref_seq_nr.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_REFSIG/sss_nr.h \ -@CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_REFSIG/scrambling_luts.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_REFSIG/dmrs_nr.c \ @CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_REFSIG/refsig_defs_ue.h \ @CMAKE_CURRENT_SOURCE_DIR@/../openair1/PHY/NR_REFSIG/ptrs_nr.h \ diff --git a/doc/FEATURE_SET.md b/doc/FEATURE_SET.md index 454faf1a1e..567187ac60 100644 --- a/doc/FEATURE_SET.md +++ b/doc/FEATURE_SET.md @@ -24,7 +24,9 @@ The following features are valid for the gNB and the 5G-NR UE. -* Static TDD, FDD +* Static TDD + - Multi TDD pattern supported refer [TDD Configuration](NR_SA_Multi_TDD_Pattern.md) +* Static FDD * Normal CP * Subcarrier spacings: 15 and 30kHz (FR1), 120kHz (FR2) * Bandwidths: 10, 20, 40, 60, 80, 100MHz diff --git a/doc/MAC/TDD_Frame_Structure.png b/doc/MAC/TDD_Frame_Structure.png new file mode 100644 index 0000000000..611be183d7 Binary files /dev/null and b/doc/MAC/TDD_Frame_Structure.png differ diff --git a/doc/MAC/mac-usage.md b/doc/MAC/mac-usage.md index c3dbd6f199..f96f94d522 100644 --- a/doc/MAC/mac-usage.md +++ b/doc/MAC/mac-usage.md @@ -240,3 +240,115 @@ here, *also they pertain to the DU*, i.e., the scheduler. options are 2, 4, 6, 8, 10, 12, 32; **32 is a Rel-17 features**) * `num_ulharq` (default 16): as `num_dlharq` for UL (other valid option is 32; **32 is i Rel-17 feature**) + +## ServingCellConfigCommon parameters + +The `gNBs` configuration section has a big structure `servingCellConfigCommon` +that has an influence on the overall behavior of MAC and L1. As the name says, +this structure is a flat representation of the ServingCellConfigCommon +structure, specified by 3GPP. Describing all of these parameters would be too +exhaustive; more information about the individual fields can be found in 3GPP +TS 38.331, section 6.3.2 "Radio resource control information elements". + +Below is a description of some of these parameters. + +### Frequency configuration + +There are many parameters, such as `absoluteFrequencySSB`, etc., that have an +impact on the frequency used by the gNB. For more information, please check the +[corresponding document](../gNB_frequency_setup.md). + +### TDD pattern configuration + +The TDD configuration parameters allow to use one or two TDD patterns. + +#### Single TDD pattern + +Configure the TDD pattern through these options: +- `dl_UL_TransmissionPeriodicity`: Refers to the UL/DL slots periodicity for + the TDD pattern. See below for valid numbers. +- `nrofDownlinkSlots`: Refers to the number of consecutive DL slots in the TDD + pattern. The number of DL slots depends on the TDD period. +- `nrofDownlinkSymbols`: Indicates the number of consecutive DL symbols within + the special slot that follows the downlink slots in the TDD pattern. The + special slot is needed only to switch from DL to UL. The maximum number of + symbols in this slot is 14. +- `nrofUplinkSlots`: Refers to the number of consecutive UL slots in the TDD + pattern, depending on the desired TDD period. +- `nrofUplinkSymbols`: Indicates the number of consecutive UL symbols within + the special slot that follows the downlink slots in the TDD pattern. The sum + of downlink and uplink symbols should not exceed 14. +- `prach_ConfigurationIndex`: index for PRACH according to tables 6.3.3.2-2 to + 6.3.3.2-4 in TS 38.211. + +As an example, the below figure shows a single TDD pattern, consisting of 3 DL +slots, 1 mixed slots (with 10 DL, 2 guard, 2 UL symbols), and 1 UL slot. + +![TDD Frame Structure](TDD_Frame_Structure.png) + +To configure this pattern in the configuration file, use + +```plaintext +#dl_UL_TransmissionPeriodicity 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10, 8=ms3, 9=ms4 + +dl_UL_TransmissionPeriodicity = 5; +nrofDownlinkSlots = 3; +nrofDownlinkSymbols = 10; +nrofUplinkSlots = 1; +nrofUplinkSymbols = 2; +``` + +The `dl_UL_TransmissionPeriodicity` is set to `5` (2.5ms). The above figure +shows two TDD periods over 5ms. The 10 ms frame period must be strictly +divisible by the sum of the TDD pattern periods. + +#### Two TDD patterns + +An optional `pattern2` structure is used to signal a TDD pattern 2. +In this case, the TDD pattern may have two extended values of 3 ms and 4 ms. +These values are standardized as `dl-UL-TransmissionPeriodicity-v1530`. For the +sake of simplicity of the gNB configuration file, we have extended the set of +`dl-UL-TransmissionPeriodicity` values to support the new TDD periods, as +explained in the table below. However, these values will later be encoded as +`dl-UL-TransmissionPeriodicity-v1530` to match the specifications. + +| `dl_UL_TransmissionPeriodicity` | TDD period | +|---------------------------------|------------| +| 0 | 0.5 ms | +| 1 | 0.625 ms | +| 2 | 1 ms | +| 3 | 1.25 ms | +| 4 | 2 ms | +| 5 | 2.5 ms | +| 6 | 5 ms | +| 7 | 10 ms | +| 8 | 3 ms | +| 9 | 4 ms | + +The 10 ms frame period must be strictly divisible by the sum of the TDD pattern +periods. For example, the 3 ms TDD pattern should be used with a second TDD +pattern of 2 ms. Additionally, the 4 ms TDD pattern should be used with a +second TDD pattern of 1 ms. + +As an example, this configuration might be used, where the first TDD pattern is +followed by a second, consisting of 4 DL slots. +``` +# pattern1 +# dl_UL_TransmissionPeriodicity +# 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 +# ext: 8=ms3, 9=ms4 +dl_UL_TransmissionPeriodicity = 8; +nrofDownlinkSlots = 3; +nrofDownlinkSymbols = 6; +nrofUplinkSlots = 2; +nrofUplinkSymbols = 4; + +# pattern2 +pattern2: { + dl_UL_TransmissionPeriodicity2 = 4; + nrofDownlinkSlots2 = 4; + nrofDownlinkSymbols2 = 0; + nrofUplinkSlots2 = 0; + nrofUplinkSymbols2 = 0; +}; +``` diff --git a/doc/README.md b/doc/README.md index 2e84db217c..13028479cd 100644 --- a/doc/README.md +++ b/doc/README.md @@ -135,3 +135,4 @@ The other SDRs (AW2S, LimeSDR, ...) have no READMEs. - [formatting](../tools/formatting/README.md) is a clang-format error detection tool - [iwyu](../tools/iwyu/README.md) is a tool to detect `#include` errors +- [docker-dev-env](../tools/docker-dev-env/README.md) is a ubuntu22 docker development environment diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c index e14e482b6d..5a2e49937b 100644 --- a/executables/nr-softmodem.c +++ b/executables/nr-softmodem.c @@ -86,6 +86,7 @@ unsigned short config_frames[4] = {2,9,11,13}; #include "time_meas.h" #include "utils.h" #include "x2ap_eNB.h" +#include "openair1/SCHED_NR/sched_nr.h" pthread_cond_t nfapi_sync_cond; pthread_mutex_t nfapi_sync_mutex; @@ -116,8 +117,7 @@ double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0},{20,0,0,0}}; double rx_gain_off = 0.0; static int tx_max_power[MAX_NUM_CCs]; /* = {0,0}*/; -int chain_offset=0; -extern void *udp_eNB_task(void *args_p); +int chain_offset = 0; int emulate_rf = 0; int numerology = 0; double cpuf; @@ -398,9 +398,6 @@ void terminate_task(task_id_t task_id, module_id_t mod_id) { itti_send_msg_to_task (task_id, ENB_MODULE_ID_TO_INSTANCE(mod_id), msg); } -//extern void free_transport(PHY_VARS_gNB *); -extern void nr_phy_free_RU(RU_t *); - int stop_L1(module_id_t gnb_id) { RU_t *ru = RC.ru[gnb_id]; @@ -701,7 +698,7 @@ int main( int argc, char **argv ) { wait_RUs(); // once all RUs are ready initialize the rest of the gNBs ((dependence on final RU parameters after configuration) - if (IS_SOFTMODEM_DOSCOPE || IS_SOFTMODEM_IMSCOPE_ENABLED) { + if (IS_SOFTMODEM_DOSCOPE || IS_SOFTMODEM_IMSCOPE_ENABLED || IS_SOFTMODEM_IMSCOPE_RECORD_ENABLED) { sleep(1); scopeParms_t p; p.argc = &argc; @@ -714,6 +711,11 @@ int main( int argc, char **argv ) { if (IS_SOFTMODEM_IMSCOPE_ENABLED) { load_softscope("im", &p); } + AssertFatal(!(IS_SOFTMODEM_IMSCOPE_ENABLED && IS_SOFTMODEM_IMSCOPE_RECORD_ENABLED), + "Data recoding and ImScope cannot be enabled at the same time\n"); + if (IS_SOFTMODEM_IMSCOPE_RECORD_ENABLED) { + load_module_shlib("imscope_record", NULL, 0, &p); + } } if (NFAPI_MODE != NFAPI_MODE_PNF && NFAPI_MODE != NFAPI_MODE_VNF && NFAPI_MODE != NFAPI_MODE_AERIAL) { diff --git a/executables/nr-ue.c b/executables/nr-ue.c index ef45cd3cb7..213263978a 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -569,6 +569,7 @@ void processSlotTX(void *arg) } } RU_write(rxtxD, sl_tx_action); + dynamic_barrier_join(rxtxD->next_barrier); TracyCZoneEnd(ctx); } @@ -1111,8 +1112,19 @@ void *UE_thread(void *arg) int slot = curMsgTx->proc.nr_slot_tx; int slot_and_frame = slot + curMsgTx->proc.frame_tx * UE->frame_parms.slots_per_frame; + int wait_for_prev_slot = stream_status == STREAM_STATUS_SYNCED ? 1 : 0; + + int next_duration_rx_to_tx = + update_ntn_system_information + ? NR_UE_CAPABILITY_SLOT_RX_TO_TX + UE->ntn_config_message->ntn_config_params.cell_specific_k_offset + : duration_rx_to_tx; + int next_nr_slot_tx = (absolute_slot + next_duration_rx_to_tx) % nb_slot_frame; + int next_frame_tx = ((absolute_slot + next_duration_rx_to_tx) / nb_slot_frame) % MAX_FRAME_NUMBER; + int next_tx_slot_and_frame = next_nr_slot_tx + next_frame_tx * UE->frame_parms.slots_per_frame + 1; + dynamic_barrier_t *next_barrier = &UE->process_slot_tx_barriers[next_tx_slot_and_frame % NUM_PROCESS_SLOT_TX_BARRIERS]; + curMsgTx->next_barrier = next_barrier; dynamic_barrier_update(&UE->process_slot_tx_barriers[slot_and_frame % NUM_PROCESS_SLOT_TX_BARRIERS], - tx_wait_for_dlsch[slot], + tx_wait_for_dlsch[slot] + wait_for_prev_slot, start_process_slot_tx, newTx); stream_status = STREAM_STATUS_SYNCED; diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index ca92f30d4f..83bee89c06 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -91,7 +91,6 @@ unsigned short config_frames[4] = {2,9,11,13}; #include "pdcp.h" #include "actor.h" -extern const char *duplex_mode[]; THREAD_STRUCT thread_struct; nrUE_params_t nrUE_params = {0}; @@ -270,12 +269,13 @@ void init_openair0() openair0_cfg[card].tx_num_channels = min(4, frame_parms->nb_antennas_tx); openair0_cfg[card].rx_num_channels = min(4, frame_parms->nb_antennas_rx); - LOG_I(PHY, "HW: Configuring card %d, sample_rate %f, tx/rx num_channels %d/%d, duplex_mode %s\n", - card, - openair0_cfg[card].sample_rate, - openair0_cfg[card].tx_num_channels, - openair0_cfg[card].rx_num_channels, - duplex_mode[openair0_cfg[card].duplex_mode]); + LOG_I(PHY, + "HW: Configuring card %d, sample_rate %f, tx/rx num_channels %d/%d, duplex_mode %s\n", + card, + openair0_cfg[card].sample_rate, + openair0_cfg[card].tx_num_channels, + openair0_cfg[card].rx_num_channels, + duplex_mode_txt[openair0_cfg[card].duplex_mode]); if (is_sidelink) { dl_carrier = frame_parms->dl_CarrierFreq; @@ -532,6 +532,11 @@ int main(int argc, char **argv) if (IS_SOFTMODEM_IMSCOPE_ENABLED) { load_softscope("im", PHY_vars_UE_g[0][0]); } + AssertFatal(!(IS_SOFTMODEM_IMSCOPE_ENABLED && IS_SOFTMODEM_IMSCOPE_RECORD_ENABLED), + "Data recoding and ImScope cannot be enabled at the same time\n"); + if (IS_SOFTMODEM_IMSCOPE_RECORD_ENABLED) { + load_module_shlib("imscope_record", NULL, 0, PHY_vars_UE_g[0][0]); + } for (int inst = 0; inst < NB_UE_INST; inst++) { LOG_I(PHY,"Intializing UE Threads for instance %d ...\n", inst); diff --git a/executables/nr-uesoftmodem.h b/executables/nr-uesoftmodem.h index c323ff18b4..90e32d651b 100644 --- a/executables/nr-uesoftmodem.h +++ b/executables/nr-uesoftmodem.h @@ -43,7 +43,6 @@ {"uecap_file", CONFIG_HLP_UECAP_FILE, 0, .strptr=&nrUE_params.uecap_file, .defstrval="./uecap_ports1.xml", TYPE_STRING, 0}, \ {"reconfig-file", CONFIG_HLP_RE_CFG_FILE, 0, .strptr=&nrUE_params.reconfig_file, .defstrval="./reconfig.raw", TYPE_STRING, 0}, \ {"rbconfig-file", CONFIG_HLP_RB_CFG_FILE, 0, .strptr=&nrUE_params.rbconfig_file, .defstrval="./rbconfig.raw", TYPE_STRING, 0}, \ - {"ue-idx-standalone", NULL, 0, .u16ptr=&ue_idx_standalone, .defuintval=0xFFFF, TYPE_UINT16, 0}, \ {"ue-rxgain", CONFIG_HLP_UERXG, 0, .dblptr=&nrUE_params.rx_gain, .defdblval=110, TYPE_DOUBLE, 0}, \ {"ue-rxgain-off", CONFIG_HLP_UERXGOFF, 0, .dblptr=&nrUE_params.rx_gain_off, .defdblval=0, TYPE_DOUBLE, 0}, \ {"ue-txgain", CONFIG_HLP_UETXG, 0, .dblptr=&nrUE_params.tx_gain, .defdblval=0, TYPE_DOUBLE, 0}, \ diff --git a/executables/softmodem-common.c b/executables/softmodem-common.c index 92c913c88e..09fced4aa3 100644 --- a/executables/softmodem-common.c +++ b/executables/softmodem-common.c @@ -77,6 +77,7 @@ void get_common_options(configmodule_interface_t *cfg) uint32_t noS1 = 0, nonbiot = 0; uint32_t rfsim = 0, do_forms = 0; uint32_t enable_imscope = 0; + uint32_t enable_imscope_record = 0; int nfapi_index = 0; char *logmem_filename = NULL; @@ -141,6 +142,10 @@ void get_common_options(configmodule_interface_t *cfg) IS_SOFTMODEM_IMSCOPE_ENABLED = true; } + if (enable_imscope_record) { + IS_SOFTMODEM_IMSCOPE_RECORD_ENABLED = true; + } + if (start_websrv) { load_module_shlib("websrv", NULL, 0, NULL); } diff --git a/executables/softmodem-common.h b/executables/softmodem-common.h index 2e7aaacc21..348920868c 100644 --- a/executables/softmodem-common.h +++ b/executables/softmodem-common.h @@ -80,6 +80,7 @@ extern "C" #define CONFIG_HLP_CHESTFREQ "Set channel estimation type in frequency domain. 0-Linear interpolation (default). 1-PRB based averaging of channel estimates in frequency. \n" #define CONFIG_HLP_CHESTTIME "Set channel estimation type in time domain. 0-Symbols take estimates of the last preceding DMRS symbol (default). 1-Symbol based averaging of channel estimates in time. \n" #define CONFIG_HLP_IMSCOPE "Enable phy scope based on imgui and implot" +#define CONFIG_HLP_IMSCOPE_RECORD "Enable recording scope data to filesystem" #define CONFIG_HLP_NONSTOP "Go back to frame sync mode after 100 consecutive PBCH failures\n" //#define CONFIG_HLP_NUMUES "Set the number of UEs for the emulation" @@ -186,6 +187,7 @@ extern int usrp_tx_thread; {"A" , CONFIG_HLP_TADV, 0, .iptr=&softmodem_params.command_line_sample_advance,.defintval=0, TYPE_INT, 0}, \ {"E" , CONFIG_HLP_TQFS, PARAMFLAG_BOOL, .iptr=&softmodem_params.threequarter_fs, .defintval=0, TYPE_INT, 0}, \ {"imscope" , CONFIG_HLP_IMSCOPE, PARAMFLAG_BOOL, .uptr=&enable_imscope, .defintval=0, TYPE_UINT, 0}, \ + {"imscope-record" , CONFIG_HLP_IMSCOPE_RECORD,PARAMFLAG_BOOL, .uptr=&enable_imscope_record, .defintval=0, TYPE_UINT, 0}, \ } // clang-format on @@ -231,6 +233,7 @@ extern int usrp_tx_thread; { .s5 = { NULL } }, \ { .s5 = { NULL } }, \ { .s5 = { NULL } }, \ + { .s5 = { NULL } }, \ } // clang-format on @@ -285,6 +288,7 @@ extern int usrp_tx_thread; #define IS_SOFTMODEM_5GUE (get_softmodem_optmask()->bit.SOFTMODEM_5GUE_BIT) #define IS_SOFTMODEM_NOSTATS (get_softmodem_optmask()->bit.SOFTMODEM_NOSTATS_BIT) #define IS_SOFTMODEM_IMSCOPE_ENABLED (get_softmodem_optmask()->bit.SOFTMODEM_IMSCOPE_BIT) +#define IS_SOFTMODEM_IMSCOPE_RECORD_ENABLED (get_softmodem_optmask()->bit.SOFTMODEM_IMSCOPE_RECORD_BIT) typedef struct optmask_s { union { struct { @@ -304,6 +308,7 @@ typedef struct optmask_s { uint64_t SOFTMODEM_5GUE_BIT: 1; uint64_t SOFTMODEM_NOSTATS_BIT: 1; uint64_t SOFTMODEM_IMSCOPE_BIT: 1; + uint64_t SOFTMODEM_IMSCOPE_RECORD_BIT : 1; } bit; uint64_t v; // allow to export entire bit set, force to 64 bit processor atomic size }; @@ -361,6 +366,8 @@ void configure_rru(void *, void *arg); struct timespec timespec_add(struct timespec lhs, struct timespec rhs); struct timespec timespec_sub(struct timespec lhs, struct timespec rhs); extern uint8_t nfapi_mode; +extern char *parallel_config; +extern char *worker_config; #ifdef __cplusplus } #endif diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h index f82c6c414a..a34796eeb3 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h @@ -25,6 +25,7 @@ #define NFAPI_MAX_NUM_CB 8 #define NFAPI_MAX_NUM_PRGS 1 #define NFAPI_MAX_NUM_BG_IF 1 +#define NFAPI_MAX_NUM_PERIODS 8 // Extension to the generic structures for single tlv values @@ -436,7 +437,10 @@ typedef struct typedef struct { - nfapi_uint8_tlv_t tdd_period;//DL UL Transmission Periodicity. Value:0: ms0p5 1: ms0p625 2: ms1 3: ms1p25 4: ms2 5: ms2p5 6: ms5 7: ms10 8: ms3 9: ms4 + /**DL UL Transmission Periodicity: for multiple TDD pattern, + * the value corresponds to the sum periodicity (3GPP TS 38.213, 11.1) + * Values: 0:ms0p5 1:ms0p625 2:ms1 3:ms1p25 4:ms2 5:ms2p5 6:ms5 7:ms10 8:ms20 */ + nfapi_uint8_tlv_t tdd_period; nfapi_nr_max_tdd_periodicity_t* max_tdd_periodicity_list; } nfapi_nr_tdd_table_t; diff --git a/nfapi/open-nFAPI/pnf/src/pnf.c b/nfapi/open-nFAPI/pnf/src/pnf.c index f3e44663f8..3880e53c6c 100644 --- a/nfapi/open-nFAPI/pnf/src/pnf.c +++ b/nfapi/open-nFAPI/pnf/src/pnf.c @@ -669,10 +669,6 @@ void pnf_nr_handle_config_request(pnf_t* pnf, void *pRecvMsg, int recvMsgLen) { nfapi_pnf_phy_config_t* phy = nfapi_pnf_phy_config_find(config, req.header.phy_id); -#if 0 // emulate set_config TLV reception (hard-code) - int tdd_return = set_tdd_config_nr(&req, 1, 7, 6, 2, 4); -#endif - if(phy) { if(phy->state != NFAPI_PNF_PHY_RUNNING) diff --git a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_encoder.c b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_encoder.c index 757566b1fc..adf9dd6624 100644 --- a/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_encoder.c +++ b/openair1/PHY/CODING/nrLDPC_coding/nrLDPC_coding_segment/nrLDPC_coding_segment_encoder.c @@ -44,8 +44,6 @@ // #define DEBUG_LDPC_ENCODING // #define DEBUG_LDPC_ENCODING_FREE 1 -extern ldpc_interface_t ldpc_interface_segment; - typedef struct ldpc8blocks_args_s { nrLDPC_TB_encoding_parameters_t *nrLDPC_TB_encoding_parameters; encoder_implemparams_t impp; diff --git a/openair1/PHY/CODING/nrLDPC_extern.h b/openair1/PHY/CODING/nrLDPC_extern.h index f93e7eb9aa..a0e10db155 100644 --- a/openair1/PHY/CODING/nrLDPC_extern.h +++ b/openair1/PHY/CODING/nrLDPC_extern.h @@ -32,7 +32,7 @@ typedef struct ldpc_interface_s { } ldpc_interface_t; // Global var to limit the rework of the dirty legacy code -extern ldpc_interface_t ldpc_interface, ldpc_interface_offload; +extern ldpc_interface_t ldpc_interface, ldpc_interface_offload, ldpc_interface_segment; /* functions to load the LDPC shared lib, implemented in openair1/PHY/CODING/nrLDPC_load.c */ int load_LDPClib(char *version, ldpc_interface_t *); diff --git a/openair1/PHY/CODING/nrPolar_tools/nr_polar_defs.h b/openair1/PHY/CODING/nrPolar_tools/nr_polar_defs.h index 14d0e9fb2d..485f50f7b1 100644 --- a/openair1/PHY/CODING/nrPolar_tools/nr_polar_defs.h +++ b/openair1/PHY/CODING/nrPolar_tools/nr_polar_defs.h @@ -292,7 +292,7 @@ static inline void nr_polar_deinterleaver(uint8_t *input, uint8_t *output, uint1 * De-interleaving of coded bits implementation * TS 138.212: Section 5.4.1.3 - Interleaving of coded bits */ -static inline void nr_polar_rm_deinterleaving_lut(uint16_t *out, const uint E) +static inline void nr_polar_rm_deinterleaving_lut(uint16_t *out, const int E) { int16_t in[E]; for (uint i = 0; i < E; i++) diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index f3c8d01579..451144dfee 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -129,6 +129,7 @@ void phy_init_nr_gNB(PHY_VARS_gNB *gNB) crcTableInit(); init_byte2m128i(); + init_byte2bit16(); init_pucch2_luts(); nr_init_fde(); // Init array for frequency equalization of transform precoding of PUSCH @@ -196,7 +197,7 @@ void phy_init_nr_gNB(PHY_VARS_gNB *gNB) int n_buf = Prx*max_ul_mimo_layers; int nb_re_pusch = N_RB_UL * NR_NB_SC_PER_RB; - int nb_re_pusch2 = ALIGN_UP_16(nb_re_pusch); + int nb_re_pusch2 = ceil_mod(nb_re_pusch, 16); gNB->pusch_vars = (NR_gNB_PUSCH *)malloc16_clear(gNB->max_nb_pusch * sizeof(NR_gNB_PUSCH)); for (int ULSCH_id = 0; ULSCH_id < gNB->max_nb_pusch; ULSCH_id++) { diff --git a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c index 42b0b0b515..2e6e4a54a6 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c +++ b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c @@ -36,10 +36,9 @@ #define I0_SKIP_DC 1 -extern openair0_config_t openair0_cfg[MAX_CARDS]; - -int nr_est_timing_advance_srs(const NR_DL_FRAME_PARMS *frame_parms, - const int32_t srs_estimated_channel_time[][frame_parms->ofdm_symbol_size]) { +int nr_est_timing_advance_srs(const NR_DL_FRAME_PARMS *frame_parms, + const c16_t srs_estimated_channel_time[][frame_parms->ofdm_symbol_size]) +{ int timing_advance = 0; int max_val = 0; diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index 6fdf6cd995..8ef3cb1b0c 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -703,11 +703,11 @@ int nr_srs_channel_estimation( const nfapi_nr_srs_pdu_t *srs_pdu, const nr_srs_info_t *nr_srs_info, const c16_t **srs_generated_signal, - int32_t srs_received_signal[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)], - int32_t srs_estimated_channel_freq[][1 << srs_pdu->num_ant_ports] - [gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)], - int32_t srs_estimated_channel_time[][1 << srs_pdu->num_ant_ports][gNB->frame_parms.ofdm_symbol_size], - int32_t srs_estimated_channel_time_shifted[][1 << srs_pdu->num_ant_ports][gNB->frame_parms.ofdm_symbol_size], + c16_t srs_received_signal[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)], + c16_t srs_estimated_channel_freq[][1 << srs_pdu->num_ant_ports] + [gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)], + c16_t srs_estimated_channel_time[][1 << srs_pdu->num_ant_ports][gNB->frame_parms.ofdm_symbol_size], + c16_t srs_estimated_channel_time_shifted[][1 << srs_pdu->num_ant_ports][gNB->frame_parms.ofdm_symbol_size], int8_t *snr_per_rb, int8_t *snr) { @@ -738,20 +738,20 @@ int nr_srs_channel_estimation( c16_t noise[arr_len]; memset(noise, 0, arr_len * sizeof(c16_t)); - uint8_t mem_offset = ((16 - ((long)&srs_estimated_channel_freq[0][0][subcarrier_offset + nr_srs_info->k_0_p[0][0]])) & 0xF) + uint8_t mem_offset = ((16 - ((intptr_t)&srs_estimated_channel_freq[0][0][subcarrier_offset + nr_srs_info->k_0_p[0][0]])) & 0xF) >> 2; // >> 2 <=> /sizeof(int32_t) // filt16_end is {4096,8192,8192,8192,12288,16384,16384,16384,0,0,0,0,0,0,0,0} // The End of OFDM symbol corresponds to the position of last 16384 in the filter // The c16multaddVectRealComplex applies the remaining 8 zeros of filter, therefore, to avoid a buffer overflow, // we added 8 in the array size - int32_t srs_est[frame_parms->ofdm_symbol_size * (1 << srs_pdu->num_symbols) + mem_offset + 8] __attribute__((aligned(32))); + c16_t srs_est[frame_parms->ofdm_symbol_size * (1 << srs_pdu->num_symbols) + mem_offset + 8] __attribute__((aligned(32))); c16_t ls_estimated = {0}; for (int ant = 0; ant < frame_parms->nb_antennas_rx; ant++) { for (int p_index = 0; p_index < N_ap; p_index++) { memset(srs_ls_estimated_channel, 0, frame_parms->ofdm_symbol_size * (1 << srs_pdu->num_symbols) * sizeof(c16_t)); - memset(srs_est, 0, (frame_parms->ofdm_symbol_size * (1 << srs_pdu->num_symbols) + mem_offset) * sizeof(int32_t)); + memset(srs_est, 0, (frame_parms->ofdm_symbol_size * (1 << srs_pdu->num_symbols) + mem_offset) * sizeof(c16_t)); #ifdef SRS_DEBUG LOG_I(NR_PHY, "====================== UE port %d --> gNB Rx antenna %i ======================\n", p_index, ant); @@ -762,7 +762,7 @@ int nr_srs_channel_estimation( subcarrier -= frame_parms->ofdm_symbol_size; } - c16_t *srs_estimated_channel16 = (c16_t *)&srs_est[subcarrier + mem_offset]; + c16_t *srs_estimated_channel16 = &srs_est[subcarrier + mem_offset]; for (int k = 0; k < M_sc_b_SRS; k++) { if (k % fd_cdm == 0) { @@ -773,8 +773,8 @@ int nr_srs_channel_estimation( int16_t generated_real = srs_generated_signal[p_index][subcarrier_cdm].r; int16_t generated_imag = srs_generated_signal[p_index][subcarrier_cdm].i; - int16_t received_real = ((c16_t *)srs_received_signal[ant])[subcarrier_cdm].r; - int16_t received_imag = ((c16_t *)srs_received_signal[ant])[subcarrier_cdm].i; + int16_t received_real = srs_received_signal[ant][subcarrier_cdm].r; + int16_t received_imag = srs_received_signal[ant][subcarrier_cdm].i; // We know that nr_srs_info->srs_generated_signal_bits bits are enough to represent the generated_real and // generated_imag. So we only need a nr_srs_info->srs_generated_signal_bits shift to ensure that the result fits into 16 @@ -806,10 +806,10 @@ int nr_srs_channel_estimation( LOG_I(NR_PHY, "(%4i) %6i\t%6i | %6i\t%6i | %6i\t%6i\n", subcarrier_log, - ((c16_t *)srs_generated_signal[p_index])[subcarrier].r, - ((c16_t *)srs_generated_signal[p_index])[subcarrier].i, - ((c16_t *)srs_received_signal[ant])[subcarrier].r, - ((c16_t *)srs_received_signal[ant])[subcarrier].i, + srs_generated_signal[p_index][subcarrier].r, + srs_generated_signal[p_index][subcarrier].i, + srs_received_signal[ant][subcarrier].r, + srs_received_signal[ant][subcarrier].i, ls_estimated.r, ls_estimated.i); #endif @@ -823,7 +823,7 @@ int nr_srs_channel_estimation( c16multaddVectRealComplex(filt8_start, &ls_estimated, srs_estimated_channel16, 8); } else if (subcarrier < K_TC) { // Start of OFDM symbol case // filt8_start is {12288,8192,4096,0,0,0,0,0} - srs_estimated_channel16 = (c16_t *)&srs_est[subcarrier]; + srs_estimated_channel16 = &srs_est[subcarrier]; const short *filter = mem_offset == 0 ? filt8_start : filt8_start_shift2; c16multaddVectRealComplex(filter, &ls_estimated, srs_estimated_channel16, 8); } else if ((subcarrier + K_TC) >= frame_parms->ofdm_symbol_size @@ -837,14 +837,14 @@ int nr_srs_channel_estimation( } else if (k % 2 == 0) { // 2nd middle case // filt8_middle4 is {0,0,4096,8192,8192,8192,4096,0} c16multaddVectRealComplex(filt8_middle4, &ls_estimated, srs_estimated_channel16, 8); - srs_estimated_channel16 = (c16_t *)&srs_est[sc_offset]; + srs_estimated_channel16 = &srs_est[sc_offset]; } } else { if (k == 0) { // First subcarrier case // filt16_start is {12288,8192,8192,8192,4096,0,0,0,0,0,0,0,0,0,0,0} c16multaddVectRealComplex(filt16_start, &ls_estimated, srs_estimated_channel16, 16); } else if (subcarrier < K_TC) { // Start of OFDM symbol case - srs_estimated_channel16 = (c16_t *)&srs_est[sc_offset]; + srs_estimated_channel16 = &srs_est[sc_offset]; // filt16_start is {12288,8192,8192,8192,4096,0,0,0,0,0,0,0,0,0,0,0} c16multaddVectRealComplex(filt16_start, &ls_estimated, srs_estimated_channel16, 16); } else if ((subcarrier + K_TC) >= frame_parms->ofdm_symbol_size @@ -854,7 +854,7 @@ int nr_srs_channel_estimation( } else { // Middle case // filt16_middle4 is {4096,8192,8192,8192,8192,8192,8192,8192,4096,0,0,0,0,0,0,0} c16multaddVectRealComplex(filt16_middle4, &ls_estimated, srs_estimated_channel16, 16); - srs_estimated_channel16 = (c16_t *)&srs_est[sc_offset]; + srs_estimated_channel16 = &srs_est[sc_offset]; } } @@ -866,9 +866,9 @@ int nr_srs_channel_estimation( } // for (int k = 0; k < M_sc_b_SRS; k++) - memcpy(&srs_estimated_channel_freq[ant][p_index][0], + memcpy(srs_estimated_channel_freq[ant][p_index], &srs_est[mem_offset], - (frame_parms->ofdm_symbol_size * (1 << srs_pdu->num_symbols)) * sizeof(int32_t)); + (frame_parms->ofdm_symbol_size * (1 << srs_pdu->num_symbols)) * sizeof(c16_t)); // Compute noise subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][0]; @@ -877,7 +877,7 @@ int nr_srs_channel_estimation( } uint16_t base_idx = ant * N_ap * M_sc_b_SRS + p_index * M_sc_b_SRS; for (int k = 0; k < M_sc_b_SRS; k++) { - ch[base_idx + k] = ((c16_t *)srs_estimated_channel_freq[ant][p_index])[subcarrier]; + ch[base_idx + k] = srs_estimated_channel_freq[ant][p_index][subcarrier]; noise[base_idx + k].r = abs(srs_ls_estimated_channel[subcarrier].r - ch[base_idx + k].r); noise[base_idx + k].i = abs(srs_ls_estimated_channel[subcarrier].i - ch[base_idx + k].i); subcarrier += K_TC; @@ -908,8 +908,8 @@ int nr_srs_channel_estimation( subcarrier_log, srs_ls_estimated_channel[subcarrier].r, srs_ls_estimated_channel[subcarrier].i, - ((c16_t *)srs_estimated_channel_freq[ant][p_index])[subcarrier].r, - ((c16_t *)srs_estimated_channel_freq[ant][p_index])[subcarrier].i, + srs_estimated_channel_freq[ant][p_index][subcarrier].r, + srs_estimated_channel_freq[ant][p_index][subcarrier].i, noise[base_idx + (k / K_TC)].r, noise[base_idx + (k / K_TC)].i); @@ -926,13 +926,13 @@ int nr_srs_channel_estimation( (int16_t *)srs_estimated_channel_freq[ant][p_index], (int16_t *)srs_estimated_channel_time[ant][p_index]); - memcpy(&srs_estimated_channel_time_shifted[ant][p_index][0], + memcpy(srs_estimated_channel_time_shifted[ant][p_index], &srs_estimated_channel_time[ant][p_index][gNB->frame_parms.ofdm_symbol_size >> 1], - (gNB->frame_parms.ofdm_symbol_size >> 1) * sizeof(int32_t)); + (gNB->frame_parms.ofdm_symbol_size >> 1) * sizeof(c16_t)); memcpy(&srs_estimated_channel_time_shifted[ant][p_index][gNB->frame_parms.ofdm_symbol_size >> 1], - &srs_estimated_channel_time[ant][p_index][0], - (gNB->frame_parms.ofdm_symbol_size >> 1) * sizeof(int32_t)); + srs_estimated_channel_time[ant][p_index], + (gNB->frame_parms.ofdm_symbol_size >> 1) * sizeof(c16_t)); } // for (int p_index = 0; p_index < N_ap; p_index++) } // for (int ant = 0; ant < frame_parms->nb_antennas_rx; ant++) diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h index 9f340d84d6..483e1ea090 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h @@ -64,7 +64,7 @@ void nr_gnb_measurements(PHY_VARS_gNB *gNB, uint8_t nrOfLayers); int nr_est_timing_advance_srs(const NR_DL_FRAME_PARMS *frame_parms, - const int32_t srs_estimated_channel_time[][frame_parms->ofdm_symbol_size]); + const c16_t srs_estimated_channel_time[][frame_parms->ofdm_symbol_size]); void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, NR_DL_FRAME_PARMS *frame_parms, @@ -81,11 +81,11 @@ int nr_srs_channel_estimation( const nfapi_nr_srs_pdu_t *srs_pdu, const nr_srs_info_t *nr_srs_info, const c16_t **srs_generated_signal, - int32_t srs_received_signal[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)], - int32_t srs_estimated_channel_freq[][1 << srs_pdu->num_ant_ports] - [gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)], - int32_t srs_estimated_channel_time[][1 << srs_pdu->num_ant_ports][gNB->frame_parms.ofdm_symbol_size], - int32_t srs_estimated_channel_time_shifted[][1 << srs_pdu->num_ant_ports][gNB->frame_parms.ofdm_symbol_size], + c16_t srs_received_signal[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)], + c16_t srs_estimated_channel_freq[][1 << srs_pdu->num_ant_ports] + [gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)], + c16_t srs_estimated_channel_time[][1 << srs_pdu->num_ant_ports][gNB->frame_parms.ofdm_symbol_size], + c16_t srs_estimated_channel_time_shifted[][1 << srs_pdu->num_ant_ports][gNB->frame_parms.ofdm_symbol_size], int8_t *snr_per_rb, int8_t *snr); diff --git a/openair1/PHY/NR_REFSIG/dmrs_nr.h b/openair1/PHY/NR_REFSIG/dmrs_nr.h index 5a3160857a..001aae4150 100644 --- a/openair1/PHY/NR_REFSIG/dmrs_nr.h +++ b/openair1/PHY/NR_REFSIG/dmrs_nr.h @@ -61,7 +61,7 @@ uint8_t allowed_xlsch_re_in_dmrs_symbol(uint16_t k, uint8_t numDmrsCdmGrpsNoData, uint8_t dmrs_type); -void nr_gen_ref_conj_symbols(const uint32_t *in, uint32_t length, int16_t *output, uint16_t offset, int mod_order); +void nr_gen_ref_conj_symbols(const uint32_t *in, uint32_t length, int16_t *output, int mod_order); int8_t get_next_dmrs_symbol_in_slot(uint16_t ul_dmrs_symb_pos, uint8_t counter, uint8_t end_symbol); uint8_t get_dmrs_symbols_in_slot(uint16_t l_prime_mask, uint16_t nb_symb, uint8_t start); int8_t get_valid_dmrs_idx_for_channel_est(uint16_t dmrs_symb_pos, uint8_t counter); diff --git a/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c b/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c index 1c217d8da0..01b05071a2 100644 --- a/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c +++ b/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c @@ -49,10 +49,21 @@ static const int wt2[12][2] = {{1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, -1}, {1, -1}, {1, -1}, {1, -1}, {1, -1}, {1, -1}}; // complex conjugate of mod table -static const c16_t nr_rx_mod_table[7] = - {{0, 0}, {23170, -23170}, {-23170, 23170}, {23170, -23170}, {23170, 23170}, {-23170, -23170}, {-23170, 23170}}; -static const c16_t nr_rx_nmod_table[7] = - {{0, 0}, {-23170, 23170}, {23170, -23170}, {-23170, 23170}, {-23170, -23170}, {23170, 23170}, {23170, -23170}}; +static const c16_t nr_rx_mod_table[4] = {{23170, -23170}, {23170, 23170}, {-23170, -23170}, {-23170, 23170}}; + +static inline c16_t get_modulated(const uint32_t *gold_sequence, const int idx_gold, const bool inverse) +{ + const uint8_t *gold = (uint8_t *)gold_sequence; + const int swap2bits[4] = {0, 2, 1, 3}; + const uint8_t packedbyte = gold[idx_gold / 4]; + const int indexByte = (idx_gold * 2) & 7; + const int idx = swap2bits[(packedbyte >> indexByte) & 3]; + const c16_t val = nr_rx_mod_table[idx]; + if (inverse) + return val; + else + return (c16_t){-val.r, -val.i}; +} int nr_pusch_dmrs_rx(PHY_VARS_gNB *gNB, unsigned int Ns, @@ -64,41 +75,27 @@ int nr_pusch_dmrs_rx(PHY_VARS_gNB *gNB, uint32_t re_offset, uint8_t dmrs_type) { - int8_t w, nb_dmrs; - unsigned char idx=0; - int k; typedef int array_of_w[2]; const array_of_w *wf = (dmrs_type == pusch_dmrs_type1) ? wf1 : wf2; const array_of_w *wt = (dmrs_type == pusch_dmrs_type1) ? wt1 : wt2; - int dmrs_offset = re_offset/((dmrs_type==pusch_dmrs_type1)?2:3); - + const int dmrs_offset = re_offset / ((dmrs_type == pusch_dmrs_type1) ? 2 : 3); if (dmrs_type > 2) LOG_E(PHY,"PUSCH DMRS config type %d not valid\n", dmrs_type+1); + const int nb_dmrs = dmrs_type == pusch_dmrs_type1 ? 6 : 4; + if ((p>=1000) && (p<((dmrs_type==pusch_dmrs_type1) ? 1008 : 1012))) { if (gNB->frame_parms.Ncp == NORMAL) { - nb_dmrs = ((dmrs_type==pusch_dmrs_type1) ? 6:4); - for (int i=dmrs_offset; i>5])>>((i<<1)&0x1f))&1)<<1) ^ (((nr_gold_pusch[((i<<1)+1)>>5])>>(((i<<1)+1)&0x1f))&1); - output[k] = mod_table[NR_MOD_TABLE_QPSK_OFFSET + idx]; + for (int k = 0; k < nb_pusch_rb * nb_dmrs; k++) { + int i = k + dmrs_offset; + int w = (wf[p - 1000][i & 1]) * (wt[p - 1000][lp]); + output[k] = get_modulated(nr_gold_pusch, i, w == 1); #ifdef DEBUG_PUSCH printf("nr_pusch_dmrs_rx dmrs config type %d port %d nb_pusch_rb %d\n", dmrs_type, p, nb_pusch_rb); printf("wf[%d] = %d wt[%d]= %d\n", i&1, wf[p-1000][i&1], lp, wt[p-1000][lp]); - printf("i %d idx %d pusch gold %u b0-b1 %d-%d mod_dmrs %d %d\n", - i, - idx, - nr_gold_pusch[(i << 1) >> 5], - (((nr_gold_pusch[(i << 1) >> 5]) >> ((i << 1) & 0x1f)) & 1), - (((nr_gold_pusch[((i << 1) + 1) >> 5]) >> (((i << 1) + 1) & 0x1f)) & 1), - output[k].r, - output[k].i); + printf("i %d idx %d pusch mod_dmrs %d %d\n", i, idx, output[k].r, output[k].i); #endif - } } else { LOG_E(PHY,"extended cp not supported for PUSCH DMRS yet\n"); @@ -119,9 +116,6 @@ int nr_pdsch_dmrs_rx(const PHY_VARS_NR_UE *ue, unsigned short nb_pdsch_rb, uint8_t config_type) { - int8_t w; - unsigned char idx=0; - typedef int array_of_w[2]; const array_of_w *wf = (config_type == NFAPI_NR_DMRS_TYPE1) ? wf1 : wf2; const array_of_w *wt = (config_type == NFAPI_NR_DMRS_TYPE1) ? wt1 : wt2; @@ -132,22 +126,13 @@ int nr_pdsch_dmrs_rx(const PHY_VARS_NR_UE *ue, if ((p >= 1000) && (p < ((config_type == NFAPI_NR_DMRS_TYPE1) ? 1008 : 1012))) { if (ue->frame_parms.Ncp == NORMAL) { for (int i = 0; i < nb_pdsch_rb * ((config_type == NFAPI_NR_DMRS_TYPE1) ? 6 : 4); i++) { - w = (wf[p - 1000][i & 1]) * (wt[p - 1000][lp]); - const c16_t *mod_table = (w == 1) ? nr_rx_mod_table : nr_rx_nmod_table; + int w = (wf[p - 1000][i & 1]) * (wt[p - 1000][lp]); + output[i] = get_modulated(nr_gold_pdsch, i, w == 1); - idx = ((((nr_gold_pdsch[(i << 1) >> 5]) >> ((i << 1) & 0x1f)) & 1) << 1) ^ (((nr_gold_pdsch[((i << 1) + 1) >> 5]) >> (((i << 1) + 1) & 0x1f)) & 1); - output[i] = mod_table[NR_MOD_TABLE_QPSK_OFFSET + idx]; #ifdef DEBUG_PDSCH printf("nr_pdsch_dmrs_rx dmrs config type %d port %d nb_pdsch_rb %d\n", config_type, p, nb_pdsch_rb); printf("wf[%d] = %d wt[%d]= %d\n", i & 1, wf[p - 1000][i & 1], lp, wt[p - 1000][lp]); - printf("i %d idx %d pdsch gold %u b0-b1 %d-%d mod_dmrs %d %d\n", - i, - idx, - nr_gold_pdsch[(i << 1) >> 5], - (((nr_gold_pdsch[(i << 1) >> 5]) >> ((i << 1) & 0x1f)) & 1), - (((nr_gold_pdsch[((i << 1) + 1) >> 5]) >> (((i << 1) + 1) & 0x1f)) & 1), - output[i].r, - output[i].i); + printf("i %d idx %d pdsch mod_dmrs %d %d\n", i, idx, output[i].r, output[i].i); #endif } } else { @@ -167,24 +152,12 @@ int nr_pdcch_dmrs_rx(const PHY_VARS_NR_UE *ue, unsigned short p, unsigned short nb_rb_coreset) { - uint8_t idx=0; - //uint8_t pdcch_rb_offset =0; - //nr_gold_pdcch += ((int)floor(ue->frame_parms.ssb_start_subcarrier/12)+pdcch_rb_offset)*3/32; - if (p==2000) { for (int i=0; i<((nb_rb_coreset*6)>>1); i++) { - idx = ((((nr_gold_pdcch[(i<<1)>>5])>>((i<<1)&0x1f))&1)<<1) ^ (((nr_gold_pdcch[((i<<1)+1)>>5])>>(((i<<1)+1)&0x1f))&1); - output[i] = nr_rx_mod_table[NR_MOD_TABLE_QPSK_OFFSET + idx]; + output[i] = get_modulated(nr_gold_pdcch, i, true); #ifdef DEBUG_PDCCH if (i<8) - printf("i %d idx %d pdcch gold %u b0-b1 %d-%d mod_dmrs %d %d\n", - i, - idx, - nr_gold_pdcch[(i << 1) >> 5], - (((nr_gold_pdcch[(i << 1) >> 5]) >> ((i << 1) & 0x1f)) & 1), - (((nr_gold_pdcch[((i << 1) + 1) >> 5]) >> (((i << 1) + 1) & 0x1f)) & 1), - output[i].r, - output[i].i); + printf("i %d idx %d pdcch mod_dmrs %d %d\n", i, idx, output[i].r, output[i].i); #endif } } @@ -194,8 +167,7 @@ int nr_pdcch_dmrs_rx(const PHY_VARS_NR_UE *ue, void nr_pbch_dmrs_rx(int symbol, const unsigned int *nr_gold_pbch, c16_t *output, bool sidelink) { - int m,m0,m1; - uint8_t idx=0; + int m0, m1; if (sidelink) { AssertFatal(symbol == 0 || (symbol >= 5 && symbol <= 12), "illegal symbol %d\n", symbol); m0 = (symbol) ? (symbol - 4) * 33 : 0; @@ -216,9 +188,8 @@ void nr_pbch_dmrs_rx(int symbol, const unsigned int *nr_gold_pbch, c16_t *output } // printf("Generating pilots symbol %d, m0 %d, m1 %d\n",symbol,m0,m1); /// QPSK modulation - for (m=m0; m>5])>>((m<<1)&0x1f))&1)<<1) ^ (((nr_gold_pbch[((m<<1)+1)>>5])>>(((m<<1)+1)&0x1f))&1); - output[m - m0] = nr_rx_mod_table[NR_MOD_TABLE_QPSK_OFFSET + idx]; + for (int m = m0; m < m1; m++) { + output[m - m0] = get_modulated(nr_gold_pbch, m, true); #ifdef DEBUG_PBCH if (m<16) @@ -235,7 +206,7 @@ void nr_pbch_dmrs_rx(int symbol, const unsigned int *nr_gold_pbch, c16_t *output \param length is number of RE in a OFDM symbol \param *output pointer to all ptrs RE in a OFDM symbol */ -void nr_gen_ref_conj_symbols(const uint32_t *in, uint32_t length, c16_t *output, uint16_t offset, int mod_order) +void nr_gen_ref_conj_symbols(const uint32_t *in, uint32_t length, c16_t *output, int mod_order) { uint8_t idx, b_idx; for (int i=0; i>b_idx)&1)<<(mod_order-j-1); } - output[i] = nr_rx_mod_table[offset + idx]; + output[i] = nr_rx_mod_table[idx]; } } diff --git a/openair1/PHY/NR_REFSIG/nr_gen_mod_table.c b/openair1/PHY/NR_REFSIG/nr_gen_mod_table.c index c9d8786b6e..76a89f670b 100644 --- a/openair1/PHY/NR_REFSIG/nr_gen_mod_table.c +++ b/openair1/PHY/NR_REFSIG/nr_gen_mod_table.c @@ -21,7 +21,7 @@ #include "nr_refsig.h" #include "nr_mod_table.h" -short nr_qpsk_mod_table[8]; +c16_t nr_qpsk_mod_table[4]; int32_t nr_16qam_mod_table[16]; simde__m128i nr_qpsk_byte_mod_table[2048]; @@ -43,8 +43,8 @@ void nr_generate_modulation_table() { // QPSK for (i=0; i<4; i++) { - nr_qpsk_mod_table[i*2] = (short)(1-2*(i&1))*val*sqrt2*sqrt2; - nr_qpsk_mod_table[i*2+1] = (short)(1-2*((i>>1)&1))*val*sqrt2*sqrt2; + nr_qpsk_mod_table[i].r = (short)(1 - 2 * (i & 1)) * val * sqrt2 * sqrt2; + nr_qpsk_mod_table[i].i = (short)(1 - 2 * ((i >> 1) & 1)) * val * sqrt2 * sqrt2; //printf("%d j%d\n",nr_qpsk_mod_table[i*2],nr_qpsk_mod_table[i*2+1]); } @@ -52,8 +52,8 @@ void nr_generate_modulation_table() { table = (short*) nr_qpsk_byte_mod_table; for (i=0; i<256; i++) { for (j=0; j<4; j++) { - table[i*8+(j*2)] = (short)(1-2*((i>>(j*2))&1))*val*sqrt2*sqrt2; - table[i*8+(j*2)+1] = (short)(1-2*((i>>(j*2+1))&1))*val*sqrt2*sqrt2; + *table++ = (short)(1 - 2 * ((i >> (j * 2)) & 1)) * val * sqrt2 * sqrt2; + *table++ = (short)(1 - 2 * ((i >> (j * 2 + 1)) & 1)) * val * sqrt2 * sqrt2; //printf("%d j%d\n",nr_qpsk_byte_mod_table[i*8+(j*2)],nr_qpsk_byte_mod_table[i*8+(j*2)+1]); } } @@ -62,16 +62,16 @@ void nr_generate_modulation_table() { table = (short*) nr_16qam_byte_mod_table; for (i=0; i<256; i++) { for (j=0; j<2; j++) { - table[i*4+(j*2)] = (short)((1-2*((i>>(j*4))&1))*(2-(1-2*((i>>(j*4+2))&1))))*val*sqrt10*sqrt2; - table[i*4+(j*2)+1] = (short)((1-2*((i>>(j*4+1))&1))*(2-(1-2*((i>>(j*4+3))&1))))*val*sqrt10*sqrt2; - //printf("%d j%d\n",nr_16qam_byte_mod_table[i*4+(j*2)],nr_16qam_byte_mod_table[i*4+(j*2)+1]); + *table++ = (short)((1 - 2 * ((i >> (j * 4)) & 1)) * (2 - (1 - 2 * ((i >> (j * 4 + 2)) & 1)))) * val * sqrt10 * sqrt2; + *table++ = (short)((1 - 2 * ((i >> (j * 4 + 1)) & 1)) * (2 - (1 - 2 * ((i >> (j * 4 + 3)) & 1)))) * val * sqrt10 * sqrt2; + // printf("%d j%d\n",nr_16qam_byte_mod_table[i*4+(j*2)],nr_16qam_byte_mod_table[i*4+(j*2)+1]); } } table = (short*) nr_16qam_mod_table; for (i=0; i<16; i++) { - table[i*2] = (short)((1-2*(i&1))*(2-(1-2*((i>>2)&1))))*val*sqrt10*sqrt2; - table[i*2+1] = (short)((1-2*((i>>1)&1))*(2-(1-2*((i>>3)&1))))*val*sqrt10*sqrt2; + *table++ = (short)((1 - 2 * (i & 1)) * (2 - (1 - 2 * ((i >> 2) & 1)))) * val * sqrt10 * sqrt2; + *table++ = (short)((1 - 2 * ((i >> 1) & 1)) * (2 - (1 - 2 * ((i >> 3) & 1)))) * val * sqrt10 * sqrt2; //printf("%d j%d\n",table[i*2],table[i*2+1]); } @@ -79,8 +79,12 @@ void nr_generate_modulation_table() { table = (short*) nr_64qam_mod_table; for (i=0; i<4096; i++) { for (j=0; j<2; j++) { - table[i*4+(j*2)] = (short)((1-2*((i>>(j*6))&1))*(4-(1-2*((i>>(j*6+2))&1))*(2-(1-2*((i>>(j*6+4))&1)))))*val*sqrt42*sqrt2; - table[i*4+(j*2)+1] = (short)((1-2*((i>>(j*6+1))&1))*(4-(1-2*((i>>(j*6+3))&1))*(2-(1-2*((i>>(j*6+5))&1)))))*val*sqrt42*sqrt2; + *table++ = (short)((1 - 2 * ((i >> (j * 6)) & 1)) + * (4 - (1 - 2 * ((i >> (j * 6 + 2)) & 1)) * (2 - (1 - 2 * ((i >> (j * 6 + 4)) & 1))))) + * val * sqrt42 * sqrt2; + *table++ = (short)((1 - 2 * ((i >> (j * 6 + 1)) & 1)) + * (4 - (1 - 2 * ((i >> (j * 6 + 3)) & 1)) * (2 - (1 - 2 * ((i >> (j * 6 + 5)) & 1))))) + * val * sqrt42 * sqrt2; //printf("%d j%d\n",table[i*4+(j*2)],table[i*4+(j*2)+1]); } } @@ -88,8 +92,12 @@ void nr_generate_modulation_table() { //256QAM table = (short*) nr_256qam_mod_table; for (i=0; i<256; i++) { - table[i*2] = (short)((1-2*(i&1))*(8-(1-2*((i>>2)&1))*(4-(1-2*((i>>4)&1))*(2-(1-2*((i>>6)&1))))))*val*sqrt170*sqrt2; - table[i*2+1] = (short)((1-2*((i>>1)&1))*(8-(1-2*((i>>3)&1))*(4-(1-2*((i>>5)&1))*(2-(1-2*((i>>7)&1))))))*val*sqrt170*sqrt2; + *table++ = (short)((1 - 2 * (i & 1)) + * (8 - (1 - 2 * ((i >> 2) & 1)) * (4 - (1 - 2 * ((i >> 4) & 1)) * (2 - (1 - 2 * ((i >> 6) & 1)))))) + * val * sqrt170 * sqrt2; + *table++ = (short)((1 - 2 * ((i >> 1) & 1)) + * (8 - (1 - 2 * ((i >> 3) & 1)) * (4 - (1 - 2 * ((i >> 5) & 1)) * (2 - (1 - 2 * ((i >> 7) & 1)))))) + * val * sqrt170 * sqrt2; } } diff --git a/openair1/PHY/NR_REFSIG/nr_mod_table.h b/openair1/PHY/NR_REFSIG/nr_mod_table.h index 4ac83ee79c..517d86b762 100644 --- a/openair1/PHY/NR_REFSIG/nr_mod_table.h +++ b/openair1/PHY/NR_REFSIG/nr_mod_table.h @@ -24,12 +24,11 @@ #define NR_MOD_TABLE_SIZE_SHORT 686 #define NR_MOD_TABLE_BPSK_OFFSET 1 -#define NR_MOD_TABLE_QPSK_OFFSET 3 #define NR_MOD_TABLE_QAM16_OFFSET 7 #define NR_MOD_TABLE_QAM64_OFFSET 23 #define NR_MOD_TABLE_QAM256_OFFSET 87 -extern short nr_qpsk_mod_table[8]; +extern c16_t nr_qpsk_mod_table[4]; extern int32_t nr_16qam_mod_table[16]; #if defined(__SSE2__) diff --git a/openair1/PHY/NR_REFSIG/nr_refsig.h b/openair1/PHY/NR_REFSIG/nr_refsig.h index c79d0b70aa..b0cd9449f0 100644 --- a/openair1/PHY/NR_REFSIG/nr_refsig.h +++ b/openair1/PHY/NR_REFSIG/nr_refsig.h @@ -44,7 +44,6 @@ void nr_generate_csi_rs(const NR_DL_FRAME_PARMS *frame_parms, const nfapi_nr_dl_tti_csi_rs_pdu_rel15_t *csi_params, const int slot, const csi_mapping_parms_t *phy_csi_parms); -void init_byte2m128i(void); void nr_generate_modulation_table(void); diff --git a/openair1/PHY/NR_REFSIG/ptrs_nr.c b/openair1/PHY/NR_REFSIG/ptrs_nr.c index eae3cebb01..c632585389 100644 --- a/openair1/PHY/NR_REFSIG/ptrs_nr.c +++ b/openair1/PHY/NR_REFSIG/ptrs_nr.c @@ -213,7 +213,7 @@ void nr_ptrs_cpe_estimation(uint8_t K_ptrs, c16_t dmrs_comp_p[(1 + sc_per_symbol / 4) * 4]; /* generate PTRS RE for the symbol */ - nr_gen_ref_conj_symbols(gold_seq,sc_per_symbol*2,(int16_t*)ptrs_p, NR_MOD_TABLE_QPSK_OFFSET,2);// 2 for QPSK + nr_gen_ref_conj_symbols(gold_seq, sc_per_symbol * 2, (int16_t *)ptrs_p, 2); // 2 for QPSK uint32_t re_cnt = 0, cnt = 0; /* loop over all sub carriers to get compensated RE on ptrs symbols*/ for (int re = 0; re < NR_NB_SC_PER_RB * nb_rb; re++) { diff --git a/openair1/PHY/NR_REFSIG/scrambling_luts.c b/openair1/PHY/NR_REFSIG/scrambling_luts.c deleted file mode 100644 index f6b1207838..0000000000 --- a/openair1/PHY/NR_REFSIG/scrambling_luts.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/* Lookup tables for 3GPP scrambling/unscrambling */ - -/* Author R. Knopp / EURECOM / OpenAirInterface.org */ - -#include "PHY/impl_defs_nr.h" -#include "PHY/sse_intrin.h" -#include - -simde__m128i byte2m128i[256]; - -void init_byte2m128i(void) { - - for (int s=0;s<256;s++) { - byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s],(1-2*(s&1)),0); - byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s],(1-2*((s>>1)&1)),1); - byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s],(1-2*((s>>2)&1)),2); - byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s],(1-2*((s>>3)&1)),3); - byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s],(1-2*((s>>4)&1)),4); - byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s],(1-2*((s>>5)&1)),5); - byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s],(1-2*((s>>6)&1)),6); - byte2m128i[s] = simde_mm_insert_epi16(byte2m128i[s],(1-2*((s>>7)&1)),7); - } -} - diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci.c b/openair1/PHY/NR_TRANSPORT/nr_dci.c index 54ca8665c3..9bda1b96c4 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dci.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dci.c @@ -66,8 +66,8 @@ static void nr_generate_dci(PHY_VARS_gNB *gNB, get_coreset_rballoc(pdcch_pdu_rel15->FreqDomainResource,&n_rb,&rb_offset); uint16_t cset_start_sc = frame_parms->first_carrier_offset + (pdcch_pdu_rel15->BWPStart + rb_offset) * NR_NB_SC_PER_RB; int idx1 = pdcch_pdu_rel15->StartSymbolIndex+pdcch_pdu_rel15->DurationSymbols; - int idx2 = (((n_rb + rb_offset + pdcch_pdu_rel15->BWPStart) * 6 + 15) >> 4) << 4; - int16_t mod_dmrs[idx1][idx2] __attribute__((aligned(16))); + int idx2 = (((n_rb + rb_offset + pdcch_pdu_rel15->BWPStart) * 3) + 15) & ~15; + c16_t mod_dmrs[idx1][idx2] __attribute__((aligned(16))); for (int d = 0; d < pdcch_pdu_rel15->numDlDci; d++) { /*The coreset is initialised @@ -114,7 +114,7 @@ static void nr_generate_dci(PHY_VARS_gNB *gNB, /// DMRS QPSK modulation for (int symb = cset_start_symb; symb < cset_start_symb + pdcch_pdu_rel15->DurationSymbols; symb++) { const uint32_t *gold = nr_gold_pdcch(frame_parms->N_RB_DL, frame_parms->symbols_per_slot, dci_pdu->ScramblingId, slot, symb); - nr_modulation(gold, dmrs_length, DMRS_MOD_ORDER, mod_dmrs[symb]); // Qm = 2 as DMRS is QPSK modulated + nr_modulation(gold, dmrs_length, DMRS_MOD_ORDER, (int16_t *)mod_dmrs[symb]); // Qm = 2 as DMRS is QPSK modulated #ifdef DEBUG_PDCCH_DMRS if(dci_pdu->RNTI!=0xFFFF) { @@ -122,8 +122,10 @@ static void nr_generate_dci(PHY_VARS_gNB *gNB, printf("symb %d i %d %p gold seq 0x%08x mod_dmrs %d %d\n", symb, i, - &gold_pdcch_dmrs[symb][i>>5],gold_pdcch_dmrs[symb][i>>5], - mod_dmrs[symb][i<<1], mod_dmrs[symb][(i<<1)+1]); + &gold_pdcch_dmrs[symb][i >> 5], + gold_pdcch_dmrs[symb][i >> 5], + mod_dmrs[symb][i].r, + mod_dmrs[symb][i].i); } #endif } @@ -160,18 +162,18 @@ static void nr_generate_dci(PHY_VARS_gNB *gNB, scrambled_output[6], scrambled_output[7], scrambled_output[8], scrambled_output[9], scrambled_output[10],scrambled_output[11] ); #endif /// QPSK modulation - int16_t mod_dci[NR_MAX_DCI_SIZE>>1] __attribute__((aligned(16))); - nr_modulation(scrambled_output, encoded_length, DMRS_MOD_ORDER, mod_dci); //Qm = 2 as DMRS is QPSK modulated + c16_t mod_dci[NR_MAX_DCI_SIZE >> 2] __attribute__((aligned(16))); + nr_modulation(scrambled_output, encoded_length, DMRS_MOD_ORDER, (int16_t *)mod_dci); // Qm = 2 as DMRS is QPSK modulated #ifdef DEBUG_DCI for (int i=0; i>1; i++) - printf("i %d mod_dci %d %d\n", i, mod_dci[i<<1], mod_dci[(i<<1)+1] ); - + printf("i %d mod_dci %d %d\n", i, mod_dci[i].r, mod_dci[i].i); + #endif /// Resource mapping uint16_t amp = gNB->TX_AMP; - int32_t *txdataF = (int32_t *)&gNB->common_vars.txdataF[beam_nb][0][txdataF_offset]; + c16_t *txdataF = gNB->common_vars.txdataF[beam_nb][0] + txdataF_offset; if (cset_start_sc >= frame_parms->ofdm_symbol_size) cset_start_sc -= frame_parms->ofdm_symbol_size; @@ -198,8 +200,7 @@ static void nr_generate_dci(PHY_VARS_gNB *gNB, for (int m = 0; m < NR_NB_SC_PER_RB; m++) { if (m == (k_prime << 2) + 1) { // DMRS if not already mapped - ((int16_t *)txdataF)[(l * frame_parms->ofdm_symbol_size + k) << 1] = (amp * mod_dmrs[l][dmrs_idx << 1]) >> 15; - ((int16_t *)txdataF)[((l * frame_parms->ofdm_symbol_size + k) << 1) + 1] = (amp * mod_dmrs[l][(dmrs_idx << 1) + 1]) >> 15; + txdataF[l * frame_parms->ofdm_symbol_size + k] = c16mulRealShift(mod_dmrs[l][dmrs_idx], amp, 15); #ifdef DEBUG_PDCCH_DMRS LOG_I(NR_PHY_DCI, @@ -207,23 +208,22 @@ static void nr_generate_dci(PHY_VARS_gNB *gNB, dmrs_idx, l, k, - ((int16_t *)txdataF)[(l * frame_parms->ofdm_symbol_size + k) << 1], - ((int16_t *)txdataF)[((l * frame_parms->ofdm_symbol_size + k) << 1) + 1]); + txdataF[l * frame_parms->ofdm_symbol_size + k].r, + txdataF[l * frame_parms->ofdm_symbol_size + k].i); #endif dmrs_idx++; k_prime++; } else { // DCI payload - ((int16_t *)txdataF)[(l * frame_parms->ofdm_symbol_size + k) << 1] = (amp * mod_dci[dci_idx << 1]) >> 15; - ((int16_t *)txdataF)[((l * frame_parms->ofdm_symbol_size + k) << 1) + 1] = (amp * mod_dci[(dci_idx << 1) + 1]) >> 15; + txdataF[l * frame_parms->ofdm_symbol_size + k] = c16mulRealShift(mod_dci[dci_idx], amp, 15); #ifdef DEBUG_DCI LOG_I(NR_PHY_DCI, "PDCCH: l %d position %d => (%d,%d)\n", l, k, - ((int16_t *)txdataF)[(l * frame_parms->ofdm_symbol_size + k) << 1], - ((int16_t *)txdataF)[((l * frame_parms->ofdm_symbol_size + k) << 1) + 1]); + txdataF[l * frame_parms->ofdm_symbol_size + k].r, + txdataF[l * frame_parms->ofdm_symbol_size + k].i; #endif dci_idx++; diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c index 2484c0e800..c415a26dfc 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c @@ -99,7 +99,7 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot) * => size_output is a sum of parts sizes rounded up to a multiple of 64 */ size_t size_output_tb = rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * Qm * rel15->nrOfLayers; - size_output += (size_output_tb + 63 - ((size_output_tb + 63) % 64)); + size_output += ceil_mod(size_output_tb, 64); } unsigned char output[size_output] __attribute__((aligned(64))); @@ -220,7 +220,7 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx, int frame, int slot) * => offset_output should remain a multiple of 64 with enough offset to fit each dlsch */ uint32_t size_output_tb = rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * Qm * rel15->nrOfLayers; - offset_output += (size_output_tb + 63) & ~63; + offset_output += ceil_mod(size_output_tb, 64); // Non interleaved VRB to PRB mapping uint16_t start_sc = frame_parms->first_carrier_offset + (rel15->rbStart+rel15->BWPStart)*NR_NB_SC_PER_RB; diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c index 76955fd259..d64c32059c 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c @@ -304,7 +304,7 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB, * => dlsch_offset should remain a multiple of 64 with enough offset to fit each dlsch */ const size_t dlsch_size = rel15->rbSize * NR_SYMBOLS_PER_SLOT * NR_NB_SC_PER_RB * rel15->qamModOrder[0] * rel15->nrOfLayers; - dlsch_offset += (dlsch_size + 63 - ((dlsch_size + 63) % 64)); + dlsch_offset += ceil_mod(dlsch_size, 64); } gNB->nrLDPC_coding_interface.nrLDPC_coding_encoder(&slot_parameters); diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c index 0a3717ec70..3f1d988c53 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_tools.c @@ -34,8 +34,6 @@ #include "nr_dlsch.h" #include "../../../nfapi/oai_integration/vendor_ext.h" -extern void set_taus_seed(unsigned int seed_type); - void nr_fill_dlsch_dl_tti_req(processingData_L1tx_t *msgTx, nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu) { NR_gNB_DLSCH_t *dlsch = &msgTx->dlsch[msgTx->num_pdsch_slot][0]; diff --git a/openair1/PHY/NR_TRANSPORT/nr_pbch.c b/openair1/PHY/NR_TRANSPORT/nr_pbch.c index 4cc55c1345..64d07723bd 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_pbch.c +++ b/openair1/PHY/NR_TRANSPORT/nr_pbch.c @@ -36,13 +36,13 @@ #include "PHY/sse_intrin.h" #include "executables/softmodem-common.h" #include "openair1/PHY/NR_REFSIG/nr_refsig_common.h" +#include "openair1/PHY/NR_REFSIG/nr_mod_table.h" +#include "openair1/PHY/TOOLS/tools_defs.h" //#define DEBUG_PBCH //#define DEBUG_PBCH_ENCODING //#define DEBUG_PBCH_DMRS -extern short nr_qpsk_mod_table[8]; - const uint8_t nr_pbch_payload_interleaving_pattern[32] = {16, 23, 18, 17, 8, 30, 10, 6, 24, 7, 0, 5, 3, 2, 1, 4, 9, 11, 12, 13, 14, 15, 19, 20, 21, 22, 25, 26, 27, 28, 29, 31 }; @@ -56,7 +56,7 @@ void nr_generate_pbch_dmrs(uint32_t *gold_pbch_dmrs, { int k,l; //int16_t a; - int16_t mod_dmrs[NR_PBCH_DMRS_LENGTH<<1]; + c16_t mod_dmrs[NR_PBCH_DMRS_LENGTH]; uint8_t idx=0; uint8_t nushift = config->cell_config.phy_cell_id.value &3; LOG_D(PHY, "PBCH DMRS mapping started at symbol %d shift %d\n", ssb_start_symbol+1, nushift); @@ -64,11 +64,16 @@ void nr_generate_pbch_dmrs(uint32_t *gold_pbch_dmrs, /// QPSK modulation for (int m=0; m>5])>>((m<<1)&0x1f))&3); - mod_dmrs[m<<1] = nr_qpsk_mod_table[idx<<1]; - mod_dmrs[(m<<1)+1] = nr_qpsk_mod_table[(idx<<1) + 1]; + mod_dmrs[m] = nr_qpsk_mod_table[idx]; #ifdef DEBUG_PBCH_DMRS - printf("m %d idx %d gold seq %u b0-b1 %d-%d mod_dmrs %d %d\n", m, idx, gold_pbch_dmrs[(m<<1)>>5], (((gold_pbch_dmrs[(m<<1)>>5])>>((m<<1)&0x1f))&1), - (((gold_pbch_dmrs[((m<<1)+1)>>5])>>(((m<<1)+1)&0x1f))&1), mod_dmrs[(m<<1)], mod_dmrs[(m<<1)+1]); + printf("m %d idx %d gold seq %u b0-b1 %d-%d mod_dmrs %d %d\n", + m, + idx, + gold_pbch_dmrs[(m << 1) >> 5], + (((gold_pbch_dmrs[(m << 1) >> 5]) >> ((m << 1) & 0x1f)) & 1), + (((gold_pbch_dmrs[((m << 1) + 1) >> 5]) >> (((m << 1) + 1) & 0x1f)) & 1), + mod_dmrs[m].r, + mod_dmrs[m].i); #endif } @@ -82,13 +87,7 @@ void nr_generate_pbch_dmrs(uint32_t *gold_pbch_dmrs, #ifdef DEBUG_PBCH_DMRS printf("m %d at k %d of l %d\n", m, k, l); #endif - ((int16_t *)txdataF)[(l*frame_parms->ofdm_symbol_size + k)<<1] = (amp * mod_dmrs[m<<1]) >> 15; - ((int16_t *)txdataF)[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1] = (amp * mod_dmrs[(m<<1) + 1]) >> 15; -#ifdef DEBUG_PBCH_DMRS - printf("(%d,%d)\n", - ((int16_t *)txdataF)[(l*frame_parms->ofdm_symbol_size + k)<<1], - ((int16_t *)txdataF)[((l*frame_parms->ofdm_symbol_size + k)<<1)+1]); -#endif + txdataF[l * frame_parms->ofdm_symbol_size + k] = c16mulRealShift(mod_dmrs[m], amp, 15); k+=4; if (k >= frame_parms->ofdm_symbol_size) @@ -103,8 +102,7 @@ void nr_generate_pbch_dmrs(uint32_t *gold_pbch_dmrs, #ifdef DEBUG_PBCH_DMRS printf("m %d at k %d of l %d\n", m, k, l); #endif - ((int16_t *)txdataF)[(l*frame_parms->ofdm_symbol_size + k)<<1] = (amp * mod_dmrs[m<<1]) >> 15; - ((int16_t *)txdataF)[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1] = (amp * mod_dmrs[(m<<1) + 1]) >> 15; + txdataF[l * frame_parms->ofdm_symbol_size + k] = c16mulRealShift(mod_dmrs[m], amp, 15); #ifdef DEBUG_PBCH_DMRS printf("(%d,%d)\n", ((int16_t *)txdataF)[(l*frame_parms->ofdm_symbol_size + k)<<1], @@ -124,13 +122,7 @@ void nr_generate_pbch_dmrs(uint32_t *gold_pbch_dmrs, #ifdef DEBUG_PBCH_DMRS printf("m %d at k %d of l %d\n", m, k, l); #endif - ((int16_t *)txdataF)[(l*frame_parms->ofdm_symbol_size + k)<<1] = (amp * mod_dmrs[m<<1]) >> 15; - ((int16_t *)txdataF)[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1] = (amp * mod_dmrs[(m<<1) + 1]) >> 15; -#ifdef DEBUG_PBCH_DMRS - printf("(%d,%d)\n", - ((int16_t *)txdataF)[(l*frame_parms->ofdm_symbol_size + k)<<1], - ((int16_t *)txdataF)[((l*frame_parms->ofdm_symbol_size + k)<<1)+1]); -#endif + txdataF[l * frame_parms->ofdm_symbol_size + k] = c16mulRealShift(mod_dmrs[m], amp, 15); k+=4; if (k >= frame_parms->ofdm_symbol_size) @@ -346,14 +338,13 @@ void nr_generate_pbch(PHY_VARS_gNB *gNB, printf("\n"); #endif - int16_t mod_pbch_e[NR_POLAR_PBCH_E]; + c16_t mod_pbch_e[NR_POLAR_PBCH_E / 2]; /// QPSK modulation for (int i=0; i>1; i++) { int idx = ((pbch_e[(i << 1) >> 5] >> ((i << 1) & 0x1f)) & 3); - mod_pbch_e[i<<1] = nr_qpsk_mod_table[idx << 1]; - mod_pbch_e[(i<<1)+1] = nr_qpsk_mod_table[(idx << 1) + 1]; + mod_pbch_e[i] = nr_qpsk_mod_table[idx]; #ifdef DEBUG_PBCH - printf("i %d idx %d mod_pbch %d %d\n", i, idx, mod_pbch_e[2 * i], mod_pbch_e[2 * i + 1]); + printf("i %d idx %d mod_pbch %d %d\n", i, idx, mod_pbch_e[i].r, mod_pbch_e[i].i); #endif } @@ -374,8 +365,7 @@ void nr_generate_pbch(PHY_VARS_gNB *gNB, #ifdef DEBUG_PBCH printf("m %d ssb_sc_idx %d at k %d of l %d\n", m, ssb_sc_idx, k, l); #endif - ((int16_t *)txdataF)[(l*frame_parms->ofdm_symbol_size + k)<<1] = (amp * mod_pbch_e[m<<1]) >> 15; - ((int16_t *)txdataF)[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1] = (amp * mod_pbch_e[(m<<1) + 1]) >> 15; + txdataF[l * frame_parms->ofdm_symbol_size + k] = c16mulRealShift(mod_pbch_e[m], amp, 15); k++; m++; } @@ -397,8 +387,7 @@ void nr_generate_pbch(PHY_VARS_gNB *gNB, #ifdef DEBUG_PBCH printf("m %d ssb_sc_idx %d at k %d of l %d\n", m, ssb_sc_idx, k, l); #endif - ((int16_t *)txdataF)[(l*frame_parms->ofdm_symbol_size + k)<<1] = (amp * mod_pbch_e[m<<1]) >> 15; - ((int16_t *)txdataF)[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1] = (amp * mod_pbch_e[(m<<1) + 1]) >> 15; + txdataF[l * frame_parms->ofdm_symbol_size + k] = c16mulRealShift(mod_pbch_e[m], amp, 15); k++; m++; } @@ -422,8 +411,7 @@ void nr_generate_pbch(PHY_VARS_gNB *gNB, #ifdef DEBUG_PBCH printf("m %d ssb_sc_idx %d at k %d of l %d\n", m, ssb_sc_idx, k, l); #endif - ((int16_t *)txdataF)[(l*frame_parms->ofdm_symbol_size + k)<<1] = (amp * mod_pbch_e[m<<1]) >> 15; - ((int16_t *)txdataF)[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1] = (amp * mod_pbch_e[(m<<1) + 1]) >> 15; + txdataF[l * frame_parms->ofdm_symbol_size + k] = c16mulRealShift(mod_pbch_e[m], amp, 15); k++; m++; } @@ -445,8 +433,7 @@ void nr_generate_pbch(PHY_VARS_gNB *gNB, #ifdef DEBUG_PBCH printf("m %d ssb_sc_idx %d at k %d of l %d\n", m, ssb_sc_idx, k, l); #endif - ((int16_t *)txdataF)[(l*frame_parms->ofdm_symbol_size + k)<<1] = (amp * mod_pbch_e[m<<1]) >> 15; - ((int16_t *)txdataF)[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1] = (amp * mod_pbch_e[(m<<1) + 1]) >> 15; + txdataF[l * frame_parms->ofdm_symbol_size + k] = c16mulRealShift(mod_pbch_e[m], amp, 15); k++; m++; } diff --git a/openair1/PHY/NR_TRANSPORT/nr_prs.c b/openair1/PHY/NR_TRANSPORT/nr_prs.c index 382e995a65..6f26b9a07f 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_prs.c +++ b/openair1/PHY/NR_TRANSPORT/nr_prs.c @@ -4,11 +4,10 @@ #include "PHY/NR_REFSIG/nr_refsig.h" #include "PHY/sse_intrin.h" #include "openair1/PHY/NR_REFSIG/refsig_defs_ue.h" +#include "openair1/PHY/NR_REFSIG/nr_mod_table.h" //#define DEBUG_PRS_MOD //#define DEBUG_PRS_MAP -extern short nr_qpsk_mod_table[8]; - int nr_generate_prs(int slot, c16_t *txdataF, int16_t amp, @@ -18,7 +17,7 @@ int nr_generate_prs(int slot, { int k_prime = 0, k = 0, idx; - int16_t mod_prs[NR_MAX_PRS_LENGTH<<1]; + c16_t mod_prs[NR_MAX_PRS_LENGTH]; int16_t k_prime_table[K_PRIME_TABLE_ROW_SIZE][K_PRIME_TABLE_COL_SIZE] = PRS_K_PRIME_TABLE; // PRS resource mapping with combsize=k which means PRS symbols exist in every k-th subcarrier in frequency domain @@ -45,25 +44,12 @@ int nr_generate_prs(int slot, uint32_t *gold = nr_gold_prs(prs_cfg->NPRSID, slot, l); for (int m = 0; m < (12/prs_cfg->CombSize) * prs_cfg->NumRB; m++) { idx = (((gold[(m << 1) >> 5]) >> ((m << 1) & 0x1f)) & 3); - mod_prs[m<<1] = nr_qpsk_mod_table[idx<<1]; - mod_prs[(m<<1)+1] = nr_qpsk_mod_table[(idx<<1) + 1]; - -#ifdef DEBUG_PRS_MOD - LOG_D("m %d idx %d gold seq %d mod_prs %d %d\n", m, idx, nr_gold_prs[l][(m<<1)>>5], mod_prs[m<<1], mod_prs[(m<<1)+1]); -#endif - + mod_prs[m] = nr_qpsk_mod_table[idx]; + #ifdef DEBUG_PRS_MAP LOG_D("m %d at k %d of l %d reIdx %d\n", m, k, l, (l*frame_parms->ofdm_symbol_size + k)<<1); #endif - - ((int16_t *)txdataF)[(l*frame_parms->ofdm_symbol_size + k)<<1] = (amp * mod_prs[m<<1]) >> 15; - ((int16_t *)txdataF)[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1] = (amp * mod_prs[(m<<1) + 1]) >> 15; - -#ifdef DEBUG_PRS_MAP - LOG_D("(%d,%d)\n", - ((int16_t *)txdataF)[(l*frame_parms->ofdm_symbol_size + k)<<1], - ((int16_t *)txdataF)[((l*frame_parms->ofdm_symbol_size + k)<<1)+1]); -#endif + txdataF[l * frame_parms->ofdm_symbol_size + k] = c16mulRealShift(mod_prs[m], amp, 15); k = k + prs_cfg->CombSize; diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h index 397c0adf98..6dbf6e565d 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h +++ b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h @@ -303,7 +303,7 @@ int nr_get_srs_signal(PHY_VARS_gNB *gNB, slot_t slot, nfapi_nr_srs_pdu_t *srs_pdu, nr_srs_info_t *nr_srs_info, - int32_t srs_received_signal[][gNB->frame_parms.ofdm_symbol_size*(1<num_symbols)]); + c16_t srs_received_signal[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)]); void init_prach_list(PHY_VARS_gNB *gNB); void init_prach_ru_list(RU_t *ru); diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c index 902a7bae02..c3b4f4dd75 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c +++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c @@ -1026,7 +1026,7 @@ static void inner_rx(PHY_VARS_gNB *gNB, int nb_layer = rel15_ul->nrOfLayers; int nb_rx_ant = frame_parms->nb_antennas_rx; int dmrs_symbol_flag = (rel15_ul->ul_dmrs_symb_pos >> symbol) & 0x01; - int buffer_length = ALIGN_UP_16(rel15_ul->rb_size * NR_NB_SC_PER_RB); + int buffer_length = ceil_mod(rel15_ul->rb_size * NR_NB_SC_PER_RB, 16); c16_t rxFext[nb_rx_ant][buffer_length] __attribute__((aligned(32))); c16_t chFext[nb_layer][nb_rx_ant][buffer_length] __attribute__((aligned(32))); @@ -1400,7 +1400,7 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, // extract the data in the OFDM frame, to the start of the array int soffset = (slot % RU_RX_SLOT_DEPTH) * frame_parms->symbols_per_slot * frame_parms->ofdm_symbol_size; - nb_re_pusch = ALIGN_UP_16(nb_re_pusch); + nb_re_pusch = ceil_mod(nb_re_pusch, 16); int dmrs_symbol; if (gNB->chest_time == 0) dmrs_symbol = get_valid_dmrs_idx_for_channel_est(rel15_ul->ul_dmrs_symb_pos, meas_symbol); @@ -1524,7 +1524,7 @@ int nr_rx_pusch_tp(PHY_VARS_gNB *gNB, // buffer due to reference symbol extraction and padding. The gNBscopeCopy call is broken up into steps: trylock, copy, unlock. metadata mt = {.slot = slot, .frame = frame}; if (gNBTryLockScopeData(gNB, gNBPuschRxIq, sizeof(c16_t), 1, total_res, &mt)) { - int buffer_length = ALIGN_UP_16(rel15_ul->rb_size * NR_NB_SC_PER_RB); + int buffer_length = ceil_mod(rel15_ul->rb_size * NR_NB_SC_PER_RB, 16); size_t offset = 0; for (uint8_t symbol = rel15_ul->start_symbol_index; symbol < (rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols); symbol++) { diff --git a/openair1/PHY/NR_TRANSPORT/srs_rx.c b/openair1/PHY/NR_TRANSPORT/srs_rx.c index 49ae659a06..8ece090cc5 100644 --- a/openair1/PHY/NR_TRANSPORT/srs_rx.c +++ b/openair1/PHY/NR_TRANSPORT/srs_rx.c @@ -74,7 +74,7 @@ int nr_get_srs_signal(PHY_VARS_gNB *gNB, slot_t slot, nfapi_nr_srs_pdu_t *srs_pdu, nr_srs_info_t *nr_srs_info, - int32_t srs_received_signal[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)]) + c16_t srs_received_signal[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)]) { const NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; @@ -88,12 +88,11 @@ int nr_get_srs_signal(PHY_VARS_gNB *gNB, const uint8_t K_TC = 2 << srs_pdu->comb_size; const uint16_t M_sc_b_SRS = get_m_srs(srs_pdu->config_index, srs_pdu->bandwidth_index) * NR_NB_SC_PER_RB / K_TC; - int32_t *rx_signal; + c16_t *rx_signal; bool no_srs_signal = true; for (int ant = 0; ant < frame_parms->nb_antennas_rx; ant++) { - - memset(srs_received_signal[ant], 0, frame_parms->ofdm_symbol_size*sizeof(int32_t)); - rx_signal = (int32_t *)&rxdataF[ant][symbol_offset]; + memset(srs_received_signal[ant], 0, frame_parms->ofdm_symbol_size * sizeof(c16_t)); + rx_signal = &rxdataF[ant][symbol_offset]; for (int p_index = 0; p_index < N_ap; p_index++) { @@ -117,7 +116,7 @@ int nr_get_srs_signal(PHY_VARS_gNB *gNB, srs_received_signal[ant][l_line_offset+subcarrier] = rx_signal[l_line_offset+subcarrier]; - if (rx_signal[l_line_offset+subcarrier] != 0) { + if (rx_signal[l_line_offset + subcarrier].r || rx_signal[l_line_offset + subcarrier].i) { no_srs_signal = false; } @@ -129,10 +128,11 @@ int nr_get_srs_signal(PHY_VARS_gNB *gNB, if(subcarrier_log%12 == 0) { LOG_I(NR_PHY,"------------ %d ------------\n", subcarrier_log/12); } - LOG_I(NR_PHY,"(%i) \t%i\t%i\n", + LOG_I(NR_PHY, + "(%i) \t%i\t%i\n", subcarrier_log, - (int16_t)(srs_received_signal[ant][l_line_offset+subcarrier]&0xFFFF), - (int16_t)((srs_received_signal[ant][l_line_offset+subcarrier]>>16)&0xFFFF)); + srs_received_signal[ant][l_line_offset + subcarrier].r, + srs_received_signal[ant][l_line_offset + subcarrier].i); #endif // Subcarrier increment diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c index 23560568cf..40bae6eac7 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -34,10 +34,7 @@ #include #include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h" #include "instrumentation.h" - - -extern openair0_config_t openair0_cfg[]; - +#include "executables/nr-softmodem-common.h" // #define DEBUG_PDSCH // #define DEBUG_PDCCH // #define DEBUG_PBCH(a...) printf(a) @@ -94,7 +91,8 @@ int nr_prs_channel_estimation(uint8_t gNB_id, int slot_prs = (proc->nr_slot_rx - rep_num * prs_cfg->PRSResourceTimeGap + frame_params->slots_per_frame) % frame_params->slots_per_frame; - int16_t *rxF, *pil, mod_prs[NR_MAX_PRS_LENGTH << 1]; + int16_t *rxF, *pil; + c16_t mod_prs[NR_MAX_PRS_LENGTH]; const int16_t *fl, *fm, *fmm, *fml, *fmr, *fr; int16_t ch[2] = {0}, noiseFig[2] = {0}; int16_t k_prime = 0, k = 0; @@ -138,8 +136,7 @@ int nr_prs_channel_estimation(uint8_t gNB_id, for (int m = 0; m < num_pilots; m++) { idx = (((gold_prs[(m << 1) >> 5]) >> ((m << 1) & 0x1f)) & 3); - mod_prs[m<<1] = nr_qpsk_mod_table[idx<<1]; - mod_prs[(m<<1)+1] = nr_qpsk_mod_table[(idx<<1) + 1]; + mod_prs[m] = nr_qpsk_mod_table[idx]; } for (rxAnt=0; rxAnt < frame_params->nb_antennas_rx; rxAnt++) @@ -152,7 +149,7 @@ int nr_prs_channel_estimation(uint8_t gNB_id, k = (prs_cfg->REOffset + k_prime) % prs_cfg->CombSize + prs_cfg->RBOffset * 12 + frame_params->first_carrier_offset; // Channel estimation and interpolation - pil = (int16_t *)&mod_prs[0]; + pil = (int16_t *)mod_prs; rxF = (int16_t *)&rxdataF[rxAnt][l*frame_params->ofdm_symbol_size + k]; if(prs_cfg->CombSize == 2) @@ -520,7 +517,7 @@ int nr_prs_channel_estimation(uint8_t gNB_id, #ifdef DEBUG_PRS_CHEST sprintf(filename, "%s%i%s", "PRSpilot_", rxAnt, ".m"); - LOG_M(filename, "prs_loc", &mod_prs[0], num_pilots,1,1); + LOG_M(filename, "prs_loc", mod_prs, num_pilots, 1, 1); sprintf(filename, "%s%i%s", "rxSigF_", rxAnt, ".m"); sprintf(varname, "%s%i", "rxF_", rxAnt); LOG_M(filename, varname, &rxdataF[rxAnt][0], prs_cfg->NumPRSSymbols*frame_params->ofdm_symbol_size,1,1); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c index 4fb88ec969..a3138f5d7f 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c @@ -321,6 +321,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, LOG_D(PHY, "DLSCH received nok \n"); kpiStructure.nb_nack++; dlsch->last_iteration_cnt = dlsch->max_ldpc_iterations + 1; + UEdumpScopeData(phy_vars_ue, proc->nr_slot_rx, proc->frame_rx, "DLSCH_NACK"); } uint8_t dmrs_Type = dlsch_config->dmrsConfigType; diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c index e5442aab48..503f58fb36 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c @@ -724,13 +724,13 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue, metadata mt = {.frame = proc->frame_rx, .slot = proc->nr_slot_rx }; int total_valid_res = 0; for (int i = startSymbIdx; i < startSymbIdx + nbSymb; i++) { - total_valid_res = dl_valid_re[i - 1]; + total_valid_res += dl_valid_re[i]; } if (UETryLockScopeData(ue, pdschRxdataF_comp, sizeof(c16_t), 1, total_valid_res, &mt)) { size_t offset = 0; for (int i = startSymbIdx; i < startSymbIdx + nbSymb; i++) { - size_t data_size = sizeof(c16_t) * dl_valid_re[i - i]; - UEscopeCopyUnsafe(ue, pdschRxdataF_comp, &rxdataF_comp[0][0][rx_size_symbol * i], data_size, offset, i - startSymbIdx); + size_t data_size = sizeof(c16_t) * dl_valid_re[i]; + UEscopeCopyUnsafe(ue, pdschRxdataF_comp, &rxdataF_comp[0][0][rx_size_symbol * i], data_size, offset, i); offset += data_size; } UEunlockScopeData(ue, pdschRxdataF_comp) @@ -1515,8 +1515,8 @@ uint8_t nr_matrix_inverse(int32_t size, //Convert Q15 to floating point for (int rtx=0;rtx0) {//determin of the symmetric matrix is real part only - ((short*) ad_bc)[i<<1] = (short) ((creal(determin_cpx)*(1<<(shift0)))+0.5);// - //((short*) ad_bc)[(i<<1)+1] = (short) ((cimag(determin_cpx)*(1<<(shift0)))+0.5);// + ((short *)ad_bc)[i << 1] = (short)((creal(determin_cpx) * (1 << (shift0))) + 0.5); // } else { - ((short*) ad_bc)[i<<1] = (short) ((creal(determin_cpx)*(1<<(shift0)))-0.5);// - //((short*) ad_bc)[(i<<1)+1] = (short) ((cimag(determin_cpx)*(1<<(shift0)))-0.5);// + ((short *)ad_bc)[i << 1] = (short)((creal(determin_cpx) * (1 << (shift0))) - 0.5); // } - //if (i<4) printf("nr_det_FP= %d+j%d \n",((short*) ad_bc)[i<<1],((short*) ad_bc)[(i<<1)+1]); //Compute Inversion of the H^*H matrix (normalized output divide by determinant) for (int rtx=0;rtx #include #include +#include +#include "imscope_internal.h" +#include +#include -#define MAX_OFFSETS 14 #define NR_MAX_RB 273 #define N_SC_PER_RB NR_NB_SC_PER_RB @@ -66,77 +69,9 @@ static void glfw_error_callback(int error, const char *description) fprintf(stderr, "GLFW Error %d: %s\n", error, description); } -typedef struct ImScopeData { - std::mutex write_mutex; - scopeGraphData_t *scope_graph_data; - bool is_data_ready; - metadata meta; - uint64_t time_taken_in_ns; - uint64_t time_taken_in_ns_per_offset[MAX_OFFSETS]; - size_t data_copied_per_offset[MAX_OFFSETS]; -} ImScopeData; - -typedef struct MovingAverageTimer { - uint64_t sum = 0; - float average = 0; - float last_update_time = 0; - void UpdateAverage(float time) - { - if (time > last_update_time + 1) { - float new_average = sum / (float)((time - last_update_time) / 1000); - average = 0.95 * average + 0.05 * new_average; - sum = 0; - } - } - void Add(uint64_t ns) - { - sum += ns; - } -} MovingAverageTimer; - MovingAverageTimer iq_procedure_timer; -static ImScopeData scope_array[EXTRA_SCOPE_TYPES]; - -typedef struct IQData { - std::vector real; - std::vector imag; - int16_t max_iq; - std::vector power; - float max_power; - float timestamp; - int nonzero_count; - int len = 0; - metadata meta; - - bool TryCollect(ImScopeData *imscope_data, float time, float epsilon) - { - if (imscope_data->is_data_ready) { - iq_procedure_timer.Add(imscope_data->time_taken_in_ns); - timestamp = time; - scopeGraphData_t *iq_header = imscope_data->scope_graph_data; - len = iq_header->lineSz; - real.reserve(len); - imag.reserve(len); - power.reserve(len); - c16_t *source = (c16_t *)(iq_header + 1); - max_iq = 0; - nonzero_count = 0; - for (auto i = 0; i < len; i++) { - real[i] = source[i].r; - imag[i] = source[i].i; - max_iq = std::max(max_iq, (int16_t)std::abs(source[i].r)); - max_iq = std::max(max_iq, (int16_t)std::abs(source[i].i)); - nonzero_count = std::abs(source[i].r) > epsilon || std::abs(source[i].i) > epsilon ? nonzero_count + 1 : nonzero_count; - power[i] = std::sqrt(std::pow(source[i].r, 2) + std::pow(source[i].i, 2)); - } - meta = imscope_data->meta; - imscope_data->is_data_ready = false; - return true; - } - return false; - } -} IQData; +ImScopeDataWrapper scope_array[EXTRA_SCOPE_TYPES]; class LLRPlot { int len = 0; @@ -163,19 +98,19 @@ class LLRPlot { ImGui::EndDisabled(); } - ImScopeData &scope_data = scope_array[type]; + ImScopeDataWrapper &scope_data = scope_array[type]; if (ImPlot::BeginPlot(label)) { if (!frozen || next) { if (scope_data.is_data_ready) { - iq_procedure_timer.Add(scope_data.time_taken_in_ns); + iq_procedure_timer.Add(scope_data.data.time_taken_in_ns); timestamp = time; - const int16_t *tmp = (int16_t *)(scope_data.scope_graph_data + 1); - len = scope_data.scope_graph_data->lineSz; + const int16_t *tmp = (int16_t *)(scope_data.data.scope_graph_data + 1); + len = scope_data.data.scope_graph_data->lineSz; llr.reserve(len); for (auto i = 0; i < len; i++) { llr[i] = tmp[i]; } - meta = scope_data.meta; + meta = scope_data.data.meta; scope_data.is_data_ready = false; if (frozen) { next = false; @@ -323,14 +258,14 @@ class IQSlotHeatmap { bool next = false; float timestamp = 0; std::vector power; - ImScopeData *scope_data; + ImScopeDataWrapper *scope_data; std::string label; int len = 0; float max = 0; float stop_at_min = 1000; public: - IQSlotHeatmap(ImScopeData *scope_data_, const char *label_) + IQSlotHeatmap(ImScopeDataWrapper *scope_data_, const char *label_) { scope_data = scope_data_; label = label_; @@ -341,7 +276,7 @@ class IQSlotHeatmap { auto num_sc = num_rb * NR_NB_SC_PER_RB; if (!frozen || next) { if (scope_data->is_data_ready) { - iq_procedure_timer.Add(scope_data->time_taken_in_ns); + iq_procedure_timer.Add(scope_data->data.time_taken_in_ns); uint16_t first_sc = first_carrier_offset; uint16_t last_sc = first_sc + num_rb * NR_NB_SC_PER_RB; bool wrapped = false; @@ -354,7 +289,7 @@ class IQSlotHeatmap { wrapped_last_sc = wrapped_first_sc + num_sc_left - 1; } timestamp = time; - scopeGraphData_t *iq_header = scope_data->scope_graph_data; + scopeGraphData_t *iq_header = scope_data->data.scope_graph_data; len = iq_header->lineSz; c16_t *source = (c16_t *)(iq_header + 1); @@ -458,8 +393,9 @@ struct ScrollingBuffer { } }; -void ShowUeScope(PHY_VARS_NR_UE *ue, float t) +void ShowUeScope(void *data_void_ptr, float t) { + PHY_VARS_NR_UE *ue = (PHY_VARS_NR_UE *)data_void_ptr; ImGui::Begin("UE KPI"); if (ImPlot::BeginPlot("##Scrolling", ImVec2(-1, 150))) { static float history = 10.0f; @@ -490,7 +426,7 @@ void ShowUeScope(PHY_VARS_NR_UE *ue, float t) static auto pdsch_iq_hist = new IQHist("PDSCH IQ"); bool new_data = false; if (pdsch_iq_hist->ShouldReadData()) { - new_data = iq_data->TryCollect(&scope_array[pdschRxdataF_comp], t, pdsch_iq_hist->GetEpsilon()); + new_data = iq_data->TryCollect(&scope_array[pdschRxdataF_comp], t, pdsch_iq_hist->GetEpsilon(), iq_procedure_timer); } pdsch_iq_hist->Draw(iq_data, t, new_data); } @@ -503,7 +439,7 @@ void ShowUeScope(PHY_VARS_NR_UE *ue, float t) static auto time_domain_iq = new IQHist("Time domain samples", disable_scatterplot); bool new_data = false; if (time_domain_iq->ShouldReadData()) { - new_data = iq_data->TryCollect(&scope_array[ueTimeDomainSamples], t, time_domain_iq->GetEpsilon()); + new_data = iq_data->TryCollect(&scope_array[ueTimeDomainSamples], t, time_domain_iq->GetEpsilon(), iq_procedure_timer); } time_domain_iq->Draw(iq_data, t, new_data); } @@ -516,7 +452,7 @@ void ShowUeScope(PHY_VARS_NR_UE *ue, float t) static auto time_domain_iq = new IQHist("Time domain samples - before sync", disable_scatterplot); bool new_data = false; if (time_domain_iq->ShouldReadData()) { - new_data = iq_data->TryCollect(&scope_array[ueTimeDomainSamplesBeforeSync], t, time_domain_iq->GetEpsilon()); + new_data = iq_data->TryCollect(&scope_array[ueTimeDomainSamplesBeforeSync], t, time_domain_iq->GetEpsilon(), iq_procedure_timer); } time_domain_iq->Draw(iq_data, t, new_data); } @@ -531,7 +467,7 @@ void ShowUeScope(PHY_VARS_NR_UE *ue, float t) if (broadcast_iq_hist->ShouldReadData()) { new_data = iq_data->TryCollect(&scope_array[ue->sl_mode ? psbchRxdataF_comp : pbchRxdataF_comp], t, - broadcast_iq_hist->GetEpsilon()); + broadcast_iq_hist->GetEpsilon(), iq_procedure_timer); } broadcast_iq_hist->Draw(iq_data, t, new_data); ImGui::TreePop(); @@ -543,7 +479,7 @@ void ShowUeScope(PHY_VARS_NR_UE *ue, float t) if (broadcast_iq_chest->ShouldReadData()) { new_data = chest_iq_data->TryCollect(&scope_array[ue->sl_mode ? psbchDlChEstimateTime : pbchDlChEstimateTime], t, - broadcast_iq_chest->GetEpsilon()); + broadcast_iq_chest->GetEpsilon(), iq_procedure_timer); } broadcast_iq_chest->Draw(chest_iq_data, t, new_data); ImGui::TreePop(); @@ -568,8 +504,9 @@ void ShowUeScope(PHY_VARS_NR_UE *ue, float t) // ImGui::End(); } -void ShowGnbScope(PHY_VARS_gNB *gNB, float t) +void ShowGnbScope(void *data_void_ptr, float t) { + (void)data_void_ptr; // if (ImGui::TreeNode("RX IQ")) { // static auto gnb_heatmap = new IQSlotHeatmap(&scope_array[gNBRxdataF], "common RX IQ"); @@ -585,7 +522,7 @@ void ShowGnbScope(PHY_VARS_gNB *gNB, float t) static auto pusch_iq_display = new IQHist("PUSCH compensated IQ"); bool new_data = false; if (pusch_iq_display->ShouldReadData()) { - new_data = pusch_iq->TryCollect(&scope_array[gNBPuschRxIq], t, pusch_iq_display->GetEpsilon()); + new_data = pusch_iq->TryCollect(&scope_array[gNBPuschRxIq], t, pusch_iq_display->GetEpsilon(), iq_procedure_timer); } pusch_iq_display->Draw(pusch_iq, t, new_data); } @@ -604,13 +541,33 @@ void ShowGnbScope(PHY_VARS_gNB *gNB, float t) static auto time_domain_iq = new IQHist("Time domain samples", disable_scatterplot); bool new_data = false; if (time_domain_iq->ShouldReadData()) { - new_data = iq_data->TryCollect(&scope_array[gNbTimeDomainSamples], t, time_domain_iq->GetEpsilon()); + new_data = iq_data->TryCollect(&scope_array[gNbTimeDomainSamples], t, time_domain_iq->GetEpsilon(), iq_procedure_timer); } time_domain_iq->Draw(iq_data, t, new_data); } ImGui::End(); } +void ShowIQFileViewer(void *data_void_ptr) +{ + auto iq_data = static_cast *>(data_void_ptr); + if (ImGui::Begin("Scope selection")) { + static int selected_scope = 0; + ImGui::Combo( + "Select scope", + &selected_scope, + [](void *userdata, int idx) { + std::vector *iq_data = static_cast*>(userdata); + return scope_id_to_string(static_cast((*iq_data)[idx].scope_id)); + }, + iq_data, + iq_data->size()); + static auto iq_display = new IQHist("IQ File Viewer"); + iq_display->Draw(&(*iq_data)[selected_scope], 0, false); + } + ImGui::End(); +} + void *imscope_thread(void *data_void_ptr) { glfwSetErrorCallback(glfw_error_callback); @@ -678,6 +635,7 @@ void *imscope_thread(void *data_void_ptr) static int target_fps = 24; bool is_ue = IS_SOFTMODEM_5GUE; + bool is_gnb = IS_SOFTMODEM_GNB; bool close_window = false; while (!glfwWindowShouldClose(window) && close_window == false) { // Poll and handle events (inputs, window resize, etc.) @@ -694,8 +652,7 @@ void *imscope_thread(void *data_void_ptr) ImGui_ImplGlfw_NewFrame(); static bool reset_ini_settings = false; - if (reset_ini_settings) - { + if (reset_ini_settings) { ImGui::LoadIniSettingsFromDisk("imscope-init.ini"); reset_ini_settings = false; } @@ -722,7 +679,7 @@ void *imscope_thread(void *data_void_ptr) } if (ImGui::BeginMenu("Layout")) { if (ImGui::MenuItem("Reset")) { - reset_ini_settings = true; + reset_ini_settings = true; } ImGui::EndMenu(); } @@ -750,12 +707,11 @@ void *imscope_thread(void *data_void_ptr) iq_procedure_timer.UpdateAverage(t); if (is_ue) { - PHY_VARS_NR_UE *ue = (PHY_VARS_NR_UE *)data_void_ptr; - ShowUeScope(ue, t); + ShowUeScope(data_void_ptr, t); + } else if (is_gnb) { + ShowGnbScope(data_void_ptr, t); } else { - scopeParms_t *scope_params = (scopeParms_t *)data_void_ptr; - PHY_VARS_gNB *gNB = scope_params->gNB; - ShowGnbScope(gNB, t); + ShowIQFileViewer(data_void_ptr); } // For reference @@ -791,147 +747,3 @@ void *imscope_thread(void *data_void_ptr) return nullptr; } - -extern "C" void imscope_autoinit(void *dataptr) -{ - AssertFatal(IS_SOFTMODEM_5GUE || IS_SOFTMODEM_GNB, "Scope cannot find NRUE or GNB context"); - - for (auto i = 0U; i < EXTRA_SCOPE_TYPES; i++) { - scope_array[i].is_data_ready = false; - scope_array[i].scope_graph_data = nullptr; - scope_array[i].meta = {-1, -1}; - } - - if (IS_SOFTMODEM_GNB) { - scopeParms_t *scope_params = (scopeParms_t *)dataptr; - scopeData_t *scope = (scopeData_t *)calloc(1, sizeof(scopeData_t)); - scope->copyData = copyDataThreadSafe; - scope->tryLockScopeData = tryLockScopeData; - scope->copyDataUnsafeWithOffset = copyDataUnsafeWithOffset; - scope->unlockScopeData = unlockScopeData; - scope_params->gNB->scopeData = scope; - scope_params->ru->scopeData = scope; - } else { - PHY_VARS_NR_UE *ue = (PHY_VARS_NR_UE *)dataptr; - scopeData_t *scope = (scopeData_t *)calloc(1, sizeof(scopeData_t)); - scope->copyData = copyDataThreadSafe; - ue->scopeData = scope; - } - pthread_t thread; - threadCreate(&thread, imscope_thread, dataptr, (char *)"imscope", -1, sched_get_priority_min(SCHED_RR)); -} - -void copyDataThreadSafe(void *scopeData, - enum scopeDataType type, - void *dataIn, - int elementSz, - int colSz, - int lineSz, - int offset, - metadata *meta) -{ - ImScopeData &scope_data = scope_array[type]; - - if (scope_data.is_data_ready) { - // data is ready, wasn't consumed yet by scope - return; - } - - if (scope_data.write_mutex.try_lock()) { - auto start = std::chrono::high_resolution_clock::now(); - scopeGraphData_t *data = scope_data.scope_graph_data; - int oldDataSz = data ? data->dataSize : 0; - int newSz = elementSz * colSz * lineSz; - if (data == NULL || oldDataSz < newSz) { - free(data); - scopeGraphData_t *ptr = (scopeGraphData_t *)malloc(sizeof(scopeGraphData_t) + newSz); - if (!ptr) { - LOG_E(PHY, "can't realloc\n"); - return; - } else { - data = ptr; - } - } - - data->elementSz = elementSz; - data->colSz = colSz; - data->lineSz = lineSz; - data->dataSize = newSz; - memcpy(((void *)(data + 1)), dataIn, newSz); - scope_data.scope_graph_data = data; - scope_data.meta = *meta; - scope_data.time_taken_in_ns = - std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start).count(); - scope_data.is_data_ready = true; - scope_data.write_mutex.unlock(); - } -} - -bool tryLockScopeData(enum scopeDataType type, int elementSz, int colSz, int lineSz, metadata *meta) -{ - ImScopeData &scope_data = scope_array[type]; - - if (scope_data.is_data_ready) { - // data is ready, wasn't consumed yet by scope - return false; - } - - if (scope_data.write_mutex.try_lock()) { - auto start = std::chrono::high_resolution_clock::now(); - scopeGraphData_t *data = scope_data.scope_graph_data; - int oldDataSz = data ? data->dataSize : 0; - int newSz = elementSz * colSz * lineSz; - if (data == NULL || oldDataSz < newSz) { - free(data); - scopeGraphData_t *ptr = (scopeGraphData_t *)malloc(sizeof(scopeGraphData_t) + newSz); - if (!ptr) { - LOG_E(PHY, "can't realloc\n"); - return false; - } else { - data = ptr; - } - } - - data->elementSz = elementSz; - data->colSz = colSz; - data->lineSz = lineSz; - data->dataSize = newSz; - scope_data.scope_graph_data = data; - scope_data.meta = *meta; - scope_data.time_taken_in_ns = - std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start).count(); - memset(scope_data.time_taken_in_ns_per_offset, 0, sizeof(scope_data.time_taken_in_ns_per_offset)); - memset(scope_data.data_copied_per_offset, 0, sizeof(scope_data.data_copied_per_offset)); - return true; - } - return false; -} - -void copyDataUnsafeWithOffset(enum scopeDataType type, void *dataIn, size_t size, size_t offset, int copy_index) -{ - AssertFatal(copy_index < MAX_OFFSETS, "Unexpected number of copies per sink. copy_index = %d\n", copy_index); - ImScopeData &scope_data = scope_array[type]; - auto start = std::chrono::high_resolution_clock::now(); - scopeGraphData_t *data = scope_data.scope_graph_data; - uint8_t *outptr = (uint8_t *)(data + 1); - memcpy(&outptr[offset], dataIn, size); - scope_data.time_taken_in_ns_per_offset[copy_index] = - std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start).count(); - scope_data.data_copied_per_offset[copy_index] = size; -} - -void unlockScopeData(enum scopeDataType type) -{ - ImScopeData &scope_data = scope_array[type]; - size_t total_size = 0; - for (auto i = 0; i < MAX_OFFSETS; i++) { - scope_data.time_taken_in_ns += scope_data.time_taken_in_ns_per_offset[i]; - total_size += scope_data.data_copied_per_offset[i]; - } - if (total_size != (uint64_t)scope_data.scope_graph_data->dataSize) { - LOG_E(PHY, - "Scope is missing data - not all data that was expected was copied - possibly missed copyDataUnsafeWithOffset call\n"); - } - scope_data.is_data_ready = true; - scope_data.write_mutex.unlock(); -} diff --git a/openair1/PHY/TOOLS/imscope/imscope_common.cpp b/openair1/PHY/TOOLS/imscope/imscope_common.cpp new file mode 100644 index 0000000000..b1bdda0905 --- /dev/null +++ b/openair1/PHY/TOOLS/imscope/imscope_common.cpp @@ -0,0 +1,194 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "imscope_internal.h" +#include + +void copyDataThreadSafe(void *scopeData, + enum scopeDataType type, + void *dataIn, + int elementSz, + int colSz, + int lineSz, + int offset, + metadata *meta) +{ + ImScopeDataWrapper &scope_data = scope_array[type]; + + if (scope_data.is_data_ready) { + // data is ready, wasn't consumed yet by scope + return; + } + + if (scope_data.write_mutex.try_lock()) { + auto start = std::chrono::high_resolution_clock::now(); + scopeGraphData_t *data = scope_data.data.scope_graph_data; + int oldDataSz = data ? data->dataSize : 0; + int newSz = elementSz * colSz * lineSz; + if (data == NULL || oldDataSz < newSz) { + free(data); + scopeGraphData_t *ptr = (scopeGraphData_t *)malloc(sizeof(scopeGraphData_t) + newSz); + if (!ptr) { + LOG_E(PHY, "can't realloc\n"); + return; + } else { + data = ptr; + } + } + + data->elementSz = elementSz; + data->colSz = colSz; + data->lineSz = lineSz; + data->dataSize = newSz; + memcpy(((void *)(data + 1)), dataIn, newSz); + scope_data.data.scope_graph_data = data; + scope_data.data.meta = *meta; + scope_data.data.time_taken_in_ns = + std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start).count(); + scope_data.data.scope_id = type; + scope_data.is_data_ready = true; + scope_data.write_mutex.unlock(); + } +} + +bool tryLockScopeData(enum scopeDataType type, int elementSz, int colSz, int lineSz, metadata *meta) +{ + ImScopeDataWrapper &scope_data = scope_array[type]; + + if (scope_data.is_data_ready) { + // data is ready, wasn't consumed yet by scope + return false; + } + + if (scope_data.write_mutex.try_lock()) { + auto start = std::chrono::high_resolution_clock::now(); + scopeGraphData_t *data = scope_data.data.scope_graph_data; + int oldDataSz = data ? data->dataSize : 0; + int newSz = elementSz * colSz * lineSz; + if (data == NULL || oldDataSz < newSz) { + free(data); + scopeGraphData_t *ptr = (scopeGraphData_t *)malloc(sizeof(scopeGraphData_t) + newSz); + if (!ptr) { + LOG_E(PHY, "can't realloc\n"); + return false; + } else { + data = ptr; + } + } + + data->elementSz = elementSz; + data->colSz = colSz; + data->lineSz = lineSz; + data->dataSize = newSz; + scope_data.data.scope_graph_data = data; + scope_data.data.meta = *meta; + scope_data.data.time_taken_in_ns = + std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start).count(); + memset(scope_data.data.time_taken_in_ns_per_offset, 0, sizeof(scope_data.data.time_taken_in_ns_per_offset)); + memset(scope_data.data.data_copied_per_offset, 0, sizeof(scope_data.data.data_copied_per_offset)); + return true; + } + return false; +} + +void copyDataUnsafeWithOffset(enum scopeDataType type, void *dataIn, size_t size, size_t offset, int copy_index) +{ + AssertFatal(copy_index < MAX_OFFSETS, "Unexpected number of copies per sink. copy_index = %d\n", copy_index); + ImScopeDataWrapper &scope_data = scope_array[type]; + auto start = std::chrono::high_resolution_clock::now(); + scopeGraphData_t *data = scope_data.data.scope_graph_data; + uint8_t *outptr = (uint8_t *)(data + 1); + memcpy(&outptr[offset], dataIn, size); + scope_data.data.time_taken_in_ns_per_offset[copy_index] = + std::chrono::duration_cast(std::chrono::high_resolution_clock::now() - start).count(); + scope_data.data.data_copied_per_offset[copy_index] = size; +} + +void unlockScopeData(enum scopeDataType type) +{ + ImScopeDataWrapper &scope_data = scope_array[type]; + size_t total_size = 0; + for (auto i = 0; i < MAX_OFFSETS; i++) { + scope_data.data.time_taken_in_ns += scope_data.data.time_taken_in_ns_per_offset[i]; + total_size += scope_data.data.data_copied_per_offset[i]; + } + if (total_size != (uint64_t)scope_data.data.scope_graph_data->dataSize) { + LOG_E(PHY, + "Scope is missing data - not all data that was expected was copied - possibly missed copyDataUnsafeWithOffset call. " + "scope = %s, total_size = %lu, dataSize = %d\n", + scope_id_to_string(type), + total_size, + scope_data.data.scope_graph_data->dataSize); + } + scope_data.data.scope_id = type; + scope_data.is_data_ready = true; + scope_data.write_mutex.unlock(); +} + +const char *scope_id_to_string(scopeDataType type) { + switch (type) { + case pbchDlChEstimateTime: + return "pbchDlChEstimateTime"; + case pbchLlr: + return "pbchLlr"; + case pbchRxdataF_comp: + return "pbchRxdataF_comp"; + case pdcchLlr: + return "pdcchLlr"; + case pdcchRxdataF_comp: + return "pdcchRxdataF_comp"; + case pdschLlr: + return "pdschLlr"; + case pdschRxdataF_comp: + return "pdschRxdataF_comp"; + case commonRxdataF: + return "commonRxdataF"; + case gNBRxdataF: + return "gNBRxdataF"; + case psbchDlChEstimateTime: + return "psbchDlChEstimateTime"; + case psbchLlr: + return "psbchLlr"; + case psbchRxdataF_comp: + return "psbchRxdataF_comp"; + case gNBPuschRxIq: + return "gNBPuschRxIq"; + case gNBPuschLlr: + return "gNBPuschLlr"; + case ueTimeDomainSamples: + return "ueTimeDomainSamples"; + case ueTimeDomainSamplesBeforeSync: + return "ueTimeDomainSamplesBeforeSync"; + case gNbTimeDomainSamples: + return "gNbTimeDomainSamples"; + default: + return "unknown type"; + } +} + +std::ostream &operator<<(std::ostream &os, const ImScopeData &dt) +{ + os << "dataSize: " << dt.scope_graph_data->dataSize << " elementSz: " << dt.scope_graph_data->elementSz + << " colSz: " << dt.scope_graph_data->colSz << " lineSz: " << dt.scope_graph_data->lineSz; + os << " meta: " << dt.meta.frame << "." << dt.meta.slot + << " scope_id: " << scope_id_to_string(static_cast(dt.scope_id)); + return os; +} diff --git a/openair1/PHY/TOOLS/imscope/imscope_init.cpp b/openair1/PHY/TOOLS/imscope/imscope_init.cpp new file mode 100644 index 0000000000..2bb3d8dd33 --- /dev/null +++ b/openair1/PHY/TOOLS/imscope/imscope_init.cpp @@ -0,0 +1,52 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "imscope_internal.h" + +extern "C" void imscope_autoinit(void *dataptr) +{ + AssertFatal(IS_SOFTMODEM_5GUE || IS_SOFTMODEM_GNB, + "Scope cannot find NRUE or GNB context"); + + for (auto i = 0U; i < EXTRA_SCOPE_TYPES; i++) { + scope_array[i].is_data_ready = false; + scope_array[i].data.scope_graph_data = nullptr; + scope_array[i].data.meta = {-1, -1}; + } + + scopeData_t *scope = (scopeData_t *)calloc(1, sizeof(scopeData_t)); + scope->copyData = copyDataThreadSafe; + scope->tryLockScopeData = tryLockScopeData; + scope->copyDataUnsafeWithOffset = copyDataUnsafeWithOffset; + scope->unlockScopeData = unlockScopeData; + scope->copyData = copyDataThreadSafe; + if (IS_SOFTMODEM_GNB) { + scopeParms_t *scope_params = (scopeParms_t *)dataptr; + scope_params->gNB->scopeData = scope; + scope_params->ru->scopeData = scope; + } else { + PHY_VARS_NR_UE *ue = (PHY_VARS_NR_UE *)dataptr; + ue->scopeData = scope; + } + + pthread_t thread; + threadCreate(&thread, imscope_thread, dataptr, (char *)"imscope", -1, sched_get_priority_min(SCHED_RR)); +} diff --git a/openair1/PHY/TOOLS/imscope/imscope_internal.h b/openair1/PHY/TOOLS/imscope/imscope_internal.h new file mode 100644 index 0000000000..7b0b04758d --- /dev/null +++ b/openair1/PHY/TOOLS/imscope/imscope_internal.h @@ -0,0 +1,160 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef IMSCOPE_INTERNAL_H +#define IMSCOPE_INTERNAL_H + +#include +#include +#include +#include +#include "openair1/PHY/defs_nr_UE.h" +extern "C" { +#include "../phy_scope_interface.h" +} + +#define MAX_OFFSETS 14 + +const char *scope_id_to_string(scopeDataType type); + +typedef struct ImScopeData { + scopeGraphData_t *scope_graph_data; + metadata meta; + uint64_t time_taken_in_ns; + uint64_t time_taken_in_ns_per_offset[MAX_OFFSETS]; + size_t data_copied_per_offset[MAX_OFFSETS]; + int scope_id; + + void dump_to_file(std::ofstream& stream) { + stream.write((char*)scope_graph_data, sizeof(*scope_graph_data)); + stream.write((char*)&meta, sizeof(meta)); + stream.write((char*)&scope_id, sizeof(scope_id)); + char *source = (char *)(scope_graph_data + 1); + stream.write(source, scope_graph_data->dataSize); + } + + void read_from_file(std::ifstream& stream) { + scopeGraphData_t temp; + stream.read((char*)&temp, sizeof(temp)); + stream.read((char*)&meta, sizeof(meta)); + stream.read((char*)&scope_id, sizeof(scope_id)); + scope_graph_data = static_cast(malloc(temp.dataSize + sizeof(*scope_graph_data))); + *scope_graph_data = temp; + char *dest = (char *)(scope_graph_data + 1); + stream.read(dest, temp.dataSize); + } + + friend std::ostream& operator<<(std::ostream& os, const ImScopeData& dt); +} ImScopeData; + +typedef struct MovingAverageTimer { + uint64_t sum = 0; + float average = 0; + float last_update_time = 0; + void UpdateAverage(float time) + { + if (time > last_update_time + 1) { + float new_average = sum / (float)((time - last_update_time) / 1000); + average = 0.95 * average + 0.05 * new_average; + sum = 0; + } + } + void Add(uint64_t ns) + { + sum += ns; + } +} MovingAverageTimer; + +typedef struct ImScopeDataWrapper { + std::mutex write_mutex; + bool is_data_ready; + ImScopeData data; +} ImScopeDataWrapper; + +typedef struct IQData { + std::vector real; + std::vector imag; + int16_t max_iq; + std::vector power; + float max_power; + float timestamp; + int nonzero_count; + int len = 0; + metadata meta; + int scope_id; + + bool TryCollect(ImScopeDataWrapper *imscope_data_wrapper, float time, float epsilon, MovingAverageTimer &iq_procedure_timer) + { + if (imscope_data_wrapper->is_data_ready) { + Collect(&imscope_data_wrapper->data, time, epsilon); + iq_procedure_timer.Add(imscope_data_wrapper->data.time_taken_in_ns); + imscope_data_wrapper->is_data_ready = false; + return true; + } + return false; + } + + void Collect(ImScopeData *scope_data, float time, float epsilon) { + timestamp = time; + scopeGraphData_t *iq_header = scope_data->scope_graph_data; + len = iq_header->lineSz; + real.resize(len); + imag.resize(len); + power.resize(len); + c16_t *source = (c16_t *)(iq_header + 1); + max_iq = 0; + nonzero_count = 0; + for (auto i = 0; i < len; i++) { + real[i] = source[i].r; + imag[i] = source[i].i; + max_iq = std::max(max_iq, (int16_t)std::abs(source[i].r)); + max_iq = std::max(max_iq, (int16_t)std::abs(source[i].i)); + nonzero_count = std::abs(source[i].r) > epsilon || std::abs(source[i].i) > epsilon ? nonzero_count + 1 : nonzero_count; + power[i] = std::sqrt(std::pow(source[i].r, 2) + std::pow(source[i].i, 2)); + } + meta = scope_data->meta; + scope_id = scope_data->scope_id; + } +} IQData; + +extern ImScopeDataWrapper scope_array[EXTRA_SCOPE_TYPES]; + +void copyDataThreadSafe(void *scopeData, + enum scopeDataType type, + void *dataIn, + int elementSz, + int colSz, + int lineSz, + int offset, + metadata *meta); + +bool tryLockScopeData(enum scopeDataType type, int elementSz, int colSz, int lineSz, metadata *meta); + +void copyDataUnsafeWithOffset(enum scopeDataType type, void *dataIn, size_t size, size_t offset, int copy_index); + +void unlockScopeData(enum scopeDataType type); + +void dumpScopeData(int slot, int frame, const char *cause_string); + +void *imscope_record_thread(void *data_void_ptr); +void *imscope_thread(void *data_void_ptr); + +#endif diff --git a/openair1/PHY/TOOLS/imscope/imscope_iq_file_viewer.cpp b/openair1/PHY/TOOLS/imscope/imscope_iq_file_viewer.cpp new file mode 100644 index 0000000000..5f9eaf46ab --- /dev/null +++ b/openair1/PHY/TOOLS/imscope/imscope_iq_file_viewer.cpp @@ -0,0 +1,74 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include +#include +#include +#include "imscope_internal.h" + +static extended_kpi_ue kpiStructure; + +extern "C" { +static softmodem_params_t softmodem_params; +softmodem_params_t *get_softmodem_params(void) +{ + return &softmodem_params; +} +extended_kpi_ue *getKPIUE(void) +{ + return &kpiStructure; +} +} + +void *imscope_thread(void *data_void_ptr); + + +std::vector LoadFromFile(char *filename) { + std::ifstream file(filename, std::ios::binary); + std::vector iq_data; + if (file.is_open()) { + while (file.peek() != EOF) { + ImScopeData source; + source.read_from_file(file); + std::cout << "Loaded from IQ from file: " << source << std::endl; + IQData iq; + iq.Collect(&source, 0, 0); + iq_data.push_back(iq); + } + } + return iq_data; +} + +int main(int argc, char **argv) +{ + if (argc < 2) { + printf("Usage: %s \n", argv[0]); + return 1; + } + + std::vector iq_data = LoadFromFile(argv[1]); + if (iq_data.size() == 0) { + printf("Error: No IQ data found in file\n"); + return 1; + } + + imscope_thread(static_cast(&iq_data)); +} diff --git a/openair1/PHY/TOOLS/imscope/imscope_record.cpp b/openair1/PHY/TOOLS/imscope/imscope_record.cpp new file mode 100644 index 0000000000..6855e1b69d --- /dev/null +++ b/openair1/PHY/TOOLS/imscope/imscope_record.cpp @@ -0,0 +1,160 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "imscope_internal.h" +#include "openair1/PHY/TOOLS/phy_scope_interface.h" +#include +#include +#include +#include + +#ifdef __cpp_lib_hardware_interference_size + using std::hardware_constructive_interference_size; + using std::hardware_destructive_interference_size; +#else + // 64 bytes on x86-64 │ L1_CACHE_BYTES │ L1_CACHE_SHIFT │ __cacheline_aligned │ ... + constexpr std::size_t hardware_constructive_interference_size = 64; + constexpr std::size_t hardware_destructive_interference_size = 64; +#endif + +#define NUM_CACHED_DATA 4 +// Set maximum number of kilobytes written per recording session to 1GB. This is a safeguard against +// recoding thread writing too many files and exhausting disk space. +#define MAX_KBYTES_WRITTEN_PER_SESSION (1000 * 1000) + +ImScopeDataWrapper scope_array[EXTRA_SCOPE_TYPES]; +typedef struct alignas(hardware_destructive_interference_size) ImScopeDumpInstruction { + int slot; + int frame; + const char *cause; +} ImScopeDumpInstruction; + +std::atomic dump_instruction; +ImScopeDumpInstruction void_instruction({-1, -1, nullptr}); + +extern "C" void imscope_record_autoinit(void *dataptr) +{ + AssertFatal(IS_SOFTMODEM_5GUE || IS_SOFTMODEM_GNB, + "Scope cannot find NRUE or GNB context"); + LOG_A(PHY, "Imscope recording started\n"); + + for (auto i = 0U; i < EXTRA_SCOPE_TYPES; i++) { + scope_array[i].is_data_ready = false; + scope_array[i].data.scope_graph_data = nullptr; + scope_array[i].data.meta = {-1, -1}; + } + + dump_instruction.exchange(void_instruction); + + scopeData_t *scope = (scopeData_t *)calloc(1, sizeof(scopeData_t)); + scope->copyData = copyDataThreadSafe; + scope->tryLockScopeData = tryLockScopeData; + scope->copyDataUnsafeWithOffset = copyDataUnsafeWithOffset; + scope->unlockScopeData = unlockScopeData; + scope->copyData = copyDataThreadSafe; + scope->dumpScopeData = dumpScopeData; + if (IS_SOFTMODEM_GNB) { + scopeParms_t *scope_params = (scopeParms_t *)dataptr; + scope_params->gNB->scopeData = scope; + scope_params->ru->scopeData = scope; + } else { + PHY_VARS_NR_UE *ue = (PHY_VARS_NR_UE *)dataptr; + ue->scopeData = scope; + } + + pthread_t thread; + threadCreate(&thread, imscope_record_thread, dataptr, (char *)"imscope_record", -1, sched_get_priority_min(SCHED_RR)); +} + +void dumpScopeData(int slot, int frame, const char *cause_string) +{ + ImScopeDumpInstruction to_dump = {slot, frame, cause_string}; + dump_instruction.compare_exchange_weak(void_instruction, to_dump); +} + +void *imscope_record_thread(void *data_void_ptr) +{ + const char *path = "imscope-dump"; + struct stat info; + bool has_dir = false; + if (stat(path, &info) == 0) { + if (info.st_mode & S_IFDIR) { + has_dir = true; + } + } + if (has_dir) { + LOG_A(PHY, "ImScope recorder thread starts, recording data to %s\n", path); + } else { + LOG_A(PHY, "ImScope recorder thread starts, recording data to cwd\n"); + } + + std::string program_name(program_invocation_name); + size_t last_slash = program_name.find_last_of("/"); + if (last_slash != std::string::npos) { + program_name = program_name.substr(last_slash + 1); + } + + ImScopeData scope_cache[EXTRA_SCOPE_TYPES][NUM_CACHED_DATA]; + memset(scope_cache, 0, sizeof(scope_cache)); + uint scope_cache_index[EXTRA_SCOPE_TYPES] = {0}; + float kbytes_written = 0.0f; + while (kbytes_written < MAX_KBYTES_WRITTEN_PER_SESSION) { + ImScopeDumpInstruction dump = dump_instruction.load(std::memory_order::memory_order_relaxed); + if (dump.slot != -1) { + std::string filename; + if (has_dir) { + filename += std::string(path) + "/"; + } + filename += program_name + std::string("-") + dump.cause + std::string("-"); + filename += std::to_string(dump.frame) + std::string("-") + std::to_string(dump.slot) + std::string(".imscope"); + std::ofstream outf(filename, std::ios_base::out | std::ios_base::binary); + if (!outf) { + LOG_E(PHY, "Could not open file %s for writing\n", filename.c_str()); + break; + } + for (auto i = 0U; i < EXTRA_SCOPE_TYPES; i++) { + for (auto j = 0U; j < NUM_CACHED_DATA; j++) { + ImScopeData &scope_data = scope_cache[i][j]; + if (scope_data.meta.frame == dump.frame && scope_data.meta.slot == dump.slot) { + scope_data.dump_to_file(outf); + } + } + } + long pos = outf.tellp(); + kbytes_written += pos / 1000.0f; + outf.close(); + LOG_D(PHY, "ImScope done writing to %s\n", filename.c_str()); + dump_instruction.exchange(void_instruction); + } + for (auto i = 0U; i < EXTRA_SCOPE_TYPES; i++) { + ImScopeDataWrapper &scope_data = scope_array[i]; + if (scope_data.is_data_ready) { + uint cache_index = scope_cache_index[i]++ % NUM_CACHED_DATA; + ImScopeData tmp = scope_cache[i][cache_index]; + scope_cache[i][cache_index] = scope_data.data; + scope_data.data = tmp; + scope_data.is_data_ready = false; + } + } + } + LOG_E(PHY, "ImScope recorder thread exits!\n"); + return nullptr; +} diff --git a/openair1/PHY/TOOLS/phy_scope_interface.h b/openair1/PHY/TOOLS/phy_scope_interface.h index 2fa97880b4..59e7d93dd9 100644 --- a/openair1/PHY/TOOLS/phy_scope_interface.h +++ b/openair1/PHY/TOOLS/phy_scope_interface.h @@ -112,6 +112,7 @@ typedef struct scopeData_s { bool (*tryLockScopeData)(enum scopeDataType type, int elementSz, int colSz, int lineSz, metadata *meta); void (*copyDataUnsafeWithOffset)(enum scopeDataType type, void *dataIn, size_t size, size_t offset, int copy_index); void (*unlockScopeData)(enum scopeDataType type); + void (*dumpScopeData)(int slot, int frame, const char *cause_string); } scopeData_t; int load_softscope(char *exectype, void *initarg); @@ -157,6 +158,14 @@ void copyData(void *, enum scopeDataType type, void *dataIn, int elementSz, int scope_data->unlockScopeData(type); \ } +#define gNBdumpScopeData(gnb, slot, frame, cause_string) \ + do { \ + scopeData_t *scope_data = (scopeData_t *)gnb->scopeData; \ + if (scope_data && scope_data->dumpScopeData) { \ + scope_data->dumpScopeData((slot), (frame), (cause_string)); \ + } \ + } while (0) + #define UEScopeHasTryLock(ue) \ (ue->scopeData && ((scopeData_t *)ue->scopeData)->tryLockScopeData) @@ -176,6 +185,20 @@ void copyData(void *, enum scopeDataType type, void *dataIn, int elementSz, int scope_data->unlockScopeData(type); \ } +#define UEdumpScopeData(ue, slot, frame, cause_string) \ + do { \ + scopeData_t *scope_data = (scopeData_t *)ue->scopeData; \ + if (scope_data && scope_data->dumpScopeData) { \ + scope_data->dumpScopeData((slot), (frame), (cause_string)); \ + } \ + } while (0) + +#ifdef __cplusplus +extern "C" { +#endif extended_kpi_ue* getKPIUE(); +#ifdef __cplusplus +} +#endif #endif diff --git a/openair1/PHY/TOOLS/readme.md b/openair1/PHY/TOOLS/readme.md index 9d1f4d465b..bff976c529 100644 --- a/openair1/PHY/TOOLS/readme.md +++ b/openair1/PHY/TOOLS/readme.md @@ -69,3 +69,21 @@ Run with `--imscope` flag Report bugs and feature requests on [gitlab](https://gitlab.eurecom.fr/oai/openairinterface5g/-/issues). There is two demo windows enabled in the scope that showcase imgui/implot, if you find something of interest it can be implemented in the scope. + +## Recording scope data and reviewing recorded IQ files + +It is possible to record scope data from the modems. + - To record IQ data, run a modem with `--imscope-record` flag. + The recording happens whenever a modem calls `dumpScopeData`, which currently is + done only in gNB on PUSCH DTX and PUSCH CRC NOK. + There is a limit of ~1GB of files written by the thread in a single run to avoid + accidentally exhausting disk space. + If a directory `imscope-dump` is available the data will be recorded there in .imscope + files. Otherwise files are written to the directory the modem was run. This is done so that + the directory can be mapped in a docker container. + + - To view recorded IQ files, use the new executable `imscope_iq_file_viewer`. This can be done by running: + ``` + ./imscope_iq_file_viewer + ``` + Replace `` with the path to the IQ file you want to view. diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index ae6bbbc2cd..172c608d38 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -627,6 +627,7 @@ typedef struct nr_rxtx_thread_data_s { PHY_VARS_NR_UE *UE; int writeBlockSize; nr_phy_data_t phy_data; + dynamic_barrier_t *next_barrier; } nr_rxtx_thread_data_t; typedef struct LDPCDecode_ue_s { diff --git a/openair1/PHY/defs_nr_common.h b/openair1/PHY/defs_nr_common.h index f6f18eb942..da01d7e639 100644 --- a/openair1/PHY/defs_nr_common.h +++ b/openair1/PHY/defs_nr_common.h @@ -52,7 +52,6 @@ #define NR_MOD_TABLE_SIZE_SHORT 686 #define NR_MOD_TABLE_BPSK_OFFSET 1 -#define NR_MOD_TABLE_QPSK_OFFSET 3 #define NR_MOD_TABLE_QAM16_OFFSET 7 #define NR_MOD_TABLE_QAM64_OFFSET 23 #define NR_MOD_TABLE_QAM256_OFFSET 87 diff --git a/openair1/SCHED_NR/fapi_nr_l1.c b/openair1/SCHED_NR/fapi_nr_l1.c index 949011a6f5..10512f3f66 100644 --- a/openair1/SCHED_NR/fapi_nr_l1.c +++ b/openair1/SCHED_NR/fapi_nr_l1.c @@ -39,14 +39,7 @@ #include "PHY/NR_TRANSPORT/nr_dci.h" #include "nfapi/oai_integration/vendor_ext.h" #include "openair2/NR_PHY_INTERFACE/nr_sched_response.h" - -extern int oai_nfapi_dl_tti_req(nfapi_nr_dl_tti_request_t *dl_config_req); -extern int oai_nfapi_tx_data_req(nfapi_nr_tx_data_request_t *tx_data_req); -extern int oai_nfapi_ul_dci_req(nfapi_nr_ul_dci_request_t *ul_dci_req); -extern int oai_nfapi_ul_tti_req(nfapi_nr_ul_tti_request_t *ul_tti_req); - - -extern uint8_t nfapi_mode; +#include "nfapi/oai_integration/nfapi_vnf.h" void handle_nr_nfapi_ssb_pdu(processingData_L1tx_t *msgTx,int frame,int slot, nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdu) diff --git a/openair1/SCHED_NR/nr_prach_procedures.c b/openair1/SCHED_NR/nr_prach_procedures.c index 75c8ae56c9..12ec6a0b42 100644 --- a/openair1/SCHED_NR/nr_prach_procedures.c +++ b/openair1/SCHED_NR/nr_prach_procedures.c @@ -42,9 +42,6 @@ #include "assertions.h" #include - -extern uint8_t nfapi_mode; - uint8_t get_nr_prach_duration(uint8_t prach_format){ switch(prach_format){ diff --git a/openair1/SCHED_NR/phy_frame_config_nr.c b/openair1/SCHED_NR/phy_frame_config_nr.c index ad672bccb8..bff35ce4ff 100644 --- a/openair1/SCHED_NR/phy_frame_config_nr.c +++ b/openair1/SCHED_NR/phy_frame_config_nr.c @@ -44,108 +44,112 @@ #define NR_TST_PHY_PRINTF(...) #endif -/******************************************************************* -* -* NAME : set_tdd_configuration -* -* PARAMETERS : pointer to frame configuration -* -* OUTPUT: table of uplink symbol for each slot for 2 frames -* -* RETURN : nb_periods_per_frame if tdd has been properly configurated -* -1 tdd configuration can not be done -* -* DESCRIPTION : generate bit map for uplink symbol for each slot for several frames -* see TS 38.213 11.1 Slot configuration -* -*********************************************************************/ - -int set_tdd_config_nr(nfapi_nr_config_request_scf_t *cfg, - int mu, - int nrofDownlinkSlots, - int nrofDownlinkSymbols, - int nrofUplinkSlots, - int nrofUplinkSymbols) +/** @brief This function processes TDD dedicated configuration for NR + * by processing the tdd_slot_bitmap and period_cfg, and + * allocates memory and fills max_num_of_symbol_per_slot_list + * in the nfapi config request (cfg) + * @ref see TS 38.213 11.1 Slot configuration + * @param cfg NR config request structure pointer + * @param fs TDD configuration pointer + * @returns void + */ +void set_tdd_config_nr(nfapi_nr_config_request_scf_t *cfg, frame_structure_t *fs) { + AssertFatal(fs != NULL, "frame_structure must be non-NULL"); + int slot_number = 0; - int nb_periods_per_frame = get_nb_periods_per_frame(cfg->tdd_table.tdd_period.value); - int nb_slots_to_set = (1 << mu) * NR_NUMBER_OF_SUBFRAMES_PER_FRAME; + int nb_slots_to_set = fs->numb_slots_frame; + int slot_index = 0; + tdd_period_config_t *pc = &fs->period_cfg; + tdd_bitmap_t *tdd_slot_bitmap = pc->tdd_slot_bitmap; - int nb_slots_per_period = ((1 << mu) * NR_NUMBER_OF_SUBFRAMES_PER_FRAME) / nb_periods_per_frame; - - if ((nrofDownlinkSymbols + nrofUplinkSymbols) == 0) - AssertFatal(nb_slots_per_period == (nrofDownlinkSlots + nrofUplinkSlots), - "set_tdd_configuration_nr: given period is inconsistent with current tdd configuration, nrofDownlinkSlots %d, " - "nrofUplinkSlots %d, nb_slots_per_period %d \n", - nrofDownlinkSlots, - nrofUplinkSlots, - nb_slots_per_period); - else { - AssertFatal(nrofDownlinkSymbols + nrofUplinkSymbols < 14, - "illegal symbol configuration DL %d, UL %d\n", - nrofDownlinkSymbols, - nrofUplinkSymbols); - AssertFatal(nb_slots_per_period == (nrofDownlinkSlots + nrofUplinkSlots + 1), - "set_tdd_configuration_nr: given period is inconsistent with current tdd configuration, nrofDownlinkSlots %d, " - "nrofUplinkSlots %d, nrofMixed slots 1, nb_slots_per_period %d \n", - nrofDownlinkSlots, - nrofUplinkSlots, - nb_slots_per_period); - } - - cfg->tdd_table.max_tdd_periodicity_list = calloc(nb_slots_to_set, sizeof(nfapi_nr_max_tdd_periodicity_t)); + LOG_I(NR_PHY, + "Set TDD Period Configuration: %d periods per frame, %d slots to be configured (%d DL, %d UL)\n", + fs->numb_period_frame, + nb_slots_to_set, + pc->num_dl_slots, + pc->num_ul_slots); + // Allocate memory formax_num_of_symbol_per_slot_list items + cfg->tdd_table.max_tdd_periodicity_list = calloc_or_fail(nb_slots_to_set, sizeof(nfapi_nr_max_tdd_periodicity_t)); for (int slot = 0; slot < nb_slots_to_set; slot++) { nfapi_nr_max_tdd_periodicity_t *p_list = &cfg->tdd_table.max_tdd_periodicity_list[slot]; p_list->max_num_of_symbol_per_slot_list = - calloc(NR_NUMBER_OF_SYMBOLS_PER_SLOT, sizeof(*p_list->max_num_of_symbol_per_slot_list)); + calloc_or_fail(NR_NUMBER_OF_SYMBOLS_PER_SLOT, sizeof(*p_list->max_num_of_symbol_per_slot_list)); for (int sym = 0; sym < NR_NUMBER_OF_SYMBOLS_PER_SLOT; sym++) { // for each symbol, assign the TLV tag for usage when packing p_list->max_num_of_symbol_per_slot_list[sym].slot_config.tl.tag = NFAPI_NR_CONFIG_SLOT_CONFIG_TAG; } } + // Loop through all periods to be configured while (slot_number != nb_slots_to_set) { - if (nrofDownlinkSlots != 0) { - for (int sym = 0; sym < nrofDownlinkSlots * NR_NUMBER_OF_SYMBOLS_PER_SLOT; sym++) { - cfg->tdd_table.max_tdd_periodicity_list[slot_number] - .max_num_of_symbol_per_slot_list[sym % NR_NUMBER_OF_SYMBOLS_PER_SLOT] - .slot_config.value = 0; - - if ((sym + 1) % NR_NUMBER_OF_SYMBOLS_PER_SLOT == 0) + slot_index = get_slot_idx_in_period(slot_number, fs); + /* Fill max_tdd_periodicity_list */ + nfapi_nr_max_tdd_periodicity_t *list = &cfg->tdd_table.max_tdd_periodicity_list[slot_number]; + // FULL DOWNLINK SLOTS + if (tdd_slot_bitmap[slot_index].slot_type == TDD_NR_DOWNLINK_SLOT) { + for (int sym = 0; sym < NR_NUMBER_OF_SYMBOLS_PER_SLOT; sym++) { + list->max_num_of_symbol_per_slot_list[sym % NR_NUMBER_OF_SYMBOLS_PER_SLOT].slot_config.value = 0; + if ((sym + 1) % NR_NUMBER_OF_SYMBOLS_PER_SLOT == 0) { slot_number++; + list += 1; + } } } - - if (nrofDownlinkSymbols != 0 || nrofUplinkSymbols != 0) { - for (int sym = 0; sym < nrofDownlinkSymbols; sym++) { - cfg->tdd_table.max_tdd_periodicity_list[slot_number].max_num_of_symbol_per_slot_list[sym].slot_config.value = 0; + // FLEXIBLE SLOTS + if (tdd_slot_bitmap[slot_index].slot_type == TDD_NR_MIXED_SLOT) { + int nrofDLSymbolsInSlot = tdd_slot_bitmap[slot_index].num_dl_symbols; + int nrofULSymbolsInSlot = tdd_slot_bitmap[slot_index].num_ul_symbols; + AssertFatal(nrofDLSymbolsInSlot + nrofULSymbolsInSlot < NR_NUMBER_OF_SYMBOLS_PER_SLOT, + "illegal symbol configuration DL %d, UL %d\n", + nrofDLSymbolsInSlot, + nrofULSymbolsInSlot); + // DL Symbols + for (int sym = 0; sym < nrofDLSymbolsInSlot; sym++) { + list->max_num_of_symbol_per_slot_list[sym].slot_config.value = 0; } - - for (int sym = nrofDownlinkSymbols; sym < NR_NUMBER_OF_SYMBOLS_PER_SLOT - nrofUplinkSymbols; sym++) { - cfg->tdd_table.max_tdd_periodicity_list[slot_number].max_num_of_symbol_per_slot_list[sym].slot_config.value = 2; + // Flexible Symbols + for (int sym = nrofDLSymbolsInSlot; sym < NR_NUMBER_OF_SYMBOLS_PER_SLOT - nrofULSymbolsInSlot; sym++) { + list->max_num_of_symbol_per_slot_list[sym].slot_config.value = 2; } - - for (int sym = NR_NUMBER_OF_SYMBOLS_PER_SLOT - nrofUplinkSymbols; sym < NR_NUMBER_OF_SYMBOLS_PER_SLOT; sym++) { - cfg->tdd_table.max_tdd_periodicity_list[slot_number].max_num_of_symbol_per_slot_list[sym].slot_config.value = 1; + // UL Symbols + for (int sym = NR_NUMBER_OF_SYMBOLS_PER_SLOT - nrofULSymbolsInSlot; sym < NR_NUMBER_OF_SYMBOLS_PER_SLOT; sym++) { + list->max_num_of_symbol_per_slot_list[sym].slot_config.value = 1; } - slot_number++; + list += 1; } - - if (nrofUplinkSlots != 0) { - for (int sym = 0; sym < nrofUplinkSlots * NR_NUMBER_OF_SYMBOLS_PER_SLOT; sym++) { - cfg->tdd_table.max_tdd_periodicity_list[slot_number] - .max_num_of_symbol_per_slot_list[sym % NR_NUMBER_OF_SYMBOLS_PER_SLOT] - .slot_config.value = 1; - - if ((sym + 1) % NR_NUMBER_OF_SYMBOLS_PER_SLOT == 0) + // FULL UPLINK SLOTS + if (tdd_slot_bitmap[slot_index].slot_type == TDD_NR_UPLINK_SLOT) { + for (int sym = 0; sym < NR_NUMBER_OF_SYMBOLS_PER_SLOT; sym++) { + list->max_num_of_symbol_per_slot_list[sym % NR_NUMBER_OF_SYMBOLS_PER_SLOT].slot_config.value = 1; + if ((sym + 1) % NR_NUMBER_OF_SYMBOLS_PER_SLOT == 0) { slot_number++; + list += 1; + } } } } - - return (nb_periods_per_frame); + // Dump 1 period on the output + for (int s = 0; s < fs->numb_slots_period; s++) { + if (tdd_slot_bitmap[s].slot_type == TDD_NR_MIXED_SLOT) { + char flexi_slot[NR_NUMBER_OF_SYMBOLS_PER_SLOT + 1]; + memset(flexi_slot, 0, sizeof(flexi_slot)); + for (int symb = 0; symb < NR_NUMBER_OF_SYMBOLS_PER_SLOT; symb++) { + uint8_t val = cfg->tdd_table.max_tdd_periodicity_list[s].max_num_of_symbol_per_slot_list[symb].slot_config.value; + char *symb_type_s[] = {"D", "U", "F"}; + flexi_slot[symb] = *symb_type_s[val]; + } + flexi_slot[NR_NUMBER_OF_SYMBOLS_PER_SLOT] = '\0'; + LOG_I(NR_PHY, "TDD period configuration: slot %d is FLEXIBLE: %s\n", s, flexi_slot); + } else { + LOG_I(NR_PHY, + "TDD period configuration: slot %d is %s\n", + s, + tdd_slot_bitmap[s].slot_type == TDD_NR_DOWNLINK_SLOT ? "DOWNLINK" : "UPLINK"); + } + } } /******************************************************************* @@ -389,3 +393,48 @@ void free_tdd_configuration_dedicated_nr(NR_DL_FRAME_PARMS *frame_parms) { } } +void do_tdd_config_sim(PHY_VARS_gNB *gNB, int mu) +{ + frame_structure_t fs = {.is_tdd = true}; + fs.numb_slots_frame = (1 << mu) * NR_NUMBER_OF_SUBFRAMES_PER_FRAME; + fs.numb_period_frame = get_nb_periods_per_frame(gNB->gNB_config.tdd_table.tdd_period.value); + fs.numb_slots_period = fs.numb_slots_frame / fs.numb_period_frame; + tdd_period_config_t *pc = &fs.period_cfg; + // Set DL/UL slots + switch (mu) + { + case 0: + pc->num_dl_slots = 3; + pc->num_ul_slots = 1; + break; + + case 1: + pc->num_dl_slots = 7; + pc->num_ul_slots = 2; + break; + + case 3: + pc->num_dl_slots = 27; + pc->num_ul_slots = 12; + break; + + default: + break; + } + for (int i = 0; i < pc->num_dl_slots; i++) { + pc->tdd_slot_bitmap[i].slot_type = TDD_NR_DOWNLINK_SLOT; + pc->tdd_slot_bitmap[i].num_dl_symbols = 0; + pc->tdd_slot_bitmap[i].num_ul_symbols = 0; + } + for (int i = pc->num_dl_slots; i < fs.numb_slots_period - pc->num_ul_slots; i++) { + pc->tdd_slot_bitmap[i].slot_type = TDD_NR_MIXED_SLOT; + pc->tdd_slot_bitmap[i].num_dl_symbols = 6; + pc->tdd_slot_bitmap[i].num_ul_symbols = 4; + } + for (int i = pc->num_ul_slots; i < fs.numb_slots_period; i++) { + pc->tdd_slot_bitmap[i].slot_type = TDD_NR_UPLINK_SLOT; + pc->tdd_slot_bitmap[i].num_dl_symbols = 0; + pc->tdd_slot_bitmap[i].num_ul_symbols = 0; + } + set_tdd_config_nr(&gNB->gNB_config, &fs); +} diff --git a/openair1/SCHED_NR/phy_frame_config_nr.h b/openair1/SCHED_NR/phy_frame_config_nr.h index b477b435f1..0caf612f37 100644 --- a/openair1/SCHED_NR/phy_frame_config_nr.h +++ b/openair1/SCHED_NR/phy_frame_config_nr.h @@ -36,18 +36,16 @@ /*************** FUNCTIONS *****************************************/ -/** \brief This function processes tdd dedicated configuration for nr - * @param frame_parms NR DL Frame parameters - * @param dl_UL_TransmissionPeriodicity periodicity - * @param nrofDownlinkSlots number of downlink slots - * @param nrofDownlinkSymbols number of downlink symbols - * @param nrofUplinkSlots number of uplink slots - * @param nrofUplinkSymbols number of uplink symbols - @returns 0 if tdd dedicated configuration has been properly set or -1 on error with message */ - -int set_tdd_config_nr(nfapi_nr_config_request_scf_t *cfg, int mu, - int nrofDownlinkSlots, int nrofDownlinkSymbols, - int nrofUplinkSlots, int nrofUplinkSymbols); +/** @brief This function processes TDD dedicated configuration for NR + * by processing the tdd_slot_bitmap and period_cfg, and + * allocates memory and fills max_num_of_symbol_per_slot_list + * in the nfapi config request (cfg) + * @param cfg NR config request structure pointer + * @param fs frame structure pointer + * @returns nb_periods_per_frame if TDD has been properly configurated + * -1 tdd configuration can not be done + */ +void set_tdd_config_nr(nfapi_nr_config_request_scf_t *cfg, frame_structure_t *fs); /** \brief This function adds a slot configuration to current dedicated configuration for nr * @param frame_parms NR DL Frame parameters @@ -92,5 +90,7 @@ void free_tdd_configuration_dedicated_nr(NR_DL_FRAME_PARMS *frame_parms); int get_next_downlink_slot(PHY_VARS_gNB *gNB, nfapi_nr_config_request_scf_t *cfg, int nr_frame, int nr_slot); +void do_tdd_config_sim(PHY_VARS_gNB *gNB, int mu); + #endif /* PHY_FRAME_CONFIG_NR_H */ diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 9e1ec84d9c..fa41491b54 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -40,6 +40,7 @@ #include "assertions.h" #include #include +#include //#define DEBUG_RXDATA //#define SRS_IND_DEBUG @@ -438,6 +439,7 @@ static int nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, boo ulsch_harq->ulsch_pdu.rb_size, ulsch_harq->TBS); nr_fill_indication(gNB, ulsch->frame, ulsch->slot, ULSCH_id, ulsch->harq_pid, 1, 0, crc, pdu); + gNBdumpScopeData(gNB, ulsch->slot, ulsch->frame, "ULSCH_NACK"); ulsch->handled = 1; LOG_D(PHY, "ULSCH %d in error\n",ULSCH_id); ulsch->last_iteration_cnt = ulsch->max_ldpc_iterations + 1; // Setting to max_ldpc_iterations + 1 is sufficient given that this variable is only used for checking for failure @@ -647,8 +649,9 @@ int fill_srs_channel_matrix(uint8_t *channel_matrix, const uint16_t prg_size, const uint16_t num_prgs, const NR_DL_FRAME_PARMS *frame_parms, - const int32_t srs_estimated_channel_freq[][1<num_ant_ports][frame_parms->ofdm_symbol_size*(1<num_symbols)]) { - + const c16_t srs_estimated_channel_freq[][1 << srs_pdu->num_ant_ports] + [frame_parms->ofdm_symbol_size * (1 << srs_pdu->num_symbols)]) +{ const uint64_t subcarrier_offset = frame_parms->first_carrier_offset + srs_pdu->bwp_start*NR_NB_SC_PER_RB; const uint16_t step = prg_size*NR_NB_SC_PER_RB; @@ -664,8 +667,7 @@ int fill_srs_channel_matrix(uint8_t *channel_matrix, } for(int pI = 0; pI < num_prgs; pI++) { - - c16_t *srs_estimated_channel16 = (c16_t *)&srs_estimated_channel_freq[gI][uI][subcarrier]; + const c16_t *srs_estimated_channel16 = srs_estimated_channel_freq[gI][uI] + subcarrier; uint16_t index = uI*num_gnb_antenna_elements*num_prgs + gI*num_prgs + pI; if (normalized_iq_representation == 0) { @@ -868,6 +870,7 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N nfapi_nr_rx_data_pdu_t *pdu = &UL_INFO->rx_ind.pdu_list[UL_INFO->rx_ind.number_of_pdus++]; nr_fill_indication(gNB, frame_rx, slot_rx, ULSCH_id, ulsch->harq_pid, 1, 1, crc, pdu); pusch_DTX++; + gNBdumpScopeData(gNB, ulsch->slot, ulsch->frame, "ULSCH_DTX"); continue; } } else { @@ -918,10 +921,13 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, N NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; nfapi_nr_srs_pdu_t *srs_pdu = &srs->srs_pdu; uint8_t N_symb_SRS = 1 << srs_pdu->num_symbols; - int32_t srs_received_signal[frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size * N_symb_SRS]; - int32_t srs_estimated_channel_freq[frame_parms->nb_antennas_rx][1 << srs_pdu->num_ant_ports][frame_parms->ofdm_symbol_size * N_symb_SRS] __attribute__((aligned(32))); - int32_t srs_estimated_channel_time[frame_parms->nb_antennas_rx][1 << srs_pdu->num_ant_ports][frame_parms->ofdm_symbol_size] __attribute__((aligned(32))); - int32_t srs_estimated_channel_time_shifted[frame_parms->nb_antennas_rx][1 << srs_pdu->num_ant_ports][frame_parms->ofdm_symbol_size]; + c16_t srs_received_signal[frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size * N_symb_SRS]; + c16_t srs_estimated_channel_freq[frame_parms->nb_antennas_rx][1 << srs_pdu->num_ant_ports] + [frame_parms->ofdm_symbol_size * N_symb_SRS] __attribute__((aligned(32))); + c16_t srs_estimated_channel_time[frame_parms->nb_antennas_rx][1 << srs_pdu->num_ant_ports][frame_parms->ofdm_symbol_size] + __attribute__((aligned(32))); + c16_t srs_estimated_channel_time_shifted[frame_parms->nb_antennas_rx][1 << srs_pdu->num_ant_ports] + [frame_parms->ofdm_symbol_size]; int8_t snr_per_rb[srs_pdu->bwp_size]; start_meas(&gNB->generate_srs_stats); diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index 6dffd4ad8c..fbfc9d8389 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -41,8 +41,7 @@ #include "utils.h" #include "openair2/PHY_INTERFACE/queue_t.h" #include "SCHED_NR_UE/phy_sch_processing_time.h" - -extern PHY_VARS_NR_UE ***PHY_vars_UE_g; +#include "openair1/PHY/phy_extern_nr_ue.h" const char *const dl_pdu_type[] = {"DCI", "DLSCH", "RA_DLSCH", "SI_DLSCH", "P_DLSCH", "CSI_RS", "CSI_IM", "TA"}; const char *const ul_pdu_type[] = {"PRACH", "PUCCH", "PUSCH", "SRS"}; diff --git a/openair1/SIMULATION/NR_PHY/dlschsim.c b/openair1/SIMULATION/NR_PHY/dlschsim.c index 4b3a128211..de5c598015 100644 --- a/openair1/SIMULATION/NR_PHY/dlschsim.c +++ b/openair1/SIMULATION/NR_PHY/dlschsim.c @@ -388,8 +388,9 @@ int main(int argc, char **argv) frame_parms->Ncp = extended_prefix_flag ? EXTENDED : NORMAL; crcTableInit(); nr_phy_config_request_sim(gNB, N_RB_DL, N_RB_DL, mu, Nid_cell,SSB_positions); - gNB->gNB_config.tdd_table.tdd_period.value = 6; - set_tdd_config_nr(&gNB->gNB_config, mu, 7, 6, 2, 4); + // TDD configuration + gNB->gNB_config.tdd_table.tdd_period.value = 6; + do_tdd_config_sim(gNB, mu); phy_init_nr_gNB(gNB); //init_eNB_afterRU(); frame_length_complex_samples = frame_parms->samples_per_subframe; @@ -620,39 +621,6 @@ int main(int argc, char **argv) } } - /*LOG_M("txsigF0.m","txsF0", gNB->common_vars.txdataF[0],frame_length_complex_samples_no_prefix,1,1); - if (gNB->frame_parms.nb_antennas_tx>1) - LOG_M("txsigF1.m","txsF1", gNB->common_vars.txdataF[1],frame_length_complex_samples_no_prefix,1,1);*/ - - //TODO: loop over slots - /*for (aa=0; aaframe_parms.nb_antennas_tx; aa++) { - if (gNB_config->subframe_config.dl_cyclic_prefix_type.value == 1) { - PHY_ofdm_mod(gNB->common_vars.txdataF[aa], - txdata[aa], - frame_parms->ofdm_symbol_size, - 12, - frame_parms->nb_prefix_samples, - CYCLIC_PREFIX); - } else { - nr_normal_prefix_mod(gNB->common_vars.txdataF[aa], - txdata[aa], - 14, - frame_parms); - } - } - - LOG_M("txsig0.m","txs0", txdata[0],frame_length_complex_samples,1,1); - if (gNB->frame_parms.nb_antennas_tx>1) - LOG_M("txsig1.m","txs1", txdata[1],frame_length_complex_samples,1,1); - - - for (i=0; inb_antennas_tx; aa++) { - r_re[aa][i] = ((double)(((short *)txdata[aa]))[(i<<1)]); - r_im[aa][i] = ((double)(((short *)txdata[aa]))[(i<<1)+1]); - } - }*/ - free_channel_desc_scm(gNB2UE); reset_DLSCH_struct(gNB, &msgDataTx); diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 236913d3f8..fc09f23bd6 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -189,7 +189,7 @@ void nr_dlsim_preprocessor(module_id_t module_id, /* the following might override the table that is mandated by RRC * configuration */ current_BWP->mcsTableIdx = g_mcsTableIdx; - sched_pdsch->time_domain_allocation = get_dl_tda(RC.nrmac[module_id], scc, slot); + sched_pdsch->time_domain_allocation = get_dl_tda(RC.nrmac[module_id], slot); AssertFatal(sched_pdsch->time_domain_allocation >= 0,"Unable to find PDSCH time domain allocation in list\n"); sched_pdsch->tda_info = get_dl_tda_info(current_BWP, diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c index b77b4ad786..b8ebf2bb30 100644 --- a/openair1/SIMULATION/NR_PHY/pbchsim.c +++ b/openair1/SIMULATION/NR_PHY/pbchsim.c @@ -448,13 +448,10 @@ int main(int argc, char **argv) frame_parms->freq_range = mu<2 ? FR1 : FR2; nr_phy_config_request_sim(gNB, N_RB_DL, N_RB_DL, mu, Nid_cell, SSB_positions); + // TDD configuration gNB->gNB_config.tdd_table.tdd_period.value = 6; - if (mu == 0) - set_tdd_config_nr(&gNB->gNB_config, mu, 3, 6, 1, 4); - else if (mu == 1) - set_tdd_config_nr(&gNB->gNB_config, mu, 7, 6, 2, 4); - else if (mu == 3) - set_tdd_config_nr(&gNB->gNB_config, mu, 27, 6, 12, 4); + do_tdd_config_sim(gNB, mu); + phy_init_nr_gNB(gNB); frame_parms->ssb_start_subcarrier = 12 * gNB->gNB_config.ssb_table.ssb_offset_point_a.value + ssb_subcarrier_offset; initFloatingCoresTpool(ssb_scan_threads, &nrUE_params.Tpool, false, "UE-tpool"); diff --git a/openair1/SIMULATION/NR_PHY/prachsim.c b/openair1/SIMULATION/NR_PHY/prachsim.c index db3631276c..fd2c1bcf77 100644 --- a/openair1/SIMULATION/NR_PHY/prachsim.c +++ b/openair1/SIMULATION/NR_PHY/prachsim.c @@ -568,7 +568,10 @@ int main(int argc, char **argv){ memcpy((void*)&ru->config,(void*)&RC.gNB[0]->gNB_config,sizeof(ru->config)); RC.nb_nr_L1_inst=1; - set_tdd_config_nr(&gNB->gNB_config, mu, 7, 6, 2, 4); + // TDD configuration + gNB->gNB_config.tdd_table.tdd_period.value = 6; + do_tdd_config_sim(gNB, mu); + phy_init_nr_gNB(gNB); nr_phy_init_RU(ru); @@ -678,16 +681,16 @@ int main(int argc, char **argv){ for (i = 0; i < frame_parms->samples_per_subframe; i++) { for (aa=0; aa<1; aa++) { if (awgn_flag == 0) { - s_re[aa][i] = ((double)(((short *)&txdata[aa][prach_start]))[(i<<1)]); - s_im[aa][i] = ((double)(((short *)&txdata[aa][prach_start]))[(i<<1)+1]); + s_re[aa][i] = txdata[aa][prach_start + i].r; + s_im[aa][i] = txdata[aa][prach_start + i].i; } else { for (aarx=0; aarxframe_parms.nb_antennas_rx; aarx++) { if (aa==0) { - r_re[aarx][i] = ((double)(((short *)&txdata[aa][prach_start]))[(i<<1)]); - r_im[aarx][i] = ((double)(((short *)&txdata[aa][prach_start]))[(i<<1)+1]); + r_re[aa][i] = txdata[aa][prach_start + i].r; + r_im[aa][i] = txdata[aa][prach_start + i].i; } else { - r_re[aarx][i] += ((double)(((short *)&txdata[aa][prach_start]))[(i<<1)]); - r_im[aarx][i] += ((double)(((short *)&txdata[aa][prach_start]))[(i<<1)+1]); + r_re[aa][i] += txdata[aa][prach_start + i].r; + r_im[aa][i] += txdata[aa][prach_start + i].i; } } } diff --git a/openair1/SIMULATION/NR_PHY/psbchsim.c b/openair1/SIMULATION/NR_PHY/psbchsim.c index 972605fc96..d1f7993346 100644 --- a/openair1/SIMULATION/NR_PHY/psbchsim.c +++ b/openair1/SIMULATION/NR_PHY/psbchsim.c @@ -260,15 +260,8 @@ static int freq_domain_loopback(PHY_VARS_NR_UE *UE_tx, PHY_VARS_NR_UE *UE_rx, in nr_tx_psbch(UE_tx, frame, slot, &phy_data->psbch_vars, txdataF); int estimateSz = sl_ue2->sl_frame_params.samples_per_slot_wCP; - __attribute__((aligned(32))) struct complex16 rxdataF[1][estimateSz]; - for (int i = 0; i < sl_ue1->sl_frame_params.samples_per_slot_wCP; i++) { - struct complex16 *txdataF_ptr = (struct complex16 *)&txdataF[0][i]; - struct complex16 *rxdataF_ptr = (struct complex16 *)&rxdataF[0][i]; - rxdataF_ptr->r = txdataF_ptr->r; - rxdataF_ptr->i = txdataF_ptr->i; - // printf("r,i TXDATAF[%d]- %d:%d, RXDATAF[%d]- %d:%d\n", - // i, txdataF_ptr->r, txdataF_ptr->i, i, txdataF_ptr->r, txdataF_ptr->i); - } + __attribute__((aligned(32))) c16_t rxdataF[1][estimateSz]; + memcpy(rxdataF[0], txdataF[0], sl_ue1->sl_frame_params.samples_per_slot_wCP * sizeof(**rxdataF)); uint8_t err_status = 0; diff --git a/openair1/SIMULATION/NR_PHY/pucchsim.c b/openair1/SIMULATION/NR_PHY/pucchsim.c index 62aa21f5f7..bc022d5bc1 100644 --- a/openair1/SIMULATION/NR_PHY/pucchsim.c +++ b/openair1/SIMULATION/NR_PHY/pucchsim.c @@ -433,8 +433,10 @@ int main(int argc, char **argv) cfg->carrier_config.num_tx_ant.value = n_tx; cfg->carrier_config.num_rx_ant.value = n_rx; nr_phy_config_request_sim(gNB,N_RB_DL,N_RB_DL,mu,Nid_cell,SSB_positions); + // TDD configuration gNB->gNB_config.tdd_table.tdd_period.value = 6; - set_tdd_config_nr(&gNB->gNB_config, mu, 7, 6, 2, 4); + do_tdd_config_sim(gNB, mu); + phy_init_nr_gNB(gNB); /* RU handles rxdataF, and gNB just has a pointer. Here, we don't have an RU, * so we need to allocate that memory as well. */ diff --git a/openair1/SIMULATION/NR_PHY/ulschsim.c b/openair1/SIMULATION/NR_PHY/ulschsim.c index 19f48c5d3c..fcc986e92c 100644 --- a/openair1/SIMULATION/NR_PHY/ulschsim.c +++ b/openair1/SIMULATION/NR_PHY/ulschsim.c @@ -406,8 +406,10 @@ int main(int argc, char **argv) gNB->frame_parms.nb_antennas_rx = n_rx; nr_phy_config_request_sim(gNB, N_RB_UL, N_RB_UL, mu, Nid_cell, SSB_positions); + // TDD configuration gNB->gNB_config.tdd_table.tdd_period.value = 6; - set_tdd_config_nr(&gNB->gNB_config, mu, 7, 6, 2, 4); + do_tdd_config_sim(gNB, mu); + phy_init_nr_gNB(gNB); //configure UE diff --git a/openair2/COMMON/as_message.h b/openair2/COMMON/as_message.h index cdf6792151..5a29d6881b 100644 --- a/openair2/COMMON/as_message.h +++ b/openair2/COMMON/as_message.h @@ -166,7 +166,7 @@ typedef struct as_stmsi_s { /* Dedicated NAS information */ typedef struct as_nas_info_s { uint32_t length; /* Length of the NAS information data */ - Byte_t* nas_data; /* Dedicated NAS information data container */ + uint8_t* nas_data; /* Dedicated NAS information data container */ } as_nas_info_t; /* Radio Access Bearer identity */ @@ -215,7 +215,7 @@ typedef struct broadcast_info_ind_s { * NAS request AS to refresh its KeNB key */ typedef struct kenb_refresh_req_s { - Byte_t kenb[32]; + uint8_t kenb[32]; } kenb_refresh_req_t; typedef struct nsa_oai_tun_nsa_s { @@ -229,7 +229,7 @@ typedef struct nsa_oai_tun_nsa_s { */ typedef struct cell_info_req_s { plmn_t plmnID; /* Selected PLMN identity */ - Byte_t rat; /* Bitmap - set of radio access technologies */ + uint8_t rat; /* Bitmap - set of radio access technologies */ } cell_info_req_t; /* diff --git a/openair2/COMMON/commonDef.h b/openair2/COMMON/commonDef.h index f5a24494a7..cff6b011fc 100644 --- a/openair2/COMMON/commonDef.h +++ b/openair2/COMMON/commonDef.h @@ -43,7 +43,6 @@ Description Contains global common definitions #include #include #include "common/platform_constants.h" -typedef uint8_t Byte_t; /* 8 bit unsigned integer */ /* ----------------------------------------------------------------------------- @@ -62,30 +61,30 @@ typedef uint8_t AcT_t; /* Access Technology */ * International Mobile Subscriber Identity */ typedef struct { - Byte_t length; + uint8_t length; union { struct { - Byte_t digit2:4; - Byte_t digit1:4; - Byte_t digit4:4; - Byte_t digit3:4; - Byte_t digit6:4; - Byte_t digit5:4; - Byte_t digit8:4; - Byte_t digit7:4; - Byte_t digit10:4; - Byte_t digit9:4; - Byte_t digit12:4; - Byte_t digit11:4; - Byte_t digit14:4; - Byte_t digit13:4; + uint8_t digit2: 4; + uint8_t digit1: 4; + uint8_t digit4: 4; + uint8_t digit3: 4; + uint8_t digit6: 4; + uint8_t digit5: 4; + uint8_t digit8: 4; + uint8_t digit7: 4; + uint8_t digit10: 4; + uint8_t digit9: 4; + uint8_t digit12: 4; + uint8_t digit11: 4; + uint8_t digit14: 4; + uint8_t digit13: 4; #define EVEN_PARITY 0 #define ODD_PARITY 1 - Byte_t parity:4; - Byte_t digit15:4; + uint8_t parity: 4; + uint8_t digit15: 4; } num; #define IMSI_SIZE 8 - Byte_t value[IMSI_SIZE]; + uint8_t value[IMSI_SIZE]; } u; } imsi_t; @@ -119,7 +118,7 @@ typedef struct { * Mobile subscriber dialing number */ typedef struct { - Byte_t ext:1; + uint8_t ext: 1; /* Type Of Number */ #define MSISDN_TON_UNKNOWKN 0b000 #define MSISDN_TON_INTERNATIONAL 0b001 @@ -128,7 +127,7 @@ typedef struct { #define MSISDN_TON_SUBCRIBER 0b100 #define MSISDN_TON_ABBREVIATED 0b110 #define MSISDN_TON_RESERVED 0b111 - Byte_t ton:3; + uint8_t ton: 3; /* Numbering Plan Identification */ #define MSISDN_NPI_UNKNOWN 0b0000 #define MSISDN_NPI_ISDN_TELEPHONY 0b0001 @@ -140,11 +139,11 @@ typedef struct { #define MSISDN_NPI_ISDN_MOBILE 0b0111 #define MSISDN_NPI_PRIVATE 0b1110 #define MSISDN_NPI_RESERVED 0b1111 - Byte_t npi:4; + uint8_t npi: 4; /* Dialing Number */ struct { - Byte_t lsb:4; - Byte_t msb:4; + uint8_t lsb: 4; + uint8_t msb: 4; #define MSISDN_DIGIT_SIZE 10 } digit[MSISDN_DIGIT_SIZE]; } msisdn_t; @@ -159,12 +158,12 @@ typedef imsi_t imei_t; * PLMN = BCD encoding (Mobile Country Code + Mobile Network Code) */ typedef struct { - Byte_t MCCdigit2:4; - Byte_t MCCdigit1:4; - Byte_t MNCdigit3:4; - Byte_t MCCdigit3:4; - Byte_t MNCdigit2:4; - Byte_t MNCdigit1:4; + uint8_t MCCdigit2: 4; + uint8_t MCCdigit1: 4; + uint8_t MNCdigit3: 4; + uint8_t MCCdigit3: 4; + uint8_t MNCdigit2: 4; + uint8_t MNCdigit1: 4; } plmn_t; /* @@ -256,17 +255,29 @@ typedef struct { /* * A list of PLMNs */ -#define PLMN_LIST_T(SIZE) struct {Byte_t n_plmns; plmn_t plmn[SIZE];} +#define PLMN_LIST_T(SIZE) \ + struct { \ + uint8_t n_plmns; \ + plmn_t plmn[SIZE]; \ + } /* * A list of TACs */ -#define TAC_LIST_T(SIZE) struct {Byte_t n_tacs; TAC_t tac[SIZE];} +#define TAC_LIST_T(SIZE) \ + struct { \ + uint8_t n_tacs; \ + TAC_t tac[SIZE]; \ + } /* * A list of TAIs */ -#define TAI_LIST_T(SIZE) struct {Byte_t n_tais; tai_t tai[SIZE];} +#define TAI_LIST_T(SIZE) \ + struct { \ + uint8_t n_tais; \ + tai_t tai[SIZE]; \ + } typedef enum eps_protocol_discriminator_e { /* Protocol discriminator identifier for EPS Mobility Management */ diff --git a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.c b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.c index 3e3caac9fe..854ef57d15 100644 --- a/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.c +++ b/openair2/E2AP/RAN_FUNCTION/CUSTOMIZED/ran_func_mac.c @@ -60,11 +60,11 @@ bool read_mac_sm(void* data) rd->dl_aggr_tbs = UE->mac_stats.dl.total_bytes; rd->ul_aggr_tbs = UE->mac_stats.ul.total_bytes; - if (is_xlsch_in_slot(RC.nrmac[mod_id]->dlsch_slot_bitmap[rd->slot / 64], rd->slot)) { + if (is_dl_slot(rd->slot, &RC.nrmac[mod_id]->frame_structure)) { rd->dl_curr_tbs = UE->mac_stats.dl.current_bytes; rd->dl_sched_rb = UE->mac_stats.dl.current_rbs; } - if (is_xlsch_in_slot(RC.nrmac[mod_id]->ulsch_slot_bitmap[rd->slot / 64], rd->slot)) { + if (is_ul_slot(rd->slot, &RC.nrmac[mod_id]->frame_structure)) { rd->ul_curr_tbs = UE->mac_stats.ul.current_bytes; rd->ul_sched_rb = sched_ctrl->sched_pusch.rbSize; } diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c index 6daae2907d..f166135fed 100644 --- a/openair2/ENB_APP/enb_config.c +++ b/openair2/ENB_APP/enb_config.c @@ -59,11 +59,6 @@ #include "executables/thread-common.h" #include -extern uint32_t to_earfcn_DL(int eutra_bandP, uint32_t dl_CarrierFreq, uint32_t bw); -extern uint32_t to_earfcn_UL(int eutra_bandP, uint32_t ul_CarrierFreq, uint32_t bw); -extern char *parallel_config; -extern char *worker_config; - RAN_CONTEXT_t RC; void RCconfig_L1(void) { diff --git a/openair2/GNB_APP/RRC_nr_paramsvalues.h b/openair2/GNB_APP/RRC_nr_paramsvalues.h index 5b77da80b4..be2fd03542 100644 --- a/openair2/GNB_APP/RRC_nr_paramsvalues.h +++ b/openair2/GNB_APP/RRC_nr_paramsvalues.h @@ -116,6 +116,7 @@ #define GNB_CONFIG_STRING_NROFDOWNLINKSYMBOLS "nrofDownlinkSymbols" #define GNB_CONFIG_STRING_NROFUPLINKSLOTS "nrofUplinkSlots" #define GNB_CONFIG_STRING_NROFUPLINKSYMBOLS "nrofUplinkSymbols" +#define GNB_CONFIG_STRING_PATTERN2 "pattern2" #define GNB_CONFIG_STRING_DLULTRANSMISSIONPERIODICITY2 "dl_UL_TransmissionPeriodicity2" #define GNB_CONFIG_STRING_NROFDOWNLINKSLOTS2 "nrofDownlinkSlots2" #define GNB_CONFIG_STRING_NROFDOWNLINKSYMBOLS2 "nrofDownlinkSymbols2" @@ -247,11 +248,6 @@ {GNB_CONFIG_STRING_NROFDOWNLINKSYMBOLS,NULL,0,.i64ptr=&scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols,.defint64val=6,TYPE_INT64,0},\ {GNB_CONFIG_STRING_NROFUPLINKSLOTS,NULL,0,.i64ptr=&scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots,.defint64val=2,TYPE_INT64,0},\ {GNB_CONFIG_STRING_NROFUPLINKSYMBOLS,NULL,0,.i64ptr=&scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols,.defint64val=4,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_DLULTRANSMISSIONPERIODICITY2,NULL,0,.i64ptr=&scc->tdd_UL_DL_ConfigurationCommon->pattern2->dl_UL_TransmissionPeriodicity,.defintval=-1,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_NROFDOWNLINKSLOTS2,NULL,0,.i64ptr=&scc->tdd_UL_DL_ConfigurationCommon->pattern2->nrofDownlinkSlots,.defint64val=-1,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_NROFDOWNLINKSYMBOLS2,NULL,0,.i64ptr=&scc->tdd_UL_DL_ConfigurationCommon->pattern2->nrofDownlinkSymbols,.defint64val=-1,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_NROFUPLINKSLOTS2,NULL,0,.i64ptr=&scc->tdd_UL_DL_ConfigurationCommon->pattern2->nrofUplinkSlots,.defint64val=-1,TYPE_INT64,0},\ -{GNB_CONFIG_STRING_NROFUPLINKSYMBOLS2,NULL,0,.i64ptr=&scc->tdd_UL_DL_ConfigurationCommon->pattern2->nrofUplinkSymbols,.defint64val=-1,TYPE_INT64,0},\ {GNB_CONFIG_STRING_SSPBCHBLOCKPOWER,NULL,0,.i64ptr=&scc->ss_PBCH_BlockPower,.defint64val=20,TYPE_INT64,0}, \ {GNB_CONFIG_STRING_CELLSPECIFICKOFFSET,NULL,0,.i64ptr=scc->ext2->ntn_Config_r17->cellSpecificKoffset_r17,.defint64val=0,TYPE_INT64,0}, \ {GNB_CONFIG_STRING_EPHEMERIS_POSITION_X,NULL,0,.i64ptr=&scc->ext2->ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17->positionX_r17,.defint64val=LONG_MAX,TYPE_INT64,0}, \ @@ -263,6 +259,15 @@ {GNB_CONFIG_STRING_TA_COMMON,NULL,0,.i64ptr=&scc->ext2->ntn_Config_r17->ta_Info_r17->ta_Common_r17,.defint64val=-1,TYPE_INT64,0}, \ {GNB_CONFIG_STRING_MSG1SUBCARRIERSPACING,NULL,0,.i64ptr=scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing,.defintval=-1,TYPE_INT64,0}} +#define SCC_PATTERN2_STRING_CONFIG "pattern2" + +#define SCC_PATTERN2_PARAMS_DESC(pattern2) { \ +{GNB_CONFIG_STRING_DLULTRANSMISSIONPERIODICITY2, NULL,0,.i64ptr=&pattern2.dl_UL_TransmissionPeriodicity,.defint64val=-1,TYPE_INT64,0},\ +{GNB_CONFIG_STRING_NROFDOWNLINKSLOTS2, NULL,0,.i64ptr=&pattern2.nrofDownlinkSlots,.defint64val=-1,TYPE_INT64,0},\ +{GNB_CONFIG_STRING_NROFDOWNLINKSYMBOLS2, NULL,0,.i64ptr=&pattern2.nrofDownlinkSymbols,.defint64val=-1,TYPE_INT64,0},\ +{GNB_CONFIG_STRING_NROFUPLINKSLOTS2,NULL, 0,.i64ptr=&pattern2.nrofUplinkSlots,.defint64val=-1,TYPE_INT64,0},\ +{GNB_CONFIG_STRING_NROFUPLINKSYMBOLS2,NULL, 0,.i64ptr=&pattern2.nrofUplinkSymbols,.defint64val=-1,TYPE_INT64,0}} + /*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ /* Serving Cell Config Dedicated configuration parameters */ /*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 39c8014adc..a57d2e0287 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -113,7 +113,10 @@ void prepare_scc(NR_ServingCellConfigCommon_t *scc) scc->ssb_periodicityServingCell = calloc_or_fail(1, sizeof(*scc->ssb_periodicityServingCell)); scc->ssbSubcarrierSpacing = calloc_or_fail(1, sizeof(*scc->ssbSubcarrierSpacing)); scc->tdd_UL_DL_ConfigurationCommon = calloc_or_fail(1, sizeof(*scc->tdd_UL_DL_ConfigurationCommon)); - scc->tdd_UL_DL_ConfigurationCommon->pattern2 = calloc_or_fail(1, sizeof(*scc->tdd_UL_DL_ConfigurationCommon->pattern2)); + struct NR_TDD_UL_DL_ConfigCommon *tdd = scc->tdd_UL_DL_ConfigurationCommon; + tdd->pattern1.ext1 = calloc_or_fail(1, sizeof(*tdd->pattern1.ext1)); + tdd->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530 = + calloc_or_fail(1, sizeof(*tdd->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530)); scc->downlinkConfigCommon = calloc_or_fail(1, sizeof(*scc->downlinkConfigCommon)); scc->downlinkConfigCommon->frequencyInfoDL = calloc_or_fail(1, sizeof(*scc->downlinkConfigCommon->frequencyInfoDL)); scc->downlinkConfigCommon->initialDownlinkBWP = calloc_or_fail(1, sizeof(*scc->downlinkConfigCommon->initialDownlinkBWP)); @@ -357,15 +360,52 @@ void fill_scc_sim(NR_ServingCellConfigCommon_t *scc, uint64_t *ssb_bitmap, int N p1->nrofUplinkSymbols = 4; struct NR_TDD_UL_DL_Pattern *p2 = tdd_UL_DL_ConfigurationCommon->pattern2; - p2->dl_UL_TransmissionPeriodicity = 321; - p2->nrofDownlinkSlots = -1; - p2->nrofDownlinkSymbols = -1; - p2->nrofUplinkSlots = -1; - p2->nrofUplinkSymbols = -1; + if (p2) { + p2->dl_UL_TransmissionPeriodicity = 321; + p2->nrofDownlinkSlots = -1; + p2->nrofDownlinkSymbols = -1; + p2->nrofUplinkSlots = -1; + p2->nrofUplinkSymbols = -1; + } scc->ss_PBCH_BlockPower = 20; } +static void fix_tdd_pattern(NR_ServingCellConfigCommon_t *scc) +{ + NR_TDD_UL_DL_Pattern_t *pattern1 = &scc->tdd_UL_DL_ConfigurationCommon->pattern1; + int pattern_ext = pattern1->dl_UL_TransmissionPeriodicity - 8; + // Check if the pattern1 extension is configured and set the value accordingly + if (pattern_ext >= 0) { + pattern1->ext1 = calloc_or_fail(1, sizeof(struct NR_TDD_UL_DL_Pattern__ext1)); + pattern1->ext1->dl_UL_TransmissionPeriodicity_v1530 = + calloc_or_fail(1, sizeof(*pattern1->ext1->dl_UL_TransmissionPeriodicity_v1530)); + *pattern1->ext1->dl_UL_TransmissionPeriodicity_v1530 = pattern_ext; + pattern1->dl_UL_TransmissionPeriodicity = 5; + } else { + pattern1->ext1 = NULL; + } + struct NR_TDD_UL_DL_Pattern *pattern2 = scc->tdd_UL_DL_ConfigurationCommon->pattern2; + if (pattern2 != NULL) { + /* The pattern2 is not configured free the memory these shall not be encoded with default values in SIB1 */ + if (pattern2->dl_UL_TransmissionPeriodicity == -1) { + free(pattern2); + pattern2 = NULL; + } else { + // Check if the pattern2 extension is configured and set the value accordingly + pattern_ext = pattern2->dl_UL_TransmissionPeriodicity - 8; + if (pattern_ext >= 0) { + pattern2->ext1 = calloc_or_fail(1, sizeof(*pattern2->ext1)); + pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530 = + CALLOC(1, sizeof(*pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530)); + *pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530 = pattern_ext; + pattern2->dl_UL_TransmissionPeriodicity = 5; + } else { + pattern2->ext1 = NULL; + } + } + } +} void fix_scc(NR_ServingCellConfigCommon_t *scc, uint64_t ssbmap) { @@ -436,11 +476,7 @@ void fix_scc(NR_ServingCellConfigCommon_t *scc, uint64_t ssbmap) ASN_STRUCT_FREE(asn_DEF_NR_TDD_UL_DL_ConfigCommon, scc->tdd_UL_DL_ConfigurationCommon); scc->tdd_UL_DL_ConfigurationCommon = NULL; } else { // TDD - if (scc->tdd_UL_DL_ConfigurationCommon->pattern2->dl_UL_TransmissionPeriodicity > 320 ) { - free(scc->tdd_UL_DL_ConfigurationCommon->pattern2); - scc->tdd_UL_DL_ConfigurationCommon->pattern2 = NULL; - } - + fix_tdd_pattern(scc); } if ((int)*scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing == -1) { @@ -982,6 +1018,16 @@ void RCconfig_NR_L1(void) } } +/** + * @brief Returns true when pattern2 is filled in + */ +bool is_pattern2_config(paramdef_t *param) +{ + if (param == NULL || param->i64ptr == NULL || *(param->i64ptr) == -1) + return false; + return true; +} + static NR_ServingCellConfigCommon_t *get_scc_config(configmodule_interface_t *cfg, int minRXTXTIME) { NR_ServingCellConfigCommon_t *scc = calloc_or_fail(1, sizeof(*scc)); @@ -1002,6 +1048,33 @@ static NR_ServingCellConfigCommon_t *get_scc_config(configmodule_interface_t *cf sprintf(aprefix, "%s.[%i].%s.[%i]", GNB_CONFIG_STRING_GNB_LIST,0,GNB_CONFIG_STRING_SERVINGCELLCONFIGCOMMON, 0); config_get(cfg, SCCsParams, sizeofArray(SCCsParams), aprefix); config_get(cfg, MsgASCCsParams, sizeofArray(MsgASCCsParams), aprefix); + // NR_TDD-UL-DL-ConfigCommon pattern2 (optional IE) + // fetch params + struct NR_TDD_UL_DL_Pattern p2; + paramdef_t pattern2Params[] = SCC_PATTERN2_PARAMS_DESC(p2); + char aprefix[MAX_OPTNAME_SIZE * 2 + 8]; + sprintf(aprefix, "%s.[%i].%s.[%i].%s", GNB_CONFIG_STRING_GNB_LIST, 0, GNB_CONFIG_STRING_SERVINGCELLCONFIGCOMMON, 0, SCC_PATTERN2_STRING_CONFIG); + config_get(config_get_if(), pattern2Params, sizeofArray(pattern2Params), aprefix); + // check validity + bool is_pattern2 = false; + for (int i = 0; i < sizeofArray(pattern2Params); i++) { + is_pattern2 |= is_pattern2_config(pattern2Params); + } + + if (is_pattern2) { + LOG_I(GNB_APP, "tdd->pattern2 present\n"); + // allocate memory + struct NR_TDD_UL_DL_ConfigCommon *tdd = scc->tdd_UL_DL_ConfigurationCommon; + tdd->pattern2 = calloc_or_fail(1, sizeof(*tdd->pattern2)); + tdd->pattern2->ext1 = calloc_or_fail(1, sizeof(struct NR_TDD_UL_DL_Pattern__ext1)); + tdd->pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530 = calloc_or_fail(1, sizeof(*tdd->pattern2->ext1->dl_UL_TransmissionPeriodicity_v1530)); + // fill in scc + *scc->tdd_UL_DL_ConfigurationCommon->pattern2 = p2; + AssertFatal(p2.nrofUplinkSlots ^ scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots, + "UL slots in pattern1 (%ld) and pattern2 (%ld) are mutually exclusive (e.g. DDDFUU DDDD, DDDD DDDFUU)\n", + scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots, + p2.nrofUplinkSlots); + } struct NR_FrequencyInfoDL *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL; LOG_I(RRC, "Read in ServingCellConfigCommon (PhysCellId %d, ABSFREQSSB %d, DLBand %d, ABSFREQPOINTA %d, DLBW " diff --git a/openair2/LAYER2/MAC/mac_proto.h b/openair2/LAYER2/MAC/mac_proto.h index 1a8a1f98bc..bf060eb820 100644 --- a/openair2/LAYER2/MAC/mac_proto.h +++ b/openair2/LAYER2/MAC/mac_proto.h @@ -1235,10 +1235,12 @@ void eNB_Config_Local_DRX(instance_t module_idP, rrc_mac_drx_config_req_t *rrc_m /* from here: prototypes to get rid of compilation warnings: doc to be written by function author */ uint8_t ul_subframe2_k_phich(COMMON_channels_t *cc, sub_frame_t ul_subframe); -#endif /** @}*/ /* MAC ITTI messaging related functions */ /* Main loop of MAC itti message handling */ void *mac_enb_task(void *arg); +uint32_t to_earfcn_DL(int eutra_bandP, long long int dl_CarrierFreq, uint32_t bw); +uint32_t to_earfcn_UL(int eutra_bandP, long long int ul_CarrierFreq, uint32_t bw); +#endif diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 762cad5106..c7ceeeab8e 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -60,8 +60,6 @@ // #define DEBUG_MIB // #define ENABLE_MAC_PAYLOAD_DEBUG 1 // #define DEBUG_RAR -extern uint32_t N_RB_DL; - /* TS 36.213 Table 9.2.3-3: Mapping of values for one HARQ-ACK bit to sequences */ static const int sequence_cyclic_shift_1_harq_ack_bit[2] /* HARQ-ACK Value 0 1 */ diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index 4927f407d0..fda1dc6c11 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -62,10 +62,6 @@ #include "nfapi_nr_interface_scf.h" #include "utils.h" -extern RAN_CONTEXT_t RC; -//extern int l2_init_gNB(void); -extern uint8_t nfapi_mode; - c16_t convert_precoder_weight(double complex c_in) { double cr = creal(c_in) * 32768 + 0.5; @@ -283,6 +279,257 @@ nfapi_nr_pm_list_t init_DL_MIMO_codebook(gNB_MAC_INST *gNB, nr_pdsch_AntennaPort return mat; } +/** + * @brief Configures the TDD period, including bitmap, in the frame structure + * + * This function sets the TDD period configuration for DL, UL, and mixed slots in + * the specified frame structure instance, according to the given pattern, and + * updates the bitmap. + * + * @param pattern NR_TDD_UL_DL_Pattern_t configuration containing TDD slots and symbols configuration + * @param fs frame_structure_t pointer + * @param curr_total_slot current position in the slot bitmap to start from + * + * @return Number of slots in the configured TDD period + */ +static uint8_t set_tdd_bmap_period(NR_TDD_UL_DL_Pattern_t *pattern, tdd_period_config_t *pc, int8_t curr_total_slot) +{ + int8_t n_dl_slot = pattern->nrofDownlinkSlots; + int8_t n_ul_slot = pattern->nrofUplinkSlots; + int8_t n_dl_symbols = pattern->nrofDownlinkSymbols; + int8_t n_ul_symbols = pattern->nrofUplinkSymbols; + + // Total slots in the period: if DL/UL symbols are present, is mixed slot + const bool has_mixed_slot = (n_ul_symbols + n_dl_symbols) > 0; + int8_t total_slot = has_mixed_slot ? n_dl_slot + n_ul_slot + 1 : n_dl_slot + n_ul_slot; + + /** Update TDD period configuration: + * mixed slots with DL symbols are counted as DL slots + * mixed slots with UL symbols are counted as UL slots */ + pc->num_dl_slots += (n_dl_slot + (n_dl_symbols > 0)); + pc->num_ul_slots += (n_ul_slot + (n_ul_symbols > 0)); + + // Populate the slot bitmap for each slot in the TDD period + for (int i = 0; i < total_slot; i++) { + tdd_bitmap_t *bitmap = &pc->tdd_slot_bitmap[i + curr_total_slot]; + if (i < n_dl_slot) + bitmap->slot_type = TDD_NR_DOWNLINK_SLOT; + else if ((i == n_dl_slot) && has_mixed_slot) { + bitmap->slot_type = TDD_NR_MIXED_SLOT; + bitmap->num_dl_symbols = n_dl_symbols; + bitmap->num_ul_symbols = n_ul_symbols; + } else if (n_ul_slot) + bitmap->slot_type = TDD_NR_UPLINK_SLOT; + } + + LOG_I(NR_MAC, + "Set TDD configuration period to: %d DL slots, %d UL slots, %d slots per period (NR_TDD_UL_DL_Pattern is %d DL slots, %d " + "UL slots, %d DL symbols, %d UL symbols)\n", + pc->num_dl_slots, + pc->num_ul_slots, + total_slot, + n_dl_slot, + n_ul_slot, + n_dl_symbols, + n_ul_symbols); + + return total_slot; +} + +/** + * @brief Configures TDD patterns (1 or 2) in the frame structure + * + * This function sets up the TDD configuration in the frame structure by applying + * DL and UL patterns as defined in NR_TDD_UL_DL_ConfigCommon. + * It handles both TDD pattern1 and pattern2. + * + * @param tdd NR_TDD_UL_DL_ConfigCommon_t pointer containing pattern1 and pattern2 + * @param fs Pointer to the frame structure to update with the configured TDD patterns. + * + * @return void + */ +static void config_tdd_patterns(NR_TDD_UL_DL_ConfigCommon_t *tdd, frame_structure_t *fs) +{ + int num_of_patterns = 1; + uint8_t nb_slots_p2 = 0; + // Reset num dl/ul slots + tdd_period_config_t *pc = &fs->period_cfg; + pc->num_dl_slots = 0; + pc->num_ul_slots = 0; + // Pattern1 + uint8_t nb_slots_p1 = set_tdd_bmap_period(&tdd->pattern1, pc, 0); + // Pattern2 + if (tdd->pattern2) { + num_of_patterns++; + nb_slots_p2 = set_tdd_bmap_period(tdd->pattern2, pc, nb_slots_p1); + } + LOG_I(NR_MAC, + "Configured %d TDD patterns (total slots: pattern1 = %d, pattern2 = %d)\n", + num_of_patterns, + nb_slots_p1, + nb_slots_p2); +} + +/** + * @brief Get the first UL slot index in period + * @param fs frame structure + * @param mixed indicates whether to include in the count also mixed slot with UL symbols or only full UL slot + * @return slot index + */ +int get_first_ul_slot(const frame_structure_t *fs, bool mixed) +{ + DevAssert(fs); + + if (fs->is_tdd) { + for (int i = 0; i < fs->numb_slots_period; i++) { + if ((mixed && is_ul_slot(i, fs)) || fs->period_cfg.tdd_slot_bitmap[i].slot_type == TDD_NR_UPLINK_SLOT) { + return i; + } + } + } + + return 0; // FDD +} + +/** + * @brief Get number of DL slots per period (full DL slots + mixed slots with DL symbols) + */ +int get_dl_slots_per_period(const frame_structure_t *fs) +{ + return fs->is_tdd ? fs->period_cfg.num_dl_slots : fs->numb_slots_frame; +} + +/** + * @brief Get number of UL slots per period (full UL slots + mixed slots with UL symbols) + */ +int get_ul_slots_per_period(const frame_structure_t *fs) +{ + return fs->is_tdd ? fs->period_cfg.num_ul_slots : fs->numb_slots_frame; +} + +/** + * @brief Get number of full UL slots per period + * @param fs Pointer to the frame structure + * @return Number of full UL slots + */ +int get_full_ul_slots_per_period(const frame_structure_t *fs) +{ + DevAssert(fs); + + if (!fs->is_tdd) + return fs->numb_slots_frame; + + int count = 0; + + for (int i = 0; i < fs->numb_slots_period; i++) + if (fs->period_cfg.tdd_slot_bitmap[i].slot_type == TDD_NR_UPLINK_SLOT) + count++; + + LOG_D(NR_MAC, "Full UL slots in TDD period: %d\n", count); + return count; +} + +/** + * @brief Get number of full DL slots per period + * @param fs Pointer to the frame structure + * @return Number of full DL slots + */ +int get_full_dl_slots_per_period(const frame_structure_t *fs) +{ + DevAssert(fs); + + if (!fs->is_tdd) + return fs->numb_slots_frame; + + int count = 0; + + for (int i = 0; i < fs->numb_slots_period; i++) + if (fs->period_cfg.tdd_slot_bitmap[i].slot_type == TDD_NR_DOWNLINK_SLOT) + count++; + + LOG_D(NR_MAC, "Full DL slots in TDD period: %d\n", count); + return count; +} + +/** + * @brief Get number of UL slots per frame + */ +int get_ul_slots_per_frame(const frame_structure_t *fs) +{ + return fs->is_tdd ? fs->numb_period_frame * get_ul_slots_per_period(fs) : fs->numb_slots_frame; +} + +/** + * @brief Get the nth UL slot offset for UE index idx in a TDD period using the frame structure bitmap + * @param fs frame structure + * @param idx UE index + * @param count_mixed indicates whether counting mixed slot with UL symbols (e.g. for SRS) or only full UL slots + * @return slot index offset + */ +int get_ul_slot_offset(const frame_structure_t *fs, int idx, bool count_mixed) +{ + DevAssert(fs); + + // FDD + if (!fs->is_tdd) + return idx; + + // UL slots indexes in period + int ul_slot_idxs[fs->numb_slots_period]; + int ul_slot_count = 0; + + /* Populate the indices of UL slots in the TDD period from the bitmap + count also mixed slots with UL symbols if flag count_mixed is present */ + for (int i = 0; i < fs->numb_slots_period; i++) { + if ((count_mixed && is_ul_slot(i, fs)) || fs->period_cfg.tdd_slot_bitmap[i].slot_type == TDD_NR_UPLINK_SLOT) { + ul_slot_idxs[ul_slot_count++] = i; + } + } + + // Compute slot index offset + int period_idx = idx / ul_slot_count; // wrap up the count of complete TDD periods spanned by the index + int ul_slot_idx_in_period = idx % ul_slot_count; // wrap up the UL slot index within the current TDD period + + return ul_slot_idxs[ul_slot_idx_in_period] + period_idx * fs->numb_slots_period; +} + +/** + * @brief Configures the frame structure and the NFAPI config request + * depending on the duplex mode. If TDD, does the TDD patterns + * and TDD periods configuration. + * + * @param mu numerology + * @param scc pointer to scc + * @param cfg pointer to NFAPI config request + * @param fs pointer to the frame structure to update + * + * @return Number of periods in frame + */ +static int config_frame_structure(int mu, + NR_ServingCellConfigCommon_t *scc, + nfapi_nr_config_request_scf_t *cfg, + frame_structure_t *fs) +{ + fs->numb_slots_frame = nr_slots_per_frame[mu]; + if (cfg->cell_config.frame_duplex_type.value == TDD) { + cfg->tdd_table.tdd_period.tl.tag = NFAPI_NR_CONFIG_TDD_PERIOD_TAG; + cfg->num_tlv++; + cfg->tdd_table.tdd_period.value = get_tdd_period_idx(scc->tdd_UL_DL_ConfigurationCommon); + LOG_D(NR_MAC, "Setting TDD configuration period to %d\n", cfg->tdd_table.tdd_period.value); + fs->numb_period_frame = get_nb_periods_per_frame(cfg->tdd_table.tdd_period.value); + fs->numb_slots_period = fs->numb_slots_frame / fs->numb_period_frame; + fs->is_tdd = true; + config_tdd_patterns(scc->tdd_UL_DL_ConfigurationCommon, fs); + set_tdd_config_nr(cfg, fs); + } else { // FDD + fs->is_tdd = false; + fs->numb_period_frame = 1; + fs->numb_slots_period = nr_slots_per_frame[mu]; + } + AssertFatal(fs->numb_period_frame > 0, "Frame configuration cannot be configured!\n"); + return fs->numb_period_frame; +} + static void config_common(gNB_MAC_INST *nrmac, const nr_mac_config_t *config, NR_ServingCellConfigCommon_t *scc) @@ -321,10 +568,10 @@ static void config_common(gNB_MAC_INST *nrmac, } } struct NR_FrequencyInfoUL *frequencyInfoUL = scc->uplinkConfigCommon->frequencyInfoUL; + int scs = frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; frequency_range = *frequencyInfoUL->frequencyBandList->list.array[0] > 256 ? FR2 : FR1; - bw_index = get_supported_band_index(frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, - frequency_range, - frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth); + bw_index = + get_supported_band_index(scs, frequency_range, frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth); cfg->carrier_config.uplink_bandwidth.value = get_supported_bw_mhz(frequency_range, bw_index); cfg->carrier_config.uplink_bandwidth.tl.tag = NFAPI_NR_CONFIG_UPLINK_BANDWIDTH_TAG; // temporary cfg->num_tlv++; @@ -343,7 +590,7 @@ static void config_common(gNB_MAC_INST *nrmac, cfg->num_tlv++; for (int i = 0; i < 5; i++) { - if (i == frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing) { + if (i == scs) { cfg->carrier_config.ul_grid_size[i].value = frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->carrierBandwidth; cfg->carrier_config.ul_k0[i].value = frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->offsetToCarrier; cfg->carrier_config.ul_grid_size[i].tl.tag = NFAPI_NR_CONFIG_UL_GRID_SIZE_TAG; @@ -442,21 +689,15 @@ static void config_common(gNB_MAC_INST *nrmac, prach_fd_occasion->k1.value = NRRIV2PRBOFFSET(scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE) + rach_ConfigCommon->rach_ConfigGeneric.msg1_FrequencyStart - + (get_N_RA_RB(cfg->prach_config.prach_sub_c_spacing.value, - frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing) - * i); + + (get_N_RA_RB(cfg->prach_config.prach_sub_c_spacing.value, scs) * i); if (IS_SA_MODE(get_softmodem_params())) { prach_fd_occasion->k1.value = NRRIV2PRBOFFSET(scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE) + rach_ConfigCommon->rach_ConfigGeneric.msg1_FrequencyStart - + (get_N_RA_RB(cfg->prach_config.prach_sub_c_spacing.value, - frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing) - * i); + + (get_N_RA_RB(cfg->prach_config.prach_sub_c_spacing.value, scs) * i); } else { prach_fd_occasion->k1.value = rach_ConfigCommon->rach_ConfigGeneric.msg1_FrequencyStart - + (get_N_RA_RB(cfg->prach_config.prach_sub_c_spacing.value, - frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing) - * i); + + (get_N_RA_RB(cfg->prach_config.prach_sub_c_spacing.value, scs) * i); } prach_fd_occasion->k1.tl.tag = NFAPI_NR_CONFIG_K1_TAG; cfg->num_tlv++; @@ -576,28 +817,9 @@ static void config_common(gNB_MAC_INST *nrmac, cfg->num_tlv++; cfg->num_tlv++; - // TDD Table Configuration - if (cfg->cell_config.frame_duplex_type.value == TDD) { - cfg->tdd_table.tdd_period.tl.tag = NFAPI_NR_CONFIG_TDD_PERIOD_TAG; - cfg->num_tlv++; - if (scc->tdd_UL_DL_ConfigurationCommon->pattern1.ext1 == NULL) { - cfg->tdd_table.tdd_period.value = scc->tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity; - } else { - AssertFatal(scc->tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530 != NULL, - "In %s: scc->tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530 is null\n", - __FUNCTION__); - cfg->tdd_table.tdd_period.value = *scc->tdd_UL_DL_ConfigurationCommon->pattern1.ext1->dl_UL_TransmissionPeriodicity_v1530; - } - LOG_D(NR_MAC, "Setting TDD configuration period to %d\n", cfg->tdd_table.tdd_period.value); - int periods_per_frame = set_tdd_config_nr(cfg, - frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing, - scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots, - scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols, - scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots, - scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols); - - AssertFatal(periods_per_frame > 0, "TDD configuration cannot be configured\n"); - } + // Frame structure configuration + uint8_t mu = frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing; + config_frame_structure(mu, scc, cfg, &nrmac->frame_structure); int nb_tx = config->nb_bfw[0]; // number of tx antennas int nb_beams = config->nb_bfw[1]; // number of beams @@ -695,31 +917,6 @@ void nr_mac_config_scc(gNB_MAC_INST *nrmac, NR_ServingCellConfigCommon_t *scc, c find_SSB_and_RO_available(nrmac); - const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; - - int nr_slots_period = n; - int nr_dl_slots = n; - int nr_ulstart_slot = 0; - if (tdd) { - nr_dl_slots = tdd->nrofDownlinkSlots + (tdd->nrofDownlinkSymbols != 0); - nr_ulstart_slot = get_first_ul_slot(tdd->nrofDownlinkSlots, tdd->nrofDownlinkSymbols, tdd->nrofUplinkSymbols); - nr_slots_period /= get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity); - } else { - // if TDD configuration is not present and the band is not FDD, it means it is a dynamic TDD configuration - AssertFatal(nrmac->common_channels[0].frame_type == FDD,"Dynamic TDD not handled yet\n"); - } - - for (int slot = 0; slot < n; ++slot) { - nrmac->dlsch_slot_bitmap[slot / 64] |= (uint64_t)((slot % nr_slots_period) < nr_dl_slots) << (slot % 64); - nrmac->ulsch_slot_bitmap[slot / 64] |= (uint64_t)((slot % nr_slots_period) >= nr_ulstart_slot) << (slot % 64); - - LOG_D(NR_MAC, - "slot %d DL %d UL %d\n", - slot, - (nrmac->dlsch_slot_bitmap[slot / 64] & ((uint64_t)1 << (slot % 64))) != 0, - (nrmac->ulsch_slot_bitmap[slot / 64] & ((uint64_t)1 << (slot % 64))) != 0); - } - NR_COMMON_channels_t *cc = &nrmac->common_channels[0]; NR_SCHED_LOCK(&nrmac->sched_lock); for (int n = 0; n < NR_NB_RA_PROC_MAX; n++) { diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c index 80bb00cfac..f8b8953920 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c @@ -122,8 +122,49 @@ void clear_beam_information(NR_beam_info_t *beam_info, int frame, int slot, int } } -bool is_xlsch_in_slot(uint64_t bitmap, sub_frame_t slot) { - return (bitmap >> (slot % 64)) & 0x01; +/** + * @brief Returns true for: + * (1) FDD + * (2) Mixed slot with UL symbols + * (3) Full UL slot + */ +bool is_ul_slot(const slot_t slot, const frame_structure_t *fs) +{ + if (!fs->is_tdd) + return true; + const tdd_period_config_t *pc = &fs->period_cfg; + slot_t s = get_slot_idx_in_period(slot, fs); + return ((is_mixed_slot(s, fs) && pc->tdd_slot_bitmap[s].num_ul_symbols) + || (pc->tdd_slot_bitmap[s].slot_type == TDD_NR_UPLINK_SLOT)); +} + +/** + * @brief Returns true for: + * (1) FDD + * (2) Mixed slot with DL symbols + * (3) Full DL slot + */ +bool is_dl_slot(const slot_t slot, const frame_structure_t *fs) +{ + if (!fs->is_tdd) + return true; + const tdd_period_config_t *pc = &fs->period_cfg; + slot_t s = get_slot_idx_in_period(slot, fs); + return ((is_mixed_slot(s, fs) && pc->tdd_slot_bitmap[s].num_dl_symbols) + || (pc->tdd_slot_bitmap[s].slot_type == TDD_NR_DOWNLINK_SLOT)); +} + +/** + * @brief Returns true for: + * (1) Mixed slot with DL and/or UL symbols + */ +bool is_mixed_slot(const slot_t slot, const frame_structure_t *fs) +{ + if (!fs->is_tdd) + return false; + slot_t s = get_slot_idx_in_period(slot, fs); + const tdd_period_config_t *pc = &fs->period_cfg; + return pc->tdd_slot_bitmap[s].slot_type == TDD_NR_MIXED_SLOT; } /* the structure nfapi_nr_ul_tti_request_t is very big, let's copy only what is necessary */ diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 5ac48f1374..3f3cbbad12 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -46,8 +46,6 @@ #include "openair2/LAYER2/RLC/rlc.h" #include -extern RAN_CONTEXT_t RC; -extern const uint8_t nr_slots_per_frame[5]; // forward declaration of functions used in this file static void fill_msg3_pusch_pdu(nfapi_nr_pusch_pdu_t *pusch_pdu, @@ -278,7 +276,7 @@ static void schedule_nr_MsgA_pusch(NR_UplinkConfigCommon_t *uplinkConfigCommon, UL_tti_req->SFN = msgA_pusch_frame; UL_tti_req->Slot = msgA_pusch_slot; - AssertFatal(is_xlsch_in_slot(nr_mac->ulsch_slot_bitmap[msgA_pusch_slot / 64], msgA_pusch_slot), + AssertFatal(is_ul_slot(msgA_pusch_slot, &nr_mac->frame_structure), "Slot %d is not an Uplink slot, invalid msgA_PUSCH_TimeDomainOffset_r16 %ld\n", msgA_pusch_slot, msgA_PUSCH_Resource->msgA_PUSCH_TimeDomainOffset_r16); @@ -376,7 +374,7 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP nfapi_nr_ul_tti_request_t *UL_tti_req = &RC.nrmac[module_idP]->UL_tti_req_ahead[0][index]; nfapi_nr_config_request_scf_t *cfg = &RC.nrmac[module_idP]->config[0]; - if (is_nr_UL_slot(scc->tdd_UL_DL_ConfigurationCommon, slotP, cc->frame_type)) { + if (is_ul_slot(slotP, &RC.nrmac[module_idP]->frame_structure)) { const NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &rach_ConfigCommon->rach_ConfigGeneric; uint8_t config_index = rach_ConfigGeneric->prach_ConfigurationIndex; uint8_t N_dur, N_t_slot, start_symbol = 0, N_RA_slot; @@ -787,7 +785,7 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, const int sched_frame = (frame + (slot + K2) / nr_slots_per_frame[mu]) % MAX_FRAME_NUMBER; const int sched_slot = (slot + K2) % nr_slots_per_frame[mu]; - if (is_xlsch_in_slot(nr_mac->ulsch_slot_bitmap[sched_slot / 64], sched_slot)) { + if (is_ul_slot(sched_slot, &nr_mac->frame_structure)) { const int n_slots_frame = nr_slots_per_frame[mu]; NR_beam_alloc_t beam_ul = beam_allocation_procedure(&nr_mac->beam_info, sched_frame, sched_slot, ra->beam_id, n_slots_frame); if (beam_ul.idx < 0) @@ -952,47 +950,44 @@ static void nr_generate_Msg3_retransmission(module_id_t module_idP, ra->ra_state = nrRA_WAIT_Msg3; ra->Msg3_frame = sched_frame; ra->Msg3_slot = sched_slot; - } } -static bool get_feasible_msg3_tda(frame_type_t frame_type, - const NR_ServingCellConfigCommon_t *scc, +static bool get_feasible_msg3_tda(const NR_ServingCellConfigCommon_t *scc, int mu_delta, - uint64_t ulsch_slot_bitmap[3], const NR_PUSCH_TimeDomainResourceAllocationList_t *tda_list, - int slots_per_frame, int frame, int slot, NR_RA_t *ra, NR_beam_info_t *beam_info, - const NR_TDD_UL_DL_Pattern_t *tdd) + const frame_structure_t *fs) { DevAssert(tda_list != NULL); const int NTN_gNB_Koffset = get_NTN_Koffset(scc); - int tdd_period_slot = tdd ? slots_per_frame / get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity) : slots_per_frame; + int slots_per_frame = fs->numb_slots_frame; for (int i = 0; i < tda_list->list.count; i++) { // check if it is UL long k2 = *tda_list->list.array[i]->k2 + NTN_gNB_Koffset; int abs_slot = slot + k2 + mu_delta; int temp_frame = (frame + (abs_slot / slots_per_frame)) & 1023; int temp_slot = abs_slot % slots_per_frame; // msg3 slot according to 8.3 in 38.213 - if ((frame_type == TDD) && !is_xlsch_in_slot(ulsch_slot_bitmap[temp_slot / 64], temp_slot)) + if (fs->is_tdd && !is_ul_slot(temp_slot, fs)) continue; + const tdd_bitmap_t *tdd_slot_bitmap = fs->period_cfg.tdd_slot_bitmap; + int s = get_slot_idx_in_period(temp_slot, fs); // check if enough symbols in case of mixed slot - bool is_mixed = false; - if (frame_type == TDD) { - bool has_mixed = tdd->nrofUplinkSymbols != 0 || tdd->nrofDownlinkSymbols != 0; - is_mixed = has_mixed && ((temp_slot % tdd_period_slot) == tdd->nrofDownlinkSlots); - } + bool is_mixed = is_mixed_slot(s, fs); // if the mixed slot has not enough symbols, skip - if (is_mixed && tdd->nrofUplinkSymbols < 3) + if (is_mixed && tdd_slot_bitmap[s].num_ul_symbols < 3) continue; - uint16_t slot_mask = is_mixed ? SL_to_bitmap(14 - tdd->nrofUplinkSymbols, tdd->nrofUplinkSymbols) : 0x3fff; + uint16_t slot_mask = + is_mixed ? SL_to_bitmap(NR_NUMBER_OF_SYMBOLS_PER_SLOT - tdd_slot_bitmap[s].num_ul_symbols, + tdd_slot_bitmap[s].num_ul_symbols) + : 0x3fff; long startSymbolAndLength = tda_list->list.array[i]->startSymbolAndLength; int start, nr; SLIV2SL(startSymbolAndLength, &start, &nr); @@ -1387,7 +1382,7 @@ static void nr_generate_Msg2(module_id_t module_idP, gNB_MAC_INST *nr_mac = RC.nrmac[module_idP]; // no DL -> cannot send Msg2 - if (!is_xlsch_in_slot(nr_mac->dlsch_slot_bitmap[slotP / 64], slotP)) { + if (!is_dl_slot(slotP, &nr_mac->frame_structure)) { return; } @@ -1415,18 +1410,14 @@ static void nr_generate_Msg2(module_id_t module_idP, return; const NR_UE_UL_BWP_t *ul_bwp = &ra->UL_BWP; - const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; - bool ret = get_feasible_msg3_tda(cc->frame_type, - scc, + bool ret = get_feasible_msg3_tda(scc, DELTA[ul_bwp->scs], - nr_mac->ulsch_slot_bitmap, ul_bwp->tdaList_Common, - nr_slots_per_frame[ul_bwp->scs], frameP, slotP, ra, &nr_mac->beam_info, - tdd); + &nr_mac->frame_structure); if (!ret || ra->Msg3_tda_id > 15) { LOG_D(NR_MAC, "UE RNTI %04x %d.%d: infeasible Msg3 TDA\n", ra->rnti, frameP, slotP); reset_beam_status(&nr_mac->beam_info, frameP, slotP, ra->beam_id, n_slots_frame, beam.new_beam); @@ -1455,7 +1446,7 @@ static void nr_generate_Msg2(module_id_t module_idP, AssertFatal(coreset, "Coreset cannot be null for RA-Msg2\n"); const int coresetid = coreset->controlResourceSetId; // Calculate number of symbols - int time_domain_assignment = get_dl_tda(nr_mac, scc, slotP); + int time_domain_assignment = get_dl_tda(nr_mac, slotP); int mux_pattern = type0_PDCCH_CSS_config ? type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern : 1; NR_tda_info_t tda_info = get_dl_tda_info(dl_bwp, ss->searchSpaceType->present, @@ -1951,8 +1942,8 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id]; NR_UE_DL_BWP_t *dl_bwp = &ra->DL_BWP; - // if it is a DL slot, if the RA is in MSG4 state - if (is_xlsch_in_slot(nr_mac->dlsch_slot_bitmap[slotP / 64], slotP)) { + // if it is a DL slot, if the RA is in MSG4 state + if (is_dl_slot(slotP, &nr_mac->frame_structure)) { NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; NR_SearchSpace_t *ss = ra->ra_ss; const char *ra_type_str = ra->ra_type == RA_2_STEP ? "MsgB" : "Msg4"; @@ -2031,7 +2022,7 @@ static void nr_generate_Msg4_MsgB(module_id_t module_idP, return; } - uint8_t time_domain_assignment = get_dl_tda(nr_mac, scc, slotP); + uint8_t time_domain_assignment = get_dl_tda(nr_mac, slotP); int mux_pattern = type0_PDCCH_CSS_config ? type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern : 1; NR_tda_info_t msg4_tda = get_dl_tda_info(dl_bwp, ss->searchSpaceType->present, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c index fb239c48e4..e2fa7d744b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c @@ -45,8 +45,6 @@ #include "executables/softmodem-common.h" -extern RAN_CONTEXT_t RC; - static void schedule_ssb(frame_t frame, sub_frame_t slot, NR_ServingCellConfigCommon_t *scc, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c index 48a72b527b..8b6639a3e7 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c @@ -52,20 +52,22 @@ #define WORD 32 //#define SIZE_OF_POINTER sizeof (void *) -int get_dl_tda(const gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int slot) +int get_dl_tda(const gNB_MAC_INST *nrmac, int slot) { /* we assume that this function is mutex-protected from outside */ - const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; - AssertFatal(tdd || nrmac->common_channels->frame_type == FDD, "Dynamic TDD not handled yet\n"); + const frame_structure_t *fs = &nrmac->frame_structure; // Use special TDA in case of CSI-RS - if(nrmac->UE_info.sched_csirs > 0) + if (nrmac->UE_info.sched_csirs > 0) return 1; - if (tdd && tdd->nrofDownlinkSymbols > 1) { // if there is a mixed slot where we can transmit DL - const int nr_slots_period = tdd->nrofDownlinkSlots + tdd->nrofUplinkSlots + 1; - if ((slot % nr_slots_period) == tdd->nrofDownlinkSlots) + if (fs->is_tdd) { + int s = get_slot_idx_in_period(slot, fs); + // if there is a mixed slot where we can transmit DL + const tdd_bitmap_t *tdd_slot_bitmap = fs->period_cfg.tdd_slot_bitmap; + if (tdd_slot_bitmap[s].num_dl_symbols > 1 && is_mixed_slot(s, fs)) { return 2; + } } return 0; // if FDD or not mixed slot in TDD, for now use default TDA } @@ -447,7 +449,7 @@ static bool allocate_dl_retransmission(module_id_t module_id, int pm_index = (curInfo->nrOfLayers < retInfo->nrOfLayers) ? curInfo->pm_index : retInfo->pm_index; const int coresetid = sched_ctrl->coreset->controlResourceSetId; - const int tda = get_dl_tda(nr_mac, scc, slot); + const int tda = get_dl_tda(nr_mac, slot); AssertFatal(tda >= 0,"Unable to find PDSCH time domain allocation in list\n"); /* Check first whether the old TDA can be reused @@ -761,7 +763,7 @@ static void pf_dl(module_id_t module_id, sched_pdsch->dl_harq_pid = sched_ctrl->available_dl_harq.head; /* MCS has been set above */ - sched_pdsch->time_domain_allocation = get_dl_tda(mac, scc, slot); + sched_pdsch->time_domain_allocation = get_dl_tda(mac, slot); AssertFatal(sched_pdsch->time_domain_allocation>=0,"Unable to find PDSCH time domain allocation in list\n"); const int coresetid = sched_ctrl->coreset->controlResourceSetId; @@ -955,7 +957,7 @@ void nr_schedule_ue_spec(module_id_t module_id, AssertFatal(pthread_mutex_trylock(&gNB_mac->sched_lock) == EBUSY, "this function should be called with the scheduler mutex locked\n"); - if (!is_xlsch_in_slot(gNB_mac->dlsch_slot_bitmap[slot / 64], slot)) + if (!is_dl_slot(slot, &gNB_mac->frame_structure)) return; /* PREPROCESSOR */ diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c index 26cffef6ac..f2c014a65f 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c @@ -37,10 +37,16 @@ #include "executables/softmodem-common.h" #include "common/utils/nr/nr_common.h" -//#define UL_HARQ_PRINT -extern RAN_CONTEXT_t RC; +// #define UL_HARQ_PRINT +// #define ENABLE_MAC_PAYLOAD_DEBUG 1 -//#define ENABLE_MAC_PAYLOAD_DEBUG 1 +/* This function checks whether the given Dl/UL slot is set + in the input bitmap, which is a mask indicating in which + slot to transmit (among those available in the TDD configuration) */ +static bool is_xlsch_in_slot(uint64_t bitmap, sub_frame_t slot) +{ + return (bitmap >> (slot % 64)) & 0x01; +} uint32_t target_dl_mcs = 9; uint32_t target_dl_Nl = 1; @@ -66,7 +72,7 @@ void nr_preprocessor_phytest(module_id_t module_id, return; } - const int tda = get_dl_tda(RC.nrmac[module_id], scc, slot); + const int tda = get_dl_tda(RC.nrmac[module_id], slot); NR_tda_info_t tda_info = get_dl_tda_info(dl_bwp, sched_ctrl->search_space->searchSpaceType->present, tda, @@ -244,7 +250,7 @@ bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, sub_frame_ sched_ctrl->coreset->controlResourceSetId, sched_ctrl->search_space->searchSpaceType->present, TYPE_C_RNTI_); - const int temp_tda = get_ul_tda(nr_mac, scc, frame, slot); + const int temp_tda = get_ul_tda(nr_mac, frame, slot); if (temp_tda < 0) return false; AssertFatal(temp_tda < tdaList->list.count, @@ -254,7 +260,7 @@ bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, sub_frame_ int K2 = get_K2(tdaList, temp_tda, mu, scc); const int sched_frame = (frame + (slot + K2) / nr_slots_per_frame[mu]) % MAX_FRAME_NUMBER; const int sched_slot = (slot + K2) % nr_slots_per_frame[mu]; - const int tda = get_ul_tda(nr_mac, scc, sched_frame, sched_slot); + const int tda = get_ul_tda(nr_mac, sched_frame, sched_slot); if (tda < 0) return false; AssertFatal(tda < tdaList->list.count, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index ec243fcd86..d6f63d46d1 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -63,12 +63,9 @@ #include "common/utils/alg/find.h" -//#define DEBUG_DCI - -extern RAN_CONTEXT_t RC; - -// CQI TABLES (10 times the value in 214 to adequately compare with R) -// Table 1 (38.214 5.2.2.1-2) +// #define DEBUG_DCI +// CQI TABLES (10 times the value in 214 to adequately compare with R) +// Table 1 (38.214 5.2.2.1-2) static const uint16_t cqi_table1[16][2] = {{0, 0}, {2, 780}, {2, 1200}, @@ -2163,6 +2160,31 @@ int get_ulbw_tbslbrm(int scc_bwpsize, const NR_ServingCellConfig_t *servingCellC return bw; } +static void set_sched_pucch_list(NR_UE_sched_ctrl_t *sched_ctrl, + const NR_UE_UL_BWP_t *ul_bwp, + const NR_ServingCellConfigCommon_t *scc, + const frame_structure_t *fs) +{ + const int NTN_gNB_Koffset = get_NTN_Koffset(scc); + const int n_ul_slots_period = get_ul_slots_per_period(fs); + + // PUCCH list size is given by the number of UL slots in the PUCCH period + // the length PUCCH period is determined by max_fb_time since we may need to prepare PUCCH for ACK/NACK max_fb_time slots ahead + const int list_size = n_ul_slots_period << (int)ceil(log2((ul_bwp->max_fb_time + NTN_gNB_Koffset) / fs->numb_slots_period + 1)); + + if (!sched_ctrl->sched_pucch) { + sched_ctrl->sched_pucch = calloc_or_fail(list_size, sizeof(*sched_ctrl->sched_pucch)); + sched_ctrl->sched_pucch_size = list_size; + } else if (list_size > sched_ctrl->sched_pucch_size) { + sched_ctrl->sched_pucch = realloc(sched_ctrl->sched_pucch, list_size * sizeof(*sched_ctrl->sched_pucch)); + for (int i = sched_ctrl->sched_pucch_size; i < list_size; i++) { + NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[i]; + memset(curr_pucch, 0, sizeof(*curr_pucch)); + } + sched_ctrl->sched_pucch_size = list_size; + } +} + // main function to configure parameters of current BWP void configure_UE_BWP(gNB_MAC_INST *nr_mac, NR_ServingCellConfigCommon_t *scc, @@ -2408,7 +2430,7 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac, NR_UL_DCI_FORMAT_0_0; set_max_fb_time(UL_BWP, DL_BWP); - set_sched_pucch_list(sched_ctrl, UL_BWP, scc); + set_sched_pucch_list(sched_ctrl, UL_BWP, scc, &nr_mac->frame_structure); } if(ra) { @@ -2540,32 +2562,6 @@ NR_UE_info_t *add_new_nr_ue(gNB_MAC_INST *nr_mac, rnti_t rntiP, NR_CellGroupConf return (UE); } -void set_sched_pucch_list(NR_UE_sched_ctrl_t *sched_ctrl, - const NR_UE_UL_BWP_t *ul_bwp, - const NR_ServingCellConfigCommon_t *scc) -{ - const int NTN_gNB_Koffset = get_NTN_Koffset(scc); - const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; - const int n_slots_frame = nr_slots_per_frame[ul_bwp->scs]; - const int nr_slots_period = tdd ? n_slots_frame / get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity) : n_slots_frame; - const int n_ul_slots_period = tdd ? tdd->nrofUplinkSlots + (tdd->nrofUplinkSymbols > 0 ? 1 : 0) : n_slots_frame; - // PUCCH list size is given by the number of UL slots in the PUCCH period - // the length PUCCH period is determined by max_fb_time since we may need to prepare PUCCH for ACK/NACK max_fb_time slots ahead - const int list_size = n_ul_slots_period << (int)ceil(log2((ul_bwp->max_fb_time + NTN_gNB_Koffset) / nr_slots_period + 1)); - if(!sched_ctrl->sched_pucch) { - sched_ctrl->sched_pucch = calloc(list_size, sizeof(*sched_ctrl->sched_pucch)); - sched_ctrl->sched_pucch_size = list_size; - } - else if (list_size > sched_ctrl->sched_pucch_size) { - sched_ctrl->sched_pucch = realloc(sched_ctrl->sched_pucch, list_size * sizeof(*sched_ctrl->sched_pucch)); - for(int i=sched_ctrl->sched_pucch_size; isched_pucch[i]; - memset(curr_pucch, 0, sizeof(*curr_pucch)); - } - sched_ctrl->sched_pucch_size = list_size; - } -} - void free_sched_pucch_list(NR_UE_sched_ctrl_t *sched_ctrl) { free(sched_ctrl->sched_pucch); diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c index e6935db7ae..cbfac0148d 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c @@ -37,10 +37,7 @@ #include #include "PHY/sse_intrin.h" -//#define SRS_DEBUG - -extern RAN_CONTEXT_t RC; - +// #define SRS_DEBUG const uint16_t m_SRS[64] = { 4, 8, 12, 16, 16, 20, 24, 24, 28, 32, 36, 40, 48, 48, 52, 56, 60, 64, 72, 72, 76, 80, 88, 96, 96, 104, 112, 120, 120, 120, 128, 128, 128, 132, 136, 144, 144, 144, 144, 152, 160, 160, 160, 168, 176, 184, 192, 192, 192, 192, 208, 216, 224, 240, 240, 240, 240, 256, 256, diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c index 378565123b..853a4a5ff8 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c @@ -33,9 +33,6 @@ #include "common/ran_context.h" #include "common/utils/nr/nr_common.h" #include "nfapi/oai_integration/vendor_ext.h" - -extern RAN_CONTEXT_t RC; - static void nr_fill_nfapi_pucch(gNB_MAC_INST *nrmac, frame_t frame, sub_frame_t slot, @@ -136,23 +133,35 @@ static const int diff_rsrp_ssb_csi_meas_10_1_6_1_2[16] = { -30 // 10 - 15 }; -static int get_pucch_index(int frame, int slot, int n_slots_frame, const NR_TDD_UL_DL_Pattern_t *tdd, int sched_pucch_size) +static int get_pucch_index(int frame, int slot, const frame_structure_t *fs, int sched_pucch_size) { // PUCCH structures are indexed by slot in the PUCCH period determined by sched_pucch_size number of UL slots // this functions return the index to the structure for slot passed to the function - const int first_ul_slot_period = tdd ? get_first_ul_slot(tdd->nrofDownlinkSlots, tdd->nrofDownlinkSymbols, tdd->nrofUplinkSymbols) : 0; - const int n_ul_slots_period = tdd ? tdd->nrofUplinkSlots + (tdd->nrofUplinkSymbols > 0 ? 1 : 0) : n_slots_frame; - const int nr_slots_period = tdd ? n_slots_frame / get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity) : n_slots_frame; - const int n_ul_slots_frame = n_slots_frame / nr_slots_period * n_ul_slots_period; + const int n_ul_slots_period = get_ul_slots_per_period(fs); + const int n_ul_slots_frame = get_ul_slots_per_frame(fs); // (frame * n_ul_slots_frame) adds up the number of UL slots in the previous frames const int frame_start = frame * n_ul_slots_frame; // ((slot / nr_slots_period) * n_ul_slots_period) adds up the number of UL slots in the previous TDD periods of this frame - const int ul_period_start = (slot / nr_slots_period) * n_ul_slots_period; + const int ul_period_start = (slot / fs->numb_slots_period) * n_ul_slots_period; // ((slot % nr_slots_period) - first_ul_slot_period) gives the progressive number of the slot in this TDD period - const int ul_period_slot = (slot % nr_slots_period) - first_ul_slot_period; + int ul_period_slot = -1; + for (int i = 0; i <= slot % fs->numb_slots_period; i++) { + if (is_ul_slot(i, fs)) { + ul_period_slot++; + } + } + LOG_D(NR_MAC, + "PUCCH frame/slot: request %4d.%2d:frame_start %d,ul_period_start %d, ul_period_slot %d pucch_index %d pucch_size %d " + "scheduling PUCCH\n", + frame, + slot, + frame_start, + ul_period_start, + ul_period_slot, + ((frame_start + ul_period_start + ul_period_slot) % sched_pucch_size), + sched_pucch_size); // the sum gives the index of current UL slot in the frame which is normalized wrt sched_pucch_size return (frame_start + ul_period_start + ul_period_slot) % sched_pucch_size; - } void nr_schedule_pucch(gNB_MAC_INST *nrmac, frame_t frameP, sub_frame_t slotP) @@ -160,17 +169,12 @@ void nr_schedule_pucch(gNB_MAC_INST *nrmac, frame_t frameP, sub_frame_t slotP) /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock); - if (!is_xlsch_in_slot(nrmac->ulsch_slot_bitmap[slotP / 64], slotP)) + if (!is_ul_slot(slotP, &nrmac->frame_structure)) return; UE_iterator(nrmac->UE_info.list, UE) { NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; - NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP; - const int n_slots_frame = nr_slots_per_frame[ul_bwp->scs]; - const NR_ServingCellConfigCommon_t *scc = nrmac->common_channels[0].ServingCellConfigCommon; - const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; - AssertFatal(tdd || nrmac->common_channels[0].frame_type == FDD, "Dynamic TDD not handled yet\n"); - const int pucch_index = get_pucch_index(frameP, slotP, n_slots_frame, tdd, sched_ctrl->sched_pucch_size); + const int pucch_index = get_pucch_index(frameP, slotP, &nrmac->frame_structure, sched_ctrl->sched_pucch_size); NR_sched_pucch_t *curr_pucch = &UE->UE_sched_ctrl.sched_pucch[pucch_index]; if (!curr_pucch->active) continue; @@ -239,7 +243,7 @@ void nr_csi_meas_reporting(int Mod_idP,frame_t frame, sub_frame_t slot) if ((sched_frame * n_slots_frame + sched_slot - offset) % period != 0) continue; - AssertFatal(is_xlsch_in_slot(nrmac->ulsch_slot_bitmap[sched_slot / 64], sched_slot), "CSI reporting slot %d is not set for an uplink slot\n", sched_slot); + AssertFatal(is_ul_slot(sched_slot, &nrmac->frame_structure), "CSI reporting slot %d is not set for an uplink slot\n", sched_slot); LOG_D(NR_MAC, "CSI reporting in frame %d slot %d CSI report ID %ld\n", sched_frame, sched_slot, csirep->reportConfigId); const NR_PUCCH_ResourceSet_t *pucchresset = pucch_Config->resourceSetToAddModList->list.array[1]; // set with formats >1 @@ -251,9 +255,7 @@ void nr_csi_meas_reporting(int Mod_idP,frame_t frame, sub_frame_t slot) AssertFatal(res_index < n, "CSI pucch resource %ld not found among PUCCH resources\n", pucchcsires->pucch_Resource); - const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; - AssertFatal(tdd || nrmac->common_channels[0].frame_type == FDD, "Dynamic TDD not handled yet\n"); - const int pucch_index = get_pucch_index(sched_frame, sched_slot, n_slots_frame, tdd, sched_ctrl->sched_pucch_size); + const int pucch_index = get_pucch_index(sched_frame, sched_slot, &nrmac->frame_structure, sched_ctrl->sched_pucch_size); NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[pucch_index]; AssertFatal(curr_pucch->active == false, "CSI structure is scheduled in advance. It should be free!\n"); curr_pucch->r_pucch = -1; @@ -1001,10 +1003,7 @@ int nr_acknack_scheduling(gNB_MAC_INST *mac, const int minfbtime = mac->radio_config.minRXTXTIME + NTN_gNB_Koffset; const NR_UE_UL_BWP_t *ul_bwp = &UE->current_UL_BWP; const int n_slots_frame = nr_slots_per_frame[ul_bwp->scs]; - const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; - AssertFatal(tdd || mac->common_channels[CC_id].frame_type == FDD, "Dynamic TDD not handled yet\n"); - const int nr_slots_period = tdd ? n_slots_frame / get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity) : n_slots_frame; - const int first_ul_slot_period = tdd ? get_first_ul_slot(tdd->nrofDownlinkSlots, tdd->nrofDownlinkSymbols, tdd->nrofUplinkSymbols) : 0; + const frame_structure_t *fs = &mac->frame_structure; NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; NR_PUCCH_Config_t *pucch_Config = ul_bwp->pucch_Config; @@ -1025,11 +1024,14 @@ int nr_acknack_scheduling(gNB_MAC_INST *mac, continue; const int pucch_slot = (slot + pdsch_to_harq_feedback[f] + NTN_gNB_Koffset) % n_slots_frame; // check if the slot is UL - if(pucch_slot%nr_slots_period < first_ul_slot_period) - continue; + if (fs->is_tdd) { + int mod_slot = pucch_slot % fs->numb_slots_period; + if (!is_ul_slot(mod_slot, fs)) + continue; + } const int pucch_frame = (frame + ((slot + pdsch_to_harq_feedback[f] + NTN_gNB_Koffset) / n_slots_frame)) % MAX_FRAME_NUMBER; // we store PUCCH resources according to slot, TDD configuration and size of the vector containing PUCCH structures - const int pucch_index = get_pucch_index(pucch_frame, pucch_slot, n_slots_frame, tdd, sched_ctrl->sched_pucch_size); + const int pucch_index = get_pucch_index(pucch_frame, pucch_slot, &mac->frame_structure, sched_ctrl->sched_pucch_size); NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[pucch_index]; if (curr_pucch->active && curr_pucch->frame == pucch_frame && @@ -1128,7 +1130,7 @@ void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t SFN, sub_frame_t slot) /* already mutex protected: held in gNB_dlsch_ulsch_scheduler() */ NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock); - if (!is_xlsch_in_slot(nrmac->ulsch_slot_bitmap[slot / 64], slot)) + if (!is_ul_slot(slot, &nrmac->frame_structure)) return; const int CC_id = 0; UE_iterator(nrmac->UE_info.list, UE) { @@ -1167,10 +1169,7 @@ void nr_sr_reporting(gNB_MAC_INST *nrmac, frame_t SFN, sub_frame_t slot) } AssertFatal(idx > -1, "SR resource not found among PUCCH resources"); - const NR_ServingCellConfigCommon_t *scc = nrmac->common_channels[CC_id].ServingCellConfigCommon; - const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; - AssertFatal(tdd || nrmac->common_channels[CC_id].frame_type == FDD, "Dynamic TDD not handled yet\n"); - const int pucch_index = get_pucch_index(SFN, slot, n_slots_frame, tdd, sched_ctrl->sched_pucch_size); + const int pucch_index = get_pucch_index(SFN, slot, &nrmac->frame_structure, sched_ctrl->sched_pucch_size); NR_sched_pucch_t *curr_pucch = &sched_ctrl->sched_pucch[pucch_index]; if (curr_pucch->active && curr_pucch->frame == SFN && curr_pucch->ul_slot == slot && curr_pucch->resource_indicator == idx) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c index afc8c7e6d9..3aacade706 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c @@ -40,19 +40,21 @@ //#define SRS_IND_DEBUG -int get_ul_tda(gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int frame, int slot) +int get_ul_tda(gNB_MAC_INST *nrmac, int frame, int slot) { /* we assume that this function is mutex-protected from outside */ NR_SCHED_ENSURE_LOCKED(&nrmac->sched_lock); /* there is a mixed slot only when in TDD */ - const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; - AssertFatal(tdd || nrmac->common_channels->frame_type == FDD, "Dynamic TDD not handled yet\n"); + frame_structure_t *fs = &nrmac->frame_structure; - if (tdd && tdd->nrofUplinkSymbols > 1) { // if there is uplink symbols in mixed slot - const int nr_slots_period = tdd->nrofDownlinkSlots + tdd->nrofUplinkSlots + 1; - if ((slot % nr_slots_period) == tdd->nrofDownlinkSlots) + if (fs->is_tdd) { + // if there is uplink symbols in mixed slot + int s = get_slot_idx_in_period(slot, fs); + tdd_bitmap_t *tdd_slot_bitmap = fs->period_cfg.tdd_slot_bitmap; + if ((tdd_slot_bitmap[s].num_ul_symbols > 1) && is_mixed_slot(s, fs)) { return 2; + } } // Avoid slots with the SRS @@ -453,9 +455,9 @@ static int nr_process_mac_pdu(instance_t module_idP, if (phr->PH < 55) { PH = phr->PH - 32; } else if (phr->PH < 63) { - PH = 28 + (phr->PH - 55) * 2; + PH = 24 + (phr->PH - 55) * 2; } else { - PH = 42; + PH = 38; } // in sched_ctrl we set normalized PH wrt MCS and PRBs long *deltaMCS = ul_bwp->pusch_Config ? ul_bwp->pusch_Config->pusch_PowerControl->deltaMCS : NULL; @@ -1519,25 +1521,21 @@ long get_K2(NR_PUSCH_TimeDomainResourceAllocationList_t *tdaList, return 3 + NTN_gNB_Koffset; } -static bool nr_UE_is_to_be_scheduled(const NR_ServingCellConfigCommon_t *scc, int CC_id, NR_UE_info_t* UE, frame_t frame, sub_frame_t slot, uint32_t ulsch_max_frame_inactivity) +static bool nr_UE_is_to_be_scheduled(const frame_structure_t *fs, + NR_UE_info_t *UE, + frame_t frame, + sub_frame_t slot, + uint32_t ulsch_max_frame_inactivity) { - const int n = nr_slots_per_frame[*scc->ssbSubcarrierSpacing]; + const int n = fs->numb_slots_frame; const int now = frame * n + slot; const NR_UE_sched_ctrl_t *sched_ctrl =&UE->UE_sched_ctrl; - - const NR_TDD_UL_DL_Pattern_t *tdd = - scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; - int num_slots_per_period; - int last_ul_slot; - if (tdd) { // Force the default transmission in a full slot as early as possible in the UL portion of TDD period (last_ul_slot) - num_slots_per_period = n / get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity); - last_ul_slot = 1 + tdd->nrofDownlinkSlots; - } else { - num_slots_per_period = n; - last_ul_slot = sched_ctrl->last_ul_slot; - } - + /** + * Force the default transmission in a full slot as early + * as possible in the UL portion of TDD period (last_ul_slot) */ + int num_slots_per_period = fs->numb_slots_period; + int last_ul_slot = fs->is_tdd ? get_first_ul_slot(fs, false) : sched_ctrl->last_ul_slot; const int last_ul_sched = sched_ctrl->last_ul_frame * n + last_ul_slot; const int diff = (now - last_ul_sched + 1024 * n) % (1024 * n); /* UE is to be scheduled if @@ -1641,7 +1639,7 @@ static void nr_ue_max_mcs_min_rb(int mu, } if (ph_limit < tx_power) - LOG_W(NR_MAC, "Normalized power %d based on current resources (RBs %d, MCS %d) exceed reported PHR %d (normalized value)\n", + LOG_D(NR_MAC, "Normalized power %d based on current resources (RBs %d, MCS %d) exceed reported PHR %d (normalized value)\n", tx_power, *Rb, *mcs, ph_limit); } @@ -1842,7 +1840,7 @@ static void pf_ul(module_id_t module_id, } int n = nr_slots_per_frame[current_BWP->scs]; - NR_beam_alloc_t beam = beam_allocation_procedure(&nrmac->beam_info, sched_pusch->frame, sched_pusch->slot, UE->UE_beam_index, n); + NR_beam_alloc_t beam = beam_allocation_procedure(&nrmac->beam_info, sched_frame, sched_slot, UE->UE_beam_index, n); if (beam.idx < 0) { LOG_D(NR_MAC, "[UE %04x][%4d.%2d] Beam could not be allocated\n", UE->rnti, frame, slot); reset_beam_status(&nrmac->beam_info, frame, slot, UE->UE_beam_index, n_dl, dci_beam.new_beam); @@ -1856,7 +1854,7 @@ static void pf_ul(module_id_t module_id, LOG_D(NR_MAC,"pf_ul: UE %04x harq_pid %d\n", UE->rnti, sched_pusch->ul_harq_pid); if (sched_pusch->ul_harq_pid >= 0) { /* Allocate retransmission*/ - const int tda = get_ul_tda(nrmac, scc, sched_frame, sched_slot); + const int tda = get_ul_tda(nrmac, sched_frame, sched_slot); bool r = allocate_ul_retransmission(nrmac, frame, slot, @@ -1869,7 +1867,7 @@ static void pf_ul(module_id_t module_id, tda); if (!r) { LOG_D(NR_MAC, "[UE %04x][%4d.%2d] UL retransmission could not be allocated\n", UE->rnti, frame, slot); - reset_beam_status(&nrmac->beam_info, sched_pusch->frame, sched_pusch->slot, UE->UE_beam_index, n, beam.new_beam); + reset_beam_status(&nrmac->beam_info, sched_frame, sched_slot, UE->UE_beam_index, n, beam.new_beam); reset_beam_status(&nrmac->beam_info, frame, slot, UE->UE_beam_index, n_dl, dci_beam.new_beam); continue; } @@ -1885,7 +1883,7 @@ static void pf_ul(module_id_t module_id, * if the UE disconnected in L2sim, in which case the gNB is not notified * (this can be considered a design flaw) */ if (sched_ctrl->available_ul_harq.head < 0) { - reset_beam_status(&nrmac->beam_info, sched_pusch->frame, sched_pusch->slot, UE->UE_beam_index, n, beam.new_beam); + reset_beam_status(&nrmac->beam_info, sched_frame, sched_slot, UE->UE_beam_index, n, beam.new_beam); reset_beam_status(&nrmac->beam_info, frame, slot, UE->UE_beam_index, n_dl, dci_beam.new_beam); LOG_D(NR_MAC, "[UE %04x][%4d.%2d] has no free UL HARQ process, skipping\n", UE->rnti, frame, slot); continue; @@ -1893,11 +1891,15 @@ static void pf_ul(module_id_t module_id, const int B = max(0, sched_ctrl->estimated_ul_buffer - sched_ctrl->sched_ul_bytes); /* preprocessor computed sched_frame/sched_slot */ - const bool do_sched = nr_UE_is_to_be_scheduled(scc, 0, UE, sched_frame, sched_slot, nrmac->ulsch_max_frame_inactivity); + const bool do_sched = nr_UE_is_to_be_scheduled(&nrmac->frame_structure, + UE, + sched_frame, + sched_slot, + nrmac->ulsch_max_frame_inactivity); LOG_D(NR_MAC,"pf_ul: do_sched UE %04x => %s\n", UE->rnti, do_sched ? "yes" : "no"); if ((B == 0 && !do_sched) || nr_timer_is_active(&sched_ctrl->transm_interrupt)) { - reset_beam_status(&nrmac->beam_info, sched_pusch->frame, sched_pusch->slot, UE->UE_beam_index, n, beam.new_beam); + reset_beam_status(&nrmac->beam_info, sched_frame, sched_slot, UE->UE_beam_index, n, beam.new_beam); reset_beam_status(&nrmac->beam_info, frame, slot, UE->UE_beam_index, n_dl, dci_beam.new_beam); continue; } @@ -1927,13 +1929,13 @@ static void pf_ul(module_id_t module_id, false); if (CCEIndex < 0) { LOG_D(NR_MAC, "[UE %04x][%4d.%2d] no free CCE for UL DCI (BSR 0)\n", UE->rnti, frame, slot); - reset_beam_status(&nrmac->beam_info, sched_pusch->frame, sched_pusch->slot, UE->UE_beam_index, n, beam.new_beam); + reset_beam_status(&nrmac->beam_info, sched_frame, sched_slot, UE->UE_beam_index, n, beam.new_beam); reset_beam_status(&nrmac->beam_info, frame, slot, UE->UE_beam_index, n_dl, dci_beam.new_beam); continue; } sched_pusch->nrOfLayers = sched_ctrl->srs_feedback.ul_ri + 1; - sched_pusch->time_domain_allocation = get_ul_tda(nrmac, scc, sched_frame, sched_slot); + sched_pusch->time_domain_allocation = get_ul_tda(nrmac, sched_frame, sched_slot); sched_pusch->tda_info = get_ul_tda_info(current_BWP, sched_ctrl->coreset->controlResourceSetId, sched_ctrl->search_space->searchSpaceType->present, @@ -1962,7 +1964,7 @@ static void pf_ul(module_id_t module_id, rbStart, min_rb, bwpSize); - reset_beam_status(&nrmac->beam_info, sched_pusch->frame, sched_pusch->slot, UE->UE_beam_index, n, beam.new_beam); + reset_beam_status(&nrmac->beam_info, sched_frame, sched_slot, UE->UE_beam_index, n, beam.new_beam); reset_beam_status(&nrmac->beam_info, frame, slot, UE->UE_beam_index, n_dl, dci_beam.new_beam); continue; } @@ -2042,11 +2044,7 @@ static void pf_ul(module_id_t module_id, NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch; int n = nr_slots_per_frame[current_BWP->scs]; - NR_beam_alloc_t beam = beam_allocation_procedure(&nrmac->beam_info, - sched_pusch->frame, - sched_pusch->slot, - iterator->UE->UE_beam_index, - n); + NR_beam_alloc_t beam = beam_allocation_procedure(&nrmac->beam_info, sched_frame, sched_slot, iterator->UE->UE_beam_index, n); if (beam.idx < 0) { LOG_D(NR_MAC, "[UE %04x][%4d.%2d] Beam could not be allocated\n", iterator->UE->rnti, frame, slot); iterator++; @@ -2054,7 +2052,7 @@ static void pf_ul(module_id_t module_id, } if (remainUEs[beam.idx] == 0 || n_rb_sched[beam.idx] < min_rb) { - reset_beam_status(&nrmac->beam_info, sched_pusch->frame, sched_pusch->slot, iterator->UE->UE_beam_index, n, beam.new_beam); + reset_beam_status(&nrmac->beam_info, sched_frame, sched_slot, iterator->UE->UE_beam_index, n, beam.new_beam); iterator++; continue; } @@ -2063,7 +2061,7 @@ static void pf_ul(module_id_t module_id, NR_beam_alloc_t dci_beam = beam_allocation_procedure(&nrmac->beam_info, frame, slot, iterator->UE->UE_beam_index, n_dl); if (dci_beam.idx < 0) { LOG_D(NR_MAC, "[UE %04x][%4d.%2d] Beam could not be allocated\n", iterator->UE->rnti, frame, slot); - reset_beam_status(&nrmac->beam_info, sched_pusch->frame, sched_pusch->slot, iterator->UE->UE_beam_index, n, beam.new_beam); + reset_beam_status(&nrmac->beam_info, sched_frame, sched_slot, iterator->UE->UE_beam_index, n, beam.new_beam); iterator++; continue; } @@ -2079,7 +2077,7 @@ static void pf_ul(module_id_t module_id, if (CCEIndex < 0) { reset_beam_status(&nrmac->beam_info, frame, slot, iterator->UE->UE_beam_index, n_dl, dci_beam.new_beam); - reset_beam_status(&nrmac->beam_info, sched_pusch->frame, sched_pusch->slot, iterator->UE->UE_beam_index, n, beam.new_beam); + reset_beam_status(&nrmac->beam_info, sched_frame, sched_slot, iterator->UE->UE_beam_index, n, beam.new_beam); LOG_D(NR_MAC, "[UE %04x][%4d.%2d] no free CCE for UL DCI\n", iterator->UE->rnti, frame, slot); iterator++; continue; @@ -2090,7 +2088,7 @@ static void pf_ul(module_id_t module_id, sched_pusch->nrOfLayers = sched_ctrl->srs_feedback.ul_ri + 1; - sched_pusch->time_domain_allocation = get_ul_tda(nrmac, scc, sched_frame, sched_slot); + sched_pusch->time_domain_allocation = get_ul_tda(nrmac, sched_frame, sched_slot); sched_pusch->tda_info = get_ul_tda_info(current_BWP, sched_ctrl->coreset->controlResourceSetId, sched_ctrl->search_space->searchSpaceType->present, @@ -2115,7 +2113,7 @@ static void pf_ul(module_id_t module_id, if (rbStart + min_rb >= bwpSize || max_rbSize < min_rb) { reset_beam_status(&nrmac->beam_info, frame, slot, iterator->UE->UE_beam_index, n_dl, dci_beam.new_beam); - reset_beam_status(&nrmac->beam_info, sched_pusch->frame, sched_pusch->slot, iterator->UE->UE_beam_index, n, beam.new_beam); + reset_beam_status(&nrmac->beam_info, sched_frame, sched_slot, iterator->UE->UE_beam_index, n, beam.new_beam); LOG_D(NR_MAC, "[UE %04x][%4d.%2d] could not allocate UL data: no resources (rbStart %d, min_rb %d, bwpSize %d)\n", iterator->UE->rnti, frame, @@ -2219,7 +2217,7 @@ static bool nr_ulsch_preprocessor(module_id_t module_id, frame_t frame, sub_fram const int K2 = nr_mac->radio_config.minRXTXTIME + get_NTN_Koffset(scc); const int sched_frame = (frame + (slot + K2) / slots_frame) % MAX_FRAME_NUMBER; const int sched_slot = (slot + K2) % slots_frame; - if (!is_xlsch_in_slot(nr_mac->ulsch_slot_bitmap[sched_slot / 64], sched_slot)) + if (!is_ul_slot(sched_slot, &nr_mac->frame_structure)) return false; int num_beams = nr_mac->beam_info.beam_allocation ? nr_mac->beam_info.beams_per_period : 1; @@ -2278,7 +2276,7 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot, n /* Uplink data ONLY can be scheduled when the current slot is downlink slot, * because we have to schedule the DCI0 first before schedule uplink data */ - if (!is_xlsch_in_slot(nr_mac->dlsch_slot_bitmap[slot / 64], slot)) { + if (!is_dl_slot(slot, &nr_mac->frame_structure)) { LOG_D(NR_MAC, "Current slot %d is NOT DL slot, cannot schedule DCI0 for UL data\n", slot); return; } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 46deef46e8..4cd5563200 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -39,6 +39,14 @@ void set_cset_offset(uint16_t); void get_K1_K2(int N1, int N2, int *K1, int *K2, int layers); int get_NTN_Koffset(const NR_ServingCellConfigCommon_t *scc); +int get_first_ul_slot(const frame_structure_t *fs, bool mixed); +int get_ul_slots_per_period(const frame_structure_t *fs); +int get_ul_slots_per_frame(const frame_structure_t *fs); +int get_dl_slots_per_period(const frame_structure_t *fs); +int get_full_ul_slots_per_period(const frame_structure_t *fs); +int get_full_dl_slots_per_period(const frame_structure_t *fs); +int get_ul_slot_offset(const frame_structure_t *fs, int idx, bool count_mixed); + void mac_top_init_gNB(ngran_node_t node_type, NR_ServingCellConfigCommon_t *scc, NR_ServingCellConfig_t *scd, @@ -344,7 +352,9 @@ int nr_write_ce_dlsch_pdu(module_id_t module_idP, int binomial(int n, int k); -bool is_xlsch_in_slot(uint64_t bitmap, sub_frame_t slot); +bool is_ul_slot(const slot_t slot, const frame_structure_t *fs); +bool is_dl_slot(const slot_t slot, const frame_structure_t *fs); +bool is_mixed_slot(const slot_t slot, const frame_structure_t *fs); /* \brief Function to indicate a received SDU on ULSCH. @param Mod_id Instance ID of gNB @@ -406,13 +416,10 @@ uint8_t get_mcs_from_cqi(int mcs_table, int cqi_table, int cqi_idx); uint8_t get_dl_nrOfLayers(const NR_UE_sched_ctrl_t *sched_ctrl, const nr_dci_format_t dci_format); -void set_sched_pucch_list(NR_UE_sched_ctrl_t *sched_ctrl, - const NR_UE_UL_BWP_t *ul_bwp, - const NR_ServingCellConfigCommon_t *scc); void free_sched_pucch_list(NR_UE_sched_ctrl_t *sched_ctrl); -int get_dl_tda(const gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int slot); -int get_ul_tda(gNB_MAC_INST *nrmac, const NR_ServingCellConfigCommon_t *scc, int frame, int slot); +int get_dl_tda(const gNB_MAC_INST *nrmac, int slot); +int get_ul_tda(gNB_MAC_INST *nrmac, int frame, int slot); int get_cce_index(const gNB_MAC_INST *nrmac, const int CC_id, diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c index 3456cc86fd..a8fe8de79c 100644 --- a/openair2/LAYER2/NR_MAC_gNB/main.c +++ b/openair2/LAYER2/NR_MAC_gNB/main.c @@ -72,9 +72,6 @@ #include "time_meas.h" #include "utils.h" -extern RAN_CONTEXT_t RC; - - #define MACSTATSSTRLEN 36256 void *nrmac_stats_thread(void *arg) { diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index bb1fba0fe8..c8604c431f 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -905,13 +905,10 @@ typedef struct gNB_MAC_INST_s { NR_beam_info_t beam_info; - /// bitmap of DLSCH slots, can hold up to 160 slots - uint64_t dlsch_slot_bitmap[3]; - /// bitmap of ULSCH slots, can hold up to 160 slots - uint64_t ulsch_slot_bitmap[3]; - /// maximum number of slots before a UE will be scheduled ULSCH automatically uint32_t ulsch_max_frame_inactivity; + /// instance of the frame structure configuration + frame_structure_t frame_structure; /// DL preprocessor for differentiated scheduling nr_pp_impl_dl pre_processor_dl; diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c index 64a152f847..bffb064159 100644 --- a/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c +++ b/openair2/LAYER2/nr_rlc/nr_rlc_oai_api.c @@ -41,9 +41,6 @@ #include "openair2/F1AP/f1ap_du_rrc_message_transfer.h" #include "openair2/F1AP/f1ap_ids.h" #include "openair3/ocp-gtpu/gtp_itf.h" - -extern RAN_CONTEXT_t RC; - #include #include diff --git a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c index f23460c994..aac556575d 100644 --- a/openair2/NR_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_PHY_INTERFACE/NR_IF_Module.c @@ -45,22 +45,11 @@ #include "openair2/NR_PHY_INTERFACE/nr_sched_response.h" #include "openair2/PHY_INTERFACE/queue_t.h" #include "utils.h" +#include "nfapi/oai_integration/nfapi_pnf.h" #define MAX_IF_MODULES 100 static NR_IF_Module_t *nr_if_inst[MAX_IF_MODULES]; -extern int oai_nfapi_harq_indication(nfapi_harq_indication_t *harq_ind); -extern int oai_nfapi_crc_indication(nfapi_crc_indication_t *crc_ind); -extern int oai_nfapi_cqi_indication(nfapi_cqi_indication_t *cqi_ind); -extern int oai_nfapi_sr_indication(nfapi_sr_indication_t *ind); -extern int oai_nfapi_rx_ind(nfapi_rx_indication_t *ind); -extern int oai_nfapi_nr_slot_indication(nfapi_nr_slot_indication_scf_t *ind); -extern int oai_nfapi_nr_rx_data_indication(nfapi_nr_rx_data_indication_t *ind); -extern int oai_nfapi_nr_crc_indication(nfapi_nr_crc_indication_t *ind); -extern int oai_nfapi_nr_srs_indication(nfapi_nr_srs_indication_t *ind); -extern int oai_nfapi_nr_uci_indication(nfapi_nr_uci_indication_t *ind); -extern int oai_nfapi_nr_rach_indication(nfapi_nr_rach_indication_t *ind); -extern uint8_t nfapi_mode; static void handle_nr_rach(NR_UL_IND_t *UL_info) { diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_Packet_Drop.c b/openair2/NR_UE_PHY_INTERFACE/NR_Packet_Drop.c index 8a6bd3118c..97c5a4e130 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_Packet_Drop.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_Packet_Drop.c @@ -57,7 +57,6 @@ void read_channel_param(const nfapi_nr_dl_tti_pdsch_pdu_rel15_t * pdu, int slot, return; } -extern nr_bler_struct nr_bler_data[NR_NUM_MCS]; float get_bler_val(uint8_t mcs, int sinr) { // 4th col = dropped packets, 5th col = total packets diff --git a/openair2/RRC/LTE/defs_NB_IoT.h b/openair2/RRC/LTE/defs_NB_IoT.h index 4cce4650d7..51835cc181 100644 --- a/openair2/RRC/LTE/defs_NB_IoT.h +++ b/openair2/RRC/LTE/defs_NB_IoT.h @@ -461,7 +461,7 @@ typedef struct UE_RRC_INST_NB_IoT_s { Rrc_State_NB_IoT_t RrcState; Rrc_Sub_State_NB_IoT_t RrcSubState; plmn_t plmnID; - Byte_t rat; + uint8_t rat; as_nas_info_t initialNasMsg; OAI_UECapability_NB_IoT_t *UECap; uint8_t *UECapability; diff --git a/openair2/RRC/LTE/rrc_defs.h b/openair2/RRC/LTE/rrc_defs.h index 959abc11f9..70897c16b7 100644 --- a/openair2/RRC/LTE/rrc_defs.h +++ b/openair2/RRC/LTE/rrc_defs.h @@ -801,7 +801,7 @@ typedef struct UE_RRC_INST_s { Rrc_State_t RrcState; Rrc_Sub_State_t RrcSubState; plmn_t plmnID; - Byte_t rat; + uint8_t rat; uint8_t selected_plmn_identity; as_nas_info_t initialNasMsg; OAI_UECapability_t *UECap; diff --git a/openair2/RRC/LTE/rrc_eNB.c b/openair2/RRC/LTE/rrc_eNB.c index bfe07c86ca..78f05cf56a 100644 --- a/openair2/RRC/LTE/rrc_eNB.c +++ b/openair2/RRC/LTE/rrc_eNB.c @@ -34,6 +34,7 @@ #include "uper_encoder.h" #include "uper_decoder.h" #include "rrc_defs.h" +#include "rrc_proto.h" #include "rrc_extern.h" #include "assertions.h" #include "common/ran_context.h" @@ -104,23 +105,8 @@ #define NUMBEROF_DRBS_TOBE_ADDED 1 static int encode_CG_ConfigInfo(char *buffer,int buffer_size,rrc_eNB_ue_context_t *const ue_context_pP,int *enc_size); -extern RAN_CONTEXT_t RC; - -extern eNB_MAC_INST *eNB_mac_inst; -extern UE_MAC_INST *UE_mac_inst; - - mui_t rrc_eNB_mui = 0; -extern uint32_t to_earfcn_DL(int eutra_bandP, uint32_t dl_CarrierFreq, uint32_t bw); -extern int rrc_eNB_process_security(const protocol_ctxt_t *const ctxt_pP, rrc_eNB_ue_context_t *const ue_context_pP, security_capabilities_t *security_capabilities_pP); -extern void process_eNB_security_key(const protocol_ctxt_t *const ctxt_pP, - rrc_eNB_ue_context_t *const ue_context_pP, - uint8_t *security_key_pP); -extern int rrc_eNB_generate_RRCConnectionReconfiguration_endc(protocol_ctxt_t *ctxt, rrc_eNB_ue_context_t *ue_context, unsigned char *buffer, int buffer_size, OCTET_STRING_t *scg_group_config, - OCTET_STRING_t *scg_RB_config); -extern struct rrc_eNB_ue_context_s *get_first_ue_context(eNB_RRC_INST *rrc_instance_pP); - pthread_mutex_t rrc_release_freelist; RRC_release_list_t rrc_release_info; pthread_mutex_t lock_ue_freelist; diff --git a/openair2/RRC/LTE/rrc_eNB_S1AP.c b/openair2/RRC/LTE/rrc_eNB_S1AP.c index 4ec1b9383d..1124cc8dd9 100644 --- a/openair2/RRC/LTE/rrc_eNB_S1AP.c +++ b/openair2/RRC/LTE/rrc_eNB_S1AP.c @@ -29,6 +29,7 @@ */ #include "rrc_defs.h" +#include "rrc_proto.h" #include "rrc_extern.h" #include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h" #include "RRC/LTE/MESSAGES/asn1_msg.h" @@ -396,7 +397,9 @@ static e_LTE_SecurityAlgorithmConfig__integrityProtAlgorithm rrc_eNB_select_inte return INTEGRITY_ALGORITHM_NONE; } -/*! \fn int rrc_eNB_process_security (uint8_t mod_id, uint8_t ue_index, security_capabilities_t *security_capabilities) +/*! \fn int rrc_eNB_process_security(const protocol_ctxt_t *const ctxt_pP, + rrc_eNB_ue_context_t *const ue_context_pP, + security_capabilities_t *security_capabilities_pP) *\brief save and analyze available security algorithms bit mask and select relevant ones. *\param mod_id Instance ID of eNB. *\param ue_index Instance ID of UE in the eNB. diff --git a/openair2/RRC/LTE/rrc_proto.h b/openair2/RRC/LTE/rrc_proto.h index 1810fbaed2..38ba42b251 100644 --- a/openair2/RRC/LTE/rrc_proto.h +++ b/openair2/RRC/LTE/rrc_proto.h @@ -654,5 +654,16 @@ extern pthread_mutex_t lock_ue_freelist; void remove_UE_from_freelist(module_id_t mod_id, rnti_t rnti); void put_UE_in_freelist(module_id_t mod_id, rnti_t rnti, bool removeFlag); void release_UE_in_freeList(module_id_t mod_id); - +int rrc_eNB_process_security(const protocol_ctxt_t *const ctxt_pP, + rrc_eNB_ue_context_t *const ue_context_pP, + security_capabilities_t *security_capabilities_pP); +void process_eNB_security_key(const protocol_ctxt_t *const ctxt_pP, + rrc_eNB_ue_context_t *const ue_context_pP, + uint8_t *security_key_pP); +int rrc_eNB_generate_RRCConnectionReconfiguration_endc(protocol_ctxt_t *ctxt, + rrc_eNB_ue_context_t *ue_context, + unsigned char *buffer, + int buffer_size, + OCTET_STRING_t *scg_group_config, + OCTET_STRING_t *scg_RB_config); /** @}*/ diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c index 68a8c49774..b66625e6b2 100644 --- a/openair2/RRC/NR/MESSAGES/asn1_msg.c +++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c @@ -153,8 +153,6 @@ typedef struct xer_sprint_string_s { size_t string_index; } xer_sprint_string_t; -extern RAN_CONTEXT_t RC; - /* * This is a helper function for xer_sprint, which directs all incoming data * into the provided string. diff --git a/openair2/RRC/NR/nr_rrc_config.c b/openair2/RRC/NR/nr_rrc_config.c index f6e7c15e8b..18487e9657 100644 --- a/openair2/RRC/NR/nr_rrc_config.c +++ b/openair2/RRC/NR/nr_rrc_config.c @@ -49,7 +49,9 @@ #include "constr_TYPE.h" #include "executables/softmodem-common.h" #include "oai_asn1.h" +#include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h" #include "openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h" +#include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h" #include "openair3/UTILS/conversions.h" #include "uper_decoder.h" #include "uper_encoder.h" @@ -312,9 +314,13 @@ static uint64_t get_ssb_bitmap(const NR_ServingCellConfigCommon_t *scc) return bitmap; } -static int set_ideal_period(const int n_slots_period, const int n_ul_slots_period) +static int set_ideal_period(bool is_csi) { - return MAX_MOBILES_PER_GNB * 2 * n_slots_period / n_ul_slots_period; // 2 reports per UE (RSRP and RI-PMI-CQI) + const frame_structure_t *fs = &RC.nrmac[0]->frame_structure; + const int nb_slots_per_period = fs->numb_slots_period; + const int n_ul_slots_per_period = get_ul_slots_per_period(fs); // full UL + mixed with UL symbols + // 2 reports per UE (RSRP and RI-PMI-CQI) + return is_csi ? MAX_MOBILES_PER_GNB * 2 * nb_slots_per_period / n_ul_slots_per_period : nb_slots_per_period * MAX_MOBILES_PER_GNB; } static void set_csirs_periodicity(NR_NZP_CSI_RS_Resource_t *nzpcsi0, @@ -389,16 +395,6 @@ static void config_csirs(const NR_ServingCellConfigCommon_t *servingcellconfigco nzpcsirs0->aperiodicTriggeringOffset = NULL; nzpcsirs0->trs_Info = NULL; asn1cSeqAdd(&csi_MeasConfig->nzp_CSI_RS_ResourceSetToAddModList->list,nzpcsirs0); - - const NR_TDD_UL_DL_Pattern_t *tdd = servingcellconfigcommon->tdd_UL_DL_ConfigurationCommon ? - &servingcellconfigcommon->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; - - const int n_slots_frame = slotsperframe[*servingcellconfigcommon->ssbSubcarrierSpacing]; - const int nb_slots_per_period = tdd ? n_slots_frame/get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity): n_slots_frame; - const int nb_dl_slots_period = tdd ? tdd->nrofDownlinkSlots : n_slots_frame; - const int n_ul_slots_period = tdd ? (tdd->nrofUplinkSlots + (tdd->nrofUplinkSymbols > 0)) : n_slots_frame; - const int ideal_period = set_ideal_period(nb_slots_per_period, n_ul_slots_period); // same periodicity as CSI measurement report - if(!csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList) csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList = calloc(1,sizeof(*csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList)); NR_NZP_CSI_RS_Resource_t *nzpcsi0 = calloc(1,sizeof(*nzpcsi0)); @@ -447,7 +443,12 @@ static void config_csirs(const NR_ServingCellConfigCommon_t *servingcellconfigco nzpcsi0->powerControlOffsetSS = calloc(1,sizeof(*nzpcsi0->powerControlOffsetSS)); *nzpcsi0->powerControlOffsetSS = NR_NZP_CSI_RS_Resource__powerControlOffsetSS_db0; nzpcsi0->scramblingID = *servingcellconfigcommon->physCellId; - set_csirs_periodicity(nzpcsi0, id, ideal_period, nb_slots_per_period, nb_dl_slots_period); + + const int ideal_period = set_ideal_period(true); // same periodicity as CSI measurement report + const frame_structure_t *fs = &(RC.nrmac[0]->frame_structure); + const int nb_dl_slots_period = get_full_dl_slots_per_period(fs); // full DL slots + set_csirs_periodicity(nzpcsi0, id, ideal_period, fs->numb_slots_period, nb_dl_slots_period); + nzpcsi0->qcl_InfoPeriodicCSI_RS = calloc(1,sizeof(*nzpcsi0->qcl_InfoPeriodicCSI_RS)); *nzpcsi0->qcl_InfoPeriodicCSI_RS = 0; asn1cSeqAdd(&csi_MeasConfig->nzp_CSI_RS_ResourceToAddModList->list,nzpcsi0); @@ -628,15 +629,12 @@ long rrc_get_max_nr_csrs(const int max_rbs, const long b_SRS) { static struct NR_SRS_Resource__resourceType__periodic *configure_periodic_srs(const NR_ServingCellConfigCommon_t *scc, const int uid) { + frame_structure_t *fs = &RC.nrmac[0]->frame_structure; + int offset = get_ul_slot_offset(fs, uid, false); // only full UL slots for SRS - const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; - const int n_slots_frame = slotsperframe[*scc->ssbSubcarrierSpacing]; - const int ul_slots_period = tdd ? tdd->nrofUplinkSlots : n_slots_frame; - const int n_slots_period = tdd ? n_slots_frame/get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity) : n_slots_frame; - const int first_full_ul_slot = n_slots_period - ul_slots_period; - const int ideal_period = n_slots_period * MAX_MOBILES_PER_GNB; - const int offset = first_full_ul_slot + (uid % ul_slots_period) + (n_slots_period * (uid / ul_slots_period)); AssertFatal(offset < 2560, "Cannot allocate SRS configuration for uid %d, not enough resources\n", uid); + const int ideal_period = set_ideal_period(false); + struct NR_SRS_Resource__resourceType__periodic *periodic_srs = calloc(1,sizeof(*periodic_srs)); if (ideal_period < 5) { periodic_srs->periodicityAndOffset_p.present = NR_SRS_PeriodicityAndOffset_PR_sl4; @@ -907,7 +905,17 @@ void nr_rrc_config_dl_tda(struct NR_PDSCH_TimeDomainResourceAllocationList *pdsc if(frame_type==TDD) { // TDD if(tdd_UL_DL_ConfigurationCommon) { - int dl_symb = tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols; + int dl_symb = 0; + if (tdd_UL_DL_ConfigurationCommon->pattern2 && tdd_UL_DL_ConfigurationCommon->pattern2->nrofDownlinkSymbols) + AssertFatal(tdd_UL_DL_ConfigurationCommon->pattern2->nrofDownlinkSymbols == tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols, + "nrofDownlinkSymbols in pattern1 %ld and pattern2 %ld must be the same in current implementation\n", + tdd_UL_DL_ConfigurationCommon->pattern2->nrofDownlinkSymbols, + tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols); + if (tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols != 0) { + dl_symb = tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols; + } else if (tdd_UL_DL_ConfigurationCommon->pattern2) { + dl_symb = tdd_UL_DL_ConfigurationCommon->pattern2->nrofDownlinkSymbols; + } if(dl_symb > 1) { // mixed slot TDA with TDA index 2 struct NR_PDSCH_TimeDomainResourceAllocation *timedomainresourceallocation2 = CALLOC(1,sizeof(NR_PDSCH_TimeDomainResourceAllocation_t)); @@ -919,6 +927,94 @@ void nr_rrc_config_dl_tda(struct NR_PDSCH_TimeDomainResourceAllocationList *pdsc } } +const float tdd_ms_period_pattern[] = {0.5, 0.625, 1.0, 1.25, 2.0, 2.5, 5.0, 10.0}; +const float tdd_ms_period_ext[] = {3.0, 4.0}; + +/** + * @brief Retrieves the periodicity in milliseconds for the given TDD pattern + * depending on the presence of the extension + * @param pattern Pointer to the NR_TDD_UL_DL_Pattern_t pattern structure + * @return Periodicity value in milliseconds. + */ +static float get_tdd_periodicity(NR_TDD_UL_DL_Pattern_t *pattern) { + if (!pattern->ext1) { + LOG_D(NR_MAC, "Setting TDD configuration period to dl_UL_TransmissionPeriodicity %ld\n", pattern->dl_UL_TransmissionPeriodicity); + return tdd_ms_period_pattern[pattern->dl_UL_TransmissionPeriodicity]; + } else { + DevAssert(pattern->ext1->dl_UL_TransmissionPeriodicity_v1530 != NULL); + LOG_D(NR_MAC, + "Setting TDD configuration period to dl_UL_TransmissionPeriodicity_v1530 %ld\n", + *pattern->ext1->dl_UL_TransmissionPeriodicity_v1530); + return tdd_ms_period_ext[*pattern->ext1->dl_UL_TransmissionPeriodicity_v1530]; + } +} + +/** + * @brief Determines the TDD period index based on pattern periodicities + * @note Not applicabile to pattern extension + * @param tdd Pointer to the NR_TDD_UL_DL_ConfigCommon_t containing patterns + * @return Index of the TDD period in tdd_ms_period_pattern + */ +int get_tdd_period_idx(NR_TDD_UL_DL_ConfigCommon_t *tdd) +{ + int tdd_period_idx = 0; + float pattern1_ms = get_tdd_periodicity(&tdd->pattern1); + float pattern2_ms = tdd->pattern2 ? get_tdd_periodicity(tdd->pattern2) : 0.0; + bool found_match = false; + // Find matching TDD period in the predefined list of periodicities + for (int i = 0; i < NFAPI_MAX_NUM_PERIODS; i++) { + if ((pattern1_ms + pattern2_ms) == tdd_ms_period_pattern[i]) { + tdd_period_idx = i; + LOG_I(NR_MAC, + "TDD period index = %d, based on the sum of dl_UL_TransmissionPeriodicity " + "from Pattern1 (%f ms) and Pattern2 (%f ms): Total = %f ms\n", + tdd_period_idx, + pattern1_ms, + pattern2_ms, + pattern1_ms + pattern2_ms); + found_match = true; + break; + } + } + // Assert if no match was found + AssertFatal(found_match, "The sum of pattern1_ms and pattern2_ms does not match any value in tdd_ms_period_pattern"); + return tdd_period_idx; +} + +static struct NR_PUSCH_TimeDomainResourceAllocation *set_TimeDomainResourceAllocation(const int k2, uint8_t index, int ul_symb) +{ + struct NR_PUSCH_TimeDomainResourceAllocation *puschTdrAlloc = calloc_or_fail(1, sizeof(*puschTdrAlloc)); + puschTdrAlloc->k2 = calloc_or_fail(1, sizeof(*puschTdrAlloc->k2)); + *puschTdrAlloc->k2 = k2; + puschTdrAlloc->mappingType = NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB; + switch (index) { + case 0: + puschTdrAlloc->startSymbolAndLength = get_SLIV(0, 13); + break; + case 1: + puschTdrAlloc->startSymbolAndLength = get_SLIV(0, 12); + break; + case 2: + // UL TDA index 2 for mixed slot (TDD) + puschTdrAlloc->startSymbolAndLength = + get_SLIV(NR_NUMBER_OF_SYMBOLS_PER_SLOT - ul_symb, ul_symb - 1); // starting in fist ul symbol til the last but one + break; + case 3: { + // UL TDA index 3 for msg3 in the mixed slot (TDD) + int no_mix_slot = ul_symb < 3 ? 1 : 0; // we need at least 2 symbols for scheduling Msg3 + *puschTdrAlloc->k2 += no_mix_slot; + if (no_mix_slot) + puschTdrAlloc->startSymbolAndLength = get_SLIV(0, 13); // full allocation if there is no mixed slot + else + puschTdrAlloc->startSymbolAndLength = + get_SLIV(NR_NUMBER_OF_SYMBOLS_PER_SLOT - ul_symb, ul_symb - 1); // starting in fist ul symbol til the last but one + } + break; + default: + break; + } + return puschTdrAlloc; +} void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay) { @@ -928,58 +1024,48 @@ void nr_rrc_config_ul_tda(NR_ServingCellConfigCommon_t *scc, int min_fb_delay) scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList; AssertFatal(tda->list.count == 0, "already have pusch_TimeDomainAllocationList members\n"); - frame_type_t frame_type = get_frame_type(*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing); const int k2 = min_fb_delay; - uint8_t DELTA[4]= {2,3,4,6}; // Delta parameter for Msg3 int mu = scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing; + struct NR_SetupRelease_PUSCH_ConfigCommon *pusch_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon; // UL TDA index 0 is basic slot configuration starting in symbol 0 til the last but one symbol - struct NR_PUSCH_TimeDomainResourceAllocation *pusch_timedomainresourceallocation = CALLOC(1,sizeof(struct NR_PUSCH_TimeDomainResourceAllocation)); - pusch_timedomainresourceallocation->k2 = CALLOC(1,sizeof(long)); - *pusch_timedomainresourceallocation->k2 = k2; - pusch_timedomainresourceallocation->mappingType = NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB; - pusch_timedomainresourceallocation->startSymbolAndLength = get_SLIV(0, 13); - asn1cSeqAdd(&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list,pusch_timedomainresourceallocation); + asn1cSeqAdd(&pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list, set_TimeDomainResourceAllocation(k2, 0, 0)); // UL TDA index 1 in case of SRS - struct NR_PUSCH_TimeDomainResourceAllocation *pusch_timedomainresourceallocation1 = CALLOC(1,sizeof(struct NR_PUSCH_TimeDomainResourceAllocation)); - pusch_timedomainresourceallocation1->k2 = CALLOC(1,sizeof(long)); - *pusch_timedomainresourceallocation1->k2 = k2; - pusch_timedomainresourceallocation1->mappingType = NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB; - pusch_timedomainresourceallocation1->startSymbolAndLength = get_SLIV(0, 12); - asn1cSeqAdd(&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list,pusch_timedomainresourceallocation1); + asn1cSeqAdd(&pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list, set_TimeDomainResourceAllocation(k2, 1, 0)); - if(frame_type==TDD) { - if(scc->tdd_UL_DL_ConfigurationCommon) { - int ul_symb = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols; - if (ul_symb>1) { - // UL TDA index 2 for mixed slot (TDD) - pusch_timedomainresourceallocation = CALLOC(1,sizeof(struct NR_PUSCH_TimeDomainResourceAllocation)); - pusch_timedomainresourceallocation->k2 = CALLOC(1,sizeof(long)); - *pusch_timedomainresourceallocation->k2 = k2; - pusch_timedomainresourceallocation->mappingType = NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB; - pusch_timedomainresourceallocation->startSymbolAndLength = get_SLIV(14 - ul_symb, ul_symb - 1); // starting in fist ul symbol til the last but one - asn1cSeqAdd(&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list,pusch_timedomainresourceallocation); - } - // UL TDA index 3 for msg3 in the mixed slot (TDD) - int nb_periods_per_frame = get_nb_periods_per_frame(scc->tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity); - int nb_slots_per_period = ((1 << mu) * 10) / nb_periods_per_frame; - struct NR_PUSCH_TimeDomainResourceAllocation *pusch_timedomainresourceallocation_msg3 = CALLOC(1,sizeof(struct NR_PUSCH_TimeDomainResourceAllocation)); - pusch_timedomainresourceallocation_msg3->k2 = CALLOC(1,sizeof(long)); - int no_mix_slot = ul_symb < 3 ? 1 : 0; // we need at least 2 symbols for scheduling Msg3 - *pusch_timedomainresourceallocation_msg3->k2 = nb_slots_per_period - DELTA[mu] + no_mix_slot; - if(*pusch_timedomainresourceallocation_msg3->k2 < min_fb_delay) - *pusch_timedomainresourceallocation_msg3->k2 += nb_slots_per_period; - AssertFatal(*pusch_timedomainresourceallocation_msg3->k2 < 33,"Computed k2 for msg3 %ld is larger than the range allowed by RRC (0..32)\n", - *pusch_timedomainresourceallocation_msg3->k2); - pusch_timedomainresourceallocation_msg3->mappingType = NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB; - if(no_mix_slot) - pusch_timedomainresourceallocation_msg3->startSymbolAndLength = get_SLIV(0, 13); // full allocation if there is no mixed slot - else - pusch_timedomainresourceallocation_msg3->startSymbolAndLength = get_SLIV(14 - ul_symb, ul_symb - 1); // starting in fist ul symbol til the last but one - asn1cSeqAdd(&scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list,pusch_timedomainresourceallocation_msg3); + if (scc->tdd_UL_DL_ConfigurationCommon) { + int ul_symb = 0; + NR_TDD_UL_DL_Pattern_t *p1 = &scc->tdd_UL_DL_ConfigurationCommon->pattern1; + NR_TDD_UL_DL_Pattern_t *p2 = scc->tdd_UL_DL_ConfigurationCommon->pattern2; + if (p2 && p2->nrofUplinkSymbols) + AssertFatal(p2->nrofUplinkSymbols == p1->nrofUplinkSymbols, + "nrofDownlinkSymbols in pattern1 %ld and pattern2 %ld must be the same in current implementation\n", + p1->nrofUplinkSymbols, + p2->nrofUplinkSymbols); + if (p1->nrofUplinkSymbols) { + ul_symb = p1->nrofUplinkSymbols; + } else if (p2) { + ul_symb = p1->nrofUplinkSymbols; } + if (ul_symb>1) { + // UL TDA index 2 for mixed slot (TDD) + asn1cSeqAdd(&pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list, + set_TimeDomainResourceAllocation(k2, 2, ul_symb)); + } + // UL TDA index 3 for msg3 in the mixed slot (TDD) + int tdd_period_idx = get_tdd_period_idx(scc->tdd_UL_DL_ConfigurationCommon); + int nb_periods_per_frame = get_nb_periods_per_frame(tdd_period_idx); + int nb_slots_per_period = ((1 << mu) * 10) / nb_periods_per_frame; + int k2_msg3 = nb_slots_per_period - DELTA[mu]; + struct NR_PUSCH_TimeDomainResourceAllocation *puschTdrAllocMsg3 = set_TimeDomainResourceAllocation(k2_msg3, 3, ul_symb); + if (*puschTdrAllocMsg3->k2 < min_fb_delay) + *puschTdrAllocMsg3->k2 += nb_slots_per_period; + AssertFatal(*puschTdrAllocMsg3->k2 < 33, + "Computed k2 for msg3 %ld is larger than the range allowed by RRC (0..32)\n", + *puschTdrAllocMsg3->k2); + asn1cSeqAdd(&pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list, puschTdrAllocMsg3); } } @@ -1118,10 +1204,10 @@ void set_pucch_power_config(NR_PUCCH_Config_t *pucch_Config, int do_csirs) { static void set_SR_periodandoffset(NR_SchedulingRequestResourceConfig_t *schedulingRequestResourceConfig, const NR_ServingCellConfigCommon_t *scc, int scs) { - const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; + const frame_structure_t *fs = &RC.nrmac[0]->frame_structure; int sr_slot = 1; // in FDD SR in slot 1 - if(tdd) - sr_slot = get_first_ul_slot(tdd->nrofDownlinkSlots, tdd->nrofDownlinkSymbols, tdd->nrofUplinkSymbols); + if (fs->is_tdd) + sr_slot = get_first_ul_slot(fs, true); schedulingRequestResourceConfig->periodicityAndOffset = calloc(1,sizeof(*schedulingRequestResourceConfig->periodicityAndOffset)); @@ -1581,15 +1667,14 @@ static void set_csi_meas_periodicity(const NR_ServingCellConfigCommon_t *scc, int curr_bwp, bool is_rsrp) { - const NR_TDD_UL_DL_Pattern_t *tdd = scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL; - const int n_slots_frame = slotsperframe[*scc->ssbSubcarrierSpacing]; - const int n_ul_slots_period = tdd ? (tdd->nrofUplinkSlots + (tdd->nrofUplinkSymbols > 0)) : n_slots_frame; - const int n_slots_period = tdd ? n_slots_frame / get_nb_periods_per_frame(tdd->dl_UL_TransmissionPeriodicity) : n_slots_frame; - const int ideal_period = set_ideal_period(n_slots_period, n_ul_slots_period); - const int first_ul_slot_period = tdd ? get_first_ul_slot(tdd->nrofDownlinkSlots, tdd->nrofDownlinkSymbols, tdd->nrofUplinkSymbols) : 0; + const int ideal_period = set_ideal_period(true); const int num_pucch2 = get_nb_pucch2_per_slot(scc, curr_bwp); const int idx = (uid * 2 / num_pucch2) + is_rsrp; - const int offset = first_ul_slot_period + idx % n_ul_slots_period + (idx / n_ul_slots_period) * n_slots_period; + + frame_structure_t *fs = &RC.nrmac[0]->frame_structure; + int offset = get_ul_slot_offset(fs, idx, true); + + LOG_D(NR_MAC, "set_csi_meas_periodicity: uid = %d, offset = %d, ideal_period = %d", uid, offset, ideal_period); AssertFatal(offset < 320, "Not enough UL slots to accomodate all possible UEs. Need to rework the implementation\n"); if (ideal_period < 5) { @@ -2499,7 +2584,10 @@ NR_BCCH_DL_SCH_Message_t *get_SIB1_NR(const NR_ServingCellConfigCommon_t *scc, AssertFatal(ServCellCom->tdd_UL_DL_ConfigurationCommon != NULL, "out of memory\n"); ServCellCom->tdd_UL_DL_ConfigurationCommon->referenceSubcarrierSpacing = scc->tdd_UL_DL_ConfigurationCommon->referenceSubcarrierSpacing; ServCellCom->tdd_UL_DL_ConfigurationCommon->pattern1 = scc->tdd_UL_DL_ConfigurationCommon->pattern1; - ServCellCom->tdd_UL_DL_ConfigurationCommon->pattern2 = scc->tdd_UL_DL_ConfigurationCommon->pattern2; + if (scc->tdd_UL_DL_ConfigurationCommon->pattern2) { + ServCellCom->tdd_UL_DL_ConfigurationCommon->pattern2 = calloc_or_fail(1, sizeof(struct NR_TDD_UL_DL_Pattern)); + *ServCellCom->tdd_UL_DL_ConfigurationCommon->pattern2 = *scc->tdd_UL_DL_ConfigurationCommon->pattern2; + } } ServCellCom->ss_PBCH_BlockPower = scc->ss_PBCH_BlockPower; diff --git a/openair2/RRC/NR/nr_rrc_config.h b/openair2/RRC/NR/nr_rrc_config.h index b9f030e897..3076b09f62 100644 --- a/openair2/RRC/NR/nr_rrc_config.h +++ b/openair2/RRC/NR/nr_rrc_config.h @@ -112,5 +112,6 @@ NR_CellGroupConfig_t *get_default_secondaryCellGroup(const NR_ServingCellConfigC int uid); NR_ReconfigurationWithSync_t *get_reconfiguration_with_sync(rnti_t rnti, uid_t uid, const NR_ServingCellConfigCommon_t *scc); +int get_tdd_period_idx(NR_TDD_UL_DL_ConfigCommon_t *tdd); #endif diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index 953f723853..7ed9bf322e 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -202,8 +202,6 @@ typedef struct gNB_RRC_UE_s { NR_CellGroupConfig_t *masterCellGroup; NR_RadioBearerConfig_t *rb_config; - ImsiMobileIdentity_t imsi; - /* KgNB as derived from KASME received from EPC */ uint8_t kgnb[32]; int8_t kgnb_ncc; diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index b4d33b16f0..fd69a4fafd 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -101,10 +101,6 @@ #include "openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc_extern.h" #endif -//#define XER_PRINT - -extern RAN_CONTEXT_t RC; - mui_t rrc_gNB_mui = 0; typedef struct deliver_ue_ctxt_release_data_t { diff --git a/openair2/RRC/NR/rrc_gNB_GTPV1U.c b/openair2/RRC/NR/rrc_gNB_GTPV1U.c index 6bf64a27a9..79882d58f3 100644 --- a/openair2/RRC/NR/rrc_gNB_GTPV1U.c +++ b/openair2/RRC/NR/rrc_gNB_GTPV1U.c @@ -36,8 +36,6 @@ #include "rrc_eNB_GTPV1U.h" #include "s1ap_messages_types.h" -extern RAN_CONTEXT_t RC; - int rrc_gNB_process_GTPV1U_CREATE_TUNNEL_RESP(gNB_RRC_UE_t *ue, const gtpv1u_enb_create_tunnel_resp_t *const create_tunnel_resp_pP, uint8_t *inde_list) diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 08f83ea5c8..0b1c3012f4 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -87,8 +87,6 @@ #include "openair2/E2AP/RAN_FUNCTION/O-RAN/ran_func_rc_extern.h" #endif -extern RAN_CONTEXT_t RC; - /* Masks for NGAP Encryption algorithms, NEA0 is always supported (not coded) */ static const uint16_t NGAP_ENCRYPTION_NEA1_MASK = 0x8000; static const uint16_t NGAP_ENCRYPTION_NEA2_MASK = 0x4000; diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.h b/openair2/RRC/NR/rrc_gNB_NGAP.h index a4ccaaa41b..22fff8705f 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.h +++ b/openair2/RRC/NR/rrc_gNB_NGAP.h @@ -40,6 +40,8 @@ #include "ngap_messages_types.h" #include "nr_rrc_defs.h" +extern mui_t rrc_gNB_mui; + void rrc_gNB_send_NGAP_NAS_FIRST_REQ(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, NR_RRCSetupComplete_IEs_t *rrcSetupComplete); int rrc_gNB_process_NGAP_INITIAL_CONTEXT_SETUP_REQ(MessageDef *msg_p, instance_t instance); diff --git a/openair2/RRC/NR/rrc_gNB_mobility.c b/openair2/RRC/NR/rrc_gNB_mobility.c index 22e86c5120..e4c4e8b67e 100644 --- a/openair2/RRC/NR/rrc_gNB_mobility.c +++ b/openair2/RRC/NR/rrc_gNB_mobility.c @@ -34,9 +34,7 @@ #include "MESSAGES/asn1_msg.h" #include "nr_pdcp/nr_pdcp_oai_api.h" #include "openair3/SECU/key_nas_deriver.h" - -/* declared in rrc_gNB.c: should be cleaned up through helper function? useful? */ -extern mui_t rrc_gNB_mui; +#include "openair2/RRC/NR/rrc_gNB_NGAP.h" typedef enum { HO_CTX_BOTH, HO_CTX_SOURCE, HO_CTX_TARGET } ho_ctx_type_t; static nr_handover_context_t *alloc_ho_ctx(ho_ctx_type_t type) diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 88b781723b..26b9f51046 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -1749,7 +1749,11 @@ static void nr_rrc_ue_generate_RRCReconfigurationComplete(NR_UE_RRC_INST_t *rrc, static void nr_rrc_ue_process_rrcReestablishment(NR_UE_RRC_INST_t *rrc, const int gNB_index, - const NR_RRCReestablishment_t *rrcReestablishment) + const NR_RRCReestablishment_t *rrcReestablishment, + int srb_id, + const uint8_t *msg, + int msg_size, + const nr_pdcp_integrity_data_t *msg_integrity) { // implementign procedues as described in 38.331 section 5.3.7.5 // stop timer T301 @@ -1764,22 +1768,31 @@ static void nr_rrc_ue_process_rrcReestablishment(NR_UE_RRC_INST_t *rrc, // update the K gNB key based on the current K gNB key or the NH, using the stored nextHopChainingCount value nr_derive_key_ng_ran_star(rrc->phyCellID, rrc->arfcn_ssb, rrc->kgnb, rrc->kgnb); - // derive the K RRCenc key associated with the previously configured cipheringAlgorithm - // derive the K RRCint key associated with the previously configured integrityProtAlgorithm + // derive the K_RRCenc key associated with the previously configured cipheringAlgorithm + // derive the K_RRCint key associated with the previously configured integrityProtAlgorithm nr_pdcp_entity_security_keys_and_algos_t security_parameters; security_parameters.ciphering_algorithm = rrc->cipheringAlgorithm; security_parameters.integrity_algorithm = rrc->integrityProtAlgorithm; nr_derive_key(RRC_ENC_ALG, rrc->cipheringAlgorithm, rrc->kgnb, security_parameters.ciphering_key); nr_derive_key(RRC_INT_ALG, rrc->integrityProtAlgorithm, rrc->kgnb, security_parameters.integrity_key); - // TODO request lower layers to verify the integrity protection of the RRCReestablishment message - // TODO if the integrity protection check of the RRCReestablishment message fails -> go to IDLE - // configure lower layers to resume integrity protection for SRB1 // configure lower layers to resume ciphering for SRB1 - int srb_id = 1; + AssertFatal(srb_id == 1, "rrcReestablishment SRB-ID %d, should be 1\n", srb_id); nr_pdcp_config_set_security(rrc->ue_id, srb_id, true, &security_parameters); + // request lower layers to verify the integrity protection of the RRCReestablishment message + // using the previously configured algorithm and the K_RRCint key + bool integrity_pass = nr_pdcp_check_integrity_srb(rrc->ue_id, srb_id, msg, msg_size, msg_integrity); + // if the integrity protection check of the RRCReestablishment message fails + // perform the actions upon going to RRC_IDLE as specified in 5.3.11 + // with release cause 'RRC connection failure', upon which the procedure ends + if (!integrity_pass) { + NR_Release_Cause_t release_cause = RRC_CONNECTION_FAILURE; + nr_rrc_going_to_IDLE(rrc, release_cause, NULL); + return; + } + // release the measurement gap configuration indicated by the measGapConfig, if configured rrcPerNB_t *rrcNB = rrc->perNB + gNB_index; asn1cFreeStruc(asn_DEF_NR_MeasGapConfig, rrcNB->measGapConfig); @@ -1860,7 +1873,13 @@ static int nr_rrc_ue_decode_dcch(NR_UE_RRC_INST_t *rrc, case NR_DL_DCCH_MessageType__c1_PR_rrcReestablishment: LOG_I(NR_RRC, "Logical Channel DL-DCCH (SRB1), Received RRCReestablishment\n"); - nr_rrc_ue_process_rrcReestablishment(rrc, gNB_indexP, c1->choice.rrcReestablishment); + nr_rrc_ue_process_rrcReestablishment(rrc, + gNB_indexP, + c1->choice.rrcReestablishment, + Srb_id, + Buffer, + Buffer_size, + msg_integrity); break; case NR_DL_DCCH_MessageType__c1_PR_dlInformationTransfer: { @@ -1894,8 +1913,7 @@ static int nr_rrc_ue_decode_dcch(NR_UE_RRC_INST_t *rrc, break; case NR_DL_DCCH_MessageType__c1_PR_securityModeCommand: LOG_I(NR_RRC, "Received securityModeCommand (gNB %d)\n", gNB_indexP); - nr_rrc_ue_process_securityModeCommand(rrc, c1->choice.securityModeCommand, - Srb_id, Buffer, Buffer_size, msg_integrity); + nr_rrc_ue_process_securityModeCommand(rrc, c1->choice.securityModeCommand, Srb_id, Buffer, Buffer_size, msg_integrity); break; } } break; diff --git a/openair3/CMakeLists.txt b/openair3/CMakeLists.txt index f638abbaaa..55f9fe91d6 100644 --- a/openair3/CMakeLists.txt +++ b/openair3/CMakeLists.txt @@ -1,6 +1,7 @@ add_subdirectory(LPP) add_subdirectory(M3AP) add_subdirectory(S1AP) +add_subdirectory(NAS) add_subdirectory(NGAP) add_subdirectory(NRPPA) -add_subdirectory(NAS) +add_subdirectory(UICC) diff --git a/openair3/NAS/CMakeLists.txt b/openair3/NAS/CMakeLists.txt index 50cbedd280..50bfe97bc3 100644 --- a/openair3/NAS/CMakeLists.txt +++ b/openair3/NAS/CMakeLists.txt @@ -1 +1,3 @@ add_subdirectory(COMMON) +add_subdirectory(NR_UE) +add_subdirectory(UE) diff --git a/openair3/NAS/COMMON/API/NETWORK/as_message.c b/openair3/NAS/COMMON/API/NETWORK/as_message.c index e1db277bcc..23d7097db3 100644 --- a/openair3/NAS/COMMON/API/NETWORK/as_message.c +++ b/openair3/NAS/COMMON/API/NETWORK/as_message.c @@ -192,7 +192,7 @@ int as_message_encode(char* buffer, as_message_t* msg, int length) int bytes = sizeof(msg->msgID); as_nas_info_t nas_msg; - Byte_t *dataptr=NULL; + uint8_t* dataptr = NULL; uint32_t len=0; memset(&nas_msg, 0, sizeof(as_nas_info_t)); @@ -230,30 +230,30 @@ int as_message_encode(char* buffer, as_message_t* msg, int length) case AS_NAS_ESTABLISH_REQ: /* NAS signalling connection establish request */ - bytes += sizeof(nas_establish_req_t) - sizeof(Byte_t*); + bytes += sizeof(nas_establish_req_t) - sizeof(uint8_t*); nas_msg = msg->msg.nas_establish_req.initialNasMsg; break; case AS_NAS_ESTABLISH_IND: /* NAS signalling connection establish indication */ - bytes += sizeof(nas_establish_ind_t) - sizeof(Byte_t*); + bytes += sizeof(nas_establish_ind_t) - sizeof(uint8_t*); nas_msg = msg->msg.nas_establish_ind.initialNasMsg; - dataptr = (Byte_t*)&(msg->msg.nas_establish_ind.initialNasMsg.nas_data); + dataptr = (uint8_t*)&(msg->msg.nas_establish_ind.initialNasMsg.nas_data); len=msg->msg.nas_establish_ind.initialNasMsg.length; break; case AS_NAS_ESTABLISH_RSP: /* NAS signalling connection establish response */ - bytes += sizeof(nas_establish_rsp_t) - sizeof(Byte_t*); + bytes += sizeof(nas_establish_rsp_t) - sizeof(uint8_t*); nas_msg = msg->msg.nas_establish_rsp.nasMsg; break; case AS_NAS_ESTABLISH_CNF: /* NAS signalling connection establish confirm */ - bytes += sizeof(nas_establish_cnf_t) - sizeof(Byte_t*); + bytes += sizeof(nas_establish_cnf_t) - sizeof(uint8_t*); nas_msg = msg->msg.nas_establish_cnf.nasMsg; - dataptr = (Byte_t*)&(msg->msg.nas_establish_cnf.nasMsg.nas_data); + dataptr = (uint8_t*)&(msg->msg.nas_establish_cnf.nasMsg.nas_data); len=msg->msg.nas_establish_ind.initialNasMsg.length; break; @@ -269,7 +269,7 @@ int as_message_encode(char* buffer, as_message_t* msg, int length) case AS_UL_INFO_TRANSFER_REQ: /* Uplink L3 data transfer request */ - bytes += sizeof(ul_info_transfer_req_t) - sizeof(Byte_t*); + bytes += sizeof(ul_info_transfer_req_t) - sizeof(uint8_t*); nas_msg = msg->msg.ul_info_transfer_req.nasMsg; break; @@ -280,13 +280,13 @@ int as_message_encode(char* buffer, as_message_t* msg, int length) case AS_UL_INFO_TRANSFER_IND: /* Uplink L3 data transfer indication */ - bytes += sizeof(ul_info_transfer_ind_t) - sizeof(Byte_t*); + bytes += sizeof(ul_info_transfer_ind_t) - sizeof(uint8_t*); nas_msg = msg->msg.ul_info_transfer_ind.nasMsg; break; case AS_DL_INFO_TRANSFER_REQ: /* Downlink L3 data transfer */ - bytes += sizeof(dl_info_transfer_req_t) - sizeof(Byte_t*); + bytes += sizeof(dl_info_transfer_req_t) - sizeof(uint8_t*); nas_msg = msg->msg.dl_info_transfer_req.nasMsg; break; @@ -297,7 +297,7 @@ int as_message_encode(char* buffer, as_message_t* msg, int length) case AS_DL_INFO_TRANSFER_IND: /* Downlink L3 data transfer indication */ - bytes += sizeof(dl_info_transfer_ind_t) - sizeof(Byte_t*); + bytes += sizeof(dl_info_transfer_ind_t) - sizeof(uint8_t*); nas_msg = msg->msg.dl_info_transfer_ind.nasMsg; break; diff --git a/openair3/NAS/COMMON/CMakeLists.txt b/openair3/NAS/COMMON/CMakeLists.txt index 21de73f92f..820b03f2b8 100644 --- a/openair3/NAS/COMMON/CMakeLists.txt +++ b/openair3/NAS/COMMON/CMakeLists.txt @@ -1,2 +1,2 @@ add_subdirectory(IES) -add_subdirectory(EMM) +add_subdirectory(UTIL) diff --git a/openair3/NAS/COMMON/EMM/MSG/CMakeLists.txt b/openair3/NAS/COMMON/EMM/MSG/CMakeLists.txt deleted file mode 100644 index fed78e453d..0000000000 --- a/openair3/NAS/COMMON/EMM/MSG/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -add_library(fgs_lib OBJECT - fgs_service_request.c -) - -target_link_libraries(fgs_lib PUBLIC fgs_ies_lib) - -target_include_directories(fgs_lib PUBLIC - ${CMAKE_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR} -) diff --git a/openair3/NAS/COMMON/EMM/MSG/RegistrationAccept.c b/openair3/NAS/COMMON/EMM/MSG/RegistrationAccept.c deleted file mode 100644 index d7c5c5d719..0000000000 --- a/openair3/NAS/COMMON/EMM/MSG/RegistrationAccept.c +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/*! \file RegistrationAccept.c - -\brief 5GS registration accept procedures -\author Yoshio INOUE, Masayuki HARADA -\email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com -\date 2020 -\version 0.1 -*/ - -#include -#include -#include -#include - - -#include "TLVEncoder.h" -#include "TLVDecoder.h" -#include "RegistrationAccept.h" -#include "assertions.h" - -int decode_registration_accept(registration_accept_msg *registration_accept, const uint8_t *buffer, uint32_t len) -{ - uint32_t decoded = 0; - int decoded_result = 0; - - /* Decoding mandatory fields */ - if ((decoded_result = decode_fgs_registration_result(®istration_accept->fgsregistrationresult, 0, *(buffer + decoded), len - decoded)) < 0) - return decoded_result; - - decoded += decoded_result; - - if (decoded < len && buffer[decoded] == 0x77) { - registration_accept->guti = calloc(1, sizeof(*registration_accept->guti)); - if (!registration_accept->guti) - return -1; - int mi_dec = decode_5gs_mobile_identity(registration_accept->guti, 0x77, buffer + decoded, len - decoded); - if (mi_dec < 0) - return -1; - decoded += mi_dec; - } - - // todo ,Decoding optional fields - return decoded; -} - -int encode_registration_accept(registration_accept_msg *registration_accept, uint8_t *buffer, uint32_t len) -{ - int encoded = 0; - - LOG_FUNC_IN; - - - *(buffer + encoded) = encode_fgs_registration_result(®istration_accept->fgsregistrationresult); - encoded = encoded + 2; - - if (registration_accept->guti) { - int mi_enc = encode_5gs_mobile_identity(registration_accept->guti, 0x77, buffer + encoded, len - encoded); - if (mi_enc < 0) - return mi_enc; - encoded += mi_enc; - } - - // todo ,Encoding optional fields - LOG_FUNC_RETURN(encoded); -} - diff --git a/openair3/NAS/COMMON/ESM/MSG/PduSessionEstablishmentAccept.c b/openair3/NAS/COMMON/ESM/MSG/PduSessionEstablishmentAccept.c deleted file mode 100644 index aa19cae2e4..0000000000 --- a/openair3/NAS/COMMON/ESM/MSG/PduSessionEstablishmentAccept.c +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#include -#include "PduSessionEstablishmentAccept.h" -#include "common/utils/LOG/log.h" -#include "nr_nas_msg.h" -#include "common/utils/tun_if.h" -#include "openair2/SDAP/nr_sdap/nr_sdap.h" - -static uint16_t getShort(uint8_t *input) -{ - uint16_t tmp16; - memcpy(&tmp16, input, sizeof(tmp16)); - return htons(tmp16); -} - -static int capture_ipv4_addr(const uint8_t *addr, char *ip, size_t len) -{ - return snprintf(ip, len, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]); -} - -static int capture_ipv6_addr(const uint8_t *addr, char *ip, size_t len) -{ - // 24.501 Sec 9.11.4.10: "an interface identifier for the IPv6 link local - // address": link local starts with fe80::, and only the last 64bits are - // given (middle is zero) - return snprintf(ip, - len, - "fe80::%02x%02x:%02x%02x:%02x%02x:%02x%02x", - addr[0], - addr[1], - addr[2], - addr[3], - addr[4], - addr[5], - addr[6], - addr[7]); -} - -void capture_pdu_session_establishment_accept_msg(uint8_t *buffer, uint32_t msg_length) -{ - security_protected_nas_5gs_msg_t sec_nas_hdr; - security_protected_plain_nas_5gs_msg_t sec_nas_msg; - pdu_session_establishment_accept_msg_t psea_msg; - uint8_t *curPtr = buffer; - sec_nas_hdr.epd = *curPtr++; - sec_nas_hdr.sht = *curPtr++; - uint32_t tmp; - memcpy(&tmp, buffer, sizeof(tmp)); - sec_nas_hdr.mac = htonl(tmp); - curPtr += sizeof(sec_nas_hdr.mac); - sec_nas_hdr.sqn = *curPtr++; - sec_nas_msg.epd = *curPtr++; - sec_nas_msg.sht = *curPtr++; - sec_nas_msg.msg_type = *curPtr++; - sec_nas_msg.payload_type = *curPtr++; - sec_nas_msg.payload_len = getShort(curPtr); - curPtr += sizeof(sec_nas_msg.payload_len); - /* Mandatory Presence IEs */ - psea_msg.epd = *curPtr++; - psea_msg.pdu_id = *curPtr++; - psea_msg.pti = *curPtr++; - psea_msg.msg_type = *curPtr++; - psea_msg.pdu_type = *curPtr & 0x0f; - psea_msg.ssc_mode = (*curPtr++ & 0xf0) >> 4; - psea_msg.qos_rules.length = getShort(curPtr); - curPtr += sizeof(psea_msg.qos_rules.length); - /* Supports the capture of only one QoS Rule, it should be changed for multiple QoS Rules */ - qos_rule_t qos_rule; - qos_rule.id = *curPtr++; - qos_rule.length = getShort(curPtr); - curPtr += sizeof(qos_rule.length); - qos_rule.oc = (*(curPtr)&0xE0) >> 5; - qos_rule.dqr = (*(curPtr)&0x10) >> 4; - qos_rule.nb_pf = *curPtr++ & 0x0F; - - if(qos_rule.nb_pf) { - packet_filter_t pf; - - if(qos_rule.oc == ROC_CREATE_NEW_QOS_RULE || - qos_rule.oc == ROC_MODIFY_QOS_RULE_ADD_PF || - qos_rule.oc == ROC_MODIFY_QOS_RULE_REPLACE_PF) { - pf.pf_type.type_1.pf_dir = (*curPtr & 0x30) >> 4; - pf.pf_type.type_1.pf_id = *curPtr++ & 0x0F; - pf.pf_type.type_1.length = *curPtr++; - curPtr += (qos_rule.nb_pf * pf.pf_type.type_1.length); /* Ommit the Packet filter List */ - } else if (qos_rule.oc == ROC_MODIFY_QOS_RULE_DELETE_PF) { - curPtr += qos_rule.nb_pf; - } - } - - qos_rule.prcd = *curPtr++; - qos_rule.qfi = *curPtr++; - psea_msg.sess_ambr.length = *curPtr++; - curPtr += psea_msg.sess_ambr.length; /* Ommit the Seassion-AMBR */ - - /* Optional Presence IEs */ - while (curPtr < buffer + msg_length) { - uint8_t psea_iei = *curPtr++; - switch (psea_iei) { - case IEI_5GSM_CAUSE: /* Ommited */ - LOG_T(NAS, "PDU SESSION ESTABLISHMENT ACCEPT - Received 5GSM Cause IEI\n"); - curPtr++; - break; - - case IEI_PDU_ADDRESS: - LOG_T(NAS, "PDU SESSION ESTABLISHMENT ACCEPT - Received PDU Address IE\n"); - psea_msg.pdu_addr_ie.pdu_length = *curPtr++; - - /* Octet 3 */ - // PDU type (3 bits) - psea_msg.pdu_addr_ie.pdu_type = *curPtr & 0x07; - // SMF's IPv6 link local address (1 bit) - uint8_t si6lla = (*curPtr >> 3) & 0x01; - if (si6lla) - LOG_E(NAS, "SMF's IPv6 link local address is not handled\n"); - curPtr++; - - /* Octet 4 to n */ - // PDU address information - uint8_t *addr = psea_msg.pdu_addr_ie.pdu_addr_oct; - if (psea_msg.pdu_addr_ie.pdu_type == PDU_SESSION_TYPE_IPV4) { - for (int i = 0; i < IPv4_ADDRESS_LENGTH; ++i) - addr[i] = *curPtr++; - char ip[20]; - capture_ipv4_addr(&addr[0], ip, sizeof(ip)); - tun_config(1, ip, NULL, "oaitun_ue"); - setup_ue_ipv4_route(1, ip, "oaitun_ue"); - } else if (psea_msg.pdu_addr_ie.pdu_type == PDU_SESSION_TYPE_IPV6) { - for (int i = 0; i < IPv6_INTERFACE_ID_LENGTH; ++i) - addr[i] = *curPtr++; - char ipv6[40]; - capture_ipv6_addr(addr, ipv6, sizeof(ipv6)); - tun_config(1, NULL, ipv6, "oaitun_ue"); - } else if (psea_msg.pdu_addr_ie.pdu_type == PDU_SESSION_TYPE_IPV4V6) { - // 24.501 Sec 9.11.4.10: "If the PDU session type value indicates - // IPv4v6, the PDU address information in octet 4 to octet 11 - // contains an interface identifier for the IPv6 link local address - // and in octet 12 to octet 15 contains an IPv4 address." - for (int i = 0; i < IPv4_ADDRESS_LENGTH + IPv6_INTERFACE_ID_LENGTH; ++i) - addr[i] = *curPtr++; - char ipv6[40]; - capture_ipv6_addr(addr, ipv6, sizeof(ipv6)); - char ipv4[20]; - capture_ipv4_addr(&addr[IPv6_INTERFACE_ID_LENGTH], ipv4, sizeof(ipv4)); - tun_config(1, ipv4, ipv6, "oaitun_ue"); - setup_ue_ipv4_route(1, ipv4, "oaitun_ue"); - } else { - LOG_E(NAS, "unknown/unhandled PDU session establishment accept PDU type %d\n", psea_msg.pdu_addr_ie.pdu_type); - curPtr += psea_msg.pdu_addr_ie.pdu_length; - } - break; - - case IEI_RQ_TIMER_VALUE: /* Ommited */ - LOG_T(NAS, "PDU SESSION ESTABLISHMENT ACCEPT - Received RQ timer value IE\n"); - curPtr++; /* TS 24.008 10.5.7.3 */ - break; - - case IEI_SNSSAI: { - LOG_T(NAS, "PDU SESSION ESTABLISHMENT ACCEPT - Received S-NSSAI IE\n"); - uint8_t snssai_length = *curPtr; - curPtr += (snssai_length + sizeof(snssai_length)); - break; - } - - case IEI_ALWAYSON_PDU: /* Ommited */ - LOG_T(NAS, "PDU SESSION ESTABLISHMENT ACCEPT - Received Always-on PDU Session indication IE\n"); - curPtr++; - break; - - case IEI_MAPPED_EPS: { - LOG_T(NAS, "PDU SESSION ESTABLISHMENT ACCEPT - Received Mapped EPS bearer context IE\n"); - uint16_t mapped_eps_length = getShort(curPtr); - curPtr += mapped_eps_length; - break; - } - - case IEI_EAP_MSG: { - LOG_T(NAS, "PDU SESSION ESTABLISHMENT ACCEPT - Received EAP message IE\n"); - uint16_t eap_length = getShort(curPtr); - curPtr += (eap_length + sizeof(eap_length)); - break; - } - - case IEI_AUTH_QOS_DESC: { - LOG_T(NAS, "PDU SESSION ESTABLISHMENT ACCEPT - Received Authorized QoS flow descriptions IE\n"); - psea_msg.qos_fd_ie.length = getShort(curPtr); - curPtr += (psea_msg.qos_fd_ie.length + sizeof(psea_msg.qos_fd_ie.length)); - break; - } - - case IEI_EXT_CONF_OPT: { - LOG_T(NAS, "PDU SESSION ESTABLISHMENT ACCEPT - Received Extended protocol configuration options IE\n"); - psea_msg.ext_pp_ie.length = getShort(curPtr); - curPtr += (psea_msg.ext_pp_ie.length + sizeof(psea_msg.ext_pp_ie.length)); - break; - } - - case IEI_DNN: { - LOG_T(NAS, "PDU SESSION ESTABLISHMENT ACCEPT - Received DNN IE\n"); - psea_msg.dnn_ie.dnn_length = *curPtr++; - char apn[APN_MAX_LEN]; - - if(psea_msg.dnn_ie.dnn_length <= APN_MAX_LEN && - psea_msg.dnn_ie.dnn_length >= APN_MIN_LEN) { - memcpy(apn, curPtr, psea_msg.dnn_ie.dnn_length); - LOG_T(NAS, "PDU SESSION ESTABLISHMENT ACCEPT - APN: %s\n", apn); - } else - LOG_E(NAS, "PDU SESSION ESTABLISHMENT ACCEPT - DNN IE has invalid length\n"); - - curPtr = buffer + msg_length; // we force stop processing - break; - } - - default: - LOG_T(NAS, "PDU SESSION ESTABLISHMENT ACCEPT - Not known IE\n"); - curPtr = buffer + msg_length; // we force stop processing - break; - } - } - - set_qfi_pduid(qos_rule.qfi, psea_msg.pdu_id); - return; -} diff --git a/openair3/NAS/COMMON/IES/AuthenticationResponseParameter.c b/openair3/NAS/COMMON/IES/AuthenticationResponseParameter.c index 3ac3e60a3d..85bcaeb1b2 100644 --- a/openair3/NAS/COMMON/IES/AuthenticationResponseParameter.c +++ b/openair3/NAS/COMMON/IES/AuthenticationResponseParameter.c @@ -53,7 +53,10 @@ int decode_authentication_response_parameter(AuthenticationResponseParameter *au #endif return decoded; } -int encode_authentication_response_parameter(AuthenticationResponseParameter *authenticationresponseparameter, uint8_t iei, uint8_t *buffer, uint32_t len) +int encode_authentication_response_parameter(const AuthenticationResponseParameter *authenticationresponseparameter, + uint8_t iei, + uint8_t *buffer, + uint32_t len) { uint8_t *lenPtr; uint32_t encoded = 0; diff --git a/openair3/NAS/COMMON/IES/AuthenticationResponseParameter.h b/openair3/NAS/COMMON/IES/AuthenticationResponseParameter.h index 4e3dd33d5b..75a2dd9a2d 100644 --- a/openair3/NAS/COMMON/IES/AuthenticationResponseParameter.h +++ b/openair3/NAS/COMMON/IES/AuthenticationResponseParameter.h @@ -35,7 +35,10 @@ typedef struct AuthenticationResponseParameter_tag { OctetString res; } AuthenticationResponseParameter; -int encode_authentication_response_parameter(AuthenticationResponseParameter *authenticationresponseparameter, uint8_t iei, uint8_t *buffer, uint32_t len); +int encode_authentication_response_parameter(const AuthenticationResponseParameter *authenticationresponseparameter, + uint8_t iei, + uint8_t *buffer, + uint32_t len); int decode_authentication_response_parameter(AuthenticationResponseParameter *authenticationresponseparameter, uint8_t iei, uint8_t *buffer, uint32_t len); diff --git a/openair3/NAS/COMMON/IES/CMakeLists.txt b/openair3/NAS/COMMON/IES/CMakeLists.txt index 99df08e7b0..67cc9d782a 100644 --- a/openair3/NAS/COMMON/IES/CMakeLists.txt +++ b/openair3/NAS/COMMON/IES/CMakeLists.txt @@ -1,9 +1,6 @@ -add_library(fgs_ies_lib OBJECT - NasKeySetIdentifier.c - FGSMobileIdentity.c +add_library(nas_common_ies_lib OBJECT + AuthenticationResponseParameter.c + NasKeySetIdentifier.c ) -target_include_directories(fgs_ies_lib PUBLIC - ${CMAKE_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR} -) +target_include_directories(nas_common_ies_lib PUBLIC .) diff --git a/openair3/NAS/COMMON/IES/ExtendedProtocolDiscriminator.c b/openair3/NAS/COMMON/IES/ExtendedProtocolDiscriminator.c deleted file mode 100644 index e3b4bd021a..0000000000 --- a/openair3/NAS/COMMON/IES/ExtendedProtocolDiscriminator.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - - -/*! \file ExtendedProtocolDiscriminator.c - -\brief Extended protocol discriminator for registration request procedures -\author Yoshio INOUE, Masayuki HARADA -\email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com -\date 2020 -\version 0.1 -*/ - -#include -#include -#include - - -#include "TLVEncoder.h" -#include "TLVDecoder.h" -#include "ExtendedProtocolDiscriminator.h" - -int encode_ex_protocol_discriminator(ExtendedProtocolDiscriminator *exprotocoldiscriminator, uint8_t iei, uint8_t *buffer, uint32_t len) -{ - return 0; -} - -int decode_ex_protocol_discriminator(ExtendedProtocolDiscriminator *exprotocoldiscriminator, uint8_t iei, uint8_t *buffer, uint32_t len) -{ - return 0; -} - diff --git a/openair3/NAS/COMMON/IES/ExtendedProtocolDiscriminator.h b/openair3/NAS/COMMON/IES/ExtendedProtocolDiscriminator.h deleted file mode 100644 index 3bf1f6ec8f..0000000000 --- a/openair3/NAS/COMMON/IES/ExtendedProtocolDiscriminator.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - - -/*! \file ExtendedProtocolDiscriminator.h - -\brief Extended protocol discriminator for registration request procedures -\author Yoshio INOUE, Masayuki HARADA -\email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com -\date 2020 -\version 0.1 -*/ - -#include -#include -#include - -#include "OctetString.h" - -#ifndef EXTENDED_PROTOCOL_DISCRIMINATOR_H_ -#define EXTENDED_PROTOCOL_DISCRIMINATOR_H_ - -typedef uint8_t ExtendedProtocolDiscriminator; - -int encode_ex_protocol_discriminator(ExtendedProtocolDiscriminator *exprotocoldiscriminator, uint8_t iei, uint8_t *buffer, uint32_t len); - -int decode_ex_protocol_discriminator(ExtendedProtocolDiscriminator *exprotocoldiscriminator, uint8_t iei, uint8_t *buffer, uint32_t len); - -#endif /* EXTENDED PROTOCOL DISCRIMINATOR_H_ */ - diff --git a/openair3/NAS/COMMON/IES/NasKeySetIdentifier.c b/openair3/NAS/COMMON/IES/NasKeySetIdentifier.c index 82fe69d79e..368e66911b 100644 --- a/openair3/NAS/COMMON/IES/NasKeySetIdentifier.c +++ b/openair3/NAS/COMMON/IES/NasKeySetIdentifier.c @@ -50,7 +50,7 @@ int decode_nas_key_set_identifier(NasKeySetIdentifier *naskeysetidentifier, uint /** * @brief Encode the NAS key set identifier in one byte */ -uint8_t encode_nas_key_set_identifier(NasKeySetIdentifier *naskeysetidentifier, uint8_t iei) +uint8_t encode_nas_key_set_identifier(const NasKeySetIdentifier *naskeysetidentifier, uint8_t iei) { #if defined (NAS_DEBUG) dump_nas_key_set_identifier_xml(naskeysetidentifier, iei); diff --git a/openair3/NAS/COMMON/IES/NasKeySetIdentifier.h b/openair3/NAS/COMMON/IES/NasKeySetIdentifier.h index 5f6b445fc4..bdc1506cb2 100644 --- a/openair3/NAS/COMMON/IES/NasKeySetIdentifier.h +++ b/openair3/NAS/COMMON/IES/NasKeySetIdentifier.h @@ -39,7 +39,7 @@ typedef struct NasKeySetIdentifier_tag { uint8_t naskeysetidentifier:3; } NasKeySetIdentifier; -uint8_t encode_nas_key_set_identifier(NasKeySetIdentifier *naskeysetidentifier, uint8_t iei); +uint8_t encode_nas_key_set_identifier(const NasKeySetIdentifier *naskeysetidentifier, uint8_t iei); void dump_nas_key_set_identifier_xml(NasKeySetIdentifier *naskeysetidentifier, uint8_t iei); diff --git a/openair3/NAS/COMMON/IES/SpareHalfOctet.c b/openair3/NAS/COMMON/IES/SpareHalfOctet.c deleted file mode 100644 index 60c45e07c2..0000000000 --- a/openair3/NAS/COMMON/IES/SpareHalfOctet.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - - -/*! \file SpareHalfOctet.c - -\brief registration request procedures for gNB -\author Yoshio INOUE, Masayuki HARADA -\email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com -\date 2020 -\version 0.1 -*/ - -#include -#include -#include - - -#include "TLVEncoder.h" -#include "TLVDecoder.h" -#include "SpareHalfOctet.h" - -int decode_spare_half_octet(SpareHalfOctet *sparehalfoctet, uint8_t iei, uint8_t *buffer, uint32_t len) -{ - return 0; -} - -int encode_spare_half_octet(SpareHalfOctet *sparehalfoctet, uint8_t iei, uint8_t *buffer, uint32_t len) -{ - return 0; -} - diff --git a/openair3/NAS/COMMON/IES/SpareHalfOctet.h b/openair3/NAS/COMMON/IES/SpareHalfOctet.h deleted file mode 100644 index fbf410d4f8..0000000000 --- a/openair3/NAS/COMMON/IES/SpareHalfOctet.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - - -/*! \file SpareHalfOctet.h - -\brief registration request procedures for gNB -\author Yoshio INOUE, Masayuki HARADA -\email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com -\date 2020 -\version 0.1 -*/ - -#include -#include -#include - -#include "OctetString.h" - -#ifndef SPARE_HALF_OCTET_H_ -#define SPARE_HALF_OCTET_H_ - -#define SPARE_HALF_OCTET_MINIMUM_LENGTH 1 -#define SPARE_HALF_OCTET_MAXIMUM_LENGTH 1 - -typedef uint8_t SpareHalfOctet; - -int encode_spare_half_octet(SpareHalfOctet *sparehalfoctet, uint8_t iei, uint8_t *buffer, uint32_t len); - -int decode_spare_half_octet(SpareHalfOctet *sparehalfoctet, uint8_t iei, uint8_t *buffer, uint32_t len); - -#endif /* SPARE HALF OCTET_H_ */ - diff --git a/openair3/NAS/COMMON/NR_NAS_defs.h b/openair3/NAS/COMMON/NR_NAS_defs.h deleted file mode 100644 index f5510e5392..0000000000 --- a/openair3/NAS/COMMON/NR_NAS_defs.h +++ /dev/null @@ -1,386 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Author and copyright: Laurent Thomas, open-cells.com - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ -#ifndef NR_NAS_DEFS_H -#define NR_NAS_DEFS_H - -#include -#include - -/* TS 24.007 possible L3 formats: - Table 11.1: Formats of information elements - Format Meaning IEI present LI present Value part present - T Type only yes no no - V Value only no no yes - TV Type and Value yes no yes - LV Length and Value no yes yes - TLV Type, Length and Value yes yes yes - LV-E Length and Value no yes yes - TLV-E Type, Length and Value yes yes yes -*/ - -/* Map task id to printable name. */ -typedef struct { - int id; - char text[256]; -} text_info_t; - -static inline const char * idToText(const text_info_t* table, int size, int id) { - for(int i=0; i TS 24.007 -typedef enum { - SGSsessionmanagementmessages=0x2e, //LTEbox: 0xC0 ??? - SGSmobilitymanagementmessages=0x7e, -} Extendedprotocoldiscriminator_t; - -#define FOREACH_TYPE(TYPE_DEF) \ - TYPE_DEF(REGISTRATION_REQUEST, 0x41) \ - TYPE_DEF(REGISTRATION_ACCEPT, 0x42) \ - TYPE_DEF(REGISTRATION_COMPLETE, 0x43) \ - TYPE_DEF(REGISTRATION_REJECT, 0x44) \ - TYPE_DEF(FGS_DEREGISTRATION_REQUEST_UE_ORIGINATING, 0x45) \ - TYPE_DEF(FGS_DEREGISTRATION_ACCEPT_UE_ORIGINATING, 0x46) \ - TYPE_DEF(DeregistrationrequestUEterminated, 0x47) \ - TYPE_DEF(DeregistrationacceptUEterminated, 0x48) \ - TYPE_DEF(FGS_SERVICE_REQUEST, 0x4c) \ - TYPE_DEF(FGS_SERVICE_REJECT, 0x4d) \ - TYPE_DEF(FGS_SERVICE_ACCEPT, 0x4e) \ - TYPE_DEF(Controlplaneservicerequest, 0x4f) \ - TYPE_DEF(Networkslicespecificauthenticationcommand, 0x50) \ - TYPE_DEF(Networkslicespecificauthenticationcomplete, 0x51) \ - TYPE_DEF(Networkslicespecificauthenticationresult, 0x52) \ - TYPE_DEF(Configurationupdatecommand, 0x54) \ - TYPE_DEF(Configurationupdatecomplete, 0x55) \ - TYPE_DEF(FGS_AUTHENTICATION_REQUEST, 0x56) \ - TYPE_DEF(FGS_AUTHENTICATION_RESPONSE, 0x57) \ - TYPE_DEF(Authenticationreject, 0x58) \ - TYPE_DEF(Authenticationfailure, 0x59) \ - TYPE_DEF(Authenticationresult, 0x5a) \ - TYPE_DEF(FGS_IDENTITY_REQUEST, 0x5b) \ - TYPE_DEF(FGS_IDENTITY_RESPONSE, 0x5c) \ - TYPE_DEF(FGS_SECURITY_MODE_COMMAND, 0x5d) \ - TYPE_DEF(FGS_SECURITY_MODE_COMPLETE, 0x5e) \ - TYPE_DEF(Securitymodereject, 0x5f) \ - TYPE_DEF(SGMMstatus, 0x64) \ - TYPE_DEF(Notification, 0x65) \ - TYPE_DEF(Notificationresponse, 0x66) \ - TYPE_DEF(FGS_UPLINK_NAS_TRANSPORT, 0x67) \ - TYPE_DEF(FGS_DOWNLINK_NAS_TRANSPORT, 0x68) \ - TYPE_DEF(FGS_PDU_SESSION_ESTABLISHMENT_REQ, 0xc1) \ - TYPE_DEF(FGS_PDU_SESSION_ESTABLISHMENT_ACC, 0xc2) \ - TYPE_DEF(FGS_PDU_SESSION_ESTABLISHMENT_REJ, 0xc3) \ - TYPE_DEF(PDUsessionauthenticationcommand, 0xc5) \ - TYPE_DEF(PDUsessionauthenticationcomplete, 0xc6) \ - TYPE_DEF(PDUsessionauthenticationresult, 0xc7) \ - TYPE_DEF(PDUsessionmodificationrequest, 0xc9) \ - TYPE_DEF(PDUsessionmodificationreject, 0xca) \ - TYPE_DEF(PDUsessionmodificationcommand, 0xcb) \ - TYPE_DEF(PDUsessionmodificationcomplete, 0xcc) \ - TYPE_DEF(PDUsessionmodificationcommandreject, 0xcd) \ - TYPE_DEF(PDUsessionreleaserequest, 0xd1) \ - TYPE_DEF(PDUsessionreleasereject, 0xd2) \ - TYPE_DEF(PDUsessionreleasecommand, 0xd3) \ - TYPE_DEF(PDUsessionreleasecomplete, 0xd4) \ - TYPE_DEF(SGSMstatus, 0xd6) - -static const text_info_t message_text_info[] = { - FOREACH_TYPE(TO_TEXT) -}; - -//! Tasks id of each task -typedef enum { - FOREACH_TYPE(TO_ENUM) -} SGSmobilitymanagementmessages_t; - -// TS 24.501 -typedef enum { - PLAIN_5GS_MSG = 0, - INTEGRITY_PROTECTED = 1, - INTEGRITY_PROTECTED_AND_CIPHERED = 2, - INTEGRITY_PROTECTED_WITH_NEW_SECU_CTX = 3, - INTEGRITY_PROTECTED_AND_CIPHERED_WITH_NEW_SECU_CTX = 4, -} Security_header_t; - -typedef enum { - SUCI=1, - SGGUTI, - IMEI, - SGSTMSI, - IMEISV, - MACaddress, - EUI64, -} identitytype_t; - - -// table 9.11.3.2.1 -#define FOREACH_CAUSE(CAUSE_DEF) \ - CAUSE_DEF(Illegal_UE,0x3 )\ - CAUSE_DEF(PEI_not_accepted,0x5 )\ - CAUSE_DEF(Illegal_ME,0x6 )\ - CAUSE_DEF(SGS_services_not_allowed,0x7 )\ - CAUSE_DEF(UE_identity_cannot_be_derived_by_the_network,0x9 )\ - CAUSE_DEF(Implicitly_de_registered,0x0a )\ - CAUSE_DEF(PLMN_not_allowed,0x0b )\ - CAUSE_DEF(Tracking_area_not_allowed,0x0c )\ - CAUSE_DEF(Roaming_not_allowed_in_this_tracking_area,0x0d )\ - CAUSE_DEF(No_suitable_cells_in_tracking_area,0x0f )\ - CAUSE_DEF(MAC_failure,0x14 )\ - CAUSE_DEF(Synch_failure,0x15 )\ - CAUSE_DEF(Congestion,0x16 )\ - CAUSE_DEF(UE_security_capabilities_mismatch,0x17 )\ - CAUSE_DEF(Security_mode_rejected_unspecified,0x18 )\ - CAUSE_DEF(Non_5G_authentication_unacceptable,0x1a )\ - CAUSE_DEF(N1_mode_not_allowed,0x1b )\ - CAUSE_DEF(Restricted_service_area,0x1c )\ - CAUSE_DEF(Redirection_to_EPC_required,0x1f )\ - CAUSE_DEF(LADN_not_available,0x2b )\ - CAUSE_DEF(No_network_slices_available,0x3e )\ - CAUSE_DEF(Maximum_number_of_PDU_sessions_reached,0x41 )\ - CAUSE_DEF(Insufficient_resources_for_specific_slice_and_DNN,0x43 )\ - CAUSE_DEF(Insufficient_resources_for_specific_slice,0x45 )\ - CAUSE_DEF(ngKSI_already_in_use,0x47 )\ - CAUSE_DEF(Non_3GPP_access_to_5GCN_not_allowed,0x48 )\ - CAUSE_DEF(Serving_network_not_authorized,0x49 )\ - CAUSE_DEF(Temporarily_not_authorized_for_this_SNPN,0x4A )\ - CAUSE_DEF(Permanently_not_authorized_for_this_SNPN,0x4b )\ - CAUSE_DEF(Not_authorized_for_this_CAG_or_authorized_for_CAG_cells_only,0x4c )\ - CAUSE_DEF(Wireline_access_area_not_allowed,0x4d )\ - CAUSE_DEF(Payload_was_not_forwarded,0x5a )\ - CAUSE_DEF(DNN_not_supported_or_not_subscribed_in_the_slice,0x5b )\ - CAUSE_DEF(Insufficient_user_plane_resources_for_the_PDU_session,0x5c )\ - CAUSE_DEF(Semantically_incorrect_message,0x5f )\ - CAUSE_DEF(Invalid_mandatory_information,0x60 )\ - CAUSE_DEF(Message_type_non_existent_or_not_implemented,0x61 )\ - CAUSE_DEF(Message_type_not_compatible_with_the_protocol_state,0x62 )\ - CAUSE_DEF(Information_element_non_existent_or_not_implemented,0x63 )\ - CAUSE_DEF(Conditional_IE_error,0x64 )\ - CAUSE_DEF(Message_not_compatible_with_the_protocol_state,0x65 )\ - CAUSE_DEF(Protocol_error_unspecified,0x67 ) - -/* Map task id to printable name. */ - -#define CAUSE_TEXT(LabEl, nUmID) {nUmID, #LabEl}, - -static const text_info_t cause_text_info[] = { - FOREACH_CAUSE(TO_TEXT) -}; - -#define CAUSE_ENUM(LabEl, nUmID ) LabEl = nUmID, -//! Tasks id of each task -typedef enum { - FOREACH_CAUSE(TO_ENUM) -} cause_id_t; - -//_table_9.11.4.2.1:_5GSM_cause_information_element -#define FOREACH_CAUSE_SECU(CAUSE_SECU_DEF) \ - CAUSE_SECU_DEF(Security_Operator_determined_barring,0x08 )\ - CAUSE_SECU_DEF(Security_Insufficient_resources,0x1a )\ - CAUSE_SECU_DEF(Security_Missing_or_unknown_DNN,0x1b )\ - CAUSE_SECU_DEF(Security_Unknown_PDU_session_type,0x1c )\ - CAUSE_SECU_DEF(Security_User_authentication_or_authorization_failed,0x1d )\ - CAUSE_SECU_DEF(Security_Request_rejected_unspecified,0x1f )\ - CAUSE_SECU_DEF(Security_Service_option_not_supported,0x20 )\ - CAUSE_SECU_DEF(Security_Requested_service_option_not_subscribed,0x21 )\ - CAUSE_SECU_DEF(Security_Service_option_temporarily_out_of_order,0x22 )\ - CAUSE_SECU_DEF(Security_PTI_already_in_use,0x23 )\ - CAUSE_SECU_DEF(Security_Regular_deactivation,0x24 )\ - CAUSE_SECU_DEF(Security_Network_failure,0x26 )\ - CAUSE_SECU_DEF(Security_Reactivation_requested,0x27 )\ - CAUSE_SECU_DEF(Security_Semantic_error_in_the_TFT_operation,0x29 )\ - CAUSE_SECU_DEF(Security_Syntactical_error_in_the_TFT_operation,0x2a )\ - CAUSE_SECU_DEF(Security_Invalid_PDU_session_identity,0x2b )\ - CAUSE_SECU_DEF(Security_Semantic_errors_in_packet_filter,0x2c )\ - CAUSE_SECU_DEF(Security_Syntactical_error_in_packet_filter,0x2d )\ - CAUSE_SECU_DEF(Security_Out_of_LADN_service_area,0x2e )\ - CAUSE_SECU_DEF(Security_PTI_mismatch,0x2f )\ - CAUSE_SECU_DEF(Security_PDU_session_type_IPv4_only_allowed,0x32 )\ - CAUSE_SECU_DEF(Security_PDU_session_type_IPv6_only_allowed,0x33 )\ - CAUSE_SECU_DEF(Security_PDU_session_does_not_exist,0x36 )\ - CAUSE_SECU_DEF(Security_PDU_session_type_IPv4v6_only_allowed,0x39 )\ - CAUSE_SECU_DEF(Security_PDU_session_type_Unstructured_only_allowed,0x3a )\ - CAUSE_SECU_DEF(Security_PDU_session_type_Ethernet_only_allowed,0x3d )\ - CAUSE_SECU_DEF(Security_Insufficient_resources_for_specific_slice_and_DNN,0x43 )\ - CAUSE_SECU_DEF(Security_Not_supported_SSC_mode,0x44 )\ - CAUSE_SECU_DEF(Security_Insufficient_resources_for_specific_slice,0x45 )\ - CAUSE_SECU_DEF(Security_Missing_or_unknown_DNN_in_a_slice,0x46 )\ - CAUSE_SECU_DEF(Security_Invalid_PTI_value,0x51 )\ - CAUSE_SECU_DEF(Security_Maximum_data_rate_per_UE_for_user_plane_integrity_protection_is_too_low,0x52 )\ - CAUSE_SECU_DEF(Security_Semantic_error_in_the_QoS_operation,0x53 )\ - CAUSE_SECU_DEF(Security_Syntactical_error_in_the_QoS_operation,0x54 )\ - CAUSE_SECU_DEF(Security_Invalid_mapped_EPS_bearer_identity,0x55 )\ - CAUSE_SECU_DEF(Security_Semantically_incorrect_message,0x5f )\ - CAUSE_SECU_DEF(Security_Invalid_mandatory_information,0x60 )\ - CAUSE_SECU_DEF(Security_Message_type_non_existent_or_not_implemented,0x61 )\ - CAUSE_SECU_DEF(Security_Message_type_not_compatible_with_the_protocol_state,0x62 )\ - CAUSE_SECU_DEF(Security_Information_element_non_existent_or_not_implemented,0x63 )\ - CAUSE_SECU_DEF(Security_Conditional_IE_error,0x64 )\ - CAUSE_SECU_DEF(Security_Message_not_compatible_with_the_protocol_state,0x65 )\ - CAUSE_SECU_DEF(Security_Protocol_error_unspecified,0x6f ) - -static const text_info_t cause_secu_text_info[] = { - FOREACH_CAUSE_SECU(TO_TEXT) -}; - -//! Tasks id of each task -typedef enum { - FOREACH_CAUSE_SECU(TO_ENUM) -} cause_secu_id_t; - -// IEI (information element identifier) are spread in each message definition -#define IEI_NULL 0x00 -#define IEI_RAND 0x21 -#define IEI_AUTN 0x20 -#define IEI_EAP 0x78 -#define IEI_AuthenticationResponse 0x2d - -//TS 24.501 sub layer states for UE -// for network side, only 5GMMderegistered, 5GMMderegistered_initiated, 5GMMregistered, 5GMMservice_request_initiated are valid -typedef enum { - SGMMnull, - SGMMderegistered, - SGMMderegistered_initiated, - SGMMregistered, - SGMMregistered_initiated, - SGMMservice_request_initiated, -} SGMM_UE_states; - -typedef struct { - Extendedprotocoldiscriminator_t epd:8; - Security_header_t sh:8; - SGSmobilitymanagementmessages_t mt:8; -} SGScommonHeader_t; - -typedef struct { - Extendedprotocoldiscriminator_t epd:8; - Security_header_t sh:8; - SGSmobilitymanagementmessages_t mt:8; - identitytype_t it:8; -} Identityrequest_t; - -// the message continues with the identity value, depending on identity type, see TS 14.501, 9.11.3.4 -typedef struct __attribute__((packed)) { - Extendedprotocoldiscriminator_t epd:8; - Security_header_t sh:8; - SGSmobilitymanagementmessages_t mt:8; - uint16_t len; -} -Identityresponse_t; - -typedef struct __attribute__((packed)) { - Identityresponse_t common; - identitytype_t mi:8; - unsigned int supiFormat:4; - unsigned int identityType:4; - unsigned int mcc1:4; - unsigned int mcc2:4; - unsigned int mcc3:4; - unsigned int mnc3:4; - unsigned int mnc1:4; - unsigned int mnc2:4; - unsigned int routing1:4; - unsigned int routing2:4; - unsigned int routing3:4; - unsigned int routing4:4; - unsigned int protectScheme:4; - unsigned int spare:4; - uint8_t hplmnId; -} -IdentityresponseIMSI_t; - -typedef struct __attribute__((packed)) { - Extendedprotocoldiscriminator_t epd:8; - Security_header_t sh:8; - SGSmobilitymanagementmessages_t mt:8; - unsigned int ngKSI:4; - unsigned int spare:4; - unsigned int ABBALen:8; - unsigned int ABBA:16; - uint8_t ieiRAND; - uint8_t RAND[16]; - uint8_t ieiAUTN; - uint8_t AUTNlen; - uint8_t AUTN[16]; -} -authenticationrequestHeader_t; - -typedef struct __attribute__((packed)) { - Extendedprotocoldiscriminator_t epd:8; - Security_header_t sh:8; - SGSmobilitymanagementmessages_t mt:8; - uint8_t iei; - uint8_t RESlen; - uint8_t RES[16]; -} authenticationresponse_t; - -//AUTHENTICATION RESULT - -typedef struct __attribute__((packed)) { - Extendedprotocoldiscriminator_t epd:8; - Security_header_t sh:8; - SGSmobilitymanagementmessages_t mt:8; - - unsigned int selectedNASsecurityalgorithms; - unsigned int ngKSI:4; //ngKSI NAS key set identifier 9.11.3.32 - unsigned int spare:4; - // LV 3-9 bytes Replayed UE security capabilities UE security capability 9.11.3.54 - - /* optional - TV (E-, 1 byte) Oprional IMEISV request IMEISV request 9.11.3.28 - TV (57, 2 bytes ) Selected EPS NAS security algorithms EPS NAS security algorithms 9.11.3.25 - TLV (36, 3 bytes) Additional 5G security information Additional 5G security information 9.11.3.12 - TLV-E (78,, 7-1503 bytes) EAP message EAP message 9.11.2.2 - TLV (38, 4-n)ABBA ABBA 9.11.3.10 - TLV (19, 4-7) Replayed S1 UE security capabilities S1 UE security capability 9.11.3.48A - */ - -} securityModeCommand_t; - -typedef struct __attribute__((packed)) { - Extendedprotocoldiscriminator_t epd: 8; - Security_header_t sh: 8; - SGSmobilitymanagementmessages_t mt: 8; -} deregistrationRequestUEOriginating_t; - -typedef struct { - uicc_t *uicc; -} nr_user_nas_t; - -#define STATIC_ASSERT(test_for_true) _Static_assert((test_for_true), "(" #test_for_true ") failed") -#define myCalloc(var, type) type * var=(type*)calloc(sizeof(type),1); -#define arrayCpy(tO, FroM) STATIC_ASSERT(sizeof(tO) == sizeof(FroM)) ; memcpy(tO, FroM, sizeof(tO)) -int resToresStar(uint8_t *msg, const uicc_t* uicc); - -int identityResponse(void **msg, nr_user_nas_t *UE); -int authenticationResponse(void **msg, nr_user_nas_t *UE); -void servingNetworkName(uint8_t *msg, char * imsiStr, int nmc_size); - -#endif diff --git a/openair3/NAS/COMMON/UTIL/CMakeLists.txt b/openair3/NAS/COMMON/UTIL/CMakeLists.txt new file mode 100644 index 0000000000..dc29dff207 --- /dev/null +++ b/openair3/NAS/COMMON/UTIL/CMakeLists.txt @@ -0,0 +1,6 @@ +add_library(nas_utils OBJECT + TLVDecoder.c + OctetString.c +) + +target_include_directories(nas_utils PRIVATE .) diff --git a/openair3/NAS/COMMON/UTIL/OctetString.c b/openair3/NAS/COMMON/UTIL/OctetString.c index 2f1b7b2c32..4afa522664 100644 --- a/openair3/NAS/COMMON/UTIL/OctetString.c +++ b/openair3/NAS/COMMON/UTIL/OctetString.c @@ -55,8 +55,7 @@ void free_octet_string(OctetString *octetstring) } } - -int encode_octet_string(OctetString *octetstring, uint8_t *buffer, uint32_t buflen) +int encode_octet_string(const OctetString *octetstring, uint8_t *buffer, uint32_t buflen) { if (octetstring != NULL) { if ((octetstring->value != NULL) && (octetstring->length > 0)) { @@ -71,7 +70,7 @@ int encode_octet_string(OctetString *octetstring, uint8_t *buffer, uint32_t bufl } } -int decode_octet_string(OctetString *octetstring, uint16_t pdulen, uint8_t *buffer, uint32_t buflen) +int decode_octet_string(OctetString *octetstring, uint16_t pdulen, const uint8_t *buffer, uint32_t buflen) { if (buflen < pdulen) return -1; diff --git a/openair3/NAS/COMMON/UTIL/OctetString.h b/openair3/NAS/COMMON/UTIL/OctetString.h index 2223b67ece..fcfe6d46b4 100644 --- a/openair3/NAS/COMMON/UTIL/OctetString.h +++ b/openair3/NAS/COMMON/UTIL/OctetString.h @@ -58,9 +58,9 @@ OctetString* dup_octet_string(OctetString*octetstring); void free_octet_string(OctetString *octetstring); -int encode_octet_string(OctetString *octetstring, uint8_t *buffer, uint32_t len); +int encode_octet_string(const OctetString *octetstring, uint8_t *buffer, uint32_t len); -int decode_octet_string(OctetString *octetstring, uint16_t pdulen, uint8_t *buffer, uint32_t buflen); +int decode_octet_string(OctetString *octetstring, uint16_t pdulen, const uint8_t *buffer, uint32_t buflen); char* dump_octet_string_xml(const OctetString * const octetstring); diff --git a/openair3/NAS/COMMON/UTIL/TLVEncoder.h b/openair3/NAS/COMMON/UTIL/TLVEncoder.h index a400d9e388..3b5fcfda3c 100644 --- a/openair3/NAS/COMMON/UTIL/TLVEncoder.h +++ b/openair3/NAS/COMMON/UTIL/TLVEncoder.h @@ -23,6 +23,7 @@ #define TLV_ENCODER_H_ #include // htonl, htons +#include // memcpy #define ENCODE_U8(buffer, value, size) \ do { \ diff --git a/openair3/NAS/COMMON/nr_common.c b/openair3/NAS/COMMON/nr_common.c deleted file mode 100644 index 6c935df4f1..0000000000 --- a/openair3/NAS/COMMON/nr_common.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Author and copyright: Laurent Thomas, open-cells.com - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -#include -#include -#include -#include - -void servingNetworkName(uint8_t *msg, char * imsiStr, int nmc_size) { - //SNN-network-identifier in TS 24.501 - // TS 24.501: If the MNC of the serving PLMN has two digits, then a zero is added at the beginning. - const char *format="5G:mnc000.mcc000.3gppnetwork.org"; - memcpy(msg,format, strlen(format)); - - if (nmc_size == 2) - memcpy(msg+7, imsiStr+3, 2); - else - memcpy(msg+6, imsiStr+3, 3); - - memcpy(msg+13, imsiStr, 3); -} - -int resToresStar(uint8_t *msg, const uicc_t* uicc) { - // TS 33.220 annex B.2 => FC=0x6B in TS 33.501 annex A.4 - //input S to KDF - uint8_t S[128]= {0}; - S[0]=0x6B; - uint8_t *ptr=S+1; - servingNetworkName(ptr, uicc->imsiStr, uicc->nmc_size); - *(uint16_t *)(ptr+strlen((char *)ptr))=htons(strlen((char *)ptr)); - ptr+=strlen((char *)ptr)+sizeof(uint16_t); - // add rand - memcpy(ptr, uicc->rand, sizeof(uicc->rand) ) ; - *(uint16_t *)(ptr+sizeof(uicc->rand))=htons(sizeof(uicc->rand)); - ptr+=sizeof(uicc->rand)+sizeof(uint16_t); - // add res - memcpy(ptr, uicc->milenage_res, sizeof(uicc->milenage_res) ) ; - *(uint16_t *)(ptr+sizeof(uicc->milenage_res))=htons(sizeof(uicc->milenage_res)); - ptr+=sizeof(uicc->milenage_res)+sizeof(uint16_t); - // S is done - uint8_t ckik[sizeof(uicc->ck) +sizeof(uicc->ik)]; - memcpy(ckik, uicc->ck, sizeof(uicc->ck)); - memcpy(ckik+sizeof(uicc->ck),uicc->ik, sizeof(uicc->ik)); - uint8_t out[32] = {0}; - assert(ptr-S == 32); - //kdf(S, ptr-S, ckik, 32, out, sizeof(out)); - byte_array_t data = {.buf = ckik, .len = 32}; - kdf(S, data, 32, out); - - memcpy(msg, out+16, 16); - return 16; -} diff --git a/openair3/NAS/NR_UE/5GS/5GMM/IES/CMakeLists.txt b/openair3/NAS/NR_UE/5GS/5GMM/IES/CMakeLists.txt new file mode 100644 index 0000000000..24ed3022a6 --- /dev/null +++ b/openair3/NAS/NR_UE/5GS/5GMM/IES/CMakeLists.txt @@ -0,0 +1,13 @@ +add_library(fgs_5gmm_ies_lib OBJECT + FGSMobileIdentity.c + FGSRegistrationType.c + FGSRegistrationResult.c + FGMMCapability.c + NrUESecurityCapability.c + FGCNasMessageContainer.c + SORTransparentContainer.c +) + +target_link_libraries(fgs_5gmm_ies_lib PUBLIC + nas_common_ies_lib +) diff --git a/openair3/NAS/COMMON/IES/FGCNasMessageContainer.c b/openair3/NAS/NR_UE/5GS/5GMM/IES/FGCNasMessageContainer.c similarity index 88% rename from openair3/NAS/COMMON/IES/FGCNasMessageContainer.c rename to openair3/NAS/NR_UE/5GS/5GMM/IES/FGCNasMessageContainer.c index 4e8de951a5..d06521c88c 100644 --- a/openair3/NAS/COMMON/IES/FGCNasMessageContainer.c +++ b/openair3/NAS/NR_UE/5GS/5GMM/IES/FGCNasMessageContainer.c @@ -32,7 +32,6 @@ #include #include - #include "TLVEncoder.h" #include "TLVDecoder.h" #include "FGCNasMessageContainer.h" @@ -52,14 +51,16 @@ int decode_fgc_nas_message_container(FGCNasMessageContainer *nasmessagecontainer decoded += 2; CHECK_LENGTH_DECODER(len - decoded, ielen); - if ((decode_result = decode_octet_string(&nasmessagecontainer->nasmessagecontainercontents, ielen, buffer + decoded, len - decoded)) < 0) + if ((decode_result = + decode_octet_string(&nasmessagecontainer->nasmessagecontainercontents, ielen, buffer + decoded, len - decoded)) + < 0) return decode_result; else decoded += decode_result; return decoded; } -int encode_fgc_nas_message_container(FGCNasMessageContainer *nasmessagecontainer, uint8_t iei, uint8_t *buffer, uint32_t len) +int encode_fgc_nas_message_container(const FGCNasMessageContainer *nasmessagecontainer, uint8_t iei, uint8_t *buffer, uint32_t len) { uint32_t encoded = 0; int encode_result; @@ -73,7 +74,8 @@ int encode_fgc_nas_message_container(FGCNasMessageContainer *nasmessagecontainer encoded += 2; - if ((encode_result = encode_octet_string(&nasmessagecontainer->nasmessagecontainercontents, buffer + encoded, len - encoded)) < 0) { + if ((encode_result = encode_octet_string(&nasmessagecontainer->nasmessagecontainercontents, buffer + encoded, len - encoded)) + < 0) { return encode_result; } else { uint16_t tmp = htons(encoded + encode_result - 3); @@ -95,5 +97,3 @@ void dump_fgc_nas_message_container_xml(FGCNasMessageContainer *nasmessagecontai printf("%s", dump_octet_string_xml(&nasmessagecontainer->nasmessagecontainercontents)); printf("\n"); } - - diff --git a/openair3/NAS/COMMON/IES/FGCNasMessageContainer.h b/openair3/NAS/NR_UE/5GS/5GMM/IES/FGCNasMessageContainer.h similarity index 93% rename from openair3/NAS/COMMON/IES/FGCNasMessageContainer.h rename to openair3/NAS/NR_UE/5GS/5GMM/IES/FGCNasMessageContainer.h index 19a1679b7e..a81c1add67 100644 --- a/openair3/NAS/COMMON/IES/FGCNasMessageContainer.h +++ b/openair3/NAS/NR_UE/5GS/5GMM/IES/FGCNasMessageContainer.h @@ -44,11 +44,10 @@ typedef struct FGCNasMessageContainer_tag { OctetString nasmessagecontainercontents; } FGCNasMessageContainer; -int encode_fgc_nas_message_container(FGCNasMessageContainer *nasmessagecontainer, uint8_t iei, uint8_t *buffer, uint32_t len); +int encode_fgc_nas_message_container(const FGCNasMessageContainer *nasmessagecontainer, uint8_t iei, uint8_t *buffer, uint32_t len); int decode_fgc_nas_message_container(FGCNasMessageContainer *nasmessagecontainer, uint8_t iei, uint8_t *buffer, uint32_t len); void dump_fgc_nas_message_container_xml(FGCNasMessageContainer *nasmessagecontainer, uint8_t iei); #endif /* FGC NAS MESSAGE CONTAINER_H_ */ - diff --git a/openair3/NAS/COMMON/IES/FGMMCapability.c b/openair3/NAS/NR_UE/5GS/5GMM/IES/FGMMCapability.c similarity index 84% rename from openair3/NAS/COMMON/IES/FGMMCapability.c rename to openair3/NAS/NR_UE/5GS/5GMM/IES/FGMMCapability.c index ce156e63bf..c053070518 100644 --- a/openair3/NAS/COMMON/IES/FGMMCapability.c +++ b/openair3/NAS/NR_UE/5GS/5GMM/IES/FGMMCapability.c @@ -31,24 +31,20 @@ #include #include - #include "TLVEncoder.h" #include "TLVDecoder.h" #include "FGMMCapability.h" - - -int encode_5gmm_capability(FGMMCapability *fgmmcapability, uint8_t iei, uint8_t *buffer, uint32_t len) +int encode_5gmm_capability(const FGMMCapability *fgmmcapability, uint8_t iei, uint8_t *buffer, uint32_t len) { int encoded = 0; - if(iei){ + if (iei) { *buffer = fgmmcapability->iei; - encoded++; - *(buffer+encoded) = fgmmcapability->length; - encoded++; - *(buffer+encoded) = fgmmcapability->value; - encoded++; + encoded++; + *(buffer + encoded) = fgmmcapability->length; + encoded++; + *(buffer + encoded) = fgmmcapability->value; + encoded++; } return encoded; } - diff --git a/openair3/NAS/COMMON/IES/FGMMCapability.h b/openair3/NAS/NR_UE/5GS/5GMM/IES/FGMMCapability.h similarity index 93% rename from openair3/NAS/COMMON/IES/FGMMCapability.h rename to openair3/NAS/NR_UE/5GS/5GMM/IES/FGMMCapability.h index d427896338..b125935f9d 100644 --- a/openair3/NAS/COMMON/IES/FGMMCapability.h +++ b/openair3/NAS/NR_UE/5GS/5GMM/IES/FGMMCapability.h @@ -27,7 +27,6 @@ * \version 0.1 */ - #include #include #include @@ -37,15 +36,12 @@ #ifndef FGMM_CAPABILITY_H_ #define FGMM_CAPABILITY_H_ - typedef struct { uint8_t iei; uint8_t length; uint8_t value; } FGMMCapability; - -int encode_5gmm_capability(FGMMCapability *fgmmcapability, uint8_t iei, uint8_t *buffer, uint32_t len); +int encode_5gmm_capability(const FGMMCapability *fgmmcapability, uint8_t iei, uint8_t *buffer, uint32_t len); #endif /* FGMM_CAPABILITY_H_ */ - diff --git a/openair3/NAS/COMMON/IES/FGSDeregistrationType.h b/openair3/NAS/NR_UE/5GS/5GMM/IES/FGSDeregistrationType.h similarity index 100% rename from openair3/NAS/COMMON/IES/FGSDeregistrationType.h rename to openair3/NAS/NR_UE/5GS/5GMM/IES/FGSDeregistrationType.h diff --git a/openair3/NAS/COMMON/IES/FGSMobileIdentity.c b/openair3/NAS/NR_UE/5GS/5GMM/IES/FGSMobileIdentity.c similarity index 72% rename from openair3/NAS/COMMON/IES/FGSMobileIdentity.c rename to openair3/NAS/NR_UE/5GS/5GMM/IES/FGSMobileIdentity.c index f70dfc66ed..883c5ba98d 100644 --- a/openair3/NAS/COMMON/IES/FGSMobileIdentity.c +++ b/openair3/NAS/NR_UE/5GS/5GMM/IES/FGSMobileIdentity.c @@ -27,7 +27,6 @@ * \version 0.1 */ - #include #include #include @@ -42,11 +41,11 @@ static int decode_guti_5gs_mobile_identity(Guti5GSMobileIdentity_t *guti, const uint8_t *buffer); -static int encode_guti_5gs_mobile_identity(Guti5GSMobileIdentity_t *guti, uint8_t *buffer); -static int encode_suci_5gs_mobile_identity(Suci5GSMobileIdentity_t *suci, uint8_t *buffer); -static int encode_imeisv_5gs_mobile_identity(Imeisv5GSMobileIdentity_t *imeisv, uint8_t *buffer); +static int encode_guti_5gs_mobile_identity(const Guti5GSMobileIdentity_t *guti, uint8_t *buffer); +static int encode_suci_5gs_mobile_identity(const Suci5GSMobileIdentity_t *suci, uint8_t *buffer); +static int encode_imeisv_5gs_mobile_identity(const Imeisv5GSMobileIdentity_t *imeisv, uint8_t *buffer); -int encode_stmsi_5gs_mobile_identity(uint8_t *buffer, Stmsi5GSMobileIdentity_t *stmsi, uint32_t len) +int encode_stmsi_5gs_mobile_identity(uint8_t *buffer, const Stmsi5GSMobileIdentity_t *stmsi, uint32_t len) { // Return if buffer is shorter than min length if (len < LEN_5G_FGS_TMSI_IE) @@ -114,12 +113,9 @@ int decode_5gs_mobile_identity(FGSMobileIdentity *fgsmobileidentity, uint8_t iei uint8_t typeofidentity = *(buffer + decoded) & 0x7; - if (typeofidentity == FGS_MOBILE_IDENTITY_5G_GUTI) { - decoded_rc = decode_guti_5gs_mobile_identity(&fgsmobileidentity->guti, - buffer + decoded); - } else { - AssertFatal(false, "Mobile Identity encoding of type %d not implemented\n", typeofidentity); - } + AssertFatal(typeofidentity == FGS_MOBILE_IDENTITY_5G_GUTI, "Mobile Identity encoding of type %d not implemented\n", typeofidentity); + if (typeofidentity == FGS_MOBILE_IDENTITY_5G_GUTI) + decoded_rc = decode_guti_5gs_mobile_identity(&fgsmobileidentity->guti, buffer + decoded); if (decoded_rc < 0) { return decoded_rc; @@ -128,7 +124,7 @@ int decode_5gs_mobile_identity(FGSMobileIdentity *fgsmobileidentity, uint8_t iei return (decoded + decoded_rc); } -int encode_5gs_mobile_identity(FGSMobileIdentity *fgsmobileidentity, uint8_t iei, uint8_t *buffer, uint32_t len) +int encode_5gs_mobile_identity(const FGSMobileIdentity *fgsmobileidentity, uint8_t iei, uint8_t *buffer, uint32_t len) { // Return if buffer is shorter than min length if (len < MIN_LEN_FGS_MOBILE_ID_IE) @@ -146,18 +142,15 @@ int encode_5gs_mobile_identity(FGSMobileIdentity *fgsmobileidentity, uint8_t iei len -= encoded; if (fgsmobileidentity->guti.typeofidentity == FGS_MOBILE_IDENTITY_5G_GUTI) { - encoded_rc = encode_guti_5gs_mobile_identity(&fgsmobileidentity->guti, - buffer + encoded); + encoded_rc = encode_guti_5gs_mobile_identity(&fgsmobileidentity->guti, buffer + encoded); } if (fgsmobileidentity->suci.typeofidentity == FGS_MOBILE_IDENTITY_SUCI) { - encoded_rc = encode_suci_5gs_mobile_identity(&fgsmobileidentity->suci, - buffer + encoded); + encoded_rc = encode_suci_5gs_mobile_identity(&fgsmobileidentity->suci, buffer + encoded); } if (fgsmobileidentity->imeisv.typeofidentity == FGS_MOBILE_IDENTITY_IMEISV) { - encoded_rc = encode_imeisv_5gs_mobile_identity(&fgsmobileidentity->imeisv, - buffer + encoded); + encoded_rc = encode_imeisv_5gs_mobile_identity(&fgsmobileidentity->imeisv, buffer + encoded); } if (fgsmobileidentity->stmsi.typeofidentity == FGS_MOBILE_IDENTITY_5GS_TMSI) { @@ -168,7 +161,7 @@ int encode_5gs_mobile_identity(FGSMobileIdentity *fgsmobileidentity, uint8_t iei return encoded_rc; } - if(iei > 0){ + if (iei > 0) { uint16_t tmp = htons(encoded + encoded_rc - 3); memcpy(buffer + 1, &tmp, sizeof(tmp)); } else { @@ -192,7 +185,6 @@ static int decode_guti_5gs_mobile_identity(Guti5GSMobileIdentity_t *guti, const return (TLV_ENCODE_VALUE_DOESNT_MATCH); } - guti->oddeven = (*(buffer + decoded) >> 3) & 0x1; /* @@ -218,33 +210,27 @@ static int decode_guti_5gs_mobile_identity(Guti5GSMobileIdentity_t *guti, const guti->mncdigit1 = *(buffer + decoded) & 0xf; decoded++; - - guti->amfregionid = *(buffer+decoded); + guti->amfregionid = *(buffer + decoded); decoded++; IES_DECODE_U16(buffer, decoded, temp); - guti->amfsetid = temp>>3; - guti->amfpointer = temp&0x3f; + guti->amfsetid = (temp >> 6) & 0x3FF; + guti->amfpointer = temp & 0x3f; IES_DECODE_U32(buffer, decoded, guti->tmsi); return decoded; } - -static int encode_guti_5gs_mobile_identity(Guti5GSMobileIdentity_t *guti, uint8_t *buffer) +static int encode_guti_5gs_mobile_identity(const Guti5GSMobileIdentity_t *guti, uint8_t *buffer) { uint32_t encoded = 0; uint16_t temp; - *(buffer + encoded) = 0xf0 | ((guti->oddeven & 0x1) << 3) | - (guti->typeofidentity & 0x7); + *(buffer + encoded) = 0xf0 | ((guti->oddeven & 0x1) << 3) | (guti->typeofidentity & 0x7); encoded++; - *(buffer + encoded) = 0x00 | ((guti->mccdigit2 & 0xf) << 4) | - (guti->mccdigit1 & 0xf); + *(buffer + encoded) = 0x00 | ((guti->mccdigit2 & 0xf) << 4) | (guti->mccdigit1 & 0xf); encoded++; - *(buffer + encoded) = 0x00 | ((guti->mncdigit3 & 0xf) << 4) | - (guti->mccdigit3 & 0xf); + *(buffer + encoded) = 0x00 | ((guti->mncdigit3 & 0xf) << 4) | (guti->mccdigit3 & 0xf); encoded++; - *(buffer + encoded) = 0x00 | ((guti->mncdigit2 & 0xf) << 4) | - (guti->mncdigit1 & 0xf); + *(buffer + encoded) = 0x00 | ((guti->mncdigit2 & 0xf) << 4) | (guti->mncdigit1 & 0xf); encoded++; *(buffer + encoded) = guti->amfregionid; @@ -257,28 +243,22 @@ static int encode_guti_5gs_mobile_identity(Guti5GSMobileIdentity_t *guti, uint8_ return encoded; } - -static int encode_suci_5gs_mobile_identity(Suci5GSMobileIdentity_t *suci, uint8_t *buffer) +static int encode_suci_5gs_mobile_identity(const Suci5GSMobileIdentity_t *suci, uint8_t *buffer) { uint32_t encoded = 0; *(buffer + encoded) = (suci->supiformat << 4) | (suci->typeofidentity); encoded++; - *(buffer + encoded) = ((suci->mccdigit2 & 0xf) << 4) | - (suci->mccdigit1 & 0xf); + *(buffer + encoded) = ((suci->mccdigit2 & 0xf) << 4) | (suci->mccdigit1 & 0xf); encoded++; - *(buffer + encoded) = ((suci->mncdigit3 & 0xf) << 4) | - (suci->mccdigit3 & 0xf); + *(buffer + encoded) = ((suci->mncdigit3 & 0xf) << 4) | (suci->mccdigit3 & 0xf); encoded++; - *(buffer + encoded) = ((suci->mncdigit2 & 0xf) << 4) | - (suci->mncdigit1 & 0xf); + *(buffer + encoded) = ((suci->mncdigit2 & 0xf) << 4) | (suci->mncdigit1 & 0xf); encoded++; - *(buffer + encoded) = ((suci->routingindicatordigit2 & 0xf) << 4) | - (suci->routingindicatordigit1 & 0xf); + *(buffer + encoded) = ((suci->routingindicatordigit2 & 0xf) << 4) | (suci->routingindicatordigit1 & 0xf); encoded++; - *(buffer + encoded) = ((suci->routingindicatordigit4 & 0xf) << 4) | - (suci->routingindicatordigit3 & 0xf); + *(buffer + encoded) = ((suci->routingindicatordigit4 & 0xf) << 4) | (suci->routingindicatordigit3 & 0xf); encoded++; *(buffer + encoded) = 0x00 | (suci->protectionschemeId & 0xf); @@ -287,19 +267,19 @@ static int encode_suci_5gs_mobile_identity(Suci5GSMobileIdentity_t *suci, uint8_ *(buffer + encoded) = suci->homenetworkpki; encoded++; - char *ptr=suci->schemeoutput; - while ( ptr < suci->schemeoutput+strlen(suci->schemeoutput) ) { - buffer[encoded]=((*(ptr+1)-'0')<<4) | (*(ptr) -'0'); + const char *ptr = suci->schemeoutput; + while (ptr < suci->schemeoutput + strlen(suci->schemeoutput)) { + buffer[encoded] = ((*(ptr + 1) - '0') << 4) | (*(ptr) - '0'); encoded++; - ptr+=2; + ptr += 2; } - if (strlen(suci->schemeoutput)%2 == 1) - buffer[encoded++]=((*(ptr-1)-'0')) | 0xF0; + if (strlen(suci->schemeoutput) % 2 == 1) + buffer[encoded++] = ((*(ptr - 1) - '0')) | 0xF0; return encoded; } -static int encode_imeisv_5gs_mobile_identity(Imeisv5GSMobileIdentity_t *imeisv, uint8_t *buffer) +static int encode_imeisv_5gs_mobile_identity(const Imeisv5GSMobileIdentity_t *imeisv, uint8_t *buffer) { uint32_t encoded = 0; *(buffer + encoded) = 0x00 | (imeisv->digittac01 << 4) | (imeisv->oddeven << 3) | (imeisv->typeofidentity); @@ -310,17 +290,16 @@ static int encode_imeisv_5gs_mobile_identity(Imeisv5GSMobileIdentity_t *imeisv, encoded++; *(buffer + encoded) = 0x00 | (imeisv->digittac07 << 4) | (imeisv->digittac06); encoded++; - *(buffer + encoded) = 0x00 | (imeisv->digit09 << 4) | (imeisv->digittac08); + *(buffer + encoded) = 0x00 | (imeisv->digit09 << 4) | (imeisv->digittac08); encoded++; - *(buffer + encoded) = 0x00 | (imeisv->digit11 << 4) | (imeisv->digit10); + *(buffer + encoded) = 0x00 | (imeisv->digit11 << 4) | (imeisv->digit10); encoded++; - *(buffer + encoded) = 0x00 | (imeisv->digit13 << 4) | (imeisv->digit12); + *(buffer + encoded) = 0x00 | (imeisv->digit13 << 4) | (imeisv->digit12); encoded++; - *(buffer + encoded) = 0x00 | (imeisv->digitsv1 << 4) | (imeisv->digit14); + *(buffer + encoded) = 0x00 | (imeisv->digitsv1 << 4) | (imeisv->digit14); encoded++; - *(buffer + encoded) = 0x00 | (imeisv->spare << 4) | (imeisv->digitsv2); + *(buffer + encoded) = 0x00 | (imeisv->spare << 4) | (imeisv->digitsv2); encoded++; return encoded; } - diff --git a/openair3/NAS/COMMON/IES/FGSMobileIdentity.h b/openair3/NAS/NR_UE/5GS/5GMM/IES/FGSMobileIdentity.h similarity index 60% rename from openair3/NAS/COMMON/IES/FGSMobileIdentity.h rename to openair3/NAS/NR_UE/5GS/5GMM/IES/FGSMobileIdentity.h index e4747461e9..b7e66019cc 100644 --- a/openair3/NAS/COMMON/IES/FGSMobileIdentity.h +++ b/openair3/NAS/NR_UE/5GS/5GMM/IES/FGSMobileIdentity.h @@ -27,7 +27,6 @@ * \version 0.1 */ - #include #include #include @@ -41,97 +40,96 @@ #define DIGIT1 0xF typedef struct { - uint8_t spare:5; - uint8_t typeofidentity:3; + uint8_t spare: 5; + uint8_t typeofidentity: 3; } NoIdentity5GSMobileIdentity_t; typedef struct { - uint8_t spare1:1; - uint8_t supiformat:3; - uint8_t spare2:1; - uint8_t typeofidentity:3; - uint8_t mccdigit2:4; - uint8_t mccdigit1:4; - uint8_t mncdigit3:4; - uint8_t mccdigit3:4; - uint8_t mncdigit2:4; - uint8_t mncdigit1:4; - uint8_t routingindicatordigit2:4; - uint8_t routingindicatordigit1:4; - uint8_t routingindicatordigit4:4; - uint8_t routingindicatordigit3:4; - uint8_t spare3:1; - uint8_t spare4:1; - uint8_t spare5:1; - uint8_t spare6:1; - uint8_t protectionschemeId:4; - uint8_t homenetworkpki; + uint8_t spare1: 1; + uint8_t supiformat: 3; + uint8_t spare2: 1; + uint8_t typeofidentity: 3; + uint8_t mccdigit2: 4; + uint8_t mccdigit1: 4; + uint8_t mncdigit3: 4; + uint8_t mccdigit3: 4; + uint8_t mncdigit2: 4; + uint8_t mncdigit1: 4; + uint8_t routingindicatordigit2: 4; + uint8_t routingindicatordigit1: 4; + uint8_t routingindicatordigit4: 4; + uint8_t routingindicatordigit3: 4; + uint8_t spare3: 1; + uint8_t spare4: 1; + uint8_t spare5: 1; + uint8_t spare6: 1; + uint8_t protectionschemeId: 4; + uint8_t homenetworkpki; char schemeoutput[32]; } Suci5GSMobileIdentity_t; typedef struct { - uint8_t spare:4; - uint8_t oddeven:1; - uint8_t typeofidentity:3; - uint8_t mccdigit2:4; - uint8_t mccdigit1:4; - uint8_t mncdigit3:4; - uint8_t mccdigit3:4; - uint8_t mncdigit2:4; - uint8_t mncdigit1:4; - uint8_t amfregionid; - uint16_t amfsetid:10; - uint16_t amfpointer:6; + uint8_t spare: 4; + uint8_t oddeven: 1; + uint8_t typeofidentity: 3; + uint8_t mccdigit2: 4; + uint8_t mccdigit1: 4; + uint8_t mncdigit3: 4; + uint8_t mccdigit3: 4; + uint8_t mncdigit2: 4; + uint8_t mncdigit1: 4; + uint8_t amfregionid; + uint16_t amfsetid: 10; + uint16_t amfpointer: 6; uint32_t tmsi; } Guti5GSMobileIdentity_t; - typedef struct { - uint8_t digit1:4; - uint8_t oddeven:1; - uint8_t typeofidentity:3; - uint8_t digitp1:4; - uint8_t digitp:4; + uint8_t digit1: 4; + uint8_t oddeven: 1; + uint8_t typeofidentity: 3; + uint8_t digitp1: 4; + uint8_t digitp: 4; } Imei5GSMobileIdentity_t; typedef struct { - uint8_t digittac01:4; - uint8_t oddeven:1; - uint8_t typeofidentity:3; - uint8_t digittac02:4; - uint8_t digittac03:4; - uint8_t digittac04:4; - uint8_t digittac05:4; - uint8_t digittac06:4; - uint8_t digittac07:4; - uint8_t digittac08:4; - uint8_t digit09:4; - uint8_t digit10:4; - uint8_t digit11:4; - uint8_t digit12:4; - uint8_t digit13:4; - uint8_t digit14:4; - uint8_t digitsv1:4; - uint8_t digitsv2:4; - uint8_t spare:4; + uint8_t digittac01: 4; + uint8_t oddeven: 1; + uint8_t typeofidentity: 3; + uint8_t digittac02: 4; + uint8_t digittac03: 4; + uint8_t digittac04: 4; + uint8_t digittac05: 4; + uint8_t digittac06: 4; + uint8_t digittac07: 4; + uint8_t digittac08: 4; + uint8_t digit09: 4; + uint8_t digit10: 4; + uint8_t digit11: 4; + uint8_t digit12: 4; + uint8_t digit13: 4; + uint8_t digit14: 4; + uint8_t digitsv1: 4; + uint8_t digitsv2: 4; + uint8_t spare: 4; } Imeisv5GSMobileIdentity_t; - typedef struct { - uint8_t digit1:4; - uint8_t spare:1; - uint8_t typeofidentity:3; - uint16_t amfsetid:10; - uint16_t amfpointer:6; + uint8_t digit1: 4; + uint8_t spare: 1; + uint8_t typeofidentity: 3; + uint16_t amfsetid: 10; + uint16_t amfpointer: 6; uint32_t tmsi; } Stmsi5GSMobileIdentity_t; typedef struct { - uint8_t spare:5; - uint8_t typeofidentity:3; - uint8_t macaddr; + uint8_t spare: 5; + uint8_t typeofidentity: 3; + uint8_t macaddr; } Macaddr5GSMobileIdentity_t; +// clang-format off typedef union FGSMobileIdentity_tag { #define FGS_MOBILE_IDENTITY_NOIDENTITY 0b000 #define FGS_MOBILE_IDENTITY_SUCI 0b001 @@ -148,13 +146,13 @@ typedef union FGSMobileIdentity_tag { Imeisv5GSMobileIdentity_t imeisv; Macaddr5GSMobileIdentity_t macaddress; } FGSMobileIdentity; +// clang-format on -int encode_5gs_mobile_identity(FGSMobileIdentity *fgsmobileidentity, uint8_t iei, uint8_t *buffer, uint32_t len); +int encode_5gs_mobile_identity(const FGSMobileIdentity *fgsmobileidentity, uint8_t iei, uint8_t *buffer, uint32_t len); int decode_5gs_mobile_identity(FGSMobileIdentity *fgsmobileidentity, uint8_t iei, const uint8_t *buffer, uint32_t len); -int encode_stmsi_5gs_mobile_identity(uint8_t *buffer, Stmsi5GSMobileIdentity_t *stmsi, uint32_t len); +int encode_stmsi_5gs_mobile_identity(uint8_t *buffer, const Stmsi5GSMobileIdentity_t *stmsi, uint32_t len); int decode_stmsi_5gs_mobile_identity(Stmsi5GSMobileIdentity_t *stmsi, const uint8_t *buffer, uint32_t len); #endif /* FGS MOBILE IDENTITY_H_ */ - diff --git a/openair3/NAS/COMMON/IES/FGSRegistrationResult.c b/openair3/NAS/NR_UE/5GS/5GMM/IES/FGSRegistrationResult.c similarity index 89% rename from openair3/NAS/COMMON/IES/FGSRegistrationResult.c rename to openair3/NAS/NR_UE/5GS/5GMM/IES/FGSRegistrationResult.c index e580b14409..739cee7973 100644 --- a/openair3/NAS/COMMON/IES/FGSRegistrationResult.c +++ b/openair3/NAS/NR_UE/5GS/5GMM/IES/FGSRegistrationResult.c @@ -32,31 +32,27 @@ #include #include - #include "TLVEncoder.h" #include "TLVDecoder.h" #include "FGSRegistrationResult.h" - int decode_fgs_registration_result(FGSRegistrationResult *fgsregistrationresult, uint8_t iei, uint16_t value, uint32_t len) { int decoded = 0; uint16_t *buffer = &value; fgsregistrationresult->registrationresult = *buffer & 0x7; fgsregistrationresult->smsallowed = *buffer & 0x8; - decoded = decoded+2; + decoded = decoded + 2; return decoded; } -uint16_t encode_fgs_registration_result(FGSRegistrationResult *fgsregistrationresult) +uint16_t encode_fgs_registration_result(const FGSRegistrationResult *fgsregistrationresult) { uint16_t bufferReturn; uint16_t *buffer = &bufferReturn; uint8_t encoded = 0; - *(buffer + encoded) = 0x00 | (fgsregistrationresult->smsallowed & 0x8) | - (fgsregistrationresult->registrationresult & 0x7); - encoded= encoded+2; + *(buffer + encoded) = 0x00 | (fgsregistrationresult->smsallowed & 0x8) | (fgsregistrationresult->registrationresult & 0x7); + encoded = encoded + 2; return bufferReturn; } - diff --git a/openair3/NAS/COMMON/IES/FGSRegistrationResult.h b/openair3/NAS/NR_UE/5GS/5GMM/IES/FGSRegistrationResult.h similarity index 89% rename from openair3/NAS/COMMON/IES/FGSRegistrationResult.h rename to openair3/NAS/NR_UE/5GS/5GMM/IES/FGSRegistrationResult.h index 0a2dedc2e5..04f45417b8 100644 --- a/openair3/NAS/COMMON/IES/FGSRegistrationResult.h +++ b/openair3/NAS/NR_UE/5GS/5GMM/IES/FGSRegistrationResult.h @@ -34,8 +34,6 @@ #include "OctetString.h" - - #ifndef FGS_REGISTRATION_RESULT_H_ #define FGS_REGISTRATION_RESULT_H_ #define FGS_REGISTRATION_RESULT_3GPP 0b001 @@ -43,17 +41,15 @@ #define FGS_REGISTRATION_RESULT_3GPP_AND_NON_3GPP 0b011 typedef struct { - uint8_t iei; - uint8_t resultlength; - uint8_t spare:4; - uint8_t smsallowed:1; - uint8_t registrationresult:3; + uint8_t iei; + uint8_t resultlength; + uint8_t spare: 4; + uint8_t smsallowed: 1; + uint8_t registrationresult: 3; } FGSRegistrationResult; - -uint16_t encode_fgs_registration_result(FGSRegistrationResult *fgsregistrationresult); +uint16_t encode_fgs_registration_result(const FGSRegistrationResult *fgsregistrationresult); int decode_fgs_registration_result(FGSRegistrationResult *fgsregistrationresult, uint8_t iei, uint16_t value, uint32_t len); #endif /* FGS REGISTRATION RESULT_H_*/ - diff --git a/openair3/NAS/COMMON/IES/FGSRegistrationType.c b/openair3/NAS/NR_UE/5GS/5GMM/IES/FGSRegistrationType.c similarity index 91% rename from openair3/NAS/COMMON/IES/FGSRegistrationType.c rename to openair3/NAS/NR_UE/5GS/5GMM/IES/FGSRegistrationType.c index 7f1c3ae667..81825f585a 100644 --- a/openair3/NAS/COMMON/IES/FGSRegistrationType.c +++ b/openair3/NAS/NR_UE/5GS/5GMM/IES/FGSRegistrationType.c @@ -31,7 +31,6 @@ #include #include - #include "TLVEncoder.h" #include "TLVDecoder.h" #include "FGSRegistrationType.h" @@ -50,16 +49,14 @@ int decode_5gs_registration_type(FGSRegistrationType *fgsregistrationtype, uint8 return decoded; } -int encode_5gs_registration_type(FGSRegistrationType *fgsregistrationtype) +int encode_5gs_registration_type(const FGSRegistrationType *fgsregistrationtype) { uint8_t bufferReturn; uint8_t *buffer = &bufferReturn; uint8_t encoded = 0; uint8_t iei = 0; - *(buffer + encoded) = 0x00 | (iei & 0xf0) | 0x8| - (*fgsregistrationtype & 0x7); + *(buffer + encoded) = 0x00 | (iei & 0xf0) | 0x8 | (*fgsregistrationtype & 0x7); encoded++; return bufferReturn; } - diff --git a/openair3/NAS/COMMON/IES/FGSRegistrationType.h b/openair3/NAS/NR_UE/5GS/5GMM/IES/FGSRegistrationType.h similarity index 94% rename from openair3/NAS/COMMON/IES/FGSRegistrationType.h rename to openair3/NAS/NR_UE/5GS/5GMM/IES/FGSRegistrationType.h index a548d45d93..ea42ac160e 100644 --- a/openair3/NAS/COMMON/IES/FGSRegistrationType.h +++ b/openair3/NAS/NR_UE/5GS/5GMM/IES/FGSRegistrationType.h @@ -40,16 +40,15 @@ typedef uint8_t FGSRegistrationType; - +// clang-format off #define INITIAL_REGISTRATION 0b001 #define MOBILITY_REGISTRATION_UPDATING 0b010 #define PERIODIC_REGISTRATION_UPDATING 0b011 #define EMERGENCY_REGISTRATION 0b100 +// clang-format on -int encode_5gs_registration_type(FGSRegistrationType *fgsregistrationtype); +int encode_5gs_registration_type(const FGSRegistrationType *fgsregistrationtype); int decode_5gs_registration_type(FGSRegistrationType *fgsregistrationtype, uint8_t iei, uint8_t value, uint32_t len); - #endif /* FGS_REGISTRATION_TYPE_H_*/ - diff --git a/openair3/NAS/COMMON/IES/NrUESecurityCapability.c b/openair3/NAS/NR_UE/5GS/5GMM/IES/NrUESecurityCapability.c similarity index 67% rename from openair3/NAS/COMMON/IES/NrUESecurityCapability.c rename to openair3/NAS/NR_UE/5GS/5GMM/IES/NrUESecurityCapability.c index 6c0ff7e7c7..5d2d7cc040 100644 --- a/openair3/NAS/COMMON/IES/NrUESecurityCapability.c +++ b/openair3/NAS/NR_UE/5GS/5GMM/IES/NrUESecurityCapability.c @@ -27,37 +27,35 @@ * \version 0.1 */ - #include #include #include - #include "TLVEncoder.h" #include "TLVDecoder.h" #include "NrUESecurityCapability.h" - - -int encode_nrue_security_capability(NrUESecurityCapability *nruesecuritycapability, uint8_t iei, uint8_t *buffer, uint32_t len) +int encode_nrue_security_capability(const NrUESecurityCapability *nruesecuritycapability, + uint8_t iei, + uint8_t *buffer, + uint32_t len) { int encoded = 0; - if(iei){ + if (iei) { *buffer = nruesecuritycapability->iei; - encoded++; - *(buffer+encoded) = nruesecuritycapability->length; - encoded++; - *(buffer+encoded) = nruesecuritycapability->fg_EA; - encoded++; - *(buffer+encoded) = nruesecuritycapability->fg_IA; - encoded++; - *(buffer+encoded) = nruesecuritycapability->EEA; - encoded++; - *(buffer+encoded) = nruesecuritycapability->EIA; - encoded++; - if((nruesecuritycapability->length - 4) > 0) - encoded = encoded + nruesecuritycapability->length - 4; + encoded++; + *(buffer + encoded) = nruesecuritycapability->length; + encoded++; + *(buffer + encoded) = nruesecuritycapability->fg_EA; + encoded++; + *(buffer + encoded) = nruesecuritycapability->fg_IA; + encoded++; + *(buffer + encoded) = nruesecuritycapability->EEA; + encoded++; + *(buffer + encoded) = nruesecuritycapability->EIA; + encoded++; + if ((nruesecuritycapability->length - 4) > 0) + encoded = encoded + nruesecuritycapability->length - 4; } return encoded; } - diff --git a/openair3/NAS/COMMON/IES/NrUESecurityCapability.h b/openair3/NAS/NR_UE/5GS/5GMM/IES/NrUESecurityCapability.h similarity index 87% rename from openair3/NAS/COMMON/IES/NrUESecurityCapability.h rename to openair3/NAS/NR_UE/5GS/5GMM/IES/NrUESecurityCapability.h index 10aa0cf0ea..a8ee4391b3 100644 --- a/openair3/NAS/COMMON/IES/NrUESecurityCapability.h +++ b/openair3/NAS/NR_UE/5GS/5GMM/IES/NrUESecurityCapability.h @@ -36,7 +36,6 @@ #ifndef NRUE_SECURITY_CAPABILITY_H_ #define NRUE_SECURITY_CAPABILITY_H_ - typedef struct { uint8_t iei; uint8_t length; @@ -46,8 +45,9 @@ typedef struct { uint8_t EIA; } NrUESecurityCapability; - -int encode_nrue_security_capability(NrUESecurityCapability *nruesecuritycapability, uint8_t iei, uint8_t *buffer, uint32_t len); +int encode_nrue_security_capability(const NrUESecurityCapability *nruesecuritycapability, + uint8_t iei, + uint8_t *buffer, + uint32_t len); #endif /* NRUE_SECURITY_CAPABILITY_H_ */ - diff --git a/openair3/NAS/COMMON/IES/SORTransparentContainer.c b/openair3/NAS/NR_UE/5GS/5GMM/IES/SORTransparentContainer.c similarity index 75% rename from openair3/NAS/COMMON/IES/SORTransparentContainer.c rename to openair3/NAS/NR_UE/5GS/5GMM/IES/SORTransparentContainer.c index 3ab2a14c3d..9a6af8517c 100644 --- a/openair3/NAS/COMMON/IES/SORTransparentContainer.c +++ b/openair3/NAS/NR_UE/5GS/5GMM/IES/SORTransparentContainer.c @@ -30,7 +30,10 @@ //#define NAS_DEBUG 1 -int decode_sor_transparent_container(SORTransparentContainer *sortransparentcontainer, uint8_t iei, uint8_t *buffer, uint32_t len) +int decode_sor_transparent_container(SORTransparentContainer *sortransparentcontainer, + uint8_t iei, + const uint8_t *buffer, + uint32_t len) { int decoded = 0; int decode_result; @@ -47,27 +50,31 @@ int decode_sor_transparent_container(SORTransparentContainer *sortransparentcont CHECK_LENGTH_DECODER(len - decoded, ielen); - - if ((decode_result = decode_octet_string(&sortransparentcontainer->sortransparentcontainercontents, ielen, buffer + decoded, len - decoded)) < 0) { + if ((decode_result = + decode_octet_string(&sortransparentcontainer->sortransparentcontainercontents, ielen, buffer + decoded, len - decoded)) + < 0) { LOG_FUNC_RETURN(decode_result); } else { decoded += decode_result; } -#if defined (NAS_DEBUG) +#if defined(NAS_DEBUG) dump_sor_transparent_container_xml(sortransparentcontainer, iei); #endif LOG_FUNC_RETURN(decoded); } -int encode_sor_transparent_container(SORTransparentContainer *sortransparentcontainer, uint8_t iei, uint8_t *buffer, uint32_t len) +int encode_sor_transparent_container(const SORTransparentContainer *sortransparentcontainer, + uint8_t iei, + uint8_t *buffer, + uint32_t len) { uint8_t *lenPtr; uint32_t encoded = 0; int32_t encode_result; /* Checking IEI and pointer */ CHECK_PDU_POINTER_AND_LENGTH_ENCODER(buffer, SOR_TRANSPARENT_CONTAINER_MINIMUM_LENGTH, len); -#if defined (NAS_DEBUG) +#if defined(NAS_DEBUG) dump_sor_transparent_container_xml(sortransparentcontainer, iei); #endif @@ -76,11 +83,12 @@ int encode_sor_transparent_container(SORTransparentContainer *sortransparentcont encoded++; } - lenPtr = (buffer + encoded); + lenPtr = (buffer + encoded); - //encoded += 2; - //if ((encode_result = encode_octet_string(&sortransparentcontainer->sortransparentcontainercontents, buffer + sizeof(uint16_t), len - sizeof(uint16_t))) < 0) - if ((encode_result = encode_octet_string(&sortransparentcontainer->sortransparentcontainercontents, lenPtr + sizeof(uint16_t), len - sizeof(uint16_t))) < 0) + if ((encode_result = encode_octet_string(&sortransparentcontainer->sortransparentcontainercontents, + lenPtr + sizeof(uint16_t), + len - sizeof(uint16_t))) + < 0) return encode_result; else encoded += encode_result; @@ -100,4 +108,3 @@ void dump_sor_transparent_container_xml(SORTransparentContainer *sortransparentc printf("%s", dump_octet_string_xml(&sortransparentcontainer->sortransparentcontainercontents)); printf("\n"); } - diff --git a/openair3/NAS/COMMON/IES/SORTransparentContainer.h b/openair3/NAS/NR_UE/5GS/5GMM/IES/SORTransparentContainer.h similarity index 79% rename from openair3/NAS/COMMON/IES/SORTransparentContainer.h rename to openair3/NAS/NR_UE/5GS/5GMM/IES/SORTransparentContainer.h index 587419b1f9..7ed4e039ef 100644 --- a/openair3/NAS/COMMON/IES/SORTransparentContainer.h +++ b/openair3/NAS/NR_UE/5GS/5GMM/IES/SORTransparentContainer.h @@ -35,11 +35,16 @@ typedef struct SORTransparentContainer_tag { OctetString sortransparentcontainercontents; } SORTransparentContainer; -int encode_sor_transparent_container(SORTransparentContainer *sortransparentcontainer, uint8_t iei, uint8_t *buffer, uint32_t len); +int encode_sor_transparent_container(const SORTransparentContainer *sortransparentcontainer, + uint8_t iei, + uint8_t *buffer, + uint32_t len); -int decode_sor_transparent_container(SORTransparentContainer *sortransparentcontainer, uint8_t iei, uint8_t *buffer, uint32_t len); +int decode_sor_transparent_container(SORTransparentContainer *sortransparentcontainer, + uint8_t iei, + const uint8_t *buffer, + uint32_t len); void dump_sor_transparent_container_xml(SORTransparentContainer *sortransparentcontainer, uint8_t iei); #endif /* ESM MESSAGE CONTAINER_H_ */ - diff --git a/openair3/NAS/NR_UE/5GS/5GMM/MSG/CMakeLists.txt b/openair3/NAS/NR_UE/5GS/5GMM/MSG/CMakeLists.txt new file mode 100644 index 0000000000..be84772da6 --- /dev/null +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/CMakeLists.txt @@ -0,0 +1,15 @@ +add_library(fgs_5gmm_lib OBJECT + fgs_service_request.c + RegistrationRequest.c + RegistrationAccept.c + FGSIdentityResponse.c + FGSAuthenticationResponse.c + FGSNASSecurityModeComplete.c + RegistrationComplete.c + FGSUplinkNasTransport.c + FGSDeregistrationRequestUEOriginating.c +) + +target_link_libraries(fgs_5gmm_lib PUBLIC fgs_5gmm_ies_lib) + +target_include_directories(fgs_5gmm_lib PRIVATE ../IES/ ../../) diff --git a/openair3/NAS/COMMON/EMM/MSG/FGSAuthenticationResponse.c b/openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSAuthenticationResponse.c similarity index 70% rename from openair3/NAS/COMMON/EMM/MSG/FGSAuthenticationResponse.c rename to openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSAuthenticationResponse.c index 5e1ff25151..319026f9ef 100644 --- a/openair3/NAS/COMMON/EMM/MSG/FGSAuthenticationResponse.c +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSAuthenticationResponse.c @@ -37,20 +37,21 @@ #include "FGSAuthenticationResponse.h" - -int encode_fgs_authentication_response(fgs_authentication_response_msg *authentication_response, uint8_t *buffer, uint32_t len) +int encode_fgs_authentication_response(const fgs_authentication_response_msg *authentication_response, + uint8_t *buffer, + uint32_t len) { int encoded = 0; int encode_result = 0; - - if ((encode_result = - encode_authentication_response_parameter(&authentication_response->authenticationresponseparameter, - AUTHENTICATION_RESPONSE_PARAMETER_IEI, buffer + encoded, len - encoded)) < 0) //Return in case of error + if ((encode_result = encode_authentication_response_parameter(&authentication_response->authenticationresponseparameter, + AUTHENTICATION_RESPONSE_PARAMETER_IEI, + buffer + encoded, + len - encoded)) + < 0) // Return in case of error return encode_result; else encoded += encode_result; return encoded; } - diff --git a/openair3/NAS/COMMON/EMM/MSG/FGSAuthenticationResponse.h b/openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSAuthenticationResponse.h similarity index 76% rename from openair3/NAS/COMMON/EMM/MSG/FGSAuthenticationResponse.h rename to openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSAuthenticationResponse.h index 0acee3382f..6c0f0eaa64 100644 --- a/openair3/NAS/COMMON/EMM/MSG/FGSAuthenticationResponse.h +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSAuthenticationResponse.h @@ -32,16 +32,14 @@ #include #include -#include "ExtendedProtocolDiscriminator.h" #include "SecurityHeaderType.h" -#include "SpareHalfOctet.h" #include "MessageType.h" #include "AuthenticationResponseParameter.h" #ifndef FGS_AUTHENTICATION_RESPONSE_H_ #define FGS_AUTHENTICATION_RESPONSE_H_ -#define AUTHENTICATION_RESPONSE_PARAMETER_IEI 0x2d +#define AUTHENTICATION_RESPONSE_PARAMETER_IEI 0x2d /* * Message name: Identity response @@ -52,15 +50,11 @@ typedef struct fgs_authentication_response_msg_tag { /* Mandatory fields */ - ExtendedProtocolDiscriminator protocoldiscriminator; - SecurityHeaderType securityheadertype:4; - SpareHalfOctet sparehalfoctet:4; - MessageType messagetype; - AuthenticationResponseParameter authenticationresponseparameter; + AuthenticationResponseParameter authenticationresponseparameter; } fgs_authentication_response_msg; -int encode_fgs_authentication_response(fgs_authentication_response_msg *authentication_response, uint8_t *buffer, uint32_t len); +int encode_fgs_authentication_response(const fgs_authentication_response_msg *authentication_response, + uint8_t *buffer, + uint32_t len); #endif /* ! defined(FGS_AUTHENTICATION_RESPONSE_H_) */ - - diff --git a/openair3/NAS/COMMON/EMM/MSG/FGSDeregistrationRequestUEOriginating.c b/openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSDeregistrationRequestUEOriginating.c similarity index 81% rename from openair3/NAS/COMMON/EMM/MSG/FGSDeregistrationRequestUEOriginating.c rename to openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSDeregistrationRequestUEOriginating.c index af8dfd8c20..dbe1a548fb 100644 --- a/openair3/NAS/COMMON/EMM/MSG/FGSDeregistrationRequestUEOriginating.c +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSDeregistrationRequestUEOriginating.c @@ -27,23 +27,18 @@ * \version 0.1 */ -#include -#include -#include +#include "FGSDeregistrationRequestUEOriginating.h" #include -#include "FGSDeregistrationRequestUEOriginating.h" -#include "NR_NAS_defs.h" +#define IEI_NULL 0x00 -int encode_fgs_deregistration_request_ue_originating(fgs_deregistration_request_ue_originating_msg *drr, +int encode_fgs_deregistration_request_ue_originating(const fgs_deregistration_request_ue_originating_msg *drr, uint8_t *buffer, uint32_t len) { int encoded = 0; - FGSDeregistrationType *dt = &drr->deregistrationtype; - *(buffer + encoded) = ((dt->switchoff & 0x1) << 7) - | ((dt->reregistration_required & 0x1) << 6) - | ((dt->access_type & 0x3) << 4); + const FGSDeregistrationType *dt = &drr->deregistrationtype; + *(buffer + encoded) = ((dt->switchoff & 0x1) << 7) | ((dt->reregistration_required & 0x1) << 6) | ((dt->access_type & 0x3) << 4); int encode_result; if ((encode_result = encode_nas_key_set_identifier(&drr->naskeysetidentifier, IEI_NULL)) < 0) diff --git a/openair3/NAS/COMMON/EMM/MSG/FGSDeregistrationRequestUEOriginating.h b/openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSDeregistrationRequestUEOriginating.h similarity index 83% rename from openair3/NAS/COMMON/EMM/MSG/FGSDeregistrationRequestUEOriginating.h rename to openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSDeregistrationRequestUEOriginating.h index 2bccd8a5bd..6374b55895 100644 --- a/openair3/NAS/COMMON/EMM/MSG/FGSDeregistrationRequestUEOriginating.h +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSDeregistrationRequestUEOriginating.h @@ -22,17 +22,12 @@ #ifndef FGS_DEREGISTRATION_REQUEST_UE_ORIGINATING_H_ #define FGS_DEREGISTRATION_REQUEST_UE_ORIGINATING_H_ -#include -#include #include - -#include "ExtendedProtocolDiscriminator.h" -#include "SecurityHeaderType.h" -#include "SpareHalfOctet.h" -#include "MessageType.h" #include "FGSDeregistrationType.h" -#include "NasKeySetIdentifier.h" #include "FGSMobileIdentity.h" +#include "MessageType.h" +#include "NasKeySetIdentifier.h" +#include "SecurityHeaderType.h" /* * Message name: De-registration request (UE originating de-registration) @@ -43,18 +38,13 @@ typedef struct fgs_deregistration_request_ue_originating_msg_tag { /* Mandatory fields */ - ExtendedProtocolDiscriminator protocoldiscriminator; - SecurityHeaderType securityheadertype: 4; - SpareHalfOctet sparehalfoctet: 4; - MessageType messagetype; FGSDeregistrationType deregistrationtype; NasKeySetIdentifier naskeysetidentifier; FGSMobileIdentity fgsmobileidentity; } fgs_deregistration_request_ue_originating_msg; -int encode_fgs_deregistration_request_ue_originating(fgs_deregistration_request_ue_originating_msg *registrationrequest, +int encode_fgs_deregistration_request_ue_originating(const fgs_deregistration_request_ue_originating_msg *registrationrequest, uint8_t *buffer, uint32_t len); #endif /* ! defined(REGISTRATION_REQUEST_H_) */ - diff --git a/openair3/NAS/COMMON/EMM/MSG/FGSIdentityResponse.c b/openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSIdentityResponse.c similarity index 78% rename from openair3/NAS/COMMON/EMM/MSG/FGSIdentityResponse.c rename to openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSIdentityResponse.c index 4f8f6dd321..f65279c355 100644 --- a/openair3/NAS/COMMON/EMM/MSG/FGSIdentityResponse.c +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSIdentityResponse.c @@ -28,29 +28,19 @@ \version 0.1 */ -#include -#include -#include +#include "FGSIdentityResponse.h" #include -#include "nas_log.h" - -#include "FGSIdentityResponse.h" - - -int encode_identiy_response(fgs_identiy_response_msg *fgs_identity_reps, uint8_t *buffer, uint32_t len) +int encode_fgmm_identity_response(uint8_t *buffer, const fgmm_identity_response_msg *fgs_identity_reps, uint32_t len) { int encoded = 0; int encode_result = 0; - if ((encode_result = - encode_5gs_mobile_identity(&fgs_identity_reps->fgsmobileidentity, 0, buffer + - encoded, len - encoded)) < 0) //Return in case of error + if ((encode_result = encode_5gs_mobile_identity(&fgs_identity_reps->fgsmobileidentity, 0, buffer + encoded, len - encoded)) + < 0) // Return in case of error return encode_result; else encoded += encode_result; return encoded; } - - diff --git a/openair3/NAS/COMMON/EMM/MSG/FGSIdentityResponse.h b/openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSIdentityResponse.h similarity index 74% rename from openair3/NAS/COMMON/EMM/MSG/FGSIdentityResponse.h rename to openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSIdentityResponse.h index 431293e03e..667cb80c59 100644 --- a/openair3/NAS/COMMON/EMM/MSG/FGSIdentityResponse.h +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSIdentityResponse.h @@ -28,15 +28,10 @@ \version 0.1 */ -#include -#include #include - -#include "ExtendedProtocolDiscriminator.h" -#include "SecurityHeaderType.h" -#include "SpareHalfOctet.h" #include "FGSMobileIdentity.h" #include "MessageType.h" +#include "SecurityHeaderType.h" #ifndef FGS_IDENTITY_RESPONSE_H_ #define FGS_IDENTITY_RESPONSE_H_ @@ -48,18 +43,11 @@ * Direction: UE to AMF */ -typedef struct fgs_identiy_response_msg_tag { +typedef struct fgmm_identity_response_msg_s { /* Mandatory fields */ - ExtendedProtocolDiscriminator protocoldiscriminator; - SecurityHeaderType securityheadertype:4; - SpareHalfOctet sparehalfoctet:4; - MessageType messagetype; - FGSMobileIdentity fgsmobileidentity; + FGSMobileIdentity fgsmobileidentity; +} fgmm_identity_response_msg; -} fgs_identiy_response_msg; - -int encode_identiy_response(fgs_identiy_response_msg *fgs_identity_reps, uint8_t *buffer, uint32_t len); +int encode_fgmm_identity_response(uint8_t *buffer, const fgmm_identity_response_msg *fgs_identity_reps, uint32_t len); #endif /* ! defined(FGS_IDENTITY_RESPONSE_H_) */ - - diff --git a/openair3/NAS/COMMON/EMM/MSG/FGSNASSecurityModeComplete.c b/openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSNASSecurityModeComplete.c similarity index 65% rename from openair3/NAS/COMMON/EMM/MSG/FGSNASSecurityModeComplete.c rename to openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSNASSecurityModeComplete.c index e0be56145f..f24dc50749 100644 --- a/openair3/NAS/COMMON/EMM/MSG/FGSNASSecurityModeComplete.c +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSNASSecurityModeComplete.c @@ -28,39 +28,32 @@ \version 0.1 */ -#include -#include -#include -#include - -#include "nas_log.h" - #include "FGSNASSecurityModeComplete.h" -#include "FGSMobileIdentity.h" +#include #include "FGCNasMessageContainer.h" +#include "FGSMobileIdentity.h" -int encode_fgs_security_mode_complete(fgs_security_mode_complete_msg *fgs_security_mode_comp, uint8_t *buffer, uint32_t len) +int encode_fgs_security_mode_complete(const fgs_security_mode_complete_msg *fgs_security_mode_comp, uint8_t *buffer, uint32_t len) { - int encoded = 0; - int encode_result = 0; + int encoded = 0; + int encode_result = 0; - if ((encode_result = - encode_5gs_mobile_identity(&fgs_security_mode_comp->fgsmobileidentity, 0x77, buffer + - encoded, len - encoded)) < 0) { //Return in case of error + if ((encode_result = + encode_5gs_mobile_identity(&fgs_security_mode_comp->fgsmobileidentity, 0x77, buffer + encoded, len - encoded)) + < 0) { // Return in case of error + return encode_result; + } else { + encoded += encode_result; + if ((encode_result = encode_fgc_nas_message_container(&fgs_security_mode_comp->fgsnasmessagecontainer, + 0x71, + buffer + encoded, + len - encoded)) + < 0) { return encode_result; } else { encoded += encode_result; - if ((encode_result = - encode_fgc_nas_message_container(&fgs_security_mode_comp->fgsnasmessagecontainer, 0x71, buffer + - encoded, len - encoded)) < 0) { - return encode_result; - } else { - encoded += encode_result; - } } + } - return encoded; + return encoded; } - - - diff --git a/openair3/NAS/COMMON/EMM/MSG/FGSNASSecurityModeComplete.h b/openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSNASSecurityModeComplete.h similarity index 74% rename from openair3/NAS/COMMON/EMM/MSG/FGSNASSecurityModeComplete.h rename to openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSNASSecurityModeComplete.h index 702dca3dc5..4c379dadee 100644 --- a/openair3/NAS/COMMON/EMM/MSG/FGSNASSecurityModeComplete.h +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSNASSecurityModeComplete.h @@ -28,16 +28,11 @@ \version 0.1 */ -#include -#include #include - -#include "ExtendedProtocolDiscriminator.h" -#include "SecurityHeaderType.h" -#include "SpareHalfOctet.h" +#include "FGCNasMessageContainer.h" #include "FGSMobileIdentity.h" #include "MessageType.h" -#include "FGCNasMessageContainer.h" +#include "SecurityHeaderType.h" #ifndef FGS_NAS_SECURITY_MODE_COMPLETE_H_ #define FGS_NAS_SECURITY_MODE_COMPLETE_H_ @@ -50,16 +45,11 @@ */ typedef struct fgs_security_mode_complete_msg_tag { - /* Mandatory fields */ - ExtendedProtocolDiscriminator protocoldiscriminator; - SecurityHeaderType securityheadertype:4; - SpareHalfOctet sparehalfoctet:4; - MessageType messagetype; - FGSMobileIdentity fgsmobileidentity; - FGCNasMessageContainer fgsnasmessagecontainer; + /* Mandatory fields */ + FGSMobileIdentity fgsmobileidentity; + FGCNasMessageContainer fgsnasmessagecontainer; } fgs_security_mode_complete_msg; -int encode_fgs_security_mode_complete(fgs_security_mode_complete_msg *fgs_security_mode_comp, uint8_t *buffer, uint32_t len); +int encode_fgs_security_mode_complete(const fgs_security_mode_complete_msg *fgs_security_mode_comp, uint8_t *buffer, uint32_t len); #endif /* ! defined(FGS_NAS_SECURITY_MODE_COMPLETE_H_) */ - diff --git a/openair3/NAS/COMMON/EMM/MSG/FGSUplinkNasTransport.c b/openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSUplinkNasTransport.c similarity index 62% rename from openair3/NAS/COMMON/EMM/MSG/FGSUplinkNasTransport.c rename to openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSUplinkNasTransport.c index 741ec095c3..6b1b748146 100644 --- a/openair3/NAS/COMMON/EMM/MSG/FGSUplinkNasTransport.c +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSUplinkNasTransport.c @@ -28,16 +28,13 @@ \version 0.1 */ -#include -#include -#include -#include -#include - #include "FGSUplinkNasTransport.h" +#include +#include +#include #include "TLVEncoder.h" -int encode_fgs_payload_container(FGSPayloadContainer *paycontainer, uint8_t iei, uint8_t *buffer, uint32_t len) +static int encode_fgs_payload_container(const FGSPayloadContainer *paycontainer, uint8_t iei, uint8_t *buffer, uint32_t len) { uint32_t encoded = 0; int encode_result; @@ -54,7 +51,7 @@ int encode_fgs_payload_container(FGSPayloadContainer *paycontainer, uint8_t iei, } else { encoded += encode_result; } - if(iei > 0){ + if (iei > 0) { uint16_t tmp = htons(encoded - 3); memcpy(buffer + 1, &tmp, sizeof(tmp)); } else { @@ -65,7 +62,7 @@ int encode_fgs_payload_container(FGSPayloadContainer *paycontainer, uint8_t iei, return encoded; } -int encode_nssai(OctetString *nssai, uint8_t iei, uint8_t *buffer) +static int encode_nssai(const OctetString *nssai, uint8_t iei, uint8_t *buffer) { uint32_t encoded = 0; int encode_result; @@ -78,7 +75,6 @@ int encode_nssai(OctetString *nssai, uint8_t iei, uint8_t *buffer) *(buffer + encoded) = nssai->length; encoded++; - if ((encode_result = encode_octet_string(nssai, buffer + encoded, nssai->length)) < 0) { return encode_result; } else { @@ -88,7 +84,7 @@ int encode_nssai(OctetString *nssai, uint8_t iei, uint8_t *buffer) return encoded; } -int encode_dnn(OctetString *dnn, uint8_t iei, uint8_t *buffer) +static int encode_dnn(const OctetString *dnn, uint8_t iei, uint8_t *buffer) { uint32_t encoded = 0; int encode_result; @@ -110,43 +106,42 @@ int encode_dnn(OctetString *dnn, uint8_t iei, uint8_t *buffer) return encoded; } -int encode_fgs_uplink_nas_transport(fgs_uplink_nas_transport_msg *fgs_up_nas_transport, uint8_t *buffer, uint32_t len) +int encode_fgs_uplink_nas_transport(const fgs_uplink_nas_transport_msg *fgs_up_nas_transport, uint8_t *buffer, uint32_t len) { - int encoded = 0; - int encode_result = 0; + int encoded = 0; + int encode_result = 0; - *(buffer + encoded) = (fgs_up_nas_transport->payloadcontainertype.iei << 4) | (fgs_up_nas_transport->payloadcontainertype.type &0xf); - encoded++; + *(buffer + encoded) = + (fgs_up_nas_transport->payloadcontainertype.iei << 4) | (fgs_up_nas_transport->payloadcontainertype.type & 0xf); + encoded++; - if ((encode_result = encode_fgs_payload_container(&fgs_up_nas_transport->fgspayloadcontainer, - 0, buffer +encoded, len - encoded)) < 0) { - return encode_result; - } else { - encoded += encode_result; - } + if ((encode_result = encode_fgs_payload_container(&fgs_up_nas_transport->fgspayloadcontainer, 0, buffer + encoded, len - encoded)) + < 0) { + return encode_result; + } else { + encoded += encode_result; + } - *(buffer + encoded) = 0x12; - encoded++; + *(buffer + encoded) = 0x12; + encoded++; - IES_ENCODE_U8(buffer, encoded, fgs_up_nas_transport->pdusessionid); + IES_ENCODE_U8(buffer, encoded, fgs_up_nas_transport->pdusessionid); - // set request type - *(buffer + encoded) = (0x8<<4)|(fgs_up_nas_transport->requesttype &0x7); - encoded++; + // set request type + *(buffer + encoded) = (0x8 << 4) | (fgs_up_nas_transport->requesttype & 0x7); + encoded++; - if ((encode_result = encode_nssai(&fgs_up_nas_transport->snssai, 0x22, buffer +encoded)) < 0) { - return encode_result; - } else { - encoded += encode_result; - } + if ((encode_result = encode_nssai(&fgs_up_nas_transport->snssai, 0x22, buffer + encoded)) < 0) { + return encode_result; + } else { + encoded += encode_result; + } - if ((encode_result = encode_dnn(&fgs_up_nas_transport->dnn, 0x25, buffer +encoded)) < 0) { - return encode_result; - } else { - encoded += encode_result; - } + if ((encode_result = encode_dnn(&fgs_up_nas_transport->dnn, 0x25, buffer + encoded)) < 0) { + return encode_result; + } else { + encoded += encode_result; + } - return encoded; + return encoded; } - - diff --git a/openair3/NAS/COMMON/EMM/MSG/FGSUplinkNasTransport.h b/openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSUplinkNasTransport.h similarity index 65% rename from openair3/NAS/COMMON/EMM/MSG/FGSUplinkNasTransport.h rename to openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSUplinkNasTransport.h index 5fabcea173..7b828a1ed3 100644 --- a/openair3/NAS/COMMON/EMM/MSG/FGSUplinkNasTransport.h +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/FGSUplinkNasTransport.h @@ -28,14 +28,10 @@ \version 0.1 */ -#include -#include #include - -#include "ExtendedProtocolDiscriminator.h" -#include "SecurityHeaderType.h" -#include "SpareHalfOctet.h" #include "MessageType.h" +#include "OctetString.h" +#include "SecurityHeaderType.h" #ifndef FGS_UPLINK_NAS_TRANSPORT_H_ #define FGS_UPLINK_NAS_TRANSPORT_H_ @@ -47,31 +43,25 @@ * Direction: UE to network */ -typedef struct PayloadContainerType_tag{ - uint8_t iei:4; - uint8_t type:4; -}PayloadContainerType; +typedef struct PayloadContainerType_tag { + uint8_t iei: 4; + uint8_t type: 4; +} PayloadContainerType; typedef struct FGSPayloadContainer_tag { OctetString payloadcontainercontents; } FGSPayloadContainer; typedef struct fgs_uplink_nas_transport_msg_tag { - /* Mandatory fields */ - ExtendedProtocolDiscriminator protocoldiscriminator; - SecurityHeaderType securityheadertype:4; - SpareHalfOctet sparehalfoctet:4; - MessageType messagetype; - PayloadContainerType payloadcontainertype; - FGSPayloadContainer fgspayloadcontainer; - /* Optional fields */ - uint16_t pdusessionid; - uint8_t requesttype; - OctetString snssai; - OctetString dnn; + /* Mandatory fields */ + PayloadContainerType payloadcontainertype; + FGSPayloadContainer fgspayloadcontainer; + /* Optional fields */ + uint16_t pdusessionid; + uint8_t requesttype; + OctetString snssai; + OctetString dnn; } fgs_uplink_nas_transport_msg; -int encode_fgs_uplink_nas_transport(fgs_uplink_nas_transport_msg *fgs_security_mode_comp, uint8_t *buffer, uint32_t len); +int encode_fgs_uplink_nas_transport(const fgs_uplink_nas_transport_msg *fgs_security_mode_comp, uint8_t *buffer, uint32_t len); #endif /* ! defined(FGS_UPLINK_NAS_TRANSPORT_H_) */ - - diff --git a/openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationAccept.c b/openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationAccept.c new file mode 100644 index 0000000000..d92244a15f --- /dev/null +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationAccept.c @@ -0,0 +1,165 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +/*! \file RegistrationAccept.c + +\brief 5GS registration accept procedures +\author Yoshio INOUE, Masayuki HARADA +\email: yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com +\date 2020 +\version 0.1 +*/ + +#include +#include +#include +#include +#include "conversions.h" +#include "TLVEncoder.h" +#include "TLVDecoder.h" +#include "RegistrationAccept.h" +#include "assertions.h" +#include "fgs_nas_utils.h" + +#define IEI_5G_GUTI 0x77 + +/** + * @brief Allowed NSSAI from Registration Accept according to 3GPP TS 24.501 Table 8.2.7.1.1 + */ +static int decode_nssai_ie(nr_nas_msg_snssai_t *nssai, const uint8_t *buf) +{ + const int length = *buf; // Length of S-NSSAI IE contents (list of S-NSSAIs) + const uint32_t decoded = length + 1; // Length IE (1 octet) + buf++; + int nssai_cnt = 0; + const uint8_t *end = buf + length; + while (buf < end) { + nr_nas_msg_snssai_t *item = nssai + nssai_cnt; + item->sd = 0xffffff; + const int item_len = *buf++; // Length of S-NSSAI IE item + switch (item_len) { + case 1: + item->sst = *buf++; + nssai_cnt++; + break; + + case 2: + item->sst = *buf++; + item->hplmn_sst = *buf++; + nssai_cnt++; + break; + + case 4: + item->sst = *buf++; + item->sd = 0xffffff & ntoh_int24_buf(buf); + buf += 3; + nssai_cnt++; + break; + + case 5: + item->sst = *buf++; + item->sd = 0xffffff & ntoh_int24_buf(buf); + buf += 3; + item->hplmn_sst = *buf++; + nssai_cnt++; + break; + + case 8: + item->sst = *buf++; + item->sd = 0xffffff & ntoh_int24_buf(buf); + buf += 3; + item->hplmn_sst = *buf++; + item->hplmn_sd = 0xffffff & ntoh_int24_buf(buf); + buf += 3; + nssai_cnt++; + break; + + default: + PRINT_NAS_ERROR("Unknown length in Allowed S-NSSAI list item\n"); + break; + } + } + return decoded; +} + +int decode_registration_accept(registration_accept_msg *registration_accept, const uint8_t *buffer, uint32_t len) +{ + int dec = 0; + const uint8_t *end = buffer + len; + + /* Decoding mandatory fields */ + if ((dec = decode_fgs_registration_result(®istration_accept->fgsregistrationresult, 0, *buffer, len)) < 0) + return dec; + buffer += dec; + + if (buffer < end && *buffer == IEI_5G_GUTI) { + registration_accept->guti = calloc_or_fail(1, sizeof(*registration_accept->guti)); + if ((dec = decode_5gs_mobile_identity(registration_accept->guti, IEI_5G_GUTI, buffer, end - buffer)) < 0) { + PRINT_NAS_ERROR("Failed to decode 5GS Mobile Identity in Registration Accept\n"); + return -1; + } + buffer += dec; + } + + // Allowed NSSAI (O) + /* Optional Presence IEs */ + while (buffer < end) { + const int iei = *buffer++; + switch (iei) { + + case 0x15: // allowed NSSAI + dec = decode_nssai_ie(registration_accept->nas_allowed_nssai, buffer); + buffer += dec; + break; + + case 0x31: // configured NSSAI + dec = decode_nssai_ie(registration_accept->config_nssai, buffer); + buffer += dec; + break; + + default: + dec = *buffer++; // content length + 1 byte (Length IE) + buffer += dec; + break; + } + } + return len; +} + +int encode_registration_accept(const registration_accept_msg *registration_accept, uint8_t *buffer, uint32_t len) +{ + int encoded = 0; + + LOG_FUNC_IN; + + *(buffer + encoded) = encode_fgs_registration_result(®istration_accept->fgsregistrationresult); + encoded = encoded + 2; + + if (registration_accept->guti) { + int mi_enc = encode_5gs_mobile_identity(registration_accept->guti, 0x77, buffer + encoded, len - encoded); + if (mi_enc < 0) + return mi_enc; + encoded += mi_enc; + } + + // todo ,Encoding optional fields + LOG_FUNC_RETURN(encoded); +} diff --git a/openair3/NAS/COMMON/EMM/MSG/RegistrationAccept.h b/openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationAccept.h similarity index 80% rename from openair3/NAS/COMMON/EMM/MSG/RegistrationAccept.h rename to openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationAccept.h index 30c434c662..6abf1e70ca 100644 --- a/openair3/NAS/COMMON/EMM/MSG/RegistrationAccept.h +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationAccept.h @@ -32,10 +32,7 @@ #include #include - -#include "ExtendedProtocolDiscriminator.h" #include "SecurityHeaderType.h" -#include "SpareHalfOctet.h" #include "MessageType.h" #include "FGSRegistrationResult.h" #include "FGSMobileIdentity.h" @@ -43,6 +40,14 @@ #ifndef REGISTRATION_ACCEPT_H_ #define REGISTRATION_ACCEPT_H_ +// 9.11.3.37 of 3GPP TS 24.501 +typedef struct { + int sst; + int hplmn_sst; + int sd; + int hplmn_sd; +} nr_nas_msg_snssai_t; + /* * Message name: Registration accept * Description: The REGISTRATION ACCEPT message is sent by the AMF to the UE. See table 8.2.7.1.1. @@ -52,19 +57,17 @@ typedef struct registration_accept_msg_tag { /* Mandatory fields */ - ExtendedProtocolDiscriminator protocoldiscriminator; - SecurityHeaderType securityheadertype:4; - SpareHalfOctet sparehalfoctet:4; - MessageType messagetype; - FGSRegistrationResult fgsregistrationresult; - + FGSRegistrationResult fgsregistrationresult; /* Optional fields */ FGSMobileIdentity *guti; + // Allowed NSSAI (O) + nr_nas_msg_snssai_t nas_allowed_nssai[8]; + // Configured NSSAI (O) + nr_nas_msg_snssai_t config_nssai[8]; } registration_accept_msg; int decode_registration_accept(registration_accept_msg *registrationaccept, const uint8_t *buffer, uint32_t len); -int encode_registration_accept(registration_accept_msg *registrationaccept, uint8_t *buffer, uint32_t len); +int encode_registration_accept(const registration_accept_msg *registrationaccept, uint8_t *buffer, uint32_t len); #endif /* ! defined(REGISTRATION_ACCEPT_H_) */ - diff --git a/openair3/NAS/COMMON/EMM/MSG/RegistrationComplete.c b/openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationComplete.c similarity index 71% rename from openair3/NAS/COMMON/EMM/MSG/RegistrationComplete.c rename to openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationComplete.c index 668e665351..0ce14cdcd8 100644 --- a/openair3/NAS/COMMON/EMM/MSG/RegistrationComplete.c +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationComplete.c @@ -19,24 +19,19 @@ * contact@openairinterface.org */ -#include -#include -#include -#include - - -#include "TLVEncoder.h" -#include "TLVDecoder.h" #include "RegistrationComplete.h" +#include #include "SORTransparentContainer.h" -int decode_registration_complete(registration_complete_msg *registration_complete, uint8_t *buffer, uint32_t len) +int decode_registration_complete(registration_complete_msg *registration_complete, const uint8_t *buffer, uint32_t len) { uint32_t decoded = 0; int decoded_result = 0; /* Decoding mandatory fields */ - if ((decoded_result = decode_sor_transparent_container(®istration_complete->sortransparentcontainer, 0, buffer + decoded, len - decoded)) < 0) + if ((decoded_result = + decode_sor_transparent_container(registration_complete->sortransparentcontainer, 0, buffer + decoded, len - decoded)) + < 0) return decoded_result; else decoded += decoded_result; @@ -44,18 +39,20 @@ int decode_registration_complete(registration_complete_msg *registration_complet return decoded; } -int encode_registration_complete(registration_complete_msg *registration_complete, uint8_t *buffer, uint32_t len) +int encode_registration_complete(const registration_complete_msg *registration_complete, uint8_t *buffer, uint32_t len) { int encoded = 0; int encode_result = 0; + if (!registration_complete->sortransparentcontainer) + return encoded; + if ((encode_result = - encode_sor_transparent_container(®istration_complete->sortransparentcontainer, 0, - buffer + encoded, len - encoded)) < 0) //Return in case of error + encode_sor_transparent_container(registration_complete->sortransparentcontainer, 0, buffer + encoded, len - encoded)) + < 0) // Return in case of error return encode_result; else encoded += encode_result; return encoded; } - diff --git a/openair3/NAS/COMMON/EMM/MSG/RegistrationComplete.h b/openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationComplete.h similarity index 72% rename from openair3/NAS/COMMON/EMM/MSG/RegistrationComplete.h rename to openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationComplete.h index 0fbf2abde1..1c2141243a 100644 --- a/openair3/NAS/COMMON/EMM/MSG/RegistrationComplete.h +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationComplete.h @@ -28,35 +28,21 @@ \version 0.1 */ -#include -#include #include - -#include "ExtendedProtocolDiscriminator.h" -#include "SecurityHeaderType.h" -#include "SpareHalfOctet.h" #include "MessageType.h" #include "SORTransparentContainer.h" +#include "SecurityHeaderType.h" #ifndef REGISTRATION_COMPLETE_H_ #define REGISTRATION_COMPLETE_H_ - typedef struct registration_complete_msg_tag { - /* Mandatory fields */ - ExtendedProtocolDiscriminator protocoldiscriminator; - SecurityHeaderType securityheadertype:4; - SpareHalfOctet sparehalfoctet:4; - MessageType messagetype; - /* Optional fields */ - SORTransparentContainer sortransparentcontainer; + SORTransparentContainer *sortransparentcontainer; } registration_complete_msg; +int decode_registration_complete(registration_complete_msg *registrationcomplete, const uint8_t *buffer, uint32_t len); -int decode_registration_complete(registration_complete_msg *registrationcomplete, uint8_t *buffer, uint32_t len); - -int encode_registration_complete(registration_complete_msg *registrationcomplete, uint8_t *buffer, uint32_t len); +int encode_registration_complete(const registration_complete_msg *registrationcomplete, uint8_t *buffer, uint32_t len); #endif /* ! defined(REGISTRATION_COMPLETE_H_) */ - diff --git a/openair3/NAS/COMMON/EMM/MSG/RegistrationRequest.c b/openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationRequest.c similarity index 73% rename from openair3/NAS/COMMON/EMM/MSG/RegistrationRequest.c rename to openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationRequest.c index cf18e46ca2..8f6fea900e 100644 --- a/openair3/NAS/COMMON/EMM/MSG/RegistrationRequest.c +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationRequest.c @@ -27,28 +27,25 @@ * \version 0.1 */ -#include -#include -#include +#include "RegistrationRequest.h" #include - +#include "T.h" #include "nas_log.h" -#include "RegistrationRequest.h" -#include "NR_NAS_defs.h" +#define IEI_NULL 0x00 -int decode_registration_request(registration_request_msg *registration_request, uint8_t *buffer, uint32_t len) +int decode_registration_request(registration_request_msg *registration_request, const uint8_t *buffer, uint32_t len) { uint32_t decoded = 0; int decoded_result = 0; LOG_FUNC_IN; - LOG_TRACE(INFO, "EMM - registration_request len = %d", - len); + LOG_TRACE(INFO, "5GMM: Registration Request len = %d", len); /* Decoding mandatory fields */ - if ((decoded_result = decode_5gs_registration_type(®istration_request->fgsregistrationtype, 0, *(buffer + decoded) & 0x0f, len - decoded)) < 0) { - // return decoded_result; + if ((decoded_result = + decode_5gs_registration_type(®istration_request->fgsregistrationtype, 0, *(buffer + decoded) & 0x0f, len - decoded)) + < 0) { LOG_FUNC_RETURN(decoded_result); } @@ -60,19 +57,18 @@ int decode_registration_request(registration_request_msg *registration_request, decoded++; - if ((decoded_result = decode_5gs_mobile_identity(®istration_request->fgsmobileidentity, 0, buffer + decoded, len - decoded)) < 0) { - // return decoded_result; + if ((decoded_result = decode_5gs_mobile_identity(®istration_request->fgsmobileidentity, 0, buffer + decoded, len - decoded)) + < 0) { LOG_FUNC_RETURN(decoded_result); } else decoded += decoded_result; - // TODO, Decoding optional fields return decoded; } -int encode_registration_request(registration_request_msg *registration_request, uint8_t *buffer, uint32_t len) +int encode_registration_request(const registration_request_msg *registration_request, uint8_t *buffer, uint32_t len) { int encoded = 0; int encode_result = 0; @@ -81,9 +77,9 @@ int encode_registration_request(registration_request_msg *registration_request, | (encode_5gs_registration_type(®istration_request->fgsregistrationtype) & 0x0f); encoded++; - if ((encode_result = - encode_5gs_mobile_identity(®istration_request->fgsmobileidentity, 0, buffer + - encoded, len - encoded)) < 0) //Return in case of error + if ((encode_result = encode_5gs_mobile_identity(®istration_request->fgsmobileidentity, 0, buffer + encoded, len - encoded)) + < 0) + // Return in case of error return encode_result; else encoded += encode_result; @@ -91,8 +87,10 @@ int encode_registration_request(registration_request_msg *registration_request, if ((registration_request->presencemask & REGISTRATION_REQUEST_5GMM_CAPABILITY_PRESENT) == REGISTRATION_REQUEST_5GMM_CAPABILITY_PRESENT) { if ((encode_result = encode_5gmm_capability(®istration_request->fgmmcapability, - REGISTRATION_REQUEST_5GMM_CAPABILITY_IEI, buffer + encoded, len - - encoded)) < 0) + REGISTRATION_REQUEST_5GMM_CAPABILITY_IEI, + buffer + encoded, + len - encoded)) + < 0) // Return in case of error return encode_result; else @@ -102,16 +100,16 @@ int encode_registration_request(registration_request_msg *registration_request, if ((registration_request->presencemask & REGISTRATION_REQUEST_UE_SECURITY_CAPABILITY_PRESENT) == REGISTRATION_REQUEST_UE_SECURITY_CAPABILITY_PRESENT) { if ((encode_result = encode_nrue_security_capability(®istration_request->nruesecuritycapability, - REGISTRATION_REQUEST_UE_SECURITY_CAPABILITY_IEI, buffer + encoded, len - - encoded)) < 0) + REGISTRATION_REQUEST_UE_SECURITY_CAPABILITY_IEI, + buffer + encoded, + len - encoded)) + < 0) // Return in case of error return encode_result; else encoded += encode_result; } - // TODO, Encoding optional fields return encoded; } - diff --git a/openair3/NAS/COMMON/EMM/MSG/RegistrationRequest.h b/openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationRequest.h similarity index 54% rename from openair3/NAS/COMMON/EMM/MSG/RegistrationRequest.h rename to openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationRequest.h index ce534bfff9..686b0bc148 100644 --- a/openair3/NAS/COMMON/EMM/MSG/RegistrationRequest.h +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/RegistrationRequest.h @@ -27,25 +27,19 @@ * \version 0.1 */ - -#include -#include #include - -#include "ExtendedProtocolDiscriminator.h" -#include "SecurityHeaderType.h" -#include "SpareHalfOctet.h" +#include "FGMMCapability.h" #include "FGSMobileIdentity.h" -#include "NasKeySetIdentifier.h" #include "FGSRegistrationType.h" #include "MessageType.h" -#include "FGMMCapability.h" +#include "NasKeySetIdentifier.h" #include "NrUESecurityCapability.h" +#include "SecurityHeaderType.h" #ifndef REGISTRATION_REQUEST_H_ #define REGISTRATION_REQUEST_H_ - +// clang-format off # define REGISTRATION_REQUEST_NON_CURRENT_NATIVE_NAS_KEYSET_PRESENT (1<<0) # define REGISTRATION_REQUEST_5GMM_CAPABILITY_PRESENT (1<<1) # define REGISTRATION_REQUEST_UE_SECURITY_CAPABILITY_PRESENT (1<<2) @@ -70,29 +64,30 @@ # define REGISTRATION_REQUEST_EPS_BEARER_CONTEXT_STATUS_PRESENT (1<<21) typedef enum registration_request_iei_tag { - REGISTRATION_REQUEST_NON_CURRENT_NATIVE_NAS_KEYSET_IEI = 0xC0, /* 0xC- = 192- */ - REGISTRATION_REQUEST_5GMM_CAPABILITY_IEI = 0x10, /* 0x10 = 16 */ - REGISTRATION_REQUEST_UE_SECURITY_CAPABILITY_IEI = 0x2E, /* 0x2E = 46 */ - REGISTRATION_REQUEST_REQUESTED_NSSAI_IEI = 0x2F, /* 0x2F = 47 */ - REGISTRATION_REQUEST_LAST_VISITED_REGISTERED_TAI_IEI = 0x52, /* 0x52 = 82 */ - REGISTRATION_REQUEST_S1_UE_NETWORK_CAPABILITY_IEI = 0x17, /* 0x17 = 23 */ - REGISTRATION_REQUEST_UPLINK_DATA_STATUS_IEI = 0x40, /* 0x40 = 64 */ - REGISTRATION_REQUEST_PDU_SESSION_STATUS_IEI = 0x50, /* 0x50 = 80 */ - REGISTRATION_REQUEST_MICO_INDICATION_IEI = 0xB0, /* 0xB- = 176- */ - REGISTRATION_REQUEST_UE_STATUS_IEI = 0x2B, /* 0x2B = 43 */ - REGISTRATION_REQUEST_ADDITIONAL_GUTI_IEI = 0x77, /* 0x77 = 119 */ - REGISTRATION_REQUEST_ALLOWED_PDU_SESSION_STATUS_IEI = 0x25, /* 0x25 = 37 */ - REGISTRATION_REQUEST_UE_USAGE_SETTING_IEI = 0x18, /* 0x18 = 24 */ - REGISTRATION_REQUEST_REQUESTED_DRX_PARAMETERS_IEI = 0x51, /* 0x51 = 81 */ - REGISTRATION_REQUEST_EPS_NAS_MESSAGE_CONTAINER_IEI = 0x70, /* 0x70 = 112 */ - REGISTRATION_REQUEST_LADN_INDICATION_IEI = 0x74, /* 0x74 = 116 */ - REGISTRATION_REQUEST_PAYLOAD_CONTAINER_TYPE_IEI = 0x80, /* 0x80 = 128 */ - REGISTRATION_REQUEST_PAYLOAD_CONTAINER_IEI = 0x7B, /* 0x7B = 123 */ - REGISTRATION_REQUEST_NETWORK_SLICING_INDICATION_IEI = 0x90, /* 0x90 = 144 */ - REGISTRATION_REQUEST_5GS_UPDATE_TYPE_IEI = 0x53, /* 0x53 = 83 */ - REGISTRATION_REQUEST_NAS_MESSAGE_CONTAINER_IEI = 0x71, /* 0x71 = 113 */ - REGISTRATION_REQUEST_EPS_BEARER_CONTEXT_STATUS_IEI = 0x60 /* 0x60 = 96 */ + REGISTRATION_REQUEST_NON_CURRENT_NATIVE_NAS_KEYSET_IEI = 0xC0, /* 0xC- = 192- */ + REGISTRATION_REQUEST_5GMM_CAPABILITY_IEI = 0x10, /* 0x10 = 16 */ + REGISTRATION_REQUEST_UE_SECURITY_CAPABILITY_IEI = 0x2E, /* 0x2E = 46 */ + REGISTRATION_REQUEST_REQUESTED_NSSAI_IEI = 0x2F, /* 0x2F = 47 */ + REGISTRATION_REQUEST_LAST_VISITED_REGISTERED_TAI_IEI = 0x52, /* 0x52 = 82 */ + REGISTRATION_REQUEST_S1_UE_NETWORK_CAPABILITY_IEI = 0x17, /* 0x17 = 23 */ + REGISTRATION_REQUEST_UPLINK_DATA_STATUS_IEI = 0x40, /* 0x40 = 64 */ + REGISTRATION_REQUEST_PDU_SESSION_STATUS_IEI = 0x50, /* 0x50 = 80 */ + REGISTRATION_REQUEST_MICO_INDICATION_IEI = 0xB0, /* 0xB- = 176- */ + REGISTRATION_REQUEST_UE_STATUS_IEI = 0x2B, /* 0x2B = 43 */ + REGISTRATION_REQUEST_ADDITIONAL_GUTI_IEI = 0x77, /* 0x77 = 119 */ + REGISTRATION_REQUEST_ALLOWED_PDU_SESSION_STATUS_IEI = 0x25, /* 0x25 = 37 */ + REGISTRATION_REQUEST_UE_USAGE_SETTING_IEI = 0x18, /* 0x18 = 24 */ + REGISTRATION_REQUEST_REQUESTED_DRX_PARAMETERS_IEI = 0x51, /* 0x51 = 81 */ + REGISTRATION_REQUEST_EPS_NAS_MESSAGE_CONTAINER_IEI = 0x70, /* 0x70 = 112 */ + REGISTRATION_REQUEST_LADN_INDICATION_IEI = 0x74, /* 0x74 = 116 */ + REGISTRATION_REQUEST_PAYLOAD_CONTAINER_TYPE_IEI = 0x80, /* 0x80 = 128 */ + REGISTRATION_REQUEST_PAYLOAD_CONTAINER_IEI = 0x7B, /* 0x7B = 123 */ + REGISTRATION_REQUEST_NETWORK_SLICING_INDICATION_IEI = 0x90, /* 0x90 = 144 */ + REGISTRATION_REQUEST_5GS_UPDATE_TYPE_IEI = 0x53, /* 0x53 = 83 */ + REGISTRATION_REQUEST_NAS_MESSAGE_CONTAINER_IEI = 0x71, /* 0x71 = 113 */ + REGISTRATION_REQUEST_EPS_BEARER_CONTEXT_STATUS_IEI = 0x60 /* 0x60 = 96 */ } registration_request_iei; +// clang-format on /* * Message name: Registration request @@ -103,23 +98,17 @@ typedef enum registration_request_iei_tag { typedef struct registration_request_msg_tag { /* Mandatory fields */ - ExtendedProtocolDiscriminator protocoldiscriminator; - SecurityHeaderType securityheadertype:4; - SpareHalfOctet sparehalfoctet:4; - MessageType messagetype; - FGSRegistrationType fgsregistrationtype; - NasKeySetIdentifier naskeysetidentifier; - FGSMobileIdentity fgsmobileidentity; - + FGSRegistrationType fgsregistrationtype; + NasKeySetIdentifier naskeysetidentifier; + FGSMobileIdentity fgsmobileidentity; /* Optional fields */ - uint32_t presencemask; - FGMMCapability fgmmcapability; - NrUESecurityCapability nruesecuritycapability; + uint32_t presencemask; + FGMMCapability fgmmcapability; + NrUESecurityCapability nruesecuritycapability; } registration_request_msg; -int decode_registration_request(registration_request_msg *registrationrequest, uint8_t *buffer, uint32_t len); +int decode_registration_request(registration_request_msg *registrationrequest, const uint8_t *buffer, uint32_t len); -int encode_registration_request(registration_request_msg *registrationrequest, uint8_t *buffer, uint32_t len); +int encode_registration_request(const registration_request_msg *registrationrequest, uint8_t *buffer, uint32_t len); #endif /* ! defined(REGISTRATION_REQUEST_H_) */ - diff --git a/openair3/NAS/COMMON/EMM/MSG/fgs_service_request.c b/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgs_service_request.c similarity index 95% rename from openair3/NAS/COMMON/EMM/MSG/fgs_service_request.c rename to openair3/NAS/NR_UE/5GS/5GMM/MSG/fgs_service_request.c index 85e67498a5..4603db55c5 100644 --- a/openair3/NAS/COMMON/EMM/MSG/fgs_service_request.c +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgs_service_request.c @@ -30,15 +30,15 @@ #include "FGSMobileIdentity.h" #include "NasKeySetIdentifier.h" #include "ServiceType.h" -#include "NR_NAS_defs.h" #define LEN_FGS_MOBILE_ID_CONTENTS_SIZE 2 // octets #define MIN_LEN_FGS_SERVICE_REQUEST 10 // octets +#define IEI_NULL 0x00 /** * @brief Encode 5GMM NAS Service Request message (8.2.16 of 3GPP TS 24.501) */ -int encode_fgs_service_request(uint8_t *buffer, fgs_service_request_msg_t *service_request, uint32_t len) +int encode_fgs_service_request(uint8_t *buffer, const fgs_service_request_msg_t *service_request, uint32_t len) { // Return if buffer is shorter than min length if (len < MIN_LEN_FGS_SERVICE_REQUEST) diff --git a/openair3/NAS/COMMON/EMM/MSG/fgs_service_request.h b/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgs_service_request.h similarity index 91% rename from openair3/NAS/COMMON/EMM/MSG/fgs_service_request.h rename to openair3/NAS/NR_UE/5GS/5GMM/MSG/fgs_service_request.h index eecd1ee34a..82a721d52a 100644 --- a/openair3/NAS/COMMON/EMM/MSG/fgs_service_request.h +++ b/openair3/NAS/NR_UE/5GS/5GMM/MSG/fgs_service_request.h @@ -27,11 +27,8 @@ #include "SecurityHeaderType.h" #include "NasKeySetIdentifier.h" #include "ServiceType.h" -#include "ExtendedProtocolDiscriminator.h" #include "FGCNasMessageContainer.h" -//#include "PDUSessionStatus.h" #include "MessageType.h" -#include "SpareHalfOctet.h" #include "FGSMobileIdentity.h" #ifndef FGS_SERVICE_REQUEST_H_ @@ -56,7 +53,7 @@ typedef struct { FGCNasMessageContainer *fgsnasmessagecontainer; } fgs_service_request_msg_t; -int encode_fgs_service_request(uint8_t *buffer, fgs_service_request_msg_t *servicerequest, uint32_t len); +int encode_fgs_service_request(uint8_t *buffer, const fgs_service_request_msg_t *servicerequest, uint32_t len); int decode_fgs_service_request(fgs_service_request_msg_t *sr, const uint8_t *buffer, uint32_t len); #endif /* ! defined(FGS_SERVICE_REQUEST_H_) */ diff --git a/openair3/NAS/NR_UE/5GS/5GSM/MSG/CMakeLists.txt b/openair3/NAS/NR_UE/5GS/5GSM/MSG/CMakeLists.txt new file mode 100644 index 0000000000..1630a48222 --- /dev/null +++ b/openair3/NAS/NR_UE/5GS/5GSM/MSG/CMakeLists.txt @@ -0,0 +1,6 @@ +add_library(fgs_5gsm_lib OBJECT PduSessionEstablishRequest.c + PduSessionEstablishmentAccept.c) + +target_link_libraries(fgs_5gsm_lib PUBLIC nas_common_ies_lib) + +target_include_directories(fgs_5gsm_lib PUBLIC . ../../) diff --git a/openair3/NAS/COMMON/ESM/MSG/PduSessionEstablishRequest.c b/openair3/NAS/NR_UE/5GS/5GSM/MSG/PduSessionEstablishRequest.c similarity index 95% rename from openair3/NAS/COMMON/ESM/MSG/PduSessionEstablishRequest.c rename to openair3/NAS/NR_UE/5GS/5GSM/MSG/PduSessionEstablishRequest.c index 1c9198b720..6c4592e2e2 100644 --- a/openair3/NAS/COMMON/ESM/MSG/PduSessionEstablishRequest.c +++ b/openair3/NAS/NR_UE/5GS/5GSM/MSG/PduSessionEstablishRequest.c @@ -28,22 +28,14 @@ \version 0.1 */ -#include -#include -#include -#include - - -#include "TLVEncoder.h" -#include "TLVDecoder.h" #include "PduSessionEstablishRequest.h" - +#include +#include "TLVEncoder.h" int encode_pdu_session_establishment_request(pdu_session_establishment_request_msg *pdusessionestablishrequest, uint8_t *buffer) { int encoded = 0; - *(buffer + encoded) = pdusessionestablishrequest->protocoldiscriminator; encoded++; *(buffer + encoded) = pdusessionestablishrequest->pdusessionid; @@ -59,5 +51,3 @@ int encode_pdu_session_establishment_request(pdu_session_establishment_request_m return encoded; } - - diff --git a/openair3/NAS/COMMON/ESM/MSG/PduSessionEstablishRequest.h b/openair3/NAS/NR_UE/5GS/5GSM/MSG/PduSessionEstablishRequest.h similarity index 75% rename from openair3/NAS/COMMON/ESM/MSG/PduSessionEstablishRequest.h rename to openair3/NAS/NR_UE/5GS/5GSM/MSG/PduSessionEstablishRequest.h index e2742ebc38..3d61491968 100644 --- a/openair3/NAS/COMMON/ESM/MSG/PduSessionEstablishRequest.h +++ b/openair3/NAS/NR_UE/5GS/5GSM/MSG/PduSessionEstablishRequest.h @@ -31,35 +31,28 @@ #include #include #include - -#include "ExtendedProtocolDiscriminator.h" #include "MessageType.h" #ifndef PDU_SESSION_ESTABLISHMENT_REQUEST_H_ #define PDU_SESSION_ESTABLISHMENT_REQUEST_H_ - /* * Message name: pdu session establishment request - * Description: The PDU SESSION ESTABLISHMENT REQUEST message is sent by the UE to the SMF to initiate establishment of a PDU session. See table 8.3.1.1.1. - * Significance: dual - * Direction: UE to network + * Description: The PDU SESSION ESTABLISHMENT REQUEST message is sent by the UE to the SMF to initiate establishment of a PDU + * session. See table 8.3.1.1.1. Significance: dual Direction: UE to network */ typedef struct pdu_session_establishment_request_msg_tag { - /* Mandatory fields */ - ExtendedProtocolDiscriminator protocoldiscriminator; - uint8_t pdusessionid; - uint8_t pti; - MessageType pdusessionestblishmsgtype; - uint16_t maxdatarate; - uint8_t pdusessiontype; - /* Optional fields */ + /* Mandatory fields */ + uint8_t protocoldiscriminator; + uint8_t pdusessionid; + uint8_t pti; + MessageType pdusessionestblishmsgtype; + uint16_t maxdatarate; + uint8_t pdusessiontype; + /* Optional fields */ } pdu_session_establishment_request_msg; - int encode_pdu_session_establishment_request(pdu_session_establishment_request_msg *pdusessionestablishrequest, uint8_t *buffer); #endif /* ! defined(PDU_SESSION_ESTABLISHMENT_REQUEST_H_) */ - - diff --git a/openair3/NAS/NR_UE/5GS/5GSM/MSG/PduSessionEstablishmentAccept.c b/openair3/NAS/NR_UE/5GS/5GSM/MSG/PduSessionEstablishmentAccept.c new file mode 100644 index 0000000000..50b66845c6 --- /dev/null +++ b/openair3/NAS/NR_UE/5GS/5GSM/MSG/PduSessionEstablishmentAccept.c @@ -0,0 +1,215 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include +#include +#include "PduSessionEstablishmentAccept.h" +#include "common/utils/LOG/log.h" +#include "common/utils/tun_if.h" +#include "fgs_nas_utils.h" + +/** + * @brief Returns the size of the single QoS rule IE + */ +static uint8_t get_len_qos_rule(qos_rule_t *rule) +{ + return rule->length + sizeof(rule->id) + sizeof(rule->length); +} + +/** + * @brief Decode QoS Rule (9.11.4.13 of 3GPP TS 24.501) + */ +static qos_rule_t decode_qos_rule(uint8_t *buf) +{ + qos_rule_t qos_rule = {0}; + // octet 4 + qos_rule.id = *buf++; + // octet 5 - 6 + GET_SHORT(buf, qos_rule.length); + buf += sizeof(qos_rule.length); + // octet 7 + qos_rule.oc = (*(buf)&0xE0) >> 5; + qos_rule.dqr = (*(buf)&0x10) >> 4; + qos_rule.nb_pf = *buf++ & 0x0F; + // octet 8 - m + for (int i = 0; i < qos_rule.nb_pf; i++) { + packet_filter_t pf; + if (qos_rule.oc == ROC_CREATE_NEW_QOS_RULE || qos_rule.oc == ROC_MODIFY_QOS_RULE_ADD_PF + || qos_rule.oc == ROC_MODIFY_QOS_RULE_REPLACE_PF) { + pf.pf_type.type_1.pf_dir = (*buf & 0x30) >> 4; + pf.pf_type.type_1.pf_id = *buf++ & 0x0F; + pf.pf_type.type_1.length = *buf++; + buf += pf.pf_type.type_1.length; // skip PF content + } else if (qos_rule.oc == ROC_MODIFY_QOS_RULE_DELETE_PF) { + pf.pf_type.type_2.pf_id = *buf++; + } + } + // octet m + 1 + qos_rule.precendence = *buf++; + // octet m + 2 + qos_rule.qfi = *buf++ & 0x3F; + return qos_rule; +} + +/** + * @brief PDU session establishment accept (8.3.2 of 3GPP TS 24.501) + * network to UE + */ +int decode_pdu_session_establishment_accept_msg(pdu_session_establishment_accept_msg_t *psea_msg, uint8_t *buffer, uint32_t msg_length) +{ + uint8_t *curPtr = buffer; + + /* Mandatory PDU Session Establishment Accept IEs */ + // PDU Session Type (half octet) + psea_msg->pdu_type = *curPtr & 0x0f; + // SSC Mode (half octet) + psea_msg->ssc_mode = (*curPtr++ & 0xf0) >> 4; + // Authorized QoS Rules + auth_qos_rule_t *qos_rules = &psea_msg->qos_rules; + // Length of the rule IEs (2 octets) + GET_SHORT(curPtr, qos_rules->length); + curPtr += sizeof(qos_rules->length); + /* Decode rule IEs as long as the total length + of all IEs (qos_rules->length) is not reached */ + uint16_t rules_tot_len = 0; + while (rules_tot_len < qos_rules->length) + { + qos_rules->rule[0] = decode_qos_rule(curPtr); + rules_tot_len += get_len_qos_rule(&qos_rules->rule[0]); + curPtr += rules_tot_len; + } + // Session-AMBR (M) + psea_msg->sess_ambr.length = *curPtr++; + curPtr += psea_msg->sess_ambr.length; // skip content + + uint8_t *resPtr = curPtr; + + /* Optional Presence IEs */ + while (curPtr < buffer + msg_length) { + uint8_t psea_iei = *curPtr++; + LOG_T(NAS, "PDU SESSION ESTABLISHMENT ACCEPT - Received %s IEI\n", iei_text_desc[psea_iei].text); + switch (psea_iei) { + case IEI_5GSM_CAUSE: /* Ommited */ + curPtr++; + break; + + case IEI_PDU_ADDRESS: + psea_msg->pdu_addr_ie.pdu_length = *curPtr++; + + /* Octet 3 */ + // PDU type (3 bits) + psea_msg->pdu_addr_ie.pdu_type = *curPtr & 0x07; + // SMF's IPv6 link local address (1 bit) + uint8_t si6lla = (*curPtr >> 3) & 0x01; + if (si6lla) + LOG_E(NAS, "SMF's IPv6 link local address is not handled\n"); + curPtr++; + + /* Octet 4 to n */ + // PDU address information + uint8_t *addr = psea_msg->pdu_addr_ie.pdu_addr_oct; + if (psea_msg->pdu_addr_ie.pdu_type == PDU_SESSION_TYPE_IPV4) { + for (int i = 0; i < IPv4_ADDRESS_LENGTH; ++i) + addr[i] = *curPtr++; + LOG_I(NAS, "Received PDU Session Establishment Accept, UE IPv4: %u.%u.%u.%u\n", addr[0], addr[1], addr[2], addr[3]); + } else if (psea_msg->pdu_addr_ie.pdu_type == PDU_SESSION_TYPE_IPV6) { + for (int i = 0; i < IPv6_INTERFACE_ID_LENGTH; ++i) + addr[i] = *curPtr++; + LOG_I(NAS, "Received PDU Session Establishment Accept, UE IPv6: %u.%u.%u.%u.%u.%u.%u.%u\n", + addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7]); + } else if (psea_msg->pdu_addr_ie.pdu_type == PDU_SESSION_TYPE_IPV4V6) { + // 24.501 Sec 9.11.4.10: "If the PDU session type value indicates + // IPv4v6, the PDU address information in octet 4 to octet 11 + // contains an interface identifier for the IPv6 link local address + // and in octet 12 to octet 15 contains an IPv4 address." + for (int i = 0; i < IPv4_ADDRESS_LENGTH + IPv6_INTERFACE_ID_LENGTH; ++i) + addr[i] = *curPtr++; + LOG_I(NAS, "Received PDU Session Establishment Accept, UE IPv4v6: %u.%u.%u.%u/%u.%u.%u.%u.%u.%u.%u.%u\n", + addr[0], addr[1], addr[2], addr[3], + addr[4], addr[5], addr[6], addr[7], addr[8], addr[9], addr[10], addr[11]); + } else { + LOG_E(NAS, "unknown/unhandled PDU session establishment accept PDU type %d\n", psea_msg->pdu_addr_ie.pdu_type); + curPtr += psea_msg->pdu_addr_ie.pdu_length; + } + break; + + case IEI_RQ_TIMER_VALUE: /* Ommited */ + curPtr++; /* TS 24.008 10.5.7.3 */ + break; + + case IEI_SNSSAI: { + uint8_t snssai_length = *curPtr; + curPtr += (snssai_length + sizeof(snssai_length)); + break; + } + + case IEI_ALWAYSON_PDU: /* Ommited */ + curPtr++; + break; + + case IEI_MAPPED_EPS: { + uint16_t mapped_eps_length = 0; + GET_SHORT(curPtr, mapped_eps_length); + curPtr += mapped_eps_length; + break; + } + + case IEI_EAP_MSG: { + uint16_t eap_length = 0; + GET_SHORT(curPtr, eap_length); + curPtr += (eap_length + sizeof(eap_length)); + break; + } + + case IEI_AUTH_QOS_DESC: { + GET_SHORT(curPtr, psea_msg->qos_fd_ie.length); + curPtr += (psea_msg->qos_fd_ie.length + sizeof(psea_msg->qos_fd_ie.length)); + break; + } + + case IEI_EXT_CONF_OPT: { + GET_SHORT(curPtr, psea_msg->ext_pp_ie.length); + curPtr += (psea_msg->ext_pp_ie.length + sizeof(psea_msg->ext_pp_ie.length)); + break; + } + + case IEI_DNN: { + psea_msg->dnn_ie.dnn_length = *curPtr++; + char apn[APN_MAX_LEN]; + + if (psea_msg->dnn_ie.dnn_length <= APN_MAX_LEN && psea_msg->dnn_ie.dnn_length >= APN_MIN_LEN) { + memcpy(apn, curPtr, psea_msg->dnn_ie.dnn_length); + LOG_T(NAS, "PDU SESSION ESTABLISHMENT ACCEPT - APN: %s\n", apn); + } else + LOG_E(NAS, "PDU SESSION ESTABLISHMENT ACCEPT - DNN IE has invalid length\n"); + resPtr = curPtr; + curPtr = buffer + msg_length; // we force stop processing + break; + } + + default: + PRINT_NAS_ERROR("Unknown IEI %d\n", psea_iei); + curPtr = buffer + msg_length; // we force stop processing + break; + } + } + return resPtr - buffer; +} diff --git a/openair3/NAS/COMMON/ESM/MSG/PduSessionEstablishmentAccept.h b/openair3/NAS/NR_UE/5GS/5GSM/MSG/PduSessionEstablishmentAccept.h similarity index 54% rename from openair3/NAS/COMMON/ESM/MSG/PduSessionEstablishmentAccept.h rename to openair3/NAS/NR_UE/5GS/5GSM/MSG/PduSessionEstablishmentAccept.h index c283079998..80694814b4 100644 --- a/openair3/NAS/COMMON/ESM/MSG/PduSessionEstablishmentAccept.h +++ b/openair3/NAS/NR_UE/5GS/5GSM/MSG/PduSessionEstablishmentAccept.h @@ -23,31 +23,39 @@ #define PDU_SESSION_ESTABLISHMENT_ACCEPT_H_ #include +#include +#include "fgs_nas_utils.h" /* PDU Session Establish Accept Optional IE Identifiers - TS 24.501 Table 8.3.2.1.1 */ -#define IEI_5GSM_CAUSE 0x59 /* 5GSM cause 9.11.4.2 */ -#define IEI_PDU_ADDRESS 0x29 /* PDU address 9.11.4.10 */ -#define IEI_RQ_TIMER_VALUE 0x56 /* GPRS timer 9.11.2.3 */ -#define IEI_SNSSAI 0x22 /* S-NSSAI 9.11.2.8 */ -#define IEI_ALWAYSON_PDU 0x80 /* Always-on PDU session indication 9.11.4.3 */ -#define IEI_MAPPED_EPS 0x75 /* Mapped EPS bearer contexts 9.11.4.8 */ -#define IEI_EAP_MSG 0x78 /* EAP message 9.11.2.2 */ -#define IEI_AUTH_QOS_DESC 0x79 /* QoS flow descriptions 9.11.4.12 */ -#define IEI_EXT_CONF_OPT 0x7b /* Extended protocol configuration options 9.11.4.6 */ -#define IEI_DNN 0x25 /* DNN 9.11.2.1B */ +#define FOREACH_IEI(IEI_DEF) \ + IEI_DEF(IEI_5GSM_CAUSE, 0x59) /* 5GSM cause 9.11.4.2 */ \ + IEI_DEF(IEI_PDU_ADDRESS, 0x29) /* PDU address 9.11.4.10 */ \ + IEI_DEF(IEI_RQ_TIMER_VALUE, 0x56) /* GPRS timer 9.11.2.3 */ \ + IEI_DEF(IEI_SNSSAI, 0x22) /* S-NSSAI 9.11.2.8 */ \ + IEI_DEF(IEI_ALWAYSON_PDU, 0x80) /* Always-on PDU session indication 9.11.4.3 */ \ + IEI_DEF(IEI_MAPPED_EPS, 0x75) /* Mapped EPS bearer contexts 9.11.4.8 */ \ + IEI_DEF(IEI_EAP_MSG, 0x78) /* EAP message 9.11.2.2 */ \ + IEI_DEF(IEI_AUTH_QOS_DESC, 0x79) /* QoS flow descriptions 9.11.4.12 */ \ + IEI_DEF(IEI_EXT_CONF_OPT, 0x7b) /* Extended protocol configuration options 9.11.4.6 */ \ + IEI_DEF(IEI_DNN, 0x25) /* DNN 9.11.2.1B */ + +static const text_info_t iei_text_desc[] = {FOREACH_IEI(TO_TEXT)}; + +typedef enum { FOREACH_IEI(TO_ENUM) } pduSessionEstablishment_IEI_t; /* PDU Session type value - TS 24.501 Table 9.11.4.10.1*/ -#define PDU_SESSION_TYPE_IPV4 0b001 -#define PDU_SESSION_TYPE_IPV6 0b010 +#define PDU_SESSION_TYPE_IPV4 0b001 +#define PDU_SESSION_TYPE_IPV6 0b010 #define PDU_SESSION_TYPE_IPV4V6 0b011 -#define IPv4_ADDRESS_LENGTH 4 // length of the IPv4 address associated with a PDU session +#define IPv4_ADDRESS_LENGTH 4 // length of the IPv4 address associated with a PDU session #define IPv6_INTERFACE_ID_LENGTH 8 // interface identifier for the IPv6 link local address #define SMF_IPv6_LLA_LENGTH 16 /* Rule operation codes - TS 24.501 Table 9.11.4.13.1 */ +// clang-format off #define ROC_RESERVED_0 0b000 /* Reserved */ #define ROC_CREATE_NEW_QOS_RULE 0b001 /* Create new QoS rule */ #define ROC_DELETE_QOS_RULE 0b010 /* Delete existing QoS rule */ @@ -56,13 +64,14 @@ #define ROC_MODIFY_QOS_RULE_DELETE_PF 0b101 /* Modify existing QoS rule and delete packet filters */ #define ROC_MODIFY_QOS_RULE_WITHOUT_PF 0b110 /* Modify existing QoS rule without modifying packet filters */ #define ROC_RESERVED_1 0b111 /* Reserved */ +// clang-format on -/* DNN - APN +/* DNN - APN * TS 23.003 9.1 * The APN is composed of two parts, the APN Network Identifier (9.1.1) & The APN Operator Identifier (9.1.2). - * + * * The DNN information element has a length in the range of 3 to 102 octets. - * The Header is consisted of two octets, the DNN IEI and the Length of the DNN contents fields, each is 1 octet. + * The Header is consisted of two octets, the DNN IEI and the Length of the DNN contents fields, each is 1 octet. * The DNN value payload starts from the 3rd octet. * The accumulated max length of APN payload is 100 octets. * The min length of the APN payload is 1 octet. @@ -70,16 +79,18 @@ #define APN_MAX_LEN 100 #define APN_MIN_LEN 1 +#define MAX_NUM_QOS_RULES 64 + /* Mandatory Presence IE - TS 24.501 Table 8.3.2.1.1 */ typedef struct packet_filter_create_qos_rule_s { uint8_t pf_dir; /* Packet filter direction */ - uint8_t pf_id; /* Packet filter identifier */ + uint8_t pf_id; /* Packet filter identifier */ uint8_t length; /* Length of packet filter contents */ } packet_filter_type1_t; /* TS 24.501 Figure 9.11.4.13.3 */ typedef struct packet_filter_modify_qos_rule_s { - uint8_t pf_id; /* Packet filter identifier */ + uint8_t pf_id; /* Packet filter identifier */ } packet_filter_type2_t; /* TS 24.501 Figure 9.11.4.13.4 */ typedef struct packet_filter_s { @@ -90,39 +101,51 @@ typedef struct packet_filter_s { } packet_filter_t; typedef struct qos_rule_s { - uint8_t id; /* QoS rule identifier */ - uint16_t length; /* Length of QoS Rule */ - uint8_t oc; /* Rule operation code (3bits) */ - uint8_t dqr; /* DQR bit (1 bit) */ - uint8_t nb_pf; /* Number of packet filters (4 bits) */ - uint8_t prcd; /* QoS rule precedence */ - uint8_t qfi; /* QoS Flow Identifier */ + // QoS rule identifier + uint8_t id; + // Length of QoS Rule + uint16_t length; + // Rule operation code + uint8_t oc; + // Default QoS Rule + bool dqr; + // Number of packet filters + uint8_t nb_pf; + // QoS rule precedence + uint8_t precendence; + // QoS Flow Identifier + uint8_t qfi; } qos_rule_t; typedef struct auth_qos_rules_s { - uint16_t length; /* Length of QoS rules IE */ -} auth_qos_rule_t; /* QoS Rule as defined in 24.501 Figure 9.11.4.13.2 */ + uint16_t length; /* Length of QoS rules IE */ + // QoS rules (M) + qos_rule_t rule[MAX_NUM_QOS_RULES]; +} auth_qos_rule_t; /* QoS Rule as defined in 24.501 Figure 9.11.4.13.2 */ typedef struct session_ambr_s { - uint8_t length; /* Length of Session-AMBR contents */ - uint8_t unit_dl; /* Unit for Session-AMBR for downlink */ + uint8_t length; /* Length of Session-AMBR contents */ + uint8_t unit_dl; /* Unit for Session-AMBR for downlink */ uint16_t sess_dl; /* Session-AMBR for downlink */ - uint8_t unit_ul; /* Unit for Session-AMBR for uplink */ + uint8_t unit_ul; /* Unit for Session-AMBR for uplink */ uint16_t sess_ul; /* Session-AMBR for uplink */ -} session_ambr_t; /* TS 24.501 Figure 9.11.4.14.1 */ +} session_ambr_t; /* TS 24.501 Figure 9.11.4.14.1 */ /* Optional Presence IE - TS 24.501 Table 8.3.2.1.1 */ typedef struct pdu_address_s { - uint8_t pdu_iei; /* PDU Address IEI (0x29) */ - uint8_t pdu_length; /* Length of PDU address contents */ - uint8_t pdu_type; /* PDU session type value */ - /// PDU address information (depending on type, up to 12 bytes) + // PDU address IEI (0x29) (octet 1) + uint8_t pdu_iei; + // Length of PDU address contents (octet 2) + uint8_t pdu_length; + // PDU session type value (9.11.4.11 of TS 24.501) + uint8_t pdu_type; + // PDU address IE (depending on type, up to 12 bytes) uint8_t pdu_addr_oct[IPv4_ADDRESS_LENGTH + IPv6_INTERFACE_ID_LENGTH]; } pdu_address_t; /* TS 24.501 9.11.4.10 */ typedef struct dnn_s { - uint8_t dnn_iei; /* DNN IEI (0x25) */ + uint8_t dnn_iei; /* DNN IEI (0x25) */ uint8_t dnn_length; /* Length of DNN contents */ } dnn_t; /* TS 24.501 9.11.2.1A */ @@ -135,38 +158,24 @@ typedef struct qos_fd_s { } qos_fd_t; /* TS 24.501 9.11.4.12 - Ommited, only length is processed*/ typedef struct pdu_session_establishment_accept_msg_s { - /* Mandatory presence */ - uint8_t epd; /* Extended Protocol Discriminator */ - uint8_t pdu_id; /* PDU Session ID */ - uint8_t pti; /* Procedure Transaction Identity */ - uint8_t msg_type; /* Message Type */ - uint8_t pdu_type; /* PDU Session Type */ - uint8_t ssc_mode; /* SSC mode */ - auth_qos_rule_t qos_rules; /* Authorized QoS rules */ - session_ambr_t sess_ambr; /* Session-AMBR */ - - /* Optional presence */ - dnn_t dnn_ie; /* Data Network Name */ - pdu_address_t pdu_addr_ie; /* PDU Address */ - ext_pP_t ext_pp_ie; /* Extended Protocol Configuration Options */ - qos_fd_t qos_fd_ie; /* QoS flow descriptions */ + // PDU Session Type (M) + uint8_t pdu_type; + // Selected SSC Mode (M) + uint8_t ssc_mode; + // Authorized QoS rules (M) + auth_qos_rule_t qos_rules; + // Session-AMBR (M) + session_ambr_t sess_ambr; + // Data Network Name (O) + dnn_t dnn_ie; + // PDU Address (O) + pdu_address_t pdu_addr_ie; + // Extended Protocol Configuration Options (O) + ext_pP_t ext_pp_ie; + // QoS flow descriptions (O) + qos_fd_t qos_fd_ie; } pdu_session_establishment_accept_msg_t; /* 24.501 Table 8.3.2.1.1 */ -typedef struct security_protected_plain_nas_5gs_msg_s { - uint8_t epd; /* Extended Protocol Discriminator */ - uint8_t sht; /* Security Header Type */ - uint8_t msg_type; /* Message Type */ - uint8_t payload_type; /* Payload Container Type */ - uint16_t payload_len; /* Payload Container Length */ -} security_protected_plain_nas_5gs_msg_t; - -typedef struct security_protected_nas_5gs_msg_s { - uint8_t epd; /* Extended Protocol Discriminator */ - uint8_t sht; /* Security Header Type */ - uint32_t mac; /* Message Authentication Code */ - uint8_t sqn; /* Sequence Number */ -} security_protected_nas_5gs_msg_t; /* 24.501 Figure 9.1.1.2 */ - -void capture_pdu_session_establishment_accept_msg(uint8_t *buffer, uint32_t msg_length); +int decode_pdu_session_establishment_accept_msg(pdu_session_establishment_accept_msg_t *psea_msg, uint8_t *buffer, uint32_t msg_length); #endif diff --git a/openair3/NAS/NR_UE/5GS/CMakeLists.txt b/openair3/NAS/NR_UE/5GS/CMakeLists.txt new file mode 100644 index 0000000000..e04abb02db --- /dev/null +++ b/openair3/NAS/NR_UE/5GS/CMakeLists.txt @@ -0,0 +1,17 @@ +add_subdirectory(5GMM/MSG) +add_subdirectory(5GMM/IES) +add_subdirectory(5GSM/MSG) + +if(ENABLE_TESTS) + add_subdirectory(tests) +endif() +add_library(fgs_lib fgs_nas_lib.c) + +target_link_libraries(fgs_lib PUBLIC + fgs_5gmm_lib + fgs_5gsm_lib + fgs_5gmm_ies_lib + nas_common_ies_lib +) + +target_include_directories(fgs_lib PUBLIC . 5GMM/MSG 5GMM/IES) diff --git a/openair3/NAS/NR_UE/5GS/NR_NAS_defs.h b/openair3/NAS/NR_UE/5GS/NR_NAS_defs.h new file mode 100644 index 0000000000..babda98aaa --- /dev/null +++ b/openair3/NAS/NR_UE/5GS/NR_NAS_defs.h @@ -0,0 +1,311 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef NR_NAS_DEFS_H +#define NR_NAS_DEFS_H + +#include +#include "openair3/UICC/usim_interface.h" +#include "fgs_nas_utils.h" +#include "FGSAuthenticationResponse.h" +#include "FGSDeregistrationRequestUEOriginating.h" +#include "FGSIdentityResponse.h" +#include "FGSMobileIdentity.h" +#include "FGSNASSecurityModeComplete.h" +#include "FGSUplinkNasTransport.h" +#include "RegistrationComplete.h" +#include "RegistrationRequest.h" +#include "fgs_service_request.h" + +/* Message types defintions for: + (a) 5GS Mobility Management (5GMM) (IDs 0x41 - 0x68) + Table 9.7.1 of 3GPP TS 24.501 + (b) 5GS Session Management (5GSM) (IDs 0xc1 - 0xd6) + Table 9.7.2 of 3GPP TS 24.501 */ +#define FOREACH_TYPE(TYPE_DEF) \ + TYPE_DEF(FGS_REGISTRATION_REQUEST, 0x41) \ + TYPE_DEF(FGS_REGISTRATION_ACCEPT, 0x42) \ + TYPE_DEF(FGS_REGISTRATION_COMPLETE, 0x43) \ + TYPE_DEF(FGS_REGISTRATION_REJECT, 0x44) \ + TYPE_DEF(FGS_DEREGISTRATION_REQUEST_UE_ORIGINATING, 0x45) \ + TYPE_DEF(FGS_DEREGISTRATION_ACCEPT_UE_ORIGINATING, 0x46) \ + TYPE_DEF(FGS_DEREGISTRATION_REQUEST_UE_TERMINATED, 0x47) \ + TYPE_DEF(FGS_DEREGISTRATION_ACCEPT_UE_TERMINATED, 0x48) \ + TYPE_DEF(FGS_SERVICE_REQUEST, 0x4c) \ + TYPE_DEF(FGS_SERVICE_REJECT, 0x4d) \ + TYPE_DEF(FGS_SERVICE_ACCEPT, 0x4e) \ + TYPE_DEF(FGS_CONTROL_PLANE_SERVICE_REQUEST, 0x4f) \ + TYPE_DEF(FGS_NSS_AUTHENTICATION_COMMAND, 0x50) \ + TYPE_DEF(FGS_NSS_AUTHENTICATION_COMPLETE, 0x51) \ + TYPE_DEF(FGS_NSS_AUTHENTICATION_RESULT, 0x52) \ + TYPE_DEF(FGS_CONFIGURATION_UPDATE_COMMAND, 0x54) \ + TYPE_DEF(FGS_CONFIGURATION_UPDATE_COMPLETE, 0x55) \ + TYPE_DEF(FGS_AUTHENTICATION_REQUEST, 0x56) \ + TYPE_DEF(FGS_AUTHENTICATION_RESPONSE, 0x57) \ + TYPE_DEF(FGS_AUTHENTICATION_REJECT, 0x58) \ + TYPE_DEF(FGS_AUTHENTICATION_FAILURE, 0x59) \ + TYPE_DEF(FGS_AUTHENTICATION_RESULT, 0x5a) \ + TYPE_DEF(FGS_IDENTITY_REQUEST, 0x5b) \ + TYPE_DEF(FGS_IDENTITY_RESPONSE, 0x5c) \ + TYPE_DEF(FGS_SECURITY_MODE_COMMAND, 0x5d) \ + TYPE_DEF(FGS_SECURITY_MODE_COMPLETE, 0x5e) \ + TYPE_DEF(FGS_SECURITY_MODE_REJECT, 0x5f) \ + TYPE_DEF(FGS_5GMM_STATUS, 0x64) \ + TYPE_DEF(FGS_NOTIFICATION, 0x65) \ + TYPE_DEF(FGS_NOTIFICATION_RESPONSE, 0x66) \ + TYPE_DEF(FGS_UPLINK_NAS_TRANSPORT, 0x67) \ + TYPE_DEF(FGS_DOWNLINK_NAS_TRANSPORT, 0x68) \ + TYPE_DEF(FGS_PDU_SESSION_ESTABLISHMENT_REQ, 0xc1) \ + TYPE_DEF(FGS_PDU_SESSION_ESTABLISHMENT_ACC, 0xc2) \ + TYPE_DEF(FGS_PDU_SESSION_ESTABLISHMENT_REJ, 0xc3) \ + TYPE_DEF(FGS_PDU_SESSION_AUTH_COMMAND, 0xc5) \ + TYPE_DEF(FGS_PDU_SESSION_AUTH_COMPLETE, 0xc6) \ + TYPE_DEF(FGS_PDU_SESSION_AUTH_RESULT, 0xc7) \ + TYPE_DEF(FGS_PDU_SESSION_MODIFICATION_REQ, 0xc9) \ + TYPE_DEF(FGS_PDU_SESSION_MODIFICATION_REJ, 0xca) \ + TYPE_DEF(FGS_PDU_SESSION_MODIFICATION_COMMAND, 0xcb) \ + TYPE_DEF(FGS_PDU_SESSION_MODIFICATION_COMPLETE, 0xcc) \ + TYPE_DEF(FGS_PDU_SESSION_MODIFICATION_COMMAND_REJ, 0xcd) \ + TYPE_DEF(FGS_PDU_SESSION_RELEASE_REQ, 0xd1) \ + TYPE_DEF(FGS_PDU_SESSION_RELEASE_REJ, 0xd2) \ + TYPE_DEF(FGS_PDU_SESSION_RELEASE_COMMAND, 0xd3) \ + TYPE_DEF(FGS_PDU_SESSION_RELEASE_COMPLETE, 0xd4) \ + TYPE_DEF(FGS_5GSM_STATUS, 0xd6) + +static const text_info_t message_text_info[] = { + FOREACH_TYPE(TO_TEXT) +}; + +//! Tasks id of each task +typedef enum { + FOREACH_TYPE(TO_ENUM) +} fgs_nas_msg_t; + +// TS 24.501 +#define FOREACH_HEADER(TYPE_DEF) \ + TYPE_DEF(PLAIN_5GS_MSG, 0) \ + TYPE_DEF(INTEGRITY_PROTECTED, 1) \ + TYPE_DEF(INTEGRITY_PROTECTED_AND_CIPHERED, 2) \ + TYPE_DEF(INTEGRITY_PROTECTED_WITH_NEW_SECU_CTX, 3) \ + TYPE_DEF(INTEGRITY_PROTECTED_AND_CIPHERED_WITH_NEW_SECU_CTX, 4) + +typedef enum { FOREACH_HEADER(TO_ENUM) } Security_header_t; + +static const text_info_t security_header_type_s[] = {FOREACH_HEADER(TO_TEXT)}; + +// table 9.11.3.2.1 +#define FOREACH_CAUSE(CAUSE_DEF) \ + CAUSE_DEF(Illegal_UE,0x3 )\ + CAUSE_DEF(PEI_not_accepted,0x5 )\ + CAUSE_DEF(Illegal_ME,0x6 )\ + CAUSE_DEF(SGS_services_not_allowed,0x7 )\ + CAUSE_DEF(UE_identity_cannot_be_derived_by_the_network,0x9 )\ + CAUSE_DEF(Implicitly_de_registered,0x0a )\ + CAUSE_DEF(PLMN_not_allowed,0x0b )\ + CAUSE_DEF(Tracking_area_not_allowed,0x0c )\ + CAUSE_DEF(Roaming_not_allowed_in_this_tracking_area,0x0d )\ + CAUSE_DEF(No_suitable_cells_in_tracking_area,0x0f )\ + CAUSE_DEF(MAC_failure,0x14 )\ + CAUSE_DEF(Synch_failure,0x15 )\ + CAUSE_DEF(Congestion,0x16 )\ + CAUSE_DEF(UE_security_capabilities_mismatch,0x17 )\ + CAUSE_DEF(Security_mode_rejected_unspecified,0x18 )\ + CAUSE_DEF(Non_5G_authentication_unacceptable,0x1a )\ + CAUSE_DEF(N1_mode_not_allowed,0x1b )\ + CAUSE_DEF(Restricted_service_area,0x1c )\ + CAUSE_DEF(Redirection_to_EPC_required,0x1f )\ + CAUSE_DEF(LADN_not_available,0x2b )\ + CAUSE_DEF(No_network_slices_available,0x3e )\ + CAUSE_DEF(Maximum_number_of_PDU_sessions_reached,0x41 )\ + CAUSE_DEF(Insufficient_resources_for_specific_slice_and_DNN,0x43 )\ + CAUSE_DEF(Insufficient_resources_for_specific_slice,0x45 )\ + CAUSE_DEF(ngKSI_already_in_use,0x47 )\ + CAUSE_DEF(Non_3GPP_access_to_5GCN_not_allowed,0x48 )\ + CAUSE_DEF(Serving_network_not_authorized,0x49 )\ + CAUSE_DEF(Temporarily_not_authorized_for_this_SNPN,0x4A )\ + CAUSE_DEF(Permanently_not_authorized_for_this_SNPN,0x4b )\ + CAUSE_DEF(Not_authorized_for_this_CAG_or_authorized_for_CAG_cells_only,0x4c )\ + CAUSE_DEF(Wireline_access_area_not_allowed,0x4d )\ + CAUSE_DEF(Payload_was_not_forwarded,0x5a )\ + CAUSE_DEF(DNN_not_supported_or_not_subscribed_in_the_slice,0x5b )\ + CAUSE_DEF(Insufficient_user_plane_resources_for_the_PDU_session,0x5c )\ + CAUSE_DEF(Semantically_incorrect_message,0x5f )\ + CAUSE_DEF(Invalid_mandatory_information,0x60 )\ + CAUSE_DEF(Message_type_non_existent_or_not_implemented,0x61 )\ + CAUSE_DEF(Message_type_not_compatible_with_the_protocol_state,0x62 )\ + CAUSE_DEF(Information_element_non_existent_or_not_implemented,0x63 )\ + CAUSE_DEF(Conditional_IE_error,0x64 )\ + CAUSE_DEF(Message_not_compatible_with_the_protocol_state,0x65 )\ + CAUSE_DEF(Protocol_error_unspecified,0x67 ) + +/* Map task id to printable name. */ +#define CAUSE_TEXT(LabEl, nUmID) {nUmID, #LabEl}, + +static const text_info_t cause_text_info[] = { + FOREACH_CAUSE(TO_TEXT) +}; + +#define CAUSE_ENUM(LabEl, nUmID ) LabEl = nUmID, +//! Tasks id of each task +typedef enum { + FOREACH_CAUSE(TO_ENUM) +} cause_id_t; + +//_table_9.11.4.2.1:_5GSM_cause_information_element +#define FOREACH_CAUSE_SECU(CAUSE_SECU_DEF) \ + CAUSE_SECU_DEF(Security_Operator_determined_barring,0x08 )\ + CAUSE_SECU_DEF(Security_Insufficient_resources,0x1a )\ + CAUSE_SECU_DEF(Security_Missing_or_unknown_DNN,0x1b )\ + CAUSE_SECU_DEF(Security_Unknown_PDU_session_type,0x1c )\ + CAUSE_SECU_DEF(Security_User_authentication_or_authorization_failed,0x1d )\ + CAUSE_SECU_DEF(Security_Request_rejected_unspecified,0x1f )\ + CAUSE_SECU_DEF(Security_Service_option_not_supported,0x20 )\ + CAUSE_SECU_DEF(Security_Requested_service_option_not_subscribed,0x21 )\ + CAUSE_SECU_DEF(Security_Service_option_temporarily_out_of_order,0x22 )\ + CAUSE_SECU_DEF(Security_PTI_already_in_use,0x23 )\ + CAUSE_SECU_DEF(Security_Regular_deactivation,0x24 )\ + CAUSE_SECU_DEF(Security_Network_failure,0x26 )\ + CAUSE_SECU_DEF(Security_Reactivation_requested,0x27 )\ + CAUSE_SECU_DEF(Security_Semantic_error_in_the_TFT_operation,0x29 )\ + CAUSE_SECU_DEF(Security_Syntactical_error_in_the_TFT_operation,0x2a )\ + CAUSE_SECU_DEF(Security_Invalid_PDU_session_identity,0x2b )\ + CAUSE_SECU_DEF(Security_Semantic_errors_in_packet_filter,0x2c )\ + CAUSE_SECU_DEF(Security_Syntactical_error_in_packet_filter,0x2d )\ + CAUSE_SECU_DEF(Security_Out_of_LADN_service_area,0x2e )\ + CAUSE_SECU_DEF(Security_PTI_mismatch,0x2f )\ + CAUSE_SECU_DEF(Security_PDU_session_type_IPv4_only_allowed,0x32 )\ + CAUSE_SECU_DEF(Security_PDU_session_type_IPv6_only_allowed,0x33 )\ + CAUSE_SECU_DEF(Security_PDU_session_does_not_exist,0x36 )\ + CAUSE_SECU_DEF(Security_PDU_session_type_IPv4v6_only_allowed,0x39 )\ + CAUSE_SECU_DEF(Security_PDU_session_type_Unstructured_only_allowed,0x3a )\ + CAUSE_SECU_DEF(Security_PDU_session_type_Ethernet_only_allowed,0x3d )\ + CAUSE_SECU_DEF(Security_Insufficient_resources_for_specific_slice_and_DNN,0x43 )\ + CAUSE_SECU_DEF(Security_Not_supported_SSC_mode,0x44 )\ + CAUSE_SECU_DEF(Security_Insufficient_resources_for_specific_slice,0x45 )\ + CAUSE_SECU_DEF(Security_Missing_or_unknown_DNN_in_a_slice,0x46 )\ + CAUSE_SECU_DEF(Security_Invalid_PTI_value,0x51 )\ + CAUSE_SECU_DEF(Security_Maximum_data_rate_per_UE_for_user_plane_integrity_protection_is_too_low,0x52 )\ + CAUSE_SECU_DEF(Security_Semantic_error_in_the_QoS_operation,0x53 )\ + CAUSE_SECU_DEF(Security_Syntactical_error_in_the_QoS_operation,0x54 )\ + CAUSE_SECU_DEF(Security_Invalid_mapped_EPS_bearer_identity,0x55 )\ + CAUSE_SECU_DEF(Security_Semantically_incorrect_message,0x5f )\ + CAUSE_SECU_DEF(Security_Invalid_mandatory_information,0x60 )\ + CAUSE_SECU_DEF(Security_Message_type_non_existent_or_not_implemented,0x61 )\ + CAUSE_SECU_DEF(Security_Message_type_not_compatible_with_the_protocol_state,0x62 )\ + CAUSE_SECU_DEF(Security_Information_element_non_existent_or_not_implemented,0x63 )\ + CAUSE_SECU_DEF(Security_Conditional_IE_error,0x64 )\ + CAUSE_SECU_DEF(Security_Message_not_compatible_with_the_protocol_state,0x65 )\ + CAUSE_SECU_DEF(Security_Protocol_error_unspecified,0x6f ) + +static const text_info_t cause_secu_text_info[] = { + FOREACH_CAUSE_SECU(TO_TEXT) +}; + +//! Tasks id of each task +typedef enum { + FOREACH_CAUSE_SECU(TO_ENUM) +} cause_secu_id_t; + +/** + * Security protected 5GS NAS message header (9.1.1 of 3GPP TS 24.501) + * either 5GMM or 5GSM + * Standard L3 message header (11.2.3.1 of 3GPP TS 24.007) + */ +typedef struct { + // Extended Protocol Discriminator + uint8_t protocol_discriminator; + // Security Header Type + uint8_t security_header_type; + // Message Authentication Code + uint32_t message_authentication_code; + // Sequence Number + uint8_t sequence_number; +} __attribute__((packed)) fgs_nas_message_security_header_t; + +/// 5GS Protocol Discriminator identifiers + +typedef enum fgs_protocol_discriminator_e { + // 5GS Mobility Management + FGS_MOBILITY_MANAGEMENT_MESSAGE = 0x7E, + // 5GS Session Management + FGS_SESSION_MANAGEMENT_MESSAGE = 0x2E, +} fgs_protocol_discriminator_t; + +/// 5GMM - 5GS mobility management + +/** + * Header of a plain 5GMM NAS message (5GS) + * Standard L3 message header (11.2.3.1 of 3GPP TS 24.007) + */ +typedef struct { + uint8_t ex_protocol_discriminator; + uint8_t security_header_type; + uint8_t message_type; +} fgmm_msg_header_t; + +/* Plain 5GMM NAS message (5GS) */ +typedef struct { + fgmm_msg_header_t header; + union { + registration_request_msg registration_request; + fgs_service_request_msg_t service_request; + fgmm_identity_response_msg fgs_identity_response; + fgs_authentication_response_msg fgs_auth_response; + fgs_deregistration_request_ue_originating_msg fgs_deregistration_request_ue_originating; + fgs_security_mode_complete_msg fgs_security_mode_complete; + registration_complete_msg registration_complete; + fgs_uplink_nas_transport_msg uplink_nas_transport; + } mm_msg; /* 5GS Mobility Management messages */ +} fgmm_nas_message_plain_t; + +/* Security protected 5GMM NAS message (5GS) */ +typedef struct { + fgs_nas_message_security_header_t header; + fgmm_nas_message_plain_t plain; +} fgmm_nas_msg_security_protected_t; + +/// 5GSM - 5GS session management + +/** + * Header of a plain 5GSM NAS message (5GS) + * Standard L3 message header (11.2.3.1 of 3GPP TS 24.007) + */ +typedef struct { + // Extended protocol discriminator + uint8_t ex_protocol_discriminator; + // PDU session identity + uint8_t pdu_session_id; + // Procedure transaction identity + uint8_t pti; + // Message type + uint8_t message_type; +} fgsm_msg_header_t; + +/// Function prototypes + +int mm_msg_encode(const fgmm_nas_message_plain_t *mm_msg, uint8_t *buffer, uint32_t len); +int nas_protected_security_header_encode(uint8_t *buffer, const fgs_nas_message_security_header_t *header, int length); +int _nas_mm_msg_encode_header(const fgmm_msg_header_t *header, uint8_t *buffer, uint32_t len); +uint8_t decode_5gmm_msg_header(fgmm_msg_header_t *mm_header, const uint8_t *buffer, uint32_t len); +uint8_t decode_5gsm_msg_header(fgsm_msg_header_t *sm_header, const uint8_t *buffer, uint32_t len); +int decode_5gs_security_protected_header(fgs_nas_message_security_header_t *header, const uint8_t *buf, uint32_t len); + +#endif // NR_NAS_DEFS_H diff --git a/openair3/NAS/NR_UE/5GS/fgs_nas_lib.c b/openair3/NAS/NR_UE/5GS/fgs_nas_lib.c new file mode 100644 index 0000000000..16d84f3ad8 --- /dev/null +++ b/openair3/NAS/NR_UE/5GS/fgs_nas_lib.c @@ -0,0 +1,179 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "NR_NAS_defs.h" +#include "nas_log.h" +#include "TLVEncoder.h" +#include "fgs_nas_utils.h" + +int _nas_mm_msg_encode_header(const fgmm_msg_header_t *header, uint8_t *buffer, uint32_t len) +{ + int size = 0; + + /* Check the buffer length */ + if (len < sizeof(fgmm_msg_header_t)) { + return (TLV_ENCODE_BUFFER_TOO_SHORT); + } + + /* Check the protocol discriminator */ + if (header->ex_protocol_discriminator != FGS_MOBILITY_MANAGEMENT_MESSAGE) { + LOG_TRACE(ERROR, "Unexpected extened protocol discriminator: 0x%x", header->ex_protocol_discriminator); + return (TLV_ENCODE_PROTOCOL_NOT_SUPPORTED); + } + + /* Encode the extendedprotocol discriminator */ + ENCODE_U8(buffer + size, header->ex_protocol_discriminator, size); + /* Encode the security header type */ + ENCODE_U8(buffer + size, (header->security_header_type & 0xf), size); + /* Encode the message type */ + ENCODE_U8(buffer + size, header->message_type, size); + return (size); +} + +int mm_msg_encode(const fgmm_nas_message_plain_t *p, uint8_t *buffer, uint32_t len) +{ + uint8_t msg_type = p->header.message_type; + int enc_msg = 0; + /* First encode the 5GMM message header */ + int enc_header = _nas_mm_msg_encode_header(&p->header, buffer, len); + + if (enc_header < 0) { + PRINT_NAS_ERROR("Failed to encode 5GMM message header\n"); + return enc_header; + } + + buffer += enc_header; + len -= enc_header; + + switch (msg_type) { + case FGS_REGISTRATION_REQUEST: + enc_msg = encode_registration_request(&p->mm_msg.registration_request, buffer, len); + break; + case FGS_IDENTITY_RESPONSE: + enc_msg = encode_fgmm_identity_response(buffer, &p->mm_msg.fgs_identity_response, len); + break; + case FGS_AUTHENTICATION_RESPONSE: + enc_msg = encode_fgs_authentication_response(&p->mm_msg.fgs_auth_response, buffer, len); + break; + case FGS_SECURITY_MODE_COMPLETE: + enc_msg = encode_fgs_security_mode_complete(&p->mm_msg.fgs_security_mode_complete, buffer, len); + break; + case FGS_UPLINK_NAS_TRANSPORT: + enc_msg = encode_fgs_uplink_nas_transport(&p->mm_msg.uplink_nas_transport, buffer, len); + break; + case FGS_DEREGISTRATION_REQUEST_UE_ORIGINATING: + enc_msg = + encode_fgs_deregistration_request_ue_originating(&p->mm_msg.fgs_deregistration_request_ue_originating, buffer, len); + break; + case FGS_SERVICE_REQUEST: + enc_msg = encode_fgs_service_request(buffer, &p->mm_msg.service_request, len); + break; + default: + LOG_TRACE(ERROR, " Unexpected message type: 0x%x", p->header.message_type); + enc_msg = TLV_ENCODE_WRONG_MESSAGE_TYPE; + break; + /* TODO: Handle not standard layer 3 messages: SERVICE_REQUEST */ + } + + if (enc_msg < 0) { + PRINT_NAS_ERROR("Failed to encode 5GMM message\n"); + return enc_msg; + } + + return enc_header + enc_msg; +} + +int nas_protected_security_header_encode(uint8_t *buffer, const fgs_nas_message_security_header_t *header, int length) +{ + int size = 0; + + if (length < sizeof(fgs_nas_message_security_header_t)) { + PRINT_NAS_ERROR("Could not encode the NAS security header\n"); + return -1; + } + + /* Encode the protocol discriminator) */ + ENCODE_U8(buffer, header->protocol_discriminator, size); + + /* Encode the security header type */ + ENCODE_U8(buffer + size, (header->security_header_type & 0xf), size); + + /* Encode the message authentication code */ + ENCODE_U32(buffer + size, header->message_authentication_code, size); + /* Encode the sequence number */ + ENCODE_U8(buffer + size, header->sequence_number, size); + + return size; +} + +/** + * @brief Decode plain 5GMM header from buffer and return fgmm_msg_header_t instance + */ +uint8_t decode_5gmm_msg_header(fgmm_msg_header_t *mm_header, const uint8_t *buffer, uint32_t len) +{ + if (len < sizeof(fgmm_msg_header_t)) { + PRINT_NAS_ERROR("Failed to decode plain 5GMM header: buffer length too short\n"); + return -1; + } + mm_header->ex_protocol_discriminator = *buffer++; + mm_header->security_header_type = *buffer++; + mm_header->message_type = *buffer++; + return sizeof(*mm_header); +} + +/** + * @brief Decode plain 5GSM header from buffer and return fgsm_msg_header_t instance + */ +uint8_t decode_5gsm_msg_header(fgsm_msg_header_t *sm_header, const uint8_t *buffer, uint32_t len) +{ + if (len < sizeof(fgsm_msg_header_t)) { + PRINT_NAS_ERROR("Failed to decode plain 5GSM header: buffer length too short\n"); + return -1; + } + sm_header->ex_protocol_discriminator = *buffer++; + sm_header->pdu_session_id = *buffer++; + sm_header->pti = *buffer++; + sm_header->message_type = *buffer++; + return sizeof(*sm_header); +} + +/** + * @brief Decode security protected 5GS header from buffer and return fgs_nas_message_security_header_t instance + */ +int decode_5gs_security_protected_header(fgs_nas_message_security_header_t *header, const uint8_t *buf, uint32_t len) +{ + int decoded = 0; + if (len < sizeof(fgs_nas_message_security_header_t)) { + PRINT_NAS_ERROR("Failed to decode security protected 5GS header: buffer length too short\n"); + return -1; + } + header->protocol_discriminator = *buf++; + decoded++; + header->security_header_type = *buf++; + decoded++; + uint32_t tmp; + memcpy(&tmp, buf, sizeof(tmp)); + decoded += sizeof(tmp); + header->message_authentication_code = htonl(tmp); + header->sequence_number = *buf++; + decoded++; + return decoded; +} diff --git a/openair3/NAS/NR_UE/5GS/fgs_nas_utils.h b/openair3/NAS/NR_UE/5GS/fgs_nas_utils.h new file mode 100644 index 0000000000..09754e9903 --- /dev/null +++ b/openair3/NAS/NR_UE/5GS/fgs_nas_utils.h @@ -0,0 +1,62 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef FGS_NAS_UTILS_H +#define FGS_NAS_UTILS_H + +#include +#include +#include // For memcpy + +#define PRINT_NAS_ERROR(...) fprintf(stderr, ##__VA_ARGS__) + +#define _NAS_EQ_CHECK_GENERIC(condition, fmt, ...) \ + do { \ + if (!(condition)) { \ + PRINT_NAS_ERROR("NAS Equality Check failure: %s:%d: Condition '%s' failed: " fmt " != " fmt "\n", \ + __FILE__, \ + __LINE__, \ + #condition, \ + ##__VA_ARGS__); \ + return false; \ + } \ + } while (0) + +#define _NAS_EQ_CHECK_LONG(A, B) _NAS_EQ_CHECK_GENERIC(A == B, "%ld", A, B); +#define _NAS_EQ_CHECK_INT(A, B) _NAS_EQ_CHECK_GENERIC(A == B, "%d", A, B); +#define _NAS_EQ_CHECK_STR(A, B) _NAS_EQ_CHECK_GENERIC(strcmp(A, B) == 0, "'%s'", A, B); + +/* Map task id to printable name. */ +typedef struct { + int id; + char text[256]; +} text_info_t; + +#define TO_TEXT(LabEl, nUmID) {nUmID, #LabEl}, +#define TO_ENUM(LabEl, nUmID ) LabEl = nUmID, + +#define GET_SHORT(input, size) ({ \ + uint16_t tmp16; \ + memcpy(&tmp16, (input), sizeof(tmp16)); \ + size += htons(tmp16); \ +}) + +#endif // FGS_NAS_UTILS_H diff --git a/openair3/NAS/COMMON/EMM/tests/CMakeLists.txt b/openair3/NAS/NR_UE/5GS/tests/CMakeLists.txt similarity index 74% rename from openair3/NAS/COMMON/EMM/tests/CMakeLists.txt rename to openair3/NAS/NR_UE/5GS/tests/CMakeLists.txt index 3f960c5562..a72a47700f 100644 --- a/openair3/NAS/COMMON/EMM/tests/CMakeLists.txt +++ b/openair3/NAS/NR_UE/5GS/tests/CMakeLists.txt @@ -5,9 +5,10 @@ add_executable(nas_lib_test nas_lib_test.c) add_dependencies(tests nas_lib_test) add_test(NAME nas_lib_test COMMAND nas_lib_test) -target_link_libraries(nas_lib_test PRIVATE fgs_lib fgs_ies_lib) +target_link_libraries(nas_lib_test PRIVATE + nr_nas +) target_include_directories(nas_lib_test PRIVATE - ${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ) diff --git a/openair3/NAS/COMMON/EMM/tests/nas_lib_test.c b/openair3/NAS/NR_UE/5GS/tests/nas_lib_test.c similarity index 100% rename from openair3/NAS/COMMON/EMM/tests/nas_lib_test.c rename to openair3/NAS/NR_UE/5GS/tests/nas_lib_test.c diff --git a/openair3/NAS/NR_UE/CMakeLists.txt b/openair3/NAS/NR_UE/CMakeLists.txt new file mode 100644 index 0000000000..5e7d5da428 --- /dev/null +++ b/openair3/NAS/NR_UE/CMakeLists.txt @@ -0,0 +1,15 @@ +add_subdirectory(5GS) + +add_library(nr_nas STATIC nr_nas_msg.c) + +target_link_libraries(nr_nas PUBLIC asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) +target_link_libraries(nr_nas PUBLIC + fgs_lib + fgs_5gmm_lib + fgs_5gsm_lib + fgs_5gmm_ies_lib + nas_common_ies_lib + nas_utils +) + +target_include_directories(nr_nas PUBLIC . 5GS/) diff --git a/openair3/NAS/NR_UE/nr_nas_msg.c b/openair3/NAS/NR_UE/nr_nas_msg.c index 5e9ce65194..d7a1c42bf3 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.c +++ b/openair3/NAS/NR_UE/nr_nas_msg.c @@ -20,7 +20,7 @@ */ /*! \file nr_nas_msg.c - * \brief simulator for nr nas message + * \brief Definitions of handlers and callbacks for NR NAS UE task * \author Yoshio INOUE, Masayuki HARADA * \email yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com * \date 2020 @@ -29,58 +29,116 @@ * 2023.01.27 Vladimir Dorovskikh 16 digits IMEISV */ -#include // memset -#include // malloc, free - -#include "nas_log.h" -#include "TLVDecoder.h" -#include "TLVEncoder.h" #include "nr_nas_msg.h" -#include "aka_functions.h" -#include "secu_defs.h" -#include "kdf.h" -#include "key_nas_deriver.h" +#include +#include "NR_NAS_defs.h" +#include +#include +#include +#include +#include "AuthenticationResponseParameter.h" +#include "FGCNasMessageContainer.h" +#include "FGSDeregistrationRequestUEOriginating.h" +#include "FGSDeregistrationType.h" +#include "NasKeySetIdentifier.h" +#include "NrUESecurityCapability.h" +#include "OctetString.h" #include "PduSessionEstablishRequest.h" #include "PduSessionEstablishmentAccept.h" #include "RegistrationAccept.h" -#include "FGSDeregistrationRequestUEOriginating.h" -#include "intertask_interface.h" +#include "SORTransparentContainer.h" +#include "FGSIdentityResponse.h" +#include "T.h" +#include "aka_functions.h" +#include "assertions.h" +#include "common/utils/ds/byte_array.h" #include "common/utils/tun_if.h" -#include -#include "openair2/SDAP/nr_sdap/nr_sdap.h" -#include "openair3/SECU/nas_stream_eia2.h" +#include "commonDef.h" +#include "intertask_interface.h" +#include "kdf.h" +#include "key_nas_deriver.h" +#include "nas_log.h" +#include "openair3/UICC/usim_interface.h" #include "openair3/UTILS/conversions.h" +#include "secu_defs.h" +#include "utils.h" +#include "openair2/SDAP/nr_sdap/nr_sdap.h" +#include "fgs_nas_utils.h" #define MAX_NAS_UE 4 -extern uint16_t NB_UE_INST; static nr_ue_nas_t nr_ue_nas[MAX_NAS_UE] = {0}; -static nr_nas_msg_snssai_t nas_allowed_nssai[8]; -typedef enum { - NAS_SECURITY_NO_SECURITY_CONTEXT, - NAS_SECURITY_UNPROTECTED, - NAS_SECURITY_INTEGRITY_FAILED, - NAS_SECURITY_INTEGRITY_PASSED, - NAS_SECURITY_BAD_INPUT -} security_state_t; +#define FOREACH_STATE(TYPE_DEF) \ + TYPE_DEF(NAS_SECURITY_NO_SECURITY_CONTEXT, 0) \ + TYPE_DEF(NAS_SECURITY_NEW_SECURITY_CONTEXT, 1) \ + TYPE_DEF(NAS_SECURITY_UNPROTECTED, 2) \ + TYPE_DEF(NAS_SECURITY_INTEGRITY_FAILED, 3) \ + TYPE_DEF(NAS_SECURITY_INTEGRITY_PASSED, 4) \ + TYPE_DEF(NAS_SECURITY_BAD_INPUT, 5) -security_state_t nas_security_rx_process(nr_ue_nas_t *nas, uint8_t *pdu_buffer, int pdu_length) +typedef enum { FOREACH_STATE(TO_ENUM) } security_state_t; + +static const text_info_t security_state_info[] = {FOREACH_STATE(TO_TEXT)}; + +static fgmm_msg_header_t set_mm_header(fgs_nas_msg_t type, Security_header_t security) +{ + fgmm_msg_header_t mm_header = {0}; + mm_header.ex_protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; + mm_header.security_header_type = security; + mm_header.message_type = type; + return mm_header; +} + +static void servingNetworkName(uint8_t *msg, char *imsiStr, int mnc_size) +{ + // SNN-network-identifier in TS 24.501 + // TS 24.501: If the MNC of the serving PLMN has two digits, then a zero is added at the beginning. + + // MNC + char mnc[4]; + if (mnc_size == 2) { + snprintf(mnc, sizeof(mnc), "0%c%c", imsiStr[3], imsiStr[4]); + } else { + snprintf(mnc, sizeof(mnc), "%c%c%c", imsiStr[3], imsiStr[4], imsiStr[5]); + } + + // MCC + char mcc[4]; + snprintf(mcc, sizeof(mcc), "%c%c%c", imsiStr[0], imsiStr[1], imsiStr[2]); + + int size = 64; + + snprintf((char *)msg, size, "5G:mnc%3s.mcc%3s.3gppnetwork.org", mnc, mcc); +} + +static security_state_t nas_security_rx_process(nr_ue_nas_t *nas, uint8_t *pdu_buffer, int pdu_length) { if (nas->security_container == NULL) return NAS_SECURITY_NO_SECURITY_CONTEXT; - if (pdu_buffer[1] == 0) - return NAS_SECURITY_UNPROTECTED; /* header is 7 bytes, require at least one byte of payload */ if (pdu_length < 8) return NAS_SECURITY_BAD_INPUT; - /* only accept "integrity protected and ciphered" messages */ - if (pdu_buffer[1] != 2) { - LOG_E(NAS, "todo: unhandled security type %d\n", pdu_buffer[2]); - return NAS_SECURITY_BAD_INPUT; + + switch (pdu_buffer[1]) { + case PLAIN_5GS_MSG: + return NAS_SECURITY_UNPROTECTED; + break; + case INTEGRITY_PROTECTED: + case INTEGRITY_PROTECTED_WITH_NEW_SECU_CTX: + case INTEGRITY_PROTECTED_AND_CIPHERED_WITH_NEW_SECU_CTX: + /* only accept "integrity protected and ciphered" messages */ + if (pdu_buffer[6] == 0) + LOG_E(NAS, "Received nas_count_dl = %d\n", pdu_buffer[6]); + LOG_E(NAS, "todo: unhandled security type %s (pdu_buffer[1] = %d)\n", security_header_type_s[pdu_buffer[1]].text, pdu_buffer[1]); + return NAS_SECURITY_BAD_INPUT; + break; + default: + break; } /* synchronize NAS SQN, based on 24.501 4.4.3.1 */ + // Sequence number int nas_sqn = pdu_buffer[6]; int target_sqn = nas->security.nas_count_dl & 0xff; if (nas_sqn != target_sqn) { @@ -97,83 +155,40 @@ security_state_t nas_security_rx_process(nr_ue_nas_t *nas, uint8_t *pdu_buffer, } /* check integrity */ - uint8_t computed_mac[4]; + uint8_t computed_mac[NAS_INTEGRITY_SIZE]; nas_stream_cipher_t stream_cipher; stream_cipher.context = nas->security_container->integrity_context; stream_cipher.count = nas->security.nas_count_dl; stream_cipher.bearer = 1; /* todo: don't hardcode */ stream_cipher.direction = 1; - stream_cipher.message = pdu_buffer + 6; + stream_cipher.message = pdu_buffer + SECURITY_PROTECTED_5GS_NAS_MESSAGE_HEADER_LENGTH - 1; /* length in bits */ - stream_cipher.blength = (pdu_length - 6) << 3; + stream_cipher.blength = (pdu_length - SECURITY_PROTECTED_5GS_NAS_MESSAGE_HEADER_LENGTH + 1) << 3; stream_compute_integrity(nas->security_container->integrity_algorithm, &stream_cipher, computed_mac); uint8_t *received_mac = pdu_buffer + 2; - if (memcmp(received_mac, computed_mac, 4) != 0) + if (memcmp(received_mac, computed_mac, NAS_INTEGRITY_SIZE) != 0) return NAS_SECURITY_INTEGRITY_FAILED; /* decipher */ - uint8_t buf[pdu_length - 7]; + uint8_t payload_len = pdu_length - SECURITY_PROTECTED_5GS_NAS_MESSAGE_HEADER_LENGTH; + uint8_t buf[payload_len]; stream_cipher.context = nas->security_container->ciphering_context; stream_cipher.count = nas->security.nas_count_dl; stream_cipher.bearer = 1; /* todo: don't hardcode */ stream_cipher.direction = 1; - stream_cipher.message = pdu_buffer + 7; + stream_cipher.message = pdu_buffer + SECURITY_PROTECTED_5GS_NAS_MESSAGE_HEADER_LENGTH; /* length in bits */ - stream_cipher.blength = (pdu_length - 7) << 3; + stream_cipher.blength = (payload_len) << 3; stream_compute_encrypt(nas->security_container->ciphering_algorithm, &stream_cipher, buf); - memcpy(pdu_buffer + 7, buf, pdu_length - 7); + memcpy(pdu_buffer + SECURITY_PROTECTED_5GS_NAS_MESSAGE_HEADER_LENGTH, buf, payload_len); nas->security.nas_count_dl++; return NAS_SECURITY_INTEGRITY_PASSED; } -static int nas_protected_security_header_encode(char *buffer, const fgs_nas_message_security_header_t *header, int length) -{ - LOG_FUNC_IN; - - int size = 0; - - /* Encode the protocol discriminator) */ - ENCODE_U8(buffer, header->protocol_discriminator, size); - - /* Encode the security header type */ - ENCODE_U8(buffer + size, (header->security_header_type & 0xf), size); - - /* Encode the message authentication code */ - ENCODE_U32(buffer + size, header->message_authentication_code, size); - /* Encode the sequence number */ - ENCODE_U8(buffer + size, header->sequence_number, size); - - LOG_FUNC_RETURN(size); -} - -static int _nas_mm_msg_encode_header(const mm_msg_header_t *header, uint8_t *buffer, uint32_t len) -{ - int size = 0; - - /* Check the buffer length */ - if (len < sizeof(mm_msg_header_t)) { - return (TLV_ENCODE_BUFFER_TOO_SHORT); - } - - /* Check the protocol discriminator */ - if (header->ex_protocol_discriminator != FGS_MOBILITY_MANAGEMENT_MESSAGE) { - LOG_TRACE(ERROR, "ESM-MSG - Unexpected extened protocol discriminator: 0x%x", header->ex_protocol_discriminator); - return (TLV_ENCODE_PROTOCOL_NOT_SUPPORTED); - } - - /* Encode the extendedprotocol discriminator */ - ENCODE_U8(buffer + size, header->ex_protocol_discriminator, size); - /* Encode the security header type */ - ENCODE_U8(buffer + size, (header->security_header_type & 0xf), size); - /* Encode the message type */ - ENCODE_U8(buffer + size, header->message_type, size); - return (size); -} - static int fill_suci(FGSMobileIdentity *mi, const uicc_t *uicc) { mi->suci.typeofidentity = FGS_MOBILE_IDENTITY_SUCI; @@ -231,71 +246,6 @@ static int fill_imeisv(FGSMobileIdentity *mi, const uicc_t *uicc) return 19; } -int mm_msg_encode(MM_msg *mm_msg, uint8_t *buffer, uint32_t len) -{ - LOG_FUNC_IN; - int header_result; - int encode_result; - uint8_t msg_type = mm_msg->header.message_type; - - /* First encode the EMM message header */ - header_result = _nas_mm_msg_encode_header(&mm_msg->header, buffer, len); - - if (header_result < 0) { - LOG_TRACE(ERROR, - "EMM-MSG - Failed to encode EMM message header " - "(%d)", - header_result); - LOG_FUNC_RETURN(header_result); - } - - buffer += header_result; - len -= header_result; - - switch (msg_type) { - case REGISTRATION_REQUEST: - encode_result = encode_registration_request(&mm_msg->registration_request, buffer, len); - break; - case FGS_IDENTITY_RESPONSE: - encode_result = encode_identiy_response(&mm_msg->fgs_identity_response, buffer, len); - break; - case FGS_AUTHENTICATION_RESPONSE: - encode_result = encode_fgs_authentication_response(&mm_msg->fgs_auth_response, buffer, len); - break; - case FGS_SECURITY_MODE_COMPLETE: - encode_result = encode_fgs_security_mode_complete(&mm_msg->fgs_security_mode_complete, buffer, len); - break; - case FGS_UPLINK_NAS_TRANSPORT: - encode_result = encode_fgs_uplink_nas_transport(&mm_msg->uplink_nas_transport, buffer, len); - break; - case FGS_DEREGISTRATION_REQUEST_UE_ORIGINATING: - encode_result = - encode_fgs_deregistration_request_ue_originating(&mm_msg->fgs_deregistration_request_ue_originating, buffer, len); - break; - case FGS_SERVICE_REQUEST: - encode_result = encode_fgs_service_request(buffer, &mm_msg->service_request, len); - break; - default: - LOG_TRACE(ERROR, "EMM-MSG - Unexpected message type: 0x%x", mm_msg->header.message_type); - encode_result = TLV_ENCODE_WRONG_MESSAGE_TYPE; - break; - /* TODO: Handle not standard layer 3 messages: SERVICE_REQUEST */ - } - - if (encode_result < 0) { - LOG_TRACE(ERROR, - "EMM-MSG - Failed to encode L3 EMM message 0x%x " - "(%d)", - mm_msg->header.message_type, - encode_result); - } - - if (encode_result < 0) - LOG_FUNC_RETURN(encode_result); - - LOG_FUNC_RETURN(header_result + encode_result); -} - void transferRES(uint8_t ck[16], uint8_t ik[16], uint8_t *input, uint8_t rand[16], uint8_t *output, uicc_t *uicc) { uint8_t S[100] = {0}; @@ -410,7 +360,7 @@ void derive_knas(algorithm_type_dist_t nas_alg_type, uint8_t nas_alg_id, uint8_t memcpy(knas, out + 16, 16); } -void derive_kgnb(uint8_t kamf[32], uint32_t count, uint8_t *kgnb) +static void derive_kgnb(uint8_t kamf[32], uint32_t count, uint8_t *kgnb) { /* Compute the KDF input parameter * S = FC(0x6E) || UL NAS Count || 0x00 0x04 || 0x01 || 0x00 0x01 @@ -445,7 +395,7 @@ void derive_kgnb(uint8_t kamf[32], uint32_t count, uint8_t *kgnb) printf("\n"); } -void derive_ue_keys(uint8_t *buf, nr_ue_nas_t *nas) +static void derive_ue_keys(uint8_t *buf, nr_ue_nas_t *nas) { uint8_t ak[6]; uint8_t sqn[6]; @@ -510,30 +460,22 @@ nr_ue_nas_t *get_ue_nas_info(module_id_t module_id) void generateRegistrationRequest(as_nas_info_t *initialNasMsg, nr_ue_nas_t *nas) { - int size = sizeof(mm_msg_header_t); - fgs_nas_message_t nas_msg = {0}; - MM_msg *mm_msg; + int size = sizeof(fgmm_msg_header_t); + fgmm_nas_message_plain_t plain = {0}; - mm_msg = &nas_msg.plain.mm_msg; - // set header - mm_msg->header.ex_protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; - mm_msg->header.security_header_type = PLAIN_5GS_MSG; - mm_msg->header.message_type = REGISTRATION_REQUEST; + // Plain 5GMM header + plain.header = set_mm_header(FGS_REGISTRATION_REQUEST, PLAIN_5GS_MSG); + size += sizeof(plain.header); - // set registration request - mm_msg->registration_request.protocoldiscriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; - size += 1; - mm_msg->registration_request.securityheadertype = PLAIN_5GS_MSG; - size += 1; - mm_msg->registration_request.messagetype = REGISTRATION_REQUEST; - size += 1; - mm_msg->registration_request.fgsregistrationtype = INITIAL_REGISTRATION; - mm_msg->registration_request.naskeysetidentifier.naskeysetidentifier = 1; + // Plain 5GMM msg + registration_request_msg *mm_msg = &plain.mm_msg.registration_request; + mm_msg->fgsregistrationtype = INITIAL_REGISTRATION; + mm_msg->naskeysetidentifier.naskeysetidentifier = 1; size += 1; if (nas->guti) { - size += fill_guti(&mm_msg->registration_request.fgsmobileidentity, nas->guti); + size += fill_guti(&mm_msg->fgsmobileidentity, nas->guti); } else { - size += fill_suci(&mm_msg->registration_request.fgsmobileidentity, nas->uicc); + size += fill_suci(&mm_msg->fgsmobileidentity, nas->uicc); } #if 0 @@ -548,20 +490,20 @@ void generateRegistrationRequest(as_nas_info_t *initialNasMsg, nr_ue_nas_t *nas) size += 3; #endif - mm_msg->registration_request.presencemask |= REGISTRATION_REQUEST_UE_SECURITY_CAPABILITY_PRESENT; - mm_msg->registration_request.nruesecuritycapability.iei = REGISTRATION_REQUEST_UE_SECURITY_CAPABILITY_IEI; - mm_msg->registration_request.nruesecuritycapability.length = 8; - mm_msg->registration_request.nruesecuritycapability.fg_EA = 0xe0; - mm_msg->registration_request.nruesecuritycapability.fg_IA = 0x60; - mm_msg->registration_request.nruesecuritycapability.EEA = 0; - mm_msg->registration_request.nruesecuritycapability.EIA = 0; + mm_msg->presencemask |= REGISTRATION_REQUEST_UE_SECURITY_CAPABILITY_PRESENT; + mm_msg->nruesecuritycapability.iei = REGISTRATION_REQUEST_UE_SECURITY_CAPABILITY_IEI; + mm_msg->nruesecuritycapability.length = 8; + mm_msg->nruesecuritycapability.fg_EA = 0xe0; + mm_msg->nruesecuritycapability.fg_IA = 0x60; + mm_msg->nruesecuritycapability.EEA = 0; + mm_msg->nruesecuritycapability.EIA = 0; size += 10; // encode the message - initialNasMsg->nas_data = malloc16_clear(size * sizeof(Byte_t)); + initialNasMsg->nas_data = malloc16_clear(size * sizeof(*initialNasMsg->nas_data)); nas->registration_request_buf = initialNasMsg->nas_data; - initialNasMsg->length = mm_msg_encode(mm_msg, initialNasMsg->nas_data, size); + initialNasMsg->length = mm_msg_encode(&plain, initialNasMsg->nas_data, size); nas->registration_request_len = initialNasMsg->length; } @@ -569,47 +511,45 @@ void generateServiceRequest(as_nas_info_t *initialNasMsg, nr_ue_nas_t *nas) { LOG_I(NAS, "Generate initial NAS message: Service Request\n"); int size = 0; - fgs_nas_message_t nas_msg = {0}; - memset(&nas_msg, 0, sizeof(nas_msg)); + // NAS is security protected if has valid security contexts bool security_protected = nas->security_container->ciphering_context && nas->security_container->integrity_context; - MM_msg *mm_msg; - if (security_protected) { - /* Set security protected 5GS NAS message header (see 9.1.1 of 3GPP TS 24.501) */ - nas_msg.header.protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; - nas_msg.header.security_header_type = INTEGRITY_PROTECTED; - nas_msg.header.sequence_number = nas->security.nas_count_ul & 0xff; - size += sizeof(fgs_nas_message_security_header_t); - mm_msg = &nas_msg.security_protected.plain.mm_msg; - } else { - // Set Mobility Management plain message header - mm_msg = &nas_msg.plain.mm_msg; - } - // Fill MM plain message header - mm_msg->header.ex_protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; - mm_msg->header.security_header_type = PLAIN_5GS_MSG; - mm_msg->header.message_type = FGS_SERVICE_REQUEST; - size += sizeof(mm_msg_header_t); - - // Fill Service Request + // Set 5GMM plain header + fgmm_nas_message_plain_t plain = {0}; + plain.header = set_mm_header(FGS_SERVICE_REQUEST, PLAIN_5GS_MSG); + size += sizeof(plain.header); + // Set plain FGMM Service Request + fgs_service_request_msg_t *mm_msg = &plain.mm_msg.service_request; // Service Type - mm_msg->service_request.serviceType = SERVICE_TYPE_DATA; + mm_msg->serviceType = SERVICE_TYPE_DATA; // NAS key set identifier - mm_msg->service_request.naskeysetidentifier.naskeysetidentifier = NAS_KEY_SET_IDENTIFIER_NOT_AVAILABLE; - mm_msg->service_request.naskeysetidentifier.tsc = NAS_KEY_SET_IDENTIFIER_NATIVE; + mm_msg->naskeysetidentifier.naskeysetidentifier = NAS_KEY_SET_IDENTIFIER_NOT_AVAILABLE; + mm_msg->naskeysetidentifier.tsc = NAS_KEY_SET_IDENTIFIER_NATIVE; size += 1; // 5G-S-TMSI - size += fill_fgstmsi(&mm_msg->service_request.fiveg_s_tmsi, nas->guti); + size += fill_fgstmsi(&mm_msg->fiveg_s_tmsi, nas->guti); - /* message encoding */ - initialNasMsg->nas_data = (Byte_t *)malloc(size * sizeof(Byte_t)); if (security_protected) { + fgmm_nas_msg_security_protected_t sp = {0}; + + // Set security protected 5GS NAS message header (see 9.1.1 of 3GPP TS 24.501) + sp.header.protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; + sp.header.security_header_type = INTEGRITY_PROTECTED; + sp.header.sequence_number = nas->security.nas_count_ul & 0xff; + size += sizeof(sp.header); + + // Payload: plain message + sp.plain = plain; + + // Allocate NAS message for encoding + initialNasMsg->nas_data = malloc_or_fail(size * sizeof(*initialNasMsg->nas_data)); + // security protected encoding - int security_header_len = nas_protected_security_header_encode((char *)(initialNasMsg->nas_data), &(nas_msg.header), size); + int security_header_len = nas_protected_security_header_encode(initialNasMsg->nas_data, &sp.header, size); initialNasMsg->length = security_header_len - + mm_msg_encode(mm_msg, (uint8_t *)(initialNasMsg->nas_data + security_header_len), size - security_header_len); + + mm_msg_encode(&sp.plain, (uint8_t *)(initialNasMsg->nas_data + security_header_len), size - security_header_len); /* ciphering */ uint8_t buf[initialNasMsg->length - 7]; nas_stream_cipher_t stream_cipher; @@ -633,44 +573,37 @@ void generateServiceRequest(as_nas_info_t *initialNasMsg, nr_ue_nas_t *nas) /* length in bits */ stream_cipher.blength = (initialNasMsg->length - 6) << 3; stream_compute_integrity(nas->security_container->integrity_algorithm, &stream_cipher, mac); - printf("Integrity protected initial NAS message: mac = %x %x %x %x \n", mac[0], mac[1], mac[2], mac[3]); + LOG_D(NAS, "Integrity protected initial NAS message: mac = %x %x %x %x \n", mac[0], mac[1], mac[2], mac[3]); for (int i = 0; i < 4; i++) initialNasMsg->nas_data[2 + i] = mac[i]; } else { // plain encoding - initialNasMsg->length = mm_msg_encode(mm_msg, (uint8_t *)(initialNasMsg->nas_data), size); + // Allocate NAS message for encoding + initialNasMsg->nas_data = malloc_or_fail(size * sizeof(*initialNasMsg->nas_data)); + initialNasMsg->length = mm_msg_encode(&plain, initialNasMsg->nas_data, size); LOG_I(NAS, "PLAIN_5GS_MSG initial NAS message: Service Request with length %d \n", initialNasMsg->length); } } void generateIdentityResponse(as_nas_info_t *initialNasMsg, uint8_t identitytype, uicc_t *uicc) { - int size = sizeof(mm_msg_header_t); - fgs_nas_message_t nas_msg; - memset(&nas_msg, 0, sizeof(fgs_nas_message_t)); - MM_msg *mm_msg; + int size = sizeof(fgmm_msg_header_t); + fgmm_nas_message_plain_t plain = {0}; - mm_msg = &nas_msg.plain.mm_msg; - // set header - mm_msg->header.ex_protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; - mm_msg->header.security_header_type = PLAIN_5GS_MSG; - mm_msg->header.message_type = FGS_IDENTITY_RESPONSE; + // Plain 5GMM header + plain.header = set_mm_header(FGS_IDENTITY_RESPONSE, PLAIN_5GS_MSG); + size += sizeof(plain.header); // set identity response - mm_msg->fgs_identity_response.protocoldiscriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; - size += 1; - mm_msg->fgs_identity_response.securityheadertype = PLAIN_5GS_MSG; - size += 1; - mm_msg->fgs_identity_response.messagetype = FGS_IDENTITY_RESPONSE; - size += 1; + fgmm_identity_response_msg *mm_msg = &plain.mm_msg.fgs_identity_response; if (identitytype == FGS_MOBILE_IDENTITY_SUCI) { - size += fill_suci(&mm_msg->fgs_identity_response.fgsmobileidentity, uicc); + size += fill_suci(&mm_msg->fgsmobileidentity, uicc); } // encode the message - initialNasMsg->nas_data = malloc(size * sizeof(Byte_t)); + initialNasMsg->nas_data = malloc_or_fail(size * sizeof(*initialNasMsg->nas_data)); - initialNasMsg->length = mm_msg_encode(mm_msg, initialNasMsg->nas_data, size); + initialNasMsg->length = mm_msg_encode(&plain, initialNasMsg->nas_data, size); } static void generateAuthenticationResp(nr_ue_nas_t *nas, as_nas_info_t *initialNasMsg, uint8_t *buf) @@ -681,32 +614,21 @@ static void generateAuthenticationResp(nr_ue_nas_t *nas, as_nas_info_t *initialN res.value = calloc(1, 16); memcpy(res.value, nas->security.res, 16); - int size = sizeof(mm_msg_header_t); - fgs_nas_message_t nas_msg; - memset(&nas_msg, 0, sizeof(fgs_nas_message_t)); - MM_msg *mm_msg; + int size = sizeof(fgmm_msg_header_t); + fgmm_nas_message_plain_t plain = {0}; - mm_msg = &nas_msg.plain.mm_msg; - // set header - mm_msg->header.ex_protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; - mm_msg->header.security_header_type = PLAIN_5GS_MSG; - mm_msg->header.message_type = FGS_AUTHENTICATION_RESPONSE; - - // set authentication response - mm_msg->fgs_identity_response.protocoldiscriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; - size += 1; - mm_msg->fgs_identity_response.securityheadertype = PLAIN_5GS_MSG; - size += 1; - mm_msg->fgs_identity_response.messagetype = FGS_AUTHENTICATION_RESPONSE; - size += 1; + // Plain 5GMM header + plain.header = set_mm_header(FGS_AUTHENTICATION_RESPONSE, PLAIN_5GS_MSG); + size += sizeof(plain.header); // set response parameter - mm_msg->fgs_auth_response.authenticationresponseparameter.res = res; + fgs_authentication_response_msg *mm_msg = &plain.mm_msg.fgs_auth_response; + mm_msg->authenticationresponseparameter.res = res; size += 18; // encode the message - initialNasMsg->nas_data = malloc(size * sizeof(Byte_t)); + initialNasMsg->nas_data = malloc_or_fail(size * sizeof(*initialNasMsg->nas_data)); - initialNasMsg->length = mm_msg_encode(mm_msg, initialNasMsg->nas_data, size); + initialNasMsg->length = mm_msg_encode(&plain, initialNasMsg->nas_data, size); // Free res value after encode free(res.value); } @@ -721,48 +643,40 @@ int nas_itti_kgnb_refresh_req(instance_t instance, const uint8_t kgnb[32]) static void generateSecurityModeComplete(nr_ue_nas_t *nas, as_nas_info_t *initialNasMsg) { - int size = sizeof(mm_msg_header_t); - fgs_nas_message_t nas_msg; - memset(&nas_msg, 0, sizeof(fgs_nas_message_t)); - - MM_msg *mm_msg; + int size = sizeof(fgmm_msg_header_t); + fgmm_nas_msg_security_protected_t nas_msg = {0}; nas_stream_cipher_t stream_cipher; - uint8_t mac[4]; + uint8_t mac[NAS_INTEGRITY_SIZE]; // set security protected header - nas_msg.header.protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; - nas_msg.header.security_header_type = INTEGRITY_PROTECTED_AND_CIPHERED_WITH_NEW_SECU_CTX; - nas_msg.header.sequence_number = nas->security.nas_count_ul & 0xff; + fgs_nas_message_security_header_t *sp = &nas_msg.header; + sp->protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; + sp->security_header_type = INTEGRITY_PROTECTED_AND_CIPHERED_WITH_NEW_SECU_CTX; + sp->sequence_number = nas->security.nas_count_ul & 0xff; size += 7; - mm_msg = &nas_msg.security_protected.plain.mm_msg; + // Plain 5GMM Security Mode Complete msg + fgmm_nas_message_plain_t *plain = &nas_msg.plain; - // set header - mm_msg->header.ex_protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; - mm_msg->header.security_header_type = PLAIN_5GS_MSG; - mm_msg->header.message_type = FGS_SECURITY_MODE_COMPLETE; + // Plain 5GMM header + plain->header = set_mm_header(FGS_SECURITY_MODE_COMPLETE, PLAIN_5GS_MSG); + size += sizeof(plain->header); - // set security mode complete - mm_msg->fgs_security_mode_complete.protocoldiscriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; - size += 1; - mm_msg->fgs_security_mode_complete.securityheadertype = PLAIN_5GS_MSG; - size += 1; - mm_msg->fgs_security_mode_complete.messagetype = FGS_SECURITY_MODE_COMPLETE; - size += 1; + // Plain 5GMM payload + fgs_security_mode_complete_msg *mm_msg = &plain->mm_msg.fgs_security_mode_complete; + size += fill_imeisv(&mm_msg->fgsmobileidentity, nas->uicc); - size += fill_imeisv(&mm_msg->fgs_security_mode_complete.fgsmobileidentity, nas->uicc); - - mm_msg->fgs_security_mode_complete.fgsnasmessagecontainer.nasmessagecontainercontents.value = nas->registration_request_buf; - mm_msg->fgs_security_mode_complete.fgsnasmessagecontainer.nasmessagecontainercontents.length = nas->registration_request_len; + mm_msg->fgsnasmessagecontainer.nasmessagecontainercontents.value = nas->registration_request_buf; + mm_msg->fgsnasmessagecontainer.nasmessagecontainercontents.length = nas->registration_request_len; size += (nas->registration_request_len + 2); // encode the message - initialNasMsg->nas_data = malloc(size * sizeof(Byte_t)); + initialNasMsg->nas_data = malloc_or_fail(size * sizeof(*initialNasMsg->nas_data)); - int security_header_len = nas_protected_security_header_encode((char *)(initialNasMsg->nas_data), &(nas_msg.header), size); + int security_header_len = nas_protected_security_header_encode(initialNasMsg->nas_data, sp, size); initialNasMsg->length = security_header_len - + mm_msg_encode(mm_msg, (uint8_t *)(initialNasMsg->nas_data + security_header_len), size - security_header_len); + + mm_msg_encode(plain, (uint8_t *)(initialNasMsg->nas_data + security_header_len), size - security_header_len); /* ciphering */ uint8_t buf[initialNasMsg->length - 7]; @@ -828,89 +742,48 @@ static void handle_security_mode_command(nr_ue_nas_t *nas, as_nas_info_t *initia generateSecurityModeComplete(nas, initialNasMsg); } -static void decodeRegistrationAccept(const uint8_t *buf, int len, nr_ue_nas_t *nas) -{ - registration_accept_msg reg_acc = {0}; - /* it seems there is no 5G corresponding emm_msg_decode() function, so here - * we just jump to the right decision */ - buf += 7; /* skip security header */ - buf += 2; /* skip prot discriminator, security header, half octet */ - AssertFatal(*buf == 0x42, "this is not a NAS Registration Accept\n"); - buf++; - int decoded = decode_registration_accept(®_acc, buf, len); - AssertFatal(decoded > 0, "could not decode registration accept\n"); - if (reg_acc.guti) { - AssertFatal(reg_acc.guti->guti.typeofidentity == FGS_MOBILE_IDENTITY_5G_GUTI, - "registration accept 5GS Mobile Identity is not GUTI, but %d\n", - reg_acc.guti->guti.typeofidentity); - nas->guti = malloc(sizeof(*nas->guti)); - AssertFatal(nas->guti, "out of memory\n"); - *nas->guti = reg_acc.guti->guti; - free(reg_acc.guti); /* no proper memory management for NAS decoded messages */ - } else { - LOG_W(NAS, "no GUTI in registration accept\n"); - } -} - static void generateRegistrationComplete(nr_ue_nas_t *nas, as_nas_info_t *initialNasMsg, SORTransparentContainer *sortransparentcontainer) { int length = 0; - int size = 0; - fgs_nas_message_t nas_msg; nas_stream_cipher_t stream_cipher; - uint8_t mac[4]; - memset(&nas_msg, 0, sizeof(fgs_nas_message_t)); - fgs_nas_message_security_protected_t *sp_msg; + uint8_t mac[NAS_INTEGRITY_SIZE]; + fgmm_nas_msg_security_protected_t sp = {0}; - sp_msg = &nas_msg.security_protected; - // set header - sp_msg->header.protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; - sp_msg->header.security_header_type = INTEGRITY_PROTECTED_AND_CIPHERED; - sp_msg->header.message_authentication_code = 0; - sp_msg->header.sequence_number = nas->security.nas_count_ul & 0xff; + // set security protected header + sp.header.protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; + sp.header.security_header_type = INTEGRITY_PROTECTED_AND_CIPHERED; + sp.header.message_authentication_code = 0; + sp.header.sequence_number = nas->security.nas_count_ul & 0xff; length = 7; - sp_msg->plain.mm_msg.registration_complete.protocoldiscriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; - length += 1; - sp_msg->plain.mm_msg.registration_complete.securityheadertype = PLAIN_5GS_MSG; - sp_msg->plain.mm_msg.registration_complete.sparehalfoctet = 0; - length += 1; - sp_msg->plain.mm_msg.registration_complete.messagetype = REGISTRATION_COMPLETE; - length += 1; + // set plain 5GMM header + sp.plain.header = set_mm_header(FGS_REGISTRATION_COMPLETE, PLAIN_5GS_MSG); + length += sizeof(sp.plain.header); + registration_complete_msg *mm_msg = &sp.plain.mm_msg.registration_complete; if (sortransparentcontainer) { + mm_msg->sortransparentcontainer = sortransparentcontainer; length += sortransparentcontainer->sortransparentcontainercontents.length; } // encode the message - initialNasMsg->nas_data = malloc(length * sizeof(Byte_t)); + initialNasMsg->nas_data = malloc_or_fail(length * sizeof(*initialNasMsg->nas_data)); initialNasMsg->length = length; - - /* Encode the first octet of the header (extended protocol discriminator) */ - ENCODE_U8(initialNasMsg->nas_data + size, sp_msg->header.protocol_discriminator, size); - - /* Encode the security header type */ - ENCODE_U8(initialNasMsg->nas_data + size, sp_msg->header.security_header_type, size); - - /* Encode the message authentication code */ - ENCODE_U32(initialNasMsg->nas_data + size, sp_msg->header.message_authentication_code, size); - - /* Encode the sequence number */ - ENCODE_U8(initialNasMsg->nas_data + size, sp_msg->header.sequence_number, size); - - /* Encode the extended protocol discriminator */ - ENCODE_U8(initialNasMsg->nas_data + size, sp_msg->plain.mm_msg.registration_complete.protocoldiscriminator, size); - - /* Encode the security header type */ - ENCODE_U8(initialNasMsg->nas_data + size, sp_msg->plain.mm_msg.registration_complete.securityheadertype, size); - - /* Encode the message type */ - ENCODE_U8(initialNasMsg->nas_data + size, sp_msg->plain.mm_msg.registration_complete.messagetype, size); - - if (sortransparentcontainer) { - encode_registration_complete(&sp_msg->plain.mm_msg.registration_complete, initialNasMsg->nas_data + size, length - size); + // encode security protected header + int encoded = nas_protected_security_header_encode(initialNasMsg->nas_data, &sp.header, length); + if (encoded < 0) { + LOG_E(NAS, "generateRegistrationComplete: failed to encode security protected header\n"); + return; } + // encode 5GMM plain header + encoded = _nas_mm_msg_encode_header(&sp.plain.header, initialNasMsg->nas_data + encoded, length - encoded); + if (encoded < 0) { + LOG_E(NAS, "generateRegistrationComplete: failed to encode 5GMM plain header\n"); + return; + } + + encode_registration_complete(mm_msg, initialNasMsg->nas_data + encoded, length - encoded); /* ciphering */ uint8_t buf[initialNasMsg->length - 7]; @@ -941,6 +814,121 @@ static void generateRegistrationComplete(nr_ue_nas_t *nas, } } +/** + * @brief Capture IPv4 PDU Session Address + */ +static int capture_ipv4_addr(const uint8_t *addr, char *ip, size_t len) +{ + return snprintf(ip, len, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]); +} + +/** + * @brief Capture IPv6 PDU Session Address + */ +static int capture_ipv6_addr(const uint8_t *addr, char *ip, size_t len) +{ + // 24.501 Sec 9.11.4.10: "an interface identifier for the IPv6 link local + // address": link local starts with fe80::, and only the last 64bits are + // given (middle is zero) + return snprintf(ip, + len, + "fe80::%02x%02x:%02x%02x:%02x%02x:%02x%02x", + addr[0], + addr[1], + addr[2], + addr[3], + addr[4], + addr[5], + addr[6], + addr[7]); +} + +/** + * @brief Process PDU Session Address in PDU Session Establishment Accept message + * and configure the tun interface + */ +static void process_pdu_session_addr(pdu_session_establishment_accept_msg_t *msg) +{ + uint8_t *addr = msg->pdu_addr_ie.pdu_addr_oct; + + switch (msg->pdu_addr_ie.pdu_type) { + case PDU_SESSION_TYPE_IPV4: { + char ip[20]; + capture_ipv4_addr(&addr[0], ip, sizeof(ip)); + tun_config(1, ip, NULL, "oaitun_ue"); + setup_ue_ipv4_route(1, ip, "oaitun_ue"); + } break; + + case PDU_SESSION_TYPE_IPV6: { + char ipv6[40]; + capture_ipv6_addr(addr, ipv6, sizeof(ipv6)); + tun_config(1, NULL, ipv6, "oaitun_ue"); + } break; + + case PDU_SESSION_TYPE_IPV4V6: { + char ipv6[40]; + capture_ipv6_addr(addr, ipv6, sizeof(ipv6)); + char ipv4[20]; + capture_ipv4_addr(&addr[IPv6_INTERFACE_ID_LENGTH], ipv4, sizeof(ipv4)); + tun_config(1, ipv4, ipv6, "oaitun_ue"); + setup_ue_ipv4_route(1, ipv4, "oaitun_ue"); + } break; + + default: + LOG_E(NAS, "Unknown PDU Session Address type %d\n", msg->pdu_addr_ie.pdu_type); + break; + } +} + +/** + * @brief Handle PDU Session Establishment Accept and process decoded message + */ +static void handle_pdu_session_accept(uint8_t *pdu_buffer, uint32_t msg_length) +{ + pdu_session_establishment_accept_msg_t msg = {0}; + int size = 0; + int decoded = 0; + + // Security protected NAS header (7 bytes) + fgs_nas_message_security_header_t sec_nas_hdr = {0}; + if ((decoded = decode_5gs_security_protected_header(&sec_nas_hdr, pdu_buffer, msg_length)) < 0) { + LOG_E(NAS, "decode_5gs_security_protected_header failure in PDU Session Establishment Accept decoding\n"); + return; + } + size += decoded; + + // decode plain 5GMM message header + fgmm_msg_header_t mm_header = {0}; + if ((decoded = decode_5gmm_msg_header(&mm_header, pdu_buffer + size, msg_length - size)) < 0) { + LOG_E(NAS, "decode_5gmm_msg_header failure in PDU Session Establishment Accept decoding\n"); + return; + } + size += decoded; + + /* Process container (5GSM message) */ + // Payload container type and spare (1 octet) + size++; + // Payload container length + uint16_t iei_len = 0; + GET_SHORT(pdu_buffer + size, iei_len); + size += sizeof(iei_len); + // decode plain 5GSM message header + fgsm_msg_header_t sm_header = {0}; + if ((decoded = decode_5gsm_msg_header(&sm_header, pdu_buffer + size, msg_length - size)) < 0) { + LOG_E(NAS, "decode_5gsm_msg_header failure in PDU Session Establishment Accept decoding\n"); + return; + } + size += decoded; + + // decode PDU Session Establishment Accept + if (!decode_pdu_session_establishment_accept_msg(&msg, pdu_buffer + size, msg_length)) + LOG_E(NAS, "decode_pdu_session_establishment_accept_msg failure\n"); + + // process PDU Session + process_pdu_session_addr(&msg); + set_qfi_pduid(msg.qos_rules.rule->qfi, sm_header.pdu_session_id); +} + /** * @brief Handle DL NAS Transport and process piggybacked 5GSM messages */ @@ -949,7 +937,7 @@ static void handleDownlinkNASTransport(uint8_t *pdu_buffer, uint32_t msg_length) uint8_t msg_type = *(pdu_buffer + 16); if (msg_type == FGS_PDU_SESSION_ESTABLISHMENT_ACC) { LOG_A(NAS, "Received PDU Session Establishment Accept in DL NAS Transport\n"); - capture_pdu_session_establishment_accept_msg(pdu_buffer, msg_length); + handle_pdu_session_accept(pdu_buffer, msg_length); } else { LOG_E(NAS, "Received unexpected message in DLinformationTransfer %d\n", msg_type); } @@ -957,36 +945,34 @@ static void handleDownlinkNASTransport(uint8_t *pdu_buffer, uint32_t msg_length) static void generateDeregistrationRequest(nr_ue_nas_t *nas, as_nas_info_t *initialNasMsg, const nas_deregistration_req_t *req) { - fgs_nas_message_t nas_msg = {0}; - fgs_nas_message_security_protected_t *sp_msg; - sp_msg = &nas_msg.security_protected; - sp_msg->header.protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; - sp_msg->header.security_header_type = INTEGRITY_PROTECTED_AND_CIPHERED; - sp_msg->header.message_authentication_code = 0; - sp_msg->header.sequence_number = nas->security.nas_count_ul & 0xff; - int size = sizeof(fgs_nas_message_security_header_t); + fgmm_nas_msg_security_protected_t sp_msg = {0}; + fgs_nas_message_security_header_t *sp_header = &sp_msg.header; + sp_header->protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; + sp_header->security_header_type = INTEGRITY_PROTECTED_AND_CIPHERED; + sp_header->message_authentication_code = 0; + sp_header->sequence_number = nas->security.nas_count_ul & 0xff; + int size = sizeof(sp_msg.header); - fgs_deregistration_request_ue_originating_msg *dereg_req = &sp_msg->plain.mm_msg.fgs_deregistration_request_ue_originating; - dereg_req->protocoldiscriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; + // Plain 5GMM header + sp_msg.plain.header = set_mm_header(FGS_DEREGISTRATION_REQUEST_UE_ORIGINATING, INTEGRITY_PROTECTED_AND_CIPHERED_WITH_NEW_SECU_CTX); + size += sizeof(sp_msg.plain.header); + + // Plain 5GMM + fgs_deregistration_request_ue_originating_msg *mm_msg = &sp_msg.plain.mm_msg.fgs_deregistration_request_ue_originating; + mm_msg->deregistrationtype.switchoff = NORMAL_DEREGISTRATION; + mm_msg->deregistrationtype.reregistration_required = REREGISTRATION_NOT_REQUIRED; + mm_msg->deregistrationtype.access_type = TGPP_ACCESS; + mm_msg->naskeysetidentifier.naskeysetidentifier = 1; size += 1; - dereg_req->securityheadertype = INTEGRITY_PROTECTED_AND_CIPHERED_WITH_NEW_SECU_CTX; - size += 1; - dereg_req->messagetype = FGS_DEREGISTRATION_REQUEST_UE_ORIGINATING; - size += 1; - dereg_req->deregistrationtype.switchoff = NORMAL_DEREGISTRATION; - dereg_req->deregistrationtype.reregistration_required = REREGISTRATION_NOT_REQUIRED; - dereg_req->deregistrationtype.access_type = TGPP_ACCESS; - dereg_req->naskeysetidentifier.naskeysetidentifier = 1; - size += 1; - size += fill_guti(&dereg_req->fgsmobileidentity, nas->guti); + size += fill_guti(&mm_msg->fgsmobileidentity, nas->guti); // encode the message - initialNasMsg->nas_data = calloc(size, sizeof(Byte_t)); - int security_header_len = nas_protected_security_header_encode((char *)(initialNasMsg->nas_data), &nas_msg.header, size); + initialNasMsg->nas_data = calloc_or_fail(size, sizeof(*initialNasMsg->nas_data)); + int security_header_len = nas_protected_security_header_encode(initialNasMsg->nas_data, sp_header, size); initialNasMsg->length = security_header_len - + mm_msg_encode(&sp_msg->plain.mm_msg, (uint8_t *)(initialNasMsg->nas_data + security_header_len), size - security_header_len); + + mm_msg_encode(&sp_msg.plain, (uint8_t *)(initialNasMsg->nas_data + security_header_len), size - security_header_len); nas_stream_cipher_t stream_cipher; @@ -1011,7 +997,7 @@ static void generateDeregistrationRequest(nr_ue_nas_t *nas, as_nas_info_t *initi stream_cipher.message = (unsigned char *)(initialNasMsg->nas_data + 6); /* length in bits */ stream_cipher.blength = (initialNasMsg->length - 6) << 3; - uint8_t mac[4]; + uint8_t mac[NAS_INTEGRITY_SIZE]; stream_compute_integrity(nas->security_container->integrity_algorithm, &stream_cipher, mac); printf("mac %x %x %x %x \n", mac[0], mac[1], mac[2], mac[3]); @@ -1023,7 +1009,6 @@ static void generateDeregistrationRequest(nr_ue_nas_t *nas, as_nas_info_t *initi static void generatePduSessionEstablishRequest(nr_ue_nas_t *nas, as_nas_info_t *initialNasMsg, nas_pdu_session_req_t *pdu_req) { int size = 0; - fgs_nas_message_t nas_msg = {0}; // setup pdu session establishment request uint16_t req_length = 7; @@ -1037,69 +1022,65 @@ static void generatePduSessionEstablishRequest(nr_ue_nas_t *nas, as_nas_info_t * pdu_session_establish.pdusessiontype = pdu_req->pdusession_type; encode_pdu_session_establishment_request(&pdu_session_establish, req_buffer); - MM_msg *mm_msg; nas_stream_cipher_t stream_cipher; - uint8_t mac[4]; - nas_msg.header.protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; - nas_msg.header.security_header_type = INTEGRITY_PROTECTED_AND_CIPHERED; - nas_msg.header.sequence_number = nas->security.nas_count_ul & 0xff; + uint8_t mac[NAS_INTEGRITY_SIZE]; + + // 5GMM security protected message + fgmm_nas_msg_security_protected_t sp_msg = {0}; + // 5GMM security protected message header + fgs_nas_message_security_header_t *sp_header = &sp_msg.header; + sp_header->protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; + sp_header->security_header_type = INTEGRITY_PROTECTED_AND_CIPHERED; + sp_header->sequence_number = nas->security.nas_count_ul & 0xff; size += 7; - mm_msg = &nas_msg.security_protected.plain.mm_msg; + fgmm_nas_message_plain_t *plain = &sp_msg.plain; - // set header - mm_msg->header.ex_protocol_discriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; - mm_msg->header.security_header_type = PLAIN_5GS_MSG; - mm_msg->header.message_type = FGS_UPLINK_NAS_TRANSPORT; + // Plain 5GMM header + plain->header = set_mm_header(FGS_UPLINK_NAS_TRANSPORT, PLAIN_5GS_MSG); + size += sizeof(plain->header); - // set uplink nas transport - mm_msg->uplink_nas_transport.protocoldiscriminator = FGS_MOBILITY_MANAGEMENT_MESSAGE; + fgs_uplink_nas_transport_msg *mm_msg = &plain->mm_msg.uplink_nas_transport; + mm_msg->payloadcontainertype.iei = 0; + mm_msg->payloadcontainertype.type = 1; size += 1; - mm_msg->uplink_nas_transport.securityheadertype = PLAIN_5GS_MSG; - size += 1; - mm_msg->uplink_nas_transport.messagetype = FGS_UPLINK_NAS_TRANSPORT; - size += 1; - - mm_msg->uplink_nas_transport.payloadcontainertype.iei = 0; - mm_msg->uplink_nas_transport.payloadcontainertype.type = 1; - size += 1; - mm_msg->uplink_nas_transport.fgspayloadcontainer.payloadcontainercontents.length = req_length; - mm_msg->uplink_nas_transport.fgspayloadcontainer.payloadcontainercontents.value = req_buffer; + mm_msg->fgspayloadcontainer.payloadcontainercontents.length = req_length; + mm_msg->fgspayloadcontainer.payloadcontainercontents.value = req_buffer; size += (2 + req_length); - mm_msg->uplink_nas_transport.pdusessionid = pdu_req->pdusession_id; - mm_msg->uplink_nas_transport.requesttype = 1; + mm_msg->pdusessionid = pdu_req->pdusession_id; + mm_msg->requesttype = 1; size += 3; const bool has_nssai_sd = pdu_req->sd != 0xffffff; // 0xffffff means "no SD", TS 23.003 const size_t nssai_len = has_nssai_sd ? 4 : 1; - mm_msg->uplink_nas_transport.snssai.length = nssai_len; + mm_msg->snssai.length = nssai_len; // Fixme: it seems there are a lot of memory errors in this: this value was on the stack, // but pushed in a itti message to another thread // this kind of error seems in many places in 5G NAS - mm_msg->uplink_nas_transport.snssai.value = calloc(1, nssai_len); - mm_msg->uplink_nas_transport.snssai.value[0] = pdu_req->sst; + mm_msg->snssai.value = calloc(1, nssai_len); + mm_msg->snssai.value[0] = pdu_req->sst; if (has_nssai_sd) - INT24_TO_BUFFER(pdu_req->sd, &mm_msg->uplink_nas_transport.snssai.value[1]); + INT24_TO_BUFFER(pdu_req->sd, &mm_msg->snssai.value[1]); size += 1 + 1 + nssai_len; int dnnSize = strlen(nas->uicc->dnnStr); - mm_msg->uplink_nas_transport.dnn.value = calloc(1, dnnSize + 1); - mm_msg->uplink_nas_transport.dnn.length = dnnSize + 1; - mm_msg->uplink_nas_transport.dnn.value[0] = dnnSize; - memcpy(mm_msg->uplink_nas_transport.dnn.value + 1, nas->uicc->dnnStr, dnnSize); + mm_msg->dnn.value = calloc(1, dnnSize + 1); + mm_msg->dnn.length = dnnSize + 1; + mm_msg->dnn.value[0] = dnnSize; + memcpy(mm_msg->dnn.value + 1, nas->uicc->dnnStr, dnnSize); size += (1 + 1 + dnnSize + 1); // encode the message - initialNasMsg->nas_data = (Byte_t *)malloc(size * sizeof(Byte_t)); - int security_header_len = nas_protected_security_header_encode((char *)(initialNasMsg->nas_data), &(nas_msg.header), size); + initialNasMsg->nas_data = malloc_or_fail(size * sizeof(*initialNasMsg->nas_data)); + int security_header_len = nas_protected_security_header_encode(initialNasMsg->nas_data, sp_header, size); initialNasMsg->length = security_header_len - + mm_msg_encode(mm_msg, (uint8_t *)(initialNasMsg->nas_data + security_header_len), size - security_header_len); + + mm_msg_encode(plain, (uint8_t *)(initialNasMsg->nas_data + security_header_len), size - security_header_len); // Free allocated memory after encode free(req_buffer); - free(mm_msg->uplink_nas_transport.dnn.value); - free(mm_msg->uplink_nas_transport.snssai.value); + free(mm_msg->dnn.value); + free(mm_msg->snssai.value); /* ciphering */ uint8_t buf[initialNasMsg->length - 7]; @@ -1185,109 +1166,13 @@ static void send_nas_detach_req(nr_ue_nas_t *nas, bool wait_release) itti_send_msg_to_task(TASK_RRC_NRUE, nas->UE_id, msg); } -static void parse_allowed_nssai(nr_nas_msg_snssai_t nssaiList[8], const uint8_t *buf, const uint32_t len) -{ - int nssai_cnt = 0; - const uint8_t *end = buf + len; - while (buf < end) { - const int length = *buf++; - nr_nas_msg_snssai_t *nssai = nssaiList + nssai_cnt; - nssai->sd = 0xffffff; - - switch (length) { - case 1: - nssai->sst = *buf++; - nssai_cnt++; - break; - - case 2: - nssai->sst = *buf++; - nssai->hplmn_sst = *buf++; - nssai_cnt++; - break; - - case 4: - nssai->sst = *buf++; - nssai->sd = 0xffffff & ntoh_int24_buf(buf); - buf += 3; - nssai_cnt++; - break; - - case 5: - nssai->sst = *buf++; - nssai->sd = 0xffffff & ntoh_int24_buf(buf); - buf += 3; - nssai->hplmn_sst = *buf++; - nssai_cnt++; - break; - - case 8: - nssai->sst = *buf++; - nssai->sd = 0xffffff & ntoh_int24_buf(buf); - buf += 3; - nssai->hplmn_sst = *buf++; - nssai->hplmn_sd = 0xffffff & ntoh_int24_buf(buf); - buf += 3; - nssai_cnt++; - break; - - default: - LOG_E(NAS, "UE received unknown length in an allowed S-NSSAI\n"); - break; - } - } -} - -/* Extract Allowed NSSAI from Regestration Accept according to - 3GPP TS 24.501 Table 8.2.7.1.1 -*/ -static void get_allowed_nssai(nr_nas_msg_snssai_t nssai[8], const uint8_t *pdu_buffer, const uint32_t pdu_length) -{ - if ((pdu_buffer == NULL) || (pdu_length <= 0)) - return; - - const uint8_t *end = pdu_buffer + pdu_length; - if (((nas_msg_header_t *)(pdu_buffer))->choice.security_protected_nas_msg_header_t.security_header_type > 0) { - pdu_buffer += SECURITY_PROTECTED_5GS_NAS_MESSAGE_HEADER_LENGTH; - } - - pdu_buffer += 1 + 1 + 1 + 2; // Mandatory fields offset - /* optional fields */ - while (pdu_buffer < end) { - const int type = *pdu_buffer++; - int length = 0; - switch (type) { - case 0x77: // 5GS mobile identity - pdu_buffer += ntoh_int16_buf(pdu_buffer) + sizeof(uint16_t); - break; - - case 0x4A: // PLMN list - case 0x54: // 5GS tracking area identity - pdu_buffer += *pdu_buffer + 1; // offset length + 1 byte which contains the length - break; - - case 0x15: // allowed NSSAI - length = *pdu_buffer++; - parse_allowed_nssai(nssai, pdu_buffer, length); - pdu_buffer += length; - break; - - default: - LOG_W(NAS, "This NAS IEI (0x%2.2x) is not handled when extracting list of allowed NSSAI\n", type); - length = *pdu_buffer++; - pdu_buffer += length; - break; - } - } -} - -static void request_default_pdusession(nr_ue_nas_t *nas, int nssai_idx) +static void request_default_pdusession(nr_ue_nas_t *nas) { MessageDef *message_p = itti_alloc_new_message(TASK_NAS_NRUE, nas->UE_id, NAS_PDU_SESSION_REQ); NAS_PDU_SESSION_REQ(message_p).pdusession_id = 10; /* first or default pdu session */ NAS_PDU_SESSION_REQ(message_p).pdusession_type = 0x91; // 0x91 = IPv4, 0x92 = IPv6, 0x93 = IPv4v6 - NAS_PDU_SESSION_REQ(message_p).sst = nas_allowed_nssai[nssai_idx].sst; - NAS_PDU_SESSION_REQ(message_p).sd = nas_allowed_nssai[nssai_idx].sd; + NAS_PDU_SESSION_REQ(message_p).sst = nas->uicc->nssai_sst; + NAS_PDU_SESSION_REQ(message_p).sd = nas->uicc->nssai_sd; itti_send_msg_to_task(TASK_NAS_NRUE, nas->UE_id, message_p); } @@ -1308,11 +1193,52 @@ void *nas_nrue_task(void *args_p) } } +static void process_guti(Guti5GSMobileIdentity_t *guti, nr_ue_nas_t *nas) +{ + AssertFatal(guti->typeofidentity == FGS_MOBILE_IDENTITY_5G_GUTI, + "registration accept 5GS Mobile Identity is not GUTI, but %d\n", + guti->typeofidentity); + nas->guti = malloc_or_fail(sizeof(*nas->guti)); + *nas->guti = *guti; +} + static void handle_registration_accept(nr_ue_nas_t *nas, const uint8_t *pdu_buffer, uint32_t msg_length) { LOG_I(NAS, "[UE] Received REGISTRATION ACCEPT message\n"); - decodeRegistrationAccept(pdu_buffer, msg_length, nas); - get_allowed_nssai(nas_allowed_nssai, pdu_buffer, msg_length); + registration_accept_msg msg = {0}; + fgs_nas_message_security_header_t sp_header = {0}; + const uint8_t *end = pdu_buffer + msg_length; + // security protected header + int decoded = decode_5gs_security_protected_header(&sp_header, pdu_buffer, msg_length); + if (!decoded) { + LOG_E(NAS, "NAS Registration Accept: failed to decode security protected header\n"); + return; + } + pdu_buffer += decoded; + // plain header + fgmm_msg_header_t mm_header = {0}; + if ((decoded = decode_5gmm_msg_header(&mm_header, pdu_buffer, end - pdu_buffer)) < 0) { + LOG_E(NAS, "Failed to decode NAS Registration Accept\n"); + return; + } + if (mm_header.message_type != FGS_REGISTRATION_ACCEPT) { + LOG_E(NAS, "Failed to process NAS Registration Accept: wrong message type\n"); + return; + } + pdu_buffer += decoded; + // plain payload + if ((decoded = decode_registration_accept(&msg, pdu_buffer, end - pdu_buffer)) < 0) { + LOG_E(NAS, "Failed to decode NAS Registration Accept\n"); + return; + } + pdu_buffer += decoded; + // process GUTI + if (msg.guti) { + process_guti(&msg.guti->guti, nas); + free(msg.guti); + } else { + LOG_W(NAS, "no GUTI in registration accept\n"); + } as_nas_info_t initialNasMsg = {0}; generateRegistrationComplete(nas, &initialNasMsg, NULL); @@ -1320,11 +1246,10 @@ static void handle_registration_accept(nr_ue_nas_t *nas, const uint8_t *pdu_buff send_nas_uplink_data_req(nas, &initialNasMsg); LOG_I(NAS, "Send NAS_UPLINK_DATA_REQ message(RegistrationComplete)\n"); } - const int nssai_idx = get_user_nssai_idx(nas_allowed_nssai, nas); - if (nssai_idx < 0) { + if (get_user_nssai_idx(msg.nas_allowed_nssai, nas) < 0) { LOG_E(NAS, "NSSAI parameters not match with allowed NSSAI. Couldn't request PDU session.\n"); } else { - request_default_pdusession(nas, nssai_idx); + request_default_pdusession(nas); } } @@ -1405,16 +1330,16 @@ void *nas_nrue(void *args_p) security_state_t security_state = nas_security_rx_process(nas, pdu_buffer, pdu_length); if (security_state != NAS_SECURITY_INTEGRITY_PASSED && security_state != NAS_SECURITY_NO_SECURITY_CONTEXT) { - LOG_E(NAS, "NAS integrity failed, discard incoming message\n"); + LOG_E(NAS, "NAS integrity failed, discard incoming message: security state is %s\n", security_state_info[security_state].text); break; } int msg_type = get_msg_type(pdu_buffer, pdu_length); - if (msg_type == REGISTRATION_ACCEPT) { + if (msg_type == FGS_REGISTRATION_ACCEPT) { handle_registration_accept(nas, pdu_buffer, pdu_length); } else if (msg_type == FGS_PDU_SESSION_ESTABLISHMENT_ACC) { - capture_pdu_session_establishment_accept_msg(pdu_buffer, pdu_length); + handle_pdu_session_accept(pdu_buffer, pdu_length); } // Free NAS buffer memory after use (coming from RRC) @@ -1474,12 +1399,12 @@ void *nas_nrue(void *args_p) uint8_t *pdu_buffer = NAS_DOWNLINK_DATA_IND(msg_p).nasMsg.nas_data; int pdu_length = NAS_DOWNLINK_DATA_IND(msg_p).nasMsg.length; + int msg_type = get_msg_type(pdu_buffer, pdu_length); security_state_t security_state = nas_security_rx_process(nas, pdu_buffer, pdu_length); /* special cases accepted without protection */ if (security_state == NAS_SECURITY_UNPROTECTED) { - int msg_type = get_msg_type(pdu_buffer, pdu_length); - /* for the moment, only FGS_DEREGISTRATION_ACCEPT is accepted */ + /* for the moment, only FGS_DEREGISTRATION_ACCEPT_UE_ORIGINATING is accepted */ if (msg_type == FGS_DEREGISTRATION_ACCEPT_UE_ORIGINATING) security_state = NAS_SECURITY_INTEGRITY_PASSED; } @@ -1489,8 +1414,6 @@ void *nas_nrue(void *args_p) break; } - int msg_type = get_msg_type(pdu_buffer, pdu_length); - switch (msg_type) { case FGS_IDENTITY_REQUEST: generateIdentityResponse(&initialNasMsg, *(pdu_buffer + 3), nas->uicc); @@ -1504,19 +1427,19 @@ void *nas_nrue(void *args_p) case FGS_DOWNLINK_NAS_TRANSPORT: handleDownlinkNASTransport(pdu_buffer, pdu_length); break; - case REGISTRATION_ACCEPT: + case FGS_REGISTRATION_ACCEPT: handle_registration_accept(nas, pdu_buffer, pdu_length); break; case FGS_DEREGISTRATION_ACCEPT_UE_ORIGINATING: LOG_I(NAS, "received deregistration accept\n"); break; case FGS_PDU_SESSION_ESTABLISHMENT_ACC: - capture_pdu_session_establishment_accept_msg(pdu_buffer, pdu_length); + handle_pdu_session_accept(pdu_buffer, pdu_length); break; case FGS_PDU_SESSION_ESTABLISHMENT_REJ: LOG_E(NAS, "Received PDU Session Establishment reject\n"); break; - case REGISTRATION_REJECT: + case FGS_REGISTRATION_REJECT: LOG_E(NAS, "Received Registration reject cause: %s\n", cause_text_info[pdu_buffer[17]].text); exit(1); break; diff --git a/openair3/NAS/NR_UE/nr_nas_msg.h b/openair3/NAS/NR_UE/nr_nas_msg.h index 0e324052ad..b4a97a36d7 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.h +++ b/openair3/NAS/NR_UE/nr_nas_msg.h @@ -23,6 +23,7 @@ * \brief simulator for nr nas message * \author Yoshio INOUE, Masayuki HARADA * \email yoshio.inoue@fujitsu.com,masayuki.harada@fujitsu.com + * \protocol 5GS (5GMM and 5GSM) * \date 2020 * \version 0.1 */ @@ -30,17 +31,14 @@ #ifndef __NR_NAS_MSG_SIM_H__ #define __NR_NAS_MSG_SIM_H__ -#include "RegistrationRequest.h" -#include "FGSIdentityResponse.h" -#include "FGSAuthenticationResponse.h" -#include "FGSNASSecurityModeComplete.h" -#include "FGSDeregistrationRequestUEOriginating.h" -#include "RegistrationComplete.h" -#include "EMM/MSG/fgs_service_request.h" -#include "as_message.h" -#include "FGSUplinkNasTransport.h" +#include #include +#include +#include +#include "as_message.h" +#include "NR_NAS_defs.h" #include "secu_defs.h" +#include "NR_NAS_defs.h" #define INITIAL_REGISTRATION 0b001 @@ -48,18 +46,11 @@ #define SECURITY_PROTECTED_5GS_NAS_MESSAGE_HEADER_LENGTH 7 #define PAYLOAD_CONTAINER_LENGTH_MIN 3 #define PAYLOAD_CONTAINER_LENGTH_MAX 65537 +#define NAS_INTEGRITY_SIZE 4 /* 3GPP TS 24.501: 9.11.3.50 Service type */ #define SERVICE_TYPE_DATA 0x1 -/* List of allowed NSSAI from NAS messaging. */ -typedef struct { - int sst; - int hplmn_sst; - int sd; - int hplmn_sd; -} nr_nas_msg_snssai_t; - /* Security Key for SA UE */ typedef struct { uint8_t kausf[32]; @@ -85,82 +76,6 @@ typedef struct { instance_t UE_id; } nr_ue_nas_t; -typedef enum fgs_protocol_discriminator_e { - /* Protocol discriminator identifier for 5GS Mobility Management */ - FGS_MOBILITY_MANAGEMENT_MESSAGE = 0x7E, - - /* Protocol discriminator identifier for 5GS Session Management */ - FGS_SESSION_MANAGEMENT_MESSAGE = 0x2E, -} fgs_protocol_discriminator_t; - -typedef struct { - uint8_t ex_protocol_discriminator; - uint8_t security_header_type; - uint8_t message_type; -} mm_msg_header_t; - -/* Structure of security protected header */ -typedef struct { - fgs_protocol_discriminator_t protocol_discriminator; - uint8_t security_header_type; - uint32_t message_authentication_code; - uint8_t sequence_number; -} fgs_nas_message_security_header_t; - -typedef union { - mm_msg_header_t header; - registration_request_msg registration_request; - fgs_service_request_msg_t service_request; - fgs_identiy_response_msg fgs_identity_response; - fgs_authentication_response_msg fgs_auth_response; - fgs_deregistration_request_ue_originating_msg fgs_deregistration_request_ue_originating; - fgs_security_mode_complete_msg fgs_security_mode_complete; - registration_complete_msg registration_complete; - fgs_uplink_nas_transport_msg uplink_nas_transport; -} MM_msg; - -typedef struct { - MM_msg mm_msg; /* 5GS Mobility Management messages */ -} fgs_nas_message_plain_t; - -typedef struct { - fgs_nas_message_security_header_t header; - fgs_nas_message_plain_t plain; -} fgs_nas_message_security_protected_t; - -typedef union { - fgs_nas_message_security_header_t header; - fgs_nas_message_security_protected_t security_protected; - fgs_nas_message_plain_t plain; -} fgs_nas_message_t; - -typedef struct { - union { - mm_msg_header_t plain_nas_msg_header; - struct security_protected_nas_msg_header_s { - uint8_t ex_protocol_discriminator; - uint8_t security_header_type; - uint16_t message_authentication_code1; - uint16_t message_authentication_code2; - uint8_t sequence_number; - } security_protected_nas_msg_header_t; - } choice; -} nas_msg_header_t; - -typedef struct { - uint8_t ex_protocol_discriminator; - uint8_t pdu_session_id; - uint8_t PTI; - uint8_t message_type; -} fgs_sm_nas_msg_header_t; - -typedef struct { - mm_msg_header_t plain_nas_msg_header; - uint8_t payload_container_type; - uint16_t payload_container_length; - fgs_sm_nas_msg_header_t sm_nas_msg_header; -} dl_nas_transport_t; - nr_ue_nas_t *get_ue_nas_info(module_id_t module_id); void generateRegistrationRequest(as_nas_info_t *initialNasMsg, nr_ue_nas_t *nas); void generateServiceRequest(as_nas_info_t *initialNasMsg, nr_ue_nas_t *nas); diff --git a/openair3/NAS/TEST/AS_SIMULATOR/as_process.c b/openair3/NAS/TEST/AS_SIMULATOR/as_process.c index 20b7a7ce35..740c67b1e0 100644 --- a/openair3/NAS/TEST/AS_SIMULATOR/as_process.c +++ b/openair3/NAS/TEST/AS_SIMULATOR/as_process.c @@ -137,11 +137,6 @@ int process_nas_establish_req(int msg_id, const nas_establish_req_t* req, printf("INFO\t: %s - Process NAS signalling connection establishment " "request\n", __FUNCTION__); - // Attach_Request.Pdn_Connectivity_Request.ebi = 5 - //req->initialNasMsg.data[23] = 0x52; // MME DEBUG (Reject Attachment) - // Attach_Request.Pdn_Connectivity_Request.messagetype = WRONG_MESSAGE_TYPE - //req->initialNasMsg.data[25] = 0xc4; // MME DEBUG (Send ESM status) - snprintf(_mscgen_buffer, MSCGEN_BUFFER_SIZE, "cause = %s, type = %s, tmsi = {MMEcode = %d, m_tmsi = %u}%c", rrcCause(req->cause), rrcType(req->type), @@ -173,7 +168,7 @@ int process_nas_establish_req(int msg_id, const nas_establish_req_t* req, ind->tac = DEFAULT_TAC; if (req->initialNasMsg.length > 0) { - ind->initialNasMsg.data = (Byte_t*)malloc(req->initialNasMsg.length); + ind->initialNasMsg.data = malloc(req->initialNasMsg.length); if (ind->initialNasMsg.data) { memcpy(ind->initialNasMsg.data, req->initialNasMsg.data, @@ -212,15 +207,6 @@ int process_ul_info_transfer_req(int msg_id, const ul_info_transfer_req_t* req, printf("INFO\t: %s - Process uplink data transfer request\n", __FUNCTION__); - // Attach_Complete.Activate_Default_EPS_Bearer_Context_Accept.ebi = UNASSIGNED - //if (req->nasMsg.data[7] == 0x43) { - // req->nasMsg.data[10] = 0x02; // MME DEBUG (Send ESM status) - //} - // Deactivate_EPS_Bearer_Context_Accept.ebi = UNASSIGNED - //if (req->nasMsg.data[8] == 0xCE) { - // req->nasMsg.data[6] = 0x02; // MME DEBUG (Discard ESM message) - //} - snprintf(_mscgen_buffer, MSCGEN_BUFFER_SIZE, "tmsi = {MMEcode = %d, m_tmsi = %u}%c", req->s_tmsi.MMEcode, req->s_tmsi.m_tmsi, '\0'); @@ -250,7 +236,7 @@ int process_ul_info_transfer_req(int msg_id, const ul_info_transfer_req_t* req, ind->UEid = 1; // Valid UEid starts at index 1 if (req->nasMsg.length > 0) { - ind->nasMsg.data = (Byte_t*)malloc(req->nasMsg.length); + ind->nasMsg.data = malloc(req->nasMsg.length); if (ind->nasMsg.data) { memcpy(ind->nasMsg.data, req->nasMsg.data, req->nasMsg.length); @@ -258,26 +244,9 @@ int process_ul_info_transfer_req(int msg_id, const ul_info_transfer_req_t* req, } } - // Identity-Response.messagetype = WRONG_MESSAGE_TYPE - //if (ind->nasMsg.data[1] == 0x56) { - // ind->nasMsg.data[1] = 0x47; // MME DEBUG (Send EMM status) - //} - // Authentication-Response.messagetype = WRONG_MESSAGE_TYPE - //if (ind->nasMsg.data[1] == 0x53) { - // ind->nasMsg.data[1] = 0x47; // MME DEBUG (Send EMM status) - //} - // Security-Mode-Complete.messagetype = WRONG_MESSAGE_TYPE - //if (ind->nasMsg.data[7] == 0x5e) { - // ind->nasMsg.data[7] = 0x47; // MME DEBUG (Send EMM status) - //} - /* Setup uplink information confirmation message */ cnf->UEid = 0; cnf->errCode = AS_SUCCESS; - // Transmission failure of Attach Complete message - //if (req->nasMsg.data[7] == 0x43) { - // cnf->errCode = AS_FAILURE; // UE DEBUG - //} printf("[%s][%s][--- Uplink Information Indication " "(0x%.4x), UEid = %u\\n%s --->][%s]\n", getTime(), @@ -324,14 +293,6 @@ int process_nas_establish_rsp(int msg_id, const nas_establish_rsp_t* rsp, printf("INFO\t: %s - Process NAS signalling connection establishment " "response\n", __FUNCTION__); - // Attach_Accept - //if (rsp->nasMsg.data[7] == 0x42) { - // Activate_Default_EPS_Bearer_Context_Request.ebi = UNASSIGNED - //rsp->nasMsg.data[19] = 0x02; // UE DEBUG (Send ESM status) - // Activate_Default_EPS_Bearer_Context_Request.messagetype = WRONG_MESSAGE_TYPE - //rsp->nasMsg.data[21] = 0xc4; // MME DEBUG (Send ESM status) - //} - printf("[%s][%s][--- NAS Signalling Connection Establishment " "Response (0x%.4x)\\nerrCode = %s, UEid = %u --->][%s]\n", getTime(), _mme_id, msg_id, @@ -360,7 +321,7 @@ int process_nas_establish_rsp(int msg_id, const nas_establish_rsp_t* rsp, cnf->errCode = rsp->errCode; if (rsp->nasMsg.length > 0) { - cnf->nasMsg.data = (Byte_t*)malloc(rsp->nasMsg.length); + cnf->nasMsg.data = malloc(rsp->nasMsg.length); if (cnf->nasMsg.data) { memcpy(cnf->nasMsg.data, rsp->nasMsg.data, @@ -392,15 +353,6 @@ int process_dl_info_transfer_req(int msg_id, const dl_info_transfer_req_t* req, printf("INFO\t: %s - Process downlink data transfer request\n", __FUNCTION__); - // Activate_default_EPS_Bearer_Context_Request.ebi = 6 (already active) - //if (req->nasMsg.data[8] == 0xC1) { - // req->nasMsg.data[6] = 0x52; // UE DEBUG (Accept with same ebi) - //} - // Deactivate_EPS_Bearer_Context_Request.ebi = UNASSIGNED - //if (req->nasMsg.data[8] == 0xCD) { - // req->nasMsg.data[6] = 0x02; // UE DEBUG - //} - printf("[%s][%s][--- Downlink Information Request " "(0x%.4x), UEid = %u --->][%s]\n", getTime(), _mme_id, msg_id, req->UEid, _as_id); @@ -426,7 +378,7 @@ int process_dl_info_transfer_req(int msg_id, const dl_info_transfer_req_t* req, /* Setup downlink information indication message */ if (req->nasMsg.length > 0) { - ind->nasMsg.data = (Byte_t*)malloc(req->nasMsg.length); + ind->nasMsg.data = malloc(req->nasMsg.length); if (ind->nasMsg.data) { memcpy(ind->nasMsg.data, req->nasMsg.data, req->nasMsg.length); @@ -524,744 +476,3 @@ static int _process_dump(char* buffer, int len, const char* msg, int size) buffer[index] = '\0'; return (index); } - -/* - 04 01 04 10 00 00 0f 00 00 00 01 00 00 00 20 8f - 10 00 22 00 00 00 07 41 71 0b f6 02 f8 01 01 02 - 0f 00 00 00 01 05 80 80 00 00 00 00 04 02 01 d0 - 31 52 02 f8 01 00 01 e0 -*/ -/* - U16 msgID = [04 01] - AS_NAS_ESTABLISH_REQ - U8 cause = [04] - NET_ESTABLISH_CAUSE_MO_SIGNAL - U8 type = [10] - NET_ESTABLISH_TYPE_ORIGINATING_SIGNAL - as_stmsi_t s_tmsi - U8 MMEcode = [0f] - U32 m_tmsi = [00 00 00 01] - plmn_t plmnID = [20 8f 10] - Byte_t MCCdigit2:4 = [0] - Byte_t MCCdigit1:4 = [2] - Byte_t MNCdigit3:4 = [f] - Byte_t MCCdigit3:4 = [8] - Byte_t MNCdigit2:4 = [0] - Byte_t MNCdigit1:4 = [1] - - U32 Length = [22 00 00 00] (34 octets) - U8* initialNasMsg = [07 41 71 0b f6 02 f8 01 01 02 0f 00 00 00 01 05] - [80 80 00 00 00 00 04 02 01 d0 31 52 02 f8 01 00] - [01 e0] - - U8:4 Security header type = [0] - Not protected - U8:4 Protocol discriminator = [7] - EMM message - U8 EMM message identifier = [41] - Attach Request - - U8:4 NAS KSI = [7] - No key available - U8:4 Attach Type = [1] - EPS Mobile Identity = [0b f6 02 f8 01 01 02 0f 00 00 00 01] - Length = [0b] (11 bytes) - U8:4 = 1111 = [f] - U8:1 oddeven = 0 - U8:3 typeofidentity = 110 = [6] - GUTI - U8:4 mccdigit2 = [0] - U8:4 mccdigit1 = [2] - U8:4 mncdigit3 = [f] - U8:4 mccdigit3 = [8] - U8:4 mncdigit2 = [0] - U8:4 mncdigit1 = [1] - U16 mmegroupid = [01 02] - U8 mmecode = [0f] - U32 mtmsi = [00 00 00 01] - UE network capability = [05 80 80 00 00 00] - Length = [05] (5 bytes) - U8 eea = [80] - EEA0 - U8 eia = [80] - EIA0 - U8 uea = [00] - U8:1 ucs2 = 0 - U8:7 uia = 0000000 = [00] - U8:3 spare = 000 - U8:1 csfb = 0 - U8:1 lpp = 0 - U8:1 lcs = 0 - U8:1 srvcc = 0 - U8:1 nf = 0 = [00] - - ESM message container = [00 04 02 01 d0 31] - Length = [00 04] (4 bytes) - ESM message = [02 01 d0 31] - U8:4 EPS bearer identity = [0] - Not assigned - U8:4 Protocol discriminator = [2] - ESM message - U8 Procedure Transaction Identity = [01] - U8 ESM message identifier = [d0] - PDN Connectivity Request - U8:4 Pdn type = [3] - IPv4v6 - U8:4 Request type = [1] - Initial request - - Last TAI = [52 02 f8 01 00 01] - PLMN = 20810, TAC = 00 01 - Old GUTI type = [e0] - Native GUTI -*/ - -/* - 07 04 00 00 00 00 03 00 00 00 07 44 03 -*/ -/* - U16 msgID = [07 04] - AS_DL_INFO_TRANSFER_IND - U32 UEid = [00 00 00 00] - - U32 Length = [03 00 00 00] (3 octets) - U8* NasMsg = [07 44 03] - - U8:4 Security header type = [0] - Not protected - U8:4 Protocol discriminator = [7] - EMM message - U8 EMM message identifier = [44] - Attach Reject - - U8 EMM cause code = [03] - EMM_CAUSE_ILLEGAL_UE -*/ - -/* - 07 04 00 00 00 00 10 00 00 00 27 ab ab ab ab 00 - 07 44 13 78 00 04 02 01 d1 1f -*/ -/* - U16 msgID = [07 04] - AS_DL_INFO_TRANSFER_IND - U32 UEid = [00 00 00 00] - - U32 Length = [10 00 00 00] (16 octets) - U8* NasMsg = [27 ab ab ab ab 00 07 44 13 78 00 04 02 01 d1 1f] - - U8:4 Security header type = [2] - Integrity protected and cyphered - U8:4 Protocol discriminator = [7] - EMM message - U32 Message authentication code = [ab ab ab ab] - U8 Sequence number = [00] - 0 - - NAS message = [07 44 13 78 00 04 02 d1 1f] - U8:4 Security header type = [0] - Not protected - U8:4 Protocol discriminator = [7] - EMM message - U8 EMM message identifier = [44] - Attach Reject - - U8 EMM cause code = [13] - #19 ESM failure - - ESM message container = [00 04 02 01 d1 1f] - U16 Length = [00 04] (4 octets) - U8* EsmMsg = [02 01 d1 1f] - U8:4 EPS bearer identity = [0] - Not assigned - U8:4 Protocol discriminator = [2] - ESM message - U8 Procedure Transaction Identity = [01] - U8 ESM message identifier = [d1] - PDN Connectivity Reject - - U8 ESM cause code = [1f] - REQUEST_REJECTED_UNSPECIFIED -*/ - -/* - 04 08 01 00 00 00 46 00 00 00 27 ab ab ab ab 00 - 07 42 01 e0 06 24 02 f8 01 00 01 00 26 52 01 c1 - 05 03 48 87 40 78 0e 77 77 77 2e 65 75 72 65 63 - 6f 6d 2e 66 72 0d 03 c0 a8 02 3c 02 21 70 ff c0 - a8 02 3c 50 0b f6 02 f8 01 01 02 0f 00 00 00 01 -*/ -/* - U16 msgID = [04 08] - AS_NAS_ESTABLISH_CNF - U8 errCode = [01] - SUCCESS - - U32 Length = [00 00 00 46] (70 octets) - U8* NasMsg = [27 ab ab ab ab 00 07 42 01 e0 06 24 02 f8 01 00] - [01 00 26 52 01 c1 05 03 48 87 40 78 0e 77 77 77] - [2e 65 75 72 65 63 6f 6d 2e 66 72 0d 03 c0 a8 02] - [3c 02 21 70 ff c0 a8 02 3c 50 0b f6 02 f8 01 01] - [02 0f 00 00 00 01] - - U8:4 Security header type = [2] - Integrity protected and cyphered - U8:4 Protocol discriminator = [7] - EMM message - U32 Message authentication code = [ab ab ab ab] - U8 Sequence number = [00] - 0 - - NAS message = [07 42 01 e0 06 24 02 f8 01 00 01 00 26 52 01 c1] - [05 03 48 87 40 78 0e 77 77 77 2e 65 75 72 65 63] - [6f 6d 2e 66 72 0d 03 c0 a8 02 3c 02 21 70 ff c0] - [a8 02 3c 50 0b f6 02 f8 01 01 02 0f 00 00 00 01] - U8:4 Security header type = [0] - Not protected - U8:4 Protocol discriminator = [7] - EMM message - U8 EMM message identifier = [42] - Attach Accept - - U8:4 Spare = [0] - U8:4 EPS attach result = [1] - EPS - U8:3 T3412 unit = 111 - Deactivated - U8:5 T3412 value = 00000 - - TAI list = [06 24 02 f8 01 00 01] - Length = [06] - U8:1 spare = 0 - U8:2 Type of list = 01 - list of TACs belonging to one PLMN, - with consecutive TAC values - U8:5 Number of elements = 0 0100 - 4 consecutive TACs - TAI = [02 f8 01 00 01] - PLMN = 20810, TAC = 00 01 - - ESM message container = [00 26 52 01 c1 05 03 48 87 40 78 0e 77 77 77 2e] - [65 75 72 65 63 6f 6d 2e 66 72 0d 03 c0 a8 02 3c] - [02 21 70 ff c0 a8 02 3c] - U16 Length = [00 26] (38 octets) - U8:4 EPS bearer identity = [5] - ebi = 5 - U8:4 Protocol discriminator = [2] - ESM message - U8 Procedure Transaction Identity = [01] - U8 ESM message identifier = [c1] - Activate Default EPS Bearer Context Request - - EPS Qos = [05 03 48 87 40 78] - Length = [05] - 5 octets - QCI = [03] - 3 - Maximum bit rate for uplink = [48] - 128K - Maximum bit rate for downlink = [87] - 1024K - Guaranteed bit rate for uplink = [40] - 64K - Guaranteed bit rate for downlink = [78] - 512K - - Access point name = [0e 77 77 77 2e 65 75 72 65 63 6f 6d 2e 66 72] - Length = [0e] - 14 octets - APN = "www.eurecom.fr" - - PDN address = [0d 03 c0 a8 02 3c 02 21 70 ff c0 a8 02 3c] - Length = [0d] - 13 octets - U8:5 Spare = 00000 - 0 - U8:3 Pdn type = 011 - IPv4v6 - PDN address information = [c0 a8 02 3c 02 21 70 ff c0 a8 02 3c] -*/ - -/* - 06 01 00 00 00 00 0f 00 00 00 01 00 00 00 0d 00 - 00 00 27 ab ab ab ab 00 07 43 00 03 52 00 c2 -*/ -/* - U16 msgID = [06 01] - AS_UL_INFO_TRANSFER_REQ - U32 UEid = [00 00 00 00] - as_stmsi_t s_tmsi - U8 MMEcode = [0f] - U32 m_tmsi = [00 00 00 01] - - U32 Length = [00 00 00 0d] (13 octets) - U8* NasMsg = [27 ab ab ab ab 00 07 43 00 03 52 00 c2] - - U8:4 Security header type = [2] - Integrity protected and ciphered - U8:4 Protocol discriminator = [7] - EMM message - U32 Message authentication code = [ab ab ab ab] - U8 Sequence number = [00] - Uplink counter value - - NAS message = [07 43 00 03 52 00 c2] - U8:4 Security header type = [0] - Not protected - U8:4 Protocol discriminator = [7] - EMM message - U8 EMM message identifier = [43] - Attach Complete - - ESM message container = [00 03 52 00 c2] - Length = [00 03] (3 bytes) - ESM message = [52 00 c2] - U8:4 EPS bearer identity = [5] - ebi = 5 - U8:4 Protocol discriminator = [2] - ESM message - U8 Procedure Transaction Identity = [00] - unassigned - U8 ESM message identifier = [c2] - Activate Default EPS Bearer Context Accept -*/ - -/* - 07 04 00 00 00 00 03 00 00 00 07 55 10 -*/ -/* - U16 msgID = [07 04] - AS_DL_INFO_TRANSFER_IND - U32 UEid = [00 00 00 00] - - U32 Length = [03 00 00 00] (3 octets) - U8* NasMsg = [07 55 10] - - U8:4 Security header type = [0] - Not protected - U8:4 Protocol discriminator = [7] - EMM message - U8 EMM message identifier = [55] - Identity Request - - U8:4 Identity type = [1] - IMSI - U8:4 spare = [0] -*/ - -/* - 06 01 00 00 00 00 0f 00 00 00 01 00 00 00 0b 00 - 00 00 07 56 08 21 80 01 0f 00 10 32 f4 -*/ -/* - U16 msgID = [06 01] - AS_UL_INFO_TRANSFER_REQ - U32 UEid = [00 00 00 00] - as_stmsi_t s_tmsi - U8 MMEcode = [0f] - U32 m_tmsi = [00 00 00 01] - - U32 Length = [00 00 00 0b] (11 octets) - U8* NasMsg = [07 56 08 21 80 01 0f 00 10 32 f4] - U8:4 Security header type = [0] - Not protected - U8:4 Protocol discriminator = [7] - EMM message - U8 EMM message identifier = [56] - Identity Response - - Mobile identity = [08 21 80 01 0f 00 10 32 f4] - Length = [08] - 8 octets - U8:4 Identity digit 1 = [2] - 2 - U8:1 odd/even indicator = [0] - even number of identity digits - U8:3 Type of identity = [001] - IMSI - U8:4 Identity digit 3 = [8] - 8 - U8:4 Identity digit 2 = [0] - 0 - U8:4 Identity digit 5 = [0] - 0 - U8:4 Identity digit 4 = [1] - 1 - U8:4 Identity digit 7 = [0] - 0 - U8:4 Identity digit 6 = [f] - f - U8:4 Identity digit 9 = [0] - 0 - U8:4 Identity digit 8 = [0] - 0 - U8:4 Identity digit 11 = [1] - 1 - U8:4 Identity digit 10 = [0] - 0 - U8:4 Identity digit 13 = [3] - 3 - U8:4 Identity digit 12 = [2] - 2 - U8:4 Identity digit 15 = [f] - f - U8:4 Identity digit 16 = [4] - 4 - -IMSI = 20810f00001234f (2081000001234) -*/ - -/* - 07 04 00 00 00 00 24 00 00 00 07 52 00 00 00 00 - 00 00 00 00 00 00 00 00 00 01 02 03 04 10 00 00 - 00 00 00 00 80 05 04 03 02 00 00 00 00 00 -*/ -/* - U16 msgID = [07 04] - AS_DL_INFO_TRANSFER_IND - U32 UEid = [00 00 00 00] - - U32 Length = [24 00 00 00] (36 octets) - U8* NasMsg = [07 52 00 00 00 00 00 00 00 00 00 00 00 00 00 01] - [02 03 04 10 00 00 00 00 00 00 80 05 04 03 02 00] - [00 00 00 00] - - U8:4 Security header type = [0] - Not protected - U8:4 Protocol discriminator = [7] - EMM message - U8 EMM message identifier = [52] - Authentication Request - - U8:4 NAS key set identifier = [0] - 000 - U8:4 spare = [0] - RAND = [00 00 00 00 00 00 00 00 00 00 00 00 01 02 03 04] - AUTHN Length = [10] - 16 octets - AUTHN = [00 00 00 00 00 00 80 05 04 03 02 00 00 00 00 00] -*/ - -/* - 06 01 00 00 00 00 0f 00 00 00 01 00 00 00 13 00 - 00 00 07 53 10 67 70 3a 31 f2 2a 2d 51 00 00 00 - 00 00 00 00 00 -*/ -/* - U16 msgID = [06 01] - AS_UL_INFO_TRANSFER_REQ - U32 UEid = [00 00 00 00] - as_stmsi_t s_tmsi - U8 MMEcode = [0f] - U32 m_tmsi = [00 00 00 01] - - U32 Length = [00 00 00 13] (19 octets) - U8* NasMsg = [07 53 10 67 70 3a 31 f2 2a 2d 51 00 00 00 00 00 00 00 00] - U8:4 Security header type = [0] - Not protected - U8:4 Protocol discriminator = [7] - EMM message - U8 EMM message identifier = [53] - Authentication Response - - RES Length = [10] - 16 octets - RES = [67 70 3a 31 f2 2a 2d 51 00 00 00 00 00 00 00 00] -*/ - -/* - 07 04 00 00 00 00 10 00 00 00 37 ab ab ab ab 00 - 07 5d 00 00 05 80 80 00 00 00 -*/ -/* - U16 msgID = [07 04] - AS_DL_INFO_TRANSFER_IND - U32 UEid = [00 00 00 00] - - U32 Length = [10 00 00 00] (16 octets) - U8* NasMsg = [37 ab ab ab ab 00 07 5d 00 00 05 80 80 00 00 00] - - U8:4 Security header type = [3] - Integrity protected with - new EPS security context - U8:4 Protocol discriminator = [7] - EMM message - U32 Message authentication code = [ab ab ab ab] - U8 Sequence number = [00] - 0 - - NAS message = [07 5d 00 00 05 80 80 00 00 00] - U8:4 Security header type = [0] - Not protected - U8:4 Protocol discriminator = [7] - EMM message - U8 EMM message identifier = [5d] - Security Mode Command - - U8 Selected NAS security algorithms = [00] - U8:4 Spare half octet = [0] - U8:4 NAS key set identifier = [0] - Replayed UE security capabilities = [05 80 80 00 00 00] - U8 EEA = [80] - EEA0 - U8 EIA = [80] - EIA0 - U8 UEA = [00] - U8 UIA = [00] - U8 GEA = [00] -*/ - -/* - 06 01 00 00 00 00 0f 00 00 00 01 00 00 00 08 00 - 00 00 47 ab ab ab ab 00 07 5e -*/ -/* - U16 msgID = [06 01] - AS_UL_INFO_TRANSFER_REQ - U32 UEid = [00 00 00 00] - as_stmsi_t s_tmsi - U8 MMEcode = [0f] - U32 m_tmsi = [00 00 00 01] - - U32 Length = [00 00 00 08] (8 octets) - U8* NasMsg = [47 ab ab ab ab 00 07 5e] - - U8:4 Security header type = [4] - Integrity protected and ciphered with - new EPS security context - U8:4 Protocol discriminator = [7] - EMM message - U32 Message authentication code = [ab ab ab ab] - U8 Sequence number = [00] - Uplink counter value - - NAS message = [07 5e] - U8:4 Security header type = [0] - Not protected - U8:4 Protocol discriminator = [7] - EMM message - U8 EMM message identifier = [5e] - Security Mode Complete -*/ - -/* - 06 01 00 00 00 00 0f 00 00 00 01 00 00 00 09 00 - 00 00 27 ab ab ab ab 00 07 5f 18 -*/ -/* - U16 msgID = [06 01] - AS_UL_INFO_TRANSFER_REQ - U32 UEid = [00 00 00 00] - as_stmsi_t s_tmsi - U8 MMEcode = [0f] - U32 m_tmsi = [00 00 00 01] - - U32 Length = [00 00 00 09] (9 octets) - U8* NasMsg = [27 ab ab ab ab 00 07 5f 18] - - U8:4 Security header type = [2] - Integrity protected and ciphered - U8:4 Protocol discriminator = [7] - EMM message - U32 Message authentication code = [ab ab ab ab] - U8 Sequence number = [00] - Uplink counter value - - NAS message = [07 5f 18] - U8:4 Security header type = [0] - Not protected - U8:4 Protocol discriminator = [7] - EMM message - U8 EMM message identifier = [5f] - Security Mode Reject - - U8 EMM cause code = [18] - EMM_CAUSE_SECURITY_MODE_REJECTED -*/ - -/* - 07 01 00 00 00 00 00 00 00 00 00 00 00 00 04 00 - 00 00 52 00 e8 6f -*/ -/* - U16 msgID = [07 01] - AS_DL_INFO_TRANSFER_REQ - U32 UEid = [00 00 00 00] - as_stmsi_t s_tmsi - U8 MMEcode = [00] - !!! - U32 m_tmsi = [00 00 00 00] - !!! - - U32 Length = [00 00 00 04] (4 octets) - NAS message = [52 00 e8 6f] - - U8:4 EPS bearer identity = [5] - ebi = 5 - U8:4 Protocol discriminator = [2] - ESM message - U8 Procedure Transaction Identity = [00] - unassigned - U8 ESM message identifier = [e8] - ESM Status - - U8 ESM cause code = [6f] - #111 PROTOCOL_ERROR -*/ - -/* - 06 01 00 00 00 00 12 00 00 00 01 00 00 00 0a 00 - 00 00 27 ab ab ab ab 00 02 01 e8 2b -*/ -/* - U16 msgID = [06 01] - AS_UL_INFO_TRANSFER_REQ - U32 UEid = [00 00 00 00] - as_stmsi_t s_tmsi - U8 MMEcode = [12] - U32 m_tmsi = [00 00 00 01] - - U32 Length = [00 00 00 0a] (10 octets) - U8* NasMsg = [27 ab ab ab ab 00 02 01 e8 2b] - - U8:4 Security header type = [2] - Integrity protected and ciphered - U8:4 Protocol discriminator = [7] - EMM message - U32 Message authentication code = [ab ab ab ab] - U8 Sequence number = [00] - Uplink counter value - - NAS message = [02 01 e8 2b] - U8:4 EPS bearer identity = [0] - Not assigned - U8:4 Protocol discriminator = [2] - ESM message - U8 Procedure Transaction Identity = [01] - U8 ESM message identifier = [e8] - ESM Status - - U8 ESM cause code = [2b] - #43 INVALID_EPS_BEARER_IDENTITY -*/ - -/* - 06 01 00 00 00 00 12 00 00 00 01 00 00 00 0a 00 - 00 00 27 ab ab ab ab 00 02 03 d2 06 -*/ -/* - U16 msgID = [06 01] - AS_UL_INFO_TRANSFER_REQ - U32 UEid = [00 00 00 00] - as_stmsi_t s_tmsi - U8 MMEcode = [12] - U32 m_tmsi = [00 00 00 01] - - U32 Length = [00 00 00 0a] (10 octets) - U8* NasMsg = [27 ab ab ab ab 00 02 03 d2 06] - - U8:4 Security header type = [2] - Integrity protected and ciphered - U8:4 Protocol discriminator = [7] - EMM message - U32 Message authentication code = [ab ab ab ab] - U8 Sequence number = [00] - Uplink counter value - - NAS message = [02 03 d2 06] - U8:4 EPS bearer identity = [0] - Not assigned - U8:4 Protocol discriminator = [2] - ESM message - U8 Procedure Transaction Identity = [03] - U8 ESM message identifier = [d2] - PDN Disconnect Request - - U8:4 Spare half octet = [0] - U8:4 Linked EPS bearer identity = [6] - ebi = 6 -*/ - -/* - 06 08 00 00 00 00 01 00 00 00 -*/ -/* - U16 msgID = [06 08] - AS_UL_INFO_TRANSFER_CNF - U32 UEid = [00 00 00 00] - U8 errCode = [01] - SUCCESS -*/ - -/* - 06 01 00 00 00 00 12 00 00 00 01 00 00 00 09 00 - 00 00 27 ab ab ab ab 00 82 00 ce -*/ -/* - U16 msgID = [06 01] - AS_UL_INFO_TRANSFER_REQ - U32 UEid = [00 00 00 00] - as_stmsi_t s_tmsi - U8 MMEcode = [12] - U32 m_tmsi = [00 00 00 01] - - U32 Length = [00 00 00 09] (9 octets) - U8* NasMsg = [27 ab ab ab ab 00 82 00 ce] - - U8:4 Security header type = [2] - Integrity protected and ciphered - U8:4 Protocol discriminator = [7] - EMM message - U32 Message authentication code = [ab ab ab ab] - U8 Sequence number = [00] - Uplink counter value - - NAS message = [82 00 ce] - U8:4 EPS bearer identity = [8] - 8 - U8:4 Protocol discriminator = [2] - ESM message - U8 Procedure Transaction Identity = [00] - U8 ESM message identifier = [ce] - Deactivate EPS Bearer Context Accept -*/ - -/* - 07 01 01 00 00 00 00 00 00 00 00 00 00 00 0a 00 - 00 00 27 ab ab ab ab 00 62 02 cd 24 -*/ -/* - U16 msgID = [07 01] - AS_DL_INFO_TRANSFER_REQ - U32 UEid = [01 00 00 00] - as_stmsi_t s_tmsi - U8 MMEcode = [00] - U32 m_tmsi = [00 00 00 00] - - U32 Length = [00 00 00 0a] (10 octets) - NAS message = [27 ab ab ab ab 00 62 02 cd 24] - - U8:4 Security header type = [2] - Integrity protected and ciphered - U8:4 Protocol discriminator = [7] - EMM message - U32 Message authentication code = [ab ab ab ab] - U8 Sequence number = [00] - Uplink counter value - - NAS message = [62 02 cd 24] - U8:4 EPS bearer identity = [6] - ebi = 6 - U8:4 Protocol discriminator = [2] - ESM message - U8 Procedure Transaction Identity = [02] - U8 ESM message identifier = [cd] - Deactivate EPS Bearer Context Request - - U8 ESM cause code = [24] - #36 REGULAR_DEACTIVATION -*/ - -/* - 04 08 01 00 00 00 00 00 00 00 -*/ -/* - U16 msgID = [04 08] - AS_NAS_ESTABLISH_CNF - U8 errCode = [01] - SUCCESS - U32 Length = [00 00 00 00] (0 octets) -*/ - - -/* - 07 01 01 00 00 00 00 00 00 00 00 00 00 00 0e 00 - 00 00 27 ab ab ab ab 00 72 00 c5 06 01 02 01 00 -*/ -/* - U16 msgID = [07 01] - AS_DL_INFO_TRANSFER_REQ - U32 UEid = [01 00 00 00] - as_stmsi_t s_tmsi - U8 MMEcode = [00] - U32 m_tmsi = [00 00 00 00] - - U32 Length = [00 00 00 0e] (14 octets) - NAS message = [27 ab ab ab ab 00 72 00 c5 06 01 02 01 00] - - U8:4 Security header type = [2] - Integrity protected and ciphered - U8:4 Protocol discriminator = [7] - EMM message - U32 Message authentication code = [ab ab ab ab] - U8 Sequence number = [00] - Uplink counter value - - NAS message = [72 00 c5 06 00 00 00 00] - U8:4 EPS bearer identity = [7] - ebi = 7 - U8:4 Protocol discriminator = [2] - ESM message - U8 Procedure Transaction Identity - Unassigned - U8 ESM message identifier = [c5] - Activate dedicated EPS Bearer Context Request - - U8:4 Spare half octet = [0] - U8:4 Linked EPS bearer identity = [6] - U8 QoS length = [01] - U8 QCI = [02] - U8 TFT length = [01] - U8 TFT = [00] -*/ - -/* - 07 04 00 00 00 00 36 00 00 00 27 ab ab ab ab 00 - 72 00 c5 06 01 02 29 22 11 02 11 10 c0 a8 0c 01 - ff ff ff 00 30 11 40 27 11 50 2e e1 22 03 11 10 - c0 a8 0c 01 ff ff ff 00 30 11 40 27 12 50 2e e2 -*/ -/* - U16 msgID = [07 04] - AS_DL_INFO_TRANSFER_IND - U32 UEid = [00 00 00 00] - - U32 Length = [36 00 00 00] (54 octets) - U8* NasMsg = [27 ab ab ab ab 00 72 00 c5 06 01 02 29 22 11 02] - [11 10 c0 a8 0c 01 ff ff ff 00 30 11 40 27 11 50] - [2e e1 22 03 11 10 c0 a8 0c 01 ff ff ff 00 30 11] - [40 27 12 50 2e e2] - - U8:4 Security header type = [2] - Integrity protected and ciphered - U8:4 Protocol discriminator = [7] - EMM message - U32 Message authentication code = [ab ab ab ab] - U8 Sequence number = [00] - 0 - - NAS message = [72 00 c5 06 01 02 29 22 11 02 11 10 c0 a8 0c 01] - [ff ff ff 00 30 11 40 27 11 50 2e e1 22 03 11 10] - [c0 a8 0c 01 ff ff ff 00 30 11 40 27 12 50 2e e2] - U8:4 EPS bearer identity = [7] - ebi = 7 - U8:4 Protocol discriminator = [2] - ESM message - U8 Procedure Transaction Identity - Unassigned - U8 ESM message identifier = [c5] - Activate dedicated EPS Bearer Context Request - - U8:4 Spare half octet = [0] - U8:4 Linked EPS bearer identity = [6] - U8 QoS length = [01] - 1 octet - U8 QCI = [02] - U8 TFT length = [29] - 41 octets - U8 TFT = [22 11 02 11 10 c0 a8 0c 01 ff ff ff 00 30 11 40] - [27 11 50 2e e1 22 03 11 10 c0 a8 0c 01 ff ff ff] - [00 30 11 40 27 12 50 2e e2] -*/ - -/* - 06 01 00 00 00 00 12 00 00 00 01 00 00 00 0a 00 - 00 00 27 ab ab ab ab 00 72 00 c7 2d -*/ -/* - U16 msgID = [06 01] - AS_UL_INFO_TRANSFER_REQ - U32 UEid = [00 00 00 00] - as_stmsi_t s_tmsi - U8 MMEcode = [12] - U32 m_tmsi = [00 00 00 01] - - U32 Length = [00 00 00 0a] (10 octets) - U8* NasMsg = [27 ab ab ab ab 00 72 00 c7 2d] - - U8:4 Security header type = [2] - Integrity protected and ciphered - U8:4 Protocol discriminator = [7] - EMM message - U32 Message authentication code = [ab ab ab ab] - U8 Sequence number = [00] - Uplink counter value - - NAS message = [72 00 c7 2d] - U8:4 EPS bearer identity = [7] - 7 - U8:4 Protocol discriminator = [2] - ESM message - U8 Procedure Transaction Identity = [00] - U8 ESM message identifier = [c7] - Activate Dedicated EPS Bearer Context - Reject - - U8 ESM cause code = [2d] - SYNTACTICAL_ERROR_IN_PACKET_FILTER -*/ - -/* - 06 01 00 00 00 00 12 00 00 00 01 00 00 00 09 00 - 00 00 27 ab ab ab ab 00 72 00 c6 -*/ -/* - U16 msgID = [06 01] - AS_UL_INFO_TRANSFER_REQ - U32 UEid = [00 00 00 00] - as_stmsi_t s_tmsi - U8 MMEcode = [12] - U32 m_tmsi = [00 00 00 01] - - U32 Length = [00 00 00 09] (9 octets) - U8* NasMsg = [27 ab ab ab ab 00 72 00 c6] - - U8:4 Security header type = [2] - Integrity protected and ciphered - U8:4 Protocol discriminator = [7] - EMM message - U32 Message authentication code = [ab ab ab ab] - U8 Sequence number = [00] - Uplink counter value - - NAS message = [72 00 c6] - U8:4 EPS bearer identity = [7] - 7 - U8:4 Protocol discriminator = [2] - ESM message - U8 Procedure Transaction Identity = [00] - U8 ESM message identifier = [c6] - Activate Dedicated EPS Bearer Context - Accept -*/ - -/* - 06 01 00 00 00 00 12 00 00 00 01 00 00 00 15 00 - 00 00 27 ab ab ab ab 00 07 45 01 0b f6 02 f8 01 - 01 02 12 00 00 00 01 -*/ -/* - U16 msgID = [06 01] - AS_UL_INFO_TRANSFER_REQ - U32 UEid = [00 00 00 00] - as_stmsi_t s_tmsi - U8 MMEcode = [12] - U32 m_tmsi = [00 00 00 01] - - U32 Length = [00 00 00 15] (21 octets) - U8* NasMsg = [27 ab ab ab ab 00 07 45 01 0b f6 02 f8 01 01 02] - [12 00 00 00 01] - - U8:4 Security header type = [2] - Integrity protected and ciphered - U8:4 Protocol discriminator = [7] - EMM message - U32 Message authentication code = [ab ab ab ab] - U8 Sequence number = [00] - Uplink counter value - - NAS message = [07 45 01 0b f6 02 f8 01 01 02 12 00 00 00 01] - U8:4 Security header type = [0] - Not protected - U8:4 Protocol discriminator = [7] - EMM message - U8 EMM message identifier = [45] - Detach Request - - U8:4 NAS key set identifier = [0] - Native 0 - U8:4 Detach type = [1] - EPS Detach - - Mobile identity = [0b f6 02 f8 01 01 02 12 00 00 00 01] - Length = [0b] - 11 octets - U8:4 = 1111 = [f] - U8:1 odd/even indicator = [0] - even number of identity digits - U8:3 Type of identity = [110] - GUTI - plmn = [02 f8 01] - 20810 - U16 mmegroupid = [01 02] - U8 mmecode = [12] - U32 mtmsi = [00 00 00 01] -*/ diff --git a/openair3/NAS/TEST/NETWORK/network_simulator.c b/openair3/NAS/TEST/NETWORK/network_simulator.c index 492a709463..a09c0a0a69 100644 --- a/openair3/NAS/TEST/NETWORK/network_simulator.c +++ b/openair3/NAS/TEST/NETWORK/network_simulator.c @@ -228,7 +228,7 @@ static int _process_activate_default_eps_bearer_context_accept(const activate_de static int _process_activate_default_eps_bearer_context_reject(const activate_default_eps_bearer_context_reject_msg* msg); static int _process_deactivate_eps_bearer_context_accept(const deactivate_eps_bearer_context_accept_msg* msg); -static void _dump_buffer(const Byte_t* buffer, size_t len) +static void _dump_buffer(const uint8_t* buffer, size_t len) { for (int i = 0; i < len; i++) { if ( (i%16) == 0 ) printf("\n\t"); @@ -538,7 +538,7 @@ static int _process_establish_req(const nas_establish_req_t* req, if (bytes > 0) { /* Setup signalling connection establishment confirm message */ rsp->errCode = AS_SUCCESS; - rsp->nasMsg.data = (Byte_t*)malloc(bytes * sizeof(Byte_t)); + rsp->nasMsg.data = malloc(bytes * sizeof(uint8_t)); if (rsp->nasMsg.data) { rsp->nasMsg.length = bytes; @@ -618,7 +618,7 @@ static int _process_ul_info_transfer_req(const ul_info_transfer_req_t* req, return (AS_UL_INFO_TRANSFER_CNF); } else if (bytes > 0) { /* Some data has to be sent back to the UE */ - ind->nasMsg.data = (Byte_t*)malloc(bytes * sizeof(Byte_t)); + ind->nasMsg.data = malloc(bytes * sizeof(uint8_t)); if (ind->nasMsg.data) { ind->nasMsg.length = bytes; @@ -1258,12 +1258,12 @@ static int _assign_pdn_address(int ue_pdn_type, int is_initial, int* pdn_type, O U8 cause = [04] - NET_ESTABLISH_CAUSE_MO_SIGNAL U8 type = [10] - NET_ESTABLISH_TYPE_ORIGINATING_SIGNAL plmn_t plmnID = [20 8f 10] - Byte_t MCCdigit2:4 = [0] - Byte_t MCCdigit1:4 = [2] - Byte_t MNCdigit3:4 = [f] - Byte_t MCCdigit3:4 = [8] - Byte_t MNCdigit2:4 = [0] - Byte_t MNCdigit1:4 = [1] + uint8_t MCCdigit2:4 = [0] + uint8_t MCCdigit1:4 = [2] + uint8_t MNCdigit3:4 = [f] + uint8_t MCCdigit3:4 = [8] + uint8_t MNCdigit2:4 = [0] + uint8_t MNCdigit1:4 = [1] as_stmsi_t s_tmsi U8 MMEcode = [0f] U32 m_tmsi = [00 00 00 01] diff --git a/openair3/NAS/UE/API/CMakeLists.txt b/openair3/NAS/UE/API/CMakeLists.txt new file mode 100644 index 0000000000..0810099d9e --- /dev/null +++ b/openair3/NAS/UE/API/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(USIM) diff --git a/openair3/NAS/UE/API/USIM/CMakeLists.txt b/openair3/NAS/UE/API/USIM/CMakeLists.txt new file mode 100644 index 0000000000..90a9cb40fe --- /dev/null +++ b/openair3/NAS/UE/API/USIM/CMakeLists.txt @@ -0,0 +1,9 @@ +add_library(usim_lib OBJECT + ${OPENAIR_DIR}/common/utils/mem/memory.c + aka_functions.c + usim_api.c +) + +target_include_directories(usim_lib PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} +) diff --git a/openair3/NAS/UE/API/USIM/usim_api.h b/openair3/NAS/UE/API/USIM/usim_api.h index f332b5ffc8..e1b379c050 100644 --- a/openair3/NAS/UE/API/USIM/usim_api.h +++ b/openair3/NAS/UE/API/USIM/usim_api.h @@ -73,7 +73,12 @@ Description Implements the API used by the NAS layer to read/write * USIM TLV parameter structure * ---------------------------- */ -#define USIM_TLV_T(SIZE) struct {uint8_t type; uint8_t length; Byte_t value[SIZE];} +#define USIM_TLV_T(SIZE) \ + struct { \ + uint8_t type; \ + uint8_t length; \ + uint8_t value[SIZE]; \ + } /* * Non Access Stratum Configuration @@ -116,13 +121,13 @@ typedef struct { #define USIM_KSI_MIN 0b000 #define USIM_KSI_MAX 0b110 #define USIM_KSI_NOT_AVAILABLE 0b111 - Byte_t ksi; + uint8_t ksi; /* Cyphering key */ #define USIM_CK_SIZE 16 - Byte_t ck[USIM_CK_SIZE]; + uint8_t ck[USIM_CK_SIZE]; /* Integrity key */ #define USIM_IK_SIZE 16 - Byte_t ik[USIM_IK_SIZE]; + uint8_t ik[USIM_IK_SIZE]; uint8_t usim_api_k[USIM_API_K_SIZE]; uint8_t opc[16]; } usim_keys_t; @@ -195,10 +200,10 @@ typedef struct { * ---------------------------- */ typedef struct { - Byte_t length; /* Length of BCD number/SSC contents */ + uint8_t length; /* Length of BCD number/SSC contents */ msisdn_t number; /* Mobile subscriber dialing number */ - Byte_t conf1_record_id; /* Configuration1 Record Identifier */ - Byte_t ext1_record_id; /* Extension1 Record Identifier */ + uint8_t conf1_record_id; /* Configuration1 Record Identifier */ + uint8_t ext1_record_id; /* Extension1 Record Identifier */ } usim_msisdn_t; /* @@ -251,12 +256,12 @@ typedef struct { typedef struct { uint32_t tmsi; /* Temporary Mobile Subscriber Identity */ lai_t lai; /* Location Area Identity */ - Byte_t reserved; /* Reserved for future use */ + uint8_t reserved; /* Reserved for future use */ #define USIM_LOCI_UPDATED 0x00 #define USIM_LOCI_NOT_UPDATED 0x01 #define USIM_LOCI_PLMN_NOT_ALLOWED 0x02 #define USIM_LOCI_LA_NOT_ALLOWED 0x03 - Byte_t status; /* Location update status */ + uint8_t status; /* Location update status */ } usim_loci_t; /* @@ -265,13 +270,13 @@ typedef struct { */ typedef struct { uint32_t p_tmsi; /* Packet Temporary Mobile Subscriber Identity */ - Byte_t signature[3]; /* P-TMSI signature value */ + uint8_t signature[3]; /* P-TMSI signature value */ RAI_t rai; /* Routing Area Identity */ #define USIM_PSLOCI_UPDATED 0x00 #define USIM_PSLOCI_NOT_UPDATED 0x01 #define USIM_PSLOCI_PLMN_NOT_ALLOWED 0x02 #define USIM_PSLOCI_LA_NOT_ALLOWED 0x03 - Byte_t status; /* Routing Area update status */ + uint8_t status; /* Routing Area update status */ } usim_psloci_t; /* @@ -284,7 +289,7 @@ typedef struct { #define USIM_EPSLOCI_UPDATED 0x00 #define USIM_EPSLOCI_NOT_UPDATED 0x01 #define USIM_EPSLOCI_ROAMING_NOT_ALLOWED 0x02 - Byte_t status; /* EPS update status */ + uint8_t status; /* EPS update status */ } usim_epsloci_t; /* @@ -308,11 +313,11 @@ typedef struct { #define USIM_TYPE_APPROVAL_SPECIFIC_MODE 0x81U #define USIM_MAINTENANCE_MODE 0x02U #define USIM_CELL_TEST_MODE 0x04U - Byte_t UE_Operation_Mode; /* Mode of operation for the UE */ + uint8_t UE_Operation_Mode; /* Mode of operation for the UE */ uint16_t Additional_Info; /* Additional information depending on * the UE operation mode */ - Byte_t MNC_Length; /* Number of digits used for extracting - * the MNC from the IMSI */ + uint8_t MNC_Length; /* Number of digits used for extracting + * the MNC from the IMSI */ } usim_ad_t; /* @@ -328,7 +333,7 @@ typedef struct { */ imsi_t imsi; /* International Mobile Subscriber Identity */ usim_keys_t keys; /* Ciphering and Integrity Keys */ - Byte_t hpplmn; /* Higher Priority PLMN search period */ + uint8_t hpplmn; /* Higher Priority PLMN search period */ #define USIM_FPLMN_MAX 4 plmn_t fplmn[USIM_FPLMN_MAX]; /* List of Forbidden PLMNs */ usim_loci_t loci; /* Location Information */ diff --git a/openair3/NAS/UE/CMakeLists.txt b/openair3/NAS/UE/CMakeLists.txt new file mode 100644 index 0000000000..01e40a3c9e --- /dev/null +++ b/openair3/NAS/UE/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(API) diff --git a/openair3/NAS/UE/EMM/SAP/emm_as.c b/openair3/NAS/UE/EMM/SAP/emm_as.c index 1c7ba03f70..32353fa969 100644 --- a/openair3/NAS/UE/EMM/SAP/emm_as.c +++ b/openair3/NAS/UE/EMM/SAP/emm_as.c @@ -837,7 +837,7 @@ _emm_as_encode( } /* Allocate memory to the NAS information container */ - info->nas_data = malloc(length * sizeof(Byte_t)); + info->nas_data = malloc(length * sizeof(uint8_t)); if (info->nas_data != NULL) { /* Encode the NAS message */ @@ -889,7 +889,7 @@ _emm_as_encrypt( } /* Allocate memory to the NAS information container */ - info->nas_data = malloc(length * sizeof(Byte_t)); + info->nas_data = malloc(length * sizeof(uint8_t)); if (info->nas_data != NULL) { /* Encrypt the NAS information message */ diff --git a/openair3/NAS/UE/EMM/SAP/emm_asDef.h b/openair3/NAS/UE/EMM/SAP/emm_asDef.h index 4f6182a2c9..531b3e5a69 100644 --- a/openair3/NAS/UE/EMM/SAP/emm_asDef.h +++ b/openair3/NAS/UE/EMM/SAP/emm_asDef.h @@ -229,7 +229,7 @@ typedef struct emm_as_cell_info_s { #define EMM_AS_PLMN_LIST_SIZE 6 PLMN_LIST_T(EMM_AS_PLMN_LIST_SIZE) plmnIDs; /* List of identifiers of available PLMNs */ - Byte_t rat; /* Bitmap of Radio Access Technologies */ + uint8_t rat; /* Bitmap of Radio Access Technologies */ tac_t tac; /* Tracking Area Code */ ci_t cellID; /* cell identity */ } emm_as_cell_info_t; diff --git a/openair3/NAS/UE/EMM/emmData.h b/openair3/NAS/UE/EMM/emmData.h index d90820edf9..37f407fec4 100644 --- a/openair3/NAS/UE/EMM/emmData.h +++ b/openair3/NAS/UE/EMM/emmData.h @@ -345,12 +345,12 @@ typedef struct emm_data_s { * ---------------------------- * see "Non Access Stratum Configuration" in USIM API header file */ - Byte_t NAS_SignallingPriority; - Byte_t NMO_I_Behaviour; - Byte_t AttachWithImsi; - Byte_t MinimumPeriodicSearchTimer; - Byte_t ExtendedAccessBarring; - Byte_t Timer_T3245_Behaviour; + uint8_t NAS_SignallingPriority; + uint8_t NMO_I_Behaviour; + uint8_t AttachWithImsi; + uint8_t MinimumPeriodicSearchTimer; + uint8_t ExtendedAccessBarring; + uint8_t Timer_T3245_Behaviour; /* * EMM data stored in the UE's memory diff --git a/openair3/NAS/UE/nas_itti_messaging.c b/openair3/NAS/UE/nas_itti_messaging.c index 6f64413b70..9a83314352 100644 --- a/openair3/NAS/UE/nas_itti_messaging.c +++ b/openair3/NAS/UE/nas_itti_messaging.c @@ -95,14 +95,16 @@ int nas_itti_protected_msg(const char *buffer, const nas_message_t *msg, const i } #endif -int nas_itti_kenb_refresh_req(const Byte_t kenb[32], int user_id) { +int nas_itti_kenb_refresh_req(const uint8_t kenb[32], int user_id) +{ MessageDef *message_p; message_p = itti_alloc_new_message(TASK_NAS_UE, 0, NAS_KENB_REFRESH_REQ); memcpy(NAS_KENB_REFRESH_REQ(message_p).kenb, kenb, sizeof(NAS_KENB_REFRESH_REQ(message_p).kenb)); return itti_send_msg_to_task(TASK_RRC_UE, NB_eNB_INST + user_id, message_p); } -int nas_itti_cell_info_req(const plmn_t plmnID, const Byte_t rat, int user_id) { +int nas_itti_cell_info_req(const plmn_t plmnID, const uint8_t rat, int user_id) +{ MessageDef *message_p; message_p = itti_alloc_new_message(TASK_NAS_UE, 0, NAS_CELL_SELECTION_REQ); NAS_CELL_SELECTION_REQ(message_p).plmnID = plmnID; @@ -110,7 +112,14 @@ int nas_itti_cell_info_req(const plmn_t plmnID, const Byte_t rat, int user_id) { return itti_send_msg_to_task(TASK_RRC_UE, NB_eNB_INST + user_id, message_p); } -int nas_itti_nas_establish_req(as_cause_t cause, as_call_type_t type, as_stmsi_t s_tmsi, plmn_t plmnID, Byte_t *data, uint32_t length, int user_id) { +int nas_itti_nas_establish_req(as_cause_t cause, + as_call_type_t type, + as_stmsi_t s_tmsi, + plmn_t plmnID, + uint8_t *data, + uint32_t length, + int user_id) +{ MessageDef *message_p; message_p = itti_alloc_new_message(TASK_NAS_UE, 0, NAS_CONN_ESTABLI_REQ); NAS_CONN_ESTABLI_REQ(message_p).cause = cause; diff --git a/openair3/NAS/UE/nas_itti_messaging.h b/openair3/NAS/UE/nas_itti_messaging.h index 7fdda32960..96cf1df60a 100644 --- a/openair3/NAS/UE/nas_itti_messaging.h +++ b/openair3/NAS/UE/nas_itti_messaging.h @@ -38,11 +38,17 @@ int nas_itti_plain_msg( int nas_itti_protected_msg(const char *buffer, const nas_message_t *msg, const int lengthP, const int instance); -int nas_itti_kenb_refresh_req(const Byte_t kenb[32], int user_id); +int nas_itti_kenb_refresh_req(const uint8_t kenb[32], int user_id); -int nas_itti_cell_info_req(const plmn_t plmnID, const Byte_t rat, int user_id); +int nas_itti_cell_info_req(const plmn_t plmnID, const uint8_t rat, int user_id); -int nas_itti_nas_establish_req(as_cause_t cause, as_call_type_t type, as_stmsi_t s_tmsi, plmn_t plmnID, Byte_t *data_pP, uint32_t lengthP, int user_id); +int nas_itti_nas_establish_req(as_cause_t cause, + as_call_type_t type, + as_stmsi_t s_tmsi, + plmn_t plmnID, + uint8_t *data_pP, + uint32_t lengthP, + int user_id); int nas_itti_ul_data_req(const uint32_t ue_idP, void *const data_pP, const uint32_t lengthP, int user_id); diff --git a/openair3/NAS/UE/nas_proc.c b/openair3/NAS/UE/nas_proc.c index 65b531342a..3fdef5ce73 100644 --- a/openair3/NAS/UE/nas_proc.c +++ b/openair3/NAS/UE/nas_proc.c @@ -311,11 +311,11 @@ int nas_proc_get_msisdn(nas_user_t *user, char *msisdn_str, int *ton_npi) if (msisdn != NULL) { union { struct { - Byte_t ext:1; - Byte_t ton:3; - Byte_t npi:4; + uint8_t ext: 1; + uint8_t ton: 3; + uint8_t npi: 4; } ext_ton_npi; - Byte_t type; + uint8_t type; } converter; converter.ext_ton_npi.ext = msisdn->ext; converter.ext_ton_npi.ton = msisdn->ton; @@ -1058,7 +1058,7 @@ int nas_proc_cell_info(nas_user_t *user, int found, tac_t tac, ci_t ci, AcT_t Ac ** Others: None ** ** ** ***************************************************************************/ -int nas_proc_establish_cnf(nas_user_t *user, const Byte_t *data, uint32_t len) +int nas_proc_establish_cnf(nas_user_t *user, const uint8_t *data, uint32_t len) { LOG_FUNC_IN; @@ -1236,7 +1236,7 @@ int nas_proc_ul_transfer_rej(nas_user_t *user) ** Others: None ** ** ** ***************************************************************************/ -int nas_proc_dl_transfer_ind(nas_user_t *user, const Byte_t *data, uint32_t len) +int nas_proc_dl_transfer_ind(nas_user_t *user, const uint8_t *data, uint32_t len) { LOG_FUNC_IN; diff --git a/openair3/NAS/UE/nas_proc.h b/openair3/NAS/UE/nas_proc.h index 1f8a88d46d..ec2a2ce2d6 100644 --- a/openair3/NAS/UE/nas_proc.h +++ b/openair3/NAS/UE/nas_proc.h @@ -113,15 +113,13 @@ int nas_proc_activate_pdn(nas_user_t *user, int cid); */ int nas_proc_cell_info(nas_user_t *user, int found, tac_t tac, ci_t ci, AcT_t AcT, uint8_t rsrq, uint8_t rsrp); -int nas_proc_establish_cnf(nas_user_t *user, const Byte_t *data, uint32_t len); +int nas_proc_establish_cnf(nas_user_t *user, const uint8_t *data, uint32_t len); int nas_proc_establish_rej(nas_user_t *user); int nas_proc_release_ind(nas_user_t *user, int cause); int nas_proc_ul_transfer_cnf(nas_user_t *user); int nas_proc_ul_transfer_rej(nas_user_t *user); -int nas_proc_dl_transfer_ind(nas_user_t *user, const Byte_t *data, uint32_t len); - - +int nas_proc_dl_transfer_ind(nas_user_t *user, const uint8_t *data, uint32_t len); #endif /* __NAS_PROC_H__*/ diff --git a/openair3/UICC/CMakeLists.txt b/openair3/UICC/CMakeLists.txt new file mode 100644 index 0000000000..0570c7238f --- /dev/null +++ b/openair3/UICC/CMakeLists.txt @@ -0,0 +1,2 @@ +add_library(lib_uicc OBJECT usim_interface.c) +target_include_directories(lib_uicc PRIVATE .) diff --git a/radio/fhi_72/oaioran.c b/radio/fhi_72/oaioran.c index 35c0356005..b7cce2964b 100644 --- a/radio/fhi_72/oaioran.c +++ b/radio/fhi_72/oaioran.c @@ -78,12 +78,15 @@ void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status) static int32_t last_slot = -1; static int32_t last_frame = -1; + + /* xran context contains the same xran_fh_init struct info, + but xran_fh_config struct info is RU specific only */ struct xran_device_ctx *xran_ctx = xran_dev_get_ctx(); const struct xran_fh_init *fh_init = &xran_ctx->fh_init; int num_ports = fh_init->xran_ports; - const struct xran_fh_config *fh_config = &xran_ctx->fh_cfg; - const int slots_per_subframe = 1 << fh_config->frame_conf.nNumerology; + /* assuming all RUs have the same numerology */ + const int slots_per_subframe = 1 << xran_ctx->fh_cfg.frame_conf.nNumerology; static int rx_RU[XRAN_PORTS_NUM][160] = {0}; uint32_t rx_tti = callback_tag->slotiId; @@ -103,17 +106,20 @@ void oai_xran_fh_rx_callback(void *pCallbackTag, xran_status_t status) ru_id); if (rx_sym == 7) { // in F release this value is defined as XRAN_FULL_CB_SYM (full slot (offset + 7)) #ifdef F_RELEASE - int32_t nCellIdx = callback_tag->cellId; - int32_t ntti = (rx_tti + XRAN_N_FE_BUF_LEN - 1) % XRAN_N_FE_BUF_LEN; + for (int ru_idx = 0; ru_idx < num_ports; ru_idx++) { + struct xran_device_ctx *xran_ctx_per_ru = xran_dev_get_ctx_by_id(ru_idx); + struct xran_fh_config *fh_config = &xran_ctx_per_ru->fh_cfg; + for (uint16_t cc_id = 0; cc_id < 1 /* fh_config->nCC */; cc_id++) { // OAI does not support multiple CC yet. + for(uint32_t ant_id = 0; ant_id < fh_config->neAxc; ant_id++) { + struct xran_prb_map *pRbMap = (struct xran_prb_map *)xran_ctx_per_ru->sFrontHaulRxPrbMapBbuIoBufCtrl[tti % XRAN_N_FE_BUF_LEN][cc_id][ant_id].sBufferList.pBuffers->pData; + AssertFatal(pRbMap != NULL, "(%d:%d:%d)pRbMap == NULL. Aborting.\n", cc_id, tti % XRAN_N_FE_BUF_LEN, ant_id); - for(uint32_t ant_id = 0; ant_id < fh_config->neAxc; ant_id++) { - struct xran_prb_map *pRbMap = (struct xran_prb_map *)xran_ctx->sFrontHaulRxPrbMapBbuIoBufCtrl[ntti][nCellIdx][ant_id].sBufferList.pBuffers->pData; - AssertFatal(pRbMap != NULL, "(%d:%d:%d)pRbMap == NULL. Aborting.\n", nCellIdx, ntti, ant_id); - - for (uint32_t sym_id = 0; sym_id < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_id++) { - for (uint32_t idxElm = 0; idxElm < pRbMap->nPrbElm; idxElm++ ) { - struct xran_prb_elm *pRbElm = &pRbMap->prbMap[idxElm]; - pRbElm->nSecDesc[sym_id] = 0; // number of section descriptors per symbol; M-plane info + for (uint32_t sym_id = 0; sym_id < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_id++) { + for (uint32_t idxElm = 0; idxElm < pRbMap->nPrbElm; idxElm++ ) { + struct xran_prb_elm *pRbElm = &pRbMap->prbMap[idxElm]; + pRbElm->nSecDesc[sym_id] = 0; // number of section descriptors per symbol; M-plane info + } + } } } } @@ -230,16 +236,12 @@ int read_prach_data(ru_info_t *ru, int frame, int slot) } } } else if (ru_conf->compMeth_PRACH == XRAN_COMPMETHOD_BLKFLOAT) { - struct xranlib_decompress_request bfp_decom_req; - struct xranlib_decompress_response bfp_decom_rsp; + struct xranlib_decompress_request bfp_decom_req = {}; + struct xranlib_decompress_response bfp_decom_rsp = {}; int16_t local_dst[12 * 2 * N_SC_PER_PRB] __attribute__((aligned(64))); int payload_len = (3 * ru_conf->iqWidth_PRACH + 1) * 12; // 12 = closest number of PRBs to 139 REs - - memset(&bfp_decom_req, 0, sizeof(struct xranlib_decompress_request)); - memset(&bfp_decom_rsp, 0, sizeof(struct xranlib_decompress_response)); - bfp_decom_req.data_in = (int8_t *)src; bfp_decom_req.numRBs = 12; // closest number of PRBs to 139 REs bfp_decom_req.len = payload_len; @@ -415,14 +417,10 @@ int xran_fh_rx_read_slot(ru_info_t *ru, int *frame, int *slot) memcpy((void *)dst2, (void *)local_dst, neg_len * 4); memcpy((void *)dst1, (void *)&local_dst[neg_len], pos_len * 4); } else if (pRbElm->compMethod == XRAN_COMPMETHOD_BLKFLOAT) { - struct xranlib_decompress_request bfp_decom_req; - struct xranlib_decompress_response bfp_decom_rsp; + struct xranlib_decompress_request bfp_decom_req = {}; + struct xranlib_decompress_response bfp_decom_rsp = {}; payload_len = (3 * pRbElm->iqWidth + 1) * pRbElm->nRBSize; - - memset(&bfp_decom_req, 0, sizeof(struct xranlib_decompress_request)); - memset(&bfp_decom_rsp, 0, sizeof(struct xranlib_decompress_response)); - bfp_decom_req.data_in = (int8_t *)src; bfp_decom_req.numRBs = pRbElm->nRBSize; bfp_decom_req.len = payload_len; @@ -556,12 +554,9 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp) for (idx = 0; idx < (pos_len + neg_len) * 2; idx++) ((uint16_t *)dst16)[idx] = htons(((uint16_t *)local_src)[idx]); } else if (p_prbMapElm->compMethod == XRAN_COMPMETHOD_BLKFLOAT) { - struct xranlib_compress_request bfp_com_req; - struct xranlib_compress_response bfp_com_rsp; + struct xranlib_compress_request bfp_com_req = {}; + struct xranlib_compress_response bfp_com_rsp = {}; payload_len = (3 * p_prbMapElm->iqWidth + 1) * p_prbMapElm->nRBSize; - memset(&bfp_com_req, 0, sizeof(struct xranlib_compress_request)); - memset(&bfp_com_rsp, 0, sizeof(struct xranlib_compress_response)); - bfp_com_req.data_in = (int16_t *)local_src; bfp_com_req.numRBs = p_prbMapElm->nRBSize; bfp_com_req.len = payload_len; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.2pattern.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.2pattern.conf new file mode 100644 index 0000000000..89a1bb23c6 --- /dev/null +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.2pattern.conf @@ -0,0 +1,247 @@ +Active_gNBs = ( "gNB-OAI" ); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +gNBs = +( +{ + ////////// Identification parameters: + gNB_ID = 0xe00; + gNB_name = "gNB-OAI"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = 1; + plmn_list = ({ mcc = 001; mnc = 01; mnc_length = 2; snssaiList = ({ sst = 1; sd = 1; }) }); + + nr_cellid = 12345678L; + + ////////// Physical parameters: + do_CSIRS = 1; + do_SRS = 1; + + servingCellConfigCommon = ( + { + # spCellConfigCommon + physCellId = 0; + + # downlinkConfigCommon + # frequencyInfoDL + # this is 3600 MHz + 43 PRBs@30kHz SCS (same as initial BWP) + absoluteFrequencySSB = 641280; + dl_frequencyBand = 78; + # this is 3600 MHz + dl_absoluteFrequencyPointA = 640008; + # scs-SpecificCarrierList + dl_offstToCarrier = 0; + # subcarrierSpacing + # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + dl_subcarrierSpacing = 1; + dl_carrierBandwidth = 106; + # initialDownlinkBWP + # genericParameters + # this is RBstart=27,L=48 (275*(L-1))+RBstart + initialDLBWPlocationAndBandwidth = 28875; + # subcarrierSpacing + # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialDLBWPsubcarrierSpacing = 1; + # pdcch-ConfigCommon + initialDLBWPcontrolResourceSetZero = 12; + initialDLBWPsearchSpaceZero = 0; + + # uplinkConfigCommon + # frequencyInfoUL + ul_frequencyBand = 78; + # scs-SpecificCarrierList + ul_offstToCarrier = 0; + # subcarrierSpacing + # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + ul_subcarrierSpacing = 1; + ul_carrierBandwidth = 106; + pMax = 20; + # initialUplinkBWP + # genericParameters + initialULBWPlocationAndBandwidth = 28875; + # subcarrierSpacing + # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + initialULBWPsubcarrierSpacing = 1; + # rach-ConfigCommon + # rach-ConfigGeneric + prach_ConfigurationIndex = 154; + # prach_msg1_FDM + # 0 = one, 1=two, 2=four, 3=eight + prach_msg1_FDM = 0; + prach_msg1_FrequencyStart = 0; + zeroCorrelationZoneConfig = 13; + preambleReceivedTargetPower = -96; + # preamblTransMax (0...10) = (3,4,5,6,7,8,10,20,50,100,200) + preambleTransMax = 6; + # powerRampingStep + # 0=dB0,1=dB2,2=dB4,3=dB6 + powerRampingStep = 1; + # ra_ReponseWindow + # 1,2,4,8,10,20,40,80 + ra_ResponseWindow = 4; + # ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR + # 1=oneeighth,2=onefourth,3=half,4=one,5=two,6=four,7=eight,8=sixteen + ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR = 4; + # one (0..15) 4,8,12,16,...60,64 + ssb_perRACH_OccasionAndCB_PreamblesPerSSB = 14; + # ra_ContentionResolutionTimer + # (0..7) 8,16,24,32,40,48,56,64 + ra_ContentionResolutionTimer = 7; + rsrp_ThresholdSSB = 19; + # prach-RootSequenceIndex_PR + # 1 = 839, 2 = 139 + prach_RootSequenceIndex_PR = 2; + prach_RootSequenceIndex = 1; + # SCS for msg1, can only be 15 for 30 kHz < 6 GHz, takes precedence over the one derived from prach-ConfigIndex + msg1_SubcarrierSpacing = 1; + # restrictedSetConfig + # 0=unrestricted, 1=restricted type A, 2=restricted type B + restrictedSetConfig = 0; + msg3_DeltaPreamble = 1; + p0_NominalWithGrant = -90; + + # pucch-ConfigCommon setup : + # pucchGroupHopping + # 0 = neither, 1= group hopping, 2=sequence hopping + pucchGroupHopping = 0; + hoppingId = 40; + p0_nominal = -90; + + # ssb_PositionsInBurs_BitmapPR + # 1=short, 2=medium, 3=long + ssb_PositionsInBurst_PR = 2; + ssb_PositionsInBurst_Bitmap = 1; + + # ssb_periodicityServingCell + # 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1 + ssb_periodicityServingCell = 2; + + # dmrs_TypeA_position + # 0 = pos2, 1 = pos3 + dmrs_TypeA_Position = 0; + + # subcarrierSpacing + # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + subcarrierSpacing = 1; + + # tdd-UL-DL-ConfigurationCommon + # subcarrierSpacing + # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120 + referenceSubcarrierSpacing = 1; + + # pattern1 + # dl_UL_TransmissionPeriodicity + # 0=ms0p5, 1=ms0p625, 2=ms1, 3=ms1p25, 4=ms2, 5=ms2p5, 6=ms5, 7=ms10 + # ext: 8=ms3, 9=ms4 + dl_UL_TransmissionPeriodicity = 8; + nrofDownlinkSlots = 3; + nrofDownlinkSymbols = 6; + nrofUplinkSlots = 2; + nrofUplinkSymbols = 4; + + # pattern2 + pattern2: { + dl_UL_TransmissionPeriodicity2 = 4; + nrofDownlinkSlots2 = 4; + nrofDownlinkSymbols2 = 0; + nrofUplinkSlots2 = 0; + nrofUplinkSymbols2 = 0; + }; + + ssPBCH_BlockPower = -25; + }); + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + ////////// AMF parameters: + amf_ip_address = ({ ipv4 = "192.168.70.132"; }); + + NETWORK_INTERFACES: { + GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.70.129"; + GNB_IPV4_ADDRESS_FOR_NGU = "192.168.70.129"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; +} +); + +MACRLCs = ( +{ + num_cc = 1; + tr_s_preference = "local_L1"; + tr_n_preference = "local_RRC"; + pusch_TargetSNRx10 = 150; + pucch_TargetSNRx10 = 200; +} +); + +L1s = ( +{ + num_cc = 1; + tr_n_preference = "local_mac"; + prach_dtx_threshold = 120; + pucch0_dtx_threshold = 100; + ofdm_offset_divisor = 8; # set this to UINT_MAX for offset 0 +} +); + +RUs = ( +{ + local_rf = "yes"; + nb_tx = 1; + nb_rx = 1; + att_tx = 12; + att_rx = 12; + bands = [78]; + max_pdschReferenceSignalPower = -27; + max_rxgain = 114; + eNB_instances = [0]; + clock_src = "internal"; +} +); + +rfsimulator : +{ + serveraddr = "server"; + serverport = 4043; + options = (); # ("saviq"); or/and "chanmod" + modelname = "AWGN"; + IQfile = "/tmp/rfsimulator.iqs"; +}; + +security = { + # preferred ciphering algorithms + # the first one of the list that a UE supports is chosen + # valid values: nea0, nea1, nea2, nea3 + ciphering_algorithms = ( "nea0" ); + + # preferred integrity algorithms + # the first one of the list that a UE supports is chosen + # valid values: nia0, nia1, nia2, nia3 + integrity_algorithms = ( "nia2", "nia0" ); + + # setting 'drb_ciphering' to "no" disables ciphering for DRBs, no matter + # what 'ciphering_algorithms' configures; same thing for 'drb_integrity' + drb_ciphering = "yes"; + drb_integrity = "no"; +}; + +log_config : +{ + global_log_level = "info"; + hw_log_level = "info"; + phy_log_level = "info"; + mac_log_level = "info"; + rlc_log_level = "info"; + pdcp_log_level = "info"; + rrc_log_level = "info"; + ngap_log_level = "info"; + f1ap_log_level = "info"; +}; diff --git a/tools/docker-dev-env/Dockerfile b/tools/docker-dev-env/Dockerfile new file mode 100644 index 0000000000..fe4fdb53f6 --- /dev/null +++ b/tools/docker-dev-env/Dockerfile @@ -0,0 +1,41 @@ +FROM ran-base:latest +ARG USERNAME=root +ARG USER_UID=1000 +ARG USER_GID=1000 + +# More developer tools can be added here +RUN apt update && apt install -y vim sudo wget meson ninja-build libnuma-dev ccache + +# Create the user +RUN groupadd --gid $USER_GID $USERNAME \ + && useradd --uid $USER_UID --gid $USER_GID -m $USERNAME \ + && echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \ + && chmod 0440 /etc/sudoers.d/$USERNAME + +## Download and build DPDK +RUN cd /oai-ran && \ + wget http://fast.dpdk.org/rel/dpdk-20.11.9.tar.xz && \ + tar -xvf dpdk-20.11.9.tar.xz && \ + cd dpdk-stable-20.11.9 && \ + meson build && \ + ninja -C build && \ + ninja install -C build + +## Build Fronthaul library +COPY cmake_targets/tools/oran_fhi_integration_patches/F/oaioran_F.patch /oaioran_F.patch +RUN git clone https://gerrit.o-ran-sc.org/r/o-du/phy.git /opt/phy && \ + cd /opt/phy && \ + git checkout oran_f_release_v1.0 &&\ + git apply /oaioran_F.patch && \ + cd /opt/phy/fhi_lib/lib && \ + WIRELESS_SDK_TOOLCHAIN=gcc RTE_SDK=/oai-ran/dpdk-stable-20.11.9/ XRAN_DIR=/opt/phy/fhi_lib make XRAN_LIB_SO=1 +ENV xran_LOCATION=/opt/phy/fhi_lib/lib/ + +# This is a temporary solution to issue with apt: one of the installed packages creates a group that may +# not be present in the host: remove the group entry to allow apt usage in container +RUN dpkg-statoverride --remove /usr/bin/uml_net + +# Override ccache directory to avoid permission issues +ENV CCACHE_DIR=/home/$USERNAME/.cache/ccache-oai-dev-env + +USER $USERNAME diff --git a/tools/docker-dev-env/README.md b/tools/docker-dev-env/README.md new file mode 100644 index 0000000000..5dcb15eb5c --- /dev/null +++ b/tools/docker-dev-env/README.md @@ -0,0 +1,48 @@ +# Containerized development environment for OAI + +## Description + +This contains bash scripts for managing a ubuntu22 dockerized development enviroment for OAI. No need to install any +tools on host machines except for docker + + - `bootstrap.sh` - build development environment image and install the following bash aliases in `~/.bash_aliases`: + * `oai_start_dev_env` - start the development environment container and detach + * `oai_stop_dev_env` - stop the development environment container + * `oai_destroy_dev_env` - remove the container, deleting all data that is not on mapped volumes. All packages installed + using `apt` or other methods in system folders (e.g. `/usr/`) will be removed. + * `oai_enter_dev_env` - enter development environment + +## Installing + +Run `./bootstrap.sh`. This will build the `ran-base:latest` image if its not present on the system and +build the `openair-dev:$USER` image and install the aliases above. + +If not present, please add `source ~/.bash_aliases` into your `~/.bashrc`. + +## Assumptions + + - The `bootstrap.sh` script will read the current environment to generate the docker image, running + it with sudo is not recommended. + - Your home directory is shared with the home directory inside the docker container. + - You can use the `oai_enter_dev_env` alias to enter the container from any directory within + your home directory - your home directory is mapped directly in the container. If you + need other directories to be mapped, add extra volumes to the `docker-compose.yml` + +## Using sudo in container + +`sudo` is not necessary in the container as it should already have the linux capabilities that running +OAI requires. However it is still possible to run `sudo` in the container. + +## Updating and preserving your image + +Each image is personally tagged with username. You can update your image (e.g. install ubuntu system packages) +either through modifying the Dockerfile (not recommended) or installing packages manually through `apt` and +saving the docker container snapshot. If the environment is running just type + +``` +docker commit openair-dev-$USER openair-dev:$USER +``` + +This will update the image that is used in the aliases and preserve the modifications when you start the environment again. + +If you ever want to reset your image to the base prepared here just rerun the `bootstrap.sh` script diff --git a/tools/docker-dev-env/bootstrap.sh b/tools/docker-dev-env/bootstrap.sh new file mode 100755 index 0000000000..8c21554dcf --- /dev/null +++ b/tools/docker-dev-env/bootstrap.sh @@ -0,0 +1,39 @@ +#!/bin/bash +set -e +CONTAINER_NAME=openair-dev-$USER +if [ "$EUID" -eq 0 ]; then + read -p "You are running this script as root. This might not work as expected. Do you want to continue? (Y/N): " response + if [[ ! "$response" =~ ^[Yy]$ ]]; then + echo "Exiting script." + exit 1 + fi +fi + +if ! docker images | grep -q "ran-base"; then + echo "ran-base:latest image not found. Building the image..." + docker build -f ../../docker/Dockerfile.base.ubuntu22 -t ran-base:latest ../../ +else + echo "ran-base:latest image found." +fi + +echo "Starting the build process for the Docker container..." +docker build -f Dockerfile -t openair-dev:$USER --build-arg USERNAME=$USER --build-arg USER_UID=$(id -u) --build-arg USER_GID=$(id -u) ../../ + +echo -e "\e[93mInstalling aliases to ~/.bash_aliases. Make sure to add 'source ~/.bash_aliases' in ~/.bashrc \e[0m" +mkdir -p ~/oai-dev-env +cp docker-compose.yml ~/oai-dev-env + +touch ~/.bash_aliases + +function add_alias() { + local alias=${1} cmd=${2} + if grep -q "${alias}" ~/.bash_aliases; then echo "cannot add alias ${alias}: already exists in ~/.bash_aliases"; return 1; fi + echo "alias ${alias}='${cmd}'" >> ~/.bash_aliases +} + +add_alias oai_start_dev_env 'docker compose -f ~/oai-dev-env/docker-compose.yml up -d' || true +add_alias oai_stop_dev_env 'docker compose -f ~/oai-dev-env/docker-compose.yml down' || true +add_alias oai_enter_dev_env "docker exec -it -w \$(pwd) $CONTAINER_NAME /bin/bash" || true +add_alias oai_destroy_dev_env "docker container rm -f ${CONTAINER_NAME}" || true + +source ~/.bash_aliases diff --git a/tools/docker-dev-env/docker-compose.yml b/tools/docker-dev-env/docker-compose.yml new file mode 100644 index 0000000000..c88faaf9bc --- /dev/null +++ b/tools/docker-dev-env/docker-compose.yml @@ -0,0 +1,21 @@ +services: + openair-dev-env: + container_name: "openair-dev-${USER}" + image: openair-dev:${USER} + command: "sleep infinity" + privileged: false + cap_add: + - NET_ADMIN + - SYS_ADMIN + - NET_RAW + - SYS_NICE + # CAPS for sudo to work + - CAP_SETUID + - CAP_SETGID + - CAP_SETFCAP + - CAP_AUDIT_WRITE + - CAP_MKNOD + volumes: + - /home/${USER}:/home/${USER} + working_dir: /home/${USER} + hostname: oai-dev-env