diff --git a/.gitignore b/.gitignore index d1c6979e76..de022c0ca7 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,8 @@ nfapi_nr_interface_scf *.log *.out CMakeUserPresets.json + +# clangd LSP files +.clangd +.cache/ +compile_commands.json diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7b2f081988..a1b8be262b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -27,4 +27,4 @@ Please refer to the steps described on our website: [How to contribute to OAI](h By contributing to OpenAirInterface, you agree that your contributions will be licensed under the license described in the file [`LICENSE`](./LICENSE) in the -root directory of this source tree. +root directory of this source tree. \ No newline at end of file diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 6f61196e7e..b010a3deec 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -184,25 +184,25 @@ function main() { "Release") CMAKE_BUILD_TYPE="Release" echo_info "Will Compile without gdb symbols and with compiler optimization" - CMAKE_CMD="$CMAKE_CMD -DCMAKE_BUILD_TYPE=Release" + CMAKE_CMD="$CMAKE_CMD -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXPORT_COMPILE_COMMANDS=ON" shift ;; "RelWithDebInfo") CMAKE_BUILD_TYPE="RelWithDebInfo" echo_info "Will Compile with gdb symbols" - CMAKE_CMD="$CMAKE_CMD -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_EXPORT_COMPILE_COMMANDS=1" + CMAKE_CMD="$CMAKE_CMD -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_EXPORT_COMPILE_COMMANDS=ON" shift ;; "MinSizeRel") CMAKE_BUILD_TYPE="MinSizeRel" echo_info "Will Compile for minimal exec size" - CMAKE_CMD="$CMAKE_CMD -DCMAKE_BUILD_TYPE=MinSizeRel" + CMAKE_CMD="$CMAKE_CMD -DCMAKE_BUILD_TYPE=MinSizeRel -DCMAKE_EXPORT_COMPILE_COMMANDS=ON" shift ;; "Debug" | *) CMAKE_BUILD_TYPE="Debug" echo_info "Will Compile with gdb symbols and disable compiler optimization" - CMAKE_CMD="$CMAKE_CMD -DCMAKE_BUILD_TYPE=Debug" + CMAKE_CMD="$CMAKE_CMD -DCMAKE_BUILD_TYPE=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS=ON" if [ "$2" == "Debug" ] ; then shift fi @@ -459,6 +459,11 @@ function main() { mkdir -p $DIR/$BUILD_DIR/build cd $DIR/$BUILD_DIR/build + # Ensure compile_commands.json is always generated for IDE support + if [[ ! "$CMAKE_CMD" =~ "-DCMAKE_EXPORT_COMPILE_COMMANDS" ]]; then + CMAKE_CMD="$CMAKE_CMD -DCMAKE_EXPORT_COMPILE_COMMANDS=ON" + fi + # for historical reasons we build in a subdirectory cmake_targets/XYZ/build, # e.g., cmake_targets/ran_build/build, hence the ../../.. CMAKE_CMD="$CMAKE_CMD ../../.." diff --git a/common/utils/telnetsrv/telnetsrv_o1.c b/common/utils/telnetsrv/telnetsrv_o1.c index 9ff56e3521..86a727dbeb 100644 --- a/common/utils/telnetsrv/telnetsrv_o1.c +++ b/common/utils/telnetsrv/telnetsrv_o1.c @@ -352,7 +352,8 @@ static int set_bwconfig(char *buf, int debug, telnet_printfunc_t prnt) mac->common_channels[0].mib = get_new_MIB_NR(scc); const f1ap_served_cell_info_t *info = &mac->f1_config.setup_req->cell[0].info; - nr_mac_configure_sib1(mac, &info->plmn, info->nr_cellid, *info->tac); + // Pass PLMN list from F1AP cell info (includes num_plmn and plmn_list) + nr_mac_configure_sib1(mac, &info->plmn, info->nr_cellid, *info->tac, info->num_plmn, info->plmn_list); prnt("OK\n"); return 0; diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index e44e1dccb4..eb20578272 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -85,6 +85,8 @@ #define F1AP_MAX_NO_OF_INDIVIDUAL_CONNECTIONS_TO_RESET 65536 /* 9.3.1.42 of 3GPP TS 38.473 - gNB-CU System Information */ #define F1AP_MAX_NO_SIB_TYPES 32 +/* Maximum number of PLMNs that can be served by a cell */ +#define F1AP_MAX_NB_PLMNS 6 typedef struct f1ap_net_config_t { char *CU_f1_ip_address; @@ -138,6 +140,10 @@ typedef struct f1ap_served_cell_info_t { uint16_t num_ssi; nssai_t nssai[MAX_NUM_SLICES]; + // PLMN list + uint16_t num_plmn; + plmn_id_t plmn_list[F1AP_MAX_NB_PLMNS]; + f1ap_mode_t mode; union { f1ap_fdd_info_t fdd; diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 1f641fc6d9..7decd94ba5 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -129,6 +129,9 @@ static uint8_t set_plmn_config(plmn_id_t *p, uint8_t idx) plmn->mcc = *PLMNParamList.paramarray[l][GNB_MOBILE_COUNTRY_CODE_IDX].uptr; plmn->mnc = *PLMNParamList.paramarray[l][GNB_MOBILE_NETWORK_CODE_IDX].uptr; plmn->mnc_digit_length = *PLMNParamList.paramarray[l][GNB_MNC_DIGIT_LENGTH].u8ptr; + + LOG_I(GNB_APP, "[cyhtest:set_plmn_config] set_plmn_config PLMN[%d]: mcc=%d, mnc=%d, mnc_digit_length=%d\n", l, plmn->mcc, plmn->mnc, plmn->mnc_digit_length); + AssertFatal((plmn->mnc_digit_length == 2) || (plmn->mnc_digit_length == 3), "BAD MNC DIGIT LENGTH %d", plmn->mnc_digit_length); } return num_plmn; @@ -1081,7 +1084,14 @@ static int read_du_cell_info(configmodule_interface_t *cfg, // PLMN plmn_id_t p[PLMN_LIST_MAX_SIZE] = {0}; - set_plmn_config(p, 0); + uint8_t num_plmn = set_plmn_config(p, 0); + + // Copy PLMN list to info structure + info->num_plmn = num_plmn; + for (int i = 0; i < num_plmn; i++) { + info->plmn_list[i] = p[i]; + } + info->plmn = p[0]; info->nr_cellid = (uint64_t) * (GNBParamList.paramarray[0][GNB_NRCELLID_IDX].u64ptr); @@ -1673,7 +1683,7 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg) cc->du_SIBs = fill_du_sibs(GNBParamList.paramarray[0]); if (IS_SA_MODE(get_softmodem_params())) - nr_mac_configure_sib1(RC.nrmac[0], &info.plmn, info.nr_cellid, *info.tac); + nr_mac_configure_sib1(RC.nrmac[0], &info.plmn, info.nr_cellid, *info.tac, info.num_plmn, info.plmn_list); // read F1 Setup information from config and generated MIB/SIB1 // and store it at MAC for sending later diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index 35b6fa509a..fee4eb967e 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -1105,13 +1105,38 @@ void prepare_du_configuration_update(gNB_MAC_INST *mac, mac->mac_rrc.gnb_du_configuration_update(&update); } -void nr_mac_configure_sib1(gNB_MAC_INST *nrmac, const plmn_id_t *plmn, uint64_t cellID, int tac) +void nr_mac_configure_sib1(gNB_MAC_INST *nrmac, const plmn_id_t *plmn, uint64_t cellID, int tac, int num_plmn, const plmn_id_t *plmn_list) { AssertFatal(IS_SA_MODE(get_softmodem_params()), "error: SIB1 only applicable for SA\n"); NR_COMMON_channels_t *cc = &nrmac->common_channels[0]; NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon; - NR_BCCH_DL_SCH_Message_t *sib1 = get_SIB1_NR(scc, plmn, cellID, tac, &nrmac->radio_config); + NR_BCCH_DL_SCH_Message_t *sib1 = get_SIB1_NR(scc, plmn, cellID, tac, &nrmac->radio_config, num_plmn, plmn_list); + + // Access SIB1 content through the message structure + if (sib1 && sib1->message.choice.c1 && + sib1->message.choice.c1->present == NR_BCCH_DL_SCH_MessageType__c1_PR_systemInformationBlockType1) { + NR_SIB1_t *sib1_content = sib1->message.choice.c1->choice.systemInformationBlockType1; + LOG_I(NR_MAC, "[cyhtest] after get_SIB1_NR: plmn_IdentityInfoList.list.count=%d\n", + sib1_content->cellAccessRelatedInfo.plmn_IdentityInfoList.list.count); + for (int i = 0; i < sib1_content->cellAccessRelatedInfo.plmn_IdentityInfoList.list.count; i++) { + NR_PLMN_IdentityInfo_t *plmn_info = sib1_content->cellAccessRelatedInfo.plmn_IdentityInfoList.list.array[i]; + LOG_I(NR_MAC, "[cyhtest] after get_SIB1_NR: plmn_IdentityInfoList.list.array[%d]->plmn_IdentityList.list.count=%d\n", + i, plmn_info->plmn_IdentityList.list.count); + for (int j = 0; j < plmn_info->plmn_IdentityList.list.count; j++) { + NR_PLMN_Identity_t *plmn_id = plmn_info->plmn_IdentityList.list.array[j]; + LOG_I(NR_MAC, "[cyhtest] after get_SIB1_NR: plmn_IdentityList.list.array[%d][%d] mcc=%02lx%02lx%02lx mnc=%02lx%02lx%02lx\n", + i, j, + plmn_id->mcc ? *plmn_id->mcc->list.array[0] : 0, + plmn_id->mcc ? *plmn_id->mcc->list.array[1] : 0, + plmn_id->mcc ? *plmn_id->mcc->list.array[2] : 0, + *plmn_id->mnc.list.array[0], + *plmn_id->mnc.list.array[1], + plmn_id->mnc.list.count > 2 ? *plmn_id->mnc.list.array[2] : 0); + } + } + } + cc->sib1 = sib1; cc->sib1_bcch_length = encode_SIB_NR(sib1, cc->sib1_bcch_pdu, sizeof(cc->sib1_bcch_pdu)); AssertFatal(cc->sib1_bcch_length > 0, "could not encode SIB1\n"); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index af0d102212..179578ef39 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -58,7 +58,7 @@ void mac_top_destroy_gNB(gNB_MAC_INST *mac); void nr_mac_send_f1_setup_req(void); void nr_mac_config_scc(gNB_MAC_INST *nrmac, NR_ServingCellConfigCommon_t *scc, const nr_mac_config_t *mac_config); -void nr_mac_configure_sib1(gNB_MAC_INST *nrmac, const plmn_id_t *plmn, uint64_t cellID, int tac); +void nr_mac_configure_sib1(gNB_MAC_INST *nrmac, const plmn_id_t *plmn, uint64_t cellID, int tac, int num_plmn, const plmn_id_t *plmn_list); bool nr_mac_configure_other_sib(gNB_MAC_INST *nrmac, int num_cu_sib, const f1ap_sib_msg_t cu_sib[num_cu_sib]); bool nr_mac_add_test_ue(gNB_MAC_INST *nrmac, uint32_t rnti, NR_CellGroupConfig_t *CellGroup); void nr_mac_prepare_ra_ue(gNB_MAC_INST *nrmac, NR_UE_info_t *UE); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c index 3cd448b216..c9ee40c682 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c @@ -2712,7 +2712,9 @@ NR_BCCH_DL_SCH_Message_t *get_SIB1_NR(const NR_ServingCellConfigCommon_t *scc, const plmn_id_t *plmn, uint64_t cellID, int tac, - const nr_mac_config_t *mac_config) + const nr_mac_config_t *mac_config, + int num_plmn, + const plmn_id_t *plmn_list) { AssertFatal(cellID < (1l << 36), "cellID must fit within 36 bits, but is %lu\n", cellID); @@ -2736,21 +2738,22 @@ NR_BCCH_DL_SCH_Message_t *get_SIB1_NR(const NR_ServingCellConfigCommon_t *scc, sib1->cellSelectionInfo->q_RxLevMin = -65; // cellAccessRelatedInfo - // TODO : Add support for more than one PLMN - int num_plmn = 1; // int num_plmn = configuration->num_plmn; + // Support multiple PLMNs + LOG_I(NR_RRC, "[cyhtest] get_SIB1_NR: Creating SIB1 with %d PLMN(s)\n", num_plmn); asn1cSequenceAdd(sib1->cellAccessRelatedInfo.plmn_IdentityInfoList.list, struct NR_PLMN_IdentityInfo, nr_plmn_info); for (int i = 0; i < num_plmn; ++i) { asn1cSequenceAdd(nr_plmn_info->plmn_IdentityList.list, struct NR_PLMN_Identity, nr_plmn); asn1cCalloc(nr_plmn->mcc, mcc); - int confMcc = plmn->mcc; + int confMcc = plmn_list[i].mcc; + LOG_I(NR_RRC, "[cyhtest] get_SIB1_NR: Adding PLMN[%d]: %d.%d\n", i, plmn_list[i].mcc, plmn_list[i].mnc); asn1cSequenceAdd(mcc->list, NR_MCC_MNC_Digit_t, mcc0); *mcc0 = (confMcc / 100) % 10; asn1cSequenceAdd(mcc->list, NR_MCC_MNC_Digit_t, mcc1); *mcc1 = (confMcc / 10) % 10; asn1cSequenceAdd(mcc->list, NR_MCC_MNC_Digit_t, mcc2); *mcc2 = confMcc % 10; - int mnc = plmn->mnc; - if (plmn->mnc_digit_length == 3) { + int mnc = plmn_list[i].mnc; + if (plmn_list[i].mnc_digit_length == 3) { asn1cSequenceAdd(nr_plmn->mnc.list, NR_MCC_MNC_Digit_t, mnc0); *mnc0 = (mnc / 100) % 10; } @@ -3020,6 +3023,31 @@ void free_SIB1_NR(NR_BCCH_DL_SCH_Message_t *sib1) int encode_SIB_NR(NR_BCCH_DL_SCH_Message_t *sib, uint8_t *buffer, int max_buffer_size) { + // Print PLMN Identity List from SIB1 + if (sib && sib->message.choice.c1 && sib->message.choice.c1->present == NR_BCCH_DL_SCH_MessageType__c1_PR_systemInformationBlockType1) { + NR_SIB1_t *sib1 = sib->message.choice.c1->choice.systemInformationBlockType1; + if (sib1 && sib1->cellAccessRelatedInfo.plmn_IdentityInfoList.list.array) { + LOG_I(NR_MAC, "[cyhtest] encode_SIB_NR: SIB1 plmn_IdentityInfoList has %d PLMN(s)\n", + sib1->cellAccessRelatedInfo.plmn_IdentityInfoList.list.count); + for (int i = 0; i < sib1->cellAccessRelatedInfo.plmn_IdentityInfoList.list.count; i++) { + NR_PLMN_IdentityInfo_t *plmn_info = sib1->cellAccessRelatedInfo.plmn_IdentityInfoList.list.array[i]; + LOG_I(NR_MAC, "[cyhtest] encode_SIB_NR: plmn_IdentityInfoList.list.array[%d]->plmn_IdentityList.list.count=%d\n", + i, plmn_info->plmn_IdentityList.list.count); + for (int j = 0; j < plmn_info->plmn_IdentityList.list.count; j++) { + NR_PLMN_Identity_t *plmn_id = plmn_info->plmn_IdentityList.list.array[j]; + LOG_I(NR_MAC, "[cyhtest] encode_SIB_NR: plmn_IdentityList.list.array[%d][%d] mcc=%02lx%02lx%02lx mnc=%02lx%02lx%02lx\n", + i, j, + plmn_id->mcc ? *plmn_id->mcc->list.array[0] : 0, + plmn_id->mcc ? *plmn_id->mcc->list.array[1] : 0, + plmn_id->mcc ? *plmn_id->mcc->list.array[2] : 0, + *plmn_id->mnc.list.array[0], + *plmn_id->mnc.list.array[1], + plmn_id->mnc.list.count > 2 ? *plmn_id->mnc.list.array[2] : 0); + } + } + } + } + AssertFatal(max_buffer_size <= NR_MAX_SIB_LENGTH / 8, "Maximum buffer size too large: 3GPP TS 38.331 section 5.2.1 - The physical layer imposes a limit to the " "maximum size a SIB can take. The maximum SIB1 or SI message size is 2976 bits.\n"); diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h index b776d667d6..443c6d15e0 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h @@ -79,7 +79,9 @@ NR_BCCH_DL_SCH_Message_t *get_SIB1_NR(const NR_ServingCellConfigCommon_t *scc, const plmn_id_t *plmn, uint64_t cellID, int tac, - const nr_mac_config_t *mac_config); + const nr_mac_config_t *mac_config, + int num_plmn, + const plmn_id_t *plmn_list); void update_SIB1_NR_SI(NR_BCCH_DL_SCH_Message_t *sib1, int num_sibs, int sibs[num_sibs]); int encode_sysinfo_ie(NR_SystemInformation_IEs_t *sysInfo, uint8_t *buf, int len); void free_SIB1_NR(NR_BCCH_DL_SCH_Message_t *sib1); diff --git a/openair2/RRC/NR/rrc_gNB_du.c b/openair2/RRC/NR/rrc_gNB_du.c index 246df60626..9d3ae3bbbf 100644 --- a/openair2/RRC/NR/rrc_gNB_du.c +++ b/openair2/RRC/NR/rrc_gNB_du.c @@ -99,6 +99,7 @@ RB_GENERATE/*_STATIC*/(rrc_du_tree, nr_rrc_du_container_t, entries, du_compare); static bool rrc_gNB_plmn_matches(const gNB_RRC_INST *rrc, const f1ap_served_cell_info_t *info) { const gNB_RrcConfigurationReq *conf = &rrc->configuration; + return conf->num_plmn == 1 // F1 supports only one && conf->plmn[0].mcc == info->plmn.mcc && conf->plmn[0].mnc == info->plmn.mnc; } @@ -311,19 +312,20 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id) return; } f1ap_served_cell_info_t *cell_info = &req->cell[0].info; - if (!rrc_gNB_plmn_matches(rrc, cell_info)) { - LOG_E(NR_RRC, - "PLMN mismatch: CU %03d.%0*d, DU %03d%0*d\n", - rrc->configuration.plmn[0].mcc, - rrc->configuration.plmn[0].mnc_digit_length, - rrc->configuration.plmn[0].mnc, - cell_info->plmn.mcc, - cell_info->plmn.mnc_digit_length, - cell_info->plmn.mnc); - fail.cause = F1AP_CauseRadioNetwork_plmn_not_served_by_the_gNB_CU; - rrc->mac_rrc.f1_setup_failure(assoc_id, &fail); - return; - } + // I have to comment this single PLMN match between CU and DU to enable multiple PLMNs broadcasting + // if (!rrc_gNB_plmn_matches(rrc, cell_info)) { + // LOG_E(NR_RRC, + // "PLMN mismatch: CU %03d.%0*d, DU %03d%0*d\n", + // rrc->configuration.plmn[0].mcc, + // rrc->configuration.plmn[0].mnc_digit_length, + // rrc->configuration.plmn[0].mnc, + // cell_info->plmn.mcc, + // cell_info->plmn.mnc_digit_length, + // cell_info->plmn.mnc); + // fail.cause = F1AP_CauseRadioNetwork_plmn_not_served_by_the_gNB_CU; + // rrc->mac_rrc.f1_setup_failure(assoc_id, &fail); + // return; + // } nr_rrc_du_container_t *it = NULL; RB_FOREACH(it, rrc_du_tree, &rrc->dus) { if (it->setup_req->gNB_DU_id == req->gNB_DU_id) { diff --git a/openair2/RRC/NR_UE/rrc_UE.c b/openair2/RRC/NR_UE/rrc_UE.c index 27e1dc0bb1..6f1fe800c5 100644 --- a/openair2/RRC/NR_UE/rrc_UE.c +++ b/openair2/RRC/NR_UE/rrc_UE.c @@ -485,6 +485,105 @@ static void get_sib19_schedinfo(NR_UE_RRC_SI_INFO *SI_info, NR_SI_SchedulingInfo static void nr_rrc_process_sib1(NR_UE_RRC_INST_t *rrc, NR_UE_RRC_SI_INFO *SI_info, NR_SIB1_t *sib1) { + // Print PLMN Identity List from SIB1 + if (sib1 && sib1->cellAccessRelatedInfo.plmn_IdentityInfoList.list.array) { + LOG_I(NR_RRC, "[cyhtest] nr_rrc_process_sib1: SIB1 plmn_IdentityInfoList has %d PLMN(s)\n", + sib1->cellAccessRelatedInfo.plmn_IdentityInfoList.list.count); + for (int i = 0; i < sib1->cellAccessRelatedInfo.plmn_IdentityInfoList.list.count; i++) { + NR_PLMN_IdentityInfo_t *plmn_info = sib1->cellAccessRelatedInfo.plmn_IdentityInfoList.list.array[i]; + LOG_I(NR_RRC, "[cyhtest] nr_rrc_process_sib1: plmn_IdentityInfoList.list.array[%d]->plmn_IdentityList.list.count=%d\n", + i, plmn_info->plmn_IdentityList.list.count); + for (int j = 0; j < plmn_info->plmn_IdentityList.list.count; j++) { + NR_PLMN_Identity_t *plmn_id = plmn_info->plmn_IdentityList.list.array[j]; + LOG_I(NR_RRC, "[cyhtest] nr_rrc_process_sib1: plmn_IdentityList.list.array[%d][%d] mcc=%02lx%02lx%02lx mnc=%02lx%02lx%02lx\n", + i, j, + plmn_id->mcc ? *plmn_id->mcc->list.array[0] : 0, + plmn_id->mcc ? *plmn_id->mcc->list.array[1] : 0, + plmn_id->mcc ? *plmn_id->mcc->list.array[2] : 0, + *plmn_id->mnc.list.array[0], + *plmn_id->mnc.list.array[1], + plmn_id->mnc.list.count > 2 ? *plmn_id->mnc.list.array[2] : 0); + } + } + } + + // PLMN selection: match UE's IMSI with SIB1 PLMNs + nr_ue_nas_t *nas = get_ue_nas_info(rrc->ue_id); + if (nas && nas->uicc && nas->uicc->imsiStr && sib1 && sib1->cellAccessRelatedInfo.plmn_IdentityInfoList.list.array) { + // Extract MCC/MNC from IMSI (imsiStr format: "MCCMNCMSIN", e.g., "208930000000003") + uint8_t ue_mcc[3], ue_mnc[3]; + ue_mcc[0] = nas->uicc->imsiStr[0] - '0'; + ue_mcc[1] = nas->uicc->imsiStr[1] - '0'; + ue_mcc[2] = nas->uicc->imsiStr[2] - '0'; + + int mnc_len = nas->uicc->nmc_size; + if (mnc_len == 2) { + ue_mnc[0] = 0xF; // padding for 2-digit MNC + ue_mnc[1] = nas->uicc->imsiStr[3] - '0'; + ue_mnc[2] = nas->uicc->imsiStr[4] - '0'; + } else { // mnc_len == 3 + ue_mnc[0] = nas->uicc->imsiStr[3] - '0'; + ue_mnc[1] = nas->uicc->imsiStr[4] - '0'; + ue_mnc[2] = nas->uicc->imsiStr[5] - '0'; + } + + LOG_I(NR_RRC, "[cyhtest] nr_rrc_process_sib1: UE IMSI=%s, MCC=%d%d%d, MNC=%s%d%d (mnc_len=%d)\n", + nas->uicc->imsiStr, ue_mcc[0], ue_mcc[1], ue_mcc[2], + (ue_mnc[0] == 0xF ? "" : ((char[]){ue_mnc[0]+'0', '\0'})), + ue_mnc[1], ue_mnc[2], mnc_len); + + // Search for matching PLMN in SIB1 list + bool plmn_matched = false; + for (int i = 0; i < sib1->cellAccessRelatedInfo.plmn_IdentityInfoList.list.count && !plmn_matched; i++) { + NR_PLMN_IdentityInfo_t *plmn_info = sib1->cellAccessRelatedInfo.plmn_IdentityInfoList.list.array[i]; + for (int j = 0; j < plmn_info->plmn_IdentityList.list.count && !plmn_matched; j++) { + NR_PLMN_Identity_t *plmn_id = plmn_info->plmn_IdentityList.list.array[j]; + + // Compare MCC + bool mcc_match = false; + if (plmn_id->mcc) { + mcc_match = (*plmn_id->mcc->list.array[0] == ue_mcc[0]) && + (*plmn_id->mcc->list.array[1] == ue_mcc[1]) && + (*plmn_id->mcc->list.array[2] == ue_mcc[2]); + } + + // Compare MNC + bool mnc_match = false; + if (mcc_match) { + if (plmn_id->mnc.list.count == 2) { + // SIB1 has 2-digit MNC + mnc_match = (mnc_len == 2) && + (*plmn_id->mnc.list.array[0] == ue_mnc[1]) && + (*plmn_id->mnc.list.array[1] == ue_mnc[2]); + } else if (plmn_id->mnc.list.count == 3) { + // SIB1 has 3-digit MNC + mnc_match = (mnc_len == 3) && + (*plmn_id->mnc.list.array[0] == ue_mnc[0]) && + (*plmn_id->mnc.list.array[1] == ue_mnc[1]) && + (*plmn_id->mnc.list.array[2] == ue_mnc[2]); + } + } + + if (mcc_match && mnc_match) { + // PLMN matched! Set selectedPLMN_Identity (1-based index) + rrc->selected_plmn_identity = j + 1; + plmn_matched = true; + LOG_I(NR_RRC, "[cyhtest] nr_rrc_process_sib1: PLMN matched at index %d, set selected_plmn_identity=%ld\n", + j, rrc->selected_plmn_identity); + } + } + } + + if (!plmn_matched) { + LOG_W(NR_RRC, "[cyhtest] nr_rrc_process_sib1: No matching PLMN found in SIB1! UE IMSI PLMN not in cell's PLMN list\n"); + // Keep default value (will use first PLMN as fallback) + rrc->selected_plmn_identity = 1; + } + } else { + LOG_W(NR_RRC, "[cyhtest] nr_rrc_process_sib1: Cannot get NAS UICC info for PLMN selection, using default selected_plmn_identity=1\n"); + rrc->selected_plmn_identity = 1; + } + if(g_log->log_component[NR_RRC].level >= OAILOG_DEBUG) xer_fprint(stdout, &asn_DEF_NR_SIB1, (const void *) sib1); LOG_A(NR_RRC, "SIB1 decoded\n"); @@ -1273,7 +1372,7 @@ NR_UE_RRC_INST_t* nr_rrc_init_ue(char* uecap_file, int instance_id, int num_ant_ NR_UE_RRC_INST_t *rrc = NR_UE_rrc_inst[instance_id]; rrc->ue_id = instance_id; // fill UE-NR-Capability @ UE-CapabilityRAT-Container here. - rrc->selected_plmn_identity = 1; + rrc->selected_plmn_identity = 1; // Initial default value, will be updated in nr_rrc_process_sib1() based on IMSI matching rrc->ra_trigger = RA_NOT_RUNNING; rrc->dl_bwp_id = 0; rrc->ul_bwp_id = 0; diff --git a/openair3/NAS/NR_UE/nr_nas_msg.c b/openair3/NAS/NR_UE/nr_nas_msg.c index 5a58af6b84..023dd8c717 100644 --- a/openair3/NAS/NR_UE/nr_nas_msg.c +++ b/openair3/NAS/NR_UE/nr_nas_msg.c @@ -677,6 +677,12 @@ nr_ue_nas_t *get_ue_nas_info(module_id_t module_id) AssertFatal(module_id < MAX_NUM_NR_UE_INST, "Invalid module_id %d\n", module_id); if (!nr_ue_nas[module_id].uicc) { nr_ue_nas[module_id].uicc = checkUicc(module_id); + // Print IMSI string from UICC after initialization + if (nr_ue_nas[module_id].uicc && nr_ue_nas[module_id].uicc->imsiStr) { + LOG_I(NAS, "[cyhtest] get_ue_nas_info: module_id=%d, imsiStr=%s\n", + module_id, nr_ue_nas[module_id].uicc->imsiStr); + } + nr_ue_nas[module_id].UE_id = module_id; } return &nr_ue_nas[module_id]; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf index 7f750d7259..8e14fae8c8 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf @@ -11,7 +11,10 @@ gNBs = // 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; }) }); + plmn_list = ( + { mcc = 460; mnc = 11; mnc_length = 2; snssaiList = ({ sst = 1; sd = 0x010204; }) }, + { mcc = 208; mnc = 93; mnc_length = 2; snssaiList = ({ sst = 1; sd = 0x010203; }) } + ); nr_cellid = 12345678L; @@ -155,13 +158,13 @@ gNBs = ////////// AMF parameters: - amf_ip_address = ({ ipv4 = "192.168.70.132"; }); + amf_ip_address = ({ ipv4 = "128.105.145.22"; }); NETWORK_INTERFACES : { - GNB_IPV4_ADDRESS_FOR_NG_AMF = "192.168.70.129/24"; - GNB_IPV4_ADDRESS_FOR_NGU = "192.168.70.129/24"; + GNB_IPV4_ADDRESS_FOR_NG_AMF = "128.105.145.24/22"; + GNB_IPV4_ADDRESS_FOR_NGU = "10.10.3.1/24"; GNB_PORT_FOR_S1U = 2152; # Spec 2152 }; diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.conf index 4cea93ea46..dc03392306 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/ue.conf @@ -1,10 +1,10 @@ uicc0 = { -imsi = "2089900007487"; -key = "fec86ba6eb707ed08905757b1bb44b8f"; -opc= "C42449363BBAD02B66D16BC975D77CC1"; -dnn= "oai"; +imsi = "208930000000003"; +key = "8baf473f2f8fd09487cccbd7097c6862"; +opc= "8e27b6af0e692e750f32667a3b14605d"; +dnn= "internet"; nssai_sst=1; -nssai_sd=1; +nssai_sd=0x010203; } position0 = { @@ -13,4 +13,4 @@ position0 = { z = 6377900.0; } -@include "channelmod_rfsimu_LEO_satellite.conf" +@include "channelmod_rfsimu_LEO_satellite.conf" \ No newline at end of file diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/ue2.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/ue2.conf new file mode 100644 index 0000000000..fed57fa5de --- /dev/null +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/ue2.conf @@ -0,0 +1,16 @@ +uicc0 = { +imsi = "208930000000004"; +key = "8baf473f2f8fd09487cccbd7097c6862"; +opc= "8e27b6af0e692e750f32667a3b14605d"; +dnn= "internet"; +nssai_sst=1; +nssai_sd=0x010203; +} + +position0 = { + x = 0.0; + y = 0.0; + z = 6377900.0; +} + +@include "channelmod_rfsimu_LEO_satellite.conf" \ No newline at end of file