From 1d9418097ff3fb58cb4f4246f404acb999946f40 Mon Sep 17 00:00:00 2001 From: Rakesh Mundlamuri Date: Mon, 16 Feb 2026 19:32:09 +0530 Subject: [PATCH 01/21] Move RCconfig_NR_NG() to NGAP --- CMakeLists.txt | 2 + openair2/GNB_APP/gnb_app.c | 1 + openair2/GNB_APP/gnb_config.c | 165 +-------------------------- openair2/GNB_APP/gnb_config.h | 1 - openair2/GNB_APP/gnb_config_common.c | 66 +++++++++++ openair2/GNB_APP/gnb_config_common.h | 26 +++++ openair2/GNB_APP/gnb_config_ng.c | 162 ++++++++++++++++++++++++++ openair2/GNB_APP/gnb_config_ng.h | 29 +++++ 8 files changed, 287 insertions(+), 165 deletions(-) create mode 100644 openair2/GNB_APP/gnb_config_common.c create mode 100644 openair2/GNB_APP/gnb_config_common.h create mode 100644 openair2/GNB_APP/gnb_config_ng.c create mode 100644 openair2/GNB_APP/gnb_config_ng.h diff --git a/CMakeLists.txt b/CMakeLists.txt index d0b9f17a02..0f2e8931a3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1308,6 +1308,8 @@ set (GNB_APP_SRC ${OPENAIR2_DIR}/GNB_APP/gnb_app.c ${OPENAIR2_DIR}/E1AP/e1ap_setup.c ${OPENAIR2_DIR}/GNB_APP/gnb_config.c + ${OPENAIR2_DIR}/GNB_APP/gnb_config_common.c + ${OPENAIR2_DIR}/GNB_APP/gnb_config_ng.c ) set (MCE_APP_SRC diff --git a/openair2/GNB_APP/gnb_app.c b/openair2/GNB_APP/gnb_app.c index 98546413a0..9597f61430 100644 --- a/openair2/GNB_APP/gnb_app.c +++ b/openair2/GNB_APP/gnb_app.c @@ -53,6 +53,7 @@ #include "openair2/E1AP/e1ap.h" #include "gnb_config.h" #include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h" +#include "openair2/GNB_APP/gnb_config_ng.h" extern RAN_CONTEXT_t RC; /*------------------------------------------------------------------------------*/ diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 667ab25093..d6d370fe70 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -79,7 +79,7 @@ #include "uper_encoder.h" #include "utils.h" #include "x2ap_messages_types.h" - +#include "gnb_config_common.h" static int DEFBANDS[] = {7}; static int DEFENBS[] = {0}; @@ -96,45 +96,6 @@ static int DEFRUTPCORES[] = {-1,-1,-1,-1}; (element)->choice.setup = CALLOC(1, sizeof(*((element)->choice.setup))); \ } while (0) -static uint16_t set_snssai_config(nssai_t *nssai, const int max_num_ssi, uint8_t k, uint8_t l) -{ - char snssaistr[MAX_OPTNAME_SIZE * 2 + 8]; - snprintf(snssaistr, sizeof(snssaistr), "%s.[%i].%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, k, GNB_CONFIG_STRING_PLMN_LIST, l); - GET_PARAMS_LIST(SNSSAIParamList, - SNSSAIParams, - GNBSNSSAIPARAMS_DESC, - GNB_CONFIG_STRING_SNSSAI_LIST, - snssaistr, - SNSSAIPARAMS_CHECK); - uint16_t num_ssi = SNSSAIParamList.numelt; - AssertFatal(num_ssi < max_num_ssi, "S-NSSAI size %d exceeds the max array size %d", num_ssi, max_num_ssi); - for (int s = 0; s < num_ssi; ++s) { - nssai[s].sst = *SNSSAIParamList.paramarray[s][GNB_SLICE_SERVICE_TYPE_IDX].uptr; - // SD is optional - // 0xffffff is "no SD", see 23.003 Sec 28.4.2 - nssai[s].sd = *SNSSAIParamList.paramarray[s][GNB_SLICE_DIFFERENTIATOR_IDX].uptr; - AssertFatal(nssai[s].sd <= 0xffffff, "SD cannot be bigger than 0xffffff, but is %d\n", nssai[s].sd); - } - return num_ssi; -} - -static uint8_t set_plmn_config(plmn_id_t *p, uint8_t idx) -{ - char gnbpath[MAX_OPTNAME_SIZE * 2 + 8]; - snprintf(gnbpath, sizeof(gnbpath), "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, idx); - GET_PARAMS_LIST(PLMNParamList, PLMNParams, GNBPLMNPARAMS_DESC, GNB_CONFIG_STRING_PLMN_LIST, gnbpath, PLMNPARAMS_CHECK); - uint8_t num_plmn = PLMNParamList.numelt; - AssertFatal(num_plmn >= 1 && num_plmn <= 6, "The number of PLMN IDs must be in [1,6], but is %d\n", num_plmn); - for (int l = 0; l < num_plmn; ++l) { - plmn_id_t *plmn = &p[l]; - 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; - AssertFatal((plmn->mnc_digit_length == 2) || (plmn->mnc_digit_length == 3), "BAD MNC DIGIT LENGTH %d", plmn->mnc_digit_length); - } - return num_plmn; -} - /** * Allocate memory and initialize ServingCellConfigCommon struct members */ @@ -2131,130 +2092,6 @@ gNB_RRC_INST *RCconfig_NRRRC() return rrc; } -int RCconfig_NR_NG(MessageDef *msg_p, uint32_t i) -{ - int j,k = 0; - int gnb_id; - - char* gnb_ipv4_address_for_NGU = NULL; - uint32_t gnb_port_for_NGU = 0; - char* gnb_ipv4_address_for_S1U = NULL; - uint32_t gnb_port_for_S1U = 0; - - GET_PARAMS(GNBSParams, GNBSPARAMS_DESC, NULL); - AssertFatal (i0) { - // Output a list of all gNBs. - GET_PARAMS_LIST(GNBParamList, GNBParams, GNBPARAMS_DESC, GNB_CONFIG_STRING_GNB_LIST, NULL); - if (GNBParamList.numelt > 0) { - for (k = 0; k < GNBParamList.numelt; k++) { - if (GNBParamList.paramarray[k][GNB_GNB_ID_IDX].uptr == NULL) { - // Calculate a default gNB ID - if (IS_SA_MODE(get_softmodem_params())) { - uint32_t hash; - - hash = ngap_generate_gNB_id (); - gnb_id = k + (hash & 0xFFFFFF8); - } else { - gnb_id = k; - } - } else { - gnb_id = *(GNBParamList.paramarray[k][GNB_GNB_ID_IDX].uptr); - } - - - // search if in active list - for (j=0; j < GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt; j++) { - if (strcmp(GNBSParams[GNB_ACTIVE_GNBS_IDX].strlistptr[j], *(GNBParamList.paramarray[k][GNB_GNB_NAME_IDX].strptr)) == 0) { - - char aprefix[MAX_OPTNAME_SIZE*2 + 8]; - NGAP_REGISTER_GNB_REQ (msg_p).gNB_id = gnb_id; - - if (strcmp(*(GNBParamList.paramarray[k][GNB_CELL_TYPE_IDX].strptr), "CELL_MACRO_GNB") == 0) { - NGAP_REGISTER_GNB_REQ (msg_p).cell_type = CELL_MACRO_GNB; - } else if (strcmp(*(GNBParamList.paramarray[k][GNB_CELL_TYPE_IDX].strptr), "CELL_HOME_GNB") == 0) { - NGAP_REGISTER_GNB_REQ (msg_p).cell_type = CELL_HOME_ENB; - } else { - AssertFatal (0, - "Failed to parse gNB configuration file %s, gnb %u unknown value \"%s\" for cell_type choice: CELL_MACRO_GNB or CELL_HOME_GNB !\n", - RC.config_file_name, i, *(GNBParamList.paramarray[k][GNB_CELL_TYPE_IDX].strptr)); - } - - NGAP_REGISTER_GNB_REQ (msg_p).gNB_name = strdup(*(GNBParamList.paramarray[k][GNB_GNB_NAME_IDX].strptr)); - NGAP_REGISTER_GNB_REQ (msg_p).tac = *GNBParamList.paramarray[k][GNB_TRACKING_AREA_CODE_IDX].uptr; - AssertFatal(!GNBParamList.paramarray[k][GNB_MOBILE_COUNTRY_CODE_IDX_OLD].strptr - && !GNBParamList.paramarray[k][GNB_MOBILE_NETWORK_CODE_IDX_OLD].strptr, - "It seems that you use an old configuration file. Please change the existing\n" - " tracking_area_code = \"1\";\n" - " mobile_country_code = \"208\";\n" - " mobile_network_code = \"93\";\n" - "to\n" - " tracking_area_code = 1; // no string!!\n" - " plmn_list = ( { mcc = 208; mnc = 93; mnc_length = 2; } )\n"); - // PLMN - plmn_id_t p[PLMN_LIST_MAX_SIZE] = {0}; - NGAP_REGISTER_GNB_REQ(msg_p).num_plmn = set_plmn_config(p, 0); - for (int l = 0; l < NGAP_REGISTER_GNB_REQ(msg_p).num_plmn; ++l) { - NGAP_REGISTER_GNB_REQ(msg_p).plmn[l].plmn = p[l]; - // SNSSAI - NGAP_REGISTER_GNB_REQ(msg_p).plmn[l].num_nssai = set_snssai_config(NGAP_REGISTER_GNB_REQ(msg_p).plmn[l].s_nssai, 8, k, l); - } - NGAP_REGISTER_GNB_REQ(msg_p).default_drx = 0; - // NG - snprintf(aprefix, sizeof(aprefix), "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, k); - GET_PARAMS_LIST(NGParamList, NGParams, GNBNGPARAMS_DESC, GNB_CONFIG_STRING_AMF_IP_ADDRESS, aprefix); - NGAP_REGISTER_GNB_REQ (msg_p).nb_amf = 0; - - for (int l = 0; l < NGParamList.numelt; l++) { - NGAP_REGISTER_GNB_REQ (msg_p).nb_amf += 1; - strcpy(NGAP_REGISTER_GNB_REQ (msg_p).amf_ip_address[l].ipv4_address,*(NGParamList.paramarray[l][GNB_AMF_IPV4_ADDRESS_IDX].strptr)); - NGAP_REGISTER_GNB_REQ (msg_p).amf_ip_address[j].ipv4 = 1; - NGAP_REGISTER_GNB_REQ (msg_p).amf_ip_address[j].ipv6 = 0; - /* if no broadcasst_plmn array is defined, fill default values */ - if (NGAP_REGISTER_GNB_REQ(msg_p).broadcast_plmn_num[l] == 0) { - NGAP_REGISTER_GNB_REQ(msg_p).broadcast_plmn_num[l] = NGAP_REGISTER_GNB_REQ(msg_p).num_plmn; - for (int el = 0; el < NGAP_REGISTER_GNB_REQ(msg_p).num_plmn; ++el) - NGAP_REGISTER_GNB_REQ(msg_p).broadcast_plmn_index[l][el] = el; - } - } - - // SCTP SETTING - NGAP_REGISTER_GNB_REQ (msg_p).sctp_out_streams = SCTP_OUT_STREAMS; - NGAP_REGISTER_GNB_REQ (msg_p).sctp_in_streams = SCTP_IN_STREAMS; - if (IS_SA_MODE(get_softmodem_params())) { - snprintf(aprefix, sizeof(aprefix), "%s.[%d].%s", GNB_CONFIG_STRING_GNB_LIST, k, GNB_CONFIG_STRING_SCTP_CONFIG); - GET_PARAMS(SCTPParams, GNBSCTPPARAMS_DESC, aprefix); - NGAP_REGISTER_GNB_REQ (msg_p).sctp_in_streams = (uint16_t)*(SCTPParams[GNB_SCTP_INSTREAMS_IDX].uptr); - NGAP_REGISTER_GNB_REQ (msg_p).sctp_out_streams = (uint16_t)*(SCTPParams[GNB_SCTP_OUTSTREAMS_IDX].uptr); - } - - // NETWORK_INTERFACES - snprintf(aprefix, sizeof(aprefix), "%s.[%d].%s", GNB_CONFIG_STRING_GNB_LIST, k, GNB_CONFIG_STRING_NETWORK_INTERFACES_CONFIG); - GET_PARAMS(NETParams, GNBNETPARAMS_DESC, aprefix); - if (NETParams[GNB_IPV4_ADDRESS_FOR_NG_AMF_IDX].strptr != NULL) { - char *cidr = *(NETParams[GNB_IPV4_ADDRESS_FOR_NG_AMF_IDX].strptr); - char *save = NULL; - char *address = strtok_r(cidr, "/", &save); - strcpy(NGAP_REGISTER_GNB_REQ (msg_p).gnb_ip_address.ipv4_address, address); - LOG_I(GNB_APP, "Parsed IPv4 address for NG AMF: %s\n", address); - } - - NGAP_REGISTER_GNB_REQ (msg_p).gnb_ip_address.ipv6 = 0; - NGAP_REGISTER_GNB_REQ (msg_p).gnb_ip_address.ipv4 = 1; - - break; - } - } - } - } - } - return 0; -} - static pthread_mutex_t rc_mutex = PTHREAD_MUTEX_INITIALIZER; static bool rc_done = false; diff --git a/openair2/GNB_APP/gnb_config.h b/openair2/GNB_APP/gnb_config.h index c33c6964dc..1f48358e67 100644 --- a/openair2/GNB_APP/gnb_config.h +++ b/openair2/GNB_APP/gnb_config.h @@ -44,7 +44,6 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg); void NRRCConfig(void); gNB_RRC_INST *RCconfig_NRRRC(); -int RCconfig_NR_NG(MessageDef *msg_p, uint32_t i); int RCconfig_NR_X2(MessageDef *msg_p, uint32_t i); void wait_f1_setup_response(void); f1ap_tdd_info_t read_tdd_config(const NR_ServingCellConfigCommon_t *scc); diff --git a/openair2/GNB_APP/gnb_config_common.c b/openair2/GNB_APP/gnb_config_common.c new file mode 100644 index 0000000000..ac5e840851 --- /dev/null +++ b/openair2/GNB_APP/gnb_config_common.c @@ -0,0 +1,66 @@ +/* + * 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 "openair2/GNB_APP/gnb_config_common.h" +#include "common/config/config_paramdesc.h" +#include "common/config/config_userapi.h" +#include "RRC_nr_paramsvalues.h" +#include "gnb_paramdef.h" +#include "sctp_default_values.h" + +uint16_t set_snssai_config(nssai_t *nssai, const int max_num_ssi, uint8_t k, uint8_t l) +{ + char snssaistr[MAX_OPTNAME_SIZE * 2 + 8]; + snprintf(snssaistr, sizeof(snssaistr), "%s.[%i].%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, k, GNB_CONFIG_STRING_PLMN_LIST, l); + GET_PARAMS_LIST(SNSSAIParamList, + SNSSAIParams, + GNBSNSSAIPARAMS_DESC, + GNB_CONFIG_STRING_SNSSAI_LIST, + snssaistr, + SNSSAIPARAMS_CHECK); + uint16_t num_ssi = SNSSAIParamList.numelt; + AssertFatal(num_ssi < max_num_ssi, "S-NSSAI size %d exceeds the max array size %d", num_ssi, max_num_ssi); + for (int s = 0; s < num_ssi; ++s) { + nssai[s].sst = *SNSSAIParamList.paramarray[s][GNB_SLICE_SERVICE_TYPE_IDX].uptr; + // SD is optional + // 0xffffff is "no SD", see 23.003 Sec 28.4.2 + nssai[s].sd = *SNSSAIParamList.paramarray[s][GNB_SLICE_DIFFERENTIATOR_IDX].uptr; + AssertFatal(nssai[s].sd <= 0xffffff, "SD cannot be bigger than 0xffffff, but is %d\n", nssai[s].sd); + } + return num_ssi; +} + +uint8_t set_plmn_config(plmn_id_t *p, uint8_t idx) +{ + char gnbpath[MAX_OPTNAME_SIZE * 2 + 8]; + snprintf(gnbpath, sizeof(gnbpath), "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, idx); + GET_PARAMS_LIST(PLMNParamList, PLMNParams, GNBPLMNPARAMS_DESC, GNB_CONFIG_STRING_PLMN_LIST, gnbpath, PLMNPARAMS_CHECK); + uint8_t num_plmn = PLMNParamList.numelt; + AssertFatal(num_plmn >= 1 && num_plmn <= 6, "The number of PLMN IDs must be in [1,6], but is %d\n", num_plmn); + for (int l = 0; l < num_plmn; ++l) { + plmn_id_t *plmn = &p[l]; + 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; + AssertFatal((plmn->mnc_digit_length == 2) || (plmn->mnc_digit_length == 3), "BAD MNC DIGIT LENGTH %d", plmn->mnc_digit_length); + } + return num_plmn; +} diff --git a/openair2/GNB_APP/gnb_config_common.h b/openair2/GNB_APP/gnb_config_common.h new file mode 100644 index 0000000000..8317709a78 --- /dev/null +++ b/openair2/GNB_APP/gnb_config_common.h @@ -0,0 +1,26 @@ +/* + * 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 "common/5g_platform_types.h" + +uint16_t set_snssai_config(nssai_t *nssai, const int max_num_ssi, uint8_t k, uint8_t l); +uint8_t set_plmn_config(plmn_id_t *p, uint8_t idx); diff --git a/openair2/GNB_APP/gnb_config_ng.c b/openair2/GNB_APP/gnb_config_ng.c new file mode 100644 index 0000000000..632c670def --- /dev/null +++ b/openair2/GNB_APP/gnb_config_ng.c @@ -0,0 +1,162 @@ +/* + * 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 "gnb_config_ng.h" +#include +#include "assertions.h" +#include "common/ran_context.h" +#include "openair2/GNB_APP/gnb_config_common.h" +#include "common/config/config_paramdesc.h" +#include "sctp_default_values.h" +#include "gnb_paramdef.h" + +int RCconfig_NR_NG(MessageDef *msg_p, uint32_t i) +{ + int j, k = 0; + int gnb_id; + + char *gnb_ipv4_address_for_NGU = NULL; + uint32_t gnb_port_for_NGU = 0; + char *gnb_ipv4_address_for_S1U = NULL; + uint32_t gnb_port_for_S1U = 0; + + GET_PARAMS(GNBSParams, GNBSPARAMS_DESC, NULL); + AssertFatal(i < GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt, + "Failed to parse config file %s, %uth attribute %s \n", + RC.config_file_name, + i, + GNB_CONFIG_STRING_ACTIVE_GNBS); + + if (GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt > 0) { + // Output a list of all gNBs. + GET_PARAMS_LIST(GNBParamList, GNBParams, GNBPARAMS_DESC, GNB_CONFIG_STRING_GNB_LIST, NULL); + if (GNBParamList.numelt > 0) { + for (k = 0; k < GNBParamList.numelt; k++) { + if (GNBParamList.paramarray[k][GNB_GNB_ID_IDX].uptr == NULL) { + // Calculate a default gNB ID + if (IS_SA_MODE(get_softmodem_params())) { + uint32_t hash; + + hash = ngap_generate_gNB_id(); + gnb_id = k + (hash & 0xFFFFFF8); + } else { + gnb_id = k; + } + } else { + gnb_id = *(GNBParamList.paramarray[k][GNB_GNB_ID_IDX].uptr); + } + + // search if in active list + for (j = 0; j < GNBSParams[GNB_ACTIVE_GNBS_IDX].numelt; j++) { + if (strcmp(GNBSParams[GNB_ACTIVE_GNBS_IDX].strlistptr[j], *(GNBParamList.paramarray[k][GNB_GNB_NAME_IDX].strptr)) == 0) { + char aprefix[MAX_OPTNAME_SIZE * 2 + 8]; + NGAP_REGISTER_GNB_REQ(msg_p).gNB_id = gnb_id; + + if (strcmp(*(GNBParamList.paramarray[k][GNB_CELL_TYPE_IDX].strptr), "CELL_MACRO_GNB") == 0) { + NGAP_REGISTER_GNB_REQ(msg_p).cell_type = CELL_MACRO_GNB; + } else if (strcmp(*(GNBParamList.paramarray[k][GNB_CELL_TYPE_IDX].strptr), "CELL_HOME_GNB") == 0) { + NGAP_REGISTER_GNB_REQ(msg_p).cell_type = CELL_HOME_ENB; + } else { + AssertFatal(0, + "Failed to parse gNB configuration file %s, gnb %u unknown value \"%s\" for cell_type choice: " + "CELL_MACRO_GNB or CELL_HOME_GNB !\n", + RC.config_file_name, + i, + *(GNBParamList.paramarray[k][GNB_CELL_TYPE_IDX].strptr)); + } + + NGAP_REGISTER_GNB_REQ(msg_p).gNB_name = strdup(*(GNBParamList.paramarray[k][GNB_GNB_NAME_IDX].strptr)); + NGAP_REGISTER_GNB_REQ(msg_p).tac = *GNBParamList.paramarray[k][GNB_TRACKING_AREA_CODE_IDX].uptr; + AssertFatal(!GNBParamList.paramarray[k][GNB_MOBILE_COUNTRY_CODE_IDX_OLD].strptr + && !GNBParamList.paramarray[k][GNB_MOBILE_NETWORK_CODE_IDX_OLD].strptr, + "It seems that you use an old configuration file. Please change the existing\n" + " tracking_area_code = \"1\";\n" + " mobile_country_code = \"208\";\n" + " mobile_network_code = \"93\";\n" + "to\n" + " tracking_area_code = 1; // no string!!\n" + " plmn_list = ( { mcc = 208; mnc = 93; mnc_length = 2; } )\n"); + // PLMN + plmn_id_t p[PLMN_LIST_MAX_SIZE] = {0}; + NGAP_REGISTER_GNB_REQ(msg_p).num_plmn = set_plmn_config(p, 0); + for (int l = 0; l < NGAP_REGISTER_GNB_REQ(msg_p).num_plmn; ++l) { + NGAP_REGISTER_GNB_REQ(msg_p).plmn[l].plmn = p[l]; + // SNSSAI + NGAP_REGISTER_GNB_REQ(msg_p).plmn[l].num_nssai = + set_snssai_config(NGAP_REGISTER_GNB_REQ(msg_p).plmn[l].s_nssai, 8, k, l); + } + NGAP_REGISTER_GNB_REQ(msg_p).default_drx = 0; + // NG + snprintf(aprefix, sizeof(aprefix), "%s.[%i]", GNB_CONFIG_STRING_GNB_LIST, k); + GET_PARAMS_LIST(NGParamList, NGParams, GNBNGPARAMS_DESC, GNB_CONFIG_STRING_AMF_IP_ADDRESS, aprefix); + NGAP_REGISTER_GNB_REQ(msg_p).nb_amf = 0; + + for (int l = 0; l < NGParamList.numelt; l++) { + NGAP_REGISTER_GNB_REQ(msg_p).nb_amf += 1; + strcpy(NGAP_REGISTER_GNB_REQ(msg_p).amf_ip_address[l].ipv4_address, + *(NGParamList.paramarray[l][GNB_AMF_IPV4_ADDRESS_IDX].strptr)); + NGAP_REGISTER_GNB_REQ(msg_p).amf_ip_address[l].ipv4 = 1; + NGAP_REGISTER_GNB_REQ(msg_p).amf_ip_address[l].ipv6 = 0; + /* if no broadcasst_plmn array is defined, fill default values */ + if (NGAP_REGISTER_GNB_REQ(msg_p).broadcast_plmn_num[l] == 0) { + NGAP_REGISTER_GNB_REQ(msg_p).broadcast_plmn_num[l] = NGAP_REGISTER_GNB_REQ(msg_p).num_plmn; + for (int el = 0; el < NGAP_REGISTER_GNB_REQ(msg_p).num_plmn; ++el) + NGAP_REGISTER_GNB_REQ(msg_p).broadcast_plmn_index[l][el] = el; + } + } + + // SCTP SETTING + NGAP_REGISTER_GNB_REQ(msg_p).sctp_out_streams = SCTP_OUT_STREAMS; + NGAP_REGISTER_GNB_REQ(msg_p).sctp_in_streams = SCTP_IN_STREAMS; + if (IS_SA_MODE(get_softmodem_params())) { + snprintf(aprefix, sizeof(aprefix), "%s.[%d].%s", GNB_CONFIG_STRING_GNB_LIST, k, GNB_CONFIG_STRING_SCTP_CONFIG); + GET_PARAMS(SCTPParams, GNBSCTPPARAMS_DESC, aprefix); + NGAP_REGISTER_GNB_REQ(msg_p).sctp_in_streams = (uint16_t) * (SCTPParams[GNB_SCTP_INSTREAMS_IDX].uptr); + NGAP_REGISTER_GNB_REQ(msg_p).sctp_out_streams = (uint16_t) * (SCTPParams[GNB_SCTP_OUTSTREAMS_IDX].uptr); + } + + // NETWORK_INTERFACES + snprintf(aprefix, + sizeof(aprefix), + "%s.[%d].%s", + GNB_CONFIG_STRING_GNB_LIST, + k, + GNB_CONFIG_STRING_NETWORK_INTERFACES_CONFIG); + GET_PARAMS(NETParams, GNBNETPARAMS_DESC, aprefix); + if (NETParams[GNB_IPV4_ADDRESS_FOR_NG_AMF_IDX].strptr != NULL) { + char *cidr = *(NETParams[GNB_IPV4_ADDRESS_FOR_NG_AMF_IDX].strptr); + char *save = NULL; + char *address = strtok_r(cidr, "/", &save); + strcpy(NGAP_REGISTER_GNB_REQ(msg_p).gnb_ip_address.ipv4_address, address); + LOG_I(GNB_APP, "Parsed IPv4 address for NG AMF: %s\n", address); + } + + NGAP_REGISTER_GNB_REQ(msg_p).gnb_ip_address.ipv6 = 0; + NGAP_REGISTER_GNB_REQ(msg_p).gnb_ip_address.ipv4 = 1; + + break; + } + } + } + } + } + return 0; +} diff --git a/openair2/GNB_APP/gnb_config_ng.h b/openair2/GNB_APP/gnb_config_ng.h new file mode 100644 index 0000000000..792f55e940 --- /dev/null +++ b/openair2/GNB_APP/gnb_config_ng.h @@ -0,0 +1,29 @@ +/* + * 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 NGAP_GNB_CONFIG_H_ +#define NGAP_GNB_CONFIG_H_ +#include +#include "intertask_interface.h" + +int RCconfig_NR_NG(MessageDef *msg_p, uint32_t i); + +#endif /* NGAP_GNB_CONFIG_H_ */ From 786d8b34c09f7424f78343b218a4859ba30470d8 Mon Sep 17 00:00:00 2001 From: Rakesh Mundlamuri Date: Mon, 29 Dec 2025 13:33:45 +0530 Subject: [PATCH 02/21] Introduce NGAP emulator that connects to the AMF to perform NGAP enc/dec - Performs NGAP setup request and handles NGAP setup response - This is introduced to test NGAP enc/dec of the NRPPa messages To compile: openairinterface5g$ mkdir build openairinterface5g$ cd build openairinterface5g/build$ cmake .. -GNinja openairinterface5g/build$ ninja nr-cu-nrppa-test To run: openairinterface5g/build$ LD_LIBRARY_PATH=. ./tests/nr-cu-nrppa/nr-cu-nrppa-test -O ../tests/nr-cu-nrppa/nr-nrppa-test.conf --- tests/CMakeLists.txt | 1 + tests/nr-cu-nrppa/CMakeLists.txt | 10 +++ tests/nr-cu-nrppa/nr-cu-nrppa.c | 99 ++++++++++++++++++++++++++++ tests/nr-cu-nrppa/nr-nrppa-test.conf | 52 +++++++++++++++ 4 files changed, 162 insertions(+) create mode 100644 tests/nr-cu-nrppa/CMakeLists.txt create mode 100644 tests/nr-cu-nrppa/nr-cu-nrppa.c create mode 100644 tests/nr-cu-nrppa/nr-nrppa-test.conf diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index cefa52d456..63d036a83c 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1 +1,2 @@ add_subdirectory(nr-cuup) +add_subdirectory(nr-cu-nrppa) diff --git a/tests/nr-cu-nrppa/CMakeLists.txt b/tests/nr-cu-nrppa/CMakeLists.txt new file mode 100644 index 0000000000..1db9b33e37 --- /dev/null +++ b/tests/nr-cu-nrppa/CMakeLists.txt @@ -0,0 +1,10 @@ +add_executable(nr-cu-nrppa-test nr-cu-nrppa.c + ${OPENAIR2_DIR}/GNB_APP/gnb_config_common.c + ${OPENAIR2_DIR}/GNB_APP/gnb_config_ng.c) + +target_link_libraries(nr-cu-nrppa-test PRIVATE + CONFIG_LIB ITTI SCTP_CLIENT + f1ap ngap SECURITY + UTIL softmodem_common) +target_link_libraries(nr-cu-nrppa-test PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) +add_dependencies(nr-cu-nrppa-test params_libconfig) diff --git a/tests/nr-cu-nrppa/nr-cu-nrppa.c b/tests/nr-cu-nrppa/nr-cu-nrppa.c new file mode 100644 index 0000000000..1436b7cd27 --- /dev/null +++ b/tests/nr-cu-nrppa/nr-cu-nrppa.c @@ -0,0 +1,99 @@ +/* + * 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 "executables/softmodem-common.h" +#include "common/utils/ocp_itti/intertask_interface.h" +#include "common/ran_context.h" +#include "nfapi/oai_integration/vendor_ext.h" +#include "openair2/GNB_APP/gnb_config_common.h" +#include "openair2/GNB_APP/gnb_config_ng.h" +#include "openair2/GNB_APP/gnb_paramdef.h" +#include "openair3/SCTP/sctp_default_values.h" + +RAN_CONTEXT_t RC; +THREAD_STRUCT thread_struct; +uint64_t downlink_frequency[MAX_NUM_CCs][4]; +int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; +int oai_exit = 0; +int gnb_id; + +void exit_function(const char *file, const char *function, const int line, const char *s, const int assert) +{ + if (assert) { + abort(); + } else { + sleep(1); // allow other threads to exit first + exit(EXIT_SUCCESS); + } +} + +nfapi_mode_t nfapi_mod = -1; +void nfapi_setmode(nfapi_mode_t nfapi_mode) +{ + nfapi_mod = nfapi_mode; +} +nfapi_mode_t nfapi_getmode(void) +{ + return nfapi_mod; +} + +ngran_node_t get_node_type() +{ + return ngran_gNB_CUUP; +} + +configmodule_interface_t *uniqCfg = NULL; + +int main(int argc, char **argv) +{ + // load the config file + if ((uniqCfg = load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY)) == NULL) { + exit_fun("[SOFTMODEM] Error, configuration module init failed\n"); + } + logInit(); + + set_softmodem_sighandler(); + + // Initialize ITTI tasks + itti_init(TASK_MAX, tasks_info); + + int rc; + rc = itti_create_task(TASK_SCTP, sctp_eNB_task, NULL); + AssertFatal(rc >= 0, "Create task for SCTP failed\n"); + + rc = itti_create_task(TASK_NGAP, ngap_gNB_task, NULL); + AssertFatal(rc >= 0, "Create task for NGAP failed\n"); + + MessageDef *msg_p; + msg_p = itti_alloc_new_message(TASK_GNB_APP, 0, NGAP_REGISTER_GNB_REQ); + RCconfig_NR_NG(msg_p, 0); + gnb_id = NGAP_REGISTER_GNB_REQ(msg_p).gNB_id; + + LOG_I(GNB_APP, "Sending NGAP_REGISTER_GNB_REQ to TASK_NGAP\n"); + itti_send_msg_to_task(TASK_NGAP, 0, msg_p); + + printf("TYPE TO TERMINATE\n"); + itti_wait_tasks_end(NULL); + + logClean(); + printf("Bye.\n"); + return 0; +} diff --git a/tests/nr-cu-nrppa/nr-nrppa-test.conf b/tests/nr-cu-nrppa/nr-nrppa-test.conf new file mode 100644 index 0000000000..f5d6ea673a --- /dev/null +++ b/tests/nr-cu-nrppa/nr-nrppa-test.conf @@ -0,0 +1,52 @@ +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; }) }); + + nr_cellid = 12345678L; + + # ------- 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/24"; + GNB_IPV4_ADDRESS_FOR_NGU = "192.168.70.129/24"; + GNB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + } +); + +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 ="debug"; + f1ap_log_level ="debug"; +}; From dabb8d338f13a9693a518c5b01587cc8136cd88c Mon Sep 17 00:00:00 2001 From: Rakesh Mundlamuri Date: Tue, 3 Feb 2026 12:55:49 +0530 Subject: [PATCH 03/21] Add docker compose file of the 5G core network with the LMF feature --- .../oai-cn5g/conf/config.yaml | 20 ++ .../oai-cn5g/docker-compose-positioning.yaml | 195 ++++++++++++++++++ 2 files changed, 215 insertions(+) create mode 100644 doc/tutorial_resources/oai-cn5g/docker-compose-positioning.yaml diff --git a/doc/tutorial_resources/oai-cn5g/conf/config.yaml b/doc/tutorial_resources/oai-cn5g/conf/config.yaml index f18c965ed1..6e55c95bb3 100644 --- a/doc/tutorial_resources/oai-cn5g/conf/config.yaml +++ b/doc/tutorial_resources/oai-cn5g/conf/config.yaml @@ -100,6 +100,12 @@ nfs: port: 8080 api_version: v1 interface_name: eth0 + lmf: + host: oai-lmf + sbi: + port: 8080 + api_version: v1 + interface_name: eth0 #### Common for UDR and AMF database: @@ -220,6 +226,20 @@ upf: - dnn: "ims" - dnn: "default" +lmf: + http_threads_count: 8 + gnb_id_bits_count: 28 + num_gnb: 1 + trp_info_wait_ms: 500 + positioning_wait_ms: 500 + measurement_wait_ms: 500 + support_features: + request_trp_info: no + determine_num_gnb: yes + use_http2: yes + use_fqdn_dns: no + register_nrf: yes + ## DNN configuration dnns: - dnn: "oai" diff --git a/doc/tutorial_resources/oai-cn5g/docker-compose-positioning.yaml b/doc/tutorial_resources/oai-cn5g/docker-compose-positioning.yaml new file mode 100644 index 0000000000..6b75c22b6b --- /dev/null +++ b/doc/tutorial_resources/oai-cn5g/docker-compose-positioning.yaml @@ -0,0 +1,195 @@ +services: + mysql: + container_name: "mysql" + image: mysql:8.0 + volumes: + - ./database/oai_db.sql:/docker-entrypoint-initdb.d/oai_db.sql + - ./healthscripts/mysql-healthcheck.sh:/tmp/mysql-healthcheck.sh + environment: + - TZ=Europe/Paris + - MYSQL_DATABASE=oai_db + - MYSQL_USER=test + - MYSQL_PASSWORD=test + - MYSQL_ROOT_PASSWORD=linux + healthcheck: + test: /bin/bash -c "/tmp/mysql-healthcheck.sh" + interval: 5s + timeout: 2s + retries: 10 + networks: + public_net: + ipv4_address: 192.168.70.131 + + ims: + container_name: "ims" + image: oaisoftwarealliance/ims:latest + volumes: + - ./conf/sip.conf:/etc/asterisk/sip.conf + - ./conf/users.conf:/etc/asterisk/users.conf + healthcheck: + test: /bin/bash -c "pgrep asterisk" + interval: 5s + timeout: 2s + retries: 10 + networks: + public_net: + ipv4_address: 192.168.70.139 + oai-udr: + container_name: "oai-udr" + image: oaisoftwarealliance/oai-udr:develop + expose: + - 80/tcp + - 8080/tcp + volumes: + - ./conf/config.yaml:/openair-udr/etc/config.yaml + environment: + - TZ=Europe/Paris + depends_on: + - mysql + - oai-nrf + networks: + public_net: + ipv4_address: 192.168.70.136 + oai-udm: + container_name: "oai-udm" + image: oaisoftwarealliance/oai-udm:develop + expose: + - 80/tcp + - 8080/tcp + volumes: + - ./conf/config.yaml:/openair-udm/etc/config.yaml + environment: + - TZ=Europe/Paris + depends_on: + - oai-udr + networks: + public_net: + ipv4_address: 192.168.70.137 + oai-ausf: + container_name: "oai-ausf" + image: oaisoftwarealliance/oai-ausf:develop + expose: + - 80/tcp + - 8080/tcp + volumes: + - ./conf/config.yaml:/openair-ausf/etc/config.yaml + environment: + - TZ=Europe/Paris + depends_on: + - oai-udm + networks: + public_net: + ipv4_address: 192.168.70.138 + oai-nrf: + container_name: "oai-nrf" + image: oaisoftwarealliance/oai-nrf:develop + expose: + - 80/tcp + - 8080/tcp + volumes: + - ./conf/config.yaml:/openair-nrf/etc/config.yaml + environment: + - TZ=Europe/Paris + networks: + public_net: + ipv4_address: 192.168.70.130 + oai-amf: + container_name: "oai-amf" + image: oaisoftwarealliance/oai-amf:develop + expose: + - 80/tcp + - 8080/tcp + - 38412/sctp + volumes: + - ./conf/config.yaml:/openair-amf/etc/config.yaml + environment: + - TZ=Europe/Paris + depends_on: + - mysql + - oai-nrf + - oai-ausf + networks: + public_net: + ipv4_address: 192.168.70.132 + oai-lmf: + container_name: "oai-lmf" + image: oaisoftwarealliance/oai-lmf:develop + #image: oai-lmf:psoElementwiseTdoAmeanVarTDoAfilter + expose: + - 80/tcp + - 8080/tcp + volumes: + - ./conf/config.yaml:/openair-lmf/etc/config.yaml + environment: + - TZ=Europe/Paris + depends_on: + - mysql + - oai-nrf + - oai-amf + networks: + public_net: + ipv4_address: 192.168.70.141 + oai-smf: + container_name: "oai-smf" + image: oaisoftwarealliance/oai-smf:develop + expose: + - 80/tcp + - 8080/tcp + - 8805/udp + volumes: + - ./conf/config.yaml:/openair-smf/etc/config.yaml + environment: + - TZ=Europe/Paris + depends_on: + - oai-nrf + - oai-amf + networks: + public_net: + ipv4_address: 192.168.70.133 + oai-upf: + container_name: "oai-upf" + image: oaisoftwarealliance/oai-upf:develop + expose: + - 2152/udp + - 8805/udp + volumes: + - ./conf/config.yaml:/openair-upf/etc/config.yaml + environment: + - TZ=Europe/Paris + depends_on: + - oai-nrf + - oai-smf + cap_add: + - NET_ADMIN + - SYS_ADMIN + cap_drop: + - ALL + privileged: true + networks: + public_net: + ipv4_address: 192.168.70.134 + oai-ext-dn: + privileged: true + init: true + container_name: oai-ext-dn + image: oaisoftwarealliance/trf-gen-cn5g:jammy + entrypoint: /bin/bash -c \ + "ip route add 10.0.0.0/16 via 192.168.70.134 dev eth0; ip route; sleep infinity" + command: ["/bin/bash", "-c", "trap : SIGTERM SIGINT; sleep infinity & wait"] + healthcheck: + test: /bin/bash -c "ip r | grep 10.0.0" + interval: 5s + timeout: 2s + retries: 10 + networks: + public_net: + ipv4_address: 192.168.70.135 +networks: + public_net: + driver: bridge + name: oai-cn5g-public-net + ipam: + config: + - subnet: 192.168.70.128/26 + driver_opts: + com.docker.network.bridge.name: "oai-cn5g" From 08d7a150b11528b55263e8206b336d2e7b6b1238 Mon Sep 17 00:00:00 2001 From: Rakesh Mundlamuri Date: Sun, 1 Feb 2026 19:01:15 +0530 Subject: [PATCH 04/21] Add json file to initiate positioning procedure from the LMF --- .../positioning/InputData.json | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 doc/tutorial_resources/positioning/InputData.json diff --git a/doc/tutorial_resources/positioning/InputData.json b/doc/tutorial_resources/positioning/InputData.json new file mode 100644 index 0000000000..0caebbabba --- /dev/null +++ b/doc/tutorial_resources/positioning/InputData.json @@ -0,0 +1,43 @@ +{ + "externalClientType": "VALUE_ADDED_SERVICES", + "amfId": "128:1:1", + "locationQoS": { + "hAccuracy": 1.5, + "vAccuracy": 1.5, + "verticalRequested": true, + "responseTime": "LOW_DELAY", + "lcsQosClass": "BEST_EFFORT" + }, + "supportedGADShapes": [ + "POINT", + "POINT_UNCERTAINTY_CIRCLE" + ], + "supi": "imsi-001010000000001", + "ncgi": { + "plmnId": { + "mcc": "001", + "mnc": "01" + }, + "nrCellId": "14680064", + "nid": "0" + }, + "priority": "HIGHEST_PRIORITY", + "velocityRequested": "VELOCITY_IS_NOT_REQUESTED", + "lcsServiceType": 127, + "ldrType": "UE_AVAILABLE", + "hgmlcCallBackURI": "198.168.70.129", + "ldrReference": "11", + "lirReference": "1", + "periodicEventInfo": { + "reportingAmount": 10, + "reportingInterval": 60 + }, + "reportingAccessTypes": [ + "NR", + "NON_3GPP_CONNECTED_TO_5GC" + ], + "ueConnectivityStates": { + "accessType": "3GPP_ACCESS", + "connectivitystate": "IDLE" + } +} From bf90e523a75aaab51fff92f6c584df2c7c695dbb Mon Sep 17 00:00:00 2001 From: Rakesh Mundlamuri Date: Mon, 29 Dec 2025 16:07:23 +0530 Subject: [PATCH 05/21] Add NGAP UPLINK UE ASSOCIATED NRPPA TRANSPORT message encoding Reference: 3GPP 38.413 v16.0.0 Mandatory fields: AMF UE NGAP ID (supported) RAN UE NGAP ID (supported) Routing ID (supported) NRPPa-PDU (supported) --- CMakeLists.txt | 1 + openair2/COMMON/ngap_messages_types.h | 12 ++ .../ngap_gNB_NRPPa_transport_procedures.c | 129 ++++++++++++++++++ .../ngap_gNB_NRPPa_transport_procedures.h | 28 ++++ 4 files changed, 170 insertions(+) create mode 100644 openair3/NGAP/ngap_gNB_NRPPa_transport_procedures.c create mode 100644 openair3/NGAP/ngap_gNB_NRPPa_transport_procedures.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 0f2e8931a3..94209f6453 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -441,6 +441,7 @@ add_library(ngap ${NGAP_DIR}/ngap_gNB_overload.c ${NGAP_DIR}/ngap_gNB_trace.c ${NGAP_DIR}/ngap_gNB_ue_context.c + ${NGAP_DIR}/ngap_gNB_NRPPa_transport_procedures.c ) target_link_libraries(ngap PUBLIC asn1_ngap) target_link_libraries(ngap PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h index 02069d056e..e40c1059d0 100644 --- a/openair2/COMMON/ngap_messages_types.h +++ b/openair2/COMMON/ngap_messages_types.h @@ -1007,4 +1007,16 @@ typedef struct { ngap_ran_status_container_t ran_status; } ngap_ran_status_transfer_t; +// Uplink UE Associated NRPPA Transport message (9.2.9.2 3GPP 38.413 v16.0.0) +typedef struct { + // AMF UE NGAP ID (Mandatory) + uint64_t amf_ue_ngap_id; + // RAN UE NGAP ID (Mandatory) + uint32_t gNB_ue_ngap_id; + // Routing ID (Mandatory) + byte_array_t routing_id; + // NRPPa pdu (Mandatory) + byte_array_t nrppa_pdu; +} ngap_uplink_ue_associated_nrppa_t; + #endif /* NGAP_MESSAGES_TYPES_H_ */ diff --git a/openair3/NGAP/ngap_gNB_NRPPa_transport_procedures.c b/openair3/NGAP/ngap_gNB_NRPPa_transport_procedures.c new file mode 100644 index 0000000000..d799057ca5 --- /dev/null +++ b/openair3/NGAP/ngap_gNB_NRPPa_transport_procedures.c @@ -0,0 +1,129 @@ +/* + * 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 "assertions.h" +#include "conversions.h" + +#include "intertask_interface.h" + +#include "ngap_common.h" +#include "ngap_gNB_defs.h" +#include "ngap_gNB_itti_messaging.h" +#include "ngap_gNB_encoder.h" +#include "ngap_gNB_nnsf.h" +#include "ngap_gNB_ue_context.h" +#include "ngap_gNB_management_procedures.h" + +#include "ngap_gNB_NRPPa_transport_procedures.h" + +// UPLINK UE ASSOCIATED NRPPA TRANSPORT (9.2.9.2 of TS 38.413 Version 16.0.0) +int ngap_gNB_uplink_ue_associated_nrppa_transport(instance_t instance, const ngap_uplink_ue_associated_nrppa_t *msg) +{ + LOG_I(NGAP, "Initiating ngap_gNB_uplink_ue_associated_nrppa_transport \n"); + DevAssert(msg != NULL); + DevAssert(msg->routing_id.buf); + DevAssert(msg->routing_id.len); + DevAssert(msg->nrppa_pdu.buf); + DevAssert(msg->nrppa_pdu.len); + struct ngap_gNB_ue_context_s *ue_context_p = NULL; + ngap_gNB_instance_t *ngap_gNB_instance_p = NULL; + + // Retrieve the NGAP gNB instance associated with Mod_id + ngap_gNB_instance_p = ngap_gNB_get_instance(instance); + DevAssert(ngap_gNB_instance_p != NULL); + + if ((ue_context_p = ngap_get_ue_context(msg->gNB_ue_ngap_id)) == NULL) { + // The context for this gNB ue ngap id doesn't exist in the map of gNB UEs + LOG_E(NGAP, "Failed to find ue context associated with gNB ue ngap id: %08x\n", msg->gNB_ue_ngap_id); + return -1; + } + /* Prepare the NGAP message to encode */ + NGAP_NGAP_PDU_t pdu = {0}; + + // IE: 9.3.1.1 Message Type UplinkUEAssociatedNRPPaTransport + pdu.present = NGAP_NGAP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu.choice.initiatingMessage, head); + head->procedureCode = NGAP_ProcedureCode_id_UplinkUEAssociatedNRPPaTransport; + head->criticality = NGAP_Criticality_ignore; + head->value.present = NGAP_InitiatingMessage__value_PR_UplinkUEAssociatedNRPPaTransport; + NGAP_UplinkUEAssociatedNRPPaTransport_t *out = &head->value.choice.UplinkUEAssociatedNRPPaTransport; + + // IE: 9.3.3.1 AMF UE NGAP ID (mandatory) + { + asn1cSequenceAdd(out->protocolIEs.list, NGAP_UplinkUEAssociatedNRPPaTransportIEs_t, ie); + ie->id = NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID; + ie->criticality = NGAP_Criticality_reject; + ie->value.present = NGAP_UplinkUEAssociatedNRPPaTransportIEs__value_PR_AMF_UE_NGAP_ID; + asn_uint642INTEGER(&ie->value.choice.AMF_UE_NGAP_ID, msg->amf_ue_ngap_id); + } + + // IE: 9.3.3.2 RAN UE NGAP ID (mandatory) + { + asn1cSequenceAdd(out->protocolIEs.list, NGAP_UplinkUEAssociatedNRPPaTransportIEs_t, ie); + ie->id = NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID; + ie->criticality = NGAP_Criticality_reject; + ie->value.present = NGAP_UplinkUEAssociatedNRPPaTransportIEs__value_PR_RAN_UE_NGAP_ID; + ie->value.choice.RAN_UE_NGAP_ID = msg->gNB_ue_ngap_id; + } + + // IE: 9.3.3.13 Routing ID (mandatory) + { + asn1cSequenceAdd(out->protocolIEs.list, NGAP_UplinkUEAssociatedNRPPaTransportIEs_t, ie); + ie->id = NGAP_ProtocolIE_ID_id_RoutingID; + ie->criticality = NGAP_Criticality_reject; + ie->value.present = NGAP_UplinkUEAssociatedNRPPaTransportIEs__value_PR_RoutingID; + ie->value.choice.RoutingID.buf = msg->routing_id.buf; + ie->value.choice.RoutingID.size = msg->routing_id.len; + } + + // IE: 9.3.3.14 NRPPa-PDU (mandatory) + { + asn1cSequenceAdd(out->protocolIEs.list, NGAP_UplinkUEAssociatedNRPPaTransportIEs_t, ie); + ie->id = NGAP_ProtocolIE_ID_id_NRPPa_PDU; + ie->criticality = NGAP_Criticality_reject; + ie->value.present = NGAP_UplinkUEAssociatedNRPPaTransportIEs__value_PR_NRPPa_PDU; + ie->value.choice.NRPPa_PDU.buf = msg->nrppa_pdu.buf; + ie->value.choice.NRPPa_PDU.size = msg->nrppa_pdu.len; + } + + // Encode NGAP message + uint8_t *buffer = NULL; + uint32_t length = 0; + if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) { + LOG_E(NGAP, "Failed to encode Uplink UE Associated NRPPa Transport\n"); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); + return -1; + } + LOG_I(NGAP, "Sending ngap_gNB_uplink_ue_associated_nrppa_transport over SCTP\n"); + + // UE associated signalling -> use the allocated stream + ngap_gNB_itti_send_sctp_data_req(ngap_gNB_instance_p->instance, + ue_context_p->amf_ref->assoc_id, + buffer, + length, + ue_context_p->tx_stream); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); + return 0; +} diff --git a/openair3/NGAP/ngap_gNB_NRPPa_transport_procedures.h b/openair3/NGAP/ngap_gNB_NRPPa_transport_procedures.h new file mode 100644 index 0000000000..ed136bfce8 --- /dev/null +++ b/openair3/NGAP/ngap_gNB_NRPPa_transport_procedures.h @@ -0,0 +1,28 @@ +/* + * 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 NGAP_GNB_NRPPA_PROCEDURES_H_ +#define NGAP_GNB_NRPPA_PROCEDURES_H_ + +// UPLINK UE ASSOCIATED NRPPA TRANSPORT (9.2.9.2 of TS 38.413 Version 16.0.0) +int ngap_gNB_uplink_ue_associated_nrppa_transport(instance_t instance, const ngap_uplink_ue_associated_nrppa_t *msg); + +#endif /* NGAP_GNB_NRPPA_PROCEDURES_H_ */ From e832424240bd7ddc6dce0e6aead4e73ff50cdc8c Mon Sep 17 00:00:00 2001 From: Rakesh Mundlamuri Date: Mon, 29 Dec 2025 17:01:15 +0530 Subject: [PATCH 06/21] Add NGAP UPLINK NON UE ASSOCIATED NRPPA TRANSPORT message encoding Reference: 3GPP 38.413 v16.0.0 Mandatory fields: Routing ID (supported) NRPPa-PDU (supported) --- openair2/COMMON/ngap_messages_types.h | 8 +++ .../ngap_gNB_NRPPa_transport_procedures.c | 67 +++++++++++++++++++ .../ngap_gNB_NRPPa_transport_procedures.h | 3 + 3 files changed, 78 insertions(+) diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h index e40c1059d0..c47a564acb 100644 --- a/openair2/COMMON/ngap_messages_types.h +++ b/openair2/COMMON/ngap_messages_types.h @@ -1019,4 +1019,12 @@ typedef struct { byte_array_t nrppa_pdu; } ngap_uplink_ue_associated_nrppa_t; +// Uplink NON UE Associated NRPPA Transport message (9.2.9.4 3GPP 38.413 v16.0.0) +typedef struct { + // Routing ID (Mandatory) + byte_array_t routing_id; + // NRPPa pdu (Mandatory) + byte_array_t nrppa_pdu; +} ngap_uplink_non_ue_associated_nrppa_t; + #endif /* NGAP_MESSAGES_TYPES_H_ */ diff --git a/openair3/NGAP/ngap_gNB_NRPPa_transport_procedures.c b/openair3/NGAP/ngap_gNB_NRPPa_transport_procedures.c index d799057ca5..56a85be44c 100644 --- a/openair3/NGAP/ngap_gNB_NRPPa_transport_procedures.c +++ b/openair3/NGAP/ngap_gNB_NRPPa_transport_procedures.c @@ -127,3 +127,70 @@ int ngap_gNB_uplink_ue_associated_nrppa_transport(instance_t instance, const nga ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); return 0; } + +// UPLINK NON UE ASSOCIATED NRPPA TRANSPORT (9.2.9.4 of TS 38.413 Version 16.0.0) +int ngap_gNB_uplink_non_ue_associated_nrppa_transport(instance_t instance, const ngap_uplink_non_ue_associated_nrppa_t *msg) +{ + LOG_I(NGAP, "ngap_gNB_uplink_non_ue_associated_nrppa_transport\n"); + DevAssert(msg != NULL); + DevAssert(msg->routing_id.buf); + DevAssert(msg->routing_id.len); + DevAssert(msg->nrppa_pdu.buf); + DevAssert(msg->nrppa_pdu.len); + + // Retrieve the NGAP gNB instance associated with Mod_id + ngap_gNB_instance_t *ngap_gNB_instance_p = NULL; + ngap_gNB_instance_p = ngap_gNB_get_instance(instance); + DevAssert(ngap_gNB_instance_p != NULL); + + // Retrieve the NGAP gNB amf data + ngap_gNB_amf_data_t *amf_desc_p = NULL; + amf_desc_p = ngap_gNB_get_AMF_from_instance(ngap_gNB_instance_p); + DevAssert(amf_desc_p != NULL); + + // Prepare the NGAP message to encode + NGAP_NGAP_PDU_t pdu = {0}; + + // IE: 9.3.1.1 Message Type UplinkNonUEAssociatedNRPPaTransport + pdu.present = NGAP_NGAP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu.choice.initiatingMessage, head); + head->procedureCode = NGAP_ProcedureCode_id_UplinkNonUEAssociatedNRPPaTransport; + head->criticality = NGAP_Criticality_ignore; + head->value.present = NGAP_InitiatingMessage__value_PR_UplinkNonUEAssociatedNRPPaTransport; + NGAP_UplinkNonUEAssociatedNRPPaTransport_t *out = &head->value.choice.UplinkNonUEAssociatedNRPPaTransport; + + // IE: 9.3.3.13 Routing ID (mandatory) + { + asn1cSequenceAdd(out->protocolIEs.list, NGAP_UplinkNonUEAssociatedNRPPaTransportIEs_t, ie); + ie->id = NGAP_ProtocolIE_ID_id_RoutingID; + ie->criticality = NGAP_Criticality_reject; + ie->value.present = NGAP_UplinkNonUEAssociatedNRPPaTransportIEs__value_PR_RoutingID; + ie->value.choice.RoutingID.buf = msg->routing_id.buf; + ie->value.choice.RoutingID.size = msg->routing_id.len; + } + + // IE: 9.3.3.14 NRPPa-PDU (mandatory) + { + asn1cSequenceAdd(out->protocolIEs.list, NGAP_UplinkNonUEAssociatedNRPPaTransportIEs_t, ie); + ie->id = NGAP_ProtocolIE_ID_id_NRPPa_PDU; + ie->criticality = NGAP_Criticality_reject; + ie->value.present = NGAP_UplinkNonUEAssociatedNRPPaTransportIEs__value_PR_NRPPa_PDU; + ie->value.choice.NRPPa_PDU.buf = msg->nrppa_pdu.buf; + ie->value.choice.NRPPa_PDU.size = msg->nrppa_pdu.len; + } + + // Encode NGAP message + uint8_t *buffer = NULL; + uint32_t length = 0; + if (ngap_gNB_encode_pdu(&pdu, &buffer, &length) < 0) { + LOG_E(NGAP, "Failed to encode Uplink Non UE Associated NRPPa Transport\n"); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); + return -1; + } + + // Non UE-Associated signalling -> stream = 0 + LOG_I(NGAP, "Sending ngap_gNB_uplink_non_ue_associated_nrppa_transport over SCTP (assoc_id %d)\n", amf_desc_p->assoc_id); + ngap_gNB_itti_send_sctp_data_req(ngap_gNB_instance_p->instance, amf_desc_p->assoc_id, buffer, length, 0); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); + return 0; +} diff --git a/openair3/NGAP/ngap_gNB_NRPPa_transport_procedures.h b/openair3/NGAP/ngap_gNB_NRPPa_transport_procedures.h index ed136bfce8..2624bee0a4 100644 --- a/openair3/NGAP/ngap_gNB_NRPPa_transport_procedures.h +++ b/openair3/NGAP/ngap_gNB_NRPPa_transport_procedures.h @@ -25,4 +25,7 @@ // UPLINK UE ASSOCIATED NRPPA TRANSPORT (9.2.9.2 of TS 38.413 Version 16.0.0) int ngap_gNB_uplink_ue_associated_nrppa_transport(instance_t instance, const ngap_uplink_ue_associated_nrppa_t *msg); +// UPLINK NON UE ASSOCIATED NRPPA TRANSPORT (9.2.9.4 of TS 38.413 Version 16.0.0) +int ngap_gNB_uplink_non_ue_associated_nrppa_transport(instance_t instance, const ngap_uplink_non_ue_associated_nrppa_t *msg); + #endif /* NGAP_GNB_NRPPA_PROCEDURES_H_ */ From d4c0431cc7e020ed06383451181d39288692a480 Mon Sep 17 00:00:00 2001 From: Rakesh Mundlamuri Date: Mon, 29 Dec 2025 18:22:46 +0530 Subject: [PATCH 07/21] Add NGAP DOWNLINK UE ASSOCIATED NRPPA TRANSPORT message decoding Reference: 3GPP 38.413 v16.0.0 Mandatory fields: AMF UE NGAP ID (supported) RAN UE NGAP ID (supported) Routing ID (supported) NRPPa-PDU (supported) --- common/utils/ocp_itti/intertask_interface.h | 1 + openair2/COMMON/ngap_messages_def.h | 6 ++ openair2/COMMON/ngap_messages_types.h | 13 +++ .../ngap_gNB_NRPPa_transport_procedures.c | 81 +++++++++++++++++++ .../ngap_gNB_NRPPa_transport_procedures.h | 3 + 5 files changed, 104 insertions(+) diff --git a/common/utils/ocp_itti/intertask_interface.h b/common/utils/ocp_itti/intertask_interface.h index d23e62365d..7580698dcf 100644 --- a/common/utils/ocp_itti/intertask_interface.h +++ b/common/utils/ocp_itti/intertask_interface.h @@ -294,6 +294,7 @@ typedef struct { TASK_DEF(TASK_RAL_ENB, 200) \ TASK_DEF(TASK_S1AP, 200) \ TASK_DEF(TASK_NGAP, 200) \ + TASK_DEF(TASK_NRPPA, 200) \ TASK_DEF(TASK_X2AP, 200) \ TASK_DEF(TASK_M2AP_ENB, 200) \ TASK_DEF(TASK_M2AP_MCE, 200) \ diff --git a/openair2/COMMON/ngap_messages_def.h b/openair2/COMMON/ngap_messages_def.h index 09e893f874..95d29baab2 100644 --- a/openair2/COMMON/ngap_messages_def.h +++ b/openair2/COMMON/ngap_messages_def.h @@ -88,3 +88,9 @@ MESSAGE_DEF(NGAP_HANDOVER_CANCEL_ACK, MESSAGE_PRIORITY_MED, ngap_handover_cancel /* NGAP <-> RRC messages (can be initiated either by MME or gNB) */ MESSAGE_DEF(NGAP_UE_CONTEXT_RELEASE_REQ , MESSAGE_PRIORITY_MED, ngap_ue_release_req_t , ngap_ue_release_req) + +/* NGAP -> NRPPA messages*/ +MESSAGE_DEF(NGAP_DOWNLINKUEASSOCIATEDNRPPA, + MESSAGE_PRIORITY_MED, + ngap_downlink_ue_associated_nrppa_t, + ngap_downlink_ue_associated_nrppa) diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h index c47a564acb..b33cb34b09 100644 --- a/openair2/COMMON/ngap_messages_types.h +++ b/openair2/COMMON/ngap_messages_types.h @@ -79,6 +79,7 @@ #define NGAP_UL_RAN_STATUS_TRANSFER(mSGpTR) (mSGpTR)->ittiMsg.ngap_ul_ran_status_transfer #define NGAP_DL_RAN_STATUS_TRANSFER(mSGpTR) (mSGpTR)->ittiMsg.ngap_dl_ran_status_transfer +#define NGAP_DOWNLINKUEASSOCIATEDNRPPA(mSGpTR) (mSGpTR)->ittiMsg.ngap_downlink_ue_associated_nrppa //-------------------------------------------------------------------------------------------// /* Length of the transport layer address string @@ -1027,4 +1028,16 @@ typedef struct { byte_array_t nrppa_pdu; } ngap_uplink_non_ue_associated_nrppa_t; +// Downlink UE Associated NRPPA Transport message (9.2.9.1 3GPP 38.413 v16.0.0) +typedef struct { + // AMF UE NGAP ID (Mandatory) + uint64_t amf_ue_ngap_id; + // RAN UE NGAP ID (Mandatory) + uint32_t gNB_ue_ngap_id; + // Routing ID (Mandatory) + byte_array_t routing_id; + // NRPPa pdu (Mandatory) + byte_array_t nrppa_pdu; +} ngap_downlink_ue_associated_nrppa_t; + #endif /* NGAP_MESSAGES_TYPES_H_ */ diff --git a/openair3/NGAP/ngap_gNB_NRPPa_transport_procedures.c b/openair3/NGAP/ngap_gNB_NRPPa_transport_procedures.c index 56a85be44c..67b1db1578 100644 --- a/openair3/NGAP/ngap_gNB_NRPPa_transport_procedures.c +++ b/openair3/NGAP/ngap_gNB_NRPPa_transport_procedures.c @@ -194,3 +194,84 @@ int ngap_gNB_uplink_non_ue_associated_nrppa_transport(instance_t instance, const ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NGAP_NGAP_PDU, &pdu); return 0; } + +// handle DOWNLINK UE ASSOCIATED NRPPA TRANSPORT (9.2.9.1 of TS 38.413 Version 16.0.0) +int ngap_gNB_handle_downlink_ue_associated_nrppa_transport(sctp_assoc_t assoc_id, uint32_t stream, NGAP_NGAP_PDU_t *pdu) +{ + DevAssert(pdu != NULL); + ngap_gNB_amf_data_t *amf_desc_p = NULL; + + if ((amf_desc_p = ngap_gNB_get_AMF(NULL, assoc_id, 0)) == NULL) { + NGAP_ERROR("[SCTP %d] Received NRPPa downlink message for non existing AMF context\n", assoc_id); + return -1; + } + + ngap_gNB_instance_t *ngap_gNB_instance = NULL; + ngap_gNB_instance = amf_desc_p->ngap_gNB_instance; + + // Prepare the NGAP message for NRPPA + NGAP_DownlinkUEAssociatedNRPPaTransport_t *container = NULL; + NGAP_DownlinkUEAssociatedNRPPaTransportIEs_t *ie = NULL; + + // IE: 9.3.1.1 Message Type + container = &pdu->choice.initiatingMessage->value.choice.DownlinkUEAssociatedNRPPaTransport; + + // IE: 9.3.3.1 AMF UE NGAP ID + uint64_t amf_ue_ngap_id; + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_DownlinkUEAssociatedNRPPaTransportIEs_t, + ie, + container, + NGAP_ProtocolIE_ID_id_AMF_UE_NGAP_ID, + true); + asn_INTEGER2ulong(&(ie->value.choice.AMF_UE_NGAP_ID), &amf_ue_ngap_id); + + // IE: 9.3.3.2 RAN UE NGAP ID + NGAP_RAN_UE_NGAP_ID_t gnb_ue_ngap_id; + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_DownlinkUEAssociatedNRPPaTransportIEs_t, + ie, + container, + NGAP_ProtocolIE_ID_id_RAN_UE_NGAP_ID, + true); + gnb_ue_ngap_id = ie->value.choice.RAN_UE_NGAP_ID; + + ngap_gNB_ue_context_t *ue_desc_p = NULL; + if ((ue_desc_p = ngap_get_ue_context(gnb_ue_ngap_id)) == NULL) { + NGAP_ERROR("[SCTP %d] Received NRPPa downlink message for non existing UE context gNB_UE_NGAP_ID: 0x%lx\n", + assoc_id, + gnb_ue_ngap_id); + return -1; + } + + // Is it the first outcome of the AMF for this UE ? If so store the amf UE ngap id + if (ue_desc_p->amf_ue_ngap_id == 0) { + ue_desc_p->amf_ue_ngap_id = amf_ue_ngap_id; + } else { + // We already have a amf ue ngap id check the received is the same + if (ue_desc_p->amf_ue_ngap_id != amf_ue_ngap_id) { + NGAP_ERROR("[SCTP %d] Mismatch in AMF UE NGAP ID (0x%lx != 0x%" PRIx64 "\n", + assoc_id, + amf_ue_ngap_id, + (uint64_t)ue_desc_p->amf_ue_ngap_id); + return -1; + } + } + + MessageDef *msg = itti_alloc_new_message(TASK_NGAP, 0, NGAP_DOWNLINKUEASSOCIATEDNRPPA); + ngap_downlink_ue_associated_nrppa_t *dl_ue_assoc_nrppa = &NGAP_DOWNLINKUEASSOCIATEDNRPPA(msg); + + dl_ue_assoc_nrppa->amf_ue_ngap_id = amf_ue_ngap_id; + dl_ue_assoc_nrppa->gNB_ue_ngap_id = gnb_ue_ngap_id; + + // IE: 9.3.3.13 Routing ID + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_DownlinkUEAssociatedNRPPaTransportIEs_t, ie, container, NGAP_ProtocolIE_ID_id_RoutingID, true); + dl_ue_assoc_nrppa->routing_id = create_byte_array(ie->value.choice.RoutingID.size, ie->value.choice.RoutingID.buf); + + // IE: 9.3.3.14 NRPPa-PDU + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_DownlinkUEAssociatedNRPPaTransportIEs_t, ie, container, NGAP_ProtocolIE_ID_id_NRPPa_PDU, true); + dl_ue_assoc_nrppa->nrppa_pdu = create_byte_array(ie->value.choice.NRPPa_PDU.size, ie->value.choice.NRPPa_PDU.buf); + + // Forward the NRPPA PDU to NRPPA + itti_send_msg_to_task(TASK_NRPPA, ngap_gNB_instance->instance, msg); + + return 0; +} diff --git a/openair3/NGAP/ngap_gNB_NRPPa_transport_procedures.h b/openair3/NGAP/ngap_gNB_NRPPa_transport_procedures.h index 2624bee0a4..c045ce31aa 100644 --- a/openair3/NGAP/ngap_gNB_NRPPa_transport_procedures.h +++ b/openair3/NGAP/ngap_gNB_NRPPa_transport_procedures.h @@ -28,4 +28,7 @@ int ngap_gNB_uplink_ue_associated_nrppa_transport(instance_t instance, const nga // UPLINK NON UE ASSOCIATED NRPPA TRANSPORT (9.2.9.4 of TS 38.413 Version 16.0.0) int ngap_gNB_uplink_non_ue_associated_nrppa_transport(instance_t instance, const ngap_uplink_non_ue_associated_nrppa_t *msg); +// DOWNLINK UE ASSOCIATED NRPPA TRANSPORT (9.2.9.1 of TS 38.413 Version 16.0.0) +int ngap_gNB_handle_downlink_ue_associated_nrppa_transport(sctp_assoc_t assoc_id, uint32_t stream, NGAP_NGAP_PDU_t *pdu); + #endif /* NGAP_GNB_NRPPA_PROCEDURES_H_ */ From 040b25bf008b85564c38866480e0c3af9f8e3617 Mon Sep 17 00:00:00 2001 From: Rakesh Mundlamuri Date: Mon, 29 Dec 2025 18:51:08 +0530 Subject: [PATCH 08/21] Add NGAP DOWNLINK NON UE ASSOCIATED NRPPA TRANSPORT message decoding Reference: 3GPP 38.413 v16.0.0 Mandatory fields: Routing ID (supported) NRPPa-PDU (supported) --- openair2/COMMON/ngap_messages_def.h | 4 ++ openair2/COMMON/ngap_messages_types.h | 9 +++++ .../ngap_gNB_NRPPa_transport_procedures.c | 37 +++++++++++++++++++ .../ngap_gNB_NRPPa_transport_procedures.h | 3 ++ 4 files changed, 53 insertions(+) diff --git a/openair2/COMMON/ngap_messages_def.h b/openair2/COMMON/ngap_messages_def.h index 95d29baab2..a82b3cb849 100644 --- a/openair2/COMMON/ngap_messages_def.h +++ b/openair2/COMMON/ngap_messages_def.h @@ -94,3 +94,7 @@ MESSAGE_DEF(NGAP_DOWNLINKUEASSOCIATEDNRPPA, MESSAGE_PRIORITY_MED, ngap_downlink_ue_associated_nrppa_t, ngap_downlink_ue_associated_nrppa) +MESSAGE_DEF(NGAP_DOWNLINKNONUEASSOCIATEDNRPPA, + MESSAGE_PRIORITY_MED, + ngap_downlink_non_ue_associated_nrppa_t, + ngap_downlink_non_ue_associated_nrppa) diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h index b33cb34b09..e05f44f0b5 100644 --- a/openair2/COMMON/ngap_messages_types.h +++ b/openair2/COMMON/ngap_messages_types.h @@ -80,6 +80,7 @@ #define NGAP_DL_RAN_STATUS_TRANSFER(mSGpTR) (mSGpTR)->ittiMsg.ngap_dl_ran_status_transfer #define NGAP_DOWNLINKUEASSOCIATEDNRPPA(mSGpTR) (mSGpTR)->ittiMsg.ngap_downlink_ue_associated_nrppa +#define NGAP_DOWNLINKNONUEASSOCIATEDNRPPA(mSGpTR) (mSGpTR)->ittiMsg.ngap_downlink_non_ue_associated_nrppa //-------------------------------------------------------------------------------------------// /* Length of the transport layer address string @@ -1040,4 +1041,12 @@ typedef struct { byte_array_t nrppa_pdu; } ngap_downlink_ue_associated_nrppa_t; +// Downlink NON UE Associated NRPPA Transport message (9.2.9.3 3GPP 38.413 v16.0.0) +typedef struct { + // Routing ID (Mandatory) + byte_array_t routing_id; + // NRPPa pdu (Mandatory) + byte_array_t nrppa_pdu; +} ngap_downlink_non_ue_associated_nrppa_t; + #endif /* NGAP_MESSAGES_TYPES_H_ */ diff --git a/openair3/NGAP/ngap_gNB_NRPPa_transport_procedures.c b/openair3/NGAP/ngap_gNB_NRPPa_transport_procedures.c index 67b1db1578..37b5e3b344 100644 --- a/openair3/NGAP/ngap_gNB_NRPPa_transport_procedures.c +++ b/openair3/NGAP/ngap_gNB_NRPPa_transport_procedures.c @@ -275,3 +275,40 @@ int ngap_gNB_handle_downlink_ue_associated_nrppa_transport(sctp_assoc_t assoc_id return 0; } + +// handle DOWNLINK NON UE ASSOCIATED NRPPA TRANSPORT (9.2.9.3 of TS 38.413 Version 16.0.0) +int ngap_gNB_handle_downlink_non_ue_associated_nrppa_transport(sctp_assoc_t assoc_id, uint32_t stream, NGAP_NGAP_PDU_t *pdu) +{ + DevAssert(pdu != NULL); + ngap_gNB_amf_data_t *amf_desc_p = NULL; + + if ((amf_desc_p = ngap_gNB_get_AMF(NULL, assoc_id, 0)) == NULL) { + NGAP_ERROR("[SCTP %d] Received NRPPa downlink message for non existing AMF context\n", assoc_id); + return -1; + } + + ngap_gNB_instance_t *ngap_gNB_instance = NULL; + ngap_gNB_instance = amf_desc_p->ngap_gNB_instance; + + MessageDef *msg = itti_alloc_new_message(TASK_NGAP, 0, NGAP_DOWNLINKNONUEASSOCIATEDNRPPA); + ngap_downlink_non_ue_associated_nrppa_t *dl_non_ue_assoc_nrppa = &NGAP_DOWNLINKNONUEASSOCIATEDNRPPA(msg); + + // Prepare the NGAP message to forward to NRPPA + NGAP_DownlinkNonUEAssociatedNRPPaTransport_t *container; + NGAP_DownlinkNonUEAssociatedNRPPaTransportIEs_t *ie; + + // IE: 9.3.1.1 Message Type + container = &pdu->choice.initiatingMessage->value.choice.DownlinkNonUEAssociatedNRPPaTransport; + + // IE: 9.3.3.13 Routing ID + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_DownlinkNonUEAssociatedNRPPaTransportIEs_t, ie, container, NGAP_ProtocolIE_ID_id_RoutingID, true); + dl_non_ue_assoc_nrppa->routing_id = create_byte_array(ie->value.choice.RoutingID.size, ie->value.choice.RoutingID.buf); + + // IE: 9.3.3.14 NRPPa-PDU + NGAP_FIND_PROTOCOLIE_BY_ID(NGAP_DownlinkNonUEAssociatedNRPPaTransportIEs_t, ie, container, NGAP_ProtocolIE_ID_id_NRPPa_PDU, true); + dl_non_ue_assoc_nrppa->nrppa_pdu = create_byte_array(ie->value.choice.NRPPa_PDU.size, ie->value.choice.NRPPa_PDU.buf); + + itti_send_msg_to_task(TASK_NRPPA, ngap_gNB_instance->instance, msg); + + return 0; +} diff --git a/openair3/NGAP/ngap_gNB_NRPPa_transport_procedures.h b/openair3/NGAP/ngap_gNB_NRPPa_transport_procedures.h index c045ce31aa..a180888029 100644 --- a/openair3/NGAP/ngap_gNB_NRPPa_transport_procedures.h +++ b/openair3/NGAP/ngap_gNB_NRPPa_transport_procedures.h @@ -31,4 +31,7 @@ int ngap_gNB_uplink_non_ue_associated_nrppa_transport(instance_t instance, const // DOWNLINK UE ASSOCIATED NRPPA TRANSPORT (9.2.9.1 of TS 38.413 Version 16.0.0) int ngap_gNB_handle_downlink_ue_associated_nrppa_transport(sctp_assoc_t assoc_id, uint32_t stream, NGAP_NGAP_PDU_t *pdu); +// DOWNLINK UE ASSOCIATED NRPPA TRANSPORT (9.2.9.3 of TS 38.413 Version 16.0.0) +int ngap_gNB_handle_downlink_non_ue_associated_nrppa_transport(sctp_assoc_t assoc_id, uint32_t stream, NGAP_NGAP_PDU_t *pdu); + #endif /* NGAP_GNB_NRPPA_PROCEDURES_H_ */ From 2cfff7520f19a0204b691234009b7484fa01c9e2 Mon Sep 17 00:00:00 2001 From: Rakesh Mundlamuri Date: Mon, 29 Dec 2025 19:40:20 +0530 Subject: [PATCH 09/21] Add NGAP encoding procedures of Uplink NRPPA Transport procedures --- openair2/COMMON/ngap_messages_def.h | 5 +++++ openair2/COMMON/ngap_messages_types.h | 3 +++ openair3/NGAP/ngap_gNB.c | 9 +++++++++ openair3/NGAP/ngap_gNB_encoder.c | 4 +++- 4 files changed, 20 insertions(+), 1 deletion(-) diff --git a/openair2/COMMON/ngap_messages_def.h b/openair2/COMMON/ngap_messages_def.h index a82b3cb849..648bd565f3 100644 --- a/openair2/COMMON/ngap_messages_def.h +++ b/openair2/COMMON/ngap_messages_def.h @@ -98,3 +98,8 @@ MESSAGE_DEF(NGAP_DOWNLINKNONUEASSOCIATEDNRPPA, MESSAGE_PRIORITY_MED, ngap_downlink_non_ue_associated_nrppa_t, ngap_downlink_non_ue_associated_nrppa) +MESSAGE_DEF(NGAP_UPLINKUEASSOCIATEDNRPPA, MESSAGE_PRIORITY_MED, ngap_uplink_ue_associated_nrppa_t, ngap_uplink_ue_associated_nrppa) +MESSAGE_DEF(NGAP_UPLINKNONUEASSOCIATEDNRPPA, + MESSAGE_PRIORITY_MED, + ngap_uplink_non_ue_associated_nrppa_t, + ngap_uplink_non_ue_associated_nrppa) diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h index e05f44f0b5..85d61bba39 100644 --- a/openair2/COMMON/ngap_messages_types.h +++ b/openair2/COMMON/ngap_messages_types.h @@ -81,6 +81,9 @@ #define NGAP_DOWNLINKUEASSOCIATEDNRPPA(mSGpTR) (mSGpTR)->ittiMsg.ngap_downlink_ue_associated_nrppa #define NGAP_DOWNLINKNONUEASSOCIATEDNRPPA(mSGpTR) (mSGpTR)->ittiMsg.ngap_downlink_non_ue_associated_nrppa + +#define NGAP_UPLINKUEASSOCIATEDNRPPA(mSGpTR) (mSGpTR)->ittiMsg.ngap_uplink_ue_associated_nrppa +#define NGAP_UPLINKNONUEASSOCIATEDNRPPA(mSGpTR) (mSGpTR)->ittiMsg.ngap_uplink_non_ue_associated_nrppa //-------------------------------------------------------------------------------------------// /* Length of the transport layer address string diff --git a/openair3/NGAP/ngap_gNB.c b/openair3/NGAP/ngap_gNB.c index 257ca25f1a..c9da148eea 100644 --- a/openair3/NGAP/ngap_gNB.c +++ b/openair3/NGAP/ngap_gNB.c @@ -58,6 +58,7 @@ #include "ngap_gNB_mobility_management.h" #include "ngap_gNB_ue_context.h" #include "ngap_gNB_pdu_session_management.h" +#include "ngap_gNB_NRPPa_transport_procedures.h" #include "oai_asn1.h" #include "openair3/SECU/kdf.h" #include "queue.h" @@ -626,6 +627,14 @@ void *ngap_gNB_process_itti_msg(void *notUsed) { ngap_gNB_handle_ul_ran_status_transfer(instance, &NGAP_UL_RAN_STATUS_TRANSFER(received_msg)); break; + case NGAP_UPLINKUEASSOCIATEDNRPPA: + ngap_gNB_uplink_ue_associated_nrppa_transport(instance, &NGAP_UPLINKUEASSOCIATEDNRPPA(received_msg)); + break; + + case NGAP_UPLINKNONUEASSOCIATEDNRPPA: + ngap_gNB_uplink_non_ue_associated_nrppa_transport(instance, &NGAP_UPLINKNONUEASSOCIATEDNRPPA(received_msg)); + break; + default: NGAP_ERROR("Received unhandled message: %d:%s\n", ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg)); break; diff --git a/openair3/NGAP/ngap_gNB_encoder.c b/openair3/NGAP/ngap_gNB_encoder.c index ff318ed184..801ce95d42 100644 --- a/openair3/NGAP/ngap_gNB_encoder.c +++ b/openair3/NGAP/ngap_gNB_encoder.c @@ -56,7 +56,9 @@ static inline int ngap_gNB_encode_initiating(NGAP_NGAP_PDU_t *pdu, uint8_t **buf NGAP_ProcedureCode_id_UplinkRANStatusTransfer, NGAP_ProcedureCode_id_HandoverPreparation, NGAP_ProcedureCode_id_HandoverCancel, - NGAP_ProcedureCode_id_HandoverNotification}; + NGAP_ProcedureCode_id_HandoverNotification, + NGAP_ProcedureCode_id_UplinkUEAssociatedNRPPaTransport, + NGAP_ProcedureCode_id_UplinkNonUEAssociatedNRPPaTransport}; int i; for (i = 0; i < sizeofArray(tmp); i++) if (pdu->choice.initiatingMessage->procedureCode == tmp[i]) From 6eceaacb731a79d0464f59400aad834e2a8a578d Mon Sep 17 00:00:00 2001 From: Rakesh Mundlamuri Date: Mon, 29 Dec 2025 19:51:53 +0530 Subject: [PATCH 10/21] Add NGAP decoding procedures of Downlink NRPPA Transport procedures --- openair3/NGAP/ngap_gNB_decoder.c | 12 ++++++++++++ openair3/NGAP/ngap_gNB_handlers.c | 5 +++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/openair3/NGAP/ngap_gNB_decoder.c b/openair3/NGAP/ngap_gNB_decoder.c index 43110e9037..3993f8aa72 100644 --- a/openair3/NGAP/ngap_gNB_decoder.c +++ b/openair3/NGAP/ngap_gNB_decoder.c @@ -112,6 +112,18 @@ static int ngap_gNB_decode_initiating_message(NGAP_NGAP_PDU_t *pdu) { NGAP_INFO("DL RAN Status Transfer initiating message\n"); break; + case NGAP_ProcedureCode_id_DownlinkUEAssociatedNRPPaTransport: + res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu); + free(res.buffer); + NGAP_INFO("DL UE Associated NRPPA Transport initiating message\n"); + break; + + case NGAP_ProcedureCode_id_DownlinkNonUEAssociatedNRPPaTransport: + res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NGAP_NGAP_PDU, pdu); + free(res.buffer); + NGAP_INFO("DL NON UE Associated NRPPA Transport initiating message\n"); + break; + default: NGAP_ERROR("Unknown procedure ID (%d) for initiating message\n", (int)pdu->choice.initiatingMessage->procedureCode); diff --git a/openair3/NGAP/ngap_gNB_handlers.c b/openair3/NGAP/ngap_gNB_handlers.c index 9113f850ca..3dd9c39db3 100644 --- a/openair3/NGAP/ngap_gNB_handlers.c +++ b/openair3/NGAP/ngap_gNB_handlers.c @@ -50,6 +50,7 @@ #include "ngap_gNB_pdu_session_management.h" #include "ngap_gNB_nas_procedures.h" #include "ngap_gNB_paging.h" +#include "ngap_gNB_NRPPa_transport_procedures.h" #include "ngap_gNB_trace.h" #include "ngap_gNB_ue_context.h" #include "ngap_messages_types.h" @@ -1499,10 +1500,10 @@ const ngap_message_decoded_callback ngap_messages_callback[][3] = { {0, 0, 0}, /* CellTrafficTrace */ {ngap_gNB_handle_deactivate_trace, 0, 0}, /* DeactivateTrace */ {ngap_gNB_handle_nas_downlink, 0, 0}, /* DownlinkNASTransport */ - {0, 0, 0}, /* DownlinkNonUEAssociatedNRPPaTransport */ + {ngap_gNB_handle_downlink_non_ue_associated_nrppa_transport, 0, 0}, /* DownlinkNonUEAssociatedNRPPaTransport */ {0, 0, 0}, /* DownlinkRANConfigurationTransfer */ {ngap_gNB_handle_dl_ran_status_transfer, 0, 0}, /* DownlinkRANStatusTransfer */ - {0, 0, 0}, /* DownlinkUEAssociatedNRPPaTransport */ + {ngap_gNB_handle_downlink_ue_associated_nrppa_transport, 0, 0}, /* DownlinkUEAssociatedNRPPaTransport */ {ngap_gNB_handle_error_indication, 0, 0}, /* ErrorIndication */ {0, ngap_gNB_handle_handover_cancel_ack, 0}, /* HandoverCancel */ {0, 0, 0}, /* HandoverNotification */ From ccf4b425419a0c784511b83bae2b63946c244c34 Mon Sep 17 00:00:00 2001 From: Rakesh Mundlamuri Date: Tue, 30 Dec 2025 15:02:31 +0530 Subject: [PATCH 11/21] Add RCconfig_nr_positioning to obtain and fill TRP related parameters from config file --- openair1/PHY/defs_nr_common.h | 23 +++++++ openair2/COMMON/positioning_nr_paramdef.h | 62 +++++++++++++++++ openair2/GNB_APP/gnb_config.c | 1 + openair3/NRPPA/nrppa_gNB_config.c | 84 +++++++++++++++++++++++ openair3/NRPPA/nrppa_gNB_config.h | 30 ++++++++ tests/nr-cu-nrppa/nr-cu-nrppa.c | 1 + tests/nr-cu-nrppa/nr-nrppa-test.conf | 21 ++++++ 7 files changed, 222 insertions(+) create mode 100644 openair2/COMMON/positioning_nr_paramdef.h create mode 100644 openair3/NRPPA/nrppa_gNB_config.c create mode 100644 openair3/NRPPA/nrppa_gNB_config.h diff --git a/openair1/PHY/defs_nr_common.h b/openair1/PHY/defs_nr_common.h index 199877d738..2543eb6650 100644 --- a/openair1/PHY/defs_nr_common.h +++ b/openair1/PHY/defs_nr_common.h @@ -305,6 +305,29 @@ typedef struct { int32_t reserved; } prs_meas_t; +// Configuration parameters required for 5G Positioning +// TRP Cartesian Coordinate information +typedef struct trp_s { + // TRP id + uint32_t id; + // TRP x-axis value + uint32_t x_axis; + // TRP y-axis value + uint32_t y_axis; + // TRP z-axis value + uint32_t z_axis; + // 0 = mm, 1 = cm, 2 = dm + uint8_t unit; +} trp_t; + +#define MAX_NUM_TRPs 8 +typedef struct { + trp_t trps[MAX_NUM_TRPs]; + uint8_t num_trp; + // Serving gNB indicator + bool is_serving_gNB; +} positioning_config_t; + // rel16 prs k_prime table as per ts138.211 sec.7.4.1.7.2 #define K_PRIME_TABLE_ROW_SIZE 4 #define K_PRIME_TABLE_COL_SIZE 12 diff --git a/openair2/COMMON/positioning_nr_paramdef.h b/openair2/COMMON/positioning_nr_paramdef.h new file mode 100644 index 0000000000..6861db6778 --- /dev/null +++ b/openair2/COMMON/positioning_nr_paramdef.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 __POSITIONING_NR_PARAMDEF__H__ +#define __POSITIONING_NR_PARAMDEF__H__ + +/* Positioning configuration section names */ +#define CONFIG_STRING_POSITIONING_CONFIG "positioning_config" + +/* Global parameters */ + +/* TRP configuration parameters names */ +#define CONFIG_STRING_POSITIONING_NUM_TRPS "NumTRPs" +#define CONFIG_STRING_POSITIONING_TRP_IDS_LIST "TRPIDs" +#define CONFIG_STRING_POSITIONING_TRP_X_AXIS_LIST "TRPxAxis" +#define CONFIG_STRING_POSITIONING_TRP_Y_AXIS_LIST "TRPyAxis" +#define CONFIG_STRING_POSITIONING_TRP_Z_AXIS_LIST "TRPzAxis" +#define CONFIG_STRING_POSITIONING_TRP_UNIT_LIST "Units" + +/* Help string for Positioning parameters */ +#define HELP_STRING_POSITIONING_NUM_TRPS "Number of TRPs connected with gNB(max 4)\n" +#define HELP_STRING_POSITIONING_TRP_IDS_LIST "User defined IDs for each TRP \n" +#define HELP_STRING_POSITIONING_TRP_X_AXIS_LIST "x-axis value of each TRP \n" +#define HELP_STRING_POSITIONING_TRP_Y_AXIS_LIST "y-axis value of each TRP \n" +#define HELP_STRING_POSITIONING_TRP_Z_AXIS_LIST "z-axis value of each TRP \n" +#define HELP_STRING_POSITIONING_TRP_UNIT_LIST "XYZ unit value of each TRP \n" + +/*----------------------------------------------------------------------------------------------------------------------------------------------------------------*/ +/* TRP configuration parameters */ +/* optname helpstr paramflags XXXptr defXXXval type + * numelt */ +/*----------------------------------------------------------------------------------------------------------------------------------------------------------------*/ +// clang-format off +#define POSITIONING_PARAMS_DESC { \ + {CONFIG_STRING_POSITIONING_NUM_TRPS, HELP_STRING_POSITIONING_NUM_TRPS, 0, .uptr=NULL, .defuintval=0, TYPE_UINT, 0}, \ + {CONFIG_STRING_POSITIONING_TRP_IDS_LIST, HELP_STRING_POSITIONING_TRP_IDS_LIST, 0, .uptr=NULL, .defintarrayval=0, TYPE_UINTARRAY, 0}, \ + {CONFIG_STRING_POSITIONING_TRP_X_AXIS_LIST, HELP_STRING_POSITIONING_TRP_X_AXIS_LIST, 0, .uptr=NULL, .defintarrayval=0, TYPE_UINTARRAY, 0}, \ + {CONFIG_STRING_POSITIONING_TRP_Y_AXIS_LIST, HELP_STRING_POSITIONING_TRP_Y_AXIS_LIST, 0, .uptr=NULL, .defintarrayval=0, TYPE_UINTARRAY, 0}, \ + {CONFIG_STRING_POSITIONING_TRP_Z_AXIS_LIST, HELP_STRING_POSITIONING_TRP_Z_AXIS_LIST, 0, .uptr=NULL, .defintarrayval=0, TYPE_UINTARRAY, 0}, \ + {CONFIG_STRING_POSITIONING_TRP_UNIT_LIST, HELP_STRING_POSITIONING_TRP_UNIT_LIST, 0, .uptr=NULL, .defintarrayval=0, TYPE_UINTARRAY, 0}, \ +} +// clang-format on + +#endif diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index d6d370fe70..3262f851a5 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -80,6 +80,7 @@ #include "utils.h" #include "x2ap_messages_types.h" #include "gnb_config_common.h" +#include "positioning_nr_paramdef.h" static int DEFBANDS[] = {7}; static int DEFENBS[] = {0}; diff --git a/openair3/NRPPA/nrppa_gNB_config.c b/openair3/NRPPA/nrppa_gNB_config.c new file mode 100644 index 0000000000..dc0590f603 --- /dev/null +++ b/openair3/NRPPA/nrppa_gNB_config.c @@ -0,0 +1,84 @@ +/* + * 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 "nrppa_gNB_config.h" +#include "assertions.h" +#include "openair1/PHY/defs_nr_common.h" +#include "openair1/PHY/defs_gNB.h" +#include "common/ran_context.h" +#include "positioning_nr_paramdef.h" + +positioning_config_t RCconfig_nr_positioning(void) +{ + positioning_config_t positioning_config = {0}; + paramdef_t positioning_params_desc[] = POSITIONING_PARAMS_DESC; + int num_params = sizeofArray(positioning_params_desc); + GET_PARAMS_LIST(POSITIONING_ParamList, POSITIONING_Params, POSITIONING_PARAMS_DESC, CONFIG_STRING_POSITIONING_CONFIG, NULL); + + if (POSITIONING_ParamList.numelt > 0) { + paramdef_t *params = POSITIONING_ParamList.paramarray[0]; + + uint8_t num_trp = *gpd(params, num_params, CONFIG_STRING_POSITIONING_NUM_TRPS)->uptr; + if (num_trp == 0) { + LOG_E(NR_PHY, "No TRP configuration found..!!!\n"); + return positioning_config; + } else if (num_trp > MAX_NUM_TRPs) { + AssertFatal(false, "Exceeded MAX number of TRPs\n"); + } + + uint8_t num_ids = gpd(params, num_params, CONFIG_STRING_POSITIONING_TRP_IDS_LIST)->numelt; + uint8_t num_x = gpd(params, num_params, CONFIG_STRING_POSITIONING_TRP_X_AXIS_LIST)->numelt; + uint8_t num_y = gpd(params, num_params, CONFIG_STRING_POSITIONING_TRP_Y_AXIS_LIST)->numelt; + uint8_t num_z = gpd(params, num_params, CONFIG_STRING_POSITIONING_TRP_Z_AXIS_LIST)->numelt; + uint8_t num_unit = gpd(params, num_params, CONFIG_STRING_POSITIONING_TRP_UNIT_LIST)->numelt; + + if (num_trp != num_ids || num_trp != num_x || num_trp != num_y || num_trp != num_z || num_trp != num_unit) { + AssertFatal(false, "Mismatch in the number of TRPs with the number of ids, x-axis, y-axis, z-axis, units\n"); + } + + positioning_config.num_trp = num_trp; + for (int l = 0; l < num_trp; l++) { + positioning_config.trps[l].id = gpd(params, num_params, CONFIG_STRING_POSITIONING_TRP_IDS_LIST)->uptr[l]; + positioning_config.trps[l].x_axis = gpd(params, num_params, CONFIG_STRING_POSITIONING_TRP_X_AXIS_LIST)->uptr[l]; + positioning_config.trps[l].y_axis = gpd(params, num_params, CONFIG_STRING_POSITIONING_TRP_Y_AXIS_LIST)->uptr[l]; + positioning_config.trps[l].z_axis = gpd(params, num_params, CONFIG_STRING_POSITIONING_TRP_Z_AXIS_LIST)->uptr[l]; + positioning_config.trps[l].unit = gpd(params, num_params, CONFIG_STRING_POSITIONING_TRP_UNIT_LIST)->uptr[l]; + } + } else { + LOG_I(NR_PHY, "No " CONFIG_STRING_POSITIONING_CONFIG " configuration found..!!\n"); + } + return positioning_config; +} + +void dump_positioning_config(const positioning_config_t *positioning_config) +{ + uint8_t num_trp = positioning_config->num_trp; + LOG_I(NR_PHY, "-----------------------------------------\n"); + LOG_I(NR_PHY, "Positioning Config\n"); + LOG_I(NR_PHY, "-----------------------------------------\n"); + LOG_I(NR_PHY, "Number of TRPs \t\t%d\n", num_trp); + for (int i = 0; i < num_trp; i++) { + LOG_I(NR_PHY, "X-axis of TRP ID %d \t\t%d\n", positioning_config->trps[i].id, positioning_config->trps[i].x_axis); + LOG_I(NR_PHY, "Y-axis of TRP ID %d \t\t%d\n", positioning_config->trps[i].id, positioning_config->trps[i].y_axis); + LOG_I(NR_PHY, "Z-axis of TRP ID %d \t\t%d\n", positioning_config->trps[i].id, positioning_config->trps[i].z_axis); + } + LOG_I(NR_PHY, "-----------------------------------------\n"); +} diff --git a/openair3/NRPPA/nrppa_gNB_config.h b/openair3/NRPPA/nrppa_gNB_config.h new file mode 100644 index 0000000000..3ae710a62c --- /dev/null +++ b/openair3/NRPPA/nrppa_gNB_config.h @@ -0,0 +1,30 @@ +/* + * 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 GNB_CONFIG_POSITIONING_H_ +#define GNB_CONFIG_POSITIONING_H_ + +#include "openair1/PHY/defs_nr_common.h" + +positioning_config_t RCconfig_nr_positioning(void); +void dump_positioning_config(const positioning_config_t *positioning_config); + +#endif /* GNB_CONFIG_POSITIONING_H_ */ diff --git a/tests/nr-cu-nrppa/nr-cu-nrppa.c b/tests/nr-cu-nrppa/nr-cu-nrppa.c index 1436b7cd27..2c29ce6258 100644 --- a/tests/nr-cu-nrppa/nr-cu-nrppa.c +++ b/tests/nr-cu-nrppa/nr-cu-nrppa.c @@ -27,6 +27,7 @@ #include "openair2/GNB_APP/gnb_config_ng.h" #include "openair2/GNB_APP/gnb_paramdef.h" #include "openair3/SCTP/sctp_default_values.h" +#include "openair3/NRPPA/nrppa_gNB_config.h" RAN_CONTEXT_t RC; THREAD_STRUCT thread_struct; diff --git a/tests/nr-cu-nrppa/nr-nrppa-test.conf b/tests/nr-cu-nrppa/nr-nrppa-test.conf index f5d6ea673a..aaaa45f176 100644 --- a/tests/nr-cu-nrppa/nr-nrppa-test.conf +++ b/tests/nr-cu-nrppa/nr-nrppa-test.conf @@ -38,6 +38,27 @@ gNBs = } ); +positioning_config = ( + { + NumTRPs = 4; # number of TRPs + TRPIDs = [1,2,3,4]; # userdefined distinct IDs + TRPxAxis = [71,21,10,45]; # X-axis value of each TRP + TRPyAxis = [11,22,62,14]; # Y-axis value of each TRP + TRPzAxis = [41,22,33,42]; # Z-axis value of each TRP + Units = [0, 0, 0, 0]; # 0 = mm, 1 = cm, 2 = dm + } +); + +L1s = ( + { + num_cc = 1; + tr_n_preference = "local_mac"; + prach_dtx_threshold = 120; + pucch0_dtx_threshold = 150; + ofdm_offset_divisor = 8; #set this to UINT_MAX for offset 0 + } +); + log_config : { global_log_level ="info"; From 446a905013d88a32d375081fe0ca71af0c4e1072 Mon Sep 17 00:00:00 2001 From: Rakesh Mundlamuri Date: Wed, 7 Jan 2026 12:08:25 +0530 Subject: [PATCH 12/21] Add TRP Information Request NRPPA message decoding procedures --- common/utils/LOG/log.h | 1 + common/utils/T/T_messages.txt | 21 ++ common/utils/ocp_itti/all_msg.h | 2 +- common/utils/ocp_itti/intertask_interface.h | 1 + openair2/COMMON/nrppa_messages_def.h | 25 +++ openair2/COMMON/nrppa_messages_types.h | 67 +++++++ openair3/NRPPA/CMakeLists.txt | 14 +- openair3/NRPPA/nrppa_common.h | 62 ++++++ openair3/NRPPA/nrppa_gNB.c | 79 ++++++++ openair3/NRPPA/nrppa_gNB.h | 32 ++++ openair3/NRPPA/nrppa_gNB_decoder.c | 116 ++++++++++++ openair3/NRPPA/nrppa_gNB_decoder.h | 30 +++ openair3/NRPPA/nrppa_gNB_handlers.c | 179 ++++++++++++++++++ openair3/NRPPA/nrppa_gNB_handlers.h | 28 +++ .../nrppa_gNB_location_information_transfer.c | 95 ++++++++++ .../nrppa_gNB_location_information_transfer.h | 28 +++ openair3/NRPPA/nrppa_gNB_ue_context.c | 85 +++++++++ openair3/NRPPA/nrppa_gNB_ue_context.h | 43 +++++ openair3/NRPPA/nrppa_includes.h | 39 ++++ tests/nr-cu-nrppa/CMakeLists.txt | 2 +- tests/nr-cu-nrppa/nr-cu-nrppa.c | 4 + 21 files changed, 948 insertions(+), 5 deletions(-) create mode 100644 openair2/COMMON/nrppa_messages_def.h create mode 100644 openair2/COMMON/nrppa_messages_types.h create mode 100644 openair3/NRPPA/nrppa_common.h create mode 100644 openair3/NRPPA/nrppa_gNB.c create mode 100644 openair3/NRPPA/nrppa_gNB.h create mode 100644 openair3/NRPPA/nrppa_gNB_decoder.c create mode 100644 openair3/NRPPA/nrppa_gNB_decoder.h create mode 100644 openair3/NRPPA/nrppa_gNB_handlers.c create mode 100644 openair3/NRPPA/nrppa_gNB_handlers.h create mode 100644 openair3/NRPPA/nrppa_gNB_location_information_transfer.c create mode 100644 openair3/NRPPA/nrppa_gNB_location_information_transfer.h create mode 100644 openair3/NRPPA/nrppa_gNB_ue_context.c create mode 100644 openair3/NRPPA/nrppa_gNB_ue_context.h create mode 100644 openair3/NRPPA/nrppa_includes.h diff --git a/common/utils/LOG/log.h b/common/utils/LOG/log.h index a9db2e9c5c..837c6897a6 100644 --- a/common/utils/LOG/log.h +++ b/common/utils/LOG/log.h @@ -165,6 +165,7 @@ static const char *const flag_name[] = {FOREACH_FLAG(FLAG_TEXT) ""}; COMP_DEF(M2AP, ) \ COMP_DEF(M3AP, ) \ COMP_DEF(NGAP, ) \ + COMP_DEF(NRPPA, ) \ COMP_DEF(GNB_APP, log) \ COMP_DEF(NR_RRC, log) \ COMP_DEF(NR_MAC, log) \ diff --git a/common/utils/T/T_messages.txt b/common/utils/T/T_messages.txt index d2405f9033..00f063f703 100644 --- a/common/utils/T/T_messages.txt +++ b/common/utils/T/T_messages.txt @@ -586,6 +586,27 @@ ID = LEGACY_NGAP_TRACE GROUP = ALL:LEGACY_NGAP:LEGACY_GROUP_TRACE:LEGACY FORMAT = string,log +ID = LEGACY_NRPPA_INFO + DESC = NRPPA legacy logs - info level + GROUP = ALL:LEGACY_NRPPA:LEGACY_GROUP_INFO:LEGACY + FORMAT = string,log +ID = LEGACY_NRPPA_ERROR + DESC = NRPPA legacy logs - error level + GROUP = ALL:LEGACY_NRPPA:LEGACY_GROUP_ERROR:LEGACY + FORMAT = string,log +ID = LEGACY_NRPPA_WARNING + DESC = NRPPA legacy logs - warning level + GROUP = ALL:LEGACY_NRPPA:LEGACY_GROUP_WARNING:LEGACY + FORMAT = string,log +ID = LEGACY_NRPPA_DEBUG + DESC = NRPPA legacy logs - debug level + GROUP = ALL:LEGACY_NRPPA:LEGACY_GROUP_DEBUG:LEGACY + FORMAT = string,log +ID = LEGACY_NRPPA_TRACE + DESC = NRPPA legacy logs - trace level + GROUP = ALL:LEGACY_NRPPA:LEGACY_GROUP_TRACE:LEGACY + FORMAT = string,log + ID = LEGACY_X2AP_INFO DESC = X2AP legacy logs - info level GROUP = ALL:LEGACY_X2AP:LEGACY_GROUP_INFO:LEGACY diff --git a/common/utils/ocp_itti/all_msg.h b/common/utils/ocp_itti/all_msg.h index 377bfc4343..8b74409a3c 100644 --- a/common/utils/ocp_itti/all_msg.h +++ b/common/utils/ocp_itti/all_msg.h @@ -14,4 +14,4 @@ #include "openair2/COMMON/f1ap_messages_def.h" #include "openair2/COMMON/e1ap_messages_def.h" #include "openair2/COMMON/ngap_messages_def.h" - +#include "openair2/COMMON/nrppa_messages_def.h" diff --git a/common/utils/ocp_itti/intertask_interface.h b/common/utils/ocp_itti/intertask_interface.h index 7580698dcf..353a0bae5a 100644 --- a/common/utils/ocp_itti/intertask_interface.h +++ b/common/utils/ocp_itti/intertask_interface.h @@ -230,6 +230,7 @@ typedef struct IttiMsgText_s { #include #include #include +#include #include #include #include diff --git a/openair2/COMMON/nrppa_messages_def.h b/openair2/COMMON/nrppa_messages_def.h new file mode 100644 index 0000000000..ae17d73742 --- /dev/null +++ b/openair2/COMMON/nrppa_messages_def.h @@ -0,0 +1,25 @@ +/* + * 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 "openair2/COMMON/nrppa_messages_types.h" + +// LMF -> CU +MESSAGE_DEF(NRPPA_TRP_INFORMATION_REQ, MESSAGE_PRIORITY_MED, nrppa_trp_information_req_t, nrppa_trp_information_req) diff --git a/openair2/COMMON/nrppa_messages_types.h b/openair2/COMMON/nrppa_messages_types.h new file mode 100644 index 0000000000..55563a59ab --- /dev/null +++ b/openair2/COMMON/nrppa_messages_types.h @@ -0,0 +1,67 @@ +/* + * 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 NRPPA_MESSAGES_TYPES_H_ +#define NRPPA_MESSAGES_TYPES_H_ + +// Defines to access message fields. + +#define NRPPA_TRP_INFORMATION_REQ(mSGpTR) (mSGpTR)->ittiMsg.nrppa_trp_information_req + +/* Structure of Positioning related NRPPA messages */ +/* IE structures for Positioning related messages as per TS 38.455 V16.7.1*/ + +typedef enum nrppa_trp_information_type_item_e { + NRPPA_TRP_INFORMATION_TYPE_ITEM_NR_PCI, + NRPPA_TRP_INFORMATION_TYPE_ITEM_NG_RAN_CGI, + NRPPA_TRP_INFORMATION_TYPE_ITEM_NR_ARFCN, + NRPPA_TRP_INFORMATION_TYPE_ITEM_PRS_CONFIG, + NRPPA_TRP_INFORMATION_TYPE_ITEM_SSB_CONFIG, + NRPPA_TRP_INFORMATION_TYPE_ITEM_SFN_INIT_TIME, + NRPPA_TRP_INFORMATION_TYPE_ITEM_SPATIAL_DIRECTION_INFO, + NRPPA_TRP_INFORMATION_TYPE_ITEM_GEO_COORDINATES +} nrppa_trp_information_type_item_pr; + +typedef struct nrppa_trp_information_type_list_s { + nrppa_trp_information_type_item_pr *trp_information_type_item; + uint8_t trp_information_type_list_length; +} nrppa_trp_information_type_list_t; + +typedef struct nrppa_trp_list_item_s { + uint32_t trp_id; +} nrppa_trp_list_item_t; + +typedef struct nrppa_trp_list_s { + nrppa_trp_list_item_t *trp_list_item; + uint32_t trp_list_length; +} nrppa_trp_list_t; + +typedef struct nrppa_trp_information_req_s { + // IE 9.2.4 (mandatory) + uint16_t transaction_id; + bool has_trp_list; + // mandatory + nrppa_trp_list_t trp_list; + // mandatory + nrppa_trp_information_type_list_t trp_information_type_list; +} nrppa_trp_information_req_t; + +#endif // NRPPA_MESSAGES_TYPES_H_ diff --git a/openair3/NRPPA/CMakeLists.txt b/openair3/NRPPA/CMakeLists.txt index 613cbfc3ce..28ad4c8618 100644 --- a/openair3/NRPPA/CMakeLists.txt +++ b/openair3/NRPPA/CMakeLists.txt @@ -1,5 +1,13 @@ add_subdirectory(MESSAGES) -add_executable(test_nrppa ${OPENAIR3_DIR}/NRPPA/test_nrppa.c ) -target_link_libraries(test_nrppa asn1_nrppa) - +add_library(nrppa + nrppa_gNB.c + nrppa_gNB_config.c + nrppa_gNB_handlers.c + nrppa_gNB_decoder.c + nrppa_gNB_ue_context.c + nrppa_gNB_location_information_transfer.c + ) + +target_link_libraries(nrppa PUBLIC asn1_nrppa) +target_link_libraries(nrppa PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) diff --git a/openair3/NRPPA/nrppa_common.h b/openair3/NRPPA/nrppa_common.h new file mode 100644 index 0000000000..b7c613e77a --- /dev/null +++ b/openair3/NRPPA/nrppa_common.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 NRPPA_COMMON_H_ +#define NRPPA_COMMON_H_ + +#include "oai_asn1.h" +#include "common/utils/LOG/log.h" +#include "ds/byte_array.h" +#include "nrppa_includes.h" + +#define NRPPA_FIND_PROTOCOLIE_BY_ID(IE_TYPE, ie, container, IE_ID, mandatory) \ + do { \ + IE_TYPE **ptr; \ + ie = NULL; \ + for (ptr = container->protocolIEs.list.array; ptr < &container->protocolIEs.list.array[container->protocolIEs.list.count]; \ + ptr++) { \ + if ((*ptr)->id == IE_ID) { \ + ie = *ptr; \ + break; \ + } \ + } \ + if (ie == NULL) { \ + if (mandatory) { \ + AssertFatal(false, "NRPPA_FIND_PROTOCOLIE_BY_ID ie is NULL (searching for ie: %ld)\n", IE_ID); \ + } else { \ + LOG_I(NRPPA, "NRPPA_FIND_PROTOCOLIE_BY_ID ie is NULL (searching for ie: %ld)\n", IE_ID); \ + } \ + } \ + } while (0); \ + if (mandatory && !ie) \ + return -1 + +// gnb and ue related info in NRPPA message +typedef struct nrppa_gnb_ue_info_s { + instance_t instance; + int32_t gNB_ue_ngap_id; + int64_t amf_ue_ngap_id; + byte_array_t routing_id; +} nrppa_gnb_ue_info_t; + +typedef int (*nrppa_message_decoded_callback)(nrppa_gnb_ue_info_t *nrppa_msg_info, const NRPPA_NRPPA_PDU_t *pdu); + +#endif /* NRPPA_COMMON_H_ */ diff --git a/openair3/NRPPA/nrppa_gNB.c b/openair3/NRPPA/nrppa_gNB.c new file mode 100644 index 0000000000..d7f067de98 --- /dev/null +++ b/openair3/NRPPA/nrppa_gNB.c @@ -0,0 +1,79 @@ +/* + * 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 "tree.h" +#include "queue.h" + +#include "intertask_interface.h" + +#include "assertions.h" +#include "conversions.h" + +#include "nrppa_gNB.h" +#include "nrppa_common.h" +#include "nrppa_gNB_handlers.h" +#include "nrppa_gNB_location_information_transfer.h" + +void nrppa_gNB_init(void) +{ + LOG_I(NRPPA, "Starting NRPPA layer\n"); + itti_mark_task_ready(TASK_NRPPA); +} + +void *nrppa_gNB_process_itti_msg(void *notUsed) +{ + MessageDef *received_msg = NULL; + int result; + itti_receive_msg(TASK_NRPPA, &received_msg); + if (received_msg) { + instance_t instance = ITTI_MSG_DESTINATION_INSTANCE(received_msg); + LOG_I(NRPPA, "Received message %s\n", ITTI_MSG_NAME(received_msg)); + switch (ITTI_MSG_ID(received_msg)) { + case TERMINATE_MESSAGE: + LOG_W(NRPPA, " *** Exiting NRPPA thread\n"); + itti_exit_task(); + break; + case NGAP_DOWNLINKUEASSOCIATEDNRPPA: + nrppa_handle_downlink_ue_associated_nrppa_transport(instance, &NGAP_DOWNLINKUEASSOCIATEDNRPPA(received_msg)); + break; + case NGAP_DOWNLINKNONUEASSOCIATEDNRPPA: + nrppa_handle_downlink_non_ue_associated_nrppa_transport(instance, &NGAP_DOWNLINKNONUEASSOCIATEDNRPPA(received_msg)); + break; + default: + LOG_E(NRPPA, "Received unhandled message: %d:%s\n", ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg)); + break; + } + result = itti_free(ITTI_MSG_ORIGIN_ID(received_msg), received_msg); + AssertFatal(result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); + } + return NULL; +} + +void *nrppa_gNB_task(void *arg) +{ + nrppa_gNB_init(); + + while (1) { + (void)nrppa_gNB_process_itti_msg(NULL); + } + + return NULL; +} diff --git a/openair3/NRPPA/nrppa_gNB.h b/openair3/NRPPA/nrppa_gNB.h new file mode 100644 index 0000000000..628cfc4587 --- /dev/null +++ b/openair3/NRPPA/nrppa_gNB.h @@ -0,0 +1,32 @@ +/* + * 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 + +#ifndef NRPPA_GNB_H_ +#define NRPPA_GNB_H_ + +void nrppa_gNB_init(void); +void *nrppa_gNB_process_itti_msg(void *notUsed); +void *nrppa_gNB_task(void *arg); + +#endif /* NRPPA_GNB_H_ */ diff --git a/openair3/NRPPA/nrppa_gNB_decoder.c b/openair3/NRPPA/nrppa_gNB_decoder.c new file mode 100644 index 0000000000..d197d0d141 --- /dev/null +++ b/openair3/NRPPA/nrppa_gNB_decoder.c @@ -0,0 +1,116 @@ +/* + * 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 "assertions.h" +#include "intertask_interface.h" +#include "nrppa_common.h" +#include "nrppa_gNB_decoder.h" + +static int nrppa_gNB_decode_initiating_message(NRPPA_NRPPA_PDU_t *pdu) +{ + asn_encode_to_new_buffer_result_t res = {NULL, {0, NULL, NULL}}; + DevAssert(pdu != NULL); + + switch (pdu->choice.initiatingMessage->procedureCode) { + case NRPPA_ProcedureCode_id_tRPInformationExchange: // TRPInformationRequest + res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NRPPA_NRPPA_PDU, pdu); + LOG_I(NRPPA, "TRP Information Request initiating message\n"); + free(res.buffer); + break; + + default: + AssertFatal(false, "Unknown procedure ID (%d) for initiating message\n", (int)pdu->choice.initiatingMessage->procedureCode); + return -1; + } + return 0; +} + +static int nrppa_gNB_decode_successful_outcome(NRPPA_NRPPA_PDU_t *pdu) +{ + asn_encode_to_new_buffer_result_t res = {NULL, {0, NULL, NULL}}; + DevAssert(pdu != NULL); + + switch (pdu->choice.successfulOutcome->procedureCode) { + case NRPPA_ProcedureCode_id_tRPInformationExchange: + res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NRPPA_NRPPA_PDU, pdu); + LOG_I(NRPPA, "TRP Information Response successfull outcome message\n"); + free(res.buffer); + break; + + default: + AssertFatal(false, + "Unknown procedure ID (%d) for successfull outcome message\n", + (int)pdu->choice.initiatingMessage->procedureCode); + return -1; + } + return 0; +} + +static int nrppa_gNB_decode_unsuccessful_outcome(NRPPA_NRPPA_PDU_t *pdu) +{ + asn_encode_to_new_buffer_result_t res = {NULL, {0, NULL, NULL}}; + DevAssert(pdu != NULL); + + switch (pdu->choice.unsuccessfulOutcome->procedureCode) { + case NRPPA_ProcedureCode_id_tRPInformationExchange: + res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NRPPA_NRPPA_PDU, pdu); + LOG_I(NRPPA, "TRP Information Failure unsuccessfull outcome message\n"); + free(res.buffer); + break; + + default: + AssertFatal(false, + "Unknown procedure ID (%d) for unsuccessfull outcome message\n", + (int)pdu->choice.initiatingMessage->procedureCode); + return -1; + } + return 0; +} + +int nrppa_gNB_decode_pdu(NRPPA_NRPPA_PDU_t *pdu, const uint8_t *const buffer, const uint32_t length) +{ + asn_dec_rval_t dec_ret; + DevAssert(pdu != NULL); + DevAssert(buffer != NULL); + asn_codec_ctx_t st = {.max_stack_size = 100 * 1000}; // if we enable asn1c debug the stack size become large + dec_ret = aper_decode(&st, &asn_DEF_NRPPA_NRPPA_PDU, (void **)&pdu, buffer, length, 0, 0); + if (dec_ret.code != RC_OK) { + LOG_E(NRPPA, "Failed to decode pdu\n"); + return -1; + } + + switch (pdu->present) { + case NRPPA_NRPPA_PDU_PR_initiatingMessage: + return nrppa_gNB_decode_initiating_message(pdu); + + case NRPPA_NRPPA_PDU_PR_successfulOutcome: + return nrppa_gNB_decode_successful_outcome(pdu); + + case NRPPA_NRPPA_PDU_PR_unsuccessfulOutcome: + return nrppa_gNB_decode_unsuccessful_outcome(pdu); + + default: + LOG_I(NRPPA, "Unknown presence (%d) or not implemented\n", (int)pdu->present); + break; + } + + return -1; +} diff --git a/openair3/NRPPA/nrppa_gNB_decoder.h b/openair3/NRPPA/nrppa_gNB_decoder.h new file mode 100644 index 0000000000..668208b8a5 --- /dev/null +++ b/openair3/NRPPA/nrppa_gNB_decoder.h @@ -0,0 +1,30 @@ +/* + * 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 "nrppa_common.h" + +#ifndef NRPPA_GNB_DECODER_H_ +#define NRPPA_GNB_DECODER_H_ + +int nrppa_gNB_decode_pdu(NRPPA_NRPPA_PDU_t *pdu, const uint8_t *const buffer, const uint32_t length) + __attribute__((warn_unused_result)); + +#endif /* NRPPA_GNB_DECODER_H_ */ diff --git a/openair3/NRPPA/nrppa_gNB_handlers.c b/openair3/NRPPA/nrppa_gNB_handlers.c new file mode 100644 index 0000000000..ce36e34d81 --- /dev/null +++ b/openair3/NRPPA/nrppa_gNB_handlers.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 "intertask_interface.h" +#include "nrppa_gNB_handlers.h" +#include "nrppa_gNB_decoder.h" +#include "nrppa_common.h" +#include "nrppa_gNB_location_information_transfer.h" + +char *nrppa_direction2String(int nrppa_dir) +{ + static char *nrppa_direction_String[] = { + "", /* Nothing */ + "Originating message", /* originating message */ + "Successfull outcome", /* successfull outcome */ + "UnSuccessfull outcome", /* successfull outcome */ + }; + return (nrppa_direction_String[nrppa_dir]); +} + +/* Handlers matrix. Only gNB related procedure present here */ +nrppa_message_decoded_callback nrppa_messages_callback[][3] = { + {0, 0, 0}, // NRPPA_ProcedureCode_id_errorIndication ((NRPPA_ProcedureCode_t)0) + {0, 0, 0}, // NRPPA_ProcedureCode_id_privateMessage ((NRPPA_ProcedureCode_t)1) + {0, 0, 0}, // NRPPA_ProcedureCode_id_e_CIDMeasurementInitiation ((NRPPA_ProcedureCode_t)2) + {0, 0, 0}, // NRPPA_ProcedureCode_id_e_CIDMeasurementFailureIndication ((NRPPA_ProcedureCode_t)3) + {0, 0, 0}, // NRPPA_ProcedureCode_id_e_CIDMeasurementReport ((NRPPA_ProcedureCode_t)4) + {0, 0, 0}, // NRPPA_ProcedureCode_id_e_CIDMeasurementTermination ((NRPPA_ProcedureCode_t)5) + {0, 0, 0}, // NRPPA_ProcedureCode_id_oTDOAInformationExchange ((NRPPA_ProcedureCode_t)6) + {0, 0, 0}, // NRPPA_ProcedureCode_id_assistanceInformationControl ((NRPPA_ProcedureCode_t)7) + {0, 0, 0}, // NRPPA_ProcedureCode_id_assistanceInformationFeedback ((NRPPA_ProcedureCode_t)8) + {0, 0, 0}, // NRPPA_ProcedureCode_id_positioningInformationExchange ((NRPPA_ProcedureCode_t)9) + {0, 0, 0}, // NRPPA_ProcedureCode_id_positioningInformationUpdate ((NRPPA_ProcedureCode_t)10) + {0, 0, 0}, // NRPPA_ProcedureCode_id_Measurement ((NRPPA_ProcedureCode_t)11) + {0, 0, 0}, // NRPPA_ProcedureCode_id_MeasurementReport ((NRPPA_ProcedureCode_t)12) + {0, 0, 0}, // NRPPA_ProcedureCode_id_MeasurementUpdate ((NRPPA_ProcedureCode_t)13) + {0, 0, 0}, // NRPPA_ProcedureCode_id_MeasurementAbort ((NRPPA_ProcedureCode_t)14) + {0, 0, 0}, // NRPPA_ProcedureCode_id_MeasurementFailureIndication ((NRPPA_ProcedureCode_t)15) + {nrppa_gNB_handle_trp_information_request, 0, 0}, // NRPPA_ProcedureCode_id_tRPInformationExchange ((NRPPA_ProcedureCode_t)16) + {0, 0, 0}, // NRPPA_ProcedureCode_id_positioningActivation ((NRPPA_ProcedureCode_t)17) + {0, 0, 0}, // NRPPA_ProcedureCode_id_positioningDeactivation ((NRPPA_ProcedureCode_t)18) +}; + +// Processing DOWNLINK UE ASSOCIATED NRPPA TRANSPORT (9.2.9.1 of TS 38.413 Version 16.0.0) +int nrppa_handle_downlink_ue_associated_nrppa_transport(instance_t instance, const ngap_downlink_ue_associated_nrppa_t *msg) +{ + LOG_I(NRPPA, "Handling DOWNLINKUEASSOCIATEDNRPPA TRANSPORT\n"); + uint8_t *const data = msg->nrppa_pdu.buf; + const uint32_t data_length = msg->nrppa_pdu.len; + NRPPA_NRPPA_PDU_t pdu; + int ret; + DevAssert(data != NULL); + memset(&pdu, 0, sizeof(pdu)); + + if (nrppa_gNB_decode_pdu(&pdu, data, data_length) < 0) { + LOG_E(NRPPA, "Failed to decode PDU\n"); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NRPPA_NRPPA_PDU, &pdu); + return -1; + } + /* Checking procedure Code and direction of message*/ + if (pdu.choice.initiatingMessage->procedureCode >= sizeof(nrppa_messages_callback) / (3 * sizeof(nrppa_message_decoded_callback)) + || (pdu.present > NRPPA_NRPPA_PDU_PR_unsuccessfulOutcome)) { + LOG_E(NRPPA, + "Either procedureCode %ld or direction %d exceed expected\n", + pdu.choice.initiatingMessage->procedureCode, + pdu.present); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NRPPA_NRPPA_PDU, &pdu); + return -1; + } + + /* No handler present. + * This can mean not implemented or no procedure for gNB (wrong direction).*/ + if (nrppa_messages_callback[pdu.choice.initiatingMessage->procedureCode][pdu.present - 1] == NULL) { + LOG_E(NRPPA, + "No handler for procedureCode %ld in %s\n", + pdu.choice.initiatingMessage->procedureCode, + nrppa_direction2String(pdu.present - 1)); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NRPPA_NRPPA_PDU, &pdu); + return -1; + } + + /* Calling the right handler*/ + nrppa_gnb_ue_info_t nrppa_msg_info; + nrppa_msg_info.instance = instance; + nrppa_msg_info.gNB_ue_ngap_id = msg->gNB_ue_ngap_id; + nrppa_msg_info.amf_ue_ngap_id = msg->amf_ue_ngap_id; + nrppa_msg_info.routing_id.buf = msg->routing_id.buf; + nrppa_msg_info.routing_id.len = msg->routing_id.len; + ret = (*nrppa_messages_callback[pdu.choice.initiatingMessage->procedureCode][pdu.present - 1])(&nrppa_msg_info, &pdu); + + if (msg->routing_id.buf) { + free(msg->routing_id.buf); + } + + if (msg->nrppa_pdu.buf) { + free(msg->nrppa_pdu.buf); + } + + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NRPPA_NRPPA_PDU, &pdu); + return ret; +} + +// Processing DOWNLINK NON UE ASSOCIATED NRPPA TRANSPORT (9.2.9.3 of TS 38.413 Version 16.0.0) +int nrppa_handle_downlink_non_ue_associated_nrppa_transport(instance_t instance, const ngap_downlink_non_ue_associated_nrppa_t *msg) +{ + LOG_I(NRPPA, "Handling DOWNLINKNONUEASSOCIATEDNRPPA TRANSPORT\n"); + uint8_t *const data = msg->nrppa_pdu.buf; + const uint32_t data_length = msg->nrppa_pdu.len; + NRPPA_NRPPA_PDU_t pdu; + int ret; + DevAssert(data != NULL); + memset(&pdu, 0, sizeof(pdu)); + + if (nrppa_gNB_decode_pdu(&pdu, data, data_length) < 0) { + LOG_E(NRPPA, "Failed to decode Downlink Non UE Associated NRPPa PDU\n"); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NRPPA_NRPPA_PDU, &pdu); + return -1; + } + + /* Checking procedure Code and direction of message*/ + if (pdu.choice.initiatingMessage->procedureCode >= sizeof(nrppa_messages_callback) / (3 * sizeof(nrppa_message_decoded_callback)) + || (pdu.present > NRPPA_NRPPA_PDU_PR_unsuccessfulOutcome)) { + LOG_E(NRPPA, + "Either procedureCode %ld or direction %d exceed expected\n", + pdu.choice.initiatingMessage->procedureCode, + pdu.present); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NRPPA_NRPPA_PDU, &pdu); + return -1; + } + + /* No handler present. + * This can mean not implemented or no procedure for gNB (wrong direction).*/ + if (nrppa_messages_callback[pdu.choice.initiatingMessage->procedureCode][pdu.present - 1] == NULL) { + LOG_E(NRPPA, + "No handler for procedureCode %ld in %s\n", + pdu.choice.initiatingMessage->procedureCode, + nrppa_direction2String(pdu.present - 1)); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NRPPA_NRPPA_PDU, &pdu); + return -1; + } + + /* Calling the right handler*/ + nrppa_gnb_ue_info_t nrppa_msg_info; + nrppa_msg_info.instance = instance; + nrppa_msg_info.gNB_ue_ngap_id = 0; // non-ue associated + nrppa_msg_info.amf_ue_ngap_id = 0; // non-ue associated + nrppa_msg_info.routing_id.buf = msg->routing_id.buf; + nrppa_msg_info.routing_id.len = msg->routing_id.len; + ret = (*nrppa_messages_callback[pdu.choice.initiatingMessage->procedureCode][pdu.present - 1])(&nrppa_msg_info, &pdu); + + if (msg->routing_id.buf) { + free(msg->routing_id.buf); + } + + if (msg->nrppa_pdu.buf) { + free(msg->nrppa_pdu.buf); + } + + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NRPPA_NRPPA_PDU, &pdu); + return ret; +} diff --git a/openair3/NRPPA/nrppa_gNB_handlers.h b/openair3/NRPPA/nrppa_gNB_handlers.h new file mode 100644 index 0000000000..ecee41caa1 --- /dev/null +++ b/openair3/NRPPA/nrppa_gNB_handlers.h @@ -0,0 +1,28 @@ +/* + * 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 NRPPA_GNB_HANDLERS_H_ +#define NRPPA_GNB_HANDLERS_H_ + +int nrppa_handle_downlink_ue_associated_nrppa_transport(instance_t instance, const ngap_downlink_ue_associated_nrppa_t *msg); +int nrppa_handle_downlink_non_ue_associated_nrppa_transport(instance_t instance, + const ngap_downlink_non_ue_associated_nrppa_t *msg); +#endif /* NRPPA_GNB_HANDLERS_H_ */ diff --git a/openair3/NRPPA/nrppa_gNB_location_information_transfer.c b/openair3/NRPPA/nrppa_gNB_location_information_transfer.c new file mode 100644 index 0000000000..6a617ea02b --- /dev/null +++ b/openair3/NRPPA/nrppa_gNB_location_information_transfer.c @@ -0,0 +1,95 @@ +/* + * 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 "intertask_interface.h" +#include "nrppa_common.h" +#include "nrppa_gNB_location_information_transfer.h" +#include "nrppa_gNB_ue_context.h" +#include "nrppa_messages_types.h" + +void free_trp_information_request(nrppa_trp_information_req_t *msg) +{ + if (msg->trp_information_type_list.trp_information_type_item) { + free(msg->trp_information_type_list.trp_information_type_item); + } +} + +int nrppa_gNB_handle_trp_information_request(nrppa_gnb_ue_info_t *nrppa_msg_info, const NRPPA_NRPPA_PDU_t *pdu) +{ + LOG_I(NRPPA, "Processing Received TRP Information Request \n"); + DevAssert(pdu != NULL); + DevAssert(nrppa_msg_info != NULL); + + if (LOG_DEBUGFLAG(DEBUG_ASN1)) { + xer_fprint(stdout, &asn_DEF_NRPPA_NRPPA_PDU, pdu); + } + + // Forward request to RRC + MessageDef *msg = itti_alloc_new_message(TASK_RRC_GNB, 0, NRPPA_TRP_INFORMATION_REQ); + nrppa_trp_information_req_t *req = &NRPPA_TRP_INFORMATION_REQ(msg); + + // Processing Received TRPInformationRequest + NRPPA_TRPInformationRequest_t *container = NULL; + NRPPA_TRPInformationRequest_IEs_t *ie = NULL; + + // IE 9.2.3 Message type : mandatory + container = &pdu->choice.initiatingMessage->value.choice.TRPInformationRequest; + + // IE 9.2.4 nrppatransactionID : mandatory + req->transaction_id = pdu->choice.initiatingMessage->nrppatransactionID; + + // IE TRP List : optional + NRPPA_FIND_PROTOCOLIE_BY_ID(NRPPA_TRPInformationRequest_IEs_t, ie, container, NRPPA_ProtocolIE_ID_id_TRPList, false); + + if (ie == NULL) { + req->has_trp_list = false; + } else { + LOG_W(NRPPA, "TRPInformationRequest IE TRP List : not handled\n"); + } + + // IE TRP Information Type List: mandatory + // not implemented in oai-lmf + NRPPA_FIND_PROTOCOLIE_BY_ID(NRPPA_TRPInformationRequest_IEs_t, + ie, + container, + NRPPA_ProtocolIE_ID_id_TRPInformationTypeList, + false); + + if (ie == NULL) { + LOG_W(NRPPA, "TRPInformationRequest IE TRP Information Type List is mandatory but not handled\n"); + } else { + uint8_t trp_info_list_len = ie->value.choice.TRPInformationTypeList.list.count; + AssertError(trp_info_list_len > 0, return false, "at least 1 TRP Information Type must be present"); + nrppa_trp_information_type_list_t *trp_info_list = &req->trp_information_type_list; + trp_info_list->trp_information_type_list_length = trp_info_list_len; + trp_info_list->trp_information_type_item = calloc_or_fail(trp_info_list_len, sizeof(*trp_info_list->trp_information_type_item)); + for (int i = 0; i < trp_info_list_len; i++) { + trp_info_list->trp_information_type_item[i] = *ie->value.choice.TRPInformationTypeList.list.array[i]; + } + } + + nrppa_store_ue_context(nrppa_msg_info, req->transaction_id); + + LOG_I(NRPPA, "Forwarding to RRC TRPInformationRequest transaction_id=%d\n", req->transaction_id); + itti_send_msg_to_task(TASK_RRC_GNB, 0, msg); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NRPPA_NRPPA_PDU, &pdu); + return 0; +} diff --git a/openair3/NRPPA/nrppa_gNB_location_information_transfer.h b/openair3/NRPPA/nrppa_gNB_location_information_transfer.h new file mode 100644 index 0000000000..5295505b22 --- /dev/null +++ b/openair3/NRPPA/nrppa_gNB_location_information_transfer.h @@ -0,0 +1,28 @@ +/* + * 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 NRPPA_GNB_POSITIONING_PROCEDURES_H_ +#define NRPPA_GNB_POSITIONING_PROCEDURES_H_ + +int nrppa_gNB_handle_trp_information_request(nrppa_gnb_ue_info_t *nrppa_msg_info, const NRPPA_NRPPA_PDU_t *pdu); +void free_trp_information_request(nrppa_trp_information_req_t *msg); + +#endif /* NRPPA_GNB_POSITIONING_PROCEDURES_H_ */ diff --git a/openair3/NRPPA/nrppa_gNB_ue_context.c b/openair3/NRPPA/nrppa_gNB_ue_context.c new file mode 100644 index 0000000000..1a1a0e7c0e --- /dev/null +++ b/openair3/NRPPA/nrppa_gNB_ue_context.c @@ -0,0 +1,85 @@ +/* + * 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 "nrppa_gNB_ue_context.h" +#include "tree.h" +#include "T.h" +#include "common/utils/T/T.h" +#include "common/utils/utils.h" +#include "common/utils/LOG/log.h" + +static RB_HEAD(nrppa_ue_map, nrppa_gNB_ue_context_s) nrppa_ue_head = RB_INITIALIZER(&nrppa_ue_head); + +/* Generate the tree management functions prototypes */ +RB_PROTOTYPE(nrppa_ue_map, nrppa_gNB_ue_context_s, entries, nrppa_gNB_compare_transaction_id); + +static int nrppa_gNB_compare_transaction_id(struct nrppa_gNB_ue_context_s *p1, struct nrppa_gNB_ue_context_s *p2) +{ + if (p1->transaction_id > p2->transaction_id) { + return 1; + } + + if (p1->transaction_id < p2->transaction_id) { + return -1; + } + + return 0; +} + +/* Generate the tree management functions */ +RB_GENERATE(nrppa_ue_map, nrppa_gNB_ue_context_s, entries, nrppa_gNB_compare_transaction_id); + +void nrppa_store_ue_context(const nrppa_gnb_ue_info_t *info, const uint16_t transaction_id) +{ + LOG_I(NRPPA, "Create NRPPa UE context (gNB UE ID %u) for transaction ID : %u\n", info->gNB_ue_ngap_id, transaction_id); + nrppa_gNB_ue_context_t *ue_info_p = calloc_or_fail(1, sizeof(*ue_info_p)); + ue_info_p->transaction_id = transaction_id; + ue_info_p->gNB_ue_ngap_id = info->gNB_ue_ngap_id; + ue_info_p->amf_ue_ngap_id = info->amf_ue_ngap_id; + if (info->routing_id.len > 0 && info->routing_id.buf != NULL) { + ue_info_p->routing_id.len = info->routing_id.len; + ue_info_p->routing_id.buf = calloc_or_fail(1, info->routing_id.len); + memcpy(ue_info_p->routing_id.buf, info->routing_id.buf, info->routing_id.len); + } else { + ue_info_p->routing_id.len = 0; + ue_info_p->routing_id.buf = NULL; + } + if (RB_INSERT(nrppa_ue_map, &nrppa_ue_head, ue_info_p)) + LOG_E(NRPPA, "Bug in UE uniq number allocation %u, we try to add a existing UE\n", ue_info_p->gNB_ue_ngap_id); + return; +} + +struct nrppa_gNB_ue_context_s *nrppa_get_ue_context(uint16_t transaction_id) +{ + nrppa_gNB_ue_context_t temp = {.transaction_id = transaction_id}; + return RB_FIND(nrppa_ue_map, &nrppa_ue_head, &temp); +} + +struct nrppa_gNB_ue_context_s *nrppa_detach_ue_context(uint16_t transaction_id) +{ + struct nrppa_gNB_ue_context_s *tmp = nrppa_get_ue_context(transaction_id); + if (tmp == NULL) { + LOG_E(NRPPA, "Trying to free a NULL UE context, %u\n", transaction_id); + return NULL; + } + RB_REMOVE(nrppa_ue_map, &nrppa_ue_head, tmp); + return tmp; +} diff --git a/openair3/NRPPA/nrppa_gNB_ue_context.h b/openair3/NRPPA/nrppa_gNB_ue_context.h new file mode 100644 index 0000000000..1aaeabe359 --- /dev/null +++ b/openair3/NRPPA/nrppa_gNB_ue_context.h @@ -0,0 +1,43 @@ +/* + * 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 "tree.h" +#include "ds/byte_array.h" +#include "nrppa_common.h" + +#ifndef NRPPA_GNB_UE_CONTEXT_H_ +#define NRPPA_GNB_UE_CONTEXT_H_ + +typedef struct nrppa_gNB_ue_context_s { + /* Tree related data */ + RB_ENTRY(nrppa_gNB_ue_context_s) entries; + uint16_t transaction_id; + uint32_t gNB_ue_ngap_id; + uint64_t amf_ue_ngap_id; + byte_array_t routing_id; +} nrppa_gNB_ue_context_t; + +void nrppa_store_ue_context(const nrppa_gnb_ue_info_t *info, const uint16_t transaction_id); +nrppa_gNB_ue_context_t *nrppa_get_ue_context(uint16_t transaction_id); +nrppa_gNB_ue_context_t *nrppa_detach_ue_context(uint16_t transaction_id); + +#endif /* NRPPA_GNB_UE_CONTEXT_H_ */ diff --git a/openair3/NRPPA/nrppa_includes.h b/openair3/NRPPA/nrppa_includes.h new file mode 100644 index 0000000000..8239033926 --- /dev/null +++ b/openair3/NRPPA/nrppa_includes.h @@ -0,0 +1,39 @@ +/* + * 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 NRPPA_INCLUDE_H_ +#define NRPPA_INCLUDE_H_ + +#include "NRPPA_NRPPA-PDU.h" +#include "NRPPA_InitiatingMessage.h" +#include "NRPPA_SuccessfulOutcome.h" +#include "NRPPA_UnsuccessfulOutcome.h" +#include "NRPPA_ProtocolIE-ID.h" +#include "NRPPA_ProtocolIE-Field.h" +#include "NRPPA_ProtocolIE-Container.h" +#include "NRPPA_ProtocolExtensionField.h" +#include "NRPPA_ProtocolIE-ContainerList.h" +#include "NRPPA_ProtocolExtensionContainer.h" +#include "NRPPA_ProtocolIE-Single-Container.h" +#include "NRPPA_asn_constant.h" +#include "NRPPA_TRPInformationRequest.h" + +#endif /* NRPPA_INCLUDE_H_ */ diff --git a/tests/nr-cu-nrppa/CMakeLists.txt b/tests/nr-cu-nrppa/CMakeLists.txt index 1db9b33e37..f24ff4b880 100644 --- a/tests/nr-cu-nrppa/CMakeLists.txt +++ b/tests/nr-cu-nrppa/CMakeLists.txt @@ -5,6 +5,6 @@ add_executable(nr-cu-nrppa-test nr-cu-nrppa.c target_link_libraries(nr-cu-nrppa-test PRIVATE CONFIG_LIB ITTI SCTP_CLIENT f1ap ngap SECURITY - UTIL softmodem_common) + UTIL softmodem_common nrppa) target_link_libraries(nr-cu-nrppa-test PRIVATE asn1_lte_rrc_hdrs asn1_nr_rrc_hdrs) add_dependencies(nr-cu-nrppa-test params_libconfig) diff --git a/tests/nr-cu-nrppa/nr-cu-nrppa.c b/tests/nr-cu-nrppa/nr-cu-nrppa.c index 2c29ce6258..893ee63e8c 100644 --- a/tests/nr-cu-nrppa/nr-cu-nrppa.c +++ b/tests/nr-cu-nrppa/nr-cu-nrppa.c @@ -28,6 +28,7 @@ #include "openair2/GNB_APP/gnb_paramdef.h" #include "openair3/SCTP/sctp_default_values.h" #include "openair3/NRPPA/nrppa_gNB_config.h" +#include "openair3/NRPPA/nrppa_gNB.h" RAN_CONTEXT_t RC; THREAD_STRUCT thread_struct; @@ -83,6 +84,9 @@ int main(int argc, char **argv) rc = itti_create_task(TASK_NGAP, ngap_gNB_task, NULL); AssertFatal(rc >= 0, "Create task for NGAP failed\n"); + rc = itti_create_task(TASK_NRPPA, nrppa_gNB_task, NULL); + AssertFatal(rc >= 0, "Create task for NRPPA failed\n"); + MessageDef *msg_p; msg_p = itti_alloc_new_message(TASK_GNB_APP, 0, NGAP_REGISTER_GNB_REQ); RCconfig_NR_NG(msg_p, 0); From 0282e64a3bc659faa3ca556a6161e88c2703f473 Mon Sep 17 00:00:00 2001 From: Rakesh Mundlamuri Date: Thu, 22 Jan 2026 18:51:27 +0530 Subject: [PATCH 13/21] Add TRP Information Response NRPPA message encoding procedures Supported TRP Information Response Types: - PCI NR - NG RAN CGI - NR ARFCN - GEOGRAPHICAL COORDINATES --- openair2/COMMON/nrppa_messages_def.h | 1 + openair2/COMMON/nrppa_messages_types.h | 181 ++++++++++ openair3/NRPPA/CMakeLists.txt | 1 + openair3/NRPPA/nrppa_gNB.c | 3 + openair3/NRPPA/nrppa_gNB_encoder.c | 135 ++++++++ openair3/NRPPA/nrppa_gNB_encoder.h | 27 ++ .../nrppa_gNB_location_information_transfer.c | 322 ++++++++++++++++++ .../nrppa_gNB_location_information_transfer.h | 4 + openair3/NRPPA/nrppa_gNB_ue_context.c | 11 + openair3/NRPPA/nrppa_gNB_ue_context.h | 1 + openair3/NRPPA/nrppa_includes.h | 7 + tests/nr-cu-nrppa/nr-cu-nrppa.c | 108 ++++++ 12 files changed, 801 insertions(+) create mode 100644 openair3/NRPPA/nrppa_gNB_encoder.c create mode 100644 openair3/NRPPA/nrppa_gNB_encoder.h diff --git a/openair2/COMMON/nrppa_messages_def.h b/openair2/COMMON/nrppa_messages_def.h index ae17d73742..ecca67ba33 100644 --- a/openair2/COMMON/nrppa_messages_def.h +++ b/openair2/COMMON/nrppa_messages_def.h @@ -23,3 +23,4 @@ // LMF -> CU MESSAGE_DEF(NRPPA_TRP_INFORMATION_REQ, MESSAGE_PRIORITY_MED, nrppa_trp_information_req_t, nrppa_trp_information_req) +MESSAGE_DEF(NRPPA_TRP_INFORMATION_RESP, MESSAGE_PRIORITY_MED, nrppa_trp_information_resp_t, nrppa_trp_information_resp) diff --git a/openair2/COMMON/nrppa_messages_types.h b/openair2/COMMON/nrppa_messages_types.h index 55563a59ab..f461909a35 100644 --- a/openair2/COMMON/nrppa_messages_types.h +++ b/openair2/COMMON/nrppa_messages_types.h @@ -25,6 +25,7 @@ // Defines to access message fields. #define NRPPA_TRP_INFORMATION_REQ(mSGpTR) (mSGpTR)->ittiMsg.nrppa_trp_information_req +#define NRPPA_TRP_INFORMATION_RESP(mSGpTR) (mSGpTR)->ittiMsg.nrppa_trp_information_resp /* Structure of Positioning related NRPPA messages */ /* IE structures for Positioning related messages as per TS 38.455 V16.7.1*/ @@ -54,6 +55,179 @@ typedef struct nrppa_trp_list_s { uint32_t trp_list_length; } nrppa_trp_list_t; +typedef struct nrppa_access_point_position_s { + long latitude_sign; + long latitude; + long longitude; + long direction_of_altitude; + long altitude; + long uncertainty_semi_major; + long uncertainty_semi_minor; + long orientation_of_major_axis; + long uncertainty_altitude; + long confidence; +} nrppa_access_point_position_t; + +typedef struct nrppa_ngran_high_accuracy_access_point_position_s { + long latitude; + long longitude; + long altitude; + long uncertainty_semi_major; + long uncertainty_semi_minor; + long orientation_of_major_axis; + long horizontal_confidence; + long uncertainty_altitude; + long vertical_confidence; +} nrppa_ngran_high_accuracy_access_point_position_t; + +typedef union nrppa_trp_position_direct_accuracy_c { + nrppa_access_point_position_t trp_position; + nrppa_ngran_high_accuracy_access_point_position_t trp_HAposition; +} nrppa_trp_position_direct_accuracy_u; + +typedef enum nrppa_trp_position_direct_accuracy_e { + NRPPA_TRP_POSITION_DIRECT_ACCURACY_PR_NOTHING, + NRPPA_TRP_POSITION_DIRECT_ACCURACY_PR_TRPPOSITION, + NRPPA_TRP_POSITION_DIRECT_ACCURACY_PR_TRPHAPOSITION +} nrppa_trp_position_direct_accuracy_pr; + +typedef struct nrppa_trp_position_direct_accuracy_s { + nrppa_trp_position_direct_accuracy_pr present; + nrppa_trp_position_direct_accuracy_u choice; +} nrppa_trp_position_direct_accuracy_t; + +typedef struct nrppa_trp_position_direct_s { + nrppa_trp_position_direct_accuracy_t accuracy; +} nrppa_trp_position_direct_t; + +typedef enum nrppa_reference_point_e { + NRPPA_REFERENCE_POINT_PR_NOTHING, + NRPPA_REFERENCE_POINT_PR_COORDINATEID, + NRPPA_REFERENCE_POINT_PR_REFERENCEPOINTCOORDINATE, + NRPPA_REFERENCE_POINT_PR_REFERENCEPOINTCOORDINATEHA +} nrppa_reference_point_pr; + +typedef union nrppa_reference_point_c { + long coordinate_id; + nrppa_access_point_position_t reference_point_coordinate; + nrppa_ngran_high_accuracy_access_point_position_t reference_point_coordinateHA; +} nrppa_reference_point_u; + +typedef struct nrppa_reference_point_s { + nrppa_reference_point_pr present; + nrppa_reference_point_u choice; +} nrppa_reference_point_t; + +typedef struct nrppa_location_uncertainty_s { + long horizontal_uncertainty; + long horizontal_confidence; + long vertical_uncertainty; + long vertical_confidence; +} nrppa_location_uncertainty_t; + +typedef struct nrppa_relative_geodetic_location_s { + long milli_arc_second_units; + long height_units; + long delta_latitude; + long delta_longitude; + long delta_height; + nrppa_location_uncertainty_t location_uncertainty; +} nrppa_relative_geodetic_location_t; + +typedef struct nrppa_relative_cartesian_location_s { + long xyz_unit; + long xvalue; + long yvalue; + long zvalue; + nrppa_location_uncertainty_t location_uncertainty; +} nrppa_relative_cartesian_location_t; + +typedef union nrppa_trp_reference_point_type_c { + nrppa_relative_geodetic_location_t trp_position_relative_geodetic; + nrppa_relative_cartesian_location_t trp_position_relative_cartesian; +} nrppa_trp_reference_point_type_u; + +typedef enum nrppa_trp_reference_point_type_e { + NRPPA_TRP_REFERENCE_POINT_TYPE_PR_NOTHING, + NRPPA_TRP_REFERENCE_POINT_TYPE_PR_TRPPOSITION_RELATIVE_GEODETIC, + NRPPA_TRP_REFERENCE_POINT_TYPE_PR_TRPPOSITION_RELATIVE_CARTESIAN +} nrppa_trp_reference_point_type_pr; + +typedef struct nrppa_trp_reference_point_type_t { + nrppa_trp_reference_point_type_pr present; + nrppa_trp_reference_point_type_u choice; +} nrppa_trp_reference_point_type_t; + +typedef struct nrppa_trp_position_referenced_t { + nrppa_reference_point_t reference_point; + nrppa_trp_reference_point_type_t reference_point_type; +} nrppa_trp_position_referenced_t; + +typedef union nrppa_trp_position_definition_type_c { + nrppa_trp_position_direct_t direct; + nrppa_trp_position_referenced_t referenced; +} nrppa_trp_position_definition_type_u; + +typedef enum nrppa_trp_position_definition_type_e { + NRPPA_TRP_POSITION_DEFINITION_TYPE_PR_NOTHING, + NRPPA_TRP_POSITION_DEFINITION_TYPE_PR_DIRECT, + NRPPA_TRP_POSITION_DEFINITION_TYPE_PR_REFERENCED +} nrppa_trp_position_definition_type_pr; + +typedef struct nrppa_trp_position_definition_type_s { + nrppa_trp_position_definition_type_u choice; + nrppa_trp_position_definition_type_pr present; +} nrppa_trp_position_definition_type_t; + +typedef struct nrppa_geographical_coordinates_s { + nrppa_trp_position_definition_type_t trp_position_definition_type; +} nrppa_geographical_coordinates_t; + +typedef struct nrppa_ng_ran_cgi_s { + plmn_id_t plmn; + uint64_t nr_cellid; +} nrppa_ng_ran_cgi_t; + +typedef union nrppa_trp_information_type_response_item_c { + uint16_t pci_nr; + nrppa_ng_ran_cgi_t ng_ran_cgi; + uint32_t nr_arfcn; + nrppa_geographical_coordinates_t geographical_coordinates; +} nrppa_trp_information_type_response_item_u; + +typedef enum nrppa_trp_information_type_response_item_e { + NRPPA_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_NOTHING, + NRPPA_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_PCI_NR, + NRPPA_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_NG_RAN_CGI, + NRPPA_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_NRARFCN, + NRPPA_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_PRSCONFIGURATION, + NRPPA_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_SSBINFORMATION, + NRPPA_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_SFNINITIALISATIONTIME, + NRPPA_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_SPATIALDIRECTIONINFORMATION, + NRPPA_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_GEOGRAPHICALCOORDINATES +} nrppa_trp_information_type_response_item_pr; + +typedef struct nrppa_trp_information_type_response_item_s { + nrppa_trp_information_type_response_item_pr present; + nrppa_trp_information_type_response_item_u choice; +} nrppa_trp_information_type_response_item_t; + +typedef struct nrppa_trp_information_type_response_list_s { + nrppa_trp_information_type_response_item_t *trp_information_type_response_item; + uint8_t trp_information_type_response_item_length; +} nrppa_trp_information_type_response_list_t; + +typedef struct nrppa_trp_information_s { + uint32_t trp_id; + nrppa_trp_information_type_response_list_t trp_information_type_response_list; +} nrppa_trp_information_t; + +// IE 9.3.1.176 (TS 38.473 V16.21.0) +typedef struct nrppa_trp_information_list_s { + nrppa_trp_information_t *trp_information_item; + uint32_t trp_information_item_length; +} nrppa_trp_information_list_t; + typedef struct nrppa_trp_information_req_s { // IE 9.2.4 (mandatory) uint16_t transaction_id; @@ -64,4 +238,11 @@ typedef struct nrppa_trp_information_req_s { nrppa_trp_information_type_list_t trp_information_type_list; } nrppa_trp_information_req_t; +typedef struct nrppa_trp_information_resp_s { + // IE 9.2.4 (mandatory) + uint16_t transaction_id; + // mandatory + nrppa_trp_information_list_t trp_information_list; +} nrppa_trp_information_resp_t; + #endif // NRPPA_MESSAGES_TYPES_H_ diff --git a/openair3/NRPPA/CMakeLists.txt b/openair3/NRPPA/CMakeLists.txt index 28ad4c8618..7ec77db3b5 100644 --- a/openair3/NRPPA/CMakeLists.txt +++ b/openair3/NRPPA/CMakeLists.txt @@ -7,6 +7,7 @@ add_library(nrppa nrppa_gNB_decoder.c nrppa_gNB_ue_context.c nrppa_gNB_location_information_transfer.c + nrppa_gNB_encoder.c ) target_link_libraries(nrppa PUBLIC asn1_nrppa) diff --git a/openair3/NRPPA/nrppa_gNB.c b/openair3/NRPPA/nrppa_gNB.c index d7f067de98..bb00cecd54 100644 --- a/openair3/NRPPA/nrppa_gNB.c +++ b/openair3/NRPPA/nrppa_gNB.c @@ -57,6 +57,9 @@ void *nrppa_gNB_process_itti_msg(void *notUsed) case NGAP_DOWNLINKNONUEASSOCIATEDNRPPA: nrppa_handle_downlink_non_ue_associated_nrppa_transport(instance, &NGAP_DOWNLINKNONUEASSOCIATEDNRPPA(received_msg)); break; + case NRPPA_TRP_INFORMATION_RESP: + nrppa_gNB_trp_information_response(instance, received_msg); + break; default: LOG_E(NRPPA, "Received unhandled message: %d:%s\n", ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg)); break; diff --git a/openair3/NRPPA/nrppa_gNB_encoder.c b/openair3/NRPPA/nrppa_gNB_encoder.c new file mode 100644 index 0000000000..9ac0c4ecb0 --- /dev/null +++ b/openair3/NRPPA/nrppa_gNB_encoder.c @@ -0,0 +1,135 @@ +/* + * 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 "nrppa_common.h" +#include "nrppa_gNB_encoder.h" + +static inline int nrppa_gNB_encode_initiating(NRPPA_NRPPA_PDU_t *pdu, uint8_t **buffer, uint32_t *len) +{ + DevAssert(pdu != NULL); + + const NRPPA_ProcedureCode_t tmp[] = {NRPPA_ProcedureCode_id_positioningInformationExchange, + NRPPA_ProcedureCode_id_positioningActivation, + NRPPA_ProcedureCode_id_positioningInformationUpdate, + NRPPA_ProcedureCode_id_positioningDeactivation, + NRPPA_ProcedureCode_id_tRPInformationExchange, + NRPPA_ProcedureCode_id_Measurement, + NRPPA_ProcedureCode_id_MeasurementReport, + NRPPA_ProcedureCode_id_MeasurementFailureIndication, + NRPPA_ProcedureCode_id_MeasurementAbort, + NRPPA_ProcedureCode_id_MeasurementUpdate}; + + int i; + for (i = 0; i < sizeofArray(tmp); i++) + if (pdu->choice.initiatingMessage->procedureCode == tmp[i]) + break; + if (i == sizeofArray(tmp)) { + LOG_E(NRPPA, "Unknown procedure ID (%d) for initiating message\n", (int)pdu->choice.initiatingMessage->procedureCode); + return -1; + } + + asn_encode_to_new_buffer_result_t res = asn_encode_to_new_buffer(NULL, ATS_ALIGNED_CANONICAL_PER, &asn_DEF_NRPPA_NRPPA_PDU, pdu); + AssertFatal(res.result.encoded > 0, "failed to encode NRPPA msg\n"); + *buffer = res.buffer; + *len = res.result.encoded; + return 0; +} + +static inline int nrppa_gNB_encode_successfull_outcome(NRPPA_NRPPA_PDU_t *pdu, uint8_t **buffer, uint32_t *len) +{ + DevAssert(pdu != NULL); + const NRPPA_ProcedureCode_t tmp[] = {NRPPA_ProcedureCode_id_positioningInformationExchange, + NRPPA_ProcedureCode_id_positioningActivation, + NRPPA_ProcedureCode_id_tRPInformationExchange, + NRPPA_ProcedureCode_id_Measurement}; + int i; + for (i = 0; i < sizeofArray(tmp); i++) + if (pdu->choice.successfulOutcome->procedureCode == tmp[i]) + break; + if (i == sizeofArray(tmp)) { + LOG_E(NRPPA, "Unknown procedure ID (%ld) for successfull outcome message\n", pdu->choice.successfulOutcome->procedureCode); + return -1; + } + // xer_fprint(stdout, &asn_DEF_NRPPA_NRPPA_PDU, pdu); + asn_encode_to_new_buffer_result_t res = asn_encode_to_new_buffer(NULL, ATS_ALIGNED_CANONICAL_PER, &asn_DEF_NRPPA_NRPPA_PDU, pdu); + AssertFatal(res.result.encoded > 0, "failed to encode NRPPA msg\n"); + *buffer = res.buffer; + *len = res.result.encoded; + return 0; +} + +static inline int nrppa_gNB_encode_unsuccessfull_outcome(NRPPA_NRPPA_PDU_t *pdu, uint8_t **buffer, uint32_t *len) +{ + DevAssert(pdu != NULL); + + const NRPPA_ProcedureCode_t tmp[] = {NRPPA_ProcedureCode_id_positioningInformationExchange, + NRPPA_ProcedureCode_id_positioningActivation, + NRPPA_ProcedureCode_id_tRPInformationExchange, + NRPPA_ProcedureCode_id_Measurement}; + + int i; + for (i = 0; i < sizeofArray(tmp); i++) + if (pdu->choice.unsuccessfulOutcome->procedureCode == tmp[i]) + break; + if (i == sizeofArray(tmp)) { + LOG_W(NRPPA, "Unknown procedure ID (%ld) for unsuccessfull outcome message\n", pdu->choice.unsuccessfulOutcome->procedureCode); + return -1; + } + + asn_encode_to_new_buffer_result_t res = asn_encode_to_new_buffer(NULL, ATS_ALIGNED_CANONICAL_PER, &asn_DEF_NRPPA_NRPPA_PDU, pdu); + AssertFatal(res.result.encoded > 0, "failed to encode NRPPA msg\n"); + *buffer = res.buffer; + *len = res.result.encoded; + return 0; +} + +int nrppa_gNB_encode_pdu(NRPPA_NRPPA_PDU_t *pdu, uint8_t **buffer, uint32_t *len) +{ + int ret = -1; + DevAssert(pdu != NULL); + DevAssert(buffer != NULL); + DevAssert(len != NULL); + + // xer_fprint(stdout, &asn_DEF_NRPPA_NRPPA_PDU, (void *)pdu); + + switch (pdu->present) { + case NRPPA_NRPPA_PDU_PR_initiatingMessage: + ret = nrppa_gNB_encode_initiating(pdu, buffer, len); + break; + + case NRPPA_NRPPA_PDU_PR_successfulOutcome: + ret = nrppa_gNB_encode_successfull_outcome(pdu, buffer, len); + break; + + case NRPPA_NRPPA_PDU_PR_unsuccessfulOutcome: + ret = nrppa_gNB_encode_unsuccessfull_outcome(pdu, buffer, len); + break; + + default: + LOG_E(NRPPA, "Unknown message outcome (%d) or not implemented", (int)pdu->present); + return -1; + } + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NRPPA_NRPPA_PDU, pdu); + return ret; +} diff --git a/openair3/NRPPA/nrppa_gNB_encoder.h b/openair3/NRPPA/nrppa_gNB_encoder.h new file mode 100644 index 0000000000..dee34a2060 --- /dev/null +++ b/openair3/NRPPA/nrppa_gNB_encoder.h @@ -0,0 +1,27 @@ +/* + * 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 NRPPA_GNB_ENCODER_H_ +#define NRPPA_GNB_ENCODER_H_ + +int nrppa_gNB_encode_pdu(NRPPA_NRPPA_PDU_t *pdu, uint8_t **buffer, uint32_t *len) __attribute__((warn_unused_result)); + +#endif /* NRPPA_GNB_ENCODER_H_ */ diff --git a/openair3/NRPPA/nrppa_gNB_location_information_transfer.c b/openair3/NRPPA/nrppa_gNB_location_information_transfer.c index 6a617ea02b..bc1af664cd 100644 --- a/openair3/NRPPA/nrppa_gNB_location_information_transfer.c +++ b/openair3/NRPPA/nrppa_gNB_location_information_transfer.c @@ -24,6 +24,8 @@ #include "nrppa_gNB_location_information_transfer.h" #include "nrppa_gNB_ue_context.h" #include "nrppa_messages_types.h" +#include "nrppa_gNB_encoder.h" +#include "openair3/UTILS/conversions.h" void free_trp_information_request(nrppa_trp_information_req_t *msg) { @@ -32,6 +34,235 @@ void free_trp_information_request(nrppa_trp_information_req_t *msg) } } +static NRPPA_TRPPositionDirect_t encode_trp_position_direct(nrppa_trp_position_direct_t *in) +{ + NRPPA_TRPPositionDirect_t out = {0}; + + switch (in->accuracy.present) { + case NRPPA_TRP_POSITION_DIRECT_ACCURACY_PR_NOTHING: + out.accuracy.present = NRPPA_TRPPositionDirectAccuracy_PR_NOTHING; + break; + case NRPPA_TRP_POSITION_DIRECT_ACCURACY_PR_TRPPOSITION: + out.accuracy.present = NRPPA_TRPPositionDirectAccuracy_PR_tRPPosition; + asn1cCalloc(out.accuracy.choice.tRPPosition, out_pos); + nrppa_access_point_position_t *in_pos = &in->accuracy.choice.trp_position; + + out_pos->latitudeSign = in_pos->latitude_sign; + out_pos->latitude = in_pos->latitude; + out_pos->longitude = in_pos->longitude; + out_pos->directionOfAltitude = in_pos->direction_of_altitude; + out_pos->altitude = in_pos->altitude; + out_pos->uncertaintySemi_major = in_pos->uncertainty_semi_major; + out_pos->uncertaintySemi_minor = in_pos->uncertainty_semi_minor; + out_pos->orientationOfMajorAxis = in_pos->orientation_of_major_axis; + out_pos->uncertaintyAltitude = in_pos->uncertainty_altitude; + out_pos->confidence = in_pos->confidence; + break; + case NRPPA_TRP_POSITION_DIRECT_ACCURACY_PR_TRPHAPOSITION: + out.accuracy.present = NRPPA_TRPPositionDirectAccuracy_PR_tRPHAposition; + asn1cCalloc(out.accuracy.choice.tRPHAposition, out_ha_pos); + nrppa_ngran_high_accuracy_access_point_position_t *in_ha_pos = &in->accuracy.choice.trp_HAposition; + out_ha_pos->latitude = in_ha_pos->latitude; + out_ha_pos->longitude = in_ha_pos->longitude; + out_ha_pos->altitude = in_ha_pos->altitude; + out_ha_pos->uncertaintySemi_major = in_ha_pos->uncertainty_semi_major; + out_ha_pos->uncertaintySemi_minor = in_ha_pos->uncertainty_semi_minor; + out_ha_pos->orientationOfMajorAxis = in_ha_pos->orientation_of_major_axis; + out_ha_pos->horizontalConfidence = in_ha_pos->horizontal_confidence; + out_ha_pos->uncertaintyAltitude = in_ha_pos->uncertainty_altitude; + out_ha_pos->verticalConfidence = in_ha_pos->vertical_confidence; + break; + default: + AssertFatal(false, "illegal direct accuracy entry\n"); + break; + } + return out; +} + +static NRPPA_TRPPositionReferenced_t encode_trp_position_referenced(nrppa_trp_position_referenced_t *in) +{ + NRPPA_TRPPositionReferenced_t out = {0}; + NRPPA_ReferencePoint_t *out_ref_point = &out.referencePoint; + nrppa_reference_point_t *in_ref_point = &in->reference_point; + switch (in_ref_point->present) { + case NRPPA_REFERENCE_POINT_PR_NOTHING: + out_ref_point->present = NRPPA_ReferencePoint_PR_NOTHING; + break; + case NRPPA_REFERENCE_POINT_PR_COORDINATEID: + out_ref_point->present = NRPPA_ReferencePoint_PR_relativeCoordinateID; + out_ref_point->choice.relativeCoordinateID = in_ref_point->choice.coordinate_id; + break; + case NRPPA_REFERENCE_POINT_PR_REFERENCEPOINTCOORDINATE: + out_ref_point->present = NRPPA_ReferencePoint_PR_referencePointCoordinate; + asn1cCalloc(out_ref_point->choice.referencePointCoordinate, out_ref_coord); + nrppa_access_point_position_t *in_ref_coord = &in_ref_point->choice.reference_point_coordinate; + out_ref_coord->latitudeSign = in_ref_coord->latitude_sign; + out_ref_coord->latitude = in_ref_coord->latitude; + out_ref_coord->longitude = in_ref_coord->longitude; + out_ref_coord->directionOfAltitude = in_ref_coord->direction_of_altitude; + out_ref_coord->altitude = in_ref_coord->altitude; + out_ref_coord->uncertaintySemi_major = in_ref_coord->uncertainty_semi_major; + out_ref_coord->uncertaintySemi_minor = in_ref_coord->uncertainty_semi_minor; + out_ref_coord->orientationOfMajorAxis = in_ref_coord->orientation_of_major_axis; + out_ref_coord->uncertaintyAltitude = in_ref_coord->uncertainty_altitude; + out_ref_coord->confidence = in_ref_coord->confidence; + break; + case NRPPA_REFERENCE_POINT_PR_REFERENCEPOINTCOORDINATEHA: + out_ref_point->present = NRPPA_ReferencePoint_PR_referencePointCoordinateHA; + asn1cCalloc(out_ref_point->choice.referencePointCoordinateHA, out_ref_coord_ha); + nrppa_ngran_high_accuracy_access_point_position_t *in_ref_coord_ha = &in_ref_point->choice.reference_point_coordinateHA; + out_ref_coord_ha->latitude = in_ref_coord_ha->latitude; + out_ref_coord_ha->longitude = in_ref_coord_ha->longitude; + out_ref_coord_ha->altitude = in_ref_coord_ha->altitude; + out_ref_coord_ha->uncertaintySemi_major = in_ref_coord_ha->uncertainty_semi_major; + out_ref_coord_ha->uncertaintySemi_minor = in_ref_coord_ha->uncertainty_semi_minor; + out_ref_coord_ha->orientationOfMajorAxis = in_ref_coord_ha->orientation_of_major_axis; + out_ref_coord_ha->horizontalConfidence = in_ref_coord_ha->horizontal_confidence; + out_ref_coord_ha->uncertaintyAltitude = in_ref_coord_ha->uncertainty_altitude; + out_ref_coord_ha->verticalConfidence = in_ref_coord_ha->vertical_confidence; + break; + default: + AssertFatal(false, "illegal reference point entry\n"); + break; + } + + NRPPA_TRPReferencePointType_t *out_ref_point_type = &out.referencePointType; + nrppa_trp_reference_point_type_t *in_ref_point_type = &in->reference_point_type; + switch (in_ref_point_type->present) { + case NRPPA_TRP_REFERENCE_POINT_TYPE_PR_NOTHING: + out_ref_point_type->present = NRPPA_TRPReferencePointType_PR_NOTHING; + break; + case NRPPA_TRP_REFERENCE_POINT_TYPE_PR_TRPPOSITION_RELATIVE_GEODETIC: + out_ref_point_type->present = NRPPA_TRPReferencePointType_PR_tRPPositionRelativeGeodetic; + asn1cCalloc(out_ref_point_type->choice.tRPPositionRelativeGeodetic, out_geodetic); + nrppa_relative_geodetic_location_t *in_geodetic = &in_ref_point_type->choice.trp_position_relative_geodetic; + out_geodetic->milli_Arc_SecondUnits = in_geodetic->milli_arc_second_units; + out_geodetic->heightUnits = in_geodetic->height_units; + out_geodetic->deltaLatitude = in_geodetic->delta_latitude; + out_geodetic->deltaLongitude = in_geodetic->delta_longitude; + out_geodetic->deltaHeight = in_geodetic->delta_height; + NRPPA_LocationUncertainty_t *out_loc_uncertainty_g = &out_geodetic->locationUncertainty; + nrppa_location_uncertainty_t *in_loc_uncertainty_g = &in_geodetic->location_uncertainty; + out_loc_uncertainty_g->horizontalUncertainty = in_loc_uncertainty_g->horizontal_uncertainty; + out_loc_uncertainty_g->horizontalConfidence = in_loc_uncertainty_g->horizontal_confidence; + out_loc_uncertainty_g->verticalUncertainty = in_loc_uncertainty_g->vertical_uncertainty; + out_loc_uncertainty_g->verticalConfidence = in_loc_uncertainty_g->vertical_confidence; + break; + case NRPPA_TRP_REFERENCE_POINT_TYPE_PR_TRPPOSITION_RELATIVE_CARTESIAN: + out_ref_point_type->present = NRPPA_TRPReferencePointType_PR_tRPPositionRelativeCartesian; + asn1cCalloc(out_ref_point_type->choice.tRPPositionRelativeCartesian, out_cartesian); + nrppa_relative_cartesian_location_t *in_cartesian = &in_ref_point_type->choice.trp_position_relative_cartesian; + + out_cartesian->xYZunit = in_cartesian->xyz_unit; + out_cartesian->xvalue = in_cartesian->xvalue; + out_cartesian->yvalue = in_cartesian->yvalue; + out_cartesian->zvalue = in_cartesian->zvalue; + NRPPA_LocationUncertainty_t *out_loc_uncertainty_c = &out_cartesian->locationUncertainty; + nrppa_location_uncertainty_t *in_loc_uncertainty_c = &in_cartesian->location_uncertainty; + out_loc_uncertainty_c->horizontalUncertainty = in_loc_uncertainty_c->horizontal_uncertainty; + out_loc_uncertainty_c->horizontalConfidence = in_loc_uncertainty_c->horizontal_confidence; + out_loc_uncertainty_c->verticalUncertainty = in_loc_uncertainty_c->vertical_uncertainty; + out_loc_uncertainty_c->verticalConfidence = in_loc_uncertainty_c->vertical_confidence; + break; + default: + AssertFatal(false, "illegal trp reference point type entry\n"); + break; + } + return out; +} + +static NRPPA_GeographicalCoordinates_t encode_geographical_coordinates_nrppa(nrppa_geographical_coordinates_t *in) +{ + NRPPA_GeographicalCoordinates_t out = {0}; + NRPPA_TRPPositionDefinitionType_t *out_type = &out.tRPPositionDefinitionType; + nrppa_trp_position_definition_type_t *in_type = &in->trp_position_definition_type; + switch (in_type->present) { + case NRPPA_TRP_POSITION_DEFINITION_TYPE_PR_NOTHING: + out_type->present = NRPPA_TRPPositionDefinitionType_PR_NOTHING; + break; + case NRPPA_TRP_POSITION_DEFINITION_TYPE_PR_DIRECT: + out_type->present = NRPPA_TRPPositionDefinitionType_PR_direct; + asn1cCalloc(out_type->choice.direct, direct); + *direct = encode_trp_position_direct(&in_type->choice.direct); + break; + case NRPPA_TRP_POSITION_DEFINITION_TYPE_PR_REFERENCED: + out_type->present = NRPPA_TRPPositionDefinitionType_PR_referenced; + asn1cCalloc(out_type->choice.referenced, referenced); + *referenced = encode_trp_position_referenced(&in_type->choice.referenced); + break; + default: + AssertFatal(false, "illegal Geographical Coordinates entry\n"); + break; + } + return out; +} + +NRPPA_TRPInformationItem_t encode_trp_info_type_response_item_nrppa(nrppa_trp_information_type_response_item_t *in) +{ + NRPPA_TRPInformationItem_t out = {0}; + switch (in->present) { + case NRPPA_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_NOTHING: + out.present = NRPPA_TRPInformationItem_PR_NOTHING; + break; + case NRPPA_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_PCI_NR: + out.present = NRPPA_TRPInformationItem_PR_pCI_NR; + out.choice.pCI_NR = in->choice.pci_nr; + break; + case NRPPA_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_NG_RAN_CGI: + out.present = NRPPA_TRPInformationItem_PR_nG_RAN_CGI; + asn1cCalloc(out.choice.nG_RAN_CGI, nG_RAN_CGI); + MCC_MNC_TO_PLMNID(in->choice.ng_ran_cgi.plmn.mcc, + in->choice.ng_ran_cgi.plmn.mnc, + in->choice.ng_ran_cgi.plmn.mnc_digit_length, + &(nG_RAN_CGI->pLMN_Identity)); + nG_RAN_CGI->nG_RANcell.present = NRPPA_NG_RANCell_PR_nR_CellID; + NR_CELL_ID_TO_BIT_STRING(in->choice.ng_ran_cgi.nr_cellid, &(nG_RAN_CGI->nG_RANcell.choice.nR_CellID)); + break; + case NRPPA_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_NRARFCN: + out.present = NRPPA_TRPInformationItem_PR_aRFCN; + out.choice.aRFCN = in->choice.nr_arfcn; + break; + case NRPPA_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_PRSCONFIGURATION: + out.present = NRPPA_TRPInformationItem_PR_pRSConfiguration; + AssertFatal(false, "TRP information type response item PRS configuration unsupported\n"); + break; + case NRPPA_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_SSBINFORMATION: + out.present = NRPPA_TRPInformationItem_PR_sSBinformation; + AssertFatal(false, "TRP information type response item SSB Information unsupported\n"); + break; + case NRPPA_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_SFNINITIALISATIONTIME: + out.present = NRPPA_TRPInformationItem_PR_sFNInitialisationTime; + AssertFatal(false, "TRP information type response item SFN Initialization Time unsupported\n"); + break; + case NRPPA_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_SPATIALDIRECTIONINFORMATION: + out.present = NRPPA_TRPInformationItem_PR_spatialDirectionInformation; + AssertFatal(false, "TRP information type response item Spatial Direction Information unsupported\n"); + break; + case NRPPA_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_GEOGRAPHICALCOORDINATES: + out.present = NRPPA_TRPInformationItem_PR_geographicalCoordinates; + asn1cCalloc(out.choice.geographicalCoordinates, nrppa_geo_coord); + nrppa_geographical_coordinates_t *geo_coord = &in->choice.geographical_coordinates; + *nrppa_geo_coord = encode_geographical_coordinates_nrppa(geo_coord); + break; + default: + AssertFatal(false, "received illegal trp information type response item %d\n", in->present); + break; + } + return out; +} + +void free_trp_information_response(nrppa_trp_information_resp_t *msg) +{ + nrppa_trp_information_list_t *trp_information_list = &msg->trp_information_list; + uint32_t trp_info_item_length = trp_information_list->trp_information_item_length; + for (int i = 0; i < trp_info_item_length; i++) { + nrppa_trp_information_t *trp_information_item = &trp_information_list->trp_information_item[i]; + nrppa_trp_information_type_response_list_t *trp_info_type_resp_list = &trp_information_item->trp_information_type_response_list; + free(trp_info_type_resp_list->trp_information_type_response_item); + } + free(msg->trp_information_list.trp_information_item); +} + int nrppa_gNB_handle_trp_information_request(nrppa_gnb_ue_info_t *nrppa_msg_info, const NRPPA_NRPPA_PDU_t *pdu) { LOG_I(NRPPA, "Processing Received TRP Information Request \n"); @@ -93,3 +324,94 @@ int nrppa_gNB_handle_trp_information_request(nrppa_gnb_ue_info_t *nrppa_msg_info ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NRPPA_NRPPA_PDU, &pdu); return 0; } + +int nrppa_gNB_trp_information_response(instance_t instance, MessageDef *msg_p) +{ + DevAssert(msg_p); + nrppa_trp_information_resp_t *resp = &NRPPA_TRP_INFORMATION_RESP(msg_p); + nrppa_gNB_ue_context_t *ue_info = nrppa_detach_ue_context(resp->transaction_id); + + if (ue_info->gNB_ue_ngap_id != 0 && ue_info->amf_ue_ngap_id != 0) { + LOG_E(NRPPA, "Illegal gNB_ue_ngap_id %d and amf_ue_ngap_id %ld\n", ue_info->gNB_ue_ngap_id, ue_info->amf_ue_ngap_id); + free_trp_information_response(resp); + nrppa_free_ue_context(ue_info); + return -1; + } + + LOG_I(NRPPA, "Received TRP Information Response info from RRC with transaction_id = %u\n", ue_info->transaction_id); + + // Prepare NRPPA TRP Information transfer Response + NRPPA_NRPPA_PDU_t pdu = {0}; + + // IE: 9.2.3 Message Type : mandatory + pdu.present = NRPPA_NRPPA_PDU_PR_successfulOutcome; + asn1cCalloc(pdu.choice.successfulOutcome, head); + head->procedureCode = NRPPA_ProcedureCode_id_tRPInformationExchange; + head->criticality = NRPPA_Criticality_reject; + head->value.present = NRPPA_SuccessfulOutcome__value_PR_TRPInformationResponse; + + // IE 9.2.4 nrppatransactionID : mandatory + head->nrppatransactionID = resp->transaction_id; + NRPPA_TRPInformationResponse_t *out = &head->value.choice.TRPInformationResponse; + + // IE TRP Information List : mandatory + { + asn1cSequenceAdd(out->protocolIEs.list, NRPPA_TRPInformationResponse_IEs_t, ie); + ie->id = NRPPA_ProtocolIE_ID_id_TRPInformationList; + ie->criticality = NRPPA_Criticality_ignore; + ie->value.present = NRPPA_TRPInformationResponse_IEs__value_PR_TRPInformationList; + + uint32_t trp_info_item_len = resp->trp_information_list.trp_information_item_length; + for (int i = 0; i < trp_info_item_len; i++) { + // TRPInformationItem (M) + asn1cSequenceAdd(ie->value.choice.TRPInformationList.list, TRPInformationList__Member, trpinfolist_member); + nrppa_trp_information_t *nrppa_tRPInformation = &resp->trp_information_list.trp_information_item[i]; + + trpinfolist_member->tRP_ID = nrppa_tRPInformation->trp_id; + + NRPPA_TRPInformation_t *trp_info = &trpinfolist_member->tRPInformation; + + nrppa_trp_information_type_response_list_t *nrppa_tRPInformationTypeResponseList = + &nrppa_tRPInformation->trp_information_type_response_list; + uint8_t trp_info_type_resp_item_len = nrppa_tRPInformationTypeResponseList->trp_information_type_response_item_length; + + for (int j = 0; j < trp_info_type_resp_item_len; j++) { + asn1cSequenceAdd(trp_info->list, NRPPA_TRPInformationItem_t, trp_info_item); + nrppa_trp_information_type_response_item_t *resp_item = + &nrppa_tRPInformationTypeResponseList->trp_information_type_response_item[j]; + *trp_info_item = encode_trp_info_type_response_item_nrppa(resp_item); + } + } + } + + free_trp_information_response(resp); + + if (LOG_DEBUGFLAG(DEBUG_ASN1)) { + xer_fprint(stdout, &asn_DEF_NRPPA_NRPPA_PDU, &pdu); + } + + // Encode NRPPA message + uint8_t *buffer = NULL; + uint32_t length = 0; + if (nrppa_gNB_encode_pdu(&pdu, &buffer, &length) < 0) { + LOG_E(NRPPA, "Failed to encode Uplink NRPPa TRP Information Response\n"); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NRPPA_NRPPA_PDU, &pdu); + return -1; + } + + MessageDef *msg = itti_alloc_new_message(TASK_NRPPA, 0, NGAP_UPLINKNONUEASSOCIATEDNRPPA); + ngap_uplink_non_ue_associated_nrppa_t *ULNRPPA = &NGAP_UPLINKNONUEASSOCIATEDNRPPA(msg); + + // Routing ID + ULNRPPA->routing_id = create_byte_array(ue_info->routing_id.len, ue_info->routing_id.buf); + + // NRPPa PDU + ULNRPPA->nrppa_pdu = create_byte_array(length, buffer); + + // Forward the NRPPA PDU to NGAP + itti_send_msg_to_task(TASK_NGAP, instance, msg); + nrppa_free_ue_context(ue_info); + free(buffer); + + return length; +} diff --git a/openair3/NRPPA/nrppa_gNB_location_information_transfer.h b/openair3/NRPPA/nrppa_gNB_location_information_transfer.h index 5295505b22..2f9ec72cd0 100644 --- a/openair3/NRPPA/nrppa_gNB_location_information_transfer.h +++ b/openair3/NRPPA/nrppa_gNB_location_information_transfer.h @@ -24,5 +24,9 @@ int nrppa_gNB_handle_trp_information_request(nrppa_gnb_ue_info_t *nrppa_msg_info, const NRPPA_NRPPA_PDU_t *pdu); void free_trp_information_request(nrppa_trp_information_req_t *msg); +int nrppa_gNB_trp_information_response(instance_t instance, MessageDef *msg_p); +void free_trp_information_request(nrppa_trp_information_req_t *msg); +NRPPA_TRPInformationItem_t encode_trp_info_type_response_item_nrppa(nrppa_trp_information_type_response_item_t *in); +void free_trp_information_response(nrppa_trp_information_resp_t *msg); #endif /* NRPPA_GNB_POSITIONING_PROCEDURES_H_ */ diff --git a/openair3/NRPPA/nrppa_gNB_ue_context.c b/openair3/NRPPA/nrppa_gNB_ue_context.c index 1a1a0e7c0e..b5da194205 100644 --- a/openair3/NRPPA/nrppa_gNB_ue_context.c +++ b/openair3/NRPPA/nrppa_gNB_ue_context.c @@ -83,3 +83,14 @@ struct nrppa_gNB_ue_context_s *nrppa_detach_ue_context(uint16_t transaction_id) RB_REMOVE(nrppa_ue_map, &nrppa_ue_head, tmp); return tmp; } + +void nrppa_free_ue_context(nrppa_gNB_ue_context_t *ue_info) +{ + if (!ue_info) + return; + + if (ue_info->routing_id.buf) { + free(ue_info->routing_id.buf); + } + free(ue_info); +} diff --git a/openair3/NRPPA/nrppa_gNB_ue_context.h b/openair3/NRPPA/nrppa_gNB_ue_context.h index 1aaeabe359..fc976c611d 100644 --- a/openair3/NRPPA/nrppa_gNB_ue_context.h +++ b/openair3/NRPPA/nrppa_gNB_ue_context.h @@ -39,5 +39,6 @@ typedef struct nrppa_gNB_ue_context_s { void nrppa_store_ue_context(const nrppa_gnb_ue_info_t *info, const uint16_t transaction_id); nrppa_gNB_ue_context_t *nrppa_get_ue_context(uint16_t transaction_id); nrppa_gNB_ue_context_t *nrppa_detach_ue_context(uint16_t transaction_id); +void nrppa_free_ue_context(nrppa_gNB_ue_context_t *ue_info); #endif /* NRPPA_GNB_UE_CONTEXT_H_ */ diff --git a/openair3/NRPPA/nrppa_includes.h b/openair3/NRPPA/nrppa_includes.h index 8239033926..63bb3fe248 100644 --- a/openair3/NRPPA/nrppa_includes.h +++ b/openair3/NRPPA/nrppa_includes.h @@ -35,5 +35,12 @@ #include "NRPPA_ProtocolIE-Single-Container.h" #include "NRPPA_asn_constant.h" #include "NRPPA_TRPInformationRequest.h" +#include "NRPPA_TRPInformationItem.h" +#include "NRPPA_TRPPositionDirect.h" +#include "NRPPA_NG-RANAccessPointPosition.h" +#include "NRPPA_NGRANHighAccuracyAccessPointPosition.h" +#include "NRPPA_TRPPositionReferenced.h" +#include "NRPPA_RelativeGeodeticLocation.h" +#include "NRPPA_RelativeCartesianLocation.h" #endif /* NRPPA_INCLUDE_H_ */ diff --git a/tests/nr-cu-nrppa/nr-cu-nrppa.c b/tests/nr-cu-nrppa/nr-cu-nrppa.c index 893ee63e8c..7d3d023f18 100644 --- a/tests/nr-cu-nrppa/nr-cu-nrppa.c +++ b/tests/nr-cu-nrppa/nr-cu-nrppa.c @@ -64,6 +64,111 @@ ngran_node_t get_node_type() configmodule_interface_t *uniqCfg = NULL; +static nrppa_trp_information_resp_t fill_trp_resp(uint8_t transaction_id) +{ + positioning_config_t positioning_config = RCconfig_nr_positioning(); + dump_positioning_config(&positioning_config); + nrppa_trp_information_resp_t resp = {0}; + resp.transaction_id = transaction_id; + + nrppa_trp_information_list_t *list = &resp.trp_information_list; + uint32_t trp_info_item_len = positioning_config.num_trp; + list->trp_information_item_length = trp_info_item_len; + list->trp_information_item = calloc_or_fail(trp_info_item_len, sizeof(*list->trp_information_item)); + + uint8_t resp_item_len = 3; + for (int i = 0; i < trp_info_item_len; i++) { + nrppa_trp_information_t *tRPInformation = &list->trp_information_item[i]; + tRPInformation->trp_id = positioning_config.trps[i].id; + nrppa_trp_information_type_response_list_t *resp_list = &tRPInformation->trp_information_type_response_list; + resp_list->trp_information_type_response_item_length = resp_item_len; + nrppa_trp_information_type_response_item_t *resp_item = calloc_or_fail(resp_item_len, sizeof(*resp_item)); + resp_list->trp_information_type_response_item = resp_item; + + // nrPCI + resp_item[0].present = NRPPA_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_PCI_NR; + resp_item[0].choice.pci_nr = 123 + i; + + // nG_RAN_CGI + resp_item[1].present = NRPPA_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_NG_RAN_CGI; + resp_item[1].choice.ng_ran_cgi.plmn.mcc = 001; + resp_item[1].choice.ng_ran_cgi.plmn.mnc = 01; + resp_item[1].choice.ng_ran_cgi.plmn.mnc_digit_length = 2; + resp_item[1].choice.ng_ran_cgi.nr_cellid = gnb_id << 8; // HACK: Made to work with lmf + + // geographicalCoordinates + resp_item[2].present = NRPPA_TRP_INFORMATION_TYPE_RESPONSE_ITEM_PR_GEOGRAPHICALCOORDINATES; + nrppa_geographical_coordinates_t *geographicalCoordinates = &resp_item[2].choice.geographical_coordinates; + nrppa_trp_position_definition_type_t *tRPPositionDefinitionType = &geographicalCoordinates->trp_position_definition_type; + // referenced + tRPPositionDefinitionType->present = NRPPA_TRP_POSITION_DEFINITION_TYPE_PR_REFERENCED; + nrppa_trp_position_referenced_t *referenced = &tRPPositionDefinitionType->choice.referenced; + // coordinate ID + referenced->reference_point.present = NRPPA_REFERENCE_POINT_PR_COORDINATEID; + referenced->reference_point.choice.coordinate_id = 2; + nrppa_trp_reference_point_type_t *referencePointType = &referenced->reference_point_type; + // relative cartesian + referencePointType->present = NRPPA_TRP_REFERENCE_POINT_TYPE_PR_TRPPOSITION_RELATIVE_CARTESIAN; + nrppa_relative_cartesian_location_t *trp_pos_cart = &referencePointType->choice.trp_position_relative_cartesian; + // 0 = millimeter + trp_pos_cart->xyz_unit = positioning_config.trps[i].unit; + + // random reference cartesian coordinates in millimeter + trp_pos_cart->xvalue = positioning_config.trps[i].x_axis; + trp_pos_cart->yvalue = positioning_config.trps[i].y_axis; + trp_pos_cart->zvalue = positioning_config.trps[i].z_axis; + // testing random values for uncertainity and confidence + trp_pos_cart->location_uncertainty.horizontal_uncertainty = i + 1; + trp_pos_cart->location_uncertainty.horizontal_confidence = i + 2; + trp_pos_cart->location_uncertainty.vertical_uncertainty = i + 3; + trp_pos_cart->location_uncertainty.vertical_confidence = i + 4; + } + return resp; +} + +void *rrc_gnb_task(void *args_p) +{ + MessageDef *msg_p; + MessageDef *msg_p_resp; + instance_t instance; + int result; + + itti_mark_task_ready(TASK_RRC_GNB); + LOG_I(NR_RRC, "Entering main loop of NR_RRC message task\n"); + + while (1) { + // Wait for a message + itti_receive_msg(TASK_RRC_GNB, &msg_p); + const char *msg_name_p = ITTI_MSG_NAME(msg_p); + instance = ITTI_MSG_DESTINATION_INSTANCE(msg_p); + LOG_D(NR_RRC, + "RRC GNB Task Received %s for instance %ld from task %s\n", + ITTI_MSG_NAME(msg_p), + ITTI_MSG_DESTINATION_INSTANCE(msg_p), + ITTI_MSG_ORIGIN_NAME(msg_p)); + switch (ITTI_MSG_ID(msg_p)) { + case TERMINATE_MESSAGE: + LOG_W(NR_RRC, " *** Exiting NR_RRC thread\n"); + itti_exit_task(); + break; + case NRPPA_TRP_INFORMATION_REQ: + nrppa_trp_information_req_t *trp_req = &NRPPA_TRP_INFORMATION_REQ(msg_p); + LOG_I(NR_RRC, "Received NRPPA_TRP_INFORMATION_REQ transaction_id %d\n", trp_req->transaction_id); + msg_p_resp = itti_alloc_new_message(TASK_RRC_GNB, 0, NRPPA_TRP_INFORMATION_RESP); + NRPPA_TRP_INFORMATION_RESP(msg_p_resp) = fill_trp_resp(trp_req->transaction_id); + LOG_I(NR_RRC, "Sending NRPPA_TRP_INFORMATION_RESP to TASK_NRPPA\n"); + itti_send_msg_to_task(TASK_NRPPA, 0, msg_p_resp); + break; + default: + LOG_E(NR_RRC, "[gNB %ld] Received unexpected message %s\n", instance, msg_name_p); + break; + } + result = itti_free(ITTI_MSG_ORIGIN_ID(msg_p), msg_p); + AssertFatal(result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); + msg_p = NULL; + } +} + int main(int argc, char **argv) { // load the config file @@ -87,6 +192,9 @@ int main(int argc, char **argv) rc = itti_create_task(TASK_NRPPA, nrppa_gNB_task, NULL); AssertFatal(rc >= 0, "Create task for NRPPA failed\n"); + rc = itti_create_task(TASK_RRC_GNB, rrc_gnb_task, NULL); + AssertFatal(rc >= 0, "Create task for RRC failed\n"); + MessageDef *msg_p; msg_p = itti_alloc_new_message(TASK_GNB_APP, 0, NGAP_REGISTER_GNB_REQ); RCconfig_NR_NG(msg_p, 0); From 1be578e89348c456cff9800d78cee6afe5fd8a85 Mon Sep 17 00:00:00 2001 From: Rakesh Mundlamuri Date: Thu, 22 Jan 2026 19:04:21 +0530 Subject: [PATCH 14/21] Add Positioning Information Request NRPPA message decoding procedures --- openair2/COMMON/nrppa_messages_def.h | 4 +++ openair2/COMMON/nrppa_messages_types.h | 6 +++++ openair3/NRPPA/nrppa_gNB_decoder.c | 5 ++++ openair3/NRPPA/nrppa_gNB_handlers.c | 4 ++- .../nrppa_gNB_location_information_transfer.c | 27 +++++++++++++++++++ .../nrppa_gNB_location_information_transfer.h | 1 + 6 files changed, 46 insertions(+), 1 deletion(-) diff --git a/openair2/COMMON/nrppa_messages_def.h b/openair2/COMMON/nrppa_messages_def.h index ecca67ba33..e3ddeb244f 100644 --- a/openair2/COMMON/nrppa_messages_def.h +++ b/openair2/COMMON/nrppa_messages_def.h @@ -24,3 +24,7 @@ // LMF -> CU MESSAGE_DEF(NRPPA_TRP_INFORMATION_REQ, MESSAGE_PRIORITY_MED, nrppa_trp_information_req_t, nrppa_trp_information_req) MESSAGE_DEF(NRPPA_TRP_INFORMATION_RESP, MESSAGE_PRIORITY_MED, nrppa_trp_information_resp_t, nrppa_trp_information_resp) +MESSAGE_DEF(NRPPA_POSITIONING_INFORMATION_REQ, + MESSAGE_PRIORITY_MED, + nrppa_positioning_information_req_t, + nrppa_positioning_information_req) diff --git a/openair2/COMMON/nrppa_messages_types.h b/openair2/COMMON/nrppa_messages_types.h index f461909a35..fef930ac9a 100644 --- a/openair2/COMMON/nrppa_messages_types.h +++ b/openair2/COMMON/nrppa_messages_types.h @@ -26,6 +26,7 @@ #define NRPPA_TRP_INFORMATION_REQ(mSGpTR) (mSGpTR)->ittiMsg.nrppa_trp_information_req #define NRPPA_TRP_INFORMATION_RESP(mSGpTR) (mSGpTR)->ittiMsg.nrppa_trp_information_resp +#define NRPPA_POSITIONING_INFORMATION_REQ(mSGpTR) (mSGpTR)->ittiMsg.nrppa_positioning_information_req /* Structure of Positioning related NRPPA messages */ /* IE structures for Positioning related messages as per TS 38.455 V16.7.1*/ @@ -245,4 +246,9 @@ typedef struct nrppa_trp_information_resp_s { nrppa_trp_information_list_t trp_information_list; } nrppa_trp_information_resp_t; +typedef struct nrppa_positioning_information_req_s { + // IE 9.2.4 (mandatory) + uint16_t transaction_id; +} nrppa_positioning_information_req_t; + #endif // NRPPA_MESSAGES_TYPES_H_ diff --git a/openair3/NRPPA/nrppa_gNB_decoder.c b/openair3/NRPPA/nrppa_gNB_decoder.c index d197d0d141..94524fd060 100644 --- a/openair3/NRPPA/nrppa_gNB_decoder.c +++ b/openair3/NRPPA/nrppa_gNB_decoder.c @@ -35,6 +35,11 @@ static int nrppa_gNB_decode_initiating_message(NRPPA_NRPPA_PDU_t *pdu) LOG_I(NRPPA, "TRP Information Request initiating message\n"); free(res.buffer); break; + case NRPPA_ProcedureCode_id_positioningInformationExchange: // PositioningInformationRequest + res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NRPPA_NRPPA_PDU, pdu); + LOG_I(NRPPA, "Positioning Information Request initiating message\n"); + free(res.buffer); + break; default: AssertFatal(false, "Unknown procedure ID (%d) for initiating message\n", (int)pdu->choice.initiatingMessage->procedureCode); diff --git a/openair3/NRPPA/nrppa_gNB_handlers.c b/openair3/NRPPA/nrppa_gNB_handlers.c index ce36e34d81..99299ecb64 100644 --- a/openair3/NRPPA/nrppa_gNB_handlers.c +++ b/openair3/NRPPA/nrppa_gNB_handlers.c @@ -47,7 +47,9 @@ nrppa_message_decoded_callback nrppa_messages_callback[][3] = { {0, 0, 0}, // NRPPA_ProcedureCode_id_oTDOAInformationExchange ((NRPPA_ProcedureCode_t)6) {0, 0, 0}, // NRPPA_ProcedureCode_id_assistanceInformationControl ((NRPPA_ProcedureCode_t)7) {0, 0, 0}, // NRPPA_ProcedureCode_id_assistanceInformationFeedback ((NRPPA_ProcedureCode_t)8) - {0, 0, 0}, // NRPPA_ProcedureCode_id_positioningInformationExchange ((NRPPA_ProcedureCode_t)9) + {nrppa_gNB_handle_positioning_information_request, + 0, + 0}, // NRPPA_ProcedureCode_id_positioningInformationExchange ((NRPPA_ProcedureCode_t)9) {0, 0, 0}, // NRPPA_ProcedureCode_id_positioningInformationUpdate ((NRPPA_ProcedureCode_t)10) {0, 0, 0}, // NRPPA_ProcedureCode_id_Measurement ((NRPPA_ProcedureCode_t)11) {0, 0, 0}, // NRPPA_ProcedureCode_id_MeasurementReport ((NRPPA_ProcedureCode_t)12) diff --git a/openair3/NRPPA/nrppa_gNB_location_information_transfer.c b/openair3/NRPPA/nrppa_gNB_location_information_transfer.c index bc1af664cd..6821e251ed 100644 --- a/openair3/NRPPA/nrppa_gNB_location_information_transfer.c +++ b/openair3/NRPPA/nrppa_gNB_location_information_transfer.c @@ -415,3 +415,30 @@ int nrppa_gNB_trp_information_response(instance_t instance, MessageDef *msg_p) return length; } + +int nrppa_gNB_handle_positioning_information_request(nrppa_gnb_ue_info_t *nrppa_msg_info, const NRPPA_NRPPA_PDU_t *pdu) +{ + DevAssert(pdu != NULL); + DevAssert(nrppa_msg_info != NULL); + + if (LOG_DEBUGFLAG(DEBUG_ASN1)) { + xer_fprint(stdout, &asn_DEF_NRPPA_NRPPA_PDU, pdu); + } + + LOG_I(NRPPA, "Processing Received Positioning Information Request\n"); + + // Preparing positioning information request for RRC + MessageDef *msg = itti_alloc_new_message(TASK_RRC_GNB, 0, NRPPA_POSITIONING_INFORMATION_REQ); + nrppa_positioning_information_req_t *req = &NRPPA_POSITIONING_INFORMATION_REQ(msg); + + // IE 9.2.4 nrppatransactionID : mandatory + req->transaction_id = pdu->choice.initiatingMessage->nrppatransactionID; + + nrppa_store_ue_context(nrppa_msg_info, req->transaction_id); + + LOG_I(NRPPA, "Forwarding to RRC Positioning Information Request transaction id=%d\n", req->transaction_id); + + itti_send_msg_to_task(TASK_RRC_GNB, 0, msg); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NRPPA_NRPPA_PDU, &pdu); + return 0; +} diff --git a/openair3/NRPPA/nrppa_gNB_location_information_transfer.h b/openair3/NRPPA/nrppa_gNB_location_information_transfer.h index 2f9ec72cd0..5fbd697c07 100644 --- a/openair3/NRPPA/nrppa_gNB_location_information_transfer.h +++ b/openair3/NRPPA/nrppa_gNB_location_information_transfer.h @@ -28,5 +28,6 @@ int nrppa_gNB_trp_information_response(instance_t instance, MessageDef *msg_p); void free_trp_information_request(nrppa_trp_information_req_t *msg); NRPPA_TRPInformationItem_t encode_trp_info_type_response_item_nrppa(nrppa_trp_information_type_response_item_t *in); void free_trp_information_response(nrppa_trp_information_resp_t *msg); +int nrppa_gNB_handle_positioning_information_request(nrppa_gnb_ue_info_t *nrppa_msg_info, const NRPPA_NRPPA_PDU_t *pdu); #endif /* NRPPA_GNB_POSITIONING_PROCEDURES_H_ */ From 3dcdedb3f8b3512356ee737049fa0a83d395d235 Mon Sep 17 00:00:00 2001 From: Rakesh Mundlamuri Date: Thu, 22 Jan 2026 20:28:12 +0530 Subject: [PATCH 15/21] Send dummy UE registration request to the AMF to register the UE. This is required for positioning as we initiate positioning procedure based on the imsi. --- tests/nr-cu-nrppa/CMakeLists.txt | 3 +- tests/nr-cu-nrppa/nr-cu-nrppa.c | 134 +++++++++++++++++++++++++++++++ 2 files changed, 136 insertions(+), 1 deletion(-) diff --git a/tests/nr-cu-nrppa/CMakeLists.txt b/tests/nr-cu-nrppa/CMakeLists.txt index f24ff4b880..b61b0dd920 100644 --- a/tests/nr-cu-nrppa/CMakeLists.txt +++ b/tests/nr-cu-nrppa/CMakeLists.txt @@ -1,7 +1,8 @@ add_executable(nr-cu-nrppa-test nr-cu-nrppa.c ${OPENAIR2_DIR}/GNB_APP/gnb_config_common.c ${OPENAIR2_DIR}/GNB_APP/gnb_config_ng.c) - + +target_link_libraries(nr-cu-nrppa-test PRIVATE nr_nas nr_common lib_uicc usim_lib) target_link_libraries(nr-cu-nrppa-test PRIVATE CONFIG_LIB ITTI SCTP_CLIENT f1ap ngap SECURITY diff --git a/tests/nr-cu-nrppa/nr-cu-nrppa.c b/tests/nr-cu-nrppa/nr-cu-nrppa.c index 7d3d023f18..aad8855797 100644 --- a/tests/nr-cu-nrppa/nr-cu-nrppa.c +++ b/tests/nr-cu-nrppa/nr-cu-nrppa.c @@ -29,6 +29,8 @@ #include "openair3/SCTP/sctp_default_values.h" #include "openair3/NRPPA/nrppa_gNB_config.h" #include "openair3/NRPPA/nrppa_gNB.h" +#include "openair3/NAS/NR_UE/nr_nas_msg.h" +#include "executables/nr-uesoftmodem.h" RAN_CONTEXT_t RC; THREAD_STRUCT thread_struct; @@ -36,6 +38,7 @@ uint64_t downlink_frequency[MAX_NUM_CCs][4]; int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; int oai_exit = 0; int gnb_id; +int NB_UE_INST = 1; void exit_function(const char *file, const char *function, const int line, const char *s, const int assert) { @@ -62,6 +65,25 @@ ngran_node_t get_node_type() return ngran_gNB_CUUP; } +nrUE_params_t *get_nrUE_params(void) +{ + static nrUE_params_t params = {0}; + params.extra_pdu_id = -1; + return ¶ms; +} + +void create_ue_ip_if(void) +{ +} + +void create_ue_eth_if(void) +{ +} + +void set_qfi(void) +{ +} + configmodule_interface_t *uniqCfg = NULL; static nrppa_trp_information_resp_t fill_trp_resp(uint8_t transaction_id) @@ -126,6 +148,106 @@ static nrppa_trp_information_resp_t fill_trp_resp(uint8_t transaction_id) return resp; } +// Initializing UE NAS Context with simulated SIM data +nr_ue_nas_t *simulated_ue_nas = NULL; +void init_ue_nas_context(void) +{ + simulated_ue_nas = calloc_or_fail(1, sizeof(nr_ue_nas_t)); + simulated_ue_nas->UE_id = 1; + simulated_ue_nas->security_container = calloc_or_fail(1, sizeof(stream_security_container_t)); + // Allocation and simulation of UICC data + simulated_ue_nas->uicc = calloc_or_fail(1, sizeof(uicc_t)); + // IMSI : 001010000000001 + simulated_ue_nas->uicc->imsiStr = calloc_or_fail(1, 16 * sizeof(char)); + strcpy(simulated_ue_nas->uicc->imsiStr, "001010000000001"); + simulated_ue_nas->uicc->nmc_size = 2; + // DNN : oai + simulated_ue_nas->uicc->dnnStr = calloc_or_fail(1, 32 * sizeof(char)); + strcpy(simulated_ue_nas->uicc->dnnStr, "oai"); + // IMEISV : 6754567890123413 + simulated_ue_nas->uicc->imeisvStr = calloc_or_fail(1, 17 * sizeof(char)); + strcpy(simulated_ue_nas->uicc->imeisvStr, "6754567890123413"); + // NSSAI: sst = 1, sd = 0xffffff + simulated_ue_nas->uicc->nssai_sst = 1; + simulated_ue_nas->uicc->nssai_sd = 0xffffff; + // Ki: fec86ba6eb707ed08905757b1bb44b8f + static const uint8_t TEST_K[16] = + {0xfe, 0xc8, 0x6b, 0xa6, 0xeb, 0x70, 0x7e, 0xd0, 0x89, 0x05, 0x75, 0x7b, 0x1b, 0xb4, 0x4b, 0x8f}; + memcpy(simulated_ue_nas->uicc->key, TEST_K, 16); + // OPc: c42449363bbad02b66d16bc975d77cc1 + static const uint8_t TEST_OPC[16] = + {0xc4, 0x24, 0x49, 0x36, 0x3b, 0xba, 0xd0, 0x2b, 0x66, 0xd1, 0x6b, 0xc9, 0x75, 0xd7, 0x7c, 0xc1}; + memcpy(simulated_ue_nas->uicc->opc, TEST_OPC, 16); + simulated_ue_nas->security.nas_count_ul = 0; + simulated_ue_nas->security.nas_count_dl = 0; + simulated_ue_nas->fiveGMM_state = FGS_DEREGISTERED; +} + +// Emulate registration request to register UE in the AMF (required for positioning) +void send_initial_ue_message(instance_t instance) +{ + MessageDef *msg_p = itti_alloc_new_message(TASK_RRC_GNB, 0, NGAP_NAS_FIRST_REQ); + + NGAP_NAS_FIRST_REQ(msg_p).gNB_ue_ngap_id = 1; // Simulated UE ID + + NGAP_NAS_FIRST_REQ(msg_p).plmn.mcc = 1; + NGAP_NAS_FIRST_REQ(msg_p).plmn.mnc = 1; + NGAP_NAS_FIRST_REQ(msg_p).plmn.mnc_digit_length = 2; + + NGAP_NAS_FIRST_REQ(msg_p).nr_cell_id = gnb_id; + + NGAP_NAS_FIRST_REQ(msg_p).establishment_cause = NGAP_RRC_CAUSE_MO_SIGNALLING; + + as_nas_info_t initialNasMsg = {0}; + generateRegistrationRequest(&initialNasMsg, simulated_ue_nas, false); + + NGAP_NAS_FIRST_REQ(msg_p).nas_pdu.buf = initialNasMsg.nas_data; + NGAP_NAS_FIRST_REQ(msg_p).nas_pdu.len = initialNasMsg.length; + + NGAP_NAS_FIRST_REQ(msg_p).ue_identity.presenceMask = 0; + + itti_send_msg_to_task(TASK_NGAP, instance, msg_p); +} + +void *gNB_app_task(void *args_p) +{ + MessageDef *msg_p = NULL; + const char *msg_name = NULL; + instance_t instance; + int result; + /* for no gcc warnings */ + (void)instance; + + itti_mark_task_ready(TASK_GNB_APP); + do { + // Wait for a message + itti_receive_msg(TASK_GNB_APP, &msg_p); + + msg_name = ITTI_MSG_NAME(msg_p); + instance = ITTI_MSG_DESTINATION_INSTANCE(msg_p); + + switch (ITTI_MSG_ID(msg_p)) { + case TERMINATE_MESSAGE: + LOG_W(GNB_APP, " *** Exiting GNB_APP thread\n"); + itti_exit_task(); + break; + + case NGAP_REGISTER_GNB_CNF: + LOG_I(GNB_APP, "[gNB %ld] Received %s: associated AMF %d\n", instance, msg_name, NGAP_REGISTER_GNB_CNF(msg_p).nb_amf); + send_initial_ue_message(instance); + break; + + default: + LOG_E(GNB_APP, "Received unexpected message %s\n", msg_name); + break; + } + result = itti_free(ITTI_MSG_ORIGIN_ID(msg_p), msg_p); + AssertFatal(result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result); + } while (1); + + return NULL; +} + void *rrc_gnb_task(void *args_p) { MessageDef *msg_p; @@ -151,6 +273,13 @@ void *rrc_gnb_task(void *args_p) LOG_W(NR_RRC, " *** Exiting NR_RRC thread\n"); itti_exit_task(); break; + case NGAP_DOWNLINK_NAS: + LOG_I(NR_RRC, "Ignore NGAP_DOWNLINK_NAS: dont have to handle"); + ngap_downlink_nas_t *nas = &NGAP_DOWNLINK_NAS(msg_p); + if (nas->nas_pdu.buf) { + free(nas->nas_pdu.buf); + } + break; case NRPPA_TRP_INFORMATION_REQ: nrppa_trp_information_req_t *trp_req = &NRPPA_TRP_INFORMATION_REQ(msg_p); LOG_I(NR_RRC, "Received NRPPA_TRP_INFORMATION_REQ transaction_id %d\n", trp_req->transaction_id); @@ -177,6 +306,8 @@ int main(int argc, char **argv) } logInit(); + init_ue_nas_context(); + set_softmodem_sighandler(); // Initialize ITTI tasks @@ -195,6 +326,9 @@ int main(int argc, char **argv) rc = itti_create_task(TASK_RRC_GNB, rrc_gnb_task, NULL); AssertFatal(rc >= 0, "Create task for RRC failed\n"); + rc = itti_create_task(TASK_GNB_APP, gNB_app_task, NULL); + AssertFatal(rc >= 0, "Create task for RRC failed\n"); + MessageDef *msg_p; msg_p = itti_alloc_new_message(TASK_GNB_APP, 0, NGAP_REGISTER_GNB_REQ); RCconfig_NR_NG(msg_p, 0); From 559e3c31de944d4621c41eb2a1869d6226c84d10 Mon Sep 17 00:00:00 2001 From: Rakesh Mundlamuri Date: Fri, 23 Jan 2026 17:50:39 +0530 Subject: [PATCH 16/21] Add Positioning Information Response NRPPA message encoding procedures --- openair2/COMMON/nrppa_messages_def.h | 4 + openair2/COMMON/nrppa_messages_types.h | 348 ++++++++ openair3/NRPPA/nrppa_gNB.c | 3 + .../nrppa_gNB_location_information_transfer.c | 802 ++++++++++++++++++ .../nrppa_gNB_location_information_transfer.h | 3 + openair3/NRPPA/nrppa_includes.h | 27 + tests/nr-cu-nrppa/nr-cu-nrppa.c | 291 +++++++ 7 files changed, 1478 insertions(+) diff --git a/openair2/COMMON/nrppa_messages_def.h b/openair2/COMMON/nrppa_messages_def.h index e3ddeb244f..d20bf1960a 100644 --- a/openair2/COMMON/nrppa_messages_def.h +++ b/openair2/COMMON/nrppa_messages_def.h @@ -28,3 +28,7 @@ MESSAGE_DEF(NRPPA_POSITIONING_INFORMATION_REQ, MESSAGE_PRIORITY_MED, nrppa_positioning_information_req_t, nrppa_positioning_information_req) +MESSAGE_DEF(NRPPA_POSITIONING_INFORMATION_RESP, + MESSAGE_PRIORITY_MED, + nrppa_positioning_information_resp_t, + nrppa_positioning_information_resp) diff --git a/openair2/COMMON/nrppa_messages_types.h b/openair2/COMMON/nrppa_messages_types.h index fef930ac9a..4522604422 100644 --- a/openair2/COMMON/nrppa_messages_types.h +++ b/openair2/COMMON/nrppa_messages_types.h @@ -27,6 +27,7 @@ #define NRPPA_TRP_INFORMATION_REQ(mSGpTR) (mSGpTR)->ittiMsg.nrppa_trp_information_req #define NRPPA_TRP_INFORMATION_RESP(mSGpTR) (mSGpTR)->ittiMsg.nrppa_trp_information_resp #define NRPPA_POSITIONING_INFORMATION_REQ(mSGpTR) (mSGpTR)->ittiMsg.nrppa_positioning_information_req +#define NRPPA_POSITIONING_INFORMATION_RESP(mSGpTR) (mSGpTR)->ittiMsg.nrppa_positioning_information_resp /* Structure of Positioning related NRPPA messages */ /* IE structures for Positioning related messages as per TS 38.455 V16.7.1*/ @@ -223,6 +224,346 @@ typedef struct nrppa_trp_information_s { nrppa_trp_information_type_response_list_t trp_information_type_response_list; } nrppa_trp_information_t; +typedef enum nrppa_subcarrier_spacing_e { + NRPPA_SUBCARRIER_SPACING_15KHZ, + NRPPA_SUBCARRIER_SPACING_30KHZ, + NRPPA_SUBCARRIER_SPACING_60KHZ, + NRPPA_SUBCARRIER_SPACING_120KHZ +} nrppa_subcarrier_spacing_pr; + +typedef struct nrppa_scs_specific_carrier_s { + uint32_t offset_to_carrier; + nrppa_subcarrier_spacing_pr subcarrier_spacing; + uint16_t carrier_bandwidth; +} nrppa_scs_specific_carrier_t; + +typedef struct nrppa_uplink_channel_bw_per_scs_list_s { + nrppa_scs_specific_carrier_t *scs_specific_carrier; + uint32_t scs_specific_carrier_list_length; +} nrppa_uplink_channel_bw_per_scs_list_t; + +typedef enum nrppa_transmission_comb_e { + NRPPA_TRANSMISSION_COMB_PR_NOTHING, + NRPPA_TRANSMISSION_COMB_PR_N2, + NRPPA_TRANSMISSION_COMB_PR_N4 +} nrppa_transmission_comb_pr; + +typedef struct nrppa_transmission_comb_n2_s { + uint8_t comb_offset_n2; + uint8_t cyclic_shift_n2; +} nrppa_transmission_comb_n2_t, nrppa_transmission_comb_pos_n2_t; + +typedef struct nrppa_transmission_comb_n4_s { + uint8_t comb_offset_n4; + uint8_t cyclic_shift_n4; +} nrppa_transmission_comb_n4_t, nrppa_transmission_comb_pos_n4_t; + +typedef union nrppa_transmission_comb_c { + nrppa_transmission_comb_n2_t n2; + nrppa_transmission_comb_n4_t n4; +} nrppa_transmission_comb_u; + +typedef struct nrppa_transmission_comb_s { + nrppa_transmission_comb_pr present; + nrppa_transmission_comb_u choice; +} nrppa_transmission_comb_t; + +typedef enum nrppa_srs_resource_type_periodicity_e { + NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT1 = 0, + NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT2, + NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT4, + NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT5, + NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT8, + NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT10, + NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT16, + NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT20, + NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT32, + NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT40, + NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT64, + NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT80, + NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT160, + NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT320, + NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT640, + NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT1280, + NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT2560 +} nrppa_srs_resource_type_periodicity_pr; + +typedef struct nrppa_resource_type_periodic_s { + nrppa_srs_resource_type_periodicity_pr periodicity; + uint16_t offset; +} nrppa_resource_type_periodic_t, nrppa_resource_type_semi_persistent_t; + +typedef union nrppa_resource_type_c { + nrppa_resource_type_periodic_t periodic; + nrppa_resource_type_semi_persistent_t semi_persistent; + bool aperiodic; +} nrppa_resource_type_u; + +typedef enum nrppa_resource_type_e { + NRPPA_RESOURCE_TYPE_PR_NOTHING, + NRPPA_RESOURCE_TYPE_PR_PERIODIC, + NRPPA_RESOURCE_TYPE_PR_SEMI_PERSISTENT, + NRPPA_RESOURCE_TYPE_PR_APERIODIC +} nrppa_resource_type_pr; + +typedef struct nrppa_resource_type_s { + nrppa_resource_type_pr present; + nrppa_resource_type_u choice; +} nrppa_resource_type_t; + +typedef struct nrppa_transmission_comb_n8_s { + uint8_t comb_offset_n8; + uint8_t cyclic_shift_n8; +} nrppa_transmission_comb_pos_n8_t; + +typedef union nrppa_transmission_comb_pos_c { + nrppa_transmission_comb_pos_n2_t n2; + nrppa_transmission_comb_pos_n4_t n4; + nrppa_transmission_comb_pos_n8_t n8; +} nrppa_transmission_comb_pos_u; + +typedef enum nrppa_transmission_comb_pos_e { + NRPPA_TRANSMISSION_COMB_POS_PR_NOTHING, + NRPPA_TRANSMISSION_COMB_POS_PR_N2, + NRPPA_TRANSMISSION_COMB_POS_PR_N4, + NRPPA_TRANSMISSION_COMB_POS_PR_N8 +} nrppa_transmission_comb_pos_pr; + +typedef struct nrppa_transmission_comb_pos_s { + nrppa_transmission_comb_pos_pr present; + nrppa_transmission_comb_pos_u choice; +} nrppa_transmission_comb_pos_t; + +typedef enum nrppa_srs_resource_type_pos_periodicity_e { + NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT1 = 0, + NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT2, + NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT4, + NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT5, + NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT8, + NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT10, + NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT16, + NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT20, + NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT32, + NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT40, + NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT64, + NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT80, + NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT160, + NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT320, + NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT640, + NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT1280, + NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT2560, + NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT5120, + NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT10240, + NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT20480, + NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT40960, + NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT81920 +} nrppa_srs_resource_type_pos_periodicity_pr; + +typedef struct nrppa_resource_type_periodic_pos_s { + nrppa_srs_resource_type_pos_periodicity_pr periodicity; + uint16_t offset; +} nrppa_resource_type_periodic_pos_t, nrppa_resource_type_semi_persistent_pos_t; + +typedef struct nrppa_resource_type_aperiodic_pos_s { + uint8_t slot_offset; +} nrppa_resource_type_aperiodic_pos_t; + +typedef union nrppa_resource_type_pos_c { + nrppa_resource_type_periodic_pos_t periodic; + nrppa_resource_type_semi_persistent_pos_t semi_persistent; + nrppa_resource_type_aperiodic_pos_t aperiodic; +} nrppa_resource_type_pos_u; + +typedef enum nrppa_resource_type_pos_e { + NRPPA_RESOURCE_TYPE_POS_PR_NOTHING, + NRPPA_RESOURCE_TYPE_POS_PR_PERIODIC, + NRPPA_RESOURCE_TYPE_POS_PR_SEMI_PERSISTENT, + NRPPA_RESOURCE_TYPE_POS_PR_APERIODIC +} nrppa_resource_type_pos_pr; + +typedef struct nrppa_resource_type_pos_s { + nrppa_resource_type_pos_pr present; + nrppa_resource_type_pos_u choice; +} nrppa_resource_type_pos_t; + +typedef struct nrppa_srs_resource_id_list_s { + long *srs_resource_id; + uint8_t srs_resource_id_list_length; +} nrppa_srs_resource_id_list_t; + +typedef struct nrppa_resource_set_type_aperiodic_s { + uint8_t srs_resource_trigger; + long slot_offset; +} nrppa_resource_set_type_aperiodic_t; + +typedef union nrppa_resource_set_type_c { + bool periodic; + bool semi_persistent; + nrppa_resource_set_type_aperiodic_t aperiodic; +} nrppa_resource_set_type_u; + +typedef enum nrppa_resource_set_type_e { + NRPPA_RESOURCE_SET_TYPE_PR_NOTHING, + NRPPA_RESOURCE_SET_TYPE_PR_PERIODIC, + NRPPA_RESOURCE_SET_TYPE_PR_SEMI_PERSISTENT, + NRPPA_RESOURCE_SET_TYPE_PR_APERIODIC +} nrppa_resource_set_type_pr; + +typedef struct nrppa_resource_set_type_s { + nrppa_resource_set_type_pr present; + nrppa_resource_set_type_u choice; +} nrppa_resource_set_type_t; + +typedef struct nrppa_pos_srs_resource_id_list_s { + long *srs_pos_resource_id; + uint32_t pos_srs_resource_id_list_length; +} nrppa_pos_srs_resource_id_list_t; + +typedef union nrppa_pos_resource_set_type_c { + bool periodic; + bool semi_persistent; + uint8_t srs_resource; +} nrppa_pos_resource_set_type_u; + +typedef enum nrppa_pos_resource_set_type_e { + NRPPA_POS_RESOURCE_SET_TYPE_PR_NOTHING, + NRPPA_POS_RESOURCE_SET_TYPE_PR_PERIODIC, + NRPPA_POS_RESOURCE_SET_TYPE_PR_SEMI_PERSISTENT, + NRPPA_POS_RESOURCE_SET_TYPE_PR_APERIODIC +} nrppa_pos_resource_set_type_pr; + +typedef struct nrppa_pos_resource_set_type_s { + nrppa_pos_resource_set_type_pr present; + nrppa_pos_resource_set_type_u choice; +} nrppa_pos_resource_set_type_t; + +typedef enum nrppa_srs_resource_number_of_ports_e { + NRPPA_SRS_NUMBER_OF_PORTS_N1, + NRPPA_SRS_NUMBER_OF_PORTS_N2, + NRPPA_SRS_NUMBER_OF_PORTS_N4 +} nrppa_srs_resource_number_of_ports_pr; + +typedef enum nrppa_srs_resource_number_of_symbols_e { + NRPPA_SRS_NUMBER_OF_SYMBOLS_N1, + NRPPA_SRS_NUMBER_OF_SYMBOLS_N2, + NRPPA_SRS_NUMBER_OF_SYMBOLS_N4 +} nrppa_srs_resource_number_of_symbols_pr; + +typedef enum nrppa_srs_repetition_factor_e { + NRPPA_SRS_REPETITION_FACTOR_RF1, + NRPPA_SRS_REPETITION_FACTOR_RF2, + NRPPA_SRS_REPETITION_FACTOR_RF4 +} nrppa_srs_repetition_factor_pr; + +typedef enum nrppa_srs_group_or_sequencehopping_e { + NRPPA_GROUPORSEQUENCEHOPPING_NOTHING, + NRPPA_GROUPORSEQUENCEHOPPING_GROUPHOPPING, + NRPPA_GROUPORSEQUENCEHOPPING_SEQUENCEHOPPING +} nrppa_srs_group_or_sequencehopping_pr; + +typedef struct nrppa_srs_resource_s { + uint32_t srs_resource_id; + nrppa_srs_resource_number_of_ports_pr nr_of_srs_ports; + nrppa_transmission_comb_t transmission_comb; + uint8_t start_position; + nrppa_srs_resource_number_of_symbols_pr nr_of_symbols; + nrppa_srs_repetition_factor_pr repetition_factor; + uint8_t freq_domain_position; + uint16_t freq_domain_shift; + uint8_t c_srs; + uint8_t b_srs; + uint8_t b_hop; + nrppa_srs_group_or_sequencehopping_pr group_or_sequence_hopping; + nrppa_resource_type_t resource_type; + uint16_t sequence_id; +} nrppa_srs_resource_t; + +typedef enum nrppa_srs_resource_item_number_of_symbols_e { + NRPPA_SRS_RESOURCE_ITEM_NUMBER_OF_SYMBOLS_N1, + NRPPA_SRS_RESOURCE_ITEM_NUMBER_OF_SYMBOLS_N2, + NRPPA_SRS_RESOURCE_ITEM_NUMBER_OF_SYMBOLS_N4, + NRPPA_SRS_RESOURCE_ITEM_NUMBER_OF_SYMBOLS_N8, + NRPPA_SRS_RESOURCE_ITEM_NUMBER_OF_SYMBOLS_N12 +} nrppa_srs_resource_item_number_of_symbols_pr; + +typedef struct nrppa_pos_srs_resource_item_s { + uint32_t srs_pos_resource_id; + nrppa_transmission_comb_pos_t transmission_comb_pos; + uint8_t start_position; + nrppa_srs_resource_item_number_of_symbols_pr nr_of_symbols; + uint16_t freq_domain_shift; + uint8_t c_srs; + nrppa_srs_group_or_sequencehopping_pr group_or_sequence_hopping; + nrppa_resource_type_pos_t resource_type_pos; + uint32_t sequence_id; +} nrppa_pos_srs_resource_item_t; + +typedef struct nrppa_srs_resource_set_s { + uint8_t srs_resource_set_id; + nrppa_srs_resource_id_list_t srs_resource_id_list; + nrppa_resource_set_type_t resource_set_type; +} nrppa_srs_resource_set_t; + +typedef struct nrppa_pos_srs_resource_set_item_s { + uint8_t pos_srs_resource_set_id; + nrppa_pos_srs_resource_id_list_t pos_srs_resource_id_list; + nrppa_pos_resource_set_type_t pos_resource_set_type; +} nrppa_pos_srs_resource_set_item_t; + +typedef struct nrppa_srs_resource_list_s { + nrppa_srs_resource_t *srs_resource; + uint32_t srs_resource_list_length; +} nrppa_srs_resource_list_t; + +typedef struct nrppa_pos_srs_resource_list_s { + nrppa_pos_srs_resource_item_t *pos_srs_resource_item; + uint32_t pos_srs_resource_list_length; +} nrppa_pos_srs_resource_list_t; + +typedef struct nrppa_srs_resource_set_list_s { + nrppa_srs_resource_set_t *srs_resource_set; + uint32_t srs_resource_set_list_length; +} nrppa_srs_resource_set_list_t; + +typedef struct nrppa_pos_srs_resource_set_list_s { + nrppa_pos_srs_resource_set_item_t *pos_srs_resource_set_item; + uint32_t pos_srs_resource_set_list_length; +} nrppa_pos_srs_resource_set_list_t; + +typedef struct nrppa_srs_config_s { + nrppa_srs_resource_list_t *srs_resource_list; + nrppa_pos_srs_resource_list_t *pos_srs_resource_list; + nrppa_srs_resource_set_list_t *srs_resource_set_list; + nrppa_pos_srs_resource_set_list_t *pos_srs_resource_set_list; +} nrppa_srs_config_t; + +typedef enum nrppa_cp_type_e { NRPPA_CP_TYPE_NORMAL, NRPPA_CP_TYPE_EXTENDED } nrppa_cp_type_pr; + +typedef struct nrppa_active_ul_bwp_s { + uint32_t location_and_bandwidth; + nrppa_subcarrier_spacing_pr subcarrier_spacing; + nrppa_cp_type_pr cyclic_prefix; + uint32_t tx_direct_current_location; + uint8_t shift_7_dot_5kHz; + nrppa_srs_config_t srs_config; +} nrppa_active_ul_bwp_t; + +typedef struct nrppa_srs_carrier_list_item_s { + uint32_t pointA; + nrppa_uplink_channel_bw_per_scs_list_t uplink_channel_bw_per_scs_list; + nrppa_active_ul_bwp_t active_ul_bwp; + uint16_t pci; +} nrppa_srs_carrier_list_item_t; + +typedef struct nrppa_srs_carrier_list_s { + nrppa_srs_carrier_list_item_t *srs_carrier_list_item; + uint32_t srs_carrier_list_length; +} nrppa_srs_carrier_list_t; + +typedef struct nrppa_srs_configuration_s { + nrppa_srs_carrier_list_t srs_carrier_list; +} nrppa_srs_configuration_t; + // IE 9.3.1.176 (TS 38.473 V16.21.0) typedef struct nrppa_trp_information_list_s { nrppa_trp_information_t *trp_information_item; @@ -251,4 +592,11 @@ typedef struct nrppa_positioning_information_req_s { uint16_t transaction_id; } nrppa_positioning_information_req_t; +typedef struct nrppa_positioning_information_resp_s { + // IE 9.2.4 (mandatory) + uint16_t transaction_id; + // IE 9.2.28 (optional) + nrppa_srs_configuration_t *srs_configuration; +} nrppa_positioning_information_resp_t; + #endif // NRPPA_MESSAGES_TYPES_H_ diff --git a/openair3/NRPPA/nrppa_gNB.c b/openair3/NRPPA/nrppa_gNB.c index bb00cecd54..19e76bc392 100644 --- a/openair3/NRPPA/nrppa_gNB.c +++ b/openair3/NRPPA/nrppa_gNB.c @@ -60,6 +60,9 @@ void *nrppa_gNB_process_itti_msg(void *notUsed) case NRPPA_TRP_INFORMATION_RESP: nrppa_gNB_trp_information_response(instance, received_msg); break; + case NRPPA_POSITIONING_INFORMATION_RESP: + nrppa_gNB_positioning_information_response(instance, received_msg); + break; default: LOG_E(NRPPA, "Received unhandled message: %d:%s\n", ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg)); break; diff --git a/openair3/NRPPA/nrppa_gNB_location_information_transfer.c b/openair3/NRPPA/nrppa_gNB_location_information_transfer.c index 6821e251ed..5d1a43c0a6 100644 --- a/openair3/NRPPA/nrppa_gNB_location_information_transfer.c +++ b/openair3/NRPPA/nrppa_gNB_location_information_transfer.c @@ -263,6 +263,728 @@ void free_trp_information_response(nrppa_trp_information_resp_t *msg) free(msg->trp_information_list.trp_information_item); } +static NRPPA_SRSConfig_t encode_srs_config(const nrppa_srs_config_t *in_config) +{ + NRPPA_SRSConfig_t out_config = {0}; + // optional: srs_resource_list + if (in_config->srs_resource_list) { + nrppa_srs_resource_list_t *srs_resource_list = in_config->srs_resource_list; + uint32_t srs_resource_list_length = srs_resource_list->srs_resource_list_length; + asn1cCalloc(out_config.sRSResource_List, nrppa_sRSResource_List); + for (int i = 0; i < srs_resource_list_length; i++) { + asn1cSequenceAdd(nrppa_sRSResource_List->list, NRPPA_SRSResource_t, nrppa_srs_resource); + nrppa_srs_resource_t *srs_resource = &srs_resource_list->srs_resource[i]; + nrppa_srs_resource->sRSResourceID = srs_resource->srs_resource_id; + + switch (srs_resource->nr_of_srs_ports) { + case NRPPA_SRS_NUMBER_OF_PORTS_N1: + nrppa_srs_resource->nrofSRS_Ports = NRPPA_SRSResource__nrofSRS_Ports_port1; + break; + case NRPPA_SRS_NUMBER_OF_PORTS_N2: + nrppa_srs_resource->nrofSRS_Ports = NRPPA_SRSResource__nrofSRS_Ports_ports2; + break; + case NRPPA_SRS_NUMBER_OF_PORTS_N4: + nrppa_srs_resource->nrofSRS_Ports = NRPPA_SRSResource__nrofSRS_Ports_ports4; + break; + default: + AssertFatal(false, "illegal number of srs ports %d\n", srs_resource->nr_of_srs_ports); + break; + } + + nrppa_transmission_comb_t *srs_res_tx_comb = &srs_resource->transmission_comb; + switch (srs_res_tx_comb->present) { + case NRPPA_TRANSMISSION_COMB_PR_NOTHING: + nrppa_srs_resource->transmissionComb.present = NRPPA_TransmissionComb_PR_NOTHING; + break; + case NRPPA_TRANSMISSION_COMB_PR_N2: + nrppa_srs_resource->transmissionComb.present = NRPPA_TransmissionComb_PR_n2; + asn1cCalloc(nrppa_srs_resource->transmissionComb.choice.n2, nrppa_n2); + nrppa_n2->combOffset_n2 = srs_res_tx_comb->choice.n2.comb_offset_n2; + nrppa_n2->cyclicShift_n2 = srs_res_tx_comb->choice.n2.cyclic_shift_n2; + break; + case NRPPA_TRANSMISSION_COMB_PR_N4: + nrppa_srs_resource->transmissionComb.present = NRPPA_TransmissionComb_PR_n4; + asn1cCalloc(nrppa_srs_resource->transmissionComb.choice.n4, nrppa_n4); + nrppa_n4->combOffset_n4 = srs_res_tx_comb->choice.n4.comb_offset_n4; + nrppa_n4->cyclicShift_n4 = srs_res_tx_comb->choice.n4.cyclic_shift_n4; + break; + default: + AssertFatal(false, "illegal transmissionComb %d\n", srs_res_tx_comb->present); + break; + } + + nrppa_srs_resource->startPosition = srs_resource->start_position; + + switch (srs_resource->nr_of_symbols) { + case NRPPA_SRS_NUMBER_OF_SYMBOLS_N1: + nrppa_srs_resource->nrofSymbols = NRPPA_SRSResource__nrofSymbols_n1; + break; + case NRPPA_SRS_NUMBER_OF_SYMBOLS_N2: + nrppa_srs_resource->nrofSymbols = NRPPA_SRSResource__nrofSymbols_n2; + break; + case NRPPA_SRS_NUMBER_OF_SYMBOLS_N4: + nrppa_srs_resource->nrofSymbols = NRPPA_SRSResource__nrofSymbols_n4; + break; + default: + AssertFatal(false, "illegal number of symbols %d\n", srs_resource->nr_of_symbols); + break; + } + + switch (srs_resource->repetition_factor) { + case NRPPA_SRS_REPETITION_FACTOR_RF1: + nrppa_srs_resource->repetitionFactor = NRPPA_SRSResource__repetitionFactor_n1; + break; + case NRPPA_SRS_REPETITION_FACTOR_RF2: + nrppa_srs_resource->repetitionFactor = NRPPA_SRSResource__repetitionFactor_n2; + break; + case NRPPA_SRS_REPETITION_FACTOR_RF4: + nrppa_srs_resource->repetitionFactor = NRPPA_SRSResource__repetitionFactor_n4; + break; + default: + AssertFatal(false, "illegal repetition factor %d\n", srs_resource->repetition_factor); + break; + } + + nrppa_srs_resource->freqDomainPosition = srs_resource->freq_domain_position; + nrppa_srs_resource->freqDomainShift = srs_resource->freq_domain_shift; + nrppa_srs_resource->c_SRS = srs_resource->c_srs; + nrppa_srs_resource->b_SRS = srs_resource->b_srs; + nrppa_srs_resource->b_hop = srs_resource->b_hop; + + switch (srs_resource->group_or_sequence_hopping) { + case NRPPA_GROUPORSEQUENCEHOPPING_NOTHING: + nrppa_srs_resource->groupOrSequenceHopping = NRPPA_SRSResource__groupOrSequenceHopping_neither; + break; + case NRPPA_GROUPORSEQUENCEHOPPING_GROUPHOPPING: + nrppa_srs_resource->groupOrSequenceHopping = NRPPA_SRSResource__groupOrSequenceHopping_groupHopping; + break; + case NRPPA_GROUPORSEQUENCEHOPPING_SEQUENCEHOPPING: + nrppa_srs_resource->groupOrSequenceHopping = NRPPA_SRSResource__groupOrSequenceHopping_sequenceHopping; + break; + default: + AssertFatal(false, "illegal groupOrSequenceHopping %d\n", srs_resource->group_or_sequence_hopping); + break; + } + + NRPPA_ResourceType_t *nrppa_resourceType = &nrppa_srs_resource->resourceType; + nrppa_resource_type_t *resource_type = &srs_resource->resource_type; + if (resource_type->present == NRPPA_RESOURCE_TYPE_PR_NOTHING) { + nrppa_resourceType->present = NRPPA_ResourceType_PR_NOTHING; + } else if (resource_type->present == NRPPA_RESOURCE_TYPE_PR_PERIODIC) { + nrppa_resourceType->present = NRPPA_ResourceType_PR_periodic; + asn1cCalloc(nrppa_resourceType->choice.periodic, nrppa_periodic); + switch (resource_type->choice.periodic.periodicity) { + case NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT1: + nrppa_periodic->periodicity = NRPPA_ResourceTypePeriodic__periodicity_slot1; + break; + case NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT2: + nrppa_periodic->periodicity = NRPPA_ResourceTypePeriodic__periodicity_slot2; + break; + case NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT4: + nrppa_periodic->periodicity = NRPPA_ResourceTypePeriodic__periodicity_slot4; + break; + case NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT5: + nrppa_periodic->periodicity = NRPPA_ResourceTypePeriodic__periodicity_slot5; + break; + case NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT8: + nrppa_periodic->periodicity = NRPPA_ResourceTypePeriodic__periodicity_slot8; + break; + case NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT10: + nrppa_periodic->periodicity = NRPPA_ResourceTypePeriodic__periodicity_slot10; + break; + case NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT16: + nrppa_periodic->periodicity = NRPPA_ResourceTypePeriodic__periodicity_slot16; + break; + case NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT20: + nrppa_periodic->periodicity = NRPPA_ResourceTypePeriodic__periodicity_slot20; + break; + case NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT32: + nrppa_periodic->periodicity = NRPPA_ResourceTypePeriodic__periodicity_slot32; + break; + case NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT40: + nrppa_periodic->periodicity = NRPPA_ResourceTypePeriodic__periodicity_slot40; + break; + case NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT64: + nrppa_periodic->periodicity = NRPPA_ResourceTypePeriodic__periodicity_slot64; + break; + case NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT80: + nrppa_periodic->periodicity = NRPPA_ResourceTypePeriodic__periodicity_slot80; + break; + case NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT160: + nrppa_periodic->periodicity = NRPPA_ResourceTypePeriodic__periodicity_slot160; + break; + case NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT320: + nrppa_periodic->periodicity = NRPPA_ResourceTypePeriodic__periodicity_slot320; + break; + case NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT640: + nrppa_periodic->periodicity = NRPPA_ResourceTypePeriodic__periodicity_slot640; + break; + case NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT1280: + nrppa_periodic->periodicity = NRPPA_ResourceTypePeriodic__periodicity_slot1280; + break; + case NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT2560: + nrppa_periodic->periodicity = NRPPA_ResourceTypePeriodic__periodicity_slot2560; + break; + default: + AssertFatal(false, "illegal periodicity %d\n", resource_type->choice.periodic.periodicity); + break; + } + nrppa_periodic->offset = resource_type->choice.periodic.offset; + } else if (resource_type->present == NRPPA_RESOURCE_TYPE_PR_SEMI_PERSISTENT) { + nrppa_resourceType->present = NRPPA_ResourceType_PR_semi_persistent; + asn1cCalloc(nrppa_resourceType->choice.semi_persistent, nrppa_semi_persistent); + switch (resource_type->choice.semi_persistent.periodicity) { + case NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT1: + nrppa_semi_persistent->periodicity = NRPPA_ResourceTypeSemi_persistent__periodicity_slot1; + break; + case NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT2: + nrppa_semi_persistent->periodicity = NRPPA_ResourceTypeSemi_persistent__periodicity_slot2; + break; + case NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT4: + nrppa_semi_persistent->periodicity = NRPPA_ResourceTypeSemi_persistent__periodicity_slot4; + break; + case NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT5: + nrppa_semi_persistent->periodicity = NRPPA_ResourceTypeSemi_persistent__periodicity_slot5; + break; + case NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT8: + nrppa_semi_persistent->periodicity = NRPPA_ResourceTypeSemi_persistent__periodicity_slot8; + break; + case NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT10: + nrppa_semi_persistent->periodicity = NRPPA_ResourceTypeSemi_persistent__periodicity_slot10; + break; + case NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT16: + nrppa_semi_persistent->periodicity = NRPPA_ResourceTypeSemi_persistent__periodicity_slot16; + break; + case NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT20: + nrppa_semi_persistent->periodicity = NRPPA_ResourceTypeSemi_persistent__periodicity_slot20; + break; + case NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT32: + nrppa_semi_persistent->periodicity = NRPPA_ResourceTypeSemi_persistent__periodicity_slot32; + break; + case NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT40: + nrppa_semi_persistent->periodicity = NRPPA_ResourceTypeSemi_persistent__periodicity_slot40; + break; + case NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT64: + nrppa_semi_persistent->periodicity = NRPPA_ResourceTypeSemi_persistent__periodicity_slot64; + break; + case NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT80: + nrppa_semi_persistent->periodicity = NRPPA_ResourceTypeSemi_persistent__periodicity_slot80; + break; + case NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT160: + nrppa_semi_persistent->periodicity = NRPPA_ResourceTypeSemi_persistent__periodicity_slot160; + break; + case NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT320: + nrppa_semi_persistent->periodicity = NRPPA_ResourceTypeSemi_persistent__periodicity_slot320; + break; + case NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT640: + nrppa_semi_persistent->periodicity = NRPPA_ResourceTypeSemi_persistent__periodicity_slot640; + break; + case NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT1280: + nrppa_semi_persistent->periodicity = NRPPA_ResourceTypeSemi_persistent__periodicity_slot1280; + break; + case NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT2560: + nrppa_semi_persistent->periodicity = NRPPA_ResourceTypeSemi_persistent__periodicity_slot2560; + break; + default: + AssertFatal(false, "illegal periodicity %d\n", resource_type->choice.semi_persistent.periodicity); + break; + } + nrppa_semi_persistent->offset = resource_type->choice.semi_persistent.offset; + } else if (resource_type->present == NRPPA_RESOURCE_TYPE_PR_APERIODIC) { + nrppa_resourceType->present = NRPPA_ResourceType_PR_aperiodic; + asn1cCalloc(nrppa_resourceType->choice.aperiodic, nrppa_aperiodic); + nrppa_aperiodic->aperiodicResourceType = resource_type->choice.aperiodic; + } else { + AssertFatal(false, "illegal resourceType %d\n", resource_type->present); + } + + nrppa_srs_resource->sequenceId = srs_resource->sequence_id; + } + } + + // optional: pos_srs_resource_list + if (in_config->pos_srs_resource_list) { + nrppa_pos_srs_resource_list_t *pos_srs_resource_list = in_config->pos_srs_resource_list; + uint32_t pos_srs_resource_list_length = pos_srs_resource_list->pos_srs_resource_list_length; + asn1cCalloc(out_config.posSRSResource_List, nrppa_posSRSResource_List); + for (int i = 0; i < pos_srs_resource_list_length; i++) { + asn1cSequenceAdd(nrppa_posSRSResource_List->list, NRPPA_PosSRSResource_Item_t, nrppa_pos_srs_resource); + nrppa_pos_srs_resource_item_t *pos_srs_resource = &pos_srs_resource_list->pos_srs_resource_item[i]; + nrppa_pos_srs_resource->srs_PosResourceId = pos_srs_resource->srs_pos_resource_id; + + nrppa_transmission_comb_pos_t *pos_srs_res_tx_comb = &pos_srs_resource->transmission_comb_pos; + switch (pos_srs_res_tx_comb->present) { + case NRPPA_TRANSMISSION_COMB_POS_PR_NOTHING: + nrppa_pos_srs_resource->transmissionCombPos.present = NRPPA_TransmissionCombPos_PR_NOTHING; + break; + case NRPPA_TRANSMISSION_COMB_POS_PR_N2: + nrppa_pos_srs_resource->transmissionCombPos.present = NRPPA_TransmissionCombPos_PR_n2; + asn1cCalloc(nrppa_pos_srs_resource->transmissionCombPos.choice.n2, nrppa_pos_srs_resource_n2); + nrppa_transmission_comb_pos_n2_t *pos_srs_resource_n2 = &pos_srs_res_tx_comb->choice.n2; + nrppa_pos_srs_resource_n2->combOffset_n2 = pos_srs_resource_n2->comb_offset_n2; + nrppa_pos_srs_resource_n2->cyclicShift_n2 = pos_srs_resource_n2->cyclic_shift_n2; + break; + case NRPPA_TRANSMISSION_COMB_POS_PR_N4: + nrppa_pos_srs_resource->transmissionCombPos.present = NRPPA_TransmissionCombPos_PR_n4; + asn1cCalloc(nrppa_pos_srs_resource->transmissionCombPos.choice.n4, nrppa_pos_srs_resource_n4); + nrppa_transmission_comb_pos_n4_t *pos_srs_resource_n4 = &pos_srs_res_tx_comb->choice.n4; + nrppa_pos_srs_resource_n4->combOffset_n4 = pos_srs_resource_n4->comb_offset_n4; + nrppa_pos_srs_resource_n4->cyclicShift_n4 = pos_srs_resource_n4->cyclic_shift_n4; + break; + case NRPPA_TRANSMISSION_COMB_POS_PR_N8: + nrppa_pos_srs_resource->transmissionCombPos.present = NRPPA_TransmissionCombPos_PR_n8; + asn1cCalloc(nrppa_pos_srs_resource->transmissionCombPos.choice.n8, nrppa_pos_srs_resource_n8); + nrppa_transmission_comb_pos_n8_t *pos_srs_resource_n8 = &pos_srs_res_tx_comb->choice.n8; + nrppa_pos_srs_resource_n8->combOffset_n8 = pos_srs_resource_n8->comb_offset_n8; + nrppa_pos_srs_resource_n8->cyclicShift_n8 = pos_srs_resource_n8->cyclic_shift_n8; + break; + default: + AssertFatal(false, "illegal transmissionComb %d\n", pos_srs_res_tx_comb->present); + break; + } + + nrppa_pos_srs_resource->startPosition = pos_srs_resource->start_position; + + switch (pos_srs_resource->nr_of_symbols) { + case NRPPA_SRS_RESOURCE_ITEM_NUMBER_OF_SYMBOLS_N1: + nrppa_pos_srs_resource->nrofSymbols = NRPPA_PosSRSResource_Item__nrofSymbols_n1; + break; + case NRPPA_SRS_RESOURCE_ITEM_NUMBER_OF_SYMBOLS_N2: + nrppa_pos_srs_resource->nrofSymbols = NRPPA_PosSRSResource_Item__nrofSymbols_n2; + break; + case NRPPA_SRS_RESOURCE_ITEM_NUMBER_OF_SYMBOLS_N4: + nrppa_pos_srs_resource->nrofSymbols = NRPPA_PosSRSResource_Item__nrofSymbols_n4; + break; + case NRPPA_SRS_RESOURCE_ITEM_NUMBER_OF_SYMBOLS_N8: + nrppa_pos_srs_resource->nrofSymbols = NRPPA_PosSRSResource_Item__nrofSymbols_n8; + break; + case NRPPA_SRS_RESOURCE_ITEM_NUMBER_OF_SYMBOLS_N12: + nrppa_pos_srs_resource->nrofSymbols = NRPPA_PosSRSResource_Item__nrofSymbols_n12; + break; + default: + AssertFatal(false, "illegal number of symbols %d\n", pos_srs_resource->nr_of_symbols); + break; + } + + nrppa_pos_srs_resource->freqDomainShift = pos_srs_resource->freq_domain_shift; + nrppa_pos_srs_resource->c_SRS = pos_srs_resource->c_srs; + + switch (pos_srs_resource->group_or_sequence_hopping) { + case NRPPA_GROUPORSEQUENCEHOPPING_NOTHING: + nrppa_pos_srs_resource->groupOrSequenceHopping = NRPPA_PosSRSResource_Item__groupOrSequenceHopping_neither; + break; + case NRPPA_GROUPORSEQUENCEHOPPING_GROUPHOPPING: + nrppa_pos_srs_resource->groupOrSequenceHopping = NRPPA_PosSRSResource_Item__groupOrSequenceHopping_groupHopping; + break; + case NRPPA_GROUPORSEQUENCEHOPPING_SEQUENCEHOPPING: + nrppa_pos_srs_resource->groupOrSequenceHopping = NRPPA_PosSRSResource_Item__groupOrSequenceHopping_sequenceHopping; + break; + default: + AssertFatal(false, "illegal groupOrSequenceHopping %d\n", pos_srs_resource->group_or_sequence_hopping); + break; + } + + nrppa_resource_type_pos_t *resource_type_pos = &pos_srs_resource->resource_type_pos; + NRPPA_ResourceTypePos_t *nrppa_resourceTypePos = &nrppa_pos_srs_resource->resourceTypePos; + if (resource_type_pos->present == NRPPA_RESOURCE_TYPE_POS_PR_NOTHING) { + nrppa_resourceTypePos->present = NRPPA_ResourceTypePos_PR_NOTHING; + } else if (resource_type_pos->present == NRPPA_RESOURCE_TYPE_POS_PR_PERIODIC) { + nrppa_resourceTypePos->present = NRPPA_ResourceTypePos_PR_periodic; + asn1cCalloc(nrppa_resourceTypePos->choice.periodic, nrppa_pos_periodic); + switch (resource_type_pos->choice.periodic.periodicity) { + case NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT1: + nrppa_pos_periodic->periodicity = NRPPA_ResourceTypePeriodicPos__periodicity_slot1; + break; + case NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT2: + nrppa_pos_periodic->periodicity = NRPPA_ResourceTypePeriodicPos__periodicity_slot2; + break; + case NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT4: + nrppa_pos_periodic->periodicity = NRPPA_ResourceTypePeriodicPos__periodicity_slot4; + break; + case NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT5: + nrppa_pos_periodic->periodicity = NRPPA_ResourceTypePeriodicPos__periodicity_slot5; + break; + case NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT8: + nrppa_pos_periodic->periodicity = NRPPA_ResourceTypePeriodicPos__periodicity_slot8; + break; + case NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT10: + nrppa_pos_periodic->periodicity = NRPPA_ResourceTypePeriodicPos__periodicity_slot10; + break; + case NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT16: + nrppa_pos_periodic->periodicity = NRPPA_ResourceTypePeriodicPos__periodicity_slot16; + break; + case NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT20: + nrppa_pos_periodic->periodicity = NRPPA_ResourceTypePeriodicPos__periodicity_slot20; + break; + case NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT32: + nrppa_pos_periodic->periodicity = NRPPA_ResourceTypePeriodicPos__periodicity_slot32; + break; + case NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT40: + nrppa_pos_periodic->periodicity = NRPPA_ResourceTypePeriodicPos__periodicity_slot40; + break; + case NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT64: + nrppa_pos_periodic->periodicity = NRPPA_ResourceTypePeriodicPos__periodicity_slot64; + break; + case NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT80: + nrppa_pos_periodic->periodicity = NRPPA_ResourceTypePeriodicPos__periodicity_slot80; + break; + case NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT160: + nrppa_pos_periodic->periodicity = NRPPA_ResourceTypePeriodicPos__periodicity_slot160; + break; + case NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT320: + nrppa_pos_periodic->periodicity = NRPPA_ResourceTypePeriodicPos__periodicity_slot320; + break; + case NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT640: + nrppa_pos_periodic->periodicity = NRPPA_ResourceTypePeriodicPos__periodicity_slot640; + break; + case NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT1280: + nrppa_pos_periodic->periodicity = NRPPA_ResourceTypePeriodicPos__periodicity_slot1280; + break; + case NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT2560: + nrppa_pos_periodic->periodicity = NRPPA_ResourceTypePeriodicPos__periodicity_slot2560; + break; + case NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT5120: + nrppa_pos_periodic->periodicity = NRPPA_ResourceTypePeriodicPos__periodicity_slot5120; + break; + case NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT10240: + nrppa_pos_periodic->periodicity = NRPPA_ResourceTypePeriodicPos__periodicity_slot10240; + break; + case NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT20480: + nrppa_pos_periodic->periodicity = NRPPA_ResourceTypePeriodicPos__periodicity_slot20480; + break; + case NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT40960: + nrppa_pos_periodic->periodicity = NRPPA_ResourceTypePeriodicPos__periodicity_slot40960; + break; + case NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT81920: + nrppa_pos_periodic->periodicity = NRPPA_ResourceTypePeriodicPos__periodicity_slot81920; + break; + default: + AssertFatal(false, "illegal periodicity %d\n", resource_type_pos->choice.periodic.periodicity); + break; + } + + nrppa_pos_periodic->offset = resource_type_pos->choice.periodic.offset; + } else if (resource_type_pos->present == NRPPA_RESOURCE_TYPE_POS_PR_SEMI_PERSISTENT) { + nrppa_resourceTypePos->present = NRPPA_ResourceTypePos_PR_semi_persistent; + asn1cCalloc(nrppa_resourceTypePos->choice.semi_persistent, nrppa_pos_semi_persistent); + switch (resource_type_pos->choice.semi_persistent.periodicity) { + case NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT1: + nrppa_pos_semi_persistent->periodicity = NRPPA_ResourceTypeSemi_persistentPos__periodicity_slot1; + break; + case NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT2: + nrppa_pos_semi_persistent->periodicity = NRPPA_ResourceTypeSemi_persistentPos__periodicity_slot2; + break; + case NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT4: + nrppa_pos_semi_persistent->periodicity = NRPPA_ResourceTypeSemi_persistentPos__periodicity_slot4; + break; + case NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT5: + nrppa_pos_semi_persistent->periodicity = NRPPA_ResourceTypeSemi_persistentPos__periodicity_slot5; + break; + case NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT8: + nrppa_pos_semi_persistent->periodicity = NRPPA_ResourceTypeSemi_persistentPos__periodicity_slot8; + break; + case NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT10: + nrppa_pos_semi_persistent->periodicity = NRPPA_ResourceTypeSemi_persistentPos__periodicity_slot10; + break; + case NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT16: + nrppa_pos_semi_persistent->periodicity = NRPPA_ResourceTypeSemi_persistentPos__periodicity_slot16; + break; + case NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT20: + nrppa_pos_semi_persistent->periodicity = NRPPA_ResourceTypeSemi_persistentPos__periodicity_slot20; + break; + case NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT32: + nrppa_pos_semi_persistent->periodicity = NRPPA_ResourceTypeSemi_persistentPos__periodicity_slot32; + break; + case NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT40: + nrppa_pos_semi_persistent->periodicity = NRPPA_ResourceTypeSemi_persistentPos__periodicity_slot40; + break; + case NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT64: + nrppa_pos_semi_persistent->periodicity = NRPPA_ResourceTypeSemi_persistentPos__periodicity_slot64; + break; + case NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT80: + nrppa_pos_semi_persistent->periodicity = NRPPA_ResourceTypeSemi_persistentPos__periodicity_slot80; + break; + case NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT160: + nrppa_pos_semi_persistent->periodicity = NRPPA_ResourceTypeSemi_persistentPos__periodicity_slot160; + break; + case NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT320: + nrppa_pos_semi_persistent->periodicity = NRPPA_ResourceTypeSemi_persistentPos__periodicity_slot320; + break; + case NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT640: + nrppa_pos_semi_persistent->periodicity = NRPPA_ResourceTypeSemi_persistentPos__periodicity_slot640; + break; + case NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT1280: + nrppa_pos_semi_persistent->periodicity = NRPPA_ResourceTypeSemi_persistentPos__periodicity_slot1280; + break; + case NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT2560: + nrppa_pos_semi_persistent->periodicity = NRPPA_ResourceTypeSemi_persistentPos__periodicity_slot2560; + break; + case NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT5120: + nrppa_pos_semi_persistent->periodicity = NRPPA_ResourceTypeSemi_persistentPos__periodicity_slot5120; + break; + case NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT10240: + nrppa_pos_semi_persistent->periodicity = NRPPA_ResourceTypeSemi_persistentPos__periodicity_slot10240; + break; + case NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT20480: + nrppa_pos_semi_persistent->periodicity = NRPPA_ResourceTypeSemi_persistentPos__periodicity_slot20480; + break; + case NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT40960: + nrppa_pos_semi_persistent->periodicity = NRPPA_ResourceTypeSemi_persistentPos__periodicity_slot40960; + break; + case NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT81920: + nrppa_pos_semi_persistent->periodicity = NRPPA_ResourceTypeSemi_persistentPos__periodicity_slot81920; + break; + default: + AssertFatal(false, "illegal periodicity %d\n", resource_type_pos->choice.semi_persistent.periodicity); + break; + } + nrppa_pos_semi_persistent->offset = resource_type_pos->choice.semi_persistent.offset; + } else if (resource_type_pos->present == NRPPA_RESOURCE_TYPE_POS_PR_APERIODIC) { + nrppa_resourceTypePos->present = NRPPA_ResourceTypePos_PR_aperiodic; + asn1cCalloc(nrppa_resourceTypePos->choice.aperiodic, nrppa_pos_aperiodic); + nrppa_pos_aperiodic->slotOffset = resource_type_pos->choice.aperiodic.slot_offset; + } else { + AssertFatal(false, "illegal resourceType %d\n", resource_type_pos->present); + } + + nrppa_pos_srs_resource->sequenceId = pos_srs_resource->sequence_id; + } + } + + // optional: srs_resource_set_list + if (in_config->srs_resource_set_list) { + nrppa_srs_resource_set_list_t *srs_resource_set_list = in_config->srs_resource_set_list; + uint32_t srs_resource_set_list_length = srs_resource_set_list->srs_resource_set_list_length; + asn1cCalloc(out_config.sRSResourceSet_List, nrppa_sRSResourceSet_List); + for (int i = 0; i < srs_resource_set_list_length; i++) { + asn1cSequenceAdd(nrppa_sRSResourceSet_List->list, NRPPA_SRSResourceSet_t, nrppa_srs_resource_set); + nrppa_srs_resource_set_t *srs_resource_set = &srs_resource_set_list->srs_resource_set[i]; + nrppa_srs_resource_set->sRSResourceSetID = srs_resource_set->srs_resource_set_id; + uint8_t srs_resource_id_list_length = srs_resource_set->srs_resource_id_list.srs_resource_id_list_length; + for (int j = 0; j < srs_resource_id_list_length; j++) { + asn1cSequenceAdd(nrppa_srs_resource_set->sRSResourceID_List.list, NRPPA_SRSResourceID_t, nrppa_srs_resource_id); + *nrppa_srs_resource_id = srs_resource_set->srs_resource_id_list.srs_resource_id[j]; + } + + NRPPA_ResourceSetType_t *nrppa_resourceSetType = &nrppa_srs_resource_set->resourceSetType; + nrppa_resource_set_type_t *resource_set_type = &srs_resource_set->resource_set_type; + switch (resource_set_type->present) { + case NRPPA_RESOURCE_SET_TYPE_PR_NOTHING: + nrppa_resourceSetType->present = NRPPA_ResourceSetType_PR_NOTHING; + break; + case NRPPA_RESOURCE_SET_TYPE_PR_PERIODIC: + nrppa_resourceSetType->present = NRPPA_ResourceSetType_PR_periodic; + asn1cCalloc(nrppa_resourceSetType->choice.periodic, nrppa_periodic_set_type); + nrppa_periodic_set_type->periodicSet = resource_set_type->choice.periodic; + break; + case NRPPA_RESOURCE_SET_TYPE_PR_SEMI_PERSISTENT: + nrppa_resourceSetType->present = NRPPA_ResourceSetType_PR_semi_persistent; + asn1cCalloc(nrppa_resourceSetType->choice.semi_persistent, nrppa_semi_persistent_set_type); + nrppa_semi_persistent_set_type->semi_persistentSet = resource_set_type->choice.semi_persistent; + break; + case NRPPA_RESOURCE_SET_TYPE_PR_APERIODIC: + nrppa_resourceSetType->present = NRPPA_ResourceSetType_PR_aperiodic; + asn1cCalloc(nrppa_resourceSetType->choice.aperiodic, nrppa_aperiodic_set_type); + nrppa_aperiodic_set_type->sRSResourceTrigger = resource_set_type->choice.aperiodic.srs_resource_trigger; + nrppa_aperiodic_set_type->slotoffset = resource_set_type->choice.aperiodic.slot_offset; + break; + default: + AssertFatal(false, "illegal resource set type %d\n", resource_set_type->present); + break; + } + } + } + + // optional: pos_srs_resource_set_list + if (in_config->pos_srs_resource_set_list) { + nrppa_pos_srs_resource_set_list_t *pos_srs_resource_set_list = in_config->pos_srs_resource_set_list; + uint32_t pos_srs_resource_set_list_length = pos_srs_resource_set_list->pos_srs_resource_set_list_length; + asn1cCalloc(out_config.posSRSResourceSet_List, nrppa_posSRSResourceSet_List); + for (int i = 0; i < pos_srs_resource_set_list_length; i++) { + asn1cSequenceAdd(nrppa_posSRSResourceSet_List->list, NRPPA_PosSRSResourceSet_Item_t, nrppa_pos_srs_resource_set); + nrppa_pos_srs_resource_set_item_t *pos_srs_resource_set = &pos_srs_resource_set_list->pos_srs_resource_set_item[i]; + nrppa_pos_srs_resource_set->possrsResourceSetID = pos_srs_resource_set->pos_srs_resource_set_id; + uint8_t pos_srs_resource_id_list_length = pos_srs_resource_set->pos_srs_resource_id_list.pos_srs_resource_id_list_length; + for (int j = 0; j < pos_srs_resource_id_list_length; j++) { + asn1cSequenceAdd(nrppa_pos_srs_resource_set->possRSResourceID_List.list, + NRPPA_SRSPosResourceID_t, + nrppa_pos_srs_resource_id); + *nrppa_pos_srs_resource_id = pos_srs_resource_set->pos_srs_resource_id_list.srs_pos_resource_id[j]; + } + + NRPPA_PosResourceSetType_t *nrppa_posresourceSetType = &nrppa_pos_srs_resource_set->posresourceSetType; + nrppa_pos_resource_set_type_t *pos_resource_set_type = &pos_srs_resource_set->pos_resource_set_type; + switch (pos_resource_set_type->present) { + case NRPPA_POS_RESOURCE_SET_TYPE_PR_NOTHING: + nrppa_posresourceSetType->present = NRPPA_PosResourceSetType_PR_NOTHING; + break; + case NRPPA_POS_RESOURCE_SET_TYPE_PR_PERIODIC: + nrppa_posresourceSetType->present = NRPPA_PosResourceSetType_PR_periodic; + asn1cCalloc(nrppa_posresourceSetType->choice.periodic, nrppa_pos_periodic_set_type); + nrppa_pos_periodic_set_type->posperiodicSet = pos_resource_set_type->choice.periodic; + break; + case NRPPA_POS_RESOURCE_SET_TYPE_PR_SEMI_PERSISTENT: + nrppa_posresourceSetType->present = NRPPA_PosResourceSetType_PR_semi_persistent; + asn1cCalloc(nrppa_posresourceSetType->choice.semi_persistent, nrppa_pos_semi_persistent_set_type); + nrppa_pos_semi_persistent_set_type->possemi_persistentSet = pos_resource_set_type->choice.semi_persistent; + break; + case NRPPA_POS_RESOURCE_SET_TYPE_PR_APERIODIC: + nrppa_posresourceSetType->present = NRPPA_PosResourceSetType_PR_aperiodic; + asn1cCalloc(nrppa_posresourceSetType->choice.aperiodic, nrppa_pos_aperiodic_set_type); + nrppa_pos_aperiodic_set_type->sRSResourceTrigger = pos_resource_set_type->choice.srs_resource; + break; + default: + AssertFatal(false, "illegal resource set type pos %d\n", pos_resource_set_type->present); + break; + } + } + } + return out_config; +} + +static NRPPA_SRSCarrier_List_Item_t encode_srs_carrier_list_item(const nrppa_srs_carrier_list_item_t *in_item) +{ + NRPPA_SRSCarrier_List_Item_t out_item = {0}; + // pointA + out_item.pointA = in_item->pointA; + + // Uplink Channel BW-PerSCS-List + const nrppa_uplink_channel_bw_per_scs_list_t *uplink_channel_bw_per_scs_list = &in_item->uplink_channel_bw_per_scs_list; + NRPPA_UplinkChannelBW_PerSCS_List_t *nrppa_uplink_channel_bw_per_scs_list = &out_item.uplinkChannelBW_PerSCS_List; + + uint32_t scs_specific_carrier_list_length = uplink_channel_bw_per_scs_list->scs_specific_carrier_list_length; + for (int i = 0; i < scs_specific_carrier_list_length; i++) { + asn1cSequenceAdd(nrppa_uplink_channel_bw_per_scs_list->list, NRPPA_SCS_SpecificCarrier_t, nrppa_scs_specific_carrier); + nrppa_scs_specific_carrier_t *scs_specific_carrier = &uplink_channel_bw_per_scs_list->scs_specific_carrier[i]; + // offset to carrier + nrppa_scs_specific_carrier->offsetToCarrier = scs_specific_carrier->offset_to_carrier; + // subcarrier spacing + switch (scs_specific_carrier->subcarrier_spacing) { + case NRPPA_SUBCARRIER_SPACING_15KHZ: + nrppa_scs_specific_carrier->subcarrierSpacing = NRPPA_SCS_SpecificCarrier__subcarrierSpacing_kHz15; + break; + case NRPPA_SUBCARRIER_SPACING_30KHZ: + nrppa_scs_specific_carrier->subcarrierSpacing = NRPPA_SCS_SpecificCarrier__subcarrierSpacing_kHz30; + break; + case NRPPA_SUBCARRIER_SPACING_60KHZ: + nrppa_scs_specific_carrier->subcarrierSpacing = NRPPA_SCS_SpecificCarrier__subcarrierSpacing_kHz60; + break; + case NRPPA_SUBCARRIER_SPACING_120KHZ: + nrppa_scs_specific_carrier->subcarrierSpacing = NRPPA_SCS_SpecificCarrier__subcarrierSpacing_kHz120; + break; + default: + AssertFatal(false, "illegal subcarrier spacing %d\n", scs_specific_carrier->subcarrier_spacing); + break; + } + // carrier bandwidth + nrppa_scs_specific_carrier->carrierBandwidth = scs_specific_carrier->carrier_bandwidth; + } + + // Active UL BWP + NRPPA_ActiveULBWP_t *nrppa_active_ul_bwp = &out_item.activeULBWP; + const nrppa_active_ul_bwp_t *active_ul_bwp = &in_item->active_ul_bwp; + + // location and bandwidth + nrppa_active_ul_bwp->locationAndBandwidth = active_ul_bwp->location_and_bandwidth; + // subcarrier spacing + switch (active_ul_bwp->subcarrier_spacing) { + case NRPPA_SUBCARRIER_SPACING_15KHZ: + nrppa_active_ul_bwp->subcarrierSpacing = NRPPA_ActiveULBWP__subcarrierSpacing_kHz15; + break; + case NRPPA_SUBCARRIER_SPACING_30KHZ: + nrppa_active_ul_bwp->subcarrierSpacing = NRPPA_ActiveULBWP__subcarrierSpacing_kHz30; + break; + case NRPPA_SUBCARRIER_SPACING_60KHZ: + nrppa_active_ul_bwp->subcarrierSpacing = NRPPA_ActiveULBWP__subcarrierSpacing_kHz60; + break; + case NRPPA_SUBCARRIER_SPACING_120KHZ: + nrppa_active_ul_bwp->subcarrierSpacing = NRPPA_ActiveULBWP__subcarrierSpacing_kHz120; + break; + default: + AssertFatal(false, "illegal subcarrier spacing %d\n", active_ul_bwp->subcarrier_spacing); + break; + } + + // cyclic prefix + if (active_ul_bwp->cyclic_prefix == NRPPA_CP_TYPE_NORMAL) + nrppa_active_ul_bwp->cyclicPrefix = NRPPA_ActiveULBWP__cyclicPrefix_normal; + else + nrppa_active_ul_bwp->cyclicPrefix = NRPPA_ActiveULBWP__cyclicPrefix_extended; + + // Tx Direct Current Location + nrppa_active_ul_bwp->txDirectCurrentLocation = active_ul_bwp->tx_direct_current_location; + + // SRS Config + const nrppa_srs_config_t *sRSConfig = &active_ul_bwp->srs_config; + nrppa_active_ul_bwp->sRSConfig = encode_srs_config(sRSConfig); + return out_item; +} + +NRPPA_SRSCarrier_List_t encode_srs_carrier_list_nrppa(const nrppa_srs_carrier_list_t *in_list) +{ + NRPPA_SRSCarrier_List_t out_list = {0}; + uint32_t list_len = in_list->srs_carrier_list_length; + for (int i = 0; i < list_len; i++) { + asn1cSequenceAdd(out_list.list, NRPPA_SRSCarrier_List_Item_t, out_item); + nrppa_srs_carrier_list_item_t *in_item = &in_list->srs_carrier_list_item[i]; + *out_item = encode_srs_carrier_list_item(in_item); + } + return out_list; +} + +static void free_srs_carrier_list(nrppa_srs_carrier_list_t *srs_carrier_list) +{ + uint32_t srs_carrier_list_len = srs_carrier_list->srs_carrier_list_length; + for (int i = 0; i < srs_carrier_list_len; i++) { + nrppa_srs_carrier_list_item_t *srs_carrier_list_item = &srs_carrier_list->srs_carrier_list_item[i]; + free(srs_carrier_list_item->uplink_channel_bw_per_scs_list.scs_specific_carrier); + + nrppa_active_ul_bwp_t *active_ul_bwp = &srs_carrier_list_item->active_ul_bwp; + nrppa_srs_config_t *sRSConfig = &active_ul_bwp->srs_config; + if (sRSConfig->srs_resource_list) { + nrppa_srs_resource_list_t *srs_resource_list = sRSConfig->srs_resource_list; + free(srs_resource_list->srs_resource); + free(sRSConfig->srs_resource_list); + } + if (sRSConfig->pos_srs_resource_list) { + nrppa_pos_srs_resource_list_t *pos_srs_resource_list = sRSConfig->pos_srs_resource_list; + free(pos_srs_resource_list->pos_srs_resource_item); + free(sRSConfig->pos_srs_resource_list); + } + if (sRSConfig->srs_resource_set_list) { + nrppa_srs_resource_set_list_t *srs_resource_set_list = sRSConfig->srs_resource_set_list; + uint32_t srs_resource_set_list_length = srs_resource_set_list->srs_resource_set_list_length; + for (int j = 0; j < srs_resource_set_list_length; j++) { + nrppa_srs_resource_set_t *srs_resource_set = &srs_resource_set_list->srs_resource_set[j]; + free(srs_resource_set->srs_resource_id_list.srs_resource_id); + } + free(srs_resource_set_list->srs_resource_set); + free(sRSConfig->srs_resource_set_list); + } + if (sRSConfig->pos_srs_resource_set_list) { + nrppa_pos_srs_resource_set_list_t *pos_srs_resource_set_list = sRSConfig->pos_srs_resource_set_list; + uint32_t pos_srs_resource_set_list_length = pos_srs_resource_set_list->pos_srs_resource_set_list_length; + for (int j = 0; j < pos_srs_resource_set_list_length; j++) { + nrppa_pos_srs_resource_set_item_t *pos_srs_resource_set = &pos_srs_resource_set_list->pos_srs_resource_set_item[j]; + free(pos_srs_resource_set->pos_srs_resource_id_list.srs_pos_resource_id); + } + free(pos_srs_resource_set_list->pos_srs_resource_set_item); + free(sRSConfig->pos_srs_resource_set_list); + } + } + free(srs_carrier_list->srs_carrier_list_item); +} + +void free_positioning_information_response(nrppa_positioning_information_resp_t *msg) +{ + /* SRS Configuration (O) */ + if (msg->srs_configuration) { + nrppa_srs_carrier_list_t *srs_carrier_list = &msg->srs_configuration->srs_carrier_list; + free_srs_carrier_list(srs_carrier_list); + free(msg->srs_configuration); + } +} + int nrppa_gNB_handle_trp_information_request(nrppa_gnb_ue_info_t *nrppa_msg_info, const NRPPA_NRPPA_PDU_t *pdu) { LOG_I(NRPPA, "Processing Received TRP Information Request \n"); @@ -442,3 +1164,83 @@ int nrppa_gNB_handle_positioning_information_request(nrppa_gnb_ue_info_t *nrppa_ ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NRPPA_NRPPA_PDU, &pdu); return 0; } + +int nrppa_gNB_positioning_information_response(instance_t instance, MessageDef *msg_p) +{ + DevAssert(msg_p); + nrppa_positioning_information_resp_t *resp = &NRPPA_POSITIONING_INFORMATION_RESP(msg_p); + nrppa_gNB_ue_context_t *ue_info = nrppa_detach_ue_context(resp->transaction_id); + + if (ue_info->gNB_ue_ngap_id <= 0 && ue_info->amf_ue_ngap_id <= 0) { + LOG_E(NRPPA, "Illegal gNB_ue_ngap_id %d and amf_ue_ngap_id %ld\n", ue_info->gNB_ue_ngap_id, ue_info->amf_ue_ngap_id); + free_positioning_information_response(resp); + nrppa_free_ue_context(ue_info); + return -1; + } + + LOG_I(NRPPA, + "Received Positioning Information Response info from RRC with transaction_id = %u and gNB_ue_ngap_id %u\n", + ue_info->transaction_id, + ue_info->gNB_ue_ngap_id); + + // Prepare NRPPA TRP Information transfer Response + NRPPA_NRPPA_PDU_t pdu = {0}; + + // IE: 9.2.3 Message Type : mandatory + pdu.present = NRPPA_NRPPA_PDU_PR_successfulOutcome; + asn1cCalloc(pdu.choice.successfulOutcome, head); + head->procedureCode = NRPPA_ProcedureCode_id_positioningInformationExchange; + head->criticality = NRPPA_Criticality_reject; + head->value.present = NRPPA_SuccessfulOutcome__value_PR_PositioningInformationResponse; + + // IE 9.2.4 nrppatransactionID : mandatory + head->nrppatransactionID = resp->transaction_id; + NRPPA_PositioningInformationResponse_t *out = &head->value.choice.PositioningInformationResponse; + + // IE SRS Configuration : optional + { + if (resp->srs_configuration) { + asn1cSequenceAdd(out->protocolIEs.list, NRPPA_PositioningInformationResponse_IEs_t, ie); + ie->id = NRPPA_ProtocolIE_ID_id_SRSConfiguration; + ie->criticality = NRPPA_Criticality_ignore; + ie->value.present = NRPPA_PositioningInformationResponse_IEs__value_PR_SRSConfiguration; + nrppa_srs_carrier_list_t *srs_carrier_list = &resp->srs_configuration->srs_carrier_list; + ie->value.choice.SRSConfiguration.sRSCarrier_List = encode_srs_carrier_list_nrppa(srs_carrier_list); + } + } + + free_positioning_information_response(resp); + + LOG_I(NRPPA, "Calling encoder for Positioning Information Response \n"); + + if (LOG_DEBUGFLAG(DEBUG_ASN1)) { + xer_fprint(stdout, &asn_DEF_NRPPA_NRPPA_PDU, &pdu); + } + + // Encode NRPPA message + uint8_t *buffer = NULL; + uint32_t length = 0; + if (nrppa_gNB_encode_pdu(&pdu, &buffer, &length) < 0) { + LOG_E(NRPPA, "Failed to encode Uplink NRPPa PositioningInformationResponse\n"); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NRPPA_NRPPA_PDU, &pdu); + return -1; + } + + MessageDef *msg = itti_alloc_new_message(TASK_NRPPA, 0, NGAP_UPLINKUEASSOCIATEDNRPPA); + ngap_uplink_ue_associated_nrppa_t *ULNRPPA = &NGAP_UPLINKUEASSOCIATEDNRPPA(msg); + + ULNRPPA->gNB_ue_ngap_id = ue_info->gNB_ue_ngap_id; + ULNRPPA->amf_ue_ngap_id = ue_info->amf_ue_ngap_id; + + // Routing ID + ULNRPPA->routing_id = create_byte_array(ue_info->routing_id.len, ue_info->routing_id.buf); + + // NRPPA PDU + ULNRPPA->nrppa_pdu = create_byte_array(length, buffer); + + // Forward the NRPPA PDU to NGAP + itti_send_msg_to_task(TASK_NGAP, instance, msg); + nrppa_free_ue_context(ue_info); + free(buffer); + return length; +} diff --git a/openair3/NRPPA/nrppa_gNB_location_information_transfer.h b/openair3/NRPPA/nrppa_gNB_location_information_transfer.h index 5fbd697c07..31ab194345 100644 --- a/openair3/NRPPA/nrppa_gNB_location_information_transfer.h +++ b/openair3/NRPPA/nrppa_gNB_location_information_transfer.h @@ -29,5 +29,8 @@ void free_trp_information_request(nrppa_trp_information_req_t *msg); NRPPA_TRPInformationItem_t encode_trp_info_type_response_item_nrppa(nrppa_trp_information_type_response_item_t *in); void free_trp_information_response(nrppa_trp_information_resp_t *msg); int nrppa_gNB_handle_positioning_information_request(nrppa_gnb_ue_info_t *nrppa_msg_info, const NRPPA_NRPPA_PDU_t *pdu); +int nrppa_gNB_positioning_information_response(instance_t instance, MessageDef *msg_p); +NRPPA_SRSCarrier_List_t encode_srs_carrier_list_nrppa(const nrppa_srs_carrier_list_t *in_list); +void free_positioning_information_response(nrppa_positioning_information_resp_t *msg); #endif /* NRPPA_GNB_POSITIONING_PROCEDURES_H_ */ diff --git a/openair3/NRPPA/nrppa_includes.h b/openair3/NRPPA/nrppa_includes.h index 63bb3fe248..6915b93370 100644 --- a/openair3/NRPPA/nrppa_includes.h +++ b/openair3/NRPPA/nrppa_includes.h @@ -42,5 +42,32 @@ #include "NRPPA_TRPPositionReferenced.h" #include "NRPPA_RelativeGeodeticLocation.h" #include "NRPPA_RelativeCartesianLocation.h" +#include "NRPPA_SRSCarrier-List-Item.h" +#include "NRPPA_SCS-SpecificCarrier.h" +#include "NRPPA_SRSConfig.h" +#include "NRPPA_SRSResource-List.h" +#include "NRPPA_SRSResource.h" +#include "NRPPA_ResourceType.h" +#include "NRPPA_ResourceTypePeriodic.h" +#include "NRPPA_ResourceTypeSemi-persistent.h" +#include "NRPPA_ResourceTypeAperiodic.h" +#include "NRPPA_PosSRSResource-List.h" +#include "NRPPA_ResourceTypePos.h" +#include "NRPPA_ResourceTypePeriodicPos.h" +#include "NRPPA_ResourceTypeSemi-persistentPos.h" +#include "NRPPA_ResourceTypeAperiodicPos.h" +#include "NRPPA_SRSResourceSet-List.h" +#include "NRPPA_SRSResourceSet.h" +#include "NRPPA_PosSRSResource-List.h" +#include "NRPPA_PosSRSResourceSet-Item.h" +#include "NRPPA_PosSRSResource-List.h" +#include "NRPPA_PosSRSResource-Item.h" +#include "NRPPA_ResourceSetTypePeriodic.h" +#include "NRPPA_ResourceSetTypeSemi-persistent.h" +#include "NRPPA_ResourceSetTypeAperiodic.h" +#include "NRPPA_PosSRSResourceSet-List.h" +#include "NRPPA_PosResourceSetTypePeriodic.h" +#include "NRPPA_PosResourceSetTypeSemi-persistent.h" +#include "NRPPA_PosResourceSetTypeAperiodic.h" #endif /* NRPPA_INCLUDE_H_ */ diff --git a/tests/nr-cu-nrppa/nr-cu-nrppa.c b/tests/nr-cu-nrppa/nr-cu-nrppa.c index aad8855797..ca47199133 100644 --- a/tests/nr-cu-nrppa/nr-cu-nrppa.c +++ b/tests/nr-cu-nrppa/nr-cu-nrppa.c @@ -148,6 +148,289 @@ static nrppa_trp_information_resp_t fill_trp_resp(uint8_t transaction_id) return resp; } +static nrppa_positioning_information_resp_t fill_position_information_resp(uint16_t transaction_id) +{ + nrppa_positioning_information_resp_t resp = {0}; + resp.transaction_id = transaction_id; + resp.srs_configuration = calloc_or_fail(1, sizeof(*resp.srs_configuration)); + nrppa_srs_carrier_list_t *srs_carrier_list = &resp.srs_configuration->srs_carrier_list; + uint32_t srs_carrier_list_len = 2; + srs_carrier_list->srs_carrier_list_length = srs_carrier_list_len; + srs_carrier_list->srs_carrier_list_item = calloc_or_fail(srs_carrier_list_len, sizeof(*srs_carrier_list->srs_carrier_list_item)); + for (int i = 0; i < srs_carrier_list_len; i++) { + nrppa_srs_carrier_list_item_t *srs_carrier_list_item = &srs_carrier_list->srs_carrier_list_item[i]; + // pointA + srs_carrier_list_item->pointA = 87641 + i; + + // Uplink Channel BW-PerSCS-List + nrppa_uplink_channel_bw_per_scs_list_t *uplink_channel_bw_per_scs_list = &srs_carrier_list_item->uplink_channel_bw_per_scs_list; + + uint32_t scs_specific_carrier_list_length = 3; + uplink_channel_bw_per_scs_list->scs_specific_carrier_list_length = scs_specific_carrier_list_length; + uplink_channel_bw_per_scs_list->scs_specific_carrier = + calloc_or_fail(scs_specific_carrier_list_length, sizeof(*uplink_channel_bw_per_scs_list->scs_specific_carrier)); + for (int j = 0; j < scs_specific_carrier_list_length; j++) { + nrppa_scs_specific_carrier_t *scs_specific_carrier = &uplink_channel_bw_per_scs_list->scs_specific_carrier[j]; + // offset to carrier + scs_specific_carrier->offset_to_carrier = 100 + i + j; + // subcarrier spacing + scs_specific_carrier->subcarrier_spacing = NRPPA_SUBCARRIER_SPACING_30KHZ; + // carrier bandwidth + scs_specific_carrier->carrier_bandwidth = 106 + i + j; + } + + // Active UL BWP + nrppa_active_ul_bwp_t *active_ul_bwp = &srs_carrier_list_item->active_ul_bwp; + + // location and bandwidth + active_ul_bwp->location_and_bandwidth = 2775 + i; + // subcarrier spacing + active_ul_bwp->subcarrier_spacing = NRPPA_SUBCARRIER_SPACING_30KHZ; + // cyclic prefix + active_ul_bwp->cyclic_prefix = NRPPA_CP_TYPE_NORMAL; + // Tx Direct Current Location + active_ul_bwp->tx_direct_current_location = 10 + i; + + // SRS Config + nrppa_srs_config_t *sRSConfig = &active_ul_bwp->srs_config; + + // srs_resource_list + sRSConfig->srs_resource_list = calloc_or_fail(1, sizeof(*sRSConfig->srs_resource_list)); + nrppa_srs_resource_list_t *srs_resource_list = sRSConfig->srs_resource_list; + uint32_t srs_resource_list_length = 3; + srs_resource_list->srs_resource_list_length = srs_resource_list_length; + srs_resource_list->srs_resource = calloc_or_fail(srs_resource_list_length, sizeof(*srs_resource_list->srs_resource)); + + // SRS resource config 1 : periodic + nrppa_srs_resource_t *srs_resource = &srs_resource_list->srs_resource[0]; + srs_resource->srs_resource_id = 22; + srs_resource->nr_of_srs_ports = NRPPA_SRS_NUMBER_OF_PORTS_N2; + srs_resource->transmission_comb.present = NRPPA_TRANSMISSION_COMB_PR_N2; + srs_resource->transmission_comb.choice.n2.comb_offset_n2 = 1; + srs_resource->transmission_comb.choice.n2.cyclic_shift_n2 = 3; + srs_resource->start_position = 8; + srs_resource->nr_of_symbols = NRPPA_SRS_NUMBER_OF_SYMBOLS_N4; + srs_resource->repetition_factor = NRPPA_SRS_REPETITION_FACTOR_RF2; + srs_resource->freq_domain_position = 32; + srs_resource->freq_domain_shift = 108; + srs_resource->c_srs = 31; + srs_resource->b_srs = 1; + srs_resource->b_hop = 3; + srs_resource->group_or_sequence_hopping = NRPPA_GROUPORSEQUENCEHOPPING_GROUPHOPPING; + srs_resource->resource_type.present = NRPPA_RESOURCE_TYPE_PR_PERIODIC; + + nrppa_resource_type_periodic_t *periodic = &srs_resource->resource_type.choice.periodic; + periodic->periodicity = NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT16; + periodic->offset = 1000; + srs_resource->sequence_id = 18; + + // SRS resource config 2 : semi-persistent + srs_resource = &srs_resource_list->srs_resource[1]; + srs_resource->srs_resource_id = 24; + srs_resource->nr_of_srs_ports = NRPPA_SRS_NUMBER_OF_PORTS_N4; + srs_resource->transmission_comb.present = NRPPA_TRANSMISSION_COMB_PR_N4; + srs_resource->transmission_comb.choice.n2.comb_offset_n2 = 3; + srs_resource->transmission_comb.choice.n2.cyclic_shift_n2 = 5; + srs_resource->start_position = 8; + srs_resource->nr_of_symbols = NRPPA_SRS_NUMBER_OF_SYMBOLS_N2; + srs_resource->repetition_factor = NRPPA_SRS_REPETITION_FACTOR_RF2; + srs_resource->freq_domain_position = 32; + srs_resource->freq_domain_shift = 108; + srs_resource->c_srs = 31; + srs_resource->b_srs = 1; + srs_resource->b_hop = 3; + srs_resource->group_or_sequence_hopping = NRPPA_GROUPORSEQUENCEHOPPING_GROUPHOPPING; + srs_resource->resource_type.present = NRPPA_RESOURCE_TYPE_PR_SEMI_PERSISTENT; + + srs_resource->resource_type.present = NRPPA_RESOURCE_TYPE_PR_SEMI_PERSISTENT; + nrppa_resource_type_semi_persistent_t *semi_persistent = &srs_resource->resource_type.choice.semi_persistent; + semi_persistent->periodicity = NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT40; + semi_persistent->offset = 1000; + srs_resource->sequence_id = 12; + + // SRS resource config 2 : aperiodic + srs_resource = &srs_resource_list->srs_resource[2]; + srs_resource->srs_resource_id = 26; + srs_resource->nr_of_srs_ports = NRPPA_SRS_NUMBER_OF_PORTS_N2; + srs_resource->transmission_comb.present = NRPPA_TRANSMISSION_COMB_PR_N2; + srs_resource->transmission_comb.choice.n2.comb_offset_n2 = 1; + srs_resource->transmission_comb.choice.n2.cyclic_shift_n2 = 3; + srs_resource->start_position = 8; + srs_resource->nr_of_symbols = NRPPA_SRS_NUMBER_OF_SYMBOLS_N4; + srs_resource->repetition_factor = NRPPA_SRS_REPETITION_FACTOR_RF2; + srs_resource->freq_domain_position = 32; + srs_resource->freq_domain_shift = 108; + srs_resource->c_srs = 31; + srs_resource->b_srs = 1; + srs_resource->b_hop = 3; + srs_resource->group_or_sequence_hopping = NRPPA_GROUPORSEQUENCEHOPPING_SEQUENCEHOPPING; + srs_resource->resource_type.present = NRPPA_RESOURCE_TYPE_PR_APERIODIC; + // set aperiodic = 0 to enable + srs_resource->resource_type.choice.aperiodic = 0; + srs_resource->sequence_id = 10; + + // optional: pos_srs_resource_list + sRSConfig->pos_srs_resource_list = calloc_or_fail(1, sizeof(*sRSConfig->pos_srs_resource_list)); + nrppa_pos_srs_resource_list_t *pos_srs_resource_list = sRSConfig->pos_srs_resource_list; + uint32_t pos_srs_resource_list_length = 3; + pos_srs_resource_list->pos_srs_resource_list_length = pos_srs_resource_list_length; + pos_srs_resource_list->pos_srs_resource_item = + calloc_or_fail(pos_srs_resource_list_length, sizeof(*pos_srs_resource_list->pos_srs_resource_item)); + + // periodic + nrppa_pos_srs_resource_item_t *pos_srs_resource = &pos_srs_resource_list->pos_srs_resource_item[0]; + pos_srs_resource->srs_pos_resource_id = 12; + pos_srs_resource->transmission_comb_pos.present = NRPPA_TRANSMISSION_COMB_POS_PR_N2; + pos_srs_resource->transmission_comb_pos.choice.n2.comb_offset_n2 = 1; + pos_srs_resource->transmission_comb_pos.choice.n2.cyclic_shift_n2 = 4; + pos_srs_resource->start_position = 9; + pos_srs_resource->nr_of_symbols = NRPPA_SRS_RESOURCE_ITEM_NUMBER_OF_SYMBOLS_N8; + pos_srs_resource->freq_domain_shift = 100; + pos_srs_resource->c_srs = 20; + pos_srs_resource->group_or_sequence_hopping = NRPPA_GROUPORSEQUENCEHOPPING_GROUPHOPPING; + pos_srs_resource->resource_type_pos.present = NRPPA_RESOURCE_TYPE_POS_PR_PERIODIC; + pos_srs_resource->resource_type_pos.choice.periodic.periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT5; + pos_srs_resource->resource_type_pos.choice.periodic.offset = 10; + pos_srs_resource->sequence_id = 1; + + // semi-persistent + pos_srs_resource = &pos_srs_resource_list->pos_srs_resource_item[1]; + pos_srs_resource->srs_pos_resource_id = 13; + pos_srs_resource->transmission_comb_pos.present = NRPPA_TRANSMISSION_COMB_POS_PR_N4; + pos_srs_resource->transmission_comb_pos.choice.n4.comb_offset_n4 = 3; + pos_srs_resource->transmission_comb_pos.choice.n4.cyclic_shift_n4 = 5; + pos_srs_resource->start_position = 12; + pos_srs_resource->nr_of_symbols = NRPPA_SRS_RESOURCE_ITEM_NUMBER_OF_SYMBOLS_N12; + pos_srs_resource->freq_domain_shift = 100; + pos_srs_resource->c_srs = 20; + pos_srs_resource->group_or_sequence_hopping = NRPPA_GROUPORSEQUENCEHOPPING_GROUPHOPPING; + pos_srs_resource->resource_type_pos.present = NRPPA_RESOURCE_TYPE_POS_PR_SEMI_PERSISTENT; + pos_srs_resource->resource_type_pos.choice.semi_persistent.periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT32; + pos_srs_resource->resource_type_pos.choice.semi_persistent.offset = 5; + pos_srs_resource->sequence_id = 2; + + // aperiodic + pos_srs_resource = &pos_srs_resource_list->pos_srs_resource_item[2]; + pos_srs_resource->srs_pos_resource_id = 14; + pos_srs_resource->transmission_comb_pos.present = NRPPA_TRANSMISSION_COMB_POS_PR_N8; + pos_srs_resource->transmission_comb_pos.choice.n8.comb_offset_n8 = 5; + pos_srs_resource->transmission_comb_pos.choice.n8.cyclic_shift_n8 = 2; + pos_srs_resource->start_position = 9; + pos_srs_resource->nr_of_symbols = NRPPA_SRS_RESOURCE_ITEM_NUMBER_OF_SYMBOLS_N4; + pos_srs_resource->freq_domain_shift = 100; + pos_srs_resource->c_srs = 20; + pos_srs_resource->group_or_sequence_hopping = NRPPA_GROUPORSEQUENCEHOPPING_SEQUENCEHOPPING; + pos_srs_resource->resource_type_pos.present = NRPPA_RESOURCE_TYPE_POS_PR_APERIODIC; + pos_srs_resource->resource_type_pos.choice.periodic.periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT5; + pos_srs_resource->resource_type_pos.choice.aperiodic.slot_offset = 31; + pos_srs_resource->sequence_id = 3; + + // optional: srs_resource_set_list + sRSConfig->srs_resource_set_list = calloc_or_fail(1, sizeof(*sRSConfig->srs_resource_set_list)); + nrppa_srs_resource_set_list_t *srs_resource_set_list = sRSConfig->srs_resource_set_list; + uint32_t srs_resource_set_list_length = 3; + srs_resource_set_list->srs_resource_set_list_length = srs_resource_set_list_length; + srs_resource_set_list->srs_resource_set = + calloc_or_fail(srs_resource_set_list_length, sizeof(*srs_resource_set_list->srs_resource_set)); + + // periodic + nrppa_srs_resource_set_t *srs_resource_set = &srs_resource_set_list->srs_resource_set[0]; + srs_resource_set->srs_resource_set_id = 0; + uint8_t srs_resource_id_list_length = 5; + srs_resource_set->srs_resource_id_list.srs_resource_id_list_length = srs_resource_id_list_length; + srs_resource_set->srs_resource_id_list.srs_resource_id = + calloc_or_fail(srs_resource_id_list_length, sizeof(*srs_resource_set->srs_resource_id_list.srs_resource_id)); + for (int k = 0; k < srs_resource_id_list_length; k++) { + srs_resource_set->srs_resource_id_list.srs_resource_id[k] = k; + } + srs_resource_set->resource_set_type.present = NRPPA_RESOURCE_SET_TYPE_PR_PERIODIC; + // set periodic = 0 to enable + srs_resource_set->resource_set_type.choice.periodic = 0; + + // semi-persistent + srs_resource_set = &srs_resource_set_list->srs_resource_set[1]; + srs_resource_set->srs_resource_set_id = 1; + srs_resource_id_list_length = 5; + srs_resource_set->srs_resource_id_list.srs_resource_id_list_length = srs_resource_id_list_length; + srs_resource_set->srs_resource_id_list.srs_resource_id = + calloc_or_fail(srs_resource_id_list_length, sizeof(srs_resource_set->srs_resource_id_list.srs_resource_id)); + for (int k = 0; k < srs_resource_id_list_length; k++) { + srs_resource_set->srs_resource_id_list.srs_resource_id[k] = k; + } + srs_resource_set->resource_set_type.present = NRPPA_RESOURCE_SET_TYPE_PR_SEMI_PERSISTENT; + // set semi_persistent = 0 to enable + srs_resource_set->resource_set_type.choice.semi_persistent = 0; + + // aperiodic + srs_resource_set = &srs_resource_set_list->srs_resource_set[2]; + srs_resource_set->srs_resource_set_id = 2; + srs_resource_id_list_length = 5; + srs_resource_set->srs_resource_id_list.srs_resource_id_list_length = srs_resource_id_list_length; + srs_resource_set->srs_resource_id_list.srs_resource_id = + calloc_or_fail(srs_resource_id_list_length, sizeof(*srs_resource_set->srs_resource_id_list.srs_resource_id)); + for (int k = 0; k < srs_resource_id_list_length; k++) { + srs_resource_set->srs_resource_id_list.srs_resource_id[k] = k; + } + + srs_resource_set->resource_set_type.present = NRPPA_RESOURCE_SET_TYPE_PR_APERIODIC; + srs_resource_set->resource_set_type.choice.aperiodic.srs_resource_trigger = 2; + srs_resource_set->resource_set_type.choice.aperiodic.slot_offset = 20; + + // optional: pos_srs_resource_set_list + sRSConfig->pos_srs_resource_set_list = calloc_or_fail(1, sizeof(*sRSConfig->pos_srs_resource_set_list)); + nrppa_pos_srs_resource_set_list_t *pos_srs_resource_set_list = sRSConfig->pos_srs_resource_set_list; + uint32_t pos_srs_resource_set_list_length = 3; + pos_srs_resource_set_list->pos_srs_resource_set_list_length = pos_srs_resource_set_list_length; + pos_srs_resource_set_list->pos_srs_resource_set_item = + calloc_or_fail(pos_srs_resource_set_list_length, sizeof(*pos_srs_resource_set_list->pos_srs_resource_set_item)); + + // periodic + nrppa_pos_srs_resource_set_item_t *pos_srs_resource_set = &pos_srs_resource_set_list->pos_srs_resource_set_item[0]; + pos_srs_resource_set->pos_srs_resource_set_id = 0; + uint8_t pos_srs_resource_id_list_length = 5; + pos_srs_resource_set->pos_srs_resource_id_list.pos_srs_resource_id_list_length = pos_srs_resource_id_list_length; + pos_srs_resource_set->pos_srs_resource_id_list.srs_pos_resource_id = + calloc_or_fail(pos_srs_resource_id_list_length, + sizeof(*pos_srs_resource_set->pos_srs_resource_id_list.srs_pos_resource_id)); + for (int k = 0; k < pos_srs_resource_id_list_length; k++) { + pos_srs_resource_set->pos_srs_resource_id_list.srs_pos_resource_id[k] = k; + } + pos_srs_resource_set->pos_resource_set_type.present = NRPPA_POS_RESOURCE_SET_TYPE_PR_PERIODIC; + // set periodic = 0 to enable + pos_srs_resource_set->pos_resource_set_type.choice.periodic = 0; + + // semi-persistent + pos_srs_resource_set = &pos_srs_resource_set_list->pos_srs_resource_set_item[1]; + pos_srs_resource_set->pos_srs_resource_set_id = 1; + pos_srs_resource_id_list_length = 5; + pos_srs_resource_set->pos_srs_resource_id_list.pos_srs_resource_id_list_length = pos_srs_resource_id_list_length; + pos_srs_resource_set->pos_srs_resource_id_list.srs_pos_resource_id = + calloc_or_fail(pos_srs_resource_id_list_length, + sizeof(*pos_srs_resource_set->pos_srs_resource_id_list.srs_pos_resource_id)); + for (int k = 0; k < pos_srs_resource_id_list_length; k++) { + pos_srs_resource_set->pos_srs_resource_id_list.srs_pos_resource_id[k] = k; + } + pos_srs_resource_set->pos_resource_set_type.present = NRPPA_POS_RESOURCE_SET_TYPE_PR_SEMI_PERSISTENT; + // set semi_persistent = 0 to enable + pos_srs_resource_set->pos_resource_set_type.choice.semi_persistent = 0; + + // aperiodic + pos_srs_resource_set = &pos_srs_resource_set_list->pos_srs_resource_set_item[2]; + pos_srs_resource_set->pos_srs_resource_set_id = 2; + pos_srs_resource_id_list_length = 5; + pos_srs_resource_set->pos_srs_resource_id_list.pos_srs_resource_id_list_length = pos_srs_resource_id_list_length; + pos_srs_resource_set->pos_srs_resource_id_list.srs_pos_resource_id = + calloc_or_fail(pos_srs_resource_id_list_length, + sizeof(*pos_srs_resource_set->pos_srs_resource_id_list.srs_pos_resource_id)); + for (int k = 0; k < pos_srs_resource_id_list_length; k++) { + pos_srs_resource_set->pos_srs_resource_id_list.srs_pos_resource_id[k] = k; + } + pos_srs_resource_set->pos_resource_set_type.present = NRPPA_POS_RESOURCE_SET_TYPE_PR_APERIODIC; + pos_srs_resource_set->pos_resource_set_type.choice.srs_resource = 3; + } + return resp; +} + // Initializing UE NAS Context with simulated SIM data nr_ue_nas_t *simulated_ue_nas = NULL; void init_ue_nas_context(void) @@ -288,6 +571,14 @@ void *rrc_gnb_task(void *args_p) LOG_I(NR_RRC, "Sending NRPPA_TRP_INFORMATION_RESP to TASK_NRPPA\n"); itti_send_msg_to_task(TASK_NRPPA, 0, msg_p_resp); break; + case NRPPA_POSITIONING_INFORMATION_REQ: + nrppa_positioning_information_req_t *pos_req = &NRPPA_POSITIONING_INFORMATION_REQ(msg_p); + LOG_I(NR_RRC, "Received NRPPA_POSITIONING_INFORMATION_REQ transaction_id %d\n", pos_req->transaction_id); + msg_p_resp = itti_alloc_new_message(TASK_RRC_GNB, 0, NRPPA_POSITIONING_INFORMATION_RESP); + NRPPA_POSITIONING_INFORMATION_RESP(msg_p_resp) = fill_position_information_resp(pos_req->transaction_id); + LOG_I(NR_RRC, "Sending NRPPA_POSITIONING_INFORMATION_RESP to TASK_NRPPA\n"); + itti_send_msg_to_task(TASK_NRPPA, 0, msg_p_resp); + break; default: LOG_E(NR_RRC, "[gNB %ld] Received unexpected message %s\n", instance, msg_name_p); break; From defafa8d24c435305bf27d0762083dd4a2284fbe Mon Sep 17 00:00:00 2001 From: Rakesh Mundlamuri Date: Fri, 23 Jan 2026 18:48:15 +0530 Subject: [PATCH 17/21] Add Positioning Activation Request NRPPA message decoding procedures --- openair2/COMMON/nrppa_messages_def.h | 4 ++ openair2/COMMON/nrppa_messages_types.h | 24 +++++++ openair3/NRPPA/nrppa_gNB_decoder.c | 6 +- openair3/NRPPA/nrppa_gNB_handlers.c | 4 +- .../nrppa_gNB_location_information_transfer.c | 68 +++++++++++++++++++ .../nrppa_gNB_location_information_transfer.h | 3 + openair3/NRPPA/nrppa_includes.h | 2 + 7 files changed, 109 insertions(+), 2 deletions(-) diff --git a/openair2/COMMON/nrppa_messages_def.h b/openair2/COMMON/nrppa_messages_def.h index d20bf1960a..bb5d534856 100644 --- a/openair2/COMMON/nrppa_messages_def.h +++ b/openair2/COMMON/nrppa_messages_def.h @@ -32,3 +32,7 @@ MESSAGE_DEF(NRPPA_POSITIONING_INFORMATION_RESP, MESSAGE_PRIORITY_MED, nrppa_positioning_information_resp_t, nrppa_positioning_information_resp) +MESSAGE_DEF(NRPPA_POSITIONING_ACTIVATION_REQ, + MESSAGE_PRIORITY_MED, + nrppa_positioning_activation_req_t, + nrppa_positioning_activation_req) diff --git a/openair2/COMMON/nrppa_messages_types.h b/openair2/COMMON/nrppa_messages_types.h index 4522604422..077c5a89b0 100644 --- a/openair2/COMMON/nrppa_messages_types.h +++ b/openair2/COMMON/nrppa_messages_types.h @@ -28,6 +28,7 @@ #define NRPPA_TRP_INFORMATION_RESP(mSGpTR) (mSGpTR)->ittiMsg.nrppa_trp_information_resp #define NRPPA_POSITIONING_INFORMATION_REQ(mSGpTR) (mSGpTR)->ittiMsg.nrppa_positioning_information_req #define NRPPA_POSITIONING_INFORMATION_RESP(mSGpTR) (mSGpTR)->ittiMsg.nrppa_positioning_information_resp +#define NRPPA_POSITIONING_ACTIVATION_REQ(mSGpTR) (mSGpTR)->ittiMsg.nrppa_positioning_activation_req /* Structure of Positioning related NRPPA messages */ /* IE structures for Positioning related messages as per TS 38.455 V16.7.1*/ @@ -570,6 +571,22 @@ typedef struct nrppa_trp_information_list_s { uint32_t trp_information_item_length; } nrppa_trp_information_list_t; +typedef union nrppa_srs_type_c { + uint8_t *srs_resource_set_id; + bool *aperiodic; +} nrppa_srs_type_u; + +typedef enum nrppa_srs_type_e { + NRPPA_SRS_TYPE_PR_NOTHING, + NRPPA_SRS_TYPE_PR_SEMIPERSISTENTSRS, + NRPPA_SRS_TYPE_PR_APERIODICSRS +} nrppa_srs_type_pr; + +typedef struct nrppa_srs_type_s { + nrppa_srs_type_pr present; + nrppa_srs_type_u choice; +} nrppa_srs_type_t; + typedef struct nrppa_trp_information_req_s { // IE 9.2.4 (mandatory) uint16_t transaction_id; @@ -599,4 +616,11 @@ typedef struct nrppa_positioning_information_resp_s { nrppa_srs_configuration_t *srs_configuration; } nrppa_positioning_information_resp_t; +typedef struct nrppa_positioning_activation_req_s { + // IE 9.2.4 (mandatory) + uint16_t transaction_id; + // (mandatory) + nrppa_srs_type_t srs_type; +} nrppa_positioning_activation_req_t; + #endif // NRPPA_MESSAGES_TYPES_H_ diff --git a/openair3/NRPPA/nrppa_gNB_decoder.c b/openair3/NRPPA/nrppa_gNB_decoder.c index 94524fd060..340ff63baa 100644 --- a/openair3/NRPPA/nrppa_gNB_decoder.c +++ b/openair3/NRPPA/nrppa_gNB_decoder.c @@ -40,7 +40,11 @@ static int nrppa_gNB_decode_initiating_message(NRPPA_NRPPA_PDU_t *pdu) LOG_I(NRPPA, "Positioning Information Request initiating message\n"); free(res.buffer); break; - + case NRPPA_ProcedureCode_id_positioningActivation: + res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NRPPA_NRPPA_PDU, pdu); + LOG_I(NRPPA, "Positioning Activation initiating message\n"); + free(res.buffer); + break; default: AssertFatal(false, "Unknown procedure ID (%d) for initiating message\n", (int)pdu->choice.initiatingMessage->procedureCode); return -1; diff --git a/openair3/NRPPA/nrppa_gNB_handlers.c b/openair3/NRPPA/nrppa_gNB_handlers.c index 99299ecb64..4689351b11 100644 --- a/openair3/NRPPA/nrppa_gNB_handlers.c +++ b/openair3/NRPPA/nrppa_gNB_handlers.c @@ -57,7 +57,9 @@ nrppa_message_decoded_callback nrppa_messages_callback[][3] = { {0, 0, 0}, // NRPPA_ProcedureCode_id_MeasurementAbort ((NRPPA_ProcedureCode_t)14) {0, 0, 0}, // NRPPA_ProcedureCode_id_MeasurementFailureIndication ((NRPPA_ProcedureCode_t)15) {nrppa_gNB_handle_trp_information_request, 0, 0}, // NRPPA_ProcedureCode_id_tRPInformationExchange ((NRPPA_ProcedureCode_t)16) - {0, 0, 0}, // NRPPA_ProcedureCode_id_positioningActivation ((NRPPA_ProcedureCode_t)17) + {nrppa_gNB_handle_positioning_activation_request, + 0, + 0}, // NRPPA_ProcedureCode_id_positioningActivation ((NRPPA_ProcedureCode_t)17) {0, 0, 0}, // NRPPA_ProcedureCode_id_positioningDeactivation ((NRPPA_ProcedureCode_t)18) }; diff --git a/openair3/NRPPA/nrppa_gNB_location_information_transfer.c b/openair3/NRPPA/nrppa_gNB_location_information_transfer.c index 5d1a43c0a6..dfaa7f1efc 100644 --- a/openair3/NRPPA/nrppa_gNB_location_information_transfer.c +++ b/openair3/NRPPA/nrppa_gNB_location_information_transfer.c @@ -985,6 +985,37 @@ void free_positioning_information_response(nrppa_positioning_information_resp_t } } +void decode_nrppa_srstype(NRPPA_SRSType_t *srs_type, nrppa_srs_type_t *out) +{ + switch (srs_type->present) { + case NRPPA_SRSType_PR_NOTHING: + out->present = NRPPA_SRS_TYPE_PR_NOTHING; + break; + case NRPPA_SRSType_PR_semipersistentSRS: + out->present = NRPPA_SRS_TYPE_PR_SEMIPERSISTENTSRS; + out->choice.srs_resource_set_id = calloc_or_fail(1, sizeof(*out->choice.srs_resource_set_id)); + *out->choice.srs_resource_set_id = srs_type->choice.semipersistentSRS->sRSResourceSetID; + break; + case NRPPA_SRSType_PR_aperiodicSRS: + out->present = NRPPA_SRS_TYPE_PR_APERIODICSRS; + out->choice.aperiodic = calloc_or_fail(1, sizeof(*out->choice.aperiodic)); + *out->choice.aperiodic = srs_type->choice.aperiodicSRS->aperiodic; + break; + default: + AssertFatal(false, "received illegal SRS type\n"); + break; + } +} + +void free_positioning_activation_request(nrppa_positioning_activation_req_t *msg) +{ + if (msg->srs_type.present == NRPPA_SRS_TYPE_PR_SEMIPERSISTENTSRS) { + free(msg->srs_type.choice.srs_resource_set_id); + } else if (msg->srs_type.present == NRPPA_SRS_TYPE_PR_APERIODICSRS) { + free(msg->srs_type.choice.aperiodic); + } +} + int nrppa_gNB_handle_trp_information_request(nrppa_gnb_ue_info_t *nrppa_msg_info, const NRPPA_NRPPA_PDU_t *pdu) { LOG_I(NRPPA, "Processing Received TRP Information Request \n"); @@ -1244,3 +1275,40 @@ int nrppa_gNB_positioning_information_response(instance_t instance, MessageDef * free(buffer); return length; } + +int nrppa_gNB_handle_positioning_activation_request(nrppa_gnb_ue_info_t *nrppa_msg_info, const NRPPA_NRPPA_PDU_t *pdu) +{ + LOG_I(NRPPA, "Processing Received Positioning Activation Request \n"); + DevAssert(pdu != NULL); + DevAssert(nrppa_msg_info != NULL); + + if (LOG_DEBUGFLAG(DEBUG_ASN1)) { + xer_fprint(stdout, &asn_DEF_NRPPA_NRPPA_PDU, pdu); + } + + // Preparing positioning information request for RRC + MessageDef *msg = itti_alloc_new_message(TASK_RRC_GNB, 0, NRPPA_POSITIONING_ACTIVATION_REQ); + nrppa_positioning_activation_req_t *req = &NRPPA_POSITIONING_ACTIVATION_REQ(msg); + + // Processing Received PositioningActivationRequest + NRPPA_PositioningActivationRequest_t *container = NULL; + NRPPA_PositioningActivationRequestIEs_t *ie = NULL; + + // IE 9.2.3 Message type : mandatory + container = &pdu->choice.initiatingMessage->value.choice.PositioningActivationRequest; + + // IE 9.2.4 nrppatransactionID : mandatory + req->transaction_id = pdu->choice.initiatingMessage->nrppatransactionID; + + // IE SRSType : mandatory + NRPPA_FIND_PROTOCOLIE_BY_ID(NRPPA_PositioningActivationRequestIEs_t, ie, container, NRPPA_ProtocolIE_ID_id_SRSType, true); + decode_nrppa_srstype(&ie->value.choice.SRSType, &req->srs_type); + + nrppa_store_ue_context(nrppa_msg_info, req->transaction_id); + + LOG_I(NRPPA, "Forwarding to RRC Positioning Activation Request transaction id = %d\n", req->transaction_id); + + itti_send_msg_to_task(TASK_RRC_GNB, 0, msg); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NRPPA_NRPPA_PDU, &pdu); + return 0; +} diff --git a/openair3/NRPPA/nrppa_gNB_location_information_transfer.h b/openair3/NRPPA/nrppa_gNB_location_information_transfer.h index 31ab194345..d86c7b2744 100644 --- a/openair3/NRPPA/nrppa_gNB_location_information_transfer.h +++ b/openair3/NRPPA/nrppa_gNB_location_information_transfer.h @@ -32,5 +32,8 @@ int nrppa_gNB_handle_positioning_information_request(nrppa_gnb_ue_info_t *nrppa_ int nrppa_gNB_positioning_information_response(instance_t instance, MessageDef *msg_p); NRPPA_SRSCarrier_List_t encode_srs_carrier_list_nrppa(const nrppa_srs_carrier_list_t *in_list); void free_positioning_information_response(nrppa_positioning_information_resp_t *msg); +int nrppa_gNB_handle_positioning_activation_request(nrppa_gnb_ue_info_t *nrppa_msg_info, const NRPPA_NRPPA_PDU_t *pdu); +void decode_nrppa_srstype(NRPPA_SRSType_t *srs_type, nrppa_srs_type_t *out); +void free_positioning_activation_request(nrppa_positioning_activation_req_t *msg); #endif /* NRPPA_GNB_POSITIONING_PROCEDURES_H_ */ diff --git a/openair3/NRPPA/nrppa_includes.h b/openair3/NRPPA/nrppa_includes.h index 6915b93370..6465d6c0af 100644 --- a/openair3/NRPPA/nrppa_includes.h +++ b/openair3/NRPPA/nrppa_includes.h @@ -69,5 +69,7 @@ #include "NRPPA_PosResourceSetTypePeriodic.h" #include "NRPPA_PosResourceSetTypeSemi-persistent.h" #include "NRPPA_PosResourceSetTypeAperiodic.h" +#include "NRPPA_SemipersistentSRS.h" +#include "NRPPA_AperiodicSRS.h" #endif /* NRPPA_INCLUDE_H_ */ From 192508e6ccfb698a65387eaf916920a7d2781f66 Mon Sep 17 00:00:00 2001 From: Rakesh Mundlamuri Date: Fri, 23 Jan 2026 19:09:42 +0530 Subject: [PATCH 18/21] Add Positioning Activation Response NRPPA message encoding procedures --- openair2/COMMON/nrppa_messages_def.h | 4 ++ openair2/COMMON/nrppa_messages_types.h | 6 ++ openair3/NRPPA/nrppa_gNB.c | 3 + .../nrppa_gNB_location_information_transfer.c | 65 +++++++++++++++++++ .../nrppa_gNB_location_information_transfer.h | 1 + tests/nr-cu-nrppa/nr-cu-nrppa.c | 10 +++ 6 files changed, 89 insertions(+) diff --git a/openair2/COMMON/nrppa_messages_def.h b/openair2/COMMON/nrppa_messages_def.h index bb5d534856..d8090ab4a4 100644 --- a/openair2/COMMON/nrppa_messages_def.h +++ b/openair2/COMMON/nrppa_messages_def.h @@ -36,3 +36,7 @@ MESSAGE_DEF(NRPPA_POSITIONING_ACTIVATION_REQ, MESSAGE_PRIORITY_MED, nrppa_positioning_activation_req_t, nrppa_positioning_activation_req) +MESSAGE_DEF(NRPPA_POSITIONING_ACTIVATION_RESP, + MESSAGE_PRIORITY_MED, + nrppa_positioning_activation_resp_t, + nrppa_positioning_activation_resp) diff --git a/openair2/COMMON/nrppa_messages_types.h b/openair2/COMMON/nrppa_messages_types.h index 077c5a89b0..21f74288f5 100644 --- a/openair2/COMMON/nrppa_messages_types.h +++ b/openair2/COMMON/nrppa_messages_types.h @@ -29,6 +29,7 @@ #define NRPPA_POSITIONING_INFORMATION_REQ(mSGpTR) (mSGpTR)->ittiMsg.nrppa_positioning_information_req #define NRPPA_POSITIONING_INFORMATION_RESP(mSGpTR) (mSGpTR)->ittiMsg.nrppa_positioning_information_resp #define NRPPA_POSITIONING_ACTIVATION_REQ(mSGpTR) (mSGpTR)->ittiMsg.nrppa_positioning_activation_req +#define NRPPA_POSITIONING_ACTIVATION_RESP(mSGpTR) (mSGpTR)->ittiMsg.nrppa_positioning_activation_resp /* Structure of Positioning related NRPPA messages */ /* IE structures for Positioning related messages as per TS 38.455 V16.7.1*/ @@ -623,4 +624,9 @@ typedef struct nrppa_positioning_activation_req_s { nrppa_srs_type_t srs_type; } nrppa_positioning_activation_req_t; +typedef struct nrppa_positioning_activation_resp_s { + // IE 9.2.4 (mandatory) + uint16_t transaction_id; +} nrppa_positioning_activation_resp_t; + #endif // NRPPA_MESSAGES_TYPES_H_ diff --git a/openair3/NRPPA/nrppa_gNB.c b/openair3/NRPPA/nrppa_gNB.c index 19e76bc392..0da07e018e 100644 --- a/openair3/NRPPA/nrppa_gNB.c +++ b/openair3/NRPPA/nrppa_gNB.c @@ -63,6 +63,9 @@ void *nrppa_gNB_process_itti_msg(void *notUsed) case NRPPA_POSITIONING_INFORMATION_RESP: nrppa_gNB_positioning_information_response(instance, received_msg); break; + case NRPPA_POSITIONING_ACTIVATION_RESP: + nrppa_gNB_positioning_activation_response(instance, received_msg); + break; default: LOG_E(NRPPA, "Received unhandled message: %d:%s\n", ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg)); break; diff --git a/openair3/NRPPA/nrppa_gNB_location_information_transfer.c b/openair3/NRPPA/nrppa_gNB_location_information_transfer.c index dfaa7f1efc..2bc0d9d9bc 100644 --- a/openair3/NRPPA/nrppa_gNB_location_information_transfer.c +++ b/openair3/NRPPA/nrppa_gNB_location_information_transfer.c @@ -1312,3 +1312,68 @@ int nrppa_gNB_handle_positioning_activation_request(nrppa_gnb_ue_info_t *nrppa_m ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NRPPA_NRPPA_PDU, &pdu); return 0; } + +int nrppa_gNB_positioning_activation_response(instance_t instance, MessageDef *msg_p) +{ + DevAssert(msg_p); + nrppa_positioning_activation_resp_t *resp = &NRPPA_POSITIONING_ACTIVATION_RESP(msg_p); + nrppa_gNB_ue_context_t *ue_info = nrppa_detach_ue_context(resp->transaction_id); + + if (ue_info->gNB_ue_ngap_id <= 0 && ue_info->amf_ue_ngap_id <= 0) { + LOG_E(NRPPA, "Illegal gNB_ue_ngap_id %d and amf_ue_ngap_id %ld\n", ue_info->gNB_ue_ngap_id, ue_info->amf_ue_ngap_id); + nrppa_free_ue_context(ue_info); + return -1; + } + + LOG_I(NRPPA, + "Received PositioningInformationResponse info from RRC with transaction_id=%u and gNB_ue_ngap_id %u\n", + ue_info->transaction_id, + ue_info->gNB_ue_ngap_id); + + // Prepare NRPPA TRP Information transfer Response + NRPPA_NRPPA_PDU_t pdu = {0}; + + // IE: 9.2.3 Message Type : mandatory + pdu.present = NRPPA_NRPPA_PDU_PR_successfulOutcome; + asn1cCalloc(pdu.choice.successfulOutcome, head); + head->procedureCode = NRPPA_ProcedureCode_id_positioningActivation; + head->criticality = NRPPA_Criticality_reject; + head->value.present = NRPPA_SuccessfulOutcome__value_PR_PositioningActivationResponse; + + // IE 9.2.4 nrppatransactionID : mandatory + head->nrppatransactionID = resp->transaction_id; + + LOG_I(NRPPA, "Calling encoder for PositioningActivationResponse \n"); + + if (LOG_DEBUGFLAG(DEBUG_ASN1)) { + xer_fprint(stdout, &asn_DEF_NRPPA_NRPPA_PDU, &pdu); + } + + // Encode NRPPA message + uint8_t *buffer = NULL; + uint32_t length = 0; + if (nrppa_gNB_encode_pdu(&pdu, &buffer, &length) < 0) { + LOG_E(NRPPA, "Failed to encode Uplink NRPPa PositioningActivationResponse\n"); + nrppa_free_ue_context(ue_info); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NRPPA_NRPPA_PDU, &pdu); + return -1; + } + + MessageDef *msg = itti_alloc_new_message(TASK_NRPPA, 0, NGAP_UPLINKUEASSOCIATEDNRPPA); + ngap_uplink_ue_associated_nrppa_t *ULNRPPA = &NGAP_UPLINKUEASSOCIATEDNRPPA(msg); + + ULNRPPA->gNB_ue_ngap_id = ue_info->gNB_ue_ngap_id; + ULNRPPA->amf_ue_ngap_id = ue_info->amf_ue_ngap_id; + + // Routing ID + ULNRPPA->routing_id = create_byte_array(ue_info->routing_id.len, ue_info->routing_id.buf); + + // NRPPA PDU + ULNRPPA->nrppa_pdu = create_byte_array(length, buffer); + + // Forward the NRPPA PDU to NGAP + itti_send_msg_to_task(TASK_NGAP, instance, msg); + nrppa_free_ue_context(ue_info); + free(buffer); + return length; +} diff --git a/openair3/NRPPA/nrppa_gNB_location_information_transfer.h b/openair3/NRPPA/nrppa_gNB_location_information_transfer.h index d86c7b2744..dc64738dfd 100644 --- a/openair3/NRPPA/nrppa_gNB_location_information_transfer.h +++ b/openair3/NRPPA/nrppa_gNB_location_information_transfer.h @@ -35,5 +35,6 @@ void free_positioning_information_response(nrppa_positioning_information_resp_t int nrppa_gNB_handle_positioning_activation_request(nrppa_gnb_ue_info_t *nrppa_msg_info, const NRPPA_NRPPA_PDU_t *pdu); void decode_nrppa_srstype(NRPPA_SRSType_t *srs_type, nrppa_srs_type_t *out); void free_positioning_activation_request(nrppa_positioning_activation_req_t *msg); +int nrppa_gNB_positioning_activation_response(instance_t instance, MessageDef *msg_p); #endif /* NRPPA_GNB_POSITIONING_PROCEDURES_H_ */ diff --git a/tests/nr-cu-nrppa/nr-cu-nrppa.c b/tests/nr-cu-nrppa/nr-cu-nrppa.c index ca47199133..0edd0842f4 100644 --- a/tests/nr-cu-nrppa/nr-cu-nrppa.c +++ b/tests/nr-cu-nrppa/nr-cu-nrppa.c @@ -31,6 +31,7 @@ #include "openair3/NRPPA/nrppa_gNB.h" #include "openair3/NAS/NR_UE/nr_nas_msg.h" #include "executables/nr-uesoftmodem.h" +#include "openair3/NRPPA/nrppa_gNB_location_information_transfer.c" RAN_CONTEXT_t RC; THREAD_STRUCT thread_struct; @@ -579,6 +580,15 @@ void *rrc_gnb_task(void *args_p) LOG_I(NR_RRC, "Sending NRPPA_POSITIONING_INFORMATION_RESP to TASK_NRPPA\n"); itti_send_msg_to_task(TASK_NRPPA, 0, msg_p_resp); break; + case NRPPA_POSITIONING_ACTIVATION_REQ: + nrppa_positioning_activation_req_t *req = &NRPPA_POSITIONING_ACTIVATION_REQ(msg_p); + LOG_I(NR_RRC, "Received NRPPA_POSITIONING_ACTIVATION_REQ transaction_id %d\n", req->transaction_id); + msg_p_resp = itti_alloc_new_message(TASK_RRC_GNB, 0, NRPPA_POSITIONING_ACTIVATION_RESP); + NRPPA_POSITIONING_ACTIVATION_RESP(msg_p_resp).transaction_id = req->transaction_id; + LOG_I(NR_RRC, "Sending NRPPA_POSITIONING_ACTIVATION_RESP to TASK_NRPPA\n"); + itti_send_msg_to_task(TASK_NRPPA, 0, msg_p_resp); + free_positioning_activation_request(req); + break; default: LOG_E(NR_RRC, "[gNB %ld] Received unexpected message %s\n", instance, msg_name_p); break; From 4f8cde62236913baacfbfe7fb0428ffa0fb29af5 Mon Sep 17 00:00:00 2001 From: Rakesh Mundlamuri Date: Thu, 29 Jan 2026 16:38:07 +0530 Subject: [PATCH 19/21] Add Measurement Request NRPPA message decoding procedures --- openair2/COMMON/nrppa_messages_def.h | 1 + openair2/COMMON/nrppa_messages_types.h | 64 ++ openair3/NRPPA/CMakeLists.txt | 1 + openair3/NRPPA/nrppa_gNB_decoder.c | 5 + openair3/NRPPA/nrppa_gNB_handlers.c | 3 +- .../nrppa_gNB_location_information_transfer.c | 2 +- .../nrppa_gNB_location_information_transfer.h | 1 + ...ppa_gNB_measurement_information_transfer.c | 874 ++++++++++++++++++ ...ppa_gNB_measurement_information_transfer.h | 29 + openair3/NRPPA/nrppa_includes.h | 3 + 10 files changed, 981 insertions(+), 2 deletions(-) create mode 100644 openair3/NRPPA/nrppa_gNB_measurement_information_transfer.c create mode 100644 openair3/NRPPA/nrppa_gNB_measurement_information_transfer.h diff --git a/openair2/COMMON/nrppa_messages_def.h b/openair2/COMMON/nrppa_messages_def.h index d8090ab4a4..a68362b18c 100644 --- a/openair2/COMMON/nrppa_messages_def.h +++ b/openair2/COMMON/nrppa_messages_def.h @@ -40,3 +40,4 @@ MESSAGE_DEF(NRPPA_POSITIONING_ACTIVATION_RESP, MESSAGE_PRIORITY_MED, nrppa_positioning_activation_resp_t, nrppa_positioning_activation_resp) +MESSAGE_DEF(NRPPA_MEASUREMENT_REQ, MESSAGE_PRIORITY_MED, nrppa_measurement_req_t, nrppa_measurement_req) diff --git a/openair2/COMMON/nrppa_messages_types.h b/openair2/COMMON/nrppa_messages_types.h index 21f74288f5..dd42af6354 100644 --- a/openair2/COMMON/nrppa_messages_types.h +++ b/openair2/COMMON/nrppa_messages_types.h @@ -30,6 +30,7 @@ #define NRPPA_POSITIONING_INFORMATION_RESP(mSGpTR) (mSGpTR)->ittiMsg.nrppa_positioning_information_resp #define NRPPA_POSITIONING_ACTIVATION_REQ(mSGpTR) (mSGpTR)->ittiMsg.nrppa_positioning_activation_req #define NRPPA_POSITIONING_ACTIVATION_RESP(mSGpTR) (mSGpTR)->ittiMsg.nrppa_positioning_activation_resp +#define NRPPA_MEASUREMENT_REQ(mSGpTR) (mSGpTR)->ittiMsg.nrppa_measurement_req /* Structure of Positioning related NRPPA messages */ /* IE structures for Positioning related messages as per TS 38.455 V16.7.1*/ @@ -588,6 +589,52 @@ typedef struct nrppa_srs_type_s { nrppa_srs_type_u choice; } nrppa_srs_type_t; +typedef struct nrppa_trp_measurement_request_item_s { + uint32_t trp_id; +} nrppa_trp_measurement_request_item_t; + +typedef struct nrppa_trp_measurement_request_list_s { + nrppa_trp_measurement_request_item_t *trp_measurement_request_item; + uint32_t trp_measurement_request_list_length; +} nrppa_trp_measurement_request_list_t; + +typedef enum nrppa_pos_report_characteristics_e { + NRPPA_POSREPORTCHARACTERISTICS_ONDEMAND = 0, + NRPPA_POSREPORTCHARACTERISTICS_PERIODIC = 1 +} nrppa_report_characteristics_pr; + +typedef enum nrppa_pos_measurement_periodicity_e { + NRPPA_POSMEASUREMENTPERIODICITY_MS120 = 0, + NRPPA_POSMEASUREMENTPERIODICITY_MS240 = 1, + NRPPA_POSMEASUREMENTPERIODICITY_MS480 = 2, + NRPPA_POSMEASUREMENTPERIODICITY_MS640 = 3, + NRPPA_POSMEASUREMENTPERIODICITY_MS1024 = 4, + NRPPA_POSMEASUREMENTPERIODICITY_MS2048 = 5, + NRPPA_POSMEASUREMENTPERIODICITY_MS5120 = 6, + NRPPA_POSMEASUREMENTPERIODICITY_MS10240 = 7, + NRPPA_POSMEASUREMENTPERIODICITY_MIN1 = 8, + NRPPA_POSMEASUREMENTPERIODICITY_MIN6 = 9, + NRPPA_POSMEASUREMENTPERIODICITY_MIN12 = 10, + NRPPA_POSMEASUREMENTPERIODICITY_MIN30 = 11, + NRPPA_POSMEASUREMENTPERIODICITY_MIN60 = 12 +} nrppa_measurement_periodicity_pr; + +typedef enum nrppa_pos_measurement_type_e { + NRPPA_POSMEASUREMENTTYPE_GNB_RX_TX = 0, + NRPPA_POSMEASUREMENTTYPE_UL_SRS_RSRP = 1, + NRPPA_POSMEASUREMENTTYPE_UL_AOA = 2, + NRPPA_POSMEASUREMENTTYPE_UL_RTOA = 3 +} nrppa_measurement_type_pr; + +typedef struct nrppa_pos_measurement_quantities_item_s { + nrppa_measurement_type_pr measurement_type; +} nrppa_measurement_quantities_item_t; + +typedef struct nrppa_pos_measurement_quantities_s { + nrppa_measurement_quantities_item_t *measurement_quantities_item; + uint32_t measurement_quantities_length; +} nrppa_measurement_quantities_t; + typedef struct nrppa_trp_information_req_s { // IE 9.2.4 (mandatory) uint16_t transaction_id; @@ -629,4 +676,21 @@ typedef struct nrppa_positioning_activation_resp_s { uint16_t transaction_id; } nrppa_positioning_activation_resp_t; +typedef struct nrppa_measurement_req_s { + // IE 9.2.4 (mandatory) + uint16_t transaction_id; + // (mandatory) + uint32_t lmf_measurement_id; + // (mandatory) + nrppa_trp_measurement_request_list_t trp_measurement_request_list; + // (mandatory) ondemand = 0, periodic = 1 + nrppa_report_characteristics_pr report_characteristics; + // if report characteristics periodic + nrppa_measurement_periodicity_pr measurement_periodicity; + // (mandatory) + nrppa_measurement_quantities_t measurement_quantities; + // IE 9.2.28 (optional) + nrppa_srs_configuration_t *srs_configuration; +} nrppa_measurement_req_t; + #endif // NRPPA_MESSAGES_TYPES_H_ diff --git a/openair3/NRPPA/CMakeLists.txt b/openair3/NRPPA/CMakeLists.txt index 7ec77db3b5..45f0964667 100644 --- a/openair3/NRPPA/CMakeLists.txt +++ b/openair3/NRPPA/CMakeLists.txt @@ -8,6 +8,7 @@ add_library(nrppa nrppa_gNB_ue_context.c nrppa_gNB_location_information_transfer.c nrppa_gNB_encoder.c + nrppa_gNB_measurement_information_transfer.c ) target_link_libraries(nrppa PUBLIC asn1_nrppa) diff --git a/openair3/NRPPA/nrppa_gNB_decoder.c b/openair3/NRPPA/nrppa_gNB_decoder.c index 340ff63baa..756871bc59 100644 --- a/openair3/NRPPA/nrppa_gNB_decoder.c +++ b/openair3/NRPPA/nrppa_gNB_decoder.c @@ -45,6 +45,11 @@ static int nrppa_gNB_decode_initiating_message(NRPPA_NRPPA_PDU_t *pdu) LOG_I(NRPPA, "Positioning Activation initiating message\n"); free(res.buffer); break; + case NRPPA_ProcedureCode_id_Measurement: + res = asn_encode_to_new_buffer(NULL, ATS_CANONICAL_XER, &asn_DEF_NRPPA_NRPPA_PDU, pdu); + LOG_I(NRPPA, "Positioning Measurement initiating message\n"); + free(res.buffer); + break; default: AssertFatal(false, "Unknown procedure ID (%d) for initiating message\n", (int)pdu->choice.initiatingMessage->procedureCode); return -1; diff --git a/openair3/NRPPA/nrppa_gNB_handlers.c b/openair3/NRPPA/nrppa_gNB_handlers.c index 4689351b11..476729cd36 100644 --- a/openair3/NRPPA/nrppa_gNB_handlers.c +++ b/openair3/NRPPA/nrppa_gNB_handlers.c @@ -24,6 +24,7 @@ #include "nrppa_gNB_decoder.h" #include "nrppa_common.h" #include "nrppa_gNB_location_information_transfer.h" +#include "nrppa_gNB_measurement_information_transfer.h" char *nrppa_direction2String(int nrppa_dir) { @@ -51,7 +52,7 @@ nrppa_message_decoded_callback nrppa_messages_callback[][3] = { 0, 0}, // NRPPA_ProcedureCode_id_positioningInformationExchange ((NRPPA_ProcedureCode_t)9) {0, 0, 0}, // NRPPA_ProcedureCode_id_positioningInformationUpdate ((NRPPA_ProcedureCode_t)10) - {0, 0, 0}, // NRPPA_ProcedureCode_id_Measurement ((NRPPA_ProcedureCode_t)11) + {nrppa_gNB_handle_measurement_request, 0, 0}, // NRPPA_ProcedureCode_id_Measurement ((NRPPA_ProcedureCode_t)11) {0, 0, 0}, // NRPPA_ProcedureCode_id_MeasurementReport ((NRPPA_ProcedureCode_t)12) {0, 0, 0}, // NRPPA_ProcedureCode_id_MeasurementUpdate ((NRPPA_ProcedureCode_t)13) {0, 0, 0}, // NRPPA_ProcedureCode_id_MeasurementAbort ((NRPPA_ProcedureCode_t)14) diff --git a/openair3/NRPPA/nrppa_gNB_location_information_transfer.c b/openair3/NRPPA/nrppa_gNB_location_information_transfer.c index 2bc0d9d9bc..bb3bc9f8bd 100644 --- a/openair3/NRPPA/nrppa_gNB_location_information_transfer.c +++ b/openair3/NRPPA/nrppa_gNB_location_information_transfer.c @@ -932,7 +932,7 @@ NRPPA_SRSCarrier_List_t encode_srs_carrier_list_nrppa(const nrppa_srs_carrier_li return out_list; } -static void free_srs_carrier_list(nrppa_srs_carrier_list_t *srs_carrier_list) +void free_srs_carrier_list(nrppa_srs_carrier_list_t *srs_carrier_list) { uint32_t srs_carrier_list_len = srs_carrier_list->srs_carrier_list_length; for (int i = 0; i < srs_carrier_list_len; i++) { diff --git a/openair3/NRPPA/nrppa_gNB_location_information_transfer.h b/openair3/NRPPA/nrppa_gNB_location_information_transfer.h index dc64738dfd..29d73c0059 100644 --- a/openair3/NRPPA/nrppa_gNB_location_information_transfer.h +++ b/openair3/NRPPA/nrppa_gNB_location_information_transfer.h @@ -31,6 +31,7 @@ void free_trp_information_response(nrppa_trp_information_resp_t *msg); int nrppa_gNB_handle_positioning_information_request(nrppa_gnb_ue_info_t *nrppa_msg_info, const NRPPA_NRPPA_PDU_t *pdu); int nrppa_gNB_positioning_information_response(instance_t instance, MessageDef *msg_p); NRPPA_SRSCarrier_List_t encode_srs_carrier_list_nrppa(const nrppa_srs_carrier_list_t *in_list); +void free_srs_carrier_list(nrppa_srs_carrier_list_t *srs_carrier_list); void free_positioning_information_response(nrppa_positioning_information_resp_t *msg); int nrppa_gNB_handle_positioning_activation_request(nrppa_gnb_ue_info_t *nrppa_msg_info, const NRPPA_NRPPA_PDU_t *pdu); void decode_nrppa_srstype(NRPPA_SRSType_t *srs_type, nrppa_srs_type_t *out); diff --git a/openair3/NRPPA/nrppa_gNB_measurement_information_transfer.c b/openair3/NRPPA/nrppa_gNB_measurement_information_transfer.c new file mode 100644 index 0000000000..02db797d81 --- /dev/null +++ b/openair3/NRPPA/nrppa_gNB_measurement_information_transfer.c @@ -0,0 +1,874 @@ +/* + * 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 "intertask_interface.h" +#include "nrppa_common.h" +#include "nrppa_gNB_ue_context.h" +#include "nrppa_messages_types.h" +#include "nrppa_gNB_encoder.h" +#include "openair3/UTILS/conversions.h" +#include "nrppa_gNB_measurement_information_transfer.h" +#include "nrppa_gNB_location_information_transfer.h" + +static void decode_srs_config(const NRPPA_SRSConfig_t *in_config, nrppa_srs_config_t *out_config) +{ + // optional: sRSResource_List + if (in_config->sRSResource_List) { + out_config->srs_resource_list = calloc_or_fail(1, sizeof(*out_config->srs_resource_list)); + nrppa_srs_resource_list_t *srs_resource_list = out_config->srs_resource_list; + uint32_t srs_resource_list_length = in_config->sRSResource_List->list.count; + srs_resource_list->srs_resource_list_length = srs_resource_list_length; + srs_resource_list->srs_resource = calloc_or_fail(srs_resource_list_length, sizeof(*srs_resource_list->srs_resource)); + for (int i = 0; i < srs_resource_list_length; i++) { + nrppa_srs_resource_t *srs_resource = &srs_resource_list->srs_resource[i]; + NRPPA_SRSResource_t *nrppa_srs_resource = in_config->sRSResource_List->list.array[i]; + srs_resource->srs_resource_id = nrppa_srs_resource->sRSResourceID; + switch (nrppa_srs_resource->nrofSRS_Ports) { + case NRPPA_SRSResource__nrofSRS_Ports_port1: + srs_resource->nr_of_srs_ports = NRPPA_SRS_NUMBER_OF_PORTS_N1; + break; + case NRPPA_SRSResource__nrofSRS_Ports_ports2: + srs_resource->nr_of_srs_ports = NRPPA_SRS_NUMBER_OF_PORTS_N2; + break; + case NRPPA_SRSResource__nrofSRS_Ports_ports4: + srs_resource->nr_of_srs_ports = NRPPA_SRS_NUMBER_OF_PORTS_N4; + break; + default: + AssertFatal(false, "illegal number of srs ports %ld\n", nrppa_srs_resource->nrofSRS_Ports); + break; + } + + nrppa_transmission_comb_t *srs_tx_comb = &srs_resource->transmission_comb; + NRPPA_TransmissionComb_t *nrppa_srs_tx_comb = &nrppa_srs_resource->transmissionComb; + switch (nrppa_srs_tx_comb->present) { + case NRPPA_TransmissionComb_PR_NOTHING: + srs_tx_comb->present = NRPPA_TRANSMISSION_COMB_PR_NOTHING; + break; + case NRPPA_TransmissionComb_PR_n2: + srs_tx_comb->present = NRPPA_TRANSMISSION_COMB_PR_N2; + srs_tx_comb->choice.n2.comb_offset_n2 = nrppa_srs_tx_comb->choice.n2->combOffset_n2; + srs_tx_comb->choice.n2.cyclic_shift_n2 = nrppa_srs_tx_comb->choice.n2->cyclicShift_n2; + break; + case NRPPA_TransmissionComb_PR_n4: + srs_tx_comb->present = NRPPA_TRANSMISSION_COMB_PR_N4; + srs_tx_comb->choice.n4.comb_offset_n4 = nrppa_srs_tx_comb->choice.n4->combOffset_n4; + srs_tx_comb->choice.n4.cyclic_shift_n4 = nrppa_srs_tx_comb->choice.n4->cyclicShift_n4; + break; + default: + AssertFatal(false, "illegal transmissionComb %d\n", nrppa_srs_tx_comb->present); + break; + } + + srs_resource->start_position = nrppa_srs_resource->startPosition; + + switch (nrppa_srs_resource->nrofSymbols) { + case NRPPA_SRSResource__nrofSymbols_n1: + srs_resource->nr_of_symbols = NRPPA_SRS_NUMBER_OF_SYMBOLS_N1; + break; + case NRPPA_SRSResource__nrofSymbols_n2: + srs_resource->nr_of_symbols = NRPPA_SRS_NUMBER_OF_SYMBOLS_N2; + break; + case NRPPA_SRSResource__nrofSymbols_n4: + srs_resource->nr_of_symbols = NRPPA_SRS_NUMBER_OF_SYMBOLS_N4; + break; + default: + AssertFatal(false, "illegal number of symbols %ld\n", nrppa_srs_resource->nrofSymbols); + break; + } + + switch (nrppa_srs_resource->repetitionFactor) { + case NRPPA_SRSResource__repetitionFactor_n1: + srs_resource->repetition_factor = NRPPA_SRS_REPETITION_FACTOR_RF1; + break; + case NRPPA_SRSResource__repetitionFactor_n2: + srs_resource->repetition_factor = NRPPA_SRS_REPETITION_FACTOR_RF2; + break; + case NRPPA_SRSResource__repetitionFactor_n4: + srs_resource->repetition_factor = NRPPA_SRS_REPETITION_FACTOR_RF4; + break; + default: + AssertFatal(false, "illegal repetition factor %ld\n", nrppa_srs_resource->repetitionFactor); + break; + } + + srs_resource->freq_domain_position = nrppa_srs_resource->freqDomainPosition; + srs_resource->freq_domain_shift = nrppa_srs_resource->freqDomainShift; + srs_resource->c_srs = nrppa_srs_resource->c_SRS; + srs_resource->b_srs = nrppa_srs_resource->b_SRS; + srs_resource->b_hop = nrppa_srs_resource->b_hop; + + switch (nrppa_srs_resource->groupOrSequenceHopping) { + case NRPPA_SRSResource__groupOrSequenceHopping_neither: + srs_resource->group_or_sequence_hopping = NRPPA_GROUPORSEQUENCEHOPPING_NOTHING; + break; + case NRPPA_SRSResource__groupOrSequenceHopping_groupHopping: + srs_resource->group_or_sequence_hopping = NRPPA_GROUPORSEQUENCEHOPPING_GROUPHOPPING; + break; + case NRPPA_SRSResource__groupOrSequenceHopping_sequenceHopping: + srs_resource->group_or_sequence_hopping = NRPPA_GROUPORSEQUENCEHOPPING_SEQUENCEHOPPING; + break; + default: + AssertFatal(false, "illegal groupOrSequenceHopping %ld\n", nrppa_srs_resource->groupOrSequenceHopping); + break; + } + + NRPPA_ResourceType_t *nrppa_resourceType = &nrppa_srs_resource->resourceType; + nrppa_resource_type_t *resource_type = &srs_resource->resource_type; + if (nrppa_resourceType->present == NRPPA_ResourceType_PR_NOTHING) { + resource_type->present = NRPPA_RESOURCE_TYPE_PR_NOTHING; + } else if (nrppa_resourceType->present == NRPPA_ResourceType_PR_periodic) { + resource_type->present = NRPPA_RESOURCE_TYPE_PR_PERIODIC; + nrppa_resource_type_periodic_t *periodic = &resource_type->choice.periodic; + switch (nrppa_resourceType->choice.periodic->periodicity) { + case NRPPA_ResourceTypePeriodic__periodicity_slot1: + periodic->periodicity = NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT1; + break; + case NRPPA_ResourceTypePeriodic__periodicity_slot2: + periodic->periodicity = NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT2; + break; + case NRPPA_ResourceTypePeriodic__periodicity_slot4: + periodic->periodicity = NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT4; + break; + case NRPPA_ResourceTypePeriodic__periodicity_slot5: + periodic->periodicity = NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT5; + break; + case NRPPA_ResourceTypePeriodic__periodicity_slot8: + periodic->periodicity = NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT8; + break; + case NRPPA_ResourceTypePeriodic__periodicity_slot10: + periodic->periodicity = NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT10; + break; + case NRPPA_ResourceTypePeriodic__periodicity_slot16: + periodic->periodicity = NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT16; + break; + case NRPPA_ResourceTypePeriodic__periodicity_slot20: + periodic->periodicity = NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT20; + break; + case NRPPA_ResourceTypePeriodic__periodicity_slot32: + periodic->periodicity = NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT32; + break; + case NRPPA_ResourceTypePeriodic__periodicity_slot40: + periodic->periodicity = NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT40; + break; + case NRPPA_ResourceTypePeriodic__periodicity_slot64: + periodic->periodicity = NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT64; + break; + case NRPPA_ResourceTypePeriodic__periodicity_slot80: + periodic->periodicity = NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT80; + break; + case NRPPA_ResourceTypePeriodic__periodicity_slot160: + periodic->periodicity = NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT160; + break; + case NRPPA_ResourceTypePeriodic__periodicity_slot320: + periodic->periodicity = NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT320; + break; + case NRPPA_ResourceTypePeriodic__periodicity_slot640: + periodic->periodicity = NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT640; + break; + case NRPPA_ResourceTypePeriodic__periodicity_slot1280: + periodic->periodicity = NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT1280; + break; + case NRPPA_ResourceTypePeriodic__periodicity_slot2560: + periodic->periodicity = NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT2560; + break; + default: + AssertFatal(false, "illegal periodicity %ld\n", nrppa_resourceType->choice.periodic->periodicity); + break; + } + periodic->offset = nrppa_resourceType->choice.periodic->offset; + } else if (nrppa_resourceType->present == NRPPA_ResourceType_PR_semi_persistent) { + resource_type->present = NRPPA_RESOURCE_TYPE_PR_SEMI_PERSISTENT; + nrppa_resource_type_semi_persistent_t *semi_persistent = &resource_type->choice.semi_persistent; + switch (nrppa_resourceType->choice.semi_persistent->periodicity) { + case NRPPA_ResourceTypeSemi_persistent__periodicity_slot1: + semi_persistent->periodicity = NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT1; + break; + case NRPPA_ResourceTypeSemi_persistent__periodicity_slot2: + semi_persistent->periodicity = NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT2; + break; + case NRPPA_ResourceTypeSemi_persistent__periodicity_slot4: + semi_persistent->periodicity = NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT4; + break; + case NRPPA_ResourceTypeSemi_persistent__periodicity_slot5: + semi_persistent->periodicity = NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT5; + break; + case NRPPA_ResourceTypeSemi_persistent__periodicity_slot8: + semi_persistent->periodicity = NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT8; + break; + case NRPPA_ResourceTypeSemi_persistent__periodicity_slot10: + semi_persistent->periodicity = NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT10; + break; + case NRPPA_ResourceTypeSemi_persistent__periodicity_slot16: + semi_persistent->periodicity = NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT16; + break; + case NRPPA_ResourceTypeSemi_persistent__periodicity_slot20: + semi_persistent->periodicity = NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT20; + break; + case NRPPA_ResourceTypeSemi_persistent__periodicity_slot32: + semi_persistent->periodicity = NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT32; + break; + case NRPPA_ResourceTypeSemi_persistent__periodicity_slot40: + semi_persistent->periodicity = NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT40; + break; + case NRPPA_ResourceTypeSemi_persistent__periodicity_slot64: + semi_persistent->periodicity = NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT64; + break; + case NRPPA_ResourceTypeSemi_persistent__periodicity_slot80: + semi_persistent->periodicity = NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT80; + break; + case NRPPA_ResourceTypeSemi_persistent__periodicity_slot160: + semi_persistent->periodicity = NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT160; + break; + case NRPPA_ResourceTypeSemi_persistent__periodicity_slot320: + semi_persistent->periodicity = NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT320; + break; + case NRPPA_ResourceTypeSemi_persistent__periodicity_slot640: + semi_persistent->periodicity = NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT640; + break; + case NRPPA_ResourceTypeSemi_persistent__periodicity_slot1280: + semi_persistent->periodicity = NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT1280; + break; + case NRPPA_ResourceTypeSemi_persistent__periodicity_slot2560: + semi_persistent->periodicity = NRPPA_SRS_RESOURCE_TYPE_PERIODICITY_SLOT2560; + break; + default: + AssertFatal(false, "illegal periodicity %ld\n", nrppa_resourceType->choice.semi_persistent->periodicity); + break; + } + semi_persistent->offset = nrppa_resourceType->choice.semi_persistent->offset; + } else if (nrppa_resourceType->present == NRPPA_ResourceType_PR_aperiodic) { + resource_type->present = NRPPA_RESOURCE_TYPE_PR_APERIODIC; + resource_type->choice.aperiodic = nrppa_resourceType->choice.aperiodic->aperiodicResourceType; + } else { + AssertFatal(false, "illegal resourceType %d\n", nrppa_resourceType->present); + } + + srs_resource->sequence_id = nrppa_srs_resource->sequenceId; + } + } + + // optional: posSRSResource_List + if (in_config->posSRSResource_List) { + out_config->pos_srs_resource_list = calloc_or_fail(1, sizeof(*out_config->pos_srs_resource_list)); + nrppa_pos_srs_resource_list_t *pos_srs_resource_list = out_config->pos_srs_resource_list; + uint32_t pos_srs_resource_list_length = in_config->posSRSResource_List->list.count; + pos_srs_resource_list->pos_srs_resource_list_length = pos_srs_resource_list_length; + pos_srs_resource_list->pos_srs_resource_item = + calloc_or_fail(pos_srs_resource_list_length, sizeof(*pos_srs_resource_list->pos_srs_resource_item)); + for (int i = 0; i < pos_srs_resource_list_length; i++) { + NRPPA_PosSRSResource_Item_t *nrppa_pos_srs_resource = in_config->posSRSResource_List->list.array[i]; + nrppa_pos_srs_resource_item_t *pos_srs_resource = &pos_srs_resource_list->pos_srs_resource_item[i]; + pos_srs_resource->srs_pos_resource_id = nrppa_pos_srs_resource->srs_PosResourceId; + + NRPPA_TransmissionCombPos_t *nrppa_tx_comb_pos = &nrppa_pos_srs_resource->transmissionCombPos; + nrppa_transmission_comb_pos_t *tx_comb_pos = &pos_srs_resource->transmission_comb_pos; + switch (nrppa_tx_comb_pos->present) { + case NRPPA_TransmissionCombPos_PR_NOTHING: + tx_comb_pos->present = NRPPA_TRANSMISSION_COMB_POS_PR_NOTHING; + break; + case NRPPA_TransmissionCombPos_PR_n2: + tx_comb_pos->present = NRPPA_TRANSMISSION_COMB_POS_PR_N2; + tx_comb_pos->choice.n2.comb_offset_n2 = nrppa_tx_comb_pos->choice.n2->combOffset_n2; + tx_comb_pos->choice.n2.cyclic_shift_n2 = nrppa_tx_comb_pos->choice.n2->cyclicShift_n2; + break; + case NRPPA_TransmissionCombPos_PR_n4: + tx_comb_pos->present = NRPPA_TRANSMISSION_COMB_POS_PR_N4; + tx_comb_pos->choice.n4.comb_offset_n4 = nrppa_tx_comb_pos->choice.n4->combOffset_n4; + tx_comb_pos->choice.n4.cyclic_shift_n4 = nrppa_tx_comb_pos->choice.n4->cyclicShift_n4; + break; + case NRPPA_TransmissionCombPos_PR_n8: + tx_comb_pos->present = NRPPA_TRANSMISSION_COMB_POS_PR_N8; + tx_comb_pos->choice.n8.comb_offset_n8 = nrppa_tx_comb_pos->choice.n8->combOffset_n8; + tx_comb_pos->choice.n8.cyclic_shift_n8 = nrppa_tx_comb_pos->choice.n8->cyclicShift_n8; + break; + default: + AssertFatal(false, "illegal transmissionComb %d\n", nrppa_tx_comb_pos->present); + break; + } + + pos_srs_resource->start_position = nrppa_pos_srs_resource->startPosition; + + switch (nrppa_pos_srs_resource->nrofSymbols) { + case NRPPA_PosSRSResource_Item__nrofSymbols_n1: + pos_srs_resource->nr_of_symbols = NRPPA_SRS_RESOURCE_ITEM_NUMBER_OF_SYMBOLS_N1; + break; + case NRPPA_PosSRSResource_Item__nrofSymbols_n2: + pos_srs_resource->nr_of_symbols = NRPPA_SRS_RESOURCE_ITEM_NUMBER_OF_SYMBOLS_N2; + break; + case NRPPA_PosSRSResource_Item__nrofSymbols_n4: + pos_srs_resource->nr_of_symbols = NRPPA_SRS_RESOURCE_ITEM_NUMBER_OF_SYMBOLS_N4; + break; + case NRPPA_PosSRSResource_Item__nrofSymbols_n8: + pos_srs_resource->nr_of_symbols = NRPPA_SRS_RESOURCE_ITEM_NUMBER_OF_SYMBOLS_N8; + break; + case NRPPA_PosSRSResource_Item__nrofSymbols_n12: + pos_srs_resource->nr_of_symbols = NRPPA_SRS_RESOURCE_ITEM_NUMBER_OF_SYMBOLS_N12; + break; + default: + AssertFatal(false, "illegal number of symbols %ld\n", nrppa_pos_srs_resource->nrofSymbols); + break; + } + + pos_srs_resource->freq_domain_shift = nrppa_pos_srs_resource->freqDomainShift; + pos_srs_resource->c_srs = nrppa_pos_srs_resource->c_SRS; + + switch (nrppa_pos_srs_resource->groupOrSequenceHopping) { + case NRPPA_PosSRSResource_Item__groupOrSequenceHopping_neither: + pos_srs_resource->group_or_sequence_hopping = NRPPA_GROUPORSEQUENCEHOPPING_NOTHING; + break; + case NRPPA_PosSRSResource_Item__groupOrSequenceHopping_groupHopping: + pos_srs_resource->group_or_sequence_hopping = NRPPA_GROUPORSEQUENCEHOPPING_GROUPHOPPING; + break; + case NRPPA_PosSRSResource_Item__groupOrSequenceHopping_sequenceHopping: + pos_srs_resource->group_or_sequence_hopping = NRPPA_GROUPORSEQUENCEHOPPING_SEQUENCEHOPPING; + break; + default: + AssertFatal(false, "illegal groupOrSequenceHopping %ld\n", nrppa_pos_srs_resource->groupOrSequenceHopping); + break; + } + + NRPPA_ResourceTypePos_t *nrppa_res_type_pos = &nrppa_pos_srs_resource->resourceTypePos; + nrppa_resource_type_pos_t *res_type_pos = &pos_srs_resource->resource_type_pos; + if (nrppa_res_type_pos->present == NRPPA_ResourceTypePos_PR_NOTHING) { + res_type_pos->present = NRPPA_RESOURCE_TYPE_POS_PR_NOTHING; + } else if (nrppa_res_type_pos->present == NRPPA_ResourceTypePos_PR_periodic) { + res_type_pos->present = NRPPA_RESOURCE_TYPE_POS_PR_PERIODIC; + nrppa_resource_type_periodic_pos_t *pos_periodic = &res_type_pos->choice.periodic; + switch (nrppa_res_type_pos->choice.periodic->periodicity) { + case NRPPA_ResourceTypePeriodicPos__periodicity_slot1: + pos_periodic->periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT1; + break; + case NRPPA_ResourceTypePeriodicPos__periodicity_slot2: + pos_periodic->periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT2; + break; + case NRPPA_ResourceTypePeriodicPos__periodicity_slot4: + pos_periodic->periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT4; + break; + case NRPPA_ResourceTypePeriodicPos__periodicity_slot5: + pos_periodic->periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT5; + break; + case NRPPA_ResourceTypePeriodicPos__periodicity_slot8: + pos_periodic->periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT8; + break; + case NRPPA_ResourceTypePeriodicPos__periodicity_slot10: + pos_periodic->periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT10; + break; + case NRPPA_ResourceTypePeriodicPos__periodicity_slot16: + pos_periodic->periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT16; + break; + case NRPPA_ResourceTypePeriodicPos__periodicity_slot20: + pos_periodic->periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT20; + break; + case NRPPA_ResourceTypePeriodicPos__periodicity_slot32: + pos_periodic->periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT32; + break; + case NRPPA_ResourceTypePeriodicPos__periodicity_slot40: + pos_periodic->periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT40; + break; + case NRPPA_ResourceTypePeriodicPos__periodicity_slot64: + pos_periodic->periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT64; + break; + case NRPPA_ResourceTypePeriodicPos__periodicity_slot80: + pos_periodic->periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT80; + break; + case NRPPA_ResourceTypePeriodicPos__periodicity_slot160: + pos_periodic->periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT160; + break; + case NRPPA_ResourceTypePeriodicPos__periodicity_slot320: + pos_periodic->periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT320; + break; + case NRPPA_ResourceTypePeriodicPos__periodicity_slot640: + pos_periodic->periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT640; + break; + case NRPPA_ResourceTypePeriodicPos__periodicity_slot1280: + pos_periodic->periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT1280; + break; + case NRPPA_ResourceTypePeriodicPos__periodicity_slot2560: + pos_periodic->periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT2560; + break; + case NRPPA_ResourceTypePeriodicPos__periodicity_slot5120: + pos_periodic->periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT5120; + break; + case NRPPA_ResourceTypePeriodicPos__periodicity_slot10240: + pos_periodic->periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT10240; + break; + case NRPPA_ResourceTypePeriodicPos__periodicity_slot20480: + pos_periodic->periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT20480; + break; + case NRPPA_ResourceTypePeriodicPos__periodicity_slot40960: + pos_periodic->periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT40960; + break; + case NRPPA_ResourceTypePeriodicPos__periodicity_slot81920: + pos_periodic->periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT81920; + break; + default: + AssertFatal(false, "illegal periodicity %ld\n", nrppa_res_type_pos->choice.periodic->periodicity); + break; + } + pos_periodic->offset = nrppa_res_type_pos->choice.periodic->offset; + } else if (nrppa_res_type_pos->present == NRPPA_ResourceTypePos_PR_semi_persistent) { + res_type_pos->present = NRPPA_RESOURCE_TYPE_POS_PR_SEMI_PERSISTENT; + nrppa_resource_type_semi_persistent_pos_t *pos_semi_persistent = &res_type_pos->choice.semi_persistent; + switch (nrppa_res_type_pos->choice.semi_persistent->periodicity) { + case NRPPA_ResourceTypeSemi_persistentPos__periodicity_slot1: + pos_semi_persistent->periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT1; + break; + case NRPPA_ResourceTypeSemi_persistentPos__periodicity_slot2: + pos_semi_persistent->periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT2; + break; + case NRPPA_ResourceTypeSemi_persistentPos__periodicity_slot4: + pos_semi_persistent->periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT4; + break; + case NRPPA_ResourceTypeSemi_persistentPos__periodicity_slot5: + pos_semi_persistent->periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT5; + break; + case NRPPA_ResourceTypeSemi_persistentPos__periodicity_slot8: + pos_semi_persistent->periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT8; + break; + case NRPPA_ResourceTypeSemi_persistentPos__periodicity_slot10: + pos_semi_persistent->periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT10; + break; + case NRPPA_ResourceTypeSemi_persistentPos__periodicity_slot16: + pos_semi_persistent->periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT16; + break; + case NRPPA_ResourceTypeSemi_persistentPos__periodicity_slot20: + pos_semi_persistent->periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT20; + break; + case NRPPA_ResourceTypeSemi_persistentPos__periodicity_slot32: + pos_semi_persistent->periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT32; + break; + case NRPPA_ResourceTypeSemi_persistentPos__periodicity_slot40: + pos_semi_persistent->periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT40; + break; + case NRPPA_ResourceTypeSemi_persistentPos__periodicity_slot64: + pos_semi_persistent->periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT64; + break; + case NRPPA_ResourceTypeSemi_persistentPos__periodicity_slot80: + pos_semi_persistent->periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT80; + break; + case NRPPA_ResourceTypeSemi_persistentPos__periodicity_slot160: + pos_semi_persistent->periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT160; + break; + case NRPPA_ResourceTypeSemi_persistentPos__periodicity_slot320: + pos_semi_persistent->periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT320; + break; + case NRPPA_ResourceTypeSemi_persistentPos__periodicity_slot640: + pos_semi_persistent->periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT640; + break; + case NRPPA_ResourceTypeSemi_persistentPos__periodicity_slot1280: + pos_semi_persistent->periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT1280; + break; + case NRPPA_ResourceTypeSemi_persistentPos__periodicity_slot2560: + pos_semi_persistent->periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT2560; + break; + case NRPPA_ResourceTypeSemi_persistentPos__periodicity_slot5120: + pos_semi_persistent->periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT5120; + break; + case NRPPA_ResourceTypeSemi_persistentPos__periodicity_slot10240: + pos_semi_persistent->periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT10240; + break; + case NRPPA_ResourceTypeSemi_persistentPos__periodicity_slot20480: + pos_semi_persistent->periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT20480; + break; + case NRPPA_ResourceTypeSemi_persistentPos__periodicity_slot40960: + pos_semi_persistent->periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT40960; + break; + case NRPPA_ResourceTypeSemi_persistentPos__periodicity_slot81920: + pos_semi_persistent->periodicity = NRPPA_SRS_RESOURCE_TYPE_POS_PERIODICITY_SLOT81920; + break; + default: + AssertFatal(false, "illegal periodicity %ld\n", nrppa_res_type_pos->choice.semi_persistent->periodicity); + break; + } + pos_semi_persistent->offset = nrppa_res_type_pos->choice.semi_persistent->offset; + } else if (nrppa_res_type_pos->present == NRPPA_ResourceTypePos_PR_aperiodic) { + res_type_pos->present = NRPPA_RESOURCE_TYPE_POS_PR_APERIODIC; + res_type_pos->choice.aperiodic.slot_offset = nrppa_res_type_pos->choice.aperiodic->slotOffset; + } else { + AssertFatal(false, "illegal resourceType %d\n", nrppa_res_type_pos->present); + } + + pos_srs_resource->sequence_id = nrppa_pos_srs_resource->sequenceId; + } + } + + // optional: sRSResourceSet_List + if (in_config->sRSResourceSet_List) { + out_config->srs_resource_set_list = calloc_or_fail(1, sizeof(*out_config->srs_resource_set_list)); + nrppa_srs_resource_set_list_t *srs_resource_set_list = out_config->srs_resource_set_list; + uint32_t srs_resource_set_list_length = in_config->sRSResourceSet_List->list.count; + srs_resource_set_list->srs_resource_set_list_length = srs_resource_set_list_length; + srs_resource_set_list->srs_resource_set = + calloc_or_fail(srs_resource_set_list_length, sizeof(*srs_resource_set_list->srs_resource_set)); + for (int i = 0; i < srs_resource_set_list_length; i++) { + NRPPA_SRSResourceSet_t *nrppa_srs_resource_set = in_config->sRSResourceSet_List->list.array[i]; + nrppa_srs_resource_set_t *srs_resource_set = &srs_resource_set_list->srs_resource_set[i]; + srs_resource_set->srs_resource_set_id = nrppa_srs_resource_set->sRSResourceSetID; + uint8_t srs_resource_id_list_length = nrppa_srs_resource_set->sRSResourceID_List.list.count; + srs_resource_set->srs_resource_id_list.srs_resource_id_list_length = srs_resource_id_list_length; + srs_resource_set->srs_resource_id_list.srs_resource_id = + calloc_or_fail(srs_resource_id_list_length, sizeof(*srs_resource_set->srs_resource_id_list.srs_resource_id)); + for (int j = 0; j < srs_resource_id_list_length; j++) { + NRPPA_SRSResourceID_t *nrppa_srs_resource_id = nrppa_srs_resource_set->sRSResourceID_List.list.array[j]; + srs_resource_set->srs_resource_id_list.srs_resource_id[j] = *nrppa_srs_resource_id; + } + + NRPPA_ResourceSetType_t *nrppa_res_set_type = &nrppa_srs_resource_set->resourceSetType; + nrppa_resource_set_type_t *res_set_type = &srs_resource_set->resource_set_type; + switch (nrppa_res_set_type->present) { + case NRPPA_ResourceSetType_PR_NOTHING: + res_set_type->present = NRPPA_RESOURCE_SET_TYPE_PR_NOTHING; + break; + case NRPPA_ResourceSetType_PR_periodic: + res_set_type->present = NRPPA_RESOURCE_SET_TYPE_PR_PERIODIC; + res_set_type->choice.periodic = nrppa_res_set_type->choice.periodic->periodicSet; + break; + case NRPPA_ResourceSetType_PR_semi_persistent: + res_set_type->present = NRPPA_RESOURCE_SET_TYPE_PR_SEMI_PERSISTENT; + res_set_type->choice.semi_persistent = nrppa_res_set_type->choice.semi_persistent->semi_persistentSet; + break; + case NRPPA_ResourceSetType_PR_aperiodic: + res_set_type->present = NRPPA_RESOURCE_SET_TYPE_PR_APERIODIC; + res_set_type->choice.aperiodic.srs_resource_trigger = nrppa_res_set_type->choice.aperiodic->sRSResourceTrigger; + res_set_type->choice.aperiodic.slot_offset = nrppa_res_set_type->choice.aperiodic->slotoffset; + break; + default: + AssertFatal(false, "illegal resource set type %d\n", nrppa_res_set_type->present); + break; + } + } + } + + // optional: posSRSResourceSet_List + if (in_config->posSRSResourceSet_List) { + out_config->pos_srs_resource_set_list = calloc_or_fail(1, sizeof(*out_config->pos_srs_resource_set_list)); + nrppa_pos_srs_resource_set_list_t *pos_srs_resource_set_list = out_config->pos_srs_resource_set_list; + uint32_t pos_srs_resource_set_list_length = in_config->posSRSResourceSet_List->list.count; + pos_srs_resource_set_list->pos_srs_resource_set_list_length = pos_srs_resource_set_list_length; + pos_srs_resource_set_list->pos_srs_resource_set_item = + calloc_or_fail(pos_srs_resource_set_list_length, sizeof(*pos_srs_resource_set_list->pos_srs_resource_set_item)); + for (int i = 0; i < pos_srs_resource_set_list_length; i++) { + NRPPA_PosSRSResourceSet_Item_t *nrppa_pos_srs_resource_set = in_config->posSRSResourceSet_List->list.array[i]; + nrppa_pos_srs_resource_set_item_t *pos_srs_resource_set = &pos_srs_resource_set_list->pos_srs_resource_set_item[i]; + pos_srs_resource_set->pos_srs_resource_set_id = nrppa_pos_srs_resource_set->possrsResourceSetID; + uint8_t pos_srs_resource_id_list_length = nrppa_pos_srs_resource_set->possRSResourceID_List.list.count; + pos_srs_resource_set->pos_srs_resource_id_list.pos_srs_resource_id_list_length = pos_srs_resource_id_list_length; + pos_srs_resource_set->pos_srs_resource_id_list.srs_pos_resource_id = + calloc_or_fail(pos_srs_resource_id_list_length, + sizeof(*pos_srs_resource_set->pos_srs_resource_id_list.srs_pos_resource_id)); + for (int j = 0; j < pos_srs_resource_id_list_length; j++) { + NRPPA_SRSPosResourceID_t *nrppa_pos_srs_resource_id = nrppa_pos_srs_resource_set->possRSResourceID_List.list.array[j]; + pos_srs_resource_set->pos_srs_resource_id_list.srs_pos_resource_id[j] = *nrppa_pos_srs_resource_id; + } + + NRPPA_PosResourceSetType_t *nrppa_pos_res_set_type = &nrppa_pos_srs_resource_set->posresourceSetType; + nrppa_pos_resource_set_type_t *pos_res_set_type = &pos_srs_resource_set->pos_resource_set_type; + switch (nrppa_pos_res_set_type->present) { + case NRPPA_PosResourceSetType_PR_NOTHING: + pos_res_set_type->present = NRPPA_POS_RESOURCE_SET_TYPE_PR_NOTHING; + break; + case NRPPA_PosResourceSetType_PR_periodic: + pos_res_set_type->present = NRPPA_POS_RESOURCE_SET_TYPE_PR_PERIODIC; + pos_res_set_type->choice.periodic = nrppa_pos_res_set_type->choice.periodic->posperiodicSet; + break; + case NRPPA_PosResourceSetType_PR_semi_persistent: + pos_res_set_type->present = NRPPA_POS_RESOURCE_SET_TYPE_PR_SEMI_PERSISTENT; + pos_res_set_type->choice.semi_persistent = nrppa_pos_res_set_type->choice.semi_persistent->possemi_persistentSet; + break; + case NRPPA_PosResourceSetType_PR_aperiodic: + pos_res_set_type->present = NRPPA_POS_RESOURCE_SET_TYPE_PR_APERIODIC; + pos_res_set_type->choice.srs_resource = nrppa_pos_res_set_type->choice.aperiodic->sRSResourceTrigger; + break; + default: + AssertFatal(false, "illegal resource set type pos %d\n", nrppa_pos_res_set_type->present); + break; + } + } + } +} + +static void decode_srs_carrier_list_item(const NRPPA_SRSCarrier_List_Item_t *in_item, nrppa_srs_carrier_list_item_t *out_item) +{ + // pointA + out_item->pointA = in_item->pointA; + + // Uplink Channel BW-PerSCS-List + nrppa_uplink_channel_bw_per_scs_list_t *uplink_channel_bw_per_scs_list = &out_item->uplink_channel_bw_per_scs_list; + const NRPPA_UplinkChannelBW_PerSCS_List_t *nrppa_uplink_channel_bw_per_scs_list = &in_item->uplinkChannelBW_PerSCS_List; + + uint32_t scs_specific_carrier_list_length = nrppa_uplink_channel_bw_per_scs_list->list.count; + AssertFatal(scs_specific_carrier_list_length > 0, "Atleast 1 uplink channel bw per scs list should be present\n"); + uplink_channel_bw_per_scs_list->scs_specific_carrier_list_length = scs_specific_carrier_list_length; + uplink_channel_bw_per_scs_list->scs_specific_carrier = + calloc_or_fail(scs_specific_carrier_list_length, sizeof(*uplink_channel_bw_per_scs_list->scs_specific_carrier)); + for (int i = 0; i < scs_specific_carrier_list_length; i++) { + NRPPA_SCS_SpecificCarrier_t *nrppa_scs_specific_carrier = nrppa_uplink_channel_bw_per_scs_list->list.array[i]; + nrppa_scs_specific_carrier_t *scs_specific_carrier = &uplink_channel_bw_per_scs_list->scs_specific_carrier[i]; + // offset to carrier + scs_specific_carrier->offset_to_carrier = nrppa_scs_specific_carrier->offsetToCarrier; + // subcarrier spacing + switch (nrppa_scs_specific_carrier->subcarrierSpacing) { + case NRPPA_SCS_SpecificCarrier__subcarrierSpacing_kHz15: + scs_specific_carrier->subcarrier_spacing = NRPPA_SUBCARRIER_SPACING_15KHZ; + break; + case NRPPA_SCS_SpecificCarrier__subcarrierSpacing_kHz30: + scs_specific_carrier->subcarrier_spacing = NRPPA_SUBCARRIER_SPACING_30KHZ; + break; + case NRPPA_SCS_SpecificCarrier__subcarrierSpacing_kHz60: + scs_specific_carrier->subcarrier_spacing = NRPPA_SUBCARRIER_SPACING_60KHZ; + break; + case NRPPA_SCS_SpecificCarrier__subcarrierSpacing_kHz120: + scs_specific_carrier->subcarrier_spacing = NRPPA_SUBCARRIER_SPACING_120KHZ; + break; + default: + AssertFatal(false, "illegal subcarrier spacing %ld\n", nrppa_scs_specific_carrier->subcarrierSpacing); + break; + } + // carrier bandwidth + scs_specific_carrier->carrier_bandwidth = nrppa_scs_specific_carrier->carrierBandwidth; + } + + // Active UL BWP + const NRPPA_ActiveULBWP_t *nrppa_active_ul_bwp = &in_item->activeULBWP; + nrppa_active_ul_bwp_t *active_ul_bwp = &out_item->active_ul_bwp; + + // location and bandwidth + active_ul_bwp->location_and_bandwidth = nrppa_active_ul_bwp->locationAndBandwidth; + // subcarrier spacing + switch (nrppa_active_ul_bwp->subcarrierSpacing) { + case NRPPA_ActiveULBWP__subcarrierSpacing_kHz15: + active_ul_bwp->subcarrier_spacing = NRPPA_SUBCARRIER_SPACING_15KHZ; + break; + case NRPPA_ActiveULBWP__subcarrierSpacing_kHz30: + active_ul_bwp->subcarrier_spacing = NRPPA_SUBCARRIER_SPACING_30KHZ; + break; + case NRPPA_ActiveULBWP__subcarrierSpacing_kHz60: + active_ul_bwp->subcarrier_spacing = NRPPA_SUBCARRIER_SPACING_60KHZ; + break; + case NRPPA_ActiveULBWP__subcarrierSpacing_kHz120: + active_ul_bwp->subcarrier_spacing = NRPPA_SUBCARRIER_SPACING_120KHZ; + break; + default: + AssertFatal(false, "illegal subcarrier spacing %ld\n", nrppa_active_ul_bwp->subcarrierSpacing); + break; + } + + // cyclic prefix + if (nrppa_active_ul_bwp->cyclicPrefix == NRPPA_ActiveULBWP__cyclicPrefix_normal) + active_ul_bwp->cyclic_prefix = NRPPA_CP_TYPE_NORMAL; + else + active_ul_bwp->cyclic_prefix = NRPPA_CP_TYPE_EXTENDED; + + // Tx Direct Current Location + active_ul_bwp->tx_direct_current_location = nrppa_active_ul_bwp->txDirectCurrentLocation; + + // SRS Config + const NRPPA_SRSConfig_t *nrppa_sRSConfig = &nrppa_active_ul_bwp->sRSConfig; + nrppa_srs_config_t *sRSConfig = &active_ul_bwp->srs_config; + decode_srs_config(nrppa_sRSConfig, sRSConfig); +} + +void decode_srs_carrier_list(nrppa_srs_carrier_list_t *out_list, const NRPPA_SRSCarrier_List_t *in_list) +{ + uint32_t list_len = in_list->list.count; + AssertFatal(list_len > 0, "atleast 1 SRS carrier list must be present"); + out_list->srs_carrier_list_length = list_len; + out_list->srs_carrier_list_item = calloc_or_fail(list_len, sizeof(*out_list->srs_carrier_list_item)); + for (int i = 0; i < list_len; i++) { + NRPPA_SRSCarrier_List_Item_t *in_item = in_list->list.array[i]; + nrppa_srs_carrier_list_item_t *out_item = &out_list->srs_carrier_list_item[i]; + decode_srs_carrier_list_item(in_item, out_item); + } +} + +void free_measurement_request(nrppa_measurement_req_t *msg) +{ + free(msg->trp_measurement_request_list.trp_measurement_request_item); + if (msg->measurement_quantities.measurement_quantities_item) { + free(msg->measurement_quantities.measurement_quantities_item); + } + + /* SRS Configuration (O) */ + if (msg->srs_configuration) { + nrppa_srs_carrier_list_t *srs_carrier_list = &msg->srs_configuration->srs_carrier_list; + free_srs_carrier_list(srs_carrier_list); + free(msg->srs_configuration); + } +} + +int nrppa_gNB_handle_measurement_request(nrppa_gnb_ue_info_t *nrppa_msg_info, const NRPPA_NRPPA_PDU_t *pdu) +{ + DevAssert(pdu != NULL); + DevAssert(nrppa_msg_info != NULL); + + LOG_I(NRPPA, "Processing Received Measurement Request \n"); + if (LOG_DEBUGFLAG(DEBUG_ASN1)) { + xer_fprint(stdout, &asn_DEF_NRPPA_NRPPA_PDU, pdu); + } + + // Forward request to RRC + MessageDef *msg = itti_alloc_new_message(TASK_RRC_GNB, 0, NRPPA_MEASUREMENT_REQ); + nrppa_measurement_req_t *req = &NRPPA_MEASUREMENT_REQ(msg); + + // Processing Received TRPInformationRequest + NRPPA_MeasurementRequest_t *container = NULL; + NRPPA_MeasurementRequest_IEs_t *ie = NULL; + + // IE 9.2.3 Message type : mandatory + container = &pdu->choice.initiatingMessage->value.choice.MeasurementRequest; + + // IE 9.2.4 nrppatransactionID : mandatory + req->transaction_id = pdu->choice.initiatingMessage->nrppatransactionID; + + NRPPA_FIND_PROTOCOLIE_BY_ID(NRPPA_MeasurementRequest_IEs_t, ie, container, NRPPA_ProtocolIE_ID_id_LMF_Measurement_ID, true); + + // LMF Measurement ID : mandatory + req->lmf_measurement_id = ie->value.choice.Measurement_ID; + + // IE TRP Measurement Request List : mandatory + NRPPA_FIND_PROTOCOLIE_BY_ID(NRPPA_MeasurementRequest_IEs_t, + ie, + container, + NRPPA_ProtocolIE_ID_id_TRP_MeasurementRequestList, + true); + NRPPA_TRP_MeasurementRequestList_t *nrppa_trp_meas_list = &ie->value.choice.TRP_MeasurementRequestList; + uint8_t meas_req_item_len = nrppa_trp_meas_list->list.count; + AssertError(meas_req_item_len > 0, return false, "at least 1 TRP Measurement Request Item must be present"); + nrppa_trp_measurement_request_list_t *trp_meas_list = &req->trp_measurement_request_list; + trp_meas_list->trp_measurement_request_list_length = meas_req_item_len; + trp_meas_list->trp_measurement_request_item = + calloc_or_fail(meas_req_item_len, sizeof(*trp_meas_list->trp_measurement_request_item)); + for (int i = 0; i < meas_req_item_len; i++) { + trp_meas_list->trp_measurement_request_item[i].trp_id = nrppa_trp_meas_list->list.array[i]->tRP_ID; + } + + // IE Report Characteristics : mandatory + NRPPA_FIND_PROTOCOLIE_BY_ID(NRPPA_MeasurementRequest_IEs_t, ie, container, NRPPA_ProtocolIE_ID_id_ReportCharacteristics, true); + switch (ie->value.choice.ReportCharacteristics) { + case NRPPA_ReportCharacteristics_onDemand: + req->report_characteristics = NRPPA_POSREPORTCHARACTERISTICS_ONDEMAND; + break; + case NRPPA_ReportCharacteristics_periodic: + req->report_characteristics = NRPPA_POSREPORTCHARACTERISTICS_PERIODIC; + break; + default: + AssertError(false, return false, "illegal report characteristics\n"); + break; + } + + // IE Measurement Periodicity : C-if Report Charateristics periodic + if (req->report_characteristics == NRPPA_POSREPORTCHARACTERISTICS_PERIODIC) { + NRPPA_FIND_PROTOCOLIE_BY_ID(NRPPA_MeasurementRequest_IEs_t, ie, container, NRPPA_ProtocolIE_ID_id_MeasurementPeriodicity, true); + switch (ie->value.choice.MeasurementPeriodicity) { + case NRPPA_MeasurementPeriodicity_ms120: + req->measurement_periodicity = NRPPA_POSMEASUREMENTPERIODICITY_MS120; + break; + case NRPPA_MeasurementPeriodicity_ms240: + req->measurement_periodicity = NRPPA_POSMEASUREMENTPERIODICITY_MS240; + break; + case NRPPA_MeasurementPeriodicity_ms480: + req->measurement_periodicity = NRPPA_POSMEASUREMENTPERIODICITY_MS480; + break; + case NRPPA_MeasurementPeriodicity_ms640: + req->measurement_periodicity = NRPPA_POSMEASUREMENTPERIODICITY_MS640; + break; + case NRPPA_MeasurementPeriodicity_ms1024: + req->measurement_periodicity = NRPPA_POSMEASUREMENTPERIODICITY_MS1024; + break; + case NRPPA_MeasurementPeriodicity_ms2048: + req->measurement_periodicity = NRPPA_POSMEASUREMENTPERIODICITY_MS2048; + break; + case NRPPA_MeasurementPeriodicity_ms5120: + req->measurement_periodicity = NRPPA_POSMEASUREMENTPERIODICITY_MS5120; + break; + case NRPPA_MeasurementPeriodicity_ms10240: + req->measurement_periodicity = NRPPA_POSMEASUREMENTPERIODICITY_MS10240; + break; + case NRPPA_MeasurementPeriodicity_min1: + req->measurement_periodicity = NRPPA_POSMEASUREMENTPERIODICITY_MIN1; + break; + case NRPPA_MeasurementPeriodicity_min6: + req->measurement_periodicity = NRPPA_POSMEASUREMENTPERIODICITY_MIN6; + break; + case NRPPA_MeasurementPeriodicity_min12: + req->measurement_periodicity = NRPPA_POSMEASUREMENTPERIODICITY_MIN12; + break; + case NRPPA_MeasurementPeriodicity_min30: + req->measurement_periodicity = NRPPA_POSMEASUREMENTPERIODICITY_MIN30; + break; + case NRPPA_MeasurementPeriodicity_min60: + req->measurement_periodicity = NRPPA_POSMEASUREMENTPERIODICITY_MIN60; + break; + default: + AssertError(false, return false, "illegal measurement periodicity\n"); + break; + } + } + + // IE Measurement Quantity : mandatory (but not handled in OAI-LMF) + NRPPA_FIND_PROTOCOLIE_BY_ID(NRPPA_MeasurementRequest_IEs_t, ie, container, NRPPA_ProtocolIE_ID_id_MeasurementQuantities, false); + if (ie == NULL) { + LOG_W(NRPPA, "MeasurementQuantities is madatory but not handled in OAI LMF\n"); + } else { + NRPPA_TRPMeasurementQuantities_t *nrppa_meas_q = &ie->value.choice.TRPMeasurementQuantities; + uint32_t q_len = nrppa_meas_q->list.count; + AssertError(q_len > 0, return false, "at least 1 TRP Measurement Quantity must be present"); + nrppa_measurement_quantities_t *meas_q = &req->measurement_quantities; + meas_q->measurement_quantities_length = q_len; + meas_q->measurement_quantities_item = calloc_or_fail(q_len, sizeof(*meas_q->measurement_quantities_item)); + nrppa_measurement_quantities_item_t *q_item = meas_q->measurement_quantities_item; + for (int i = 0; i < meas_req_item_len; i++) { + switch (nrppa_meas_q->list.array[i]->tRPMeasurementQuantities_Item) { + case NRPPA_TRPMeasurementQuantities_Item_gNB_RxTxTimeDiff: + q_item[i].measurement_type = NRPPA_POSMEASUREMENTTYPE_GNB_RX_TX; + break; + case NRPPA_TRPMeasurementQuantities_Item_uL_SRS_RSRP: + q_item[i].measurement_type = NRPPA_POSMEASUREMENTTYPE_UL_SRS_RSRP; + break; + case NRPPA_TRPMeasurementQuantities_Item_uL_AoA: + q_item[i].measurement_type = NRPPA_POSMEASUREMENTTYPE_UL_AOA; + break; + case NRPPA_TRPMeasurementQuantities_Item_uL_RTOA: + q_item[i].measurement_type = NRPPA_POSMEASUREMENTTYPE_UL_RTOA; + break; + default: + AssertError(false, return false, "illegal measurement quantity\n"); + break; + } + } + } + + // IE SRS Configuration : optional + NRPPA_FIND_PROTOCOLIE_BY_ID(NRPPA_MeasurementRequest_IEs_t, ie, container, NRPPA_ProtocolIE_ID_id_SRSConfiguration, false); + if (ie != NULL) { + NRPPA_SRSCarrier_List_t *nrppa_srs_carrier_list = &ie->value.choice.SRSConfiguration.sRSCarrier_List; + req->srs_configuration = calloc_or_fail(1, sizeof(*req->srs_configuration)); + nrppa_srs_carrier_list_t *srs_carrier_list = &req->srs_configuration->srs_carrier_list; + decode_srs_carrier_list(srs_carrier_list, nrppa_srs_carrier_list); + } + + nrppa_store_ue_context(nrppa_msg_info, req->transaction_id); + + LOG_I(NRPPA, "Forwarding to RRC Measurement Request transaction_id %d\n", req->transaction_id); + itti_send_msg_to_task(TASK_RRC_GNB, 0, msg); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NRPPA_NRPPA_PDU, &pdu); + return 0; +} diff --git a/openair3/NRPPA/nrppa_gNB_measurement_information_transfer.h b/openair3/NRPPA/nrppa_gNB_measurement_information_transfer.h new file mode 100644 index 0000000000..f154fc1ce8 --- /dev/null +++ b/openair3/NRPPA/nrppa_gNB_measurement_information_transfer.h @@ -0,0 +1,29 @@ +/* + * 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 NRPPA_GNB_MEASUREMENT_INFORMATION_TRANSFER_H_ +#define NRPPA_GNB_MEASUREMENT_INFORMATION_TRANSFER_H_ + +int nrppa_gNB_handle_measurement_request(nrppa_gnb_ue_info_t *nrppa_msg_info, const NRPPA_NRPPA_PDU_t *pdu); +void decode_srs_carrier_list(nrppa_srs_carrier_list_t *out_list, const NRPPA_SRSCarrier_List_t *in_list); +void free_measurement_request(nrppa_measurement_req_t *msg); + +#endif /* NRPPA_GNB_MEASUREMENT_INFORMATION_TRANSFER_H_ */ diff --git a/openair3/NRPPA/nrppa_includes.h b/openair3/NRPPA/nrppa_includes.h index 6465d6c0af..64c642587c 100644 --- a/openair3/NRPPA/nrppa_includes.h +++ b/openair3/NRPPA/nrppa_includes.h @@ -71,5 +71,8 @@ #include "NRPPA_PosResourceSetTypeAperiodic.h" #include "NRPPA_SemipersistentSRS.h" #include "NRPPA_AperiodicSRS.h" +#include "NRPPA_TRP-MeasurementRequestItem.h" +#include "NRPPA_TRPMeasurementQuantities-Item.h" +#include "NRPPA_TRPMeasurementQuantitiesList-Item.h" #endif /* NRPPA_INCLUDE_H_ */ From cbc85dd448d57455b47a906ff9f564e0ebf7a097 Mon Sep 17 00:00:00 2001 From: Rakesh Mundlamuri Date: Thu, 29 Jan 2026 23:23:52 +0530 Subject: [PATCH 20/21] Add Measurement Response NRPPA message encoding procedures --- openair2/COMMON/nrppa_messages_def.h | 1 + openair2/COMMON/nrppa_messages_types.h | 128 +++++++++ openair3/NRPPA/nrppa_gNB.c | 4 + ...ppa_gNB_measurement_information_transfer.c | 269 ++++++++++++++++++ ...ppa_gNB_measurement_information_transfer.h | 3 + openair3/NRPPA/nrppa_includes.h | 5 + tests/nr-cu-nrppa/nr-cu-nrppa.c | 86 ++++++ 7 files changed, 496 insertions(+) diff --git a/openair2/COMMON/nrppa_messages_def.h b/openair2/COMMON/nrppa_messages_def.h index a68362b18c..aa40adce44 100644 --- a/openair2/COMMON/nrppa_messages_def.h +++ b/openair2/COMMON/nrppa_messages_def.h @@ -41,3 +41,4 @@ MESSAGE_DEF(NRPPA_POSITIONING_ACTIVATION_RESP, nrppa_positioning_activation_resp_t, nrppa_positioning_activation_resp) MESSAGE_DEF(NRPPA_MEASUREMENT_REQ, MESSAGE_PRIORITY_MED, nrppa_measurement_req_t, nrppa_measurement_req) +MESSAGE_DEF(NRPPA_MEASUREMENT_RESP, MESSAGE_PRIORITY_MED, nrppa_measurement_resp_t, nrppa_measurement_resp) diff --git a/openair2/COMMON/nrppa_messages_types.h b/openair2/COMMON/nrppa_messages_types.h index dd42af6354..881362231d 100644 --- a/openair2/COMMON/nrppa_messages_types.h +++ b/openair2/COMMON/nrppa_messages_types.h @@ -31,6 +31,7 @@ #define NRPPA_POSITIONING_ACTIVATION_REQ(mSGpTR) (mSGpTR)->ittiMsg.nrppa_positioning_activation_req #define NRPPA_POSITIONING_ACTIVATION_RESP(mSGpTR) (mSGpTR)->ittiMsg.nrppa_positioning_activation_resp #define NRPPA_MEASUREMENT_REQ(mSGpTR) (mSGpTR)->ittiMsg.nrppa_measurement_req +#define NRPPA_MEASUREMENT_RESP(mSGpTR) (mSGpTR)->ittiMsg.nrppa_measurement_resp /* Structure of Positioning related NRPPA messages */ /* IE structures for Positioning related messages as per TS 38.455 V16.7.1*/ @@ -635,6 +636,122 @@ typedef struct nrppa_pos_measurement_quantities_s { uint32_t measurement_quantities_length; } nrppa_measurement_quantities_t; +typedef struct nrppa_lcs_to_gcs_translationaoa_c { + uint16_t alpha; + uint16_t beta; + uint16_t gamma; +} nrppa_lcs_to_gcs_translationaoa_t; + +typedef struct nrppa_ul_aoa_s { + uint16_t azimuth_aoa; + uint16_t *zenith_aoa; + nrppa_lcs_to_gcs_translationaoa_t *lcs_to_gcs_translation_aoa; +} nrppa_ul_aoa_t; + +typedef union nrppa_relative_path_delay_c { + uint32_t k0; + uint32_t k1; + uint32_t k2; + uint32_t k3; + uint32_t k4; + uint32_t k5; +} nrppa_relative_path_delay_u, nrppa_ul_rtoa_measurement_u, nrppa_gnb_rx_tx_time_diff_u; + +typedef enum nrppa_gnb_rx_tx_time_diff_meas_e { + NRPPA_GNBRXTXTIMEDIFFMEAS_PR_NOTHING, + NRPPA_GNBRXTXTIMEDIFFMEAS_PR_K0, + NRPPA_GNBRXTXTIMEDIFFMEAS_PR_K1, + NRPPA_GNBRXTXTIMEDIFFMEAS_PR_K2, + NRPPA_GNBRXTXTIMEDIFFMEAS_PR_K3, + NRPPA_GNBRXTXTIMEDIFFMEAS_PR_K4, + NRPPA_GNBRXTXTIMEDIFFMEAS_PR_K5 +} nrppa_gnb_rx_tx_time_diff_pr; + +typedef struct nrppa_gnb_rx_tx_time_diff_s { + nrppa_gnb_rx_tx_time_diff_pr present; + nrppa_gnb_rx_tx_time_diff_u choice; +} nrppa_gnb_rx_tx_time_diff_t; + +typedef enum nrppa_ul_rtoa_measurement_e { + NRPPA_ULRTOAMEAS_PR_NOTHING, + NRPPA_ULRTOAMEAS_PR_K0, + NRPPA_ULRTOAMEAS_PR_K1, + NRPPA_ULRTOAMEAS_PR_K2, + NRPPA_ULRTOAMEAS_PR_K3, + NRPPA_ULRTOAMEAS_PR_K4, + NRPPA_ULRTOAMEAS_PR_K5 +} nrppa_ul_rtoa_measurement_pr; + +typedef struct nrppa_ul_rtoa_measurement_s { + nrppa_ul_rtoa_measurement_pr present; + nrppa_ul_rtoa_measurement_u choice; +} nrppa_ul_rtoa_measurement_t; + +typedef union nrppa_measured_results_value_c { + nrppa_ul_aoa_t ul_angle_of_arrival; + uint8_t ul_srs_rsrp; + nrppa_ul_rtoa_measurement_t ul_rtoa; + nrppa_gnb_rx_tx_time_diff_t gnb_rx_tx_time_diff; +} nrppa_measured_results_value_u; + +typedef enum nrppa_measured_results_value_e { + NRPPA_MEASURED_RESULTS_VALUE_PR_NOTHING, + NRPPA_MEASURED_RESULTS_VALUE_PR_UL_ANGLEOFARRIVAL, + NRPPA_MEASURED_RESULTS_VALUE_PR_UL_SRS_RSRP, + NRPPA_MEASURED_RESULTS_VALUE_PR_UL_RTOA, + NRPPA_MEASURED_RESULTS_VALUE_PR_GNB_RXTXTIMEDIFF +} nrppa_measured_results_value_pr; + +typedef struct nrppa_measured_results_value_s { + nrppa_measured_results_value_pr present; + nrppa_measured_results_value_u choice; +} nrppa_measured_results_value_t; + +typedef union nrppa_time_stamp_slot_index_c { + uint8_t scs_15; + uint8_t scs_30; + uint8_t scs_60; + uint8_t scs_120; +} nrppa_time_stamp_slot_index_u; + +typedef enum nrppa_time_stamp_slot_index_e { + NRPPA_TIME_STAMP_SLOT_INDEX_PR_NOTHING, + NRPPA_TIME_STAMP_SLOT_INDEX_PR_SCS_15, + NRPPA_TIME_STAMP_SLOT_INDEX_PR_SCS_30, + NRPPA_TIME_STAMP_SLOT_INDEX_PR_SCS_60, + NRPPA_TIME_STAMP_SLOT_INDEX_PR_SCS_120 +} nrppa_time_stamp_slot_index_pr; + +typedef struct nrppa_time_stamp_slot_index_s { + nrppa_time_stamp_slot_index_pr present; + nrppa_time_stamp_slot_index_u choice; +} nrppa_time_stamp_slot_index_t; + +typedef struct nrppa_time_stamp_s { + uint16_t system_frame_number; + nrppa_time_stamp_slot_index_t slot_index; +} nrppa_time_stamp_t; + +typedef struct nrppa_measurement_result_item_s { + nrppa_measured_results_value_t measured_results_value; + nrppa_time_stamp_t time_stamp; +} nrppa_measurement_result_item_t; + +typedef struct nrppa_measurement_result_s { + nrppa_measurement_result_item_t *measurement_result_item; + uint32_t measurement_result_item_length; +} nrppa_measurement_result_t; + +typedef struct nrppa_measurement_response_item_s { + nrppa_measurement_result_t measurement_result; + uint32_t trp_id; +} nrppa_measurement_response_item_t; + +typedef struct nrppa_measurement_response_list_s { + nrppa_measurement_response_item_t *measurement_response_item; + uint32_t measurement_response_list_length; +} nrppa_measurement_response_list_t; + typedef struct nrppa_trp_information_req_s { // IE 9.2.4 (mandatory) uint16_t transaction_id; @@ -693,4 +810,15 @@ typedef struct nrppa_measurement_req_s { nrppa_srs_configuration_t *srs_configuration; } nrppa_measurement_req_t; +typedef struct nrppa_measurement_resp_s { + // IE 9.2.4 (mandatory) + uint16_t transaction_id; + // (mandatory) + uint32_t lmf_measurement_id; + // (mandatory) + uint32_t ran_measurement_id; + // (optional) + nrppa_measurement_response_list_t *measurement_response_list; +} nrppa_measurement_resp_t; + #endif // NRPPA_MESSAGES_TYPES_H_ diff --git a/openair3/NRPPA/nrppa_gNB.c b/openair3/NRPPA/nrppa_gNB.c index 0da07e018e..a561c026fd 100644 --- a/openair3/NRPPA/nrppa_gNB.c +++ b/openair3/NRPPA/nrppa_gNB.c @@ -31,6 +31,7 @@ #include "nrppa_common.h" #include "nrppa_gNB_handlers.h" #include "nrppa_gNB_location_information_transfer.h" +#include "nrppa_gNB_measurement_information_transfer.h" void nrppa_gNB_init(void) { @@ -66,6 +67,9 @@ void *nrppa_gNB_process_itti_msg(void *notUsed) case NRPPA_POSITIONING_ACTIVATION_RESP: nrppa_gNB_positioning_activation_response(instance, received_msg); break; + case NRPPA_MEASUREMENT_RESP: + nrppa_gNB_measurement_response(instance, received_msg); + break; default: LOG_E(NRPPA, "Received unhandled message: %d:%s\n", ITTI_MSG_ID(received_msg), ITTI_MSG_NAME(received_msg)); break; diff --git a/openair3/NRPPA/nrppa_gNB_measurement_information_transfer.c b/openair3/NRPPA/nrppa_gNB_measurement_information_transfer.c index 02db797d81..afeacae4c7 100644 --- a/openair3/NRPPA/nrppa_gNB_measurement_information_transfer.c +++ b/openair3/NRPPA/nrppa_gNB_measurement_information_transfer.c @@ -714,6 +714,180 @@ void free_measurement_request(nrppa_measurement_req_t *msg) } } +static NRPPA_TrpMeasurementResult_t encode_measurement_results(nrppa_measurement_result_t *in_result) +{ + NRPPA_TrpMeasurementResult_t out_result = {0}; + for (int i = 0; i < in_result->measurement_result_item_length; i++) { + asn1cSequenceAdd(out_result.list, NRPPA_TrpMeasurementResultItem_t, out_item); + nrppa_measurement_result_item_t *in_item = &in_result->measurement_result_item[i]; + NRPPA_TrpMeasuredResultsValue_t *out_meas_res_val = &out_item->measuredResultsValue; + nrppa_measured_results_value_t *in_meas_res_val = &in_item->measured_results_value; + switch (in_meas_res_val->present) { + case NRPPA_MEASURED_RESULTS_VALUE_PR_NOTHING: + out_meas_res_val->present = NRPPA_TrpMeasuredResultsValue_PR_NOTHING; + break; + case NRPPA_MEASURED_RESULTS_VALUE_PR_UL_ANGLEOFARRIVAL: + out_meas_res_val->present = NRPPA_TrpMeasuredResultsValue_PR_uL_AngleOfArrival; + asn1cCalloc(out_meas_res_val->choice.uL_AngleOfArrival, out_ul_aoa); + nrppa_ul_aoa_t *in_ul_aoa = &in_meas_res_val->choice.ul_angle_of_arrival; + out_ul_aoa->azimuthAoA = in_ul_aoa->azimuth_aoa; + if (in_ul_aoa->zenith_aoa) { + asn1cCalloc(out_ul_aoa->zenithAoA, out_z_aoa); + *out_z_aoa = *in_ul_aoa->zenith_aoa; + } + break; + case NRPPA_MEASURED_RESULTS_VALUE_PR_UL_SRS_RSRP: + out_meas_res_val->present = NRPPA_TrpMeasuredResultsValue_PR_uL_SRS_RSRP; + out_meas_res_val->choice.uL_SRS_RSRP = in_meas_res_val->choice.ul_srs_rsrp; + break; + case NRPPA_MEASURED_RESULTS_VALUE_PR_UL_RTOA: + out_meas_res_val->present = NRPPA_TrpMeasuredResultsValue_PR_uL_RTOA; + asn1cCalloc(out_meas_res_val->choice.uL_RTOA, out_ul_rtoa); + nrppa_ul_rtoa_measurement_t *in_ul_rtoa = &in_meas_res_val->choice.ul_rtoa; + switch (in_ul_rtoa->present) { + case NRPPA_ULRTOAMEAS_PR_NOTHING: + out_ul_rtoa->uLRTOAmeas.present = NRPPA_ULRTOAMeas_PR_NOTHING; + break; + case NRPPA_ULRTOAMEAS_PR_K0: + out_ul_rtoa->uLRTOAmeas.present = NRPPA_ULRTOAMeas_PR_k0; + out_ul_rtoa->uLRTOAmeas.choice.k0 = in_ul_rtoa->choice.k0; + break; + case NRPPA_ULRTOAMEAS_PR_K1: + out_ul_rtoa->uLRTOAmeas.present = NRPPA_ULRTOAMeas_PR_k1; + out_ul_rtoa->uLRTOAmeas.choice.k1 = in_ul_rtoa->choice.k1; + break; + case NRPPA_ULRTOAMEAS_PR_K2: + out_ul_rtoa->uLRTOAmeas.present = NRPPA_ULRTOAMeas_PR_k2; + out_ul_rtoa->uLRTOAmeas.choice.k2 = in_ul_rtoa->choice.k2; + break; + case NRPPA_ULRTOAMEAS_PR_K3: + out_ul_rtoa->uLRTOAmeas.present = NRPPA_ULRTOAMeas_PR_k3; + out_ul_rtoa->uLRTOAmeas.choice.k3 = in_ul_rtoa->choice.k3; + break; + case NRPPA_ULRTOAMEAS_PR_K4: + out_ul_rtoa->uLRTOAmeas.present = NRPPA_ULRTOAMeas_PR_k4; + out_ul_rtoa->uLRTOAmeas.choice.k4 = in_ul_rtoa->choice.k4; + break; + case NRPPA_ULRTOAMEAS_PR_K5: + out_ul_rtoa->uLRTOAmeas.present = NRPPA_ULRTOAMeas_PR_k5; + out_ul_rtoa->uLRTOAmeas.choice.k5 = in_ul_rtoa->choice.k5; + break; + default: + AssertFatal(false, "illegal ul rtoa measure type\n"); + break; + } + break; + case NRPPA_MEASURED_RESULTS_VALUE_PR_GNB_RXTXTIMEDIFF: + out_meas_res_val->present = NRPPA_TrpMeasuredResultsValue_PR_gNB_RxTxTimeDiff; + asn1cCalloc(out_meas_res_val->choice.gNB_RxTxTimeDiff, out_rxtx_time_diff); + nrppa_gnb_rx_tx_time_diff_t *in_rxtx_time_diff = &in_meas_res_val->choice.gnb_rx_tx_time_diff; + switch (in_rxtx_time_diff->present) { + case NRPPA_GNBRXTXTIMEDIFFMEAS_PR_NOTHING: + out_rxtx_time_diff->rxTxTimeDiff.present = NRPPA_GNBRxTxTimeDiffMeas_PR_NOTHING; + break; + case NRPPA_GNBRXTXTIMEDIFFMEAS_PR_K0: + out_rxtx_time_diff->rxTxTimeDiff.present = NRPPA_GNBRxTxTimeDiffMeas_PR_k0; + out_rxtx_time_diff->rxTxTimeDiff.choice.k0 = in_rxtx_time_diff->choice.k0; + break; + case NRPPA_GNBRXTXTIMEDIFFMEAS_PR_K1: + out_rxtx_time_diff->rxTxTimeDiff.present = NRPPA_GNBRxTxTimeDiffMeas_PR_k1; + out_rxtx_time_diff->rxTxTimeDiff.choice.k1 = in_rxtx_time_diff->choice.k1; + break; + case NRPPA_GNBRXTXTIMEDIFFMEAS_PR_K2: + out_rxtx_time_diff->rxTxTimeDiff.present = NRPPA_GNBRxTxTimeDiffMeas_PR_k2; + out_rxtx_time_diff->rxTxTimeDiff.choice.k2 = in_rxtx_time_diff->choice.k2; + break; + case NRPPA_GNBRXTXTIMEDIFFMEAS_PR_K3: + out_rxtx_time_diff->rxTxTimeDiff.present = NRPPA_GNBRxTxTimeDiffMeas_PR_k3; + out_rxtx_time_diff->rxTxTimeDiff.choice.k3 = in_rxtx_time_diff->choice.k3; + break; + case NRPPA_GNBRXTXTIMEDIFFMEAS_PR_K4: + out_rxtx_time_diff->rxTxTimeDiff.present = NRPPA_GNBRxTxTimeDiffMeas_PR_k4; + out_rxtx_time_diff->rxTxTimeDiff.choice.k4 = in_rxtx_time_diff->choice.k4; + break; + case NRPPA_GNBRXTXTIMEDIFFMEAS_PR_K5: + out_rxtx_time_diff->rxTxTimeDiff.present = NRPPA_GNBRxTxTimeDiffMeas_PR_k5; + out_rxtx_time_diff->rxTxTimeDiff.choice.k5 = in_rxtx_time_diff->choice.k5; + break; + default: + AssertFatal(false, "illegal ul rtoa measure type\n"); + break; + } + break; + default: + AssertFatal(false, "illegal measured results type\n"); + break; + } + + NRPPA_TimeStamp_t *out_time_stamp = &out_item->timeStamp; + nrppa_time_stamp_t *in_time_stamp = &in_item->time_stamp; + out_time_stamp->systemFrameNumber = in_time_stamp->system_frame_number; + switch (in_time_stamp->slot_index.present) { + case NRPPA_TIME_STAMP_SLOT_INDEX_PR_NOTHING: + out_time_stamp->slotIndex.present = NRPPA_TimeStampSlotIndex_PR_NOTHING; + break; + case NRPPA_TIME_STAMP_SLOT_INDEX_PR_SCS_15: + out_time_stamp->slotIndex.present = NRPPA_TimeStampSlotIndex_PR_sCS_15; + out_time_stamp->slotIndex.choice.sCS_15 = in_time_stamp->slot_index.choice.scs_15; + break; + case NRPPA_TIME_STAMP_SLOT_INDEX_PR_SCS_30: + out_time_stamp->slotIndex.present = NRPPA_TimeStampSlotIndex_PR_sCS_30; + out_time_stamp->slotIndex.choice.sCS_30 = in_time_stamp->slot_index.choice.scs_30; + break; + case NRPPA_TIME_STAMP_SLOT_INDEX_PR_SCS_60: + out_time_stamp->slotIndex.present = NRPPA_TimeStampSlotIndex_PR_sCS_60; + out_time_stamp->slotIndex.choice.sCS_60 = in_time_stamp->slot_index.choice.scs_60; + break; + case NRPPA_TIME_STAMP_SLOT_INDEX_PR_SCS_120: + out_time_stamp->slotIndex.present = NRPPA_TimeStampSlotIndex_PR_sCS_120; + out_time_stamp->slotIndex.choice.sCS_120 = in_time_stamp->slot_index.choice.scs_120; + break; + default: + AssertFatal(false, "illegal slot index\n"); + break; + } + } + return out_result; +} + +NRPPA_TRP_MeasurementResponseList_t encode_trp_measurement_reponse_list(nrppa_measurement_response_list_t *in_list) +{ + NRPPA_TRP_MeasurementResponseList_t out_list = {0}; + for (int i = 0; i < in_list->measurement_response_list_length; i++) { + asn1cSequenceAdd(out_list.list, NRPPA_TRP_MeasurementResponseItem_t, out_item); + nrppa_measurement_response_item_t *in_item = &in_list->measurement_response_item[i]; + out_item->tRP_ID = in_item->trp_id; + out_item->measurementResult = encode_measurement_results(&in_item->measurement_result); + } + + return out_list; +} + +void free_measurement_resp(nrppa_measurement_resp_t *msg) +{ + if (msg->measurement_response_list) { + nrppa_measurement_response_list_t *list = msg->measurement_response_list; + uint32_t meas_resp_list_len = list->measurement_response_list_length; + for (int i = 0; i < meas_resp_list_len; i++) { + nrppa_measurement_response_item_t *meas_response_item = &list->measurement_response_item[i]; + nrppa_measurement_result_t *MeasurementResult = &meas_response_item->measurement_result; + uint32_t meas_result_length = MeasurementResult->measurement_result_item_length; + for (int j = 0; j < meas_result_length; j++) { + nrppa_measurement_result_item_t *item = &MeasurementResult->measurement_result_item[j]; + nrppa_measured_results_value_t *measuredResultsValue = &item->measured_results_value; + if (measuredResultsValue->present == NRPPA_MEASURED_RESULTS_VALUE_PR_UL_ANGLEOFARRIVAL) { + if (measuredResultsValue->choice.ul_angle_of_arrival.zenith_aoa) { + free(measuredResultsValue->choice.ul_angle_of_arrival.zenith_aoa); + } + } + } + free(MeasurementResult->measurement_result_item); + } + free(msg->measurement_response_list->measurement_response_item); + free(msg->measurement_response_list); + } +} + int nrppa_gNB_handle_measurement_request(nrppa_gnb_ue_info_t *nrppa_msg_info, const NRPPA_NRPPA_PDU_t *pdu) { DevAssert(pdu != NULL); @@ -872,3 +1046,98 @@ int nrppa_gNB_handle_measurement_request(nrppa_gnb_ue_info_t *nrppa_msg_info, co ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NRPPA_NRPPA_PDU, &pdu); return 0; } + +int nrppa_gNB_measurement_response(instance_t instance, MessageDef *msg_p) +{ + DevAssert(msg_p); + nrppa_measurement_resp_t *resp = &NRPPA_MEASUREMENT_RESP(msg_p); + nrppa_gNB_ue_context_t *ue_info = nrppa_detach_ue_context(resp->transaction_id); + + if (ue_info->gNB_ue_ngap_id != 0 && ue_info->amf_ue_ngap_id != 0) { + LOG_E(NRPPA, "Illegal gNB_ue_ngap_id %d and amf_ue_ngap_id %ld\n", ue_info->gNB_ue_ngap_id, ue_info->amf_ue_ngap_id); + free_measurement_resp(resp); + nrppa_free_ue_context(ue_info); + return -1; + } + + LOG_I(NRPPA, + "Received measurement response info from RRC with transaction_id %u and gNB_ue_ngap_id %u\n", + ue_info->transaction_id, + ue_info->gNB_ue_ngap_id); + + // Prepare NRPPA TRP Information transfer Response + NRPPA_NRPPA_PDU_t pdu = {0}; + + // IE: 9.2.3 Message Type : mandatory + pdu.present = NRPPA_NRPPA_PDU_PR_successfulOutcome; + asn1cCalloc(pdu.choice.successfulOutcome, head); + head->procedureCode = NRPPA_ProcedureCode_id_Measurement; + head->criticality = NRPPA_Criticality_reject; + head->value.present = NRPPA_SuccessfulOutcome__value_PR_MeasurementResponse; + + // IE 9.2.4 nrppatransactionID : mandatory + head->nrppatransactionID = resp->transaction_id; + NRPPA_MeasurementResponse_t *out = &head->value.choice.MeasurementResponse; + + // IE LMF Measurement ID : mandatory + { + asn1cSequenceAdd(out->protocolIEs.list, NRPPA_MeasurementResponse_IEs_t, ie); + ie->id = NRPPA_ProtocolIE_ID_id_LMF_Measurement_ID; + ie->criticality = NRPPA_Criticality_reject; + ie->value.present = NRPPA_MeasurementResponse_IEs__value_PR_Measurement_ID; + ie->value.choice.Measurement_ID = resp->lmf_measurement_id; + } + + // IE RAN Measurement ID : mandatory + { + asn1cSequenceAdd(out->protocolIEs.list, NRPPA_MeasurementResponse_IEs_t, ie); + ie->id = NRPPA_ProtocolIE_ID_id_RAN_Measurement_ID; + ie->criticality = NRPPA_Criticality_reject; + ie->value.present = NRPPA_MeasurementResponse_IEs__value_PR_Measurement_ID_1; + ie->value.choice.Measurement_ID_1 = resp->ran_measurement_id; + } + + // IE TRP Measurement Response List : mandatory + { + if (resp->measurement_response_list) { + asn1cSequenceAdd(out->protocolIEs.list, NRPPA_MeasurementResponse_IEs_t, ie); + ie->id = NRPPA_ProtocolIE_ID_id_TRP_MeasurementResponseList; + ie->criticality = NRPPA_Criticality_reject; + ie->value.present = NRPPA_MeasurementResponse_IEs__value_PR_TRP_MeasurementResponseList; + ie->value.choice.TRP_MeasurementResponseList = encode_trp_measurement_reponse_list(resp->measurement_response_list); + } + } + + free_measurement_resp(resp); + + LOG_I(NRPPA, "Calling encoder for Measurement Response \n"); + + if (LOG_DEBUGFLAG(DEBUG_ASN1)) { + xer_fprint(stdout, &asn_DEF_NRPPA_NRPPA_PDU, &pdu); + } + + // Encode NRPPA message + uint8_t *buffer = NULL; + uint32_t length = 0; + if (nrppa_gNB_encode_pdu(&pdu, &buffer, &length) < 0) { + LOG_E(NRPPA, "Failed to encode Uplink NRPPa Measurement Response\n"); + nrppa_free_ue_context(ue_info); + ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_NRPPA_NRPPA_PDU, &pdu); + return -1; + } + + MessageDef *msg = itti_alloc_new_message(TASK_NRPPA, 0, NGAP_UPLINKNONUEASSOCIATEDNRPPA); + ngap_uplink_non_ue_associated_nrppa_t *ULNRPPA = &NGAP_UPLINKNONUEASSOCIATEDNRPPA(msg); + + // Routing ID + ULNRPPA->routing_id = create_byte_array(ue_info->routing_id.len, ue_info->routing_id.buf); + + // NRPPa PDU + ULNRPPA->nrppa_pdu = create_byte_array(length, buffer); + + // Forward the NRPPA PDU to NGAP + itti_send_msg_to_task(TASK_NGAP, instance, msg); + nrppa_free_ue_context(ue_info); + free(buffer); + return length; +} diff --git a/openair3/NRPPA/nrppa_gNB_measurement_information_transfer.h b/openair3/NRPPA/nrppa_gNB_measurement_information_transfer.h index f154fc1ce8..da03403f4d 100644 --- a/openair3/NRPPA/nrppa_gNB_measurement_information_transfer.h +++ b/openair3/NRPPA/nrppa_gNB_measurement_information_transfer.h @@ -25,5 +25,8 @@ int nrppa_gNB_handle_measurement_request(nrppa_gnb_ue_info_t *nrppa_msg_info, const NRPPA_NRPPA_PDU_t *pdu); void decode_srs_carrier_list(nrppa_srs_carrier_list_t *out_list, const NRPPA_SRSCarrier_List_t *in_list); void free_measurement_request(nrppa_measurement_req_t *msg); +int nrppa_gNB_measurement_response(instance_t instance, MessageDef *msg_p); +NRPPA_TRP_MeasurementResponseList_t encode_trp_measurement_reponse_list(nrppa_measurement_response_list_t *in_list); +void free_measurement_resp(nrppa_measurement_resp_t *msg); #endif /* NRPPA_GNB_MEASUREMENT_INFORMATION_TRANSFER_H_ */ diff --git a/openair3/NRPPA/nrppa_includes.h b/openair3/NRPPA/nrppa_includes.h index 64c642587c..98e447d379 100644 --- a/openair3/NRPPA/nrppa_includes.h +++ b/openair3/NRPPA/nrppa_includes.h @@ -74,5 +74,10 @@ #include "NRPPA_TRP-MeasurementRequestItem.h" #include "NRPPA_TRPMeasurementQuantities-Item.h" #include "NRPPA_TRPMeasurementQuantitiesList-Item.h" +#include "NRPPA_TRP-MeasurementResponseList.h" +#include "NRPPA_TRP-MeasurementResponseItem.h" +#include "NRPPA_TrpMeasurementResultItem.h" +#include "NRPPA_UL-RTOAMeasurement.h" +#include "NRPPA_GNB-RxTxTimeDiff.h" #endif /* NRPPA_INCLUDE_H_ */ diff --git a/tests/nr-cu-nrppa/nr-cu-nrppa.c b/tests/nr-cu-nrppa/nr-cu-nrppa.c index 0edd0842f4..de784a3a16 100644 --- a/tests/nr-cu-nrppa/nr-cu-nrppa.c +++ b/tests/nr-cu-nrppa/nr-cu-nrppa.c @@ -32,6 +32,7 @@ #include "openair3/NAS/NR_UE/nr_nas_msg.h" #include "executables/nr-uesoftmodem.h" #include "openair3/NRPPA/nrppa_gNB_location_information_transfer.c" +#include "openair3/NRPPA/nrppa_gNB_measurement_information_transfer.h" RAN_CONTEXT_t RC; THREAD_STRUCT thread_struct; @@ -432,6 +433,82 @@ static nrppa_positioning_information_resp_t fill_position_information_resp(uint1 return resp; } +static nrppa_measurement_resp_t fill_measurement_response(uint16_t transaction_id, uint32_t lmf_measurement_id) +{ + positioning_config_t positioning_config = RCconfig_nr_positioning(); + nrppa_measurement_resp_t resp = {0}; + resp.transaction_id = transaction_id; + resp.lmf_measurement_id = lmf_measurement_id; + resp.ran_measurement_id = 1; + resp.measurement_response_list = calloc_or_fail(1, sizeof(*resp.measurement_response_list)); + uint32_t meas_response_list_len = positioning_config.num_trp; + resp.measurement_response_list->measurement_response_list_length = meas_response_list_len; + resp.measurement_response_list->measurement_response_item = + calloc_or_fail(meas_response_list_len, sizeof(*resp.measurement_response_list->measurement_response_item)); + for (int i = 0; i < meas_response_list_len; i++) { + nrppa_measurement_response_item_t *meas_response_item = &resp.measurement_response_list->measurement_response_item[i]; + meas_response_item->trp_id = positioning_config.trps[i].id; + + nrppa_measurement_result_t *MeasurementResult = &meas_response_item->measurement_result; + uint32_t meas_result_length = 4; + MeasurementResult->measurement_result_item_length = meas_result_length; + MeasurementResult->measurement_result_item = + calloc_or_fail(meas_result_length, sizeof(*MeasurementResult->measurement_result_item)); + + // Angle of arrival + nrppa_measurement_result_item_t *measurement_result_item = &MeasurementResult->measurement_result_item[0]; + nrppa_measured_results_value_t *measuredResultsValue = &measurement_result_item->measured_results_value; + measuredResultsValue->present = NRPPA_MEASURED_RESULTS_VALUE_PR_UL_ANGLEOFARRIVAL; + nrppa_ul_aoa_t *uL_AngleOfArrival = &measuredResultsValue->choice.ul_angle_of_arrival; + uL_AngleOfArrival->azimuth_aoa = 700 + i; + uL_AngleOfArrival->zenith_aoa = calloc_or_fail(1, sizeof(*uL_AngleOfArrival->zenith_aoa)); + *uL_AngleOfArrival->zenith_aoa = 450 + i; + + nrppa_time_stamp_t *timeStamp = &measurement_result_item->time_stamp; + timeStamp->system_frame_number = 100; + timeStamp->slot_index.present = NRPPA_TIME_STAMP_SLOT_INDEX_PR_SCS_30; + timeStamp->slot_index.choice.scs_30 = 15; + + // UL SRS RSRP + measurement_result_item = &MeasurementResult->measurement_result_item[1]; + measuredResultsValue = &measurement_result_item->measured_results_value; + measuredResultsValue->present = NRPPA_MEASURED_RESULTS_VALUE_PR_UL_SRS_RSRP; + measuredResultsValue->choice.ul_srs_rsrp = 100 + i; + + timeStamp = &measurement_result_item->time_stamp; + timeStamp->system_frame_number = 101; + timeStamp->slot_index.present = NRPPA_TIME_STAMP_SLOT_INDEX_PR_SCS_15; + timeStamp->slot_index.choice.scs_15 = 8; + + // UL RToA + measurement_result_item = &MeasurementResult->measurement_result_item[2]; + measuredResultsValue = &measurement_result_item->measured_results_value; + measuredResultsValue->present = NRPPA_MEASURED_RESULTS_VALUE_PR_UL_RTOA; + nrppa_ul_rtoa_measurement_t *uL_RTOA = &measuredResultsValue->choice.ul_rtoa; + uL_RTOA->present = NRPPA_ULRTOAMEAS_PR_K1; + uL_RTOA->choice.k1 = 98500 + i; + + timeStamp = &measurement_result_item->time_stamp; + timeStamp->system_frame_number = 102; + timeStamp->slot_index.present = NRPPA_TIME_STAMP_SLOT_INDEX_PR_SCS_60; + timeStamp->slot_index.choice.scs_60 = 31; + + // gNB RX-TX Time Diff + measurement_result_item = &MeasurementResult->measurement_result_item[3]; + measuredResultsValue = &measurement_result_item->measured_results_value; + measuredResultsValue->present = NRPPA_MEASURED_RESULTS_VALUE_PR_GNB_RXTXTIMEDIFF; + nrppa_gnb_rx_tx_time_diff_t *gNB_RxTxTimeDiff = &measuredResultsValue->choice.gnb_rx_tx_time_diff; + gNB_RxTxTimeDiff->present = NRPPA_GNBRXTXTIMEDIFFMEAS_PR_K3; + gNB_RxTxTimeDiff->choice.k3 = 98412 + i; + + timeStamp = &measurement_result_item->time_stamp; + timeStamp->system_frame_number = 103; + timeStamp->slot_index.present = NRPPA_TIME_STAMP_SLOT_INDEX_PR_SCS_120; + timeStamp->slot_index.choice.scs_120 = 70; + } + return resp; +} + // Initializing UE NAS Context with simulated SIM data nr_ue_nas_t *simulated_ue_nas = NULL; void init_ue_nas_context(void) @@ -589,6 +666,15 @@ void *rrc_gnb_task(void *args_p) itti_send_msg_to_task(TASK_NRPPA, 0, msg_p_resp); free_positioning_activation_request(req); break; + case NRPPA_MEASUREMENT_REQ: + nrppa_measurement_req_t *m_req = &NRPPA_MEASUREMENT_REQ(msg_p); + LOG_I(NR_RRC, "Received NRPPA_MEASUREMENT_REQ transaction_id %d\n", m_req->transaction_id); + msg_p_resp = itti_alloc_new_message(TASK_RRC_GNB, 0, NRPPA_MEASUREMENT_RESP); + NRPPA_MEASUREMENT_RESP(msg_p_resp) = fill_measurement_response(m_req->transaction_id, m_req->lmf_measurement_id); + LOG_I(NR_RRC, "Sending NRPPA_MEASUREMENT_RESP to TASK_NRPPA\n"); + itti_send_msg_to_task(TASK_NRPPA, 0, msg_p_resp); + free_measurement_request(m_req); + break; default: LOG_E(NR_RRC, "[gNB %ld] Received unexpected message %s\n", instance, msg_name_p); break; From 7de93489cf50ab4f7a30f615530a4cd20d2b8030 Mon Sep 17 00:00:00 2001 From: Rakesh Mundlamuri Date: Tue, 24 Feb 2026 21:08:57 +0530 Subject: [PATCH 21/21] Add README for the nr-cu-nrppa tester --- doc/README.md | 5 ++- tests/nr-cu-nrppa/README.md | 81 +++++++++++++++++++++++++++++++++++++ 2 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 tests/nr-cu-nrppa/README.md diff --git a/doc/README.md b/doc/README.md index 8fc53eea24..13a9669f76 100644 --- a/doc/README.md +++ b/doc/README.md @@ -121,8 +121,9 @@ The other SDRs (AW2S, LimeSDR, ...) have no READMEs. ## Testing - [UnitTests.md](./UnitTests.md) explains the unit testing setup -- Component tests are under `tests/`. Currently, there is a simple CU-UP - tester, see the corresponding [README.md](../tests/nr-cuup/README.md). +- Component tests are under `tests/`. Currently, the following component tests are supported + - A simple CU-UP tester, see the corresponding [README.md](../tests/nr-cuup/README.md). + - A CU-NRPPA tester, see the corresponding [README.md](../tests/nr-cu-nrppa/README.md). - [TESTBenches.md](./TESTBenches.md) lists the CI setup and links to pipelines - The CI setup uses a [custom framework](../ci-scripts/README.md) to run end-to-end tests. diff --git a/tests/nr-cu-nrppa/README.md b/tests/nr-cu-nrppa/README.md new file mode 100644 index 0000000000..4ea780a20e --- /dev/null +++ b/tests/nr-cu-nrppa/README.md @@ -0,0 +1,81 @@ +This is a simple standalone tester for NRPPA and NGAP positioning messages. It connects to the AMF to perform NGAP and NRPPA encoding/decoding and validates the exchange of positioning data. + +[[_TOC_]] + +# Overview +From a schematic point of view, the tester and Core Network interaction looks like this: +``` + +-------+ +-------+ + | LMF |<--- HTTP POST---| User | + +-------+ +-------+ + | + | Nlmf + | + +-------+ + | AMF | + +-------+ + | + NGAP/NRPPA | + | + +-------+ + |tester | (nr-cu-nrppa-test) + +-------+ +``` +The tester is designed to validate the integration of NRPPA and NGAP messages required for 5G positioning (*3GPP 38.413 V16.0.0* and *3GPP 38.455 V16.7.1*). It acts as a simulated RAN node (like a CU) connecting to the 5G Core Network's AMF. + +The following messages are integrated and tested: +* **NGAP:** Uplink/Downlink UE Associated NRPPA Transport, Uplink/Downlink Non-UE Associated NRPPA Transport. +* **NRPPA:** TRP Information Request/Response, Positioning Information Request/Response, Positioning Activation Request/Response, Measurement Request/Response. + +A test scenario is fixed to these steps: +1. The 5G Core Network, specifically including the Location Management Function (LMF), is deployed via Docker. +2. The tester connects to the AMF and establishes the NGAP connection. +3. The user initiates a positioning procedure via a API call to the LMF. +4. The AMF and the tester exchange the required NGAP and NRPPA messages to determine location. + +# Usage +To run this test, you need to set up the Core Network and build the tester. + +**1. Core Network Deployment** + +Pull the required Docker images for the OAI 5G Core: + + docker pull oaisoftwarealliance/ims:latest + docker pull oaisoftwarealliance/oai-amf:develop + docker pull oaisoftwarealliance/oai-nrf:develop + docker pull oaisoftwarealliance/oai-smf:develop + docker pull oaisoftwarealliance/oai-udr:develop + docker pull oaisoftwarealliance/oai-upf:develop + docker pull oaisoftwarealliance/oai-udm:develop + docker pull oaisoftwarealliance/oai-ausf:develop + docker pull oaisoftwarealliance/oai-lmf:develop + +Deploy the network using the positioning compose file: + + cd doc/tutorial_resources/oai-cn5g + docker compose -f docker-compose-positioning.yaml up -d + +*(To undeploy later, run `docker compose -f docker-compose-positioning.yaml down -t 0`)* + +**2. Building the Tester** + +You can build the NRPPA tester like so: + + cd ~/openairinterface5g + mkdir build && cd build && cmake .. -GNinja && ninja nr-cu-nrppa-test + +**3. Running the Tester** + +Start the tester with the dedicated configuration file: + + LD_LIBRARY_PATH=. ./tests/nr-cu-nrppa/nr-cu-nrppa-test -O ../tests/nr-cu-nrppa/nr-nrppa-test.conf + +**4. Initiating the Procedure** + +Trigger the location determination by sending an HTTP POST request to the LMF: + + cd ~/openairinterface5g/doc/tutorial_resources/positioning/ + curl --http2-prior-knowledge -H "Content-Type: application/json" -d "@InputData.json" -X POST http://192.168.70.141:8080/nlmf-loc/v1/determine-location + +# Limitations +- The tester is a standalone validation tool (`nr-cu-nrppa-test`) and does not represent a fully integrated, end-to-end gNB positioning setup.