diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index e44e1dccb4..3557d1c0e7 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -671,4 +671,14 @@ typedef struct f1ap_reset_ack_t { //uint16_t criticality_diagnostics; // not implemented as of now } f1ap_reset_ack_t; +/* Structure of Position Information Transfer related NRPPA messages */ +/* IE structures for Positioning related messages as per TS 38.473 V16.3.1*/ + +typedef struct f1ap_positioning_information_req_s { + // IE 9.3.1.4 (mandatory) + uint32_t gNB_CU_ue_id; + // IE 9.3.1.5 (mandatory) + uint32_t gNB_DU_ue_id; +} f1ap_positioning_information_req_t; + #endif /* F1AP_MESSAGES_TYPES_H_ */ diff --git a/openair2/F1AP/lib/CMakeLists.txt b/openair2/F1AP/lib/CMakeLists.txt index 978f69fb29..0a46fa2bf0 100644 --- a/openair2/F1AP/lib/CMakeLists.txt +++ b/openair2/F1AP/lib/CMakeLists.txt @@ -3,6 +3,7 @@ add_library(f1ap_lib OBJECT f1ap_rrc_message_transfer.c f1ap_interface_management.c f1ap_ue_context.c + f1ap_positioning.c ) target_link_libraries(f1ap_lib PRIVATE asn1_f1ap ds) target_include_directories(f1ap_lib PUBLIC diff --git a/openair2/F1AP/lib/f1ap_positioning.c b/openair2/F1AP/lib/f1ap_positioning.c new file mode 100644 index 0000000000..a934c05e35 --- /dev/null +++ b/openair2/F1AP/lib/f1ap_positioning.c @@ -0,0 +1,143 @@ +/* + * 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 "f1ap_positioning.h" + +#include "f1ap_lib_common.h" +#include "f1ap_lib_includes.h" +#include "f1ap_messages_types.h" + +#include "common/utils/assertions.h" +#include "openair3/UTILS/conversions.h" +#include "common/utils/oai_asn1.h" +#include "common/utils/utils.h" +#include "common/utils/ds/byte_array.h" + +/** + * @brief Encode F1 positioning information request to ASN.1 + */ +F1AP_F1AP_PDU_t *encode_positioning_information_req(const f1ap_positioning_information_req_t *msg) +{ + F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + + /* Message Type */ + pdu->present = F1AP_F1AP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu->choice.initiatingMessage, tmp); + tmp->procedureCode = F1AP_ProcedureCode_id_PositioningInformationExchange; + tmp->criticality = F1AP_Criticality_reject; + tmp->value.present = F1AP_InitiatingMessage__value_PR_PositioningInformationRequest; + F1AP_PositioningInformationRequest_t *out = &tmp->value.choice.PositioningInformationRequest; + + /* mandatory : GNB_CU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningInformationRequestIEs_t, ie1); + ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; + ie1->criticality = F1AP_Criticality_reject; + ie1->value.present = F1AP_PositioningInformationRequestIEs__value_PR_GNB_CU_UE_F1AP_ID; + ie1->value.choice.GNB_CU_UE_F1AP_ID = msg->gNB_CU_ue_id; + + /* mandatory : GNB_DU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_PositioningInformationRequestIEs_t, ie2); + ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; + ie2->criticality = F1AP_Criticality_reject; + ie2->value.present = F1AP_PositioningInformationRequestIEs__value_PR_GNB_DU_UE_F1AP_ID; + ie2->value.choice.GNB_DU_UE_F1AP_ID = msg->gNB_DU_ue_id; + + return pdu; +} + +/** + * @brief Decode F1 positioning information request + */ +bool decode_positioning_information_req(const F1AP_F1AP_PDU_t *pdu, f1ap_positioning_information_req_t *out) +{ + DevAssert(out != NULL); + memset(out, 0, sizeof(*out)); + + F1AP_PositioningInformationRequest_t *in = &pdu->choice.initiatingMessage->value.choice.PositioningInformationRequest; + F1AP_PositioningInformationRequestIEs_t *ie; + + F1AP_LIB_FIND_IE(F1AP_PositioningInformationRequestIEs_t, + ie, + &in->protocolIEs.list, + F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, + true); + F1AP_LIB_FIND_IE(F1AP_PositioningInformationRequestIEs_t, + ie, + &in->protocolIEs.list, + F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, + true); + + for (int i = 0; i < in->protocolIEs.list.count; ++i) { + ie = in->protocolIEs.list.array[i]; + AssertError(ie != NULL, return false, "in->protocolIEs.list.array[i] is NULL"); + switch (ie->id) { + case F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningInformationRequestIEs__value_PR_GNB_CU_UE_F1AP_ID); + out->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; + break; + case F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_PositioningInformationRequestIEs__value_PR_GNB_DU_UE_F1AP_ID); + out->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; + break; + case F1AP_ProtocolIE_ID_id_RequestedSRSTransmissionCharacteristics: + PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld not handled, skipping\n", ie->id); + break; + default: + PRINT_ERROR("F1AP_ProtocolIE_ID_id %ld unknown, skipping\n", ie->id); + break; + } + } + + return true; +} + +/** + * @brief F1 positioning information request deep copy + */ +f1ap_positioning_information_req_t cp_positioning_information_req(const f1ap_positioning_information_req_t *orig) +{ + /* copy all mandatory fields that are not dynamic memory */ + f1ap_positioning_information_req_t cp = { + .gNB_CU_ue_id = orig->gNB_CU_ue_id, + .gNB_DU_ue_id = orig->gNB_DU_ue_id, + }; + + return cp; +} + +/** + * @brief F1 positioning information request equality check + */ +bool eq_positioning_information_req(const f1ap_positioning_information_req_t *a, const f1ap_positioning_information_req_t *b) +{ + _F1_EQ_CHECK_INT(a->gNB_CU_ue_id, b->gNB_CU_ue_id); + _F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id); + + return true; +} + +/** + * @brief Free Allocated F1 positioning information request + */ +void free_positioning_information_req(f1ap_positioning_information_req_t *msg) +{ + // nothing to free +} diff --git a/openair2/F1AP/lib/f1ap_positioning.h b/openair2/F1AP/lib/f1ap_positioning.h new file mode 100644 index 0000000000..e6fa6040db --- /dev/null +++ b/openair2/F1AP/lib/f1ap_positioning.h @@ -0,0 +1,36 @@ +/* + * 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 F1AP_POSITIONING_H_ +#define F1AP_POSITIONING_H_ + +#include +#include "f1ap_messages_types.h" + +struct F1AP_F1AP_PDU; + +struct F1AP_F1AP_PDU *encode_positioning_information_req(const f1ap_positioning_information_req_t *msg); +bool decode_positioning_information_req(const struct F1AP_F1AP_PDU *pdu, f1ap_positioning_information_req_t *out); +f1ap_positioning_information_req_t cp_positioning_information_req(const f1ap_positioning_information_req_t *orig); +bool eq_positioning_information_req(const f1ap_positioning_information_req_t *a, const f1ap_positioning_information_req_t *b); +void free_positioning_information_req(f1ap_positioning_information_req_t *msg); + +#endif /* F1AP_POSITIONING_H_ */ diff --git a/openair2/F1AP/tests/f1ap_lib_test.c b/openair2/F1AP/tests/f1ap_lib_test.c index 72ea809245..ca2d37eaf1 100644 --- a/openair2/F1AP/tests/f1ap_lib_test.c +++ b/openair2/F1AP/tests/f1ap_lib_test.c @@ -43,6 +43,7 @@ #include "lib/f1ap_rrc_message_transfer.h" #include "lib/f1ap_interface_management.h" #include "lib/f1ap_ue_context.h" +#include "lib/f1ap_positioning.h" void exit_function(const char *file, const char *function, const int line, const char *s, const int assert) { @@ -1268,6 +1269,34 @@ static void test_f1ap_ue_context_release_complete() printf("%s() successful\n", __func__); } +static void test_f1ap_positioning_information_request() +{ + f1ap_positioning_information_req_t orig = { + .gNB_CU_ue_id = 12, + .gNB_DU_ue_id = 19, + }; + F1AP_F1AP_PDU_t *f1enc = encode_positioning_information_req(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_positioning_information_req_t decoded = {0}; + bool ret = decode_positioning_information_req(f1dec, &decoded); + AssertFatal(ret, "decode_positioning_information_req(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_positioning_information_req(&orig, &decoded); + AssertFatal(ret, "eq_positioning_information_req(): decoded message doesn't match\n"); + free_positioning_information_req(&decoded); + + f1ap_positioning_information_req_t cp = cp_positioning_information_req(&orig); + ret = eq_positioning_information_req(&orig, &cp); + AssertFatal(ret, "eq_positioning_information_req(): copied message doesn't match\n"); + free_positioning_information_req(&orig); + free_positioning_information_req(&cp); + + printf("%s() successful\n", __func__); +} + int main() { test_initial_ul_rrc_message_transfer(); @@ -1294,5 +1323,6 @@ int main() test_f1ap_ue_context_release_request(); test_f1ap_ue_context_release_command(); test_f1ap_ue_context_release_complete(); + test_f1ap_positioning_information_request(); return 0; }