From 2cb6fd089041dfae6a36ad380e6ffab5cf044ca9 Mon Sep 17 00:00:00 2001 From: Xin Zhe Khooi Date: Sat, 18 May 2024 13:05:07 +0000 Subject: [PATCH 1/7] Stubs for F1 Reset --- openair2/COMMON/f1ap_messages_def.h | 4 +++ openair2/COMMON/f1ap_messages_types.h | 30 +++++++++++++++++++ openair2/F1AP/f1ap_cu_interface_management.c | 6 ++-- openair2/F1AP/f1ap_cu_interface_management.h | 6 ++-- openair2/F1AP/f1ap_cu_task.c | 4 +++ openair2/F1AP/f1ap_du_interface_management.c | 5 ++-- openair2/F1AP/f1ap_du_interface_management.h | 4 +-- openair2/F1AP/f1ap_du_task.c | 4 +++ openair2/F1AP/f1ap_handlers.c | 5 +++- .../LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 12 ++++++++ .../LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h | 2 ++ openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h | 3 ++ .../LAYER2/NR_MAC_gNB/mac_rrc_ul_direct.c | 14 +++++++++ openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c | 13 ++++++++ openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h | 2 ++ openair2/RRC/NR/mac_rrc_dl.h | 3 ++ openair2/RRC/NR/mac_rrc_dl_direct.c | 14 +++++++++ openair2/RRC/NR/mac_rrc_dl_f1ap.c | 14 +++++++++ openair2/RRC/NR/nr_rrc_defs.h | 2 ++ 19 files changed, 136 insertions(+), 11 deletions(-) diff --git a/openair2/COMMON/f1ap_messages_def.h b/openair2/COMMON/f1ap_messages_def.h index 9177ed9001..405ecae3d5 100644 --- a/openair2/COMMON/f1ap_messages_def.h +++ b/openair2/COMMON/f1ap_messages_def.h @@ -23,6 +23,10 @@ /* To setup F1 at DU */ MESSAGE_DEF(F1AP_DU_REGISTER_REQ, MESSAGE_PRIORITY_MED, f1ap_du_register_req_t, f1ap_du_register_req) +/* RESET */ +MESSAGE_DEF(F1AP_RESET, MESSAGE_PRIORITY_MED, f1ap_reset_t, f1ap_reset) +MESSAGE_DEF(F1AP_RESET_ACK, MESSAGE_PRIORITY_MED, f1ap_reset_ack_t, f1ap_reset_ack) + /* eNB_DU application layer -> F1AP messages or CU F1AP -> RRC*/ MESSAGE_DEF(F1AP_SETUP_REQ , MESSAGE_PRIORITY_MED, f1ap_setup_req_t , f1ap_setup_req) MESSAGE_DEF(F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE , MESSAGE_PRIORITY_MED, f1ap_gnb_cu_configuration_update_acknowledge_t , f1ap_gnb_cu_configuration_update_acknowledge) diff --git a/openair2/COMMON/f1ap_messages_types.h b/openair2/COMMON/f1ap_messages_types.h index 8ec4613327..3b6082e221 100644 --- a/openair2/COMMON/f1ap_messages_types.h +++ b/openair2/COMMON/f1ap_messages_types.h @@ -34,6 +34,9 @@ #define F1AP_DU_REGISTER_REQ(mSGpTR) (mSGpTR)->ittiMsg.f1ap_du_register_req +#define F1AP_RESET(mSGpTR) (mSGpTR)->ittiMsg.f1ap_reset +#define F1AP_RESET_ACK(mSGpTR) (mSGpTR)->ittiMsg.f1ap_reset_ack + #define F1AP_SETUP_REQ(mSGpTR) (mSGpTR)->ittiMsg.f1ap_setup_req #define F1AP_SETUP_RESP(mSGpTR) (mSGpTR)->ittiMsg.f1ap_setup_resp #define F1AP_GNB_CU_CONFIGURATION_UPDATE(mSGpTR) (mSGpTR)->ittiMsg.f1ap_gnb_cu_configuration_update @@ -78,6 +81,8 @@ #define F1AP_MAX_NO_OF_TNL_ASSOCIATIONS 32 #define F1AP_MAX_NO_UE_ID 1024 +#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 { @@ -534,4 +539,29 @@ typedef struct f1ap_lost_connection_t { int dummy; } f1ap_lost_connection_t; +typedef enum F1AP_ResetType_e { + F1AP_RESET_ALL, + F1AP_RESET_PART_OF_F1_INTERFACE +} f1ap_ResetType_t; + +typedef struct f1ap_reset_t { + uint64_t transaction_id; + f1ap_Cause_t cause; + long cause_value; + f1ap_ResetType_t reset_type; + struct { + uint32_t gNB_CU_ue_id; + uint32_t gNB_DU_ue_id; + } ue_to_reset[F1AP_MAX_NO_OF_INDIVIDUAL_CONNECTIONS_TO_RESET]; +} f1ap_reset_t; + +typedef struct f1ap_reset_ack_t { + uint64_t transaction_id; + struct { + uint32_t gNB_CU_ue_id; + uint32_t gNB_DU_ue_id; + } ue_to_reset[F1AP_MAX_NO_OF_INDIVIDUAL_CONNECTIONS_TO_RESET]; + uint16_t criticality_diagnostics; +} f1ap_reset_ack_t; + #endif /* F1AP_MESSAGES_TYPES_H_ */ diff --git a/openair2/F1AP/f1ap_cu_interface_management.c b/openair2/F1AP/f1ap_cu_interface_management.c index 360a2323aa..2e73172e2b 100644 --- a/openair2/F1AP/f1ap_cu_interface_management.c +++ b/openair2/F1AP/f1ap_cu_interface_management.c @@ -35,12 +35,12 @@ #include "f1ap_itti_messaging.h" #include "f1ap_cu_interface_management.h" -int CU_send_RESET(sctp_assoc_t assoc_id, F1AP_Reset_t *Reset) +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_ACKKNOWLEDGE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu) +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"); } @@ -50,7 +50,7 @@ int CU_handle_RESET(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, AssertFatal(1==0,"Not implemented yet\n"); } -int CU_send_RESET_ACKNOWLEDGE(sctp_assoc_t assoc_id, F1AP_ResetAcknowledge_t *ResetAcknowledge) +int CU_send_RESET_ACKNOWLEDGE(sctp_assoc_t assoc_id, const f1ap_reset_ack_t *ack) { AssertFatal(1==0,"Not implemented yet\n"); } diff --git a/openair2/F1AP/f1ap_cu_interface_management.h b/openair2/F1AP/f1ap_cu_interface_management.h index f506b83152..11a45868e1 100644 --- a/openair2/F1AP/f1ap_cu_interface_management.h +++ b/openair2/F1AP/f1ap_cu_interface_management.h @@ -36,10 +36,10 @@ /* * Reset */ -int CU_send_RESET(sctp_assoc_t assoc_id, F1AP_Reset_t *Reset); -int CU_handle_RESET_ACKKNOWLEDGE(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu); +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, F1AP_ResetAcknowledge_t *ResetAcknowledge); +int CU_send_RESET_ACKNOWLEDGE(sctp_assoc_t assoc_id, const f1ap_reset_ack_t *ack); /* * Error Indication diff --git a/openair2/F1AP/f1ap_cu_task.c b/openair2/F1AP/f1ap_cu_task.c index 3d8061b961..a320b92935 100644 --- a/openair2/F1AP/f1ap_cu_task.c +++ b/openair2/F1AP/f1ap_cu_task.c @@ -160,6 +160,10 @@ void *F1AP_CU_task(void *arg) { &received_msg->ittiMsg.sctp_data_ind); break; + case F1AP_RESET_ACK: + CU_send_RESET_ACKNOWLEDGE(assoc_id, &F1AP_RESET_ACK(received_msg)); + break; + case F1AP_SETUP_RESP: // from rrc CU_send_F1_SETUP_RESPONSE(assoc_id, &F1AP_SETUP_RESP(received_msg)); diff --git a/openair2/F1AP/f1ap_du_interface_management.c b/openair2/F1AP/f1ap_du_interface_management.c index 7ea710a0b4..caef18ed91 100644 --- a/openair2/F1AP/f1ap_du_interface_management.c +++ b/openair2/F1AP/f1ap_du_interface_management.c @@ -55,11 +55,12 @@ int DU_handle_RESET(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, AssertFatal(1==0,"Not implemented yet\n"); } -int DU_send_RESET_ACKKNOWLEDGE(sctp_assoc_t assoc_id, F1AP_ResetAcknowledge_t *ResetAcknowledge) { +int DU_send_RESET_ACKNOWLEDGE(sctp_assoc_t assoc_id, const f1ap_reset_ack_t *ack) +{ AssertFatal(1==0,"Not implemented yet\n"); } -int DU_send_RESET(sctp_assoc_t assoc_id, F1AP_Reset_t *Reset) +int DU_send_RESET(sctp_assoc_t assoc_id, const f1ap_reset_t *reset) { AssertFatal(1==0,"Not implemented yet\n"); } diff --git a/openair2/F1AP/f1ap_du_interface_management.h b/openair2/F1AP/f1ap_du_interface_management.h index c48754010f..f8d7eafb02 100644 --- a/openair2/F1AP/f1ap_du_interface_management.h +++ b/openair2/F1AP/f1ap_du_interface_management.h @@ -37,8 +37,8 @@ * Reset */ int DU_handle_RESET(instance_t instance, sctp_assoc_t assoc_id, uint32_t stream, F1AP_F1AP_PDU_t *pdu); -int DU_send_RESET_ACKKNOWLEDGE(sctp_assoc_t assoc_id, F1AP_ResetAcknowledge_t *ResetAcknowledge); -int DU_send_RESET(sctp_assoc_t assoc_id, F1AP_Reset_t *Reset); +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); /* diff --git a/openair2/F1AP/f1ap_du_task.c b/openair2/F1AP/f1ap_du_task.c index 7959f734fe..ff188e52df 100644 --- a/openair2/F1AP/f1ap_du_task.c +++ b/openair2/F1AP/f1ap_du_task.c @@ -134,6 +134,10 @@ void *F1AP_DU_task(void *arg) { DUuniqInstance = gtpInst; } break; + case F1AP_RESET_ACK: + DU_send_RESET_ACKNOWLEDGE(assoc_id, &F1AP_RESET_ACK(msg)); + break; + case F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE: DU_send_gNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(assoc_id, &F1AP_GNB_CU_CONFIGURATION_UPDATE_ACKNOWLEDGE(msg)); diff --git a/openair2/F1AP/f1ap_handlers.c b/openair2/F1AP/f1ap_handlers.c index ecdda72000..bfaa9959dc 100644 --- a/openair2/F1AP/f1ap_handlers.c +++ b/openair2/F1AP/f1ap_handlers.c @@ -42,7 +42,10 @@ /* Handlers matrix. Only f1 related procedure present here */ static const f1ap_message_processing_t f1ap_messages_processing[][3] = { - {0, 0, 0}, /* Reset */ + // TODO: How to handle RESET if CU/DU has their respective handlers? + // We need to check node type and call the right handler. + {DU_handle_RESET, CU_handle_RESET_ACKNOWLEDGE, 0}, /* Reset */ + // {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 */ 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 7353e61711..9596260163 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -95,6 +95,18 @@ static bool check_plmn_identity(const f1ap_plmn_t *check_plmn, const f1ap_plmn_t return plmn->mcc == check_plmn->mcc && plmn->mnc_digit_length == check_plmn->mnc_digit_length && plmn->mnc == check_plmn->mnc; } +void f1_reset_cu_initiated(const f1ap_reset_t *reset) +{ + (void) reset; + AssertFatal(false, "%s() not implemented yet\n", __func__); +} + +void f1_reset_acknowledge_du_initiated(const f1ap_reset_ack_t *ack) +{ + (void) ack; + AssertFatal(false, "%s() not implemented yet\n", __func__); +} + void f1_setup_response(const f1ap_setup_resp_t *resp) { LOG_I(MAC, "received F1 Setup Response from CU %s\n", resp->gNB_CU_name); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h index 7a284f2d8b..e9aceb1192 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h @@ -26,6 +26,8 @@ #include "f1ap_messages_types.h" #include "openair2/RRC/NR/MESSAGES/asn1_msg.h" +void f1_reset_cu_initiated(const f1ap_reset_t *reset); +void f1_reset_acknowledge_du_initiated(const f1ap_reset_ack_t *ack); void f1_setup_response(const f1ap_setup_resp_t *resp); void f1_setup_failure(const f1ap_setup_failure_t *failure); void gnb_du_configuration_update_acknowledge(const f1ap_gnb_du_configuration_update_acknowledge_t *ack); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h index 0d902a77c6..1e416f01f9 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul.h @@ -25,6 +25,9 @@ #include "common/platform_types.h" #include "f1ap_messages_types.h" +typedef void (*f1_reset_du_initiated_func_t)(const f1ap_reset_t *reset); +typedef void (*f1_reset_acknowledge_cu_initiated_func_t)(const f1ap_reset_ack_t *ack); + typedef void (*f1_setup_request_func_t)(const f1ap_setup_req_t* req); typedef void (*gnb_du_configuration_update_t)(const f1ap_gnb_du_configuration_update_t *upd); 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 acef49ef5b..29a7bc8621 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,18 @@ #include "mac_rrc_ul.h" +static void f1_reset_du_initiated_direct(const f1ap_reset_t *reset) +{ + (void) reset; + AssertFatal(false, "%s() not implemented yet\n", __func__); +} + +static void f1_reset_acknowledge_cu_initiated_direct(const f1ap_reset_ack_t *ack) +{ + (void) ack; + AssertFatal(false, "%s() not implemented yet\n", __func__); +} + 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); @@ -284,6 +296,8 @@ static void initial_ul_rrc_message_transfer_direct(module_id_t module_id, const void mac_rrc_ul_direct_init(struct nr_mac_rrc_ul_if_s *mac_rrc) { + mac_rrc->f1_reset = f1_reset_du_initiated_direct; + mac_rrc->f1_reset_acknowledge = f1_reset_acknowledge_cu_initiated_direct; mac_rrc->f1_setup_request = f1_setup_request_direct; mac_rrc->gnb_du_configuration_update = gnb_du_configuration_update_direct; mac_rrc->ue_context_setup_response = ue_context_setup_response_direct; 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 19beddad7a..4d716e9fb7 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c @@ -53,6 +53,17 @@ static f1ap_net_config_t read_DU_IP_config(const eth_params_t* f1_params, const return nc; } +static void f1_reset_du_initiated_f1ap(const f1ap_reset_t *reset) +{ + (void) reset; + AssertFatal(false, "%s() not implemented yet\n", __func__); +} + +static void f1_reset_acknowledge_cu_initiated_f1ap(const f1ap_reset_ack_t *ack) +{ + (void) ack; + AssertFatal(false, "%s() not implemented yet\n", __func__); +} static void f1_setup_request_f1ap(const f1ap_setup_req_t *req) { @@ -275,6 +286,8 @@ static void initial_ul_rrc_message_transfer_f1ap(module_id_t module_id, const f1 void mac_rrc_ul_f1ap_init(struct nr_mac_rrc_ul_if_s *mac_rrc) { + mac_rrc->f1_reset = f1_reset_du_initiated_f1ap; + mac_rrc->f1_reset_acknowledge = f1_reset_acknowledge_cu_initiated_f1ap; mac_rrc->f1_setup_request = f1_setup_request_f1ap; mac_rrc->gnb_du_configuration_update = gnb_du_configuration_update_f1ap; mac_rrc->ue_context_setup_response = ue_context_setup_response_f1ap; diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h index 350a909088..8362a61205 100644 --- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h +++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h @@ -690,6 +690,8 @@ typedef struct NR_bler_options { } NR_bler_options_t; typedef struct nr_mac_rrc_ul_if_s { + f1_reset_du_initiated_func_t f1_reset; + f1_reset_acknowledge_cu_initiated_func_t f1_reset_acknowledge; f1_setup_request_func_t f1_setup_request; gnb_du_configuration_update_t gnb_du_configuration_update; ue_context_setup_response_func_t ue_context_setup_response; diff --git a/openair2/RRC/NR/mac_rrc_dl.h b/openair2/RRC/NR/mac_rrc_dl.h index 49eb03512a..d6937591b5 100644 --- a/openair2/RRC/NR/mac_rrc_dl.h +++ b/openair2/RRC/NR/mac_rrc_dl.h @@ -25,6 +25,9 @@ #include "common/platform_types.h" #include "f1ap_messages_types.h" +typedef void (*f1_reset_cu_initiated_func_t)(sctp_assoc_t assoc_id, const f1ap_reset_t *reset); +typedef void (*f1_reset_acknowledge_du_initiated_func_t)(sctp_assoc_t assoc_id, const f1ap_reset_ack_t *ack); + typedef void (*f1_setup_response_func_t)(sctp_assoc_t assoc_id, const f1ap_setup_resp_t *resp); typedef void (*f1_setup_failure_func_t)(sctp_assoc_t assoc_id, const f1ap_setup_failure_t *fail); typedef void (*gnb_du_configuration_update_ack_func_t)(sctp_assoc_t assoc_id, diff --git a/openair2/RRC/NR/mac_rrc_dl_direct.c b/openair2/RRC/NR/mac_rrc_dl_direct.c index 4b0afbc0e1..54ec7c8e4c 100644 --- a/openair2/RRC/NR/mac_rrc_dl_direct.c +++ b/openair2/RRC/NR/mac_rrc_dl_direct.c @@ -24,6 +24,18 @@ #include "mac_rrc_dl.h" #include "openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.h" +static void f1_reset_cu_initiated_direct(sctp_assoc_t assoc_id, const f1ap_reset_t *reset) +{ + (void)reset; + AssertFatal(false, "%s() not implemented yet\n", __func__); +} + +static void f1_reset_acknowledge_du_initiated_direct(sctp_assoc_t assoc_id, const f1ap_reset_ack_t *ack) +{ + (void)ack; + AssertFatal(false, "%s() not implemented yet\n", __func__); +} + static void f1_setup_response_direct(sctp_assoc_t assoc_id, const f1ap_setup_resp_t *resp) { AssertFatal(assoc_id == -1, "illegal assoc_id %d\n", assoc_id); @@ -80,6 +92,8 @@ static void dl_rrc_message_transfer_direct(sctp_assoc_t assoc_id, const f1ap_dl_ void mac_rrc_dl_direct_init(nr_mac_rrc_dl_if_t *mac_rrc) { + mac_rrc->f1_reset = f1_reset_cu_initiated_direct; + mac_rrc->f1_reset_acknowledge = f1_reset_acknowledge_du_initiated_direct; mac_rrc->f1_setup_response = f1_setup_response_direct; mac_rrc->f1_setup_failure = f1_setup_failure_direct; mac_rrc->gnb_du_configuration_update_acknowledge = gnb_du_configuration_update_ack_direct; diff --git a/openair2/RRC/NR/mac_rrc_dl_f1ap.c b/openair2/RRC/NR/mac_rrc_dl_f1ap.c index 9a934cc675..439712ec7e 100644 --- a/openair2/RRC/NR/mac_rrc_dl_f1ap.c +++ b/openair2/RRC/NR/mac_rrc_dl_f1ap.c @@ -24,6 +24,18 @@ #include "mac_rrc_dl.h" #include "nr_rrc_defs.h" +static void f1_reset_cu_initiated_f1ap(sctp_assoc_t assoc_id, const f1ap_reset_t *reset) +{ + (void)reset; + AssertFatal(false, "%s() not implemented yet\n", __func__); +} + +static void f1_reset_acknowledge_du_initiated_f1ap(sctp_assoc_t assoc_id, const f1ap_reset_ack_t *ack) +{ + (void)ack; + AssertFatal(false, "%s() not implemented yet\n", __func__); +} + static void f1_setup_response_f1ap(sctp_assoc_t assoc_id, const f1ap_setup_resp_t *resp) { MessageDef *msg = itti_alloc_new_message(TASK_RRC_GNB, 0, F1AP_SETUP_RESP); @@ -215,6 +227,8 @@ static void dl_rrc_message_transfer_f1ap(sctp_assoc_t assoc_id, const f1ap_dl_rr void mac_rrc_dl_f1ap_init(nr_mac_rrc_dl_if_t *mac_rrc) { + mac_rrc->f1_reset = f1_reset_cu_initiated_f1ap; + mac_rrc->f1_reset_acknowledge = f1_reset_acknowledge_du_initiated_f1ap; mac_rrc->f1_setup_response = f1_setup_response_f1ap; mac_rrc->f1_setup_failure = f1_setup_failure_f1ap; mac_rrc->gnb_du_configuration_update_acknowledge = gnb_du_configuration_update_ack_f1ap; diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h index 961406986a..a9234ed5bd 100644 --- a/openair2/RRC/NR/nr_rrc_defs.h +++ b/openair2/RRC/NR/nr_rrc_defs.h @@ -398,6 +398,8 @@ typedef struct neighbour_cell_configuration_s { } neighbour_cell_configuration_t; typedef struct nr_mac_rrc_dl_if_s { + f1_reset_cu_initiated_func_t f1_reset; + f1_reset_acknowledge_du_initiated_func_t f1_reset_acknowledge; f1_setup_response_func_t f1_setup_response; f1_setup_failure_func_t f1_setup_failure; gnb_du_configuration_update_ack_func_t gnb_du_configuration_update_acknowledge; From 03c2f6277dbc2fb569afc41d72347d2864887871 Mon Sep 17 00:00:00 2001 From: Xin Zhe Khooi Date: Tue, 21 May 2024 02:46:07 +0000 Subject: [PATCH 2/7] Implement encoder/decoder for F1 Reset at DU --- openair2/F1AP/f1ap_du_interface_management.c | 104 ++++++++++++++++++- 1 file changed, 102 insertions(+), 2 deletions(-) diff --git a/openair2/F1AP/f1ap_du_interface_management.c b/openair2/F1AP/f1ap_du_interface_management.c index caef18ed91..eec39ee7fc 100644 --- a/openair2/F1AP/f1ap_du_interface_management.c +++ b/openair2/F1AP/f1ap_du_interface_management.c @@ -52,12 +52,112 @@ int to_NRNRB(int nrb) { int DU_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"); + LOG_D(F1AP, "DU_handle_RESET\n");\ + F1AP_Reset_t *container; + F1AP_ResetIEs_t *ie; + DevAssert(pdu != NULL); + container = &pdu->choice.initiatingMessage->value.choice.Reset; + + /* Reset == Non UE-related procedure -> stream 0 */ + if (stream != 0) { + LOG_W(F1AP, "[SCTP %d] Received Reset on stream != 0 (%d)\n", + assoc_id, stream); + } + + MessageDef *msg_p = itti_alloc_new_message(TASK_DU_F1, 0, F1AP_RESET); + msg_p->ittiMsgHeader.originInstance = assoc_id; + f1ap_reset_t *f1ap_reset = &F1AP_RESET(msg_p); + + /* Transaction ID */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_ResetIEs_t, ie, container, F1AP_ProtocolIE_ID_id_TransactionID, true); + f1ap_reset->transaction_id = ie->value.choice.TransactionID; + LOG_D(F1AP, "req->transaction_id %lu \n", f1ap_reset->transaction_id); + + /* Cause */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_ResetIEs_t, ie, container, F1AP_ProtocolIE_ID_id_Cause, true); + switch(ie->value.choice.Cause.present) + { + case F1AP_Cause_PR_radioNetwork: + LOG_D(F1AP, "Cause: Radio Network\n"); + f1ap_reset->cause = F1AP_CAUSE_RADIO_NETWORK; + f1ap_reset->cause_value = ie->value.choice.Cause.choice.radioNetwork; + break; + case F1AP_Cause_PR_transport: + LOG_D(F1AP, "Cause: Transport\n"); + f1ap_reset->cause = F1AP_CAUSE_TRANSPORT; + f1ap_reset->cause_value = ie->value.choice.Cause.choice.transport; + break; + case F1AP_Cause_PR_protocol: + LOG_D(F1AP, "Cause: Protocol\n"); + f1ap_reset->cause = F1AP_CAUSE_PROTOCOL; + f1ap_reset->cause_value = ie->value.choice.Cause.choice.protocol; + break; + case F1AP_Cause_PR_misc: + LOG_D(F1AP, "Cause: Misc\n"); + f1ap_reset->cause = F1AP_CAUSE_MISC; + f1ap_reset->cause_value = ie->value.choice.Cause.choice.misc; + break; + default: + AssertFatal(1==0,"Unknown cause\n"); + } + + /* ResetType */ + F1AP_FIND_PROTOCOLIE_BY_ID(F1AP_ResetIEs_t, ie, container, F1AP_ProtocolIE_ID_id_ResetType, true); + switch(ie->value.choice.ResetType.present) { + case F1AP_ResetType_PR_f1_Interface: + LOG_D(F1AP, "ResetType: F1 Interface\n"); + f1ap_reset->reset_type = F1AP_RESET_ALL; + break; + case F1AP_ResetType_PR_partOfF1_Interface: + LOG_D(F1AP, "ResetType: Part of F1 Interface\n"); + f1ap_reset->reset_type = F1AP_RESET_PART_OF_F1_INTERFACE; + break; + default: + AssertFatal(1==0,"Unknown reset type\n"); + } + + /* Part of F1 Interface */ + if (f1ap_reset->reset_type == F1AP_RESET_PART_OF_F1_INTERFACE) { + AssertFatal(1==0, "Not implemented yet\n"); + } + + f1_reset_cu_initiated(f1ap_reset); + return 0; } int DU_send_RESET_ACKNOWLEDGE(sctp_assoc_t assoc_id, const f1ap_reset_ack_t *ack) { - AssertFatal(1==0,"Not implemented yet\n"); + F1AP_F1AP_PDU_t pdu= {0}; + uint8_t *buffer; + uint32_t len; + /* Create */ + /* 0. pdu Type */ + pdu.present = F1AP_F1AP_PDU_PR_successfulOutcome; + asn1cCalloc(pdu.choice.successfulOutcome, successMsg); + successMsg->procedureCode = F1AP_ProcedureCode_id_Reset; + successMsg->criticality = F1AP_Criticality_reject; + successMsg->value.present = F1AP_SuccessfulOutcome__value_PR_ResetAcknowledge; + F1AP_ResetAcknowledge_t *f1ResetAcknowledge = &successMsg->value.choice.ResetAcknowledge; + /* mandatory */ + /* c1. Transaction ID (integer value) */ + asn1cSequenceAdd(f1ResetAcknowledge->protocolIEs.list, F1AP_ResetAcknowledgeIEs_t, ieC1); + ieC1->id = F1AP_ProtocolIE_ID_id_TransactionID; + ieC1->criticality = F1AP_Criticality_reject; + ieC1->value.present = F1AP_ResetAcknowledgeIEs__value_PR_TransactionID; + ieC1->value.choice.TransactionID = ack->transaction_id; + + /* TODO: (Optional) partialF1Interface, criticality diagnostics */ + + /* encode */ + if (f1ap_encode_pdu(&pdu, &buffer, &len) < 0) { + LOG_E(F1AP, "Failed to encode F1ResetAcknowledge\n"); + return -1; + } + + /* send */ + ASN_STRUCT_RESET(asn_DEF_F1AP_F1AP_PDU, &pdu); + f1ap_itti_send_sctp_data_req(assoc_id, buffer, len); + return 0; } int DU_send_RESET(sctp_assoc_t assoc_id, const f1ap_reset_t *reset) From a92ab368f223699225ba675c21e6c6b485c25ee6 Mon Sep 17 00:00:00 2001 From: Xin Zhe Khooi Date: Thu, 25 Jul 2024 13:37:38 +0000 Subject: [PATCH 3/7] Decouple UEContextReleaseComplete message generation from MAC UE release The next commit implements the release of all UEs following the F1 Reset message. It uses nr_mac_release_ue(), which as of now, triggered a release complete message automatically, which we don't want in the case of F1 Reset. This commit refactors the code to split UE release at MAC/RLC and release complete message sending to allow to release UEs without sending the complete. Corresponding users are updated. --- openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c | 1 + .../NR_MAC_gNB/gNB_scheduler_primitives.c | 46 +++++++++++-------- openair2/LAYER2/NR_MAC_gNB/mac_proto.h | 1 + .../LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 1 + 4 files changed, 29 insertions(+), 20 deletions(-) diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c index 200a21258e..495eb30eef 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c @@ -2190,6 +2190,7 @@ void nr_schedule_RA(module_id_t module_idP, if (ra->contention_resolution_timer < 0) { LOG_W(NR_MAC, "(%d.%d) RA Contention Resolution timer expired for UE 0x%04x, RA procedure failed...\n", frameP, slotP, ra->rnti); nr_mac_release_ue(mac, ra->rnti); + nr_mac_trigger_release_complete(mac, ra->rnti); nr_clear_ra_proc(ra); continue; } diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c index 4c67bfdf35..5728f6bb3f 100644 --- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c +++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c @@ -3013,32 +3013,36 @@ int nr_mac_enable_ue_rrc_processing_timer(gNB_MAC_INST *mac, NR_UE_info_t *UE, b return 0; } +void nr_mac_trigger_release_complete(gNB_MAC_INST *mac, int rnti) +{ + // the CU might not know such UE, e.g., because we never sent a message to + // it, so there might not be a corresponding entry for such UE in the look up + // table. This can happen, e.g., on Msg.3 with C-RNTI, where we create a UE + // MAC context, decode the PDU, find the C-RNTI MAC CE, and then throw the + // newly created context away. See also in _nr_rx_sdu() and commit 93f59a3c6e56f + if (!du_exists_f1_ue_data(rnti)) + return; + + // unlock the scheduler temporarily to prevent possible deadlocks with + // du_remove_f1_ue_data() (and also while sending the message to RRC) + NR_SCHED_UNLOCK(&mac->sched_lock); + f1_ue_data_t ue_data = du_get_f1_ue_data(rnti); + f1ap_ue_context_release_complete_t complete = { + .gNB_CU_ue_id = ue_data.secondary_ue, + .gNB_DU_ue_id = rnti, + }; + mac->mac_rrc.ue_context_release_complete(&complete); + + du_remove_f1_ue_data(rnti); + NR_SCHED_LOCK(&mac->sched_lock); +} + void nr_mac_release_ue(gNB_MAC_INST *mac, int rnti) { NR_SCHED_ENSURE_LOCKED(&mac->sched_lock); nr_rlc_remove_ue(rnti); mac_remove_nr_ue(mac, rnti); - - // the CU might not know such UE, e.g., because we never sent a message to - // it, so there might not be a corresponding entry for such UE in the look up - // table. This can happen, e.g., on Msg.3 with C-RNTI, where we create a UE - // MAC context, decode the PDU, find the C-RNTI MAC CE, and then throw the - // newly created context away. See also in _nr_rx_sdu() and commit 93f59a3c6e56f - if (du_exists_f1_ue_data(rnti)) { - // unlock the scheduler temporarily to prevent possible deadlocks with - // du_remove_f1_ue_data() (and also while sending the message to RRC) - NR_SCHED_UNLOCK(&mac->sched_lock); - f1_ue_data_t ue_data = du_get_f1_ue_data(rnti); - f1ap_ue_context_release_complete_t complete = { - .gNB_CU_ue_id = ue_data.secondary_ue, - .gNB_DU_ue_id = rnti, - }; - mac->mac_rrc.ue_context_release_complete(&complete); - - du_remove_f1_ue_data(rnti); - NR_SCHED_LOCK(&mac->sched_lock); - } } void nr_mac_update_timers(module_id_t module_id, @@ -3055,6 +3059,8 @@ void nr_mac_update_timers(module_id_t module_id, NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl; if (nr_mac_check_release(sched_ctrl, UE->rnti)) { + // trigger release first as nr_mac_release_ue() invalidates UE ptr + nr_mac_trigger_release_complete(mac, UE->rnti); nr_mac_release_ue(mac, UE->rnti); // go back to examine the next UE, which is at the position the // current UE was diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 84f06c873c..938d5cf27b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -438,6 +438,7 @@ void abort_nr_dl_harq(NR_UE_info_t* UE, int8_t harq_pid); void nr_mac_trigger_release_timer(NR_UE_sched_ctrl_t *sched_ctrl, NR_SubcarrierSpacing_t subcarrier_spacing); bool nr_mac_check_release(NR_UE_sched_ctrl_t *sched_ctrl, int rnti); +void nr_mac_trigger_release_complete(gNB_MAC_INST *mac, int rnti); void nr_mac_release_ue(gNB_MAC_INST *mac, int rnti); void nr_mac_trigger_ul_failure(NR_UE_sched_ctrl_t *sched_ctrl, NR_SubcarrierSpacing_t subcarrier_spacing); 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 9596260163..d47392491b 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -627,6 +627,7 @@ void ue_context_release_command(const f1ap_ue_context_release_cmd_t *cmd) if (UE->UE_sched_ctrl.ul_failure || cmd->rrc_container_length == 0) { /* The UE is already not connected anymore or we have nothing to forward*/ nr_mac_release_ue(mac, cmd->gNB_DU_ue_id); + nr_mac_trigger_release_complete(mac, cmd->gNB_DU_ue_id); } else { /* UE is in sync: forward release message and mark to be deleted * after UL failure */ From 23a865db77d84121f055e21b8caf73b60f47b57b Mon Sep 17 00:00:00 2001 From: Xin Zhe Khooi Date: Tue, 21 May 2024 02:46:35 +0000 Subject: [PATCH 4/7] Implement DU F1 Reset handlers --- .../LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 38 ++++++++++++++++++- openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c | 6 ++- 2 files changed, 40 insertions(+), 4 deletions(-) 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 d47392491b..aac03be132 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -95,10 +95,44 @@ static bool check_plmn_identity(const f1ap_plmn_t *check_plmn, const f1ap_plmn_t return plmn->mcc == check_plmn->mcc && plmn->mnc_digit_length == check_plmn->mnc_digit_length && plmn->mnc == check_plmn->mnc; } +static void du_clear_all_ue_states() +{ + gNB_MAC_INST *mac = RC.nrmac[0]; + NR_SCHED_LOCK(&mac->sched_lock); + + NR_UE_info_t *UE = *mac->UE_info.list; + + instance_t f1inst = get_f1_gtp_instance(); + + while (UE != NULL) { + int rnti = UE->rnti; + nr_mac_release_ue(mac, rnti); + // free all F1 contexts + if (du_exists_f1_ue_data(rnti)) + du_remove_f1_ue_data(rnti); + newGtpuDeleteAllTunnels(f1inst, rnti); + UE = *mac->UE_info.list; + } + NR_SCHED_UNLOCK(&mac->sched_lock); +} + void f1_reset_cu_initiated(const f1ap_reset_t *reset) { - (void) reset; - AssertFatal(false, "%s() not implemented yet\n", __func__); + LOG_I(MAC, "F1 Reset initiated by CU\n"); + + f1ap_reset_ack_t ack = {0}; + if(reset->reset_type == F1AP_RESET_ALL) { + du_clear_all_ue_states(); + ack = (f1ap_reset_ack_t) { + .transaction_id = reset->transaction_id + }; + } else { + // reset->reset_type == F1AP_RESET_PART_OF_F1_INTERFACE + AssertFatal(1==0, "Not implemented yet\n"); + } + + gNB_MAC_INST *mac = RC.nrmac[0]; + mac->mac_rrc.f1_reset_acknowledge(&ack); } void f1_reset_acknowledge_du_initiated(const f1ap_reset_ack_t *ack) 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 4d716e9fb7..742f85c390 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_ul_f1ap.c @@ -61,8 +61,10 @@ static void f1_reset_du_initiated_f1ap(const f1ap_reset_t *reset) static void f1_reset_acknowledge_cu_initiated_f1ap(const f1ap_reset_ack_t *ack) { - (void) ack; - AssertFatal(false, "%s() not implemented yet\n", __func__); + MessageDef *msg = itti_alloc_new_message(TASK_MAC_GNB, 0, F1AP_RESET_ACK); + f1ap_reset_ack_t *f1ap_msg = &F1AP_RESET_ACK(msg); + *f1ap_msg = *ack; + itti_send_msg_to_task(TASK_DU_F1, 0, msg); } static void f1_setup_request_f1ap(const f1ap_setup_req_t *req) From 52f077c478f2dfe76b79ac3543471371299ae046 Mon Sep 17 00:00:00 2001 From: Xin Zhe Khooi Date: Tue, 21 May 2024 03:33:41 +0000 Subject: [PATCH 5/7] Initialized DU UE states on F1SetupResponse 38.473 requires to reset UE-related contexts in F1 Setup Request, so do it. However, avoid resetting UE states in phy_test: it has preconfigured UE which we should not reset. Note that if NSA/phy-test used F1, we could likely reset the UE state here, as the F1 UE context setup would come afterwards. --- .../LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) 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 aac03be132..2435ed629a 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c +++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c @@ -29,6 +29,8 @@ #include "openair3/ocp-gtpu/gtp_itf.h" #include "openair2/LAYER2/nr_pdcp/nr_pdcp_oai_api.h" +#include "executables/softmodem-common.h" + #include "uper_decoder.h" #include "uper_encoder.h" @@ -172,6 +174,24 @@ void f1_setup_response(const f1ap_setup_resp_t *resp) mac->f1_config.setup_resp->gNB_CU_name = strdup(resp->gNB_CU_name); NR_SCHED_UNLOCK(&mac->sched_lock); + + // NOTE: Before accepting any UEs, we should initialize the UE states. + // This is to handle cases when DU loses the existing SCTP connection, + // and reestablishes a new connection to either a new CU or the same CU. + // This triggers a new F1 Setup Request from DU to CU as per the specs. + // Reinitializing the UE states is necessary to avoid any inconsistent states + // between DU and CU. + // NOTE2: do not reset in phy_test, because there is a pre-configured UE in + // this case. Once NSA/phy-test use F1, this might be lifted, because + // creation of a UE will be requested from higher layers. + + // TS38.473 [Sec 8.2.3.1]: "This procedure also re-initialises the F1AP UE-related + // contexts (if any) and erases all related signalling connections + // in the two nodes like a Reset procedure would do." + if (!get_softmodem_params()->phy_test) { + LOG_I(MAC, "Clearing the DU's UE states before, if any.\n"); + du_clear_all_ue_states(); + } } void f1_setup_failure(const f1ap_setup_failure_t *failure) From 2b44e5252d045e95f4625f4a7e0cf9bbc2bfec97 Mon Sep 17 00:00:00 2001 From: Robert Schmidt Date: Fri, 26 Jul 2024 08:56:00 +0200 Subject: [PATCH 6/7] Add log statement that DU sends F1 Setup Request, as done in other functions --- openair2/F1AP/f1ap_du_interface_management.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openair2/F1AP/f1ap_du_interface_management.c b/openair2/F1AP/f1ap_du_interface_management.c index eec39ee7fc..f560754bf3 100644 --- a/openair2/F1AP/f1ap_du_interface_management.c +++ b/openair2/F1AP/f1ap_du_interface_management.c @@ -324,6 +324,8 @@ static F1AP_GNB_DU_System_Information_t *encode_system_info(const f1ap_gnb_du_sy // 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}; uint8_t *buffer; uint32_t len; From 52bd1ad7c6c5c670e5081fbee5845e0596541830 Mon Sep 17 00:00:00 2001 From: Xin Zhe Khooi Date: Fri, 26 Jul 2024 10:23:57 +0200 Subject: [PATCH 7/7] Update FEATURE_SET.md with F1 Reset (DU-only) --- doc/FEATURE_SET.md | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/FEATURE_SET.md b/doc/FEATURE_SET.md index b49c2e7a2f..a722b3a41d 100644 --- a/doc/FEATURE_SET.md +++ b/doc/FEATURE_SET.md @@ -205,6 +205,7 @@ These modes of operation are supported: - F1 UE Context modification required - F1 UE Context release req/cmd/complete - F1 gNB CU configuration update + - F1 Reset (handled at DU only, full reset only) - Interface with RRC - Interface with GTP-u (tunnel creation/handling for F1-U interface) - One CU(-CP) can handle multiple DUs