From 3554b33f37f6a313c78b85a0e3c699ca80ae2976 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Tue, 21 May 2024 10:35:02 +0200 Subject: [PATCH 01/46] Cleanup unused F1AP message transmission and system information files --- CMakeLists.txt | 3 -- .../f1ap_cu_warning_message_transmission.c | 31 ------------------- .../f1ap_cu_warning_message_transmission.h | 31 ------------------- openair2/F1AP/f1ap_du_system_information.c | 31 ------------------- openair2/F1AP/f1ap_du_system_information.h | 31 ------------------- .../f1ap_du_warning_message_transmission.c | 31 ------------------- .../f1ap_du_warning_message_transmission.h | 31 ------------------- 7 files changed, 189 deletions(-) delete mode 100644 openair2/F1AP/f1ap_cu_warning_message_transmission.c delete mode 100644 openair2/F1AP/f1ap_cu_warning_message_transmission.h delete mode 100644 openair2/F1AP/f1ap_du_system_information.c delete mode 100644 openair2/F1AP/f1ap_du_system_information.h delete mode 100644 openair2/F1AP/f1ap_du_warning_message_transmission.c delete mode 100644 openair2/F1AP/f1ap_du_warning_message_transmission.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 627b87593d..034bc89fc9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -435,14 +435,11 @@ add_library(f1ap ${F1AP_DIR}/f1ap_cu_rrc_message_transfer.c ${F1AP_DIR}/f1ap_cu_task.c ${F1AP_DIR}/f1ap_cu_ue_context_management.c - ${F1AP_DIR}/f1ap_cu_warning_message_transmission.c ${F1AP_DIR}/f1ap_du_interface_management.c ${F1AP_DIR}/f1ap_du_paging.c ${F1AP_DIR}/f1ap_du_rrc_message_transfer.c - ${F1AP_DIR}/f1ap_du_system_information.c ${F1AP_DIR}/f1ap_du_task.c ${F1AP_DIR}/f1ap_du_ue_context_management.c - ${F1AP_DIR}/f1ap_du_warning_message_transmission.c ${F1AP_DIR}/f1ap_encoder.c ${F1AP_DIR}/f1ap_handlers.c ${F1AP_DIR}/f1ap_itti_messaging.c) diff --git a/openair2/F1AP/f1ap_cu_warning_message_transmission.c b/openair2/F1AP/f1ap_cu_warning_message_transmission.c deleted file mode 100644 index 725bb4e1af..0000000000 --- a/openair2/F1AP/f1ap_cu_warning_message_transmission.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/*! \file f1ap_du_interface_management.h - * \brief f1ap interface management for DU - * \author EURECOM/NTUST - * \date 2018 - * \version 0.1 - * \company Eurecom - * \email: navid.nikaein@eurecom.fr, bing-kai.hong@eurecom.fr - * \note - * \warning - */ diff --git a/openair2/F1AP/f1ap_cu_warning_message_transmission.h b/openair2/F1AP/f1ap_cu_warning_message_transmission.h deleted file mode 100644 index b6bbedba2f..0000000000 --- a/openair2/F1AP/f1ap_cu_warning_message_transmission.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/*! \file f1ap_du_interface_management.h - * \brief f1ap interface management for DU - * \author EURECOM/NTUST - * \date 2018 - * \version 0.1 - * \company Eurecom - * \email: navid.nikaein@eurecom.fr, bing-kai.hong@eurecom.fr - * \note - * \warning - */ \ No newline at end of file diff --git a/openair2/F1AP/f1ap_du_system_information.c b/openair2/F1AP/f1ap_du_system_information.c deleted file mode 100644 index 725bb4e1af..0000000000 --- a/openair2/F1AP/f1ap_du_system_information.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/*! \file f1ap_du_interface_management.h - * \brief f1ap interface management for DU - * \author EURECOM/NTUST - * \date 2018 - * \version 0.1 - * \company Eurecom - * \email: navid.nikaein@eurecom.fr, bing-kai.hong@eurecom.fr - * \note - * \warning - */ diff --git a/openair2/F1AP/f1ap_du_system_information.h b/openair2/F1AP/f1ap_du_system_information.h deleted file mode 100644 index b6bbedba2f..0000000000 --- a/openair2/F1AP/f1ap_du_system_information.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/*! \file f1ap_du_interface_management.h - * \brief f1ap interface management for DU - * \author EURECOM/NTUST - * \date 2018 - * \version 0.1 - * \company Eurecom - * \email: navid.nikaein@eurecom.fr, bing-kai.hong@eurecom.fr - * \note - * \warning - */ \ No newline at end of file diff --git a/openair2/F1AP/f1ap_du_warning_message_transmission.c b/openair2/F1AP/f1ap_du_warning_message_transmission.c deleted file mode 100644 index 725bb4e1af..0000000000 --- a/openair2/F1AP/f1ap_du_warning_message_transmission.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/*! \file f1ap_du_interface_management.h - * \brief f1ap interface management for DU - * \author EURECOM/NTUST - * \date 2018 - * \version 0.1 - * \company Eurecom - * \email: navid.nikaein@eurecom.fr, bing-kai.hong@eurecom.fr - * \note - * \warning - */ diff --git a/openair2/F1AP/f1ap_du_warning_message_transmission.h b/openair2/F1AP/f1ap_du_warning_message_transmission.h deleted file mode 100644 index b6bbedba2f..0000000000 --- a/openair2/F1AP/f1ap_du_warning_message_transmission.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The OpenAirInterface Software Alliance licenses this file to You under - * the OAI Public License, Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.openairinterface.org/?page_id=698 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - *------------------------------------------------------------------------------- - * For more information about the OpenAirInterface (OAI) Software Alliance: - * contact@openairinterface.org - */ - -/*! \file f1ap_du_interface_management.h - * \brief f1ap interface management for DU - * \author EURECOM/NTUST - * \date 2018 - * \version 0.1 - * \company Eurecom - * \email: navid.nikaein@eurecom.fr, bing-kai.hong@eurecom.fr - * \note - * \warning - */ \ No newline at end of file From deb63888d9ba0b9de8820a785efe4f04be9199c7 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Mon, 27 May 2024 18:06:08 +0200 Subject: [PATCH 02/46] Cleanup of long-time unused F1AP interface management functions --- openair2/F1AP/f1ap_cu_interface_management.c | 50 +------------------ openair2/F1AP/f1ap_cu_interface_management.h | 26 ---------- openair2/F1AP/f1ap_du_interface_management.c | 51 -------------------- openair2/F1AP/f1ap_du_interface_management.h | 28 ----------- openair2/F1AP/f1ap_handlers.c | 4 +- 5 files changed, 3 insertions(+), 156 deletions(-) diff --git a/openair2/F1AP/f1ap_cu_interface_management.c b/openair2/F1AP/f1ap_cu_interface_management.c index 2e73172e2b..075d3c5671 100644 --- a/openair2/F1AP/f1ap_cu_interface_management.c +++ b/openair2/F1AP/f1ap_cu_interface_management.c @@ -35,36 +35,14 @@ #include "f1ap_itti_messaging.h" #include "f1ap_cu_interface_management.h" -int CU_send_RESET(sctp_assoc_t assoc_id, const f1ap_reset_t *reset) -{ - AssertFatal(1==0,"Not implemented yet\n"); -} - int CU_handle_RESET_ACKNOWLEDGE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { - AssertFatal(1==0,"Not implemented yet\n"); -} - -int CU_handle_RESET(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) -{ - AssertFatal(1==0,"Not implemented yet\n"); + AssertFatal(1 == 0, "Not implemented yet\n"); } int CU_send_RESET_ACKNOWLEDGE(sctp_assoc_t assoc_id, const f1ap_reset_ack_t *ack) { - AssertFatal(1==0,"Not implemented yet\n"); -} - -/* - Error Indication -*/ -int CU_handle_ERROR_INDICATION(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) -{ - AssertFatal(1==0,"Not implemented yet\n"); -} - -int CU_send_ERROR_INDICATION(sctp_assoc_t assoc_id, F1AP_ErrorIndication_t *ErrorIndication) { - AssertFatal(1==0,"Not implemented yet\n"); + AssertFatal(1 == 0, "Not implemented yet\n"); } static uint8_t *cp_octet_string(const OCTET_STRING_t *os, int *len) @@ -790,12 +768,6 @@ int CU_handle_gNB_DU_CONFIGURATION_UPDATE(instance_t instance, sctp_assoc_t asso return 0; } -int CU_send_gNB_DU_CONFIGURATION_FAILURE(sctp_assoc_t assoc_id, - f1ap_gnb_du_configuration_update_failure_t *GNBDUConfigurationUpdateFailure) -{ - AssertFatal(1==0,"Not implemented yet\n"); -} - int CU_send_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE( sctp_assoc_t assoc_id, f1ap_gnb_du_configuration_update_acknowledge_t *GNBDUConfigurationUpdateAcknowledge) @@ -931,11 +903,6 @@ int CU_send_gNB_CU_CONFIGURATION_UPDATE(sctp_assoc_t assoc_id, f1ap_gnb_cu_confi return 0; } -int CU_handle_gNB_CU_CONFIGURATION_UPDATE_FAILURE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) -{ - AssertFatal(1==0,"Not implemented yet\n"); -} - int CU_handle_gNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, @@ -944,16 +911,3 @@ int CU_handle_gNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(instance_t instance, LOG_I(F1AP,"Cell Configuration ok (assoc_id %d)\n",assoc_id); return(0); } - -int CU_handle_gNB_DU_RESOURCE_COORDINATION_REQUEST(instance_t instance, - sctp_assoc_t assoc_id, - uint32_t stream, - F1AP_F1AP_PDU_t *pdu) -{ - AssertFatal(0, "Not implemented yet\n"); -} - -int CU_send_gNB_DU_RESOURCE_COORDINATION_RESPONSE(sctp_assoc_t assoc_id, - F1AP_GNBDUResourceCoordinationResponse_t *GNBDUResourceCoordinationResponse) { - AssertFatal(0, "Not implemented yet\n"); -} diff --git a/openair2/F1AP/f1ap_cu_interface_management.h b/openair2/F1AP/f1ap_cu_interface_management.h index 11a45868e1..9d0bf4a391 100644 --- a/openair2/F1AP/f1ap_cu_interface_management.h +++ b/openair2/F1AP/f1ap_cu_interface_management.h @@ -36,17 +36,9 @@ /* * Reset */ -int CU_send_RESET(sctp_assoc_t assoc_id, const f1ap_reset_t *reset); int CU_handle_RESET_ACKNOWLEDGE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu); -int CU_handle_RESET(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu); int CU_send_RESET_ACKNOWLEDGE(sctp_assoc_t assoc_id, const f1ap_reset_ack_t *ack); -/* - * Error Indication - */ -int CU_handle_ERROR_INDICATION(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu); -int CU_send_ERROR_INDICATION(sctp_assoc_t assoc_id, F1AP_ErrorIndication_t *ErrorIndication); - /* * F1 Setup */ @@ -61,9 +53,6 @@ int CU_send_F1_SETUP_FAILURE(sctp_assoc_t assoc_id, const f1ap_setup_failure_t * */ int CU_handle_gNB_DU_CONFIGURATION_UPDATE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu); -int CU_send_gNB_DU_CONFIGURATION_FAILURE(sctp_assoc_t assoc_id, - f1ap_gnb_du_configuration_update_failure_t *GNBDUConfigurationUpdateFailure); - int CU_send_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE( sctp_assoc_t assoc_id, f1ap_gnb_du_configuration_update_acknowledge_t *GNBDUConfigurationUpdateAcknowledge); @@ -72,25 +61,10 @@ int CU_send_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE( * gNB-CU Configuration Update */ int CU_send_gNB_CU_CONFIGURATION_UPDATE(sctp_assoc_t assoc_id, f1ap_gnb_cu_configuration_update_t *f1ap_gnb_cu_configuration_update); -int CU_handle_gNB_CU_CONFIGURATION_UPDATE_FAILURE(instance_t instance, - sctp_assoc_t assoc_id, - uint32_t stream, - F1AP_F1AP_PDU_t *pdu); int CU_handle_gNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu); -/* - * gNB-DU Resource Coordination - */ -int CU_handle_gNB_DU_RESOURCE_COORDINATION_REQUEST(instance_t instance, - sctp_assoc_t assoc_id, - uint32_t stream, - F1AP_F1AP_PDU_t *pdu); - -int CU_send_gNB_DU_RESOURCE_COORDINATION_RESPONSE(sctp_assoc_t assoc_id, - F1AP_GNBDUResourceCoordinationResponse_t *GNBDUResourceCoordinationResponse); - #endif /* F1AP_CU_INTERFACE_MANAGEMENT_H_ */ diff --git a/openair2/F1AP/f1ap_du_interface_management.c b/openair2/F1AP/f1ap_du_interface_management.c index f560754bf3..673d37b637 100644 --- a/openair2/F1AP/f1ap_du_interface_management.c +++ b/openair2/F1AP/f1ap_du_interface_management.c @@ -160,30 +160,6 @@ int DU_send_RESET_ACKNOWLEDGE(sctp_assoc_t assoc_id, const f1ap_reset_ack_t *ack return 0; } -int DU_send_RESET(sctp_assoc_t assoc_id, const f1ap_reset_t *reset) -{ - AssertFatal(1==0,"Not implemented yet\n"); -} - -int DU_handle_RESET_ACKNOWLEDGE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) -{ - AssertFatal(1==0,"Not implemented yet\n"); -} - -/* - Error Indication -*/ - -int DU_send_ERROR_INDICATION(sctp_assoc_t assoc_id, F1AP_F1AP_PDU_t *pdu_p) -{ - AssertFatal(1==0,"Not implemented yet\n"); -} - -int DU_handle_ERROR_INDICATION(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) -{ - AssertFatal(1==0,"Not implemented yet\n"); -} - static F1AP_Served_Cell_Information_t encode_served_cell_info(const f1ap_served_cell_info_t *c) { /* 4.1.1 served cell Information */ @@ -744,19 +720,6 @@ int DU_send_gNB_DU_CONFIGURATION_UPDATE(sctp_assoc_t assoc_id, const f1ap_gnb_du return 0; } -int DU_handle_gNB_DU_CONFIGURATION_FAILURE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) -{ - AssertFatal(1==0,"Not implemented yet\n"); -} - -int DU_handle_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(instance_t instance, - sctp_assoc_t assoc_id, - uint32_t stream, - F1AP_F1AP_PDU_t *pdu) -{ - AssertFatal(1==0,"Not implemented yet\n"); -} - int DU_handle_gNB_CU_CONFIGURATION_UPDATE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { LOG_D(F1AP, "DU_handle_gNB_CU_CONFIGURATION_UPDATE\n"); @@ -956,17 +919,3 @@ int DU_send_gNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE( f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); return 0; } - -int DU_send_gNB_DU_RESOURCE_COORDINATION_REQUEST(sctp_assoc_t assoc_id, - F1AP_GNBDUResourceCoordinationRequest_t *GNBDUResourceCoordinationRequest) -{ - AssertFatal(0, "Not implemented yet\n"); -} - -int DU_handle_gNB_DU_RESOURCE_COORDINATION_RESPONSE(instance_t instance, - sctp_assoc_t assoc_id, - uint32_t stream, - F1AP_F1AP_PDU_t *pdu) -{ - AssertFatal(0, "Not implemented yet\n"); -} diff --git a/openair2/F1AP/f1ap_du_interface_management.h b/openair2/F1AP/f1ap_du_interface_management.h index f8d7eafb02..0cbf6adae2 100644 --- a/openair2/F1AP/f1ap_du_interface_management.h +++ b/openair2/F1AP/f1ap_du_interface_management.h @@ -38,14 +38,6 @@ */ int DU_handle_RESET(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu); int DU_send_RESET_ACKNOWLEDGE(sctp_assoc_t assoc_id, const f1ap_reset_ack_t *ack); -int DU_send_RESET(sctp_assoc_t assoc_id, const f1ap_reset_t *reset); -int DU_handle_RESET_ACKNOWLEDGE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu); - -/* - * Error Indication - */ -int DU_send_ERROR_INDICATION(sctp_assoc_t assoc_id, F1AP_F1AP_PDU_t *pdu_p); -int DU_handle_ERROR_INDICATION(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu); /* * F1 Setup @@ -61,13 +53,6 @@ int DU_handle_F1_SETUP_FAILURE(instance_t instance, sctp_assoc_t assoc_id, uint3 */ int DU_send_gNB_DU_CONFIGURATION_UPDATE(sctp_assoc_t assoc_id, const f1ap_gnb_du_configuration_update_t *upd); -int DU_handle_gNB_DU_CONFIGURATION_FAILURE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu); - -int DU_handle_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(instance_t instance, - sctp_assoc_t assoc_id, - uint32_t stream, - F1AP_F1AP_PDU_t *pdu); - /* * gNB-CU Configuration Update */ @@ -79,17 +64,4 @@ int DU_send_gNB_CU_CONFIGURATION_UPDATE_FAILURE(sctp_assoc_t assoc_id, int DU_send_gNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(sctp_assoc_t assoc_id, f1ap_gnb_cu_configuration_update_acknowledge_t *GNBCUConfigurationUpdateAcknowledge); - - -/* - * gNB-DU Resource Coordination - */ -int DU_send_gNB_DU_RESOURCE_COORDINATION_REQUEST(sctp_assoc_t assoc_id, - F1AP_GNBDUResourceCoordinationRequest_t *GNBDUResourceCoordinationRequest); - -int DU_handle_gNB_DU_RESOURCE_COORDINATION_RESPONSE(instance_t instance, - sctp_assoc_t assoc_id, - uint32_t stream, - F1AP_F1AP_PDU_t *pdu); - #endif /* F1AP_DU_INTERFACE_MANAGEMENT_H_ */ diff --git a/openair2/F1AP/f1ap_handlers.c b/openair2/F1AP/f1ap_handlers.c index bfaa9959dc..544e763c49 100644 --- a/openair2/F1AP/f1ap_handlers.c +++ b/openair2/F1AP/f1ap_handlers.c @@ -49,9 +49,7 @@ static const f1ap_message_processing_t f1ap_messages_processing[][3] = { {CU_handle_F1_SETUP_REQUEST, DU_handle_F1_SETUP_RESPONSE, DU_handle_F1_SETUP_FAILURE}, /* F1Setup */ {0, 0, 0}, /* ErrorIndication */ {CU_handle_gNB_DU_CONFIGURATION_UPDATE, 0, 0}, /* gNBDUConfigurationUpdate */ - {DU_handle_gNB_CU_CONFIGURATION_UPDATE, - CU_handle_gNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE, - CU_handle_gNB_CU_CONFIGURATION_UPDATE_FAILURE}, /* gNBCUConfigurationUpdate */ + {DU_handle_gNB_CU_CONFIGURATION_UPDATE, CU_handle_gNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE, 0}, /* gNBCUConfigurationUpdate */ {DU_handle_UE_CONTEXT_SETUP_REQUEST, CU_handle_UE_CONTEXT_SETUP_RESPONSE, 0}, /* UEContextSetup */ {DU_handle_UE_CONTEXT_RELEASE_COMMAND, CU_handle_UE_CONTEXT_RELEASE_COMPLETE, 0}, /* UEContextRelease */ {DU_handle_UE_CONTEXT_MODIFICATION_REQUEST, CU_handle_UE_CONTEXT_MODIFICATION_RESPONSE, 0}, /* UEContextModification */ From bacf713299d5025bc46398301c48bb257718e624 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 29 Apr 2024 16:35:00 +0200 Subject: [PATCH 03/46] Use char * for DU/CU IP address The previously used net_ip_address_t type is limited to some bytes, but the CU name might be longer. Use char * to allow longer DNS names. Also, this type separates IPv4/v6, which is not necessary, as it is now handled by the same C API (getaddrinfo()), since !2635. Co-authored-by: Guido Casati --- openair2/COMMON/f1ap_messages_types.h | 6 ++---- openair2/F1AP/f1ap_du_task.c | 17 ++++++++++++++--- openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c | 12 ++++-------- openair3/SCTP/sctp_eNB_task.c | 2 +- 4 files changed, 21 insertions(+), 16 deletions(-) diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index 3b6082e221..dc444366ea 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -83,11 +83,9 @@ #define F1AP_MAX_NO_OF_INDIVIDUAL_CONNECTIONS_TO_RESET 65536 -typedef net_ip_address_t f1ap_net_ip_address_t; - typedef struct f1ap_net_config_t { - f1ap_net_ip_address_t CU_f1_ip_address; - f1ap_net_ip_address_t DU_f1c_ip_address; + char *CU_f1_ip_address; + char *DU_f1c_ip_address; char *DU_f1u_ip_address; uint16_t CUport; uint16_t DUport; diff --git a/openair2/F1AP/f1ap_du_task.c b/openair2/F1AP/f1ap_du_task.c index ff188e52df..02e23c0281 100644 --- a/openair2/F1AP/f1ap_du_task.c +++ b/openair2/F1AP/f1ap_du_task.c @@ -44,7 +44,7 @@ static instance_t du_create_gtpu_instance_to_cu(const f1ap_net_config_t *nc) { openAddr_t tmp = {0}; strncpy(tmp.originHost, nc->DU_f1u_ip_address, sizeof(tmp.originHost) - 1); - strncpy(tmp.destinationHost, nc->CU_f1_ip_address.ipv4_address, sizeof(tmp.destinationHost) - 1); + strncpy(tmp.destinationHost, nc->CU_f1_ip_address, sizeof(tmp.destinationHost) - 1); sprintf(tmp.originService, "%d", nc->DUport); sprintf(tmp.destinationService, "%d", nc->CUport); return gtpv1Init(tmp); @@ -63,9 +63,20 @@ void du_task_send_sctp_association_req(instance_t instance, f1ap_net_config_t *n sctp_new_association_req_p->in_streams = 2; //du_inst->sctp_in_streams; sctp_new_association_req_p->out_streams = 2; //du_inst->sctp_out_streams; // remote - memcpy(&sctp_new_association_req_p->remote_address, &nc->CU_f1_ip_address, sizeof(nc->CU_f1_ip_address)); + sctp_new_association_req_p->remote_address.ipv4 = 1; + strncpy(sctp_new_association_req_p->remote_address.ipv4_address, + nc->CU_f1_ip_address, + sizeof(sctp_new_association_req_p->remote_address.ipv4_address) - 1); // local - memcpy(&sctp_new_association_req_p->local_address, &nc->DU_f1c_ip_address, sizeof(nc->DU_f1c_ip_address)); + sctp_new_association_req_p->local_address.ipv4 = 1; + strncpy(sctp_new_association_req_p->local_address.ipv4_address, + nc->DU_f1c_ip_address, + sizeof(sctp_new_association_req_p->local_address.ipv4_address) - 1); + LOG_D(F1AP, + "Local IPv4 Address: %s, Remote IPv4 Address: %s\n", + sctp_new_association_req_p->local_address.ipv4_address, + sctp_new_association_req_p->remote_address.ipv4_address); + // du_f1ap_register_to_sctp itti_send_msg_to_task(TASK_SCTP, instance, message_p); } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c index 742f85c390..3fe7fcf91a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c @@ -33,20 +33,16 @@ static f1ap_net_config_t read_DU_IP_config(const eth_params_t* f1_params, const { f1ap_net_config_t nc = {0}; - nc.CU_f1_ip_address.ipv6 = 0; - nc.CU_f1_ip_address.ipv4 = 1; - strcpy(nc.CU_f1_ip_address.ipv4_address, f1_params->remote_addr); + nc.CU_f1_ip_address= strdup(f1_params->remote_addr); nc.CUport = f1_params->remote_portd; - nc.DU_f1c_ip_address.ipv6 = 0; - nc.DU_f1c_ip_address.ipv4 = 1; - strcpy(nc.DU_f1c_ip_address.ipv4_address, f1_params->my_addr); + nc.DU_f1c_ip_address = strdup(f1_params->my_addr); nc.DU_f1u_ip_address = strdup(f1u_ip_addr); nc.DUport = f1_params->my_portd; LOG_I(F1AP, "F1-C DU IPaddr %s, connect to F1-C CU %s, binding GTP to %s\n", - nc.DU_f1c_ip_address.ipv4_address, - nc.CU_f1_ip_address.ipv4_address, + nc.DU_f1c_ip_address, + nc.CU_f1_ip_address, nc.DU_f1u_ip_address); // sctp_in_streams/sctp_out_streams are given by SCTP layer diff --git a/openair3/SCTP/sctp_eNB_task.c b/openair3/SCTP/sctp_eNB_task.c index a6d3a11a39..530b3ea6b0 100644 --- a/openair3/SCTP/sctp_eNB_task.c +++ b/openair3/SCTP/sctp_eNB_task.c @@ -394,7 +394,7 @@ static void sctp_handle_new_association_req(const instance_t instance, struct addrinfo *serv; int status = getaddrinfo(local, NULL, &hints, &serv); - AssertFatal(status == 0, "getaddrinfo() failed: %s\n", gai_strerror(status)); + AssertFatal(status == 0, "getaddrinfo(%s) failed: %s\n", local, gai_strerror(status)); int sd; struct addrinfo *p = NULL; From c9da5aabff084fa77e3e6d9737d00bebe99a54c2 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 29 Apr 2024 16:43:25 +0200 Subject: [PATCH 04/46] Use primitive type for TEID teid_t is defined in platfrom_types.h, which defines a bunch of 4G-specific things. In an attempt to decouple from 4G types, do not use it. --- openair2/COMMON/f1ap_messages_types.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index dc444366ea..d8c832e6e5 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -344,7 +344,7 @@ typedef struct f1ap_ul_rrc_message_s { typedef struct f1ap_up_tnl_s { in_addr_t tl_address; // currently only IPv4 supported - teid_t teid; + uint32_t teid; uint16_t port; } f1ap_up_tnl_t; From 4b5ea6dcf8528e3eaf58ec774a3a81910655a01b Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 29 Apr 2024 16:56:55 +0200 Subject: [PATCH 05/46] Fix header inclusion: NGAP message types depends on S1AP --- openair2/COMMON/f1ap_messages_types.h | 1 - openair2/COMMON/ngap_messages_types.h | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index d8c832e6e5..e71c0eab64 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -24,7 +24,6 @@ #include #include -#include "s1ap_messages_types.h" #include "ngap_messages_types.h" //-------------------------------------------------------------------------------------------// diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h index 861f5e6d2c..99d9d1dc0c 100644 --- a/openair2/COMMON/ngap_messages_types.h +++ b/openair2/COMMON/ngap_messages_types.h @@ -33,6 +33,7 @@ #include "common/platform_types.h" #include "common/ngran_types.h" #include "LTE_asn_constant.h" +#include "s1ap_messages_types.h" //-------------------------------------------------------------------------------------------// // Defines to access message fields. From da6b1a4be4cb941b3eb39c4584383be79d22a06c Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 28 Aug 2024 17:48:20 +0200 Subject: [PATCH 06/46] Fixes to SI message struct item in CU messages * num_SI is the size of the list of gNB-CU System Information messages * the new struct member is an array, sized after the maximum nb of SIB types, which contains the SI container, the container length and the SIB type --- openair2/COMMON/f1ap_messages_types.h | 16 +++++-- openair2/F1AP/f1ap_cu_interface_management.c | 44 ++++++++++++-------- openair2/F1AP/f1ap_du_interface_management.c | 29 +++++++------ 3 files changed, 53 insertions(+), 36 deletions(-) diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index e71c0eab64..c3cc837f4c 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -81,6 +81,8 @@ #define F1AP_MAX_NO_UE_ID 1024 #define F1AP_MAX_NO_OF_INDIVIDUAL_CONNECTIONS_TO_RESET 65536 +/* 9.3.1.42 of 3GPP TS 38.473 - gNB-CU System Information */ +#define F1AP_MAX_NO_SIB_TYPES 32 typedef struct f1ap_net_config_t { char *CU_f1_ip_address; @@ -176,6 +178,14 @@ typedef struct f1ap_du_register_req_t { f1ap_net_config_t net_config; } f1ap_du_register_req_t; +typedef struct f1ap_sib_msg_t { + /// RRC container with system information owned by gNB-CU + uint8_t *SI_container; + int SI_container_length; + /// SIB block type, e.g. 2 for sibType2 + int SI_type; +} f1ap_sib_msg_t; + typedef struct served_cells_to_activate_s { f1ap_plmn_t plmn; // NR Global Cell Id @@ -184,10 +194,8 @@ typedef struct served_cells_to_activate_s { uint16_t nrpci; /// num SI messages per DU cell uint8_t num_SI; - /// SI message containers (up to 21 messages per cell) - uint8_t *SI_container[21]; - int SI_container_length[21]; - int SI_type[21]; + /// gNB-CU System Information message (up to 32 messages per cell) + f1ap_sib_msg_t SI_msg[F1AP_MAX_NO_SIB_TYPES]; } served_cells_to_activate_t; typedef struct f1ap_setup_resp_s { diff --git a/openair2/F1AP/f1ap_cu_interface_management.c b/openair2/F1AP/f1ap_cu_interface_management.c index 075d3c5671..afd2775863 100644 --- a/openair2/F1AP/f1ap_cu_interface_management.c +++ b/openair2/F1AP/f1ap_cu_interface_management.c @@ -322,14 +322,22 @@ int CU_send_F1_SETUP_RESPONSE(sctp_assoc_t assoc_id, f1ap_setup_resp_t *f1ap_set // for (int sIBtype=2;sIBtype<33;sIBtype++) { //21 ? 33 ? for (int sIBtype=2; sIBtype<21; sIBtype++) { - if (f1ap_setup_resp->cells_to_activate[i].SI_container[sIBtype]!=NULL) { - AssertFatal(sIBtype < 6 || sIBtype == 9, "Illegal SI type %d\n",sIBtype); - asn1cSequenceAdd(gNB_CUSystemInformation->sibtypetobeupdatedlist.list, F1AP_SibtypetobeupdatedListItem_t, sib_item); - sib_item->sIBtype = sIBtype; - OCTET_STRING_fromBuf(&sib_item->sIBmessage, - (const char *)f1ap_setup_resp->cells_to_activate[i].SI_container[sIBtype], - f1ap_setup_resp->cells_to_activate[i].SI_container_length[sIBtype]); - LOG_D(F1AP, "f1ap_setup_resp->SI_container_length[%d][%d] = %d \n", i,sIBtype,f1ap_setup_resp->cells_to_activate[i].SI_container_length[sIBtype]); + for (int n = 0; n < f1ap_setup_resp->cells_to_activate[i].num_SI; n++) { + if (f1ap_setup_resp->cells_to_activate[i].SI_msg[n].SI_container != NULL) { + if (f1ap_setup_resp->cells_to_activate[i].SI_msg[n].SI_type > 6 + && f1ap_setup_resp->cells_to_activate[i].SI_msg[n].SI_type != 9) { + asn1cSequenceAdd(gNB_CUSystemInformation->sibtypetobeupdatedlist.list, F1AP_SibtypetobeupdatedListItem_t, sib_item); + sib_item->sIBtype = f1ap_setup_resp->cells_to_activate[i].SI_msg[n].SI_type; + OCTET_STRING_fromBuf(&sib_item->sIBmessage, + (const char *)f1ap_setup_resp->cells_to_activate[i].SI_msg[n].SI_container, + f1ap_setup_resp->cells_to_activate[i].SI_msg[n].SI_container_length); + LOG_D(F1AP, + "f1ap_setup_resp->cells_to_activate[%d].SI_msg[%d].SI_container_length = %d \n", + i, + n, + f1ap_setup_resp->cells_to_activate[i].SI_msg[n].SI_container_length); + } + } } } } @@ -875,16 +883,18 @@ int CU_send_gNB_CU_CONFIGURATION_UPDATE(sctp_assoc_t assoc_id, f1ap_gnb_cu_confi //printf("\n"); // for (int sIBtype=2;sIBtype<33;sIBtype++) { //21 ? 33 ? - for (int sIBtype=2; sIBtype<21; sIBtype++) { - if (f1ap_gnb_cu_configuration_update->cells_to_activate[i].SI_container[sIBtype]!=NULL) { - AssertFatal(sIBtype < 6 || sIBtype == 9, "Illegal SI type %d\n",sIBtype); + for (int j = 0; j < sizeofArray(f1ap_gnb_cu_configuration_update->cells_to_activate[i].SI_msg); j++) { + f1ap_sib_msg_t *SI_msg = &f1ap_gnb_cu_configuration_update->cells_to_activate[i].SI_msg[j]; + if (SI_msg->SI_container != NULL) { asn1cSequenceAdd(gNB_CUSystemInformation->sibtypetobeupdatedlist.list, F1AP_SibtypetobeupdatedListItem_t, sib_item); - sib_item->sIBtype = sIBtype; - OCTET_STRING_fromBuf(&sib_item->sIBmessage, - (const char *)f1ap_gnb_cu_configuration_update->cells_to_activate[i].SI_container[sIBtype], - f1ap_gnb_cu_configuration_update->cells_to_activate[i].SI_container_length[sIBtype]); - LOG_D(F1AP, "f1ap_setup_resp->SI_container_length[%d][%d] = %d \n", i,sIBtype, - f1ap_gnb_cu_configuration_update->cells_to_activate[i].SI_container_length[sIBtype]); + sib_item->sIBtype = SI_msg->SI_type; + AssertFatal(sib_item->sIBtype < 6 || sib_item->sIBtype == 9, "Illegal SI type %ld\n", sib_item->sIBtype); + OCTET_STRING_fromBuf(&sib_item->sIBmessage, (const char *)SI_msg->SI_container, SI_msg->SI_container_length); + LOG_D(F1AP, + "f1ap_gnb_cu_configuration_update->SI_container_length[%d][sIBtype %ld] = %d \n", + i, + sib_item->sIBtype, + SI_msg->SI_container_length); } } } diff --git a/openair2/F1AP/f1ap_du_interface_management.c b/openair2/F1AP/f1ap_du_interface_management.c index 673d37b637..56cb9d0e7b 100644 --- a/openair2/F1AP/f1ap_du_interface_management.c +++ b/openair2/F1AP/f1ap_du_interface_management.c @@ -525,15 +525,15 @@ int DU_handle_F1_SETUP_RESPONSE(instance_t instance, sctp_assoc_t assoc_id, uint resp.cells_to_activate[i].plmn.mnc, resp.cells_to_activate[i].nr_cellid, resp.cells_to_activate[i].num_SI); - - for (int si = 0; si < gNB_CUSystemInformation->sibtypetobeupdatedlist.list.count; si++) { - F1AP_SibtypetobeupdatedListItem_t *sib_item = gNB_CUSystemInformation->sibtypetobeupdatedlist.list.array[si]; - size_t size = sib_item->sIBmessage.size; - resp.cells_to_activate[i].SI_container_length[si] = size; - LOG_D(F1AP, "F1AP: SI_container_length[%d][%ld] %ld bytes\n", i, sib_item->sIBtype, size); - resp.cells_to_activate[i].SI_container[si] = malloc(resp.cells_to_activate[i].SI_container_length[si]); - memcpy(resp.cells_to_activate[i].SI_container[si], sib_item->sIBmessage.buf, size); - resp.cells_to_activate[i].SI_type[si]=sib_item->sIBtype; + for (int s = 0; s < resp.cells_to_activate[i].num_SI; s++) { + F1AP_SibtypetobeupdatedListItem_t *sib_item = gNB_CUSystemInformation->sibtypetobeupdatedlist.list.array[s]; + f1ap_sib_msg_t *SI_msg = &resp.cells_to_activate[i].SI_msg[s]; + SI_msg->SI_container = calloc(sib_item->sIBmessage.size, sizeof(uint8_t)); + AssertFatal(SI_msg->SI_container != NULL, "out of memory\n"); + memcpy(SI_msg->SI_container, sib_item->sIBmessage.buf, sib_item->sIBmessage.size); + SI_msg->SI_container_length = sib_item->sIBmessage.size; + SI_msg->SI_type = sib_item->sIBtype; + LOG_D(F1AP, "F1AP: SI_container_length[%d][%ld] %ld bytes\n", i, sib_item->sIBtype, sib_item->sIBmessage.size); } break; @@ -816,13 +816,12 @@ int DU_handle_gNB_CU_CONFIGURATION_UPDATE(instance_t instance, sctp_assoc_t asso for (int si = 0; si < gNB_CUSystemInformation->sibtypetobeupdatedlist.list.count; si++) { F1AP_SibtypetobeupdatedListItem_t *sib_item = gNB_CUSystemInformation->sibtypetobeupdatedlist.list.array[si]; size_t size = sib_item->sIBmessage.size; - F1AP_GNB_CU_CONFIGURATION_UPDATE (msg_p).cells_to_activate[i].SI_container_length[si] = size; + f1ap_sib_msg_t *SI_msg = &F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p).cells_to_activate[i].SI_msg[si]; + SI_msg->SI_container_length = size; LOG_D(F1AP, "F1AP: SI_container_length[%d][%ld] %ld bytes\n", i, sib_item->sIBtype, size); - F1AP_GNB_CU_CONFIGURATION_UPDATE (msg_p).cells_to_activate[i].SI_container[si] = malloc(F1AP_GNB_CU_CONFIGURATION_UPDATE (msg_p).cells_to_activate[i].SI_container_length[si]); - memcpy((void *)F1AP_GNB_CU_CONFIGURATION_UPDATE (msg_p).cells_to_activate[i].SI_container[si], - (void *)sib_item->sIBmessage.buf, - size); - F1AP_GNB_CU_CONFIGURATION_UPDATE (msg_p).cells_to_activate[i].SI_type[si]=sib_item->sIBtype; + SI_msg->SI_container = malloc(SI_msg->SI_container_length); + memcpy((void *)SI_msg->SI_container, (void *)sib_item->sIBmessage.buf, size); + SI_msg->SI_type = sib_item->sIBtype; } break; From ea28b9bb5bb50568c57e9d2b0d6781460c2a8f16 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 29 Apr 2024 17:32:56 +0200 Subject: [PATCH 07/46] F1AP: RLC mode: introduce separate type The currently used type does not cover all possibilities. While we don't encode&decode them, it might still be good to be able to express it, so introduce the new type. Co-authored-by: Guido Casati --- openair2/COMMON/f1ap_messages_types.h | 3 ++- openair2/F1AP/f1ap_cu_ue_context_management.c | 18 ++++++++----- openair2/F1AP/f1ap_du_ue_context_management.c | 26 ++++++++++++------- .../LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 2 +- openair2/RRC/NR/rrc_gNB.c | 2 +- 5 files changed, 32 insertions(+), 19 deletions(-) diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index c3cc837f4c..5752cd0660 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -406,6 +406,7 @@ typedef struct f1ap_drb_information_s { uint8_t flows_to_be_setup_length; } f1ap_drb_information_t; +typedef enum f1ap_rlc_mode_t { F1AP_RLC_MODE_AM, F1AP_RLC_MODE_UM_BIDIR, F1AP_RLC_UM_UNI_UL, F1AP_RLC_UM_UNI_DL } f1ap_rlc_mode_t; typedef struct f1ap_drb_to_be_setup_s { long drb_id; f1ap_up_tnl_t up_ul_tnl[2]; @@ -413,7 +414,7 @@ typedef struct f1ap_drb_to_be_setup_s { f1ap_up_tnl_t up_dl_tnl[2]; uint8_t up_dl_tnl_length; f1ap_drb_information_t drb_info; - rlc_mode_t rlc_mode; + f1ap_rlc_mode_t rlc_mode; nssai_t nssai; } f1ap_drb_to_be_setup_t; diff --git a/openair2/F1AP/f1ap_cu_ue_context_management.c b/openair2/F1AP/f1ap_cu_ue_context_management.c index 8451fb7062..7e8e26564a 100644 --- a/openair2/F1AP/f1ap_cu_ue_context_management.c +++ b/openair2/F1AP/f1ap_cu_ue_context_management.c @@ -483,12 +483,15 @@ int CU_send_UE_CONTEXT_SETUP_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_context_setu /* 12.1.4 rLCMode */ /* TODO use rlc_mode from f1ap_drb_to_be_setup */ switch (f1ap_ue_context_setup_req->drbs_to_be_setup[i].rlc_mode) { - case RLC_MODE_AM: + case F1AP_RLC_MODE_AM: drbs_toBeSetup_item->rLCMode = F1AP_RLCMode_rlc_am; break; - - default: + case F1AP_RLC_MODE_UM_BIDIR: drbs_toBeSetup_item->rLCMode = F1AP_RLCMode_rlc_um_bidirectional; + break; + default: + AssertFatal(false, "modes other than AM/UM-Bidir not supported\n"); + break; } /* OPTIONAL */ @@ -1218,12 +1221,15 @@ int CU_send_UE_CONTEXT_MODIFICATION_REQUEST(sctp_assoc_t assoc_id, f1ap_ue_conte /* 12.1.4 rLCMode */ /* TODO use rlc_mode from f1ap_drb_to_be_setup */ switch (f1ap_ue_context_modification_req->drbs_to_be_setup[i].rlc_mode) { - case RLC_MODE_AM: + case F1AP_RLC_MODE_AM: drbs_toBeSetupMod_item->rLCMode = F1AP_RLCMode_rlc_am; break; - - default: + case F1AP_RLC_MODE_UM_BIDIR: drbs_toBeSetupMod_item->rLCMode = F1AP_RLCMode_rlc_um_bidirectional; + break; + default: + AssertFatal(false, "modes other than AM/UM-Bidir not supported\n"); + break; } /* OPTIONAL */ diff --git a/openair2/F1AP/f1ap_du_ue_context_management.c b/openair2/F1AP/f1ap_du_ue_context_management.c index 6d9771f1f4..fb3d640855 100644 --- a/openair2/F1AP/f1ap_du_ue_context_management.c +++ b/openair2/F1AP/f1ap_du_ue_context_management.c @@ -209,11 +209,14 @@ int DU_handle_UE_CONTEXT_SETUP_REQUEST(instance_t instance, sctp_assoc_t assoc_i switch (drbs_tobesetup_item_p->rLCMode) { case F1AP_RLCMode_rlc_am: - drb_p->rlc_mode = RLC_MODE_AM; + drb_p->rlc_mode = F1AP_RLC_MODE_AM; + break; + case F1AP_RLCMode_rlc_um_bidirectional: + drb_p->rlc_mode = F1AP_RLC_MODE_UM_BIDIR; break; - default: - drb_p->rlc_mode = RLC_MODE_TM; + LOG_W(F1AP, "unsupported RLC Mode %ld received: setting UM bidir\n", drbs_tobesetup_item_p->rLCMode); + drb_p->rlc_mode = F1AP_RLC_MODE_UM_BIDIR; break; } @@ -930,13 +933,16 @@ int DU_handle_UE_CONTEXT_MODIFICATION_REQUEST(instance_t instance, sctp_assoc_t drb_p->up_ul_tnl[0].port = getCxt(instance)->net_config.CUport; switch (drbs_tobesetupmod_item_p->rLCMode) { - case F1AP_RLCMode_rlc_am: - drb_p->rlc_mode = RLC_MODE_AM; - break; - - default: - drb_p->rlc_mode = RLC_MODE_TM; - break; + case F1AP_RLCMode_rlc_am: + drb_p->rlc_mode = F1AP_RLC_MODE_AM; + break; + case F1AP_RLCMode_rlc_um_bidirectional: + drb_p->rlc_mode = F1AP_RLC_MODE_UM_BIDIR; + break; + default: + LOG_W(F1AP, "unsupported RLC Mode %ld received: setting UM bidir\n", drbs_tobesetupmod_item_p->rLCMode); + drb_p->rlc_mode = F1AP_RLC_MODE_UM_BIDIR; + break; } if (drbs_tobesetupmod_item_p->qoSInformation.present == F1AP_QoSInformation_PR_eUTRANQoS) { diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c index bb84a4793c..52d978309a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -244,7 +244,7 @@ static int handle_ue_context_srbs_setup(NR_UE_info_t *UE, static NR_RLC_BearerConfig_t *get_bearerconfig_from_drb(const f1ap_drb_to_be_setup_t *drb) { - const NR_RLC_Config_PR rlc_conf = drb->rlc_mode == RLC_MODE_UM ? NR_RLC_Config_PR_um_Bi_Directional : NR_RLC_Config_PR_am; + const NR_RLC_Config_PR rlc_conf = drb->rlc_mode == F1AP_RLC_MODE_AM ? NR_RLC_Config_PR_am : NR_RLC_Config_PR_um_Bi_Directional; long priority = 13; // hardcoded for the moment return get_DRB_RLC_BearerConfig(get_lcid_from_drbid(drb->drb_id), drb->drb_id, rlc_conf, priority); } diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 2c5e45f428..1b75028013 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -2189,7 +2189,7 @@ static int fill_drb_to_be_setup_from_e1_resp(const gNB_RRC_INST *rrc, const DRB_nGRAN_setup_t *drb_config = &pduSession[p].DRBnGRanList[i]; f1ap_drb_to_be_setup_t *drb = &drbs[nb_drb]; drb->drb_id = pduSession[p].DRBnGRanList[i].id; - drb->rlc_mode = rrc->configuration.um_on_default_drb ? RLC_MODE_UM : RLC_MODE_AM; + drb->rlc_mode = rrc->configuration.um_on_default_drb ? F1AP_RLC_MODE_UM_BIDIR : F1AP_RLC_MODE_AM; drb->up_ul_tnl[0].tl_address = drb_config->UpParamList[0].tlAddress; drb->up_ul_tnl[0].port = rrc->eth_params_s.my_portd; drb->up_ul_tnl[0].teid = drb_config->UpParamList[0].teId; From ba208c0fc23e3bb9cc667b27dcffefb76feec88d Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 29 Apr 2024 17:08:19 +0200 Subject: [PATCH 08/46] Group 5G platform types for common 5G-specific types Co-authored-by: Guido Casati --- common/5g_platform_types.h | 34 +++++++++++++++++++ common/ngran_types.h | 1 - openair2/COMMON/e1ap_messages_types.h | 2 +- openair2/COMMON/f1ap_messages_types.h | 4 +-- openair2/COMMON/ngap_messages_types.h | 9 ++--- openair2/E1AP/e1ap.c | 6 ++-- openair2/F1AP/f1ap_cu_ue_context_management.c | 4 +-- openair2/F1AP/f1ap_du_ue_context_management.c | 8 ++--- .../LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 4 +-- openair2/RRC/NR/rrc_gNB.c | 6 ++-- openair2/RRC/NR/rrc_gNB_NGAP.c | 10 +++--- 11 files changed, 58 insertions(+), 30 deletions(-) create mode 100644 common/5g_platform_types.h diff --git a/common/5g_platform_types.h b/common/5g_platform_types.h new file mode 100644 index 0000000000..05fc2be28d --- /dev/null +++ b/common/5g_platform_types.h @@ -0,0 +1,34 @@ +/* + * 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 FIVEG_PLATFORM_TYPES_H__ +#define FIVEG_PLATFORM_TYPES_H__ + +#include + +typedef struct nssai_s { + uint8_t sst; + uint32_t sd; +} nssai_t; + +typedef enum { NON_DYNAMIC, DYNAMIC } fiveQI_t; + +#endif diff --git a/common/ngran_types.h b/common/ngran_types.h index 37a6ea9177..ac5af71f23 100644 --- a/common/ngran_types.h +++ b/common/ngran_types.h @@ -55,5 +55,4 @@ typedef enum { CPtype = 0, UPtype } E1_t; #define NODE_IS_MBMS(nOdE_TyPe) ((nOdE_TyPe) == ngran_eNB_MBMS_STA) #define GTPV1_U_PORT_NUMBER (2152) -typedef enum { non_dynamic, dynamic } fiveQI_type_t; #endif diff --git a/openair2/COMMON/e1ap_messages_types.h b/openair2/COMMON/e1ap_messages_types.h index cc48a6f9e9..f2fd64252c 100644 --- a/openair2/COMMON/e1ap_messages_types.h +++ b/openair2/COMMON/e1ap_messages_types.h @@ -163,7 +163,7 @@ typedef struct qos_characteristics_s { } packet_error_rate; } dynamic; }; - fiveQI_type_t qos_type; + fiveQI_t qos_type; } qos_characteristics_t; typedef struct ngran_allocation_retention_priority_s { diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index 5752cd0660..7c46b5fef8 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -24,7 +24,7 @@ #include #include -#include "ngap_messages_types.h" +#include "common/5g_platform_types.h" //-------------------------------------------------------------------------------------------// // Defines to access message fields. @@ -381,7 +381,7 @@ typedef struct f1ap_qos_characteristics_s { } packet_error_rate; } dynamic; }; - fiveQI_type_t qos_type; + fiveQI_t qos_type; } f1ap_qos_characteristics_t; typedef struct f1ap_ngran_allocation_retention_priority_s { diff --git a/openair2/COMMON/ngap_messages_types.h b/openair2/COMMON/ngap_messages_types.h index 99d9d1dc0c..0f1555cfdf 100644 --- a/openair2/COMMON/ngap_messages_types.h +++ b/openair2/COMMON/ngap_messages_types.h @@ -31,7 +31,7 @@ #define NGAP_MESSAGES_TYPES_H_ #include "common/platform_constants.h" #include "common/platform_types.h" -#include "common/ngran_types.h" +#include "common/5g_platform_types.h" #include "LTE_asn_constant.h" #include "s1ap_messages_types.h" //-------------------------------------------------------------------------------------------// @@ -197,16 +197,11 @@ typedef enum ngap_rrc_establishment_cause_e { NGAP_RRC_CAUSE_LAST } ngap_rrc_establishment_cause_t; -typedef struct nssai_s { - uint8_t sst; - uint32_t sd; -} nssai_t; - typedef struct pdusession_level_qos_parameter_s { uint8_t qfi; uint64_t fiveQI; uint64_t qos_priority; - fiveQI_type_t fiveQI_type; + fiveQI_t fiveQI_type; ngap_allocation_retention_priority_t allocation_retention_priority; } pdusession_level_qos_parameter_t; diff --git a/openair2/E1AP/e1ap.c b/openair2/E1AP/e1ap.c index fda507ef4e..df359c9234 100644 --- a/openair2/E1AP/e1ap.c +++ b/openair2/E1AP/e1ap.c @@ -686,7 +686,7 @@ static int fill_BEARER_CONTEXT_SETUP_REQUEST(e1ap_bearer_setup_req_t *const bear ieC6_1_1_1->qoS_Flow_Identifier = k->qfi; /* QoS Characteristics */ qos_characteristics_t *qos_char_in = &k->qos_params.qos_characteristics; - if (qos_char_in->qos_type == non_dynamic) { // non Dynamic 5QI + if (qos_char_in->qos_type == NON_DYNAMIC) { // non Dynamic 5QI ieC6_1_1_1->qoSFlowLevelQoSParameters.qoS_Characteristics.present = E1AP_QoS_Characteristics_PR_non_Dynamic_5QI; asn1cCalloc(ieC6_1_1_1->qoSFlowLevelQoSParameters.qoS_Characteristics.choice.non_Dynamic_5QI, non_Dynamic_5QI); non_Dynamic_5QI->fiveQI = qos_char_in->non_dynamic.fiveqi; @@ -1002,12 +1002,12 @@ static void extract_BEARER_CONTEXT_SETUP_REQUEST(const E1AP_E1AP_PDU_t *pdu, e1a qos_characteristics_t *qos_char = &qos_flow->qos_params.qos_characteristics; if (qos2Setup->qoSFlowLevelQoSParameters.qoS_Characteristics.present == E1AP_QoS_Characteristics_PR_non_Dynamic_5QI) { - qos_char->qos_type = non_dynamic; + qos_char->qos_type = NON_DYNAMIC; qos_char->non_dynamic.fiveqi = qos2Setup->qoSFlowLevelQoSParameters.qoS_Characteristics.choice.non_Dynamic_5QI->fiveQI; } else { E1AP_Dynamic5QIDescriptor_t *dynamic5QI = qos2Setup->qoSFlowLevelQoSParameters.qoS_Characteristics.choice.dynamic_5QI; - qos_char->qos_type = dynamic; + qos_char->qos_type = DYNAMIC; qos_char->dynamic.qos_priority_level = dynamic5QI->qoSPriorityLevel; qos_char->dynamic.packet_delay_budget = dynamic5QI->packetDelayBudget; qos_char->dynamic.packet_error_rate.per_scalar = dynamic5QI->packetErrorRate.pER_Scalar; diff --git a/openair2/F1AP/f1ap_cu_ue_context_management.c b/openair2/F1AP/f1ap_cu_ue_context_management.c index 7e8e26564a..78e0ba02e9 100644 --- a/openair2/F1AP/f1ap_cu_ue_context_management.c +++ b/openair2/F1AP/f1ap_cu_ue_context_management.c @@ -44,7 +44,7 @@ static void f1ap_write_drb_qos_param(const f1ap_qos_flow_level_qos_parameters_t int type = drb_qos_in->qos_characteristics.qos_type; const f1ap_qos_characteristics_t *drb_qos_char_in = &drb_qos_in->qos_characteristics; - if (type == non_dynamic) { + if (type == NON_DYNAMIC) { asn1_qosparam->qoS_Characteristics.present = F1AP_QoS_Characteristics_PR_non_Dynamic_5QI; asn1cCalloc(asn1_qosparam->qoS_Characteristics.choice.non_Dynamic_5QI, tmp); @@ -130,7 +130,7 @@ static void f1ap_write_flows_mapped(const f1ap_flows_mapped_to_drb_t *flows_mapp const f1ap_qos_characteristics_t *flow_qos_char_in = &flow_qos_params_in->qos_characteristics; int type = flow_qos_params_in->qos_characteristics.qos_type; - if (type == non_dynamic) { + if (type == NON_DYNAMIC) { QosParams->present = F1AP_QoS_Characteristics_PR_non_Dynamic_5QI; asn1cCalloc(QosParams->choice.non_Dynamic_5QI, tmp); diff --git a/openair2/F1AP/f1ap_du_ue_context_management.c b/openair2/F1AP/f1ap_du_ue_context_management.c index fb3d640855..529c478ac2 100644 --- a/openair2/F1AP/f1ap_du_ue_context_management.c +++ b/openair2/F1AP/f1ap_du_ue_context_management.c @@ -45,13 +45,13 @@ static void f1ap_read_drb_qos_param(const F1AP_QoSFlowLevelQoSParameters_t *asn1 const F1AP_QoS_Characteristics_t *dRB_QoS_Char = &asn1_qos->qoS_Characteristics; if (dRB_QoS_Char->present == F1AP_QoS_Characteristics_PR_non_Dynamic_5QI) { - drb_qos_char->qos_type = non_dynamic; + drb_qos_char->qos_type = NON_DYNAMIC; drb_qos_char->non_dynamic.fiveqi = dRB_QoS_Char->choice.non_Dynamic_5QI->fiveQI; drb_qos_char->non_dynamic.qos_priority_level = (dRB_QoS_Char->choice.non_Dynamic_5QI->qoSPriorityLevel != NULL) ? *dRB_QoS_Char->choice.non_Dynamic_5QI->qoSPriorityLevel : -1; } else { - drb_qos_char->qos_type = dynamic; + drb_qos_char->qos_type = DYNAMIC; drb_qos_char->dynamic.fiveqi = (dRB_QoS_Char->choice.dynamic_5QI->fiveQI != NULL) ? *dRB_QoS_Char->choice.dynamic_5QI->fiveQI : -1; drb_qos_char->dynamic.qos_priority_level = dRB_QoS_Char->choice.dynamic_5QI->qoSPriorityLevel; @@ -84,13 +84,13 @@ static void f1ap_read_flows_mapped(const F1AP_Flows_Mapped_To_DRB_List_t *asn1_f const F1AP_QoS_Characteristics_t *Flow_QoS_Char = &Flow_QoS->qoS_Characteristics; if (Flow_QoS_Char->present == F1AP_QoS_Characteristics_PR_non_Dynamic_5QI) { - flow_qos_char->qos_type = non_dynamic; + flow_qos_char->qos_type = NON_DYNAMIC; flow_qos_char->non_dynamic.fiveqi = Flow_QoS_Char->choice.non_Dynamic_5QI->fiveQI; flow_qos_char->non_dynamic.qos_priority_level = (Flow_QoS_Char->choice.non_Dynamic_5QI->qoSPriorityLevel != NULL) ? *Flow_QoS_Char->choice.non_Dynamic_5QI->qoSPriorityLevel : -1; } else { - flow_qos_char->qos_type = dynamic; + flow_qos_char->qos_type = DYNAMIC; flow_qos_char->dynamic.fiveqi = (Flow_QoS_Char->choice.dynamic_5QI->fiveQI != NULL) ? *Flow_QoS_Char->choice.dynamic_5QI->fiveQI : -1; flow_qos_char->dynamic.qos_priority_level = Flow_QoS_Char->choice.dynamic_5QI->qoSPriorityLevel; diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c index 52d978309a..ff73b8b646 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -262,11 +262,11 @@ static NR_QoS_config_t get_qos_config(const f1ap_qos_characteristics_t *qos_char { NR_QoS_config_t qos_c = {0}; switch (qos_char->qos_type) { - case dynamic: + case DYNAMIC: qos_c.priority = qos_char->dynamic.qos_priority_level; qos_c.fiveQI = qos_char->dynamic.fiveqi > 0 ? qos_char->dynamic.fiveqi : 0; break; - case non_dynamic: + case NON_DYNAMIC: qos_c.fiveQI = qos_char->non_dynamic.fiveqi; qos_c.priority = get_non_dynamic_priority(qos_char->non_dynamic.fiveqi); break; diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 1b75028013..ffd22e6a7d 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -2161,12 +2161,12 @@ static pdusession_level_qos_parameter_t *get_qos_characteristics(const int qfi, static f1ap_qos_characteristics_t get_qos_char_from_qos_flow_param(const pdusession_level_qos_parameter_t *qos_param) { f1ap_qos_characteristics_t qos_char = {0}; - if (qos_param->fiveQI_type == dynamic) { - qos_char.qos_type = dynamic; + if (qos_param->fiveQI_type == DYNAMIC) { + qos_char.qos_type = DYNAMIC; qos_char.dynamic.fiveqi = qos_param->fiveQI; qos_char.dynamic.qos_priority_level = qos_param->qos_priority; } else { - qos_char.qos_type = non_dynamic; + qos_char.qos_type = NON_DYNAMIC; qos_char.non_dynamic.fiveqi = qos_param->fiveQI; qos_char.non_dynamic.qos_priority_level = qos_param->qos_priority; } diff --git a/openair2/RRC/NR/rrc_gNB_NGAP.c b/openair2/RRC/NR/rrc_gNB_NGAP.c index 1ef1f8c808..6ffb8ad88e 100644 --- a/openair2/RRC/NR/rrc_gNB_NGAP.c +++ b/openair2/RRC/NR/rrc_gNB_NGAP.c @@ -248,11 +248,11 @@ static void fill_qos(NGAP_QosFlowSetupRequestList_t *qos, pdusession_t *session) AssertFatal(qosChar, "Qos characteristics are not available for qos flow index %d\n", qosIdx); if (qosChar->present == NGAP_QosCharacteristics_PR_nonDynamic5QI) { AssertFatal(qosChar->choice.dynamic5QI, "Non-Dynamic 5QI is NULL\n"); - session->qos[qosIdx].fiveQI_type = non_dynamic; + session->qos[qosIdx].fiveQI_type = NON_DYNAMIC; session->qos[qosIdx].fiveQI = (uint64_t)qosChar->choice.nonDynamic5QI->fiveQI; } else { AssertFatal(qosChar->choice.dynamic5QI, "Dynamic 5QI is NULL\n"); - session->qos[qosIdx].fiveQI_type = dynamic; + session->qos[qosIdx].fiveQI_type = DYNAMIC; session->qos[qosIdx].fiveQI = (uint64_t)(*qosChar->choice.dynamic5QI->fiveQI); } @@ -412,7 +412,7 @@ void trigger_bearer_setup(gNB_RRC_INST *rrc, gNB_RRC_UE_t *UE, int n, pdusession qos_characteristics_t *qos_char = &qos_flow->qos_params.qos_characteristics; qos_flow->qfi = qos_session->qfi; qos_char->qos_type = qos_session->fiveQI_type; - if (qos_char->qos_type == dynamic) { + if (qos_char->qos_type == DYNAMIC) { qos_char->dynamic.fiveqi = qos_session->fiveQI; qos_char->dynamic.qos_priority_level = qos_session->qos_priority; } else { @@ -861,11 +861,11 @@ static void fill_qos2(NGAP_QosFlowAddOrModifyRequestList_t *qos, pdusession_t *s AssertFatal(qosChar, "Qos characteristics are not available for qos flow index %d\n", qosIdx); if (qosChar->present == NGAP_QosCharacteristics_PR_nonDynamic5QI) { AssertFatal(qosChar->choice.dynamic5QI, "Non-Dynamic 5QI is NULL\n"); - session->qos[qosIdx].fiveQI_type = non_dynamic; + session->qos[qosIdx].fiveQI_type = NON_DYNAMIC; session->qos[qosIdx].fiveQI = (uint64_t)qosChar->choice.nonDynamic5QI->fiveQI; } else { AssertFatal(qosChar->choice.dynamic5QI, "Dynamic 5QI is NULL\n"); - session->qos[qosIdx].fiveQI_type = dynamic; + session->qos[qosIdx].fiveQI_type = DYNAMIC; session->qos[qosIdx].fiveQI = (uint64_t)(*qosChar->choice.dynamic5QI->fiveQI); } From ab27d02e1c63b9e7a00ad4ef1a0d95f806dc4d55 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Mon, 29 Apr 2024 19:16:49 +0200 Subject: [PATCH 09/46] Add new F1AP msg enc&dec library Add a new target f1ap_lib that groups F1AP ASN.1 encoding&decoding for messages defined f1ap_messages_types.h. The objective is to, for each F1AP message, - add encoder&decoder (similar to what already exists, but without mandatory message sending afterwards) - eq_X() function that checks two messages for equality (to be used mostly in tests) - cp_X() function that deep-copies a message, e.g., to be used when sending ITTI messages, instead of manual copying done currently - free_X() function that frees the memory associated to a memory, to avoid memory leaks. Each message will be tested, notably that encoding&decoding as well as copying yield identical messages. The actual message encoding & decoding, tests, and their use will be done in the forthcoming commits. --- openair2/F1AP/CMakeLists.txt | 3 ++ openair2/F1AP/lib/CMakeLists.txt | 8 ++++ openair2/F1AP/lib/f1ap_lib_common.c | 41 ++++++++++++++++++++ openair2/F1AP/lib/f1ap_lib_common.h | 54 +++++++++++++++++++++++++++ openair2/F1AP/lib/f1ap_lib_extern.h | 25 +++++++++++++ openair2/F1AP/lib/f1ap_lib_includes.h | 27 ++++++++++++++ openair2/F1AP/tests/CMakeLists.txt | 6 +++ openair2/F1AP/tests/f1ap_lib_test.c | 47 +++++++++++++++++++++++ 8 files changed, 211 insertions(+) create mode 100644 openair2/F1AP/lib/CMakeLists.txt create mode 100644 openair2/F1AP/lib/f1ap_lib_common.c create mode 100644 openair2/F1AP/lib/f1ap_lib_common.h create mode 100644 openair2/F1AP/lib/f1ap_lib_extern.h create mode 100644 openair2/F1AP/lib/f1ap_lib_includes.h create mode 100644 openair2/F1AP/tests/CMakeLists.txt create mode 100644 openair2/F1AP/tests/f1ap_lib_test.c diff --git a/openair2/F1AP/CMakeLists.txt b/openair2/F1AP/CMakeLists.txt index e6490b96b0..78bc9435a2 100644 --- a/openair2/F1AP/CMakeLists.txt +++ b/openair2/F1AP/CMakeLists.txt @@ -1,3 +1,4 @@ +add_subdirectory(lib) add_subdirectory(MESSAGES) if(ENABLE_TESTS) @@ -5,4 +6,6 @@ if(ENABLE_TESTS) target_link_libraries(f1ap_ids_test UTIL HASHTABLE minimal_lib) add_dependencies(tests f1ap_ids_test) add_test(NAME F1AP_ID_test COMMAND f1ap_ids_test) + + add_subdirectory(tests) endif() diff --git a/openair2/F1AP/lib/CMakeLists.txt b/openair2/F1AP/lib/CMakeLists.txt new file mode 100644 index 0000000000..6ad2e38aaf --- /dev/null +++ b/openair2/F1AP/lib/CMakeLists.txt @@ -0,0 +1,8 @@ +add_library(f1ap_lib OBJECT + f1ap_lib_common.c +) +target_link_libraries(f1ap_lib PRIVATE asn1_f1ap) +target_include_directories(f1ap_lib PUBLIC + ${CMAKE_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR} +) diff --git a/openair2/F1AP/lib/f1ap_lib_common.c b/openair2/F1AP/lib/f1ap_lib_common.c new file mode 100644 index 0000000000..09c1b83b42 --- /dev/null +++ b/openair2/F1AP/lib/f1ap_lib_common.c @@ -0,0 +1,41 @@ +/* + * 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_lib_common.h" +#include "f1ap_messages_types.h" + +#include "OCTET_STRING.h" + +#include "common/utils/assertions.h" +#include "common/utils/utils.h" + +bool eq_f1ap_plmn(const f1ap_plmn_t *a, const f1ap_plmn_t *b) +{ + return a->mcc == b->mcc && a->mnc == b->mnc && a->mnc_digit_length == b->mnc_digit_length; +} + +uint8_t *cp_octet_string(const OCTET_STRING_t *os, int *len) +{ + uint8_t *buf = calloc_or_fail(os->size, sizeof(*buf)); + memcpy(buf, os->buf, os->size); + *len = os->size; + return buf; +} diff --git a/openair2/F1AP/lib/f1ap_lib_common.h b/openair2/F1AP/lib/f1ap_lib_common.h new file mode 100644 index 0000000000..fa1b6246d0 --- /dev/null +++ b/openair2/F1AP/lib/f1ap_lib_common.h @@ -0,0 +1,54 @@ +/* + * 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_LIB_COMMON_H_ +#define F1AP_LIB_COMMON_H_ + +#include +#include +#include + +/* macro to look up IE. If mandatory and not found, macro will print + * descriptive debug message to stderr and force exit in calling function */ +#define F1AP_LIB_FIND_IE(IE_TYPE, ie, container, IE_ID, mandatory) \ + do { \ + ie = NULL; \ + for (IE_TYPE **ptr = container->protocolIEs.list.array; \ + ptr < &container->protocolIEs.list.array[container->protocolIEs.list.count]; \ + ptr++) { \ + if ((*ptr)->id == IE_ID) { \ + ie = *ptr; \ + break; \ + } \ + } \ + if (mandatory && ie == NULL) { \ + fprintf(stderr, "%s(): could not find element " #IE_ID " with type " #IE_TYPE "\n", __func__); \ + return false; \ + } \ + } while (0) + +struct f1ap_plmn_t; +bool eq_f1ap_plmn(const struct f1ap_plmn_t *a, const struct f1ap_plmn_t *b); + +struct OCTET_STRING; +uint8_t *cp_octet_string(const struct OCTET_STRING *os, int *len); + +#endif /* F1AP_LIB_COMMON_H_ */ diff --git a/openair2/F1AP/lib/f1ap_lib_extern.h b/openair2/F1AP/lib/f1ap_lib_extern.h new file mode 100644 index 0000000000..88cc11d3b1 --- /dev/null +++ b/openair2/F1AP/lib/f1ap_lib_extern.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 + */ + +#ifndef F1AP_LIB_EXTERN_H_ +#define F1AP_LIB_EXTERN_H_ + +#endif /* F1AP_LIB_EXTERN_H_ */ diff --git a/openair2/F1AP/lib/f1ap_lib_includes.h b/openair2/F1AP/lib/f1ap_lib_includes.h new file mode 100644 index 0000000000..d68189d277 --- /dev/null +++ b/openair2/F1AP/lib/f1ap_lib_includes.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 F1AP_LIB_INCLUDES_H_ +#define F1AP_LIB_INCLUDES_H_ + +#include "F1AP_F1AP-PDU.h" + +#endif /* F1AP_LIB_INCLUDES_H_ */ diff --git a/openair2/F1AP/tests/CMakeLists.txt b/openair2/F1AP/tests/CMakeLists.txt new file mode 100644 index 0000000000..a73334051a --- /dev/null +++ b/openair2/F1AP/tests/CMakeLists.txt @@ -0,0 +1,6 @@ +add_executable(f1ap_lib_test f1ap_lib_test.c) +add_dependencies(tests f1ap_lib_test) +add_test(NAME f1ap_lib_test COMMAND f1ap_lib_test) +target_link_libraries(f1ap_lib_test PRIVATE f1ap_lib) +target_link_libraries(f1ap_lib_test PRIVATE asn1_f1ap) +target_include_directories(f1ap_lib_test PRIVATE ${CMAKE_SOURCE_DIR}) diff --git a/openair2/F1AP/tests/f1ap_lib_test.c b/openair2/F1AP/tests/f1ap_lib_test.c new file mode 100644 index 0000000000..39f69b5beb --- /dev/null +++ b/openair2/F1AP/tests/f1ap_lib_test.c @@ -0,0 +1,47 @@ +#include +#include +#include + +#include "common/utils/assertions.h" + +#include "f1ap_messages_types.h" +#include "F1AP_F1AP-PDU.h" + +void exit_function(const char *file, const char *function, const int line, const char *s, const int assert) +{ + printf("detected error at %s:%d:%s: %s\n", file, line, function, s); + abort(); +} + +static F1AP_F1AP_PDU_t *f1ap_encode_decode(const F1AP_F1AP_PDU_t *enc_pdu) +{ + //xer_fprint(stdout, &asn_DEF_F1AP_F1AP_PDU, enc_pdu); + + DevAssert(enc_pdu != NULL); + char errbuf[1024]; + size_t errlen = sizeof(errbuf); + int ret = asn_check_constraints(&asn_DEF_F1AP_F1AP_PDU, enc_pdu, errbuf, &errlen); + AssertFatal(ret == 0, "asn_check_constraints() failed: %s\n", errbuf); + + uint8_t msgbuf[16384]; + asn_enc_rval_t enc = aper_encode_to_buffer(&asn_DEF_F1AP_F1AP_PDU, NULL, enc_pdu, msgbuf, sizeof(msgbuf)); + AssertFatal(enc.encoded > 0, "aper_encode_to_buffer() failed\n"); + + F1AP_F1AP_PDU_t *dec_pdu = NULL; + asn_codec_ctx_t st = {.max_stack_size = 100 * 1000}; + asn_dec_rval_t dec = aper_decode(&st, &asn_DEF_F1AP_F1AP_PDU, (void **)&dec_pdu, msgbuf, enc.encoded, 0, 0); + AssertFatal(dec.code == RC_OK, "aper_decode() failed\n"); + + //xer_fprint(stdout, &asn_DEF_F1AP_F1AP_PDU, dec_pdu); + return dec_pdu; +} + +static void f1ap_msg_free(F1AP_F1AP_PDU_t *pdu) +{ + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); +} + +int main() +{ + return 0; +} From 11df3c743f2c106150ac19a39b71891cfa0bf07f Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 29 May 2024 12:25:51 +0200 Subject: [PATCH 10/46] Introduce new macros to improve debugging capabilities in F1AP library * _F1_EQ_CHECK_GENERIC can be used to check the equality of two different members of F1AP structs and return `false` if the condition is not met. When the condition fails, the macros will print a debug message to the standard error stream, including the function name, line number, and the provided format string and arguments. --- openair2/F1AP/lib/f1ap_lib_common.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/openair2/F1AP/lib/f1ap_lib_common.h b/openair2/F1AP/lib/f1ap_lib_common.h index fa1b6246d0..97e4f7eac4 100644 --- a/openair2/F1AP/lib/f1ap_lib_common.h +++ b/openair2/F1AP/lib/f1ap_lib_common.h @@ -26,6 +26,28 @@ #include #include +#ifdef ENABLE_TESTS + #define PRINT_ERROR(...) fprintf(stderr, ##__VA_ARGS__) +#else + #define PRINT_ERROR(...) // Do nothing +#endif + +#define _F1_EQ_CHECK_GENERIC(condition, fmt, ...) \ + do { \ + if (!(condition)) { \ + PRINT_ERROR("F1 Equality Check failure: %s:%d: Condition '%s' failed: " fmt " != " fmt "\n", \ + __FILE__, \ + __LINE__, \ + #condition, \ + ##__VA_ARGS__); \ + return false; \ + } \ + } while (0) + +#define _F1_EQ_CHECK_LONG(A, B) _F1_EQ_CHECK_GENERIC(A == B, "%ld", A, B); +#define _F1_EQ_CHECK_INT(A, B) _F1_EQ_CHECK_GENERIC(A == B, "%d", A, B); +#define _F1_EQ_CHECK_STR(A, B) _F1_EQ_CHECK_GENERIC(strcmp(A, B) == 0, "'%s'", A, B); + /* macro to look up IE. If mandatory and not found, macro will print * descriptive debug message to stderr and force exit in calling function */ #define F1AP_LIB_FIND_IE(IE_TYPE, ie, container, IE_ID, mandatory) \ From 648ed19544caaa0840a770b32b6f0f3a1d25fc64 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 25 Sep 2024 17:18:21 +0200 Subject: [PATCH 11/46] Use _F1_EQ_CHECK_INT in eq_f1ap_plmn --- openair2/F1AP/lib/f1ap_lib_common.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/openair2/F1AP/lib/f1ap_lib_common.c b/openair2/F1AP/lib/f1ap_lib_common.c index 09c1b83b42..a7d47c990f 100644 --- a/openair2/F1AP/lib/f1ap_lib_common.c +++ b/openair2/F1AP/lib/f1ap_lib_common.c @@ -29,7 +29,10 @@ bool eq_f1ap_plmn(const f1ap_plmn_t *a, const f1ap_plmn_t *b) { - return a->mcc == b->mcc && a->mnc == b->mnc && a->mnc_digit_length == b->mnc_digit_length; + _F1_EQ_CHECK_INT(a->mcc, b->mcc); + _F1_EQ_CHECK_INT(a->mnc, b->mnc); + _F1_EQ_CHECK_INT(a->mnc_digit_length, b->mnc_digit_length); + return true; } uint8_t *cp_octet_string(const OCTET_STRING_t *os, int *len) From ca6eb7bd101c8bf39d2bff6f99d57eec81ad9823 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 30 Apr 2024 10:15:13 +0200 Subject: [PATCH 12/46] Add message enc&dec for F1AP Initial UL RRC msg, and test Co-authored-by: Guido Casati --- openair2/COMMON/f1ap_messages_types.h | 1 + openair2/F1AP/lib/CMakeLists.txt | 1 + openair2/F1AP/lib/f1ap_lib_extern.h | 2 + openair2/F1AP/lib/f1ap_lib_includes.h | 4 + openair2/F1AP/lib/f1ap_rrc_message_transfer.c | 199 ++++++++++++++++++ openair2/F1AP/lib/f1ap_rrc_message_transfer.h | 36 ++++ openair2/F1AP/tests/f1ap_lib_test.c | 42 ++++ 7 files changed, 285 insertions(+) create mode 100644 openair2/F1AP/lib/f1ap_rrc_message_transfer.c create mode 100644 openair2/F1AP/lib/f1ap_rrc_message_transfer.h diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index 7c46b5fef8..f34b1dfea7 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -339,6 +339,7 @@ typedef struct f1ap_initial_ul_rrc_message_s { int rrc_container_length; uint8_t *du2cu_rrc_container; int du2cu_rrc_container_length; + uint8_t transaction_id; } f1ap_initial_ul_rrc_message_t; typedef struct f1ap_ul_rrc_message_s { diff --git a/openair2/F1AP/lib/CMakeLists.txt b/openair2/F1AP/lib/CMakeLists.txt index 6ad2e38aaf..7e08cb18b1 100644 --- a/openair2/F1AP/lib/CMakeLists.txt +++ b/openair2/F1AP/lib/CMakeLists.txt @@ -1,5 +1,6 @@ add_library(f1ap_lib OBJECT f1ap_lib_common.c + f1ap_rrc_message_transfer.c ) target_link_libraries(f1ap_lib PRIVATE asn1_f1ap) target_include_directories(f1ap_lib PUBLIC diff --git a/openair2/F1AP/lib/f1ap_lib_extern.h b/openair2/F1AP/lib/f1ap_lib_extern.h index 88cc11d3b1..f95b685540 100644 --- a/openair2/F1AP/lib/f1ap_lib_extern.h +++ b/openair2/F1AP/lib/f1ap_lib_extern.h @@ -22,4 +22,6 @@ #ifndef F1AP_LIB_EXTERN_H_ #define F1AP_LIB_EXTERN_H_ +#include "f1ap_rrc_message_transfer.h" + #endif /* F1AP_LIB_EXTERN_H_ */ diff --git a/openair2/F1AP/lib/f1ap_lib_includes.h b/openair2/F1AP/lib/f1ap_lib_includes.h index d68189d277..e9ebeab266 100644 --- a/openair2/F1AP/lib/f1ap_lib_includes.h +++ b/openair2/F1AP/lib/f1ap_lib_includes.h @@ -23,5 +23,9 @@ #define F1AP_LIB_INCLUDES_H_ #include "F1AP_F1AP-PDU.h" +#include "F1AP_InitialULRRCMessageTransfer.h" +#include "F1AP_InitiatingMessage.h" +#include "F1AP_NRCellIdentity.h" +#include "F1AP_ProtocolIE-Field.h" #endif /* F1AP_LIB_INCLUDES_H_ */ diff --git a/openair2/F1AP/lib/f1ap_rrc_message_transfer.c b/openair2/F1AP/lib/f1ap_rrc_message_transfer.c new file mode 100644 index 0000000000..7d9dd9c682 --- /dev/null +++ b/openair2/F1AP/lib/f1ap_rrc_message_transfer.c @@ -0,0 +1,199 @@ +/* + * 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_rrc_message_transfer.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" + +/* ==================================== + * F1AP Initial UL RRC Message Transfer + * ==================================== */ + +/** + * @brief Initial UL RRC Message Transfer encoding + */ +F1AP_F1AP_PDU_t *encode_initial_ul_rrc_message_transfer(const f1ap_initial_ul_rrc_message_t *msg) +{ + F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + + /* 0. Message Type */ + pdu->present = F1AP_F1AP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu->choice.initiatingMessage, tmp); + tmp->procedureCode = F1AP_ProcedureCode_id_InitialULRRCMessageTransfer; + tmp->criticality = F1AP_Criticality_ignore; + tmp->value.present = F1AP_InitiatingMessage__value_PR_InitialULRRCMessageTransfer; + F1AP_InitialULRRCMessageTransfer_t *out = &tmp->value.choice.InitialULRRCMessageTransfer; + + /* mandatory */ + /* c1. GNB_DU_UE_F1AP_ID */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_InitialULRRCMessageTransferIEs_t, ie1); + ie1->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; + ie1->criticality = F1AP_Criticality_reject; + ie1->value.present = F1AP_InitialULRRCMessageTransferIEs__value_PR_GNB_DU_UE_F1AP_ID; + ie1->value.choice.GNB_DU_UE_F1AP_ID = msg->gNB_DU_ue_id; + + /* mandatory */ + /* c2. NRCGI */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_InitialULRRCMessageTransferIEs_t, ie2); + ie2->id = F1AP_ProtocolIE_ID_id_NRCGI; + ie2->criticality = F1AP_Criticality_reject; + ie2->value.present = F1AP_InitialULRRCMessageTransferIEs__value_PR_NRCGI; + MCC_MNC_TO_PLMNID(msg->plmn.mcc, msg->plmn.mnc, msg->plmn.mnc_digit_length, &ie2->value.choice.NRCGI.pLMN_Identity); + NR_CELL_ID_TO_BIT_STRING(msg->nr_cellid, &ie2->value.choice.NRCGI.nRCellIdentity); + + /* mandatory */ + /* c3. C_RNTI */ // 16 + asn1cSequenceAdd(out->protocolIEs.list, F1AP_InitialULRRCMessageTransferIEs_t, ie3); + ie3->id = F1AP_ProtocolIE_ID_id_C_RNTI; + ie3->criticality = F1AP_Criticality_reject; + ie3->value.present = F1AP_InitialULRRCMessageTransferIEs__value_PR_C_RNTI; + ie3->value.choice.C_RNTI = msg->crnti; + + /* mandatory */ + /* c4. RRCContainer */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_InitialULRRCMessageTransferIEs_t, ie4); + ie4->id = F1AP_ProtocolIE_ID_id_RRCContainer; + ie4->criticality = F1AP_Criticality_reject; + ie4->value.present = F1AP_InitialULRRCMessageTransferIEs__value_PR_RRCContainer; + OCTET_STRING_fromBuf(&ie4->value.choice.RRCContainer, (const char *)msg->rrc_container, msg->rrc_container_length); + + /* optional */ + /* c5. DUtoCURRCContainer */ + if (msg->du2cu_rrc_container != NULL) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_InitialULRRCMessageTransferIEs_t, ie5); + ie5->id = F1AP_ProtocolIE_ID_id_DUtoCURRCContainer; + ie5->criticality = F1AP_Criticality_reject; + ie5->value.present = F1AP_InitialULRRCMessageTransferIEs__value_PR_DUtoCURRCContainer; + OCTET_STRING_fromBuf(&ie5->value.choice.DUtoCURRCContainer, + (const char *)msg->du2cu_rrc_container, + msg->du2cu_rrc_container_length); + } + + /* mandatory */ + /* c6. Transaction ID (integer value) */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_InitialULRRCMessageTransferIEs_t, ie6); + ie6->id = F1AP_ProtocolIE_ID_id_TransactionID; + ie6->criticality = F1AP_Criticality_ignore; + ie6->value.present = F1AP_InitialULRRCMessageTransferIEs__value_PR_TransactionID; + ie6->value.choice.TransactionID = msg->transaction_id; + + return pdu; +} + +/** + * @brief Initial UL RRC Message Transfer decoding + */ +bool decode_initial_ul_rrc_message_transfer(const F1AP_F1AP_PDU_t *pdu, f1ap_initial_ul_rrc_message_t *out) +{ + DevAssert(out != NULL); + memset(out, 0, sizeof(*out)); + + F1AP_InitialULRRCMessageTransfer_t *container = &pdu->choice.initiatingMessage->value.choice.InitialULRRCMessageTransfer; + F1AP_InitialULRRCMessageTransferIEs_t *ie; + + F1AP_LIB_FIND_IE(F1AP_InitialULRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); + out->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; + + F1AP_LIB_FIND_IE(F1AP_InitialULRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_NRCGI, true); + PLMNID_TO_MCC_MNC(&ie->value.choice.NRCGI.pLMN_Identity, out->plmn.mcc, out->plmn.mnc, out->plmn.mnc_digit_length); + BIT_STRING_TO_NR_CELL_IDENTITY(&ie->value.choice.NRCGI.nRCellIdentity, out->nr_cellid); + + F1AP_LIB_FIND_IE(F1AP_InitialULRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_C_RNTI, true); + out->crnti = ie->value.choice.C_RNTI; + + F1AP_LIB_FIND_IE(F1AP_InitialULRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_RRCContainer, true); + out->rrc_container = cp_octet_string(&ie->value.choice.RRCContainer, &out->rrc_container_length); + + F1AP_LIB_FIND_IE(F1AP_InitialULRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_DUtoCURRCContainer, false); + if (ie != NULL) + out->du2cu_rrc_container = cp_octet_string(&ie->value.choice.DUtoCURRCContainer, &out->du2cu_rrc_container_length); + + F1AP_LIB_FIND_IE(F1AP_InitialULRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_TransactionID, true); + out->transaction_id = ie->value.choice.TransactionID; + + return true; +} + +/** + * @brief Initial UL RRC Message Transfer deep copy + */ +f1ap_initial_ul_rrc_message_t cp_initial_ul_rrc_message_transfer(const f1ap_initial_ul_rrc_message_t *msg) +{ + uint8_t *rrc_container = calloc_or_fail(msg->rrc_container_length, sizeof(*rrc_container)); + memcpy(rrc_container, msg->rrc_container, msg->rrc_container_length); + uint8_t *du2cu_rrc_container = NULL; + if (msg->du2cu_rrc_container_length > 0) { + DevAssert(msg->du2cu_rrc_container != NULL); + du2cu_rrc_container = calloc_or_fail(msg->du2cu_rrc_container_length, sizeof(*du2cu_rrc_container)); + memcpy(du2cu_rrc_container, msg->du2cu_rrc_container, msg->du2cu_rrc_container_length); + } + f1ap_initial_ul_rrc_message_t cp = { + .gNB_DU_ue_id = msg->gNB_DU_ue_id, + .plmn = msg->plmn, + .nr_cellid = msg->nr_cellid, + .crnti = msg->crnti, + .rrc_container = rrc_container, + .rrc_container_length = msg->rrc_container_length, + .du2cu_rrc_container = du2cu_rrc_container, + .du2cu_rrc_container_length = msg->du2cu_rrc_container_length, + .transaction_id = msg->transaction_id + }; + return cp; +} + +/** + * @brief Initial UL RRC Message Transfer equality check + */ +bool eq_initial_ul_rrc_message_transfer(const f1ap_initial_ul_rrc_message_t *a, const f1ap_initial_ul_rrc_message_t *b) +{ + _F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id); + if (!eq_f1ap_plmn(&a->plmn, &b->plmn)) + return false; + _F1_EQ_CHECK_LONG(a->nr_cellid, b->nr_cellid); + _F1_EQ_CHECK_INT(a->crnti, b->crnti); + _F1_EQ_CHECK_INT(a->rrc_container_length, b->rrc_container_length); + _F1_EQ_CHECK_LONG(a->nr_cellid, b->nr_cellid); + if (memcmp(a->rrc_container, b->rrc_container, a->rrc_container_length) != 0) + return false; + _F1_EQ_CHECK_INT(a->du2cu_rrc_container_length, b->du2cu_rrc_container_length); + if (memcmp(a->du2cu_rrc_container, b->du2cu_rrc_container, a->du2cu_rrc_container_length) != 0) + return false; + _F1_EQ_CHECK_INT(a->transaction_id, b->transaction_id); + return true; +} + +/** + * @brief Initial UL RRC Message Transfer memory management + */ +void free_initial_ul_rrc_message_transfer(f1ap_initial_ul_rrc_message_t *msg) +{ + DevAssert(msg != NULL); + free(msg->rrc_container); + free(msg->du2cu_rrc_container); +} diff --git a/openair2/F1AP/lib/f1ap_rrc_message_transfer.h b/openair2/F1AP/lib/f1ap_rrc_message_transfer.h new file mode 100644 index 0000000000..b38b98cc38 --- /dev/null +++ b/openair2/F1AP/lib/f1ap_rrc_message_transfer.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_RRC_MESSAGE_TRANSFER_H_ +#define F1AP_RRC_MESSAGE_TRANSFER_H_ + +#include +#include "f1ap_messages_types.h" + +struct F1AP_F1AP_PDU; + +struct F1AP_F1AP_PDU *encode_initial_ul_rrc_message_transfer(const f1ap_initial_ul_rrc_message_t *msg); +bool decode_initial_ul_rrc_message_transfer(const struct F1AP_F1AP_PDU *pdu, f1ap_initial_ul_rrc_message_t *out); +f1ap_initial_ul_rrc_message_t cp_initial_ul_rrc_message_transfer(const f1ap_initial_ul_rrc_message_t *msg); +bool eq_initial_ul_rrc_message_transfer(const f1ap_initial_ul_rrc_message_t *a, const f1ap_initial_ul_rrc_message_t *b); +void free_initial_ul_rrc_message_transfer(f1ap_initial_ul_rrc_message_t *msg); + +#endif /* F1AP_RRC_MESSAGE_TRANSFER_H_ */ diff --git a/openair2/F1AP/tests/f1ap_lib_test.c b/openair2/F1AP/tests/f1ap_lib_test.c index 39f69b5beb..896ea127e6 100644 --- a/openair2/F1AP/tests/f1ap_lib_test.c +++ b/openair2/F1AP/tests/f1ap_lib_test.c @@ -7,6 +7,8 @@ #include "f1ap_messages_types.h" #include "F1AP_F1AP-PDU.h" +#include "f1ap_lib_extern.h" + void exit_function(const char *file, const char *function, const int line, const char *s, const int assert) { printf("detected error at %s:%d:%s: %s\n", file, line, function, s); @@ -41,7 +43,47 @@ static void f1ap_msg_free(F1AP_F1AP_PDU_t *pdu) ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); } +/** + * @brief Test Initial UL RRC Message Transfer encoding/decoding + */ +static void test_initial_ul_rrc_message_transfer(void) +{ + f1ap_plmn_t plmn = { .mcc = 208, .mnc = 95, .mnc_digit_length = 2 }; + uint8_t rrc[] = "RRC Container"; + uint8_t du2cu[] = "DU2CU Container"; + f1ap_initial_ul_rrc_message_t orig = { + .gNB_DU_ue_id = 12, + .plmn = plmn, + .nr_cellid = 135, + .crnti = 0x1234, + .rrc_container = rrc, + .rrc_container_length = sizeof(rrc), + .du2cu_rrc_container = du2cu, + .du2cu_rrc_container_length = sizeof(du2cu), + .transaction_id = 2, + }; + + F1AP_F1AP_PDU_t *f1enc = encode_initial_ul_rrc_message_transfer(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_initial_ul_rrc_message_t decoded; + bool ret = decode_initial_ul_rrc_message_transfer(f1dec, &decoded); + AssertFatal(ret, "decode_initial_ul_rrc_message_transfer(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_initial_ul_rrc_message_transfer(&orig, &decoded); + AssertFatal(ret, "eq_initial_ul_rrc_message_transfer(): decoded message doesn't match\n"); + free_initial_ul_rrc_message_transfer(&decoded); + + f1ap_initial_ul_rrc_message_t cp = cp_initial_ul_rrc_message_transfer(&orig); + ret = eq_initial_ul_rrc_message_transfer(&orig, &cp); + AssertFatal(ret, "eq_initial_ul_rrc_message_transfer(): copied message doesn't match\n"); + free_initial_ul_rrc_message_transfer(&cp); +} + int main() { + test_initial_ul_rrc_message_transfer(); return 0; } From 57ecb11d5352d8f12cc8db9dcd1f8fc670f579a6 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Tue, 30 Apr 2024 13:41:09 +0200 Subject: [PATCH 13/46] Use F1AP lib Init UL RRC Msg in stack Co-authored-by: Guido Casati --- CMakeLists.txt | 5 +- openair2/F1AP/f1ap_cu_rrc_message_transfer.c | 56 ++----------- openair2/F1AP/f1ap_du_rrc_message_transfer.c | 82 ++++--------------- openair2/F1AP/lib/f1ap_rrc_message_transfer.c | 2 +- openair2/F1AP/lib/f1ap_rrc_message_transfer.h | 2 +- .../LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c | 15 +--- openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c | 16 +--- openair2/RRC/NR/rrc_gNB.c | 7 +- 8 files changed, 38 insertions(+), 147 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 034bc89fc9..e6c9abdb9a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -445,7 +445,8 @@ add_library(f1ap ${F1AP_DIR}/f1ap_itti_messaging.c) target_include_directories(f1ap PUBLIC F1AP_DIR) target_link_libraries(f1ap PUBLIC asn1_f1ap L2_NR) -target_link_libraries(f1ap PRIVATE ngap nr_rrc HASHTABLE) +target_link_libraries(f1ap PRIVATE ngap nr_rrc HASHTABLE f1ap_lib) +target_include_directories(f1ap PRIVATE ${F1AP_DIR}/lib) # LPP ############## @@ -1435,6 +1436,8 @@ add_library(L2_NR ${GNB_APP_SRC} ) target_link_libraries(L2_NR PRIVATE ds alg) +target_link_libraries(L2_NR PRIVATE f1ap_lib) +target_include_directories(L2_NR PRIVATE ${F1AP_DIR}/lib) add_library(e1_if ${NR_RRC_DIR}/cucp_cuup_direct.c diff --git a/openair2/F1AP/f1ap_cu_rrc_message_transfer.c b/openair2/F1AP/f1ap_cu_rrc_message_transfer.c index 8ccca9f478..020c3be50d 100644 --- a/openair2/F1AP/f1ap_cu_rrc_message_transfer.c +++ b/openair2/F1AP/f1ap_cu_rrc_message_transfer.c @@ -39,67 +39,25 @@ #include "openair3/UTILS/conversions.h" #include "LAYER2/nr_pdcp/nr_pdcp_oai_api.h" +#include "f1ap_rrc_message_transfer.h" + /* Initial UL RRC Message Transfer */ int CU_handle_INITIAL_UL_RRC_MESSAGE_TRANSFER(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { - LOG_D(F1AP, "CU_handle_INITIAL_UL_RRC_MESSAGE_TRANSFER\n"); - // decode the F1 message - // get the rrc message from the contauiner - // call func rrc_eNB_decode_ccch: <-- needs some update here - MessageDef *message_p; - F1AP_InitialULRRCMessageTransfer_t *container; - F1AP_InitialULRRCMessageTransferIEs_t *ie; - DevAssert(pdu != NULL); - - if (stream != 0) { - LOG_E(F1AP, "[SCTP %d] Received F1 on stream != 0 (%d)\n", - assoc_id, stream); + f1ap_initial_ul_rrc_message_t msg; + if (!decode_initial_ul_rrc_message_transfer(pdu, &msg)) { + LOG_E(F1AP, "cannot decode F1 initial UL RRC message Transfer\n"); return -1; } - container = &pdu->choice.initiatingMessage->value.choice.InitialULRRCMessageTransfer; - /* GNB_DU_UE_F1AP_ID */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_InitialULRRCMessageTransferIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); - uint32_t du_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; - - /* NRCGI - * Fixme: process NRCGI - */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_InitialULRRCMessageTransferIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_NRCGI, true); - uint64_t nr_cellid; - BIT_STRING_TO_NR_CELL_IDENTITY(&ie->value.choice.NRCGI.nRCellIdentity,nr_cellid); - /* RNTI */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_InitialULRRCMessageTransferIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_C_RNTI, true); - rnti_t rnti = ie->value.choice.C_RNTI; - F1AP_InitialULRRCMessageTransferIEs_t *rrccont; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_InitialULRRCMessageTransferIEs_t, rrccont, container, - F1AP_ProtocolIE_ID_id_RRCContainer, true); - AssertFatal(rrccont!=NULL,"RRCContainer is missing\n"); - - F1AP_InitialULRRCMessageTransferIEs_t *du2cu; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_InitialULRRCMessageTransferIEs_t, du2cu, container, - F1AP_ProtocolIE_ID_id_DUtoCURRCContainer, false); - // create an ITTI message and copy SDU - message_p = itti_alloc_new_message(TASK_CU_F1, 0, F1AP_INITIAL_UL_RRC_MESSAGE); + MessageDef *message_p = itti_alloc_new_message(TASK_CU_F1, 0, F1AP_INITIAL_UL_RRC_MESSAGE); message_p->ittiMsgHeader.originInstance = assoc_id; f1ap_initial_ul_rrc_message_t *ul_rrc = &F1AP_INITIAL_UL_RRC_MESSAGE(message_p); - ul_rrc->gNB_DU_ue_id = du_ue_id; - ul_rrc->nr_cellid = nr_cellid; // CU instance - ul_rrc->crnti = rnti; - ul_rrc->rrc_container_length = rrccont->value.choice.RRCContainer.size; - ul_rrc->rrc_container = malloc(ul_rrc->rrc_container_length); - memcpy(ul_rrc->rrc_container, rrccont->value.choice.RRCContainer.buf, ul_rrc->rrc_container_length); - AssertFatal(du2cu != NULL, "no masterCellGroup in initial UL RRC message\n"); - ul_rrc->du2cu_rrc_container_length = du2cu->value.choice.DUtoCURRCContainer.size; - ul_rrc->du2cu_rrc_container = malloc(ul_rrc->du2cu_rrc_container_length); - memcpy(ul_rrc->du2cu_rrc_container, du2cu->value.choice.DUtoCURRCContainer.buf, ul_rrc->du2cu_rrc_container_length); + *ul_rrc = msg; /* "move" message into ITTI, RRC thread will free it */ itti_send_msg_to_task(TASK_RRC_GNB, instance, message_p); return 0; diff --git a/openair2/F1AP/f1ap_du_rrc_message_transfer.c b/openair2/F1AP/f1ap_du_rrc_message_transfer.c index 4a3526dd0a..62e6c1f0e3 100644 --- a/openair2/F1AP/f1ap_du_rrc_message_transfer.c +++ b/openair2/F1AP/f1ap_du_rrc_message_transfer.c @@ -53,6 +53,8 @@ #include "openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h" +#include "f1ap_rrc_message_transfer.h" + /* DL RRC Message Transfer */ int DU_handle_DL_RRC_MESSAGE_TRANSFER(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { @@ -141,74 +143,26 @@ int DU_handle_DL_RRC_MESSAGE_TRANSFER(instance_t instance, sctp_assoc_t assoc_id /* UL RRC Message Transfer */ int DU_send_INITIAL_UL_RRC_MESSAGE_TRANSFER(sctp_assoc_t assoc_id, const f1ap_initial_ul_rrc_message_t *msg) { - F1AP_F1AP_PDU_t pdu= {0}; - F1AP_InitialULRRCMessageTransfer_t *out; - uint8_t *buffer=NULL; - uint32_t len=0; + F1AP_F1AP_PDU_t *pdu = encode_initial_ul_rrc_message_transfer(msg); + /* free F1AP message after encoding */ + free_initial_ul_rrc_message_transfer(msg); - /* Create */ - /* 0. Message Type */ - pdu.present = F1AP_F1AP_PDU_PR_initiatingMessage; - asn1cCalloc(pdu.choice.initiatingMessage, tmp); - tmp->procedureCode = F1AP_ProcedureCode_id_InitialULRRCMessageTransfer; - tmp->criticality = F1AP_Criticality_ignore; - tmp->value.present = F1AP_InitiatingMessage__value_PR_InitialULRRCMessageTransfer; - out = &tmp->value.choice.InitialULRRCMessageTransfer; - /* mandatory */ - /* c1. GNB_DU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_InitialULRRCMessageTransferIEs_t, ie1); - ie1->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; - ie1->criticality = F1AP_Criticality_reject; - ie1->value.present = F1AP_InitialULRRCMessageTransferIEs__value_PR_GNB_DU_UE_F1AP_ID; - ie1->value.choice.GNB_DU_UE_F1AP_ID = msg->gNB_DU_ue_id; - /* mandatory */ - /* c2. NRCGI */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_InitialULRRCMessageTransferIEs_t, ie2); - ie2->id = F1AP_ProtocolIE_ID_id_NRCGI; - ie2->criticality = F1AP_Criticality_reject; - ie2->value.present = F1AP_InitialULRRCMessageTransferIEs__value_PR_NRCGI; - //Fixme: takes always the first cell - addnRCGI(ie2->value.choice.NRCGI, &getCxt(0)->setupReq.cell[0].info); - /* mandatory */ - /* c3. C_RNTI */ // 16 - asn1cSequenceAdd(out->protocolIEs.list, F1AP_InitialULRRCMessageTransferIEs_t, ie3); - ie3->id = F1AP_ProtocolIE_ID_id_C_RNTI; - ie3->criticality = F1AP_Criticality_reject; - ie3->value.present = F1AP_InitialULRRCMessageTransferIEs__value_PR_C_RNTI; - ie3->value.choice.C_RNTI = msg->crnti; - /* mandatory */ - /* c4. RRCContainer */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_InitialULRRCMessageTransferIEs_t, ie4); - ie4->id = F1AP_ProtocolIE_ID_id_RRCContainer; - ie4->criticality = F1AP_Criticality_reject; - ie4->value.present = F1AP_InitialULRRCMessageTransferIEs__value_PR_RRCContainer; - OCTET_STRING_fromBuf(&ie4->value.choice.RRCContainer, (const char *)msg->rrc_container, msg->rrc_container_length); - - /* optional */ - /* c5. DUtoCURRCContainer */ - if (msg->du2cu_rrc_container != NULL) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_InitialULRRCMessageTransferIEs_t, ie5); - ie5->id = F1AP_ProtocolIE_ID_id_DUtoCURRCContainer; - ie5->criticality = F1AP_Criticality_reject; - ie5->value.present = F1AP_InitialULRRCMessageTransferIEs__value_PR_DUtoCURRCContainer; - OCTET_STRING_fromBuf(&ie5->value.choice.DUtoCURRCContainer, - (const char *)msg->du2cu_rrc_container, - msg->du2cu_rrc_container_length); - } - /* mandatory */ - /* c6. Transaction ID (integer value) */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_InitialULRRCMessageTransferIEs_t, ie6); - ie6->id = F1AP_ProtocolIE_ID_id_TransactionID; - ie6->criticality = F1AP_Criticality_ignore; - ie6->value.present = F1AP_InitialULRRCMessageTransferIEs__value_PR_TransactionID; - ie6->value.choice.TransactionID = F1AP_get_next_transaction_identifier(0, 0); - - /* encode */ - if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { - LOG_E(F1AP, "Failed to encode F1 INITIAL UL RRC MESSAGE TRANSFER\n"); + if (pdu == NULL) { + LOG_E(F1AP, "cannot encode F1 INITIAL UL RRC MESSAGE TRANSFER, can't send message\n"); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); return -1; } + /* encode */ + uint8_t *buffer = NULL; + uint32_t len = 0; + if (f1ap_encode_pdu(pdu, &buffer, &len) < 0) { + LOG_E(F1AP, "Failed to encode F1 INITIAL UL RRC MESSAGE TRANSFER\n"); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); + return -1; + } + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); + f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); return 0; } diff --git a/openair2/F1AP/lib/f1ap_rrc_message_transfer.c b/openair2/F1AP/lib/f1ap_rrc_message_transfer.c index 7d9dd9c682..4c4a353cee 100644 --- a/openair2/F1AP/lib/f1ap_rrc_message_transfer.c +++ b/openair2/F1AP/lib/f1ap_rrc_message_transfer.c @@ -191,7 +191,7 @@ bool eq_initial_ul_rrc_message_transfer(const f1ap_initial_ul_rrc_message_t *a, /** * @brief Initial UL RRC Message Transfer memory management */ -void free_initial_ul_rrc_message_transfer(f1ap_initial_ul_rrc_message_t *msg) +void free_initial_ul_rrc_message_transfer(const f1ap_initial_ul_rrc_message_t *msg) { DevAssert(msg != NULL); free(msg->rrc_container); diff --git a/openair2/F1AP/lib/f1ap_rrc_message_transfer.h b/openair2/F1AP/lib/f1ap_rrc_message_transfer.h index b38b98cc38..30a884e8fc 100644 --- a/openair2/F1AP/lib/f1ap_rrc_message_transfer.h +++ b/openair2/F1AP/lib/f1ap_rrc_message_transfer.h @@ -31,6 +31,6 @@ struct F1AP_F1AP_PDU *encode_initial_ul_rrc_message_transfer(const f1ap_initial_ bool decode_initial_ul_rrc_message_transfer(const struct F1AP_F1AP_PDU *pdu, f1ap_initial_ul_rrc_message_t *out); f1ap_initial_ul_rrc_message_t cp_initial_ul_rrc_message_transfer(const f1ap_initial_ul_rrc_message_t *msg); bool eq_initial_ul_rrc_message_transfer(const f1ap_initial_ul_rrc_message_t *a, const f1ap_initial_ul_rrc_message_t *b); -void free_initial_ul_rrc_message_transfer(f1ap_initial_ul_rrc_message_t *msg); +void free_initial_ul_rrc_message_transfer(const f1ap_initial_ul_rrc_message_t *msg); #endif /* F1AP_RRC_MESSAGE_TRANSFER_H_ */ diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c index 29a7bc8621..b06abeb5bc 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c @@ -23,6 +23,7 @@ #include "intertask_interface.h" #include "mac_rrc_ul.h" +#include "f1ap_lib_extern.h" static void f1_reset_du_initiated_direct(const f1ap_reset_t *reset) { @@ -277,20 +278,8 @@ static void initial_ul_rrc_message_transfer_direct(module_id_t module_id, const { MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_INITIAL_UL_RRC_MESSAGE); msg->ittiMsgHeader.originInstance = -1; // means monolithic - /* copy all fields, but reallocate rrc_containers! */ f1ap_initial_ul_rrc_message_t *f1ap_msg = &F1AP_INITIAL_UL_RRC_MESSAGE(msg); - *f1ap_msg = *ul_rrc; - - f1ap_msg->rrc_container = malloc(ul_rrc->rrc_container_length); - DevAssert(f1ap_msg->rrc_container); - memcpy(f1ap_msg->rrc_container, ul_rrc->rrc_container, ul_rrc->rrc_container_length); - f1ap_msg->rrc_container_length = ul_rrc->rrc_container_length; - - f1ap_msg->du2cu_rrc_container = malloc(ul_rrc->du2cu_rrc_container_length); - DevAssert(f1ap_msg->du2cu_rrc_container); - memcpy(f1ap_msg->du2cu_rrc_container, ul_rrc->du2cu_rrc_container, ul_rrc->du2cu_rrc_container_length); - f1ap_msg->du2cu_rrc_container_length = ul_rrc->du2cu_rrc_container_length; - + *f1ap_msg = cp_initial_ul_rrc_message_transfer(ul_rrc); itti_send_msg_to_task(TASK_RRC_GNB, module_id, msg); } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c index 3fe7fcf91a..e3e46310eb 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c @@ -29,6 +29,8 @@ #include "mac_rrc_ul.h" +#include "f1ap_lib_extern.h" + static f1ap_net_config_t read_DU_IP_config(const eth_params_t* f1_params, const char *f1u_ip_addr) { f1ap_net_config_t nc = {0}; @@ -265,20 +267,8 @@ static void ue_context_release_complete_f1ap(const f1ap_ue_context_release_compl static void initial_ul_rrc_message_transfer_f1ap(module_id_t module_id, const f1ap_initial_ul_rrc_message_t *ul_rrc) { MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_INITIAL_UL_RRC_MESSAGE); - /* copy all fields, but reallocate rrc_containers! */ f1ap_initial_ul_rrc_message_t *f1ap_msg = &F1AP_INITIAL_UL_RRC_MESSAGE(msg); - *f1ap_msg = *ul_rrc; - - f1ap_msg->rrc_container = malloc(ul_rrc->rrc_container_length); - DevAssert(f1ap_msg->rrc_container); - memcpy(f1ap_msg->rrc_container, ul_rrc->rrc_container, ul_rrc->rrc_container_length); - f1ap_msg->rrc_container_length = ul_rrc->rrc_container_length; - - f1ap_msg->du2cu_rrc_container = malloc(ul_rrc->du2cu_rrc_container_length); - DevAssert(f1ap_msg->du2cu_rrc_container); - memcpy(f1ap_msg->du2cu_rrc_container, ul_rrc->du2cu_rrc_container, ul_rrc->du2cu_rrc_container_length); - f1ap_msg->du2cu_rrc_container_length = ul_rrc->du2cu_rrc_container_length; - + *f1ap_msg = cp_initial_ul_rrc_message_transfer(ul_rrc); itti_send_msg_to_task(TASK_DU_F1, module_id, msg); } diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index ffd22e6a7d..53b158aac0 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -94,6 +94,7 @@ #include #include "openair2/F1AP/f1ap_common.h" #include "openair2/F1AP/f1ap_ids.h" +#include "openair2/F1AP/lib/f1ap_lib_extern.h" #include "openair2/SDAP/nr_sdap/nr_sdap_entity.h" #include "openair2/E1AP/e1ap.h" #include "cucp_cuup_if.h" @@ -1839,11 +1840,6 @@ void rrc_gNB_process_initial_ul_rrc_message(sctp_assoc_t assoc_id, const f1ap_in } } ASN_STRUCT_FREE(asn_DEF_NR_UL_CCCH_Message, ul_ccch_msg); - - if (ul_rrc->rrc_container) - free(ul_rrc->rrc_container); - if (ul_rrc->du2cu_rrc_container) - free(ul_rrc->du2cu_rrc_container); } void rrc_gNB_process_release_request(const module_id_t gnb_mod_idP, x2ap_ENDC_sgnb_release_request_t *m) @@ -2439,6 +2435,7 @@ void *rrc_gnb_task(void *args_p) { AssertFatal(NODE_IS_CU(RC.nrrrc[instance]->node_type) || NODE_IS_MONOLITHIC(RC.nrrrc[instance]->node_type), "should not receive F1AP_INITIAL_UL_RRC_MESSAGE, need call by CU!\n"); rrc_gNB_process_initial_ul_rrc_message(msg_p->ittiMsgHeader.originInstance, &F1AP_INITIAL_UL_RRC_MESSAGE(msg_p)); + free_initial_ul_rrc_message_transfer(&F1AP_INITIAL_UL_RRC_MESSAGE(msg_p)); break; /* Messages from PDCP */ From 3374327752ac5575bb48ad81b4ae5cec6df2d80d Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Mon, 13 May 2024 15:55:00 +0200 Subject: [PATCH 14/46] Add encoding/decoding lib for F1AP DL RRC Transfer message --- openair2/F1AP/lib/f1ap_rrc_message_transfer.c | 162 ++++++++++++++++++ openair2/F1AP/lib/f1ap_rrc_message_transfer.h | 7 + 2 files changed, 169 insertions(+) diff --git a/openair2/F1AP/lib/f1ap_rrc_message_transfer.c b/openair2/F1AP/lib/f1ap_rrc_message_transfer.c index 4c4a353cee..e449d68096 100644 --- a/openair2/F1AP/lib/f1ap_rrc_message_transfer.c +++ b/openair2/F1AP/lib/f1ap_rrc_message_transfer.c @@ -197,3 +197,165 @@ void free_initial_ul_rrc_message_transfer(const f1ap_initial_ul_rrc_message_t *m free(msg->rrc_container); free(msg->du2cu_rrc_container); } + +/* ============================ + * F1AP DL RRC Message Transfer + * ============================ */ + +/** + * @brief DL RRC Message Transfer encoding (9.2.3.2 of 3GPP TS 38.473) + * gNB-CU → gNB-DU + */ +F1AP_F1AP_PDU_t *encode_dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *msg) +{ + F1AP_F1AP_PDU_t *pdu = calloc(1, sizeof(*pdu)); + AssertFatal(pdu != NULL, "out of memory\n"); + + /* Create */ + /* 0. Message Type */ + pdu->present = F1AP_F1AP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu->choice.initiatingMessage, tmp); + tmp->procedureCode = F1AP_ProcedureCode_id_DLRRCMessageTransfer; + tmp->criticality = F1AP_Criticality_ignore; + tmp->value.present = F1AP_InitiatingMessage__value_PR_DLRRCMessageTransfer; + F1AP_DLRRCMessageTransfer_t *out = &tmp->value.choice.DLRRCMessageTransfer; + // gNB-CU UE F1AP ID (M) + asn1cSequenceAdd(out->protocolIEs.list, F1AP_DLRRCMessageTransferIEs_t, ie1); + ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; + ie1->criticality = F1AP_Criticality_reject; + ie1->value.present = F1AP_DLRRCMessageTransferIEs__value_PR_GNB_CU_UE_F1AP_ID; + ie1->value.choice.GNB_CU_UE_F1AP_ID = msg->gNB_CU_ue_id; + // gNB-DU UE F1AP ID (M) + asn1cSequenceAdd(out->protocolIEs.list, F1AP_DLRRCMessageTransferIEs_t, ie2); + ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; + ie2->criticality = F1AP_Criticality_reject; + ie2->value.present = F1AP_DLRRCMessageTransferIEs__value_PR_GNB_DU_UE_F1AP_ID; + ie2->value.choice.GNB_DU_UE_F1AP_ID = msg->gNB_DU_ue_id; + // old gNB-DU UE F1AP ID (O) + if (msg->old_gNB_DU_ue_id) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_DLRRCMessageTransferIEs_t, ie3); + ie3->id = F1AP_ProtocolIE_ID_id_oldgNB_DU_UE_F1AP_ID; + ie3->criticality = F1AP_Criticality_reject; + ie3->value.present = F1AP_DLRRCMessageTransferIEs__value_PR_GNB_DU_UE_F1AP_ID_1; + ie3->value.choice.GNB_DU_UE_F1AP_ID_1 = *msg->old_gNB_DU_ue_id; + } + // SRB ID (M) + asn1cSequenceAdd(out->protocolIEs.list, F1AP_DLRRCMessageTransferIEs_t, ie4); + ie4->id = F1AP_ProtocolIE_ID_id_SRBID; + ie4->criticality = F1AP_Criticality_reject; + ie4->value.present = F1AP_DLRRCMessageTransferIEs__value_PR_SRBID; + ie4->value.choice.SRBID = msg->srb_id; + // Execute Duplication (O) + if (msg->execute_duplication) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_DLRRCMessageTransferIEs_t, ie5); + ie5->id = F1AP_ProtocolIE_ID_id_ExecuteDuplication; + ie5->criticality = F1AP_Criticality_ignore; + ie5->value.present = F1AP_DLRRCMessageTransferIEs__value_PR_ExecuteDuplication; + ie5->value.choice.ExecuteDuplication = F1AP_ExecuteDuplication_true; + } + // RRC-Container (M) + asn1cSequenceAdd(out->protocolIEs.list, F1AP_DLRRCMessageTransferIEs_t, ie6); + ie6->id = F1AP_ProtocolIE_ID_id_RRCContainer; + ie6->criticality = F1AP_Criticality_reject; + ie6->value.present = F1AP_DLRRCMessageTransferIEs__value_PR_RRCContainer; + OCTET_STRING_fromBuf(&ie6->value.choice.RRCContainer, (const char *)msg->rrc_container, msg->rrc_container_length); + + return pdu; +} + +/** + * @brief DL RRC Message Transfer decoding (9.2.3.2 of 3GPP TS 38.473) + * gNB-CU → gNB-DU + */ +bool decode_dl_rrc_message_transfer(const F1AP_F1AP_PDU_t *pdu, f1ap_dl_rrc_message_t *out) +{ + DevAssert(out != NULL); + memset(out, 0, sizeof(*out)); + + DevAssert(pdu != NULL); + F1AP_DLRRCMessageTransfer_t *container = &pdu->choice.initiatingMessage->value.choice.DLRRCMessageTransfer; + F1AP_DLRRCMessageTransferIEs_t *ie; + // gNB-CU UE F1AP ID (M) + F1AP_LIB_FIND_IE(F1AP_DLRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); + out->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; + // gNB-DU UE F1AP ID (M) + F1AP_LIB_FIND_IE(F1AP_DLRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); + out->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; + // old gNB-DU UE F1AP ID (O) + out->old_gNB_DU_ue_id = NULL; + F1AP_LIB_FIND_IE(F1AP_DLRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_oldgNB_DU_UE_F1AP_ID, false); + if (ie) { + out->old_gNB_DU_ue_id = malloc_or_fail(sizeof(*out->old_gNB_DU_ue_id)); + *out->old_gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID_1; + } + // SRB ID (M) + F1AP_LIB_FIND_IE(F1AP_DLRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_SRBID, true); + out->srb_id = ie->value.choice.SRBID; + // Execute Duplication (O) + F1AP_LIB_FIND_IE(F1AP_DLRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_ExecuteDuplication, false); + if (ie) { + out->execute_duplication = ie->value.choice.ExecuteDuplication; + } + // RRC-Container (M) + F1AP_LIB_FIND_IE(F1AP_DLRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_RRCContainer, true); + out->rrc_container = cp_octet_string(&ie->value.choice.RRCContainer, &out->rrc_container_length); + + return true; +} + +/** + * @brief DL RRC Message Transfer deep copy + */ +f1ap_dl_rrc_message_t cp_dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *msg) +{ + uint8_t *rrc_container = calloc_or_fail(msg->rrc_container_length, sizeof(*rrc_container)); + memcpy(rrc_container, msg->rrc_container, msg->rrc_container_length); + + uint32_t *old_gNB_DU_ue_id = NULL; + if (msg->old_gNB_DU_ue_id) { + old_gNB_DU_ue_id = malloc_or_fail(sizeof(*old_gNB_DU_ue_id)); + *old_gNB_DU_ue_id = *(msg->old_gNB_DU_ue_id); + } + + f1ap_dl_rrc_message_t cp = { + .gNB_DU_ue_id = msg->gNB_DU_ue_id, + .gNB_CU_ue_id = msg->gNB_CU_ue_id, + .old_gNB_DU_ue_id = old_gNB_DU_ue_id, + .srb_id = msg->srb_id, + .execute_duplication = msg->execute_duplication, + .rrc_container = rrc_container, + .rrc_container_length = msg->rrc_container_length, + }; + + return cp; +} + +/** + * @brief DL RRC Message Transfer equality check + */ +bool eq_dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *a, const f1ap_dl_rrc_message_t *b) +{ + _F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id); + _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); + _F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id); + _F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id); + if (!(a->old_gNB_DU_ue_id == NULL && b->old_gNB_DU_ue_id == NULL)) + _F1_EQ_CHECK_INT(*a->old_gNB_DU_ue_id, *b->old_gNB_DU_ue_id); + _F1_EQ_CHECK_INT(a->srb_id, b->srb_id); + _F1_EQ_CHECK_INT(a->execute_duplication, b->execute_duplication); + _F1_EQ_CHECK_INT(a->rrc_container_length, b->rrc_container_length); + if (memcmp(a->rrc_container, b->rrc_container, a->rrc_container_length) != 0) + return false; + return true; +} + +/** + * @brief DL RRC Message Transfer memory management + */ +void free_dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *msg) +{ + DevAssert(msg != NULL); + free(msg->rrc_container); + free(msg->old_gNB_DU_ue_id); +} diff --git a/openair2/F1AP/lib/f1ap_rrc_message_transfer.h b/openair2/F1AP/lib/f1ap_rrc_message_transfer.h index 30a884e8fc..60aae835ab 100644 --- a/openair2/F1AP/lib/f1ap_rrc_message_transfer.h +++ b/openair2/F1AP/lib/f1ap_rrc_message_transfer.h @@ -33,4 +33,11 @@ f1ap_initial_ul_rrc_message_t cp_initial_ul_rrc_message_transfer(const f1ap_init bool eq_initial_ul_rrc_message_transfer(const f1ap_initial_ul_rrc_message_t *a, const f1ap_initial_ul_rrc_message_t *b); void free_initial_ul_rrc_message_transfer(const f1ap_initial_ul_rrc_message_t *msg); +/* DL RRC Message transfer */ +struct F1AP_F1AP_PDU *encode_dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *msg); +bool decode_dl_rrc_message_transfer(const struct F1AP_F1AP_PDU *pdu, f1ap_dl_rrc_message_t *out); +f1ap_dl_rrc_message_t cp_dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *msg); +bool eq_dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *a, const f1ap_dl_rrc_message_t *b); +void free_dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *msg); + #endif /* F1AP_RRC_MESSAGE_TRANSFER_H_ */ From 718269f1eb3af2b1d4886cf8aebcf6a4aa9d600f Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Mon, 13 May 2024 15:55:21 +0200 Subject: [PATCH 15/46] Add test for F1AP DL RRC Transfer enc/dec messages --- openair2/F1AP/tests/f1ap_lib_test.c | 40 +++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/openair2/F1AP/tests/f1ap_lib_test.c b/openair2/F1AP/tests/f1ap_lib_test.c index 896ea127e6..3bd71c97b5 100644 --- a/openair2/F1AP/tests/f1ap_lib_test.c +++ b/openair2/F1AP/tests/f1ap_lib_test.c @@ -82,8 +82,48 @@ static void test_initial_ul_rrc_message_transfer(void) free_initial_ul_rrc_message_transfer(&cp); } +/** + * @brief Test DL RRC Message Transfer encoding/decoding + */ +static void test_dl_rrc_message_transfer(void) +{ + uint8_t *rrc = (uint8_t *)calloc(strlen("RRC Container") + 1, sizeof(uint8_t)); + uint32_t *old_gNB_DU_ue_id = calloc(1, sizeof(uint32_t)); + AssertFatal(rrc != NULL && old_gNB_DU_ue_id != NULL, "out of memory\n"); + memcpy((void *)rrc, "RRC Container", strlen("RRC Container") + 1); + + f1ap_dl_rrc_message_t orig = { + .gNB_DU_ue_id = 12, + .gNB_CU_ue_id = 12, + .old_gNB_DU_ue_id = old_gNB_DU_ue_id, + .srb_id = 1, + .rrc_container = rrc, + .rrc_container_length = sizeof(rrc), + }; + + F1AP_F1AP_PDU_t *f1enc = encode_dl_rrc_message_transfer(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_dl_rrc_message_t decoded = {0}; + bool ret = decode_dl_rrc_message_transfer(f1dec, &decoded); + AssertFatal(ret, "decode_initial_ul_rrc_message_transfer(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_dl_rrc_message_transfer(&orig, &decoded); + AssertFatal(ret, "eq_dl_rrc_message_transfer(): decoded message doesn't match\n"); + free_dl_rrc_message_transfer(&decoded); + + f1ap_dl_rrc_message_t cp = cp_dl_rrc_message_transfer(&orig); + ret = eq_dl_rrc_message_transfer(&orig, &cp); + AssertFatal(ret, "eq_dl_rrc_message_transfer(): copied message doesn't match\n"); + free_dl_rrc_message_transfer(&orig); + free_dl_rrc_message_transfer(&cp); +} + int main() { test_initial_ul_rrc_message_transfer(); + test_dl_rrc_message_transfer(); return 0; } From 1d0d7e7bafe457376d171ac4db241dae5c62ea6f Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Thu, 29 Aug 2024 23:45:55 +0200 Subject: [PATCH 16/46] Use F1AP lib for DL RRC Message Transfer in stack --- openair2/F1AP/f1ap_cu_rrc_message_transfer.c | 114 +++---------------- openair2/F1AP/f1ap_du_rrc_message_transfer.c | 85 ++------------ openair2/RRC/NR/mac_rrc_dl_f1ap.c | 14 +-- 3 files changed, 28 insertions(+), 185 deletions(-) diff --git a/openair2/F1AP/f1ap_cu_rrc_message_transfer.c b/openair2/F1AP/f1ap_cu_rrc_message_transfer.c index 020c3be50d..66be251d04 100644 --- a/openair2/F1AP/f1ap_cu_rrc_message_transfer.c +++ b/openair2/F1AP/f1ap_cu_rrc_message_transfer.c @@ -66,105 +66,27 @@ int CU_handle_INITIAL_UL_RRC_MESSAGE_TRANSFER(instance_t instance, sctp_assoc_t /* DL RRC Message Transfer. */ -int CU_send_DL_RRC_MESSAGE_TRANSFER(sctp_assoc_t assoc_id, f1ap_dl_rrc_message_t *f1ap_dl_rrc) +int CU_send_DL_RRC_MESSAGE_TRANSFER(sctp_assoc_t assoc_id, f1ap_dl_rrc_message_t *msg) { - LOG_D(F1AP, "CU send DL_RRC_MESSAGE_TRANSFER \n"); - F1AP_F1AP_PDU_t pdu= {0}; - F1AP_DLRRCMessageTransfer_t *out; - uint8_t *buffer=NULL; - uint32_t len=0; - /* Create */ - /* 0. Message Type */ - pdu.present = F1AP_F1AP_PDU_PR_initiatingMessage; - asn1cCalloc(pdu.choice.initiatingMessage, tmp); - tmp->procedureCode = F1AP_ProcedureCode_id_DLRRCMessageTransfer; - tmp->criticality = F1AP_Criticality_ignore; - tmp->value.present = F1AP_InitiatingMessage__value_PR_DLRRCMessageTransfer; - out = &tmp->value.choice.DLRRCMessageTransfer; - /* mandatory */ - /* c1. GNB_CU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_DLRRCMessageTransferIEs_t, ie1); - ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; - ie1->criticality = F1AP_Criticality_reject; - ie1->value.present = F1AP_DLRRCMessageTransferIEs__value_PR_GNB_CU_UE_F1AP_ID; - DevAssert(f1ap_dl_rrc->gNB_CU_ue_id != 0); - ie1->value.choice.GNB_CU_UE_F1AP_ID = f1ap_dl_rrc->gNB_CU_ue_id; - - /* mandatory */ - /* c2. GNB_DU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_DLRRCMessageTransferIEs_t, ie2); - ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; - ie2->criticality = F1AP_Criticality_reject; - ie2->value.present = F1AP_DLRRCMessageTransferIEs__value_PR_GNB_DU_UE_F1AP_ID; - DevAssert(f1ap_dl_rrc->gNB_DU_ue_id != 0); - ie2->value.choice.GNB_DU_UE_F1AP_ID = f1ap_dl_rrc->gNB_DU_ue_id; - - /* optional */ - /* c3. oldgNB_DU_UE_F1AP_ID */ - if (f1ap_dl_rrc->old_gNB_DU_ue_id != NULL) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_DLRRCMessageTransferIEs_t, ie3); - ie3->id = F1AP_ProtocolIE_ID_id_oldgNB_DU_UE_F1AP_ID; - ie3->criticality = F1AP_Criticality_reject; - ie3->value.present = F1AP_DLRRCMessageTransferIEs__value_PR_GNB_DU_UE_F1AP_ID_1; - ie3->value.choice.GNB_DU_UE_F1AP_ID_1 = *f1ap_dl_rrc->old_gNB_DU_ue_id; - } - - /* mandatory */ - /* c4. SRBID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_DLRRCMessageTransferIEs_t, ie4); - ie4->id = F1AP_ProtocolIE_ID_id_SRBID; - ie4->criticality = F1AP_Criticality_reject; - ie4->value.present = F1AP_DLRRCMessageTransferIEs__value_PR_SRBID; - ie4->value.choice.SRBID = f1ap_dl_rrc->srb_id; - - /* optional */ - /* c5. ExecuteDuplication */ - if (f1ap_dl_rrc->execute_duplication) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_DLRRCMessageTransferIEs_t, ie5); - ie5->id = F1AP_ProtocolIE_ID_id_ExecuteDuplication; - ie5->criticality = F1AP_Criticality_ignore; - ie5->value.present = F1AP_DLRRCMessageTransferIEs__value_PR_ExecuteDuplication; - ie5->value.choice.ExecuteDuplication = F1AP_ExecuteDuplication_true; - } - - // issue in here - /* mandatory */ - /* c6. RRCContainer */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_DLRRCMessageTransferIEs_t, ie6); - ie6->id = F1AP_ProtocolIE_ID_id_RRCContainer; - ie6->criticality = F1AP_Criticality_reject; - ie6->value.present = F1AP_DLRRCMessageTransferIEs__value_PR_RRCContainer; - OCTET_STRING_fromBuf(&ie6->value.choice.RRCContainer, - (const char *)f1ap_dl_rrc->rrc_container, f1ap_dl_rrc->rrc_container_length); - - /* optional */ - /* c7. RAT_FrequencyPriorityInformation */ - /* TODO */ - if (0) { - int endc=1; - asn1cSequenceAdd(out->protocolIEs.list, F1AP_DLRRCMessageTransferIEs_t, ie7); - ie7->id = F1AP_ProtocolIE_ID_id_RAT_FrequencyPriorityInformation; - ie7->criticality = F1AP_Criticality_reject; - ie7->value.present = F1AP_DLRRCMessageTransferIEs__value_PR_RAT_FrequencyPriorityInformation; - - if (endc==1) { - ie7->value.choice.RAT_FrequencyPriorityInformation.present = F1AP_RAT_FrequencyPriorityInformation_PR_eNDC; - ie7->value.choice.RAT_FrequencyPriorityInformation.choice.eNDC = 123L; - } else { - ie7->value.choice.RAT_FrequencyPriorityInformation.present = F1AP_RAT_FrequencyPriorityInformation_PR_nGRAN; - ie7->value.choice.RAT_FrequencyPriorityInformation.choice.nGRAN = 11L; - } - - //ie->value.choice.RAT_FrequencyPriorityInformation.present = F1AP_RAT_FrequencyPriorityInformation_PR_rAT_FrequencySelectionPriority; - //ie->value.choice.RAT_FrequencyPriorityInformation.choice.rAT_FrequencySelectionPriority = 123L; - } - - /* encode */ - if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { - LOG_E(F1AP, "Failed to encode F1 DL RRC MESSAGE TRANSFER \n"); + /* encode DL RRC Message Transfer */ + F1AP_F1AP_PDU_t *pdu = encode_dl_rrc_message_transfer(msg); + if (pdu == NULL) { + LOG_E(F1AP, "Failed to encode F1 DL RRC MESSAGE TRANSFER: can't send message!\n"); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); return -1; } - + /* encode F1AP PDU */ + uint8_t *buffer = NULL; + uint32_t len = 0; + if (f1ap_encode_pdu(pdu, &buffer, &len) < 0) { + LOG_E(F1AP, "Failed to encode F1 DL RRC MESSAGE TRANSFER \n"); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); + return -1; + } + /* Free F1AP PDU */ + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); + /* Send to DU */ + LOG_D(F1AP, "CU send DL_RRC_MESSAGE_TRANSFER \n"); f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); return 0; } diff --git a/openair2/F1AP/f1ap_du_rrc_message_transfer.c b/openair2/F1AP/f1ap_du_rrc_message_transfer.c index 62e6c1f0e3..74178b17c3 100644 --- a/openair2/F1AP/f1ap_du_rrc_message_transfer.c +++ b/openair2/F1AP/f1ap_du_rrc_message_transfer.c @@ -58,85 +58,16 @@ /* DL RRC Message Transfer */ int DU_handle_DL_RRC_MESSAGE_TRANSFER(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { - F1AP_DLRRCMessageTransfer_t *container; - F1AP_DLRRCMessageTransferIEs_t *ie; - int executeDuplication; - //uint64_t subscriberProfileIDforRFP; - //uint64_t rAT_FrequencySelectionPriority; - DevAssert(pdu != NULL); - container = &pdu->choice.initiatingMessage->value.choice.DLRRCMessageTransfer; - /* GNB_CU_UE_F1AP_ID */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_DLRRCMessageTransferIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); - uint32_t cu_ue_f1ap_id = ie->value.choice.GNB_CU_UE_F1AP_ID; - /* GNB_DU_UE_F1AP_ID */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_DLRRCMessageTransferIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); - uint32_t du_ue_f1ap_id = ie->value.choice.GNB_DU_UE_F1AP_ID; - - /* optional */ - /* oldgNB_DU_UE_F1AP_ID */ - uint32_t *old_gNB_DU_ue_id = NULL; - uint32_t old_gNB_DU_ue_id_stack = 0; - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_DLRRCMessageTransferIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_oldgNB_DU_UE_F1AP_ID, false); - if (ie) { - /* strange: it is not named OLD_GNB_DU_UE... */ - old_gNB_DU_ue_id_stack = ie->value.choice.GNB_DU_UE_F1AP_ID_1; - old_gNB_DU_ue_id = &old_gNB_DU_ue_id_stack; + f1ap_dl_rrc_message_t msg = {0}; + if (!decode_dl_rrc_message_transfer(pdu, &msg)) { + LOG_E(F1AP, "cannot decode F1 DL RRC message Transfer\n"); + free_dl_rrc_message_transfer(&msg); + return -1; } - /* mandatory */ - /* SRBID */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_DLRRCMessageTransferIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_SRBID, true); - uint64_t srb_id = ie->value.choice.SRBID; - LOG_D(F1AP, "srb_id %lu \n", srb_id); - - /* optional */ - /* ExecuteDuplication */ - if (0) { - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_DLRRCMessageTransferIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_ExecuteDuplication, true); - executeDuplication = ie->value.choice.ExecuteDuplication; - LOG_D(F1AP, "ExecuteDuplication %d \n", executeDuplication); - } - - // issue in here - /* mandatory */ - /* RRC Container */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_DLRRCMessageTransferIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_RRCContainer, true); - /* optional */ - /* RAT_FrequencyPriorityInformation */ - if (0) { - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_DLRRCMessageTransferIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_RAT_FrequencyPriorityInformation, true); - - switch(ie->value.choice.RAT_FrequencyPriorityInformation.present) { - case F1AP_RAT_FrequencyPriorityInformation_PR_eNDC: - //subscriberProfileIDforRFP = ie->value.choice.RAT_FrequencyPriorityInformation.choice.subscriberProfileIDforRFP; - break; - - case F1AP_RAT_FrequencyPriorityInformation_PR_nGRAN: - //rAT_FrequencySelectionPriority = ie->value.choice.RAT_FrequencyPriorityInformation.choice.rAT_FrequencySelectionPriority; - break; - - default: - LOG_W(F1AP, "unhandled IE RAT_FrequencyPriorityInformation.present\n"); - break; - } - } - - f1ap_dl_rrc_message_t dl_rrc = { - .gNB_CU_ue_id = cu_ue_f1ap_id, - .gNB_DU_ue_id = du_ue_f1ap_id, - .old_gNB_DU_ue_id = old_gNB_DU_ue_id, - .rrc_container_length = ie->value.choice.RRCContainer.size, - .rrc_container = ie->value.choice.RRCContainer.buf, - .srb_id = srb_id - }; - dl_rrc_message_transfer(&dl_rrc); + dl_rrc_message_transfer(&msg); + /* Free DL RRC Message Transfer */ + free_dl_rrc_message_transfer(&msg); return 0; } diff --git a/openair2/RRC/NR/mac_rrc_dl_f1ap.c b/openair2/RRC/NR/mac_rrc_dl_f1ap.c index 439712ec7e..9f1b8b4b53 100644 --- a/openair2/RRC/NR/mac_rrc_dl_f1ap.c +++ b/openair2/RRC/NR/mac_rrc_dl_f1ap.c @@ -23,6 +23,7 @@ #include "mac_rrc_dl.h" #include "nr_rrc_defs.h" +#include "openair2/F1AP/lib/f1ap_rrc_message_transfer.h" static void f1_reset_cu_initiated_f1ap(sctp_assoc_t assoc_id, const f1ap_reset_t *reset) { @@ -210,18 +211,7 @@ static void dl_rrc_message_transfer_f1ap(sctp_assoc_t assoc_id, const f1ap_dl_rr MessageDef *message_p = itti_alloc_new_message (TASK_RRC_GNB, 0, F1AP_DL_RRC_MESSAGE); message_p->ittiMsgHeader.originInstance = assoc_id; f1ap_dl_rrc_message_t *msg = &F1AP_DL_RRC_MESSAGE(message_p); - *msg = *dl_rrc; - if (dl_rrc->old_gNB_DU_ue_id) { - msg->old_gNB_DU_ue_id = malloc(sizeof(*msg->old_gNB_DU_ue_id)); - AssertFatal(msg->old_gNB_DU_ue_id != NULL, "out of memory\n"); - *msg->old_gNB_DU_ue_id = *dl_rrc->old_gNB_DU_ue_id; - } - if (dl_rrc->rrc_container) { - msg->rrc_container = malloc(dl_rrc->rrc_container_length); - AssertFatal(msg->rrc_container != NULL, "out of memory\n"); - msg->rrc_container_length = dl_rrc->rrc_container_length; - memcpy(msg->rrc_container, dl_rrc->rrc_container, dl_rrc->rrc_container_length); - } + *msg = cp_dl_rrc_message_transfer(dl_rrc); itti_send_msg_to_task (TASK_CU_F1, 0, message_p); } From b85fd159b840a811f9bec243e98976ebf8d23f1b Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Mon, 13 May 2024 15:19:06 +0200 Subject: [PATCH 17/46] Add encoding/decoding lib for UL RRC Message Trasfer --- openair2/F1AP/lib/f1ap_rrc_message_transfer.c | 120 +++++++++++++++++- openair2/F1AP/lib/f1ap_rrc_message_transfer.h | 7 + 2 files changed, 126 insertions(+), 1 deletion(-) diff --git a/openair2/F1AP/lib/f1ap_rrc_message_transfer.c b/openair2/F1AP/lib/f1ap_rrc_message_transfer.c index e449d68096..5fc9e2d622 100644 --- a/openair2/F1AP/lib/f1ap_rrc_message_transfer.c +++ b/openair2/F1AP/lib/f1ap_rrc_message_transfer.c @@ -23,7 +23,6 @@ #include "f1ap_lib_common.h" #include "f1ap_lib_includes.h" - #include "f1ap_messages_types.h" #include "common/utils/assertions.h" @@ -198,6 +197,125 @@ void free_initial_ul_rrc_message_transfer(const f1ap_initial_ul_rrc_message_t *m free(msg->du2cu_rrc_container); } +/* ==================================== + * F1AP UL RRC Message Transfer + * ==================================== */ + +/** + * @brief UL RRC Message Transfer encoding (9.2.3.3 of 3GPP TS 38.473) + * gNB-DU → gNB-CU + */ +F1AP_F1AP_PDU_t *encode_ul_rrc_message_transfer(const f1ap_ul_rrc_message_t *msg) +{ + + F1AP_F1AP_PDU_t *pdu = calloc(1, sizeof(*pdu)); + AssertFatal(pdu != NULL, "out of memory\n"); + + /* Create */ + /* 0. Message Type */ + pdu->present = F1AP_F1AP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu->choice.initiatingMessage, tmp); + tmp->procedureCode = F1AP_ProcedureCode_id_ULRRCMessageTransfer; + tmp->criticality = F1AP_Criticality_ignore; + tmp->value.present = F1AP_InitiatingMessage__value_PR_ULRRCMessageTransfer; + F1AP_ULRRCMessageTransfer_t *out = &tmp->value.choice.ULRRCMessageTransfer; + // gNB-CU UE F1AP ID (M) + asn1cSequenceAdd(out->protocolIEs.list, F1AP_ULRRCMessageTransferIEs_t, ie1); + ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; + ie1->criticality = F1AP_Criticality_reject; + ie1->value.present = F1AP_ULRRCMessageTransferIEs__value_PR_GNB_CU_UE_F1AP_ID; + ie1->value.choice.GNB_CU_UE_F1AP_ID = msg->gNB_CU_ue_id; + // gNB-DU UE F1AP ID (M) + asn1cSequenceAdd(out->protocolIEs.list, F1AP_ULRRCMessageTransferIEs_t, ie2); + ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; + ie2->criticality = F1AP_Criticality_reject; + ie2->value.present = F1AP_ULRRCMessageTransferIEs__value_PR_GNB_DU_UE_F1AP_ID; + ie2->value.choice.GNB_DU_UE_F1AP_ID = msg->gNB_DU_ue_id; + // SRB ID (M) + asn1cSequenceAdd(out->protocolIEs.list, F1AP_ULRRCMessageTransferIEs_t, ie3); + ie3->id = F1AP_ProtocolIE_ID_id_SRBID; + ie3->criticality = F1AP_Criticality_reject; + ie3->value.present = F1AP_ULRRCMessageTransferIEs__value_PR_SRBID; + ie3->value.choice.SRBID = msg->srb_id; + // RRC-Container (M) + asn1cSequenceAdd(out->protocolIEs.list, F1AP_ULRRCMessageTransferIEs_t, ie4); + ie4->id = F1AP_ProtocolIE_ID_id_RRCContainer; + ie4->criticality = F1AP_Criticality_reject; + ie4->value.present = F1AP_ULRRCMessageTransferIEs__value_PR_RRCContainer; + OCTET_STRING_fromBuf(&ie4->value.choice.RRCContainer, (const char *)msg->rrc_container, msg->rrc_container_length); + + return pdu; +} + +/** + * @brief UL RRC Message Transfer decoding (9.2.3.3 of 3GPP TS 38.473) + * gNB-DU → gNB-CU + */ +bool decode_ul_rrc_message_transfer(const F1AP_F1AP_PDU_t *pdu, f1ap_ul_rrc_message_t *out) +{ + DevAssert(out != NULL); + memset(out, 0, sizeof(*out)); + DevAssert(pdu != NULL); + + F1AP_ULRRCMessageTransfer_t *container = &pdu->choice.initiatingMessage->value.choice.ULRRCMessageTransfer; + F1AP_ULRRCMessageTransferIEs_t *ie; + + // gNB-CU UE F1AP ID (M) + F1AP_LIB_FIND_IE(F1AP_ULRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); + out->gNB_CU_ue_id = ie->value.choice.GNB_CU_UE_F1AP_ID; + // gNB-DU UE F1AP ID (M) + F1AP_LIB_FIND_IE(F1AP_ULRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); + out->gNB_DU_ue_id = ie->value.choice.GNB_DU_UE_F1AP_ID; + // SRB ID (M) + F1AP_LIB_FIND_IE(F1AP_ULRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_SRBID, true); + out->srb_id = ie->value.choice.SRBID; + // RRC-Container (M) + F1AP_LIB_FIND_IE(F1AP_ULRRCMessageTransferIEs_t, ie, container, F1AP_ProtocolIE_ID_id_RRCContainer, true); + out->rrc_container = cp_octet_string(&ie->value.choice.RRCContainer, &out->rrc_container_length); + + return true; +} + +/** + * @brief UL RRC Message Transfer deep copy + */ +f1ap_ul_rrc_message_t cp_ul_rrc_message_transfer(const f1ap_ul_rrc_message_t *msg) +{ + uint8_t *rrc_container = calloc_or_fail(msg->rrc_container_length, sizeof(*rrc_container)); + memcpy(rrc_container, msg->rrc_container, msg->rrc_container_length); + f1ap_ul_rrc_message_t cp = { + .gNB_DU_ue_id = msg->gNB_DU_ue_id, + .gNB_CU_ue_id = msg->gNB_CU_ue_id, + .srb_id = msg->srb_id, + .rrc_container = rrc_container, + .rrc_container_length = msg->rrc_container_length, + }; + return cp; +} + +/** + * @brief UL RRC Message Transfer equality check + */ +bool eq_ul_rrc_message_transfer(const f1ap_ul_rrc_message_t *a, const f1ap_ul_rrc_message_t *b) +{ + _F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id); + _F1_EQ_CHECK_INT(a->gNB_CU_ue_id, b->gNB_CU_ue_id); + _F1_EQ_CHECK_INT(a->rrc_container_length, b->rrc_container_length); + _F1_EQ_CHECK_INT(a->gNB_DU_ue_id, b->gNB_DU_ue_id); + if (memcmp(a->rrc_container, b->rrc_container, a->rrc_container_length) != 0) + return false; + return true; +} + +/** + * @brief UL RRC Message Transfer memory management + */ +void free_ul_rrc_message_transfer(const f1ap_ul_rrc_message_t *msg) +{ + DevAssert(msg != NULL); + free(msg->rrc_container); +} + /* ============================ * F1AP DL RRC Message Transfer * ============================ */ diff --git a/openair2/F1AP/lib/f1ap_rrc_message_transfer.h b/openair2/F1AP/lib/f1ap_rrc_message_transfer.h index 60aae835ab..4e6d682f78 100644 --- a/openair2/F1AP/lib/f1ap_rrc_message_transfer.h +++ b/openair2/F1AP/lib/f1ap_rrc_message_transfer.h @@ -40,4 +40,11 @@ f1ap_dl_rrc_message_t cp_dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *ms bool eq_dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *a, const f1ap_dl_rrc_message_t *b); void free_dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *msg); +/* UL RRC Message transfer */ +struct F1AP_F1AP_PDU *encode_ul_rrc_message_transfer(const f1ap_ul_rrc_message_t *msg); +bool decode_ul_rrc_message_transfer(const struct F1AP_F1AP_PDU *pdu, f1ap_ul_rrc_message_t *out); +f1ap_ul_rrc_message_t cp_ul_rrc_message_transfer(const f1ap_ul_rrc_message_t *msg); +bool eq_ul_rrc_message_transfer(const f1ap_ul_rrc_message_t *a, const f1ap_ul_rrc_message_t *b); +void free_ul_rrc_message_transfer(const f1ap_ul_rrc_message_t *msg); + #endif /* F1AP_RRC_MESSAGE_TRANSFER_H_ */ From cc0ad07aa0025bb4e6a050a8b8091e8c44926569 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Mon, 13 May 2024 15:51:22 +0200 Subject: [PATCH 18/46] Add test for F1AP UL RRC Message Transfer enc/dec lib --- openair2/F1AP/tests/f1ap_lib_test.c | 37 ++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/openair2/F1AP/tests/f1ap_lib_test.c b/openair2/F1AP/tests/f1ap_lib_test.c index 3bd71c97b5..5974e52f7a 100644 --- a/openair2/F1AP/tests/f1ap_lib_test.c +++ b/openair2/F1AP/tests/f1ap_lib_test.c @@ -87,7 +87,7 @@ static void test_initial_ul_rrc_message_transfer(void) */ static void test_dl_rrc_message_transfer(void) { - uint8_t *rrc = (uint8_t *)calloc(strlen("RRC Container") + 1, sizeof(uint8_t)); + uint8_t *rrc = calloc(strlen("RRC Container") + 1, sizeof(uint8_t)); uint32_t *old_gNB_DU_ue_id = calloc(1, sizeof(uint32_t)); AssertFatal(rrc != NULL && old_gNB_DU_ue_id != NULL, "out of memory\n"); memcpy((void *)rrc, "RRC Container", strlen("RRC Container") + 1); @@ -121,9 +121,44 @@ static void test_dl_rrc_message_transfer(void) free_dl_rrc_message_transfer(&cp); } +/** + * @brief Test UL RRC Message Transfer encoding/decoding + */ +static void test_ul_rrc_message_transfer(void) +{ + uint8_t rrc[] = "RRC Container"; + + f1ap_ul_rrc_message_t orig = { + .gNB_DU_ue_id = 12, + .gNB_CU_ue_id = 12, + .srb_id = 1, + .rrc_container = rrc, + .rrc_container_length = sizeof(rrc), + }; + + F1AP_F1AP_PDU_t *f1enc = encode_ul_rrc_message_transfer(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_ul_rrc_message_t decoded = {0}; + bool ret = decode_ul_rrc_message_transfer(f1dec, &decoded); + AssertFatal(ret, "decode_initial_ul_rrc_message_transfer(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_ul_rrc_message_transfer(&orig, &decoded); + AssertFatal(ret, "eq_dl_rrc_message_transfer(): decoded message doesn't match\n"); + free_ul_rrc_message_transfer(&decoded); + + f1ap_ul_rrc_message_t cp = cp_ul_rrc_message_transfer(&orig); + ret = eq_ul_rrc_message_transfer(&orig, &cp); + AssertFatal(ret, "eq_dl_rrc_message_transfer(): copied message doesn't match\n"); + free_ul_rrc_message_transfer(&cp); +} + int main() { test_initial_ul_rrc_message_transfer(); test_dl_rrc_message_transfer(); + test_ul_rrc_message_transfer(); return 0; } From 1a8ed8642fef7a010ecd3d1cfe9c7f71bff1228b Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Thu, 29 Aug 2024 23:47:19 +0200 Subject: [PATCH 19/46] Use F1AP lib for UL RRC Message Trasfer in stack --- openair2/F1AP/f1ap_cu_rrc_message_transfer.c | 89 +++++++++----------- openair2/F1AP/f1ap_du_rrc_message_transfer.c | 67 ++++----------- 2 files changed, 56 insertions(+), 100 deletions(-) diff --git a/openair2/F1AP/f1ap_cu_rrc_message_transfer.c b/openair2/F1AP/f1ap_cu_rrc_message_transfer.c index 66be251d04..cf85961ff5 100644 --- a/openair2/F1AP/f1ap_cu_rrc_message_transfer.c +++ b/openair2/F1AP/f1ap_cu_rrc_message_transfer.c @@ -96,76 +96,67 @@ int CU_send_DL_RRC_MESSAGE_TRANSFER(sctp_assoc_t assoc_id, f1ap_dl_rrc_message_t */ int CU_handle_UL_RRC_MESSAGE_TRANSFER(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { - LOG_D(F1AP, "CU_handle_UL_RRC_MESSAGE_TRANSFER \n"); - F1AP_ULRRCMessageTransfer_t *container; - F1AP_ULRRCMessageTransferIEs_t *ie; - uint64_t cu_ue_f1ap_id; - uint64_t du_ue_f1ap_id; - uint64_t srb_id; - DevAssert(pdu != NULL); - if (stream != 0) { LOG_E(F1AP, "[SCTP %d] Received F1 on stream != 0 (%d)\n", assoc_id, stream); return -1; } - container = &pdu->choice.initiatingMessage->value.choice.ULRRCMessageTransfer; - /* GNB_CU_UE_F1AP_ID */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_ULRRCMessageTransferIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID, true); - cu_ue_f1ap_id = ie->value.choice.GNB_CU_UE_F1AP_ID; - /* GNB_DU_UE_F1AP_ID */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_ULRRCMessageTransferIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID, true); - du_ue_f1ap_id = ie->value.choice.GNB_DU_UE_F1AP_ID; + f1ap_ul_rrc_message_t msg = {0}; - if (!cu_exists_f1_ue_data(cu_ue_f1ap_id)) { - LOG_E(F1AP, "unknown CU UE ID %ld\n", cu_ue_f1ap_id); - return 1; + LOG_D(F1AP, "CU_handle_UL_RRC_MESSAGE_TRANSFER \n"); + if (!decode_ul_rrc_message_transfer(pdu, &msg)) { + LOG_E(F1AP, "cannot decode F1 UL RRC message Transfer\n"); + free_ul_rrc_message_transfer(&msg); + return -1; + } + + if (!cu_exists_f1_ue_data(msg.gNB_CU_ue_id)) { + LOG_E(F1AP, "unknown CU UE ID %d\n", msg.gNB_CU_ue_id); + free_ul_rrc_message_transfer(&msg); + return -1; } /* the RLC-PDCP does not transport the DU UE ID (yet), so we drop it here. * For the moment, let's hope this won't become relevant; to sleep in peace, * let's put an assert to check that it is the expected DU UE ID. */ - f1_ue_data_t ue_data = cu_get_f1_ue_data(cu_ue_f1ap_id); - if (ue_data.secondary_ue != du_ue_f1ap_id) { - LOG_E(F1AP, "unexpected DU UE ID %u received, expected it to be %lu\n", ue_data.secondary_ue, du_ue_f1ap_id); - return 1; + f1_ue_data_t ue_data = cu_get_f1_ue_data(msg.gNB_CU_ue_id); + if (ue_data.secondary_ue != msg.gNB_DU_ue_id) { + LOG_E(F1AP, "unexpected DU UE ID %u received, expected it to be %u\n", ue_data.secondary_ue, msg.gNB_DU_ue_id); + free_ul_rrc_message_transfer(&msg); + return -1; } - /* mandatory */ - /* SRBID */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_ULRRCMessageTransferIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_SRBID, true); - srb_id = ie->value.choice.SRBID; - - if (srb_id < 1 ) - LOG_E(F1AP, "Unexpected UL RRC MESSAGE for srb_id %lu \n", srb_id); + if (msg.srb_id < 1) + LOG_E(F1AP, "Unexpected UL RRC MESSAGE for SRB %d \n", msg.srb_id); else - LOG_D(F1AP, "UL RRC MESSAGE for srb_id %lu in DCCH \n", srb_id); + LOG_D(F1AP, "UL RRC MESSAGE for SRB %d in DCCH \n", msg.srb_id); + + protocol_ctxt_t ctxt = { + .instance = instance, + .module_id = instance, + .enb_flag = 1, + .eNB_index = 0, + .rntiMaybeUEid = msg.gNB_CU_ue_id, + }; + + LOG_D(F1AP, + "[UE %lx] calling pdcp_data_ind for SRB %d with size %d (DCCH) \n", + ctxt.rntiMaybeUEid, + msg.srb_id, + msg.rrc_container_length); + uint8_t *mb = malloc16(msg.rrc_container_length); + memcpy(mb, msg.rrc_container, msg.rrc_container_length); - // issue in here - /* mandatory */ - /* RRC Container */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_ULRRCMessageTransferIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_RRCContainer, true); - protocol_ctxt_t ctxt={0}; - ctxt.instance = instance; - ctxt.module_id = instance; - ctxt.rntiMaybeUEid = cu_ue_f1ap_id; - ctxt.enb_flag = 1; - ctxt.eNB_index = 0; - uint8_t *mb = malloc16(ie->value.choice.RRCContainer.size); - memcpy(mb, ie->value.choice.RRCContainer.buf, ie->value.choice.RRCContainer.size); - LOG_D(F1AP, "Calling pdcp_data_ind for UE RNTI %lx srb_id %lu with size %ld (DCCH) \n", ctxt.rntiMaybeUEid, srb_id, ie->value.choice.RRCContainer.size); nr_pdcp_data_ind(&ctxt, 1, // srb_flag 0, // embms_flag - srb_id, - ie->value.choice.RRCContainer.size, + msg.srb_id, + msg.rrc_container_length, mb, NULL, NULL); + /* Free UL RRC Message Transfer */ + free_ul_rrc_message_transfer(&msg); return 0; } diff --git a/openair2/F1AP/f1ap_du_rrc_message_transfer.c b/openair2/F1AP/f1ap_du_rrc_message_transfer.c index 74178b17c3..5f150bf25c 100644 --- a/openair2/F1AP/f1ap_du_rrc_message_transfer.c +++ b/openair2/F1AP/f1ap_du_rrc_message_transfer.c @@ -100,64 +100,29 @@ int DU_send_INITIAL_UL_RRC_MESSAGE_TRANSFER(sctp_assoc_t assoc_id, const f1ap_in int DU_send_UL_NR_RRC_MESSAGE_TRANSFER(sctp_assoc_t assoc_id, const f1ap_ul_rrc_message_t *msg) { - F1AP_F1AP_PDU_t pdu= {0}; - F1AP_ULRRCMessageTransfer_t *out; - uint8_t *buffer = NULL; - uint32_t len; LOG_D(F1AP, "size %d UE RNTI %x in SRB %d\n", msg->rrc_container_length, msg->gNB_DU_ue_id, msg->srb_id); - //for (int i = 0;i < msg->rrc_container_length; i++) - // printf("%02x ", msg->rrc_container[i]); - //printf("\n"); - /* Create */ - /* 0. Message Type */ - pdu.present = F1AP_F1AP_PDU_PR_initiatingMessage; - asn1cCalloc(pdu.choice.initiatingMessage, tmp); - tmp->procedureCode = F1AP_ProcedureCode_id_ULRRCMessageTransfer; - tmp->criticality = F1AP_Criticality_ignore; - tmp->value.present = F1AP_InitiatingMessage__value_PR_ULRRCMessageTransfer; - out = &tmp->value.choice.ULRRCMessageTransfer; - /* mandatory */ - /* c1. GNB_CU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_ULRRCMessageTransferIEs_t, ie1); - ie1->id = F1AP_ProtocolIE_ID_id_gNB_CU_UE_F1AP_ID; - ie1->criticality = F1AP_Criticality_reject; - ie1->value.present = F1AP_ULRRCMessageTransferIEs__value_PR_GNB_CU_UE_F1AP_ID; - ie1->value.choice.GNB_CU_UE_F1AP_ID = msg->gNB_CU_ue_id; - /* mandatory */ - /* c2. GNB_DU_UE_F1AP_ID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_ULRRCMessageTransferIEs_t, ie2); - ie2->id = F1AP_ProtocolIE_ID_id_gNB_DU_UE_F1AP_ID; - ie2->criticality = F1AP_Criticality_reject; - ie2->value.present = F1AP_ULRRCMessageTransferIEs__value_PR_GNB_DU_UE_F1AP_ID; - ie2->value.choice.GNB_DU_UE_F1AP_ID = msg->gNB_DU_ue_id; - /* mandatory */ - /* c3. SRBID */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_ULRRCMessageTransferIEs_t, ie3); - ie3->id = F1AP_ProtocolIE_ID_id_SRBID; - ie3->criticality = F1AP_Criticality_reject; - ie3->value.present = F1AP_ULRRCMessageTransferIEs__value_PR_SRBID; - ie3->value.choice.SRBID = msg->srb_id; - // issue in here - /* mandatory */ - /* c4. RRCContainer */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_ULRRCMessageTransferIEs_t, ie4); - ie4->id = F1AP_ProtocolIE_ID_id_RRCContainer; - ie4->criticality = F1AP_Criticality_reject; - ie4->value.present = F1AP_ULRRCMessageTransferIEs__value_PR_RRCContainer; - OCTET_STRING_fromBuf(&ie4->value.choice.RRCContainer, - (const char *) msg->rrc_container, - msg->rrc_container_length); - - /* encode */ - if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { - LOG_E(F1AP, "Failed to encode F1 UL RRC MESSAGE TRANSFER \n"); + /* encode UL RRC Message Transfer */ + F1AP_F1AP_PDU_t *pdu = encode_ul_rrc_message_transfer(msg); + if (pdu == NULL) { + LOG_E(F1AP, "Failed to encode F1 UL RRC MESSAGE TRANSFER: cannot send message\n"); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); return -1; } - + /* encode F1AP PDU */ + uint8_t *buffer = NULL; + uint32_t len; + if (f1ap_encode_pdu(pdu, &buffer, &len) < 0) { + LOG_E(F1AP, "Failed to encode F1 UL RRC MESSAGE TRANSFER \n"); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); + return -1; + } + /* Free F1AP PDU */ + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); + /* Send to ITTI */ f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); return 0; } From f278b008375d415ad4b6a6d381647581d9afe434 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Tue, 21 May 2024 22:36:49 +0200 Subject: [PATCH 20/46] Add encoding/decoding library for F1AP Setup Request (Interface Management) --- openair2/COMMON/f1ap_messages_types.h | 2 +- openair2/F1AP/f1ap_cu_interface_management.c | 2 + openair2/F1AP/lib/CMakeLists.txt | 1 + openair2/F1AP/lib/f1ap_interface_management.c | 521 ++++++++++++++++++ openair2/F1AP/lib/f1ap_interface_management.h | 36 ++ openair2/F1AP/lib/f1ap_lib_common.c | 75 ++- openair2/F1AP/lib/f1ap_lib_common.h | 9 + openair2/F1AP/lib/f1ap_lib_includes.h | 10 + 8 files changed, 654 insertions(+), 2 deletions(-) create mode 100644 openair2/F1AP/lib/f1ap_interface_management.c create mode 100644 openair2/F1AP/lib/f1ap_interface_management.h diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index f34b1dfea7..2224cf822f 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -190,7 +190,7 @@ typedef struct served_cells_to_activate_s { f1ap_plmn_t plmn; // NR Global Cell Id uint64_t nr_cellid; - /// NRPCI + /// NRPCI [int 0..1007] uint16_t nrpci; /// num SI messages per DU cell uint8_t num_SI; diff --git a/openair2/F1AP/f1ap_cu_interface_management.c b/openair2/F1AP/f1ap_cu_interface_management.c index afd2775863..e420ddf295 100644 --- a/openair2/F1AP/f1ap_cu_interface_management.c +++ b/openair2/F1AP/f1ap_cu_interface_management.c @@ -34,6 +34,8 @@ #include "f1ap_encoder.h" #include "f1ap_itti_messaging.h" #include "f1ap_cu_interface_management.h" +#include "f1ap_default_values.h" +#include "lib/f1ap_interface_management.h" int CU_handle_RESET_ACKNOWLEDGE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { diff --git a/openair2/F1AP/lib/CMakeLists.txt b/openair2/F1AP/lib/CMakeLists.txt index 7e08cb18b1..cb8d8b9712 100644 --- a/openair2/F1AP/lib/CMakeLists.txt +++ b/openair2/F1AP/lib/CMakeLists.txt @@ -1,6 +1,7 @@ add_library(f1ap_lib OBJECT f1ap_lib_common.c f1ap_rrc_message_transfer.c + f1ap_interface_management.c ) target_link_libraries(f1ap_lib PRIVATE asn1_f1ap) target_include_directories(f1ap_lib PUBLIC diff --git a/openair2/F1AP/lib/f1ap_interface_management.c b/openair2/F1AP/lib/f1ap_interface_management.c new file mode 100644 index 0000000000..437fa4f36d --- /dev/null +++ b/openair2/F1AP/lib/f1ap_interface_management.c @@ -0,0 +1,521 @@ +/* + * 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/utils/assertions.h" +#include "openair3/UTILS/conversions.h" +#include "common/utils/oai_asn1.h" +#include "common/utils/utils.h" + +#include "f1ap_interface_management.h" +#include "f1ap_lib_common.h" +#include "f1ap_lib_includes.h" +#include "f1ap_messages_types.h" +#include "f1ap_lib_extern.h" + +static const int nrb_lut[29] = {11, 18, 24, 25, 31, 32, 38, 51, 52, 65, 66, 78, 79, 93, 106, + 107, 121, 132, 133, 135, 160, 162, 189, 216, 217, 245, 264, 270, 273}; + +static int to_NRNRB(int nrb) +{ + for (int i = 0; i < sizeofArray(nrb_lut); i++) + if (nrb_lut[i] == nrb) + return i; + AssertFatal(1 == 0, "nrb %d is not in the list of possible NRNRB\n", nrb); +} + +static int read_slice_info(const F1AP_ServedPLMNs_Item_t *plmn, nssai_t *nssai, int max_nssai) +{ + if (plmn->iE_Extensions == NULL) + return 0; + + const F1AP_ProtocolExtensionContainer_10696P34_t *p = (F1AP_ProtocolExtensionContainer_10696P34_t *)plmn->iE_Extensions; + if (p->list.count == 0) + return 0; + + const F1AP_ServedPLMNs_ItemExtIEs_t *splmn = p->list.array[0]; + DevAssert(splmn->id == F1AP_ProtocolIE_ID_id_TAISliceSupportList); + DevAssert(splmn->extensionValue.present == F1AP_ServedPLMNs_ItemExtIEs__extensionValue_PR_SliceSupportList); + const F1AP_SliceSupportList_t *ssl = &splmn->extensionValue.choice.SliceSupportList; + AssertFatal(ssl->list.count <= max_nssai, "cannot handle more than 16 slices\n"); + for (int s = 0; s < ssl->list.count; ++s) { + const F1AP_SliceSupportItem_t *sl = ssl->list.array[s]; + nssai_t *n = &nssai[s]; + OCTET_STRING_TO_INT8(&sl->sNSSAI.sST, n->sst); + n->sd = 0xffffff; + if (sl->sNSSAI.sD != NULL) + OCTET_STRING_TO_INT24(sl->sNSSAI.sD, n->sd); + } + + return ssl->list.count; +} + +/** + * @brief F1AP Setup Request memory management + */ +static void free_f1ap_cell(const f1ap_served_cell_info_t *info, const f1ap_gnb_du_system_info_t *sys_info) +{ + if (sys_info) { + free(sys_info->mib); + free(sys_info->sib1); + free((void *)sys_info); + } + free(info->measurement_timing_config); + free(info->tac); +} + +/** + * @brief Encoding of Served Cell Information (9.3.1.10 of 3GPP TS 38.473) + */ +static F1AP_Served_Cell_Information_t encode_served_cell_info(const f1ap_served_cell_info_t *c) +{ + F1AP_Served_Cell_Information_t scell_info = {0}; + // NR CGI + MCC_MNC_TO_PLMNID(c->plmn.mcc, c->plmn.mnc, c->plmn.mnc_digit_length, &(scell_info.nRCGI.pLMN_Identity)); + NR_CELL_ID_TO_BIT_STRING(c->nr_cellid, &(scell_info.nRCGI.nRCellIdentity)); + // NR PCI + scell_info.nRPCI = c->nr_pci; // int 0..1007 + // 5GS TAC + if (c->tac != NULL) { + uint32_t tac = htonl(*c->tac); + asn1cCalloc(scell_info.fiveGS_TAC, netOrder); + OCTET_STRING_fromBuf(netOrder, ((char *)&tac) + 1, 3); + } + // Served PLMNs + asn1cSequenceAdd(scell_info.servedPLMNs.list, F1AP_ServedPLMNs_Item_t, servedPLMN_item); + MCC_MNC_TO_PLMNID(c->plmn.mcc, c->plmn.mnc, c->plmn.mnc_digit_length, &servedPLMN_item->pLMN_Identity); + // NR-Mode-Info + F1AP_NR_Mode_Info_t *nR_Mode_Info = &scell_info.nR_Mode_Info; + if (c->mode == F1AP_MODE_FDD) { // FDD + const f1ap_fdd_info_t *fdd = &c->fdd; + nR_Mode_Info->present = F1AP_NR_Mode_Info_PR_fDD; + asn1cCalloc(nR_Mode_Info->choice.fDD, fDD_Info); + /* FDD.1.1 UL NRFreqInfo ARFCN */ + fDD_Info->uL_NRFreqInfo.nRARFCN = fdd->ul_freqinfo.arfcn; + /* FDD.1.3 freqBandListNr */ + int ul_band = 1; + for (int j = 0; j < ul_band; j++) { + asn1cSequenceAdd(fDD_Info->uL_NRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, nr_freqBandNrItem); + /* FDD.1.3.1 freqBandIndicatorNr*/ + nr_freqBandNrItem->freqBandIndicatorNr = fdd->ul_freqinfo.band; + } + /* FDD.2.1 DL NRFreqInfo ARFCN */ + fDD_Info->dL_NRFreqInfo.nRARFCN = fdd->dl_freqinfo.arfcn; + /* FDD.2.3 freqBandListNr */ + int dl_bands = 1; + for (int j = 0; j < dl_bands; j++) { + asn1cSequenceAdd(fDD_Info->dL_NRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, nr_freqBandNrItem); + /* FDD.2.3.1 freqBandIndicatorNr*/ + nr_freqBandNrItem->freqBandIndicatorNr = fdd->dl_freqinfo.band; + } // for FDD : DL freq_Bands + /* FDD.3 UL Transmission Bandwidth */ + fDD_Info->uL_Transmission_Bandwidth.nRSCS = fdd->ul_tbw.scs; + fDD_Info->uL_Transmission_Bandwidth.nRNRB = to_NRNRB(fdd->ul_tbw.nrb); + /* FDD.4 DL Transmission Bandwidth */ + fDD_Info->dL_Transmission_Bandwidth.nRSCS = fdd->dl_tbw.scs; + fDD_Info->dL_Transmission_Bandwidth.nRNRB = to_NRNRB(fdd->dl_tbw.nrb); + } else if (c->mode == F1AP_MODE_TDD) { + const f1ap_tdd_info_t *tdd = &c->tdd; + nR_Mode_Info->present = F1AP_NR_Mode_Info_PR_tDD; + asn1cCalloc(nR_Mode_Info->choice.tDD, tDD_Info); + /* TDD.1.1 nRFreqInfo ARFCN */ + tDD_Info->nRFreqInfo.nRARFCN = tdd->freqinfo.arfcn; + /* TDD.1.3 freqBandListNr */ + int bands = 1; + for (int j = 0; j < bands; j++) { + asn1cSequenceAdd(tDD_Info->nRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, nr_freqBandNrItem); + /* TDD.1.3.1 freqBandIndicatorNr*/ + nr_freqBandNrItem->freqBandIndicatorNr = tdd->freqinfo.band; + } + /* TDD.2 transmission_Bandwidth */ + tDD_Info->transmission_Bandwidth.nRSCS = tdd->tbw.scs; + tDD_Info->transmission_Bandwidth.nRNRB = to_NRNRB(tdd->tbw.nrb); + } else { + AssertFatal(false, "unknown duplex mode %d\n", c->mode); + } + // Measurement Timing Configuration + OCTET_STRING_fromBuf(&scell_info.measurementTimingConfiguration, + (const char *)c->measurement_timing_config, + c->measurement_timing_config_len); + + return scell_info; +} + +static bool decode_served_cell_info(const F1AP_Served_Cell_Information_t *in, f1ap_served_cell_info_t *info) +{ + AssertError(in != NULL, return false, "Input message pointer is NULL"); + // 5GS TAC (O) + if (in->fiveGS_TAC) { + info->tac = malloc_or_fail(sizeof(*info->tac)); + OCTET_STRING_TO_INT24(in->fiveGS_TAC, *info->tac); + } + // NR CGI (M) + TBCD_TO_MCC_MNC(&(in->nRCGI.pLMN_Identity), info->plmn.mcc, info->plmn.mnc, info->plmn.mnc_digit_length); + // NR Cell Identity (M) + BIT_STRING_TO_NR_CELL_IDENTITY(&in->nRCGI.nRCellIdentity, info->nr_cellid); + // NR PCI (M) + info->nr_pci = in->nRPCI; + // Served PLMNs (>= 1) + AssertError(in->servedPLMNs.list.count == 1, return false, "at least and only 1 PLMN must be present"); + info->num_ssi = read_slice_info(in->servedPLMNs.list.array[0], info->nssai, 16); + // FDD Info + if (in->nR_Mode_Info.present == F1AP_NR_Mode_Info_PR_fDD) { + info->mode = F1AP_MODE_FDD; + f1ap_fdd_info_t *FDDs = &info->fdd; + F1AP_FDD_Info_t *fDD_Info = in->nR_Mode_Info.choice.fDD; + FDDs->ul_freqinfo.arfcn = fDD_Info->uL_NRFreqInfo.nRARFCN; + // Note: cannot handle more than one UL frequency band + int num_ulBands = fDD_Info->uL_NRFreqInfo.freqBandListNr.list.count; + AssertError(num_ulBands == 1, return false, "1 FDD UL frequency band must be present, more is not supported"); + for (int f = 0; f < num_ulBands && f < 1; f++) { + F1AP_FreqBandNrItem_t *FreqItem = fDD_Info->uL_NRFreqInfo.freqBandListNr.list.array[f]; + FDDs->ul_freqinfo.band = FreqItem->freqBandIndicatorNr; + AssertError(FreqItem->supportedSULBandList.list.count == 0, return false, "cannot handle FDD SUL bands"); + } + // Note: cannot handle more than one DL frequency band + FDDs->dl_freqinfo.arfcn = fDD_Info->dL_NRFreqInfo.nRARFCN; + int num_dlBands = fDD_Info->dL_NRFreqInfo.freqBandListNr.list.count; + AssertError(num_dlBands == 1, return false, "1 FDD DL frequency band must be present, more is not supported"); + for (int dlB = 0; dlB < num_dlBands && dlB < 1; dlB++) { + F1AP_FreqBandNrItem_t *FreqItem = fDD_Info->dL_NRFreqInfo.freqBandListNr.list.array[dlB]; + FDDs->dl_freqinfo.band = FreqItem->freqBandIndicatorNr; + AssertError(FreqItem->supportedSULBandList.list.count == 0, return false, "cannot handle FDD SUL bands"); + } + FDDs->ul_tbw.scs = fDD_Info->uL_Transmission_Bandwidth.nRSCS; + FDDs->ul_tbw.nrb = nrb_lut[fDD_Info->uL_Transmission_Bandwidth.nRNRB]; + FDDs->dl_tbw.scs = fDD_Info->dL_Transmission_Bandwidth.nRSCS; + FDDs->dl_tbw.nrb = nrb_lut[fDD_Info->dL_Transmission_Bandwidth.nRNRB]; + } else if (in->nR_Mode_Info.present == F1AP_NR_Mode_Info_PR_tDD) { + info->mode = F1AP_MODE_TDD; + f1ap_tdd_info_t *TDDs = &info->tdd; + F1AP_TDD_Info_t *tDD_Info = in->nR_Mode_Info.choice.tDD; + TDDs->freqinfo.arfcn = tDD_Info->nRFreqInfo.nRARFCN; + // Handle frequency bands + int num_tddBands = tDD_Info->nRFreqInfo.freqBandListNr.list.count; + AssertError(num_tddBands == 1, return false, "1 TDD DL frequency band must be present, more is not supported"); + for (int f = 0; f < num_tddBands && f < 1; f++) { + struct F1AP_FreqBandNrItem *FreqItem = tDD_Info->nRFreqInfo.freqBandListNr.list.array[f]; + TDDs->freqinfo.band = FreqItem->freqBandIndicatorNr; + AssertError(FreqItem->supportedSULBandList.list.count == 0, return false, "cannot handle TDD SUL bands"); + } + TDDs->tbw.scs = tDD_Info->transmission_Bandwidth.nRSCS; + TDDs->tbw.nrb = nrb_lut[tDD_Info->transmission_Bandwidth.nRNRB]; + } else { + AssertError(1 == 0, return false, "unknown or missing NR Mode info %d\n", in->nR_Mode_Info.present); + } + // MeasurementConfig (M) + AssertError(in->measurementTimingConfiguration.size > 0, return false, "measurementTimingConfigurationc size is 0"); + info->measurement_timing_config = cp_octet_string(&in->measurementTimingConfiguration, &info->measurement_timing_config_len); + return true; +} + +static F1AP_GNB_DU_System_Information_t *encode_system_info(const f1ap_gnb_du_system_info_t *sys_info) +{ + if (sys_info == NULL) + return NULL; /* optional: can be NULL */ + + F1AP_GNB_DU_System_Information_t *enc_sys_info = calloc_or_fail(1, sizeof(*enc_sys_info)); + + AssertFatal(sys_info->mib != NULL, "MIB must be present in DU sys info\n"); + OCTET_STRING_fromBuf(&enc_sys_info->mIB_message, (const char *)sys_info->mib, sys_info->mib_length); + + AssertFatal(sys_info->sib1 != NULL, "SIB1 must be present in DU sys info\n"); + OCTET_STRING_fromBuf(&enc_sys_info->sIB1_message, (const char *)sys_info->sib1, sys_info->sib1_length); + + return enc_sys_info; +} + +static void decode_system_info(struct F1AP_GNB_DU_System_Information *DUsi, f1ap_gnb_du_system_info_t *sys_info) +{ + /* mib */ + sys_info->mib = calloc_or_fail(DUsi->mIB_message.size, sizeof(*sys_info->mib)); + memcpy(sys_info->mib, DUsi->mIB_message.buf, DUsi->mIB_message.size); + sys_info->mib_length = DUsi->mIB_message.size; + /* sib1 */ + sys_info->sib1 = calloc_or_fail(DUsi->sIB1_message.size, sizeof(*sys_info->sib1)); + memcpy(sys_info->sib1, DUsi->sIB1_message.buf, DUsi->sIB1_message.size); + sys_info->sib1_length = DUsi->sIB1_message.size; +} + +/* ==================================== + * F1 SETUP REQUEST + * ==================================== */ + +/** + * @brief F1 SETUP REQUEST encoding (9.2.1.4 of 3GPP TS 38.473) + * gNB-DU → gNB-CU + */ +F1AP_F1AP_PDU_t *encode_f1ap_setup_request(const f1ap_setup_req_t *msg) +{ + F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + + /* Create */ + /* 0. pdu Type */ + pdu->present = F1AP_F1AP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu->choice.initiatingMessage, initMsg); + initMsg->procedureCode = F1AP_ProcedureCode_id_F1Setup; + initMsg->criticality = F1AP_Criticality_reject; + initMsg->value.present = F1AP_InitiatingMessage__value_PR_F1SetupRequest; + F1AP_F1SetupRequest_t *f1Setup = &initMsg->value.choice.F1SetupRequest; + // Transaction ID (M) + asn1cSequenceAdd(f1Setup->protocolIEs.list, F1AP_F1SetupRequestIEs_t, ieC1); + ieC1->id = F1AP_ProtocolIE_ID_id_TransactionID; + ieC1->criticality = F1AP_Criticality_reject; + ieC1->value.present = F1AP_F1SetupRequestIEs__value_PR_TransactionID; + ieC1->value.choice.TransactionID = msg->transaction_id; + // gNB-DU ID (M) + asn1cSequenceAdd(f1Setup->protocolIEs.list, F1AP_F1SetupRequestIEs_t, ieC2); + ieC2->id = F1AP_ProtocolIE_ID_id_gNB_DU_ID; + ieC2->criticality = F1AP_Criticality_reject; + ieC2->value.present = F1AP_F1SetupRequestIEs__value_PR_GNB_DU_ID; + asn_int642INTEGER(&ieC2->value.choice.GNB_DU_ID, msg->gNB_DU_id); + // gNB-DU Name (O) + if (msg->gNB_DU_name) { + asn1cSequenceAdd(f1Setup->protocolIEs.list, F1AP_F1SetupRequestIEs_t, ieC3); + ieC3->id = F1AP_ProtocolIE_ID_id_gNB_DU_Name; + ieC3->criticality = F1AP_Criticality_ignore; + ieC3->value.present = F1AP_F1SetupRequestIEs__value_PR_GNB_DU_Name; + OCTET_STRING_fromBuf(&ieC3->value.choice.GNB_DU_Name, msg->gNB_DU_name, strlen(msg->gNB_DU_name)); + } + /// gNB-DU Served Cells List (0..1) + asn1cSequenceAdd(f1Setup->protocolIEs.list, F1AP_F1SetupRequestIEs_t, ieCells); + ieCells->id = F1AP_ProtocolIE_ID_id_gNB_DU_Served_Cells_List; + ieCells->criticality = F1AP_Criticality_reject; + ieCells->value.present = F1AP_F1SetupRequestIEs__value_PR_GNB_DU_Served_Cells_List; + for (int i = 0; i < msg->num_cells_available; i++) { + // gNB-DU Served Cells Item (M) + const f1ap_served_cell_info_t *cell = &msg->cell[i].info; + const f1ap_gnb_du_system_info_t *sys_info = msg->cell[i].sys_info; + asn1cSequenceAdd(ieCells->value.choice.GNB_DU_Served_Cells_List.list, F1AP_GNB_DU_Served_Cells_ItemIEs_t, duServedCell); + duServedCell->id = F1AP_ProtocolIE_ID_id_GNB_DU_Served_Cells_Item; + duServedCell->criticality = F1AP_Criticality_reject; + duServedCell->value.present = F1AP_GNB_DU_Served_Cells_ItemIEs__value_PR_GNB_DU_Served_Cells_Item; + F1AP_GNB_DU_Served_Cells_Item_t *scell_item = &duServedCell->value.choice.GNB_DU_Served_Cells_Item; + scell_item->served_Cell_Information = encode_served_cell_info(cell); + scell_item->gNB_DU_System_Information = encode_system_info(sys_info); + } + // gNB-DU RRC version (M) + asn1cSequenceAdd(f1Setup->protocolIEs.list, F1AP_F1SetupRequestIEs_t, ie2); + ie2->id = F1AP_ProtocolIE_ID_id_GNB_DU_RRC_Version; + ie2->criticality = F1AP_Criticality_reject; + ie2->value.present = F1AP_F1SetupRequestIEs__value_PR_RRC_Version; + // RRC Version: "This IE is not used in this release." + // we put one bit for each byte in rrc_ver that is != 0 + uint8_t bits = 0; + for (int i = 0; i < sizeofArray(msg->rrc_ver); ++i) + bits |= (msg->rrc_ver[i] != 0) << i; + BIT_STRING_t *bs = &ie2->value.choice.RRC_Version.latest_RRC_Version; + bs->buf = calloc_or_fail(1, sizeof(*bs->buf)); + bs->buf[0] = bits; + bs->size = 1; + bs->bits_unused = 5; + + F1AP_ProtocolExtensionContainer_10696P228_t *p = calloc_or_fail(1, sizeof(*p)); + asn1cSequenceAdd(p->list, F1AP_RRC_Version_ExtIEs_t, rrcv_ext); + rrcv_ext->id = F1AP_ProtocolIE_ID_id_latest_RRC_Version_Enhanced; + rrcv_ext->criticality = F1AP_Criticality_ignore; + rrcv_ext->extensionValue.present = F1AP_RRC_Version_ExtIEs__extensionValue_PR_OCTET_STRING_SIZE_3_; + OCTET_STRING_t *os = &rrcv_ext->extensionValue.choice.OCTET_STRING_SIZE_3_; + os->size = sizeofArray(msg->rrc_ver); + os->buf = malloc_or_fail(sizeof(msg->rrc_ver)); + for (int i = 0; i < sizeofArray(msg->rrc_ver); ++i) + os->buf[i] = msg->rrc_ver[i]; + ie2->value.choice.RRC_Version.iE_Extensions = (struct F1AP_ProtocolExtensionContainer *)p; + return pdu; +} + +/** + * @brief F1AP Setup Request decoding + */ +bool decode_f1ap_setup_request(const F1AP_F1AP_PDU_t *pdu, f1ap_setup_req_t *out) +{ + /* Check presence of message type */ + _F1_EQ_CHECK_INT(pdu->present, F1AP_F1AP_PDU_PR_initiatingMessage); + AssertError(pdu->choice.initiatingMessage != NULL, return false, "pdu->choice.initiatingMessage is NULL"); + _F1_EQ_CHECK_LONG(pdu->choice.initiatingMessage->procedureCode, F1AP_ProcedureCode_id_F1Setup); + _F1_EQ_CHECK_INT(pdu->choice.initiatingMessage->value.present, F1AP_InitiatingMessage__value_PR_F1SetupRequest); + /* Check presence of mandatory IEs */ + F1AP_F1SetupRequest_t *in = &pdu->choice.initiatingMessage->value.choice.F1SetupRequest; + F1AP_F1SetupRequestIEs_t *ie; + F1AP_LIB_FIND_IE(F1AP_F1SetupRequestIEs_t, ie, in, F1AP_ProtocolIE_ID_id_TransactionID, true); + F1AP_LIB_FIND_IE(F1AP_F1SetupRequestIEs_t, ie, in, F1AP_ProtocolIE_ID_id_gNB_DU_ID, true); + F1AP_LIB_FIND_IE(F1AP_F1SetupRequestIEs_t, ie, in, F1AP_ProtocolIE_ID_id_GNB_DU_RRC_Version, true); + /* Loop over all IEs */ + for (int i = 0; i < in->protocolIEs.list.count; i++) { + AssertError(in->protocolIEs.list.array[i] != NULL, return false, "in->protocolIEs.list.array[i] is NULL"); + ie = in->protocolIEs.list.array[i]; + switch (ie->id) { + case F1AP_ProtocolIE_ID_id_TransactionID: + // Transaction ID (M) + _F1_EQ_CHECK_INT(ie->value.present, F1AP_F1SetupRequestIEs__value_PR_TransactionID); + AssertError(ie->value.choice.TransactionID != -1, return false, "ie->value.choice.TransactionID is -1"); + out->transaction_id = ie->value.choice.TransactionID; + break; + case F1AP_ProtocolIE_ID_id_gNB_DU_ID: + // gNB-DU ID (M) + _F1_EQ_CHECK_INT(ie->value.present, F1AP_F1SetupRequestIEs__value_PR_GNB_DU_ID); + asn_INTEGER2ulong(&ie->value.choice.GNB_DU_ID, &out->gNB_DU_id); + break; + case F1AP_ProtocolIE_ID_id_gNB_DU_Name: { + const F1AP_GNB_DU_Name_t *du_name = &ie->value.choice.GNB_DU_Name; + out->gNB_DU_name = calloc_or_fail(du_name->size + 1, sizeof(*out->gNB_DU_name)); + strncpy(out->gNB_DU_name, (char *)du_name->buf, du_name->size); + break; + } + case F1AP_ProtocolIE_ID_id_gNB_DU_Served_Cells_List: + /* GNB_DU_Served_Cells_List */ + out->num_cells_available = ie->value.choice.GNB_DU_Served_Cells_List.list.count; + AssertError(out->num_cells_available > 0, return false, "at least 1 cell must be present"); + /* Loop over gNB-DU Served Cells Items */ + for (int i = 0; i < out->num_cells_available; i++) { + F1AP_GNB_DU_Served_Cells_Item_t *served_cells_item = + &(((F1AP_GNB_DU_Served_Cells_ItemIEs_t *)ie->value.choice.GNB_DU_Served_Cells_List.list.array[i]) + ->value.choice.GNB_DU_Served_Cells_Item); + // gNB-DU System Information (O) + struct F1AP_GNB_DU_System_Information *DUsi = served_cells_item->gNB_DU_System_Information; + if (DUsi != NULL) { + // System Information + out->cell[i].sys_info = calloc_or_fail(1, sizeof(*out->cell[i].sys_info)); + f1ap_gnb_du_system_info_t *sys_info = out->cell[i].sys_info; + /* mib */ + sys_info->mib = cp_octet_string(&DUsi->mIB_message, &sys_info->mib_length); + /* sib1 */ + sys_info->sib1 = cp_octet_string(&DUsi->sIB1_message, &sys_info->sib1_length); + } + /* Served Cell Information (M) */ + if (!decode_served_cell_info(&served_cells_item->served_Cell_Information, &out->cell[i].info)) + return false; + } + break; + case F1AP_ProtocolIE_ID_id_GNB_DU_RRC_Version: + /* gNB-DU RRC version (M) */ + if (ie->value.choice.RRC_Version.iE_Extensions) { + F1AP_ProtocolExtensionContainer_10696P228_t *ext = + (F1AP_ProtocolExtensionContainer_10696P228_t *)ie->value.choice.RRC_Version.iE_Extensions; + if (ext->list.count > 0) { + F1AP_RRC_Version_ExtIEs_t *rrcext = ext->list.array[0]; + OCTET_STRING_t *os = &rrcext->extensionValue.choice.OCTET_STRING_SIZE_3_; + DevAssert(os->size == sizeofArray(out->rrc_ver)); + for (int i = 0; i < os->size; ++i) + out->rrc_ver[i] = os->buf[i]; + } + } + break; + default: + AssertError(1 == 0, return false, "F1AP_ProtocolIE_ID_id %ld unknown\n", ie->id); + break; + } + } + return true; +} + +static void copy_f1ap_served_cell_info(f1ap_served_cell_info_t *dest, const f1ap_served_cell_info_t *src) { + *dest = *src; + dest->mode = src->mode; + dest->tdd = src->tdd; + dest->fdd = src->fdd; + dest->plmn = src->plmn; + if (src->tac) { + dest->tac = malloc_or_fail(sizeof(*dest->tac)); + *dest->tac = *src->tac; + } + if (src->measurement_timing_config_len) { + dest->measurement_timing_config = calloc_or_fail(src->measurement_timing_config_len, sizeof(*dest->measurement_timing_config)); + memcpy(dest->measurement_timing_config, src->measurement_timing_config, src->measurement_timing_config_len); + } +} + +/** + * @brief F1AP Setup Request deep copy + */ +f1ap_setup_req_t cp_f1ap_setup_request(const f1ap_setup_req_t *msg) +{ + f1ap_setup_req_t cp = {0}; + /* gNB_DU_id */ + cp.gNB_DU_id = msg->gNB_DU_id; + /* gNB_DU_name */ + if (msg->gNB_DU_name != NULL) + cp.gNB_DU_name = strdup(msg->gNB_DU_name); + /* transaction_id */ + cp.transaction_id = msg->transaction_id; + /* num_cells_available */ + cp.num_cells_available = msg->num_cells_available; + for (int n = 0; n < msg->num_cells_available; n++) { + /* cell.info */ + f1ap_served_cell_info_t *sci = &cp.cell[n].info; + const f1ap_served_cell_info_t *msg_sci = &msg->cell[n].info; + copy_f1ap_served_cell_info(sci, msg_sci); + /* cell.sys_info */ + if (msg->cell[n].sys_info) { + f1ap_gnb_du_system_info_t *orig_sys_info = msg->cell[n].sys_info; + f1ap_gnb_du_system_info_t *copy_sys_info = calloc_or_fail(1, sizeof(*copy_sys_info)); + cp.cell[n].sys_info = copy_sys_info; + if (orig_sys_info->mib_length > 0) { + copy_sys_info->mib = calloc_or_fail(orig_sys_info->mib_length, sizeof(*copy_sys_info->mib)); + copy_sys_info->mib_length = orig_sys_info->mib_length; + memcpy(copy_sys_info->mib, orig_sys_info->mib, copy_sys_info->mib_length); + } + if (orig_sys_info->sib1_length > 0) { + copy_sys_info->sib1 = calloc_or_fail(orig_sys_info->sib1_length, sizeof(*copy_sys_info->sib1)); + copy_sys_info->sib1_length = orig_sys_info->sib1_length; + memcpy(copy_sys_info->sib1, orig_sys_info->sib1, copy_sys_info->sib1_length); + } + } + } + for (int i = 0; i < sizeofArray(msg->rrc_ver); i++) + cp.rrc_ver[i] = msg->rrc_ver[i]; + return cp; +} + +/** + * @brief F1AP Setup Request equality check + */ +bool eq_f1ap_setup_request(const f1ap_setup_req_t *a, const f1ap_setup_req_t *b) +{ + _F1_EQ_CHECK_LONG(a->gNB_DU_id, b->gNB_DU_id); + _F1_EQ_CHECK_STR(a->gNB_DU_name, b->gNB_DU_name); + _F1_EQ_CHECK_LONG(a->transaction_id, b->transaction_id); + _F1_EQ_CHECK_INT(a->num_cells_available, b->num_cells_available); + for (int i = 0; i < a->num_cells_available; i++) { + if (!eq_f1ap_cell_info(&a->cell[i].info, &b->cell[i].info)) + return false; + if (!eq_f1ap_sys_info(a->cell[i].sys_info, b->cell[i].sys_info)) + return false; + } + _F1_EQ_CHECK_LONG(sizeofArray(a->rrc_ver), sizeofArray(b->rrc_ver)); + for (int i = 0; i < sizeofArray(a->rrc_ver); i++) { + _F1_EQ_CHECK_INT(a->rrc_ver[i], b->rrc_ver[i]); + } + return true; +} + +/** + * @brief F1AP Setup Request memory management + */ +void free_f1ap_setup_request(const f1ap_setup_req_t *msg) +{ + DevAssert(msg != NULL); + free(msg->gNB_DU_name); + for (int i = 0; i < msg->num_cells_available; i++) { + free_f1ap_cell(&msg->cell[i].info, msg->cell[i].sys_info); + } +} diff --git a/openair2/F1AP/lib/f1ap_interface_management.h b/openair2/F1AP/lib/f1ap_interface_management.h new file mode 100644 index 0000000000..6b196b9999 --- /dev/null +++ b/openair2/F1AP/lib/f1ap_interface_management.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_INTERFACE_MANAGEMENT_H_ +#define F1AP_INTERFACE_MANAGEMENT_H_ + +#include +#include "f1ap_messages_types.h" + +struct F1AP_F1AP_PDU; + +struct F1AP_F1AP_PDU *encode_f1ap_setup_request(const f1ap_setup_req_t *msg); +bool decode_f1ap_setup_request(const struct F1AP_F1AP_PDU *pdu, f1ap_setup_req_t *out); +f1ap_setup_req_t cp_f1ap_setup_request(const f1ap_setup_req_t *msg); +bool eq_f1ap_setup_request(const f1ap_setup_req_t *a, const f1ap_setup_req_t *b); +void free_f1ap_setup_request(const f1ap_setup_req_t *msg); + +#endif /* F1AP_INTERFACE_MANAGEMENT_H_ */ diff --git a/openair2/F1AP/lib/f1ap_lib_common.c b/openair2/F1AP/lib/f1ap_lib_common.c index a7d47c990f..edf48f426c 100644 --- a/openair2/F1AP/lib/f1ap_lib_common.c +++ b/openair2/F1AP/lib/f1ap_lib_common.c @@ -23,7 +23,7 @@ #include "f1ap_messages_types.h" #include "OCTET_STRING.h" - +#include "common/utils/utils.h" #include "common/utils/assertions.h" #include "common/utils/utils.h" @@ -35,6 +35,79 @@ bool eq_f1ap_plmn(const f1ap_plmn_t *a, const f1ap_plmn_t *b) return true; } +bool eq_f1ap_freq_info(const f1ap_nr_frequency_info_t *a, const f1ap_nr_frequency_info_t *b) +{ + if (a->arfcn != b->arfcn) + return false; + if (a->band != b->band) + return false; + return true; +} + +bool eq_f1ap_tx_bandwidth(const f1ap_transmission_bandwidth_t *a, const f1ap_transmission_bandwidth_t *b) +{ + if (a->nrb != b->nrb) + return false; + if (a->scs != b->scs) + return false; + return true; +} + +bool eq_f1ap_cell_info(const f1ap_served_cell_info_t *a, const f1ap_served_cell_info_t *b) +{ + if (a->nr_cellid != b->nr_cellid) + return false; + if (a->nr_pci != b->nr_pci) + return false; + if (*a->tac != *b->tac) + return false; + if (a->mode != b->mode) + return false; + if (a->mode == F1AP_MODE_TDD) { + /* TDD */ + if (!eq_f1ap_tx_bandwidth(&a->tdd.tbw, &b->tdd.tbw)) + return false; + if (!eq_f1ap_freq_info(&a->tdd.freqinfo, &b->tdd.freqinfo)) + return false; + } else if (a->mode == F1AP_MODE_FDD) { + /* FDD */ + if (!eq_f1ap_tx_bandwidth(&a->fdd.dl_tbw, &b->fdd.dl_tbw)) + return false; + if (!eq_f1ap_freq_info(&a->fdd.dl_freqinfo, &b->fdd.dl_freqinfo)) + return false; + if (!eq_f1ap_tx_bandwidth(&a->fdd.ul_tbw, &b->fdd.ul_tbw)) + return false; + if (!eq_f1ap_freq_info(&a->fdd.ul_freqinfo, &b->fdd.ul_freqinfo)) + return false; + } + if (a->measurement_timing_config_len != b->measurement_timing_config_len) + return false; + if (*a->measurement_timing_config != *b->measurement_timing_config) + return false; + if (!eq_f1ap_plmn(&a->plmn, &b->plmn)) + return false; + return true; +} + +bool eq_f1ap_sys_info(const f1ap_gnb_du_system_info_t *a, const f1ap_gnb_du_system_info_t *b) +{ + /* MIB */ + if (a->mib_length != b->mib_length) + return false; + for (int i = 0; i < a->mib_length; i++) { + if (a->mib[i] != b->mib[i]) + return false; + } + /* SIB1 */ + if (a->sib1_length != b->sib1_length) + return false; + for (int i = 0; i < a->sib1_length; i++) { + if (a->sib1[i] != b->sib1[i]) + return false; + } + return true; +} + uint8_t *cp_octet_string(const OCTET_STRING_t *os, int *len) { uint8_t *buf = calloc_or_fail(os->size, sizeof(*buf)); diff --git a/openair2/F1AP/lib/f1ap_lib_common.h b/openair2/F1AP/lib/f1ap_lib_common.h index 97e4f7eac4..2380a2da87 100644 --- a/openair2/F1AP/lib/f1ap_lib_common.h +++ b/openair2/F1AP/lib/f1ap_lib_common.h @@ -25,6 +25,7 @@ #include #include #include +#include "openair3/UTILS/conversions.h" #ifdef ENABLE_TESTS #define PRINT_ERROR(...) fprintf(stderr, ##__VA_ARGS__) @@ -69,6 +70,14 @@ struct f1ap_plmn_t; bool eq_f1ap_plmn(const struct f1ap_plmn_t *a, const struct f1ap_plmn_t *b); +struct f1ap_served_cell_info_t; +bool eq_f1ap_cell_info(const struct f1ap_served_cell_info_t *a, const struct f1ap_served_cell_info_t *b); +struct f1ap_gnb_du_system_info_t; +bool eq_f1ap_sys_info(const struct f1ap_gnb_du_system_info_t *a, const struct f1ap_gnb_du_system_info_t *b); +struct f1ap_nr_frequency_info_t; +bool eq_f1ap_freq_info(const struct f1ap_nr_frequency_info_t *a, const struct f1ap_nr_frequency_info_t *b); +struct f1ap_transmission_bandwidth_t; +bool eq_f1ap_tx_bandwidth(const struct f1ap_transmission_bandwidth_t *a, const struct f1ap_transmission_bandwidth_t *b); struct OCTET_STRING; uint8_t *cp_octet_string(const struct OCTET_STRING *os, int *len); diff --git a/openair2/F1AP/lib/f1ap_lib_includes.h b/openair2/F1AP/lib/f1ap_lib_includes.h index e9ebeab266..0e5ace104d 100644 --- a/openair2/F1AP/lib/f1ap_lib_includes.h +++ b/openair2/F1AP/lib/f1ap_lib_includes.h @@ -27,5 +27,15 @@ #include "F1AP_InitiatingMessage.h" #include "F1AP_NRCellIdentity.h" #include "F1AP_ProtocolIE-Field.h" +#include "F1AP_ServedPLMNs-Item.h" +#include "F1AP_ProtocolExtensionContainer.h" +#include "F1AP_ProtocolExtensionField.h" +#include "F1AP_ProtocolIE-Field.h" +#include "F1AP_SliceSupportItem.h" +#include "F1AP_NR-Mode-Info.h" +#include "F1AP_GNB-DU-System-Information.h" +#include "F1AP_FDD-Info.h" +#include "F1AP_TDD-Info.h" +#include "F1AP_FreqBandNrItem.h" #endif /* F1AP_LIB_INCLUDES_H_ */ From c433f4de156f65851f1b3f3ff62e904b3ccd415d Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Thu, 29 Aug 2024 23:50:50 +0200 Subject: [PATCH 21/46] Add test for F1 Setup Request enc/dec lib --- openair2/F1AP/tests/f1ap_lib_test.c | 117 ++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) diff --git a/openair2/F1AP/tests/f1ap_lib_test.c b/openair2/F1AP/tests/f1ap_lib_test.c index 5974e52f7a..005ebe5bb8 100644 --- a/openair2/F1AP/tests/f1ap_lib_test.c +++ b/openair2/F1AP/tests/f1ap_lib_test.c @@ -8,6 +8,7 @@ #include "F1AP_F1AP-PDU.h" #include "f1ap_lib_extern.h" +#include "lib/f1ap_interface_management.h" void exit_function(const char *file, const char *function, const int line, const char *s, const int assert) { @@ -155,10 +156,126 @@ static void test_ul_rrc_message_transfer(void) free_ul_rrc_message_transfer(&cp); } +/** + * @brief Test F1AP Setup Request Encoding/Decoding + */ +static void test_f1ap_setup_request(void) +{ + /* allocate memory */ + /* gNB_DU_name */ + uint8_t *gNB_DU_name = calloc(strlen("OAI DU") + 1, sizeof(uint8_t)); + AssertFatal(gNB_DU_name != NULL, "out of memory\n"); + memcpy((void *)gNB_DU_name, "OAI DU", strlen("OAI DU") + 1); + /* sys_info */ + uint8_t *mib = calloc(3, sizeof(uint8_t)); + uint8_t *sib1 = calloc(3, sizeof(uint8_t)); + f1ap_gnb_du_system_info_t sys_info = { + .mib_length = 3, + .mib = mib, + .sib1_length = 3, + .sib1 = sib1, + }; + /* measurement_timing_information */ + int measurement_timing_config_len = strlen("0") + 1; + uint8_t *measurement_timing_information = calloc(measurement_timing_config_len, sizeof(uint8_t)); + AssertFatal(measurement_timing_information != NULL, "out of memory\n"); + memcpy((void *)measurement_timing_information, "0", measurement_timing_config_len); + /* TAC */ + uint32_t *tac = calloc(1, sizeof(uint32_t)); + /* + * TDD test + */ + // Served Cell Info + f1ap_served_cell_info_t info = { + .mode = F1AP_MODE_TDD, + .tdd.freqinfo.arfcn = 640000, + .tdd.freqinfo.band = 78, + .tdd.tbw.nrb = 66, + .tdd.tbw.scs = 1, + .measurement_timing_config_len = measurement_timing_config_len, + .measurement_timing_config = measurement_timing_information, + .nr_cellid = 123456, + .plmn.mcc = 1, + .plmn.mnc = 1, + .plmn.mnc_digit_length = 3, + .num_ssi = 1, + .nssai[0].sst = 1, + .nssai[0].sd = 1, + .tac = tac, + }; + // create message + f1ap_setup_req_t orig = { + .gNB_DU_id = 1, + .gNB_DU_name = (char *)gNB_DU_name, + .num_cells_available = 1, + .transaction_id = 2, + .rrc_ver[0] = 12, + .rrc_ver[1] = 34, + .rrc_ver[2] = 56, + .cell[0].info = info, + }; + orig.cell[0].sys_info = calloc(1, sizeof(*orig.cell[0].sys_info)); + *orig.cell[0].sys_info = sys_info; + // encode + F1AP_F1AP_PDU_t *f1enc = encode_f1ap_setup_request(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + // decode + f1ap_setup_req_t decoded = {0}; + bool ret = decode_f1ap_setup_request(f1dec, &decoded); + AssertFatal(ret, "decode_f1ap_setup_request(): could not decode message\n"); + f1ap_msg_free(f1dec); + // equality check + ret = eq_f1ap_setup_request(&orig, &decoded); + AssertFatal(ret, "eq_f1ap_setup_request(): decoded message doesn't match\n"); + free_f1ap_setup_request(&decoded); + // deep copy + f1ap_setup_req_t cp = cp_f1ap_setup_request(&orig); + ret = eq_f1ap_setup_request(&orig, &cp); + AssertFatal(ret, "eq_f1ap_setup_request(): copied message doesn't match\n"); + free_f1ap_setup_request(&cp); + /* + * FDD test + */ + info.mode = F1AP_MODE_FDD; + info.tdd.freqinfo.arfcn = 0; + info.tdd.freqinfo.band = 0; + info.tdd.tbw.nrb = 0; + info.tdd.tbw.scs = 0; + info.fdd.ul_freqinfo.arfcn = 640000; + info.fdd.ul_freqinfo.band = 78; + info.fdd.dl_freqinfo.arfcn = 641000; + info.fdd.dl_freqinfo.band = 78; + info.fdd.ul_tbw.nrb = 66; + info.fdd.ul_tbw.scs = 1; + info.fdd.dl_tbw.nrb = 66; + info.fdd.dl_tbw.scs = 1; + // encode + f1enc = encode_f1ap_setup_request(&orig); + f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + // decode + ret = decode_f1ap_setup_request(f1dec, &decoded); + AssertFatal(ret, "decode_f1ap_setup_request(): could not decode message\n"); + f1ap_msg_free(f1dec); + // equality check + ret = eq_f1ap_setup_request(&orig, &decoded); + AssertFatal(ret, "eq_f1ap_setup_request(): decoded message doesn't match\n"); + free_f1ap_setup_request(&decoded); + // copy + cp = cp_f1ap_setup_request(&orig); + ret = eq_f1ap_setup_request(&orig, &cp); + AssertFatal(ret, "eq_f1ap_setup_request(): copied message doesn't match\n"); + free_f1ap_setup_request(&cp); + // free original message + free_f1ap_setup_request(&orig); +} + int main() { test_initial_ul_rrc_message_transfer(); test_dl_rrc_message_transfer(); test_ul_rrc_message_transfer(); + test_f1ap_setup_request(); return 0; } From 1d8e896567fe2ea6811b5499b4c9e6cc71feacac Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Thu, 29 Aug 2024 23:49:53 +0200 Subject: [PATCH 22/46] Use F1AP lib for F1 Setup Request in stack --- openair2/F1AP/f1ap_cu_interface_management.c | 171 ++---------------- openair2/F1AP/f1ap_du_interface_management.c | 107 ++--------- openair2/F1AP/f1ap_du_task.c | 2 + .../LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c | 44 +---- openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c | 46 +---- openair2/RRC/NR/rrc_gNB_du.c | 7 +- 6 files changed, 38 insertions(+), 339 deletions(-) diff --git a/openair2/F1AP/f1ap_cu_interface_management.c b/openair2/F1AP/f1ap_cu_interface_management.c index e420ddf295..2685325d6e 100644 --- a/openair2/F1AP/f1ap_cu_interface_management.c +++ b/openair2/F1AP/f1ap_cu_interface_management.c @@ -36,6 +36,7 @@ #include "f1ap_cu_interface_management.h" #include "f1ap_default_values.h" #include "lib/f1ap_interface_management.h" +#include "lib/f1ap_lib_common.h" int CU_handle_RESET_ACKNOWLEDGE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { @@ -47,15 +48,6 @@ int CU_send_RESET_ACKNOWLEDGE(sctp_assoc_t assoc_id, const f1ap_reset_ack_t *ack AssertFatal(1 == 0, "Not implemented yet\n"); } -static uint8_t *cp_octet_string(const OCTET_STRING_t *os, int *len) -{ - uint8_t *buf = calloc(os->size, sizeof(*buf)); - AssertFatal(buf != NULL, "out of memory\n"); - memcpy(buf, os->buf, os->size); - *len = os->size; - return buf; -} - static int read_slice_info(const F1AP_ServedPLMNs_Item_t *plmn, nssai_t *nssai, int max_nssai) { if (plmn->iE_Extensions == NULL) @@ -82,168 +74,31 @@ static int read_slice_info(const F1AP_ServedPLMNs_Item_t *plmn, nssai_t *nssai, return ssl->list.count; } -/* - F1 Setup -*/ +/** + * @brief F1AP Setup Request decoding (9.2.1.4 of 3GPP TS 38.473) and transfer to RRC + */ int CU_handle_F1_SETUP_REQUEST(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { LOG_D(F1AP, "CU_handle_F1_SETUP_REQUEST\n"); - F1AP_F1SetupRequest_t *container; - F1AP_F1SetupRequestIEs_t *ie; - int i = 0; DevAssert(pdu != NULL); - container = &pdu->choice.initiatingMessage->value.choice.F1SetupRequest; - /* F1 Setup Request == Non UE-related procedure -> stream 0 */ if (stream != 0) { LOG_W(F1AP, "[SCTP %d] Received f1 setup request on stream != 0 (%d)\n", assoc_id, stream); } - + f1ap_setup_req_t msg = {0}; + /* Decode */ + if (!decode_f1ap_setup_request(pdu, &msg)) { + LOG_E(F1AP, "cannot decode F1AP Setup Request\n"); + free_f1ap_setup_request(&msg); + return -1; + } + /* Send to RRC (ITTI) */ MessageDef *message_p = itti_alloc_new_message(TASK_CU_F1, 0, F1AP_SETUP_REQ); message_p->ittiMsgHeader.originInstance = assoc_id; f1ap_setup_req_t *req = &F1AP_SETUP_REQ(message_p); - - /* Transaction ID*/ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_F1SetupRequestIEs_t, ie, container, F1AP_ProtocolIE_ID_id_TransactionID, true); - req->transaction_id = ie->value.choice.TransactionID; - LOG_D(F1AP, "req->transaction_id %lu \n", req->transaction_id); - - /* gNB_DU_id */ - // this function exits if the ie is mandatory - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_F1SetupRequestIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_gNB_DU_ID, true); - asn_INTEGER2ulong(&ie->value.choice.GNB_DU_ID, &req->gNB_DU_id); - LOG_D(F1AP, "req->gNB_DU_id %lu \n", req->gNB_DU_id); - /* gNB_DU_name */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_F1SetupRequestIEs_t, ie, container, F1AP_ProtocolIE_ID_id_gNB_DU_Name, false); - req->gNB_DU_name = NULL; - if (ie != NULL) { - req->gNB_DU_name = calloc(ie->value.choice.GNB_DU_Name.size + 1, sizeof(char)); - memcpy(req->gNB_DU_name, ie->value.choice.GNB_DU_Name.buf, ie->value.choice.GNB_DU_Name.size); - LOG_D(F1AP, "req->gNB_DU_name %s \n", req->gNB_DU_name); - } - /* GNB_DU_Served_Cells_List */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_F1SetupRequestIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_gNB_DU_Served_Cells_List, true); - req->num_cells_available = ie->value.choice.GNB_DU_Served_Cells_List.list.count; - LOG_D(F1AP, "req->num_cells_available %d \n", req->num_cells_available); - - for (i=0; inum_cells_available; i++) { - F1AP_GNB_DU_Served_Cells_Item_t *served_cells_item = &(((F1AP_GNB_DU_Served_Cells_ItemIEs_t *) - ie->value.choice.GNB_DU_Served_Cells_List.list.array[i])-> - value.choice.GNB_DU_Served_Cells_Item); - F1AP_Served_Cell_Information_t *servedCellInformation= &served_cells_item->served_Cell_Information; - /* tac */ - if (servedCellInformation->fiveGS_TAC) { - req->cell[i].info.tac = malloc(sizeof(*req->cell[i].info.tac)); - AssertFatal(req->cell[i].info.tac != NULL, "out of memory\n"); - OCTET_STRING_TO_INT24(servedCellInformation->fiveGS_TAC, *req->cell[i].info.tac); - LOG_D(F1AP, "req->tac[%d] %d \n", i, *req->cell[i].info.tac); - } - - /* - nRCGI */ - TBCD_TO_MCC_MNC(&(servedCellInformation->nRCGI.pLMN_Identity), - req->cell[i].info.plmn.mcc, - req->cell[i].info.plmn.mnc, - req->cell[i].info.plmn.mnc_digit_length); - // NR cellID - BIT_STRING_TO_NR_CELL_IDENTITY(&servedCellInformation->nRCGI.nRCellIdentity, - req->cell[i].info.nr_cellid); - LOG_D(F1AP, "[SCTP %d] Received nRCGI: MCC %d, MNC %d, CELL_ID %llu\n", assoc_id, - req->cell[i].info.plmn.mcc, - req->cell[i].info.plmn.mnc, - (long long unsigned int)req->cell[i].info.nr_cellid); - /* - nRPCI */ - req->cell[i].info.nr_pci = servedCellInformation->nRPCI; - LOG_D(F1AP, "req->nr_pci[%d] %d \n", i, req->cell[i].info.nr_pci); - - AssertFatal(servedCellInformation->servedPLMNs.list.count == 1, "only one PLMN handled\n"); - req->cell[i].info.num_ssi = read_slice_info(servedCellInformation->servedPLMNs.list.array[0], req->cell[i].info.nssai, 16); - - // FDD Cells - if (servedCellInformation->nR_Mode_Info.present==F1AP_NR_Mode_Info_PR_fDD) { - req->cell[i].info.mode = F1AP_MODE_FDD; - f1ap_fdd_info_t *FDDs = &req->cell[i].info.fdd; - F1AP_FDD_Info_t * fDD_Info=servedCellInformation->nR_Mode_Info.choice.fDD; - FDDs->ul_freqinfo.arfcn = fDD_Info->uL_NRFreqInfo.nRARFCN; - AssertFatal(fDD_Info->uL_NRFreqInfo.freqBandListNr.list.count == 1, "cannot handle more than one frequency band\n"); - for (int f=0; f < fDD_Info->uL_NRFreqInfo.freqBandListNr.list.count; f++) { - F1AP_FreqBandNrItem_t * FreqItem=fDD_Info->uL_NRFreqInfo.freqBandListNr.list.array[f]; - FDDs->ul_freqinfo.band = FreqItem->freqBandIndicatorNr; - AssertFatal(FreqItem->supportedSULBandList.list.count == 0, "cannot handle SUL bands!\n"); - } - FDDs->dl_freqinfo.arfcn = fDD_Info->dL_NRFreqInfo.nRARFCN; - int dlBands=fDD_Info->dL_NRFreqInfo.freqBandListNr.list.count; - AssertFatal(dlBands == 1, "cannot handled more than one frequency band\n"); - for (int dlB=0; dlB < dlBands; dlB++) { - F1AP_FreqBandNrItem_t * FreqItem=fDD_Info->dL_NRFreqInfo.freqBandListNr.list.array[dlB]; - FDDs->dl_freqinfo.band = FreqItem->freqBandIndicatorNr; - int num_available_supported_SULBands = FreqItem->supportedSULBandList.list.count; - AssertFatal(num_available_supported_SULBands == 0, "cannot handle SUL bands!\n"); - } - FDDs->ul_tbw.scs = fDD_Info->uL_Transmission_Bandwidth.nRSCS; - FDDs->ul_tbw.nrb = nrb_lut[fDD_Info->uL_Transmission_Bandwidth.nRNRB]; - FDDs->dl_tbw.scs = fDD_Info->dL_Transmission_Bandwidth.nRSCS; - FDDs->dl_tbw.nrb = nrb_lut[fDD_Info->dL_Transmission_Bandwidth.nRNRB]; - } else if (servedCellInformation->nR_Mode_Info.present==F1AP_NR_Mode_Info_PR_tDD) { - req->cell[i].info.mode = F1AP_MODE_TDD; - f1ap_tdd_info_t *TDDs = &req->cell[i].info.tdd; - F1AP_TDD_Info_t *tDD_Info = servedCellInformation->nR_Mode_Info.choice.tDD; - TDDs->freqinfo.arfcn = tDD_Info->nRFreqInfo.nRARFCN; - AssertFatal(tDD_Info->nRFreqInfo.freqBandListNr.list.count == 1, "cannot handle more than one frequency band\n"); - for (int f=0; f < tDD_Info->nRFreqInfo.freqBandListNr.list.count; f++) { - struct F1AP_FreqBandNrItem * FreqItem=tDD_Info->nRFreqInfo.freqBandListNr.list.array[f]; - TDDs->freqinfo.band = FreqItem->freqBandIndicatorNr; - int num_available_supported_SULBands = FreqItem->supportedSULBandList.list.count; - AssertFatal(num_available_supported_SULBands == 0, "cannot hanlde SUL bands!\n"); - } - TDDs->tbw.scs = tDD_Info->transmission_Bandwidth.nRSCS; - TDDs->tbw.nrb = nrb_lut[tDD_Info->transmission_Bandwidth.nRNRB]; - } else { - AssertFatal(false, "unknown NR Mode info %d\n", servedCellInformation->nR_Mode_Info.present); - } - - /* MeasurementConfig */ - if (servedCellInformation->measurementTimingConfiguration.size > 0) - req->cell[i].info.measurement_timing_config = - cp_octet_string(&servedCellInformation->measurementTimingConfiguration, &req->cell[i].info.measurement_timing_config_len); - - struct F1AP_GNB_DU_System_Information * DUsi=served_cells_item->gNB_DU_System_Information; - if (DUsi != NULL) { - // System Information - req->cell[i].sys_info = calloc(1, sizeof(*req->cell[i].sys_info)); - AssertFatal(req->cell[i].sys_info != NULL, "out of memory\n"); - f1ap_gnb_du_system_info_t *sys_info = req->cell[i].sys_info; - /* mib */ - sys_info->mib = calloc(DUsi->mIB_message.size, sizeof(char)); - memcpy(sys_info->mib, DUsi->mIB_message.buf, DUsi->mIB_message.size); - sys_info->mib_length = DUsi->mIB_message.size; - /* sib1 */ - sys_info->sib1 = calloc(DUsi->sIB1_message.size, sizeof(char)); - memcpy(sys_info->sib1, DUsi->sIB1_message.buf, DUsi->sIB1_message.size); - sys_info->sib1_length = DUsi->sIB1_message.size; - } - } - - /* Handle RRC Version */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_F1SetupRequestIEs_t, ie, container, - F1AP_ProtocolIE_ID_id_GNB_DU_RRC_Version, true); - // Latest RRC Version: "This IE is not used in this release." - // BIT_STRING_to_uint8(&ie->value.choice.RRC_Version.latest_RRC_Version); - if (ie->value.choice.RRC_Version.iE_Extensions) { - F1AP_ProtocolExtensionContainer_10696P228_t *ext = - (F1AP_ProtocolExtensionContainer_10696P228_t *)ie->value.choice.RRC_Version.iE_Extensions; - if (ext->list.count > 0) { - F1AP_RRC_Version_ExtIEs_t *rrcext = ext->list.array[0]; - OCTET_STRING_t *os = &rrcext->extensionValue.choice.OCTET_STRING_SIZE_3_; - DevAssert(os->size == 3); - for (int i = 0; i < 3; ++i) - req->rrc_ver[i] = os->buf[i]; - } - } + *req = msg; /* "move" message into ITTI, RRC thread will free it */ itti_send_msg_to_task(TASK_RRC_GNB, GNB_MODULE_ID_TO_INSTANCE(instance), message_p); - return 0; } diff --git a/openair2/F1AP/f1ap_du_interface_management.c b/openair2/F1AP/f1ap_du_interface_management.c index 56cb9d0e7b..ab55fd0f05 100644 --- a/openair2/F1AP/f1ap_du_interface_management.c +++ b/openair2/F1AP/f1ap_du_interface_management.c @@ -34,6 +34,8 @@ #include "f1ap_encoder.h" #include "f1ap_itti_messaging.h" #include "f1ap_du_interface_management.h" +#include "lib/f1ap_interface_management.h" +#include "lib/f1ap_lib_common.h" #include "openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h" #include "assertions.h" @@ -297,110 +299,25 @@ static F1AP_GNB_DU_System_Information_t *encode_system_info(const f1ap_gnb_du_sy return enc_sys_info; } -// SETUP REQUEST +/** + * @brief F1AP Setup Request + */ int DU_send_F1_SETUP_REQUEST(sctp_assoc_t assoc_id, const f1ap_setup_req_t *setup_req) { LOG_D(F1AP, "DU_send_F1_SETUP_REQUEST\n"); - - F1AP_F1AP_PDU_t pdu= {0}; + F1AP_F1AP_PDU_t *pdu = encode_f1ap_setup_request(setup_req); uint8_t *buffer; uint32_t len; - /* Create */ - /* 0. pdu Type */ - pdu.present = F1AP_F1AP_PDU_PR_initiatingMessage; - asn1cCalloc(pdu.choice.initiatingMessage, initMsg); - initMsg->procedureCode = F1AP_ProcedureCode_id_F1Setup; - initMsg->criticality = F1AP_Criticality_reject; - initMsg->value.present = F1AP_InitiatingMessage__value_PR_F1SetupRequest; - F1AP_F1SetupRequest_t *f1Setup = &initMsg->value.choice.F1SetupRequest; - /* mandatory */ - /* c1. Transaction ID (integer value) */ - asn1cSequenceAdd(f1Setup->protocolIEs.list, F1AP_F1SetupRequestIEs_t, ieC1); - ieC1->id = F1AP_ProtocolIE_ID_id_TransactionID; - ieC1->criticality = F1AP_Criticality_reject; - ieC1->value.present = F1AP_F1SetupRequestIEs__value_PR_TransactionID; - ieC1->value.choice.TransactionID = F1AP_get_next_transaction_identifier(0, 0); - /* mandatory */ - /* c2. GNB_DU_ID (integer value) */ - asn1cSequenceAdd(f1Setup->protocolIEs.list, F1AP_F1SetupRequestIEs_t, ieC2); - ieC2->id = F1AP_ProtocolIE_ID_id_gNB_DU_ID; - ieC2->criticality = F1AP_Criticality_reject; - ieC2->value.present = F1AP_F1SetupRequestIEs__value_PR_GNB_DU_ID; - asn_int642INTEGER(&ieC2->value.choice.GNB_DU_ID, setup_req->gNB_DU_id); - - /* optional */ - /* c3. GNB_DU_Name */ - if (setup_req->gNB_DU_name != NULL) { - asn1cSequenceAdd(f1Setup->protocolIEs.list, F1AP_F1SetupRequestIEs_t, ieC3); - ieC3->id = F1AP_ProtocolIE_ID_id_gNB_DU_Name; - ieC3->criticality = F1AP_Criticality_ignore; - ieC3->value.present = F1AP_F1SetupRequestIEs__value_PR_GNB_DU_Name; - char *gNB_DU_name=setup_req->gNB_DU_name; - OCTET_STRING_fromBuf(&ieC3->value.choice.GNB_DU_Name, gNB_DU_name, strlen(gNB_DU_name)); - } - - /* mandatory */ - /* c4. served cells list */ - asn1cSequenceAdd(f1Setup->protocolIEs.list, F1AP_F1SetupRequestIEs_t, ieCells); - ieCells->id = F1AP_ProtocolIE_ID_id_gNB_DU_Served_Cells_List; - ieCells->criticality = F1AP_Criticality_reject; - ieCells->value.present = F1AP_F1SetupRequestIEs__value_PR_GNB_DU_Served_Cells_List; - int num_cells_available = setup_req->num_cells_available; - LOG_D(F1AP, "num_cells_available = %d \n", num_cells_available); - - for (int i=0; icell[i].info; - const f1ap_gnb_du_system_info_t *sys_info = setup_req->cell[i].sys_info; - asn1cSequenceAdd(ieCells->value.choice.GNB_DU_Served_Cells_List.list, - F1AP_GNB_DU_Served_Cells_ItemIEs_t, duServedCell); - duServedCell->id = F1AP_ProtocolIE_ID_id_GNB_DU_Served_Cells_Item; - duServedCell->criticality = F1AP_Criticality_reject; - duServedCell->value.present = F1AP_GNB_DU_Served_Cells_ItemIEs__value_PR_GNB_DU_Served_Cells_Item; - F1AP_GNB_DU_Served_Cells_Item_t *scell_item = &duServedCell->value.choice.GNB_DU_Served_Cells_Item; - scell_item->served_Cell_Information = encode_served_cell_info(cell); - scell_item->gNB_DU_System_Information = encode_system_info(sys_info); - } - - /* mandatory */ - /* c5. RRC VERSION */ - asn1cSequenceAdd(f1Setup->protocolIEs.list, F1AP_F1SetupRequestIEs_t, ie2); - ie2->id = F1AP_ProtocolIE_ID_id_GNB_DU_RRC_Version; - ie2->criticality = F1AP_Criticality_reject; - ie2->value.present = F1AP_F1SetupRequestIEs__value_PR_RRC_Version; - // RRC Version: "This IE is not used in this release." - // we put one bit for each byte in rrc_ver that is != 0 - uint8_t bits = 0; - for (int i = 0; i < 3; ++i) - bits |= (setup_req->rrc_ver[i] != 0) << i; - BIT_STRING_t *bs = &ie2->value.choice.RRC_Version.latest_RRC_Version; - bs->buf = calloc(1, sizeof(char)); - AssertFatal(bs->buf != NULL, "out of memory\n"); - bs->buf[0] = bits; - bs->size = 1; - bs->bits_unused = 5; - - F1AP_ProtocolExtensionContainer_10696P228_t *p = calloc(1, sizeof(F1AP_ProtocolExtensionContainer_10696P228_t)); - asn1cSequenceAdd(p->list, F1AP_RRC_Version_ExtIEs_t, rrcv_ext); - rrcv_ext->id = F1AP_ProtocolIE_ID_id_latest_RRC_Version_Enhanced; - rrcv_ext->criticality = F1AP_Criticality_ignore; - rrcv_ext->extensionValue.present = F1AP_RRC_Version_ExtIEs__extensionValue_PR_OCTET_STRING_SIZE_3_; - OCTET_STRING_t *os = &rrcv_ext->extensionValue.choice.OCTET_STRING_SIZE_3_; - os->size = 3; - os->buf = malloc(3 * sizeof(*os->buf)); - AssertFatal(os->buf != NULL, "out of memory\n"); - for (int i = 0; i < 3; ++i) - os->buf[i] = setup_req->rrc_ver[i]; - ie2->value.choice.RRC_Version.iE_Extensions = (struct F1AP_ProtocolExtensionContainer*)p; - /* encode */ - if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { + if (f1ap_encode_pdu(pdu, &buffer, &len) < 0) { LOG_E(F1AP, "Failed to encode F1 setup request\n"); + /* free PDU */ + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); return -1; } - - ASN_STRUCT_RESET(asn_DEF_F1AP_F1AP_PDU, &pdu); + /* free PDU */ + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); + /* Send to ITTI */ f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); return 0; } diff --git a/openair2/F1AP/f1ap_du_task.c b/openair2/F1AP/f1ap_du_task.c index 02e23c0281..6c4f8c3be6 100644 --- a/openair2/F1AP/f1ap_du_task.c +++ b/openair2/F1AP/f1ap_du_task.c @@ -100,6 +100,8 @@ void du_task_handle_sctp_association_resp(instance_t instance, sctp_new_associat f1ap_du_data->du.assoc_id = sctp_new_association_resp->assoc_id; f1ap_du_data->sctp_in_streams = sctp_new_association_resp->in_streams; f1ap_du_data->sctp_out_streams = sctp_new_association_resp->out_streams; + /* next transaction ID */ + f1ap_du_data->setupReq.transaction_id = F1AP_get_next_transaction_identifier(0, 0); /* setup parameters for F1U and start the server */ DU_send_F1_SETUP_REQUEST(f1ap_du_data->du.assoc_id, &f1ap_du_data->setupReq); } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c index b06abeb5bc..7bdad73d21 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c @@ -24,6 +24,7 @@ #include "mac_rrc_ul.h" #include "f1ap_lib_extern.h" +#include "lib/f1ap_interface_management.h" static void f1_reset_du_initiated_direct(const f1ap_reset_t *reset) { @@ -41,47 +42,8 @@ static void f1_setup_request_direct(const f1ap_setup_req_t *req) { MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_SETUP_REQ); msg->ittiMsgHeader.originInstance = -1; // means monolithic - f1ap_setup_req_t *f1ap_msg = &F1AP_SETUP_REQ(msg); - f1ap_msg->gNB_DU_id = req->gNB_DU_id; - f1ap_msg->gNB_DU_name = strdup(req->gNB_DU_name); - f1ap_msg->num_cells_available = req->num_cells_available; - for (int n = 0; n < req->num_cells_available; ++n) { - f1ap_msg->cell[n].info = req->cell[n].info; // copy most fields - if (req->cell[n].info.tac) { - f1ap_msg->cell[n].info.tac = malloc(sizeof(*f1ap_msg->cell[n].info.tac)); - AssertFatal(f1ap_msg->cell[n].info.tac != NULL, "out of memory\n"); - *f1ap_msg->cell[n].info.tac = *req->cell[n].info.tac; - } - if (req->cell[n].info.measurement_timing_config_len > 0) { - f1ap_msg->cell[n].info.measurement_timing_config = calloc(req->cell[n].info.measurement_timing_config_len, sizeof(uint8_t)); - AssertFatal(f1ap_msg->cell[n].info.measurement_timing_config != NULL, "out of memory\n"); - memcpy(f1ap_msg->cell[n].info.measurement_timing_config, - req->cell[n].info.measurement_timing_config, - req->cell[n].info.measurement_timing_config_len); - f1ap_msg->cell[n].info.measurement_timing_config_len = req->cell[n].info.measurement_timing_config_len; - } - - if (req->cell[n].sys_info) { - f1ap_gnb_du_system_info_t *orig_sys_info = req->cell[n].sys_info; - f1ap_gnb_du_system_info_t *copy_sys_info = calloc(1, sizeof(*copy_sys_info)); - AssertFatal(copy_sys_info, "out of memory\n"); - f1ap_msg->cell[n].sys_info = copy_sys_info; - - copy_sys_info->mib = calloc(orig_sys_info->mib_length, sizeof(uint8_t)); - AssertFatal(copy_sys_info->mib, "out of memory\n"); - memcpy(copy_sys_info->mib, orig_sys_info->mib, orig_sys_info->mib_length); - copy_sys_info->mib_length = orig_sys_info->mib_length; - - if (orig_sys_info->sib1_length > 0) { - copy_sys_info->sib1 = calloc(orig_sys_info->sib1_length, sizeof(uint8_t)); - AssertFatal(copy_sys_info->sib1, "out of memory\n"); - memcpy(copy_sys_info->sib1, orig_sys_info->sib1, orig_sys_info->sib1_length); - copy_sys_info->sib1_length = orig_sys_info->sib1_length; - } - } - } - memcpy(f1ap_msg->rrc_ver, req->rrc_ver, sizeof(req->rrc_ver)); - + f1ap_setup_req_t cp = cp_f1ap_setup_request(req); + F1AP_SETUP_REQ(msg) = cp; itti_send_msg_to_task(TASK_RRC_GNB, 0, msg); } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c index e3e46310eb..caf4309bec 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c @@ -30,6 +30,7 @@ #include "mac_rrc_ul.h" #include "f1ap_lib_extern.h" +#include "lib/f1ap_interface_management.h" static f1ap_net_config_t read_DU_IP_config(const eth_params_t* f1_params, const char *f1u_ip_addr) { @@ -68,50 +69,9 @@ static void f1_reset_acknowledge_cu_initiated_f1ap(const f1ap_reset_ack_t *ack) static void f1_setup_request_f1ap(const f1ap_setup_req_t *req) { MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_DU_REGISTER_REQ); - - f1ap_setup_req_t *f1ap_setup = &F1AP_DU_REGISTER_REQ(msg).setup_req; - f1ap_setup->gNB_DU_id = req->gNB_DU_id; - f1ap_setup->gNB_DU_name = strdup(req->gNB_DU_name); - f1ap_setup->num_cells_available = req->num_cells_available; - for (int n = 0; n < req->num_cells_available; ++n) { - f1ap_setup->cell[n].info = req->cell[n].info; // copy most fields - if (req->cell[n].info.tac) { - f1ap_setup->cell[n].info.tac = malloc(sizeof(*f1ap_setup->cell[n].info.tac)); - AssertFatal(f1ap_setup->cell[n].info.tac != NULL, "out of memory\n"); - *f1ap_setup->cell[n].info.tac = *req->cell[n].info.tac; - } - if (req->cell[n].info.measurement_timing_config_len > 0) { - f1ap_setup->cell[n].info.measurement_timing_config = calloc(req->cell[n].info.measurement_timing_config_len, sizeof(uint8_t)); - AssertFatal(f1ap_setup->cell[n].info.measurement_timing_config != NULL, "out of memory\n"); - memcpy(f1ap_setup->cell[n].info.measurement_timing_config, - req->cell[n].info.measurement_timing_config, - req->cell[n].info.measurement_timing_config_len); - f1ap_setup->cell[n].info.measurement_timing_config_len = req->cell[n].info.measurement_timing_config_len; - } - - if (req->cell[n].sys_info) { - f1ap_gnb_du_system_info_t *orig_sys_info = req->cell[n].sys_info; - f1ap_gnb_du_system_info_t *copy_sys_info = calloc(1, sizeof(*copy_sys_info)); - AssertFatal(copy_sys_info, "out of memory\n"); - f1ap_setup->cell[n].sys_info = copy_sys_info; - - copy_sys_info->mib = calloc(orig_sys_info->mib_length, sizeof(uint8_t)); - AssertFatal(copy_sys_info->mib, "out of memory\n"); - memcpy(copy_sys_info->mib, orig_sys_info->mib, orig_sys_info->mib_length); - copy_sys_info->mib_length = orig_sys_info->mib_length; - - if (orig_sys_info->sib1_length > 0) { - copy_sys_info->sib1 = calloc(orig_sys_info->sib1_length, sizeof(uint8_t)); - AssertFatal(copy_sys_info->sib1, "out of memory\n"); - memcpy(copy_sys_info->sib1, orig_sys_info->sib1, orig_sys_info->sib1_length); - copy_sys_info->sib1_length = orig_sys_info->sib1_length; - } - } - } - memcpy(f1ap_setup->rrc_ver, req->rrc_ver, sizeof(req->rrc_ver)); - + f1ap_setup_req_t f1ap_setup = cp_f1ap_setup_request(req); + F1AP_DU_REGISTER_REQ(msg).setup_req = f1ap_setup; F1AP_DU_REGISTER_REQ(msg).net_config = read_DU_IP_config(&RC.nrmac[0]->eth_params_n, RC.nrmac[0]->f1u_addr); - itti_send_msg_to_task(TASK_DU_F1, 0, msg); } diff --git a/openair2/RRC/NR/rrc_gNB_du.c b/openair2/RRC/NR/rrc_gNB_du.c index e20121e8c2..d9fe4ef416 100644 --- a/openair2/RRC/NR/rrc_gNB_du.c +++ b/openair2/RRC/NR/rrc_gNB_du.c @@ -29,6 +29,7 @@ #include "executables/softmodem-common.h" #include "common/utils/ds/seq_arr.h" #include "common/utils/alg/foreach.h" +#include "lib/f1ap_interface_management.h" int get_dl_band(const struct f1ap_served_cell_info_t *cell_info) { @@ -261,7 +262,6 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id) DevAssert(rrc); LOG_I(NR_RRC, "Received F1 Setup Request from gNB_DU %lu (%s) on assoc_id %d\n", req->gNB_DU_id, req->gNB_DU_name, assoc_id); - // check: // - it is one cell // - PLMN and Cell ID matches @@ -358,7 +358,8 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id) * allocate memory and copy it in */ du->setup_req = calloc(1,sizeof(*du->setup_req)); AssertFatal(du->setup_req, "out of memory\n"); - *du->setup_req = *req; + // Copy F1AP message + *du->setup_req = cp_f1ap_setup_request(req); // MIB can be null and configured later via DU Configuration Update du->mib = mib; du->sib1 = sib1; @@ -379,6 +380,8 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id) f1ap_setup_resp_t resp = {.transaction_id = req->transaction_id, .num_cells_to_activate = 1, .cells_to_activate[0] = cell}; + // free F1AP message after use + free_f1ap_setup_request(req); int num = read_version(TO_STRING(NR_RRC_VERSION), &resp.rrc_ver[0], &resp.rrc_ver[1], &resp.rrc_ver[2]); AssertFatal(num == 3, "could not read RRC version string %s\n", TO_STRING(NR_RRC_VERSION)); if (rrc->node_name != NULL) From 30628b820c3be6a341e98df2caecf991f439bd49 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 24 May 2024 14:42:09 +0200 Subject: [PATCH 23/46] Add encoding/decoding lib for F1AP Setup Response (Interface Management) --- openair2/F1AP/lib/f1ap_interface_management.c | 337 ++++++++++++++++++ openair2/F1AP/lib/f1ap_interface_management.h | 7 + openair2/F1AP/lib/f1ap_lib_includes.h | 2 + 3 files changed, 346 insertions(+) diff --git a/openair2/F1AP/lib/f1ap_interface_management.c b/openair2/F1AP/lib/f1ap_interface_management.c index 437fa4f36d..674bae84de 100644 --- a/openair2/F1AP/lib/f1ap_interface_management.c +++ b/openair2/F1AP/lib/f1ap_interface_management.c @@ -256,6 +256,108 @@ static void decode_system_info(struct F1AP_GNB_DU_System_Information *DUsi, f1ap sys_info->sib1_length = DUsi->sIB1_message.size; } +static void encode_cells_to_activate(const served_cells_to_activate_t *cell, F1AP_Cells_to_be_Activated_List_ItemIEs_t *cells_to_be_activated_ies) +{ + cells_to_be_activated_ies->id = F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List_Item; + cells_to_be_activated_ies->criticality = F1AP_Criticality_reject; + cells_to_be_activated_ies->value.present = F1AP_Cells_to_be_Activated_List_ItemIEs__value_PR_Cells_to_be_Activated_List_Item; + // Cells to be Activated List Item (M) + F1AP_Cells_to_be_Activated_List_Item_t *cells_to_be_activated_item = + &cells_to_be_activated_ies->value.choice.Cells_to_be_Activated_List_Item; + // NR CGI (M) + MCC_MNC_TO_PLMNID(cell->plmn.mcc, + cell->plmn.mnc, + cell->plmn.mnc_digit_length, + &(cells_to_be_activated_item->nRCGI.pLMN_Identity)); + NR_CELL_ID_TO_BIT_STRING(cell->nr_cellid, &(cells_to_be_activated_item->nRCGI.nRCellIdentity)); + // NR PCI (O) + asn1cCalloc(cells_to_be_activated_item->nRPCI, tmp); + *tmp = cell->nrpci; + // gNB-CU System Information (O) + for (int n = 0; n < cell->num_SI; n++) { + F1AP_ProtocolExtensionContainer_10696P112_t *p = calloc_or_fail(1, sizeof(*p)); + cells_to_be_activated_item->iE_Extensions = (struct F1AP_ProtocolExtensionContainer *)p; + asn1cSequenceAdd(p->list, F1AP_Cells_to_be_Activated_List_ItemExtIEs_t, cells_to_be_activated_itemExtIEs); + cells_to_be_activated_itemExtIEs->id = F1AP_ProtocolIE_ID_id_gNB_CUSystemInformation; + cells_to_be_activated_itemExtIEs->criticality = F1AP_Criticality_reject; + cells_to_be_activated_itemExtIEs->extensionValue.present = + F1AP_Cells_to_be_Activated_List_ItemExtIEs__extensionValue_PR_GNB_CUSystemInformation; + // gNB-CU System Information message + F1AP_GNB_CUSystemInformation_t *gNB_CUSystemInformation = + &cells_to_be_activated_itemExtIEs->extensionValue.choice.GNB_CUSystemInformation; + const f1ap_sib_msg_t *SI_msg = &cell->SI_msg[n]; + if (SI_msg->SI_container != NULL) { + if (SI_msg->SI_type > 6 && SI_msg->SI_type != 9) { + asn1cSequenceAdd(gNB_CUSystemInformation->sibtypetobeupdatedlist.list, F1AP_SibtypetobeupdatedListItem_t, sib_item); + sib_item->sIBtype = SI_msg->SI_type; + OCTET_STRING_fromBuf(&sib_item->sIBmessage, (const char *)SI_msg->SI_container, SI_msg->SI_container_length); + } + } + } +} + +static bool decode_cells_to_activate(served_cells_to_activate_t *out, const F1AP_Cells_to_be_Activated_List_ItemIEs_t *in) +{ + AssertError(in->id == F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List_Item, + return false, + "ID != F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List_Item\n"); + AssertError(in->value.present == F1AP_Cells_to_be_Activated_List_ItemIEs__value_PR_Cells_to_be_Activated_List_Item, + return false, + "in->value.present != F1AP_Cells_to_be_Activated_List_ItemIEs__value_PR_Cells_to_be_Activated_List_Item\n"); + const F1AP_Cells_to_be_Activated_List_Item_t *cell = &in->value.choice.Cells_to_be_Activated_List_Item; + // NR CGI (M) + TBCD_TO_MCC_MNC(&cell->nRCGI.pLMN_Identity, out->plmn.mcc, out->plmn.mnc, out->plmn.mnc_digit_length); + BIT_STRING_TO_NR_CELL_IDENTITY(&cell->nRCGI.nRCellIdentity, out->nr_cellid); + // NR PCI (O) + if (cell->nRPCI != NULL) + out->nrpci = *cell->nRPCI; + /* IE extensions (O) */ + F1AP_ProtocolExtensionContainer_10696P112_t *ext = (F1AP_ProtocolExtensionContainer_10696P112_t *)cell->iE_Extensions; + if (ext != NULL) { + for (int cnt = 0; cnt < ext->list.count; cnt++) { + AssertError(ext->list.count == 1, return false, "At least one SI message should be present, and only 1 is supported"); + F1AP_Cells_to_be_Activated_List_ItemExtIEs_t *cells_to_be_activated_list_itemExtIEs = + (F1AP_Cells_to_be_Activated_List_ItemExtIEs_t *)ext->list.array[cnt]; + /* IE extensions items (O) */ + switch (cells_to_be_activated_list_itemExtIEs->id) { + /* gNB-CU System Information */ + case F1AP_ProtocolIE_ID_id_gNB_CUSystemInformation: { + out->nrpci = (cell->nRPCI != NULL) ? *cell->nRPCI : 0; + F1AP_GNB_CUSystemInformation_t *gNB_CUSystemInformation = + (F1AP_GNB_CUSystemInformation_t *)&cells_to_be_activated_list_itemExtIEs->extensionValue.choice.GNB_CUSystemInformation; + /* System Information */ + out->num_SI = gNB_CUSystemInformation->sibtypetobeupdatedlist.list.count; + for (int s = 0; s < out->num_SI; s++) { + F1AP_SibtypetobeupdatedListItem_t *sib_item = gNB_CUSystemInformation->sibtypetobeupdatedlist.list.array[s]; + /* SI container */ + f1ap_sib_msg_t *SI_msg = &out->SI_msg[s]; + SI_msg->SI_container = cp_octet_string(&sib_item->sIBmessage, &SI_msg->SI_container_length); + /* SIB type */ + SI_msg->SI_type = sib_item->sIBtype; + } + break; + } + case F1AP_ProtocolIE_ID_id_AvailablePLMNList: + AssertError(1 == 0, return false, "F1AP_ProtocolIE_ID_id_AvailablePLMNList is not supported"); + break; + case F1AP_ProtocolIE_ID_id_ExtendedAvailablePLMN_List: + AssertError(1 == 0, return false, "F1AP_ProtocolIE_ID_id_ExtendedAvailablePLMN_List is not supported"); + break; + case F1AP_ProtocolIE_ID_id_IAB_Info_IAB_donor_CU: + AssertError(1 == 0, return false, "F1AP_ProtocolIE_ID_id_IAB_Info_IAB_donor_CU is not supported"); + break; + case F1AP_ProtocolIE_ID_id_AvailableSNPN_ID_List: + AssertError(1 == 0, return false, "F1AP_ProtocolIE_ID_id_AvailableSNPN_ID_List is not supported"); + break; + default: + AssertError(1 == 0, return false, "F1AP_ProtocolIE_ID_id %ld unknown\n", cells_to_be_activated_list_itemExtIEs->id); + break; + } + } + } + return true; +} + /* ==================================== * F1 SETUP REQUEST * ==================================== */ @@ -519,3 +621,238 @@ void free_f1ap_setup_request(const f1ap_setup_req_t *msg) free_f1ap_cell(&msg->cell[i].info, msg->cell[i].sys_info); } } + +/* ==================================== + * F1 Setup Response + * ==================================== */ + +/** + * @brief F1 Setup Response encoding (9.2.1.5 of 3GPP TS 38.473) + * gNB-CU → gNB-DU + */ +F1AP_F1AP_PDU_t *encode_f1ap_setup_response(const f1ap_setup_resp_t *msg) +{ + F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + + /* Create */ + /* 0. Message Type */ + pdu->present = F1AP_F1AP_PDU_PR_successfulOutcome; + asn1cCalloc(pdu->choice.successfulOutcome, tmp); + tmp->procedureCode = F1AP_ProcedureCode_id_F1Setup; + tmp->criticality = F1AP_Criticality_reject; + tmp->value.present = F1AP_SuccessfulOutcome__value_PR_F1SetupResponse; + F1AP_F1SetupResponse_t *out = &pdu->choice.successfulOutcome->value.choice.F1SetupResponse; + // Transaction ID (M) + asn1cSequenceAdd(out->protocolIEs.list, F1AP_F1SetupResponseIEs_t, ie1); + ie1->id = F1AP_ProtocolIE_ID_id_TransactionID; + ie1->criticality = F1AP_Criticality_reject; + ie1->value.present = F1AP_F1SetupResponseIEs__value_PR_TransactionID; + ie1->value.choice.TransactionID = msg->transaction_id; + // gNB-CU Name (O) + if (msg->gNB_CU_name != NULL) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_F1SetupResponseIEs_t, ie2); + ie2->id = F1AP_ProtocolIE_ID_id_gNB_CU_Name; + ie2->criticality = F1AP_Criticality_ignore; + ie2->value.present = F1AP_F1SetupResponseIEs__value_PR_GNB_CU_Name; + OCTET_STRING_fromBuf(&ie2->value.choice.GNB_CU_Name, msg->gNB_CU_name, strlen(msg->gNB_CU_name)); + } + // Cells to be Activated List (O) + for (int i = 0; i < msg->num_cells_to_activate; i++) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_F1SetupResponseIEs_t, ie3); + ie3->id = F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List; + ie3->criticality = F1AP_Criticality_reject; + ie3->value.present = F1AP_F1SetupResponseIEs__value_PR_Cells_to_be_Activated_List; + asn1cSequenceAdd(ie3->value.choice.Cells_to_be_Activated_List.list, + F1AP_Cells_to_be_Activated_List_ItemIEs_t, + cells_to_be_activated_ies); + encode_cells_to_activate(&msg->cells_to_activate[i], cells_to_be_activated_ies); + } + // gNB-CU RRC version (M) + asn1cSequenceAdd(out->protocolIEs.list, F1AP_F1SetupResponseIEs_t, ie4); + ie4->id = F1AP_ProtocolIE_ID_id_GNB_CU_RRC_Version; + ie4->criticality = F1AP_Criticality_reject; + ie4->value.present = F1AP_F1SetupResponseIEs__value_PR_RRC_Version; + // RRC Version: "This IE is not used in this release." + // we put one bit for each byte in rrc_ver that is != 0 + uint8_t bits = 0; + for (int i = 0; i < sizeofArray(msg->rrc_ver); ++i) + bits |= (msg->rrc_ver[i] != 0) << i; + BIT_STRING_t *bs = &ie4->value.choice.RRC_Version.latest_RRC_Version; + bs->buf = calloc_or_fail(1, sizeof(*bs->buf)); + bs->buf[0] = bits; + bs->size = 1; + bs->bits_unused = 5; + + F1AP_ProtocolExtensionContainer_10696P228_t *p = calloc_or_fail(1, sizeof(*p)); + asn1cSequenceAdd(p->list, F1AP_RRC_Version_ExtIEs_t, rrcv_ext); + rrcv_ext->id = F1AP_ProtocolIE_ID_id_latest_RRC_Version_Enhanced; + rrcv_ext->criticality = F1AP_Criticality_ignore; + rrcv_ext->extensionValue.present = F1AP_RRC_Version_ExtIEs__extensionValue_PR_OCTET_STRING_SIZE_3_; + OCTET_STRING_t *os = &rrcv_ext->extensionValue.choice.OCTET_STRING_SIZE_3_; + os->size = sizeofArray(msg->rrc_ver); + os->buf = malloc_or_fail(sizeof(msg->rrc_ver)); + for (int i = 0; i < sizeofArray(msg->rrc_ver); ++i) + os->buf[i] = msg->rrc_ver[i]; + ie4->value.choice.RRC_Version.iE_Extensions = (struct F1AP_ProtocolExtensionContainer *)p; + + return pdu; +} + +/** + * @brief F1 Setup Response decoding (9.2.1.5 of 3GPP TS 38.473) + * gNB-CU → gNB-DU + */ +bool decode_f1ap_setup_response(const F1AP_F1AP_PDU_t *pdu, f1ap_setup_resp_t *out) +{ + /* Check presence of message type */ + _F1_EQ_CHECK_INT(pdu->present, F1AP_F1AP_PDU_PR_successfulOutcome); + _F1_EQ_CHECK_LONG(pdu->choice.successfulOutcome->procedureCode, F1AP_ProcedureCode_id_F1Setup); + _F1_EQ_CHECK_INT(pdu->choice.successfulOutcome->value.present, F1AP_SuccessfulOutcome__value_PR_F1SetupResponse); + /* Check presence of mandatory IEs */ + F1AP_F1SetupResponse_t *in = &pdu->choice.successfulOutcome->value.choice.F1SetupResponse; + F1AP_F1SetupResponseIEs_t *ie; + F1AP_LIB_FIND_IE(F1AP_F1SetupResponseIEs_t, ie, in, F1AP_ProtocolIE_ID_id_TransactionID, true); + F1AP_LIB_FIND_IE(F1AP_F1SetupResponseIEs_t, ie, in, F1AP_ProtocolIE_ID_id_GNB_CU_RRC_Version, true); + /* Loop over all IEs */ + for (int i = 0; i < in->protocolIEs.list.count; i++) { + ie = in->protocolIEs.list.array[i]; + switch (ie->id) { + case F1AP_ProtocolIE_ID_id_TransactionID: + // Transaction ID (M) + _F1_EQ_CHECK_INT(ie->value.present, F1AP_F1SetupResponseIEs__value_PR_TransactionID); + AssertError(ie->value.choice.TransactionID != -1, return false, "ie->value.choice.TransactionID is -1"); + out->transaction_id = ie->value.choice.TransactionID; + break; + + case F1AP_ProtocolIE_ID_id_gNB_CU_Name: { + // gNB-CU Name (O) + _F1_EQ_CHECK_INT(ie->value.present, F1AP_F1SetupResponseIEs__value_PR_GNB_CU_Name); + const F1AP_GNB_CU_Name_t *cu_name = &ie->value.choice.GNB_CU_Name; + out->gNB_CU_name = calloc_or_fail(cu_name->size + 1, sizeof(*out->gNB_CU_name)); + strncpy(out->gNB_CU_name, (char *)cu_name->buf, cu_name->size); + } break; + + case F1AP_ProtocolIE_ID_id_GNB_CU_RRC_Version: + // gNB-CU RRC version (M) + _F1_EQ_CHECK_INT(ie->value.present, F1AP_F1SetupResponseIEs__value_PR_RRC_Version); + // RRC Version: "This IE is not used in this release." + if (ie->value.choice.RRC_Version.iE_Extensions) { + F1AP_ProtocolExtensionContainer_10696P228_t *ext = + (F1AP_ProtocolExtensionContainer_10696P228_t *)ie->value.choice.RRC_Version.iE_Extensions; + if (ext->list.count > 0) { + F1AP_RRC_Version_ExtIEs_t *rrcext = ext->list.array[0]; + OCTET_STRING_t *os = &rrcext->extensionValue.choice.OCTET_STRING_SIZE_3_; + for (int i = 0; i < sizeofArray(out->rrc_ver); i++) + out->rrc_ver[i] = os->buf[i]; + } + } + break; + + case F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List: { + // Cells to be Activated List (O) + if (ie->value.present != F1AP_F1SetupResponseIEs__value_PR_Cells_to_be_Activated_List) + break; + struct F1AP_Cells_to_be_Activated_List *Cells_to_be_Activated_List = &ie->value.choice.Cells_to_be_Activated_List; + out->num_cells_to_activate = Cells_to_be_Activated_List->list.count; + // Loop Cells to be Activated List Items (count >= 1) + AssertError(out->num_cells_to_activate > 0, return false, "At least 1 cell must be present"); + for (int i = 0; i < out->num_cells_to_activate; i++) { + const F1AP_Cells_to_be_Activated_List_ItemIEs_t *itemIEs + = (F1AP_Cells_to_be_Activated_List_ItemIEs_t *)Cells_to_be_Activated_List->list.array[i]; + if (!decode_cells_to_activate(&out->cells_to_activate[i], itemIEs)) + return false; + } + break; + } + default: + AssertError(1 == 0, return false, "F1AP_ProtocolIE_ID_id %ld unknown\n", ie->id); + break; + } + } + + return true; +} + +/** + * @brief F1AP Setup Response equality check + */ +bool eq_f1ap_setup_response(const f1ap_setup_resp_t *a, const f1ap_setup_resp_t *b) +{ + _F1_EQ_CHECK_STR(a->gNB_CU_name, b->gNB_CU_name); + _F1_EQ_CHECK_INT(a->num_cells_to_activate, b->num_cells_to_activate); + _F1_EQ_CHECK_LONG(a->transaction_id, b->transaction_id); + if (a->num_cells_to_activate) { + for (int i = 0; i < a->num_cells_to_activate; i++) { + const served_cells_to_activate_t *a_cell = &a->cells_to_activate[i]; + const served_cells_to_activate_t *b_cell = &b->cells_to_activate[i]; + _F1_EQ_CHECK_LONG(a_cell->nr_cellid, b_cell->nr_cellid); + _F1_EQ_CHECK_INT(a_cell->nrpci, b_cell->nrpci); + _F1_EQ_CHECK_INT(a_cell->num_SI, b_cell->num_SI); + _F1_EQ_CHECK_LONG(a_cell->nr_cellid, b_cell->nr_cellid); + if (!eq_f1ap_plmn(&a_cell->plmn, &b_cell->plmn)) + return false; + if (sizeofArray(a->cells_to_activate[i].SI_msg) != sizeofArray(b->cells_to_activate[i].SI_msg)) + return false; + for (int j = 0; j < b->cells_to_activate[i].num_SI; j++) { + const f1ap_sib_msg_t *a_SI_msg = &a->cells_to_activate[i].SI_msg[j]; + const f1ap_sib_msg_t *b_SI_msg = &b->cells_to_activate[i].SI_msg[j]; + _F1_EQ_CHECK_INT(*a_SI_msg->SI_container, *b_SI_msg->SI_container); + _F1_EQ_CHECK_INT(a_SI_msg->SI_container_length, b_SI_msg->SI_container_length); + _F1_EQ_CHECK_INT(a_SI_msg->SI_type, b_SI_msg->SI_type); + } + } + } + _F1_EQ_CHECK_LONG(sizeofArray(a->rrc_ver), sizeofArray(b->rrc_ver)); + for (int i = 0; i < sizeofArray(a->rrc_ver); i++) { + _F1_EQ_CHECK_INT(a->rrc_ver[i], b->rrc_ver[i]); + } + return true; +} + +/** + * @brief F1AP Setup Response deep copy + */ +f1ap_setup_resp_t cp_f1ap_setup_response(const f1ap_setup_resp_t *msg) +{ + f1ap_setup_resp_t cp = {0}; + /* gNB_CU_name */ + if (msg->gNB_CU_name != NULL) + cp.gNB_CU_name = strdup(msg->gNB_CU_name); + /* transaction_id */ + cp.transaction_id = msg->transaction_id; + /* num_cells_available */ + cp.num_cells_to_activate = msg->num_cells_to_activate; + for (int n = 0; n < msg->num_cells_to_activate; n++) { + /* cell.info */ + served_cells_to_activate_t *cp_cell = &cp.cells_to_activate[n]; + const served_cells_to_activate_t *msg_cell = &msg->cells_to_activate[n]; + cp_cell->nr_cellid = msg_cell->nr_cellid; + cp_cell->nrpci = msg_cell->nrpci; + cp_cell->num_SI = msg_cell->num_SI; + cp_cell->plmn = msg_cell->plmn; + for (int j = 0; j < cp_cell->num_SI; j++) { + f1ap_sib_msg_t *cp_SI_msg = &cp_cell->SI_msg[j]; + const f1ap_sib_msg_t *b_SI_msg = &msg_cell->SI_msg[j]; + cp_SI_msg->SI_container_length = b_SI_msg->SI_container_length; + cp_SI_msg->SI_container = malloc_or_fail(cp_SI_msg->SI_container_length); + *cp_SI_msg->SI_container = *b_SI_msg->SI_container; + cp_SI_msg->SI_type = b_SI_msg->SI_type; + } + } + for (int i = 0; i < sizeofArray(msg->rrc_ver); i++) + cp.rrc_ver[i] = msg->rrc_ver[i]; + return cp; +} + +/** + * @brief F1AP Setup Response memory management + */ +void free_f1ap_setup_response(const f1ap_setup_resp_t *msg) +{ + DevAssert(msg != NULL); + free(msg->gNB_CU_name); + for (int i = 0; i < msg->num_cells_to_activate; i++) + for (int j = 0; j < msg->cells_to_activate[i].num_SI; j++) + if (msg->cells_to_activate[i].SI_msg[j].SI_container_length > 0) + free(msg->cells_to_activate[i].SI_msg[j].SI_container); +} diff --git a/openair2/F1AP/lib/f1ap_interface_management.h b/openair2/F1AP/lib/f1ap_interface_management.h index 6b196b9999..33a5f8402b 100644 --- a/openair2/F1AP/lib/f1ap_interface_management.h +++ b/openair2/F1AP/lib/f1ap_interface_management.h @@ -33,4 +33,11 @@ f1ap_setup_req_t cp_f1ap_setup_request(const f1ap_setup_req_t *msg); bool eq_f1ap_setup_request(const f1ap_setup_req_t *a, const f1ap_setup_req_t *b); void free_f1ap_setup_request(const f1ap_setup_req_t *msg); +/* F1 Setup Response */ +struct F1AP_F1AP_PDU *encode_f1ap_setup_response(const f1ap_setup_resp_t *msg); +bool decode_f1ap_setup_response(const struct F1AP_F1AP_PDU *pdu, f1ap_setup_resp_t *out); +void free_f1ap_setup_response(const f1ap_setup_resp_t *msg); +f1ap_setup_resp_t cp_f1ap_setup_response(const f1ap_setup_resp_t *msg); +bool eq_f1ap_setup_response(const f1ap_setup_resp_t *a, const f1ap_setup_resp_t *b); + #endif /* F1AP_INTERFACE_MANAGEMENT_H_ */ diff --git a/openair2/F1AP/lib/f1ap_lib_includes.h b/openair2/F1AP/lib/f1ap_lib_includes.h index 0e5ace104d..2386073dee 100644 --- a/openair2/F1AP/lib/f1ap_lib_includes.h +++ b/openair2/F1AP/lib/f1ap_lib_includes.h @@ -37,5 +37,7 @@ #include "F1AP_FDD-Info.h" #include "F1AP_TDD-Info.h" #include "F1AP_FreqBandNrItem.h" +#include "F1AP_SuccessfulOutcome.h" +#include "F1AP_SibtypetobeupdatedListItem.h" #endif /* F1AP_LIB_INCLUDES_H_ */ From df2c92e652eee9a642e22aa8687c4217969d4087 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Mon, 27 May 2024 17:23:33 +0200 Subject: [PATCH 24/46] Add test for F1AP Setup Response enc/dec lib --- openair2/F1AP/tests/f1ap_lib_test.c | 60 +++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/openair2/F1AP/tests/f1ap_lib_test.c b/openair2/F1AP/tests/f1ap_lib_test.c index 005ebe5bb8..16c404b722 100644 --- a/openair2/F1AP/tests/f1ap_lib_test.c +++ b/openair2/F1AP/tests/f1ap_lib_test.c @@ -3,6 +3,7 @@ #include #include "common/utils/assertions.h" +#include "common/utils/utils.h" #include "f1ap_messages_types.h" #include "F1AP_F1AP-PDU.h" @@ -271,11 +272,70 @@ static void test_f1ap_setup_request(void) free_f1ap_setup_request(&orig); } +/** + * @brief Test F1AP Setup Response Encoding/Decoding + */ +static void test_f1ap_setup_response(void) +{ + /* allocate memory */ + /* gNB_CU_name */ + char *cu_name = "OAI-CU"; + int len = strlen(cu_name) + 1; + uint8_t *gNB_CU_name = calloc(len, sizeof(uint8_t)); + AssertFatal(gNB_CU_name != NULL, "out of memory\n"); + memcpy((void *)gNB_CU_name, cu_name, len); + /* create message */ + f1ap_setup_resp_t orig = { + .gNB_CU_name = (char *)gNB_CU_name, + .transaction_id = 2, + .rrc_ver[0] = 12, + .rrc_ver[1] = 34, + .rrc_ver[2] = 56, + .num_cells_to_activate = 1, + .cells_to_activate[0].nr_cellid = 123456, + .cells_to_activate[0].nrpci = 1, + .cells_to_activate[0].plmn.mcc = 12, + .cells_to_activate[0].plmn.mnc = 123, + .cells_to_activate[0].plmn.mnc_digit_length = 3, + }; + /* Cells to activate */ + if (orig.num_cells_to_activate) { + /* SI_container */ + char *s = "test"; + int SI_container_length = strlen(s) + 1; + orig.cells_to_activate[0].num_SI = 1; + f1ap_sib_msg_t *SI_msg = &orig.cells_to_activate[0].SI_msg[0]; + SI_msg->SI_container = malloc_or_fail(SI_container_length); + memcpy(SI_msg->SI_container, (uint8_t *)s, SI_container_length); + SI_msg->SI_container_length = SI_container_length; + SI_msg->SI_type = 7; + } + F1AP_F1AP_PDU_t *f1enc = encode_f1ap_setup_response(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_setup_resp_t decoded = {0}; + bool ret = decode_f1ap_setup_response(f1dec, &decoded); + AssertFatal(ret, "decode_f1ap_setup_response(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_f1ap_setup_response(&orig, &decoded); + AssertFatal(ret, "eq_f1ap_setup_response(): decoded message doesn't match\n"); + free_f1ap_setup_response(&decoded); + + f1ap_setup_resp_t cp = cp_f1ap_setup_response(&orig); + ret = eq_f1ap_setup_response(&orig, &cp); + AssertFatal(ret, "eq_f1ap_setup_response(): copied message doesn't match\n"); + free_f1ap_setup_response(&cp); + free_f1ap_setup_response(&orig); +} + int main() { test_initial_ul_rrc_message_transfer(); test_dl_rrc_message_transfer(); test_ul_rrc_message_transfer(); test_f1ap_setup_request(); + test_f1ap_setup_response(); return 0; } From 3a5ace00d274ae1a595aec984231a813a8d43c4f Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Thu, 29 Aug 2024 23:51:29 +0200 Subject: [PATCH 25/46] Use F1AP lib for F1 Setup Response in stack --- openair2/F1AP/f1ap_cu_interface_management.c | 138 ++------------ openair2/F1AP/f1ap_du_interface_management.c | 176 +----------------- .../LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 9 +- openair2/RRC/NR/mac_rrc_dl_f1ap.c | 2 + 4 files changed, 24 insertions(+), 301 deletions(-) diff --git a/openair2/F1AP/f1ap_cu_interface_management.c b/openair2/F1AP/f1ap_cu_interface_management.c index 2685325d6e..c3a9f39d7d 100644 --- a/openair2/F1AP/f1ap_cu_interface_management.c +++ b/openair2/F1AP/f1ap_cu_interface_management.c @@ -102,142 +102,26 @@ int CU_handle_F1_SETUP_REQUEST(instance_t instance, sctp_assoc_t assoc_id, uint3 return 0; } +/** + * @brief F1AP Setup Response encoding (9.2.1.5 of 3GPP TS 38.473) and message transfer + */ int CU_send_F1_SETUP_RESPONSE(sctp_assoc_t assoc_id, f1ap_setup_resp_t *f1ap_setup_resp) { - F1AP_F1AP_PDU_t pdu= {0}; uint8_t *buffer=NULL; - uint32_t len=0; - /* Create */ - /* 0. Message Type */ - pdu.present = F1AP_F1AP_PDU_PR_successfulOutcome; - asn1cCalloc(pdu.choice.successfulOutcome, tmp); - tmp->procedureCode = F1AP_ProcedureCode_id_F1Setup; - tmp->criticality = F1AP_Criticality_reject; - tmp->value.present = F1AP_SuccessfulOutcome__value_PR_F1SetupResponse; - F1AP_F1SetupResponse_t *out = &pdu.choice.successfulOutcome->value.choice.F1SetupResponse; - /* mandatory */ - /* c1. Transaction ID (integer value)*/ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_F1SetupResponseIEs_t, ie1); - ie1->id = F1AP_ProtocolIE_ID_id_TransactionID; - ie1->criticality = F1AP_Criticality_reject; - ie1->value.present = F1AP_F1SetupResponseIEs__value_PR_TransactionID; - ie1->value.choice.TransactionID = f1ap_setup_resp->transaction_id; + uint32_t len = 0; - /* optional */ - /* c2. GNB_CU_Name */ - if (f1ap_setup_resp->gNB_CU_name != NULL) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_F1SetupResponseIEs_t, ie2); - ie2->id = F1AP_ProtocolIE_ID_id_gNB_CU_Name; - ie2->criticality = F1AP_Criticality_ignore; - ie2->value.present = F1AP_F1SetupResponseIEs__value_PR_GNB_CU_Name; - OCTET_STRING_fromBuf(&ie2->value.choice.GNB_CU_Name, f1ap_setup_resp->gNB_CU_name, - strlen(f1ap_setup_resp->gNB_CU_name)); - } - - /* mandatory */ - /* c3. cells to be Activated list */ - int num_cells_to_activate = f1ap_setup_resp->num_cells_to_activate; - LOG_D(F1AP, "num_cells_to_activate = %d \n", num_cells_to_activate); - - if (num_cells_to_activate >0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_F1SetupResponseIEs_t, ie3); - ie3->id = F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List; - ie3->criticality = F1AP_Criticality_reject; - ie3->value.present = F1AP_F1SetupResponseIEs__value_PR_Cells_to_be_Activated_List; - - for (int i=0; ivalue.choice.Cells_to_be_Activated_List.list, - F1AP_Cells_to_be_Activated_List_ItemIEs_t, cells_to_be_activated_ies); - cells_to_be_activated_ies->id = F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List_Item; - cells_to_be_activated_ies->criticality = F1AP_Criticality_reject; - cells_to_be_activated_ies->value.present = F1AP_Cells_to_be_Activated_List_ItemIEs__value_PR_Cells_to_be_Activated_List_Item; - /* 3.1 cells to be Activated list item */ - F1AP_Cells_to_be_Activated_List_Item_t *cells_to_be_activated_item= - &cells_to_be_activated_ies->value.choice.Cells_to_be_Activated_List_Item; - /* - nRCGI */ - addnRCGI(cells_to_be_activated_item->nRCGI, f1ap_setup_resp->cells_to_activate+i); - - /* optional */ - /* - nRPCI */ - if (1) { - cells_to_be_activated_item->nRPCI = (F1AP_NRPCI_t *)calloc(1, sizeof(F1AP_NRPCI_t)); - *cells_to_be_activated_item->nRPCI = f1ap_setup_resp->cells_to_activate[i].nrpci; // int 0..1007 - } - - /* optional */ - /* - gNB-CU System Information */ - if (f1ap_setup_resp->cells_to_activate[i].num_SI > 0) { - /* 3.1.2 gNB-CUSystem Information */ - F1AP_ProtocolExtensionContainer_10696P112_t *p = calloc(1, sizeof(* p)); - cells_to_be_activated_item->iE_Extensions = (struct F1AP_ProtocolExtensionContainer *) p; - asn1cSequenceAdd(p->list, F1AP_Cells_to_be_Activated_List_ItemExtIEs_t, cells_to_be_activated_itemExtIEs); - cells_to_be_activated_itemExtIEs->id = F1AP_ProtocolIE_ID_id_gNB_CUSystemInformation; - cells_to_be_activated_itemExtIEs->criticality = F1AP_Criticality_reject; - cells_to_be_activated_itemExtIEs->extensionValue.present = F1AP_Cells_to_be_Activated_List_ItemExtIEs__extensionValue_PR_GNB_CUSystemInformation; - F1AP_GNB_CUSystemInformation_t *gNB_CUSystemInformation = - &cells_to_be_activated_itemExtIEs->extensionValue.choice.GNB_CUSystemInformation; - - // for (int sIBtype=2;sIBtype<33;sIBtype++) { //21 ? 33 ? - for (int sIBtype=2; sIBtype<21; sIBtype++) { - for (int n = 0; n < f1ap_setup_resp->cells_to_activate[i].num_SI; n++) { - if (f1ap_setup_resp->cells_to_activate[i].SI_msg[n].SI_container != NULL) { - if (f1ap_setup_resp->cells_to_activate[i].SI_msg[n].SI_type > 6 - && f1ap_setup_resp->cells_to_activate[i].SI_msg[n].SI_type != 9) { - asn1cSequenceAdd(gNB_CUSystemInformation->sibtypetobeupdatedlist.list, F1AP_SibtypetobeupdatedListItem_t, sib_item); - sib_item->sIBtype = f1ap_setup_resp->cells_to_activate[i].SI_msg[n].SI_type; - OCTET_STRING_fromBuf(&sib_item->sIBmessage, - (const char *)f1ap_setup_resp->cells_to_activate[i].SI_msg[n].SI_container, - f1ap_setup_resp->cells_to_activate[i].SI_msg[n].SI_container_length); - LOG_D(F1AP, - "f1ap_setup_resp->cells_to_activate[%d].SI_msg[%d].SI_container_length = %d \n", - i, - n, - f1ap_setup_resp->cells_to_activate[i].SI_msg[n].SI_container_length); - } - } - } - } - } - } - } - - /* c5. RRC VERSION */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_F1SetupResponseIEs_t, ie4); - ie4->id = F1AP_ProtocolIE_ID_id_GNB_CU_RRC_Version; - ie4->criticality = F1AP_Criticality_reject; - ie4->value.present = F1AP_F1SetupResponseIEs__value_PR_RRC_Version; - // RRC Version: "This IE is not used in this release." - // we put one bit for each byte in rrc_ver that is != 0 - uint8_t bits = 0; - for (int i = 0; i < 3; ++i) - bits |= (f1ap_setup_resp->rrc_ver[i] != 0) << i; - BIT_STRING_t *bs = &ie4->value.choice.RRC_Version.latest_RRC_Version; - bs->buf = calloc(1, sizeof(char)); - AssertFatal(bs->buf != NULL, "out of memory\n"); - bs->buf[0] = bits; - bs->size = 1; - bs->bits_unused = 5; - - F1AP_ProtocolExtensionContainer_10696P228_t *p = (F1AP_ProtocolExtensionContainer_10696P228_t*)calloc(1, sizeof(F1AP_ProtocolExtensionContainer_10696P228_t)); - asn1cSequenceAdd(p->list, F1AP_RRC_Version_ExtIEs_t, rrcv_ext); - rrcv_ext->id = F1AP_ProtocolIE_ID_id_latest_RRC_Version_Enhanced; - rrcv_ext->criticality = F1AP_Criticality_ignore; - rrcv_ext->extensionValue.present = F1AP_RRC_Version_ExtIEs__extensionValue_PR_OCTET_STRING_SIZE_3_; - OCTET_STRING_t *os = &rrcv_ext->extensionValue.choice.OCTET_STRING_SIZE_3_; - os->size = 3; - os->buf = malloc(3 * sizeof(*os->buf)); - AssertFatal(os->buf != NULL, "out of memory\n"); - for (int i = 0; i < 3; ++i) - os->buf[i] = f1ap_setup_resp->rrc_ver[i]; - ie4->value.choice.RRC_Version.iE_Extensions = (struct F1AP_ProtocolExtensionContainer *)p; + /* Encode F1 Setup Response */ + F1AP_F1AP_PDU_t *pdu = encode_f1ap_setup_response(f1ap_setup_resp); + /* Free after encode */ + free_f1ap_setup_response(f1ap_setup_resp); /* encode */ - if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { + if (f1ap_encode_pdu(pdu, &buffer, &len) < 0) { LOG_E(F1AP, "Failed to encode F1 setup response\n"); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); return -1; } - - ASN_STRUCT_RESET(asn_DEF_F1AP_F1AP_PDU, &pdu); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); return 0; } diff --git a/openair2/F1AP/f1ap_du_interface_management.c b/openair2/F1AP/f1ap_du_interface_management.c index ab55fd0f05..5d1f44dbdc 100644 --- a/openair2/F1AP/f1ap_du_interface_management.c +++ b/openair2/F1AP/f1ap_du_interface_management.c @@ -325,177 +325,13 @@ int DU_send_F1_SETUP_REQUEST(sctp_assoc_t assoc_id, const f1ap_setup_req_t *setu int DU_handle_F1_SETUP_RESPONSE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { LOG_D(F1AP, "DU_handle_F1_SETUP_RESPONSE\n"); - AssertFatal(pdu->present == F1AP_F1AP_PDU_PR_successfulOutcome, - "pdu->present != F1AP_F1AP_PDU_PR_successfulOutcome\n"); - AssertFatal(pdu->choice.successfulOutcome->procedureCode == F1AP_ProcedureCode_id_F1Setup, - "pdu->choice.successfulOutcome->procedureCode != F1AP_ProcedureCode_id_F1Setup\n"); - AssertFatal(pdu->choice.successfulOutcome->criticality == F1AP_Criticality_reject, - "pdu->choice.successfulOutcome->criticality != F1AP_Criticality_reject\n"); - AssertFatal(pdu->choice.successfulOutcome->value.present == F1AP_SuccessfulOutcome__value_PR_F1SetupResponse, - "pdu->choice.successfulOutcome->value.present != F1AP_SuccessfulOutcome__value_PR_F1SetupResponse\n"); - F1AP_F1SetupResponse_t *in = &pdu->choice.successfulOutcome->value.choice.F1SetupResponse; - F1AP_F1SetupResponseIEs_t *ie; - int TransactionId = -1; - int num_cells_to_activate = 0; + /* Decode */ f1ap_setup_resp_t resp = {0}; - - for (int i=0; i < in->protocolIEs.list.count; i++) { - ie = in->protocolIEs.list.array[i]; - - switch (ie->id) { - case F1AP_ProtocolIE_ID_id_TransactionID: - AssertFatal(ie->criticality == F1AP_Criticality_reject, - "ie->criticality != F1AP_Criticality_reject\n"); - AssertFatal(ie->value.present == F1AP_F1SetupResponseIEs__value_PR_TransactionID, - "ie->value.present != F1AP_F1SetupResponseIEs__value_PR_TransactionID\n"); - TransactionId=ie->value.choice.TransactionID; - LOG_D(F1AP, "F1AP: F1Setup-Resp: TransactionId %d\n", - TransactionId); - break; - - case F1AP_ProtocolIE_ID_id_gNB_CU_Name: - AssertFatal(ie->criticality == F1AP_Criticality_ignore, - "ie->criticality != F1AP_Criticality_ignore\n"); - AssertFatal(ie->value.present == F1AP_F1SetupResponseIEs__value_PR_GNB_CU_Name, - "ie->value.present != F1AP_F1SetupResponseIEs__value_PR_GNB_CU_Name\n"); - resp.gNB_CU_name = malloc(ie->value.choice.GNB_CU_Name.size+1); - memcpy(resp.gNB_CU_name, ie->value.choice.GNB_CU_Name.buf, ie->value.choice.GNB_CU_Name.size); - resp.gNB_CU_name[ie->value.choice.GNB_CU_Name.size] = '\0'; - LOG_D(F1AP, "F1AP: F1Setup-Resp: gNB_CU_name %s\n", resp.gNB_CU_name); - break; - - case F1AP_ProtocolIE_ID_id_GNB_CU_RRC_Version: - AssertFatal(ie->criticality == F1AP_Criticality_reject, - "ie->criticality != F1AP_Criticality_reject\n"); - AssertFatal(ie->value.present == F1AP_F1SetupResponseIEs__value_PR_RRC_Version, - "ie->value.present != F1AP_F1SetupResponseIEs__value_PR_RRC_Version\n"); - // RRC Version: "This IE is not used in this release." - if(ie->value.choice.RRC_Version.iE_Extensions) { - F1AP_ProtocolExtensionContainer_10696P228_t *ext = - (F1AP_ProtocolExtensionContainer_10696P228_t *)ie->value.choice.RRC_Version.iE_Extensions; - if(ext->list.count > 0){ - F1AP_RRC_Version_ExtIEs_t *rrcext = ext->list.array[0]; - OCTET_STRING_t *os = &rrcext->extensionValue.choice.OCTET_STRING_SIZE_3_; - for (int i = 0; i < 3; i++) - resp.rrc_ver[i] = os->buf[i]; - } - } - break; - - case F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List: { - AssertFatal(ie->criticality == F1AP_Criticality_reject, - "ie->criticality != F1AP_Criticality_reject\n"); - AssertFatal(ie->value.present == F1AP_F1SetupResponseIEs__value_PR_Cells_to_be_Activated_List, - "ie->value.present != F1AP_F1SetupResponseIEs__value_PR_Cells_to_be_Activated_List\n"); - num_cells_to_activate = ie->value.choice.Cells_to_be_Activated_List.list.count; - LOG_D(F1AP, "F1AP: Activating %d cells\n",num_cells_to_activate); - - for (int i=0; ivalue.choice.Cells_to_be_Activated_List.list.array[i]; - AssertFatal(cells_to_be_activated_list_item_ies->id == F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List_Item, - "cells_to_be_activated_list_item_ies->id != F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List_Item"); - AssertFatal(cells_to_be_activated_list_item_ies->criticality == F1AP_Criticality_reject, - "cells_to_be_activated_list_item_ies->criticality == F1AP_Criticality_reject"); - AssertFatal(cells_to_be_activated_list_item_ies->value.present == F1AP_Cells_to_be_Activated_List_ItemIEs__value_PR_Cells_to_be_Activated_List_Item, - "cells_to_be_activated_list_item_ies->value.present == F1AP_Cells_to_be_Activated_List_ItemIEs__value_PR_Cells_to_be_Activated_List_Item"); - F1AP_Cells_to_be_Activated_List_Item_t *cell = - &cells_to_be_activated_list_item_ies->value.choice.Cells_to_be_Activated_List_Item; - TBCD_TO_MCC_MNC(&cell->nRCGI.pLMN_Identity, - resp.cells_to_activate[i].plmn.mcc, - resp.cells_to_activate[i].plmn.mnc, - resp.cells_to_activate[i].plmn.mnc_digit_length); - LOG_D(F1AP, "nr_cellId : %x %x %x %x %x\n", - cell->nRCGI.nRCellIdentity.buf[0], - cell->nRCGI.nRCellIdentity.buf[1], - cell->nRCGI.nRCellIdentity.buf[2], - cell->nRCGI.nRCellIdentity.buf[3], - cell->nRCGI.nRCellIdentity.buf[4]); - BIT_STRING_TO_NR_CELL_IDENTITY(&cell->nRCGI.nRCellIdentity, resp.cells_to_activate[i].nr_cellid); - if (cell->nRPCI != NULL) - resp.cells_to_activate[i].nrpci = *cell->nRPCI; - F1AP_ProtocolExtensionContainer_10696P112_t *ext = (F1AP_ProtocolExtensionContainer_10696P112_t *)cell->iE_Extensions; - - if (ext==NULL) - continue; - - for (int cnt=0; cntlist.count; cnt++) { - F1AP_Cells_to_be_Activated_List_ItemExtIEs_t *cells_to_be_activated_list_itemExtIEs=(F1AP_Cells_to_be_Activated_List_ItemExtIEs_t *)ext->list.array[cnt]; - - switch (cells_to_be_activated_list_itemExtIEs->id) { - /* - case F1AP_Cells_to_be_Activated_List_ItemExtIEs__extensionValue_PR_NOTHING: - case F1AP_Cells_to_be_Activated_List_ItemExtIEs__extensionValue_PR_GNB_CUSystemInformation, - case F1AP_Cells_to_be_Activated_List_ItemExtIEs__extensionValue_PR_AvailablePLMNList, - case F1AP_Cells_to_be_Activated_List_ItemExtIEs__extensionValue_PR_ExtendedAvailablePLMN_List, - case F1AP_Cells_to_be_Activated_List_ItemExtIEs__extensionValue_PR_IAB_Info_IAB_donor_CU, - case F1AP_Cells_to_be_Activated_List_ItemExtIEs__extensionValue_PR_AvailableSNPN_ID_List - */ - case F1AP_ProtocolIE_ID_id_gNB_CUSystemInformation: { - resp.cells_to_activate[i].nrpci = (cell->nRPCI != NULL) ? *cell->nRPCI : 0; - F1AP_GNB_CUSystemInformation_t *gNB_CUSystemInformation = (F1AP_GNB_CUSystemInformation_t *)&cells_to_be_activated_list_itemExtIEs->extensionValue.choice.GNB_CUSystemInformation; - resp.cells_to_activate[i].num_SI = gNB_CUSystemInformation->sibtypetobeupdatedlist.list.count; - AssertFatal(ext->list.count==1,"At least one SI message should be there, and only 1 for now!\n"); - LOG_D(F1AP, - "F1AP: Cell %d MCC %d MNC %d NRCellid %lx num_si %d\n", - i, - resp.cells_to_activate[i].plmn.mcc, - resp.cells_to_activate[i].plmn.mnc, - resp.cells_to_activate[i].nr_cellid, - resp.cells_to_activate[i].num_SI); - for (int s = 0; s < resp.cells_to_activate[i].num_SI; s++) { - F1AP_SibtypetobeupdatedListItem_t *sib_item = gNB_CUSystemInformation->sibtypetobeupdatedlist.list.array[s]; - f1ap_sib_msg_t *SI_msg = &resp.cells_to_activate[i].SI_msg[s]; - SI_msg->SI_container = calloc(sib_item->sIBmessage.size, sizeof(uint8_t)); - AssertFatal(SI_msg->SI_container != NULL, "out of memory\n"); - memcpy(SI_msg->SI_container, sib_item->sIBmessage.buf, sib_item->sIBmessage.size); - SI_msg->SI_container_length = sib_item->sIBmessage.size; - SI_msg->SI_type = sib_item->sIBtype; - LOG_D(F1AP, "F1AP: SI_container_length[%d][%ld] %ld bytes\n", i, sib_item->sIBtype, sib_item->sIBmessage.size); - } - - break; - } - - case F1AP_ProtocolIE_ID_id_AvailablePLMNList: - AssertFatal(1==0,"F1AP_ProtocolIE_ID_id_AvailablePLMNList not supported yet\n"); - break; - - case F1AP_ProtocolIE_ID_id_ExtendedAvailablePLMN_List: - AssertFatal(1==0,"F1AP_ProtocolIE_ID_id_AvailablePLMNList not supported yet\n"); - break; - - case F1AP_ProtocolIE_ID_id_IAB_Info_IAB_donor_CU: - AssertFatal(1==0,"F1AP_ProtocolIE_ID_id_AvailablePLMNList not supported yet\n"); - break; - - case F1AP_ProtocolIE_ID_id_AvailableSNPN_ID_List: - AssertFatal(1==0,"F1AP_ProtocolIE_ID_id_AvailablePLMNList not supported yet\n"); - break; - - default: - AssertFatal(1==0,"F1AP_ProtocolIE_ID_id %d unknown\n",(int)cells_to_be_activated_list_itemExtIEs->id); - break; - } - } // for (cnt=... - } // for (cells_to_activate... - - break; - } // case F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List - - default: - AssertFatal(1==0,"F1AP_ProtocolIE_ID_id %d unknown\n", (int)ie->id); - break; - } // switch ie - } // for IE - - AssertFatal(TransactionId!=-1,"TransactionId was not sent\n"); - LOG_D(F1AP,"F1AP: num_cells_to_activate %d\n",num_cells_to_activate); - resp.num_cells_to_activate = num_cells_to_activate; - - // tmp - for (int i=0; if1_config.setup_resp = malloc(sizeof(*mac->f1_config.setup_resp)); AssertFatal(mac->f1_config.setup_resp != NULL, "out of memory\n"); - *mac->f1_config.setup_resp = *resp; - if (resp->gNB_CU_name) - mac->f1_config.setup_resp->gNB_CU_name = strdup(resp->gNB_CU_name); - + // Copy F1AP message + *mac->f1_config.setup_resp = cp_f1ap_setup_response(resp); + // free F1AP message after copy + free_f1ap_setup_response(resp); NR_SCHED_UNLOCK(&mac->sched_lock); // NOTE: Before accepting any UEs, we should initialize the UE states. diff --git a/openair2/RRC/NR/mac_rrc_dl_f1ap.c b/openair2/RRC/NR/mac_rrc_dl_f1ap.c index 9f1b8b4b53..e2e094d866 100644 --- a/openair2/RRC/NR/mac_rrc_dl_f1ap.c +++ b/openair2/RRC/NR/mac_rrc_dl_f1ap.c @@ -24,6 +24,7 @@ #include "mac_rrc_dl.h" #include "nr_rrc_defs.h" #include "openair2/F1AP/lib/f1ap_rrc_message_transfer.h" +#include "openair2/F1AP/lib/f1ap_interface_management.h" static void f1_reset_cu_initiated_f1ap(sctp_assoc_t assoc_id, const f1ap_reset_t *reset) { @@ -45,6 +46,7 @@ static void f1_setup_response_f1ap(sctp_assoc_t assoc_id, const f1ap_setup_resp_ *f1ap_msg = *resp; if (resp->gNB_CU_name != NULL) f1ap_msg->gNB_CU_name = strdup(resp->gNB_CU_name); + free_f1ap_setup_response(resp); itti_send_msg_to_task(TASK_CU_F1, 0, msg); } From 28e2d67ee5dfc5c04cacefd0d27f47107e974b42 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Tue, 28 May 2024 10:25:59 +0200 Subject: [PATCH 26/46] Fixes to F1 Setup Failure * added missing Transaction ID to te F1 Setup Failure message struct * fill F1 Setup Failure transaction ID in RRC before calling the F1 Setup Failure function --- openair2/COMMON/f1ap_messages_types.h | 4 +++- openair2/RRC/NR/rrc_gNB_du.c | 13 ++++++++----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index 2224cf822f..f46fe3b55b 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -233,7 +233,9 @@ typedef struct f1ap_gnb_cu_configuration_update_s { typedef struct f1ap_setup_failure_s { uint16_t cause; uint16_t time_to_wait; - uint16_t criticality_diagnostics; + uint16_t criticality_diagnostics; + /// Transaction ID (M) + uint64_t transaction_id; } f1ap_setup_failure_t; typedef struct f1ap_gnb_cu_configuration_update_acknowledge_s { diff --git a/openair2/RRC/NR/rrc_gNB_du.c b/openair2/RRC/NR/rrc_gNB_du.c index d9fe4ef416..1322c52141 100644 --- a/openair2/RRC/NR/rrc_gNB_du.c +++ b/openair2/RRC/NR/rrc_gNB_du.c @@ -262,6 +262,9 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id) DevAssert(rrc); LOG_I(NR_RRC, "Received F1 Setup Request from gNB_DU %lu (%s) on assoc_id %d\n", req->gNB_DU_id, req->gNB_DU_name, assoc_id); + // pre-fill F1 Setup Failure message + f1ap_setup_failure_t fail = {.transaction_id = F1AP_get_next_transaction_identifier(0, 0)}; + // check: // - it is one cell // - PLMN and Cell ID matches @@ -269,7 +272,7 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id) // else reject if (req->num_cells_available != 1) { LOG_E(NR_RRC, "can only handle on DU cell, but gNB_DU %ld has %d\n", req->gNB_DU_id, req->num_cells_available); - f1ap_setup_failure_t fail = {.cause = F1AP_CauseRadioNetwork_gNB_CU_Cell_Capacity_Exceeded}; + fail.cause = F1AP_CauseRadioNetwork_gNB_CU_Cell_Capacity_Exceeded; rrc->mac_rrc.f1_setup_failure(assoc_id, &fail); return; } @@ -283,7 +286,7 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id) cell_info->plmn.mcc, cell_info->plmn.mnc_digit_length, cell_info->plmn.mnc); - f1ap_setup_failure_t fail = {.cause = F1AP_CauseRadioNetwork_plmn_not_served_by_the_gNB_CU}; + fail.cause = F1AP_CauseRadioNetwork_plmn_not_served_by_the_gNB_CU; rrc->mac_rrc.f1_setup_failure(assoc_id, &fail); return; } @@ -295,7 +298,7 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id) it->setup_req->gNB_DU_name, it->assoc_id, it->setup_req->gNB_DU_id); - f1ap_setup_failure_t fail = {.cause = F1AP_CauseMisc_unspecified}; + fail.cause = F1AP_CauseMisc_unspecified; rrc->mac_rrc.f1_setup_failure(assoc_id, &fail); return; } @@ -312,7 +315,7 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id) exist_info->nr_pci, new_info->nr_cellid, new_info->nr_pci); - f1ap_setup_failure_t fail = {.cause = F1AP_CauseMisc_unspecified}; + fail.cause = F1AP_CauseMisc_unspecified; rrc->mac_rrc.f1_setup_failure(assoc_id, &fail); return; } @@ -339,7 +342,7 @@ void rrc_gNB_process_f1_setup_req(f1ap_setup_req_t *req, sctp_assoc_t assoc_id) if (sys_info != NULL && sys_info->mib != NULL && !(sys_info->sib1 == NULL && get_softmodem_params()->sa)) { if (!extract_sys_info(sys_info, &mib, &sib1)) { LOG_W(RRC, "rejecting DU ID %ld\n", req->gNB_DU_id); - f1ap_setup_failure_t fail = {.cause = F1AP_CauseProtocol_semantic_error}; + fail.cause = F1AP_CauseProtocol_semantic_error; rrc->mac_rrc.f1_setup_failure(assoc_id, &fail); ASN_STRUCT_FREE(asn_DEF_NR_MeasurementTimingConfiguration, mtc); return; From 7e495db5ec03df79529a91e3f0b33a2d09a77588 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Tue, 28 May 2024 10:27:19 +0200 Subject: [PATCH 27/46] Add encoding/decoding lib for F1 Setup Failure (interface management) --- openair2/F1AP/lib/f1ap_interface_management.c | 114 ++++++++++++++++++ openair2/F1AP/lib/f1ap_interface_management.h | 6 + openair2/F1AP/lib/f1ap_lib_includes.h | 1 + 3 files changed, 121 insertions(+) diff --git a/openair2/F1AP/lib/f1ap_interface_management.c b/openair2/F1AP/lib/f1ap_interface_management.c index 674bae84de..544b89893b 100644 --- a/openair2/F1AP/lib/f1ap_interface_management.c +++ b/openair2/F1AP/lib/f1ap_interface_management.c @@ -856,3 +856,117 @@ void free_f1ap_setup_response(const f1ap_setup_resp_t *msg) if (msg->cells_to_activate[i].SI_msg[j].SI_container_length > 0) free(msg->cells_to_activate[i].SI_msg[j].SI_container); } + +/* ==================================== + * F1AP Setup Failure + * ==================================== */ + +/** + * @brief F1AP Setup Failure encoding + */ +F1AP_F1AP_PDU_t *encode_f1ap_setup_failure(const f1ap_setup_failure_t *msg) +{ + F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + /* Create */ + /* 0. Message Type */ + asn1cCalloc(pdu->choice.unsuccessfulOutcome, UnsuccessfulOutcome); + pdu->present = F1AP_F1AP_PDU_PR_unsuccessfulOutcome; + UnsuccessfulOutcome->procedureCode = F1AP_ProcedureCode_id_F1Setup; + UnsuccessfulOutcome->criticality = F1AP_Criticality_reject; + UnsuccessfulOutcome->value.present = F1AP_UnsuccessfulOutcome__value_PR_F1SetupFailure; + F1AP_F1SetupFailure_t *out = &pdu->choice.unsuccessfulOutcome->value.choice.F1SetupFailure; + /* mandatory */ + /* c1. Transaction ID (integer value)*/ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_F1SetupFailureIEs_t, ie1); + ie1->id = F1AP_ProtocolIE_ID_id_TransactionID; + ie1->criticality = F1AP_Criticality_reject; + ie1->value.present = F1AP_F1SetupFailureIEs__value_PR_TransactionID; + ie1->value.choice.TransactionID = msg->transaction_id; + /* mandatory */ + /* c2. Cause */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_F1SetupFailureIEs_t, ie2); + ie2->id = F1AP_ProtocolIE_ID_id_Cause; + ie2->criticality = F1AP_Criticality_ignore; + ie2->value.present = F1AP_F1SetupFailureIEs__value_PR_Cause; + ie2->value.choice.Cause.present = F1AP_Cause_PR_radioNetwork; + ie2->value.choice.Cause.choice.radioNetwork = msg->cause; + /* optional */ + /* c3. TimeToWait */ + if (msg->time_to_wait > 0) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_F1SetupFailureIEs_t, ie3); + ie3->id = F1AP_ProtocolIE_ID_id_TimeToWait; + ie3->criticality = F1AP_Criticality_ignore; + ie3->value.present = F1AP_F1SetupFailureIEs__value_PR_TimeToWait; + ie3->value.choice.TimeToWait = F1AP_TimeToWait_v10s; + } + /* optional */ + /* c4. CriticalityDiagnostics*/ + if (msg->criticality_diagnostics) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_F1SetupFailureIEs_t, ie4); + ie4->id = F1AP_ProtocolIE_ID_id_CriticalityDiagnostics; + ie4->criticality = F1AP_Criticality_ignore; + ie4->value.present = F1AP_F1SetupFailureIEs__value_PR_CriticalityDiagnostics; + asn1cCallocOne(ie4->value.choice.CriticalityDiagnostics.procedureCode, F1AP_ProcedureCode_id_UEContextSetup); + asn1cCallocOne(ie4->value.choice.CriticalityDiagnostics.triggeringMessage, F1AP_TriggeringMessage_initiating_message); + asn1cCallocOne(ie4->value.choice.CriticalityDiagnostics.procedureCriticality, F1AP_Criticality_reject); + asn1cCallocOne(ie4->value.choice.CriticalityDiagnostics.transactionID, 0); + } + return pdu; +} + +/** + * @brief F1AP Setup Failure decoding + */ +bool decode_f1ap_setup_failure(const F1AP_F1AP_PDU_t *pdu, f1ap_setup_failure_t *out) +{ + F1AP_F1SetupFailureIEs_t *ie; + F1AP_F1SetupFailure_t *in = &pdu->choice.unsuccessfulOutcome->value.choice.F1SetupFailure; + /* Check presence of mandatory IEs */ + F1AP_LIB_FIND_IE(F1AP_F1SetupFailureIEs_t, ie, in, F1AP_ProtocolIE_ID_id_TransactionID, true); + F1AP_LIB_FIND_IE(F1AP_F1SetupFailureIEs_t, ie, in, F1AP_ProtocolIE_ID_id_Cause, true); + /* Loop over all IEs */ + for (int i = 0; i < in->protocolIEs.list.count; i++) { + ie = in->protocolIEs.list.array[i]; + switch (ie->id) { + case F1AP_ProtocolIE_ID_id_TransactionID: + /* Transaction ID (M) */ + out->transaction_id = ie->value.choice.TransactionID; + break; + case F1AP_ProtocolIE_ID_id_Cause: + /* Cause (M) */ + out->cause = ie->value.choice.Cause.choice.radioNetwork; + break; + case F1AP_ProtocolIE_ID_id_TimeToWait: + out->time_to_wait = ie->value.choice.TimeToWait; + break; + case F1AP_ProtocolIE_ID_id_CriticalityDiagnostics: + AssertError(1 == 0, return false, "F1AP_ProtocolIE_ID_id_CriticalityDiagnostics is not supported"); + break; + default: + AssertError(1 == 0, return false, "F1AP_ProtocolIE_ID_id %ld unknown\n", ie->id); + break; + } + } + return true; +} + +/** + * @brief F1AP Setup Failure equality check + */ +bool eq_f1ap_setup_failure(const f1ap_setup_failure_t *a, const f1ap_setup_failure_t *b) +{ + if (a->transaction_id != b->transaction_id) + return false; + return true; +} + +/** + * @brief F1AP Setup Failure deep copy + */ +f1ap_setup_failure_t cp_f1ap_setup_failure(const f1ap_setup_failure_t *msg) +{ + f1ap_setup_failure_t cp = {0}; + /* transaction_id */ + cp.transaction_id = msg->transaction_id; + return cp; +} diff --git a/openair2/F1AP/lib/f1ap_interface_management.h b/openair2/F1AP/lib/f1ap_interface_management.h index 33a5f8402b..ca0b7df491 100644 --- a/openair2/F1AP/lib/f1ap_interface_management.h +++ b/openair2/F1AP/lib/f1ap_interface_management.h @@ -40,4 +40,10 @@ void free_f1ap_setup_response(const f1ap_setup_resp_t *msg); f1ap_setup_resp_t cp_f1ap_setup_response(const f1ap_setup_resp_t *msg); bool eq_f1ap_setup_response(const f1ap_setup_resp_t *a, const f1ap_setup_resp_t *b); +/* F1 Setup Failure */ +struct F1AP_F1AP_PDU *encode_f1ap_setup_failure(const f1ap_setup_failure_t *msg); +bool decode_f1ap_setup_failure(const struct F1AP_F1AP_PDU *pdu, f1ap_setup_failure_t *out); +bool eq_f1ap_setup_failure(const f1ap_setup_failure_t *a, const f1ap_setup_failure_t *b); +f1ap_setup_failure_t cp_f1ap_setup_failure(const f1ap_setup_failure_t *msg); + #endif /* F1AP_INTERFACE_MANAGEMENT_H_ */ diff --git a/openair2/F1AP/lib/f1ap_lib_includes.h b/openair2/F1AP/lib/f1ap_lib_includes.h index 2386073dee..6ff60a4897 100644 --- a/openair2/F1AP/lib/f1ap_lib_includes.h +++ b/openair2/F1AP/lib/f1ap_lib_includes.h @@ -39,5 +39,6 @@ #include "F1AP_FreqBandNrItem.h" #include "F1AP_SuccessfulOutcome.h" #include "F1AP_SibtypetobeupdatedListItem.h" +#include "F1AP_UnsuccessfulOutcome.h" #endif /* F1AP_LIB_INCLUDES_H_ */ From 6146c470e233e49eb8453bfb61e9643ed37667ee Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Tue, 28 May 2024 10:30:49 +0200 Subject: [PATCH 28/46] Add test for F1AP Setup Failure enc/dec lib --- openair2/F1AP/tests/f1ap_lib_test.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/openair2/F1AP/tests/f1ap_lib_test.c b/openair2/F1AP/tests/f1ap_lib_test.c index 16c404b722..42f07e4c2a 100644 --- a/openair2/F1AP/tests/f1ap_lib_test.c +++ b/openair2/F1AP/tests/f1ap_lib_test.c @@ -330,6 +330,33 @@ static void test_f1ap_setup_response(void) free_f1ap_setup_response(&orig); } +/** + * @brief Test F1AP Setup Failure Encoding/Decoding + */ +static void test_f1ap_setup_failure(void) +{ + /* create message */ + f1ap_setup_failure_t orig = { + .transaction_id = 2, + .cause = 4, + }; + F1AP_F1AP_PDU_t *f1enc = encode_f1ap_setup_failure(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_setup_failure_t decoded = {0}; + bool ret = decode_f1ap_setup_failure(f1dec, &decoded); + AssertFatal(ret, "decode_f1ap_setup_failure(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_f1ap_setup_failure(&orig, &decoded); + AssertFatal(ret, "eq_f1ap_setup_failure(): decoded message doesn't match\n"); + + f1ap_setup_failure_t cp = cp_f1ap_setup_failure(&orig); + ret = eq_f1ap_setup_failure(&orig, &cp); + AssertFatal(ret, "eq_f1ap_setup_failure(): copied message doesn't match\n"); +} + int main() { test_initial_ul_rrc_message_transfer(); @@ -337,5 +364,6 @@ int main() test_ul_rrc_message_transfer(); test_f1ap_setup_request(); test_f1ap_setup_response(); + test_f1ap_setup_failure(); return 0; } From 289fdfe3814b70fc486c75e1daac105a0c304ccd Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Thu, 29 Aug 2024 23:52:00 +0200 Subject: [PATCH 29/46] Use F1AP Setup Failure enc/dec lib in stack --- openair2/F1AP/f1ap_cu_interface_management.c | 68 +++----------------- openair2/F1AP/f1ap_du_interface_management.c | 23 ++----- 2 files changed, 17 insertions(+), 74 deletions(-) diff --git a/openair2/F1AP/f1ap_cu_interface_management.c b/openair2/F1AP/f1ap_cu_interface_management.c index c3a9f39d7d..49f887ad49 100644 --- a/openair2/F1AP/f1ap_cu_interface_management.c +++ b/openair2/F1AP/f1ap_cu_interface_management.c @@ -126,70 +126,22 @@ int CU_send_F1_SETUP_RESPONSE(sctp_assoc_t assoc_id, f1ap_setup_resp_t *f1ap_set return 0; } +/** + * @brief F1 Setup Failure encoding and transmission + */ int CU_send_F1_SETUP_FAILURE(sctp_assoc_t assoc_id, const f1ap_setup_failure_t *fail) { LOG_D(F1AP, "CU_send_F1_SETUP_FAILURE\n"); - F1AP_F1AP_PDU_t pdu= {0}; - uint8_t *buffer=NULL; - uint32_t len=0; - /* Create */ - /* 0. Message Type */ - asn1cCalloc(pdu.choice.unsuccessfulOutcome, UnsuccessfulOutcome); - pdu.present = F1AP_F1AP_PDU_PR_unsuccessfulOutcome; - UnsuccessfulOutcome->procedureCode = F1AP_ProcedureCode_id_F1Setup; - UnsuccessfulOutcome->criticality = F1AP_Criticality_reject; - UnsuccessfulOutcome->value.present = F1AP_UnsuccessfulOutcome__value_PR_F1SetupFailure; - F1AP_F1SetupFailure_t *out = &pdu.choice.unsuccessfulOutcome->value.choice.F1SetupFailure; - /* mandatory */ - /* c1. Transaction ID (integer value)*/ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_F1SetupFailureIEs_t, ie1); - ie1->id = F1AP_ProtocolIE_ID_id_TransactionID; - ie1->criticality = F1AP_Criticality_reject; - ie1->value.present = F1AP_F1SetupFailureIEs__value_PR_TransactionID; - ie1->value.choice.TransactionID = F1AP_get_next_transaction_identifier(0, 0); - /* mandatory */ - /* c2. Cause */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_F1SetupFailureIEs_t, ie2); - ie2->id = F1AP_ProtocolIE_ID_id_Cause; - ie2->criticality = F1AP_Criticality_ignore; - ie2->value.present = F1AP_F1SetupFailureIEs__value_PR_Cause; - ie2->value.choice.Cause.present = F1AP_Cause_PR_radioNetwork; - ie2->value.choice.Cause.choice.radioNetwork = F1AP_CauseRadioNetwork_unspecified; - - /* optional */ - /* c3. TimeToWait */ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_F1SetupFailureIEs_t, ie3); - ie3->id = F1AP_ProtocolIE_ID_id_TimeToWait; - ie3->criticality = F1AP_Criticality_ignore; - ie3->value.present = F1AP_F1SetupFailureIEs__value_PR_TimeToWait; - ie3->value.choice.TimeToWait = F1AP_TimeToWait_v10s; - } - - /* optional */ - /* c4. CriticalityDiagnostics*/ - if (0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_F1SetupFailureIEs_t, ie4); - ie4->id = F1AP_ProtocolIE_ID_id_CriticalityDiagnostics; - ie4->criticality = F1AP_Criticality_ignore; - ie4->value.present = F1AP_F1SetupFailureIEs__value_PR_CriticalityDiagnostics; - asn1cCallocOne(ie4->value.choice.CriticalityDiagnostics.procedureCode, - F1AP_ProcedureCode_id_UEContextSetup); - asn1cCallocOne(ie4->value.choice.CriticalityDiagnostics.triggeringMessage, - F1AP_TriggeringMessage_initiating_message); - asn1cCallocOne(ie4->value.choice.CriticalityDiagnostics.procedureCriticality, - F1AP_Criticality_reject); - asn1cCallocOne(ie4->value.choice.CriticalityDiagnostics.transactionID, - 0); - } - - /* encode */ - if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { + uint8_t *buffer = NULL; + uint32_t len = 0; + /* Encode F1 Setup Failure */ + F1AP_F1AP_PDU_t *pdu = encode_f1ap_setup_failure(fail); + if (f1ap_encode_pdu(pdu, &buffer, &len) < 0) { LOG_E(F1AP, "Failed to encode F1 setup failure\n"); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); return -1; } - - ASN_STRUCT_RESET(asn_DEF_F1AP_F1AP_PDU, &pdu); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); return 0; } diff --git a/openair2/F1AP/f1ap_du_interface_management.c b/openair2/F1AP/f1ap_du_interface_management.c index 5d1f44dbdc..62da719aa0 100644 --- a/openair2/F1AP/f1ap_du_interface_management.c +++ b/openair2/F1AP/f1ap_du_interface_management.c @@ -337,25 +337,16 @@ int DU_handle_F1_SETUP_RESPONSE(instance_t instance, sctp_assoc_t assoc_id, uint return 0; } -// SETUP FAILURE +/** + * @brief F1 Setup Failure handler (DU) + */ int DU_handle_F1_SETUP_FAILURE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { - F1AP_F1SetupFailure_t *out; - F1AP_F1SetupFailureIEs_t *ie; - f1ap_setup_failure_t fail = {0}; - out = &pdu->choice.unsuccessfulOutcome->value.choice.F1SetupFailure; - /* Transaction ID */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_F1SetupFailureIEs_t, ie, out, F1AP_ProtocolIE_ID_id_TransactionID, true); - /* Cause */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_F1SetupFailureIEs_t, ie, out, - F1AP_ProtocolIE_ID_id_Cause, true); - - if(0) { - /* TimeToWait */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_F1SetupFailureIEs_t, ie, out, - F1AP_ProtocolIE_ID_id_TimeToWait, true); + f1ap_setup_failure_t fail; + if (!decode_f1ap_setup_failure(pdu, &fail)) { + LOG_E(F1AP, "Failed to decode F1AP Setup Failure\n"); + return -1; } - f1_setup_failure(&fail); return 0; } From df62abca0c5f8b669edb0ab50d2af9adbaaa204b Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 28 Aug 2024 23:43:10 +0200 Subject: [PATCH 30/46] Removed gNB_CU_name from f1ap_gnb_du_configuration_update_t * not defined in 9.2.1.8 of 3GPP TS 38.473 --- openair2/COMMON/f1ap_messages_types.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index f46fe3b55b..95ff676307 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -300,8 +300,6 @@ typedef struct f1ap_gnb_du_configuration_update_s { typedef struct f1ap_gnb_du_configuration_update_acknowledge_s { /// ulong transaction id uint64_t transaction_id; - /// string holding gNB_CU_name - char *gNB_CU_name; /// number of DU cells to activate uint16_t num_cells_to_activate; // 0< num_cells_to_activate <= 512; served_cells_to_activate_t cells_to_activate[F1AP_MAX_NB_CELLS]; From 9958e53cb17c1d8029e71a82d5689a4054f9195c Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 9 Aug 2024 12:33:29 +0200 Subject: [PATCH 31/46] Add encoding/decoding library for F1AP gNB-DU Configuration Update (Interface Management) --- openair2/F1AP/lib/f1ap_interface_management.c | 321 ++++++++++++++++++ openair2/F1AP/lib/f1ap_interface_management.h | 7 + 2 files changed, 328 insertions(+) diff --git a/openair2/F1AP/lib/f1ap_interface_management.c b/openair2/F1AP/lib/f1ap_interface_management.c index 544b89893b..667fba31be 100644 --- a/openair2/F1AP/lib/f1ap_interface_management.c +++ b/openair2/F1AP/lib/f1ap_interface_management.c @@ -970,3 +970,324 @@ f1ap_setup_failure_t cp_f1ap_setup_failure(const f1ap_setup_failure_t *msg) cp.transaction_id = msg->transaction_id; return cp; } + +/* ==================================== + * F1AP gNB-DU Configuration Update + * ==================================== */ + +/** + * @brief F1 gNB-DU Configuration Update encoding (9.2.1.7 of 3GPP TS 38.473) + */ +F1AP_F1AP_PDU_t *encode_f1ap_du_configuration_update(const f1ap_gnb_du_configuration_update_t *msg) +{ + F1AP_F1AP_PDU_t *pdu = calloc(1, sizeof(*pdu)); + AssertFatal(pdu != NULL, "out of memory\n"); + /* Create */ + /* 0. Message Type */ + pdu->present = F1AP_F1AP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu->choice.initiatingMessage, initMsg); + initMsg->procedureCode = F1AP_ProcedureCode_id_gNBDUConfigurationUpdate; + initMsg->criticality = F1AP_Criticality_reject; + initMsg->value.present = F1AP_InitiatingMessage__value_PR_GNBDUConfigurationUpdate; + F1AP_GNBDUConfigurationUpdate_t *out = &initMsg->value.choice.GNBDUConfigurationUpdate; + /* mandatory */ + /* c1. Transaction ID (integer value) */ + asn1cSequenceAdd(out->protocolIEs.list, F1AP_GNBDUConfigurationUpdateIEs_t, ie1); + ie1->id = F1AP_ProtocolIE_ID_id_TransactionID; + ie1->criticality = F1AP_Criticality_reject; + ie1->value.present = F1AP_GNBDUConfigurationUpdateIEs__value_PR_TransactionID; + ie1->value.choice.TransactionID = msg->transaction_id; + /* mandatory */ + /* c2. Served_Cells_To_Add */ + if (msg->num_cells_to_add > 0) { + AssertFatal(false, "code for adding cells not tested\n"); + asn1cSequenceAdd(out->protocolIEs.list, F1AP_GNBDUConfigurationUpdateIEs_t, ie2); + ie2->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Add_List; + ie2->criticality = F1AP_Criticality_reject; + ie2->value.present = F1AP_GNBDUConfigurationUpdateIEs__value_PR_Served_Cells_To_Add_List; + + for (int j = 0; j < msg->num_cells_to_add; j++) { + const f1ap_served_cell_info_t *cell = &msg->cell_to_add[j].info; + const f1ap_gnb_du_system_info_t *sys_info = msg->cell_to_add[j].sys_info; + asn1cSequenceAdd(ie2->value.choice.Served_Cells_To_Add_List.list, + F1AP_Served_Cells_To_Add_ItemIEs_t, + served_cells_to_add_item_ies); + served_cells_to_add_item_ies->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Add_Item; + served_cells_to_add_item_ies->criticality = F1AP_Criticality_reject; + served_cells_to_add_item_ies->value.present = F1AP_Served_Cells_To_Add_ItemIEs__value_PR_Served_Cells_To_Add_Item; + F1AP_Served_Cells_To_Add_Item_t *served_cells_to_add_item = + &served_cells_to_add_item_ies->value.choice.Served_Cells_To_Add_Item; + served_cells_to_add_item->served_Cell_Information = encode_served_cell_info(cell); + served_cells_to_add_item->gNB_DU_System_Information = encode_system_info(sys_info); + } + } + + /* mandatory */ + /* c3. Served_Cells_To_Modify */ + if (msg->num_cells_to_modify > 0) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_GNBDUConfigurationUpdateIEs_t, ie3); + ie3->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Modify_List; + ie3->criticality = F1AP_Criticality_reject; + ie3->value.present = F1AP_GNBDUConfigurationUpdateIEs__value_PR_Served_Cells_To_Modify_List; + for (int i = 0; i < msg->num_cells_to_modify; i++) { + const f1ap_served_cell_info_t *cell = &msg->cell_to_modify[i].info; + const f1ap_gnb_du_system_info_t *sys_info = msg->cell_to_modify[i].sys_info; + asn1cSequenceAdd(ie3->value.choice.Served_Cells_To_Modify_List.list, + F1AP_Served_Cells_To_Modify_ItemIEs_t, + served_cells_to_modify_item_ies); + served_cells_to_modify_item_ies->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Modify_Item; + served_cells_to_modify_item_ies->criticality = F1AP_Criticality_reject; + served_cells_to_modify_item_ies->value.present = F1AP_Served_Cells_To_Modify_ItemIEs__value_PR_Served_Cells_To_Modify_Item; + F1AP_Served_Cells_To_Modify_Item_t *served_cells_to_modify_item = + &served_cells_to_modify_item_ies->value.choice.Served_Cells_To_Modify_Item; + + F1AP_NRCGI_t *oldNRCGI = &served_cells_to_modify_item->oldNRCGI; + const f1ap_plmn_t *old_plmn = &msg->cell_to_modify[i].old_plmn; + MCC_MNC_TO_PLMNID(old_plmn->mcc, old_plmn->mnc, old_plmn->mnc_digit_length, &oldNRCGI->pLMN_Identity); + NR_CELL_ID_TO_BIT_STRING(msg->cell_to_modify[i].old_nr_cellid, &oldNRCGI->nRCellIdentity); + + served_cells_to_modify_item->served_Cell_Information = encode_served_cell_info(cell); + served_cells_to_modify_item->gNB_DU_System_Information = encode_system_info(sys_info); + } + } + + /* mandatory */ + /* c4. Served_Cells_To_Delete */ + if (msg->num_cells_to_delete > 0) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_GNBDUConfigurationUpdateIEs_t, ie4); + ie4->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Delete_List; + ie4->criticality = F1AP_Criticality_reject; + ie4->value.present = F1AP_GNBDUConfigurationUpdateIEs__value_PR_Served_Cells_To_Delete_List; + AssertFatal(msg->num_cells_to_delete == 0, "code for deleting cells not tested\n"); + for (int i = 0; i < msg->num_cells_to_delete; i++) { + asn1cSequenceAdd(ie4->value.choice.Served_Cells_To_Delete_List.list, + F1AP_Served_Cells_To_Delete_ItemIEs_t, + served_cells_to_delete_item_ies); + served_cells_to_delete_item_ies->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Delete_Item; + served_cells_to_delete_item_ies->criticality = F1AP_Criticality_reject; + served_cells_to_delete_item_ies->value.present = F1AP_Served_Cells_To_Delete_ItemIEs__value_PR_Served_Cells_To_Delete_Item; + F1AP_Served_Cells_To_Delete_Item_t *served_cells_to_delete_item = + &served_cells_to_delete_item_ies->value.choice.Served_Cells_To_Delete_Item; + F1AP_NRCGI_t *oldNRCGI = &served_cells_to_delete_item->oldNRCGI; + const f1ap_plmn_t *plmn = &msg->cell_to_delete[i].plmn; + MCC_MNC_TO_PLMNID(plmn->mcc, plmn->mnc, plmn->mnc_digit_length, &(oldNRCGI->pLMN_Identity)); + NR_CELL_ID_TO_BIT_STRING(msg->cell_to_delete[i].nr_cellid, &(oldNRCGI->nRCellIdentity)); + } + } + + /* optional */ + /* c5. GNB_DU_ID (integer value) */ + if (msg->gNB_DU_ID != NULL) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_GNBDUConfigurationUpdateIEs_t, ie5); + ie5->id = F1AP_ProtocolIE_ID_id_gNB_DU_ID; + ie5->criticality = F1AP_Criticality_reject; + ie5->value.present = F1AP_GNBDUConfigurationUpdateIEs__value_PR_GNB_DU_ID; + asn_int642INTEGER(&ie5->value.choice.GNB_DU_ID, *msg->gNB_DU_ID); + } + + return pdu; +} + +/** + * @brief F1 gNB-DU Configuration Update decoding (9.2.1.7 of 3GPP TS 38.473) + */ +bool decode_f1ap_du_configuration_update(const F1AP_F1AP_PDU_t *pdu, f1ap_gnb_du_configuration_update_t *out) +{ + /* Check presence of message type */ + _F1_EQ_CHECK_INT(pdu->present, F1AP_F1AP_PDU_PR_initiatingMessage); + _F1_EQ_CHECK_LONG(pdu->choice.initiatingMessage->procedureCode, F1AP_ProcedureCode_id_gNBDUConfigurationUpdate); + _F1_EQ_CHECK_INT(pdu->choice.initiatingMessage->value.present, F1AP_InitiatingMessage__value_PR_GNBDUConfigurationUpdate); + /* Check presence of mandatory IEs */ + F1AP_GNBDUConfigurationUpdate_t *in = &pdu->choice.initiatingMessage->value.choice.GNBDUConfigurationUpdate; + F1AP_GNBDUConfigurationUpdateIEs_t *ie; + /* Check mandatory IEs */ + F1AP_LIB_FIND_IE(F1AP_GNBDUConfigurationUpdateIEs_t, ie, in, F1AP_ProtocolIE_ID_id_TransactionID, true); + /* Loop over all IEs */ + for (int i = 0; i < in->protocolIEs.list.count; i++) { + AssertError(in->protocolIEs.list.array[i] != NULL, return false, "in->protocolIEs.list.array[i] is NULL"); + ie = in->protocolIEs.list.array[i]; + switch (ie->id) { + case F1AP_ProtocolIE_ID_id_TransactionID: { + out->transaction_id = ie->value.choice.TransactionID; + } break; + case F1AP_ProtocolIE_ID_id_Served_Cells_To_Add_List: { + /* Served Cells To Add List */ + AssertError(out->num_cells_to_add > 0, return false, "at least 1 cell to add shall to be present"); + out->num_cells_to_add = ie->value.choice.Served_Cells_To_Add_List.list.count; + for (int i = 0; i < out->num_cells_to_add; i++) { + F1AP_Served_Cells_To_Add_Item_t *served_cells_item = + &((F1AP_Served_Cells_To_Add_ItemIEs_t *)ie->value.choice.Served_Cells_To_Add_List.list.array[i]) + ->value.choice.Served_Cells_To_Add_Item; + /* Served Cell Information (M) */ + if (!decode_served_cell_info(&served_cells_item->served_Cell_Information, &out->cell_to_add[i].info)) + return false; + /* gNB-DU System Information */ + if (served_cells_item->gNB_DU_System_Information != NULL) { + out->cell_to_add[i].sys_info = calloc_or_fail(1, sizeof(*out->cell_to_add[i].sys_info)); + decode_system_info(served_cells_item->gNB_DU_System_Information, out->cell_to_add[i].sys_info); + } + } + } break; + case F1AP_ProtocolIE_ID_id_Served_Cells_To_Modify_List: { + /* Served Cells To Modify List (O) */ + out->num_cells_to_modify = ie->value.choice.Served_Cells_To_Modify_List.list.count; + AssertError(out->num_cells_to_modify > 0, return false, "at least 1 cell to modify shall to be present"); + for (int i = 0; i < out->num_cells_to_modify; i++) { + /* Served Cells To Modify List item (count >= 1) */ + F1AP_Served_Cells_To_Modify_Item_t *served_cells_item = + &((F1AP_Served_Cells_To_Modify_ItemIEs_t *)ie->value.choice.Served_Cells_To_Modify_List.list.array[i]) + ->value.choice.Served_Cells_To_Modify_Item; + /* Old NR CGI (M) */ + F1AP_NRCGI_t *oldNRCGI = &served_cells_item->oldNRCGI; + f1ap_plmn_t *old_plmn = &out->cell_to_modify[i].old_plmn; + TBCD_TO_MCC_MNC(&(oldNRCGI->pLMN_Identity), old_plmn->mcc, old_plmn->mnc, old_plmn->mnc_digit_length); + /* Old NR CGI Cell ID */ + BIT_STRING_TO_NR_CELL_IDENTITY(&oldNRCGI->nRCellIdentity, out->cell_to_modify[i].old_nr_cellid); + /* Served Cell Information (M) */ + if (!decode_served_cell_info(&served_cells_item->served_Cell_Information, &out->cell_to_modify[i].info)) + return false; + /* gNB-DU System Information (O) */ + if (served_cells_item->gNB_DU_System_Information != NULL) { + out->cell_to_modify[i].sys_info = calloc_or_fail(1, sizeof(*out->cell_to_modify[i].sys_info)); + decode_system_info(served_cells_item->gNB_DU_System_Information, out->cell_to_modify[i].sys_info); + } + } + } break; + case F1AP_ProtocolIE_ID_id_Served_Cells_To_Delete_List: { + /* Served Cells To Delete List */ + out->num_cells_to_delete = ie->value.choice.Served_Cells_To_Delete_List.list.count; + AssertError(out->num_cells_to_delete > 0, return false, "at least 1 cell to delete shall to be present"); + for (int i = 0; i < out->num_cells_to_delete; i++) { + F1AP_Served_Cells_To_Delete_Item_t *served_cells_item = + &((F1AP_Served_Cells_To_Delete_ItemIEs_t *)ie->value.choice.Served_Cells_To_Delete_List.list.array[i]) + ->value.choice.Served_Cells_To_Delete_Item; + F1AP_NRCGI_t *oldNRCGI = &served_cells_item->oldNRCGI; + f1ap_plmn_t *plmn = &out->cell_to_delete[i].plmn; + /* Old NR CGI (M) */ + TBCD_TO_MCC_MNC(&(oldNRCGI->pLMN_Identity), plmn->mcc, plmn->mnc, plmn->mnc_digit_length); + // NR cellID + BIT_STRING_TO_NR_CELL_IDENTITY(&oldNRCGI->nRCellIdentity, out->cell_to_delete[i].nr_cellid); + } + } break; + case F1AP_ProtocolIE_ID_id_Cells_Status_List: + /* Cells Status List (O) */ + AssertError(1 == 0, return false, "F1AP_ProtocolIE_ID_id_Cells_Status_List is not supported"); + break; + case F1AP_ProtocolIE_ID_id_Dedicated_SIDelivery_NeededUE_List: + /* Dedicated SI Delivery Needed UE List (O) */ + AssertError(1 == 0, return false, "F1AP_ProtocolIE_ID_id_Dedicated_SIDelivery_NeededUE_List is not supported"); + break; + case F1AP_ProtocolIE_ID_id_gNB_DU_ID: + /* gNB-DU ID (O)*/ + asn_INTEGER2ulong(&ie->value.choice.GNB_DU_ID, out->gNB_DU_ID); + break; + case F1AP_ProtocolIE_ID_id_GNB_DU_TNL_Association_To_Remove_List: + /* Cells Status List (O) */ + AssertError(1 == 0, return false, "F1AP_ProtocolIE_ID_id_GNB_DU_TNL_Association_To_Remove_List is not supported"); + break; + } + } + return true; +} + +void free_f1ap_du_configuration_update(const f1ap_gnb_du_configuration_update_t *msg) +{ + free(msg->gNB_DU_ID); + for (int i = 0; i < msg->num_cells_to_add; i++) { + free_f1ap_cell(&msg->cell_to_add[i].info, msg->cell_to_add[i].sys_info); + } + for (int i = 0; i < msg->num_cells_to_modify; i++) { + free_f1ap_cell(&msg->cell_to_modify[i].info, msg->cell_to_modify[i].sys_info); + } +} + +/** + * @brief F1 gNB-DU Configuration Update check + */ +bool eq_f1ap_du_configuration_update(const f1ap_gnb_du_configuration_update_t *a, const f1ap_gnb_du_configuration_update_t *b) +{ + if (a->gNB_DU_ID != NULL && b->gNB_DU_ID != NULL) + _F1_EQ_CHECK_LONG(*a->gNB_DU_ID, *b->gNB_DU_ID); + _F1_EQ_CHECK_LONG(a->transaction_id, b->transaction_id); + /* to add */ + _F1_EQ_CHECK_INT(a->num_cells_to_add, b->num_cells_to_add); + for (int i = 0; i < a->num_cells_to_add; i++) { + if (!eq_f1ap_cell_info(&a->cell_to_add[i].info, &b->cell_to_add[i].info)) + return false; + if (a->cell_to_add[i].sys_info && b->cell_to_add[i].sys_info) { + if (!eq_f1ap_sys_info(a->cell_to_add[i].sys_info, b->cell_to_add[i].sys_info)) + return false; + } + } + /* to delete */ + _F1_EQ_CHECK_INT(a->num_cells_to_delete, b->num_cells_to_delete); + for (int i = 0; i < a->num_cells_to_delete; i++) { + _F1_EQ_CHECK_LONG(a->cell_to_delete[i].nr_cellid, b->cell_to_delete[i].nr_cellid); + if (!eq_f1ap_plmn(&a->cell_to_delete[i].plmn, &b->cell_to_delete[i].plmn)) + return false; + } + /* to modify */ + _F1_EQ_CHECK_INT(a->num_cells_to_modify, b->num_cells_to_modify); + for (int i = 0; i < a->num_cells_to_modify; i++) { + if (!eq_f1ap_cell_info(&a->cell_to_modify[i].info, &b->cell_to_modify[i].info)) + return false; + if (a->cell_to_modify[i].sys_info && b->cell_to_modify[i].sys_info) { + if (!eq_f1ap_sys_info(a->cell_to_modify[i].sys_info, b->cell_to_modify[i].sys_info)) + return false; + } + } + return true; +} + +/** + * @brief F1 gNB-DU Configuration Update deep copy + */ +f1ap_gnb_du_configuration_update_t cp_f1ap_du_configuration_update(const f1ap_gnb_du_configuration_update_t *msg) +{ + f1ap_gnb_du_configuration_update_t cp = {0}; + /* gNB_DU_ID */ + if (msg->gNB_DU_ID != NULL) { + cp.gNB_DU_ID = calloc_or_fail(1, sizeof(*cp.gNB_DU_ID)); + *cp.gNB_DU_ID = *msg->gNB_DU_ID; + } + /* transaction_id */ + cp.transaction_id = msg->transaction_id; + /* to add */ + cp.num_cells_to_add = msg->num_cells_to_add; + /* to delete */ + cp.num_cells_to_delete = msg->num_cells_to_delete; + for (int i = 0; i < cp.num_cells_to_delete; i++) { + cp.cell_to_delete[i].nr_cellid = msg->cell_to_delete[i].nr_cellid; + cp.cell_to_delete[i].plmn = msg->cell_to_delete[i].plmn; + } + /* to modify */ + cp.num_cells_to_modify = msg->num_cells_to_modify; + for (int i = 0; i < cp.num_cells_to_modify; i++) { + cp.cell_to_modify[i].info = msg->cell_to_modify[i].info; + f1ap_served_cell_info_t *info = &cp.cell_to_modify[i].info; + if (info->measurement_timing_config_len > 0) { + info->measurement_timing_config = malloc_or_fail(info->measurement_timing_config_len * sizeof(*info->measurement_timing_config)); + for (int j = 0; j < info->measurement_timing_config_len; j++) + info->measurement_timing_config[j] = msg->cell_to_modify[i].info.measurement_timing_config[j]; + } + /* TAC */ + info->tac = calloc_or_fail(1, sizeof(*info->tac)); + *info->tac = *msg->cell_to_modify[i].info.tac; + /* System information */ + cp.cell_to_modify[i].sys_info = malloc_or_fail(sizeof(*cp.cell_to_modify[i].sys_info)); + f1ap_gnb_du_system_info_t *sys_info = cp.cell_to_modify[i].sys_info; + if (msg->cell_to_modify[i].sys_info->mib_length > 0) { + sys_info->mib_length = msg->cell_to_modify[i].sys_info->mib_length; + sys_info->mib = calloc_or_fail(msg->cell_to_modify[i].sys_info->mib_length, sizeof(*sys_info->mib)); + for (int j = 0; j < sys_info->mib_length; j++) + sys_info->mib[j] = msg->cell_to_modify[i].sys_info->mib[j]; + } + if (msg->cell_to_modify[i].sys_info->sib1_length > 0) { + sys_info->sib1_length = msg->cell_to_modify[i].sys_info->sib1_length; + sys_info->sib1 = calloc_or_fail(msg->cell_to_modify[i].sys_info->sib1_length, sizeof(*sys_info->sib1)); + for (int j = 0; j < sys_info->sib1_length; j++) + sys_info->sib1[j] = msg->cell_to_modify[i].sys_info->sib1[j]; + } + } + return cp; +} diff --git a/openair2/F1AP/lib/f1ap_interface_management.h b/openair2/F1AP/lib/f1ap_interface_management.h index ca0b7df491..aa7991488b 100644 --- a/openair2/F1AP/lib/f1ap_interface_management.h +++ b/openair2/F1AP/lib/f1ap_interface_management.h @@ -46,4 +46,11 @@ bool decode_f1ap_setup_failure(const struct F1AP_F1AP_PDU *pdu, f1ap_setup_failu bool eq_f1ap_setup_failure(const f1ap_setup_failure_t *a, const f1ap_setup_failure_t *b); f1ap_setup_failure_t cp_f1ap_setup_failure(const f1ap_setup_failure_t *msg); +/* F1 gNB-DU Configuration Update */ +struct F1AP_F1AP_PDU *encode_f1ap_du_configuration_update(const f1ap_gnb_du_configuration_update_t *msg); +bool decode_f1ap_du_configuration_update(const struct F1AP_F1AP_PDU *pdu, f1ap_gnb_du_configuration_update_t *out); +bool eq_f1ap_du_configuration_update(const f1ap_gnb_du_configuration_update_t *a, const f1ap_gnb_du_configuration_update_t *b); +f1ap_gnb_du_configuration_update_t cp_f1ap_du_configuration_update(const f1ap_gnb_du_configuration_update_t *msg); +void free_f1ap_du_configuration_update(const f1ap_gnb_du_configuration_update_t *msg); + #endif /* F1AP_INTERFACE_MANAGEMENT_H_ */ From 2cc50832d11a97fa1da01c0259a9c4125e010e17 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 9 Aug 2024 12:36:47 +0200 Subject: [PATCH 32/46] Add test for F1AP gNB-DU Configuration Update enc/dec library --- openair2/F1AP/tests/f1ap_lib_test.c | 75 +++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/openair2/F1AP/tests/f1ap_lib_test.c b/openair2/F1AP/tests/f1ap_lib_test.c index 42f07e4c2a..6ccc814cfc 100644 --- a/openair2/F1AP/tests/f1ap_lib_test.c +++ b/openair2/F1AP/tests/f1ap_lib_test.c @@ -357,6 +357,80 @@ static void test_f1ap_setup_failure(void) AssertFatal(ret, "eq_f1ap_setup_failure(): copied message doesn't match\n"); } +/** + * @brief Test F1 gNB-DU Configuration Update + */ +static void test_f1ap_du_configuration_update(void) +{ + /* sys_info */ + uint8_t *mib = calloc(3, sizeof(uint8_t)); + uint8_t *sib1 = calloc(3, sizeof(uint8_t)); + f1ap_gnb_du_system_info_t sys_info = { + .mib_length = 3, + .mib = mib, + .sib1_length = 3, + .sib1 = sib1, + }; + /* measurement_timing_information modify */ + char *s = "1"; + int measurement_timing_config_len = strlen(s) + 1; + uint8_t *measurement_timing_config_mod = calloc(measurement_timing_config_len, sizeof(uint8_t)); + AssertFatal(measurement_timing_config_mod != NULL, "out of memory\n"); + memcpy((void *)measurement_timing_config_mod, s, measurement_timing_config_len); + /* TAC modify */ + uint32_t *tac = calloc(1, sizeof(uint32_t)); + AssertFatal(tac != NULL, "out of memory\n"); + *tac = 456; + /* info modify */ + f1ap_served_cell_info_t info = { + .mode = F1AP_MODE_TDD, + .tdd.freqinfo.arfcn = 640000, + .tdd.freqinfo.band = 78, + .tdd.tbw.nrb = 66, + .tdd.tbw.scs = 1, + .measurement_timing_config_len = measurement_timing_config_len, + .measurement_timing_config = measurement_timing_config_mod, + .nr_cellid = 123456, + .plmn.mcc = 1, + .plmn.mnc = 1, + .plmn.mnc_digit_length = 3, + .tac = tac, + }; + /* create message */ + f1ap_gnb_du_configuration_update_t orig = { + .transaction_id = 2, + .num_cells_to_modify = 1, + .cell_to_modify[0].info = info, + .num_cells_to_delete = 0, + .cell_to_delete[0].nr_cellid = 1234UL, + .cell_to_delete[0].plmn.mcc = 1, + .cell_to_delete[0].plmn.mnc = 1, + .cell_to_delete[0].plmn.mnc_digit_length = 3, + }; + orig.cell_to_modify[0].sys_info = calloc(1, sizeof(*orig.cell_to_modify[0].sys_info)); + AssertFatal(orig.cell_to_modify[0].sys_info != NULL, "out of memory\n"); + *orig.cell_to_modify[0].sys_info = sys_info; + + F1AP_F1AP_PDU_t *f1enc = encode_f1ap_du_configuration_update(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_gnb_du_configuration_update_t decoded = {0}; + bool ret = decode_f1ap_du_configuration_update(f1dec, &decoded); + AssertFatal(ret, "decode_f1ap_setup_request(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_f1ap_du_configuration_update(&orig, &decoded); + AssertFatal(ret, "eq_f1ap_setup_request(): decoded message doesn't match\n"); + free_f1ap_du_configuration_update(&decoded); + + f1ap_gnb_du_configuration_update_t cp = cp_f1ap_du_configuration_update(&orig); + ret = eq_f1ap_du_configuration_update(&orig, &cp); + AssertFatal(ret, "eq_f1ap_setup_request(): copied message doesn't match\n"); + free_f1ap_du_configuration_update(&cp); + free_f1ap_du_configuration_update(&orig); +} + int main() { test_initial_ul_rrc_message_transfer(); @@ -365,5 +439,6 @@ int main() test_f1ap_setup_request(); test_f1ap_setup_response(); test_f1ap_setup_failure(); + test_f1ap_du_configuration_update(); return 0; } From 07da84ede2e65e1f606d68f88db6fc6d68c5bb19 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Thu, 29 Aug 2024 23:53:02 +0200 Subject: [PATCH 33/46] Use F1 gNB-DU Configuration Update lib in stack --- openair2/F1AP/f1ap_common.h | 2 - openair2/F1AP/f1ap_cu_interface_management.c | 350 +----------------- openair2/F1AP/f1ap_du_interface_management.c | 263 +------------ openair2/F1AP/f1ap_du_interface_management.h | 2 +- .../LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c | 47 +-- openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c | 36 +- openair2/RRC/NR/rrc_gNB_du.c | 3 +- 7 files changed, 40 insertions(+), 663 deletions(-) diff --git a/openair2/F1AP/f1ap_common.h b/openair2/F1AP/f1ap_common.h index 13f1d8f53b..83781484c7 100644 --- a/openair2/F1AP/f1ap_common.h +++ b/openair2/F1AP/f1ap_common.h @@ -411,8 +411,6 @@ typedef struct f1ap_cudu_inst_s { instance_t gtpInst; } f1ap_cudu_inst_t; -static const int nrb_lut[29] = {11, 18, 24, 25, 31, 32, 38, 51, 52, 65, 66, 78, 79, 93, 106, 107, 121, 132, 133, 135, 160, 162, 189, 216, 217, 245, 264, 270, 273}; - uint8_t F1AP_get_next_transaction_identifier(instance_t mod_idP, instance_t cu_mod_idP); f1ap_cudu_inst_t *getCxt(instance_t instanceP); diff --git a/openair2/F1AP/f1ap_cu_interface_management.c b/openair2/F1AP/f1ap_cu_interface_management.c index 49f887ad49..e6064c1502 100644 --- a/openair2/F1AP/f1ap_cu_interface_management.c +++ b/openair2/F1AP/f1ap_cu_interface_management.c @@ -48,32 +48,6 @@ int CU_send_RESET_ACKNOWLEDGE(sctp_assoc_t assoc_id, const f1ap_reset_ack_t *ack AssertFatal(1 == 0, "Not implemented yet\n"); } -static int read_slice_info(const F1AP_ServedPLMNs_Item_t *plmn, nssai_t *nssai, int max_nssai) -{ - if (plmn->iE_Extensions == NULL) - return 0; - - const F1AP_ProtocolExtensionContainer_10696P34_t *p = (F1AP_ProtocolExtensionContainer_10696P34_t *)plmn->iE_Extensions; - if (p->list.count == 0) - return 0; - - const F1AP_ServedPLMNs_ItemExtIEs_t *splmn = p->list.array[0]; - DevAssert(splmn->id == F1AP_ProtocolIE_ID_id_TAISliceSupportList); - DevAssert(splmn->extensionValue.present == F1AP_ServedPLMNs_ItemExtIEs__extensionValue_PR_SliceSupportList); - const F1AP_SliceSupportList_t *ssl = &splmn->extensionValue.choice.SliceSupportList; - AssertFatal(ssl->list.count <= max_nssai, "cannot handle more than 16 slices\n"); - for (int s = 0; s < ssl->list.count; ++s) { - const F1AP_SliceSupportItem_t *sl = ssl->list.array[s]; - nssai_t *n = &nssai[s]; - OCTET_STRING_TO_INT8(&sl->sNSSAI.sST, n->sst); - n->sd = 0xffffff; - if (sl->sNSSAI.sD != NULL) - OCTET_STRING_TO_INT24(sl->sNSSAI.sD, n->sd); - } - - return ssl->list.count; -} - /** * @brief F1AP Setup Request decoding (9.2.1.4 of 3GPP TS 38.473) and transfer to RRC */ @@ -146,324 +120,30 @@ int CU_send_F1_SETUP_FAILURE(sctp_assoc_t assoc_id, const f1ap_setup_failure_t * return 0; } -/* - gNB-DU Configuration Update -*/ - +/** + * @brief Decode and send F1 gNB-DU Configuration Update message to RRC + */ int CU_handle_gNB_DU_CONFIGURATION_UPDATE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { - LOG_D(F1AP, "CU_handle_gNB_DU_CONFIGURATION_UPDATE\n"); - F1AP_GNBDUConfigurationUpdate_t *container; - F1AP_GNBDUConfigurationUpdateIEs_t *ie; - int i = 0; + LOG_D(F1AP, "[SCTP %d] CU_handle_gNB_DU_CONFIGURATION_UPDATE\n", assoc_id); DevAssert(pdu != NULL); - container = &pdu->choice.initiatingMessage->value.choice.GNBDUConfigurationUpdate; - /* gNB DU Configuration Update == Non UE-related procedure -> stream 0 */ if (stream != 0) { LOG_W(F1AP, "[SCTP %d] Received f1 setup request on stream != 0 (%d)\n", assoc_id, stream); } - + /* Decode */ + f1ap_gnb_du_configuration_update_t msg = {0}; + if (!decode_f1ap_du_configuration_update(pdu, &msg)) { + LOG_E(F1AP, "cannot decode F1AP gNB-DU Configuration Update\n"); + free_f1ap_du_configuration_update(&msg); + return -1; + } + /* Send to RRC */ MessageDef *message_p = itti_alloc_new_message(TASK_CU_F1, 0, F1AP_GNB_DU_CONFIGURATION_UPDATE); message_p->ittiMsgHeader.originInstance = assoc_id; - f1ap_gnb_du_configuration_update_t *req = &F1AP_GNB_DU_CONFIGURATION_UPDATE(message_p); - - /* 3GPP TS 38.473 Transaction ID*/ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_GNBDUConfigurationUpdateIEs_t, ie, container, F1AP_ProtocolIE_ID_id_TransactionID, true); - req->transaction_id = ie->value.choice.TransactionID; - LOG_D(F1AP, "req->transaction_id %lu \n", req->transaction_id); - - /* 3GPP TS 38.473 Served Cells To Add List */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_GNBDUConfigurationUpdateIEs_t, - ie, - container, - F1AP_ProtocolIE_ID_id_Served_Cells_To_Add_List, - false); - - if (ie != NULL) { - req->num_cells_to_add = ie->value.choice.Served_Cells_To_Add_List.list.count; - LOG_D(F1AP, "req->num_cells_to_add %d \n", req->num_cells_to_add); - - for (i = 0; i < req->num_cells_to_add; i++) { - F1AP_Served_Cells_To_Add_Item_t *served_cells_item = - &((F1AP_Served_Cells_To_Add_ItemIEs_t *)ie->value.choice.Served_Cells_To_Add_List.list.array[i]) - ->value.choice.Served_Cells_To_Add_Item; - F1AP_Served_Cell_Information_t *servedCellInformation = &served_cells_item->served_Cell_Information; - /* tac */ - if (servedCellInformation->fiveGS_TAC) { - req->cell_to_add[i].info.tac = malloc(sizeof(*req->cell_to_add[i].info.tac)); - AssertFatal(req->cell_to_add[i].info.tac != NULL, "out of memory\n"); - OCTET_STRING_TO_INT24(servedCellInformation->fiveGS_TAC, *req->cell_to_add[i].info.tac); - LOG_D(F1AP, "req->tac[%d] %d \n", i, *req->cell_to_add[i].info.tac); - } - - /* - nRCGI */ - TBCD_TO_MCC_MNC(&(servedCellInformation->nRCGI.pLMN_Identity), - req->cell_to_add[i].info.plmn.mcc, - req->cell_to_add[i].info.plmn.mnc, - req->cell_to_add[i].info.plmn.mnc_digit_length); - // NR cellID - BIT_STRING_TO_NR_CELL_IDENTITY(&servedCellInformation->nRCGI.nRCellIdentity, req->cell_to_add[i].info.nr_cellid); - LOG_D(F1AP, - "[SCTP %d] Received nRCGI: MCC %d, MNC %d, CELL_ID %llu\n", - assoc_id, - req->cell_to_add[i].info.plmn.mcc, - req->cell_to_add[i].info.plmn.mnc, - (long long unsigned int)req->cell_to_add[i].info.nr_cellid); - - /* - nRPCI */ - req->cell_to_add[i].info.nr_pci = servedCellInformation->nRPCI; - LOG_D(F1AP, "req->nr_pci[%d] %d \n", i, req->cell_to_add[i].info.nr_pci); - - AssertFatal(servedCellInformation->servedPLMNs.list.count == 1, "only one PLMN handled\n"); - req->cell_to_add[i].info.num_ssi = - read_slice_info(servedCellInformation->servedPLMNs.list.array[0], req->cell_to_add[i].info.nssai, 16); - - // FDD Cells - if (servedCellInformation->nR_Mode_Info.present == F1AP_NR_Mode_Info_PR_fDD) { - req->cell_to_add[i].info.mode = F1AP_MODE_FDD; - f1ap_fdd_info_t *FDDs = &req->cell_to_add[i].info.fdd; - F1AP_FDD_Info_t *fDD_Info = servedCellInformation->nR_Mode_Info.choice.fDD; - FDDs->ul_freqinfo.arfcn = fDD_Info->uL_NRFreqInfo.nRARFCN; - AssertFatal(fDD_Info->uL_NRFreqInfo.freqBandListNr.list.count == 1, "cannot handle more than one frequency band\n"); - for (int f = 0; f < fDD_Info->uL_NRFreqInfo.freqBandListNr.list.count; f++) { - F1AP_FreqBandNrItem_t *FreqItem = fDD_Info->uL_NRFreqInfo.freqBandListNr.list.array[f]; - FDDs->ul_freqinfo.band = FreqItem->freqBandIndicatorNr; - AssertFatal(FreqItem->supportedSULBandList.list.count == 0, "cannot handle SUL bands!\n"); - } - FDDs->dl_freqinfo.arfcn = fDD_Info->dL_NRFreqInfo.nRARFCN; - int dlBands = fDD_Info->dL_NRFreqInfo.freqBandListNr.list.count; - AssertFatal(dlBands == 0, "cannot handled more than one frequency band\n"); - for (int dlB = 0; dlB < dlBands; dlB++) { - F1AP_FreqBandNrItem_t *FreqItem = fDD_Info->dL_NRFreqInfo.freqBandListNr.list.array[dlB]; - FDDs->dl_freqinfo.band = FreqItem->freqBandIndicatorNr; - int num_available_supported_SULBands = FreqItem->supportedSULBandList.list.count; - AssertFatal(num_available_supported_SULBands == 0, "cannot handle SUL bands!\n"); - } - FDDs->ul_tbw.scs = fDD_Info->uL_Transmission_Bandwidth.nRSCS; - FDDs->ul_tbw.nrb = nrb_lut[fDD_Info->uL_Transmission_Bandwidth.nRNRB]; - FDDs->dl_tbw.scs = fDD_Info->dL_Transmission_Bandwidth.nRSCS; - FDDs->dl_tbw.nrb = nrb_lut[fDD_Info->dL_Transmission_Bandwidth.nRNRB]; - } else if (servedCellInformation->nR_Mode_Info.present == F1AP_NR_Mode_Info_PR_tDD) { - req->cell_to_add[i].info.mode = F1AP_MODE_TDD; - f1ap_tdd_info_t *TDDs = &req->cell_to_add[i].info.tdd; - F1AP_TDD_Info_t *tDD_Info = servedCellInformation->nR_Mode_Info.choice.tDD; - TDDs->freqinfo.arfcn = tDD_Info->nRFreqInfo.nRARFCN; - AssertFatal(tDD_Info->nRFreqInfo.freqBandListNr.list.count == 1, "cannot handle more than one frequency band\n"); - for (int f = 0; f < tDD_Info->nRFreqInfo.freqBandListNr.list.count; f++) { - struct F1AP_FreqBandNrItem *FreqItem = tDD_Info->nRFreqInfo.freqBandListNr.list.array[f]; - TDDs->freqinfo.band = FreqItem->freqBandIndicatorNr; - int num_available_supported_SULBands = FreqItem->supportedSULBandList.list.count; - AssertFatal(num_available_supported_SULBands == 0, "cannot hanlde SUL bands!\n"); - } - TDDs->tbw.scs = tDD_Info->transmission_Bandwidth.nRSCS; - TDDs->tbw.nrb = nrb_lut[tDD_Info->transmission_Bandwidth.nRNRB]; - } else { - AssertFatal(false, "unknown NR Mode info %d\n", servedCellInformation->nR_Mode_Info.present); - } - - /* MeasurementConfig */ - if (servedCellInformation->measurementTimingConfiguration.size > 0) - req->cell_to_add[i].info.measurement_timing_config = - cp_octet_string(&servedCellInformation->measurementTimingConfiguration, - &req->cell_to_add[i].info.measurement_timing_config_len); - - struct F1AP_GNB_DU_System_Information *DUsi = served_cells_item->gNB_DU_System_Information; - // System Information - req->cell_to_add[i].sys_info = calloc(1, sizeof(*req->cell_to_add[i].sys_info)); - AssertFatal(req->cell_to_add[i].sys_info != NULL, "out of memory\n"); - f1ap_gnb_du_system_info_t *sys_info = req->cell_to_add[i].sys_info; - /* mib */ - sys_info->mib = calloc(DUsi->mIB_message.size, sizeof(char)); - memcpy(sys_info->mib, DUsi->mIB_message.buf, DUsi->mIB_message.size); - sys_info->mib_length = DUsi->mIB_message.size; - /* sib1 */ - sys_info->sib1 = calloc(DUsi->sIB1_message.size, sizeof(char)); - memcpy(sys_info->sib1, DUsi->sIB1_message.buf, DUsi->sIB1_message.size); - sys_info->sib1_length = DUsi->sIB1_message.size; - } - } else { - req->num_cells_to_add = 0; - } - /* 3GPP TS 38.473 Served Cells To Modify List */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_GNBDUConfigurationUpdateIEs_t, - ie, - container, - F1AP_ProtocolIE_ID_id_Served_Cells_To_Modify_List, - false); - - if (ie) { - req->num_cells_to_modify = ie->value.choice.Served_Cells_To_Modify_List.list.count; - LOG_D(F1AP, "req->num_cells_to_modify %d \n", req->num_cells_to_modify); - - for (i = 0; i < req->num_cells_to_modify; i++) { - F1AP_Served_Cells_To_Modify_Item_t *served_cells_item = - &((F1AP_Served_Cells_To_Modify_ItemIEs_t *)ie->value.choice.Served_Cells_To_Modify_List.list.array[i]) - ->value.choice.Served_Cells_To_Modify_Item; - - /* OLD NRCGI */ - TBCD_TO_MCC_MNC(&(served_cells_item->oldNRCGI.pLMN_Identity), - req->cell_to_modify[i].old_plmn.mcc, - req->cell_to_modify[i].old_plmn.mnc, - req->cell_to_modify[i].old_plmn.mnc_digit_length); - - BIT_STRING_TO_NR_CELL_IDENTITY(&served_cells_item->oldNRCGI.nRCellIdentity, req->cell_to_modify[i].old_nr_cellid); - - F1AP_Served_Cell_Information_t *servedCellInformation = &served_cells_item->served_Cell_Information; - /* SERVED CELL INFORMATION*/ - /* tac */ - if (servedCellInformation->fiveGS_TAC) { - req->cell_to_modify[i].info.tac = malloc(sizeof(*req->cell_to_modify[i].info.tac)); - AssertFatal(req->cell_to_modify[i].info.tac != NULL, "out of memory\n"); - OCTET_STRING_TO_INT24(servedCellInformation->fiveGS_TAC, *req->cell_to_modify[i].info.tac); - LOG_D(F1AP, "req->tac[%d] %d \n", i, *req->cell_to_modify[i].info.tac); - } - - /* - nRCGI */ - TBCD_TO_MCC_MNC(&(servedCellInformation->nRCGI.pLMN_Identity), - req->cell_to_modify[i].info.plmn.mcc, - req->cell_to_modify[i].info.plmn.mnc, - req->cell_to_modify[i].info.plmn.mnc_digit_length); - // NR cellID - BIT_STRING_TO_NR_CELL_IDENTITY(&servedCellInformation->nRCGI.nRCellIdentity, req->cell_to_modify[i].info.nr_cellid); - LOG_D(F1AP, - "[SCTP %d] Received nRCGI: MCC %d, MNC %d, CELL_ID %llu\n", - assoc_id, - req->cell_to_modify[i].info.plmn.mcc, - req->cell_to_modify[i].info.plmn.mnc, - (long long unsigned int)req->cell_to_modify[i].info.nr_cellid); - - /* - nRPCI */ - req->cell_to_modify[i].info.nr_pci = servedCellInformation->nRPCI; - LOG_D(F1AP, "req->nr_pci[%d] %d \n", i, req->cell_to_modify[i].info.nr_pci); - - // FDD Cells - if (servedCellInformation->nR_Mode_Info.present == F1AP_NR_Mode_Info_PR_fDD) { - req->cell_to_modify[i].info.mode = F1AP_MODE_FDD; - f1ap_fdd_info_t *FDDs = &req->cell_to_modify[i].info.fdd; - F1AP_FDD_Info_t *fDD_Info = servedCellInformation->nR_Mode_Info.choice.fDD; - FDDs->ul_freqinfo.arfcn = fDD_Info->uL_NRFreqInfo.nRARFCN; - AssertFatal(fDD_Info->uL_NRFreqInfo.freqBandListNr.list.count == 1, "cannot handle more than one frequency band\n"); - for (int f = 0; f < fDD_Info->uL_NRFreqInfo.freqBandListNr.list.count; f++) { - F1AP_FreqBandNrItem_t *FreqItem = fDD_Info->uL_NRFreqInfo.freqBandListNr.list.array[f]; - FDDs->ul_freqinfo.band = FreqItem->freqBandIndicatorNr; - AssertFatal(FreqItem->supportedSULBandList.list.count == 0, "cannot handle SUL bands!\n"); - } - FDDs->dl_freqinfo.arfcn = fDD_Info->dL_NRFreqInfo.nRARFCN; - int dlBands = fDD_Info->dL_NRFreqInfo.freqBandListNr.list.count; - AssertFatal(dlBands == 0, "cannot handled more than one frequency band\n"); - for (int dlB = 0; dlB < dlBands; dlB++) { - F1AP_FreqBandNrItem_t *FreqItem = fDD_Info->dL_NRFreqInfo.freqBandListNr.list.array[dlB]; - FDDs->dl_freqinfo.band = FreqItem->freqBandIndicatorNr; - int num_available_supported_SULBands = FreqItem->supportedSULBandList.list.count; - AssertFatal(num_available_supported_SULBands == 0, "cannot handle SUL bands!\n"); - } - FDDs->ul_tbw.scs = fDD_Info->uL_Transmission_Bandwidth.nRSCS; - FDDs->ul_tbw.nrb = nrb_lut[fDD_Info->uL_Transmission_Bandwidth.nRNRB]; - FDDs->dl_tbw.scs = fDD_Info->dL_Transmission_Bandwidth.nRSCS; - FDDs->dl_tbw.nrb = nrb_lut[fDD_Info->dL_Transmission_Bandwidth.nRNRB]; - } else if (servedCellInformation->nR_Mode_Info.present == F1AP_NR_Mode_Info_PR_tDD) { - req->cell_to_modify[i].info.mode = F1AP_MODE_TDD; - f1ap_tdd_info_t *TDDs = &req->cell_to_modify[i].info.tdd; - F1AP_TDD_Info_t *tDD_Info = servedCellInformation->nR_Mode_Info.choice.tDD; - TDDs->freqinfo.arfcn = tDD_Info->nRFreqInfo.nRARFCN; - AssertFatal(tDD_Info->nRFreqInfo.freqBandListNr.list.count == 1, "cannot handle more than one frequency band\n"); - for (int f = 0; f < tDD_Info->nRFreqInfo.freqBandListNr.list.count; f++) { - struct F1AP_FreqBandNrItem *FreqItem = tDD_Info->nRFreqInfo.freqBandListNr.list.array[f]; - TDDs->freqinfo.band = FreqItem->freqBandIndicatorNr; - int num_available_supported_SULBands = FreqItem->supportedSULBandList.list.count; - AssertFatal(num_available_supported_SULBands == 0, "cannot hanlde SUL bands!\n"); - } - TDDs->tbw.scs = tDD_Info->transmission_Bandwidth.nRSCS; - TDDs->tbw.nrb = nrb_lut[tDD_Info->transmission_Bandwidth.nRNRB]; - } else { - AssertFatal(false, "unknown NR Mode info %d\n", servedCellInformation->nR_Mode_Info.present); - } - - /* MeasurementConfig */ - if (servedCellInformation->measurementTimingConfiguration.size > 0) - req->cell_to_modify[i].info.measurement_timing_config = - cp_octet_string(&servedCellInformation->measurementTimingConfiguration, - &req->cell_to_modify[i].info.measurement_timing_config_len); - - /*gNB DU SYSTEM INFORMATION */ - struct F1AP_GNB_DU_System_Information *DUsi = served_cells_item->gNB_DU_System_Information; - if (DUsi != NULL) { - // System Information - req->cell_to_modify[i].sys_info = calloc(1, sizeof(*req->cell_to_modify[i].sys_info)); - AssertFatal(req->cell_to_modify[i].sys_info != NULL, "out of memory\n"); - f1ap_gnb_du_system_info_t *sys_info = req->cell_to_modify[i].sys_info; - /* mib */ - sys_info->mib = calloc(DUsi->mIB_message.size, sizeof(char)); - AssertFatal(req->cell_to_modify[i].sys_info->mib != NULL, "out of memory\n"); - memcpy(sys_info->mib, DUsi->mIB_message.buf, DUsi->mIB_message.size); - sys_info->mib_length = DUsi->mIB_message.size; - - /* sib1 */ - sys_info->sib1 = calloc(DUsi->sIB1_message.size, sizeof(char)); - AssertFatal(req->cell_to_modify[i].sys_info->sib1 != NULL, "out of memory\n"); - memcpy(sys_info->sib1, DUsi->sIB1_message.buf, DUsi->sIB1_message.size); - sys_info->sib1_length = DUsi->sIB1_message.size; - } - } - } else { - req->num_cells_to_modify = 0; - } - - /* 3GPP TS 38.473 Served Cells To Delete List */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_GNBDUConfigurationUpdateIEs_t, - ie, - container, - F1AP_ProtocolIE_ID_id_Served_Cells_To_Delete_List, - false); - if (ie) { - req->num_cells_to_delete = ie->value.choice.Served_Cells_To_Delete_List.list.count; - LOG_D(F1AP, "req->num_cells_to_delete %d \n", req->num_cells_to_delete); - - for (i = 0; i < req->num_cells_to_delete; i++) { - F1AP_Served_Cells_To_Delete_Item_t *served_cells_item = - &((F1AP_Served_Cells_To_Delete_ItemIEs_t *)ie->value.choice.Served_Cells_To_Delete_List.list.array[i]) - ->value.choice.Served_Cells_To_Delete_Item; - /* - Old nRCGI */ - TBCD_TO_MCC_MNC(&(served_cells_item->oldNRCGI.pLMN_Identity), - req->cell_to_delete[i].plmn.mcc, - req->cell_to_delete[i].plmn.mnc, - req->cell_to_delete[i].plmn.mnc_digit_length); - // NR cellID - BIT_STRING_TO_NR_CELL_IDENTITY(&served_cells_item->oldNRCGI.nRCellIdentity, req->cell_to_delete[i].nr_cellid); - LOG_D(F1AP, - "[SCTP %d] Received nRCGI to delete: MCC %d, MNC %d, CELL_ID %llu\n", - assoc_id, - req->cell_to_delete[i].plmn.mcc, - req->cell_to_delete[i].plmn.mnc, - (long long unsigned int)req->cell_to_delete[i].nr_cellid); - } - } else { - req->num_cells_to_delete = 0; - } - - /* 3GPP TS 38.473 Cells Status List */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_GNBDUConfigurationUpdateIEs_t, ie, container, F1AP_ProtocolIE_ID_id_Cells_Status_List, false); - - /* 3GPP TS 38.473 Dedicated SI Delivery Needed UE List */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_GNBDUConfigurationUpdateIEs_t, - ie, - container, - F1AP_ProtocolIE_ID_id_Dedicated_SIDelivery_NeededUE_List, - false); - - /* 3GPP TS 38.473 gNB-DU ID */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_GNBDUConfigurationUpdateIEs_t, ie, container, F1AP_ProtocolIE_ID_id_gNB_DU_ID, false); - if (ie != NULL) - asn_INTEGER2ulong(&ie->value.choice.GNB_DU_ID, req->gNB_DU_ID); - - /* 3GPP TS 38.473 gNB-DU TNL Association To Remove List */ - F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_GNBDUConfigurationUpdateIEs_t, - ie, - container, - F1AP_ProtocolIE_ID_id_GNB_DU_TNL_Association_To_Remove_List, - false); - + f1ap_gnb_du_configuration_update_t *req = &F1AP_GNB_DU_CONFIGURATION_UPDATE(message_p); // RRC thread will free it + *req = msg; // copy F1 message to ITTI + free_f1ap_du_configuration_update(&msg); LOG_D(F1AP, "Sending F1AP_GNB_DU_CONFIGURATION_UPDATE ITTI message \n"); itti_send_msg_to_task(TASK_RRC_GNB, GNB_MODULE_ID_TO_INSTANCE(instance), message_p); return 0; diff --git a/openair2/F1AP/f1ap_du_interface_management.c b/openair2/F1AP/f1ap_du_interface_management.c index 62da719aa0..6104757816 100644 --- a/openair2/F1AP/f1ap_du_interface_management.c +++ b/openair2/F1AP/f1ap_du_interface_management.c @@ -41,17 +41,6 @@ #include "GNB_APP/gnb_paramdef.h" -int to_NRNRB(int nrb) { - for (int i=0; inr_pci; // int 0..1007 - - /* - fiveGS_TAC */ - if (c->tac != NULL) { - uint32_t tac = htonl(*c->tac); - asn1cCalloc(scell_info.fiveGS_TAC, netOrder); - OCTET_STRING_fromBuf(netOrder, ((char *)&tac) + 1, 3); - } - - /* - Configured_EPS_TAC */ - if (0) { - scell_info.configured_EPS_TAC = (F1AP_Configured_EPS_TAC_t *)calloc(1, sizeof(F1AP_Configured_EPS_TAC_t)); - OCTET_STRING_fromBuf(scell_info.configured_EPS_TAC, "2", 2); - } - - /* servedPLMN information */ - asn1cSequenceAdd(scell_info.servedPLMNs.list, F1AP_ServedPLMNs_Item_t, servedPLMN_item); - MCC_MNC_TO_PLMNID(c->plmn.mcc, c->plmn.mnc, c->plmn.mnc_digit_length, &servedPLMN_item->pLMN_Identity); - - F1AP_NR_Mode_Info_t *nR_Mode_Info = &scell_info.nR_Mode_Info; - if (c->num_ssi > 0) { - F1AP_ProtocolExtensionContainer_10696P34_t *p = calloc(1, sizeof(*p)); - servedPLMN_item->iE_Extensions = (struct F1AP_ProtocolExtensionContainer *)p; - asn1cSequenceAdd(p->list, F1AP_ServedPLMNs_ItemExtIEs_t, served_plmns_itemExtIEs); - served_plmns_itemExtIEs->criticality = F1AP_Criticality_ignore; - served_plmns_itemExtIEs->id = F1AP_ProtocolIE_ID_id_TAISliceSupportList; - served_plmns_itemExtIEs->extensionValue.present = F1AP_ServedPLMNs_ItemExtIEs__extensionValue_PR_SliceSupportList; - F1AP_SliceSupportList_t *slice_support_list = &served_plmns_itemExtIEs->extensionValue.choice.SliceSupportList; - - for (int s = 0; s < c->num_ssi; s++) { - asn1cSequenceAdd(slice_support_list->list, F1AP_SliceSupportItem_t, slice); - const nssai_t *nssai = &c->nssai[s]; - INT8_TO_OCTET_STRING(nssai->sst, &slice->sNSSAI.sST); - if (nssai->sd != 0xffffff) { - asn1cCalloc(slice->sNSSAI.sD, tmp); - INT24_TO_OCTET_STRING(nssai->sd, tmp); - } - } - } - - if (c->mode == F1AP_MODE_FDD) { // FDD - const f1ap_fdd_info_t *fdd = &c->fdd; - nR_Mode_Info->present = F1AP_NR_Mode_Info_PR_fDD; - asn1cCalloc(nR_Mode_Info->choice.fDD, fDD_Info); - /* FDD.1.1 UL NRFreqInfo ARFCN */ - fDD_Info->uL_NRFreqInfo.nRARFCN = fdd->ul_freqinfo.arfcn; // Integer - - /* FDD.1.2 F1AP_SUL_Information */ - - /* FDD.1.3 freqBandListNr */ - int ul_band = 1; - for (int j = 0; j < ul_band; j++) { - asn1cSequenceAdd(fDD_Info->uL_NRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, nr_freqBandNrItem); - /* FDD.1.3.1 freqBandIndicatorNr*/ - nr_freqBandNrItem->freqBandIndicatorNr = fdd->ul_freqinfo.band; - - /* FDD.1.3.2 supportedSULBandList*/ - } - - /* FDD.2.1 DL NRFreqInfo ARFCN */ - fDD_Info->dL_NRFreqInfo.nRARFCN = fdd->dl_freqinfo.arfcn; // Integer - - /* FDD.2.2 F1AP_SUL_Information */ - - /* FDD.2.3 freqBandListNr */ - int dl_bands = 1; - for (int j = 0; j < dl_bands; j++) { - asn1cSequenceAdd(fDD_Info->dL_NRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, nr_freqBandNrItem); - /* FDD.2.3.1 freqBandIndicatorNr*/ - nr_freqBandNrItem->freqBandIndicatorNr = fdd->dl_freqinfo.band; - - /* FDD.2.3.2 supportedSULBandList*/ - } // for FDD : DL freq_Bands - - /* FDD.3 UL Transmission Bandwidth */ - fDD_Info->uL_Transmission_Bandwidth.nRSCS = fdd->ul_tbw.scs; - fDD_Info->uL_Transmission_Bandwidth.nRNRB = to_NRNRB(fdd->ul_tbw.nrb); - /* FDD.4 DL Transmission Bandwidth */ - fDD_Info->dL_Transmission_Bandwidth.nRSCS = fdd->dl_tbw.scs; - fDD_Info->dL_Transmission_Bandwidth.nRNRB = to_NRNRB(fdd->dl_tbw.nrb); - } else if (c->mode == F1AP_MODE_TDD) { - const f1ap_tdd_info_t *tdd = &c->tdd; - nR_Mode_Info->present = F1AP_NR_Mode_Info_PR_tDD; - asn1cCalloc(nR_Mode_Info->choice.tDD, tDD_Info); - /* TDD.1.1 nRFreqInfo ARFCN */ - tDD_Info->nRFreqInfo.nRARFCN = tdd->freqinfo.arfcn; - - /* TDD.1.2 F1AP_SUL_Information */ - - /* TDD.1.3 freqBandListNr */ - int bands = 1; - for (int j = 0; j < bands; j++) { - asn1cSequenceAdd(tDD_Info->nRFreqInfo.freqBandListNr.list, F1AP_FreqBandNrItem_t, nr_freqBandNrItem); - /* TDD.1.3.1 freqBandIndicatorNr*/ - nr_freqBandNrItem->freqBandIndicatorNr = tdd->freqinfo.band; - /* TDD.1.3.2 supportedSULBandList*/ - } - - /* TDD.2 transmission_Bandwidth */ - tDD_Info->transmission_Bandwidth.nRSCS = tdd->tbw.scs; - tDD_Info->transmission_Bandwidth.nRNRB = to_NRNRB(tdd->tbw.nrb); - } else { - AssertFatal(false, "unknown mode %d\n", c->mode); - } - - /* - measurementTimingConfiguration */ - OCTET_STRING_fromBuf(&scell_info.measurementTimingConfiguration, - (const char *)c->measurement_timing_config, - c->measurement_timing_config_len); - - return scell_info; -} - -static F1AP_GNB_DU_System_Information_t *encode_system_info(const f1ap_gnb_du_system_info_t *sys_info) -{ - if (sys_info == NULL) - return NULL; /* optional: can be NULL */ - - F1AP_GNB_DU_System_Information_t *enc_sys_info = calloc(1, sizeof(*enc_sys_info)); - AssertFatal(enc_sys_info != NULL, "out of memory\n"); - - AssertFatal(sys_info->mib != NULL, "MIB must be present in DU sys info\n"); - OCTET_STRING_fromBuf(&enc_sys_info->mIB_message, (const char *)sys_info->mib, sys_info->mib_length); - - AssertFatal(sys_info->sib1 != NULL, "SIB1 must be present in DU sys info\n"); - OCTET_STRING_fromBuf(&enc_sys_info->sIB1_message, (const char *)sys_info->sib1, sys_info->sib1_length); - - return enc_sys_info; -} - /** * @brief F1AP Setup Request */ @@ -351,115 +203,24 @@ int DU_handle_F1_SETUP_FAILURE(instance_t instance, sctp_assoc_t assoc_id, uint3 return 0; } -/* - gNB-DU Configuration Update -*/ - -int DU_send_gNB_DU_CONFIGURATION_UPDATE(sctp_assoc_t assoc_id, const f1ap_gnb_du_configuration_update_t *upd) +/** + * @brief F1 gNB-DU Configuration Update: encoding and ITTI transmission + */ +int DU_send_gNB_DU_CONFIGURATION_UPDATE(sctp_assoc_t assoc_id, f1ap_gnb_du_configuration_update_t *msg) { - F1AP_F1AP_PDU_t pdu= {0}; uint8_t *buffer=NULL; uint32_t len=0; - /* Create */ - /* 0. Message Type */ - pdu.present = F1AP_F1AP_PDU_PR_initiatingMessage; - asn1cCalloc(pdu.choice.initiatingMessage, initMsg); - initMsg->procedureCode = F1AP_ProcedureCode_id_gNBDUConfigurationUpdate; - initMsg->criticality = F1AP_Criticality_reject; - initMsg->value.present = F1AP_InitiatingMessage__value_PR_GNBDUConfigurationUpdate; - F1AP_GNBDUConfigurationUpdate_t *out = &initMsg->value.choice.GNBDUConfigurationUpdate; - - /* mandatory */ - /* c1. Transaction ID (integer value) */ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_GNBDUConfigurationUpdateIEs_t, ie1); - ie1->id = F1AP_ProtocolIE_ID_id_TransactionID; - ie1->criticality = F1AP_Criticality_reject; - ie1->value.present = F1AP_GNBDUConfigurationUpdateIEs__value_PR_TransactionID; - ie1->value.choice.TransactionID = upd->transaction_id; - - /* mandatory */ - /* c2. Served_Cells_To_Add */ - if (upd->num_cells_to_add > 0) { - AssertFatal(false, "code for adding cells not tested\n"); - asn1cSequenceAdd(out->protocolIEs.list, F1AP_GNBDUConfigurationUpdateIEs_t, ie2); - ie2->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Add_List; - ie2->criticality = F1AP_Criticality_reject; - ie2->value.present = F1AP_GNBDUConfigurationUpdateIEs__value_PR_Served_Cells_To_Add_List; - - for (int j = 0; j < upd->num_cells_to_add; j++) { - const f1ap_served_cell_info_t *cell = &upd->cell_to_add[j].info; - const f1ap_gnb_du_system_info_t *sys_info = upd->cell_to_add[j].sys_info; - asn1cSequenceAdd(ie2->value.choice.Served_Cells_To_Add_List.list, - F1AP_Served_Cells_To_Add_ItemIEs_t, - served_cells_to_add_item_ies); - served_cells_to_add_item_ies->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Add_Item; - served_cells_to_add_item_ies->criticality = F1AP_Criticality_reject; - served_cells_to_add_item_ies->value.present = F1AP_Served_Cells_To_Add_ItemIEs__value_PR_Served_Cells_To_Add_Item; - F1AP_Served_Cells_To_Add_Item_t *served_cells_to_add_item = - &served_cells_to_add_item_ies->value.choice.Served_Cells_To_Add_Item; - served_cells_to_add_item->served_Cell_Information = encode_served_cell_info(cell); - served_cells_to_add_item->gNB_DU_System_Information = encode_system_info(sys_info); - } - } - - /* mandatory */ - /* c3. Served_Cells_To_Modify */ - if (upd->num_cells_to_modify > 0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_GNBDUConfigurationUpdateIEs_t, ie3); - ie3->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Modify_List; - ie3->criticality = F1AP_Criticality_reject; - ie3->value.present = F1AP_GNBDUConfigurationUpdateIEs__value_PR_Served_Cells_To_Modify_List; - for (int i = 0; i < upd->num_cells_to_modify; i++) { - const f1ap_served_cell_info_t *cell = &upd->cell_to_modify[i].info; - const f1ap_gnb_du_system_info_t *sys_info = upd->cell_to_modify[i].sys_info; - asn1cSequenceAdd(ie3->value.choice.Served_Cells_To_Modify_List.list, - F1AP_Served_Cells_To_Modify_ItemIEs_t, - served_cells_to_modify_item_ies); - served_cells_to_modify_item_ies->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Modify_Item; - served_cells_to_modify_item_ies->criticality = F1AP_Criticality_reject; - served_cells_to_modify_item_ies->value.present = F1AP_Served_Cells_To_Modify_ItemIEs__value_PR_Served_Cells_To_Modify_Item; - F1AP_Served_Cells_To_Modify_Item_t *served_cells_to_modify_item = - &served_cells_to_modify_item_ies->value.choice.Served_Cells_To_Modify_Item; - - F1AP_NRCGI_t *oldNRCGI = &served_cells_to_modify_item->oldNRCGI; - const f1ap_plmn_t *old_plmn = &upd->cell_to_modify[i].old_plmn; - MCC_MNC_TO_PLMNID(old_plmn->mcc, old_plmn->mnc, old_plmn->mnc_digit_length, &oldNRCGI->pLMN_Identity); - NR_CELL_ID_TO_BIT_STRING(upd->cell_to_modify[i].old_nr_cellid, &oldNRCGI->nRCellIdentity); - - served_cells_to_modify_item->served_Cell_Information = encode_served_cell_info(cell); - served_cells_to_modify_item->gNB_DU_System_Information = encode_system_info(sys_info); - } - } - - /* mandatory */ - /* c4. Served_Cells_To_Delete */ - if (upd->num_cells_to_delete > 0) { - asn1cSequenceAdd(out->protocolIEs.list, F1AP_GNBDUConfigurationUpdateIEs_t, ie4); - ie4->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Delete_List; - ie4->criticality = F1AP_Criticality_reject; - ie4->value.present = F1AP_GNBDUConfigurationUpdateIEs__value_PR_Served_Cells_To_Delete_List; - AssertFatal(upd->num_cells_to_delete == 0, "code for deleting cells not tested\n"); - for (int i = 0; i < upd->num_cells_to_delete; i++) { - asn1cSequenceAdd(ie4->value.choice.Served_Cells_To_Delete_List.list, - F1AP_Served_Cells_To_Delete_ItemIEs_t, - served_cells_to_delete_item_ies); - served_cells_to_delete_item_ies->id = F1AP_ProtocolIE_ID_id_Served_Cells_To_Delete_Item; - served_cells_to_delete_item_ies->criticality = F1AP_Criticality_reject; - served_cells_to_delete_item_ies->value.present = F1AP_Served_Cells_To_Delete_ItemIEs__value_PR_Served_Cells_To_Delete_Item; - F1AP_Served_Cells_To_Delete_Item_t *served_cells_to_delete_item = - &served_cells_to_delete_item_ies->value.choice.Served_Cells_To_Delete_Item; - addnRCGI(served_cells_to_delete_item->oldNRCGI, &upd->cell_to_delete[i]); - } - } - - AssertFatal(upd->gNB_DU_ID == 0, "encoding of gNB-DU Id not handled yet\n"); - - if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { + /* encode F1AP message */ + F1AP_F1AP_PDU_t *pdu = encode_f1ap_du_configuration_update(msg); + /* free anfter encoding */ + free_f1ap_du_configuration_update(msg); + /* encode F1AP pdu */ + if (f1ap_encode_pdu(pdu, &buffer, &len) < 0) { LOG_E(F1AP, "Failed to encode F1 gNB-DU CONFIGURATION UPDATE\n"); return -1; } - - ASN_STRUCT_RESET(asn_DEF_F1AP_F1AP_PDU, &pdu); + /* transfer the message */ + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); return 0; } diff --git a/openair2/F1AP/f1ap_du_interface_management.h b/openair2/F1AP/f1ap_du_interface_management.h index 0cbf6adae2..c8975a2361 100644 --- a/openair2/F1AP/f1ap_du_interface_management.h +++ b/openair2/F1AP/f1ap_du_interface_management.h @@ -51,7 +51,7 @@ int DU_handle_F1_SETUP_FAILURE(instance_t instance, sctp_assoc_t assoc_id, uint3 /* * gNB-DU Configuration Update */ -int DU_send_gNB_DU_CONFIGURATION_UPDATE(sctp_assoc_t assoc_id, const f1ap_gnb_du_configuration_update_t *upd); +int DU_send_gNB_DU_CONFIGURATION_UPDATE(sctp_assoc_t assoc_id, f1ap_gnb_du_configuration_update_t *msg); /* * gNB-CU Configuration Update diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c index 7bdad73d21..ad8978d514 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c @@ -51,51 +51,8 @@ static void gnb_du_configuration_update_direct(const f1ap_gnb_du_configuration_u { MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_GNB_DU_CONFIGURATION_UPDATE); msg->ittiMsgHeader.originInstance = -1; // means monolithic - f1ap_gnb_du_configuration_update_t *f1ap_msg = &F1AP_GNB_DU_CONFIGURATION_UPDATE(msg); - DevAssert(upd->gNB_DU_ID == NULL); - f1ap_msg->transaction_id = upd->transaction_id; - DevAssert(upd->num_cells_to_add == 0); - DevAssert(upd->num_cells_to_delete == 0); - - f1ap_msg->num_cells_to_modify = upd->num_cells_to_modify; - for (int n = 0; n < upd->num_cells_to_modify; ++n) { - f1ap_msg->cell_to_modify[n].old_nr_cellid = upd->cell_to_modify[n].old_nr_cellid; - f1ap_msg->cell_to_modify[n].info = upd->cell_to_modify[n].info; // copy most fields - if (upd->cell_to_modify[n].info.tac) { - f1ap_msg->cell_to_modify[n].info.tac = malloc(sizeof(*f1ap_msg->cell_to_modify[n].info.tac)); - AssertFatal(f1ap_msg->cell_to_modify[n].info.tac != NULL, "out of memory\n"); - *f1ap_msg->cell_to_modify[n].info.tac = *upd->cell_to_modify[n].info.tac; - } - if (upd->cell_to_modify[n].info.measurement_timing_config_len > 0) { - f1ap_msg->cell_to_modify[n].info.measurement_timing_config = - calloc(upd->cell_to_modify[n].info.measurement_timing_config_len, sizeof(uint8_t)); - AssertFatal(f1ap_msg->cell_to_modify[n].info.measurement_timing_config != NULL, "out of memory\n"); - memcpy(f1ap_msg->cell_to_modify[n].info.measurement_timing_config, - upd->cell_to_modify[n].info.measurement_timing_config, - upd->cell_to_modify[n].info.measurement_timing_config_len); - f1ap_msg->cell_to_modify[n].info.measurement_timing_config_len = upd->cell_to_modify[n].info.measurement_timing_config_len; - } - - if (upd->cell_to_modify[n].sys_info) { - f1ap_gnb_du_system_info_t *orig_sys_info = upd->cell_to_modify[n].sys_info; - f1ap_gnb_du_system_info_t *copy_sys_info = calloc(1, sizeof(*copy_sys_info)); - AssertFatal(copy_sys_info != NULL, "out of memory\n"); - f1ap_msg->cell_to_modify[n].sys_info = copy_sys_info; - - copy_sys_info->mib = calloc(orig_sys_info->mib_length, sizeof(uint8_t)); - AssertFatal(copy_sys_info->mib != NULL, "out of memory\n"); - memcpy(copy_sys_info->mib, orig_sys_info->mib, orig_sys_info->mib_length); - copy_sys_info->mib_length = orig_sys_info->mib_length; - - if (orig_sys_info->sib1_length > 0) { - copy_sys_info->sib1 = calloc(orig_sys_info->sib1_length, sizeof(uint8_t)); - AssertFatal(copy_sys_info->sib1 != NULL, "out of memory\n"); - memcpy(copy_sys_info->sib1, orig_sys_info->sib1, orig_sys_info->sib1_length); - copy_sys_info->sib1_length = orig_sys_info->sib1_length; - } - } - } - + /* transfer to RRC via ITTI */ + F1AP_GNB_DU_CONFIGURATION_UPDATE(msg) = cp_f1ap_du_configuration_update(upd); itti_send_msg_to_task(TASK_RRC_GNB, 0, msg); } diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c index caf4309bec..2af81d0cfd 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c @@ -78,34 +78,14 @@ static void f1_setup_request_f1ap(const f1ap_setup_req_t *req) static void gnb_du_configuration_update_f1ap(const f1ap_gnb_du_configuration_update_t *upd) { MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_GNB_DU_CONFIGURATION_UPDATE); - f1ap_gnb_du_configuration_update_t *f1_upd = &F1AP_GNB_DU_CONFIGURATION_UPDATE(msg); - f1_upd->transaction_id = upd->transaction_id; - AssertFatal(upd->num_cells_to_add == 0, "gNB-DU config update: cells to add not supported\n"); - f1_upd->num_cells_to_modify = upd->num_cells_to_modify; - for (int n = 0; n < upd->num_cells_to_modify; ++n) { - f1_upd->cell_to_modify[n].old_plmn = upd->cell_to_modify[n].old_plmn; - f1_upd->cell_to_modify[n].old_nr_cellid = upd->cell_to_modify[n].old_nr_cellid; - f1_upd->cell_to_modify[n].info = upd->cell_to_modify[n].info; - if (upd->cell_to_modify[n].sys_info) { - f1ap_gnb_du_system_info_t *orig_sys_info = upd->cell_to_modify[n].sys_info; - f1ap_gnb_du_system_info_t *copy_sys_info = calloc(1, sizeof(*copy_sys_info)); - f1_upd->cell_to_modify[n].sys_info = copy_sys_info; - - copy_sys_info->mib = calloc(orig_sys_info->mib_length, sizeof(uint8_t)); - AssertFatal(copy_sys_info->mib != NULL, "out of memory\n"); - memcpy(copy_sys_info->mib, orig_sys_info->mib, orig_sys_info->mib_length); - copy_sys_info->mib_length = orig_sys_info->mib_length; - - if (orig_sys_info->sib1_length > 0) { - copy_sys_info->sib1 = calloc(orig_sys_info->sib1_length, sizeof(uint8_t)); - AssertFatal(copy_sys_info->sib1 != NULL, "out of memory\n"); - memcpy(copy_sys_info->sib1, orig_sys_info->sib1, orig_sys_info->sib1_length); - copy_sys_info->sib1_length = orig_sys_info->sib1_length; - } - } - } - AssertFatal(upd->num_cells_to_delete == 0, "gNB-DU config update: cells to add not supported\n"); - itti_send_msg_to_task(TASK_DU_F1, 0, msg); + /* copy F1AP message */ + f1ap_gnb_du_configuration_update_t cp = cp_f1ap_du_configuration_update(upd); + /* transfer to ITTI message */ + F1AP_GNB_DU_CONFIGURATION_UPDATE(msg) = cp; + /* free after copy */ + free_f1ap_du_configuration_update(upd); + /* send to RRC task */ + itti_send_msg_to_task(TASK_RRC_GNB, 0, msg); } static void ue_context_setup_response_f1ap(const f1ap_ue_context_setup_t *req, const f1ap_ue_context_setup_t *resp) diff --git a/openair2/RRC/NR/rrc_gNB_du.c b/openair2/RRC/NR/rrc_gNB_du.c index 1322c52141..e2806edf60 100644 --- a/openair2/RRC/NR/rrc_gNB_du.c +++ b/openair2/RRC/NR/rrc_gNB_du.c @@ -516,8 +516,9 @@ void rrc_gNB_process_f1_du_configuration_update(f1ap_gnb_du_configuration_update /* Send DU Configuration Acknowledgement */ f1ap_gnb_du_configuration_update_acknowledge_t ack = {.transaction_id = conf_up->transaction_id}; - rrc->mac_rrc.gnb_du_configuration_update_acknowledge(assoc_id, &ack); + /* free F1AP message after use */ + free_f1ap_du_configuration_update(conf_up); } void rrc_CU_process_f1_lost_connection(gNB_RRC_INST *rrc, f1ap_lost_connection_t *lc, sctp_assoc_t assoc_id) From 3b11764d1de8a7686cb087aed8f8da283c9d2cce Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 28 Aug 2024 17:22:09 +0200 Subject: [PATCH 34/46] Minor comments --- openair2/COMMON/f1ap_messages_types.h | 3 +-- openair2/F1AP/f1ap_du_rrc_message_transfer.c | 4 +++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index 95ff676307..f2fd001e4e 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -292,8 +292,7 @@ typedef struct f1ap_gnb_du_configuration_update_s { f1ap_plmn_t plmn; uint64_t nr_cellid; // NR Global Cell Id } cell_to_delete[F1AP_MAX_NB_CELLS]; - - /// string holding gNB_CU_name + /// gNB-DU unique ID, at least within a gNB-CU (0 .. 2^36 - 1) uint64_t *gNB_DU_ID; } f1ap_gnb_du_configuration_update_t; diff --git a/openair2/F1AP/f1ap_du_rrc_message_transfer.c b/openair2/F1AP/f1ap_du_rrc_message_transfer.c index 5f150bf25c..7fd83ecd78 100644 --- a/openair2/F1AP/f1ap_du_rrc_message_transfer.c +++ b/openair2/F1AP/f1ap_du_rrc_message_transfer.c @@ -74,6 +74,7 @@ int DU_handle_DL_RRC_MESSAGE_TRANSFER(instance_t instance, sctp_assoc_t assoc_id /* UL RRC Message Transfer */ int DU_send_INITIAL_UL_RRC_MESSAGE_TRANSFER(sctp_assoc_t assoc_id, const f1ap_initial_ul_rrc_message_t *msg) { + /* encode Initial UL RRC Message Transfer */ F1AP_F1AP_PDU_t *pdu = encode_initial_ul_rrc_message_transfer(msg); /* free F1AP message after encoding */ free_initial_ul_rrc_message_transfer(msg); @@ -84,7 +85,7 @@ int DU_send_INITIAL_UL_RRC_MESSAGE_TRANSFER(sctp_assoc_t assoc_id, const f1ap_in return -1; } - /* encode */ + /* encode F1AP PDU */ uint8_t *buffer = NULL; uint32_t len = 0; if (f1ap_encode_pdu(pdu, &buffer, &len) < 0) { @@ -94,6 +95,7 @@ int DU_send_INITIAL_UL_RRC_MESSAGE_TRANSFER(sctp_assoc_t assoc_id, const f1ap_in } ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); + /* Send to ITTI */ f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); return 0; } From c416c57f929aef337b72d332c97251d174a717e0 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 31 Jul 2024 17:19:36 +0200 Subject: [PATCH 35/46] Simplified F1AP gNB-CU Configuration Update message struct * removed optional IEs, whose encoding/decoding is not done --- openair2/COMMON/f1ap_messages_types.h | 14 ++------------ openair2/GNB_APP/gnb_app.c | 4 ---- openair2/GNB_APP/gnb_config.c | 1 - 3 files changed, 2 insertions(+), 17 deletions(-) diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index f2fd001e4e..54d12f4e2a 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -213,18 +213,8 @@ typedef struct f1ap_setup_resp_s { } f1ap_setup_resp_t; typedef struct f1ap_gnb_cu_configuration_update_s { - /* Connexion id used between SCTP/F1AP */ - uint16_t cnx_id; - - /* SCTP association id */ - sctp_assoc_t assoc_id; - - /* Number of SCTP streams used for a mme association */ - uint16_t sctp_in_streams; - uint16_t sctp_out_streams; - - /// string holding gNB_CU_name - char *gNB_CU_name; + /// Transaction ID + uint64_t transaction_id; /// number of DU cells to activate uint16_t num_cells_to_activate; //0< num_cells_to_activate/mod <= 512; served_cells_to_activate_t cells_to_activate[F1AP_MAX_NB_CELLS]; diff --git a/openair2/GNB_APP/gnb_app.c b/openair2/GNB_APP/gnb_app.c index 39946c95f1..64affd6c0a 100644 --- a/openair2/GNB_APP/gnb_app.c +++ b/openair2/GNB_APP/gnb_app.c @@ -236,10 +236,6 @@ void *gNB_app_task(void *args_p) case F1AP_GNB_CU_CONFIGURATION_UPDATE: AssertFatal(NODE_IS_DU(node_type), "Should not have received F1AP_GNB_CU_CONFIGURATION_UPDATE in CU/gNB\n"); - - LOG_I(GNB_APP, "Received %s: associated ngran_gNB_CU %s with %d cells to activate\n", ITTI_MSG_NAME (msg_p), - F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p).gNB_CU_name,F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p).num_cells_to_activate); - cell_to_activate += F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p).num_cells_to_activate; gNB_app_handle_f1ap_gnb_cu_configuration_update(&F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p)); diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 57e081b0e9..923a60f2eb 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -2367,7 +2367,6 @@ int gNB_app_handle_f1ap_gnb_cu_configuration_update(f1ap_gnb_cu_configuration_up ret++; mac->f1_config.setup_resp = malloc(sizeof(*mac->f1_config.setup_resp)); AssertFatal(mac->f1_config.setup_resp != NULL, "out of memory\n"); - mac->f1_config.setup_resp->gNB_CU_name = gnb_cu_cfg_update->gNB_CU_name; mac->f1_config.setup_resp->num_cells_to_activate = gnb_cu_cfg_update->num_cells_to_activate; mac->f1_config.setup_resp->cells_to_activate[0] = gnb_cu_cfg_update->cells_to_activate[0]; } else { From 8e3d6583a52162dafe86b3a5b839ffb172916cfe Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 9 Aug 2024 14:07:16 +0200 Subject: [PATCH 36/46] Add enc/dec library for F1AP gNB-CU Configuration Update (Interface Management) --- openair2/F1AP/lib/f1ap_interface_management.c | 140 +++++++++++++++++- openair2/F1AP/lib/f1ap_interface_management.h | 7 + 2 files changed, 145 insertions(+), 2 deletions(-) diff --git a/openair2/F1AP/lib/f1ap_interface_management.c b/openair2/F1AP/lib/f1ap_interface_management.c index 667fba31be..f29383faee 100644 --- a/openair2/F1AP/lib/f1ap_interface_management.c +++ b/openair2/F1AP/lib/f1ap_interface_management.c @@ -980,8 +980,7 @@ f1ap_setup_failure_t cp_f1ap_setup_failure(const f1ap_setup_failure_t *msg) */ F1AP_F1AP_PDU_t *encode_f1ap_du_configuration_update(const f1ap_gnb_du_configuration_update_t *msg) { - F1AP_F1AP_PDU_t *pdu = calloc(1, sizeof(*pdu)); - AssertFatal(pdu != NULL, "out of memory\n"); + F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); /* Create */ /* 0. Message Type */ pdu->present = F1AP_F1AP_PDU_PR_initiatingMessage; @@ -1291,3 +1290,140 @@ f1ap_gnb_du_configuration_update_t cp_f1ap_du_configuration_update(const f1ap_gn } return cp; } + +/* ==================================== + * F1AP gNB-CU Configuration Update + * ==================================== */ + +/** + * @brief F1 gNB-CU Configuration Update encoding (9.2.1.10 of 3GPP TS 38.473) + */ +F1AP_F1AP_PDU_t *encode_f1ap_cu_configuration_update(const f1ap_gnb_cu_configuration_update_t *msg) +{ + F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + /* Create + 0. Message Type */ + pdu->present = F1AP_F1AP_PDU_PR_initiatingMessage; + asn1cCalloc(pdu->choice.initiatingMessage, initMsg); + initMsg->procedureCode = F1AP_ProcedureCode_id_gNBCUConfigurationUpdate; + initMsg->criticality = F1AP_Criticality_reject; + initMsg->value.present = F1AP_InitiatingMessage__value_PR_GNBCUConfigurationUpdate; + F1AP_GNBCUConfigurationUpdate_t *cfgUpdate = &pdu->choice.initiatingMessage->value.choice.GNBCUConfigurationUpdate; + /* mandatory + c1. Transaction ID (integer value) */ + asn1cSequenceAdd(cfgUpdate->protocolIEs.list, F1AP_GNBCUConfigurationUpdateIEs_t, ieC1); + ieC1->id = F1AP_ProtocolIE_ID_id_TransactionID; + ieC1->criticality = F1AP_Criticality_reject; + ieC1->value.present = F1AP_GNBCUConfigurationUpdateIEs__value_PR_TransactionID; + ieC1->value.choice.TransactionID = msg->transaction_id; + /* optional + c2. Cells_to_be_Activated_List (O) */ + for (int i = 0; i < msg->num_cells_to_activate; i++) { + asn1cSequenceAdd(cfgUpdate->protocolIEs.list, F1AP_GNBCUConfigurationUpdateIEs_t, ieC3); + ieC3->id = F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List; + ieC3->criticality = F1AP_Criticality_reject; + ieC3->value.present = F1AP_GNBCUConfigurationUpdateIEs__value_PR_Cells_to_be_Activated_List; + asn1cSequenceAdd(ieC3->value.choice.Cells_to_be_Activated_List.list, + F1AP_Cells_to_be_Activated_List_ItemIEs_t, + cells_to_be_activated_ies); + encode_cells_to_activate(&msg->cells_to_activate[i], cells_to_be_activated_ies); + } + return pdu; +} + +/** + * @brief F1 gNB-CU Configuration Update decoding (9.2.1.10 of 3GPP TS 38.473) + */ +bool decode_f1ap_cu_configuration_update(const F1AP_F1AP_PDU_t *pdu, f1ap_gnb_cu_configuration_update_t *out) +{ + /* Check presence of message type */ + _F1_EQ_CHECK_INT(pdu->present, F1AP_F1AP_PDU_PR_initiatingMessage); + AssertError(pdu->choice.initiatingMessage != NULL, return false, "pdu->choice.initiatingMessage is NULL"); + _F1_EQ_CHECK_LONG(pdu->choice.initiatingMessage->procedureCode, F1AP_ProcedureCode_id_gNBCUConfigurationUpdate); + _F1_EQ_CHECK_INT(pdu->choice.initiatingMessage->value.present, F1AP_InitiatingMessage__value_PR_GNBCUConfigurationUpdate); + /* Check presence of mandatory IEs */ + F1AP_GNBCUConfigurationUpdate_t *in = &pdu->choice.initiatingMessage->value.choice.GNBCUConfigurationUpdate; + F1AP_GNBCUConfigurationUpdateIEs_t *ie; + F1AP_LIB_FIND_IE(F1AP_GNBCUConfigurationUpdateIEs_t, ie, in, F1AP_ProtocolIE_ID_id_TransactionID, true); + /* Loop over all IEs */ + for (int i = 0; i < in->protocolIEs.list.count; i++) { + ie = in->protocolIEs.list.array[i]; + switch (ie->id) { + case F1AP_ProtocolIE_ID_id_TransactionID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_GNBCUConfigurationUpdateIEs__value_PR_TransactionID); + AssertError(ie->value.choice.TransactionID != -1, return false, "ie->value.choice.TransactionID is -1"); + out->transaction_id = ie->value.choice.TransactionID; + break; + case F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List: { + /* Cells to be Activated List (O) */ + _F1_EQ_CHECK_INT(ie->value.present, F1AP_GNBCUConfigurationUpdateIEs__value_PR_Cells_to_be_Activated_List); + /* Cells to be Activated List Item (count >= 1) */ + F1AP_Cells_to_be_Activated_List_t *Cells_to_be_Activated_List = &ie->value.choice.Cells_to_be_Activated_List; + out->num_cells_to_activate = Cells_to_be_Activated_List->list.count; + AssertError(out->num_cells_to_activate > 0, return false, "At least 1 cell to activate must be present"); + for (int i = 0; i < out->num_cells_to_activate; i++) { + if (!decode_cells_to_activate(&out->cells_to_activate[i], + (F1AP_Cells_to_be_Activated_List_ItemIEs_t *)Cells_to_be_Activated_List->list.array[i])) + return false; + } + break; + } + default: + AssertError(1 == 0, return false, "F1AP_ProtocolIE_ID_id %ld unknown\n", ie->id); + break; + } + } + return true; +} + +void free_f1ap_cu_configuration_update(const f1ap_gnb_cu_configuration_update_t *msg) +{ + for (int i = 0; i < msg->num_cells_to_activate; i++) + for (int j = 0; j < msg->cells_to_activate[j].num_SI; j++) + free(msg->cells_to_activate[i].SI_msg[j].SI_container); +} + +/** + * @brief F1 gNB-CU Configuration Update check + */ +bool eq_f1ap_cu_configuration_update(const f1ap_gnb_cu_configuration_update_t *a, const f1ap_gnb_cu_configuration_update_t *b) +{ + _F1_EQ_CHECK_LONG(a->transaction_id, b->transaction_id); + /* to activate */ + _F1_EQ_CHECK_INT(a->num_cells_to_activate, b->num_cells_to_activate); + for (int i = 0; i < a->num_cells_to_activate; i++) { + _F1_EQ_CHECK_LONG(a->cells_to_activate[i].nr_cellid, b->cells_to_activate[i].nr_cellid); + _F1_EQ_CHECK_INT(a->cells_to_activate[i].nrpci, b->cells_to_activate[i].nrpci); + if (!eq_f1ap_plmn(&a->cells_to_activate[i].plmn, &b->cells_to_activate[i].plmn)) + return false; + _F1_EQ_CHECK_INT(a->cells_to_activate[i].num_SI, b->cells_to_activate[i].num_SI); + for (int s = 0; s < a->cells_to_activate[i].num_SI; s++) { + _F1_EQ_CHECK_INT(*a->cells_to_activate[i].SI_msg[s].SI_container, *a->cells_to_activate[i].SI_msg[s].SI_container); + _F1_EQ_CHECK_INT(a->cells_to_activate[i].SI_msg[s].SI_container_length, a->cells_to_activate[i].SI_msg[s].SI_container_length); + _F1_EQ_CHECK_INT(a->cells_to_activate[i].SI_msg[s].SI_type, a->cells_to_activate[i].SI_msg[s].SI_type); + } + } + return true; +} + +/** + * @brief F1 gNB-CU Configuration Update deep copy + */ +f1ap_gnb_cu_configuration_update_t cp_f1ap_cu_configuration_update(const f1ap_gnb_cu_configuration_update_t *msg) +{ + f1ap_gnb_cu_configuration_update_t cp = {0}; + /* transaction_id */ + cp.transaction_id = msg->transaction_id; + cp.num_cells_to_activate = msg->num_cells_to_activate; + for (int i = 0; i < cp.num_cells_to_activate; i++) { + cp.cells_to_activate[i] = msg->cells_to_activate[i]; + for (int s = 0; s < cp.cells_to_activate[i].num_SI; s++) { + cp.cells_to_activate[i].SI_msg[s] = msg->cells_to_activate[i].SI_msg[s]; + f1ap_sib_msg_t *SI_msg = &cp.cells_to_activate[i].SI_msg[s]; + SI_msg->SI_container = calloc_or_fail(SI_msg->SI_container_length, sizeof(*SI_msg->SI_container)); + for (int j = 0; j < SI_msg->SI_container_length; j++) + SI_msg->SI_container[j] = msg->cells_to_activate[i].SI_msg[s].SI_container[j]; + } + } + return cp; +} diff --git a/openair2/F1AP/lib/f1ap_interface_management.h b/openair2/F1AP/lib/f1ap_interface_management.h index aa7991488b..563524c26a 100644 --- a/openair2/F1AP/lib/f1ap_interface_management.h +++ b/openair2/F1AP/lib/f1ap_interface_management.h @@ -53,4 +53,11 @@ bool eq_f1ap_du_configuration_update(const f1ap_gnb_du_configuration_update_t *a f1ap_gnb_du_configuration_update_t cp_f1ap_du_configuration_update(const f1ap_gnb_du_configuration_update_t *msg); void free_f1ap_du_configuration_update(const f1ap_gnb_du_configuration_update_t *msg); +/* F1 gNB-CU Configuration Update */ +struct F1AP_F1AP_PDU *encode_f1ap_cu_configuration_update(const f1ap_gnb_cu_configuration_update_t *msg); +bool decode_f1ap_cu_configuration_update(const struct F1AP_F1AP_PDU *pdu, f1ap_gnb_cu_configuration_update_t *out); +bool eq_f1ap_cu_configuration_update(const f1ap_gnb_cu_configuration_update_t *a, const f1ap_gnb_cu_configuration_update_t *b); +f1ap_gnb_cu_configuration_update_t cp_f1ap_cu_configuration_update(const f1ap_gnb_cu_configuration_update_t *msg); +void free_f1ap_cu_configuration_update(const f1ap_gnb_cu_configuration_update_t *msg); + #endif /* F1AP_INTERFACE_MANAGEMENT_H_ */ From 3626366228e134671fa0edea3f5e40efdef937b4 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 29 May 2024 15:49:33 +0200 Subject: [PATCH 37/46] Add test for F1 gNB-CU Configuration Update enc/dec lib --- openair2/F1AP/tests/f1ap_lib_test.c | 38 +++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/openair2/F1AP/tests/f1ap_lib_test.c b/openair2/F1AP/tests/f1ap_lib_test.c index 6ccc814cfc..912ef52ff4 100644 --- a/openair2/F1AP/tests/f1ap_lib_test.c +++ b/openair2/F1AP/tests/f1ap_lib_test.c @@ -431,6 +431,43 @@ static void test_f1ap_du_configuration_update(void) free_f1ap_du_configuration_update(&orig); } +/** + * @brief Test F1 gNB-CU Configuration Update + */ +static void test_f1ap_cu_configuration_update(void) +{ + /* create message */ + f1ap_gnb_cu_configuration_update_t orig = {.transaction_id = 2, + .num_cells_to_activate = 1, + .cells_to_activate = {{.nr_cellid = 123456789, + .nrpci = 100, + .plmn = {.mcc = 001, .mnc = 01, .mnc_digit_length = 2}, + .num_SI = 1, + .SI_msg = {{ + .SI_type = 7, + .SI_container_length = 10, + .SI_container = malloc(sizeof(uint8_t) * 10), + }}}}}; + F1AP_F1AP_PDU_t *f1enc = encode_f1ap_cu_configuration_update(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + + f1ap_gnb_cu_configuration_update_t decoded = {0}; + bool ret = decode_f1ap_cu_configuration_update(f1dec, &decoded); + AssertFatal(ret, "decode_f1ap_setup_request(): could not decode message\n"); + f1ap_msg_free(f1dec); + + ret = eq_f1ap_cu_configuration_update(&orig, &decoded); + AssertFatal(ret, "eq_f1ap_setup_request(): decoded message doesn't match\n"); + free_f1ap_cu_configuration_update(&decoded); + + f1ap_gnb_cu_configuration_update_t cp = cp_f1ap_cu_configuration_update(&orig); + ret = eq_f1ap_cu_configuration_update(&orig, &cp); + AssertFatal(ret, "eq_f1ap_setup_request(): copied message doesn't match\n"); + free_f1ap_cu_configuration_update(&cp); + free_f1ap_cu_configuration_update(&orig); +} + int main() { test_initial_ul_rrc_message_transfer(); @@ -440,5 +477,6 @@ int main() test_f1ap_setup_response(); test_f1ap_setup_failure(); test_f1ap_du_configuration_update(); + test_f1ap_cu_configuration_update(); return 0; } From 80a05271d6f820edd7993f1f549fbb326a8e3d99 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Thu, 29 Aug 2024 23:54:13 +0200 Subject: [PATCH 38/46] Use F1AP gNB-CU Configuration Update lib in stack --- openair2/F1AP/f1ap_cu_interface_management.c | 102 ++----------- openair2/F1AP/f1ap_du_interface_management.c | 149 ++----------------- openair2/GNB_APP/gnb_app.c | 4 + openair2/GNB_APP/gnb_config.c | 3 + 4 files changed, 33 insertions(+), 225 deletions(-) diff --git a/openair2/F1AP/f1ap_cu_interface_management.c b/openair2/F1AP/f1ap_cu_interface_management.c index e6064c1502..df4bb2ecf1 100644 --- a/openair2/F1AP/f1ap_cu_interface_management.c +++ b/openair2/F1AP/f1ap_cu_interface_management.c @@ -189,99 +189,27 @@ int CU_send_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE( return 0; } -/* - gNB-CU Configuration Update -*/ - -int CU_send_gNB_CU_CONFIGURATION_UPDATE(sctp_assoc_t assoc_id, f1ap_gnb_cu_configuration_update_t *f1ap_gnb_cu_configuration_update) +/** + * @brief F1 gNB-CU Configuration Update message encoding and transfer + */ +int CU_send_gNB_CU_CONFIGURATION_UPDATE(sctp_assoc_t assoc_id, f1ap_gnb_cu_configuration_update_t *msg) { - F1AP_F1AP_PDU_t pdu= {0}; + /* complete F1AP message */ + msg->transaction_id = F1AP_get_next_transaction_identifier(0, 0); // note: has to be done in the caller uint8_t *buffer; uint32_t len; - /* Create */ - /* 0. Message Type */ - pdu.present = F1AP_F1AP_PDU_PR_initiatingMessage; - asn1cCalloc(pdu.choice.initiatingMessage, initMsg); - initMsg->procedureCode = F1AP_ProcedureCode_id_gNBCUConfigurationUpdate; - initMsg->criticality = F1AP_Criticality_reject; - initMsg->value.present = F1AP_InitiatingMessage__value_PR_GNBCUConfigurationUpdate; - F1AP_GNBCUConfigurationUpdate_t *cfgUpdate = &pdu.choice.initiatingMessage->value.choice.GNBCUConfigurationUpdate; - /* mandatory */ - /* c1. Transaction ID (integer value) */ - asn1cSequenceAdd(cfgUpdate->protocolIEs.list, F1AP_GNBCUConfigurationUpdateIEs_t, ieC1); - ieC1->id = F1AP_ProtocolIE_ID_id_TransactionID; - ieC1->criticality = F1AP_Criticality_reject; - ieC1->value.present = F1AP_GNBCUConfigurationUpdateIEs__value_PR_TransactionID; - ieC1->value.choice.TransactionID = F1AP_get_next_transaction_identifier(0, 0); - - // mandatory - // c2. Cells_to_be_Activated_List - if (f1ap_gnb_cu_configuration_update->num_cells_to_activate > 0) { - asn1cSequenceAdd(cfgUpdate->protocolIEs.list, F1AP_GNBCUConfigurationUpdateIEs_t, ieC3); - ieC3->id = F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List; - ieC3->criticality = F1AP_Criticality_reject; - ieC3->value.present = F1AP_GNBCUConfigurationUpdateIEs__value_PR_Cells_to_be_Activated_List; - - for (int i=0; inum_cells_to_activate; i++) { - asn1cSequenceAdd(ieC3->value.choice.Cells_to_be_Activated_List.list,F1AP_Cells_to_be_Activated_List_ItemIEs_t, - cells_to_be_activated_ies); - cells_to_be_activated_ies->id = F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List_Item; - cells_to_be_activated_ies->criticality = F1AP_Criticality_reject; - cells_to_be_activated_ies->value.present = F1AP_Cells_to_be_Activated_List_ItemIEs__value_PR_Cells_to_be_Activated_List_Item; - // 2.1 cells to be Activated list item - F1AP_Cells_to_be_Activated_List_Item_t *cells_to_be_activated_list_item= - &cells_to_be_activated_ies->value.choice.Cells_to_be_Activated_List_Item; - // - nRCGI - addnRCGI(cells_to_be_activated_list_item->nRCGI, f1ap_gnb_cu_configuration_update->cells_to_activate+i); - // optional - // -nRPCI - asn1cCalloc(cells_to_be_activated_list_item->nRPCI, tmp); - *tmp = f1ap_gnb_cu_configuration_update->cells_to_activate[i].nrpci; // int 0..1007 - // optional - // 3.1.2 gNB-CUSystem Information - F1AP_ProtocolExtensionContainer_10696P112_t *p = calloc(1,sizeof(*p)); - cells_to_be_activated_list_item->iE_Extensions = (struct F1AP_ProtocolExtensionContainer *) p; - //F1AP_ProtocolExtensionContainer_154P112_t - asn1cSequenceAdd(p->list, F1AP_Cells_to_be_Activated_List_ItemExtIEs_t, cells_to_be_activated_itemExtIEs); - cells_to_be_activated_itemExtIEs->id = F1AP_ProtocolIE_ID_id_gNB_CUSystemInformation; - cells_to_be_activated_itemExtIEs->criticality = F1AP_Criticality_reject; - cells_to_be_activated_itemExtIEs->extensionValue.present = F1AP_Cells_to_be_Activated_List_ItemExtIEs__extensionValue_PR_GNB_CUSystemInformation; - - if (f1ap_gnb_cu_configuration_update->cells_to_activate[i].num_SI > 0) { - F1AP_GNB_CUSystemInformation_t *gNB_CUSystemInformation = - &cells_to_be_activated_itemExtIEs->extensionValue.choice.GNB_CUSystemInformation; - //LOG_I(F1AP, "%s() SI %d size %d: ", __func__, i, f1ap_setup_resp->SI_container_length[i][0]); - //for (int n = 0; n < f1ap_setup_resp->SI_container_length[i][0]; n++) - // printf("%02x ", f1ap_setup_resp->SI_container[i][0][n]); - //printf("\n"); - - // for (int sIBtype=2;sIBtype<33;sIBtype++) { //21 ? 33 ? - for (int j = 0; j < sizeofArray(f1ap_gnb_cu_configuration_update->cells_to_activate[i].SI_msg); j++) { - f1ap_sib_msg_t *SI_msg = &f1ap_gnb_cu_configuration_update->cells_to_activate[i].SI_msg[j]; - if (SI_msg->SI_container != NULL) { - asn1cSequenceAdd(gNB_CUSystemInformation->sibtypetobeupdatedlist.list, F1AP_SibtypetobeupdatedListItem_t, sib_item); - sib_item->sIBtype = SI_msg->SI_type; - AssertFatal(sib_item->sIBtype < 6 || sib_item->sIBtype == 9, "Illegal SI type %ld\n", sib_item->sIBtype); - OCTET_STRING_fromBuf(&sib_item->sIBmessage, (const char *)SI_msg->SI_container, SI_msg->SI_container_length); - LOG_D(F1AP, - "f1ap_gnb_cu_configuration_update->SI_container_length[%d][sIBtype %ld] = %d \n", - i, - sib_item->sIBtype, - SI_msg->SI_container_length); - } - } - } - } - } - - /* encode */ - if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { - LOG_E(F1AP, "Failed to encode F1 gNB-CU CONFIGURATION UPDATE\n"); + /* Encode F1 gNB-CU Configuration Update message */ + F1AP_F1AP_PDU_t *pdu = encode_f1ap_cu_configuration_update(msg); + /* Free after encoding */ + free_f1ap_cu_configuration_update(msg); + /* Encode F1AP PDU */ + if (f1ap_encode_pdu(pdu, &buffer, &len) < 0) { + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); + LOG_E(F1AP, "Failed to encode F1 gNB-CU Configuration Update\n"); return -1; } - LOG_DUMPMSG(F1AP, LOG_DUMP_CHAR, buffer, len, "F1AP gNB-CU CONFIGURATION UPDATE : "); - ASN_STRUCT_RESET(asn_DEF_F1AP_F1AP_PDU, &pdu); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); return 0; } diff --git a/openair2/F1AP/f1ap_du_interface_management.c b/openair2/F1AP/f1ap_du_interface_management.c index 6104757816..cb2843c5f9 100644 --- a/openair2/F1AP/f1ap_du_interface_management.c +++ b/openair2/F1AP/f1ap_du_interface_management.c @@ -225,148 +225,21 @@ int DU_send_gNB_DU_CONFIGURATION_UPDATE(sctp_assoc_t assoc_id, f1ap_gnb_du_confi return 0; } +/** + * @brief F1 gNB-CU Configuration Update decoding and message transfer + */ int DU_handle_gNB_CU_CONFIGURATION_UPDATE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { LOG_D(F1AP, "DU_handle_gNB_CU_CONFIGURATION_UPDATE\n"); - AssertFatal(pdu->present == F1AP_F1AP_PDU_PR_initiatingMessage, - "pdu->present != F1AP_F1AP_PDU_PR_initiatingMessage\n"); - AssertFatal(pdu->choice.initiatingMessage->procedureCode == F1AP_ProcedureCode_id_gNBCUConfigurationUpdate, - "pdu->choice.initiatingMessage->procedureCode != F1AP_ProcedureCode_id_gNBCUConfigurationUpdate\n"); - AssertFatal(pdu->choice.initiatingMessage->criticality == F1AP_Criticality_reject, - "pdu->choice.initiatingMessage->criticality != F1AP_Criticality_reject\n"); - AssertFatal(pdu->choice.initiatingMessage->value.present == F1AP_InitiatingMessage__value_PR_GNBCUConfigurationUpdate, - "pdu->choice.initiatingMessage->value.present != F1AP_InitiatingMessage__value_PR_GNBCUConfigurationUpdate\n"); - F1AP_GNBCUConfigurationUpdate_t *in = &pdu->choice.initiatingMessage->value.choice.GNBCUConfigurationUpdate; - F1AP_GNBCUConfigurationUpdateIEs_t *ie; - int TransactionId = -1; - int num_cells_to_activate = 0; - F1AP_Cells_to_be_Activated_List_Item_t *cell; + f1ap_gnb_cu_configuration_update_t in = {0}; + if (!decode_f1ap_cu_configuration_update(pdu, &in)) { + LOG_E(F1AP, "Failed to decode F1AP Setup Failure\n"); + free_f1ap_cu_configuration_update(&in); + return -1; + } MessageDef *msg_p = itti_alloc_new_message (TASK_DU_F1, 0, F1AP_GNB_CU_CONFIGURATION_UPDATE); - LOG_D(F1AP, "F1AP: gNB_CU_Configuration_Update: protocolIEs.list.count %d\n", - in->protocolIEs.list.count); - - for (int i=0; i < in->protocolIEs.list.count; i++) { - ie = in->protocolIEs.list.array[i]; - - switch (ie->id) { - case F1AP_ProtocolIE_ID_id_TransactionID: - AssertFatal(ie->criticality == F1AP_Criticality_reject, - "ie->criticality != F1AP_Criticality_reject\n"); - AssertFatal(ie->value.present == F1AP_GNBCUConfigurationUpdateIEs__value_PR_TransactionID, - "ie->value.present != F1AP_GNBCUConfigurationUpdateIEs__value_PR_TransactionID\n"); - TransactionId=ie->value.choice.TransactionID; - LOG_D(F1AP, "F1AP: GNB-CU-ConfigurationUpdate: TransactionId %d\n", - TransactionId); - break; - - case F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List: { - AssertFatal(ie->criticality == F1AP_Criticality_reject, - "ie->criticality != F1AP_Criticality_reject\n"); - AssertFatal(ie->value.present == F1AP_GNBCUConfigurationUpdateIEs__value_PR_Cells_to_be_Activated_List, - "ie->value.present != F1AP_GNBCUConfigurationUpdateIEs__value_PR_Cells_to_be_Activated_List\n"); - num_cells_to_activate = ie->value.choice.Cells_to_be_Activated_List.list.count; - LOG_D(F1AP, "F1AP: Activating %d cells\n",num_cells_to_activate); - - for (int i=0; ivalue.choice.Cells_to_be_Activated_List.list.array[i]; - AssertFatal(cells_to_be_activated_list_item_ies->id == F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List_Item, - "cells_to_be_activated_list_item_ies->id != F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List_Item"); - AssertFatal(cells_to_be_activated_list_item_ies->criticality == F1AP_Criticality_reject, - "cells_to_be_activated_list_item_ies->criticality == F1AP_Criticality_reject"); - AssertFatal(cells_to_be_activated_list_item_ies->value.present == F1AP_Cells_to_be_Activated_List_ItemIEs__value_PR_Cells_to_be_Activated_List_Item, - "cells_to_be_activated_list_item_ies->value.present == F1AP_Cells_to_be_Activated_List_ItemIEs__value_PR_Cells_to_be_Activated_List_Item"); - cell = &cells_to_be_activated_list_item_ies->value.choice.Cells_to_be_Activated_List_Item; - TBCD_TO_MCC_MNC(&cell->nRCGI.pLMN_Identity, - F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p).cells_to_activate[i].plmn.mcc, - F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p).cells_to_activate[i].plmn.mnc, - F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p).cells_to_activate[i].plmn.mnc_digit_length); - LOG_D(F1AP, "nr_cellId : %x %x %x %x %x\n", - cell->nRCGI.nRCellIdentity.buf[0], - cell->nRCGI.nRCellIdentity.buf[1], - cell->nRCGI.nRCellIdentity.buf[2], - cell->nRCGI.nRCellIdentity.buf[3], - cell->nRCGI.nRCellIdentity.buf[4]); - BIT_STRING_TO_NR_CELL_IDENTITY(&cell->nRCGI.nRCellIdentity, - F1AP_GNB_CU_CONFIGURATION_UPDATE (msg_p).cells_to_activate[i].nr_cellid); - F1AP_ProtocolExtensionContainer_10696P112_t *ext = (F1AP_ProtocolExtensionContainer_10696P112_t *)cell->iE_Extensions; - - if (ext==NULL) - continue; - - for (int cnt=0; cntlist.count; cnt++) { - F1AP_Cells_to_be_Activated_List_ItemExtIEs_t *cells_to_be_activated_list_itemExtIEs=(F1AP_Cells_to_be_Activated_List_ItemExtIEs_t *)ext->list.array[cnt]; - - switch (cells_to_be_activated_list_itemExtIEs->id) { - /* - case F1AP_Cells_to_be_Activated_List_ItemExtIEs__extensionValue_PR_NOTHING: - case F1AP_Cells_to_be_Activated_List_ItemExtIEs__extensionValue_PR_GNB_CUSystemInformation, - case F1AP_Cells_to_be_Activated_List_ItemExtIEs__extensionValue_PR_AvailablePLMNList, - case F1AP_Cells_to_be_Activated_List_ItemExtIEs__extensionValue_PR_ExtendedAvailablePLMN_List, - case F1AP_Cells_to_be_Activated_List_ItemExtIEs__extensionValue_PR_IAB_Info_IAB_donor_CU, - case F1AP_Cells_to_be_Activated_List_ItemExtIEs__extensionValue_PR_AvailableSNPN_ID_List - */ - case F1AP_ProtocolIE_ID_id_gNB_CUSystemInformation: { - F1AP_GNB_CU_CONFIGURATION_UPDATE (msg_p).cells_to_activate[i].nrpci = (cell->nRPCI != NULL) ? *cell->nRPCI : 0; - F1AP_GNB_CUSystemInformation_t *gNB_CUSystemInformation = (F1AP_GNB_CUSystemInformation_t *)&cells_to_be_activated_list_itemExtIEs->extensionValue.choice.GNB_CUSystemInformation; - F1AP_GNB_CU_CONFIGURATION_UPDATE (msg_p).cells_to_activate[i].num_SI = gNB_CUSystemInformation->sibtypetobeupdatedlist.list.count; - AssertFatal(ext->list.count==1,"At least one SI message should be there, and only 1 for now!\n"); - LOG_D(F1AP, - "F1AP: Cell %d MCC %d MNC %d NRCellid %lx num_si %d\n", - i, - F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p).cells_to_activate[i].plmn.mcc, - F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p).cells_to_activate[i].plmn.mnc, - F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p).cells_to_activate[i].nr_cellid, - F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p).cells_to_activate[i].num_SI); - - for (int si = 0; si < gNB_CUSystemInformation->sibtypetobeupdatedlist.list.count; si++) { - F1AP_SibtypetobeupdatedListItem_t *sib_item = gNB_CUSystemInformation->sibtypetobeupdatedlist.list.array[si]; - size_t size = sib_item->sIBmessage.size; - f1ap_sib_msg_t *SI_msg = &F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p).cells_to_activate[i].SI_msg[si]; - SI_msg->SI_container_length = size; - LOG_D(F1AP, "F1AP: SI_container_length[%d][%ld] %ld bytes\n", i, sib_item->sIBtype, size); - SI_msg->SI_container = malloc(SI_msg->SI_container_length); - memcpy((void *)SI_msg->SI_container, (void *)sib_item->sIBmessage.buf, size); - SI_msg->SI_type = sib_item->sIBtype; - } - - break; - } - - case F1AP_ProtocolIE_ID_id_AvailablePLMNList: - AssertFatal(1==0,"F1AP_ProtocolIE_ID_id_AvailablePLMNList not supported yet\n"); - break; - - case F1AP_ProtocolIE_ID_id_ExtendedAvailablePLMN_List: - AssertFatal(1==0,"F1AP_ProtocolIE_ID_id_AvailablePLMNList not supported yet\n"); - break; - - case F1AP_ProtocolIE_ID_id_IAB_Info_IAB_donor_CU: - AssertFatal(1==0,"F1AP_ProtocolIE_ID_id_AvailablePLMNList not supported yet\n"); - break; - - case F1AP_ProtocolIE_ID_id_AvailableSNPN_ID_List: - AssertFatal(1==0,"F1AP_ProtocolIE_ID_id_AvailablePLMNList not supported yet\n"); - break; - - default: - AssertFatal(1==0,"F1AP_ProtocolIE_ID_id %d unknown\n",(int)cells_to_be_activated_list_itemExtIEs->id); - break; - } - } // for (cnt=... - } // for (cells_to_activate... - - break; - } // case F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List - - default: - AssertFatal(1==0,"F1AP_ProtocolIE_ID_id %d unknown\n", (int)ie->id); - break; - } // switch ie - } // for IE - - AssertFatal(TransactionId!=-1,"TransactionId was not sent\n"); - LOG_D(F1AP,"F1AP: num_cells_to_activate %d\n",num_cells_to_activate); - F1AP_GNB_CU_CONFIGURATION_UPDATE (msg_p).num_cells_to_activate = num_cells_to_activate; + f1ap_gnb_cu_configuration_update_t *msg = &F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p); // RRC thread will free it + *msg = in; // copy F1 message to ITTI LOG_D(F1AP, "Sending F1AP_GNB_CU_CONFIGURATION_UPDATE ITTI message \n"); itti_send_msg_to_task(TASK_GNB_APP, GNB_MODULE_ID_TO_INSTANCE(assoc_id), msg_p); return 0; diff --git a/openair2/GNB_APP/gnb_app.c b/openair2/GNB_APP/gnb_app.c index 64affd6c0a..caaf5d64e7 100644 --- a/openair2/GNB_APP/gnb_app.c +++ b/openair2/GNB_APP/gnb_app.c @@ -236,6 +236,10 @@ void *gNB_app_task(void *args_p) case F1AP_GNB_CU_CONFIGURATION_UPDATE: AssertFatal(NODE_IS_DU(node_type), "Should not have received F1AP_GNB_CU_CONFIGURATION_UPDATE in CU/gNB\n"); + LOG_I(GNB_APP, + "Received %s: associated with %d cells to activate\n", + ITTI_MSG_NAME(msg_p), + F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p).num_cells_to_activate); cell_to_activate += F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p).num_cells_to_activate; gNB_app_handle_f1ap_gnb_cu_configuration_update(&F1AP_GNB_CU_CONFIGURATION_UPDATE(msg_p)); diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 923a60f2eb..06d4318e97 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -94,6 +94,7 @@ #ifdef ENABLE_AERIAL #include "nfapi/oai_integration/aerial/fapi_vnf_p5.h" #endif +#include "lib/f1ap_interface_management.h" extern uint16_t sf_ahead; @@ -2375,6 +2376,8 @@ int gNB_app_handle_f1ap_gnb_cu_configuration_update(f1ap_gnb_cu_configuration_up } } NR_SCHED_UNLOCK(&mac->sched_lock); + /* Free F1AP struct after use */ + free_f1ap_cu_configuration_update(gnb_cu_cfg_update); MessageDef *msg_ack_p = NULL; if (ret > 0) { // generate gNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE From d2863d96935021468e93a31e5811716407f5a24c Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 9 Aug 2024 14:16:57 +0200 Subject: [PATCH 39/46] Refactored f1ap_gnb_cu_configuration_update_acknowledge_t * add transaction_id * refactored remaining members --- openair2/COMMON/f1ap_messages_types.h | 36 +++++++++++++++++++-------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index 54d12f4e2a..f159e63ca3 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -98,6 +98,11 @@ typedef struct f1ap_plmn_t { uint8_t mnc_digit_length; } f1ap_plmn_t; +typedef struct f1ap_cp_tnl_s { + in_addr_t tl_address; // currently only IPv4 supported + uint16_t port; +} f1ap_cp_tnl_t; + typedef enum f1ap_mode_t { F1AP_MODE_TDD = 0, F1AP_MODE_FDD = 1 } f1ap_mode_t; typedef struct f1ap_nr_frequency_info_t { @@ -229,22 +234,31 @@ typedef struct f1ap_setup_failure_s { } f1ap_setup_failure_t; typedef struct f1ap_gnb_cu_configuration_update_acknowledge_s { + uint64_t transaction_id; + // Cells Failed to be Activated List uint16_t num_cells_failed_to_be_activated; - f1ap_plmn_t plmn[F1AP_MAX_NB_CELLS]; - uint64_t nr_cellid[F1AP_MAX_NB_CELLS]; - uint16_t cause[F1AP_MAX_NB_CELLS]; + struct { + // NR CGI + f1ap_plmn_t plmn; + uint64_t nr_cellid; + uint16_t cause; + } cells_failed_to_be_activated[F1AP_MAX_NB_CELLS]; int have_criticality; - uint16_t criticality_diagnostics; + uint16_t criticality_diagnostics; + // gNB-CU TNL Association Setup List uint16_t noofTNLAssociations_to_setup; - uint16_t have_port[F1AP_MAX_NO_OF_TNL_ASSOCIATIONS]; - in_addr_t tl_address[F1AP_MAX_NO_OF_TNL_ASSOCIATIONS]; // currently only IPv4 supported + f1ap_cp_tnl_t tnlAssociations_to_setup[F1AP_MAX_NO_OF_TNL_ASSOCIATIONS]; + // gNB-CU TNL Association Failed to Setup List uint16_t noofTNLAssociations_failed; - in_addr_t tl_address_failed[F1AP_MAX_NO_OF_TNL_ASSOCIATIONS]; // currently only IPv4 supported - uint16_t cause_failed[F1AP_MAX_NO_OF_TNL_ASSOCIATIONS]; + f1ap_cp_tnl_t tnlAssociations_failed[F1AP_MAX_NO_OF_TNL_ASSOCIATIONS]; + // Dedicated SI Delivery Needed UE List uint16_t noofDedicatedSIDeliveryNeededUEs; - uint32_t gNB_CU_ue_id[F1AP_MAX_NO_UE_ID]; - f1ap_plmn_t ue_plmn[F1AP_MAX_NO_UE_ID]; - uint64_t ue_nr_cellid[F1AP_MAX_NO_UE_ID]; + struct { + uint32_t gNB_CU_ue_id; + // NR CGI + f1ap_plmn_t ue_plmn; + uint64_t ue_nr_cellid; + } dedicatedSIDeliveryNeededUEs[F1AP_MAX_NO_UE_ID]; } f1ap_gnb_cu_configuration_update_acknowledge_t; typedef struct f1ap_gnb_cu_configuration_update_failure_s { From 3724e84fed064ec3542369653528395072035d3c Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 9 Aug 2024 14:18:37 +0200 Subject: [PATCH 40/46] Add enc library for F1 gNB-CU Configuration Update Acknowledge (Interface Management) --- openair2/F1AP/lib/f1ap_interface_management.c | 190 ++++++++++++++++++ openair2/F1AP/lib/f1ap_interface_management.h | 3 + 2 files changed, 193 insertions(+) diff --git a/openair2/F1AP/lib/f1ap_interface_management.c b/openair2/F1AP/lib/f1ap_interface_management.c index f29383faee..7dad7452f7 100644 --- a/openair2/F1AP/lib/f1ap_interface_management.c +++ b/openair2/F1AP/lib/f1ap_interface_management.c @@ -1427,3 +1427,193 @@ f1ap_gnb_cu_configuration_update_t cp_f1ap_cu_configuration_update(const f1ap_gn } return cp; } + +/* ==================================== + * F1AP gNB-CU Configuration Ack + * ==================================== */ + +/** + * @brief F1 gNB-CU Configuration Update Acknowledge message encoding (9.2.1.11 of 3GPP TS 38.473) + * gNB-DU → gNB-CU + */ +F1AP_F1AP_PDU_t *encode_f1ap_cu_configuration_update_acknowledge(const f1ap_gnb_cu_configuration_update_acknowledge_t *msg) +{ + F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + /* Create */ + /* 0. pdu Type */ + pdu->present = F1AP_F1AP_PDU_PR_successfulOutcome; + asn1cCalloc(pdu->choice.successfulOutcome, tmp); + tmp->procedureCode = F1AP_ProcedureCode_id_gNBCUConfigurationUpdate; + tmp->criticality = F1AP_Criticality_reject; + tmp->value.present = F1AP_SuccessfulOutcome__value_PR_GNBCUConfigurationUpdateAcknowledge; + F1AP_GNBCUConfigurationUpdateAcknowledge_t *out = &tmp->value.choice.GNBCUConfigurationUpdateAcknowledge; + // Transaction ID (M) + asn1cSequenceAdd(out->protocolIEs.list, F1AP_GNBCUConfigurationUpdateAcknowledgeIEs_t, ie1); + ie1->id = F1AP_ProtocolIE_ID_id_TransactionID; + ie1->criticality = F1AP_Criticality_reject; + ie1->value.present = F1AP_GNBCUConfigurationUpdateAcknowledgeIEs__value_PR_TransactionID; + ie1->value.choice.TransactionID = msg->transaction_id; + // Cells Failed to be Activated List (0..1) + if (msg->num_cells_failed_to_be_activated > 0) { + asn1cSequenceAdd(out->protocolIEs.list, F1AP_GNBCUConfigurationUpdateAcknowledgeIEs_t, ie2); + ie2->id = F1AP_ProtocolIE_ID_id_Cells_Failed_to_be_Activated_List; + ie2->criticality = F1AP_Criticality_reject; + ie2->value.present = F1AP_GNBCUConfigurationUpdateAcknowledgeIEs__value_PR_Cells_Failed_to_be_Activated_List; + F1AP_Cells_Failed_to_be_Activated_List_t *failedCellsList = &ie2->value.choice.Cells_Failed_to_be_Activated_List; + for (int i = 0; i < msg->num_cells_failed_to_be_activated; i++) { + asn1cSequenceAdd(failedCellsList->list, F1AP_Cells_Failed_to_be_Activated_List_ItemIEs_t, failedCellIE); + failedCellIE->id = F1AP_ProtocolIE_ID_id_Cells_Failed_to_be_Activated_List_Item; + failedCellIE->criticality = F1AP_Criticality_reject; + failedCellIE->value.present = F1AP_Cells_Failed_to_be_Activated_List_ItemIEs__value_PR_Cells_Failed_to_be_Activated_List_Item; + F1AP_Cells_Failed_to_be_Activated_List_Item_t *p1 = &failedCellIE->value.choice.Cells_Failed_to_be_Activated_List_Item; + // Cause (M) + p1->cause.present = F1AP_Cause_PR_radioNetwork; + p1->cause.choice.radioNetwork = msg->cells_failed_to_be_activated[i].cause; + // NR CGI (M) + const f1ap_plmn_t *plmn = &msg->cells_failed_to_be_activated[i].plmn; + MCC_MNC_TO_PLMNID(plmn->mcc, plmn->mnc, plmn->mnc_digit_length, &(p1->nRCGI.pLMN_Identity)); + printf("plmn->mcc %d %d %d %ld \n", + p1->nRCGI.pLMN_Identity.buf[0], p1->nRCGI.pLMN_Identity.buf[1], p1->nRCGI.pLMN_Identity.buf[2], p1->nRCGI.pLMN_Identity.size); + NR_CELL_ID_TO_BIT_STRING(msg->cells_failed_to_be_activated[i].nr_cellid, &(p1->nRCGI.nRCellIdentity)); + } + } + return pdu; +} + +/** + * @brief F1 gNB-CU Configuration Update Acknowledge decoding (9.2.1.11 of 3GPP TS 38.473) + */ +bool decode_f1ap_cu_configuration_update_acknowledge(const F1AP_F1AP_PDU_t *pdu, + f1ap_gnb_cu_configuration_update_acknowledge_t *out) +{ + /* Message type */ + _F1_EQ_CHECK_INT(pdu->present, F1AP_F1AP_PDU_PR_successfulOutcome); + AssertError(pdu->choice.successfulOutcome != NULL, return false, "pdu->choice.successfulOutcome is NULL"); + _F1_EQ_CHECK_LONG(pdu->choice.successfulOutcome->procedureCode, F1AP_ProcedureCode_id_gNBCUConfigurationUpdate); + _F1_EQ_CHECK_INT(pdu->choice.successfulOutcome->value.present, + F1AP_SuccessfulOutcome__value_PR_GNBCUConfigurationUpdateAcknowledge); + /* payload */ + F1AP_GNBCUConfigurationUpdateAcknowledge_t *in = &pdu->choice.successfulOutcome->value.choice.GNBCUConfigurationUpdateAcknowledge; + F1AP_GNBCUConfigurationUpdateAcknowledgeIEs_t *ie; + /* Check mandatory IEs */ + F1AP_LIB_FIND_IE(F1AP_GNBCUConfigurationUpdateAcknowledgeIEs_t, ie, in, F1AP_ProtocolIE_ID_id_TransactionID, true); + /* Loop over all IEs */ + for (int i = 0; i < in->protocolIEs.list.count; i++) { + ie = in->protocolIEs.list.array[i]; + switch (ie->id) { + case F1AP_ProtocolIE_ID_id_TransactionID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_GNBCUConfigurationUpdateAcknowledgeIEs__value_PR_TransactionID); + AssertError(ie->value.choice.TransactionID != -1, return false, "ie->value.choice.TransactionID is -1"); + out->transaction_id = ie->value.choice.TransactionID; + break; + case F1AP_ProtocolIE_ID_id_Cells_Failed_to_be_Activated_List: { + /* Decode Cells Failed to be Activated List */ + _F1_EQ_CHECK_INT(ie->value.present, + F1AP_GNBCUConfigurationUpdateAcknowledgeIEs__value_PR_Cells_Failed_to_be_Activated_List); + F1AP_Cells_Failed_to_be_Activated_List_t *cell_fail_list = &ie->value.choice.Cells_Failed_to_be_Activated_List; + out->num_cells_failed_to_be_activated = cell_fail_list->list.count; + for (int j = 0; j < out->num_cells_failed_to_be_activated; j++) { + const F1AP_Cells_Failed_to_be_Activated_List_ItemIEs_t *itemIE = + (F1AP_Cells_Failed_to_be_Activated_List_ItemIEs_t *)cell_fail_list->list.array[j]; + const F1AP_Cells_Failed_to_be_Activated_List_Item_t *item = &itemIE->value.choice.Cells_Failed_to_be_Activated_List_Item; + // NR CGI (M) + f1ap_plmn_t *plmn = &out->cells_failed_to_be_activated[j].plmn; + TBCD_TO_MCC_MNC(&(item->nRCGI.pLMN_Identity), plmn->mcc, plmn->mnc, plmn->mnc_digit_length); + BIT_STRING_TO_NR_CELL_IDENTITY(&item->nRCGI.nRCellIdentity, out->cells_failed_to_be_activated[j].nr_cellid); + // Cause (M) + switch (item->cause.present) { + case F1AP_Cause_PR_radioNetwork: + out->cells_failed_to_be_activated[j].cause = item->cause.choice.radioNetwork; + break; + case F1AP_Cause_PR_transport: + out->cells_failed_to_be_activated[j].cause = item->cause.choice.transport; + break; + case F1AP_Cause_PR_protocol: + out->cells_failed_to_be_activated[j].cause = item->cause.choice.protocol; + break; + case F1AP_Cause_PR_misc: + out->cells_failed_to_be_activated[j].cause = item->cause.choice.misc; + break; + default: + AssertError(1 == 0, return false, "Unknown cause type %d\n", item->cause.present); + break; + } + } + break; + } + default: + AssertError(1 == 0, return false, "F1AP_ProtocolIE_ID_id %ld unknown\n", ie->id); + break; + } + } + return true; +} + +/** + * @brief F1 gNB-CU Configuration Update Acknowledge check + */ +bool eq_f1ap_cu_configuration_update_acknowledge(const f1ap_gnb_cu_configuration_update_acknowledge_t *a, + const f1ap_gnb_cu_configuration_update_acknowledge_t *b) +{ + // Transaction ID + _F1_EQ_CHECK_LONG(a->transaction_id, b->transaction_id); + // number of cells failed to be activated + _F1_EQ_CHECK_INT(a->num_cells_failed_to_be_activated, b->num_cells_failed_to_be_activated); + for (int i = 0; i < a->num_cells_failed_to_be_activated; i++) { + if (!eq_f1ap_plmn(&a->cells_failed_to_be_activated[i].plmn, &b->cells_failed_to_be_activated[i].plmn)) + return false; + _F1_EQ_CHECK_LONG(a->cells_failed_to_be_activated[i].nr_cellid, b->cells_failed_to_be_activated[i].nr_cellid); + _F1_EQ_CHECK_INT(a->cells_failed_to_be_activated[i].cause, b->cells_failed_to_be_activated[i].cause); + } + // TNL Associations to setup + _F1_EQ_CHECK_INT(a->noofTNLAssociations_to_setup, b->noofTNLAssociations_to_setup); + for (int i = 0; i < a->noofTNLAssociations_to_setup; i++) { + // Explicit comparison of TNL Association fields + _F1_EQ_CHECK_INT(a->tnlAssociations_to_setup[i].tl_address, b->tnlAssociations_to_setup[i].tl_address); + _F1_EQ_CHECK_INT(a->tnlAssociations_to_setup[i].port, b->tnlAssociations_to_setup[i].port); + } + // TNL Associations failed to setup + _F1_EQ_CHECK_INT(a->noofTNLAssociations_failed, b->noofTNLAssociations_failed); + for (int i = 0; i < a->noofTNLAssociations_failed; i++) { + // Explicit comparison of TNL Association fields + _F1_EQ_CHECK_INT(a->tnlAssociations_failed[i].tl_address, b->tnlAssociations_failed[i].tl_address); + _F1_EQ_CHECK_INT(a->tnlAssociations_failed[i].port, b->tnlAssociations_failed[i].port); + } + // Dedicated SI Delivery Needed UE List + _F1_EQ_CHECK_INT(a->noofDedicatedSIDeliveryNeededUEs, b->noofDedicatedSIDeliveryNeededUEs); + for (int i = 0; i < a->noofDedicatedSIDeliveryNeededUEs; i++) { + _F1_EQ_CHECK_INT(a->dedicatedSIDeliveryNeededUEs[i].gNB_CU_ue_id, b->dedicatedSIDeliveryNeededUEs[i].gNB_CU_ue_id); + if (!eq_f1ap_plmn(&a->dedicatedSIDeliveryNeededUEs[i].ue_plmn, &b->dedicatedSIDeliveryNeededUEs[i].ue_plmn)) + return false; + _F1_EQ_CHECK_LONG(a->dedicatedSIDeliveryNeededUEs[i].ue_nr_cellid, b->dedicatedSIDeliveryNeededUEs[i].ue_nr_cellid); + } + return true; +} + +/** + * @brief F1 gNB-CU Configuration Update Acknowledge deep copy + */ +f1ap_gnb_cu_configuration_update_acknowledge_t cp_f1ap_cu_configuration_update_acknowledge( + const f1ap_gnb_cu_configuration_update_acknowledge_t *msg) +{ + f1ap_gnb_cu_configuration_update_acknowledge_t cp = {0}; + // Transaction ID + cp.transaction_id = msg->transaction_id; + // number of cells failed to be activated + cp.num_cells_failed_to_be_activated = msg->num_cells_failed_to_be_activated; + for (int i = 0; i < cp.num_cells_failed_to_be_activated; i++) + cp.cells_failed_to_be_activated[i] = msg->cells_failed_to_be_activated[i]; + // TNL Associations to setup + cp.noofTNLAssociations_to_setup = msg->noofTNLAssociations_to_setup; + for (int i = 0; i < cp.noofTNLAssociations_to_setup; i++) + cp.tnlAssociations_to_setup[i] = msg->tnlAssociations_to_setup[i]; + // TNL Associations failed to setup + cp.noofTNLAssociations_failed = msg->noofTNLAssociations_failed; + for (int i = 0; i < cp.noofTNLAssociations_failed; i++) + cp.tnlAssociations_failed[i] = msg->tnlAssociations_failed[i]; + // Dedicated SI Delivery Needed UE List + cp.noofDedicatedSIDeliveryNeededUEs = msg->noofDedicatedSIDeliveryNeededUEs; + for (int i = 0; i < cp.noofDedicatedSIDeliveryNeededUEs; i++) + cp.dedicatedSIDeliveryNeededUEs[i] = msg->dedicatedSIDeliveryNeededUEs[i]; + return cp; +} diff --git a/openair2/F1AP/lib/f1ap_interface_management.h b/openair2/F1AP/lib/f1ap_interface_management.h index 563524c26a..b368b5576f 100644 --- a/openair2/F1AP/lib/f1ap_interface_management.h +++ b/openair2/F1AP/lib/f1ap_interface_management.h @@ -60,4 +60,7 @@ bool eq_f1ap_cu_configuration_update(const f1ap_gnb_cu_configuration_update_t *a f1ap_gnb_cu_configuration_update_t cp_f1ap_cu_configuration_update(const f1ap_gnb_cu_configuration_update_t *msg); void free_f1ap_cu_configuration_update(const f1ap_gnb_cu_configuration_update_t *msg); +/* F1 gNB-CU Configuration Update Acknowledge */ +struct F1AP_F1AP_PDU *encode_f1ap_cu_configuration_update_acknowledge(const f1ap_gnb_cu_configuration_update_acknowledge_t *msg); + #endif /* F1AP_INTERFACE_MANAGEMENT_H_ */ From c936aabd9a517a7eaad94267d9bd8c894339a849 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 30 Aug 2024 00:29:44 +0200 Subject: [PATCH 41/46] Add test for CU Configuration Update Acknowledge lib --- openair2/F1AP/tests/f1ap_lib_test.c | 35 +++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/openair2/F1AP/tests/f1ap_lib_test.c b/openair2/F1AP/tests/f1ap_lib_test.c index 912ef52ff4..878c7fad78 100644 --- a/openair2/F1AP/tests/f1ap_lib_test.c +++ b/openair2/F1AP/tests/f1ap_lib_test.c @@ -468,6 +468,40 @@ static void test_f1ap_cu_configuration_update(void) free_f1ap_cu_configuration_update(&orig); } +/** + * @brief Test F1 gNB-CU Configuration Update Acknowledge + */ +static void test_f1ap_cu_configuration_update_acknowledge(void) +{ + // Create the original message + f1ap_gnb_cu_configuration_update_acknowledge_t orig = { + .transaction_id = 2, + .num_cells_failed_to_be_activated = 1, + .cells_failed_to_be_activated = {{.nr_cellid = 123456789, + .plmn = {.mcc = 001, .mnc = 01, .mnc_digit_length = 2}, + .cause = F1AP_CAUSE_RADIO_NETWORK}} + }; + // F1AP Enc/dec + F1AP_F1AP_PDU_t *f1enc = encode_f1ap_cu_configuration_update_acknowledge(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + // Decoding + f1ap_gnb_cu_configuration_update_acknowledge_t decoded = {0}; + bool ret = decode_f1ap_cu_configuration_update_acknowledge(f1dec, &decoded); + AssertFatal(ret, "decode_f1ap_cu_configuration_update_acknowledge(): could not decode message\n"); + f1ap_msg_free(f1dec); + // Equality check + ret = eq_f1ap_cu_configuration_update_acknowledge(&orig, &decoded); + AssertFatal(ret, "eq_f1ap_cu_configuration_update_acknowledge(): decoded message doesn't match\n"); + // No free needed + // Deep copy + f1ap_gnb_cu_configuration_update_acknowledge_t cp = cp_f1ap_cu_configuration_update_acknowledge(&orig); + // Equality check + ret = eq_f1ap_cu_configuration_update_acknowledge(&orig, &cp); + AssertFatal(ret, "eq_f1ap_cu_configuration_update_acknowledge(): copied message doesn't match\n"); + // No free needed +} + int main() { test_initial_ul_rrc_message_transfer(); @@ -478,5 +512,6 @@ int main() test_f1ap_setup_failure(); test_f1ap_du_configuration_update(); test_f1ap_cu_configuration_update(); + test_f1ap_cu_configuration_update_acknowledge(); return 0; } From 3ce1f0e2c55a4fe20da693262fadfdbf5e0c8105 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 29 May 2024 21:38:59 +0200 Subject: [PATCH 42/46] Use F1 gNB-CU Configuration Update Acknowledge lib in stack --- openair2/F1AP/f1ap_cu_interface_management.c | 22 ++++++++- openair2/F1AP/f1ap_du_interface_management.c | 52 +++++--------------- openair2/GNB_APP/gnb_config.c | 1 + openair2/RRC/NR/rrc_gNB.c | 6 +++ 4 files changed, 40 insertions(+), 41 deletions(-) diff --git a/openair2/F1AP/f1ap_cu_interface_management.c b/openair2/F1AP/f1ap_cu_interface_management.c index df4bb2ecf1..cd408c6720 100644 --- a/openair2/F1AP/f1ap_cu_interface_management.c +++ b/openair2/F1AP/f1ap_cu_interface_management.c @@ -214,11 +214,29 @@ int CU_send_gNB_CU_CONFIGURATION_UPDATE(sctp_assoc_t assoc_id, f1ap_gnb_cu_confi return 0; } +/** + * @brief gNB CU Configuration Update Acknowledge decoding (9.2.1.11 of 3GPP TS 38.473) + * and handling by CU + */ int CU_handle_gNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) { - LOG_I(F1AP,"Cell Configuration ok (assoc_id %d)\n",assoc_id); - return(0); + DevAssert(pdu != NULL); + if (stream != 0) + LOG_W(F1AP, "[SCTP %d] Received gNB CU Configuration Update Acknowledge on stream != 0 (%d)\n", assoc_id, stream); + // Decode + f1ap_gnb_cu_configuration_update_acknowledge_t msg = {0}; + if (!decode_f1ap_cu_configuration_update_acknowledge(pdu, &msg)) { + LOG_E(F1AP, "Failed to decode gNB CU Configuration Update Acknowledge\n"); + return -1; + } + // Allocate ITTI message and send to RRC + MessageDef *message_p = itti_alloc_new_message(TASK_CU_F1, 0, F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE); + message_p->ittiMsgHeader.originInstance = assoc_id; + f1ap_gnb_cu_configuration_update_acknowledge_t *ack = &F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(message_p); + *ack = msg; // copy decoded message to ITTI, the RRC thread will free it + itti_send_msg_to_task(TASK_RRC_GNB, GNB_MODULE_ID_TO_INSTANCE(instance), message_p); + return 0; } diff --git a/openair2/F1AP/f1ap_du_interface_management.c b/openair2/F1AP/f1ap_du_interface_management.c index cb2843c5f9..391f9164eb 100644 --- a/openair2/F1AP/f1ap_du_interface_management.c +++ b/openair2/F1AP/f1ap_du_interface_management.c @@ -251,48 +251,22 @@ int DU_send_gNB_CU_CONFIGURATION_UPDATE_FAILURE(sctp_assoc_t assoc_id, GNBCUConfigurationUpdateFailure->cause); } -int DU_send_gNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE( - sctp_assoc_t assoc_id, - f1ap_gnb_cu_configuration_update_acknowledge_t *GNBCUConfigurationUpdateAcknowledge) +/** + * @brief Encode and transfer F1 GNB CU Configuration Update Acknowledge message + */ +int DU_send_gNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(sctp_assoc_t assoc_id, f1ap_gnb_cu_configuration_update_acknowledge_t *msg) { - AssertFatal(GNBCUConfigurationUpdateAcknowledge->num_cells_failed_to_be_activated == 0, - "%d cells failed to activate\n", - GNBCUConfigurationUpdateAcknowledge->num_cells_failed_to_be_activated); - AssertFatal(GNBCUConfigurationUpdateAcknowledge->noofTNLAssociations_to_setup == 0, - "%d TNLAssociations to setup, handle this ...\n", - GNBCUConfigurationUpdateAcknowledge->noofTNLAssociations_to_setup); - AssertFatal(GNBCUConfigurationUpdateAcknowledge->noofTNLAssociations_failed == 0, - "%d TNLAssociations failed\n", - GNBCUConfigurationUpdateAcknowledge->noofTNLAssociations_failed); - AssertFatal(GNBCUConfigurationUpdateAcknowledge->noofDedicatedSIDeliveryNeededUEs == 0, - "%d DedicatedSIDeliveryNeededUEs\n", - GNBCUConfigurationUpdateAcknowledge->noofDedicatedSIDeliveryNeededUEs); - F1AP_F1AP_PDU_t pdu= {0}; - uint8_t *buffer=NULL; - uint32_t len=0; - /* Create */ - /* 0. pdu Type */ - pdu.present = F1AP_F1AP_PDU_PR_successfulOutcome; - asn1cCalloc(pdu.choice.successfulOutcome, tmp); - tmp->procedureCode = F1AP_ProcedureCode_id_gNBCUConfigurationUpdate; - tmp->criticality = F1AP_Criticality_reject; - tmp->value.present = F1AP_SuccessfulOutcome__value_PR_GNBCUConfigurationUpdateAcknowledge; - F1AP_GNBCUConfigurationUpdateAcknowledge_t *out = &tmp->value.choice.GNBCUConfigurationUpdateAcknowledge; - /* mandatory */ - /* c1. Transaction ID (integer value)*/ - asn1cSequenceAdd(out->protocolIEs.list, F1AP_GNBCUConfigurationUpdateAcknowledgeIEs_t, ie); - ie->id = F1AP_ProtocolIE_ID_id_TransactionID; - ie->criticality = F1AP_Criticality_reject; - ie->value.present = F1AP_GNBCUConfigurationUpdateAcknowledgeIEs__value_PR_TransactionID; - ie->value.choice.TransactionID = F1AP_get_next_transaction_identifier(0, 0); - - /* encode */ - if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { - LOG_E(F1AP, "Failed to encode GNB-DU-Configuration-Update-Acknowledge\n"); + uint8_t *buffer = NULL; + uint32_t len = 0; + /* encode F1 message */ + F1AP_F1AP_PDU_t *pdu = encode_f1ap_cu_configuration_update_acknowledge(msg); + /* encode F1AP PDU */ + if (!pdu || f1ap_encode_pdu(pdu, &buffer, &len) < 0) { + LOG_E(F1AP, "Failed to encode GNB-CU-Configuration-Update-Acknowledge\n"); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); return -1; } - - ASN_STRUCT_RESET(asn_DEF_F1AP_F1AP_PDU, &pdu); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); return 0; } diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 06d4318e97..5e07d15f4c 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -2387,6 +2387,7 @@ int gNB_app_handle_f1ap_gnb_cu_configuration_update(f1ap_gnb_cu_configuration_up F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(msg_ack_p).noofTNLAssociations_to_setup =0; F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(msg_ack_p).noofTNLAssociations_failed = 0; F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(msg_ack_p).noofDedicatedSIDeliveryNeededUEs = 0; + F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(msg_ack_p).transaction_id = F1AP_get_next_transaction_identifier(0, 0); itti_send_msg_to_task (TASK_DU_F1, INSTANCE_DEFAULT, msg_ack_p); } diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c index 53b158aac0..c1c78943e5 100644 --- a/openair2/RRC/NR/rrc_gNB.c +++ b/openair2/RRC/NR/rrc_gNB.c @@ -2512,6 +2512,12 @@ void *rrc_gnb_task(void *args_p) { rrc_gNB_process_f1_du_configuration_update(&F1AP_GNB_DU_CONFIGURATION_UPDATE(msg_p), msg_p->ittiMsgHeader.originInstance); break; + case F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE: + AssertFatal(!NODE_IS_DU(RC.nrrrc[instance]->node_type), + "should not receive F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE in DU!\n"); + LOG_E(NR_RRC, "Handling of F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE not implemented\n"); + break; + /* Messages from X2AP */ case X2AP_ENDC_SGNB_ADDITION_REQ: LOG_I(NR_RRC, "Received ENDC sgNB addition request from X2AP \n"); From b91e1b0a12e97b2b898e2987372149ad1dc687e4 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 29 May 2024 22:51:57 +0200 Subject: [PATCH 43/46] Add enc/dec lib for F1AP gNB-DU Configuration Update Acknowledge (Interface Management) --- openair2/F1AP/lib/f1ap_interface_management.c | 148 ++++++++++++++++++ openair2/F1AP/lib/f1ap_interface_management.h | 16 ++ 2 files changed, 164 insertions(+) diff --git a/openair2/F1AP/lib/f1ap_interface_management.c b/openair2/F1AP/lib/f1ap_interface_management.c index 7dad7452f7..cb0b6ab8aa 100644 --- a/openair2/F1AP/lib/f1ap_interface_management.c +++ b/openair2/F1AP/lib/f1ap_interface_management.c @@ -1617,3 +1617,151 @@ f1ap_gnb_cu_configuration_update_acknowledge_t cp_f1ap_cu_configuration_update_a cp.dedicatedSIDeliveryNeededUEs[i] = msg->dedicatedSIDeliveryNeededUEs[i]; return cp; } + +/* ================================== + * F1AP gNB-DU Configuration Ack + * ================================== */ + +/** + * @brief F1 gNB-DU Configuration Update Acknowledge message encoding (9.2.1.8 of 3GPP TS 38.473) + */ +F1AP_F1AP_PDU_t *encode_f1ap_du_configuration_update_acknowledge(const f1ap_gnb_du_configuration_update_acknowledge_t *msg) +{ + F1AP_F1AP_PDU_t *pdu = calloc_or_fail(1, sizeof(*pdu)); + /* Create */ + /* 0. Message */ + pdu->present = F1AP_F1AP_PDU_PR_successfulOutcome; + asn1cCalloc(pdu->choice.successfulOutcome, succOut); + succOut->procedureCode = F1AP_ProcedureCode_id_gNBDUConfigurationUpdate; + succOut->criticality = F1AP_Criticality_reject; + succOut->value.present = F1AP_SuccessfulOutcome__value_PR_GNBDUConfigurationUpdateAcknowledge; + F1AP_GNBDUConfigurationUpdateAcknowledge_t *ack = &succOut->value.choice.GNBDUConfigurationUpdateAcknowledge; + /* Mandatory */ + /* Transaction Id */ + asn1cSequenceAdd(ack->protocolIEs.list, F1AP_GNBDUConfigurationUpdateAcknowledgeIEs_t, ie1); + ie1->id = F1AP_ProtocolIE_ID_id_TransactionID; + ie1->criticality = F1AP_Criticality_reject; + ie1->value.present = F1AP_GNBDUConfigurationUpdateAcknowledgeIEs__value_PR_TransactionID; + ie1->value.choice.TransactionID = msg->transaction_id; + // Cells to be Activated List (O) + for (int i = 0; i < msg->num_cells_to_activate; i++) { + asn1cSequenceAdd(ack->protocolIEs.list, F1AP_GNBDUConfigurationUpdateAcknowledgeIEs_t, ie3); + ie3->id = F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List; + ie3->criticality = F1AP_Criticality_reject; + ie3->value.present = F1AP_GNBDUConfigurationUpdateAcknowledgeIEs__value_PR_Cells_to_be_Activated_List; + asn1cSequenceAdd(ie3->value.choice.Cells_to_be_Activated_List.list, + F1AP_Cells_to_be_Activated_List_ItemIEs_t, + cells_to_be_activated_ies); + encode_cells_to_activate(&msg->cells_to_activate[i], cells_to_be_activated_ies); + } + return pdu; +} + +/** + * @brief F1 gNB-DU Configuration Update Acknowledge decoding + */ +bool decode_f1ap_du_configuration_update_acknowledge(const F1AP_F1AP_PDU_t *pdu, + f1ap_gnb_du_configuration_update_acknowledge_t *out) +{ + /* message type */ + _F1_EQ_CHECK_INT(pdu->present, F1AP_F1AP_PDU_PR_successfulOutcome); + AssertError(pdu->choice.successfulOutcome != NULL, return false, "pdu->choice.successfulOutcome is NULL"); + _F1_EQ_CHECK_LONG(pdu->choice.successfulOutcome->procedureCode, F1AP_ProcedureCode_id_gNBDUConfigurationUpdate); + _F1_EQ_CHECK_INT(pdu->choice.successfulOutcome->value.present, + F1AP_SuccessfulOutcome__value_PR_GNBDUConfigurationUpdateAcknowledge); + F1AP_GNBDUConfigurationUpdateAcknowledge_t *in = &pdu->choice.successfulOutcome->value.choice.GNBDUConfigurationUpdateAcknowledge; + F1AP_GNBDUConfigurationUpdateAcknowledgeIEs_t *ie; + /* Check mandatory IEs */ + F1AP_LIB_FIND_IE(F1AP_GNBDUConfigurationUpdateAcknowledgeIEs_t, ie, in, F1AP_ProtocolIE_ID_id_TransactionID, true); + /* Loop over all IEs */ + for (int i = 0; i < in->protocolIEs.list.count; i++) { + ie = in->protocolIEs.list.array[i]; + switch (ie->id) { + case F1AP_ProtocolIE_ID_id_TransactionID: + _F1_EQ_CHECK_INT(ie->value.present, F1AP_GNBDUConfigurationUpdateAcknowledgeIEs__value_PR_TransactionID); + AssertError(ie->value.choice.TransactionID != -1, return false, "ie->value.choice.TransactionID is -1"); + out->transaction_id = ie->value.choice.TransactionID; + break; + case F1AP_ProtocolIE_ID_id_Cells_to_be_Activated_List: { + /* Decode Cells Failed to be Activated List */ + _F1_EQ_CHECK_INT(ie->value.present, F1AP_GNBDUConfigurationUpdateAcknowledgeIEs__value_PR_Cells_to_be_Activated_List); + F1AP_Cells_to_be_Activated_List_t *list = &ie->value.choice.Cells_to_be_Activated_List; + out->num_cells_to_activate = list->list.count; + for (int j = 0; j < out->num_cells_to_activate; j++) { + const F1AP_Cells_to_be_Activated_List_ItemIEs_t *itemIE = + (F1AP_Cells_to_be_Activated_List_ItemIEs_t *)list->list.array[j]; + decode_cells_to_activate(&out->cells_to_activate[0], itemIE); + } + break; + } + default: + AssertError(1 == 0, return false, "F1AP_ProtocolIE_ID_id %ld unknown\n", ie->id); + break; + } + } + return true; +} + +/** + * @brief F1 gNB-DU Configuration Update Acknowledge equality check + */ +bool eq_f1ap_du_configuration_update_acknowledge(const f1ap_gnb_du_configuration_update_acknowledge_t *a, + const f1ap_gnb_du_configuration_update_acknowledge_t *b) +{ + // Transaction ID + _F1_EQ_CHECK_LONG(a->transaction_id, b->transaction_id); + // number of cells to activate + _F1_EQ_CHECK_INT(a->num_cells_to_activate, b->num_cells_to_activate); + // loop over cells to activate + for (int i = 0; i < a->num_cells_to_activate; i++) { + _F1_EQ_CHECK_LONG(a->cells_to_activate[i].nr_cellid, b->cells_to_activate[i].nr_cellid); + _F1_EQ_CHECK_INT(a->cells_to_activate[i].nrpci, b->cells_to_activate[i].nrpci); + if (!eq_f1ap_plmn(&a->cells_to_activate[i].plmn, &b->cells_to_activate[i].plmn)) + return false; + _F1_EQ_CHECK_INT(a->cells_to_activate[i].num_SI, b->cells_to_activate[i].num_SI); + for (int s = 0; s < a->cells_to_activate[i].num_SI; s++) { + _F1_EQ_CHECK_INT(*a->cells_to_activate[i].SI_msg[s].SI_container, *b->cells_to_activate[i].SI_msg[s].SI_container); + _F1_EQ_CHECK_INT(a->cells_to_activate[i].SI_msg[s].SI_container_length, + b->cells_to_activate[i].SI_msg[s].SI_container_length); + _F1_EQ_CHECK_INT(a->cells_to_activate[i].SI_msg[s].SI_type, b->cells_to_activate[i].SI_msg[s].SI_type); + } + } + return true; +} + +/** + * @brief F1 gNB-DU Configuration Update Acknowledge deep copy + */ +f1ap_gnb_du_configuration_update_acknowledge_t cp_f1ap_du_configuration_update_acknowledge( + const f1ap_gnb_du_configuration_update_acknowledge_t *msg) +{ + f1ap_gnb_du_configuration_update_acknowledge_t cp = {0}; + // Transaction ID + cp.transaction_id = msg->transaction_id; + // number of cells to activate + cp.num_cells_to_activate = msg->num_cells_to_activate; + // Loop through cells to activate + for (int i = 0; i < cp.num_cells_to_activate; i++) { + cp.cells_to_activate[i] = msg->cells_to_activate[i]; + for (int s = 0; s < cp.cells_to_activate[i].num_SI; s++) { + cp.cells_to_activate[i].SI_msg[s].SI_container = calloc_or_fail(1, sizeof(*cp.cells_to_activate[i].SI_msg[s].SI_container)); + *cp.cells_to_activate[i].SI_msg[s].SI_container = *msg->cells_to_activate[i].SI_msg[s].SI_container; + } + } + return cp; +} + +/** + * @brief gNB-DU Configuration Update Acknowledge memory management + */ +void free_f1ap_du_configuration_update_acknowledge(const f1ap_gnb_du_configuration_update_acknowledge_t *msg) +{ + // SI_container + for (int i = 0; i < msg->num_cells_to_activate; i++) { + for (int j = 0; j < msg->cells_to_activate[i].num_SI; j++) { + if (msg->cells_to_activate[i].SI_msg[j].SI_container) { + free(msg->cells_to_activate[i].SI_msg[j].SI_container); + } + } + } +} diff --git a/openair2/F1AP/lib/f1ap_interface_management.h b/openair2/F1AP/lib/f1ap_interface_management.h index b368b5576f..bdceee9a61 100644 --- a/openair2/F1AP/lib/f1ap_interface_management.h +++ b/openair2/F1AP/lib/f1ap_interface_management.h @@ -62,5 +62,21 @@ void free_f1ap_cu_configuration_update(const f1ap_gnb_cu_configuration_update_t /* F1 gNB-CU Configuration Update Acknowledge */ struct F1AP_F1AP_PDU *encode_f1ap_cu_configuration_update_acknowledge(const f1ap_gnb_cu_configuration_update_acknowledge_t *msg); +bool decode_f1ap_cu_configuration_update_acknowledge(const struct F1AP_F1AP_PDU *pdu, + f1ap_gnb_cu_configuration_update_acknowledge_t *out); +bool eq_f1ap_cu_configuration_update_acknowledge(const f1ap_gnb_cu_configuration_update_acknowledge_t *a, + const f1ap_gnb_cu_configuration_update_acknowledge_t *b); +f1ap_gnb_cu_configuration_update_acknowledge_t cp_f1ap_cu_configuration_update_acknowledge( + const f1ap_gnb_cu_configuration_update_acknowledge_t *msg); + +/* F1 gNB-DU Configuration Update Acknowledge */ +struct F1AP_F1AP_PDU *encode_f1ap_du_configuration_update_acknowledge(const f1ap_gnb_du_configuration_update_acknowledge_t *msg); +bool decode_f1ap_du_configuration_update_acknowledge(const struct F1AP_F1AP_PDU *pdu, + f1ap_gnb_du_configuration_update_acknowledge_t *out); +bool eq_f1ap_du_configuration_update_acknowledge(const f1ap_gnb_du_configuration_update_acknowledge_t *a, + const f1ap_gnb_du_configuration_update_acknowledge_t *b); +f1ap_gnb_du_configuration_update_acknowledge_t cp_f1ap_du_configuration_update_acknowledge( + const f1ap_gnb_du_configuration_update_acknowledge_t *msg); +void free_f1ap_du_configuration_update_acknowledge(const f1ap_gnb_du_configuration_update_acknowledge_t *msg); #endif /* F1AP_INTERFACE_MANAGEMENT_H_ */ From b8ee622f1c2b532c44e6fd0fc56f884f000ed534 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 30 Aug 2024 00:29:19 +0200 Subject: [PATCH 44/46] Add test for F1 DU Configuration Update Acknowledge lib --- openair2/F1AP/tests/f1ap_lib_test.c | 47 +++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/openair2/F1AP/tests/f1ap_lib_test.c b/openair2/F1AP/tests/f1ap_lib_test.c index 878c7fad78..969efc5afa 100644 --- a/openair2/F1AP/tests/f1ap_lib_test.c +++ b/openair2/F1AP/tests/f1ap_lib_test.c @@ -431,6 +431,52 @@ static void test_f1ap_du_configuration_update(void) free_f1ap_du_configuration_update(&orig); } +/** + * @brief Test F1 gNB-DU Configuration Update Acknowledge + */ +static void test_f1ap_du_configuration_update_acknowledge(void) +{ + // Create message + f1ap_gnb_du_configuration_update_acknowledge_t orig = { + .transaction_id = 5, + .num_cells_to_activate = 1, + .cells_to_activate = {{ + .nr_cellid = 987654321, + .nrpci = 50, + .plmn = {.mcc = 001, .mnc = 01, .mnc_digit_length = 2}, + .num_SI = 1, + .SI_msg = {{ + .SI_type = 7, + .SI_container_length = 10, + .SI_container = malloc(sizeof(uint8_t) * 10), + }}, + }}, + }; + for (int i = 0; i < orig.cells_to_activate[0].SI_msg[0].SI_container_length; i++) { + orig.cells_to_activate[0].SI_msg[0].SI_container[i] = i; + } + // ASN.1 enc/dec + F1AP_F1AP_PDU_t *f1enc = encode_f1ap_du_configuration_update_acknowledge(&orig); + F1AP_F1AP_PDU_t *f1dec = f1ap_encode_decode(f1enc); + f1ap_msg_free(f1enc); + // Decoding + f1ap_gnb_du_configuration_update_acknowledge_t decoded = {0}; + bool ret = decode_f1ap_du_configuration_update_acknowledge(f1dec, &decoded); + AssertFatal(ret, "decode_f1ap_du_configuration_update_acknowledge(): could not decode message\n"); + f1ap_msg_free(f1dec); + // Equality check + ret = eq_f1ap_du_configuration_update_acknowledge(&orig, &decoded); + AssertFatal(ret, "eq_f1ap_du_configuration_update_acknowledge(): decoded message doesn't match\n"); + free_f1ap_du_configuration_update_acknowledge(&decoded); + // Deep copy + f1ap_gnb_du_configuration_update_acknowledge_t cp = cp_f1ap_du_configuration_update_acknowledge(&orig); + ret = eq_f1ap_du_configuration_update_acknowledge(&orig, &cp); + AssertFatal(ret, "eq_f1ap_du_configuration_update_acknowledge(): copied message doesn't match\n"); + // Free + free_f1ap_du_configuration_update_acknowledge(&cp); + free_f1ap_du_configuration_update_acknowledge(&orig); +} + /** * @brief Test F1 gNB-CU Configuration Update */ @@ -513,5 +559,6 @@ int main() test_f1ap_du_configuration_update(); test_f1ap_cu_configuration_update(); test_f1ap_cu_configuration_update_acknowledge(); + test_f1ap_du_configuration_update_acknowledge(); return 0; } From 3aa9f4c0becdd5fcabea331da213871cc7f8f6ff Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Wed, 29 May 2024 22:50:34 +0200 Subject: [PATCH 45/46] Use F1 gNB-DU Configuration Update Acknowledge lib in stack --- openair2/F1AP/f1ap_cu_interface_management.c | 38 +++++--------------- openair2/F1AP/f1ap_du_interface_management.c | 24 +++++++++++++ openair2/F1AP/f1ap_du_interface_management.h | 5 +++ openair2/F1AP/f1ap_handlers.c | 2 +- openair2/GNB_APP/gnb_app.c | 5 +++ 5 files changed, 43 insertions(+), 31 deletions(-) diff --git a/openair2/F1AP/f1ap_cu_interface_management.c b/openair2/F1AP/f1ap_cu_interface_management.c index cd408c6720..aed1ae6d23 100644 --- a/openair2/F1AP/f1ap_cu_interface_management.c +++ b/openair2/F1AP/f1ap_cu_interface_management.c @@ -149,42 +149,20 @@ int CU_handle_gNB_DU_CONFIGURATION_UPDATE(instance_t instance, sctp_assoc_t asso return 0; } -int CU_send_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE( - sctp_assoc_t assoc_id, - f1ap_gnb_du_configuration_update_acknowledge_t *GNBDUConfigurationUpdateAcknowledge) +int CU_send_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(sctp_assoc_t assoc_id, f1ap_gnb_du_configuration_update_acknowledge_t *msg) { - F1AP_F1AP_PDU_t pdu = {}; uint8_t *buffer; uint32_t len; - - /* Create */ - /* 0. Message */ - - pdu.present = F1AP_F1AP_PDU_PR_successfulOutcome; - asn1cCalloc(pdu.choice.successfulOutcome, succOut); - succOut->procedureCode = F1AP_ProcedureCode_id_gNBDUConfigurationUpdate; - succOut->criticality = F1AP_Criticality_reject; - succOut->value.present = F1AP_SuccessfulOutcome__value_PR_GNBDUConfigurationUpdateAcknowledge; - F1AP_GNBDUConfigurationUpdateAcknowledge_t *ack = &succOut->value.choice.GNBDUConfigurationUpdateAcknowledge; - - /* Mandatory */ - /* Transaction Id */ - asn1cSequenceAdd(ack->protocolIEs.list, F1AP_GNBDUConfigurationUpdateAcknowledgeIEs_t, ie1); - ie1->id = F1AP_ProtocolIE_ID_id_TransactionID; - ie1->criticality = F1AP_Criticality_reject; - ie1->value.present = F1AP_GNBDUConfigurationUpdateAcknowledgeIEs__value_PR_TransactionID; - ie1->value.choice.TransactionID = GNBDUConfigurationUpdateAcknowledge->transaction_id; - - /* Todo add optional fields */ - /* encode */ - - if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { - LOG_E(F1AP, "Failed to encode F1 gNB-DU CONFIGURATION UPDATE\n"); + /* Encode F1 gNB-CU Configuration Update message */ + F1AP_F1AP_PDU_t *pdu = encode_f1ap_du_configuration_update_acknowledge(msg); + /* Encode F1AP PDU */ + if (f1ap_encode_pdu(pdu, &buffer, &len) < 0) { + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); + LOG_E(F1AP, "Failed to encode F1 gNB-DU Configuration Update Acknowledge\n"); return -1; } - LOG_DUMPMSG(F1AP, LOG_DUMP_CHAR, buffer, len, "F1AP gNB-DU CONFIGURATION UPDATE : "); - ASN_STRUCT_RESET(asn_DEF_F1AP_F1AP_PDU, &pdu); + ASN_STRUCT_FREE(asn_DEF_F1AP_F1AP_PDU, pdu); f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); return 0; } diff --git a/openair2/F1AP/f1ap_du_interface_management.c b/openair2/F1AP/f1ap_du_interface_management.c index 391f9164eb..85e963ea6a 100644 --- a/openair2/F1AP/f1ap_du_interface_management.c +++ b/openair2/F1AP/f1ap_du_interface_management.c @@ -245,6 +245,30 @@ int DU_handle_gNB_CU_CONFIGURATION_UPDATE(instance_t instance, sctp_assoc_t asso return 0; } +/** + * @brief F1 gNB-DU Configuration Update Acknowledge decoding and message transfer + */ +int DU_handle_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(instance_t instance, + sctp_assoc_t assoc_id, + uint32_t stream, + F1AP_F1AP_PDU_t *pdu) +{ + // Decoding + f1ap_gnb_du_configuration_update_acknowledge_t in = {0}; + if (!decode_f1ap_du_configuration_update_acknowledge(pdu, &in)) { + LOG_E(F1AP, "Failed to decode gNB-DU Configuration Update Acknowledge\n"); + free_f1ap_du_configuration_update_acknowledge(&in); + return -1; + } + // Allocate and send an ITTI message + MessageDef *msg_p = itti_alloc_new_message(TASK_DU_F1, 0, F1AP_GNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE); + f1ap_gnb_du_configuration_update_acknowledge_t *msg = &F1AP_GNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(msg_p); + // Copy the decoded message to the ITTI message (RRC thread will free it) + *msg = in; // Copy the decoded message to the ITTI message (RRC thread will free it) + itti_send_msg_to_task(TASK_GNB_APP, GNB_MODULE_ID_TO_INSTANCE(assoc_id), msg_p); + return 0; +} + int DU_send_gNB_CU_CONFIGURATION_UPDATE_FAILURE(sctp_assoc_t assoc_id, f1ap_gnb_cu_configuration_update_failure_t *GNBCUConfigurationUpdateFailure) { AssertFatal(1==0,"received gNB CU CONFIGURATION UPDATE FAILURE with cause %d\n", diff --git a/openair2/F1AP/f1ap_du_interface_management.h b/openair2/F1AP/f1ap_du_interface_management.h index c8975a2361..bb5caf90df 100644 --- a/openair2/F1AP/f1ap_du_interface_management.h +++ b/openair2/F1AP/f1ap_du_interface_management.h @@ -64,4 +64,9 @@ int DU_send_gNB_CU_CONFIGURATION_UPDATE_FAILURE(sctp_assoc_t assoc_id, int DU_send_gNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(sctp_assoc_t assoc_id, f1ap_gnb_cu_configuration_update_acknowledge_t *GNBCUConfigurationUpdateAcknowledge); +int DU_handle_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE(instance_t instance, + sctp_assoc_t assoc_id, + uint32_t stream, + F1AP_F1AP_PDU_t *pdu); + #endif /* F1AP_DU_INTERFACE_MANAGEMENT_H_ */ diff --git a/openair2/F1AP/f1ap_handlers.c b/openair2/F1AP/f1ap_handlers.c index 544e763c49..6234dcd624 100644 --- a/openair2/F1AP/f1ap_handlers.c +++ b/openair2/F1AP/f1ap_handlers.c @@ -48,7 +48,7 @@ static const f1ap_message_processing_t f1ap_messages_processing[][3] = { // {CU_handle_RESET, DU_handle_RESET_ACKNOWLEDGE, 0}, /* Reset */ {CU_handle_F1_SETUP_REQUEST, DU_handle_F1_SETUP_RESPONSE, DU_handle_F1_SETUP_FAILURE}, /* F1Setup */ {0, 0, 0}, /* ErrorIndication */ - {CU_handle_gNB_DU_CONFIGURATION_UPDATE, 0, 0}, /* gNBDUConfigurationUpdate */ + {CU_handle_gNB_DU_CONFIGURATION_UPDATE, DU_handle_gNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE, 0}, /* gNBDUConfigurationUpdate */ {DU_handle_gNB_CU_CONFIGURATION_UPDATE, CU_handle_gNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE, 0}, /* gNBCUConfigurationUpdate */ {DU_handle_UE_CONTEXT_SETUP_REQUEST, CU_handle_UE_CONTEXT_SETUP_RESPONSE, 0}, /* UEContextSetup */ {DU_handle_UE_CONTEXT_RELEASE_COMMAND, CU_handle_UE_CONTEXT_RELEASE_COMPLETE, 0}, /* UEContextRelease */ diff --git a/openair2/GNB_APP/gnb_app.c b/openair2/GNB_APP/gnb_app.c index caaf5d64e7..0e7e25e2c0 100644 --- a/openair2/GNB_APP/gnb_app.c +++ b/openair2/GNB_APP/gnb_app.c @@ -247,6 +247,11 @@ void *gNB_app_task(void *args_p) AssertFatal(cell_to_activate == 1,"No cells to activate or cells > 1 %d\n",cell_to_activate); break; + + case F1AP_GNB_DU_CONFIGURATION_UPDATE_ACKNOWLEDGE: + LOG_E(GNB_APP, "[gNB %ld] Handling of %s message not implemented yet\n", instance, msg_name); + break; + case NGAP_DEREGISTERED_GNB_IND: LOG_W(GNB_APP, "[gNB %ld] Received %s: associated AMF %d\n", instance, msg_name, NGAP_DEREGISTERED_GNB_IND(msg_p).nb_amf); From 5daad21ca61257ffbf4c97f4dd84644fba2c6dc6 Mon Sep 17 00:00:00 2001 From: Guido Casati Date: Fri, 10 May 2024 11:50:18 +0200 Subject: [PATCH 46/46] Reworked F1AP documentation and added info about the library * moved F1AP related docs to a separate folder in docs --- doc/E1AP/E1-design.md | 2 +- doc/{ => F1AP}/F1-design.md | 0 doc/F1AP/F1AP-lib.md | 69 +++++++++++++++++++++++++++++++++++++ doc/README.md | 2 +- doc/UnitTests.md | 4 +++ 5 files changed, 75 insertions(+), 2 deletions(-) rename doc/{ => F1AP}/F1-design.md (100%) create mode 100644 doc/F1AP/F1AP-lib.md diff --git a/doc/E1AP/E1-design.md b/doc/E1AP/E1-design.md index 04d19bb514..4dd042f87d 100644 --- a/doc/E1AP/E1-design.md +++ b/doc/E1AP/E1-design.md @@ -79,7 +79,7 @@ More details about the E1AP procedures in OAI are available in this document: [E # 2. Running the E1 Split -The setup is assuming that all modules are running on the same machine. The user can refer to the [F1 design document](./../F1-design.md) for local deployment of the DU. +The setup is assuming that all modules are running on the same machine. The user can refer to the [F1 design document](./../F1AP/F1-design.md) for local deployment of the DU. ## 2.1 Configuration File diff --git a/doc/F1-design.md b/doc/F1AP/F1-design.md similarity index 100% rename from doc/F1-design.md rename to doc/F1AP/F1-design.md diff --git a/doc/F1AP/F1AP-lib.md b/doc/F1AP/F1AP-lib.md new file mode 100644 index 0000000000..46712914ed --- /dev/null +++ b/doc/F1AP/F1AP-lib.md @@ -0,0 +1,69 @@ + + + + + +
+ + + + + + F1AP Messages Encoding & Decoding Library +
+ +[[_TOC_]] + + +# Intro + +This library is for the encoding, decoding and testing of F1AP (F1 Application Protocol) messages. + +# Implementation Details + +The library includes the following components: + +1. **Common Functions**: + +This file [f1ap_lib_common.c](../../openair2/F1AP/lib/f1ap_lib_common.c) and its corresponding header contain utility functions and macros shared across different F1AP functions. + +2. **Message-Specific Modules**: + +Each F1AP message (e.g., DL RRC, UL RRC, etc.) has its corresponding modules and each module will include the encoder, decoder, equality check, and memory management functions specific to that message type. Specifically, the goal is to achieve the following: + +* **Encoder & Decoder**: Implement encoding and decoding functions for each F1AP message. These functions will convert F1AP messages coming from upper or lower layers into an F1AP PDU to be sent over F1 interface. +* **Equality Check (eq_X)**: `eq_X()` function that compares two messages for equality. This function is useful for testing purposes, ensuring that encoded and decoded messages match. +* **Deep Copy (cp_X)**: `cp_X()` function that performs a deep copy of a message. This function is beneficial when sending ITTI messages, as it avoids manual copying. +* **Memory Management (free_X)**: `free_X()` function to release memory associated with a message. Proper memory management helps prevent memory leaks. + +e.g. The following module contains functions that performs the encoding/decoding, equality check, deep copy and memory management for DL/UL RRC message transfer: + +* [f1ap_rrc_message_transfer.c](../../openair2/F1AP/lib/f1ap_rrc_message_transfer.c) + +# Testing + +The functions in the file [f1ap_lib_common.c](../../openair2/F1AP/tests/f1ap_lib_test.c) are used to test F1AP message encoding and decoding functionalities, according to the following steps: + +* call the encoder function for the message to be transferred into a F1AP PDU +* use `f1ap_encode_decode` to perform the following steps: + - Validates the input encoded PDU against constraints. + - Encodes the PDU using APER into a binary buffer. + - Decodes the binary buffer back into a PDU. + - Returns the decoded PDU. +* call the decoder function for the decoded F1AP PDU to obtain the decoded message +* call `eq_dl_rrc_message_transfer` to compare the original message with the decoded one +* call `cp_dl_rrc_message_transfer` to deep copy the original message, then compare the with the original one +* free all messages and PDUs + +A flowchart for a function testing F1AP messages, such as `test_f1ap_setup_request`, would look like this: + +```mermaid +flowchart TD + create[Create F1AP message]-->|f1ap_setup_req_t msg|enc[encode_f1ap_setup_request] + enc-->|F1AP_F1AP_PDU_t *f1enc|encdec[f1ap_encode_decode] + encdec-->|F1AP_F1AP_PDU_t *f1dec|dec[decode_f1ap_setup_request] + create-->|f1ap_setup_req_t msg|eq + dec-->|f1ap_setup_req_t decoded|eq[eq_f1ap_setup_request] + create-->|f1ap_setup_req_t msg|cp[cp_f1ap_setup_request] + cp-->|f1ap_setup_req_t cp|eq[eq_f1ap_setup_request] +``` diff --git a/doc/README.md b/doc/README.md index 70e8bf05be..7f57a24eb0 100644 --- a/doc/README.md +++ b/doc/README.md @@ -65,7 +65,7 @@ Legacy unmaintained files: - General software architecture notes: [SW_archi.md](./SW_archi.md) - [Information on E1](./E1AP/E1-design.md) -- [Information on F1](./F1-design.md) +- [Information on F1](./F1AP/F1-design.md) - [Information on how NR nFAPI works](./NR_NFAPI_archi.md) - [Flow graph of the L1 in gNB](SW-archi-graph.md) - [L1 threads in NR-UE](./nr-ue-design.md) diff --git a/doc/UnitTests.md b/doc/UnitTests.md index aa6b7b1123..76cfe7bee1 100644 --- a/doc/UnitTests.md +++ b/doc/UnitTests.md @@ -24,6 +24,10 @@ cmake .. -GNinja -DENABLE_TESTS=ON ninja tests ``` +The user can use either `ninja` or `make`. + +# Run unit tests + Then, you can run `ctest` to run all tests: ```bash